View Javadoc

1   /**
2    * 
3    */
4   package de.desy.acop.video;
5   
6   import java.awt.Graphics;
7   import java.awt.Graphics2D;
8   import java.awt.geom.GeneralPath;
9   import java.awt.geom.Line2D;
10  import java.awt.geom.Rectangle2D;
11  
12  import javax.swing.JPanel;
13  
14  /**
15   * </code>SideProfileDisplayer</code> is a component that displays a one dimensional profile
16   * of an image. This displayer can have either horizontal or vertical orientation.
17   * It plots a </code>double[]</code> normalized to its height or width. 
18   * 
19   * @author Tilen Kusterle, Cosylab
20   *
21   */
22  public class SideProfileDisplayer extends JPanel {
23  	
24  	private static final long serialVersionUID = 1L;
25  	
26  	private boolean horizontalOrientation = true;
27  	
28  	private double[] profile = null;
29  	private double[] gaussProfile = null;
30  	private double[] gaussProfileFit = null;
31  	private double max;
32  	private double min;
33  	
34  	private double canvasStart = 0;
35  	private double canvasSize = 0;
36  	private int roiStart = -1;
37  	private int roiLength = -1;
38  	private double roi1 = Double.NaN;
39  	private double roi2 = Double.NaN;
40  	
41  	private boolean displayStatistics = true;
42  		
43  	private Object mutex = new Object();
44  	
45  	/**
46  	 * Constructs this </code>SideProfileDisplayer</code>. The construction parameter
47  	 * defines the orientation of this displayer (horizontal or vertical).
48  	 * @param horizontalOrientation if </code>true</code> the displayer is horizontally
49  	 * oriented; if </code>false</code> the displayer is vertically oriented
50  	 */
51  	public SideProfileDisplayer(boolean horizontalOrientation) {
52  		this.horizontalOrientation = horizontalOrientation;
53  		setBackground(Definitions.getBackgroundColor());
54  	}
55  	
56  	/**
57  	 * Sets data to this </code>SideProfileDisplayer</code>.
58  	 * @param profile the profile to draw
59  	 * @param amplitude the amplitude of Gauss fit
60  	 * @param mean the mean of Gauss fit
61  	 * @param std the STD value of Gauss fit
62  	 * @param constant the constant of Gauss fit
63  	 * @param roiStart the start index of region of interest
64  	 * @param roiLength the length of region of interest
65  	 */
66  	@SuppressWarnings({"null"})
67  	public void setData(double[] profile, double amplitude, double mean, double std, double constant, 
68  			double amplitudeFit, double meanFit, double stdFit, double constantFit, double slopeFit, int roiStart, int roiLength,
69  			boolean drawFit) {
70  		this.profile = profile;
71  		this.roiStart = roiStart;
72  		this.roiLength = roiLength;
73  		
74  		int length = profile.length;
75  		if (roiStart < 0 || roiLength < 0 || roiStart+roiLength > length) throw new IllegalStateException("Illegal region of interest!");
76  		
77  		int i = 0;
78  		double[] statProfile = new double[roiLength];
79  		double[] fitProfile = null;
80  		if (drawFit) {
81  			fitProfile = new double[roiLength];
82      		for(; i < roiLength; i++) {
83      			statProfile[i] = amplitude*Math.exp(-(roiStart+i-mean)*(roiStart+i-mean)/(2*std*std))+constant;
84      			fitProfile[i] = amplitudeFit*Math.exp(-(roiStart+i-meanFit)*(roiStart+i-meanFit)/(2*stdFit*stdFit))+constantFit + (roiStart+i)*slopeFit;
85      		}
86  		} else {
87  			for(; i < roiLength; i++) {
88  				statProfile[i] = amplitude*Math.exp(-(roiStart+i-mean)*(roiStart+i-mean)/(2*std*std))+constant;
89      		}
90  		}
91  		
92  		min = Double.MAX_VALUE;
93  		max = -Double.MAX_VALUE;
94  		for (i = 0; i < length; i++) {
95  			if (profile[i] < min) min = profile[i];
96  			if (profile[i] > max) max = profile[i];
97  		}
98  		if (drawFit) {
99      		for (i = 0; i < roiLength; i++) {
100     			if (statProfile[i] < min) min = statProfile[i];
101     			if (statProfile[i] > max) max = statProfile[i];
102     			if (fitProfile[i] < min) min = fitProfile[i];
103     			if (fitProfile[i] > max) max = fitProfile[i];
104     		}
105 		} else {
106 			for (i = 0; i < roiLength; i++) {
107     			if (statProfile[i] < min) min = statProfile[i];
108     			if (statProfile[i] > max) max = statProfile[i];
109     		}
110 		}
111     	synchronized(mutex) {
112     		if (drawFit) {
113     			gaussProfileFit = fitProfile;
114     			gaussProfile = statProfile;
115     		} else {
116     			gaussProfile = statProfile;
117     			gaussProfileFit = null;
118     		}
119 		}
120 		
121 		repaint();
122 	}
123 	
124 	/**
125 	 * Clears this displayer's data.
126 	 */
127 	public void clearData() {
128 		profile = null;
129 		gaussProfile = null;
130 		gaussProfileFit = null;
131 		min = Double.MAX_VALUE;
132 		max = -Double.MAX_VALUE;
133 		
134 		canvasStart = 0;
135 		canvasSize = 0;
136 		roiStart = -1;
137 		roiLength = -1;
138 		roi1 = Double.NaN;
139 		roi2 = Double.NaN;
140 		
141 		repaint();
142 	}
143 	
144 	/**
145 	 * Sets the position of region of interest markers on this displayer.
146 	 * @param c1 the position of the first marker
147 	 * @param c2 the position of the second marker
148 	 */
149 	public void setRoi(double c1, double c2) {
150 		roi1 = c1;
151 		roi2 = c2;
152 		repaint();
153 	}
154 	
155 	public void setCanvasSize(double start, double size, boolean repaintAtOnce) {
156 		canvasSize = size;
157 		canvasStart = start;
158 		if (repaintAtOnce) repaint();
159 	}
160 	
161 	public void setCanvasStart(double start) {
162 		if (canvasStart == start) return;
163 		canvasStart = start;
164 		repaint();
165 	}
166 	
167 	/**
168 	 * Clears the region of interest markers on this displayer.
169 	 */
170 	public void clearRoi() {
171 		roi1 = Double.NaN;
172 		roi2 = Double.NaN;
173 		repaint();
174 	}
175 	
176 	@Override
177 	protected void paintComponent(Graphics g) {
178 		super.paintComponent(g);
179 		drawProfile((Graphics2D) g);
180 		drawRoi((Graphics2D) g);
181 	}
182 	
183 	void setDisplayStatistics(boolean display) {
184 		this.displayStatistics = display;
185 		repaint();
186 	}
187 		
188 	private void drawProfile(Graphics2D g) {
189 		if (gaussProfile == null || gaussProfile.length == 0) return;
190 		int i = 0;
191 		int length = profile.length;
192 
193 		double coeff = (horizontalOrientation ? getHeight() : getWidth())/(max-min);
194 		double delta = canvasSize/(length-1);
195 
196 		GeneralPath dataPath = new GeneralPath();
197 		GeneralPath statisticsPath = new GeneralPath();
198 		GeneralPath fitPath = new GeneralPath();
199 		double x, y;
200 		synchronized (mutex) {
201     		if (horizontalOrientation) {
202     			for (i = 0; i < length; i++) {
203     				x = canvasStart+i*delta;
204     				y = getHeight()-(profile[i]-min)*coeff;
205     				if (i == 0) dataPath.moveTo(x, y);
206     				else dataPath.lineTo(x, y);
207     			}
208     			for (i = 0; i < roiLength; i++) {
209     				x = canvasStart+(roiStart+i)*delta;
210     				y = getHeight()-(gaussProfile[i]-min)*coeff;
211     				if (i == 0) statisticsPath.moveTo(x, y);
212     				else statisticsPath.lineTo(x, y);
213     			}
214     			if (gaussProfileFit != null) {
215         			for (i = 0; i < roiLength; i++) {
216         				x = canvasStart+(roiStart+i)*delta;
217         				y = getHeight()-(gaussProfileFit[i]-min)*coeff;
218         				if (i == 0) fitPath.moveTo(x, y);
219         				else fitPath.lineTo(x, y);
220         			}
221     			}
222     		} else {
223     			for (i = 0; i < length; i++) {
224     				x = canvasStart+i*delta;
225     				y = getWidth()-(profile[i]-min)*coeff;
226     				if (i == 0) dataPath.moveTo(y, x);
227     				else dataPath.lineTo(y, x);
228     			}
229     			for (i = 0; i < roiLength; i++) {
230     				x = canvasStart+(roiStart+i)*delta;
231     				y = getWidth()-(gaussProfile[i]-min)*coeff;
232     				if (i == 0) statisticsPath.moveTo(y, x);
233     				else statisticsPath.lineTo(y, x);
234     			}
235     			if (gaussProfileFit != null) {
236         			for (i = 0; i < roiLength; i++) {
237         				x = canvasStart+(roiStart+i)*delta;
238         				y = getWidth()-(gaussProfileFit[i]-min)*coeff;
239         				if (i == 0) fitPath.moveTo(y,x);
240         				else fitPath.lineTo(y,x);
241         			}
242     			}
243     		}
244 		}
245 		
246 		double x1 = horizontalOrientation ? canvasStart : 0;
247 		double y1 = horizontalOrientation ? 0 : canvasStart;
248 		double x2 = horizontalOrientation ? canvasSize : getWidth();
249 		double y2 = horizontalOrientation ? getHeight() : canvasSize;
250 		Rectangle2D r = new Rectangle2D.Double(x1, y1, x2, y2);
251 		g.setPaint(Definitions.getCanvasColor());
252 		g.fill(r);
253 		
254 		g.setPaint(Definitions.getDataColor());
255 		g.draw(dataPath);
256 		if (gaussProfileFit != null) {
257     		g.setPaint(Definitions.getFitColor());
258     		g.draw(fitPath);
259 		}
260 		if (displayStatistics) {
261     		g.setPaint(Definitions.getStatisticsColor());
262     		g.draw(statisticsPath);
263 		}
264 		
265 		double p1 = canvasStart+roiStart*delta;
266 		double p2 = canvasStart+(roiStart+roiLength-1)*delta;
267 		
268 		x1 = horizontalOrientation ? p1 : 0;
269 		y1 = horizontalOrientation ? 0 : p1;
270 		x2 = horizontalOrientation ? p1 : getWidth();
271 		y2 = horizontalOrientation ? getHeight() : p1;
272 		Line2D l1 = new Line2D.Double(x1, y1, x2, y2);
273 		x1 = horizontalOrientation ? p2 : 0;
274 		y1 = horizontalOrientation ? 0 : p2;
275 		x2 = horizontalOrientation ? p2 : getWidth();
276 		y2 = horizontalOrientation ? getHeight() : p2;
277 		Line2D l2 = new Line2D.Double(x1, y1, x2, y2);
278 		
279 		g.setPaint(Definitions.getRoiColor());
280 		g.draw(l1);
281 		g.draw(l2);
282 		
283 	}
284 	
285 	private void drawRoi(Graphics2D g) {
286 		if (!Double.isNaN(roi1) && !Double.isNaN(roi2)) {
287 			double x1 = horizontalOrientation ? roi1 : 0;
288 			double y1 = horizontalOrientation ? 0 : roi1;
289 			double x2 = horizontalOrientation ? roi1 : getWidth();
290 			double y2 = horizontalOrientation ? getHeight() : roi1;
291 			Line2D l1 = new Line2D.Double(x1, y1, x2, y2);
292 			x1 = horizontalOrientation ? roi2 : 0;
293 			y1 = horizontalOrientation ? 0 : roi2;
294 			x2 = horizontalOrientation ? roi2 : getWidth();
295 			y2 = horizontalOrientation ? getHeight() : roi2;
296 			Line2D l2 = new Line2D.Double(x1, y1, x2, y2);
297 			
298 			g.setPaint(Definitions.getRoiSelectingColor());
299 			g.draw(l1);
300 			g.draw(l2);
301 		}
302 	}
303 
304 }