Microarrays

Guillermo Ayala Gallego

5/16/23

Microarrays

DNA Microarrays

Un ejemplo

Affymetrix Genechip

  • ¿Qué tipo de objeto tenemos? ¿Cuál es su clase?
class(gse21779raw)
[1] "AffyBatch"
attr(,"package")
[1] "affy"
  • ¿Qué anotación tiene?
pacman::p_load(Biobase,affy)
annotation(gse21779raw)
[1] "hgu133plus2"
  • ¿Cuántas sondas y muestras?
dim(exprs(gse21779raw))
[1] 1354896      18

La primera muestra

gse21779_1

AffyID

head(probeNames(gse21779raw))
[1] "1007_s_at" "1007_s_at" "1007_s_at" "1007_s_at" "1007_s_at" "1007_s_at"
(ID = probeNames(gse21779raw)[400])
[1] "1552281_at"
sum(probeNames(gse21779raw) == ID)
[1] 11
  • ¿Qué tamaños tienen los grupos de sondas?
counts = table(probeNames(gse21779raw))
table(counts)
counts
    8     9    10    11    13    14    15    16    20    69 
    5     1     6 54130     4     4     2   482    40     1 

Variabilidad intra y entre arrays

PM y MM: código

indexProbes(gse21779raw,"both",ID)[[1]]
 [1] 1088751  883561 1054203  366753  178855   68793  490689   62456 1123802
[10]  939573 1349651 1089915  884725 1055367  367917  180019   69957  491853
[19]   63620 1124966  940737 1350815
(posiciones = indexProbes(gse21779raw,"pm",ID)[[1]])
 [1] 1088751  883561 1054203  366753  178855   68793  490689   62456 1123802
[10]  939573 1349651
indexProbes(gse21779raw,"mm",ID)[[1]]
 [1] 1089915  884725 1055367  367917  180019   69957  491853   63620 1124966
[10]  940737 1350815

PM y MM: sondas

Intra

library(ggplot2)
pmID = probes(gse21779raw[,1],"pm",ID)
df1 = data.frame(sondas = 1:11,intensidad = pmID[,"GSM542488.CEL.gz"])
ggplot(df1,aes(x=sondas,y=intensidad))+geom_line()

Entre

pm0 = probes(gse21779raw,"pm",ID)
pm0 = data.frame(pm0,sondas=1:11)
pm1 = reshape::melt(pm0,id="sondas")
ggplot2::ggplot(data=pm1,aes(x=sondas,y=value,colour=variable))+
    geom_line()+ylab("Intensidad")

Comparando PM y MM

library(reshape)
pmm = data.frame(sondas=1:11,pm = probes(gse21779raw[,1],"pm",ID),
    mm = probes(gse21779raw[,1],"mm",ID)) 
df2 = reshape::melt(pmm,id="sondas")
levels(df2[,"variable"]) = c("pm","mm")
ggplot(df2,aes(x=sondas,y=value,colour=variable,linetype=variable))+geom_line()

Control de calidad

MA plot

Estimadores de densidad

Diagramas de cajas

MAS5

¿Qué tenemos?

  • En cada localización tendremos sondas que son oligonucleótidos específicos de un gen.
  • De hecho son pares de sonda: una con la secuencia deseada y otra en la que se modifica la base en la posicion 13.
  • La intensidad (o expresión) observada con el oligonucleótido correcto le llamamos PM (perfect matching).
  • La expresión observado sobre el modificado le llamamos MM (miss matching).
  • Una cierta proporción de localizaciones muestran un valor MM mayor que el valor PM.
  • http://media.affymetrix.com/support/technical/whitepapers/sadd_whitepaper.pdf

Corrección de fondo

  • Se divide el array en K zonas rectangulares: \(Z_k\) con \(k=1,\ldots,K\).
  • En cada \(Z_k\) se ordenan las intensidades observadas en las distintas celdas y se considera el 2% con intensidades menores.
  • Calculamos su media y desviación estándar muestrales: \(b(Z_k)\) y \(s(Z_k)\).
  • Sea la celda localizada en \((x,y)\).
  • \(d_k(x,y)\)= la distancia desde \((x,y)\) al centro de la región \(Z_k\).
  • Consideramos la siguiente cantidad \[ w_k(x,y) = \frac{1}{d^2_k(x,y) + s_0} \] donde \(s_0\) nos evita que el cociente se pueda anular y por defecto \(s_0 = 100\).
  • Para la celda localizada en \((x,y)\) consideramos \[ b(x,y) = \frac{1}{\sum_{k=1}^K w_k(x,y)} \sum_{k=1}^K w_k(x,y) b(Z_k) \]

