View Javadoc
1   
2   package com.github.celldynamics.quimp;
3   
4   import java.util.Arrays;
5   
6   import com.github.celldynamics.quimp.geom.ExtendedVector2d;
7   
8   import ij.IJ;
9   
10  /**
11   * Represents a vertex in the outline. Contains several methods that operate on vertexes and
12   * vectors. Properties defined for {@link Vert} object are updated by different QuimP modules (ECMM,
13   * QA)
14   * 
15   * @author rtyson
16   * @author p.baniukiewicz
17   */
18  public class Vert extends PointsList<Vert> {
19    /**
20     * Charge on the vertex.
21     */
22    public double charge;
23    /**
24     * distance vert migrated (actually converted to speed by Tool.speedToScale.
25     */
26    public double distance;
27    /**
28     * fluorescence channels 1-3.
29     */
30    public final FluoMeasurementement.html#FluoMeasurement">FluoMeasurement[] fluores = new FluoMeasurement[3];
31    /**
32     * curvature local to a node. Updated by {@link Vert#setCurvatureLocal()} called during
33     * creation and serialization.
34     */
35    public double curvatureLocal;
36    /**
37     * Smoothed curvature. Updated during map generation (Q Analysis) by
38     * {@link com.github.celldynamics.quimp.plugin.qanalysis.STmap#calcCurvature()} or
39     * {@link com.github.celldynamics.quimp.plugin.qanalysis.STmap#averageCurvature(Outline)}
40     */
41    @SuppressWarnings("javadoc")
42    public double curvatureSmoothed;
43    /**
44     * summed curvature over x microns this is the value recorded into maps. Updated during map
45     * generation (Q Analysis) by
46     * {@link com.github.celldynamics.quimp.plugin.qanalysis.STmap#calcCurvature()}
47     */
48    @SuppressWarnings("javadoc")
49    public double curvatureSum;
50    /**
51     * coord relative to head node on current frame. Set during ECMM
52     */
53    public double coord;
54    /**
55     * coord relative to coord on previous frame. Set by
56     * {@link com.github.celldynamics.quimp.plugin.ecmm.Mapping#migrate()} and during changing
57     * resolution
58     * in ECMM
59     */
60    @SuppressWarnings("javadoc")
61    public double fCoord;
62    /**
63     * landing relative to previous frame. Set by
64     * {@link com.github.celldynamics.quimp.Vert#setLandingCoord(ExtendedVector2d, Vert)} called on
65     * solving ECMM equations
66     */
67    public double fLandCoord;
68    /**
69     * global coord relative to head node on frame 1. Set by
70     * {@link com.github.celldynamics.quimp.plugin.ecmm.Mapping#migrate()} and during changing
71     * resolution
72     * in ECMM
73     */
74    @SuppressWarnings("javadoc")
75    public double gCoord;
76    /**
77     * landing coord relative to head node on frame 1. Set by
78     * {@link com.github.celldynamics.quimp.Vert#setLandingCoord(ExtendedVector2d, Vert)} called on
79     * solving ECMM equations
80     */
81    public double gLandCoord;
82    /**
83     * tarLandingCoord.
84     */
85    public double tarLandingCoord;
86    /**
87     * Color of Vert.
88     */
89    public QColor color;
90    /**
91     * Vert represents an intersect point and is temporary. Mark start end of sectors.
92     */
93    private transient boolean intPoint;
94    /**
95     * The vert has been snapped to an edge.
96     */
97    public transient boolean snapped;
98    /**
99     * intsectID.
100    */
101   public int intsectID;
102   /**
103    * Internal state of the vert. Possible values:
104    * <ul>
105    * <li>0 - undetermined
106    * <li>1 - forms valid sector
107    * <li>2 - LOOSE sector
108    * <li>3 - forms inverted sector
109    * <li>4 - inverted and loose
110    * </ul>
111    */
112   public int intState;
113 
114   /**
115    * Default constructor, creates Vert element with ID=1.
116    */
117   public Vert() {
118     super();
119     vertInitializer();
120   }
121 
122   /**
123    * Create Vert element with given ID.
124    * 
125    * @param t ID of Vert
126    */
127   public Vert(int t) {
128     super(t);
129     vertInitializer();
130   }
131 
132   /**
133    * Create Vert from {x,y} coordinates.
134    * 
135    * @param xx x-axis coordinate
136    * @param yy y-axis coordinate
137    * @param t id of Vert
138    */
139   public Vert(double xx, double yy, int t) {
140     super(xx, yy, t);
141     vertInitializer();
142   }
143 
144   /**
145    * Copy constructor. Copy properties of Vert. Previous or next points are not copied
146    * 
147    * @param src Source Vert
148    */
149   public Vertmics/quimp/Vert.html#Vert">Vert(final Vert src) {
150     super(src);
151     charge = src.charge;
152     distance = src.distance;
153     for (int i = 0; i < 3; i++) {
154       fluores[i] = new FluoMeasurement(src.fluores[i]);
155     }
156     curvatureLocal = src.curvatureLocal;
157     curvatureSmoothed = src.curvatureSmoothed;
158     curvatureSum = src.curvatureSum;
159     coord = src.coord;
160     fCoord = src.fCoord;
161     fLandCoord = src.fLandCoord;
162     gCoord = src.gCoord;
163     gLandCoord = src.gLandCoord;
164     tarLandingCoord = src.tarLandingCoord;
165     color = new QColor(src.color);
166     intPoint = src.intPoint;
167     snapped = src.snapped;
168     intsectID = src.intsectID;
169     intState = src.intState;
170   }
171 
172   /**
173    * Conversion constructor.
174    * 
175    * @param src Node to convert to Vert
176    */
177   public Vert(final Node src) {
178     super(src);
179     vertInitializer(); // default params that are not passed from Vert
180   }
181 
182   /**
183    * Initializers for Vert object.
184    */
185   private void vertInitializer() {
186     intPoint = false;
187     intState = 0;
188     fCoord = -1;
189     gCoord = -1;
190     color = new QColor(1, 0, 0);
191     for (int i = 0; i < 3; i++) {
192       fluores[i] = new FluoMeasurement(-2, -2, -2);
193     }
194   }
195 
196   /**
197    * (non-Javadoc)
198    * 
199    * @see java.lang.Object#hashCode()
200    */
201   @Override
202   public int hashCode() {
203     final int prime = 31;
204     int result = super.hashCode();
205     long temp;
206     temp = Double.doubleToLongBits(charge);
207     result = prime * result + (int) (temp ^ (temp >>> 32));
208     result = prime * result + ((color == null) ? 0 : color.hashCode());
209     temp = Double.doubleToLongBits(coord);
210     result = prime * result + (int) (temp ^ (temp >>> 32));
211     temp = Double.doubleToLongBits(curvatureLocal);
212     result = prime * result + (int) (temp ^ (temp >>> 32));
213     temp = Double.doubleToLongBits(curvatureSmoothed);
214     result = prime * result + (int) (temp ^ (temp >>> 32));
215     temp = Double.doubleToLongBits(curvatureSum);
216     result = prime * result + (int) (temp ^ (temp >>> 32));
217     temp = Double.doubleToLongBits(distance);
218     result = prime * result + (int) (temp ^ (temp >>> 32));
219     temp = Double.doubleToLongBits(fCoord);
220     result = prime * result + (int) (temp ^ (temp >>> 32));
221     temp = Double.doubleToLongBits(fLandCoord);
222     result = prime * result + (int) (temp ^ (temp >>> 32));
223     result = prime * result + Arrays.hashCode(fluores);
224     temp = Double.doubleToLongBits(gCoord);
225     result = prime * result + (int) (temp ^ (temp >>> 32));
226     temp = Double.doubleToLongBits(gLandCoord);
227     result = prime * result + (int) (temp ^ (temp >>> 32));
228     result = prime * result + (intPoint ? 1231 : 1237);
229     result = prime * result + intState;
230     result = prime * result + intsectID;
231     result = prime * result + (snapped ? 1231 : 1237);
232     temp = Double.doubleToLongBits(tarLandingCoord);
233     result = prime * result + (int) (temp ^ (temp >>> 32));
234     return result;
235   }
236 
237   /*
238    * (non-Javadoc)
239    * 
240    * @see java.lang.Object#equals(java.lang.Object)
241    */
242   @Override
243   public boolean equals(Object obj) {
244     if (this == obj) {
245       return true;
246     }
247     if (!super.equals(obj)) {
248       return false;
249     }
250     if (!(obj instanceof Vert)) {
251       return false;
252     }
253     Vertf="../../../../com/github/celldynamics/quimp/Vert.html#Vert">Vert other = (Vert) obj;
254     if (Double.doubleToLongBits(charge) != Double.doubleToLongBits(other.charge)) {
255       return false;
256     }
257     if (color == null) {
258       if (other.color != null) {
259         return false;
260       }
261     } else if (!color.equals(other.color)) {
262       return false;
263     }
264     if (Double.doubleToLongBits(coord) != Double.doubleToLongBits(other.coord)) {
265       return false;
266     }
267     if (Double.doubleToLongBits(curvatureLocal) != Double.doubleToLongBits(other.curvatureLocal)) {
268       return false;
269     }
270     if (Double.doubleToLongBits(curvatureSmoothed) != Double
271             .doubleToLongBits(other.curvatureSmoothed)) {
272       return false;
273     }
274     if (Double.doubleToLongBits(curvatureSum) != Double.doubleToLongBits(other.curvatureSum)) {
275       return false;
276     }
277     if (Double.doubleToLongBits(distance) != Double.doubleToLongBits(other.distance)) {
278       return false;
279     }
280     if (Double.doubleToLongBits(fCoord) != Double.doubleToLongBits(other.fCoord)) {
281       return false;
282     }
283     if (Double.doubleToLongBits(fLandCoord) != Double.doubleToLongBits(other.fLandCoord)) {
284       return false;
285     }
286     if (!Arrays.equals(fluores, other.fluores)) {
287       return false;
288     }
289     if (Double.doubleToLongBits(gCoord) != Double.doubleToLongBits(other.gCoord)) {
290       return false;
291     }
292     if (Double.doubleToLongBits(gLandCoord) != Double.doubleToLongBits(other.gLandCoord)) {
293       return false;
294     }
295     if (intPoint != other.intPoint) {
296       return false;
297     }
298     if (intState != other.intState) {
299       return false;
300     }
301     if (intsectID != other.intsectID) {
302       return false;
303     }
304     if (snapped != other.snapped) {
305       return false;
306     }
307     if (Double.doubleToLongBits(tarLandingCoord) != Double
308             .doubleToLongBits(other.tarLandingCoord)) {
309       return false;
310     }
311     return true;
312   }
313 
314   /**
315    * Old part of code.
316    * 
317    * @param s s
318    * @deprecated This is old part of code
319    */
320   public void print(String s) {
321     System.out.print(s + "vert: " + tracknumber + ", x:" + getX() + ", y:" + getY() + ", coord: "
322             + coord + ", fCoord: " + fCoord + ", gCoord: " + gCoord);
323     if (intPoint) {
324       System.out.print(", isIntPoint (" + intsectID + ")");
325     }
326     if (head) {
327       System.out.print(", Head");
328     }
329     System.out.println("");
330   }
331 
332   /**
333    * isIntPoint.
334    * 
335    * @return intPoint
336    */
337   public boolean isIntPoint() {
338     return intPoint;
339   }
340 
341   /**
342    * setIntPoint.
343    * 
344    * @param t t
345    * @param i i
346    */
347   public void setIntPoint(boolean t, int i) {
348     intPoint = t;
349     intsectID = i;
350     tracknumber = -1;
351   }
352 
353   /**
354    * setLandingCoord.
355    * 
356    * @param p p
357    * @param edge edge
358    */
359   public void setLandingCoord(ExtendedVector2d p, Vert edge) {
360     Vert edge2 = edge.getNext(); // 'edge' is the 1st vert of an edge
361 
362     while (edge.isIntPoint()) {
363       edge = edge.getPrev();
364     }
365     while (edge2.isIntPoint()) {
366       edge2 = edge2.getNext();
367     }
368 
369     // relative position of landing
370     double d1 = ExtendedVector2d.lengthP2P(edge.point, edge2.point);
371     double d2 = ExtendedVector2d.lengthP2P(edge.point, p);
372     double prop = d2 / d1;
373 
374     gLandCoord = calcLanding(edge.gCoord, edge2.gCoord, prop);
375     fLandCoord = calcLanding(edge.coord, edge2.coord, prop);
376 
377     if (gLandCoord >= 1 || gLandCoord < 0 || fLandCoord >= 1 || fLandCoord < 0) {
378       System.out.println("Vert253:setLandingCoord-Error in landing coord\n\t" + "gLandCoord= "
379               + gLandCoord + ", fLandCoord = " + fLandCoord);
380 
381     }
382 
383     /*
384      * double d1 = Vec2d.lengthP2P(edge.point, edge2.point); double d2 =
385      * Vec2d.lengthP2P(edge.point, p); double prop = d2 / d1;
386      * 
387      * double edge2coord = edge2.coord; // if wrapping around if (edge2.coord < edge.coord) {
388      * edge2coord += 1; }
389      * 
390      * double coordDist = edge2coord - edge.coord; landingCoor = edge.coord + (prop *
391      * coordDist);
392      * 
393      * if (landingCoor >= 1) { //if wrapped around and passed 1 landingCoor -= 1; }
394      * 
395      * if (landingCoor < 0 || landingCoor > 1 || Double.isNaN(landingCoor)) {
396      * IJ.write("ERROR 1: NAN or < landing coord ("+IJ.d2s(landingCoor)+ ")< 0; e1=" +
397      * edge.coord + ", e2=" + edge2.coord + ", prop" + prop); }
398      */
399   }
400 
401   private double calcLanding(double coordA, double coordB, double prop) {
402     double landing;
403 
404     if (coordB < coordA) {
405       coordB += 1;
406     }
407 
408     double coordDist = coordB - coordA;
409     landing = coordA + (prop * coordDist);
410 
411     if (landing >= 1) { // if wrapped around and passed 1
412       landing -= 1;
413     }
414 
415     if (landing < 0 || landing >= 1 || Double.isNaN(landing)) {
416       System.out.println(
417               "Vert295:calcLanding ERROR in landing coord:\n\t" + "landing:" + IJ.d2s(landing)
418                       + ", coordA=" + coordA + ", coorB=" + coordB + ", proportion=" + prop);
419     }
420     return landing;
421   }
422 
423   /**
424    * Calculate and set local field {@link #curvatureLocal}.
425    */
426   public void setCurvatureLocal() {
427     curvatureLocal = getCurvatureLocal();
428   }
429 
430   /**
431    * setFluoresChannel.
432    * 
433    * @param m Fluoro measurements
434    * @param channel channel to set
435    */
436   public void setFluoresChannel(FluoMeasurement m, int channel) {
437     fluores[channel].intensity = m.intensity;
438     fluores[channel].x = m.x;
439     fluores[channel].y = m.y;
440   }
441 
442   /**
443    * setFluoresChannel.
444    * 
445    * @param x coord
446    * @param y coord
447    * @param i fluoro intensity
448    * @param channel channel
449    */
450   public void setFluoresChannel(int x, int y, int i, int channel) {
451     fluores[channel].intensity = i;
452     fluores[channel].x = x;
453     fluores[channel].y = y;
454   }
455 
456   /**
457    * setFluores.
458    * 
459    * @param m all channels measurements
460    */
461   public void setFluores(FluoMeasurement[] m) {
462 
463     for (int i = 0; i < 3; i++) {
464       fluores[i].intensity = m[i].intensity;
465       fluores[i].x = m[i].x;
466       fluores[i].y = m[i].y;
467     }
468   }
469 
470   /*
471    * (non-Javadoc)
472    * 
473    * @see java.lang.Object#toString()
474    */
475   @Override
476   public String toString() {
477     return "Vert [charge=" + charge + ", distance=" + distance + ", fluores="
478             + Arrays.toString(fluores) + ", curvatureLocal=" + curvatureLocal
479             + ", curvatureSmoothed=" + curvatureSmoothed + ", curvatureSum=" + curvatureSum
480             + ", coord=" + coord + ", fCoord=" + fCoord + ", fLandCoord=" + fLandCoord + ", gCoord="
481             + gCoord + ", gLandCoord=" + gLandCoord + ", tarLandingCoord=" + tarLandingCoord
482             + ", color=" + color + ", intsectID=" + intsectID + ", intState=" + intState
483             + ", toString()=" + super.toString() + "]";
484   }
485 
486   /**
487    * Dis coord 2 coord.
488    *
489    * @param a the a
490    * @param b the b
491    * @return the double
492    */
493   static double disCoord2Coord(double a, double b) {
494     if (a < b) {
495       return b - a;
496     }
497     if (b < a) {
498       return (1 - a) + b;
499     } else {
500       return 0;
501     }
502   }
503 
504   /**
505    * Adds the coords.
506    *
507    * @param a the a
508    * @param b the b
509    * @return the double
510    */
511   static double addCoords(double a, double b) {
512     double r = a + b;
513     if (r >= 1) {
514       r = r - 1;
515     }
516     return r;
517   }
518 
519 }