-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #117 from hover2pi/anomoly_db
`jwqldb` interface
- Loading branch information
Showing
6 changed files
with
537 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
******** | ||
database | ||
******** | ||
|
||
.. automodule:: jwql.database.database_interface | ||
:members: | ||
:undoc-members: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
""" | ||
A module to interact with the JWQL postgresql database ``jwqldb`` | ||
The ``load_connection()`` function within this module allows the user | ||
to connect to the ``jwqldb`` database via the ``session``, ``base``, | ||
and ``engine`` objects (described below). The classes within serve as | ||
ORMs (Object-relational mappings) that define the individual tables of | ||
the relational database. | ||
The ``engine`` object serves as the low-level database API and perhaps | ||
most importantly contains dialects which allows the ``sqlalchemy`` | ||
module to communicate with the database. | ||
The ``base`` object serves as a base class for class definitions. It | ||
produces ``Table`` objects and constructs ORMs. | ||
The ``session`` object manages operations on ORM-mapped objects, as | ||
construced by the base. These operations include querying, for | ||
example. | ||
Authors | ||
------- | ||
Joe Filippazzo, Johannes Sahlmann, Matthew Bourque | ||
""" | ||
|
||
from datetime import datetime | ||
|
||
import pandas as pd | ||
from sqlalchemy import Boolean | ||
from sqlalchemy import Column | ||
from sqlalchemy import create_engine | ||
from sqlalchemy import DateTime | ||
from sqlalchemy import Integer | ||
from sqlalchemy import MetaData | ||
from sqlalchemy import String | ||
from sqlalchemy.ext.declarative import declarative_base | ||
from sqlalchemy.orm import sessionmaker | ||
from sqlalchemy.orm.query import Query | ||
|
||
from ..utils import utils | ||
|
||
|
||
SETTINGS = utils.get_config() | ||
|
||
|
||
# Monkey patch Query with data_frame method | ||
@property | ||
def data_frame(self): | ||
"""Method to return a pandas.DataFrame of the results""" | ||
return pd.read_sql(self.statement, self.session.bind) | ||
|
||
|
||
Query.data_frame = data_frame | ||
|
||
|
||
def load_connection(connection_string): | ||
"""Return ``session``, ``base``, ``engine``, and ``metadata`` | ||
objects for connecting to the ``jwqldb`` database. | ||
Create an ``engine`` using an given ``connection_string``. Create | ||
a ``base`` class and ``session`` class from the ``engine``. Create | ||
an instance of the ``session`` class. Return the ``session``, | ||
``base``, and ``engine`` instances. This was stolen from the | ||
`ascql` repository. | ||
Parameters | ||
---------- | ||
connection_string : str | ||
A postgresql database connection string. The | ||
connection string should take the form: | ||
``dialect+driver://username:password@host:port/database`` | ||
Returns | ||
------- | ||
session : sesson object | ||
Provides a holding zone for all objects loaded or associated | ||
with the database. | ||
base : base object | ||
Provides a base class for declarative class definitions. | ||
engine : engine object | ||
Provides a source of database connectivity and behavior. | ||
meta: metadata object | ||
The connection metadata | ||
References | ||
---------- | ||
``ascql``: | ||
https://github.com/spacetelescope/acsql/blob/master/acsql/database/database_interface.py | ||
""" | ||
engine = create_engine(connection_string, echo=False) | ||
base = declarative_base(engine) | ||
Session = sessionmaker(bind=engine) | ||
session = Session() | ||
meta = MetaData() | ||
|
||
return session, base, engine, meta | ||
|
||
|
||
session, base, engine, meta = load_connection(SETTINGS['connection_string']) | ||
|
||
|
||
class Anomaly(base): | ||
"""ORM for the anomalies table""" | ||
# Name the table | ||
__tablename__ = 'anomalies' | ||
|
||
# Define the columns | ||
id = Column(Integer, primary_key=True, nullable=False) | ||
filename = Column(String, nullable=False) | ||
flag_date = Column(DateTime, nullable=False, default=datetime.now()) | ||
bowtie = Column(Boolean, nullable=False, default=False) | ||
snowball = Column(Boolean, nullable=False, default=False) | ||
cosmic_ray_shower = Column(Boolean, nullable=False, default=False) | ||
crosstalk = Column(Boolean, nullable=False, default=False) | ||
cte_correction_error = Column(Boolean, nullable=False, default=False) | ||
data_transfer_error = Column(Boolean, nullable=False, default=False) | ||
detector_ghost = Column(Boolean, nullable=False, default=False) | ||
diamond = Column(Boolean, nullable=False, default=False) | ||
diffraction_spike = Column(Boolean, nullable=False, default=False) | ||
dragon_breath = Column(Boolean, nullable=False, default=False) | ||
earth_limb = Column(Boolean, nullable=False, default=False) | ||
excessive_saturation = Column(Boolean, nullable=False, default=False) | ||
figure8_ghost = Column(Boolean, nullable=False, default=False) | ||
filter_ghost = Column(Boolean, nullable=False, default=False) | ||
fringing = Column(Boolean, nullable=False, default=False) | ||
guidestar_failure = Column(Boolean, nullable=False, default=False) | ||
banding = Column(Boolean, nullable=False, default=False) | ||
persistence = Column(Boolean, nullable=False, default=False) | ||
prominent_blobs = Column(Boolean, nullable=False, default=False) | ||
trail = Column(Boolean, nullable=False, default=False) | ||
scattered_light = Column(Boolean, nullable=False, default=False) | ||
other = Column(Boolean, nullable=False, default=False) | ||
|
||
def __repr__(self): | ||
"""Return the canonical string representation of the object""" | ||
# Get the columns that are True | ||
a_list = [col for col, val in self.__dict__.items() | ||
if val is True and isinstance(val, bool)] | ||
|
||
txt = ('Anomaly {0.id}: {0.filename} flagged at ' | ||
'{0.flag_date} for {1}').format(self, a_list) | ||
|
||
return txt | ||
|
||
@property | ||
def colnames(self): | ||
"""A list of all the column names in this table""" | ||
# Get the columns | ||
a_list = [col for col, val in self.__dict__.items() | ||
if isinstance(val, bool)] | ||
|
||
return a_list | ||
|
||
|
||
if __name__ == '__main__': | ||
|
||
base.metadata.create_all(engine) |
Oops, something went wrong.