p2api 1.0.6__tar.gz → 1.0.8__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.
@@ -2,3 +2,4 @@ p2api.egg-info/
2
2
  dist/
3
3
  p2api/__pycache__/
4
4
  p2api/utils/__pycache__/
5
+ *.pyc
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: p2api
3
- Version: 1.0.6
3
+ Version: 1.0.8
4
4
  Summary: Binding for the ESO phase 2 programmatic API
5
5
  Project-URL: Homepage, https://www.eso.org/copdemo/apidoc/index.html
6
6
  Author-email: Thomas Bierwirth <thomas.bierwirth@eso.org>, John Pritchard <john.pritchard@eso.org>
@@ -40,8 +40,6 @@ Classifier: Programming Language :: Python :: 3.9
40
40
  Classifier: Programming Language :: Python :: 3.10
41
41
  Classifier: Programming Language :: Python :: 3.11
42
42
  Classifier: Programming Language :: Python :: 3.12
43
- Requires-Dist: astroplan
44
- Requires-Dist: astropy
45
43
  Requires-Dist: keyring
46
44
  Requires-Dist: requests
47
45
  Description-Content-Type: text/markdown
@@ -0,0 +1 @@
1
+ __version__ = "1.0.8"
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  This file provides an example binding to ESO's RESTful phase 2 programmatic interface.
3
4
  The data required and returned by many of the API calls is instrument-specific.
@@ -141,6 +142,7 @@ class ApiConnection(object):
141
142
  raise P2Error(500, 'POST', param_values['environment'], 'environment not supported')
142
143
  self.apiUrl = API_URL[param_values['environment']]
143
144
  self.loginUrl = LOGIN_URL[param_values['environment']]
145
+ self.p2fc_url = P2FC_URL[param_values['environment']]
144
146
  self.session = self.requests_retry_session()
145
147
 
