Storing output of plugin BaSiC to file

Hello everyone,

Sorry if it’s a simple question, but I am new to scripting with Python in FiJi and still at the start of the learning curve.

I have a stack of images in nd2 format (Nikon) with 256 positions x 15 time points x 3 fluorescence channels (CFP, YFP and DsRed). I want to apply the plugin BaSiC from ICB on them.

Thanks to previous answers from this community, I now have a running script which loads the input file “test_1.nd2” and applied the Basic plugin to a sub-stack of 15 images corresponding to the first position and CFP channel, which computes and removes the background image from this images.

This script displays the initial stack “CFP stack”, and three result stacks: “Corrected:CFP stack” (the corrected images), “Flat-Field:CFP stack” and “Dark-Field: CFP stack”, the two components of the background calculation.

Now, I would ideally like to not display all these stacks and simply save the resulting three stacks to files. So my questions are the following:

  1. is there a way to run the plugin on these images without displaying them? I tried removing “imp2.show()” from the script, but then the BaSiC plugin complained about no image being open.
  2. how do I save the resulting three stack correct, flat-field and dark-field to tiff files for further processing?

Thank you for your help, the full script is below:

from loci.plugins import BF
from loci.plugins.in import ImporterOptions
from loci.formats import MetadataTools
from loci.formats import ImageReader
from ij import ImagePlus, ImageStack, IJ

file = "Z:/case_imagesc/test_1.nd2"

# load position by position
options = ImporterOptions()
options.setId(file)

# Choose first position for now
s =0

options.setSeriesOn(s, True)
imp = BF.openImagePlus(options)[0]
stack = imp.getImageStack()
print 'Number of frames in stack  = ', stack.size()

# three new stacks for each fluorescence channel
CFP_stack = ImageStack(stack.width, stack.height)  
YFP_stack = ImageStack(stack.width, stack.height)
DsRed_stack = ImageStack(stack.width, stack.height)
    
# Iterate each frame in the stack and sort 
for i in range(stack.size()):  
     if i%3==0:
         cp = stack.getProcessor(i+1)
         fp = cp.convertToFloat() 
         CFP_stack.addSlice(None,fp)

     if i%3==1:
         cp = stack.getProcessor(i+1)
         fp = cp.convertToFloat() 
         YFP_stack.addSlice(None,fp)

     if i%3==2:
         cp = stack.getProcessor(i+1)
         fp = cp.convertToFloat() 
         DsRed_stack.addSlice(None,fp)

options.setSeriesOn(s, False)

# first channel selected to run BaSiC
imp2 = ImagePlus("CFP stack", CFP_stack)
imp2.show()

# run BaSiC plugin
IJ.run("BaSiC ", 
"processing_stack=[CFP stack] flat-field=None dark-field=None shading_estimation=[Estimate shading profiles] shading_model=[Estimate both flat-field and dark-field] setting_regularisationparametes=Automatic temporal_drift=Ignore correction_options=[Compute shading and correct images] lambda_flat=0.50 lambda_dark=0.50")

Yes. Instead of IJ.run("BaSiC ", ...) use the following call with your imp2 as first parameter (see also the Javadoc):

IJ.run(imp2, "BaSiC ", yourOptionStringHere);

This is also what the macro recorder records when in Java or Javascript mode. I highly recommend to always use the macro recorder to generate commands. This works well for Python as well, because the statements are just calls to ImageJ’s Java API anyway.

What does the macro recorder record when you try File > Save As > Tiff… ? :wink:

Let us know if you get stuck and need more help.

Thanks @imagejan for your answer.

I followed your answer and commented out imp2.show() in the script above and then called the plugin BaSic using

# run BaSiC plugin
IJ.run(imp2, "BaSiC ", "processing_stack=[CFP stack] otherOptions");

instead of the earlier version.

I still get an error message in a pop-up window stating “There are no images open”. So I’m still unsure on how to call BaSiC without having to display the original stack and having to display the three resulting stacks.

Concerning your answer to my second question, I am able to see that the recorder gives me

IJ.saveAs(imp, "Tiff", "Z:/case_imagesc/test.tif");

when I save one of the open resulting stacks to tiff (using the earlier version of my script with display). However, “imp” seems to be the current stack I select manually, and I would like to save the three different resulting stacks (corrected, flat-field and dark-field) from the plugin via the script. I’m not quite sure how to “grab” each of them with the script once the plugin has run in order to save them to tiff.

Oh, I see. Sorry my previous attempt of an answer was not helpful then.

It seems like BaSiC was not programmed with headless processing in any other language than IJ1 macros in mind (because the processing_stack=[CFP_Stack] parameter relies on a window with that title being registered with ImageJ’s WindowManager.

Your best bet then might be to run in IJ1 Macro language instead of Jython. In a macro you can use setBatchMode(true) to avoid displaying any images. (With the other scripting languages, that’s also possible but can get a bit tricky if the plugin authors didn’t separate functionality from user interface in their plugin, and don’t provide a public API to call the plugin.)

Again, the plugin seems to rely on displaying the output images in the UI, so your only chance might be to query the window manager for the window titles:

from ij import WindowManager
imp1 = WindowManager.getImage("corrected")

Edit: FWIW, I invited Carsten Marr, the author of the BaSiC plugin, to join this discussion.

Hi all,

I am Lorenz, a student working together with Dr. Tingying Peng and Dr. Carsten Marr from ICB, who developed BaSiC.

We have also tried to solve this problem. However, it is indeed very hard to store the images without displaying them. That is why we are currently working on a new Fiji BaSiC plugin, that incorporates exactly these features, i.e. choose whether to display the images and choose whether to directly store the outputs to the drive.

I will keep you updated on the progress of this version.

Best,
Lorenz