// If the inputs change size, this will affect the output state. All the inputs need to be the same size for now, otherwise the result is invalid. void AM1DExpressionAB::onInputSourceSizeChanged() { size_ = inputDataSourceAt(0)->size(0); sizesMatch_ = true; for(int i=1; i<inputDataSourceCount(); i++) if(inputDataSourceAt(i)->size(0) != size_) sizesMatch_ = false; // anything that could trigger a change in the output validity must call this reviewState(); }
void AMOrderReductionAB::setInputSources() { if (source_){ disconnect(source_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(source_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(source_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); source_ = 0; } int selectedIndex = indexOfInputSource(selectedName_); if (selectedIndex >= 0){ source_ = inputDataSourceAt(selectedIndex); axes_.clear(); for (int i = 0; i < source_->rank()-1; i++) axes_.append(AMAxisInfo("invalid", 0, "No input data")); updateAxes(); cacheUpdateRequired_ = true; cachedData_ = QVector<double>(size().product()); setDescription(QString("Reduced Order of %1").arg(source_->name())); connect(source_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(source_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(source_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); }
// If the inputs change state, this will affect the output state. If any inputs are InvalidState, then the output is InvalidState. If any of the inputs are in ProcessingState, then the output is ProcessingState. Otherwise, it's ReadyState. void AM1DExpressionAB::onInputSourceStateChanged() { combinedInputState_ = 0; for(int i=0; i<inputDataSourceCount(); i++) combinedInputState_ |= inputDataSourceAt(i)->state(); // anything that could trigger a change in the output validity must call this reviewState(); }
void AMAnalysisBlock::onInputSourceDeleted(void* deletedSource) { // this implementation is just like calling setInputDataSources() with an empty list, except we don't want to call deregisterObserver() on the deleted input source. (In a single-threaded situation, this would be okay, but if the deleted() signal came through a queued signal-slot connection, then that object might already be deleted) for(int i=0; i<inputDataSourceCount(); i++) { AMDataSource* oldSource = inputDataSourceAt(i); if(oldSource != deletedSource) { disconnect(oldSource->signalSource(), SIGNAL(deleted(void*)), this, SLOT(onInputSourceDeleted(void*))); oldSource->deregisterObserver(this); } }
void AMNormalizationAB::setInputSources() { if (data_){ disconnect(data_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(data_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(data_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); data_ = 0; } if (normalizer_){ disconnect(normalizer_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(normalizer_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(normalizer_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); normalizer_ = 0; } int dataIndex = indexOfInputSource(dataName_); int normalizationIndex = indexOfInputSource(normalizationName_); if (dataIndex >= 0 && normalizationIndex >= 0){ data_ = inputDataSourceAt(dataIndex); normalizer_ = inputDataSourceAt(normalizationIndex); canAnalyze_ = true; axes_.clear(); for (int i = 0, size = sources_.at(0)->rank(); i < size; i++) axes_ << sources_.at(0)->axisInfoAt(i); cacheUpdateRequired_ = true; cachedData_ = QVector<double>(size().product()); setDescription(QString("Normalized %1").arg(data_->name())); connect(data_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(data_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(data_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); connect(normalizer_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(normalizer_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(normalizer_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); }
void AM3DNormalizationAB::setInputSources() { if (data_){ disconnect(data_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(data_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(data_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); data_ = 0; } if (normalizer_){ disconnect(normalizer_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(normalizer_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(normalizer_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); normalizer_ = 0; } int dataIndex = indexOfInputSource(dataName_); int normalizationIndex = indexOfInputSource(normalizationName_); if (dataIndex >= 0 && normalizationIndex >= 0){ data_ = inputDataSourceAt(dataIndex); normalizer_ = inputDataSourceAt(normalizationIndex); canAnalyze_ = true; axes_[0] = data_->axisInfoAt(0); axes_[1] = data_->axisInfoAt(1); axes_[2] = data_->axisInfoAt(2); setDescription(QString("Normalized %1 map").arg(data_->name())); connect(data_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(data_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(data_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); connect(normalizer_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(normalizer_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(normalizer_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); }
void AM1DDarkCurrentCorrectionAB::setInputSources() { if (data_){ disconnect(data_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(data_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(data_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); data_ = 0; } if (dwellTime_){ disconnect(dwellTime_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(dwellTime_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(dwellTime_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); dwellTime_ = 0; } int dataIndex = indexOfInputSource(dataName_); int dwellTimeIndex = indexOfInputSource(dwellTimeName_); if (dataIndex >= 0 && dwellTimeIndex >= 0){ data_ = inputDataSourceAt(dataIndex); dwellTime_ = inputDataSourceAt(dwellTimeIndex); canAnalyze_ = true; axes_[0] = data_->axisInfoAt(0); setDescription(QString("Dark Current Corrected %1").arg(data_->name())); connect(data_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(data_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(data_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); connect(dwellTime_->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); connect(dwellTime_->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(dwellTime_->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); }
bool AMAnalysisBlock::setInputDataSources(const QList<AMDataSource*>& dataSources) { // if a non-empty set of data sources has been provided, and they are not acceptable, return false. (An empty list must always be acceptable) if(!dataSources.isEmpty() && !areInputDataSourcesAcceptable(dataSources)) { AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, -98, QString("There was an error connecting the input data sources to this analysis component '%1: %2'. The data sources provided weren't acceptable. This can happen if they have the wrong dimension, don't provide enough data, etc.").arg(name()).arg(description()))); return false; } for(int i=0; i<inputDataSourceCount(); i++) { AMDataSource* oldSource = inputDataSourceAt(i); disconnect(oldSource->signalSource(), SIGNAL(deleted(void*)), this, SLOT(onInputSourceDeleted(void*))); oldSource->deregisterObserver(this); } for(int i=0; i<dataSources.count(); i++) { AMDataSource* newSource = dataSources.at(i); connect(newSource->signalSource(), SIGNAL(deleted(void*)), this, SLOT(onInputSourceDeleted(void*))); dataSources.at(i)->registerObserver(this); } setInputDataSourcesImplementation(dataSources); emit inputSourcesChanged(); return true; }
/* \note Whenever new input sources are set, if the xExpression() is blank/invalid, it is automatically initialized to the axisValue() of the first input source. Otherwise it, like expression(), is left as it was prior to setting the new inputs. Note that if the names of the new inputs are different, the old expressions will both likely become invalid. */ void AM1DExpressionAB::setInputDataSourcesImplementation(const QList<AMDataSource*>& dataSources) { currentlySettingInputSources_ = true; QString oldExpression = expression(); QString oldXExpression = xExpression(); // disconnect signals from the old data sources (if any) for(int i=0; i<inputDataSourceCount(); i++) { disconnect(inputDataSourceAt(i)->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); disconnect(inputDataSourceAt(i)->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); disconnect(inputDataSourceAt(i)->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); } // done with the old sources; these are our new sources now sources_ = dataSources; // clear old parser variables parser_.ClearVar(); xParser_.ClearVar(); allVariables_.clear(); usedVariables_.clear(); // create registry of variables: two for each source for(int i=0; i<sources_.count(); i++) { allVariables_ << AMParserVariable(i, false); // dependent value() variable allVariables_ << AMParserVariable(i, true); // independent axisValue() variable } // install all these variables in the parser. Name comes from the data source name, with ".x" added for the axisValue() version. for(int i=0; i<allVariables_.count(); i++) { QString varName = sources_.at(allVariables_.at(i).sourceIndex)->name(); if(allVariables_.at(i).useAxisValue) varName.append(".x"); try { parser_.DefineVar( varName.toStdString(), &(allVariables_[i].value) ); xParser_.DefineVar( varName.toStdString(), &(allVariables_[i].value) ); } catch(mu::Parser::exception_type& e) { QString explanation = QString("AM1DExpressionAB: Error setting up variables: %1 [%2].").arg(QString::fromStdString(e.GetMsg())).arg(varName); AMErrorMon::report(AMErrorReport(this, AMErrorReport::Alert, e.GetCode(), explanation)); } } // connect new input sources to signal handlers. for(int i=0; i<sources_.count(); i++) { connect(sources_.at(i)->signalSource(), SIGNAL(valuesChanged(AMnDIndex,AMnDIndex)), this, SLOT(onInputSourceValuesChanged(AMnDIndex,AMnDIndex))); /// \todo Optimization: only connect this when this input source is actually used in the expression... connect(inputDataSourceAt(i)->signalSource(), SIGNAL(sizeChanged(int)), this, SLOT(onInputSourceSizeChanged())); connect(inputDataSourceAt(i)->signalSource(), SIGNAL(stateChanged(int)), this, SLOT(onInputSourceStateChanged())); } // initialize the combination of state flags. These will be kept updated by onInputSourceStateChanged() combinedInputState_ = 0; for(int i=0; i<sources_.count(); i++) combinedInputState_ |= sources_.at(i)->state(); // initialize whether the sizes all match. This will be kept updated by onInputSourceSizeChanged() sizesMatch_ = true; size_ = 0; if(!sources_.isEmpty()) { size_ = sources_.at(0)->size(0); for(int i=1; i<sources_.count(); i++) if(sources_.at(i)->size(0) != size_) sizesMatch_ = false; } setExpression(oldExpression); setXExpression(oldXExpression); // both the setExpression() and setXExpression() calls will end by calling reviewState(), which will call setState() appropriately, given the status of the inputs, their sizes, and the expression validity. currentlySettingInputSources_ = false; }
// Retrieve index of an input data source by pointer. If it doesn't exist, returns -1. int AM1DExpressionAB::indexOfInputSource(const AMDataSource* source) const { for(int i=0; i<inputDataSourceCount(); i++) if(inputDataSourceAt(i) == source) return i; return 0; }
/* This might be involve a slow lookup; users should not call repeatedly.*/ int AM1DExpressionAB::indexOfInputSource(const QString& dataSourceName) const { for(int i=0; i<inputDataSourceCount(); i++) if(inputDataSourceAt(i)->name() == dataSourceName) return i; return -1; }