egui wasm32 working, except file loading

This commit is contained in:
David Holland 2023-09-14 22:26:01 +02:00
parent 9124e147f2
commit e6f47328a0
84 changed files with 511 additions and 13817 deletions

2
.gitignore vendored
View File

@ -7,7 +7,9 @@
!/config.toml
!/index.html
!/rust-toolchain.toml
!/Trunk.toml
!/assets/
!/beanconqueror/
!/shots/
!/src/

1814
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -18,16 +18,16 @@ toml = "0.5.9"
rfd = "0.10.0"
egui = "0.22.0"
eframe = "0.22.0"
log = "0.4.20"
async-std = "1.12.0"
zip = "0.6.6"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tracing-subscriber = "0.3"
rfd = "0.10.0"
env_logger = "0.10"
# web:
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.6"
tracing-wasm = "0.2"
wasm-bindgen-futures = "0.4"

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

View File

@ -1,161 +0,0 @@
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()

View File

@ -1,75 +0,0 @@
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()

View File

@ -1,160 +0,0 @@
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
Trunk.toml Normal file
View File

@ -0,0 +1 @@
[build]

BIN
assets/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
assets/icon-1024.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

BIN
assets/icon-256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

28
assets/manifest.json Normal file
View File

@ -0,0 +1,28 @@
{
"name": "egui Template PWA",
"short_name": "egui-template-pwa",
"icons": [
{
"src": "./icon-256.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "./maskable_icon_x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "./icon-1024.png",
"sizes": "1024x1024",
"type": "image/png"
}
],
"lang": "en-US",
"id": "/index.html",
"start_url": "./index.html",
"display": "standalone",
"background_color": "white",
"theme_color": "white"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

25
assets/sw.js Normal file
View File

@ -0,0 +1,25 @@
var cacheName = 'egui-template-pwa';
var filesToCache = [
'./',
'./index.html',
'./eframe_template.js',
'./eframe_template_bg.wasm',
];
/* Start the service worker and cache all of the app's content */
self.addEventListener('install', function (e) {
e.waitUntil(
caches.open(cacheName).then(function (cache) {
return cache.addAll(filesToCache);
})
);
});
/* Serve cached content when offline */
self.addEventListener('fetch', function (e) {
e.respondWith(
caches.match(e.request).then(function (response) {
return response || fetch(e.request);
})
);
});

View File

@ -7,7 +7,7 @@
<head>
<!-- change this to your project name -->
<title>RustyBeans</title>
<title>eframe template</title>
<!-- config for our rust wasm binary. go to https://trunkrs.dev/assets/#rust for more customization -->
<link data-trunk rel="rust" data-wasm-opt="2" />
@ -24,6 +24,8 @@
<link data-trunk rel="copy-file" href="assets/icon_ios_touch_192.png" />
<link data-trunk rel="copy-file" href="assets/maskable_icon_x512.png" />
<link data-trunk rel="copy-dir" href="beanconqueror" data-target-path="beanconqueror" />
<link rel="manifest" href="manifest.json">
<link rel="apple-touch-icon" href="icon_ios_touch_192.png">
@ -39,14 +41,14 @@
body {
/* Light mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #f8f8f2;
background: #909090;
}
@media (prefers-color-scheme: dark) {
body {
/* Dark mode background color for what is not covered by the egui canvas,
or where the egui canvas is translucent. */
background: #282a36;
background: #404040;
}
}
@ -119,20 +121,22 @@
</head>
<body>
<!-- The WASM code will resize the canvas dynamically -->
<!-- the id is hardcoded in main.rs . so, make sure both match. -->
<canvas id="RustyBeans"></canvas>
<!-- The WASM code will resize the canvas dynamically -->
<!-- the id is hardcoded in main.rs . so, make sure both match. -->
<canvas id="RustyBeans"></canvas>
<!--Register Service Worker. this will cache the wasm / js scripts for offline use (for PWA functionality). -->
<!-- Force refresh (Ctrl + F5) to load the latest files instead of cached files -->
<script>
// We disable caching during development so that we always view the latest version.
if ('serviceWorker' in navigator && window.location.hash !== "#dev") {
window.addEventListener('load', function () {
navigator.serviceWorker.register('sw.js');
});
}
</script>
<!--Register Service Worker. this will cache the wasm / js scripts for offline use (for PWA functionality). -->
<!-- Force refresh (Ctrl + F5) to load the latest files instead of cached files -->
<script>
// We disable caching during development so that we always view the latest version.
if ('serviceWorker' in navigator && window.location.hash !== "#dev") {
window.addEventListener('load', function () {
navigator.serviceWorker.register('sw.js');
});
}
</script>
</body>
</html>
</html>
<!-- Powered by egui: https://github.com/emilk/egui/ -->

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

