All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines
Public Types | Public Member Functions
GeopsyCore::CitySignal Class Reference

Brief description of class still missing. More...

#include <CitySignal.h>

List of all members.

Public Types

enum  RecorderType { Unknown, CityShark1, CityShark2 }

Public Member Functions

int channelNum () const
 CitySignal ()
int duration () const
const DateTimeendTime () const
bool erase (QFile *stream)
bool erased () const
const char * fileIndex () const
QString fileName () const
int frequency () const
int gain () const
bool loadSignals (QFile *stream) const
int maxAllowedAmpl () const
int maxReachedAmpl () const
int nSamples () const
bool readHeader (QFile *stream, int version)
double saturation () const
const DateTimestartTime () const
 ~CitySignal ()

Detailed Description

Brief description of class still missing.

Full description of class still missing


Member Enumeration Documentation

Enumerator:
Unknown 
CityShark1 
CityShark2 

Constructor & Destructor Documentation

Description of constructor still missing

References BLOCK_SIZE, TRACE, and Unknown.

{
  TRACE;
  _frequency=0;
  _duration=0;
  _recorder=Unknown;
  _erased=false;
  _dataOffset=0;
  _currentBlock[BLOCK_SIZE]='\0';
  _fileIndex[3]='\0';
}

Description of destructor still missing

References TRACE.

{
  TRACE;
}

Member Function Documentation

int GeopsyCore::CitySignal::channelNum ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _channelNum;}
int GeopsyCore::CitySignal::duration ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _duration;}
const DateTime& GeopsyCore::CitySignal::endTime ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _endTime;}
bool GeopsyCore::CitySignal::erase ( QFile *  stream)

References BLOCK_SIZE, CityShark1, CityShark2, and TRACE.

Referenced by GeopsyCore::CityScanner::erase().

{
  TRACE;
  if(_erased)
    return true;
  switch (_recorder) {
  case CityShark1:
    stream->seek(_dataOffset - 13 * BLOCK_SIZE);
    if(stream->write( "ERASED   ", BLOCK_SIZE)!=BLOCK_SIZE) return false;
    break;
  case CityShark2:
    stream->seek(_dataOffset - 19 * BLOCK_SIZE);
    if(stream->write( "ERASED2  ", BLOCK_SIZE)!=BLOCK_SIZE) return false;;
    break;
  default:
    return false;
  }
  _erased=true;
  return true;
}
bool GeopsyCore::CitySignal::erased ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _erased;}
const char* GeopsyCore::CitySignal::fileIndex ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _fileIndex;}
QString GeopsyCore::CitySignal::fileName ( ) const [inline]

Referenced by loadSignals(), and readHeader().

{return _startTime.toString("yyMMdd_hhmm")+"."+_fileIndex;}
int GeopsyCore::CitySignal::frequency ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _frequency;}
int GeopsyCore::CitySignal::gain ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _gain;}
bool GeopsyCore::CitySignal::loadSignals ( QFile *  stream) const

Read flash card accessed with stream

References GeopsyCore::GeopsyCoreEngine::currentDB(), QGpCoreTools::DateTime::dateTime(), GeopsyCore::DoubleSignal::deltaT(), GeopsyCore::DoubleSignal::duration(), GeopsyCore::Signal::East, fileName(), QGpCoreTools::DateTime::fractions(), GeopsyCore::geopsyCore, LOCK_SAMPLES, GeopsyCore::Signal::North, QGpCoreTools::DateTime::secondsTo(), GeopsyCore::Signal::setComments(), GeopsyCore::Signal::setComponent(), GeopsyCore::Signal::setCountPerVolt(), GeopsyCore::Signal::setDeltaT(), GeopsyCore::Signal::setFile(), GeopsyCore::Signal::setNSamples(), GeopsyCore::Signal::setNumberInFile(), GeopsyCore::GeopsyCoreEngine::setProgressMaximum(), GeopsyCore::GeopsyCoreEngine::setProgressValue(), GeopsyCore::SignalFile::setSignalName(), GeopsyCore::Signal::setT0(), GeopsyCore::SignalFile::setTimeReference(), GeopsyCore::Signal::setTimeReference(), GeopsyCore::DoubleSignal::setType(), GeopsyCore::GeopsyCoreEngine::showMessage(), GeopsyCore::SignalFileFormat::Temporary, QGpCoreTools::DateTime::toString(), QGpCoreTools::tr(), TRACE, GeopsyCore::Signal::unitPerCount(), UNLOCK_SAMPLES, GeopsyCore::Signal::Vertical, and GeopsyCore::DoubleSignal::Waveform.

