automating calibration in the HCS plugin

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

automating calibration in the HCS plugin

Rong

Hi everyone,

We are using the HCS plugin to collect data from 96 well plates with a Marzhauser stage in MM1.4 (Unfortunately, MM2 has a tendency to behave erratically with our hardware setup, its HCS plugin is more flexible).

The first step in using the plugin is to position the stage at the middle of well A1 and calibrate. Is there some way using the Startup group to send the stage to the same absolute position upon initiation of MM to automate this? Or has someone written a script to do something similar?

Also, is there a way to do the centering accurately? We use a 2x objective, but its always a guestimate of where exactly the center of the well is.

Thanks,

-Ron


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
micro-manager-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/micro-manager-general
Reply | Threaded
Open this post in threaded view
|

Re: automating calibration in the HCS plugin

m.losen

Dear Ron,

After starting MM, the stage uses the current (usually random) stage position as zero-coordinates.

But by using the “set-origin” function (in “Tools”, “XY list” / “stage position list”) the absolute coordinates can be found:  The stage then moves to the limit switches (of the Marzhauser stage, for example) to calibrate the coordinates.

If you could once determine the middle of well A1 accurately, this position can be marked (using “Mark” button in the “stage position list”) and saved (“save as…”). Next time you start up MM and start “set-origin”, it should be possible to reload the exact position (using the “Load…” button), and send the stage there again (“go to”).

You could write a script to do all that.

As an example, I copy below a beanshell script I wrote for 1.4 and a Marzhauser stage; it duplicates a few of the features of the HCS plugin.

It uses the standardized dimensions of various multiwell plates. If you could find the corner point of the plate on the stage, you can also calculate the center coordinates of well A1 accodingly.

Hope this helps,

Mario

 

 

 

import ij.*;

import ij.process.*;

import ij.IJ;

import ij.ImagePlus;

import ij.ImageWindow;

import ij.ImageCanvas;

import java.awt.Dimension;

import org.micromanager.navigation.PositionList;

import org.micromanager.navigation.MultiStagePosition;

 

xyStage = mmc.getXYStageDevice();

 

String[] wellStrings = {"6 well", "12 well", "24 well", "48 well", "96 well", "384 well", "1536 well"};

int[] Columns_X = {3, 4, 6, 8, 12, 24, 48};

int[] Rows_Y = {2, 3, 4, 6, 8, 16, 32};

double[] Diameter = {35580, 22780, 16280, 11950, 6960, 3700, 1700};

double[] Column_Offset_X = {24900, 24900, 15150, 18400, 14380, 12130, 11010};

double[] Row_Offset_Y = {23250, 16750, 13500, 10250, 11240, 8990, 7870};

double[] Pitch_XY = {39000, 26000, 19500, 13000, 9000, 4500, 2250};

double Length_X = 127800;

double Width_Y = 85500;

String[] Column_Label = {" 1", " 2", " 3", " 4", " 5", " 6", " 7", " 8", " 9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22",

 

"23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", "45", "46", "47", "48"};

String[] Row_Label = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "A2",

 

"B2", "C2", "D2", "E2", "F2", "G2", "H2", "I2", "J2", "K2", "L2", "M2", "N2", "O2", "P2", "Q2", "R2", "S2", "T2", "U2", "V2", "W2", "X2", "Y2", "Z2"};

double[] resolution = { 0.002, 0.004, 0.008, 0.016};

String[] resolutionStrings = { "2 pix/mm", "4 pix/mm", "8 pix/mm", "16 pix/mm"};

 

int wellindex = 4;

int resolutionindex = 2;

 

 

boolean selectionStageXmirror = true; // 'true' or 'false' is depending on orientation of the plate relative to the stage

boolean selectionStageYmirror = true;

double stageXmirror;   // will be set to "1" or "-1" depending of 'selectionStage x/Y mirror' variables

double stageYmirror;

double plateXoffset;   // Stage position of the upper left corner of the plate (near A1). Unit: µm

double plateYoffset;

