/* Michael Cammer mcammer@gmail.com cammem01@nyumc.org Macros for ImageJ Java 1.8 This collection of macros are the ones I like to have on hand most of the time. More at http://microscopynotes.com/imagej/index.html 20180411 In subtract BG in ROI macro, with IJ 1.51 PlotProfile no longer send results to the Results window so rewritten with a measurements loop. */ var clipsize = 150; // edge size of the box for clipping cells for montage var snipwindow = -1; var projectiondepth = 2; // default depth for projection of variable depth var tab = " \t"; /* ============================================================= Should be updated each time macros are edited */ function checkCurrentVersion() { requires('1.52f'); } /* ============================================================= Standard ImageJ allows for installing macros from the macro editor text window by typing ctrl i. Fiji does not. Therefore, to easily update macros in Fiji, change the path of the current macro file being edited in this macro and use ctrl s followed by F4 to reinstall the macros from the Fiji text editor. */ macro "Install Macros [F4]" { run("Install...", "install=D:\\20171214\\Macro.txt"); } /* ============================================================ */ macro "interleave stacks" { getVoxelSize(width, height, depth, unit); s1 = getImageID; s1title = getTitleStripExtension(); run("Duplicate...", "title=tempstack duplicate"); projectStackVariableWidth("Average Intensity", 2); s2 = getImageID; s2title = getTitle; setSlice(nSlices); run("Delete Slice"); setPasteMode("Copy"); selectImage(s1); s1length = nSlices; for (i=s1length-1; i>0; i--) { selectImage(s2); setSlice(nSlices); run("Select All"); run("Copy"); if (nSlices > 1) run("Delete Slice"); else close(); selectImage(s1); setSlice(i); run("Add Slice"); run("Paste"); } selectImage(s1); newTitle = "" + s1title + "_interpolated"; rename(newTitle); run("Select None"); setVoxelSize(width, height, depth/2, unit); } //================================================================== /* Version edited 20161002 corrects the global variable projectiondepth getting set to NaN. It is now set correctly to the zdepth entered by the user to be recycled the next time the macro is run. A global could also be added for projection type. */ macro "Projections of variable width"{ projtypes = newArray("Max Intensity", "Average Intensity", "Standard Deviation", "Min Intensity", "Median"); Dialog.create("Projections of variable width"); Dialog.addMessage("Each slice of the stack is replaced with a projection of the depth\ndefined."); Dialog.addChoice("Label", projtypes, "Average Intensity"); Dialog.addNumber("Slices to project: ", projectiondepth); Dialog.show(); projection = Dialog.getChoice(); projectiondepth = Dialog.getNumber(); projectStackVariableWidth(projection, projectiondepth); } // Projections of variable width //================================================================== /* Version edited 20161002 corrects the number of slices projected. Previous versions did zdepth+1 slices. Also projects maximum number available. Previous version stopped one short of the end. Also, the slices out to the end are projected at progressively shorter depths. */ function projectStackVariableWidth(projtype, zdepth) { setBatchMode(true); setPasteMode("Copy"); original = getImageID(); end = nSlices(); for (i=1; i1) || (frames>1) ) exit("Only works for single Z, time, or position images.\nAsk for modification if you need implemented."); if ( (slices > 1) || (frames > 1) ) exit("Requires single Z and single timepoint image"); if (channels < 2) exit("Requires composite color image."); title = getTitleStripExtension(); if (channels < 2) exit("Not a composite image with 2 or more channels."); if (channels == 2) { montageX=3; montageY=1; } if (channels == 3) { Dialog.create("get montage info"); //Dialog.addMessage(); Dialog.create("Radio Buttons"); items = newArray("One row of four panels", "2 X 2 panels"); Dialog.addRadioButtonGroup("Three channels will result in four panels.\nClick which layout preferred.", items, 2, 1, ""); Dialog.show; if ( Dialog.getRadioButton == "One row of four panels") { montageX=4; montageY=1; } else { montageX=2; montageY=2; } } if ((channels==4) || (channels==5)) { Dialog.create("get montage info"); Dialog.create("Radio Buttons"); items = newArray("One row of panels", "3 X 2 panels"); Dialog.addRadioButtonGroup("Click which layout preferred.", items, 2, 1, ""); Dialog.show; if ( Dialog.getRadioButton == "One row of panels") { montageX=channels+1; montageY=1; } else { montageX=3; montageY=2; } } if (channels > 5) exit("Not programmed for more than 5 channels; ask for modification if you need this."); simpleMergeAndMontage (title, montageX, montageY); } /* ========================================= This function does the work for Simple merge as is. It takes a number of arguments. title = text Title of the image, will have montage added to it. montageX = integer How many columns in montage. montageY = integer How many rows in montage. To be implemented in future: grayscale = true/false To be coded someday. This directs the function whether to use LUTs as is or make individual panels in grayscale. */ function simpleMergeAndMontage (title, montageX, montageY) { run("Duplicate...", "duplicate"); rename(title); original = getImageID; run("RGB Color"); // This should make a new window run("Select All"); run("Copy"); setPasteMode("Copy"); close(); selectImage(original); Stack.setDisplayMode("color"); run("RGB Color"); run("Hyperstack to Stack"); setSlice(nSlices); run("Add Slice"); run("Paste"); run("Scale Bar...", "width=10 height=4 font=14 color=[White] background=None location=[Lower Right] bold"); run("Colors...", "foreground=white background=black selection=yellow"); if ((nSlices==5) & (montageY == 2)) { // Make the last panel white if 3 x 2 with only five panels. run("Add Slice"); run("Select All"); run("Fill", "slice"); } run("Select None"); run("Make Montage...", "columns="+montageX+" rows="+montageY+" scale=1 border=2 use"); rename(title+"_montage"); close(title); close(title+" (RGB)"); //Following steps copy the result to the system clipboard for pasting into another application. Only tested on win7. run("Select All"); run("Copy to System"); run("Select None"); } //=========================================================================== macro "Change Values (works on stacks)"{ // as implemented, does not work on multichannel hyperstacks for individual channels run("32-bit"); for (i=1; i<=nSlices(); i++){ setSlice(i); changeValues(0,128,NaN); } } //=========================================================================== // This macro takes all open stacks and projects them. Depending on the filename, in this case // "C=#", the projection method may be different. The projection command automatically names // the new windows with the type of projection followed by the original filename. //=========================================================================== macro "Project all open stacks" { projectAllOpenStacks(); } // "Project all open stacks" function projectAllOpenStacks(){ n = nImages(); for (i=1; i<=n; i++) { selectImage(i); t = getTitleStripExtension(); if ( endsWith(getTitle(), "C=2") ) run("Z Project...", "start=1 stop="+nSlices+" projection=[Min Intensity]"); else run("Z Project...", "start=1 stop="+nSlices+" projection=[Max Intensity]"); rename(t+"_proj"); } // for i } // end projectAllOpenStacks() //=============================================================================== // Extracts the nth slice from a timelapse or Z stack. //=============================================================================== macro "Extract nth slices from stacks" { extract_all_nth_timepoints(2); // change the number in this command to the required slice } function extract_all_nth_timepoints(extract) { // extract is an integer between 1 and nSlices n = nImages(); for (i=1; i<=n; i++) { selectImage(i); t = getTitleStripExtension(); setSlice(extract); title = "M" + extract + "_" + getTitle; run("Duplicate...", "title="+title); rename(t+"_s" + extract); } // for i } macro "=========================="{} //============================================================== // This is for when you already have color images. //macro "box location" { // getCursorLoc(x, y, z, mousestate); // makeRectangle(x-(boxsize/2),y-(boxsize/2), boxsize, boxsize); //} macro "Make snipping box" { makeRectangle(10,10, clipsize, clipsize); } //============================================================== macro "snip out the box [F5]" { roiManager("Add"); run("Duplicate...", "title=[snip]"); } //============================================================================= // calls function clipCellAndPopOnStack(original, clipstack); // macro "clip all ROIs in Roi Manager, center, and put in stack for montage" { original = getImageID; t = getTitle; bits = bitDepth(); if (bits == 24) bitstring="RGB"; else bitstring = ""+bits+"-bit"; clipsize = getNumber("Enter side of square box in pixels: ", clipsize); setPasteMode("Copy"); setBatchMode(true); newImage("snippedstack "+ t, bitstring+" Black", clipsize, clipsize, 1); clipstack = getImageID; for (i=0; i maxMean) maxMean = means[i-1]; } // for i measuring run("Select All"); for (i=1; i<=nSlices; i++){ run("Set Slice...", "slice="+i); factor = maxMean / means[i-1]; run("Multiply...", "slice value="+factor); } // for i multiplying run("Select None"); selectWindow("Results"); run("Close"); } // macro 'Multiply to fix bleaching based on ROI' //================================================================ // See http://microscopynotes.com/imagej/float/ for explanation. // originally by Kenton Arkill [underwaterginge@GMAIL.COM] // Floating means that each image has the same mean pixel value and the same standard deviation. // I find it really useful as it means the same threshold can often be used on all the images. Here is my macro, // it floats the stack to the values of the first slice (so make sure it is a good image): // macro "Float the stack"{ run("32-bit"); setSlice(1); getRawStatistics(nPixels, meanref, min, max, stdref, histogram); for (i = 1; i <= nSlices; i++) { setSlice(i); getRawStatistics(nPixels, meani, min, max, stdi, histogram); run("Subtract...", "value="+meani+" slice"); run("Divide...", "value="+stdi+" slice"); run("Multiply...", "value="+stdref+" slice"); run("Add...", "value="+stdref+" slice"); } run("Enhance Contrast", "saturated=0.35"); setSlice(1); } //=================================================================== // This macro measures the same region of interest in each slice of a stack and subtracts the mean plus // specified standard deviation of the mean from each corresponding slice. It is useful for situations where // there is background intensity changing over time due to something like a flickering light source and you // want the stack's background to be uniform. It may not be appropriate for situations where precise intensity // measurements will be made that should be uniform through the stack. Subtracting one constant from the // entire stack is likely better. // To use, put a ROI over a region that is background in all slices. (Choose the ROI on a maximum pixel // projection if features to assure only bg pixels are included.) Run the macro. // macro 'Subtract background based on ROI'{ n = 0; // this is the number of standard deviations to add to the mean bg to subtract checkCurrentVersion(); image_to_process = getImageID(); run("Set Measurements...", " mean standard redirect=None decimal=2"); // run("Plot Z-axis Profile"); // With IJ 1.51 this command no longer send results to the Results window so rewritten with a measurements loop here. // run("Close"); // selectImage(image_to_process); run("Measure"); run("Clear Results"); for (i=1; i<=nSlices; i++){ run("Measure"); } // for loop run("Select All"); for (i=1; i<=nSlices; i++){ bgmean=getResult("Mean",(i-1)) + n*getResult("StdDev",(i-1)); run("Set Slice...", "slice="+i); run("Subtract...", "slice value="+bgmean); } // for loop run("Select None"); run("Min...", "value=0 stack"); resetMinAndMax(); } // Subtract background based on ROI //================================================================ //This macro is for drawing a ROI onto a range of serial slices of a stack. //1. Draw the ROI. //2. Add it to the manager (ctrl-t). //3. Choose the color using Edit>Options>Colors... //4. Run this macro. // macro 'draw ROI on range of slices in stack'{ checkCurrentVersion(); image_to_process = getImageID(); Dialog.create("draw on slices..."); Dialog.addNumber("first slice to draw on", 1); Dialog.addNumber("last slice to draw on", nSlices()); Dialog.show(); first = Dialog.getNumber(); last = Dialog.getNumber(); if (last < first) { temp=first; first=last; last=temp; } if (first < 1) exit("first slice must be 1 or greater"); if (last > nSlices()) exit("last slice must be the stack size or smaller"); n = roiManager("count"); // get the last ROI in the manager selectImage(image_to_process); roiManager('select', n-1); for (i=first; i<=last; i++){ setSlice(i); run("Draw", "slice"); } // for loop run("Select None"); resetMinAndMax(); } // draw ROI on range of slices in stack /* This macro requires a grayscale stack any bit depth as input. It duplicates this stack twice, thus requiring sufficient RAM. The output is 8 bit per channel RGB. */ macro "RGB merge adjacent slices into a new stack"{ //checkCurrentVersion(); original = getImageID(); t = getTitleStripExtension(); run("Select None"); rename("red"); run("Duplicate...", "title=green duplicate"); setSlice(1); run("Select All"); run("Copy"); run("Add Slice"); run("Paste"); run("Set...", "value=0 slice"); run("Select None"); run("Duplicate...", "title=blue duplicate"); run("Add Slice"); selectWindow("red"); setSlice(nSlices); run("Add Slice"); run("Add Slice"); selectWindow("green"); setSlice(nSlices); run("Add Slice"); run("Merge Channels...", "c1=red c2=green c3=blue"); rename(t+"_runRGB"); } //RGB merge adjacent slices into a new stack //================================================================== /* This macro is for making a movie of a stack that loops, especially useful for animated GIFs of 3D projections that rock back and forth. Downside: doubles the size of the stack. */ macro "Loop stack" { t = getTitle(); run("Duplicate...", "title=xyztemp duplicate"); run("Reverse"); run("Concatenate...", " title="+t+"_3D image1=["+t+"] image2=[xyztemp] image3=[-- None --]"); } macro "make test stack for Projections of variable width" { size = 25; slices = 50; width = 256; newImage("Untitled", "8-bit black", width, width, slices); setColor(255, 255, 255); for (i=1; i= (1/ratio) ) { newWidth = w + (border * w); newHeight = newWidth * ratio; } else { newHeight = h + (border * h); newWidth = newHeight / ratio; } run("Colors...", "foreground=black background=white selection=yellow"); run("Canvas Size...", "width="+newWidth+" height="+newHeight+" position=Center"); } /* =============================================== A future version would have an if statement to check image type and also work on composite images. */ macro "EQ each channel of RGB image" { path = getDirectory("image"); run("RGB Stack"); setSlice(1); run("Enhance Contrast...", "saturated=0 equalize"); setSlice(2); run("Enhance Contrast...", "saturated=0 equalize"); setSlice(3); run("Enhance Contrast...", "saturated=0 equalize"); run("RGB Color"); title = "eq_" + getTitle(); rename(title); // save the new image run("Input/Output...", "jpeg=100 gif=-1 file=.txt use_file copy_column copy_row save_column save_row"); saveAs("Jpeg", path + title); }