cortex-lab / phylib

Lightweight electrophysiological data analysis library
BSD 3-Clause "New" or "Revised" License
11 stars 23 forks source link

Fix same_kind numpy multiplication #19

Closed alejoe91 closed 4 years ago

alejoe91 commented 4 years ago

Hi @rossant

In spikeinterface we export the channel positions as float64 and this raises a same_kind exception with the new version of phy.

I was able to get rid of the error with this fix. Let me know if that works for you! I wasn't able to figure out another way.

Cheers Alessio

codecov-io commented 4 years ago

Codecov Report

Merging #19 into master will not change coverage. The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master    #19   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          35     35           
  Lines        3506   3506           
=====================================
  Hits         3506   3506
Impacted Files Coverage Δ
phylib/utils/geometry.py 100% <100%> (ø) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 02ef43f...fbbb4de. Read the comment docs.

rossant commented 4 years ago

What about this fix, does it work?

out *= ((t1 - t0) / d).astype(out.dtype)

alejoe91 commented 4 years ago

Surprisingly with your suggestion the problem is still there..very strange!

alejoe91 commented 4 years ago

So if I change that line alone I get:

16:28:01.765 [E] __init__:62          An error has occurred (UFuncTypeError): Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
Traceback (most recent call last):
  File "/home/alessio/.virtualenvs/expipe/bin/phy", line 11, in <module>
    load_entry_point('phy', 'console_scripts', 'phy')()
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/__init__.py", line 158, in cli_template_gui
    template_gui(params_path, **kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/template/gui.py", line 200, in template_gui
    gui = controller.create_gui()
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/base.py", line 1643, in create_gui
    gui.create_views()
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/gui/gui.py", line 676, in create_views
    self.create_and_add_view(view_name)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/gui/gui.py", line 647, in create_and_add_view
    view = fn()
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/base.py", line 1441, in create_probe_view
    channel_labels=self._get_channel_labels(),
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/cluster/views/probe.py", line 77, in __init__
    self.positions, self.data_bounds = _get_pos_data_bounds(positions)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/cluster/views/probe.py", line 27, in _get_pos_data_bounds
    positions, _ = get_non_overlapping_boxes(positions)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/forks/phylib/phylib/utils/geometry.py", line 152, in get_non_overlapping_boxes
    box_pos = range_transform(b1, b2, box_pos)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/forks/phylib/phylib/utils/geometry.py", line 65, in range_transform
    out -= f0
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

Traceback (most recent call last):
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/gui/qt.py", line 532, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/cluster/views/base.py", line 236, in _worker
    self.on_select(cluster_ids=cluster_ids, **kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/cluster/views/base.py", line 207, in on_select
    self.plot(**kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/cluster/views/waveform.py", line 328, in plot
    self.canvas.boxed.update_boxes(_get_box_pos(bunchs, channel_ids))
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/plot/interact.py", line 234, in update_boxes
    self.box_pos, self.box_size = get_non_overlapping_boxes(box_pos)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/forks/phylib/phylib/utils/geometry.py", line 152, in get_non_overlapping_boxes
    box_pos = range_transform(b1, b2, box_pos)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/forks/phylib/phylib/utils/geometry.py", line 65, in range_transform
    out -= f0
numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'subtract' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'

If I also apply the same to lines 65 and 68 I get:

16:29:43.242 [E] __init__:62          An error has occurred (AssertionError): 
Traceback (most recent call last):
  File "/home/alessio/.virtualenvs/expipe/bin/phy", line 11, in <module>
    load_entry_point('phy', 'console_scripts', 'phy')()
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 764, in __call__
    return self.main(*args, **kwargs)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/alessio/.virtualenvs/expipe/lib/python3.6/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/__init__.py", line 158, in cli_template_gui
    template_gui(params_path, **kwargs)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/template/gui.py", line 200, in template_gui
    gui = controller.create_gui()
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/base.py", line 1643, in create_gui
    gui.create_views()
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/gui/gui.py", line 676, in create_views
    self.create_and_add_view(view_name)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/gui/gui.py", line 647, in create_and_add_view
    view = fn()
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/apps/base.py", line 1441, in create_probe_view
    channel_labels=self._get_channel_labels(),
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/cluster/views/probe.py", line 96, in __init__
    color=color, size=self.unselected_marker_size)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/plot/visuals.py", line 224, in set_data
    pos_tr = self.transforms.apply(data.pos)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/plot/transform.py", line 504, in apply
    arr = t.apply(arr)
  File "/home/alessio/Documents/Codes/spike_sorting/phy-project/phy/phy/plot/transform.py", line 31, in wrapped
    assert arr.dtype in (np.float32, np.float64)
AssertionError
rossant commented 4 years ago

Can you try this fix instead?

diff --git a/phy/cluster/views/probe.py b/phy/cluster/views/probe.py
index a2df95a6..2561d6ef 100644
--- a/phy/cluster/views/probe.py
+++ b/phy/cluster/views/probe.py
@@ -63,17 +63,18 @@ class ProbeView(ManualClusteringView):
     # Alpha value of the dead channels.
     dead_channel_alpha = .25

     def __init__(
             self, positions=None, best_channels=None, channel_labels=None,
             dead_channels=None, **kwargs):
         self.do_show_labels = True
         super(ProbeView, self).__init__(**kwargs)
         self.state_attrs += ('do_show_labels',)

         # Normalize positions.
         assert positions.ndim == 2
         assert positions.shape[1] == 2
+        positions = positions.astype(np.float32)
         self.positions, self.data_bounds = _get_pos_data_bounds(positions)

         self.n_channels = positions.shape[0]
alejoe91 commented 4 years ago

Yep that works! I think it's safe to cast it to float32 :) Committing the change. Thanks for the help!

alejoe91 commented 4 years ago

(actually making another PR)

alejoe91 commented 4 years ago

Even if the GUI starts, I still get some exception printed. I'd leave the astype(out.dtype) :)

rossant commented 4 years ago

okay thanks!

alejoe91 commented 4 years ago

Thank you for the help!