//////////////////////////////////////////////////////////////// /* PIPSQUEAK! Perineuronal net Intensity Program for the Standardization and Quantification of ECM Analysis Written by John H. Harkness, PhD. >>> Contact: harknessjh@gmail.com >>> Copyright (C) 2016, John H. Harkness Washington State University, Vancouver Supported by: >>> Rewire Neuroscience (rewireneuroscience.com) >>> WSU Alcohol and Drug Abuse Research Program (ADARP) >>> The Translational Addiction Research Center (TARC) >>> NIH DA 033404 >>> Washington State Initiative Measure No. 171 Protocol based on Slaker, Harkness, and Sorg, 2016 >>> Special thanks to Megan Slaker, PhD >>> PLEASE CITE: Slaker, et al., 2016 (IN SUBMISSION) <<< */ //////////////////////////////////////////////////////////////// /* For recurring tasks, you can define your own functions: function closeImageByTitle(title) { selectWindow(title); close(); } Note that the title is just another variable, which is implicitly assigned when the function is called. In other words, this call will execute the code in above definition, with the variable title set to My pretty new image: closeImageByTitle("My pretty new image"); */ //Global variables var scale_size = 1.194; var scale_known = 1; var scale_pixel = 1; var scale_unit = "um"; var set_intensity_low_threshold = 1.165; var set_intensity_high_threshold = 5000; var set_low_particlesize = 70; var set_high_particlesize = 9999999; var set_low_circularity = 0.02; var set_high_circularity = 1.00; var set_count_low_threshold = 0.5; var set_count_high_threshold = 5000; var set_count_low_particlesize = 20; var set_count_high_particlesize = 9999999; var set_count_low_circularity = 0.02; var set_count_high_circularity = 1.00; var first_image = 0; var second_image = 0; var series_name = 0; var first_suffix = 1; var second_suffix = 3; var total_images = 3; var first_stain_type = "PV"; var DL1_set_intensity_low_threshold = 1.0; var DL1_set_intensity_high_threshold = 5000; var DL1_set_low_particlesize = 40; var DL1_set_high_particlesize = 1000; var DL1_set_low_circularity = 0.02; var DL1_set_high_circularity = 1.00; var second_stain_type = "WFA"; var DL2_set_intensity_low_threshold = 1.165; var DL2_set_intensity_high_threshold = 5000; var DL2_set_low_particlesize = 70; var DL2_set_high_particlesize = 999999; var DL2_set_low_circularity = 0.02; var DL2_set_high_circularity = 1.00; var lower = 0; var import_type = 0; var first_open = 0; var last_open = 0; var name = 0; var full_name = 0; var dir = 0; var first_time = 0; var save_location = 0; var pipsqueakCount = 1; var countCount = 1; var countDouble = 0; var first_open_double = 0; var last_open_double = 0; /////////////////////////// macro "PIPSQUEAK" { if (pipsqueakCount==1){ print("PIPSQUEAK! Perineuronal net Intensity Program for the Standardization and Quantification of ECM Analysis."); print("\n"+"Copyright (C) 2016, John H. Harkness, PhD."); print("Protocol by Megan Slaker, PhD."); print("Lab of Barb Sorg, PhD., Washington State University, Vancouver"); print("\n"+"\n"+"Distance in pixels: "+scale_size+"\n"+"Known distance: "+scale_known+"\n"+"Pixel aspect ratio: "+scale_pixel+"\n"+"Unit of length: "+scale_unit); waitForUser("PIPSQUEAK Beta version 0.91, July 16, 2016 \n \n CHANGE LOG: \n Refined Double ROI enlargement (PV and WFA) \n Lowered PV pixel detection requirement \n Removed Double-label Open Next Functionality \n Bugs Squashed \n Splines Reticulated \n Llamas Herded"); wait(1000); pipsqueakCount = pipsqueakCount+1; } else { wait(50); } Dialog.create("Welcome."); items = newArray("Count labeled cells.", "Single label intensity analysis.", "Double label intensity analysis.", "->Change image scale settings."); Dialog.addRadioButtonGroup("What would you like to do?", items, 4, 1, "Single label intensity analysis."); Dialog.show; choice = Dialog.getRadioButton; if (choice=="Count labeled cells.") { run("__sub_PIPSQUEAK_count"); } else { if (choice=="Single label intensity analysis.") { run("__sub_PIPSQUEAK_single"); } if (choice=="Double label intensity analysis.") { run("__sub_PIPSQUEAK_double"); } if (choice=="->Change image scale settings.") { Dialog.create("Settings 1 of 2"); Dialog.addMessage("**Image scale measurements (for both single and double label analysis)**"); Dialog.addNumber("Distance in pixels:", scale_size); Dialog.addNumber("Known distance:", scale_known); Dialog.addNumber("Pixel aspect ratio:", scale_pixel); Dialog.addString("Unit of length:", scale_unit); Dialog.addMessage(" "); Dialog.addMessage("---------------------------------------------------------------------"); Dialog.addMessage(" **ROI identification settings.**"); Dialog.addMessage("Adjustments will alter cell determination and MAY reduce identification specificity."); Dialog.addMessage("Proceed with caution: here be dragons."); //this can be improved in the future by adding a drop down menu that calls up set stain parameters. //!!need additional settings for double labeled analysis?!! Dialog.addMessage(" "); Dialog.addMessage("**Intensity measurements**"); //Dialog.addMessage(" "); Dialog.addNumber("Lower threshold multiplier:",set_intensity_low_threshold); Dialog.addNumber("Upper threshold limit:", set_intensity_high_threshold); Dialog.addNumber("Lower limit particle size:", set_low_particlesize); Dialog.addNumber("Upper limit particle size:", set_high_particlesize); Dialog.addNumber("Lower limit circularity:", set_low_circularity); Dialog.addNumber("Upper limit circularity:", set_high_circularity); Dialog.addMessage(" "); Dialog.addMessage(" "); Dialog.addMessage("**Cell count**"); //Dialog.addMessage(" "); Dialog.addNumber("Lower threshold multiplier:", set_count_low_threshold ); Dialog.addNumber("Upper threshold limit:", set_count_high_threshold); Dialog.addNumber("Lower limit particle size:", set_count_low_particlesize); Dialog.addNumber("Upper limit particle size:", set_count_high_particlesize); Dialog.addNumber("Lower limit circularity:", set_count_low_circularity); Dialog.addNumber("Upper limit circularity:", set_count_high_circularity); Dialog.show; scale_size = Dialog.getNumber(); scale_known = Dialog.getNumber();; scale_pixel = Dialog.getNumber();;; scale_unit = Dialog.getString(); set_intensity_low_threshold = Dialog.getNumber(); set_intensity_high_threshold = Dialog.getNumber();; set_low_particlesize = Dialog.getNumber();;; set_high_particlesize = Dialog.getNumber();;;; set_low_circularity = Dialog.getNumber();;;;; set_high_circularity = Dialog.getNumber();;;;;; set_count_low_threshold = Dialog.getNumber();;;;;;; set_count_high_threshold = Dialog.getNumber();;;;;;;; set_count_low_particlesize = Dialog.getNumber();;;;;;;;; set_count_high_particlesize = Dialog.getNumber();;;;;;;;;; set_count_low_circularity = Dialog.getNumber();;;;;;;;;;; set_count_high_circularity = Dialog.getNumber();;;;;;;;;;;; Dialog.create("Settings 1 of 2"); Dialog.addMessage("**Double-label Analysis**"); Dialog.addMessage(" "); Dialog.addMessage("Please enter the numbering suffixes of the image series you want to analyze in the space below."); Dialog.addMessage("eg: Exp42_SubA_example_1.tif and Exp42_SubA_example_3.tif = #1 and #3"); Dialog.addMessage(" "); Dialog.addNumber("First image (if possible, smaller volume stain):", first_suffix); Dialog.addNumber("Second image (if possible, larger volume stain):", second_suffix); //Dialog.addNumber("Total number of stains plus composite in each subject series:", total_images); //REMOVED FOR NOW—SEE NOTE IN "__SUB_PIPSQUEAK_OPENNEXT_DOUBLE". Dialog.addMessage(" "); Dialog.addMessage("*First stain parameters*"); Dialog.addString("Stain type:", first_stain_type); Dialog.addNumber("Lower threshold multiplier:", DL1_set_intensity_low_threshold); Dialog.addNumber("Upper threshold limit:", DL1_set_intensity_high_threshold); Dialog.addNumber("Lower limit particle size:", DL1_set_low_particlesize); Dialog.addNumber("Upper limit particle size:", DL1_set_high_particlesize); Dialog.addNumber("Lower limit circularity:", DL1_set_low_circularity); Dialog.addNumber("Upper limit circularity:", DL1_set_high_circularity); Dialog.addMessage(" "); Dialog.addMessage("*Second stain parameters*"); Dialog.addString("Stain type:", second_stain_type); Dialog.addNumber("Lower threshold multiplier:", DL2_set_intensity_low_threshold); Dialog.addNumber("Upper threshold limit:", DL2_set_intensity_high_threshold); Dialog.addNumber("Lower limit particle size:", DL2_set_low_particlesize); Dialog.addNumber("Upper limit particle size:", DL2_set_high_particlesize); Dialog.addNumber("Lower limit circularity:", DL2_set_low_circularity); Dialog.addNumber("Upper limit circularity:", DL2_set_high_circularity); Dialog.show; first_suffix = Dialog.getNumber(); second_suffix = Dialog.getNumber();; //total_images = Dialog.getNumber();;; first_stain_type = Dialog.getString(); DL1_set_intensity_low_threshold = Dialog.getNumber();; DL1_set_intensity_high_threshold = Dialog.getNumber();;; DL1_set_low_particlesize = Dialog.getNumber();;;; DL1_set_high_particlesize = Dialog.getNumber();;;;; DL1_set_low_circularity = Dialog.getNumber();;;;;; DL1_set_high_circularity = Dialog.getNumber();;;;;;; second_stain_type = Dialog.getString(); DL2_set_intensity_low_threshold = Dialog.getNumber();; DL2_set_intensity_high_threshold = Dialog.getNumber();;; DL2_set_low_particlesize = Dialog.getNumber();;;; DL2_set_high_particlesize = Dialog.getNumber();;;;; DL2_set_low_circularity = Dialog.getNumber();;;;;; DL2_set_high_circularity = Dialog.getNumber();;;;;;; run("PIPSQUEAK"); } } } ////////////////////////// macro "__sub_PIPSQUEAK_count" { //count labeled cells import_type=4; if (countCount == 1) { Dialog.create("Count Labeled Cells."); items = newArray("Yes, continue.", "No. Go back."); Dialog.addRadioButtonGroup("For this analysis, you NEED TO SET THE CELL DETECTION PARAMETERS in Settings. Also, you need previously summed z-stacks. \n Do you have the correct settings and summed files ready?", items, 2, 1, "Yes, continue."); Dialog.show; choice = Dialog.getRadioButton; if (choice=="No. Go back.") { run("PIPSQUEAK"); } else { wait(50); } } else { wait(50); } countCount = countCount+1; Dialog.create("Cell Count"); items = newArray("Open image to count", "Adjust cell detection parameters", "Return to main menu"); Dialog.addRadioButtonGroup("What would you like to do?", items, 3, 1, "Open image to count"); Dialog.show; choice = Dialog.getRadioButton; if (choice=="Open image to count") { wait(100); } else { if (choice=="Return to main menu") { run("PIPSQUEAK"); } if (choice=="Adjust cell detection parameters") { Dialog.create("Settings"); Dialog.addMessage("**Cell count**"); //Dialog.addMessage(" "); Dialog.addNumber("Lower threshold multiplier:", set_count_low_threshold ); Dialog.addNumber("Upper threshold limit:", set_count_high_threshold); Dialog.addNumber("Lower limit particle size:", set_count_low_particlesize); Dialog.addNumber("Upper limit particle size:", set_count_high_particlesize); Dialog.addNumber("Lower limit circularity:", set_count_low_circularity); Dialog.addNumber("Upper limit circularity:", set_count_high_circularity); Dialog.show; set_count_low_threshold = Dialog.getNumber();;;;;;; set_count_high_threshold = Dialog.getNumber();;;;;;;; set_count_low_particlesize = Dialog.getNumber();;;;;;;;; set_count_high_particlesize = Dialog.getNumber();;;;;;;;;; set_count_low_circularity = Dialog.getNumber();;;;;;;;;;; set_count_high_circularity = Dialog.getNumber();;;;;;;;;;;; run("__sub_PIPSQUEAK_count"); } } open(); run("Set Measurements...", "area mean standard min redirect=None decimal=3"); run("Set Scale...", "distance=scale_size known=scale_known pixel=scale_pixel unit=&scale_unit global"); dir = getDirectory("image"); print(dir); name = getTitle; full_name = getTitle; index = lastIndexOf(name, "."); if (index!=-1) name = substring(name, 0, index); print("\n"+name+" loaded."); first_open = name; run("__sub_PIPSQUEAK_Background"); } ////////////////////////// macro "__sub_PIPSQUEAK_single" { // /* print("PIPSQUEAK! Perineuronal net Intensity Program for the Standardization and Quantification of ECM Analysis."); print("\n"+"Copyright (C) 2016, John H. Harkness, PhD."); print("Protocol by Megan Slaker, PhD."); print("Lab of Barb Sorg, PhD., Washington State University, Vancouver"); print("\n"+"Distance in pixels: "+scale_size+"\n"+"Known distance: "+scale_known+"\n"+"Pixel aspect ratio: "+scale_pixel+"\n"+"Unit of length: "+scale_unit); wait(1000); */ Dialog.create("Import Type"); // /*items = newArray("Semiautomated analysis of raw, non-summed, individual Tiffs", "Semiautomated analysis of summed Z-stacks", "Automatic analysis of summed Z-stacks","->Make summed image from z-stacks."); Dialog.addRadioButtonGroup("What type of file do you want to import?", items, 4, 1, "Semiautomated analysis of summed Z-stacks"); */ // items = newArray("Semiautomated analysis of raw, non-summed, individual Tiffs", "Semiautomated analysis of summed Z-stacks", "Automatic analysis of summed Z-stacks"); Dialog.addRadioButtonGroup("What type of file do you want to import?", items, 3, 1, "Semiautomated analysis of summed Z-stacks"); Dialog.show; choice = Dialog.getRadioButton; if (choice=="Semiautomated analysis of raw, non-summed, individual Tiffs") { import_type=1; run("__sub_PIPSQUEAK_Import"); } else { if (choice=="Semiautomated analysis of summed Z-stacks") { import_type=2; run("__sub_PIPSQUEAK_Import_Summed"); } if (choice=="Automatic analysis of summed Z-stacks") { import_type=3; run("__sub_PIPSQUEAK_Auto_Import_Summed"); } // /* if (choice=="->Make summed image from z-stacks.") { //Dialog.create("Stacks folder"); //Dialog.addMessage("Before using this function, please place z-stack images into a folder titled 'Stacks' within your experiment folder."); //Dialog.addMessage("ie, /Desktop/experiment folder/Stacks/image1... image20"); //Dialog.show(); run("__sub_PIPSQUEAK_z-project"); } */ } } ///////////////////////////// macro "__sub_PIPSQUEAK_Import" { // Importing stacks //import_type=1; run("Image Sequence...", "disable_global convert sort"); name = getTitle; dir = getDirectory("image"); selectWindow(name); run("Set Measurements...", "area mean standard min redirect=None decimal=3"); run("Z Project...", "projection=[Sum Slices]"); run("Set Scale...", "distance=scale_size known=scale_known pixel=scale_pixel unit=&scale_unit global"); full_name = "SUM_"+name; print("\n"+name+" loaded."); run("__sub_PIPSQUEAK_Background"); } ///////////////////////////// macro "__sub_PIPSQUEAK_Import_Summed" { // Importing image //import_type=2; open(); run("Set Measurements...", "area mean standard min redirect=None decimal=3"); run("Set Scale...", "distance=scale_size known=scale_known pixel=scale_pixel unit=&scale_unit global"); dir = getDirectory("image"); //print(dir); name = getTitle; full_name = getTitle; index = lastIndexOf(name, "."); if (index!=-1) name = substring(name, 0, index); print("\n"+name+" loaded."); first_open = name; run("__sub_PIPSQUEAK_Background"); } //////////////////////////////// macro "__sub_PIPSQUEAK_Auto_Import_Summed" { // Importing image //import_type=3; open(); run("Set Measurements...", "area mean standard min redirect=None decimal=3"); run("Set Scale...", "distance=scale_size known=scale_known pixel=scale_pixel unit=&scale_unit global"); dir = getDirectory("image"); name = getTitle; full_name = getTitle; index = lastIndexOf(name, "."); if (index!=-1) name = substring(name, 0, index); print("\n"+name+" loaded."); first_open = name; waitForUser("Please don't touch", "Please let the macro run without clicking windows. Disruption may cause the macro to stall."); run("__sub_PIPSQUEAK_Background"); } //////////////////////////////// macro "__sub_PIPSQUEAK_z-project" { //makes summed image from z-stack top_dir = getDirectory("Choose a Directory "); count = 1; listFiles(top_dir); function listFiles(top_dir) { list = getFileList(top_dir+"/.."); //child_list = getFileList(top_dir); parentlist = File.getParent(top_dir); for (i=0; iMake summed double-labeled images from z-stacks."); Dialog.addRadioButtonGroup("What type of file do you want to import?", items, 3, 1, "Semiautomated analysis of summed double-labeled Z-stack"); Dialog.show; choice = Dialog.getRadioButton; if (choice=="Semiautomated analysis of summed double-labeled Z-stack") { import_type = 5; run("__sub_PIPSQUEAK_Open_Double"); } else { if (choice=="Automatic analysis of summed double-labeled Z-stacks") { import_type = 6; run("__sub_PIPSQUEAK_Open_Double"); } if (choice=="->Make summed double-labeled images from z-stacks.") { //Dialog.create("Stacks folder"); //Dialog.addMessage("Before using this function, please place z-stack images into a folder titled 'Stacks' within your experiment folder."); //Dialog.addMessage("ie, /Desktop/experiment folder/Stacks/image1... image20"); //Dialog.show(); run("__sub_PIPSQUEAK_double_sum""); } } } ///////////////////////////// macro "__sub_PIPSQUEAK_double_sum" { countDouble = 1 Ldest = getDirectory("Choose a Directory "); //load from name = getTitle; countDouble++ if (countDouble == 2) { Sdest = Ldest+"/summed/"; //save to Dialog.create("Save location"); Dialog.addMessage("Select a place to save the summed image. ie, /Users/John/Desktop"); Dialog.addString("Save to: ", Sdest); Dialog.show(); Sdest = Dialog.getString(Ldest="/summed/"); print("Save location: "+Sdest); } else { wait(100); } if (File.exists(Sdest+name+"/")) { wait(100); } else { File.makeDirectory(Sdest+name+"/"); } sfold = Sdest + name; stackfold = getFileList(Ldest); //if(!File.exists(sfold)) { // File.makeDirectory(sfold); //} for(i=0; i0){ selectImage(nImages); close(); } } ///////////////////////////// macro "__sub_PIPSQUEAK_Open_Double" { waitForUser("Select First Image", "Please open the first image of the subject series."); open(); run("Set Measurements...", "area mean standard min redirect=None decimal=3"); run("Set Scale...", "distance=scale_size known=scale_known pixel=scale_pixel unit=&scale_unit global"); first_image = getTitle; dir = getDirectory("image"); index = lastIndexOf(first_image, "."); if (index!=-1) first_image = substring(first_image, 0, index); print("\n"+first_image+" loaded."); series_name = substring(first_image, 0, index-2); first_open_double = series_name; if(endsWith(first_image,first_suffix)) { open(series_name+"_"+second_suffix+".tif"); second_image = getTitle; if (index!=-1) second_image = substring(second_image, 0, index); print(second_image+" loaded."); run("__sub_PIPSQUEAK_Double_Background"); } else { waitForUser("Please update Settings to match numbering suffixes of double-label image series"); run("PIPSQUEAK"); } } ////////////////////////////// /* //MACRO REMOVED BECAUSE SUBJECT SEQUENCE LOADING COMPLICATED BY IMAGE ORDER. MUST REVISIT STRATEGY TO MAKE THIS FUNCTION WORK. macro "__sub_PIPSQUEAK_OpenNext_Double" { if (total_images == second_suffix) { run("Open Next"); } else { series_diff = total_images-second_suffix; for (i = 0; i < series_diff; i++) { run("Open Next"); }} first_image = getTitle; index = lastIndexOf(first_image, "."); series_name = substring(first_image, 0, index-2); last_open_double = series_name; //print(series_name); /* if (last_open_double==first_open_double) { print("\n"+"All images processed! Done."); makeRectangle(0, 0, 0, 0); run("Revert"); run("Clear Results"); run("Close"); selectWindow(first_image+".tif"); run("Close"); } else { wait(100); } */ if (index!=-1) first_image = substring(first_image, 0, index); if(endsWith(first_image,first_suffix)) { print("\n"+first_image+" loaded."); open(series_name+"_"+second_suffix+".tif"); second_image = getTitle; if (index!=-1) second_image = substring(second_image, 0, index); if(endsWith(second_image,second_suffix)) { print(second_image+" loaded."); run("__sub_PIPSQUEAK_Double_Background"); } else { waitForUser("Please update Settings to match numbering suffixes of double-label image series"); run("__sub_PIPSQUEAK_Open_Double"); } } */ /////////////////////////////// macro "__sub_PIPSQUEAK_Double_Background" { //First Image // Selecting Background first_image_tif = first_image+".tif"; second_image_tif = second_image+".tif"; run("Clear Results"); run("ROI Manager..."); roiManager("Show All"); roiManager("Show All with labels"); selectWindow(first_image_tif); makeRectangle(475, 10, 30, 30); roiManager("Add"); makeRectangle(475, 104, 30, 30); roiManager("Add"); makeRectangle(475, 198, 30, 30); roiManager("Add"); makeRectangle(475, 292, 30, 30); roiManager("Add"); makeRectangle(475, 390, 30, 30); roiManager("Add"); makeRectangle(475, 475, 30, 30); roiManager("Add"); makeRectangle(407, 475, 30, 30); roiManager("Add"); makeRectangle(324, 475, 30, 30); roiManager("Add"); makeRectangle(246, 475, 30, 30); roiManager("Add"); makeRectangle(167, 475, 30, 30); roiManager("Add"); makeRectangle(89, 475, 30, 30); roiManager("Add"); makeRectangle(10, 475, 30, 30); roiManager("Add"); makeRectangle(10, 390, 30, 30); roiManager("Add"); makeRectangle(10, 292, 30, 30); roiManager("Add"); makeRectangle(10, 198, 30, 30); roiManager("Add"); makeRectangle(10, 104, 30, 30); roiManager("Add"); makeRectangle(10, 10, 30, 30); roiManager("Add"); makeRectangle(89, 10, 30, 30); roiManager("Add"); makeRectangle(167, 10, 30, 30); roiManager("Add"); makeRectangle(246, 10, 30, 30); roiManager("Add"); makeRectangle(324, 10, 30, 30); roiManager("Add"); makeRectangle(407, 10, 30, 30); roiManager("Add"); run("Subtract Background...", "rolling=10"); roiManager("Select", newArray(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,21)); roiManager("Measure"); // Calculating lower threshold background value in "Mean" column DL1_m=0; DL1_bkgd_mean=0; DL1_meanbkgd=0; DL1_std=0; DL1_bkgd_std=0; DL1_stdbkgd=0; DL1_m = nResults; DL1_bkgd_mean = newArray(DL1_m); run("Select None"); for (i=0; i0){ roiManager("Select", array); roiManager("Delete"); }else{ wait(50); } selectWindow("ROI Manager"); run("Close"); run("Clear Results"); //if (import_type==6) { // run("__sub_PIPSQUEAK_OpenNext_Double"); // } else { Dialog.create("Next image?"); items = newArray("Open next image for analysis.", "Return to main menu."); Dialog.addRadioButtonGroup("What would you like to do next?", items, 2, 1, "Open next image for analysis."); Dialog.show; choice = Dialog.getRadioButton; if (choice=="Return to main menu.") { run("PIPSQUEAK"); } else { // run("__sub_PIPSQUEAK_OpenNext_Double"); //SEE NOT IN "__SUB_PIPSQUEAK_OPENNEXT_DOUBLE" ABOUT REMOVAL OF AUTO OPEN FUNCTION. run("__sub_PIPSQUEAK_Open_Double"); } } } /////////////////////////////