In [1]:
%matplotlib inline
import matplotlib.pyplot as plt
def fax(w=15, h=10, n=111):
    fig = plt.figure(figsize=(w,h))
    ax = fig.add_subplot(n)
    ax.grid()
    return fig, ax
In [2]:
import numpy as np
import pandas as pd
from datetime import datetime
from calendar import timegm
from pyfbf import Workspace
In [3]:
kts2mps = lambda x: 0.514444 * float(x) if x!='' else np.NAN
ft2m = lambda x: 0.3048 * float(x) if x!='' else np.NAN
def iso2aircraftTime(s):
    if s=='': 
        return np.NAN
    dt = datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
    midnight = datetime(dt.year, dt.month, dt.day)
    hours = (dt - midnight).total_seconds() / 3600.0
    return hours
In [4]:
fn_iwg1 = '/data/rdr/shis/dock/sh170411/IWG1.csv'
columns = [ "iwg", "aircraftTime", "instrumentLatitude", "instrumentLongitude", "_", 
           "Altitude", "barometricAltitude", "radarAltitude", "groundSpeed", "_", 
           "aircraftIndicatedAirSpeed", "aircraftMachNumber", "aircraftVerticalSpeed", 
           "Heading", "aircraftTrackAngle", "driftAngle", 
           "Pitch", "Roll", "aircraftSideSlip", "aircraftAttackAngle", 
           "staticAirTemp", "dewpointTemp", "totalAirTemp", "aircraftExtPressure", "_", "_", 
           "windSpeed", "windDirection", "_", "solarZenithAngle", 
           "sunAircraftElevation", "sunGroundAzimuth", "sunAircraftNoseAzimuth" ]
converters = {'barometricAltitude': ft2m, 'radarAltitude': ft2m, 'aircraftIndicatedAirSpeed': kts2mps, 'aircraftTime': iso2aircraftTime}
In [5]:
df = pd.read_csv(fn_iwg1, names=columns, header=None, converters=converters) #  parse_dates=True,
In [6]:
df[1000:1005]
Out[6]:
iwg aircraftTime instrumentLatitude instrumentLongitude _ Altitude barometricAltitude radarAltitude groundSpeed _.1 ... aircraftExtPressure _.2 _.3 windSpeed windDirection _.4 solarZenithAngle sunAircraftElevation sunGroundAzimuth sunAircraftNoseAzimuth
1000 IWG1 14.917501 34.612214 -118.075844 NaN NaN 749.046 NaN 0.0 24.5 ... 926.4 0.7 907.5 NaN NaN NaN NaN NaN 1.491922e+09 NaN
1001 IWG1 14.917779 34.612214 -118.075843 NaN NaN NaN NaN 0.0 24.5 ... NaN NaN 907.0 NaN NaN NaN NaN NaN 1.491922e+09 NaN
1002 IWG1 14.918057 34.612214 -118.075843 NaN NaN 749.046 NaN 0.0 24.5 ... 926.4 0.7 907.5 NaN NaN NaN NaN NaN 1.491922e+09 NaN
1003 IWG1 14.918335 34.612214 -118.075843 NaN NaN 749.046 NaN 0.0 24.5 ... 926.4 0.7 906.8 NaN NaN NaN NaN NaN 1.491922e+09 NaN
1004 IWG1 14.918612 34.612213 -118.075843 NaN NaN 749.046 NaN 0.0 24.5 ... 926.4 0.7 907.3 NaN NaN NaN NaN NaN 1.491922e+09 NaN

5 rows × 33 columns

In [7]:
W = Workspace('rdr20170411T161346end20170411T220220sdr20170414T160410')
In [8]:
acT, sT = W.aircraftTime[:], W.systemTimer[:]
r = np.argwhere((acT > 0) & (sT > 0)).squeeze()
len(r), r[:3]
/home/rayg/.conda/envs/sat/lib/python3.6/site-packages/ipykernel_launcher.py:2: RuntimeWarning: invalid value encountered in greater
  
Out[8]:
(12984, array([21753, 21754, 21755]))
In [9]:
# confirm that records of interest are monotonic
r[np.argwhere(np.diff(acT[r])<0).squeeze()], r[np.argwhere(np.diff(sT[r])<0).squeeze()]
Out[9]:
(array([], dtype=int64), 31986)
In [10]:
sT[31985:31999]
Out[10]:
memmap([  1.68325410e+04,   1.68330566e+04,   1.52787504e+01,
         1.57922497e+01,   1.62992496e+01,   1.68127499e+01,
         1.73195000e+01,   1.78332500e+01,   1.83402500e+01,
         1.88537502e+01,   1.93605003e+01,   1.98742504e+01,
         2.03807507e+01,   2.08945007e+01], dtype=float32)
In [11]:
# choose subset for polyfit, given descent data has one flaky point in systemTimer
rsub = r[:8000]
np.max(rsub)
Out[11]:
29758
In [12]:
m,b = np.polyfit(acT[rsub], sT[rsub], 1)
m,b
Out[12]:
(3599.9693866608427, -58404.856755900713)
In [13]:
fig,ax = fax()
rss = rsub[:400]
ax.plot(acT[rss], sT[rss], '.')
ax.plot(acT[rss], m*acT[rss] + b)
Out[13]:
[<matplotlib.lines.Line2D at 0x7fb78b2069e8>]
In [14]:
# estimate systemTimer based on IWG1 aircraftTime, noting that IWG1 starts before SHIS
esT = df['aircraftTime'] * m + b
esT[6000:6020]
Out[14]:
6000    296.648060
6001    297.648051
6002    298.648043
6003    299.649034
6004    300.649026
6005    301.649017
6006    302.648009
6007    303.651000
6008    304.647992
6009    305.647983
6010    306.647975
6011    307.647966
6012    308.648958
6013    309.648949
6014    310.648940
6015    311.647932
6016    312.647923
6017    313.648915
6018    314.647906
6019    315.647898
Name: aircraftTime, dtype: float64
In [15]:
# piecewise linear interpolate IWG1 to actual systemTimer values
D = {}
rzero = np.argwhere(sT==0).squeeze()
for c in columns[1:]:
    if '_' in c:
        continue
    print(c)
    q = np.require(np.interp(sT, esT, np.array(df[c])), dtype=np.float32)
    q[rzero] = np.NAN
    D[c] = q
aircraftTime
instrumentLatitude
instrumentLongitude
Altitude
barometricAltitude
radarAltitude
groundSpeed
aircraftIndicatedAirSpeed
aircraftMachNumber
aircraftVerticalSpeed
Heading
aircraftTrackAngle
driftAngle
Pitch
Roll
aircraftSideSlip
aircraftAttackAngle
staticAirTemp
dewpointTemp
totalAirTemp
aircraftExtPressure
windSpeed
windDirection
solarZenithAngle
sunAircraftElevation
sunGroundAzimuth
sunAircraftNoseAzimuth
In [16]:
fig,ax = fax()
ax.plot(D['instrumentLongitude'], D['instrumentLatitude'], '.')
ax.plot(W['instrumentLongitude'][:][r], W['instrumentLatitude'][:][r], '.')
Out[16]:
[<matplotlib.lines.Line2D at 0x7fb78c3c8828>]
In [17]:
fig,ax = fax()
rss = r[2000:2100]
ax.plot(sT[rss], D['instrumentLatitude'][rss], '.')
ax.plot(sT[rss], W['instrumentLatitude'][:][rss], '.')
ax.legend(['interp latitude', 'orig latitude'])
Out[17]:
<matplotlib.legend.Legend at 0x7fb789471358>
In [18]:
fig,ax = fax()
ax.plot(D['Roll'], '.')
ax.plot(D['Pitch'], '.')
ax.legend(['Roll', 'Pitch'])
Out[18]:
<matplotlib.legend.Legend at 0x7fb789396fd0>
In [21]:
print("mkdir orig-nav")
for c in D.keys():
    print("cp -n {}.real4 orig-nav/".format(c))
mkdir orig-nav
cp -n aircraftTime.real4 orig-nav/
cp -n instrumentLatitude.real4 orig-nav/
cp -n instrumentLongitude.real4 orig-nav/
cp -n Altitude.real4 orig-nav/
cp -n barometricAltitude.real4 orig-nav/
cp -n radarAltitude.real4 orig-nav/
cp -n groundSpeed.real4 orig-nav/
cp -n aircraftIndicatedAirSpeed.real4 orig-nav/
cp -n aircraftMachNumber.real4 orig-nav/
cp -n aircraftVerticalSpeed.real4 orig-nav/
cp -n Heading.real4 orig-nav/
cp -n aircraftTrackAngle.real4 orig-nav/
cp -n driftAngle.real4 orig-nav/
cp -n Pitch.real4 orig-nav/
cp -n Roll.real4 orig-nav/
cp -n aircraftSideSlip.real4 orig-nav/
cp -n aircraftAttackAngle.real4 orig-nav/
cp -n staticAirTemp.real4 orig-nav/
cp -n dewpointTemp.real4 orig-nav/
cp -n totalAirTemp.real4 orig-nav/
cp -n aircraftExtPressure.real4 orig-nav/
cp -n windSpeed.real4 orig-nav/
cp -n windDirection.real4 orig-nav/
cp -n solarZenithAngle.real4 orig-nav/
cp -n sunAircraftElevation.real4 orig-nav/
cp -n sunGroundAzimuth.real4 orig-nav/
cp -n sunAircraftNoseAzimuth.real4 orig-nav/
In [23]:
end=21753
acT[end-1], acT[end]
Out[23]:
(nan, 19.330557)
In [24]:
# patch nav in-place
import os
for k,v in D.items():
    path = os.path.join(W.path, k+'.real4')
    print('patching {}'.format(path))
    mm = np.memmap(path, dtype=np.float32, mode='r+', shape=v.shape)
    mm[:end] = v[:end]
    mm.flush()
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftTime.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/instrumentLatitude.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/instrumentLongitude.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/Altitude.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/barometricAltitude.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/radarAltitude.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/groundSpeed.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftIndicatedAirSpeed.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftMachNumber.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftVerticalSpeed.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/Heading.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftTrackAngle.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/driftAngle.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/Pitch.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/Roll.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftSideSlip.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftAttackAngle.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/staticAirTemp.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/dewpointTemp.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/totalAirTemp.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/aircraftExtPressure.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/windSpeed.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/windDirection.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/solarZenithAngle.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/sunAircraftElevation.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/sunGroundAzimuth.real4
patching rdr20170411T161346end20170411T220220sdr20170414T160410/sunAircraftNoseAzimuth.real4
In [25]:
# correct aircraftType
fn_type = os.path.join(W.path, 'aircraftType.real4')
aircraftType = np.memmap(fn_type, mode='r+', dtype=np.float32)
aircraftType[:] = 871
aircraftType.flush()
In [ ]: