---
# System prepended metadata

title: FODs para Histología
tags: [Histology]

---



### FODs para Histología

En este tutorial veremos como calcular los Fiber Orientation Distributions (FODs) en imágenes histologicas. Este tipo de análisis es común para las imágenes de resonancia magnética sensibles a difusión, sin embargo, extrapolarlo de alguna manera a las imágenes histológicas puede ser de gran ayuda para la validación directa. 

Este acercamiento ha sido anteriormente descrito en el articulo:
> Budde MD, Annese J. Quantification of anisotropy and fiber orientation in human brain histological sections. Front Integr Neurosci. 2013 Feb 1;7:3. doi: 10.3389/fnint.2013.00003. PMID: 23378830; PMCID: PMC3561729.

Sin embargo, el código y la manera exacta en como calculan los FODs no es completamente clara. Aqui nos dimos a la tarea de crear unos códigos usando una combinacion entre `javascript` y `R`, lo cual veremos a continuación. 

Para este ejercicio utilizamos la siguiente tincion de plata de la corteza, la cual podemos ver que tiene las fibras que ascienden y descienden, asi como aquellas que van tangencialmente en el plano:

![Captura de pantalla 2024-08-27 a la(s) 10.32.56 a.m.](https://hackmd.io/_uploads/BJLd6zisR.png)

Ahora bien, el primer paso es abrir `FIJI` y la imágen a analizar. Despues corremos `Pluing > Macros > New` con el código que se proporciona aqui abajo:
> Puedes modificar la dimension del parche al cambiar el número de pixeles de altura y ancho.

```javascript
// Get image dimensions
width = getWidth();
height = getHeight();

// Suggested number of patches
suggestedPatchesX = Math.ceil(width / 400);
suggestedPatchesY = Math.ceil(height / 400);

// Prompt the user to input the number of patches or use the suggested value
Dialog.create("Especifica la cantidad de parches por imagen");
Dialog.addNumber("Numero de parches en eje X (Sugerido: " + suggestedPatchesX+ ")", suggestedPatchesX);
Dialog.addNumber("Numero de parches en eje Y (Sugerido: " + suggestedPatchesY+ ")", suggestedPatchesY);
Dialog.show();

numPatchesX = Dialog.getNumber();
numPatchesY = Dialog.getNumber();

// Calculate patch size based on the number of patches
patchSizeX = Math.floor(width / numPatchesX);
patchSizeY = Math.floor(height / numPatchesY);

// Create folders for storing patches and results
patchFolder = getDirectory("current") + "patches/";
resultFolder = getDirectory("current") + "results/";
File.makeDirectory(patchFolder);
File.makeDirectory(resultFolder);

// Loop through the image in patches
for (x = 0; x < width; x += patchSizeX) {
    for (y = 0; y < height; y += patchSizeY) {
        // Define the size of the current patch
        currentPatchWidth = patchSizeX;
        currentPatchHeight = patchSizeY;

        // Ensure the patch fits within the image boundaries
        if (x + currentPatchWidth > width) {
            currentPatchWidth = width - x;
        }
        if (y + currentPatchHeight > height) {
            currentPatchHeight = height - y;
        }

        // Define ROIs
        makeRectangle(x, y, currentPatchWidth, currentPatchHeight);
        
        // Duplicate the ROIs and save them
        title = "ROI_" + x + "_" + y;
        run("Duplicate...", "title=" + title);
        
        // Save the patch
        patchFilePath = patchFolder + title + ".tif";
        saveAs("Tiff", patchFilePath);
        
        // Close the duplicated ROI window
        close();
    }
}

// Apply analysis to each patch and save the results
fileList = getFileList(patchFolder);
for (i = 0; i < fileList.length; i++) {
    // Open the patch image
    open(patchFolder + fileList[i]);

    // Perform analysis (OrientationJ Distribution on the duplicated patch)
    run("OrientationJ Distribution", "tensor=5");

    // Name the new table file (output of 0J) according to the patch file name
    fileName = fileList[i].replace(".tif", ".csv");

    // Save the results
    filePath = resultFolder + fileName;
    saveAs("Results", filePath);

    // Close the patch image
    close();
}
```

El codigo va a crear dos carpetas, una llamada **patches** donde va a almacenar cada recuadro al que se le hizo `OrientationJ Distribution` , y la segunda carpeta es la de **results** que va a contener los archivos `.csv` con la información de la orientación y anisotropía de cada uno de los parches. **MUY importarte es que tanto los parches como los archivos CSV se guardan de acuerdo a las coordenadas que les corresponde en la imágen. Esto nos será realmente util para poder realizar la recontrucción y saber quién es quién**.


![Captura de pantalla 2024-08-27 a la(s) 10.34.50 a.m.](https://hackmd.io/_uploads/B1zGAzsjR.png)

Ahora bien, ya que tenemos los resultados del tensor de estructura por parche, podemos proceder a la segunda parte que es calcular los FODs. Para esto utilizaremos el siguiente código en `R`.

Lo unico que necesitamos para este paso es la carpeta en donde se encuentran los archivos `.csv`, que contienen las distribuciones que queremos graficar.

```javascript

## Load the libraries
library(tidyverse)
library(dplyr)
library(readr)
library(stringr)
library(ggplot2)
library(xml2)

## Check directory
getwd()
## Change directory where my csv are located
setwd("/Users/paulinav/Desktop/results/")
## list all files from the current directory
list.files()
## Crate a list from these files 
list_files <- list.files()
list_files
## Create an empty list that will serve as a container to the receiving files
files_all <- list()
files_all
## Loop to read all files
for (i in 1:length(list_files)) {
  files_all[[i]] <- read_csv(list_files[i])
}
files_all
## Add the name of the files 
names(files_all) <- list_files
files_all
## Merged the files into a dataframe by rows
df <- do.call(rbind, files_all)
## Convert rownames to a first column (name of the file)
dataframe <- cbind(rownames(df), data.frame(df, row.names = NULL)) 
colnames(dataframe)[1] <- c("filename")
## Normalize the negatives to positive 
dataframe$adjOrientation <- ifelse(
  dataframe$Orientation < 0, 180 + dataframe$Orientation, 
  dataframe$Orientation) 

## Do the mirror of FODs

dataframe$reversed2 <- ifelse(
  dataframe$adjOrientation > 0, 180 + dataframe$adjOrientation, 
  dataframe$adjOrientation)

## Create new variables for coordinates
# Use str_split_fixed() to split the filenames and extract X and Y
dataframe$split_names <- str_split_fixed(dataframe$filename, "_", 3)
dataframe$X <- as.numeric(dataframe$split_names[, 2])
dataframe$Y <- as.numeric(str_replace(dataframe$split_names[, 3], ".csv.*", ""))

dataframe <- dataframe[, -5]
## Create a variable "group" so we can differentiate between patches prior to plotting
paste(sample(LETTERS[cur_group_id()], 10, replace=TRUE), collapse="")

dataframe <- dataframe %>% group_by(X, Y) %>%
 mutate(group = paste(sample(LETTERS, 3, replace=TRUE), collapse="")) 
 # mutate(group = rep.len(LETTERS[cur_group_id()]))


"Lets now plot in bulk for each combination of X and Y"

## We will use ggplot and geom_line + coord_polar
dataframe

group_unique <- unique(dataframe$group)
X_unique <- unique(dataframe$X)
Y_unique <- unique(dataframe$Y)

plot_list <- list()


for (i in seq_along(group_unique)) {
  grp <- group_unique[i]
  
  # Subset the dataframe for the current group
  df_sub <- subset(dataframe, group == grp)
  
  # Create the plot
  p <- ggplot(data = df_sub) +
    geom_line(aes(x=adjOrientation, y=Slice1), colour = "white", size = 2) +
    geom_line(aes(x=reversed2, y=Slice1), colour = "white", size = 2) +
    coord_polar()  +
    theme(panel.grid.major = element_blank(), 
          panel.grid.minor = element_blank(),
          panel.background = element_blank(), 
          legend.text = element_blank(),
          legend.title = element_blank(),
          legend.position = "none",
          axis.line = element_blank(),
          axis.text = element_blank(),
          axis.ticks = element_blank(),
          axis.title = element_blank(),
          rect = element_rect(fill = "transparent"),
          plot.background = element_rect(fill = "transparent",
                                         color = NA)
    )  
    #ggtitle(paste0("X: ", df_sub$X[1], ", Y: ", df_sub$Y[1])) 
  
  # Add the plot to the plot list
  plot_list[[paste0("Group_", grp)]] <- p
  
  # Create a filename based on X and Y
  filename <- paste0(df_sub$X[1], "_", df_sub$Y[1], ".png")
  
  # Save the plot as an SVG file
  ggsave(filename = filename, 
         plot = p, 
         device = "png", 
        # width = 8, 
        # height = 6, 
         bg = "transparent")
  
}
```
Como resultado final, tendremos una carpeta en donde se almacenarán todos los gráficos que representan los FODs de cada uno de los parches. Y como podrás notar, los FODs se guardaron también de acuerdo a las coordenadas de la imágen de histologia original. Lo cual nos ayudará a la siguiente fase que es la recontrucción de los parches y el overlay de los FODs.

![Captura de pantalla 2024-08-27 a la(s) 11.08.31 a.m.](https://hackmd.io/_uploads/Skx3HmsiR.png)


