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
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
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