Skip to content

[BUG] No warning for 3d input image or current slice detection #166

Description

@HarshdipSaha

Describe the bug
When running the "Automatic Slice Detection" tool with a carea_mouse_25um and sample_3d the plugin crashed with error
ValueError: operands could not be broadcast together...
To Reproduce

Load this atlas and moving image and press automatic slice detection
Expected behaviour

The algorithm should automatically:

  • Handle 3D input robustly before padding,
  • Generate warnings, or automatic extract current 2d slice(from slider or let user decide)

so that Bayesian optimization runs successfully without shape mismatches during the padding step.
Log file

                                Step | Target: -1.0000 | pitch: -3.8040|yaw: -3.5235|z_slice: 564.9790              
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\superqt\utils\_qthreading.py:613, in create_worker.<locals>.reraise(e=ValueError('operands could not be broadcast toge...al->remapped]: (2,2)  and requested shape (3,2)'))
    612 def reraise(e):
--> 613     raise e
        e = ValueError('operands could not be broadcast together with remapped shapes [original->remapped]: (2,2)  and requested shape (3,2)')

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\superqt\utils\_qthreading.py:175, in WorkerBase.run(self=<napari._qt.qthreading.GeneratorWorker object>)
    173     warnings.filterwarnings("always")
    174     warnings.showwarning = lambda *w: self.warned.emit(w)
--> 175     result = self.work()
        self = <napari._qt.qthreading.GeneratorWorker object at 0x000001B81180D640>
    176 if isinstance(result, Exception):
    177     if isinstance(result, RuntimeError):
    178         # The Worker object has likely been deleted.
    179         # A deleted wrapped C/C++ object may result in a runtime
    180         # error that will cause segfault if we try to do much other
    181         # than simply notify the user.

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\superqt\utils\_qthreading.py:440, in GeneratorWorker.work(self=<napari._qt.qthreading.GeneratorWorker object>)
    438 try:
    439     _input = self._next_value()
--> 440     output = self._gen.send(_input)
        self = <napari._qt.qthreading.GeneratorWorker object at 0x000001B81180D640>
        _input = None
        output = {'progress': 20}
        self._gen = <generator object RegistrationWidget.run_auto_slice_thread at 0x000001B811A28BC0>
    441     self.yielded.emit(output)
    442 except StopIteration as exc:

File H:\gsoc2026\rw2\brainglobe-registration\brainglobe_registration\registration_widget.py:1468, in RegistrationWidget.run_auto_slice_thread(self=<brainglobe_registration.registration_widget.RegistrationWidget object>, params={'init_points': 5, 'metric': 'mi', 'n_iter': 15, 'pitch_bounds': (-5, 5), 'roll_bounds': (-5, 5), 'weights': (1.0, 0.0, 0.0), 'yaw_bounds': (-5, 5), 'z_range': (0, 565)})
   1466 try:
   1467     while True:
-> 1468         next(result_generator)
        result_generator = <generator object run_bayesian_generator at 0x000001B810F6C610>
   1469         i += 1
   1470         yield {"progress": i}

File H:\gsoc2026\rw2\brainglobe-registration\brainglobe_registration\automated_target_selection.py:366, in run_bayesian_generator(atlas_volume=array([[[  0,   0, ...,   0,   0],
        [  0,...       [  0,   0, ...,   0, 228]]], dtype=uint16), sample=array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0... 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16), manual_z_range=(0, 565), pitch_bounds=(-5, 5), yaw_bounds=(-5, 5), roll_bounds=(-5, 5), init_points=5, n_iter=15, metric='mi', weights=(1.0, 0.0, 0.0))
    364 for _ in range(init_points):
    365     point = opt_roll.suggest()
--> 366     score = similarity_only_objective(
        score = -1.0
        point = {'roll': np.float64(-1.254598811526375)}
        target_slice = array([[0, 0, ..., 0, 0],
       [0, 0, ..., 0, 0],
       ...,
       [0, 0, ..., 0, 0],
       [0, 0, ..., 0, 0]], dtype=uint16)
        sample = array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       ...,

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16)
        metric = 'mi'
        weights = (1.0, 0.0, 0.0)
    367         **point,
    368         target_slice=target_slice,
    369         sample=sample,
    370         metric=metric,
    371         weights=weights,
    372     )
    373     opt_roll.register(params=point, target=score)
    375     yield {
    376         "stage": "fine",
    377         "roll": round(point["roll"], 2),
    378         "roll_score": score,
    379     }

File H:\gsoc2026\rw2\brainglobe-registration\brainglobe_registration\automated_target_selection.py:195, in similarity_only_objective(roll=np.float64(-1.254598811526375), target_slice=array([[0, 0, ..., 0, 0],
       [0, 0, ..., 0, ..., 0, 0],
       [0, 0, ..., 0, 0]], dtype=uint16), sample=array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0... 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16), metric='mi', weights=(1.0, 0.0, 0.0))
    165 """
    166 Compute similarity score between rotated fixed slice and 2D sample image.
    167 Used to optimise roll independently.
   (...)
    192     Similarity score between rotated fixed slice and sample image.
    193 """
    194 rotated_slice = rotate(target_slice, roll, clip=False)
--> 195 sample_padded, rotated_slice_padded = pad_to_match_shape(
        rotated_slice = array([[0., 0., ..., 0., 0.],
       [0., 0., ..., 0., 0.],
       ...,
       [0., 0., ..., 0., 0.],
       [0., 0., ..., 0., 0.]])
        sample = array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       ...,

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16)
    196     sample, rotated_slice, mode="constant", constant_values=0
    197 )
    199 score = compute_similarity_metric(
    200     moving=sample_padded,
    201     fixed=rotated_slice_padded,
    202     metric=metric,
    203     weights=weights,
    204 )
    205 return score

File H:\gsoc2026\rw2\brainglobe-registration\brainglobe_registration\similarity_metrics.py:61, in pad_to_match_shape(moving=array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0... 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16), fixed=array([[0., 0., ..., 0., 0.],
       [0., 0., ..... 0., ..., 0., 0.],
       [0., 0., ..., 0., 0.]]), mode='constant', constant_values=0)
     53         kwargs["constant_values"] = constant_values
     55     return np.pad(
     56         img,
     57         pad_width=((pad_top, pad_bottom), (pad_left, pad_right)),
     58         **kwargs,
     59     )
---> 61 moving_padded = pad_to_shape(moving, (target_height, target_width))
        target_height = 333
        target_width = 500
        moving = array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       ...,

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16)
        (target_height, target_width) = (333, 500)
     62 fixed_padded = pad_to_shape(fixed, (target_height, target_width))
     64 return moving_padded, fixed_padded

File H:\gsoc2026\rw2\brainglobe-registration\brainglobe_registration\similarity_metrics.py:55, in pad_to_match_shape.<locals>.pad_to_shape(img=array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0... 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16), target_shape=(333, 500))
     52 if mode == "constant":
     53     kwargs["constant_values"] = constant_values
---> 55 return np.pad(
        np.pad = <function pad at 0x000001B82FD6FF70>
        np = <module 'numpy' from 'C:\\Users\\HARSHDIP\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\numpy\\__init__.py'>
        img = array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       ...,

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16)
        pad_top = 39
        pad_bottom = 39
        pad_left = 141
        pad_right = 142
        ((pad_top, pad_bottom), (pad_left, pad_right)) = ((39, 39), (141, 142))
        (pad_top, pad_bottom) = (39, 39)
        (pad_left, pad_right) = (141, 142)
        kwargs = {'mode': 'constant', 'constant_values': 0}
     56     img,
     57     pad_width=((pad_top, pad_bottom), (pad_left, pad_right)),
     58     **kwargs,
     59 )

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\numpy\lib\_arraypad_impl.py:760, in pad(array=array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0... 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16), pad_width=array([[ 39,  39],
       [141, 142]]), mode='constant', **kwargs={'constant_values': 0})
    757     raise TypeError('`pad_width` must be of integral type.')
    759 # Broadcast to shape (array.ndim, 2)
--> 760 pad_width = _as_pairs(pad_width, array.ndim, as_index=True)
        array = array([[[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       ...,

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]],

       [[0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0],
        ...,
        [0, 0, ..., 0, 0],
        [0, 0, ..., 0, 0]]], dtype=int16)
        pad_width = array([[ 39,  39],
       [141, 142]])
    762 if callable(mode):
    763     # Old behavior: Use user-supplied function with np.apply_along_axis
    764     function = mode

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\numpy\lib\_arraypad_impl.py:534, in _as_pairs(x=array([[ 39,  39],
       [141, 142]]), ndim=3, as_index=True)
    530     raise ValueError("index can't contain negative values")
    532 # Converting the array with `tolist` seems to improve performance
    533 # when iterating and indexing the result (see usage in `pad`)
--> 534 return np.broadcast_to(x, (ndim, 2)).tolist()
        x = array([[ 39,  39],
       [141, 142]])
        ndim = 3
        np = <module 'numpy' from 'C:\\Users\\HARSHDIP\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\numpy\\__init__.py'>
        np.broadcast_to = <function broadcast_to at 0x000001B82FC56430>
        (ndim, 2) = (3, 2)

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\numpy\lib\_stride_tricks_impl.py:422, in broadcast_to(array=array([[ 39,  39],
       [141, 142]]), shape=(3, 2), subok=False)
    376 @array_function_dispatch(_broadcast_to_dispatcher, module='numpy')
    377 def broadcast_to(array, shape, subok=False):
    378     """Broadcast an array to a new shape.
    379
    380     Parameters
   (...)
    420            [1, 2, 3]])
    421     """
--> 422     return _broadcast_to(array, shape, subok=subok, readonly=True)
        array = array([[ 39,  39],
       [141, 142]])
        shape = (3, 2)
        subok = False

File ~\AppData\Local\Programs\Python\Python312\Lib\site-packages\numpy\lib\_stride_tricks_impl.py:358, in _broadcast_to(array=array([[ 39,  39],
       [141, 142]]), shape=(3, 2), subok=False, readonly=True)
    355     raise ValueError('all elements of broadcast shape must be non-'
    356                      'negative')
    357 extras = []
--> 358 it = np.nditer(
        np = <module 'numpy' from 'C:\\Users\\HARSHDIP\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\numpy\\__init__.py'>
        array = array([[ 39,  39],
       [141, 142]])
        extras = []
        (array,) = (array([[ 39,  39],
       [141, 142]]),)
        ['multi_index', 'refs_ok', 'zerosize_ok'] + extras = ['multi_index', 'refs_ok', 'zerosize_ok']
        shape = (3, 2)
    359     (array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'] + extras,
    360     op_flags=['readonly'], itershape=shape, order='C')
    361 with it:
    362     # never really has writebackifcopy semantics
    363     broadcast = it.itviews[0]

ValueError: operands could not be broadcast together with remapped shapes [original->remapped]: (2,2)  and requested shape (3,2)```

Computer used (please complete the following information):

Windows 11

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions