LALFrameIO.c

Go to the documentation of this file.
00001 /*
00002 *  Copyright (C) 2007 Bernd Machenschalk, Jolien Creighton, Robert Adam Mercer, Xavier Siemens
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 #include <config.h>
00021 #include <unistd.h>
00022 #ifndef HAVE_GETHOSTNAME_PROTOTYPE
00023 int gethostname(char *name, int len);
00024 #endif
00025 
00026 #include <math.h>
00027 
00028 #include <lal/LALDetectors.h>
00029 #include <lal/LALStdio.h>
00030 #include <lal/Date.h>
00031 #include <lal/Units.h>
00032 #include <lal/TimeSeries.h>
00033 #include <lal/FrequencySeries.h>
00034 
00035 #include <lal/LALString.h>
00036 #include <lal/FrameCache.h>
00037 #include <lal/LALFrameIO.h>
00038 #include <lal/LALCalibration.h>
00039 
00040 #include <lal/LALRCSID.h>
00041 NRCSID (LALFRAMEIOC,"$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $");
00042 
00043 struct FrFile * XLALFrOpenURL( const char *url )
00044 {
00045   static const char *func = "XLALFrOpenURL";
00046   struct FrFile *frfile = NULL;
00047   char prot[FILENAME_MAX] = "";
00048   char host[FILENAME_MAX] = "";
00049   char path[FILENAME_MAX] = "";
00050   int n;
00051 
00052   if ( ! url )
00053     XLAL_ERROR_NULL( func, XLAL_EFAULT );
00054   if ( strlen( url ) >= FILENAME_MAX )
00055   {
00056     XLALPrintError( "XLAL Error - %s: URL too long: %s\n", func, url );
00057     XLAL_ERROR_NULL( func, XLAL_EBADLEN );
00058   }
00059 
00060   n = sscanf( url, "%[^:]://%[^/]%s", prot, host, path );
00061   if ( n != 3 ) /* perhaps the hostname has been omitted */
00062   {
00063     strncpy( host, "localhost", sizeof( host ) - 1 );
00064     n = sscanf( url, "%[^:]://%s", prot, path );
00065     if ( n != 2 ) /* assume the whole thing is a file path */
00066     {
00067       strncpy( prot, "file", sizeof( prot ) - 1 );
00068       strncpy( path, url, sizeof( path ) - 1 );
00069     }
00070   }
00071 
00072   if ( strcmp( prot, "file" ) ) /* not a file URL */
00073   {
00074     XLALPrintError( "XLAL Error - %s: unsupported protocol %s\n", func, prot );
00075     XLAL_ERROR_NULL( func, XLAL_EINVAL );
00076   }
00077   else /* OK: this is a file URL */
00078   {
00079     if ( strcmp( host, "localhost" ) ) /* not explicitly localhost */
00080     { /* make sure that the host is the localhost */
00081       char localhost[FILENAME_MAX];
00082       gethostname( localhost, FILENAME_MAX - 1 );
00083       if ( strcmp( host, localhost ) ) /* not localhost */
00084       {
00085         XLALPrintError( "XLAL Error - %s: cannot read files from remote host %s\n", func, host );
00086         XLAL_ERROR_NULL( func, XLAL_EINVAL );
00087       }
00088     }
00089     frfile = FrFileINew( path );
00090     if ( ! frfile )
00091     {
00092       XLALPrintError( "XLAL Error - %s: could not open frame file %s\n", func, path );
00093       XLAL_ERROR_NULL( func, XLAL_EIO );
00094     }
00095   }
00096 
00097   return frfile;
00098 }
00099 
00100 
00101 /* code taken from the FrCheck program in the FrameL library */
00102 int XLALFrFileCheckSum( FrFile *iFile )
00103 {
00104   static const char *func = "XLALFrFileCheckSum";
00105   FrameH *frame = NULL;
00106   FRBOOL chkSumFiFlag = iFile->chkSumFiFlag;
00107   FRBOOL chkSumFrFlag = iFile->chkSumFrFlag;
00108   iFile->chkSumFiFlag = FR_YES;
00109   iFile->chkSumFrFlag = FR_NO;
00110   /* sequential read */
00111   while ((frame = FrameReadRecycle(iFile, frame)))
00112     ;
00113   iFile->chkSumFiFlag = chkSumFiFlag;
00114   iFile->chkSumFrFlag = chkSumFrFlag;
00115   if ( iFile->error != FR_OK ) {
00116     XLALPrintError( "XLAL Error - %s: %s\n", func, FrErrorGetHistory() );
00117     XLAL_ERROR( func, XLAL_EFAILED );
00118     return -1;
00119   }
00120   if ( iFile->chkTypeFiRead == 0 ) {
00121     XLALPrintWarning( "XLAL Warning - %s: missing checksum\n", func );
00122     return 1;
00123   } 
00124   if ( iFile->chkSumFiRead != iFile->chkSumFi ) {
00125     XLALPrintError( "XLAL Error - %s: bad checksum\n", func );
00126     return -1;
00127   }
00128   return 0;
00129 }
00130 
00131 
00132 /* This routine is essentially the same as FrHistoryNew but the name of the
00133  * history can be set too. */
00134 FrHistory * XLALFrHistoryAdd( FrameH *frame, const char *name, const char *comment )
00135 {
00136   static const char *func = "XLALFrHistoryAdd";
00137   union { const char *cs; char *s; } namecnvrt; /* get rid of const qual */
00138   union { const char *cs; char *s; } commentcnvrt; /* get rid of const qual */
00139   LIGOTimeGPS now;
00140   FrHistory *history;
00141 
00142   /* get current time */
00143   if ( ! XLALGPSTimeNow( &now ) )
00144     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00145 
00146   /* this nonsense is to convert const char * to char * ... don't worry,
00147    * the frame library just copies the string anyway */
00148   namecnvrt.cs    = name;
00149   commentcnvrt.cs = comment;
00150 
00151   /* now create the history */
00152   history = FrHistoryNew( namecnvrt.s, now.gpsSeconds, commentcnvrt.s );
00153   if ( ! history )
00154     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00155 
00156   /* attach history to the frame structure */
00157   if ( frame )
00158   {
00159     /* behaviour is identical to FrHistoryAdd if name is NULL */
00160     if ( ! name )
00161       FrStrCpy( &history->name, frame->name );
00162     history->next = frame->history;
00163     frame->history = history;
00164   }
00165 
00166   return history;
00167 }
00168 
00169 FrDetector * XLALFrDetectorNew( int detector )
00170 {
00171   static const char *func = "XLALFrDetectorNew";
00172   const LALDetector *lalDetector;
00173   FrDetector *frDetector;
00174   char *detectorName;
00175 
00176   if ( detector < 0 || detector >= LAL_NUM_DETECTORS )
00177     XLAL_ERROR_NULL( func, XLAL_EINVAL );
00178   lalDetector = lalCachedDetectors + detector;
00179 
00180   detectorName = XLALStringDuplicate( lalDetector->frDetector.name );
00181   frDetector = FrDetectorNew( detectorName );
00182   LALFree( detectorName );
00183   if ( ! frDetector )
00184     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00185 
00186   memcpy( frDetector->prefix, lalDetector->frDetector.prefix, 2 );
00187   frDetector->longitude    = lalDetector->frDetector.vertexLongitudeRadians;
00188   frDetector->latitude     = lalDetector->frDetector.vertexLatitudeRadians;
00189   frDetector->elevation    = lalDetector->frDetector.vertexElevation;
00190   frDetector->armXazimuth  = lalDetector->frDetector.xArmAzimuthRadians;
00191   frDetector->armYazimuth  = lalDetector->frDetector.yArmAzimuthRadians;
00192   frDetector->armXaltitude = lalDetector->frDetector.xArmAltitudeRadians;
00193   frDetector->armYaltitude = lalDetector->frDetector.yArmAltitudeRadians;
00194   frDetector->armXmidpoint = lalDetector->frDetector.xArmMidpoint;
00195   frDetector->armYmidpoint = lalDetector->frDetector.yArmMidpoint;
00196   frDetector->localTime    = 0;
00197 
00198   return frDetector;
00199 }
00200 
00201 
00202 FrameH * XLALFrameNew( LIGOTimeGPS *epoch, double duration, 
00203     const char *project, int run, int frnum, int detectorFlags )
00204 {
00205   static const char *func = "XLALFrameNew";
00206   static char histidname[] = __FILE__ " Id";
00207   static char histtagname[] = __FILE__ " Tag";
00208   static char rcsname[] = "$Name:  $";
00209   static char rcsid[] = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $";
00210   int detector;
00211   char *proj;
00212   FrameH *frame;
00213 
00214   proj = XLALStringDuplicate( project );
00215   if ( ! proj )
00216     XLAL_ERROR_NULL( func, XLAL_ENOMEM );
00217   frame = FrameHNew( proj );
00218   LALFree( proj );
00219   if ( ! frame )
00220     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00221 
00222   frame->run    = run;
00223   frame->frame  = frnum;
00224   frame->GTimeS = epoch->gpsSeconds;
00225   frame->GTimeN = epoch->gpsNanoSeconds;
00226   frame->ULeapS = XLALLeapSeconds( epoch->gpsSeconds );
00227   frame->dt     = duration;
00228   /* TODO: what about dataQuality ? */
00229 
00230   for ( detector = 0; detector < LAL_NUM_DETECTORS; ++detector )
00231   {
00232     int detector_flag = 1 << 2 * detector;
00233     if ( ( detector_flag & detectorFlags ) ) /* yes, one ampersand! */
00234     {
00235       /* add this detector */
00236       FrDetector *d;
00237       d = XLALFrDetectorNew( detector );
00238       if ( ! d )
00239         XLAL_ERROR_NULL( func, XLAL_EFUNC );
00240       d->next = frame->detectProc;
00241       frame->detectProc = d;
00242     }
00243   }
00244 
00245   /* add history: name of history field is this function's name */
00246   if ( ! XLALFrHistoryAdd( frame, histidname, rcsid ) )
00247     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00248   if ( ! XLALFrHistoryAdd( frame, histtagname, rcsname ) )
00249     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00250   return frame;
00251 }
00252 
00253 
00254 FrVect * XLALFrVectREAL4TimeSeries( REAL4TimeSeries *series )
00255 {
00256   static const char *func = "XLALFrVectREAL4TimeSeries";
00257   char seconds[LALUnitTextSize] = "s";
00258   char units[LALUnitTextSize];
00259   FrVect *vect;
00260 
00261   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00262     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00263 
00264   vect = FrVectNew1D( series->name, FR_VECT_4R, series->data->length, series->deltaT, seconds, units );
00265   if ( ! vect )
00266     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00267   vect->startX[0] = 0.0;
00268 
00269   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00270 
00271   FrVectCompress (vect, 8, 0);
00272   if (vect->compress == 0) FrVectCompress (vect, 6, 1);
00273 
00274   return vect;
00275 }
00276 
00277 
00278 FrVect * XLALFrVectREAL8TimeSeries( REAL8TimeSeries *series )
00279 {
00280   static const char *func = "XLALFrVectREAL8TimeSeries";
00281   char seconds[LALUnitTextSize] = "s";
00282   char units[LALUnitTextSize];
00283   FrVect *vect;
00284 
00285   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00286     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00287 
00288   vect = FrVectNew1D( series->name, FR_VECT_8R, series->data->length, series->deltaT, seconds, units );
00289   if ( ! vect )
00290     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00291   vect->startX[0] = 0.0;
00292 
00293   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00294 
00295   FrVectCompress (vect, 6, 1);
00296 
00297   return vect;
00298 }
00299 
00300 
00301 FrVect * XLALFrVectCOMPLEX8TimeSeries( COMPLEX8TimeSeries *series )
00302 {
00303   static const char *func = "XLALFrVectCOMPLEX8TimeSeries";
00304   char seconds[LALUnitTextSize] = "s";
00305   char units[LALUnitTextSize];
00306   FrVect *vect;
00307 
00308   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00309     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00310 
00311   vect = FrVectNew1D( series->name, FR_VECT_8C, series->data->length, series->deltaT, seconds, units );
00312   if ( ! vect )
00313     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00314   vect->startX[0] = 0.0;
00315 
00316   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00317 
00318   FrVectCompress (vect, 6, 1);
00319 
00320   return vect;
00321 }
00322 
00323 
00324 
00325 FrVect * XLALFrVectCOMPLEX16TimeSeries( COMPLEX16TimeSeries *series )
00326 {
00327   static const char *func = "XLALFrVectCOMPLEX8TimeSeries";
00328   char seconds[LALUnitTextSize] = "s";
00329   char units[LALUnitTextSize];
00330   FrVect *vect;
00331 
00332   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00333     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00334 
00335   vect = FrVectNew1D( series->name, FR_VECT_16C, series->data->length, series->deltaT, seconds, units );
00336   if ( ! vect )
00337     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00338   vect->startX[0] = 0.0;
00339 
00340   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00341 
00342   FrVectCompress (vect, 6, 1);
00343 
00344   return vect;
00345 }
00346 
00347 /*  FIXME: Should f0 be startX in the vect or fShift in the proc data ??? */
00348 
00349 FrVect * XLALFrVectREAL4FrequencySeries( REAL4FrequencySeries *series )
00350 {
00351   static const char *func = "XLALFrVectREAL4FrequencySeries";
00352   char hertz[LALUnitTextSize] = "s^-1";
00353   char units[LALUnitTextSize];
00354   FrVect *vect;
00355 
00356   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00357     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00358 
00359   vect = FrVectNew1D( series->name, FR_VECT_4R, series->data->length, series->deltaF, hertz, units );
00360   if ( ! vect )
00361     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00362   vect->startX[0] = series->f0;
00363 
00364   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00365 
00366   FrVectCompress (vect, 8, 0);
00367   if (vect->compress == 0) FrVectCompress (vect, 6, 1);
00368 
00369   return vect;
00370 }
00371 
00372 
00373 FrVect * XLALFrVectREAL8FrequencySeries( REAL8FrequencySeries *series )
00374 {
00375   static const char *func = "XLALFrVectREAL8FrequencySeries";
00376   char hertz[LALUnitTextSize] = "s^-1";
00377   char units[LALUnitTextSize];
00378   FrVect *vect;
00379 
00380   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00381     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00382 
00383   vect = FrVectNew1D( series->name, FR_VECT_8R, series->data->length, series->deltaF, hertz, units );
00384   if ( ! vect )
00385     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00386   vect->startX[0] = series->f0;
00387 
00388   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00389 
00390   FrVectCompress (vect, 6, 1);
00391 
00392   return vect;
00393 }
00394 
00395 
00396 FrVect * XLALFrVectCOMPLEX8FrequencySeries( COMPLEX8FrequencySeries *series )
00397 {
00398   static const char *func = "XLALFrVectCOMPLEX8FrequencySeries";
00399   char hertz[LALUnitTextSize] = "s^-1";
00400   char units[LALUnitTextSize];
00401   FrVect *vect;
00402 
00403   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00404     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00405 
00406   vect = FrVectNew1D( series->name, FR_VECT_8C, series->data->length, series->deltaF, hertz, units );
00407   if ( ! vect )
00408     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00409   vect->startX[0] = series->f0;
00410 
00411   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00412 
00413   FrVectCompress (vect, 6, 1);
00414 
00415   return vect;
00416 }
00417 
00418 
00419 FrVect * XLALFrVectCOMPLEX16FrequencySeries( COMPLEX16FrequencySeries *series )
00420 {
00421   static const char *func = "XLALFrVectCOMPLEX16FrequencySeries";
00422   char hertz[LALUnitTextSize] = "s^-1";
00423   char units[LALUnitTextSize];
00424   FrVect *vect;
00425 
00426   if ( NULL == XLALUnitAsString( units, sizeof( units ), &series->sampleUnits ) )
00427     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00428 
00429   vect = FrVectNew1D( series->name, FR_VECT_8C, series->data->length, series->deltaF, hertz, units );
00430   if ( ! vect )
00431     XLAL_ERROR_NULL( func, XLAL_EERR ); /* "internal" error */
00432   vect->startX[0] = series->f0;
00433 
00434   memcpy( vect->data, series->data->data, series->data->length * sizeof( *series->data->data ) );
00435 
00436   FrVectCompress (vect, 6, 1);
00437 
00438   return vect;
00439 }
00440 
00441 
00442 int XLALFrameAddCalRef( FrameH *frame, COMPLEX8FrequencySeries *series, int version, double duration )
00443 {
00444   static const char *func = "XLALFrameAddCalRef";
00445   char representation[] = "freq_series";
00446   char comment[] = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $";
00447   char prefix[3];
00448   FrDetector *detector;
00449   FrStatData *sdat;
00450   FrVect *vect;
00451   int tstart;
00452   int tend;
00453 
00454   /* To find the detector, look for the detector prefix stored as the first
00455    * two characters of the channel name. */
00456   prefix[0] = series->name[0];
00457   prefix[1] = series->name[1];
00458   prefix[2] = 0;
00459 
00460   detector = FrameFindDetector( frame, prefix );
00461   if ( ! detector )
00462   {
00463     XLALPrintError( "XLAL Error - %s: no detector associated with prefix %s in frame\n", func, prefix );
00464     XLAL_ERROR( func, XLAL_EINVAL );
00465   }
00466 
00467   vect = XLALFrVectCOMPLEX8FrequencySeries( series );
00468   if ( ! vect )
00469     XLAL_ERROR( func, XLAL_EFUNC );
00470 
00471   tstart = series->epoch.gpsSeconds;
00472   tend = (int)ceil( series->epoch.gpsSeconds + 1e-9*series->epoch.gpsNanoSeconds + duration );
00473   sdat = FrStatDataNew( series->name, comment, representation, tstart, tend, version, vect, NULL );
00474   if ( ! sdat )
00475   {
00476     FrVectFree( vect );
00477     XLAL_ERROR( func, XLAL_EERR );
00478   }
00479 
00480   FrStatDataAdd( detector, sdat );
00481 
00482   return 0;
00483 }
00484 
00485 
00486 COMPLEX8FrequencySeries * XLALFrameGetCalRef( LIGOTimeGPS *validUntil, LIGOTimeGPS *epoch, const char *channel, FrameH *frame )
00487 {
00488   static const char *func = "XLALFrameGetCalRef";
00489   char prefix[3];
00490   LALUnit unit;
00491   COMPLEX8FrequencySeries *series;
00492   FrStatData *sdat;
00493   char *chan;
00494 
00495   /* To find the detector, look for the detector prefix stored as the first
00496    * two characters of the channel name. */
00497   prefix[0] = channel[0];
00498   prefix[1] = channel[1];
00499   prefix[2] = 0;
00500 
00501   chan = XLALStringDuplicate( channel );
00502   sdat = FrameFindStatData( frame, prefix, chan, epoch->gpsSeconds );
00503   LALFree( chan );
00504   if ( ! sdat || sdat->timeStart > (UINT4)epoch->gpsSeconds || sdat->timeEnd < (UINT4)epoch->gpsSeconds )
00505   {
00506     XLALPrintError( "XLAL Error - %s: no stat data channel %s for GPS time %d in frame\n", func, channel, epoch->gpsSeconds );
00507     XLAL_ERROR_NULL( func, XLAL_EINVAL );
00508   }
00509 
00510   /* parse units */
00511   if ( NULL == XLALParseUnitString( &unit, sdat->data->unitY ) )
00512   {
00513     XLALPrintError( "XLAL Error - %s: could not parse unit string %s\n", func, sdat->data->unitY );
00514     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00515   }
00516 
00517   /* use validUntil as dummy structure */
00518   validUntil->gpsSeconds     = sdat->timeStart;
00519   validUntil->gpsNanoSeconds = 0;
00520 
00521   series = XLALCreateCOMPLEX8FrequencySeries( sdat->data->name, validUntil, sdat->data->startX[0], sdat->data->dx[0], &unit, sdat->data->nData );
00522   if ( ! series )
00523     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00524 
00525   memcpy( series->data->data, sdat->data->data, series->data->length * sizeof( *series->data->data ) );
00526 
00527   /* report end time of validity in validUntil */
00528   validUntil->gpsSeconds = sdat->timeEnd;
00529 
00530   return series;
00531 }
00532 
00533 
00534 int XLALFrameAddCalFac( FrameH *frame, REAL4TimeSeries *series, int version )
00535 {
00536   static const char *func = "XLALFrameAddCalFac";
00537   char representation[] = "time_series";
00538   char comment[] = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $";
00539   char prefix[3];
00540   FrDetector *detector;
00541   FrStatData *sdat;
00542   FrVect *vect;
00543   int tstart;
00544   int tend;
00545 
00546   /* To find the detector, look for the detector prefix stored as the first
00547    * two characters of the channel name. */
00548   prefix[0] = series->name[0];
00549   prefix[1] = series->name[1];
00550   prefix[2] = 0;
00551 
00552   detector = FrameFindDetector( frame, prefix );
00553   if ( ! detector )
00554   {
00555     XLALPrintError( "XLAL Error - %s: no detector associated with prefix %s in frame\n", func, prefix );
00556     XLAL_ERROR( func, XLAL_EINVAL );
00557   }
00558 
00559   vect = XLALFrVectREAL4TimeSeries( series );
00560   if ( ! vect )
00561     XLAL_ERROR( func, XLAL_EFUNC );
00562 
00563   tstart = series->epoch.gpsSeconds;
00564   tend = (int)ceil( series->epoch.gpsSeconds + 1e-9*series->epoch.gpsNanoSeconds + series->data->length * series->deltaT );
00565   sdat = FrStatDataNew( series->name, comment, representation, tstart, tend, version, vect, NULL );
00566   if ( ! sdat )
00567   {
00568     FrVectFree( vect );
00569     XLAL_ERROR( func, XLAL_EERR );
00570   }
00571 
00572   FrStatDataAdd( detector, sdat );
00573 
00574   return 0;
00575 }
00576 
00577 
00578 REAL4TimeSeries * XLALFrameGetCalFac( LIGOTimeGPS *epoch, const char *channel, FrameH *frame )
00579 {
00580   static const char *func = "XLALFrameGetCalFac";
00581   char prefix[3];
00582   LIGOTimeGPS tmpEpoch;
00583   REAL4TimeSeries *series;
00584   FrStatData *sdat;
00585   char *chan;
00586 
00587   /* To find the detector, look for the detector prefix stored as the first
00588    * two characters of the channel name. */
00589   prefix[0] = channel[0];
00590   prefix[1] = channel[1];
00591   prefix[2] = 0;
00592 
00593   chan = XLALStringDuplicate( channel );
00594   sdat = FrameFindStatData( frame, prefix, chan, epoch->gpsSeconds );
00595   LALFree( chan );
00596   if ( ! sdat || sdat->timeStart > (UINT4)epoch->gpsSeconds || sdat->timeEnd < (UINT4)epoch->gpsSeconds )
00597   {
00598     XLALPrintError( "XLAL Error - %s: no stat data channel %s for GPS time %d in frame\n", func, channel, epoch->gpsSeconds );
00599     XLAL_ERROR_NULL( func, XLAL_EINVAL );
00600   }
00601 
00602   tmpEpoch.gpsSeconds     = sdat->timeStart;
00603   tmpEpoch.gpsNanoSeconds = 0;
00604   series = XLALCreateREAL4TimeSeries( sdat->data->name, &tmpEpoch, 0.0, sdat->data->dx[0], &lalDimensionlessUnit, sdat->data->nData );
00605   if ( ! series )
00606     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00607 
00608   memcpy( series->data->data, sdat->data->data, series->data->length * sizeof( *series->data->data ) );
00609 
00610   return series;
00611 }
00612 
00613 int XLALFrameAddREAL8TimeSeriesProcData( FrameH *frame, REAL8TimeSeries *series )
00614 {
00615         static const char * func = "XLALFrameAddREAL8TimeSeriesProcData";
00616         char rcsinfo[]  = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $" "$Name:  $";
00617         LIGOTimeGPS frameEpoch;
00618         FrProcData *proc;
00619         FrVect *vect;
00620         REAL8 duration;
00621 
00622         duration = series->deltaT * series->data->length;
00623 
00624         vect = XLALFrVectREAL8TimeSeries( series );
00625         if ( ! vect )
00626                 XLAL_ERROR( func, XLAL_EFUNC );
00627 
00628         proc = FrProcDataNewV( frame, vect );
00629         if ( ! proc ) {
00630                 FrVectFree( vect );
00631                 XLAL_ERROR( func, XLAL_EERR );
00632         }
00633 
00634         /* comment is rcs info of this routine */
00635 /*      FrStrCpy( &proc->comment, rcsinfo ); */
00636 
00637         /* time offset: compute this from frame time */
00638         frameEpoch.gpsSeconds     = frame->GTimeS;
00639         frameEpoch.gpsNanoSeconds = frame->GTimeN;
00640         proc->timeOffset = XLALGPSDiff( &series->epoch, &frameEpoch );
00641 
00642         /* remaining metadata */
00643         proc->type    = 1;
00644         proc->subType = 0;
00645         proc->tRange  = duration;
00646         proc->fShift  = 0.0;
00647         proc->phase   = 0.0;
00648         proc->BW      = 0.0;
00649 
00650         return 0;
00651 }
00652 
00653 int XLALFrameAddREAL4TimeSeriesProcData( FrameH *frame, REAL4TimeSeries *series )
00654 {
00655         static const char * func = "XLALFrameAddREAL4TimeSeriesProcData";
00656         char rcsinfo[]  = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $" "$Name:  $";
00657         LIGOTimeGPS frameEpoch;
00658         FrProcData *proc;
00659         FrVect *vect;
00660         REAL8 duration;
00661 
00662         duration = series->deltaT * series->data->length;
00663 
00664         vect = XLALFrVectREAL4TimeSeries( series );
00665         if ( ! vect )
00666                 XLAL_ERROR( func, XLAL_EFUNC );
00667 
00668         proc = FrProcDataNewV( frame, vect );
00669         if ( ! proc ) {
00670                 FrVectFree( vect );
00671                 XLAL_ERROR( func, XLAL_EERR );
00672         }
00673 
00674         /* comment is rcs info of this routine */
00675 /*      FrStrCpy( &proc->comment, rcsinfo ); */
00676 
00677         /* time offset: compute this from frame time */
00678         frameEpoch.gpsSeconds     = frame->GTimeS;
00679         frameEpoch.gpsNanoSeconds = frame->GTimeN;
00680         proc->timeOffset = XLALGPSDiff( &series->epoch, &frameEpoch );
00681 
00682         /* remaining metadata */
00683         proc->type    = 1;
00684         proc->subType = 0;
00685         proc->tRange  = duration;
00686         proc->fShift  = 0.0;
00687         proc->phase   = 0.0;
00688         proc->BW      = 0.0;
00689 
00690         return 0;
00691 }
00692 
00693 
00694 int XLALFrameAddREAL4TimeSeriesSimData( FrameH *frame, REAL4TimeSeries *series )
00695 {
00696         static const char * func = "XLALFrameAddREAL4TimeSeriesSimData";
00697         char rcsinfo[]  = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $" "$Name:  $";
00698   LIGOTimeGPS frameEpoch;
00699         FrSimData *sim;
00700         FrVect *vect;
00701 
00702         vect = XLALFrVectREAL4TimeSeries( series );
00703         if ( ! vect )
00704                 XLAL_ERROR( func, XLAL_EFUNC );
00705 
00706         sim = FrSimDataNew( frame, series->name, series->deltaT, series->data->length, -32 );
00707         if ( ! sim ) {
00708                 FrVectFree( vect );
00709                 XLAL_ERROR( func, XLAL_EERR );
00710         }
00711   FrVectFree( sim->data );
00712   sim->data = vect;
00713 
00714         /* comment is rcs info of this routine */
00715 /*      FrStrCpy( &proc->comment, rcsinfo ); */
00716 
00717   /* time offset: compute this from frame time */
00718   frameEpoch.gpsSeconds     = frame->GTimeS;
00719   frameEpoch.gpsNanoSeconds = frame->GTimeN;
00720   sim->timeOffset = XLALGPSDiff( &series->epoch, &frameEpoch );
00721 
00722   /* remaining metadata */
00723   sim->fShift = 0;
00724   sim->phase  = 0;
00725 
00726         return 0;
00727 }
00728 
00729 int XLALFrameAddREAL4TimeSeriesAdcData( FrameH *frame, REAL4TimeSeries *series )
00730 {
00731         static const char * func = "XLALFrameAddREAL4TimeSeriesAdcData";
00732         char rcsinfo[]  = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $" "$Name:  $";
00733         LIGOTimeGPS frameEpoch;
00734         FrAdcData *adc;
00735         int i;
00736 
00737         adc = FrAdcDataNew( frame, series->name, 1./series->deltaT, series->data->length, -32 );
00738 /*      adc = FrAdcDataNewF (frame, series->name, rcsinfo, 1, 1, -32, 0, 1, "Counts", 1.0/series->deltaT, series->data->length); */
00739         if ( ! adc ) {
00740           XLAL_ERROR( func, XLAL_EERR );
00741         }
00742         
00743         for(i=0; i < (int)series->data->length; i++) {
00744           adc->data->dataF[i] = series->data->data[i];
00745 /*        fprintf(stdout,"%d %f %f\n",i, adc->data->dataF[i], series->data->data[i]); */
00746         }
00747 
00748         FrVectCompress (adc->data, 8, 0);
00749         if (adc->data->compress == 0) FrVectCompress (adc->data, 6, 1);
00750 
00751         return 0;
00752 }
00753 
00754 #if 0
00755 int XLALFrameAddCalFac( FrameH *frame, REAL4TimeSeries *series )
00756 {
00757   static const char *func = "XLALFrameAddCalFac";
00758   char comment[] = "$Id: LALFrameIO.c,v 1.16 2007/06/08 14:41:46 bema Exp $";
00759   LIGOTimeGPS frameEpoch;
00760   FrProcData *proc;
00761   FrVect *vect;
00762 
00763   vect = XLALFrVectREAL4TimeSeries( series );
00764   if ( ! vect )
00765     XLAL_ERROR( func, XLAL_EFUNC );
00766 
00767   proc = FrProcDataNewV( frame, vect );
00768   if ( ! proc )
00769   {
00770     FrVectFree( vect );
00771     XLAL_ERROR( func, XLAL_EERR );
00772   }
00773 
00774   /* comment is rcs id */
00775   FrStrCpy( &proc->comment, comment );
00776 
00777   /* time offset: compute this from frame time */
00778   frameEpoch.gpsSeconds     = frame->GTimeS;
00779   frameEpoch.gpsNanoSeconds = frame->GTimeN;
00780   proc->timeOffset = XLALGPSDiff( &series->epoch, &frameEpoch );
00781 
00782   /* remaining metadata */
00783   proc->type    = 1;
00784   proc->subType = 0;
00785   proc->tRange  = series->data->length * series->deltaT;
00786   proc->fShift  = 0.0;
00787   proc->phase   = 0.0;
00788   proc->BW      = 0.0;
00789 
00790   return 0;
00791 }
00792 
00793 
00794 REAL4TimeSeries * XLALFrameGetCalFac( const char *channel, FrameH *frame )
00795 {
00796   static const char *func = "XLALFrameGetCalFac";
00797   LIGOTimeGPS epoch;
00798   REAL4TimeSeries *series;
00799   FrProcData *proc;
00800   char *chan;
00801 
00802   chan = XLALStringDuplicate( channel );
00803   proc = FrProcDataFind( frame, chan );
00804   LALFree( chan );
00805   if ( ! proc )
00806   {
00807     XLALPrintError( "XLAL Error - %s: no proc data channel %s in frame\n", func, channel );
00808     XLAL_ERROR_NULL( func, XLAL_EINVAL );
00809   }
00810 
00811   epoch.gpsSeconds     = frame->GTimeS;
00812   epoch.gpsNanoSeconds = frame->GTimeN;
00813   XLALGPSAdd( &epoch, proc->timeOffset );
00814 
00815   series = XLALCreateREAL4TimeSeries( proc->data->name, &epoch, proc->fShift, proc->data->dx[0], &lalDimensionlessUnit, proc->data->nData );
00816   if ( ! series )
00817     XLAL_ERROR_NULL( func, XLAL_EFUNC );
00818 
00819   memcpy( series->data->data, proc->data->data, series->data->length * sizeof( *series->data->data ) );
00820 
00821   return series;
00822 }
00823 #endif
00824 
00825 
00826 LALCalData * XLALFrameGetCalData( LIGOTimeGPS *epoch, const char *readoutChannel, FrameH *frame )
00827 {
00828   static const char *func = "XLALFrameGetCalData";
00829   LALCalData *caldata;
00830   char oloopgainName[LALNameLength]     = "Xn:CAL-OLOOP_GAIN";
00831   char cavgainName[LALNameLength]       = "Xn:CAL-CAV_GAIN_";
00832   char responseName[LALNameLength]      = "Xn:CAL-RESPONSE_";
00833   char actuationName[LALNameLength]     = "Xn:CAL-ACTUATION";
00834   char digfltName[LALNameLength]        = "Xn:CAL-DIGFLT_";
00835   char cavfacName[LALNameLength]        = "Xn:CAL-CAV_FAC";
00836   char oloopfacName[