a2p2 0.2.14__py3-none-any.whl → 0.7.4__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.
Files changed (47) hide show
  1. a2p2/__main__.py +40 -1
  2. a2p2/chara/facility.py +54 -4
  3. a2p2/chara/gui.py +31 -5
  4. a2p2/client.py +158 -31
  5. a2p2/facility.py +14 -1
  6. a2p2/gui.py +46 -12
  7. a2p2/instrument.py +3 -0
  8. a2p2/jmmc/__init__.py +7 -0
  9. a2p2/jmmc/catalogs.py +129 -0
  10. a2p2/jmmc/generated_models.py +191 -0
  11. a2p2/jmmc/models.py +104 -0
  12. a2p2/jmmc/services.py +16 -0
  13. a2p2/jmmc/utils.py +130 -0
  14. a2p2/jmmc/webservices.py +48 -0
  15. a2p2/ob.py +98 -9
  16. a2p2/samp.py +20 -0
  17. a2p2/version.py +210 -131
  18. a2p2/vlti/conf/GRAVITY_ditTable.json +21 -19
  19. a2p2/vlti/conf/GRAVITY_rangeTable.json +200 -28
  20. a2p2/vlti/conf/MATISSE_rangeTable.json +58 -22
  21. a2p2/vlti/conf/PIONIER_ditTable.json +1 -1
  22. a2p2/vlti/conf/PIONIER_rangeTable.json +16 -18
  23. a2p2/vlti/facility.py +160 -43
  24. a2p2/vlti/gravity.py +243 -311
  25. a2p2/vlti/gui.py +165 -39
  26. a2p2/vlti/instrument.py +266 -49
  27. a2p2/vlti/matisse.py +61 -147
  28. a2p2/vlti/pionier.py +34 -157
  29. {a2p2-0.2.14.dist-info → a2p2-0.7.4.dist-info}/METADATA +34 -20
  30. a2p2-0.7.4.dist-info/RECORD +39 -0
  31. {a2p2-0.2.14.dist-info → a2p2-0.7.4.dist-info}/WHEEL +1 -1
  32. {a2p2-0.2.14.dist-info → a2p2-0.7.4.dist-info}/entry_points.txt +0 -1
  33. a2p2/vlti/confP104/GRAVITY_ditTable.json +0 -122
  34. a2p2/vlti/confP104/GRAVITY_rangeTable.json +0 -202
  35. a2p2/vlti/confP104/MATISSE_ditTable.json +0 -2
  36. a2p2/vlti/confP104/MATISSE_rangeTable.json +0 -202
  37. a2p2/vlti/confP104/PIONIER_ditTable.json +0 -77
  38. a2p2/vlti/confP104/PIONIER_rangeTable.json +0 -118
  39. a2p2/vlti/confP105/GRAVITY_ditTable.json +0 -37
  40. a2p2/vlti/confP105/GRAVITY_rangeTable.json +0 -42
  41. a2p2/vlti/confP105/MATISSE_ditTable.json +0 -2
  42. a2p2/vlti/confP105/MATISSE_rangeTable.json +0 -44
  43. a2p2/vlti/confP105/PIONIER_ditTable.json +0 -25
  44. a2p2/vlti/confP105/PIONIER_rangeTable.json +0 -38
  45. a2p2-0.2.14.dist-info/RECORD +0 -44
  46. {a2p2-0.2.14.dist-info → a2p2-0.7.4.dist-info}/LICENSE +0 -0
  47. {a2p2-0.2.14.dist-info → a2p2-0.7.4.dist-info}/top_level.txt +0 -0
a2p2/vlti/facility.py CHANGED
@@ -3,7 +3,12 @@
3
3
  __all__ = []
4
4
 
5
5
  import os
6
+ from tkinter.constants import TRUE
6
7
  import traceback
8
+ import logging
9
+ import re
10
+
11
+ import p2api
7
12
 
8
13
  from a2p2.facility import Facility
9
14
  from a2p2.vlti.gui import VltiUI
@@ -48,6 +53,7 @@ On your first valid VLTI's OB, A2p2 will ask for your ESO User Portal credential
48
53
  """
49
54
  HELPTEXT += "Config files loaded from " + CONFDIR
50
55
 
56
+ logger = logging.getLogger(__name__)
51
57
 
52
58
  class VltiFacility(Facility):
53
59
 
@@ -77,53 +83,142 @@ class VltiFacility(Facility):
77
83
  self.username = None
78
84
  self.api = None
79
85
 
86
+ # store ob to insert after container selection if not done previously
87
+ self.ob_to_confirm=[]
88
+ self.ob_to_submit=[]
89
+
90
+
80
91
  def getName():
81
92
  return "VLTI"
82
93
 
83
94
  def autologin(self):
95
+ self.ui.addToLog("\nAutologin into P2 API please wait...\n")
84
96
  self.ui.loginFrame.on_loginbutton_clicked()
85
97
  self.a2p2client.ui.showFacilityUI(self.ui)
86
98
  self.ui.showTreeFrame()
87
99
 
88
100
  def processOB(self, ob):
101
+ # process last accepted OB if ob is None
102
+ if not ob:
103
+ self.processLastAcceptedOB()
104
+ return
105
+
89
106
  # give focus on last updated UI
90
107
  self.a2p2client.ui.showFacilityUI(self.ui)
91
108
  # show ob dict for debug
92
109
  self.ui.addToLog(str(ob), False)
93
110
 
94
111
  # OB is checked and submitted by instrument
112
+ period = ob.getPeriod()
113
+ self.ui.addToLog(f"Request received for OB creation for P{period} - please press Submit or Abort button")
114
+
115
+ # always stores OB and pop them if everything is ok or later selecting containers in the tree
116
+ self.pushOB(ob)
117
+ self.tryLastOB()
118
+
119
+ def tryLastOB(self):
120
+ self.showOBConfirmationButtons()
121
+ # stop if no ob has to be handled
122
+ if not self.hasOB():
123
+ return
124
+
125
+ ob = self.ob_to_confirm[-1]
126
+ # run checkOB which may raise some error before connection request
127
+ # TODO we should test much more because lot of stuff still are beeing processed on live ob creations
128
+
129
+ period = ob.getPeriod()
95
130
  instrument = self.getInstrument(ob.instrumentConfiguration.name)
96
- try:
97
- # run checkOB which may raise some error before connection request
98
- instrument.checkOB(ob)
99
-
100
- insname = instrument.getShortName()
101
-
102
- # performs operation
103
- if not self.isConnected():
104
- self.ui.showLoginFrame(ob)
105
- elif not self.isReadyToSubmit():
106
- # self.a2p2client.ui.addToLog("Receive OB for
107
- # '"+ob.instrumentConfiguration.name+"'")
108
- self.ui.addToLog(
109
- "Please select a folder (not a concatenation) in the above list. OBs are not shown")
110
- elif insname.lower() != self.containerInfo.getInstrument().lower():
111
- self.ui.ShowErrorMessage("Aborting: container's instrument '%s' in not applicable for received OB's one '%s'." %(self.containerInfo.getInstrument(),insname))
112
- else:
113
- self.ui.addToLog(
114
- "everything ready! Request OB creation inside selected container ")
115
- instrument.submitOB(ob, self.containerInfo)
116
- self.refreshTree()
131
+ insname = instrument.getShortName()
132
+
133
+ # performs operation
134
+ if not self.isConnected():
135
+ self.ui.showLoginFrame(ob)
136
+ elif not self.isReadyToSubmit(ob):
137
+ # self.a2p2client.ui.addToLog("Receive OB for
138
+ # '"+ob.instrumentConfiguration.name+"'")
139
+ self.ui.addToLog(
140
+ f"Selected folder must not be a concatenation. please choose another container for '{insname}' P'{period}'.")
141
+ elif insname.lower() != self.containerInfo.getInstrument().lower():
142
+ self.ui.addToLog(
143
+ f"'{self.containerInfo.getInstrument()}' selection in not applicable for received OB. Please choose another one for '{insname}' P'{period}'.")
144
+ elif period != int(self.containerInfo.getIpVersion()):
145
+ self.ui.addToLog(
146
+ f"Container's IpVersion '{int(self.containerInfo.getIpVersion())}' is not applicable for received OB's one '{period}', please select another '{insname}' container or change it in Aspro2.")
147
+ else:
148
+ self.showOBConfirmationButtons(ob, insname=="GRAVITY")
149
+
150
+ def showOBConfirmationButtons(self, ob=None, showAcqButtons=False):
151
+ self.ui.showOBConfirmationButtons(ob, showAcqButtons)
152
+
153
+ def isReadyToSubmit(self, ob):
154
+ return self.api and self.containerInfo.isOk(ob)
155
+
156
+ def isConnected(self):
157
+ return self.connected
158
+
159
+ def setConnected(self, flag):
160
+ self.connected = flag
161
+
162
+ def pushOB(self,ob):
163
+ self.ob_to_confirm.append(ob)
164
+
165
+ def hasOB(self):
166
+ return len(self.ob_to_confirm)>0
167
+
168
+ def popOB(self, ignore=False):
169
+ """ Called as last step : ob is for the selected container and User click on submit!
170
+ If ignore is set to True, last ob is simply removed else it is forwarded to P2 and removed from stack. """
171
+
172
+ if not self.hasOB():
173
+ return
174
+
175
+ # pop last OB
176
+ o = self.ob_to_confirm.pop()
177
+ self.showOBConfirmationButtons()
117
178
 
118
- # TODO add P2Error handling P2Error(r.status_code, method, url,
119
- # r.json()['error'])
179
+ if ignore:
180
+ self.ui.addToLog("Last received OB has been aborted")
181
+ return
182
+ else:
183
+ self.ob_to_submit.append(o)
184
+
185
+ def processLastAcceptedOB(self):
186
+ if len(self.ob_to_submit)==0:
187
+ return
188
+
189
+ o=self.ob_to_submit.pop()
190
+ try:
191
+ instrument = self.getInstrument(o.instrumentConfiguration.name)
192
+ instrument.checkOB(o)
193
+ # check for warnings and abort if requested by user
194
+ # this implementation should be more detailled so we can have various VERSION associated to various warning
195
+ if len(instrument.warnings)>0:
196
+ linesep="\n - "
197
+ header=""
198
+ try:
199
+ # some ditTable may have a VERSION entry some not...
200
+ version=instrument.getDitTable()["VERSION"]
201
+ header= f"According to the template manual {version} :\n \n - \n"
202
+ except:
203
+ pass
204
+ answer = self.ui.AskYesNoMessage(f"{header} {linesep.join(instrument.warnings)}\n\nClick \"Yes\" to proceed \"No\" to abort the submission")
205
+ instrument.warnings.clear()
206
+ if answer == False:
207
+ self.ui.addToLog("Submission has been marked to be aborted - do not proceed")
208
+ return
209
+
210
+ self.ui.addToLog("Everything ready! Request OB creation inside selected container")
211
+ instrument.submitOB(o, self.containerInfo)
212
+
213
+ # TODO add P2Error handling P2Error(r.status_code, method, url,
214
+ # r.json()['error'])
120
215
  except ValueError as e:
121
216
  traceback.print_exc()
122
217
  trace = traceback.format_exc(limit=1)
123
218
  # ui.ShowErrorMessage("Value error :\n %s \n%s\n\n%s" % (e, trace,
124
219
  # "Aborting submission to P2. Look at the whole traceback in the log."))
125
220
  self.ui.ShowErrorMessage("Value error :\n %s \n\n%s" %
126
- (e, "Aborting submission to P2. Please check LOG and fix before new submission."))
221
+ (e, "Aborting submission to P2. Please check LOG and fix before new submission."))
127
222
  trace = traceback.format_exc()
128
223
  self.ui.addToLog(trace, False)
129
224
  self.ui.setProgress(0)
@@ -138,27 +233,23 @@ class VltiFacility(Facility):
138
233
  self.ui.addToLog(trace, False)
139
234
  self.ui.setProgress(0)
140
235
 
141
- def isReadyToSubmit(self):
142
- return self.api and self.containerInfo.isOk()
143
-
144
- def isConnected(self):
145
- return self.connected
146
-
147
- def setConnected(self, flag):
148
- self.connected = flag
149
-
150
236
  def getStatus(self):
237
+ ob_info=""
238
+ if self.hasOB():
239
+ ob_info=f" / {len(self.ob_to_confirm)} OB in stack"
151
240
  if self.isConnected():
152
- return " P2API connected with " + self.username
241
+ return f" P2API({self.apitype}) connected with {self.username} { ob_info }"
153
242
 
154
243
  def connectAPI(self, username, password, ob):
155
- import p2api
156
- if username == TUTORIAL_LOGIN or username == JMMC_LOGIN:
244
+ if username == TUTORIAL_LOGIN: # or username == JMMC_LOGIN:
157
245
  self.apitype = DEMO_APITYPE
158
246
  else:
159
247
  self.apitype = PRODUCTION_APITYPE
160
248
  try:
249
+ logger.info("Connecting to p2 api...")
161
250
  self.api = p2api.ApiConnection(self.apitype, username, password)
251
+
252
+ self.ui.addToLog("Connected to p2 api (%s)"%self.apitype)
162
253
  # TODO test that api is ok and handle error if any...
163
254
 
164
255
  self.refreshTree()
@@ -167,9 +258,9 @@ class VltiFacility(Facility):
167
258
  self.username = username
168
259
  self.ui.showTreeFrame(ob)
169
260
  except:
170
- self.ui.addToLog("Can't connect to P2 (see LOG).")
261
+ self.ui.ShowErrorMessage("Can't connect to P2 (see LOG).")
171
262
  trace = traceback.format_exc()
172
- self.ui.addToLog(trace, False)
263
+ self.ui.addToLog(trace, False, level=logging.ERROR)
173
264
 
174
265
  def refreshTree(self):
175
266
  runs, _ = self.api.getRuns()
@@ -190,9 +281,12 @@ class VltiFacility(Facility):
190
281
  """
