00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00053 if( strcmp( theFile->format, lastFormatString ) == 0 )
00054 {
00055 *out = lastFormatStruct;
00056 return;
00057 }
00058
00059
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
00078 s1 = strchr( theFile->format, '_');
00079
00080
00081 while( s1 )
00082 {
00083
00084 s1++;
00085
00086
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
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
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
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
00310 SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, blockOffset, thisNumEl, formatStruct.prngSigma, data );
00311 i += thisNumEl;
00312 blockIndex++;
00313
00314
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
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
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
00344 dzfft( 0, fftLength, noise, forwardPlan, &err );
00345 zdfft( 0, fftLength, noise, backwardPlan, &err );
00346
00347
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
00359 for( i = 1; i <= noiseHeader.corLength; i++)
00360 noise[fftLength - i] = noise[i];
00361
00362
00363 dzfft(1, fftLength, noise, forwardPlan, &err );
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
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
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
00399 SRNG_Generate_WhiteNoise( formatStruct.prngSeed, formatStruct.prngFirstBlock + blockIndex, blockOffset, thisNumEl, 1.0, noise );
00400 i += thisNumEl;
00401 blockIndex++;
00402
00403
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
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
00419 dzfft(1, fftLength, noise, forwardPlan, &err );
00420
00421 for( i = 0; i < fftLength; i++ )
00422 noise[i] *= filter[i];
00423
00424 zdfft(1, fftLength, noise, backwardPlan, &err );
00425
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