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/vlti/gravity.py CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  #!/usr/bin/env python
2
3
 
3
4
  __all__ = []
@@ -36,227 +37,237 @@ class Gravity(VltiInstrument):
36
37
 
37
38
  instrumentMode = instrumentConfiguration.instrumentMode
38
39
 
39
- # Retrieve SPEC_RES and POL info from instrumentMode
40
-
41
- # We could force ins_spec_res to be default but prefer a bad keyword value
42
- # that throws a Value Error if instrumentMode does not start with an accepted one
43
- # ins_spec_res = self.getDefault("GRAVITY_gen_acq.tsf", "INS.SPEC.RES")
44
- ins_spec_res = "BAD_SPEC_RES"
45
- for res in self.getRange("GRAVITY_gen_acq.tsf", "INS.SPEC.RES"):
46
- if res in instrumentMode[0:len(res)]:
47
- ins_spec_res = res
48
-
49
40
  if "COMBINED" in instrumentMode:
50
- ins_pol = "OUT"
41
+ ins_spec_pol = "OUT"
51
42
  else:
52
- ins_pol = 'IN'
43
+ ins_spec_pol = 'IN'
53
44
 
54
- for observationConfiguration in ob.observationConfiguration:
55
-
56
- # create keywords storage objects
57
- acqTSF = TSF(self, "GRAVITY_gen_acq.tsf")
58
- obsTSF = TSF(self, "GRAVITY_single_obs_exp.tsf")
59
- # alias for
60
- # ,GRAVITY_single_obs_calibrator.tsf,GRAVITY_dual_obs_exp.tsf,GRAVITY_dual_obs_calibrator.tsf")
61
- obTarget = OBTarget()
62
- obConstraints = OBConstraints(self)
63
-
64
- # set common properties if any
65
- if ins_spec_res:
66
- acqTSF.INS_SPEC_RES = ins_spec_res
67
- acqTSF.INS_FT_POL = ins_pol
68
- acqTSF.INS_SPEC_POL = ins_pol
45
+ for observationConfiguration in self.getSequence(ob):
69
46
 
47
+ # define top level variable
70
48
  if 'SCIENCE' in observationConfiguration.type:
71
49
  OBJTYPE = 'SCIENCE'
72
50
  else:
73
51
  OBJTYPE = 'CALIBRATOR'
74
52
 