191
282
  return CONFDIR
192
283
 
284
+ def getIssVltiTypes(self):
285
+ return ['snapshot','imaging','time-series','astrometry']
286
+
193
287
 
194
- # TODO Move code out of this class
195
288
 
289
+ # TODO Move code out of this class
196
290
 
197
291
  class P2Container:
198
292
  # run object stores:
@@ -216,23 +310,46 @@ class P2Container:
216
310
  self.containerId = item['containerId']
217
311
  self.log()
218
312
 
313
+ def reset(self):
314
+ self.run = None # dict returned by p2api
315
+ self.containerId = None
316
+ self.item = None
317
+
219
318
  def log(self):
319
+ logmsg = f"*** Working with {self} ***"
220
320
  if self.run != self.item and self.item['itemType'] == ITEMTYPE_CONCATENATION:
321
+ self.reset()
221
322
  self.facility.ui.addToLog(
222
- "*** Please do not select a Concatenation and select another container. ***")
323
+ "*** Please do not select a Concatenation and select another container. Or just append a calibrator. ***", )
324
+ logger.info(logmsg)
223
325
  else:
224
- self.facility.ui.addToLog("*** Working with %s ***" % self)
326
+ self.facility.ui.addToLog(logmsg)
225
327
 
226
- def isOk(self):
328
+ def isOk(self, ob):
329
+ """ Tell if given container is ready to receive content of given OB."""
227
330
  if self.run == None:
228
331
  return False
229
332
  if self.run == self.item:
230
333
  return True
231
- return self.item['itemType'] != ITEMTYPE_CONCATENATION
334
+
335
+ has_calib = False
336
+ has_science = False
337
+ for obsConf in ob.observationConfiguration:
338
+ if 'SCIENCE' in obsConf.type:
339
+ has_science = True
340
+ else:
341
+ has_calib = True
342
+
343
+ if has_science:
344
+ return self.item['itemType'] != ITEMTYPE_CONCATENATION
345
+ return has_calib
232
346
 
233
347
  def getInstrument(self):
234
348
  return self.run['instrument']
235
349
 
350
+ def getIpVersion(self):
351
+ return self.run['ipVersion']
352
+
236
353
  def isRoot(self):
237
354
  return self.item.keys() != None and 'pi' in self.item.keys()
238
355