Created
March 29, 2021 09:15
-
-
Save NicoKiaru/d08618d3b8b04bafe0ab9520c59edf5e to your computer and use it in GitHub Desktop.
Takes a Nikon ND2 file and batch exports individual series, optionally Z Projected and rescaled #BIOP #Fiji #BigDataViewer #NikonStereology
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// You need to activate https://biop.epfl.ch/Fiji-Bdv-Playground/ for this script to function | |
// It takes a Nikon ND2 file and batch exports individual series, optionally Z Projected and rescaled | |
// Nicolas Chiaruttini, BIOP, EPFL, 2021 | |
#@CommandService cs | |
#@SourceAndConverterService sac_service | |
#@File(label="Select your Nikon ND2 file (single timepoint only)", style="open") nikonNd2File | |
#@File(label="Select directory to save images", style="directory", value="default") saveDir | |
#@Integer(label="Resize Factor (XY)", value=1) resize | |
#@Boolean(label="Project Z Slices", value=false) is_do_z_project | |
#@String(label="Z Projection Method", choices={"avg", "min", "max", "sum", "sd", "median"}) z_project_method | |
#@Integer(label="Number of images processed in parallel", value=8) nMaxThreads | |
// Opens Nikon nd2 dataset ( = multi series ) | |
def dataset = cs.run(BasicOpenFilesWithBigdataviewerBioformatsBridgeCommand.class, true, | |
"unit", "MICROMETER", | |
"files", [nikonNd2File] as File[], | |
"splitRGBChannels", false | |
).get().getOutput("spimData") | |
// Sets a meaningful name to the opened dataset - if not it is called SpimData 0 | |
sac_service.setSpimDataName(dataset, nikonNd2File.getName()) | |
// Uses the Bdv UI to fetch the number of series ( how many nodes are there below dataset>SeriesNumber ? | |
def datasetPath = sac_service.getUI().getTreePathFromString(nikonNd2File.getName()+">SeriesNumber") | |
def int number_of_series = datasetPath.getLastPathComponent().getChildCount(); | |
// For the user - IJ log starts | |
IJ.log("Starting processing "+number_of_series+" series contained in "+ nikonNd2File.getName()+"...") | |
// Times the whole process | |
def exporterTimer = new Timer("Export from file "+nikonNd2File.getName()) | |
exporterTimer.tic() | |
// Sets output directory | |
def File outputDirectory; | |
if(!saveDir.getName().equals("default")) { | |
outputDirectory = new File(saveDir.getAbsolutePath()) | |
} else { | |
outputDirectory = new File(nikonNd2File.getParent(), "output") | |
if (!outputDirectory.exists()) { | |
outputDirectory.mkdir() | |
} | |
} | |
// Processes series in parallel | |
GParsExecutorsPool.withPool(nMaxThreads as int) { | |
(0..number_of_series-1).eachParallel{ series_index -> | |
def seriesProcessTimer = new Timer("--- processing series "+series_index) | |
seriesProcessTimer.tic() | |
// Export dataset as a Virtual Image Plus | |
def original_imp = cs.run(ExportToImagePlusCommand.class, true, | |
"level",0, | |
"timepointBegin",0, | |
"timepointEnd",1, | |
"sacs", nikonNd2File.getName()+">SeriesNumber>Series_"+series_index).get().getOutput("imp_out"); | |
def output_imp = original_imp | |
// Projects the image if set by the user | |
if (is_do_z_project) { | |
output_imp = ZProjector.run(output_imp, z_project_method) | |
} | |
// Resizes the image if set by the user | |
if (resize!=1) { | |
output_imp = Scaler.resize( | |
output_imp, output_imp.getWidth()/resize as int, | |
output_imp.getHeight()/resize as int, | |
output_imp.getNSlices() as int, | |
"bilinear") | |
} | |
output_imp.show() | |
original_imp.close() | |
// Sets series outputfilename | |
def fileName = FilenameUtils.getBaseName(nikonNd2File.getName())+"_S"+series_index | |
IJ.saveAs(output_imp, "Tiff", outputDirectory.getAbsolutePath()+"//"+fileName+".tif") | |
output_imp.close() | |
seriesProcessTimer.toc() | |
} | |
} | |
cs.run(SourcesRemoverCommand.class, true, "sacs", nikonNd2File.getName()) // Cleans source and converter service -> releases memory | |
// Ends timer | |
exporterTimer.toc() | |
/* | |
* Time class to 'tic-toc' a few steps and check time spent. | |
*/ | |
class Timer{ | |
Long startTime | |
Long endTime | |
def name | |
public Timer(String name){ | |
this.name = name | |
} | |
public void tic(){ | |
this.startTime = System.nanoTime() | |
} | |
public void toc(){ | |
this.endTime = System.nanoTime() | |
IJ.log("'"+name+"' took : "+((endTime-startTime)/1e9)+" s") | |
} | |
} | |
import ch.epfl.biop.bdv.bioformats.command.BasicOpenFilesWithBigdataviewerBioformatsBridgeCommand | |
import sc.fiji.bdvpg.scijava.command.source.SourcesRemoverCommand | |
import ch.epfl.biop.bdv.command.exporter.ExportToImagePlusCommand | |
import ij.plugin.Scaler | |
import ij.plugin.ZProjector | |
import ij.IJ | |
import org.apache.commons.io.FilenameUtils | |
import ch.epfl.biop.bdv.bioformats.imageloader.SeriesNumber | |
import groovyx.gpars.GParsExecutorsPool |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment