def __init__(self, **params): super(LoadModel, self).__init__(**params) self.dat_files = [] self.model = None self.adh_mod = AdhModel()
class ConceptualModelEditor(param.Parameterized): adh_mod = param.ClassSelector(default=AdhModel( path_type=gv.Polygons, poly_columns=['node_spacing'], point_columns=['node_spacing']), class_=AdhModel) polys = param.ClassSelector(class_=hv.Path) def __init__(self, polys, **params): super(ConceptualModelEditor, self).__init__(polys=polys, **params) self.adh_mod = AdhModel(path_type=gv.Polygons, polys=polys, point_columns=['node_spacing'], poly_columns=['node_spacing'], crs=polys.crs) self.adh_mod.projection.set_crs(polys.crs) self.adh_mod.wmts.source = gv.tile_sources.EsriImagery self.adh_mod.height = 600 self.adh_mod.width = 600 @param.output(adh_mod=AdhModel) def output(self): return self.adh_mod def panel(self): return self.adh_mod.panel()
def test_adhmodel_read_mesh(): # set test project name project_name = 'SanDiego' # set project directory path = os.path.join(TESTDIR, 'test_files', project_name) # instantiate empty adh model object adhmod = AdhModel() # read the mesh file adhmod.read_mesh(path=path, project_name=project_name, crs=None, fmt='nc')
def test_read_result(self): file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files/SanDiego', 'SanDiego_dep.dat') model = AdhModel() model.read_result(file_path) results = model.simulation.results self.assertEqual(len(results), 1) self.assertIn('Depth', results) self.assertEqual(results.Depth.shape, (49, 9140))
def test_adhmodel_fromnnetcdf(): # set test project name project_name = 'SanDiego' # set project directory path = os.path.join(TESTDIR, 'test_files', project_name) # instantiate empty adh model object adhmod = AdhModel() # read model files adhmod.from_netcdf(path=path, project_name=project_name, crs=None)
def test_bad_format_e3t(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'bad_mesh_e3t.3dm') model = AdhModel() with self.assertRaises(ValueError) as context: model.read_mesh(fname, fmt='3dm') # self.assertTrue('Error reading element (E3T) record from file on line 3.' in str(context.exception)) self.assertTrue( "list.remove(x): x not in list" in str(context.exception))
def test_adhmodel_read_bc(): # set test project name project_name = 'SanDiego' # set project directory path = os.path.join(TESTDIR, 'test_files', project_name, f'{project_name}.bc') # instantiate empty adh model object adhmod = AdhModel() # read the mesh file adhmod.read_bc(file_name=path, fmt='bc')
def test_bad_format_nds(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'bad_mesh_nds.3dm') model = AdhModel() with self.assertRaises(UnboundLocalError) as context: model.read_mesh(fname, fmt='3dm') # self.assertTrue('Error reading node (ND) record from file on line 2.' in str(context.exception)) self.assertTrue( "local variable 'extra_cols' referenced before assignment" in str( context.exception))
def test_read_hot_start(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'angle_bt.hot') out_file = os.path.join(path, 'out_files', 'out_angle_bt.hot') base_file = os.path.join(path, 'base_angle_bt.hot') model = AdhModel() model.read_hotstart(fname, fmt='ascii') hotstart = model.simulation.hotstart self.assertEqual(1, len(hotstart)) self.assertEqual(250, hotstart.ioh.size) model.simulation.write_hotstart(out_file) self.assertTrue(filecmp.cmp(base_file, out_file, shallow=False))
def __init__(self, polys, **params): super(ConceptualModelEditor, self).__init__(polys=polys, **params) self.adh_mod = AdhModel(path_type=gv.Polygons, polys=polys, point_columns=['node_spacing'], poly_columns=['node_spacing'], crs=polys.crs) self.adh_mod.projection.set_crs(polys.crs) self.adh_mod.wmts.source = gv.tile_sources.EsriImagery self.adh_mod.height = 600 self.adh_mod.width = 600
def test_read_results(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files/SanDiego') project_name = 'SanDiego' model = AdhModel() model.read_results(path=path, project_name=project_name, fmt='ascii') results = model.simulation.results self.assertEqual(len(results), 3) self.assertIn('Depth', results) self.assertIn('Error', results) self.assertIn('Depth-Averaged Velocity', results) self.assertEqual(results.Depth.shape, (49, 9140)) self.assertEqual(results['Depth-Averaged Velocity'].shape, (49, 9140, 3))
def test_read_bc_2d_coriolis_x(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, '2D-coriolis_X.bc') base_file = os.path.join(path, 'base_2D-coriolis_X.bc') out_file = os.path.join(path, 'out_files', 'out_2D-coriolis_X.bc') model = AdhModel() model.read_bc(fname, fmt='bc') model.write_bc(out_file, fmt='bc', validate=False) self.assertTrue(filecmp.cmp(base_file, out_file))
def test_read_bc_east_ll_coarse(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'east_LL_coarse.bc') base_file = os.path.join(path, 'base_east_LL_coarse.bc') out_file = os.path.join(path, 'out_files', 'out_east_LL_coarse.bc') model = AdhModel() model.read_bc(fname, fmt='bc') model.write_bc(out_file, fmt='bc', validate=False) self.assertTrue(filecmp.cmp(base_file, out_file))
def test_read_bc_red_river(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'RedRiver.bc') base_file = os.path.join(path, 'base_RedRiver.bc') out_file = os.path.join(path, 'out_files', 'out_RedRiver.bc') model = AdhModel() model.read_bc(fname, fmt='bc') model.write_bc(out_file, fmt='bc', validate=False) self.assertTrue(filecmp.cmp(base_file, out_file))
def test_read_mesh_file(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'angle_bt.3dm') out_file = os.path.join(path, 'out_files', 'out_angle_bt.3dm') base_file = os.path.join(path, 'base_angle_bt2.3dm') model = AdhModel() model.read_mesh(fname, fmt='3dm') model.write_mesh(out_file, fmt='3dm') self.assertTrue(filecmp.cmp(base_file, out_file))
def test_read_bc_file(self): path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test_files') fname = os.path.join(path, 'ka_mult_sed.bc') base_file = os.path.join(path, 'base_ka_mult_sed.bc') out_file = os.path.join(path, 'out_files', 'out_ka_mult_sed.bc') out_file2 = os.path.join(path, 'out_files', 'out2_ka_mult_sed.bc') model = AdhModel() model.read_bc(fname, fmt='bc') model.write_bc(out_file, fmt='bc', validate=False) self.assertTrue(filecmp.cmp(base_file, out_file)) bc_class2 = BoundaryConditions() read_bc_file(out_file, bc_class2) write_bc_file(out_file2, bc_class2) self.assertTrue(filecmp.cmp(out_file, out_file2))
def test_adhmodel_initialize(): adhmod = AdhModel(version=5.0) assert adhmod.version == 5
class CreateMesh(param.Parameterized): """ We need a UUID for each polygon created (https://github.com/pyviz/EarthSim/issues/292) and then we need to apply attirbutes to the UUID. This is an issue right now since polygons are currently not being deleted properly. So they will always be in poly_stream (either as empty list or a single node - I cant remember) """ create = param.Action(lambda self: self.param.trigger('create'), label='Generate Mesh', precedence=0.2) status_bar = param.ClassSelector(default=StatusBar(), class_=StatusBar) # import data point_file = param.String(default=os.path.join(ROOTDIR, 'tests', 'test_files', 'vicksburg_pts.geojson'), label='Point file (*.geojson)', precedence=3) poly_file = param.String(default=os.path.join(ROOTDIR, 'tests', 'test_files', 'vicksburg_polys.geojson'), label='Polygon file (*geojson)', precedence=4) import_projection = param.ClassSelector(default=Projection(), class_=Projection, precedence=5) load_data = param.Action(lambda self: self.param.trigger('load_data'), label='Load', precedence=6) map_height = param.Number(default=600, bounds=(0, None), precedence=-1) map_width = param.Number(default=600, bounds=(0, None), precedence=-1) default_point_spacing = param.Number(default=1000, bounds=(0, None), precedence=-1) default_poly_spacing = param.Number(default=1000, bounds=(0, None), precedence=-1) adh_mod = param.ClassSelector(default=AdhModel( path_type=gv.Polygons, poly_columns=['node_spacing'], point_columns=['node_spacing'], crs=ccrs.GOOGLE_MERCATOR), class_=AdhModel) def __init__(self, **params): super(CreateMesh, self).__init__(**params) # self.map.opts.get('style') # merged but not released. (https://github.com/pyviz/holoviews/pull/3440) self.mesh_io = None self.adh_mod.wmts.source = gv.tile_sources.EsriImagery self.import_projection.set_crs(ccrs.GOOGLE_MERCATOR) @param.depends('load_data', watch=True) def _load_data(self): polys = geopandas.read_file(self.poly_file) pts = geopandas.read_file(self.point_file) self.adh_mod.points = geodframe_to_geoviews( pts, 'point', crs=self.import_projection.get_crs()) self.adh_mod.polys = geodframe_to_geoviews( polys, 'polygon', crs=self.import_projection.get_crs()) @param.depends('create', watch=True) def _create(self): # print('create clicked') # todo modify to always reproject to mercator before creating the mesh self.status_bar.busy() refine_points = [] if self.adh_mod.point_stream.data and 'node_spacing' in self.adh_mod.point_stream.element.columns( ): # for item in zip(element['Longitude'], element['Latitude'], element['node_spacing']): for idx in range(len(self.adh_mod.point_stream.data['Longitude'])): refine_points.append( xmsmesh.meshing.RefinePoint( create_mesh_point=True, point=( self.adh_mod.point_stream.element['Longitude'] [idx], self.adh_mod.point_stream.element['Latitude'][idx], 0), size=float(self.adh_mod.point_stream. element['node_spacing']))) # ============== input_polygon = [] if self.adh_mod.poly_stream.data: for idx in range(len(self.adh_mod.poly_stream.data['xs'])): poly_arr = np.fromiter(zip( self.adh_mod.poly_stream.data['xs'][idx], self.adh_mod.poly_stream.data['ys'][idx], [0] * len(self.adh_mod.poly_stream.data['ys'][idx])), dtype=('float,float,float')) # if no spacing value is given, use only the existing polygon vertices # if self.adh_mod.poly_stream.data['node_spacing'][idx] == self.adh_mod.default_value: # if self.adh_mod.poly_stream.data['node_spacing'][idx] == '': # input_polygon.append(xmsmesh.meshing.PolyInput(outside_polygon=poly_arr)) # redistribute vertices based on spacing from user # else: # instantiate the redistribution class rdp = xmsmesh.meshing.PolyRedistributePts() # set the node distance node_spacing = float( self.adh_mod.poly_stream.element.dimension_values( 'node_spacing', expanded=False)[idx]) # print(node_spacing, type(node_spacing)) # rdp.set_constant_size_func(float(self.adh_mod.poly_stream.data['node_spacing'][idx])) # create_constant_size_function rdp.set_constant_size_func(node_spacing) # run the redistribution function outdata = rdp.redistribute(poly_arr) # AML CHANGE redistribute with the closed loop and then remove the duplicates # and reverse the order because the mesher expects clockwise polygons # ensure start and end node are different # if len(poly_arr) != 0: # todo - waiting on fix for moving poly edges that leave a single node poly behind # outdata = check_polygon(outdata)[::-1] # todo pretty sure this is fixed so I'm commenting it out # convert the polygon to an 'input polygon' input_polygon.append( xmsmesh.meshing.PolyInput(outside_polygon=outdata)) # add the input polygons as polygons to the mesher class self.mesh_io = xmsmesh.meshing.MultiPolyMesherIo( poly_inputs=input_polygon, refine_points=refine_points) # Generate Mesh succeded, errors = xmsmesh.meshing.mesh_utils.generate_mesh( mesh_io=self.mesh_io) if succeded: self.status_bar.set_msg('Meshing was successful') else: self.status_bar.set_msg('Meshing errors found: {}'.format(errors)) # poly_stream and point_stream are always mercator because they come from bokeh proj = Projection(crs_label='Mercator') self.adh_mod.mesh = AdhMesh(projection=proj) self.adh_mod.mesh.verts, self.adh_mod.mesh.tris = xmsmesh_to_dataframe( self.mesh_io.points, self.mesh_io.cells) self.adh_mod.mesh.reproject_points() self.adh_mod.mesh.tri_mesh = gv.TriMesh( (self.adh_mod.mesh.tris[['v0', 'v1', 'v2']], self.adh_mod.mesh.mesh_points)).opts( opts.TriMesh(edge_cmap='yellow', edge_color='yellow')) # @param.depends('adh_mod.mesh', 'adh_mod.viewable_points', 'adh_mod.viewable_polys', 'load_data', 'adh_mod.wmts.source', watch=True) @param.depends('create', 'load_data', watch=True) def view_map(self): map = hv.DynamicMap( self.adh_mod.wmts.view) * self.adh_mod.polys * self.adh_mod.points if not self.adh_mod.mesh.verts.empty: # map *= self.adh_mod.mesh.view_elements(line_color='black') map *= self.adh_mod.mesh.view_mesh(line_color='blue') return map.opts(width=self.map_width, height=self.map_height) @param.depends('create', 'load_data', watch=True) def _data_tab(self): return pn.Tabs(('Polygons', self.adh_mod.poly_table), ('Points', self.adh_mod.point_table), name='View Data') @param.output(adh_mod=AdhModel) def output(self): return self.adh_mod # @param.depends('load_data') def panel(self): map_panel = pn.Column( self.view_map, pn.panel(self.param, parameters=['create'], show_name=False)) # display_tab = pn.Column( # pn.panel(self.adh_mod.wmts.param, parameters=['source'], expand_button=False), # pn.pane.Markdown('Visibility', style={'font-family':'Arial'}), # pn.panel(self.adh_mod.param, parameters=['viewable_points'], show_name=False), # self.adh_mod.param.viewable_polys # ) display_tab = pn.Column( pn.panel(self.adh_mod.wmts.param, parameters=['source'], expand_button=False, show_name=False)) # data_tab = pn.Tabs(('Polygons', self.adh_mod.poly_table), ('Points', self.adh_mod.point_table), name='View Data') import_tab = pn.Column( pn.panel(self.param, parameters=['point_file', 'poly_file'], show_name=False), pn.panel(self.import_projection, show_name=False), pn.panel(self.param, parameters=['load_data'], show_name=False)) logo_box = pn.Spacer() tool_panel = pn.Column( pn.Tabs(('Conceptual Model', self._data_tab), ('Display', display_tab)), logo_box) main = pn.Column(pn.Row(map_panel, tool_panel), self.status_bar.panel) return main
class AdhView(param.Parameterized): """ """ # projection options projection = param.ClassSelector(default=Projection(name=''), class_=Projection) # generic display options cmap_opts = param.ClassSelector(default=ColormapOpts(), class_=ColormapOpts) display_range = param.ClassSelector(default=DisplayRangeOpts(), class_=DisplayRangeOpts) adh_mod = param.ClassSelector( default=AdhModel(), class_=AdhModel, precedence=-1, doc="""AdhModel object containing all the model data""") # todo view analysis is currently hidden until it receives more work view_analysis = param.Boolean( default=False, precedence=-1, ) resolution = param.Number(default=1000, bounds=(10, 2000), softbounds=(10, 2000), doc=""" Distance between samples in meters. Used for interpolation of the cross-section paths.""") selected_result = param.ObjectSelector() selected_times = param.ObjectSelector() bc_ui = param.ClassSelector(class_=BoundaryConditionsUI) def __init__(self, **params): super(AdhView, self).__init__(**params) # initialize the boundary condition ui self.bc_ui = BoundaryConditionsUI( bound_cond=self.adh_mod.simulation.boundary_conditions) self.meshes = None if len(self.adh_mod.simulation.results.data_vars) != 0: # set default values self.param.selected_result.objects = self.adh_mod.simulation.results.data_vars try: self.selected_result = 'Depth' except: self.selected_result = set( self.adh_mod.simulation.results.data_vars).pop() self.param.selected_times.objects = self.adh_mod.mesh.current_sim.results[ self.selected_result].times.data self.selected_times = set(self.adh_mod.mesh.current_sim.results[ self.selected_result].times.data).pop() # set default colormap self.cmap_opts.colormap = process_cmap('rainbow_r') # set default wmts self.adh_mod.wmts.source = gvts.tile_sources['EsriImagery'] # function for dynamic map call @param.depends('selected_times') def time_mesh_scalar(self): # add this time step's data as a vdim under the provided label data_points = self.adh_mod.mesh.mesh_points.add_dimension( self.selected_result, 0, self.adh_mod.mesh.current_sim.results[self.selected_result].sel( times=self.selected_times).data, vdim=True) # return a trimesh with this data return gv.TriMesh( (self.adh_mod.mesh.tris[['v0', 'v1', 'v2']], data_points), label=self.selected_result, crs=ccrs.GOOGLE_MERCATOR) @param.depends('selected_times') def time_mesh_vector(self): vx = self.adh_mod.mesh.current_sim.results[self.selected_result].sel( times=self.selected_times).data[:, 0] vy = self.adh_mod.mesh.current_sim.results[self.selected_result].sel( times=self.selected_times).data[:, 1] xs = self.adh_mod.mesh.mesh_points.data['x'] ys = self.adh_mod.mesh.mesh_points.data['y'] with np.errstate(divide='ignore', invalid='ignore'): angle = np.arctan2(vy, vx) mag = np.sqrt(vx**2 + vy**2) return gv.VectorField((xs, ys, angle, mag), vdims=['Angle', 'Magnitude'], crs=ccrs.GOOGLE_MERCATOR) @param.depends('selected_result') def create_animation(self): """ Method to create holoviews dynamic map meshes for vector or scalar datasets""" # check to make sure the mesh points have been set. if self.adh_mod.mesh.mesh_points.data.empty: self.adh_mod.mesh.reproject_points() if 'BEGSCL' in self.adh_mod.mesh.current_sim.results[ self.selected_result].attrs.keys(): meshes = hv.DynamicMap(self.time_mesh_scalar, label='scalar') # meshes = hv.DynamicMap(self.time_mesh_scalar, kdims='times', label='scalar').redim.values( # times=sorted(self.adh_mod.mesh.current_sim.results['Depth'].times.values)) return meshes elif 'BEGVEC' in self.adh_mod.mesh.current_sim.results[ self.selected_result].attrs.keys(): meshes = hv.DynamicMap(self.time_mesh_vector, label='vector') return meshes else: log.error('Data type not recognized. Must be BEGSCL or BEGVEC.') @property def tabs(self): # if the annotator has no mesh if self.adh_mod.mesh.verts.empty: disp_tab = pn.Column( pn.panel(self.adh_mod.wmts.param, parameters=['source'], expand_button=False, show_name=False)) # otherwise display all mesh options else: disp_tab = pn.Column( pn.panel(self.adh_mod.wmts.param, parameters=['source'], expand_button=False, show_name=False), pn.panel(self.cmap_opts, show_name=False), pn.panel(self.display_range, show_name=False), pn.panel(self.adh_mod.mesh.param, parameters=['elements_toggle'], show_name=False), pn.panel(self.param, parameters=['selected_result'], show_name=False), pn.panel(self, parameters=['view_analysis'], show_name=False)) return [('Display', disp_tab)] # what to pass out of this page (for pipeline) @param.output() def output(self): pass # how to build this page def panel(self): return pn.panel(self.run) @param.depends('selected_result', 'view_analysis', 'adh_mod.mesh.elements_toggle', watch=True) def run(self): self.build_map_pane() self.build_tool_pane() self.build_analysis_pane() return pn.Row(self.map_pane, self.analysis_pane, self.tool_pane) def build_tool_pane(self, logo=None): if logo: logo_box = pn.panel(logo, width=300) else: logo_box = pn.Spacer() # self.tool_pane = pn.Column(pn.Tabs(*self.tabs, *self.bc_ui.tabs), logo_box) self.tool_pane = pn.Column(pn.Tabs(*self.tabs), logo_box) # self.tool_pane = pn.Column(pn.Tabs(*self.tabs), self.bc_ui.panel(), logo_box) # @param.depends('annotator.result_label') # @param.depends('adh_mod.mesh.elements_toggle', watch=True) # todo I don't know why this won't work def build_map_pane(self): if self.adh_mod.mesh.verts.empty: self.map_pane = self.adh_mod.map_view self.analysis_pane = pn.Spacer() else: # create the meshes for the dynamic map meshes = self.create_animation() edgepaths_overlay = self.adh_mod.mesh.view_elements() # Define dynamic options opts = dict(clipping_colors={ 'NaN': 'transparent', 'min': 'transparent' }, cmap=self.cmap_opts.param.colormap, clim=self.display_range.param.color_range, height=600, width=600) if meshes.label == 'scalar': # todo THIS IS GOING TO LOSE ALL ANNOTATIONS EVERY TIME THE MAP IS REDRAWN rasterized = rasterize(meshes).apply.opts(**opts) # Apply the colormap and color range dynamically dynamic = (rasterized * hv.DynamicMap(self.adh_mod.wmts.view) * self.adh_mod.polys * self.adh_mod.points * edgepaths_overlay) elif meshes.label == 'vector': # Apply the colormap and color range dynamically paths = vectorfield_to_paths(meshes, color='Magnitude', magnitude='Magnitude', scale=0.005) rasterized = rasterize(paths, aggregator='mean', precompute=True).apply.opts(**opts) dynamic = (rasterized * hv.DynamicMap(self.adh_mod.wmts.view) * self.adh_mod.polys * self.adh_mod.points * edgepaths_overlay) # time = pn.panel(self.adh_mod, parameters=['time'], widgets={'time': pn.widgets.DiscretePlayer}, show_name=False, width=400) # time = pn.panel(self.adh_mod.mesh.simulations[self.sim_selector], parameters=['time'], widgets={'time': pn.widgets.DiscretePlayer}, show_name=False, width=400) # time = pn.panel(self.adh_mod.mesh.current_sim, parameters=['time'], # widgets={'time': pn.widgets.DiscretePlayer}, show_name=False, width=400) time = pn.panel( self.param, parameters=['selected_times'], widgets={'selected_times': pn.widgets.DiscretePlayer}, show_name=False, width=600) hv_panel = pn.panel(dynamic) if self.view_analysis: # todo going to have to combine the dynamic maps for meshes/vectorization/moving_points # self.map_pane = pn.Column(hv_panel[0] * self.annotator.moving_points, pn.Row(pn.Spacer(width=100), time)) # create the sections of the trimesh self.sections = meshes.apply( self.adh_mod._sample, streams=[self.adh_mod.poly_stream]) point_x = PointerX(source=self.sections, x=0) self.vline = hv.DynamicMap(hv.VLine, streams=[point_x]) self.moving_points = self.sections.apply( self.adh_mod._pos_indicator, streams=[point_x]) self.analysis_pane = pn.Column( (self.sections * self.vline).redim.range( Depth=(0, 100), Distance=(0, 20000)).opts(framewise=True)) self.map_pane = pn.Column(hv_panel[0], pn.Row(pn.Spacer(width=80), time)) else: self.map_pane = pn.Column(hv_panel[0], pn.Row(pn.Spacer(width=80), time)) self.analysis_pane = pn.Spacer() def build_analysis_pane(self): # if self.view_analysis: # self.analysis_pane = pn.Column(self.sections * self.vline) pass
class LoadModel(param.Parameterized): """ Parameterized class to load model information Formatted for Panel and Pipeline Page """ load_sim_widget = param.ClassSelector(default=LoadSimulation(), class_=LoadSimulation) att_widget = param.ClassSelector(default=Attributes(), class_=Attributes) projection = param.ClassSelector(default=Projection(), class_=Projection) load_data = param.Action(lambda self: self.param.trigger('load_data'), label='Load Data', precedence=0.2) label = param.String(default='Basic Input', precedence=-1) def __init__(self, **params): super(LoadModel, self).__init__(**params) self.dat_files = [] self.model = None self.adh_mod = AdhModel() # output the adh_viz object # @param.output(annot=AdhAnnotator) @param.output(adh_mod=AdhModel) def output(self): return self._load_data() @param.depends('load_sim_widget.load_netcdf', 'load_sim_widget.adh_root_filename', 'load_sim_widget.adh_directory', watch=True) def available_attributes(self): # todo this needs a 'no files found' check att_list = [] # enable the projections self.projection.set_constant(value=False) # if netcdf is selected if self.load_sim_widget.load_netcdf: filename = os.path.join( self.load_sim_widget.adh_directory, self.load_sim_widget.adh_root_filename + '.nc') try: # open the xarray dataset (does not load into memory) ncdf = xr.open_dataset(filename) except FileNotFoundError: print('File Not Found: {}'.format(filename)) else: # look for crs in the file if 'crs' in ncdf.attrs.keys(): # set the projection in the widget self.projection.set_crs(get_crs(ncdf)) # disable the widget self.projection.set_constant(value=True) with ncdf: # enable and add all variables in the netcdf file for var in ncdf.data_vars: att_name = var.lower().replace(" ", "_") # if the variable has results dimensions if 'times' in ncdf[var].dims and 'nodes_ids' in ncdf[ var].dims: if att_name == 'depth-averaged_velocity': att_list.append('velocity') elif att_name == 'error': att_list.append('error_hydro') else: # add to the list att_list.append(att_name) # close the dataset ncdf.close() # otherwise read from available *.dat files else: # get the list of filenames # todo this isn't foolproof e.g. `SanDieg` finds files file_names = glob.glob( os.path.join(self.load_sim_widget.adh_directory, self.load_sim_widget.adh_root_filename + '_*.dat')) # convert file suffixes to a list of widgets att_list = [ self.att_widget.suffix_to_widget[get_variable_from_file_name( x)] for x in file_names ] # # dictionary for naming inconsistencies # todo add complexity for err_con in future # label_to_widget = {'error': 'error_hydro', # 'depth-averaged_velocity': 'velocity'} # # # loop over the inconsistencies # for key in label_to_widget.keys(): # # if this is found in the list # if key in att_list: # # remove the key # att_list.remove(key) # # add back in the corrected value # att_list.append(label_to_widget[key]) # adjust available attribute widgets based on available data for p in self.att_widget.param: # if this attribute wasn't in the list pobj = self.att_widget.param[p] if p in att_list: # ensure the widget is enabled pobj.constant = False # set the widget value setattr(self.att_widget, p, True) elif p != 'name': # ensure the widget is enabled pobj.constant = False # uncheck the attribute setattr(self.att_widget, p, False) # disable attribute pobj.constant = True @param.depends('load_data', watch=True) def _load_data(self): # if file is netcdf if self.load_sim_widget.load_netcdf: self.adh_mod.from_netcdf( path=self.load_sim_widget.adh_directory, project_name=self.load_sim_widget.adh_root_filename, crs=self.projection.get_crs()) # request to load data from *dat files: else: # get a list of requested suffix strings slist = self.att_widget.suffix_list(value=True) # construct list of filenames fnames = [] [ fnames.append( os.path.join( self.load_sim_widget.adh_directory, self.load_sim_widget.adh_root_filename + '_' + x + '.dat')) for x in slist ] # read the requested files self.adh_mod.from_ascii( path=self.load_sim_widget.adh_directory, project_name=self.load_sim_widget.adh_root_filename, crs=self.projection.get_crs(), file_names=fnames) return self.adh_mod # visualize the page def panel(self): self.available_attributes() # for the initial load return pn.Column( pn.Row(pn.Param(self.load_sim_widget, show_name=False), pn.Param(self.att_widget, show_name=False), pn.Param(self.projection, show_name=False), name=self.label), pn.Pane(self.param, parameters=['load_data'], show_name=False))