/* 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 = 16; // 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"); } /* ============================================================= After some operations the colors and mode are set wrong. This macro corrects the colors and sets composite mode. */ macro "Correct multichannel image colors" { colorLUT = newArray("Grays", "Blue", "Red"); for (i=1; i<=colorLUT.length; i++) { Stack.setChannel(i); run(colorLUT[i-1]); } Stack.setDisplayMode("composite"); run("Channels Tool..."); //Stack.setActiveChannels("011"); } /* ============================================================= Reports a line profile plot of three channels. Expected input is a multicahnnel image with 3 or more channels. */ macro "show multichannel plot profiles" { // add command to error check for line ROI t = getTitleStripExtension(); original = getImageID; // IR selectImage(original); Stack.setChannel(1); run("Plot Profile"); Plot.getLimits(xMin, xMax, yMin, yMax); Plot.setLimits(xMin, xMax, 0, 255); rename("IRplot"); // Red selectImage(original); Stack.setChannel(2); run("Plot Profile"); Plot.getLimits(xMin, xMax, yMin, yMax); Plot.setLimits(xMin, xMax, 0, 255); rename("redplot"); // Green selectImage(original); Stack.setChannel(3); run("Plot Profile"); Plot.getLimits(xMin, xMax, yMin, yMax); Plot.setLimits(xMin, xMax, 0, 255); rename("greenplot"); run("Merge Channels...", "c1=redplot c2=greenplot c3=IRplot create"); run("Invert"); rename("tempplot"); run("RGB Color"); rename(t + "_plot"); close("temp*"); } /* ============================================================= Report intensities of two channels based on thresholded segmentation of objects. These intensity values are only valid when the labeling is known to describe the biology. For instance, where ability to diffuse and incubation times change the labeling intensity, this is not a useful tool for measuring # of molecules. The Pearson's correlation may, however, be valid, because the locations of the probes are far more important than the absolute intensities which are are always rescaled from min to max. The two channels to be measured are contrast enhanced and max combined before the thresholding is applied. Also, the segmentated areas may have Pearson's correlation done. In the first version, size range is set to 2 to 25 um^2 and roundness to 0.4 or greater. These may be changed. */ macro "measure segmented objects in two channels" { chA = 2; // Sets the first channel to be measured. chB = 3; // original = getImageID; run("Select None"); run("Duplicate...", "title=tempA duplicate channels="+chA); run("Subtract Background...", "rolling=25"); run("Enhance Contrast...", "saturated=0.1 normalize"); selectImage(original); run("Duplicate...", "title=tempB duplicate channels="+chB); run("Subtract Background...", "rolling=25"); run("Enhance Contrast...", "saturated=0.1 normalize"); imageCalculator("Max create", "tempA","tempB"); rename("tempC"); run("Threshold..."); setAutoThreshold("Default dark"); waitForUser("Tweak threshold and click OK in this window."); roiManager("reset"); run("Set Measurements...", "area mean shape redirect=None decimal=3"); run("Clear Results"); run("Analyze Particles...", "size=2-25 circularity=0.40-1.00 exclude include add"); roiManager("Remove Channel Info"); roiManager("Remove Slice Info"); roiManager("Remove Frame Info"); run("Clear Results"); selectImage(original); Stack.setChannel(chA); roiManager("Measure"); chAmean = newArray(nResults); for (i=0; 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; iOptions>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 --]"); } //================================================================== /* 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, "Max 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; 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); }