Coverage for /wheeldirectory/casa-6.7.0-12-py3.10.el8/lib/py/lib/python3.10/site-packages/casatasks/private/task_listsdm.py: 97%
294 statements
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-01 07:19 +0000
« prev ^ index » next coverage.py v7.6.4, created at 2024-11-01 07:19 +0000
1########################################################################
2# Task to retrieve observing information from SDM XML files
3#
4# v1.0: 2010.12.07, M. Krauss
5# v1.1: 2011.02.23, M. Krauss: added functionality for ALMA data
6#
7# Original code based on readscans.py, courtesy S. Meyers
9import numpy as np
11try:
12 from xml.dom import minidom
13except ImportError as exc:
14 raise ImportError("task listsdm requires minidom but there was an import error: {}".
15 format(exc))
17from casatools import quanta, measures
18from casatasks import casalog
20_qa = quanta( )
21_me = measures( )
22str_split = str.split
24def listsdm(sdm=None):
25 # read Scan.xml
26 xmlscans = minidom.parse(sdm+'/Scan.xml')
27 scandict = {}
28 startTimeShort = []
29 endTimeShort = []
30 rowlist = xmlscans.getElementsByTagName("row")
31 for rownode in rowlist:
32 rowfid = rownode.getElementsByTagName("scanNumber")
33 fid = int(rowfid[0].childNodes[0].nodeValue)
34 scandict[fid] = {}
36 # number of subscans
37 rowsubs = rownode.getElementsByTagName("numSubscan")
38 if len(rowsubs) == 0:
39 # EVLA and old ALMA data
40 rowsubs = rownode.getElementsByTagName("numSubScan")
41 nsubs = int(rowsubs[0].childNodes[0].nodeValue)
43 # intents
44 rownint = rownode.getElementsByTagName("numIntent")
45 nint = int(rownint[0].childNodes[0].nodeValue)
47 rowintents = rownode.getElementsByTagName("scanIntent")
48 sint = str(rowintents[0].childNodes[0].nodeValue)
49 sints = sint.split()
50 rint = ''
51 for r in range(nint):
52 intent = sints[2+r]
53 if rint=='':
54 rint = intent
55 else:
56 rint += ' '+intent
58 # start and end times in mjd ns
59 rowstart = rownode.getElementsByTagName("startTime")
60 start = int(rowstart[0].childNodes[0].nodeValue)
61 startmjd = float(start)*1.0E-9/86400.0
62 t = _qa.quantity(startmjd,'d')
63 starttime = _qa.time(t,form="ymd",prec=8)[0]
64 startTimeShort.append(_qa.time(t,prec=8)[0])
65 rowend = rownode.getElementsByTagName("endTime")
66 end = int(rowend[0].childNodes[0].nodeValue)
67 endmjd = float(end)*1.0E-9/86400.0
68 t = _qa.quantity(endmjd,'d')
69 endtime = _qa.time(t,form="ymd",prec=8)[0]
70 endTimeShort.append(_qa.time(t,prec=8)[0])
72 # source name
73 rowsrc = rownode.getElementsByTagName("sourceName")
74 src = str(rowsrc[0].childNodes[0].nodeValue)
76 scandict[fid]['start'] = starttime
77 scandict[fid]['end'] = endtime
78 timestr = starttime+'~'+endtime
79 scandict[fid]['timerange'] = timestr
80 scandict[fid]['source'] = src
81 scandict[fid]['intent'] = rint
82 scandict[fid]['nsubs'] = nsubs
84 # read Main.xml
85 xmlmain = minidom.parse(sdm+'/Main.xml')
86 rowlist = xmlmain.getElementsByTagName("row")
87 mainScanList = []
88 mainConfigList = []
89 fieldIdList = []
90 for rownode in rowlist:
92 # get the scan numbers
93 rowfid = rownode.getElementsByTagName("scanNumber")
94 fid = int(rowfid[0].childNodes[0].nodeValue)
95 mainScanList.append(fid)
97 # get the configuration description
98 rowconfig = rownode.getElementsByTagName("configDescriptionId")
99 config = str(rowconfig[0].childNodes[0].nodeValue)
100 mainConfigList.append(config)
102 # get the field ID
103 rowfieldid = rownode.getElementsByTagName("fieldId")
104 fieldid = str_split(str(rowfieldid[0].childNodes[0].nodeValue), '_')[1]
105 fieldIdList.append(fieldid)
107 # read ConfigDescription.xml to relate the configuration
108 # description to a (set) of data description IDs
109 xmlconfig = minidom.parse(sdm+'/ConfigDescription.xml')
110 rowlist = xmlconfig.getElementsByTagName("row")
111 configDescList = []
112 dataDescList = []
113 for rownode in rowlist:
115 # get the configuration description
116 rowConfigDesc = rownode.getElementsByTagName("configDescriptionId")
117 configDesc = str(rowConfigDesc[0].childNodes[0].nodeValue)
118 configDescList.append(configDesc)
120 # make a list of the data description IDs:
121 rowNumDataDesc = rownode.getElementsByTagName("numDataDescription")
122 numDataDesc = int(rowNumDataDesc[0].childNodes[0].nodeValue)
124 rowDataDesc = rownode.getElementsByTagName("dataDescriptionId")
125 dataDescStr = str(rowDataDesc[0].childNodes[0].nodeValue)
126 dataDescSplit = dataDescStr.split()
127 dataDesc = []
128 for i in range(numDataDesc):
129 dataDesc.append(dataDescSplit[i+2])
130 dataDescList.append(dataDesc)
132 # read DataDescription.xml to relate the data description IDs to
133 # spectral window IDs
134 xmlDataDesc = minidom.parse(sdm+'/DataDescription.xml')
135 rowlist = xmlDataDesc.getElementsByTagName("row")
136 dataDescElList = []
137 spwIdDataDescList = []
138 for rownode in rowlist:
140 # get the data description ID, make another list:
141 rowDataDescEl = rownode.getElementsByTagName("dataDescriptionId")
142 dataDescEl = str(rowDataDescEl[0].childNodes[0].nodeValue)
143 dataDescElList.append(dataDescEl)
145 # get the related spectral window ID:
146 rowSpwIdDataDesc = rownode.getElementsByTagName("spectralWindowId")
147 spwIdDataDesc = str(rowSpwIdDataDesc[0].childNodes[0].nodeValue)
148 spwIdDataDescList.append(spwIdDataDesc)
150 # read SpectralWindow.xml, get information about number of
151 # channels, reference frequency, baseband name, channel width.
152 # Interesting that there seem to be multiple fields that give the
153 # same information: chanFreqStart=reFreq,
154 # chanFreqStep=chanWidth=resolution. Why? (Note: all units are Hz)
155 # Note: this is where the script breaks for ALMA data, since there
156 # are different tags in SpectraWindow.xml (for varying channel widths).
157 xmlSpecWin = minidom.parse(sdm+'/SpectralWindow.xml')
158 rowlist = xmlSpecWin.getElementsByTagName("row")
159 spwIdList = []
160 nChanList = []
161 refFreqList = []
162 chanWidthList = []
163 basebandList = []
164 for rownode in rowlist:
166 # get the various row values:
167 rowSpwId = rownode.getElementsByTagName("spectralWindowId")
168 rowNChan = rownode.getElementsByTagName("numChan")
169 rowRefFreq = rownode.getElementsByTagName("refFreq")
170 # For EVLA
171 rowChanWidth = rownode.getElementsByTagName("chanWidth")
172 # For ALMA
173 rowChanWidthArr = rownode.getElementsByTagName("chanWidthArray")
174 rowBaseband = rownode.getElementsByTagName("basebandName")
176 # convert to values or strings and append to the relevant lists:
177 spwId = str(rowSpwId[0].childNodes[0].nodeValue)
178 spwIdList.append(spwId)
179 nChan = int(rowNChan[0].childNodes[0].nodeValue)
180 nChanList.append(nChan)
181 refFreq = float(rowRefFreq[0].childNodes[0].nodeValue)
182 refFreqList.append(refFreq)
183 if rowChanWidth:
184 chanWidth = float(rowChanWidth[0].childNodes[0].nodeValue)
185 chanWidthList.append(chanWidth)
186 if rowChanWidthArr:
187 tmpArr = str(rowChanWidthArr[0].childNodes[0].nodeValue).split(' ')
188 tmpWidth = []
189 for cw in range(2, len(tmpArr)):
190 thisWidth = float(tmpArr[cw])
191 tmpWidth.append(thisWidth)
192 chanWidthList.append(tmpWidth)
193 baseband = str(rowBaseband[0].childNodes[0].nodeValue)
194 basebandList.append(baseband)
196 # read Field.xml
197 xmlField = minidom.parse(sdm+'/Field.xml')
198 rowlist = xmlField.getElementsByTagName("row")
199 fieldList = []
200 fieldNameList = []
201 fieldCodeList = []
202 fieldRAList = []
203 fieldDecList = []
204 fieldSrcIDList = []
205 for rownode in rowlist:
206 rowField = rownode.getElementsByTagName("fieldId")
207 rowName = rownode.getElementsByTagName("fieldName")
208 rowCode = rownode.getElementsByTagName("code")
209 rowCoords = rownode.getElementsByTagName("referenceDir")
210 rowSrcId = rownode.getElementsByTagName("sourceId")
212 # convert to values or strings and append to relevent lists:
213 fieldList.append(int(str_split(str(rowField[0].childNodes[0].nodeValue),'_')[1]))
214 fieldNameList.append(str(rowName[0].childNodes[0].nodeValue))
215 fieldCodeList.append(str(rowCode[0].childNodes[0].nodeValue))
216 coordInfo = rowCoords[0].childNodes[0].nodeValue.split()
217 RADeg = float(coordInfo[3])*(180.0/np.pi)
218 DecDeg = float(coordInfo[4])*(180.0/np.pi)
219 RAInp = {'unit': 'deg', 'value': RADeg}
220 DecInp = {'unit': 'deg', 'value': DecDeg}
221 RAHMS = _qa.formxxx(RAInp, format='hms')
222 DecDMS = _qa.formxxx(DecInp, format='dms')
223 fieldRAList.append(RAHMS)
224 fieldDecList.append(DecDMS)
225 fieldSrcIDList.append(int(rowSrcId[0].childNodes[0].nodeValue))
227 # read Antenna.xml
228 xmlAnt = minidom.parse(sdm+'/Antenna.xml')
229 rowlist = xmlAnt.getElementsByTagName("row")
230 antList = []
231 antNameList = []
232 dishDiamList = []
233 stationList = []
234 for rownode in rowlist:
235 rowAnt = rownode.getElementsByTagName("antennaId")
236 rowAntName = rownode.getElementsByTagName("name")
237 rowDishDiam = rownode.getElementsByTagName("dishDiameter")
238 rowStation = rownode.getElementsByTagName("stationId")
240 # convert and append
241 antList.append(int(str_split(str(rowAnt[0].childNodes[0].nodeValue), '_')[1]))
242 antNameList.append(str(rowAntName[0].childNodes[0].nodeValue))
243 dishDiamList.append(float(rowDishDiam[0].childNodes[0].nodeValue))
244 stationList.append(str(rowStation[0].childNodes[0].nodeValue))
246 # read Station.xml
247 xmlStation = minidom.parse(sdm+'/Station.xml')
248 rowlist = xmlStation.getElementsByTagName("row")
249 statIdList = []
250 statNameList = []
251 statLatList = []
252 statLonList = []
253 for rownode in rowlist:
254 rowStatId = rownode.getElementsByTagName("stationId")
255 rowStatName = rownode.getElementsByTagName("name")
256 rowStatPos = rownode.getElementsByTagName("position")
258 # convert and append
259 statIdList.append(str(rowStatId[0].childNodes[0].nodeValue))
260 statNameList.append(str(rowStatName[0].childNodes[0].nodeValue))
261 posInfo = str_split(str(rowStatPos[0].childNodes[0].nodeValue))
262 x = _qa.quantity([float(posInfo[2])], 'm')
263 y = _qa.quantity([float(posInfo[3])], 'm')
264 z = _qa.quantity([float(posInfo[4])], 'm')
265 pos = _me.position('ITRF', x, y, z)
266 qLon = pos['m0']
267 qLat = pos['m1']
268 statLatList.append(_qa.formxxx(qLat, 'dms', prec=0))
269 statLonList.append(_qa.formxxx(qLon, 'dms', prec=0))
271 # associate antennas with stations:
272 assocStatList = []
273 for station in stationList:
274 i = np.where(np.array(statIdList) == station)[0][0]
275 assocStatList.append(statNameList[i])
277 # read ExecBlock.xml
278 xmlExecBlock = minidom.parse(sdm+'/ExecBlock.xml')
279 rowlist = xmlExecBlock.getElementsByTagName("row")
280 sTime = float(rowlist[0].getElementsByTagName("startTime")[0].childNodes[0].nodeValue)*1.0E-9
281 eTime = float(rowlist[0].getElementsByTagName("endTime")[0].childNodes[0].nodeValue)*1.0E-9
282 # integration time in seconds, start and end times:
283 intTime = eTime - sTime
284 t = _qa.quantity(sTime/86400.0, 'd')
285 obsStart = _qa.time(t, form="ymd", prec=8)[0]
286 t = _qa.quantity(eTime/86400.0, 'd')
287 obsEnd = _qa.time(t, form="ymd", prec=8)[0]
288 # observer name and obs. info:
289 observerName = str(rowlist[0].getElementsByTagName("observerName")[0].childNodes[0].nodeValue)
290 configName = str(rowlist[0].getElementsByTagName("configName")[0].childNodes[0].nodeValue)
291 telescopeName = str(rowlist[0].getElementsByTagName("telescopeName")[0].childNodes[0].nodeValue)
292 numAntenna = int(rowlist[0].getElementsByTagName("numAntenna")[0].childNodes[0].nodeValue)
294 # make lists like the dataDescList for spectral windows & related info:
295 spwOrd = []
296 nChanOrd = []
297 rFreqOrd = []
298 cWidthOrd = []
299 bbandOrd = []
300 for i in range(0, len(configDescList)):
301 spwTempList = []
302 nChanTempList = []
303 rFreqTempList = []
304 cWidthTempList = []
305 bbandTempList = []
307 for dDesc in dataDescList[i]:
308 el = np.where(np.array(dataDescElList) == dDesc)[0][0]
309 spwIdN = spwIdDataDescList[el]
310 spwEl = np.where(np.array(spwIdList) == spwIdN)[0][0]
311 spwTempList.append(int(str_split(spwIdList[spwEl], '_')[1]))
312 nChanTempList.append(nChanList[spwEl])
313 rFreqTempList.append(refFreqList[spwEl])
314 cWidthTempList.append(chanWidthList[spwEl])
315 bbandTempList.append(basebandList[spwEl])
316 spwOrd.append(spwTempList)
317 nChanOrd.append(nChanTempList)
318 rFreqOrd.append(rFreqTempList)
319 cWidthOrd.append(cWidthTempList)
320 bbandOrd.append(bbandTempList)
322 # add this info to the scan dictionary:
323 for scanNum in scandict:
324 spwOrdList = []
325 nChanOrdList = []
326 rFreqOrdList = []
327 cWidthOrdList = []
328 bbandOrdList = []
329 # scanEl could have multiple elements if subscans are present,
330 # or for ALMA data:
331 scanEl = np.where(np.array(mainScanList) == scanNum)[0]
332 for thisEl in scanEl:
333 configEl = mainConfigList[thisEl]
334 listEl = np.where(np.array(configDescList) == configEl)[0][0]
335 spwOrdList.append(spwOrd[listEl])
336 nChanOrdList.append(nChanOrd[listEl])
337 rFreqOrdList.append(rFreqOrd[listEl])
338 cWidthOrdList.append(cWidthOrd[listEl])
339 bbandOrdList.append(bbandOrd[listEl])
340 if len(scanEl) > 0:
341 scandict[scanNum]['field'] = int(fieldIdList[scanEl[0]])
342 else:
343 scandict[scanNum]['field'] = -1
344 scandict[scanNum]['spws'] = spwOrdList
345 scandict[scanNum]['nchan'] = nChanOrdList
346 scandict[scanNum]['reffreq'] = rFreqOrdList
347 scandict[scanNum]['chanwidth'] = cWidthOrdList
348 scandict[scanNum]['baseband'] = bbandOrdList
350 # report informatio to the logger
351 casalog.origin('listsdm')
352 casalog.post("================================================================================")
353 casalog.post(" SDM File: %s" % sdm)
354 casalog.post("================================================================================")
355 casalog.post(" Observer: %s" % observerName)
356 casalog.post(" Facility: %s, %s-configuration" % (telescopeName, configName))
357 casalog.post(" Observed from %s to %s (UTC)" % (obsStart, obsEnd))
358 casalog.post(" Total integration time = %.2f seconds (%.2f hours)" % (intTime, intTime/3600))
359 casalog.post(" ")
360 casalog.post("Scan listing:")
361 casalog.post(" Timerange (UTC) Scan FldID FieldName SpwIDs Intent(s)")
363 i = 0
364 #SPWs = []
365 for scan in scandict:
366 SPWs = []
367 for spw in scandict[scan]['spws']:
368 SPWs += spw
369 #printSPWs = sorted(SPWs)
370 printSPWs = list(set(SPWs))
371 casalog.post(" %s - %s %s %s %s %s %s" % (startTimeShort[i], endTimeShort[i], str(list(scandict.keys())[i]).rjust(4), str(scandict[scan]['field']).rjust(5), scandict[scan]['source'].ljust(15), str(printSPWs), scandict[scan]['intent']))
372 i = i + 1
374 casalog.post(" ")
375 casalog.post("Spectral window information:")
376 casalog.post(" SpwID #Chans Ch0(MHz) ChWidth(kHz) TotBW(MHz) Baseband")
378 for i in range(0, len(spwIdList)):
379 casalog.post(" %s %s %s %s %s %s" % (str_split(spwIdList[i], '_')[1].ljust(4), str(nChanList[i]).ljust(4), str(refFreqList[i]/1e6).ljust(8), str(np.array(chanWidthList[i])/1e3).ljust(8), str(np.array(chanWidthList[i])*nChanList[i]/1e6).ljust(8), basebandList[i].ljust(8)))
381 casalog.post(" ")
382 casalog.post("Field information:")
383 casalog.post(" FldID Code Name RA Dec SrcID")
385 for i in range(0, len(fieldList)):
386 casalog.post(" %s %s %s %s %s %s" % (str(fieldList[i]).ljust(5), fieldCodeList[i].ljust(6), fieldNameList[i].ljust(15), fieldRAList[i].ljust(13), fieldDecList[i].ljust(15), str(fieldSrcIDList[i]).ljust(5)))
388 casalog.post(" ")
389 casalog.post("Antennas (%i):" % len(antList))
390 casalog.post(" ID Name Station Diam.(m) Lat. Long.")
392 for i in range(0, len(antList)):
393 casalog.post(" %s %s %s %s %s %s " % (str(antList[i]).ljust(5), antNameList[i].ljust(6), assocStatList[i].ljust(5), str(dishDiamList[i]).ljust(5), statLatList[i].ljust(12), statLonList[i].ljust(12)))
395 # return the scan dictionary
396 return scandict