GeopsyCore/SignalTemplate.h
Go to the documentation of this file.
00001 /***************************************************************************
00002 **
00003 **  This file is part of GeopsyCore.
00004 **
00005 **  This library is free software; you can redistribute it and/or
00006 **  modify it under the terms of the GNU Lesser General Public
00007 **  License as published by the Free Software Foundation; either
00008 **  version 2.1 of the License, or (at your option) any later version.
00009 **
00010 **  This file is distributed in the hope that it will be useful, but WITHOUT
00011 **  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012 **  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00013 **  License for more details.
00014 **
00015 **  You should have received a copy of the GNU Lesser General Public
00016 **  License along with this library; if not, write to the Free Software
00017 **  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018 **
00019 **  See http://www.geopsy.org for more information.
00020 **
00021 **  Created : 2003-11-22
00022 **  Authors :
00023 **    Marc Wathelet
00024 **    Marc Wathelet (ULg, Liège, Belgium)
00025 **    Marc Wathelet (LGIT, Grenoble, France)
00026 **
00027 ***************************************************************************/
00028 
00029 #ifndef SIGNALTEMPLATE_H
00030 #define SIGNALTEMPLATE_H
00031 
00032 #include <QGpCoreTools.h>
00033 
00034 #include "GeopsyCoreEngine.h"
00035 #include "GeopsyCoreDLLExport.h"
00036 
00037 namespace GeopsyCore {
00038 
00039 template <class sampleType> class GEOPSYCORE_EXPORT SignalTemplate : public CacheItem
00040 {
00041 public:
00042   SignalTemplate( );
00043   SignalTemplate(int n);
00044   SignalTemplate(const SignalTemplate<sampleType>& o);
00045   virtual ~SignalTemplate();
00046 
00047   sampleType * lockSamples(char * file, int line);
00048   const sampleType * constLockSamples(char * file, int line) const;
00049   void unlockSamples(char * file, int line) const;
00050 
00051   virtual sampleType * lockSamples();
00052   virtual const sampleType * constLockSamples() const;
00053   virtual inline void unlockSamples() const;
00054   void freeSamples();
00055   // Properties
00056   int nSamples() const {return _nSamples;}
00057   virtual void setNSamples(int n) {ASSERT(!_samples); _nSamples=n;}
00058   // Funtion to perform signal processing
00059   void multiply(const SignalTemplate<sampleType> * sig);
00060   void multiply(sampleType value);
00061   void subtractSignal(const SignalTemplate<sampleType> * sig);
00062   void range(sampleType& min, sampleType& max) const;
00063   sampleType maximum() const;
00064   sampleType average(int startAt, int nSamples) const;
00065   sampleType average2(int startAt, int nSamples) const;
00066   sampleType variance(int startAt, int nSamples) const;
00067   void copySamplesFrom(const SignalTemplate<sampleType> * sig);
00068   bool copySamplesFrom(const SignalTemplate<sampleType> * sig,
00069                         int sigStart, int thisStart, int nToCopy);
00070   int add(const SignalTemplate<sampleType> * sig,
00071            int sigStart=0, int thisStart=0, int nToCopy=-1,
00072            bool checkInvalid=false, sampleType invalidValue=0);
00073   void initValues(sampleType value, int startAt, int nSamples);
00074   int findValue(sampleType value, int from, bool whileNotFound=false) const;
00075 
00076   double dataSizeMb() const {return (double) dataSize()/(1024.0 * 1024.0);}
00077 protected:
00078   int _nSamples;
00079 
00080   // Used only by Signal::lock and DynamicSignal waiting another object pattern for signal
00081   sampleType * samples() const {return _samples;}
00082   void setSamples(sampleType * s) const {_samples=s;}
00083 
00084   void adjustLimits(const SignalTemplate<sampleType> * sig,
00085                      int& sigStart, int& thisStart, int& nToCopy) const;
00086   virtual bool isAllocated() const {return _samples;}
00087   virtual int dataSize() const {return _nSamples * sizeof(sampleType);}
00088 private:
00089   mutable sampleType *_samples;
00090   // Memory management for samples
00091   virtual bool allocate() const;
00092   virtual void free() const;
00093   virtual void save(QDir& d) const;
00094   virtual void load(QDir& d) const;
00095 };
00096 
00100 template <class sampleType>
00101 sampleType * SignalTemplate<sampleType>::lockSamples()
00102 {
00103   lockData();
00104   if(isAllocated() || geopsyCore->cache()->makeAvailable(this)) {
00105     return _samples;
00106   } else {
00107     unlockData();
00108     return 0;
00109   }
00110 }
00111 
00112 
00116 template <class sampleType>
00117 const sampleType * SignalTemplate<sampleType>::constLockSamples() const
00118 {
00119   lockData();
00120   if(isAllocated() || geopsyCore->cache()->makeAvailable(this)) {
00121     return _samples;
00122   } else {
00123     unlockData();
00124     return 0;
00125   }
00126 }
00127 
00131 template <class sampleType>
00132 inline void SignalTemplate<sampleType>::unlockSamples() const
00133 {
00134   unlockData();
00135 }
00136 
00137 #if 0
00138 // Debug only
00139 template <class sampleType>
00140 sampleType * SignalTemplate<sampleType>::lockSamples(char * file, int line)
00141 {
00142   printf( "Lock samples of signal %p at %s:%i\n", this, file, line);
00143   return lockSamples();
00144 }
00145 
00146 template <class sampleType>
00147 const sampleType * SignalTemplate<sampleType>::constLockSamples(char * file, int line) const
00148 {
00149   printf( "Const lock samples of signal %p at %s:%i\n", this, file, line);
00150   return constLockSamples();
00151 }
00152 
00153 template <class sampleType>
00154 void SignalTemplate<sampleType>::unlockSamples(char * file, int line) const
00155 {
00156   unlockSamples();
00157   printf( "Unlock samples of signal %p at %s:%i\n", this, file, line);
00158 }
00159 
00160 #define LOCK_SAMPLES(type,samp,sig) \
00161   type * samp=sig->lockSamples(__FILE__, __LINE__); \
00162   if(samp) {
00163 #define CONST_LOCK_SAMPLES(type,samp,sig) \
00164   const type * samp=sig->constLockSamples(__FILE__, __LINE__); \
00165   if(samp) {
00166 #define UNLOCK_SAMPLES(sig) \
00167     sig->unlockSamples(__FILE__, __LINE__); \
00168   }
00169 #endif
00170 
00171 #define LOCK_SAMPLES(type,samp,sig) \
00172   type * samp=sig->lockSamples(); \
00173   if(samp) {
00174 #define CONST_LOCK_SAMPLES(type,samp,sig) \
00175   const type * samp=sig->constLockSamples(); \
00176   if(samp) {
00177 #define UNLOCK_SAMPLES(sig) \
00178     sig->unlockSamples(); \
00179   }
00180 
00181 template <class sampleType>
00182 SignalTemplate<sampleType>::SignalTemplate( )
00183 {
00184   _samples=0;
00185   _nSamples=0;
00186 }
00187 
00188 template <class sampleType>
00189 SignalTemplate<sampleType>::SignalTemplate(int n)
00190 {
00191   _samples=0;
00192   _nSamples=n;
00193 }
00194 
00195 template <class sampleType>
00196 SignalTemplate<sampleType>::SignalTemplate(const SignalTemplate<sampleType>& o) :
00197     CacheItem(o)
00198 {
00199   _nSamples=o._nSamples;
00200   _samples=0;
00201 }
00202 
00203 template <class sampleType>
00204 SignalTemplate<sampleType>::~SignalTemplate()
00205 {
00206   geopsyCore->cache()->free(this, false);
00207 }
00208 
00209 template <class sampleType>
00210 void SignalTemplate<sampleType>::freeSamples()
00211 {
00212   lockData();
00213   if(isAllocated()) {
00214     geopsyCore->cache()->free(this, false);
00215   }
00216   unlockData();
00217 }
00218 
00219 template <class sampleType>
00220 bool SignalTemplate<sampleType>::allocate() const
00221 {
00222   TRACE;
00223   if( !_samples) {
00224     if(_nSamples<=0) {
00225       // Allocate at least one sample
00226       _samples=new sampleType [ 1 ];
00227       ASSERT(_samples);
00228     } else {
00229       _samples=new sampleType [ _nSamples ];
00230       ASSERT(_samples);
00231     }
00232   }
00233   return true;
00234 }
00235 
00236 template <class sampleType>
00237 void SignalTemplate<sampleType>::free() const
00238 {
00239   TRACE;
00240   if(_samples) {
00241     delete [] _samples;
00242     _samples=0;
00243   }
00244 }
00245 
00249 template <class sampleType>
00250 void SignalTemplate<sampleType>::save(QDir& d) const
00251 {
00252   TRACE;
00253   QFile f(d.absoluteFilePath(swapFileName()) );
00254   if(f.open(QIODevice::WriteOnly) ) {
00255     f.write(( const char * ) _samples, dataSize());
00256   } else App::stream() << QObject::tr( "Cannot save temporary file, check disk space!" ) << endl;
00257 }
00258 
00262 template <class sampleType>
00263 void SignalTemplate<sampleType>::load(QDir& d) const
00264 {
00265   TRACE;
00266   QFile f(d.absoluteFilePath(swapFileName()) );
00267   if(f.open(QIODevice::ReadOnly) ) {
00268     f.read((char *)_samples, dataSize());
00269   } else App::stream() << QObject::tr( "Cannot load temporary file" ) << endl;
00270 }
00271 
00272 template <class sampleType>
00273 void SignalTemplate<sampleType>::multiply(sampleType value)
00274 {
00275   TRACE;
00276   LOCK_SAMPLES(sampleType, thisSamples, this)
00277     for(int i=0; i < _nSamples; i++ ) thisSamples[ i ] *= value;
00278   UNLOCK_SAMPLES(this)
00279 }
00280 
00281 template <class sampleType>
00282 void SignalTemplate<sampleType>::multiply(const SignalTemplate<sampleType> * sig)
00283 {
00284   TRACE;
00285   if(nSamples()!=sig->nSamples()) return;
00286   CacheProcess cp;
00287   cp << this << sig;
00288   LOCK_SAMPLES(sampleType, thisSamples, this)
00289     CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00290       for(int i=0; i < _nSamples; i++ ) thisSamples[ i ] *= sigSamples[ i ];
00291     UNLOCK_SAMPLES(sig)
00292   UNLOCK_SAMPLES(this)
00293 }
00294 
00295 template <class sampleType>
00296 void SignalTemplate<sampleType>::subtractSignal(const SignalTemplate<sampleType> * sig)
00297 {
00298   TRACE;
00299   CacheProcess cp;
00300   cp << this << sig;
00301   LOCK_SAMPLES(sampleType, thisSamples, this)
00302     CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00303       int nSamples=_nSamples;
00304       if(sig->nSamples() < _nSamples) nSamples=sig->nSamples();
00305       for(int i=0; i < nSamples; i++ ) thisSamples[ i ] -= sigSamples[ i ];
00306     UNLOCK_SAMPLES(sig)
00307   UNLOCK_SAMPLES(this)
00308 }
00309 
00310 template <class sampleType>
00311 void SignalTemplate<sampleType>::range(sampleType& min, sampleType& max) const
00312 {
00313   TRACE;
00314   CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00315     min=thisSamples[ 0 ];
00316     max=thisSamples[ 0 ];
00317     for(int i=0; i < _nSamples; i++ ) {
00318       if(thisSamples[ i ] < min) min=thisSamples[ i ];
00319       if(thisSamples[ i ] > max) max=thisSamples[ i ];
00320     }
00321   UNLOCK_SAMPLES(this)
00322 }
00323 
00324 template <class sampleType>
00325 void SignalTemplate<sampleType>::copySamplesFrom(const SignalTemplate<sampleType> * sig)
00326 {
00327   TRACE;
00328   if(sig->_nSamples!=_nSamples) return ;
00329   CacheProcess cp;
00330   cp << this << sig;
00331   LOCK_SAMPLES(sampleType, thisSamples, this)
00332     CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00333       memcpy(thisSamples, sigSamples, _nSamples * sizeof(sampleType) );
00334     UNLOCK_SAMPLES(sig)
00335   UNLOCK_SAMPLES(this)
00336 }
00337 
00338 template <class sampleType>
00339 void SignalTemplate<sampleType>::adjustLimits(const SignalTemplate<sampleType> * sig,
00340                                                   int& sigStart, int& thisStart, int& nToCopy) const
00341 {
00342   TRACE;
00343   // If signal have no common time range return
00344   if(sigStart >= sig->_nSamples ||
00345        thisStart >= _nSamples ||
00346        sigStart + nToCopy < 0 ||
00347        thisStart + nToCopy < 0) {
00348      nToCopy=0;
00349      return;
00350   }
00351   if(sigStart < 0) {
00352     nToCopy += sigStart;
00353     thisStart -= sigStart;
00354     sigStart=0;
00355   }
00356   if(thisStart < 0) {
00357     nToCopy += thisStart;
00358     sigStart -= thisStart;
00359     thisStart=0;
00360   }
00361   if(thisStart + nToCopy >= _nSamples) nToCopy=_nSamples - thisStart;
00362   if(sigStart + nToCopy >= sig->_nSamples) nToCopy=sig->_nSamples - sigStart;
00363 }
00364 
00365 template <class sampleType>
00366 bool SignalTemplate<sampleType>::copySamplesFrom(const SignalTemplate<sampleType> * sig,
00367                                                      int sigStart, int thisStart, int nToCopy)
00368 {
00369   TRACE;
00370   adjustLimits(sig, sigStart, thisStart, nToCopy);
00371   if(nToCopy<=0) return false;
00372   CacheProcess cp;
00373   cp << this << sig;
00374   LOCK_SAMPLES(sampleType, thisSamples, this)
00375     CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00376       memcpy(thisSamples + thisStart, sigSamples + sigStart, nToCopy * sizeof(sampleType) );
00377     UNLOCK_SAMPLES(sig)
00378   UNLOCK_SAMPLES(this)
00379   return true;
00380 }
00381 
00382 template <class sampleType>
00383 int SignalTemplate<sampleType>::add(const SignalTemplate<sampleType> * sig,
00384                                         int sigStart, int thisStart, int nToCopy,
00385                                         bool checkInvalid, sampleType invalidValue)
00386 {
00387   TRACE;
00388   if(nToCopy==-1) nToCopy=nSamples();
00389   adjustLimits(sig, sigStart, thisStart, nToCopy);
00390   if(nToCopy<=0) return 0;
00391   int nCommon=0;
00392   CacheProcess cp;
00393   cp << this << sig;
00394   LOCK_SAMPLES(sampleType, thisSamples, this)
00395     CONST_LOCK_SAMPLES(sampleType, sigSamples, sig)
00396       sampleType * thisPtr=thisSamples + thisStart;
00397       const sampleType * sigPtr=sigSamples + sigStart;
00398       sampleType * endPtr=thisPtr + nToCopy;
00399       if(checkInvalid) {
00400         for( ;thisPtr < endPtr;thisPtr++, sigPtr++ ) {
00401           if(( *thisPtr)==invalidValue) ( *thisPtr)=( *sigPtr);
00402           else {
00403             nCommon++;
00404             ( *thisPtr) += ( *sigPtr);
00405           }
00406         }
00407       } else {
00408         for( ;thisPtr < endPtr;thisPtr++, sigPtr++ )
00409           ( *thisPtr) += ( *sigPtr);
00410       }
00411     UNLOCK_SAMPLES(sig)
00412   UNLOCK_SAMPLES(this)
00413   return nCommon;
00414 }
00415 
00416 template <class sampleType>
00417 sampleType SignalTemplate<sampleType>::maximum() const
00418 {
00419   TRACE;
00420   sampleType max=0;
00421   CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00422     for(int i=0;i < _nSamples;i++ ) {
00423       if(thisSamples[ i ] > 0) {
00424         if(thisSamples[ i ] > max) max=thisSamples[ i ];
00425       } else {
00426         if(thisSamples[ i ] < -max) max=-thisSamples[ i ];
00427       }
00428     }
00429   UNLOCK_SAMPLES(this)
00430   return max;
00431 }
00432 
00433 template <class sampleType>
00434 sampleType SignalTemplate<sampleType>::average(int startAt, int nSamples) const
00435 {
00436   TRACE;
00437   if(startAt >= _nSamples) return 0;
00438   int endAt=startAt + nSamples;
00439   if(endAt > _nSamples) endAt=_nSamples;
00440   if(startAt < 0) startAt=0;
00441   sampleType average=0;
00442   CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00443     for(int i=startAt;i < endAt;i++ ) average += thisSamples[ i ];
00444   UNLOCK_SAMPLES(this)
00445   return average/nSamples;
00446 }
00447 
00448 template <class sampleType>
00449 sampleType SignalTemplate<sampleType>::average2(int startAt, int nSamples) const
00450 {
00451   TRACE;
00452   if(startAt >= _nSamples) return 0;
00453   int endAt=startAt + nSamples;
00454   if(endAt > _nSamples) endAt=_nSamples;
00455   if(startAt < 0) startAt=0;
00456   sampleType average2=0;
00457   CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00458     for(int i=startAt;i < endAt;i++ ) {
00459       average2 += thisSamples[ i ] * thisSamples[ i ];
00460     }
00461   UNLOCK_SAMPLES(this)
00462   return average2/(nSamples-1);
00463 }
00464 
00465 template <class sampleType>
00466 sampleType SignalTemplate<sampleType>::variance(int startAt, int nSamples) const
00467 {
00468   double aver=average(startAt, nSamples);
00469   return average2(startAt, nSamples) - nSamples*aver*aver/(nSamples-1);
00470 }
00471 
00472 template <class sampleType>
00473 void SignalTemplate<sampleType>::initValues(sampleType value, int startAt, int nSamples)
00474 {
00475   TRACE;
00476   if(startAt >= _nSamples) return ;
00477   int endAt=startAt + nSamples;
00478   if(endAt > _nSamples) endAt=_nSamples;
00479   if(startAt < 0) startAt=0;
00480   LOCK_SAMPLES(sampleType, thisSamples, this)
00481     for(int i=startAt;i < endAt;i++ ) thisSamples[ i ]=value;
00482   UNLOCK_SAMPLES(this)
00483 }
00484 
00485 template <class sampleType>
00486 int SignalTemplate<sampleType>::findValue(sampleType value, int from, bool whileNotFound) const
00487 {
00488   TRACE;
00489   int i=-1;
00490   CONST_LOCK_SAMPLES(sampleType, thisSamples, this)
00491     if(whileNotFound) {
00492       for(i=from;i < _nSamples;i++ ) {
00493         if(thisSamples[ i ]!=value) {
00494           break;
00495         }
00496       }
00497     } else {
00498       for(i=from;i < _nSamples;i++ ) {
00499         if(thisSamples[ i ]==value) {
00500           break;
00501         }
00502       }
00503     }
00504   UNLOCK_SAMPLES(this)
00505   return i;
00506 }
00507 
00508 } // namespace GeopsyCore
00509 
00510 #endif // SIGNALTEMPLATE_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines