Source code for lfd.results.frame

"""Frame represents a single SDSS image. On a single CCD there can be up to 3
such frames simultaneously, slightly overlapped on top and bottom edges. It is
not clear to me how to resolve a Frame's position within a CCD due to the SDSS'
drift-scan method.

Frames can only exist within a CCD and CCD's are placed in an fiter x camcol
grid in the CCD plane where the distance between camcols is only slightly less
than the size of the CCD itself so that the gaps can be filled in by another
run.

A single Frame can contain many Events. 
"""
import sqlalchemy as sql
from sqlalchemy.orm import relationship

from astropy.time import Time

from lfd.results import Base
from lfd.results import __query_aliases as query_aliases
from lfd.results.basictime import BasicTime
from lfd.results.utils import session_scope

__all__ = ["Frame"]


[docs]class Frame(Base): """Class Frame maps table 'frames'. Corresponds to an SDSS frame. A frame is uniquely defined by the set (run, camcol, filter, field). For in-depth see datamodel: https://data.sdss.org/datamodel/files/BOSS_PHOTOOBJ/frames/RERUN/RUN/CAMCOL/frame.html Parameters ---------- run : int run id (composite PrimaryKey) camcol : int camcol id (composite PrimaryKey) filter : str filter id (composite PrimaryKey) field : int field id (composite PrimaryKey) crpix1 : int x frame coordinate of the reference central pixel crpix2 : int y frame coordinate of the reference central pixel crval1 : float RA on-sky coordinates of the reference pixel (degrees) crval2 : float DEC on-sky coordinate of the reference pixel cd11 : float change of RA per column pixel cd12 : float change of RA per row pixel cd21 : float change of DEC per column pixel cd22 : float chage of DEC per row pixel t : BasicTime time of start of frame exposure events : sql.relationship list of all event(s) registered on this frame, a one to many relationship to events Example ------- Almost everything is not nullable so supply everything: >>> foo = Frame(run, camcol, filter, field, crpix1, cprix2, crval1, crval2, cd11, cd21, cd22, t) i.e. >>> foo = Frame(2888, 1, 'i', 139, 741, 1024, 119, 23, 1, 1, 1, 4575925956.49) Time can be given as SDSS TAI or any of the other formats supported by Astropy Time Object. In the DB itself it is always forced to the SDSS TAI time format. """ __tablename__ = "frames" run = sql.Column(sql.Integer, primary_key=True) camcol = sql.Column(sql.Integer, primary_key=True) filter = sql.Column(sql.String(length=1), primary_key=True) field = sql.Column(sql.Integer, primary_key=True) crpix1 = sql.Column(sql.Float, nullable=False) crpix2 = sql.Column(sql.Float, nullable=False) crval1 = sql.Column(sql.Float, nullable=False) crval2 = sql.Column(sql.Float, nullable=False) cd11 = sql.Column(sql.Float, nullable=False) cd12 = sql.Column(sql.Float, nullable=False) cd21 = sql.Column(sql.Float, nullable=False) cd22 = sql.Column(sql.Float, nullable=False) t = sql.Column(BasicTime, nullable=False) #http://docs.sqlalchemy.org/en/latest/orm/cascades.html events = relationship("Event", back_populates="frame", passive_updates=False, cascade="save-update,delete,expunge", lazy="joined", innerjoin=True) def __init__(self, run, camcol, filter, field, crpix1, crpix2, crval1, crval2, cd11, cd12, cd21, cd22, t, **kwargs): """Supply everything: >>> foo = Frame(run, camcol, filter, field, crpix1, cprix2, crval1, crval2, cd11, cd21, cd22, t) i.e.: >>> foo = Frame(2888, 1, 'i', 139, 741, 1024, 119.211, 23.321, 1, 1, 1, 4575925956.49) Time can be given as Astropy Time Object, SDSS TAI format or any of the formats supported by Astropy Time object. """ self.run = run self.camcol = camcol self.filter = filter self.field = field self.crpix1 = crpix1 self.crpix2 = crpix2 self.crval1 = crval1 self.crval2 = crval2 self.cd11 = cd11 self.cd12 = cd12 self.cd21 = cd21 self.cd22 = cd22 if isinstance(t, Time): self.t = t else: format = kwargs.pop("format", "sdss-tai") if format == "sdss-tai": self.t = Time(t/(24*3600.), format="mjd") else: self.t = Time(t, format=format) def __repr__(self): m = self.__class__.__module__ n = self.__class__.__name__ t = repr(self.t).split("results.")[-1][:-1] return "<{0}.{1}(run={2}, camcol={3}, filter={4}, frame={5}, "\ "t={6})>".format(m, n, self.run, self.camcol, self.filter, self.field, t) def __str__(self): return "Frame(run={0}, camcol={1}, filter={2}, field={3}, {4})".format( self.run, self.camcol, self.filter, self.field, self.t.iso)
[docs] @classmethod def query(cls, condition=None): """Class method that used to query the Frame ('frames') table. Returns a Query object. Appropriate for interactive work as Session remains open for the lifetime of the Query. See results package help to see details. If condition is supplied it is interpreted as an SQL string query. It's suffiecient to use mapped class names and their attributes as the translation to table and column names will be automaticall performed. Example ------- Frame.query("Frame.run > 2").first() Frame.query("field == 1 and filter == 'i'").all() Frame.query("Event.y1 > 2).all() """ if condition is None: with session_scope() as s: return s.query(cls).join("events") for key, val in query_aliases.items(): condition = condition.replace(key, val) with session_scope() as s: return s.query(cls).join("events").filter(sql.text(condition))