54 std::map<std::string, std::string> errors;
64 if (
inputWS->getInstrument()->getName() !=
"CORELLI")
65 errors[
"InputWorkspace"] =
"This Algorithm will only work for Corelli.";
68 else if (!
inputWS->getInstrument()->getComponentByName(
"correlation-chopper"))
69 errors[
"InputWorkspace"] =
"Correlation chopper not found.";
72 else if (
inputWS->getInstrument()->getComponentByName(
"correlation-chopper")->getStringParameter(
"sequence").empty())
73 errors[
"InputWorkspace"] =
"Found the correlation chopper but no chopper sequence?";
76 else if (!
inputWS->getInstrument()->getSource() || !
inputWS->getInstrument()->getSample())
77 errors[
"InputWorkspace"] =
"Instrument not sufficiently defined: failed to "
78 "get source and/or sample";
81 else if (!
inputWS->run().hasProperty(
"chopper4_TDC"))
82 errors[
"InputWorkspace"] =
"Workspace is missing chopper4 TDCs.";
85 else if (!
inputWS->run().hasProperty(
"BL9:Chop:Skf4:MotorSpeed"))
86 errors[
"InputWorkspace"] =
"Workspace is missing chopper4 Motor Speed.";
90 errors[
"InputWorkspace"] =
"The workspace needs to be a sorted.";
94 errors[
"InputWorkspace"] =
"This workspace has no pulse time information.";
113 std::vector<std::string> chopperSequence = chopper->getStringParameter(
"sequence");
116 std::vector<std::string> chopperSequenceSplit;
117 boost::split(chopperSequenceSplit, chopperSequence[0], boost::is_space());
119 std::vector<double> sequence;
120 sequence.resize(chopperSequenceSplit.size());
121 sequence[0] = boost::lexical_cast<double>(chopperSequenceSplit[0]);
124 double totalOpen = 0;
125 for (
unsigned int i = 1; i < chopperSequenceSplit.size(); i++) {
126 auto seqAngle = boost::lexical_cast<double>(chopperSequenceSplit[i]);
127 sequence[i] = sequence[i - 1] + seqAngle;
129 totalOpen += seqAngle;
133 double dutyCycle = totalOpen / sequence.back();
134 auto weightAbsorbing =
static_cast<float>(-dutyCycle / (1.0 - dutyCycle));
135 g_log.
information() <<
"dutyCycle = " << dutyCycle <<
" weightTransparent = 1.0"
136 <<
" weightAbsorbing = " << weightAbsorbing <<
"\n";
142 throw std::runtime_error(
"chopper4_TDC not found");
144 std::vector<DateAndTime> tdc = chopperTdc->timesAsVector();
147 const auto offset =
static_cast<int64_t
>(offset_int);
149 std::transform(tdc.begin(), tdc.end(), tdc.begin(), [offset](
auto timing) { return timing + offset; });
152 if (!
inputWS->run().hasProperty(
"BL9:Chop:Skf4:MotorSpeed")) {
155 const auto motorSpeed =
inputWS->run().getPropertyAsSingleValue(
"BL9:Chop:Skf4:MotorSpeed");
156 double period = 1e9 / motorSpeed;
157 g_log.
information() <<
"Frequency = " << 1e9 / period <<
"Hz Period = " << period <<
"ns\n";
161 const double distanceChopperToSource =
inputWS->getInstrument()->getSource()->getDistance(*chopper);
162 const double distanceSourceToSample =
inputWS->getInstrument()->getSource()->getDistance(*sample);
165 std::vector<std::string> t0_formula =
inputWS->getInstrument()->getStringParameter(
"t0_formula");
166 if (t0_formula.empty())
168 std::string formula = t0_formula[0];
174 auto numHistograms =
static_cast<int64_t
>(
inputWS->getNumberHistograms());
176 const auto &spectrumInfo =
inputWS->spectrumInfo();
178 for (int64_t i = 0; i < numHistograms; ++i) {
181 auto &evlist =
outputWS->getSpectrum(i);
184 if (evlist.getEventType() ==
TOF)
187 std::vector<WeightedEvent> &events = evlist.getWeightedEvents();
194 DateAndTime emptyTime;
195 if (events.back().pulseTime() == emptyTime)
196 throw std::runtime_error(
"Missing pulse times on events. This will not work.");
199 double distanceSourceToDetector = distanceSourceToSample + spectrumInfo.l2(i);
200 double tofScale = distanceChopperToSource / distanceSourceToDetector;
204 parser.DefineVar(
"incidentEnergy",
206 parser.SetExpr(formula);
209 std::vector<WeightedEvent>::iterator it;
210 for (it = events.begin(); it != events.end(); ++it) {
211 double tof = it->tof();
212 E1 = m_convfactor * (distanceSourceToDetector / tof) * (distanceSourceToDetector / tof);
213 double t0 = parser.Eval();
215 DateAndTime tofTime = it->pulseTime() +
static_cast<int64_t
>(((tof - t0) * tofScale + t0) * 1000.);
216 while (tdc_i != tdc.size() && tofTime > tdc[tdc_i])
220 360. *
static_cast<double>(tofTime.totalNanoseconds() - tdc[tdc_i - 1].totalNanoseconds()) / period;
222 std::vector<double>::iterator location;
223 location = std::lower_bound(sequence.begin(), sequence.end(), angle);
225 if ((location - sequence.begin()) % 2 == 0) {
226 it->m_weight *= weightAbsorbing;
227 it->m_errorSquared *= weightAbsorbing * weightAbsorbing;
232 if ((events.back().pulseTime() +
static_cast<int64_t
>(events.back().tof() * 1000.)) >
233 (tdc.back() +
static_cast<int64_t
>(period * 2)))