package gdsc.smlm.model; /*----------------------------------------------------------------------------- * 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 model for an image of blinking fluorophores under pulsed activation illumination. Activation energy is * sampled from an exponential distribution. Fluorophores are created when the activation energy has been achieved under * the given illumination. * <p> * Based on the work of Coltharp et al (2012) Accurate Construction of photoactivated localization microscopy images for * quantitative measurements. PLOS One 7, Issue 12, pp 1-15 */ public class ActivationEnergyImageModel extends ImageModel { private double eAct; private SpatialIllumination illumination; /** * Construct a new image model * * @param eAct * Average energy for activation * @param illumination * The illumination model * @param tOn * Average on-state time * @param tOff * Average off-state time for the first dark state * @param tOff2 * Average off-state time for the second dark state * @param nBlinks * Average number of blinks int the first dark state (used for each burst between second dark states) * @param nBlinks2 * Average number of blinks into the second dark state */ public ActivationEnergyImageModel(double eAct, SpatialIllumination illumination, double tOn, double tOff, double tOff2, double nBlinks, double nBlinks2) { super(tOn, tOff, tOff2, nBlinks, nBlinks2); init(eAct, illumination); } private void init(double eAct, SpatialIllumination illumination) { checkParameter("eAct", eAct); if (illumination == null) throw new IllegalArgumentException("SpatialIllumination is null"); this.eAct = eAct; this.illumination = illumination; } /** * @return the average energy for activation */ public double getActivationEnergy() { return eAct; } /* * (non-Javadoc) * * @see gdsc.smlm.model.ImageModel#createActivationTime(double[]) */ @Override protected double createActivationTime(double[] xyz) { return getActivationTime(xyz, frameLimit); } /* * (non-Javadoc) * * @see gdsc.smlm.model.ImageModel#createFluorophore(int, double[], double) */ @Override protected FluorophoreSequenceModel createFluorophore(int id, double[] xyz, double tAct) { return new StandardFluorophoreSequenceModel(id, xyz, tAct, tOn, tOff, tOff2, nBlinks, nBlinks2, isUseGeometricDistribution(), getRandom()); } private double getActivationTime(double[] xyz, int frames) { final double activation = getRandom().nextExponential(eAct); double e = 0; for (int t = 0; t < frames; t++) { // Q. Should the molecule be moving during the activation phase? final double[] photons = illumination.getPulsedPhotons(xyz, t + 1); e += photons[0]; // pulse energy if (e > activation) return t; e += photons[1]; // during energy if (e > activation) { // Interpolate return t + 1 - (e - activation) / photons[1]; } } return frames; // default to the number of frames. } }