All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.celldynamics.quimp.plugin.protanalysis.TrackVisualisation Maven / Gradle / Ivy

Go to download

QuimP software, a set of plugins for ImageJ to quantify spatio-temporal patterns of fluorescently labeled proteins in the cortex of moving cells.

The newest version!
package com.github.celldynamics.quimp.plugin.protanalysis;

import java.awt.Color;
import java.awt.Point;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.celldynamics.quimp.plugin.protanalysis.ProtAnalysisOptions.OutlinesToImage;
import com.github.celldynamics.quimp.plugin.qanalysis.STmap;
import com.github.celldynamics.quimp.utils.graphics.GraphicsElements;

import ij.ImagePlus;
import ij.ImageStack;
import ij.gui.Overlay;
import ij.gui.PointRoi;
import ij.gui.PolygonRoi;
import ij.plugin.ZProjector;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;

/**
 * Support various methods of visualising protrusion data.
 * 
 * 

In general all plots are added to image used to construct this object as overlay layer. * *

This super class contains methods for creating static plots in [x,y] domain from coordinates * in [outline,frame] system (native for maps generated by Qanalysis). * *

Warning * *

It is assumed that plotted maps have frames on x-axis and indexes on y-axis * * @author p.baniukiewicz * */ public abstract class TrackVisualisation { /** * The Constant LOGGER. */ static final Logger LOGGER = LoggerFactory.getLogger(TrackVisualisation.class.getName()); /** * Radius of circles plotted. */ public double circleRadius = 7.; /** * Color for maxima points. */ public static Color MAXIMA_COLOR = Color.MAGENTA; /** * Definition of colors used to plot tracks. * *

These are: *

    *
  1. index 0 - backtracked position of point *
  2. index 1 - forwardtracked position of point. *
  3. index 2 - other *
*/ public static Color[] color = { Color.YELLOW, Color.GREEN, Color.WHITE }; /** * The original image. */ protected ImagePlus originalImage; // reference of image to be plotted on /** * The overlay. */ protected Overlay overlay; /** * Create correct object. * *

If input image contains any overlay data, they will be extended by new plots. * * @param originalImage Image to be plotted on. */ public TrackVisualisation(ImagePlus originalImage) { this.originalImage = originalImage; LOGGER.trace("Num of slices: " + originalImage.getStackSize()); overlay = originalImage.getOverlay(); // check for existing overlay if (overlay == null) { overlay = new Overlay(); } } /** * Construct object from raw ImageProcessor. * * @param name Name of the image * @param imp ImageProcessor */ public TrackVisualisation(String name, ImageProcessor imp) { this(new ImagePlus(name, imp)); } /** * Plot filled circle on overlay. * * @param x center * @param y center * @param color color * @param radius radius */ public void plotCircle(double x, double y, Color color, double radius) { // create ROI PolygonRoi or = GraphicsElements.getCircle(x, y, color, radius); overlay.add(or); // add to collection of overlays } /** * getOriginalImage. * * @return the originalImage */ public ImagePlus getOriginalImage() { return originalImage; } /** * Helper method. * *

Allows to convert enum to index of array of Colors. * * @param track track * @return Color from color array */ protected Color getColor(Track track) { Color c; Track.TrackType type = track.type; switch (type) { case FORWARD: c = color[1]; break; case BACKWARD: c = color[0]; break; case OTHER: c = color[2]; break; default: throw new IllegalArgumentException("Color not supported"); } return c; } /** * Flatten stack according to given type. * *

Output has the same resolution (x,y,t) as input. For stacks, slices are duplicated. Refer to * ij.plugin.ZProjector.setMethod(int) * * @param method How to flatten - ZProjector methods. * @param preserveStack - if true size of output stack is preserved (slices are * duplicated to form stack with the same number of slices as original one). Otherwise * only one slice is built */ public void flatten(int method, boolean preserveStack) { ImageStack is = originalImage.getStack(); is = is.convertToFloat(); // for better averaging ZProjector zp = new ZProjector(new ImagePlus(originalImage.getTitle(), is)); zp.setStartSlice(1); zp.setStopSlice(originalImage.getStackSize()); zp.setMethod(method); zp.doProjection(); ImagePlus ret = zp.getProjection(); // recreate stack if needed if (originalImage.getStackSize() > 1 && preserveStack) { ImageStack imS = new ImageStack(ret.getWidth(), ret.getHeight()); for (int s = 0; s < originalImage.getStackSize(); s++) { imS.addSlice(ret.getProcessor().convertToByte(true)); } originalImage = new ImagePlus(originalImage.getTitle(), imS); } else { // return only one slice (due to input format or preserveStack flag status) originalImage = new ImagePlus(originalImage.getTitle(), ret.getProcessor().convertToByte(true)); } } /** * Clear overlay. */ public void clear() { if (overlay != null) { overlay.clear(); } } /** * Subclass for plotting on single image in coord space [outline,frame]. * * @author p.baniukiewicz * */ static class Map extends TrackVisualisation { /** * Denote if map is rotated. * *

QuimP maps returned by * {@link STmap#map2ColorImagePlus(String, String, double[][], double, double)} are rotated in * relation to raw map returned by {@link STmap#getMotMap()}. If this filed is false it means * raw maps, use true for ImagePlus map. * *

Internally all tracks refer to map that has time on x axis (rotated==false). * * @see STmap#map2ImagePlus(String, ImageProcessor) */ private boolean rotated = false; // scales if maps are scaled by map2ColorImagePlus private double ts = 1.0; private double os = 1.0; /** * Instantiates a new map from ImagePlus. * *

Note that x-coords must be time and y - outline which is reverse to QuimP format. * * @param originalImage the original image */ public Map(ImagePlus originalImage) { super(originalImage); } /** * Instantiates a new map from ImagePlus. * *

Should be used with output from * {@link STmap#map2ColorImagePlus(String, String, double[][], double, double)} after setting * correct scales. Typically ts = 400/frames and os = 1 * * @param originalImage the original image * @param rotated true if map is rotated so time is y and outline is x. Typically map is output * from {@link STmap#map2ColorImagePlus(String, String, double[][], double, double)} * @param ts time scale if map is scaled as abobe * @param os outline scale */ public Map(ImagePlus originalImage, boolean rotated, double ts, double os) { super(originalImage); this.rotated = rotated; this.ts = ts; this.os = os; } /** * Instantiates a new map. * * @param name the name * @param imp the imp */ public Map(String name, ImageProcessor imp) { super(name, imp); } /** * Create object from raw data like e.g. motility map. * * @param name Name of the image * @param data 2D data. */ public Map(String name, float[][] data) { super(name, new FloatProcessor(data)); } /** * Plot unrelated points on image (static). * * @param points list of points to plot in coordinates (index,frame) * @param color color of point * @param radius radius of point */ public void addCirclesToImage(Polygon points, Color color, double radius) { Polygon polsc = scale(points); // time scale int[] indexes = polsc.ypoints; int[] frames = polsc.xpoints; for (int n = 0; n < points.npoints; n++) { // decode frame,outline to screen coordinates if (frames[n] < 0 || indexes[n] < 0) { continue; } plotCircle(frames[n], indexes[n], color, radius); } originalImage.setOverlay(overlay); // add to image } /** * Plot maxima found by {@link MaximaFinder} on current image. * * @param maxF properly initialized {@link MaximaFinder} object. */ public void addMaximaToImage(MaximaFinder maxF) { Polygon max = maxF.getMaxima(); Polygon polsc = scale(max); // time scale PointRoi pr = GraphicsElements.getPoint(polsc, TrackVisualisation.MAXIMA_COLOR); overlay.add(pr); originalImage.setOverlay(overlay); } private int[] scale(int[] in, int len, double sc) { int[] ret = new int[len]; for (int i = 0; i < len; i++) { ret[i] = (int) Math.round(in[i] * sc); } return ret; } private Polygon scale(Polygon in) { int[] xp; int[] yp; if (rotated) { yp = scale(in.xpoints, in.npoints, ts); xp = scale(in.ypoints, in.npoints, os); } else { xp = scale(in.xpoints, in.npoints, ts); yp = scale(in.ypoints, in.npoints, os); } return new Polygon(xp, yp, xp.length); } /** * Add lines defined as polygons to image. * * @param trackCollection initialised TrackCollection object * */ public void addTrackingLinesToImage(TrackCollection trackCollection) { Iterator> it = trackCollection.iterator(); while (it.hasNext()) { Pair pair = it.next(); Polygon pairLeft = scale(pair.getLeft().asPolygon()); Polygon pairRight = scale(pair.getRight().asPolygon()); PolygonRoi pr = GraphicsElements.getLine(pairLeft, getColor(pair.getLeft())); // b // pr.fitSpline(); overlay.add(pr); pr = GraphicsElements.getLine(pairRight, getColor(pair.getRight())); // fw // pr.fitSpline(); overlay.add(pr); } originalImage.setOverlay(overlay); } } /** * Class for plotting on [x,y] image. * * @author p.baniukiewicz * */ static class Image extends TrackVisualisation { /** * Instantiates a new image. * * @param originalImage the original image */ public Image(ImagePlus originalImage) { super(originalImage); } /** * Instantiates a new image. * * @param name the name * @param imp the imp */ public Image(String name, ImageProcessor imp) { super(name, imp); } /** * Plot unrelated points on image (static). * * @param mapCell source of coordinate maps * @param points list of points to plot in coordinates (index,frame) * @param color color of point * @param radius radius of point */ public void addCirclesToImage(STmap mapCell, Polygon points, Color color, double radius) { double[][] x = mapCell.getxMap(); double[][] y = mapCell.getyMap(); int[] indexes = points.ypoints; int[] frames = points.xpoints; for (int n = 0; n < points.npoints; n++) { // decode frame,outline to screen coordinates if (frames[n] < 0 || indexes[n] < 0) { continue; } double xcoord = x[frames[n]][indexes[n]]; // screen coordinate of double ycoord = y[frames[n]][indexes[n]]; // (frame,index) point plotCircle(xcoord, ycoord, color, radius); } originalImage.setOverlay(overlay); // add to image } /** * Plot static elements on image if they are not null. * * @param mapCell STmap * @param trackCollection initialised TrackCollection object * @param mf maxima according to Prot_Analysis.MaximaFinder */ public void addElementsToImage(STmap mapCell, TrackCollection trackCollection, MaximaFinder mf) { if (mf != null) { Polygon max = mf.getMaxima(); addCirclesToImage(mapCell, max, TrackVisualisation.MAXIMA_COLOR, circleRadius); } if (trackCollection != null) { addTrackingLinesToImage(mapCell, trackCollection); } } /** * Plot tracking lines before and after maxima points (static). * * @param mapCell map related to given cell. * @param trackCollection * */ public void addTrackingLinesToImage(STmap mapCell, TrackCollection trackCollection) { double[][] x = mapCell.getxMap(); // temporary x and y coordinates for given cell double[][] y = mapCell.getyMap(); // these are raw coordinates of tracking lines extracted from List pL ArrayList xcoorda = new ArrayList<>(); ArrayList ycoorda = new ArrayList<>(); int al = 0; // iterate over tracks Iterator it = trackCollection.iteratorTrack(); while (it.hasNext()) { Track track = it.next(); Polygon pr = track.asPolygon(); // create store for tracking line coordinates xcoorda.add(new float[pr.npoints]); ycoorda.add(new float[pr.npoints]); // counter of invalid vertexes. According to TrackMap#trackForward last points can // be -1 when user provided longer time span than available. (last in term of time) int invalidVertex = 0; // decode frame,outline to x,y for (int f = 0; f < pr.npoints; f++) { // -1 stands for points that are outside of range - assured by TrackMap.class if (pr.ypoints[f] < 0 || pr.xpoints[f] < 0) { invalidVertex++; // count bad points continue; } xcoorda.get(al)[f] = (float) x[pr.xpoints[f]][pr.ypoints[f]]; ycoorda.get(al)[f] = (float) y[pr.xpoints[f]][pr.ypoints[f]]; } PolygonRoi polyRoi = GraphicsElements.getLine(xcoorda.get(al), ycoorda.get(al), pr.npoints - invalidVertex, getColor(track)); overlay.add(polyRoi); al++; } originalImage.setOverlay(overlay); // add to image } } /** * Subclass for plotting on stacks in coord space [x,y,f]. * * @author p.baniukiewicz * */ static class Stack extends TrackVisualisation { /** * Instantiates a new stack. * * @param originalImage the original image */ public Stack(ImagePlus originalImage) { super(originalImage); } /** * Constructor. * * @param name name * @param imp base ImageProcessor */ public Stack(String name, ImageProcessor imp) { super(name, imp); } /** * Plot unrelated points on image (stack). * * @param mapCell source of coordinate maps * @param points list of points to plot in coordinates (index,frame) * @param color color of point * @param radius radius of point */ public void addCirclesToImage(STmap mapCell, Polygon points, Color color, double radius) { double[][] x = mapCell.getxMap(); double[][] y = mapCell.getyMap(); int[] indexes = points.ypoints; int[] frames = points.xpoints; // LOGGER.trace("Frames:" + Arrays.toString(frames)); // LOGGER.trace("Indexe:" + Arrays.toString(indexes)); for (int n = 0; n < points.npoints; n++) { // decode frame,outline to screen coordinates if (frames[n] < 0 || indexes[n] < 0) { continue; } double xcoord = x[frames[n]][indexes[n]]; // screen coordinate of double ycoord = y[frames[n]][indexes[n]]; // (frame,index) point plotCircle(xcoord, ycoord, frames[n] + 1, color, radius); } originalImage.setOverlay(overlay); // add to image } /** * Plot unrelated points on image (stack). Input compatible with * {@link TrackMapAnalyser#getIntersectionParents(List, int)}. * * @param mapCell source of coordinate maps * @param points list of points to plot in coordinates (index,frame) * @param color color of point * @param radius radius of point */ public void addCirclesToImage(STmap mapCell, List> points, Color color, double radius) { int[] x = new int[points.size()]; int[] y = new int[points.size()]; int l = 0; for (Pair p : points) { x[l] = p.getRight().x; y[l] = p.getRight().y; l++; } Polygon poly = new Polygon(x, y, points.size()); addCirclesToImage(mapCell, poly, color, radius); } /** * Plot maxima for each frame. * *

Work like {@link #addTrackingLinesToImage(STmap, TrackCollection)} but does not remember * lines but only points. * * @param mapCell map related to given cell. * @param trackCollection initialised TrackCollection object TODO This method uses old * approach assuming that back and forward tracks are repeating. */ public void addTrackingMaximaToImage(STmap mapCell, TrackCollection trackCollection) { double[][] x = mapCell.getxMap(); // temporary x and y coordinates for given cell double[][] y = mapCell.getyMap(); // these are raw coordinates of tracking lines extracted from List pL ArrayList xcoorda = new ArrayList<>(); ArrayList ycoorda = new ArrayList<>(); int al = 0; // iterate over tracks Iterator it = trackCollection.iteratorTrack(); while (it.hasNext()) { Track track = it.next(); Polygon polyR = track.asPolygon(); // we need to sort tracking line points according to frames where they appear in // first convert poygon to list of Point2i object List plR = TrackMapAnalyser.polygon2Point2i(new ArrayList(Arrays.asList(polyR))); // then sort this list according y-coordinate (frame) Collections.sort(plR, new ListPoint2iComparator()); // convert to polygon again but now it is sorted along frames Polygon plRsorted = TrackMapAnalyser.point2i2Polygon(plR); // create store for tracking line coordinates xcoorda.add(new float[plRsorted.npoints]); ycoorda.add(new float[plRsorted.npoints]); // counter of invalid vertexes. According to TrackMap#trackForward last points can // be -1 when user provided longer time span than available. (last in term of time) int invalidVertex = 0; // decode frame,outline to x,y for (int f = 0; f < plRsorted.npoints; f++) { // -1 stands for points that are outside of range - assured by TrackMap.class if (plRsorted.ypoints[f] < 0 || plRsorted.xpoints[f] < 0) { invalidVertex++; // count bad points continue; } xcoorda.get(al)[f] = (float) x[plRsorted.xpoints[f]][plRsorted.ypoints[f]]; ycoorda.get(al)[f] = (float) y[plRsorted.xpoints[f]][plRsorted.ypoints[f]]; } // now xcoorda,yccora keep coordinates of aL track, it is time to plot // iterate over points in sorted polygon (one track line) even indexes stand for // backward tracking, odd for forward tracking lines Some last points can be skipped // here (sorting does not influence this because last points means last in term of // time) for (int f = 0; f < plRsorted.npoints - invalidVertex; f++) { // x/ycoorda keep all points of tracking lines but PolygonRoi constructor allow // to define how many first of them we take. This allows us to add points // together with frames - in result the line grows as frames rise. After // sorting, first points are those on lower frames // set colors (remember about backward/forward order) PolygonRoi polyRoi = GraphicsElements.getCircle(xcoorda.get(al)[f], ycoorda.get(al)[f], color[al % 2], circleRadius); // set where we want plot f+1 points from x/ycoorda polyRoi.setPosition((int) plRsorted.xpoints[f] + 1); overlay.add(polyRoi); } al++; } originalImage.setOverlay(overlay); // add to image } /** * Plot tracking lines before and after maxima points (in term of frames). * *

First backward tracking lines are plotted then forward in two different colors. For given * maximum first is plotted backward tracking frame by frame, then forward tracking. * Backward tracking is visible as long as forward tracking is plotted. Then both disappear. * * @param mapCell map related to given cell. * @param trackCollection initialised TrackCollection object TODO This method uses old * approach assuming that back and forward tracks are repeating. */ public void addTrackingLinesToImage(STmap mapCell, TrackCollection trackCollection) { double[][] x = mapCell.getxMap(); // temporary x and y coordinates for given cell double[][] y = mapCell.getyMap(); // these are raw coordinates of tracking lines extracted from List pL ArrayList xcoorda = new ArrayList<>(); ArrayList ycoorda = new ArrayList<>(); int al = 0; // iterate over tracks Iterator it = trackCollection.iteratorTrack(); while (it.hasNext()) { Track track = it.next(); Polygon polyR = track.asPolygon(); // we need to sort tracking line points according to frames where they appear in // first convert poygon to list of Point2i object List plR = TrackMapAnalyser.polygon2Point2i(new ArrayList(Arrays.asList(polyR))); // then sort this list according y-coordinate (frame) Collections.sort(plR, new ListPoint2iComparator()); // convert to polygon again but now it is sorted along frames Polygon plRsorted = TrackMapAnalyser.point2i2Polygon(plR); // create store for tracking line coordinates xcoorda.add(new float[plRsorted.npoints]); ycoorda.add(new float[plRsorted.npoints]); // counter of invalid vertexes. According to TrackMap#trackForward last points can // be -1 when user provided longer time span than available. (last in term of time) int invalidVertex = 0; // decode frame,outline to x,y for (int f = 0; f < plRsorted.npoints; f++) { // -1 stands for points that are outside of range - assured by TrackMap.class if (plRsorted.ypoints[f] < 0 || plRsorted.xpoints[f] < 0) { invalidVertex++; // count bad points continue; } xcoorda.get(al)[f] = (float) x[plRsorted.xpoints[f]][plRsorted.ypoints[f]]; ycoorda.get(al)[f] = (float) y[plRsorted.xpoints[f]][plRsorted.ypoints[f]]; } // now xcoorda,yccora keep coordinates of aL track, it is time to plot // iterate over points in sorted polygon (one track line) even indexes stand for // backward tracking, odd for forward tracking lines Some last points can be skipped // here (sorting does not influence this because last points means last in term of // time) for (int f = 0; f < plRsorted.npoints - invalidVertex; f++) { // x/ycoorda keep all points of tracking lines but PolygonRoi constructor allow // to define how many first of them we take. This allows us to add points // together with frames - in result the line grows as frames rise. After // sorting, first points are those on lower frames // set colors (remember about backward/forward order) PolygonRoi polyRoi = GraphicsElements.getLine(xcoorda.get(al), ycoorda.get(al), f + 1, color[al % 2]); // set where we want plot f+1 points from x/ycoorda polyRoi.setPosition((int) plRsorted.xpoints[f] + 1); overlay.add(polyRoi); // If there is maximum on x frame and we plotted backward line from x-n to x, we // wont to keep it during plotting forward tracking from x to x+z frames. So // this whole line is plotted on every x-x+z frame if (al % 2 == 1) { PolygonRoi polyRoi1 = GraphicsElements.getLine(xcoorda.get(al - 1), ycoorda.get(al - 1), xcoorda.get(al - 1).length, color[al % 2 - 1]); polyRoi1.setPosition((int) plRsorted.xpoints[f] + 1); overlay.add(polyRoi1); } } al++; } originalImage.setOverlay(overlay); // add to image } /** * Plot maxima found by {@link MaximaFinder} on current image. * * @param mapCell map related to given cell. * @param mf properly initialized {@link MaximaFinder} object. */ public void addMaximaToImage(STmap mapCell, MaximaFinder mf) { Polygon max = mf.getMaxima(); addCirclesToImage(mapCell, max, TrackVisualisation.MAXIMA_COLOR, 7); } /** * Plot filled circle on overlay on given frame. * * @param x center * @param y center * @param frame frame * @param color color * @param radius radius */ public void plotCircle(double x, double y, int frame, Color color, double radius) { // create ROI PolygonRoi or = GraphicsElements.getCircle(x, y, color, radius); // set z-position of ROI!!! or.setPosition(frame); overlay.add(or); // add to collection of overlays } /** * Plot outline around cell on image. * *

Uses {@link OutlinesToImage} options from {@link ProtAnalysisOptions} through filed * {@link ProtAnalysisOptions#selOutlineColoring} * * @param mapCell map related to given cell. * @param config configuration object defining colors, type of plot, etc. * @see ProtAnalysisOptions#selOutlineColoring * @see OutlinesToImage */ public void addOutlinesToImage(STmap mapCell, ProtAnalysisOptions config) { double[][] mm = mapCell.getMotMap(); double[][] cm = mapCell.getConvMap(); switch (config.selOutlineColoring.plotType) { case MOTILITY: plotOutline(mapCell.getxMap(), mapCell.getyMap(), new Color[] { config.selOutlineColoring.motColor, config.selOutlineColoring.defColor }, new double[] { config.selOutlineColoring.motThreshold }, mapCell.getMotMap()); break; case CONVEXITY: plotOutline(mapCell.getxMap(), mapCell.getyMap(), new Color[] { config.selOutlineColoring.convColor, config.selOutlineColoring.defColor }, new double[] { config.selOutlineColoring.convThreshold }, mapCell.getConvMap()); break; case CONVANDEXP: { // prepare fake map double[][] tmpMap = new double[mm.length][]; for (int f = 0; f < tmpMap.length; f++) { tmpMap[f] = new double[mm[f].length]; for (int r = 0; r < mm[f].length; r++) { tmpMap[f][r] = ((mm[f][r] > 0 && cm[f][r] > 0)) ? 1.0 : -1.0; } } plotOutline( mapCell.getxMap(), mapCell.getyMap(), new Color[] { config.selOutlineColoring.convColor, config.selOutlineColoring.defColor }, new double[] { 0 }, tmpMap); } break; case CONCANDRETR: { // prepare fake map double[][] tmpMap = new double[mm.length][]; for (int f = 0; f < tmpMap.length; f++) { tmpMap[f] = new double[mm[f].length]; for (int r = 0; r < mm[f].length; r++) { tmpMap[f][r] = (mm[f][r] < 0 && cm[f][r] < 0) ? 1.0 : -1.0; } } plotOutline( mapCell.getxMap(), mapCell.getyMap(), new Color[] { config.selOutlineColoring.motColor, config.selOutlineColoring.defColor }, new double[] { 0 }, tmpMap); } break; case BOTH: { double[][] tmpMap = new double[mm.length][]; for (int f = 0; f < tmpMap.length; f++) { tmpMap[f] = new double[mm[f].length]; for (int r = 0; r < mm[f].length; r++) { tmpMap[f][r] = (mm[f][r] > 0 && cm[f][r] > 0) ? 1.0 : -1.0; } } double[][] tmpMap1 = new double[mm.length][]; for (int f = 0; f < tmpMap.length; f++) { tmpMap1[f] = new double[mm[f].length]; for (int r = 0; r < mm[f].length; r++) { tmpMap1[f][r] = (mm[f][r] < 0 && cm[f][r] < 0) ? 1.0 : -1.0; } } plotOutline(mapCell.getxMap(), mapCell.getyMap(), new Color[] { config.selOutlineColoring.motColor, config.selOutlineColoring.convColor, config.selOutlineColoring.defColor }, new double[] { 0, 0 }, tmpMap, tmpMap1); } break; case UNIFORM: { // plot any map with impossible threshold (def color) plotOutline(mapCell.getxMap(), mapCell.getyMap(), new Color[] { config.selOutlineColoring.motColor, config.selOutlineColoring.defColor }, new double[] { Double.MAX_VALUE }, mapCell.getMotMap()); } break; default: throw new IllegalArgumentException("Plot Type not supported"); } originalImage.setOverlay(overlay); } /** * Helper method for plotting outlines. * *

Plot outline according to given maps and thresholds with specified colour. Points that * does not meet criterion are plotted in default colour. * * @param x x-coordinates map * @param y y-coordinates map * @param color array of colours used for plotting maps given in map. The array * must contain default colour on its last position. Its size is usually greater by 1 * than number of maps. * @param threshold array of threshold that applies to maps. Must be size of maps. * @param map list of maps to be plotted with colour color if they meet criterion * threshold */ private void plotOutline(double[][] x, double[][] y, Color[] color, double[] threshold, double[][]... map) { Polygon[] lines = new Polygon[map.length + 1]; // last line is default one for (int i = 0; i < lines.length; i++) { lines[i] = new Polygon(); } // plot map lines (those points that are consecutive for given map and its criterion) // and default lines (those consecutive points that do no belong to any map) for (int f = 0; f < x.length; f++) { // over frames for (int r = 0; r < x[0].length; r++) { // over indexes of outline int l = 0; boolean added = false; // indicate whether given point is plotted as map for (Object item : map) { // over maps double[][] tmpmap = (double[][]) item; // check threshold. If point is accepted, any started default line is // finished here and new map line is started. if (tmpmap[f][r] >= threshold[l]) { // store this point as l-th line lines[l].addPoint((int) Math.round(x[f][r]), (int) Math.round(y[f][r])); added = true; // mark that this point is plotted already within any map // plot default no-map points if any stored (stored in else part) if (lines[lines.length - 1].npoints > 0) { PolygonRoi polyR = GraphicsElements.getLine(lines[lines.length - 1], color[color.length - 1], f + 1); overlay.add(polyR); lines[lines.length - 1] = new Polygon(); } } else { // if not meet criterion plot all lines and initialise them again if (lines[l].npoints > 0) { PolygonRoi polyR = GraphicsElements.getLine(lines[l], color[l], f + 1); overlay.add(polyR); lines[l] = new Polygon(); } // and and add this point to default if not plotted yet if (!added) { lines[lines.length - 1].addPoint((int) Math.round(x[f][r]), (int) Math.round(y[f][r])); } } l++; } } // plot if else-if above does not fire (if fire all lines are initialized again) PolygonRoi polyR; for (int i = 0; i < lines.length; i++) { if (lines[i].npoints > 0) { polyR = GraphicsElements.getLine(lines[i], color[i], f + 1); overlay.add(polyR); lines[i] = new Polygon(); } } } } /** * Compare Point2i objects along frames (x-coordinate). * * @author p.baniukiewicz * */ class ListPoint2iComparator implements Comparator { /* * (non-Javadoc) * * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(Point o1, Point o2) { if (o1.x < o2.x) { return -1; } if (o1.x > o2.x) { return 1; } else { return 0; } } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy