// 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); } } }
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); }
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); } } }
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); } } }
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; }
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 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; } }
/* This base-class implementation simply calls value() repeatedly and should absolutely be re-implemented for better performance. */ bool AMDataSource::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { static bool programmerWarningIssued = false; if(!programmerWarningIssued) { AMErrorMon::debug(0, AMDATASOURCE_VALUES_BASE_IMPLEMENTATION_CALLED, QString("AMDataSource: Warning: Data source '%1' is using the base implementation of AMDataSource::values(), which is very inefficient. Re-implement values() to improve performance. (This warning will only be given once.)").arg(name())); programmerWarningIssued = true; // one problem with this warning method: if multiple classes have this problem, it will only be given once, and the subsequent classes will not be named. } int _rank = rank(); if(indexStart.rank() != _rank || indexEnd.rank() != _rank) return false; #ifdef AM_ENABLE_BOUNDS_CHECKING for(int mu=0; mu<_rank; ++mu) { if(indexEnd.at(mu) >= size(mu)) return false; if(indexEnd.at(mu) < indexStart.at(mu)) return false; } #endif switch(_rank) { case 0: *outputValues = double(value(indexStart)); break; case 1: { for(int i=indexStart.i(); i<=indexEnd.i(); ++i) *(outputValues++) = double(value(AMnDIndex(i))); break; } case 2: { for(int i=indexStart.i(); i<=indexEnd.i(); ++i) for(int j=indexStart.j(); j<=indexEnd.j(); ++j) *(outputValues++) = double(value(AMnDIndex(i,j))); break; } case 3: { for(int i=indexStart.i(); i<=indexEnd.i(); ++i) for(int j=indexStart.j(); j<=indexEnd.j(); ++j) for(int k=indexStart.k(); k<=indexEnd.k(); ++k) *(outputValues++) = double(value(AMnDIndex(i,j,k))); break; } case 4: { for(int i=indexStart.i(); i<=indexEnd.i(); ++i) for(int j=indexStart.j(); j<=indexEnd.j(); ++j) for(int k=indexStart.k(); k<=indexEnd.k(); ++k) for(int l=indexStart.l(); l<=indexEnd.l(); ++l) *(outputValues++) = double(value(AMnDIndex(i,j,k,l))); break; } default: { valuesImplementationRecursive(indexStart, indexEnd, AMnDIndex(_rank, AMnDIndex::DoNotInit), 0, &outputValues); break; } } return true; }
bool AMnDDeadTimeAB::values(const AMnDIndex &indexStart, const AMnDIndex &indexEnd, double *outputValues) const { if(indexStart.rank() != rank() || indexEnd.rank() != indexStart.rank()) return false; if(!isValid()) return false; #ifdef AM_ENABLE_BOUNDS_CHECKING for (int i = 0, size = axes_.size(); i < size; i++) if (indexEnd.at(i) >= axes_.at(i).size || (unsigned)indexStart.at(i) > (unsigned)indexEnd.at(i)) return false; #endif switch(rank()){ case 0: // Can't happen. break; case 1:{ int totalSize = indexStart.totalPointsTo(indexEnd); double inputCounts = inputCounts_->value(AMnDIndex()); double outputCounts = outputCounts_->value(AMnDIndex()); if (outputCounts == 0){ QVector<double> data = QVector<double>(totalSize, 0); outputValues = data.data(); } else { double scalingFactor = qAbs(inputCounts/outputCounts); QVector<double> data = QVector<double>(totalSize); spectrum_->values(indexStart, indexEnd, data.data()); for (int i = 0, size = data.size(); i < size; i++) outputValues[i] = data.at(i)*scalingFactor; } break; } case 2:{ int totalSize = indexStart.totalPointsTo(indexEnd); int crTotalSize = AMnDIndex(indexStart.i()).totalPointsTo(AMnDIndex(indexEnd.i())); QVector<double> data = QVector<double>(totalSize); QVector<double> inputCounts = QVector<double>(crTotalSize); QVector<double> outputCounts = QVector<double>(crTotalSize); spectrum_->values(indexStart, indexEnd, data.data()); inputCounts_->values(indexStart.i(), indexEnd.i(), inputCounts.data()); outputCounts_->values(indexStart.i(), indexEnd.i(), outputCounts.data()); for (int i = 0, iSize = indexEnd.i() - indexStart.i()+1; i < iSize; i++){ // If outputCounts is equal to 0 then that will cause division by zero. if (outputCounts.at(i) <= 0){ for (int j = 0, jSize = indexEnd.j()-indexStart.j()+1; j < jSize; j++) outputValues[i*jSize+j] = 0; } else { double factor = qAbs(inputCounts.at(i)/outputCounts.at(i)); for (int j = 0, jSize = indexEnd.j()-indexStart.j()+1; j < jSize; j++) outputValues[i*jSize+j] = data.at(i*jSize+j)*factor; } } break; } case 3:{ 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> inputCounts = QVector<double>(icrOcrTotalSize); QVector<double> outputCounts = QVector<double>(icrOcrTotalSize); spectrum_->values(indexStart, indexEnd, data.data()); inputCounts_->values(start2D, end2D, inputCounts.data()); outputCounts_->values(start2D, end2D, outputCounts.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++){ int scaleFactorIndex = i*jSize+j; // If outputCounts is equal to 0 then that will cause division by zero. if (outputCounts.at(scaleFactorIndex) <= 0){ for (int k = 0, kSize = indexEnd.k()-indexStart.k()+1; k < kSize; k++) outputValues[i*jSize*kSize+j*kSize+k] = 0; } else { double scaleFactor = qAbs(inputCounts.at(scaleFactorIndex)/outputCounts.at(scaleFactorIndex)); for (int k = 0, kSize = indexEnd.k()-indexStart.k()+1; k < kSize; k++){ int spectrumIndex = i*jSize*kSize+j*kSize+k; outputValues[spectrumIndex] = data.at(spectrumIndex)*scaleFactor; } } } } break; } case 4:{ int totalSize = indexStart.totalPointsTo(indexEnd); AMnDIndex start3D = AMnDIndex(indexStart.i(), indexStart.j()); AMnDIndex end3D = AMnDIndex(indexEnd.i(), indexEnd.j()); int icrOcrTotalSize = start3D.totalPointsTo(end3D); QVector<double> data = QVector<double>(totalSize); QVector<double> inputCounts = QVector<double>(icrOcrTotalSize); QVector<double> outputCounts = QVector<double>(icrOcrTotalSize); spectrum_->values(indexStart, indexEnd, data.data()); inputCounts_->values(start3D, end3D, inputCounts.data()); outputCounts_->values(start3D, end3D, outputCounts.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 scaleFactorIndex = i*jSize*kSize+j*kSize+k; // If outputCounts is equal to 0 then that will cause division by zero. if (outputCounts.at(scaleFactorIndex) <= 0){ for (int l = 0, lSize = indexEnd.l()-indexStart.l()+1; l < lSize; l++) outputValues[i*jSize*kSize*lSize+j*kSize*lSize+k*lSize+l] = 0; } else { double scaleFactor = qAbs(inputCounts.at(scaleFactorIndex)/outputCounts.at(scaleFactorIndex)); for (int l = 0, lSize = indexEnd.l()-indexStart.l()+1; l < lSize; l++){ int spectrumIndex = i*jSize*kSize*lSize+j*kSize*lSize+k*lSize+l; outputValues[spectrumIndex] = data.at(spectrumIndex)*scaleFactor; } } } } } break; } } return true; }
bool AMInMemoryDataStore::values(const AMnDIndex &scanIndexStart, const AMnDIndex &scanIndexEnd, int measurementId, const AMnDIndex &measurementIndexStart, const AMnDIndex &measurementIndexEnd, double *outputValues) const { if(scanIndexStart.rank() != axes_.count() || scanIndexEnd.rank() != axes_.count()) return false; if(measurementId >= measurements_.count()) return false; const AMMeasurementInfo& mi = measurements_.at(measurementId); if(measurementIndexStart.rank() != mi.rank() || measurementIndexEnd.rank() != mi.rank()) return false; #ifdef AM_ENABLE_BOUNDS_CHECKING // check bounds for scan axes for(int mu=axes_.count()-1; mu >= 0; --mu) { if(scanIndexEnd.at(mu) < scanIndexStart.at(mu)) return false; if(scanIndexEnd.at(mu) >= axes_.at(mu).size) return false; } // check bounds for measurement axes for(int mu=mi.rank()-1; mu >= 0; --mu) { if(measurementIndexEnd.at(mu) < measurementIndexStart.at(mu)) return false; if(measurementIndexEnd.at(mu) >= mi.size(mu)) return false; } #endif // Determine the full size of the measurement (not necessarily the size of the block that we want to read out). AMnDIndex measurementSize = mi.size(); int flatMeasurementSize = measurementSize.product(); // specific cases of scan rank: switch(scanIndexStart.rank()) { case 0: { // null scan space; just copy in the measurement block if(measurementIndexStart.rank() == 0) { // If measurements are scalar values, can optimize. outputValues[0] = double(scalarScanPoint_.at(measurementId).at(0)); } else { // need to find out how many points one measurement block takes int measurementSpaceSize = measurementIndexStart.totalPointsTo(measurementIndexEnd); if(measurementSpaceSize == flatMeasurementSize) // if asking for the whole measurement, can optimize. measurementValues(scalarScanPoint_.at(measurementId), flatMeasurementSize, outputValues); else measurementValues(scalarScanPoint_.at(measurementId), measurementSize, measurementIndexStart, measurementIndexEnd, outputValues); } break; } case 1:{ if(measurementIndexStart.rank() == 0) { // If measurements are scalar values, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) *(outputValues++) = double(scanPoints_.at(i).at(measurementId).at(0)); } else { // need to find out how many points one measurement block takes int measurementSpaceSize = measurementIndexStart.totalPointsTo(measurementIndexEnd); if(measurementSpaceSize == flatMeasurementSize) // if asking for the whole measurement, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { measurementValues(scanPoints_.at(i).at(measurementId), flatMeasurementSize, outputValues); outputValues += measurementSpaceSize; } else for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { measurementValues(scanPoints_.at(i).at(measurementId), measurementSize, measurementIndexStart, measurementIndexEnd, outputValues); outputValues += measurementSpaceSize; } } break; } case 2:{ if(measurementIndexStart.rank() == 0) { // If measurements are scalar values, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { *(outputValues++) = double(scanPoints_.at(ic+j).at(measurementId).at(0)); } } } else { // need to find out how many points one measurement block takes int measurementSpaceSize = measurementIndexStart.totalPointsTo(measurementIndexEnd); if(measurementSpaceSize == flatMeasurementSize) { // if asking for the whole measurement, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { measurementValues(scanPoints_.at(ic+j).at(measurementId), flatMeasurementSize, outputValues); outputValues += measurementSpaceSize; } } } else { for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { measurementValues(scanPoints_.at(ic+j).at(measurementId), measurementSize, measurementIndexStart, measurementIndexEnd, outputValues); outputValues += measurementSpaceSize; } } } } break; } case 3:{ if(measurementIndexStart.rank() == 0) { // If measurements are scalar values, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j()*scanSize_.k(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { int jc = j*scanSize_.k(); for(int k=scanIndexStart.k(); k<=scanIndexEnd.k(); ++k) { *(outputValues++) = double(scanPoints_.at(ic+jc+k).at(measurementId).at(0)); } } } } else { // need to find out how many points one measurement block takes int measurementSpaceSize = measurementIndexStart.totalPointsTo(measurementIndexEnd); if(measurementSpaceSize == flatMeasurementSize) { // if asking for the whole measurement, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j()*scanSize_.k(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { int jc = j*scanSize_.k(); for(int k=scanIndexStart.k(); k<=scanIndexEnd.k(); ++k) { measurementValues(scanPoints_.at(ic+jc+k).at(measurementId), flatMeasurementSize, outputValues); outputValues += measurementSpaceSize; } } } } else { for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j()*scanSize_.k(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { int jc = j*scanSize_.k(); for(int k=scanIndexStart.k(); k<=scanIndexEnd.k(); ++k) { measurementValues(scanPoints_.at(ic+jc+k).at(measurementId), measurementSize, measurementIndexStart, measurementIndexEnd, outputValues); outputValues += measurementSpaceSize; } } } } } break; } case 4:{ if(measurementIndexStart.rank() == 0) { // If measurements are scalar values, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j()*scanSize_.k()*scanSize_.l(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { int jc = j*scanSize_.k()*scanSize_.l(); for(int k=scanIndexStart.k(); k<=scanIndexEnd.k(); ++k) { int kc = k*scanSize_.l(); for(int l=scanIndexStart.l(); l<=scanIndexEnd.l(); ++l) { *(outputValues++) = double(scanPoints_.at(ic+jc+kc+l).at(measurementId).at(0)); } } } } } else { int measurementSpaceSize = measurementIndexStart.totalPointsTo(measurementIndexEnd); if(measurementSpaceSize == flatMeasurementSize) { // if asking for the whole measurement, can optimize. for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j()*scanSize_.k()*scanSize_.l(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { int jc = j*scanSize_.k()*scanSize_.l(); for(int k=scanIndexStart.k(); k<=scanIndexEnd.k(); ++k) { int kc = k*scanSize_.l(); for(int l=scanIndexStart.l(); l<=scanIndexEnd.l(); ++l) { measurementValues(scanPoints_.at(ic+jc+kc+l).at(measurementId), flatMeasurementSize, outputValues); outputValues += measurementSpaceSize; } } } } } else { for(int i=scanIndexStart.i(); i<=scanIndexEnd.i(); ++i) { int ic = i*scanSize_.j()*scanSize_.k()*scanSize_.l(); for(int j=scanIndexStart.j(); j<=scanIndexEnd.j(); ++j) { int jc = j*scanSize_.k()*scanSize_.l(); for(int k=scanIndexStart.k(); k<=scanIndexEnd.k(); ++k) { int kc = k*scanSize_.l(); for(int l=scanIndexStart.l(); l<=scanIndexEnd.l(); ++l) { measurementValues(scanPoints_.at(ic+jc+kc+l).at(measurementId), measurementSize, measurementIndexStart, measurementIndexEnd, outputValues); outputValues += measurementSpaceSize; } } } } } } break; } default:{ int measurementSpaceSize = measurementIndexStart.totalPointsTo(measurementIndexEnd); valuesImplementationRecursive(scanIndexStart, scanIndexEnd, measurementId, measurementIndexStart, measurementIndexEnd, &outputValues, 0, 0, measurementSize, measurementSpaceSize); return false; break; } } return true; }