Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision Next revision Both sides next revision | ||
software:micro-manager [2017/08/02 19:41] Jon Daniels [Troubleshooting] |
software:micro-manager [2022/06/20 21:41] Jon Daniels [Scripting the plugin] fixed link |
||
---|---|---|---|
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 there have been some efforts to port it to 2.0. At some point after the official release | + | Currently the diSPIM plugin is supported in 1.4.x only. There have been some efforts to port it to 2.0 but don't expect the 2.0 version to work even if you can find it. As of October 2021, initial conversations are happening around making a new plugin in Micro-manager 2.0 that will supersede |
You can download the nightly builds of Micro-manager 1.4 for Windows [[http:// | You can download the nightly builds of Micro-manager 1.4 for Windows [[http:// | ||
+ | |||
+ | |||
+ | ==== 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:// | ||
+ | |||
+ | ==== Launching the plugin on startup ==== | ||
+ | |||
+ | Add the following lines to your MMStartup.bsh script (or create the file if it doesn' | ||
+ | |||
+ | <code java> | ||
+ | import org.micromanager.asidispim.ASIdiSPIM; | ||
+ | import org.micromanager.asidispim.Utils.MyDialogUtils; | ||
+ | |||
+ | // the if statement and closing brace can be removed if you want the plugin to always load regardless | ||
+ | if (MyDialogUtils.getConfirmDialogResult(" | ||
+ | ASIdiSPIM plugin = new ASIdiSPIM(); | ||
+ | plugin.setApp(gui); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== 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. | ||
+ | |||
+ | Here is a bare-bones example script: | ||
+ | |||
+ | <code java> | ||
+ | // required imports | ||
+ | import org.micromanager.asidispim.api.ASIdiSPIMInterface; | ||
+ | import org.micromanager.asidispim.api.ASIdiSPIMImplementation; | ||
+ | |||
+ | // 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(); | ||
+ | |||
+ | // use the plugin' | ||
+ | diSPIM.runAcquisition(); | ||
+ | </ | ||
+ | |||
+ | Here are some example scripts: | ||
+ | |||
+ | <code java> | ||
+ | // This script changes channels in the middle of a multi-timepoint acquistion. | ||
+ | |||
+ | import org.micromanager.asidispim.api.ASIdiSPIMInterface; | ||
+ | import org.micromanager.asidispim.api.ASIdiSPIMImplementation; | ||
+ | |||
+ | // change these constants for your use | ||
+ | int timepointIntervalSec = 100; | ||
+ | int numTimepointsFirst = 100; | ||
+ | int numTimepointsSecond = 50; | ||
+ | String channelToRemove = " | ||
+ | String channelToAdd_1 = " | ||
+ | String channelToAdd_2 = " | ||
+ | |||
+ | |||
+ | // gets 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 | ||
+ | ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | ||
+ | |||
+ | // script uses existing settings except for the number of timepoints and time point interval which are controlled by the script | ||
+ | // NB: the channels for the first portion of acquisition should be configured correctly | ||
+ | diSPIM.setTimepointInterval(timepointIntervalSec); | ||
+ | diSPIM.setsetTimepointsNumber(numTimepointsFirst); | ||
+ | |||
+ | // launch the acquisition with current settings, will block until acquisition is done | ||
+ | diSPIM.runAcquisitionBlocking(); | ||
+ | |||
+ | // pause script to attempt to simulate the interval between timepoints (really it will take a few seconds longer, could try to compensate if it matters) | ||
+ | Thread.sleep(1000*(timepointIntervalSec)); | ||
+ | |||
+ | // remove and add the requested channels (here one subtration and 2 additions are hardcoded) | ||
+ | diSPIM.setChannelEnabled(channelToRemove, | ||
+ | diSPIM.setChannelEnabled(channelToAdd_1, | ||
+ | diSPIM.setChannelEnabled(channelToAdd_2, | ||
+ | |||
+ | // change the number of timepoints | ||
+ | diSPIM.setsetTimepointsNumber(numTimepointsSecond); | ||
+ | |||
+ | // launch the acquisition with current settings, will block until acquisition is done | ||
+ | diSPIM.runAcquisitionBlocking(); | ||
+ | </ | ||
+ | |||
+ | |||
+ | <code java> | ||
+ | // 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/ | ||
+ | |||
+ | import org.micromanager.asidispim.api.ASIdiSPIMInterface; | ||
+ | import org.micromanager.asidispim.api.ASIdiSPIMImplementation; | ||
+ | import org.micromanager.api.PositionList; | ||
+ | import org.micromanager.api.MultiStagePosition; | ||
+ | |||
+ | // change these constants for your use | ||
+ | int postMoveDelayMs = 500; // delay after stage arrives as position before imaging, overrides one set in plugin | ||
+ | |||
+ | // gets 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 | ||
+ | // acquisition settings aren't modified in this script, set them in the plugin GUI | ||
+ | ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | ||
+ | |||
+ | // get MM's position list | ||
+ | // should have positions set there already before launching script | ||
+ | PositionList pl = gui.getPositionList(); | ||
+ | int numPositions = pl.getNumberOfPositions(); | ||
+ | |||
+ | // make sure plugin is set _not_ to use positions | ||
+ | diSPIM.setMultiplePositionsEnabled(false); | ||
+ | |||
+ | // base name for file saving | ||
+ | String basePrefix = diSPIM.getSavingNamePrefix(); | ||
+ | |||
+ | // loop over all positions in position list | ||
+ | for( int i=0; i< | ||
+ | MultiStagePosition.goToPosition(pl.getPosition(i), | ||
+ | Thread.sleep(postMoveDelayMs); | ||
+ | diSPIM.setSavingNamePrefix(basePrefix + " | ||
+ | diSPIM.runAcquisitionBlocking() | ||
+ | } | ||
+ | |||
+ | // restore prefix | ||
+ | diSPIM.setSavingNamePrefix(basePrefix); | ||
+ | </ | ||
+ | |||
+ | |||
+ | <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, | ||
- | You can see recent changes to the plugin code by [[https:// | + | </code> |
/* | /* |