114 lines
3.4 KiB
Python
114 lines
3.4 KiB
Python
|
|
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
|
|
|
|
|
|
|
|
|
|
|