Ruido local

  • Vamos a restar a las intensidades una medida de ruido de fondo local.
  • El problema es que nos encontremos con valores negativos.
  • Este valor de ruido en la celda localizada en \((x,y)\) se calcula como \[ n(x,y) = \frac{1}{\sum_{k=1}^K w_k(x,y)} \sum_{k=1}^K w_k(x,y) s(Z_k). \]
  • La idea ahora es quitar a las intensidades originales el fondo (\(b(x,y)\)) que hemos calculado pero asegurándonos que no nos surja valores negativos.
  • La intensidad original se denota como \(I(x,y)\) en la localización \((x,y)\). El valor ajustado de la intensidad viene dado por \[ A(x,y) = \max\{I(x,y) - b(x,y), f_0 n(x,y) \} \]
  • El parámetro \(f_0\) se suele fijar en \(f_0 =0.5\).

Cálculo del valor de expresión

  • Por el procemiento descrito anteriormente podemos ajustar los valores de PM y de MM.
  • En lo que sigue se supone que hemos ajustado estos valores.
  • Lo esperable y correcto es que en una celda tengamos un valor de PM mayor que el correspondiente valor MM.
  • Esto no es así en muchas ocasiones.
  • Se define un valor IM (Ideal Mismatch).

Ideal Mismatch

  • Denotamos: \((PM_{ij},MM_{ij})\) el valor de PM y de MM de la j-ésima sonda perteneciente al i-ésimo conjunto de sondas.
  • Se calcula un valor que llaman background específico para cada conjunto de sondas. \[ B_i = T_{bi} \{\log_2(PM_{ij}) - \log_2(MM_{ij}): j= 1, \ldots,n_i \}, \] donde \(T_{bi}\) denota el algoritmo bipesado en un solo paso.

  • Si el valor de \[ IM_{ij} = \left\{ \begin{array}{cc} MM_{ij} & \mbox{si $MM_{ij}< PM_{ij}$} \\ \frac{PM_{ij}}{2^{ B_i}} &\mbox{si $MM_{ij} \geq PM_{ij}$ y $ B_i > \alpha $} \\ \frac{PM_{ij}}{2^{\frac{\alpha}{1 + (\alpha - B_i)/\beta}}} & \mbox{si $MM_{ij} \geq PM_{ij}$ y $ B_i \leq \alpha $} \end{array} \right. \]
  • Por defecto: \(\alpha = 0.03\) y \(\beta = 10\).

Valor resumen

  • Calculamos \[ V_{ij} = \max\{PM_{ij} - IM_{ij},d\} \] siendo por defecto \(d = 2^{-20}\).
  • Transformamos \[ {\mathbb V}_{ij} = \log_2 (V_{ij}) \] con \(j = 1, \ldots, n_i\).
  • Y volvemos a aplicar un estimador biponderado en un solo paso. \[ SignalLogValue_i = T_{bi}({\mathbb V}_{i1}, \ldots, {\mathbb V}_{in_i}). \]

  • Fijamos una señal objetivo, Sc: por defecto, \(Sc = 500\).
  • Se calcula el siguiente factor de escala para el grupo de sondas i. \[ sf_i = \frac{Sc}{MediaAjustada\{2^{SignalLogValue_i},0.02,0.98\}} \]
  • MediaAjustada indica la media ajustada (media de los valores quitando una cierta proporción de los más grandes y de los más pequeños) en donde se quita el 2% de los más grandes y el 2% de los más pequeños.
  • El valor final para el conjunto de sondas i es \[ ReportedValue(i) = sf_i \times 2^{SignalLogValue_i} \]
  • Se incorpora una posibilidad de normalización que no indicamos.

Algoritmo biponderado de Tukey

  • Tenemos unos datos \(x_1,\ldots, x_n\).
  • Calculamos la mediana \(m_x\) de los datos \(x_1,\ldots, x_n\).
  • Determinamos las distancias \(d_i = |x_i - m_x|\).
  • Calculamos la mediana \(m_d\) de \(d_i\) con \(i = 1, \ldots, n\) (MAD, median absolute deviation).
  • Consideramos \[ u_i = \frac{x_i - m_x}{c m_d + \epsilon}, \] con \(i = 1, \ldots, n\). Los valores por defecto son \(c= 5\) y \(e =0.0001\) (con el valor de e evitamos la división por cero).

  • Consideremos una función bicuadrada (bisquare) definida como \[ w(u) = \left\{ \begin{array}{cl} (1- u^2)^2 &\mbox{si $|u| \leq 1$} \\ 0 &\mbox{si $|u| >1$} \end{array} \right.\]

  • Se define el estimador en un solo paso como \[ T_{bi}(x_1,\ldots,x_n) = \frac{\sum_{i=1}^n w(u_i) x_i}{\sum_{i=1}^n w(u_i)}. \]

  • Si sustituimos el valor \(m_x\) por \(T_b\) podríamos aplicar iterativamente el procedimiento hasta que se estabilice.

Robust Multichip Average (RMA)

RMA

  • En este método trabajamos con todos los arrays simultáneamente.
  • A diferencia del método anterior donde se procesaba cada array independientemente.
  • El procedimiento solamente utiliza los valores PM y no utiliza para nada los valores MM.

Corrección de fondo

  • El valor observado aleatorio \(S\) sería \[ S = X + Y \] con \(X \sim Exp(\alpha)\) e \(Y \sim N(\mu,\sigma^2)\).

  • Se tiene \[ E(X | S = s) = a + b \frac{\phi(\frac{a}{b})}{\Phi(\frac{a}{b})} \] siendo \(a = s - \mu - \sigma^2 \alpha\) y \(b= \sigma\) mientras que
    \(\phi\) y \(\Phi\) denotan las funciones de densidad y de distribución de una normal estándar (con media 0 y varianza 1).

  • Los parámetros del modelo (\(\alpha, \mu, \sigma^2\)) se estiman mediante un procedimiento no paramétrico.

Normalización de cuantiles

  • Tomamos n vectores de longitud N y construimos la matriz \(X\)
    \(N \times n\) que los tiene por vectores columna.
  • Ordenamos cada columna de \(X\) separadamente y tenemos \(X_s\).
  • Calculamos la media por filas de la matrix \(X_s\) y creamos \(X'_s\) una matriz con la misma dimensión que \(X\), tal que en la fila j tenemos la media de la fila de \(X_s\) repetida n veces.
  • Obtenemos \(X_t\) en donde cada columna de \(X'_s\) recupera el orden original.

Resumen

  • En cada array tendremos \(N\) sondas.
  • Suponemos que tenemos \(n\) arrays.
  • La matriz de expresión a nivel de sonda será: \[ {\mathbf x} = [x_{ij}]_{i=1,\ldots,N; j =1,\ldots,n}\]
  • La sonda \(i\)-ésima en el array \(j\)-ésimo tiene una expresión o intensidad \(x_{ij}\).
  • Denotamos el grupo \(k\)-ésimo de sondas con \(S_k\).
  • \(S_k \subset \{1,\ldots,N\}\)
  • \(S_k = \{i_1,\ldots,i_{|S_k|}\}\)
  • Denotamos \[{\mathbf y} = [y_{ij}]_{i=1,\ldots,|S_k|,j=1,\ldots,n} = [x_{ij}]_{i \in S_k,j =1,\ldots,n}.\]

Median polish

  • Consideramos la matriz para cada grupo de sondas. \[ \begin{array}{ccc|c} \delta_{1,1} & \cdots & \delta_{1,n} & a_1 \\ \vdots & \ddots & \vdots & \vdots \\ \delta_{|S_k|,1} & \cdots & \delta_{|S_k|,n} & a_{|S_k|}\\ \hline b_1 & \cdots & b_{n} & m \end{array} \]

  • Fijamos \(\delta_{ij} = \log_2(y_{ij})\), \(a_i = b_i = 0 \forall i,j\).

  • Calculamos la mediana para cada fila a lo largo de las columnas ignorando la última columna (separada por la línea).

  • Restamos a cada elemento de la fila la mediana correspondiente. Esta mediana se suma a la última columna (formada por \(a_1, \ldots, a_{|S_k|},m\).

  • Calculamos la mediana para cada columna de los valores correspondientes a las distintas filas sin considerar la última fila.

  • Restamos la mediana calculada en el paso anterior a cada elemento de la columna exceptuando la última fila. A la última fila sumamos las medianas calculadas.

  • El proceso descrito en los cuatro pasos anteriores continua iterando sucesivamente entre filas y columnas hasta que los cambios que se producen son nulos o muy pequeños.

Estimaciones

Una vez finalizado el proceso iterativo tendremos:

  • \(\hat{\mu} = m\)

  • \(\hat{\theta}_j = b_j\)

  • \(\hat{\alpha}_i = a_i\)

  • \(\hat{\epsilon}_{ij} = \delta_{ij}\)

  • ¿Y cómo estimamos la expresión de un grupo de sondas en una array? \[ \hat{\mu} + \hat{\theta}_j \]

  • Y esto lo repetimos para cada grupo de sondas.

affy

MAS5 y RMA

library(affy)

El método MAS5

gse21779_mas5 = mas5(gse21779raw)

El método RMA

gse21779_rma = rma(gse21779raw)
load(paste0(dirTamiData,"gse21779_mas5.rda"))
load(paste0(dirTamiData,"gse21779_rma.rda"))

Densidades: MAS5

library(geneplotter)
multidensity(exprs(gse21779_mas5))

Densidades: RMA

multidensity(exprs(gse21779_rma))

Diagramas de cajas: MAS5

graphics::boxplot.matrix(exprs(gse21779_mas5))

Diagramas de cajas: RMA

graphics::boxplot.matrix(exprs(gse21779_rma))