tataratat / gustaf

python library to process and visualize numerical-analysis-geometries
https://tataratat.github.io/gustaf
Other
16 stars 8 forks source link

Jupyter notebook plotting issue with numpy 2.1.1 #218

Open mkofler96 opened 1 month ago

mkofler96 commented 1 month ago

When running the example notebook on a fresh installation, I get a trait error TraitError: The 'width' trait of a Line instance expected a float or a dict, not the float32 np.float32(0.054083023)."

Downgrading numpy to version 1.26.4 solved the issue for me.

{
    "name": "TraitError",
    "message": "The 'width' trait of a Line instance expected a float or a dict, not the float32 np.float32(0.054083023).",
    "stack": "---------------------------------------------------------------------------
TraitError                                Traceback (most recent call last)
Cell In[2], line 30
      1 nurbs = spp.NURBS(
      2     degrees=[1, 2],
      3     knot_vectors=[[0, 0, 1, 1], [0, 0, 0, 1, 1, 2, 2, 2]],
   (...)
     27     ],
     28 )
---> 30 gus.show(nurbs)

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/gustaf/show.py:48, in _CallableShowDotPy.__call__(self, *args, **kwargs)
     46 def __call__(self, *args, **kwargs):
     47     \"\"\"call show()\"\"\"
---> 48     return show(*args, **kwargs)

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/gustaf/show.py:203, in show(*args, **kwargs)
    201 # set interactive to true at last element
    202 if int(i + 1) == len(args):
