###### tags: `QuPath` `Fiji` `imageJ` `R` # Immunohistochemistry image processing and analysis * Author: Lun-Hsien Chang * Date created: May 2020 --- ### Using the R function in next section to annotate all IHC images * Download the cell segmentation data file `cell-seg-data-merged_CD8.txt` from QIMR L drive `L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/analysis-results` * Download the folder with IHC image files from QIMR L drive `L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/data_input/AshR/1. mIHF/Exp 108 210728/CD8 path` * Create a new R script file. Copy the code chunk below and modify the path of input files and folders. * Run the `source()` function to load the R function to the working environment. * Modify the file path within the double quotes. Make sure backword slashes \ are replaced by forward slashes / when the path is copied from Windows address bar. * In R, place your cursor anywhere in the line with the `source()` and run this function by pressing the Ctrl and Enter keys at the same time. * Modify the values that will be taken by the following arguments in the function `DrawAllIHCImagesTMAWithRectanglesInForm()` * `input.cell.seg.data.file.path=` This is the full path of your cell segmentation file. Make sure the string value is within a pair of quotes. * `input.images.folder.path=` This is the full path of the folder with IHC image files to annotate. Do not end the path with / . * `threshold.marker=` Specify a threshold for positive marker measurement with a number. * `threshold.confidence=` Specify a threshold for confidence with a number. * `rectangle.width.half=` Specify 50% of the width of a square. This value is used to calculate the coordinates of the four points. `rectangle.width.half=15` creates squares that are 30 by 30 pixels. * `legend.location=` Specify which corner you want your legend to be. Aceept four string values- `"topright"` `"topleft"` `"bottomright"` `"bottomleft"` * `rectangle.color=` Name the color of your rectangles. To use a different color from the default black, look up a color name in R [An overview of color names in R](https://www.r-graph-gallery.com/42-colors-names.html) * `legend.text.line1=` `legend.text.line2=` `legend.text.line3=` Allow a 3-line legned to be placed using the text you supply. Use line 1 for your project/study name. Use line 2 for your marker. Use line 3 for the thresholds. * `legend.color=` Name the color of the legend. To use a different color from the default black, look up a color name in R [An overview of color names in R](https://www.r-graph-gallery.com/42-colors-names.html) * `legend.text.cex=` Use a number to increase or decrease the font size of the legend. `legend.text.cex=2.5` expands the size to 250% * `output.folder.path=` Create a new folder where the annotated image files will be exported. Add the folder path to the argument. Do not end the path with / * `output.excluded.images.folder.path=` Create another new folder where the unannotated image files will be exported. Add the folder path to the argument. Do not end the path with / ```r! source("E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/scripts/RFunction_annotate-all-IHC-images.R") # Annotate CD8+ DrawAllIHCImagesTMAWithRectanglesInForm(input.cell.seg.data.file.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/analysis-results/cell-seg-data-merged_CD8.txt" ,input.images.folder.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_input/AshR/1. mIHF/Exp 108 210728/CD8 path" ,threshold.marker=5 ,threshold.confidence=95 ,rectangle.width.half=12.5 ,legend.location="topright" ,rectangle.color="black" ,legend.text.line1="Project: Exp108" ,legend.text.line2="Marker: CD8+" ,legend.text.line3="Marker threshold: 5, confidence threshold: 95%" ,legend.color="black" ,legend.text.cex=2.5 ,output.folder.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/CD8_path_view" ,output.excluded.images.folder.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/CD8_path_view/excluded") ``` * Download R script file `annotate-IHC-images_Exp108v1.R` with the code above from QIMR L drive `L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/scripts` --- ### A R function to annotate IHC images using a cell segmentation data file * Download the R script file `RFunction_annotate-all-IHC-images.R` from QIMR network drive L `L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/scripts` * The input cell segmentation data file should be * A tab-separated file * Having at least five columns with headers in this order. The function identifies the columns by their positions, not by their names * column 1 : image file names * column 2 : X coordinates * column 3 : Y coordinates * column 4 : Marker measurement * column 5 : Confidence * The input image files can be in different formats such as .tif, .tiff, .jpg, .jpeg, and .png (not tested yet) * ```r! # Check if required packages are already installed if (!"dplyr" %in% rownames(installed.packages())) install.packages("dplyr") if (!"foreach" %in% rownames(installed.packages())) install.packages("foreach") if (!"doParallel" %in% rownames(installed.packages())) install.packages("doParallel") if (!"magick" %in% rownames(installed.packages())) install.packages("magick") if (!"graphics" %in% rownames(installed.packages())) install.packages("graphics") if (!"grDevices" %in% rownames(installed.packages())) install.packages("grDevices") if (!"tools" %in% rownames(installed.packages())) install.packages("tools") # Load packages library(dplyr) # to use %>% operator library(doParallel) # to use %dopar% operator DrawAllIHCImagesTMAWithRectanglesInForm<- function( input.cell.seg.data.file.path="D:/googleDrive/copy-to-lunC_work/Merged_data/190529 batch analysis_lung cancer_cell_seg_data.txt" ,column.position.image.file.name=1 ,column.position.x.cooridnate=2 ,column.position.y.cooridnate=3 ,column.position.marker.measurement=4 ,column.position.confidence=5 ,input.images.folder.path ,threshold.marker=8 ,threshold.confidence=0 ,rectangle.width.half=12.5 ,legend.location="topright" ,rectangle.color="black" ,legend.text.line1="Project: demo" ,legend.text.line2="Marker: CD8+" ,legend.text.line3="Marker threshold: 8, confidence threshold: 0" ,legend.color="black" ,legend.text.cex=2.5 ,output.folder.path="D:/googleDrive/copy-to-lunC_work/CD8_annotated" ,output.excluded.images.folder.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/CD8_path_view/excluded"){ # Check file existence if(file.exists(input.cell.seg.data.file.path)!=TRUE){ cat("Input file for cell segmentation data could not be found") } else { # Import cell segmentation data file data <- read.delim(file=input.cell.seg.data.file.path, header = TRUE, sep = "\t", stringsAsFactors = F) %>% dplyr::select(c( column.position.image.file.name ,column.position.x.cooridnate ,column.position.y.cooridnate ,column.position.marker.measurement ,column.position.confidence)) %>% dplyr::mutate( Confidence_percent= as.numeric(stringr::str_replace_all(string=.[,5] ,pattern="%" ,replacement=""))) # dim(data) 2110587 6 data.subset <- data %>% dplyr::filter(data[,4] > threshold.marker & data[,5] > threshold.confidence) # dim(data.subset) 52173 6 cat((nrow(data)-nrow(data.subset))/nrow(data)*100, "% data are filtered out by the marker threshold of ", threshold.marker, "and confidence threshold of", threshold.confidence) } if(dir.exists(input.images.folder.path)!=TRUE){ cat("Input image file could not be found") } else{ # Read input image file paths as a vector image.file.paths <- list.files(path = input.images.folder.path, full.names = TRUE) # length(image.file.paths) 104 cat("There are",length(image.file.paths),"images in the folder") # Use image file name to look up data for the image in the cell segmentation data foreach::foreach(i=1:length(image.file.paths) ,.combine = 'c' ,.packages=c("foreach","dplyr")) %dopar% { print(paste0("=========== Working on image ",i,"============")) # If data can be found, then subset. If data cannot be found, then copy the input image to the output image.file.path <-image.file.paths[i] image.file.name <-basename(image.file.path) # Use image file name to subset data. If no data can be found, copy the image file to the excluded folder d <- data.subset %>% dplyr::filter(file.name==image.file.name) # dim(d) 99 6 # nrow(d) if(nrow(d)==0){ file.copy( from = image.file.path ,to=file.path(output.excluded.images.folder.path, image.file.name) ,copy.date = TRUE ) } else{ # Handle errors when the pattern fails to find the matched image file # Calculate coordinates for four points of rectangles tryCatch({ # Read input image as a magick-image object image <- magick::image_read(path=image.file.path) # class(image) "magick-image" # Draw the imported image. image.drew <- magick::image_draw(image) # Create pixel coordinates for rectangles rect.x.left <- d[,2] - rectangle.width.half # length(rect.x.left) 556 rect.x.right <- d[,2] + rectangle.width.half # length(rect.x.right) 556 rect.y.top <- d[,3] - rectangle.width.half # length(rect.y.top) 556 rect.y.bottom <- d[,3] + rectangle.width.half # length(rect.y.bottom) 556 graphics::legend(legend.location #"topleft" ,legend = c( legend.text.line1 ,legend.text.line2 ,stringr::str_wrap(string=legend.text.line3, width=80) ,paste0(rectangle.width.half*2, " x ", rectangle.width.half*2, " pixels") ) ,bty = "n" ,pt.cex = legend.text.cex ,cex = legend.text.cex ,text.col = c(legend.color)) ## Draw rectangles for individual stained cells graphics::rect( xleft= rect.x.left ,ybottom=rect.y.bottom ,xright=rect.x.right ,ytop=rect.y.top ,col = NA # color(s) to fill or shade the rectangle(s) with. The default NA (or also NULL) means do not fill, i.e., draw transparent rectangles, unless density is specified. ,border = rectangle.color # color for rectangle border(s). ,lty = par("lty") ,lwd = 2) # Close the image device grDevices::dev.off() #-------------------------- # Export the painted image #-------------------------- # Make output file name output.image.file.name <- paste("annotated", basename(image.file.path) ,sep = "_") # ,TMA.core.ID # Make output file path without file extension output.image.file.path <- file.path(output.folder.path, output.image.file.name) # Make output file name without file extension output.image.file.name.ext.rm <- tools::file_path_sans_ext(output.image.file.name) if(nchar(output.image.file.path) < 260){ magick::image_write( image= image.drew ,path= output.image.file.path) } else { # Truncate file name to 259 character long from the end cut.length <- nchar(output.image.file.path) - 259 # 4 end.position <- nchar(output.image.file.name.ext.rm) - cut.length output.image.file.path.shortened <- file.path(output.folder.path ,paste0( stringr::str_sub( string= tools::file_path_sans_ext(output.image.file.name) ,start = 1 ,end= end.position) # Append file extension to shortened file name ,"." ,tools::file_ext(output.image.file.name) ) ) magick::image_write( image= image.drew ,path= output.image.file.path.shortened) } }, error=function(e){cat("ERROR :",conditionMessage(e), "\n")} ) # End tryCatch() function } } # End %dopar% } # End else } # End the main function ``` --- ### Using the R function in next section to summarise cell segmentation data to counts of single, double positive cells * Download the cell segmentation data file `AP_Exp108.1_PeterMac-lungCancer-CD8-PD1_cell-seg-data-merged_CD8_PD1.tsv` from QIMR L drive `L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/analysis-results` * Create a new R script file. Copy the code chunk and modify the paths of input and output files and folders * Run the `source()` function to load the R function to the working environment. * Modify the file path within the double quotes. Make sure backword slashes \ are replaced by forward slashes / when the path is copied from Windows address bar. * In R, place your cursor anywhere in the line with the `source()` and run this function by pressing the Ctrl and Enter keys at the same time. * Modify the values that will be taken by the following arguments in the function `SummariseTwoMarkersCellSegmentationDataInForm()` * `file.path.cell.seg.data.file=` This is the full path of your cell segmentation file. Make sure the string value is within a pair of quotes. * `input.images.folder.path=` This is the full path of the folder with IHC image files to annotate. Do not end the path with / . * `marker.1.info.list=` Specify a list of three values for marker 1 (1) Name your marker 1 (e.g., CD8), (2) a threshold that dichotimises marker measurement values into negative or positive, (3) a threshold that dichotimises confidence. * `marker.2.info.list=` Specify a list of three values for marker 2 (1) Name your marker 1 (e.g., CD226), (2) a threshold that dichotimises marker measurement values into negative or positive, (3) a threshold that dichotimises confidence. * `output.folder.path=` Create a new folder where the summary data will be exported. Add the folder path to the argument. Do not end the path with / ```r! source("E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/scripts/RFunction_summarise-cell-segmentation-files.R") SummariseTwoMarkersCellSegmentationDataInForm( file.path.cell.seg.data.file="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/analysis-results/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1_cell-seg-data-merged_CD8_PD1.tsv" ,marker.1.info.list=list(c("CD8", 1.8, 98)) ,marker.2.info.list=list(c("CD226", 3, 98)) ,output.folder.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp109.1_PeterMac-lungCancer-CD8-CD226/analysis-results") ``` * The R code above is in the R script file `annotate-IHC-images_Exp108v1.R` at QIMR L drive `L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/scripts` --- ### A R function to summarise cell segmentation data to counts of single, double positive cells * Location of the script file on QIMR network drive L L:/Lab_MarkS/lunC/work/Immunohistochemistry_images/scripts/RFunction_summarise-cell-segmentation-files.R * The input cell segmentation data file should be * A tab-separated file * Having at least 4 columns with headers in this order. The function identifies the columns by their positions, not by their names * column 1 : A grouping variable that uniquely identifies TMA core location * column 2 : Confidence variable with string values (e.g., 95%) * column 3 : measurement of marker 1 * column 4 : measurement of marker 2 ```r! # Check if required packages are already installed if (!"dplyr" %in% rownames(installed.packages())) install.packages("dplyr") if (!"tools" %in% rownames(installed.packages())) install.packages("tools") # Load packages library(dplyr) # to use %>% operator SummariseTwoMarkersCellSegmentationDataInForm<- function( file.path.cell.seg.data.file="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1/analysis-results/AP_Exp108.1_PeterMac-lungCancer-CD8-PD1_cell-seg-data-merged_CD8_PD1.tsv" ,column.position.grouping.variable=1 ,column.position.confidence=2 # Measurement for marker 1 should be at column 3 ,column.position.marker.1=3 # Measurement for marker 2 should be at column 4 ,column.position.marker.2=4 ,marker.1.info.list=list(c("CD8", 1.8, 98)) ,marker.2.info.list=list(c("CD226", 3, 98)) # Name marker, threshold, confidence threshold ,output.folder.path="E:/Lab_MarkS/lunC_work/Immunohistochemistry_images/data_output/AP_Exp109.1_PeterMac-lungCancer-CD8-CD226/analysis-results"){ # Check file existence if(file.exists(file.path.cell.seg.data.file)!=TRUE){ cat("Input file for cell segmentation data could not be found") } else { # Add wanted column positions to a vector column.positions <- as.numeric(c( column.position.grouping.variable ,column.position.confidence ,column.position.marker.1 ,column.position.marker.2 ) ) # Import cell segmentation data file cat("Reading these columns by position from the input data file into R","\n" ,column.positions,"\n") # Import data varname.marker.1 <- marker.1.info.list[[1]][1] varname.marker.2 <- marker.2.info.list[[1]][1] data <- read.delim( file=file.path.cell.seg.data.file ,header = TRUE ,sep = "\t" ,stringsAsFactors = F #,nrows = 20000 ) %>% dplyr::select(column.positions) %>% # Rename columns by positions dplyr::rename( grouping.variable = 1 ,!!varname.marker.1 := 3 ,!!varname.marker.2 := 4 ) %>% dplyr::mutate( # Create numeric confidence from string variable confidence confidence_percent= as.numeric(stringr::str_replace_all(string=.[,2] ,pattern="%" ,replacement=""))) %>% # Remove string column confidence dplyr::select(-2) %>% # Reorder columns dplyr::select(grouping.variable, confidence_percent, everything()) # dim(data) 2136791 4 #---------------------------------------------------- # Specify filtration conditions as expression objects #---------------------------------------------------- measurement.threshold.marker.1 <- as.numeric(marker.1.info.list[[1]][2]) # marker.1.info.list[[1]][2] confidence.threshold.marker.1 <- as.numeric(marker.1.info.list[[1]][3]) measurement.threshold.marker.2 <- as.numeric(marker.2.info.list[[1]][2]) confidence.threshold.marker.2 <- as.numeric(marker.2.info.list[[1]][3]) # Set thresholds for marker 1 (column 3) and confidence (column 2) filtration.conditions.single.positive.marker.1 <- expression(.[,3] > measurement.threshold.marker.1 & .[,2] > confidence.threshold.marker.1) # class(filtration.conditions.single.positive.marker.1) [1] "expression" # Set thresholds for marker 2 (column 5)and confidence (column 6) filtration.conditions.single.positive.marker.2 <- expression(.[,4] > measurement.threshold.marker.2 & .[,2] > confidence.threshold.marker.2) # Set thresholds for double positive cells filtration.conditions.double.positive <- expression(.[,3] > measurement.threshold.marker.1 & .[,2] > confidence.threshold.marker.1 & .[,4] > measurement.threshold.marker.2 & .[,2] > confidence.threshold.marker.2) # Subset single positive cells for marker 1 data.subset.single.positive.marker.1 <- data %>% dplyr::filter(eval(filtration.conditions.single.positive.marker.1)) %>% dplyr::mutate(cell.status=paste0(marker.1.info.list[[1]][1],"+")) # dim(data.subset.single.positive.marker.1) 29226 5 cat("Subsetting single positive cells based on" ,marker.1.info.list[[1]][1] ,"threshold of" , measurement.threshold.marker.1 , "and confidence threshold of" , confidence.threshold.marker.1,"\n" ,(nrow(data)-nrow(data.subset.single.positive.marker.1))/nrow(data)*100 ,"% data are filtered out","\n") # Subset single positive cells for marker 2 data.subset.single.positive.marker.2 <- data %>% dplyr::filter(eval(filtration.conditions.single.positive.marker.2))%>% dplyr::mutate(cell.status=paste0(marker.2.info.list[[1]][1],"+")) # dim(data.subset.single.positive.marker.2) 40777 7 cat("Subsetting single positive cells based on" ,marker.2.info.list[[1]][1] ,"threshold of" , measurement.threshold.marker.2 , "and confidence threshold of" , confidence.threshold.marker.2,"\n" ,(nrow(data)-nrow(data.subset.single.positive.marker.2))/nrow(data)*100 ,"% data are filtered out","\n") # Subset double positive cells data.subset.double.positive <- data %>% dplyr::filter(eval(filtration.conditions.double.positive))%>% dplyr::mutate(cell.status=paste0( marker.1.info.list[[1]][1],"+" ,marker.2.info.list[[1]][1],"+"))# dim(data.subset.double.positive) 9501 7 cat("Subsetting double positive cells based on" ,marker.1.info.list[[1]][1] ,"threshold of" , measurement.threshold.marker.1 ,marker.2.info.list[[1]][1] ,"threshold of" , measurement.threshold.marker.1 , "confidence threshold of" , confidence.threshold.marker.1 ,"&" , confidence.threshold.marker.2,"\n" ,(nrow(data)-nrow(data.subset.double.positive))/nrow(data)*100 ,"% data are filtered out","\n") #----------------------------------------- # Count single positive cells per by group #----------------------------------------- # Get a list of TMA.core.location summary.data <- data %>% dplyr::group_by(grouping.variable) %>% dplyr::count(name = "number.cells") # dim(summary.data) 553 2 summary.marker.1 <- data.subset.single.positive.marker.1 %>% dplyr::group_by(grouping.variable) %>% # Add suffix _p for single positive cells dplyr::count(name = paste0(marker.1.info.list[[1]][1],"_p")) # dim(summary.marker.1) 424 2 summary.marker.2 <- data.subset.single.positive.marker.2 %>% dplyr::group_by(grouping.variable) %>% # Add suffix _p for single positive cells dplyr::count(name = paste0(marker.2.info.list[[1]][1],"_p")) # dim(summary.marker.2) 504 2 summary.double.positive <- data.subset.double.positive %>% dplyr::group_by(grouping.variable) %>% # Add suffix _p for single positive cells dplyr::count(name = paste0(marker.1.info.list[[1]][1],"p" ,marker.2.info.list[[1]][1],"p")) # dim(summary.double.positive) 317 2 # Combine all summary data above summary.all <- list( summary.data ,summary.marker.1 ,summary.marker.2 ,summary.double.positive) %>% purrr::reduce(dplyr::full_join, by=c("grouping.variable")) # dim(summary.all) 533 5 # Change attribute class to data.frame # class(summary.all) # [1] "grouped_df" "tbl_df" "tbl" "data.frame" attributes(summary.all)$class <- "data.frame" # Calculate ratio as number of double positive divided by number of CD8+ column.name.ratio <- paste0(names(summary.marker.2)[2],"_ratio") summary.all[[column.name.ratio]] <- summary.all[,5]/summary.all[,3] # Replace NA with 0 summary.all[is.na(summary.all)] <- 0 # Export summary data as a file write.table( x=summary.all ,file = file.path(output.folder.path, "summary-of-cell-seg-data_single-positive_double-positive_ratio.tsv") ,sep = "\t" ,col.names = TRUE ,quote = FALSE ,row.names = FALSE) cat("Exported summary data file at","\n" ,file.path(output.folder.path, "summary-of-cell-seg-data_single-positive_double-positive_ratio.tsv"),"\n") } # End the else } # End the main function ``` --- ### Annotate tissue and detect DAB in QuPath #### CD39 Create a new empty folder at C:\Lab_MarkS\lunC_work\Immunohistochemistry_images\QuPath-projects\QuPath-project_Exp91-BRAFRES1-RBWHMM_CD39 Create a new QuPath project and select the folder above as the project folder `File> Project > create project` Add images to the project from L:\Lab_MarkS\AshR\CD39 project images (all)\exp91_CD39 abcam M3R repeat Create class `Annotations > right-click in the class panel > Add class > Name it as "tissue" > change color to "Red"` The pixel classifier tissueClassifier adds red to tissue according the color specified by tissue=red `Annotations > right-click in the class panel > Add class > Name it as "DAB-positive" > change color to "Lime".` The pixel classifier DAB-measurement adds green to DAB according the color specified by DAB-positive=green Following the project description at L:\Lab_MarkS\AshR\5. QuPath Analysis\Analysis01.1 - MM_CD39 DAB Measure_AP210401\Description analysis01.1.txt, find out which the json file names used as the pixel classifiers. Here they are `findtissue vh H G 1 0.05 tissue ignore e.json` `vh dab g 0.25 pos neg ash.json` Copy the source [pixel_classifiers folder](L:/Lab_MarkS/AshR/5. QuPath Analysis/Analysis01.1 - MM_CD39 DAB Measure_AP210401/classifiers/pixel_classifiers) to the [project folder](C:\Lab_MarkS\lunC_work\Immunohistochemistry_images\QuPath-projects\QuPath-project_Exp91-BRAFRES1-RBWHMM_CD39\classifiers\pixel_classifiers) Copy an [existing scripts folder](C:\Lab_MarkS\lunC_work\Immunohistochemistry_images\QuPath-projects\QuPath-project_TMA-extractions_BRAFRES.1_CD39_analysis01.1\scripts) to the [project scripts folder](C:\Lab_MarkS\lunC_work\Immunohistochemistry_images\QuPath-projects\QuPath-project_Exp91-BRAFRES1-RBWHMM_CD39\scripts) Modify the [script file](C:\Lab_MarkS\lunC_work\Immunohistochemistry_images\QuPath-projects\QuPath-project_Exp91-BRAFRES1-RBWHMM_CD39\scripts\tissue-classification_DAB-detection_H-DAB-images.groovy) ```java! //Change the name of json files from createAnnotationsFromPixelClassifier("findtissue_vh_H_G_1_0.05_tissue_ignore_e", 10000.0, 10000.0) //threshold 0.05 // to createAnnotationsFromPixelClassifier("findtissue vh H G 1 0.05 tissue ignore e", 10000.0, 10000.0) //threshold 0.05 //from addPixelClassifierMeasurements("VH_DAB_G_0.5_POS_NEG_JASON2", "VH_DAB_G_0.5_POS_NEG_JASON2") createDetectionsFromPixelClassifier("VH_DAB_G_0.5_POS_NEG_JASON2", 10.0, 10.0) //to ``` Run the script `Script Editor> Run > Run for project > select all images` --- ### Classifying pixels with 2 pixel classifiers (manually) 1. Create a project and add images 2. load a pixel classifier ![1](https://i.imgur.com/Q9Okusa.jpg) 3. Select tissueClassifier (/classifiers/pixel_classifiers/tissueClassifier.json) ![2](https://i.imgur.com/Se43Ywt.png) 4. Apply the classifier to full image ![3](https://i.imgur.com/qCC5Ahu.png) 5. Specify hole size as 1000 ![4](https://i.imgur.com/xNdnMdZ.png) 6. Export renderred RGB ![5](https://i.imgur.com/fRmJT5R.png) 7. exported image ![step 1 to 6](https://i.imgur.com/ITe0u2m.jpg) 8. Delete annotations ![6](https://i.imgur.com/jhNGAhS.jpg) 9. load another pixel classifer ![7](https://i.imgur.com/1pO4MS7.png) 10. Apply the classifier to full image ![8](https://i.imgur.com/mSXR3F4.png) 11. Specify hole size as 1000 ![9](https://i.imgur.com/o278xVg.png) 12. Export renderred RGB ![10](https://i.imgur.com/XX4T9BK.png) 13. Exported image as ![step 9 to 12](https://i.imgur.com/mAIDrXn.jpg) --- ### Classifying pixels with 2 pixel classifiers (Tam's script) 1. Run the script on 1 image ![](https://i.imgur.com/t4WTE5p.jpg) 2. exported image ![](https://i.imgur.com/guFpu4O.jpg) --- ### Merge 3 channels in Fiji **Problem**: THUNDER Imaging Systems generates images in grayscale. You would like to combine these grayscale images to single colored images **Data**: L:\Lab_MarkS\lunC\Immunohistochemistry_images\data_input\Exp59_HNSCC-CD226-ratio-201014-Rescanned\HNSCC_TMA_A_1core `HNSCC A Re-scan_1B_ICC Merged_RAW_ch00.tif` `HNSCC A Re-scan_1B_ICC Merged_RAW_ch01.tif` `HNSCC A Re-scan_1B_ICC Merged_RAW_ch02.tif` **Solution**: Drag and drop a group of 3 images to Fiji ![imageJ_merge-channels_01](https://i.imgur.com/hHEq2zD.png) Select channels ![imageJ_merge-channels_02_select-channels](https://i.imgur.com/rXa20vI.png) Save your merged image ![imageJ_merge-channels_03_save-as](https://i.imgur.com/bfQHer3.jpg) --- ### Merge channels by a script **Problem**: You have a large number of grayscale images to merge. You don't enjoy clicking your mouse multiple times. **Data**: L:\Lab_MarkS\lunC\Immunohistochemistry_images\data_input\Exp59_HNSCC-CD226-ratio-201014-Rescanned\HNSCC_TMA_A_1core `HNSCC A Re-scan_1B_ICC Merged_RAW_ch00.tif` `HNSCC A Re-scan_1B_ICC Merged_RAW_ch01.tif` `HNSCC A Re-scan_1B_ICC Merged_RAW_ch02.tif` **Solution**: Move image files to a new folder if non-image Run a imageJ macro script file (C:\Lab_MarkS\lunC\Immunohistochemistry_images\scripts\merge-red-green-blue-channels.ijm) Plugins > Macro > Edit > Select the merge-red-green-blue-channels.ijm file ![imageJ_merge-channels_04_plugins-edit-macro](https://i.imgur.com/ssaVmIt.png) Run the script by clicking the `Run` tab or `Ctrl+R` ![imageJ_merge-channels_05_run-macro](https://i.imgur.com/8UBa8T2.png) Enter file suffixes for blue, green and red channels ![imageJ_merge-channels_06_enter-file-suffixes](https://i.imgur.com/YewXORC.png) Select the source image folder ![imageJ_merge-channels_07_select-input-folder](https://i.imgur.com/aayhmZY.png) Select a folder to save merged images ![imageJ_merge-channels_08_select-output-folder](https://i.imgur.com/pyYdWF7.png) This error occurs if the number of elements in the folder is not a multiple of 3 ![imageJ_merge-channels_09_error](https://i.imgur.com/rOglfNB.png) Channel merging successfully completed ![imageJ_merge-channels_10_task-completed](https://i.imgur.com/dom3RZW.png) ```javascript! //Clear the log window print("//Clear"); //Create a popup window that takes input from users Dialog.create("Enter file name suffixes that correspond to their channels"); Dialog.addString("Blue Suffix:", "00"); Dialog.addString("Green Suffix:", "01"); Dialog.addString("Red Suffix:", "02"); Dialog.show(); blueSuffix = Dialog.getString() + "."; print("blueSuffix="+blueSuffix); greenSuffix = Dialog.getString() + "."; print("greenSuffix="+greenSuffix); redSuffix = Dialog.getString() + "."; print("redSuffix="+redSuffix); //Select the folder of source images input_directory = getDirectory("Choose Source Directory"); list = getFileList(input_directory); //Select a folder to save images output_directory = getDirectory("Choose Save Directory"); setBatchMode(true); n = list.length; print("The number of image files is "+n); if ((n%3)!=0) exit("The number of files must be a multiple of 3"); stack = 0; first = 0; for (i=0; i<n/3; i++) { print("====================== Iternation "+i+"======================"); showProgress(i+1, n/3); blue="?"; print("blue="+blue); green="?"; print("green="+green); red="?"; print("red="+red); for (j=first; j<first+3; j++) { if (indexOf(list[j], blueSuffix)!=-1) blue = list[j]; if (indexOf(list[j], greenSuffix)!=-1) green = list[j]; if (indexOf(list[j], redSuffix)!=-1) red = list[j]; } open(input_directory+blue); print("Opening blue channel image from "+input_directory+blue); open(input_directory+green); print("Opening green channel image from "+input_directory+green); open(input_directory+red); print("Opening red channel image from "+input_directory+red); run("Merge Channels...", "c1=["+red+"] c2=["+green+"] c3=["+blue+"] create"); index = indexOf(blue, blueSuffix); print("index="+index); //Create output file names using input file name excluding the last 9 characters (e.g., _ch00.tif) and adding suffix "_channels-merged" name = substring(blue, 0, lengthOf(blue)-9)+"_channels-merged"; print("The merged channels will be saved as ", name+".tiff"); saveAs("tiff", output_directory+name); //Increment the first variable by 3 to work on the next group of 3 images first += 3; //Close all the opened images close(); setBatchMode(false); } showMessage("Channels merging completed"); ``` --- ### Check the MetaData folder **Problem**: What if you don't know the file suffixes of channels **Solution?**: Check `*_Properties.xml` file under the MetaData folder ![MetaData_01_open-properties.xml-file](https://i.imgur.com/PNxa8R4.png) ---