Accessing GSR data using C code

Post Reply
Eric42
Posts: 3
Joined: Mon Feb 17, 2014 11:25 pm

Accessing GSR data using C code

Post by Eric42 » Tue Feb 18, 2014 12:05 am

Hi, I am having trouble storing GSR data when it is directly accessed using some C code, but no trouble storing the EEG data, and no trouble with the external data (EX1-EX8).

There is more detail below, but my core questions are:

1) Is the GSR data treated differently than the external analog channels?

2) If so, how is the raw GSR data converted to the final GSR/skin conductance signal?

Some elaboration:

We are using an Active Two system, running on a Macbook (ActiveVew 700-Mac). It is setup so it can record GSR with a 16hz coupler (the units in ActiveView are nanoSiemens). When we record the data using ActiveView, the GSR data stored in the BDF file seems fine (loaded using EEGlab in matlab).

However, I am having trouble getting the GSR data in our real-time setup. Our real-time setup uses Fieldtrip to stream the data, and we record data into a GDF file (rather than a BDF). Fieldtrip provides a set of c++ files that we used for the data streaming and real-time storage. This code accesses the USB driver and then relays the Activew data both to a TCP/IP server, and also stores the data in a GDF file. The real-time code works fine when just accessing EEG data, and it also works fine when we add the 8 external channels (channel numbers 257-264) on top of the EEG data.

The problem arises when we go beyond the 8 External channels. In the real-time code when I record channels 265-272 (the auxiliary channels, of which 265 is the GSR channel I really want to record), the GSR data does not seem to be accessed/stored properly. Instead of the GSR data, instead on channels 265&266 we get what appears to be the 16Hz excitation signal (the two channels appear to be 180 degrees out of phase with each other). Similarly on channels 267&268 we get what looks to be a low-pass filtered square wave, also ~16hz (also ~180 degrees out of phase). We currently don’t have a system with the strain gauges (Erg1&2) hooked up (which is what should be on channels 267&268), but I was trying to record all the external and auxiliary channels to see if the data was just miss-numbered and saw the second set of 16hz signals.

Looking at post: www.biosemi.nl/forum/viewtopic.php?f=7&t=607 it sounds like GSR data undergoes additional processing within the ActiveView Client before storage in the BDF file. Is this the case? And am I thus correct in understanding that without replicating those operations, the ‘raw’ GSR data arriving from the Actiview would simply appear as a sine’ish wave? I would like to know if this is so, because it would confirm that we are accessing the raw data correctly but we need to replicate the ActiveView operations for the raw data to be useful.

If so, does channel 265 still correspond to the first (of the two optional) GSR sensors? Or is there more than one channel of ‘raw’ GSR data that corresponds to a single GSR sensor (eg 265&266), and which are both combined in some fashion to derive the final GSR signal? I am, unfortunately, not a Labview programmer, although I am proficient at C and am extremely good at matlab, so I was just wondering if anyone had a summary of the operations that Actiview does to the channel(s) of raw GSR data so I could then replicate that in our C code.

Any pointers would be appreciated.

Thanks!

Eric

Coen
Site Admin
Posts: 921
Joined: Fri Mar 26, 2004 7:00 pm
Location: Amsterdam, Netherlands
Contact:

Re: Accessing GSR data using C code

Post by Coen » Tue Feb 18, 2014 2:37 pm

GSR 1: chan 265 vs chan 266
GSR 2: chan 267 vs chan 268

The amplitude of the resultant 16 Hz filtered square wave is a measure of the impedance between a pair of GSR electrodes (voltage drop of the 16 Hz, 1 uA excitation current). Scaling is best achieved with a few test resistors between the GSR electrodes (with CMS+DRL connected to one of the GSR electrodes). Admittance (in Siemens) is then the inverse of the calculated impedance (in Ohm).

Best regards, Coen (BioSemi)

Eric42
Posts: 3
Joined: Mon Feb 17, 2014 11:25 pm

