AMNumber AMInMemoryDataStore::value(const AMnDIndex &scanIndex, int measurementId, const AMnDIndex &measurementIndex) const { // scan axis index doesn't provide enough / too many dimensions if(scanIndex.rank() != axes_.count()) return AMNumber(AMNumber::DimensionError); if((unsigned)measurementId >= (unsigned)measurements_.count()) return AMNumber(AMNumber::InvalidError); // invalid measurement specified; if(measurementIndex.rank() != measurements_.at(measurementId).rank()) return AMNumber(AMNumber::DimensionError); int flatMeasurementIndex = flatIndexForMeasurement(measurementId, measurementIndex); if(axes_.count() == 0) { #ifdef AM_ENABLE_BOUNDS_CHECKING if(flatMeasurementIndex >= scalarScanPoint_.at(measurementId).size()) return AMNumber(AMNumber::OutOfBoundsError); #endif return scalarScanPoint_.at(measurementId).at(flatMeasurementIndex); } else { // higher dimensions: int flatScanIndex = scanIndex.flatIndexInArrayOfSize(scanSize_); #ifdef AM_ENABLE_BOUNDS_CHECKING if(flatScanIndex >= scanPoints_.count()) return AMNumber(AMNumber::OutOfBoundsError); if(flatMeasurementIndex >= scanPoints_.at(flatScanIndex).at(measurementId).size()) return AMNumber(AMNumber::OutOfBoundsError); #endif return scanPoints_.at(flatScanIndex).at(measurementId).at(flatMeasurementIndex); } }
void AMNormalizationAB::reviewState() { // Are there data sources? if(sources_.isEmpty()){ setState(AMDataSource::InvalidFlag); return; } // Are all the data sources the same size? AMnDIndex firstSize = sources_.first()->size(); for (int i = 0, size = firstSize.rank(); i < size; i++) foreach (AMDataSource *dataSource, sources_) if(firstSize.at(i) != dataSource->size(i)){ setState(AMDataSource::InvalidFlag); return; } // Validity check on all data sources. bool valid = true; for (int i = 0; i < sources_.size(); i++) valid = valid && sources_.at(i)->isValid(); if (valid) setState(0); else setState(AMDataSource::InvalidFlag); }
bool AMInMemoryDataStore::setValue(const AMnDIndex &scanIndex, int measurementId, const AMnDIndex &measurementIndex, const AMNumber &newValue) { if(scanIndex.rank() != axes_.count()) return false; // scan axis index doesn't provide enough / too many dimensions if((unsigned)measurementId >= (unsigned)measurements_.count()) return false; // invalid measurement specified; if(measurementIndex.rank() != measurements_.at(measurementId).rank()) return false; int flatMeasurementIndex = flatIndexForMeasurement(measurementId, measurementIndex); if(axes_.count() == 0) { #ifdef AM_ENABLE_BOUNDS_CHECKING if(flatMeasurementIndex >= scalarScanPoint_.at(measurementId).size()) return false; #endif scalarScanPoint_[measurementId][flatMeasurementIndex] = newValue; } else { // higher dimensions: int flatScanIndex = scanIndex.flatIndexInArrayOfSize(scanSize_); #ifdef AM_ENABLE_BOUNDS_CHECKING if(flatScanIndex >= scanPoints_.count()) return false; if(flatMeasurementIndex >= scanPoints_.at(flatScanIndex).at(measurementId).size()) return false; #endif scanPoints_[flatScanIndex][measurementId][flatMeasurementIndex] = newValue; } emitDataChanged(scanIndex, scanIndex, measurementId); return true; }
bool AMInMemoryDataStore::setValue(const AMnDIndex &scanIndex, int measurementId, const double *inputData) { // scan axis index doesn't provide enough / too many dimensions if(scanIndex.rank() != axes_.count()) return false; if((unsigned)measurementId >= (unsigned)measurements_.count()) return false; // invalid measurement specified; // scalar scan space: if(axes_.count() == 0) { AMIMDSMeasurement& measurement = scalarScanPoint_[measurementId]; for(int i=0,cc=measurement.size(); i<cc; ++i) measurement[i] = inputData[i]; } // higher dimension scan space: else { int flatScanIndex = scanIndex.flatIndexInArrayOfSize(scanSize_); #ifdef AM_ENABLE_BOUNDS_CHECKING if(flatScanIndex >= scanPoints_.count()) return false; #endif AMIMDSMeasurement& measurement = scanPoints_[flatScanIndex][measurementId]; for(int i=0,cc=measurement.size(); i<cc; ++i) measurement[i] = inputData[i]; } emitDataChanged(scanIndex, scanIndex, measurementId); return true; }
AMNumber CLSQE65000Detector::reading(const AMnDIndex &indexes) const{ if( (!isConnected()) || (indexes.rank() != 1) || (indexes.i() > 1024) ) return AMNumber(AMNumber::DimensionError); AMReadOnlyPVControl *tmpControl = qobject_cast<AMReadOnlyPVControl*>(spectrumControl_); return tmpControl->readPV()->lastIntegerValues().at(indexes.i()); }
// Connected to be called when the values of the input data source change void AM2DDeadTimeAB::onInputSourceValuesChanged(const AMnDIndex& start, const AMnDIndex& end) { if (start.rank() == axes_.size() && end.rank() == axes_.size()) emitValuesChanged(start, end); else emitValuesChanged(); }
// Connected to be called when the values of the input data source change void AMDeadTimeAB::onInputSourceValuesChanged(const AMnDIndex& start, const AMnDIndex& end) { if (start.isValid() && end.isValid()) emitValuesChanged(start, end); else emitValuesChanged(); }
AMnDIndex AMDetector::size() const { AMnDIndex index = AMnDIndex(axes_.size(), AMnDIndex::DoNotInit); for (int i = 0, size = index.rank(); i < size; i++) index[i] = axes_.at(i).size; return index; }
bool AMBasicXRFDetectorInfo::setSize(const AMnDIndex &size) { if (size.rank() != 1) return false; channels_ = size.i(); setModified(true); return true; }
void AM3DAdditionAB::computeCachedValues() const { AMnDIndex start = AMnDIndex(); AMnDIndex end = AMnDIndex(); if (dirtyIndices_.isEmpty()){ start = AMnDIndex(rank(), AMnDIndex::DoInit); end = size()-1; } else { start = dirtyIndices_.first(); end = dirtyIndices_.last(); end[rank()-1] = size(rank()-1); } int totalSize = start.totalPointsTo(end); int flatStartIndex = start.flatIndexInArrayOfSize(size()); QVector<double> data = QVector<double>(totalSize); sources_.at(0)->values(start, end, data.data()); // Do the first data source separately to initialize the values. memcpy(cachedData_.data()+flatStartIndex, data.constData(), totalSize*sizeof(double)); cachedData_ = data; // Iterate through the rest of the sources. for (int i = 1, count = sources_.size(); i < count; i++){ sources_.at(i)->values(start, end, data.data()); for (int j = 0; j < totalSize; j++) cachedData_[flatStartIndex+j] += data.at(j); } if (dirtyIndices_.isEmpty()) cachedDataRange_ = AMUtility::rangeFinder(cachedData_); else{ AMRange cachedRange = AMUtility::rangeFinder(cachedData_.mid(flatStartIndex, totalSize)); if (cachedDataRange_.minimum() > cachedRange.minimum()) cachedDataRange_.setMinimum(cachedRange.minimum()); if (cachedDataRange_.maximum() < cachedRange.maximum()) cachedDataRange_.setMaximum(cachedRange.maximum()); } cacheUpdateRequired_ = false; dirtyIndices_.clear(); }
// Returns the dependent value at a (complete) set of axis indexes. Returns an invalid AMNumber if the indexes are insuffient or any are out of range, or if the data is not ready. AMNumber AM1DExpressionAB::value(const AMnDIndex& indexes) const { if(!isValid()) // will catch most invalid situations: non matching sizes, invalid inputs, invalid expressions. return AMNumber(AMNumber::InvalidError); if(indexes.rank() != 1) return AMNumber(AMNumber::DimensionError); #ifdef AM_ENABLE_BOUNDS_CHECKING if(indexes.i() < 0 || indexes.i() >= size_) return AMNumber(AMNumber::OutOfBoundsError); #endif // can we get it directly? Single-value expressions don't require the parser. if(direct_) { // info on which variable to use is contained in directVar_. if(directVar_.useAxisValue) return sources_.at(directVar_.sourceIndex)->axisValue(0, indexes.i()); else return sources_.at(directVar_.sourceIndex)->value(indexes); } // otherwise we need the parser else { // copy the new input data values into parser storage for(int i=0; i<usedVariables_.count(); i++) { AMParserVariable* usedVar = usedVariables_.at(i); if(usedVar->useAxisValue) usedVar->value = sources_.at(usedVar->sourceIndex)->axisValue(0, indexes.i()); else usedVar->value = sources_.at(usedVar->sourceIndex)->value(indexes); } // evaluate using the parser: double rv; try { rv = parser_.Eval(); } catch(mu::Parser::exception_type& e) { QString explanation = QString("AM1DExpressionAB Analysis Block: error evaluating value: %1: '%2'. We found '%3' at position %4.").arg(QString::fromStdString(e.GetMsg()), QString::fromStdString(e.GetExpr()), QString::fromStdString(e.GetToken())).arg(e.GetPos()); AMErrorMon::report(AMErrorReport(this, AMErrorReport::Debug, e.GetCode(), explanation)); return AMNumber(AMNumber::InvalidError); } if (rv == std::numeric_limits<qreal>::infinity() || rv == -std::numeric_limits<qreal>::infinity() || rv == std::numeric_limits<qreal>::quiet_NaN()) return 0; return rv; } }
// Helper function to implement the base-class version of values() when rank > 4. void AMDataSource::valuesImplementationRecursive(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, AMnDIndex current, int dimension, double **outputValues) const { if(dimension == current.rank()-1) { // base case: final dimension for(int i=indexStart.at(dimension); i<=indexEnd.at(dimension); ++i) { current[dimension] = i; *((*outputValues)++) = double(value(current)); } } else { for(int i=indexStart.at(dimension); i<indexEnd.at(dimension); ++i) { current[dimension] = i; valuesImplementationRecursive(indexStart, indexEnd, current, dimension+1, outputValues); } } }
AMNumber AMDeadTimeAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != 1) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); if (indexes.i() >= spectra_->size(0)) return AMNumber(AMNumber::OutOfBoundsError); if ((int)spectra_->value(indexes.i()) == 0) return 0; else return double(icr_->value(AMnDIndex()))/double(ocr_->value(AMnDIndex()))*(int)spectra_->value(indexes.i()); }
AMNumber REIXSXESImageInterpolationAB::value(const AMnDIndex &indexes) const { if((indexes.rank() != 1)) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); if(((unsigned long)indexes.i() >= (unsigned long)axes_.at(0).size)) return AMNumber(AMNumber::OutOfBoundsError); if(cacheUpdateRequired_) computeCachedValues(); return AMNumber(cachedData_.at(indexes.i())); }
AMNumber AM1DInterpolationAB::value(const AMnDIndex& indexes) const{ if(indexes.rank() != 1) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); #ifdef AM_ENABLE_BOUNDS_CHECKING if((unsigned)indexes.i() >= (unsigned)axes_.at(0).size) return AMNumber(AMNumber::OutOfBoundsError); #endif int index = indexes.i(); return inputSource_->value(index); }
bool AM1DInterpolationAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != 1 || indexEnd.rank() != 1) return false; if(!isValid()) return false; #ifdef AM_ENABLE_BOUNDS_CHECKING if((unsigned)indexEnd.i() >= (unsigned)axes_.at(0).size || (unsigned)indexStart.i() > (unsigned)indexEnd.i()) return false; #endif inputSource_->values(indexStart, indexEnd, outputValues); return true; }
AMNumber AMNormalizationAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != rank()) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); for (int i = 0, size = indexes.rank(); i < size; i++) if((unsigned)indexes.at(i) >= (unsigned)axes_.at(i).size) return AMNumber(AMNumber::OutOfBoundsError); if (cacheUpdateRequired_) computeCachedValues(); return cachedData_.at(indexes.flatIndexInArrayOfSize(size())); }
AMNumber AM2DDeadTimeCorrectionAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != 2) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); if (indexes.i() >= spectra_->size(0) || indexes.j() >= spectra_->size(1)) return AMNumber(AMNumber::OutOfBoundsError); if ((int)spectra_->value(indexes) == 0 || double(ocr_->value(indexes)) == 0) return 0; else return double(icr_->value(indexes))/double(ocr_->value(indexes))*(int)spectra_->value(indexes); }
AMNumber AMMockDetector::reading(const AMnDIndex &indexes) const { // We want an "invalid" AMnDIndex for this 0D detector if (indexes.isValid()) { return AMNumber(AMNumber::DimensionError); } return generateRandomNumber(); }
QPair<double, double> AM2DScanView::getCurrentExclusiveDataSourceRange(const AMnDIndex &start, const AMnDIndex &end) const { if (start == end && start.rank() == 2 && end.rank() == 2){ QPair<double, double> range = exclusive2DScanBar_->range(); double val = double(currentExclusiveDataSource_->value(start)); if ((val != -1 && range.first > val) || range.first == -1) range.first = val; if (range.second < val) range.second = val; return range; } else { int totalSize = 0; AMnDIndex startIndex = start; AMnDIndex endIndex = end; if (startIndex.rank() == 0 || endIndex.rank() == 0){ startIndex = AMnDIndex(0, 0); endIndex = AMnDIndex(currentExclusiveDataSource_->size(0)-1, currentExclusiveDataSource_->size(1)-1); totalSize = startIndex.totalPointsTo(endIndex); } else totalSize = start.totalPointsTo(end); if (totalSize > 0){ QVector<double> data(totalSize); currentExclusiveDataSource_->values(startIndex, endIndex, data.data()); double min = data.at(0); double max = data.at(0); foreach (double value, data){ if ((value != -1 && min > value) || min == -1) min = value; if (max < value) max = value; } return qMakePair(min, max); } else return qMakePair(-1.0, -1.0);
AMNumber AMnDDeadTimeAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != rank()) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); #ifdef AM_ENABLE_BOUNDS_CHECKING for (int i = 0, size = axes_.size(); i < size; i++) if (indexes.at(i) >= axes_.at(i).size) return AMNumber(AMNumber::OutOfBoundsError); #endif if ((int)spectrum_->value(indexes) == 0 || double(outputCounts_->value(indexes.i())) == 0) return 0; else return double(inputCounts_->value(indexes.i()))/double(outputCounts_->value(indexes.i()))*(int)spectrum_->value(indexes); }
void AMExternalScanDataSourceAB::copyAxisValues(int dataSourceIndex) { AMDataSource* ds = scan_->dataSourceAt(dataSourceIndex); const AMnDIndex size = ds->size(); axisValues_.clear(); for(int mu=0; mu<size.rank(); mu++) { // for each axis QVector<AMNumber> av; if(!axes_.at(mu).isUniform) { int axisLength = size.at(mu); for(int i=0; i<axisLength; i++) // copy all the axis values av << axisValue(mu, i); } axisValues_ << av; } }
bool AMDetector::reading1D(const AMnDIndex &startIndex, const AMnDIndex &endIndex, double *outputValues) const { if(!checkValid(startIndex, endIndex)) return false; if (endIndex.i() < startIndex.i()) return false; for (int i = startIndex.i(); i <= endIndex.i(); i++) { AMNumber retVal = reading(i); if(!retVal.isValid()) return false; outputValues[i] = double(retVal); } return true; }
AMNumber AMScalerTimeControlDetector::reading(const AMnDIndex &indexes) const { if(!isConnected()) return AMNumber(AMNumber::Null); // We want an "invalid" AMnDIndex for this 0D detector if(indexes.isValid()) return AMNumber(AMNumber::DimensionError); return control_->value()/1000; }
void AMInMemoryDataStore::valuesImplementationRecursive(const AMnDIndex &siStart, const AMnDIndex &siEnd, int measurementId, const AMnDIndex &miStart, const AMnDIndex &miEnd, double **outputValues, int scanDimension, int scanSpaceOffset, const AMnDIndex &fullSize, int measurementSpaceSize) const { if(scanDimension == axes_.count()-1) { // base case: last (final) dimension for(int i=siStart.at(scanDimension); i<=siEnd.at(scanDimension); ++i) { measurementValues(scanPoints_.at(scanSpaceOffset+i).at(measurementId), fullSize, miStart, miEnd, *outputValues); *outputValues += measurementSpaceSize; } } else { for(int i=siStart.at(scanDimension); i<=siEnd.at(scanDimension); ++i) { // get product of all higher scan dimensions: int multiplier = 1; for(int mu=scanDimension+1; mu<siStart.rank(); ++mu) multiplier *= scanSize_.at(mu); // recurse: valuesImplementationRecursive(siStart, siEnd, measurementId, miStart, miEnd, outputValues, scanDimension+1, scanSpaceOffset + i*multiplier, fullSize, measurementSpaceSize); } } }
AMNumber AM1DSummingAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != 1) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); #ifdef AM_ENABLE_BOUNDS_CHECKING for (int i = 0; i < sources_.size(); i++) if (indexes.i() >= sources_.at(i)->size(0)) return AMNumber(AMNumber::OutOfBoundsError); #endif double val = 0; for (int i = 0; i < sources_.size(); i++) val += (double)sources_.at(i)->value(indexes.i()); return val; }
bool AMDetector::readingND(const AMnDIndex &startIndex, const AMnDIndex &endIndex, double *outputValues) const { switch(startIndex.rank()) { case 0: return reading0D(startIndex, endIndex, outputValues); case 1: return reading1D(startIndex, endIndex, outputValues); case 2: return reading2D(startIndex, endIndex, outputValues); default: return false; } }
AMNumber AM1DRunningAverageFilterAB::value(const AMnDIndex& indexes) const{ if(indexes.rank() != 1) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); #ifdef AM_ENABLE_BOUNDS_CHECKING if((unsigned)indexes.i() >= (unsigned)axes_.at(0).size) return AMNumber(AMNumber::OutOfBoundsError); #endif int index = indexes.i(); double runningAverage = 0; int numAvgPoints = 1; runningAverage += (double)inputSource_->value(index); for(int x = 1; x <= (filterSize_-1)/2; x++){ if( (index-x) >= 0 ){ runningAverage += (double)inputSource_->value(index-x); numAvgPoints++; } if( (index+x) < axes_.at(0).size ){ runningAverage += (double)inputSource_->value(index+x); numAvgPoints++; } } return runningAverage/((double)numAvgPoints); }
bool AMDeadTimeAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != 1 || indexEnd.rank() != 1) return false; if(!isValid()) return false; if((unsigned)indexEnd.i() >= (unsigned)axes_.at(0).size || (unsigned)indexStart.i() > (unsigned)indexEnd.i()) return false; int totalSize = indexStart.totalPointsTo(indexEnd); QVector<double> data = QVector<double>(totalSize); spectra_->values(indexStart, indexEnd, data.data()); double icr = double(icr_->value(AMnDIndex())); double ocr = double(ocr_->value(AMnDIndex())); // If ocr is equal to 0 then that will cause division by zero. Since these are both count rates, they should both be greater than zero. if (icr <= 0 || ocr <= 0){ for (int i = 0; i < totalSize; i++) outputValues[i] = 0; } else { double factor = icr/ocr; for (int i = 0; i < totalSize; i++) outputValues[i] = data.at(i)*factor; } return true; }
void AMAdditionAB::computeCachedValues() const { AMnDIndex start = AMnDIndex(rank(), AMnDIndex::DoInit, 0); AMnDIndex end = size()-1; int totalSize = start.totalPointsTo(end); QVector<double> data = QVector<double>(totalSize); sources_.at(0)->values(start, end, data.data()); // Do the first data source separately to initialize the values. cachedData_ = data; // Iterate through the rest of the sources. for (int i = 1, count = sources_.size(); i < count; i++) { sources_.at(i)->values(start, end, data.data()); for (int j = 0; j < totalSize; j++) cachedData_[j] += data.at(j); } cachedDataRange_ = AMUtility::rangeFinder(cachedData_); cacheUpdateRequired_ = false; }