package gdsc.smlm.results; /*----------------------------------------------------------------------------- * 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. *---------------------------------------------------------------------------*/ /** * Contain the calibration settings for the microscope * <p> * The calibration has flags to indicate that a valid value has been set for each property. If these are false then the * property get method can optionally throw an exception. */ public class Calibration implements Cloneable { // State flags private static int FIELD_MISSING_EXCEPTION = 0x00000001; private static int FIELD_NM_PER_PIXEL = 0x00000002; private static int FIELD_GAIN = 0x00000004; private static int FIELD_EXPOSURE_TIME = 0x00000008; private static int FIELD_READ_NOISE = 0x00000010; private static int FIELD_BIAS = 0x00000020; private static int FIELD_EM_CCD = 0x00000040; private static int FIELD_AMPLIFICATION = 0x00000080; private int fields = 0; /** * Checks if an exception will be thrown when accessing a field that is missing. * * @return true, if is field missing exceptions are enabled */ public boolean isFieldMissingException() { return ((fields & FIELD_MISSING_EXCEPTION) == FIELD_MISSING_EXCEPTION); } /** * Sets the field missing exception enabled flag. If true an exception will be thrown when accessing a field that is * missing. * * @param enabled * the new field missing exception enabled flag */ public void setFieldMissingException(boolean enabled) { if (enabled) fields |= FIELD_MISSING_EXCEPTION; else fields = fields & ~FIELD_MISSING_EXCEPTION; } public boolean hasNmPerPixel() { return ((fields & FIELD_NM_PER_PIXEL) == FIELD_NM_PER_PIXEL); } public boolean hasGain() { return ((fields & FIELD_GAIN) == FIELD_GAIN); } public boolean hasExposureTime() { return ((fields & FIELD_EXPOSURE_TIME) == FIELD_EXPOSURE_TIME); } public boolean hasReadNoise() { return ((fields & FIELD_READ_NOISE) == FIELD_READ_NOISE); } public boolean hasBias() { return ((fields & FIELD_BIAS) == FIELD_BIAS); } public boolean hasEMCCD() { return ((fields & FIELD_EM_CCD) == FIELD_EM_CCD); } public boolean hasAmplification() { return ((fields & FIELD_AMPLIFICATION) == FIELD_AMPLIFICATION); } private void setHasNmPerPixel() { fields |= FIELD_NM_PER_PIXEL; } private void setHasGain() { fields |= FIELD_GAIN; } private void setHasExposureTime() { fields |= FIELD_EXPOSURE_TIME; } private void setHasReadNoise() { fields |= FIELD_READ_NOISE; } private void setHasBias() { fields |= FIELD_BIAS; } private void setHasEMCCD() { fields |= FIELD_EM_CCD; } private void setHasAmplification() { fields |= FIELD_AMPLIFICATION; } public void clearHasNmPerPixel() { fields = fields & ~FIELD_NM_PER_PIXEL; } public void clearHasGain() { fields = fields & ~FIELD_GAIN; } public void clearHasExposureTime() { fields = fields & ~FIELD_EXPOSURE_TIME; } public void clearHasReadNoise() { fields = fields & ~FIELD_READ_NOISE; } public void clearHasBias() { fields = fields & ~FIELD_BIAS; } public void clearHasEMCCD() { fields = fields & ~FIELD_EM_CCD; } public void clearHasAmplification() { fields = fields & ~FIELD_AMPLIFICATION; } /** * The image pixel size in nanometers */ private double nmPerPixel = 107; /** * The gain (ADUs/photon). Can be used to convert the signal in Analogue-to-Digital units * (ADUs) to photons. */ private double gain = 37.7; /** * The exposure time in milliseconds per frame */ private double exposureTime; /** * The CCD camera Gaussian read noise (in ADUs) */ private double readNoise; /** * The CCD camera bias (in ADUs) */ private double bias; /** * True if the CCD camera was run in Electron Multiplying (EM) mode */ private boolean emCCD; /** * The camera amplification (ADUs/e-) used when modelling a microscope camera. * <p> * Note that the camera noise model assumes that electrons are converted to ADUs by amplification that is not * perfect (i.e. it has noise). The amplification is equal to the gain (ADUs/photon) divided by the quantum * efficiency (e-/photon). */ private double amplification; /** * Default constructor. All properties are set to be invalid but field missing exceptions are disabled. */ public Calibration() { } /** * All properties are set to be invalid but missing exceptions can be enabled. * * @param fieldMissingExceptionEnabled * Set to true to enable the field missing exceptions in the get methods */ public Calibration(boolean fieldMissingExceptionEnabled) { setFieldMissingException(fieldMissingExceptionEnabled); } /** * Parameterised constructor for essential settings. * * @param nmPerPixel * the nm per pixel * @param gain * the gain * @param exposureTime * the exposure time */ public Calibration(double nmPerPixel, double gain, double exposureTime) { this.setNmPerPixel(nmPerPixel); this.setGain(gain); this.setExposureTime(exposureTime); } /* * (non-Javadoc) * * @see java.lang.Object#clone() */ public Calibration clone() { Calibration c; try { c = (Calibration) super.clone(); } catch (CloneNotSupportedException e) { return null; } return c; } /** * Clear the calibration (set all valid flags to false). */ public void clear() { // Clear all but the field missing flag fields = fields & FIELD_MISSING_EXCEPTION; } /** * Validate the calibration by calling each property setter with the current value. This will set the valid flags to * false if the current value is not valid. */ public void validate() { setNmPerPixel(nmPerPixel); setGain(gain); setExposureTime(exposureTime); setReadNoise(readNoise); setBias(bias); setEmCCD(emCCD); setAmplification(amplification); } /** * Gets image pixel size in nanometers. * * @return image pixel size in nanometers * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set to a valid value */ public double getNmPerPixel() { if (isFieldMissingException() && !hasNmPerPixel()) throw new IllegalStateException(); return nmPerPixel; } /** * Sets the image pixel size in nanometers. * * @param nmPerPixel * image pixel size in nanometers */ public void setNmPerPixel(double nmPerPixel) { if (nmPerPixel > 0) { setHasNmPerPixel(); this.nmPerPixel = nmPerPixel; } else clearHasNmPerPixel(); } /** * Gets the gain (ADUs/photon). Can be used to convert the signal in Analogue-to-Digital units * (ADUs) to photons. * * @return the gain * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set to a valid value */ public double getGain() { if (isFieldMissingException() && !hasGain()) throw new IllegalStateException(); return gain; } /** * Sets the (ADUs/photon). Can be used to convert the signal in Analogue-to-Digital units * (ADUs) to photons. * * @param gain * the new gain */ public void setGain(double gain) { if (gain > 0) { setHasGain(); this.gain = gain; } else clearHasGain(); } /** * Gets the exposure time in milliseconds per frame. * * @return the exposure time * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set to a valid value */ public double getExposureTime() { if (isFieldMissingException() && !hasExposureTime()) throw new IllegalStateException(); return exposureTime; } /** * Sets the exposure time in milliseconds per frame * * @param exposureTime * the new exposure time */ public void setExposureTime(double exposureTime) { if (exposureTime > 0) { setHasExposureTime(); this.exposureTime = exposureTime; } else clearHasExposureTime(); } /** * Gets the CCD camera Gaussian read noise (in ADUs). * * @return the CCD camera Gaussian read noise (in ADUs) * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set to a valid value */ public double getReadNoise() { if (isFieldMissingException() && !hasReadNoise()) throw new IllegalStateException(); return readNoise; } /** * Sets CCD camera Gaussian read noise (in ADUs). * * @param readNoise * the new read noise */ public void setReadNoise(double readNoise) { if (readNoise >= 0) { setHasReadNoise(); this.readNoise = readNoise; } else clearHasReadNoise(); } /** * Gets CCD camera bias (in ADUs). * * @return CCD camera bias (in ADUs) * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set to a valid value */ public double getBias() { if (isFieldMissingException() && !hasBias()) throw new IllegalStateException(); return bias; } /** * Sets CCD camera bias (in ADUs). * * @param bias * the new bias */ public void setBias(double bias) { if (bias >= 0) { setHasBias(); this.bias = bias; } else clearHasBias(); } /** * Checks if the CCD camera was run in Electron Multiplying (EM) mode. * * @return true, if the CCD camera was run in Electron Multiplying (EM) mode. * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set */ public boolean isEmCCD() { if (isFieldMissingException() && !hasEMCCD()) throw new IllegalStateException(); return emCCD; } /** * Set if the CCD camera was run in Electron Multiplying (EM) mode. * * @param emCCD * true, if the CCD camera was run in Electron Multiplying (EM) mode. */ public void setEmCCD(boolean emCCD) { setHasEMCCD(); this.emCCD = emCCD; } /** * Get the camera amplification (ADUs/e-) used when modelling a microscope camera. * <p> * Note that the camera noise model assumes that electrons are converted to ADUs by amplification that is not * perfect (i.e. it has noise). The amplification is equal to the gain (ADUs/photon) divided by the quantum * efficiency (e-/photon). * * @return the amplification * @throws IllegalStateException if the missing field exceptions is enabled and the field has not been set to a valid value */ public double getAmplification() { if (isFieldMissingException() && !hasAmplification()) throw new IllegalStateException(); return amplification; } /** * Set the camera amplification (ADUs/e-) used when modelling a microscope camera. * <p> * Note that the camera noise model assumes that electrons are converted to ADUs by amplification that is not * perfect (i.e. it has noise). The amplification is equal to the gain (ADUs/photon) divided by the quantum * efficiency (e-/photon). * * @param amplification * the new amplification */ public void setAmplification(double amplification) { if (amplification > 0) { setHasAmplification(); this.amplification = amplification; } else clearHasAmplification(); } }