--> 203     plt.show(
    204         list_of_showables,
    205         at=i,
    206         interactive=interact,
    207         camera=cam_tuple_to_list(cam),
    208         axes=axes,
    209     )
    211 else:
    212     plt.show(
    213         list_of_showables,
    214         at=i,
   (...)
    217         axes=axes,
    218     )

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/gustaf/helpers/notebook.py:127, in K3DPlotterN.show(self, list_of_showables, at, interactive, camera, axes, *args, **kwargs)
    123     self._logd(f\"*args ({args}) and **kwargs ({kwargs}) ignored\")
    125 # this converts vedo plotter to k3d plot.
    126 # after this, vedo plotter has no relevance to what you see
--> 127 self[self._at_get_location(at)] = self.vedo_plotters[at].show(
    128     list_of_showables,
    129     interactive=interactive,
    130     camera=camera,
    131     axes=axes,
    132 )

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/vedo/plotter.py:3317, in Plotter.show(self, at, axes, resetcam, zoom, interactive, viewup, azimuth, elevation, roll, camera, mode, rate, bg, bg2, size, title, screenshot, *objects)
   3315 # Backend ###############################################################
   3316 if vedo.settings.default_backend in [\"k3d\"]:
-> 3317     return backends.get_notebook_backend(self.objects)
   3318 #########################################################################
   3320 for ia in utils.flatten(objects):

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/vedo/backends.py:31, in get_notebook_backend(actors2show)
     29 #########################################
     30 if settings.default_backend == \"k3d\":
---> 31     return start_k3d(actors2show)
     33 #########################################
     34 if settings.default_backend.startswith(\"trame\"):

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/vedo/backends.py:245, in start_k3d(actors2show)
    241         pts = ia.vertices[ln_idx]
    243         aves = ia.diagonal_size() * iap.GetLineWidth() / 100
--> 245         kobj = k3d.line(
    246             pts.astype(np.float32),
    247             color=_rgb2int(iap.GetColor()),
    248             opacity=iap.GetOpacity(),
    249             shader=settings.k3d_line_shader,
    250             width=aves,
    251             name=name,
    252         )
    253         vedo.notebook_plotter += kobj
    255 ################################################################## Mesh

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/k3d/factory.py:244, in line(vertices, color, colors, attribute, color_map, color_range, width, opacity, shader, radial_segments, name, group, custom_data, compression_level, **kwargs)
    237 attribute = (
    238     np.array(attribute, np.float32) if type(
    239         attribute) is not dict else attribute
    240 )
    241 color_range = check_attribute_color_range(attribute, color_range)
    243 return process_transform_arguments(
--> 244     Line(
    245         vertices=vertices,
    246         color=color,
    247         width=width,
    248         shader=shader,
    249         radial_segments=radial_segments,
    250         colors=colors,
    251         attribute=attribute,
    252         color_map=color_map,
    253         color_range=color_range,
    254         opacity=opacity,
    255         name=name,
    256         group=group,
    257         custom_data=custom_data,
    258         compression_level=compression_level,
    259     ),
    260     **kwargs
    261 )

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/k3d/objects.py:310, in Line.__init__(self, **kwargs)
    309 def __init__(self, **kwargs):
--> 310     super(Line, self).__init__(**kwargs)
    312     self.set_trait(\"type\", \"Line\")

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/k3d/objects.py:108, in Drawable.__init__(self, **kwargs)
    105 def __init__(self, **kwargs):
    106     self.id = id(self)
--> 108     super(Drawable, self).__init__(**kwargs)

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/ipywidgets/widgets/widget.py:503, in Widget.__init__(self, **kwargs)
    501 \"\"\"Public constructor\"\"\"
    502 self._model_id = kwargs.pop('model_id', None)
--> 503 super().__init__(**kwargs)
    505 Widget._call_widget_constructed(self)
    506 self.open()

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/traitlets/traitlets.py:1355, in HasTraits.__init__(self, *args, **kwargs)
   1353 for key, value in kwargs.items():
   1354     if self.has_trait(key):
-> 1355         setattr(self, key, value)
   1356         changes[key] = Bunch(
   1357             name=key,
   1358             old=None,
   (...)
   1361             type=\"change\",
   1362         )
   1363     else:
   1364         # passthrough args that don't set traits to super

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/traitlets/traitlets.py:716, in TraitType.__set__(self, obj, value)
    714 if self.read_only:
    715     raise TraitError('The \"%s\" trait is read-only.' % self.name)
--> 716 self.set(obj, value)

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/traitlets/traitlets.py:690, in TraitType.set(self, obj, value)
    689 def set(self, obj: HasTraits, value: S) -> None:
--> 690     new_value = self._validate(obj, value)
    691     assert self.name is not None
    692     try:

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/traitlets/traitlets.py:722, in TraitType._validate(self, obj, value)
    720     return value
    721 if hasattr(self, \"validate\"):
--> 722     value = self.validate(obj, value)
    723 if obj._cross_validation_lock is False:
    724     value = self._cross_validate(obj, value)

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/traitlets/traitlets.py:2460, in Union.validate(self, obj, value)
   2458         except TraitError:
   2459             continue
-> 2460 self.error(obj, value)

File ~/anaconda3/envs/fresh_env/lib/python3.12/site-packages/traitlets/traitlets.py:831, in TraitType.error(self, obj, value, error, info)
    825 else:
    826     e = \"The '{}' trait expected {}, not {}.\".format(
    827         self.name,
    828         info or self.info(),
    829         describe(\"the\", value),
    830     )
--> 831 raise TraitError(e)

TraitError: The 'width' trait of a Line instance expected a float or a dict, not the float32 np.float32(0.054083023)."
}

Relevant conda environment specs:

gustaf                    0.0.26 
ipykernel                 6.29.5
ipython                   8.27.0
ipywidgets                8.1.5
jupyter_client            8.6.0
jupyter_core              5.7.2
jupyterlab-widgets        3.0.13
numpy                     2.1.1
numpy-base                2.0.1
k3d                       2.16.1
python                    3.12.5
splinepy                  0.1.3
clemens-fricke commented 1 month ago

I will look into this.

clemens-fricke commented 1 month ago

Did anything else downgrade as well? Or just numpy? Could you provide the package list with versions for the downgraded environment?

j042 commented 1 month ago

similar to https://github.com/tataratat/splinepy/issues/451

clemens-fricke commented 7 hours ago

I have looked into it a bit. This seems to be a problem with how vedo converts points and lines to k3d. If I change in vedo.backends the corresponding lines to not include conversion to numpy floats or explicitly convert them back it seems to work again.

Specifically the lines 316 onward to:

            aves = float(ia.average_size() * iap.GetPointSize() / 200)

            kobj = k3d.points(
                ia.vertices.astype(float),
                color=_rgb2int(iap.GetColor()),
                colors=kcols,
                opacity=iap.GetOpacity(),
                shader=settings.k3d_point_shader,
                point_size=aves,
                name=name,
            )

and lines from 243 onward


                aves = float(ia.diagonal_size() * iap.GetLineWidth() / 100)

                kobj = k3d.line(
                    pts.astype(float),
                    color=_rgb2int(iap.GetColor()),
                    opacity=iap.GetOpacity(),
                    shader=settings.k3d_line_shader,
                    width=aves,
                    name=name,
                )

it works again for me. I am not sure why this is just changing its functionality now and not before. Why traitlets was ok with this before and now it is not I am not sure.

clemens-fricke commented 7 hours ago

I opened an issue for this on vedo for this https://github.com/marcomusy/vedo/issues/1197#issue-2635555643.