def testBasic(self): start = TinyVector([10, 100, 200, 300, 1]) stop = TinyVector([11, 150, 300, 500, 3]) image_shape = [20, 152, 500, 500, 10] sigma = 3.1 window = 2 enlarge_axes = (False, True, True, True, False) enlarged_start, enlarged_stop = enlargeRoiForHalo(start, stop, image_shape, sigma, window, enlarge_axes ) full_halo_width = numpy.ceil(sigma*window) # Non-enlarged axes should remain the same assert (enlarged_start[[0,4]] == (start[0], start[4])).all(), \ "{} == {}".format( enlarged_start[[0,4]], (start[0], start[4]) ) assert (enlarged_stop[[0,4]] == (stop[0], stop[4])).all(), \ "{} == {}".format( enlarged_stop[[0,4]], (stop[0], stop[4]) ) # The start coord isn't close to the image border, so the halo should be full-sized on the start side assert (enlarged_start[1:4] == numpy.array(start)[1:4] - full_halo_width).all() # The stop coord is close to the image border in some dimensions, # so some axes couldn't be expanded by the full halo width. assert enlarged_stop[1] == 152 assert enlarged_stop[2] == stop[2] + full_halo_width assert enlarged_stop[3] == 500
def _getInputComputeRois(self, roi): shape = self.Input.meta.shape start = numpy.asarray(roi.start) stop = numpy.asarray(roi.stop) n = len(stop) spatStart = [roi.start[i] for i in range(n) if shape[i] > 1] spatStop = [roi.stop[i] for i in range(n) if shape[i] > 1] sigma = [0] + map(self._sigmas.get, 'xyz') + [0] spatialRoi = (spatStart, spatStop) inputSpatialRoi = enlargeRoiForHalo(roi.start, roi.stop, shape, sigma, window=2.0) # Determine the roi within the input data we're going to request inputRoiOffset = roi.start - inputSpatialRoi[0] computeRoi = [inputRoiOffset, inputRoiOffset + stop - start] for i in (0, 1): computeRoi[i] = [computeRoi[i][j] for j in range(n) if shape[j] > 1 and j not in (0, 4)] # make sure that vigra understands our integer types computeRoi = (tuple(map(int, computeRoi[0])), tuple(map(int, computeRoi[1]))) inputRoi = (list(inputSpatialRoi[0]), list(inputSpatialRoi[1])) return inputRoi, computeRoi
def _collect_blocks(self, image_slot, label_slot, block_slicings): model = self.ModelSession.value image_data_blocks = [] label_data_blocks = [] block_ids = [] for block_slicing in block_slicings: # Get labels block_label_roi = sliceToRoi(block_slicing, label_slot.meta.shape) block_label_data = label_slot(*block_label_roi).wait() bb_roi_within_block = numpy.array([[0] * len(block_label_data.shape), list(block_label_data.shape)]) block_label_bb_roi = bb_roi_within_block + block_label_roi[0] # Ask for the halo needed by the classifier axiskeys = image_slot.meta.getAxisKeys() halo_shape = model.get_halo(axiskeys) assert len(halo_shape) == len(block_label_roi[0]) assert halo_shape[ -1] == 0, "Didn't expect a non-zero halo for channel dimension." # Expand block by halo, but keep clipped to image bounds padded_label_roi, bb_roi_within_padded = enlargeRoiForHalo( *block_label_bb_roi, shape=label_slot.meta.shape, sigma=halo_shape, window=1, return_result_roi=True) # Copy labels to new array, which has size == bounding-box + halo padded_label_data = numpy.zeros( padded_label_roi[1] - padded_label_roi[0], label_slot.meta.dtype) padded_label_data[roiToSlice( *bb_roi_within_padded)] = block_label_data[roiToSlice( *bb_roi_within_block)] padded_image_roi = numpy.array(padded_label_roi) assert (padded_image_roi[:, -1] == [0, 1]).all() num_channels = image_slot.meta.shape[-1] padded_image_roi[:, -1] = [0, num_channels] # Ensure the results are plain ndarray, not VigraArray, # which some classifiers might have trouble with. padded_image_data = numpy.asarray( image_slot(*padded_image_roi).wait()) image_data_blocks.append(padded_image_data) label_data_blocks.append(padded_label_data) block_ids.append( tuple( int(block_label_bb_roi[0][i]) for i, key in enumerate(axiskeys) if key != "c")) return image_data_blocks, label_data_blocks, block_ids
def execute(self, slot, subindex, roi, result): sigma = 3.0 roi_with_halo, result_roi = enlargeRoiForHalo( roi.start, roi.stop, self.Input.meta.shape, sigma, return_result_roi=True ) start, stop = roi_with_halo newroi = SubRegion(self.Input, start=start, stop=stop) data = self.Input.get(newroi).wait() time.sleep(self.delay) result[:] = data[roiToSlice(*result_roi)]
def execute(self, slot, subindex, roi, result): sigma = 3.0 roi_with_halo, result_roi = enlargeRoiForHalo( roi.start, roi.stop, self.Input.meta.shape, sigma, return_result_roi=True ) start, stop = roi_with_halo newroi = SubRegion(self.Input, start=start, stop=stop) data = self.Input.get(newroi).wait() time.sleep(self.delay) result[:] = data[roiToSlice(*result_roi)]
def _getInputComputeRois(self, roi): axiskeys = self.Input.meta.getAxisKeys() spatialkeys = [k for k in axiskeys if k in 'zyx'] sigma = list(map(self._sigmas.get, spatialkeys)) inputSpatialShape = self.Input.meta.getTaggedShape() spatialRoi = (TinyVector(roi.start), TinyVector(roi.stop)) tIndex = None cIndex = None zIndex = None if 'c' in inputSpatialShape: del inputSpatialShape['c'] cIndex = axiskeys.index('c') if 't' in list(inputSpatialShape.keys()): assert inputSpatialShape['t'] == 1 tIndex = axiskeys.index('t') if 'z' in list( inputSpatialShape.keys()) and inputSpatialShape['z'] == 1: #2D image, avoid kernel longer than line exception del inputSpatialShape['z'] zIndex = axiskeys.index('z') indices = [tIndex, cIndex, zIndex] indices = sorted(indices, reverse=True) for ind in indices: if ind: spatialRoi[0].pop(ind) spatialRoi[1].pop(ind) inputSpatialRoi = enlargeRoiForHalo(spatialRoi[0], spatialRoi[1], list(inputSpatialShape.values()), sigma, window=2.0) # Determine the roi within the input data we're going to request inputRoiOffset = spatialRoi[0] - inputSpatialRoi[0] computeRoi = (inputRoiOffset, inputRoiOffset + spatialRoi[1] - spatialRoi[0]) # For some reason, vigra.filters.gaussianSmoothing will raise an exception if this parameter doesn't have the correct integer type. # (for example, if we give it as a numpy.ndarray with dtype=int64, we get an error) computeRoi = (tuple(map(int, computeRoi[0])), tuple(map(int, computeRoi[1]))) inputRoi = (list(inputSpatialRoi[0]), list(inputSpatialRoi[1])) for ind in reversed(indices): if ind: inputRoi[0].insert(ind, 0) inputRoi[1].insert(ind, 1) return inputRoi, computeRoi
def _getInputComputeRois(self, roi): axiskeys = self.Input.meta.getAxisKeys() spatialkeys = filter( lambda k: k in 'xyz', axiskeys ) sigma = map( self._sigmas.get, spatialkeys ) inputSpatialShape = self.Input.meta.getTaggedShape() spatialRoi = ( TinyVector(roi.start), TinyVector(roi.stop) ) tIndex = None cIndex = None zIndex = None if 'c' in inputSpatialShape: del inputSpatialShape['c'] cIndex = axiskeys.index('c') if 't' in inputSpatialShape.keys(): assert inputSpatialShape['t'] == 1 tIndex = axiskeys.index('t') if 'z' in inputSpatialShape.keys() and inputSpatialShape['z']==1: #2D image, avoid kernel longer than line exception del inputSpatialShape['z'] zIndex = axiskeys.index('z') indices = [tIndex, cIndex, zIndex] indices = sorted(indices, reverse=True) for ind in indices: if ind: spatialRoi[0].pop(ind) spatialRoi[1].pop(ind) inputSpatialRoi = enlargeRoiForHalo(spatialRoi[0], spatialRoi[1], inputSpatialShape.values(), sigma, window=2.0) # Determine the roi within the input data we're going to request inputRoiOffset = spatialRoi[0] - inputSpatialRoi[0] computeRoi = (inputRoiOffset, inputRoiOffset + spatialRoi[1] - spatialRoi[0]) # For some reason, vigra.filters.gaussianSmoothing will raise an exception if this parameter doesn't have the correct integer type. # (for example, if we give it as a numpy.ndarray with dtype=int64, we get an error) computeRoi = ( tuple(map(int, computeRoi[0])), tuple(map(int, computeRoi[1])) ) inputRoi = (list(inputSpatialRoi[0]), list(inputSpatialRoi[1])) for ind in reversed(indices): if ind: inputRoi[0].insert( ind, 0 ) inputRoi[1].insert( ind, 1 ) return inputRoi, computeRoi
def _enlarge_roi_for_halo(self, start, stop): """ Given a roi of INPUT coordinates (3D+c, not 3D+ij), enlarge it with an appropriate halo. Also return the "result roi". (See enlargeRoiForHalo() docs for details.) """ assert len(self.Input.meta.shape) == 4, "Data must be exactly 3D+c (no time axis)" assert self.Input.meta.getAxisKeys()[-1] == 'c' spatial_axes = (True, True, True, False) # don't enlarge channel roi enlarged_roi, result_roi = enlargeRoiForHalo( start, stop, self.Input.meta.shape, self.Sigma.value, window=self.WINDOW_SIZE, enlarge_axes=spatial_axes, return_result_roi=True ) return enlarged_roi, result_roi
def _enlarge_roi_for_halo(self, start, stop): """ Given a roi of INPUT coordinates (3D+c, not 3D+ij), enlarge it with an appropriate halo. Also return the "result roi". (See enlargeRoiForHalo() docs for details.) """ assert len(self.Input.meta.shape) == 4, "Data must be exactly 3D+c (no time axis)" assert self.Input.meta.getAxisKeys()[-1] == 'c' spatial_axes = (True, True, True, False) # don't enlarge channel roi enlarged_roi, result_roi = enlargeRoiForHalo( start, stop, self.Input.meta.shape, self.Sigma.value, window=self.WINDOW_SIZE, enlarge_axes=spatial_axes, return_result_roi=True ) return enlarged_roi, result_roi
def propagateDirty(self, slot, subindex, rroi): # If some input we don't know about is dirty (i.e. we are subclassed by an operator with extra inputs), # then mark the entire output dirty. This is the correct behavior for e.g. 'sigma' inputs. out_dirty = slice(None) # Check for proper name because subclasses may define extra inputs. # (but decline to override notifyDirty) if slot is self.Input: out_dirty = list(rroi.toSlice()) out_dirty[1] = slice( None ) # todo: map dirty input channels to dirty output channels if self.invalid_z or self.ComputeIn2d.value: axes2enlarge = [0, 0, 0, 1, 1] else: axes2enlarge = [0, 0, 1, 1, 1] output_shape = self.Output.meta.shape rroi = roi.sliceToRoi(out_dirty, output_shape) out_dirty = roi.roiToSlice( *roi.enlargeRoiForHalo(rroi[0], rroi[1], output_shape, self.max_sigma, window=self.window_size_smoother, enlarge_axes=axes2enlarge)) elif slot is self.ComputeIn2d: if self.invalid_z: # Output is computed in 2D anyway due to a small z dimension if not self.ComputeIn2d.value: logger.warning( f'{self.name}: filtering in 2d for {self.filter_kwargs} (z dimension too small)' ) return self.Output.setDirty(out_dirty)
def execute(self, slot, subindex, slot_roi, target): assert slot == self.Features or slot == self.Output if slot == self.Features: feature_slice = roiToSlice(slot_roi.start, slot_roi.stop) index = subindex[0] feature_slice = list(feature_slice) # Translate channel slice of this feature to the channel slice of the output slot. output_channel_offset = self.featureOutputChannels[index][0] feature_slice[1] = slice( output_channel_offset + feature_slice[1].start, output_channel_offset + feature_slice[1].stop ) slot_roi = SubRegion(self.Output, pslice=feature_slice) # Get output slot region for this channel return self.execute(self.Output, (), slot_roi, target) elif slot == self.Output: # Correlation of variable 'families' representing reference frames: # ______________________________ # | input/output frame | input/output shape given by slots # | _________________________ | # | | smooth frame | | pre-smoothing op needs halo around filter roi # | | ____________________ | | # | | |filter frame | | | filter needs halo around target roi # | | | _______________ | | | # | | | | target frame | | | | target is given by output_roi # note: The 'full_' variable prefix refers to the full 5D shape (tczyx), without 'full_' variables mostly # refer to the 3D space subregion (zyx) full_output_slice = slot_roi.toSlice() logger.debug(f"OpPixelFeaturesPresmoothed: request {slot_roi.pprint()}") assert (slot_roi.stop <= self.Output.meta.shape).all() full_output_shape = self.Output.meta.shape full_output_start, full_output_stop = sliceToRoi(full_output_slice, full_output_shape) assert len(full_output_shape) == 5 if all(self.ComputeIn2d.value): # todo: check for this particular slice axes2enlarge = (0, 1, 1) else: axes2enlarge = (1, 1, 1) output_shape = full_output_shape[2:] output_start = full_output_start[2:] output_stop = full_output_stop[2:] axistags = self.Output.meta.axistags target = target.view(vigra.VigraArray) target.axistags = copy.copy(axistags) # filter roi in input frame # sigma = 0.7, because the features receive a pre-smoothed array and don't need much of a neighborhood input_filter_start, input_filter_stop = roi.enlargeRoiForHalo( output_start, output_stop, output_shape, 0.7, self.WINDOW_SIZE, enlarge_axes=axes2enlarge ) # smooth roi in input frame input_smooth_start, input_smooth_stop = roi.enlargeRoiForHalo( input_filter_start, input_filter_stop, output_shape, self.max_sigma, self.WINDOW_SIZE, enlarge_axes=axes2enlarge, ) # target roi in filter frame filter_target_start = roi.TinyVector(output_start - input_filter_start) filter_target_stop = roi.TinyVector(output_stop - input_filter_start) # filter roi in smooth frame smooth_filter_start = roi.TinyVector(input_filter_start - input_smooth_start) smooth_filter_stop = roi.TinyVector(input_filter_stop - input_smooth_start) filter_target_slice = roi.roiToSlice(filter_target_start, filter_target_stop) input_smooth_slice = roi.roiToSlice(input_smooth_start, input_smooth_stop) # pre-smooth for all requested time slices and all channels full_input_smooth_slice = (full_output_slice[0], slice(None), *input_smooth_slice) req = self.Input[full_input_smooth_slice] source = req.wait() req.clean() req.destination = None if source.dtype != numpy.float32: sourceF = source.astype(numpy.float32) try: source.resize((1,), refcheck=False) except Exception: pass del source source = sourceF sourceV = source.view(vigra.VigraArray) sourceV.axistags = copy.copy(self.Input.meta.axistags) dimCol = len(self.scales) dimRow = self.matrix.shape[0] presmoothed_source = [None] * dimCol source_smooth_shape = tuple(smooth_filter_stop - smooth_filter_start) full_source_smooth_shape = ( full_output_stop[0] - full_output_start[0], self.Input.meta.shape[1], ) + source_smooth_shape try: for j in range(dimCol): for i in range(dimRow): if self.matrix[i, j]: # There is at least one filter op with this scale break else: # There is no filter op at this scale continue if self.scales[j] > 1.0: tempSigma = math.sqrt(self.scales[j] ** 2 - 1.0) else: tempSigma = self.scales[j] presmoothed_source[j] = numpy.ndarray(full_source_smooth_shape, numpy.float32) droi = ( (0, *tuple(smooth_filter_start._asint())), (sourceV.shape[1], *tuple(smooth_filter_stop._asint())), ) for i, vsa in enumerate(sourceV.timeIter()): presmoothed_source[j][i, ...] = self._computeGaussianSmoothing( vsa, tempSigma, droi, in2d=self.ComputeIn2d.value[j] ) except RuntimeError as e: if "kernel longer than line" in str(e): raise RuntimeError( "Feature computation error:\nYour image is too small to apply a filter with " f"sigma={self.scales[j]:.1f}. Please select features with smaller sigmas." ) else: raise e del sourceV try: source.resize((1,), refcheck=False) except ValueError: # Sometimes this fails, but that's okay. logger.debug("Failed to free array memory.") del source cnt = 0 written = 0 closures = [] # connect individual operators for i in range(dimRow): for j in range(dimCol): if self.matrix[i, j]: oslot = self.featureOps[i][j].Output req = None slices = oslot.meta.shape[1] if ( cnt + slices >= slot_roi.start[1] and slot_roi.start[1] - cnt < slices and slot_roi.start[1] + written < slot_roi.stop[1] ): begin = 0 if cnt < slot_roi.start[1]: begin = slot_roi.start[1] - cnt end = slices if cnt + end > slot_roi.stop[1]: end = slot_roi.stop[1] - cnt # feature slice in output frame feature_slice = (slice(None), slice(written, written + end - begin)) + (slice(None),) * 3 subtarget = target[feature_slice] # readjust the roi for the new source array full_filter_target_slice = [full_output_slice[0], slice(begin, end), *filter_target_slice] filter_target_roi = SubRegion(oslot, pslice=full_filter_target_slice) closure = partial( oslot.operator.execute, oslot, (), filter_target_roi, subtarget, sourceArray=presmoothed_source[j], ) closures.append(closure) written += end - begin cnt += slices pool = RequestPool() for c in closures: pool.request(c) pool.wait() pool.clean() for i in range(len(presmoothed_source)): if presmoothed_source[i] is not None: try: presmoothed_source[i].resize((1,)) except Exception: presmoothed_source[i] = None
def execute(self, slot, subindex, slot_roi, target): assert slot == self.Features or slot == self.Output if slot == self.Features: feature_slice = roiToSlice(slot_roi.start, slot_roi.stop) index = subindex[0] feature_slice = list(feature_slice) # Translate channel slice of this feature to the channel slice of the output slot. output_channel_offset = self.featureOutputChannels[index][0] feature_slice[1] = slice( output_channel_offset + feature_slice[1].start, output_channel_offset + feature_slice[1].stop) slot_roi = SubRegion(self.Output, pslice=feature_slice) # Get output slot region for this channel return self.execute(self.Output, (), slot_roi, target) elif slot == self.Output: # Correlation of variable 'families' representing reference frames: # ______________________________ # | input/output frame | input/output shape given by slots # | _________________________ | # | | smooth frame | | pre-smoothing op needs halo around filter roi # | | ____________________ | | # | | |filter frame | | | filter needs halo around target roi # | | | _______________ | | | # | | | | target frame | | | | target is given by output_roi # note: The 'full_' variable prefix refers to the full 5D shape (tczyx), without 'full_' variables mostly # refer to the 3D space subregion (zyx) full_output_slice = slot_roi.toSlice() logger.debug( f"OpPixelFeaturesPresmoothed: request {slot_roi.pprint()}") assert (slot_roi.stop <= self.Output.meta.shape).all() full_output_shape = self.Output.meta.shape full_output_start, full_output_stop = sliceToRoi( full_output_slice, full_output_shape) assert len(full_output_shape) == 5 if all(self.ComputeIn2d.value ): # todo: check for this particular slice axes2enlarge = (0, 1, 1) else: axes2enlarge = (1, 1, 1) output_shape = full_output_shape[2:] output_start = full_output_start[2:] output_stop = full_output_stop[2:] axistags = self.Output.meta.axistags target = target.view(vigra.VigraArray) target.axistags = copy.copy(axistags) # filter roi in input frame # sigma = 0.7, because the features receive a pre-smoothed array and don't need much of a neighborhood input_filter_start, input_filter_stop = roi.enlargeRoiForHalo( output_start, output_stop, output_shape, 0.7, self.WINDOW_SIZE, enlarge_axes=axes2enlarge) # smooth roi in input frame input_smooth_start, input_smooth_stop = roi.enlargeRoiForHalo( input_filter_start, input_filter_stop, output_shape, self.max_sigma, self.WINDOW_SIZE, enlarge_axes=axes2enlarge, ) # target roi in filter frame filter_target_start = roi.TinyVector(output_start - input_filter_start) filter_target_stop = roi.TinyVector(output_stop - input_filter_start) # filter roi in smooth frame smooth_filter_start = roi.TinyVector(input_filter_start - input_smooth_start) smooth_filter_stop = roi.TinyVector(input_filter_stop - input_smooth_start) filter_target_slice = roi.roiToSlice(filter_target_start, filter_target_stop) input_smooth_slice = roi.roiToSlice(input_smooth_start, input_smooth_stop) # pre-smooth for all requested time slices and all channels full_input_smooth_slice = (full_output_slice[0], slice(None), *input_smooth_slice) req = self.Input[full_input_smooth_slice] source = req.wait() req.clean() req.destination = None if source.dtype != numpy.float32: sourceF = source.astype(numpy.float32) try: source.resize((1, ), refcheck=False) except Exception: pass del source source = sourceF sourceV = source.view(vigra.VigraArray) sourceV.axistags = copy.copy(self.Input.meta.axistags) dimCol = len(self.scales) dimRow = self.matrix.shape[0] presmoothed_source = [None] * dimCol source_smooth_shape = tuple(smooth_filter_stop - smooth_filter_start) full_source_smooth_shape = ( full_output_stop[0] - full_output_start[0], self.Input.meta.shape[1], ) + source_smooth_shape try: for j in range(dimCol): for i in range(dimRow): if self.matrix[i, j]: # There is at least one filter op with this scale break else: # There is no filter op at this scale continue if self.scales[j] > 1.0: tempSigma = math.sqrt(self.scales[j]**2 - 1.0) else: tempSigma = self.scales[j] presmoothed_source[j] = numpy.ndarray( full_source_smooth_shape, numpy.float32) droi = ( (0, *tuple(smooth_filter_start._asint())), (sourceV.shape[1], *tuple(smooth_filter_stop._asint())), ) for i, vsa in enumerate(sourceV.timeIter()): presmoothed_source[j][ i, ...] = self._computeGaussianSmoothing( vsa, tempSigma, droi, in2d=self.ComputeIn2d.value[j]) except RuntimeError as e: if "kernel longer than line" in str(e): raise RuntimeError( "Feature computation error:\nYour image is too small to apply a filter with " f"sigma={self.scales[j]:.1f}. Please select features with smaller sigmas." ) else: raise e del sourceV try: source.resize((1, ), refcheck=False) except ValueError: # Sometimes this fails, but that's okay. logger.debug("Failed to free array memory.") del source cnt = 0 written = 0 closures = [] # connect individual operators for i in range(dimRow): for j in range(dimCol): if self.matrix[i, j]: oslot = self.featureOps[i][j].Output req = None slices = oslot.meta.shape[1] if (cnt + slices >= slot_roi.start[1] and slot_roi.start[1] - cnt < slices and slot_roi.start[1] + written < slot_roi.stop[1]): begin = 0 if cnt < slot_roi.start[1]: begin = slot_roi.start[1] - cnt end = slices if cnt + end > slot_roi.stop[1]: end = slot_roi.stop[1] - cnt # feature slice in output frame feature_slice = (slice(None), slice( written, written + end - begin)) + (slice(None), ) * 3 subtarget = target[feature_slice] # readjust the roi for the new source array full_filter_target_slice = [ full_output_slice[0], slice(begin, end), *filter_target_slice ] filter_target_roi = SubRegion( oslot, pslice=full_filter_target_slice) closure = partial( oslot.operator.execute, oslot, (), filter_target_roi, subtarget, sourceArray=presmoothed_source[j], ) closures.append(closure) written += end - begin cnt += slices pool = RequestPool() for c in closures: pool.request(c) pool.wait() pool.clean() for i in range(len(presmoothed_source)): if presmoothed_source[i] is not None: try: presmoothed_source[i].resize((1, )) except Exception: presmoothed_source[i] = None
def execute(self, slot, subindex, roi, result): classifier_factory = self.ClassifierFactory.value assert issubclass(type(classifier_factory), LazyflowPixelwiseClassifierFactoryABC), \ "Factory is of type {}, which does not satisfy the LazyflowPixelwiseClassifierFactoryABC interface."\ "".format( type(classifier_factory) ) # Accumulate all non-zero blocks of each image into lists label_data_blocks = [] image_data_blocks = [] for image_slot, label_slot, nonzero_block_slot in zip( self.Images, self.Labels, self.nonzeroLabelBlocks): block_slicings = nonzero_block_slot.value for block_slicing in block_slicings: # Get labels block_label_roi = sliceToRoi(block_slicing, label_slot.meta.shape) block_label_data = label_slot(*block_label_roi).wait() # Shrink roi to bounding box of actual label pixels bb_roi_within_block = nonzero_bounding_box(block_label_data) block_label_bb_roi = bb_roi_within_block + block_label_roi[0] # Double-check that there is at least 1 non-zero label in the block. if (block_label_bb_roi[1] > block_label_bb_roi[0]).all(): # Ask for the halo needed by the classifier axiskeys = image_slot.meta.getAxisKeys() halo_shape = classifier_factory.get_halo_shape(axiskeys) assert len(halo_shape) == len(block_label_roi[0]) assert halo_shape[ -1] == 0, "Didn't expect a non-zero halo for channel dimension." # Expand block by halo, but keep clipped to image bounds padded_label_roi, bb_roi_within_padded = enlargeRoiForHalo( *block_label_bb_roi, shape=label_slot.meta.shape, sigma=halo_shape, window=1, return_result_roi=True) # Copy labels to new array, which has size == bounding-box + halo padded_label_data = numpy.zeros( padded_label_roi[1] - padded_label_roi[0], label_slot.meta.dtype) padded_label_data[roiToSlice( *bb_roi_within_padded)] = block_label_data[roiToSlice( *bb_roi_within_block)] padded_image_roi = numpy.array(padded_label_roi) assert (padded_image_roi[:, -1] == [0, 1]).all() num_channels = image_slot.meta.shape[-1] padded_image_roi[:, -1] = [0, num_channels] # Ensure the results are plain ndarray, not VigraArray, # which some classifiers might have trouble with. padded_image_data = numpy.asarray( image_slot(*padded_image_roi).wait()) label_data_blocks.append(padded_label_data) image_data_blocks.append(padded_image_data) if len(image_data_blocks) == 0: result[0] = None else: channel_names = self.Images[0].meta.channel_names axistags = self.Images[0].meta.axistags logger.debug("Training new pixelwise classifier: {}".format( classifier_factory.description)) classifier = classifier_factory.create_and_train_pixelwise( image_data_blocks, label_data_blocks, axistags, channel_names) result[0] = classifier if classifier is not None: assert issubclass(type(classifier), LazyflowPixelwiseClassifierABC), \ "Classifier is of type {}, which does not satisfy the LazyflowPixelwiseClassifierABC interface."\ "".format( type(classifier) )
def execute(self, slot, subindex, rroi, result, sourceArray=None): assert len(subindex) == self.Output.level == 0 key = roiToSlice(rroi.start, rroi.stop) kwparams = {} for islot in list(self.inputs.values()): if islot.name != "Input": kwparams[islot.name] = islot.value if "sigma" in self.inputs: sigma = self.inputs["sigma"].value elif "scale" in self.inputs: sigma = self.inputs["scale"].value elif "sigma0" in self.inputs: sigma = self.inputs["sigma0"].value elif "innerScale" in self.inputs: sigma = self.inputs["innerScale"].value windowSize = 3.5 if self.supportsWindow: kwparams['window_size']=self.window_size_feature windowSize = self.window_size_smoother largestSigma = max(0.7,sigma) #we use 0.7 as an approximation of not doing any smoothing #smoothing was already applied previously shape = self.outputs["Output"].meta.shape axistags = self.inputs["Input"].meta.axistags hasChannelAxis = self.inputs["Input"].meta.axistags.axisTypeCount(vigra.AxisType.Channels) channelAxis=self.inputs["Input"].meta.axistags.index('c') hasTimeAxis = self.inputs["Input"].meta.axistags.axisTypeCount(vigra.AxisType.Time) timeAxis=self.inputs["Input"].meta.axistags.index('t') zAxis = self.inputs["Input"].meta.axistags.index('z') subkey = popFlagsFromTheKey(key,axistags,'c') subshape=popFlagsFromTheKey(shape,axistags,'c') at2 = copy.copy(axistags) at2.dropChannelAxis() subshape=popFlagsFromTheKey(subshape,at2,'t') subkey = popFlagsFromTheKey(subkey,at2,'t') oldstart, oldstop = roi.sliceToRoi(key, shape) start, stop = roi.sliceToRoi(subkey,subkey) if sourceArray is not None and zAxis<len(axistags): if timeAxis>zAxis: subshape[at2.index('z')]=sourceArray.shape[zAxis] else: subshape[at2.index('z')-1]=sourceArray.shape[zAxis] newStart, newStop = roi.enlargeRoiForHalo(start, stop, subshape, largestSigma, window = windowSize) readKey = roi.roiToSlice(newStart, newStop) writeNewStart = start - newStart writeNewStop = writeNewStart + stop - start if (writeNewStart == 0).all() and (newStop == writeNewStop).all(): fullResult = True else: fullResult = False writeKey = roi.roiToSlice(writeNewStart, writeNewStop) writeKey = list(writeKey) if timeAxis < channelAxis: writeKey.insert(channelAxis-1, slice(None,None,None)) else: writeKey.insert(channelAxis, slice(None,None,None)) writeKey = tuple(writeKey) #print writeKey channelsPerChannel = self.resultingChannels() if self.supportsRoi is False and largestSigma > 5: logger.warning(f"WARNING: operator {self.name} does not support roi!!") i2 = 0 for i in range(int(numpy.floor(1.0 * oldstart[channelAxis]/channelsPerChannel)),int(numpy.ceil(1.0 * oldstop[channelAxis]/channelsPerChannel))): newReadKey = list(readKey) #add channel and time axis if needed if hasTimeAxis: if channelAxis > timeAxis: newReadKey.insert(timeAxis, key[timeAxis]) else: newReadKey.insert(timeAxis-1, key[timeAxis]) if hasChannelAxis: newReadKey.insert(channelAxis, slice(i, i+1, None)) if sourceArray is None: req = self.inputs["Input"][newReadKey] t = req.wait() else: if hasChannelAxis: t = sourceArray[getAllExceptAxis(len(newReadKey),channelAxis,slice(i,i+1,None) )] else: fullkey = [slice(None, None, None)]*len(newReadKey) t = sourceArray[fullkey] t = numpy.require(t, dtype=self.inputDtype) t = t.view(vigra.VigraArray) t.axistags = copy.copy(axistags) t = t.insertChannelAxis() sourceBegin = 0 if oldstart[channelAxis] > i * channelsPerChannel: sourceBegin = oldstart[channelAxis] - i * channelsPerChannel sourceEnd = channelsPerChannel if oldstop[channelAxis] < (i+1) * channelsPerChannel: sourceEnd = channelsPerChannel - ((i+1) * channelsPerChannel - oldstop[channelAxis]) destBegin = i2 destEnd = i2 + sourceEnd - sourceBegin if channelsPerChannel>1: tkey=getAllExceptAxis(len(shape),channelAxis,slice(destBegin,destEnd,None)) resultArea = result[tkey] else: tkey=getAllExceptAxis(len(shape),channelAxis,slice(i2,i2+1,None)) resultArea = result[tkey] i2 += destEnd-destBegin supportsOut = self.supportsOut if (destEnd-destBegin != channelsPerChannel): supportsOut = False supportsOut = False #disable for now due to vigra crashes! #FIXME for step,image in enumerate(t.timeIter()): nChannelAxis = channelAxis - 1 if timeAxis > channelAxis or not hasTimeAxis: nChannelAxis = channelAxis twriteKey=getAllExceptAxis(image.ndim, nChannelAxis, slice(sourceBegin,sourceEnd,None)) if hasTimeAxis > 0: tresKey = getAllExceptAxis(resultArea.ndim, timeAxis, step) else: tresKey = slice(None, None,None) #print tresKey, twriteKey, resultArea.shape, temp.shape vres = resultArea[tresKey] if supportsOut: if self.supportsRoi: vroi = (tuple(writeNewStart._asint()), tuple(writeNewStop._asint())) try: vres = vres.view(vigra.VigraArray) vres.axistags = copy.copy(image.axistags) logger.debug( "FAST LANE {} {} {} {}".format( self.name, vres.shape, image[twriteKey].shape, vroi ) ) temp = self.vigraFilter(image[twriteKey], roi = vroi,out=vres, **kwparams) except: logger.error( "{} {} {} {}".format(self.name, image.shape, vroi, kwparams) ) raise else: try: temp = self.vigraFilter(image, **kwparams) except: logger.error( "{} {} {} {}".format(self.name, image.shape, vroi, kwparams) ) raise temp=temp[writeKey] else: if self.supportsRoi: vroi = (tuple(writeNewStart._asint()), tuple(writeNewStop._asint())) try: temp = self.vigraFilter(image, roi = vroi, **kwparams) except Exception as e: logger.error( "EXCEPT 2.1 {} {} {} {}".format( self.name, image.shape, vroi, kwparams ) ) traceback.print_exc(e) import sys sys.exit(1) else: try: temp = self.vigraFilter(image, **kwparams) except Exception as e: logger.error( "EXCEPT 2.2 {} {} {}".format( self.name, image.shape, kwparams ) ) traceback.print_exc(e) import sys sys.exit(1) temp=temp[writeKey] try: vres[:] = temp[twriteKey] except: logger.error( "EXCEPT3 {} {} {}".format( vres.shape, temp.shape, twriteKey ) ) logger.error( "EXCEPT3 {} {} {}".format( resultArea.shape, tresKey, twriteKey ) ) logger.error( "EXCEPT3 {} {} {}".format( step, t.shape, timeAxis ) ) raise
def execute(self, slot, subindex, roi, result): classifier_factory = self.ClassifierFactory.value assert issubclass(type(classifier_factory), LazyflowPixelwiseClassifierFactoryABC), \ "Factory is of type {}, which does not satisfy the LazyflowPixelwiseClassifierFactoryABC interface."\ "".format( type(classifier_factory) ) # Accumulate all non-zero blocks of each image into lists label_data_blocks = [] image_data_blocks = [] for image_slot, label_slot, nonzero_block_slot in zip(self.Images, self.Labels, self.nonzeroLabelBlocks): block_slicings = nonzero_block_slot.value for block_slicing in block_slicings: # Get labels block_label_roi = sliceToRoi( block_slicing, label_slot.meta.shape ) block_label_data = label_slot(*block_label_roi).wait() # Shrink roi to bounding box of actual label pixels bb_roi_within_block = nonzero_bounding_box(block_label_data) block_label_bb_roi = bb_roi_within_block + block_label_roi[0] # Double-check that there is at least 1 non-zero label in the block. if (block_label_bb_roi[1] > block_label_bb_roi[0]).all(): # Ask for the halo needed by the classifier axiskeys = image_slot.meta.getAxisKeys() halo_shape = classifier_factory.get_halo_shape(axiskeys) assert len(halo_shape) == len( block_label_roi[0] ) assert halo_shape[-1] == 0, "Didn't expect a non-zero halo for channel dimension." # Expand block by halo, but keep clipped to image bounds padded_label_roi, bb_roi_within_padded = enlargeRoiForHalo( *block_label_bb_roi, shape=label_slot.meta.shape, sigma=halo_shape, window=1, return_result_roi=True ) # Copy labels to new array, which has size == bounding-box + halo padded_label_data = numpy.zeros( padded_label_roi[1] - padded_label_roi[0], label_slot.meta.dtype ) padded_label_data[roiToSlice(*bb_roi_within_padded)] = block_label_data[roiToSlice(*bb_roi_within_block)] padded_image_roi = numpy.array( padded_label_roi ) assert (padded_image_roi[:, -1] == [0,1]).all() num_channels = image_slot.meta.shape[-1] padded_image_roi[:, -1] = [0, num_channels] # Ensure the results are plain ndarray, not VigraArray, # which some classifiers might have trouble with. padded_image_data = numpy.asarray( image_slot(*padded_image_roi).wait() ) label_data_blocks.append( padded_label_data ) image_data_blocks.append( padded_image_data ) if len(image_data_blocks) == 0: result[0] = None else: channel_names = self.Images[0].meta.channel_names axistags = self.Images[0].meta.axistags logger.debug("Training new pixelwise classifier: {}".format( classifier_factory.description )) classifier = classifier_factory.create_and_train_pixelwise( image_data_blocks, label_data_blocks, axistags, channel_names ) result[0] = classifier if classifier is not None: assert issubclass(type(classifier), LazyflowPixelwiseClassifierABC), \ "Classifier is of type {}, which does not satisfy the LazyflowPixelwiseClassifierABC interface."\ "".format( type(classifier) )
def execute(self, slot, subindex, output_roi, target, sourceArray=None): assert slot == self.Output # explanatory notes for variable 'families': # output_* : associated with Output slot # target_* : associated with target area inside of output, described by output_roi # input_* : associated with Input slot (same shape as Output slot, except for channels) # source_* : associated with source area inside of input, described by output_roi + halo # result_* : associated with the filtered source # # relations between variable 'families': (for further clarification) # TARGET is subregion of OUTPUT # SOURCE is subregion of INPUT (or from sourceArray) # TARGET area plus halo equals SOURCE area # applying filter to SOURCE yields RESULT # RESULT without halo is TARGET # note: The 'full_' variable prefix refers to the full 5D shape (tczyx), without 'full_' variables mostly # refer to the 3D space subregion (zyx) assert len(subindex) == self.Output.level == 0 if self.supports_roi is False and self.max_sigma > 5: logger.warning(f"WARNING: operator {self.name} does not support roi!!") key = roiToSlice(output_roi.start, output_roi.stop) full_output_shape = self.Output.meta.shape full_output_start, full_output_stop = roi.sliceToRoi(key, full_output_shape) if self.invalid_z or self.ComputeIn2d.value: axes2enlarge = (0, 1, 1) process_in_2d = True axistags = vigra.defaultAxistags("cyx") else: axes2enlarge = (1, 1, 1) process_in_2d = False axistags = vigra.defaultAxistags("czyx") output_shape = full_output_shape[2:] # without tc assert output_shape == self.Input.meta.shape[2:], (output_shape, self.Input.meta.shape[2:]) output_start = full_output_start[2:] output_stop = full_output_stop[2:] input_start, input_stop = roi.enlargeRoiForHalo( output_start, output_stop, output_shape, self.max_sigma, window=self.window_size_smoother, enlarge_axes=axes2enlarge, ) input_slice = roi.roiToSlice(input_start, input_stop) result_start = output_start - input_start result_stop = result_start + output_stop - output_start result_slice = roi.roiToSlice(result_start, result_stop) filter_kwargs = self.filter_kwargs def step(tstep, target_z_slice, full_input_slice, full_result_slice): if sourceArray is None: # no tmatter, if slices or indices are in 'full_input_slice', they will be converted to slices => 5d source = self.Input[full_input_slice].wait()[0] # => remove singleton t dimension if process_in_2d: source = source[:, 0] # if processing in 2d, remove singleton z dimension assert source.shape[0] == 1 # single channel axis for input else: assert sourceArray.shape[1] == self.Input.meta.shape[1] source = sourceArray[tstep, full_input_slice[1], ...] if process_in_2d: # eliminate singleton z dimension assert isinstance(target_z_slice, int) source = source[:, target_z_slice] # in 2d z is shared between source and target (like time) source = numpy.require(source, dtype=self.input_dtype) source = source.view(vigra.VigraArray) source.axistags = axistags supports_roi = self.supports_roi # in vigra the roi parameter does not support a channel roi if not WITH_FAST_FILTERS: if target_c_stop - target_c_start != self.resultingChannels(): supports_roi = False if supports_roi: if not WITH_FAST_FILTERS: # filter_roi without channel axis (not supported by vigra) filter_roi = roi.sliceToRoi(full_result_slice[1:], source.shape[1:]) if self.supports_out: try: subtarget = target[tstep, target_c_start:target_c_stop, target_z_slice].view(vigra.VigraArray) if process_in_2d: subtarget = subtarget[:, 0] subtarget.axistags = copy.copy(axistags) logger.debug( f"r o: {self.name} {source.shape} {full_result_slice} {subtarget.shape} {filter_kwargs}" ) self.filter_fn(source, roi=filter_roi, out=subtarget, **filter_kwargs) return except Exception: logger.error( f"r o: {self.name} {source.shape} {filter_roi} {subtarget.shape} {filter_kwargs} " f"{process_in_2d}" ) raise else: try: logger.debug(f"r : {self.name} {source.shape} {full_result_slice} {filter_kwargs}") result = self.filter_fn(source, roi=filter_roi, **filter_kwargs) except Exception: logger.error(f"r : {self.name} {source.shape} {target.shape} {filter_kwargs}") raise else: # note: support of 'out' gives no advantage, if no roi can be specified. The filter result (including a # halo) would not fit into the target (without a halo). # todo: implement 'no halo exception' of above note try: logger.debug(f" : {self.name} {source.shape} {filter_kwargs} {process_in_2d}") result = self.filter_fn(source, **filter_kwargs) except Exception: logger.error(f" : {self.name} {source.shape} {filter_kwargs} {process_in_2d}") raise result = result[full_result_slice] try: target[tstep, target_c_start:target_c_stop, target_z_slice] = result except Exception: logger.error(f"t : {target.shape} {target[tstep, target_c_start:target_c_stop].shape} {result.shape}") logger.error(f"tstep {tstep} c {target_c_start},{target_c_stop} z {target_z_slice} {result.shape}") raise resC = self.resultingChannels() for tstep, t in enumerate(range(full_output_start[0], full_output_stop[0])): target_c_stop = 0 for input_c in range( int(numpy.floor(full_output_start[1] / resC)), int(numpy.ceil(full_output_stop[1] / resC)) ): output_c_start = resC * input_c output_c_stop = resC * (input_c + 1) result_c_start = 0 result_c_stop = resC if output_c_start < full_output_start[1]: result_c_start = full_output_start[1] - output_c_start output_c_start = full_output_start[1] if output_c_stop > full_output_stop[1]: result_c_stop -= output_c_stop - full_output_stop[1] output_c_stop = full_output_stop[1] target_c_start = target_c_stop target_c_stop += result_c_stop - result_c_start result_c_slice = slice(result_c_start, result_c_stop) input_c_slice = slice(input_c, input_c + 1) if process_in_2d: for target_z, input_z in enumerate(range(input_start[0], input_stop[0])): step( tstep, target_z_slice=target_z, full_input_slice=(t, input_c_slice, input_z, *input_slice[1:]), full_result_slice=(result_c_slice, *result_slice[1:]), ) else: step( tstep, target_z_slice=slice(None), full_input_slice=(t, input_c_slice, *input_slice), full_result_slice=(result_c_slice, *result_slice), )
def execute(self, slot, subindex, rroi, result): assert slot == self.Features or slot == self.Output if slot == self.Features: key = roiToSlice(rroi.start, rroi.stop) index = subindex[0] key = list(key) channelIndex = self.Input.meta.axistags.index('c') # Translate channel slice to the correct location for the output slot. key[channelIndex] = slice(self.featureOutputChannels[index][0] + key[channelIndex].start, self.featureOutputChannels[index][0] + key[channelIndex].stop) rroi = SubRegion(self.Output, pslice=key) # Get output slot region for this channel return self.execute(self.Output, (), rroi, result) elif slot == self.outputs["Output"]: key = rroi.toSlice() logger.debug("OpPixelFeaturesPresmoothed: request %s" % (rroi.pprint(),)) cnt = 0 written = 0 assert (rroi.stop<=self.outputs["Output"].meta.shape).all() flag = 'c' channelAxis=self.inputs["Input"].meta.axistags.index('c') axisindex = channelAxis oldkey = list(key) oldkey.pop(axisindex) inShape = self.inputs["Input"].meta.shape hasChannelAxis = (self.Input.meta.axistags.axisTypeCount(vigra.AxisType.Channels) > 0) #if (self.Input.meta.axistags.axisTypeCount(vigra.AxisType.Channels) == 0): # noChannels = True inAxistags = self.inputs["Input"].meta.axistags shape = self.outputs["Output"].meta.shape axistags = self.outputs["Output"].meta.axistags result = result.view(vigra.VigraArray) result.axistags = copy.copy(axistags) hasTimeAxis = self.inputs["Input"].meta.axistags.axisTypeCount(vigra.AxisType.Time) timeAxis=self.inputs["Input"].meta.axistags.index('t') subkey = popFlagsFromTheKey(key,axistags,'c') subshape=popFlagsFromTheKey(shape,axistags,'c') at2 = copy.copy(axistags) at2.dropChannelAxis() subshape=popFlagsFromTheKey(subshape,at2,'t') subkey = popFlagsFromTheKey(subkey,at2,'t') oldstart, oldstop = roi.sliceToRoi(key, shape) start, stop = roi.sliceToRoi(subkey,subkey) maxSigma = max(0.7,self.maxSigma) #we use 0.7 as an approximation of not doing any smoothing #smoothing was already applied previously # The region of the smoothed image we need to give to the feature filter (in terms of INPUT coordinates) # 0.7, because the features receive a pre-smoothed array and don't need much of a neighborhood vigOpSourceStart, vigOpSourceStop = roi.enlargeRoiForHalo(start, stop, subshape, 0.7, self.WINDOW_SIZE) # The region of the input that we need to give to the smoothing operator (in terms of INPUT coordinates) newStart, newStop = roi.enlargeRoiForHalo(vigOpSourceStart, vigOpSourceStop, subshape, maxSigma, self.WINDOW_SIZE) newStartSmoother = roi.TinyVector(start - vigOpSourceStart) newStopSmoother = roi.TinyVector(stop - vigOpSourceStart) roiSmoother = roi.roiToSlice(newStartSmoother, newStopSmoother) # Translate coordinates (now in terms of smoothed image coordinates) vigOpSourceStart = roi.TinyVector(vigOpSourceStart - newStart) vigOpSourceStop = roi.TinyVector(vigOpSourceStop - newStart) readKey = roi.roiToSlice(newStart, newStop) writeNewStart = start - newStart writeNewStop = writeNewStart + stop - start treadKey=list(readKey) if hasTimeAxis: if timeAxis < channelAxis: treadKey.insert(timeAxis, key[timeAxis]) else: treadKey.insert(timeAxis-1, key[timeAxis]) if self.inputs["Input"].meta.axistags.axisTypeCount(vigra.AxisType.Channels) == 0: treadKey = popFlagsFromTheKey(treadKey,axistags,'c') else: treadKey.insert(channelAxis, slice(None,None,None)) treadKey=tuple(treadKey) req = self.inputs["Input"][treadKey] sourceArray = req.wait() req.clean() #req.result = None req.destination = None if sourceArray.dtype != numpy.float32: sourceArrayF = sourceArray.astype(numpy.float32) try: sourceArray.resize((1,), refcheck = False) except: pass del sourceArray sourceArray = sourceArrayF #if (self.Input.meta.axistags.axisTypeCount(vigra.AxisType.Channels) == 0): #add a channel dimension to make the code afterwards more uniform # sourceArray = sourceArray.view(numpy.ndarray) # sourceArray = sourceArray.reshape(sourceArray.shape+(1,)) sourceArrayV = sourceArray.view(vigra.VigraArray) sourceArrayV.axistags = copy.copy(inAxistags) dimCol = len(self.scales) dimRow = self.matrix.shape[0] sourceArraysForSigmas = [None]*dimCol #connect individual operators try: for j in range(dimCol): hasScale = False for i in range(dimRow): if self.matrix[i,j]: hasScale = True if not hasScale: continue destSigma = 1.0 if self.scales[j] > destSigma: tempSigma = math.sqrt(self.scales[j]**2 - destSigma**2) else: destSigma = 0.0 tempSigma = self.scales[j] vigOpSourceShape = list(vigOpSourceStop - vigOpSourceStart) if hasTimeAxis: if timeAxis < channelAxis: vigOpSourceShape.insert(timeAxis, ( oldstop - oldstart)[timeAxis]) else: vigOpSourceShape.insert(timeAxis-1, ( oldstop - oldstart)[timeAxis]) vigOpSourceShape.insert(channelAxis, inShape[channelAxis]) sourceArraysForSigmas[j] = numpy.ndarray(tuple(vigOpSourceShape),numpy.float32) for i,vsa in enumerate(sourceArrayV.timeIter()): droi = (tuple(vigOpSourceStart._asint()), tuple(vigOpSourceStop._asint())) tmp_key = getAllExceptAxis(len(sourceArraysForSigmas[j].shape),timeAxis, i) sourceArraysForSigmas[j][tmp_key] = self._computeGaussianSmoothing(vsa, tempSigma, droi) else: droi = (tuple(vigOpSourceStart._asint()), tuple(vigOpSourceStop._asint())) sourceArraysForSigmas[j] = self._computeGaussianSmoothing(sourceArrayV, tempSigma, droi) except RuntimeError as e: if e.message.find('kernel longer than line') > -1: message = "Feature computation error:\nYour image is too small to apply a filter with sigma=%.1f. Please select features with smaller sigmas." % self.scales[j] raise RuntimeError(message) else: raise e del sourceArrayV try: sourceArray.resize((1,), refcheck = False) except ValueError: # Sometimes this fails, but that's okay. logger.debug("Failed to free array memory.") del sourceArray closures = [] #connect individual operators for i in range(dimRow): for j in range(dimCol): val=self.matrix[i,j] if val: vop= self.featureOps[i][j] oslot = vop.outputs["Output"] req = None #inTagKeys = [ax.key for ax in oslot.meta.axistags] #print inTagKeys, flag if hasChannelAxis: slices = oslot.meta.shape[axisindex] if cnt + slices >= rroi.start[axisindex] and rroi.start[axisindex]-cnt<slices and rroi.start[axisindex]+written<rroi.stop[axisindex]: begin = 0 if cnt < rroi.start[axisindex]: begin = rroi.start[axisindex] - cnt end = slices if cnt + end > rroi.stop[axisindex]: end -= cnt + end - rroi.stop[axisindex] key_ = copy.copy(oldkey) key_.insert(axisindex, slice(begin, end, None)) reskey = [slice(None, None, None) for x in range(len(result.shape))] reskey[axisindex] = slice(written, written+end-begin, None) destArea = result[tuple(reskey)] #readjust the roi for the new source array roiSmootherList = list(roiSmoother) roiSmootherList.insert(axisindex, slice(begin, end, None)) if hasTimeAxis: # The time slice in the ROI doesn't matter: # The sourceArrayParameter below overrides the input data to be used. roiSmootherList.insert(timeAxis, 0) roiSmootherRegion = SubRegion(oslot, pslice=roiSmootherList) closure = partial(oslot.operator.execute, oslot, (), roiSmootherRegion, destArea, sourceArray = sourceArraysForSigmas[j]) closures.append(closure) written += end - begin cnt += slices else: if cnt>=rroi.start[axisindex] and rroi.start[axisindex] + written < rroi.stop[axisindex]: reskey = [slice(None, None, None) for x in range(len(result.shape))] slices = oslot.meta.shape[axisindex] reskey[axisindex]=slice(written, written+slices, None) #print "key: ", key, "reskey: ", reskey, "oldkey: ", oldkey, "resshape:", result.shape #print "roiSmoother:", roiSmoother destArea = result[tuple(reskey)] #print "destination area:", destArea.shape logger.debug(oldkey, destArea.shape, sourceArraysForSigmas[j].shape) oldroi = SubRegion(oslot, pslice=oldkey) #print "passing roi:", oldroi closure = partial(oslot.operator.execute, oslot, (), oldroi, destArea, sourceArray = sourceArraysForSigmas[j]) closures.append(closure) written += 1 cnt += 1 pool = RequestPool() for c in closures: r = pool.request(c) pool.wait() pool.clean() for i in range(len(sourceArraysForSigmas)): if sourceArraysForSigmas[i] is not None: try: sourceArraysForSigmas[i].resize((1,)) except: sourceArraysForSigmas[i] = None