Implement automatic chart generation with user input and notifications
This commit is contained in:
parent
8e9b8f193a
commit
1821871ceb
File diff suppressed because it is too large
Load Diff
|
@ -17,3 +17,6 @@ plotly = { version = "0.8.1", features = ["wasm"] }
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
toml = "0.5.9"
|
||||
indicatif = "0.17.3"
|
||||
dialoguer = "0.10.3"
|
||||
notify-rust = "4.7.0"
|
||||
|
|
322
Shots/Shots.py
322
Shots/Shots.py
|
@ -1,161 +1,161 @@
|
|||
import pandas as pd
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import numpy as np
|
||||
from numpy import diff
|
||||
|
||||
from scipy.interpolate import make_interp_spline
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
timestamp_start = None
|
||||
|
||||
def unix_to_datetime(unix_string):
|
||||
return datetime.strptime(unix_string, "%H:%M:%S.%f")
|
||||
|
||||
def deltatime(time):
|
||||
global timestamp_start
|
||||
return (time - timestamp_start).total_seconds()
|
||||
|
||||
def timestamp_converter(timestamp):
|
||||
time = unix_to_datetime(timestamp)
|
||||
|
||||
global timestamp_start
|
||||
if timestamp_start == None:
|
||||
timestamp_start = time
|
||||
|
||||
delta = deltatime(time)
|
||||
return delta
|
||||
|
||||
shots = [
|
||||
{
|
||||
'filename': 'Elisabeth/16_06_2022_1.xlsx',
|
||||
'title': 'Elisabeth 16.06.2022 #1',
|
||||
'cutoff': 38,
|
||||
}, # [0]
|
||||
{
|
||||
'filename': 'Elisabeth/19_06_2022_1.xlsx',
|
||||
'title': 'Elisabeth 19.06.2022 #1',
|
||||
}, # [1]
|
||||
{
|
||||
'filename': 'Laura/20_06_2022_1.xlsx',
|
||||
'title': 'Laura 20.06.2022 #1',
|
||||
'cutoff': 38.7,
|
||||
}, # [2]
|
||||
{
|
||||
'filename': 'Laura/20_06_2022_2.xlsx',
|
||||
'title': 'Laura 20.06.2022 #2',
|
||||
'cutoff': 32.6,
|
||||
}, # [3]
|
||||
]
|
||||
|
||||
comparison = {
|
||||
'Elisabeth 19.06.22 Shot #1 vs. #2': (0, 1), #[0]
|
||||
'Laura 20.06.22 Shot #1 vs #2': (2, 3), #[1]
|
||||
#'comparison': {
|
||||
# 'Elisabeth Shots 06/13/22 - 06/10/22': (1, 2), #[0]
|
||||
# 'Elisabeth Shots 06/15/22 - 06/10/22': (1, 3), #[1]
|
||||
# 'Elisabeth Shots 06/15/22 - 06/13/22': (2, 3), #[2]
|
||||
# }
|
||||
}
|
||||
|
||||
|
||||
curr_figure = 0
|
||||
|
||||
fig1 = plt.figure(curr_figure)
|
||||
ax1 = plt.subplot(2, 2, 1)
|
||||
# ax1.minorticks_on()
|
||||
# plt.title('Shotweight over time')
|
||||
plt.ylabel('Weight (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
ax2 = plt.subplot(2, 2, 3, sharex=ax1)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.ylabel('Flow-rate (g/s)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
ax3 = plt.subplot(2, 2, 2, sharex=ax1, sharey=ax1)
|
||||
# plt.title('Shotweight over time')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
ax4 = plt.subplot(2, 2, 4, sharex=ax2, sharey=ax2)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
fig1.supxlabel('Time (s)')
|
||||
plt.tight_layout()
|
||||
|
||||
plt.subplot(2, 2, 1)
|
||||
|
||||
for shot in shots:
|
||||
timestamp_start = None
|
||||
|
||||
df_raw = pd.read_excel(shot['filename'], converters={
|
||||
0: lambda x: timestamp_converter(x)
|
||||
}, sheet_name=0)
|
||||
df_calc = pd.read_excel(shot['filename'], converters={
|
||||
0: lambda x: timestamp_converter(x)
|
||||
}, sheet_name=1)
|
||||
|
||||
time_col_raw = df_raw.keys()[0]
|
||||
profile_col_raw = df_raw.keys()[5]
|
||||
|
||||
time_col_calc = df_calc.keys()[0]
|
||||
profile_col_calc = df_calc.keys()[2]
|
||||
|
||||
if 'cutoff' in shot:
|
||||
if shot['cutoff'] != -1:
|
||||
df_raw = df_raw.loc[df_raw[time_col_raw] < shot['cutoff']]
|
||||
df_calc = df_calc.loc[df_calc[time_col_calc] < shot['cutoff']]
|
||||
|
||||
shot['data'] = {}
|
||||
|
||||
shot['data']['profile'] = df_raw
|
||||
shot['data']['flowrate'] = df_calc
|
||||
|
||||
time = df_raw[time_col_raw].tolist()
|
||||
weight = df_raw[profile_col_raw].tolist()
|
||||
# print("time: ", time)
|
||||
# print("weight: ", time)
|
||||
plt.plot(time, weight, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 2, 3)
|
||||
|
||||
flow_time = df_calc[time_col_calc].tolist()
|
||||
flowrate = df_calc[profile_col_calc].tolist()
|
||||
# print("flow_time: ", flow_time)
|
||||
# print("flowrate: ", flowrate)
|
||||
plt.plot(flow_time, flowrate, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 2, 1)
|
||||
|
||||
plt.subplot(2, 2, 4)
|
||||
|
||||
for key in comparison:
|
||||
calc1 = shots[comparison[key][0]]['data']['flowrate']
|
||||
calc2 = shots[comparison[key][1]]['data']['flowrate']
|
||||
|
||||
t1 = np.array(calc1[calc1.keys()[0]].tolist())
|
||||
r1 = np.array(calc1[calc1.keys()[2]].tolist())
|
||||
|
||||
t2 = np.array(calc2[calc2.keys()[0]].tolist())
|
||||
r2 = np.array(calc2[calc2.keys()[2]].tolist())
|
||||
|
||||
dt = None
|
||||
size_diff = t2.size - t1.size
|
||||
if size_diff > 0:
|
||||
dt = t2
|
||||
r1 = np.pad(r1, (0, size_diff), 'constant')
|
||||
elif size_diff < 0:
|
||||
dt = t1
|
||||
r2 = np.pad(r2, (0, -size_diff), 'constant')
|
||||
|
||||
dr = r2 - r1
|
||||
|
||||
plt.plot(dt, dr, label = key, linewidth=1)
|
||||
|
||||
plt.legend(loc='best')
|
||||
|
||||
plt.show()
|
||||
import pandas as pd
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import numpy as np
|
||||
from numpy import diff
|
||||
|
||||
from scipy.interpolate import make_interp_spline
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
timestamp_start = None
|
||||
|
||||
def unix_to_datetime(unix_string):
|
||||
return datetime.strptime(unix_string, "%H:%M:%S.%f")
|
||||
|
||||
def deltatime(time):
|
||||
global timestamp_start
|
||||
return (time - timestamp_start).total_seconds()
|
||||
|
||||
def timestamp_converter(timestamp):
|
||||
time = unix_to_datetime(timestamp)
|
||||
|
||||
global timestamp_start
|
||||
if timestamp_start == None:
|
||||
timestamp_start = time
|
||||
|
||||
delta = deltatime(time)
|
||||
return delta
|
||||
|
||||
shots = [
|
||||
{
|
||||
'filename': 'Elisabeth/16_06_2022_1.xlsx',
|
||||
'title': 'Elisabeth 16.06.2022 #1',
|
||||
'cutoff': 38,
|
||||
}, # [0]
|
||||
{
|
||||
'filename': 'Elisabeth/19_06_2022_1.xlsx',
|
||||
'title': 'Elisabeth 19.06.2022 #1',
|
||||
}, # [1]
|
||||
{
|
||||
'filename': 'Laura/20_06_2022_1.xlsx',
|
||||
'title': 'Laura 20.06.2022 #1',
|
||||
'cutoff': 38.7,
|
||||
}, # [2]
|
||||
{
|
||||
'filename': 'Laura/20_06_2022_2.xlsx',
|
||||
'title': 'Laura 20.06.2022 #2',
|
||||
'cutoff': 32.6,
|
||||
}, # [3]
|
||||
]
|
||||
|
||||
comparison = {
|
||||
'Elisabeth 19.06.22 Shot #1 vs. #2': (0, 1), #[0]
|
||||
'Laura 20.06.22 Shot #1 vs #2': (2, 3), #[1]
|
||||
#'comparison': {
|
||||
# 'Elisabeth Shots 06/13/22 - 06/10/22': (1, 2), #[0]
|
||||
# 'Elisabeth Shots 06/15/22 - 06/10/22': (1, 3), #[1]
|
||||
# 'Elisabeth Shots 06/15/22 - 06/13/22': (2, 3), #[2]
|
||||
# }
|
||||
}
|
||||
|
||||
|
||||
curr_figure = 0
|
||||
|
||||
fig1 = plt.figure(curr_figure)
|
||||
ax1 = plt.subplot(2, 2, 1)
|
||||
# ax1.minorticks_on()
|
||||
# plt.title('Shotweight over time')
|
||||
plt.ylabel('Weight (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
ax2 = plt.subplot(2, 2, 3, sharex=ax1)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.ylabel('Flow-rate (g/s)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
ax3 = plt.subplot(2, 2, 2, sharex=ax1, sharey=ax1)
|
||||
# plt.title('Shotweight over time')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
ax4 = plt.subplot(2, 2, 4, sharex=ax2, sharey=ax2)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
fig1.supxlabel('Time (s)')
|
||||
plt.tight_layout()
|
||||
|
||||
plt.subplot(2, 2, 1)
|
||||
|
||||
for shot in shots:
|
||||
timestamp_start = None
|
||||
|
||||
df_raw = pd.read_excel(shot['filename'], converters={
|
||||
0: lambda x: timestamp_converter(x)
|
||||
}, sheet_name=0)
|
||||
df_calc = pd.read_excel(shot['filename'], converters={
|
||||
0: lambda x: timestamp_converter(x)
|
||||
}, sheet_name=1)
|
||||
|
||||
time_col_raw = df_raw.keys()[0]
|
||||
profile_col_raw = df_raw.keys()[5]
|
||||
|
||||
time_col_calc = df_calc.keys()[0]
|
||||
profile_col_calc = df_calc.keys()[2]
|
||||
|
||||
if 'cutoff' in shot:
|
||||
if shot['cutoff'] != -1:
|
||||
df_raw = df_raw.loc[df_raw[time_col_raw] < shot['cutoff']]
|
||||
df_calc = df_calc.loc[df_calc[time_col_calc] < shot['cutoff']]
|
||||
|
||||
shot['data'] = {}
|
||||
|
||||
shot['data']['profile'] = df_raw
|
||||
shot['data']['flowrate'] = df_calc
|
||||
|
||||
time = df_raw[time_col_raw].tolist()
|
||||
weight = df_raw[profile_col_raw].tolist()
|
||||
# print("time: ", time)
|
||||
# print("weight: ", time)
|
||||
plt.plot(time, weight, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 2, 3)
|
||||
|
||||
flow_time = df_calc[time_col_calc].tolist()
|
||||
flowrate = df_calc[profile_col_calc].tolist()
|
||||
# print("flow_time: ", flow_time)
|
||||
# print("flowrate: ", flowrate)
|
||||
plt.plot(flow_time, flowrate, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 2, 1)
|
||||
|
||||
plt.subplot(2, 2, 4)
|
||||
|
||||
for key in comparison:
|
||||
calc1 = shots[comparison[key][0]]['data']['flowrate']
|
||||
calc2 = shots[comparison[key][1]]['data']['flowrate']
|
||||
|
||||
t1 = np.array(calc1[calc1.keys()[0]].tolist())
|
||||
r1 = np.array(calc1[calc1.keys()[2]].tolist())
|
||||
|
||||
t2 = np.array(calc2[calc2.keys()[0]].tolist())
|
||||
r2 = np.array(calc2[calc2.keys()[2]].tolist())
|
||||
|
||||
dt = None
|
||||
size_diff = t2.size - t1.size
|
||||
if size_diff > 0:
|
||||
dt = t2
|
||||
r1 = np.pad(r1, (0, size_diff), 'constant')
|
||||
elif size_diff < 0:
|
||||
dt = t1
|
||||
r2 = np.pad(r2, (0, -size_diff), 'constant')
|
||||
|
||||
dr = r2 - r1
|
||||
|
||||
plt.plot(dt, dr, label = key, linewidth=1)
|
||||
|
||||
plt.legend(loc='best')
|
||||
|
||||
plt.show()
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
import pandas as pd
|
||||
|
||||
import numpy as np
|
||||
from numpy import diff
|
||||
|
||||
from scipy.interpolate import make_interp_spline
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
shots = [
|
||||
{
|
||||
'filename': 'Elisabeth/16_06_2022_1.xlsx',
|
||||
'title': 'Elisabeth 16.06.2022 #1',
|
||||
'cutoff': 38,
|
||||
'data': {}
|
||||
}, # [0]
|
||||
]
|
||||
|
||||
curr_figure = 0
|
||||
|
||||
plt.figure(curr_figure)
|
||||
plt.subplot(2, 1, 1)
|
||||
# plt.title('Shotweight over time')
|
||||
# plt.xlabel('Time (s)')
|
||||
plt.ylabel('Weight (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.xlabel('Time (s)')
|
||||
plt.ylabel('Flow-rate (g/s)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
for shot in shots:
|
||||
df_raw = pd.read_excel(shot['filename'], converters={
|
||||
1: lambda x: float(x) if not str(x).endswith('.10') else float(x) + 0.85
|
||||
}, sheet_name=0)
|
||||
df_calc = pd.read_excel(shot['filename'], converters={
|
||||
1: lambda x: float(x) if not str(x).endswith('.10') else float(x) + 0.85
|
||||
}, sheet_name=1)
|
||||
|
||||
time_col_raw = df_raw.keys()[1]
|
||||
profile_col_raw = df_raw.keys()[5]
|
||||
|
||||
time_col_calc = df_calc.keys()[1]
|
||||
profile_col_calc = df_calc.keys()[2]
|
||||
|
||||
df_raw_co = df_raw.loc[df_raw[time_col_raw] < shot['cutoff']]
|
||||
df_calc_co = df_calc.loc[df_calc[time_col_calc] < shot['cutoff']]
|
||||
|
||||
shot['data']['profile'] = df_raw_co
|
||||
shot['data']['flowrate'] = df_calc_co
|
||||
|
||||
time = df_raw_co[time_col_raw].tolist()
|
||||
weight = df_raw_co[profile_col_raw].tolist()
|
||||
print("time: ", time)
|
||||
print("weight: ", time)
|
||||
plt.plot(time, weight, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
|
||||
flow_time = df_calc_co[time_col_calc].tolist()
|
||||
flowrate = df_calc_co[profile_col_calc].tolist()
|
||||
print("flow_time: ", flow_time)
|
||||
print("flowrate: ", flowrate)
|
||||
plt.plot(flow_time, flowrate, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
plt.legend(loc='best')
|
||||
|
||||
plt.show()
|
||||
import pandas as pd
|
||||
|
||||
import numpy as np
|
||||
from numpy import diff
|
||||
|
||||
from scipy.interpolate import make_interp_spline
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
shots = [
|
||||
{
|
||||
'filename': 'Elisabeth/16_06_2022_1.xlsx',
|
||||
'title': 'Elisabeth 16.06.2022 #1',
|
||||
'cutoff': 38,
|
||||
'data': {}
|
||||
}, # [0]
|
||||
]
|
||||
|
||||
curr_figure = 0
|
||||
|
||||
plt.figure(curr_figure)
|
||||
plt.subplot(2, 1, 1)
|
||||
# plt.title('Shotweight over time')
|
||||
# plt.xlabel('Time (s)')
|
||||
plt.ylabel('Weight (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.xlabel('Time (s)')
|
||||
plt.ylabel('Flow-rate (g/s)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
for shot in shots:
|
||||
df_raw = pd.read_excel(shot['filename'], converters={
|
||||
1: lambda x: float(x) if not str(x).endswith('.10') else float(x) + 0.85
|
||||
}, sheet_name=0)
|
||||
df_calc = pd.read_excel(shot['filename'], converters={
|
||||
1: lambda x: float(x) if not str(x).endswith('.10') else float(x) + 0.85
|
||||
}, sheet_name=1)
|
||||
|
||||
time_col_raw = df_raw.keys()[1]
|
||||
profile_col_raw = df_raw.keys()[5]
|
||||
|
||||
time_col_calc = df_calc.keys()[1]
|
||||
profile_col_calc = df_calc.keys()[2]
|
||||
|
||||
df_raw_co = df_raw.loc[df_raw[time_col_raw] < shot['cutoff']]
|
||||
df_calc_co = df_calc.loc[df_calc[time_col_calc] < shot['cutoff']]
|
||||
|
||||
shot['data']['profile'] = df_raw_co
|
||||
shot['data']['flowrate'] = df_calc_co
|
||||
|
||||
time = df_raw_co[time_col_raw].tolist()
|
||||
weight = df_raw_co[profile_col_raw].tolist()
|
||||
print("time: ", time)
|
||||
print("weight: ", time)
|
||||
plt.plot(time, weight, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
|
||||
flow_time = df_calc_co[time_col_calc].tolist()
|
||||
flowrate = df_calc_co[profile_col_calc].tolist()
|
||||
print("flow_time: ", flow_time)
|
||||
print("flowrate: ", flowrate)
|
||||
plt.plot(flow_time, flowrate, label = shot['title'], linewidth=1)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
plt.legend(loc='best')
|
||||
|
||||
plt.show()
|
||||
|
|
|
@ -1,160 +1,160 @@
|
|||
import csv
|
||||
|
||||
import numpy as np
|
||||
from numpy import diff
|
||||
|
||||
from scipy.interpolate import make_interp_spline
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
filenames = [
|
||||
'Laura/06_09-1.csv', # [0]
|
||||
'Laura/06_09-2.csv', # [1]
|
||||
'Elisabeth/06_10-1.csv', #[2]
|
||||
'Elisabeth/06_10-2.csv', #[3]
|
||||
# 'Elisabeth/06_12-1.csv',
|
||||
'Elisabeth/06_13-1.csv', #[4]
|
||||
'Elisabeth/06_13-2.csv', #[5]
|
||||
'Elisabeth/06_15-1.csv', #[6]
|
||||
'Elisabeth/06_15-2.csv', #[7]
|
||||
]
|
||||
|
||||
comparison = {
|
||||
'Laura Shot #1 vs #2': (0, 1), #[0]
|
||||
'Elisabeth 06/10/22 Shot #2 - #1': (2, 3), #[1]
|
||||
'Elisabeth 06/13/22 Shot #2 - #1': (4, 5), #[2]
|
||||
'Elisabeth 06/15/22 Shot #2 - #1': (6, 7), #[3]
|
||||
'comparison': {
|
||||
'Elisabeth Shots 06/13/22 - 06/10/22': (1, 2), #[0]
|
||||
'Elisabeth Shots 06/15/22 - 06/10/22': (1, 3), #[1]
|
||||
'Elisabeth Shots 06/15/22 - 06/13/22': (2, 3), #[2]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data = {}
|
||||
|
||||
curr_figure = 0
|
||||
|
||||
plt.figure(curr_figure)
|
||||
plt.subplot(2, 1, 1)
|
||||
# plt.title('Shotweight over time')
|
||||
# plt.xlabel('Time (s)')
|
||||
plt.ylabel('Weight (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.xlabel('Time (s)')
|
||||
plt.ylabel('Flow-rate (g/s)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
for filename in filenames:
|
||||
data[filename] = {
|
||||
'shot_name': '',
|
||||
'rows': [],
|
||||
'time': [],
|
||||
'weight': []
|
||||
}
|
||||
|
||||
with open(filename, newline='') as file:
|
||||
reader = csv.DictReader(file, delimiter=',')
|
||||
|
||||
for row in reader:
|
||||
data[filename]['rows'].append(row)
|
||||
|
||||
if row['information_type'] == 'meta':
|
||||
if row['metatype'] == 'Name':
|
||||
data[filename]['shot_name'] = row['metadata']
|
||||
elif row['information_type'] == 'moment':
|
||||
try:
|
||||
elapsed = float(row['elapsed'])
|
||||
weight = float(row['current_total_shot_weight'])
|
||||
|
||||
data[filename]['time'].append(elapsed)
|
||||
data[filename]['weight'].append(weight)
|
||||
except ValueError:
|
||||
continue
|
||||
#print("Not a float!")
|
||||
|
||||
time = data[filename]['time']
|
||||
weight = data[filename]['weight']
|
||||
|
||||
first_zero = list(x > 0 for x in weight).index(True) - 1
|
||||
zero_time = time[first_zero]
|
||||
|
||||
weight = weight[first_zero:]
|
||||
time = time[first_zero:]
|
||||
time = list(map(lambda t: t - zero_time, time))
|
||||
|
||||
data[filename]['time'] = time
|
||||
data[filename]['weight'] = weight
|
||||
|
||||
weight_savgol = savgol_filter(weight, 30, 3)
|
||||
|
||||
plt.plot(time, weight_savgol, label = data[filename]['shot_name'], linewidth=1)
|
||||
plt.scatter(time, weight, label = '', s=0.25)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
|
||||
dweight_dt = diff(weight)/diff(time)
|
||||
dweight_dt_savgol = savgol_filter(dweight_dt, 60, 3)
|
||||
|
||||
plt.plot(time[:-1], dweight_dt_savgol, label = data[filename]['shot_name'], linewidth=1)
|
||||
plt.scatter(time[1:-1], dweight_dt[1:], label = '', s=0.25)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
#print(filename, "\n", time, "\n", weight)
|
||||
|
||||
plt.legend(loc='best')
|
||||
|
||||
def comparison_plot(curr_figure, comparison_dict):
|
||||
curr_figure += 1
|
||||
plt.figure(curr_figure)
|
||||
|
||||
for key in comparison_dict:
|
||||
if key != 'comparison':
|
||||
item = comparison_dict[key]
|
||||
i0 = item[0]
|
||||
i1 = item[1]
|
||||
|
||||
fn0 = filenames[i0]
|
||||
fn1 = filenames[i1]
|
||||
|
||||
plt.xlabel('Time (s)')
|
||||
plt.ylabel('Weight difference (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
t0 = np.array(data[fn0]['time'])
|
||||
w0 = np.array(data[fn0]['weight'])
|
||||
|
||||
t1 = np.array(data[fn1]['time'])
|
||||
w1 = np.array(data[fn1]['weight'])
|
||||
|
||||
time_linspace = np.linspace(max(np.array(t0).min(), np.array(t1).min()), min(np.array(t0).max(), np.array(t1).max()), max(len(t0), len(t1)))
|
||||
|
||||
i0 = make_interp_spline(t0, w0, k=3)
|
||||
wi0 = i0(time_linspace)
|
||||
i1 = make_interp_spline(t1, w1, k=3)
|
||||
wi1 = i1(time_linspace)
|
||||
|
||||
dw = wi1 - wi0
|
||||
|
||||
dw_savgol = savgol_filter(dw, 30, 3)
|
||||
|
||||
plt.plot(time_linspace, dw_savgol, label = key, linewidth=1)
|
||||
plt.scatter(time_linspace, dw, label = '', s=0.25)
|
||||
|
||||
plt.legend(loc='best')
|
||||
else:
|
||||
curr_figure = comparison_plot(curr_figure, comparison_dict['comparison'])
|
||||
return curr_figure
|
||||
|
||||
curr_figure = comparison_plot(curr_figure, comparison)
|
||||
|
||||
|
||||
plt.show()
|
||||
import csv
|
||||
|
||||
import numpy as np
|
||||
from numpy import diff
|
||||
|
||||
from scipy.interpolate import make_interp_spline
|
||||
from scipy.signal import savgol_filter
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
filenames = [
|
||||
'Laura/06_09-1.csv', # [0]
|
||||
'Laura/06_09-2.csv', # [1]
|
||||
'Elisabeth/06_10-1.csv', #[2]
|
||||
'Elisabeth/06_10-2.csv', #[3]
|
||||
# 'Elisabeth/06_12-1.csv',
|
||||
'Elisabeth/06_13-1.csv', #[4]
|
||||
'Elisabeth/06_13-2.csv', #[5]
|
||||
'Elisabeth/06_15-1.csv', #[6]
|
||||
'Elisabeth/06_15-2.csv', #[7]
|
||||
]
|
||||
|
||||
comparison = {
|
||||
'Laura Shot #1 vs #2': (0, 1), #[0]
|
||||
'Elisabeth 06/10/22 Shot #2 - #1': (2, 3), #[1]
|
||||
'Elisabeth 06/13/22 Shot #2 - #1': (4, 5), #[2]
|
||||
'Elisabeth 06/15/22 Shot #2 - #1': (6, 7), #[3]
|
||||
'comparison': {
|
||||
'Elisabeth Shots 06/13/22 - 06/10/22': (1, 2), #[0]
|
||||
'Elisabeth Shots 06/15/22 - 06/10/22': (1, 3), #[1]
|
||||
'Elisabeth Shots 06/15/22 - 06/13/22': (2, 3), #[2]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data = {}
|
||||
|
||||
curr_figure = 0
|
||||
|
||||
plt.figure(curr_figure)
|
||||
plt.subplot(2, 1, 1)
|
||||
# plt.title('Shotweight over time')
|
||||
# plt.xlabel('Time (s)')
|
||||
plt.ylabel('Weight (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
# plt.title('Flow-rate over time')
|
||||
plt.xlabel('Time (s)')
|
||||
plt.ylabel('Flow-rate (g/s)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
for filename in filenames:
|
||||
data[filename] = {
|
||||
'shot_name': '',
|
||||
'rows': [],
|
||||
'time': [],
|
||||
'weight': []
|
||||
}
|
||||
|
||||
with open(filename, newline='') as file:
|
||||
reader = csv.DictReader(file, delimiter=',')
|
||||
|
||||
for row in reader:
|
||||
data[filename]['rows'].append(row)
|
||||
|
||||
if row['information_type'] == 'meta':
|
||||
if row['metatype'] == 'Name':
|
||||
data[filename]['shot_name'] = row['metadata']
|
||||
elif row['information_type'] == 'moment':
|
||||
try:
|
||||
elapsed = float(row['elapsed'])
|
||||
weight = float(row['current_total_shot_weight'])
|
||||
|
||||
data[filename]['time'].append(elapsed)
|
||||
data[filename]['weight'].append(weight)
|
||||
except ValueError:
|
||||
continue
|
||||
#print("Not a float!")
|
||||
|
||||
time = data[filename]['time']
|
||||
weight = data[filename]['weight']
|
||||
|
||||
first_zero = list(x > 0 for x in weight).index(True) - 1
|
||||
zero_time = time[first_zero]
|
||||
|
||||
weight = weight[first_zero:]
|
||||
time = time[first_zero:]
|
||||
time = list(map(lambda t: t - zero_time, time))
|
||||
|
||||
data[filename]['time'] = time
|
||||
data[filename]['weight'] = weight
|
||||
|
||||
weight_savgol = savgol_filter(weight, 30, 3)
|
||||
|
||||
plt.plot(time, weight_savgol, label = data[filename]['shot_name'], linewidth=1)
|
||||
plt.scatter(time, weight, label = '', s=0.25)
|
||||
|
||||
plt.subplot(2, 1, 2)
|
||||
|
||||
dweight_dt = diff(weight)/diff(time)
|
||||
dweight_dt_savgol = savgol_filter(dweight_dt, 60, 3)
|
||||
|
||||
plt.plot(time[:-1], dweight_dt_savgol, label = data[filename]['shot_name'], linewidth=1)
|
||||
plt.scatter(time[1:-1], dweight_dt[1:], label = '', s=0.25)
|
||||
|
||||
plt.subplot(2, 1, 1)
|
||||
|
||||
#print(filename, "\n", time, "\n", weight)
|
||||
|
||||
plt.legend(loc='best')
|
||||
|
||||
def comparison_plot(curr_figure, comparison_dict):
|
||||
curr_figure += 1
|
||||
plt.figure(curr_figure)
|
||||
|
||||
for key in comparison_dict:
|
||||
if key != 'comparison':
|
||||
item = comparison_dict[key]
|
||||
i0 = item[0]
|
||||
i1 = item[1]
|
||||
|
||||
fn0 = filenames[i0]
|
||||
fn1 = filenames[i1]
|
||||
|
||||
plt.xlabel('Time (s)')
|
||||
plt.ylabel('Weight difference (g)')
|
||||
plt.grid(visible=True, which='both', axis='both', linewidth=0.5)
|
||||
|
||||
t0 = np.array(data[fn0]['time'])
|
||||
w0 = np.array(data[fn0]['weight'])
|
||||
|
||||
t1 = np.array(data[fn1]['time'])
|
||||
w1 = np.array(data[fn1]['weight'])
|
||||
|
||||
time_linspace = np.linspace(max(np.array(t0).min(), np.array(t1).min()), min(np.array(t0).max(), np.array(t1).max()), max(len(t0), len(t1)))
|
||||
|
||||
i0 = make_interp_spline(t0, w0, k=3)
|
||||
wi0 = i0(time_linspace)
|
||||
i1 = make_interp_spline(t1, w1, k=3)
|
||||
wi1 = i1(time_linspace)
|
||||
|
||||
dw = wi1 - wi0
|
||||
|
||||
dw_savgol = savgol_filter(dw, 30, 3)
|
||||
|
||||
plt.plot(time_linspace, dw_savgol, label = key, linewidth=1)
|
||||
plt.scatter(time_linspace, dw, label = '', s=0.25)
|
||||
|
||||
plt.legend(loc='best')
|
||||
else:
|
||||
curr_figure = comparison_plot(curr_figure, comparison_dict['comparison'])
|
||||
return curr_figure
|
||||
|
||||
curr_figure = comparison_plot(curr_figure, comparison)
|
||||
|
||||
|
||||
plt.show()
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
shot_dir = "shots"
|
||||
data_dir = "beanconqueror"
|
||||
brew_dir = "beanconqueror/brews"
|
||||
output_dir = "images"
|
||||
main_json = "beanconqueror/Beanconqueror.json"
|
||||
main_json = "Beanconqueror.json"
|
||||
|
||||
width = 1600
|
||||
height = 900
|
||||
|
|
|
@ -28,6 +28,7 @@ pub struct Config {
|
|||
|
||||
pub shot_dir: String,
|
||||
pub brew_dir: String,
|
||||
pub data_dir: String,
|
||||
pub output_dir: String,
|
||||
pub main_json: String,
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ pub struct Mill {
|
|||
pub struct Preparation {
|
||||
pub name: String,
|
||||
pub config: Config,
|
||||
pub tools: Tools,
|
||||
pub tools: Vec<Tools>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
15
src/main.rs
15
src/main.rs
|
@ -6,7 +6,8 @@ mod plot;
|
|||
mod sheets;
|
||||
mod time;
|
||||
|
||||
use crate::flow_profile::FlowProfile;
|
||||
use plot::database_plots;
|
||||
|
||||
use crate::plot::generate_plots;
|
||||
|
||||
extern crate console_error_panic_hook;
|
||||
|
@ -16,17 +17,9 @@ use std::panic;
|
|||
fn main() {
|
||||
panic::set_hook(Box::new(console_error_panic_hook::hook));
|
||||
|
||||
let mut brew = FlowProfile::from_file("brews/test.json", None);
|
||||
// generate_plots();
|
||||
|
||||
println!("Brew: {:?}\n", &brew);
|
||||
println!("process_json(): {:?}\n", &brew.process_json());
|
||||
brew.preprocess_json_mut();
|
||||
println!("preprocess_json_mut(): {:?}\n", &brew);
|
||||
|
||||
brew = brew.preprocess_json();
|
||||
println!("preprocess_json: {:?}\n", &brew);
|
||||
|
||||
generate_plots();
|
||||
database_plots();
|
||||
|
||||
// Counter::run(Settings::default())
|
||||
}
|
||||
|
|
127
src/plot.rs
127
src/plot.rs
|
@ -1,7 +1,14 @@
|
|||
use crate::config::Config;
|
||||
use crate::database::{Database};
|
||||
use crate::database::Database;
|
||||
use crate::flow_profile::FlowProfile;
|
||||
use crate::sheets::load_data;
|
||||
use crate::time::{unix_to_human_date, unix_to_human_date_time, unix_to_machine_date};
|
||||
|
||||
use dialoguer::{theme::ColorfulTheme, MultiSelect};
|
||||
|
||||
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
|
||||
|
||||
use notify_rust::Notification;
|
||||
|
||||
use plotly::{
|
||||
common::{Mode, Title},
|
||||
|
@ -19,7 +26,7 @@ pub fn generate_plots() -> Vec<(String, Plot)> {
|
|||
for chart in config.charts {
|
||||
// println!("Chart: {}\n", chart.1.title);
|
||||
|
||||
let filename = format!("{}/{}.html", config.output_dir, &chart.1.title);
|
||||
let filename = format!("{}/{}.html", &config.output_dir, &chart.1.title);
|
||||
let mut plot = Plot::new();
|
||||
|
||||
let _shot_count = chart.1.shots.len();
|
||||
|
@ -77,7 +84,121 @@ pub fn generate_plots() -> Vec<(String, Plot)> {
|
|||
}
|
||||
|
||||
pub fn database_plots() -> Vec<(String, Plot)> {
|
||||
let config_file = fs::read_to_string("config.toml").expect("Can't read config.toml");
|
||||
let config: Config = toml::from_str(&config_file).expect("Can't deserialize config.toml");
|
||||
|
||||
let mut result: Vec<(String, Plot)> = Vec::with_capacity(config.charts.len());
|
||||
|
||||
vec![]
|
||||
let database = Database::from_file(&format!("{}/{}", &config.data_dir, &config.main_json));
|
||||
|
||||
let bean_names: Vec<String> = database
|
||||
.beans
|
||||
.iter()
|
||||
.map(|bean| {
|
||||
format!(
|
||||
"{} from {}",
|
||||
bean.name.clone(),
|
||||
unix_to_human_date(bean.config.unix_timestamp).clone()
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let selection = MultiSelect::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt("Select the Beans you want to automatically generate charts for:")
|
||||
.items(&bean_names[..])
|
||||
.interact()
|
||||
.expect("You need to select at least one bean to proceed");
|
||||
|
||||
if !selection.is_empty() {
|
||||
let multi_progress = MultiProgress::new();
|
||||
multi_progress.println("Generating brew charts.\nCheck the specified output directory and open the corresponding .html files to view.").unwrap();
|
||||
|
||||
let progress_style = ProgressStyle::with_template(
|
||||
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
|
||||
)
|
||||
.expect("Can't generate progress bar style");
|
||||
let progress_beans = multi_progress.add(
|
||||
ProgressBar::new(selection.len() as u64)
|
||||
.with_style(progress_style.clone())
|
||||
.with_message("Beans"),
|
||||
);
|
||||
let mut progress_brews: ProgressBar = ProgressBar::new(0);
|
||||
|
||||
for single_selection in selection {
|
||||
if let Some(bean) = &database.beans.get(single_selection) {
|
||||
let bean_timestamp = bean.config.unix_timestamp.clone();
|
||||
|
||||
let title = format!("{} from {}", &bean.name, unix_to_human_date(bean_timestamp));
|
||||
let filename = format!(
|
||||
"{}/{}_from_{}.html",
|
||||
&config.output_dir,
|
||||
&bean.name,
|
||||
unix_to_machine_date(bean_timestamp)
|
||||
)
|
||||
.replace(" ", "_");
|
||||
let mut plot = Plot::new();
|
||||
|
||||
let brews = &database.brews_for_bean(&bean);
|
||||
|
||||
progress_brews = multi_progress.insert_after(
|
||||
&progress_beans,
|
||||
ProgressBar::new(brews.len() as u64)
|
||||
.with_style(progress_style.clone())
|
||||
.with_message("Brews"),
|
||||
);
|
||||
|
||||
for brew in brews {
|
||||
if let Some(flow_profile) = &brew.flow_profile {
|
||||
if !&flow_profile.is_empty() {
|
||||
let brew_title =
|
||||
unix_to_human_date_time(brew.config.unix_timestamp.clone());
|
||||
|
||||
let brew = FlowProfile::from_file(
|
||||
&format!("{}/{}", &config.data_dir, &flow_profile),
|
||||
None,
|
||||
)
|
||||
.preprocess_json();
|
||||
|
||||
let (x, y): (Vec<_>, Vec<_>) = brew
|
||||
.data_collection
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"No data_collection present for flow_profile: {}",
|
||||
&flow_profile
|
||||
)
|
||||
})
|
||||
.weight
|
||||
.iter()
|
||||
.cloned()
|
||||
.unzip();
|
||||
let trace = Scatter::new(x, y).name(&brew_title).mode(Mode::Lines);
|
||||
plot.add_trace(trace);
|
||||
|
||||
progress_brews.inc(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let layout = Layout::new().title(Title::new(&title));
|
||||
plot.set_layout(layout);
|
||||
|
||||
plot.use_local_plotly();
|
||||
plot.write_html(filename);
|
||||
|
||||
result.push((title.to_string(), plot));
|
||||
}
|
||||
|
||||
progress_beans.inc(1);
|
||||
multi_progress.remove(&progress_brews);
|
||||
}
|
||||
}
|
||||
|
||||
Notification::new()
|
||||
.summary("RustyBeans finished")
|
||||
.body("Successfully generated all selected bean charts automatically, according to the database.")
|
||||
.timeout(5000)
|
||||
.show()
|
||||
.expect("Couldn't show desktop notification");
|
||||
|
||||
result
|
||||
}
|
||||
|
|
24
src/time.rs
24
src/time.rs
|
@ -23,3 +23,27 @@ pub fn unix_to_naivetime(unix_timestamp: i64) -> Option<NaiveTime> {
|
|||
pub fn is_same_day(time_1: NaiveTime, time_2: NaiveTime) -> bool {
|
||||
time_1.format("%Y:%m:%d").to_string() == time_2.format("%Y:%m:%d").to_string()
|
||||
}
|
||||
|
||||
pub fn unix_to_human_date_time(unix_timestamp: i64) -> String {
|
||||
if let Some(date_time) = NaiveDateTime::from_timestamp_opt(unix_timestamp, 0) {
|
||||
date_time.format("%b %d, %Y %I:%M %P").to_string()
|
||||
} else {
|
||||
"Unknown date & time".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unix_to_human_date(unix_timestamp: i64) -> String {
|
||||
if let Some(date_time) = NaiveDateTime::from_timestamp_opt(unix_timestamp, 0) {
|
||||
date_time.format("%b %d, %Y").to_string()
|
||||
} else {
|
||||
"Unknown date".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unix_to_machine_date(unix_timestamp: i64) -> String {
|
||||
if let Some(date_time) = NaiveDateTime::from_timestamp_opt(unix_timestamp, 0) {
|
||||
date_time.format("%F").to_string()
|
||||
} else {
|
||||
"unknown".to_string()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue