# 3D_Confocal_LiveDead_analysis # Developed by Carles Bada # Automatic particle quantification for fluorescent images for a live/dead analysis # The following code describes the process of making an automatic live/dead quantification # giving as result: csv files with the volume and the position of the particles, an histogram # of the particle distribution in z-axis for live and dead channels, and a 3D z-stack image # with the particle surfaces and centres of masses of both analysis. # Imported packages and classes from ij import IJ, WindowManager from ij.gui import GenericDialog, Plot, NonBlockingGenericDialog from ij.process import LUT from ij.plugin import ZProjector, filter from java.io import File from ij.measure import ResultsTable import os from org.jfree.chart import ChartFactory, ChartPanel, plot, ChartUtils from org.jfree.data.statistics import HistogramDataset, HistogramType from javax.swing import JFrame from java.awt import Color import array as ar import time def image_importer(): # Fucntion for imporing the directory and the list of images directory = IJ.getDirectory("Choose a Directory "); img_list = os.listdir(directory); os.chdir(directory); return directory,img_list def user_dialog_format(): # Basic dialog for selecting the analysis type and Bio-Formats configuration gui = GenericDialog("Previuos considerations"); gui.addChoice("Choose analysis type", ["Normal", "Only live cells"], "Normal"); gui.addChoice("Have you configured bio-formats?", ["YES", "NO"], "YES"); gui.addMessage("If you are not sure, mark NO"); gui.showDialog(); if gui.wasOKed(): # if was Oked, sabe the answers culture_type = gui.getNextChoice(); bio_formats = gui.getNextChoice(); if bio_formats=="NO": # if Bio-Formats is not configurated, open the plugin and the tutorial IJ.run("Bio-Formats Plugins Configuration", ""); tutorial = NonBlockingGenericDialog("Follow this instructions: "); tutorial.addMessage("1. In the formats window find your image format in the list"); tutorial.addMessage("2. Make sure enable and windowless is activated"); tutorial.addMessage("3. Close the bio-formats window"); tutorial.addMessage("4. Press OK!"); tutorial.showDialog(); return (culture_type) def image_opener(directory,img_open): # function for opening the image IJ.open(directory+img_open); imp = WindowManager.getCurrentImage(); dim=imp.getDimensions(); # get dimensions n_slices = dim[3] # get the number of slices if (dim[2]>1): # if the number of channels is higher than 1, split channels IJ.run("Split Channels"); else: pass img_pre_opened=WindowManager.getImageTitles(); # actual openned images for img in img_pre_opened: imp = WindowManager.getImage(img); lut=imp.getLuts(); # get the LUT of the image for lut_item in lut: lut_str = str(lut_item); if "green" in lut_str: # if green add Live label IJ.selectWindow(img); IJ.run ('Rename...', 'title=Live-'+img); if "red" in lut_str: # if red add Dead label IJ.selectWindow(img); IJ.run ('Rename...', 'title=Dead-'+img); else: continue img_opened=WindowManager.getImageTitles(); # list with opened images with actual names return (img_opened,n_slices) def newFolder(directory,img_open): # creates a new folder with the name of the image newFolderDir = directory + "Analysis_" + img_open+'/'; if not os.path.exists(newFolderDir): os.makedirs(newFolderDir); os.chdir(newFolderDir); return newFolderDir def image_processing(img_opened, culture_type): # Function for the analysis of each image IJ.run("3D OC Options", "volume centre_of_mass dots_size=10 font_size=20 store_results_within_a_table_named_after_the_image_(macro_friendly) redirect_to=none"); # 3D OC options configuration for img in img_opened: imp = IJ.selectWindow(img); # image filtering IJ.run(imp, "Minimum...", "radius=1 stack"); IJ.run(imp, "Maximum...", "radius=1 stack"); IJ.run(imp, "Maximum...", "radius=1 stack"); # To avoid non-particles problems: make a z-project and detect if there are or not particles IJ.run(imp, "Z Project...", "projection=[Average Intensity]"); img_opened=WindowManager.getImageTitles(); for name in img_opened: if "AVG" in name: IJ.selectWindow(name); print("Detecting particles...") IJ.run(imp, "Find Maxima...", "prominence=1 output=Count"); time.sleep(3); IJ.selectWindow(name); IJ.run("Close"); rt = ResultsTable.getResultsTable(); count = rt.getColumn(0); count_l = [count[-1]]; imp = IJ.selectWindow(img); min_size = "50"; # default size filter if culture_type == "Only live cells": if "Live" in img: min_size = "100"; # filter for live cells if count_l[0]>1: print("Analysing channel..."); IJ.run(imp, "3D Objects Counter", " threshold=1" + " min.="+min_size+" max.=6638 exclude_objects_on_edges" + " surfaces centres_of_masses" + " statistics") else: print("Analysing channel...") IJ.run(imp, "3D Objects Counter", " min.="+min_size+" max.=6638 exclude_objects_on_edges" + " surfaces centres_of_masses" + " statistics") time.sleep(0.8) else: if "Live" in img: min_size = "100"; if count_l[0]>1: print("Analysing channel..."); IJ.run(imp, "3D Objects Counter", " threshold=1" + " min.="+min_size+" max.=6638 exclude_objects_on_edges" + " surfaces centres_of_masses" + " statistics") else: print("Analysing channel...") IJ.run(imp, "3D Objects Counter", " min.="+min_size+" max.=6638 exclude_objects_on_edges" + " surfaces centres_of_masses" + " statistics") time.sleep(0.8) IJ.selectWindow(img); IJ.run("Close"); img_analysed=WindowManager.getImageTitles(); return img_analysed def histogramer(NewFolderDir,n_slices): # Function for saving the results and making the histogram non_img_list = WindowManager.getNonImageTitles(); Z_M = []; # for non_img in non_img_list: if "Statistics" in non_img: print("Saving data...") rt = WindowManager.getWindow(non_img).getTextPanel().getOrCreateResultsTable(); # save the results in a results table index = rt.getColumnIndex("ZM"); # z_m_i = rt.getColumn(index); # get ZM column if "Live" in non_img or "Dead" in non_img: rt.saveAs(NewFolderDir+non_img+'.csv'); # save the data z_m_double = ar.array('d',[]); for value in z_m_i: z_m_double.append(value); Z_M.append(z_m_double); else: continue hist = HistogramDataset(); # generate the dataset hist.setType(HistogramType.FREQUENCY); # select type of histogram channels = ["Live","Dead"]; i = 0; for data_set in Z_M: hist.addSeries(channels[i], data_set, n_slices,0,n_slices); # generate each serie i+=1; chart = ChartFactory.createHistogram("Live-Dead along Z-axis", "Depth", "Counts", hist, plot.PlotOrientation.VERTICAL, True, True, False); # histogram configuration chart.getXYPlot().getRendererForDataset(hist).setSeriesPaint(1, Color.red) chart.getXYPlot().getRendererForDataset(hist).setSeriesPaint(0, Color.green) chart.plot.setForegroundAlpha(0.5); w = 640; h = 480; directory_img = File(NewFolderDir + "Histogram.png"); print("Histogram completed"); ChartUtils.saveChartAsPNG( directory_img , chart , w , h ); # save histogram def reconstruction_3d(img_analysed, newFolderDir,culture_type): # function for 3D reconstruction after the analysis if culture_type == "Only live cells": for img in img_analysed: imp = IJ.selectWindow(img); #seleccionem la primera imatge de la llista IJ.run(imp, "8-bit", ""); if "Centres of mass" in img: if "Live" in img: c7 = img; if "Surface map" in img: if "Live" in img: c2 = img; else: continue IJ.run("Merge Channels...", "c2=["+c2+"] c7=["+c7+"] create ignore"); else: for img in img_analysed: imp = IJ.selectWindow(img); #seleccionem la primera imatge de la llista IJ.run(imp, "8-bit", ""); if "Centres of mass" in img: if "Dead" in img: c6 = img; if "Centres of mass" in img: if "Live" in img: c7 = img; if "Surface map" in img: if "Dead" in img: c1 = img; if "Surface map" in img: if "Live" in img: c2 = img; else: continue IJ.run("Merge Channels...", "c1=["+c1+"] c2=["+c2+"] c6=["+c6+"] c7=["+c7+"] create ignore"); IJ.saveAs("Tiff", newFolderDir+"live_dead_3d.tiff"); print("Reconstruction complete"); def closer(): # Function for closing images to save memory over the process IJ.run("Close All", "OK"); statistics_open = WindowManager.getNonImageTitles(); for stat in statistics_open: IJ.selectWindow(stat); IJ.run ('Close'); def process_completed(): # End dialog function gui = GenericDialog("End"); gui.addMessage("Process ready!"); gui.addMessage("Check your results in the image directory"); gui.showDialog(); def main(): # function that organizes the whole plugin directory,img_list=image_importer(); # define directory culture_type=user_dialog_format(); # previous consideretions for img_open in img_list: # for each image in the directory... print("Processing image: "+img_open); newFolderDir=newFolder(directory,img_open); # create a new folder img_opened,n_slices=image_opener(directory,img_open); # open the image img_analysed=image_processing(img_opened,culture_type); # process and analyse it histogramer(newFolderDir,n_slices); # make the histogram reconstruction_3d(img_analysed,newFolderDir,culture_type); # make the new 3D image print("\\Clear"); closer(); # close windows process_completed(); # end of the process main()