# @File(label = "Input directory", style = "directory") srcFile # @File(label = "Output directory", style = "directory") dstFile # @String(label = "File extension", value=".nd2") ext # @String(label = "File name contains", value = "") containString # @Integer(label = "Which file number start from?", value = 0) startNum # @boolean(label = "Keep directory structure when saving", value = true) keepDirectories # @boolean(label = "Include subfolders?", value = false) subDirectories # @boolean(label = "Align stack using StackReg?", value = true) align ### This Jython (Python for Java) batch script for Fiji (ImageJ) separates a multidimensional image ### into separate files for each channel and timestep and aligns all the frames to the first one ### using StackReg plugin. It saves the aligned frames in a defined directory together with ### timing information for each frames (that it tries to get from the initial file or separate csv file with the same name) ## The input variables are: ## srcFile: select the directory containing the files that should be processed ## dstFile: select the directory where the final files should be saved ## ext: select the extension of the files that should be processed ## containString: if the directory contains other files, enter the common part of the filenames that should be processed ## startNum: only if filenames end with a number: select the number the script should start from ## align: choose whether you need the images to be aligned with StackReg (true by default) import os import csv from ij import IJ, ImagePlus, WindowManager from loci.plugins import BF from loci.formats import ImageReader from loci.formats import MetadataTools from ome.xml.meta import OMEXMLMetadata from xml.etree import ElementTree as ETree from java.io import File def run(): srcDir = srcFile.getAbsolutePath() dstDir = (srcFile.getAbsolutePath() if str(dstFile) == 'same' else dstFile.getAbsolutePath()) for (root, directories, filenames) in os.walk(srcDir): filenames.sort() for filename in filenames: # Check for file extension if not filename.endswith(ext): continue # Check for file name pattern if necessary if containString not in filename: continue # Check whether the files in subdirectories should be processed as well if not subDirectories: if root != srcDir: continue # Check whether the filenumber is bigger than 'start from' number if startNum != 0 and int(filename[-6:-4]) < startNum: continue process(srcDir, dstDir, root, filename, keepDirectories) def process( srcDir, dstDir, currentDir, fileName, keepDirectories, ): print 'Processing:' # Opening the image as virtual stack with splitted channels using Bioformats importer print 'Opening image file', fileName path = os.path.join(currentDir, fileName) imp = IJ.run('Bio-Formats', 'open=[' + path +'] color_mode=Default rois_import=[ROI manager] split_channels view=Hyperstack stack_order=XYCZT use_virtual_stack') # Populating metadata file = File(currentDir, fileName) r = ImageReader() meta = MetadataTools.createOMEXMLMetadata() r.setMetadataStore(meta) r.setId(file.getAbsolutePath()) # Trying to get DeltaTime for each frame from metadata time = [] for i in range(0, meta.getPlaneCount(0), 2): time.append(meta.getPlaneDeltaT(0, i).value()) # if DeltaTime is not found in metadata, trying to load an external csv file with the same name # and directory. csv file should contain a single column with timestamps. try: if time == []: print "Can't get timestamps from metadata, trying an external csv file" with open(os.path.join(currentDir, fileName[0:-4] + '.csv'), 'rb') as t: reader = csv.reader(t) time = [row[0] for row in reader] t.close() except: print 'External file with timestamps is not found' # converting timestamps to seconds if they are in milliseconds try: if float(time[0]) > 60: time = [x / 1000 for x in time] except: pass time = [[str(x)] for x in time] open_images_titles = WindowManager.getImageTitles() # iterates over open windows (channels) for image_name in open_images_titles: # forms output name ch_pos = image_name.find('C=') if ch_pos == -1: output_name = image_name else: output_name = image_name[:ch_pos - 7] + '_c' + image_name[ch_pos + 2:] # duplicates completely in memory and shows new window image = WindowManager.getImage(image_name) imageD = image.duplicate() imageD.show() # fix the image to a 12-bit range imageD.setDefault16bitRange(12) IJ.setMinAndMax(imageD, 0, 4095) # aligning the images with StackReg plugin if align: IJ.run(imageD, 'StackReg ', 'transformation=[Translation]') # forms output directory saveDir = (currentDir.replace(srcDir, dstDir) + '//' + image_name[:ch_pos - 7] if keepDirectories else dstDir + '//' + image_name[:ch_pos - 7]) if not os.path.exists(saveDir): print 'Creating folder ', saveDir os.makedirs(saveDir) print 'Saving to', saveDir # saves a channel as tiff-sequence: one image for each timestep IJ.run(imageD, 'Image Sequence... ', 'format=TIFF name=[' + output_name + '_t] digits=3 save=[' + saveDir + '\\' + output_name + '.tif]') print 'File saved as', saveDir + '\\' + output_name + '.tif]' # closes windows imageD.changes = False # avoid "Save changes?" dialog imageD.close() image.close() # saves timestamps in a separate csv file in the output directory with open(os.path.join(saveDir, 'DeltaTime.csv'), 'wb') as f: writer = csv.writer(f, dialect='excel', delimiter=',') writer.writerows(time) f.close() # saves all metadata in a separate xml file in the output directory with open(os.path.join(saveDir, 'Metadata.xml'), 'wb') as f: f.write(meta.dumpXML().encode('utf-8')) f.close() run()