astro-otter 0.3.0__tar.gz → 0.3.3__tar.gz

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.

Files changed (30) hide show
  1. {astro_otter-0.3.0/src/astro_otter.egg-info → astro_otter-0.3.3}/PKG-INFO +4 -9
  2. {astro_otter-0.3.0 → astro_otter-0.3.3}/README.md +2 -7
  3. {astro_otter-0.3.0 → astro_otter-0.3.3}/pyproject.toml +1 -1
  4. {astro_otter-0.3.0 → astro_otter-0.3.3/src/astro_otter.egg-info}/PKG-INFO +4 -9
  5. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/astro_otter.egg-info/requires.txt +1 -1
  6. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/_version.py +1 -1
  7. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/io/otter.py +72 -24
  8. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/io/transient.py +246 -64
  9. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/schema.py +7 -1
  10. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/util.py +27 -1
  11. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_data_finder.py +7 -4
  12. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_host.py +6 -1
  13. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_otter.py +11 -105
  14. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_transient.py +2 -13
  15. {astro_otter-0.3.0 → astro_otter-0.3.3}/LICENSE +0 -0
  16. {astro_otter-0.3.0 → astro_otter-0.3.3}/setup.cfg +0 -0
  17. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/astro_otter.egg-info/SOURCES.txt +0 -0
  18. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/astro_otter.egg-info/dependency_links.txt +0 -0
  19. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/astro_otter.egg-info/top_level.txt +0 -0
  20. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/__init__.py +0 -0
  21. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/exceptions.py +0 -0
  22. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/io/__init__.py +0 -0
  23. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/io/data_finder.py +0 -0
  24. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/io/host.py +0 -0
  25. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/plotter/__init__.py +0 -0
  26. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/plotter/otter_plotter.py +0 -0
  27. {astro_otter-0.3.0 → astro_otter-0.3.3}/src/otter/plotter/plotter.py +0 -0
  28. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_exceptions.py +0 -0
  29. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_package.py +0 -0
  30. {astro_otter-0.3.0 → astro_otter-0.3.3}/tests/test_util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astro-otter
3
- Version: 0.3.0
3
+ Version: 0.3.3
4
4
  Author-email: Noah Franz <nfranz@arizona.edu>
5
5
  License: MIT License
6
6
 
@@ -45,6 +45,7 @@ Requires-Dist: pandas
45
45
  Requires-Dist: synphot
46
46
  Requires-Dist: typing-extensions
47
47
  Requires-Dist: pyarango
48
+ Requires-Dist: tabulate
48
49
  Requires-Dist: matplotlib
49
50
  Requires-Dist: plotly
50
51
  Requires-Dist: astroquery
@@ -53,7 +54,6 @@ Requires-Dist: skypatrol
53
54
  Requires-Dist: fundamentals
54
55
  Requires-Dist: astro-datalab
55
56
  Requires-Dist: sparclclient
56
- Requires-Dist: astro-ghost
57
57
  Requires-Dist: pydantic
58
58
  Requires-Dist: pyreadline3; platform_system == "Windows"
59
59
  Provides-Extra: docs
@@ -117,6 +117,7 @@ python3 -m pip install astro-otter
117
117
  ```
118
118
  git clone https://github.com/astro-otter/otter.git $OTTER_ROOT/otter
119
119
  git clone https://github.com/astro-otter/otterdb.git $OTTER_ROOT/otterdb
120
+ git clone https://github.com/astro-otter/otter-web.git $OTTER_ROOT/otter-web
120
121
  ```
121
122
  3. Install the NASA ADS Python API by following the instructions at https://ads.readthedocs.io/en/latest/#getting-started
122
123
  4. Install otter, the API for this database. From
@@ -125,13 +126,7 @@ python3 -m pip install astro-otter
125
126
  cd $OTTER_ROOT/otter
126
127
  python -m pip install -e .
127
128
  ```
128
- 5. Process the data to build the local "database" (although it is really just a directory).
129
- Then, you can build the "database" by running the
130
- following commands:
131
- ```
132
- cd $OTTER_ROOT/otter/scripts/
133
- python3 gen_summary_table.py --otterroot $OTTER_ROOT
134
- ```
129
+ 5. Process the data to build the local copy of the database. Follow the instructions in the otterdb repo README.
135
130
  6. Easily access the data using the Otter code! In python:
136
131
  ```
137
132
  import os
@@ -45,6 +45,7 @@ python3 -m pip install astro-otter
45
45
  ```
46
46
  git clone https://github.com/astro-otter/otter.git $OTTER_ROOT/otter
47
47
  git clone https://github.com/astro-otter/otterdb.git $OTTER_ROOT/otterdb
48
+ git clone https://github.com/astro-otter/otter-web.git $OTTER_ROOT/otter-web
48
49
  ```
49
50
  3. Install the NASA ADS Python API by following the instructions at https://ads.readthedocs.io/en/latest/#getting-started
50
51
  4. Install otter, the API for this database. From
@@ -53,13 +54,7 @@ python3 -m pip install astro-otter
53
54
  cd $OTTER_ROOT/otter
54
55
  python -m pip install -e .
55
56
  ```
56
- 5. Process the data to build the local "database" (although it is really just a directory).
57
- Then, you can build the "database" by running the
58
- following commands:
59
- ```
60
- cd $OTTER_ROOT/otter/scripts/
61
- python3 gen_summary_table.py --otterroot $OTTER_ROOT
62
- ```
57
+ 5. Process the data to build the local copy of the database. Follow the instructions in the otterdb repo README.
63
58
  6. Easily access the data using the Otter code! In python:
64
59
  ```
65
60
  import os
