View Javadoc
1   /*** WellButton.java - part of the MirkE (say murky) application for colormetric analysis emphesizing 
2   kinetics.
3   
4   Created by: Scott Menor on 21 July, 2004.
5   Last modified by: Scott Menor on 12 December, 2004
6   
7   Copyright (c) 2004 Arizona State University - Cancer Research Institute. All rights reserved.
8   
9   MirkE is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13  
14  MirkE is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  GNU General Public License for more details.
18  
19  You should have received a copy of the GNU General Public License
20  along with MirkE; if not, write to the Free Software
21  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  US
22  */
23  
24  package edu.asu.cri.MirkE.gui;
25  
26  import edu.asu.cri.MirkE.*;
27  import edu.asu.cri.MirkE.exceptions.MirkEApplicationException;
28  import edu.asu.cri.MirkE.exceptions.MirkESystemException;
29  import edu.asu.cri.MirkE.dataStructures.PlateWellCategory;
30  
31  import java.awt.BasicStroke;
32  import java.awt.Color;
33  import java.awt.Graphics;
34  import java.awt.Graphics2D;
35  import java.awt.RenderingHints;
36  import java.awt.event.MouseEvent;
37  import java.awt.event.MouseListener;
38  import java.awt.geom.Ellipse2D;
39  import java.text.DecimalFormat;
40  import java.text.NumberFormat;
41  import java.util.HashMap;
42  import java.util.Iterator;
43  import java.util.Map;
44  import java.util.Set;
45  
46  import javax.swing.JComponent;
47  
48  /*** A viewer for multiwell plates used to represent colormetric data and to allow users to select which well(s) belong to a specific group 
49  
50  @author Scott Menor
51  @version 0.3.0 12 december, 2004
52  */
53  
54  import org.apache.commons.logging.Log;
55  import org.apache.commons.logging.LogFactory;
56   
57  /***
58   * @author smenor
59   *
60   */
61  public class WellButton extends JComponent implements MouseListener, PlateViewEventListener {
62  	private MirkE mirke;
63  	
64  	private String plateWellType; // TODO - add getter and setter
65  	
66  	private java.util.List wellDataPointList;
67  	
68  	private Map observableToMeanValueMap;
69  	private Map observableToMinValueMap;
70  	private Map observableToMaxValueMap;
71  	
72  	private String selectableParameter;
73  
74  	private static NumberFormat measuredValueFormat;
75  	
76  	 /***
77       * Logger one of those classes were we need to use a logger
78       * signiture of mouse event doesn'nt support exception
79       * */
80      private static final Log log = LogFactory.getLog(WellButton.class);
81  
82  	private NumberFormat getMeasuredValueFormat() {
83  		if (measuredValueFormat == null) {
84  			measuredValueFormat = new DecimalFormat();
85  			measuredValueFormat.setMaximumFractionDigits(4);
86  			
87  		}
88  		
89  		return measuredValueFormat;
90  	}
91  
92  	/***
93  		
94  	 @param selectableParameter
95  		*/
96  	public void setSelectableParameter(String selectableParameter) {
97  		this.selectableParameter = selectableParameter;
98  	}
99  	
100 	/*** 
101 		@return selectableParameter
102 		*/
103 	public String getSelectableParameter() {
104 		return selectableParameter;
105 	}
106 	
107 	private boolean selectableParameterState = false;
108 	
109 	/***
110 	 *
111 	 * @param mirke
112 	 * @throws MirkEApplicationException
113 	 */
114 	public void setMirke(MirkE mirke) throws  MirkEApplicationException{
115 		this.mirke = mirke;
116 	}
117 	
118 	/***
119 		
120 	 @return mirke
121 	 */
122 	public MirkE getMirke() {
123 		return this.mirke;
124 	}
125 	
126 	private String plateRowLabel;
127 	
128 	/***
129 		@param plateRowLabel
130 	 */
131 	public void setPlateRowLabel(String plateRowLabel) {
132 		this.plateRowLabel = plateRowLabel;
133 	}
134 	
135 	/***
136 		@return plateRowLabel
137 	 */
138 	public String getPlateRowLabel() {
139 		return this.plateRowLabel;
140 	}
141 	
142 	
143 	private String plateColumnLabel;
144 	
145 	/***
146 		@return plateColumnLabel
147 	 */
148 	public String getPlateColumnLabel() {
149 		return this.plateColumnLabel;
150 	}
151 	
152 	/***
153 		@param plateColumnLabel
154 	 */
155 	public void setPlateColumnLabel(String plateColumnLabel) {
156 		this.plateColumnLabel = plateColumnLabel;
157 	}
158 	
159 	/*** preferred constructor	
160 	 * @param mirke
161 	 * @param plateRowLabel
162 	 * @param plateColumnLabel
163 	 * @param plateWellType
164 	 * @param selectableParameter
165 	 * @throws MirkEApplicationException
166 	 */
167 	public WellButton(MirkE mirke,
168 					  String plateRowLabel,
169 					  String plateColumnLabel,
170 					  String plateWellType,
171 					  String selectableParameter)throws MirkEApplicationException {
172 		super();
173 		
174 		this.mirke = mirke;
175 		this.plateRowLabel = plateRowLabel;
176 		this.plateColumnLabel = plateColumnLabel;
177 		this.plateWellType = plateWellType;
178 		this.selectableParameter = selectableParameter;
179 		
180 		addMouseListener(this);
181 		update();
182 	}
183 	
184 	/***
185 		
186 	 @param graphics
187 	 */
188 	public void paintComponent(Graphics graphics){
189 		graphics.setColor(getBackground());
190 		
191 		Graphics2D graphics2D = (Graphics2D) graphics;
192 		graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
193 		
194 		graphics2D.setPaint(getBackground());
195 		
196 		graphics2D.fill(new Ellipse2D.Double(0,
197 											 0,
198 											 getWidth(),
199 											 getHeight()));
200 						
201 		if (plateWellType.equals("E")) {
202 			graphics2D.setPaint(Color.white);
203 //			graphics2D.fill(new Ellipse2D.Double(2,2,getWidth()-4,getHeight()-4));
204 
205 		} else {
206 		   
207 		    try{
208 		        graphics2D.setPaint(DataSetColorModel.toColor(mirke,
209 														  observableToMinValueMap,
210 														  observableToMeanValueMap,
211 														  observableToMaxValueMap));
212 			
213 		    } catch (MirkESystemException me){
214 		        
215 		    //    exception to the exception handling graphic dosen't throw exception
216 		        
217 		    }
218 			
219 			graphics2D.fill(new Ellipse2D.Double(3,
220 												 3,
221 												 getWidth()-6,
222 												 getHeight()-6));
223 		    
224 			
225 			// paint a black or white circle around the well if it is of is not a member of the category, respectively
226 			if (selectableParameterState) {
227 				graphics2D.setPaint(Color.black);
228 			} else {
229 				graphics2D.setPaint(Color.white);
230 			}
231 			
232 			graphics2D.setStroke(new BasicStroke(2.0f));
233 			graphics2D.draw(new Ellipse2D.Double(2,2,getWidth()-4,getHeight()-4));
234 			
235 		}
236 		
237 		graphics2D.dispose();
238 	}
239 	
240 	/*** update the <code>WellButton</code> to reflect the current state of the <code>DataSet</code>
241 	 * @throws MirkEApplicationException
242 	 
243 	 */
244 	public void update() throws MirkEApplicationException {		
245 		java.util.List selectableParameterStateList = mirke.getDataSet().find("from PlateWellCategory as c where c.plateRow='"+plateRowLabel+"' and c.plateColumn='"+plateColumnLabel+"' and c.categoryName='"+selectableParameter+"'");
246 		
247 		if (selectableParameterStateList.size() > 0) { 
248 			
249 			selectableParameterState = true;
250 		} else {
251 			selectableParameterState = false;
252 		}
253 		
254 		if (observableToMinValueMap == null) {
255 			observableToMinValueMap = new HashMap();	
256 		}
257 		
258 		if (observableToMeanValueMap == null) {
259 			observableToMeanValueMap = new HashMap();	
260 		}
261 		
262 		if (observableToMaxValueMap == null) {
263 			observableToMaxValueMap = new HashMap();	
264 		}
265 		
266 		if (plateWellType.equals("M")) {
267 			Set observables = mirke.getDataSet().getObservables();
268 			Iterator observablesIterator = observables.iterator();
269 			while (observablesIterator.hasNext()) {
270 				String observable = observablesIterator.next().toString();
271 				
272 				// TODO - move this to DataSet or some other class(no sense in repeating the same query for every well)
273 				java.util.List minObservedValueList = mirke.getDataSet().find("select min(p.observedValue) from PlateWellDataPoint p where p.observableName='"+observable+"'");
274 				java.util.List meanObservedValueList = mirke.getDataSet().find("select avg(p.observedValue) from PlateWellDataPoint p where p.plateRow='"+plateRowLabel+"' and p.plateColumn='"+plateColumnLabel+"' and p.observableName='"+observable+"'");
275 				java.util.List maxObservedValueList = mirke.getDataSet().find("select max(p.observedValue) from PlateWellDataPoint p where p.observableName='"+observable+"'");
276 				
277 				if ((meanObservedValueList.size() == 1) && (minObservedValueList.size() == 1) && (maxObservedValueList.size() == 1)) {
278 					Double minValue  = (Double)(minObservedValueList.get(0));
279 					observableToMinValueMap.put(observable,
280 												minValue);
281 					
282 					Double meanValue = (Double)(meanObservedValueList.get(0));
283 					observableToMeanValueMap.put(observable,
284 												 meanValue);
285 					
286 					Double maxValue  = (Double)(maxObservedValueList.get(0)); 
287 					observableToMaxValueMap.put(observable,
288 												maxValue);
289 				}
290 			}
291 			
292 			updateToolTipText();
293 		}
294 		
295 		repaint(getVisibleRect());
296 	}
297 	
298 	/***
299 		*/
300 	public void updateToolTipText() {
301 		Set observableToMeanValueMapEntrySet = observableToMeanValueMap.entrySet();
302 		
303 		String toolTipText = "" + plateRowLabel + plateColumnLabel + " ";
304 		
305 		Iterator observableToMeanValueMapEntrySetIterator = observableToMeanValueMapEntrySet.iterator();
306 		while (observableToMeanValueMapEntrySetIterator.hasNext()) {
307 			Map.Entry observableToMeanValueMapEntry = (Map.Entry)observableToMeanValueMapEntrySetIterator.next();
308 			
309 			String observable = observableToMeanValueMapEntry.getKey().toString();
310 			
311 			Double observableValue = (Double)observableToMeanValueMapEntry.getValue();
312 			
313 			toolTipText += observable + ": " + getMeasuredValueFormat().format(observableValue) + "\t";
314 		}
315 		
316 		setToolTipText(toolTipText);	
317 	}
318 	
319 	/***
320 	 * @throws MirkEApplicationException
321 	 *
322 	 */
323 	public void toggleWellState() throws MirkEApplicationException{	
324 		java.util.List selectableParameterStateList = mirke.getDataSet().find("from PlateWellCategory as c where c.plateRow='"+plateRowLabel+"' and c.plateColumn='"+plateColumnLabel+"' and c.categoryName='"+selectableParameter+"'");
325 		
326 		if (selectableParameterStateList.size() > 0) {
327 			// iterate through selectableParameterStateList and delete the items in it
328 			Iterator selectableParameterStateListIterator = selectableParameterStateList.iterator();
329 			while (selectableParameterStateListIterator.hasNext()) {
330 				PlateWellCategory plateWellCategory = (PlateWellCategory)selectableParameterStateListIterator.next();
331 				
332 				mirke.getDataSet().delete(plateWellCategory);
333 			}
334 			
335 			selectableParameterState = false;
336 			
337 		} else {
338 			// TODO - iterate through the plateIdentifiers represented by this well (for now, use all of them)
339  			java.util.Set plateIdentifiers = mirke.getDataSet().getPlateIdentifiers();
340 			
341 			Iterator plateIdentifierIterator = plateIdentifiers.iterator();
342 			while (plateIdentifierIterator.hasNext()) {
343 				String plateIdentifier = plateIdentifierIterator.next().toString();
344 
345 				PlateWellCategory plateWellCategory = new PlateWellCategory(plateIdentifier,
346 																			plateRowLabel,
347 																			plateColumnLabel,
348 																			selectableParameter);
349 				mirke.getDataSet().save(plateWellCategory); // TODO - do this more efficiently?
350 			}
351 			
352 			selectableParameterState = true;
353 		}
354 		
355 		update();
356 	}
357 	
358 	/***
359 		
360 	 @param mouseEvent
361 	 */
362 	public void mouseClicked(MouseEvent mouseEvent) {
363 		//		toggleWellState();
364 	}
365 	
366 	/***
367 		
368 	 @param mouseEvent
369 	 */
370 	public void mouseEntered(MouseEvent mouseEvent) {
371 		if (mouseEvent.getClickCount() > 0) {
372 		  try {  
373 			toggleWellState();
374 		} catch(MirkEApplicationException e){
375 		    
376 		}
377 		}
378 	}
379 	
380 	/***
381 		
382 	 @param mouseEvent
383 	 */
384 	public void mouseExited(MouseEvent mouseEvent) {
385 		
386 	}
387 	
388 	/***
389 		
390 	 @param mouseEvent
391 	 */
392 	public void mousePressed(MouseEvent mouseEvent) {
393 	    try{
394 		toggleWellState();
395 	    } catch(MirkEApplicationException e){
396 		    
397 		}
398 	} 
399 	
400 	/***
401 		
402 	 @param mouseEvent
403 	 */
404 	public void mouseReleased(MouseEvent mouseEvent) {
405 		
406 	}	
407 	
408 	/***
409 		
410 	 @param plateViewEvent
411 		*/
412 	public void plateViewChanged(PlateViewEvent plateViewEvent) {
413 		// TODO - identify the nature of the event and update the well / representation (most likely, changing a category, for now) 
414 		
415 		PlateView plateView = plateViewEvent.getPlateView();
416 		setSelectableParameter(plateView.getSelectableParameter());
417 		
418 	}
419 
420 }