146
148
  r = requests.post(
@@ -168,6 +170,7 @@ class ApiConnection(object):
168
170
  raise P2Error(500, 'POST', kwargs['url'], 'Invalid URL')
169
171
  self.apiUrl = API_URL[environment]
170
172
  self.loginUrl = LOGIN_URL[environment]
173
+ self.p2fc_url = P2FC_URL[param_values['environment']]
171
174
  self.access_token = kwargs['access_token']
172
175
  self.session = self.requests_retry_session()
173
176
  else :
@@ -1 +1,2 @@
1
1
  # $Id: __init__.py 244843 2019-09-12 07:31:09Z jpritcha $
2
+ # -*- coding: utf-8 -*-
@@ -1,9 +1,15 @@
1
1
  #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
2
3
 
3
4
  # $Id: generate_finding_charts.py 267033 2021-09-16 11:08:57Z jpritcha $
4
5
  from __future__ import print_function
5
6
 
6
7
  _VERSION_ = "$Revision: 267033 $"
8
+ try:
9
+ from ..p2api import __version__
10
+ except:
11
+ from p2api.__about__ import __version__
12
+ _VERSION_ = __version__
7
13
 
8
14
  import sys # interaction with Python interpreter
9
15
  from optparse import OptionParser # for parsing command line arguments
@@ -63,9 +69,24 @@ e.g. yyyy-mm-ddThh:mm,yyyy-mm-ddThh:mm_yyyy-mm-ddThh:mm,yyyy-mm-ddThh:mm{_...}
63
69
 
64
70
  group = OptionGroup(parser, "Specify the Absolute Time Intervals using an orbital ephemeris. This functionality is EXPERIMENTAL, please check carefully!!!")
65
71
  group.add_option("-E", "--ephem", dest="ephem", metavar="T0,PERIOD", help="Comma separated list of orbital T0[JD] and period[days] [optional]", default=None)
66
- group.add_option("--phase_intervals", dest="phase_intervals", help="Comma separated list of phase intervals e.g. 0.1-0.2,0.305-0.375 [optional]", default=None)
72
+ group.add_option(
73
+ "--phase_intervals",
74
+ dest="phase_intervals",
75
+ help="""\
76
+ Comma separated list of phase intervals e.g. 0.1-0.2,0.305-0.375 [optional].
77
+ Remember that ATCs specify the intervals during which the OBs must be started.
78
+ This code however interprets the phase intervals as the intervals during which the OB must start AND finish. \
79
+ Therefore the ending phase intervals of the ATCs that will be added to the OBs will always be \
80
+ less than the phase intervals specified.\
81
+ """,
82
+ default=None
83
+ )
67
84
  group.add_option("--phase_target", dest="phase_target", help="Comma separated list of target phase, start_before [mins], min_start_before [mins] e.g. 0.01,120,30 [optional]", default=None)
68
- group.add_option("--periods", dest="periods", help=f"Comma separated list of periods, default={default_eso_period} [optional]", default=str(default_eso_period))
85
+ group.add_option("--periods", dest="periods", help="Comma separated list of periods, default={} [optional]".format(default_eso_period), default=str(default_eso_period))
86
+ parser.add_option_group(group)
87
+
88
+ group = OptionGroup(parser, "Do NOT check ATCs for experimental methods.")
89
+ group.add_option("--NO_checkATCs", dest="NO_checkATCs", help="Do NOT check ATCs for experimental methods.", action="store_true", default=False)
69
90
  parser.add_option_group(group)
70
91
 
71
92
  group = OptionGroup(parser, "p2 server selection, options and password management")
@@ -121,6 +142,8 @@ e.g. yyyy-mm-ddThh:mm,yyyy-mm-ddThh:mm_yyyy-mm-ddThh:mm,yyyy-mm-ddThh:mm{_...}
121
142
  self.phase_intervals = options.phase_intervals
122
143
  self.phase_target = options.phase_target
123
144
 
145
+ self.NO_checkATCs = options.NO_checkATCs
146
+
124
147
  self.user = options.user
125
148
  self.env = options.env
126
149
  self.pwstore = options.pwstore
@@ -149,7 +172,7 @@ def get_ob_ATCs(telescope=None, ob_info=None, run_info=None) :
149
172
  if options.ATCs is not None :
150
173
  ATCs=[
151
174
  [p2api_utils.decode_datetime(x.split(',')[0]),p2api_utils.decode_datetime(x.split(',')[1])]
152
- for x in options.ATCs.splt('_')
175
+ for x in options.ATCs.split('_')
153
176
  ]
154
177
 
155
178
  elif options.file is not None :
@@ -214,9 +237,23 @@ def get_ob_ATCs(telescope=None, ob_info=None, run_info=None) :
214
237
  checked_phase_intervals+=[p_int,]
215
238
  else :
216
239
  if ob_exec_time < p_int_in_sec :
217
- logging.warning(f'Phase interval {p_int[0]}--{p_int[1]} == {p_int_in_sec:3.1f}sec is too short to start and finish this OB with execution time of {ob_exec_time}secs.')
240
+ logging.warning(
241
+ 'Phase interval {}--{} == {:3.1f}sec is too short to start and finish this OB with execution time of {}secs.'.format(
242
+ p_int[0],
243
+ p_int[1],
244
+ p_int_in_sec,
245
+ ob_exec_time,
246
+ )
247
+ )
218
248
  if p_int_in_sec > min_ATI_length.to_value(u.second) :
219
- logging.warning(f'Phase interval {p_int[0]}--{p_int[1]} == {p_int_in_sec:3.1f}sec is shorter than the minimum ATI length time of {min_ATI_length.to_value(u.second)}secs.')
249
+ logging.warning(
250
+ 'Phase interval {}--{} == {:3.1f}sec is shorter than the minimum ATI length time of {}secs.'.format(
251
+ p_int[0],
252
+ p_int[1],
253
+ p_int_in_sec,
254
+ min_ATI_length.to_value(u.second),
255
+ )
256
+ )
220
257
 
221
258
  sf_ints=[]
222
259
  for sf_jd in sf_jds :
@@ -241,22 +278,25 @@ def get_ob_ATCs(telescope=None, ob_info=None, run_info=None) :
241
278
  int_spans_nighttime=False
242
279
  for which in ['previous','next',] :
243
280
  sun_set_time=telescope.sun_set_time(Time(sf_int[0], format='jd'), which=which)
244
- sun_rise_time=telescope.sun_rise_time(sun_set_time, which='next')
245
- sssr+=[[sun_set_time,sun_rise_time],]
246
- if (
247
- (sf_int[0] > sun_set_time.jd and sf_int[0] < sun_rise_time.jd-ob_exec_time/24./60./60. )
248
- or
249
- (sf_int[1] > sun_set_time.jd and sf_int[1] < sun_rise_time.jd-ob_exec_time/24./60./60. )
250
- or
251
- (sf_int[0] < sun_set_time.jd and sf_int[1] > sun_rise_time.jd-ob_exec_time/24./60./60. )
252
- ) :
253
- sf_int=[
254
- np.max([sf_int[0],sun_set_time.jd]),
255
- np.min([sf_int[1],sun_rise_time.jd-ob_exec_time/24./60./60.,sun_rise_time.jd-post_ob_exec_time/24./60./60.]),
256
- ]
257
- if sf_int[1] > sf_int[0]+min_start_before/24./60. :
258
- int_spans_nighttime=True
259
- break
281
+ if isinstance(sun_set_time.value,np.float64) :
282
+ sun_rise_time=telescope.sun_rise_time(sun_set_time, which='next')
283
+ sssr+=[[sun_set_time,sun_rise_time],]
284
+ if (
285
+ (sf_int[0] > sun_set_time.jd and sf_int[0] < sun_rise_time.jd-ob_exec_time/24./60./60. )
286
+ or
287
+ (sf_int[1] > sun_set_time.jd and sf_int[1] < sun_rise_time.jd-ob_exec_time/24./60./60. )
288
+ or
289
+ (sf_int[0] < sun_set_time.jd and sf_int[1] > sun_rise_time.jd-ob_exec_time/24./60./60. )
290
+ ) :
291
+ sf_int=[
292
+ np.max([sf_int[0],sun_set_time.jd]),
293
+ np.min([sf_int[1],sun_rise_time.jd-ob_exec_time/24./60./60.,sun_rise_time.jd-post_ob_exec_time/24./60./60.]),
294
+ ]
295
+ if sf_int[1] > sf_int[0]+min_start_before/24./60. :
296
+ int_spans_nighttime=True
297
+ break
298
+ else :
299
+ logging.error(f"telescope.sun_set_time(Time({sf_int[0]}, format='jd'), which={which}) did not return np.float64 ")
260
300
  if (
261
301
  int_spans_nighttime
262
302
  and
@@ -267,11 +307,33 @@ def get_ob_ATCs(telescope=None, ob_info=None, run_info=None) :
267
307
  sf_ints+=[sf_int,]
268
308
  else :
269
309
  if not int_spans_nighttime :
270
- logging.debug(f'Interval does not span any part of the night, original interval = {original_sf_int}, SSSR of previous and next nights {sssr[0][0].jd}--{sssr[0][1].jd} and {sssr[1][0].jd}--{sssr[1][1].jd}')
310
+ logging.debug(
311
+ 'Interval does not span any part of the night, original interval = {}, SSSR of previous and next nights {}--{} and {}--{}'.format(
312
+ original_sf_int,
313
+ sssr[0][0].jd,
314
+ sssr[0][1].jd,
315
+ sssr[1][0].jd,
316
+ sssr[1][1].jd,
317
+ )
318
+ )
271
319
  if ((sf_int[1]-sf_int[0])*24*60.*60. < ob_exec_time) :
272
- logging.debug(f'Checked Interval shorter [{(sf_int[1]-sf_int[0])*24*60.*60.:3.1f}sec] than OB execution time [{ob_exec_time:3.1f}sec], original interval = {original_sf_int}, checked interval = {sf_int}')
320
+ logging.debug(
321
+ 'Checked Interval shorter [{:3.1f}sec] than OB execution time [{:3.1f}sec], original interval = {}, checked interval = {}'.format(
322
+ (sf_int[1]-sf_int[0])*24*60.*60.,
323
+ ob_exec_time,
324
+ original_sf_int,
325
+ sf_int,
326
+ )
327
+ )
273
328
  if ((sf_int[1]-sf_int[0])*24*60.*60. < min_ATI_length.to_value(u.second)) :
274
- logging.debug(f'Checked Interval shorter [{(sf_int[1]-sf_int[0])*24*60.*60.:3.1f}sec] than minimum ATI length time [{min_ATI_length.to_value(u.second):3.1f}sec], original interval = {original_sf_int}, checked interval = {sf_int}')
329
+ logging.debug(
330
+ 'Checked Interval shorter [{:3.1f}sec] than minimum ATI length time [{:3.1f}sec], original interval = {}, checked interval = {}'.format(
331
+ (sf_int[1]-sf_int[0])*24*60.*60.,
332
+ min_ATI_length.to_value(u.second),
333
+ original_sf_int,
334
+ sf_int,
335
+ )
336
+ )
275
337
  pass
276
338
  ATCs=[Time(sf_int, format='jd') for sf_int in sf_ints]
277
339
  check_ATCs=True
@@ -290,8 +352,18 @@ def get_ob_ATCs(telescope=None, ob_info=None, run_info=None) :
290
352
  if check_ATCs :
291
353
  phase_range=''
292
354
  if options.ephem is not None :
293
- phase_range=f" [Phases: {(((t[0]-Time(T0,format='jd'))/P).to_value(u.day)%1):5.3f} -- {(((t[1]-Time(T0,format='jd'))/P).to_value(u.day)%1):5.3f}]"
294
- print(f"{i+1:3d} {ob_ATCs[-1]['from']} -- {ob_ATCs[-1]['to']} [duration={((t[1]-t[0]).to_datetime())}]{phase_range}")
355
+ phase_range=" [Phases: {:5.3f} -- {:5.3f}]".format(
356
+ (((t[0]-Time(T0,format='jd'))/P).to_value(u.day)%1),
357
+ (((t[1]-Time(T0,format='jd'))/P).to_value(u.day)%1),
358
+ )
359
+ print("{:3d} {} -- {} [OB_exectime={}, Int.duration={}]{}".format(
360
+ i+1,
361
+ ob_ATCs[-1]['from'],
362
+ ob_ATCs[-1]['to'],
363
+ datetime.timedelta(seconds=ob_exec_time),
364
+ ((t[1]-t[0]).to_datetime()),
365
+ phase_range,
366
+ ))
295
367
  if check_ATCs :
296
368
  '''
297
369
  logging.warning("****************************************************************************************")
@@ -306,14 +378,19 @@ def get_ob_ATCs(telescope=None, ob_info=None, run_info=None) :
306
378
  print("****************************************************************************************")
307
379
  print("Intervals via Orbital Ephemeris functionality is EXPERIMENTAL")
308
380
  print("Please check the above intervals carefully and only continue if you are sure they are what YOU require.")
309
- print("YOU, and YOU ALONE are responsible for the accuracy of these intervals.")
310
- yorn = input("Continue [y/N] ")
311
- if yorn.lower() not in ['y',] :
312
- print("Please contact ESO User Support via a ticket at https://support.eso.org/tickets")
313
- print("to report/discuss the errors/problems in the above calculations.")
314
- print("Please include in the description the EXACT command line used to run the script.")
315
- sys.exit(0)
316
- #raise Exception(f"Aborted.")
381
+ print("Remember that ATCs specify the intervals during which the OBs must be started.")
382
+ print("While this code interprets the phase intervals as the intervals during which the OB must start AND finish.")
383
+ print("Therefore the ending phase intervals of the ATCs listed above will always be")
384
+ print("less than the phase intervals specified.")
385
+ print("Ultimately YOU, and YOU ALONE, are responsible for the accuracy of these intervals.")
386
+ if not options.NO_checkATCs :
387
+ yorn = input("Continue [y/N] ")
388
+ if yorn.lower() not in ['y',] :
389
+ print("Please contact ESO User Support via a ticket at https://support.eso.org/tickets")
390
+ print("to report/discuss the errors/problems in the above calculations.")
391
+ print("Please include in the description the EXACT command line used to run the script.")
392
+ sys.exit(0)
393
+ #raise Exception("Aborted.")
317
394
  return ob_ATCs
318
395
  # ------------------------------------------------------------------------------
319
396
  def oneOB( api, obId ) :
@@ -0,0 +1,149 @@
1
+ # -*- coding: utf-8 -*-
2
+ import datetime
3
+ import copy
4
+
5
+ # ---------------------------------------------------------------------------------------
6
+ ## From https://stackoverflow.com/questions/51913210/python-script-with-timezone-fails-when-back-ported-to-python-2-7
7
+ ZERO = datetime.timedelta(0)
8
+ HOUR = datetime.timedelta(hours=1)
9
+
10
+ class UTC(datetime.tzinfo):
11
+ """UTC"""
12
+
13
+ def utcoffset(self, dt):
14
+ return ZERO
15
+
16
+ def tzname(self, dt):
17
+ return "UTC"
18
+
19
+ def dst(self, dt):
20
+ return ZERO
21
+
22
+ tz_utc=UTC()
23
+ if hasattr(datetime,'timezone') :
24
+ if hasattr(datetime.timezone,'utc') :
25
+ tz_utc=datetime.timezone.utc
26
+ # ---------------------------------------------------------------------------------------
27
+ # ---------------------------------------------------------------------------------------
28
+ def get_ESO_period( d ):
29
+ """
30
+ Return the (int) ESO period for a specified datetime.date or datetime.datetime
31
+ If d is naive (no timezone), UTC is assumed
32
+ """
33
+ ## ToDo: Update this method when we go to yearly cycle!
34
+ ## 2024-07: currently planned for P117, with P116 lasting 7 months...
35
+ # 113 2024-04 -- 2024-09
36
+ # 114 2024-10 -- 2025-03
37
+ # 115 2025-04 -- 2026-09
38
+ # 116 2025-10 -- 2026-04
39
+ # 117 2026-05 -- 2027-04
40
+ # 118 2027-05 -- 2028-04
41
+ # ...
42
+ if isinstance(d,datetime.date) :
43
+ d=datetime.datetime(
44
+ year=d.year,
45
+ month=d.month,
46
+ day=d.day,
47
+ hour=0,
48
+ minute=0,
49
+ second=0,
50
+ microsecond=0,
51
+ tzinfo=tz_utc,
52
+ )
53
+ if d.tzinfo is None :
54
+ d=d.replace(tzinfo=tz_utc)
55
+ if d < datetime.datetime(2025,10,1,0,0,tzinfo=tz_utc) :
56
+ # P < 116...
57
+ return ((d.year-2012)+44)*2+int(float(d.month+2)/6.)
58
+ elif d > datetime.datetime(2026,5,1,0,0,tzinfo=tz_utc) :
59
+ # P > 116...
60
+ return ((d.year-2026)+116)+int(float(d.month+7)/12.)
61
+ elif d > datetime.datetime(2026,4,1,0,0,tzinfo=tz_utc) :
62
+ ## Special case for 7month long P116
63
+ return ((d.year-2012)+44)*2+int(float(d.month+2)/7.)
64
+ return ((d.year-2012)+44)*2+int(float(d.month+2)/6.)
65
+ # ---------------------------------------------------------------------------------------
66
+ def current_ESO_period( days_from_now=0, dt=None ):
67
+ d=datetime.datetime.now(tz_utc) + datetime.timedelta(days=days_from_now)
68
+ return get_ESO_period(d)
69
+ # ---------------------------------------------------------------------------------------
70
+ def ESO_period_datetime_start( eso_period=current_ESO_period() ):
71
+ ## ToDo: Update this method when we go to yearly cycle!
72
+ ## 2024-07: currently planned for P117, with P116 lasting 7 months...
73
+ ## i.e.
74
+ ## P115 starts
75
+ if eso_period < 116 :
76
+ y=2024+(eso_period-113)//2
77
+ m=4+6*((eso_period-113)%2)
78
+ elif eso_period > 116 :
79
+ y=2026+(eso_period-117)
80
+ m=5
81
+ else :
82
+ y=2025
83
+ m=10
84
+ return datetime.datetime(y,m,1,0,0,0,0,tzinfo=tz_utc)
85
+ # ---------------------------------------------------------------------------------------
86
+ def ESO_period_datetime_end( eso_period=current_ESO_period() ):
87
+ return ESO_period_datetime_start((eso_period or current_ESO_period())+1)-datetime.timedelta(days=1)
88
+ # ---------------------------------------------------------------------------------------
89
+ def ESO_period_date_start( eso_period=current_ESO_period() ):
90
+ return ESO_period_datetime_start( eso_period ).date()
91
+ # ---------------------------------------------------------------------------------------
92
+ def ESO_period_date_end( eso_period=current_ESO_period() ):
93
+ return ESO_period_datetime_end( eso_period ).date()
94
+ # ---------------------------------------------------------------------------------------
95
+ # -----------------------------------------------------------------------------
96
+ if __name__ == '__main__' :
97
+ ## ToDo: These tests, should be moved to proper tests...
98
+
99
+ ## Testing get_ESO_period
100
+ ## verify input date type is not changed
101
+ d=datetime.date(2024,4,1)
102
+ get_ESO_period(d)
103
+ assert isinstance(d,datetime.date)
104
+
105
+ # verify input datetime tzinfo is not modified
106
+ d=datetime.datetime(2024,4,1,0,0)
107
+ get_ESO_period(d)
108
+ assert d.tzinfo is None
109
+
110
+ # P113
111
+ assert get_ESO_period(datetime.date(2024,4,1)) == 113
112
+ assert get_ESO_period(datetime.datetime(2024,4,1,0,0)) == 113
113
+ assert get_ESO_period(datetime.datetime(2024,9,30,23,59,59)) == 113
114
+ # P114
115
+ assert get_ESO_period(datetime.datetime(2024,10,1,0,0)) == 114
116
+ assert get_ESO_period(datetime.datetime(2025,3,31,23,59,59)) == 114
117
+ # P115
118
+ assert get_ESO_period(datetime.datetime(2025,4,1,0,0)) == 115
119
+ assert get_ESO_period(datetime.datetime(2025,9,30,23,59,59)) == 115
120
+ # P116
121
+ assert get_ESO_period(datetime.datetime(2025,10,1,0,0)) == 116
122
+ assert get_ESO_period(datetime.datetime(2026,3,31,23,59,59)) == 116
123
+ assert get_ESO_period(datetime.datetime(2026,4,30,23,59,59)) == 116
124
+ # P117
125
+ assert get_ESO_period(datetime.datetime(2026,5,1,0,0)) == 117
126
+ assert get_ESO_period(datetime.datetime(2027,4,30,23,59,59)) == 117
127
+ # P118
128
+ assert get_ESO_period(datetime.datetime(2027,5,1,0,0)) == 118
129
+ assert get_ESO_period(datetime.datetime(2028,4,30,23,59,59)) == 118
130
+
131
+ ## testing ESO_period_date_start() & ESO_period_date_end()
132
+ # P113
133
+ assert ESO_period_date_start(113) == datetime.date(2024,4,1)
134
+ assert ESO_period_date_end(113) == datetime.date(2024,9,30)
135
+ # P114
136
+ assert ESO_period_date_start(114) == datetime.date(2024,10,1)
137
+ assert ESO_period_date_end(114) == datetime.date(2025,3,31)
138
+ # P115
139
+ assert ESO_period_date_start(115) == datetime.date(2025,4,1)
140
+ assert ESO_period_date_end(115) == datetime.date(2025,9,30)
141
+ # P116
142
+ assert ESO_period_date_start(116) == datetime.date(2025,10,1)
143
+ assert ESO_period_date_end(116) == datetime.date(2026,4,30)
144
+ # P117
145
+ assert ESO_period_date_start(117) == datetime.date(2026,5,1)
146
+ assert ESO_period_date_end(117) == datetime.date(2027,4,30)
147
+ # P118
148
+ assert ESO_period_date_start(118) == datetime.date(2027,5,1)
149
+ assert ESO_period_date_end(118) == datetime.date(2028,4,30)
@@ -1,9 +1,12 @@
1
1
  #! /usr/bin/env python
2
+ # -*- coding: utf-8 -*-
2
3
 
3
4
  # $Id: generate_finding_charts.py 267033 2021-09-16 11:08:57Z jpritcha $
4
5
  from __future__ import print_function
5
6
 
6
7
  _VERSION_ = "$Revision: 267033 $"
8
+ from ..p2api import __version__
9
+ _VERSION_ = __version__
7
10
 
8
11
  import sys # interaction with Python interpreter
9
12
  from optparse import OptionParser # for parsing command line arguments
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  import datetime
2
3
  import logging
3
4
  import p2api
@@ -7,44 +8,50 @@ import getpass
7
8
  import keyring
8
9
  import re
9
10
 
10
- import astropy.units as u
11
- from astropy.coordinates import EarthLocation
11
+ from p2api.utils.eso_period import *
12
12
 
13
- # The GPS coordinates of the UTs
14
- # https://www.eso.org/sci/facilities/paranal/astroclimate/site.html
15
- UT1_loc = EarthLocation.from_geodetic('-70d24m18.27s', '-24d37m39.44s', (2635.43+13.044)*u.m)
16
- UT2_loc = EarthLocation.from_geodetic('-70d24m17.39s', '-24d37m37.80s', (2635.43+13.044)*u.m)
17
- UT3_loc = EarthLocation.from_geodetic('-70d24m16.32s', '-24d37m36.64s', (2635.43+13.044)*u.m)
18
- UT4_loc = EarthLocation.from_geodetic('-70d24m14.25s', '-24d37m37.36s', (2635.43+13.044)*u.m)
19
- VST_loc = EarthLocation.from_geodetic('-70d24m14.27s', '-24d37m34.79s', (2635.43+4.5399)*u.m)
20
- VISTA_loc = EarthLocation.from_geodetic('-70d23m51.36s', '-24d36m56.52s', (2530.)*u.m)
13
+ try:
14
+ import astropy.units as u
15
+ from astropy.coordinates import EarthLocation
16
+ # The GPS coordinates of the UTs
17
+ # https://www.eso.org/sci/facilities/paranal/astroclimate/site.html
18
+ UT1_loc = EarthLocation.from_geodetic('-70d24m18.27s', '-24d37m39.44s', (2635.43+13.044)*u.m)
19
+ UT2_loc = EarthLocation.from_geodetic('-70d24m17.39s', '-24d37m37.80s', (2635.43+13.044)*u.m)
20
+ UT3_loc = EarthLocation.from_geodetic('-70d24m16.32s', '-24d37m36.64s', (2635.43+13.044)*u.m)
21
+ UT4_loc = EarthLocation.from_geodetic('-70d24m14.25s', '-24d37m37.36s', (2635.43+13.044)*u.m)
22
+ VST_loc = EarthLocation.from_geodetic('-70d24m14.27s', '-24d37m34.79s', (2635.43+4.5399)*u.m)
23
+ VISTA_loc = EarthLocation.from_geodetic('-70d23m51.36s', '-24d36m56.52s', (2530.)*u.m)
21
24
 
22
- # https://www.eso.org/sci/facilities/lasilla/telescopes/3p6/overview.html
23
- ## The telescope is at a geographical location of:
24
- ## 70° 43' 54.1" W -29° 15' 39.5" S (WGS84), 2400 metres above sea level
25
- LS3p6_loc = EarthLocation.from_geodetic('-70d43m54.1s', '-29d15m39.5s', (2400.)*u.m)
25
+ # https://www.eso.org/sci/facilities/lasilla/telescopes/3p6/overview.html
26
+ ## The telescope is at a geographical location of:
27
+ ## 70° 43' 54.1" W -29° 15' 39.5" S (WGS84), 2400 metres above sea level
28
+ LS3p6_loc = EarthLocation.from_geodetic('-70d43m54.1s', '-29d15m39.5s', (2400.)*u.m)
26
29
 
27
- # https://www.eso.org/sci/facilities/lasilla/telescopes/ntt/overview.html
28
- ## 70° 44' 01.5" W -29° 15' 32.1" S (WGS84), 2375m
29
- LSntt_loc = EarthLocation.from_geodetic('-70d44m01.5s', '-29d15m32.1s', (2375.)*u.m)
30
+ # https://www.eso.org/sci/facilities/lasilla/telescopes/ntt/overview.html
31
+ ## 70° 44' 01.5" W -29° 15' 32.1" S (WGS84), 2375m
32
+ LSntt_loc = EarthLocation.from_geodetic('-70d44m01.5s', '-29d15m32.1s', (2375.)*u.m)
30
33
 
31
- # https://www.eso.org/sci/facilities/lasilla/telescopes/national/2p2.html
32
- # 2p2 70°44'4"543 W 29°15'15"433 S
33
- LS2p2_loc = EarthLocation.from_geodetic('-70d44m04.543s', '-29d15m15.433s', (2335.)*u.m)
34
-
35
- ## All together as a dictionary:
36
- telescope_locations={
37
- 'UT1': UT1_loc,
38
- 'UT2': UT2_loc,
39
- 'UT3': UT3_loc,
40
- 'UT4': UT4_loc,
41
- 'VST': VST_loc,
42
- 'VISTA': VISTA_loc,
43
- 'LS3p6': LS3p6_loc,
44
- 'LSntt': LSntt_loc,
45
- 'LS2p2': LS2p2_loc,
46
- }
34
+ # https://www.eso.org/sci/facilities/lasilla/telescopes/national/2p2.html
35
+ # 2p2 70°44'4"543 W 29°15'15"433 S
36
+ LS2p2_loc = EarthLocation.from_geodetic('-70d44m04.543s', '-29d15m15.433s', (2335.)*u.m)
47
37
 
38
+ ## All together as a dictionary:
39
+ telescope_locations={
40
+ 'UT1': UT1_loc,
41
+ 'UT2': UT2_loc,
42
+ 'UT3': UT3_loc,
43
+ 'UT4': UT4_loc,
44
+ 'VST': VST_loc,
45
+ 'VISTA': VISTA_loc,
46
+ 'LS3p6': LS3p6_loc,
47
+ 'LSntt': LSntt_loc,
48
+ 'LS2p2': LS2p2_loc,
49
+ }
50
+ except:
51
+ pass
52
+ '''
53
+ ## ToDo: make usd_config module public...
54
+ ## use local copy (for now) of usd_config.eso_period
48
55
  # ---------------------------------------------------------------------------------------
49
56
  def current_ESO_period():
50
57
  d=datetime.datetime.utcnow()
@@ -59,7 +66,7 @@ def ESO_period_start_end_dates(P):
59
66
  md1=ESO_period_first_last_dates[P%2][0]
60
67
  y2=1967+(P+2)//2
61
68
  md2=ESO_period_first_last_dates[P%2][1]
62
- return [f"{y1}{md1}",f"{y2}{md2}"]
69
+ return ["{}{}".format(y1,md1),"{y2}{md2}.format(y2,md2)"]
63
70
  # ---------------------------------------------------------------------------------------
64
71
  def ESO_period_start_end_datetimes(P):
65
72
  ESO_period_first_last_dates=[
@@ -70,7 +77,20 @@ def ESO_period_start_end_datetimes(P):
70
77
  md1=ESO_period_first_last_dates[P%2][0]
71
78
  y2=1967+(P+2)//2
72
79
  md2=ESO_period_first_last_dates[P%2][1]
73
- return [f"{y1}{md1}",f"{y2}{md2}"]
80
+ return ["{}{}".format(y1,md1),"{y2}{md2}.format(y2,md2)"]
81
+ '''
82
+ # ---------------------------------------------------------------------------------------
83
+ def ESO_period_start_end_dates(P):
84
+ return [
85
+ ESO_period_date_start(P),
86
+ ESO_period_date_end(P),
87
+ ]
88
+ # ---------------------------------------------------------------------------------------
89
+ def ESO_period_start_end_datetimes(P):
90
+ return [
91
+ ESO_period_datetime_start(P),
92
+ ESO_period_datetime_end(P),
93
+ ]
74
94
  # ---------------------------------------------------------------------------------------
75
95
  def get_attrs(klass):
76
96
  return [k for k in klass.__dict__.keys()
@@ -280,8 +300,8 @@ def decode_datetime( d ) :
280
300
  d_tz=d
281
301
  for tz in tz_info :
282
302
  d_tz=re.sub(
283
- f'{tz}',
284
- f'{tz_info[tz]}',
303
+ '{}.format(tz)',
304
+ '{}.format(tz_info[tz])',
285
305
  d_tz,
286
306
  )
287
307
  for s in [d_tz,d] :
@@ -300,5 +320,5 @@ def decode_datetime( d ) :
300
320
  return dt
301
321
  except :
302
322
  pass
303
- raise Exception(f"Could not decode date '{d}'.")
323
+ raise Exception("Could not decode date '{}'.".format(d))
304
324
  # ---------------------------------------------------------------------------------------
@@ -36,14 +36,14 @@ classifiers = [
36
36
  "Programming Language :: Python :: 3.12",
37
37
  ]
38
38
  dependencies = [
39
- "astroplan",
40
- "astropy",
39
+ #"astroplan",
40
+ #"astropy",
41
41
  "keyring",
42
42
  "requests",
43
43
  ]
44
44
 
45
45
  [project.scripts]
46
- p2api_add_absolute_time_intervals = "p2api.utils.add_absolute_time_intervals:main"
46
+ #p2api_add_absolute_time_intervals = "p2api.utils.add_absolute_time_intervals:main"
47
47
  p2api_generate_finding_charts = "p2api.utils.generate_finding_charts:main"
48
48
 
49
49
  [project.urls]
@@ -55,4 +55,6 @@ path = "p2api/__about__.py"
55
55
  [tool.hatch.build.targets.sdist]
56
56
  include = [
57
57
  "/p2api",
58
+ "/setup.py",
59
+ "/setup.cfg",
58
60
  ]
p2api-1.0.8/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
p2api-1.0.8/setup.py ADDED
@@ -0,0 +1,127 @@
1
+ from setuptools import setup
2
+ import os
3
+ import io
4
+
5
+ '''
6
+ Restored setup.py & setup.cfg following instructions at:
7
+ Follow instructions at https://stackoverflow.com/questions/42287533/restore-deleted-file-with-history-in-git
8
+
9
+ git config --get remote.origin.url
10
+ git checkout a53fb714b8b48cd0112ae175a179e4a2c6859de1 -b restore_setuptools_build_support
11
+ git mv setup.py setup_1.py
12
+ git mv setup.cfg setup_1.cfg
13
+ git commit -m "Move file (1)"
14
+ SAVED=`git rev-parse HEAD`
15
+ git reset --hard "HEAD^"
16
+ git mv setup.py setup_2.py
17
+ git mv setup.cfg setup_2.cfg
18
+ git commit -m "Move file (2)"
19
+ git merge $SAVED
20
+ git commit -a -n
21
+ git checkout master
22
+ git merge restore_setuptools_build_support
23
+ git commit -a -n
24
+ git rm setup_1.py setup_1.cfg
25
+ git mv setup_2.py setup.py
26
+ git mv setup_2.cfg setup.cfg
27
+ git commit -m "recovery finished"
28
+ '''
29
+
30
+
31
+ # ----------------------------------------------------
32
+ def read(*paths, **kwargs):
33
+ """Read the contents of a text file safely.
34
+ >>> read("p2api", "VERSION")
35
+ '0.1.0'
36
+ >>> read("README.md")
37
+ ...
38
+ """
39
+ content = ""
40
+ with io.open(
41
+ os.path.join(os.path.dirname(__file__), *paths),
42
+ encoding=kwargs.get("encoding", "utf8"),
43
+ ) as open_file:
44
+ content = open_file.read().strip()
45
+ return content
46
+ # ----------------------------------------------------
47
+ from p2api import __about__
48
+ setup(
49
+ name='p2api',
50
+ #version=read('p2api', 'VERSION'),
51
+ version=__about__.__version__,
52
+ description='Binding for the ESO phase 2 programmatic API',
53
+ long_description=read('README.md'),
54
+ long_description_content_type='text/markdown',
55
+ url='https://www.eso.org/copdemo/apidoc/index.html',
56
+ author='Thomas Bierwirth',
57
+ author_email='thomas.bierwirth@eso.org',
58
+
59
+ packages=['p2api', 'p2api/utils',],
60
+ include_package_data=True,
61
+ entry_points={
62
+ 'console_scripts' : [
63
+ #'p2api_add_absolute_time_intervals = p2api.utils.add_absolute_time_intervals:main',
64
+ 'p2api_generate_finding_charts = p2api.utils.generate_finding_charts:main',
65
+ ],
66
+ },
67
+
68
+ # Classifiers help users find your project by categorizing it.
69
+ #
70
+ # For a list of valid classifiers, see
71
+ # https://pypi.python.org/pypi?%3Aaction=list_classifiers
72
+ classifiers=[ # Optional
73
+ # How mature is this project? Common values are
74
+ # 3 - Alpha
75
+ # 4 - Beta
76
+ # 5 - Production/Stable
77
+ 'Development Status :: 5 - Production/Stable',
78
+
79
+ # Indicate who your project is intended for
80
+ 'Intended Audience :: Developers',
81
+
82
+ # Pick your license as you wish
83
+ 'License :: OSI Approved :: MIT License',
84
+
85
+ # Specify the Python versions you support here. In particular, ensure
86
+ # that you indicate whether you support Python 2, Python 3 or both.
87
+ 'Programming Language :: Python :: 2',
88
+ 'Programming Language :: Python :: 2.7',
89
+ 'Programming Language :: Python :: 3',
90
+ 'Programming Language :: Python :: 3.4',
91
+ 'Programming Language :: Python :: 3.5',
92
+ 'Programming Language :: Python :: 3.6',
93
+ 'Programming Language :: Python :: 3.7',
94
+ 'Programming Language :: Python :: 3.8',
95
+ 'Programming Language :: Python :: 3.9',
96
+ 'Programming Language :: Python :: 3.10',
97
+ ],
98
+
99
+ # This field adds keywords for your project which will appear on the
100
+ # project page. What does your project relate to?
101
+ #
102
+ # Note that this is a string of words separated by whitespace, not a list.
103
+ keywords='ESO Phase2 Observation Preparation Programmatic API',
104
+
105
+ # You can just specify package directories manually here if your project is
106
+ # simple. Or you can use find_packages().
107
+ #
108
+ # Alternatively, if you just want to distribute a single Python file, use
109
+ # the `py_modules` argument instead as follows, which will expect a file
110
+ # called `my_module.py` to exist:
111
+ #
112
+ py_modules=["p2api"],
113
+
114
+ # This field lists other packages that your project depends on to run.
115
+ # Any package you put here will be installed by pip when your project is
116
+ # installed, so they must be valid existing projects.
117
+ #
118
+ # For an analysis of "install_requires" vs pip's requirements files see:
119
+ # https://packaging.python.org/en/latest/requirements.html
120
+ install_requires=[
121
+ 'requests',
122
+ 'keyring',
123
+ #'astropy', ## needed for add_absolute_time_intervals
124
+ #'astroplan', ## needed for add_absolute_time_intervals
125
+ ],
126
+ license='MIT'
127
+ )
@@ -1 +0,0 @@
1
- __version__ = "1.0.6"
File without changes
File without changes
File without changes