pyscript-bootstrap-templates/examples/03_numpy_grid_demo/main.py

114 lines
3.4 KiB
Python
Raw Permalink Normal View History

2022-10-16 18:41:50 +02:00
from pyscript_bootstrap_templates import bootstrap_templates
from pyscript_bootstrap_templates import bootstrap_HTML as bHTML
from pyscript_bootstrap_templates import HTML as HTML
from pyscript_bootstrap_templates import bootstrap_inputs as bInputs
import numpy as np
# wrapper class to create editable numpy matrices:
class NumpyGrid2D(HTML.Table, bHTML.BootstrapContainer):
def __init__(self, numpy_grid: np.ndarray, parent: HTML.Element = None):
# store numpy grid
self._numpy_grid = numpy_grid.copy()
m,n = self._numpy_grid.shape
super().__init__(parent=parent)
self.m = 0
self.p = 0
# create a grid of inputs
self._inputs = []
for i in range(m):
row = []
# to keep it simple: use plain html table elements
tr = HTML.Tr(parent=self)
for j in range(n):
th = HTML.Th(parent=tr)
cell = bInputs.InputFloat(parent=th)
cell.p = 0
cell.m = 0
cell.value = self._numpy_grid[i,j]
row.append(cell)
self._inputs.append(row)
def _update_ndarray(self):
for i, row in enumerate(self._inputs):
for j, cell in enumerate(row):
self._numpy_grid[i,j] = float(cell.value)
@property
def numpy_grid(self) -> np.ndarray:
self._update_ndarray()
return self._numpy_grid.copy()
@numpy_grid.setter
def numpy_grid(self, value:np.ndarray):
assert value.shape == self._numpy_grid.shape
self._numpy_grid = value.copy()
# update input grid
for i, row in enumerate(self._inputs):
for j, cell in enumerate(row):
cell.value = self._numpy_grid[i,j]
# create default values
matrix_a = np.array([[1,2,3],[4,5,6],[7,8,9]])
matrix_b = np.array([[1,2,3],[4,5,6],[7,8,9]])
matrix_result = np.zeros((3,3))
app = bootstrap_templates.PyScriptBootstrapDashboard(
parent_element="pyscript_app", brand_name="03_numpy_grid_demo")
div = bHTML.BootstrapContainer("Matrix operations", parent=app.sidebar)
div.font_size = 4
matrix_row = bHTML.Row(parent=app.main)
matrix_row.p = 1
matrix_row.m = 1
matrix_row.display_property = bHTML.DisplayProperty.INLINE_FLEX
# create row of three matrices
mat_widget_a = NumpyGrid2D(matrix_a)
mat_widget_b = NumpyGrid2D(matrix_b)
mat_widget_result = NumpyGrid2D(matrix_result)
# just for fanciness: wrap the matrices in bootstrap cards
col_a = bHTML.Col(parent=matrix_row)
col_b = bHTML.Col(parent=matrix_row)
col_result = bHTML.Col(parent=matrix_row)
card_a = bHTML.Card(mat_widget_a, card_header=bHTML.Div("Matrix A"), parent=col_a)
card_b = bHTML.Card(mat_widget_b, card_header=bHTML.Div("Matrix B"), parent=col_b)
card_result = bHTML.Card(mat_widget_result, card_header=bHTML.Div("Result"), parent=col_result)
card_a.shadow = bHTML.Shadow.MEDIUM
card_b.shadow = bHTML.Shadow.MEDIUM
card_result.shadow = bHTML.Shadow.MEDIUM
operations = {
'+': np.add,
'-': np.subtract,
'*': np.multiply,
'/': np.divide,
'dot product': np.dot
}
for op in operations:
btn = bHTML.ButtonPrimary(op, parent=app.sidebar)
btn.w = 100
btn.m = 1
def onclick(event, numpy_func=operations[op]):
mat_widget_result.numpy_grid = numpy_func(mat_widget_a.numpy_grid, mat_widget_b.numpy_grid)
btn.onclick = onclick