Skip to content

Commit

Permalink
merge changes from #115
Browse files Browse the repository at this point in the history
  • Loading branch information
jrob93 committed May 14, 2024
2 parents 075994e + 84112d4 commit 436cdeb
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 99 deletions.
152 changes: 85 additions & 67 deletions src/adler/adler.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,106 +7,124 @@
from adler.science.PhaseCurve import PhaseCurve
from adler.utilities.AdlerCLIArguments import AdlerCLIArguments
from adler.utilities.adler_logging import setup_adler_logging
from adler.utilities.readin_utilities import read_in_SSObjectID_file

logger = logging.getLogger(__name__)


def runAdler(cli_args):
logger.info("Beginning Adler.")
logger.info("Ingesting all data for object {} from RSP...".format(cli_args.ssObjectId))

planetoid = AdlerPlanetoid.construct_from_RSP(
cli_args.ssObjectId, cli_args.filter_list, cli_args.date_range
)

logger.info("Data successfully ingested.")
logger.info("Calculating phase curves...")

# now let's do some phase curves!
N_pc_fit = 10 # minimum number of data points to fit phase curve

# # operate on each filter in turn
for filt in planetoid.filter_list:

print("fit {} filter data".format(filt))

# get the filter SSObject metadata
sso = planetoid.SSObject_in_filter(filt)

# get the LSST phase curve filter model
pc = PhaseCurve(
abs_mag=sso.H * u.mag,
phase_param=sso.G12,
model_name="HG12_Pen16",
)
print(pc)
print(pc.abs_mag)
print(pc.phase_param)

# get the filter observations
obs = planetoid.observations_in_filter(filt)
alpha = obs.phaseAngle * u.deg
red_mag = obs.reduced_mag * u.mag
mag_err = obs.magErr * u.mag

# when fitting, consider only the previous observations (not tonight's)
mjd = obs.midPointMjdTai
obs_mask = mjd < int(np.amax(mjd))
# also drop any past outlying observations?

print("total N obs = {}".format(len(mjd)))
print("number of past obs = {}".format(sum(obs_mask)))
print("number of tonight's obs = {}".format(sum(~obs_mask)))

if sum(obs_mask) < N_pc_fit:
# use an assumed value of G12 until more data is available
pc_fit = PhaseCurve(abs_mag=sso.H * u.mag, phase_param=0.62, model_name="HG12_Pen16")
else:
# do a simple HG12_Pen16 fit to the past data
pc_fit = pc.FitModel(alpha[obs_mask], red_mag[obs_mask], mag_err[obs_mask])
pc_fit = pc.InitModelSbpy(pc_fit)

print(pc_fit)
print(pc_fit.abs_mag)
print(pc_fit.phase_param)

# now check if the new observations are outlying

# also check for past observations that are outlying?

# output results
# flag outlying observations
# output the phase curve model parameters

if cli_args.ssObjectId_list:
ssObjectId_list = read_in_SSObjectID_file(cli_args.ssObjectId_list)
else:
ssObjectId_list = [cli_args.ssObjectId]

for i, ssObjectId in enumerate(ssObjectId_list):
logger.info("Processing object {}/{}.".format(i + 1, len(ssObjectId_list)))
logger.info("Ingesting all data for object {} from RSP...".format(cli_args.ssObjectId))

planetoid = AdlerPlanetoid.construct_from_RSP(ssObjectId, cli_args.filter_list, cli_args.date_range)

logger.info("Data successfully ingested.")
logger.info("Calculating phase curves...")

# now let's do some phase curves!

# # operate on each filter in turn
for filt in planetoid.filter_list:

print("fit {} filter data".format(filt))

# get the filter SSObject metadata
sso = planetoid.SSObject_in_filter(filt)

# get the LSST phase curve filter model
pc = PhaseCurve(
abs_mag=sso.H * u.mag,
phase_param=sso.G12,
model_name="HG12_Pen16",
)
print(pc)
print(pc.abs_mag)
print(pc.phase_param)

# get the filter observations
obs = planetoid.observations_in_filter(filt)
alpha = obs.phaseAngle * u.deg
red_mag = obs.reduced_mag * u.mag
mag_err = obs.magErr * u.mag

# when fitting, consider only the previous observations (not tonight's)
mjd = obs.midPointMjdTai
obs_mask = mjd < int(np.amax(mjd))
# also drop any past outlying observations?