double stageXpos;   // Position of the stage. Unit: µm

double stageYpos;

double plateXpos;   // Position realtive to the upper left corner of the plate. Unit: µm 

double plateYpos;

int cursorXpos;     // Pixel position on the image "wellmanager". Used for drawing elements and selections

int cursorYpos;

int mouseclickXpos; // Pixel position on the image "wellmanager". Used for keeping track of mouseclicks

int mouseclickYpos;

int CircelDiameter; // used for drawing "well"-circles in the the image "wellmanager"

 

public linkstage()

{

//calculate offset here:

plateXoffset = mmc.getXPosition(xyStage) - plateXpos * stageXmirror;

plateYoffset = mmc.getYPosition(xyStage) - plateYpos * stageYmirror;

PlateXfield.setText("set X");

PlateYfield.setText("set Y");

};

 

public drawplate()

{

//close previously opened Wellnavigator windows first:

wList = WindowManager.getIDList();

if (null == wList) {}

else

{for (i=0; i < wList.length; i++)

{if (WindowManager.getImage(wList[i]).getTitle() =="wellnavigator")

{IJ.selectWindow("wellnavigator");

IJ.run("Close");

}

}

}

 

Scalefactor = resolution[resolutionindex];

CircelDiameter = (int) (Diameter[wellindex] * Scalefactor);

Imageheight = (int) (Length_X * Scalefactor);

Imagewidth  = (int) (Width_Y  * Scalefactor);

 

IJ.newImage("wellnavigator", "RGB Black", Imageheight, Imagewidth, 1);

IJ.run("Colors...", "foreground=blue background=black selection=yellow");

wellnav_ip = IJ.getProcessor();

 

for (int i=0; i < Columns_X[wellindex]; i++)

{for (int j=0; j < Rows_Y[wellindex]; j++)

{

plateXpos=i*Pitch_XY[wellindex] + Column_Offset_X[wellindex];

plateYpos=j*Pitch_XY[wellindex] +    Row_Offset_Y[wellindex];

cursorXpos = (int) ((plateXpos-Diameter[wellindex]/2) * Scalefactor);

cursorYpos = (int) ((plateYpos-Diameter[wellindex]/2) * Scalefactor);

IJ.makeOval(cursorXpos, cursorYpos, CircelDiameter, CircelDiameter);

IJ.run("Fill", "slice");}

}

 

TextSize = (int) (1536*Scalefactor*1000/25/Columns_X[wellindex]);

if (TextSize>Scalefactor*4*1000) (TextSize = (int) (Scalefactor*4*1000));

wellnav_ip.setFont(new Font("Serif", Font.BOLD, TextSize));

 

for (int i=0; i < Columns_X[wellindex]; i++)

{

plateXpos = i*Pitch_XY[wellindex]+Column_Offset_X[wellindex];

cursorXpos = (int) (plateXpos * Scalefactor - TextSize/2);

label = Integer.toString(i+1);

wellnav_ip.drawString(Column_Label[i], cursorXpos, TextSize+ (int) (Scalefactor*1000));

};

 

for (int j=0; j < Rows_Y[wellindex]; j++)

{

plateYpos = j*Pitch_XY[wellindex]+Row_Offset_Y[wellindex];

cursorYpos = (int) (plateYpos*Scalefactor + TextSize/2);

wellnav_ip.drawString(Row_Label[j], (int) (Scalefactor*1000), cursorYpos);

};

IJ.run("Select None");

 

f = IJ.getImage().getWindow().getCanvas();

 

mousePressed( e )

{x = (int) e.getX();

y =  (int) e.getY();

mouseclickXpos = (int)f.offScreenX(x);

mouseclickYpos = (int)f.offScreenY(y);

 

if (cb3.getState()==false){stageXmirror = 1;} else {stageXmirror = -1;};

if (cb4.getState()==false){stageYmirror = 1;} else {stageYmirror = -1;};

 

if (cb1.getState()==true)

{

plateXpos =mouseclickXpos/Scalefactor;

plateYpos =mouseclickYpos/Scalefactor;

i= (int) Math.round((plateXpos - Column_Offset_X[wellindex] ) / Pitch_XY[wellindex]);

j= (int) Math.round((plateYpos -    Row_Offset_Y[wellindex] ) / Pitch_XY[wellindex]);

if (i> (int) Columns_X[wellindex]-1) {i = (int) Columns_X[wellindex]-1;};

if (j> (int)    Rows_Y[wellindex]-1) {j = (int)    Rows_Y[wellindex]-1;};

if (i<0) {i = 0;};

if (j<0) {j = 0;};

plateXpos = i*Pitch_XY[wellindex] + Column_Offset_X[wellindex];

plateYpos = j*Pitch_XY[wellindex] +    Row_Offset_Y[wellindex];

cursorXpos = (int) ((plateXpos-Diameter[wellindex]/2) * Scalefactor);

cursorYpos = (int) ((plateYpos-Diameter[wellindex]/2) * Scalefactor);

IJ.makeOval(cursorXpos, cursorYpos, CircelDiameter, CircelDiameter);

stageXpos = plateXoffset + stageXmirror*plateXpos;

stageYpos = plateYoffset + stageYmirror*plateYpos;

}

else

{IJ.makePoint(mouseclickXpos, mouseclickYpos);

plateXpos = mouseclickXpos/Scalefactor;

plateYpos = mouseclickYpos/Scalefactor;

stageXpos = plateXoffset + stageXmirror*plateXpos;

stageYpos = plateYoffset + stageYmirror*plateYpos;

}

PlateXfield.setText("x: "+String.valueOf(plateXpos)+" µm");

PlateYfield.setText("y: "+String.valueOf(plateYpos)+" µm");

if (cb2.getState()==true)

{mmc.setXYPosition(xyStage,stageXpos,stageYpos);

mmc.waitForDevice(xystage);}

 

}

 

mouseMoved( e ) { }

f.addMouseListener (this);}

 

