Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
software:micro-manager [2018/04/06 18:01] Jon Daniels [Scripting the plugin] |
software:micro-manager [2024/05/21 23:52] (current) Jon Daniels [Runnables in the plugin] |
||
---|---|---|---|
Line 3: | Line 3: | ||
There is a Micro-manager plugin to control the diSPIM. | There is a Micro-manager plugin to control the diSPIM. | ||
- | Details about the plugin operation can be found in the manual section of this website in the section | + | Details about the plugin operation can be found in the manual section of this website in the [[:docs:mm_dispim_plugin_user_guide|Micro-manager diSPIM Plugin |
- | Currently the diSPIM plugin is supported in 1.4.x only, although | + | Currently the diSPIM plugin is supported in 1.4.x only. In 2023 there have been efforts to create a new plugin in Micro-Manager |
- | You can download the nightly builds of Micro-manager 1.4 for Windows [[http://valelab4.ucsf.edu/~MM/ | + | You can download the nightly builds of Micro-manager 1.4 for Windows [[https://download.micro-manager.org/nightly/ |
+ | |||
+ | |||
+ | ==== Changelog === | ||
+ | |||
+ | For convenience the change log at https:// | ||
+ | |||
+ | * 20190306: added overview acquisition feature to show 2D slice of large sample | ||
+ | * 20180928: added path-specific presets | ||
+ | * 20180222: added XYZ grid creator, useful for large tiled datasets | ||
+ | * 20171031: added reflective imaging option | ||
+ | * 20170217: can use light sheet mode on supported cameras | ||
+ | * 20170208: new camera tab, allows setting ROI numerically or with buttons | ||
+ | * 20170112: allow remote access via Java RMI for automated microscopy | ||
+ | * 20161222: plugin can deskew stage scan data | ||
+ | * 20160701: oSPIM support (need to build JAR with flag set) | ||
+ | * 20151218: added API calls to control acquisition programmatically | ||
+ | * 20151125: added ImageJ toolset for common image manipulation tasks | ||
+ | * 20151124: ability to run test acquisition with optionally exported raw file | ||
+ | * 20151013: added API calls to change acquisition settings programmatically | ||
+ | * 20150925: significantly expanded autofocus options | ||
+ | * 20150819: buttons to raise/lower SPIM head and sync upper and lower Z axes | ||
+ | * (1.4.22 release) | ||
+ | * 20150811: autofocus during timelapse | ||
+ | * 20150807: rapid-fire (hardware-timed) acquisition | ||
+ | * (1.4.21 release) | ||
+ | * 20150428: autofocus to define calibration (not yet during timelapse) | ||
+ | * 20150415: added basic stage scanning (contact ASI for firmware if needed) | ||
+ | * 20150225: added hardware switching for multi-channel using Tiger' | ||
+ | * 20150113: added multi-position support and software-based multi-channel support | ||
+ | * (1.4.20 release) | ||
+ | * 20141219: added ability to easily do offset-only calibration adjustment | ||
+ | * 20141215: improved slice timing calculations including speeding up optimized easy timing slice period by 0.25 ms | ||
+ | * 20141209: added colored status indicators for "quick glance" | ||
+ | * 20141207: added ability to export data for Fiji Multiview plugin (as of April 2015 the Fiji plugin can directly import data without requiring this step) | ||
+ | * (1.4.19 release) | ||
+ | * first included with 1.4.16 release Jan 2014 | ||
+ | |||
+ | |||
+ | You can view all changes to the diSPIM plugin code by [[https:// | ||
Line 13: | Line 52: | ||
- | ^ Problem | + | ^ Problem |
- | | Stage scanning cameras not getting triggered | + | | Stage scanning cameras not getting triggered |
- | | Dropped frames during acquisition | + | | Dropped frames during acquisition |
- | | Dropped frames during acquisition | + | | Dropped frames during acquisition |
- | | Acquisition fails (“Camera did not send the first image within a reasonable time" | + | | Acquisition fails (“Camera did not send the first image within a reasonable time" |
- | | Error on running plugin " | + | | Error on running plugin " |
- | | Error " | + | | Error " |
+ | | | ||
Line 26: | Line 66: | ||
The first step is to check and see if your problem has already been fixed by using a recent nightly build of Micro-Manager ([[http:// | The first step is to check and see if your problem has already been fixed by using a recent nightly build of Micro-Manager ([[http:// | ||
- | If the bug still happens, is helpful to generate a problem report using " | + | If the bug still happens, is helpful to generate a problem report using " |
+ | |||
+ | If you cannot reproduce the problem in order to generate a bug report, then an alternative is to enable debug logging in " | ||
You can see recent changes to the plugin code by [[https:// | You can see recent changes to the plugin code by [[https:// | ||
Line 32: | Line 74: | ||
==== Launching the plugin on startup ==== | ==== Launching the plugin on startup ==== | ||
- | Add the following lines to your MMStartup.bsh script (or create the file if it doesn' | + | Add the following lines to your MMStartup.bsh script (or create the file if it doesn' |
- | < | + | < |
import org.micromanager.asidispim.ASIdiSPIM; | import org.micromanager.asidispim.ASIdiSPIM; | ||
- | ASIdiSPIM plugin = new ASIdiSPIM(); | + | import org.micromanager.asidispim.Utils.MyDialogUtils; |
- | plugin.setApp(gui); | + | |
+ | // the if statement and closing brace can be removed if you want the plugin to always load regardless | ||
+ | if (MyDialogUtils.getConfirmDialogResult(" | ||
+ | | ||
+ | plugin.setApp(gui); | ||
+ | } | ||
</ | </ | ||
==== Scripting the plugin ==== | ==== Scripting the plugin ==== | ||
- | The Micro-Manager plugin has an API that allows most of its functionality to be accessed via Beanshell scripts run from within Micro-Manager. | + | The Micro-Manager plugin has an API that allows most of its functionality to be accessed via Beanshell scripts run from within Micro-Manager. |
Here is a bare-bones example script: | Here is a bare-bones example script: | ||
- | < | + | < |
// required imports | // required imports | ||
import org.micromanager.asidispim.api.ASIdiSPIMInterface; | import org.micromanager.asidispim.api.ASIdiSPIMInterface; | ||
Line 63: | Line 110: | ||
Here are some example scripts: | Here are some example scripts: | ||
- | < | + | < |
// This script changes channels in the middle of a multi-timepoint acquistion. | // This script changes channels in the middle of a multi-timepoint acquistion. | ||
Line 108: | Line 155: | ||
- | < | + | < |
// This script runs a multi-timepoint acquisition at multiple positions, collecting all time points at a single position | // This script runs a multi-timepoint acquisition at multiple positions, collecting all time points at a single position | ||
// before moving to the next position (reversing the time/ | // before moving to the next position (reversing the time/ | ||
Line 150: | Line 197: | ||
</ | </ | ||
+ | |||
+ | <code java> | ||
+ | // This script runs a " | ||
+ | // in a separate acquisition on disk. | ||
+ | |||
+ | // required imports | ||
+ | import org.micromanager.asidispim.api.*; | ||
+ | import org.micromanager.api.PositionList; | ||
+ | import org.micromanager.api.MultiStagePosition; | ||
+ | import org.micromanager.asidispim.utils.MyDialogUtils; | ||
+ | import java.text.DecimalFormat; | ||
+ | |||
+ | // get reference to plugin (requires plugin to be open) | ||
+ | ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | ||
+ | |||
+ | // get MM's position list (should have positions set there already before running script) | ||
+ | PositionList pl = gui.getPositionList(); | ||
+ | int numPositions = pl.getNumberOfPositions(); | ||
+ | |||
+ | // make sure plugin is set _not_ to use positions after caching old value | ||
+ | boolean multiXY = diSPIM.getMultiplePositionsEnabled(); | ||
+ | diSPIM.setMultiplePositionsEnabled(false); | ||
+ | |||
+ | // get value of post-move delay from plugin | ||
+ | double postMoveDelayMs = diSPIM.getMultiplePositionsDelay(); | ||
+ | |||
+ | // save original name prefix for file saving | ||
+ | String basePrefix = diSPIM.getSavingNamePrefix(); | ||
+ | |||
+ | // set up formatting with leading 0s | ||
+ | DecimalFormat df = new DecimalFormat(" | ||
+ | |||
+ | // setup for closing finished acquisition windows | ||
+ | // instead of leaving every window open want to close when done | ||
+ | // found that call to closeAcquisitionWindow() can come before writing is finished and cause problems | ||
+ | // so let there be 2 open windows but prevent opening more | ||
+ | String lastAcqName = ""; | ||
+ | String lastLastAcqName = ""; | ||
+ | |||
+ | |||
+ | // loop over all positions in position list | ||
+ | try { | ||
+ | for(int i=1; i< | ||
+ | MultiStagePosition.goToPosition(pl.getPosition(i-1), | ||
+ | Thread.sleep(Math.round(postMoveDelayMs)); | ||
+ | diSPIM.setSavingNamePrefix(basePrefix + " | ||
+ | try { | ||
+ | diSPIM.closeAcquisitionWindow(lastLastAcqName); | ||
+ | } catch (Exception ex) { | ||
+ | // do nothing | ||
+ | } | ||
+ | diSPIM.runAcquisitionBlocking() | ||
+ | lastLastAcqName = lastAcqName; | ||
+ | lastAcqName = diSPIM.getLastAcquisitionName(); | ||
+ | } | ||
+ | } catch (Exception ex) { | ||
+ | MyDialogUtils.showError(ex, | ||
+ | } finally { | ||
+ | // restore prefix and multi-XY value | ||
+ | diSPIM.setSavingNamePrefix(basePrefix); | ||
+ | diSPIM.setMultiplePositionsEnabled(multiXY); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | <code java> | ||
+ | |||
+ | // This script runs a " | ||
+ | // to save each position in a separate file on disk. | ||
+ | // Positions are the "outer loop", channels are the "inner loop" | ||
+ | // Channels are not necessarily in the order specified in the plugin but should be the same order every time. | ||
+ | // User should put the plugin " | ||
+ | |||
+ | |||
+ | // required imports | ||
+ | import org.micromanager.asidispim.api.*; | ||
+ | import org.micromanager.api.PositionList; | ||
+ | import org.micromanager.api.MultiStagePosition; | ||
+ | import org.micromanager.asidispim.utils.MyDialogUtils; | ||
+ | import java.text.DecimalFormat; | ||
+ | |||
+ | // get reference to plugin (requires plugin to be open) | ||
+ | ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | ||
+ | |||
+ | // get MM's position list (should have positions set there already before running script) | ||
+ | PositionList pl = gui.getPositionList(); | ||
+ | int numPositions = pl.getNumberOfPositions(); | ||
+ | |||
+ | // make sure plugin is set _not_ to use positions after caching old value | ||
+ | boolean multiXY = diSPIM.getMultiplePositionsEnabled(); | ||
+ | diSPIM.setMultiplePositionsEnabled(false); | ||
+ | |||
+ | // get value of post-move delay from plugin | ||
+ | double postMoveDelayMs = diSPIM.getMultiplePositionsDelay(); | ||
+ | |||
+ | // save original name prefix for file saving | ||
+ | String basePrefix = diSPIM.getSavingNamePrefix(); | ||
+ | |||
+ | // set up formatting with leading 0s | ||
+ | DecimalFormat df = new DecimalFormat(" | ||
+ | |||
+ | // setup for closing finished acquisition windows | ||
+ | // instead of leaving every window open want to close when done | ||
+ | // found that call to closeAcquisitionWindow() can come before writing is finished and cause problems | ||
+ | // so let there be 2 open windows but prevent opening more | ||
+ | String lastAcqName = ""; | ||
+ | String lastLastAcqName = ""; | ||
+ | |||
+ | // figure out which channels we are using | ||
+ | boolean channelsEnabled = diSPIM.getChannelsEnabled(); | ||
+ | String [] allChannels = diSPIM.getAvailableChannels(); | ||
+ | |||
+ | try { | ||
+ | // loop over all positions in position list | ||
+ | for( int i=1; i< | ||
+ | MultiStagePosition.goToPosition(pl.getPosition(i-1), | ||
+ | Thread.sleep(Math.round(postMoveDelayMs)); | ||
+ | |||
+ | for( s : allChannels) { | ||
+ | if (!diSPIM.getChannelEnabled(s)) | ||
+ | continue; | ||
+ | diSPIM.setSavingNamePrefix(basePrefix + " | ||
+ | try { | ||
+ | diSPIM.closeAcquisitionWindow(lastLastAcqName); | ||
+ | } catch (Exception ex) { | ||
+ | // do nothing | ||
+ | } | ||
+ | diSPIM.runAcquisitionBlocking() | ||
+ | lastLastAcqName = lastAcqName; | ||
+ | lastAcqName = diSPIM.getLastAcquisitionName(); | ||
+ | } | ||
+ | } | ||
+ | } catch (Exception ex) { | ||
+ | MyDialogUtils.showError(ex, | ||
+ | } finally { | ||
+ | // restore prefix and multi-XY value | ||
+ | diSPIM.setSavingNamePrefix(basePrefix); | ||
+ | diSPIM.setMultiplePositionsEnabled(multiXY); | ||
+ | diSPIM.setChannelsEnabled(channelsEnabled); | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | ==== Runnables in the plugin ==== | ||
+ | |||
+ | Support for " | ||
+ | |||
+ | These runnables are normally defined in a Beanshell script executed from Micro-Manager' | ||
+ | |||
+ | Currently there are six times when runnables can be inserted: | ||
+ | - Start of acquisition | ||
+ | - End of acquisition | ||
+ | - Start of timepoint | ||
+ | - End of timepoint | ||
+ | - Start of position | ||
+ | - End of position | ||
+ | |||
+ | Note that these would be called only once each for an acquisition without timepoints nor positions selected. | ||
+ | |||
+ | Here is an example adding a runnable to each of these possible invocation points. | ||
+ | |||
+ | <code java> | ||
+ | // required imports | ||
+ | import org.micromanager.asidispim.api.*; | ||
+ | |||
+ | // get a reference to the plugin; use this to call the plugin' | ||
+ | // API documented in ASIdiSPIMInterface.java in source code | ||
+ | // | ||
+ | // note that the plugin must be launched for this to work | ||
+ | ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | ||
+ | int runnableTimepointCounter; | ||
+ | int runnablePositionCounter; | ||
+ | |||
+ | taskStartAcquisition = new Runnable() { | ||
+ | public void run() { | ||
+ | // test code which will raise dialog; should be replaced | ||
+ | gui.showError(" | ||
+ | runnableTimepointCounter = 0; | ||
+ | runnablePositionCounter = 0; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | taskEndAcquisition = new Runnable() { | ||
+ | public void run() { | ||
+ | // test code which will raise dialog; should be replaced | ||
+ | gui.showError(" | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | |||
+ | taskStartPosition = new Runnable() { | ||
+ | public void run() { | ||
+ | runnablePositionCounter++; | ||
+ | // test code which will raise dialog; should be replaced | ||
+ | gui.showError(" | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | taskEndPosition = new Runnable() { | ||
+ | int localCounter = 0; | ||
+ | public void run() { | ||
+ | localCounter++; | ||
+ | // test code which will raise dialog; should be replaced | ||
+ | gui.showError(" | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | taskStartTimepoint = new Runnable() { | ||
+ | public void run() { | ||
+ | runnablePositionCounter = 0; | ||
+ | runnableTimepointCounter++; | ||
+ | // test code which will raise dialog; should be replaced | ||
+ | gui.showError(" | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | taskEndTimepoint = new Runnable() { | ||
+ | int localCounter = 0; | ||
+ | public void run() { | ||
+ | localCounter++; | ||
+ | // test code which will raise dialog; should be replaced | ||
+ | gui.showError(" | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // add all run | ||
+ | diSPIM.clearAllRunnables(); | ||
+ | diSPIM.attachRunnable(taskStartAcquisition, | ||
+ | diSPIM.attachRunnable(taskEndAcquisition, | ||
+ | diSPIM.attachRunnable(taskStartPosition, | ||
+ | diSPIM.attachRunnable(taskEndPosition, | ||
+ | diSPIM.attachRunnable(taskStartTimepoint, | ||
+ | diSPIM.attachRunnable(taskEndTimepoint, | ||
+ | |||
+ | </ | ||
+ | |||
+ | |||
+ | Here is another example that runs autofocus periodically, | ||
+ | |||
+ | < | ||
+ | |||
+ | // runs autofocus once on the first position and periodically afterwards based on period set in script (currently every 13th position) | ||
+ | // script assumes that CRISP is already set up and is the default focus device | ||
+ | // run this script after launching the plugin and before beginning the acquisition | ||
+ | |||
+ | // required imports | ||
+ | import org.micromanager.asidispim.api.*; | ||
+ | |||
+ | // get a reference to the plugin; use this to call the plugins API methods | ||
+ | ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | ||
+ | |||
+ | // local variables | ||
+ | int runnablePositionCounter; | ||
+ | int counterPeriod = 13; | ||
+ | |||
+ | // initialize the counter when the acquisition begins | ||
+ | taskStartAcquisition = new Runnable() { | ||
+ | public void run() { | ||
+ | runnablePositionCounter = 0; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | // at each position see if it's time to run autofocus, plus also increment the counter | ||
+ | taskStartPosition = new Runnable() { | ||
+ | public void run() { | ||
+ | // | ||
+ | if ((runnablePositionCounter % counterPeriod)< | ||
+ | mmc.fullFocus(); | ||
+ | } | ||
+ | runnablePositionCounter++; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | |||
+ | // add the runnables to the diSPIM plugin' | ||
+ | diSPIM.clearAllRunnables(); | ||
+ | diSPIM.attachRunnable(taskStartAcquisition, | ||
+ | diSPIM.attachRunnable(taskStartPosition, | ||
+ | |||
+ | |||
+ | </ | ||
/* | /* |