knop.psfj.BeadFrameList.java Source code

Java tutorial

Introduction

Here is the source code for knop.psfj.BeadFrameList.java

Source

/*
This file is part of PSFj.
    
PSFj 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.
    
PSFj 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.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with PSFj.  If not, see <http://www.gnu.org/licenses/>. 
    
   Copyright 2013,2014 Cyril MONGIS, Patrick Theer, Michael Knop
       
 */
package knop.psfj;

import ij.process.Blitter;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;

import knop.psfj.resolution.Microscope;
import knop.psfj.utils.MathUtils;

import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;

// TODO: Auto-generated Javadoc
/**
 * The Class BeadFrameList.
 */
public class BeadFrameList extends ArrayList<BeadFrame> {

    /**
     * The bead hashmap. This hashmap is used for retrieving beads by there id.
     * However, it becomes useless when mixing beads from different sources.
     * */
    HashMap<Integer, BeadFrame> beadHash = new HashMap<Integer, BeadFrame>();

    String[] FWHM_NORM_NAMES = new String[] { "FWHMmin / Theoretical FWHMxy", "FWHMmax / Theoretical FWHMxy",
            "FWHMz / Theoretical FWHMz" };

    /**
     * Returns a FovDataSet of the valid beads contained inside the bead frame
     * list.
     * 
     * @return the data set
     */
    public FovDataSet getDataSet() {
        return getDataSet(true, false);
    }

    /**
     * Returns a new BeadFrameList object containing only the valid beads.
     * 
     * @return the only valid beads
     */
    public BeadFrameList getOnlyValidBeads() {
        BeadFrameList list = new BeadFrameList();
        for (BeadFrame frame : this) {
            if (frame.isValid())
                list.add(frame);
        }
        return list;
    }

    /**
     * Returns a new BeadFrameList object containing only the beads paired with
     * an alter ego.
     * 
     * @return the with alter ego
     */
    public BeadFrameList getWithAlterEgo() {
        BeadFrameList list = new BeadFrameList();
        for (BeadFrame frame : this) {
            if (frame.getAlterEgo() != null)
                list.add(frame);
        }
        return list;
    }

    /**
     * Return a FovDataSet of the beads containd inside the list. if
     * excludeNonValid is true, only valid beads will be included in the data
     * set. Elsewhere, valid and non-valid beads will be included.
     * 
     * @param excludeNonValid
     *            the exclude non valid
     * @return the data set
     */
    public FovDataSet getDataSet(boolean excludeNonValid) {
        return getDataSet(excludeNonValid, true);
    }

