// Michael Cammer; Michael Dustin laboratory at Skirball at NYU Medical Dec 2011 // These macros were written specifically for Catarina Sacristan's multi-field timelapse experiments // on the Nikon TIRF microscope run by Elements software with files saved in .nd2 format. // The files are imported using LOCI BioFormats importer with all series selected and channels split. var clipsize = 150; // edge size of the box for clipping cells for montage var snipwindow = -1; var projectiondepth = 15; function checkCurrentVersion(){ requires('1.46a'); } //========================================================================== // User needs to change path and name is the last line of code. This could be made more user friendly by // prompting user to choose directory and click the "Select" button. // User should change this to delete # of characters from beginning of filename. It is used here to get rid of // redundant filenames. Set to zero or remark out to do nothing. //========================================================================== macro "Rename Open WIndows and Save All" { n = nImages(); for (i=1; i<=n; i++) { selectImage(i); run("Canvas Size...", "width=600 height=600 position=Center zero"); // save // close() } } //=============================================================================== macro "pad windows and save" { n = nImages(); for (i=1; i<=n; i++) { selectImage(i); a = getTitle(); a = replace(a, ".nd2", ""); // delete the .nd2 extension // The next line of code has to be edited manually for each file! a = substring(a, 6); // <=============== rename(a); saveAs("Tiff", "D:\\Catarina Sacristán\\20111214 LCMV Cl13 d7 P14 CD8 GFP 12_14_11 CSR\\"+a+".tif"); } //=============================================================================== // Use: Open .nd2 file which is a multi-channel multi-field time lapse. This will select from these fields either // projections or single timepoints. // The purpose of this macro is to extract all the nth //=============================================================================== macro "Extract or otherwise process all open .nd2 stacks [q]" { // function convertProjectedImagesToStacks(); // use this or extract as first command extract_all_nth_timepoints(2); close_all_nonM_windows(); convertProjectedImagesToStacks(); // additional processing!!! n = nImages(); for (i=1; i<=n; i++) { selectImage(i); run("Bandpass Filter...", "filter_large=160 filter_small=0 suppress=None tolerance=5 process"); } } //=========================================================================== // 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. //=========================================================================== function projectAllOpenStacks(){ n = nImages(); for (i=1; i<=n; i++) { selectImage(i); // run("Bandpass Filter...", "filter_large=200 filter_small=1 suppress=None tolerance=0"); 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]"); } // for i } //=============================================================================== // Extracts from a timelapse or Z stack the nth slice only. //=============================================================================== function extract_all_nth_timepoints(extract) { // extract is an integer between 1 and nSlices n = nImages(); for (i=1; i<=n; i++) { selectImage(i); setSlice(extract); title = "M" + extract + "_" + getTitle; run("Duplicate...", "title="+title); rename(title); } // for i } macro "Extract All First Timepoints"{ extract_all_nth_timepoints(1); } macro "Extract All 2nd Timepoints"{ extract_all_nth_timepoints(2); } macro "Extract All 5th Timepoints"{ extract_all_nth_timepoints(5); } //=============================================================================== // Extracted or projected files begin with the letter "M". As long as the original files do not have titles that // begin with the letter "M", all original stacks are removed and only the extracted files remain. //=============================================================================== function close_all_nonM_windows() { for (i=nImages(); i>0; i--) { selectImage(i); if (!( startsWith(getTitle(), "M") ) ) close(); } // for i } // end function close_all_non-M_windows(); function convertProjectedImagesToStacks() { run("Images to Stack", "name=Stack title=C=0 use"); rename("GFP"); run("Images to Stack", "name=Stack title=C=1 use"); rename("PDL1"); run("Images to Stack", "name=Stack title=C=2 use"); rename("reflection"); run("Images to Stack", "name=Stack title=C=3 use"); rename("ICAM"); } // end function convertProjectedImagesToStacks(); //============================================================================ // This macro was written for Hila who has a series of nd2 files of fixed stained material. // Each file consists of n channels. They are all imported with channels split and this macro // copies them into stacks. macro "sort open files of split channels into stacks using name C=#" { t = replace(getTitle(), " ", "_"); t = substring(t, 0, (indexOf(t, "nd2"))); t = replace(t, "\\.", ""); run("Images to Stack", "name="+t+"_C=0 title=C=0 use"); run("Images to Stack", "name="+t+"_C=1 title=C=1 use"); run("Images to Stack", "name="+t+"_C=2 title=C=2 use"); run("Images to Stack", "name="+t+"_C=3 title=C=3 use"); run("Images to Stack", "name="+t+"_C=4 title=C=4 use"); run("Images to Stack", "name="+t+"_C=5 title=C=5 use"); run("Images to Stack", "name="+t+"_C=6 title=C=6 use"); run("Images to Stack", "name="+t+"_C=7 title=C=7 use"); run("Images to Stack", "name="+t+"_C=8 title=C=8 use"); run("Images to Stack", "name="+t+"_C=9 title=C=9 use"); run("Images to Stack", "name="+t+"_C=10 title=C=10 use"); } //======================== //============================================================================ // macro "RENAME C=#" { n = nImages(); for (i=1; i<=n; i++) { selectImage(i); t = replace(getTitle, " ", "_"); t = replace(t, "\\.nd2", ""); t = replace(t, "\\.tif", ""); t = replace(t, "C=0", "ICAM red"); t = replace(t, "C=1", "gp120 green"); t = replace(t, "C=2", "anti-CD3 blue"); t = replace(t, "C=3", "reflection"); t = replace(t, "C=4", "trans"); rename(t); } // i } //======================== //============================================================================ // macro "MAKE ALL RGB" { n = nImages(); for (i=1; i<=n; i++) { selectImage(i); run("RGB Color"); } // 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]"); } //============================================================================= // Modified 20121001 for composite color hyperstacks. // calls function clipCellAndPopOnStack(original, clipstack); // macro "clip all ROIs in Roi Manager, center, and put in stack for montage [F4]" { if (! Stack.isHyperstack) exit('Expecting a hyperstack'); original = getImageID; Stack.getDimensions(width, height, channels, slices, frames); Stack.getDisplayMode(displaymode); Stack.getActiveChannels(activechannel); 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"); clipstackID=newArray(channels); clipstackTitle=newArray(channels); for (c=1; c<=channels; c++){ setBatchMode(true); newImage("snippedstack "+ t + " C=" + c, bitstring+" Black", clipsize, clipsize, 1); clipstackTitle[c-1] = getTitle(); clipstackID[c-1] = getImageID; for (i=0; i 10) { // if cell footprint is bigger than 10 um^2 run("Enlarge...", "enlarge=1 pixel"); run("Make Band...", "band=1"); run("Measure"); bandMean=getResult("Mean", nResults-1); //print(cellMean / bandMean); if (cellMean / bandMean > 1.10) { // This is the amount over bg the cell needs to be to be considered positive ICAMrois[i] = i; //run("Draw"); } // if cellmean } // if selectionarea else { countSmallCells++; } // else i++; } // while print(countSmallCells+" cells too small (less than 10^2)."); //print(roiCount+" cells considered ICAM positive."); positiveCount=0; for (i=0; i 0) { roiManager("select", i); positiveCount++; } // if } // for print (positiveCount+" cells considered positive."); print (""); selectWindow("Log"); } // end "Count cells by center brighter than edges" //========================================================= function closeWindowsNotInterestedIn() { n = nImages(); for (i=1; i<=n; i++) { selectImage(i); if ( !(endsWith(getTitle(), "C=2")) ) // use not and the title feature you want to keep run("Close"); } // end function closeWindowsNotInterestedIn() //========================================================= macro "Process movies for timelapse analysis"{ open the full .nd2 file //eliminate all stacks except the channels used for cell extraction closeWindowsNotInterestedIn(); for each reflection stack: cover up the black edges //fft 255-0 twice run("Bandpass Filter...", "filter_large=200 filter_small=0 suppress=None tolerance=0"); maybe smooth? linear contrast if necessary threshold huang make binary save for Imaris or later ImageJ In Imaris, have tracks made then manually eliminate touching cells This involves opening each movie. } // end Process movies for timelapse analysis //===================================================================================== // Timelapse macros v115 November 2011 // Macro for ImageJ by Michael Cammer michael@coxcammer.com // A roundish (or circular, but with pixel edges, not vectors) ROI is drawn on a timelapse stack such that the // center of the circle is the centroid of the feature to be measured over time and that the entire object at every // time is contained within the perimeter. // Then radii spaced by step size perimeter / n step around and are resampled in the time axis // and pasted into a new window. // After I wrote this, somebody posted a similar plugin version at http://rsbweb.nih.gov/ij/plugins/radial-reslice/ // This macro produces radial reslices from the center out. The original version of this reslicing went from the // periphery such that the alignment was along the traced outer edge and could be used for the annuluar // intensity and spatial distribution in relation to the outer edge of spreading cells instead of in relation to the center // and some slices never even went to the very center. //===================================================================================== macro"Radial Sweep as a circle"{ requires("1.45m"); run("Set Scale...", "distance=1 known=1 pixel=1 unit=px"); number_of_radii = 360; // number of pixels on perimeter of circle to be sampled. run("Set Measurements...", " centroid redirect=None decimal=0"); run("Measure"); xc = getResult("X", nResults-1); yc = getResult("Y", nResults-1); selectWindow("Results"); run("Close"); slices = nSlices(); step = 2 * PI / number_of_radii; extrasteps = 16; // allows for overshooting to adjust for when slices are projected together maxradius = 5 + round(calculateMaximumRadius()/2); // this is to find the longest radius to make a new window this width or to rescale the shorter lines this length original = getImageID(); originaltitle = getTitle(); bits = bitDepth(); newtitle = "reslice_"+originaltitle+""; newslices = 1+ number_of_radii + extrasteps; newbits = "" + bits + "-bit Black"; newImage(newtitle, newbits, maxradius, slices, newslices); stream = getImageID(); setBatchMode(true); setPasteMode("Copy"); s=1; for (i=0; i<2*PI+(step*extrasteps); i=i+step) { edgex = xc + maxradius * sin(i); edgey = yc + maxradius * cos(i); selectImage(original); makeLine(xc, yc, edgex, edgey); run("Reslice [/]...", "input=1.000 output=1.000 start=Top"); run("Select All"); run("Copy"); run("Close"); selectImage(stream); setSlice(s); s++; run("Paste"); } //for i setBatchMode(false); resetMinAndMax(); //projectStackVariableWidth("Max Intensity", 4); } //macro("Radial Sweep") //========================================================= // This function is required by the macro "Diameter Sweep" to calculate the // longest possible radius if the selection is non-circular. // Uses Feret's diameter. function calculateMaximumRadius (){ run("Clear Results"); run("Set Measurements...", " mean feret's redirect=None decimal=3"); run("Measure"); diameter = getResult("Feret",(0)); selectWindow("Results"); run("Close"); return (diameter); } // function calculateMaximumRadius //----------------------------------------------- macro 'Multiply to fix bleaching based on ROI'{ //checkCurrentVersion(); original = getImageID(); run("Set Measurements...", " mean redirect=None decimal=0"); run("Plot Z-axis Profile"); run("Close"); standard = getResult("Mean",(0)); selectImage(original); for (i=1; i<=nSlices; i++){ bgmean = standard / getResult("Mean",(i-1)); run("Set Slice...", "slice="+i); run("Select All"); run("Multiply...", "slice value="+bgmean); } // for run("Select None"); selectWindow("Results"); run("Close"); } // macro 'Multiply to fix bleaching based on ROI' //--------------------------------------------------------- //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=5"); run("Plot Z-axis Profile"); run("Close"); selectImage(image_to_process); 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 //========================================================= macro "RGB merge adjacent slices into a new stack"{ //checkCurrentVersion(); setPasteMode("Copy"); original = getImageID(); selectImage(original); slices = nSlices()-2; for (i=1;i<=slices;i++) { selectImage(original); run("Set Slice...", "slice="+i); run("Select All"); run("Duplicate...", "title=[A]"); selectImage(original); run("Set Slice...", "slice="+(i+1)); run("Select All"); run("Duplicate...", "title=[B]"); selectImage(original); run("Set Slice...", "slice="+(i+2)); run("Select All"); run("Duplicate...", "title=[C]"); run("RGB Merge...", "red=[A] green=[B] blue=[C]"); if (i == 1) { newrgb = getImageID(); } else { run("Select All"); run("Copy"); close(); selectImage(newrgb); run("Add Slice"); run("Paste"); } } //for i selectImage(original); run("Set Slice...", "slice="+nSlices); run("Delete Slice"); run("Set Slice...", "slice="+1); run("Delete Slice"); run("Brightness/Contrast..."); selectImage(newrgb); run("Select None"); exit(); } //RGB merge adjacent slices into a new stack //================================================================= macro "paste with subtract adjacent slices"{ checkCurrentVersion(); original = getImageID(); selectImage(original); setPasteMode("Subtract"); for (i=2;i<=nSlices;i++) { run("Set Slice...", "slice="+i); run("Select All"); run("Copy"); run("Set Slice...", "slice="+(i-1)); run("Paste"); } selectImage(original); run("Select None"); run("Set Slice...", "slice="+nSlices); run("Delete Slice"); run("Set Slice...", "slice="+1); run("Delete Slice"); run("Brightness/Contrast..."); } // end "paste with subtract adjacent slices" //================================================================== macro "Remove Outliers and AVG Projection of variable width"{ checkCurrentVersion(); projectiondepth = 5; 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 = projection; zdepth = Dialog.getNumber(); run("Remove Outliers...", "radius=1 threshold=0 which=Bright stack"); run("Remove Outliers...", "radius=1 threshold=0 which=Bright stack"); projectStackVariableWidth(projection, zdepth); } // Projections of variable width //================================================================== macro "Projections of variable width"{ checkCurrentVersion(); 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 = projection; zdepth = Dialog.getNumber(); projectStackVariableWidth(projection, zdepth); } // Projections of variable width //================================================================== function projectStackVariableWidth(projtype, zdepth) { setBatchMode(true); setPasteMode("Copy"); original = getImageID(); end = nSlices(); for (i=1;i<(end-zdepth+2);i++){ stop = i + zdepth; run("Z Project...", "start="+i+" stop="+stop+" projection=["+projtype+"]"); run("Select All"); run("Copy"); run("Close"); selectImage(original); run("Set Slice...", "slice="+i); run("Paste"); } setBatchMode(false); run("Select None"); } // end projectStackVariableWidth() //X================================================X macro "measure mean intensity above threshold [q]" { // only works on 8 and 16 bit images for (s=1; s<=nSlices; s++){ setSlice(s); histogramAboveThreshold(1.01); } } function histogramAboveThreshold(threshold) { getHistogram(values, a, 256); counts = 0; sum = 0; for (i=threshold; i