LALfctSample.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Jolien Creighton
00003 *
00004 *  This program is free software; you can redistribute it and/or modify
00005 *  it under the terms of the GNU General Public License as published by
00006 *  the Free Software Foundation; either version 2 of the License, or
00007 *  (at your option) any later version.
00008 *
00009 *  This program is distributed in the hope that it will be useful,
00010 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 *  GNU General Public License for more details.
00013 *
00014 *  You should have received a copy of the GNU General Public License
00015 *  along with with program; see the file COPYING. If not, write to the
00016 *  Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00017 *  MA  02111-1307  USA
00018 */
00019 
00020 /* <lalVerbatim file="LALfctSampleCV">
00021  * Author: Edlund, Jeffrey A.
00022  * $Id: LALfctSample.c,v 1.6 2007/06/08 14:41:44 bema Exp $
00023  * </lalVerbatim>
00024  */
00025 
00026 /* <lalLaTeX> 
00027    \section{Sample Program \texttt{LALfctSample.c}}
00028    \label{ss:LALfctSample.c}
00029 
00030    This program shows the basic use of the LALfct package.
00031  It also allows the user to specify the amount of memory that the output
00032  array should use. It then calculates the output of the FCT in chunks that
00033  will fit into memory and appends each chunk to the output file.
00034 
00035  This document goes step by step through the code of LALfctSample.c as an
00036  example of how to use the LALfct library. It may seem a little redundant,
00037  but hopefully it will make it easier for someone to use the library.
00038  </lalLaTeX> */
00039 
00040 /* <lalLaTeX>
00041    \subsubsection*{Command line Usage}
00042    </lalLaTeX> <lalVerbatim> */ 
00043  /* Usage: LALfctTest accepts these commandline parameters. 
00044    Valid Options are: 
00045       -d X  dataSize = X  (Where X is an integer)
00046       -m F  maxSizeOfOutputArrayInMegs = F (Where F is a float) 
00047             Use this to deal with memory constraints.
00048       -i inputFileName
00049       -o outputFileName
00050  
00051   An index of the Rows output will also be dumped out to inputFileName.index
00052   
00053   Example Commandline:
00054   LALfctSample -d 1024 -m 128 -i input.dat -o output.dat */
00055 /* </lalVerbatim> */
00056 
00057 /* <lalLaTeX>
00058    \subsubsection*{Required Headers}
00059    The following headers are probably the minimum required to use LALfct.
00060    But your needs may vary. 
00061    </lalLaTeX> */
00062 
00063 #include <config.h>
00064 #if defined LAL_FFTW3_ENABLED
00065 /* fftw3 not yet supported */
00066 int main( void ) { return 77; }
00067 #else /* fftw3 implementation */
00068 
00069 /*<lalVerbatim> */
00070 #include <lal/LALfct.h>  /* Include any required headers */
00071 #include <stdio.h>
00072 #include <lal/AVFactories.h>
00073 #include <lal/LALStatusMacros.h>
00074 #include <lal/LALfct.h>
00075 
00076 #include <unistd.h> /* This is for getopt */
00077   /* </lalVerbatim> */
00078 
00079 /* <lalLaTeX> 
00080    \subsubsection*{Other definitions and declarations}
00081    LAL standards require the following command to define the RCS ID string.
00082    </lalLaTeX> 
00083    <lalVerbatim> */
00084 NRCSID(LALFCTSAMPLEC,"$Id: LALfctSample.c,v 1.6 2007/06/08 14:41:44 bema Exp $");
00085 /* </lalVerbatim> */
00086 
00087 
00088 /* <lalLaTeX>
00089    I got these CODES defines from a LAL package.  They are needed for the TestStatus
00090    function. Hopefully they'll have a standard way of checking the return status of
00091    functions soon. 
00092    </lalLaTeX> <lalVerbatim>*/
00093 #define CODES_(x) #x
00094 #define CODES(x) CODES_(x)
00095 /* </lalVerbatim> */
00096 
00097 /* <lalLaTeX> 
00098    Declare and set global laldebuglevel. Set to 0 for no debugging info.  Set
00099    to LALALLDBG for full debugging. 
00100    </lalLaTeX> <lalVerbatim>*/
00101 int lalDebugLevel = 0;
00102 /* </lalVerbatim> */
00103 
00104 /* <lalLaTeX> 
00105    Local (static) function declarations (definitions are after the main function.): 
00106    </lalLaTeX> <lalVerbatim>*/
00107 LALFCTREAL phaseFunction1(LALFCTREAL x);
00108 void readData(LALFCTCOMPVector *inputDataVector, char *inputFileName);
00109 static void TestStatus( LALStatus *status, const char *ignored, int exitcode );
00110 static INT4 CheckStatus( LALStatus *status);
00111 /* </lalVerbatim> */
00112 
00113 /*  <lalLaTeX> 
00114     These are for getopt
00115     </lalLaTeX> <lalVerbatim> */
00116 extern char *optarg;
00117 extern int optind, opterr, optopt;
00118 int indx;
00119 int c; 
00120 /* </lalVerbatim> */
00121 
00122 /* <lalLaTeX>
00123    \subsubsection*{Main Function}
00124    </lalLaTeX> <lalVerbatim>  */
00125 int main( int argc, char **argv ) {
00126   /* </lalVerbatim> */
00127 
00128   /* <lalLaTeX> 
00129      Declare and zero the LALStatus structure that will be passed to the
00130      the LAL functions. 
00131      </lalLaTeX> <lalVerbatim> */
00132   static LALStatus status; /* status initialization will complain if status is
00133                              not set to zero. */
00134   /* </lalVerbatim> <lalLaTeX> 
00135      Declare the LALfct Structures that will be passed to the LALfct functions. 
00136      </lalLaTeX> <lalVerbatim> */ 
00137   LALFCTCOMPVector *inputDataVector=0; 
00138   LALfctInitParams fctInitParams;
00139   LALfctAddPhaseFuncParams fctAddPhaseFuncParams;
00140   LALfctCalcParams fctCalcParams;
00141   LALfctGenRowIndexParams fctGenRowIndexParams;
00142   LALfctGenRowIndexOutput fctGenRowIndexOutput;
00143   LALfctCalcOutput fctCalcOutput;
00144   LALFCTPlan *fctPlan=0; 
00145   /* </lalVerbatim> */
00146 
00147   /* <lalLaTeX> 
00148      The following variables will be used to divide the FCT calculation
00149      into reasonably sized chunks. 
00150      </lalLaTeX> 
00151      <lalVerbatim> */
00152   LALFCTREAL maxSizeOfOutputArrayInMegs = 0;
00153   LALFCTREAL megsPerRow = 0;
00154   UINT4 numOfIndices = 0;
00155   UINT4 numOfRowsPerIndex = 0;
00156   /* </lalVerbatim> 
00157      <lalLaTeX>
00158      Define input and output variables: 
00159      </lalLaTeX> <lalVerbatim> */
00160   char inputFileNameDefault[] = "./input.dat";
00161   char outputFileNameDefault[] = "./output.dat";
00162   char outputIndexFileNameDefault[] = "./output.dat.index";
00163   char *inputFileName = inputFileNameDefault;
00164   char *outputFileName = outputFileNameDefault;
00165   char *outputIndexFileName = outputIndexFileNameDefault;
00166   FILE *OUTPUT = NULL;  
00167   BOOLEAN outputIndexFileNameMalloced = 0;
00168   UINT2 outputIndexFileNameSize = 0;
00169   /* </lalVerbatim> <lalLaTeX>
00170      Define variables that will determine the length of the data
00171      that will be processed and the number of phase functions that
00172      will be used.  
00173      </lalLaTeX> <lalVerbatim> */
00174   UINT4 dataSize=0;
00175   UINT2 numOfDims = 2;
00176   /* </lalVerbatim> */
00177   
00178   /* <lalLaTeX>
00179      These have to be set to 0 or the CreateVector functions will complain.
00180      </lalLaTeX> <lalVerbatim>*/
00181   fctCalcOutput.rowIndex = 0;
00182   fctCalcOutput.outputData = 0;
00183   /* </lalVerbatim> */
00184   
00185   /* <lalLaTeX> 
00186      I'm going to skip over the code that calls getopt to check the 
00187      commandline parameters.  Take a look at the code if you're
00188      interested. 
00189      </lalLaTeX>*/
00190   /* Check the commandline parameters */
00191   printf("Reading commandline options:\n");
00192   opterr = 0;
00193   while ((c = getopt (argc, argv, "d:m:i:o:")) != -1) {
00194     switch (c) {
00195       case 'd':
00196         dataSize = atoi(optarg);
00197         printf("  dataSize = %d\n", dataSize);
00198         break;
00199       case 'm':
00200         maxSizeOfOutputArrayInMegs = atof(optarg);
00201         printf("  maxSizeOfOutputArrayInMegs = %g\n", 00202                maxSizeOfOutputArrayInMegs);
00203         break;
00204       case 'i':
00205         inputFileName = optarg;
00206         printf("  inputFileName = %s\n", inputFileName);
00207         break;
00208       case 'o':
00209         outputFileName = optarg;
00210         printf("  outputFileName = %s\n", outputFileName);
00211         if (outputIndexFileNameMalloced) {
00212           LALFree(outputIndexFileName);
00213         }
00214         outputIndexFileNameSize = strlen(outputFileName) + strlen(".index");
00215         outputIndexFileName = LALCalloc(outputIndexFileNameSize + 1, 00216                                         sizeof(char));
00217         strncpy(outputIndexFileName, outputFileName, outputIndexFileNameSize);
00218         strncat(outputIndexFileName, ".index", 6);
00219 
00220         break;
00221       case '?':
00222         fprintf (stderr, "Unknown option `-%c'.\n", optopt);
00223         printf("Usage:\n");
00224         printf(" -d X  dataSize = X  (Where X is an integer)\n");
00225         printf(" -m F  maxSizeOfOutputArrayInMegs = F (Where F is a float)\n");
00226         printf(" -i inputFileName\n");
00227         printf(" -o outputFileName\n");
00228         
00229         exit(1);
00230         break;
00231       default:
00232         exit(1);
00233     }
00234   }
00235   for (indx = optind; indx < argc; indx++) {
00236     printf ("Non-option argument %s\n", argv[indx]);
00237   }
00238   
00239   printf("Done reading commandline options.\n\n");
00240 
00241   /* <lalLaTeX>
00242      dataSize must be specified on the command line.
00243      </lalLaTeX> <lalVerbatim> */
00244   if (dataSize == 0) {
00245     printf("Please specify the dataSize on the Commandline");
00246     printf("using the -dX option (where X is an integer.)\n");
00247     exit(1);
00248   }
00249   /* </lalVerbatim> */
00250   printf("\n");
00251 
00252   
00253   /* <lalLaTeX> 
00254      Initialize the fctPlan. 
00255   </lalLaTeX> <lalVerbatim> */
00256   fctInitParams.numOfDataPoints = dataSize; /* Number of points in input data. */
00257   fctInitParams.numOfDims = numOfDims; /* Number of phase functions that will be used. */
00258   LALfctInitialize( &status, &fctPlan, &fctInitParams );
00259   TestStatus( &status, CODES( 0 ), 1 );
00260   /* </lalVerbatim> */
00261 
00262   /*  <lalLaTeX> 
00263       Add the phase function to the fctPlan.
00264       </lalLaTeX> <lalVerbatim> */
00265   fctAddPhaseFuncParams.dim = 1;  /* The dimension in the N dimensional 
00266                                      space that this phase function effects. */
00267   fctAddPhaseFuncParams.lengthOfDim = 128; /* This determines the range
00268                                               that you want to use to
00269                                               resolve the dimension. */
00270   fctAddPhaseFuncParams.phaseFuncForDim =  &phaseFunction1; /* A reference to
00271                                                                the phase
00272                                                                function. */
00273   LALfctAddPhaseFunc(&status, fctPlan, &fctAddPhaseFuncParams);
00274   TestStatus( &status, CODES( 0 ), 1 ); 
00275   /* </lalVerbatim> */
00276   
00277   /* <lalLaTeX>
00278      Create the proper size inputDataVector
00279      </lalLaTeX> <lalVerbatim> */
00280   LALFCTCOMPCreateVector ( &status, &inputDataVector, dataSize );
00281   TestStatus( &status, CODES( 0 ), 1 );
00282   /* </lalVerbatim> */
00283 
00284   /* <lalLaTeX> 
00285      Fill the inputDataVector with data from an input file. 
00286   </lalLaTeX> <lalVerbatim>*/
00287   readData(inputDataVector, inputFileName);
00288   /* </lalVerbatim> */
00289     
00290   /* <lalLaTeX> 
00291      Fill in fctCalcParams
00292      </lalLaTeX> <lalVerbatim>*/ 
00293   fctCalcParams.fctPlan = fctPlan;
00294   fctCalcParams.fctGenRowIndexParams = &fctGenRowIndexParams;
00295   fctCalcParams.fctGenRowIndexFunc = 0; /* Setting this to zero tells
00296                                            LALfctCalc to use the internal
00297                                            LALfctGenRowIndex */
00298   /* </lalVerbatim> */
00299 
00300 
00301   /* <lalLaTeX> 
00302      With some applications of the FCT, the entire output will not fit
00303      into the memory of the machine you're running on.  The following 
00304      section of code will divide the problem into chunks and process
00305      each chunk of the problem individually. 
00306      </lalLaTeX> */
00307 
00308   /* <lalLaTeX> 
00309      Initialize the fctGenRowIndexParams structure. 
00310      </lalLaTeX> <lalVerbatim> */
00311   fctGenRowIndexParams.fctPlan = fctPlan;
00312   fctGenRowIndexParams.goToEndOfRows = 1; /* Keep going to the end */
00313   fctGenRowIndexParams.createIndex = 0; /* Don't create the index yet. */
00314   fctGenRowIndexParams.skipRows = 0; 
00315   fctGenRowIndexParams.numOfRows = 0; /* This is ignored  because 
00316                                          goToEndOfRows is set.*/
00317   /* </lalVerbatim>  */
00318 
00319   /* <lalLaTeX> Let's figure of the number of chunks that we need to
00320      calculate. </lalLaTeX> <lalVerbatim> */
00321   if (maxSizeOfOutputArrayInMegs != 0) {
00322     megsPerRow = ((LALFCTREAL) dataSize*sizeof(LALFCTCOMP)) / 1048576.0;
00323     /* </lalVerbatim> <lalLaTeX> Let's ask LalfctGenRowIndex to return the
00324        number of rows that we will be calculating. This is returned in
00325        fctGenRowIndexOutput.numOfRows.  Note that no index is created because 
00326        fctGenRowIndexParams.createIndex is set to zero. 
00327        </lalLaTeX> <lalVerbatim> */
00328     LALfctGenRowIndex(&status, &fctGenRowIndexOutput, &fctGenRowIndexParams);
00329     TestStatus( &status, CODES( 0 ), 1 ); 
00330     /* </lalVerbatim> <lalLaTeX> 
00331        Using fctGenRowIndexOutput.numOfRows, lets calculate the number of
00332        Indices (or chunks) needed. 
00333     </lalLaTeX> <lalVerbatim> */
00334     numOfRowsPerIndex = maxSizeOfOutputArrayInMegs / megsPerRow;
00335     numOfIndices =  fctGenRowIndexOutput.numOfRows / numOfRowsPerIndex;
00336     if (numOfIndices * numOfRowsPerIndex < fctGenRowIndexOutput.numOfRows) {
00337       numOfIndices++;
00338     }
00339     /* </lalVerbatim> <lalLaTeX>
00340        If maxSizeOfOutputArrayInMegs was not specified on the command line
00341        then just do the whole thing in one chunk. 
00342        </lalLaTeX> <lalVerbatim> */
00343   } else {
00344     numOfIndices = 1;
00345     numOfRowsPerIndex = 0; /* This will be ignored, but I set it anyway. */
00346   }
00347   /* </lalVerbatim> <lalLaTeX>
00348      Okay, now lets Calculate the chunks.
00349      </lalLaTeX> <lalVerbatim> */
00350   printf("Calculating the FCT:\n");
00351   fctGenRowIndexParams.createIndex = 1; /* Create a row index this time. */
00352   fctGenRowIndexParams.numOfRows = numOfRowsPerIndex; /* Calculate only 
00353                                                          numOfRowsPerIndex
00354                                                          number of rows each time. */
00355   /* loop through the chunks */
00356   for (indx = 1; indx <= (int)numOfIndices; indx++) {
00357         
00358     if (indx == (int)numOfIndices) {
00359       fctGenRowIndexParams.goToEndOfRows = 1; /* If it's the last one then
00360                                                  ignore the numOfRows and
00361                                                  just go to the end of the
00362                                                  space. */
00363     } else {
00364       fctGenRowIndexParams.goToEndOfRows = 0; 
00365     }
00366     
00367     /* Skip the rows that we've already calculated. */
00368     fctGenRowIndexParams.skipRows = numOfRowsPerIndex * (indx - 1);
00369    
00370     /* Run LALfctCalc on the chunk */
00371     LALfctCalc(&status, &fctCalcOutput, inputDataVector, &fctCalcParams);
00372     TestStatus( &status, CODES( 0 ), 1 );
00373 
00374     /* Store the output somewhere */
00375     if (indx == 1) {
00376       OUTPUT = fopen (outputFileName, "w");
00377     } else {
00378       OUTPUT = fopen (outputFileName, "a");
00379     }
00380     fwrite(fctCalcOutput.outputData->data, sizeof(REAL4), 2 * 00381            fctCalcOutput.outputData->dimLength->data[0] * 00382            fctCalcOutput.outputData->dimLength->data[1], OUTPUT);
00383     fclose(OUTPUT);
00384     
00385     /* Store the index to the output somewhere. */
00386     if (indx == 1) {
00387       OUTPUT = fopen (outputIndexFileName, "w");
00388     } else {
00389       OUTPUT = fopen (outputIndexFileName, "a");
00390     }
00391     fwrite(fctCalcOutput.rowIndex->data, sizeof(UINT2),
00392            fctCalcOutput.rowIndex->dimLength->data[0] * 00393            fctCalcOutput.rowIndex->dimLength->data[1], OUTPUT);
00394     fclose(OUTPUT);
00395 
00396     
00397     printf("  Calculated chunk %d of %d.\n", indx, numOfIndices);
00398  
00399     /* Destroy the output Data Array */
00400     LALFCTCOMPDestroyArray(&status, &(fctCalcOutput.outputData));
00401     if (CheckStatus(&status)) {
00402       LALU4DestroyArray(&status, &(fctCalcOutput.rowIndex));
00403       TestStatus( &status, CODES( 0 ), 1 );
00404     }
00405     fctCalcOutput.outputData = 0; /* make sure that it's zero. */
00406     
00407     
00408     /* Destroy the output index Array */
00409     LALU4DestroyArray(&status, &(fctCalcOutput.rowIndex));
00410     if (CheckStatus(&status)) {
00411       TestStatus( &status, CODES( 0 ), 1 );
00412     }    
00413     fctCalcOutput.rowIndex = 0; /* Make sure that it's zero. */
00414 
00415   }
00416   /*</lalVerbatim> <lalLaTeX>
00417     We're done calculating the FCT.  So Let's clean things up and exit.
00418     </lalLaTeX> <lalVerbatim> */
00419 
00420   /* free the inputData Vector */
00421   LALFCTCOMPDestroyVector(&status, &inputDataVector);
00422     
00423   /* Destroy the fctPlan */
00424   LALfctDestroyPlan(&status, &fctPlan);
00425   TestStatus( &status, CODES( 0 ), 1 );
00426   
00427   if (outputIndexFileNameMalloced) {
00428     LALFree(outputIndexFileName);
00429   }
00430 
00431   /*Check for Memory leaks.  This is only effective if you set debuglevel 
00432     to something like LALALLDBG. (or some other value that causes memory 
00433     checks at least.) */
00434   LALCheckMemoryLeaks();
00435 
00436   return 0;
00437 }
00438 /*</lalVerbatim> */
00439 
00440 /*<lalLaTeX> 
00441   \subsubsection*{Miscellaneous Functions} 
00442 
00443   This is a sample phase function.
00444   </lalLaTeX> <lalVerbatim> */
00445 LALFCTREAL phaseFunction1(LALFCTREAL x) {
00446   return(x*x);
00447 }
00448 /*</lalVerbatim> <lalLaTeX>
00449 
00450 This is the function that reads the data from the input data file 
00451 </lalLaTeX> <lalVerbatim> */
00452 void readData(LALFCTCOMPVector *inputDataVector, char *inputFileName) {
00453   /* This function fills the inputDataVector with data from input.dat */
00454   FILE *INPUT;
00455   int Check;
00456   
00457   INPUT = fopen( inputFileName, "r" );
00458   if (INPUT == NULL) {
00459     printf("Error couldn't read Data File. inputFileName = %s\n", 00460            inputFileName);
00461     exit(1);
00462   }
00463   Check = fread(inputDataVector->data, sizeof(LALFCTREAL), 00464                 2 * inputDataVector->length, INPUT);
00465   if ( Check != (int)(2 * inputDataVector->length) ) {
00466     printf("Error couldn't read Data File.  Read Check = %d\n", Check);
00467     exit(1);
00468   }
00469 }
00470 /* </lalVerbatim> <lalLaTeX> 
00471    The following are two functions that I found in another LAL package
00472    to test the status returned from LAL functions.
00473    </lalLaTeX> <lalVerbatim> */
00474 
00475 static void TestStatus( LALStatus *status, const char *ignored, int exitcode ) {
00476   /* This function tests the status structure. I took most of this from 
00477      one of the LAL fft test programs. */
00478   char  str[64];
00479   char *tok;
00480 
00481   if ( strncpy( str, ignored, sizeof( str ) ) ) {
00482     if ( (tok = strtok( str, " " ) ) ) {
00483       do {
00484         if ( status->statusCode == atoi( tok ) ) {
00485           return;
00486         }
00487       }
00488       while ( ( tok = strtok( NULL, " " ) ) );
00489     } else {
00490       if ( status->statusCode == atoi( tok ) ) {
00491         return;
00492       }
00493     }
00494   }
00495   
00496   REPORTSTATUS( status );
00497   fprintf( stderr, "\nExiting to system with code %d\n", exitcode );
00498   exit( exitcode );
00499 }
00500 
00501 static INT4 CheckStatus( LALStatus *status) {
00502   /* This function reports nonzero values of status. */
00503   if ( status->statusCode != 0) {
00504     REPORTSTATUS( status );
00505     return(1);
00506   } 
00507   return(0);
00508 }
00509 /*</lalVerbatim>*/
00510 #endif /* fftw2 implementation */

Generated on Mon Oct 6 02:31:43 2008 for LAL by  doxygen 1.5.2