1 from datetime
import datetime
as DT
2 from datetime
import timedelta
as TDel
4 from astropy.time
import Time
5 from scipy.interpolate
import UnivariateSpline
as UVS
21 __author__ =
"R. Healy & E. Karakoylu (erdem.m.karakoylu@nasa.gov)"
28 gps_time = DT(1980, 1, 6, 0, 0, 0)
29 sec_per_count = 1.117460459e-6
30 secOffset = TDel(seconds=15)
35 do_nav_time_correction = kwargs.pop(
'doNavTimeCorrection',
False)
38 self.
paramsDict[
'd_tisspvq'] = kwargs.pop(
'delta_tisspvq', 0)
39 self.
paramsDict[
'd_ticugps'] = kwargs.pop(
'delta_ticugps', 0)
40 self.
paramsDict[
'orientation'] = hicoPtr.params[
'issOrientation']
41 self.
paramsDict[
'gps_secs_090101'] = (DT(2009, 1, 1, 0, 0, 0) + secOffset
42 - gps_time).total_seconds()
43 self.
paramsDict[
'trigger_pulse_width'] = 0.860e-3
45 hicoPtr.L0.data[
'start_time'])
47 hicoPtr.L0.data[
'end_time'])
48 self.
paramsDict[
'start_date_time'] -= secOffset
50 self.
paramsDict[
'thetas'] = hicoPtr.L0.data[
'ScenePointingAngle']
51 self.
paramsDict[
'nls'] = hicoPtr.L0.data[
'n_image']
52 ffpps_all = hicoPtr.L0.header[
'FFpps'] +\
54 lfpps_all = hicoPtr.L0.header[
'LFpps'] +\
56 if ffpps_all > lfpps_all:
60 self.
paramsDict[
'exptimes'] = hicoPtr.L0.header[
'TriggerCount'] * sec_per_count
65 self.
paramsDict[
'exptimes'] = hicoPtr.L0.header[
'TriggerCount'] * sec_per_count
67 rootName = os.path.basename(hicoPtr.inpDict[
'l0File']).split(
'.bil')[0]
68 self.
paramsDict[
'pvqFileName'] = kwargs.pop(
'outputFileName',
69 '%s_pos_vel_quat.csv' % rootName)
70 self.
paramsDict[
'anglFileName'] =
'%s_LonLatViewAngles.bil' % rootName
71 self.
paramsDict[
'csvName'] = hicoPtr.inpDict[
'csvFile']
72 self.
paramsDict[
'n_pixels'] = hicoPtr.L0.data[
'ns']
74 if do_nav_time_correction:
81 def __ReadCSVFile(self):
82 usecols = [
'USGNC_PS_Pointing_Coarse_Time_Tag',
83 'USGNC_PS_Pointing_Inert_Posn_VectorX',
84 'USGNC_PS_Pointing_Inert_Posn_VectorY',
85 'USGNC_PS_Pointing_Inert_Posn_VectorZ',
86 'USGNC_PS_Pointing_Inert_Vel_VectorX',
87 'USGNC_PS_Pointing_Inert_Vel_VectorY',
88 'USGNC_PS_Pointing_Inert_Vel_VectorZ',
89 'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_0',
90 'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_1',
91 'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_2',
92 'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_3',
93 'USGNC_PS_PD_Fine_Pointing_Fine_Time_Tag',
94 'HSTCLOCKTIME0',
'HSTATTITUDEQUATS',
95 'HSTATTITUDESTATUSMODE',
96 'HSTATTITUDEQUATX',
'HSTATTITUDEQUATY',
'HSTATTITUDEQUATZ',
97 'HSTATTITUDETIME0',
'HSTATTITUDETIME1',
'_ISSGPSTIME',
98 'ISSTIMESUBSECOND',
'ICUTIMEGPSSECONDS',
99 'ICUTIMEISSSUBSECOND',
'ICUTIMEHWREGSECOND',
100 'ICUTIMEHWREGSUBSECOND',
'ISSTIMECENTURY',
101 'ISSTIMEYEAR',
'ISSTIMEMONTH',
'ISSTIMEDAY',
'ISSTIMEHOUR',
102 'ISSTIMEMINUTE',
'ISSTIMESECOND']
108 print(
"badly formatted csv file - attempting to resolve")
109 ocdataroot = os.getenv(
'OCDATAROOT')
110 hicocaldir = os.path.join(ocdataroot,
'hico/cal')
111 col_name_file = os.path.join(hicocaldir,
'csv_columns.pkl')
113 with open(col_name_file,
'rb')
as f:
114 col_names = pickle.load(f)
117 skiprows=1, names=col_names,
119 print(
'csv format issue resolved')
121 raise BadFormatCSVException
122 except FileNotFoundError:
123 raise BadFormatCSVException
126 raise EmptyCSVException
129 def __WriteHeader2CSV(self):
130 with open(self.
paramsDict[
'pvqFileName'],
'w')
as fpvq:
131 print(
'\nThis file name, %s' % os.path.basename(self.
paramsDict[
'pvqFileName']),
133 print(
'Source CSV file, %s' % self.
paramsDict[
'csvName'], file=fpvq)
134 print(
'Subset CSV file, None', file=fpvq)
135 print(
'Expected Lon/Lat/View angle filename, %s' % self.
paramsDict[
'anglFileName'],
137 print(
'Epoch, 2009 Jan 01 00:00:00 UTC', file=fpvq)
138 print(
'Requested number of pixels, %d' % self.
paramsDict[
'n_pixels'], file=fpvq)
139 print(
'Distance Unit, Feet', file=fpvq)
140 print(
'Central Body, Earth', file=fpvq)
141 print(
'CoordinateSystem, J2000', file=fpvq)
142 print(
'Theta (degrees from stowed position), %.16f' % self.
paramsDict[
'thetas'],
144 print(
'Code name, %s' % __name__, file=fpvq)
145 print(
'Code version, %s' % __version__, file=fpvq)
146 print(
'Code date, %s' % __date__, file=fpvq)
147 print(
'Code author, %s' % __author__, file=fpvq)
148 print(
'Code executed on computer, %s' % socket.gethostname(), file=fpvq)
149 print(
'Code executed by username, %s' % getpass.getuser(), file=fpvq)
150 print(
'Code run under Python osfamily, %s' % os.name, file=fpvq)
151 print(
'Code run under Python os, %s' % platform.release(), file=fpvq)
152 print(
'Code start time, %s' % self.
beginTime.strftime(
"%a %b %d %H:%M:%S"), file=fpvq)
153 print(
'Code end time, %s' % self.
finishTime.strftime(
"%a %b %d %H:%M:%S"), file=fpvq)
154 print(
'Exposure interval (frame time), %f' % self.
paramsDict[
'exptimes'], file=fpvq)
155 print(
'ISS orientation, %s' % self.
paramsDict[
'orientation'], file=fpvq)
156 print(
'Trigger pulse width (s), %.3e' % self.
paramsDict[
'trigger_pulse_width'],
158 print(
'ODRC broadcast time - gps time (s), %s' % self.
paramsDict[
'odrc_time_offset'],
160 print(
'delta_ticugps (s), %.6f' % 0, file=fpvq)
161 print(
'delta_tisspvq (s), %.6f' % 0, file=fpvq)
164 def __WriteData2CSV(self):
165 with open(self.
paramsDict[
'pvqFileName'],
'a')
as fpvq:
166 self.
dfPVQ.to_csv(fpvq, index=
False)
168 def __GetPVQIdx(self, relTimes):
169 crstmtagfld =
'USGNC_PS_Pointing_Coarse_Time_Tag'
170 fntmtagfld =
'USGNC_PS_PD_Fine_Pointing_Fine_Time_Tag'
171 locs_goodt = ((self.
dfCSV[crstmtagfld] >= relTimes[0] - 10) &
172 (self.
dfCSV[crstmtagfld] <= relTimes[-1] + 10))
173 idx = locs_goodt[locs_goodt].index
175 raise(USGNCCoarseTimeException)
176 u_usgnc = self.
dfCSV.loc[idx, crstmtagfld].duplicated()
177 udx_usgnc = u_usgnc.index[np.logical_not(u_usgnc)]
178 u_usgnc_coarse = self.
dfCSV.loc[udx_usgnc, crstmtagfld].values
179 u_usgnc_fine = self.
dfCSV.loc[udx_usgnc, fntmtagfld].values
180 t_issposvelquat = u_usgnc_coarse + u_usgnc_fine / 256 + self.
paramsDict[
'd_tisspvq']
181 return udx_usgnc, t_issposvelquat
183 def __GetStarTracking(self, hicoTimes, hstField):
189 t_issgps = self.
dfCSV._ISSGPSTIME + 1e-6 * self.
dfCSV.ISSTIMESUBSECOND -\
192 return interpolator(hicoTimes)
194 def __SplineIfNeeded(self, hicoRelTimes, fieldName):
195 if self.
dfCSV[fieldName].unique().size > 1:
198 return np.ones((self.
dfPVQ.shape[0],),
199 dtype=self.
dfCSV[fieldName].dtype) * self.
dfCSV[fieldName].unique()
201 def __GetNavOffsetTimeCorrection(self, rootname):
202 '''distance units are in km, time in s, speed in km/s'''
203 hico_ground_speed = 6.9
204 rootnameparts = rootname.split(
'.')
205 scene_ref =
'H%s%s' % (rootnameparts[1], rootnameparts[3])
206 nav_offset_file = os.path.join(os.getenv(
'OCVARROOT'),
'hico',
'navigation_offsets.txt')
207 regex_pattern = re.compile(
r'H\d+\s(-*\d*\.\d+|-*\d+)\s*(-*\d*\.\d+|-*\d+)*')
208 with open(nav_offset_file)
as nof:
210 if scene_ref
in line:
211 linematch = regex_pattern.findall(line)
213 along_track =
float(linematch[0][0])
214 across_track =
float(linematch[0][1])
215 self.
paramsDict[
'nav_offset_km'] = {
'along_track': along_track,
216 'across_track': across_track,
218 self.
paramsDict[
'nav_time_offset'] = along_track / hico_ground_speed
224 def __FillPoVeQuDF(self):
225 fields = [
'SecondsSinceEpoch',
'ISSPOSX',
'ISSPOSY',
'ISSPOSZ',
'ISSVELX',
'ISSVELY',
226 'ISSVELZ',
'ISSQX',
'ISSQY',
'ISSQZ',
'ISSQS',
'STQX',
'STQY',
'STQZ',
'STQS',
227 'HST_ATTITUDE_STATUS']
228 vecPosXfld =
'USGNC_PS_Pointing_Inert_Posn_VectorX'
229 vecPosYfld =
'USGNC_PS_Pointing_Inert_Posn_VectorY'
230 vecPosZfld =
'USGNC_PS_Pointing_Inert_Posn_VectorZ'
231 vecVelXfld =
'USGNC_PS_Pointing_Inert_Vel_VectorX'
232 vecVelYfld =
'USGNC_PS_Pointing_Inert_Vel_VectorY'
233 vecVelZfld =
'USGNC_PS_Pointing_Inert_Vel_VectorZ'
234 vecQuat0fld =
'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_0'
235 vecQuat1fld =
'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_1'
236 vecQuat2fld =
'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_2'
237 vecQuat3fld =
'USGNC_PS_Pointing_Current_Inert_Att_Quatrn_3'
238 hstAttXfld =
'HSTATTITUDEQUATX'
239 hstAttYfld =
'HSTATTITUDEQUATY'
240 hstAttZfld =
'HSTATTITUDEQUATZ'
241 hstAttSfld =
'HSTATTITUDEQUATS'
242 hstAttStatfld =
'HSTATTITUDESTATUSMODE'
243 self.
dfPVQ = pd.DataFrame(columns=fields)
245 self.
dfPVQ[
'SecondsSinceEpoch'] = hicoRelTimes - self.
paramsDict[
'gps_secs_090101']
264 def __PVQInterpolator(timeInGrid, pvqOutGrid):
265 ditp = pd.DataFrame(dict(time=timeInGrid, pvq=pvqOutGrid))
266 ditp.drop_duplicates(subset=
'time', inplace=
True)
267 ditp.sort_values(
'time', inplace=
True)
268 return UVS(ditp.time.values, ditp.pvq.values)
271 def __GetODRCTimeOffset(hdrFilePath):
273 with open(hdrFilePath,
'rt')
as fhdr:
274 for line
in fhdr.readlines():
275 if 'odrc_time_offset' in line:
276 return float(line.split(
'=')[1])
278 except FileNotFoundError
as e:
282 def __ExtractTimeDataFromCSV(self):
284 Extracts columns for the rest of processing
285 replaces half-baked date and time columns with proper datetime
288 def GetDateTime(row):
289 row = row.astype(int)
290 year = row[
'ISSTIMECENTURY'] * 100 + row[
'ISSTIMEYEAR']
291 return DT(year, row[
'ISSTIMEMONTH'], row[
'ISSTIMEDAY'],
292 row[
'ISSTIMEHOUR'], row[
'ISSTIMEMINUTE'], row[
'ISSTIMESECOND'])
294 hsdat = pd.DataFrame(columns=[
'datetime', ])
295 cols2copy = [
'ICUTIMEGPSSECONDS',
'ICUTIMEISSSUBSECOND',
296 'ICUTIMEHWREGSECOND',
'ICUTIMEHWREGSUBSECOND']
299 hsdat[
'datetime'] = self.
dfCSV.
filter(regex=
'ISSTIME',
300 axis=1).apply(GetDateTime,
303 np.testing.assert_array_equal(hsdat.datetime.values, np.sort(hsdat.datetime.values))
304 except AssertionError:
305 print(
"Caution: datetime column unordered")
309 def __GetSecsSinceEpoch(self):
310 def CheckStuff(self, hsdat, hwreg):
311 badhwregs = (hsdat.ICUTIMEHWREGSECOND[0] > hsdat.ICUTIMEHWREGSECOND).values
321 def GetHwReg(hsdat, ffpps_all):
322 hwreg = hsdat.ICUTIMEHWREGSECOND +\
323 hsdat.ICUTIMEHWREGSUBSECOND * 16.72e-6
324 locs_lt = hwreg <= ffpps_all
325 idx_lt = locs_lt.index[locs_lt]
331 hwreg, idx_lt = GetHwReg(hsdat, self.
paramsDict[
'ffpps_all'])
334 t_icugps = hsdat.loc[:,
'ICUTIMEGPSSECONDS'].values +\
335 1.e-6 * hsdat.loc[:,
'ICUTIMEISSSUBSECOND'].values
337 t_icugps -= self.
paramsDict[
'odrc_time_offset']
338 t_icugps += d_ticugps
339 hwstart = (self.
paramsDict[
'ffpps_all'] - hwreg[idx_lt[-2]]
340 ) / (hwreg[idx_lt[-1]] - hwreg[idx_lt[-2]])
341 time_start = hwstart*(t_icugps[idx_lt[-1]] -
342 t_icugps[idx_lt[-2]]) + t_icugps[idx_lt[-2]]
343 scanrange = np.arange(self.
paramsDict[
'nls'], dtype=float)
344 testrange = np.multiply(scanrange, self.
paramsDict[
'exptimes'])
345 hico_times = np.add(np.add(time_start, testrange),
346 (self.
paramsDict[
'trigger_pulse_width'] + 0.5 *
350 def __GetIssPosVelQuatXYZ(self, hicoTimes, pvtimes, inputField, pvidx=np.zeros(1)):
352 pvGrid = self.
dfCSV.loc[pvidx, inputField].values
354 pvGrid = self.
dfCSV[inputField].values
359 issPvOut =
f(hicoTimes)
362 def __GetSTQXYZS(self):
365 def __GetHSTAttitudeStat(self):