440 if (fileName.empty() && !inputEventWS) {
441 g_log.
error() <<
"EQSANSLoad input error: Either a valid file path or an "
442 "input workspace must be provided\n";
443 throw std::runtime_error(
"EQSANSLoad input error: Either a valid file path "
444 "or an input workspace must be provided");
445 }
else if (!fileName.empty() && inputEventWS) {
446 g_log.
error() <<
"EQSANSLoad input error: Either a valid file path or an "
447 "input workspace must be provided, but not both\n";
448 throw std::runtime_error(
"EQSANSLoad input error: Either a valid file path "
449 "or an input workspace must be provided, but not "
454 const bool skipTOFCorrection =
getProperty(
"SkipTOFCorrection");
461 const bool noBeamCenter =
getProperty(
"NoBeamCenter");
464 const std::string reductionManagerName =
getProperty(
"ReductionProperties");
465 std::shared_ptr<PropertyManager> reductionManager;
466 if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) {
467 reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName);
469 reductionManager = std::make_shared<PropertyManager>();
470 PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager);
473 if (!reductionManager->existsProperty(
"LoadAlgorithm")) {
474 auto loadProp = std::make_unique<AlgorithmProperty>(
"LoadAlgorithm");
478 reductionManager->declareProperty(std::move(loadProp));
481 if (!reductionManager->existsProperty(
"InstrumentName"))
489 const bool loadMonitors =
getProperty(
"LoadMonitors");
490 const bool loadNexusInstrumentXML =
getProperty(
"LoadNexusInstrumentXML");
492 loadAlg->setProperty(
"LoadMonitors", loadMonitors);
493 loadAlg->setProperty(
"Filename", fileName);
494 loadAlg->setProperty(
"LoadNexusInstrumentXML", loadNexusInstrumentXML);
495 if (skipTOFCorrection) {
502 Workspace_sptr dataWS_asWks = loadAlg->getProperty(
"OutputWorkspace");
503 dataWS = std::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks);
507 if (loadMonitors && loadAlg->existsProperty(
"MonitorWorkspace")) {
508 Workspace_sptr monWSOutput = loadAlg->getProperty(
"MonitorWorkspace");
510 if ((monWSOutput) && (!monWS))
514 "data, support for this is not "
515 "implemented in EQSANSLoad yet");
517 "Monitors from the Event NeXus file");
523 if (inputEventWS != outputEventWS) {
525 copyAlg->setProperty(
"InputWorkspace", inputEventWS);
526 copyAlg->executeAsChildAlg();
527 Workspace_sptr dataWS_asWks = copyAlg->getProperty(
"OutputWorkspace");
528 dataWS = std::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks);
530 dataWS = std::dynamic_pointer_cast<MatrixWorkspace>(inputEventWS);
538 const double sampleflange_det_dist =
getProperty(
"SampleDetectorDistance");
539 if (!
isEmpty(sampleflange_det_dist)) {
540 sfdd = sampleflange_det_dist;
542 if (!
dataWS->run().hasProperty(
"detectorZ")) {
543 g_log.
error() <<
"Could not determine Z position: the "
544 "SampleDetectorDistance property was not set "
545 "and the run logs do not contain the detectorZ property\n";
546 throw std::invalid_argument(
"Could not determine Z position: stopping execution");
549 const std::string dzName =
"detectorZ";
553 throw std::runtime_error(
"Could not cast (interpret) the property " + dzName +
554 " as a time series property value.");
555 sfdd = dp->getStatistics().mean;
558 const double sampleflange_det_offset =
getProperty(
"DetectorOffset");
559 if (!
isEmpty(sampleflange_det_offset))
560 sfdd += sampleflange_det_offset;
564 const double sample_det_offset =
getProperty(
"SampleDetectorDistanceOffset");
565 if (!
isEmpty(sample_det_offset))
566 sfdd += sample_det_offset;
567 if (!
isEmpty(sample_det_offset) && !
isEmpty(sampleflange_det_offset))
568 g_log.
error() <<
"Both DetectorOffset and SampleDetectorDistanceOffset "
569 "are set. Only one should be used.\n";
574 const double sampleflange_sample_offset =
getProperty(
"SampleOffset");
575 if (!
isEmpty(sampleflange_sample_offset)) {
576 s2d -= sampleflange_sample_offset;
581 mvAlg->setProperty(
"ComponentName",
"sample-position");
582 mvAlg->setProperty(
"Z", sampleflange_sample_offset / 1000.0);
583 mvAlg->setProperty(
"RelativePosition",
false);
584 mvAlg->executeAsChildAlg();
585 g_log.
information() <<
"Moving sample to " << sampleflange_sample_offset / 1000.0 <<
" meters\n";
587 " Sample position: " + Poco::NumberFormatter::format(sampleflange_sample_offset / 1000.0, 3) +
" m\n";
590 dataWS->mutableRun().addProperty(
"sampleflange_detector_distance", sfdd,
"mm",
true);
591 dataWS->mutableRun().addProperty(
"sample_detector_distance", s2d,
"mm",
true);
596 mvAlg->setProperty(
"ComponentName",
"detector1");
597 mvAlg->setProperty(
"Z", sfdd / 1000.0);
598 mvAlg->setProperty(
"RelativePosition",
false);
599 mvAlg->executeAsChildAlg();
600 g_log.
information() <<
"Moving detector to " << sfdd / 1000.0 <<
" meters\n";
601 m_output_message +=
" Detector position: " + Poco::NumberFormatter::format(sfdd / 1000.0, 3) +
" m\n";
605 std::string config_file;
606 if (
dataWS->run().hasProperty(
"run_number")) {
607 const std::string run_str =
dataWS->run().getPropertyValueAsType<std::string>(
"run_number");
608 Poco::NumberParser::tryParse(run_str, run_number);
618 if (use_config && !config_file.empty()) {
626 }
else if (use_config) {
630 " Could not find configuration file for run " + Poco::NumberFormatter::format(run_number) +
"\n";
636 g_log.
error() <<
"Moderator position seems close to the sample, please check\n";
641 mvAlg->setProperty(
"ComponentName",
"moderator");
643 mvAlg->setProperty(
"RelativePosition",
false);
644 mvAlg->executeAsChildAlg();
653 if (reductionManager->existsProperty(
"LatestBeamCenterX") &&
654 reductionManager->existsProperty(
"LatestBeamCenterY")) {
655 m_center_x = reductionManager->getProperty(
"LatestBeamCenterX");
656 m_center_y = reductionManager->getProperty(
"LatestBeamCenterY");
664 if (!reductionManager->existsProperty(
"LatestBeamCenterX"))
667 reductionManager->setProperty(
"LatestBeamCenterX",
m_center_x);
668 if (!reductionManager->existsProperty(
"LatestBeamCenterY"))
671 reductionManager->setProperty(
"LatestBeamCenterY",
m_center_y);
675 const bool correct_for_flight_path =
getProperty(
"CorrectForFlightPath");
678 double wl_combined_max = 0.0;
679 if (skipTOFCorrection) {
680 m_output_message +=
" Skipping EQSANS TOF correction: assuming a single frame\n";
681 dataWS->mutableRun().addProperty(
"is_frame_skipping", 0,
true);
682 if (correct_for_flight_path) {
683 g_log.
error() <<
"CorrectForFlightPath and SkipTOFCorrection can't be "
684 "set to true at the same time\n";
689 if (!correct_for_flight_path)
697 tofAlg->setProperty(
"FlightPathCorrection", correct_for_flight_path);
698 tofAlg->executeAsChildAlg();
699 wl_min = tofAlg->getProperty(
"WavelengthMin");
700 wl_max = tofAlg->getProperty(
"WavelengthMax");
701 if (wl_min >= wl_max) {
706 const bool frame_skipping = tofAlg->getProperty(
"FrameSkipping");
707 dataWS->mutableRun().addProperty(
"wavelength_min", wl_min,
"Angstrom",
true);
708 dataWS->mutableRun().addProperty(
"wavelength_max", wl_max,
"Angstrom",
true);
709 dataWS->mutableRun().addProperty(
"is_frame_skipping",
int(frame_skipping),
true);
710 wl_combined_max = wl_max;
712 " Wavelength range: " + Poco::NumberFormatter::format(wl_min) +
" - " + Poco::NumberFormatter::format(wl_max);
713 if (frame_skipping) {
714 const double wl_min2 = tofAlg->getProperty(
"WavelengthMinFrame2");
715 const double wl_max2 = tofAlg->getProperty(
"WavelengthMaxFrame2");
716 wl_combined_max = wl_max2;
717 dataWS->mutableRun().addProperty(
"wavelength_min_frame2", wl_min2,
"Angstrom",
true);
718 dataWS->mutableRun().addProperty(
"wavelength_max_frame2", wl_max2,
"Angstrom",
true);
719 m_output_message +=
" and " + Poco::NumberFormatter::format(wl_min2) +
" - " +
720 Poco::NumberFormatter::format(wl_max2) +
" Angstrom\n";
728 const double ssd =
fabs(
dataWS->getInstrument()->getSource()->getPos().Z()) * 1000.0;
729 const double conversion_factor = 3.9560346 / (sfdd + ssd);
731 " TOF to wavelength conversion factor: " + Poco::NumberFormatter::format(conversion_factor) +
"\n";
733 if (skipTOFCorrection) {
735 if (dataWS_evt->getNumberEvents() == 0)
736 throw std::invalid_argument(
"No event to process: check your TOF cuts");
737 wl_min = dataWS_evt->getTofMin() * conversion_factor;
738 wl_max = dataWS_evt->getTofMax() * conversion_factor;
739 wl_combined_max = wl_max;
740 g_log.
information() <<
"Wavelength range: " << wl_min <<
" to " << wl_max <<
'\n';
741 dataWS->mutableRun().addProperty(
"wavelength_min", wl_min,
"Angstrom",
true);
742 dataWS->mutableRun().addProperty(
"wavelength_max", wl_max,
"Angstrom",
true);
748 scAlg->setProperty(
"Factor", conversion_factor);
749 scAlg->executeAsChildAlg();
750 dataWS->getAxis(0)->setUnit(
"Wavelength");
753 const bool preserveEvents =
getProperty(
"PreserveEvents");
754 const double wl_step =
getProperty(
"WavelengthStep");
756 const double wl_min_rounded = round(wl_min * 100.0) / 100.0;
757 const double wl_max_rounded = round(wl_combined_max * 100.0) / 100.0;
758 std::string params = Poco::NumberFormatter::format(wl_min_rounded, 2) +
"," + Poco::NumberFormatter::format(wl_step) +
759 "," + Poco::NumberFormatter::format(wl_max_rounded, 2);
765 rebinAlg->setPropertyValue(
"Params", params);
766 rebinAlg->setProperty(
"PreserveEvents", preserveEvents);
767 rebinAlg->executeAsChildAlg();
770 dataWS = rebinAlg->getProperty(
"OutputWorkspace");
773 setProperty<MatrixWorkspace_sptr>(
"OutputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(
dataWS));