// Written by Cenna van Manen. // This macro will count the number of nuclei per image, based on the user defined variables. // As input, the macro assumes all images in the chosen folder are single layered tif files. If required, these files can be generated using the channel splitter macro. // Furthermore, make sure the files and foldername do not contain comma's (,) or semicolons (;). Last, the indicated folder should not contain any other files // As output a control image and an excel file per photo will be generated, as well as, a summary of all counted nuclei. // Furthermore, three text files will be generated, one containing the macro, one containing the log of the run, and the other containing the used variables. print ("Starting nuclei count"); requires("1.52h") //Determine if the macro is called upon by another macro, otherwise the variables will be gathered here //Data format data_from_other_macro: input folder, general output folder, channel name list, channel names, image type, is silent mode data_from_other_macro = getArgument(); if (lengthOf(data_from_other_macro)>1){ stand_alone = 0; data_from_other_macro = split(data_from_other_macro, ","); //Sets silent mode based on previously indicated preferences silent_mode = data_from_other_macro[1]; if(silent_mode){ setBatchMode(1); } else { setBatchMode(0); } parent_input_folder = File.getParent(data_from_other_macro[0]); input_folder = parent_input_folder + File.separator + "Split channels" + File.separator + "Nuclear marker" + File.separator; general_output_folder = data_from_other_macro[0]; output_folder = CreateOutputDirectory(general_output_folder); } else { stand_alone = 1; print ("Choose input folder"); input_folder = getDirectory("Choose input folder"); silent_mode = RunSilentMode(); output_folder = CreateOutputDirectory(input_folder); general_output_folder = output_folder; print("Input folder:", input_folder); print("Output folder:", output_folder); } //Save the macro that was used File.copy(File.directory + File.name, general_output_folder + "Macro_used_to_count_nuclei.txt"); //Gather all variables used in the analysis greyvalue_threshold = DetermineVariableByUser(); automated_variables = CalculateVariables(input_folder); PrintVariables(greyvalue_threshold, automated_variables[0], automated_variables[1], general_output_folder); AnalyzeImages(input_folder, greyvalue_threshold, automated_variables[0], automated_variables[1], output_folder, silent_mode); SaveLog(output_folder,stand_alone); print ("Finished nuclei count"); //Create output directory function CreateOutputDirectory(folder){ parent_folder = File.getParent(folder); output_folder = parent_folder + File.separator + "Counted nuclei" + File.separator; File.makeDirectory(output_folder); return output_folder; } //Define user variables function DetermineVariableByUser(){ Dialog.create("Define variable to count the nuclei"); message = "Count nuclei:" + "\n" + "Define the signal threshold you want to apply by defining the minimal value. You can only enter a" + "\n" + " whole number <254. If you want to use automated treasholding per image type 0."; Dialog.addMessage(message); Dialog.addNumber("Signal threshold", 0); Dialog.show(); value_output = Dialog.getNumber(); return value_output; } //Define if the macro will be ran in silent mode function RunSilentMode(){ silent_mode = getBoolean("Do you want to run the macro in silent mode? This will not open images while running." + "\n" + "If you select 'no' you will not be able to use the computer while the macro is running. "); setBatchMode(silent_mode); return silent_mode; } //Define dilate cycles function DetermineDilateRepeats(){ getPixelSize(unit, pixel_width, pixel_height); gap_width = 0.5; //Set as a constant of 0.5 um dilate_correction = (0.5*gap_width*(1/pixel_width)); dilate_repeat = floor(dilate_correction)+1; //+1 to make sure the gaps are covert return dilate_repeat; } //Calculates the optimal values for analyzing the nuclei function CalculateVariables(input_folder){ images = getFileList(input_folder); input_path = input_folder + images[0]; open(input_path); getPixelSize(unit, pixel_width, pixel_height); //Calculate the optimal sigma value for the gaussian blur based on the image resolution. The sigma value can never be smaller then one. sigma = round(0.25/pixel_width); if (sigma<1){ sigma = 1; } variables = newArray(2); variables[0] = sigma; //Calculate the particle size of a nucleus based on the image resolution. minimal_area_nucleus = 42; //This value can be altered by the user if required particle_size = (minimal_area_nucleus/(pixel_width * pixel_height)); variables[1] = particle_size; close(); return variables; } //Saves the user defined variables in separate text files for future reference function PrintVariables(greyvalue_threshold, gaussian_blur, particle_size, output_folder){ file = File.open(output_folder + "Variables_used_to_count_nuclei.txt"); print(file, "User defined variables:"); print(file, "Signal threshold: " + greyvalue_threshold + ", 255 (min, max). 0 indicates the Li Auto treshold was used, for which the values are indicated in the Log."); print(file, ""); print(file, "Automated variables:"); print(file, "Gaussian blur sigma: " + gaussian_blur); print(file, "Particle size measured: " + particle_size + "-inf"); File.close(file); } //Image analysis function AnalyzeImages(input_folder, greyvalue_threshold, gaussian_blur, particle_size, output_folder, silent_mode){ images = getFileList(input_folder); for (i=0; i 0){ setAutoThreshold("Default dark"); setThreshold(greyvalue_threshold, 255); } else { run("Auto Threshold", "method=Li white show"); } run("Convert to Mask"); if (i==0){ dilate_repeat = DetermineDilateRepeats(); } for (j=0; j