    /**
     * Gets the data set.
     *
     * @param excludeNonValid the exclude non valid
     * @param includeMultichannelData the include multichannel data
     * @return the data set
     */
    public FovDataSet getDataSet(boolean excludeNonValid, boolean includeMultichannelData) {

        // instanciating the data set
        FovDataSet dataSet = new FovDataSet();

        // if the list is empty, the function is aborted
        if (size() == 0)
            return dataSet;

        // retrieving the microscope settings of the beads contained inside the
        // list
        Microscope m = get(0).getSource().getMicroscope(); // get the microscope
        // setting of the
        // first bead
        String unit = m.getUnit();

        if (includeMultichannelData) {
            dataSet.addColumn(PSFj.WAVELENGHT_KEY).setName("Wavelength");
        }
        dataSet.addColumn(PSFj.BEAD_ID).setName("Bead Id");
        ;

        String[] axeStrings = new String[] { "min", "max", "z" };

        for (int axe : PSFj.AXES) {

            String columnNameNotNormalized = String.format("FWHM %s", axeStrings[axe]);
            String columnNameNotCorrected = columnNameNotNormalized + " not corrected";
            String columnNameNormalized = FWHM_NORM_NAMES[axe];
            String rCoeffName = String.format("R^2 FWHM%s", axeStrings[axe]);
            if (axe < 2)
                rCoeffName = "R^2 FWHMmin;max";
            dataSet.addColumn(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NOT_NORMALIZED)).setUnit(unit)
                    .setName(columnNameNotNormalized);
            ;
            dataSet.addColumn(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NOT_NORMALIZED) + "_nc").setUnit(unit)
                    .setName(columnNameNotCorrected);
            ;
            ;
            dataSet.addColumn(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NORMALIZED))
                    .setName(columnNameNormalized);
            ;
            dataSet.addColumn(PSFj.getColumnName(PSFj.R_COEFF_KEY, axe, PSFj.NOT_NORMALIZED)).setName(rCoeffName);
        }

        dataSet.addColumn(PSFj.ASYMMETRY_KEY).setName("Asymmetry");
        dataSet.addColumn(PSFj.THETA_KEY).setName("Theta").setUnit(MathUtils.DEGREES);

        dataSet.addColumn(PSFj.XC).setUnit(unit).setName("Bead x coordinates");
        dataSet.addColumn(PSFj.YC).setUnit(unit).setName("Bead y coordinates");
        dataSet.addColumn(PSFj.RADIUS).setUnit(unit).setName("Distance from the center");
        dataSet.addColumn(PSFj.Z_PROFILE, PSFj.NOT_NORMALIZED).setUnit(unit).setName("z0");
        ;
        dataSet.addColumn(PSFj.Z_PROFILE, PSFj.NORMALIZED).setName("(z0 - mean(z0)) / FWHMz");
        ;
        dataSet.addColumn(PSFj.Z0_ZMEAN).setUnit(unit);

        dataSet.addColumn(PSFj.THRESHOLD_KEY).setName("Threshold");
        dataSet.addColumn(PSFj.FRAME_SIZE_KEY).setName("Frame size");
        dataSet.addColumn(PSFj.SOURCE_IMAGE).setName("Image name");

        if (get(0) instanceof BeadFrame2D) {
            dataSet.addColumn(PSFj.SIGMA_X_KEY).setName("Sigma X").setUnit(unit);
            dataSet.addColumn(PSFj.SIGMA_Y_KEY).setName("Sigma Y").setUnit(unit);
            dataSet.addColumn(PSFj.THETA_IN_RADIAN_KEY).setName("Theta").setUnit(MathUtils.RADIANT);
        }

        axeStrings = new String[] { "x", "y", "z" };
        String[] axeNormsValue = new String[] { "XY", "XY", "Z" };

        if (includeMultichannelData) {

            for (int axe : PSFj.AXES) {
                String notNormName = String.format("Chromatic shift in %s", axeStrings[axe]);
                String normName = String.format("Chromatic shift in %s / Theo. FWHM %s", axeStrings[axe],
                        axeNormsValue[axe]);

                dataSet.addColumn(PSFj.CHR_SHIFT_KEY, axe, PSFj.NOT_NORMALIZED).setUnit(unit).setName(notNormName);
                ;
                dataSet.addColumn(PSFj.CHR_SHIFT_KEY, axe, PSFj.NORMALIZED).setName(normName);
            }

            dataSet.addColumn(PSFj.CHR_SHIFT_XY, PSFj.NOT_NORMALIZED).setUnit(unit).setName("Chromatic shift (XY)");
            dataSet.addColumn(PSFj.CHR_SHIFT_XY, PSFj.NORMALIZED).setName("Chromatic shift (XY) / Theo. FWHMxy");

            dataSet.addColumn(PSFj.CHR_SHIFT_XYZ, PSFj.NOT_NORMALIZED).setUnit(unit)
                    .setName("Chromatic shift (XYZ) ");
            dataSet.addColumn(PSFj.CHR_SHIFT_XYZ, PSFj.NORMALIZED).setName("Chromatic shift (XYZ) / Theo. FWHMz");

        }

        dataSet.addColumn(PSFj.IS_FITTING_VALID).setName("Fit valid");

        // for each bead of the list
        for (BeadFrame bead : this) {

            // if excludeNonValid is true and the current bead is not valid,
            // it's not included in the data set
            if (excludeNonValid == true && bead.isValid() == false)
                continue;

            for (int axe : PSFj.AXES) {
                dataSet.addValue(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NOT_NORMALIZED),
                        bead.getCorrectionResolution(axe));
                dataSet.addValue(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NOT_NORMALIZED) + "_nc",
                        bead.getResolution(axe));
                dataSet.addValue(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NORMALIZED),
                        bead.getCorrectionResolution(axe)
                                / bead.getSource().getMicroscope().getTheoreticalResolution(axe));

            }

            dataSet.addValue(PSFj.SOURCE_IMAGE, bead.getSource().getImageNameWithoutExtension());

            // adding bead position to the dataset
            dataSet.addValue(PSFj.BEAD_ID, bead.getId());

            if (includeMultichannelData) {
                dataSet.addValue(PSFj.WAVELENGHT_KEY, bead.getSource().getMicroscope().getWaveLength() * 1000);
            }

            dataSet.addValue(PSFj.XC, bead.getFovX());
            dataSet.addValue(PSFj.YC, bead.getFovY());
            dataSet.addValue(PSFj.RADIUS, bead.getDistanceFromCenter());

            double z_profile = bead.getCParameter(BeadFrame.Z);

            dataSet.addValue(PSFj.Z_PROFILE, PSFj.NOT_NORMALIZED, z_profile);

            /*
            // corrected and uncorrected resolutions
            dataSet.addValue("fwhmX", correctedResolutionX);
            dataSet.addValue("fwhmY", correctedResolutionY);
            dataSet.addValue("fwhmZ", correctedResolutionZ);
                
            dataSet.addValue("fwhmX_norm",
                  correctedResolutionX / m.getXYTheoreticalResolution());
            dataSet.addValue("fwhmY_norm",
                  correctedResolutionY / m.getXYTheoreticalResolution());
            dataSet.addValue("fwhmZ_norm",
                  correctedResolutionZ / m.getZTheoreticalResolution());
                
            dataSet.addValue("fwhmX_nc", resolutionX);
            dataSet.addValue("fwhmY_nc", resolutionY);
            dataSet.addValue("fwhmZ_nc", resolutionZ);
             */

            // the minimum fitting among X, Y and Z fitting
            //dataSet.addValue("fitting_min", bead.getMinimumFittingGoodness());

            dataSet.addValue(PSFj.ASYMMETRY_KEY, bead.getAsymetry());
            dataSet.addValue(PSFj.THETA_KEY, 180.0 * bead.getTheta() / Math.PI);
            dataSet.addValue(PSFj.FRAME_SIZE_KEY, bead.getBoundariesAsRectangle().width);

            dataSet.addValue(PSFj.THRESHOLD_KEY, bead.getSource().getThresholdValue());

            if (bead instanceof BeadFrame2D) {
                BeadFrame2D bead2d = (BeadFrame2D) bead;
                if (bead2d.getFittedParameters() == null) {
                    //System.out.println("Fitted parameter is null... why ??");
                    //System.out.println("isValid : "+bead2d.isValid);
                    //System.out.println("fitting goodness : "+bead2d.getFittingGoodness(0));
                    dataSet.addValue(PSFj.SIGMA_X_KEY, Double.NaN);
                    dataSet.addValue(PSFj.SIGMA_Y_KEY, Double.NaN);
                    dataSet.addValue(PSFj.THETA_IN_RADIAN_KEY, Double.NaN);
                } else {
                    dataSet.addValue(PSFj.SIGMA_X_KEY, bead2d.getFittedParameters()[BeadFrame2D.SX]);

                    dataSet.addValue(PSFj.SIGMA_Y_KEY, bead2d.getFittedParameters()[BeadFrame2D.SY]);
                    dataSet.addValue(PSFj.THETA_IN_RADIAN_KEY, bead2d.getTheta());

                }
            }

            // if the bead has an alter ego
            if (includeMultichannelData) {
                if (bead.getAlterEgo() == null) {
                    dataSet.addValue("Corresponding bead id", -1);
                } else {
                    dataSet.addValue("Corresponding bead id", bead.getAlterEgo().getId());
                }

                for (int axe : PSFj.AXES) {
                    dataSet.addValue(PSFj.CHR_SHIFT_KEY, axe, PSFj.NOT_NORMALIZED, 1.0 * bead.getShift(axe));
                    dataSet.addValue(PSFj.CHR_SHIFT_KEY, axe, PSFj.NORMALIZED,
                            1.0 * bead.getShift(axe) / m.getTheoreticalResolution(axe));
                }

                dataSet.addValue(PSFj.CHR_SHIFT_XY, PSFj.NOT_NORMALIZED, bead.getDistance(bead.getAlterEgo()));

                dataSet.addValue(PSFj.CHR_SHIFT_XY, PSFj.NORMALIZED,
                        bead.getDistance(bead.getAlterEgo()) / m.getXYTheoreticalResolution());

                dataSet.addValue(PSFj.CHR_SHIFT_XYZ, PSFj.NOT_NORMALIZED,
                        bead.getDistanceIncludingZ(bead.getAlterEgo()));

                dataSet.addValue(PSFj.CHR_SHIFT_XYZ, PSFj.NORMALIZED,
                        bead.getDistanceIncludingZ(bead.getAlterEgo()) / m.getZTheoreticalResolution());

            }

            // adding fitting goodness
            for (int axe : PSFj.AXES) {
                dataSet.addValue(PSFj.R_COEFF_KEY, axe, PSFj.NOT_NORMALIZED, bead.getFittingGoodness(axe));
            }

            dataSet.addValue(PSFj.IS_FITTING_VALID, bead.isValid() ? 1 : 0);
        }

        for (int axe : PSFj.AXES) {
            dataSet.setTheoriticalValue(PSFj.getColumnName(PSFj.FWHM_KEY, axe, PSFj.NOT_NORMALIZED),
                    get(0).getSource().getMicroscope().getTheoreticalResolution(axe));
        }

        dataSet.recalculateZProfileNormalisation();

        return dataSet;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.ArrayList#add(java.lang.Object)
     */
    @Override
    public boolean add(BeadFrame bead) {

        beadHash.put(bead.getId(), bead);
        return super.add(bead);

    }

    /*
     * (non-Javadoc)
     * 
     * @see java.util.ArrayList#clear()
     */
    @Override
    public void clear() {
        super.clear();
        beadHash.clear();
    }

    /**
     * Gets a BeadFrame from its integer id.
     * 
     * @param id
     *            the BeadFrame integer id
     * @return a BeadFrame
     */
    public BeadFrame getFromId(Integer id) {
        return beadHash.get(id);
    }

    /**
     * Gets the number of non-valid beads.
     *
     * @return the number of non valid beads
     */
    public int getNonValidBeadFrameCount() {

        return getTotalOfBeads() - getValidBeadFrameCount();
    }

    /**
     * Gets the valid bead frames.
     *
     * @return the valid bead frames
     */
    public int getValidBeadFrameCount() {
        int count = 0;
        for (BeadFrame frame : this) {
            if (frame.isValid()) {
                count++;
            }
        }
        return count;
    }

    /**
     * Add the bead frames from an other bead frame list.
     *
     * @param beadFrameList            the bead frame list
     */
    public void mergeList(BeadFrameList beadFrameList) {
        for (BeadFrame frame : beadFrameList) {
            add(frame);
        }
    }

    /**
     * Gets the valid bead frames.
     * 
     * @return a list of the valid bead frames
     */
    public BeadFrameList getValidBeadFrames() {

        BeadFrameList list = new BeadFrameList();

        for (BeadFrame frame : this) {
            if (frame.isValid()) {
                list.add(frame);
            }
        }

        return list;
    }

    /**
     * Gets the total of beads.
     * 
     * @return the total of beads
     */
    public int getTotalOfBeads() {
        return size();
    }

    /**
     * Gets the delta x statistics.
     * 
     * @return the delta x statistics
     */
    public DescriptiveStatistics getDeltaXStatistics() {
        DescriptiveStatistics stats = new DescriptiveStatistics();
        for (BeadFrame f : this) {
            if (f.isValid() == false)
                continue;
            stats.addValue(f.getDeltaX());
        }
        return stats;
    }

    /**
     * Gets the delta y statistics.
     * 
     * @return the delta y statistics
     */
    public DescriptiveStatistics getDeltaYStatistics() {
        DescriptiveStatistics stats = new DescriptiveStatistics();
        for (BeadFrame f : this) {
            if (f.isValid() == false)
                continue;
            stats.addValue(f.getDeltaY());
        }
        return stats;
    }

    /**
     * Gets the delta z statistics.
     * 
     * @return the delta z statistics
     */
    public DescriptiveStatistics getDeltaZStatistics() {
        DescriptiveStatistics stats = new DescriptiveStatistics();
        for (BeadFrame f : this) {
            if (f.isValid() == false)
                continue;
            stats.addValue(f.getDeltaZ());
        }
        return stats;
    }

    /**
     * Gets the number of beads paired bead frames (with an alter ego).
     *
     * @return the number of beads with an alter ego
     */
    public int getPairedCount() {
        int count = 0;
        for (BeadFrame f : this) {
            if (f.getAlterEgo() != null) {
                count++;
            }
        }

        return count;
    }

    /**
     * Gets the from roi.
     *
     * @param roi the roi
     * @return the from roi
     */
    public BeadFrameList getFromROI(Rectangle roi) {

        if (roi == null)
            return this;
        BeadFrameList list = new BeadFrameList();

        for (BeadFrame frame : this) {
            if (roi.contains(frame.getFrameCenterX(), frame.getFrameCenterY()))
                list.add(frame);
        }

        return list;

    }

    /**
     * Gets the certain number of beads contained inside a defined zone. The
     * zone should be in pixel and in the image space.
     * 
     * @param zone
     *            the zone
     * @param max
     *            the maximum number of beads to be retrieved
     * @return the sample from corner
     */
    public BeadFrameList getSampleFromCorner(Rectangle zone, int max) {

        BeadFrameList list = new BeadFrameList();

        int count = 0;

        for (BeadFrame frame : this) {
            if (zone.contains(new Point(frame.getFrameX(), frame.getFrameY())) && frame.getAlterEgo() != null) {
                list.add(frame);
                count++;

            }
            if (count >= max)
                break;

        }

        return list;

    }

    /**
     * Gets the bead montage of the bead contained inside the list.
     *
     * @return the bead montage
     */
    public ImageProcessor getBeadMontage() {

        if (size() == 0)
            return new ColorProcessor(10, 10);

        int lines = MathUtils.round(Math.sqrt(size()));
        int columns = lines;

        int fw = get(0).getWidth();
        int fh = get(0).getHeight();

        int w = get(0).getWidth() * lines;
        int h = get(0).getHeight() * lines;

        ColorProcessor montage = new ColorProcessor(w, h);

        int count = 0;

        for (int l = 0; l != lines; l++) {
            for (int c = 0; c != columns; c++) {
                montage.copyBits(get(count).getOverlayWithAlterEgo(), c * fw, l * fh, Blitter.COPY);
                montage.setColor(Color.yellow.darker().darker().darker().darker());
                montage.drawRect(c * fw, l * fh, fw, fh);
                count++;
                if (count >= size())
                    break;
            }
            if (count >= size())
                break;
        }

        return montage;

    }

    /**
     * Gets the.
     *
     * @param start the start
     * @param count the count
     * @return the bead frame list
     */
    public BeadFrameList get(int start, int count) {

        BeadFrameList list = new BeadFrameList();

        int index = 0;
        for (BeadFrame frame : this) {
            if ((index >= start) && (index - start < count)) {
                list.add(frame);
            }
            index++;
        }

        return list;
    }

}