1 package com.github.celldynamics.quimp.plugin.protanalysis;
2
3 import java.awt.BorderLayout;
4 import java.awt.Color;
5 import java.awt.Component;
6 import java.awt.Font;
7 import java.awt.Graphics;
8 import java.awt.Graphics2D;
9 import java.awt.GridBagConstraints;
10 import java.awt.GridBagLayout;
11 import java.awt.GridLayout;
12 import java.awt.Panel;
13 import java.awt.Point;
14 import java.awt.event.InputEvent;
15 import java.awt.event.MouseEvent;
16 import java.awt.geom.Rectangle2D;
17 import java.util.ArrayList;
18 import java.util.ListIterator;
19
20 import javax.swing.BorderFactory;
21 import javax.swing.BoxLayout;
22 import javax.swing.ButtonGroup;
23 import javax.swing.JButton;
24 import javax.swing.JCheckBox;
25 import javax.swing.JComboBox;
26 import javax.swing.JLabel;
27 import javax.swing.JPanel;
28 import javax.swing.JRadioButton;
29 import javax.swing.JSeparator;
30 import javax.swing.JTextArea;
31 import javax.swing.JToggleButton;
32 import javax.swing.SwingConstants;
33 import javax.swing.SwingUtilities;
34 import javax.swing.border.EmptyBorder;
35
36 import org.apache.commons.lang3.mutable.MutableBoolean;
37 import org.scijava.vecmath.Point2d;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import com.github.celldynamics.quimp.Outline;
42 import com.github.celldynamics.quimp.OutlineHandler;
43 import com.github.celldynamics.quimp.QParamsQconf;
44 import com.github.celldynamics.quimp.QuimpException;
45 import com.github.celldynamics.quimp.Vert;
46 import com.github.celldynamics.quimp.plugin.protanalysis.ProtAnalysisOptions.GradientType;
47 import com.github.celldynamics.quimp.plugin.protanalysis.ProtAnalysisOptions.OutlinePlotTypes;
48 import com.github.celldynamics.quimp.plugin.qanalysis.STmap;
49 import com.github.celldynamics.quimp.utils.UiTools;
50 import com.github.celldynamics.quimp.utils.graphics.GraphicsElements;
51
52 import ij.ImagePlus;
53 import ij.gui.ImageCanvas;
54 import ij.gui.Overlay;
55 import ij.gui.PolygonRoi;
56 import ij.gui.Roi;
57 import ij.gui.StackWindow;
58
59
60
61
62
63
64
65 @SuppressWarnings("serial")
66 class ProtAnalysisUi extends StackWindow {
67 private Prot_Analysis model;
68 private Color overlayColor = Color.GREEN;
69
70 private ArrayList<OutlineHandler> handlers;
71
72 private Component cmp;
73 private Overlay overlay;
74 private ImagePlus imp;
75 JLabel pointsSelected = new JLabel("");
76 JLabel pointsSelectedPolar = new JLabel("");
77 JToggleButton bnPickPoint;
78
79
80
81
82
83
84
85 public ProtAnalysisUi(Prot_Analysis model, final ImagePlus imp) {
86 super(imp, new CustomCanvas(imp, model));
87 this.model = model;
88 try {
89 handlers = model.getQconfLoader().getEcmm().oHs;
90 } catch (QuimpException e) {
91
92 throw new RuntimeException("ECMM can not be obtained");
93 }
94 cmp = this.getComponent(1);
95 remove(cmp);
96 this.imp = imp;
97 buildWindow();
98 }
99
100 void updateStaticFields() {
101 pointsSelected.setText(Integer.toString(model.selected.size()));
102 Point2d point = ((ProtAnalysisOptions) model.getOptions()).gradientPoint;
103 pointsSelectedPolar.setText(point.toString());
104 }
105
106
107
108
109 public void buildWindow() {
110 ProtAnalysisOptions./../../com/github/celldynamics/quimp/plugin/protanalysis/ProtAnalysisOptions.html#ProtAnalysisOptions">ProtAnalysisOptions opt = (ProtAnalysisOptions) model.getOptions();
111 setLayout(new BorderLayout(10, 10));
112 add(ic, BorderLayout.CENTER);
113
114 JPanel cmpP = new JPanel();
115 cmpP.setLayout(new GridLayout());
116 cmpP.add(cmp);
117 cmpP.setBorder(new EmptyBorder(5, 5, 10, 10));
118 add(cmpP, BorderLayout.SOUTH);
119
120 Panel right = new Panel();
121 right.setLayout(new GridBagLayout());
122 GridBagConstraints c = new GridBagConstraints();
123 {
124 JPanel visualTrackingPanel = new JPanel();
125
126 visualTrackingPanel.setLayout(new BoxLayout(visualTrackingPanel, BoxLayout.PAGE_AXIS));
127 visualTrackingPanel.setBorder(BorderFactory.createTitledBorder("Visual tracking"));
128 {
129 JTextArea help = new JTextArea("Select points with CTRL key");
130 help.setLineWrap(true);
131 help.setWrapStyleWord(true);
132 help.setAlignmentX(Component.RIGHT_ALIGNMENT);
133
134
135 JPanel textPanel = new JPanel();
136 textPanel.setLayout(new GridLayout(1, 2));
137 JLabel selected = new JLabel("Selected: ");
138 textPanel.add(selected);
139 pointsSelected.setHorizontalAlignment(JLabel.RIGHT);
140 textPanel.add(pointsSelected);
141 visualTrackingPanel.add(buildSubPanel(2, 1, help, textPanel));
142 }
143 {
144 visualTrackingPanel.add(buildSubPanel(1, 2, getButton(new ActionToRoi("-> ROI",
145 "Transfer selected points to ROI manager. ROI manager will be cleared", this)),
146 getButton(new ActionFromRoi("<- ROI",
147 "Import ROIs from Roi Manager. ROI name must have format: "
148 + ProtAnalysisOptions.roiPrefix
149 + "CELLNO, where CELLNO is cell index. Hold CTRL key if all points "
150 + "refer to the same cell (no naming pattern needed, active cell is"
151 + " the one selected in Maps section).",
152 this))));
153 }
154 {
155 visualTrackingPanel.add(buildSubPanel(1, 1, getButton(
156 new ActionClearPoints("Remove all", "Remove all selected points", this))));
157 }
158 {
159 JRadioButton rbnStatic = new JRadioButton();
160 rbnStatic.setAction(new ActionUpdateOptionsRadio("Static", "Static", this,
161 opt.plotStaticDynamic, ProtAnalysisOptions.PLOT_STATIC));
162 JRadioButton rbnDynamic = new JRadioButton();
163 rbnDynamic.setAction(new ActionUpdateOptionsRadio("Dynamic", "Dynamic", this,
164 opt.plotStaticDynamic, ProtAnalysisOptions.PLOT_DYNAMIC));
165 switch (opt.plotStaticDynamic.getValue()) {
166 case ProtAnalysisOptions.PLOT_STATIC:
167 rbnStatic.setSelected(true);
168 break;
169 case ProtAnalysisOptions.PLOT_DYNAMIC:
170 rbnDynamic.setSelected(true);
171 break;
172 default:
173 rbnStatic.setSelected(true);
174 }
175 ButtonGroup buttonGroup = new ButtonGroup();
176 buttonGroup.add(rbnStatic);
177 buttonGroup.add(rbnDynamic);
178 visualTrackingPanel.add(buildSubPanel(1, 2, rbnStatic, rbnDynamic));
179 }
180 {
181 visualTrackingPanel.add(buildSubPanel(2, 2,
182 getCheckbox("Show point", "Show tracked point", opt.chbShowPoint),
183 getCheckbox("Show track", "Show tracks", opt.chbShowTrack),
184 getCheckbox("Smooth", "!Apply track smoothing in static and dynamic view",
185 opt.chbSmoothTracks),
186 getCheckbox("Show map", "Show tracks on motility map", opt.chbShowTrackMotility)));
187 }
188 {
189 JComboBox<OutlinePlotTypes> cbOutlineColor =
190 new JComboBox<OutlinePlotTypes>(OutlinePlotTypes.values());
191 cbOutlineColor.setSelectedItem(opt.selOutlineColoring.plotType);
192 cbOutlineColor.setAction(new ActionUpdateOptionsEnum("Outline color", "Set outline color",
193 this, opt.selOutlineColoring));
194 visualTrackingPanel.add(buildSubPanel(1, 1, cbOutlineColor));
195 }
196 {
197 JCheckBox cb =
198 getCheckbox("New image", "Always open new image with tracks", opt.chbNewImage);
199 visualTrackingPanel.add(buildSubPanel(1, 1, cb, getCheckbox("Flatten",
200 "Flatten stack used for showing static tracks", opt.chbFlattenStaticTrackImage)));
201
202 cb.setEnabled(false);
203 }
204 {
205 JButton tmpButton = getButton(new ActionTrackPoints("Track", "Track points", this));
206 tmpButton.addActionListener(new ActionSaveTracks(this));
207 visualTrackingPanel.add(buildSubPanel(2, 1, tmpButton,
208 getButton(new ActionClearOverlay("Clear overlay", "Clear Overlay", this))));
209 }
210 c.anchor = GridBagConstraints.NORTH;
211 c.gridx = 0;
212 c.gridy = 0;
213 c.weighty = 0;
214 c.fill = GridBagConstraints.HORIZONTAL;
215 right.add(visualTrackingPanel, c);
216 }
217 {
218 JPanel mapsPanel = new JPanel();
219 mapsPanel.setLayout(new BoxLayout(mapsPanel, BoxLayout.Y_AXIS));
220 mapsPanel.setBorder(BorderFactory.createTitledBorder("Maps"));
221 {
222 JComboBox<Integer> cbMapCellNumber = new JComboBox<Integer>();
223
224 STmap[] gs = ((QParamsQconf) model.getQconfLoader().getQp()).getLoadedDataContainer()
225 .getQState();
226 setComboBox(cbMapCellNumber, 0, gs.length - 1, opt.selActiveCellMap.getValue());
227 cbMapCellNumber.setAction(new ActionUpdateOptionsNumber("Cell number",
228 "Which cell to generate map for.", this, opt.selActiveCellMap));
229 mapsPanel.add(buildSubPanel(1, 1, cbMapCellNumber));
230 }
231 {
232 mapsPanel.add(buildSubPanel(1, 3, getButton(new ActionPlotMap("Mot",
233 "Plot motility map for selected cell. Hold CTRL to get unscaled 32-bit map.", this,
234 "MOT")),
235 getButton(new ActionPlotMap("Con",
236 "Plot convexity map for selected cell. Hold CTRL to get unscaled 32-bit "
237 + "map.",
238 this, "CONV")),
239 getButton(new ActionPlotMap("Flu",
240 "Plot fluoresence maps for selected cell. Hold CTRL to get unscaled 32-bit"
241 + " map.",
242 this, "FLU"))));
243 }
244 c.anchor = GridBagConstraints.NORTHWEST;
245 c.gridx = 0;
246 c.gridy = 1;
247 c.weighty = 0;
248 right.add(mapsPanel, c);
249 }
250 {
251 JPanel tablePanel = new JPanel();
252 tablePanel.setLayout(new BoxLayout(tablePanel, BoxLayout.Y_AXIS));
253 tablePanel.setBorder(BorderFactory.createTitledBorder("Tables and plots"));
254 {
255 JComboBox<Integer> cbPlotCellNumber = new JComboBox<Integer>();
256
257 STmap[] gs = ((QParamsQconf) model.getQconfLoader().getQp()).getLoadedDataContainer()
258 .getQState();
259 setComboBox(cbPlotCellNumber, 0, gs.length - 1, opt.selActiveCellPlot.getValue());
260 cbPlotCellNumber.setAction(new ActionUpdateOptionsNumber("Cell number",
261 "Which cell to generate map for.", this, opt.selActiveCellPlot));
262 tablePanel.add(buildSubPanel(1, 1, cbPlotCellNumber));
263 }
264 {
265 JRadioButton rbnCh1 = new JRadioButton();
266 rbnCh1.setAction(new ActionUpdateOptionsRadio("Ch1", "Set channel 1 active", this,
267 opt.selActiveChannel, ProtAnalysisOptions.CH1));
268 JRadioButton rbnCh2 = new JRadioButton();
269 rbnCh2.setAction(new ActionUpdateOptionsRadio("Ch2", "Set channel 2 active", this,
270 opt.selActiveChannel, ProtAnalysisOptions.CH2));
271 JRadioButton rbnCh3 = new JRadioButton();
272 rbnCh3.setAction(new ActionUpdateOptionsRadio("Ch3", "Set channel 3 active", this,
273 opt.selActiveChannel, ProtAnalysisOptions.CH3));
274 switch (opt.selActiveChannel.getValue()) {
275 case ProtAnalysisOptions.CH2:
276 rbnCh2.setSelected(true);
277 break;
278 case ProtAnalysisOptions.CH3:
279 rbnCh3.setSelected(true);
280 break;
281 default:
282 rbnCh1.setSelected(true);
283 }
284 ButtonGroup buttonGroup = new ButtonGroup();
285 buttonGroup.add(rbnCh1);
286 buttonGroup.add(rbnCh2);
287 buttonGroup.add(rbnCh3);
288 tablePanel.add(buildSubPanel(1, 3, rbnCh1, rbnCh2, rbnCh3));
289 }
290 {
291 tablePanel.add(buildSubPanel(1, 1, new JSeparator(SwingConstants.HORIZONTAL)));
292 tablePanel.add(buildSubPanel(1, 2,
293 getButton(new ActionTableGeom("Geom", "Show geometric features in table.", this)),
294 getButton(
295 new ActionTableFluo("Fluo", "Show fluoresecne features in table.", this))));
296 }
297 {
298 tablePanel.add(buildSubPanel(1, 1, new JSeparator(SwingConstants.HORIZONTAL)));
299 }
300 {
301 tablePanel.add(buildSubPanel(5, 2,
302 getCheckbox("X-Centr", "Centroid x-coordinate", opt.chbXcentrPlot),
303 getCheckbox("Y-Centr", "Centroid y-coordinate", opt.chbYcentrPlot),
304 getCheckbox("Displ", "Displacement", opt.chbDisplPlot),
305 getCheckbox("Dist", "Distance", opt.chbDistPlot),
306 getCheckbox("Persist", "Persistence", opt.chbPersistencePlot),
307 getCheckbox("Speed", "Speed", opt.chbSpeedPlot),
308 getCheckbox("Perim", "Perimeter", opt.chbPerimPlot),
309 getCheckbox("Elong", "Elongation", opt.chbElongPlot),
310 getCheckbox("Circ", "Circularity", opt.chbCircPlot),
311 getCheckbox("Area", "Area", opt.chbAreaPlot)));
312 }
313 {
314 tablePanel.add(buildSubPanel(1, 1, new JSeparator(SwingConstants.HORIZONTAL)));
315 }
316 {
317 tablePanel.add(buildSubPanel(5, 2,
318
319 getCheckbox("Total fl",
320 "Total fluorescence. Sum of all pixel intensities within the cell outline.",
321 opt.chbTotFluPlot),
322
323 getCheckbox("Mean fl",
324 "Mean fluorescence. Average intensity of pixels within the cell outline.",
325 opt.chbMeanFluPlot),
326
327 getCheckbox("Cortex", "Width of the cortex, as specified by the user.",
328 opt.chbCortexWidthPlot),
329
330 getCheckbox("Cyto",
331 "Area of the cytoplasm (area of the whole cell minus the cortex area).",
332 opt.chbCytoAreaPlot),
333
334 getCheckbox("Total ctf", "Sum of all pixel intensities within the cytoplasm.",
335 opt.chbTotalCytoPlot),
336
337 getCheckbox("Mean ctf", "Average pixel intensity within the cytoplasm.",
338 opt.chbMeanCytoPlot),
339
340 getCheckbox("Cortex ar", "Area of the cortex.", opt.chbCortexAreaPlot),
341
342 getCheckbox("Total ctf", "Sum of all pixel intensities within the cortex.",
343 opt.chbTotalCtf2Plot),
344
345 getCheckbox("Mean ctf", "Average pixel intensity within the cortex.",
346 opt.chbManCtfPlot)));
347 }
348 {
349 tablePanel.add(buildSubPanel(1, 1,
350 getButton(new ActionPlot2d("Plot", "Plot selected parameters.", this))));
351 }
352 c.anchor = GridBagConstraints.NORTHWEST;
353 c.gridx = 0;
354 c.gridy = 2;
355 c.weighty = 0;
356 right.add(tablePanel, c);
357 }
358 {
359 JPanel polarPanel = new JPanel();
360 polarPanel.setLayout(new BoxLayout(polarPanel, BoxLayout.Y_AXIS));
361 polarPanel.setBorder(BorderFactory.createTitledBorder("Polar plots"));
362 polarPanel.setToolTipText(UiTools.getToolTipString(
363 "Use of any selection tool from those below overwrites current selected point."));
364 {
365 bnPickPoint = getToggleButton(new ActionClickPredefinedPoint("Click",
366 "Select reference point on the screen.", this));
367 polarPanel.add(buildSubPanel(1, 2, bnPickPoint, getButton(
368 new ActionRoiPredefinedPoint("ROI", "Select reference point from ROI.", this))));
369 }
370 {
371 JComboBox<GradientType> cbRelativePolar =
372 new JComboBox<GradientType>(GradientType.values());
373 cbRelativePolar.setSelectedItem(GradientType.LB_CORNER);
374 cbRelativePolar.setAction(
375 new ActionGetPredefinedPoint("Relative to", "Select point relative to:", this));
376 polarPanel.add(buildSubPanel(1, 1, cbRelativePolar));
377 }
378 {
379 JLabel selected = new JLabel("Selected: ");
380 Font f = selected.getFont();
381 selected.setFont(f.deriveFont(f.getStyle() | Font.ITALIC | Font.BOLD));
382 pointsSelectedPolar.setHorizontalAlignment(JLabel.RIGHT);
383 polarPanel.add(buildSubPanel(1, 2, selected, pointsSelectedPolar));
384 }
385 {
386 polarPanel.add(buildSubPanel(1, 1, getButton(new ActionPolarPlot("Generate",
387 "Generate polar plot for reference point as shown above.", this))));
388 }
389 c.anchor = GridBagConstraints.NORTHWEST;
390 c.gridx = 0;
391 c.gridy = 3;
392 c.weighty = 1;
393 right.add(polarPanel, c);
394 }
395
396 add(right, BorderLayout.EAST);
397 pack();
398 updateStaticFields();
399
400 imp.setSlice(1);
401 updateOverlay(1);
402 setVisible(false);
403 }
404
405
406
407
408
409
410
411
412
413 private JCheckBox getCheckbox(String name, String desc, MutableBoolean option) {
414 JCheckBox chb = new JCheckBox();
415 chb.setAction(new ActionUpdateOptionsBoolean(name, desc, this, option));
416 chb.setSelected(option.getValue());
417 if (desc.startsWith("!")) {
418 chb.setAction(new ActionNotSupported(name, desc, this));
419 }
420 return chb;
421 }
422
423
424
425
426
427
428
429 private JButton getButton(ProtAnalysisAbstractAction act) {
430 JButton chb = new JButton();
431 chb.setAction(act);
432 return chb;
433 }
434
435
436
437
438
439
440
441 private JToggleButton getToggleButton(ProtAnalysisAbstractAction act) {
442 JToggleButton chb = new JToggleButton();
443 chb.setAction(act);
444 return chb;
445 }
446
447
448
449
450
451
452
453
454 private void setJComboBox(JComboBox<String> component, String[] item, String sel) {
455 for (String i : item) {
456 component.addItem(i);
457 }
458 if (item.length > 0) {
459 component.setSelectedItem(sel);
460 }
461 }
462
463
464
465
466
467
468
469
470
471 private void setComboBox(JComboBox<Integer> component, Integer min, Integer max, Integer sel) {
472 for (Integer i = min; i <= max; i++) {
473 component.addItem(i);
474 }
475 component.setSelectedItem(sel);
476 }
477
478
479
480
481
482
483
484
485
486 private JPanel buildSubPanel(int w, int h, Component... cmp) {
487 JPanel localPanel = new JPanel(new GridLayout(w, h));
488 for (Component c : cmp) {
489 localPanel.add(c);
490 }
491 return localPanel;
492
493 }
494
495
496
497
498
499
500
501
502
503
504 @Override
505 public void updateSliceSelector() {
506 super.updateSliceSelector();
507 model.currentFrame = imp.getCurrentSlice() - 1;
508 model.outlines.clear();
509 updateOverlay(model.currentFrame + 1);
510
511 }
512
513
514
515
516
517
518
519
520 public void updateOverlay(int frame) {
521 overlay = new Overlay();
522 for (OutlineHandler oh : handlers) {
523 if (oh.isOutlineAt(frame)) {
524 Outline outline = oh.getStoredOutline(frame);
525 model.outlines.add(outline);
526 Roi r = outline.asFloatRoi();
527 r.setStrokeColor(overlayColor);
528 overlay.add(r);
529 }
530 }
531 imp.setOverlay(overlay);
532 updateOverlayPoints(frame);
533 }
534
535
536
537
538
539
540
541
542 void updateOverlayPoints(int frame) {
543
544 final String roiName = "USER_POINT";
545 overlay = imp.getOverlay();
546 if (overlay == null) {
547 return;
548 }
549
550
551 overlay.remove(roiName);
552
553 for (PointCoords p : model.selected) {
554 if (p.frame == imp.getCurrentSlice() - 1) {
555 PolygonRoi or = GraphicsElements.getCircle(p.point.getX(), p.point.getY(),
556 ProtAnalysisOptions.staticPointColor, ProtAnalysisOptions.staticPointSize);
557 or.setName(roiName);
558 overlay.add(or);
559 }
560 }
561 }
562
563
564
565
566
567
568 public void showUI(boolean val) {
569 setVisible(val);
570 }
571
572
573
574
575
576
577 Prot_Analysis getModel() {
578 return model;
579 }
580 }
581
582
583
584
585
586
587
588 @SuppressWarnings("serial")
589 class CustomCanvas extends ImageCanvas {
590 static final Logger LOGGER = LoggerFactory.getLogger(CustomCanvas.class.getName());
591
592
593 PointCoords pc = null;
594 private Prot_Analysis model;
595 private ProtAnalysisOptions options;
596 private int sensitivity = 10;
597
598 public CustomCanvas(ImagePlus imp, Prot_Analysis model) {
599 super(imp);
600 this.model = model;
601 this.options = ((ProtAnalysisOptions) model.getOptions());
602 }
603
604
605
606
607
608
609 @Override
610 public void mousePressed(MouseEvent e) {
611
612
613 if (SwingUtilities.isLeftMouseButton(e)
614 && ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) == InputEvent.CTRL_DOWN_MASK)) {
615 if (pc != null) {
616
617 if (model.selected.add(pc) == false) {
618 model.selected.remove(pc);
619 }
620 model.getGui().updateStaticFields();
621 model.getGui().updateOverlayPoints(model.currentFrame);
622 }
623 } else {
624 if (SwingUtilities.isLeftMouseButton(e) && options.bnGradientPickActive.booleanValue()) {
625 options.gradientPoint = new Point2d(e.getX(), e.getY());
626 model.getGui().bnPickPoint.doClick();
627 model.getGui().updateStaticFields();
628 } else {
629 super.mousePressed(e);
630 }
631 }
632
633 }
634
635
636
637
638
639
640
641
642
643 private PointCoords checkProximity(Point current, double dist) {
644
645 ListIterator<Outline> it = model.outlines.listIterator();
646 while (it.hasNext()) {
647 Integer io = it.nextIndex();
648 Outline o = it.next();
649 Rectangle2D.Double bounds = o.getDoubleBounds();
650 if (bounds.contains(current)) {
651 for (Vert v : o) {
652 if (current.distanceSq(v.getX(), v.getY()) < dist) {
653 return new PointCoords(
654 new Point((int) Math.round(v.getX()), (int) Math.round(v.getY())), io);
655 }
656 }
657 }
658 }
659 return null;
660 }
661
662
663
664
665
666
667 @Override
668 public void mouseMoved(MouseEvent e) {
669 super.mouseMoved(e);
670
671 Point p = new Point(offScreenX(e.getX()), offScreenY(e.getY()));
672
673 PointCoords ptmp = checkProximity(p, sensitivity);
674 if (ptmp != null) {
675 pc = ptmp;
676 repaint();
677 } else {
678 if (pc != null) {
679 pc = null;
680 repaint();
681 }
682 }
683 }
684
685
686
687
688
689
690 @Override
691 public void paint(Graphics g) {
692 super.paint(g);
693 Graphics2D g2 = (Graphics2D) g;
694 double half = ProtAnalysisOptions.pointSize / 2;
695 if (pc != null) {
696 Rectangle2D e = new Rectangle2D.Double(screenXD(pc.point.getX()) - half,
697 screenYD(pc.point.getY()) - half, ProtAnalysisOptions.pointSize,
698 ProtAnalysisOptions.pointSize);
699 g2.setPaint(ProtAnalysisOptions.pointColor);
700 g2.draw(e);
701 }
702 }
703
704 }