diff --git a/zetastitcher/fuse/fuse.py b/zetastitcher/fuse/fuse.py index b7cefb2..ab42c59 100644 --- a/zetastitcher/fuse/fuse.py +++ b/zetastitcher/fuse/fuse.py @@ -68,7 +68,7 @@ def squircle_alpha(height, width): return squircle -def fuse_queue(q, dest, frame_shape, debug=False): +def fuse_queue(q, dest, frame_shape, weighting_mode="squircle_alpha", debug=False): """Fuse a queue of images along Y, optionally applying padding. Parameters @@ -87,6 +87,9 @@ def fuse_queue(q, dest, frame_shape, debug=False): Shape of a stack plane (XY). dest : :class:`numpy.ndarray` Destination array. + weighting_mode : str + Weighting mode, defines the weighting window used to fuse overlapping slices. + Currently only ``squircle_alpha`` and ``none`` are supported. debug: bool Whether to overlay debug information (tile edges and numbers). """ @@ -113,7 +116,12 @@ def fuse_queue(q, dest, frame_shape, debug=False): z = np.unique(z) z = np.sort(z) - xy_weights = squircle_alpha(*frame_shape) + if weighting_mode == "squircle_alpha": + xy_weights = squircle_alpha(*frame_shape) + elif weighting_mode == "none": + xy_weights = np.ones(frame_shape) + else: + raise ValueError("Unknown weighting mode: {}".format(weighting_mode)) z_list = list(zip(z, z[1::])) try: @@ -135,8 +143,8 @@ def fuse_queue(q, dest, frame_shape, debug=False): area = width * height if not area: continue - - w = squircle_alpha(*frame_shape)[:height, :width] + + w = xy_weights[:height, :width] if row.X_from == 0: w = np.fliplr(w) diff --git a/zetastitcher/fuse/virtual_fused_volume.py b/zetastitcher/fuse/virtual_fused_volume.py index 0a116e1..ac97b43 100644 --- a/zetastitcher/fuse/virtual_fused_volume.py +++ b/zetastitcher/fuse/virtual_fused_volume.py @@ -48,7 +48,7 @@ class VirtualFusedVolume: ('0100_0000.tiff', (slice(40, 41, 1), slice(1000, 1500, 1), slice(0, 453, 1))), ] """ - def __init__(self, file_or_matrix): + def __init__(self, file_or_matrix, weighting_mode: str = 'squircle_alpha'): if isinstance(file_or_matrix, str): self.path, _ = os.path.split(file_or_matrix) self.fm = FileMatrix(file_or_matrix) @@ -78,7 +78,10 @@ def __init__(self, file_or_matrix): self.nchannels = f.nchannels self.squeeze_enabled = True - + self.weighting_mode = weighting_mode + if self.weighting_mode not in ['squircle_alpha', 'none']: + raise ValueError('Invalid weighting mode: {}'.format(self.weighting_mode)) + @property def overlay_debug_enabled(self): """Whether to overlay debug information (tile edges and numbers). @@ -229,6 +232,7 @@ def __getitem__(self, item): args=(q, fused, self.temp_shape[-2::]), kwargs={ 'debug': self._debug, + 'weighting_mode': self.weighting_mode, } ) t.start() diff --git a/zetastitcher/io/inputfile.py b/zetastitcher/io/inputfile.py index 9929c04..34473e6 100644 --- a/zetastitcher/io/inputfile.py +++ b/zetastitcher/io/inputfile.py @@ -56,21 +56,46 @@ def __getitem__(self, item): step = item[0].step else: raise TypeError("Invalid type: {}".format(type(item[0]))) + try: + a = self.zslice(start, stop, step) - a = self.zslice(start, stop, step) + if not a.size: + return a - if not a.size: - return a + if item[0] is not Ellipsis: + myitem[0] = slice(None) - if item[0] is not Ellipsis: - myitem[0] = slice(None) + a = a[tuple(myitem)] + except np.core._exceptions._ArrayMemoryError: + z_start, z_stop, z_step, z_width = self._slice_to_idxs(myitem[0],0) + y_start, y_stop, y_step, y_width = self._slice_to_idxs(myitem[1],1) + x_start, x_stop, x_step, x_width = self._slice_to_idxs(myitem[2],2) + a = None + for idx, i in enumerate(range(z_start, z_stop, z_step)): + frame = self.zslice_idx(i)[0] + if a is None: + a = np.zeros((z_width, y_width, x_width), dtype=self.dtype) + a[slice(idx,idx+1,1), myitem[1], myitem[2]] = frame[myitem[1], myitem[2]] - a = a[tuple(myitem)] + #raise MemoryError('Not enough memory to load the requested data') if self.squeeze: a = np.squeeze(a) return a + def _slice_to_idxs(self, _slice, idx=0): + start = _slice.start if _slice.start is not None else 0 + if start < 0: + start += self.shape[idx] + stop = _slice.stop if _slice.stop is not None else self.shape[idx] + if stop < 0: + stop += self.shape[idx] + step = _slice.step if _slice.step is not None else 1 + slice_width = (stop - start) // step + + return start, stop, step, slice_width + + @property def channel(self): return self._channel