meteortools.fileformats.UFOAnalyzerXML

  1#  A class to handle UFO Analyser xml files
  2# Copyright (C) 2018-2023 Mark McIntyre
  3
  4import xmltodict
  5import datetime
  6import math
  7import numpy
  8try:
  9    from ..utils import datetime2JD, altAz2RADec
 10except Exception:
 11    from meteortools.utils import datetime2JD, altAz2RADec
 12
 13
 14class UAXml:
 15    """" Load and manage a UFO-Analyser XML file containing meteor detections """
 16    def __init__(self, fname):
 17        """Construct a UAxml object from fname"""
 18        with open(fname) as fd:
 19            self.uaxml = xmltodict.parse(fd.read())
 20
 21    def getDateTime(self):
 22        y, m, d = UAXml.getDateYMD(self)
 23        h, mi, s = UAXml.getTimeHMS(self)
 24        ss = int(math.floor(s))
 25        ms = int((s - ss) * 1000000)
 26
 27        dtim = datetime.datetime(y, m, d, h, mi, ss, ms)
 28        return dtim
 29
 30    def getDate(self):
 31        ur = self.uaxml['ufoanalyzer_record']
 32        return int(ur['@y']) * 10000 + int(ur['@mo']) * 100 + int(ur['@d'])
 33
 34    def getDateYMD(self):
 35        yr = int(self.uaxml['ufoanalyzer_record']['@y'])
 36        mo = int(self.uaxml['ufoanalyzer_record']['@mo'])
 37        dy = int(self.uaxml['ufoanalyzer_record']['@d'])
 38        return yr, mo, dy
 39
 40    def getDateStr(self):
 41        ur = self.uaxml['ufoanalyzer_record']
 42        return f'{ur["@y"]}-{int(ur["@mo"]):02d}-{int(ur["@d"]):02d}'
 43
 44    def getTime(self):
 45        ur = self.uaxml['ufoanalyzer_record']
 46        return int(ur['@h']) * 3600 + int(ur['@m']) * 60 + float(ur['@s'])
 47
 48    def getTimeStr(self):
 49        ur = self.uaxml['ufoanalyzer_record']
 50        return ur['@h'] + ":" + ur['@m'] + ":" + ur['@s']
 51
 52    def getTimeHMS(self):
 53        h = int(self.uaxml['ufoanalyzer_record']['@h'])
 54        m = int(self.uaxml['ufoanalyzer_record']['@m'])
 55        s = float(self.uaxml['ufoanalyzer_record']['@s'])
 56        return h, m, s
 57
 58    def getCameraDetails(self):
 59        fps = float(self.uaxml['ufoanalyzer_record']['@fps'])
 60        cx = float(self.uaxml['ufoanalyzer_record']['@cx'])
 61        cy = float(self.uaxml['ufoanalyzer_record']['@cy'])
 62        isintl = int(self.uaxml['ufoanalyzer_record']['@interlaced'])
 63        return fps, cx, cy, isintl
 64
 65    def getStationDetails(self):
 66        sta = self.uaxml['ufoanalyzer_record']['@lid'] + "_" + self.uaxml['ufoanalyzer_record']['@sid']
 67        lid = self.uaxml['ufoanalyzer_record']['@lid']
 68        sid = self.uaxml['ufoanalyzer_record']['@sid']
 69        lat = float(self.uaxml['ufoanalyzer_record']['@lat'])
 70        lng = float(self.uaxml['ufoanalyzer_record']['@lng'])
 71        alt = float(self.uaxml['ufoanalyzer_record']['@alt'])
 72        return sta, lid, sid, lat, lng, alt
 73
 74    def getProfDetails(self):
 75        az = float(self.uaxml['ufoanalyzer_record']['@az'])
 76        ev = float(self.uaxml['ufoanalyzer_record']['@ev'])
 77        rot = float(self.uaxml['ufoanalyzer_record']['@rot'])
 78        fovh = float(self.uaxml['ufoanalyzer_record']['@vx'])
 79        yx = float(self.uaxml['ufoanalyzer_record']['@yx'])
 80        dx = float(self.uaxml['ufoanalyzer_record']['@dx'])
 81        dy = float(self.uaxml['ufoanalyzer_record']['@dy'])
 82        lnk = float(self.uaxml['ufoanalyzer_record']['@dl'])
 83        return az, ev, rot, fovh, yx, dx, dy, lnk
 84
 85    def getObjectCount(self):
 86        return int(self.uaxml['ufoanalyzer_record']['@o'])
 87
 88    def getObjectBasics(self, objno):
 89        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
 90        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
 91        if oc == 1:
 92            uo = uos['ua2_object']
 93        else:
 94            uo = uos['ua2_object'][objno]
 95        sec = float(uo['@sec'])
 96        av = float(uo['@av'])
 97        pix = int(uo['@pix'])
 98        bmax = float(uo['@bmax'])
 99        mag = float(uo['@mag'])
