diff --git a/data_processing/app.py b/data_processing/app.py new file mode 100644 index 0000000..a4ad7d0 --- /dev/null +++ b/data_processing/app.py @@ -0,0 +1,27 @@ +# Run this app with `python app.py` and +# visit http://127.0.0.1:8050/ in your web browser. + +from dash import Dash, dcc, html +import plotly.express as px +from c_impedance import c_impedance_plot +from mudbat_plot import mudbat_plot +import pandas as pd + +app = Dash(__name__) + +app.layout = html.Main(children=[ + html.Div(children=[ + html.H1(children=['DirtViz']), + html.H3(children=['A soil-battery data dashboard made with Dash']) + ]), + html.Div(className="flex", children=[ + html.Div(className="flexItem", children= [dcc.Graph(figure=c_impedance_plot())]), + html.Div(className="flexItem", children= [dcc.Graph(figure=mudbat_plot())]), + html.Div(id="graph3",className="flexItem"), + html.Div(id="graph4",className="flexItem"), + html.Div(id="graph5",className="flexItem"), + ]) +]) + +if __name__ == '__main__': + app.run_server(debug=True) diff --git a/data_processing/assets/main.css b/data_processing/assets/main.css new file mode 100644 index 0000000..d14ffb4 --- /dev/null +++ b/data_processing/assets/main.css @@ -0,0 +1,51 @@ +body{ + font-family: 'Courier New', Courier, monospace; + background-color: #0d0c0c; + color:#FFFDE7; +} + +Main{ + margin: 1% 1%; +} + +.flex{ + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + align-items: flex-end; +} + +.flexItem{ + background-color: #121212; + flex-basis: auto; + margin: 0.7% 0.7%; + padding: 5px 5px; + box-shadow: 3px 3px 10px rgb(0 0 0 / 0.2); + border-radius: 10px; +} + +#graph1{ + width: 700px; + height: 400px; +} + +#graph2{ + width: 1000px; + height: 400px; +} + +#graph3{ + width: 700px; + height: 500px; +} + +#graph4{ + width: 400px; + height: 300px; +} + +#graph5{ + width: 300px; + height: 500px; +} \ No newline at end of file diff --git a/data_processing/c_impedance.py b/data_processing/c_impedance.py index 92d91fb..e166077 100755 --- a/data_processing/c_impedance.py +++ b/data_processing/c_impedance.py @@ -1,74 +1,43 @@ #!/usr/bin/env python3 -import matplotlib as mpl -mpl.use('Agg') -font= {'family': 'Arial', - 'size': 7} -mpl.rc('font', **font) -import matplotlib.pyplot as plt -import matplotlib.gridspec as gridspec -import matplotlib.dates as md -import numpy as np -from pytz import timezone -import pandas as pd -from glob import glob -import arrow -import os -from pandas.plotting import register_matplotlib_converters -register_matplotlib_converters() +import plotly.graph_objects as go +from plotly.subplots import make_subplots +import pandas as pd -avgdata = []; -avgdata.append({'mcurrent':2.2,'mvoltage':1.38,'mpower':0.003}) -avgdata.append({'mcurrent':3.2,'mvoltage':1.92,'mpower':0.006}) -avgdata.append({'mcurrent':12.3,'mvoltage':15.7,'mpower':0.19}) -avgdata.append({'mcurrent':14.8,'mvoltage':26.7,'mpower':0.4}) -avgdata.append({'mcurrent':16.3,'mvoltage':39.3,'mpower':0.64}) -avgdata.append({'mcurrent':17.1,'mvoltage':48,'mpower':0.82}) -avgdata.append({'mcurrent':17.7,'mvoltage':58.7,'mpower':0.84}) -avgdata.append({'mcurrent':18,'mvoltage':70,'mpower':1.06}) -avgdata.append({'mcurrent':19,'mvoltage':86,'mpower':1.33}) -avgdata.append({'mcurrent':20,'mvoltage':120,'mpower':2.4}) -avgdata.append({'mcurrent':20,'mvoltage':176,'mpower':3.52}) +avgdata = { + 'mcurrent':[2.2, 3.2, 12.3, 14.8, 16.3, 17.1, 17.7, 18, 19, 20, 20], + 'mvoltage':[1.38, 1.92, 15.7, 26.7, 39.3, 48, 58.7, 70, 86, 120, 176], + 'mpower':[0.003, 0.006, 0.19, 0.4, 0.64, 0.82, 0.84, 1.06, 1.33, 2.4, 3.52], + 'impedance':[68, 100, 1e3, 2e3, 3.3e3, 4.7e3, 6.8e3, 9.1e3, 15e3, 39e3, 82e3] + } avgdata = pd.DataFrame(avgdata) -print(avgdata) - -plt.close() - -fig, (ax1, ax3) = plt.subplots(2,figsize=(4,2), sharex=True) - -volt_color= 'tab:blue' -volt_style = 'solid' -amp_color = 'tab:red' -amp_style='dashed' -ax1.set_ylabel('Cell Voltage (mV)') -ax1.plot(avgdata.index, avgdata['mvoltage'], color=volt_color, ls=volt_style) -ax1.tick_params(axis='y', labelcolor=volt_color) -ax1.set_ylim(0, 200) - -ax2 = ax1.twinx() -ax2.set_ylabel('Harvesting Current (μA)') -ax2.plot(avgdata.index, avgdata['mcurrent'], color=amp_color, ls=amp_style) -ax2.tick_params(axis='y', labelcolor=amp_color) -ax2.set_ylim(0,25) - -ax1.tick_params(axis='x', which='both', length=0) -ax2.tick_params(axis='x', which='both', length=0) - -ax1.grid(True) -ax1.legend(['voltage'], loc='lower right') -ax2.legend(['current'], loc='upper left') - -ax3.set_ylabel("Power (uW)") -ax3.set_xlabel("Impedance ($\Omega$)") -ax3.grid(True) -ax3.set_ylim(0, 4) -ax3.plot(avgdata.index, avgdata['mpower']) -plt.xticks(np.arange(11), ['68', '100', '1k', '2k','3.3k','4.7k','6.8k','9.1k','15k','39k','82k']) - -plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5) -plt.subplots_adjust(hspace=0.15) -plt.savefig('c_impedance.pdf') -plt.close() - - +def c_impedance_plot(): + fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, + specs=[[{"secondary_y": True}], [{"secondary_y":False}]] + ) + + fig.add_trace( + go.Scatter(x=avgdata['impedance'], y=avgdata['mvoltage'], mode='lines', name='voltage'), + row=1, col=1, + secondary_y=False + ) + fig.add_trace( + go.Scatter(x=avgdata['impedance'], y=avgdata['mcurrent'], mode='lines', name='current'), + row=1, col=1, + secondary_y=True + ) + fig.add_trace( + go.Scatter(x=avgdata['impedance'], y=avgdata['mpower'], mode='lines', showlegend=False), + row=2, col=1 + ) + + fig.update_xaxes(title={'text':"Impedance (Ω)"}, row=2, col=1) + fig.update_yaxes(title={'text':"Cell Voltage (mV)", 'standoff':5}, row=1,col=1, secondary_y=False) + fig.update_yaxes(title={'text':"Harvesting Current (μA)"}, row=1,col=1, secondary_y=True) + fig.update_yaxes(title={'text':"Power (uW)", 'standoff':20}, row=2, col=1) + fig.update_layout(height=500, width=700, title="Impedance Subplots",template='plotly_dark', + paper_bgcolor="#121212", plot_bgcolor="#121212" + ) + + return fig \ No newline at end of file diff --git a/data_processing/mudbat_plot.py b/data_processing/mudbat_plot.py index 224afb3..f029c4a 100755 --- a/data_processing/mudbat_plot.py +++ b/data_processing/mudbat_plot.py @@ -15,12 +15,14 @@ import arrow import os +import plotly.graph_objects as go +from plotly.subplots import make_subplots + if not os.path.exists("mudbat_data.pkl"): fnames = glob("data/carbon-carbon/mudbat*.csv") mudbat_data = None for fname in sorted(fnames, key=lambda x: int(x.split('.')[0].split('_')[-1])): - print(fname) data = np.genfromtxt(fname, dtype=float, delimiter=',',skip_header=11) if '3' in fname: data = pd.DataFrame({'timestamp':pd.to_datetime(data[:,0], unit='s'), 'current':data[:,3]*-10E-12, 'voltage':data[:,4]*-10E-9}) @@ -30,8 +32,6 @@ if '3' in fname: start = data['timestamp'][0] data['power'] = np.abs(np.multiply(data['current'], data['voltage'])) - data.set_index('timestamp', inplace=True) - print(data) if mudbat_data is None: mudbat_data = data else: @@ -41,56 +41,39 @@ else: mudbat_data = pd.read_pickle("mudbat_data.pkl") -print(mudbat_data) - -mv = mudbat_data.rolling(5*60).mean() -plt.xlabel("Time") -fig, (ax1, ax3) = plt.subplots(2,figsize=(4,2), sharex=True) -fig.autofmt_xdate() - -ind = mv.index > start -mv = mv[ind] +mudbat_data.iloc[:, 1:4] = mudbat_data.iloc[:, 1:4].rolling(5*60).mean() -volt_color= 'tab:blue' -volt_style = 'solid' -amp_color = 'tab:red' -amp_style='dashed' -ax1.set_ylabel('Cell Voltage (V)') -ax1.plot(mv.index, mv['voltage'], color=volt_color, ls=volt_style) -ax1.tick_params(axis='y', labelcolor=volt_color) -ax1.set_ylim(0, .05) +ind = mudbat_data['timestamp'] > start +mudbat_data = mudbat_data[ind] -ax2 = ax1.twinx() -ax2.set_ylabel('Harvesting Current (μA)') -ax2.plot(mv.index, -1E6*mv['current'], color=amp_color, ls=amp_style) -ax2.tick_params(axis='y', labelcolor=amp_color) -ax2.set_ylim(0,50) -ax1.tick_params(axis='x', which='both', length=0) -ax2.tick_params(axis='x', which='both', length=0) -ax1.grid(True) -ax1.legend(['voltage'], loc='upper left' , prop={'size':6}) -ax2.legend(['current'], loc='lower right', prop={'size':6}) +def mudbat_plot(): + fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.1, + specs=[[{"secondary_y": True}], [{"secondary_y":False}]], + ) -#ax3.fmt_xdata = md.DateFormatter('%d %h:%m') -ax3.xaxis.set_major_formatter(md.DateFormatter('%m-%d')) -ax3.set_ylabel("Power (uW)") -ax3.grid(True) -ax3.plot(mv.index, 1E6*mv['power']) -ax3.tick_params(axis='x', labelsize=6, rotation=0) -for label in ax3.get_xticklabels(): - label.set_horizontalalignment('center') -ax3.set_xlim(mv.index[0], datetime.date(2020,5,27)) -ax3.set_ylim(0,1) + fig.add_trace( + go.Scatter(x=mudbat_data['timestamp'], y=mudbat_data['voltage'], mode='lines', name='voltage'), + row=1, col=1, + secondary_y=False + ) + fig.add_trace( + go.Scatter(x=mudbat_data['timestamp'], y=mudbat_data['current'], mode='lines', name='current'), + row=1, col=1, + secondary_y=True + ) + fig.add_trace( + go.Scatter(x=mudbat_data['timestamp'], y=mudbat_data['power'], mode='lines', showlegend=False), + row=2, col=1 + ) -plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=0.5) -plt.subplots_adjust(hspace=0.15) -#plt.show() -plt.savefig('c-c_battery.pdf') -#plt.savefig('soil.png', dpi=180) -tot_energy = np.trapz(mudbat_data['power']) -print(tot_energy) -print(mudbat_data) -after_spike = mudbat_data['power'][60*60*24*5:] -print(np.average(after_spike), np.std(after_spike)) -print((mudbat_data.tail(1).index - mudbat_data.head(1).index).total_seconds()) + fig.update_xaxes(title={'text':"Impedance (Ω)"}, row=2, col=1) + fig.update_yaxes(title={'text':"Cell Voltage (mV)", 'standoff':5}, row=1,col=1, secondary_y=False) + fig.update_yaxes(title={'text':"Harvesting Current (μA)"}, row=1,col=1, secondary_y=True) + fig.update_yaxes(title={'text':"Power (uW)", 'standoff':5}, row=2, col=1) + fig.update_layout(height=500, width=700, title="Mudbat Subplots",template='plotly_dark', + paper_bgcolor="#121212", plot_bgcolor="#121212", + legend={'orientation':'h', 'xanchor':'right', 'yanchor': 'bottom', 'y':1.02, 'x':1} + ) + + return fig \ No newline at end of file