I am trying to write an imageJ macro that will
1) Open and split an image into two channels 2) Perform particle analysis on each image and save measurements 3) Save the original image with the particle outlines overlayed So far I have realised I need to first duplicate the original image so that the ROI can later be saved on top of this. However I at the moment I can't figure out how to rename this duplicated image so I can later select it for flattening: dir=getDirectory("Choose a Directory"); print(dir); greenDir=dir + "/Green/"; blueDir=dir + "/Blue/"; print(greenDir); print(blueDir); File.makeDirectory(greenDir); File.makeDirectory(blueDir); list = getFileList(dir); for (i=0; i<list.length; i++) { if (endsWith(list[i], ".tif")){ print(i + ": " + dir+list[i]); open(dir+list[i]); imgName=getTitle(); baseNameEnd=indexOf(imgName, ".tif"); baseName=substring(imgName, 0, baseNameEnd); run("Split Channels"); selectWindow("C1-" + imgName); run("Duplicate...", "title= imgName + "original"); selectWindow("C1-" + imgName); setAutoThreshold("Default dark"); //run("Threshold..."); //setThreshold(1, 255); run("Convert to Mask"); run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude summarize add"); selectWindow(imgName + "original"); roiManager("Show All without labels"); run("Flatten"); saveAs("Tiff", greenDir + baseName + "green.tif"); close(); I know the error is in the run("Duplicate...", "title= imgName + "original"); line, but I don't know what's wrong with the code! |
Hi Eloiselockyer,
I think if you write run("Duplicate...", "title=list[i]+_original"); it should work. No spaces, and you can use the list of the directory images as you loop through them. Also, you can make it easier to navigate between images if you don't split the original image nad choose the channel to duplicate. The example code below does a similar thing and works, but more simply (please excuse my crude coding!). Rather than split the channels, it opens a multicahnnel image, and duplicates each channel one at a time (with the duplicate channels option). It then thresholds the duplicate then counts particles (you can see I've commented out different thresholding methods to play around with the best one). Found particles are then added to the ROI manager and the thresholded image renamed. //Assumes the image is a MIP'ed tif with PML in channel1, H2AX in channel2 //(although these can be the other way round and it doesn't matter too much except for labelling in results) //and DAPI in channel3. It looks for pure overlap and counts respective spots. //All results get stored in a concatenating results file. //Plus the mask images are stored (all 3 original images converted to masks plus the coloc maskin the 4th channel) // so you can see what it did. var tolerance = 30; run("Set Measurements...", "area integrated limit display redirect=None decimal=3"); dir1 = getDirectory("Choose folder with tif files "); list = getFileList(dir1); setBatchMode(true); // create folders for the tifs dir1parent = File.getParent(dir1); dir1name = File.getName(dir1); dir2 = dir1parent+File.separator+dir1name+"_masks"; if (File.exists(dir2)==false) { File.makeDirectory(dir2); // new directory for mask images } for (i=0; i<list.length; i++) { showProgress(i+1, list.length); print("processing ... "+i+1+"/"+list.length+"\n "+list[i]); filename = dir1 + list[i]; if (endsWith(filename, "tif")) { path=dir1+list[i]; run("Bio-Formats Importer", "open="+filename+" autoscale color_mode=Default view=Hyperstack stack_order=XYCZT"); originalImage = getTitle(); roiManager("Reset"); selectWindow(originalImage); run("Duplicate...", "duplicate channels=1"); //Change this to the DAPI channel slice******* // run("8-bit"); setAutoThreshold("Moments dark"); run("Threshold"); run("Watershed"); // run("Entropy Threshold"); run("Analyze Particles...", "size=120-2500 circularity=0.04-1.00 exclude add"); rename("nuc"); //nuclei now added to ROI manager //next find pml bodies selectWindow(originalImage); run("Duplicate...", "title=PML duplicate channels=3"); // run("8-bit"); setAutoThreshold("Triangle dark"); run("Threshold"); // rename("PML"); //next find h2ax foci selectWindow(originalImage); run("Duplicate...", "title=h2ax duplicate channels=2"); wait(1000); // run("8-bit"); setAutoThreshold("MaxEntropy dark"); run("Threshold"); // rename("h2ax"); //Next find colocalised PML-H2AX foci pixels imageCalculator("Multiply create", "h2ax","PML"); selectWindow("Result of h2ax"); rename(originalImage+":coloc"); run("Grays"); for(j=0; j<roiManager("count"); j++) { roiManager("select", j); run("Find Maxima...", "noise="+tolerance+" output=[Count]"); // run("Find Maxima...", "noise="+tolerance+" output=[Point Selection]"); run("Add Selection..."); } // saveAs("Results", dir2+File.separator+originalImage+"_nuc_coloc.xls"); //next find H2AX foci per nuc selectWindow("h2ax"); rename(originalImage+":h2ax"); for(j=0; j<roiManager("count"); j++) { roiManager("select", j); run("Find Maxima...", "noise="+tolerance+" output=[Count]"); // run("Find Maxima...", "noise="+tolerance+" output=[Point Selection]"); run("Add Selection..."); } saveAs("Results", dir2+File.separator+originalImage+"_nuc_coloc_and_h2ax.xls"); //This is savign as it goes along in case it crashes selectWindow(originalImage+"h2ax"); rename("h2ax"); selectWindow(originalImage+"coloc"); rename("coloc"); selectWindow(originalImage); close(); run("Merge Channels...", "c1=PML c2=h2ax c3=nuc c4=coloc create"); rename("masks"); saveAs("TIFF", dir2+File.separator+originalImage+"_colocmasks.tif"); close(); } setBatchMode(false); } showMessage(" Well, I think we gave them a damn good thrashing there, what what??"); // macro |
Thank you for your help, I ended up modifying my code last night to get it to work and this is what I have now:
dir=getDirectory("Choose a Directory"); print(dir); greenDir=dir + "/Green/"; blueDir=dir + "/Blue/"; print(greenDir); print(blueDir); File.makeDirectory(greenDir); File.makeDirectory(blueDir); list = getFileList(dir); for (i=0; i<list.length; i++) { if (endsWith(list[i], ".tif")){ print(i + ": " + dir+list[i]); open(dir+list[i]); imgName=getTitle(); baseNameEnd=indexOf(imgName, ".tif"); baseName=substring(imgName, 0, baseNameEnd); run("Split Channels"); roiManager("Reset"); selectWindow("C1-" + imgName); run("Duplicate...", "title="); saveAs("Tiff", greenDir + "originalgreen" + baseName); selectWindow("C1-" + imgName); setAutoThreshold("Default dark"); //run("Threshold..."); //setThreshold(1, 255); setOption("BlackBackground", false); run("Convert to Mask"); run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude summarize add"); selectWindow("originalgreen" + imgName); roiManager("Show All with labels"); run("Flatten"); saveAs("Tiff", greenDir + baseName + "overlaygreen.tif"); close(); } } for (i=0; i<list.length; i++) { if (endsWith(list[i], ".tif")){ print(i + ": " + dir+list[i]); open(dir+list[i]); imgName=getTitle(); baseNameEnd=indexOf(imgName, ".tif"); baseName=substring(imgName, 0, baseNameEnd); run("Split Channels"); roiManager("Reset"); selectWindow("C2-" + imgName); run("Duplicate...", "title="); saveAs("Tiff", blueDir + "originalblue" + baseName); selectWindow("C2-" + imgName); //run("Threshold..."); //setThreshold(23, 255); setOption("BlackBackground", false); run("Convert to Mask"); run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude summarize add"); selectWindow("originalblue" + imgName); roiManager("Show All with labels"); run("Flatten"); saveAs("Tiff", blueDir + baseName + "overlayblue.tif"); run("Close All"); } } |
In reply to this post by eloiselockyer
Hi Eloise,
"I think if you write run("Duplicate...", "title=list[i]+_original"); it should work. No spaces, and you can use the list of the directory images as you loop through them." Unfortunately this suggestion leads to an image named list[i]+_original and the macro breaks down just like in the original version. Likewise run("Duplicate...", "title=imgName + 'original '"); doesn't work. Adding text strings to variables after the Duplicate command is tricky, it doesn't work like adding text strings to variables in other commands (like selectWindow(imgName + "_original"); works, for example). The absolute easiest way to rename an image duplicate with the name you want is to add rename(imgName + "original"); on the line immediately after the Duplicate command, like this: run("Duplicate...", "title="); <-- doesn't matter what title= because it will be replaced right away rename(imgName + "original"); That will get you what you want and keep your code intact. Also, if I may suggest, your strategy to strip off ".tiff" from your image name to get to the baseName variable also doesn't work as written. Replace this: baseNameEnd=indexOf(imgName, ".tif"); with this: baseNameEnd=lastIndexOf(imgName, "."); and you should be good to go. Finally, because I know someone else will suggest this, you could work with image IDs instead of image names. Every image or copy of an image has a unique ID, even if they have the same names. Something like original=getImageID(); then duplicate, then copy=getImageID(); and then later selectImage(original); or selectImage(copy); Best, Christine -------------------------------------------- Christine Labno, Ph.D. Asst. Technical Director Light Microscopy Core University of Chicago Office of Shared Research Facilities KCBD 1250 900 E. 57th St. (773) 834-9040 (phone) ________________________________________ From: ImageJ Interest Group [[hidden email]] on behalf of eloiselockyer [[hidden email]] Sent: Thursday, May 18, 2017 6:07 AM To: [hidden email] Subject: Macro to measure particles and save ROI on to original image I am trying to write an imageJ macro that will 1) Open and split an image into two channels 2) Perform particle analysis on each image and save measurements 3) Save the original image with the particle outlines overlayed So far I have realised I need to first duplicate the original image so that the ROI can later be saved on top of this. However I at the moment I can't figure out how to rename this duplicated image so I can later select it for flattening: dir=getDirectory("Choose a Directory"); print(dir); greenDir=dir + "/Green/"; blueDir=dir + "/Blue/"; print(greenDir); print(blueDir); File.makeDirectory(greenDir); File.makeDirectory(blueDir); list = getFileList(dir); for (i=0; i<list.length; i++) { if (endsWith(list[i], ".tif")){ print(i + ": " + dir+list[i]); open(dir+list[i]); imgName=getTitle(); baseNameEnd=indexOf(imgName, ".tif"); baseName=substring(imgName, 0, baseNameEnd); run("Split Channels"); selectWindow("C1-" + imgName); run("Duplicate...", "title= imgName + "original"); selectWindow("C1-" + imgName); setAutoThreshold("Default dark"); //run("Threshold..."); //setThreshold(1, 255); run("Convert to Mask"); run("Analyze Particles...", "size=60-Infinity pixel show=Outlines display exclude summarize add"); selectWindow(imgName + "original"); roiManager("Show All without labels"); run("Flatten"); saveAs("Tiff", greenDir + baseName + "green.tif"); close(); I know the error is in the run("Duplicate...", "title= imgName + "original"); line, but I don't know what's wrong with the code! -- View this message in context: http://imagej.1557.x6.nabble.com/Macro-to-measure-particles-and-save-ROI-on-to-original-image-tp5018747.html Sent from the ImageJ mailing list archive at Nabble.com. -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hello,
I'd like to make the following ImageJ feature request: Would it be possible to modify the FFT command to prompt the user and ask if it wants to apply the FFT function to each frame in a stack (as opposed to just applying the FFT to the active frame of a stack)? I have a series of time-lapse imaging data where I'd like to analyze the FFT of each frame in the stack and do some filtering there, and subsequently inverse FFT the stack back to the image domain. Hoping Wayne can work his magic! Sincerely, John Oreopoulos -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Hi John,
The Process > FFT > Bandpass Filter... and Custom Filter... can process Stacks. If you want a different filter for each frame in the stack, you currently cannot have a stack of FFT images, but you can do this a set of two macros: A first macro loops the original slices, performs the FFT transform, and copies the spectrum images in a new stack. You could then edit this stack. For invert transform, a second macro loops through the original slices again, retransform each slice, replace the FFT image with the edited version, inverse transform, and copy this result to a results stack. https://gist.github.com/mutterer/66f4b2385cef14ef1d088ad7d9070e94 https://gist.github.com/mutterer/9735d0beb1bc31f56de8ecc6e8d35995 The results are best viewed after synchronizing windows with Analyze>Tools>Synchronize Windows. Sincerely, Jerome. 2017-05-19 23:49 GMT+02:00 John Oreopoulos <[hidden email]>: > Hello, > > I'd like to make the following ImageJ feature request: Would it be > possible to modify the FFT command to prompt the user and ask if it wants > to apply the FFT function to each frame in a stack (as opposed to just > applying the FFT to the active frame of a stack)? I have a series of > time-lapse imaging data where I'd like to analyze the FFT of each frame in > the stack and do some filtering there, and subsequently inverse FFT the > stack back to the image domain. Hoping Wayne can work his magic! > > Sincerely, > > John Oreopoulos > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html > -- Jerome Mutterer CNRS - Institut de biologie moléculaire des plantes 12, rue du Général Zimmer 67084 Strasbourg Cedex www.ibmp.cnrs.fr -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
In reply to this post by John Oreopoulos
> On May 19, 2017, at 5:49 PM, John Oreopoulos <[hidden email]> wrote:
> > Hello, > > I'd like to make the following ImageJ feature request: Would it be possible to modify the FFT command to prompt the user and ask if it wants to apply the FFT function to each frame in a stack (as opposed to just applying the FFT to the active frame of a stack)? I have a series of time-lapse imaging data where I'd like to analyze the FFT of each frame in the stack and do some filtering there, and subsequently inverse FFT the stack back to the image domain. Hoping Wayne can work his magic! Upgrade to the latest daily build (1.51o20) and you can use simple macros to do FFTs and Inverse FFTs on the images in a stack. I included two macros. The first runs the “FFT” command on the images in the T1 Head sample stack, saving the output in a virtual stack. The second runs the “Inverse FFT” command on the virtual stack. You will need to modify the second line of the first macro so that ‘dir’ points to an empty folder. -wayne macro "Stack FFT" { requires("1.51o"); dir = "/Users/wayne/Downloads/FFT_Stack/"; setBatchMode(true); run("T1 Head (2.4M, 16-bits)"); for (i=1; i<=nSlices; i++) { setSlice(i); run("FFT"); saveAs("TIFF", dir+"FFT of "+IJ.pad(i,4)); close; } run("Image Sequence...", "open=&dir sort use"); setBatchMode(false); } macro "Stack Inverse FFT" { stack = getImageID; setBatchMode(true); setSlice(2); n = nSlices; for (i=1; i<=n; i++) { selectImage(stack); setSlice(i); run("Inverse FFT"); } run("Images to Stack", "title=[Inverse FFT] use"); setBatchMode(false); } -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Much thanks as usual!
John Oreopoulos On May 22, 2017, at 10:45 PM, Wayne Rasband <[hidden email]> wrote: >> On May 19, 2017, at 5:49 PM, John Oreopoulos <[hidden email]> wrote: >> >> Hello, >> >> I'd like to make the following ImageJ feature request: Would it be possible to modify the FFT command to prompt the user and ask if it wants to apply the FFT function to each frame in a stack (as opposed to just applying the FFT to the active frame of a stack)? I have a series of time-lapse imaging data where I'd like to analyze the FFT of each frame in the stack and do some filtering there, and subsequently inverse FFT the stack back to the image domain. Hoping Wayne can work his magic! > > Upgrade to the latest daily build (1.51o20) and you can use simple macros to do FFTs and Inverse FFTs on the images in a stack. I included two macros. The first runs the “FFT” command on the images in the T1 Head sample stack, saving the output in a virtual stack. The second runs the “Inverse FFT” command on the virtual stack. You will need to modify the second line of the first macro so that ‘dir’ points to an empty folder. > > -wayne > > macro "Stack FFT" { > requires("1.51o"); > dir = "/Users/wayne/Downloads/FFT_Stack/"; > setBatchMode(true); > run("T1 Head (2.4M, 16-bits)"); > for (i=1; i<=nSlices; i++) { > setSlice(i); > run("FFT"); > saveAs("TIFF", dir+"FFT of "+IJ.pad(i,4)); > close; > } > run("Image Sequence...", "open=&dir sort use"); > setBatchMode(false); > } > > macro "Stack Inverse FFT" { > stack = getImageID; > setBatchMode(true); > setSlice(2); > n = nSlices; > for (i=1; i<=n; i++) { > selectImage(stack); > setSlice(i); > run("Inverse FFT"); > } > run("Images to Stack", "title=[Inverse FFT] use"); > setBatchMode(false); > } > > -- > ImageJ mailing list: http://imagej.nih.gov/ij/list.html -- ImageJ mailing list: http://imagej.nih.gov/ij/list.html |
Free forum by Nabble | Edit this page |