100        fcount = int(uo['@sN'])
101        return sec, av, pix, bmax, mag, fcount
102
103    def getObjectStart(self, objno):
104        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
105        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
106        if oc == 1:
107            uo = uos['ua2_object']
108        else:
109            uo = uos['ua2_object'][objno]
110        ra1 = uo['@ra1']
111        dc1 = uo['@dc1']
112        h1 = uo['@h1']
113        dist1 = uo['@dist1']
114        lng1 = uo['@lng1']
115        lat1 = uo['@lat1']
116        az1 = uo['@az1']
117        ev1 = uo['@ev1']
118        fs = uo['@fs']
119        return ra1, dc1, h1, dist1, lng1, lat1, az1, ev1, fs
120
121    def getObjectEnd(self, objno):
122        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
123        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
124        if oc == 1:
125            uo = uos['ua2_object']
126        else:
127            uo = uos['ua2_object'][objno]
128        ra2 = uo['@ra2']
129        dc2 = uo['@dc2']
130        h2 = uo['@h2']
131        dist2 = uo['@dist2']
132        lng2 = uo['@lng2']
133        lat2 = uo['@lat2']
134        az2 = uo['@az2']
135        ev2 = uo['@ev2']
136        fe = uo['@fe']
137        return ra2, dc2, h2, dist2, lng2, lat2, az2, ev2, fe
138
139    def getObjectFrameDetails(self, objno, fno):
140        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
141        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
142        if oc == 1:
143            uo = uos['ua2_object']
144        else:
145            uo = uos['ua2_object'][objno]
146        uop = uo['ua2_objpath']['ua2_fdata2'][fno]
147        fno = int(uop['@fno'])
148        b = int(uop['@b'])
149        lsum = float(uop['@Lsum'])
150        mag = float(uop['@mag'])
151        az = float(uop['@az'])
152        ev = float(uop['@ev'])
153        ra = float(uop['@ra'])
154        dec = float(uop['@dec'])
155        return fno, ra, dec, mag, az, ev, lsum, b
156
157    def getPathVector(self, objno):
158        fps, _, _, isintl = UAXml.getCameraDetails(self)
159        dtim = UAXml.getDateTime(self)
160
161        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
162        oc = UAXml.getObjectCount(self)
163        if oc == 1:
164            uo = uos['ua2_object']
165        else:
166            uo = uos['ua2_object'][objno]
167        fcount = int(uo['@sN'])
168        fs = int(uo['@fs'])
169        fno = numpy.zeros(fcount)
170        ra = numpy.zeros(fcount)
171        dec = numpy.zeros(fcount)
172        alt = numpy.zeros(fcount)
173        az = numpy.zeros(fcount)
174        tt = numpy.zeros(fcount)
175        mag = numpy.zeros(fcount)
176        b = numpy.zeros(fcount)
177        lsum = numpy.zeros(fcount)
178        for fc in range(fcount):
179            uop = uo['ua2_objpath']['ua2_fdata2'][fc]
180            fno[fc] = int(uop['@fno'])
181            ra[fc] = float(uop['@ra'])
182            dec[fc] = float(uop['@dec'])
183            az[fc] = float(uop['@az'])
184            alt[fc] = float(uop['@ev'])
185            mag[fc] = float(uop['@mag'])
186            b[fc] = float(uop['@b'])
187            lsum[fc] = float(uop['@Lsum'])
188
189            # UFO timestamps the first half-frame in which a detection happens and
190            # the framenumber of this is stored in "fs"
191            us = int((fno[fc] - fs) / fps * 1000000)
192            tt[fc] = round((dtim + datetime.timedelta(microseconds=us)).timestamp(), 2)
193        return fno, tt, ra, dec, mag, fcount, alt, az, b, lsum
194
195
196    def makePlateParEntry(self, statid):
197        """ Make a fake platepar file from the data, so it can be processed with RMS/WMPL """
198        imgdt = self.getDateTime()
199        _, cx, cy, _ = self.getCameraDetails()
200        az, ev, _, fovh, yx, _, _, _ = self.getProfDetails()
201        _, lid, sid, lat, lng, alt = self.getStationDetails()
202
203        ff_name = 'FF_' + statid +'_'
204        ff_name = ff_name + imgdt.strftime('%Y%m%d_%H%M%S_') 
205        ms = '{:03d}'.format(int(imgdt.microsecond / 1000))
206        ff_name = ff_name + ms + '_0000000.fits'
207
208        fovv = fovh*(cx*yx/cy)
209
210        ref_jd = datetime2JD(imgdt)
211        ra_d, dec_d = altAz2RADec(numpy.radians(az), numpy.radians(ev), ref_jd, 
212            numpy.radians(lat), numpy.radians(lng))
213
214        pp = '"' + ff_name + '": {\n'
215        pp = pp + '    "lat": {:f},\n'.format(lat)
216        pp = pp + '    "lon": {:f},\n'.format(lng)
217        pp = pp + '    "elev": {:f},\n'.format(alt)
218        pp = pp + '    "X_res": {:d},\n'.format(int(cx))
219        pp = pp + '    "Y_res": {:d},\n'.format(int(cy))
220        pp = pp + '    "JD": {:.8f},\n'.format(ref_jd)
221        pp = pp + '    "RA_d": {:.8f},\n'.format(numpy.degrees(ra_d))
222        pp = pp + '    "dec_d": {:.8f},\n'.format(numpy.degrees(dec_d))
223        pp = pp + '    "fov_h": {:f},\n'.format(fovh)
224        pp = pp + '    "fov_v": {:f},\n'.format(fovv)
225        pp = pp + '    "station_code": "{:s}",\n'.format(statid)
226        pp = pp + '    "auto_recalibrated": true,\n'
227        pp = pp + '    "az_centre": 0,\n'
228        pp = pp + '    "alt_centre": 0,\n'
229        pp = pp + '    "rotation_from_horiz": 0,\n'
230        pp = pp + '    "pos_angle_ref": 0,\n'
231        pp = pp + '    "Ho": 0,\n'
232        pp = pp + '    "UT_corr": 0,\n'
233        pp = pp + '    "F_scale": 0,\n'
234        pp = pp + '    "version": 2\n'
235        pp = pp + '}'
236
237        return pp
class UAXml:
 15class UAXml:
 16    """" Load and manage a UFO-Analyser XML file containing meteor detections """
 17    def __init__(self, fname):
 18        """Construct a UAxml object from fname"""
 19        with open(fname) as fd:
 20            self.uaxml = xmltodict.parse(fd.read())
 21
 22    def getDateTime(self):
 23        y, m, d = UAXml.getDateYMD(self)
 24        h, mi, s = UAXml.getTimeHMS(self)
 25        ss = int(math.floor(s))
 26        ms = int((s - ss) * 1000000)
 27
 28        dtim = datetime.datetime(y, m, d, h, mi, ss, ms)
 29        return dtim
 30
 31    def getDate(self):
 32        ur = self.uaxml['ufoanalyzer_record']
 33        return int(ur['@y']) * 10000 + int(ur['@mo']) * 100 + int(ur['@d'])
 34
 35    def getDateYMD(self):
 36        yr = int(self.uaxml['ufoanalyzer_record']['@y'])
 37        mo = int(self.uaxml['ufoanalyzer_record']['@mo'])
 38        dy = int(self.uaxml['ufoanalyzer_record']['@d'])
 39        return yr, mo, dy
 40
 41    def getDateStr(self):
 42        ur = self.uaxml['ufoanalyzer_record']
 43        return f'{ur["@y"]}-{int(ur["@mo"]):02d}-{int(ur["@d"]):02d}'
 44
 45    def getTime(self):
 46        ur = self.uaxml['ufoanalyzer_record']
 47        return int(ur['@h']) * 3600 + int(ur['@m']) * 60 + float(ur['@s'])
 48
 49    def getTimeStr(self):
 50        ur = self.uaxml['ufoanalyzer_record']
 51        return ur['@h'] + ":" + ur['@m'] + ":" + ur['@s']
 52
 53    def getTimeHMS(self):
 54        h = int(self.uaxml['ufoanalyzer_record']['@h'])
 55        m = int(self.uaxml['ufoanalyzer_record']['@m'])
 56        s = float(self.uaxml['ufoanalyzer_record']['@s'])
 57        return h, m, s
 58
 59    def getCameraDetails(self):
 60        fps = float(self.uaxml['ufoanalyzer_record']['@fps'])
 61        cx = float(self.uaxml['ufoanalyzer_record']['@cx'])
 62        cy = float(self.uaxml['ufoanalyzer_record']['@cy'])
 63        isintl = int(self.uaxml['ufoanalyzer_record']['@interlaced'])
 64        return fps, cx, cy, isintl
 65
 66    def getStationDetails(self):
 67        sta = self.uaxml['ufoanalyzer_record']['@lid'] + "_" + self.uaxml['ufoanalyzer_record']['@sid']
 68        lid = self.uaxml['ufoanalyzer_record']['@lid']
 69        sid = self.uaxml['ufoanalyzer_record']['@sid']
 70        lat = float(self.uaxml['ufoanalyzer_record']['@lat'])
 71        lng = float(self.uaxml['ufoanalyzer_record']['@lng'])
 72        alt = float(self.uaxml['ufoanalyzer_record']['@alt'])
 73        return sta, lid, sid, lat, lng, alt
 74
 75    def getProfDetails(self):
 76        az = float(self.uaxml['ufoanalyzer_record']['@az'])
 77        ev = float(self.uaxml['ufoanalyzer_record']['@ev'])
 78        rot = float(self.uaxml['ufoanalyzer_record']['@rot'])
 79        fovh = float(self.uaxml['ufoanalyzer_record']['@vx'])
 80        yx = float(self.uaxml['ufoanalyzer_record']['@yx'])
 81        dx = float(self.uaxml['ufoanalyzer_record']['@dx'])
 82        dy = float(self.uaxml['ufoanalyzer_record']['@dy'])
 83        lnk = float(self.uaxml['ufoanalyzer_record']['@dl'])
 84        return az, ev, rot, fovh, yx, dx, dy, lnk
 85
 86    def getObjectCount(self):
 87        return int(self.uaxml['ufoanalyzer_record']['@o'])
 88
 89    def getObjectBasics(self, objno):
 90        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
 91        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
 92        if oc == 1:
 93            uo = uos['ua2_object']
 94        else:
 95            uo = uos['ua2_object'][objno]
 96        sec = float(uo['@sec'])
 97        av = float(uo['@av'])
 98        pix = int(uo['@pix'])
 99        bmax = float(uo['@bmax'])
