Source code for crtomo.notebook.steps.fe_mesh
import io
from copy import deepcopy
from IPython.display import display
import ipywidgets as widgets
from .base_step import base_step
from ipywidgets import GridBox, Layout
import pylab as plt
import crtomo
[docs]
class step_fe_mesh(base_step):
"""Load, or generate, an FE mesh for CRTomo
"""
def __init__(self, persistent_directory=None):
super().__init__(persistent_directory=persistent_directory)
self.name = 'fe_mesh'
self.title = 'FE Mesh'
self.required_steps = None
self.help_page = 'fe_meshes.html'
self.input_skel = {
'elem_data': io.BytesIO,
'elec_data': io.BytesIO,
}
[docs]
def create_ipywidget_gui(self):
self.widgets['label_intro'] = widgets.Label(
'This tab allows you to load CRTomo Finite-Element meshes'
)
# Variant 1: directly load elem/elec.dat files
self.widgets['label_elem'] = widgets.Label(
"Upload elem.dat"
)
self.widgets['file_elem'] = widgets.FileUpload(
accept='.dat',
multiple=False
)
self.widgets['label_elec'] = widgets.Label(
"Upload elec.dat"
)
self.widgets['file_elec'] = widgets.FileUpload(
accept='.dat',
multiple=False
)
self.widgets['button_upload'] = widgets.Button(
description='Import elem.dat and elec.dat',
disabled=False,
# 'success', 'info', 'warning', 'danger' or ''
button_style='',
tooltip='Click me',
icon='check' # (FontAwesome names without the `fa-` prefix)
)
self.widgets['button_upload'].on_click(
self.apply_next_input_from_gui
)
self.widgets['label_feedback'] = widgets.Label()
self.widgets['output_meshimg'] = widgets.Output()
self.jupyter_gui = widgets.VBox([
GridBox(
children=[
self.widgets['label_intro'],
widgets.HBox([
self.widgets['label_elem'],
self.widgets['file_elem'],
]),
widgets.HBox([
self.widgets['label_elec'],
self.widgets['file_elec'],
]),
widgets.HBox([
self.widgets['button_upload'],
self.widgets['label_feedback'],
]),
self.widgets['output_meshimg'],
],
layout=Layout(
width='100%',
grid_template_columns='auto',
grid_template_rows='50px 50px 50px 50px auto',
grid_gap='5px 10px'
)
)
]
)
# self.jupyter_gui = GridspecLayout(
# 5, 3
# )
# self.jupyter_gui[0, :] = self.widgets['label_intro']
# self.jupyter_gui[1, 0] = self.widgets['label_elem']
# self.jupyter_gui[1, 1] = self.widgets['file_elem']
# self.jupyter_gui[2, 0] = self.widgets['label_elec']
# self.jupyter_gui[2, 1] = self.widgets['file_elec']
# self.jupyter_gui[3, 0:2] = self.widgets['button_upload']
# self.jupyter_gui[3, 2] = self.widgets['label_feedback']
# self.jupyter_gui[4, :] = self.widgets['output_meshimg']
# Variant 2: Create a mesh using electrodes.dat, boundaries.dat,
# char_length.dat, extra_nodes.dat, extra_lines.dat
# TODO
[docs]
def transfer_input_new_to_applied(self):
"""Make a copy of the self.input_new dict and store in
self.input_applied
This is complicated because some objects cannot be easily copied (e.g.,
io.BytesIO). Therefore, each step must implement this function by
itself.
"""
self.input_applied = deepcopy(self.input_new)
self.input_applied['elem_data'].seek(0)
self.input_applied['elec_data'].seek(0)
[docs]
def apply_next_input(self):
"""
"""
print('FE MESH: apply_next_input')
if not self.can_run():
return False
print('TELL 1', self.input_new['elem_data'].tell())
# load mesh into a grid object
mesh = crtomo.crt_grid(
self.input_new['elem_data'],
self.input_new['elec_data'],
)
# rewind positions for future use
self.input_new['elem_data'].seek(0)
self.input_new['elec_data'].seek(0)
print('TELL 2', self.input_new['elem_data'].tell())
self.results['mesh'] = mesh
with plt.ioff():
fig, ax = mesh.plot_grid()
self.results['mesh_fig'] = fig
self.results['mesh_ax'] = ax
with self.widgets['output_meshimg']:
fig_mesh = self.results['mesh_fig']
display(fig_mesh)
self.has_run = True
self.transfer_input_new_to_applied()
self.persistency_store()
return True
[docs]
def apply_next_input_from_gui(self, button):
"""Generate an input dict from the GUI elements and apply those new
inputs
"""
print('Applying input from GUI')
feedback = self.widgets['label_feedback']
for widget_name in ('file_elem', 'file_elec'):
widget = self.widgets[widget_name]
if len(widget.value) == 0 or widget.value[0]['size'] == 0:
feedback.value = 'You must provide both elem and elec files'
return
# get the file data from GUI elements
settings = {
'elem_data': io.BytesIO(
self.widgets['file_elem'].value[0].content
),
'elec_data': io.BytesIO(
self.widgets['file_elec'].value[0].content
),
}
self.set_input_new(settings)
ret_value = self.apply_next_input()
if ret_value:
feedback.value = 'Mesh was loaded'
# notify external objects
if self.callback_step_ran is not None:
self.callback_step_ran(self)
else:
feedback.value = 'There was an error loading the mesh'