75
- scienceTarget = observationConfiguration.SCTarget
76
-
77
- # define target
78
- acqTSF.SEQ_INS_SOBJ_NAME = scienceTarget.name.strip()
79
- obTarget.name = acqTSF.SEQ_INS_SOBJ_NAME.replace(
80
- ' ', '_') # allowed characters: letters, digits, + - _ . and no spaces
81
- obTarget.ra, obTarget.dec = self.getCoords(scienceTarget)
82
- obTarget.properMotionRa, obTarget.properMotionDec = self.getPMCoords(
83
- scienceTarget)
84
-
85
- # Set baseline interferometric array code (should be a keywordlist)
86
- acqTSF.ISS_BASELINE = [self.getBaselineCode(BASELINE)]
87
-
88
- # define some default values
89
- DIAMETER = float(self.get(scienceTarget, "DIAMETER", 0.0))
90
- VIS = 1.0 # FIXME
91
-
92
- # Retrieve Fluxes
93
- COU_GS_MAG = self.getFlux(scienceTarget, "V")
94
- acqTSF.SEQ_INS_SOBJ_MAG = self.getFlux(scienceTarget, "K")
95
- acqTSF.SEQ_FI_HMAG = self.getFlux(scienceTarget, "H")
96
-
97
- # setup some default values, to be changed below
98
- COU_AG_GSSOURCE = 'SCIENCE' # by default
99
- GSRA = '00:00:00.000'
100
- GSDEC = '00:00:00.000'
101
- dualField = False
102
- dualFieldDistance = 0.0 # needed as must exist for the argument list of createGravityOB
103
-
104
- # initialize FT variables (must exist)
105
- # TODO remove next lines using a dual_acq TSF that would handle
106
- # them
107
- SEQ_FT_ROBJ_NAME = ""
108
- SEQ_FT_ROBJ_MAG = -99.99
109
- SEQ_FT_ROBJ_DIAMETER = -1.0
110
- SEQ_FT_ROBJ_VIS = -1.0
111
-
112
- # if FT Target is not ScTarget, we are in dual-field (TBD)
113
- ftTarget = ob.get(observationConfiguration, "FTTarget")
114
- if ftTarget != None:
115
- SEQ_FT_ROBJ_NAME = ftTarget.name
116
- FTRA, FTDEC = self.getCoords(ftTarget)
117
- # no PMRA, PMDE for FT !!
118
- SEQ_FI_HMAG = float(ftTarget.FLUX_H)
119
- # just to say we must treat the case there
120
- # is no FT Target
121
- SEQ_FT_ROBJ_MAG = self.getFlux(ftTarget, "K")
122
- SEQ_FT_ROBJ_DIAMETER = 0.0 # FIXME
123
- SEQ_FT_ROBJ_VIS = 1.0 # FIXME
124
- dualField = True
125
-
126
- # test distance in dual field mode
127
- if tel == "UT":
128
- SCtoREFmaxDist = 2000
129
- SCtoREFminDist = 0 # before P103: 400
130
- else:
131
- SCtoREFminDist = 0 # before P103: 1500
132
- SCtoREFmaxDist = 4000
133
- # compute x,y between science and ref beams:
134
- dualFieldDistance = self.getSkyDiff(
135
- obTarget.ra, obTarget.dec, FTRA, FTDEC)
136
- if np.abs(dualFieldDistance[0]) < SCtoREFminDist:
137
- raise ValueError("Dual-Field distance of two stars is < " + str(
138
- SCtoREFminDist) + " mas, Please Correct.")
139
- elif np.abs(dualFieldDistance[0]) > SCtoREFmaxDist:
140
- raise ValueError("Dual-Field distance of two stars is > " + str(
141
- SCtoREFmaxDist) + " mas, Please Correct.")
142
-
143
- # AO target
144
- aoTarget = ob.get(observationConfiguration, "AOTarget")
145
- if aoTarget != None:
146
- AONAME = aoTarget.name
147
- COU_AG_GSSOURCE = 'SETUPFILE' # since we have an AO
148
- GSRA, GSDEC = self.getCoords(aoTarget, requirePrecision=False)
149
- acqTSF.COU_AG_PMA, acqTSF.COU_AG_PMD = self.getPMCoords(
150
- aoTarget)
151
- # Case of CIAO to be implemented...based on v and k magnitudes?
152
- COU_GS_MAG = float(aoTarget.FLUX_V)
153
-
154
- # Guide Star
155
- gsTarget = ob.get(observationConfiguration, 'GSTarget')
156
- if gsTarget != None and aoTarget == None:
157
- COU_AG_SOURCE = 'SETUPFILE' # since we have an GS
158
- GSRA, GSDEC = self.getCoords(gsTarget, requirePrecision=False)
159
- acqTSF.COU_AG_PMA, acqTSF.COU_AG_PMD = self.getPMCoords(
160
- gsTarget)
161
- COU_GS_MAG = float(gsTarget.FLUX_V)
162
-
163
- # LST interval
164
- try:
165
- obsConstraint = observationConfiguration.observationConstraints
166
- LSTINTERVAL = obsConstraint.LSTinterval
167
- except:
168
- LSTINTERVAL = None
169
-
170
- # Constraints
171
- obConstraints.name = 'Aspro-created constraints'
172
- skyTransparencyMagLimits = {"AT": 3, "UT": 5}
173
- if acqTSF.SEQ_INS_SOBJ_MAG < skyTransparencyMagLimits[tel]:
174
- obConstraints.skyTransparency = 'Variable, thin cirrus'
53
+ wideMode = self.getAcquisitionType() == "wide"
54
+ onaxisMode = self.isCalibrator(OBJTYPE) or self.getAcquisitionType() == "onaxis"
55
+ offaxisMode = self.isScience(OBJTYPE) and self.getAcquisitionType() == "offaxis"
56
+
57
+ # skip calib with wide mode
58
+ # According to templat manual P112 : Calibrations of the interferometric transfer function are thus not needed and not offered for this mode
59
+ if OBJTYPE == 'CALIBRATOR' and wideMode:
60
+ ui.addToLog("Calibrator ignored with wide mode")
175
61
  else:
