Spaces:
Runtime error
Runtime error
| # Note: Main must be imported even though it is not used. | |
| from h2o_wave import Q, ui, app, main, data, on | |
| import numpy as np | |
| import pandas as pd | |
| import random | |
| import time | |
| import asyncio | |
| NUMBER_SENSORS = 4 | |
| LIMIT_LEN_SHOWING = 20 | |
| REALTIME_UPDATE = 5 # seconds | |
| list_data = [] | |
| line_charts_data = [] # [(sensor_id, [data]), ...] | |
| for i in range(NUMBER_SENSORS): | |
| line_charts_data.append((i, [])) | |
| start_year = 1991 | |
| while True: | |
| for i in range(NUMBER_SENSORS): | |
| random_value = random.uniform(1, 50) # Generate a random value between 1 and 50 | |
| value = (str(start_year), random_value) | |
| line_charts_data[i][1].append(value) | |
| start_year += 1 | |
| if start_year == 2021: | |
| break | |
| async def update_value(q: Q): | |
| while True: | |
| time.sleep(REALTIME_UPDATE) | |
| # TODO: Update realtime values for current stats cards | |
| # value_counts = random.randint(0, 100) | |
| # percentages = random.random() | |
| percentages = np.random.random(NUMBER_SENSORS) | |
| value_counts = np.random.randint(0, 100, NUMBER_SENSORS) | |
| show_multiple_stats_cards(q, value_counts, percentages) | |
| await q.page.save() | |
| async def api_get_data(): | |
| global list_data, line_charts_data, start_year | |
| while True: | |
| for i in range(NUMBER_SENSORS): | |
| random_value = random.uniform(1, 50) # Generate a random value between 1 and 50 | |
| value = (str(start_year), random_value) | |
| line_charts_data[i][1].append(value) | |
| start_year += 1 | |
| await asyncio.sleep(REALTIME_UPDATE) | |
| async def update_charts(q: Q): | |
| global line_charts_data | |
| while True: | |
| time.sleep(REALTIME_UPDATE) | |
| for sensor_data in line_charts_data: | |
| sensor_id = str(sensor_data[0]) | |
| data = sensor_data[1] | |
| limites_showing_data = LIMIT_LEN_SHOWING if len(data) > LIMIT_LEN_SHOWING else len(data) | |
| show_line_graph(q, sensor_id, data[-limites_showing_data:]) | |
| percentages = np.random.random(NUMBER_SENSORS) | |
| value_counts = np.random.randint(0, 100, NUMBER_SENSORS) | |
| show_multiple_stats_cards(q, value_counts, percentages) | |
| await q.page.save() | |
| def on_startup(): | |
| print('App started!') | |
| def on_shutdown(): | |
| print('App stopped!') | |
| task_data = asyncio.create_task(api_get_data()) | |
| async def sever(q: Q): | |
| apply_layout(q) | |
| show_homepage(q) | |
| # show_histograms(q, df, index=[1, 7, 8]) | |
| # await update_value(q) | |
| await update_charts(q) | |
| # await q.page.save() | |
| def show_homepage(q: Q): | |
| q.page['header'] = ui.header_card( | |
| box=ui.box('header', width='100%', height='86px'), | |
| icon='Video360Generic', | |
| icon_color='White', | |
| title='AgroTrack Application', | |
| subtitle='๋ด์๋์ ๊ธฐ์ ์ผํฐ') | |
| q.page['footer'] = ui.footer_card( | |
| box='footer', | |
| caption='Copyright (C) [AISeed](https://sprout-fibre-be6.notion.site/AISEED-40e62bb70c024a2c974c0a7051aca86f?pvs=4) Designed by [Blackhole](https://github.com/andrewlee1807/)') | |
| def apply_layout(q: Q): | |
| q.page['meta'] = ui.meta_card(box='', theme='oceanic', title="SmartFarm's Sensor Dashboard", | |
| layouts=[ | |
| ui.layout( | |
| breakpoint='xl', | |
| width='1600px', | |
| zones=[ | |
| ui.zone('header'), | |
| ui.zone('body', direction=ui.ZoneDirection.ROW, zones=[ | |
| ui.zone('content', direction=ui.ZoneDirection.COLUMN, zones=[ | |
| ui.zone('section1'), | |
| ui.zone('top', size='300px', direction=ui.ZoneDirection.ROW), | |
| ui.zone('section2'), | |
| ui.zone('bottom', direction=ui.ZoneDirection.ROW), | |
| ui.zone('chart1', direction=ui.ZoneDirection.ROW), | |
| ]), | |
| ]), | |
| ui.zone('footer') | |
| ]), | |
| ]) | |
| ## Making stats cards | |
| def make_stats_card_data(q: Q, column): | |
| value_counts = column.value_counts() | |
| total = value_counts.sum() | |
| return value_counts[1], total | |
| # Randomly generate data for stats cards: percentage and value (randomly generated) | |
| def show_stats_card(q: Q, name, value_count, percentage): | |
| q.page['stat_' + name] = ui.tall_gauge_stat_card( | |
| box=ui.box('top', width='12.5%'), | |
| title='Number of houses with ' + name, | |
| value='={{intl one}}', | |
| aux_value='={{intl perc style="percent" minimum_fraction_digits=2 maximum_fraction_digits=2 }}', | |
| progress=percentage, | |
| data=dict(one=int(value_count), perc=float(percentage)), | |
| plot_color='$red' | |
| ) | |
| def show_multiple_stats_cards(q: Q, value_counts, percentages): | |
| for i, j in enumerate(zip(value_counts, percentages)): | |
| name = "feature_" + str(i) | |
| value_count, percentage = j | |
| show_stats_card(q, name, value_count, percentage) | |
| # Making histograms | |
| def make_histogram_data(values): | |
| count, division = np.histogram(values) | |
| return [(x, y) for x, y in zip(division.tolist(), count.tolist())] | |
| def show_histogram(q: Q, values, variable_name, index): | |
| q.page['feat' + str(index)] = ui.tall_series_stat_card( | |
| box=ui.box('bottom', width='25%'), | |
| title='Linear tall series' + variable_name, | |
| value='=${{intl qux minimum_fraction_digits=2 maximum_fraction_digits=2}}', | |
| aux_value='={{intl quux style="percent" minimum_fraction_digits=1 maximum_fraction_digits=1}}', | |
| data=dict(qux=800, quux=80 / 100), | |
| plot_type='area', | |
| plot_category='foo', | |
| plot_value='qux', | |
| plot_color='$yellow', | |
| plot_data=data('foo qux', 3, rows=[[90, 0.9], [50, 0.5], [80, 0.8]]), | |
| plot_zero_value=0, | |
| plot_curve='smooth', | |
| ) | |
| def show_line_graph(q: Q, name, data_rows): | |
| q.page['section2'] = ui.section_card(box='section2', | |
| title='Plot of the data', | |
| subtitle='') | |
| position = 'bottom' if int(name) < 2 else 'chart1' | |
| q.page[name] = ui.plot_card( | |
| box=ui.box(position, width='50%'), | |
| title='Sensor ' + name, | |
| animate=True, | |
| data=data('time value', LIMIT_LEN_SHOWING, rows=data_rows), | |
| events=['select_marks'], | |
| plot=ui.plot([ | |
| ui.mark(type='line', | |
| x_scale='time', | |
| x='=time', | |
| y='=value', | |
| y_min=0, interactive=True), | |
| ui.mark(type='point', | |
| x='=time', | |
| # x='={{intl year type="time" month="numeric" day="numeric" hour="numeric" minute="numeric" hourCycle="h24" }}', | |
| y='=value', | |
| size=4, | |
| fill_color='#FFFF28', | |
| x_title='Time', y_title='Value', | |
| interactive=True), | |
| ]), | |
| ) | |
| async def on_marks_selected(q: Q): | |
| print("Click") | |