documents:101029imagej_cui_lifconversion
Differences
This shows you the differences between two versions of the page.
Previous revision | |||
— | documents:101029imagej_cui_lifconversion [2020/11/26 09:11] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Command Line: LIF to Tiff conversion ====== | ||
+ | |||
+ | LIF is a grouped-stack file format containing multiple stacks. One could access each stack by [[http:// | ||
+ | |||
+ | TO avoid this, one could do the file conversion via command line. This could be done by [[http:// | ||
+ | < | ||
+ | sh / | ||
+ | </ | ||
+ | One missing function with this CL tool is that physical scales in x, y and z are not read out from LIF so that resulting Tiff stacks are devoid of these parameters. In addition, dimensional values such as number of slices per time point, and number of time points are not converted. | ||
+ | |||
+ | For this reason, following shell script was created to transfer physical scales in together with conversion. | ||
+ | < | ||
+ | sh / | ||
+ | </ | ||
+ | This script will extract metadata from LIF, convert each stack to Tiff stack, and set the physical parameters of the image by extracting these values from metadata. Tiff stack will be saved under a newly created directly where the LIF is located. Name of the directory will be | ||
+ | |||
+ | < | ||
+ | |||
+ | A text file named | ||
+ | |||
+ | < | ||
+ | |||
+ | is also generated, where extracted metadata is stored. | ||
+ | |||
+ | ===== How Metadata is Extracted ===== | ||
+ | |||
+ | Bioformat commandline tool " | ||
+ | |||
+ | Since macro command run(" | ||
+ | |||
+ | Link for the Image Property setter. | ||
+ | |||
+ | ===== Shell Script lifcon.sh ===== | ||
+ | |||
+ | <sxh shell> | ||
+ | #!/bin/sh | ||
+ | #script for converting Lif file to tif, and set physical scale. | ||
+ | # | ||
+ | imgfullpath=$1 | ||
+ | |||
+ | # path to IJ jar file | ||
+ | IJJARS="/ | ||
+ | |||
+ | # path to image | ||
+ | IMGFILE=" | ||
+ | IMGPATH=" | ||
+ | METAFULLPATH=" | ||
+ | echo ${METAFULLPATH} | ||
+ | |||
+ | # Lif converting IJ macro name | ||
+ | IJMACRONAME=" | ||
+ | |||
+ | #timer | ||
+ | jobstart=$(date +%s) | ||
+ | |||
+ | sh / | ||
+ | |||
+ | chmod ugo+x ${METAFULLPATH} | ||
+ | |||
+ | / | ||
+ | JARS} -batch ${IJJARS}/ | ||
+ | |||
+ | # timer | ||
+ | jobend=$(date +%s) | ||
+ | echo "Time: $((jobend-jobstart)) secs." | ||
+ | |||
+ | </ | ||
+ | |||
+ | ===== ImpProps.java ===== | ||
+ | |||
+ | Accessing Image Physical Properties. Compiled class should be copied to the imageJ plugin folder. [[http:// | ||
+ | |||
+ | <sxh java> | ||
+ | import ij.*; | ||
+ | import ij.measure.Calibration; | ||
+ | //import java.lang.Double; | ||
+ | /** | ||
+ | * This simple class can be called from an ImageJ macro via the " | ||
+ | * get and set the (string) properties of the active image (ImagePlus). | ||
+ | * | ||
+ | * call(" | ||
+ | * set property <key> to < | ||
+ | | ||
+ | * | ||
+ | * call(" | ||
+ | | ||
+ | * | ||
+ | * @see ij.ImagePlus# | ||
+ | * @see ij.ImagePlus# | ||
+ | * | ||
+ | * @author Joachim Wesner | ||
+ | * @author Leica Microsystems CMS GmbH | ||
+ | * @author joachim.wesner@leica-microsystems.com | ||
+ | * @version 2008-3-15 | ||
+ | | ||
+ | * @author Kota Miura | ||
+ | * cmci, embl | ||
+ | * added methods for setting image dimension sizes and pixel scales. | ||
+ | * this was done for setting these values in headless mode. | ||
+ | * @version 2010-10-28 | ||
+ | * This class can be compiled with ImageJ' | ||
+ | */ | ||
+ | |||
+ | public class ImpProps { | ||
+ | |||
+ | //kota | ||
+ | public static String getProperties() { | ||
+ | ImagePlus imp = WindowManager.getCurrentImage(); | ||
+ | if (imp == null) | ||
+ | return ""; | ||
+ | Object prop = imp.getProperties(); | ||
+ | if (prop != null && prop instanceof String) | ||
+ | return (String)prop; | ||
+ | else | ||
+ | return ""; | ||
+ | } | ||
+ | |||
+ | public static String setProperty(String arg1, String arg2) { | ||
+ | ImagePlus imp = WindowManager.getCurrentImage(); | ||
+ | if (imp == null) | ||
+ | return ""; | ||
+ | imp.setProperty(arg1, | ||
+ | imp.updateAndDraw(); | ||
+ | return arg2; | ||
+ | } | ||
+ | |||
+ | public static String getProperty(String arg1) { | ||
+ | ImagePlus imp = WindowManager.getCurrentImage(); | ||
+ | if (imp == null) | ||
+ | return ""; | ||
+ | Object prop = imp.getProperty(arg1); | ||
+ | if (prop != null && prop instanceof String) | ||
+ | return (String)prop; | ||
+ | else | ||
+ | return ""; | ||
+ | } | ||
+ | |||
+ | //kota | ||
+ | public static int setCalibration(String unit, String spixelWidth, | ||
+ | double pixelWidth = java.lang.Double.parseDouble(spixelWidth); | ||
+ | double pixelHeight = java.lang.Double.parseDouble(spixelHeight); | ||
+ | double pixelDepth = java.lang.Double.parseDouble(spixelDepth); | ||
+ | ImagePlus imp = WindowManager.getCurrentImage(); | ||
+ | if (imp == null) | ||
+ | return -1; | ||
+ | Calibration cal = imp.getCalibration(); | ||
+ | cal.setUnit(unit); | ||
+ | cal.pixelWidth = pixelWidth; | ||
+ | cal.pixelHeight = pixelHeight; | ||
+ | cal.pixelDepth = pixelDepth; | ||
+ | imp.setCalibration(cal); | ||
+ | WindowManager.repaintImageWindows(); | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | //kota | ||
+ | public static int setCalibration( | ||
+ | String schannels, String sslices, | ||
+ | String sframes, String unit, | ||
+ | String spixelWidth, | ||
+ | String spixelDepth) { | ||
+ | int channels = java.lang.Integer.parseInt(schannels); | ||
+ | int slices | ||
+ | int frames | ||
+ | double pixelWidth | ||
+ | double pixelHeight = java.lang.Double.parseDouble(spixelHeight); | ||
+ | double pixelDepth | ||
+ | |||
+ | ImagePlus imp = WindowManager.getCurrentImage(); | ||
+ | if (imp == null) | ||
+ | return -1; | ||
+ | int stackSize = imp.getImageStackSize(); | ||
+ | if (channels*slices*frames==stackSize) | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | Calibration cal = imp.getCalibration(); | ||
+ | cal.setUnit(unit); | ||
+ | // | ||
+ | cal.pixelWidth = pixelWidth; | ||
+ | cal.pixelHeight = pixelHeight; | ||
+ | cal.pixelDepth = pixelDepth; | ||
+ | imp.setCalibration(cal); | ||
+ | WindowManager.repaintImageWindows(); | ||
+ | return 1; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | ===== bfconvert help ===== | ||
+ | |||
+ | < | ||
+ | To convert a file between formats, run: | ||
+ | bfconvert [-debug] [-stitch] [-separate] [-merge] [-expand] | ||
+ | [-bigtiff] [-compression codec] [-series series] [-map id] | ||
+ | in_file out_file | ||
+ | |||
+ | -debug: turn on debugging output | ||
+ | | ||
+ | | ||
+ | -merge: combine separate channels into RGB image | ||
+ | | ||
+ | -bigtiff: force BigTIFF files to be written | ||
+ | -compression: | ||
+ | | ||
+ | -map: specify file on disk to which name should be mapped | ||
+ | |||
+ | If any of the following patterns are present in out_file, they will | ||
+ | be replaced with the indicated metadata value from the input file. | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | |||
+ | If any of these patterns are present, then the images to be saved | ||
+ | will be split into multiple files. | ||
+ | contains 5 Z sections and 3 timepoints, and out_file is | ||
+ | |||
+ | converted_Z%z_T%t.tiff | ||
+ | |||
+ | then 15 files will be created, with the names | ||
+ | |||
+ | converted_Z0_T0.tiff | ||
+ | converted_Z0_T1.tiff | ||
+ | converted_Z0_T2.tiff | ||
+ | converted_Z1_T0.tiff | ||
+ | ... | ||
+ | converted_Z4_T2.tiff | ||
+ | |||
+ | Each file would have a single image plane. | ||
+ | </ | ||
+ | |||
+ | ===== LifOpenerCUI.ijm ===== | ||
+ | |||
+ | ImageJ macro for converting LIF stack series to multiple tiff stacks, together with setting physical parameters. | ||
+ | < | ||
+ | // converts LIF file to channel-separated tif stacks. | ||
+ | // output files will be saved under the folder <LIF file name> | ||
+ | |||
+ | //bach command example | ||
+ | /* | ||
+ | / | ||
+ | */ | ||
+ | // TODO: scale should be set as the propertiy of tiff file. | ||
+ | // reading out of the scale from LIF is somehow not working, unlike it was done in 2009 | ||
+ | // metadata of .lif file would be saved as < | ||
+ | //will be saved in the same directory. | ||
+ | // TODO: program might return error if sequence is terminated abruptly. | ||
+ | |||
+ | // for setting scale, plugin " ImpProp.class" | ||
+ | |||
+ | srcfile = getArgument(); | ||
+ | // srcfile = File.openDialog(" | ||
+ | requires(" | ||
+ | run(" | ||
+ | |||
+ | path = srcfile; | ||
+ | name = File.getName(path); | ||
+ | dir = File.getParent(path); | ||
+ | DAPIch = 0;// | ||
+ | FISHch = 1;// | ||
+ | metaname = name + " | ||
+ | |||
+ | q = File.separator; | ||
+ | metafullpath = dir+q+metaname; | ||
+ | metastr = File.openAsString(metafullpath); | ||
+ | workdir = File.getParent(srcfile); | ||
+ | |||
+ | //create " | ||
+ | pathtifstack = workdir + q + name+ " | ||
+ | if (File.isDirectory(pathtifstack)==0) File.makeDirectory(pathtifstack); | ||
+ | |||
+ | Ext.setId(path); | ||
+ | Ext.getSeriesCount(seriesCount); | ||
+ | Ext.getCurrentFile(file); | ||
+ | Ext.close(); | ||
+ | print(" | ||
+ | print(" | ||
+ | |||
+ | for (s=0; s< | ||
+ | |||
+ | seriesNum = s; | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | // | ||
+ | |||
+ | if (s>0) refresh =0; | ||
+ | |||
+ | seriesName = OpenLIFSeriesOneChannel(path, | ||
+ | G_GID = getImageID(); | ||
+ | savepath = pathtifstack + q+getTitle(); | ||
+ | print(savepath); | ||
+ | saveAs(" | ||
+ | close(); | ||
+ | |||
+ | OpenLIFSeriesOneChannel(path, | ||
+ | G_RID = getImageID(); | ||
+ | savepath = pathtifstack | ||
+ | print(savepath); | ||
+ | saveAs(" | ||
+ | close(); | ||
+ | } | ||
+ | |||
+ | |||
+ | // | ||
+ | /* 090907 | ||
+ | 090908 | ||
+ | - save tif file in a specified directory | ||
+ | - problem with DAPI appearance in the resulting window. | ||
+ | */ | ||
+ | function OpenLIFSeriesOneChannel(id, | ||
+ | run(" | ||
+ | |||
+ | //if (datasetOpened ==0) Ext.setId(id); | ||
+ | Ext.setId(id); | ||
+ | Ext.setSeries(seriesNum); | ||
+ | Ext.getSeriesName(seriesName); | ||
+ | Ext.getSizeZ(sizeZ); | ||
+ | Ext.getSizeC(sizeC); | ||
+ | Ext.getSizeT(sizeT); | ||
+ | Ext.getImageCount(imageCount); | ||
+ | print(" | ||
+ | calculatedCount = sizeZ*sizeC*sizeT; | ||
+ | print(" | ||
+ | if (imageCount != calculatedCount) { | ||
+ | print(); | ||
+ | exit(); | ||
+ | } | ||
+ | sizeT = imageCount/ | ||
+ | print(" | ||
+ | newname = name+" | ||
+ | setBatchMode(true); | ||
+ | for (j=0; j<sizeT; j++){ | ||
+ | for (i=0; i<sizeZ; i++){ | ||
+ | currentZch0 = i*sizeC; | ||
+ | currentPlane = j*sizeZ*sizeC + i*sizeC; | ||
+ | Ext.openImage(" | ||
+ | if ((i==0) && (j==0)) | ||
+ | stackID=getImageID(); | ||
+ | else { | ||
+ | run(" | ||
+ | close; | ||
+ | selectImage(stackID); | ||
+ | run(" | ||
+ | run(" | ||
+ | } | ||
+ | // | ||
+ | } | ||
+ | } | ||
+ | rename(newname); | ||
+ | xscale = returnXscale(metastr); | ||
+ | yscale = returnYscale(metastr); | ||
+ | zscale = returnZscale(metastr); | ||
+ | tscale = 1;// | ||
+ | xscalemicron = parseFloat(xscale) * pow(10, 6); | ||
+ | yscalemicron = parseFloat(yscale) * pow(10, 6); | ||
+ | zscalemicron = parseFloat(zscale) * pow(10, 6); | ||
+ | op = " | ||
+ | //since run(" | ||
+ | // | ||
+ | // ImpProp.class | ||
+ | SsizeC = "" | ||
+ | SsizeZ = "" | ||
+ | SsizeT = "" | ||
+ | Sxscalemicron = "" | ||
+ | Syscalemicron = "" | ||
+ | Szscalemicron = "" | ||
+ | call(" | ||
+ | SsizeC, SsizeZ, SsizeT, " | ||
+ | Sxscalemicron, | ||
+ | |||
+ | setBatchMode(false); | ||
+ | //if (datasetOpened ==0) Ext.close(); | ||
+ | Ext.close(); | ||
+ | return seriesName; | ||
+ | } | ||
+ | |||
+ | //zscale in micron | ||
+ | function returnZscale(metastr){ | ||
+ | metaA = split(metastr, | ||
+ | zscale = 1; | ||
+ | for (i=0; i< | ||
+ | if (startsWith(metaA[i], | ||
+ | lineA = split(metaA[i], | ||
+ | //for (j=0; j< | ||
+ | if (lineA.length> | ||
+ | zscale = parseFloat(lineA[2]); | ||
+ | print(zscale); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return zscale; | ||
+ | } | ||
+ | |||
+ | //Xscale in micron | ||
+ | function returnXscale(metastr){ | ||
+ | metaA = split(metastr, | ||
+ | xscale = 1; | ||
+ | for (i=0; i< | ||
+ | if (startsWith(metaA[i], | ||
+ | lineA = split(metaA[i], | ||
+ | //for (j=0; j< | ||
+ | if (lineA.length> | ||
+ | xscale = parseFloat(lineA[2]); | ||
+ | print(xscale); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return xscale; | ||
+ | } | ||
+ | |||
+ | function returnYscale(metastr){ | ||
+ | metaA = split(metastr, | ||
+ | yscale = 1; | ||
+ | for (i=0; i< | ||
+ | if (startsWith(metaA[i], | ||
+ | lineA = split(metaA[i], | ||
+ | //for (j=0; j< | ||
+ | if (lineA.length> | ||
+ | yscale = parseFloat(lineA[2]); | ||
+ | print(yscale); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | return yscale; | ||
+ | } | ||
+ | |||
+ | function returnTscale(){ | ||
+ | metaA = split(metastr, | ||
+ | for (i=0; i< | ||
+ | if (startsWith(metaA[i], | ||
+ | lineA = split(metaA[i], | ||
+ | //for (j=0; j< | ||
+ | if (lineA.length> | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||