diff --git a/00-Introduction.ipynb b/00-Introduction.ipynb index a9a3ed9..ddcf8a1 100644 --- a/00-Introduction.ipynb +++ b/00-Introduction.ipynb @@ -4,7 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Introduction" + "## Introduction\n", + "\n", + "## Introduccion\n" ] }, { @@ -14,7 +16,10 @@ "
\n", "Welcome to the Voytek Lab GitHub and Jupyter notebook collection.\n", "This is the first Jupyter notebook in a tutorial series that discusses the main topics involved with the projects being done in Voytek lab. We will walk through many of the concepts and calculations that are used in our lab.\n", - "
" + "\n", + "Bienvenido a la coleccion de GitHub y cuadernos de Jupyter del Voytek Lab.\n", + "Este es el primer cuaderno de Jupyter de una serie de tutoriales que presenta los temas principales involucrados en los proyectos que se realizan en el Voytek Lab. Vamos a recorrer muchos de los conceptos y calculos que se usan en nuestro laboratorio.\n", + "\n" ] }, { @@ -23,8 +28,10 @@ "source": [ "Knowledge in python is ***strongly*** recommended to help understand these tutorials and to help you preform these procedures, although it is not strictly necessary. Here are a couple of links that cover Python basics, from installation to more complex topics. These are resources and tutorials from two classes the lab has developed here at UC San Diego for the [Department of Cognitive Science](http://www.cogsci.ucsd.edu/) and the [Halıcıoğlu Data Science Institute](http://datascience.ucsd.edu/) and undergraduate Data Science major.
\n", "\n", + "Se ***recomienda mucho*** tener conocimientos de Python para ayudar a entender estos tutoriales y para ayudarte a realizar estos procedimientos, aunque no es estrictamente necesario. Aqui hay un par de enlaces que cubren los fundamentos de Python, desde la instalacion hasta temas mas complejos. Estos son recursos y tutoriales de dos cursos que el laboratorio ha desarrollado aqui en UC San Diego para el [Department of Cognitive Science](http://www.cogsci.ucsd.edu/) y el [Halıcıoğlu Data Science Institute](http://datascience.ucsd.edu/), asi como para la licenciatura en Ciencia de Datos.
\n", + "\n", "- [COGS 18: Introduction to Python](https://cogs18.github.io/intro/)
\n", - "- [COGS 108: Data Science in Practice](https://cogs108.github.io/Tutorials/00-Introduction)
" + "- [COGS 108: Data Science in Practice](https://cogs108.github.io/Tutorials/00-Introduction)
\n" ] }, { @@ -36,14 +43,23 @@ "- Introduce you to Jupyter Notebook.\n", "- Learn how to run Notebook cells.\n", "- Install relevant Python packages.\n", - "- Load your data into a Jupyter Notebook." + "- Load your data into a Jupyter Notebook.\n", + "\n", + "El proposito de _este_ cuaderno es:\n", + "\n", + "- Presentarte Jupyter Notebook.\n", + "- Aprender a ejecutar celdas del cuaderno.\n", + "- Instalar paquetes de Python relevantes.\n", + "- Cargar tus datos en un cuaderno de Jupyter.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This notebook will be a brief introduction and we encourage you to explore these tools further. " + "This notebook will be a brief introduction and we encourage you to explore these tools further. \n", + "\n", + "Este cuaderno sera una introduccion breve y te animamos a explorar estas herramientas mas a fondo.\n" ] }, { @@ -57,7 +73,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Setting up Jupyter Notebooks" + "### Setting up Jupyter Notebooks\n", + "\n", + "### Configuracion de Jupyter Notebooks\n" ] }, { @@ -66,7 +84,9 @@ "source": [ "
\n", "Jupyter Notebooks are an easy way to develop algorithms through which we can process our data. It lets us write, run, and present code and results in an approachable format.\n", - "
" + "\n", + "Los cuadernos de Jupyter son una forma sencilla de desarrollar algoritmos con los que podemos procesar nuestros datos. Nos permiten escribir, ejecutar y presentar codigo y resultados en un formato accesible.\n", + "\n" ] }, { @@ -77,23 +97,37 @@ "\n", "Below are the two recommended ways to consume these tutorials. If you think you will be using Jupyter in the future, we recommend following the first option. Otherwise if you just want to take a look at these tutorials and never return to Jupyter, you should probably use the second option, which will lead you to a cloud-based environment that allows you to run these tutorial notebooks without installing anything on your system.

\n", "\n", + "Anaconda es una distribucion de Python que gestiona paquetes y entornos de Python. Los cuadernos de Jupyter vienen incluidos con Anaconda, pero son aplicaciones separadas.\n", + "\n", + "A continuacion se muestran las dos formas recomendadas de seguir estos tutoriales. Si crees que vas a usar Jupyter en el futuro, te recomendamos seguir la primera opcion. En cambio, si solo quieres revisar estos tutoriales y no volver a usar Jupyter, probablemente deberias usar la segunda opcion, que te llevara a un entorno en la nube que permite ejecutar estos cuadernos tutoriales sin instalar nada en tu sistema.

\n", + "\n", "#### Follow along using Git\n", "\n", + "#### Sigue el tutorial usando Git\n", + "\n", "\n", "\n", "- Download Anaconda [here](https://store.continuum.io/cshop/anaconda/).\n", + "- Descarga Anaconda [aqui](https://store.continuum.io/cshop/anaconda/).\n", "\n", "- Clone this [repository](https://github.com/voytekresearch/tutorials) by using git clone.\n", + "- Clona este [repositorio](https://github.com/voytekresearch/tutorials) usando git clone.\n", "\n", "- Run the 'Anaconda Navigator' GUI from first bullet point and launch this Jupyter notebook.\n", + "- Ejecuta la interfaz grafica de 'Anaconda Navigator' del primer punto y abre este cuaderno de Jupyter.\n", "\n", "- Navigate to where you cloned the GitHub repository and click on the _.ipynb_ file you want to run.

\n", + "- Ve a la ubicacion donde clonaste el repositorio de GitHub y haz clic en el archivo _.ipynb_ que quieras ejecutar.

\n", "\n", "#### Follow along using Binder\n", "\n", + "#### Sigue el tutorial usando Binder\n", + "\n", "\n", "\n", - "Alternatively, if you don't want to install anything open this [Binder link](https://mybinder.org/v2/gh/voytekresearch/tutorials/master). You can consume 100% of these tutorials this way without installing anything on your local machine." + "Alternatively, if you don't want to install anything open this [Binder link](https://mybinder.org/v2/gh/voytekresearch/tutorials/master). You can consume 100% of these tutorials this way without installing anything on your local machine.\n", + "\n", + "Como alternativa, si no quieres instalar nada, abre este [enlace de Binder](https://mybinder.org/v2/gh/voytekresearch/tutorials/master). Puedes seguir el 100% de estos tutoriales de esta manera sin instalar nada en tu maquina local.\n" ] }, { @@ -102,7 +136,10 @@ "source": [ "
\n", "If you are unfamiliar with Jupyter Notebooks, follow the above links for COGS 18 and COGS 108.\n", + "\n", + "Si no estas familiarizado con los cuadernos de Jupyter, sigue los enlaces anteriores de COGS 18 y COGS 108.\n", "
\n", + "\n", "\n" ] }, @@ -110,7 +147,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Modules" + "## Modules\n", + "\n", + "## Modulos\n" ] }, { @@ -119,7 +158,9 @@ "source": [ "
\n", "In this section we will discuss the Python modules used most often in Voytek lab, and show you how to install them.\n", - "
" + "\n", + "En esta seccion hablaremos de los modulos de Python que se usan con mayor frecuencia en el Voytek Lab y te mostraremos como instalarlos.\n", + "\n" ] }, { @@ -129,10 +170,17 @@ "#### Installing modules using Anaconda\n", "If you are using Anaconda, you will be able to install many modules by opening 'Anaconda Prompt' and running the command: pip install <*module name*>\n", "\n", + "#### Instalacion de modulos usando Anaconda\n", + "Si estas usando Anaconda, podras instalar muchos modulos abriendo 'Anaconda Prompt' y ejecutando el comando: pip install <*nombre del modulo*>\n", + "\n", "\n", "For example:

\n", "$pip install pandas

\n", - "_pip_ is a package installation tool. On the other hand if you are using Binder to follow along then everything should be set up already." + "_pip_ is a package installation tool. On the other hand if you are using Binder to follow along then everything should be set up already.\n", + "\n", + "Por ejemplo:

\n", + "$pip install pandas

\n", + "_pip_ es una herramienta para instalar paquetes. Por otro lado, si estas siguiendo el tutorial con Binder, entonces todo ya deberia estar configurado.\n" ] }, { @@ -142,27 +190,32 @@ "outputs": [], "source": [ "# this sets up the notebook to allow inline plotting of higher-resolution plots\n", + "# esto configura el cuaderno para permitir graficas en linea de mayor resolucion\n", "%matplotlib inline\n", "%config InlineBackend.figure_format = 'retina' \n", "\n", "# here are some common modules used in Voytek lab:\n", - "import numpy as np # package for scientific computing in python\n", - "import scipy as sp # package of scientific data functions\n", - "import pandas as pd # package of data analysis functions\n", - "import sklearn as skl # package for data mining and machine learning\n", + "# aqui hay algunos modulos comunes usados en el Voytek Lab:\n", + "import numpy as np # package for scientific computing in python / paquete para computacion cientifica en Python\n", + "import scipy as sp # package of scientific data functions / paquete de funciones para datos cientificos\n", + "import pandas as pd # package of data analysis functions / paquete de funciones de analisis de datos\n", + "import sklearn as skl # package for data mining and machine learning / paquete para mineria de datos y aprendizaje automatico\n", "\n", - "import matplotlib.pyplot as plt # functions to plot data\n", + "import matplotlib.pyplot as plt # functions to plot data / funciones para graficar datos\n", "\n", "# here are some plotting set-ups\n", + "# aqui hay algunas configuraciones para las graficas\n", "from matplotlib import rcParams\n", - "rcParams['figure.figsize'] = 16, 4" + "rcParams['figure.figsize'] = 16, 4\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Importing Data" + "### Importing Data\n", + "\n", + "### Importacion de Datos\n" ] }, { @@ -172,7 +225,12 @@ "Let's start by loading some electrophysiology data. To do that, we need to tell python where to get the data from and tell it to save it as a variable.

\n", "'emodat.npy' is data from one channel of an [ECoG recording](https://en.wikipedia.org/wiki/Electrocorticography) from a participant looking at faces displaying various emotions. \n", "\n", - "We'll use this data in several of the tutorials. It should be saved at './dat/emodat.npy'" + "We'll use this data in several of the tutorials. It should be saved at './dat/emodat.npy'\n", + "\n", + "Comencemos cargando algunos datos de electrofisiologia. Para hacerlo, necesitamos indicarle a Python de donde obtener los datos y decirle que los guarde como una variable.

\n", + "'emodat.npy' contiene datos de un canal de un [registro ECoG](https://en.wikipedia.org/wiki/Electrocorticography) de una persona participante que observaba rostros mostrando varias emociones. \n", + "\n", + "Usaremos estos datos en varios de los tutoriales. Deberian estar guardados en './dat/emodat.npy'\n" ] }, { @@ -184,17 +242,21 @@ "outputs": [], "source": [ "# The name of the data file to load\n", + "# El nombre del archivo de datos que se va a cargar\n", "filename = \"./dat/emodat.npy\"\n", "\n", "# Loading data\n", - "data = np.load(filename)" + "# Cargando los datos\n", + "data = np.load(filename)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Let's use our plotting library to plot some of the data." + "Let's use our plotting library to plot some of the data.\n", + "\n", + "Usemos nuestra biblioteca de graficacion para visualizar una parte de los datos.\n" ] }, { @@ -219,15 +281,17 @@ } ], "source": [ - "plt.plot(data[0:1000]) #this is what about 1 second of ECoG data looks like\n", - "plt.show()" + "plt.plot(data[0:1000]) #this is what about 1 second of ECoG data looks like / esto es aproximadamente como se ve 1 segundo de datos de ECoG\n", + "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Alright, that's all we're going to talk about here! Good luck with Jupyter Notebook and the rest of the tutorials." + "Alright, that's all we're going to talk about here! Good luck with Jupyter Notebook and the rest of the tutorials.\n", + "\n", + "Muy bien, eso es todo lo que vamos a ver aqui. Buena suerte con Jupyter Notebook y con el resto de los tutoriales.\n" ] }, { diff --git a/01-ElectrophysiologicalTimeSeries.ipynb b/01-ElectrophysiologicalTimeSeries.ipynb index fa124d7..d122ed1 100644 --- a/01-ElectrophysiologicalTimeSeries.ipynb +++ b/01-ElectrophysiologicalTimeSeries.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Electrophysiological Time-Series" + "# Series temporales electrofisiologicas\n" ] }, { @@ -13,29 +13,29 @@ "source": [ "**Michael Tran 2018**\n", "\n", - "Welcome to the Voytek Lab GitHub and Jupyter notebook collection. This is the second Jupyter notebook of a tutorial series aiming to get those interested in doing meaningful work in Voytek lab up to speed. We use this tool to learn how to load our data and graph it.\n", + "Bienvenido a la coleccion de GitHub y Jupyter notebook del Voytek Lab. Este es el segundo Jupyter notebook de una serie de tutoriales cuyo objetivo es poner al dia a quienes estan interesados en realizar trabajo significativo en el Voytek Lab. Usamos esta herramienta para aprender a cargar nuestros datos y graficarlos.\n", "\n", - "The purpose of this notebook is to:\n", - "* Learn how to load data with a npy file \n", - "* Learn the purpose of Sampling and Aliasing\n", - "* Generate a time axis and plot the time series as a graph\n", - "* Learn (generally) what our generated graph shows\n", - "* Learn about different wave types and burstiness\n", - "* Introduce you to reference nodes\n" + "El proposito de este notebook es:\n", + "* Aprender a cargar datos con un archivo npy\n", + "* Aprender el proposito del muestreo y el aliasing\n", + "* Generar un eje temporal y representar la serie temporal como una grafica\n", + "* Aprender, de manera general, que muestra la grafica generada\n", + "* Aprender sobre diferentes tipos de ondas y la actividad en rafagas\n", + "* Introducirte a los nodos de referencia\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Default Imports" + "### Importaciones predeterminadas\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "First, we will import some basic python libraries that contain functions in order to do this tutorial." + "Primero, importaremos algunas bibliotecas basicas de Python que contienen funciones para realizar este tutorial.\n" ] }, { @@ -59,21 +59,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Part 1: Loading, Sampling, Generating a time axis, Analyzing" + "## Parte 1: Cargar, muestrear, generar un eje temporal y analizar\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Loading data with npy file" + "### Cargar datos con un archivo npy\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We will now load in our data which is a voltage series." + "Ahora cargaremos nuestros datos, que consisten en una serie de voltaje.\n" ] }, { @@ -82,45 +82,44 @@ "metadata": {}, "outputs": [], "source": [ - "volt = np.load('./dat/sample_data_2.npy') # voltage series" + "volt = np.load('./dat/sample_data_2.npy') # serie de voltaje\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Sampling & Aliasing" + "### Muestreo y aliasing\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In order to generate our time axis, we must set a sampling rate. What does this mean you might ask? Jack Schaedler at [his interactive tutorial page](https://jackschaedler.github.io/circles-sines-signals/aliasing.html) does an excellent job of explaining this under \"Sampling & Aliasing\", so read up and return!\n", + "Para generar nuestro eje temporal, debemos establecer una frecuencia de muestreo. ¿Que significa esto? Jack Schaedler, en [su pagina de tutorial interactivo](https://jackschaedler.github.io/circles-sines-signals/aliasing.html), hace un excelente trabajo explicandolo en la seccion \"Sampling & Aliasing\", asi que leelo y vuelve.\n", "\n", "-----------------------------------------------------------------------------------------------------------------------------\n", "\n", - "To go further in depth, the sampling rate is important for how we analyze data in the frequency domain. When you digitally record a signal, you measure it at a certain rate by taking samples x times per second (quantified in Hertz). For this reason, we don't know the exact amplitude of any digital signal at every single point in time. Our best guess is the closest sample to a given point in time.\n", + "Para profundizar un poco mas, la frecuencia de muestreo es importante para analizar datos en el dominio de la frecuencia. Cuando registras una senal de manera digital, la mides a cierta tasa tomando muestras x veces por segundo (cuantificado en Hertz). Por esa razon, no conocemos la amplitud exacta de una senal digital en cada punto del tiempo. Nuestra mejor aproximacion es la muestra mas cercana a un punto dado en el tiempo.\n", "\n", "\n", - "Resampling, PSD, and many other things we do in this lab fall under the title of Digital Signal Processing. You can read more about it for free [here](http://dspguide.com/)\n", + "El remuestreo, la PSD y muchas otras cosas que hacemos en este laboratorio entran dentro del procesamiento digital de senales. Puedes leer mas al respecto gratis [aqui](http://dspguide.com/)\n", "\n", - "##### So why should we Sample?\n", + "##### Entonces, ¿por que debemos muestrear?\n", "\n", - "We sample because there is a cost to data which is memory. If we have a faster sampling rate, we can have better temporal resolution but storing excessive samples can make the file size too big and use too much memory. Sometimes you will have extremely large data sets that simply take too much memory so we take sample rates to divide that space usage. It is possible to oversample which means that we have more samples than necessary which would make our files unneccesarily large, but there is also undersampling which is when we lose information by not sampling enough, but in return we can make our files smaller. The sample rate is something that we must choose carefully as there is a trade off for both sides.\n", + "Muestreamos porque los datos tienen un costo en memoria. Si usamos una frecuencia de muestreo mas alta, podemos obtener mejor resolucion temporal, pero almacenar demasiadas muestras puede hacer que el archivo sea demasiado grande y consuma demasiada memoria. A veces tendras conjuntos de datos extremadamente grandes que simplemente requieren demasiada memoria, por lo que usamos frecuencias de muestreo para reducir ese uso de espacio. Es posible sobremuestrear, lo que significa que tenemos mas muestras de las necesarias y que nuestros archivos se vuelven innecesariamente grandes, pero tambien existe el submuestreo, que ocurre cuando perdemos informacion por no muestrear lo suficiente; a cambio, podemos hacer que los archivos sean mas pequenos. La frecuencia de muestreo es algo que debemos elegir con cuidado, ya que existe un equilibrio entre ambos extremos.\n", "\n", "-----------------------------------------------------------------------------------------------------------------------------\n", - "If you would like further information on how to choose a good sampling rate, take a look at Schaedler's interactive site https://jackschaedler.github.io/circles-sines-signals/sampling.html under \"The Sampling Theorem\"\n", - "\n" + "Si quieres mas informacion sobre como elegir una buena frecuencia de muestreo, revisa el sitio interactivo de Schaedler https://jackschaedler.github.io/circles-sines-signals/sampling.html en la seccion \"The Sampling Theorem\"\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "To show how sampling can go wrong if we jump to conclusions, take a look at figure 1 shown below. \n", + "Para mostrar como el muestreo puede salir mal si sacamos conclusiones apresuradas, observa la figura 1 que se muestra a continuacion.\n", "\n", - "We have four different 2 hour flights from Paris to Berlin with a sample rate of 10 minutes. We should take care not to \"connect the dots\" as we can see that figure 1 has the same sample rates for four different flights which all create the same graph (shown in grey). We can see here, however, that they are drastically different altitude patterns when we see the overall flight altitudes of each flight." + "Tenemos cuatro vuelos distintos de 2 horas de Paris a Berlin con una frecuencia de muestreo de 10 minutos. Debemos tener cuidado de no \"unir los puntos\", ya que podemos ver que la figura 1 tiene las mismas frecuencias de muestreo para cuatro vuelos diferentes que generan la misma grafica (mostrada en gris). Sin embargo, aqui podemos ver que los patrones generales de altitud de cada vuelo son drasticamente distintos.\n" ] }, { @@ -128,21 +127,21 @@ "metadata": {}, "source": [ "![image1.png](img/image1.png)\n", - "from [Jack Schaedler](https://jackschaedler.github.io/circles-sines-signals/aliasing.html)" + "desde [Jack Schaedler](https://jackschaedler.github.io/circles-sines-signals/aliasing.html)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Generate time axis" + "### Generar eje temporal\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now, we will generate our time axis. We will set our sampling rate to be 1000 in this example case." + "Ahora generaremos nuestro eje temporal. En este ejemplo estableceremos la frecuencia de muestreo en 1000.\n" ] }, { @@ -153,22 +152,22 @@ }, "outputs": [], "source": [ - "rate = 1000. # sampling rate\n", - "time = np.arange(0,len(volt)/rate, 1/rate) #time series" + "rate = 1000. # frecuencia de muestreo\n", + "time = np.arange(0,len(volt)/rate, 1/rate) # serie temporal\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### 1. Plot the time series" + "### 1. Graficar la serie temporal\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We have our time series and now we will visualize it by graphing it." + "Ya tenemos nuestra serie temporal y ahora la visualizaremos graficandola.\n" ] }, { @@ -188,26 +187,26 @@ } ], "source": [ - "time_plot = [9, 10.5] # time range you want to plot\n", + "time_plot = [9, 10.5] # rango de tiempo que quieres graficar\n", "time_plot_idx = np.where(np.logical_and(time>=time_plot[0], time < time_plot[1]))[0]\n", "plt.figure(figsize=(12,3))\n", "plt.plot(time[time_plot_idx], volt[time_plot_idx],'k')\n", "plt.yticks(size=15)\n", "plt.xticks(size=15)\n", - "plt.xlabel('Time (s)',size=20)\n", - "plt.ylabel('Voltage (uV)',size=20)\n", + "plt.xlabel('Tiempo (s)',size=20)\n", + "plt.ylabel('Voltaje (uV)',size=20)\n", "plt.xlim((time_plot))\n", - "plt.show()" + "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "##### Analyzing our graph\n", - "Neural data has rythmic patterns that are variable as well as other patterns that are \"bursty\" i.e non continuous shown above. Our graph also has 8 peaks in half a second which is equal to 16 Hz, making this a Beta wave.\n", + "##### Analizando nuestra grafica\n", + "Los datos neuronales tienen patrones ritmicos que son variables, asi como otros patrones que aparecen en \"rafagas\", es decir, no continuos, como se muestra arriba. Nuestra grafica tambien tiene 8 picos en medio segundo, lo que equivale a 16 Hz, haciendo que esta sea una onda beta.\n", "\n", - "Different neural oscillatory patterns have different ranges and the general ranges are shown below." + "Los diferentes patrones oscilatorios neuronales tienen distintos rangos, y los rangos generales se muestran a continuacion.\n" ] }, { @@ -215,53 +214,53 @@ "metadata": {}, "source": [ "![image2.jpg](img/image2.jpg)\n", - "from [mindbodyvortex](http://www.mindbodyvortex.com/wp-content/uploads/2015/09/f3a6b3eb4cc6f2d7392b34284c233281.jpg)" + "desde [mindbodyvortex](http://www.mindbodyvortex.com/wp-content/uploads/2015/09/f3a6b3eb4cc6f2d7392b34284c233281.jpg)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Part 2: Ground vs. Referencing" + "## Parte 2: Tierra vs. referencia\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "To learn more about ground vs. reference for EEG recordings, we can visit \n", + "Para aprender mas sobre tierra vs. referencia en registros EEG, podemos visitar\n", "1. https://www.biopac.com/knowledge-base/ground-vs-reference-for-eeg-recording/\n", "2. (https://www.researchgate.net/post/What_is_the_difference_between_ground_and_reference_electrode_in_EEG_recording)\n", "\n", - "To summarize,\n", + "En resumen,\n", "\n", - "An EEG (electroencephalogram)is the potential difference between an active electrode and a reference electrode.\n", - "Voltage signals are always relative. You can have different references.\n", + "Un EEG (electroencefalograma) es la diferencia de potencial entre un electrodo activo y un electrodo de referencia.\n", + "Las senales de voltaje siempre son relativas. Puedes tener distintas referencias.\n", "\n", - "The ground electrode is used to reduce artifacts (electrical circuit, mouvement...), preventing noise from interfering with the signals of interest.\n", + "El electrodo de tierra se usa para reducir artefactos (circuito electrico, movimiento...), evitando que el ruido interfiera con las senales de interes.\n", "\n", - "Referencing is when you have an electrode you use to measure the electrical difference between the active electrode and itself.\n" + "La referencia es el electrodo que usas para medir la diferencia electrica entre el electrodo activo y el propio electrodo de referencia.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "\"The reference lead is the lead that connects the reference electrode; in EEG recordings, this electrode is usually placed at the ear or, in the case of “summed ears,” to a pair of electrodes, one at each ear. The measured electrical potential differences are ideally the voltage drops from the active electrode to the reference electrode.\n" + "\"El cable de referencia es el cable que conecta el electrodo de referencia; en los registros EEG, este electrodo suele colocarse en la oreja o, en el caso de \"orejas sumadas\", en un par de electrodos, uno en cada oreja. Las diferencias de potencial electrico medidas son idealmente las caidas de voltaje desde el electrodo activo hasta el electrodo de referencia.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Part 3: Neural Oscillations" + "## Parte 3: Oscilaciones neuronales\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "# UNDER CONSTRUCTION" + "# EN CONSTRUCCION\n" ] } ], diff --git a/02-Filtering.ipynb b/02-Filtering.ipynb index 673fb2f..063068e 100644 --- a/02-Filtering.ipynb +++ b/02-Filtering.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Filters" + "# Filtros\n" ] }, { @@ -13,14 +13,14 @@ "source": [ "**Michael Tran 2018, Torben Noto 2015**\n", "\n", - "In this notebook, I'm going to provide a broad but shallow overview of how filters basically work. There are many resources available for understanding filtering. This is just an introduction.\n" + "En este notebook voy a ofrecer una vision general amplia pero superficial de como funcionan basicamente los filtros. Hay muchos recursos disponibles para comprender el filtrado. Esto es solo una introduccion.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Default Imports" + "### Importaciones predeterminadas\n" ] }, { @@ -31,7 +31,7 @@ }, "outputs": [], "source": [ - "#setting settings and loading modules\n", + "# configurar parametros y cargar modulos\n", "from __future__ import division\n", "\n", "import time\n", @@ -43,16 +43,16 @@ "import scipy.io\n", "import scipy.signal\n", "from ipywidgets import interactive, IntSlider, FloatSlider, fixed\n", - "from IPython.display import display" + "from IPython.display import display\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "So what is a filter and why do we use them?\n", + "Entonces, ¿que es un filtro y por que lo usamos?\n", "\n", - "Filters are rad because they can isolate certain frequency bands in any oscillating signal. Here's an example:\n" + "Los filtros son utiles porque pueden aislar ciertas bandas de frecuencia en cualquier senal oscilatoria. Aqui tienes un ejemplo:\n" ] }, { @@ -72,39 +72,39 @@ } ], "source": [ - "#Settings used to generate a signal\n", - "f = 1024 #sampling frequency\n", - "dur = 10 #10 seconds of signal\n", - "freq = 7 #7 Hz signal\n", - "freq2 = 130 #130 Hz signal\n", - "\n", - "#Signal Generation\n", - "t = np.arange(0, dur, 1/f) #times for d\n", - "sig1 = np.sin(2 * np.pi * freq * t) #10 Hz wavelength\n", - "sig1 = 1.5*sig1; #increase the power of signal 1\n", - "sig2 = np.sin(2 * np.pi * freq2 * t) #130 Hz wavelength\n", + "# parametros usados para generar una senal\n", + "f = 1024 # frecuencia de muestreo\n", + "dur = 10 # 10 segundos de senal\n", + "freq = 7 # senal de 7 Hz\n", + "freq2 = 130 # senal de 130 Hz\n", + "\n", + "# generacion de la senal\n", + "t = np.arange(0, dur, 1/f) # tiempos para los datos\n", + "sig1 = np.sin(2 * np.pi * freq * t) # longitud de onda de 7 Hz\n", + "sig1 = 1.5*sig1; # aumentar la potencia de la senal 1\n", + "sig2 = np.sin(2 * np.pi * freq2 * t) # longitud de onda de 130 Hz\n", "complex_signal = sig1+sig2;\n", - "plt.plot(t[0:512],complex_signal[0:512], label = 'complex signal') #plot 0.5 seconds of data\n", + "plt.plot(t[0:512],complex_signal[0:512], label = 'senal compleja') # graficar 0.5 segundos de datos\n", "plt.legend()\n", - "plt.show()" + "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This signal is composed of two sin waves oscillating at different frequencies, a high-amplitude, slow frequency wave and a low-amplitude, high frequency wave. We can use a **filter** to get just one component of this complex wave and ignore everything else. The filter we will use is known as a Butterworth filter, you can read more about it [here](https://en.wikipedia.org/wiki/Butterworth_filter)\n", + "Esta senal esta compuesta por dos ondas sinusoidales que oscilan a diferentes frecuencias: una onda lenta de alta amplitud y una onda rapida de baja amplitud. Podemos usar un **filtro** para obtener solo un componente de esta onda compleja e ignorar todo lo demas. El filtro que usaremos se conoce como filtro de Butterworth; puedes leer mas sobre el [aqui](https://en.wikipedia.org/wiki/Butterworth_filter)\n", "\n", - "In the plot below, I used a filter called the Butterworth filter to seperate out the two freqencies present in a complex signal. This could be useful if, for example, that high frequency wave is noise and we're only interested in the lower frequency one. \n", - "There are many types of filters and none of them are perfect. Each filter has advantages and disadvantages and the details of these are important but I won't cover them here.\n", + "En la grafica de abajo, use un filtro llamado Butterworth para separar las dos frecuencias presentes en una senal compleja. Esto podria ser util si, por ejemplo, esa onda de alta frecuencia es ruido y solo nos interesa la de menor frecuencia.\n", + "Hay muchos tipos de filtros y ninguno es perfecto. Cada filtro tiene ventajas y desventajas, y esos detalles son importantes, pero no los cubrire aqui.\n", "\n", - "A Butterworth filter takes in 3 parameters:\n", - "- The sampling rate of the data\n", - "- A lower bound on the frequency band you want to keep\n", - "- An upper bound on the frequency band you want to keep\n", - "- An order of the filter. This determines how *sharply* the filter cuts off bounding frequencies.\n", + "Un filtro Butterworth recibe 3 parametros:\n", + "- La frecuencia de muestreo de los datos\n", + "- Un limite inferior de la banda de frecuencia que quieres conservar\n", + "- Un limite superior de la banda de frecuencia que quieres conservar\n", + "- El orden del filtro. Esto determina cuan *bruscamente* el filtro recorta las frecuencias limite.\n", "\n", - "Below are some functions to allow us to use the Butterworth filter. We will ignore the details of these functions for now as the most important part is not how to create a filter, but to understand why we use them." + "Abajo hay algunas funciones que nos permiten usar el filtro Butterworth. Por ahora ignoraremos los detalles de estas funciones, ya que lo mas importante no es como crear un filtro, sino entender por que lo usamos.\n" ] }, { @@ -117,10 +117,10 @@ "source": [ "\n", "def butter_bandpass(lowcut, highcut, fs, order=4):\n", - " #lowcut is the lower bound of the frequency that we want to isolate\n", - " #hicut is the upper bound of the frequency that we want to isolate\n", - " #fs is the sampling rate of our data\n", - " nyq = 0.5 * fs #nyquist frequency - see http://www.dspguide.com/ if you want more info\n", + " # lowcut es el limite inferior de la frecuencia que queremos aislar\n", + " # highcut es el limite superior de la frecuencia que queremos aislar\n", + " # fs es la frecuencia de muestreo de nuestros datos\n", + " nyq = 0.5 * fs # frecuencia de Nyquist; ver http://www.dspguide.com/ si quieres mas informacion\n", " low = float(lowcut) / nyq\n", " high = float(highcut) / nyq\n", " b, a = sp.signal.butter(order, [low, high], btype='band')\n", @@ -129,7 +129,7 @@ "def butter_bandpass_filter(mydata, lowcut, highcut, fs, order=4):\n", " b, a = butter_bandpass(lowcut, highcut, fs, order=order)\n", " y = sp.signal.filtfilt(b, a, mydata)\n", - " return y" + " return y\n" ] }, { @@ -169,7 +169,7 @@ } ], "source": [ - "#Using filters to isolate high and low frequencies\n", + "# usar filtros para aislar frecuencias altas y bajas\n", "lo_cut = 6;\n", "hi_cut = 8;\n", "low_filtered_dat = butter_bandpass_filter(complex_signal,lo_cut,hi_cut,1024);\n", @@ -177,24 +177,24 @@ "hi_cut = 140;\n", "hi_filtered_dat = butter_bandpass_filter(complex_signal,lo_cut,hi_cut,1024);\n", "\n", - "#Separating our plots\n", + "# separar nuestras graficas\n", "plt.figure(figsize = (15,6));\n", - "plt.plot(t[0:512],complex_signal[0:512], label = 'complex signal') #plot 0.5 seconds of data\n", + "plt.plot(t[0:512],complex_signal[0:512], label = 'senal compleja') # graficar 0.5 segundos de datos\n", "plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", "plt.show()\n", - "plt.plot(t[0:512],low_filtered_dat[0:512], color = 'k', label = 'low frequency component') #plot 0.5 seconds of low frequency signal\n", + "plt.plot(t[0:512],low_filtered_dat[0:512], color = 'k', label = 'componente de baja frecuencia') # graficar 0.5 segundos de la senal de baja frecuencia\n", "plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", "plt.show()\n", - "plt.plot(t[0:512],hi_filtered_dat[0:512], color = 'g', label = 'high frequency component') #plot 0.5 seconds of high frequency signal\n", + "plt.plot(t[0:512],hi_filtered_dat[0:512], color = 'g', label = 'componente de alta frecuencia') # graficar 0.5 segundos de la senal de alta frecuencia\n", "plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", - "plt.show()" + "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We have separated our complex signal into two components: the low frequency component and the high frequency component." + "Hemos separado nuestra senal compleja en dos componentes: el componente de baja frecuencia y el componente de alta frecuencia.\n" ] }, { @@ -214,27 +214,26 @@ } ], "source": [ - "#Overlapping our plots for a better visualization\n", - "plt.plot(t[0:512],complex_signal[0:512], label = 'complex signal') #plot 0.5 seconds of data\n", - "plt.plot(t[0:512],low_filtered_dat[0:512], color = 'k', label = 'low frequency component') #plot 0.5 seconds of low frequency signal\n", - "plt.plot(t[0:512],hi_filtered_dat[0:512], color = 'g', label = 'high frequency component') #plot 0.5 seconds of high frequency signal\n", + "# superponer nuestras graficas para una mejor visualizacion\n", + "plt.plot(t[0:512],complex_signal[0:512], label = 'senal compleja') # graficar 0.5 segundos de datos\n", + "plt.plot(t[0:512],low_filtered_dat[0:512], color = 'k', label = 'componente de baja frecuencia') # graficar 0.5 segundos de la senal de baja frecuencia\n", + "plt.plot(t[0:512],hi_filtered_dat[0:512], color = 'g', label = 'componente de alta frecuencia') # graficar 0.5 segundos de la senal de alta frecuencia\n", "plt.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", - "plt.show()" + "plt.show()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "\n", - "# UNDER CONSTRUCTION BELOW" + "# EN CONSTRUCCION A CONTINUACION\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If you run this notebook locally, you can use the output of the next cell to play with a filter on some ECoG data to see what kinds of features of the signal that you can pick out in different frequency bands." + "Si ejecutas este notebook localmente, puedes usar la salida de la siguiente celda para jugar con un filtro en algunos datos de ECoG y ver que tipos de caracteristicas de la senal puedes distinguir en diferentes bandas de frecuencia.\n" ] }, { @@ -262,7 +261,7 @@ "filename = os.path.join('./', filename)\n", "data = sp.io.loadmat(filename)\n", "srate = data['srate'];\n", - "data = data['data']; # time series\n", + "data = data['data']; # serie temporal\n", "data = data[0, :];\n", "dat = data[0:1024];\n", "def filter_dat(lo_cut,hi_cut,order): \n", @@ -270,8 +269,8 @@ " filtdat = butter_bandpass_filter(dat,lo_cut,hi_cut,srate,order);\n", " fig = plt.figure(figsize=(24,6))\n", " ax1 = fig.add_subplot(2, 1, 1)\n", - " plt.plot(dat,lw=2,color='blue',label = 'raw data')\n", - " plt.plot(filtdat,lw=2,color='black',label='filtered data')\n", + " plt.plot(dat,lw=2,color='blue',label = 'datos sin filtrar')\n", + " plt.plot(filtdat,lw=2,color='black',label='datos filtrados')\n", " plt.xlim(0, 1024)\n", " legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", " plt.show()\n", @@ -283,18 +282,18 @@ "\n", "w=interactive(filter_dat,lo_cut=a_slider,hi_cut=b_slider,order=c_slider)\n", "\n", - "display(w)" + "display(w)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "So far, I've been trying to provide you with an intuition for what a filter can do.\n", + "Hasta ahora he tratado de darte una intuicion de lo que puede hacer un filtro.\n", "\n", - "Now we're going to look at how a simple filter works, mathematically:\n", + "Ahora vamos a ver como funciona matematicamente un filtro sencillo:\n", "\n", - "The simplest filter is a convolution filter. In this kind of filter, we slide a shape (often called a kernal) along the data. As it passes along the data, each point on the kernal multiplies a point on the data. In the next cell we'll see what happens if we slide a gaussian distribution (a pretty common filter) along a delta function (zeros with one 1) and some real ECoG data.\n" + "El filtro mas simple es un filtro de convolucion. En este tipo de filtro, desplazamos una forma (a menudo llamada kernel) a lo largo de los datos. A medida que pasa sobre los datos, cada punto del kernel multiplica un punto de los datos. En la siguiente celda veremos que ocurre si desplazamos una distribucion gaussiana (un filtro bastante comun) sobre una funcion delta (ceros con un unico 1) y sobre algunos datos reales de ECoG.\n" ] }, { @@ -335,8 +334,8 @@ "\n", "dat = data[0:1024];\n", "\n", - "#kernel 1: Gaussian Filter\n", - "x = np.linspace(0, 1, 10) #size of filter\n", + "# kernel 1: filtro gaussiano\n", + "x = np.linspace(0, 1, 10) # tamano del filtro\n", "\n", "mu = .5;\n", "sig =.25; ##\n", @@ -350,34 +349,34 @@ "\n", "fig = plt.figure(figsize=(24,6))\n", "ax1 = fig.add_subplot(2, 1, 1);\n", - "ax1.plot(delta_funct,color = 'b',label = 'delta function')\n", - "ax1.plot(convolved_delt,color = 'r',label = 'filtered delta')\n", + "ax1.plot(delta_funct,color = 'b',label = 'funcion delta')\n", + "ax1.plot(convolved_delt,color = 'r',label = 'delta filtrada')\n", "legend()\n", - "title('Filtering a Delta Function')\n", + "title('Filtrado de una funcion delta')\n", "\n", "\n", "ax2 = fig.add_subplot(2, 1, 2);\n", - "ax2.plot(dat*2,color = 'b',label = 'raw data') #multiplied by 2 to scale to filtered data\n", - "ax2.plot(convolved_dat,color = 'r',label = 'filtered data')\n", + "ax2.plot(dat*2,color = 'b',label = 'datos sin filtrar') # multiplicado por 2 para escalar a los datos filtrados\n", + "ax2.plot(convolved_dat,color = 'r',label = 'datos filtrados')\n", "legend()\n", - "title('Filtering a Delta Function')" + "title('Filtrado de una funcion delta')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Something looks wrong.\n", + "Algo parece estar mal.\n", "\n", - "Why is the filtered data shifted over to the right in both graphs?\n", + "¿Por que los datos filtrados estan desplazados hacia la derecha en ambas graficas?\n", "\n", - "To answer this, let's look at the filtered delta function.\n", + "Para responder eso, veamos la funcion delta filtrada.\n", "\n", - "A convolution is the same as sliding our kernal over the data and multiplying our data by each point in the kernal. As the gaussian filter slid left to right across 0's each point was multiplied by 0, resulting in nothing. However, when the nose of the gaussian filter reached the 1 in the delta function, it multiplied the leading non-zero value of the gaussian by 1. As we kept pushing the shape through, each point in the filter was multiplied by 1. You'll see that the length of the vector produced by the convolution is the length of the data + the length of the filter - 1. This happened beacuse had to multiply each point in the data by both the nose and the tail of the kernal, resulting in some extra points. Because we simply multiplied each point in the kernal by 1, convolving a delta function with any filter will perfectly reproduce the kernal.\n", + "Una convolucion es lo mismo que deslizar nuestro kernel sobre los datos y multiplicar los datos por cada punto del kernel. A medida que el filtro gaussiano se desplazaba de izquierda a derecha sobre ceros, cada punto se multiplicaba por 0, lo que no producia nada. Sin embargo, cuando la punta del filtro gaussiano alcanzo el 1 de la funcion delta, multiplico por 1 el primer valor no nulo de la gaussiana. A medida que seguiamos empujando la forma, cada punto del filtro se multiplicaba por 1. Veras que la longitud del vector producido por la convolucion es la longitud de los datos + la longitud del filtro - 1. Esto sucedio porque tuvimos que multiplicar cada punto de los datos tanto por la punta como por la cola del kernel, lo que produjo algunos puntos extra. Debido a que simplemente multiplicamos cada punto del kernel por 1, convolucionar una funcion delta con cualquier filtro reproducira perfectamente el kernel.\n", "\n", - "What if we don't want our filtered data to be shifted? And how come the filtered data a few cells above isn't shifted?\n", + "¿Que pasa si no queremos que nuestros datos filtrados queden desplazados? ¿Y por que los datos filtrados de unas celdas arriba no estan desplazados?\n", "\n", - "In the next cell I'll show you some simple ways to get rid of this shift.\n" + "En la siguiente celda te mostrare algunas maneras sencillas de eliminar ese desplazamiento.\n" ] }, { @@ -414,9 +413,9 @@ "source": [ "dat = data[0:1024];\n", "\n", - "#time lag resistant kernel #1: Causal Filter (exponential filter)\n", - "#filter parameters\n", - "x = np.linspace(0, 1, 10) #size of filter\n", + "# kernel resistente al desfase temporal n.° 1: filtro causal (filtro exponencial)\n", + "# parametros del filtro\n", + "x = np.linspace(0, 1, 10) # tamano del filtro\n", "tau = .5;\n", "amp_reduct = .1;\n", "def generate_causal_filter(x,tau,amp_reduct):\n", @@ -430,7 +429,7 @@ "convolved_dat_causal_filt = sp.signal.convolve(dat,causal_filter)\n", "\n", "\n", - "#time lag resistant kernel #2: Two-way Filter\n", + "# kernel resistente al desfase temporal n.° 2: filtro bidireccional\n", "convolved_delt_two_way = sp.signal.convolve(delta_funct,gaussian_filter)\n", "convolved_delt_two_way = convolved_delt_two_way[0:len(delta_funct)]\n", "convolved_delt_two_way = sp.signal.convolve(list(reversed(convolved_delt_two_way)),gaussian_filter)\n", @@ -441,30 +440,30 @@ "convolved_dat_two_way = sp.signal.convolve(list(reversed(convolved_dat_two_way)),gaussian_filter)\n", "convolved_dat_two_way = list(reversed(convolved_dat_two_way[0:len(dat)]))\n", "\n", - "#plotting\n", + "# graficar\n", "fig = plt.figure(figsize=(24,8))\n", "ax1 = fig.add_subplot(2, 2, 1);\n", - "ax1.plot(delta_funct,color = 'b',label = 'delta function')\n", - "ax1.plot(convolved_delt_causal_filt,color = 'r',label = 'filtered delta')\n", + "ax1.plot(delta_funct,color = 'b',label = 'funcion delta')\n", + "ax1.plot(convolved_delt_causal_filt,color = 'r',label = 'delta filtrada')\n", "legend()\n", - "title('Filtering a delta function with a causal filter')\n", + "title('Filtrado de una funcion delta con un filtro causal')\n", "\n", "ax2 = fig.add_subplot(2, 2, 2);\n", - "ax2.plot(dat*2,color = 'b',label = 'raw data') #multiplied by 2 to scale to filtered data\n", - "ax2.plot(convolved_dat_causal_filt,color = 'r',label = 'filtered data')\n", - "title('Filtering data with a causal filter')\n", + "ax2.plot(dat*2,color = 'b',label = 'datos sin filtrar') # multiplicado por 2 para escalar a los datos filtrados\n", + "ax2.plot(convolved_dat_causal_filt,color = 'r',label = 'datos filtrados')\n", + "title('Filtrado de datos con un filtro causal')\n", "legend()\n", "\n", "ax3 = fig.add_subplot(2, 2, 3);\n", - "ax3.plot(delta_funct*10,color = 'b',label = 'delta function')\n", - "ax3.plot(convolved_delt_two_way,color = 'r',label = 'filtered delta')\n", + "ax3.plot(delta_funct*10,color = 'b',label = 'funcion delta')\n", + "ax3.plot(convolved_delt_two_way,color = 'r',label = 'delta filtrada')\n", "legend()\n", - "title('Filtering a delta function with a two-way filter')\n", + "title('Filtrado de una funcion delta con un filtro bidireccional')\n", "\n", "ax4 = fig.add_subplot(2, 2, 4);\n", - "ax4.plot(dat*50,color = 'b',label = 'raw data')\n", - "ax4.plot(convolved_dat_two_way, color = 'r', label = 'Filtering data with a two-way filter')\n", - "title('Filtering data with a two-way filter')\n", + "ax4.plot(dat*50,color = 'b',label = 'datos sin filtrar')\n", + "ax4.plot(convolved_dat_two_way, color = 'r', label = 'Filtrado de datos con un filtro bidireccional')\n", + "title('Filtrado de datos con un filtro bidireccional')\n", "legend()\n" ] }, @@ -472,19 +471,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "One way of getting rid of dealing with time lag is to have a filter with no leading tail like we do here with a causal filter.\n", + "Una forma de evitar lidiar con el desfase temporal es usar un filtro sin cola adelantada, como hacemos aqui con un filtro causal.\n", "\n", - "Another way is to perform a convolution on the data with a filter kernal, then convolve the convolved data again, backwards. This works because convolving the convolved data backwards reverses any time lag, exactly. This is what the sp.signal.filtfilt method in one of the first cells does. Try replacing sp.signal.filtfilt with sp.signal.lfilter and you'll see the time lag occur.\n", + "Otra forma es realizar una convolucion de los datos con un kernel de filtro y luego convolucionar nuevamente los datos ya convolucionados, pero hacia atras. Esto funciona porque convolucionar los datos filtrados hacia atras revierte exactamente cualquier desfase temporal. Eso es lo que hace el metodo sp.signal.filtfilt en una de las primeras celdas. Intenta reemplazar sp.signal.filtfilt por sp.signal.lfilter y veras aparecer el desfase temporal.\n", "\n", - "There are many, many filtering methods and these are just a few simple ones. There is no such thing as a perfect filter. Some filtering methods are better for certain uses and picking the best one takes some expertise.\n", + "Existen muchisimos metodos de filtrado y estos son solo algunos sencillos. No existe el filtro perfecto. Algunos metodos de filtrado son mejores para ciertos usos, y elegir el mejor requiere cierta experiencia.\n", "\n", - "What we learned:\n", + "Lo que aprendimos:\n", "\n", - " Filters help us see what is going on in different frequency ranges in data\n", - " You can apply a filter to data in just a few lines of code\n", - " Filters work by convolving a shape with your data, the same as multiplying everything on a sliding window\n", - " Time delay in filtering is a problem that can be solved.\n", - "\n" + " Los filtros nos ayudan a ver lo que ocurre en distintos rangos de frecuencia de los datos\n", + " Puedes aplicar un filtro a los datos con solo unas pocas lineas de codigo\n", + " Los filtros funcionan convolucionando una forma con tus datos, equivalente a multiplicar todo dentro de una ventana deslizante\n", + " El retraso temporal en el filtrado es un problema que puede resolverse.\n" ] }, { diff --git a/03-SpectralMethods.ipynb b/03-SpectralMethods.ipynb index 71bd79e..cefc8be 100644 --- a/03-SpectralMethods.ipynb +++ b/03-SpectralMethods.ipynb @@ -4,32 +4,32 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Spectral Methods and the PSD\n", + "# Metodos espectrales y la PSD\n", "\n", - "##### Sydney Smith 2018, Torben Noto 2015" + "##### Sydney Smith 2018, Torben Noto 2015\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Although there are many ways you can process a digital signal, one of the most useful is the power spectral density (PSD). The PSD allows you to vizualize what frequencies are present in a signal. In other words, the PSD lets you look at the signal in the **frequency domain**. Discovering which frequencies are present allows you to investigate the signal beyond the time domain and can be very useful for large-scale data analysis. Let's go over how to generate one.\n", - "\n", - "The purpose of this tutorial is to:\n", - "1. Define the PSD\n", - "2. Introduce the Fourier Transform\n", - "3. Demonstrate how the Fourier transform is used to analyze a complex signal\n", - "4. Generate a PSD from real electrophysiological data\n", - "5. Identify features in the PSD that are important for data analysis" + "Aunque hay muchas formas de procesar una senal digital, una de las mas utiles es la densidad espectral de potencia (PSD). La PSD te permite visualizar que frecuencias estan presentes en una senal. En otras palabras, la PSD te permite observar la senal en el **dominio de la frecuencia**. Descubrir que frecuencias estan presentes te permite investigar la senal mas alla del dominio temporal y puede ser muy util para el analisis de datos a gran escala. Veamos como generar una.\n", + "\n", + "El proposito de este tutorial es:\n", + "1. Definir la PSD\n", + "2. Introducir la transformada de Fourier\n", + "3. Demostrar como se usa la transformada de Fourier para analizar una senal compleja\n", + "4. Generar una PSD a partir de datos electrofisiologicos reales\n", + "5. Identificar caracteristicas de la PSD que son importantes para el analisis de datos\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Default Imports\n", + "### Importaciones predeterminadas\n", "\n", - "First, let's import some python libraries that contain the functions we need to do this tutorial. I've also included some figure formatting to make sure our plots are easy to read." + "Primero, importemos algunas bibliotecas de Python que contienen las funciones que necesitamos para realizar este tutorial. Tambien he incluido algo de formato para las figuras para asegurar que nuestras graficas sean faciles de leer.\n" ] }, { @@ -67,9 +67,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Analyzing data in the frequency domain: The PSD\n", + "## 1. Analizar datos en el dominio de la frecuencia: la PSD\n", "\n", - "Electrophysiological signals are time series composed of many different frequencies. Each of these frequencies contains some amount of voltage power. In the analysis of electrophysiological signals, it can be useful to determine what frequencies are present and how much power they have. These measurements of frequency and power can be correlated to a variety of factors associated with brain function, allowing us to learn even more about the brain." + "Las senales electrofisiologicas son series temporales compuestas por muchas frecuencias diferentes. Cada una de estas frecuencias contiene cierta cantidad de potencia de voltaje. En el analisis de senales electrofisiologicas, puede ser util determinar que frecuencias estan presentes y cuanta potencia tienen. Estas mediciones de frecuencia y potencia pueden correlacionarse con una variedad de factores asociados a la funcion cerebral, lo que nos permite aprender aun mas sobre el cerebro.\n" ] }, { @@ -83,37 +83,37 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Pictured above is an example of a PSD calculated from the time series recording from the hippocampus of a rat.\n", + "La imagen de arriba muestra un ejemplo de una PSD calculada a partir del registro de una serie temporal del hipocampo de una rata.\n", "\n", - "The power spectral density (PSD) is a graphical representation of the frequencies present in a signal that allows us to vizualize how much power is present in each frequency. The plot of **power vs. frequency** is known as a spectrum. PSDs aren't limited to the analysis of neural signals; they can be used to vizualize any kind of time series data (eg. sounds, financial trends, earthquakes, etc.). \n", + "La densidad espectral de potencia (PSD) es una representacion grafica de las frecuencias presentes en una senal que nos permite visualizar cuanta potencia hay en cada frecuencia. La grafica de **potencia vs. frecuencia** se conoce como espectro. Las PSD no se limitan al analisis de senales neuronales; pueden usarse para visualizar cualquier tipo de serie temporal (por ejemplo, sonidos, tendencias financieras, terremotos, etc.).\n", "\n", - "In the next sections, we'll delve a little deeper into how the PSD is generated and how to read it. " + "En las siguientes secciones profundizaremos un poco mas en como se genera la PSD y como leerla.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. The Fourier Transform\n", + "## 2. La transformada de Fourier\n", "\n", - "The mathmatical technique that allows us to calculate the PSD is called the Fourier Transform. **The Fourier Transform measures the amplitude of every frequency in a signal**. The math that it takes to do this is pretty brilliant and challenging but we don't have to get too deep into it.\n", + "La tecnica matematica que nos permite calcular la PSD se llama transformada de Fourier. **La transformada de Fourier mide la amplitud de cada frecuencia en una senal**. Las matematicas necesarias para hacerlo son brillantes y desafiantes, pero no necesitamos profundizar demasiado en ellas.\n", "\n", - "Here's an analogy: Imagine you play a chord on a piano. If you ran a Fourier transform on the sound signal, you could see how hard you pressed each of the keys. However, in the brain, there are a lot of frequencies present in the same signal and they aren't as simple as a chord with 3 discrete notes. \n", + "Aqui va una analogia: imagina que tocas un acorde en un piano. Si aplicaras una transformada de Fourier a la senal de sonido, podrias ver con que fuerza presionaste cada tecla. Sin embargo, en el cerebro hay muchas frecuencias presentes en la misma senal y no son tan simples como un acorde con 3 notas discretas.\n", "\n", - "For now, let's try something simpler to investigate what a Fourier Transform can tell us about a signal. Let's start by running it on a complex sinusoid." + "Por ahora, intentemos algo mas simple para investigar que puede decirnos una transformada de Fourier sobre una senal. Empecemos aplicandola a una senoide compleja.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. The FFT of a complex sinusoid\n", + "## 3. La FFT de una senoide compleja\n", "\n", - "In this section, I will generate a complex sinusoid that is composed of 2 frequencies: 7 Hz and 130 Hz. Then, I'll run the Fourier Transform, abbreviated here as \"FFT.\"\n", + "En esta seccion generare una senoide compleja compuesta por 2 frecuencias: 7 Hz y 130 Hz. Luego ejecutare la transformada de Fourier, abreviada aqui como \"FFT\".\n", "\n", - "#### Generating the a complex sinusoid\n", + "#### Generar una senoide compleja\n", "\n", - "To make the following signal, I added 2 sin waves together. There is a slower wave (7 Hz) with a large amplitude and a fast wave (130 Hz) with a smaller amplitude. Make sure that you pick these out." + "Para construir la siguiente senal, sume 2 ondas sinusoidales. Hay una onda mas lenta (7 Hz) con gran amplitud y una onda rapida (130 Hz) con menor amplitud. Asegurate de poder identificarlas.\n" ] }, { @@ -143,26 +143,26 @@ } ], "source": [ - "f = 1024 #sampling frequency\n", - "dur = 10 #10 seconds of signal\n", - "freq = 7 #7 Hz signal\n", - "freq2 = 130 #130 Hz signal\n", - "t = np.arange(0, dur, 1/f) #times for d\n", - "sig1 = np.sin(2 * np.pi * freq * t) #10 Hz wavelength\n", - "sig1 = 1.5*sig1; #increase the power of signal 1\n", - "sig2 = np.sin(2 * np.pi * freq2 * t) #130 Hz wavelength\n", + "f = 1024 # frecuencia de muestreo\n", + "dur = 10 # 10 segundos de senal\n", + "freq = 7 # senal de 7 Hz\n", + "freq2 = 130 # senal de 130 Hz\n", + "t = np.arange(0, dur, 1/f) # tiempos para los datos\n", + "sig1 = np.sin(2 * np.pi * freq * t) # longitud de onda de 7 Hz\n", + "sig1 = 1.5*sig1; # aumentar la potencia de la senal 1\n", + "sig2 = np.sin(2 * np.pi * freq2 * t) # longitud de onda de 130 Hz\n", "plt.figure(figsize=(16,6))\n", - "plt.title(\"Complex Signal (7Hz + 130Hz)\", size=18)\n", - "plt.plot(t[0:512],sig1[0:512]+sig2[0:512]) #plot 0.5 seconds of data" + "plt.title(\"Senal compleja (7 Hz + 130 Hz)\", size=18)\n", + "plt.plot(t[0:512],sig1[0:512]+sig2[0:512]) # graficar 0.5 segundos de datos\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Running and Plotting the FFT\n", + "#### Ejecutar y graficar la FFT\n", "\n", - "Now that we have the complex signal, let's run the FFT and see if it can pick out the 2 component frequencies. We can vizualize the output in a plot of Power vs. Frequency. Recall from the first section that this is called a spectrum." + "Ahora que tenemos la senal compleja, ejecutemos la FFT y veamos si puede detectar las 2 frecuencias componentes. Podemos visualizar la salida en una grafica de Potencia vs. Frecuencia. Recuerda de la primera seccion que esto se llama espectro.\n" ] }, { @@ -200,48 +200,48 @@ } ], "source": [ - "# calculating fourier transform of complex signal\n", + "# calcular la transformada de Fourier de la senal compleja\n", "fourier = np.fft.fft(sig1+sig2)\n", "\n", - "# finding frequency values for the x axis\n", + "# encontrar los valores de frecuencia para el eje x\n", "fx_step_size = f/len(sig1)\n", "nyq = f/2\n", "total_steps = nyq/fx_step_size\n", "fx_bins = np.linspace(0,nyq,total_steps)\n", "\n", - "# plotting up to 200 Hz\n", + "# graficar hasta 200 Hz\n", "plt.figure(figsize = (10,6))\n", "plt.plot(fx_bins[0:1500],abs(fourier[0:1500]))\n", - "plt.ylabel('Power')\n", - "plt.xlabel('Frequency (Hz)')\n", - "plt.title('FFT of a complex signal', size=18)" + "plt.ylabel('Potencia')\n", + "plt.xlabel('Frecuencia (Hz)')\n", + "plt.title('FFT de una senal compleja', size=18)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "So in this plot we're looking at the power of all of the freqencies present in our signal.\n", + "En esta grafica estamos observando la potencia de todas las frecuencias presentes en nuestra senal.\n", "\n", - "We can clearly see that there is a peak at 7 Hz and a peak at 130 Hz.\n", - "We can also see that the 7 Hz peak has a greater amplitude than the one at 130 Hz.\n", + "Podemos ver claramente que hay un pico en 7 Hz y otro en 130 Hz.\n", + "Tambien podemos ver que el pico de 7 Hz tiene una amplitud mayor que el de 130 Hz.\n", "\n", - "From this we can conclude that the Fourier Transform accurately identified both frequency components in the signal in addition to telling us how much power (amplitude) is present in each of those components.\n", + "A partir de esto podemos concluir que la transformada de Fourier identifico con precision ambos componentes de frecuencia en la senal, ademas de indicarnos cuanta potencia (amplitud) esta presente en cada uno de ellos.\n", "\n", - "However, notice that when we do this, we can't see any information about the timing in our signal. When looking at a signal in frequency space, we can't know anything about the **offset of the phases** of these oscillations.\n", + "Sin embargo, observa que al hacer esto no podemos ver informacion sobre el tiempo en nuestra senal. Al mirar una senal en el espacio de frecuencias, no podemos saber nada sobre el **desplazamiento de fase** de estas oscilaciones.\n", "\n", - "But we still have information about phase. This information is stored as complex numbers that we're not plotting above. It's called a Fourier **transform** because **no information is lost when we apply it**. You can calculate the fourier transform or the inverse fourier transform of a signal over and over again and not lose any information, effectively switching between the frequency and time domains. " + "Pero aun conservamos informacion sobre la fase. Esa informacion se almacena como numeros complejos que no estamos graficando arriba. Se llama Fourier **transform** porque **no se pierde informacion cuando la aplicamos**. Puedes calcular la transformada de Fourier o la transformada inversa de Fourier de una senal una y otra vez sin perder informacion, cambiando efectivamente entre los dominios de la frecuencia y del tiempo.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 4. Generating the PSD of electrophysiological data\n", + "## 4. Generar la PSD de datos electrofisiologicos\n", "\n", - "Now that we've demonstrated how the FFT can help us look at a signal in the frequency domain, let's apply it to something a little more interesting: electrophysiological data. Specifically, in this section we will use the FFT to generate a PSD of a real ECoG signal. \n", + "Ahora que hemos demostrado como la FFT puede ayudarnos a observar una senal en el dominio de la frecuencia, apliquemola a algo un poco mas interesante: datos electrofisiologicos. Especificamente, en esta seccion usaremos la FFT para generar una PSD de una senal real de ECoG.\n", "\n", - "#### Load the electrophysiological data (ECoG)" + "#### Cargar los datos electrofisiologicos (ECoG)\n" ] }, { @@ -250,20 +250,20 @@ "metadata": {}, "outputs": [], "source": [ - "#loading data\n", + "# cargar datos\n", "path = 'dat/emodat.npy'\n", "\n", - "data = np.load(path)" + "data = np.load(path)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Returning to sampling rate \n", - "The sampling rate is important for analyzing in the frequency domain because it determines the range of frequencies that can be detected in the signal. If you need to review sampling rate, see [our tutorial](LINK) or, if you want a more in-depth explanation, check out this [interactive guide](https://jackschaedler.github.io/circles-sines-signals/part2.html) from Jack Schaedler.\n", + "#### Volviendo a la frecuencia de muestreo\n", + "La frecuencia de muestreo es importante para analizar en el dominio de la frecuencia porque determina el rango de frecuencias que pueden detectarse en la senal. Si necesitas repasar este concepto, consulta [nuestro tutorial](LINK) o, si quieres una explicacion mas profunda, revisa esta [guia interactiva](https://jackschaedler.github.io/circles-sines-signals/part2.html) de Jack Schaedler.\n", "\n", - "I'll print the sampling rate for the data we loaded below." + "A continuacion imprimire la frecuencia de muestreo de los datos que cargamos.\n" ] }, { @@ -282,26 +282,26 @@ "source": [ "srate = 1017.2533333333334\n", "\n", - "#resample at 1024 Hz\n", - "newsrate = 1024 # new sampling rate\n", + "# remuestrear a 1024 Hz\n", + "newsrate = 1024 # nueva frecuencia de muestreo\n", "ecog_signal = sp.signal.resample(data, int(np.floor(len(data)*(newsrate/srate))))\n", - "srate = newsrate" + "srate = newsrate\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The sampling rate for this data is about 1017 Hz. This means we can detect frequencies in the signal up to about 508 Hz. I won't go into detail about why this is, but if you're curious, use the links above to find more information." + "La frecuencia de muestreo de estos datos es de aproximadamente 1017 Hz. Esto significa que podemos detectar frecuencias en la senal de hasta aproximadamente 508 Hz. No entrare en detalle sobre por que ocurre esto, pero si tienes curiosidad, usa los enlaces de arriba para encontrar mas informacion.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Plot the data in the time domain\n", + "#### Graficar los datos en el dominio temporal\n", "\n", - "Plotted below is 1 second of neural data. You might observe some up-and-downs and conclude that it is oscillatory, but it's not too insightful otherwise." + "Abajo se muestra 1 segundo de datos neuronales. Puede que observes algunas subidas y bajadas y concluyas que es oscilatorio, pero mas alla de eso no resulta muy informativo.\n" ] }, { @@ -342,9 +342,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "#### Calculate and plot the PSD using the FFT\n", + "#### Calcular y graficar la PSD usando la FFT\n", "\n", - "Now that we've loaded the ECoG signal and we know what it looks like in the time domain, let's run a FFT and plot the output into a PSD." + "Ahora que hemos cargado la senal de ECoG y sabemos como se ve en el dominio temporal, ejecutemos una FFT y grafiquemos la salida como una PSD.\n" ] }, { @@ -384,28 +384,28 @@ } ], "source": [ - "# calculating fourier transform of complex signal\n", - "# we're going to take a sample of the data to keep fx bins at a reasonable size.\n", + "# calcular la transformada de Fourier de la senal compleja\n", + "# vamos a tomar una muestra de los datos para mantener un tamano razonable de los bins de frecuencia\n", "fourier = np.fft.fft(data[0:10000]) \n", "\n", - "# finding frequency values for the x axis\n", + "# encontrar los valores de frecuencia para el eje x\n", "fx_step_size = srate/len(data[0:10000])\n", "nyq = srate/2\n", "total_steps = nyq/fx_step_size\n", "fx_bins = np.linspace(0,nyq,total_steps)\n", "\n", "plt.figure(figsize=(16,10))\n", - "plt.plot(fx_bins[0:2000],abs(fourier[0:2000])) #any frequencies above 200 Hz are probably noise\n", - "plt.ylabel('Power')\n", - "plt.xlabel('Frequency (Hz)')\n", - "plt.title('FFT of ECoG signal', size=18)" + "plt.plot(fx_bins[0:2000],abs(fourier[0:2000])) # cualquier frecuencia por encima de 200 Hz probablemente sea ruido\n", + "plt.ylabel('Potencia')\n", + "plt.xlabel('Frecuencia (Hz)')\n", + "plt.title('FFT de la senal de ECoG', size=18)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Tada! Our first PSD! It looks significantly different than the one we just made for the complex signal. This one looks pretty messy and is difficult to interpret because power seems to be decaying exponentially with frequency. So let's try plotting it in log scale. " + "¡Listo! ¡Nuestra primera PSD! Se ve considerablemente diferente de la que acabamos de hacer para la senal compleja. Esta se ve bastante desordenada y es dificil de interpretar porque la potencia parece decaer exponencialmente con la frecuencia. Asi que intentemos graficarla en escala logaritmica.\n" ] }, { @@ -436,25 +436,25 @@ ], "source": [ "plt.figure(figsize=(16,10))\n", - "plt.loglog((fx_bins[0:2000]),(abs(fourier[0:2000]))) #any frequencies above 200 Hz are probably noise\n", + "plt.loglog((fx_bins[0:2000]),(abs(fourier[0:2000]))) # cualquier frecuencia por encima de 200 Hz probablemente sea ruido\n", "plt.xlim([1,200])\n", - "plt.ylabel('Power')\n", - "plt.xlabel('Frequency (Hz)')\n", - "plt.title('FFT of ECoG signal (log scale)', size=18)" + "plt.ylabel('Potencia')\n", + "plt.xlabel('Frecuencia (Hz)')\n", + "plt.title('FFT de la senal de ECoG (escala logaritmica)', size=18)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "That looks a little better. We can see that there are many wavelengths that contribute to this signal, a stark comparison to the two-component sinusoid we analyzed earlier. Additionally, notice that it looks like longer wavelengths (slower frequencies) seem to have a larger power than shorter wavelengths (higher frequencies).\n", + "Eso se ve un poco mejor. Podemos ver que hay muchas longitudes de onda que contribuyen a esta senal, en fuerte contraste con la senoide de dos componentes que analizamos antes. Ademas, observa que parece que las longitudes de onda mas largas (frecuencias mas lentas) tienen mayor potencia que las longitudes de onda mas cortas (frecuencias mas altas).\n", "\n", - "##### Slope of the PSD and 1/f power law\n", - "While messy, the data in this plot show an interesting relationship. The data form a rough line that proceeds downward diagonally from the upper left corner to the lower right corner of the plot. Actually, the equation for this line is P = 1/f. This is a very special mathmatical ratio called a power law distribution or pink noise. 1/f relationships show up everywhere in nature in spooky ways. Magnitudes of earthquakes, fluctuations in the stock market, sizes of craters on the moon, and even the power spectrum of popular music all have power law distributions. Here we can see the same relationship in neural signals. We'll look at the 1/f relationship in more detail in a later tutorial but for now, back to the PSD!\n", + "##### Pendiente de la PSD y ley de potencia 1/f\n", + "Aunque desordenados, los datos de esta grafica muestran una relacion interesante. Forman una linea aproximada que desciende en diagonal desde la esquina superior izquierda hasta la esquina inferior derecha. De hecho, la ecuacion de esta linea es P = 1/f. Esta es una relacion matematica muy especial llamada distribucion de ley de potencia o ruido rosa. Las relaciones 1/f aparecen en todas partes en la naturaleza de formas sorprendentes. La magnitud de los terremotos, las fluctuaciones del mercado de valores, los tamanos de los crateres en la luna e incluso el espectro de potencia de la musica popular presentan distribuciones de ley de potencia. Aqui podemos ver la misma relacion en las senales neuronales. Veremos la relacion 1/f con mas detalle en un tutorial posterior, pero por ahora, volvamos a la PSD.\n", "\n", - "#### Welch's PSD\n", - "There's a way to smooth out our FFT without losing too much information. The most common way of doing this is by using **Welch's method**.\n", - "Basically, we calculate the FFT of a signal across a few sliding windows. Then we calculate the mean PSD from all the sliding windows. Notice that this PSD is also plotted on a log scale." + "#### PSD de Welch\n", + "Existe una forma de suavizar nuestra FFT sin perder demasiada informacion. La forma mas comun de hacerlo es usando **el metodo de Welch**.\n", + "Basicamente, calculamos la FFT de una senal en varias ventanas deslizantes. Luego calculamos la PSD promedio de todas esas ventanas. Observa que esta PSD tambien se grafica en escala logaritmica.\n" ] }, { @@ -492,46 +492,46 @@ } ], "source": [ - "#Calculate the Welch's PSD of the data\n", + "# calcular la PSD de Welch de los datos\n", "f,pspec = sp.signal.welch(data, fs=srate, window='hanning', nperseg=2*srate, noverlap=srate/2,\n", " nfft=None, detrend='linear', return_onesided=True, scaling='density')\n", "\n", "plt.figure(figsize=(16,10))\n", - "plt.loglog(f[0:200*2],pspec[0:200*2])#Any frequencies with >200 Hz are going to be noise in ECoG data.\n", - "plt.ylabel('Power')\n", - "plt.xlabel('Frequency (Hz)')\n", + "plt.loglog(f[0:200*2],pspec[0:200*2])# cualquier frecuencia superior a 200 Hz sera ruido en datos de ECoG\n", + "plt.ylabel('Potencia')\n", + "plt.xlabel('Frecuencia (Hz)')\n", "plt.xlim([1, 150])\n", - "plt.title(\"Welch's PSD of ECoG signal\", size=18)" + "plt.title(\"PSD de Welch de la senal de ECoG\", size=18)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now the signal is much cleaner and easier to interpret. We can start to notice some interesting features of the PSD including a much clearer 1/f slope and some interesting \"bumps\", or peaks, in the spectrum around 8, 14, and 25 Hz. We'll talk about why these peaks are significant in the next section." + "Ahora la senal esta mucho mas limpia y es mas facil de interpretar. Podemos empezar a notar algunas caracteristicas interesantes de la PSD, incluyendo una pendiente 1/f mucho mas clara y algunos \"bultos\" o picos interesantes en el espectro alrededor de 8, 14 y 25 Hz. Hablaremos de por que estos picos son importantes en la siguiente seccion.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 5. Analyzing the PSD: Important features and insights\n", + "## 5. Analizar la PSD: caracteristicas e ideas importantes\n", "\n", - "The PSD is an extremely useful tool when it comes to analyzing neural data. Different features of the PSD can be correlated with certain brain regions, tasks and behaviors, age, and even mental illnesses. Two of these features are oscillations and aperiodic slope. \n", + "La PSD es una herramienta extremadamente util cuando se trata de analizar datos neuronales. Distintas caracteristicas de la PSD pueden correlacionarse con ciertas regiones cerebrales, tareas y comportamientos, la edad e incluso enfermedades mentales. Dos de estas caracteristicas son las oscilaciones y la pendiente aperiodica.\n", "\n", - "#### Oscillations\n", + "#### Oscilaciones\n", "\n", - "Neural oscillations are prominent, consistent fluctuations in electrophysiological signals that are present throughout the brain. Although there is still much more to understand about them, they have been associated with the brain's vital functions, including interregional communication, perceptual performance, and the production of motor movements. \n", + "Las oscilaciones neuronales son fluctuaciones prominentes y consistentes en senales electrofisiologicas que estan presentes en todo el cerebro. Aunque aun queda mucho por entender sobre ellas, se las ha asociado con funciones vitales del cerebro, incluidas la comunicacion interregional, el rendimiento perceptual y la produccion de movimientos motores.\n", "\n", - "Identifying oscillations is vital to studying them and their purpose in the brain. Luckily, oscillations can be picked out by analyzing the PSD. Remember the peaks we talked about in the previous section? Although not universally accepted, the majority of the electrophysiological community has agreed that a *peak in the PSD at a certain frequency indicates the presence of an oscillation at that frequency* ([He, et al. 2010](https://doi.org/10.1016/j.neuron.2010.04.020)). \n", + "Identificar oscilaciones es fundamental para estudiarlas y comprender su funcion en el cerebro. Afortunadamente, las oscilaciones pueden detectarse analizando la PSD. ¿Recuerdas los picos de los que hablamos en la seccion anterior? Aunque no es una idea universalmente aceptada, la mayoria de la comunidad electrofisiologica ha acordado que un *pico en la PSD a una frecuencia determinada indica la presencia de una oscilacion en esa frecuencia* ([He, et al. 2010](https://doi.org/10.1016/j.neuron.2010.04.020)).\n", "\n", - "For example, the Welch's PSD from the previous section most likely has oscillations at 8, 14, and 25 Hz. Oscillations in these frequencies are associated with bands of activity, known as theta, alpha, and beta. These frequency bands have been studied since the 1950's but we're still discovering lots of new things about them. \n", + "Por ejemplo, la PSD de Welch de la seccion anterior probablemente tenga oscilaciones a 8, 14 y 25 Hz. Las oscilaciones en estas frecuencias se asocian con bandas de actividad conocidas como theta, alpha y beta. Estas bandas de frecuencia se estudian desde la decada de 1950, pero todavia seguimos descubriendo muchas cosas nuevas sobre ellas.\n", "\n", - "#### Aperiodic Slope\n", + "#### Pendiente aperiodica\n", "\n", - "The relationship between power and frequency is another important property of PSDs. In the literature this property is referred to as aperiodic slope. The PSD tends to have a slope of roughly 1/f, following a **power law distribution**. However, when you look at lots of PSDs, you start to see variations in the slope of the spectrum. These variations in slope can be correlated with factors like age or mental illness, even task performance. Although the slope of electrophysiological PSDs was recognized decades ago, what slope is and what is producing it is still being investigated. \n", + "La relacion entre potencia y frecuencia es otra propiedad importante de las PSD. En la literatura esta propiedad se conoce como pendiente aperiodica. La PSD tiende a tener una pendiente aproximada de 1/f, siguiendo una **distribucion de ley de potencia**. Sin embargo, cuando observas muchas PSD, comienzas a ver variaciones en la pendiente del espectro. Estas variaciones pueden correlacionarse con factores como la edad, enfermedades mentales o incluso el rendimiento en tareas. Aunque la pendiente de las PSD electrofisiologicas se reconocio hace decadas, aun se investiga que es exactamente y que la produce.\n", "\n", - "If you'd like to know more about what the Voytek lab thinks slope could be, check out [Gao, et al. 2017](https://doi.org/10.1016/j.neuroimage.2017.06.078)." + "Si quieres saber mas sobre lo que piensa el Voytek Lab acerca de lo que podria ser la pendiente, revisa [Gao, et al. 2017](https://doi.org/10.1016/j.neuroimage.2017.06.078).\n" ] } ], diff --git a/04-EventRelatedPotentials.ipynb b/04-EventRelatedPotentials.ipynb index c0dd252..393df32 100644 --- a/04-EventRelatedPotentials.ipynb +++ b/04-EventRelatedPotentials.ipynb @@ -4,10 +4,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Cognitive and Neural Dynamics Lab Tutorials\n", - "## Event Related Potentials (ERP)\n", + "# Tutoriales del Cognitive and Neural Dynamics Lab\n", + "## Potenciales relacionados con eventos (ERP)\n", "\n", "##### Michael Tran 2018, Torben Noto 2015\n", + "\n", "\n" ] }, @@ -15,22 +16,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In this notebook we're going to talk about how to calculate the **event related potential (ERP)** on some ECoG data.\n", + "En este notebook vamos a hablar sobre como calcular el **potencial relacionado con eventos (ERP)** en algunos datos de ECoG.\n", "\n", - "The basic idea of an ERP is to look at how the electrical activity of a participant's brain changes when you present a stimulus.\n", + "La idea basica de un ERP es observar como cambia la actividad electrica del cerebro de una persona participante cuando se presenta un estimulo.\n", "\n", - "Because the signal is **very** noisy, you will take the average brain activity across a time window of many trials.\n", + "Debido a que la senal es **muy** ruidosa, tomaras el promedio de la actividad cerebral en una ventana temporal a traves de muchos ensayos.\n", "\n", - "Let's say you are running an experiment where you want to see how people's brains respond to sentances with expected words (I take coffee with cream and **sugar**) vs. sentences with unexpected words (I take coffee with cream and **dog**)\n", + "Supongamos que estas ejecutando un experimento en el que quieres ver como responde el cerebro de las personas a oraciones con palabras esperadas (Tomo cafe con crema y **azucar**) frente a oraciones con palabras inesperadas (Tomo cafe con crema y **perro**)\n", "\n", "\n", - "So we get a participant and put some electrodes on their head. We show them 10 sentences with expected words and 10 sentences with unexpected words. \n", - "This is actually a famous ERP experiment that Marta Kutas, the chair of the CogSci Department here at UCSD, did.\n", + "Entonces reclutamos a una persona participante y colocamos algunos electrodos en su cabeza. Le mostramos 10 oraciones con palabras esperadas y 10 con palabras inesperadas.\n", + "Este es, de hecho, un experimento clasico de ERP que realizo Marta Kutas, directora del Departamento de Ciencias Cognitivas aqui en UCSD.\n", "\n", - "This tutorial will tell you how to analyze the data in an experiment like this in this experiment and calculate a result.\n", + "Este tutorial te mostrara como analizar los datos de un experimento como este y calcular un resultado.\n", "\n", "\n", - "Here's how we do it:\n" + "Asi es como lo hacemos:\n" ] }, { @@ -41,7 +42,7 @@ }, "outputs": [], "source": [ - "#Loading all of the helpful modules\n", + "# cargar todos los modulos utiles\n", "import scipy as sp\n", "import numpy as np\n", "import pandas as pd\n", @@ -49,7 +50,7 @@ "\n", "import os\n", "import scipy.io\n", - "import scipy.signal" + "import scipy.signal\n" ] }, { @@ -67,25 +68,25 @@ } ], "source": [ - "#loading ECoG data\n", + "# cargar datos de ECoG\n", "filename = 'dat/emodat.mat'\n", "filename = os.path.join('./', filename)\n", "data = sp.io.loadmat(filename)\n", - "srate = data['srate'] # sampling rate\n", + "srate = data['srate'] # frecuencia de muestreo\n", "srate = srate[0][0];\n", - "data = data['data'] # time series\n", + "data = data['data'] # serie temporal\n", "data = data[0, :]\n", "\n", - "print(\"There are \" + str(len(data)) + \" samples in this data\")\n", - "print(\"The sampling rate is \" + str(srate))" + "print(\"Hay \" + str(len(data)) + \" muestras en estos datos\")\n", + "print(\"La frecuencia de muestreo es \" + str(srate))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Step 1:\n", - "Let's start simple and look at the data surround 1 event" + "#### Paso 1:\n", + "Comencemos de manera simple y observemos los datos alrededor de 1 evento\n" ] }, { @@ -112,31 +113,31 @@ } ], "source": [ - "event_inds = [1034, 2133, 4681, 9960, 12574] #Time indicies when a stimulus is presented to the subject\n", + "event_inds = [1034, 2133, 4681, 9960, 12574] # indices temporales cuando se presenta un estimulo a la persona participante\n", "this_event = event_inds[0]\n", - "timewin = [500, 1000] #500 samples before and 1000 samples after. Remember this: The units here are samples, not milliseconds. \n", - "#We sampled at 1017.253 samples per second so we'll looking at about a second and a half of data.\n", + "timewin = [500, 1000] # 500 muestras antes y 1000 muestras despues. Recuerda esto: las unidades aqui son muestras, no milisegundos. \n", + "# Muestreamos a 1017.253 muestras por segundo, asi que veremos aproximadamente un segundo y medio de datos.\n", "\n", "\n", "my_ERP = data[this_event-timewin[0]:this_event + timewin[1]]\n", "\n", "plt.plot(my_ERP,label = 'ERP')\n", - "plt.plot([500,500], [-150, 100],label = 'event onset')\n", + "plt.plot([500,500], [-150, 100],label = 'inicio del evento')\n", "plt.legend()\n", "plt.show()\n", - "print('ECoG data ~500 ms before and ~1000 ms after an event')" + "print('Datos de ECoG ~500 ms antes y ~1000 ms despues de un evento')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "This really doesn't tell us much about what someone's brain is doing. We have no idea how much of the change in voltage is caused by the **event** compared to **other random ongoing brain activity** and there is no reliability that we will see this in the other stimulus presentations.\n", + "Esto en realidad no nos dice mucho sobre lo que esta haciendo el cerebro de alguien. No tenemos idea de cuanto del cambio de voltaje esta causado por el **evento** frente a **otra actividad cerebral aleatoria y continua**, y no hay garantia de que vayamos a ver esto en las otras presentaciones del estimulo.\n", "\n", - "We can do better by looking at multiple events \n", - "(and eventually multiple channels and participants) involved in our analysis.\n", + "Podemos hacerlo mejor observando multiples eventos\n", + "(y eventualmente multiples canales y participantes) involucrados en nuestro analisis.\n", "\n", - "Now let's do a much more robust method of computing ERP:" + "Ahora apliquemos un metodo mucho mas robusto para calcular un ERP:\n" ] }, { @@ -163,29 +164,29 @@ } ], "source": [ - "#Let's look at ERP's of 5 events next to eachother\n", + "# veamos los ERP de 5 eventos uno junto al otro\n", "\n", "for event in range(len(event_inds)):\n", " this_ERP = data[event_inds[event]-timewin[0]:event_inds[event] + timewin[1]]\n", " plt.plot(this_ERP,label = 'ERP ' +str(event+1))\n", "\n", - "plt.plot([500,500], [-200, 200],label = 'event onset') \n", + "plt.plot([500,500], [-200, 200],label = 'inicio del evento') \n", "plt.legend()\n", "plt.show()\n", - "print(my_ERP.shape)" + "print(my_ERP.shape)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "What a mess.\n", + "Que desorden.\n", "\n", - "I don't know how you could draw any meaningful conclusions from data if we visualize it this way.\n", + "No se como podrias sacar conclusiones significativas de los datos si los visualizamos de esta manera.\n", "\n", - "Here's how we're going to clean up this data matrix to make a basic ERP:\n", - "1. We'll **normalize** all of the events to the same baseline and\n", - "2. We'll calculate the voltage for the **average** trial\n" + "Asi es como vamos a limpiar esta matriz de datos para obtener un ERP basico:\n", + "1. **Normalizaremos** todos los eventos al mismo nivel de linea base y\n", + "2. Calcularemos el voltaje del ensayo **promedio**\n" ] }, { @@ -212,23 +213,25 @@ } ], "source": [ - "chan_baselines = np.zeros(len(event_inds)); #We're going to get a baseline ERP data before we analyze any of the data.\n", - "ERP_matrix = np.zeros((len(event_inds),timewin[0]+timewin[1])); #We're making a matrix that will hold all the trials. We will get the mean from this.\n", + "chan_baselines = np.zeros(len(event_inds)); # vamos a obtener una linea base del ERP antes de analizar cualquiera de los datos\n", + "ERP_matrix = np.zeros((len(event_inds),timewin[0]+timewin[1])); # estamos construyendo una matriz que contendra todos los ensayos. De ahi obtendremos la media.\n", "\n", "for event in range(len(event_inds)):\n", " chan_baselines[event] = np.mean(data[event_inds[event]-100:event_inds[event] + 0]) \n", - " ERP_baseline_removed = data[event_inds[event]-timewin[0]:event_inds[event] + timewin[1]] - chan_baselines[event] #subtracting baseline from each trial. \n", + " ERP_baseline_removed = data[event_inds[event]-timewin[0]:event_inds[event] + timewin[1]] - chan_baselines[event] # restar la linea base de cada ensayo\n", " ERP_matrix[event,:] = ERP_baseline_removed;\n", " \n", - "mean_ERP = np.mean(ERP_matrix,0) #taking the mean voltage across trials.\n", - "print(chan_baselines) #see why it's important to remove baseline?\n", + "mean_ERP = np.mean(ERP_matrix,0) # tomar el voltaje medio a traves de los ensayos\n", + "print(chan_baselines) # ¿ves por que es importante eliminar la linea base?\n", "\n", - "#plotting\n", + "# graficar\n", "plt.plot(mean_ERP, label = 'ERP');\n", - "plt.plot([500,500], [-60, 60],label = 'event onset');\n", + "plt.plot([500,500], [-60, 60],label = 'inicio del evento');\n", "plt.legend()\n", "plt.show()\n", "\n", + "\n", + "\n", "\n" ] }, @@ -236,22 +239,22 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This is just a a basic example of an ERP. This plot represents the average signal across 5 events for one electrode.\n", + "Este es solo un ejemplo basico de un ERP. Esta grafica representa la senal promedio a traves de 5 eventos para un electrodo.\n", "\n", - "A typical ERP has features that are indicitive of cognitive processes (such as the P1, N2 etc.). You don't see any of those here because this ERP is calculated on sham events. It also looks 'noisier' because it is done on ECoG data where the frequency resolution is much higher.\n", + "Un ERP tipico tiene caracteristicas que son indicativas de procesos cognitivos (como P1, N2, etc.). Aqui no ves ninguna de esas porque este ERP esta calculado sobre eventos simulados. Tambien se ve mas \"ruidoso\" porque esta hecho con datos de ECoG, donde la resolucion en frecuencia es mucho mayor.\n", "\n", - "Make sure that you understand every step of the simple introductory code above." + "Asegurate de entender cada paso del codigo introductorio sencillo de arriba.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "That's it! In Summary here's what we learned:\n", - "1. You can look at the time window surrounding a single event or multiple events to see what is going on. By the way, an event in an ERP doesn't have to be a stimulus presentation. An ERP can be calculated using any timepoints that might be interesting\n", - "2. If you want an accurate ERP, you have to subtract out the baseline noise\n", - "3. You can also look at ERP's as a percent increase from baseline if you want. \n", - "4. Think hard about what this signal means physiologically and what taking the mean of lots of trials tells you as well. What does it mean that the average amplitudes are higher or lower after an event?" + "¡Eso es todo! En resumen, esto es lo que aprendimos:\n", + "1. Puedes observar la ventana temporal que rodea un solo evento o multiples eventos para ver que esta ocurriendo. Por cierto, un evento en un ERP no tiene que ser necesariamente la presentacion de un estimulo. Un ERP puede calcularse usando cualquier punto temporal que resulte interesante\n", + "2. Si quieres un ERP preciso, tienes que sustraer el ruido de linea base\n", + "3. Tambien puedes observar los ERP como un incremento porcentual respecto a la linea base, si quieres.\n", + "4. Piensa con cuidado que significa fisiologicamente esta senal y que nos dice el hecho de promediar muchos ensayos. ¿Que significa que las amplitudes promedio sean mayores o menores despues de un evento?\n" ] }, { diff --git a/05-FrequencyInteractions.ipynb b/05-FrequencyInteractions.ipynb index 39fe4a4..3229b39 100644 --- a/05-FrequencyInteractions.ipynb +++ b/05-FrequencyInteractions.ipynb @@ -4,34 +4,35 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Frequency Interactions and Phase-Amplitude Coupling (PAC)\n", + "# Interacciones de frecuencia y acoplamiento fase-amplitud (PAC)\n", "\n", - "##### Sydney Smith 2018, Torben Noto 2015\n" + "##### Sydney Smith 2018, Torben Noto 2015\n", + "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Neural Oscillations can be embedded within each other.\n", - "There are many ongoing oscillations in the brain and **features of oscillations in different frequency bands can interact with each other**. Phase-amplitude coupling (PAC) measures how much the amplitude of a fast oscilation is related to the phase of a slower oscillation. This has been proposed as a mechanism that different brain regions may use to communicate.\n", + "#### Las oscilaciones neuronales pueden estar anidadas unas dentro de otras.\n", + "Hay muchas oscilaciones en curso en el cerebro y **las caracteristicas de las oscilaciones en distintas bandas de frecuencia pueden interactuar entre si**. El acoplamiento fase-amplitud (PAC) mide cuanto se relaciona la amplitud de una oscilacion rapida con la fase de una oscilacion mas lenta. Se ha propuesto que este podria ser un mecanismo que distintas regiones cerebrales usan para comunicarse.\n", "\n", - "In this notebook, we will:\n", - "1. Introduce the concept of PAC using complex sinusoid\n", - "2. Vizualize the relationship between phase and amplitude in the time domain\n", - "3. Discuss what PAC looks like in neural data\n", - "4. Explore PAC between theta (4-8 Hz) and HFA (80-150 Hz) in real ECoG data\n", + "En este notebook vamos a:\n", + "1. Introducir el concepto de PAC usando una senoide compleja\n", + "2. Visualizar la relacion entre fase y amplitud en el dominio temporal\n", + "3. Analizar como se ve el PAC en datos neuronales\n", + "4. Explorar el PAC entre theta (4-8 Hz) y HFA (80-150 Hz) en datos reales de ECoG\n", "\n", - "I recommend that you read the [filtering](Filtering Link) and/or [PSD tutorials](PSD Link) before reading this if you are not familiar at all with filters and frequency analyses." + "Te recomiendo leer los tutoriales de [filtrado](Filtering Link) y/o [PSD](PSD Link) antes de este si no estas familiarizado con los filtros y el analisis en frecuencia.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Default Imports\n", + "### Importaciones predeterminadas\n", "\n", - "Before we get started, let's import the python libraries with the functions we need to perform these analyses. " + "Antes de comenzar, importemos las bibliotecas de Python con las funciones que necesitamos para realizar estos analisis.\n" ] }, { @@ -53,15 +54,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Phase-amplitude coupling (simulated)\n", + "## 1. Acoplamiento fase-amplitud (simulado)\n", "\n", - "If you're not familiar with signal processing, the concept of cross-frequency coupling, or phase-amplitude coupling (PAC) as it's known in neural data analysis, can be difficult to conceptualize. Before we look at PAC in real neural data, we'll simulate a signal in which PAC is occuring and then break it down into it's frequency components to investigate the phase-amplitude relationship.\n", + "Si no estas familiarizado con el procesamiento de senales, el concepto de acoplamiento entre frecuencias, o acoplamiento fase-amplitud (PAC) como se conoce en el analisis de datos neuronales, puede ser dificil de conceptualizar. Antes de observar PAC en datos neuronales reales, simularemos una senal en la que el PAC esta ocurriendo y luego la descompondremos en sus componentes de frecuencia para investigar la relacion fase-amplitud.\n", "\n", - "##### PAC occurs when the frequency of a low frequency oscillation modulates the amplitude of a high frequency oscillation.\n", + "##### El PAC ocurre cuando la frecuencia de una oscilacion lenta modula la amplitud de una oscilacion de alta frecuencia.\n", "\n", - "In the following cells, I'll generate a sinusoidal signal that has two frequency components, one slow (4 Hz) and one fast (100 Hz), where the amplitude of the fast component is changed by the phase of the slow component.\n", + "En las siguientes celdas generare una senal sinusoidal con dos componentes de frecuencia, uno lento (4 Hz) y otro rapido (100 Hz), en la que la amplitud del componente rapido cambia segun la fase del componente lento.\n", "\n", - "First, we'll make some variables for the two different frequencies, sampling rate, signal duration, and an array for the times associated with the amplitude values of the signal." + "Primero, crearemos algunas variables para las dos frecuencias, la frecuencia de muestreo, la duracion de la senal y un arreglo con los tiempos asociados a los valores de amplitud de la senal.\n" ] }, { @@ -70,18 +71,18 @@ "metadata": {}, "outputs": [], "source": [ - "freq1 = 4 #Slow, modulating signal, 4 Hz\n", - "freq2 = 100 #Fast, modulated signal, 100 Hz\n", - "srate = 1024 #sampling rate\n", - "dur = 10 #10 seconds of signal\n", - "t = np.arange(0, dur, 1/srate) #times array" + "freq1 = 4 # senal lenta moduladora, 4 Hz\n", + "freq2 = 100 # senal rapida modulada, 100 Hz\n", + "srate = 1024 # frecuencia de muestreo\n", + "dur = 10 # 10 segundos de senal\n", + "t = np.arange(0, dur, 1/srate) # arreglo de tiempos\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now that we have our variables defined, let's generate and plot the amplitude-modulated signal." + "Ahora que ya definimos nuestras variables, generemos y grafiquemos la senal modulada en amplitud.\n" ] }, { @@ -111,40 +112,40 @@ } ], "source": [ - "#Generate amplitude-modulated signal by combining 2 sinusoids\n", + "# generar una senal modulada en amplitud combinando 2 senoides\n", "sim_signal = np.sin(2*np.pi*freq1*t)*np.sin(2*np.pi*freq2*t) + 6*np.sin(2*np.pi*freq1*t) + np.sin(2*np.pi*freq2*t)\n", "\n", - "#Plot 1 second of signal\n", + "# graficar 1 segundo de senal\n", "plt.figure(figsize=(16,6))\n", - "plt.title('Simulated PAC Signal (4Hz & 100Hz)', size=18)\n", - "plt.xlabel('Time (seconds)', size=14)\n", - "plt.ylabel('Amplitude', size=14)\n", - "plt.plot(t[0:1024],sim_signal[0:1024])" + "plt.title('Senal PAC simulada (4 Hz y 100 Hz)', size=18)\n", + "plt.xlabel('Tiempo (segundos)', size=14)\n", + "plt.ylabel('Amplitud', size=14)\n", + "plt.plot(t[0:1024],sim_signal[0:1024])\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "At first glance, there seem to be two things going on in this signal: \n", + "A primera vista, parece que en esta senal ocurren dos cosas:\n", "\n", - "1. A larger wave that completes four cycles over the course of a second\n", - "2. A smalller, higher frequency wave that changes amplitude through time\n", + "1. Una onda mas grande que completa cuatro ciclos en el transcurso de un segundo\n", + "2. Una onda mas pequena, de mayor frecuencia, cuya amplitud cambia con el tiempo\n", "\n", - "We can identify **(1)** as the 4 Hz component. **(2)** has a much higher frequency (100 Hz) and its amplitude seems to fluctuate over time. Specifically, its amplitude is greatest at the peaks of the 4 Hz wave and almost non-existent at the troughs of the 4 Hz wave. From this information we can hypothesize that the phase of the 4 Hz wave and the amplitude 100 Hz wave are related.\n", + "Podemos identificar **(1)** como el componente de 4 Hz. **(2)** tiene una frecuencia mucho mayor (100 Hz) y su amplitud parece fluctuar con el tiempo. En concreto, su amplitud es mayor en los picos de la onda de 4 Hz y casi inexistente en los valles de esa misma onda. A partir de esta informacion podemos plantear la hipotesis de que la fase de la onda de 4 Hz y la amplitud de la onda de 100 Hz estan relacionadas.\n", "\n", - "Now that we have our hypothesis, we'll take a closer look at the relationship between thes two frequency components in the signal." + "Ahora que tenemos nuestra hipotesis, observaremos con mas detalle la relacion entre estos dos componentes de frecuencia en la senal.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Vizualizing phase and amplitude in the time domain using filters\n", + "## 2. Visualizar fase y amplitud en el dominio temporal usando filtros\n", "\n", - "Using filters, let's track the phase of the 4 Hz signal and the amplitude of the 100 Hz signal through time. If you need a refresher on filters, check out our [tutorial](LINK).\n", + "Usando filtros, sigamos a traves del tiempo la fase de la senal de 4 Hz y la amplitud de la senal de 100 Hz. Si necesitas repasar filtros, revisa nuestro [tutorial](LINK).\n", "\n", - "First, let's define our filtering functions." + "Primero, definamos nuestras funciones de filtrado.\n" ] }, { @@ -153,14 +154,14 @@ "metadata": {}, "outputs": [], "source": [ - "#filtering functions\n", + "# funciones de filtrado\n", "def butter_bandpass(lowcut, highcut, srate, order=4):\n", " \"\"\"\"\"\n", - " lowcut: lower bound of the frequency that we want to isolate\n", - " highcut: upper bound of the frequency that we want to isolate\n", - " srate: sampling rate of our data\n", + " lowcut: limite inferior de la frecuencia que queremos aislar\n", + " highcut: limite superior de la frecuencia que queremos aislar\n", + " srate: frecuencia de muestreo de nuestros datos\n", " \"\"\"\"\"\n", - " nyq = 0.5 * srate #nyquist frequency \n", + " nyq = 0.5 * srate # frecuencia de Nyquist\n", " low = float(lowcut) / nyq\n", " high = float(highcut) / nyq\n", " b, a = butter(order, [low, high], btype='band')\n", @@ -169,17 +170,17 @@ "def butter_bandpass_filter(mydata, lowcut, highcut, srate, order=4):\n", " b, a = butter_bandpass(lowcut, highcut, srate, order=order)\n", " y = filtfilt(b, a, mydata)\n", - " return y" + " return y\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Filter the generated signal\n", - "Now that we have our filters prepped and ready, let's apply them to the signal we generated. \n", + "#### Filtrar la senal generada\n", + "Ahora que nuestros filtros estan preparados y listos, apliquemolos a la senal que generamos.\n", "\n", - "Let's start by filtering out the two frequency components in the signal. We'll do this by filtering the simulated signal through two butterworth bandpass filters, one filtering in a range of 2-6 Hz to isolate our low frequency (4 Hz) component and the other filtering in a range of 80-110 Hz to isolate our high frequency component (100 Hz). " + "Comencemos filtrando los dos componentes de frecuencia presentes en la senal. Lo haremos filtrando la senal simulada con dos filtros pasa banda de Butterworth: uno en el rango de 2-6 Hz para aislar nuestro componente de baja frecuencia (4 Hz) y otro en el rango de 80-110 Hz para aislar nuestro componente de alta frecuencia (100 Hz).\n" ] }, { @@ -188,24 +189,24 @@ "metadata": {}, "outputs": [], "source": [ - "#parameters\n", - "phase_band = [2,6] #4 Hz modulating frequency filter band\n", - "amplitude_band = [80,110] #100 Hz modulated frequency filter band\n", + "# parametros\n", + "phase_band = [2,6] # banda del filtro para la frecuencia moduladora de 4 Hz\n", + "amplitude_band = [80,110] # banda del filtro para la frecuencia modulada de 100 Hz\n", "\n", - "#isolate the slow component\n", + "# aislar el componente lento\n", "phase_data_filt = butter_bandpass_filter(sim_signal, phase_band[0], phase_band[1], np.round(srate))\n", "\n", - "#isolate the fast component\n", - "amp_data_filt = butter_bandpass_filter(sim_signal, amplitude_band[0], amplitude_band[1], np.round(srate))" + "# aislar el componente rapido\n", + "amp_data_filt = butter_bandpass_filter(sim_signal, amplitude_band[0], amplitude_band[1], np.round(srate))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Plot the filtered signal\n", + "#### Graficar la senal filtrada\n", "\n", - "Here, we'll plot the outputs of the filters we just applied to the simulated signal. It will show us two signals overlayed so we can look at their relationship through time." + "Aqui graficaremos las salidas de los filtros que acabamos de aplicar a la senal simulada. Esto nos mostrara dos senales superpuestas para que podamos observar su relacion a traves del tiempo.\n" ] }, { @@ -250,13 +251,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "When we overlay the filtered fast and slow components, we can see interesting \"pulses\" of high amplitude in the fast component that coincide with the peaks of the slow component.\n", + "Cuando superponemos los componentes rapido y lento filtrados, podemos ver interesantes \"pulsos\" de alta amplitud en el componente rapido que coinciden con los picos del componente lento.\n", "\n", - "Because it looks like the amplitude of the fast component wave is only occuring during a certain phase of the slow component wave, the next step is to plot the phase of the slow component and the amplitude envelope of the fast component through time. We'll do this using a Hilbert function.\n", + "Debido a que parece que la amplitud de la onda del componente rapido solo ocurre durante cierta fase de la onda del componente lento, el siguiente paso es graficar la fase del componente lento y la envolvente de amplitud del componente rapido a traves del tiempo. Haremos esto usando la funcion de Hilbert.\n", "\n", - "#### Calculating phase and amplitude envelope \n", + "#### Calcular fase y envolvente de amplitud\n", "\n", - "The first function calculates the phase of the slow (4 Hz) component and the second calculates the amplitude envelope of the fast component (100 Hz)." + "La primera funcion calcula la fase del componente lento (4 Hz) y la segunda calcula la envolvente de amplitud del componente rapido (100 Hz).\n" ] }, { @@ -265,21 +266,21 @@ "metadata": {}, "outputs": [], "source": [ - "#calculating phase angle of slow component\n", + "# calcular el angulo de fase del componente lento\n", "phase_data = hilbert(phase_data_filt)\n", "phase_data = np.angle(phase_data)\n", "\n", - "#calculating amplitude envelope of fast component\n", + "# calcular la envolvente de amplitud del componente rapido\n", "amp_data = hilbert(amp_data_filt)\n", - "amp_data = abs(amp_data)" + "amp_data = abs(amp_data)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Plotting the outputs of the Hilbert function\n", - "When you look at the plot below, notice that the phase of the slow component is plotted between positive and negative π (3.14). Amplitude is plotted between 0 and 1. " + "#### Graficar las salidas de la funcion de Hilbert\n", + "Cuando observes la grafica de abajo, nota que la fase del componente lento se representa entre π positivo y π negativo (3.14). La amplitud se representa entre 0 y 1.\n" ] }, { @@ -321,41 +322,40 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "As we can see from the results of our filters, the phase of the slow (4 Hz) component cycles between -π to π four times in a second. We see a similar result for the amplitude envelope of the fast (100 Hz) component; it oscillates between 0 and 1 four times per second as well. The amplitude of the fast component is highest when the phase of the slow component equals zero (the peak of the slow wave) and lowest when the phase equals ±π (the trough of the slow wave). This vizualization makes it very clear that the amplitude of the 100 Hz component is directly related to the phase of the 4 Hz component. \n", + "Como podemos ver en los resultados de nuestros filtros, la fase del componente lento (4 Hz) recorre el intervalo de -π a π cuatro veces por segundo. Vemos un resultado similar para la envolvente de amplitud del componente rapido (100 Hz): tambien oscila entre 0 y 1 cuatro veces por segundo. La amplitud del componente rapido es maxima cuando la fase del componente lento es igual a cero (el pico de la onda lenta) y minima cuando la fase es ±π (el valle de la onda lenta). Esta visualizacion deja muy claro que la amplitud del componente de 100 Hz esta directamente relacionada con la fase del componente de 4 Hz.\n", "\n", - "In other words, **the amplitude of the 100 Hz signal is coupled to the phase of the 4 Hz signal**. " + "En otras palabras, **la amplitud de la senal de 100 Hz esta acoplada a la fase de la senal de 4 Hz**.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### To summarize\n", + "#### En resumen\n", "\n", - "In the last two sections we generated a signal in which the amplitude of a fast component was related to the phase of a slow component. We explored this relationship with two analyses:\n", + "En las dos secciones anteriores generamos una senal en la que la amplitud de un componente rapido estaba relacionada con la fase de un componente lento. Exploramos esta relacion con dos analisis:\n", "\n", - "1. Butterworth bandpass filtering to isolate the slow and fast frequency components\n", - "2. Applying a Hilbert function to plot the phase of the slow wave with the amplitude envelope of the fast wave\n", + "1. Filtrado pasa banda de Butterworth para aislar los componentes de frecuencia lento y rapido\n", + "2. Aplicacion de una funcion de Hilbert para graficar la fase de la onda lenta junto con la envolvente de amplitud de la onda rapida\n", "\n", - "Using these two visual methods, we determined that in the simulated signal, the **amplitude** of the fast wave was *coupled* to the **phase** of the slow wave...\n", + "Usando estos dos metodos visuales, determinamos que en la senal simulada la **amplitud** de la onda rapida estaba *acoplada* a la **fase** de la onda lenta...\n", "\n", - "***Phase-Amplitude Coupling!***\n", - "\n" + "***¡Acoplamiento fase-amplitud!***\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. PAC in neural data\n", + "## 3. PAC en datos neuronales\n", "\n", - "In real electrophysiological data recorded from living brains, PAC is not as obvious as it was in our simulated signal. Although we can see some semblance of frequency interactions when we look at neural time series, most of the time the interaction is obscured by the presence of noise, low-frequency drift, artifacts, and other common characteristics of this kind of data. Not to mention that neural signals aren't always sinusoidal, but that's a story for another day (or another [tutorial](LINKTO#8)). \n", + "En datos electrofisiologicos reales registrados en cerebros vivos, el PAC no es tan obvio como en nuestra senal simulada. Aunque podemos ver cierto parecido con interacciones de frecuencia cuando observamos series temporales neuronales, la mayor parte del tiempo esa interaccion queda oculta por la presencia de ruido, deriva de baja frecuencia, artefactos y otras caracteristicas comunes de este tipo de datos. Sin mencionar que las senales neuronales no siempre son sinusoidales, pero esa es una historia para otro dia (o para otro [tutorial](LINKTO#8)).\n", "\n", - "For the sake of comparison, let's plot some real neural data and compare it to our simulated signal from earlier.\n", + "Para comparar, graficaremos algunos datos neuronales reales y los compararemos con la senal simulada de antes.\n", "\n", - "#### Load ECoG data\n", + "#### Cargar datos de ECoG\n", "\n", - "First, let's load some electrocorticography (ECoG) data and resample it at the same rate of our simulated signal (not necessary, just easier to work with)." + "Primero, carguemos algunos datos de electrocorticografia (ECoG) y remuestreemoslos a la misma frecuencia que nuestra senal simulada (no es necesario, pero facilita el trabajo).\n" ] }, { @@ -364,23 +364,23 @@ "metadata": {}, "outputs": [], "source": [ - "#loading ECoG data from local save\n", + "# cargar datos de ECoG guardados localmente\n", "path = 'dat/emodat.npy'\n", "data = np.load(path)\n", "fs = 1017.2533333333334\n", "\n", - "#resample at 1024 Hz\n", - "newsrate = 1024 # new sampling rate\n", - "ecog_signal = sp.signal.resample(data, int(np.floor(len(data)*(newsrate/fs))))" + "# remuestrear a 1024 Hz\n", + "newsrate = 1024 # nueva frecuencia de muestreo\n", + "ecog_signal = sp.signal.resample(data, int(np.floor(len(data)*(newsrate/fs))))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Plot ECoG data and simulated data\n", + "#### Graficar datos de ECoG y datos simulados\n", "\n", - "Plotting the ECoG data and the simulated data from the previous sections will let us compare them purely on a visual basis, highlighting the differences between what PAC looks like in simulations vs. real data." + "Graficar los datos de ECoG y los datos simulados de las secciones anteriores nos permitira compararlos de manera puramente visual, destacando las diferencias entre como se ve el PAC en simulaciones frente a datos reales.\n" ] }, { @@ -414,40 +414,40 @@ "source": [ "plt.figure(figsize=(16,8))\n", "\n", - "#Plot ECoG Signal\n", + "# graficar la senal de ECoG\n", "plt.subplot(2,1,1)\n", "plt.plot(t[0:1024], ecog_signal[0:1024])\n", - "plt.title('Raw ECoG Signal', size=16)\n", - "plt.ylabel('Voltage', size=12)\n", + "plt.title('Senal de ECoG sin procesar', size=16)\n", + "plt.ylabel('Voltaje', size=12)\n", "\n", - "#Plot Simulated Signal\n", + "# graficar la senal simulada\n", "plt.subplot(2,1,2)\n", "plt.plot(t[0:1024], sim_signal[0:1024])\n", - "plt.title('Simulated PAC Signal', size=16)\n", - "plt.ylabel('Amplitude', size=12)\n", - "plt.xlabel('Time (Seconds)', size=12)" + "plt.title('Senal PAC simulada', size=16)\n", + "plt.ylabel('Amplitud', size=12)\n", + "plt.xlabel('Tiempo (segundos)', size=12)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Even at first glance, these signals are obviousy VERY different. The ECoG signal looks irregular, jagged, and much more natural than the smooth, sinusoidal simulated signal. \n", + "Incluso a primera vista, estas senales son obviamente MUY diferentes. La senal de ECoG se ve irregular, dentada y mucho mas natural que la senal simulada suave y sinusoidal.\n", "\n", - "However, upon closer inspection, we can see some interesting similarities. For example, there does seem to be a slower oscillation within the ECoG signal. At some phases of this slow wave, there are some periods of high-frequency activity. \n", + "Sin embargo, al observarla mas de cerca, podemos ver algunas similitudes interesantes. Por ejemplo, parece haber una oscilacion mas lenta dentro de la senal de ECoG. En algunas fases de esa onda lenta, hay periodos de actividad de alta frecuencia.\n", "\n", - "So even though the signals look very different at first, it's possible that PAC could also exist in the ECoG signal. To investigate this further, let's run some of the same analyses from section 2 on the ECoG signal." + "Asi que, aunque las senales se ven muy distintas al principio, es posible que tambien exista PAC en la senal de ECoG. Para investigarlo con mas detalle, ejecutemos algunos de los mismos analisis de la seccion 2 sobre la senal de ECoG.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 4. Visualizing PAC in ECoG data\n", + "## 4. Visualizar PAC en datos de ECoG\n", "\n", - "In this section, we will filter and analyze the ECoG data we loaded in the previous section to see if PAC is present in the signal. In humans, PAC is common between oscillations in the theta (4-8 Hz) and high gamma (80-150 Hz) bands, so those frequency ranges will be the ones we use in our filter functions.\n", + "En esta seccion filtraremos y analizaremos los datos de ECoG que cargamos en la seccion anterior para ver si el PAC esta presente en la senal. En humanos, el PAC es comun entre las oscilaciones en las bandas theta (4-8 Hz) y gamma alta (80-150 Hz), asi que esos rangos de frecuencia seran los que usemos en nuestras funciones de filtrado.\n", "\n", - "To filter the data, we can use the functions we defined in Section 2. " + "Para filtrar los datos, podemos usar las funciones que definimos en la Seccion 2.\n" ] }, { @@ -456,24 +456,24 @@ "metadata": {}, "outputs": [], "source": [ - "#parameters\n", - "phase_band = [4,8] #4-8 Hz theta band (modulating frequency)\n", - "amplitude_band = [80,150] #80-150 Hz high gamma band (modulated frequency)\n", + "# parametros\n", + "phase_band = [4,8] # banda theta de 4-8 Hz (frecuencia moduladora)\n", + "amplitude_band = [80,150] # banda gamma alta de 80-150 Hz (frecuencia modulada)\n", "\n", - "#isolate the slow component\n", + "# aislar el componente lento\n", "phase_data_filt = butter_bandpass_filter(ecog_signal, phase_band[0], phase_band[1], np.round(srate))\n", "\n", - "#isolate the fast component\n", - "amp_data_filt = butter_bandpass_filter(ecog_signal, amplitude_band[0], amplitude_band[1], np.round(srate))" + "# aislar el componente rapido\n", + "amp_data_filt = butter_bandpass_filter(ecog_signal, amplitude_band[0], amplitude_band[1], np.round(srate))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Plot the filtered ECoG data\n", + "#### Graficar los datos de ECoG filtrados\n", "\n", - "Plotting the filtered data can let us look at the both the slow frequencies and the fast frequencies separately." + "Graficar los datos filtrados puede permitirnos observar por separado tanto las frecuencias lentas como las frecuencias rapidas.\n" ] }, { @@ -518,16 +518,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "When we look at the plot above, we can see that there is a theta oscillation present in the signal that has a relatively high amplitude. We can also observe there is higher frequency activity in the high-gamma band. Although the amplitude of the gamma component does seem to change over time, if there is a pattern, it's not as clear as the one in our simulated signal. So let's run a Hilbert function and see if we can detect any correlations in gamma envelope and theta phase." + "Cuando observamos la grafica de arriba, podemos ver que hay una oscilacion theta presente en la senal con una amplitud relativamente alta. Tambien podemos observar actividad de mayor frecuencia en la banda gamma alta. Aunque la amplitud del componente gamma parece cambiar con el tiempo, si hay un patron, no es tan claro como en nuestra senal simulada. Asi que apliquemos una funcion de Hilbert y veamos si podemos detectar correlaciones entre la envolvente gamma y la fase theta.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Calculate phase angle and amplitude envelope\n", + "#### Calcular angulo de fase y envolvente de amplitud\n", "\n", - "Here we're using the same functions from section 2 on our ECoG data to calculate gamma amplitude envelope and theta phase angle." + "Aqui estamos usando las mismas funciones de la seccion 2 sobre nuestros datos de ECoG para calcular la envolvente de amplitud gamma y el angulo de fase theta.\n" ] }, { @@ -536,22 +536,22 @@ "metadata": {}, "outputs": [], "source": [ - "#calculating phase angle of slow component\n", + "# calcular el angulo de fase del componente lento\n", "phase_data = hilbert(phase_data_filt)\n", "phase_data = np.angle(phase_data)\n", "\n", - "#calculating amplitude envelope of fast component\n", + "# calcular la envolvente de amplitud del componente rapido\n", "amp_data = hilbert(amp_data_filt)\n", - "amp_data = abs(amp_data)" + "amp_data = abs(amp_data)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Plot phase and amplitude of ECoG data\n", + "#### Graficar fase y amplitud de los datos de ECoG\n", "\n", - "Now that we've run our calculations, let's plot the result and see if we can visually detect any correlations." + "Ahora que hicimos los calculos, grafiquemos el resultado y veamos si podemos detectar visualmente alguna correlacion.\n" ] }, { @@ -593,19 +593,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "When we look at the figure above, what we need to focus on is the phase of theta and the height of the gamma envelope. Although it's not very clear at first glance, when you look closely, it's possible a positive correlation between these two measures. Specifically, it's seems like **the amplitude envelope of gamma is greatest when the phase angle of theta is close to zero**, or maybe slightly less than zero.\n", + "Cuando observamos la figura de arriba, en lo que debemos concentrarnos es en la fase de theta y la altura de la envolvente gamma. Aunque no es muy evidente a primera vista, si miras con cuidado es posible ver una correlacion positiva entre estas dos medidas. En particular, parece que **la envolvente de amplitud de gamma es maxima cuando el angulo de fase de theta esta cerca de cero**, o tal vez ligeramente por debajo de cero.\n", "\n", - "However, it would be silly to conclude that there is a relationship present based on this basic visual analysis. In order to determine if the relationship is present and significant, we should do some math and get a correlation value (r). " + "Sin embargo, seria absurdo concluir que existe una relacion basandonos solo en este analisis visual basico. Para determinar si la relacion esta presente y es significativa, deberiamos hacer algunas cuentas y obtener un valor de correlacion (r).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Determine the strength of the correlation between theta phase and high-gamma amplitude envelope\n", - "Picking the right correlation function to use here is key because the data is periodic. A simple Pearson correlation cannot be used because the phase of theta is periodic (between -π and π) and a Pearson correlation, intended for linear data, would yeild inaccurate results.\n", + "#### Determinar la fuerza de la correlacion entre la fase theta y la envolvente de amplitud gamma alta\n", + "Elegir la funcion de correlacion correcta aqui es clave porque los datos son periodicos. No se puede usar una correlacion de Pearson simple porque la fase de theta es periodica (entre -π y π) y una correlacion de Pearson, pensada para datos lineales, produciria resultados inexactos.\n", "\n", - "To address this problem, we'll make a function that correctly correlates periodic data with linear data. Then, we'll run it on our data and get some correlation values." + "Para resolver este problema, construiremos una funcion que correlacione correctamente datos periodicos con datos lineales. Luego la ejecutaremos sobre nuestros datos y obtendremos algunos valores de correlacion.\n" ] }, { @@ -630,32 +630,32 @@ " rxc = rxc[0]\n", " rcs = sp.stats.pearsonr(np.sin(ang),np.cos(ang))\n", " rcs = rcs[0]\n", - " rho = np.sqrt((rxc**2 + rxs**2 - 2*rxc*rxs*rcs)/(1-rcs**2)) #r\n", - " r_2 = rho**2 #r squared\n", + " rho = np.sqrt((rxc**2 + rxs**2 - 2*rxc*rxs*rcs)/(1-rcs**2)) # r\n", + " r_2 = rho**2 # r al cuadrado\n", " pval = 1- sp.stats.chi2.cdf(n*(rho**2),1)\n", " standard_error = np.sqrt((1-r_2)/(n-2))\n", "\n", " return rho, pval, r_2,standard_error\n", "\n", - "print('Correlation Values:', circCorr(phase_data, amp_data))" + "print('Valores de correlacion:', circCorr(phase_data, amp_data))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The values above represent the r, p, r^2 and standard of error respectively. These values show that there is a significant correlation between theta phase and high gamma amplitude that explains about 5% of the variance.\n", + "Los valores de arriba representan respectivamente r, p, r^2 y el error estandar. Estos valores muestran que existe una correlacion significativa entre la fase theta y la amplitud gamma alta que explica aproximadamente el 5% de la varianza.\n", "\n", - "Now that we know that a significant correlation exists, we just need to determine what phase of theta the amplitude of gamma is coupled to. We can visualize that with a polar bar graph." + "Ahora que sabemos que existe una correlacion significativa, solo nos falta determinar a que fase de theta esta acoplada la amplitud de gamma. Podemos visualizarlo con una grafica polar de barras.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "#### Visualize coupled phase\n", + "#### Visualizar la fase acoplada\n", "\n", - "The polar historgram we will generate below will tell us where the greatest amounts of gamma amplitude are located in the theta wave. Discovering the phase of theta that contains the greatest amount of gamma amplitude will give us even more information about the PAC present in the ECoG signal. It's a lot of code but the result will be worth it, I promise." + "El histograma polar que generaremos abajo nos dira en que parte de la onda theta se encuentran las mayores cantidades de amplitud gamma. Descubrir la fase de theta que contiene la mayor amplitud gamma nos dara aun mas informacion sobre el PAC presente en la senal de ECoG. Es bastante codigo, pero el resultado valdra la pena.\n" ] }, { @@ -691,7 +691,7 @@ "\n", "amps = []\n", "\n", - "#filling phase bins with amplitudes\n", + "# llenar los bins de fase con amplitudes\n", "for x in range(len(bins)-1):\n", " amps_above_lo_bound = np.where(phase_data >= bins[x])[0]\n", " amps_below_hi_bound = np.where(phase_data < bins[x+1])[0]\n", @@ -702,42 +702,42 @@ "\n", "bins = bins[:len(bins)-1]\n", "\n", - "#normalizing to make the effect more clear\n", + "# normalizar para hacer el efecto mas claro\n", "amps = (amps-np.mean(amps))/(np.std(amps))\n", "\n", - "#plotting figure\n", + "# graficar figura\n", "fig = plt.figure(figsize=(8,8))\n", "ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)\n", "ax.bar(bins, amps, width=bins[1]-bins[0])\n", - "plt.title('Amplitude of High Gamma at Theta Phase', size=15)\n", - "plt.ylim(bottom=0)" + "plt.title('Amplitud de gamma alta en la fase theta', size=15)\n", + "plt.ylim(bottom=0)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "In the figure above, the amplitude of high gamma steadily gets greater at around 135-180 degrees into the theta phase. This means that the amplitude of high gamma is greatest just following the peak of the theta wave. Remember that terms of a periodic signal, 180 degrees is equivalent to zero. \n", + "En la figura de arriba, la amplitud de gamma alta aumenta de forma sostenida alrededor de 135-180 grados dentro de la fase theta. Esto significa que la amplitud de gamma alta es maxima justo despues del pico de la onda theta. Recuerda que, en una senal periodica, 180 grados es equivalente a cero.\n", "\n", - "If we look back at the last figure, the figure where we plotted theta phase and gamma amplitude, we can see that the gamma amplitude is greatest just before the phase of theta reaches zero. In other words, we can look at the two figures and see that they tell give us a similar result: gamma amplitude is greatest around the phase of theta at 135-180 degrees.\n", + "Si volvemos a la figura anterior, aquella en la que graficamos la fase theta y la amplitud gamma, podemos ver que la amplitud gamma es maxima justo antes de que la fase theta alcance cero. En otras palabras, podemos observar ambas figuras y ver que nos dan un resultado similar: la amplitud gamma es maxima alrededor de la fase theta entre 135 y 180 grados.\n", "\n", - "Therefore, we can conclude that in this ECoG signal the amplitude of high-gamma is coupled to the phase of theta. Our analysis shows that greatest gamma amplitudes occur in the first half of the descending phase, just after the theta peak. " + "Por lo tanto, podemos concluir que en esta senal de ECoG la amplitud de gamma alta esta acoplada a la fase de theta. Nuestro analisis muestra que las mayores amplitudes gamma ocurren en la primera mitad de la fase descendente, justo despues del pico theta.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## In summary\n", + "## En resumen\n", "\n", - "In this tutorial, we learned that we can examine the relationship between the phase of a slow wave \n", - "and the amplitude of a faster wave. To isolate the frequency ranges that we want, we use filters and useful mathematical functions to get the phase and amplitude of the waves that we're interested in. Then we can use statistics to quantify the relationship between the two.\n", + "En este tutorial aprendimos que podemos examinar la relacion entre la fase de una onda lenta\n", + "y la amplitud de una onda mas rapida. Para aislar los rangos de frecuencia que nos interesan, usamos filtros y funciones matematicas utiles para obtener la fase y la amplitud de las ondas que queremos estudiar. Despues podemos usar estadistica para cuantificar la relacion entre ambas.\n", "\n", - "In this example we have shown that, in our data, the amplitude of high gamma is biased to be greatest in the phase just following the peak of theta, demonstrating a phase-amplitude coupling realtionship. Our statistical analysis revealed that this is a small--but significant--correlation.\n", + "En este ejemplo mostramos que, en nuestros datos, la amplitud de gamma alta tiende a ser mayor en la fase inmediatamente posterior al pico de theta, demostrando una relacion de acoplamiento fase-amplitud. Nuestro analisis estadistico revelo que esta es una correlacion pequena, pero significativa.\n", "\n", - "This tutorial was just an introduction to frequency interactions, specifically phase-amplitude coupling. In the brain, frequency interactions are hypothesized to serve a variety of functions including interregional communication, which is required for coordinated behaviors ranging from simple movement to high-level cognition. Although the mechanism behind frequency interactions is still undetermined, [Fries 2005](https://doi.org/10.1016/j.tics.2005.08.011) presents an excellent theory of neuronal coherence and I highly recommend reading it. \n", + "Este tutorial fue solo una introduccion a las interacciones de frecuencia, especificamente al acoplamiento fase-amplitud. En el cerebro, se plantea la hipotesis de que las interacciones de frecuencia cumplen diversas funciones, incluida la comunicacion interregional, necesaria para comportamientos coordinados que van desde movimientos simples hasta cognicion de alto nivel. Aunque el mecanismo detras de estas interacciones aun no esta determinado, [Fries 2005](https://doi.org/10.1016/j.tics.2005.08.011) presenta una excelente teoria de la coherencia neuronal y recomiendo mucho leerlo.\n", "\n", - "There are several mathematical tools available that provide PAC measurements for time series data. You can find them in our lab's repository [NeuroDSP](https://github.com/voytekresearch/neurodsp). Feel free to check them out and try them on your own. Happy analyzing!\n" + "Existen varias herramientas matematicas disponibles para medir PAC en series temporales. Puedes encontrarlas en el repositorio del laboratorio [NeuroDSP](https://github.com/voytekresearch/neurodsp). Si quieres, revisalas y pruébalas por tu cuenta.\n" ] } ], diff --git a/06-ColoredNoise.ipynb b/06-ColoredNoise.ipynb index cca41df..7853acf 100644 --- a/06-ColoredNoise.ipynb +++ b/06-ColoredNoise.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Colored Noise" + "# Ruido coloreado\n" ] }, { @@ -12,8 +12,8 @@ "metadata": {}, "source": [ "
\n", - "This notebook will discuss colored noise in the time and frequency domain.\n", - "
" + "Este notebook tratara el ruido coloreado en los dominios temporal y de frecuencia.\n", + "\n" ] }, { @@ -29,17 +29,17 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "General noise is a signal that is largely formed through a [stochasitc process](https://en.wikipedia.org/wiki/Stochastic). When we talk about colored noise we usually refer to an additional underlying pattern that is evident in the signal eventhough there is some amount of randomness involved.\n", - "Some types of colored noise follow the general form of $$\\frac{1}{f^{\\beta}}$$ where β determines the 'color' and properties of the noise. These are the types of noise we will be discussing in this notebook which we will call 'power law noises'." + "El ruido general es una senal formada en gran parte por un [proceso estocastico](https://en.wikipedia.org/wiki/Stochastic). Cuando hablamos de ruido coloreado, normalmente nos referimos a un patron subyacente adicional que es evidente en la senal aunque exista cierto grado de aleatoriedad.\n", + "Algunos tipos de ruido coloreado siguen la forma general $$\\frac{1}{f^{\\beta}}$$ donde β determina el 'color' y las propiedades del ruido. Estos son los tipos de ruido que analizaremos en este notebook y a los que llamaremos 'ruidos de ley de potencia'.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### White Noise - Time Domain\n", + "### Ruido blanco - dominio temporal\n", "\n", - "White noise is an example of a power law noise where β = 0. Below is a time series of white noise. This noise is generated by sampling from a standard normal distribution and as a result we see the y values mirror the domain of a standard normal distribution - there are many samples close to 0 and fewer samples further away from 0. White noise can also be generated from other distributions such as unifom and poisson distributions which affect the range of the samples." + "El ruido blanco es un ejemplo de ruido de ley de potencia donde β = 0. A continuacion se muestra una serie temporal de ruido blanco. Este ruido se genera muestreando una distribucion normal estandar y, como resultado, vemos que los valores en y reflejan el dominio de una distribucion normal estandar: hay muchas muestras cerca de 0 y menos muestras a medida que nos alejamos de 0. El ruido blanco tambien puede generarse a partir de otras distribuciones, como la uniforme y la de Poisson, lo que afecta el rango de las muestras.\n" ] }, { @@ -59,32 +59,32 @@ } ], "source": [ - "# define number of samples in serie\n", + "# definir numero de muestras en la serie\n", "num_samples = 1000000\n", "\n", - "# Generate white noise time series \n", + "# generar serie temporal de ruido blanco\n", "mean = 0\n", "std = 1 \n", "\n", - "# sampling rate 1000Hz\n", + "# frecuencia de muestreo 1000 Hz\n", "fs_white = 1000 \n", "\n", - "# generate white (random) noise\n", + "# generar ruido blanco (aleatorio)\n", "white_data = np.random.normal(mean, std, size=num_samples) \n", "\n", - "# time scale = number of samples / sampling rate\n", + "# escala temporal = numero de muestras / frecuencia de muestreo\n", "time_scale = np.arange(len(white_noise_data))/fs_white \n", "\n", - "noise_time_plot(white_data, time_scale)" + "noise_time_plot(white_data, time_scale)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### White Noise - Frequency Domain\n", + "### Ruido blanco - dominio de la frecuencia\n", "\n", - "If we compute a fourier transfrom on our white noise time series we will arrive at the frequency domain of our signal. Notice the property that the frequency spectrum is flat - this is where the Power law relationship of 1/f^0 comes from. The total power in any two frequency bands of equal width is the same. For example, the total power from [20, 50] Hz is the same as the total power in [350, 380] Hz because the bandwidths are both the same. For those interested, here's [why.](https://en.wikipedia.org/wiki/Law_of_large_numbers)" + "Si calculamos una transformada de Fourier de nuestra serie temporal de ruido blanco, llegaremos al dominio de la frecuencia de la senal. Observa la propiedad de que el espectro de frecuencias es plano: de ahi proviene la relacion de ley de potencia 1/f^0. La potencia total en dos bandas de frecuencia de igual ancho es la misma. Por ejemplo, la potencia total entre [20, 50] Hz es la misma que entre [350, 380] Hz porque ambos anchos de banda son iguales. Para quienes tengan interes, aqui esta [la explicacion](https://en.wikipedia.org/wiki/Law_of_large_numbers).\n" ] }, { @@ -114,23 +114,23 @@ } ], "source": [ - "# calculating fourier transform of signal\n", + "# calcular la transformada de Fourier de la senal\n", "white_fourier = np.fft.fft(white_noise_data[0:10000])\n", "\n", - "# finding frequency values for the x axis\n", + "# encontrar los valores de frecuencia para el eje x\n", "fx_step_size = fs_white / len(white_noise_data[0:10000])\n", "nyq = .5 * fs_white\n", "total_steps = nyq / fx_step_size\n", "fx_bins = np.linspace(0, nyq, total_steps)\n", "\n", - "noise_frequency_plot(white_fourier, fx_bins, \"FFT of White Noise\")" + "noise_frequency_plot(white_fourier, fx_bins, \"FFT del ruido blanco\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Below is a welch plot which estimates the power at every frequency. Notice that the trend is a line parallel to the x-axis. This is a result of β = 0." + "Abajo se muestra una grafica de Welch que estima la potencia en cada frecuencia. Observa que la tendencia es una linea paralela al eje x. Esto es resultado de β = 0.\n" ] }, { @@ -159,11 +159,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Pink Noise - Time Domain\n", + "### Ruido rosa - dominio temporal\n", "\n", - "Pink noise is our next power law noise which has a β value of β = 1. The time series seems more sporadic than the white noise time series but the pink noise PSD has some interesting features. This is the first noise whose power spectrum resembles a signal found in the brain. The following is an algorithm created by Voss and McCarthy to generate pink noise. \n", + "El ruido rosa es nuestro siguiente ruido de ley de potencia y tiene un valor β = 1. La serie temporal parece mas esporadica que la del ruido blanco, pero la PSD del ruido rosa tiene algunas caracteristicas interesantes. Este es el primer ruido cuyo espectro de potencia se parece a una senal encontrada en el cerebro. Lo siguiente es un algoritmo creado por Voss y McCarthy para generar ruido rosa.\n", "\n", - "Voss, R. F., & Clarke, J. (1978). \"1/f noise\" in music: Music from 1/f noise\". Journal of the Acoustical Society of America 63: 258–263." + "Voss, R. F., & Clarke, J. (1978). \"1/f noise\" in music: Music from 1/f noise\". Journal of the Acoustical Society of America 63: 258–263.\n" ] }, { @@ -172,21 +172,21 @@ "metadata": {}, "outputs": [], "source": [ - "#Function to generate time series with properties of pink noise\n", + "# funcion para generar una serie temporal con propiedades de ruido rosa\n", "def voss(nrows, ncols=16):\n", - " \"\"\"Generates pink noise using the Voss-McCartney algorithm.\n", + " \"\"\"Genera ruido rosa usando el algoritmo de Voss-McCartney.\n", "\n", - " nrows: number of values to generate\n", - " rcols: number of random sources to add\n", + " nrows: numero de valores a generar\n", + " rcols: numero de fuentes aleatorias a sumar\n", "\n", - " returns: NumPy array\n", + " devuelve: arreglo de NumPy\n", " \"\"\"\n", " array = np.empty((nrows, ncols))\n", " array.fill(np.nan)\n", " array[0, :] = np.random.random(ncols)\n", " array[:, 0] = np.random.random(nrows)\n", "\n", - " # the total number of changes is nrows\n", + " # el numero total de cambios es nrows\n", " n = nrows\n", " cols = np.random.geometric(0.5, n)\n", " cols[cols >= ncols] = 0\n", @@ -197,7 +197,7 @@ " df.fillna(method='ffill', axis=0, inplace=True)\n", " total = df.sum(axis=1)\n", "\n", - " return total.values" + " return total.values\n" ] }, { @@ -227,7 +227,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Pink Noise - Frequency Domain" + "### Ruido rosa - dominio de la frecuencia\n" ] }, { @@ -257,27 +257,27 @@ "source": [ "pink_fourier = np.fft.fft(pink_data[0:10000]) \n", "\n", - "# finding frequency values for the x axis\n", + "# encontrar los valores de frecuencia para el eje x\n", "fx_step_size = fs_pink / len(pink_data[0:10000])\n", "nyq = .5 * fs_pink\n", "total_steps = nyq / fx_step_size\n", "fx_bins = np.linspace(0, nyq, total_steps)\n", "\n", - "noise_frequency_plot(pink_fourier, fx_bins, 'FFT of Pink Noise')" + "noise_frequency_plot(pink_fourier, fx_bins, 'FFT del ruido rosa')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Notice that in linear space plot (up on left) plots the data in a hard-to-digest way. As a result, pink noise is often shown in semi-log space. The y-axis is scaled such that each subsequent value is 10x larger than the previous. It turns out that this distribution $\\frac{1}{f^{1}}$ mysteriously shows up quite a lot in the [universe.](https://www.youtube.com/watch?v=fCn8zs912OE)" + "Observa que la grafica en espacio lineal (arriba a la izquierda) presenta los datos de una forma dificil de interpretar. Como resultado, el ruido rosa suele mostrarse en espacio semilogaritmico. El eje y se escala de modo que cada valor sucesivo es 10 veces mayor que el anterior. Resulta que esta distribucion $\\frac{1}{f^{1}}$ aparece con bastante frecuencia en el [universo](https://www.youtube.com/watch?v=fCn8zs912OE).\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Below is the distriution of power in each frequency. Notice that there is a downward slope which is a result of β = 1. This figure is in log-log space which means that both axes have a logrithmic scaling." + "Abajo se muestra la distribucion de potencia en cada frecuencia. Observa que hay una pendiente descendente que es resultado de β = 1. Esta figura esta en espacio log-log, lo que significa que ambos ejes tienen una escala logaritmica.\n" ] }, { @@ -306,14 +306,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Brown Noise - Time Domain" + "### Ruido marron - dominio temporal\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The last colored noise we will go over is Brown noise in which β = 2. Brown noise, also known as red noise, looks similar to pink noise in both the time domain and frequency domain but with some exaggerated features. Below is the time series of a brown noise signal." + "El ultimo ruido coloreado que revisaremos es el ruido marron, en el cual β = 2. El ruido marron, tambien conocido como ruido rojo, se parece al ruido rosa tanto en el dominio temporal como en el dominio de la frecuencia, pero con algunas caracteristicas mas exageradas. Abajo se muestra la serie temporal de una senal de ruido marron.\n" ] }, { @@ -322,17 +322,17 @@ "metadata": {}, "outputs": [], "source": [ - "#Function to generate time series with properties of brown noise\n", + "# funcion para generar una serie temporal con propiedades de ruido marron\n", "def brown(N, state=None):\n", "\n", " state = np.random.RandomState() if state is None else state\n", " uneven = N % 2\n", " X = state.randn(N // 2 + 1 + uneven) + 1j * state.randn(N // 2 + 1 + uneven)\n", - " S = (np.arange(len(X)) + 1)# Filter\n", + " S = (np.arange(len(X)) + 1)# filtro\n", " y = (irfft(X / S)).real\n", " if uneven:\n", " y = y[:-1]\n", - " return normalize(y,1)[0]" + " return normalize(y,1)[0]\n" ] }, { @@ -352,19 +352,19 @@ } ], "source": [ - "# get brown noise data as time series\n", + "# obtener datos de ruido marron como serie temporal\n", "brown_data = brown(1000000)\n", "fs_brown = 1000\n", "time_scale = np.arange(len(brown_data)) / fs_brown\n", "\n", - "noise_time_plot(brown_data, time_scale)" + "noise_time_plot(brown_data, time_scale)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Brown Noise - Frequency Domain" + "### Ruido marron - dominio de la frecuencia\n" ] }, { @@ -394,20 +394,20 @@ "source": [ "brown_fourier = np.fft.fft(brown_data[0:10000]) \n", "\n", - "# finding frequency values for the x axis\n", + "# encontrar los valores de frecuencia para el eje x\n", "fx_step_size = fs_brown/len(brown_data[0:10000])\n", "nyq = .5*fs_brown\n", "total_steps = nyq/fx_step_size\n", "fx_bins = np.linspace(0,nyq,total_steps)\n", "\n", - "noise_frequency_plot(brown_fourier, fx_bins, \"FFT of brown noise\")" + "noise_frequency_plot(brown_fourier, fx_bins, \"FFT del ruido marron\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Notice that in linear space the power spectrum is slightly harder to digest than the pink noise counterpart. Also note that the decrease of the power spectrum is slightly more exaggerated than that of pink noise. These patterns will be more exaggerated as β takes on larger values." + "Observa que en espacio lineal el espectro de potencia es un poco mas dificil de interpretar que su equivalente de ruido rosa. Observa tambien que la disminucion del espectro de potencia es ligeramente mas exagerada que en el ruido rosa. Estos patrones se vuelven mas marcados a medida que β toma valores mayores.\n" ] }, { @@ -429,14 +429,14 @@ "source": [ "fs_brown, ps_brown = sp.signal.welch(brown_data, fs=fs_brown, window='hanning', nperseg=2*fs_brown, noverlap=fs_brown/2, nfft=None, detrend='linear', return_onesided=True, scaling='density')\n", "\n", - "welch_plot(fs_brown, ps_brown, \"Welch's PSD of Brown Noise\")" + "welch_plot(fs_brown, ps_brown, \"PSD de Welch del ruido marron\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Compare this distribution to that of pink noise. Notice the scaling to see how the β value affects slope in this log-log plot." + "Compara esta distribucion con la del ruido rosa. Observa la escala para ver como el valor de β afecta la pendiente en esta grafica log-log.\n" ] }, { diff --git a/07-CommonMisinterpretations.ipynb b/07-CommonMisinterpretations.ipynb index 075a3e0..a952145 100644 --- a/07-CommonMisinterpretations.ipynb +++ b/07-CommonMisinterpretations.ipynb @@ -4,16 +4,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Common Band Analysis Misinterpretations\n", + "# Interpretaciones erroneas comunes en el analisis por bandas\n", "\n", - "### How band-specific analysis goes wrong" + "### Como falla el analisis especifico por bandas\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "These last couple of tutorials will discuss how various forms of analysis can go arwy and the proposed solutions offered in Voytek Lab." + "Estos ultimos tutoriales analizaran como varias formas de analisis pueden salir mal y las soluciones propuestas por el Voytek Lab.\n" ] }, { @@ -22,10 +22,10 @@ "metadata": {}, "source": [ "
\n", - "This tutorial will discuss:
 \n", - " - differences in aperiodic background
 \n", - " - individualized frequency bands\n", - "
" + "Este tutorial tratara:
 \n", + " - diferencias en el fondo aperiodico
 \n", + " - bandas de frecuencia individualizadas\n", + "\n" ] }, { @@ -50,21 +50,21 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Differences in Aperiodic Background" + "## Diferencias en el fondo aperiodico\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Unfortunately, analysis of an individual's power spectral density does not neccesarilly generalize to a broader population. This is because the features which comprise a power spectral density can differ between people. Specifically, power spectral densities have two main features - an ***aperiodic component*** which is a 1/f-like trendline and ***periodic oscillations*** which are \"bumps\" above the 1/f curve. These two features often differ between people, state, and task and Voytek Lab is working on determining if these features can reliably inform us about the individual eventhough there are differences between apparent power spectra." + "Desafortunadamente, el analisis de la densidad espectral de potencia de una persona no necesariamente se generaliza a una poblacion mas amplia. Esto se debe a que las caracteristicas que componen una densidad espectral de potencia pueden diferir entre personas. En concreto, las densidades espectrales de potencia tienen dos caracteristicas principales: un ***componente aperiodico*** que sigue una tendencia similar a 1/f y unas ***oscilaciones periodicas*** que aparecen como \"bultos\" por encima de la curva 1/f. Estas dos caracteristicas a menudo difieren entre personas, estados y tareas, y el Voytek Lab esta trabajando para determinar si estas caracteristicas pueden informarnos de manera confiable sobre el individuo incluso cuando existen diferencias entre espectros de potencia aparentes.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Don't worry too much about the details of the following cell." + "No te preocupes demasiado por los detalles de la siguiente celda.\n" ] }, { @@ -73,32 +73,33 @@ "metadata": {}, "outputs": [], "source": [ - "# Define arguments to create Power Spectral Density\n", + "# definir argumentos para crear una densidad espectral de potencia\n", "freq_range = [1,50]\n", "bg_params = [0,1]\n", "gauss_params = []\n", "gauss_params_fr = [8,.5,1,25,.6,.9]\n", "\n", - "# Create fooof model\n", + "# crear modelo fooof\n", "fm_osc = FOOOF()\n", "fm_bg = FOOOF()\n", "\n", - "# Generate synth psd settings\n", + "# generar parametros de PSD sintetica\n", "fs, ps = gen_power_spectrum(freq_range, bg_params, gauss_params)\n", "fs_osc, ps_osc = gen_power_spectrum(freq_range, bg_params, gauss_params_fr)\n", "\n", "\n", - "# Add to fooof model\n", + "# agregar al modelo fooof\n", "fm_bg.add_data(fs, ps)\n", - "fm_osc.add_data(fs_osc, ps_osc)\n" + "fm_osc.add_data(fs_osc, ps_osc)\n", + "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "As mentioned above, one difference among individuals is the aperiodic component of their PSD could vary. This harkens to the previous tutorial about colored noise where β can take different values in the equation:\n", - "$$\\frac{1}{f^{\\beta}}$$" + "Como se menciono arriba, una diferencia entre individuos es que el componente aperiodico de su PSD puede variar. Esto se relaciona con el tutorial anterior sobre ruido coloreado, donde β puede tomar distintos valores en la ecuacion:\n", + "$$\\frac{1}{f^{\\beta}}$$\n" ] }, { @@ -125,14 +126,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The above plot illustrates the ***aperiodic background*** and can vary across people by age, cognitive state, and task during recording. For example, older people tend to have a flatter or less steep curve and this alone could conflate power based analysis because if the background shifts then all power values are affected by that change." + "La grafica de arriba ilustra el ***fondo aperiodico***, que puede variar entre personas segun la edad, el estado cognitivo y la tarea durante el registro. Por ejemplo, las personas mayores tienden a tener una curva mas plana o menos pronunciada, y solo eso puede confundir los analisis basados en potencia, porque si el fondo cambia, todos los valores de potencia se ven afectados por ese cambio.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "While a difference in slope alone can introduce confounds in analysis, including oscillations in the picture further confounds analysis. The below plot illustrates the ***periodic oscillations*** above the ***aperiodic background***." + "Aunque una diferencia solo en la pendiente puede introducir factores de confusion en el analisis, incluir oscilaciones en el panorama complica aun mas el analisis. La grafica de abajo ilustra las ***oscilaciones periodicas*** por encima del ***fondo aperiodico***.\n" ] }, { @@ -159,24 +160,24 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Individual differences in slope render analytic measures drawn from these Power Spectral Densities less reliable.\n", - "For example - consider that power within a band range is significantly changed when the aperiodic component is varied. Furthermore, the relationship between any two band's power changes. This ultimately introduces confounds in analysis and is likely to decrease external validity." + "Las diferencias individuales en la pendiente hacen que las medidas analiticas extraidas de estas densidades espectrales de potencia sean menos confiables.\n", + "Por ejemplo, considera que la potencia dentro de un rango de banda cambia significativamente cuando varia el componente aperiodico. Ademas, cambia la relacion entre la potencia de dos bandas. Esto termina introduciendo factores de confusion en el analisis y probablemente reduce la validez externa.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Individualized Frequency Bands" + "## Bandas de frecuencia individualizadas\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Another way analyzing power spectra can go wrong is by using defined frequency bands. Cannonically, frequency bands such as the Alpha band have been set at [8,12]Hz. However, individuals can have a personal shift in these bands. For example, some people can have a slow peak alpha which can range from [6,10]Hz. This is a problem because oscillations might not land perfectly in the confines of the band and thus further analysis might miss out on characteristics of the oscillation.\n", + "Otra forma en la que el analisis de espectros de potencia puede salir mal es usando bandas de frecuencia definidas de forma fija. De manera canonica, bandas como la alfa se han establecido en [8,12] Hz. Sin embargo, las personas pueden presentar desplazamientos individuales en estas bandas. Por ejemplo, algunas personas pueden tener un pico alfa lento que va de [6,10] Hz. Esto es un problema porque las oscilaciones pueden no quedar perfectamente dentro de los limites de la banda y, en consecuencia, analisis posteriores pueden perder caracteristicas importantes de la oscilacion.\n", "\n", - "Below, the shaded areas are the cannonically alpha and beta band([8,12] , [15,25]) notice that the oscillations are ***NOT*** captured with the pre defined bands." + "Abajo, las areas sombreadas corresponden a las bandas alfa y beta canonicas ([8,12] y [15,25]). Observa que las oscilaciones ***NO*** quedan capturadas por las bandas predefinidas.\n" ] }, { @@ -203,14 +204,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If we are measuring power in predefined frequency bands then we are largly missing out in the power given by the oscillation. This information loss could motivated skew analysis and suggest inaccurate conclusions. A more complete analysis would take into consideration that oscillations do not always reside within a particular band." + "Si medimos la potencia dentro de bandas de frecuencia predefinidas, estamos perdiendo en gran medida la potencia aportada por la oscilacion. Esta perdida de informacion puede sesgar el analisis y llevar a conclusiones inexactas. Un analisis mas completo tendria en cuenta que las oscilaciones no siempre residen dentro de una banda determinada.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "tl;dr - Analysis of neural power spectra is hazy because differences in individuals' aperiodic component and oscillatory patterns cause the comparison of two power density spectrums to be less valid. Here is Voytek Lab's solution to some of these problems [Fooof](https://github.com/voytekresearch/fooof)." + "En resumen: el analisis de espectros de potencia neuronales es difuso porque las diferencias en el componente aperiodico y en los patrones oscilatorios de las personas hacen que la comparacion entre dos espectros de densidad de potencia sea menos valida. Aqui esta la solucion del Voytek Lab para algunos de estos problemas: [Fooof](https://github.com/voytekresearch/fooof).\n" ] }, { diff --git a/08-FrequencyMisinterpretations.ipynb b/08-FrequencyMisinterpretations.ipynb index 9c9e7f9..d776043 100644 --- a/08-FrequencyMisinterpretations.ipynb +++ b/08-FrequencyMisinterpretations.ipynb @@ -4,38 +4,37 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# How Frequency Representations Go Wrong\n", + "# Como fallan las representaciones en frecuencia\n", "\n", - "##### Sydney Smith 2018" + "##### Sydney Smith 2018\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "The information provided in this tutorial is based on the [Cole & Voytek 2017](https://doi.org/10.1016/j.tics.2016.12.008) paper *Brain Oscillations and the Importance of Waveform Shape*. \n", + "La informacion presentada en este tutorial se basa en el articulo [Cole & Voytek 2017](https://doi.org/10.1016/j.tics.2016.12.008) *Brain Oscillations and the Importance of Waveform Shape*.\n", "\n", - "Many of the techniques used to analyze neural signals, such as the Fourier Transform, filtering, etc., assume that the signals are sinusoidal in nature. These methods are found broadly in the literature and have been used to characterize aspects of the signal like oscillations, bursts, and frequency interactions. This presents a problem. Why? Because neural signals are rarely, if ever, sinusoidal. \n", + "Muchas de las tecnicas usadas para analizar senales neuronales, como la transformada de Fourier, el filtrado, etc., asumen que las senales son de naturaleza sinusoidal. Estos metodos se encuentran ampliamente en la literatura y se han usado para caracterizar aspectos de la senal como oscilaciones, rafagas e interacciones de frecuencia. Esto plantea un problema. ¿Por que? Porque las senales neuronales rara vez, si es que alguna vez, son sinusoidales.\n", "\n", - "In this this tutorial, we will:\n", + "En este tutorial vamos a:\n", "\n", - "1. Differentiate between sinuoids and non-sinusoids\n", + "1. Diferenciar entre senoides y senales no sinusoidales\n", "\n", - "2. Demonstrate non-sinusoidal waveforms in the frequency domain\n", + "2. Mostrar formas de onda no sinusoidales en el dominio de la frecuencia\n", "\n", - "3. Identify the non-sinusoidal features of neural oscillatons\n", + "3. Identificar caracteristicas no sinusoidales de las oscilaciones neuronales\n", "\n", - "4. Suggest alternative analysis methods and where to find them\n", - "\n" + "4. Sugerir metodos alternativos de analisis y donde encontrarlos\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Default imports\n", + "### Importaciones predeterminadas\n", "\n", - "Before we begin, we'll import useful python libraries and set some standard figure parameters." + "Antes de comenzar, importaremos bibliotecas utiles de Python y estableceremos algunos parametros estandar para las figuras.\n" ] }, { @@ -64,16 +63,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Sinusoids vs Non-sinusoids" + "## 1. Senoides vs. no senoides\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Simple Sinusoids\n", + "### Senoides simples\n", "\n", - "Methods in neural signal analysis are based on the assumptions that the signal in question is sinusoidal. A sinusoid is a smooth, periodic oscillation. Let's generate one now." + "Los metodos de analisis de senales neuronales se basan en la suposicion de que la senal en cuestion es sinusoidal. Una senoide es una oscilacion suave y periodica. Generemos una ahora.\n" ] }, { @@ -108,26 +107,26 @@ } ], "source": [ - "f = 1024 #sampling frequency\n", - "dur = 10 #10 seconds of signal\n", - "freq = 7 #7 Hz signal\n", - "freq2 = 130 #130 Hz signal\n", - "t = np.arange(0, dur, 1/f) #times for d\n", - "sig1 = np.sin(2 * np.pi * freq * t) #10 Hz wavelength\n", - "sig1 = 1.5*sig1; #increase the power of signal 1\n", - "#sig2 = np.sin(2 *np.pi * freq2 * t) #130 Hz wavelength\n", + "f = 1024 # frecuencia de muestreo\n", + "dur = 10 # 10 segundos de senal\n", + "freq = 7 # senal de 7 Hz\n", + "freq2 = 130 # senal de 130 Hz\n", + "t = np.arange(0, dur, 1/f) # tiempos para los datos\n", + "sig1 = np.sin(2 * np.pi * freq * t) # longitud de onda de 7 Hz\n", + "sig1 = 1.5*sig1; # aumentar la potencia de la senal 1\n", + "#sig2 = np.sin(2 *np.pi * freq2 * t) # longitud de onda de 130 Hz\n", "#complex_signal = sig1+sig2;\n", - "plt.plot(t[0:512],sig1[0:512]) #plot 0.5 seconds of data\n", - "plt.title('Sinusoidal Signal')" + "plt.plot(t[0:512],sig1[0:512]) # graficar 0.5 segundos de datos\n", + "plt.title('Senal sinusoidal')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Complex Sinusoids\n", + "### Senoides complejas\n", "\n", - "Adding more than one sinusoid together creates a complex sinusoid." + "Sumar mas de una senoide crea una senoide compleja.\n" ] }, { @@ -165,14 +164,14 @@ "sig2 = np.sin(2*np.pi*freq2*t)\n", "complex_signal = sig1+sig2;\n", "plt.plot(t[0:512], complex_signal[0:512])\n", - "plt.title('Complex Sinusoid')" + "plt.title('Senoide compleja')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Adding enough sinusoids together creates a complex signal that starts to resemble something we might see in a real electrophysiological recording. The following complex signal is composed of four frequencies: 7 Hz, 18 Hz, 80 Hz, and 130 Hz. " + "Sumar suficientes senoides crea una senal compleja que empieza a parecerse a algo que podriamos ver en un registro electrofisiologico real. La siguiente senal compleja esta compuesta por cuatro frecuencias: 7 Hz, 18 Hz, 80 Hz y 130 Hz.\n" ] }, { @@ -207,22 +206,22 @@ } ], "source": [ - "freq3 = 18 #18 Hz signal\n", + "freq3 = 18 # senal de 18 Hz\n", "freq4 = 80\n", "sig3 = np.sin(2*np.pi*freq3*t)\n", "sig4 = np.sin(2*np.pi*freq4*t)\n", "complex_signal2 = signal = sig1+sig2+sig3+sig4\n", - "plt.plot(t[0:512], complex_signal2[0:512], label = 'complex signal')\n", - "plt.title('4-Frequency Complex Sinusoid')" + "plt.plot(t[0:512], complex_signal2[0:512], label = 'senal compleja')\n", + "plt.title('Senoide compleja de 4 frecuencias')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Non-sinusoids\n", + "### No senoides\n", "\n", - "Now lets see what a non-sinusoidal signal looks like." + "Ahora veamos como se ve una senal no sinusoidal.\n" ] }, { @@ -259,17 +258,17 @@ "source": [ "from scipy import signal\n", "\n", - "freq = 10 #10 Hz signal\n", + "freq = 10 # senal de 10 Hz\n", "saw_signal = signal.sawtooth(2*np.pi*freq*t)\n", - "plt.plot(t[0:512], saw_signal[0:512], label='sawtooth signal')\n", - "plt.title('Sawtooth Signal')" + "plt.plot(t[0:512], saw_signal[0:512], label='senal diente de sierra')\n", + "plt.title('Senal diente de sierra')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Notice this waveform is not a smooth oscillation like the sinusoids above. Instead, its shape resembles the serrated edge of a saw. The \"sawtooth\" wave is an example of a nonsinudoidal waveform. Here are a few more non-sinusoids. " + "Observa que esta forma de onda no es una oscilacion suave como las senoides de arriba. En cambio, su forma se parece al borde dentado de una sierra. La onda \"diente de sierra\" es un ejemplo de una forma de onda no sinusoidal. Aqui tienes algunos ejemplos mas de senales no sinusoidales.\n" ] }, { @@ -306,32 +305,32 @@ "source": [ "plt.figure(figsize = [16,8])\n", "\n", - "freq = 20 #20Hz \n", + "freq = 20 # 20 Hz \n", "square_signal = signal.square(np.pi*freq*t)\n", "plt.subplot(2,1,1)\n", - "plt.plot(t[0:512], square_signal[0:512], label = 'square signal')\n", - "plt.title('Square Wave')\n", + "plt.plot(t[0:512], square_signal[0:512], label = 'senal cuadrada')\n", + "plt.title('Onda cuadrada')\n", "\n", "triangle_signal = np.abs(signal.sawtooth(2*np.pi*7*t))\n", "plt.subplot(2,1,2)\n", "plt.plot(t[0:512], triangle_signal[0:512])\n", - "plt.title('Triangle Wave')" + "plt.title('Onda triangular')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Non-sinusoids in the Frequency Domain" + "## 2. No senoides en el dominio de la frecuencia\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now lets see how sinusoids and non-sinusoids compare in the frequency domain. Let's start with the sawtooth wave. Here's the frequency spectrum, the first is the Fourier-transformed signal and the second is plotted using Welch's method. \n", + "Ahora veamos como se comparan las senoides y las senales no sinusoidales en el dominio de la frecuencia. Empecemos con la onda diente de sierra. Aqui esta su espectro de frecuencias: el primero es la senal transformada por Fourier y el segundo esta graficado usando el metodo de Welch.\n", "\n", - "If you need a refresher on the frequency domain and PSD, check out our [tutorial](LINK!)." + "Si necesitas repasar el dominio de la frecuencia y la PSD, revisa nuestro [tutorial](LINK!).\n" ] }, { @@ -376,29 +375,29 @@ } ], "source": [ - "# Generate sawtooth signal at 10Hz\n", + "# generar una senal diente de sierra a 10 Hz\n", "freq = 10 \n", "saw_signal = signal.sawtooth(2*np.pi*freq*t)\n", "\n", - "# Fourier Transform on the sawtooth\n", + "# transformada de Fourier de la onda diente de sierra\n", "fourier = np.fft.fft(saw_signal[0:10000])\n", "fx_step_size = 1024/len(saw_signal[0:10000])\n", "nyq = .5*1024\n", "total_steps = nyq/fx_step_size\n", "fx_bins = np.linspace(0,nyq,total_steps)\n", "\n", - "# Plot FFT\n", + "# graficar FFT\n", "plt.plot(fx_bins[0:600],np.log(abs(fourier[0:600]))) \n", - "plt.ylabel('log Power')\n", - "plt.xlabel('Frequency (Hz)')\n", - "plt.title('FFT of Sawtooth signal')" + "plt.ylabel('log Potencia')\n", + "plt.xlabel('Frecuencia (Hz)')\n", + "plt.title('FFT de la senal diente de sierra')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Although we can see some clear peaks, that PSD looks a little messy, let's clean it up and plot it again using the Welch's method." + "Aunque podemos ver algunos picos claros, esa PSD se ve un poco desordenada. Limpiemosla y volvamos a graficarla usando el metodo de Welch.\n" ] }, { @@ -441,53 +440,53 @@ } ], "source": [ - "# Welch's PSD on sawtooth\n", + "# PSD de Welch para la onda diente de sierra\n", "welch_freq,pspec = sp.signal.welch(saw_signal, fs=1024, window='hanning', nperseg=2*1024, \n", " noverlap=1024/2, nfft=None, detrend='linear', return_onesided=True, scaling='density')\n", - "# Plot Welch's\n", + "# graficar Welch\n", "plt.plot(welch_freq[0:60*2],np.log(abs(pspec[0:60*2])))\n", - "plt.ylabel('log Power')\n", - "plt.xlabel('Frequency (Hz)')\n", + "plt.ylabel('log Potencia')\n", + "plt.xlabel('Frecuencia (Hz)')\n", "plt.xlim([1, 60])\n", - "plt.title(\"Welch's PSD of sawtooth signal\")" + "plt.title(\"PSD de Welch de la senal diente de sierra\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Wait a minute... Those look weird, right? The sawtooth signal we generated has a frequency of 10Hz. So why are we seeing prominent peaks at 10, 20, 30, 40, 50, 60Hz? Notice that these peaks are appearing at integer multiples of the fundamental 10Hz. These are called harmonics. So why is the spectrum telling us there is power in these harmonics when we know that the only frequency present is 10Hz? \n", + "Espera un momento... Eso se ve raro, ¿no? La senal diente de sierra que generamos tiene una frecuencia de 10 Hz. Entonces, ¿por que estamos viendo picos prominentes en 10, 20, 30, 40, 50 y 60 Hz? Observa que estos picos aparecen en multiplos enteros de la frecuencia fundamental de 10 Hz. A eso se le llama armonicos. Entonces, ¿por que el espectro nos dice que hay potencia en esos armonicos cuando sabemos que la unica frecuencia presente es 10 Hz?\n", "\n", - "Take a guess.\n", + "Intenta adivinar.\n", "\n", - "YES! It's because the sawtooth signal is non-sinusoidal. The Fourier Transform is specifically meant for sinusoidal waveforms, so **when it's used on a signal that is not sinusoidal, the math is still treating it like it's a complex sinusoid instead of a non-sinusoidal signal**. Therefore, we are given the frequencies of the sinusoidal psuedo-components that would create this non-sinusoidal signal. \n", + "¡SI! Es porque la senal diente de sierra no es sinusoidal. La transformada de Fourier esta pensada especificamente para formas de onda sinusoidales, asi que **cuando se usa sobre una senal que no es sinusoidal, las matematicas siguen tratandola como si fuera una senoide compleja en lugar de una senal no sinusoidal**. Por lo tanto, obtenemos las frecuencias de los pseudocomponentes sinusoidales que producirian esta senal no sinusoidal.\n", "\n", - "This creates a problem: the spectrum isn't representing the reality of the signal. But don't blame the math! It's doing exactly what we ask it too. We're just choosing the wrong method to look at it so *of course* we're getting the wrong answer. \n", + "Esto crea un problema: el espectro no esta representando la realidad de la senal. Pero no culpes a las matematicas. Estan haciendo exactamente lo que les pedimos. Somos nosotros quienes estamos eligiendo el metodo equivocado para observar la senal, asi que *por supuesto* obtenemos la respuesta incorrecta.\n", "\n", - "However, this hints at an even bigger problem. Sinusoid-based functions are used almost universally in the field of neuroscience. So what happens when the neural signals they're used to analyze aren't always sinusoidal? \n", + "Sin embargo, esto apunta a un problema aun mayor. Las funciones basadas en senoides se usan casi universalmente en neurociencia. Entonces, ¿que pasa cuando las senales neuronales que analizan no siempre son sinusoidales?\n", "\n", - "Just something to think about..." + "Solo algo para pensar...\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. Non-sinusoidal Features of Neural Oscillations" + "## 3. Caracteristicas no sinusoidales de las oscilaciones neuronales\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now let's take a closer look at neural oscillations. What do the waveforms actually look like? We'll start by loading and plotting some local field potential (LFP) data recorded from a rat hippocampus." + "Ahora observemos con mas detalle las oscilaciones neuronales. ¿Como son realmente las formas de onda? Empezaremos cargando y graficando algunos datos de potencial de campo local (LFP) registrados en el hipocampo de una rata.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Load and plot data" + "### Cargar y graficar datos\n" ] }, { @@ -522,55 +521,55 @@ } ], "source": [ - "# Load signal\n", + "# cargar senal\n", "x = np.load('dat/sample_data_1.npy')\n", "Fs = 1000\n", "t = np.arange(0, len(x)/Fs, 1/Fs)\n", "f_range = (13,30)\n", "\n", - "# Plot example signal\n", + "# graficar senal de ejemplo\n", "plt.plot(t, x)\n", "plt.xlim((4,5))\n", - "plt.xlabel('Time (s)')\n", - "plt.ylabel('Voltage (uV)')\n", - "plt.title('Rat Hippocampal LFP')" + "plt.xlabel('Tiempo (s)')\n", + "plt.ylabel('Voltaje (uV)')\n", + "plt.title('LFP hipocampal de rata')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Take a closer look at the time series we just plotted. **Notice how the peaks and the troughs of the waveforms aren't symmetrical for each cycle**. It looks like the peaks of the waveform are much wider and smoother than the sharp, narrow troughs. The waves around 4.4s are a great example of this. \n", + "Observa con mas detalle la serie temporal que acabamos de graficar. **Fijate en que los picos y los valles de las formas de onda no son simetricos en cada ciclo**. Parece que los picos de la forma de onda son mucho mas anchos y suaves que los valles agudos y estrechos. Las ondas alrededor de 4.4 s son un gran ejemplo de esto.\n", "\n", - "Sinusoids are smooth, symmetrical oscillations. These waveforms aren't smooth or symmetrical. Therefore, this is probably not a sinusoid. \n", + "Las senoides son oscilaciones suaves y simetricas. Estas formas de onda no son suaves ni simetricas. Por lo tanto, probablemente no se trate de una senoide.\n", "\n", - "If neural signals aren't sinusoidal, the sinusoid-dependent analysis methods like the Fourier transform could potentially give false results, just like it did on the non-sinusoidal sawtooth wave. And if the math gives us bad output, what hope do we have of accurately characterizing the signal?\n", + "Si las senales neuronales no son sinusoidales, los metodos de analisis que dependen de senoides, como la transformada de Fourier, podrian dar resultados falsos, igual que ocurrio con la onda diente de sierra no sinusoidal. Y si las matematicas nos dan una salida deficiente, ¿que esperanza tenemos de caracterizar con precision la senal?\n", "\n", - "It's a tough problem, one that's still in the works of being solved (like everything in science). Luckily, one thing we can do is learn how to better paramaterize the signal." + "Es un problema dificil, uno que todavia esta en proceso de resolverse (como casi todo en ciencia). Afortunadamente, una cosa que si podemos hacer es aprender a parametrizar mejor la senal.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## 4. Analyzing Non-sinusoidal Signals" + "## 4. Analizar senales no sinusoidales\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "So how do we start to extract information from non-sinusoidal neural data? One option is to stay within the time series and look at waveform shape. Specifically, we can quantify the degree of symmetry within the waveform. \n", + "Entonces, ¿como empezamos a extraer informacion de datos neuronales no sinusoidales? Una opcion es permanecer en la serie temporal y observar la forma de onda. En particular, podemos cuantificar el grado de simetria dentro de la forma de onda.\n", "\n", - "Scott Cole, one of the Voytek Lab's awesome graduate students, has written an algorithm to do just this. His method, called Cycle-by-cycle, measures the degree of symmetry in each cycle of the waveform. Specifically, it delivers two very important ratios: \n", - "1. Sharpness or **Peak/Trough Symmetry**, defined as a ratio of how much of the waveform is located in the peak compared to the trough.\n", - "2. Sawtooth-yness or **Rise/Decay Symmetry**, defined as a ratio of how much of the waveform is located in the rising phase of the waveform compared to the decaying phase.\n", + "Scott Cole, uno de los excelentes estudiantes de posgrado del Voytek Lab, ha escrito un algoritmo para hacer precisamente eso. Su metodo, llamado Cycle-by-cycle, mide el grado de simetria en cada ciclo de la forma de onda. En concreto, entrega dos razones muy importantes:\n", + "1. Agudeza o **simetria pico/valle**, definida como una razon de cuanta parte de la forma de onda se encuentra en el pico en comparacion con el valle.\n", + "2. Forma de diente de sierra o **simetria subida/caida**, definida como una razon de cuanta parte de la forma de onda se encuentra en la fase ascendente en comparacion con la fase descendente.\n", "\n", - "For more information, read Scott's paper *Cycle-by-cycle Analysis of Neural Oscillations*, [preprint](https://www.biorxiv.org/content/biorxiv/early/2018/04/16/302000.full.pdf) now available on bioRxiv.\n", + "Para obtener mas informacion, lee el articulo de Scott *Cycle-by-cycle Analysis of Neural Oscillations*, [preprint](https://www.biorxiv.org/content/biorxiv/early/2018/04/16/302000.full.pdf) disponible en bioRxiv.\n", "\n", - "The algorithm itself, along with a helpful tutorial, is available on the Voytek Lab Github in the repository [NeuroDSP](https://github.com/voytekresearch/neurodsp).\n", + "El algoritmo en si, junto con un tutorial util, esta disponible en el GitHub del Voytek Lab en el repositorio [NeuroDSP](https://github.com/voytekresearch/neurodsp).\n", "\n", - "NeuroDSP contains a collection of useful tools for digital signal processing, including filtering, spectral analysis, phase-amplitude coupling, and much more, all with detailed and helpful tutorials that make using it easy. Check it out and happy analyzing!" + "NeuroDSP contiene una coleccion de herramientas utiles para el procesamiento digital de senales, incluyendo filtrado, analisis espectral, acoplamiento fase-amplitud y mucho mas, todo con tutoriales detallados y utiles que facilitan su uso. Revisalo si te interesa.\n" ] } ],