wintertoo 1.1.0__tar.gz → 1.3.0__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 wintertoo might be problematic. Click here for more details.

Files changed (39) hide show
  1. {wintertoo-1.1.0 → wintertoo-1.3.0}/PKG-INFO +1 -1
  2. {wintertoo-1.1.0 → wintertoo-1.3.0}/pyproject.toml +1 -1
  3. {wintertoo-1.1.0 → wintertoo-1.3.0}/tests/test_schedule.py +2 -1
  4. wintertoo-1.3.0/tests/testdata/test_schedule.json +1 -0
  5. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/data/__init__.py +5 -0
  6. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/data/observing_request_schema.json +2 -1
  7. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/models/__init__.py +7 -0
  8. wintertoo-1.3.0/wintertoo/models/image.py +115 -0
  9. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/models/too.py +26 -1
  10. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/schedule.py +2 -0
  11. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/submit.py +36 -5
  12. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo.egg-info/PKG-INFO +1 -1
  13. wintertoo-1.1.0/tests/testdata/test_schedule.json +0 -1
  14. wintertoo-1.1.0/wintertoo/models/image.py +0 -84
  15. {wintertoo-1.1.0 → wintertoo-1.3.0}/.github/dependabot.yml +0 -0
  16. {wintertoo-1.1.0 → wintertoo-1.3.0}/.github/workflows/automerge.yml +0 -0
  17. {wintertoo-1.1.0 → wintertoo-1.3.0}/.github/workflows/black.yml +0 -0
  18. {wintertoo-1.1.0 → wintertoo-1.3.0}/.github/workflows/continuous_integration.yml +0 -0
  19. {wintertoo-1.1.0 → wintertoo-1.3.0}/.github/workflows/isort.yml +0 -0
  20. {wintertoo-1.1.0 → wintertoo-1.3.0}/.github/workflows/pylint.yml +0 -0
  21. {wintertoo-1.1.0 → wintertoo-1.3.0}/.gitignore +0 -0
  22. {wintertoo-1.1.0 → wintertoo-1.3.0}/.pre-commit-config.yaml +0 -0
  23. {wintertoo-1.1.0 → wintertoo-1.3.0}/LICENSE +0 -0
  24. {wintertoo-1.1.0 → wintertoo-1.3.0}/README.md +0 -0
  25. {wintertoo-1.1.0 → wintertoo-1.3.0}/setup.cfg +0 -0
  26. {wintertoo-1.1.0 → wintertoo-1.3.0}/tests/test_fields.py +0 -0
  27. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/__init__.py +0 -0
  28. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/data/summer_fields.txt +0 -0
  29. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/data/winter_fields.txt +0 -0
  30. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/database.py +0 -0
  31. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/errors.py +0 -0
  32. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/fields.py +0 -0
  33. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/models/program.py +0 -0
  34. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/utils.py +0 -0
  35. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo/validate.py +0 -0
  36. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo.egg-info/SOURCES.txt +0 -0
  37. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo.egg-info/dependency_links.txt +0 -0
  38. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo.egg-info/requires.txt +0 -0
  39. {wintertoo-1.1.0 → wintertoo-1.3.0}/wintertoo.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wintertoo
3
- Version: 1.1.0
3
+ Version: 1.3.0
4
4
  Author-email: Robert Stein <rdstein@caltech.edu>, Danielle Frostig <frostig@mit.edu>, Viraj Karambelkar <viraj@astro.caltech.edu>
5
5
  License: MIT
6
6
  Project-URL: homepage, https://github.com/winter-telescope/wintertoo
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "wintertoo"
7
- version = "1.1.0"
7
+ version = "1.3.0"
8
8
  description = ""
9
9
  authors = [
10
10
  {name = "Robert Stein", email = "rdstein@caltech.edu"},
@@ -85,7 +85,8 @@ class TestSchedule(unittest.TestCase):
85
85
 
86
86
  validate_schedule_with_program(schedule, program)
87
87
 
88
- export_schedule_to_sqlitedb(schedule, "test_schedule.db")
88
+ output_path = export_schedule_to_sqlitedb(schedule, test_data_dir)
89
+ output_path.unlink()
89
90
 
90
91
  def test_schedule_utils(self):
91
92
  """
@@ -0,0 +1 @@
1
+ {"targName":{"0":null,"1":null,"2":null,"3":null},"raDeg":{"0":173.7056754,"1":173.7056754,"2":173.7056754,"3":173.7056754},"decDeg":{"0":11.253441,"1":11.253441,"2":11.253441,"3":11.253441},"fieldID":{"0":999999999,"1":999999999,"2":999999999,"3":999999999},"filter":{"0":"u","1":"g","2":"r","3":"i"},"visitExpTime":{"0":30.0,"1":30.0,"2":30.0,"3":30.0},"priority":{"0":50.0,"1":50.0,"2":50.0,"3":50.0},"progPI":{"0":"Stein","1":"Stein","2":"Stein","3":"Stein"},"progName":{"0":"2021A000","1":"2021A000","2":"2021A000","3":"2021A000"},"progID":{"0":1,"1":1,"2":1,"3":1},"validStart":{"0":62721.1894969287,"1":62721.1894969287,"2":62721.1894969287,"3":62721.1894969287},"validStop":{"0":62722.1894969452,"1":62722.1894969452,"2":62722.1894969452,"3":62722.1894969452},"observed":{"0":false,"1":false,"2":false,"3":false},"maxAirmass":{"0":2.0,"1":2.0,"2":2.0,"3":2.0},"ditherNumber":{"0":1,"1":1,"2":1,"3":1},"ditherStepSize":{"0":30.0,"1":30.0,"2":30.0,"3":30.0},"bestDetector":{"0":true,"1":true,"2":true,"3":true},"obsHistID":{"0":0,"1":1,"2":2,"3":3}}
@@ -30,6 +30,11 @@ WINTER_SCIENCE_FILTERS = ["Y", "J", "Hs"]
30
30
  SUMMER_BASE_WIDTH = 0.26112
31
31
  WINTER_BASE_WIDTH = 1.0
32
32
 
33
+ MAX_TARGNAME_LEN = 30
34
+
35
+ WinterImageTypes = Literal["exposure", "raw", "science", "stack", "diff"]
36
+ DEFAULT_IMAGE_TYPE = "stack"
37
+
33
38
  PROGRAM_DB_HOST = "jagati.caltech.edu"
34
39
 
35
40
  too_schedule_config_path = data_dir.joinpath("observing_request_schema.json")
@@ -17,7 +17,8 @@
17
17
  "ditherNumber": {"type": "integer", "default": 1},
18
18
  "ditherStepSize": {"type": "number", "comment": "arcsec", "default": 30.0},
19
19
  "fieldID": {"type": "integer", "default": 999999999},
20
- "targName": {"type": ["string", "null"], "comment": "Target name e.g. GW170817"}
20
+ "targName": {"type": ["string", "null"], "comment": "Target name e.g. GW170817", "default": null},
21
+ "bestDetector": {"type": "boolean", "comment": "Center Ra/Dec of target on best detector", "default": true}
21
22
  },
22
23
  "required": [
23
24
  "obsHistID",
@@ -2,6 +2,13 @@
2
2
  Models for the wintertoo
3
3
  """
4
4
 
5
+ from wintertoo.models.image import (
6
+ ConeImageQuery,
7
+ ImagePath,
8
+ ProgramImageQuery,
9
+ RectangleImageQuery,
10
+ TargetImageQuery,
11
+ )
5
12
  from wintertoo.models.program import Program, ProgramCredentials
6
13
  from wintertoo.models.too import (
7
14
  AllTooClasses,
@@ -0,0 +1,115 @@
1
+ """
2
+ Base models for image queries
3
+ """
4
+
5
+ from typing import Optional
6
+
7
+ from astropy import units as u
8
+ from astropy.time import Time
9
+ from pydantic import BaseModel, Field, model_validator
10
+
11
+ from wintertoo.data import DEFAULT_IMAGE_TYPE, MAX_TARGNAME_LEN, WinterImageTypes
12
+ from wintertoo.errors import WinterValidationError
13
+ from wintertoo.utils import get_date
14
+
15
+
16
+ class ImagePath(BaseModel):
17
+ """
18
+ Base model for image paths
19
+ """
20
+
21
+ path: str = Field(title="Path to image", min_length=1, example="path/to/image.fits")
22
+
23
+
24
+ class ProgramImageQuery(BaseModel):
25
+ """
26
+ Base model for image queries
27
+ """
28
+
29
+ program_name: str = Field(
30
+ title="Program to search for", min_length=1, examples=["2020A000", "2021B001"]
31
+ )
32
+ start_date: int = Field(
33
+ title="Start date for images",
34
+ le=get_date(Time.now()),
35
+ default=get_date(Time.now() - 30.0 * u.day),
36
+ examples=[get_date(Time.now() - 30.0 * u.day), "20230601"],
37
+ )
38
+ end_date: int = Field(
39
+ title="End date for images",
40
+ le=get_date(Time.now()),
41
+ default=get_date(Time.now()),
42
+ examples=[get_date(Time.now() - 30.0 * u.day), get_date(Time.now())],
43
+ )
44
+ kind: WinterImageTypes = Field(
45
+ default=DEFAULT_IMAGE_TYPE, example="raw/science/diff"
46
+ )
47
+
48
+
49
+ class TargetImageQuery(ProgramImageQuery):
50
+ """
51
+ Model for image queries based on target name
52
+ """
53
+
54
+ target_name: Optional[str] = Field(
55
+ title="Name of target",
56
+ min_length=1,
57
+ max_length=MAX_TARGNAME_LEN,
58
+ examples=["SN2023ixf", "ZTF19aapreis"],
59
+ )
60
+
61
+
62
+ class RectangleImageQuery(ProgramImageQuery):
63
+ """
64
+ Model for image queries with a rectangular region
65
+ """
66
+
67
+ ra_min: float = Field(
68
+ title="Minimum RA (degrees)", ge=0.0, le=360.0, examples=[90.0, 180.0]
69
+ )
70
+ ra_max: float = Field(
71
+ title="Minimum RA (degrees)", ge=0.0, le=360.0, examples=[90.0, 180.0]
72
+ )
73
+
74
+ dec_min: float = Field(
75
+ title="Minimum dec (degrees)", ge=-90.0, le=90.0, examples=[-30.0, 10.0]
76
+ )
77
+ dec_max: float = Field(
78
+ title="Minimum dec (degrees)", ge=-90.0, le=90.0, examples=[-30.0, 10.0]
79
+ )
80
+
81
+ @model_validator(mode="after")
82
+ def validate_field_pairs(self):
83
+ """
84
+ Validate that the max value is greater than the min value
85
+
86
+ :return: validated field value
87
+ """
88
+
89
+ pairs = [
90
+ (self.ra_min, self.ra_max, "RA"),
91
+ (self.dec_min, self.dec_max, "Dec"),
92
+ ]
93
+ for min_val, max_val, label in pairs:
94
+ if max_val <= min_val:
95
+ raise WinterValidationError(
96
+ f"{label} range invalid: maximum value ({max_val}) not "
97
+ f"greater than minimum value({min_val})"
98
+ )
99
+ return self
100
+
101
+
102
+ class ConeImageQuery(ProgramImageQuery):
103
+ """
104
+ Model for image queries with a circular region
105
+ """
106
+
107
+ ra: float = Field(
108
+ title="Center RA (degrees)", ge=0.0, le=360.0, examples=[90.0, 180.0]
109
+ )
110
+ dec: float = Field(
111
+ title="Center dec (degrees)", ge=-90.0, le=90.0, examples=[-30.0, 10.0]
112
+ )
113
+ radius_deg: float = Field(
114
+ title="Search radius in degrees", ge=0.0, le=90.0, default=1.0
115
+ )
@@ -8,6 +8,7 @@ from astropy.time import Time
8
8
  from pydantic import BaseModel, ConfigDict, Field, model_validator
9
9
 
10
10
  from wintertoo.data import (
11
+ MAX_TARGNAME_LEN,
11
12
  SUMMER_FILTERS,
12
13
  WINTER_SCIENCE_FILTERS,
13
14
  SummerFilters,
@@ -31,6 +32,13 @@ class ToORequest(BaseModel):
31
32
  title="Priority for target",
32
33
  ge=0.0,
33
34
  )
35
+ target_name: Optional[str] = Field(
36
+ title="Name of the target",
37
+ min_length=1,
38
+ max_length=MAX_TARGNAME_LEN,
39
+ examples=["SN2021abc", "ZTF19aapreis"],
40
+ default=get_default_value("targName"),
41
+ )
34
42
  t_exp: float = Field(
35
43
  default=get_default_value("visitExpTime"),
36
44
  title="Combined Exposure Time across dithers (s)",
@@ -56,6 +64,10 @@ class ToORequest(BaseModel):
56
64
  le=5,
57
65
  title="Allowed airmass range",
58
66
  )
67
+ use_best_detector: bool = Field(
68
+ default=get_default_value("bestDetector"),
69
+ title="Place ra/dec at the center of the best detector",
70
+ )
59
71
 
60
72
  @model_validator(mode="after")
61
73
  def validate_end_time(self):
@@ -116,9 +128,22 @@ class ObsWithRaDec(BaseModel):
116
128
  )
117
129
  use_field_grid: bool = Field(
118
130
  title="boolean whether to select nearest field in grid for central ra/dec",
119
- default=True,
131
+ default=False,
120
132
  )
121
133
 
134
+ @model_validator(mode="after")
135
+ def validate_field_best_detector(self):
136
+ """
137
+ Field validator to ensure that the end time is greater than the start time
138
+
139
+ :return: validated field value
140
+ """
141
+ if self.use_best_detector & self.use_field_grid:
142
+ raise WinterValidationError(
143
+ "Cannot use both use_best_detector and use_field_grid"
144
+ )
145
+ return self
146
+
122
147
 
123
148
  class ObsWithField(BaseModel):
124
149
  """
@@ -45,6 +45,7 @@ def make_schedule(
45
45
  for filter_name in too.filters:
46
46
  for _ in range(too.n_exp):
47
47
  new = {
48
+ "targName": too.target_name,
48
49
  "raDeg": too.ra_deg,
49
50
  "decDeg": too.dec_deg,
50
51
  "fieldID": too.field_id,
@@ -60,6 +61,7 @@ def make_schedule(
60
61
  "maxAirmass": too.max_airmass,
61
62
  "ditherNumber": too.n_dither,
62
63
  "ditherStepSize": too.dither_distance,
64
+ "bestDetector": too.use_best_detector,
63
65
  }
64
66
  all_entries.append(new)
65
67
 
@@ -4,6 +4,7 @@ Module handling submission of ToO schedules
4
4
 
5
5
  import logging
6
6
  from datetime import datetime
7
+ from pathlib import Path
7
8
  from typing import Optional
8
9
 
9
10
  import pandas as pd
@@ -13,8 +14,27 @@ from wintertoo.validate import validate_schedule_df, validate_schedule_request
13
14
 
14
15
  logger = logging.getLogger(__name__)
15
16
 
17
+ FILE_DATE_FORMAT = "%Y_%m_%d_%H_%M_%S"
16
18
 
17
- def export_schedule_to_sqlitedb(schedule: pd.DataFrame, base_save_path: str):
19
+
20
+ def get_db_file_name(program_name: str, date: Optional[datetime] = None) -> str:
21
+ """
22
+ Function to get the name of a database file
23
+
24
+ :param program_name: Name of program
25
+ :param date: Date to use
26
+ :return: String of database file name
27
+ """
28
+
29
+ if date is None:
30
+ date = datetime.now()
31
+
32
+ strf_time = date.strftime(FILE_DATE_FORMAT)
33
+
34
+ return f"request_{program_name}_{strf_time}.db"
35
+
36
+
37
+ def export_schedule_to_sqlitedb(schedule: pd.DataFrame, base_save_path: str) -> Path:
18
38
  """
19
39
  Function to export a schedule to an sqlite db file
20
40
 
@@ -25,17 +45,26 @@ def export_schedule_to_sqlitedb(schedule: pd.DataFrame, base_save_path: str):
25
45
  # Validate format of schedule using json schema
26
46
  validate_schedule_df(schedule)
27
47
 
28
- date = datetime.now().strftime("%m_%d_%Y_%H_%s")
48
+ program_name = str(schedule["progName"].iloc[0])
49
+
50
+ schedule_file_name = get_db_file_name(program_name=program_name)
29
51
 
30
- save_path = f"{base_save_path}timed_requests_{date}.db"
52
+ save_path = Path(base_save_path).joinpath(schedule_file_name)
31
53
 
32
54
  logger.info(f"Saving to {save_path}")
33
55
 
34
56
  sqlite_table = "Summary"
35
57
 
58
+ if not save_path.parent.exists():
59
+ err = f"Parent directory {save_path.parent} does not exist"
60
+ logger.error(err)
61
+ raise ValueError(err)
62
+
36
63
  engine = create_engine(f"sqlite:///{save_path}?check_same_thread=False", echo=True)
37
64
  schedule.to_sql(sqlite_table, engine, if_exists="replace", index=False)
38
65
 
66
+ return save_path
67
+
39
68
 
40
69
  def submit_schedule( # pylint: disable=too-many-arguments
41
70
  schedule: pd.DataFrame,
@@ -47,7 +76,7 @@ def submit_schedule( # pylint: disable=too-many-arguments
47
76
  program_db_password: str,
48
77
  save_path: Optional[str] = None,
49
78
  submit_trigger: bool = True,
50
- ):
79
+ ) -> Optional[Path]:
51
80
  """
52
81
  Function to validate, and then optionally submit, a schedule
53
82
 
@@ -77,4 +106,6 @@ def submit_schedule( # pylint: disable=too-many-arguments
77
106
  logger.error(err)
78
107
  raise ValueError(err)
79
108
 
80
- export_schedule_to_sqlitedb(schedule, save_path)
109
+ return export_schedule_to_sqlitedb(schedule, save_path)
110
+
111
+ return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: wintertoo
3
- Version: 1.1.0
3
+ Version: 1.3.0
4
4
  Author-email: Robert Stein <rdstein@caltech.edu>, Danielle Frostig <frostig@mit.edu>, Viraj Karambelkar <viraj@astro.caltech.edu>
5
5
  License: MIT
6
6
  Project-URL: homepage, https://github.com/winter-telescope/wintertoo
@@ -1 +0,0 @@
1
- {"raDeg":{"0":173.60947,"1":173.60947,"2":173.60947,"3":173.60947},"decDeg":{"0":11.16715,"1":11.16715,"2":11.16715,"3":11.16715},"fieldID":{"0":244641,"1":244641,"2":244641,"3":244641},"filter":{"0":"u","1":"g","2":"r","3":"i"},"visitExpTime":{"0":30.0,"1":30.0,"2":30.0,"3":30.0},"priority":{"0":50.0,"1":50.0,"2":50.0,"3":50.0},"progPI":{"0":"Stein","1":"Stein","2":"Stein","3":"Stein"},"progName":{"0":"2021A000","1":"2021A000","2":"2021A000","3":"2021A000"},"progID":{"0":1,"1":1,"2":1,"3":1},"validStart":{"0":62721.1894969287,"1":62721.1894969287,"2":62721.1894969287,"3":62721.1894969287},"validStop":{"0":62722.1894969452,"1":62722.1894969452,"2":62722.1894969452,"3":62722.1894969452},"observed":{"0":false,"1":false,"2":false,"3":false},"maxAirmass":{"0":2.0,"1":2.0,"2":2.0,"3":2.0},"ditherNumber":{"0":1,"1":1,"2":1,"3":1},"ditherStepSize":{"0":30.0,"1":30.0,"2":30.0,"3":30.0},"obsHistID":{"0":0,"1":1,"2":2,"3":3}}
@@ -1,84 +0,0 @@
1
- """
2
- Base models for image queries
3
- """
4
-
5
- from typing import Literal
6
-
7
- from astropy import units as u
8
- from astropy.time import Time
9
- from pydantic import BaseModel, Field, model_validator
10
-
11
- from wintertoo.errors import WinterValidationError
12
- from wintertoo.models import ProgramCredentials
13
- from wintertoo.utils import get_date
14
-
15
-
16
- class BaseImageQuery(BaseModel):
17
- """
18
- Base model for image queries
19
- """
20
-
21
- program_list: list[ProgramCredentials] = Field(
22
- title="List of programs to search for", min_length=1
23
- )
24
- start_date: int = Field(
25
- title="Start date for images",
26
- le=get_date(Time.now()),
27
- default=get_date(Time.now() - 30.0 * u.day),
28
- )
29
- end_date: int = Field(
30
- title="End date for images",
31
- le=get_date(Time.now()),
32
- default=get_date(Time.now()),
33
- )
34
- kind: Literal["raw", "science", "diff"] = Field(
35
- default="science", title="raw/science/diff"
36
- )
37
-
38
-
39
- class RectangleImageQuery(BaseImageQuery):
40
- """
41
- Model for image queries with a rectangular region
42
- """
43
-
44
- ra_min: float = Field(title="Minimum RA (degrees)", ge=0.0, le=360.0, default=0.0)
45
- ra_max: float = Field(title="Minimum RA (degrees)", ge=0.0, le=360.0, default=360.0)
46
-
47
- dec_min: float = Field(
48
- title="Minimum dec (degrees)", ge=-90.0, le=90.0, default=-90.0
49
- )
50
- dec_max: float = Field(
51
- title="Minimum dec (degrees)", ge=-90.0, le=90.0, default=90.0
52
- )
53
-
54
- @model_validator(mode="after")
55
- def validate_field_pairs(self):
56
- """
57
- Validate that the max value is greater than the min value
58
-
59
- :return: validated field value
60
- """
61
-
62
- pairs = [
63
- (self.ra_min, self.ra_max, "RA"),
64
- (self.dec_min, self.dec_max, "Dec"),
65
- ]
66
- for min_val, max_val, label in pairs:
67
- if max_val <= min_val:
68
- raise WinterValidationError(
69
- f"{label} range invalid: maximum value ({max_val}) not "
70
- f"greater than minimum value({min_val})"
71
- )
72
- return self
73
-
74
-
75
- class ConeImageQuery(BaseImageQuery):
76
- """
77
- Model for image queries with a circular region
78
- """
79
-
80
- ra: float = Field(title="Center RA (degrees)", ge=0.0, le=360.0, default=0.0)
81
- dec: float = Field(title="Center dec (degrees)", ge=-90.0, le=90.0, default=-90.0)
82
- radius_deg: float = Field(
83
- title="Search radius in degrees", ge=0.0, le=90.0, default=1.0
84
- )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes