M3_format_otfs.c

00001 /*******************************************************************************
00002 *   M3:  M3_format_otfs.c                                                      *
00003 *                                                                              *
00004 *   Version 2.0 April 2007                                                     *
00005 *                                                                              *
00006 *   Copyright (C) 2004-2007  C.M. Cantalupo                                    *
00007 *                                                                              *
00008 *   This program is free software; you can redistribute it and/or modify       *
00009 *   it under the terms of the GNU General Public License as published by       *
00010 *   the Free Software Foundation; either version 2 of the License, or          *
00011 *   (at your option) any later version.                                        *
00012 *                                                                              *
00013 *   This program is distributed in the hope that it will be useful,            *
00014 *   but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00015 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
00016 *   GNU General Public License for more details.                               *
00017 *                                                                              *
00018 *   You should have received a copy of the GNU General Public License          *
00019 *   along with this program; if not, write to the Free Software                *
00020 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA  *
00021 *                                                                              *
00022 *******************************************************************************/
00023 
00024 #include "M3.h"
00025 #include "M3_internal.h"
00026 #include "M3_format_otfs.h"
00027 #include "M3_gcp.h"
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 
00031 #include "rotateCoords.h"
00032 #define M3_CONTENT_LENGTH 256
00033 
00034 
00035 void M3_File_parseFormatString_otfs( M3_File *theFile, M3_FormatStruct_otfs *out );
00036 void M3_File_readHeader_otfs( M3_File *theFile, void *data );
00037 void M3_File_readData_otfs( M3_File *theFile, void *readArg, void *data );
00038 void M3_File_readHeader_otfs_tod( M3_File *theFile, M3_TODheader *data );
00039 void M3_File_readData_otfs_tod( M3_File *theFile, M3_Interval *readInterval, double *data );
00040 
00041 void M3_CreateNoiseFilter( double fknee, double alpha, double fmin, double fsample, double NET, int64_t corr, double *inv_tt_noise );
00042 
00043 
00044 void M3_File_parseFormatString_otfs( M3_File *theFile, M3_FormatStruct_otfs *out )
00045 {
00046   M3_FormatStruct_otfs formatStruct;
00047   char *s1, *s2;
00048   char errorString[M3_CONTENT_LENGTH];
00049   static char lastFormatString[M3_CONTENT_LENGTH] = {0};
00050   static M3_FormatStruct_otfs lastFormatStruct;
00051 
00052    /* Build in a last call cache, as we will often be parsing the same format strings over and over again.  */
00053   if( strcmp( theFile->format, lastFormatString ) == 0 )
00054   {
00055     *out = lastFormatStruct;
00056     return;
00057   }
00058   
00059   /* Set default values */
00060   out->prngSeed = 0;
00061   out->prngFirstBlock = 0;
00062   out->prngNumBlock = 4096;
00063   out->prngOffset = 0;
00064   out->prngSigma = 1;
00065   out->firstSample = 0;
00066   out->lastSample = 0;
00067   out->oofSimFormat = NULL;
00068   out->fknee = 0;
00069   out->alpha = 0;
00070   out->fmin = 0;
00071   out->fsample = 0;
00072   out->NET = 0;
00073   out->corLength = 0;
00074 
00075   sprintf( errorString, "Error interpreting format string: \"%s\"", theFile->format );
00076 
00077   /* Advance to the first parameter */
00078   s1 = strchr( theFile->format, '_');
00079 
00080   /* Loop over the parameters in the format string */
00081   while( s1 )
00082   {
00083     /* Skip '_' character */
00084     s1++;
00085 
00086     /* Switch over all of the parameters */
00087     if( strncmp( s1, "prngSeed", 8 ) == 0 )
00088     {
00089       s1 += 8;
00090       M3_ErrorCheck( -1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00091       s1++;
00092       out->prngSeed = strtoll(s1, NULL, 10);
00093     }
00094     else if( strncmp( s1, "prngFirstBlock", 14 ) == 0 )
00095     {
00096       s1 += 14;
00097       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT );
00098       s1++;
00099       out->prngFirstBlock = strtoll( s1, NULL, 10 );
00100     }
00101     else if( strncmp( s1, "prngNumBlock", 12 ) == 0 )
00102     {
00103       s1 += 12;
00104       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00105       s1++;
00106       out->prngNumBlock = strtoll( s1, NULL, 10 );
00107     }
00108     else if( strncmp( s1, "prngOffset", 10 ) == 0 )
00109     {
00110       s1 += 10;
00111       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00112       s1++;
00113       out->prngOffset = strtoll( s1, NULL, 10 );
00114     }
00115     else if( strncmp( s1, "prngSigma", 9 ) == 0 )
00116     {
00117       s1 += 9;
00118       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT );
00119       s1++;
00120       out->prngSigma = atof( s1 );
00121     }
00122     else if( strncmp( s1, "firstSample", 11 ) == 0 )
00123     {
00124       s1 += 11;
00125       M3_ErrorCheck( -1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00126       s1++;
00127       out->firstSample = strtoll(s1, NULL, 10 );
00128     }
00129     else if( strncmp( s1, "lastSample", 10 ) == 0 )
00130     {
00131       s1 += 10;
00132       M3_ErrorCheck( -1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00133       s1++;
00134       out->lastSample = strtoll(s1, NULL, 10 );
00135     }
00136     else if( strncmp( s1, "oofSimFormat", 12 ) == 0 )
00137     {
00138       s1 += 12;
00139       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT );
00140       s1++;
00141       out->oofSimFormat = s1;
00142     }
00143     else if( strncmp( s1, "fknee", 5 ) == 0 )
00144     {
00145       s1 += 5;
00146       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00147       s1++;
00148       out->fknee = atof(s1);
00149     }
00150     else if( strncmp( s1, "alpha", 5 ) == 0 )
00151     {
00152       s1 += 5;
00153       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00154       s1++;
00155       out->alpha = atof(s1);
00156     }
00157     else if( strncmp( s1, "fmin", 4 ) == 0 )
00158     {
00159       s1 += 4;
00160       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00161       s1++;
00162       out->fmin = atof(s1);
00163     }
00164     else if( strncmp( s1, "fsample", 7 ) == 0 )
00165     {
00166       s1 += 7;
00167       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00168       s1++;
00169       out->fsample = atof(s1);
00170     }
00171     else if( strncmp( s1, "NET", 3 ) == 0 )
00172     {
00173       s1 += 3;
00174       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00175       s1++;
00176       out->NET = atof(s1);
00177     }
00178     else if( strncmp( s1, "corLength", 9 ) == 0 )
00179     {
00180       s1 += 9;
00181       M3_ErrorCheck(-1, errorString, *s1 == '=', M3_EFLAG_DEFAULT);
00182       s1++;
00183       out->corLength = strtoll(s1, NULL, 10);
00184     }
00185 
00186 
00187     s1 = strchr( s1, '_');
00188   }
00189 
00190 
00191   /* Set last call cache */
00192   strcpy( lastFormatString, theFile->format );
00193   lastFormatStruct = *out;
00194 
00195 }
00196 
00197 void M3_File_readHeader_otfs_noise( M3_File *theFile, M3_NoiseHeader *header )
00198 {
00199   M3_FormatStruct_otfs formatStruct;
00200 
00201   M3_File_parseFormatString_otfs( theFile, &formatStruct );
00202 
00203   header->firstSample = formatStruct.firstSample;
00204   header->lastSample = formatStruct.lastSample;
00205   header->corLength = formatStruct.corLength;
00206 
00207 }
00208 
00209 
00210 void M3_File_readData_otfs_noise( M3_File *theFile, double *noise )
00211 {
00212   M3_FormatStruct_otfs formatStruct;
00213 
00214   M3_File_parseFormatString_otfs( theFile, &formatStruct );
00215 
00216   M3_CreateNoiseFilter( formatStruct.fknee, formatStruct.alpha, formatStruct.fmin, formatStruct.fsample, formatStruct.NET, formatStruct.corLength, noise ); 
00217 
00218 }
00219 
00220 void M3_File_readHeader_otfs( M3_File *theFile, void *data )
00221 {
00222   /* Simple switch over sub-functions for each file type */
00223   switch( theFile->fileType )
00224   {
00225     case M3_TOD_FILE_TYPE:
00226       M3_File_readHeader_otfs_tod( theFile, (M3_TODheader *)data );
00227       break;
00228     case M3_NOISE_FILE_TYPE:
00229       M3_File_readHeader_otfs_noise(theFile, (M3_NoiseHeader *)data );
00230       break;  
00231     default:
00232       M3_ErrorCheck(-1, "M3 can only read otfs files for the tod and noise file type", 0, M3_EFLAG_DEFAULT );
00233       break;
00234   }
00235 }
00236 
00237 void M3_File_readData_otfs( M3_File *theFile, void *readArg, void *data )
00238 {
00239   /* Simple switch over sub-functions for each file type */
00240   switch( theFile->fileType )
00241   {
00242     case M3_TOD_FILE_TYPE:
00243       M3_File_readData_otfs_tod( theFile, (M3_Interval*)readArg, (double *)data );
00244       break;
00245     case M3_NOISE_FILE_TYPE:
00246       M3_File_readData_otfs_noise( theFile, (double *)data );
00247       break;
00248     default:
00249       M3_ErrorCheck(-1, "M3 can only read otfs files for the tod noise file type", 0, M3_EFLAG_DEFAULT );
00250       break;
00251   }
00252 }
00253 
00254 void M3_File_readHeader_otfs_tod( M3_File *theFile, M3_TODheader *data )
00255 {
00256   M3_FormatStruct_otfs formatStruct;
00257   char *strPtr;
00258   M3_NoiseHeader noiseHeader;
00259 
00260   M3_File_parseFormatString_otfs( theFile, &formatStruct);
00261   if( formatStruct.oofSimFormat )
00262   {
00263     theFile->fileType = M3_NOISE_FILE_TYPE;
00264     strPtr = theFile->format;
00265     theFile->format = formatStruct.oofSimFormat;
00266     M3_File_ReadHeader( theFile, &noiseHeader);
00267     data->firstSample = noiseHeader.firstSample;
00268     data->lastSample = noiseHeader.lastSample;
00269     theFile->param.noise.corLength = noiseHeader.corLength;
00270     theFile->format = strPtr;
00271     theFile->fileType = M3_TOD_FILE_TYPE;
00272   }
00273   else
00274   {
00275     data->firstSample = formatStruct.firstSample;
00276     data->lastSample = formatStruct.lastSample;
00277   }
00278 
00279 }
00280 
00281 void M3_File_readData_otfs_tod( M3_File *theFile, M3_Interval *readInterval, double *data )
00282 {
00283   M3_FormatStruct_otfs formatStruct;
00284   int64_t offset, numReadEl, numFileEl, i, blockSize, j, blockIndex, blockOffset, thisNumEl, fftLength;
00285   double *noise, *filter, *forwardPlan, *backwardPlan, *nptr;
00286   double temp;
00287   int err;
00288   char *strPtr;
00289   M3_NoiseHeader noiseHeader;
00290 
00291   M3_File_parseFormatString_otfs( theFile, &formatStruct );
00292 
00293   numReadEl = readInterval->lastSample - readInterval->firstSample + 1;
00294   numFileEl = theFile->param.tod.interval.lastSample - theFile->param.tod.interval.firstSample + 1;
00295 
00296   if( !formatStruct.oofSimFormat )
00297   {
00298     offset = readInterval->firstSample - theFile->param.tod.interval.firstSample + formatStruct.prngOffset;
00299     
00300     blockSize = (numFileEl + formatStruct.prngOffset)/formatStruct.prngNumBlock + ((numFileEl + formatStruct.prngOffset)%formatStruct.prngNumBlock ? 1:0);
00301     blockIndex = offset/blockSize;
00302     blockOffset = offset%blockSize;
00303 
00304     thisNumEl = blockSize - blockOffset; 
00305     if( thisNumEl > numReadEl )
00306       thisNumEl = numReadEl;
00307 
00308     i = 0;
00309     /* Get data from part of the first used block */
00310     SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, blockOffset, thisNumEl, formatStruct.prngSigma, data );
00311     i += thisNumEl;
00312     blockIndex++;
00313     
00314     /* Get data from the full blocks */
00315     while( numReadEl - i  > blockSize )
00316     {
00317       SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, 0, blockSize, formatStruct.prngSigma, data + i );
00318       i += blockSize;
00319       blockIndex++;
00320     }
00321   
00322     /* Get the last part */
00323     if ( numReadEl - i )
00324     {
00325       thisNumEl = numReadEl - i;
00326       SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, 0, thisNumEl, formatStruct.prngSigma, data + i );
00327     }
00328   }
00329   else
00330   {
00331 #ifndef USE_LIBACML
00332     M3_ErrorCheck(-1, "Generation of noise requires ACML, FFTW not yet implemented", 0, M3_EFLAG_DEFAULT );
00333 #else
00334 
00335     /* allocate and initizlize two arrays that are twice the length of the file */
00336     fftLength = pow(2,floor(log2(2*numFileEl-1))+1);
00337 
00338     filter = (double *)calloc(fftLength,sizeof(double));
00339     noise = (double *)calloc(fftLength,sizeof(double));
00340     forwardPlan = (double *)malloc((3*fftLength+100)*sizeof(double));
00341     backwardPlan = (double *)malloc((3*fftLength+100)*sizeof(double));
00342     M3_ErrorCheck(-1, "M3_File_readData_otfs_tod(): FFT vectors", (filter && noise && forwardPlan && backwardPlan ), M3_EFLAG_MALLOC_FSTRING );
00343     /* Initialize workspace */
00344     dzfft( 0, fftLength, noise, forwardPlan, &err );
00345     zdfft( 0, fftLength, noise, backwardPlan, &err );
00346 
00347     /* read in the inv_tt_noise file into the first bit of the filter vector.*/
00348     theFile->fileType = M3_NOISE_FILE_TYPE;
00349     strPtr = theFile->format;
00350     theFile->format = formatStruct.oofSimFormat;
00351     M3_File_ReadHeader( theFile, &noiseHeader);
00352     M3_ErrorCheck(-1, "Noise generation OTFS TOD has a correlation length that is longer than half the file length.", 2*noiseHeader.corLength < numFileEl, M3_EFLAG_DEFAULT);
00353     M3_File_ReadData( theFile, NULL, noise );
00354     theFile->format = strPtr;
00355     theFile->fileType = M3_TOD_FILE_TYPE;
00356 
00357 
00358     /* copy it into the last bit of the filter vector. */
00359     for( i = 1; i <= noiseHeader.corLength; i++)
00360       noise[fftLength - i] = noise[i];
00361 
00362     /* fft the filter vector */
00363     dzfft(1, fftLength, noise, forwardPlan, &err );
00364 
00365     /***********************************************************************
00366     *   Now we know that the Fourier domain filter is real valued and      *
00367     *   even, so convert the filter from Hermitian form to real (and       *
00368     *   even).  We also need to conjugate before we do the backward FFT    *
00369     *   of the filtered data, so change the sign of the imaginary part of  *
00370     *   the filter.                                                        *
00371     ***********************************************************************/
00372 
00373     /* invert the square root of each element to go from N^-1 -> N^1/2 
00374        (note that it is positive and real valued) */
00375     temp = pow(fftLength,-0.25);
00376     filter[0] = temp/sqrt(noise[0]);
00377     i = fftLength/2 + 1;
00378     for( j = 1; j < i; j++ )
00379     {
00380       filter[j] = temp/sqrt(noise[j]);
00381       filter[fftLength - j] = -1*filter[j];
00382     }
00383 
00384     /* fill the first half of the noise array with normal zero one noise */
00385     memset(noise, 0, sizeof(double)*fftLength);
00386     offset = formatStruct.prngOffset;
00387     numFileEl = theFile->param.tod.interval.lastSample - theFile->param.tod.interval.firstSample + 1;
00388 
00389     blockSize = (numFileEl + formatStruct.prngOffset)/formatStruct.prngNumBlock + ((numFileEl + formatStruct.prngOffset)%formatStruct.prngNumBlock ? 1:0);
00390     blockIndex = offset/blockSize;
00391     blockOffset = offset%blockSize;
00392 
00393     thisNumEl = blockSize - blockOffset; 
00394     if( thisNumEl > numFileEl )
00395       thisNumEl = numFileEl;
00396 
00397     i = 0;
00398     /* Get data from part of the first used block */
00399     SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, blockOffset, thisNumEl, 1.0, noise );
00400     i += thisNumEl;
00401     blockIndex++;
00402     
00403     /* Get data from the full blocks */
00404     while( numFileEl - i  > blockSize )
00405     {
00406       SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, 0, blockSize, 1.0, noise + i );
00407       i += blockSize;
00408       blockIndex++;
00409     }
00410   
00411     /* Get the last part */
00412     if ( numFileEl - i )
00413     {
00414       thisNumEl = numFileEl - i;
00415       SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, 0, thisNumEl, 1.0, noise + i );
00416     }
00417 
00418     /* fft the noise vector */
00419     dzfft(1, fftLength, noise, forwardPlan, &err );     
00420     /* multiply the noise vector by the filter vector. */
00421     for( i = 0; i < fftLength; i++ )
00422       noise[i] *= filter[i];
00423     /* ifft the noise vector */
00424     zdfft(1, fftLength, noise, backwardPlan, &err );
00425     /* fill in the elements of the output array from the noise vector */
00426     nptr = noise + readInterval->firstSample - theFile->param.tod.interval.firstSample;
00427     for( i = 0; i < numReadEl; i++ )
00428       data[i] = nptr[i];
00429     free(backwardPlan);
00430     free(forwardPlan);
00431     free(noise);
00432     free(filter);
00433 #endif
00434 
00435   }
00436 
00437 }
00438 
00439 

Generated on Mon Nov 24 10:05:12 2008 for M3 by  doxygen 1.5.3-20071008