176
- obConstraints.skyTransparency = 'Clear'
177
- # FIXME: error (OB): "Phase 2 constraints must closely follow what was requested in the Phase 1 proposal.
178
-
179
- # The seeing value allowed for this OB is >= java0x0 arcsec."
180
- # FIXME REPLACE SEEING THAT IS NO MORE SUPPORTED
181
- # obConstraints.seeing = 1.0
182
-
183
- # FIXME: default values NOT IN ASPRO!
184
- # constaints.airmass = 5.0
185
- # constaints.fli = 1
186
-
187
- # compute dit, ndit, nexp
188
- dit = self.getDit(tel, acqTSF.INS_SPEC_RES, acqTSF.INS_SPEC_POL,
189
- acqTSF.SEQ_INS_SOBJ_MAG, dualField, showWarning=(p2container == None))
190
- ndit = 300 / dit
191
- if ndit < 10:
192
- ndit = 10
193
- if ndit > 300:
194
- ndit = 300
195
- ndit = int(ndit) # must be integer
196
- exptime = int(ndit * dit + 40) # 40 sec overhead by exp
197
- nexp = (1800 - 900) / exptime
198
- nexp = int(nexp)
199
- ui.addToLog(
200
- 'number of exposures to reach 1800 s per OB is ' + str(nexp))
201
- if nexp < 3:
202
- nexp = 3 # min is O S O
203
- # recompute ndit
204
- exptime = (1800 - 900) / nexp
205
- ndit = (exptime - 40) / dit
206
- ndit = int(ndit)
62
+
63
+ # dualField is true if FT Target is defined, else false
64
+ ftTarget = ob.get(observationConfiguration, "FTTarget")
65
+ if ftTarget:
66
+ dualField = True
67
+ else:
68
+ dualField = False
69
+
70
+ # create keywords storage objects
71
+ acqTSF = TSF(self, self.getGravityAcqTemplateName(
72
+ ob, OBJTYPE, dualField))
73
+ obsTSF = TSF(self, self.getGravityObsTemplateName(
74
+ ob, OBJTYPE, dualField))
75
+
76
+ obConstraints = OBConstraints(self)
77
+
78
+ # Check SPEC_RES from instrumentMode and set SPEC_POL except for single_offaxis ( missing keyword INS_SPEC_RES)
79
+ if offaxisMode and not dualField:
80
+ for res in ("LOW","MED","HIGH"):
81
+ if res in instrumentMode[0:len(res)]:
82
+ ins_spec_res = res
83
+ else:
84
+ ins_spec_res = instrumentMode
85
+ for res in self.getRange(acqTSF.getName(), "INS.SPEC.RES"):
86
+ if res in instrumentMode[0:len(res)]:
87
+ ins_spec_res = res
88
+ acqTSF.INS_SPEC_RES = ins_spec_res
89
+ acqTSF.INS_SPEC_POL = ins_spec_pol
90
+
91
+ acqTSF.INS_FT_POL = ins_spec_pol
92
+
93
+ scienceTarget = observationConfiguration.SCTarget
94
+
95
+ obTarget = OBTarget(self, scienceTarget)
96
+
97
+ # define target
98
+ acqTSF.SEQ_INS_SOBJ_NAME = obTarget.name
99
+
100
+ # Set baseline interferometric array code (should be a keywordlist)
101
+ acqTSF.ISS_BASELINE = [self.getBaselineCode(ob)]
102
+
103
+ self.checkIssVltiType(acqTSF)
104
+
105
+ # define some default values
106
+ acqTSF.SEQ_INS_SOBJ_DIAMETER = float(
107
+ self.get(scienceTarget, "DIAMETER", 0.0))
108
+
109
+ # Retrieve Fluxes
110
+ acqTSF.COU_GS_MAG = self.getFlux(scienceTarget, "V")
111
+ acqTSF.SEQ_INS_SOBJ_MAG = self.getFlux(scienceTarget, "K")
112
+ if not dualField or wideMode:
113
+ acqTSF.SEQ_INS_SOBJ_HMAG = self.getFlux(scienceTarget, "H")
114
+
115
+ # setup some default values, to be changed below
116
+ GSRA = '00:00:00.000'
117
+ GSDEC = '00:00:00.000'
118
+
119
+ # if FT Target is not ScTarget, we are in dual-field (TBD)
120
+ ftTarget = ob.get(observationConfiguration, "FTTarget")
121
+ if ftTarget != None:
122
+ acqTSF.SEQ_FT_ROBJ_NAME = ftTarget.name
123
+ acqTSF.SEQ_FT_ROBJ_MAG = self.getFlux(ftTarget, "K")
124
+ acqTSF.SEQ_FT_ROBJ_HMAG = self.getFlux(ftTarget, "H")
125
+
126
+ # test arcseconds distance in dual field or wide mode (GRAVITY_TemplateManual_P112 values)
127
+ if tel == "UT":
128
+ if wideMode:
129
+ SCtoREFmaxDist = 30
130
+ SCtoREFminDist = 2
131
+ elif offaxisMode:
132
+ SCtoREFmaxDist = 2
133
+ SCtoREFminDist = .27
134
+ else:
135
+ SCtoREFmaxDist = .6
136
+ SCtoREFminDist = 0
137
+ else:
138
+ if wideMode:
139
+ SCtoREFmaxDist = 30
140
+ SCtoREFminDist = 4
141
+ elif offaxisMode:
142
+ SCtoREFmaxDist = 4
143
+ SCtoREFminDist = 1.17
144
+ else:
145
+ SCtoREFmaxDist = 2.7
146
+ SCtoREFminDist = 0
147
+
148
+ FTRA, FTDEC = self.getCoords(ftTarget)
149
+ dualFieldSeparation = self.getSkySeparation(obTarget.ra, obTarget.dec, FTRA, FTDEC)
150
+ dualFieldSeparation = dualFieldSeparation.arcsec
151
+ if dualFieldSeparation <= SCtoREFminDist or dualFieldSeparation >= SCtoREFmaxDist:
152
+ raise ValueError(f"Dual-Field separation of two stars {dualFieldSeparation:.3f}'' is out of range [{SCtoREFminDist}'', {SCtoREFmaxDist}''], Please correct.")
153
+ else:
154
+ ui.addToLog(f"Dual-Field separation of two stars is {dualFieldSeparation:.3f}''")
155
+
156
+ # Provide FT position
157
+ if wideMode:
158
+ acqTSF.SEQ_FT_ROBJ_ALPHA = FTRA
159
+ acqTSF.SEQ_FT_ROBJ_DELTA = FTDEC
160
+ else:
161
+ # compute x,y between science and ref beams and set X,Y (mas) keywords:
162
+ dualFieldOffset = self.getSkyOffset(obTarget.ra, obTarget.dec, FTRA, FTDEC)
163
+ acqTSF.SEQ_INS_SOBJ_X = dualFieldOffset[0].mas
164
+ acqTSF.SEQ_INS_SOBJ_Y = dualFieldOffset[1].mas
165
+
166
+ FTPMA, FTPMD = self.getPMCoords(ftTarget)
167
+ acqTSF.SEQ_FT_ROBJ_PMA = FTPMA
168
+ acqTSF.SEQ_FT_ROBJ_PMD = FTPMD
169
+
170
+ FTPARALLAX = self.getPARALLAX(ftTarget)
171
+ acqTSF.SEQ_FT_ROBJ_PARALLAX = FTPARALLAX
172
+
173
+ acqTSF.SEQ_FT_MODE = "AUTO"
174
+
175
+ # AO target
176
+ aoTarget = ob.get(observationConfiguration, "AOTarget")
177
+ if aoTarget != None:
178
+ AONAME = aoTarget.name
179
+ acqTSF.COU_AG_GSSOURCE = 'SETUPFILE' # since we have an AO
180
+ acqTSF.COU_AG_ALPHA, acqTSF.COU_AG_DELTA = self.getCoords(
181
+ aoTarget, requirePrecision=False)
182
+ acqTSF.COU_AG_PMA, acqTSF.COU_AG_PMD = self.getPMCoords(
183
+ aoTarget)
184
+ # Case of CIAO to be implemented...based on v and k magnitudes?
185
+ acqTSF.COU_GS_MAG = float(aoTarget.FLUX_V)
186
+
187
+ # Guide Star
188
+ gsTarget = ob.get(observationConfiguration, 'GSTarget')
189
+ if gsTarget != None and aoTarget == None:
190
+ acqTSF.COU_AG_SOURCE = 'SETUPFILE' # since we have an GS
191
+ acqTSF.COU_AG_ALPHA, acqTSF.COU_AG_DELTA = self.getCoords(
192
+ gsTarget, requirePrecision=False)
193
+ acqTSF.COU_AG_PMA, acqTSF.COU_AG_PMD = self.getPMCoords(
194
+ gsTarget)
195
+ acqTSF.COU_GS_MAG = float(gsTarget.FLUX_V)
196
+
197
+ # LST interval
198
+ try:
199
+ obsConstraint = observationConfiguration.observationConstraints
200
+ LSTINTERVAL = obsConstraint.LSTinterval
201
+ except:
202
+ LSTINTERVAL = None
203
+
204
+ # Constraints
205
+ obConstraints.name = 'Aspro-created constraints'
206
+ skyTransparencyMagLimits = {"AT": 3, "UT": 5}
207
+ if acqTSF.SEQ_INS_SOBJ_MAG < skyTransparencyMagLimits[tel]:
208
+ obConstraints.skyTransparency = 'Variable, thin cirrus'
209
+ else:
210
+ obConstraints.skyTransparency = 'Clear'
211
+ # FIXME: error (OB): "Phase 2 constraints must closely follow what was requested in the Phase 1 proposal.
212
+
213
+ # The seeing value allowed for this OB is >= java0x0 arcsec."
214
+ # FIXME REPLACE SEEING THAT IS NO MORE SUPPORTED
215
+ # obConstraints.seeing = 1.0
216
+
217
+ # FIXME: default values NOT IN ASPRO!
218
+ # constaints.airmass = 5.0
219
+ # constaints.fli = 1
220
+
221
+
222
+
223
+ # compute dit, ndit, nexp
224
+ dit = self.getDit(tel, ins_spec_res, ins_spec_pol,
225
+ acqTSF.SEQ_INS_SOBJ_MAG, dualField, targetName=scienceTarget.name.strip(), showWarning=(p2container == None))
226
+ ndit = 300 / dit
207
227
  if ndit < 10:
