Skip to content

Commit

Permalink
Merge pull request #71 from lsst-uk/filters_refactor
Browse files Browse the repository at this point in the history
Refactor and adding filters.
  • Loading branch information
astronomerritt authored Mar 11, 2024
2 parents 610d429 + 6ae74ca commit 6077e15
Show file tree
Hide file tree
Showing 7 changed files with 625 additions and 435 deletions.
8 changes: 6 additions & 2 deletions src/adler/adler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


def runAdler(args):
planetoid = AdlerPlanetoid(args.ssoid)
planetoid = AdlerPlanetoid.construct_from_RSP(args.ssoid, args.filter_list)

planetoid.do_pretend_science()

Expand All @@ -13,12 +13,16 @@ def main():
parser = argparse.ArgumentParser(description="Runs Adler for a select planetoid and given user input.")

parser.add_argument("-s", "--ssoid", help="SSObject ID of planetoid.", type=str, required=True)
parser.add_argument(
"-f", "--filters", help="Comma-separated list of filters required.", type=str, default="u,g,r,i,z,y"
)

# can add arguments to specify a date range etc later
# alternatively we may start using a config file

args = parser.parse_args()

args.filter_list = args.filters.split(",")

runAdler(args)


Expand Down
229 changes: 176 additions & 53 deletions src/adler/dataclasses/AdlerPlanetoid.py
Original file line number Diff line number Diff line change
@@ -1,91 +1,214 @@
from adler.dataclasses.DataSchema import Observations, MPCORB, SSObject
from lsst.rsp import get_tap_service

from adler.dataclasses.Observations import Observations
from adler.dataclasses.MPCORB import MPCORB
from adler.dataclasses.SSObject import SSObject
from adler.dataclasses.AdlerData import AdlerData
from adler.dataclasses.dataclass_utilities import get_data_table
from adler.science.DummyScience import DummyScience


class AdlerPlanetoid:
"""AdlerPlanetoid class. Contains the Observations, MPCORB and SSObject objects."""
"""AdlerPlanetoid class. Contains the Observations, MPCORB and SSObject dataclass objects."""

def __init__(self, ssObjectId, population_location="RSP", sql_filename=None):
def __init__(self, ssObjectId, filter_list, observations_by_filter, mpcorb, ssobject, adler_data):
"""Initialises the AdlerPlanetoid object.
Parameters
Attributes
-----------
ssObjectId : str
ssObjectId of the object of interest.
population_location : str
String delineating source of data. Should be "RSP" for Rubin Science Platform or "SQL" for a SQL table.
sql_filename: str, optional
Location of local SQL database, if using.
filter_list : list of str
A comma-separated list of the filters of interest.
observations_by_filter : list of Observations objects
A list of Observations objects holding joined DIASource/SSSource observations of the planetoid specified by ssObjectId. Each item in the list holds observations of a different filter, in the order specified by filter_list.
mpcorb : MPCORB object
An MPCORB object, holding the MPCORB database information of the planetoid specified by ssObjectId.
ssobject : SSObject object
An SSObject object, holding the SSObject database information of the planetoid specified by ssObjectId.
adler_data : AdlerData object
An empty AdlerData object ready to store Adler-calculated values.
"""
self.ssObjectId = ssObjectId
self.population_location = population_location
self.sql_filename = sql_filename
# can also include date ranges at some point

# create empty AdlerData dataclass object.
self.AdlerData = AdlerData(["r"])

# this creates the AdlerPlanetoid.Observations, AdlerPlanetoid.MPCORB and
# AdlerPlanetoid.SSObject objects.
self.populate_observations()
self.populate_MPCORB()
self.populate_SSObject()

def populate_observations(self):
"""Populates the Observations object class attribute."""
observations_sql_query = f"""
SELECT
ssObject.ssObjectId, mag, magErr, band, midpointMjdTai, ra, dec, phaseAngle,
topocentricDist, heliocentricDist
FROM
dp03_catalogs_10yr.ssObject
JOIN dp03_catalogs_10yr.diaSource ON dp03_catalogs_10yr.ssObject.ssObjectId = dp03_catalogs_10yr.diaSource.ssObjectId
JOIN dp03_catalogs_10yr.ssSource ON dp03_catalogs_10yr.diaSource.diaSourceId = dp03_catalogs_10yr.ssSource.diaSourceId
WHERE
ssObject.ssObjectId = {self.ssObjectId} and band='r'
"""
self.filter_list = filter_list
self.observations_by_filter = observations_by_filter
self.MPCORB = mpcorb
self.SSObject = ssobject
self.AdlerData = adler_data

@classmethod
def construct_from_SQL(cls):
# to-do
pass

@classmethod
def construct_from_RSP(cls, ssObjectId, filter_list=["u", "g", "r", "i", "z", "y"]):
"""Custom constructor which builds the AdlerPlanetoid object and the associated Observations, MPCORB and SSObject objects
from the RSP.
Parameters
-----------
ssObjectId : str
ssObjectId of the object of interest.
filter_list : list of str
A comma-separated list of the filters of interest.
"""

service = get_tap_service("ssotap")
observations_by_filter = cls.populate_observations(cls, ssObjectId, filter_list, service=service)
mpcorb = cls.populate_MPCORB(cls, ssObjectId, service=service)
ssobject = cls.populate_SSObject(cls, ssObjectId, filter_list, service=service)

adler_data = AdlerData(filter_list)

return cls(ssObjectId, filter_list, observations_by_filter, mpcorb, ssobject, adler_data)

def populate_observations(self, ssObjectId, filter_list, service=None, sql_filename=None):
"""Populates the observations_by_filter class attribute. Can populate from either the RSP for a SQL database:
this behaviour is controlled by the service and sql_filename parameters, one of which must be supplied.
Parameters
-----------
ssObjectId : str
ssObjectId of the object of interest.
filter_list : list of str
A comma-separated list of the filters of interest.
service : pyvo.dal.tap.TAPService object
TAPService object linked to the RSP. Default=None.
sql_filename : str
Filepath to a SQL database. Default=None.
"""

observations_by_filter = []

for filter_name in filter_list:
observations_sql_query = f"""
SELECT
ssObject.ssObjectId, mag, magErr, band, midpointMjdTai, ra, dec, phaseAngle,
topocentricDist, heliocentricDist
FROM
dp03_catalogs_10yr.ssObject
JOIN dp03_catalogs_10yr.diaSource ON dp03_catalogs_10yr.ssObject.ssObjectId = dp03_catalogs_10yr.diaSource.ssObjectId
JOIN dp03_catalogs_10yr.ssSource ON dp03_catalogs_10yr.diaSource.diaSourceId = dp03_catalogs_10yr.ssSource.diaSourceId
WHERE
ssObject.ssObjectId = {ssObjectId} and band = '{filter_name}'
"""

data_table = get_data_table(observations_sql_query, service=service, sql_filename=sql_filename)

self.Observations = Observations(
self.ssObjectId, self.population_location, observations_sql_query, sql_filename=self.sql_filename
)
observations_by_filter.append(
Observations.construct_from_data_table(ssObjectId, filter_name, data_table)
)

def populate_MPCORB(self):
"""Populates the MPCORB object class attribute."""
return observations_by_filter

def populate_MPCORB(self, ssObjectId, service=None, sql_filename=None):
"""Populates the MPCORB object class attribute. Can populate from either the RSP for a SQL database:
this behaviour is controlled by the service and sql_filename parameters, one of which must be supplied.
Parameters
-----------
ssObjectId : str
ssObjectId of the object of interest.
service : pyvo.dal.tap.TAPService object
TAPService object linked to the RSP. Default=None.
sql_filename : str
Filepath to a SQL database. Default=None.
"""
MPCORB_sql_query = f"""
SELECT
ssObjectId, mpcDesignation, mpcNumber, mpcH, mpcG, epoch, peri, node, incl, e, n, q,
uncertaintyParameter, flags
FROM
dp03_catalogs_10yr.MPCORB
WHERE
ssObjectId = {self.ssObjectId}
ssObjectId = {ssObjectId}
"""

data_table = get_data_table(MPCORB_sql_query, service=service, sql_filename=sql_filename)

return MPCORB.construct_from_data_table(ssObjectId, data_table)

def populate_SSObject(self, ssObjectId, filter_list, service=None, sql_filename=None):
"""Populates the SSObject class attribute. Can populate from either the RSP for a SQL database:
this behaviour is controlled by the service and sql_filename parameters, one of which must be supplied.
Parameters
-----------
ssObjectId : str
ssObjectId of the object of interest.
filter_list : list of str
A comma-separated list of the filters of interest.
service : pyvo.dal.tap.TAPService object
TAPService object linked to the RSP. Default=None.
sql_filename : str
Filepath to a SQL database. Default=None.
"""

self.MPCORB = MPCORB(
self.ssObjectId, self.population_location, MPCORB_sql_query, sql_filename=self.sql_filename
)
filter_dependent_columns = ""

for filter_name in filter_list:
filter_string = "{}_H, {}_G12, {}_Herr, {}_G12err, {}_nData, ".format(
filter_name, filter_name, filter_name, filter_name, filter_name
)

filter_dependent_columns += filter_string

def populate_SSObject(self):
"""Populates the SSObject class attribute."""
SSObject_sql_query = f"""
SELECT
discoverySubmissionDate, firstObservationDate, arc, numObs,
r_H, r_G12, r_Herr, r_G12err, r_nData,
{filter_dependent_columns}
maxExtendedness, minExtendedness, medianExtendedness
FROM
dp03_catalogs_10yr.SSObject
WHERE
ssObjectId = {self.ssObjectId}
ssObjectId = {ssObjectId}
"""

data_table = get_data_table(SSObject_sql_query, service=service, sql_filename=sql_filename)

return SSObject.construct_from_data_table(ssObjectId, filter_list, data_table)

def observations_in_filter(self, filter_name):
"""User-friendly helper function. Returns the Observations object for a given filter.
Parameters
-----------
filter_name : str
The desired filter.
Returns
-----------
Observations object
The Observations object in self.observations_by_filter corresponding to the desired filter.
"""

self.SSObject = SSObject(
self.ssObjectId,
self.population_location,
sql_query=SSObject_sql_query,
sql_filename=self.sql_filename,
)
try:
filter_index = self.filter_list.index(filter_name)
except ValueError:
raise ValueError("Filter {} is not in AdlerPlanetoid.filter_list.".format(filter_name))

return self.observations_by_filter[filter_index]

def do_pretend_science(self):
self.DummyScienceResult = DummyScience().science_result
Expand Down
Loading

0 comments on commit 6077e15

Please sign in to comment.