ElectroPy
Context
This is a Python program that reads an excel file with information from eletrophysiology recordings on brain slices, analyses it and exports the required parameters in an accessible way. I made it for my girlfriend, who is currently a Neurocience Masters’ student. She is studying the role of inflammation on an epilepsy model, using hippocampal slices to assess both molecular and electrophysiology hallmarks in the progression of the disease. She submits those slices to a 40-minute protocol where a specific program detects spontaneous brain activity and then returns those oscillations in data: time and amplitude. She asked for my help to optimise that data’s treatment because the method she used was archaic and very time consuming. From the results the program returns, she needed to apply certain temporal conditions to find bursts of activity, on top of which she needed to extract the number of bursts, the duration and frequency of each burst, the number of events per burst and the peak and average amplitude of each burst. All of this for a single sample, and she has around 12 samples per week.
Please keep in mind this was my first time trying to create something like this so I am positive that there are more efficient ways to simulate what I did. I still have a lot to develop in my Python skills, but the goal with this program was to provide, with what I know today, an user-friendly solution that could simplify my girlfriend's tasks of analysing each sample's data.
You can also find this blog post in my Medium page, and the script and some sample datasets in my GitHub.
The program explained
The first part of the code is just to import the required libraries:
Then, to start it off, first we get the current folder’s directory so in the end we can just have the executable in the folder where we have our files. Since there might be more than one file to be analysed, I wanted to make a script that could handle multiple analyses so it would be easier and quicker to use.
Since we might be working with multiple files, I decided to create an empty dictionary so we could store in there, separately, the data for each file. I also created a variable for the file number but it is only used to increment at the end of each for loop, so it is always reading and analysing the correct file. From here on, everything will be inside a for loop that runs through all files in the folder.
Here we will start the analysis that is made to each file. First, we store the name of the file and then, in the dictionary, read the excel file to a dataframe. After that we clear all rows with empty values. These are mostly at the beginning and end of the file, where some information is missing.
We can now get the number of entries each file has and calculate the frequency for each row. To do so, we considered that the period of each wave starts with the start time of one row and ends with the start time of the next row.
The whole goal of this analysis is to see if each file’s sample had a “burst” during the experiment. A burst is considered to be an event that lasts at least 6 seconds and, during that period, all activity has frequency higher than 2 Hz and all occurrences are less than 2 second apart. So now we establish the last two conditions mentioned, for a first analysis.
With these conditions, we now apply them to the dataset and create a new column where 1 means that the row fulfills both conditions, and 0 means that at least one condition is not met.
Theoretically, the data should both start and end with a 0 in the column we created previous to this. But I found that there are some cases where the file starts or ends with a row that meets the conditions and these didn’t work well with the method I used to apply the last condition to detect bursts. To prevent these issues (probably related with data inconsistencies), I created two extra rows, one at the beginning and one at the end, with the same data as the rows next to them but then I force the column ‘Possible Burst’ to have the value 0.
We now know where there are possible bursts, we just need to apply the third condition. To do so, we create an empty dataframe to calculate the period between each 0 to 1 and 1 to 0 change. With this, we can then select only the events that lasted more than 6 seconds as the last condition.
If there happens to be a file that does not include a burst, there is no need to continue analysing it’s data. In this step, if that is the case, we create a text file with the name of the sample just saying that there are no bursts in this dataset.
For the files that do actually have bursts, we first add a column to know how many bursts there are. After that, we need to get the actual data from the interval of each burst. Since the previous information just had the times at which it started and ended, we get the indexes from those rows and then use those indexes to create a new dataframe we all of the data from all of the bursts.
Aside from calculating some outputs with the data from all bursts, we also want information on each burst, individually. To get that, we create an empty dictionary and store there each burst’s information.
On to the results! First, for all bursts’ data, we get the number of events and number of bursts, and then some averages per burst: number of events, burst time, peak amplitude and frequency. All of these are stored in a dataframe to easily export the data.
For each burst, we get the number of events, burst time, average peak amplitude and average frequency.
Before exporting the results, in the folder we are working, we create a new folder with the name of the sample and store it’s directory.
To end the program, we export the results in a new excel file and save it to the new folder. After that, we send to that same folder the original file, used for the analysis, and then increment the number of the file.
Execution of the program
Since the goal was to have an easy, user-friendly, solution, I didn’t her to rely on an IDE to run the script so I decided to create an executable from this python script. To do this I had to install the PyInstaller Package (pip install pyinstaller
), open the cmd in the folder where I had the script (tip: open the actual folder and then just write ‘cmd’ in the folder’s directory) and then write the following:
“Program.py” is the name of the script and the “--windowed” part is so that the cmd does not open when we execute the file. Here is a quick video showing how this program works:
Full python script
Final thoughts
This was a great test of my Python knowledge where learned a lot of features I wasn’t aware of and got even more excited about the possibilites about learning this programming language. It was also very satisfying to able to use Python in a real-case scenario where it helps someones’ actual work.