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

MAXGAP = 50
def setMaxGap(self, mg):
15    def setMaxGap(self, mg):
16        self.MAXGAP = mg
def getDate(self):
23    def getDate(self):
24        ur = self.ucxml['ufocapture_record']
25        return int(ur['@y']) * 10000 + int(ur['@mo']) * 100 + int(ur['@d'])
def getDateYMD(self):
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
def getDateStr(self):
33    def getDateStr(self):
34        ur = self.ucxml['ufocapture_record']
35        return ur['@y'] + "-" + ur['@mo'] + "-" + ur['@d']
def getTime(self):
37    def getTime(self):
38        ur = self.ucxml['ufocapture_record']
39        return int(ur['@h']) * 3600 + int(ur['@m']) * 60 + float(ur['@s'])
def getTimeStr(self):
41    def getTimeStr(self):
42        ur = self.ucxml['ufocapture_record']
43        return ur['@h'] + ":" + ur['@m'] + ":" + ur['@s']
def getTimeHMS(self):
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
def getCameraDetails(self):
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
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 getHits(self):
66    def getHits(self):
67        uc = self.ucxml['ufocapture_record']['ufocapture_paths']
68        return int(uc['@hit'])
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
def getPathElement(self, fno):
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']