Close

Does this project spark your interest?

Become a member to follow this project and don't miss any updates

Stagmo: Microscope Stage Automator

A low-cost microscope stage automation solution that enables large scale image montages with relative ease.

Similar projects worth following
This project is submitted for

This project was created on 07/11/2014 and last updated 2 months ago.

Description
In microscopy, the field of view is limited and depends on the objective magnification. With growing applications of microscopic imaging and spatial analysis, digitally capturing large montages of a sample is often required. Automated microscope stages facilitate the production of accurate montages of a given sample. Unfortunately, the cost of entry level automated microscope stages (>$10,000) is prohibitive to many researchers. This project provides an alternative to consumer options at relatively low cost (<$100) and utilizes existing open source software solutions. The microscope stage automator – Stagmo – presented in this project can be non-invasively attached to existing (and widely used) microscopes.

Details

The microscope used in this project is an Olympus Bx40 with a third-party digital camera. Stagmo, is secured to the existing microscope stage, and stepper motors are utilized to control the existing manual stage control knobs. Stagmo does not require any modification of existing microscope systems, but "straps" on and hijacks existing controls. This makes Stagmo ideal for traveling researchers or graduate students who are using other facilities equipment. A simple button interface is used to input the dimensions of the microscopic sample into an Arduino. Stagmo utilizes input dimensions to precisely move the microscope stage every few seconds, and triggers the camera controller on the computer capture an image of the current microscope field and output the image to a specified directory. The path, rows and columns utilized by Stagmo to capture the image are output with the image file into imageJ. The image stitching plug-in by Stephan Preibisch (http://fly.mpi-cbg.de/~preibisch/software.html#Stitching ) is used to assemble the images in the directory into a montage. Since the precise location of each image is specified by Stagmo, this process is minimizes the computation load required to produce large montages. 

This project was utilized to create cross-sectional  montages of over 200 rib samples (@ 100x)  (requiring 15 - 40 fields) and 100 femur samples (@ 100x) (requiring upwards of 600 fields). Use of the automated system improved efficiency by roughly 600%. 

The current version of Stagmo can be greatly enhanced with greater user control (integrated microscope calibration for changing objectives on the fly), improved user interface with a simple lcd to provide the current parameters and estimated time to completion, improved digital camera integration, and an improved chassis/ hardware microscope integration.

Components
  • 1 × arduino
  • 1 × motorshield
  • 2 × stepper motors
  • 4 × buttons
  • 1 × switch Development Kits, Boards and Systems / Development Kits and Boards
  • 1 × assorted resistors
  • 2 × pulley
  • 2 × bands
  • 1 × Custom bracket
  • 1 × Duct Tape

See all components

Project logs
  • Arduino Code

    3 months ago • 0 comments

    //parts of this code have been scavenged from code created by: Michael Pilcher
    
    #include <AFMotor.h>
    //manually calibrate your stage to find the values of xmove and y move for each objective you will be using
    int xmove = 12;//[12 (100x)  30 (40x)  dp72] 
    int ymove = 5;//[5  (100x)  13 (40x) dp72]
    int xrpm = 150;
    int yrpm = 150;
    int j = 1; // integer used in scanning the array designating column number
    //2-dimensional array for assigning the buttons and there high and low values
    int Button[9][3] = {{1, 705, 715}, // button 1
                         {2, 735, 745}, // button 1b
                         {3, 830, 840}, // button 2
                         {4, 845, 860}, // button 2b
                         {5, 600, 620}, // button 3
                         {6, 640, 670}, // button 3b
                         {7, 300, 320}, // button 4
                         {8, 445, 460}, // button 4b
                         {9, 260, 265}, // button b
    };
    int analogpin = 0; // analog pin to read the buttons
    int label = 0;  // setting button mode
    int counter = 0; // how many times we have seen new value
    long time = 0;  // the last time the output pin was sampled
    int debounce_count = 50; // number of millis/samples to consider before declaring a debounced input
    int current_state = 0;  // the debounced input value
    int ButtonVal;
    int column=8;
    int row=50;
    int row_count;
    int column_count;
    double movement;
    int pause = 2800;
    int frames=0;
    int count = 0;
    AF_Stepper motor1(100, 1);
    AF_Stepper motor2(100, 2);
    
    void setup()
    {
      Serial.begin(9600);
      motor1.setSpeed(yrpm);  
       motor2.setSpeed(xrpm);  
    }
    
    void loop()
    {
       // If we have gone on to the next millisecond
      if (millis() != time)
      {
        // check analog pin for the button value and save it to ButtonVal
        ButtonVal = analogRead(analogpin);
        if(ButtonVal == current_state && counter >0)
        {
          counter--;
        }
        if(ButtonVal != current_state)
        {
          counter++;
        }
        // If ButtonVal has shown the same value for long enough let's switch it
        if (counter >= debounce_count)
        {
          counter = 0;
          current_state = ButtonVal;
          //Checks which button or button combo has been pressed
          if (ButtonVal > 0)
          {
            ButtonCheck();
          }
        }
        time = millis();
      }
    }
    
    void ButtonCheck()
    {
      // loop for scanning the button array.
      for(int i = 0; i <= 21; i++)
      {
        // checks the ButtonVal against the high and low vales in the array
        if(ButtonVal >= Button[i][j] && ButtonVal <= Button[i][j+1])
        {
          // stores the button number to a variable
          label = Button[i][0];
          Action();      
        }
      }
    }
    
    void Action()
    {
      if(label == 1)
      {
        Serial.println("Button 1");//Y Coordinate down
        motor1.step(xmove, FORWARD, DOUBLE);  
      }
      if(label == 2)
      {
        Serial.println("Column =");
        column++;
        Serial.println(column);
    }
      if(label == 3)
      {
        Serial.println("Button 2"); //Y Coordinate up
        motor1.step(xmove, BACKWARD, DOUBLE);   
    }
      if(label == 4)
      {
        Serial.println("Initiated");
    
       row_count=1;
       movement=1;
       column_count=1;
       frames= row * column;
       while(count<= frames){
          if( movement==1){
           while(column_count <= column){
            motor1.step(xmove, FORWARD, DOUBLE); 
                Serial.println(column_count);
                Serial.println(movement);
            delay(pause);
            count++;
            column_count++;
           }
          }
           if( movement!= 1){
           while(column_count >= 1){
              motor1.step(xmove, BACKWARD, DOUBLE); 
              Serial.println(column_count);
              Serial.println(movement);
              delay(pause);
              count++;
              column_count--;
             }
           }
          if (column_count==column+1){
              if(movement == 1){
              motor2.step(ymove, BACKWARD, DOUBLE); 
                  Serial.println(column_count);
                  Serial.println(movement);
              delay(pause);
              count++;
              column_count = column;
              movement = movement * (-1);
              row_count++;
              
               motor1.step(xmove-2, BACKWARD, DOUBLE); 
              Serial.println(column_count);
              Serial.println(movement);
              delay(pause);
              count++;
              column_count--; 
              }
          }
          if (column_count == 0){
              if(movement ==- 1){
                     motor2.step(ymove, BACKWARD,  DOUBLE); 
                         Serial.println(column_count);
                         Serial.println(movement);
                     delay(pause);
                     count++;
                     column_count =1 ;
                     row_count++;
                     movement=1;
            }
          }
        }
      }
      if(label == 5)
      {
        Serial.println("Button 3");  //x coordinate to the left
        motor2.step(ymove, FORWARD, DOUBLE); 
      }
      if(label == 6)
      {
        Serial.println("Row =");
        row++;
        Serial.println(row);
    ...
    Read more »

  • Example Montage and Status

    3 months ago • 0 comments

    Thanks for all the interest, and I apologize for the lack of updates and responses over the last year (my dissertation research got in the way). I neglected to document Stagmo as much as I should have during my graduate research, but I have uploaded an example montage (undecalficied human midshaft femur thick-section – 100~µm thick). The size of this montage was greatly reduced for internet viewing and is made up of 180 individual fields. This demonstrates the ability and weaknesses of Stagmo coupled with an imageJ stitching plugin. The software end is highly sensitive to "blank" fields, so fields with minimal features are more likely to be misaligned (as seen the medullary cavity). Since these fields typically do not have features of interest, this wasnt a big deal for my research and could be fixed in photoediting software using the raw images after stitching for the small number of montages that were problematic.

    Stagmo is currently on hold, but I am happy to revive and update this project with interested individuals. There are a number of improvements that can easily be made. The first edition was significantly hindered by limited tools and materials. Future updates could include a significantly improved UI, computer triggering and interface, and the addition of automated focus control (using a simple plane capturing method). Since stagmo is design to attach to existing stages (which are typically precisely machined and expensive), the general concept should not be restricted to any specific microscope. 3D printed hubs coupled with standard hardware could provide a range of automated options to low budget researchers.

View all 2 project logs

Discussions

andyhull wrote 11 months ago point
I've been giving this idea some thought, and if I get the chance, I might try a polar co-ordinate approach. By this I mean, make a three servo controlled platform that sits on the existing stage and rotates, shifts and lifts the slide.

I suspect this will take less effort than motorising the existing stage (I am probably wrong in this assumption).

The work flow would be something like... place slide on (clear acrylic?) block controlled by servos, one for rotation (θ), one for horizontal linear movement (h), one for vertical movement (z).

Focus manually on specimen, trigger computer to take a sequence of images by scanning using a polar co-ordinate location algorithm. Lift or lower for change of focal plane with z axis servo...

This would be similar to the method used by this printer.. http://hackaday.com/2014/08/28/thp-semifinalist-theta-printer/

Any thoughts, on the subject, such as ...don't be so daft, it wont work because... would be welcome.

Are you sure? [yes] / [no]

Mike Smith wrote a year ago point
Hi, I'm based in Kampala, Uganda and am working on automated image analysis (via a microscope and a smart phone). One issue is somehow getting the microscope to focus etc. An MSc student here built some hardware to do this http://aidevmakerere.blogspot.com/2013/03/microscope-autofocus.html . One issue is that we are trying to get the costs down. The clinics have microscopes (but rarely have trained lab-techs), which is why the device might be useful, but the reliability and cost of the autofocus/translation motorisation will probably be prohibitive... (even at $100/clinic). Currently we're thinking of the app telling someone what to do (e.g. turn focus knob clockwise, etc!). This part of the project's not been developed yet, so I'm just looking for ideas.
see the blog for more details about the project: http://aidevmakerere.blogspot.com/search/label/Ocula

Are you sure? [yes] / [no]

Benchoff wrote a year ago point
Woah. Any chance of putting up some pictures of montages, or some video of it working?

Are you sure? [yes] / [no]

andyhull wrote a year ago point
Wow... the Olympus Bx40 is rather impressive microscope. You've set the bar pretty high, I doubt if my results will be quite as good, but that isn't going to stop me from trying... I presume as well as moving the stage, you have some form of automatic control of the focus, so you can stack in the z axis as well as stitch in the x and y axis.

Are you sure? [yes] / [no]

andyhull wrote a year ago point
You've beaten me to it on this project, I have a bunch of microscope stages "rescued" from a local skip... two of which have been resurrected for this exact purpose. I even have the servos and an arduino clone sitting ready to start the project. I'm just missing the magic "infinite amount of spare time" ingredient. best of luck with this... I'll be following along with interest.

Are you sure? [yes] / [no]

naroom wrote a year ago point
Hey, good to see more science projects in here!

You probably already know about this, but Labrigger is a blog you'd like: http://labrigger.com/blog/

Are you sure? [yes] / [no]

Jarred Heinrich wrote a year ago point
Thanks for the link! Looks like something that is right up my alley

Are you sure? [yes] / [no]

Similar projects