View File

@ -1,161 +0,0 @@
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()

View File

@ -1,75 +0,0 @@
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()

View File

@ -1,160 +0,0 @@
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()

View File

@ -55,6 +55,11 @@ impl Config {
toml::from_str(&config_file).expect("Can't deserialize config.toml")
}
pub fn from_raw(bytes: &Vec<u8>) -> Self {
let config_file = core::str::from_utf8(&bytes).expect("Not valid UTF-8");
toml::from_str(&config_file).expect("Can't deserialize config.toml")
}
pub fn from_default() -> Self {
Self::from_file("config.toml")
}

View File

@ -71,7 +71,7 @@ impl Database {
}
pub fn from_config(config: &config::Config) -> Self {
Database::from_file(&format!("{}/{}", &config.data_dir, &config.main_json))
Database::from_file(&format!("./{}/{}", &config.data_dir, &config.main_json))
}
pub fn bean_names(&self) -> Vec<String> {

View File

@ -12,17 +12,9 @@ use std::panic;
use eframe::egui;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::prelude::*;
extern crate console_error_panic_hook;
// use crate::plot::database_plot_selected_tui;
// use crate::plot::generate_plots;
#[cfg(not(target_arch = "wasm32"))]
fn main() -> Result<(), eframe::Error> {
panic::set_hook(Box::new(console_error_panic_hook::hook));
fn main() -> eframe::Result<()> {
env_logger::init();
let options = eframe::NativeOptions {
drag_and_drop_support: true,
@ -39,19 +31,18 @@ fn main() -> Result<(), eframe::Error> {
#[cfg(target_arch = "wasm32")]
fn main() {
console_error_panic_hook::set_once();
tracing_wasm::set_as_global_default();
eframe::WebLogger::init(log::LevelFilter::Debug).ok();
let options = eframe::WebOptions::default();
wasm_bindgen_futures::spawn_local(async {
eframe::start_web(
"RustyBeans",
options,
Box::new(|cc| Box::new(Ui::default())),
)
.await
.expect("Failed to start eframe");
eframe::WebRunner::new()
.start(
"RustyBeans",
options,
Box::new(|cc| Box::new(Ui::default())),
)
.await
.expect("Failed to start eframe");
});
}

View File

@ -19,6 +19,7 @@ pub struct LoadingProgress {
pub current: usize,
pub total: usize,
pub percentage: f32,
pub finished: bool,
}
pub fn plot_points_to_owned(plot_points: &RawPlotPoints) -> PlotPoints {
@ -59,12 +60,17 @@ pub fn database_plot_entries(
let mut plot_entries: HashMap<String, PlotEntry> = HashMap::new();
let step_size = 1.0 / brews.len() as f32;
if let Some(progress) = &progress {
let mut progress_lock = progress.lock().unwrap();
(*progress_lock).total = brews.len();
(*progress_lock).finished = false;
}
for (i, brew) in brews.iter().enumerate() {
if let Some(progress) = &progress {
let mut progress_lock = progress.lock().unwrap();
(*progress_lock).curr_name = brew.date_time_with_bean(&database);
(*progress_lock).current = i + 1;
(*progress_lock).total = brews.len();
(*progress_lock).percentage += step_size;
}
@ -73,5 +79,10 @@ pub fn database_plot_entries(
}
}
if let Some(progress) = &progress {
let mut progress_lock = progress.lock().unwrap();
(*progress_lock).finished = true;
}
plot_entries
}

137
src/ui.rs
View File

@ -3,7 +3,7 @@
use eframe::egui;
use egui::{plot::{Legend, Line, Plot}, Align, Layout, ProgressBar, Modifiers};
use rfd::FileDialog;
use rfd::{FileHandle, AsyncFileDialog};
use crate::{
config::Config,
@ -20,6 +20,8 @@ use std::{
sync::{Arc, Mutex},
};
use async_std::task;
#[derive(Default, Debug)]
struct LoadingData {
config: Config,
@ -36,9 +38,9 @@ pub struct Ui {
side_panel_expanded: bool,
loading_progress: Arc<Mutex<LoadingProgress>>,
loader_thread: Option<JoinHandle<()>>,
loading_data: Arc<Mutex<Option<LoadingData>>>,
data_loaded: bool,
loading_file: Arc<Mutex<Option<Vec<u8>>>>,
data_transfered: bool,
config: Config,
database: Database,
@ -49,8 +51,6 @@ pub struct Ui {
select_all: bool,
clear_all: bool,
picked_path: Option<String>,
plot_entries: HashMap<String, PlotEntry>,
continuous_mode: bool,
@ -76,15 +76,11 @@ impl Ui {
}
pub fn reload(&mut self, _ctx: &egui::Context) {
if let Some(loader_thread) = &self.loader_thread {
if loader_thread.is_finished() {
self.data_loaded = false;
self.loader_thread = None;
if self.data_transfered {
self.data_transfered = false;
let loading_progress_arc = self.loading_progress.clone();
let mut loading_progress_lock = loading_progress_arc.lock().unwrap();
*loading_progress_lock = LoadingProgress::default();
}
let mut loading_progress_lock = self.loading_progress.lock().unwrap();
*loading_progress_lock = LoadingProgress::default();
}
}
}
@ -109,15 +105,15 @@ impl eframe::App for Ui {
self.reload(ctx);
}
if reload_button.hovered() {
if let Some(loader_thread) = &self.loader_thread {
if !loader_thread.is_finished() {
egui::show_tooltip(ctx, egui::Id::new("reload_tooltip"), |ui| {
ui.label("Loading is still in progress.\nTo reload, please wait until previous loading has finished!");
});
}
}
}
// if reload_button.hovered() {
// if let Some(loader_thread) = &self.loader_thread {
// if !loader_thread.is_finished() {
// egui::show_tooltip(ctx, egui::Id::new("reload_tooltip"), |ui| {
// ui.label("Loading is still in progress.\nTo reload, please wait until previous loading has finished!");
// });
// }
// }
// }
ui.with_layout(Layout::right_to_left(Align::Min), |ui| {
egui::widgets::global_dark_light_mode_buttons(ui);
@ -131,8 +127,7 @@ impl eframe::App for Ui {
egui::CentralPanel::default().show(ctx, |ui| {
ui.centered_and_justified(|ui| {
if self.show_loading_screen {
let loading_progress_arc = self.loading_progress.clone();
let loading_progress_lock = loading_progress_arc.lock().unwrap();
let loading_progress_lock = self.loading_progress.lock().unwrap();
ui.add(
ProgressBar::new(loading_progress_lock.percentage.to_owned()).text(
@ -145,15 +140,14 @@ impl eframe::App for Ui {
),
);
if let Some(loader_thread) = &self.loader_thread {
if loader_thread.is_finished() {
self.continuous_mode = false;
self.modal = false;
self.show_loading_screen = false;
}
if loading_progress_lock.finished {
self.continuous_mode = false;
self.modal = false;
self.show_loading_screen = false;
}
}
#[cfg(not(target_arch = "wasm32"))]
if self.show_confirmation_dialog {
// Show confirmation dialog:
ui.separator();
@ -183,7 +177,7 @@ impl eframe::App for Ui {
ui.horizontal_centered(|ui| {
ui.vertical(|ui| {
if self.data_loaded {
if self.data_transfered {
ui.heading("Beans");
egui::ScrollArea::vertical()
@ -211,7 +205,7 @@ impl eframe::App for Ui {
});
ui.vertical(|ui| {
if self.data_loaded {
if self.data_transfered {
if let Some(bean) =
&self.database.bean_for_uuid(&self.selected_bean)
{
@ -249,7 +243,7 @@ impl eframe::App for Ui {
ui.horizontal_centered(|ui| {
ui.vertical(|ui| {
if self.data_loaded {
if self.data_transfered {
ui.heading("Selected Brews");
egui::ScrollArea::vertical()
@ -320,23 +314,32 @@ impl eframe::App for Ui {
ui.with_layout(
Layout::top_down(Align::Center).with_main_align(Align::Center),
|ui| {
if let Some(picked_path) = &self.picked_path {
let thread_handle = self.loader_thread.get_or_insert_with(|| {
let file_loaded: bool;
{
file_loaded = self.loading_file.lock().unwrap().is_some();
}
if file_loaded {
let loading_finished: bool;
{
loading_finished = self.loading_progress.lock().unwrap().finished;
}
if !loading_finished {
self.continuous_mode = true;
self.modal = true;
self.show_loading_screen = true;
let loading_file_arc = self.loading_file.clone();
let loading_data_arc = self.loading_data.clone();
let loading_progress_arc = self.loading_progress.clone();
let picked_path_owned = picked_path.to_owned();
let ctx_clone = ctx.clone();
thread::spawn(move || {
let data_loader = async move {
let ctx = ctx_clone;
let mut loading_data = LoadingData::default();
loading_data.config = Config::from_file(&picked_path_owned);
let loading_file_lock = loading_file_arc.lock().unwrap();
loading_data.config = Config::from_raw(loading_file_lock.as_ref().expect("No file loaded"));
loading_data.database =
Database::from_config(&loading_data.config);
@ -374,11 +377,15 @@ impl eframe::App for Ui {
*loading_data_lock = Some(loading_data);
ctx.request_repaint();
})
});
};
if thread_handle.is_finished() {
if !self.data_loaded {
#[cfg(not(target_arch = "wasm32"))]
task::spawn(data_loader);
#[cfg(target_arch = "wasm32")]
wasm_bindgen_futures::spawn_local(data_loader);
} else {
if !self.data_transfered {
self.side_panel_expanded = true;
// println!("loading_data: {:?}", &self.loading_data);
@ -393,7 +400,7 @@ impl eframe::App for Ui {
self.selected_bean = loading_data.selected_bean;
self.plot_entries = loading_data.plot_entries;
self.data_loaded = true;
self.data_transfered = true;
} else {
Plot::new("Combined Chart of selected brews")
.legend(Legend::default())
@ -416,27 +423,33 @@ impl eframe::App for Ui {
}
}
} else {
ui.label("Select the config.toml to start");
ui.label("Select the config file (.toml) to start");
#[cfg(not(target_arch = "wasm32"))]
if ui.button("Open file").clicked() {
if let Some(path) = FileDialog::new()
.add_filter("toml", &["toml"])
.set_directory(
match &env::current_dir() {
Ok(path) => path.to_str(),
Err(_) => None,
}
.unwrap_or_default(),
)
.pick_file()
{
self.picked_path = Some(path.display().to_string());
}
}
if ui.button("Load file").clicked() {
let loading_file_arc = self.loading_file.clone();
if ui.button("Open default config.toml").clicked() {
self.picked_path = Some(String::from("config.toml"));
let file_dialog = async move {
let file = AsyncFileDialog::new()
.add_filter("toml", &["toml"])
.set_directory(
match &env::current_dir() {
Ok(path) => path.to_str(),
Err(_) => None,
}.unwrap_or_default()
)
.pick_file().await;
let data = file.unwrap().read().await;
let mut loading_file_lock = loading_file_arc.lock().unwrap();
*loading_file_lock = Some(data);
};
#[cfg(not(target_arch = "wasm32"))]
task::spawn(file_dialog);
#[cfg(target_arch = "wasm32")]
wasm_bindgen_futures::spawn_local(file_dialog);
}
}
},