use of uk.ac.sussex.gdsc.core.data.DataException in project GDSC-SMLM by aherbert.
the class TranslateResults method run.
@Override
public void run(String arg) {
SmlmUsageTracker.recordPlugin(this.getClass(), arg);
if (MemoryPeakResults.isMemoryEmpty()) {
IJ.error(TITLE, "There are no fitting results in memory");
return;
}
final TranslateResultsSettings.Builder settings = SettingsManager.readTranslateResultsSettings(0).toBuilder();
// Show a dialog allowing the results set to be filtered
final ExtendedGenericDialog gd = new ExtendedGenericDialog(TITLE);
gd.addMessage("Select a dataset to translate");
ResultsManager.addInput(gd, settings.getInputOption(), InputSource.MEMORY);
gd.addNumericField("x", settings.getDx(), 3);
gd.addNumericField("y", settings.getDy(), 3);
gd.addNumericField("z", settings.getDz(), 3);
gd.addChoice("Distance_unit", SettingsManager.getDistanceUnitNames(), settings.getDistanceUnitValue());
gd.addHelp(HelpUrls.getUrl("translate-results"));
gd.showDialog();
if (gd.wasCanceled()) {
return;
}
settings.setInputOption(ResultsManager.getInputSource(gd));
settings.setDx(gd.getNextNumber());
settings.setDy(gd.getNextNumber());
settings.setDz(gd.getNextNumber());
settings.setDistanceUnitValue(gd.getNextChoiceIndex());
SettingsManager.writeSettings(settings);
final MemoryPeakResults results = ResultsManager.loadInputResults(settings.getInputOption(), false, null, null);
if (MemoryPeakResults.isEmpty(results)) {
IJ.error(TITLE, "No results could be loaded");
return;
}
TypeConverter<DistanceUnit> converter;
try {
converter = results.getDistanceConverter(settings.getDistanceUnit());
} catch (final DataException ex) {
IJ.error(TITLE, "Unit conversion error: " + ex.getMessage());
return;
}
final float x = (float) converter.convertBack(settings.getDx());
final float y = (float) converter.convertBack(settings.getDy());
final float z = (float) converter.convertBack(settings.getDz());
// Reset the 2D bounds
if (x != 0 || y != 0) {
results.setBounds(null);
}
results.forEach((PeakResultProcedure) peakResult -> {
final float[] params = peakResult.getParameters();
params[PeakResult.X] += x;
params[PeakResult.Y] += y;
params[PeakResult.Z] += z;
});
}
use of uk.ac.sussex.gdsc.core.data.DataException in project GDSC-SMLM by aherbert.
the class TrackPopulationAnalysis method getTracks.
/**
* Gets the tracks. Each track has contiguous frames and the length is enough to fit
* {@code minTrackLength} overlapping windows of the specified size:
*
* <pre>
* length >= window + minTrackLength - 1
* </pre>
*
* @param combinedResults the combined results
* @param window the window size
* @param minTrackLength the minimum track length (assumed to be {@code >= 1})
* @return the tracks
*/
private static List<Trace> getTracks(List<MemoryPeakResults> combinedResults, int window, int minTrackLength) {
final LocalList<Trace> tracks = new LocalList<>();
final Statistics stats = new Statistics();
final int minSize = window + Math.max(minTrackLength, 1) - 1;
combinedResults.forEach(results -> {
final int start = tracks.size();
// Sort by id then frame
results = results.copy();
results.sort(IdFramePeakResultComparator.INSTANCE);
final int size = results.size();
// Skip IDs not associated with clustering
int index = 0;
while (index < size && results.get(index).getId() < 1) {
index++;
}
// Initialise current id and frame
int id = results.get(index).getId() - 1;
int frame = results.get(index).getFrame();
Trace track = new Trace();
for (; index < size; index++) {
final PeakResult result = results.get(index);
// Same ID and contiguous frames
if (result.getId() != id || result.getFrame() != frame + 1) {
addTrack(minSize, tracks, track);
track = new Trace();
}
id = result.getId();
frame = result.getFrame();
track.add(result);
}
addTrack(minSize, tracks, track);
stats.reset();
for (int i = start; i < tracks.size(); i++) {
stats.add(tracks.unsafeGet(i).size());
}
final StringBuilder sb = new StringBuilder(256);
TextUtils.formatTo(sb, "%s tracks=%d, length=%s +/- %s", results.getName(), stats.getN(), MathUtils.rounded(stats.getMean(), 3), MathUtils.rounded(stats.getStandardDeviation(), 3));
// Limit of diffusion coefficient from the localisation precision.
// Just use the entire dataset for simplicity (i.e. not the tracks of min length).
final PrecisionResultProcedure pp = new PrecisionResultProcedure(results);
try {
pp.getPrecision();
final Mean mean = new Mean();
for (final double p : pp.precisions) {
mean.add(p);
}
// 2nDt = MSD (n = number of dimensions)
// D = MSD / 2nt
final CalibrationReader reader = results.getCalibrationReader();
final double t = reader.getExposureTime() / 1000.0;
// Assume computed in nm. Convert to um.
final double x = mean.getMean() / 1000;
final double d = x * x / (2 * t);
TextUtils.formatTo(sb, ", precision=%s nm, D limit=%s um^2/s", MathUtils.rounded(x * 1000, 4), MathUtils.rounded(d, 4));
} catch (final DataException ex) {
// No precision
}
IJ.log(sb.toString());
});
return tracks;
}
use of uk.ac.sussex.gdsc.core.data.DataException in project GDSC-SMLM by aherbert.
the class PoissonCalculatorTest method canComputeLogLikelihoodRatio.
private static void canComputeLogLikelihoodRatio(RandomSeed seed, BaseNonLinearFunction nlf) {
logger.log(TestLogUtils.getRecord(LOG_LEVEL, nlf.name));
final int n = maxx * maxx;
final double[] a = new double[] { 1 };
// Simulate Poisson process
nlf.initialise(a);
final UniformRandomProvider rng = RngUtils.create(seed.getSeed());
final double[] x = new double[n];
final double[] u = new double[n];
for (int i = 0; i < n; i++) {
u[i] = nlf.eval(i);
if (u[i] > 0) {
x[i] = GdscSmlmTestUtils.createPoissonSampler(rng, u[i]).sample();
}
}
final DoubleDoubleBiPredicate predicate = TestHelper.doublesAreClose(1e-10, 0);
double ll = PoissonCalculator.logLikelihood(u, x);
final double mll = PoissonCalculator.maximumLogLikelihood(x);
double llr = -2 * (ll - mll);
double llr2 = PoissonCalculator.logLikelihoodRatio(u, x);
logger.log(TestLogUtils.getRecord(LOG_LEVEL, "llr=%f, llr2=%f", llr, llr2));
TestAssertions.assertTest(llr, llr2, predicate, "Log-likelihood ratio");
final double[] op = new double[x.length];
for (int i = 0; i < n; i++) {
op[i] = PoissonCalculator.maximumLikelihood(x[i]);
}
// TestSettings.setLogLevel(uk.ac.sussex.gdsc.smlm.TestLog.Level.FINE);
final int df = n - 1;
final ChiSquaredDistributionTable table = ChiSquaredDistributionTable.createUpperTailed(0.05, df);
final ChiSquaredDistributionTable table2 = ChiSquaredDistributionTable.createUpperTailed(0.001, df);
if (logger.isLoggable(LOG_LEVEL)) {
logger.log(TestLogUtils.getRecord(LOG_LEVEL, "Chi2 = %f (q=%.3f), %f (q=%.3f) %f %b %f", table.getCrititalValue(df), table.getSignificanceValue(), table2.getCrititalValue(df), table2.getSignificanceValue(), ChiSquaredDistributionTable.computeQValue(24, 2), ChiSquaredDistributionTable.createUpperTailed(0.05, 2).reject(24, 2), ChiSquaredDistributionTable.getChiSquared(1e-6, 2)));
}
final TDoubleArrayList list = new TDoubleArrayList();
final int imin = 5;
final int imax = 15;
for (int i = imin; i <= imax; i++) {
a[0] = (double) i / 10;
nlf.initialise(a);
for (int j = 0; j < n; j++) {
u[j] = nlf.eval(j);
}
ll = PoissonCalculator.logLikelihood(u, x);
list.add(ll);
llr = PoissonCalculator.logLikelihoodRatio(u, x);
BigDecimal product = new BigDecimal(1);
double ll2 = 0;
for (int j = 0; j < n; j++) {
final double p1 = PoissonCalculator.likelihood(u[j], x[j]);
ll2 += Math.log(p1);
final double ratio = p1 / op[j];
product = product.multiply(new BigDecimal(ratio));
}
llr2 = -2 * Math.log(product.doubleValue());
final double p = ChiSquaredDistributionTable.computePValue(llr, df);
final double q = ChiSquaredDistributionTable.computeQValue(llr, df);
logger.log(TestLogUtils.getRecord(LOG_LEVEL, "a=%f, ll=%f, ll2=%f, llr=%f, llr2=%f, product=%s, p=%f, q=%f " + "(reject=%b @ %.3f, reject=%b @ %.3f)", a[0], ll, ll2, llr, llr2, product.round(new MathContext(4)).toString(), p, q, table.reject(llr, df), table.getSignificanceValue(), table2.reject(llr, df), table2.getSignificanceValue()));
// too small to store in a double.
if (product.doubleValue() > 0) {
TestAssertions.assertTest(ll, ll2, predicate, "Log-likelihood");
TestAssertions.assertTest(llr, llr2, predicate, "Log-likelihood ratio");
}
}
// Find max using quadratic fit
final double[] data = list.toArray();
int index = SimpleArrayUtils.findMaxIndex(data);
final double maxa = (double) (imin + index) / 10;
double fita = maxa;
try {
if (index == 0) {
index++;
}
if (index == data.length - 1) {
index--;
}
final int i1 = index - 1;
final int i2 = index;
final int i3 = index + 1;
fita = QuadraticUtils.findMinMax((double) (imin + i1) / 10, data[i1], (double) (imin + i2) / 10, data[i2], (double) (imin + i3) / 10, data[i3]);
} catch (final DataException ex) {
// Ignore
}
// Allow a tolerance as the random data may alter the p-value computation.
// Should allow it to be less than 2 increment either side of the answer.
logger.log(TestLogUtils.getRecord(LOG_LEVEL, "max fit = %g => %g", maxa, fita));
Assertions.assertEquals(1, fita, 0.199, "max");
}
use of uk.ac.sussex.gdsc.core.data.DataException in project GDSC-SMLM by aherbert.
the class ScmosLikelihoodWrapperTest method canComputePValue.
private static void canComputePValue(RandomSeed seed, BaseNonLinearFunction nlf) {
logger.log(TestLogUtils.getRecord(Level.INFO, nlf.name));
final int n = maxx * maxx;
final double[] a = new double[] { 1 };
// Simulate sCMOS camera
nlf.initialise(a);
final SCcmosLikelihoodWrapperTestData testData = (SCcmosLikelihoodWrapperTestData) dataCache.computeIfAbsent(seed, ScmosLikelihoodWrapperTest::createData);
final float[] var = testData.var;
final float[] g = testData.gain;
final float[] o = testData.offset;
final float[] sd = testData.sd;
final UniformRandomProvider r = RngUtils.create(seed.getSeed());
final SharedStateContinuousSampler gs = SamplerUtils.createGaussianSampler(r, 0, 1);
final double[] k = SimpleArrayUtils.newArray(n, 0, 1.0);
for (int i = 0; i < n; i++) {
double mean = nlf.eval(i);
if (mean > 0) {
mean = GdscSmlmTestUtils.createPoissonSampler(r, mean).sample();
}
k[i] = mean * g[i] + o[i] + gs.sample() * sd[i];
}
final ScmosLikelihoodWrapper f = new ScmosLikelihoodWrapper(nlf, a, k, n, var, g, o);
final double oll = f.computeObservedLikelihood();
double oll2 = 0;
final double[] op = new double[n];
for (int j = 0; j < n; j++) {
op[j] = ScmosLikelihoodWrapper.likelihood((k[j] - o[j]) / g[j], var[j], g[j], o[j], k[j]);
oll2 -= Math.log(op[j]);
}
logger.log(TestLogUtils.getRecord(Level.INFO, "oll=%f, oll2=%f", oll, oll2));
final DoubleDoubleBiPredicate predicate = TestHelper.doublesAreClose(1e-10, 0);
TestAssertions.assertTest(oll2, oll, predicate, "Observed Log-likelihood");
final TDoubleArrayList list = new TDoubleArrayList();
final int imin = 5;
final int imax = 15;
for (int i = imin; i <= imax; i++) {
a[0] = (double) i / 10;
final double ll = f.likelihood(a);
list.add(ll);
final double llr = f.computeLogLikelihoodRatio(ll);
BigDecimal product = new BigDecimal(1);
double ll2 = 0;
for (int j = 0; j < n; j++) {
final double p1 = ScmosLikelihoodWrapper.likelihood(nlf.eval(j), var[j], g[j], o[j], k[j]);
ll2 -= Math.log(p1);
final double ratio = p1 / op[j];
product = product.multiply(new BigDecimal(ratio));
}
final double llr2 = -2 * Math.log(product.doubleValue());
final double q = f.computeQValue(ll);
logger.log(TestLogUtils.getRecord(Level.INFO, "a=%f, ll=%f, ll2=%f, llr=%f, llr2=%f, product=%s, p=%f", a[0], ll, ll2, llr, llr2, product.round(new MathContext(4)).toString(), q));
// too small to store in a double.
if (product.doubleValue() > 0) {
TestAssertions.assertTest(llr, llr2, predicate, "Log-likelihood");
}
}
// Find min using quadratic fit
final double[] data = list.toArray();
int index = SimpleArrayUtils.findMinIndex(data);
final double mina = (double) (imin + index) / 10;
double fita = mina;
try {
if (index == 0) {
index++;
}
if (index == data.length - 1) {
index--;
}
final int i1 = index - 1;
final int i2 = index;
final int i3 = index + 1;
fita = QuadraticUtils.findMinMax((double) (imin + i1) / 10, data[i1], (double) (imin + i2) / 10, data[i2], (double) (imin + i3) / 10, data[i3]);
} catch (final DataException ex) {
// Ignore
}
// Allow a tolerance as the random data may alter the p-value computation.
// Should allow it to be less than 2 increment either side of the answer.
logger.log(TestLogUtils.getRecord(Level.INFO, "min fit = %g => %g", mina, fita));
Assertions.assertEquals(1, fita, 0.199, "min");
}
use of uk.ac.sussex.gdsc.core.data.DataException in project GDSC-SMLM by aherbert.
the class CreateFilters method processElement.
private int processElement(StringWriter sw, Node node) throws TransformerFactoryConfigurationError {
// Get entire element as a string
final String xmlString = uk.ac.sussex.gdsc.core.utils.XmlUtils.getString(node, false);
ArrayList<StringBuilder> out = new ArrayList<>();
// Process through the XML appending to the current output.
final String[] tokens = xmlString.split("\\s+");
for (final String token : tokens) {
// Any attributes with enumerations should be expanded.
final Matcher match = pattern.matcher(token);
if (match.find()) {
final String prefix = " " + match.group(1) + "=\"";
// Use Big Decimal for the enumeration to preserve the precision of the input text
// (i.e. using doubles for an enumeration can lose precision and fail to correctly
// enumerate)
BigDecimal min;
BigDecimal max;
BigDecimal inc;
try {
min = new BigDecimal(match.group(2));
max = new BigDecimal(match.group(3));
inc = new BigDecimal(match.group(4));
if (min.compareTo(max) > 0 || inc.compareTo(BigDecimal.ZERO) <= 0) {
throw new DataException("Invalid 'min:max:increment' attribute: " + token);
}
} catch (final NumberFormatException ex) {
throw new DataException("Invalid 'min:max:increment' attribute: " + token, ex);
}
final String suffix = "\"" + match.group(5);
// Enumerate the attribute
final ArrayList<String> attributeText = new ArrayList<>();
for (BigDecimal bd = min; bd.compareTo(max) <= 0; bd = bd.add(inc)) {
attributeText.add(prefix + bd.toString() + suffix);
}
// Add to the current output
final ArrayList<StringBuilder> out2 = new ArrayList<>(out.size() * attributeText.size());
if (enumerateEarly) {
// Enumerate earlier attributes first
for (final String text : attributeText) {
for (final StringBuilder sb : out) {
out2.add(new StringBuilder(sb.toString()).append(text));
}
}
} else {
// Enumerate later attributes first
for (final StringBuilder sb : out) {
final String current = sb.toString();
for (final String text : attributeText) {
out2.add(new StringBuilder(current).append(text));
}
}
}
out = out2;
} else if (out.isEmpty()) {
out.add(new StringBuilder(token));
} else {
for (final StringBuilder sb : out) {
sb.append(" ").append(token);
}
}
}
if (!out.isEmpty()) {
sw.write("<FilterSet name=\"");
sw.write(getName(out.get(0)));
sw.write("\"><filters class=\"linked-list\">");
for (final StringBuilder sb : out) {
sw.write(sb.toString());
}
sw.write("</filters></FilterSet>");
}
return out.size();
}
Aggregations