astro-otter 0.0.2__py3-none-any.whl → 0.2.0__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.

@@ -1,875 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: astro-otter
3
- Version: 0.0.2
4
- Author-email: Noah Franz <nfranz@arizona.edu>
5
- License: MIT License
6
-
7
- Copyright (c) 2023 Noah Franz
8
-
9
- Permission is hereby granted, free of charge, to any person obtaining a copy
10
- of this software and associated documentation files (the "Software"), to deal
11
- in the Software without restriction, including without limitation the rights
12
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
- copies of the Software, and to permit persons to whom the Software is
14
- furnished to do so, subject to the following conditions:
15
-
16
- The above copyright notice and this permission notice shall be included in all
17
- copies or substantial portions of the Software.
18
-
19
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
- SOFTWARE.
26
-
27
- Project-URL: Home, https://github.com/astro-otter
28
- Classifier: License :: OSI Approved :: BSD License
29
- Classifier: Topic :: Scientific/Engineering
30
- Classifier: Intended Audience :: Science/Research
31
- Classifier: Intended Audience :: Developers
32
- Classifier: Operating System :: OS Independent
33
- Classifier: License :: OSI Approved :: BSD License
34
- Classifier: Programming Language :: Python
35
- Classifier: Programming Language :: Python :: 3
36
- Classifier: Programming Language :: Python :: 3.9
37
- Classifier: Programming Language :: Python :: 3.10
38
- Classifier: Programming Language :: Python :: 3.11
39
- Classifier: Development Status :: 2 - Pre-Alpha
40
- Requires-Python: >=3.9
41
- Description-Content-Type: text/markdown
42
- License-File: LICENSE
43
- Requires-Dist: numpy >=1.20
44
- Requires-Dist: astropy >=5.2
45
- Requires-Dist: pandas
46
- Requires-Dist: matplotlib
47
- Requires-Dist: plotly
48
- Requires-Dist: astroquery
49
- Requires-Dist: synphot
50
- Requires-Dist: ads
51
- Requires-Dist: ruff
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
60
-
61
- # OTTER API
62
- ### **O**pen mul**T**iwavelength **T**ransient **E**vent **R**epository
63
-
64
- A Python API for the OTTER.
65
-
66
- [actions-badge]: https://github.com/astro-otter/otter/workflows/CI/badge.svg
67
- [actions-link]: https://github.com/astro-otter/otter/actions
68
- [black-badge]: https://img.shields.io/badge/code%20style-black-000000.svg
69
- [black-link]: https://github.com/psf/black
70
- [conda-badge]: https://img.shields.io/conda/vn/conda-forge/hepfile
71
- [conda-link]: https://github.com/conda-forge/hepfile-feedstock
72
- [github-discussions-badge]: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github
73
- [github-discussions-link]: https://github.com/mattbellis/hepfile/discussions
74
- [gitter-badge]: https://badges.gitter.im/https://github.com/mattbellis/hepfile/community.svg
75
- [gitter-link]: https://gitter.im/https://github.com/mattbellis/hepfile/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
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
79
- [rtd-badge]: https://readthedocs.org/projects/otter/badge/?version=latest
80
- [rtd-link]: https://otter.readthedocs.io/en/latest/?badge=latest
81
- [sk-badge]: https://scikit-hep.org/assets/images/Scikit--HEP-Project-blue.svg
82
- [ruff-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/charliermarsh/ruff/main/assets/badge/v2.json
83
- [ruff-link]: https://github.com/astral-sh/ruff
84
- [codecov-badge]: https://codecov.io/gh/astro-otter/otter/graph/badge.svg?token=BtCerOdTc0
85
- [codecov-link]: https://codecov.io/gh/astro-otter/otter
86
-
87
- [![Documentation Status](https://readthedocs.org/projects/astro-otter/badge/?version=latest)](https://astro-otter.readthedocs.io/en/latest/?badge=latest)
88
- [![Actions Status][actions-badge]][actions-link]
89
- [![PyPI version][pypi-version]][pypi-link]
90
- [![Linting: Ruff][ruff-badge]][ruff-link]
91
- [![codecov][codecov-badge]][codecov-link]
92
-
93
- ## Installation
94
- To install the OTTER API use
95
- ```
96
- git clone https://github.com/astro-otter/otter.git
97
- cd otter
98
- python -m pip install .
99
- ```
100
- This will be changed into the more convenient `python -m pip install astro-otter` at a later date!
101
-
102
- For developers, please also enable the pre-commit hooks using
103
- ```
104
- pre-commit install
105
- ```
106
-
107
- ## Tutorial
108
- ### Connecting to the OTTER
109
- ```python
110
- # import the API
111
- from otter import Otter, Transient
112
- ```
113
-
114
-
115
- ```python
116
- # connect to the database
117
- # this username and password is just for now and will be updated later!
118
- db = Otter(username='user@otter', password='insecure')
119
- ```
120
-
121
- ### A typical workflow
122
-
123
- First use `Otter.getMeta` to query
124
-
125
- ```python
126
- # can query by ANY name associated with an object
127
- db.getMeta(names=['ASASSN-15oi', 'AT2020opy'])
128
- ```
129
-
130
-
131
-
132
-
133
- [{'name': {'default_name': 'ASASSN-15oi', 'alias': [{'value': 'ASASSN-15oi', 'reference': 'ASASSN'}]}, 'coordinate': {'equitorial': [{'ra': '20 39 09.096', 'dec': '-30 45 20.71', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2021NatAs...5..491H'], 'computed': False, 'default': True, 'uuid': 'a06be641-1601-4737-9a1a-bd25c5dd61e6'}], 'galactic': [{'l': 13.01154485751856, 'b': -35.41877256185317, 'l_units': 'deg', 'b_units': 'deg', 'reference': 'a06be641-1601-4737-9a1a-bd25c5dd61e6', 'computed': True}]}, 'epoch': {'date_discovery': [{'value': 57248.2, 'date_format': 'MJD', 'reference': ['2021NatAs...5..491H'], 'computed': False}]}, 'distance': {'redshift': [{'value': '0.0484', 'reference': ['2021NatAs...5..491H'], 'computed': False, 'default': True}]}, 'classification': [{'object_class': 'TDE', 'confidence': 1, 'reference': ['2021NatAs...5..491H'], 'default': True}]},
134
- {'name': {'default_name': 'AT2020opy', 'alias': [{'value': 'AT2020opy', 'reference': 'TNS'}]}, 'coordinate': {'equitorial': [{'ra': '15 56 25.728', 'dec': '+23 22 21.15', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2023MNRAS.518..847G'], 'computed': False, 'default': True, 'uuid': '4f414ede-e0f0-4423-b2cc-f3ad309f0936'}], 'galactic': [{'l': 38.411569358993255, 'b': 48.23253616380999, 'l_units': 'deg', 'b_units': 'deg', 'reference': '4f414ede-e0f0-4423-b2cc-f3ad309f0936', 'computed': True}]}, 'epoch': {'date_discovery': [{'value': 59038.23, 'date_format': 'MJD', 'reference': ['2023MNRAS.518..847G'], 'computed': False}]}, 'distance': {'redshift': [{'value': '0.159', 'reference': ['2023MNRAS.518..847G'], 'computed': False, 'default': True}]}, 'classification': [{'object_class': 'TDE', 'confidence': 1, 'reference': ['2023MNRAS.518..847G'], 'default': True}]}]
135
-
136
-
137
-
138
- We can also do a cone search
139
- ```python
140
- from astropy.coordinates import SkyCoord
141
- import astropy.units as u
142
- coord = SkyCoord(239, 23, unit=('deg', 'deg'))
143
- rad = (1*u.deg).to(u.arcsec).value
144
- db.getMeta(coords=coord, radius=rad)
145
- ```
146
-
147
-
148
-
149
-
150
- [{'name': {'default_name': 'AT2020opy', 'alias': [{'value': 'AT2020opy', 'reference': 'TNS'}]}, 'coordinate': {'equitorial': [{'ra': '15 56 25.728', 'dec': '+23 22 21.15', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2023MNRAS.518..847G'], 'computed': False, 'default': True, 'uuid': '4f414ede-e0f0-4423-b2cc-f3ad309f0936'}], 'galactic': [{'l': 38.411569358993255, 'b': 48.23253616380999, 'l_units': 'deg', 'b_units': 'deg', 'reference': '4f414ede-e0f0-4423-b2cc-f3ad309f0936', 'computed': True}]}, 'epoch': {'date_discovery': [{'value': 59038.23, 'date_format': 'MJD', 'reference': ['2023MNRAS.518..847G'], 'computed': False}]}, 'distance': {'redshift': [{'value': '0.159', 'reference': ['2023MNRAS.518..847G'], 'computed': False, 'default': True}]}, 'classification': [{'object_class': 'TDE', 'confidence': 1, 'reference': ['2023MNRAS.518..847G'], 'default': True}]}]
151
-
152
-
153
-
154
- Or search within a redshift range (or just a maximum or minimum)
155
- ```python
156
- # can search a redshift range
157
- db.getMeta(minZ=0.5, maxZ=0.9)
158
- ```
159
-
160
-
161
-
162
-
163
- [{'name': {'default_name': 'Sw J1112-82', 'alias': [{'value': 'Sw J1112-82', 'reference': 'Swift'}]}, 'coordinate': {'equitorial': [{'ra': '11 11 47.6', 'dec': '-82 38 44.44', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2017MNRAS.472.4469B'], 'computed': False, 'default': True, 'uuid': '3bb02aa4-eb60-4f09-acdf-d1431a6addc4'}], 'galactic': [{'l': 299.6337165869647, 'b': -20.420594756871665, 'l_units': 'deg', 'b_units': 'deg', 'reference': '3bb02aa4-eb60-4f09-acdf-d1431a6addc4', 'computed': True}]}, 'epoch': {'date_discovery': [{'value': '55729.5', 'date_format': 'MJD', 'reference': ['2017MNRAS.472.4469B'], 'computed': False}]}, 'distance': {'redshift': [{'value': '0.89', 'reference': ['2017MNRAS.472.4469B'], 'computed': False, 'default': True}]}, 'classification': [{'object_class': 'TDE', 'confidence': 1, 'reference': ['2017MNRAS.472.4469B'], 'default': True}]}]
164
-
165
-
166
-
167
- We can even get all objects that have spectra associated with them
168
- ```python
169
- # just get objects that have spectra associated with them
170
- db.getMeta(hasSpec=True)
171
- ```
172
-
173
-
174
-
175
-
176
- []
177
-
178
- This should be empty because at the time of developing this tutorial there were no spectra in
179
- OTTER. Similarly, we can get all objects that have photometry associated with them with
180
- `db.getMeta(hasPhot=True)`.
181
-
182
- These outputs may appear like dictionaries but they're actually customized!
183
-
184
- Besides the typical dictionary methods the following methods are also implemented for Transient objects.
185
-
186
- ```python
187
- help(Transient)
188
- ```
189
-
190
- Help on class Transient in module otter.transient:
191
-
192
- class Transient(collections.abc.MutableMapping)
193
- | Transient(d={}, name=None)
194
- |
195
- | Method resolution order:
196
- | Transient
197
- | collections.abc.MutableMapping
198
- | collections.abc.Mapping
199
- | collections.abc.Collection
200
- | collections.abc.Sized
201
- | collections.abc.Iterable
202
- | collections.abc.Container
203
- | builtins.object
204
- |
205
- | Methods defined here:
206
- |
207
- | __add__(self, other, strict_merge=True)
208
- | Merge this transient object with another transient object
209
- |
210
- | Args:
211
- | other [Transient]: A Transient object to merge with
212
- | strict_merge [bool]: If True it won't let you merge objects that
213
- | intuitively shouldn't be merged (ie. different
214
- | transient events).
215
- |
216
- | __delitem__(self, keys)
217
- |
218
- | __getitem__(self, keys)
219
- |
220
- | __init__(self, d={}, name=None)
221
- | Overwrite the dictionary init
222
- |
223
- | Args:
224
- | d [dict]: A transient dictionary
225
- |
226
- | __iter__(self)
227
- |
228
- | __len__(self)
229
- |
230
- | __repr__(self, html=False)
231
- | Return repr(self).
232
- |
233
- | __setitem__(self, key, value)
234
- |
235
- | cleanPhotometry(self, flux_unit='mag(AB)', date_unit='MJD')
236
- | Ensure the photometry associated with this transient is all in the same units/system/etc
237
- |
238
- | getMeta(self, keys=None)
239
- | Get the metadata (no photometry or spectra)
240
- |
241
- | This essentially just wraps on __getitem__ but with some checks
242
- |
243
- | Args:
244
- | keys [list[str]] : list of keys
245
- |
246
- | getSkyCoord(self, coord_type='equitorial', idx=0)
247
- | Convert the coordinates to an astropy SkyCoord
248
- |
249
- | keys(self)
250
- | D.keys() -> a set-like object providing a view on D's keys
251
- |
252
- | plotPhotometry(self, flux_unit='mag(AB)', date_unit='datetime', **kwargs)
253
- | Plot the photometry associated with this transient (if any)
254
- |
255
- | Args:
256
- | flux_unit [str]: Valid astropy unit string for the flux (y-axis) units.
257
- | Default: 'ABmag'
258
- | date_unit [str]: Valid astropy unit string for the date (x-axis) units.
259
- | Default: 'MJD'
260
-
261
-
262
- Some other advantages of the Transient objects are
263
- ```python
264
- t = db.getMeta(minZ=0.5, maxZ=0.9)[0]
265
- print(type(t))
266
- print()
267
- # say you want to get the equitorial coordinates
268
- # you can do it classically
269
- print(t['coordinate']['equitorial'])
270
-
271
- # or you can use the hdf5 style
272
- print(t['coordinate/equitorial'])
273
- ```
274
-
275
- <class 'otter.transient.Transient'>
276
-
277
- [{'ra': '11 11 47.6', 'dec': '-82 38 44.44', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2017MNRAS.472.4469B'], 'computed': False, 'default': True, 'uuid': '3bb02aa4-eb60-4f09-acdf-d1431a6addc4'}]
278
- [{'ra': '11 11 47.6', 'dec': '-82 38 44.44', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2017MNRAS.472.4469B'], 'computed': False, 'default': True, 'uuid': '3bb02aa4-eb60-4f09-acdf-d1431a6addc4'}]
279
-
280
-
281
- You can even get multiple fields at once like with astropy Tables or pandas DataFrames
282
- ```python
283
- # You can also get multiple fields at once
284
- t[['name/default_name', 'coordinate/equitorial', 'distance']]
285
- ```
286
-
287
-
288
-
289
-
290
- {'name/default_name': 'Sw J1112-82', 'coordinate/equitorial': [{'ra': '11 11 47.6', 'dec': '-82 38 44.44', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2017MNRAS.472.4469B'], 'computed': False, 'default': True, 'uuid': '3bb02aa4-eb60-4f09-acdf-d1431a6addc4'}], 'distance': {'redshift': [{'value': '0.89', 'reference': ['2017MNRAS.472.4469B'], 'computed': False, 'default': True}]}}
291
-
292
-
293
-
294
- You can also add two Transient objects to merge them
295
- ```python
296
- t1, t2 = db.query(names=['ASASSN-15oi', 'AT2020opy'])
297
-
298
- try:
299
- t1 + t2
300
- except ValueError as ve:
301
- print('The following error is actually expected!')
302
- print('We dont want you to be able to combine any old transients!')
303
- print()
304
- print('Error Message:')
305
- print(ve)
306
- ```
307
-
308
- The following error is actually expected!
309
- We dont want you to be able to combine any old transients!
310
-
311
- Error Message:
312
- These two transients are not within 5 arcseconds! They probably do not belong together! If they do You can set strict_merge=False to override the check
313
-
314
-
315
- This error message is expected! If you want to override it then you can do
316
- ```python
317
- t2['photometry'][0]['reference'] = '2021NatAs...5..491H'
318
-
319
- t3 = t1.__add__(t2, strict_merge=False)
320
- ```
321
-
322
- Obviously, this result doesn't makes sense! This has the data from two completely different transients in it. So, be careful using `strict_merge=False`!
323
-
324
- ### Can then get photometry
325
- This does the conversion for you!!!
326
-
327
-
328
- ```python
329
- db.getPhot?
330
- ```
331
- Get the photometry of the objects matching the arguments. This will do the
332
- unit conversion for you!
333
-
334
- Args:
335
- flux_units [astropy.unit.Unit]: Either a valid string to convert
336
- or an astropy.unit.Unit
337
- date_units [astropy.unit.Unit]: Either a valid string to convert to a date
338
- or an astropy.unit.Unit
339
- return_type [str]: Either 'astropy' or 'pandas'. If astropy, returns an
340
- astropy Table. If pandas, returns a pandas DataFrame.
341
- Default is 'astropy'.
342
-
343
- **kwargs : Arguments to pass to Otter.query(). Can be:
344
- names [list[str]]: A list of names to get the metadata for
345
- coords [SkyCoord]: An astropy SkyCoord object with coordinates to match to
346
- radius [float]: The radius in arcseconds for a cone search, default is 0.05"
347
- minZ [float]: The minimum redshift to search for
348
- maxZ [float]: The maximum redshift to search for
349
- refs [list[str]]: A list of ads bibcodes to match to. Will only return
350
- metadata for transients that have this as a reference.
351
- hasSpec [bool]: if True, only return transients that have spectra.
352
-
353
- Return:
354
- The photometry for the requested transients that match the arguments.
355
- Will be an astropy Table sorted by transient default name.
356
-
357
-
358
- This means you can easily grab photometry in consistent units to plot!
359
- ```python
360
- import matplotlib.pyplot as plt
361
- flux_unit = u.ABmag #u.erg/u.s/u.cm**2/u.Hz #'erg/s/cm^2/Hz'
362
- tab = db.getPhot(flux_unit=flux_unit, date_unit='datetime', names=['ASASSN-15oi', 'ASASSN-14li'], return_type='pandas')
363
-
364
- tab
365
- ```
366
-
367
-
368
-
369
-
370
- <div>
371
- <table border="1" class="dataframe">
372
- <thead>
373
- <tr style="text-align: right;">
374
- <th></th>
375
- <th>reference</th>
376
- <th>date</th>
377
- <th>filter_key</th>
378
- <th>computed</th>
379
- <th>obs_type</th>
380
- <th>upperlimit</th>
381
- <th>freq_eff</th>
382
- <th>freq_units</th>
383
- <th>human_readable_refs</th>
384
- <th>converted_flux</th>
385
- <th>converted_date</th>
386
- <th>name</th>
387
- </tr>
388
- </thead>
389
- <tbody>
390
- <tr>
391
- <th>0</th>
392
- <td>2016ApJ...819L..25A</td>
393
- <td>57124.871000</td>
394
- <td>5.0GHz</td>
395
- <td>False</td>
396
- <td>radio</td>
397
- <td>False</td>
398
- <td>5.0</td>
399
- <td>GHz</td>
400
- <td>Alexander et al. (2016)</td>
401
- <td>15.697417</td>
402
- <td>2015-04-12 20:54:14.400000</td>
403
- <td>ASASSN-14li</td>
404
- </tr>
405
- <tr>
406
- <th>1</th>
407
- <td>2016ApJ...819L..25A</td>
408
- <td>57190.830000</td>
409
- <td>5.0GHz</td>
410
- <td>False</td>
411
- <td>radio</td>
412
- <td>False</td>
413
- <td>5.0</td>
414
- <td>GHz</td>
415
- <td>Alexander et al. (2016)</td>
416
- <td>15.797567</td>
417
- <td>2015-06-17 19:55:12.000000</td>
418
- <td>ASASSN-14li</td>
419
- </tr>
420
- <tr>
421
- <th>2</th>
422
- <td>2016ApJ...819L..25A</td>
423
- <td>57229.750000</td>
424
- <td>5.0GHz</td>
425
- <td>False</td>
426
- <td>radio</td>
427
- <td>False</td>
428
- <td>5.0</td>
429
- <td>GHz</td>
430
- <td>Alexander et al. (2016)</td>
431
- <td>15.915797</td>
432
- <td>2015-07-26 18:00:00.000000</td>
433
- <td>ASASSN-14li</td>
434
- </tr>
435
- <tr>
436
- <th>3</th>
437
- <td>2016ApJ...819L..25A</td>
438
- <td>57286.514583</td>
439
- <td>5.0GHz</td>
440
- <td>False</td>
441
- <td>radio</td>
442
- <td>False</td>
443
- <td>5.0</td>
444
- <td>GHz</td>
445
- <td>Alexander et al. (2016)</td>
446
- <td>16.152094</td>
447
- <td>2015-09-21 12:20:59.997120</td>
448
- <td>ASASSN-14li</td>
449
- </tr>
450
- <tr>
451
- <th>4</th>
452
- <td>2016ApJ...819L..25A</td>
453
- <td>57362.700000</td>
454
- <td>5.0GHz</td>
455
- <td>False</td>
456
- <td>radio</td>
457
- <td>False</td>
458
- <td>5.0</td>
459
- <td>GHz</td>
460
- <td>Alexander et al. (2016)</td>
461
- <td>16.547278</td>
462
- <td>2015-12-06 16:48:00.000000</td>
463
- <td>ASASSN-14li</td>
464
- </tr>
465
- <tr>
466
- <th>0</th>
467
- <td>2021NatAs...5..491H</td>
468
- <td>57256.200000</td>
469
- <td>6.1GHz</td>
470
- <td>False</td>
471
- <td>radio</td>
472
- <td>True</td>
473
- <td>6.1</td>
474
- <td>GHz</td>
475
- <td>Horesh et al. (2021)</td>
476
- <td>20.103715</td>
477
- <td>2015-08-22 04:48:00.000000</td>
478
- <td>ASASSN-15oi</td>
479
- </tr>
480
- <tr>
481
- <th>1</th>
482
- <td>2021NatAs...5..491H</td>
483
- <td>57271.200000</td>
484
- <td>6.1GHz</td>
485
- <td>False</td>
486
- <td>radio</td>
487
- <td>True</td>
488
- <td>6.1</td>
489
- <td>GHz</td>
490
- <td>Horesh et al. (2021)</td>
491
- <td>20.009244</td>
492
- <td>2015-09-06 04:48:00.000000</td>
493
- <td>ASASSN-15oi</td>
494
- </tr>
495
- <tr>
496
- <th>2</th>
497
- <td>2021NatAs...5..491H</td>
498
- <td>57338.200000</td>
499
- <td>6.1GHz</td>
500
- <td>False</td>
501
- <td>radio</td>
502
- <td>True</td>
503
- <td>6.1</td>
504
- <td>GHz</td>
505
- <td>Horesh et al. (2021)</td>
506
- <td>19.454622</td>
507
- <td>2015-11-12 04:48:00.000000</td>
508
- <td>ASASSN-15oi</td>
509
- </tr>
510
- <tr>
511
- <th>3</th>
512
- <td>2021NatAs...5..491H</td>
513
- <td>57430.200000</td>
514
- <td>4.8GHz</td>
515
- <td>False</td>
516
- <td>radio</td>
517
- <td>False</td>
518
- <td>4.8</td>
519
- <td>GHz</td>
520
- <td>Horesh et al. (2021)</td>
521
- <td>16.282787</td>
522
- <td>2016-02-12 04:48:00.000000</td>
523
- <td>ASASSN-15oi</td>
524
- </tr>
525
- <tr>
526
- <th>4</th>
527
- <td>2021NatAs...5..491H</td>
528
- <td>57438.200000</td>
529
- <td>4.8GHz</td>
530
- <td>False</td>
531
- <td>radio</td>
532
- <td>False</td>
533
- <td>4.8</td>
534
- <td>GHz</td>
535
- <td>Horesh et al. (2021)</td>
536
- <td>16.515601</td>
537
- <td>2016-02-20 04:48:00.000000</td>
538
- <td>ASASSN-15oi</td>
539
- </tr>
540
- <tr>
541
- <th>5</th>
542
- <td>2021NatAs...5..491H</td>
543
- <td>57445.200000</td>
544
- <td>5.5GHz</td>
545
- <td>False</td>
546
- <td>radio</td>
547
- <td>False</td>
548
- <td>5.5</td>
549
- <td>GHz</td>
550
- <td>Horesh et al. (2021)</td>
551
- <td>16.537560</td>
552
- <td>2016-02-27 04:48:00.000000</td>
553
- <td>ASASSN-15oi</td>
554
- </tr>
555
- <tr>
556
- <th>6</th>
557
- <td>2021NatAs...5..491H</td>
558
- <td>57481.200000</td>
559
- <td>5.5GHz</td>
560
- <td>False</td>
561
- <td>radio</td>
562
- <td>False</td>
563
- <td>5.5</td>
564
- <td>GHz</td>
565
- <td>Horesh et al. (2021)</td>
566
- <td>16.610182</td>
567
- <td>2016-04-03 04:48:00.000000</td>
568
- <td>ASASSN-15oi</td>
569
- </tr>
570
- <tr>
571
- <th>7</th>
572
- <td>2021NatAs...5..491H</td>
573
- <td>57531.200000</td>
574
- <td>5.0GHz</td>
575
- <td>False</td>
576
- <td>radio</td>
577
- <td>False</td>
578
- <td>5.0</td>
579
- <td>GHz</td>
580
- <td>Horesh et al. (2021)</td>
581
- <td>16.571355</td>
582
- <td>2016-05-23 04:48:00.000000</td>
583
- <td>ASASSN-15oi</td>
584
- </tr>
585
- <tr>
586
- <th>8</th>
587
- <td>2021NatAs...5..491H</td>
588
- <td>57617.200000</td>
589
- <td>5.0GHz</td>
590
- <td>False</td>
591
- <td>radio</td>
592
- <td>False</td>
593
- <td>5.0</td>
594
- <td>GHz</td>
595
- <td>Horesh et al. (2021)</td>
596
- <td>16.924287</td>
597
- <td>2016-08-17 04:48:00.000000</td>
598
- <td>ASASSN-15oi</td>
599
- </tr>
600
- <tr>
601
- <th>9</th>
602
- <td>2021NatAs...5..491H</td>
603
- <td>57824.200000</td>
604
- <td>5.0GHz</td>
605
- <td>False</td>
606
- <td>radio</td>
607
- <td>False</td>
608
- <td>5.0</td>
609
- <td>GHz</td>
610
- <td>Horesh et al. (2021)</td>
611
- <td>17.854247</td>
612
- <td>2017-03-12 04:48:00.000000</td>
613
- <td>ASASSN-15oi</td>
614
- </tr>
615
- <tr>
616
- <th>10</th>
617
- <td>2021NatAs...5..491H</td>
618
- <td>58665.200000</td>
619
- <td>3.0GHz</td>
620
- <td>False</td>
621
- <td>radio</td>
622
- <td>False</td>
623
- <td>3.0</td>
624
- <td>GHz</td>
625
- <td>Horesh et al. (2021)</td>
626
- <td>14.142275</td>
627
- <td>2019-07-01 04:48:00.000000</td>
628
- <td>ASASSN-15oi</td>
629
- </tr>
630
- </tbody>
631
- </table>
632
- </div>
633
-
634
-
635
-
636
-
637
- ```python
638
- fig, ax = plt.subplots()
639
- for key, table in tab.groupby('name'):
640
- ax.plot(table['converted_date'], table['converted_flux'], label=key, marker='o', linestyle='none')
641
-
642
- ax.set_ylabel(f'Flux Density [{flux_unit}]')
643
- ax.set_xlabel('Date')
644
- ax.set_xticks(ax.get_xticks(), ax.get_xticklabels(), rotation=45)
645
- ax.legend();
646
- ```
647
-
648
-
649
- ![png](api-test_files/api-test_17_0.png)
650
-
651
-
652
- ### General Queries (shouldn't be used unless you know what you're doing!)
653
-
654
- The structure of a more generalized query to OTTER is
655
- ```python
656
- # General queries
657
- Otter.query?
658
- ```
659
- Wraps on the super.AQLQuery and queries the OTTER database more intuitively.
660
-
661
- WARNING! This does not do any conversions for you!
662
- This is how it differs from the `getMeta` method. Users should prefer to use
663
- `getMeta`, `getPhot`, and `getSpec` independently because it is a better
664
- workflow and can return the data in an astropy table with everything in the
665
- same units.
666
-
667
- Args:
668
- names [list[str]]: A list of names to get the metadata for
669
- coords [SkyCoord]: An astropy SkyCoord object with coordinates to match to
670
- radius [float]: The radius in arcseconds for a cone search, default is 0.05"
671
- minZ [float]: The minimum redshift to search for
672
- maxZ [float]: The maximum redshift to search for
673
- refs [list[str]]: A list of ads bibcodes to match to. Will only return
674
- metadata for transients that have this as a reference.
675
- hasPhot [bool]: if True, only returns transients which have photometry.
676
- hasSpec [bool]: if True, only return transients that have spectra.
677
-
678
- Return:
679
- Get all of the raw (unconverted!) json data for objects that match the criteria.
680
-
681
-
682
- An example of this is
683
- ```python
684
- res = db.query(names=['ASASSN-15oi', 'AT2020opy'])
685
- print(len(res))
686
- print(type(res[0]))
687
- ```
688
-
689
- 2
690
- <class 'otter.transient.Transient'>
691
-
692
-
693
-
694
- ```python
695
- res[0].keys()
696
- ```
697
-
698
-
699
-
700
-
701
- dict_keys(['_key', '_id', '_rev', 'schema_version', 'name', 'coordinate', 'distance', 'classification', 'reference_alias', 'epoch', 'photometry', 'filter_alias'])
702
-
703
-
704
-
705
- However, Notice how this is simply the raw results!!! This means you need to be very careful with the results you get from these queries because no conversion is done!
706
- ```python
707
- res[0]
708
- ```
709
-
710
-
711
-
712
-
713
- {'_key': '3776907', '_id': 'tdes/3776907', '_rev': '_hD8NTy2---', 'schema_version': {'value': '0', 'comment': 'Original Dataset'}, 'name': {'default_name': 'ASASSN-15oi', 'alias': [{'value': 'ASASSN-15oi', 'reference': 'ASASSN'}]}, 'coordinate': {'equitorial': [{'ra': '20 39 09.096', 'dec': '-30 45 20.71', 'epoch': 'J2000', 'system': 'ICRS', 'ra_units': 'hourangle', 'dec_units': 'deg', 'reference': ['2021NatAs...5..491H'], 'computed': False, 'default': True, 'uuid': 'a06be641-1601-4737-9a1a-bd25c5dd61e6'}], 'galactic': [{'l': 13.01154485751856, 'b': -35.41877256185317, 'l_units': 'deg', 'b_units': 'deg', 'reference': 'a06be641-1601-4737-9a1a-bd25c5dd61e6', 'computed': True}]}, 'distance': {'redshift': [{'value': '0.0484', 'reference': ['2021NatAs...5..491H'], 'computed': False, 'default': True}]}, 'classification': [{'object_class': 'TDE', 'confidence': 1, 'reference': ['2021NatAs...5..491H'], 'default': True}], 'reference_alias': [{'name': '2021NatAs...5..491H', 'human_readable_name': 'Horesh et al. (2021)'}], 'epoch': {'date_discovery': [{'value': 57248.2, 'date_format': 'MJD', 'reference': ['2021NatAs...5..491H'], 'computed': False}]}, 'photometry': [{'reference': '2021NatAs...5..491H', 'raw': [0.033, 0.036, 0.06, 1.114, 0.899, 0.881, 0.824, 0.854, 0.617, 0.262, 8], 'raw_units': ['mJy', 'mJy', 'mJy', 'mJy', 'mJy', 'mJy', 'mJy', 'mJy', 'mJy', 'mJy', 'mJy'], 'date': [57256.2, 57271.2, 57338.2, 57430.2, 57438.2, 57445.2, 57481.2, 57531.2, 57617.2, 57824.2, 58665.2], 'date_format': ['MJD', 'MJD', 'MJD', 'MJD', 'MJD', 'MJD', 'MJD', 'MJD', 'MJD', 'MJD', 'MJD'], 'filter_key': ['6.1GHz', '6.1GHz', '6.1GHz', '4.8GHz', '4.8GHz', '5.5GHz', '5.5GHz', '5.0GHz', '5.0GHz', '5.0GHz', '3.0GHz'], 'computed': [False, False, False, False, False, False, False, False, False, False, False], 'obs_type': ['radio', 'radio', 'radio', 'radio', 'radio', 'radio', 'radio', 'radio', 'radio', 'radio', 'radio'], 'upperlimit': [True, True, True, False, False, False, False, False, False, False, False]}], 'filter_alias': [{'filter_key': '6.1GHz', 'freq_eff': 6.1, 'freq_units': 'GHz'}, {'filter_key': '4.8GHz', 'freq_eff': 4.8, 'freq_units': 'GHz'}, {'filter_key': '5.5GHz', 'freq_eff': 5.5, 'freq_units': 'GHz'}, {'filter_key': '5.0GHz', 'freq_eff': 5, 'freq_units': 'GHz'}, {'filter_key': '3.0GHz', 'freq_eff': 3, 'freq_units': 'GHz'}]}
714
-
715
-
716
-
717
- ### Some helpful methods
718
-
719
- To get the Astropy SkyCoord object for a specific transient you can use
720
- ```python
721
- skycoord = t1.getSkyCoord()
722
- skycoord
723
- ```
724
-
725
-
726
-
727
-
728
- <SkyCoord (ICRS): (ra, dec) in deg
729
- (309.7879, -30.75575278)>
730
-
731
-
732
-
733
- Or, to get the html code for plotting the photometry for a transient
734
- ```python
735
- html = res[0].plotPhotometry()
736
- html[:100] # only show the first part of it
737
- ```
738
-
739
-
740
-
741
-
742
- '<div> <script type="text/javascript">window.PlotlyConfig = {MathJaxConfig: \'l'
743
-
744
-
745
-
746
- ### Uploading/Editing Data
747
- If you have admin access to OTTER you can also upload new data! An example of this is that we first
748
- need to create a new Transient object.
749
-
750
- ```python
751
- from otter import Otter, Transient
752
- from copy import deepcopy
753
- from collections import Counter
754
- import awkward as ak
755
- import warnings
756
- import numpy as np
757
- import re
758
- from astropy.coordinates import SkyCoord
759
- import json
760
-
761
- # generate some test cases
762
- db = Otter()
763
- t1 = db.query(names='2022xkq')[0] #
764
- t2 = deepcopy(t1)
765
- print(t1.keys())
766
-
767
- # change t2 for testing
768
- t2['name'] = {'default_name':'2022xkq',
769
- 'alias': [{'value':'foo', 'reference': 'x'},
770
- {'value': '2022xkq', 'reference': 'x'}]}
771
- t2['reference_alias'].append({'name': 'x',
772
- 'human_readable_name': 'test, name (year)'}) # add an extra value
773
- del t2['photometry']
774
- t2['for_test'] = {'test': 'bar'} # add a test key that isn't in t1
775
- t2['coordinate/equitorial'][0]['reference'] = 'noah'
776
- t2['filter_alias'].append({'filter_key': 'foo'})
777
- t2['schema_version/value'] = 100
778
- t2['epoch'] = {'date_peak': [{'value': 56983,
779
- 'date_format': 'MJD',
780
- 'reference': ['2016ApJ...819L..25A',
781
- '2016Sci...351...62V',
782
- '2016ApJ...832L..10R',
783
- '2018MNRAS.475.4011B'],
784
- 'computed': False}],
785
-
786
- 'date_discovery': [{'value': 56983,
787
- 'date_format': 'MJD',
788
- 'reference': ['2016ApJ...819L..25A',
789
- '2016Sci...351...62V',
790
- '2016ApJ...832L..10R',
791
- '2018MNRAS.475.4011B'],
792
- 'computed': False}],
793
-
794
-
795
- 'date_discovery': [{'value': 56984,
796
- 'date_format': 'MJD',
797
- 'reference': ['2016ApJ...819L..25A',
798
- '2016Sci...351...62V',
799
- '2016ApJ...832L..10R',
800
- '2018MNRAS.475.4011B'],
801
- 'computed': False}]
802
- }
803
-
804
- t2['distance'] = {
805
- "redshift": [
806
- {
807
- "value": "0.0207",
808
- "reference": [
809
- "Noah"
810
- ],
811
- "computed": False
812
- },
813
- {
814
- "value": "0.02",
815
- "reference": [
816
- "Noah"
817
- ],
818
- "computed": False
819
- }
820
- ],
821
-
822
- "dispersion_measure": [
823
- {
824
- "value": "0.0206",
825
- "reference": [
826
- "Noah"
827
- ],
828
- "computed": False
829
- }
830
- ]
831
- }
832
-
833
- t2['classification'] = [{'object_class':'SN',
834
- 'confidence': 1,
835
- 'reference': 'Noah'
836
- }]
837
-
838
- t2['photometry'] = {'phot_0': {'telescope': 'Noahs Telescope',
839
- 'reference': 'Noah',
840
- 'flux': [{'filter': 'z',
841
- 'telescope': 'Noahs Telescope',
842
- 'upperlimit': True,
843
- 'date': 59864.4914116667,
844
- 'date_format': 'MJD',
845
- 'raw': 20.01,
846
- 'raw_units': 'mag(AB)',
847
- 'filter_key': 'NoahsTelescope.z',
848
- 'obs_type': 'uvoir'}]},
849
- 'phot_1': {'telescope': 'CAHA',
850
- 'reference': 'Noah',
851
- 'flux': [{'filter': 'H',
852
- 'telescope': 'CAHA',
853
- 'upperlimit': False,
854
- 'date': 59898.12077,
855
- 'date_format': 'MJD',
856
- 'raw': 14.87048,
857
- 'raw_err': 0.0187,
858
- 'raw_units': 'mag(AB)',
859
- 'filter_key': 'CAHA.H',
860
- 'obs_type': 'uvoir'}]}
861
-
862
- }
863
- ```
864
-
865
- Now we need to connect to OTTER with admin access and upload the new transient object.
866
- ```python
867
- db = Otter(username='admin@otter', password='insecure')
868
- #db.upload(t2)
869
- ```
870
-
871
-
872
- ## Repo Organization
873
- | Directory | Contents |
874
- |------------|------------|
875
- | `py/otter` | A pip installable API for interfacing with the ArangoDB database|