Re: Accessing GSR data using C code

Post by Eric42 » Fri Feb 21, 2014 6:14 pm

Coen:

Thanks for the response.

1) Assuming some of the exact numbers (scaling and filtering) may not be essential, would it be possible to just get the theoretical goal of how to go from the two raw voltages values to a final GSR/Impedance value?

2) Failing that, I had a look at the Labview code with a friend who knows Labview better than I. I don’t think I follow it exactly, but below is my (rough) understanding how Actiview is treating the pair of channels that correspond to GSR sensor one (channels 265 and 266). Could you please have a look and see whether this is close, or if there are still gaps/misconceptions in our understanding of the process.

==============================================================
GSR Processing Steps (16hz signal NOT the 512, which is a completely different bit of Labview code):

Step 1) Differential is calculated between the raw channels (266&265): Signal1 = CH266 – CH265
Step 2) Signal1 is low passed filtered: chevechev, 4th order, lowpass, 16hz cutoff, 1dB ripple
Step 3) Signal1 is scaled (gain of 13.3, I am unclear on the significance of this number): Signal1 = 13.3 * Signal1
Step 4) Signal1 (currently collected at 2048Hz) is downsampled in rate by a factor of either ?16 or 32? I’m not quite sure.
Step 5) There is an accumulation/buffering of the most recent ?32? samples of Signal1 (is it the most recent, or does this simply run once every time 32 new numbers arrive?)
Step 6) The difference in the maximum and minimum values of the buffered Signal1 is calculated: Signal2 = max(Signal1inbuffer)- min(Signal1inbuffer)
Step 7) Signal2 is scaled (is the goal here some kind of byte compensation or bit shift, since 8192 is 2^13/10000000000000 in binary?): Signal2 = Signal2/8192
Step 8) Signal2 is inverted: Signal3 = 1/Signal2 (is this a conversion from Ohms to Siemens?).
Step 9) Signal3 is scaled (?conversion to nanoSiemens?): Signal3 = 1E+9 * Signal3
Step 10) Signal3 is then what is stored in the BDF file (after some data type/endian operations).
==============================================================

Are we even close? Is this the process that is used to convert the raw signals to the final GSR values? If so, could you please confirm the amount of scaling, the degree of downsampling and the number of datapoints used in the buffering?

There are other operations I can see in the labview code that I have not included in my summary above. This includes the checks to ensure the data is in range, as well as some code that includes an additional decimation, gain, and fitering (3rd order low pass Bessel function) that I believe are related to the data as it is shown on the Actiview display and not prior to the data storage. But if I have missed important steps in the GSR calculation itself for data as it is finally stored, could you please clarify.

Also, I know in the BDF files there are duplicate dataopints (64) in the GSR data that has to do with an internal downsampling operation (to 32Hz) followed by an upsampling back to 2048Hz to match the rest of the analog data. While I don’t need really need to duplicate that step, neither did I see it within the Labview, is that part of the downsampling/buffering steps that I was unclear on? Looking at the results of my above code, it does appear stronger when plotting every 64th point.

Since we seem to be able to record both channels 265 and 266 in our raw data files, I am just interested in being able to post-hoc convert them appropriately into a GSR signal, and was mostly interested in just doing it in the same way as is done during standard Biosemi data acquisition.

Thanks,

Eric

Coen
Site Admin
Posts: 921
Joined: Fri Mar 26, 2004 7:00 pm
Location: Amsterdam, Netherlands
Contact:

Re: Accessing GSR data using C code

Post by Coen » Tue Feb 25, 2014 1:57 pm

Your analysis of the LabVIEW steps is correct and very thorough, just see a few additional comments below

> Step 5) There is an accumulation/buffering of the most recent ?32? samples of Signal1 (is it the most recent, or does this simply run once every time 32 new numbers arrive?)

