Skip to content
  • Home
  • Resources
  • Support
  • Contributors
  • Get Involved
  • About
Search
Login
Create Account

0
FAQ
→
Forum
0
Posts
-
Javadoc
Filter by type
Plugin Script Protocol FAQ Forum Topic Article
Filter by category
3-D3D3D coordinatesalignmentbasicsbatch processingCalciumcell trackingCLEMcolocalizationcomptageconfocalconnected componentscontributionconvolutioncorrelationdeconvolutiondeformable registrationdenoisingdetectiondetectordeveloperdisplacementsdistance mapexportezplugfeature detectionfeature matchingfilteringfluorescenceguiheadlesshelperHSV visualisationimage processImageJintensitymaskmavenmeasurementMHTmicroscopymonitoringmorphologymultiple hypothesis trackingnon rigid registrationoperatoroptimizationotsupluginpoint-spread functionprojectionprotocolPSFpythonregistrationreleaseRipley's K functionroiscriptscriptingsegmentationsequencesmoothingspatial distributionspotspot countstatisticssurfacesyntheticthresholdtoolboxtoolstrack processortrackingtutorialwarpingwavelet transformwaveletswidefieldworkbookXLS output
  • Plugin Script Protocol FAQ Forum Topic Article
  • 3-D
  • 3D
  • 3D coordinates
  • alignment
  • basics
  • batch processing
  • Calcium
  • cell tracking
  • CLEM
  • colocalization
  • comptage
  • confocal
  • connected components
  • contribution
  • convolution
  • correlation
  • deconvolution
  • deformable registration
  • denoising
  • detection
  • detector
  • developer
  • displacements
  • distance map
  • export
  • ezplug
  • feature detection
  • feature matching
  • filtering
  • fluorescence
  • gui
  • headless
  • helper
  • HSV visualisation
  • image process
  • ImageJ
  • intensity
  • mask
  • maven
  • measurement
  • MHT
  • microscopy
  • monitoring
  • morphology
  • multiple hypothesis tracking
  • non rigid registration
  • operator
  • optimization
  • otsu
  • plugin
  • point-spread function
  • projection
  • protocol
  • PSF
  • python
  • registration
  • release
  • Ripley's K function
  • roi
  • script
  • scripting
  • segmentation
  • sequence
  • smoothing
  • spatial distribution
  • spot
  • spot count
  • statistics
  • surface
  • synthetic
  • threshold
  • toolbox
  • tools
  • track processor
  • tracking
  • tutorial
  • warping
  • wavelet transform
  • wavelets
  • widefield
  • workbook
  • XLS output
Creating an Icy plugin with EzPlug
Installation instructions for Icy software

Creating blocks for Icy protocols

The plugin Protocols provide a graphical environment that enables anyone to create graphically and without any prior knowledge in programming a bioimage analysis workflow, and automate it on many images (batch processing). Protocols can also contain blocks with custom scripts and be run from the command line, which makes it a very powerful tool in Icy. You can find more information about Protocols in the end-user documentation. In this article, we explain how to write your own protocol block.

To get you quickly started and inspired, you can also browse the online collection of Icy protocols or search directly through the Icy software search bar with your favorite keywords. The video below shows an example of protocol and its execution.

Protocols are composed of blocks with various input and output variables. Blocks are connected with each other, the output variable of the first block being the input variable of the next one.

Block description

Protocols is fully compatible with Maven to manage dependencies and create the JAR file that Icy uses to run the plugin. If you want more details about it, please check our Maven tutorial.

This plugin is working similarly as EzPlug by minimizing as much as possible the code to write.
You can begin from our plugin template available on Gitlab and select MyIcyPlugin as your main class (it is possible to rename it of course) and delete MyEzPlugIcyPlugin as we do not need EzPlug to create a new protocol block.

The Block interface

To write a block from scratch or to convert an existing plug-in into a block, the main class should extend Plugin (as usual) and implement the Block interface:

package plugins.adufour.blocks.lang.Block;

public interface Block extends Runnable
{
void declareInput(VarList inputMap);
void declareOutput(VarList outputMap);
}

These two methods are quite explicit: the first one lets the developer add all block inputs to the specified input map, while the second one does likewise for outputs. Also, since this interface extends Runnable, your block should also contain a method called run() containing the main code.
Note to EzPlug users: since EzPlug already implements the Runnable interface, the run() method need not be implemented anymore. Hence, the main computation code may remain in your execute() method.

Handling and encapsulating objects with Var

Block inputs and outputs are encapsulated using Var objects, provided by EzPlug in the plugins.adufour.vars package. Var objects simplify the encapsulation of objects by adding various features such as value-change listeners and a referencing mechanism (a variable may be asked to transparently ‘point to’ another variable). In a nutshell, here is a short example of how Var objects work:

Integer i = 2;
VarInteger varInt = new VarInteger("my number", 0); // the second argument is the default value
VarInteger varInt2 = new VarInteger("some other number", 0);
VarListener listener = new VarListener
{
   public void valueChanged(Var source, Integer oldValue, Integer newValue)
   {
      System.out.println("the value of " + source.getName() + " changed from " + oldValue + " to " + newValue);
   }
   public void referenceChanged(Var source, Var<? extends Integer> oldReference, Var<? extends Integer> newReference)
   {
      System.out.println("the reference of " + source.getName() + " changed from " + oldReference + " to " + newReference);
   }
}
varInt.addListener(listener);
varInt2.addListener(listener);
varInt2.setReference(varInt); //will display "the reference of my other number changed from null to my number"
varInt.setValue(i); // will display "the value of my number changed from 0 to 2"
System.out.println(varInt2.getValue()); // will display "2"

