void
TSWFilter::Preflight( const SignalProperties& Input,
                            SignalProperties& Output ) const
{
#if 0
  if( Parameter( "YMean" ) != 0 )
    bciout << "YMean should be set to zero for Slow Waves" << endl;
  if( Parameter( "YGain" ) < 300 || Parameter( "YGain" ) > 400 )
    bciout << "YGain should be set to 327.68 for Slow Waves" << endl;
#endif
  Parameter( "FeedbackEnd" );
  State( itiStateName );

  if( Parameter( "SWOutChList" )->NumValues() != Parameter( "SWInChList" )->NumValues() )
    bcierr << "The number of entries in SWOutChList must match that in SWInChList"
           << endl;
  for( int i = 0; i < Parameter( "SWInChList" )->NumValues(); ++i )
    PreflightCondition( Parameter( "SWInChList" )( i ) > 0 && Parameter( "SWInChList" )( i ) <= Input.Channels() );
  for( int i = 0; i < Parameter( "SWOutChList" )->NumValues(); ++i )
    PreflightCondition( Parameter( "SWOutChList" )( i ) > 0 && Parameter( "SWOutChList" )( i ) <= Input.Channels() );
  PreflightCondition( Parameter( "Tc" ).InSampleBlocks() >= 0.0 );
  PreflightCondition( Parameter( "SpatialFilteredChannels" ) == Input.Channels() );
  Output = SignalProperties( Input.Channels(), 1 );
  Output.SetName( "SWFiltered" );
}
void
Normalizer::Preflight( const SignalProperties& Input,
                             SignalProperties& Output ) const
{
  if( Parameter( "NormalizerOffsets" )->NumValues() < Input.Channels() )
    bcierr << "The number of entries in the NormalizerOffsets parameter must match "
           << "the number of input channels"
           << endl;
  if( Parameter( "NormalizerGains" )->NumValues() < Input.Channels() )
    bcierr << "The number of entries in the NormalizerGains parameter must match "
           << "the number of input channels"
           << endl;

  ParamRef Adaptation = Parameter( "Adaptation" );
  if( Adaptation->NumValues() < Input.Channels() )
    bcierr << "The number of entries in the Adaptation parameter must match "
           << "the number of input channels"
           << endl;

  bool adaptation = false;
  for( int channel = 0;
      channel < Input.Channels() && channel < Adaptation->NumValues();
      ++channel )
    adaptation |= ( Adaptation( channel ) != none );

  if( adaptation )
  {
    GenericSignal preflightSignal( Input );

    string UpdateTrigger = Parameter( "UpdateTrigger" );
    if( !UpdateTrigger.empty() )
      Expression( UpdateTrigger ).Evaluate( &preflightSignal );

    ParamRef BufferConditions = Parameter( "BufferConditions" );
    if( BufferConditions->NumColumns() > Input.Channels() )
      bcierr << "The number of columns in the BufferConditions parameter "
             << "may not exceed the number of input channels"
             << endl;

    // Evaluate all expressions to test for validity.
    for( int row = 0; row < BufferConditions->NumRows(); ++row )
      for( int col = 0; col < BufferConditions->NumColumns(); ++col )
        Expression( BufferConditions( row, col ) ).Evaluate( &preflightSignal );

    double bufferSize = Parameter( "BufferLength" ).InSampleBlocks();
    if( bufferSize < 1 )
      bciout << "The BufferLength parameter specifies a zero-sized buffer"
             << endl;
  }
  // Request output signal properties:
  Output = Input;
  // Describe output:
  if( adaptation )
    Output.ValueUnit().SetOffset( 0 ).SetGain( 1 ).SetSymbol( "" )
                      .SetRawMin( -2 ).SetRawMax( 2 );
}
void
ComplexDemodulator::Preflight( const SignalProperties& Input,
                                     SignalProperties& Output ) const
{
  ParamRef DemodulatorFrequencies = Parameter( "DemodulatorFrequencies" );
  bool error = false;
  for( int i = 0; i < DemodulatorFrequencies->NumValues(); ++i )
  {
    double frequency = MeasurementUnits::ReadAsFreq( DemodulatorFrequencies( i ) );
    error |= ( frequency < 0 );
    error |= ( frequency > 0.5 );
  }
  if( error )
    bcierr << "DemodulatorFrequencies must be greater 0 and less than half the "
           << "sampling rate "
           << "(currently " << Parameter( "SamplingRate" ) << "Hz)"
           << endl;
  double FrequencyResolution
    = MeasurementUnits::ReadAsFreq( Parameter( "FrequencyResolution" ) );
  PreflightCondition( FrequencyResolution > 0 );

  // Request output signal properties:
  Output = SignalProperties(
            Input.Channels(),
            DemodulatorFrequencies->NumValues(),
            SignalType::float32
           );
}
示例#4
0
void
ARFilter::Initialize( const SignalProperties& Input,
                      const SignalProperties& /*Output*/ )
{
  int windowLength = MeasurementUnits::ReadAsTime( Parameter( "WindowLength" ) )
                     * Parameter( "SampleBlockSize" );
  mBuffer.clear();
  mBuffer.resize( Input.Channels(), DataVector( 0.0, windowLength ) );

  mOutputType = Parameter( "OutputType" );
  mDetrend = Parameter( "Detrend" );
  mMEMPredictor.SetModelOrder( Parameter( "ModelOrder" ) );

  switch( mOutputType )
  {
    case SpectralAmplitude:
    case SpectralPower:
    {
      float firstBinCenter = MeasurementUnits::ReadAsFreq( Parameter( "FirstBinCenter" ) ),
            lastBinCenter = MeasurementUnits::ReadAsFreq( Parameter( "LastBinCenter" ) ),
            binWidth = MeasurementUnits::ReadAsFreq( Parameter( "BinWidth" ) );
      int outputElements = ::floor( ( lastBinCenter - firstBinCenter + eps ) / binWidth + 1 );
      mTransferSpectrum
        .SetFirstBinCenter( firstBinCenter )
        .SetBinWidth( binWidth )
        .SetNumBins( outputElements )
        .SetEvaluationsPerBin( Parameter( "EvaluationsPerBin" ) );

    } break;

    case ARCoefficients:
      break;
  }
}
void
TFBArteCorrection::Preflight( const SignalProperties& inSignalProperties,
                                    SignalProperties& outSignalProperties ) const
{
  for( int i = 0; i < Parameter( "ArteChList" )->NumValues(); ++i )
  {
    PreflightCondition( Parameter( "ArteChList" )( i ) >= 0 );
    PreflightCondition( Parameter( "ArteChList" )( i ) <= inSignalProperties.Channels() );
  }
  outSignalProperties = inSignalProperties;
  outSignalProperties.SetName( "Artifact Filtered" );
}
示例#6
0
// **************************************************************************
// Function:   Preflight
// Purpose:    Checks parameters for availability and consistency with
//             input signal properties; requests minimally needed properties for
//             the output signal; checks whether resources are available.
// Parameters: Input and output signal properties pointers.
// Returns:    N/A
// **************************************************************************
void FIRFilter::Preflight( const SignalProperties& inSignalProperties,
                                 SignalProperties& outSignalProperties ) const
{
  // Parameter consistency checks: Existence/Ranges and mutual Ranges.
  Parameter( "SamplingRate" );
  PreflightCondition(
    Parameter( "FIRFilteredChannels" ) == Parameter( "FIRFilterKernal" )->NumRows() );
 // PreflightCondition(
 //   Parameter( "SampleBlockSize" ) == Parameter( "FIRFilterKernal" )->GetNumValuesDimension2() );
  PreflightCondition(
     Parameter( "FIRFilterKernal" )->NumRows() <= MAX_M );
  PreflightCondition(
     Parameter( "FIRFilterKernal" )->NumColumns() <= MAX_N );

  // Resource availability checks.
  /* The FIR filter seems not to depend on external resources. */

  // Input signal checks.
  PreflightCondition( Parameter( "FIRFilteredChannels" ) <= inSignalProperties.Channels() );

  // Requested output signal properties.

  if( Parameter( "Integration" ) == 0 )
  {

         PreflightCondition( Parameter( "FIRFilterKernal" )->NumColumns() ==
           ( Parameter( "FIRWindows" ) -1 ) * Parameter( "SampleBlockSize" ) + 1 );

         outSignalProperties = SignalProperties( inSignalProperties.Channels(), Parameter( "SampleBlockSize" ) );
  }
  else
  {
        PreflightCondition( Parameter( "FIRFilterKernal" )->NumColumns() <=
           ( Parameter( "FIRWindows" ) -1 ) * Parameter( "SampleBlockSize" ) + 1 );

         outSignalProperties = SignalProperties( inSignalProperties.Channels(), 1 );
  }
}
void
EDFOutputFormat::Initialize( const SignalProperties& inProperties,
                             const StateVector& inStatevector )
{
  EDFOutputBase::Initialize( inProperties, inStatevector );
  // Adapt marker channels to EDF conventions.
  for( size_t i = inProperties.Channels(); i < Channels().size(); ++i )
  {
    Channels()[ i ].DigitalMinimum = 0;
    Channels()[ i ].DigitalMaximum = static_cast<int>( Channels()[ i ].DigitalMaximum - 1 ) & 0x7fff;
    Channels()[ i ].PhysicalMinimum = Channels()[ i ].DigitalMinimum;
    Channels()[ i ].PhysicalMaximum = Channels()[ i ].DigitalMaximum;
  }
}
示例#8
0
void
EDFFileWriter::Initialize( const SignalProperties& Input,
                           const SignalProperties& Output )
{
    EDFFileWriterBase::Initialize( Input, Output );
    // Adapt marker channels to EDF conventions.
    for( size_t i = Input.Channels(); i < Channels().size(); ++i )
    {
        Channels()[ i ].DigitalMinimum = 0;
        Channels()[ i ].DigitalMaximum = int( Channels()[ i ].DigitalMaximum - 1 ) & 0x7fff;
        Channels()[ i ].PhysicalMinimum = Channels()[ i ].DigitalMinimum;
        Channels()[ i ].PhysicalMaximum = Channels()[ i ].DigitalMaximum;
    }
}
void
CustomFIRFilter::Initialize( const SignalProperties& Input, const SignalProperties& /*Output*/ )
{
  mBuffer.clear();

  ParamRef FIRCoefficients = Parameter( "FIRCoefficients" );
  int filterLength = FIRCoefficients->NumValues();
  mFilter.resize( filterLength, 0.0 );
  for( int sample = 0; sample < filterLength; ++sample )
    mFilter[sample] = FIRCoefficients( sample );

  int bufferLength = filterLength + Input.Elements() - 1;
  mBuffer.resize( Input.Channels(), DataVector( 0.0, bufferLength ) );
}
示例#10
0
void
AlignmentFilter::Initialize( const SignalProperties& Input,
                             const SignalProperties& /*Output*/ )
{
  mPrevSample.clear();
  mWeightPrev.clear();
  mWeightCur.clear();

  // Do we want to align the samples in time ?
  mAlign = ( Parameter( "AlignChannels" ) == 1 );
  if( mAlign )
  {
    mPrevSample.resize( Input.Channels(), 0.0 );
    mWeightPrev.resize( Input.Channels(), 0.0 );
    mWeightCur.resize( Input.Channels(), 1.0 );

    // Calculate weight values for linear interpolation if we do not use the default value.
    if( Parameter( "SourceChTimeOffset" )->NumValues() > 0 )
    {
      for( int i = 0; i < Input.Channels(); ++i ) // get original channel position
      {
        mWeightPrev[ i ] = Parameter( "SourceChTimeOffset" )( i );
        mWeightCur[ i ] = 1.0 - mWeightPrev[ i ];
      }
    }
    // If we do use the default value, assume that all sampled channels are evenly distributed in time.
    else
    {
      float delta = 1.0 / Input.Channels();
      for( int i = 0; i < Input.Channels(); ++i ) // get original channel position
      {
        mWeightPrev[ i ] = delta * i;
        mWeightCur[ i ] = 1.0 - mWeightPrev[ i ];
      }
    }
  }
}
void
BufferedADC::Preflight( const SignalProperties&,
                        SignalProperties& Output ) const
{
    if( Parameter( "SourceBufferSize" ).InSampleBlocks() < 2 )
        bcierr << "The SourceBufferSize parameter must be greater or"
               << " equal 2 sample blocks."
               << endl;
    State( "SourceTime" );
    State( "Running" );
    mAcquisitionProperties = Output;
    this->OnPreflight( mAcquisitionProperties );
    Output = mAcquisitionProperties;
    int numStateChannels = 0;
    for( int ch = 0; ch < Output.Channels(); ++ch )
    {
        bool isStateChannel = ( *Output.ChannelLabels()[ch].c_str() == StateMark );
        if( numStateChannels && !isStateChannel )
            bcierr_ << "State channels must be located at the end of the channel list";
        else if( isStateChannel )
            ++numStateChannels;
    }
    Output.SetChannels( Output.Channels() - numStateChannels );
}
示例#12
0
void
AverageDisplay::Preflight( const SignalProperties& Input, SignalProperties& Output ) const
{
  PreflightCondition( Parameter( "AvgDisplayCh" )->NumColumns() >= 2 );
  for( int i = 0; i < Parameter( "AvgDisplayCh" )->NumRows(); ++i )
    PreflightCondition
    (
      Parameter( "AvgDisplayCh" )( i, 0 ) > 0
      && Parameter( "AvgDisplayCh" )( i, 0 ) <= Input.Channels()
    );
  PreflightCondition( Parameter( "SamplingRate" ) > 0 );
  PreflightCondition( Input.Elements() > 0 );
  State( "TargetCode" );
  Output = Input;
}
void
Normalizer::Initialize( const SignalProperties& Input,
                        const SignalProperties& /*Output*/ )
{
  mOffsets.clear();
  mGains.clear();

  delete mpUpdateTrigger;
  mpUpdateTrigger = NULL;

  mBufferConditions.clear();
  mDataBuffers.clear();

  ParamRef Adaptation = Parameter( "Adaptation" ),
           NormalizerOffsets = Parameter( "NormalizerOffsets" ),
           NormalizerGains = Parameter( "NormalizerGains" );

  mAdaptation.clear();
  mDoAdapt = false;
  for( int channel = 0; channel < Input.Channels(); ++channel )
  {
    mOffsets.push_back( NormalizerOffsets( channel ) );
    mGains.push_back( NormalizerGains( channel ) );
    mAdaptation.push_back( int( Adaptation( channel ) ) );
    mDoAdapt |= ( Adaptation( channel ) != none );
  }
  if( mDoAdapt )
  {
    string UpdateTrigger = Parameter( "UpdateTrigger" );
    if( !UpdateTrigger.empty() )
      mpUpdateTrigger = new Expression( UpdateTrigger );

    size_t bufferSize = static_cast<size_t>( Parameter( "BufferLength" ).InSampleBlocks() * Input.Elements() );
    ParamRef BufferConditions = Parameter( "BufferConditions" );
    mBufferConditions.resize( BufferConditions->NumColumns() );
    for( int col = 0; col < BufferConditions->NumColumns(); ++col )
      for( int row = 0; row < BufferConditions->NumRows(); ++row )
        mBufferConditions[ col ].push_back( Expression( BufferConditions( row, col ) ) );
    mDataBuffers.resize(
      BufferConditions->NumColumns(),
      vector<RingBuffer>( BufferConditions->NumRows(), RingBuffer( bufferSize ) )
    );
    bcidbg << "Allocated " << mDataBuffers.size()
           << "x" << ( mDataBuffers.empty() ? 0 : mDataBuffers[ 0 ].size() )
           << " data buffers of size " << bufferSize << "."
           << endl;
  }
}
示例#14
0
void
SpatialFilter::Preflight( const SignalProperties& Input,
                                SignalProperties& Output ) const
{
  // Parameter/Input consistency.
  if( Input.Channels() != Parameter( "SpatialFilter" )->NumColumns() )
    bcierr << "The input signal's number of channels must match "
           << "the number of columns in the SpatialFilter parameter"
           << endl;

  // Output signal description.
  Output = Input;
  Output.SetChannels( 0 ).SetChannels( Parameter( "SpatialFilter" )->NumRows() );
  if( !Parameter( "SpatialFilter" )->RowLabels().IsTrivial() )
    for( int i = 0; i < Parameter( "SpatialFilter" )->NumRows(); ++i )
      Output.ChannelLabels()[ i ] = Parameter( "SpatialFilter" )->RowLabels()[ i ];
}
示例#15
0
void
FFTFilter::Preflight( const SignalProperties& Input, SignalProperties& Output ) const
{
  for( int i = 0; i < Parameter( "FFTInputChannels" )->NumValues(); ++i )
  {
    int channelIndex = Input.ChannelIndex( Parameter( "FFTInputChannels" )( i ) );
    if( channelIndex < 0 || channelIndex >= Input.Channels() )
      bcierr << "Invalid channel specification \""
             << Parameter( "FFTInputChannels" )( i )
             << "\" in FFTInputChannels, evaluates to "
             << channelIndex
             << endl;
  }

  bool fftRequired = ( ( int )Parameter( "FFTOutputSignal" ) != eInput
                       || ( int )Parameter( "VisualizeFFT" ) )
                     && ( Parameter( "FFTInputChannels" )->NumValues() > 0 );
  if( fftRequired )
  {
    if( mFFT.LibAvailable() )
    {
      FFTLibWrapper preflightFFT;
      int fftWindowLength = Parameter( "SampleBlockSize" )
                            * MeasurementUnits::ReadAsTime( Parameter( "FFTWindowLength" ) );
      if( !preflightFFT.Initialize( fftWindowLength ) )
        bcierr << "Requested parameters are not supported by FFT library" << endl;
    }
    else
      bcierr << "The FFT Filter could not find the " << mFFT.LibName() << " library. "
             << "For legal reasons, this library is not part of the BCI2000 distribution. "
             << "Please download the latest version of fftw3.dll from "
             << "http://www.fftw.org/install/windows.html"
             << endl;
  }

  if( int( Parameter( "VisualizeFFT" ) ) )
  {
    SignalProperties temp;
    DetermineSignalProperties( temp, ePower );
  }

  Output = Input;
  DetermineSignalProperties( Output, Parameter( "FFTOutputSignal" ) );
}
示例#16
0
void
FeedbackDemoTask::OnPreflight( const SignalProperties& Input ) const
{
  Parameter( "WindowHeight" );
  Parameter( "WindowWidth" );
  Parameter( "WindowLeft" );
  Parameter( "WindowTop" );

  if( RGBColor( Parameter( "CursorColor" ) ) == RGBColor::NullColor )
    bcierr << "Invalid RGB value in CursorColor" << endl;

  if( MeasurementUnits::ReadAsTime( Parameter( "FeedbackDuration" ) ) <= 0 )
    bcierr << "FeedbackDuration must be greater 0" << endl;

  if( Input.IsEmpty() )
    bcierr << "Requires at least one entry in control signal" << endl;

  if( Input.Channels() > 1 )
    bciout << "Will ignore additional channels in control signal" << endl;
}
示例#17
0
void
FFTFilter::Preflight( const SignalProperties& Input, SignalProperties& Output ) const
{
  for( int i = 0; i < Parameter( "FFTInputChannels" )->NumValues(); ++i )
  {
    double channelIndex = Input.ChannelIndex( Parameter( "FFTInputChannels" )( i ) );
    if( channelIndex < 0 || channelIndex >= Input.Channels() )
      bcierr << "Invalid channel specification \""
             << Parameter( "FFTInputChannels" )( i )
             << "\" in FFTInputChannels, evaluates to "
             << channelIndex
             << endl;
  }

  bool fftRequired = ( int( Parameter( "FFTOutputSignal" ) ) != eInput
                       || int( Parameter( "VisualizeFFT" ) ) )
                     && ( Parameter( "FFTInputChannels" )->NumValues() > 0 );
  if( fftRequired )
  {
    if( mFFT.LibAvailable() )
    {
      RealFFT preflightFFT;
      int fftWindowLength =
        static_cast<int>( Input.Elements() * Parameter( "FFTWindowLength" ).InSampleBlocks() );
      if( !preflightFFT.Initialize( fftWindowLength ) )
        bcierr << "Requested parameters are not supported by FFT library" << endl;
    }
    else
      bcierr << "The FFT Filter could not find the " << mFFT.LibName() << " library."
             << endl;
  }

  if( int( Parameter( "VisualizeFFT" ) ) || int( Parameter( "FFTOutputSignal" ) ) == ePower )
  {
    SignalProperties temp( Input );
    DetermineSignalProperties( temp, ePower );
  }

  Output = Input;
  DetermineSignalProperties( Output, Parameter( "FFTOutputSignal" ) );
}
示例#18
0
void
AlignmentFilter::Preflight( const SignalProperties& Input,
                                  SignalProperties& Output ) const
{
  // Check the SourceChTimeOffset; only check if we do not use the default value.
  if( Parameter( "SourceChTimeOffset" )->NumValues() > 0 )
  {
    // We need to have as many entries in SourceChTimeOffset as we have digitized channels:
    if( Parameter( "SourceChTimeOffset" )->NumValues() < Input.Channels() )
      bcierr << "If not empty, the number of entries in SourceChTimeOffset must"
             << " match the number of input channels."
             << endl;
    // Each value in SourceChTimeOffset has to be >= 0 and < 1:
    for( int i = 0; i < Parameter( "SourceChTimeOffset" )->NumValues(); ++i )
      if( Parameter( "SourceChTimeOffset" )( i ) < 0
          || Parameter( "SourceChTimeOffset" )( i ) > 1 )
        bcierr << "Values in SourceChTimeOffset must be between 0 and 1." << endl;
  }
  // Requested output signal properties.
  Output = Input;
}
示例#19
0
void
P3TemporalFilter::Preflight( const SignalProperties& Input,
                             SignalProperties& Output ) const
{
    // Required states.
    State( "Running" );
    State( "StimulusCode" );
    State( "StimulusType" );
    OptionalState( "StimulusBegin" );

    float outputSamples = MeasurementUnits::ReadAsTime( Parameter( "EpochLength" ) );
    outputSamples *= Input.Elements();
    outputSamples = ::ceil( outputSamples );
    // Requested output signal properties.
    Output = Input;
    Output.SetChannels( Input.Channels() )
    .SetElements( outputSamples )
    .SetType( SignalType::float32 )
    .ElementUnit().SetRawMin( 0 )
    .SetRawMax( outputSamples - 1 );
}
示例#20
0
void
ComplexDemodulator::Initialize( const SignalProperties& Input,
                                const SignalProperties& Output )
{
  float FrequencyResolution = MeasurementUnits::ReadAsFreq( Parameter( "FrequencyResolution" ) );
  size_t numCoefficients = ::floor( 1.0 / FrequencyResolution ) + 1;
  ParamRef DemodulatorFrequencies = Parameter( "DemodulatorFrequencies" );
  mCoefficients.clear();
  mCoefficients.resize(
    DemodulatorFrequencies->NumValues(),
    vector<complex<double> >( numCoefficients )
  );
  for( int i = 0; i < DemodulatorFrequencies->NumValues(); ++i )
  {
    double freq = MeasurementUnits::ReadAsFreq( DemodulatorFrequencies( i ) );
    for( size_t j = 0; j < numCoefficients; ++j )
      mCoefficients[ i ][ j ] = polar( 0.5 / numCoefficients, freq * j * 2.0 * M_PI );
  }
  mSignalBuffer.clear();
  mSignalBuffer.resize( Input.Channels(), vector<double>( numCoefficients ) );
}
void
RDAClientADC::OnPreflight( SignalProperties& Output ) const
{
  // Resource availability and parameter consistency checks.
  RDA::Connection preflightConnection;
  int numSignalChannels = 0,
      numMarkerChannels = 0,
      numOutputChannels = 0;
  preflightConnection.Open( Parameter( "HostName" ) );
  if( preflightConnection )
  {
    const RDA::Info& info = preflightConnection.Info();
    bool goodOffsets = true,
         goodGains   = true;
    numSignalChannels = info.numChannels;
    string matchMessage = " parameter must match the number of channels"
                          " in the recording software";
    if( Parameter( "AddMarkerChannel" ) != 0 )
    {
      numMarkerChannels = 1;
      matchMessage += " plus one marker channel";
    }
    numOutputChannels = numSignalChannels + numMarkerChannels;
    if( Parameter( "SourceCh" ) != numOutputChannels )
      bcierr << "The SourceCh "
             << matchMessage
             << " (" << numOutputChannels << ") ";

    if( Parameter( "SourceChOffset" )->NumValues() != numOutputChannels )
      bcierr << "The number of values in the SourceChOffset"
             << matchMessage
             << " (" << numOutputChannels << ") ";
    else
      for( int i = 0; i < numSignalChannels; ++i )
        goodOffsets &= ( Parameter( "SourceChOffset" )( i ) == 0 );

    if( !goodOffsets )
      bcierr << "The SourceChOffset values for the first "
             << numSignalChannels << " channels "
             << "must be 0";


    if( Parameter( "SourceChGain" )->NumValues() != numOutputChannels )
      bcierr << "The number of values in the SourceChGain"
             << matchMessage
             << " (" << numOutputChannels << ") ";
    else
      for( int i = 0; i < numSignalChannels; ++i )
      {
        double gain = info.channelResolutions[ i ];
        double prmgain = Parameter( "SourceChGain")( i );
        bool same = ( 1e-3 > ::fabs( prmgain - gain ) / ( gain ? gain : 1.0 ) );
        goodGains &= same;

        if ( !same ) bciout << "The RDA server says the gain of"
                            << " channel " << i+1
                            << " is " << gain
                            << " whereas the corresponding value in the"
                            << " SourceChGain parameter is " << prmgain;
      }

    if( !goodGains )
      bcierr << "The SourceChGain values for the first "
             << numSignalChannels << " channels "
             << "must match the channel resolutions settings "
             << "in the recording software";


    if( info.samplingInterval < Limits( info.samplingInterval ).epsilon() )
      bcierr << "The recording software reports an infinite sampling rate "
             << "-- make sure it shows a running signal in its window";
    else
    {
      double sourceSamplingRate = 1e6 / info.samplingInterval;
      if( Parameter( "SamplingRate" ).InHertz() != sourceSamplingRate )
        bcierr << "The SamplingRate parameter must match "
               << "the setting in the recording software "
               << "(" << sourceSamplingRate << ")";

      // Check whether block sizes are sub-optimal.
      int sampleBlockSize = Parameter( "SampleBlockSize" ),
          sourceBlockSize = static_cast<int>( info.blockDuration / info.samplingInterval );
      if( sampleBlockSize % sourceBlockSize != 0 )
        bcierr << "System block size is " << sampleBlockSize << ", must be equal to "
               << "or a multiple of the RDA server's block size, which is " << sourceBlockSize;
    }
  }

  // Requested output signal properties.
#if RDA_FLOAT
  Output = SignalProperties( numOutputChannels + 1, Parameter( "SampleBlockSize" ), SignalType::float32 );
#else
  bciwarn << "You are using the 16 bit variant of the RDA protocol, which is"
          << " considered unreliable. Switching to float is recommended" << endl;
  Output = SignalProperties( numOutputChannels + 1, Parameter( "SampleBlockSize" ), SignalType::int16 );
#endif // RDA_FLOAT
  Output.ChannelLabels()[Output.Channels() - 1] = StateMark + string( "RDAMarkers" );
}
示例#22
0
void
LinearClassifier::Preflight( const SignalProperties& Input,
                                   SignalProperties& Output ) const
{
  // Determine the classifier matrix format:
  int controlSignalChannels = 0;
  const ParamRef& Classifier = Parameter( "Classifier" );
  if( Classifier->NumColumns() != 4 )
    bcierr << "Classifier parameter must have 4 columns "
           << "(input channel, input element, output channel, weight)"
           << endl;
  else
  {
    for( int row = 0; row < Classifier->NumRows(); ++row )
    {
      if( Classifier( row, 2 ) < 1 )
        bcierr << "Output channels must be positive integers"
               << endl;

      float ch = Input.ChannelIndex( Classifier( row, 0 ) );
      if( ch < 0 )
        bcierr << DescribeEntry( row, 0 )
               << " points to negative input index"
               << endl;
      else if( ::floor( ch ) > Input.Channels() )
        bcierr << "Channel specification in "
               << DescribeEntry( row, 0 )
               << " exceeds number of input channels"
               << endl;
      if( ::fmod( ch, 1.0f ) > 1e-2 )
        bciout << "Channel specification in physical units: "
               << DescribeEntry( row, 0 )
               << " does not exactly meet a single channel"
               << endl;

      float el = Input.ElementIndex( Classifier( row, 1 ) );
      if( el < 0 )
        bcierr << DescribeEntry( row, 1 )
               << " points to negative input index"
               << endl;
      if( ::floor( el ) > Input.Elements() )
        bcierr << "Element (bin) specification in "
               << DescribeEntry( row, 1 )
               << " exceeds number of input elements"
               << endl;
      if( ::fmod( el, 1.0f ) > 1e-2 )
        bciout << "Element (bin) specification in physical units: "
               << DescribeEntry( row, 1 )
               << " does not exactly meet a single element"
               << endl;

      int outputChannel =  Classifier( row, 2 );
      controlSignalChannels = max( controlSignalChannels, outputChannel );
    }
  }
  // Requested output signal properties.
  Output = SignalProperties( controlSignalChannels, 1, Input.Type() );
  // Output description.
  Output.ChannelUnit() = Input.ChannelUnit();
  Output.ValueUnit().SetRawMin( Input.ValueUnit().RawMin() )
                    .SetRawMax( Input.ValueUnit().RawMax() );

  float secsPerBlock = Parameter( "SampleBlockSize" ) / Parameter( "SamplingRate" );
  Output.ElementUnit().SetOffset( 0 ).SetGain( secsPerBlock ).SetSymbol( "s" );
  int visualizationTime = Output.ElementUnit().PhysicalToRaw( "15s" );
  Output.ElementUnit().SetRawMin( 0 ).SetRawMax( visualizationTime - 1 );
}
示例#23
0
void
EDFFileWriterBase::Initialize( const SignalProperties& Input,
                               const SignalProperties& Output )
{
  FileWriterBase::Initialize( Input, Output );
  mChannels.clear();
  // Enter brain signal channels into the channel list.
  int typeCode = GDF::float64::Code;
  switch( Input.Type() )
  {
    case SignalType::int16:
      typeCode = GDF::int16::Code;
      break;
    case SignalType::int32:
      typeCode = GDF::int32::Code;
      break;
    case SignalType::float24:
    case SignalType::float32:
      typeCode = GDF::float32::Code;
      break;
  }
  float digitalMin = Input.Type().Min(),
        digitalMax = Input.Type().Max();
  // GDF 1.25 uses int64 for digital min and max.
  if( digitalMin < numeric_limits<GDF::int64::ValueType>::min() )
    digitalMin = numeric_limits<GDF::int64::ValueType>::min();
  if( digitalMax > numeric_limits<GDF::int64::ValueType>::max() )
    digitalMax = numeric_limits<GDF::int64::ValueType>::max();
  ChannelInfo channel;
  channel.TransducerType = Parameter( "TransducerType" );
  channel.PhysicalDimension = Parameter( "SignalUnit" );
  channel.SamplesPerRecord = Parameter( "SampleBlockSize" );
  channel.DataType = typeCode;
  channel.DigitalMinimum = digitalMin;
  channel.DigitalMaximum = digitalMax;
  for( int i = 0; i < Input.Channels(); ++i )
  {
    if( i < Parameter( "ChannelNames" )->NumValues() )
      channel.Label = Parameter( "ChannelNames" )( i );
    else
    {
      ostringstream oss;
      oss << "Ch" << i + 1;
      channel.Label = oss.str();
    }
    ostringstream filtering;
    if( OptionalParameter( "FilterEnabled", 0 ) == 1 )
      filtering << "HP:" << Parameter( "FilterHighPass" )
                << "LP:" << Parameter( "FilterLowPass" );
    if( OptionalParameter( "NotchEnabled", 0 ) == 1 )
      filtering << "N:"
                << ( Parameter( "NotchHighPass" ) + Parameter( "NotchLowPass" ) ) / 2.0;
    channel.Filtering = filtering.str();
    channel.PhysicalMinimum = Parameter( "SourceChGain" )( i )
                               * ( digitalMin + Parameter( "SourceChOffset" )( i ) );
    channel.PhysicalMaximum = Parameter( "SourceChGain" )( i )
                               * ( digitalMax + Parameter( "SourceChOffset" )( i ) );
    mChannels.push_back( channel );
  }

  // Marker channels to represent states.
  mStateNames.clear();
  ChannelInfo markerChannel;
  markerChannel.TransducerType = "Marker";
  markerChannel.PhysicalDimension = "";
  markerChannel.SamplesPerRecord = 1;
  markerChannel.DataType = GDF::int16::Code;
  for( int i = 0; i < States->Size(); ++i )
  {
    static string statesToIgnore[] = { "Running", "Recording" };
    bool ignoreCurrentState = false;
    class State& state = ( *States )[ i ];
    for( size_t i = 0; i < sizeof( statesToIgnore ) / sizeof( *statesToIgnore ) && !ignoreCurrentState; ++i )
      ignoreCurrentState |= ( statesToIgnore[ i ] == state.Name() );
    if( !ignoreCurrentState )
    {
      double digitalMinimum = -1,
             digitalMaximum = 1 << state.Length();
      markerChannel.Label = state.Name();
      // DigitalMinimum and DigitalMaximum should be outside the range of actually
      // occurring values.
      markerChannel.DigitalMinimum = digitalMinimum;
      markerChannel.DigitalMaximum = digitalMaximum;
      markerChannel.PhysicalMinimum = digitalMinimum;
      markerChannel.PhysicalMaximum = digitalMaximum;
      Channels().push_back( markerChannel );
      mStateNames.push_back( state.Name() );
    }
  }
}
示例#24
0
MatlabEngine::DoubleMatrix::DoubleMatrix( const SignalProperties& inProperties )
    : vector<vector<double> >( 1, vector<double>( 2 ) )
{
    ( *this )[ 0 ][ 0 ] = inProperties.Channels();
    ( *this )[ 0 ][ 1 ] = inProperties.Elements();
}