Referenced by GeopsyGui::CityLoader::on_loadBut_clicked().

{
  TRACE;
  QDateTime timeReference;
  double t0=_startTime.fractions();
  if(!SignalFile::setTimeReference(t0, timeReference, _startTime.dateTime())) {
    return false;
  }
  QString originalFileName=fileName();
  geopsyCore->showMessage(tr("Reading flash card ..."));
  // Read all channels in one buffer
  int n=_nSamples*_channelNum*3;
  char * data=new char [n];
  stream->seek(_dataOffset);
  // Read buffer with 20 blocks (to display advance)
  int block20Size=n/20;
  int blockRemaining=n%20;
  geopsyCore->setProgressMaximum(20);
  for(int i=0; i<20; i++) {
    geopsyCore->setProgressValue(i);
    stream->read(data+i*block20Size, block20Size);
  }
  if(blockRemaining>0) {
    stream->read(data+20*block20Size, blockRemaining);
  }
  geopsyCore->setProgressValue(20);

  geopsyCore->showMessage(tr( "Loading file %1" ).arg(originalFileName) );
  // Compute gain and conversion factors
  /* Conversion factors initialy transcripted from Frechet
  switch(_frequency) {
  case 50:
    resp=209715; break; // 1048575 /5
  case 100:
    resp=52428.6; break; // 262143 /5
  case 125:
    resp=26214.2; break; // 131071 /5
  case 200:
    resp=13107; break; // 65535 /5
  case 250:
    resp=6553.4; break; // 32767 /5
  default:
    resp=0.0; break;
  }*/ 
  // Conversion factors from new version: 9/4/2004
  // First resp is set to the amplitude range for counts
  // Check that it is correct, there might be 1 to be subtracted (e.g. from -8192 to 8191 or -8191 to 8191?)
  double resp;
  switch (_frequency) {
  case 10:
  case 20:
  case 25:
  case 40:
  case 50:
    resp=1048576.0;
    break;
  case 60:
    resp=524288.0;
    break;
  case 75:
  case 80:
  case 100:
    resp=262144.0;
    break;
  case 125:
  case 150:
    resp=131072.0;
    break;
  case 200:
    resp=65536.0;
    break;
  case 250:
    resp=32768.0;
    break;
  case 300:
    resp=16384.0;
    break;
  case 400:
    resp=8192.0;
    break;
  case 500:
  case 600:
    resp=4096.0;
    break;
  case 750:
    resp=2048.0;
    break;
  case 1000:
    resp=1024.0;
    break;
  default:
    resp=1.0;
    break;
  }
  // Then divided by the peak to peak voltage difference (currently 5 volts)
  resp/=5.0;
  double countPerVolt=resp*_gain;

  // Create a new temporary file
  SignalFile * newFile=new SignalFile(geopsyCore->currentDB(), originalFileName, SignalFileFormat::Temporary);

  geopsyCore->setProgressMaximum(_channelNum-1);
  for(int iSig=0; iSig<_channelNum; iSig++) {
    Signal * newSignal=new Signal(geopsyCore->currentDB());

    newSignal->setFile(newFile);
    newSignal->setNumberInFile(iSig);
    newSignal->setT0(t0);
    newSignal->setDeltaT(1.0/_frequency);
    newSignal->setType(Signal::Waveform);
    int recNum=iSig/3 + 1;
    if(_channelNum > 3)
      SignalFile::setSignalName(newSignal, originalFileName, QString("_%1").arg(recNum), recNum, originalFileName);
    else
      SignalFile::setSignalName(newSignal, originalFileName, "", 1, originalFileName);
    if(iSig % 3==0)
      newSignal->setComponent(Signal::Vertical);
    else if(iSig % 3==1)
      newSignal->setComponent(Signal::North);
    else if(iSig % 3==2)
      newSignal->setComponent(Signal::East);
    newSignal->setTimeReference(timeReference);
    newSignal->setNSamples(_nSamples);
    newSignal->setCountPerVolt(countPerVolt);
    QString cmt;
    cmt+="Station serial number: "+QString::number(_serialNum)+"\n";
    cmt+="Station software version: "+QString::number(_softwareVersion)+"\n";
    cmt+="Starting date: "+_startTime.toString("dd.MM.yyyy")+"\n";
    cmt+="Starting time: "+_startTime.toString("hh:mm:ssz", 3)+"\n";
    cmt+="Ending date: "+_endTime.toString("dd.MM.yyyy")+"\n";
    cmt+="Ending time: "+_endTime.toString("hh:mm:ssz", 3)+"\n";
    cmt+="Latitude : "+QString::number(_latitudeDeg)+" "+QString::number(_latitudeMin)+" N\n";
    cmt+="Longitude: "+QString::number(_longitudeDeg)+" "+QString::number(_longitudeMin)+" E\n";
    cmt+="Altitude : "+QString::number(_altitude)+" m\n";
    cmt+="No. satellites: "+QString::number(_satNum)+"\n";
    cmt+="Gain: "+QString::number(_gain)+"\n";
    // Duration calculated between start and end time does not account for the last sample duration
    cmt+="Time drift: "+QString::number(_startTime.secondsTo(_endTime)-newSignal->duration()+newSignal->deltaT())+" s";
    newSignal->setComments(cmt);
    // Extract samples for this signal from buffer
    LOCK_SAMPLES(double, newSamples, newSignal)
      char * ptr=data+3*iSig;
      int di=_channelNum*3;
      double unitPerCount=newSignal->unitPerCount();
      for(int i=0; i<_nSamples; i++) {
        newSamples[i]=getSample(ptr+i*di)*unitPerCount;
      }
    UNLOCK_SAMPLES(newSignal)
    geopsyCore->setProgressValue(iSig);
  }
  delete [] data;
  return true;
}

