holoviz-topics / EarthSim

Tools for working with and visualizing environmental simulations.
https://earthsim.holoviz.org
BSD 3-Clause "New" or "Revised" License
65 stars 21 forks source link

Trimesh error when adding additional columns to tris #241

Closed kcpevey closed 5 years ago

kcpevey commented 5 years ago

3dm mesh files contain the nodal info [x,y,z] and element info [v0, v1, v2, material type]. The earthsim mesh reader in /earthsim/io/read_3dm_mesh doesn't keep the material information. So I rewrote it to keep the materials as an additional column in the dataframe:

def read_3dm_mesh2(fpath, skiprows=1):
    all_df = pd.read_table(fpath, delim_whitespace=True, header=None, skiprows=skiprows,
                           names=('row_type', 'cmp1', 'cmp2', 'cmp3', 'val'), index_col=1)
    conns = all_df[all_df['row_type'].str.lower() == 'e3t'][['cmp1', 'cmp2', 'cmp3', 'val']].values.astype(int) - 1
    pts = all_df[all_df['row_type'].str.lower() == 'nd'][['cmp1', 'cmp2', 'cmp3']].values.astype(float)
    verts = pd.DataFrame(pts, columns=['x', 'y', 'z'])
    tris = pd.DataFrame(conns, columns=['v0', 'v1', 'v2', 'mat'])
    return tris, verts

This does what I need it to do, but it causes an error when I try to use a trimesh generated from the verts and tris. If you replace the reader in the second cell of the Analyzing_Meshes.ipynb with the above code, you get this error:

WARNING:root:dynamic_operation: Callable raised "DataError("Supplied data does not contain specified dimensions, the following dimensions were not found: ['z']\n\nPandasInterface expects tabular data, for more information on supported datatypes see http://holoviews.org/user_guide/Tabular_Datasets.html",)".
Invoked as dynamic_operation(data=None)
WARNING:root:dynamic_operation: Callable raised "DataError("Supplied data does not contain specified dimensions, the following dimensions were not found: ['z']\n\nPandasInterface expects tabular data, for more information on supported datatypes see http://holoviews.org/user_guide/Tabular_Datasets.html",)".
Invoked as dynamic_operation(x=0)
---------------------------------------------------------------------------
DataError                                 Traceback (most recent call last)
C:\ProgramData\Anaconda3\envs\earthsimAUG\lib\site-packages\IPython\core\formatters.py in __call__(self, obj, include, exclude)
    968 
    969             if method is not None:
--> 970                 return method(include=include, exclude=exclude)
    971             return None
    972         else:

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\dimension.py in _repr_mimebundle_(self, include, exclude)
   1271         combined and returned.
   1272         """
-> 1273         return Store.render(self)
   1274 
   1275 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\options.py in render(cls, obj)
   1287         data, metadata = {}, {}
   1288         for hook in hooks:
-> 1289             ret = hook(obj)
   1290             if ret is None:
   1291                 continue

c:\projects\ers\github\holoviews\master\holoviews\holoviews\ipython\display_hooks.py in pprint_display(obj)
    270     if not ip.display_formatter.formatters['text/plain'].pprint:
    271         return None
--> 272     return display(obj, raw_output=True)
    273 
    274 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\ipython\display_hooks.py in display(obj, raw_output, **kwargs)
    243     elif isinstance(obj, (Layout, NdLayout, AdjointLayout)):
    244         with option_state(obj):
--> 245             output = layout_display(obj)
    246     elif isinstance(obj, (HoloMap, DynamicMap)):
    247         with option_state(obj):

c:\projects\ers\github\holoviews\master\holoviews\holoviews\ipython\display_hooks.py in wrapped(element)
    140         try:
    141             max_frames = OutputSettings.options['max_frames']
--> 142             mimebundle = fn(element, max_frames=max_frames)
    143             if mimebundle is None:
    144                 return {}, {}

c:\projects\ers\github\holoviews\master\holoviews\holoviews\ipython\display_hooks.py in layout_display(layout, max_frames)
    213         return None
    214 
--> 215     return render(layout)
    216 
    217 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\ipython\display_hooks.py in render(obj, **kwargs)
     63         renderer = renderer.instance(fig='png')
     64 
---> 65     return renderer.components(obj, **kwargs)
     66 
     67 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\plotting\bokeh\renderer.py in components(self, obj, fmt, comm, **kwargs)
    275         # Bokeh has to handle comms directly in <0.12.15
    276         comm = False if bokeh_version < '0.12.15' else comm
--> 277         return super(BokehRenderer, self).components(obj,fmt, comm, **kwargs)
    278 
    279 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\plotting\renderer.py in components(self, obj, fmt, comm, **kwargs)
    314             plot = obj
    315         else:
--> 316             plot, fmt = self._validate(obj, fmt)
    317 
    318         widget_id = None

c:\projects\ers\github\holoviews\master\holoviews\holoviews\plotting\renderer.py in _validate(self, obj, fmt, **kwargs)
    213         if isinstance(obj, tuple(self.widgets.values())):
    214             return obj, 'html'
--> 215         plot = self.get_plot(obj, renderer=self, **kwargs)
    216 
    217         fig_formats = self.mode_formats['fig'][self.mode]

c:\projects\ers\github\holoviews\master\holoviews\holoviews\plotting\bokeh\renderer.py in get_plot(self_or_cls, obj, doc, renderer)
    160             curdoc().theme = self_or_cls.theme
    161         doc.theme = self_or_cls.theme
--> 162         plot = super(BokehRenderer, self_or_cls).get_plot(obj, renderer)
    163         plot.document = doc
    164         return plot

c:\projects\ers\github\holoviews\master\holoviews\holoviews\plotting\renderer.py in get_plot(self_or_cls, obj, renderer)
    180 
    181         # Initialize DynamicMaps with first data item
--> 182         initialize_dynamic(obj)
    183 
    184         if not isinstance(obj, Plot):

c:\projects\ers\github\holoviews\master\holoviews\holoviews\plotting\util.py in initialize_dynamic(obj)
    242             continue
    243         if not len(dmap):
--> 244             dmap[dmap._initial_key()]
    245 
    246 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in __getitem__(self, key)
   1137         # Not a cross product and nothing cached so compute element.
   1138         if cache is not None: return cache
-> 1139         val = self._execute_callback(*tuple_key)
   1140         if data_slice:
   1141             val = self._dataslice(val, data_slice)

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in _execute_callback(self, *args)
    916 
    917         with dynamicmap_memoization(self.callback, self.streams):
--> 918             retval = self.callback(*args, **kwargs)
    919         return self._style(retval)
    920 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in __call__(self, *args, **kwargs)
    543         kwarg_hash = kwargs.pop('memoization_hash', ())
    544         (self.args, self.kwargs) = (args, kwargs)
--> 545         if not args and not kwargs: return self.callable()
    546         inputs = [i for i in self.inputs if isinstance(i, DynamicMap)]
    547         streams = []

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in dynamic_mul(*key, **kwargs)
    188                 pass
    189             try:
--> 190                 other_el = other.select(HoloMap, **key_map) if other.kdims else other[()]
    191                 layers.append(other_el)
    192             except KeyError:

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in __getitem__(self, key)
   1137         # Not a cross product and nothing cached so compute element.
   1138         if cache is not None: return cache
-> 1139         val = self._execute_callback(*tuple_key)
   1140         if data_slice:
   1141             val = self._dataslice(val, data_slice)

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in _execute_callback(self, *args)
    916 
    917         with dynamicmap_memoization(self.callback, self.streams):
--> 918             retval = self.callback(*args, **kwargs)
    919         return self._style(retval)
    920 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in __call__(self, *args, **kwargs)
    573 
    574         try:
--> 575             ret = self.callable(*args, **kwargs)
    576         except KeyError:
    577             # KeyError is caught separately because it is used to signal

c:\projects\ers\github\holoviews\master\holoviews\holoviews\util\__init__.py in dynamic_operation(*key, **kwargs)
    435             def dynamic_operation(*key, **kwargs):
    436                 self.p.kwargs.update(kwargs)
--> 437                 return self._process(map_obj[key], key)
    438         if isinstance(self.p.operation, Operation):
    439             return OperationCallable(dynamic_operation, inputs=[map_obj],

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in __getitem__(self, key)
   1137         # Not a cross product and nothing cached so compute element.
   1138         if cache is not None: return cache
-> 1139         val = self._execute_callback(*tuple_key)
   1140         if data_slice:
   1141             val = self._dataslice(val, data_slice)

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in _execute_callback(self, *args)
    916 
    917         with dynamicmap_memoization(self.callback, self.streams):
--> 918             retval = self.callback(*args, **kwargs)
    919         return self._style(retval)
    920 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\spaces.py in __call__(self, *args, **kwargs)
    573 
    574         try:
--> 575             ret = self.callable(*args, **kwargs)
    576         except KeyError:
    577             # KeyError is caught separately because it is used to signal

c:\projects\ers\github\holoviews\master\holoviews\holoviews\util\__init__.py in dynamic_operation(*key, **kwargs)
    431                 self.p.kwargs.update(kwargs)
    432                 obj = map_obj[key] if isinstance(map_obj, HoloMap) else map_obj
--> 433                 return self._process(obj, key)
    434         else:
    435             def dynamic_operation(*key, **kwargs):

c:\projects\ers\github\holoviews\master\holoviews\holoviews\util\__init__.py in _process(self, element, key)
    419             return self.p.operation.process_element(element, key, **kwargs)
    420         else:
--> 421             return self.p.operation(element, **self.p.kwargs)
    422 
    423 

c:\projects\ers\github\earthsim\master\earthsim\earthsim\analysis.py in _sample(self, obj, data)
    101             points = raster.data.sel_points(method='nearest', **indexes).to_dataframe()
    102             points['Distance'] = distance
--> 103             sections.append(Curve(points, 'Distance', vdims=[vdim, x, y]))
    104         return NdOverlay(dict(enumerate(sections)))
    105 

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\data\__init__.py in __init__(self, data, kdims, vdims, **kwargs)
    232         (data, self.interface, dims, extra_kws) = initialized
    233         super(Dataset, self).__init__(data, **dict(kwargs, **dict(dims, **extra_kws)))
--> 234         self.interface.validate(self, validate_vdims)
    235 
    236         self.redim = redim(self, mode='dataset')

c:\projects\ers\github\holoviews\master\holoviews\holoviews\core\data\pandas.py in validate(cls, dataset, vdims)
    148             raise DataError("Supplied data does not contain specified "
    149                             "dimensions, the following dimensions were "
--> 150                             "not found: %s" % repr(not_found), cls)
    151 
    152 

DataError: Supplied data does not contain specified dimensions, the following dimensions were not found: ['z']

PandasInterface expects tabular data, for more information on supported datatypes see http://holoviews.org/user_guide/Tabular_Datasets.html

How can I fix this?

kcpevey commented 5 years ago

Also note that this:
mat = tris.pop('mat')
fixes the error

philippjfr commented 5 years ago

The problem was that the trimesh rasterization code aggregates on one particular column and a tris column takes precedence over a vertex column. I'll submit a PR for holoviews to handle this correctly shortly.

kcpevey commented 5 years ago

Everything I have works now. Looks good!