|
Correlation Library DLL
1.0
|
Correlation Library is a C++ library implemented by Raul C. Muresan. The code is free for non-commercial purposes.
For details on the Scaled Correlation algorithm see paper on "Scaled Correlation Analysis" by Danko Nikolic, Raul C. Muresan, Weijia Feng, and Wolf Singer.
The Correlation Library offers support for computing cross and scaled correlation between a pair of continuous valued, binary valued, or mixed signals.
For each method of computing the correlation and each combination of signals, there is one specialized class that can handle the respective operations.
The library compiles into a Windows DLL that exports a number of functions as wrappers over the original classes.
The C++ classes are not explicitly described here. We only provide a short description for the user to understand the structure of the library.
The class functionalities are exported by the means of wrapper functions that are described in section "Dll functions exported".
Each class is named as: C_descriptor_sufix, where
All classes respect the same standard for accepting the input data. For a binary input, a vector of time stamps is expected as input while for a continuous valued input, a digitized vector of samples is expected as input.
When multiple measurements (trials) are available for the data, the classes can handle multiple trials. The length of the trial, in original sampling units, has to be specified in the constructor. Next, when the input signals are provided in the method call to ComputeCrossCorrelation or ComputeScaledCorrelation, the method determines how many trials are available, computes the correlogram on each trial and finally averages the correlograms into one single correlogram.
When multiple trials are available, the input should be structured as follows:
|.........Trial 1...........||.........Trial 2...........||.........Trial 3...........||.........Trial 4...........||.........Trial 5...........|
If the user cannot structure the trials as a contiguous series of datapoints, then the best option is to pass a single trial to the class, get the correlogram for each trial, and then the user should compute the average correlogram.
For the two types of correlations the classes expose an interface to compute the CrossCorrelation and the ScaledCorrelation respectively. Depending on the type of the input data, the methods accept different parameter types. However, they have a general format:
Each class exposes an interface that allows access to the computed cross or scaled correlogram. The correlogram is stored in the object as a vector of floats. The vector has a size of 2*CorrelationWindow+1.
The correlogram vector is stored such that the correlation at lag -CorrelationWindow is at position 0, the correlation at lag 0 is stored at position CorrelationWindow, and the correlation at lag +CorrelationWindow is stored at position 2*CorrelationWindow.
To retrieve the correlogram, call:
The correlation library provides flexible means to interact with the classes that compute correlation. It exports a set of wrapper functions that can be used by an external caller to access the full class functionality.
To interface a given class method, the library exports a function with a similar name that has an additional parameter, which is an untyped pointer to an already created object of that class.
For example, let ClassA be the class of interest, and Method1 be a method of ClassA. To create an interface to ClassA functionality, one must first create an object of that class and then call a wrapper function to access the class method.
void* Wrapper_ObjectConstructor_ClassA() { return new ClassA(); } void Wrapper_ObjectDestructor_ClassA(void* pObj) { delete ((ClassA*) pObj); } void Wrapper_Method1_Of_ClassA(void* pObj,int iSomeParam) { ((ClassA*) pObj)->Method1(iSomeParam); } void main() { void *pObject; pObject = Wrapper_ObjectConstructor_ClassA(); //A wrapper over the constructor of class A Wrapper_Method1_Of_ClassA(pObject,1); //A wrapper over Method1 of class A Wrapper_ObjectDestructor_ClassA(pObject); //A wrapper over the destructor of class A }
Each function is named as: prefix_name_sufix, where
Cross-correlation for Continuous-Continuous data:
Cross-correlation for Binary-Continuous data:
Cross-correlation for Binary-Binary data:
Scaled correlation for Continuous-Continuous data:
Scaled correlation for Binary-Continuous data:
Scaled correlation for Binary-Binary data:
Let us consider we have two continuous valued signals that we want to correlate. The signals, we suppose, have been sampled at 1 kHz. Each signal has 2 trials recorded, with a length of 1000 ms each. We want to compute the cross-correlation and the scaled correlation.
//Cross correlogram example: #include "CorrelationLib.h" #include "Constants.h" float SignalA[2000]; float SignalB[2000]; float* CrossCorrelogram; int iTrialLength = 1000; //the legth of the trial is 1000 so we have signal vectors holding 2 trials (2000 entries) int iCorrelationWindow = 100; //-100..+100 correlation lags //Here you should fill the SignalA and SignalB arrays with values //And then compute the correlogram int isError = 0; void* ClassicCC_Computer = NULL; ClassicCC_Computer = CreateCrossCorrelationComputerCC(iCorrelationWindow,iTrialLength,isError); if(isError == 0) { ComputeCrossCorrelationCC(ClassicCC_Computer,SignalA,2000,SignalB,2000,0); CrossCorrelogram = GetCrossCorrelogramCC(ClassicCC_Computer); for(int j=0;j<2*iCorrelationWindow+1;j++) { if(CrossCorrelogram[j] != NAN) { //use the CrossCorrelogram only if the value is not NAN (only if the correlation was defined) } } } if(ClassicCC_Computer != NULL) FreeCrossCorrelationComputerCC(ClassicCC_Computer);
//Scaled correlogram example: #include "CorrelationLib.h" #include "Constants.h" float SignalA[2000]; float SignalB[2000]; float* ScaledCorrelogram; int iTrialLength = 1000; //the legth of the trial is 1000 so we have signal vectors holding 2 trials (2000 entries) int iCorrelationWindow = 100; //-100..+100 correlation lags int iScaleWindow = 25; //25 ms - if the sampling frequency of the signals is 1 kHz => we are looking to components faster than 40 Hz //Here you should fill the SignalA and SignalB arrays with values //And then compute the correlogram int isError = 0; void* ScaledCC_Computer = NULL; ScaledCC_Computer = CreateScaledCorrelationComputerCC(iScaleWindow,iCorrelationWindow,iTrialLength,isError); if(isError == 0) { ComputeScaledCorrelationCC(ScaledCC_Computer,SignalA,2000,SignalB,2000,0); ScaledCorrelogram = GetScaledCrossCorrelogramCC(ScaledCC_Computer); for(int j=0;j<2*iCorrelationWindow+1;j++) { if(ScaledCorrelogram[j] != NAN) { //use the ScaledCorrelogram only if the value is not NAN (only if the correlation was defined) } } } if(ScaledCC_Computer != NULL) FreeScaledCorrelationComputerCC(ScaledCC_Computer);
Let us now assume we have again two signals each with two trials. This time however, we want to compute the correlogram manually by computing the sum of correlation coefficients for each trial and then computing the average in the end.
//Scaled correlogram example with only one trial passed at a time: //This is useful when the user wants to compute the correlogram per trial and in the end average the correlation coefficients himself. //Averaging the sums of correlation coefficients gives a better and smoother estimate of the final scaled correlogram than averaging the individual scaled correlograms for each trial!!! #include "CorrelationLib.h" #include "Constants.h" float SignalA[2000]; float SignalB[2000]; float ScaledCorrelogram[201]; int SummedCoefficientsCount[201]; float *coeff_sum_buffer; int *coeff_count_buffer; int iTrialLength = 1000; //the legth of the trial is 1000 so we have signal vectors holding 2 trials (2000 entries) int iCorrelationWindow = 100; //-100..+100 correlation lags int iScaleWindow = 25; //25 ms - if the sampling frequency of the signals is 1 kHz => we are looking to components faster than 40 Hz int iTrialNr = 2; //Two trials //Here you should fill the SignalA and SignalB arrays with values //And then compute the correlogram int isError = 0; void* ScaledCC_Computer; ScaledCC_Computer = CreateScaledCorrelationComputerCC(iScaleWindow,iCorrelationWindow,iTrialLength,isError); if(isError == 0) { //Cleanup the final buffer and the counting buffer for(int j=0;j<2*iCorrelationWindow+1;j++) { ScaledCorrelogram[j] = 0; SummedCoefficientsCount[j] = 0; } //For each trial, compute the sum of correlation coefficients for(int i=0;i<iTrialNr;i++) { ComputeScaledCorrelationCC(ScaledCC_Computer,&(SignalA[i*iTrialLength]),iTrialLength,&(SignalB[i*iTrialLength]),iTrialLength,0); coeff_sum_buffer = GetPearsonCoefficientSumsCC(ScaledCC_Computer); coeff_count_buffer = GetPearsonCoefficientCountsCC(ScaledCC_Computer); for(j=0;j<2*iCorrelationWindow+1;j++) { if(coeff_sum_buffer[j] != NAN) ScaledCorrelogram[j] += coeff_sum_buffer[j]; SummedCoefficientsCount[j] += coeff_count_buffer[j]; } } //Now compute the final scaled correlogram by computing the average for(j=0;j<2*iCorrelationWindow+1;j++) if(SummedCoefficientsCount[j]) ScaledCorrelogram[j] /= SummedCoefficientsCount[j]; } if(ScaledCC_Computer != NULL) FreeScaledCorrelationComputerCC(ScaledCC_Computer);