Commits

C. Enrique Garcia Dabo authored and Ville Suoranta committed d992c3455d1 Merge
Pull request #878: CAS-14458

Merge in CASA/casa6 from CAS-14458 to release/6.6.6 * commit '508d4cb71db113b424bdbb3f04a86187b2605e87': Add test cases for expected failures in gencal Add test with the new functionality to create a caltable from ALMA antenna positions JSON file CAS-14253: Use input JSON file to compute the ALMA antenna position corrections CAS-14253: Describe the infile parameter for the JSON ALMA antenna positions case

casatasks/src/private/correct_ant_posns_alma.py

Deleted
1 -from __future__ import absolute_import
2 -import time
3 -import numpy as np
4 -import sys
5 -
6 -from casatasks.private.casa_transition import is_CASA6
7 -if is_CASA6:
8 - from casatools import table
9 - from casatasks import casalog
10 -
11 - tb_tool = table( )
12 -else:
13 - from taskinit import *
14 -
15 - (tb_tool,) = gentools(['tb'])
16 -
17 -def _fetch_tmcdb_info(ant_names, obs_time):
18 - use_soap = False
19 - if use_soap:
20 - response = query_tmcdb_antennas_soap(ant_names, obs_time)
21 - return process_tmcdb_response_soap_for_gencal(response)
22 - else:
23 - response = query_tmcdb_antennas_rest(ant_names, obs_time)
24 - return process_tmcdb_response_rest_for_gencal(ant_names, response)
25 -
26 -
27 -def query_tmcdb_antennas_rest(ant_names, timestamp):
28 - """
29 - Queries the new REST web service for positions of a list of antennas at a given
30 - timestamp.
31 -
32 - REST service deployed for testing https://2018may.asa-test.alma.cl/antenna-position
33 - Service doc:
34 - https://bitbucket.sco.alma.cl/projects/ALMA/repos/almasw/browse/CONTROL-SERVICES/PositionsService
35 - Swagger TMCDB Positions API doc:
36 - https://2018may.asa-test.alma.cl/antenna-position/swagger-ui.html
37 -
38 - Example query:
39 - https://2018may.asa-test.alma.cl/antenna-position/position/antenna?configuration=CURRENT.AOS&antenna=DV10&timestamp=2015-04-19T16:53:54.000
40 -
41 - :param ant_names: list of antenna names as strings
42 - :param timestamp: timestamp specification string (in '2017-01-01T16:53:54.000' format)
43 -
44 - :returns: list of per antenna responses as retrieved from the web service
45 - """
46 - import time
47 - import requests
48 -
49 - TEST_HOSTNAME = 'https://2018may.asa-test.alma.cl'
50 -
51 - hostname = TEST_HOSTNAME
52 - port = 443
53 - api = 'antenna-position/position/antenna'
54 - # To have the .milliseconds (which is not included in the MS obs_time), like:
55 - # 2015-04-19T16:53:54.000
56 - tstamp_ms = '{}.000'.format(timestamp)
57 - ant_responses = []
58 -
59 - casalog.post('Querying TMC DB, positions for these antennas: {0}, at time: {1}'.
60 - format(ant_names, tstamp_ms), 'INFO')
61 - time_start = time.time()
62 - try:
63 - for aname in ant_names:
64 - url = '{}:{}/{}?antenna={}&timestamp={}'.format(hostname, port, api, aname,
65 - tstamp_ms)
66 - resp = requests.get(url)
67 - casalog.post('Queried antenna "{0}". Response status: {1}. Response text: {2}'.
68 - format(aname, resp.status_code, resp.text), 'DEBUG2')
69 - ant_responses.append(resp)
70 -
71 - time_end = time.time()
72 - casalog.post('Got responses from TMC DB. Took {0}s'.format(time_end - time_start))
73 - except RuntimeError as exc:
74 - casalog.post('Exception while querying the TMC DB for antenna positions information:'
75 - '{0}'.format(exc), 'ERROR')
76 - raise
77 -
78 - return ant_responses
79 -
80 -
81 -def process_tmcdb_response_rest_for_gencal(ant_names, responses):
82 - """
83 - Takes a list of response from the TMCDB Positions service (REST)
84 - and produces a list of antenna names and a list of their position
85 - correction parameters.
86 -
87 - :param resp: names of the antennas
88 - :param resp: response objects from web service (some might be error or
89 - incomplete)
90 -
91 - :returns: a tuple with three elements. The tuple has
92 - as first element a list of antenna names as strings, and as
93 - second element a vector of positions (as Bx, By, Bz) for
94 - every antenna. The third element holds the positions of the
95 - corresponding pads.
96 - """
97 -
98 - def get_ant_pad_position(ant_name, resp):
99 - import json
100 - pos_found = False
101 - if 200 == resp.status_code:
102 - json_resp = json.loads(resp.text)
103 - ant_pos = json_resp['antenna']['position']
104 - ant_position = np.asarray([ant_pos['x'], ant_pos['y'], ant_pos['z']],
105 - dtype=float)
106 - pad_pos = json_resp['pad']['position']
107 - pad_position = np.asarray([pad_pos['x'], pad_pos['y'], pad_pos['z']],
108 - dtype=float)
109 - pos_found = True
110 - else:
111 - casalog.post('Did not find position parameters for antenna {0}. '
112 - 'Status code: {1}. Response: {2}'.
113 - format(ant_name, resp.status_code, resp.text), 'WARN')
114 - ant_position = np.array([0, 0, 0], dtype=float)
115 - pad_position = np.array([0, 0, 0], dtype=float)
116 -
117 - return (pos_found, ant_position, pad_position)
118 -
119 - casalog.post('Got these responses from ALMA TMC DB: {}'.
120 - format(responses), 'DEBUG2')
121 - accum_ant_names = []
122 - accum_positions = []
123 - accum_pad_positions = []
124 - cnt_pos_found = 0
125 - for aname, resp in zip(ant_names, responses):
126 - accum_ant_names.append(aname)
127 - (found, ant_position, pad_position) = get_ant_pad_position(aname, resp)
128 - if found:
129 - cnt_pos_found += 1
130 - accum_positions.append(ant_position)
131 - accum_pad_positions.append(pad_position)
132 -
133 - casalog.post('Queried ALMA TMC DB and found position parameters for {} antennas out of '
134 - '{} requested in total '.
135 - format(cnt_pos_found, len(accum_ant_names)), 'INFO')
136 -
137 - return (accum_ant_names, accum_positions, accum_pad_positions)
138 -
139 -
140 -def query_tmcdb_antennas_soap(ant_names, timestamp):
141 - """
142 - Retrieves information for a list of antennas, at a given timestamp,
143 - by querying the ALMA TMC DB AntennaPad web service.
144 - See service documentation:
145 - https://ictwiki.alma.cl/twiki/bin/view/SoftOps/TMCDBAntennaPadService
146 -
147 - TODO: deprecate and remove SOAP stuff once the auto gencal mode is validated with
148 - information from the TMCDB. This stuff is left here now for testing purposes - cross-
149 - comparison of SOAP and REST service.
150 -
151 - :param ant_names: list of antenna names as strings
152 - :param timestamp: timestamp specification string (in
153 - '2017-01-01T16:53:54' format)
154 -
155 - :returns: response as retrieved from the web service
156 - :raises urllib2.URLError: if network or server issues
157 - """
158 -
159 - SRV_WSDL_URL = 'http://asa.alma.cl/axis2/services/TMCDBAntennaPadService?wsdl'
160 -
161 - ALMA_CONFIG_NAME = 'CURRENT.AOS'
162 -
163 - import time
164 - from suds.client import Client
165 -
166 - # build a string of space-separated antenna names
167 - try:
168 - ant_names_str = ' '.join(ant for ant in ant_names)
169 - except RuntimeError as exc:
170 - raise AttributeError('Error in antenna names strings: {0}. ant_names must '
171 - 'be a list of strings. Got: {1}'.format(exc, ant_names))
172 - config_name = ALMA_CONFIG_NAME
173 - casalog.post('Querying TMC DB, positions for configuration: {0}, for these '
174 - 'antennas: {1}, at time: {2}'.
175 - format(config_name, ant_names_str, timestamp), 'INFO')
176 - time_start = time.time()
177 -
178 - wscli = Client(SRV_WSDL_URL)
179 - resp = None
180 - try:
181 - resp = wscli.service.getAntennaPositions(configurationName=config_name,
182 - antennaNames=ant_names_str,
183 - timestamp=timestamp)
184 - time_end = time.time()
185 - casalog.post('Got response from TMC DB. Took {0}s'.format(time_end - time_start))
186 - except AttributeError as exc:
187 - import traceback
188 - traceback.print_exc(file=sys.stdout)
189 - raise RuntimeError('Got a response back from the server but it is '
190 - 'wrong or could not be parsed as a valid SOAP '
191 - 'response. This occurs for example when a wrong '
192 - 'timestamp is given. Response object: {0}. '
193 - 'Error description:'.
194 - format(resp, exc))
195 -
196 - return resp
197 -
198 -
199 -def process_tmcdb_response_soap_for_gencal(resp):
200 - """
201 - Takes a response from the TMC DB AntennaPad service and produces a
202 - list of antenna names and a list of their position correction
203 - parameters.
204 -
205 - :param resp: response object from web service
206 -
207 - :returns: a tuple with three elements. The tuple has
208 - as first element a list of antenna names as strings, and as
209 - second element a vector of positions (as Bx, By, Bz) for
210 - every antenna. The third element holds the positions of the
211 - corresponding pads.
212 - """
213 -
214 - def check_pos(pos, ant_idx):
215 - """
216 - Basic sanity checks on a position object
217 -
218 - :param pos: position object as returned for one antenna by the
219 - TMC DB AntennaPad service.
220 - :param ant_idx: index of the antenna
221 - """
222 - if not pos:
223 - casalog.post('Empty position object received for antenna with '
224 - 'index {}'.format(ant_idx), 'ERROR')
225 -
226 - try:
227 - pos.completion
228 - except AttributeError as exc:
229 - raise RuntimeError('Got response but with only a single '
230 - 'completion object: {0}. errorList: {1}. '
231 - 'Antenna index: {2}, exception: {3}'.
232 - format(pos, pos.errorList, ant_idx, exc))
233 -
234 - def get_ant_pad_position(pos):
235 - """
236 - Get the position parameters for an antenna from a position object
237 -
238 - :param pos: position object as returned for one antenna by the
239 - TMC DB AntennaPad service.
240 -
241 - :returns: tuple: position found, position as a list [x,y,z], pad
242 - position as a list [x, y, z]
243 - """
244 -
245 - pos_found = False
246 - # when the antenna is not found
247 - if not pos.completion.status == 'true' or not pos.position:
248 - casalog.post('Did not find position parameters for antenna {0}. '
249 - 'Error description: {1}'.
250 - format(pos.name, pos.completion.errorList), 'WARN')
251 - ant_position = np.array([0, 0, 0], dtype=float)
252 - pad_position = np.array([0, 0, 0], dtype=float)
253 - else:
254 - ant_position = np.asarray([pos.position.x, pos.position.y,
255 - pos.position.z], dtype=float)
256 - pad_position = np.asarray([pos.pad.position.x, pos.pad.position.y,
257 - pos.pad.position.z], dtype=float)
258 - pos_found = True
259 -
260 - return (pos_found, ant_position, pad_position)
261 -
262 - if not resp:
263 - raise RuntimeError('No response received: {}'.format(resp))
264 - elif not resp.antennaPositionList or 0 == len(resp.antennaPositionList):
265 - raise RuntimeError('Response with no list: {}'.format(resp))
266 -
267 - casalog.post('Got this response from ALMA TMC DB: {}'.
268 - format(resp), 'DEBUG2')
269 -
270 - accum_ant_names = []
271 - accum_positions = []
272 - accum_pad_positions = []
273 - cnt_pos_found = 0
274 - for ant_idx, pos in enumerate(resp.antennaPositionList):
275 - check_pos(pos, ant_idx)
276 -
277 - accum_ant_names.append(pos.name)
278 - (found, ant_position, pad_position) = get_ant_pad_position(pos)
279 - if found:
280 - cnt_pos_found += 1
281 - accum_positions.append(ant_position)
282 - accum_pad_positions.append(pad_position)
283 -
284 - casalog.post('Queried ALMA TMC DB and found position parameters for {} antennas out of '
285 - '{} requested in total '.
286 - format(cnt_pos_found, len(accum_ant_names)), 'INFO')
287 -
288 - return (accum_ant_names, accum_positions, accum_pad_positions)
289 -
290 -
291 -def correct_ant_posns_alma(vis_name, print_offsets=False):
292 - """
293 - Implements the interface of correct_ant_posns with specific logic
294 - for ALMA. The parameters (third returned variable) are calculated
295 - from the the difference between the pad+antenna position found from
296 - the web service - the pad+antenna position found in the MS (ASDM).
297 -
298 - This produces a return error code as returned by correct_ant_posns()
299 - by capturing some common exceptions.
300 - """
301 -
302 - def get_ant_pad_names_posns(vis_name):
303 - """
304 - Find positions recorded in the MS (ASDM).
305 -
306 - :param vis_name: name of an MS
307 -
308 - :returns: a tuple: 1) list of antenna names from the MS, 2) list
309 - of pad/station names from the MS, 3) positions [x, y, z] of the
310 - antennas as recorded in the MS, 4) positions [x, y, z] of the
311 - pads/stations as recorded in the MS.
312 - """
313 - tb_tool.open(vis_name + '/ANTENNA')
314 - ant_names = tb_tool.getcol('NAME')
315 - pad_names = tb_tool.getcol('STATION')
316 - tb_tool.close()
317 -
318 - try:
319 - tb_tool.open(vis_name)
320 - if 'ASDM_ANTENNA' not in tb_tool.keywordnames():
321 - raise RuntimeError('The ANTENNA tables from the ASDM were not '
322 - 'transferred to the Measurement Set')
323 - if 'ASDM_STATION' not in tb_tool.keywordnames():
324 - raise RuntimeError('The ANTENNA and/or STATION tables from '
325 - 'the ASDM were not transferred to the '
326 - 'Measurement Set')
327 - tb_tool.close()
328 -
329 - tb_tool.open(vis_name + '/ASDM_ANTENNA')
330 - asdm_ant_pos = tb_tool.getcol('position')
331 - tb_tool.close()
332 -
333 - tb_tool.open(vis_name + '/ASDM_STATION')
334 - asdm_pad_pos = tb_tool.getcol('position')
335 - tb_tool.close()
336 -
337 - asdm_pad_pos = asdm_pad_pos[:, 0:asdm_ant_pos.shape[1]]
338 - except RuntimeError as exc:
339 - casalog.post('Could not find pad and antenna position information '
340 - 'from the ASDM_ANTENNA and ASDM_STATION subtables. '
341 - 'Defaulting to the POSITION column of the ANTENNA '
342 - 'subtable. This means that the parameters calculated '
343 - 'are most likely inaccurate. Error description: {0}'.
344 - format(exc), 'WARN')
345 - tb_tool.open(vis_name + '/ANTENNA')
346 - asdm_pad_pos = tb_tool.getcol('POSITION')
347 - tb_tool.close()
348 - tb_tool.open(vis_name + '/ASDM_ANTENNA')
349 - asdm_ant_pos = tb_tool.getcol('position')
350 - tb_tool.close()
351 -
352 - ant_posns_ms = map(list, zip(asdm_ant_pos[0], asdm_ant_pos[1],
353 - asdm_ant_pos[2]))
354 - pad_posns_ms = map(list, zip(asdm_pad_pos[0], asdm_pad_pos[1],
355 - asdm_pad_pos[2]))
356 - return (ant_names, pad_names, ant_posns_ms, pad_posns_ms)
357 -
358 - def get_time_range_from_obs(vis_name):
359 - tb_tool.open(vis_name + '/OBSERVATION')
360 - time_range = tb_tool.getcol('TIME_RANGE')
361 - tb_tool.close()
362 - return time_range
363 -
364 - def build_obs_time(time_range):
365 - """
366 - Produces an observation time string, picking the middle point in time
367 - between start and end of observation.
368 -
369 - :returns: time specification string formatted as for example
370 - 2011-11-13T04:10:12
371 - """
372 - obs_time = (time_range[0] + time_range[1]) / 2.0
373 - obs_time = ((obs_time / 86400.0) + 2400000.5 - 2440587.5) * 86400.0
374 - obs_time = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime(obs_time))
375 - return obs_time
376 -
377 - def calc_ant_params_from_positions(ant_names, ant_corr_posns, pad_posns,
378 - ant_posns_ms, pad_posns_ms):
379 - """
380 - Produces the antenna position correction offset parameters required by
381 - gencal. Uses positions from the TMCDB and the MS.
382 -
383 - :param ant_names: list of names of the antennas
384 - :param ant_corr_posns: antenna positions offsets from the TMCDB
385 - :param pad_posns: pad positions from the TMCDB
386 - :param ant_posns_ms: antenna position offsets recorded from the MS/ASDM
387 - :param pad_posns_ms: pad/station positions recorded from the MS/ASDM
388 -
389 - :returns: position correction parameters for the antennas listed in the
390 - first parameter
391 - """
392 -
393 - def calc_param_diff(name, ant_corr_pos, pad_pos, ant_pos_ms, pad_pos_ms):
394 - """
395 - Produce the correction parameters expected by gencal.
396 -
397 - :param name: antenna name
398 - :param ant_corr_pos: antenna position from the TMCDB
399 - :param pad_pos: pad position from the TMCDB
400 - :param ant_pos_ms: antenna position recorded from the MS/ASDM
401 - :param ant_pos_ms: pad position recorded from the MS/ASDM
402 -
403 - :returns: position correction parameters for one antenna
404 - (Bx, By, Bz)
405 - """
406 - if (pad_pos == pad_pos_ms).all():
407 - return calc_param_diff_same_pad_pos(name, ant_corr_pos, pad_pos, ant_pos_ms)
408 - else:
409 - return calc_param_diff_diff_pad_pos(name, ant_corr_pos, pad_pos, ant_pos_ms,
410 - pad_pos_ms)
411 -
412 - def calc_param_diff_same_pad_pos(name, ant_corr_pos, pad_pos, ant_pos_ms):
413 - """
414 - Calculate correction parameters for an antenna when the pad position has not
415 - changed, comparing between the info that was recorded in the MS and the current
416 - info from the TMC DB.
417 -
418 - Subtracts A (found from the TMCDB) - B (found in the MS), where
419 - A is: pad position + antenna position correction/vector
420 - B is: antenna position in MS
421 - to produce the correction parameters expected by gencal
422 -
423 - :param name: antenna name
424 - :param ant_corr_pos: antenna position from the TMCDB
425 - :param pad_pos: pad position from the TMCDB
426 - :param ant_pos_ms: antenna position from the MS/ASDM
427 - :param ant_pos_ms: pad position from the MS/ASDM
428 -
429 - :returns: position correction parameters for one antenna
430 - (Bx, By, Bz)
431 - """
432 - from math import sqrt, sin, cos, asin, atan2
433 -
434 - lat = (asin(pad_pos[2] / sqrt(pad_pos[0]**2 + pad_pos[1]**2 +
435 - pad_pos[2]**2)))
436 - lon = atan2(pad_pos[1], pad_pos[0])
437 -
438 - itrf_diff = ant_corr_pos - ant_pos_ms
439 - param = np.array([0, 0, 0], dtype=float)
440 - param[0] = (-sin(lon) * itrf_diff[0]
441 - - cos(lon) * sin(lat) * itrf_diff[1]
442 - + cos(lon) * cos(lat) * itrf_diff[2])
443 - param[1] = (cos(lon) * itrf_diff[0]
444 - - sin(lon) * sin(lat) * itrf_diff[1]
445 - + sin(lon) * cos(lat) * itrf_diff[2])
446 - param[2] = (cos(lat) * itrf_diff[1] + sin(lat) * itrf_diff[2])
447 -
448 - return param
449 -
450 - def calc_param_diff_diff_pad_pos(name, ant_corr_pos, pad_pos, ant_pos_ms,
451 - pad_pos_ms):
452 - """
453 - Calculate correction parameters for an antenna when the pad position has changed.
454 - """
455 - from math import sqrt, cos, sin, asin, atan2
456 -
457 - lat = (asin(pad_pos[2] / sqrt(pad_pos[0]**2 + pad_pos[1]**2 + pad_pos[2]**2)))
458 - lon = atan2(pad_pos[1], pad_pos[0])
459 - pos_tot = np.array([0, 0, 0], dtype=float)
460 - pos_tot[0] = (ant_corr_pos[0] - sin(-lon) * pad_pos[0] -
461 - cos(-lon) * sin(-lat) * pad_pos[1] +
462 - cos(-lon) * cos(-lat) * pad_pos[2])
463 - pos_tot[1] = (ant_corr_pos[1] + cos(-lon) * pad_pos[0] -
464 - sin(-lon) * sin(-lat) * pad_pos[1] +
465 - sin(-lon) * cos(-lat) * pad_pos[2])
466 - pos_tot[2] = (ant_corr_pos[2] + cos(-lat) * pad_pos[1] +
467 - sin(-lat) * pad_pos[2])
468 -
469 - lat_ms = (asin(pad_pos_ms[2] / sqrt(pad_pos_ms[0]**2 + pad_pos_ms[1]**2 +
470 - pad_pos_ms[2]**2)))
471 - lon_ms = atan2(pad_pos_ms[1], pad_pos_ms[0])
472 - pos_tot_ms = np.array([0, 0, 0], dtype=float)
473 - pos_tot_ms[0] = (ant_pos_ms[0] - sin(-lon_ms) * pad_pos_ms[0] -
474 - cos(-lon_ms) * sin(-lat_ms) * pad_pos_ms[1] +
475 - cos(-lon_ms) * cos(-lat_ms) * pad_pos_ms[2])
476 - pos_tot_ms[1] = (ant_pos_ms[1] + cos(-lon_ms) * pad_pos_ms[0] -
477 - sin(-lon_ms) * sin(-lat_ms) * pad_pos_ms[1] +
478 - sin(-lon_ms) * cos(-lat_ms) * pad_pos_ms[2])
479 - pos_tot_ms[2] = (ant_pos_ms[2] + cos(-lat_ms) * pad_pos_ms[1] +
480 - sin(-lat_ms) * ant_pos_ms[2])
481 -
482 - pos_diff = pos_tot - pos_tot_ms
483 -
484 - # Errors fixed. Not clear at this point (201712) if/when they could be
485 - # retrieved from the database
486 - pos_err = np.array([1e-10, 1e-10, 1e-10])
487 -
488 - if (pos_err == 0).any():
489 - casalog.post('Note: some errors are null for an antenna position. Error '
490 - 'vector: {}'.format(pos_err), 'WARN')
491 -
492 - # Threshold fixed as the default value in analysisUtils:correctMyAntennaPositions
493 - thresh = 5
494 - norm_ratio = sqrt(((pos_diff / pos_err)**2).sum())
495 - if norm_ratio < thresh:
496 - casalog.post('Note: norm of position difference / errors ({}) is lower '
497 - 'than threshold ({}).'.format(norm_ratio, thresh), 'WARN')
498 -
499 - # calculate parameters for gencal
500 - par_tot = np.array([0, 0, 0], dtype=float)
501 - par_tot[0] = (pad_pos[0] - sin(lon) * ant_corr_pos[0] -
502 - cos(lon) * sin(lat) * ant_corr_pos[1] +
503 - cos(lon) * cos(lat) * ant_corr_pos[2])
504 - par_tot[1] = (pad_pos[1] + cos(lon) * ant_corr_pos[0] -
505 - sin(lon) * sin(lat) * ant_corr_pos[1] +
506 - sin(lon) * cos(lat) * ant_corr_pos[2])
507 - par_tot[2] = (pad_pos[2] + cos(lat) * ant_corr_pos[1] +
508 - sin(lat) * ant_corr_pos[2])
509 -
510 - par_tot_ms = np.array([0, 0, 0], dtype=float)
511 - par_tot_ms[0] = (pad_pos_ms[0] - sin(lon_ms) * ant_pos_ms[0] -
512 - cos(lon_ms) * sin(lat_ms) * ant_pos_ms[1] +
513 - cos(lon_ms) * cos(lat_ms) * ant_pos_ms[2])
514 - par_tot_ms[1] = (pad_pos_ms[1] + cos(lon_ms) * ant_pos_ms[0] -
515 - sin(lon_ms) * sin(lat_ms) * ant_pos_ms[1] +
516 - sin(lon_ms) * cos(lat_ms) * ant_pos_ms[2])
517 - par_tot_ms[2] = (pad_pos_ms[2] + cos(lat_ms) * ant_pos_ms[1] +
518 - sin(lat_ms) * ant_pos_ms[2])
519 -
520 - pos_par_diff = par_tot - par_tot_ms
521 -
522 - correction_thresh = 2e-3
523 - norm_par = np.linalg.norm(pos_par_diff)
524 - if norm_par >= correction_thresh:
525 - casalog.post('Note: the norm of the correction for antenna {} ({}) is '
526 - 'larger than {}.'.
527 - format(name, norm_par, correction_thresh), 'WARN')
528 -
529 - return pos_par_diff
530 -
531 - ant_params = []
532 - casalog.post('Antennas {0}\nPositions from TMC DB: {1},\nPositions '
533 - 'found in MS: {2}'.format(ant_names, ant_corr_posns, ant_posns_ms),
534 - 'DEBUG1')
535 -
536 - for idx, name in enumerate(ant_names):
537 - if np.all(ant_corr_posns[idx] == 0) and np.all(pad_posns[idx] == 0):
538 - param = np.array([0, 0, 0], dtype=float)
539 - else:
540 - param = calc_param_diff(name, ant_corr_posns[idx], pad_posns[idx],
541 - ant_posns_ms[idx], pad_posns_ms[idx])
542 - casalog.post('Antenna name: {}, pos offset: {}, pad pos: {}, pos MS: {}, '
543 - 'params: {} '.format(name, ant_corr_posns[idx], pad_posns[idx],
544 - ant_posns_ms[idx], param), 'DEBUG2')
545 - ant_params.extend(param)
546 -
547 - # build a string of comma-separated antenna names
548 - ant_names_str = ','.join(str(ant) for ant in ant_names)
549 -
550 - return (ant_names_str, ant_params)
551 -
552 - def print_ant_params_info(ant_names, ant_params):
553 - """
554 - Produce one line per antenna: name + 3 params, from the two values
555 - returned to gencal """
556 - pretty_pars = 'Parameters produced by antenna:\n'
557 - for idx, name in enumerate(ant_names):
558 - idx3 = idx*3
559 - pretty_pars += ('{0}: {1:14.5e} {2:14.5e} {3:14.5e}\n'.
560 - format(name, ant_params[idx3], ant_params[idx3+1],
561 - ant_params[idx3+2]))
562 - return pretty_pars
563 -
564 - time_range = get_time_range_from_obs(vis_name)
565 - ant_names, _pad_names, ant_posns_ms, pad_posns_ms = get_ant_pad_names_posns(vis_name)
566 - obs_time = build_obs_time(time_range)
567 -
568 - # the three element to return
569 - ret_code = 1
570 - ant_names_str = ''
571 - ant_params = []
572 - # Get corrected positions by querying the TMC database via the TMCDB
573 - # AntennaPad service
574 - try:
575 - import urllib2
576 - (ant_names_db, ant_corr_posns, pad_posns) = _fetch_tmcdb_info(ant_names, obs_time)
577 - if (ant_names_db != ant_names).any():
578 - raise RuntimeError('The antenna names found in the MS (which were '
579 - 'used to query the TMC DB) do not match the '
580 - 'names returned by the database.\nFound in MS: '
581 - '{0}.\nFound in TMC DB: {1}'.
582 - format(ant_names_db, ant_names))
583 - ant_names_str, ant_params = (
584 - calc_ant_params_from_positions(ant_names, ant_corr_posns,
585 - pad_posns, ant_posns_ms, pad_posns_ms))
586 - ret_code = 0
587 - except urllib2.URLError as exc:
588 - casalog.post('Network or server issue found while querying ALMA TMC DB '
589 - 'AntennaPad service. Details: {}'.format(exc), 'ERROR')
590 - ret_code = 2
591 - except RuntimeError as exc:
592 - casalog.post('Issue found while querying ALMA TMC DB AntennaPad '
593 - 'service. Details: {}'.format(exc), 'ERROR')
594 - ret_code = 1
595 -
596 - casalog.post(print_ant_params_info(ant_names, ant_params), 'DEBUG1')
597 - ant_names = ant_names_str.split(',')
598 - format_pars = '[' + ', '.join(['{:.5e}'.format(val) for val in ant_params]) + ']'
599 - casalog.post('Parameter values (FPARAM) produced for gencal, using position information '
600 - 'retrieved from the ALMA TMC DB:\n{0}'.format(format_pars), 'INFO')
601 -
602 - return [ret_code, ant_names_str, ant_params]

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut