add programs

This commit is contained in:
ken
2022-11-27 10:34:31 -08:00
parent 2a1dd28d97
commit 1113a0cb31
8 changed files with 1347 additions and 0 deletions
+144
View File
@@ -0,0 +1,144 @@
"""
This program converts an EFIS file to csv
example:
MacPro:programs ken$ python efis2csv.py ../N72KH\ Data/flights/19oct2018/N72KH_EFIS_19oct2018/LOG000N_F.TXT
which prints the csv format to standard out
MacPro:programs ken$ python efis2csv.py ../N72KH\ Data/flights/19oct2018/N72KH_EFIS_19oct2018/LOG000N_F.TXT > ../N72KH\ Data/flights/19oct2018/N72KH_EFIS_19oct2018/LOG000N_F.csv
which pipes standard out to LOG000N_F.csv
or run from flights/
MacPro:flights ken$ python ../../programs/efis2csv.py 10oct2018/N72KH_EFIS_10oct2018/LOG000N_F.TXT > 10oct2018/N72KH_EFIS_10oct2018/LOG000N_F.csv
Dynon EFIS data description:
index, width, description, comment
1, 2, Hour, 00 to 23, current hour according to EFIS-D10As internal clock
3, 2, Minute, 00 to 59, current minute according to EFIS-D10As internal clock
5, 2, Second, 00 to 59, current second according to EFIS-D10As internal clock
7, 2, Fractions, 00 to 63, counter for 1/64 second. Data output frequency.
9, 1, Pitch Sign, + or - (positive means plane is pitched up)
10, 3, Pitch, 000 to 900, pitch up or down from level flight in 1/10 degrees (900 = 90o)
13, 1, Roll Sign, + or - (positive means plane is banked right)
14, 4, Roll, 0000 to 1800, roll left or right from level flight in 1/10 degrees (1800 = 180o)
18, 3, Yaw, 000 to 359 in degrees (000 = North, 090 = East, 180 = South, 270 = West)
21, 4, Airspeed, 0000 to 9999, airspeed in units of 1/10 m/s (1555 = 155.5 m/s)
25, 1, Altitude Sign, + or - (positive means altitude is above sea-level)
26, 4, Altitude, 0000 to 9999, altitude in units of meters
30, 1, Turn Rate Sign, + or - (positive means plane is turning right)
31, 3, Turn Rate, 000 to 999, 1/10 degrees/second rate of yaw change
34, 1, Lateral Gs Sign, + or - (positive means plane is experiencing leftward lateral acceleration)
35, 2, Lateral Gs, 00 to 99, lateral Gs in units of 1/100 G (99 = 0.99 Gs)
37, 1, Vertical Gs Sign, + or - (positive means plane is experiencing upward vertical acceleration)
38, 2, Vertical Gs, 00 to 99, vertical Gs in units of 1/10 G (99 = 9.9 Gs)
40, 2, Angle of Attack, 00 to 99, percentage of stall angle.
42, 6, Status Bitmask, An internal-use status bitmask containing 24 bits
48, 2, Product ID, Ascii-hex Dynon product ID: 01=EFIS-D10A, 10=EFIS-D10, 03=EMS-D10
50, 2, Checksum, The ascii-hex 2 byte sum of all 49 preceding bytes
52, 2, CR/LF, Carriage Return, Linefeed = 0x0D, 0x0A
"""
import argparse
import struct
"""
open file and read a byte at a time into a buffer
when two headers have been found, process bytes inbetween
then copy second header into the beginning of a new buffer and throw away old buffer
lines are only valid if surrounded by headers, otherwise they may be incomplete
"""
def calculate(buf):
"""
one buffer of data.
"""
feetpermeter=3.2808399
mps2mph=2.2369363
hrs=int(buf[0:2])
min=int(buf[2:4])
sec=int(buf[4:6])
alti=int(buf[25:29])*feetpermeter
altsign=buf[24]
if altsign=='-': alti=alti*-1
airspeed=(int(buf[20:24])/10.0)*mps2mph
values = (hrs,min,sec,\
alti,airspeed)
#return values
def efistime(buf):
hrs=int(buf[0:2])
min=int(buf[2:4])
sec=int(buf[4:6])
return(hrs,min,sec)
def alti(buf):
feetpermeter=3.2808399
alti=int(buf[25:29])*feetpermeter
altsign=buf[24]
if altsign=='-': alti=alti*-1
return(alti)
def pitch(buf):
pit=int(buf[9:12])/10.0
pitsign=buf[8]
if pitsign=='-': pit=pit*-1
return(pit)
def roll(buf):
roll=int(buf[13:17])/10.0
rollsign=buf[12]
if rollsign=='-': roll=roll*-1
return(roll)
def yaw(buf):
yaw=int(buf[17:20])
return(yaw)
def airspeed(buf):
mps2mph=2.2369363
return((int(buf[20:24])/10.0)*mps2mph)
def aoa(buf):
return(int(buf[39:41]))
def output_values(h,m,s,alti,airspeed,aoa,pitch,roll,yaw):
print(("%02d:%02d:%02d, " # h,m,s
"%d, %d, %d, " # alti,airspeed, aoa
"%4.1f, %4.1f, %d") % (h,m,s,alti,airspeed,aoa,pitch,roll,yaw))
def read_data(name):
with open(name, "r") as f:
buf1=[] # start with buffer clear
l1=f.readline()
while l1 != "": # not EOF
#print(l1)
if (len(l1)==52): # was 53 with openlog
b=l1
output_values(efistime(b)[0],efistime(b)[1],efistime(b)[2],alti(b),airspeed(b),aoa(b),pitch(b),roll(b),yaw(b))
l1=f.readline()
return 0
def main():
parser = argparse.ArgumentParser(
description='EFIS csv converter',
epilog="./%(prog)s [options] > outputfile.csv to save the result")
parser.add_argument('fname',
help='file name to convert with path')
args = parser.parse_args()
data=read_data(args.fname)
return data
if __name__=="__main__":
d=main()
@@ -0,0 +1,259 @@
# %pylab makes the following imports::
#
#import numpy
#import matplotlib
#from matplotlib import pylab, mlab, pyplot
#np = numpy
#plt = pyplot
#
#from IPython.display import display
#from IPython.core.pylabtools import figsize, getfigs
#
#from pylab import *
#from numpy import *
import pandas as pd
from matplotlib.dates import date2num, DateFormatter
import matplotlib.pyplot as plt
import matplotlib.ticker as mplT
import datetime
import time
import subprocess
# GLOBAL start value sv:
sv=0
def get_df(datafile):
global sv
df=pd.read_csv(datafile, names=['TIME','ALTI','AIRSP','AOA','PITCH','ROLL','YAW'])
# convert time data to datetime format
df['TIME']=pd.to_datetime(df['TIME'], format='%H:%M:%S')
sv=1
# ignore data before clock is set from EFIS
# this IS the EFIS
'''
for i in range(1,len(df)):
if ((df['TIME'][i]-df['TIME'][i-1]).value > 1000000000):
sv=i
print("start %d" %(sv))
break
'''
return df
def add_elapsed(df):
st=df['TIME'][sv] # start time
et=[] # elapsed time
# add elapsed time column
for i in range(0,len(df)):
et.append(df['TIME'][i]-st)
df2=pd.DataFrame(et)
df2.columns=['ELAPSED']
#s=pd.Series([val.time() for val in df['TIME']])
#df2.merge(s.to_frame(), left_index=True, right_index=True)
ndf=df.join(df2)
# make flight duration (elapsed time) the index
#ndf.index=ndf['ELAPSED']
#del ndf['ELAPSED'] # delete the column
ndf = ndf.set_index('ELAPSED')
#ndf = ndf.set_index('TIME')
#ndf.drop(['TIME'], axis=1, inplace=True)
return ndf
def log_number(date):
"""get number of logs on date and return size + name"""
result=[]
rv=subprocess.check_output("python "+"flight_index.py "+date, shell=True)
rvl=rv.decode('utf-8').split('\n')
for i in range(0,len(rvl)-1):
result.append(rvl[i].lstrip(" ").split(" "))
return result
def check_newday(df):
"""returns boolean and the index of the last time before 00:00:00"""
newday=False
idx=0
# quick check if we need to search for the idx
r=df['TIME'][sv]-df['TIME'][len(df)-1]
if (r.days == -1):
return newday,0
# skip ['TIME'][0] since includes index name...
for i in range(1,len(df)-1):
td=date2num(df['TIME'][i+1])-date2num(df['TIME'][i])
if td < 0:
print("day wrap @ ", end=' ')
print(i)
idx=i
newday=True
return newday,idx
def fix_newday(df,idx):
# fix new day in-line so we don't parameterize or globalize the df
t1=df['TIME'][:idx+1]
t2=df['TIME'][idx+1:]
t2a=pd.DataFrame([x+datetime.timedelta(days=1) for x in t2])
t2as=t2a.iloc[:,0] # get series
t2as.name='TIME'
t2as.index=t2.index
tn=t1.append(t2as)
df.loc[:,'TIME']=tn
return df
def flighttime(df):
print("flight time = ", ( df['TIME'][len(df)-1] - df['TIME'][sv]))
def x_format(df):
"""sets x axis time format based on flight time"""
if df.index[-1] > pd.Timedelta("01:00:00"):
formatter=mplT.FuncFormatter(lambda s, x: time.strftime('%H:%M:%S', time.gmtime(s)))
else:
formatter=mplT.FuncFormatter(lambda s, x: time.strftime('%M:%S', time.gmtime(s)))
return formatter
"""
##################################################################################
###
### Useful plots...
###
"""
def plot_ALTSPD(df):
fig,axes = plt.subplots(nrows=2, ncols=1, sharex=True)
df.plot(y='ALTI', ax=axes[0])
df.plot(y='AIRSP', ax=axes[1])
ax=plt.gca()
tick_labels=ax.xaxis.major.formatter.seq
ax.xaxis.major.formatter.seq = [label.split()[-1] if label else "" for label in tick_labels]
plt.xticks(rotation=30)
def plot_ALTI(df):
# RPM
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
#df.plot(ax=ax, y="RPM", xlim=(sv+50,len(df)), color='b')
ax.plot(t,df['ALTI'][sv:],'-',label="ALTI")
ax.xaxis.set_major_formatter(x_format(df))
ax.set_ylabel('Feet')
ax.legend(loc='lower center')
ax=plt.gca()
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elasped Time (MM:SS)")
plt.title(FLIGHTDATE)
def plot_AIRSP(df):
# RPM
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
#df.plot(ax=ax, y="RPM", xlim=(sv+50,len(df)), color='b')
ax.plot(t,df['AIRSP'][sv:],'-',label="AIRSP")
ax.xaxis.set_major_formatter(x_format(df))
ax.set_ylabel('Kts')
ax.legend(loc='lower center')
ax=plt.gca()
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elasped Time (MM:SS)")
plt.title(FLIGHTDATE)
def plot_ROLL(df):
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
ax.plot(t,df['ROLL'][sv:],'-',label="ROLL")
ax.xaxis.set_major_formatter(x_format(df))
ax.set_ylabel('Degree')
ax.legend(loc='lower center')
ax=plt.gca()
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elasped Time (MM:SS)")
plt.title(FLIGHTDATE)
def plot_AOA(df):
# RPM
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
#df.plot(ax=ax, y="RPM", xlim=(sv+50,len(df)), color='b')
ax.plot(t,df['AOA'][sv:],'-',label="AOA")
ax.xaxis.set_major_formatter(x_format(df))
ax.set_ylabel('Deg')
ax.legend(loc='lower center')
ax=plt.gca()
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elasped Time (MM:SS)")
plt.title(FLIGHTDATE)
def plot_PITCH(df):
# RPM
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
#df.plot(ax=ax, y="RPM", xlim=(sv+50,len(df)), color='b')
ax.plot(t,df['PITCH'][sv:],'-',label="PITCH")
ax.xaxis.set_major_formatter(x_format(df))
ax.set_ylabel('Deg')
ax.legend(loc='lower center')
ax=plt.gca()
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elasped Time (MM:SS)")
plt.title(FLIGHTDATE)
+146
View File
@@ -0,0 +1,146 @@
"""
This program converts an EMS file to csv
index, width, description, comment
0, 2, Hour, 00 to 23, zulu hour
2, 2, Minute, 00 to 59, zulu minutes
4, 2, Second, 00 to 59, zulu seconds
6, 2, Fractions, 00 to 63, counter for 1/64 second. Data output frequency.
8, 4, manifold pressure, inHg * 100
12, 3, oil temp, deg F
15, 3, oil pressure, psi
18, 3, fuel pressure, psi * 10
21, 3, voltage, volts * 10
24, 3, current, amps
27, 3, rpm, rpm/10
30, 3, fuel flow, gph * 10
33, 4, fuel remaining, gallons * 10
37, 3, fuel left tank, gallons * 10
40, 3, fuel right tank, gallons * 10
43, 8, GP-1
51, 8, GP-2
59, 8, GP-3
67, 4, GP thremocouple
71, 4, EGT_1
75, 4, EGT_2
79, 4, EGT_3
83, 4, EGT_4
87, 4, EGT_5
91, 4, EGT_6
95, 3, CHT_1
98, 3, CHT_2
101, 3, CHT_3
104, 3, CHT_4
107, 3, CHT_5
110, 3, CHT_6
113, 1, contact-1
114, 1, contact-2
115, 2, Product ID, Ascii-hex Dynon product ID: 01=EFIS-D10A, 10=EFIS-D10, 03=EMS-D10
117, 2, Checksum, The ascii-hex 2 byte sum of all 49 preceding bytes
119, 2, CR/LF, Carriage Return, Linefeed = 0x0D, 0x0A
"""
import argparse
import struct
"""
open file and read a byte at a time into a buffer
when two headers have been found, process bytes inbetween
then copy second header into the beginning of a new buffer and throw away old buffer
lines are only valid if surrounded by headers, otherwise they may be incomplete
"""
def emstime(buf):
hrs=int(buf[0:2])
min=int(buf[2:4])
sec=int(buf[4:6])
return(hrs,min,sec)
def manp(buf):
return(int(buf[8:12])/100.0)
def oilt(buf):
return(int(buf[12:15]))
def oilp(buf):
return(int(buf[15:18]))
def fuelp(buf):
return(int(buf[18:21])/10.0)
def volts(buf):
return(int(buf[21:24])/10.0)
def amps(buf):
return(int(buf[24:27]))
def rpm(buf):
return(int(buf[27:30])*10.0)
def fflow(buf):
return(int(buf[30:33])/10.0)
def frem(buf):
return(int(buf[33:37])/10.0)
def ful(buf):
return(int(buf[37:40])/10.0)
def fur(buf):
return(int(buf[40:43])/10.0)
def egt(buf):
e1=int(buf[71:75])
e2=int(buf[75:79])
e3=int(buf[79:83])
e4=int(buf[83:87])
return(e1,e2,e3,e4)
def cht(buf):
c1=int(buf[95:98])
c2=int(buf[98:101])
c3=int(buf[101:104])
c4=int(buf[104:107])
return(c1,c2,c3,c4)
def output_values(h,m,s,manp,oilt,oilp,fuelp,volts,amps,rpm,fflow,frem,ful,fur,egt1,egt2,egt3,egt4,cht1,cht2,cht3,cht4):
print(("%02d:%02d:%02d, " # h,m,s
"%4.2f, %d, %d, %3.1f, %3.1f, %d, " # manp,oilt,oilp,fuelp,volts,amps
"%d, %3.1f, %3.1f, %3.1f, %3.1f, " # rpm,fflow,frem,ful,fur
"%d, %d, %d, %d, " # egt[1..4]
"%d, %d, %d, %d") % (h,m,s,manp,oilt,oilp,fuelp,volts,amps,rpm,fflow,frem,ful,fur,egt1,egt2,egt3,egt4,cht1,cht2,cht3,cht4))
def read_data(name):
with open(name, "r") as f:
buf1=[] # start with buffer clear
l1=f.readline()
while l1 != "": # not EOF
#print(len(l1))
#print(l1)
if (len(l1)==120): # was 121 with openlog
b=l1
output_values(emstime(b)[0],emstime(b)[1],emstime(b)[2],manp(b),oilt(b),oilp(b),fuelp(b),volts(b),amps(b),rpm(b),fflow(b),frem(b),ful(b),fur(b),egt(b)[0],egt(b)[1],egt(b)[2],egt(b)[3],cht(b)[0],cht(b)[1],cht(b)[2],cht(b)[3])
l1=f.readline()
return 0
def main():
parser = argparse.ArgumentParser(
description='EMS csv converter',
epilog="./%(prog)s [options] > outputfile.csv to save the result")
parser.add_argument('fname',
help='file name to convert with path')
args = parser.parse_args()
data=read_data(args.fname)
return data
if __name__=="__main__":
d=main()
+454
View File
@@ -0,0 +1,454 @@
# %pylab makes the following imports::
#
#import numpy
#import matplotlib
#from matplotlib import pylab, mlab, pyplot
#np = numpy
#plt = pyplot
#
#from IPython.display import display
#from IPython.core.pylabtools import figsize, getfigs
#
#from pylab import *
#from numpy import *
import pandas as pd
from matplotlib.dates import date2num, DateFormatter
import matplotlib.pyplot as plt
import matplotlib.ticker as mplT
import datetime
import time
import subprocess
# GLOBAL SAVEPLOTS
SAVEPLOTS = False
SAVEPATH = "."
# GLOBAL start value sv:
sv=0
def get_df(datafile):
"""read csv datafile; return dataframe"""
global sv
df=pd.read_csv(datafile, comment="#", names=['TIME','MP','OILT','OILP', 'FUELP','VBAT','IBAT','RPM','FFLOW','Frem','FL','FR','EGT1','EGT2','EGT3','EGT4','CHT1','CHT2','CHT3','CHT4'])
# convert time data to datetime format
df['TIME']=pd.to_datetime(df['TIME'], format='%H:%M:%S')
sv=1
# ignore data before clock is set from EFIS
# set GLOBAL sv
for i in range(1,len(df)):
if ((df['TIME'][i]-df['TIME'][i-1]).value > 1000000000):
sv=i
print("start %d" %(sv))
break
return df
def add_elapsed(df):
st=df['TIME'][sv] # start time
et=[] # elapsed time
# add elapsed time column
for i in range(0,len(df)):
et.append(df['TIME'][i]-st)
df2=pd.DataFrame(et)
df2.columns=['ELAPSED']
#s=pd.Series([val.time() for val in df['TIME']])
#df2.merge(s.to_frame(), left_index=True, right_index=True)
ndf=df.join(df2)
# make flight duration (elapsed time) the index
#ndf.index=ndf['ELAPSED']
#del ndf['ELAPSED'] # delete the column
ndf = ndf.set_index('ELAPSED')
#ndf = ndf.set_index('TIME')
#ndf.drop(['TIME'], axis=1, inplace=True)
return ndf
def log_number(date):
"""get number of logs on date and return size + name"""
result=[]
rv=subprocess.check_output("python "+"flight_index.py "+date, shell=True)
rvl=rv.split('\n')
for i in range(0,len(rvl)-1):
result.append(rvl[i].lstrip(" ").split(" "))
return result
def check_newday(df):
"""returns boolean and the index of the last time before 00:00:00"""
newday=False
idx=0
# quick check if we need to search for the idx
r=df['TIME'][sv]-df['TIME'][len(df)-1]
if (r.days == -1):
return newday,0
# skip ['TIME'][0] since includes index name...
for i in range(1,len(df)-1):
td=date2num(df['TIME'][i+1])-date2num(df['TIME'][i])
if td < 0:
print("day wrap @ ", end=' ')
print(i)
idx=i
newday=True
return newday,idx
def fix_newday(df,idx):
# fix new day in-line so we don't parameterize or globalize the df
t1=df['TIME'][:idx+1]
t2=df['TIME'][idx+1:]
t2a=pd.DataFrame([x+datetime.timedelta(days=1) for x in t2])
t2as=t2a.iloc[:,0] # get series
t2as.name='TIME'
t2as.index=t2.index
tn=t1.append(t2as)
df.loc[:,'TIME']=tn
return df
def flighttime(df):
"""returns flight time of current dataframe"""
#print "flight time = ", ( df['TIME'][len(df)-1] - df['TIME'][sv])
# use elapsed time to avoid day change
print("flight time = ", ( df.index[len(df)-1] - df.index[sv]))
def x_format(df):
"""sets x axis time format based on flight time"""
if df.index[-1] > pd.Timedelta("01:00:00"):
formatter=mplT.FuncFormatter(lambda s, x: time.strftime('%H:%M:%S', time.gmtime(s)))
else:
formatter=mplT.FuncFormatter(lambda s, x: time.strftime('%M:%S', time.gmtime(s)))
return formatter
"""
##################################################################################
###
### Useful plots...
###
"""
def plot_all_df(df):
df[sv:].plot(rot=30)
pass
def plot_EGT(df):
# Zulu time
fig, ax = plt.subplots()
ax.xaxis_date()
ax.xaxis.set_major_formatter(DateFormatter('%H:%M'))
x=df['TIME'][sv:]
t=list(map(date2num, x))
y1=df['EGT1'][sv:]
y2=df['EGT2'][sv:]
y3=df['EGT3'][sv:]
y4=df['EGT4'][sv:]
ax.plot_date(t,y1,'-',label="EGT1")
ax.plot_date(t,y2,'-',label="EGT2")
ax.plot_date(t,y3,'-',label="EGT3")
ax.plot_date(t,y4,'-',label="EGT4")
plt.legend(loc='lower center')
plt.xlabel("Time")
plt.ylabel("Temp (F)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_EGT.png")
def plot_EGTdt(df):
# Elapsed time
# index set to 'ELAPSED'
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
y1=df['EGT1'][sv:]
y2=df['EGT2'][sv:]
y3=df['EGT3'][sv:]
y4=df['EGT4'][sv:]
ax.plot(t,y1,'-',label="EGT1")
ax.plot(t,y2,'-',label="EGT2")
ax.plot(t,y3,'-',label="EGT3")
ax.plot(t,y4,'-',label="EGT4")
ax.xaxis.set_major_formatter(x_format(df))
plt.legend(loc='lower center')
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elapsed Time (MM:SS)")
plt.ylabel("Temp (F)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_EGTe.png")
def plot_CHT(df):
fig, ax = plt.subplots()
ax.xaxis_date()
ax.xaxis.set_major_formatter(DateFormatter('%H:%M'))
x=df['TIME'][sv:]
t=list(map(date2num, x))
y1=df['CHT1'][sv:]
y2=df['CHT2'][sv:]
y3=df['CHT3'][sv:]
y4=df['CHT4'][sv:]
ax.plot(t,y1,'-',label="CHT1")
ax.plot(t,y2,'-',label="CHT2")
ax.plot(t,y3,'-',label="CHT3")
ax.plot(t,y4,'-',label="CHT4")
plt.legend(loc='lower center')
plt.xlabel("Time")
plt.ylabel("Temp (F)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_CHT.png")
def plot_CHTdt(df):
# Elapsed time
# index set to 'ELAPSED'
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
y1=df['CHT1'][sv:]
y2=df['CHT2'][sv:]
y3=df['CHT3'][sv:]
y4=df['CHT4'][sv:]
ax.plot(t,y1,'-',label="CHT1")
ax.plot(t,y2,'-',label="CHT2")
ax.plot(t,y3,'-',label="CHT3")
ax.plot(t,y4,'-',label="CHT4")
ax.xaxis.set_major_formatter(x_format(df))
plt.legend(loc='lower center')
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elapsed Time (MM:SS)")
plt.ylabel("Temp (F)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_CHTe.png")
def plot_OIL(df):
fig,axs = plt.subplots(nrows=2, ncols=1, sharex=True)
df.plot(y='RPM', xlim=(sv+50,len(df)), ax=axs[0])
df.plot(y='OILP', xlim=(sv+50,len(df)), ax=axs[1])
plt.ylabel("PSI")
ax=plt.gca()
tick_labels=ax.xaxis.major.formatter.seq
ax.xaxis.major.formatter.seq = [label.split()[-1] if label else "" for label in tick_labels]
plt.xticks(rotation=30)
plt.xlabel("Time (MM:SS)")
axs[0].set_title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_OIL.png")
"""
def plot_BAT(df):
# VBAT, IBAT
fig, ax = plt.subplots()
ax.xaxis_date()
ax.xaxis.set_major_formatter(DateFormatter('%H:%M'))
x=df['TIME'][sv:]
t=list(map(date2num, x))
df.plot(ax=ax, y="VBAT", xlim=(sv+50,len(df)), color='b')
ax.set_ylabel('Volts')
ax.legend(loc='lower center')
ax2=ax.twinx()
df.plot(ax=ax2, y="IBAT", xlim=(sv+50,len(df)), color='g')
ax2.set_ylabel("Amps")
ax2.legend(loc='lower right')
ax=plt.gca()
#tick_labels=ax.xaxis.major.formatter.seq
#ax.xaxis.major.formatter.seq = [label.split()[-1] if label else "" for label in tick_labels]
plt.xticks(rotation=30)
plt.xlabel("Time (MM:SS)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_BAT.png")
"""
def plot_BAT(df):
# VBAT, IBAT
t=df.index.seconds[sv:]
fig,axs = plt.subplots(nrows=2, ncols=1, sharex=True)
#axs[1].xaxis_date()
axs[1].xaxis.set_major_formatter(DateFormatter('%H:%M'))
df.plot(ax=axs[0],y='VBAT', xlim=(sv,len(df)))
axs[0].set_ylabel("Volts")
axs[0].set_ylim(10.0,14.0)
axs[0].grid()
#axs[0].legend(loc='lower center')
#
df.plot(ax=axs[1],y='IBAT', xlim=(sv,len(df)))
axs[1].set_ylabel("Amps")
axs[1].set_ylim(-25.0,25)
axs[1].grid()
#
ax=plt.gca()
ax.xaxis.set_major_formatter(x_format(df))
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elapsed Time (MM:SS)")
axs[0].set_title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_VI.png")
def plot_FUEL(df):
# FL, FR
t=df.index.seconds[sv:]
fig,axs = plt.subplots(nrows=2, ncols=1, sharex=True)
#axs[1].xaxis_date()
axs[1].xaxis.set_major_formatter(DateFormatter('%H:%M'))
axs[0].plot(t,df['FL'][sv:],'-',label="FuelLeft")
axs[1].plot(t,df['FR'][sv:],'-',label="FuelRight")
axs[0].set_ylim(0,18)
axs[1].set_ylim(0,18)
axs[0].set_ylabel("Gal")
axs[1].set_ylabel("Gal")
axs[0].legend(loc='lower center')
axs[1].legend(loc='lower center')
ax=plt.gca()
ax.xaxis.set_major_formatter(x_format(df))
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elapsed Time (MM:SS)")
axs[0].set_title(FLIGHTDATE)
axs[0].grid()
axs[1].grid()
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_FuelLR.png")
# FFLOW, Frem
# see https://matplotlib.org/2.0.2/examples/color/named_colors.html
fig, ax = plt.subplots()
plt.xticks(rotation=30)
ax.plot(t,df["Frem"][sv:],'-',label="Frem", color='b')
ax.set_ylabel('Gal')
ax.legend(loc='lower center')
ax2=ax.twinx()
ax2.plot(t,df["FFLOW"][sv:],'-',label="FFLOW", color='g')
ax2.set_ylabel("GPH")
ax2.legend(loc='lower right')
ax.xaxis.set_major_formatter(x_format(df))
ax2.xaxis.set_major_formatter(x_format(df))
if df.index[-1] > pd.Timedelta("01:00:00"):
ax.set_xlabel("Elapsed Time (HH:MM:SS)")
ax2.set_xlabel("Elapsed Time (HH:MM:SS)")
else:
ax.set_xlabel("Elapsed Time (MM:SS)")
ax2.set_xlabel("Elapsed Time (MM:SS)")
plt.title(FLIGHTDATE)
ax.grid(axis='y',color='lightblue')
ax2.grid(axis='y',color='lightgreen')
ax.grid(axis='x')
ax2.grid(axis='x')
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_Fuel.png")
def plot_PWR(df):
# MP, RPM
fig, ax = plt.subplots()
df.plot(ax=ax, y="MP", xlim=(sv+50,len(df)), color='b')
ax.set_ylabel('PSI')
ax.legend(loc='lower center')
ax2=ax.twinx()
df.plot(ax=ax2, y="RPM", xlim=(sv+50,len(df)), color='g')
ax2.set_ylabel("rpm")
ax2.legend(loc='lower right')
ax=plt.gca()
tick_labels=ax.xaxis.major.formatter.seq
ax.xaxis.major.formatter.seq = [label.split()[-1] if label else "" for label in tick_labels]
plt.xticks(rotation=30)
plt.xlabel("Time (MM:SS)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_PWR.png")
def plot_RPM(df):
# RPM
fig, ax = plt.subplots()
t=df.index.seconds[sv:]
#df.plot(ax=ax, y="RPM", xlim=(sv+50,len(df)), color='b')
ax.plot(t,df['RPM'][sv:],'-',label="RPM")
ax.xaxis.set_major_formatter(x_format(df))
ax.set_ylabel('RPM')
ax.legend(loc='lower center')
ax=plt.gca()
plt.xticks(rotation=30)
if df.index[-1] > pd.Timedelta("01:00:00"):
plt.xlabel("Elapsed Time (HH:MM:SS)")
else:
plt.xlabel("Elasped Time (MM:SS)")
plt.title(FLIGHTDATE)
if SAVEPLOTS: savefig(SAVEPATH+FLIGHTDATE+"/"+FLIGHTDATE+"_PWR.png")
def plot_ALL(df):
plot_PWR(df)
plot_FUEL(df)
plot_OIL(df)
plot_BAT(df)
plot_CHT(df)
plot_EGT(df)
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
# $1 is .csv input $2 is .kml output
gpsbabel -t -i unicsv -f "$1" -x transform,trk=wpt -o kml,floating=1 -F "$2"
#echo "$1"
#echo "$2"
+183
View File
@@ -0,0 +1,183 @@
# IPython log file
"""
This program converts a Garmin aviation GPS log to csv
"""
"""
FIXME:
need to handle FlightPlan data. see 30oct2017 LOG005N_G.TXT
search KBFL
"""
import argparse
"""
start with simple lat/lon & altitude
STX (0x02 ^B)
type-1 sentence
type-2 sentence(s)
ETX (0x03 ^C)
type-1
------
id-char (alphabetic)
dd..dd data 1-10 chars
CR
LF
id=z
aaaaa altitude in feet
xcsv format ALT_FEET
id=A
s dd mmhh latitude: s{N,S} deg min hundredths of min
min to decimal = mmhh/60
xcsv format: N=+,S=- deg.min
xcsv format LAT_DIRDECIMAL
id=B
s ddd mmhh longitude: s{E,W} deg min hundredths of min
min to decimal = mmhh/60
xcsv format: E=+,W=- deg.min
xcsv format LON_DIRDECIMAL
id=C
ddd track in degrees
id=D
sss ground speed in knots
xcsv format PATH_SPEED_KNOTS
unicsv format in m/s
1mps = 1.94384617178935 knot
1knot = 0.5144440mps
type-2
------
id 3 chars: w nn nn{01..31}
seq
wpt
lat
lon
mvar
CR
LF
"""
"""
drop chars until first ETX
keep chars STX until ETX
trim STX and ETX
read lines searching for id
example:
z-0000
AN 37 3053
BW 122 1492
C346
D000
"""
def openfile(fname):
f=open(fname, "r")
return f
def format_data(buf):
"""process 1 record"""
s=''.join(buf)
ss=s.replace('\r','').split("\n")
# don't process when A- B- = missing lat/lon
if s.find("A-") > 0 or s.find("B-") > 0: return
for i in range(0,len(ss)):
if ss[i][0]=='z':
#print ss[i][1:]+", ",
s2=ss[i][1:]
try:
int(s2)
isint=True
except ValueError:
isint=False
if isint == True: print(s2+", ", end=' ')
if ss[i][0]=='A':
s1=ss[i][1:].split()
if s1[0]=='N': sign=1
else: sign=-1
try:
s2=sign*(int(s1[1])+(int(s1[2])/100.0)/60.0)
print("%0.5f"%(s2)+", ", end=' ')
except:
#print "ERROR!!"
#print s1
pass
if ss[i][0]=='B':
s1=ss[i][1:].split()
if s1[0]=='E': sign=1
else: sign=-1
try:
s2=sign*(int(s1[1])+(int(s1[2])/100.0)/60.0)
print("%0.5f"%(s2)+", ", end=' ')
except:
#print "ERROR!!"
#print s1
pass
if ss[i][0]=='D':
try:
s1=int(ss[i][1:])*0.5144440
print("%0.2f"%(s1)+", ", end=' ')
except:
pass
def read_data(f):
"""read gps records"""
rec_num=0
# search for begin record in GPS.TXT using vim with :/^v^b
# skip to the end of record
# in case we started logging in the middle of a record
byte=f.read(1)
if byte == '' : return
while (ord(byte) != 3): # ETX (0x03 ^C)
byte=f.read(1)
if byte == '' : return
# now process records until the end of file
byte=f.read(1)
while byte != '':
buf1=[] # start with buffer clear
while ord(byte) != 3: # ETX (0x03 ^C)
#print "%02X " % ord(byte),
byte = f.read(1)
if byte == '': break
buf1.append(byte)
else: # ETX, so process this record
rec_num+=1
byte = f.read(1)
#print buf1
format_data(buf1)
print(" ") # essentially new line for the record
#print rec_num
def main():
parser = argparse.ArgumentParser(description='Garmin Aviaiton GPS format converter')
parser.add_argument('file',
help='name of file to convert')
args = parser.parse_args()
fh=openfile(args.file)
#print "ALT_FEET, LAT_DIRDECIMAL, LON_DIRDECIMAL, PATH_SPEED_KNOTS"
print("altfeet, lat, lon, speed")
data=read_data(fh)
if __name__=="__main__":
main()
+68
View File
@@ -0,0 +1,68 @@
# IPython log file
"""
This program splits a combo log into separate log files
The combo log has a header on each sentence.
E: for EMS
F: for EFIS
G: for GPS
There appears to be a bug with the MBed GPS logger where the end of record
^C is dropped.
The MBed logger also uses \r as line end
use
LC_CTYPE=C tr -s '\r' '\n' < Log001n.txt > tmp
so we can process with readline()
EFIS and EMS have \r line ends
GPS has \r\n line ends
"""
import argparse
import os
def process_data(fname):
EOF=False
f=open(fname, encoding='utf-8', errors='ignore')
fname=os.path.splitext(fname)[0]
#fe=open(fname+"_F.txt", "w") # E <-> F label reversed in MBED!! or miswired @ MBED!!
#ff=open(fname+"_E.txt", "w")
fe=open(fname+"_E.txt", "w") # Teensy
ff=open(fname+"_F.txt", "w")
fg=open(fname+"_G.txt", "w")
while not EOF:
s=f.readline()
if s=="":
EOF=True
break
if s[:2] == "G:":
"""multiple lines... """
fg.write(s[2:])
while not EOF:
s=f.readline()
if s=="":
EOF=True
break
if (s[:2] != "E:") and (s[:2] != "F:"):
fg.write(s)
else:
fg.write(chr(3))
break # done with GPS record
if s[:2] == "E:": fe.write(s[2:])
if s[:2] == "F:": ff.write(s[2:])
def main():
parser = argparse.ArgumentParser(description='Log Splitter: creates separate log files for each device')
parser.add_argument('file',
help='name of file to convert')
args = parser.parse_args()
process_data(args.file)
if __name__=="__main__":
main()
+87
View File
@@ -0,0 +1,87 @@
"""
run from Airplane_Data_logger/programs/
processes all LOG0*.TXT files
~/Documents/Projects/Airplane_Data_Logger/N72KH Data/flights/-date-/
~/Documents/Projects/Airplane_Data_Logger/programs/
"""
import glob
import os
import argparse
def prepare(date):
print("splitting logs")
sp="../N72KH Data/flights/%s/N72KH_combined_%s/" %(date,date) # combined log
fl=glob.glob(sp+"L*")
for f in fl: # file in filelist
os.rename(f, f.upper())
fn=os.path.splitext(f.upper())[0] # fn = filename
# tr bsd command = translate characters \r -> \n
c="LC_CTYPE=C tr -s '\r' '\n' < '%s' > '%s'" % (f.upper(),fn+"N.TXT")
os.system(c)
# run log_splitter.py on the translated file (fn+"N")
c="python ./log_splitter.py '%s.TXT'" % (fn+"N")
os.system(c)
# NOW MOVE TO CORRECT DIRECTORY
pi=[i for i, c in enumerate(f) if c =='/']
c="mv '%sN_E.TXT' '%s/N72KH_EMS_%s/'" % (fn,f[:pi[-2]],date)
os.system(c)
c="mv '%sN_F.TXT' '%s/N72KH_EFIS_%s/'" % (fn,f[:pi[-2]],date)
os.system(c)
c="mv '%sN_G.TXT' '%s/N72KH_GPS_%s/'" % (fn,f[:pi[-2]],date)
os.system(c)
def process(date,logs):
if logs=='all' or logs=='ems':
print("processing EMS")
#sp="../N72KH Data/flights/%s/N72KH_EIS_%s/" %(date,date) # GRT EIS
sp="../N72KH Data/flights/%s/N72KH_EMS_%s/" %(date,date) # Dynon EMS
fl=glob.glob(sp+"LOG0*.TXT")
for f in fl:
fn=f.split("/")[-1].split(".")[0] # filename
# s="python ./eis_bin2csv.py '%s%s.TXT' > '%s%s.csv'" % (sp,fn,sp,fn) # GRT EIS
s="python ./ems2csv.py '%s%s.TXT' > '%s%s.csv'" % (sp,fn,sp,fn) # Dynon EMS
os.system(s)
if logs=='all' or logs=='efis':
print("processing EFIS")
sp="../N72KH Data/flights/%s/N72KH_EFIS_%s/" %(date,date)
fl=glob.glob(sp+"LOG0*.TXT")
for f in fl:
fn=f.split("/")[-1].split(".")[0] # filename
s="python ./efis2csv.py '%s%s.TXT' > '%s%s.csv'" % (sp,fn,sp,fn)
os.system(s)
if logs=='all' or logs=='gps':
print("processing GPS")
sp="../N72KH Data/flights/%s/N72KH_GPS_%s/" %(date,date) # path
fl=glob.glob(sp+"LOG0*.TXT") # file list
for f in fl:
fn=f.split("/")[-1].split(".")[0] # filename
s="python ./gps_formatter.py '%s%s.TXT' > '%s%s.csv'" % (sp,fn,sp,fn)
os.system(s)
s="./gps_convert.sh \"%s%s.csv\" \"%s%s.kml\"" % (sp,fn,sp,fn)
#print s
os.system(s)
def main():
parser = argparse.ArgumentParser(description='Process all log files')
parser.add_argument('date',
help='folder date (e.g. 2nov2017)')
parser.add_argument('logname', nargs='?', default='all',
help='{gps | ems | efis | all}')
args = parser.parse_args()
prepare(args.date)
process(args.date,args.logname)
if __name__=="__main__":
main()