edu.ucsf.valelab.saim.calculations.SaimCalc.java Source code

Java tutorial

Introduction

Here is the source code for edu.ucsf.valelab.saim.calculations.SaimCalc.java

Source

///////////////////////////////////////////////////////////////////////////////
//FILE:          SaimCalc.java
//PROJECT:       SAIM
//-----------------------------------------------------------------------------
//
// AUTHOR:       Nico Stuurman
//
// COPYRIGHT:    University of California, San Francisco 2015
//
// LICENSE:      This file is distributed under the BSD license.
//               License text is included with the source distribution.
//
//               This file is distributed in the hope that it will be useful,
//               but WITHOUT ANY WARRANTY; without even the implied warranty
//               of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
//               IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//               CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//               INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES.

package edu.ucsf.valelab.saim.calculations;

import edu.ucsf.valelab.saim.data.RI;
import org.apache.commons.math3.complex.Complex;

/**
 * Various calculations needed in the calculation of the strength of the local 
 * electric field as described in:
 * Paszek, M.J., C.C. DuFort, M.G. Rubashkin, M.W. Davidson, K.S. Thorn, J.T. 
 * Liphardt, and V.M. Weaver. 2012. 
 * Scanning angle interference microscopy reveals cell dynamics at the nanoscale. 
 * Nat Meth. 9:825827. doi:10.1038/nmeth.2077.
 * 
 * @author nico
 */
public class SaimCalc {

    /**
     * Calculates the phase difference as a function of height as described in:
     * Paszek, M.J., C.C. DuFort, M.G. Rubashkin, M.W. Davidson, K.S. Thorn, J.T. 
     * Liphardt, and V.M. Weaver. 2012. 
     * Scanning angle interference microscopy reveals cell dynamics at the nanoscale. 
     * Nat Meth. 9:825827. doi:10.1038/nmeth.2077.
     *
     * @param wavelength of the excitation light source in nm
     * @param nSample refractive index of the sample medium
     * @param angle Angle with respect to the normal in the sample in radians
     * @param axialPos Position in the sample above the silicon oxide (in nm)
     * @return phase difference (dimensionless)
     */
    public static double PhaseDiff(final double wavelength, final double angle, final double nSample,
            final double axialPos) {
        return 4.0 * Math.PI * nSample * axialPos * Math.cos(angle) / wavelength;
    }

    /**
     * Calculates the transverse electric (TE) component, perpendicular to the 
     * plane of incidence, of the Fresnel coefficient of reflection between the 
     * sample interface and the virtual silicon oxidesilicon layer, 
     * as described in:
     * Paszek, M.J., C.C. DuFort, M.G. Rubashkin, M.W. Davidson, K.S. Thorn, J.T. 
     * Liphardt, and V.M. Weaver. 2012. 
     * Scanning angle interference microscopy reveals cell dynamics at the nanoscale. 
     * Nat Meth. 9:825827. doi:10.1038/nmeth.2077.
     * 
     * 
     * 1/11/2016: Note that the above manuscript contains a mistake that is corrected
     * in a later publication: http://dx.doi.org/10.1016/B978-0-12-420138-5.00013-6
     * That correction is now applied.
     * 
     * 
     * @param wavelength of the excitation light source in nm
     * @param angle with respect to the normal in radiance
     * @param dOx Thickness of the Silicon Oxide layer in nm
     * @param nSample Refractive index of the sample's buffer
     * @return FresnelCoefficient for these conditions
     */
    public static Complex fresnelTE(final double wavelength, final double angle, final double dOx,
            final double nSample) {

        double nSi = RI.getRI(RI.Compound.SILICON, wavelength);
        double nOx = RI.getRI(RI.Compound.SILICONOXIDE, wavelength);
        double kOx = k(wavelength, nOx);
        double angleOx = snell2(angle, nSample, RI.getRI(RI.Compound.SILICONOXIDE, wavelength));
        double cosOx = Math.cos(angleOx);
        double cosSi = Math.cos(snell2(angleOx, nOx, RI.getRI(RI.Compound.SILICON, wavelength)));
        double p0 = nSi * cosSi;
        double p1 = nOx * cosOx;
        double p2 = nSample * Math.cos(angle);
        double kOxdOxCosOx = kOx * dOx * cosOx;

        double cosOfkOxdOxCosOx = Math.cos(kOxdOxCosOx);
        double sinOfkOxdOxCosOx = Math.sin(kOxdOxCosOx);

        double m11TE = cosOfkOxdOxCosOx;
        Complex m12TE = Complex.I.multiply(-1 / p1 * sinOfkOxdOxCosOx);
        Complex m21TE = Complex.I.multiply(-p1 * sinOfkOxdOxCosOx);
        double m22TE = cosOfkOxdOxCosOx;

        Complex tmp1 = ((m12TE.multiply(p0)).add(m11TE)).multiply(p2);
        // this is the only line changed due to the error in the NM paper
        Complex tmp2 = tmp1.subtract(m21TE.add(m22TE * p0));
        //Complex tmp2 = tmp1.add( m21TE.subtract(m22TE * p0) );
        Complex tmp3 = tmp1.add(m21TE.add(m22TE * p0));
        Complex rTE = tmp2.divide(tmp3);

        return rTE;
    }

    public static double fieldStrength(final double wavelength, final double angle, final double nSample,
            final double dOx, final double distance) {
        Complex rTE = fresnelTE(wavelength, angle, dOx, nSample);
        double phaseDiff = PhaseDiff(wavelength, angle, nSample, distance);
        Complex tmp = new Complex(Math.cos(phaseDiff), Math.sin(phaseDiff));
        Complex fieldStrength = rTE.multiply(tmp);
        fieldStrength = fieldStrength.add(1.0);

        return fieldStrength.getReal() * fieldStrength.getReal()
                + fieldStrength.getImaginary() * fieldStrength.getImaginary();
    }

    /**
     * Returns the angular wavenumber given the wavelength and refractive index
     * See: https://en.wikipedia.org/wiki/Wavenumber#In_wave_equations
     * @param wavelength in nm in vacuum
     * @param ri refractive index of the compound of interest
     * @return wavenumber (in radians per nm)
     */
    public static double k(double wavelength, double ri) {
        return 2.0 * Math.PI * ri / wavelength;
    }

    /**
     * Calculates the angle of incidence for light traveling through a medium
     * with known refractive index and angle of incidence into a medium with 
     * another known refractive index using Snell's law: sin(1)/sin(2) = n2/n1
     * See: https://en.wikipedia.org/wiki/Snell%27s_law
     * 
     * @param angle1 angle with respect to the normal in radiance in medium 1
     * @param ri1 Refractive index of medium 1
     * @param ri2 Refractive index of medium 2
     * @return angle of incidence in medium 2 in radiance
     */
    public static double snell2(double angle1, double ri1, double ri2) {
        double sinAngle2 = ri1 * Math.sin(angle1) / ri2;
        return Math.asin(sinAngle2);
    }
}