100        mag = float(uo['@mag'])
101        fcount = int(uo['@sN'])
102        return sec, av, pix, bmax, mag, fcount
103
104    def getObjectStart(self, objno):
105        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
106        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
107        if oc == 1:
108            uo = uos['ua2_object']
109        else:
110            uo = uos['ua2_object'][objno]
111        ra1 = uo['@ra1']
112        dc1 = uo['@dc1']
113        h1 = uo['@h1']
114        dist1 = uo['@dist1']
115        lng1 = uo['@lng1']
116        lat1 = uo['@lat1']
117        az1 = uo['@az1']
118        ev1 = uo['@ev1']
119        fs = uo['@fs']
120        return ra1, dc1, h1, dist1, lng1, lat1, az1, ev1, fs
121
122    def getObjectEnd(self, objno):
123        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
124        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
125        if oc == 1:
126            uo = uos['ua2_object']
127        else:
128            uo = uos['ua2_object'][objno]
129        ra2 = uo['@ra2']
130        dc2 = uo['@dc2']
131        h2 = uo['@h2']
132        dist2 = uo['@dist2']
133        lng2 = uo['@lng2']
134        lat2 = uo['@lat2']
135        az2 = uo['@az2']
136        ev2 = uo['@ev2']
137        fe = uo['@fe']
138        return ra2, dc2, h2, dist2, lng2, lat2, az2, ev2, fe
139
140    def getObjectFrameDetails(self, objno, fno):
141        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
142        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
143        if oc == 1:
144            uo = uos['ua2_object']
145        else:
146            uo = uos['ua2_object'][objno]
147        uop = uo['ua2_objpath']['ua2_fdata2'][fno]
148        fno = int(uop['@fno'])
149        b = int(uop['@b'])
150        lsum = float(uop['@Lsum'])
151        mag = float(uop['@mag'])
152        az = float(uop['@az'])
153        ev = float(uop['@ev'])
154        ra = float(uop['@ra'])
155        dec = float(uop['@dec'])
156        return fno, ra, dec, mag, az, ev, lsum, b
157
158    def getPathVector(self, objno):
159        fps, _, _, isintl = UAXml.getCameraDetails(self)
160        dtim = UAXml.getDateTime(self)
161
162        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
163        oc = UAXml.getObjectCount(self)
164        if oc == 1:
165            uo = uos['ua2_object']
166        else:
167            uo = uos['ua2_object'][objno]
168        fcount = int(uo['@sN'])
169        fs = int(uo['@fs'])
170        fno = numpy.zeros(fcount)
171        ra = numpy.zeros(fcount)
172        dec = numpy.zeros(fcount)
173        alt = numpy.zeros(fcount)
174        az = numpy.zeros(fcount)
175        tt = numpy.zeros(fcount)
176        mag = numpy.zeros(fcount)
177        b = numpy.zeros(fcount)
178        lsum = numpy.zeros(fcount)
179        for fc in range(fcount):
180            uop = uo['ua2_objpath']['ua2_fdata2'][fc]
181            fno[fc] = int(uop['@fno'])
182            ra[fc] = float(uop['@ra'])
183            dec[fc] = float(uop['@dec'])
184            az[fc] = float(uop['@az'])
185            alt[fc] = float(uop['@ev'])
186            mag[fc] = float(uop['@mag'])
187            b[fc] = float(uop['@b'])
188            lsum[fc] = float(uop['@Lsum'])
189
190            # UFO timestamps the first half-frame in which a detection happens and
191            # the framenumber of this is stored in "fs"
192            us = int((fno[fc] - fs) / fps * 1000000)
193            tt[fc] = round((dtim + datetime.timedelta(microseconds=us)).timestamp(), 2)
194        return fno, tt, ra, dec, mag, fcount, alt, az, b, lsum
195
196
197    def makePlateParEntry(self, statid):
198        """ Make a fake platepar file from the data, so it can be processed with RMS/WMPL """
199        imgdt = self.getDateTime()
200        _, cx, cy, _ = self.getCameraDetails()
201        az, ev, _, fovh, yx, _, _, _ = self.getProfDetails()
202        _, lid, sid, lat, lng, alt = self.getStationDetails()
203
204        ff_name = 'FF_' + statid +'_'
205        ff_name = ff_name + imgdt.strftime('%Y%m%d_%H%M%S_') 
206        ms = '{:03d}'.format(int(imgdt.microsecond / 1000))
207        ff_name = ff_name + ms + '_0000000.fits'
208
209        fovv = fovh*(cx*yx/cy)
210
211        ref_jd = datetime2JD(imgdt)
212        ra_d, dec_d = altAz2RADec(numpy.radians(az), numpy.radians(ev), ref_jd, 
213            numpy.radians(lat), numpy.radians(lng))
214
215        pp = '"' + ff_name + '": {\n'
216        pp = pp + '    "lat": {:f},\n'.format(lat)
217        pp = pp + '    "lon": {:f},\n'.format(lng)
218        pp = pp + '    "elev": {:f},\n'.format(alt)
219        pp = pp + '    "X_res": {:d},\n'.format(int(cx))
220        pp = pp + '    "Y_res": {:d},\n'.format(int(cy))
221        pp = pp + '    "JD": {:.8f},\n'.format(ref_jd)
222        pp = pp + '    "RA_d": {:.8f},\n'.format(numpy.degrees(ra_d))
223        pp = pp + '    "dec_d": {:.8f},\n'.format(numpy.degrees(dec_d))
224        pp = pp + '    "fov_h": {:f},\n'.format(fovh)
225        pp = pp + '    "fov_v": {:f},\n'.format(fovv)
226        pp = pp + '    "station_code": "{:s}",\n'.format(statid)
227        pp = pp + '    "auto_recalibrated": true,\n'
228        pp = pp + '    "az_centre": 0,\n'
229        pp = pp + '    "alt_centre": 0,\n'
230        pp = pp + '    "rotation_from_horiz": 0,\n'
231        pp = pp + '    "pos_angle_ref": 0,\n'
232        pp = pp + '    "Ho": 0,\n'
233        pp = pp + '    "UT_corr": 0,\n'
234        pp = pp + '    "F_scale": 0,\n'
235        pp = pp + '    "version": 2\n'
236        pp = pp + '}'
237
238        return pp