208
228
  ndit = 10
209
- ui.addToLog(
210
- "**Warning**, OB NDIT has been set to min value=%d, but OB will take longer than 1800 s" % (
211
- ndit))
212
- nexp %= 40
213
- sequence = 'O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O'
214
- my_sequence = sequence[0:2 * nexp]
215
- # and store computed values in obsTSF
216
- obsTSF.DET2_DIT = str(dit)
217
- obsTSF.DET2_NDIT_OBJECT = ndit
218
- obsTSF.DET2_NDIT_SKY = ndit
219
- obsTSF.SEQ_OBSSEQ = my_sequence
220
- obsTSF.SEQ_SKY_X = 2000
221
- obsTSF.SEQ_SKY_Y = 2000
222
-
223
- # then call the ob-creation using the API if p2container exists.
224
- if p2container == None:
225
- ui.addToLog(obTarget.name +
226
- " ready for p2 upload (details logged)")
227
- ui.addToLog(obTarget, False)
228
- ui.addToLog(obConstraints, False)
229
- ui.addToLog(acqTSF, False)
230
- ui.addToLog(obsTSF, False)
231
- else:
232
- self.createGravityOB(p2container, obTarget, obConstraints, acqTSF, obsTSF, OBJTYPE, instrumentMode,
233
- DIAMETER, COU_AG_GSSOURCE, GSRA, GSDEC, COU_GS_MAG, dualField, dualFieldDistance,
234
- SEQ_FT_ROBJ_NAME, SEQ_FT_ROBJ_MAG, SEQ_FT_ROBJ_DIAMETER, SEQ_FT_ROBJ_VIS,
235
- LSTINTERVAL)
236
- ui.addToLog(obTarget.name + " submitted on p2")
237
-
238
- def formatRangeTable(self):
239
- rangeTable = self.getRangeTable()
240
- buffer = ""
241
- for l in rangeTable.keys():
242
- buffer += l + "\n"
243
- for k in rangeTable[l].keys():
244
- constraint = rangeTable[l][k]
245
- keys = constraint.keys()
246
- buffer += ' %30s :' % (k)
247
- if 'min' in keys and 'max' in keys:
248
- buffer += ' %f ... %f ' % (
249
- constraint['min'], constraint['max'])
250
- elif 'list' in keys:
251
- buffer += str(constraint['list'])
252
- elif "spaceseparatedlist" in keys:
253
- buffer += ' ' + " ".join(constraint['spaceseparatedlist'])
254
- if 'default' in keys:
255
- buffer += ' (' + str(constraint['default']) + ')'
229
+ if ndit > 300:
230
+ ndit = 300
231
+ ndit = int(ndit) # must be integer
232
+ exptime = int(ndit * dit + 40) # 40 sec overhead by exp
233
+ nexp = (1800 - 900) / exptime
234
+ nexp = int(nexp)
235
+ ui.addToLog(
236
+ 'number of exposures to reach 1800 s per OB is ' + str(nexp))
237
+ if nexp < 3:
238
+ nexp = 3 # min is O S O
239
+ # recompute ndit
240
+ exptime = (1800 - 900) / nexp
241
+ ndit = (exptime - 40) / dit
242
+ ndit = int(ndit)
243
+ if ndit < 10:
244
+ ndit = 10
245
+ ui.addToLog(
246
+ "**Warning**, OB NDIT has been set to min value=%d, but OB will take longer than 1800 s" % (
247
+ ndit))
248
+ nexp %= 40
249
+ sequence = 'O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O S O O'
250
+ my_sequence = sequence[0:2 * nexp]
251
+ # and store computed values in obsTSF
252
+ obsTSF.DET2_DIT = str(dit)
253
+ obsTSF.DET2_NDIT_OBJECT = ndit
254
+ obsTSF.DET2_NDIT_SKY = ndit
255
+ obsTSF.SEQ_OBSSEQ = my_sequence
256
+
257
+ obsTSF.SEQ_SKY_X = 2000
258
+ obsTSF.SEQ_SKY_Y = 2000
259
+
260
+ # then call the ob-creation using the API if p2container exists.
261
+ if p2container == None:
262
+ ui.addToLog(obTarget.name +
263
+ " ready for p2 upload (details logged)")
264
+ ui.addToLog(obTarget, False)
265
+ ui.addToLog(obConstraints, False)
266
+ ui.addToLog(acqTSF, False)
267
+ ui.addToLog(obsTSF, False)
256
268
  else:
257
- buffer += ' -no default-'
258
- buffer += "\n"
259
- return buffer
269
+ self.createOB(p2container, obTarget, obConstraints, OBJTYPE, instrumentMode,
270
+ LSTINTERVAL, [acqTSF, obsTSF])
260
271
 
261
272
  def formatDitTable(self):
262
273
  ditTable = self.getDitTable()
@@ -284,110 +295,31 @@ class Gravity(VltiInstrument):
284
295
  tel, Kut + Kdf)
285
296
  return buffer
286
297
 
287
- def getGravityTemplateName(self, templateType, dualField, OBJTYPE):
288
- objType = "calibrator"
289
- if OBJTYPE and "SCI" in OBJTYPE:
290
- objType = "exp"
291
- field = "single"
298
+ def getGravityObsTemplateName(self, ob, OBJTYPE, dualField):
299
+ return self.getGravityTemplateName("obs", ob, OBJTYPE, dualField)
292
300
 
293
- if dualField:
294
- field = "dual"
295
- if OBJTYPE:
296
- return "_".join((self.getName(), field, templateType, objType))
297
- return "_".join((self.getName(), field, templateType))
301
+ def getGravityAcqTemplateName(self, ob, OBJTYPE, dualField):
302
+ return self.getGravityTemplateName("acq", ob, OBJTYPE, dualField)
298
303
 
