DataBuffer.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 #if 0  /* autodoc block */
00021 
00022 <lalVerbatim file="DataBufferCV">
00023 $Id: DataBuffer.c,v 1.10 2007/06/08 14:41:46 bema Exp $
00024 </lalVerbatim>
00025 
00026 <lalLaTeX>
00027 \subsection{Module \texttt{DataBuffer.c}}
00028 \label{ss:DataBuffer.c}
00029 
00030 Routines for getting overlapping segments of data along with estimated spectra
00031 and calibration information.
00032 
00033 \subsubsection*{Prototypes}
00034 \vspace{0.1in}
00035 \input{DataBufferCP}
00036 \idx{LALCreateDataBuffer()}
00037 \idx{LALDestroyDataBuffer()}
00038 \idx{LALGetData()}
00039 
00040 \subsubsection*{Description}
00041 
00042 The routine \texttt{LALCreateDataBuffer()} sets up a buffer for holding
00043 (overlapping) segments of data.  The parameters for this routine are the
00044 number of spectra to average, the number of points in each segment, the type
00045 of window to use in computing the spectra, the forward real FFT plan, and the
00046 directory path of the frame data.  When the user is finished with a data
00047 buffer, it is to be destroyed using \texttt{LALDestroyDataBuffer()}.
00048 
00049 The routine \texttt{LALGetData()} acquires the next segment of data, its
00050 spectrum, and its response function, as well as sets flags indicating if the
00051 end of the data has been reached, if a new locked segment is being entered,
00052 and if the response function has been changed.  The data in the buffer is
00053 advanced by an amount \texttt{advance} specified as input.
00054 
00055 \subsubsection*{Operating Instructions}
00056 
00057 \begin{verbatim}
00058 const  UINT4                   numSpec     = 8;
00059 const  UINT4                   numPoints   = 1024;
00060 CHAR                           framePath[] = "/data/frames"
00061 static LALStatus               status;
00062 static DataBufferPar           params;
00063 static DataBuffer             *buffer;
00064 static DataSegment             segmnt;
00065 static INT2TimeSeries          dmro;
00066 static REAL4FrequencySeries    spec;
00067 static COMPLEX8FrequencySeries resp;
00068 
00069 params.numSpec    = numSpec;
00070 params.numPoints  = numPoints;
00071 params.windowType = Welch;
00072 params.framePath  = framePath;
00073 LALCreateForwardRealFFTPlan( &status, &params.plan, numPoints, 0 );
00074 LALCreateDataBuffer( &status, &buffer, &params );
00075 LALI2CreateVector( &status, &dmro.data, numPoints );
00076 LALSCreateVector( &status, &spec.data, numPoints/2 + 1 );
00077 LALCCreateVector( &status, &resp.data, numPoints/2 + 1 );
00078 segmnt.data = &dmro;
00079 segmnt.spec = &spec;
00080 segmnt.resp = &resp;
00081 
00082 /* enter infinite loop */
00083 while ( 1 )
00084 {
00085   /* get next data segment, overlapping by 1/4 of a segment */
00086   LALGetData( &status, &segmnt, 3*numPoints/4, buffer );
00087 
00088   /* break out of loop when end of data is reached */
00089   if ( segmnt.endOfData )
00090   {
00091     break;
00092   }
00093 
00094   if ( segmnt.newLock )
00095   {
00096     /* new lock acquired */
00097   }
00098 
00099   if ( segmnt.newCal )
00100   {
00101     /* new calibration data */
00102   }
00103 
00104 }
00105 
00106 LALCDestroyVector( &status, &resp.data );
00107 LALSDestroyVector( &status, &spec.data );
00108 LALI2DestroyVector( &status, &dmro.data );
00109 LALDestroyDataBuffer( &status, &buffer );
00110 LALDestroyRealFFTPlan( &status, &params.plan );
00111 \end{verbatim}
00112 
00113 \subsubsection*{Algorithm}
00114 
00115 \subsubsection*{Uses}
00116 
00117 \subsubsection*{Notes}
00118 \vfill{\footnotesize\input{DataBufferCV}}
00119 
00120 </lalLaTeX>
00121 
00122 #endif /* autodoc block */
00123 
00124 #include <math.h>
00125 #include <lal/LALStdlib.h>
00126 #include <lal/SeqFactories.h>
00127 #include <lal/SpecBuffer.h>
00128 #include <lal/DataBuffer.h>
00129 
00130 NRCSID (DATABUFFERC, "$Id: DataBuffer.c,v 1.10 2007/06/08 14:41:46 bema Exp $");
00131 
00132 static void
00133 FillDataBlock (
00134     LALStatus     *status,
00135     DataBuffer *buffer,
00136     INT4        whichBlock
00137     )
00138 {
00139   DataBlock    *theBlock;
00140 
00141   INITSTATUS (status, "FillDataBlock", DATABUFFERC);
00142   ATTATCHSTATUSPTR (status);
00143 
00144   theBlock = buffer->blockArray + whichBlock;
00145 
00146   /* get next block of locked data */
00147   theBlock->continuous = 1;
00148   theBlock->anomalous  = 0;
00149   theBlock->number     = buffer->blocksFilled++;
00150 
00151   LALGetFrameData (status->statusPtr, theBlock->framedata, buffer->frameData);
00152   CHECKSTATUSPTR (status);
00153   if (buffer->frameData->endOfData) /* end of data */
00154   {
00155     buffer->endOfData    = 1;
00156     theBlock->continuous = 0;
00157     DETATCHSTATUSPTR (status);
00158     RETURN (status);
00159   }
00160   if (buffer->frameData->newCalibration) /* new calib info pending */
00161   {
00162     buffer->newCal = 1;
00163   }
00164 
00165   while (buffer->frameData->newLock)
00166   {
00167     INT2TimeSeries dummy;
00168     INT2Vector     dumvec;
00169     theBlock->continuous    = 0;
00170     theBlock->anomalous     = 1;
00171     buffer->newLock         = 1; /* indicate a new lock is pending */
00172     dumvec.length           = 3*60/theBlock->framedata->deltaT; /* 3 minutes */
00173     dumvec.data             = NULL;                             /* seek mode */
00174     dummy.data              = &dumvec;
00175     LALGetFrameData (status->statusPtr, theBlock->framedata, buffer->frameData);
00176     CHECKSTATUSPTR (status);
00177     if (buffer->frameData->endOfData) /* end of data */
00178     {
00179       buffer->endOfData = 1;
00180       DETATCHSTATUSPTR (status);
00181       RETURN (status);
00182     }
00183     if (buffer->frameData->newCalibration) /* new calib info pending */
00184     {
00185       buffer->newCal = 1;
00186     }
00187   }
00188 
00189   /* if the block is not anomalous, add it to the spectrum buffer */
00190   if (!theBlock->anomalous)
00191   {
00192     LALAddSpectrum (status->statusPtr, buffer->specBuffer, theBlock->framedata);
00193     CHECKSTATUSPTR (status);
00194   }
00195 
00196   /* normal exit */
00197   DETATCHSTATUSPTR (status);
00198   RETURN (status);
00199 }
00200 
00201 
00202 static void
00203 FillAllDataBlocks (
00204     LALStatus     *status,
00205     DataBuffer *buffer
00206     )
00207 {
00208   INT4 block;
00209 
00210   INITSTATUS (status, "FillAllDataBlocks", DATABUFFERC);
00211   ATTATCHSTATUSPTR (status);
00212 
00213   buffer->newLock      = 0; /* new lock no longer pending */
00214 
00215   for (block = 0; block < buffer->blockArraySize; ++block)
00216   {
00217     FillDataBlock (status->statusPtr, buffer, block);
00218     CHECKSTATUSPTR (status);
00219 
00220     if (buffer->endOfData) /* end of data: immediate exit */
00221     {
00222       DETATCHSTATUSPTR (status);
00223       RETURN (status);
00224     }
00225 
00226     if (buffer->newLock) /* need to refill from beginning */
00227     {
00228       block = -1;
00229       buffer->newLock = 0;
00230     }
00231   }
00232 
00233   buffer->nextData     = 0;
00234   buffer->nextBlock    = 0;
00235   buffer->deltaPoints  = 0;
00236   buffer->newLock      = 0; /* new lock no longer pending */
00237   
00238   /* normal exit */
00239   DETATCHSTATUSPTR (status);
00240   RETURN (status);
00241 }
00242 
00243 
00244 /* <lalVerbatim file="DataBufferCP"> */
00245 void
00246 LALCreateDataBuffer (
00247     LALStatus         *status,
00248     DataBuffer    **buffer,
00249     DataBufferPar  *params
00250     )
00251 { /* </lalVerbatim> */
00252   SpectrumBufferPar      specpar;
00253   CreateVectorSequenceIn vseqin;
00254   INT4 block;
00255 
00256   INITSTATUS (status, "LALCreateDataBuffer", DATABUFFERC);
00257   ATTATCHSTATUSPTR (status);
00258 
00259   /* make sure that arguments are not NULL */
00260   ASSERT (buffer, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00261   ASSERT (params, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00262 
00263   /* make sure that the buffer has not already been assigned */
00264   ASSERT (*buffer == NULL, status, DATABUFFERH_ENNUL, DATABUFFERH_MSGENNUL);
00265 
00266   /* assign memory for buffer */
00267   *buffer = (DataBuffer *) LALMalloc (sizeof (DataBuffer));
00268 
00269   /* make sure that the allocation was successful */
00270   ASSERT (*buffer, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00271 
00272   (*buffer)->blockArraySize = params->numSpec;
00273   vseqin.length             = params->numSpec + 1; /* extra swap space */
00274   vseqin.vectorLength       = params->numPoints;
00275 
00276   /* create buffer */
00277   (*buffer)->dataBuffer = NULL;
00278   LALI2CreateVectorSequence (status->statusPtr, &(*buffer)->dataBuffer, &vseqin);
00279   CHECKSTATUSPTR (status);
00280 
00281   /* create block array */
00282   (*buffer)->blockArray = (DataBlock *)
00283     LALMalloc ((*buffer)->blockArraySize*sizeof(DataBlock));
00284   ASSERT ((*buffer)->blockArray, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00285 
00286   for (block = 0; block < (*buffer)->blockArraySize; ++block)
00287   {
00288     DataBlock *thisBlock = (*buffer)->blockArray + block;
00289 
00290     /* allocate memory for the framedata */
00291     thisBlock->framedata = (INT2TimeSeries *)
00292       LALMalloc (sizeof (INT2TimeSeries));
00293     ASSERT (thisBlock->framedata, status,
00294             DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00295     thisBlock->framedata->data = (INT2Vector *)LALMalloc (sizeof(INT2Vector));
00296     ASSERT (thisBlock->framedata->data, status,
00297             DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00298     /* should create units vector ... */
00299     thisBlock->framedata->data->length = params->numPoints;
00300     thisBlock->framedata->data->data   = (*buffer)->dataBuffer->data +
00301       block*params->numPoints;
00302   }
00303 
00304   /* create spectrum buffer */
00305   (*buffer)->specBuffer = NULL;
00306   specpar.numSpec       = params->numSpec;
00307   specpar.numPoints     = params->numPoints;
00308   specpar.windowType    = params->windowType;
00309   specpar.plan          = params->plan;
00310   LALCreateSpectrumBuffer (status->statusPtr, &(*buffer)->specBuffer, &specpar);
00311   CHECKSTATUSPTR (status);
00312 
00313   /* initialize frame data */
00314   (*buffer)->frameData = NULL;
00315   LALInitializeFrameData (
00316       status->statusPtr,
00317       &(*buffer)->frameData,
00318       params->framePath
00319       );
00320   CHECKSTATUSPTR (status);
00321 
00322   (*buffer)->blocksFilled = 0;
00323   (*buffer)->endOfData    = 0;
00324   (*buffer)->newCal       = 0;
00325   (*buffer)->numSent      = 0;
00326   (*buffer)->first        = 1;
00327 
00328   /* fill all data blocks */
00329   FillAllDataBlocks (status->statusPtr, *buffer);
00330   CHECKSTATUSPTR (status);
00331 
00332   /* normal exit */
00333   DETATCHSTATUSPTR (status);
00334   RETURN (status);
00335 }
00336 
00337 
00338 /* <lalVerbatim file="DataBufferCP"> */
00339 void
00340 LALDestroyDataBuffer (
00341     LALStatus      *status,
00342     DataBuffer **buffer
00343     )
00344 { /* </lalVerbatim> */
00345   INT4 block;
00346 
00347   INITSTATUS (status, "LALDestroyDataBuffer", DATABUFFERC);
00348   ATTATCHSTATUSPTR (status);
00349 
00350   /* make sure that arguments are not NULL */
00351   ASSERT (buffer, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00352   ASSERT (*buffer, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00353 
00354   /* finalize frame data */
00355   LALFinalizeFrameData (status->statusPtr, &(*buffer)->frameData);
00356   CHECKSTATUSPTR (status);
00357 
00358   /* destroy spectrum buffer */
00359   LALDestroySpectrumBuffer (status->statusPtr, &(*buffer)->specBuffer);
00360   CHECKSTATUSPTR (status);
00361 
00362   /* destroy data buffer */
00363   LALI2DestroyVectorSequence (status->statusPtr, &(*buffer)->dataBuffer);
00364   CHECKSTATUSPTR (status);
00365 
00366   for (block = 0; block < (*buffer)->blockArraySize; ++block)
00367   {
00368     DataBlock *thisBlock = (*buffer)->blockArray + block;
00369     LALFree (thisBlock->framedata->data);
00370     LALFree (thisBlock->framedata);
00371   }
00372 
00373   LALFree ((*buffer)->blockArray);
00374   LALFree (*buffer);
00375   *buffer = NULL;
00376 
00377   /* normal exit */
00378   DETATCHSTATUSPTR (status);
00379   RETURN (status);
00380 }
00381 
00382 
00383 /* <lalVerbatim file="DataBufferCP"> */
00384 void
00385 LALGetData (
00386     LALStatus      *status,
00387     DataSegment *output,
00388     INT4         advance,
00389     DataBuffer  *buffer
00390     )
00391 { /* </lalVerbatim> */
00392   INT4 numPoints;
00393   INT4 numBlocks;
00394 
00395   INITSTATUS (status, "LALGetData", DATABUFFERC);
00396   ATTATCHSTATUSPTR (status);
00397 
00398   /* make sure that arguments are not NULL */
00399   ASSERT (output, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00400   ASSERT (buffer, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00401   ASSERT (output->data, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00402   ASSERT (output->spec, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00403   ASSERT (output->resp, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00404   ASSERT (output->data->data, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00405   ASSERT (output->spec->data, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00406   ASSERT (output->resp->data, status, DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00407   ASSERT (output->data->data->data, status,
00408           DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00409   ASSERT (output->spec->data->data, status,
00410           DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00411   ASSERT (output->resp->data->data, status,
00412           DATABUFFERH_ENULL, DATABUFFERH_MSGENULL);
00413 
00414   /* check sizes ... */
00415   numPoints = output->data->data->length;
00416   ASSERT (numPoints > 0, status, DATABUFFERH_ESIZE, DATABUFFERH_MSGESIZE);
00417   ASSERT ((INT4)buffer->dataBuffer->vectorLength == numPoints, status,
00418           DATABUFFERH_ESZMM, DATABUFFERH_MSGESZMM);
00419   ASSERT ((INT4)output->resp->data->length == numPoints/2 + 1, status,
00420           DATABUFFERH_ESZMM, DATABUFFERH_MSGESZMM);
00421   ASSERT ((INT4)output->spec->data->length == numPoints/2 + 1, status,
00422           DATABUFFERH_ESZMM, DATABUFFERH_MSGESZMM);
00423 
00424   /* make sure advance is reasonable */
00425   ASSERT (advance > 0, status, DATABUFFERH_ESIZE, DATABUFFERH_MSGESIZE);
00426   ASSERT (advance < numPoints, status, DATABUFFERH_ESIZE, DATABUFFERH_MSGESIZE);
00427 
00428   if (buffer->endOfData) /* no more data: immediate exit */
00429   {
00430     output->endOfData = 1;
00431     DETATCHSTATUSPTR (status);
00432     RETURN (status);
00433   }
00434 
00435   numBlocks = buffer->blockArraySize;
00436 
00437   if (buffer->first)
00438   {
00439     output->newLock = 1;
00440     buffer->first   = 0;
00441   }
00442   else
00443   {
00444     output->newLock = 0;
00445   }
00446   output->newCal = 0;
00447 
00448   /* 
00449    * does next block contain continuous data?  (only need to check if
00450    * buffer->nextData is not at the beginning of a block)
00451    */
00452   if (buffer->nextData%numPoints > 0)
00453   {
00454     INT4       nextBlockNo = (buffer->nextData/numPoints + 1)%numBlocks;
00455     DataBlock *nextBlock   = buffer->blockArray + nextBlockNo;
00456     INT4       continuous  = nextBlock->continuous;
00457 
00458     if (!continuous) /* no: skip into next block */
00459     {
00460       output->newLock = 1;
00461 
00462       /* refill buffer */
00463       FillAllDataBlocks (status->statusPtr, buffer);
00464       CHECKSTATUSPTR (status);
00465 
00466       if (buffer->endOfData)
00467       {
00468         output->endOfData = 1;
00469         DETATCHSTATUSPTR (status);
00470         RETURN (status);
00471       }
00472     }
00473   }
00474 
00475   /* 
00476    * do we need to fill another block of data? (only do so if a
00477    * buffer->newLock flag is not pending)
00478    */
00479   if (buffer->deltaPoints > numBlocks*numPoints/2 && !buffer->newLock)
00480   {
00481     FillDataBlock (status->statusPtr, buffer, buffer->nextBlock);
00482     CHECKSTATUSPTR (status);
00483     if (buffer->endOfData)
00484     {
00485       output->endOfData = 1;
00486       DETATCHSTATUSPTR (status);
00487       RETURN (status);
00488     }
00489 
00490     buffer->deltaPoints -= numPoints;
00491 
00492     if (buffer->nextBlock == 0) /* copy data to end of buffer */
00493     {
00494       INT2 *first = buffer->dataBuffer->data;
00495       INT2 *last  = first + numBlocks*numPoints;
00496       memcpy (last, first, numPoints*sizeof(INT2));
00497     }
00498 
00499     buffer->nextBlock = (buffer->nextBlock + 1)%numBlocks;
00500   }
00501 
00502   /* copy the data to the output vector */
00503   memcpy (
00504       output->data->data->data,
00505       buffer->dataBuffer->data + buffer->nextData,
00506       numPoints*sizeof(INT2)
00507       );
00508 
00509   /* set epoch, etc ... */
00510   {
00511     INT4            blockno = buffer->nextData/numPoints;
00512     INT2TimeSeries *tseries = (buffer->blockArray + blockno)->framedata;
00513     INT8            timeNS;
00514     timeNS  = 1000000000L*(INT8)(tseries->epoch.gpsSeconds);
00515     timeNS += tseries->epoch.gpsNanoSeconds;
00516     timeNS += (INT8)(1e9*(buffer->nextData%numPoints)*tseries->deltaT);
00517     output->data->epoch.gpsSeconds     = (INT4)(timeNS/1000000000L);
00518     output->data->epoch.gpsNanoSeconds = (INT4)(timeNS%1000000000L);
00519     output->data->deltaT = tseries->deltaT;
00520     output->data->f0     = tseries->f0;
00521   }
00522 
00523   /* get average spectrum */
00524   LALAverageSpectrum (status->statusPtr, output->spec, buffer->specBuffer);
00525   CHECKSTATUSPTR (status);
00526 
00527   /* now is the time to deal with new calibration if pending */
00528   if (buffer->newCal && output->newLock)
00529   {
00530     output->newCal = 1;
00531 
00532     /* get new calibration data */
00533     LALGetFrameDataResponse (
00534         status->statusPtr,
00535         output->resp,
00536         buffer->frameData
00537         );
00538     CHECKSTATUSPTR (status);
00539 
00540     buffer->newCal = 0;
00541   }
00542 
00543   output->endOfData = 0;
00544   output->number    = buffer->numSent++;
00545 
00546   /* bookkeeping */
00547   buffer->deltaPoints += advance;
00548   buffer->nextData    += advance;
00549 
00550   /* if next data is in end of buffer, move it back to the beginning */
00551   if (buffer->nextData/numPoints == numBlocks)
00552     buffer->nextData = buffer->nextData%numPoints;
00553 
00554   /* normal exit */
00555   DETATCHSTATUSPTR (status);
00556   RETURN (status);
00557 }

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