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 [2019/07/03 03:58] Jon Daniels [Scripting the plugin] |
software:micro-manager [2024/05/21 23:52] (current) Jon Daniels [Runnables in the plugin] |
||
---|---|---|---|
Line 5: | Line 5: | ||
Details about the plugin operation can be found in the manual section of this website in the [[: | Details about the plugin operation can be found in the manual section of this website in the [[: | ||
- | 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/ |
Line 66: | 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 72: | 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 103: | 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 148: | 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 191: | Line 198: | ||
+ | <code java> | ||
+ | // This script runs a " | ||
+ | // in a separate acquisition on disk. | ||
- | As of July 2019 limited support | + | // 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 | ||
+ | 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 "runnables" was added to the plugin | ||
+ | |||
+ | 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 | - Start of timepoint | ||
- End of timepoint | - End of timepoint | ||
Line 198: | Line 355: | ||
- End of position | - End of position | ||
- | Note that these would be called only once each for an acquisition without timepoints nor positions selected. | + | 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: | + | Here is an example adding a runnable to each of these possible invocation points. Note the use of global variables in the script so that state can be passed between runnables, as well as local variables within a runnable that cannot be changed by another runnable (e.g. reset at the start of the acquisition). |
- | < | + | < |
// required imports | // required imports | ||
import org.micromanager.asidispim.api.*; | import org.micromanager.asidispim.api.*; | ||
Line 211: | Line 368: | ||
// note that the plugin must be launched for this to work | // note that the plugin must be launched for this to work | ||
ASIdiSPIMInterface diSPIM = new ASIdiSPIMImplementation(); | 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() { | taskStartPosition = new Runnable() { | ||
public void run() { | public void run() { | ||
+ | runnablePositionCounter++; | ||
// test code which will raise dialog; should be replaced | // test code which will raise dialog; should be replaced | ||
- | gui.showError(" | + | gui.showError(" |
} | } | ||
}; | }; | ||
taskEndPosition = new Runnable() { | taskEndPosition = new Runnable() { | ||
+ | int localCounter = 0; | ||
public void run() { | public void run() { | ||
+ | localCounter++; | ||
// test code which will raise dialog; should be replaced | // test code which will raise dialog; should be replaced | ||
- | gui.showError(" | + | gui.showError(" |
} | } | ||
}; | }; | ||
Line 228: | Line 407: | ||
taskStartTimepoint = new Runnable() { | taskStartTimepoint = new Runnable() { | ||
public void run() { | public void run() { | ||
+ | runnablePositionCounter = 0; | ||
+ | runnableTimepointCounter++; | ||
// test code which will raise dialog; should be replaced | // test code which will raise dialog; should be replaced | ||
- | gui.showError(" | + | gui.showError(" |
} | } | ||
}; | }; | ||
taskEndTimepoint = new Runnable() { | taskEndTimepoint = new Runnable() { | ||
+ | int localCounter = 0; | ||
public void run() { | public void run() { | ||
+ | localCounter++; | ||
// test code which will raise dialog; should be replaced | // test code which will raise dialog; should be replaced | ||
- | gui.showError(" | + | gui.showError(" |
} | } | ||
}; | }; | ||
Line 242: | Line 425: | ||
// add all run | // add all run | ||
diSPIM.clearAllRunnables(); | diSPIM.clearAllRunnables(); | ||
+ | diSPIM.attachRunnable(taskStartAcquisition, | ||
+ | diSPIM.attachRunnable(taskEndAcquisition, | ||
diSPIM.attachRunnable(taskStartPosition, | diSPIM.attachRunnable(taskStartPosition, | ||
diSPIM.attachRunnable(taskEndPosition, | diSPIM.attachRunnable(taskEndPosition, | ||
Line 247: | Line 432: | ||
diSPIM.attachRunnable(taskEndTimepoint, | diSPIM.attachRunnable(taskEndTimepoint, | ||
- | diSPIM.runAcquisition(); | + | </ |
+ | |||
+ | |||
+ | 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 | ||
+ | |||
+ | // 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() { | ||
+ | //gui.showError(" | ||
+ | if ((runnablePositionCounter % counterPeriod)< | ||
+ | mmc.fullFocus(); | ||
+ | } | ||
+ | runnablePositionCounter++; | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | |||
+ | // add the runnables to the diSPIM plugin' | ||
+ | diSPIM.clearAllRunnables(); | ||
+ | diSPIM.attachRunnable(taskStartAcquisition, | ||
+ | diSPIM.attachRunnable(taskStartPosition, | ||