//******* // Author: Pradeep Rajasekhar // March 2021 // License: BSD3 // // Copyright 2021 Pradeep Rajasekhar, Walter and Eliza Hall Institute of Medical Research, Melbourne, Australia // // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. var fs=File.separator; setOption("ExpandableArrays", true); print("\\Clear"); var fiji_dir=getDirectory("imagej"); var gat_dir=fiji_dir+"scripts"+fs+"GAT"+fs+"Tools"+fs+"commands"; //settings for GAT gat_settings_path=fiji_dir+"scripts"+fs+"GAT"+fs+"gat_settings.txt"; if(!File.exists(gat_settings_path)) exit("Cannot find settings file. Check: "+gat_settings_path); run("Results... ", "open="+gat_settings_path); training_pixel_size=parseFloat(Table.get("Values", 0)); //0.7; neuron_area_limit=parseFloat(Table.get("Values", 1)); //1500 neuron_seg_lower_limit=parseFloat(Table.get("Values", 2)); //90 neuron_lower_limit=parseFloat(Table.get("Values", 3)); //160 run("Close"); //specify directory where StarDist models are stored var models_dir=fiji_dir+"scripts"+fs+"GAT"+fs+"Models"+fs; //Neuron segmentation model neuron_model_path=models_dir+"2D_enteric_neuron_v2.zip"; //check if required plugins are installed var check_plugin=gat_dir+fs+"check_plugin.ijm"; if(!File.exists(check_plugin)) exit("Cannot find check plugin macro. Returning: "+check_plugin); runMacro(check_plugin); //check if label to roi macro is present var label_to_roi=gat_dir+fs+"Convert_Label_to_ROIs.ijm"; if(!File.exists(label_to_roi)) exit("Cannot find label to roi script. Returning: "+label_to_roi); //check if roi to label macro is present var roi_to_label=gat_dir+fs+"Convert_ROI_to_Labels.ijm"; if(!File.exists(roi_to_label)) exit("Cannot find roi to label script. Returning: "+roi_to_label); //check if ganglia cell count is present var ganglia_cell_count=gat_dir+fs+"Calculate_Neurons_per_Ganglia.ijm"; if(!File.exists(ganglia_cell_count)) exit("Cannot find ganglia cell count script. Returning: "+ganglia_cell_count); //check if ganglia prediction post processing macro present var deepimagej_post_processing=gat_dir+fs+"Ganglia_prediction_post_processing.ijm"; if(!File.exists(deepimagej_post_processing)) exit("Cannot find roi to label script. Returning: "+deepimagej_post_processing); //check if ganglia prediction post processing macro present var segment_ganglia=gat_dir+fs+"Segment_Ganglia.ijm"; if(!File.exists(segment_ganglia)) exit("Cannot find segment ganglia script. Returning: "+segment_ganglia); #@ File (style="open", label="Choose the image to segment.
Enter NA if image is open.") path #@ boolean image_already_open #@ String(value="If image is already open, tick above box.", visibility="MESSAGE") hint1 // File (style="open", label="Choose the StarDist model file if segmenting neurons.
Enter NA if empty",value="NA", description="Enter NA if nothing") neuron_model_path cell_type="Neuron"; #@ String(value=" Cell counts per ganglia will get cell counts for each ganglia
If you have a channel for neuron and another marker that labels the ganglia (PGP9.5/GFAP/NOS)
that should be enough. You can also manually draw the ganglia",visibility="MESSAGE") hint4 #@ boolean Cell_counts_per_ganglia (description="Use a pretrained deepImageJ model to predict ganglia outline") #@ String(choices={"DeepImageJ","Manually draw ganglia"}, style="radioButtonHorizontal") Ganglia_detection #@ String(value="--------------------------------------------------------------Advanced------------------------------------------------------------------------------------",visibility="MESSAGE") hint_adv #@ boolean Change_pixel_size_segmentation (description="Change the pixel size of the scaled image thats used to detect neurons") #@ Float(label="Enter pixel size for segmenting neurons. Leave as is if unsure.", value=0.7) training_pixel_size_custom if(Change_pixel_size_segmentation==true) training_pixel_size=training_pixel_size_custom; if(image_already_open==true) { waitForUser("Select Image and choose output folder in next prompt"); file_name_full=getTitle(); //get file name without extension (.lif) dir=getDirectory("Choose Output Folder"); } else { if(endsWith(path, ".czi")|| endsWith(path, ".lif")) run("Bio-Formats", "open=["+path+"] color_mode=Composite rois_import=[ROI manager] view=Hyperstack stack_order=XYCZT"); else if (endsWith(path, ".tif")|| endsWith(path, ".tiff")) open(path); else exit("File type not recognised. Tif, Lif and Czi files supported."); dir=File.directory; file_name_full=File.nameWithoutExtension; //get file name without extension (.lif) } //file_name=File.nameWithoutExtension; file_name_length=lengthOf(file_name_full); if(file_name_length>50) file_name=substring(file_name_full, 0, 39); //Restricting file name length as in Windows long path names can cause errors //print(file_name); img_name=getTitle(); Stack.getDimensions(width, height, sizeC, sizeZ, frames); run("Select None"); run("Remove Overlay"); getPixelSize(unit, pixelWidth, pixelHeight); //Training images were pixelsize of ~0.568, 0.7 is default value that works scale_factor=pixelWidth/training_pixel_size; if(scale_factor<1.001 && scale_factor>1) scale_factor=1; print("Analysing: "+file_name); analysis_dir= dir+"Analysis"+fs; if (!File.exists(analysis_dir)) File.makeDirectory(analysis_dir); print("Files will be saved at: "+analysis_dir); print("Analysing: "+file_name); //Create results directory with file name in "analysis" results_dir=analysis_dir+file_name+fs; //directory to save images if (!File.exists(results_dir)) File.makeDirectory(results_dir); //create directory to save results file //do not include cells greater than 1000 micron in area //neuron_area_limit=1500; //microns neuron_max_pixels=neuron_area_limit/pixelWidth; //convert micron to pixels //using limit when segmenting neurons //neuron_seg_lower_limit=90;//microns neuron_seg_lower_limit=neuron_seg_lower_limit/pixelWidth; table_name="Analysis_"+cell_type+"_"+file_name; Table.create(table_name);//Final Results Table row=0; //row counter for the table image_counter=0; if(sizeC>1) { waitForUser("Note the neuron channel."); if (Cell_counts_per_ganglia==true) { Dialog.create("Choose channels for "+cell_type); Dialog.addNumber("Enter "+cell_type+" channel", 3); Dialog.addNumber("Enter channel for segmenting ganglia", 2); Dialog.show(); cell_channel= Dialog.getNumber(); ganglia_channel=Dialog.getNumber(); Stack.setChannel(cell_channel); resetMinAndMax(); Stack.setChannel(ganglia_channel); resetMinAndMax(); } else { Dialog.create("Choose channel for "+cell_type); Dialog.addNumber("Enter "+cell_type+" channel", 3); Dialog.show(); cell_channel= Dialog.getNumber(); Stack.setChannel(cell_channel); resetMinAndMax(); } } //add option for extended depth of field projection for widefield images if(sizeZ>1) { print(img_name+" is a stack"); roiManager("reset"); waitForUser("Verify the type of image projection you'd like (MIP or Extended depth of field\nYou can select in the next prompt."); projection_method=getBoolean("3D stack detected. Which projection method would you like?", "Maximum Intensity Projection", "Extended Depth of Field (Variance)"); if(projection_method==1) { waitForUser("Note the start and end of the stack.\nPress OK when done"); Dialog.create("Choose slices"); Dialog.addNumber("Start slice", 1); Dialog.addNumber("End slice", sizeZ); Dialog.show(); start=Dialog.getNumber(); end=Dialog.getNumber(); run("Z Project...", "start="+start+" stop="+end+" projection=[Max Intensity]"); max_projection=getTitle(); } else { max_projection=extended_depth_proj(img_name); } } else { print(img_name+" has only one slice, using as max projection"); max_projection=getTitle(); } max_save_name="MAX_"+file_name; //Segment Neurons selectWindow(max_projection); run("Select None"); run("Remove Overlay"); //if more than one channel, set on cell_channel or reference channel if(sizeC>1) { Stack.setChannel(cell_channel); } roiManager("show none"); run("Duplicate...", "title="+cell_type+"_segmentation"); seg_image=getTitle(); roiManager("reset"); n_tiles=2; new_width=round(width*scale_factor); if(new_width>1200) n_tiles=4; else if(new_width>4000) n_tiles=10; //scale image if scaling factor is not equal to 1 if(scale_factor!=1) { selectWindow(seg_image); new_width=round(width*scale_factor); new_height=round(height*scale_factor); run("Scale...", "x=- y=- width="+new_width+" height="+new_height+" interpolation=None create title=img_resize"); close(seg_image); selectWindow("img_resize"); seg_image=getTitle(); } roiManager("UseNames", "false"); selectWindow("Log"); print("*********Segmenting cells using StarDist********"); //segment neurons using StarDist model segment_cells(max_projection,seg_image,neuron_model_path,n_tiles,width,height,scale_factor,neuron_seg_lower_limit); close(seg_image); //manually correct or verify if needed waitForUser("Correct "+cell_type+" ROIs if needed. You can delete or add ROIs using ROI Manager"); cell_count=roiManager("count"); rename_roi(); //rename ROIs roiManager("deselect"); print("No of "+cell_type+" in "+max_projection+" : "+cell_count); roiManager("deselect"); roi_location=results_dir+cell_type+"_ROIs_"+file_name+".zip"; roiManager("save",roi_location ); selectWindow(max_projection); //uses roi to label macro code; clij is a dependency runMacro(roi_to_label); wait(5); neuron_label_image=getTitle(); selectWindow(table_name); Table.set("File name",row,file_name_full); Table.set("Total "+cell_type, row, cell_count); //set total count of neurons after nos analysis if nos selected Table.update; selectWindow(max_projection); run("Select None"); run("Remove Overlay"); if (Cell_counts_per_ganglia==true) { roiManager("reset"); if(Ganglia_detection=="DeepImageJ") { args=max_projection+","+cell_channel+","+ganglia_channel; //get ganglia outline runMacro(segment_ganglia,args); wait(5); ganglia_binary=getTitle(); draw_ganglia_outline(ganglia_binary,true); } else ganglia_binary=draw_ganglia_outline(ganglia_img,false); args=neuron_label_image+","+ganglia_binary; //get cell count per ganglia runMacro(ganglia_cell_count,args); //make ganglia binary image with ganglia having atleast 1 neuron selectWindow("label_overlap"); //getMinAndMax(min, max); setThreshold(1, 65535); run("Convert to Mask"); resetMinAndMax; close(ganglia_binary); selectWindow("label_overlap"); rename("ganglia_binary"); selectWindow("ganglia_binary"); ganglia_binary=getTitle(); selectWindow("cells_ganglia_count"); cell_count_per_ganglia=Table.getColumn("Cell counts"); roiManager("deselect"); ganglia_number=roiManager("count"); roi_location=results_dir+"Ganglia_ROIs_"+file_name+".zip"; roiManager("save",roi_location ); roiManager("reset"); selectWindow(table_name); Table.set("No of ganglia",0, ganglia_number); Table.setColumn("Neuron counts per ganglia", cell_count_per_ganglia); Table.update; selectWindow("cells_ganglia_count"); run("Close"); } //update table Table.update; Table.save(results_dir+cell_type+"_"+file_name+".csv"); selectWindow(neuron_label_image); saveAs("Tiff", results_dir+"Neuron_label_"+max_save_name); //using this image to detect neuron subtypes by label overlap rename("Neuron_label"); neuron_label_image=getTitle(); selectWindow(neuron_label_image); run("Select None"); roiManager("UseNames", "false"); close("*"); exit("Neuron analysis complete"); //function to segment cells using max projection, image to segment, model file location //no of tiles for stardist, width and height of image //returns the ROI manager with ROIs overlaid on the image. function segment_cells(max_projection,img_seg,model_file,n_tiles,width,height,scale_factor,neuron_seg_lower_limit) { //need to have the file separator as \\\\ in the file path when passing to StarDist Command from Macro. //regex uses \ as an escape character, so \\ gives one backslash \, \\\\ gives \\. //Windows file separator \ is actually \\ as one backslash is an escape character //StarDist command takes the escape character as well, so pass 16 backlash to get 4xbackslash in the StarDIst macro command (which is then converted into 2) model_file=replace(model_file, "\\\\","\\\\\\\\\\\\\\\\"); choice=0; print(img_seg); print(max_projection); roiManager("reset"); //model_file="D:\\\\Gut analysis toolbox\\\\models\\\\2d_enteric_neuron\\\\TF_SavedModel.zip"; selectWindow(img_seg); run("Command From Macro", "command=[de.csbdresden.stardist.StarDist2D],args=['input':'"+img_seg+"', 'modelChoice':'Model (.zip) from File', 'normalizeInput':'true', 'percentileBottom':'1.0', 'percentileTop':'99.8', 'probThresh':'0.4', 'nmsThresh':'0.45', 'outputType':'Label Image', 'modelFile':'"+model_file+"', 'nTiles':'"+n_tiles+"', 'excludeBoundary':'2', 'roiPosition':'Automatic', 'verbose':'false', 'showCsbdeepProgress':'false', 'showProbAndDist':'false'], process=[false]"); wait(50); temp=getTitle(); run("Duplicate...", "title=label_image"); label_image=getTitle(); run("Remove Overlay"); close(temp); roiManager("reset"); selectWindow(label_image); wait(20); //remove all labels touching the borders run("Remove Border Labels", "left right top bottom"); wait(10); rename("Label-killBorders"); //renaming as the remove border labels gives names with numbers in brackets //revert labelled image back to original size if(scale_factor!=1) { selectWindow("Label-killBorders"); //run("Duplicate...", "title=label_original"); run("Scale...", "x=- y=- width="+width+" height="+height+" interpolation=None create title=label_original"); close("Label-killBorders"); } else { selectWindow("Label-killBorders"); rename("label_original"); } wait(10); //rename("label_original"); //size filtering selectWindow("label_original"); run("Label Size Filtering", "operation=Greater_Than_Or_Equal size="+neuron_seg_lower_limit); label_filter=getTitle(); resetMinAndMax(); close("label_original"); //convert the labels to ROIs runMacro(label_to_roi,label_filter); wait(10); close(label_image); selectWindow(max_projection); roiManager("show all"); close(label_filter); } //rename ROIs as consecutive numbers function rename_roi() { for (i=0; i1) { for(ch=1;ch<=channels;ch++) { selectWindow(img); Stack.setChannel(ch); getLut(reds, greens, blues); Ext.CLIJ2_push(img); radius_x = 2.0; radius_y = 2.0; sigma = 10.0; proj_img="proj_img"+ch; Ext.CLIJ2_extendedDepthOfFocusVarianceProjection(img, proj_img, radius_x, radius_y, sigma); Ext.CLIJ2_pull(proj_img); setLut(reds, greens, blues); //Ext.CLIJ2_pull(img); concat_ch=concat_ch+"c"+ch+"="+proj_img+" "; } Ext.CLIJ2_clear(); //print(concat_ch); run("Merge Channels...", concat_ch+" create"); Stack.setDisplayMode("color"); } else { selectWindow(img); getLut(reds, greens, blues); Ext.CLIJ2_push(img); radius_x = 2.0; radius_y = 2.0; sigma = 10.0; proj_img="proj_img"; Ext.CLIJ2_extendedDepthOfFocusVarianceProjection(img, proj_img, radius_x, radius_y, sigma); Ext.CLIJ2_pull(proj_img); setLut(reds, greens, blues); } max_name="MAX_"+img; rename(max_name); close(img); return max_name; }