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; }
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); } }
// 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(); }
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);
// Connected to be called when the values of the input data source change void AM3DAdditionAB::onInputSourceValuesChanged(const AMnDIndex& start, const AMnDIndex& end) { cacheUpdateRequired_ = true; AMnDIndex scanStart = start; AMnDIndex scanEnd = end; scanStart.setRank(start.rank()-1); scanEnd.setRank(end.rank()-1); if (scanStart == scanEnd) dirtyIndices_ << start; emitValuesChanged(start, end); }
bool AM3DDeadTimeAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != 3 || indexEnd.rank() != 3) 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() || (unsigned)indexEnd.j() >= (unsigned)axes_.at(1).size || (unsigned)indexStart.j() > (unsigned)indexEnd.j() || (unsigned)indexEnd.k() >= (unsigned)axes_.at(2).size || (unsigned)indexStart.k() > (unsigned)indexEnd.k()) return false; #endif int totalSize = indexStart.totalPointsTo(indexEnd); AMnDIndex start2D = AMnDIndex(indexStart.i(), indexStart.j()); AMnDIndex end2D = AMnDIndex(indexEnd.i(), indexEnd.j()); int icrOcrTotalSize = start2D.totalPointsTo(end2D); QVector<double> data = QVector<double>(totalSize); QVector<double> icr = QVector<double>(icrOcrTotalSize); QVector<double> ocr = QVector<double>(icrOcrTotalSize); spectra_->values(indexStart, indexEnd, data.data()); icr_->values(start2D, end2D, icr.data()); ocr_->values(start2D, end2D, ocr.data()); for (int i = 0, iSize = indexEnd.i()-indexStart.i()+1; i < iSize; i++){ for (int j = 0, jSize = indexEnd.j()-indexStart.j()+1; j < jSize; j++){ // 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.at(i*jSize+j) <= 0 || ocr.at(i*jSize+j) <= 0){ for (int k = 0, kSize = indexEnd.k()-indexStart.k()+1; k < kSize; k++) outputValues[i*jSize*kSize+j*kSize+k] = 0; } else { double factor = icr.at(i*jSize+j)/ocr.at(i*jSize+j); for (int k = 0, kSize = indexEnd.k()-indexStart.k()+1; k < kSize; k++) outputValues[i*jSize*kSize+j*kSize+k] = data.at(i*jSize*kSize+j*kSize+k)*factor; } } } return true; }
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); }
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()); }
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; }
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())); }
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 AMInMemoryDataStore::measurementValuesImplementationRecursive(const AMIMDSMeasurement &measurement, const AMnDIndex &indexStart, const AMnDIndex &indexEnd, const AMnDIndex &fullSize, double **outputValues, int dimension, int cOffset) const { if(dimension == indexStart.rank()-1) { // base case: final dimension for(int i=indexStart.at(dimension); i<=indexEnd.at(dimension); ++i) { *((*outputValues)++) = double(measurement.at(cOffset+i)); } } else { for(int i=indexStart.at(dimension); i<=indexEnd.at(dimension); ++i) { // get product of all higher dimensions: int multiplier = 1; for(int mu=dimension+1; mu<indexStart.rank(); ++mu) multiplier *= fullSize.at(mu); // recurse: measurementValuesImplementationRecursive(measurement, indexStart, indexEnd, fullSize, outputValues, dimension+1, cOffset + i*multiplier); } } }
bool AM3DDeadTimeCorrectionAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != 3 || indexEnd.rank() != 3) return false; if(!isValid()) return false; if((unsigned)indexEnd.i() >= (unsigned)axes_.at(0).size || (unsigned)indexStart.i() > (unsigned)indexEnd.i() || (unsigned)indexEnd.j() >= (unsigned)axes_.at(1).size || (unsigned)indexStart.j() > (unsigned)indexEnd.j() || (unsigned)indexEnd.k() >= (unsigned)axes_.at(2).size || (unsigned)indexStart.k() > (unsigned)indexEnd.k()) return false; int totalSize = indexStart.totalPointsTo(indexEnd); QVector<double> data = QVector<double>(totalSize); QVector<double> icr = QVector<double>(totalSize); QVector<double> ocr = QVector<double>(totalSize); spectra_->values(indexStart, indexEnd, data.data()); icr_->values(indexStart, indexEnd, icr.data()); ocr_->values(indexStart, indexEnd, ocr.data()); for (int i = 0, iSize = indexEnd.i()-indexStart.i()+1; i < iSize; i++){ for (int j = 0, jSize = indexEnd.j()-indexStart.j()+1; j < jSize; j++){ for (int k = 0, kSize = indexEnd.k()-indexStart.k()+1; k < kSize; k++){ int index = i + j*iSize + k*iSize*jSize; // 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.at(index) <= 0 || ocr.at(index) <= 0) outputValues[index] = 0; else outputValues[index] = data.at(index)*icr.at(index)/ocr.at(index); } } } return true; }
bool AMNormalizationAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != rank() || indexEnd.rank() != rank()) return false; if(!isValid()) return false; for (int i = 0, size = indexStart.rank(); i < size; i++) if((unsigned)indexStart.at(i) >= (unsigned)axes_.at(i).size || (unsigned)indexStart.at(i) > (unsigned)indexEnd.at(i)) return false; if (cacheUpdateRequired_) computeCachedValues(); int totalSize = indexStart.totalPointsTo(indexEnd); memcpy(outputValues, cachedData_.constData()+indexStart.flatIndexInArrayOfSize(size()), totalSize*sizeof(double)); return true; }
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; } }
bool REIXSXESImageInterpolationAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != 1 || indexEnd.rank() != 1) return false; // dimension error if(!isValid()) return false; // invalid error // Max x pixel value: int maxI = inputSource_->size(0); if(indexEnd.i() < indexStart.i()) return false; if(indexEnd.i() >= maxI) return false; if(cacheUpdateRequired_) computeCachedValues(); memcpy(outputValues, (cachedData_.constData()+indexStart.i()), (indexEnd.i()-indexStart.i()+1)*sizeof(double)); return true; }
// 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; } }
bool AM1DSummingAB::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 for (int i = 0; i < sources_.size(); i++) if ((unsigned)indexEnd.i() >= (unsigned)axes_.at(0).size) return false; if ((unsigned)indexStart.i() > (unsigned)indexEnd.i()) return false; #endif int totalSize = indexStart.totalPointsTo(indexEnd); QVector<double> data = QVector<double>(totalSize); sources_.at(0)->values(indexStart, indexEnd, data.data()); // Do the first data source separately to initialize the values. for (int i = 0; i < totalSize; i++) outputValues[i] = data.at(i); // Iterate through the rest of the sources. for (int i = 1, count = sources_.size(); i < count; i++){ sources_.at(i)->values(indexStart, indexEnd, data.data()); for (int j = 0; j < totalSize; j++) outputValues[j] += data.at(j); } return true; }
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; }
// 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 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); }
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 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 AM3DAdditionAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != 3) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); for (int i = 0; i < sources_.size(); i++) if (indexes.i() >= sources_.at(i)->size(0) || indexes.j() >= sources_.at(i)->size(1) || indexes.k() >= sources_.at(i)->size(2)) return AMNumber(AMNumber::OutOfBoundsError); if (cacheUpdateRequired_) computeCachedValues(); return cachedData_.at(indexes.i()*size(1)*size(2)+indexes.j()*size(2)+indexes.k()); }
AMNumber AM2DDeadTimeAB::value(const AMnDIndex &indexes) const { if(indexes.rank() != 2) return AMNumber(AMNumber::DimensionError); if(!isValid()) return AMNumber(AMNumber::InvalidError); #ifdef AM_ENABLE_BOUNDS_CHECKING if (indexes.i() >= spectra_->size(0) || indexes.j() >= spectra_->size(1)) return AMNumber(AMNumber::OutOfBoundsError); #endif if ((int)spectra_->value(indexes) == 0 || double(ocr_->value(indexes.i())) == 0) return 0; else return double(icr_->value(indexes.i()))/double(ocr_->value(indexes.i()))*(int)spectra_->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; } }
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); }