KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > JSci > instruments > PTCroquetteCross


1 package JSci.instruments;
2
3 import JSci.swing.*;
4
5 import java.awt.*;
6 import java.awt.event.*;
7 import java.awt.geom.*;
8 import javax.swing.*;
9 import javax.swing.text.*;
10 import javax.swing.event.*;
11 import java.util.*;
12 import java.text.*;
13 import java.awt.image.*;
14
15 /** Data about a cross that can be put on an image, follow the
16  * center, find the height
17 */

18 public class PTCroquetteCross extends Polygon implements Control {
19
20     private int crossHW=3;
21     private int crossL=32;
22     private Point2D position = new Point2D.Double();
23     private Point intPosition = new Point();
24     private double z = 0.0;
25     private boolean dragging = true;
26     private Rectangle bbox = null;
27     private Color color;
28
29     /**
30      * Crates a new cross
31      * @param l length of the arm of the cross
32      * @param hw half width of the arms of the cross
33      * @param p initial center of the cross
34      */

35     public PTCroquetteCross(int l, int hw, Point p, Color col) {
36     super(new int[] {-hw,hw,hw,l,l,hw,hw,-hw,-hw,-l,-l,-hw},
37           new int[] {-l,-l,-hw,-hw,hw,hw,l,l,hw,hw,-hw,-hw},
38           12
39           );
40     crossHW=hw;
41     crossL=l;
42     intPosition.setLocation(p);
43     translate(intPosition.x,intPosition.y);
44     position.setLocation(p);
45     color=col;
46     z = 0.0;
47     dragging = false;
48     calibrating=false;
49     }
50
51
52
53
54
55     private void FFT(double []x,double []y,int d)
56     {
57     int n,m,l,le,le1,i,j,ip,nv2,nm1,k;
58     double ur,ui,wr,wi,tr,ti,sr,si;
59     
60     n=x.length;
61     m=2;
62     switch (n) {
63     case 4:m=2;break;
64     case 8:m=3;break;
65     case 16:m=4;break;
66     case 32:m=5;break;
67     case 64:m=6;break;
68     case 128:m=7;break;
69     case 256:m=8;break;
70     case 512:m=9;break;
71     case 1024:m=10;break;
72     case 2048:m=11;break;
73     }
74     le1=n;
75     for (l=1;l<=m;l++)
76         {
77         le=le1;
78         le1=le/2;
79         ur=1.0;ui=0.0;
80         wr=Math.cos(Math.PI/le1);wi=d*Math.sin(Math.PI/le1);
81         for (j=0;j<le1;j++)
82             {
83             for (i=j;i<n;i+=le)
84                 {
85                 ip=i+le1;
86                 tr=x[i]+x[ip];ti=y[i]+y[ip];
87                 sr=x[i]-x[ip];si=y[i]-y[ip];
88                 x[ip]=sr*ur-si*ui;y[ip]=sr*ui+si*ur;
89                 x[i]=tr;y[i]=ti;
90                 }
91             tr=ur*wr-ui*wi;
92             ui=ur*wi+ui*wr;
93             ur=tr;
94             }
95         
96         }
97     
98     nv2=n/2;
99     nm1=n-1;
100     j=0;
101     for (i=0;i<nm1;i++)
102         {
103         if (i<j)
104             {
105             tr=x[j];ti=y[j];
106             x[j]=x[i];y[j]=y[i];
107             x[i]=tr;y[i]=ti;
108             }
109         k=nv2;
110         while (k<j+1) {j=j-k;k/=2;}
111         j+=k;
112         }
113     
114     }
115
116
117     int fromImg(byte c) { if (c>=0) return (int)c; else return (int)(256+c); }
118
119     private Point2D findJNIXY(Image f,int x0,int y0,int l,int w) {
120     double t,tx,ty,frp,fip,frm,fim,tr,ti;
121     double h[],v[];
122     int j,k,mx,my;
123     
124     h=new double[2*l];
125     v=new double[2*l];
126     
127     for (j=0;j<2*l;j++) h[j]=v[j]=0.0;
128     for (k=-w;k<w;k++) for (j=0;j<2*l;j++) h[j]+=fromImg(f.getData()[f.getOffset()+x0-l+j+(y0+k)*f.getScansize()]);
129     for (k=0;k<2*l;k++) for (j=-w;j<w;j++) v[k]+=fromImg(f.getData()[f.getOffset()+x0+j+(y0-l+k)*f.getScansize()]);
130     
131     FFT(h,v,1);
132     for (j=0;j<=l;j++) {
133         if (j==0) k=0; else k=2*l-j;
134         /* f */
135         frp=h[j]; fip=v[j]; frm=h[k]; fim=v[k];
136         /* h, v = 0 */
137         h[j]=v[j]=h[k]=v[k]=0.0;
138         /* h */
139         tr=(frp+frm)/2.0; ti=(fip-fim)/2.0;
140         /* h^2 */
141         t=Math.pow(tr,2)-Math.pow(ti,2); ti=2.0*tr*ti; tr=t;
142         /* sums h^2 */
143         h[j]+=tr; v[j]+=ti;
144         h[k]+=tr; v[k]+=-ti;
145         /* v */
146         tr=(fip+fim)/2.0; ti=-(frp-frm)/2.0;
147         /* v^2 */
148         t=Math.pow(tr,2)-Math.pow(ti,2); ti=2.0*tr*ti; tr=t;
149         /* sums v^2 */
150         h[j]+=-ti; v[j]+=tr;
151         h[k]+=ti; v[k]+=tr;
152     }
153     FFT(h,v,-1);
154     
155     tx=h[0];ty=v[0];mx=my=0;
156     for (j=0;j<2*l;j++) {
157         if (h[j]>tx) { tx=h[j]; mx=j; }
158         if (v[j]>ty) { ty=v[j]; my=j; }
159     }
160     
161     if (mx>=l) mx-=2*l;
162     if (my>=l) my-=2*l;
163     return new Point2D.Double(mx/2.0+x0,my/2.0+y0);
164     
165     }
166
167
168     private double findJNIZ(Image f,int x0,int y0,int l,int w,int n,double []templ) {
169     int j,k;
170     double msd[],s[],mv,c1,c2;
171     int mp;
172     s=new double[l];
173     for (j=0;j<l;j++) s[j]=0.0;
174     for (k=-w;k<w;k++) for (j=0;j<l;j++)
175         s[j]+=
176         fromImg(f.getData()[f.getOffset()+x0+j+(y0+k)*f.getScansize()])+
177         fromImg(f.getData()[f.getOffset()+x0-j+(y0+k)*f.getScansize()])+
178         fromImg(f.getData()[f.getOffset()+x0+k+(y0+j)*f.getScansize()])+
179         fromImg(f.getData()[f.getOffset()+x0+k+(y0-j)*f.getScansize()]);
180     mv=0.0;
181     for (j=0;j<l;j++) mv+=s[j];
182     for (j=0;j<l;j++) s[j]/=mv;
183     msd=new double[n];
184     for (k=0;k<n;k++) {
185         msd[k]=0.0;
186         for (j=0;j<l;j++) msd[k]+=Math.pow(templ[k*l+j]-s[j],2);
187     }
188     mv=msd[4];mp=4;
189     for (k=0;k<n;k++) if (msd[k]<mv) {mv=msd[k];mp=k;}
190     if (mp==0) mp=1;
191     if (mp==n-1) mp=n-2;
192     c1 = (msd[mp+1]-msd[mp-1])/2.0;
193     c2 = msd[mp+1]+msd[mp-1]-2.0*msd[mp];
194     return mp-c1/c2;
195     }
196
197     void addJNIToTemplate(Image f,int x0,int y0,int l,int w,double []templ,int z) {
198     int j,k;
199     double s[],mv;
200     s=new double[l];
201     for (j=0;j<l;j++) s[j]=0.0;
202     for (k=-w;k<w;k++) for (j=0;j<l;j++)
203         s[j]+=
204         fromImg(f.getData()[f.getOffset()+x0+j+(y0+k)*f.getScansize()])+
205         fromImg(f.getData()[f.getOffset()+x0-j+(y0+k)*f.getScansize()])+
206         fromImg(f.getData()[f.getOffset()+x0+k+(y0+j)*f.getScansize()])+
207         fromImg(f.getData()[f.getOffset()+x0+k+(y0-j)*f.getScansize()]);
208     mv=0.0;
209     for (j=0;j<l;j++) mv+=s[j];
210     for (j=0;j<l;j++) s[j]/=mv;
211     for (j=0;j<l;j++) templ[j+l*z]+=s[j];
212     }
213
214
215
216
217     /** Let the cross find the best center of the bead that is pointing
218 */
/* * @param ph the PixelHandler to access the frame
219      */

220     public synchronized void findXY(Image f) {
221     if (dragging) return;
222     setLocation(findJNIXY(f,intPosition.x,intPosition.y,crossL,crossHW));
223     }
224     
225
226     /** Find the best position of the bead along the vertical axis
227 */
/* * @param ph the PixelHandler to access the frame
228      */

229     public void findZ(Image f) {
230     if (calibrating || dragging || calibration==null) return;
231     z=findJNIZ(f,
232            intPosition.x,intPosition.y,
233            crossL,crossHW,
234            zNum,calibration
235            )*(maxZ-minZ)/zNum+minZ;
236     component.setValue(z);
237     }
238
239  
240     /** call this when the mouse starts dragging the cross
241      * @param v is dragged - don't move automatically, even if findXY is called
242      */

243     public synchronized void setDragging(boolean v) {
244     dragging = v;
245     }
246
247
248     /** the cross is being dragged by the mouse?
249      * @return the cross is being dragged by the mouse?
250      */

251     public boolean isDragging() {
252     return dragging;
253     }
254
255
256     /** set the bounding box of the whole image. Ensures that the cross doesn't exit from the image.
257      * @param r the bounding box
258      */

259     public void setBBox(Rectangle r) {
260     bbox=r;
261     }
262
263
264     /** set the position of the cross.
265      * @param p the new position
266      */

267     public void setLocation(Point2D p) {
268     Point ip = new Point((int)p.getX(),(int)p.getY());
269     if (!bbox.contains(getBounds(ip))) return;
270     position.setLocation(p);
271     translate(-intPosition.x+ip.x,-intPosition.y+ip.y);
272     intPosition.setLocation(ip);
273     }
274
275
276     /** get the position of the bead
277      * @return the position
278      */

279     public Point2D getLocation() {
280     Point2D r = new Point2D.Double();
281     r.setLocation(position);
282     return r;
283     }
284
285     /** get the position of the bead along Z axis
286      * @return the position
287      */

288     public double getZ() {
289     return z;
290     }
291  
292
293     private Rectangle getBounds(Point p) {
294     return new Rectangle(p.x-crossL,p.y-crossL,2*crossL,2*crossL);
295     }
296
297
298     /** get the bounds of the cross.
299      * @return the bounds of the cross
300      */

301     public Rectangle getBounds() {
302     return getBounds(intPosition);
303     }
304
305
306     /** get the color of the cross.
307      * @return the color of the cross
308      */

309     public Color getColor() {
310     return color;
311     }
312
313
314     private CComponent component = new CComponent();
315     private class CComponent extends JPanel implements ChangeListener {
316     JPointer sliderZero = new JPointer(JPointer.SLIDER_SIMPLE_STOP);
317     JPointer sliderFound = new JPointer(JPointer.SLIDER_SIMPLE_QUADRANGLE);
318     JSliderPlus sliderHolder = new JSliderPlus(JSliderPlus.VERTICAL,0.0,100.0);
319     JLabel calibrImg = new JLabel();
320     public CComponent() {
321         add(calibrImg);
322         sliderZero.setColor(Color.MAGENTA);
323         sliderFound.setColor(Color.CYAN);
324         sliderHolder.addJPointer(sliderZero);
325         sliderHolder.addJPointer(sliderFound);
326         add(sliderHolder);
327         sliderZero.setEnabled(false);
328         sliderFound.setEnabled(false);
329     }
330     public void setValue(double p) {
331         sliderFound.setValue(p);
332     }
333     public void setMinMax(double a,double b) {
334         sliderHolder.setLimits(a,b);
335         if (Math.abs(b-a)<5.0) {
336         sliderHolder.setMinorTickSpacing(0.5);
337         sliderHolder.setMajorTickSpacing(1.0);
338         }
339         else {
340         sliderHolder.setMinorTickSpacing(5.0);
341         sliderHolder.setMajorTickSpacing(10.0);
342         }
343     }
344     public void stateChanged(ChangeEvent e) {
345         double p=((PositionControl)e.getSource()).getPosition();
346         sliderZero.setValue(p);
347     }
348     public void updateCalibrationImageLabel() {
349         java.awt.Image JavaDoc img=calibrImg.createImage(createCalibrationImage());
350         calibrImg.setIcon(new ImageIcon(img));
351     }
352     }
353     /** get a Component that describes the Z position of the cross.
354      * It is also a ChangeListener, that can be added to a Spinner,
355      * and listens to the z-movements of the objective
356      * @return the Component
357      */

358     public Component getControlComponent() {
359     return component;
360     }
361
362     // ---------------------------
363
// Calibration
364

365     private double [] calibration = null;
366     private boolean calibrating = true;
367     private int zNum,zLevel=-1;
368     private double minZ,maxZ;
369
370     /** Start the calibration
371      * @param zNum number of position of the microscope objective
372      * @param minZ minimum position of the microscope objective
373      * @param maxZ maximum position of the microscope objective
374      */

375     public void calibrationStart(int zNum, double minZ, double maxZ) {
376     calibrating = true;
377     this.zNum=zNum;
378     this.minZ=minZ;
379     this.maxZ=maxZ;
380     zLevel=-1;
381     calibration = new double[zNum*crossL];
382     component.setMinMax(minZ,maxZ);
383     }
384
385     /** send the image that has been acquired, so that it is used for
386      * calibration
387      * @param f the image from which data must be obtained
388      */

389     synchronized public void calibrationSendImage(Image f) {
390     if (zLevel<0 || zLevel>=zNum) return;
391     addJNIToTemplate(f,
392              intPosition.x,intPosition.y,
393              crossL,crossHW,
394              calibration,zLevel);
395     zLevel=-1;
396     notify();
397     }
398
399     
400     /** Call this when the microscope objective position is right
401      * for the calibration. This method returns immediately; to wait for the
402      * processing to be done, call calibrationWait()
403      * @param zLevel position in the calibration image. Evaluate
404      * zNum = how many levels are in the calibration image?
405      * minZ, maxZ = the min and max levels (in micron)
406      * z = where is now the objective?
407      * So zLevel = (z-minZ)*zNum/(maxZ/minZ)
408      *
409      */

410     synchronized public void calibrationRequest(int zLevel) {
411     this.zLevel = zLevel;
412     }
413
414
415     /** wait that the calibration, requested by calibrationRequest(), has been
416      * completed.
417      */

418     synchronized public void calibrationWait() {
419     while (zLevel>=0) {
420         try { wait(); } catch (InterruptedException JavaDoc e) {}
421     }
422     }
423
424
425     /** call this when the calibration has been done
426      */

427     public void calibrationEnd() {
428     double s;
429     for (int j=0;j<zNum;j++) {
430         s=0.0;
431         for (int k=0;k<crossL;k++) s+=calibration[j*crossL+k];
432         for (int k=0;k<crossL;k++) calibration[j*crossL+k]/=s;
433     }
434     calibrating=false;
435     component.updateCalibrationImageLabel();
436     }
437
438     private ImageProducer createCalibrationImage() {
439     int width=crossL;
440     int height=zNum;
441     byte [] ima = new byte[width*height];
442     for (int j=0;j<width;j++) for (int k=0;k<height;k++)
443         ima[j+k*width]=(byte)(int)(calibration[j+(height-1-k)*width]*crossL*128.0);
444     byte [] reds = new byte[256];
445     byte [] greens = new byte[256];
446     byte [] blues = new byte[256];
447     for (int j=0;j<256;j++) { reds[j]=greens[j]=blues[j]=(byte)j; }
448     ColorModel icm = new IndexColorModel(8,256,reds,greens,blues);
449     ImageProducer imgsrc=new MemoryImageSource(width,height,icm,ima,0,width);
450     return imgsrc;
451     }
452
453 }
454
Popular Tags