// Batch_Warp_Channels.js script by Christophe Leterrier // Use warping function in N-STORM.ini to apply warping correction // 15-07-16 importClass(Packages.java.io.File); importClass(Packages.java.nio.file.Files); importClass(Packages.java.nio.file.Paths); importClass(Packages.ij.io.DirectoryChooser); importClass(Packages.ij.IJ); importClass(Packages.ij.gui.GenericDialog); // extension for input files extFormat = "csv"; colZ = 3; pxSizeDef = 160; // cam image pixel size in nm ZCompDef = 1; manShiftDef = false; manZShiftDef = 25; // Dialog 1: choose source directory var dc = new DirectoryChooser("Choose a folder"); var inDir = dc.getDirectory() + File.separator; var inDirFile = new File(inDir); var parDir = inDirFile.getParent() + File.separator; // Localize the SR folder to get the path to functions and ini File var routineFolder = "NeuroCyto" + File.separator + "added macros" + File.separator + "ChriSTORM extras" + File.separator; var plugDir = IJ.getDirectory("imagej"); plugDir = plugDir + "scripts" + File.separator + routineFolder; // ini File should be placed in the chriSTORM scripts folder var iniName = "N-STORM.ini"; var iniPath = plugDir + iniName; IJ.log("\n\n*** Batch Warp Channels started ***"); IJ.log(""); IJ.log("N-STORM.ini file path: " + iniPath); // get the ini reader function and the warp transformation function function path and load var Func1JS = "F-IniReadWarp.js"; var Func1Path = plugDir + Func1JS; IJ.log("Function path:" + plugDir + Func1JS); load(Func1Path); var Func2JS = "F-TSWarp.js"; var Func2Path = plugDir + Func2JS; IJ.log("Function path:" + plugDir + Func2JS); load(Func2Path); var iniArray = readIniWarp(iniPath); var objArray = iniArray[0]; var repArray = iniArray[1]; var warpArray = iniArray[2]; var zShiftArray = iniArray[3]; // Dialog 2: choose objective, source string, source and destination WL var gd = new GenericDialog("Batch warp channels: options"); gd.addNumericField("Camera pixel size", pxSizeDef, 1, 6, "nm"); gd.addChoice("Objective", objArray, objArray[0]); gd.addStringField("String for source wavelength", "_647_"); gd.addChoice("Source wavelength (longer)", repArray, repArray[0]); gd.addChoice("Destination wavelength (shorter)", repArray, repArray[1]); gd.addCheckbox("3D files", true); gd.addNumericField("Z compression (1 for none)", ZCompDef, 3, 6, "X"); gd.addCheckbox("Manual Z shift", manShiftDef); gd.addNumericField("Z shift value", manZShiftDef, 0, 6, "nm"); gd.showDialog(); var pxSize = gd.getNextNumber(); var objName = gd.getNextChoice(); var swlString = gd.getNextString(); var objIndex = getIndex(objArray, objName); var swlName = gd.getNextChoice(); var swlIndex = getIndex(repArray, swlName); var dwlName = gd.getNextChoice(); var dwlIndex = getIndex(repArray, dwlName); var is3D = gd.getNextBoolean(); var ZComp = gd.getNextNumber(); var manShift = gd.getNextBoolean(); var manZShift = gd.getNextNumber(); if (gd.wasOKed()) { // start var startTime = new Date().getTime(); IJ.log("Input folder: " + inDir); // define input folder, define and create output folder var inDirFunc = inDir; var outDirFunc = parDir + "Locs TS warp" + File.separator; IJ.log("Function input folder: " + inDirFunc); IJ.log("Function output folder: " + outDirFunc); var outDirFuncFile = new File(outDirFunc); if (!outDirFuncFile.exists()) { outDirFuncFile.mkdir(); } // get the file list from the input folder, batch process them var fileQueueS = getExtFiles(inDirFunc, extFormat); for (var f = 0; f < fileQueueS.length; f++) { inPath = fileQueueS[f]; inName = inPath.getName(); // only process source files defined by source WL string if (inName.indexOf(swlString) > 0) { IJ.log("input file: " + inPath.getAbsolutePath()); // test if 3D or 2D ThunderSTORM file if (is3D == true || inName.indexOf("TS3D.csv") > 0) { dimIndex = 1; IJ.log("3D file"); } else { dimIndex = 0; IJ.log("2D file"); } // build the Warp ID (in binary format, then convert it to 32-bit int) var fBin = dimIndex.toString(2) + padBin(dwlIndex.toString(2), 4) + padBin(swlIndex.toString(2), 4) + padBin(objIndex.toString(2), 4); var fIndex = parseInt(fBin, 2); IJ.log("Condition index in warpDB: " + fIndex); // find what warp (index) corresponds to this Warp ID in the warps array var wIndex = getWarpIndex(warpArray, fIndex); // find what Z shift (index) corresponds to this Z shift ID in the Z shifts array if (dimIndex == 1) var zIndex = getWarpIndex(zShiftArray, fIndex); else zIndex = -1; // Log the indexes found // IJ.log("warp ID (binary): " + fBin); // IJ.log("warp ID: " + fIndex); IJ.log("XY warp index in warpDB: " + wIndex); if (dimIndex == 1) IJ.log("Z shift index in warpDB: " + zIndex); // Process only if Warp has been correctly identified if (wIndex > -1) { // will send the warp array var currWarp = warpArray[wIndex]; // will send the z shift value or 0 if 2D file if (dimIndex == 1) var currZShift = zShiftArray[zIndex][1]; else var currZShift = 0; // Log Warp ID and coeffients to check if everything was found IJ.log("XY warp ID: " + currWarp[0]); xCoefs = "X coefficients: " + currWarp[1][0]; yCoefs = "Y coefficients: " + currWarp[2][0]; for (w = 1; w < currWarp[1].length; w++) { xCoefs += ", " + currWarp[1][w]; yCoefs += ", " + currWarp[2][w]; } IJ.log(xCoefs); IJ.log(yCoefs); if (dimIndex == 1) { currZFactor = ZComp; if (manShift == true) { currZShift = manZShift; IJ.log("Using Z correction: " + currZFactor + "* Z + " + currZShift + " (manual)"); } else { IJ.log("Using Z correction: " + currZFactor + "* Z + " + currZShift + " (from ini file)"); } } // call to the transformation function TSWarp(inPath, outDirFunc, currWarp, dimIndex, currZFactor, currZShift, pxSize); IJ.log(" warped file created\n"); } } else { var inPathP = Paths.get(inPath); var outPathP = Paths.get(outDirFunc + inName); Files.copy(inPathP, outPathP); } } // end var stopTime = new Date().getTime(); var Time = stopTime - startTime; IJ.log("\n*** Batch Warp Channels end after " + Time / 1000 + " s ***"); } // Utility functions function getIndex(arr, str) { for (var f = 0; f < arr.length; f++) { if (arr[f] == str) return f; } return -1; } function getExtFiles(dirst, inext) { var dir = new File(dirst); var allfiles = dir.listFiles(); var extFiles = new Array(); for (var i = 0 ; i < allfiles.length; i++) { var name = allfiles[i].getName(); var ext = name.substring(name.lastIndexOf(".")+1); if (ext == inext) { extFiles.push(allfiles[i]); } } return extFiles; } function padBin(s, l) { var out = s; for (var i = s.length; i < l; i++) { out = "0" + out; } return out; } function getWarpIndex(ca, fi) { for (var i = 0; i < ca.length; i++) { if (ca[i][0] == fi) return i; } return -1; }