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);
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(); }
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; }
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 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; }
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; }
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; }
bool AM1DRunningAverageFilterAB::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 int totalSize = indexStart.totalPointsTo(indexEnd); QVector<double> data = QVector<double>(totalSize); inputSource_->values(indexStart, indexEnd, data.data()); int numberOfPoints = (filterSize_-1)/2; double average = 0; int tempNumberOfPoints = 1; // If the filter size is bigger then the total size of the data then we will just check every point along the way. if (numberOfPoints > totalSize){ for (int i = 0; i < totalSize; i++){ average = data.at(i); tempNumberOfPoints = 1; for (int j = 1; j < numberOfPoints; j++){ if ((i-j) >= 0){ average += data.at(i-j); tempNumberOfPoints++; } if ((i+j) < totalSize){ average += data.at(i+j); tempNumberOfPoints++; } } outputValues[i] = average/double(tempNumberOfPoints); } } // Otherwise, we can optimize the middle indices of the without having to check if we will be accessing data outside of the array range. else { // Compute the beginning values. for (int i = 0; i < numberOfPoints; i++){ average = data.at(i); tempNumberOfPoints = 1; // Only need the substraction check at the beginning. for (int j = 1; j < numberOfPoints; j++){ if ((i-j) >= 0){ average += data.at(i-j); tempNumberOfPoints++; } average += data.at(i+j); tempNumberOfPoints++; } outputValues[i] = average/double(tempNumberOfPoints); } // No need for conditionals in the middle of the data. double averagePoints = double(numberOfPoints); for (int i = numberOfPoints, count = totalSize-numberOfPoints; i < count; i++){ average = data.at(i); for (int j = 1; j < numberOfPoints; j++) average += data.at(i-j) + data.at(i+j); outputValues[i] = average/averagePoints; } // Compute the last values. for (int i = totalSize-numberOfPoints; i < totalSize; i++){ average = data.at(i); tempNumberOfPoints = 1; // Only need the addition check at the end. for (int j = 1; j < numberOfPoints; j++){ average += data.at(i-j); tempNumberOfPoints++; if ((i+j) < totalSize){ average += data.at(i+j); tempNumberOfPoints++; } } outputValues[i] = average/double(tempNumberOfPoints); } } 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; }