add temp range and heat range

This commit is contained in:
2026-04-26 19:07:02 +02:00
parent 5543e2fe1d
commit 1b46f2cf6c

176
app.py
View File

@@ -3,6 +3,7 @@
""" """
import os import os
import numpy as np import numpy as np
import time
import datetime import datetime
try: try:
from nicegui import app, ui, events, Client from nicegui import app, ui, events, Client
@@ -30,11 +31,15 @@ pio.templates["plotly_light"].layout['yaxis']['zerolinecolor'] = 'lightgray'
ELM = { ELM = {
'name': 'tempplot', 'name': 'tempplot',
'filename': './data/20260420213656.txt', 'filename': './data/20260420213656.txt',
'label_file_fmt': 'file: {filename}', 'label_file_fmt': 'File: {filename}',
#'label_data_len_fmt': 'data points (rendered): {num}', 'label_data_len_fmt': 'Data points: {num:,} (rendered) / {numa:,} (total)',
'label_data_len_fmt': 'data points: {num} (rendered), {numa} (total)', 'label_data_temp_fmt': 'Temperature = [{min:.1f}, {max:.1f}] K',
'label_data_heat_fmt': 'Heater = [{min:.1f}, {max:.1f}] %',
'plotly_light': 'plotly_light', 'plotly_light': 'plotly_light',
'plotly_dark': 'plotly_dark', 'plotly_dark': 'plotly_dark',
'update_last': time.time(),
'update_timeout': 1,
'label_update_last_fmt': 'Last refresh: {last}',
} }
def main_cli(): def main_cli():
@@ -84,10 +89,11 @@ async def pick_file() -> None:
if result: if result:
filename = result[-1] filename = result[-1]
ELM['filename'] = filename ELM['filename'] = filename
# update_data() # see timer below # see timer below, but still here active b/c the time might be inactive
ui.timer(0, lambda: update_data(), once=True)
ELM['label_file'].set_text(ELM['label_file_fmt'].format(filename=os.path.basename(filename))) ELM['label_file'].set_text(ELM['label_file_fmt'].format(filename=os.path.basename(filename)))
async def get_data(filename=ELM['filename']): def get_data(filename=ELM['filename']):
data = np.genfromtxt(fname=filename, skip_header=1) data = np.genfromtxt(fname=filename, skip_header=1)
if len(data) > 0 and len(data[0]) > 6: if len(data) > 0 and len(data[0]) > 6:
@@ -102,42 +108,82 @@ async def get_data(filename=ELM['filename']):
) )
return data return data
async def update_data(): def update_data():
filename=ELM['filename'] if not app.storage.user['timer'] or time.time() - ELM['update_last'] > ELM['update_timeout']:
data_all = await get_data(filename) ELM['update_busy'] = True
data = data_all filename=ELM['filename']
# time_range = ELM['number_time_range'].value data_all = get_data(filename)
time_range = app.storage.user['time_range'] data = data_all
if time_range is not None and time_range > 0:
# delta = datetime.datetime.now() - data['time']
delta = data['time'][-1] - data['time']
data = data[np.where(delta <= datetime.timedelta(hours=time_range))]
print(filename, data_all.shape, data.shape)
ELM['label_data_len'].set_text(ELM['label_data_len_fmt'].format(num=len(data), numa=len(data_all)))
ELM['fig'].data = []
ELM['plot'].visible = False
ELM['plot'].update()
ELM['fig'].add_trace(pgo.Scatter(**np2pgo(data['time'], data['ts'], 'Setp'))) # time_range = ELM['number_time_range'].value
ELM['fig'].add_trace(pgo.Scatter(**np2pgo(data['time'], data['ta'], 'Temp A'))) time_range = app.storage.user['time_range']
ELM['fig'].add_trace(pgo.Scatter(**np2pgo(data['time'], data['tb'], 'Temp B'))) if time_range is not None and time_range > 0:
if len(data) > 0 and len(data[0]) > 6: # delta = datetime.datetime.now() - data['time']
ELM['fig'].add_trace(pgo.Scatter(**np2pgo(data['time'], data['tc'], 'Temp C'))) delta = data['time'][-1] - data['time']
ELM['fig'].add_trace(pgo.Scatter(**np2pgo(data['time'], data['td'], 'Temp D'))) data = data[np.where(delta <= datetime.timedelta(hours=time_range))]
print(datetime.datetime.now(), filename, data_all.shape, data.shape)
ELM['label_data_len'].set_text(ELM['label_data_len_fmt'].format(
num=len(data), numa=len(data_all)))
if len(data) > 0:
if len(data[0]) > 6:
ELM['label_data_temp'].set_text(ELM['label_data_temp_fmt'].format(
min=np.min([data['ts'], data['ta'], data['tb'], data['tc'], data['td']]),
max=np.max([data['ts'], data['ta'], data['tb'], data['tc'], data['td']])))
else:
ELM['label_data_temp'].set_text(ELM['label_data_temp_fmt'].format(
min=np.min([data['ts'], data['ta'], data['tb']]),
max=np.max([data['ts'], data['ta'], data['tb']])))
ELM['label_data_heat'].set_text(ELM['label_data_heat_fmt'].format(
min=np.min(data['hp']), max=np.max(data['hp'])))
ELM['fig'].add_trace(pgo.Scatter(**np2pgo(data['time'], data['hp'], 'Heat')), ELM['fig'].data = []
row=2, col=1) ELM['plot'].visible = False
ELM['plot'].update()
ELM['plot'].visible = True # mode='lines+markers' too heavy
ELM['plot'].update() ELM['fig'].add_trace(pgo.Scatter(
**np2pgo(data['time'], data['ts'], 'Setp'), mode='lines', legendgroup=None))
ELM['fig'].add_trace(pgo.Scatter(
**np2pgo(data['time'], data['ta'], 'Temp A'), mode='lines', legendgroup=None))
ELM['fig'].add_trace(pgo.Scatter(
**np2pgo(data['time'], data['tb'], 'Temp B'), mode='lines', legendgroup=None))
if len(data) > 0 and len(data[0]) > 6:
ELM['fig'].add_trace(pgo.Scatter(
**np2pgo(data['time'], data['tc'], 'Temp C'), mode='lines', legendgroup=None))
ELM['fig'].add_trace(pgo.Scatter(
**np2pgo(data['time'], data['td'], 'Temp D'), mode='lines', legendgroup=None))
ELM['fig'].add_trace(pgo.Scatter(
**np2pgo(data['time'], data['hp'], 'Heat'), mode='lines',
legendgroup=None), row=2, col=1)
ELM['plot'].visible = True
ELM['plot'].update()
ELM['update_last'] = time.time()
ELM['label_update_last'].set_text(
ELM['label_update_last_fmt'].format(
last=datetime.datetime.fromtimestamp(
ELM['update_last']).strftime("%Y-%m-%dT%H:%M:%S.%f")))
def update_fig():
ELM['fig'].update_yaxes(
row=1, col=1, range=[ELM['number_temp_min'].value, ELM['number_temp_max'].value],
rangemode="nonnegative")
ELM['fig'].update_yaxes(
row=2, col=1, range=[ELM['number_heat_min'].value, ELM['number_heat_max'].value],
rangemode="nonnegative")
@ui.page('/') @ui.page('/')
async def index(): def index():
await ui.context.client.connected()
# initialize objects # initialize objects
ELM['fig'] = ply.subplots.make_subplots(rows=2, cols=1) pio.templates.default = 'plotly_dark'
# ELM['fig'] = pgo.Figure()
ELM['fig'] = ply.subplots.make_subplots(
rows=2, cols=1, specs = [[{'t': 0.0}], [{}]], shared_xaxes=True,
vertical_spacing=0.02)
# render header # render header
ui.context.client.content.classes('h-[100vh]') ui.context.client.content.classes('h-[100vh]')
@@ -152,12 +198,18 @@ async def index():
ui.button('Choose file', on_click=pick_file, icon='folder') ui.button('Choose file', on_click=pick_file, icon='folder')
ELM['number_time_range'] = ui.number( ELM['number_time_range'] = ui.number(
label='time range', value=6, format='%.2f', min=0, step=0.5, label='Time range', value=6, format='%.2f', min=0, step=0.5,
suffix='h', suffix='h',
# on_change=lambda e: update_data(), # see timer below # see timer below, but still here active b/c the time might be inactive
).props('clearable').bind_value(app.storage.user, 'time_range').classes('w-32') ).on('update:model-value', lambda e: update_data(), throttle=1.0) \
.props('clearable').bind_value(app.storage.user, 'time_range').classes('w-32')
ELM['switch_timer'] = ui.switch('auto-refresh').bind_value(app.storage.user, 'timer') ELM['switch_timer'] = ui.switch('Auto-refresh').bind_value(app.storage.user, 'timer')
ELM['label_update_last'] = ui.label(
ELM['label_update_last_fmt'].format(
last=datetime.datetime.fromtimestamp(
ELM['update_last']).strftime("%Y-%m-%dT%H:%M:%S.%f")))
ui.space() ui.space()
@@ -172,19 +224,55 @@ async def index():
ELM['label_file'] = ui.label( ELM['label_file'] = ui.label(
ELM['label_file_fmt'].format(filename=os.path.basename(ELM['filename']))) ELM['label_file_fmt'].format(filename=os.path.basename(ELM['filename'])))
ELM['label_data_len'] = ui.label(ELM['label_data_len_fmt'].format(num=0, numa=0)) ELM['label_data_len'] = ui.label(ELM['label_data_len_fmt'].format(num=0, numa=0))
ELM['label_data_temp'] = ui.label(ELM['label_data_temp_fmt'].format(min=0, max=0))
ELM['label_data_heat'] = ui.label(ELM['label_data_heat_fmt'].format(min=0, max=0))
with ui.row(align_items="baseline").classes('w-full'):
ui.label('Temperature')
ELM['number_temp_min'] = \
ui.number(
label='min', value=None, format='%.2f', min=0, step=1.0, suffix='K') \
.props('clearable').classes('w-32').on(
'update:model-value', lambda e: update_fig(), throttle=1.0)
ELM['number_temp_max'] = \
ui.number(
label='max', value=None, format='%.2f', min=0, step=1.0, suffix='K') \
.props('clearable').classes('w-32').on(
'update:model-value', lambda e: update_fig(), throttle=1.0)
ui.label().classes('w-22')
ui.label('Heater')
ELM['number_heat_min'] = \
ui.number(
label='min', value=None, format='%.2f', min=0, step=1.0, suffix='%') \
.props('clearable').classes('w-32').on(
'update:model-value', lambda e: update_fig(), throttle=1.0)
ELM['number_heat_max'] = \
ui.number(
label='max', value=None, format='%.2f', min=0, step=1.0, suffix='%') \
.props('clearable').classes('w-32').on(
'update:model-value', lambda e: update_fig(), throttle=1.0)
pio.templates.default = 'plotly_dark'
# ELM['fig'] = pgo.Figure()
ELM['fig'].update_layout( ELM['fig'].update_layout(
height=600, height=640,
#template='plotly_white' margin={'t': 25},
#legend_tracegroupgap=140,
template=ELM['plotly_dark'] if dark_mode.value else ELM['plotly_light'], template=ELM['plotly_dark'] if dark_mode.value else ELM['plotly_light'],
yaxis1_title='Temperature, K',
yaxis2_title='Power, %',
yaxis2_range=[0, 100],
xaxis2_title='Time',
) )
ELM['fig'].update_yaxes(
row=1, col=1, range=[ELM['number_temp_min'].value, ELM['number_temp_max'].value],
rangemode="nonnegative")
ELM['fig'].update_yaxes(
row=2, col=1, range=[ELM['number_heat_min'].value, ELM['number_heat_max'].value],
rangemode="nonnegative")
ELM['plot'] = ui.plotly(ELM['fig']).classes('w-full') ELM['plot'] = ui.plotly(ELM['fig']).classes('w-full')
# update_data() # update_data()
ui.timer(0, lambda: update_data(), once=True) ui.timer(0, lambda: update_data(), once=True)
ELM['timer'] = ui.timer(2.0, lambda: update_data(), immediate=False) ELM['timer'] = ui.timer(0.5, lambda: update_data(), immediate=False)
ELM['switch_timer'].bind_value_to(ELM['timer'], 'active') ELM['switch_timer'].bind_value_to(ELM['timer'], 'active')
def main_gui(args): def main_gui(args):