I collect a full 16 Hz wave, and then determine the min/max values in this wave at a rate of 32 Hz (after a new half wave is collected) . Consequently, on 2048 Hz, the GSR value is determined in each group of 128 data points, after each new set of 64 samples (proportionally less on higher speedmodes with higher sample rates, and proportionally less on downsampled signals),

> Step 7) Signal2 is scaled (is the goal here some kind of byte compensation or bit shift, since 8192 is 2^13/10000000000000 in binary?): Signal2 = Signal2/8192

Original 24 bit data has LSB = 1/32 uV, extra byte is added in receiver to construct 32-bit integers, conversion to uV by dividing by 32*256.

> Step 8 ) Signal2 is inverted: Signal3 = 1/Signal2 (is this a conversion from Ohms to Siemens?).

Yes, admittance (Siemens or Mho) is inverse of impedance (Ohm).

> Step 9) Signal3 is scaled (?conversion to nanoSiemens?): Signal3 = 1E+9 * Signal3

Correct.

The resultant GSR data stream is at 32 Hz sample rate. This is indeed upsampled to the original sample rate by just copying values. This is only done to keep the eventual BDF file simple with the same sample rate for all channels (although BDF does support different sample rates for different channels).

Best regards, Coen (BioSemi)

Eric42
Posts: 3
Joined: Mon Feb 17, 2014 11:25 pm

Re: Accessing GSR data using C code

Post by Eric42 » Thu Feb 27, 2014 12:42 am

Coen:

Thanks for the help. I used some resistors and the process as you clarified it (also skipping my step 4) and got values that look good and matched data collected via Actiview, so I think we are set.

Just to confirm though, my step 4 (the downsampling) is incorrect (either entirely or just because we are running at 2048Hz, there may be some Labview code that you have included to accomodate different speeds than 2048). The only downssampling (when running at 2048Hz) that would occur is the max/min subtraction sliding window (128 datapoints with 50% overlap when running at 2048Hz) that takes the sampling from 2048Hz to 32Hz (my step 5).

Thanks again!

Eric

Gordak
Posts: 7
Joined: Sat May 03, 2014 12:11 pm

Re: Accessing GSR data using C code

Post by Gordak » Tue May 13, 2014 9:22 am

Hi

First, what is the input data ? The voltage digitized with a LSB = 31.25 nV ? Or the resistance ? Both are proportional, but with a difference of magnitude of10^6.

I have some questions about two steps:

step 3) Signal1 = 13.3 * Signal1
Can you explain the reason behind this multiplication ?

step 7) Signal2 = Signal2/8192

This step confuses me a lot. I understand you divide by 32 to make the LSB = 1uV. But why do you divide by 256 afterwards ? It seems to correpsond to a logical shift "x >> 8", but what is the use here ? Don't you lose information by doing this ? Also, I guess that you need to convert the 32 bits integer into a float in order to compute 1/signal2 for the next step ?

I'm not able to understand your LabView code, but if Ican understand these two steps I would be glad !

Gordak

Coen
Site Admin
Posts: 921
Joined: Fri Mar 26, 2004 7:00 pm
Location: Amsterdam, Netherlands
Contact:

Re: Accessing GSR data using C code

Post by Coen » Tue May 13, 2014 2:20 pm

>step 3) Signal1 = 13.3 * Signal1

Scaling factor determined by hardware components.

>But why do you divide by 256 afterwards ?

To compensate for the extra byte added to the 24-bit ADC output words.

>Don't you lose information by doing this

No, there is no information in the 4th byte.

> Also, I guess that you need to convert the 32 bits integer into a float in order to compute 1/signal2 for the next step ?

It is already a float after the low-pass filter (blue data steam changes to orange in the LabVIEW code).

Best regards, Coen (BioSemi)

Gordak
Posts: 7
Joined: Sat May 03, 2014 12:11 pm

Re: Accessing GSR data using C code

Post by Gordak » Wed May 14, 2014 2:05 pm

Thank you for your time.

Post Reply