299
- def getGravityObsTemplateName(self, OBJTYPE, dualField=False):
300
- return self.getGravityTemplateName("obs", dualField, OBJTYPE)
304
+ def getGravityTemplateName(self, templateType, ob, OBJTYPE, dualField):
301
305
 
302
- def getGravityAcqTemplateName(self, dualField=False, OBJTYPE=None):
303
- return self.getGravityTemplateName("acq", dualField, OBJTYPE)
306
+ dualValue = {True: "dual", False: "single"}
307
+ objValue = {"SCIENCE": "exp", "CALIBRATOR": "calibrator"}
304
308
 
305
- def createGravityOB(
306
- self, p2container, obTarget, obConstraints, acqTSF, obsTSF, OBJTYPE, instrumentMode,
307
- DIAMETER, COU_AG_GSSOURCE, GSRA, GSDEC, COU_GS_MAG, dualField, dualFieldDistance, SEQ_FT_ROBJ_NAME,
308
- SEQ_FT_ROBJ_MAG,
309
- SEQ_FT_ROBJ_DIAMETER, SEQ_FT_ROBJ_VIS, LSTINTERVAL):
310
-
311
- api = self.facility.getAPI()
312
- ui = self.ui
313
- ui.setProgress(0.1)
314
-
315
- # TODO compute value
316
- VISIBILITY = 1.0
317
-
318
- # everything seems OK
319
- # create new OB in container:
320
- # TODO use a common function for next lines
321
- goodName = re.sub('[^A-Za-z0-9]+', '_', acqTSF.SEQ_INS_SOBJ_NAME)
322
- OBS_DESCR = OBJTYPE[0:3] + '_' + goodName + '_GRAVITY_' + \
323
- acqTSF.ISS_BASELINE[0] + '_' + instrumentMode
324
-
325
- ob, obVersion = api.createOB(p2container.containerId, OBS_DESCR)
326
- obId = ob['obId']
327
-
328
- # we use obId to populate OB
329
- ob['obsDescription']['name'] = OBS_DESCR[0:min(len(OBS_DESCR), 31)]
330
- ob['obsDescription']['userComments'] = self.getA2p2Comments()
331
- # ob['obsDescription']['InstrumentComments'] = 'AO-B1-C2-E3' #should be
332
- # a list of alternative quadruplets!
333
-
334
- # copy target info
335
- targetInfo = obTarget.getDict()
336
- for key in targetInfo:
337
- ob['target'][key] = targetInfo[key]
338
-
339
- # copy constraints info
340
- constraints = obConstraints.getDict()
341
- for k in constraints:
342
- ob['constraints'][k] = constraints[k]
343
-
344
- ui.addToLog("Save ob to p2:\n%s" % ob, False)
345
- ob, obVersion = api.saveOB(ob, obVersion)
346
-
347
- # time constraints if present
348
- self.saveSiderealTimeConstraints(api, obId, LSTINTERVAL)
349
-
350
- ui.setProgress(0.2)
351
-
352
- # then, attach acquisition template(s)
353
- tpl, tplVersion = api.createTemplate(
354
- obId, self.getGravityAcqTemplateName(dualField=dualField))
355
- # and put values
356
- # start with acqTSF ones and complete manually missing ones
357
- values = acqTSF.getDict()
358
- values.update({
359
- 'SEQ.INS.SOBJ.DIAMETER': DIAMETER,
360
- 'SEQ.INS.SOBJ.VIS': VISIBILITY,
361
- 'COU.AG.GSSOURCE': COU_AG_GSSOURCE,
362
- 'COU.AG.ALPHA': GSRA,
363
- 'COU.AG.DELTA': GSDEC,
364
- 'COU.GS.MAG': round(COU_GS_MAG, 3),
365
- 'TEL.TARG.PARALLAX': 0.0
366
- })
367
- if dualField:
368
- values.update({'SEQ.INS.SOBJ.X': dualFieldDistance[0],
369
- 'SEQ.INS.SOBJ.Y': dualFieldDistance[1],
370
- 'SEQ.FT.ROBJ.NAME': SEQ_FT_ROBJ_NAME,
371
- 'SEQ.FT.ROBJ.MAG': round(SEQ_FT_ROBJ_MAG, 3),
372
- 'SEQ.FT.ROBJ.DIAMETER': SEQ_FT_ROBJ_DIAMETER,
373
- 'SEQ.FT.ROBJ.VIS': SEQ_FT_ROBJ_VIS,
374
- 'SEQ.FT.MODE': "AUTO"})
375
- tpl, tplVersion = api.setTemplateParams(obId, tpl, values, tplVersion)
376
- ui.setProgress(0.3)
377
-
378
- tpl, tplVersion = api.createTemplate(
379
- obId, self.getGravityObsTemplateName(OBJTYPE, dualField))
380
- ui.setProgress(0.4)
381
-
382
- # put values. they are the same except for dual obs science (?)
383
- values = obsTSF.getDict()
384
- if dualField and OBJTYPE == 'SCIENCE':
385
- # not included in our general TSF
386
- values.update({'SEQ.RELOFF.X': "0.0", 'SEQ.RELOFF.Y': "0.0"})
387
- tpl, tplVersion = api.setTemplateParams(obId, tpl, values, tplVersion)
388
- ui.setProgress(0.5)
389
-
390
- # verify OB online
391
- response, _ = api.verifyOB(obId, True)
392
- ui.setProgress(1.0)
393
- self.showP2Response(response, ob, obId)
309
+ # Add : name , <dual|single>, <obs|acq>, [objValue]
310
+ items = [self.getName()]
311
+ # Add dual or single for SCIENCE or single for other OBJTYPES
312
+ items.append(dualValue[dualField and self.isScience(OBJTYPE)])
313
+ # Add acquisitionType (or onaxis for CAL) after P112 if acq
314
+ if templateType == "acq" and ob.getPeriod() >= 112:
315
+ if self.isScience(OBJTYPE):
316
+ items.append(self.getAcquisitionType())
317
+ else:
318
+ items.append("onaxis")
319
+ # Add acq or obs
320
+ items.append(templateType)
321
+ # Add objValue if obs
322
+ if templateType == "obs":
323
+ items.append(objValue[OBJTYPE])
324
+
325
+ return "_".join([i for i in items if i is not None])+".tsf"