package gdsc.smlm.model; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /*----------------------------------------------------------------------------- * GDSC SMLM Software * * Copyright (C) 2013 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. *---------------------------------------------------------------------------*/ /** * Contains a collection of localisations associated with a discrete-time. This can be used to model a moving * localisation * simulated on a more refined time-scale to a single localisation. */ public class LocalisationModelSet implements Comparable<LocalisationModelSet> { private int id, time; private List<LocalisationModel> localisations = new ArrayList<LocalisationModel>(); private double[] data = null; private LocalisationModelSet previous, next; /** * Create a new localisation * * @param id * @param time */ public LocalisationModelSet(int id, int time) { this.id = id; this.time = time; } public void add(LocalisationModel l) { localisations.add(l); } public int size() { return localisations.size(); } public List<LocalisationModel> getLocalisations() { return localisations; } /** * @return The Id */ public int getId() { return id; } /** * Allow the package to set the id * * @param id * The Id */ void setId(int id) { this.id = id; } /** * @return The time */ public int getTime() { return time; } /* * (non-Javadoc) * * @see java.lang.Comparable#compareTo(java.lang.Object) */ public int compareTo(LocalisationModelSet o) { return time - o.time; } /** * @return True if this localisation is on for the entire duration of the time interval */ public boolean isContinuous() { if (localisations.isEmpty()) return false; // All localisations must be continuous and consecutive in time int[] t = new int[localisations.size()]; int c = 0; for (LocalisationModel l : localisations) { t[c++] = l.getTime(); if (!l.isContinuous()) return false; } // Check consecutive in time Arrays.sort(t); if ((t[t.length - 1] - t[0] + 1) > c) return false; //System.out.printf("continuous size = %d\n", localisations.size()); return true; } /** * @return the data */ public double[] getData() { return data; } /** * @param data * the data to set */ public void setData(double[] data) { this.data = data; } /** * Convert the set of localisations to a single localisation with the combined signal and the centroid location * (centre-of-mass weighted by intensity). * * @return */ public LocalisationModel toLocalisation() { double intensity = 0; double[] xyz = new double[3]; for (LocalisationModel l : localisations) { final double s = l.getIntensity(); intensity += s; final double[] xyz2 = l.getCoordinates(); for (int i = 0; i < 3; i++) xyz[i] += xyz2[i] * s; } if (!localisations.isEmpty()) for (int i = 0; i < 3; i++) xyz[i] /= intensity; LocalisationModel l = new LocalisationModel(id, time, xyz, intensity, isContinuous() ? LocalisationModel.CONTINUOUS : LocalisationModel.SINGLE); l.setData(data); return l; } /** * @return The total intensity */ public double getIntensity() { double intensity = 0; for (LocalisationModel l : localisations) intensity += l.getIntensity(); return intensity; } /** * @return the previous */ public LocalisationModelSet getPrevious() { return previous; } /** * @param previous * the previous to set */ public void setPrevious(LocalisationModelSet previous) { this.previous = previous; if (previous != null) previous.next = this; } /** * @return the next */ public LocalisationModelSet getNext() { return next; } /** * @param next * the next to set */ public void setNext(LocalisationModelSet next) { this.next = next; if (next != null) next.previous = this; } /** * @return True if either of the previous/next pointers are not null */ public boolean hasNeighbour() { return next != null || previous != null; } }