" Load and manage a UFO-Analyser XML file containing meteor detections

UAXml(fname)
17    def __init__(self, fname):
18        """Construct a UAxml object from fname"""
19        with open(fname) as fd:
20            self.uaxml = xmltodict.parse(fd.read())

Construct a UAxml object from fname

def getDateTime(self):
22    def getDateTime(self):
23        y, m, d = UAXml.getDateYMD(self)
24        h, mi, s = UAXml.getTimeHMS(self)
25        ss = int(math.floor(s))
26        ms = int((s - ss) * 1000000)
27
28        dtim = datetime.datetime(y, m, d, h, mi, ss, ms)
29        return dtim
def getDate(self):
31    def getDate(self):
32        ur = self.uaxml['ufoanalyzer_record']
33        return int(ur['@y']) * 10000 + int(ur['@mo']) * 100 + int(ur['@d'])
def getDateYMD(self):
35    def getDateYMD(self):
36        yr = int(self.uaxml['ufoanalyzer_record']['@y'])
37        mo = int(self.uaxml['ufoanalyzer_record']['@mo'])
38        dy = int(self.uaxml['ufoanalyzer_record']['@d'])
39        return yr, mo, dy
def getDateStr(self):
41    def getDateStr(self):
42        ur = self.uaxml['ufoanalyzer_record']
43        return f'{ur["@y"]}-{int(ur["@mo"]):02d}-{int(ur["@d"]):02d}'
def getTime(self):
45    def getTime(self):
46        ur = self.uaxml['ufoanalyzer_record']
47        return int(ur['@h']) * 3600 + int(ur['@m']) * 60 + float(ur['@s'])
def getTimeStr(self):
49    def getTimeStr(self):
50        ur = self.uaxml['ufoanalyzer_record']
51        return ur['@h'] + ":" + ur['@m'] + ":" + ur['@s']
def getTimeHMS(self):
53    def getTimeHMS(self):
54        h = int(self.uaxml['ufoanalyzer_record']['@h'])
55        m = int(self.uaxml['ufoanalyzer_record']['@m'])
56        s = float(self.uaxml['ufoanalyzer_record']['@s'])
57        return h, m, s
def getCameraDetails(self):
59    def getCameraDetails(self):
60        fps = float(self.uaxml['ufoanalyzer_record']['@fps'])
61        cx = float(self.uaxml['ufoanalyzer_record']['@cx'])
62        cy = float(self.uaxml['ufoanalyzer_record']['@cy'])
63        isintl = int(self.uaxml['ufoanalyzer_record']['@interlaced'])
64        return fps, cx, cy, isintl
def getStationDetails(self):
66    def getStationDetails(self):
67        sta = self.uaxml['ufoanalyzer_record']['@lid'] + "_" + self.uaxml['ufoanalyzer_record']['@sid']
68        lid = self.uaxml['ufoanalyzer_record']['@lid']
69        sid = self.uaxml['ufoanalyzer_record']['@sid']
70        lat = float(self.uaxml['ufoanalyzer_record']['@lat'])
71        lng = float(self.uaxml['ufoanalyzer_record']['@lng'])
72        alt = float(self.uaxml['ufoanalyzer_record']['@alt'])
73        return sta, lid, sid, lat, lng, alt
def getProfDetails(self):
75    def getProfDetails(self):
76        az = float(self.uaxml['ufoanalyzer_record']['@az'])
77        ev = float(self.uaxml['ufoanalyzer_record']['@ev'])
78        rot = float(self.uaxml['ufoanalyzer_record']['@rot'])
79        fovh = float(self.uaxml['ufoanalyzer_record']['@vx'])
80        yx = float(self.uaxml['ufoanalyzer_record']['@yx'])
81        dx = float(self.uaxml['ufoanalyzer_record']['@dx'])
82        dy = float(self.uaxml['ufoanalyzer_record']['@dy'])
83        lnk = float(self.uaxml['ufoanalyzer_record']['@dl'])
84        return az, ev, rot, fovh, yx, dx, dy, lnk
def getObjectCount(self):
86    def getObjectCount(self):
87        return int(self.uaxml['ufoanalyzer_record']['@o'])
def getObjectBasics(self, objno):
 89    def getObjectBasics(self, objno):
 90        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
 91        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
 92        if oc == 1:
 93            uo = uos['ua2_object']
 94        else:
 95            uo = uos['ua2_object'][objno]
 96        sec = float(uo['@sec'])
 97        av = float(uo['@av'])
 98        pix = int(uo['@pix'])
 99        bmax = float(uo['@bmax'])
