/* l1d2.c ... generates scaling data for calculating the largest Lyapunov exponent and the correlation dimension Copyright (c) 1999. Michael T. Rosenstein. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. You may contact the author by e-mail (mtr@cs.umass.edu) or postal mail (c/o Department of Computer Science, University of Massachusetts, 140 Governors Drive, Amherst, MA 01003-4610 USA). For updates to this software, please visit PhysioNet (http://www.physionet.org/). reference: M.T. Rosenstein, J.J. Collins, C.J. De Luca, A practical method for calculating largest Lyapunov exponents from small data sets, Physica D 65:117-134, 1993. email contact: mtr@cs.umass.edu */ #include #include #include #include #include #include #define IOTA 10e-15 #define MAX_LN_R 12 #define MIN_LN_R -12 #define N_LN_R 600 typedef struct { char fileName[16]; long startIndex, stopIndex; int seriesN, m, J, W, divergeT; } test; double **AllocateDMatrix(long nRows, long nCols); void ComputeSlopes(void); void FreeDMatrix(double **mat, long nRows); void GenerateTemplateFile(void); long GetData(char *fileName, int tsN, long start, long stop); void LineFit(double *data, double n, double *m, double *b, double *rr); void PercentDone(int percentDone); void ProcessTest(int testN); void ReadTestFile(char *fileName); void SaveL1Results(char *fileRoot); void SaveD2Results(char *fileRoot); int gNTests, gMaxDivergeT; double *gData, *gNDivergence; double **gDivergence, **gCSum; test *gTest; int main(void) { int i; char str[256]; printf("\n"); printf("*** L1D2: generates scaling information for L1 and D2 ***\n"); printf(" v1.0 Copyright (c) 1999 M.T. Rosenstein\n"); printf(" (mtr@cs.umass.edu)\n\n"); printf(" reference: M.T. Rosenstein, J.J. Collins, C.J. De Luca,\n"); printf(" A practical method for calculating largest\n"); printf(" Lyapunov exponents from small data sets,\n"); printf(" Physica D 65:117-134, 1993.\n\n"); GenerateTemplateFile(); printf("Enter test file name: "); scanf("%s", str); ReadTestFile(str); printf("\nEnter output file root (no extension): "); scanf("%s", str); /* allocate the divergence and correlation sum arrays */ for(i=0; i gMaxDivergeT) gMaxDivergeT = 1+gTest[i].divergeT; gNDivergence = (double *) calloc(gMaxDivergeT, sizeof(double)); gDivergence = AllocateDMatrix(gMaxDivergeT, 2*gNTests); gCSum = AllocateDMatrix(N_LN_R, 2*gNTests); for(i=0; igMaxDivergeT ? N_LN_R : gMaxDivergeT, sizeof(double)); if(data == NULL) { printf("OUT OF MEMORY: ComputeSlopes\n\n"); exit(1); }; for(i=0; i=0; i--) free(mat[i]); /* free space for the row pointers */ free(mat); } void GenerateTemplateFile(void) { FILE *outFile; outFile = fopen("sample.l1d2", "w"); fprintf(outFile, "* Header info starts with an asterisk.\n*\n"); fprintf(outFile, "* Each line of the test file contains the name of a data file followed\n"); fprintf(outFile, "* by the parameters for the test:\n"); fprintf(outFile, "* file_name series# startIndex stopIndex m J W divergeT\n*\n"); fprintf(outFile, "* file_name = name of the data file\n"); fprintf(outFile, "* series# = time series number to use for delay reconstruction\n"); fprintf(outFile, "* startIndex = index of first data point to read (usually 1)\n"); fprintf(outFile, "* stopIndex = index of last data point to read\n"); fprintf(outFile, "* (enter 0 for maximum)\n"); fprintf(outFile, "* m = embedding dimension\n"); fprintf(outFile, "* J = delay in samples\n"); fprintf(outFile, "* W = window size for skipping temporally close nearest neighbors\n"); fprintf(outFile, "* divergT = total divergence time in samples\n"); fprintf(outFile, "* example: lorenz.dat 1 1 0 5 7 100 300\n"); fclose(outFile); } long GetData(char *fileName, int tsN, long start, long stop) { long i, j, len; long nHead, nCols, nRows, nPts; char str[1024]; double dummy; FILE *inFile; /* try to open the data file */ inFile = fopen(fileName, "r"); if(inFile == NULL) { printf("FILE ERROR: GetData(%s)\n\n", fileName); exit(1); }; /* skip the header */ nHead = 0; fgets(str, 1024, inFile); while(str[0]=='*') { nHead++; fgets(str, 1024, inFile); }; /* figure out the number of columns */ len = strlen(str); i = 0; nCols = 0; while(inRows) stop = nRows; if(start<1 || start>stop-3) start = 1; nPts = stop-start+1; gData = calloc(nPts, sizeof(double)); /* now read the time series data */ rewind(inFile); for(i=0; ilast && percentDone%2==0) { last = percentDone; if(percentDone%10==0) printf("%d", percentDone/10); else printf("."); fflush(stdout); }; } void ProcessTest(int testN) { long m, J, W, divergeT, neighborIndex, maxIndex; long i, j, k, T, CSumIndex, percentDone; long nPts, nCompletedPairs=0, nVectors; char *isNeighbor; double distance, d; double k1, k2, temp, kNorm; printf("\nProcessing test %d of %d: ", testN+1, gNTests); fflush(stdout); m = gTest[testN].m; J = gTest[testN].J; W = gTest[testN].W; divergeT = gTest[testN].divergeT; nPts = GetData(gTest[testN].fileName, gTest[testN].seriesN, gTest[testN].startIndex, gTest[testN].stopIndex); k1 = (double) N_LN_R/(MAX_LN_R-MIN_LN_R); k1 *= 0.5; /* accounts for the SQUARED distances later on */ k2 = N_LN_R/2; nVectors = nPts-J*(m-1); isNeighbor = (char *) calloc(nVectors, sizeof(char)); if(isNeighbor==NULL) { printf("\nOUT OF MEMORY: ProcessTest\n\n"); exit(1); }; /* clear the divergence arrays */ for(i=0; iW) for(j=0; j=N_LN_R) CSumIndex = N_LN_R-1; /* increment the correlation sum array */ gCSum[CSumIndex][testN]++; /* now compare to current nearest neighbor */ /* use IOTA above to ignore nbrs that are too close */ if(d=N_LN_R) CSumIndex = N_LN_R-1; gCSum[CSumIndex][testN]++; if(d0.990050) ) gCSum[i][testN] = 0; else gCSum[i][testN] = log(temp); }; /* now take care of Lyapunovv average */ for(i=0; i<=divergeT; i++) if(gNDivergence[i]>0) gDivergence[i][testN] /= gNDivergence[i]; free(isNeighbor); free(gData); } void ReadTestFile(char *fileName) { int i; int nHead, nRows; char str[1024]; FILE *inFile; printf("\nReading Test File...\n"); /* try to open the data file */ inFile = fopen(fileName, "r"); if(inFile == NULL) { printf("FILE ERROR: ReadTestFile(%s)\n\n", fileName); exit(1); }; /* skip the header */ nHead = 0; fgets(str, 1024, inFile); while(str[0]=='*') { nHead++; fgets(str, 1024, inFile); }; /* figure out the number of rows; assume there's at least one */ nRows = 1; while(fgets(str, 1024, inFile) != NULL && !isspace(str[0])) nRows++; gNTests = nRows; /* allocate the test array */ gTest = (test *) calloc(gNTests, sizeof(test)); if(gTest == NULL) { printf("OUT OF MEMORY: ReadTestFile(%d)\n\n", gNTests); exit(1); }; printf("detected %d %s\n", gNTests, gNTests==1 ? "test" : "tests"); /* rewind the file and skip the header */ rewind(inFile); for(i=0; i=N_LN_R) i1 = 0; keepGoing = 1; i2 = N_LN_R-1; while(keepGoing) { for(testN=0; testN=N_LN_R) i2 = N_LN_R-1; /* write the data */ for(i=i1; i