drawplate();

JFrame WOptions= new JFrame();

JPanel p1= new JPanel();

JPanel p2= new JPanel();

JPanel p3= new JPanel();

JButton jb1= new JButton("Update plate!");

JButton jb2= new JButton("Current selection correponds to stage position!");

Checkbox cb1=new Checkbox("snap to well?",true);

Checkbox cb2=new Checkbox("activate stage?",false);

Checkbox cb3=new Checkbox("mirror X?",selectionStageXmirror);

Checkbox cb4=new Checkbox("mirror Y?",selectionStageYmirror);

JTextField PlateXfield=new JTextField("x: 0 µm", 10);

JTextField PlateYfield=new JTextField("y: 0 µm", 10);

 

JComboBox plateList = new JComboBox(wellStrings);

plateList.setSelectedIndex(wellindex);

plateList.addActionListener(this);

 

JComboBox zoomMenu = new JComboBox(resolutionStrings);

zoomMenu.setSelectedIndex(resolutionindex);

WOptions.setTitle("wellnavigator options");

WOptions.getContentPane().setLayout(new GridLayout(3,0));

p1.add(plateList);

p1.add(zoomMenu);

p1.add(jb1);

p1.add(cb1);

p2.add(PlateXfield);

p2.add(PlateYfield);

p2.add(cb2);

p3.add(cb3);

p3.add(cb4);

p3.add(jb2);

WOptions.getContentPane().add(p1);

WOptions.getContentPane().add(p2);

WOptions.getContentPane().add(p3);

WOptions.pack();

WOptions.setVisible(true);

 

jb1.addMouseListener(new MouseAdapter()

{ public void mousePressed(MouseEvent e)

{

wellindex = plateList.getSelectedIndex();

resolutionindex =zoomMenu.getSelectedIndex();

drawplate();}

} );

jb2.addMouseListener(new MouseAdapter()

{ public void mousePressed(MouseEvent e)

{linkstage();}

} );

 


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
micro-manager-general mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/micro-manager-general