Skip to content

Commit 4615ebc

Browse files
committed
bidiphase.shift: copy the source slice before the overlapping in-place assignment
bidiphase.shift shifts the odd scan lines with an in-place assignment whose source and destination slices overlap. numpy handles overlapping assignments by making a temporary copy, but torch.Tensor.copy_ does not, so since the registration path started passing torch tensors (v1.0.0.1) every odd line was corrupted instead of shifted: with bidiphase=3, 34% of odd-line pixels in register_frames' output differ from the intended shift (they contain repeated copies of the first columns). The reference image, which still goes through the numpy path in registration_wrapper, was shifted correctly, so frames and reference disagreed. Copy the source slice first (clone for torch, copy for numpy), which restores the numpy semantics for both array types. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012d2sJAD5EUp4GqAStqoBX7
1 parent 90be895 commit 4615ebc

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

suite2p/registration/bidiphase.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44
import numpy as np
55
from numpy import fft
6+
import torch
67

78

89
def compute(frames: np.ndarray) -> int:
@@ -60,8 +61,16 @@ def shift(frames: np.ndarray, bidiphase: int) -> None:
6061
frames : np.ndarray
6162
The input frames with odd lines shifted.
6263
"""
64+
# The source and destination slices overlap. numpy makes a temporary copy
65+
# for overlapping assignments, but torch.Tensor.copy_ does not, so on a
66+
# torch tensor the in-place assignment reads already-overwritten pixels
67+
# and corrupts the odd lines. Copy the source first for both array types.
6368
if bidiphase > 0:
64-
frames[:, 1::2, bidiphase:] = frames[:, 1::2, :-bidiphase]
69+
src = frames[:, 1::2, :-bidiphase]
70+
src = src.clone() if isinstance(frames, torch.Tensor) else src.copy()
71+
frames[:, 1::2, bidiphase:] = src
6572
elif bidiphase < 0:
66-
frames[:, 1::2, :bidiphase] = frames[:, 1::2, -bidiphase:]
73+
src = frames[:, 1::2, -bidiphase:]
74+
src = src.clone() if isinstance(frames, torch.Tensor) else src.copy()
75+
frames[:, 1::2, :bidiphase] = src
6776
return frames

0 commit comments

Comments
 (0)