def test_2d_along_t(self): data = numpy.random.randint(0, 255, (20, 100, 200, 3)).astype(numpy.uint8) expected_axistags = vigra.AxisTags([ vigra.AxisInfo("t", typeFlags=vigra.AxisType.Time), vigra.AxisInfo("y", typeFlags=vigra.AxisType.Space), vigra.AxisInfo("x", typeFlags=vigra.AxisType.Space), vigra.AxisInfo("c", typeFlags=vigra.AxisType.Channels), ]) with tempdir() as d: tiff_path = d + "/test-2d-{slice_index:02d}.tiff" tiff_glob_path = d + "/test-2d-*.tiff" for slice_index, t_slice in enumerate(data): vigra.impex.writeImage( vigra.taggedView(t_slice, "yxc"), tiff_path.format(slice_index=slice_index), dtype="NATIVE", mode="w", ) op = OpTiffSequenceReader(graph=Graph()) op.SequenceAxis.setValue("t") op.GlobString.setValue(tiff_glob_path) assert op.Output.ready() assert op.Output.meta.axistags == expected_axistags assert (op.Output[5:10, 50:100, 100:150].wait() == data[5:10, 50:100, 100:150]).all()
def setupOutputs(self): inputSlot = self.inputs["Input"] self.outputs["Output"].meta.assignFrom(inputSlot.meta) self.Output.meta.axistags = vigra.AxisTags( [vigra.AxisInfo("t"), vigra.AxisInfo("x"), vigra.AxisInfo("y"), vigra.AxisInfo("z"), vigra.AxisInfo("c")] )
def setupOutputs(self): assert len(self.Input.meta.shape ) == 4, "Data must be exactly 3D+c (no time axis)" assert self.Input.meta.getAxisKeys()[-1] == 'c' assert self.Input.meta.shape[-1] == 1, "Input must be 1-channel" self.Output.meta.assignFrom(self.Input.meta) self.Output.meta.dtype = numpy.float32 self.Output.meta.shape = self.Input.meta.shape[:-1] + (3, 3) # axistags: start with input, drop channel and append i,j input_axistags = copy.copy(self.Input.meta.axistags) tag_list = [tag for tag in input_axistags] tag_list = tag_list[:-1] tag_list.append(vigra.AxisInfo('i', description='eigenvector index')) tag_list.append( vigra.AxisInfo('j', description='eigenvector component')) self.Output.meta.axistags = vigra.AxisTags(tag_list) # Calculate anisotropy factor. x_tag = self.Input.meta.axistags['x'] z_tag = self.Input.meta.axistags['z'] self.z_anisotropy_factor = 1.0 if z_tag.resolution != 0.0 and x_tag.resolution != 0.0: self.z_anisotropy_factor = z_tag.resolution / x_tag.resolution logger.debug("Anisotropy factor: {}/{} = {}".format( z_tag.resolution, x_tag.resolution, self.z_anisotropy_factor))
def test_withAxisTags(self): # Write it again, this time with weird axistags axistags = vigra.AxisTags( vigra.AxisInfo("x", vigra.AxisType.Space), vigra.AxisInfo("y", vigra.AxisType.Space), vigra.AxisInfo("z", vigra.AxisType.Space), vigra.AxisInfo("c", vigra.AxisType.Channels), vigra.AxisInfo("t", vigra.AxisType.Time), ) # Write the dataset to an hdf5 file # (Note: Don't use vigra to do this, which may reorder the axes) self.h5File["volume"].create_dataset("tagged_data", data=self.data) self.n5File["volume"].create_dataset("tagged_data", data=self.data) # Write the axistags attribute self.h5File["volume/tagged_data"].attrs["axistags"] = axistags.toJSON() self.n5File["volume/tagged_data"].attrs["axistags"] = axistags.toJSON() # Read the data with an operator self.h5_op.H5N5File.setValue(self.h5File) self.n5_op.H5N5File.setValue(self.n5File) self.h5_op.InternalPath.setValue("volume/tagged_data") self.n5_op.InternalPath.setValue("volume/tagged_data") assert self.h5_op.OutputImage.meta.shape == self.data.shape assert self.n5_op.OutputImage.meta.shape == self.data.shape numpy.testing.assert_array_equal(self.h5_op.OutputImage.value, self.data) numpy.testing.assert_array_equal(self.n5_op.OutputImage.value, self.data)
def setupOutputs(self): self.Output.meta.shape = self.shape self.Output.meta.dtype = self.dtype self.Output.meta.axistags = vigra.AxisTags([ vigra.AxisInfo("t"), vigra.AxisInfo("x"), vigra.AxisInfo("y"), vigra.AxisInfo("z"), vigra.AxisInfo("c"), ])
def create_axistags(self): """ Generate a vigra.AxisTags object corresponding to this VoxelsMetadata. (Requires vigra.) """ tags_f = vigra.AxisTags() tags_f.insert( 0, vigra.AxisInfo('c', typeFlags=vigra.AxisType.Channels)) dtypes = [] channel_labels = [] for channel_fields in self["Properties"]["Values"]: dtypes.append(numpy.dtype(channel_fields["DataType"]).type) channel_labels.append(channel_fields["Label"]) # We monkey-patch the channel labels onto the axistags object as a new member tags_f.channelLabels = channel_labels for axisfields in self['Axes']: key = str(axisfields["Label"]).lower() res = axisfields["Resolution"] tag = vigra.defaultAxistags(key)[0] tag.resolution = res tags_f.insert(len(tags_f), tag) # TODO: Check resolution units, because apparently # they can be different from one axis to the next... assert all( [dtype == dtypes[0] for dtype in dtypes] ), \ "Can't support heterogeneous channel types: {}".format( dtypes ) # Reverse from F-order to C-order tags_c = vigra.AxisTags(list(tags_f)[::-1]) return tags_c
def setRightShape(self): c = 0 flag = self.inputs["AxisFlag"].value self.intervals = [] inTagKeys = [] for inSlot in self.inputs["Images"]: inTagKeys = [ax.key for ax in inSlot.meta.axistags] if inSlot.partner is not None: self.Output.meta.assignFrom(inSlot.meta) outTagKeys = [ ax.key for ax in self.outputs["Output"].meta.axistags ] if not flag in outTagKeys: if self.AxisIndex.ready(): axisindex = self.AxisIndex.value else: axisindex = len(outTagKeys) self.outputs["Output"].meta.axistags.insert( axisindex, vigra.AxisInfo(flag, axisType(flag))) old_c = c if flag in inTagKeys: c += inSlot.meta.shape[inSlot.meta.axistags.index(flag)] else: c += 1 self.intervals.append((old_c, c)) if len(self.inputs["Images"]) > 0: newshape = list(self.inputs["Images"][0].meta.shape) if flag in inTagKeys: #here we assume that all axis are present axisindex = self.Output.meta.axistags.index(flag) newshape[axisindex] = c else: #FIXME axisindex is not necessarily defined yet (try setValue on subslot) newshape.insert(axisindex, c) ideal_blockshape = self.Output.meta.ideal_blockshape if ideal_blockshape is not None: ideal_blockshape = ideal_blockshape[:axisindex] + ( 1, ) + ideal_blockshape[axisindex:] self.Output.meta.ideal_blockshape = ideal_blockshape max_blockshape = self.Output.meta.max_blockshape if max_blockshape is not None: max_blockshape = max_blockshape[:axisindex] + ( 1, ) + max_blockshape[axisindex:] self.Output.meta.max_blockshape = max_blockshape self.outputs["Output"].meta.shape = tuple(newshape) else: self.outputs["Output"].meta.shape = None
def test_withAxisTags(self): # Write it again, this time with weird axistags axistags = vigra.AxisTags(vigra.AxisInfo('x', vigra.AxisType.Space), vigra.AxisInfo('y', vigra.AxisType.Space), vigra.AxisInfo('z', vigra.AxisType.Space), vigra.AxisInfo('c', vigra.AxisType.Channels), vigra.AxisInfo('t', vigra.AxisType.Time)) # Write the dataset to an hdf5 file # (Note: Don't use vigra to do this, which may reorder the axes) self.h5File['volume'].create_dataset('tagged_data', data=self.data) # Write the axistags attribute self.h5File['volume/tagged_data'].attrs['axistags'] = axistags.toJSON() # Read the data with an operator self.op.Hdf5File.setValue(self.h5File) self.op.InternalPath.setValue('volume/tagged_data') assert self.op.OutputImage.meta.shape == self.data.shape assert self.op.OutputImage[0, 1, 2, 1, 0].wait() == 4
def axisTagObjectFromFlag(flag): if flag in ['x', 'y', 'z']: type = vigra.AxisType.Space elif flag == 'c': type = vigra.AxisType.Channel elif flag == 't': type = vigra.AxisType.Time else: print "Requested flag", str(flag) raise return vigra.AxisTags(vigra.AxisInfo(flag, type))
def func_wrapper(array, *args, **kwargs): if hasattr(array, 'axistags'): array = vigra.taggedView(np.ascontiguousarray(array), array.axistags) squeezed = array.squeeze() res = func(squeezed, *args, **kwargs) if res.shape == squeezed.shape: res = vigra.taggedView(res, squeezed.axistags) else: res = vigra.taggedView( res, list(squeezed.axistags) + [vigra.AxisInfo('c')]) return res.withAxes(array.axistags) else: assert not any( np.array(array.shape) == 1 ), \ "Can't handle arrays with singleton dimensions (unless they are tagged VigraArrays)." return func(array, *args, **kwargs)
def blockwise_view(a, blockshape, aslist=False, require_aligned_blocks=True): """ Return a 2N-D view of the given N-D array, rearranged so each ND block (tile) of the original array is indexed by its block address using the first N indexes of the output array. Note: This function is nearly identical to ``skimage.util.view_as_blocks()``, except: - "imperfect" block shapes are permitted (via require_aligned_blocks=False) - only contiguous arrays are accepted. (This function will NOT silently copy your array.) As a result, the return value is *always* a view of the input. Args: a: The ND array blockshape: The tile shape aslist: If True, return all blocks as a list of ND blocks instead of a 2D array indexed by ND block coordinate. require_aligned_blocks: If True, check to make sure no data is "left over" in each row/column/etc. of the output view. That is, the blockshape must divide evenly into the full array shape. If False, "leftover" items that cannot be made into complete blocks will be discarded from the output view. Here's a 2D example (this function also works for ND): >>> a = numpy.arange(1,21).reshape(4,5) >>> print a [[ 1 2 3 4 5] [ 6 7 8 9 10] [11 12 13 14 15] [16 17 18 19 20]] >>> view = blockwise_view(a, (2,2), False) >>> print view [[[[ 1 2] [ 6 7]] <BLANKLINE> [[ 3 4] [ 8 9]]] <BLANKLINE> <BLANKLINE> [[[11 12] [16 17]] <BLANKLINE> [[13 14] [18 19]]]] Inspired by the 2D example shown here: http://stackoverflow.com/a/8070716/162094 """ assert a.flags[ 'C_CONTIGUOUS'], "This function relies on the memory layout of the array." blockshape = tuple(blockshape) outershape = tuple(numpy.array(a.shape) // blockshape) view_shape = outershape + blockshape if require_aligned_blocks: assert (numpy.mod(a.shape, blockshape) == 0).all(), \ "blockshape {} must divide evenly into array shape {}"\ .format( blockshape, a.shape ) # inner strides: strides within each block (same as original array) intra_block_strides = a.strides # outer strides: strides from one block to another inter_block_strides = tuple(a.strides * numpy.array(blockshape)) # This is where the magic happens. # Generate a view with our new strides (outer+inner). view = numpy.lib.stride_tricks.as_strided(a, shape=view_shape, strides=(inter_block_strides + intra_block_strides)) # Special handling for VigraArrays if _vigra_available and isinstance(a, vigra.VigraArray) and hasattr( a, 'axistags'): view_axistags = vigra.AxisTags([vigra.AxisInfo() for _ in blockshape] + list(a.axistags)) view = vigra.taggedView(view, view_axistags) if aslist: return list(map(view.__getitem__, numpy.ndindex(outershape))) return view
def synthetic_EPSCaT_linescan(field_width, duration, spatial_resolution, sampling_frequency, spine_parameters, epscat_parameters, space_units = None, time_units = None, data_units = pq.dimensionless, twoChannels=False, addChannelAxis=True, returnCalibration=False): """Generates a synthetic 2D EPSCaT as a vigra.VigraArray Parameters: =========== field_width : spatial extent where the synthetic spines are to be generated: float value, or a scalar Python Quantity where units SHOULD be "um" duration : temporal extent of the entire EPSCaT signal containing synthetic EPSCaT waveforms float value, or a scalar Python Quantity where units SHOULD be "s" spatial_resolution : size of a "pixel" (sample) in the spatial domain either float or a scalar Python Quantity with units convertible to those of field_width sampling_frequency : sampling frequency of the time domain either flooat or a scalar Python Quantity with units convertible to the inverse of duration's units spine_parameters: a sequence of parameters for the models.gaussianSum1D function see models.gaussianSum1D() docstring for details epscat_parameters: a sequence of parameters for the models.compound_exp_rise_multi_decay function see models.compound_exp_rise_multi_decay() docstring for details Named parameters (keywords): Default values indicated (in parenthesis are default values if field_width and duration are floats) ============================ space_units = None (pq.um) time_units = None (pq.s) data_units = pq.dimensionless addChannelAxis: boolean (default True) adds a singleton channel axis as the last axis returnCalibration: boolean, default False: When True, also returns the datatypes.AxisCalibration object for the axistags if the result twoChannels : boolean (default is False) When True, the result will be two-channel image with the "spine" on channel 0 and the epscat on channel 1 (a channel axis will be automatically inserted in the image regardless of the value of addChannelAxis parameter) When False, the result will be a single-channel images containing the synthetic EPSCaT linescan Returns: ======== When returnCalibration is False (default): a vigra.VigraArray containing the outer product of the synthetic spine(s) (on the horizontal space axis) with the synthetic epscat (on the vertical temporal axis) When returnCalibration is True, returns a tuple: (image, axiscalibration) where image is as above, and axiscalibration is a datatypes.AxisCalibration object for the image axes (axistags property). NOTE that in any case the image axistags will contain a calibration data in their decsription properties """ if space_units is None: if isinstance(field_width, pq.Quantity): space_units = field_width.units field_width = field_width.magnitude else: space_units = pq.um if time_units is None: if isinstance(duration, pq.Quantity): time_units = duration.units duration = duration.magnitude else: time_units = pq.s # NOTE: 2018-09-14 14:13:56 # below, we get each signal as a tuple (y,x) of numpy arrays (vector columns) # NOTE the order epscat = synthetic_transients(duration, sampling_frequency, epscat_parameters)[1] spine = synthetic_spine(field_width, spatial_resolution, *spine_parameters)[1] axistags = vigra.AxisTags(vigra.AxisInfo("x", vigra.AxisType.Space, resolution=spatial_resolution), vigra.AxisInfo("t", vigra.AxisType.Time, resolution=1/sampling_frequency)) linescan = vigra.VigraArray(np.outer(spine, epscat), axistags = axistags) if twoChannels: spine2D = vigra.VigraArray(np.outer(spine, np.ones_like(epscat)), axistags = axistags) result = imgp.concatenateImages(spine2D, linescan, axis = "c") else: result = linescan if addChannelAxis and result.channelIndex == linescan.ndim: linescan = linescan.insertChannelAxis() axiscal = dt.AxisCalibration(result) axiscal.setUnits(space_units, "x") axiscal.setResolution(spatial_resolution, "x") axiscal.setUnits(time_units, "t") axiscal.setResolution(1/sampling_frequency, "t") if result.channelIndex < result.ndim: # by default there is only one channel axiscal.setUnits(data_units, "c", 0) axiscal.setOrigin(np.min(result), "c", 0) axiscal.setResolution(np.finfo(float).eps, "c", 0) axiscal.calibrateAxes() if returnCalibration: return result, axiscal else: return result