Referenced by GeopsyGui::CitySignalItem::data().

{return _maxAllowedAmpl;}

Referenced by GeopsyGui::CitySignalItem::data().

{return _maxReachedAmpl;}
int GeopsyCore::CitySignal::nSamples ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _nSamples;}
bool GeopsyCore::CitySignal::readHeader ( QFile *  stream,
int  version 
)

version is used only to fill signal comments. It does not modify the way samples or header information is extracted. It switches automatically to CityShark 1 or 2 with DEB or DEB2 keyword found at the beginning of every signal.

References QGpCoreTools::DateTime::addSeconds(), BLOCK_SIZE, CityShark2, QGpCoreTools::endl(), fileName(), QGpCoreTools::DateTime::fromString(), QGpCoreTools::tr(), and TRACE.

Referenced by GeopsyCore::CityScanner::normalScan().

{
  TRACE;
  _softwareVersion=version;
  char * ptr;
  qint64 initialOffset=stream->pos();
  char timeBuf[15];
  timeBuf[14]='\0';

  // Signals always start and end with those tags (2 for Cityshark 2):
  //    DEB, DEB2, ERASE or ERASE2
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  if(strncmp(ptr, "DEB", 3)==0) {
    _erased=false;
    setRecorder(ptr+3);
  } else if(strncmp(ptr, "ERASED", 6)==0) {
    _erased=true;
    setRecorder(ptr+6);
  } else {
    // No more signal header found
    App::stream() << tr(" # Warning # No more file header found. Valid data occupy %1 bytes (%2 Mbytes)")
                     .arg(initialOffset).arg((double)initialOffset/(1024.0*1024.0)) << endl;
    return false;
  }

  // Channel number, serial number
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  _serialNum=atoi(getCouple(ptr));
  _channelNum=atoi(ptr);

  // FILE tag
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  if(strcmp(ptr, "FILE")!=0) {
    App::stream() << tr( " # Error # Cannot read keyword FILE, block corrupted, skipping it" ) << endl;
    return false;
  }
  // Start time (MMJJHHmm)
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  strncpy(timeBuf, ptr, 8);
  // Start time (sszzz)
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  strncpy(timeBuf+8, ptr, 2);
  strncpy(timeBuf+10, ".", 1);
  strncpy(timeBuf+11, ptr+2, 3);
  App::freezeStream(true);  // Avoid message from time conversion
  _startTime.fromString(timeBuf, "MMddhhmmssz");
  App::freezeStream(false);
  setCurrentYear(_startTime);
  // File index
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  strncpy(_fileIndex, ptr, 3);

  // PARAM tag
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  if(strcmp(ptr, "PARAM")!=0) {
    App::stream() << tr(" # Error # Cannot read keyword PARAM, block corrupted, skipping it") << endl;
    return false;
  }
  // Frequency, duration
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  _duration=atoi(getCouple(ptr));
  _frequency=atoi(ptr);
  _nSamples=_frequency*_duration*60;
  if(_nSamples <= 0) {
    App::stream() << tr( " # Error # Number of samples is null or negative, block corrupted, skipping it" ) << endl;
    return false;
  }
  // Gain
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  _gain=atoi(ptr);
  // Saturation
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  _saturation=atof(ptr);
  // Maximum allowed amplitude
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  _maxAllowedAmpl=atoi(ptr);
  // Maximum reached amplitude
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  _maxReachedAmpl=atoi(ptr);
  // Test if all blocks have been read correctly
  if(( stream->pos()-initialOffset)!=12*BLOCK_SIZE) {
    if(stream->atEnd()) {
      App::stream() << tr( " # Error # End of file reached (CityShark 1 infos), partial block skipped" ) << endl;
      return false;
    } else {
      App::stream() << tr( " # Error # Block not read correctly due to an unknown error (CityShark 1 infos)" ) << endl;
      return false;
    }
  }
  if(_recorder==CityShark2) {
    // Latitude, Longitude (degrees)
    readBlock(stream);
    ptr=File::stripWhiteSpace(_currentBlock);
    _longitudeDeg=atoi(getCouple( ptr) );
    _latitudeDeg=atoi(ptr);
    // Latitude (minutes)
    readBlock(stream);
    ptr=File::stripWhiteSpace(_currentBlock);
    _latitudeMin=atof(ptr);
    // Longitude (minutes)
    readBlock(stream);
    ptr=File::stripWhiteSpace(_currentBlock);
    _longitudeMin=atof(ptr);
    // Number of satelites, altitude
    readBlock(stream);
    ptr=File::stripWhiteSpace(_currentBlock);
    _altitude=atof(getCouple( ptr) );
    _satNum=atoi(ptr);
    if(_softwareVersion >= 413) { // since station software version 0413
      // Calculate end time from time elapsed from start in milliseconds
      readBlock(stream);
      _endTime=_startTime;
      _endTime.addSeconds(atoi( File::stripWhiteSpace(_currentBlock) )*0.001);
      readBlock(stream); // useless block
    } else {
      // End time (MMJJHHmm)
      readBlock(stream);
      ptr=File::stripWhiteSpace(_currentBlock);
      strncpy(timeBuf, ptr, 8);
      // End time (ss.mmm)
      readBlock(stream);
      ptr=File::stripWhiteSpace(_currentBlock);
      strncpy(timeBuf + 8, ptr, 2);
      strncpy(timeBuf + 10, ".", 1);
      strncpy(timeBuf + 11, ptr+2, 3);
      App::freezeStream(true);
      _endTime.fromString(timeBuf, "MMddhhmmssz");
      App::freezeStream(false);
      setCurrentYear(_endTime);
    }
    // Test if all blocks have been read correctly
    if(( stream->pos() - initialOffset)!=18 * BLOCK_SIZE) {
      if(stream->atEnd()) {
        App::stream() << tr( " # Error # End of file reached (CityShark 2 infos), partial block skipped" ) << endl;
        return false;
      } else {
        App::stream() << tr( " # Error # Block not read correctly due to an unknown error (CityShark 2 infos)" ) << endl;
        return false;
      }
    }
  }
  initialOffset=stream->pos();
  // DATA
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  if(strcmp( ptr, "DATA" )!=0) {
    App::stream() << tr( " # Error # Cannot read keyword DATA, block corrupted, skipping it" ) << endl;
    return false;
  }
  _dataOffset=stream->pos();
  // Skip data block
  int dataLength=_channelNum * _nSamples * 3;
  stream->seek(stream->pos() + dataLength);
  // FIN
  readBlock(stream);
  ptr=File::stripWhiteSpace(_currentBlock);
  if(strcmp( ptr, "FIN" )!=0) {
    App::stream() << tr( " # Warning # Cannot read keyword FIN for file %1, end of trace may be corrupted" ).arg(fileName()) << endl;
  }
  // Test if all blocks have been read correctly
  if(( stream->pos() - initialOffset)!=dataLength + BLOCK_SIZE * 2) {
    if(stream->atEnd()) {
      App::stream() << tr(" ### End of file reached (data part), partial block skipped") << endl;
      return false;
    } else {
      App::stream() << tr(" ### Block not read correctly due to an unknown error (data part)") << endl;
      return false;
    }
  }
  App::stream() << tr("     File %1 ok").arg(fileName()) << endl;
  return true;
}
double GeopsyCore::CitySignal::saturation ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _saturation;}
const DateTime& GeopsyCore::CitySignal::startTime ( ) const [inline]

Referenced by GeopsyGui::CitySignalItem::data().

{return _startTime;}

The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines