use of qupath.lib.analysis.stats.RunningStatistics in project qupath by qupath.
the class LocalBinaryPatternsPlugin method addBasicStatistics.
static void addBasicStatistics(final SimpleImage img, final MeasurementList measurementList, final String name) {
RunningStatistics stats = StatisticsHelper.computeRunningStatistics(img);
measurementList.addMeasurement(name + " Mean", stats.getMean());
measurementList.addMeasurement(name + " Min", stats.getMin());
measurementList.addMeasurement(name + " Max", stats.getMax());
measurementList.addMeasurement(name + " Range", stats.getRange());
measurementList.addMeasurement(name + " Std.dev.", stats.getStdDev());
// measurementList.addMeasurement(String.format("%s Mean", name), stats.getMean());
// measurementList.addMeasurement(String.format("%s Min", name), stats.getMin());
// measurementList.addMeasurement(String.format("%s Max", name), stats.getMax());
// measurementList.addMeasurement(String.format("%s Range", name), stats.getRange());
// measurementList.addMeasurement(String.format("%s Std.dev.", name), stats.getStdDev());
}
use of qupath.lib.analysis.stats.RunningStatistics in project qupath by qupath.
the class PathIntensityClassifierPane method updateIntensityHistogram.
private void updateIntensityHistogram() {
String selected = comboIntensities.getSelectionModel().getSelectedItem();
PathObjectHierarchy hierarchy = getHierarchy();
// if (!"None".equals(selected) || hierarchy == null)
if ("None".equals(selected) || hierarchy == null) {
if (panelHistogram != null)
panelHistogram.getHistogramData().clear();
return;
}
// Try to make a histogram & set it in the panel
// PathObject pathObjectSelected = hierarchy.getSelectionModel().getSelectedPathObject();
// For now, always use all objects (not direct descendants only)
Collection<PathObject> pathObjects = null;
// if (pathObjectSelected == null || !pathObjectSelected.hasChildren())
pathObjects = hierarchy.getDetectionObjects();
// else
// pathObjects = hierarchy.getDescendantObjects(pathObjectSelected, pathObjects, PathDetectionObject.class);
// Histogram histogram = Histogram.makeMeasurementHistogram(pathObjects, (String)selected, 256);
double[] values = Histogram.getMeasurementValues(pathObjects, (String) selected);
Histogram histogram = new Histogram(values, 128);
// Compute quartile values
Arrays.sort(values);
int nNaNs = 0;
// NaNs should be at the end of the list
for (int i = values.length - 1; i >= 0; i--) {
if (Double.isNaN(values[i]))
nNaNs++;
else
break;
}
// Should be same as histogram.getCountSum() ?
int nValues = values.length - nNaNs;
assert nValues == histogram.getCountSum();
if (nValues > 0) {
double median = values[nValues / 2];
double quartile1 = values[(int) (nValues / 4 + .5)];
double quartile3 = values[(int) (nValues * 3 / 4 + .5)];
logger.info(String.format("%s Quartile 1: %.4f", selected, quartile1));
logger.info(String.format("%s Median: %.4f", selected, median));
logger.info(String.format("%s Quartile 3: %.4f", selected, quartile3));
RunningStatistics stats = StatisticsHelper.computeRunningStatistics(values);
logger.info(String.format("%s Mean: %.4f", selected, stats.getMean()));
logger.info(String.format("%s Std.Dev.: %.4f", selected, stats.getStdDev()));
panelHistogram.getHistogramData().setAll(HistogramPanelFX.createHistogramData(histogram, true, (Integer) null));
} else
panelHistogram.getHistogramData().clear();
updateHistogramThresholdLines();
}
use of qupath.lib.analysis.stats.RunningStatistics in project qupath by qupath.
the class Preprocessing method createNormalizer.
/**
* Create a simple normalizer to rescale input data.
*
* @param normalization the method of normalization to apply
* @param samples the input samples used to determine the normalization parameter
* @param missingValue an optional value that may be used to replace non-finite (i.e. missing) feature values
* @return a {@link Normalizer} that may be applied to new data
*/
public static Normalizer createNormalizer(final Normalization normalization, final Mat samples, final double missingValue) {
Mat features;
if (samples.channels() == 1)
features = samples;
else
features = samples.reshape(1, samples.rows() * samples.cols());
int nSamples = features.rows();
int nFeatures = features.cols();
var offsets = new double[nFeatures];
var scales = new double[nFeatures];
Arrays.fill(scales, 1.0);
if (normalization == Normalization.NONE) {
return Normalizer.createNormalizer(offsets, scales, missingValue);
}
var indexer = samples.createIndexer();
var inds = new long[2];
for (int c = 0; c < nFeatures; c++) {
var stats = new RunningStatistics();
inds[1] = c;
for (int r = 0; r < nSamples; r++) {
inds[0] = r;
var val = indexer.getDouble(inds);
if (Double.isFinite(val))
stats.addValue(val);
}
offsets[c] = 0.0;
scales[c] = 1.0;
if (stats.size() > 0) {
if (normalization == Normalization.MEAN_VARIANCE) {
offsets[c] = -stats.getMean();
scales[c] = 1.0 / stats.getStdDev();
} else if (normalization == Normalization.MIN_MAX) {
offsets[c] = -stats.getMin();
scales[c] = 1.0 / (stats.getMax() - stats.getMin());
}
}
}
indexer.release();
if (features != samples)
features.close();
return Normalizer.createNormalizer(offsets, scales, missingValue);
}
use of qupath.lib.analysis.stats.RunningStatistics in project qupath by qupath.
the class OpenCvClassifier method updateClassifier.
@Override
public boolean updateClassifier(final Map<PathClass, List<PathObject>> map, final List<String> measurements, Normalization normalization) {
// There is a chance we don't need to retrain... to find out, cache the most important current variables
boolean maybeSameClassifier = isValid() && this.normalization == normalization && !classifierOptionsChanged() && this.measurements.equals(measurements) && pathClasses.size() == map.size() && map.keySet().containsAll(pathClasses);
float[] arrayTrainingPrevious = arrayTraining;
int[] arrayResponsesPrevious = arrayResponses;
pathClasses = new ArrayList<>(map.keySet());
Collections.sort(pathClasses);
int n = 0;
for (Map.Entry<PathClass, List<PathObject>> entry : map.entrySet()) {
n += entry.getValue().size();
}
// Compute running statistics for normalization
HashMap<String, RunningStatistics> statsMap = new LinkedHashMap<>();
for (String m : measurements) statsMap.put(m, new RunningStatistics());
this.measurements.clear();
this.measurements.addAll(measurements);
int nMeasurements = measurements.size();
arrayTraining = new float[n * nMeasurements];
arrayResponses = new int[n];
int row = 0;
int nnan = 0;
for (PathClass pathClass : pathClasses) {
List<PathObject> list = map.get(pathClass);
int classIndex = pathClasses.indexOf(pathClass);
for (int i = 0; i < list.size(); i++) {
MeasurementList measurementList = list.get(i).getMeasurementList();
int col = 0;
for (String m : measurements) {
double value = measurementList.getMeasurementValue(m);
if (Double.isNaN(value))
nnan++;
else
statsMap.get(m).addValue(value);
arrayTraining[row * nMeasurements + col] = (float) value;
col++;
}
arrayResponses[row] = classIndex;
row++;
}
}
// Normalise, if required
if (normalization != null && normalization != Normalization.NONE) {
logger.debug("Training classifier with normalization: {}", normalization);
int numMeasurements = measurements.size();
normOffset = new double[numMeasurements];
normScale = new double[numMeasurements];
for (int i = 0; i < numMeasurements; i++) {
RunningStatistics stats = statsMap.get(measurements.get(i));
if (normalization == Normalization.MEAN_VARIANCE) {
normOffset[i] = -stats.getMean();
if (stats.getStdDev() > 0)
normScale[i] = 1.0 / stats.getStdDev();
} else if (normalization == Normalization.MIN_MAX) {
normOffset[i] = -stats.getMin();
if (stats.getRange() > 0)
normScale[i] = 1.0 / (stats.getMax() - stats.getMin());
else
normScale[i] = 1.0;
}
}
// Apply normalisation
for (int i = 0; i < arrayTraining.length; i++) {
int k = i % numMeasurements;
arrayTraining[i] = (float) ((arrayTraining[i] + normOffset[k]) * normScale[k]);
}
this.normalization = normalization;
} else {
logger.debug("Training classifier without normalization");
normScale = null;
normOffset = null;
this.normalization = Normalization.NONE;
}
// Record that we have NaNs
if (nnan > 0)
logger.debug("Number of NaNs in training set: " + nnan);
// Having got this far, check to see whether we really do need to retrain
if (maybeSameClassifier) {
if (Arrays.equals(arrayTrainingPrevious, arrayTraining) && Arrays.equals(arrayResponsesPrevious, arrayResponses)) {
logger.info("Classifier already trained with the same samples - existing classifier will be used");
return false;
}
}
createAndTrainClassifier();
timestamp = System.currentTimeMillis();
this.measurements = new ArrayList<>(measurements);
return true;
}
use of qupath.lib.analysis.stats.RunningStatistics in project qupath by qupath.
the class WatershedNucleiCV method computeRunningStatistics.
private static void computeRunningStatistics(float[] pxIntensities, float[] pxLabels, List<RunningStatistics> statsList) {
float lastLabel = Float.NaN;
int nLabels = statsList.size();
RunningStatistics stats = null;
for (int i = 0; i < pxIntensities.length; i++) {
float label = pxLabels[i];
if (label == 0 || label > nLabels)
continue;
// Get a new statistics object if necessary
if (label != lastLabel) {
stats = statsList.get((int) label - 1);
lastLabel = label;
}
// Add the value
stats.addValue(pxIntensities[i]);
}
}
Aggregations