52 std::string output_message;
54 const std::string reductionManagerName =
getProperty(
"ReductionProperties");
55 std::shared_ptr<PropertyManager> reductionManager;
56 if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) {
57 reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName);
59 reductionManager = std::make_shared<PropertyManager>();
60 PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager);
64 const bool persistent =
getProperty(
"PersistentCorrection");
65 if (!reductionManager->existsProperty(
"DarkCurrentAlgorithm") && persistent) {
66 auto algProp = std::make_unique<AlgorithmProperty>(
"DarkCurrentAlgorithm");
68 reductionManager->declareProperty(std::move(algProp));
80 g_log.
error() <<
"To use this version of EQSANSDarkCurrentSubtraction, "
81 <<
"you need to make sure EQSANSLoad produces histograms. "
82 <<
"You can also turn the dark current subtraction off.\n";
83 throw std::invalid_argument(
"EQSANSDarkCurrentSubtraction-v2 only works on histograms.");
89 progress.report(
"Subtracting dark current");
92 std::filesystem::path path(fileName);
93 const std::string entryName =
"DarkCurrent" + path.stem().string();
94 std::string darkWSName =
"__dark_current_" + path.stem().string();
96 if (reductionManager->existsProperty(entryName)) {
97 darkWS = reductionManager->getProperty(entryName);
98 darkWSName = reductionManager->getPropertyValue(entryName);
99 output_message += darkWSName +
'\n';
103 if (!reductionManager->existsProperty(
"LoadAlgorithm")) {
105 loadAlg->setProperty(
"Filename", fileName);
106 if (loadAlg->existsProperty(
"LoadMonitors"))
107 loadAlg->setProperty(
"LoadMonitors",
false);
108 loadAlg->executeAsChildAlg();
109 darkWS = loadAlg->getProperty(
"OutputWorkspace");
113 IAlgorithm_sptr loadAlg0 = reductionManager->getProperty(
"LoadAlgorithm");
114 const std::string loadString = loadAlg0->toString();
116 loadAlg->setChild(
true);
117 loadAlg->setProperty(
"Filename", fileName);
118 if (loadAlg->existsProperty(
"LoadMonitors"))
119 loadAlg->setProperty(
"LoadMonitors",
false);
120 loadAlg->setPropertyValue(
"OutputWorkspace", darkWSName);
122 darkWS = loadAlg->getProperty(
"OutputWorkspace");
125 output_message +=
"\n Loaded " + fileName +
"\n";
126 if (loadAlg->existsProperty(
"OutputMessage")) {
127 std::string msg = loadAlg->getPropertyValue(
"OutputMessage");
128 output_message +=
" |" + Poco::replace(msg,
"\n",
"\n |") +
"\n";
131 std::string darkWSOutputName =
getPropertyValue(
"OutputDarkCurrentWorkspace");
132 if (!darkWSOutputName.empty())
134 AnalysisDataService::Instance().addOrReplace(darkWSName, darkWS);
136 reductionManager->setPropertyValue(entryName, darkWSName);
137 reductionManager->setProperty(entryName, darkWS);
139 progress.report(3,
"Loaded dark current");
142 double scaling_factor = 1.0;
143 if (inputWS->run().hasProperty(
"duration")) {
144 auto duration = inputWS->run().getPropertyValueAsType<
double>(
"duration");
145 auto dark_duration = darkWS->run().getPropertyValueAsType<
double>(
"duration");
147 scaling_factor = duration / dark_duration;
148 }
else if (inputWS->run().hasProperty(
"proton_charge")) {
149 auto dp = inputWS->run().getTimeSeriesProperty<
double>(
"proton_charge");
150 double duration = dp->getStatistics().duration;
152 dp = darkWS->run().getTimeSeriesProperty<
double>(
"proton_charge");
153 double dark_duration = dp->getStatistics().duration;
154 scaling_factor = duration / dark_duration;
155 }
else if (inputWS->run().hasProperty(
"timer")) {
156 auto duration = inputWS->run().getPropertyValueAsType<
double>(
"timer");
157 auto dark_duration = darkWS->run().getPropertyValueAsType<
double>(
"timer");
159 scaling_factor = duration / dark_duration;
161 output_message +=
"\n Could not find proton charge or duration in sample logs";
162 g_log.
error() <<
"ERROR: Could not find proton charge or duration in sample logs\n";
170 progress.report(
"Scaling dark current");
174 rebinAlg->setProperty(
"InputWorkspace", darkWS);
175 rebinAlg->setProperty(
"OutputWorkspace", darkWS);
176 rebinAlg->executeAsChildAlg();
181 scaleAlg->setProperty(
"InputWorkspace", scaledDarkWS);
182 scaleAlg->setProperty(
"Factor", scaling_factor);
183 scaleAlg->setProperty(
"OutputWorkspace", scaledDarkWS);
184 scaleAlg->setProperty(
"Operation",
"Multiply");
185 scaleAlg->executeAsChildAlg();
186 scaledDarkWS = rebinAlg->getProperty(
"OutputWorkspace");
189 const auto numberOfSpectra =
static_cast<int>(inputWS->getNumberHistograms());
190 const auto numberOfDarkSpectra =
static_cast<int>(scaledDarkWS->getNumberHistograms());
191 if (numberOfSpectra != numberOfDarkSpectra) {
192 g_log.
error() <<
"Incompatible number of pixels between sample run and "
195 const auto nBins =
static_cast<int>(inputWS->readY(0).size());
196 const auto xLength =
static_cast<int>(inputWS->readX(0).size());
197 if (xLength != nBins + 1) {
198 g_log.
error() <<
"The input workspaces are expected to be histograms\n";
201 progress.report(
"Subtracting dark current");
202 const auto &spectrumInfo = inputWS->spectrumInfo();
204 for (
int i = 0; i < numberOfSpectra; i++) {
206 if (spectrumInfo.isMasked(i))
209 const MantidVec &YDarkValues = scaledDarkWS->readY(i);
210 const MantidVec &YDarkErrors = scaledDarkWS->readE(i);
211 const MantidVec &XValues = inputWS->readX(i);
214 for (
int j = 0; j < nBins; j++) {
215 double bin_scale = (XValues[j + 1] - XValues[j]) / (XValues[nBins] - XValues[0]);
216 YValues[j] -= YDarkValues[0] * bin_scale;
217 YErrors[j] = sqrt(YErrors[j] * YErrors[j] + YDarkErrors[0] * YDarkErrors[0] * bin_scale * bin_scale);
221 setProperty(
"OutputMessage",
"Dark current subtracted: " + output_message);
223 progress.report(
"Subtracted dark current");