144 const double maxDSpaceShift =
getProperty(
"MaxDSpaceShift");
145 const int referenceSpectra =
getProperty(
"ReferenceSpectra");
149 const auto index_ref =
static_cast<size_t>(referenceSpectra);
152 std::vector<size_t> indexes =
getProperty(
"WorkspaceIndexList");
153 if (indexes.empty()) {
154 const int wsIndexMin =
getProperty(
"WorkspaceIndexMin");
155 const int wsIndexMax =
getProperty(
"WorkspaceIndexMax");
156 indexes.reserve(
static_cast<size_t>(wsIndexMax - wsIndexMin + 1));
157 std::copy(boost::make_counting_iterator(wsIndexMin), boost::make_counting_iterator(wsIndexMax + 1),
158 std::back_inserter(indexes));
160 const int numSpectra =
static_cast<int>(indexes.size());
163 g_log.
information() <<
"There are " << numSpectra <<
" spectra in the range\n";
166 auto &referenceSpectraE = inputWS->e(index_ref);
167 auto &referenceSpectraX = inputWS->x(index_ref);
168 auto &referenceSpectraY = inputWS->y(index_ref);
170 using std::placeholders::_1;
172 std::find_if(referenceSpectraX.cbegin(), referenceSpectraX.cend(), std::bind(std::greater<double>(), _1, xmin));
173 if (rangeStart == referenceSpectraX.cend())
174 throw std::runtime_error(
"No data above XMin");
175 auto rangeEnd = std::find_if(rangeStart, referenceSpectraX.cend(), std::bind(std::greater<double>(), _1, xmax));
176 if (rangeStart == rangeEnd)
177 throw std::runtime_error(
"Range is not valid");
179 MantidVec::difference_type rangeStartCorrection = std::distance(referenceSpectraX.cbegin(), rangeStart);
180 MantidVec::difference_type rangeEndCorrection = std::distance(referenceSpectraX.cbegin(), rangeEnd);
182 const std::vector<double> referenceXVector(rangeStart, rangeEnd);
183 std::vector<double> referenceYVector(referenceSpectraY.cbegin() + rangeStartCorrection,
184 referenceSpectraY.cbegin() + (rangeEndCorrection - 1));
185 std::vector<double> referenceEVector(referenceSpectraE.cbegin() + rangeStartCorrection,
186 referenceSpectraE.cbegin() + (rangeEndCorrection - 1));
188 g_log.
information() <<
"min max " << referenceXVector.front() <<
" " << referenceXVector.back() <<
'\n';
192 const auto numReferenceY =
static_cast<int>(referenceYVector.size());
195 int shiftCorrection = 0;
197 if (xmax - xmin < maxDSpaceShift)
199 <<
") is larger than specified range of xmin(" << xmin <<
") to xmax(" << xmax
200 <<
"), please make it smaller or removed it entirely!"
204 const auto maxBins = std::max(0.0 + maxDSpaceShift * 2, 0.1) / inputWS->getDimension(0)->getBinWidth();
206 shiftCorrection =
static_cast<int>(std::max(0.0, abs((-numReferenceY + 2) - (numReferenceY - 2)) - maxBins)) / 2;
209 const int numPoints = 2 * (numReferenceY - shiftCorrection) - 3;
211 throw std::runtime_error(
"Range is not valid");
213 MatrixWorkspace_sptr out = create<HistoWorkspace>(*inputWS, numSpectra, Points(
static_cast<size_t>(numPoints)));
215 const auto referenceVariance = subtractMean(referenceYVector, referenceEVector);
217 const double referenceNorm = 1.0 / sqrt(referenceVariance.y);
218 double referenceNormE = 0.5 * pow(referenceNorm, 3) * sqrt(referenceVariance.e);
221 const bool isDistribution = inputWS->isDistribution();
223 auto &outX = out->mutableX(0);
225 for (
int i = 0; i < static_cast<int>(outX.size()); ++i) {
226 outX[i] =
static_cast<double>(i - (numReferenceY - shiftCorrection) + 2);
230 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, numSpectra);
232 for (
int currentSpecIndex = 0; currentSpecIndex < numSpectra; ++currentSpecIndex)
235 const size_t currentSpecIndex_szt =
static_cast<size_t>(currentSpecIndex);
236 const size_t wsIndex = indexes[currentSpecIndex_szt];
238 out->getSpectrum(currentSpecIndex_szt).copyInfoFrom(inputWS->getSpectrum(wsIndex));
239 out->setSharedX(currentSpecIndex_szt, out->sharedX(0));
241 const auto &inputXVector = inputWS->x(wsIndex);
242 const auto &inputYVector = inputWS->y(wsIndex);
243 const auto &inputEVector = inputWS->e(wsIndex);
246 std::vector<double> tempY(
static_cast<size_t>(numReferenceY));
247 std::vector<double> tempE(
static_cast<size_t>(numReferenceY));
249 VectorHelper::rebin(inputXVector.rawData(), inputYVector.rawData(), inputEVector.rawData(), referenceXVector, tempY,
250 tempE, isDistribution);
251 const auto tempVar = subtractMean(tempY, tempE);
254 const double tempNorm = 1.0 / sqrt(tempVar.y);
255 const double tempNormE = 0.5 * pow(tempNorm, 3) * sqrt(tempVar.e);
256 const double normalisation = referenceNorm * tempNorm;
257 const double normalisationE2 = pow((referenceNorm * tempNormE), 2) + pow((tempNorm * referenceNormE), 2);
260 auto &outY = out->mutableY(currentSpecIndex_szt);
261 auto &outE = out->mutableE(currentSpecIndex_szt);
263 for (
int dataIndex = -numReferenceY + 2 + shiftCorrection; dataIndex <= numReferenceY - 2 - shiftCorrection;
265 const auto dataIndexMagnitude =
static_cast<int>(abs(dataIndex));
266 const auto dataIndexPositive = bool(dataIndex >= 0);
267 double val = 0, err2 = 0;
269 if (dataIndexPositive) {
270 for (
int binIndex = numReferenceY - 1 - dataIndexMagnitude; binIndex >= 0; --binIndex) {
271 const auto x = referenceYVector[binIndex];
272 const auto y = tempY[binIndex + dataIndexMagnitude];
273 const auto xE = referenceEVector[binIndex];
274 const auto yE = tempE[binIndex + dataIndexMagnitude];
276 err2 +=
x *
x * yE +
y *
y * xE;
279 for (
int binIndex = numReferenceY - 1 - dataIndexMagnitude; binIndex >= 0; --binIndex) {
280 const auto x = tempY[binIndex];
281 const auto y = referenceYVector[binIndex + dataIndexMagnitude];
282 const auto xE = tempE[binIndex];
283 const auto yE = referenceEVector[binIndex + dataIndexMagnitude];
285 err2 +=
x *
x * yE +
y *
y * xE;
288 const size_t dataIndex_corrected =
static_cast<size_t>(dataIndex + numReferenceY - shiftCorrection - 2);
289 outY[dataIndex_corrected] = (val * normalisation);
290 outE[dataIndex_corrected] = sqrt(val * val * normalisationE2 + normalisation * normalisation * err2);
298 out->getAxis(0)->unit() = UnitFactory::Instance().create(
"Label");
299 Unit_sptr unit = out->getAxis(0)->unit();
300 std::shared_ptr<Units::Label> label = std::dynamic_pointer_cast<Units::Label>(unit);
301 label->setLabel(
"Bins of Shift",
"\\mathbb{Z}");