astro-otter 0.0.1__py3-none-any.whl → 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of astro-otter might be problematic. Click here for more details.
- {astro_otter-0.0.1.dist-info → astro_otter-0.0.2.dist-info}/METADATA +13 -4
- astro_otter-0.0.2.dist-info/RECORD +15 -0
- otter/__init__.py +2 -0
- otter/_version.py +1 -1
- otter/exceptions.py +19 -0
- otter/io/otter.py +71 -53
- otter/io/transient.py +60 -11
- otter/plotter/otter_plotter.py +10 -8
- otter/plotter/plotter.py +19 -18
- otter/util.py +60 -1
- astro_otter-0.0.1.dist-info/RECORD +0 -15
- {astro_otter-0.0.1.dist-info → astro_otter-0.0.2.dist-info}/LICENSE +0 -0
- {astro_otter-0.0.1.dist-info → astro_otter-0.0.2.dist-info}/WHEEL +0 -0
- {astro_otter-0.0.1.dist-info → astro_otter-0.0.2.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: astro-otter
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.2
|
|
4
4
|
Author-email: Noah Franz <nfranz@arizona.edu>
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -50,6 +50,13 @@ Requires-Dist: synphot
|
|
|
50
50
|
Requires-Dist: ads
|
|
51
51
|
Requires-Dist: ruff
|
|
52
52
|
Requires-Dist: pre-commit
|
|
53
|
+
Requires-Dist: Sphinx >=3.0.0
|
|
54
|
+
Requires-Dist: myst-parser >=0.13
|
|
55
|
+
Requires-Dist: nbsphinx >=0.9.1
|
|
56
|
+
Requires-Dist: sphinx-book-theme >=0.0.33
|
|
57
|
+
Requires-Dist: sphinx-copybutton
|
|
58
|
+
Requires-Dist: autodoc
|
|
59
|
+
Requires-Dist: ipykernel
|
|
53
60
|
|
|
54
61
|
# OTTER API
|
|
55
62
|
### **O**pen mul**T**iwavelength **T**ransient **E**vent **R**epository
|
|
@@ -66,9 +73,9 @@ A Python API for the OTTER.
|
|
|
66
73
|
[github-discussions-link]: https://github.com/mattbellis/hepfile/discussions
|
|
67
74
|
[gitter-badge]: https://badges.gitter.im/https://github.com/mattbellis/hepfile/community.svg
|
|
68
75
|
[gitter-link]: https://gitter.im/https://github.com/mattbellis/hepfile/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
|
69
|
-
[pypi-link]: https://pypi.org/project/
|
|
70
|
-
[pypi-platforms]: https://img.shields.io/pypi/pyversions/
|
|
71
|
-
[pypi-version]: https://badge.fury.io/py/
|
|
76
|
+
[pypi-link]: https://pypi.org/project/astro-otter/
|
|
77
|
+
[pypi-platforms]: https://img.shields.io/pypi/pyversions/astro-otter
|
|
78
|
+
[pypi-version]: https://badge.fury.io/py/astro-otter.svg
|
|
72
79
|
[rtd-badge]: https://readthedocs.org/projects/otter/badge/?version=latest
|
|
73
80
|
[rtd-link]: https://otter.readthedocs.io/en/latest/?badge=latest
|
|
74
81
|
[sk-badge]: https://scikit-hep.org/assets/images/Scikit--HEP-Project-blue.svg
|
|
@@ -77,7 +84,9 @@ A Python API for the OTTER.
|
|
|
77
84
|
[codecov-badge]: https://codecov.io/gh/astro-otter/otter/graph/badge.svg?token=BtCerOdTc0
|
|
78
85
|
[codecov-link]: https://codecov.io/gh/astro-otter/otter
|
|
79
86
|
|
|
87
|
+
[](https://astro-otter.readthedocs.io/en/latest/?badge=latest)
|
|
80
88
|
[![Actions Status][actions-badge]][actions-link]
|
|
89
|
+
[![PyPI version][pypi-version]][pypi-link]
|
|
81
90
|
[![Linting: Ruff][ruff-badge]][ruff-link]
|
|
82
91
|
[![codecov][codecov-badge]][codecov-link]
|
|
83
92
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
otter/__init__.py,sha256=QcHr5dccvRTbhHvmYPxeA3Tu_cTPSaly6HpWpYIOKuE,375
|
|
2
|
+
otter/_version.py,sha256=LmHTKaM1wouerxDnWDFcgY_MwrMKXJg7gfYzgnpWjcA,76
|
|
3
|
+
otter/exceptions.py,sha256=d2g7Lmh8k06P8C_No2yX38nM9Si_Xh60n09d8BEtO60,938
|
|
4
|
+
otter/util.py,sha256=3_Vi3ufPcquHJSnS7VvLEQ5SPhSElHDt0WZGbFJ_Vbo,15163
|
|
5
|
+
otter/io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
otter/io/otter.py,sha256=KCRU8KHGVqz4BItqLj5U7eLBOi_rBGEFU1rcCOABh0E,17608
|
|
7
|
+
otter/io/transient.py,sha256=COp8itX3P70eXXDKhs-m4lOZI5IzlJHSB59XGRy9gg0,33621
|
|
8
|
+
otter/plotter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
otter/plotter/otter_plotter.py,sha256=iQe5AFsB5plw5eClUfuEfqcNRiXEcKc5-hkLPVKCkg8,2091
|
|
10
|
+
otter/plotter/plotter.py,sha256=i9ZAlbIjftpzyFzgCIFdye9XnppTwOSwazb5ruLpjnE,2896
|
|
11
|
+
astro_otter-0.0.2.dist-info/LICENSE,sha256=s9IPE8A3CAMEaZpDhj4eaorpmfLYGB0mIGphq301PUY,1067
|
|
12
|
+
astro_otter-0.0.2.dist-info/METADATA,sha256=Tw9V-rhA8kudxXJjlPWrGMcNdJbnwvYIxolUCgQ-VCw,32275
|
|
13
|
+
astro_otter-0.0.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
14
|
+
astro_otter-0.0.2.dist-info/top_level.txt,sha256=Wth72sCwBRUk3KZGknSKvLQDMFuJk6qiaAavMDOdG5k,6
|
|
15
|
+
astro_otter-0.0.2.dist-info/RECORD,,
|
otter/__init__.py
CHANGED
otter/_version.py
CHANGED
otter/exceptions.py
CHANGED
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
Custom exceptions for otter
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
class FailedQueryError(ValueError):
|
|
9
|
+
"""
|
|
10
|
+
Exception thrown when the users query does not return any results.
|
|
11
|
+
"""
|
|
12
|
+
|
|
7
13
|
def __str__(self):
|
|
8
14
|
txt = "You're query/search did not return any results! "
|
|
9
15
|
txt += "Try again with different parameters!"
|
|
@@ -11,10 +17,19 @@ class FailedQueryError(ValueError):
|
|
|
11
17
|
|
|
12
18
|
|
|
13
19
|
class IOError(ValueError):
|
|
20
|
+
"""
|
|
21
|
+
Exception thrown when the input or output argument/value is not the correct type.
|
|
22
|
+
"""
|
|
23
|
+
|
|
14
24
|
pass
|
|
15
25
|
|
|
16
26
|
|
|
17
27
|
class OtterLimitationError(Exception):
|
|
28
|
+
"""
|
|
29
|
+
Exception thrown when the user requests something that is currently not supported
|
|
30
|
+
by the API.
|
|
31
|
+
"""
|
|
32
|
+
|
|
18
33
|
def __init__(self, msg):
|
|
19
34
|
self.msg = "Current Limitation Found: " + msg
|
|
20
35
|
|
|
@@ -23,4 +38,8 @@ class OtterLimitationError(Exception):
|
|
|
23
38
|
|
|
24
39
|
|
|
25
40
|
class TransientMergeError(Exception):
|
|
41
|
+
"""
|
|
42
|
+
Exception thrown when the Transient objects can not be combined as expected.
|
|
43
|
+
"""
|
|
44
|
+
|
|
26
45
|
pass
|
otter/io/otter.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
This is the primary class for user interaction with the catalog
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
import os
|
|
6
7
|
import json
|
|
7
8
|
import glob
|
|
@@ -28,14 +29,11 @@ class Otter(object):
|
|
|
28
29
|
This is the primary class for users to access the otter backend database
|
|
29
30
|
|
|
30
31
|
Args:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
collection [str]: The collection to read data from. Right now the only
|
|
37
|
-
collection is 'tdes'.
|
|
38
|
-
debug [bool]: debug mode, set to true to limit reading from database.
|
|
32
|
+
datadir (str): Path to the data directory with the otter data. If not provided
|
|
33
|
+
will default to a ".otter" directory in the CWD where you call
|
|
34
|
+
this class from.
|
|
35
|
+
debug (bool): If we should just debug and not do anything serious.
|
|
36
|
+
|
|
39
37
|
"""
|
|
40
38
|
|
|
41
39
|
def __init__(self, datadir: str = None, debug: bool = False) -> None:
|
|
@@ -87,9 +85,9 @@ class Otter(object):
|
|
|
87
85
|
Performs a cone search of the catalog over the given coords and radius.
|
|
88
86
|
|
|
89
87
|
Args:
|
|
90
|
-
coords
|
|
91
|
-
radius
|
|
92
|
-
raw
|
|
88
|
+
coords (SkyCoord): An astropy SkyCoord object with coordinates to match to
|
|
89
|
+
radius (float): The radius of the cone in arcseconds, default is 0.05"
|
|
90
|
+
raw (bool): If False (the default) return an astropy table of the metadata
|
|
93
91
|
for matching objects. Otherwise, return the raw json dicts
|
|
94
92
|
|
|
95
93
|
Return:
|
|
@@ -117,35 +115,40 @@ class Otter(object):
|
|
|
117
115
|
unit conversion for you!
|
|
118
116
|
|
|
119
117
|
Args:
|
|
120
|
-
flux_units
|
|
118
|
+
flux_units (astropy.unit.Unit): Either a valid string to convert
|
|
121
119
|
or an astropy.unit.Unit
|
|
122
|
-
date_units
|
|
120
|
+
date_units (astropy.unit.Unit): Either a valid string to convert to a date
|
|
123
121
|
or an astropy.unit.Unit
|
|
124
|
-
return_type
|
|
122
|
+
return_type (str): Either 'astropy' or 'pandas'. If astropy, returns an
|
|
125
123
|
astropy Table. If pandas, returns a pandas DataFrame.
|
|
126
124
|
Default is 'astropy'.
|
|
127
|
-
obs_type
|
|
125
|
+
obs_type (str): Either 'radio', 'uvoir', or 'xray'. Will only return that
|
|
128
126
|
type of photometry if not None. Default is None and will
|
|
129
127
|
return any type of photometry.
|
|
130
|
-
keep_raw
|
|
128
|
+
keep_raw (bool): If True, keep the raw flux/date/freq/wave associated with
|
|
131
129
|
the dataset. Else, just keep the converted data. Default
|
|
132
130
|
is False.
|
|
133
|
-
**kwargs : Arguments to pass to Otter.query(). Can be
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
**kwargs : Arguments to pass to Otter.query(). Can be::
|
|
132
|
+
|
|
133
|
+
names (list[str]): A list of names to get the metadata for
|
|
134
|
+
coords (SkyCoord): An astropy SkyCoord object with coordinates
|
|
136
135
|
to match to
|
|
137
|
-
radius
|
|
136
|
+
radius (float): The radius in arcseconds for a cone search,
|
|
138
137
|
default is 0.05"
|
|
139
|
-
minZ
|
|
140
|
-
maxZ
|
|
141
|
-
refs
|
|
138
|
+
minZ (float): The minimum redshift to search for
|
|
139
|
+
maxZ (float): The maximum redshift to search for
|
|
140
|
+
refs (list[str]): A list of ads bibcodes to match to. Will only
|
|
142
141
|
return metadata for transients that have this
|
|
143
142
|
as a reference.
|
|
144
|
-
hasSpec
|
|
143
|
+
hasSpec (bool): if True, only return events that have spectra.
|
|
145
144
|
|
|
146
145
|
Return:
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
The photometry for the requested transients that match the arguments.
|
|
147
|
+
Will be an astropy Table sorted by transient default name.
|
|
148
|
+
|
|
149
|
+
Raises:
|
|
150
|
+
FailedQueryError: When the query returns no results
|
|
151
|
+
IOError: if one of your inputs is incorrect
|
|
149
152
|
"""
|
|
150
153
|
queryres = self.query(hasphot=True, **kwargs)
|
|
151
154
|
|
|
@@ -153,16 +156,25 @@ class Otter(object):
|
|
|
153
156
|
for transient in queryres:
|
|
154
157
|
# clean the photometry
|
|
155
158
|
default_name = transient["name/default_name"]
|
|
156
|
-
phot = transient.clean_photometry(
|
|
157
|
-
flux_unit=flux_unit,
|
|
158
|
-
date_unit=date_unit,
|
|
159
|
-
wave_unit=wave_unit,
|
|
160
|
-
freq_unit=freq_unit,
|
|
161
|
-
obs_type=obs_type,
|
|
162
|
-
)
|
|
163
|
-
phot["name"] = [default_name] * len(phot)
|
|
164
159
|
|
|
165
|
-
|
|
160
|
+
try:
|
|
161
|
+
phot = transient.clean_photometry(
|
|
162
|
+
flux_unit=flux_unit,
|
|
163
|
+
date_unit=date_unit,
|
|
164
|
+
wave_unit=wave_unit,
|
|
165
|
+
freq_unit=freq_unit,
|
|
166
|
+
obs_type=obs_type,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
phot["name"] = [default_name] * len(phot)
|
|
170
|
+
|
|
171
|
+
dicts.append(phot)
|
|
172
|
+
|
|
173
|
+
except FailedQueryError:
|
|
174
|
+
# This is fine, it just means that there is no data associated
|
|
175
|
+
# with this one transient. We'll check and make sure there is data
|
|
176
|
+
# associated with at least one of the transients later!
|
|
177
|
+
pass
|
|
166
178
|
|
|
167
179
|
if len(dicts) == 0:
|
|
168
180
|
raise FailedQueryError()
|
|
@@ -203,7 +215,7 @@ class Otter(object):
|
|
|
203
215
|
Loads an otter JSON file
|
|
204
216
|
|
|
205
217
|
Args:
|
|
206
|
-
filename
|
|
218
|
+
filename (str): The path to the OTTER JSON file to load
|
|
207
219
|
"""
|
|
208
220
|
|
|
209
221
|
# read in files from summary
|
|
@@ -234,15 +246,15 @@ class Otter(object):
|
|
|
234
246
|
same units.
|
|
235
247
|
|
|
236
248
|
Args:
|
|
237
|
-
names
|
|
238
|
-
coords
|
|
239
|
-
radius
|
|
240
|
-
minz
|
|
241
|
-
maxz
|
|
242
|
-
refs
|
|
249
|
+
names (list[str]): A list of names to get the metadata for
|
|
250
|
+
coords (SkyCoord): An astropy SkyCoord object with coordinates to match to
|
|
251
|
+
radius (float): The radius in arcseconds for a cone search, default is 0.05"
|
|
252
|
+
minz (float): The minimum redshift to search for
|
|
253
|
+
maxz (float): The maximum redshift to search for
|
|
254
|
+
refs (list[str]): A list of ads bibcodes to match to. Will only return
|
|
243
255
|
metadata for transients that have this as a reference.
|
|
244
|
-
hasphot
|
|
245
|
-
hasspec
|
|
256
|
+
hasphot (bool): if True, only returns transients which have photometry.
|
|
257
|
+
hasspec (bool): if True, only return transients that have spectra.
|
|
246
258
|
|
|
247
259
|
Return:
|
|
248
260
|
Get all of the raw (unconverted!) data for objects that match the criteria.
|
|
@@ -344,24 +356,29 @@ class Otter(object):
|
|
|
344
356
|
|
|
345
357
|
return outdata
|
|
346
358
|
|
|
347
|
-
def save(self, schema: list[dict], testing=False
|
|
359
|
+
def save(self, schema: list[dict], testing=False) -> None:
|
|
348
360
|
"""
|
|
349
361
|
Upload all the data in the given list of schemas.
|
|
350
362
|
|
|
351
363
|
Args:
|
|
352
|
-
schema
|
|
364
|
+
schema (list[dict]): A list of json dictionaries
|
|
365
|
+
testing (bool): Should we just enter test mode? Default is False
|
|
366
|
+
|
|
367
|
+
Raises:
|
|
368
|
+
OtterLimitationError: If some objects in OTTER are within 5" we can't figure
|
|
369
|
+
out which ones to merge with which ones.
|
|
353
370
|
"""
|
|
354
371
|
|
|
355
372
|
if not isinstance(schema, list):
|
|
356
373
|
schema = [schema]
|
|
357
374
|
|
|
358
375
|
for transient in schema:
|
|
359
|
-
print(transient["name/default_name"])
|
|
360
|
-
|
|
361
376
|
# convert the json to a Transient
|
|
362
377
|
if not isinstance(transient, Transient):
|
|
363
378
|
transient = Transient(transient)
|
|
364
379
|
|
|
380
|
+
print(transient["name/default_name"])
|
|
381
|
+
|
|
365
382
|
coord = transient.get_skycoord()
|
|
366
383
|
res = self.cone_search(coords=coord)
|
|
367
384
|
|
|
@@ -405,8 +422,6 @@ class Otter(object):
|
|
|
405
422
|
outfilepath = os.path.join(self.DATADIR, todel[0] + ".json")
|
|
406
423
|
if test_mode:
|
|
407
424
|
print("Renaming the following file for backups: ", outfilepath)
|
|
408
|
-
else:
|
|
409
|
-
os.rename(outfilepath, outfilepath + ".backup")
|
|
410
425
|
else:
|
|
411
426
|
if test_mode:
|
|
412
427
|
print("Don't need to mess with the files at all!")
|
|
@@ -429,13 +444,16 @@ class Otter(object):
|
|
|
429
444
|
print(f"Would write to {outfilepath}")
|
|
430
445
|
# print(out)
|
|
431
446
|
|
|
432
|
-
def generate_summary_table(self, save=False):
|
|
447
|
+
def generate_summary_table(self, save=False) -> pd.DataFrame:
|
|
433
448
|
"""
|
|
434
449
|
Generate a summary table for the JSON files in self.DATADIR
|
|
435
450
|
|
|
436
451
|
args:
|
|
437
|
-
save
|
|
438
|
-
in self.DATADIR. Default is False.
|
|
452
|
+
save (bool): if True, save the summary file to "summary.csv"
|
|
453
|
+
in self.DATADIR. Default is False and is just returned.
|
|
454
|
+
|
|
455
|
+
returns:
|
|
456
|
+
pandas.DataFrame of the summary meta information of the transients
|
|
439
457
|
"""
|
|
440
458
|
allfiles = glob.glob(os.path.join(self.DATADIR, "*.json"))
|
|
441
459
|
|
otter/io/transient.py
CHANGED
|
@@ -3,10 +3,12 @@ Class for a transient,
|
|
|
3
3
|
basically just inherits the dict properties with some overwriting
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
from __future__ import annotations
|
|
6
7
|
import warnings
|
|
7
8
|
from copy import deepcopy
|
|
8
9
|
import re
|
|
9
10
|
from collections.abc import MutableMapping
|
|
11
|
+
from typing_extensions import Self
|
|
10
12
|
|
|
11
13
|
import numpy as np
|
|
12
14
|
import pandas as pd
|
|
@@ -37,7 +39,9 @@ class Transient(MutableMapping):
|
|
|
37
39
|
Overwrite the dictionary init
|
|
38
40
|
|
|
39
41
|
Args:
|
|
40
|
-
d
|
|
42
|
+
d (dict): A transient dictionary
|
|
43
|
+
name (str): The default name of the transient, default is None and it will
|
|
44
|
+
be inferred from the input dictionary.
|
|
41
45
|
"""
|
|
42
46
|
self.data = d
|
|
43
47
|
|
|
@@ -68,7 +72,7 @@ class Transient(MutableMapping):
|
|
|
68
72
|
"""
|
|
69
73
|
|
|
70
74
|
if isinstance(keys, (list, tuple)):
|
|
71
|
-
return Transient({key: self[key] for key in keys})
|
|
75
|
+
return Transient({key: (self[key] if key in self else []) for key in keys})
|
|
72
76
|
elif isinstance(keys, str) and "/" in keys: # this is for a path
|
|
73
77
|
s = "']['".join(keys.split("/"))
|
|
74
78
|
s = "['" + s
|
|
@@ -85,6 +89,10 @@ class Transient(MutableMapping):
|
|
|
85
89
|
return self.data[keys]
|
|
86
90
|
|
|
87
91
|
def __setitem__(self, key, value):
|
|
92
|
+
"""
|
|
93
|
+
Override set item to work with the '/' syntax
|
|
94
|
+
"""
|
|
95
|
+
|
|
88
96
|
if isinstance(key, str) and "/" in key: # this is for a path
|
|
89
97
|
s = "']['".join(key.split("/"))
|
|
90
98
|
s = "['" + s
|
|
@@ -109,7 +117,7 @@ class Transient(MutableMapping):
|
|
|
109
117
|
|
|
110
118
|
def __repr__(self, html=False):
|
|
111
119
|
if not html:
|
|
112
|
-
return
|
|
120
|
+
return f"Transient(\n\tName: {self.default_name},\n\tKeys: {self.keys()}\n)"
|
|
113
121
|
else:
|
|
114
122
|
html = ""
|
|
115
123
|
|
|
@@ -260,14 +268,17 @@ class Transient(MutableMapping):
|
|
|
260
268
|
# now return out as a Transient Object
|
|
261
269
|
return Transient(out)
|
|
262
270
|
|
|
263
|
-
def get_meta(self, keys=None):
|
|
271
|
+
def get_meta(self, keys=None) -> Self:
|
|
264
272
|
"""
|
|
265
273
|
Get the metadata (no photometry or spectra)
|
|
266
274
|
|
|
267
275
|
This essentially just wraps on __getitem__ but with some checks
|
|
268
276
|
|
|
269
277
|
Args:
|
|
270
|
-
keys
|
|
278
|
+
keys (list[str]) : list of keys to get the metadata for from the transient
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
A Transient object of just the meta data
|
|
271
282
|
"""
|
|
272
283
|
if keys is None:
|
|
273
284
|
keys = list(self.keys())
|
|
@@ -296,9 +307,16 @@ class Transient(MutableMapping):
|
|
|
296
307
|
|
|
297
308
|
return self[keys]
|
|
298
309
|
|
|
299
|
-
def get_skycoord(self, coord_format="icrs"):
|
|
310
|
+
def get_skycoord(self, coord_format="icrs") -> SkyCoord:
|
|
300
311
|
"""
|
|
301
312
|
Convert the coordinates to an astropy SkyCoord
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
coord_format (str): Astropy coordinate format to convert the SkyCoord to
|
|
316
|
+
defaults to icrs.
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Astropy.coordinates.SkyCoord of the default coordinate for the transient
|
|
302
320
|
"""
|
|
303
321
|
|
|
304
322
|
# now we can generate the SkyCoord
|
|
@@ -309,9 +327,12 @@ class Transient(MutableMapping):
|
|
|
309
327
|
|
|
310
328
|
return coord
|
|
311
329
|
|
|
312
|
-
def get_discovery_date(self):
|
|
330
|
+
def get_discovery_date(self) -> Time:
|
|
313
331
|
"""
|
|
314
|
-
Get the default discovery date
|
|
332
|
+
Get the default discovery date for this Transient
|
|
333
|
+
|
|
334
|
+
Returns:
|
|
335
|
+
astropy.time.Time of the default discovery date
|
|
315
336
|
"""
|
|
316
337
|
key = "date_reference"
|
|
317
338
|
date = self._get_default(key, filt='df["date_type"] == "discovery"')
|
|
@@ -322,9 +343,12 @@ class Transient(MutableMapping):
|
|
|
322
343
|
|
|
323
344
|
return Time(date["value"], format=f)
|
|
324
345
|
|
|
325
|
-
def get_redshift(self):
|
|
346
|
+
def get_redshift(self) -> float:
|
|
326
347
|
"""
|
|
327
|
-
Get the default redshift
|
|
348
|
+
Get the default redshift of this Transient
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
Float value of the default redshift
|
|
328
352
|
"""
|
|
329
353
|
f = "df['distance_type']=='redshift'"
|
|
330
354
|
default = self._get_default("distance", filt=f)
|
|
@@ -390,10 +414,32 @@ class Transient(MutableMapping):
|
|
|
390
414
|
wave_unit: u.Unit = "nm",
|
|
391
415
|
by: str = "raw",
|
|
392
416
|
obs_type: str = None,
|
|
393
|
-
):
|
|
417
|
+
) -> pd.DataFrame:
|
|
394
418
|
"""
|
|
395
419
|
Ensure the photometry associated with this transient is all in the same
|
|
396
420
|
units/system/etc
|
|
421
|
+
|
|
422
|
+
Args:
|
|
423
|
+
flux_unit (astropy.unit.Unit): The astropy unit or string representation of
|
|
424
|
+
an astropy unit to convert and return the
|
|
425
|
+
flux as.
|
|
426
|
+
date_unit (str): Valid astropy date format string.
|
|
427
|
+
freq_unit (astropy.unit.Unit): The astropy unit or string representation of
|
|
428
|
+
an astropy unit to convert and return the
|
|
429
|
+
frequency as.
|
|
430
|
+
wave_unit (astropy.unit.Unit): The astropy unit or string representation of
|
|
431
|
+
an astropy unit to convert and return the
|
|
432
|
+
wavelength as.
|
|
433
|
+
by (str): Either 'raw' or 'value'. 'raw' is the default and is highly
|
|
434
|
+
recommended! If 'value' is used it may skip some photometry.
|
|
435
|
+
See the schema definition to understand this keyword completely
|
|
436
|
+
before using it.
|
|
437
|
+
obs_type (str): "radio", "xray", or "uvoir". If provided, it only returns
|
|
438
|
+
data taken within that range of wavelengths/frequencies.
|
|
439
|
+
Default is None which will return all of the data.
|
|
440
|
+
|
|
441
|
+
Returns:
|
|
442
|
+
A pandas DataFrame of the cleaned up photometry in the requested units
|
|
397
443
|
"""
|
|
398
444
|
|
|
399
445
|
# check inputs
|
|
@@ -429,6 +475,9 @@ class Transient(MutableMapping):
|
|
|
429
475
|
else:
|
|
430
476
|
by = "value"
|
|
431
477
|
|
|
478
|
+
# skip rows where 'by' is nan
|
|
479
|
+
df = df[df[by].notna()]
|
|
480
|
+
|
|
432
481
|
# drop irrelevant obs_types before continuing
|
|
433
482
|
if obs_type is not None:
|
|
434
483
|
valid_obs_types = {"radio", "uvoir", "xray"}
|
otter/plotter/otter_plotter.py
CHANGED
|
@@ -6,19 +6,21 @@ Currently supported backends are:
|
|
|
6
6
|
- plotly
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
from __future__ import annotations
|
|
9
10
|
import importlib
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class OtterPlotter:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Handles the backend for the "plotter" module
|
|
14
|
+
"""
|
|
15
|
+
Handles the backend for the "plotter" module
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
Args:
|
|
18
|
+
backend (string): a string of the module name to import and use
|
|
19
|
+
as the backend. Currently supported are "matplotlib",
|
|
20
|
+
"matplotlib.pyplot", "plotly", and "plotly.graph_objects"
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, backend):
|
|
22
24
|
if backend == "matplotlib.pyplot":
|
|
23
25
|
self.backend = backend
|
|
24
26
|
elif backend == "pyplot.graph_objects":
|
otter/plotter/plotter.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Some utilities to create common plots for transients that use the OtterPlotter
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
from .otter_plotter import OtterPlotter
|
|
6
7
|
|
|
7
8
|
|
|
@@ -21,15 +22,15 @@ def plot_light_curve(
|
|
|
21
22
|
Plot the light curve for the input data
|
|
22
23
|
|
|
23
24
|
Args:
|
|
24
|
-
date
|
|
25
|
-
flux
|
|
26
|
-
date_err
|
|
27
|
-
flux_err
|
|
28
|
-
fig
|
|
29
|
-
ax
|
|
30
|
-
backend
|
|
31
|
-
xlabel
|
|
32
|
-
ylabel
|
|
25
|
+
date (float): MJD dates
|
|
26
|
+
flux (float): Flux
|
|
27
|
+
date_err (float): optional error on the MJD dates
|
|
28
|
+
flux_err (float): optional error on the flux
|
|
29
|
+
fig (float): matplotlib fig object, optional. Will be created if not provided.
|
|
30
|
+
ax (float): matplitlib axis object, optional. Will be created if not provided.
|
|
31
|
+
backend (str): backend for plotting. options: "matplotlib" (default) or "plotly"
|
|
32
|
+
xlabel (str): x-axis label
|
|
33
|
+
ylabel (str): y-axis label
|
|
33
34
|
**kwargs: keyword arguments to pass to either plotly.graph_objects.add_scatter
|
|
34
35
|
or matplotlib.pyplot.errorbar
|
|
35
36
|
|
|
@@ -66,15 +67,15 @@ def plot_sed(
|
|
|
66
67
|
Plot the SED for the input data
|
|
67
68
|
|
|
68
69
|
Args:
|
|
69
|
-
wave_or_freq
|
|
70
|
-
flux
|
|
71
|
-
wave_or_freq_err
|
|
72
|
-
flux_err
|
|
73
|
-
fig
|
|
74
|
-
ax
|
|
75
|
-
backend
|
|
76
|
-
xlabel
|
|
77
|
-
ylabel
|
|
70
|
+
wave_or_freq (float): wave or frequency array
|
|
71
|
+
flux (float): Flux
|
|
72
|
+
wave_or_freq_err (float): optional error on the MJD dates
|
|
73
|
+
flux_err (float): optional error on the flux
|
|
74
|
+
fig (float): matplotlib fig object, optional. Will be created if not provided.
|
|
75
|
+
ax (float): matplitlib axis object, optional. Will be created if not provided.
|
|
76
|
+
backend (str): backend for plotting. Options: "matplotlib" (default) or "plotly"
|
|
77
|
+
xlabel (str): x-axis label
|
|
78
|
+
ylabel (str): y-axis label
|
|
78
79
|
**kwargs: keyword arguments to pass to either plotly.graph_objects.add_scatter
|
|
79
80
|
or matplotlib.pyplot.errorbar
|
|
80
81
|
|
otter/util.py
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Some constants, mappings, and functions to be used across the software
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from __future__ import annotations
|
|
5
6
|
import os
|
|
6
7
|
import ads
|
|
7
8
|
import astropy.units as u
|
|
@@ -187,6 +188,10 @@ FILTER_MAP_WAVE = {
|
|
|
187
188
|
"F2100W": 20842.526633138932,
|
|
188
189
|
"F2550W": 25408.228367890282,
|
|
189
190
|
}
|
|
191
|
+
"""
|
|
192
|
+
Mapping for the effective wavelength in nanometers for all filters used in the dataset.
|
|
193
|
+
"""
|
|
194
|
+
|
|
190
195
|
|
|
191
196
|
# gives the effective frequency for all filters
|
|
192
197
|
# These are all in THz
|
|
@@ -302,6 +307,10 @@ FILTER_MAP_FREQ = {
|
|
|
302
307
|
"F2100W": 14.581938602646188,
|
|
303
308
|
"F2550W": 11.919267708332558,
|
|
304
309
|
}
|
|
310
|
+
"""
|
|
311
|
+
Mapping for the effective frequencies in THz for all the filters used in OTTER
|
|
312
|
+
"""
|
|
313
|
+
|
|
305
314
|
|
|
306
315
|
# x-ray telescope areas for converting
|
|
307
316
|
# NOTE: these are estimates from the links provided
|
|
@@ -319,10 +328,27 @@ XRAY_AREAS = {
|
|
|
319
328
|
# https://cxc.harvard.edu/cdo/about_chandra
|
|
320
329
|
"chandra": 600 * u.cm**2,
|
|
321
330
|
}
|
|
331
|
+
"""
|
|
332
|
+
X-Ray telescope areas that are used for converting from counts to other units.
|
|
333
|
+
|
|
334
|
+
NOTE: These are estimates from the following links
|
|
335
|
+
* https://swift.gsfc.nasa.gov/about_swift/Sci_Fact_Sheet.pdf
|
|
336
|
+
* https://heasarc.gsfc.nasa.gov/docs/rosat/ruh/handbook/node39.html#SECTION00634000000000000000
|
|
337
|
+
* https://www.cosmos.esa.int/web/xmm-newton/technical-details-mirrors
|
|
338
|
+
* https://cxc.harvard.edu/cdo/about_chandra
|
|
339
|
+
"""
|
|
340
|
+
|
|
322
341
|
|
|
323
342
|
# define a working base directory constant
|
|
324
343
|
BASEDIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
344
|
+
"""
|
|
345
|
+
Base directory for the OTTER API software package
|
|
346
|
+
"""
|
|
347
|
+
|
|
325
348
|
DATADIR = os.path.join(BASEDIR, "data", "base")
|
|
349
|
+
"""
|
|
350
|
+
Deprecated database directory that IS NOT always constant anymore
|
|
351
|
+
"""
|
|
326
352
|
|
|
327
353
|
# Overarching schema that stops once we get down to a string or list
|
|
328
354
|
schema = {
|
|
@@ -337,10 +363,16 @@ schema = {
|
|
|
337
363
|
"spectra": [],
|
|
338
364
|
"filter_alias": [],
|
|
339
365
|
}
|
|
340
|
-
|
|
366
|
+
"""
|
|
367
|
+
Schema dictionary to be filled with values from the subschemas
|
|
368
|
+
"""
|
|
341
369
|
|
|
342
370
|
# sub schemas that get filled into lists
|
|
343
371
|
name_alias_schema = {"value": None, "reference": None}
|
|
372
|
+
"""
|
|
373
|
+
Subschema for the name and alias dictionary
|
|
374
|
+
"""
|
|
375
|
+
|
|
344
376
|
coordinate_schema = {
|
|
345
377
|
"ra": None,
|
|
346
378
|
"dec": None,
|
|
@@ -367,6 +399,10 @@ coordinate_schema = {
|
|
|
367
399
|
"reference": None,
|
|
368
400
|
"default": None,
|
|
369
401
|
}
|
|
402
|
+
"""
|
|
403
|
+
Subschema to describe the possible attributes for the coordinate dictionary
|
|
404
|
+
"""
|
|
405
|
+
|
|
370
406
|
|
|
371
407
|
distance_schema = {
|
|
372
408
|
"value": None,
|
|
@@ -379,6 +415,10 @@ distance_schema = {
|
|
|
379
415
|
"default": None,
|
|
380
416
|
"distance_type": None,
|
|
381
417
|
}
|
|
418
|
+
"""
|
|
419
|
+
Subschema to describe the possible attributes for the distance dictionary
|
|
420
|
+
"""
|
|
421
|
+
|
|
382
422
|
|
|
383
423
|
classification_schema = {
|
|
384
424
|
"object_class": None,
|
|
@@ -387,8 +427,14 @@ classification_schema = {
|
|
|
387
427
|
"reference": None,
|
|
388
428
|
"default": None,
|
|
389
429
|
}
|
|
430
|
+
"""
|
|
431
|
+
Subschema to describe the attributes for the classification dictionary
|
|
432
|
+
"""
|
|
390
433
|
|
|
391
434
|
reference_alias_schema = {"name": None, "human_readable_name": None}
|
|
435
|
+
"""
|
|
436
|
+
Subschema to describe the attributes for the reference alias dictionary
|
|
437
|
+
"""
|
|
392
438
|
|
|
393
439
|
date_reference_schema = {
|
|
394
440
|
"value": None,
|
|
@@ -397,6 +443,9 @@ date_reference_schema = {
|
|
|
397
443
|
"reference": None,
|
|
398
444
|
"computed": None,
|
|
399
445
|
}
|
|
446
|
+
"""
|
|
447
|
+
Subschema to describe the date_reference dictionary attributes
|
|
448
|
+
"""
|
|
400
449
|
|
|
401
450
|
photometry_schema = {
|
|
402
451
|
"raw": None,
|
|
@@ -436,6 +485,10 @@ photometry_schema = {
|
|
|
436
485
|
"val_host": None,
|
|
437
486
|
"val_hostav": None,
|
|
438
487
|
}
|
|
488
|
+
"""
|
|
489
|
+
Subschema to describe all of the possible attributes that can be used in the photometry
|
|
490
|
+
dictionary
|
|
491
|
+
"""
|
|
439
492
|
|
|
440
493
|
spectra_schema = {
|
|
441
494
|
"wavelength": None,
|
|
@@ -495,6 +548,9 @@ filter_alias_schema = {
|
|
|
495
548
|
"zp_units": None,
|
|
496
549
|
"zp_system": None,
|
|
497
550
|
}
|
|
551
|
+
"""
|
|
552
|
+
Subschema to describe the attributes in the filter_alias dictionary
|
|
553
|
+
"""
|
|
498
554
|
|
|
499
555
|
# package the subschemas by the key used for that location in the Transient object
|
|
500
556
|
subschema = {
|
|
@@ -508,3 +564,6 @@ subschema = {
|
|
|
508
564
|
"spectra": spectra_schema,
|
|
509
565
|
"filter_alias": filter_alias_schema,
|
|
510
566
|
}
|
|
567
|
+
"""
|
|
568
|
+
A useful variable to describe all of the subschemas that are available and can be used
|
|
569
|
+
"""
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
otter/__init__.py,sha256=llO9sEPh8xa_dH2W0nlp6eaINvOFmxdThUMfnRLvTlg,339
|
|
2
|
-
otter/_version.py,sha256=IF3Dl1lgaRSZdnbDGaVgT-Wp8FNX0rjz37C1iwLyXlU,76
|
|
3
|
-
otter/exceptions.py,sha256=jaNg0fw5WBWlIRLG0aE5xKJvpIg8JAEDqQ7orwkStq4,494
|
|
4
|
-
otter/util.py,sha256=rnzyNWwjrBLsZIbKi33o1Ly-HbTeAMaUT5E8N313RiY,13600
|
|
5
|
-
otter/io/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
otter/io/otter.py,sha256=S1DaOFg3DtPPyNzrvOg7_QG8fps_6m-w-usINJ6X2gk,17038
|
|
7
|
-
otter/io/transient.py,sha256=vMyaYjlc2SKn9gWII8wrpJRe3NyZViXGMiZ9Pv_voNo,31165
|
|
8
|
-
otter/plotter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
otter/plotter/otter_plotter.py,sha256=WbnzNUR_pE3d2tJcH3K2pxJvl-r6OUUOZ0kWb35FlQE,2083
|
|
10
|
-
otter/plotter/plotter.py,sha256=QeAQXgeJ9O429Khin9dCT2tXvcjxUzc_HLU74LbRw6g,2861
|
|
11
|
-
astro_otter-0.0.1.dist-info/LICENSE,sha256=s9IPE8A3CAMEaZpDhj4eaorpmfLYGB0mIGphq301PUY,1067
|
|
12
|
-
astro_otter-0.0.1.dist-info/METADATA,sha256=KM1FpQrYPArikJMNzmNCYshN6PzJGrYCp4UCTkM3TOw,31847
|
|
13
|
-
astro_otter-0.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
14
|
-
astro_otter-0.0.1.dist-info/top_level.txt,sha256=Wth72sCwBRUk3KZGknSKvLQDMFuJk6qiaAavMDOdG5k,6
|
|
15
|
-
astro_otter-0.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|