Declaring block inputs

We will now focus on declaring inputs (declaration of outputs is analogous). Each block input should be added to the VarList parameter of the declareInput method, using any of the following methods:

  • void add(Var<?> variable)
  • void add(String id, Var<?> variable)

It is highly recommended to use the second version, which explicitly asks for a unique variable identifier. This unique identifier is used to save parameter values inside the protocol, and must be unique throughout the map (an exception will be thrown if a similar id already exists). This id must not be changed to ensure that parameter values will be correctly reloaded from disk. This being said, you are free to change the name of the variable itself at anytime (this name is the one displayed on the graphical interface). In case you opt for the first version, the variable name is considered as the id, and you therefore cannot change it afterwards.

Note to EzPlug users: since your plugin extends EzPlug, most of your parameters are probably EzVarXXX objects. If this is the case, no need to create new Var objects to represent input variables. Each EzVar contains a variable field of type Var. Hence, within the declareInput(..) method, all you have to do is to add one line per object in the form inputMap.add(“some unique ID”, myEzVar.variable).

Important note: in block mode, the initialize() method is no longer called. Therefore, make sure your EzVar objects are initialized upon declaration of the instance field and not in the initialize() method. It is not recommended to simply call the initialize() method within the declareInput(..) method, as the graphical user interface system works a little bit differently in standalone and block mode, and this may result in performance decrease and memory leaks.

Declaring block outputs

As you may guess, declaring block outputs is analogous to input case, nothing fancy here. Keep in mind however that output Var objects should be filled with the output of the algorithm, however this output should not be displayed directly to the user (or stored in some sort), as this is the goal of other blocks dedicated to these tasks.
Note to EzPlug users: it is presumable that your plug-in does nothing much about the output data (it is either sent to screen for display, to disk, to the swimming pool etc.). Therefore, the output should be (as usual) stored in Var instance fields, however one should ensure that nothing is displayed / stored when the plug-in is in block mode. To do so, use the EzPlug.isHeadless(), which will return false if the EzPlug runs standalone, or true if it is run headless, i.e., called from within another plugin or as a block.

Example:

// old code

public void execute()
{
  Sequence sout; // assume this contains a result

  addSequence(sout); // display the result on screen
}

// new code

VarSequence outputSequence = new VarSequence("output sequence", null);

public void execute()
{
  Sequence sout; // assume this contains a result

  outputSequence.setValue(outputSequence); // store the result

  if (!EzPlug.isHeadless)
  {
    addSequence(sout);
  }
}

Note that when submitting your plugin online, you will have to list both Blocks and EzPlug as dependencies, even though your plugin’s main does not extend EzPlug.

Handling user interruption

It may happen quite often that you (or any user) wish to interrupt a running protocol (wrong parameters, taking too long to do the job, etc.). Interrupting the execution is possible at two levels: at the protocol level, and at the block level:

  • Interrupting a protocol: this is the easiest scenario (nothing to do on the developer side). When a user clicks on the Stop button (on top of the Protocols interface), Protocols waits for the currently running block to finish its job and will stop there. This is not necessarily the most convenient use-case, since the number one reason to stop a process is because a block itself is taking forever to finish the job.
  • Interrupting a block: this is where you kick in. The entire workflow (i.e. your block) runs in a specific thread. When the previous Stop button is clicked, Protocols actually doesn’t just wait for the current Block to end its process, it also interrupts your main block thread by calling Thread.interrupt() on it. Note that this will not automatically kill your process (remember that proper Java practice dictates that threads shouldn’t be killed “brutally”, as this could leave the memory in a weird state). Instead, it changes the thread state to interrupted, and you can easily check this state using Thread.currentThread.isInterrupted() in your main code. All you have to do is check the value of this method every now and then throughout your process (at the beginning/end of a recursion for instance) and exit your process smoothly before exiting (i.e. closing file streams & network connections, stop other custom threads you started yourself, etc.).

Leave a Review Cancel reply

You must Register or Login to post a review.

Leave a review
Cancel review

Welcome

Welcome to the Icy community support.

View Forum

Google Group

We’re migrating to a new Forum ⚡️, but if you need to access the old Google Group, please follow this link. All new topics should be opened here from now.

Latest Articles

  • Creating an Icy plugin with EzPlug
  • Creating blocks for Icy protocols
  • Installation instructions for Icy software
  • Code of Conduct
  • Icy cheat sheets
Icy is founded by
Institut Pasteur
France BioImaging
Resources
Plugins Protocols Scripts
Get Involved
Contributors Information Trainings Join Icy
Support
Forum Articles FAQ Ask for help
About
Aknowledgements Bioimage Analysis Contributors Privacy Policy
Credits
Designed by Yhello
contact
Yhello is a digital creation agency based in Paris, created by former scientists passionate about the web.
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept All”, you consent to the use of ALL the cookies. However, you may visit "Cookie Settings" to provide a controlled consent.
Cookie SettingsAccept All
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SAVE & ACCEPT