100        mag = float(uo['@mag'])
101        fcount = int(uo['@sN'])
102        return sec, av, pix, bmax, mag, fcount
def getObjectStart(self, objno):
104    def getObjectStart(self, objno):
105        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
106        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
107        if oc == 1:
108            uo = uos['ua2_object']
109        else:
110            uo = uos['ua2_object'][objno]
111        ra1 = uo['@ra1']
112        dc1 = uo['@dc1']
113        h1 = uo['@h1']
114        dist1 = uo['@dist1']
115        lng1 = uo['@lng1']
116        lat1 = uo['@lat1']
117        az1 = uo['@az1']
118        ev1 = uo['@ev1']
119        fs = uo['@fs']
120        return ra1, dc1, h1, dist1, lng1, lat1, az1, ev1, fs
def getObjectEnd(self, objno):
122    def getObjectEnd(self, objno):
123        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
124        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
125        if oc == 1:
126            uo = uos['ua2_object']
127        else:
128            uo = uos['ua2_object'][objno]
129        ra2 = uo['@ra2']
130        dc2 = uo['@dc2']
131        h2 = uo['@h2']
132        dist2 = uo['@dist2']
133        lng2 = uo['@lng2']
134        lat2 = uo['@lat2']
135        az2 = uo['@az2']
136        ev2 = uo['@ev2']
137        fe = uo['@fe']
138        return ra2, dc2, h2, dist2, lng2, lat2, az2, ev2, fe
def getObjectFrameDetails(self, objno, fno):
140    def getObjectFrameDetails(self, objno, fno):
141        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
142        oc = int(self.uaxml['ufoanalyzer_record']['@o'])
143        if oc == 1:
144            uo = uos['ua2_object']
145        else:
146            uo = uos['ua2_object'][objno]
147        uop = uo['ua2_objpath']['ua2_fdata2'][fno]
148        fno = int(uop['@fno'])
149        b = int(uop['@b'])
150        lsum = float(uop['@Lsum'])
151        mag = float(uop['@mag'])
152        az = float(uop['@az'])
153        ev = float(uop['@ev'])
154        ra = float(uop['@ra'])
155        dec = float(uop['@dec'])
156        return fno, ra, dec, mag, az, ev, lsum, b
def getPathVector(self, objno):
158    def getPathVector(self, objno):
159        fps, _, _, isintl = UAXml.getCameraDetails(self)
160        dtim = UAXml.getDateTime(self)
161
162        uos = self.uaxml['ufoanalyzer_record']['ua2_objects']
163        oc = UAXml.getObjectCount(self)
164        if oc == 1:
165            uo = uos['ua2_object']
166        else:
167            uo = uos['ua2_object'][objno]
168        fcount = int(uo['@sN'])
169        fs = int(uo['@fs'])
170        fno = numpy.zeros(fcount)
171        ra = numpy.zeros(fcount)
172        dec = numpy.zeros(fcount)
173        alt = numpy.zeros(fcount)
174        az = numpy.zeros(fcount)
175        tt = numpy.zeros(fcount)
176        mag = numpy.zeros(fcount)
177        b = numpy.zeros(fcount)
178        lsum = numpy.zeros(fcount)
179        for fc in range(fcount):
180            uop = uo['ua2_objpath']['ua2_fdata2'][fc]
181            fno[fc] = int(uop['@fno'])
182            ra[fc] = float(uop['@ra'])
183            dec[fc] = float(uop['@dec'])
184            az[fc] = float(uop['@az'])
185            alt[fc] = float(uop['@ev'])
186            mag[fc] = float(uop['@mag'])
187            b[fc] = float(uop['@b'])
188            lsum[fc] = float(uop['@Lsum'])
189
190            # UFO timestamps the first half-frame in which a detection happens and
191            # the framenumber of this is stored in "fs"
192            us = int((fno[fc] - fs) / fps * 1000000)
193            tt[fc] = round((dtim + datetime.timedelta(microseconds=us)).timestamp(), 2)
194        return fno, tt, ra, dec, mag, fcount, alt, az, b, lsum
def makePlateParEntry(self, statid):
197    def makePlateParEntry(self, statid):
198        """ Make a fake platepar file from the data, so it can be processed with RMS/WMPL """
199        imgdt = self.getDateTime()
200        _, cx, cy, _ = self.getCameraDetails()
201        az, ev, _, fovh, yx, _, _, _ = self.getProfDetails()
202        _, lid, sid, lat, lng, alt = self.getStationDetails()
203
204        ff_name = 'FF_' + statid +'_'
205        ff_name = ff_name + imgdt.strftime('%Y%m%d_%H%M%S_') 
206        ms = '{:03d}'.format(int(imgdt.microsecond / 1000))
207        ff_name = ff_name + ms + '_0000000.fits'
208
209        fovv = fovh*(cx*yx/cy)
210
211        ref_jd = datetime2JD(imgdt)
212        ra_d, dec_d = altAz2RADec(numpy.radians(az), numpy.radians(ev), ref_jd, 
213            numpy.radians(lat), numpy.radians(lng))
214
215        pp = '"' + ff_name + '": {\n'
216        pp = pp + '    "lat": {:f},\n'.format(lat)
217        pp = pp + '    "lon": {:f},\n'.format(lng)
218        pp = pp + '    "elev": {:f},\n'.format(alt)
219        pp = pp + '    "X_res": {:d},\n'.format(int(cx))
220        pp = pp + '    "Y_res": {:d},\n'.format(int(cy))
221        pp = pp + '    "JD": {:.8f},\n'.format(ref_jd)
222        pp = pp + '    "RA_d": {:.8f},\n'.format(numpy.degrees(ra_d))
223        pp = pp + '    "dec_d": {:.8f},\n'.format(numpy.degrees(dec_d))
224        pp = pp + '    "fov_h": {:f},\n'.format(fovh)
225        pp = pp + '    "fov_v": {:f},\n'.format(fovv)
226        pp = pp + '    "station_code": "{:s}",\n'.format(statid)
227        pp = pp + '    "auto_recalibrated": true,\n'
228        pp = pp + '    "az_centre": 0,\n'
229        pp = pp + '    "alt_centre": 0,\n'
230        pp = pp + '    "rotation_from_horiz": 0,\n'
231        pp = pp + '    "pos_angle_ref": 0,\n'
232        pp = pp + '    "Ho": 0,\n'
233        pp = pp + '    "UT_corr": 0,\n'
234        pp = pp + '    "F_scale": 0,\n'
235        pp = pp + '    "version": 2\n'
236        pp = pp + '}'
237
238        return pp

Make a fake platepar file from the data, so it can be processed with RMS/WMPL