├── README.md ├── sacm ├── __init__.py ├── dicts.py ├── utils.py ├── geo_helper.py └── parserALMA.py ├── app.py ├── .gitignore ├── LICENSE └── metadatachecker.py /README.md: -------------------------------------------------------------------------------- 1 | # metadatachecker 2 | MetaData Checker 3 | -------------------------------------------------------------------------------- /sacm/__init__.py: -------------------------------------------------------------------------------- 1 | __author__ = 'sdk' 2 | from utils import * 3 | from dicts import * 4 | from parserALMA import * 5 | -------------------------------------------------------------------------------- /sacm/dicts.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | __author__ = 'sdk' 3 | 4 | FlagError = {'EmptyUID': False, 5 | 'NullStateID': False} 6 | 7 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from waitress import serve 2 | from pyramid.config import Configurator 3 | from metadatachecker import * 4 | 5 | def checkMetadata(request): 6 | uid = request.params.get('uid',None) 7 | if uid is None: return 'No UID provided' 8 | try: 9 | asdm = AsdmCheck() 10 | asdm.setUID(uid) 11 | if asdm.doCheck(): 12 | return str(asdm.check) 13 | else: 14 | return str({'Message':'Check not completed'}) 15 | except: 16 | print 'There was an error during Metadata Checker execution' 17 | 18 | 19 | if __name__ == '__main__': 20 | config = Configurator() 21 | config.add_route('metadatachecker', '/') 22 | config.add_view(checkMetadata, route_name='metadatachecker',renderer='string') 23 | app = config.make_wsgi_app() 24 | serve(app, host='0.0.0.0', port=8080) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | password.py 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | .idea/ 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | 57 | # Sphinx documentation 58 | docs/_build/ 59 | 60 | # PyBuilder 61 | target/ 62 | 63 | #Ipython Notebook 64 | .ipynb_checkpoints 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Sebastian Gonzalez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /metadatachecker.py: -------------------------------------------------------------------------------- 1 | __author__ = 'sagonzal' 2 | from sacm import * 3 | import math as mymath 4 | import itertools 5 | 6 | class AsdmCheck: 7 | #uid = '' 8 | #asdmDict = dict() 9 | #check = dict() 10 | #toc = '' 11 | #main = '' 12 | #antennas = '' 13 | #source = '' 14 | #scan = '' 15 | #field = '' 16 | #syscal = '' 17 | 18 | 19 | def __init__(self): 20 | self.uid = '' 21 | self.asdmDict = {} 22 | self.check = {} 23 | self.toc = '' 24 | self.main = '' 25 | self.antennas = '' 26 | self.source = '' 27 | self.scan = '' 28 | self.field = '' 29 | self.syscal = '' 30 | 31 | 32 | def setUID(self,uid=None): 33 | self.uid = uid 34 | try: 35 | asdmList, asdm , self.toc = getASDM(self.uid) 36 | for i in asdmList: 37 | self.asdmDict[i[0].strip()] = i[3].strip() 38 | self.main = getMain(self.asdmDict['Main']) 39 | self.antennas = getAntennas(self.asdmDict['Antenna']) 40 | self.source = getSource(self.asdmDict['Source']) 41 | self.scan = getScan(self.asdmDict['Scan']) 42 | self.field = getField(self.asdmDict['Field']) 43 | self.syscal = getSysCal(self.asdmDict['SysCal']) 44 | 45 | 46 | return True 47 | except Exception as e: 48 | print 'There is a problem with the uid: ', uid 49 | print e 50 | 51 | 52 | def isNullState(self): 53 | """ 54 | Checks the Main.xml table for "null" states 55 | Sets in the self.check dictionary the value 'NullState' with True or False 56 | True: There is no state with null values 57 | False: There is at least one state in the Main.xml table with null state. 58 | :return: 59 | """ 60 | try: 61 | 62 | self.main['null'] = self.main.apply(lambda x: True if 'null' in x['stateId'] else False, axis = 1) 63 | if len(self.main['null'].unique()) > 1: 64 | self.check['NullState'] = False 65 | else: 66 | self.check['NullState'] = True 67 | except Exception as e: 68 | print e 69 | return False 70 | return True 71 | 72 | 73 | def isValidUID(self): 74 | """ 75 | 76 | :return: 77 | """ 78 | import re 79 | regex = re.compile("^uid\:\/\/A00.\/X[a-zA-Z0-9]+\/X[a-zA-Z0-9]+") 80 | try: 81 | for k,v in self.asdmDict.iteritems(): 82 | if '/X0/X0/X0' in v: 83 | self.check['ValidUID'] = False 84 | return True 85 | if regex.match(v) is None: 86 | self.check['ValidUID'] = False 87 | return True 88 | self.check['ValidUID'] = True 89 | return True 90 | except Exception as e: 91 | print e 92 | return False 93 | 94 | def isSyscaltimestamp(self): 95 | try: 96 | dfa = self.syscal[['spectralWindowId','antennaId','timeInterval']] 97 | spw = dfa.groupby('spectralWindowId') 98 | for name,group in spw: 99 | df = group 100 | df['time'] = df.apply(lambda x: int(x['timeInterval'].strip().split(' ')[0]) / 1000000000.0, axis = 1 ) 101 | df['interval'] = df.apply(lambda x: int(x['timeInterval'].strip().split(' ')[1]) / 1000000000.0, axis = 1 ) 102 | df['timestamp'] = df.apply(lambda x: x.time - x.interval / 2, axis = 1) 103 | t0 = 86400.0 * mymath.floor(df.timestamp.min() / 86400.0) 104 | df['utimes'] = df.apply(lambda x: x['time'] - t0, axis =1) 105 | nT = df.utimes.nunique() 106 | df['utimestamp'] = df.apply(lambda x: mymath.floor(x['timestamp']) - t0 , axis =1) 107 | nTS = df.utimestamp.nunique() 108 | #print name,nT, nTS 109 | #print (group) 110 | if nT != nTS: 111 | self.check['SysCalTimes'] = True 112 | return True 113 | self.check['SysCalTimes'] = False 114 | return True 115 | except Exception as e: 116 | return False 117 | 118 | 119 | def iscsv2555(self): 120 | try: 121 | src = self.source[['sourceId', 'sourceName']] 122 | src['sourceName1'] = src.apply(lambda x: x['sourceName'].strip(), axis = 1) 123 | src = src.drop_duplicates() 124 | fld = self.field[['sourceId', 'fieldName']] 125 | fld['fieldName1'] = fld.apply(lambda x: x['fieldName'].strip(), axis = 1) 126 | fld = fld.drop_duplicates() 127 | a = pd.merge(src,fld,left_on = 'sourceId',right_on='sourceId',how='outer') 128 | a['csv2555'] = a.apply(lambda x: True if x['sourceName1'] == x['fieldName1'] else False, axis = 1) 129 | if a['csv2555'].nunique() == 1 and a['csv2555'].unique()[0] is True: 130 | self.check['CSV2555'] = True 131 | else: 132 | self.check['CSV2555'] = False 133 | return True 134 | except Exception as e: 135 | return False 136 | 137 | 138 | def isfixplanets(self): 139 | try: 140 | df = self.source[['sourceName','direction']].drop_duplicates() 141 | df['coordinate'] = df.apply(lambda x: True if float(arrayParser(x['direction'].strip() , 1 )[0]) == 0.0 else False , axis = 1) 142 | df['coordinate2'] = df.apply(lambda x: True if float(arrayParser(x['direction'].strip() , 1 )[1]) == 0.0 else False , axis = 1) 143 | if df['coordinate'].unique()[0] is False and df['coordinate'].nunique() == 1 and df['coordinate2'].unique()[0] is False and df['coordinate2'].nunique() == 1: 144 | self.check['FixPlanets'] = True 145 | else: 146 | self.check['FixPlanets'] = False 147 | return True 148 | except Exception as e: 149 | return False 150 | 151 | def ict4871(self): 152 | try: 153 | nant = self.antennas.antennaId.nunique() 154 | sys_nant = self.syscal.antennaId.nunique() 155 | sc = self.scan[['scanNumber','startTime','scanIntent']] 156 | problem_list = list() 157 | if nant == sys_nant: 158 | df = self.syscal[['timeInterval','antennaId','spectralWindowId']] 159 | df['start'] = df.apply(lambda x: int(x['timeInterval'].strip().split(' ')[0]) - int(x['timeInterval'].strip().split(' ')[1])/2, axis = 1) 160 | df2 = pd.merge (df,sc, left_on='start',right_on='startTime',copy=False,how='inner') 161 | antlist = [x.strip(' ') for x in self.antennas.antennaId.unique().tolist()] 162 | df3 = df2.groupby(['antennaId','spectralWindowId','scanNumber']) 163 | spw_list = self.syscal.spectralWindowId.unique().tolist() 164 | scan_list = df2.scanNumber.unique().tolist() 165 | fu = list(itertools.product(antlist,spw_list,scan_list)) 166 | for i in fu: 167 | try: 168 | df3.groups[i] 169 | except KeyError as k: 170 | problem_list.append(i) 171 | 172 | if len(problem_list) > 0: 173 | df = pd.DataFrame(problem_list, columns= ['antennaId','spectralWindowId','scanNumber']) 174 | popular_scan = df.scanNumber.mode().values[0] 175 | ant = df.antennaId.nunique() 176 | self.check['MissingTsys'] = False 177 | self.check['MissingTsys_explain'] = 'Scan: '+str(popular_scan)+' Antennas Affected: '+str(ant) 178 | else: 179 | self.check['MissingTsys'] = True 180 | 181 | else: 182 | self.check['AntennasMissing'] = "Number of antennas are diferent between Antenna.xml ("+nant+") and SysCal.xml ("+sys_nant+")" 183 | self.check['MissingTsys'] = False 184 | self.check['MissingTsys_explain'] = 'Some antenna is completly missing from Syscal.xml table' 185 | 186 | 187 | except Exception as e: 188 | print e 189 | return False 190 | 191 | def doCheck(self): 192 | try: 193 | self.iscsv2555() 194 | self.isSyscaltimestamp() 195 | self.isValidUID() 196 | self.isfixplanets() 197 | self.isNullState() 198 | self.ict4871() 199 | return True 200 | except Exception as e: 201 | print e 202 | return False 203 | 204 | -------------------------------------------------------------------------------- /sacm/utils.py: -------------------------------------------------------------------------------- 1 | __author__ = 'sdk' 2 | from time import strftime, gmtime, mktime 3 | import datetime 4 | from xml.dom import minidom 5 | import numpy as np 6 | import cx_Oracle 7 | from password import databaseSCO as database 8 | import pandas as pd 9 | pd.options.mode.chained_assignment = None 10 | 11 | tables = {"ASDM": "XML_ASDM_ENTITIES", "Main": "XML_MAINTABLE_ENTITIES", 12 | "AlmaRadiometer": "XML_ALMARADIOMETERTAB_ENTITIES", "Antenna": "XML_ANTENNATABLE_ENTITIES", 13 | "CalAmpli": "XML_CALAMPLITABLE_ENTITIES", "CalAtmosphere": "XML_CALATMOSPHERETABL_ENTITIES", 14 | "CalCurve": "XML_CALCURVETABLE_ENTITIES", "CalSeeing": "XML_CALSEEINGTABLE_ENTITIES", 15 | "CalWVR": "XML_CALWVRTABLE_ENTITIES", "CalData": "XML_CALDATATABLE_ENTITIES", 16 | "CalDelay": "XML_CALDELAYTABLE_ENTITIES", "CalDevice": "XML_CALDEVICETABLE_ENTITIES", 17 | "CalFlux": "XML_CALFLUXTABLE_ENTITIES", "CalPhase": "XML_CALPHASETABLE_ENTITIES", 18 | "CalReduction": "XML_CALREDUCTIONTABLE_ENTITIES", "ConfigDescription": "XML_CONFIGDESCRIPTION_ENTITIES", 19 | "CorrelatorMode": "XML_CORRELATORMODETAB_ENTITIES", "DataDescription": "XML_DATADESCRIPTIONTA_ENTITIES", 20 | "ExecBlock": "XML_EXECBLOCKTABLE_ENTITIES", "Feed": "XML_FEEDTABLE_ENTITIES", 21 | "Annotation": "XML_ANNOTATIONTABLE_ENTITIES", "Ephemeris": "XML_EPHEMERISTABLE_ENTITIES", 22 | "Anotation": "XML_ANNOTATIONTABLE_ENTITIES", "CalBandpass": "XML_CALBANDPASSTABLE_ENTITIES", 23 | "CalPointing": "XML_CALPOINTINGTABLE_ENTITIES", "Field": "XML_FIELDTABLE_ENTITIES", 24 | "Flag": "XML_FLAGTABLE_ENTITIES", "Focus": "XML_FOCUSTABLE_ENTITIES", 25 | "FocusModel": "XML_FOCUSMODELTABLE_ENTITIES", "Pointing": "XML_POINTINGTABLE_ENTITIES", 26 | "PointingModel": "XML_POINTINGMODELTABL_ENTITIES", "Polarization": "XML_POLARIZATIONTABLE_ENTITIES", 27 | "Processor": "XML_PROCESSORTABLE_ENTITIES", "Receiver": "XML_RECEIVERTABLE_ENTITIES", 28 | "SBSummary": "XML_SBSUMMARYTABLE_ENTITIES", "Scan": "XML_SCANTABLE_ENTITIES", 29 | "Source": "XML_SOURCETABLE_ENTITIES", "SpectralWindow": "XML_SPECTRALWINDOWTAB_ENTITIES", 30 | "State": "XML_STATETABLE_ENTITIES", "Station": "XML_STATIONTABLE_ENTITIES", "Subscan": "XML_SUBSCANTABLE_ENTITIES", 31 | "SquareLawDetector": "XML_SQUARELAWDETECTOR_ENTITIES", "SwitchCycle": "XML_SWITCHCYCLETABLE_ENTITIES", 32 | "SysCal": "XML_SYSCALTABLE_ENTITIES", "Weather": "XML_WEATHERTABLE_ENTITIES", 33 | "SchedBlock":"XML_SCHEDBLOCK_ENTITIES", "ObsProject":"XML_OBSPROJECT_ENTITIES"} 34 | 35 | def sdmTimeString(number=None): 36 | """ 37 | Convert a time value (as used by ASDM, i.e. MJD in nanoseconds) into a FITS type string. 38 | :param number: 39 | """ 40 | st = number/1000000000L 41 | # decimal microseconds ... 42 | number = (number-st*1000000000L)/1000 43 | # number of seconds since 1970-01-01T00:00:00 44 | st = st-3506716800L 45 | return strftime("%Y-%m-%dT%H:%M:%S", gmtime(st))+(".%6.6d" % number) 46 | 47 | 48 | def gtm(t=None): 49 | """ 50 | Convert a time value (as used by ASDM, i.e. MJD in nanoseconds) into a FITS type string. 51 | :param t: 52 | """ 53 | st = t-3506716800000000000L 54 | return st/1000000000L 55 | 56 | 57 | def gtm2(number=None): 58 | """ 59 | Convert a time value (as used by ASDM, i.e. MJD in nanoseconds) into a FITS type string. 60 | :param number: 61 | """ 62 | st = number/1000000000L 63 | # decimal microseconds ... 64 | number = (number-st*1000000000L)/1000 65 | # number of seconds since 1970-01-01T00:00:00 66 | st = st-3506716800L 67 | return datetime.datetime.fromtimestamp(mktime(gmtime(st))).replace(microsecond=(number)) 68 | 69 | def returnMAXPWVC(pwv=None): 70 | if pwv <= 0.472: 71 | return 0.472 72 | elif pwv <= 0.658: 73 | return 0.658 74 | elif pwv <= 0.913: 75 | return 0.913 76 | elif pwv <= 1.262: 77 | return 1.262 78 | elif pwv <= 1.796: 79 | return 1.796 80 | elif pwv <= 2.748: 81 | return 2.748 82 | else: 83 | return 5.186 84 | 85 | 86 | def findChannel(start=None, width=None, repFreq=None, nchan=None): 87 | channel = 0 88 | if width < 0: 89 | for i in xrange(nchan): 90 | if start > repFreq: 91 | start = start + width 92 | else: 93 | channel = -1.*i 94 | break 95 | else: 96 | for i in xrange(nchan): 97 | if start < repFreq: 98 | start = start + width 99 | else: 100 | channel = i 101 | break 102 | 103 | return channel 104 | 105 | 106 | def RadianTo(num=None, unit=None): 107 | """ 108 | 109 | :param num: 110 | :param unit: 111 | :return: 112 | """ 113 | Deg = float(num)*180.0/np.pi 114 | if unit == 'dms': 115 | if Deg < 0: 116 | Deg = -Deg 117 | sign = '-' 118 | else: 119 | sign = '+' 120 | g = int(Deg) 121 | m = int((Deg-g)*60.) 122 | s = (Deg-g-m/60.)*3600. 123 | return sign+str(g)+":"+str(m)+":"+str('%5.5f' % s) 124 | if unit == 'hms': 125 | h = int(Deg/15.) 126 | m = int((Deg/15.-h)*60.) 127 | s = (Deg/15.-h-m/60.)*3600. 128 | return str(h)+":"+str(m)+":"+str('%5.5f' % s) 129 | 130 | 131 | def arrayParser(line=None, dimensions=None, castFloat=False): 132 | """ 133 | 134 | :param line: String to be formated 135 | :param dimensions: dimensions of the array 136 | :return: a list, or a list of list 1D o 2D arrays, no support for 3D arrays yet 137 | """ 138 | result = list() 139 | line = line.strip() 140 | if dimensions == 1: 141 | elements = line.split(' ')[1] 142 | splits = line.split(' ')[2:] 143 | for i in splits: 144 | result.append(float(i)) if castFloat else result.append(i) 145 | if int(elements) == len(result): 146 | return result 147 | else: 148 | return False 149 | 150 | if dimensions == 2: 151 | rows = int(line.split(' ')[1]) 152 | columns = int(line.split(' ')[2]) 153 | splits = line.split(' ')[3:] 154 | for j in range(0, rows): 155 | temp = list() 156 | for i in range(0, columns): 157 | temp.append(float(splits[i+(j*columns)])) if castFloat else temp.append(splits[i+(j*columns)]) 158 | result.append(temp) 159 | return result 160 | 161 | 162 | 163 | 164 | def GetXML(archiveUID=None,table=None): 165 | """ 166 | 167 | :param archiveUID: Archive UID 168 | :param table: Table 169 | :return: XML String 170 | """ 171 | sqlXML = "select XMLType.GetClobVal(xml) from ALMA.XXXXYYY where archive_uid='ZZZZCCCC' " 172 | sqlXML = sqlXML.replace('XXXXYYY',tables[table]).replace('ZZZZCCCC',archiveUID) 173 | try: 174 | orcl = cx_Oracle.connect(database) 175 | cursorXML = orcl.cursor() 176 | cursorXML.execute(sqlXML) 177 | XMLTable = cursorXML.fetchone() 178 | return XMLTable[0].read() 179 | except Exception as e: 180 | print e 181 | return False 182 | return False 183 | 184 | 185 | def getProjectUID(projectCode=None): 186 | """ 187 | 188 | :param projectCode: 189 | :return: 190 | """ 191 | sql = "select prj_archive_uid from ALMA.BMMV_OBSPROJECT where prj_code = 'XXXYYY'" 192 | sql = sql.replace('XXXYYY',projectCode) 193 | try: 194 | orcl = cx_Oracle.connect(database) 195 | cursor = orcl.cursor() 196 | cursor.execute(sql) 197 | data = cursor.fetchall() 198 | orcl.close() 199 | return data[0][0] 200 | 201 | except Exception as e: 202 | print e 203 | 204 | def getSBMOUS(): 205 | sql = "select DOMAIN_ENTITY_ID, PARENT_OBS_UNIT_SET_STATUS_ID from ALMA.SCHED_BLOCK_STATUS" 206 | try: 207 | orcl = cx_Oracle.connect(database) 208 | cursor = orcl.cursor() 209 | cursor.execute(sql) 210 | data = cursor.fetchall() 211 | status = list() 212 | for i in data: 213 | status.append((i[0],i[1])) 214 | orcl.close() 215 | return status 216 | except Exception as e: 217 | print e 218 | 219 | def getSBNames(): 220 | sql = "select archive_uid, sb_name from ALMA.BMMV_SCHEDBLOCK" 221 | try: 222 | orcl = cx_Oracle.connect(database) 223 | cursor = orcl.cursor() 224 | cursor.execute(sql) 225 | data = cursor.fetchall() 226 | sbnames = list() 227 | for i in data: 228 | sbnames.append((i[0],i[1])) 229 | orcl.close() 230 | return sbnames 231 | except Exception as e: 232 | print e 233 | 234 | def getProjectCodes(cycle=2): 235 | cycle_code = dict() 236 | cycle_code[0] = '2011._.%._' 237 | cycle_code[1] = '2012._.%._' 238 | cycle_code[2] = '2013._.%._' 239 | cycle_code[3] = '2015._.%._' 240 | 241 | sql = '''select al2.PRJ_ARCHIVE_UID, al2.code 242 | from ALMA.OBS_PROJECT_STATUS al1, 243 | ALMA.BMMV_OBSPROJECT al2 244 | where al1.obs_project_id in (select prj_archive_uid from ALMA.BMMV_OBSPROJECT where prj_code like 'XXXYYYZZZ') 245 | and al1.domain_entity_state in ('Ready', 'Canceled', 'InProgress', 'Broken','Completed', 'Repaired','Phase2Submitted') 246 | and al1.OBS_PROJECT_ID = al2.PRJ_ARCHIVE_UID ''' 247 | 248 | sql = sql.replace('XXXYYYZZZ',cycle_code[int(cycle)]) 249 | try: 250 | orcl = cx_Oracle.connect(database) 251 | cursor = orcl.cursor() 252 | cursor.execute(sql) 253 | data = cursor.fetchall() 254 | codes = list() 255 | for i in data: 256 | codes.append((i[0],i[1])) 257 | orcl.close() 258 | return codes 259 | except Exception as e: 260 | print e 261 | 262 | 263 | 264 | def getSBs(prj_uid=None): 265 | sql = '''with t1 as ( 266 | select status_entity_id as seid1 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' and PARENT_OBS_UNIT_SET_STATUS_ID is null 267 | ), 268 | t2 as ( 269 | select status_entity_id as seid2, PARENT_OBS_UNIT_SET_STATUS_ID as paid2, domain_entity_id from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 270 | ), 271 | t3 as ( 272 | select status_entity_id as seid3, PARENT_OBS_UNIT_SET_STATUS_ID as paid3 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 273 | ), 274 | t4 as ( 275 | select status_entity_id as seid4, PARENT_OBS_UNIT_SET_STATUS_ID as paid4 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 276 | ), 277 | t5 as ( 278 | select domain_entity_id as scheckblock_uid, PARENT_OBS_UNIT_SET_STATUS_ID as paid5 from ALMA.SCHED_BLOCK_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 279 | ) 280 | SELECT t2.domain_entity_id, t5.scheckblock_uid 281 | FROM t1, 282 | t2, 283 | t3, 284 | t4, 285 | t5 286 | WHERE t1.seid1 = t2.paid2 287 | AND t2.seid2 = t3.paid3 288 | AND t3.seid3 = t4.paid4 289 | AND t4.seid4 = t5.paid5 290 | ORDER BY 1 ASC''' 291 | sql = sql.replace('PPPRRRJJJ', prj_uid) 292 | try: 293 | orcl = cx_Oracle.connect(database) 294 | cursor = orcl.cursor() 295 | cursor.execute(sql) 296 | sb = cursor.fetchall() 297 | orcl.close() 298 | return sb 299 | except Exception as e: 300 | orcl.close() 301 | print e 302 | 303 | 304 | def spectrals_sb(prj_uid=None, partid=None): 305 | sql = '''with t1 as ( 306 | select status_entity_id as seid1 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' and PARENT_OBS_UNIT_SET_STATUS_ID is null 307 | ), 308 | t2 as ( 309 | select status_entity_id as seid2, PARENT_OBS_UNIT_SET_STATUS_ID as paid2, domain_entity_id from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 310 | ), 311 | t3 as ( 312 | select status_entity_id as seid3, PARENT_OBS_UNIT_SET_STATUS_ID as paid3 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 313 | ), 314 | t4 as ( 315 | select status_entity_id as seid4, PARENT_OBS_UNIT_SET_STATUS_ID as paid4 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 316 | ), 317 | t5 as ( 318 | select domain_entity_id as scheckblock_uid, PARENT_OBS_UNIT_SET_STATUS_ID as paid5 from ALMA.SCHED_BLOCK_STATUS where OBS_PROJECT_ID = 'PPPRRRJJJ' 319 | ) 320 | SELECT t2.domain_entity_id, t5.scheckblock_uid 321 | FROM t1, 322 | t2, 323 | t3, 324 | t4, 325 | t5 326 | WHERE t1.seid1 = t2.paid2 327 | AND t2.seid2 = t3.paid3 328 | AND t3.seid3 = t4.paid4 329 | AND t4.seid4 = t5.paid5 330 | AND t2.domain_entity_id = 'ZZZXXXYYY' 331 | ORDER BY 1 ASC''' 332 | sql = sql.replace('PPPRRRJJJ', prj_uid).replace('ZZZXXXYYY', partid) 333 | try: 334 | orcl = cx_Oracle.connect(database) 335 | cursor = orcl.cursor() 336 | cursor.execute(sql) 337 | sb = cursor.fetchall() 338 | specscan = list() 339 | for i in sb: 340 | specscan.append((prj_uid,i[1],'SpectralScan')) 341 | return specscan 342 | except Exception as e: 343 | print e 344 | 345 | 346 | def is_spectralscan(prj_uid=None): 347 | sql = '''select al1.archive_uid, x.* 348 | from 349 | ALMA.XML_OBSPROJECT_ENTITIES al1, 350 | XMLTable('for $first in /*:ObsProject/*:ObsProgram/*:ScienceGoal return element i { 351 | element pol { data($first/*:SpectralSetupParameters/@polarisation)}, 352 | element type { data($first/*:SpectralSetupParameters/@type)}, 353 | element partid { data($first/*:ObsUnitSetRef/@partId)} 354 | }' 355 | PASSING al1.XML COLUMNS 356 | pol varchar2(50) PATH 'pol', 357 | type varchar2(32) PATH 'type', 358 | partid varchar2(20) PATH 'partid' 359 | ) x 360 | where al1. archive_uid = 'XXXXYYYY' 361 | order by al1.timestamp desc''' 362 | sql = sql.replace('XXXXYYYY', prj_uid) 363 | try: 364 | orcl = cx_Oracle.connect(database) 365 | cursor = orcl.cursor() 366 | cursor.execute(sql) 367 | science_goals = cursor.fetchall() 368 | cursor.close() 369 | return science_goals 370 | except Exception as e: 371 | print e 372 | 373 | 374 | 375 | def is_band89(prj_uid=None): 376 | sql = '''with t1 as ( 377 | select status_entity_id as seid1 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'XXXXYYYYZZZZ' and PARENT_OBS_UNIT_SET_STATUS_ID is null 378 | ), 379 | t2 as ( 380 | select status_entity_id as seid2, PARENT_OBS_UNIT_SET_STATUS_ID as paid2, domain_entity_id from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'XXXXYYYYZZZZ' 381 | ), 382 | t3 as ( 383 | select status_entity_id as seid3, PARENT_OBS_UNIT_SET_STATUS_ID as paid3 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'XXXXYYYYZZZZ' 384 | ), 385 | t4 as ( 386 | select status_entity_id as seid4, PARENT_OBS_UNIT_SET_STATUS_ID as paid4 from ALMA.OBS_UNIT_SET_STATUS where OBS_PROJECT_ID = 'XXXXYYYYZZZZ' 387 | ), 388 | t5 as ( 389 | select domain_entity_id as schedblock_uid, PARENT_OBS_UNIT_SET_STATUS_ID as paid5 from ALMA.SCHED_BLOCK_STATUS where OBS_PROJECT_ID = 'XXXXYYYYZZZZ' 390 | ), 391 | t6 as ( 392 | select archive_uid as sb_uid, receiver_band as band from ALMA.BMMV_SCHEDBLOCK where prj_ref = 'XXXXYYYYZZZZ' 393 | ) 394 | SELECT t2.domain_entity_id, t5.schedblock_uid,t6.band 395 | FROM t1, 396 | t2, 397 | t3, 398 | t4, 399 | t5, 400 | t6 401 | WHERE t1.seid1 = t2.paid2 402 | AND t2.seid2 = t3.paid3 403 | AND t3.seid3 = t4.paid4 404 | AND t4.seid4 = t5.paid5 405 | and t6.sb_uid = t5.schedblock_uid 406 | ORDER BY 1 ASC''' 407 | sql = sql.replace('XXXXYYYYZZZZ',prj_uid) 408 | try: 409 | orcl = cx_Oracle.connect(database) 410 | cursor = orcl.cursor() 411 | cursor.execute(sql) 412 | sb = cursor.fetchall() 413 | cursor.close() 414 | return sb 415 | except Exception as e: 416 | print e 417 | 418 | 419 | 420 | 421 | -------------------------------------------------------------------------------- /sacm/geo_helper.py: -------------------------------------------------------------------------------- 1 | # Geographical helper functions for nmea_info.py and friends 2 | # 3 | # Helps with geographic functions, including: 4 | # Lat+Long+Height -> XYZ 5 | # XYZ -> Lat+Long+Height 6 | # Lat+Long -> other Lat+Long (Helmert Transform) 7 | # Lat+Long -> easting/northing (OS GB+IE Only) 8 | # easting/northing -> Lat+Long (OS GB+IE Only) 9 | # OS easting/northing -> OS 6 figure ref 10 | # 11 | # See http://gagravarr.org/code/ for updates and information 12 | # 13 | # GPL 14 | # 15 | # Nick Burch - v0.06 (30/05/2007) 16 | 17 | import math 18 | 19 | # For each co-ordinate system we do, what are the A, B and E2 values? 20 | # List is A, B, E^2 (E^2 calculated after) 21 | abe_values = { 22 | 'wgs84': [ 6378137.0, 6356752.3141, -1 ], 23 | 'osgb' : [ 6377563.396, 6356256.91, -1 ], 24 | 'osie' : [ 6377340.189, 6356034.447, -1 ] 25 | } 26 | 27 | # The earth's radius, in meters, as taken from an average of the WGS84 28 | # a and b parameters (should be close enough) 29 | earths_radius = (abe_values['wgs84'][0] + abe_values['wgs84'][1]) / 2.0 30 | 31 | # Calculate the E2 values 32 | for system in abe_values.keys(): 33 | a = abe_values[system][0] 34 | b = abe_values[system][1] 35 | e2 = (a*a - b*b) / (a*a) 36 | abe_values[system][2] = e2 37 | 38 | # For each co-ordinate system we can translate between, what are 39 | # the tx, ty, tz, s, rx, ry and rz values? 40 | # List is tx, ty, tz, s, rx, ry, rz 41 | transform_values = { 42 | 'wgs84_to_osgb' : [ -446.448, 125.157, -542.060, 43 | 20.4894 / 1000.0 / 1000.0, # given as ppm 44 | -0.1502 / 206265.0, # given as seconds of arc 45 | -0.2470 / 206265.0, # given as seconds of arc 46 | -0.8421 / 206265.0 # given as seconds of arc 47 | ], 48 | 'wgs84_to_osie' : [ -482.530, 130.596, -564.557, 49 | -8.1500 / 1000.0 / 1000.0, # given as ppm 50 | -1.0420 / 206265.0, # given as seconds of arc 51 | -0.2140 / 206265.0, # given as seconds of arc 52 | -0.6310 / 206265.0 # given as seconds of arc 53 | ], 54 | 'itrs2000_to_etrs89' : [ 0.054, 0.051, -0.048, 0, 55 | 0.000081 / 206265.0, # given as seconds of arc 56 | 0.00049 / 206265.0, # given as seconds of arc 57 | 0.000792 / 206265.0 # given as seconds of arc 58 | ] 59 | } 60 | 61 | # Calculate reverse transforms 62 | for systems in [('wgs84','osgb'), ('wgs84','osie'), ('itrs2000','etrs89')]: 63 | fs = systems[0] + "_to_" + systems[1] 64 | rs = systems[1] + "_to_" + systems[0] 65 | ra = [] 66 | for val in transform_values[fs]: 67 | ra.append(-1.0 * val) 68 | transform_values[rs] = ra 69 | 70 | # Easting and Northin system values, for the systems we work with. 71 | # List is n0, e0, F0, theta0 and landa0 72 | en_values = { 73 | 'osgb' : [ -100000.0, 400000.0, 0.9996012717, 74 | 49.0 /360.0 *2.0*math.pi, 75 | -2.0 /360.0 *2.0*math.pi 76 | ], 77 | 'osie' : [ 250000.0, 200000.0, 1.000035, 78 | 53.5 /360.0 *2.0*math.pi, 79 | -8.0 /360.0 *2.0*math.pi 80 | ] 81 | } 82 | 83 | # Cassini Projection Origins 84 | # List is lat (rad), long (rad), false easting, false northing 85 | cassini_values = { 86 | 'osgb' : [ (53.0 + (13.0 / 60.0) + (17.274 / 3600.0)) /360.0 *2.0*math.pi, 87 | -(2.0 + (41.0 / 60.0) + (3.562 / 3600.0)) /360.0 *2.0*math.pi, 88 | 0, 0 ] 89 | } 90 | 91 | # How many feet to the meter 92 | feet_per_meter = 1.0 / 0.3048007491 # 3.28083 93 | 94 | ############################################################## 95 | # OS GB Specific Helpers for Generic Methods # 96 | ############################################################## 97 | 98 | def turn_wgs84_into_osgb36(lat_dec,long_dec,height): 99 | """See http://www.gps.gov.uk/guide6.asp#6.2 and http://www.gps.gov.uk/guide6.asp#6.6 for the calculations, and http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34h.html for some background.""" 100 | 101 | wgs84_xyz = turn_llh_into_xyz(lat_dec,long_dec,height,'wgs84') 102 | 103 | osgb_xyz = turn_xyz_into_other_xyz( 104 | wgs84_xyz[0],wgs84_xyz[1],wgs84_xyz[2],'wgs84','osgb') 105 | 106 | osgb_latlong = turn_xyz_into_llh( 107 | osgb_xyz[0],osgb_xyz[1],osgb_xyz[2],'osgb') 108 | return osgb_latlong 109 | 110 | def turn_osgb36_into_wgs84(lat_dec,long_dec,height): 111 | """See http://www.gps.gov.uk/guide6.asp#6.2 and http://www.gps.gov.uk/guide6.asp#6.6 for the calculations, and http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34h.html for some background.""" 112 | 113 | osgb_xyz = turn_llh_into_xyz(lat_dec,long_dec,height,'osgb') 114 | 115 | wgs84_xyz = turn_xyz_into_other_xyz( 116 | osgb_xyz[0],osgb_xyz[1],osgb_xyz[2],'osgb','wgs84') 117 | 118 | wgs84_latlong = turn_xyz_into_llh( 119 | wgs84_xyz[0],wgs84_xyz[1],wgs84_xyz[2],'wgs84') 120 | 121 | return wgs84_latlong 122 | 123 | def turn_osgb36_into_eastingnorthing(lat_dec,long_dec): 124 | """Turn OSGB36 (decimal) lat/long values into OS easting and northing values.""" 125 | return turn_latlong_into_eastingnorthing(lat_dec,long_dec,'osgb') 126 | 127 | def turn_eastingnorthing_into_osgb36(easting,northing): 128 | """Turn OSGB36 easting and northing values into (decimal) lat/long values inOSGB36.""" 129 | return turn_eastingnorthing_into_latlong(easting,northing,'osgb') 130 | 131 | ############################################################## 132 | # OS IE Specific Helpers for Generic Methods # 133 | ############################################################## 134 | 135 | def turn_wgs84_into_osie36(lat_dec,long_dec,height): 136 | """As per turn_wgs84_into_osgb36, but for Irish grid""" 137 | 138 | wgs84_xyz = turn_llh_into_xyz(lat_dec,long_dec,height,'wgs84') 139 | 140 | osie_xyz = turn_xyz_into_other_xyz( 141 | wgs84_xyz[0],wgs84_xyz[1],wgs84_xyz[2],'wgs84','osie') 142 | 143 | osie_latlong = turn_xyz_into_llh( 144 | osie_xyz[0],osie_xyz[1],osie_xyz[2],'osie') 145 | return osie_latlong 146 | 147 | def turn_osie36_into_wgs84(lat_dec,long_dec,height): 148 | """As per turn_osgb36_into_wgs84, but for Irish grid""" 149 | 150 | osie_xyz = turn_llh_into_xyz(lat_dec,long_dec,height,'osie') 151 | 152 | wgs84_xyz = turn_xyz_into_other_xyz( 153 | osie_xyz[0],osie_xyz[1],osie_xyz[2],'osie','wgs84') 154 | 155 | wgs84_latlong = turn_xyz_into_llh( 156 | wgs84_xyz[0],wgs84_xyz[1],wgs84_xyz[2],'wgs84') 157 | 158 | return wgs84_latlong 159 | 160 | def turn_osie36_into_eastingnorthing(lat_dec,long_dec): 161 | """Turn OSIE36 (decimal) lat/long values into OS IE easting and northing values.""" 162 | return turn_latlong_into_eastingnorthing(lat_dec,long_dec,'osie') 163 | 164 | def turn_eastingnorthing_into_osie36(easting,northing): 165 | """Turn OSIE36 easting and northing values into (decimal) lat/long values inOSIE36.""" 166 | return turn_eastingnorthing_into_latlong(easting,northing,'osie') 167 | 168 | ############################################################## 169 | # Generic Transform Functions # 170 | ############################################################## 171 | 172 | def turn_llh_into_xyz(lat_dec,long_dec,height,system): 173 | """Convert Lat, Long and Height into 3D Cartesian x,y,z 174 | See http://www.ordnancesurvey.co.uk/gps/docs/convertingcoordinates3D.pdf""" 175 | 176 | a = abe_values[system][0] 177 | b = abe_values[system][1] 178 | e2 = abe_values[system][2] 179 | 180 | theta = float(lat_dec) / 360.0 * 2.0 * math.pi 181 | landa = float(long_dec) / 360.0 * 2.0 * math.pi 182 | height = float(height) 183 | 184 | v = a / math.sqrt( 1.0 - e2 * (math.sin(theta) * math.sin(theta)) ) 185 | x = (v + height) * math.cos(theta) * math.cos(landa) 186 | y = (v + height) * math.cos(theta) * math.sin(landa) 187 | z = ( (1.0 - e2) * v + height ) * math.sin(theta) 188 | 189 | return [x,y,z] 190 | 191 | def turn_xyz_into_llh(x,y,z,system): 192 | """Convert 3D Cartesian x,y,z into Lat, Long and Height 193 | See http://www.ordnancesurvey.co.uk/gps/docs/convertingcoordinates3D.pdf""" 194 | 195 | a = abe_values[system][0] 196 | b = abe_values[system][1] 197 | e2 = abe_values[system][2] 198 | 199 | p = math.sqrt(x*x + y*y) 200 | 201 | long = math.atan(y/x) 202 | lat_init = math.atan( z / (p * (1.0 - e2)) ) 203 | v = a / math.sqrt( 1.0 - e2 * (math.sin(lat_init) * math.sin(lat_init)) ) 204 | lat = math.atan( (z + e2*v*math.sin(lat_init)) / p ) 205 | 206 | height = (p / math.cos(lat)) - v # Ignore if a bit out 207 | 208 | # Turn from radians back into degrees 209 | long = long / 2 / math.pi * 360 210 | lat = lat / 2 / math.pi * 360 211 | 212 | return [lat,long,height] 213 | 214 | def turn_xyz_into_other_xyz(old_x,old_y,old_z,from_scheme,to_scheme): 215 | """Helmert Transformation between one lat+long system and another 216 | See http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/guide6.html for the calculations, and http://www.movable-type.co.uk/scripts/LatLongConvertCoords.html for a friendlier version with examples""" 217 | 218 | transform = from_scheme + "_to_" + to_scheme 219 | tx = transform_values[transform][0] 220 | ty = transform_values[transform][1] 221 | tz = transform_values[transform][2] 222 | s = transform_values[transform][3] 223 | rx = transform_values[transform][4] 224 | ry = transform_values[transform][5] 225 | rz = transform_values[transform][6] 226 | 227 | # Do the transform 228 | new_x = tx + ((1.0+s) * old_x) + (-rz * old_y) + (ry * old_z) 229 | new_y = ty + (rz * old_x) + ((1.0+s) * old_y) + (-rx * old_z) 230 | new_z = tz + (-ry * old_x) + (rx * old_y) + ((1.0+s) * old_z) 231 | 232 | return [new_x,new_y,new_z] 233 | 234 | def calculate_distance_and_bearing(from_lat_dec,from_long_dec,to_lat_dec,to_long_dec): 235 | """Uses the spherical law of cosines to calculate the distance and bearing between two positions""" 236 | 237 | # Turn them all into radians 238 | from_theta = float(from_lat_dec) / 360.0 * 2.0 * math.pi 239 | from_landa = float(from_long_dec) / 360.0 * 2.0 * math.pi 240 | to_theta = float(to_lat_dec) / 360.0 * 2.0 * math.pi 241 | to_landa = float(to_long_dec) / 360.0 * 2.0 * math.pi 242 | 243 | d = math.acos( 244 | math.sin(from_theta) * math.sin(to_theta) + 245 | math.cos(from_theta) * math.cos(to_theta) * math.cos(to_landa-from_landa) 246 | ) * earths_radius 247 | 248 | bearing = math.atan2( 249 | math.sin(to_landa-from_landa) * math.cos(to_theta), 250 | math.cos(from_theta) * math.sin(to_theta) - 251 | math.sin(from_theta) * math.cos(to_theta) * math.cos(to_landa-from_landa) 252 | ) 253 | bearing = bearing / 2.0 / math.pi * 360.0 254 | 255 | return [d,bearing] 256 | 257 | ############################################################## 258 | # Easting/Northing Transform Methods # 259 | ############################################################## 260 | 261 | def turn_latlong_into_eastingnorthing(lat_dec,long_dec,scheme): 262 | """Turn OSGB36 or OSIE36 (decimal) lat/long values into OS easting and northing values. See http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/guide7.html for the calculations, and http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34h.html for some background.""" 263 | 264 | n0 = en_values[scheme][0] 265 | e0 = en_values[scheme][1] 266 | f0 = en_values[scheme][2] 267 | 268 | theta0 = en_values[scheme][3] 269 | landa0 = en_values[scheme][4] 270 | 271 | a = abe_values[scheme][0] 272 | b = abe_values[scheme][1] 273 | e2 = abe_values[scheme][2] 274 | 275 | theta = float(lat_dec) /360.0 *2.0*math.pi 276 | landa = float(long_dec) /360.0 *2.0*math.pi 277 | 278 | n = (a-b) / (a+b) 279 | v = a * f0 * math.pow( (1 - e2 * math.sin(theta)*math.sin(theta)), -0.5 ) 280 | ro = a * f0 * (1 - e2) * math.pow( (1 - e2 * math.sin(theta)*math.sin(theta)), -1.5 ) 281 | nu2 = v/ro - 1 282 | 283 | M = b * f0 * ( \ 284 | (1.0 + n + 5.0/4.0 *n*n + 5.0/4.0 *n*n*n) * (theta-theta0) - \ 285 | (3.0*n + 3.0*n*n + 21.0/8.0 *n*n*n) *math.sin(theta-theta0) *math.cos(theta+theta0) + \ 286 | (15.0/8.0*n*n + 15.0/8.0*n*n*n) *math.sin(2.0*(theta-theta0)) *math.cos(2.0*(theta+theta0)) - \ 287 | 35.0/24.0*n*n*n *math.sin(3.0*(theta-theta0)) *math.cos(3.0*(theta+theta0)) \ 288 | ) 289 | 290 | I = M + n0 291 | II = v/2.0 * math.sin(theta) * math.cos(theta) 292 | III = v/24.0 * math.sin(theta) * math.pow( math.cos(theta),3 ) * \ 293 | (5.0 - math.pow(math.tan(theta),2) + 9.0*nu2) 294 | IIIa = v/720.0 * math.sin(theta) * math.pow( math.cos(theta),5 ) * \ 295 | ( 61.0 - 58.0 *math.pow(math.tan(theta),2) + math.pow(math.tan(theta),4) ) 296 | IV = v * math.cos(theta) 297 | V = v/6.0 * math.pow( math.cos(theta),3 ) * \ 298 | ( v/ro - math.pow(math.tan(theta),2) ) 299 | VI = v/120.0 * math.pow(math.cos(theta),5) * \ 300 | ( 5.0 - 18.0 *math.pow(math.tan(theta),2) + \ 301 | math.pow(math.tan(theta),4) + 14.0*nu2 - \ 302 | 58.0 * math.pow(math.tan(theta),2)*nu2 ) 303 | 304 | northing = I + II*math.pow(landa-landa0,2) + \ 305 | III*math.pow(landa-landa0,4) + \ 306 | IIIa*math.pow(landa-landa0,6) 307 | easting = e0 + IV*(landa-landa0) + V*math.pow(landa-landa0,3) + \ 308 | VI*math.pow(landa-landa0,5) 309 | 310 | return (easting,northing) 311 | 312 | def turn_eastingnorthing_into_latlong(easting,northing,scheme): 313 | """Turn OSGB36 or OSIE36 easting and northing values into (decimal) lat/long values in OSGB36 / OSIE36. See http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/guide7.html for the calculations, and http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34h.html for some background.""" 314 | 315 | n0 = en_values[scheme][0] 316 | e0 = en_values[scheme][1] 317 | f0 = en_values[scheme][2] 318 | 319 | theta0 = en_values[scheme][3] 320 | landa0 = en_values[scheme][4] 321 | 322 | a = abe_values[scheme][0] 323 | b = abe_values[scheme][1] 324 | e2 = abe_values[scheme][2] 325 | 326 | n = (a-b) / (a+b) 327 | 328 | # Prepare to iterate 329 | M = 0 330 | theta = theta0 331 | # Iterate, 4 times should be enough 332 | for i in range(4): 333 | theta = ((northing - n0 - M) / (a * f0)) + theta 334 | M = b * f0 * ( \ 335 | (1.0 + n + 5.0/4.0 *n*n + 5.0/4.0 *n*n*n) * (theta-theta0) - \ 336 | (3.0*n + 3.0*n*n + 21.0/8.0 *n*n*n) *math.sin(theta-theta0) *math.cos(theta+theta0) + \ 337 | (15.0/8.0*n*n + 15.0/8.0*n*n*n) *math.sin(2.0*(theta-theta0)) *math.cos(2.0*(theta+theta0)) - \ 338 | 35.0/24.0*n*n*n *math.sin(3.0*(theta-theta0)) *math.cos(3.0*(theta+theta0)) \ 339 | ) 340 | 341 | # Compute intermediate values 342 | v = a * f0 * math.pow( (1 - e2 * math.sin(theta)*math.sin(theta)), -0.5 ) 343 | ro = a * f0 * (1 - e2) * math.pow( (1 - e2 * math.sin(theta)*math.sin(theta)), -1.5 ) 344 | nu2 = v/ro - 1 345 | tantheta2 = math.pow(math.tan(theta),2) 346 | 347 | VII = math.tan(theta) / (2 * ro * v) 348 | VIII = math.tan(theta) / (24 * ro * math.pow(v,3)) \ 349 | * (5 + 3 * tantheta2 + nu2 - \ 350 | 9 * tantheta2 * nu2 ) 351 | IX = math.tan(theta) / (720 * ro * math.pow(v,5)) \ 352 | * (61 + 90 * tantheta2 + 45 * tantheta2 * tantheta2) 353 | X = 1 / (math.cos(theta) * v) 354 | XI = 1 / (math.cos(theta) * 6 * math.pow(v,3)) \ 355 | * (v/ro + 2*tantheta2) 356 | XII = 1 / (math.cos(theta) * 120 * math.pow(v,5)) \ 357 | * (5 + 28 * tantheta2 + 24 * tantheta2 * tantheta2) 358 | XIIa = 1 / (math.cos(theta) * 5040 * math.pow(v,7)) \ 359 | * (61 + 662 * tantheta2 + 1320 * tantheta2 * tantheta2 \ 360 | + 720 * tantheta2 * tantheta2 * tantheta2) 361 | 362 | lat_rad = theta - VII * math.pow((easting-e0),2) \ 363 | + VIII * math.pow((easting-e0),4) \ 364 | - IX * math.pow((easting-e0),6) 365 | long_rad = landa0 + X * (easting-e0) \ 366 | - XI * math.pow((easting-e0),3) \ 367 | + XII * math.pow((easting-e0),5) \ 368 | - XIIa * math.pow((easting-e0),7) 369 | 370 | lat = lat_rad / 2.0 / math.pi * 360.0 371 | long = long_rad / 2.0 / math.pi * 360.0 372 | 373 | return (lat,long) 374 | 375 | ############################################################## 376 | # Cassini Easting/Northing Transform Methods # 377 | ############################################################## 378 | 379 | def turn_latlong_into_cassini_en(lat_dec,long_dec,scheme): 380 | """Latitude and Longitude, into Cassini-Soldner easting and northing co-ordinates, in the given scheme. See http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34g.html for details of the calculation used""" 381 | 382 | a = abe_values[scheme][0] 383 | b = abe_values[scheme][1] 384 | e2 = abe_values[scheme][2] 385 | 386 | e4 = e2 * e2 387 | e6 = e2 * e2 * e2 388 | 389 | theta = float(lat_dec) /360.0 *2.0*math.pi 390 | landa = float(long_dec) /360.0 *2.0*math.pi 391 | 392 | theta0 = cassini_values[scheme][0] 393 | landa0 = cassini_values[scheme][1] 394 | false_easting = cassini_values[scheme][2] 395 | false_northing = cassini_values[scheme][3] 396 | 397 | # Compute intermediate values 398 | A = (landa - landa0) * math.cos(theta) 399 | T = math.tan(theta) * math.tan(theta) 400 | C = e2 / (1.0 - e2) * math.cos(theta) * math.cos(theta) 401 | v = a / math.sqrt( 1 - (e2 * math.sin(theta) * math.sin(theta)) ) 402 | 403 | A2 = A ** 2 404 | A3 = A ** 3 405 | A4 = A ** 4 406 | A5 = A ** 5 407 | 408 | # And M, which is how far along the meridian our latitude is from the origin 409 | def makeM(picked_theta): 410 | return a * ( 411 | (1.0 - e2/4.0 - 3.0*e4/64.0 - 5.0*e6/256.0) * picked_theta 412 | - (3.0*e2/8.0 + 3.0*e4/32.0 + 45.0*e6/1024.0) * math.sin(2.0*picked_theta) 413 | + (15.0*e4/256.0 + 45.0*e6/1024.0) * math.sin(4.0*picked_theta) 414 | - (35.0*e6/3072.0) * math.sin(6.0*picked_theta) 415 | ) 416 | M = makeM(theta) 417 | M0 = makeM(theta0) 418 | 419 | # Now calculate 420 | easting = false_easting + v * ( 421 | A - T * A3 / 6.0 - (8.0 - T + 8.0*C) * T * A5 / 120.0 ) 422 | northing = false_northing + M - M0 + v * math.tan(theta) * ( 423 | A2 / 2.0 + (5.0 - T + 6.0*C) * A4 / 24.0 ) 424 | 425 | return (easting,northing) 426 | 427 | def turn_cassini_en_into_latlong(easting,northing,scheme): 428 | """Cassini-Soldner easting and northing, into Latitude and Longitude, in the given scheme. See http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs34g.html for details of the calculation used""" 429 | 430 | a = abe_values[scheme][0] 431 | b = abe_values[scheme][1] 432 | e2 = abe_values[scheme][2] 433 | 434 | e4 = e2 * e2 435 | e6 = e2 * e2 * e2 436 | 437 | theta0 = cassini_values[scheme][0] 438 | landa0 = cassini_values[scheme][1] 439 | false_easting = cassini_values[scheme][2] 440 | false_northing = cassini_values[scheme][3] 441 | 442 | def makeM(picked_theta): 443 | return a * ( 444 | (1.0 - e2/4.0 - 3.0*e4/64.0 - 5.0*e6/256.0) * picked_theta 445 | - (3.0*e2/8.0 + 3.0*e4/32.0 + 45.0*e6/1024.0) * math.sin(2.0*picked_theta) 446 | + (15.0*e4/256.0 + 45.0*e6/1024.0) * math.sin(4.0*picked_theta) 447 | - (35.0*e6/3072.0) * math.sin(6.0*picked_theta) 448 | ) 449 | 450 | # Compute first batch of intermediate values 451 | M1 = makeM(theta0) + (northing - false_northing) 452 | mu1 = M1 / (a * (1.0 - e2/4.0 - 3.0*e4/64.0 - 5.0*e6/256.0) ) 453 | e1 = (1 - ((1-e2) ** 0.5)) / (1 + ((1-e2) ** 0.5)) 454 | 455 | e1_2 = e1 ** 2 456 | e1_3 = e1 ** 3 457 | e1_4 = e1 ** 4 458 | 459 | # Now compute theta1 at T1 460 | theta1 = mu1 + ( 461 | + (3.0*e1 / 2.0 - 27.0*e1_3 / 32.0) * math.sin(2.0*mu1) 462 | + (21.0*e1_2 / 16.0 - 55.0*e1_4 / 32.0) * math.sin(4.0*mu1) 463 | + (151.0*e1_3 / 96.0) * math.sin(6.0*mu1) 464 | + (1097.0*e1_4 / 512.0) * math.sin(8.0*mu1) 465 | ) 466 | T1 = (math.tan(theta1)) ** 2 467 | 468 | # Now we can find v1, ro1 and D 469 | v1 = a / math.sqrt( 1.0 - (e2 * math.sin(theta1) * math.sin(theta1)) ) 470 | ro1 = a * (1 - e2) / ((1 - e2 * math.sin(theta1) * math.sin(theta1)) ** 1.5) 471 | D = (easting - false_easting) / v1 472 | 473 | # And finally the lat and long 474 | lat = theta1 - (v1 * math.tan(theta1)) / ro1 * ( 475 | D*D/2.0 - (1.0 + 3.0 * T1) * ( (D**4) / 24.0 ) ) 476 | long = landa0 + ( 477 | D - T1 * (D**3) / 3.0 + (1 + 3.0 * T1) * T1 * (D**5) / 15.0 478 | ) / math.cos(theta1) 479 | 480 | # Now make decimal versions 481 | lat_dec = lat * 360.0 / 2.0 / math.pi 482 | long_dec = long * 360.0 / 2.0 / math.pi 483 | 484 | return (lat_dec,long_dec) 485 | 486 | ############################################################## 487 | # OS Specific Methods Follow # 488 | ############################################################## 489 | 490 | def turn_easting_northing_into_six_fig(easting,northing): 491 | """Turn OS easting and northing values into the six figure OS grid refecence. See http://www.jstott.me.uk/jscoord/""" 492 | first_letter = "" 493 | second_letter = "" 494 | 495 | easting = int(easting) 496 | northing = int(northing) 497 | 498 | # Get the 100 km part 499 | hkm_east = int( math.floor(easting / 100000.0) ) 500 | hkm_north = int( math.floor(northing / 100000.0) ) 501 | if hkm_north < 5: 502 | if hkm_east < 5: 503 | first_letter = "S" 504 | else: 505 | first_letter = "T" 506 | elif hkm_north < 10: 507 | if hkm_east < 5: 508 | first_letter = "N" 509 | else: 510 | first_letter = "O" 511 | else: 512 | first_letter = "H" 513 | 514 | # Get the 10km part 515 | index = 65 + ((4 - (hkm_north % 5)) * 5) + (hkm_east % 5) 516 | ti = index 517 | if index >= 73: 518 | index += 1 519 | second_letter = chr(index) 520 | 521 | # Get digits 2-4 on easting and northing 522 | e = math.floor( (easting - (100000.0 * hkm_east)) / 100.0) 523 | n = math.floor( (northing - (100000.0 * hkm_north)) / 100.0) 524 | e = "%03d" % e 525 | n = "%03d" % n 526 | 527 | return first_letter + second_letter + e + n 528 | -------------------------------------------------------------------------------- /sacm/parserALMA.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | __author__ = 'sdk' 3 | from sacm import * 4 | from xml.dom import minidom 5 | import pandas as pd 6 | 7 | def getASDM(uid=None): 8 | asdmXML = GetXML(uid,'ASDM') 9 | if asdmXML is not False: 10 | asdm = minidom.parseString(asdmXML) 11 | rows = asdm.getElementsByTagName('Table') 12 | asdmList = list() 13 | for i in rows: 14 | if int(i.getElementsByTagName('NumberRows')[0].firstChild.data) != 0: 15 | #print i.getElementsByTagName('Name')[0].firstChild.data,i.getElementsByTagName('NumberRows')[0].firstChild.data 16 | asdmList.append((i.getElementsByTagName('Name')[0].firstChild.data, 17 | i.getElementsByTagName('NumberRows')[0].firstChild.data, 18 | str(i.getElementsByTagName('Entity')[0].getAttribute('entityTypeName')), 19 | str(i.getElementsByTagName('Entity')[0].getAttribute('entityId')))) 20 | toc = asdm.getElementsByTagName('TimeOfCreation')[0].firstChild.data 21 | 22 | return asdmList, pd.DataFrame(asdmList, columns=['table', 'numrows', 'typename', 'uid'],) , datetime.datetime.strptime(toc.strip()[0:19],"%Y-%m-%dT%H:%M:%S" ) 23 | 24 | else: 25 | return False 26 | 27 | 28 | 29 | 30 | def getMain(uid=None): 31 | mainXML = GetXML(uid,'Main') 32 | if mainXML is not False: 33 | main = minidom.parseString(mainXML) 34 | mainList = list() 35 | rows = main.getElementsByTagName('row') 36 | for i in rows: 37 | #print i.getElementsByTagName('time')[0].firstChild.data, i.getElementsByTagName('stateId')[0].firstChild.data 38 | mainList.append((sdmTimeString(int(i.getElementsByTagName('time')[0].firstChild.data)), 39 | #i.getElementsByTagName('numAntenna')[0].firstChild.data, 40 | i.getElementsByTagName('timeSampling')[0].firstChild.data, 41 | int(i.getElementsByTagName('interval')[0].firstChild.data), 42 | #i.getElementsByTagName('numIntegration')[0].firstChild.data, 43 | int(i.getElementsByTagName('scanNumber')[0].firstChild.data), 44 | int(i.getElementsByTagName('subscanNumber')[0].firstChild.data), 45 | int(i.getElementsByTagName('dataSize')[0].firstChild.data), 46 | i.getElementsByTagName('dataUID')[0].getElementsByTagName('EntityRef')[0].getAttribute('entityId'), 47 | i.getElementsByTagName('fieldId')[0].firstChild.data, 48 | i.getElementsByTagName('stateId')[0].firstChild.data)) 49 | return pd.DataFrame(mainList, columns=['time', 'timeSampling', 'interval', 'scanNumber', 50 | 'subscanNumber', 'dataSize', 'dataUID', 'fieldId', 'stateId']) 51 | else: 52 | return False 53 | 54 | def getAntennas(uid=None): 55 | antennaXML = GetXML(uid,'Antenna') 56 | if antennaXML is not False: 57 | antenna = minidom.parseString(antennaXML) 58 | antennaList = list() 59 | rows = antenna.getElementsByTagName('row') 60 | for i in rows: 61 | antennaList.append(( 62 | i.getElementsByTagName('antennaId')[0].firstChild.data, 63 | i.getElementsByTagName('name')[0].firstChild.data, 64 | i.getElementsByTagName('antennaMake')[0].firstChild.data, 65 | i.getElementsByTagName('dishDiameter')[0].firstChild.data, 66 | i.getElementsByTagName('stationId')[0].firstChild.data, 67 | )) 68 | return pd.DataFrame(antennaList,columns=['antennaId','name','antennaMake','dishDiameter','stationId']) 69 | else: 70 | return False 71 | 72 | 73 | def getCalPhase(uid=None): 74 | calPhaseXML = GetXML(uid,'CalPhase') 75 | if calPhaseXML is not False: 76 | calPhase = minidom.parseString(calPhaseXML) 77 | calPhaseList = list() 78 | rows = calPhase.getElementsByTagName('row') 79 | for i in rows: 80 | calPhaseList.append(( 81 | i.getElementsByTagName('basebandName')[0].firstChild.data, 82 | i.getElementsByTagName('receiverBand')[0].firstChild.data, 83 | i.getElementsByTagName('atmPhaseCorrection')[0].firstChild.data, 84 | i.getElementsByTagName('startValidTime')[0].firstChild.data, 85 | i.getElementsByTagName('endValidTime')[0].firstChild.data, 86 | i.getElementsByTagName('numBaseline')[0].firstChild.data, 87 | i.getElementsByTagName('numReceptor')[0].firstChild.data, 88 | i.getElementsByTagName('ampli')[0].firstChild.data, 89 | i.getElementsByTagName('antennaNames')[0].firstChild.data, 90 | i.getElementsByTagName('baselineLengths')[0].firstChild.data, 91 | i.getElementsByTagName('decorrelationFactor')[0].firstChild.data, 92 | i.getElementsByTagName('direction')[0].firstChild.data, 93 | i.getElementsByTagName('frequencyRange')[0].firstChild.data, 94 | i.getElementsByTagName('integrationTime')[0].firstChild.data, 95 | i.getElementsByTagName('phase')[0].firstChild.data, 96 | i.getElementsByTagName('polarizationTypes')[0].firstChild.data, 97 | i.getElementsByTagName('phaseRMS')[0].firstChild.data, 98 | i.getElementsByTagName('statPhaseRMS')[0].firstChild.data, 99 | i.getElementsByTagName('calDataId')[0].firstChild.data, 100 | i.getElementsByTagName('calReductionId')[0].firstChild.data, 101 | )) 102 | return pd.DataFrame(calPhaseList,columns=['basebandName','receiverBand','atmPhaseCorrection','startValidTime','endValidTime','numBaseline', 103 | 'numReceptor','ampli','antennaNames','baselineLengths','decorrelationFactor','direction', 104 | 'frequencyRange','integrationTime','phase','polarizationTypes','phaseRMS','statPhaseRMS','calDataId','calReductionId']) 105 | else: 106 | return False 107 | 108 | 109 | def getCalDelay(uid=None): 110 | calDelayXML = GetXML(uid,'CalDelay') 111 | if calDelayXML is not False: 112 | calDelay = minidom.parseString(calDelayXML) 113 | calDelayList = list() 114 | rows = calDelay.getElementsByTagName('row') 115 | for i in rows: 116 | calDelayList.append(( 117 | i.getElementsByTagName('basebandName')[0].firstChild.data, 118 | i.getElementsByTagName('receiverBand')[0].firstChild.data, 119 | i.getElementsByTagName('atmPhaseCorrection')[0].firstChild.data, 120 | i.getElementsByTagName('startValidTime')[0].firstChild.data, 121 | i.getElementsByTagName('endValidTime')[0].firstChild.data, 122 | i.getElementsByTagName('numBaseline')[0].firstChild.data, 123 | i.getElementsByTagName('numReceptor')[0].firstChild.data, 124 | i.getElementsByTagName('ampli')[0].firstChild.data, 125 | i.getElementsByTagName('antennaNames')[0].firstChild.data, 126 | i.getElementsByTagName('baselineLengths')[0].firstChild.data, 127 | i.getElementsByTagName('decorrelationFactor')[0].firstChild.data, 128 | i.getElementsByTagName('direction')[0].firstChild.data, 129 | i.getElementsByTagName('frequencyRange')[0].firstChild.data, 130 | i.getElementsByTagName('integrationTime')[0].firstChild.data, 131 | i.getElementsByTagName('phase')[0].firstChild.data, 132 | i.getElementsByTagName('polarizationTypes')[0].firstChild.data, 133 | i.getElementsByTagName('phaseRMS')[0].firstChild.data, 134 | i.getElementsByTagName('statPhaseRMS')[0].firstChild.data, 135 | i.getElementsByTagName('calDataId')[0].firstChild.data, 136 | i.getElementsByTagName('calReductionId')[0].firstChild.data, 137 | )) 138 | return pd.DataFrame(calDelayList,columns=['basebandName','receiverBand','atmPhaseCorrection','startValidTime','endValidTime','numBaseline', 139 | 'numReceptor','ampli','antennaNames','baselineLengths','decorrelationFactor','direction', 140 | 'frequencyRange','integrationTime','phase','polarizationTypes','phaseRMS','statPhaseRMS','calDataId','calReductionId']) 141 | else: 142 | return False 143 | 144 | def getSBSummary(uid=None): 145 | summaryXML = GetXML(uid,'SBSummary') 146 | if summaryXML is not False: 147 | summary = minidom.parseString(summaryXML) 148 | summaryList = list() 149 | rows = summary.getElementsByTagName('row') 150 | for i in rows: 151 | summaryList.append((i.getElementsByTagName('sbSummaryUID')[0].getElementsByTagName('EntityRef')[0].getAttribute('entityId'), 152 | i.getElementsByTagName('projectUID')[0].getElementsByTagName('EntityRef')[0].getAttribute('entityId'), 153 | i.getElementsByTagName('obsUnitSetUID')[0].getElementsByTagName('EntityRef')[0].getAttribute('entityId'), 154 | float(i.getElementsByTagName('frequency')[0].firstChild.data), 155 | i.getElementsByTagName('frequencyBand')[0].firstChild.data, 156 | i.getElementsByTagName('scienceGoal')[0].firstChild.data, 157 | i.getElementsByTagName('weatherConstraint')[0].firstChild.data )) 158 | 159 | return pd.DataFrame(summaryList, columns=['sbSummaryUID', 'projectUID', 'obsUnitSetUID', 'frequency', 160 | 'frequencyBand', 'scienceGoal', 'weatherConstraint']) 161 | else: 162 | return False 163 | 164 | def getScan(uid=None): 165 | scanXML = GetXML(uid,'Scan') 166 | if scanXML is not False: 167 | scan = minidom.parseString(scanXML) 168 | scanList = list() 169 | rows = scan.getElementsByTagName('row') 170 | for i in rows: 171 | try: 172 | scanList.append((int(i.getElementsByTagName('scanNumber')[0].firstChild.data), 173 | int(i.getElementsByTagName('startTime')[0].firstChild.data), 174 | int(i.getElementsByTagName('endTime')[0].firstChild.data), 175 | #i.getElementsByTagName('numIntent')[0].firstChild.data, 176 | int(i.getElementsByTagName('numSubscan')[0].firstChild.data), 177 | arrayParser(i.getElementsByTagName('scanIntent')[0].firstChild.data, 1), 178 | arrayParser(i.getElementsByTagName('calDataType')[0].firstChild.data, 1), 179 | int(i.getElementsByTagName('numField')[0].firstChild.data), 180 | i.getElementsByTagName('fieldName')[0].firstChild.data, 181 | i.getElementsByTagName('sourceName')[0].firstChild.data)) 182 | except IndexError as e: 183 | scanList.append((int(i.getElementsByTagName('scanNumber')[0].firstChild.data), 184 | int(i.getElementsByTagName('startTime')[0].firstChild.data), 185 | int(i.getElementsByTagName('endTime')[0].firstChild.data), 186 | #i.getElementsByTagName('numIntent')[0].firstChild.data, 187 | int(i.getElementsByTagName('numSubscan')[0].firstChild.data), 188 | arrayParser(i.getElementsByTagName('scanIntent')[0].firstChild.data, 1), 189 | arrayParser(i.getElementsByTagName('calDataType')[0].firstChild.data, 1), 190 | 0, 191 | u"None", 192 | u"None")) 193 | 194 | 195 | return pd.DataFrame(scanList, columns=['scanNumber', 'startTime', 'endTime', 'numSubscan', 196 | 'scanIntent', 'calDataType', 'numField', 'fieldName', 'sourceName']) 197 | else: 198 | return False 199 | 200 | def getStation(uid=None): 201 | stationXML = GetXML(uid,'Station') 202 | if stationXML is not False: 203 | station = minidom.parseString(stationXML) 204 | stationList = list() 205 | rows = station.getElementsByTagName('row') 206 | for i in rows: 207 | try: 208 | stationList.append(( 209 | i.getElementsByTagName('stationId')[0].firstChild.data, 210 | i.getElementsByTagName('name')[0].firstChild.data, 211 | i.getElementsByTagName('position')[0].firstChild.data, 212 | i.getElementsByTagName('type')[0].firstChild.data, 213 | )) 214 | except IndexError as error: 215 | print error 216 | return False 217 | return pd.DataFrame(stationList ,columns=['stationId','name','position','type']) 218 | 219 | 220 | 221 | def getSubScan(uid=None): 222 | subscanXML = GetXML(uid,'Subscan') 223 | if subscanXML is not False: 224 | subscan = minidom.parseString(subscanXML) 225 | subscanList = list() 226 | rows = subscan.getElementsByTagName('row') 227 | for i in rows: 228 | subscanList.append((int(i.getElementsByTagName('scanNumber')[0].firstChild.data), 229 | int(i.getElementsByTagName('subscanNumber')[0].firstChild.data), 230 | int(i.getElementsByTagName('startTime')[0].firstChild.data), 231 | int(i.getElementsByTagName('endTime')[0].firstChild.data), 232 | i.getElementsByTagName('fieldName')[0].firstChild.data, 233 | i.getElementsByTagName('subscanIntent')[0].firstChild.data, 234 | i.getElementsByTagName('subscanMode')[0].firstChild.data, 235 | i.getElementsByTagName('numIntegration')[0].firstChild.data, 236 | #i.getElementsByTagName('numSubintegration')[0].firstChild.data, 237 | #i.getElementsByTagName('correlatorCalibration')[0].firstChild.data 238 | )) 239 | return pd.DataFrame(subscanList, columns=['scanNumber','subscanNumber','startTime','endTime','fieldName', 240 | 'subscanIntent','subscanMode','numIntegration']) 241 | else: 242 | return False 243 | 244 | 245 | def getSource(uid=None): 246 | sourceXML = GetXML(uid,'Source') 247 | if sourceXML is not False: 248 | source = minidom.parseString(sourceXML) 249 | sourceList = list() 250 | rows = source.getElementsByTagName('row') 251 | #there are missing fields in some rows for the Source table. 252 | for i in rows: 253 | sourceList.append((int(i.getElementsByTagName('sourceId')[0].firstChild.data), 254 | i.getElementsByTagName('timeInterval')[0].firstChild.data, 255 | i.getElementsByTagName('direction')[0].firstChild.data, 256 | i.getElementsByTagName('directionCode')[0].firstChild.data, 257 | i.getElementsByTagName('sourceName')[0].firstChild.data, 258 | i.getElementsByTagName('spectralWindowId')[0].firstChild.data)) 259 | return pd.DataFrame(sourceList,columns=['sourceId','timeInterval','direction','directionCode','sourceName', 260 | 'spectralWindowId']) 261 | else: 262 | return False 263 | 264 | 265 | def getSpectralWindow(uid=None): 266 | spwXML = GetXML(uid,'SpectralWindow') 267 | if spwXML is not False: 268 | spw = minidom.parseString(spwXML) 269 | spwList = list() 270 | rows = spw.getElementsByTagName('row') 271 | for i in rows: 272 | if int(i.getElementsByTagName('numChan')[0].firstChild.data) > 4: 273 | try: 274 | spwList.append((i.getElementsByTagName('spectralWindowId')[0].firstChild.data, 275 | i.getElementsByTagName('basebandName')[0].firstChild.data, 276 | i.getElementsByTagName('netSideband')[0].firstChild.data, 277 | int(i.getElementsByTagName('numChan')[0].firstChild.data), 278 | float(i.getElementsByTagName('refFreq')[0].firstChild.data), 279 | i.getElementsByTagName('sidebandProcessingMode')[0].firstChild.data, 280 | float(i.getElementsByTagName('totBandwidth')[0].firstChild.data), 281 | i.getElementsByTagName('chanFreqStart')[0].firstChild.data, 282 | i.getElementsByTagName('chanFreqStep')[0].firstChild.data, 283 | i.getElementsByTagName('chanWidth')[0].firstChild.data, 284 | i.getElementsByTagName('effectiveBw')[0].firstChild.data, 285 | i.getElementsByTagName('name')[0].firstChild.data, 286 | #i.getElementsByTagName('resolutionArray')[0].firstChild.data, 287 | i.getElementsByTagName('assocNature')[0].firstChild.data, 288 | i.getElementsByTagName('assocSpectralWindowId')[0].firstChild.data)) 289 | except IndexError as e: 290 | print e 291 | 292 | return pd.DataFrame(spwList, columns=['spectralWindowId', 'basebandName', 'netSideband', 'numChan', 293 | 'refFreq', 'sidebandProcessingMode', 'totBandwidth', 'chanFreqStart','chanFreqStep','chanWidth', 294 | 'effectiveBw', 'name', 295 | 'assocNature', 'assocSpectralWindowId']) 296 | else: 297 | return False 298 | 299 | 300 | def getField(uid=None): 301 | fieldXML = GetXML(uid,'Field') 302 | if fieldXML is not False: 303 | field = minidom.parseString(fieldXML) 304 | fieldList = list() 305 | rows = field.getElementsByTagName('row') 306 | for i in rows: 307 | fieldList.append((i.getElementsByTagName('fieldId')[0].firstChild.data, 308 | i.getElementsByTagName('fieldName')[0].firstChild.data, 309 | i.getElementsByTagName('numPoly')[0].firstChild.data, 310 | #i.getElementsByTagName('delayDir')[0].firstChild.data, 311 | #i.getElementsByTagName('phaseDir')[0].firstChild.data, 312 | i.getElementsByTagName('referenceDir')[0].firstChild.data, 313 | int(i.getElementsByTagName('time')[0].firstChild.data), 314 | i.getElementsByTagName('code')[0].firstChild.data, 315 | i.getElementsByTagName('directionCode')[0].firstChild.data, 316 | int(i.getElementsByTagName('sourceId')[0].firstChild.data))) 317 | #return pd.DataFrame(fieldList, columns=['fieldId', 'fieldName', 'numPoly','delayDir','phaseDir','referenceDir', 'time', 'code', 'directionCode', 'sourceId']) 318 | return pd.DataFrame(fieldList, columns=['fieldId', 'fieldName', 'numPoly','referenceDir', 'time', 'code', 'directionCode', 'sourceId']) 319 | else: 320 | return False 321 | 322 | def getSysCal(uid=None): 323 | syscalXML = GetXML(uid,'SysCal') 324 | if syscalXML is not False: 325 | syscal = minidom.parseString(syscalXML) 326 | syscalList = list() 327 | rows = syscal.getElementsByTagName('row') 328 | for i in rows: 329 | syscalList.append(( 330 | i.getElementsByTagName('timeInterval')[0].firstChild.data, 331 | i.getElementsByTagName('numReceptor')[0].firstChild.data, 332 | i.getElementsByTagName('numChan')[0].firstChild.data, 333 | i.getElementsByTagName('tcalFlag')[0].firstChild.data, 334 | i.getElementsByTagName('tcalSpectrum')[0].firstChild.data, 335 | i.getElementsByTagName('trxFlag')[0].firstChild.data, 336 | i.getElementsByTagName('trxSpectrum')[0].firstChild.data, 337 | i.getElementsByTagName('tskyFlag')[0].firstChild.data, 338 | i.getElementsByTagName('tskySpectrum')[0].firstChild.data, 339 | i.getElementsByTagName('tsysFlag')[0].firstChild.data, 340 | i.getElementsByTagName('tsysSpectrum')[0].firstChild.data, 341 | i.getElementsByTagName('antennaId')[0].firstChild.data.strip(), 342 | i.getElementsByTagName('feedId')[0].firstChild.data, 343 | i.getElementsByTagName('spectralWindowId')[0].firstChild.data.strip() )) 344 | return pd.DataFrame(syscalList, columns=['timeInterval','numReceptor','numChan','tcalFlag','tcalSpectrum','trxFlag', 345 | 'trxSpectrum','tskyFlag','tskySpectrum','tsysFlag','tsysSpectrum','antennaId', 346 | 'feedId','spectralWindowId']) 347 | else: 348 | return False 349 | 350 | 351 | def getSBData(sbuid=None): 352 | schedXML = GetXML(sbuid, 'SchedBlock') 353 | sched = minidom.parseString(schedXML) 354 | 355 | schedList = list() 356 | rowsBL = sched.getElementsByTagName('sbl:BLSpectralWindow') 357 | rowsACA = sched.getElementsByTagName('sbl:ACASpectralWindow') 358 | rows = rowsBL if len(rowsBL) > len(rowsACA) else rowsACA 359 | for i in rows: 360 | brother = i.parentNode.getElementsByTagName('sbl:BaseBandSpecificationRef') 361 | parent = i.parentNode.parentNode.parentNode 362 | schedList.append(( 363 | parent.getAttribute('entityPartId'), 364 | parent.getAttribute('switchingType'), 365 | #parent.getAttribute('receiverType'), 366 | parent.getElementsByTagName('sbl:name')[0].firstChild.data, 367 | brother[0].getAttribute('entityId'), 368 | brother[0].getAttribute('partId'), 369 | #brother[0].getAttribute('entityTypeName'), 370 | #i.getAttribute('sideBand'), 371 | #i.getAttribute('windowFunction'), 372 | i.getAttribute('polnProducts'), 373 | #i.getAttribute('correlationBits'), 374 | i.getElementsByTagName('sbl:centerFrequency')[0].firstChild.data, 375 | i.getElementsByTagName('sbl:centerFrequency')[0].getAttribute('unit'), 376 | #i.getElementsByTagName('sbl:spectralAveragingFactor')[0].firstChild.data, 377 | #i.getElementsByTagName('sbl:name')[0].firstChild.data, 378 | i.getElementsByTagName('sbl:effectiveBandwidth')[0].firstChild.data, 379 | i.getElementsByTagName('sbl:effectiveBandwidth')[0].getAttribute('unit'), 380 | i.getElementsByTagName('sbl:effectiveNumberOfChannels')[0].firstChild.data, 381 | #i.getElementsByTagName('sbl:useThisSpectralWindow')[0].firstChild.data, 382 | i.getElementsByTagName('sbl:ChannelAverageRegion')[0].getElementsByTagName('sbl:startChannel')[0].firstChild.data, 383 | i.getElementsByTagName('sbl:ChannelAverageRegion')[0].getElementsByTagName('sbl:numberChannels')[0].firstChild.data, 384 | 385 | )) 386 | 387 | specs = pd.DataFrame(schedList) 388 | 389 | rows = sched.getElementsByTagName('sbl:BaseBandSpecification') 390 | bbList = list() 391 | 392 | for i in rows: 393 | parent = i.parentNode 394 | bbList.append(( 395 | parent.getAttribute('receiverBand'), 396 | parent.getAttribute('dopplerReference'), 397 | parent.getElementsByTagName('sbl:restFrequency')[0].firstChild.data, 398 | parent.getElementsByTagName('sbl:restFrequency')[0].getAttribute('unit'), 399 | parent.getElementsByTagName('sbl:frequencySwitching')[0].firstChild.data, 400 | parent.getElementsByTagName('sbl:lO2Frequency')[0].firstChild.data, 401 | parent.getElementsByTagName('sbl:lO2Frequency')[0].getAttribute('unit'), 402 | #parent.getElementsByTagName('sbl:weighting')[0].firstChild.data, 403 | #parent.getElementsByTagName('sbl:useUSB')[0].firstChild.data, 404 | #parent.getElementsByTagName('sbl:use12GHzFilter')[0].firstChild.data, 405 | #parent.getElementsByTagName('sbl:imageCenterFrequency')[0].firstChild.data, 406 | #parent.getElementsByTagName('sbl:imageCenterFrequency')[0].getAttribute('unit'), 407 | i.getAttribute('entityPartId'), 408 | i.getAttribute('baseBandName'), 409 | #i.getAttribute('sideBandPreference'), 410 | i.getElementsByTagName('sbl:centerFrequency')[0].firstChild.data, 411 | i.getElementsByTagName('sbl:lO2Frequency')[0].firstChild.data, 412 | i.getElementsByTagName('sbl:lO2Frequency')[0].getAttribute('unit'), 413 | #i.getElementsByTagName('sbl:weighting')[0].firstChild.data, 414 | #i.getElementsByTagName('sbl:useUSB')[0].firstChild.data, 415 | #i.getElementsByTagName('sbl:use12GHzFilter')[0].firstChild.data, 416 | #i.getElementsByTagName('sbl:imageCenterFrequency')[0].firstChild.data, 417 | #i.getElementsByTagName('sbl:imageCenterFrequency')[0].getAttribute('unit') 418 | )) 419 | 420 | bb = pd.DataFrame(bbList) 421 | targetList = list() 422 | rows = sched.getElementsByTagName('sbl:Target') 423 | for i in rows: 424 | targetList.append(( 425 | i.getAttribute('entityPartId'), 426 | i.getElementsByTagName('sbl:AbstractInstrumentSpecRef')[0].getAttribute('partId'), 427 | i.getElementsByTagName('sbl:FieldSourceRef')[0].getAttribute('partId'), 428 | i.getElementsByTagName('sbl:ObservingParametersRef')[0].getAttribute('partId'), 429 | )) 430 | 431 | target = pd.DataFrame(targetList, columns=['entityPartId', 'InstrumentSpec', 'FieldSource', 'ObsParameter']) 432 | 433 | rows = sched.getElementsByTagName('sbl:ScienceParameters') 434 | scienceList = list() 435 | for i in rows: 436 | scienceList.append(( 437 | i.getAttribute('entityPartId'), 438 | i.getElementsByTagName('sbl:name')[0].firstChild.data, 439 | i.getElementsByTagName('sbl:representativeBandwidth')[0].firstChild.data, 440 | i.getElementsByTagName('sbl:representativeBandwidth')[0].getAttribute('unit'), 441 | i.getElementsByTagName('sbl:representativeFrequency')[0].firstChild.data, 442 | i.getElementsByTagName('sbl:representativeFrequency')[0].getAttribute('unit'), 443 | i.getElementsByTagName('sbl:sensitivityGoal')[0].firstChild.data, 444 | i.getElementsByTagName('sbl:sensitivityGoal')[0].getAttribute('unit'), 445 | i.getElementsByTagName('sbl:integrationTime')[0].firstChild.data, 446 | i.getElementsByTagName('sbl:integrationTime')[0].getAttribute('unit'), 447 | i.getElementsByTagName('sbl:subScanDuration')[0].firstChild.data, 448 | i.getElementsByTagName('sbl:subScanDuration')[0].getAttribute('unit'), 449 | i.getElementsByTagName('sbl:forceAtmCal')[0].firstChild.data 450 | )) 451 | 452 | science = pd.DataFrame(scienceList) 453 | 454 | rows = sched.getElementsByTagName('sbl:PhaseCalParameters') 455 | phaseList = list() 456 | for i in rows: 457 | phaseList.append(( 458 | i.getAttribute('entityPartId'), 459 | #i.getElementsByTagName('sbl:name')[0].firstChild.data, 460 | i.getElementsByTagName('sbl:cycleTime')[0].firstChild.data, 461 | i.getElementsByTagName('sbl:cycleTime')[0].getAttribute('unit'), 462 | i.getElementsByTagName('sbl:defaultIntegrationTime')[0].firstChild.data, 463 | i.getElementsByTagName('sbl:defaultIntegrationTime')[0].getAttribute('unit'), 464 | i.getElementsByTagName('sbl:subScanDuration')[0].firstChild.data, 465 | i.getElementsByTagName('sbl:subScanDuration')[0].getAttribute('unit'), 466 | i.getElementsByTagName('sbl:forceAtmCal')[0].firstChild.data, 467 | i.getElementsByTagName('sbl:forceExecution')[0].firstChild.data 468 | )) 469 | 470 | phase = pd.DataFrame(phaseList) 471 | 472 | rows = sched.getElementsByTagName('sbl:FieldSource') 473 | fieldList = list() 474 | for i in rows: 475 | fieldList.append(( 476 | i.getAttribute('entityPartId'), 477 | i.getAttribute('solarSystemObject'), 478 | i.getElementsByTagName('sbl:sourceName')[0].firstChild.data, 479 | #i.getElementsByTagName('sbl:sourceEphemeris')[0].firstChild.data, 480 | i.getElementsByTagName('sbl:name')[0].firstChild.data, 481 | )) 482 | 483 | field = pd.DataFrame(fieldList) 484 | return bb,specs,target,phase,science,field 485 | 486 | def getSBFields(sbuid=None): 487 | schedXML = GetXML(sbuid, 'SchedBlock') 488 | sched = minidom.parseString(schedXML) 489 | 490 | rows = sched.getElementsByTagName('sbl:FieldSource') 491 | fieldList = list() 492 | for i in rows: 493 | fieldList.append(( 494 | i.getAttribute('entityPartId'), 495 | i.getAttribute('solarSystemObject'), 496 | i.getElementsByTagName('sbl:sourceName')[0].firstChild.data, 497 | #i.getElementsByTagName('sbl:sourceEphemeris')[0].firstChild.data, 498 | i.getElementsByTagName('sbl:name')[0].firstChild.data, 499 | i.getElementsByTagName('sbl:sourceCoordinates')[0].getElementsByTagName('val:longitude')[0].firstChild.data, 500 | i.getElementsByTagName('sbl:sourceCoordinates')[0].getElementsByTagName('val:latitude')[0].firstChild.data, 501 | 502 | )) 503 | 504 | field = pd.DataFrame(fieldList, columns=['entityPartId','solarSystemObject','sourceName','name','longitude','latitude']) 505 | return field 506 | 507 | def getSBScience(sbuid=None): 508 | schedXML = GetXML(sbuid, 'SchedBlock') 509 | sched = minidom.parseString(schedXML) 510 | 511 | rows = sched.getElementsByTagName('sbl:ScienceParameters') 512 | scienceList = list() 513 | for i in rows: 514 | scienceList.append(( 515 | i.getAttribute('entityPartId'), 516 | i.getElementsByTagName('sbl:name')[0].firstChild.data, 517 | i.getElementsByTagName('sbl:representativeBandwidth')[0].firstChild.data, 518 | i.getElementsByTagName('sbl:representativeBandwidth')[0].getAttribute('unit'), 519 | i.getElementsByTagName('sbl:representativeFrequency')[0].firstChild.data, 520 | i.getElementsByTagName('sbl:representativeFrequency')[0].getAttribute('unit'), 521 | i.getElementsByTagName('sbl:sensitivityGoal')[0].firstChild.data, 522 | i.getElementsByTagName('sbl:sensitivityGoal')[0].getAttribute('unit'), 523 | i.getElementsByTagName('sbl:integrationTime')[0].firstChild.data, 524 | i.getElementsByTagName('sbl:integrationTime')[0].getAttribute('unit'), 525 | i.getElementsByTagName('sbl:subScanDuration')[0].firstChild.data, 526 | i.getElementsByTagName('sbl:subScanDuration')[0].getAttribute('unit'), 527 | i.getElementsByTagName('sbl:forceAtmCal')[0].firstChild.data 528 | )) 529 | 530 | science = pd.DataFrame(scienceList, columns=['entityPartId','name','representativeBandwidth','unit_rb','representativeFrequency','unit_rf', 531 | 'sensitivityGoal','unit_sg','integrationTime','unit_it','subScanDuration','unit_sc','forceAtmCal']) 532 | return science 533 | 534 | def getSBTargets(sbuid=None): 535 | schedXML = GetXML(sbuid, 'SchedBlock') 536 | sched = minidom.parseString(schedXML) 537 | targetList = list() 538 | rows = sched.getElementsByTagName('sbl:Target') 539 | for i in rows: 540 | targetList.append(( 541 | i.getAttribute('entityPartId'), 542 | i.getElementsByTagName('sbl:AbstractInstrumentSpecRef')[0].getAttribute('partId'), 543 | i.getElementsByTagName('sbl:FieldSourceRef')[0].getAttribute('partId'), 544 | i.getElementsByTagName('sbl:ObservingParametersRef')[0].getAttribute('partId'), 545 | )) 546 | 547 | target = pd.DataFrame(targetList, columns=['entityPartId', 'InstrumentSpec', 'FieldSource', 'ObsParameter']) 548 | return target 549 | 550 | def getSBOffsets(sbuid=None): 551 | schedXML = GetXML(sbuid, 'SchedBlock') 552 | sched = minidom.parseString(schedXML) 553 | offsetList = list() 554 | rows = sched.getElementsByTagName('sbl:phaseCenterCoordinates') 555 | for i in rows: 556 | offsetList.append(( 557 | i.parentNode.parentNode.getAttribute('entityPartId'), 558 | i.getAttribute('system'), 559 | i.getAttribute('type'), 560 | i.getElementsByTagName('val:longitude')[0].firstChild.data, 561 | i.getElementsByTagName('val:longitude')[0].getAttribute('unit'), 562 | i.getElementsByTagName('val:latitude')[0].firstChild.data, 563 | i.getElementsByTagName('val:latitude')[0].getAttribute('unit'), 564 | )) 565 | 566 | offset = pd.DataFrame(offsetList, columns=['partId','system', 'type', 'longitude','lon_unit', 'latitude','lat_unit']) 567 | return offset 568 | 569 | def getScienceGoal(prjUID=None): 570 | projXML = GetXML(prjUID, 'ObsProject') 571 | proj = minidom.parseString(projXML) 572 | scienceGoalList = list() 573 | rows = proj.getElementsByTagName('prj:ScienceSpectralWindow') 574 | 575 | for i in rows: 576 | scienceGoalList.append(( 577 | i.parentNode.parentNode.getElementsByTagName('prj:name')[0].firstChild.data, 578 | i.parentNode.parentNode.getElementsByTagName('prj:ObsUnitSetRef')[0].getAttribute('entityId'), 579 | i.parentNode.parentNode.getElementsByTagName('prj:ObsUnitSetRef')[0].getAttribute('partId'), 580 | i.parentNode.getElementsByTagName('prj:representativeFrequency')[0].firstChild.data, 581 | i.parentNode.getElementsByTagName('prj:userRepresentativeFrequency')[0].firstChild.data, 582 | i.getElementsByTagName('prj:centerFrequency')[0].firstChild.data, 583 | i.getElementsByTagName('prj:representativeWindow')[0].firstChild.data, 584 | )) 585 | 586 | scienceGoal = pd.DataFrame(scienceGoalList) 587 | return scienceGoal 588 | 589 | 590 | 591 | def getSB_spectralconf(sbuid=None): 592 | schedXML = GetXML(sbuid, 'SchedBlock') 593 | sched = minidom.parseString(schedXML) 594 | 595 | schedList = list() 596 | rowsBL = sched.getElementsByTagName('sbl:BLSpectralWindow') 597 | rowsACA = sched.getElementsByTagName('sbl:ACASpectralWindow') 598 | rows = rowsBL if len(rowsBL) > len(rowsACA) else rowsACA 599 | for i in rows: 600 | brother = i.parentNode.getElementsByTagName('sbl:BaseBandSpecificationRef') 601 | parent = i.parentNode.parentNode.parentNode 602 | schedList.append(( 603 | parent.getAttribute('entityPartId'), 604 | parent.getAttribute('switchingType'), 605 | #parent.getAttribute('receiverType'), 606 | parent.getElementsByTagName('sbl:name')[0].firstChild.data, 607 | brother[0].getAttribute('entityId'), 608 | brother[0].getAttribute('partId'), 609 | #brother[0].getAttribute('entityTypeName'), 610 | #i.getAttribute('sideBand'), 611 | #i.getAttribute('windowFunction'), 612 | #i.getAttribute('polnProducts'), 613 | #i.getAttribute('correlationBits'), 614 | #i.getElementsByTagName('sbl:centerFrequency')[0].firstChild.data, 615 | #i.getElementsByTagName('sbl:centerFrequency')[0].getAttribute('unit'), 616 | #i.getElementsByTagName('sbl:spectralAveragingFactor')[0].firstChild.data, 617 | #i.getElementsByTagName('sbl:name')[0].firstChild.data, 618 | #i.getElementsByTagName('sbl:effectiveBandwidth')[0].firstChild.data, 619 | #i.getElementsByTagName('sbl:effectiveBandwidth')[0].getAttribute('unit'), 620 | #i.getElementsByTagName('sbl:effectiveNumberOfChannels')[0].firstChild.data, 621 | #i.getElementsByTagName('sbl:useThisSpectralWindow')[0].firstChild.data, 622 | #i.getElementsByTagName('sbl:ChannelAverageRegion')[0].getElementsByTagName('sbl:startChannel')[0].firstChild.data, 623 | #i.getElementsByTagName('sbl:ChannelAverageRegion')[0].getElementsByTagName('sbl:numberChannels')[0].firstChild.data, 624 | 625 | )) 626 | 627 | specs = pd.DataFrame(schedList) 628 | 629 | rows = sched.getElementsByTagName('sbl:BaseBandSpecification') 630 | bbList = list() 631 | 632 | for i in rows: 633 | parent = i.parentNode 634 | bbList.append(( 635 | parent.getAttribute('receiverBand'), 636 | #parent.getAttribute('dopplerReference'), 637 | #parent.getElementsByTagName('sbl:restFrequency')[0].firstChild.data, 638 | #parent.getElementsByTagName('sbl:restFrequency')[0].getAttribute('unit'), 639 | #parent.getElementsByTagName('sbl:frequencySwitching')[0].firstChild.data, 640 | #parent.getElementsByTagName('sbl:lO2Frequency')[0].firstChild.data, 641 | #parent.getElementsByTagName('sbl:lO2Frequency')[0].getAttribute('unit'), 642 | #parent.getElementsByTagName('sbl:weighting')[0].firstChild.data, 643 | #parent.getElementsByTagName('sbl:useUSB')[0].firstChild.data, 644 | #parent.getElementsByTagName('sbl:use12GHzFilter')[0].firstChild.data, 645 | #parent.getElementsByTagName('sbl:imageCenterFrequency')[0].firstChild.data, 646 | #parent.getElementsByTagName('sbl:imageCenterFrequency')[0].getAttribute('unit'), 647 | i.getAttribute('entityPartId'), 648 | i.getAttribute('baseBandName'), 649 | #i.getAttribute('sideBandPreference'), 650 | #i.getElementsByTagName('sbl:centerFrequency')[0].firstChild.data, 651 | #i.getElementsByTagName('sbl:lO2Frequency')[0].firstChild.data, 652 | #i.getElementsByTagName('sbl:lO2Frequency')[0].getAttribute('unit'), 653 | #i.getElementsByTagName('sbl:weighting')[0].firstChild.data, 654 | #i.getElementsByTagName('sbl:useUSB')[0].firstChild.data, 655 | #i.getElementsByTagName('sbl:use12GHzFilter')[0].firstChild.data, 656 | #i.getElementsByTagName('sbl:imageCenterFrequency')[0].firstChild.data, 657 | #i.getElementsByTagName('sbl:imageCenterFrequency')[0].getAttribute('unit') 658 | )) 659 | 660 | bb = pd.DataFrame(bbList) 661 | 662 | return bb,specs 663 | 664 | --------------------------------------------------------------------------------