print("total N obs = {}".format(len(mjd)))
print("number of past obs = {}".format(sum(obs_mask)))
print("number of tonight's obs = {}".format(sum(~obs_mask)))

if sum(obs_mask) < N_pc_fit:
# use an assumed value of G12 until more data is available
pc_fit = PhaseCurve(abs_mag=sso.H * u.mag, phase_param=0.62, model_name="HG12_Pen16")
else:
# do a simple HG12_Pen16 fit to the past data
pc_fit = pc.FitModel(alpha[obs_mask], red_mag[obs_mask], mag_err[obs_mask])
pc_fit = pc.InitModelSbpy(pc_fit)

print(pc_fit)
print(pc_fit.abs_mag)
print(pc_fit.phase_param)

# now check if the new observations are outlying

# also check for past observations that are outlying?

# output results
# flag outlying observations
# output the phase curve model parameters

def main():
parser = argparse.ArgumentParser(description="Runs Adler for select planetoid(s) and given user input.")

parser.add_argument("-s", "--ssObjectId", help="SSObject ID of planetoid.", type=str, required=True)
parser.add_argument(
# the below group ensures that AT LEAST one of the below arguments is included, but NOT both
input_group = parser.add_mutually_exclusive_group(required=True)
input_group.add_argument("-s", "--ssObjectId", help="SSObject ID of planetoid.", type=str, default=None)
input_group.add_argument(
"-sl",
"--ssObjectId_list",
help="Filepath to text file listing multiple SSObjectIds.",
type=str,
default=None,
)

optional_group = parser.add_argument_group("Optional arguments")
optional_group.add_argument(
"-f",
"--filter_list",
help="Filters required.",
nargs="*",
type=str,
default=["u", "g", "r", "i", "z", "y"],
)
parser.add_argument(
optional_group.add_argument(
"-d",
"--date_range",
help="Minimum and maximum MJD(TAI) of required observations. Default is to pull all observations.",
nargs=2,
type=float,
default=[60000.0, 67300.0],
)
parser.add_argument(
optional_group.add_argument(
"-o",
"--outpath",
help="Output path location. Default is current working directory.",
type=str,
default="./",
)
parser.add_argument(
optional_group.add_argument(
"-n",
"--db_name",
help="Stem filename of output database. If this doesn't exist, it will be created. Default: adler_out.",
Expand Down
5 changes: 0 additions & 5 deletions src/adler/dataclasses/AdlerPlanetoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,6 @@ def populate_observations(
filter_name
)
)
print(
"WARNING: No observations found in {} filter for this object. Skipping this filter.".format(
filter_name
)
)
else:
observations_by_filter.append(
Observations.construct_from_data_table(ssObjectId, filter_name, data_table)
Expand Down
5 changes: 0 additions & 5 deletions src/adler/dataclasses/dataclass_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,6 @@ def check_value_populated(data_val, data_type, column_name, table_name):
logger.warning(
"{} unpopulated in {} table for this object. Storing NaN instead.".format(column_name, table_name)
)
print(
"WARNING: {} unpopulated in {} table for this object. Storing NaN instead.".format(
column_name, table_name
)
)
data_val = np.nan

return data_val
35 changes: 33 additions & 2 deletions src/adler/utilities/AdlerCLIArguments.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import os
import logging

logger = logging.getLogger(__name__)


class AdlerCLIArguments:
"""
Class for storing abd validating Adler command-line arguments.
Attributes:
Attributes
-----------
args : argparse.Namespace object
argparse.Namespace object created by calling parse_args().
Expand All @@ -14,6 +17,7 @@ class AdlerCLIArguments:

def __init__(self, args):
self.ssObjectId = args.ssObjectId
self.ssObjectId_list = args.ssObjectId_list
self.filter_list = args.filter_list
self.date_range = args.date_range
self.outpath = args.outpath
Expand All @@ -23,14 +27,22 @@ def __init__(self, args):

def validate_arguments(self):
self._validate_filter_list()
self._validate_ssObjectId()
self._validate_date_range()
self._validate_outpath()

if self.ssObjectId:
self._validate_ssObjectId()

if self.ssObjectId_list:
self._validate_ssObjectId_list()

def _validate_filter_list(self):
expected_filters = ["u", "g", "r", "i", "z", "y"]

if not set(self.filter_list).issubset(expected_filters):
logging.error(
"Unexpected filters found in --filter_list command-line argument. --filter_list must be a list of LSST filters."
)
raise ValueError(
"Unexpected filters found in --filter_list command-line argument. --filter_list must be a list of LSST filters."
)
Expand All @@ -39,18 +51,25 @@ def _validate_ssObjectId(self):
try:
int(self.ssObjectId)
except ValueError:
logging.error("--ssObjectId command-line argument does not appear to be a valid ssObjectId.")
raise ValueError("--ssObjectId command-line argument does not appear to be a valid ssObjectId.")

def _validate_date_range(self):
for d in self.date_range:
try:
float(d)
except ValueError:
logging.error(
"One or both of the values for the --date_range command-line argument do not seem to be valid numbers."
)
raise ValueError(
"One or both of the values for the --date_range command-line argument do not seem to be valid numbers."
)

if any(d > 250000 for d in self.date_range):
logging.error(
"Dates for --date_range command-line argument seem rather large. Did you input JD instead of MJD?"
)
raise ValueError(
"Dates for --date_range command-line argument seem rather large. Did you input JD instead of MJD?"
)
Expand All @@ -60,4 +79,16 @@ def _validate_outpath(self):
self.outpath = os.path.abspath(self.outpath)

if not os.path.isdir(self.outpath):
logging.error("The output path for the command-line argument --outpath cannot be found.")
raise ValueError("The output path for the command-line argument --outpath cannot be found.")

def _validate_ssObjectId_list(self):
self.ssObjectId_list = os.path.abspath(self.ssObjectId_list)

if not os.path.exists(self.ssObjectId_list):
logging.error(
"The file supplied for the command-line argument --ssObjectId_list cannot be found."
)
raise ValueError(
"The file supplied for the command-line argument --ssObjectId_list cannot be found."
)
26 changes: 26 additions & 0 deletions src/adler/utilities/adler_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,32 @@ def setup_adler_logging(
log_file_info="adler.log",
log_file_error="adler.err",
):
"""Sets up two logs for Adler: info, which logs everything, and error, which logs warnings and errors.
Parameters
-----------
log_location : string
Filepath to directory in which to save logs.
log_format : string, optional
Format for log filename.
Default = "%(asctime)s %(name)-12s %(levelname)-8s %(message)s "
log_name : string, optional
Name of log. Default = ""
log_file_info : string, optional
Name with which to save info log. Default = "adler.log"
log_file_error : string, optional
Name with which to save error log. Default = "adler.err"
Returns
----------
log : logging object
Log object.
"""

log = logging.getLogger(log_name)
log_formatter = logging.Formatter(log_format)

Expand Down
36 changes: 36 additions & 0 deletions src/adler/utilities/readin_utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import logging

logger = logging.getLogger(__name__)


def read_in_SSObjectID_file(readin_path):
"""Reads in a list of SSOIDs from a text file and performs basic validation.
Parameters
-----------
readin_path : str
String containing filepath to text file.
Returns
-----------
ssoid_list : list
A list of SSOIDs.
"""

with open(readin_path) as f:
ssoid_list = f.read().splitlines()

# bit of validation here: we expect these to cast nicely to ints
for ssoid in ssoid_list:
try:
int(ssoid)
except ValueError:
logger.error(
"ValueError: One or more of the SSObjectIDs in the supplied list does not seem to be valid."
)
raise ValueError("One or more of the SSObjectIDs in the supplied list does not seem to be valid.")

return ssoid_list
13 changes: 0 additions & 13 deletions tests/adler/dataclasses/test_AdlerPlanetoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,19 +137,6 @@ def test_no_observations():
)


def test_for_warnings(capsys):
test_planetoid = AdlerPlanetoid.construct_from_SQL(ssoid, test_db_path, filter_list=["u", "g"])
captured = capsys.readouterr()

expected = (
"WARNING: No observations found in u filter for this object. Skipping this filter.\n"
+ "WARNING: n unpopulated in MPCORB table for this object. Storing NaN instead.\n"
+ "WARNING: uncertaintyParameter unpopulated in MPCORB table for this object. Storing NaN instead.\n"
)

assert captured.out == expected


def test_failed_SQL_queries():
test_planetoid = AdlerPlanetoid.construct_from_SQL(
ssoid, test_db_path, filter_list=["u", "g", "r", "i", "z", "y"]
Expand Down
Loading

0 comments on commit 436cdeb

Please sign in to comment.