meteortools.fileformats.UFOCapXML
1# Python class to parse a UFOCapture XML files 2# 3# disable some linter warnings 4# Copyright (C) 2018-2023 Mark McIntyre 5 6import xmltodict 7import numpy 8 9 10class UCXml: 11 """ Load and manage a UFOCapture XML file containing potential detections """ 12 MAXGAP = 50 13 14 def setMaxGap(self, mg): 15 self.MAXGAP = mg 16 17 def __init__(self, fname): 18 """ Construct a UCXML object from fname """ 19 with open(fname) as fd: 20 self.ucxml = xmltodict.parse(fd.read()) 21 22 def getDate(self): 23 ur = self.ucxml['ufocapture_record'] 24 return int(ur['@y']) * 10000 + int(ur['@mo']) * 100 + int(ur['@d']) 25 26 def getDateYMD(self): 27 yr = int(self.ucxml['ufocapture_record']['@y']) 28 mo = int(self.ucxml['ufocapture_record']['@mo']) 29 dy = int(self.ucxml['ufocapture_record']['@d']) 30 return yr, mo, dy 31 32 def getDateStr(self): 33 ur = self.ucxml['ufocapture_record'] 34 return ur['@y'] + "-" + ur['@mo'] + "-" + ur['@d'] 35 36 def getTime(self): 37 ur = self.ucxml['ufocapture_record'] 38 return int(ur['@h']) * 3600 + int(ur['@m']) * 60 + float(ur['@s']) 39 40 def getTimeStr(self): 41 ur = self.ucxml['ufocapture_record'] 42 return ur['@h'] + ":" + ur['@m'] + ":" + ur['@s'] 43 44 def getTimeHMS(self): 45 h = int(self.ucxml['ufocapture_record']['@h']) 46 m = int(self.ucxml['ufocapture_record']['@m']) 47 s = float(self.ucxml['ufocapture_record']['@s']) 48 return h, m, s 49 50 def getCameraDetails(self): 51 fps = float(self.ucxml['ufocapture_record']['@fps']) 52 cx = float(self.ucxml['ufocapture_record']['@cx']) 53 cy = float(self.ucxml['ufocapture_record']['@cy']) 54 return fps, cx, cy 55 56 def getStationDetails(self): 57 sta = self.ucxml['ufocapture_record']['@lid'] + "_" + self.ucxml['ufocapture_record']['@sid'] 58 lid = self.ucxml['ufocapture_record']['@lid'] 59 sid = self.ucxml['ufocapture_record']['@sid'] 60 lat = float(self.ucxml['ufocapture_record']['@lat']) 61 lng = float(self.ucxml['ufocapture_record']['@lng']) 62 alt = float(self.ucxml['ufocapture_record']['@alt']) 63 return sta, lid, sid, lat, lng, alt 64 65 def getHits(self): 66 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 67 return int(uc['@hit']) 68 69 def getNumObjs(self): 70 try: 71 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 72 except: 73 return 0, None 74 nhits = int(uc['@hit']) 75 objlist = numpy.zeros(nhits) 76 nobjs = 0 77 for i in range(nhits): 78 if nhits == 1: 79 p = uc['uc_path'] 80 else: 81 p = uc['uc_path'][i] 82 ono = int(p['@ono']) 83 if ono not in objlist: 84 objlist[nobjs] = ono 85 nobjs = nobjs + 1 86 objlist = numpy.resize(objlist, nobjs) 87 return nobjs, objlist 88 89 def getPath(self): 90 try: 91 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 92 except: 93 # print('xml file not valid - no ufocapture_paths') 94 pathx = numpy.zeros(1) 95 pathy = numpy.zeros(1) 96 bri = numpy.zeros(1) 97 return pathx, pathy, bri, 0 98 nhits = int(uc['@hit']) 99 pathx = numpy.zeros(nhits) 100 pathy = numpy.zeros(nhits) 101 bri = numpy.zeros(nhits) 102 if nhits < 2: 103 return pathx, pathy, bri, 0 104 lastono = 0 105 for i in range(nhits): 106 p = uc['uc_path'][i] 107 ono = int(p['@ono']) 108 # its possible for one path to include two events 109 # at different times. This is a UFO feature... 110 if lastono > 0 and lastono != ono: 111 pathx = numpy.resize(pathx, i) 112 pathy = numpy.resize(pathy, i) 113 bri = numpy.resize(bri, i) 114 return pathx, pathy, bri, i 115 lastono = ono 116 pathx[i] = p['@x'] 117 pathy[i] = p['@y'] 118 bri[i] = p['@bmax'] 119 return pathx, pathy, bri, 0 120 121 def getPathv2(self, objno): 122 try: 123 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 124 except: 125 pathx = numpy.zeros(1) 126 pathy = numpy.zeros(1) 127 bri = numpy.zeros(1) 128 pxls = numpy.zeros(1) 129 fnos = numpy.zeros(1) 130 return pathx, pathy, bri, pxls, fnos 131 pfno = 0 # previous frame number, to check for unrealistic gaps in trails 132 fno = 0 # current frame number, to check for unrealistic gaps in trails 133 nhits = int(uc['@hit']) 134 pathx = numpy.zeros(nhits) 135 pathy = numpy.zeros(nhits) 136 bri = numpy.zeros(nhits) 137 pxls = numpy.zeros(nhits) 138 fnos = numpy.zeros(nhits) 139 j = 0 140 for i in range(nhits): 141 if nhits == 1: 142 p = uc['uc_path'] 143 else: 144 p = uc['uc_path'][i] 145 ono = int(p['@ono']) 146 # npx = int(p['@pixel']) 147 fno = int(p['@fno']) 148 if pfno == 0: 149 pfno = fno 150 #fdiff = fno - pfno 151 if ono == objno: # and fdiff < self.MAXGAP: # and npx > 3: 152 # its possible for one path to include two events 153 # at different times. This is a UFO feature... 154 pathx[j] = p['@x'] 155 pathy[j] = p['@y'] 156 bri[j] = p['@bmax'] 157 pxls[j] = p['@pixel'] 158 fnos[j] = p['@fno'] 159 j = j + 1 160 if j > 0: 161 pathx = numpy.resize(pathx, j) 162 pathy = numpy.resize(pathy, j) 163 bri = numpy.resize(bri, j) 164 pxls = numpy.resize(pxls, j) 165 fnos = numpy.resize(fnos, j) 166 else: 167 pathx = numpy.zeros(1) 168 pathy = numpy.zeros(1) 169 bri = numpy.zeros(1) 170 pxls = numpy.zeros(1) 171 fnos = numpy.zeros(1) 172 return pathx, pathy, bri, pxls, fnos 173 174 def getPathElement(self, fno): 175 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 176 pth = uc['uc_path'][fno] 177 return pth['@fno'], pth['@ono'], pth['@pixel'], pth['@bmax'], pth['@x'], pth['@y']
class
UCXml:
11class UCXml: 12 """ Load and manage a UFOCapture XML file containing potential detections """ 13 MAXGAP = 50 14 15 def setMaxGap(self, mg): 16 self.MAXGAP = mg 17 18 def __init__(self, fname): 19 """ Construct a UCXML object from fname """ 20 with open(fname) as fd: 21 self.ucxml = xmltodict.parse(fd.read()) 22 23 def getDate(self): 24 ur = self.ucxml['ufocapture_record'] 25 return int(ur['@y']) * 10000 + int(ur['@mo']) * 100 + int(ur['@d']) 26 27 def getDateYMD(self): 28 yr = int(self.ucxml['ufocapture_record']['@y']) 29 mo = int(self.ucxml['ufocapture_record']['@mo']) 30 dy = int(self.ucxml['ufocapture_record']['@d']) 31 return yr, mo, dy 32 33 def getDateStr(self): 34 ur = self.ucxml['ufocapture_record'] 35 return ur['@y'] + "-" + ur['@mo'] + "-" + ur['@d'] 36 37 def getTime(self): 38 ur = self.ucxml['ufocapture_record'] 39 return int(ur['@h']) * 3600 + int(ur['@m']) * 60 + float(ur['@s']) 40 41 def getTimeStr(self): 42 ur = self.ucxml['ufocapture_record'] 43 return ur['@h'] + ":" + ur['@m'] + ":" + ur['@s'] 44 45 def getTimeHMS(self): 46 h = int(self.ucxml['ufocapture_record']['@h']) 47 m = int(self.ucxml['ufocapture_record']['@m']) 48 s = float(self.ucxml['ufocapture_record']['@s']) 49 return h, m, s 50 51 def getCameraDetails(self): 52 fps = float(self.ucxml['ufocapture_record']['@fps']) 53 cx = float(self.ucxml['ufocapture_record']['@cx']) 54 cy = float(self.ucxml['ufocapture_record']['@cy']) 55 return fps, cx, cy 56 57 def getStationDetails(self): 58 sta = self.ucxml['ufocapture_record']['@lid'] + "_" + self.ucxml['ufocapture_record']['@sid'] 59 lid = self.ucxml['ufocapture_record']['@lid'] 60 sid = self.ucxml['ufocapture_record']['@sid'] 61 lat = float(self.ucxml['ufocapture_record']['@lat']) 62 lng = float(self.ucxml['ufocapture_record']['@lng']) 63 alt = float(self.ucxml['ufocapture_record']['@alt']) 64 return sta, lid, sid, lat, lng, alt 65 66 def getHits(self): 67 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 68 return int(uc['@hit']) 69 70 def getNumObjs(self): 71 try: 72 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 73 except: 74 return 0, None 75 nhits = int(uc['@hit']) 76 objlist = numpy.zeros(nhits) 77 nobjs = 0 78 for i in range(nhits): 79 if nhits == 1: 80 p = uc['uc_path'] 81 else: 82 p = uc['uc_path'][i] 83 ono = int(p['@ono']) 84 if ono not in objlist: 85 objlist[nobjs] = ono 86 nobjs = nobjs + 1 87 objlist = numpy.resize(objlist, nobjs) 88 return nobjs, objlist 89 90 def getPath(self): 91 try: 92 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 93 except: 94 # print('xml file not valid - no ufocapture_paths') 95 pathx = numpy.zeros(1) 96 pathy = numpy.zeros(1) 97 bri = numpy.zeros(1) 98 return pathx, pathy, bri, 0 99 nhits = int(uc['@hit']) 100 pathx = numpy.zeros(nhits) 101 pathy = numpy.zeros(nhits) 102 bri = numpy.zeros(nhits) 103 if nhits < 2: 104 return pathx, pathy, bri, 0 105 lastono = 0 106 for i in range(nhits): 107 p = uc['uc_path'][i] 108 ono = int(p['@ono']) 109 # its possible for one path to include two events 110 # at different times. This is a UFO feature... 111 if lastono > 0 and lastono != ono: 112 pathx = numpy.resize(pathx, i) 113 pathy = numpy.resize(pathy, i) 114 bri = numpy.resize(bri, i) 115 return pathx, pathy, bri, i 116 lastono = ono 117 pathx[i] = p['@x'] 118 pathy[i] = p['@y'] 119 bri[i] = p['@bmax'] 120 return pathx, pathy, bri, 0 121 122 def getPathv2(self, objno): 123 try: 124 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 125 except: 126 pathx = numpy.zeros(1) 127 pathy = numpy.zeros(1) 128 bri = numpy.zeros(1) 129 pxls = numpy.zeros(1) 130 fnos = numpy.zeros(1) 131 return pathx, pathy, bri, pxls, fnos 132 pfno = 0 # previous frame number, to check for unrealistic gaps in trails 133 fno = 0 # current frame number, to check for unrealistic gaps in trails 134 nhits = int(uc['@hit']) 135 pathx = numpy.zeros(nhits) 136 pathy = numpy.zeros(nhits) 137 bri = numpy.zeros(nhits) 138 pxls = numpy.zeros(nhits) 139 fnos = numpy.zeros(nhits) 140 j = 0 141 for i in range(nhits): 142 if nhits == 1: 143 p = uc['uc_path'] 144 else: 145 p = uc['uc_path'][i] 146 ono = int(p['@ono']) 147 # npx = int(p['@pixel']) 148 fno = int(p['@fno']) 149 if pfno == 0: 150 pfno = fno 151 #fdiff = fno - pfno 152 if ono == objno: # and fdiff < self.MAXGAP: # and npx > 3: 153 # its possible for one path to include two events 154 # at different times. This is a UFO feature... 155 pathx[j] = p['@x'] 156 pathy[j] = p['@y'] 157 bri[j] = p['@bmax'] 158 pxls[j] = p['@pixel'] 159 fnos[j] = p['@fno'] 160 j = j + 1 161 if j > 0: 162 pathx = numpy.resize(pathx, j) 163 pathy = numpy.resize(pathy, j) 164 bri = numpy.resize(bri, j) 165 pxls = numpy.resize(pxls, j) 166 fnos = numpy.resize(fnos, j) 167 else: 168 pathx = numpy.zeros(1) 169 pathy = numpy.zeros(1) 170 bri = numpy.zeros(1) 171 pxls = numpy.zeros(1) 172 fnos = numpy.zeros(1) 173 return pathx, pathy, bri, pxls, fnos 174 175 def getPathElement(self, fno): 176 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 177 pth = uc['uc_path'][fno] 178 return pth['@fno'], pth['@ono'], pth['@pixel'], pth['@bmax'], pth['@x'], pth['@y']
Load and manage a UFOCapture XML file containing potential detections
UCXml(fname)
18 def __init__(self, fname): 19 """ Construct a UCXML object from fname """ 20 with open(fname) as fd: 21 self.ucxml = xmltodict.parse(fd.read())
Construct a UCXML object from fname
def
getStationDetails(self):
57 def getStationDetails(self): 58 sta = self.ucxml['ufocapture_record']['@lid'] + "_" + self.ucxml['ufocapture_record']['@sid'] 59 lid = self.ucxml['ufocapture_record']['@lid'] 60 sid = self.ucxml['ufocapture_record']['@sid'] 61 lat = float(self.ucxml['ufocapture_record']['@lat']) 62 lng = float(self.ucxml['ufocapture_record']['@lng']) 63 alt = float(self.ucxml['ufocapture_record']['@alt']) 64 return sta, lid, sid, lat, lng, alt
def
getNumObjs(self):
70 def getNumObjs(self): 71 try: 72 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 73 except: 74 return 0, None 75 nhits = int(uc['@hit']) 76 objlist = numpy.zeros(nhits) 77 nobjs = 0 78 for i in range(nhits): 79 if nhits == 1: 80 p = uc['uc_path'] 81 else: 82 p = uc['uc_path'][i] 83 ono = int(p['@ono']) 84 if ono not in objlist: 85 objlist[nobjs] = ono 86 nobjs = nobjs + 1 87 objlist = numpy.resize(objlist, nobjs) 88 return nobjs, objlist
def
getPath(self):
90 def getPath(self): 91 try: 92 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 93 except: 94 # print('xml file not valid - no ufocapture_paths') 95 pathx = numpy.zeros(1) 96 pathy = numpy.zeros(1) 97 bri = numpy.zeros(1) 98 return pathx, pathy, bri, 0 99 nhits = int(uc['@hit']) 100 pathx = numpy.zeros(nhits) 101 pathy = numpy.zeros(nhits) 102 bri = numpy.zeros(nhits) 103 if nhits < 2: 104 return pathx, pathy, bri, 0 105 lastono = 0 106 for i in range(nhits): 107 p = uc['uc_path'][i] 108 ono = int(p['@ono']) 109 # its possible for one path to include two events 110 # at different times. This is a UFO feature... 111 if lastono > 0 and lastono != ono: 112 pathx = numpy.resize(pathx, i) 113 pathy = numpy.resize(pathy, i) 114 bri = numpy.resize(bri, i) 115 return pathx, pathy, bri, i 116 lastono = ono 117 pathx[i] = p['@x'] 118 pathy[i] = p['@y'] 119 bri[i] = p['@bmax'] 120 return pathx, pathy, bri, 0
def
getPathv2(self, objno):
122 def getPathv2(self, objno): 123 try: 124 uc = self.ucxml['ufocapture_record']['ufocapture_paths'] 125 except: 126 pathx = numpy.zeros(1) 127 pathy = numpy.zeros(1) 128 bri = numpy.zeros(1) 129 pxls = numpy.zeros(1) 130 fnos = numpy.zeros(1) 131 return pathx, pathy, bri, pxls, fnos 132 pfno = 0 # previous frame number, to check for unrealistic gaps in trails 133 fno = 0 # current frame number, to check for unrealistic gaps in trails 134 nhits = int(uc['@hit']) 135 pathx = numpy.zeros(nhits) 136 pathy = numpy.zeros(nhits) 137 bri = numpy.zeros(nhits) 138 pxls = numpy.zeros(nhits) 139 fnos = numpy.zeros(nhits) 140 j = 0 141 for i in range(nhits): 142 if nhits == 1: 143 p = uc['uc_path'] 144 else: 145 p = uc['uc_path'][i] 146 ono = int(p['@ono']) 147 # npx = int(p['@pixel']) 148 fno = int(p['@fno']) 149 if pfno == 0: 150 pfno = fno 151 #fdiff = fno - pfno 152 if ono == objno: # and fdiff < self.MAXGAP: # and npx > 3: 153 # its possible for one path to include two events 154 # at different times. This is a UFO feature... 155 pathx[j] = p['@x'] 156 pathy[j] = p['@y'] 157 bri[j] = p['@bmax'] 158 pxls[j] = p['@pixel'] 159 fnos[j] = p['@fno'] 160 j = j + 1 161 if j > 0: 162 pathx = numpy.resize(pathx, j) 163 pathy = numpy.resize(pathy, j) 164 bri = numpy.resize(bri, j) 165 pxls = numpy.resize(pxls, j) 166 fnos = numpy.resize(fnos, j) 167 else: 168 pathx = numpy.zeros(1) 169 pathy = numpy.zeros(1) 170 bri = numpy.zeros(1) 171 pxls = numpy.zeros(1) 172 fnos = numpy.zeros(1) 173 return pathx, pathy, bri, pxls, fnos