spacr.normalization¶
Control crop storage precision and model-input normalization.
.npy crops keep whatever
the merged stack held, PNG crops narrow once through
spacr.crops.narrow_to_uint8() – the high byte of a uint16, a linear
rescale rather than a clip – and measurements are taken from the
full-precision array. So the structure the request asks for is the structure:
original precision wherever it can be, one declared narrowing at the only
boundary that requires one.
Storage dtype and model input scaling are separate choices.
transforms.ToTensor() divides by 255 and
hands the model a float in [0, 1] whatever the file held, so “scale to 0-1”
is already what happens at the point it matters. The dtype on disk decides
file size and what other tools can open the crop – a storage decision.
The subsequent normalization setting changes the model input. spaCR has historically normalized with
mean = std = (0.5, 0.5, 0.5)
which maps [0, 1] onto [-1, 1]. Every ImageNet-pretrained torchvision model was fitted on
mean = (0.485, 0.456, 0.406) std = (0.229, 0.224, 0.225)
so a finetune starts by handing pretrained weights inputs distributed differently from the ones they learned. A long finetune adapts; a short one, or a frozen backbone, pays for it. That was a literal in two places and is now a choice.
The default remains symmetric for compatibility. This is what spaCR has
always done, and switching it silently would move every existing model’s
scores with nothing in the artifact to say why.
Functions¶
|
Return |
|
Return the dataset's per-channel mean and standard deviation. |
|
One line for the log, so a model card records what it was trained on. |
|
|
Module Contents¶
- spacr.normalization.apply_crop_dtype(array: numpy.ndarray, dtype: Any = 'original') numpy.ndarray[source]¶
Return
arrayin the dtype a crop file should hold.- Parameters:
array – the crop as the pipeline produced it.
dtype – one of
CROP_DTYPES.
- Returns:
the array, unchanged for
original.
Conversion to
uint8delegates tospacr.crops.narrow_to_uint8(), which applies the project’s declared 16-to-8-bit linear mapping. Conversion touint16is a cast rather than an intensity stretch; values from an 8-bit input remain unchanged.
- spacr.normalization.dataset_statistics(loader: Any, *, max_batches: int | None = None) Tuple[Tuple[float, ...], Tuple[float, ...]][source]¶
Return the dataset’s per-channel mean and standard deviation.
Dataset-specific statistics are appropriate when fluorescence channels differ substantially from the natural-image distribution represented by ImageNet statistics. Fluorescence channels may contain independently exposed stains and a large background fraction.
Computed in one streaming pass with the sum-of-squares identity, so a dataset that does not fit in memory still yields exact statistics rather than statistics of whatever fitted.
- Parameters:
loader – anything iterable yielding
(images, ...)batches, or bare image tensors, shaped(N, C, H, W)on [0, 1].max_batches – stop after this many. The mean of a plate converges in far fewer batches than the plate has, and a full pass over a million crops to compute two numbers per channel is a cost with no matching gain.
Nonereads everything.
- Returns:
(mean, std), per channel.- Raises:
ValueError – the loader yielded nothing, so the answer would be the statistics of an empty set rather than of this dataset.
- spacr.normalization.describe_normalization(mode: Any, **kwargs) str[source]¶
One line for the log, so a model card records what it was trained on.
- Parameters:
mode – normalization preset or explicit normalization mode.
- spacr.normalization.normalization_stats(mode: Any, *, mean: Sequence[float] | None = None, std: Sequence[float] | None = None, channels: int = 3) Tuple[Tuple[float, ...], Tuple[float, ...]] | None[source]¶
(mean, std)formode, or None when nothing should be applied.- Parameters:
mode – one of
NORMALIZATIONS. Anything unrecognised falls back tosymmetricwith a log line – a typo must not silently train a model on statistics nobody chose, but it must not stop a run either, andsymmetricis what the run would have used before this setting existed.mean – for
customanddataset, the per-channel means. One value is broadcast to every channel, which is what a single-stain dataset wants.std – as
mean. A zero is replaced by 1.0 rather than dividing by it – a channel with no variance is a constant channel, and dividing it by its own zero spread produces inf and then a loss of nan, several minutes into training, with nothing saying why.channels – how many planes the model will see. Only used to broadcast a single supplied value.