@@ -33,6 +33,7 @@ dependencies = [
33
33
  "synphot",
34
34
  "typing-extensions",
35
35
  "pyarango",
36
+ "tabulate",
36
37
 
37
38
  # for the plotting
38
39
  "matplotlib",
@@ -45,7 +46,6 @@ dependencies = [
45
46
  "fundamentals",
46
47
  "astro-datalab",
47
48
  "sparclclient",
48
- "astro-ghost",
49
49
 
50
50
  # for the schema validation
51
51
  "pydantic",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: astro-otter
3
- Version: 0.3.0
3
+ Version: 0.3.3
4
4
  Author-email: Noah Franz <nfranz@arizona.edu>
5
5
  License: MIT License
6
6
 
@@ -45,6 +45,7 @@ Requires-Dist: pandas
45
45
  Requires-Dist: synphot
46
46
  Requires-Dist: typing-extensions
47
47
  Requires-Dist: pyarango
48
+ Requires-Dist: tabulate
48
49
  Requires-Dist: matplotlib
49
50
  Requires-Dist: plotly
50
51
  Requires-Dist: astroquery
@@ -53,7 +54,6 @@ Requires-Dist: skypatrol
53
54
  Requires-Dist: fundamentals
54
55
  Requires-Dist: astro-datalab
55
56
  Requires-Dist: sparclclient
56
- Requires-Dist: astro-ghost
57
57
  Requires-Dist: pydantic
58
58
  Requires-Dist: pyreadline3; platform_system == "Windows"
59
59
  Provides-Extra: docs
@@ -117,6 +117,7 @@ python3 -m pip install astro-otter
117
117
  ```
118
118
  git clone https://github.com/astro-otter/otter.git $OTTER_ROOT/otter
119
119
  git clone https://github.com/astro-otter/otterdb.git $OTTER_ROOT/otterdb
120
+ git clone https://github.com/astro-otter/otter-web.git $OTTER_ROOT/otter-web
120
121
  ```
121
122
  3. Install the NASA ADS Python API by following the instructions at https://ads.readthedocs.io/en/latest/#getting-started
122
123
  4. Install otter, the API for this database. From
@@ -125,13 +126,7 @@ python3 -m pip install astro-otter
125
126
  cd $OTTER_ROOT/otter
126
127
  python -m pip install -e .
127
128
  ```
128
- 5. Process the data to build the local "database" (although it is really just a directory).
129
- Then, you can build the "database" by running the
130
- following commands:
131
- ```
132
- cd $OTTER_ROOT/otter/scripts/
133
- python3 gen_summary_table.py --otterroot $OTTER_ROOT
134
- ```
129
+ 5. Process the data to build the local copy of the database. Follow the instructions in the otterdb repo README.
135
130
  6. Easily access the data using the Otter code! In python:
136
131
  ```
137
132
  import os
@@ -4,6 +4,7 @@ pandas
4
4
  synphot
5
5
  typing-extensions
6
6
  pyarango
7
+ tabulate
7
8
  matplotlib
8
9
  plotly
9
10
  astroquery
@@ -12,7 +13,6 @@ skypatrol
12
13
  fundamentals
13
14
  astro-datalab
14
15
  sparclclient
15
- astro-ghost
16
16
  pydantic
17
17
 
18
18
  [:platform_system == "Windows"]
@@ -2,4 +2,4 @@
2
2
  Just define the package version in one place
3
3
  """
4
4
 
5
- __version__ = "0.3.0"
5
+ __version__ = "0.3.3"
@@ -3,11 +3,12 @@ This is the primary class for user interaction with the catalog
3
3
  """
4
4
 
5
5
  from __future__ import annotations
6
+ from typing import Optional
6
7
  import os
7
8
  import json
8
9
  import glob
9
- from warnings import warn
10
10
  from copy import deepcopy
11
+ import logging
11
12
 
12
13
  from pyArango.connection import Connection
13
14
  from pyArango.database import Database
@@ -22,7 +23,7 @@ from astropy import units as u
22
23
 
23
24
  from .transient import Transient
24
25
  from ..exceptions import FailedQueryError, OtterLimitationError, TransientMergeError
25
- from ..util import bibcode_to_hrn, freq_to_obstype, freq_to_band
26
+ from ..util import bibcode_to_hrn, freq_to_obstype, freq_to_band, _DuplicateFilter
26
27
 
27
28
  import warnings
28
29
 
@@ -30,6 +31,8 @@ warnings.simplefilter("once", RuntimeWarning)
30
31
  warnings.simplefilter("once", UserWarning)
31
32
  warnings.simplefilter("once", u.UnitsWarning)
32
33
 
34
+ logger = logging.getLogger(__name__)
35
+
33
36
 
34
37
  def _np_encoder(object):
35
38
  """
@@ -44,23 +47,34 @@ class Otter(Database):
44
47
  This is the primary class for users to access the otter backend database
45
48
 
46
49
  Args:
50
+ url (str): The url where the database api endpoints are located
51
+ username (str): The username to log into the database with
52
+ password (str): The password to log into the database with
53
+ gen_summary (bool): Generate a local summary table, this should generally be
54
+ left as False!
47
55
  datadir (str): Path to the data directory with the otter data. If not provided
48
56
  will default to a ".otter" directory in the CWD where you call
49
57
  this class from.
50
58
  debug (bool): If we should just debug and not do anything serious.
51
59
 
60
+ Returns:
61
+ An Otter object that is connected to the otter database
52
62
  """
53
63
 
54
64
  def __init__(
55
65
  self,
56
66
  url: str = "http://127.0.0.1:8529",
57
- username: str = "user-guest",
58
- password: str = "",
67
+ username: str = os.environ.get("ARANGO_USER_USERNAME", "user-guest"),
68
+ password: str = os.environ.get("ARANGO_USER_PASSWORD", ""),
59
69
  gen_summary: bool = False,
60
70
  datadir: str = None,
61
71
  debug: bool = False,
62
72
  **kwargs,
63
73
  ) -> None:
74
+ print("Attempting to login with the following credentials:")
75
+ print(f"username: {username}")
76
+ print(f"password: {password}")
77
+
64
78
  # save inputs
65
79
  if datadir is None:
66
80
  self.CWD = os.path.dirname(os.path.abspath("__FILE__"))
@@ -79,7 +93,7 @@ class Otter(Database):
79
93
  try:
80
94
  os.makedirs(self.DATADIR)
81
95
  except FileExistsError:
82
- warn(
96
+ logger.warning(
83
97
  "Directory was created between the if statement and trying "
84
98
  + "to create the directory!"
85
99
  )
@@ -93,7 +107,8 @@ class Otter(Database):
93
107
  Get the metadata of the objects matching the arguments
94
108
 
95
109
  Args:
96
- **kwargs : Arguments to pass to Otter.query()
110
+ **kwargs : Arguments to pass to Otter.query(). See that documentation with
111
+ `help(otter.Otter.query)`.
97
112
  Return:
98
113
  The metadata for the transients that match the arguments. Will be an astropy
99
114
  Table by default, if raw=True will be a dictionary.
@@ -146,9 +161,9 @@ class Otter(Database):
146
161
  unit conversion for you!
147
162
 
148
163
  Args:
149
- flux_units (astropy.unit.Unit): Either a valid string to convert
164
+ flux_unit (astropy.unit.Unit): Either a valid string to convert
150
165
  or an astropy.unit.Unit
151
- date_units (astropy.unit.Unit): Either a valid string to convert to a date
166
+ date_unit (astropy.unit.Unit): Either a valid string to convert to a date
152
167
  or an astropy.unit.Unit
153
168
  return_type (str): Either 'astropy' or 'pandas'. If astropy, returns an
154
169
  astropy Table. If pandas, returns a pandas DataFrame.
@@ -159,6 +174,8 @@ class Otter(Database):
159
174
  keep_raw (bool): If True, keep the raw flux/date/freq/wave associated with
160
175
  the dataset. Else, just keep the converted data. Default
161
176
  is False.
177
+ wave_unit (str): The astropy wavelength unit to return with
178
+ freq_unit (str): The astropy frequency unit to return with`
162
179
  **kwargs : Arguments to pass to Otter.query(). Can be::
163
180
 
164
181
  names (list[str]): A list of names to get the metadata for
@@ -181,6 +198,9 @@ class Otter(Database):
181
198
  FailedQueryError: When the query returns no results
182
199
  IOError: if one of your inputs is incorrect
183
200
  """
201
+ warn_filt = _DuplicateFilter()
202
+ logger.addFilter(warn_filt)
203
+
184
204
  queryres = self.query(hasphot=True, **kwargs)
185
205
 
186
206
  dicts = []
@@ -239,6 +259,7 @@ class Otter(Database):
239
259
  else:
240
260
  fullphot = fullphot[keys_to_keep]
241
261
 
262
+ logger.removeFilter(warn_filt)
242
263
  if return_type == "astropy":
243
264
  return Table.from_pandas(fullphot)
244
265
  elif return_type == "pandas":
@@ -252,6 +273,9 @@ class Otter(Database):
252
273
 
253
274
  Args:
254
275
  filename (str): The path to the OTTER JSON file to load
276
+
277
+ Returns:
278
+ dictionary with the otter JSON file contents
255
279
  """
256
280
 
257
281
  # read in files from summary
@@ -270,6 +294,8 @@ class Otter(Database):
270
294
  refs: list[str] = None,
271
295
  hasphot: bool = False,
272
296
  hasspec: bool = False,
297
+ spec_classed: bool = False,
298
+ unambiguous: bool = False,
273
299
  classification: str = None,
274
300
  class_confidence_threshold: float = 0,
275
301
  query_private=False,
@@ -293,10 +319,17 @@ class Otter(Database):
293
319
  refs (list[str]): A list of ads bibcodes to match to. Will only return
294
320
  metadata for transients that have this as a reference.
295
321
  hasphot (bool): if True, only returns transients which have photometry.
296
- hasspec (bool): if True, only return transients that have spectra.
322
+ hasspec (bool): NOT IMPLEMENTED! Will return False for all targets!
323
+ spec_classed (bool): If True, only returns transients that have been
324
+ specotroscopically classified/confirmed
325
+ unambiguous (bool): If True, only returns transients that only have a single
326
+ published classification in OTTER. If classifications
327
+ disagree for a transient, it will be filtered out.
297
328
  classification (str): A classification string to search for
298
329
  class_confidence_threshold (float): classification confidence cutoff for
299
330
  query, between 0 and 1. Default is 0.
331
+ query_private (bool): Set to True if you would like to also query the
332
+ dataset located at whatever you set datadir to
300
333
 
301
334
  Return:
302
335
  Get all of the raw (unconverted!) data for objects that match the criteria.
@@ -310,9 +343,15 @@ class Otter(Database):
310
343
  if hasspec is True:
311
344
  query_filters += "FILTER 'spectra' IN ATTRIBUTES(transient)\n"
312
345
 
346
+ if spec_classed:
347
+ query_filters += "FILTER transient.classification.spec_classed >= 1"
348
+
349
+ if unambiguous:
350
+ query_filters += "FILTER transient.classification.unambiguous"
351
+
313
352
  if classification is not None:
314
353
  query_filters += f"""
315
- FOR subdoc IN transient.classification
354
+ FOR subdoc IN transient.classification.value
316
355
  FILTER subdoc.confidence > TO_NUMBER({class_confidence_threshold})
317
356
  FILTER subdoc.object_class LIKE '%{classification}%'
318
357
  """
@@ -573,7 +612,7 @@ class Otter(Database):
573
612
 
574
613
  def upload(self, json_data, collection="vetting", testing=False) -> Document:
575
614
  """
576
- Upload json_data to collection
615
+ Upload json_data to collection WITHOUT deduplication!
577
616
 
578
617
  Args:
579
618
  json_data [dict] : A dictionary of the json data to upload to Otter
@@ -793,7 +832,7 @@ class Otter(Database):
793
832
  def from_csvs(
794
833
  metafile: str,
795
834
  photfile: str = None,
796
- local_outpath: str = "private_otter_data",
835
+ local_outpath: Optional[str] = None,
797
836
  db: Otter = None,
798
837
  ) -> Otter:
799
838
  """
@@ -815,6 +854,7 @@ class Otter(Database):
815
854
  """
816
855
  # read in the metadata and photometry file
817
856
  meta = pd.read_csv(metafile)
857
+ meta.columns = meta.columns.str.strip() # clean up the col names
818
858
  phot = None
819
859
 
820
860
  required_phot_cols = [
@@ -831,17 +871,20 @@ class Otter(Database):
831
871
 
832
872
  if photfile is not None:
833
873
  phot_unclean = pd.read_csv(photfile)
874
+ phot_unclean.columns = phot_unclean.columns.str.strip() # cleanup colnames
834
875
 
835
876
  phot = phot_unclean.dropna(subset=required_phot_cols)
836
877
  if len(phot) != len(phot_unclean):
837
- warn("""
878
+ logger.warning("""
838
879
  Filtered out rows with nan in the photometry file! Make sure you
839
880
  expect this behaviour!
840
881
  """)
841
882
 
842
883
  if "bibcode" not in phot:
843
884
  phot["bibcode"] = "private"
844
- warn("Setting the bibcode column to the special keyword 'private'!")
885
+ logger.warning("""
886
+ Setting the bibcode column to the special keyword 'private'!
887
+ """)
845
888
 
846
889
  # we need to generate columns of wave_eff and freq_eff
847
890
  wave_eff = []
@@ -866,7 +909,7 @@ class Otter(Database):
866
909
  phot["band_eff_freq_unit"] = str(freq_eff_unit)
867
910
 
868
911
  if not os.path.exists(local_outpath):
869
- os.mkdir(local_outpath)
912
+ os.makedirs(local_outpath)
870
913
 
871
914
  # drop duplicated names in meta and keep the first
872
915
  meta = meta.drop_duplicates(subset="name", keep="first")
@@ -907,7 +950,7 @@ class Otter(Database):
907
950
  ra_units=tde.ra_unit[0],
908
951
  dec_units=tde.dec_unit[0],
909
952
  reference=[tde.coord_bibcode[0]],
910
- coordinate_type="equitorial",
953
+ coordinate_type="equatorial",
911
954
  )
912
955
  ]
913
956
 
@@ -956,13 +999,18 @@ class Otter(Database):
956
999
  ### Classification information that is in the csvs
957
1000
  # classification
958
1001
  if "classification" in tde:
959
- json["classification"] = [
960
- dict(
961
- object_class=tde.classification[0],
962
- confidence=1, # we know this is at least an tde
963
- reference=[tde.classification_bibcode[0]],
964
- )
965
- ]
1002
+ class_flag = 0
1003
+ if "classification_flag" in tde:
1004
+ class_flag = tde.classification_flag[0]
1005
+ json["classification"] = dict(
1006
+ value=[
1007
+ dict(
1008
+ object_class=tde.classification[0],
1009
+ confidence=class_flag,
1010
+ reference=[tde.classification_bibcode[0]],
1011
+ )
1012
+ ]
1013
+ )
966
1014
 
967
1015
  # discovery date
968
1016
  # print(tde)
@@ -1260,7 +1308,7 @@ class Otter(Database):
1260
1308
  if db is None:
1261
1309
  db = Otter(datadir=local_outpath)
1262
1310
  else:
1263
- db.datadir = local_outpath
1311
+ db.DATADIR = local_outpath
1264
1312
 
1265
1313
  # always save this document as a new one
1266
1314
  db.save(all_jsons)