Como se describió en capítulos anteriores, le recomiendo encarecidamente que pase por cada paso del procesamiento de EEG manualmente, mirando los datos de cada paso, antes de ejecutar un script. En realidad, no me limito a recomendar, ¡insisto en ello! Esto le permitirá detectar problemas que de otra manera contaminarían sus datos. También le permitirá determinar algunos parámetros específicos del sujeto, como qué canales deben interpolarse y qué parámetros de detección de artefactos deben usarse. Pero si algunos parámetros difieren entre los sujetos, ¿cómo se puede usar un script que procese los datos de todos los sujetos?
La respuesta es almacenar los parámetros específicos del sujeto en una hoja de cálculo y luego hacer que su script lea los parámetros de esa hoja de cálculo. Este ejercicio está diseñado para mostrarte cómo funciona esto en el contexto de la interpolación de canales malos y otros pasos de preprocesamiento. El proceso de interpolación no funcionará correctamente si hay grandes compensaciones de voltaje en los datos, por lo que aplicaremos un filtro de paso alto que elimina estos desplazamientos antes de la interpolación. Además, necesitamos averiguar las ubicaciones tridimensionales de los electrodos, ya que esta información es necesaria por la rutina de interpolación (que utiliza la distancia entre el electrodo a ser interpolado y los otros electrodos para calcular valores sensibles, ponderados por distancia).
No voy a pasar por el proceso de ejecutar estas rutinas en la GUI y mirar el historial para ver el código Matlab correspondiente. Apuesto que ahora entiendes ese proceso, así que iré directamente al código. Puedes buscar la información de ayuda para estas rutinas si quieres una mejor comprensión de las opciones disponibles.
Comience saliendo de EEGLAB, escribiendo clear all y cargando Script5.m. Echemos un vistazo al guión antes de ejecutarlo. Lo primero que hay que notar es una variable llamada Interpolation_filename que contiene el nombre de un archivo de Excel, interpolate.xlsx. Este archivo contiene información sobre qué canales son malos y deben ser interpolados. Echa un vistazo al archivo en Excel (o importarlo a Google Sheets o algún otro programa de hojas de cálculo). Esto es lo que deberías ver:
Cuadro 11.2. Hoja de cálculo de información para interpolación (interpolate.xlsx).
ID
|
Bad_Channels
|
Canales ignorados
|
Channel_Names
|
1
|
[6 13]
|
[31 32 33]
|
C5, Oz
|
2
|
|
[31 32 33]
|
|
3
|
[25]
|
[31 32 33]
|
P8
|
4
|
|
[31 32 33]
|
|
6
|
|
[31 32 33]
|
|
7
|
|
[31 32 33]
|
|
8
|
|
[31 32 33]
|
|
9
|
|
[31 32 33]
|
|
10
|
|
[31 32 33]
|
|
La primera columna contiene los valores de ID de sujeto (sin Subject 5, a quien todavía estamos excluyendo). La segunda columna indica los canales malos (si los hay) correspondientes a los valores de ID de sujeto. Se especifican usando corchetes para que Matlab los interprete como arrays. Verás por qué eso es importante en un rato. La siguiente columna indica qué canales deben excluirse cuando calculamos los valores interpolados (los canales EOG). Esos son los mismos para cada participante, por lo que podrían estar listados en el guión, pero me pareció más conveniente ponerlos en la hoja de cálculo. La última columna muestra los nombres de los canales malos. Esta columna no es utilizada por el script, pero es bueno tener esa información cuando estás mirando la hoja de cálculo.
Si observa de cerca el contenido de las celdas (por ejemplo, mirando la barra de fórmulas), verá que el valor de cada celda comienza con una sola comilla (excepto los valores de ID). Esto le dice a Excel que el contenido de esa celda debe tratarse como una cadena de texto y nunca interpretarse como un número. He descubierto que esto puede evitar problemas cuando leemos los valores en Matlab, porque queremos que cada celda de una columna sea del mismo tipo de datos. También debe tener en cuenta que las etiquetas de columna no tienen espacios ni caracteres especiales en ellas (excepto el carácter de guión bajo). La rutina de Matlab que usaremos para leer la hoja de cálculo utilizará las etiquetas de columna para crear nuevas variables, por lo que las etiquetas deben ser nombres de variables legales de Matlab.
Ahora mira de nuevo el script y encuentra la línea con el comando legible. Esta es una función de Matlab que lee datos de un archivo en una estructura de datos especial de Table. Es una función muy potente que puede leer desde muchos tipos de archivos diferentes. Utiliza el nombre de archivo para determinar qué tipo de archivo se está leyendo (por ejemplo, la extensión de nombre de archivo.xlsx se usa para indicar que es un archivo XML de Excel). Crea una Tabla a partir del archivo de datos, y le hemos dicho que almacene esta Tabla en una variable llamada interpolation_parametros.
Para ver cómo funciona esto, ejecuta la primera parte del script, comenzando con la línea DIR = pwd y pasando por la línea interpolation_parametros = readtable (interpolation_filename). Después haga doble clic en la variable interpolation_parametros en el panel Espacio de trabajo para que pueda ver el contenido de esta variable. Verás que contiene las mismas filas y columnas que estaban en la hoja de cálculo. Ahora escriba Interpolation_parameters.bad_channels en la línea de comandos. Verás una lista de los canales malos para cada tema:
Matriz de celdas 9×1
{'[6 13]'}
{0×0 char}
{'[25]'}
{0×0 char}
{0×0 char}
{0×0 char}
{0×0 char}
{0×0 char}
{0×0 char}
Puede ver que esta lista está en un formato especial específico de MATLAB llamado matriz de celdas. Las matrices de células son un poco difíciles de entender y difíciles de usar correctamente. Esto es especialmente cierto para los principiantes, pero todavía a menudo cometo errores cuando trato de usarlos. En algún momento necesitarás aprender sobre ellos, porque son muy útiles, pero por ahora puedes confiar en el código que escribí que extrae el contenido de la tabla interpolation_parametros en un conjunto de matrices numéricas simples.
Este código está incrustado dentro del bucle en Script5.m. Ejecutemos el código, pero sin pasar realmente por todo el bucle. Para ello, primero escriba subject = 1 en la línea de comandos para que la variable de bucle tenga el valor correcto para el primer sujeto. Luego ejecuta la línea ID = num2str (SUB (subject)) en el cuerpo del bucle, porque vamos a necesitar esta variable. Ahora ejecuta las tres líneas de código comenzando con table_row =. La primera de estas líneas determina qué fila de la tabla interpolation_parametros contiene los valores para este tema. La segunda línea obtiene la matriz de canales malos para este tema y la almacena en una variable denominada bad_channels (que tiene cero elementos si no hay canales malos). La tercera línea obtiene la matriz de canales por ignorar y la almacena en una variable llamada ignored_channels. Si aún no eres un programador experimentado de Matlab, el código en esas líneas probablemente se vea como jeroglíficos, como dije, las matrices de celdas son un poco complicadas. Una vez que esté más familiarizado con la codificación de Matlab y haya envuelto su cerebro alrededor de matrices celulares, debería volver a este código y averiguar cómo funciona. Pero por ahora, puedes tratarlo como un poco de magia que te dé la información que necesitas.
Ahora deberías inspeccionar el contenido de bad_channels e ignored_channels, ya sea escribiendo los nombres de las variables en la línea de comandos o mirándolos en el Workspace. Verás que bad_channels es una matriz con los valores 6 y 13 (los dos canales malos para Subject 1), y ignored_channels es una matriz con los valores 31 a 33 (los tres canales estaremos ignorando al calcular valores interpolados para los canales malos).
La siguiente línea de código realiza la interpolación usando la función POP_ErplabInterpolateElectrodes. Se puede ver que enviamos las variables bad_channels e ignored_channels a esta función. Pero aún no ejecutes esta línea de código, porque no hemos corrido todas las líneas anteriores en el cuerpo del bucle. Echemos un vistazo a esas líneas antes de ejecutarlas.
El cuerpo del bucle comienza estableciendo algunas variables y cargando el conjunto de datos, al igual que en el script anterior. Después ejecuta una rutina llamada POP_ErplabShiftEventCodes, que desplaza todos los códigos de eventos de estímulo para que sean 26 ms después. Esto es necesario porque hay un retraso bastante sustancial entre cuando una pantalla LCD recibe una imagen de la tarjeta de video de la computadora y cuando realmente muestra esa imagen. Medimos ese retraso usando un fotosensor y encontramos que fue de 26 ms. Por lo tanto, cambiamos los códigos de eventos para que ocurran en el momento real en que apareció el estímulo en lugar de en el momento en que se envió la imagen a la pantalla. Si estás usando una pantalla LCD, debes hacer esto. Si no sabes cómo, comunícate con el fabricante de tu sistema de grabación EEG.
El siguiente paso utiliza la función pop_basicfilter para ejecutar un filtro de paso de banda con un paso de banda de 0.1 a 30 Hz (12 dB/octava, que corresponde a un orden de filtro de 2 en el código). Filtrar las bajas frecuencias es esencial antes de la interpolación, ya que de lo contrario los desplazamientos aleatorios de voltaje en cada canal producirán una distribución extraña del cuero cabelludo y el algoritmo de interpolación (que asume una distribución suave del cuero cabelludo) producirá resultados extraños. Tenga en cuenta que es una buena idea eliminar el desplazamiento DC antes de filtrar datos EEG continuos, y esto se implementa especificando 'removeDC', 'on' cuando llamamos a la función pop_basicfilter.
El siguiente paso ejecuta la función pop_chanedit para agregar información sobre la ubicación 3D de cada sitio de electrodo en función de los nombres de los electrodos. La función utiliza un archivo llamado estándar-10-5-cap385.elp que es proporcionado por EEGLAB. Contiene una lista de nombres de electrodos estándar (por ejemplo, CpZ) y sus ubicaciones idealizadas en una cabeza esférica. Esto no te da la verdadera ubicación de cada participante, lo que requeriría usar un sistema de digitalización 3D, pero es una aproximación lo suficientemente buena para el proceso de interpolación.
Las siguientes líneas extraen la información de la tabla interpolation_parametros y ejecutan la rutina de interpolación.
Finalmente, hacemos referencia a los datos y guardamos el conjunto de datos en el disco duro (igual que en el ejercicio anterior).
Tenga en cuenta que, para cada una de estas operaciones de procesamiento, enviamos el conjunto de datos a la rutina en la variable EEG, y luego la rutina devuelve un conjunto de datos modificado que almacenamos en la variable EEG. En otras palabras, el nuevo conjunto de datos sobrescribe el antiguo conjunto de datos en la variable EEG. Eso es mucho más eficiente que almacenar el resultado de cada nueva operación en ALLEEG. Pero tenga en cuenta que mantener los conjuntos de datos individuales tiene sentido cuando procesa los datos en la GUI, porque desea la flexibilidad de volver a un conjunto de datos anterior.
Ahora que hemos mirado el código, vamos a ejecutar el script, pero sólo para el primer tema. Para limitarlo al primer tema, asegúrese de que la línea SUB = [1] cerca de la parte superior no esté comentada. Después ejecuta el script. Ahora puede ver que el script ha creado un nuevo archivo de conjunto de datos llamado 1_N170_SHIFT_FILT_CHANLOCS_INTERP_REF.set en la carpeta Chapter_11 > N170_Data > 1.
Sin embargo, este conjunto de datos no está visible en el menú Conjuntos de datos. Script5.m difiere de los scripts de ejemplo anteriores en que no hace que los conjuntos de datos estén disponibles en la GUI de EEGLAB. Simplemente realiza el procesamiento y guarda los resultados de cada participante en un archivo de conjunto de datos. Como verá más adelante en el capítulo, a menudo tendrá una serie de scripts para procesar un experimento determinado (por ejemplo, uno para el preprocesamiento inicial, otro para ICA, otro para el procesamiento EEG post-ICA y otro para tratar con promedios). Cada uno de estos scripts se leerá en los archivos creados por el script anterior, por lo que a menudo no es necesario que los conjuntos de datos estén disponibles en la GUI.
Si quieres ver los resultados de un script determinado, querrás una forma conveniente de leer en los archivos que se acaban de crear. Script5.m logra esto al incluir código al final para cargar los nuevos archivos de conjunto de datos en ALLEEG. Esto le permite acceder a estos conjuntos de datos desde la GUI de EEGLAB. Este código va precedido de un comando return, que hace que el script termine, por lo que el código al final no se ejecutará normalmente cuando ejecute el script. Pero después de ejecutar el script, puede seleccionar el código al final y ejecutarlo manualmente (por ejemplo, haciendo clic en el botón Ejecutar sección en la parte superior de la ventana del editor de scripts). Pruébalo y luego verifica que puedes ver el nuevo conjunto de datos en el menú Conjuntos de datos.
Trace este nuevo conjunto de datos con EEGLAB > Trazar > Datos de canal (scroll). Después cargue el conjunto de datos original (1_N170.set) para este participante desde la carpeta Chapter_11 > N170_Data > 1 y graficarlo también. Verá que el nuevo conjunto de datos es mucho más suave y no tiene grandes desplazamientos de CC (porque ha sido filtrado de paso de banda). Y se pueden ver algunos artefactos enormes en los canales C5 y Oz en los datos originales que se han ido en los nuevos datos (porque el script interpoló esos canales). También debe notar que los canales están en un orden más conveniente en el nuevo conjunto de datos que en el conjunto de datos original como resultado del paso de Operaciones de canal EEG cerca del final del bucle.
Ahora comente la línea SUB = [1] cerca de la parte superior del script y vuelva a ejecutar el script para procesar los datos de los 9 participantes. A continuación, puede seleccionar y ejecutar el código al final del script para cargar los nuevos conjuntos de datos en la GUI de EEGLAB.
En este punto, me gustaría recordarte algunos consejos que te di al inicio del capítulo: ¡Juega! La mejor manera de entender cómo funcionan realmente estos scripts es jugar con el código. Si no estás seguro de entender uno de los pasos, intenta cambiarlo para ver qué pasa. Pero no solo hagas esto al azar. Crea hipótesis y pruébalas mediante manipulaciones experimentales (es decir, cambiando el código y viendo si los resultados confirman o desconfirman tus hipótesis). También puedes intentar modificar los scripts para procesar tus propios datos. A menos que seas un programador muy experimentado, probablemente no entenderás los puntos clave de este capítulo a menos que te involucres en este tipo de exploración activa. Y ahora es un buen momento para jugar con el código, porque el resto del capítulo asume que entiendes completamente los conceptos básicos y estás listo para unirlos en una canalización completa de procesamiento de datos.