a2p2 0.2.15__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 (46) hide show
  1. a2p2/__main__.py +39 -0
  2. a2p2/chara/facility.py +51 -3
  3. a2p2/chara/gui.py +29 -5
  4. a2p2/client.py +144 -34
  5. a2p2/facility.py +11 -1
  6. a2p2/gui.py +32 -1
  7. a2p2/jmmc/__init__.py +7 -0
  8. a2p2/jmmc/catalogs.py +129 -0
  9. a2p2/jmmc/generated_models.py +191 -0
  10. a2p2/jmmc/models.py +104 -0
  11. a2p2/jmmc/services.py +16 -0
  12. a2p2/jmmc/utils.py +130 -0
  13. a2p2/jmmc/webservices.py +48 -0
  14. a2p2/ob.py +95 -9
  15. a2p2/samp.py +17 -0
  16. a2p2/version.py +205 -137
  17. a2p2/vlti/conf/GRAVITY_ditTable.json +21 -19
  18. a2p2/vlti/conf/GRAVITY_rangeTable.json +200 -28
  19. a2p2/vlti/conf/MATISSE_rangeTable.json +58 -22
  20. a2p2/vlti/conf/PIONIER_ditTable.json +1 -1
  21. a2p2/vlti/conf/PIONIER_rangeTable.json +16 -18
  22. a2p2/vlti/facility.py +156 -118
  23. a2p2/vlti/gravity.py +243 -311
  24. a2p2/vlti/gui.py +162 -40
  25. a2p2/vlti/instrument.py +264 -49
  26. a2p2/vlti/matisse.py +61 -147
  27. a2p2/vlti/pionier.py +34 -157
  28. {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/METADATA +34 -20
  29. a2p2-0.7.4.dist-info/RECORD +39 -0
  30. {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/WHEEL +1 -1
  31. {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/entry_points.txt +0 -1
  32. a2p2/vlti/confP104/GRAVITY_ditTable.json +0 -122
  33. a2p2/vlti/confP104/GRAVITY_rangeTable.json +0 -202
  34. a2p2/vlti/confP104/MATISSE_ditTable.json +0 -2
  35. a2p2/vlti/confP104/MATISSE_rangeTable.json +0 -202
  36. a2p2/vlti/confP104/PIONIER_ditTable.json +0 -77
  37. a2p2/vlti/confP104/PIONIER_rangeTable.json +0 -118
  38. a2p2/vlti/confP105/GRAVITY_ditTable.json +0 -37
  39. a2p2/vlti/confP105/GRAVITY_rangeTable.json +0 -42
  40. a2p2/vlti/confP105/MATISSE_ditTable.json +0 -2
  41. a2p2/vlti/confP105/MATISSE_rangeTable.json +0 -44
  42. a2p2/vlti/confP105/PIONIER_ditTable.json +0 -25
  43. a2p2/vlti/confP105/PIONIER_rangeTable.json +0 -38
  44. a2p2-0.2.15.dist-info/RECORD +0 -44
  45. {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/LICENSE +0 -0
  46. {a2p2-0.2.15.dist-info → a2p2-0.7.4.dist-info}/top_level.txt +0 -0
a2p2/__main__.py CHANGED
@@ -2,7 +2,40 @@
2
2
  from __future__ import with_statement
3
3
 
4
4
  import traceback
5
+
5
6
  from argparse import ArgumentParser
7
+ from a2p2 import __release_notes__
8
+ from distutils.version import LooseVersion
9
+
10
+
11
+
12
+ def createMdReleaseNotes():
13
+ """
14
+ Present in a reverse ordered way the dictionnary version items.
15
+ """
16
+ txt = "# A2P2 release notes"
17
+ lvs = [LooseVersion(v) for v in __release_notes__]
18
+ for lv in sorted(lvs, reverse=True):
19
+ v=lv.vstring
20
+ txt += "\n## V " + v + " :"
21
+ keys = []
22
+ for k in sorted(__release_notes__[v]):
23
+ if not ("TODO" in k):
24
+ keys.append(k)
25
+ for k in sorted(__release_notes__[v]):
26
+ if "TODO" in k:
27
+ keys.append(k)
28
+
29
+ for e in keys:
30
+ infos = __release_notes__[v][e]
31
+ if infos:
32
+ txt += "\n### " + e + " : "
33
+ for i in infos:
34
+ txt += "\n- " + i
35
+ txt += "\n\n"
36
+ f=open("release-notes.md", "w")
37
+ f.write(txt)
38
+ print(f"{f.name} generated")
6
39
 
7
40
 
8
41
  def main():
@@ -14,15 +47,21 @@ def main():
14
47
  help='fake API to avoid remote connection (dev. only).')
15
48
  parser.add_argument('-v', '--verbose', action='store_true', help='Verbose')
16
49
  parser.add_argument('-c', '--createprefs', action='store_true', help='Create preferences file')
50
+ parser.add_argument('-r', '--releasenotes', action='store_true', help='Create md release notes file')
17
51
 
18
52
  args = parser.parse_args()
19
53
 
20
54
  from . import A2p2Client
21
55
 
56
+ if args.releasenotes:
57
+ createMdReleaseNotes()
58
+ exit()
59
+
22
60
  if args.createprefs:
23
61
  A2p2Client.createPreferencesFile()
24
62
  exit()
25
63
 
64
+
26
65
  try:
27
66
  with A2p2Client(args.fakeapi, args.verbose) as a2p2c:
28
67
  # if args.config:
a2p2/chara/facility.py CHANGED
@@ -4,7 +4,9 @@ __all__ = []
4
4
 
5
5
  from a2p2.chara.gui import CharaUI
6
6
  from a2p2.facility import Facility
7
+ import requests
7
8
  import logging
9
+ import traceback
8
10
 
9
11
  HELPTEXT = "TODO update this HELP message in a2p2/chara/facility.py"
10
12
 
@@ -15,8 +17,13 @@ class CharaFacility(Facility):
15
17
  def __init__(self, a2p2client):
16
18
  Facility.__init__(self, a2p2client, "CHARA", HELPTEXT)
17
19
  self.charaUI = CharaUI(self)
20
+ self.connected2OB2 = False
21
+ self.validQueueServer = None
18
22
 
19
23
  def processOB(self, ob):
24
+ if not ob:
25
+ return
26
+
20
27
  self.a2p2client.ui.addToLog(
21
28
  "OB received for '" + self.facilityName + "' interferometer")
22
29
  # show ob dict for debug
@@ -28,8 +35,49 @@ class CharaFacility(Facility):
28
35
  # give focus on last updated UI
29
36
  self.a2p2client.ui.showFacilityUI(self.charaUI)
30
37
 
38
+ def checkServer(self):
39
+ if self.validQueueServer:
40
+ # recheck ?
41
+ return True
42
+ else:
43
+ # search and test servers from preferences
44
+ queueServers=self.a2p2client.preferences.getCharaQueueServer()
45
+ msg=""
46
+ if queueServers :
47
+ for queueServer in queueServers:
48
+ logger.debug(f'Trying to send OB on queuserver : {queueServer}')
49
+ try:
50
+ c=requests.get(queueServer, timeout=3)
51
+ msg+=f"Connection succeeded on OB server : {c.json()}\n"
52
+ self.validQueueServer = queueServer
53
+ break
54
+ except:
55
+ msg+=f"Connection failed on {queueServer}\n"
56
+
57
+ self.a2p2client.ui.addToLog(msg)
58
+ self.charaUI.display(msg)
59
+
60
+ return self.validQueueServer
61
+
31
62
  def consumeOB(self, ob):
32
- # for the prototype: just delegate handling to the GUI
33
- # we could imagine to store obs in a list and recompute a sorted
34
- # summary report e.g.
63
+ if self.checkServer():
64
+ try:
65
+ r = requests.post(self.validQueueServer, json=ob.as_dict(), timeout=3)
66
+ msg = ""
67
+ msg+=f"OB sent to remote server queue : {r}"
68
+ self.connected2OB2 = True
69
+ self.a2p2client.ui.addToLog(msg)
70
+ self.charaUI.display(msg)
71
+ except:
72
+ print(traceback.format_exc())
73
+ msg=f"Can't send OB to the '{self.validQueueServer}' queue server, please relaunch it or try again for a new one."
74
+ self.validQueueServer = None
75
+ self.a2p2client.ui.addToLog(msg)
76
+ self.charaUI.display(msg)
77
+ else:
78
+ msg=f"Can't find any queue server, please launch it, edit your preferences or check your ssh port forwarding"
79
+
80
+ # display OB
35
81
  self.charaUI.displayOB(ob)
82
+
83
+
a2p2/chara/gui.py CHANGED
@@ -42,6 +42,10 @@ class CharaUI(FacilityUI):
42
42
  else:
43
43
  return None
44
44
 
45
+ def display(self, msg):
46
+ self.text.insert(END, msg)
47
+
48
+
45
49
  def displayOB(self, ob):
46
50
  try:
47
51
  buffer = self.extractReport(ob)
@@ -91,8 +95,8 @@ AO Flat Star:
91
95
  targets = {} # store ids for futur retrieval in schedule
92
96
  for oc in ob.observationConfiguration:
93
97
  targets[oc.id] = oc
94
- if "SCI" in oc.type:
95
- sciences.append(oc)
98
+ # if "SCI" in oc.type:
99
+ sciences.append(oc)
96
100
 
97
101
  # Retrieve cals from schedule
98
102
  cals = {}
@@ -109,13 +113,28 @@ AO Flat Star:
109
113
 
110
114
  for oc in sciences:
111
115
  sct = oc.SCTarget
116
+ extrainfos = self.get(sct, "EXTRA_INFORMATIONS")
112
117
  ftt = self.get(oc, "FTTarget")
113
118
  aot = self.get(oc, "AOTarget")
114
- buffer += oc.observationConstraints.LSTinterval + "\n"
115
- buffer += "Object:\n"
119
+
120
+ if self.get(oc,'observationConstraints'):
121
+ buffer += ", ".join(oc.observationConstraints.LSTinterval) + "\n"
122
+ else:
123
+ buffer += " NOT OBSERVABLE \n"
124
+ buffer += f"{oc.type} Object:\n"
116
125
  fluxes = ", ".join([e[0] + "=" + e[1]
117
126
  for e in ob.getFluxes(sct).items()])
118
- info = sct.SPECTYP + ", " + sct.PARALLAX
127
+ try:
128
+ info = sct.SPECTYP
129
+ except:
130
+ info = "no SPECTYP"
131
+ info+=", "
132
+ try:
133
+ info += sct.PARALLAX
134
+ except:
135
+ info += "no PARALLAX"
136
+
137
+
119
138
  buffer += sct.name + " (" + info + ") : " + fluxes + "\n"
120
139
  if ftt:
121
140
  buffer += "Fringe Finder:\n"
@@ -133,6 +152,11 @@ AO Flat Star:
133
152
  for cal in cals:
134
153
  buffer += "- " + cal + "\n"
135
154
 
155
+ # Display Extra_Informations if any
156
+ if extrainfos:
157
+ buffer += "Extra_infos:\n"
158
+ buffer += ", ".join([f"{field}={self.get(extrainfos,field)}" for field in extrainfos._fields])
159
+
136
160
  buffer += _HR
137
161
 
138
162
  return buffer
a2p2/client.py CHANGED
@@ -16,19 +16,23 @@ from a2p2.samp import A2p2SampClient
16
16
  from a2p2.vlti.facility import VltiFacility
17
17
 
18
18
 
19
+
19
20
  # prepare global logging
20
21
  a2p2Rootlogger = logging.getLogger("a2p2")
21
- # uncomment next line to log requests done by p2api and maybe other ones...
22
- #a2p2Rootlogger = logging.getLogger()
23
22
  a2p2Rootlogger.setLevel(logging.INFO)
23
+ # uncomment next two lines to log requests done by p2api as debug and maybe other ones...
24
+ #a2p2Rootlogger = logging.getLogger()
25
+ #a2p2Rootlogger.setLevel(logging.DEBUG)
24
26
  console = logging.StreamHandler()
25
27
  console.setLevel(logging.DEBUG)
26
- consoleFormatter = logging.Formatter('%(levelname)s - %(name)s - %(asctime)s - %(filename)s:%(lineno)d - %(message)s')
28
+ consoleFormatter = logging.Formatter(
29
+ '%(levelname)s - %(name)s - %(asctime)s - %(filename)s:%(lineno)d - %(message)s')
27
30
  console.setFormatter(consoleFormatter)
28
31
  a2p2Rootlogger.addHandler(console)
29
32
 
30
33
  logger = logging.getLogger(__name__)
31
34
 
35
+
32
36
  class A2p2Client():
33
37
  """Transmit your Aspro2 observation to remote Observatory scheduling database.
34
38
 
@@ -36,7 +40,6 @@ class A2p2Client():
36
40
  a2p2.run()
37
41
  ..."""
38
42
 
39
-
40
43
  def __init__(self, fakeAPI=False, verbose=False):
41
44
  """Create the A2p2 client."""
42
45
 
@@ -56,11 +59,17 @@ class A2p2Client():
56
59
  self.facilityManager = FacilityManager(self)
57
60
 
58
61
  if self.preferences.exists():
59
- pass
62
+ A2P2ClientPreferences.updatePreferencesFile()
63
+ self.ui.addToLog(
64
+ f"Using preference from '{A2P2ClientPreferences.getPreferencesFileName()}'.\n")
60
65
  else:
61
- self.ui.addToLog("No preference file found, please create one so your data persists (launch program with -c option).\n\n")
66
+ self.ui.addToLog(
67
+ "No preference file found, please create one so your data persists (launch program with -c option).\n")
62
68
 
63
- self.errors=[]
69
+ self.ui.addToLog("Please often update ( pip install -U [--user] a2p2 ) and don't hesitate to send any feedback or issues!\n\n")
70
+
71
+
72
+ self.errors = []
64
73
 
65
74
  pass
66
75
 
@@ -120,16 +129,16 @@ class A2p2Client():
120
129
 
121
130
  # handle autologin
122
131
  if self.preferences.getP2AutoLoginBoolean():
123
- logger.debug("Autologin using '%s' file"%A2P2ClientPreferences.getPreferencesFileName())
124
- self.ui.addToLog("\nAutologin into P2 API please wait...\n")
132
+ logger.debug("Autologin using '%s' file" %
133
+ A2P2ClientPreferences.getPreferencesFileName())
125
134
  self.ui.loop()
126
- vltifacility = self.facilityManager.facilities.get(VltiFacility.getName())
135
+ vltifacility = self.facilityManager.facilities.get(
136
+ VltiFacility.getName())
127
137
  vltifacility.autologin()
128
138
 
129
-
130
139
  # We now run the loop to wait for the message in a try/finally block so that if
131
140
  # the program is interrupted e.g. by control-C, the client terminates
132
- # gracefully.
141
+ # gracefully. ( but sometimes fails inside tkinter/__init__.py CallWrapper/__call__() )
133
142
 
134
143
  # We test every 1s to see if the hub has sent a message
135
144
  delay = 0.1
@@ -142,8 +151,14 @@ class A2p2Client():
142
151
  loop_cnt += 1
143
152
  time.sleep(delay)
144
153
 
154
+ # if loop_cnt % each == 0:
155
+ # logger.debug(f"loop {loop_cnt}")
156
+
145
157
  self.ui.loop()
146
158
 
159
+ # process any stacked OBs
160
+ self.facilityManager.processOB()
161
+
147
162
  if not self.a2p2SampClient.is_connected() and loop_cnt % each == 0:
148
163
  try:
149
164
  self.a2p2SampClient.connect()
@@ -159,11 +174,21 @@ class A2p2Client():
159
174
 
160
175
  if self.a2p2SampClient.has_message():
161
176
  try:
162
- ob = OB(self.a2p2SampClient.get_ob_url())
163
- self.facilityManager.processOB(ob)
177
+ if self.a2p2SampClient.has_ob_message():
178
+ ob = OB(self.a2p2SampClient.get_ob_url())
179
+ self.facilityManager.processOB(ob)
164
180
  except:
165
181
  self.ui.addToLog(
166
- "Exception during ob creation: " + traceback.format_exc(), False)
182
+ "Exception during a2p2 ob creation: " + traceback.format_exc(), False)
183
+ self.ui.addToLog("Can't process last OB")
184
+
185
+ try:
186
+ if self.a2p2SampClient.has_model_message():
187
+ m = self.a2p2SampClient.get_model()
188
+ self.showModel(m)
189
+ except:
190
+ self.ui.addToLog(
191
+ "Exception during a2p2 ob creation: " + traceback.format_exc(), False)
167
192
  self.ui.addToLog("Can't process last OB")
168
193
 
169
194
  # always clear previous received message
@@ -173,16 +198,27 @@ class A2p2Client():
173
198
  loop_cnt = -1
174
199
  except KeyboardInterrupt:
175
200
  loop_cnt = -1
201
+ print("\nDisconnecting SAMP ...")
202
+ self.a2p2SampClient.disconnect()
203
+ print("Bye!")
204
+
176
205
 
177
206
  def createPreferencesFile():
178
207
  A2P2ClientPreferences.createPreferencesFile()
179
208
 
209
+
210
+ def showModel(self, xmlmodel):
211
+ from a2p2.jmmc.models import modelsFromXml
212
+ self.ui.addToLog("Received star model")
213
+ self.ui.addToLog(modelsFromXml(xmlmodel))
214
+
215
+
180
216
  class A2P2ClientPreferences():
181
217
  # define application name
182
218
  appname = "a2p2"
183
219
 
184
220
  def __init__(self):
185
- self._config = A2P2ClientPreferences.getPreferences()
221
+ self._config = A2P2ClientPreferences.getPreferences()
186
222
  pass
187
223
 
188
224
  def exists(self):
@@ -193,36 +229,84 @@ class A2P2ClientPreferences():
193
229
 
194
230
  def getPreferences():
195
231
  preferences_file = A2P2ClientPreferences.getPreferencesFileName()
196
- config = configparser.ConfigParser()
232
+ config = configparser.ConfigParser(allow_no_value=True)
197
233
  config.read(preferences_file)
198
234
  return config
199
235
 
200
236
  def getPreferencesFileName():
201
237
  from appdirs import user_config_dir
202
- preferences_file = os.path.join(user_config_dir(A2P2ClientPreferences.appname), "prefs.ini")
238
+ preferences_file = os.path.join(user_config_dir(
239
+ A2P2ClientPreferences.appname), "prefs.ini")
203
240
  return preferences_file
241
+ def updatePreferencesFile():
242
+ return
243
+ # TODO
244
+ # we suppose the file exists
245
+ filename = A2P2ClientPreferences.getPreferencesFileName()
246
+ buffer=""
247
+ for line in open(filename):
248
+ buffer+=line+"\n"
249
+ print (buffer)
204
250
 
205
251
  def createPreferencesFile():
206
- filename=A2P2ClientPreferences.getPreferencesFileName()
207
-
252
+ filename = A2P2ClientPreferences.getPreferencesFileName()
208
253
  if os.path.exists(filename):
209
- print("%s already exists. Nothing done"%filename)
254
+ print(f"{filename} already exists. Nothing done")
255
+ p=A2P2ClientPreferences()
256
+ versionInPref=p.getA2P2Version()
257
+ if __version__ != versionInPref:
258
+ print(f"HINT: You may try to backup this file (V{versionInPref}) and merge with a new generated one for V{__version__}.")
210
259
  else:
211
- config = configparser.ConfigParser()
260
+ import getpass
261
+
262
+ config = configparser.ConfigParser(allow_no_value=True)
212
263
  #config['DEFAULT'] = {'_noprefyet': '42'}
264
+
265
+ config['a2p2'] = {}
266
+ s = config['a2p2']
267
+ s['# A2P2 SECTION'] = ""
268
+ s['# = > please do not modify next properties <'] = ""
269
+ s['version'] = __version__
270
+
271
+
272
+ config['jmmc'] = {}
273
+ s = config['jmmc']
274
+ s['# JMMC SECTION'] = ""
275
+ s['# = > please uncomment and update next properties to make it active <'] = ""
276
+ s['#login'] = "my.email@my.lab"
277
+ s['#password'] = "12345zZ"
278
+
279
+ config['chara'] = {}
280
+ s = config['chara']
281
+ s['# CHARA SECTION'] = ""
282
+ s['# = > please uncomment and update next properties to make it active <'] = ""
283
+ s['# = > queueserver may be uncommented to forward OB to a remote server instead <'] = ""
284
+ s['#queueserver'] = 'http://192.168.3.153:2468/test,http://localhost:2468/test'
285
+
213
286
  config['p2'] = {}
214
- import getpass
215
- config['p2']['# = > please uncomment and update next properties to make it active <']=""
216
- config['p2']['#username'] = getpass.getuser()
217
- config['p2']['#password'] = "12345zZ"
218
- config['p2']['#user_comment_name'] = "changed it if your local USER name is not fine"
219
- config['p2']['#autologin'] = "yes"
287
+ s=config['p2']
288
+ s['# ESO P2 SECTION'] = ""
289
+ s['# = > please uncomment and update next properties to make it active <'] = ""
290
+ s['#username'] = getpass.getuser()
291
+ s['#password'] = "12345zZ"
292
+ s['#autologin'] = "yes"
293
+ s['# = > please change next properties to change the name recorded in the OB comments <'] = ""
294
+ s['user_comment_name'] = f"{getpass.getuser()}"
295
+
296
+ config['p2.iss.vltitype'] = {}
297
+ s=config['p2.iss.vltitype']
298
+ s['# = > please uncomment the default values to add for ISS.VLTITYPE <'] = ""
299
+ s['# = > all supported will be added for any VLTI instrument if info is not provided by Aspro2 <'] = None
300
+ s['#snapshot'] = None
301
+ s['#imaging'] = None
302
+ s['#time-series'] = None
303
+ s['#astrometry'] = None
220
304
 
221
305
  os.makedirs(os.path.dirname(filename), exist_ok=True)
222
306
  with open(filename, 'w+') as configfile:
223
307
  config.write(configfile)
224
308
 
225
- print("%s template created. Please adjust."%filename)
309
+ print("'%s' template file created to store preferences. Please check and adjust it's content." % filename)
226
310
 
227
311
  def getConfig(self, section, key, default=None):
228
312
  try:
@@ -230,19 +314,44 @@ class A2P2ClientPreferences():
230
314
  except:
231
315
  return default
232
316
 
317
+ def getConfigKeys(self, section, default=None):
318
+ try:
319
+ return list(self._config[section].keys())
320
+ except:
321
+ return default
322
+
323
+
233
324
  def getConfigBoolean(self, section, key, default=None):
234
325
  try:
235
- return self._config.getboolean(section,key)
326
+ return self._config.getboolean(section, key)
236
327
  except:
237
328
  return default
238
329
 
330
+ # Retrieve A2P2 prefs
331
+ def getA2P2Version(self):
332
+ return self.getConfig("a2p2", "version", 'missing')
333
+
334
+ # Retrieve JMMC prefs
335
+ def getJmmcLogin(self):
336
+ return self.getConfig("jmmc", "login", None)
239
337
 
240
- # retrieve P2 username in config or use default demo account
338
+ def getJmmcPassword(self):
339
+ return self.getConfig("jmmc", "password", None)
340
+
341
+ # Retrieve CHARA prefs
342
+ def getCharaQueueServer(self):
343
+ s = self.getConfig("chara", "queueserver", None)
344
+ if s:
345
+ return s.split(",")
346
+
347
+
348
+ # Retrieve P2 prefs
241
349
  def getP2Username(self):
242
- return self.getConfig("p2","username", '52052')
350
+ """ Get P2 username in config or use default demo account """
351
+ return self.getConfig("p2", "username", '52052')
243
352
 
244
- # retrieve P2 password in config or use default demo account
245
353
  def getP2Password(self):
354
+ """Get P2 password in config or use default demo account"""
246
355
  return self.getConfig("p2", "password", 'tutorial')
247
356
 
248
357
  def getP2UserCommentName(self):
@@ -250,5 +359,6 @@ class A2P2ClientPreferences():
250
359
  return self.getConfig("p2", "user_comment_name", getpass.getuser())
251
360
 
252
361
  def getP2AutoLoginBoolean(self):
253
- return self.getConfigBoolean("p2", "autologin", False)
362
+ return self.getConfigBoolean("p2", "autologin", False)
363
+
254
364
 
a2p2/facility.py CHANGED
@@ -38,7 +38,17 @@ class FacilityManager():
38
38
 
39
39
  return " | ".join(status)
40
40
 
41
- def processOB(self, ob):
41
+ def processOB(self, ob=None):
42
+
43
+ # handled queued obs if ob is null
44
+ # TODO add a new method in the futur
45
+ if not ob:
46
+ for f in self.facilities.values():
47
+ f.processOB(ob)
48
+ return
49
+
50
+ # else handle given ob
51
+
42
52
  """ Test instrument on facility that registerInstrument() before OB forward for specialized handling."""
43
53
  interferometer = ob.interferometerConfiguration.name
44
54
  insname = ob.instrumentConfiguration.name
a2p2/gui.py CHANGED
@@ -19,6 +19,8 @@ else:
19
19
 
20
20
  from distutils.version import LooseVersion
21
21
 
22
+ import signal
23
+
22
24
  HELPTEXT = """This application provides the link between ASPRO (that you should have started) and interferometers facilities.
23
25
 
24
26
  """
@@ -44,6 +46,8 @@ class MainWindow():
44
46
  print("Can not set tk scaling !")
45
47
 
46
48
  self.window.protocol("WM_DELETE_WINDOW", self._requestAbort)
49
+ # throws an exception self.window.bind_all('<Control-c>', self._requestAbort) # maybe already bound with WM_DELETE_WINDOW ?
50
+ signal.signal(signal.SIGINT, self._requestAbortSignal)
47
51
 
48
52
  self.notebook = ttk.Notebook(self.window)
49
53
 
@@ -96,6 +100,10 @@ class MainWindow():
96
100
  def _requestAbort(self):
97
101
  self.requestAbort = True
98
102
 
103
+ def _requestAbortSignal(self, arg1,arg2):
104
+ self.requestAbort = True
105
+
106
+
99
107
  def addHelp(self, tabname, txt):
100
108
  frame = Frame(self.helptabs)
101
109
  widget = Text(frame, width=120)
@@ -176,8 +184,12 @@ class MainWindow():
176
184
  self.logtext.insert(END, "\n" + str(text))
177
185
  self.logtext.see(END)
178
186
  self.showFrameToFront()
187
+ self.refresh()
179
188
  logger.log(level,text)
180
189
 
190
+ def refresh(self):
191
+ self.window.update()
192
+
181
193
  def ShowErrorMessage(self, text):
182
194
  if self.a2p2client.fakeAPI:
183
195
  pass
@@ -195,7 +207,7 @@ class MainWindow():
195
207
  else:
196
208
  showwarning("Warning", text)
197
209
  self.addToLog("Warning message")
198
- self.addToLog(text, False, loggin.WARNING)
210
+ self.addToLog(text, False, logging.WARNING)
199
211
 
200
212
  def ShowInfoMessage(self, text):
201
213
  if self.a2p2client.fakeAPI:
@@ -205,6 +217,19 @@ class MainWindow():
205
217
  self.addToLog("Info message")
206
218
  self.addToLog(text, False, logging.INFO)
207
219
 
220
+ def AskYesNoMessage(self, text):
221
+ if self.a2p2client.fakeAPI:
222
+ pass
223
+ else:
224
+ self.addToLog(f"Question: {text}", displayString=False)
225
+ ret = askyesno("", text)
226
+ self.addToLog(f"Reply: yes={ret}", displayString=False)
227
+ return ret
228
+
229
+ def addProgress(self, offset=0.1):
230
+ self.setProgress(self.progress_value.get()+offset)
231
+
232
+
208
233
  def setProgress(self, perc):
209
234
  if perc > 1:
210
235
  perc = perc / 100.0
@@ -268,6 +293,12 @@ class FacilityUI(Frame):
268
293
  def ShowInfoMessage(self, *args, **kwargs):
269
294
  self.a2p2client.ui.ShowInfoMessage(*args, **kwargs)
270
295
 
296
+ def AskYesNoMessage(self,*args, **kwargs):
297
+ return self.a2p2client.ui.AskYesNoMessage(*args, **kwargs)
298
+
299
+ def addProgress(self, offset=0.1):
300
+ self.a2p2client.ui.addProgress(offset)
301
+
271
302
  def setProgress(self, perc):
272
303
  """ Wrapper to update progress bar """
273
304
  if perc > 1:
a2p2/jmmc/__init__.py ADDED
@@ -0,0 +1,7 @@
1
+ __all__ = ['Catalog', 'Models','CallIper']
2
+
3
+ PRODLABEL = {True: "production", False: "pre-prod"}
4
+
5
+ from .catalogs import Catalog
6
+ from .models import Models
7
+ from .webservices import CallIper