From 3d564fe85f6865daf4582d35146e9352dbd0bf3f Mon Sep 17 00:00:00 2001 From: Vickie Lynch <lynchve@ornl.gov> Date: Mon, 25 Jul 2016 18:52:09 -0400 Subject: [PATCH] Refs #16199 optimize one bank --- .../Crystal/inc/MantidCrystal/PeakHKLErrors.h | 22 + .../inc/MantidCrystal/SCDCalibratePanels.h | 2 +- .../inc/MantidCrystal/SCDPanelErrors.h | 227 ++--- Framework/Crystal/src/PeakHKLErrors.cpp | 41 +- Framework/Crystal/src/SCDCalibratePanels.cpp | 720 ++------------ Framework/Crystal/src/SCDPanelErrors.cpp | 905 +++++------------- .../src/MoveInstrumentComponent.cpp | 46 +- 7 files changed, 474 insertions(+), 1489 deletions(-) diff --git a/Framework/Crystal/inc/MantidCrystal/PeakHKLErrors.h b/Framework/Crystal/inc/MantidCrystal/PeakHKLErrors.h index c5fb91c9fec..c9d3a65b398 100644 --- a/Framework/Crystal/inc/MantidCrystal/PeakHKLErrors.h +++ b/Framework/Crystal/inc/MantidCrystal/PeakHKLErrors.h @@ -17,6 +17,7 @@ #include "MantidAPI/IFunction.h" #include "MantidGeometry/Crystal/OrientedLattice.h" #include "MantidKernel/Matrix.h" +#include "MantidDataObjects/PeaksWorkspace.h" namespace Mantid { namespace Crystal { @@ -65,6 +66,27 @@ public: void init() override; + /** + * Creates a new peak, matching the old peak except for a different + *instrument. + * + * The Time of flightis the same except offset by T0. L0 should be the L0 + *for the new instrument. + * It is added as a parameter in case the instrument will have the initial + *flight path adjusted later. + * NOTE: the wavelength is changed. + * + * @param peak_old - The old peak + * @param instrNew -The new instrument + * @param T0 : + * @param L0 : + * @return The new peak with the new instrument( adjusted with the + *parameters) and time adjusted. + */ + static DataObjects::Peak createNewPeak(const Geometry::IPeak &peak_old, + Geometry::Instrument_sptr instrNew, + double T0, double L0); + static void cLone(boost::shared_ptr<Geometry::ParameterMap> &pmap, boost::shared_ptr<const Geometry::IComponent> component, boost::shared_ptr<const Geometry::ParameterMap> &pmapSv); diff --git a/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h b/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h index d90e4605040..2f257bff0fc 100644 --- a/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h +++ b/Framework/Crystal/inc/MantidCrystal/SCDCalibratePanels.h @@ -238,7 +238,7 @@ public: std::string bankPrefixName); private: - void saveIsawDetCal(boost::shared_ptr<const Geometry::Instrument> &instrument, + void saveIsawDetCal(boost::shared_ptr<Geometry::Instrument> &instrument, std::set<std::string> &AllBankName, double T0, std::string filename); diff --git a/Framework/Crystal/inc/MantidCrystal/SCDPanelErrors.h b/Framework/Crystal/inc/MantidCrystal/SCDPanelErrors.h index 60097b2e682..d4ac0d95406 100644 --- a/Framework/Crystal/inc/MantidCrystal/SCDPanelErrors.h +++ b/Framework/Crystal/inc/MantidCrystal/SCDPanelErrors.h @@ -4,201 +4,98 @@ //---------------------------------------------------------------------- // Includes //---------------------------------------------------------------------- -//#include "MantidCurveFitting/DllConfig.h" #include "MantidAPI/ParamFunction.h" #include "MantidAPI/IFunction1D.h" -#include "MantidDataObjects/PeaksWorkspace.h" -#include "MantidDataObjects/Workspace2D.h" -#include "MantidGeometry/Crystal/UnitCell.h" -#include <boost/lexical_cast.hpp> +#include "MantidKernel/System.h" +#include "MantidAPI/Workspace_fwd.h" +#include <cmath> namespace Mantid { namespace Crystal { +/* +@author Vickie Lynch, SNS +@date 7/25/2016 -/** - * Copyright © 2011-12 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge - *National Laboratory & European Spallation Source - * - * This file is part of Mantid. - * - * Mantid is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * Mantid is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * File change history is stored at: <https://github.com/mantidproject/mantid> - * Code Documentation is available at: <http://doxygen.mantidproject.org> - */ +Copyright © 2007-8 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge +National Laboratory & European Spallation Source +This file is part of Mantid. + +Mantid is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +Mantid is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. + +File change history is stored at: <https://github.com/mantidproject/mantid> +Code Documentation is available at: <http://doxygen.mantidproject.org> +*/ class DLLExport SCDPanelErrors : public API::ParamFunction, - public API::IFunction1D { + public API::IFunction1D { public: + /// Constructor SCDPanelErrors(); - /** - * Constructor - * @param pwk - The PeaksWorkspace - * @param Component_name - The comma separated list of bank names for which - *this - *Function - * this Function calculates the associated errors in - *qx,qy,qz - * @param ax - The a lattice parameter - * @param bx - The b lattice parameter - * @param cx - The c lattice parameter - * @param alphax - The alpha lattice parameter in degrees - * @param betax - The beta lattice parameter in degrees - * @param gammax - The gamma lattice parameter in degrees - * @param tolerance1 - The maximum distance a peak's h value, k value and - *lvalue are - * from an integer to be considered indexed. Outside of - *this - * constructor, ALL PEAKS are considered INDEXED. - * - * - */ - SCDPanelErrors(DataObjects::PeaksWorkspace_sptr &pwk, - std::string &Component_name, double ax, double bx, double cx, - double alphax, double betax, double gammax, double tolerance1); - + /// overwrite IFunction base class methods std::string name() const override { return "SCDPanelErrors"; } - - const std::string category() const override { return "Calibrate"; } - + const std::string category() const override { return "General"; } void function1D(double *out, const double *xValues, const size_t nData) const override; - + /// function derivatives void functionDeriv1D(API::Jacobian *out, const double *xValues, const size_t nData) override; - size_t nAttributes() const override; - - std::vector<std::string> getAttributeNames() const override; - - Attribute getAttribute(const std::string &attName) const override; - + /// Set a value to attribute attName void setAttribute(const std::string &attName, - const Attribute &value) override; - - bool hasAttribute(const std::string &attName) const override; - - /** - * A utility method that will set up the Workspace needed by this function. - * @param pwks -The peaksWorkspace. All peaks indexed to the given - *tolerance and whose - * associated bankName matches on of the strings in bankNames - *will be included. - * @param bankNames -A list of bankNames. See pwks - * @param tolerance -A measure of the maxiumum distance a peak's h value,k - *value, or l value is - * from an integer to be considered indexed. - * @return The associated workspace - * - * NOTE: This method could be used if this FitFunction is part of a composite - *function, but an Xstart - * and Xend for each composite is needed and may be difficult to - *determine. - */ - static DataObjects::Workspace2D_sptr - calcWorkspace(DataObjects::PeaksWorkspace_sptr &pwks, - std::vector<std::string> &bankNames, double tolerance); - - /** - * Creates a new peak, matching the old peak except for a different - *instrument. - * - * The Time of flightis the same except offset by T0. L0 should be the L0 - *for the new instrument. - * It is added as a parameter in case the instrument will have the initial - *flight path adjusted later. - * NOTE: the wavelength is changed. - * - * @param peak_old - The old peak - * @param instrNew -The new instrument - * @param T0 : - * @param L0 : - * @return The new peak with the new instrument( adjusted with the - *parameters) and time adjusted. - */ - static DataObjects::Peak createNewPeak(const Geometry::IPeak &peak_old, - Geometry::Instrument_sptr instrNew, - double T0, double L0); - -protected: - void init() override; - - /** - * Checks for out of bounds values , peaksWorkspace status - */ - void Check(DataObjects::PeaksWorkspace_sptr &pkwsp, const double *xValues, - const size_t nData, size_t &StartX, size_t &EndX) const; - - /** - * Gets the new instrument by applying parameters values to the old - *instrument - * @param peak A peak. Only used to get an old instrument from the 1st - *peak. - * - * @return A new instrument with the parameters applied. - */ - Geometry::Instrument_sptr getNewInstrument(const Geometry::IPeak &peak) const; - -private: - /** - * Even though constrains are used. Often very illogical parameters have to be - * processed. - * This checks for these conditions. - */ - double checkForNonsenseParameters() const; - - boost::shared_ptr<const Geometry::IComponent> findBank(std::string bankName); + const IFunction::Attribute &value) override; - std::map<std::string, boost::shared_ptr<const Geometry::IComponent>> - bankDetMap; + /// Move detectors with parameters + void moveDetector( + double x, double y, double z, double rotx, double roty, double rotz, + std::string detname, API::Workspace_sptr inputW) const; - /** - * Get the peaks workspace that was specified. - */ - void getPeaks() const; +private: + /// Call the appropriate load function + void load(const std::string &fname); - mutable boost::shared_ptr<DataObjects::PeaksWorkspace> m_peaks; + /// Load the points from a Workspace + void loadWorkspace(const std::string &wsName) const; - double a, b, c, alpha, beta, gamma; - int NGroups; - bool RotateCenters, SampleOffsets; - double SampleX, SampleY, SampleZ; + /// Load the points from a Workspace + void loadWorkspace(boost::shared_ptr<API::Workspace> ws) const; - std::string PeakName; //< SCDPanelErrors{PeakName} is name in the Analysis - // Data Service where the PeaksWorkspace is stored + /// Clear all data + void clear() const; - bool a_set, b_set, c_set, alpha_set, beta_set, gamma_set, PeakName_set, - BankNames_set, startX_set, endX_set, NGroups_set, sampleX_set, - sampleY_set, sampleZ_set; + /// Evaluate the function for a list of arguments and given scaling factor + void eval(double xrotate, double yrotate, double zrotate, double xshift, double yshift, double zshift, double *out, + const double *xValues, const size_t nData) const; - double tolerance; + /// Fill in the workspace and bank names + void setupData() const; - /// The OrientedLattice created from the parameters - boost::shared_ptr<Geometry::UnitCell> m_unitCell; + /// The default value for the workspace index + static const int defaultIndexValue; - std::string BankNames; + /// Temporary workspace holder + mutable boost::shared_ptr<API::Workspace> m_workspace; - int m_startX; ///<start index in xValues array in functionMW. -1 use all. - int m_endX; ///<end index in xValues array in functionMW. -1 use all. + /// Stores bank + mutable std::string m_bank; - std::vector<std::string> m_attrNames; + /// Flag of completing data setup + mutable bool m_setupFinished; - // ki-kf for Inelastic convention; kf-ki for Crystallography convention - std::string convention; }; -} -} + +} // namespace Crystal +} // namespace Mantid #endif /*MANTID_CRYSTAL_SCDPANELERRORS_H_*/ diff --git a/Framework/Crystal/src/PeakHKLErrors.cpp b/Framework/Crystal/src/PeakHKLErrors.cpp index 5e2849dc58b..90a0daced7a 100644 --- a/Framework/Crystal/src/PeakHKLErrors.cpp +++ b/Framework/Crystal/src/PeakHKLErrors.cpp @@ -10,13 +10,13 @@ #include "MantidGeometry/Crystal/IPeak.h" #include "MantidAPI/ParamFunction.h" #include "MantidCrystal/PeakHKLErrors.h" -#include "MantidCrystal/SCDPanelErrors.h" - +#include "MantidAPI/AnalysisDataService.h" #include <boost/math/special_functions/round.hpp> using namespace Mantid::DataObjects; using namespace Mantid::API; using namespace Mantid::Kernel; +using namespace Mantid::Kernel::Units; using Mantid::Geometry::CompAssembly; using Mantid::Geometry::IObjComponent_const_sptr; using Mantid::Geometry::IComponent_const_sptr; @@ -378,7 +378,7 @@ void PeakHKLErrors::function1D(double *out, const double *xValues, int runNum = peak_old.getRunNumber(); std::string runNumStr = std::to_string(runNum); Peak peak = - SCDPanelErrors::createNewPeak(peak_old, instNew, 0, peak_old.getL1()); + createNewPeak(peak_old, instNew, 0, peak_old.getL1()); size_t N = OptRuns.find("/" + runNumStr + "/"); if (N < OptRuns.size()) { @@ -471,7 +471,7 @@ void PeakHKLErrors::functionDeriv1D(Jacobian *out, const double *xValues, int peakNum = boost::math::iround(xValues[i]); IPeak &peak_old = Peaks->getPeak(peakNum); Peak peak = - SCDPanelErrors::createNewPeak(peak_old, instNew, 0, peak_old.getL1()); + createNewPeak(peak_old, instNew, 0, peak_old.getL1()); int runNum = peak_old.getRunNumber(); std::string runNumStr = std::to_string(runNum); @@ -623,5 +623,38 @@ void PeakHKLErrors::functionDeriv1D(Jacobian *out, const double *xValues, } } } + +Peak PeakHKLErrors::createNewPeak(const Geometry::IPeak &peak_old, + Geometry::Instrument_sptr instrNew, + double T0, double L0) { + Geometry::Instrument_const_sptr inst = peak_old.getInstrument(); + if (inst->getComponentID() != instrNew->getComponentID()) { + g_log.error("All peaks must have the same instrument"); + throw std::invalid_argument("All peaks must have the same instrument"); + } + + double T = peak_old.getTOF() + T0; + + int ID = peak_old.getDetectorID(); + + Kernel::V3D hkl = peak_old.getHKL(); + // peak_old.setDetectorID(ID); //set det positions + Peak peak(instrNew, ID, peak_old.getWavelength(), hkl, + peak_old.getGoniometerMatrix()); + + Wavelength wl; + + wl.initialize(L0, peak.getL2(), peak.getScattering(), 0, + peak_old.getInitialEnergy(), 0.0); + + peak.setWavelength(wl.singleFromTOF(T)); + peak.setIntensity(peak_old.getIntensity()); + peak.setSigmaIntensity(peak_old.getSigmaIntensity()); + peak.setRunNumber(peak_old.getRunNumber()); + peak.setBinCount(peak_old.getBinCount()); + + //!!!peak.setDetectorID(ID); + return peak; +} } } diff --git a/Framework/Crystal/src/SCDCalibratePanels.cpp b/Framework/Crystal/src/SCDCalibratePanels.cpp index 83b660caf27..e26b4df2994 100644 --- a/Framework/Crystal/src/SCDCalibratePanels.cpp +++ b/Framework/Crystal/src/SCDCalibratePanels.cpp @@ -9,10 +9,12 @@ #include "MantidAPI/IFunction.h" #include "MantidAPI/FunctionFactory.h" #include "MantidAPI/IFunction1D.h" +#include "MantidCrystal/SCDPanelErrors.h" #include <fstream> #include "MantidGeometry/Crystal/IndexingUtils.h" #include "MantidGeometry/Crystal/OrientedLattice.h" #include "MantidGeometry/Crystal/ReducedCell.h" +#include <boost/math/special_functions/round.hpp> #include <Poco/File.h> #include <sstream> @@ -605,9 +607,13 @@ void SCDCalibratePanels::exec() { } } } - - int nPeaks = peaksWs->getNumberPeaks(); - std::string cell_type = getProperty("CellType"); + IAlgorithm_sptr ub_alg; + try { + ub_alg = createChildAlgorithm("CalculateUMatrix", -1, -1, false); + } catch (Exception::NotFoundError &) { + g_log.error("Can't locate CalculateUMatrix algorithm"); + throw; + } double a = getProperty("a"); double b = getProperty("b"); double c = getProperty("c"); @@ -624,656 +630,80 @@ void SCDCalibratePanels::exec() { alpha = latt.alpha(); beta = latt.beta(); gamma = latt.gamma(); - } /*else { - boost::shared_ptr<Algorithm> alg = - createChildAlgorithm("FindUBUsingLatticeParameters", .2, .9, true); - alg->setProperty("PeaksWorkspace", peaksWs); - alg->setProperty("a", a); - alg->setProperty("b", b); - alg->setProperty("c", c); - alg->setProperty("alpha", alpha); - alg->setProperty("beta", beta); - alg->setProperty("gamma", gamma); - alg->setProperty("NumInitial", 15); - alg->setProperty("Tolerance", 0.12); - alg->executeAsChildAlg(); - }*/ - double tolerance = getProperty("tolerance"); - - string DetCalFileName = getProperty("DetCalFilename"); - if (Poco::File(DetCalFileName).exists()) - Poco::File(DetCalFileName).remove(); - - bool useL0 = getProperty("useL0"); - bool useTimeOffset = getProperty("useTimeOffset"); - int nIter = 1; - if (useL0 || useTimeOffset) - nIter = 2; - bool use_PanelWidth = getProperty("usePanelWidth"); - bool use_PanelHeight = getProperty("usePanelHeight"); - bool use_PanelPosition = getProperty("usePanelPosition"); - bool use_PanelOrientation = getProperty("usePanelOrientation"); - double SampleXoffset = getProperty("SampleXoffset"); - double SampleYoffset = getProperty("SampleYoffset"); - double SampleZoffset = getProperty("SampleZoffset"); - - string Grouping = getProperty("PanelGroups"); - string bankPrefix = getProperty("PanelNamePrefix"); - string bankingCode = getProperty("Grouping"); - - //----------------- Set Up Bank Name Vectors ------------------------- - set<string, compareBanks> AllBankNames; - for (int i = 0; i < nPeaks; ++i) - AllBankNames.insert(peaksWs->getPeak(i).getBankName()); - - vector<vector<string>> Groups; - CalculateGroups(AllBankNames, Grouping, bankPrefix, bankingCode, Groups); - - //----------------- Calculate & Create Calculated vs Theoretical - // workspaces------------------,); - int nGroups = static_cast<int>(AllBankNames.size()); - MatrixWorkspace_sptr ColWksp = - Mantid::API::WorkspaceFactory::Instance().create("Workspace2D", nGroups, - nPeaks, nPeaks); - MatrixWorkspace_sptr RowWksp = - Mantid::API::WorkspaceFactory::Instance().create("Workspace2D", nGroups, - nPeaks, nPeaks); - MatrixWorkspace_sptr TofWksp = - Mantid::API::WorkspaceFactory::Instance().create("Workspace2D", nGroups, - nPeaks, nPeaks); - nGroups = static_cast<int>(Groups.size()); - - double chisqSum = 0; - int NDofSum = 0; - if (!GoodStart(peaksWs, a, b, c, alpha, beta, gamma, tolerance)) { - g_log.warning() << "**** Indexing is NOT compatible with given lattice " - "parameters******\n"; - g_log.warning() - << " Index with conventional orientation matrix???\n"; } + ub_alg->setProperty("PeaksWorkspace", peaksWs); + ub_alg->setProperty("a", a); + ub_alg->setProperty("b", b); + ub_alg->setProperty("c", c); + ub_alg->setProperty("alpha", alpha); + ub_alg->setProperty("beta", beta); + ub_alg->setProperty("gamma", gamma); + ub_alg->executeAsChildAlg(); - //----------- Initialize peaksWorkspace, initial parameter values - // etc.--------- - boost::shared_ptr<const Instrument> instrument = - peaksWs->getPeak(0).getInstrument(); - - // Time offset from property - const API::Run &run = peaksWs->run(); - double T0 = 0.0; - if (run.hasProperty("T0")) { - Kernel::Property *prop = run.getProperty("T0"); - T0 = boost::lexical_cast<double, std::string>(prop->value()); - if (T0 != 0) { - g_log.notice() << "T0 = " << T0 << '\n'; + for (int i = int(peaksWs->getNumberPeaks()) - 1; i >= 0; --i) { + Peak peak = peaksWs->getPeak(i); + if (peak.getHKL() == V3D(0,0,0) || peak.getBankName() != "bank13") { + peaksWs->removePeak(i); } } - if ((string)getProperty("PreProcessInstrument") == - "C)Apply a LoadParameter.xml type file") - T0 = getProperty("InitialTimeOffset"); //!***** - - double L0 = peaksWs->getPeak(0).getL1(); - std::ofstream outfile(DetCalFileName); - g_log.debug() << "Initial L0,T0=" << L0 << "," << T0 << '\n'; - std::vector<std::string> detcal; - - for (auto iIter = 0; iIter != nIter; ++iIter) { - detcal.clear(); - PARALLEL_FOR1(peaksWs) - for (int iGr = 0; iGr < nGroups; iGr++) { - PARALLEL_START_INTERUPT_REGION - auto group = Groups.begin() + iGr; - vector<string> banksVec; - for (auto &bankName : *group) { - banksVec.push_back(bankName); - } - //------------------ Set Up Workspace for IFitFunction Fit--------------- - vector<int> bounds; - Workspace2D_sptr ws = calcWorkspace(peaksWs, banksVec, tolerance, bounds); - double T0_bank = T0; - double L0_bank = L0; - boost::shared_ptr<const Instrument> PreCalibinstrument = - GetNewCalibInstrument(instrument, - (string)getProperty("PreProcessInstrument"), - (string)getProperty("PreProcFilename"), T0_bank, - L0_bank, banksVec); - V3D samplePos = - peaksWs->getPeak(0).getInstrument()->getSample()->getPos(); - - string PeakWSName = getPropertyValue("PeakWorkspace"); - if (PeakWSName.length() < 1) { - PeakWSName = "xxx"; - AnalysisDataService::Instance().addOrReplace("xxx", peaksWs); - } - - int NGroups = 1; //(int)Groups.size(); - double detWidthScale0, detHeightScale0, Xoffset0, Yoffset0, Zoffset0, - Xrot0, Yrot0, Zrot0; - - //------------------- For each Group set up Function, - //-------------------------- - //---------------Ties, and Constraint Properties for Fit - // algorithm-------------------- - - // set up the string for specifying groups - string BankNameString; - // for (auto group = Groups.begin(); group != Groups.end(); ++group) { - // if (group != Groups.begin()) - // BankNameString += "!"; - for (auto bank = group->begin(); bank != group->end(); ++bank) { - if (bank != group->begin()) - BankNameString += "/"; - - BankNameString += (*bank); - } - //} - - int RotGroups = 0; - if (getProperty("RotateCenters")) - RotGroups = 1; - int SampOffsets = 0; - if (getProperty("AllowSampleShift")) - SampOffsets = 1; - - // first round of function setup - IFunction_sptr iFunc = - FunctionFactory::Instance().createFunction("SCDPanelErrors"); - iFunc->setAttributeValue("PeakWorkspaceName", PeakWSName); - iFunc->setAttributeValue("a", a); - iFunc->setAttributeValue("b", b); - iFunc->setAttributeValue("c", c); - iFunc->setAttributeValue("alpha", alpha); - iFunc->setAttributeValue("beta", beta); - iFunc->setAttributeValue("gamma", gamma); - iFunc->setAttributeValue("NGroups", NGroups); - iFunc->setAttributeValue("BankNames", BankNameString); - iFunc->setAttributeValue("startX", -1); - iFunc->setAttributeValue("endX", -1); - iFunc->setAttributeValue("RotateCenters", RotGroups); - iFunc->setAttributeValue("SampleOffsets", SampOffsets); - iFunc->setParameter("l0", L0_bank); - iFunc->setParameter("t0", T0_bank); - - double maxXYOffset = getProperty("MaxPositionChange_meters"); - - boost::shared_ptr<const RectangularDetector> bank_rect; - - string name = group->front(); - boost::shared_ptr<const IComponent> bank_cmp = - instrument->getComponentByName(name); - bank_rect = - boost::dynamic_pointer_cast<const RectangularDetector>(bank_cmp); - - if (!bank_rect) { - g_log.error("No Rectangular detector bank " + banksVec[0] + - " in instrument"); - throw invalid_argument("No Rectangular detector bank " + banksVec[0] + - " in instrument"); - } - - // if( it1 == (*itv).begin()) - CalcInitParams(bank_rect, instrument, PreCalibinstrument, detWidthScale0, - detHeightScale0, Xoffset0, Yoffset0, Zoffset0, Xrot0, - Yrot0, Zrot0); - - // --- set Function property ---------------------- - iFunc->setParameter("f0_detWidthScale", detWidthScale0); - iFunc->setParameter("f0_detHeightScale", detHeightScale0); - iFunc->setParameter("f0_Xoffset", Xoffset0); - iFunc->setParameter("f0_Yoffset", Yoffset0); - iFunc->setParameter("f0_Zoffset", Zoffset0); - iFunc->setParameter("f0_Xrot", Xrot0); - iFunc->setParameter("f0_Yrot", Yrot0); - iFunc->setParameter("f0_Zrot", Zrot0); - - set<string> MyBankNames; - for (int i = 0; i < nPeaks; ++i) - MyBankNames.insert(banksVec[0]); - int startX = bounds[0]; - int endXp1 = bounds[group->size()]; - if (endXp1 - startX < 13) { - g_log.error() << "Bank Group " << BankNameString - << " does not have enough peaks for fitting\n"; - saveIsawDetCal(instrument, MyBankNames, T0_bank, - DetCalFileName + std::to_string(iGr)); - continue; - } - - //---------- setup ties ---------------------------------- - tie(iFunc, !use_PanelWidth, "f0_detWidthScale", detWidthScale0); - tie(iFunc, !use_PanelHeight, "f0_detHeightScale", detHeightScale0); - tie(iFunc, !use_PanelPosition, "f0_Xoffset", Xoffset0); - tie(iFunc, !use_PanelPosition, "f0_Yoffset", Yoffset0); - tie(iFunc, !use_PanelPosition, "f0_Zoffset", Zoffset0); - tie(iFunc, !use_PanelOrientation, "f0_Xrot", Xrot0); - tie(iFunc, !use_PanelOrientation, "f0_Yrot", Yrot0); - tie(iFunc, !use_PanelOrientation, "f0_Zrot", Zrot0); - - //--------------- setup constraints ------------------------------ - constrain(iFunc, "l0", (MIN_DET_HW_SCALE * L0_bank), - (MAX_DET_HW_SCALE * L0_bank)); - constrain(iFunc, "t0", -5., 5.); - - constrain(iFunc, "f0_detWidthScale", MIN_DET_HW_SCALE * detWidthScale0, - MAX_DET_HW_SCALE * detWidthScale0); - constrain(iFunc, "f0_detHeightScale", MIN_DET_HW_SCALE * detHeightScale0, - MAX_DET_HW_SCALE * detHeightScale0); - constrain(iFunc, "f0_Xoffset", -1. * maxXYOffset + Xoffset0, - maxXYOffset + Xoffset0); - constrain(iFunc, "f0_Yoffset", -1. * maxXYOffset + Yoffset0, - maxXYOffset + Yoffset0); - constrain(iFunc, "f0_Zoffset", -1. * maxXYOffset + Zoffset0, - maxXYOffset + Zoffset0); - - double MaxRotOffset = getProperty("MaxRotationChangeDegrees"); - constrain(iFunc, "f0_Xrot", -1. * MaxRotOffset, MaxRotOffset); - constrain(iFunc, "f0_Yrot", -1. * MaxRotOffset, MaxRotOffset); - constrain(iFunc, "f0_Zrot", -1. * MaxRotOffset, MaxRotOffset); - //} // for vector< string > in Groups - - // Function supports setting the sample position even when it isn't be - // refined - iFunc->setAttributeValue("SampleX", samplePos.X() + SampleXoffset); - iFunc->setAttributeValue("SampleY", samplePos.Y() + SampleYoffset); - iFunc->setAttributeValue("SampleZ", samplePos.Z() + SampleZoffset); - - // Constraints for sample offsets - if (getProperty("AllowSampleShift")) { - maxXYOffset = getProperty("MaxSamplePositionChangeMeters"); - constrain(iFunc, "SampleX", samplePos.X() + SampleXoffset - maxXYOffset, - samplePos.X() + SampleXoffset + maxXYOffset); - constrain(iFunc, "SampleY", samplePos.Y() + SampleYoffset - maxXYOffset, - samplePos.Y() + SampleYoffset + maxXYOffset); - constrain(iFunc, "SampleZ", samplePos.Z() + SampleZoffset - maxXYOffset, - samplePos.Z() + SampleZoffset + maxXYOffset); - } else { - tie(iFunc, true, "SampleX", samplePos.X() + SampleXoffset); - tie(iFunc, true, "SampleY", samplePos.Y() + SampleYoffset); - tie(iFunc, true, "SampleZ", samplePos.Z() + SampleZoffset); - } - - tie(iFunc, !useL0, "l0", L0_bank); - tie(iFunc, !useTimeOffset, "t0", T0_bank); - - //--------------------- Set up Fit Algorithm and - // Execute------------------- - boost::shared_ptr<Algorithm> fit_alg = - createChildAlgorithm("Fit", .2, .9, true); - - if (!fit_alg) - throw invalid_argument("Cannot find Fit algorithm"); - fit_alg->initialize(); - - int Niterations = getProperty("NumIterations"); - std::string minimizerError = getProperty("MinimizerError"); - std::string minimizer = getProperty("Minimizer"); - fit_alg->setProperty("Function", iFunc); - fit_alg->setProperty("MaxIterations", Niterations); - fit_alg->setProperty("InputWorkspace", ws); - fit_alg->setProperty("Output", "out"); - fit_alg->setProperty("CreateOutput", true); - fit_alg->setProperty("CalcErrors", false); - fit_alg->setPropertyValue("Minimizer", minimizer + ",AbsError=" + - minimizerError + ",RelError=" + - minimizerError); - fit_alg->executeAsChildAlg(); - - PARALLEL_CRITICAL(afterFit) { - MatrixWorkspace_sptr fitWS = fit_alg->getProperty("OutputWorkspace"); - // AnalysisDataService::Instance().addOrReplace("out"+boost::lexical_cast<std::string>(iGr), - // fitWS); - g_log.debug() << "Finished executing Fit algorithm\n"; - string OutputStatus = fit_alg->getProperty("OutputStatus"); - g_log.notice() << BankNameString << " Output Status=" << OutputStatus - << "\n"; - - //--------------------- Get and Process Results ----------------------- - double chisq = fit_alg->getProperty("OutputChi2overDoF"); - chisqSum += chisq; - - if (chisq > 1) { - g_log.warning() << "************* This is a large chi squared value " - "************\n"; - g_log.warning() - << " the indexing may have been using an incorrect\n"; - g_log.warning() << " orientation matrix, instrument geometry or " - "goniometer info\n"; - } - ITableWorkspace_sptr RRes = fit_alg->getProperty("OutputParameters"); - vector<double> params; - vector<double> errs; - vector<string> names; - double sigma = sqrt(chisq); - - if (chisq < 0 || chisq != chisq) - sigma = -1; - string fieldBaseNames = - ";l0;t0;detWidthScale;detHeightScale;Xoffset;Yoffset;" - "Zoffset;Xrot;Yrot;Zrot;"; - if (getProperty("AllowSampleShift")) - fieldBaseNames += "SampleX;SampleY;SampleZ;"; - for (size_t prm = 0; prm < RRes->rowCount(); ++prm) { - string namee = RRes->getRef<string>("Name", prm); - size_t dotPos = namee.find('_'); - if (dotPos >= namee.size()) - dotPos = 0; - else - dotPos++; - string Field = namee.substr(dotPos); - size_t FieldNum = fieldBaseNames.find(";" + Field + ";"); - if (FieldNum > fieldBaseNames.size()) - continue; - if (dotPos != 0) { - int col = atoi(namee.substr(1, dotPos).c_str()); - if (col < 0 || col >= NGroups) - continue; - } - names.push_back(namee); - params.push_back(RRes->getRef<double>("Value", prm)); - double err = RRes->getRef<double>("Error", prm); - errs.push_back(sigma * err); - } - - //------------------- Report chi^2 value -------------------- - int nVars = 8; // NGroups; - - if (!use_PanelWidth) - nVars--; - if (!use_PanelHeight) - nVars--; - if (!use_PanelPosition) - nVars -= 3; - if (!use_PanelOrientation) - nVars -= 3; - nVars *= NGroups; - nVars += 2; - - if (!useL0) - nVars--; - if (!useTimeOffset) - nVars--; - - // g_log.notice() << " nVars=" <<nVars<< '\n'; - int NDof = (static_cast<int>(ws->dataX(0).size()) - nVars); - NDofSum = +NDof; - - map<string, double> result; - - for (size_t i = 0; i < min<size_t>(params.size(), names.size()); ++i) { - result[names[i]] = params[i]; - } - - g_log.notice() << BankNameString << " ChiSqoverDoF =" << chisq - << " NDof =" << NDof << " l0 = " << result["l0"] - << " T0 = " << result["t0"] - << " peaks = " << endXp1 - startX << "\n"; - - //--------------------- Create Result Table Workspace------------------- - this->progress(.92, "Creating Results table"); - createResultWorkspace(nGroups, iGr + 1, names, params, errs); - - //---------------- Create new instrument with ------------------------ - //--------------new parameters to SAVE to files--------------------- - - auto pmap = boost::make_shared<ParameterMap>(); - boost::shared_ptr<const ParameterMap> pmapOld = - instrument->getParameterMap(); - boost::shared_ptr<const Instrument> NewInstrument = - boost::make_shared<Instrument>(instrument->baseInstrument(), pmap); - - boost::shared_ptr<const RectangularDetector> bank_rect; - double rotx, roty, rotz; - - rotx = result["f0_Xrot"]; - roty = result["f0_Yrot"]; - rotz = result["f0_Zrot"]; - - Quat newRelRot = Quat(rotx, V3D(1, 0, 0)) * Quat(roty, V3D(0, 1, 0)) * - Quat(rotz, V3D(0, 0, 1)); //*RelRot; - - FixUpBankParameterMap((banksVec), NewInstrument, - V3D(result["f0_Xoffset"], result["f0_Yoffset"], - result["f0_Zoffset"]), - newRelRot, result["f0_detWidthScale"], - result["f0_detHeightScale"], pmapOld, - getProperty("RotateCenters")); - - //} // For @ group - - V3D sampPos( - NewInstrument->getSample()->getPos()); // should be (0,0,0)??? - if (getProperty("AllowSampleShift")) - sampPos = - V3D(result["SampleX"], result["SampleY"], result["SampleZ"]); + int nPeaks = peaksWs->getNumberPeaks(); - FixUpSourceParameterMap(NewInstrument, result["l0"], sampPos, pmapOld); + MatrixWorkspace_sptr q3DWS = boost::dynamic_pointer_cast<MatrixWorkspace>( + API::WorkspaceFactory::Instance().create("Workspace2D", 1, + nPeaks*3, nPeaks*3)); - //---------------------- Save new instrument to DetCal-------------- - this->progress(.94, "Saving detcal file"); - saveIsawDetCal(NewInstrument, MyBankNames, result["t0"], - DetCalFileName + std::to_string(iGr)); - } - PARALLEL_END_INTERUPT_REGION - } - PARALLEL_CHECK_INTERUPT_REGION - std::vector<double> l0vec, t0vec; - std::string line, seven; - for (int iGr = 0; iGr < nGroups; iGr++) { - std::ifstream infile(DetCalFileName + std::to_string(iGr)); - while (std::getline(infile, line)) { - if (iGr == 0 && iIter == nIter - 1) { - if (line[0] == '#' || line[0] == '6') - outfile << line << "\n"; - } - if (line[0] == '7') { - double L0bank, T0bank; - std::stringstream(line) >> seven >> L0bank >> T0bank; - l0vec.push_back(L0bank); - t0vec.push_back(T0bank); - } else if (line[0] == '5') - detcal.push_back(line); - } - infile.close(); - if (Poco::File(DetCalFileName + std::to_string(iGr)).exists()) - Poco::File(DetCalFileName + std::to_string(iGr)).remove(); - } - if (useL0) { - removeOutliers(l0vec); - Statistics stats = getStatistics(l0vec); - L0 = stats.mean * 0.01; // cm when read from file - useL0 = false; - } - if (useTimeOffset) { - removeOutliers(t0vec); - Statistics stats = getStatistics(t0vec); - T0 = stats.mean; - // set T0 in the run parameters - API::Run &m_run = peaksWs->mutableRun(); - m_run.addProperty<double>("T0", T0, true); - useTimeOffset = false; - } - } - L0 *= 100; // ISAW uses cm - outfile << "7 " << std::setprecision(4) << std::fixed << L0; - outfile << std::setw(13) << std::setprecision(3) << T0 << '\n'; - outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX " - " CenterY CenterZ BaseX BaseY BaseZ UpX UpY " - " UpZ\n"; - for (vector<std::string>::const_iterator itdet = detcal.begin(); - itdet != detcal.end(); ++itdet) - outfile << *itdet << "\n"; - outfile.close(); - - setProperty("ColWorkspace", ColWksp); - setProperty("RowWorkspace", RowWksp); - setProperty("TofWorkspace", TofWksp); - setProperty("ChiSqOverDOF", chisqSum); - setProperty("DOF", NDofSum); - - set<string> bankNames; - for (int i = 0; i < nPeaks; ++i) { - IPeak &peak = peaksWs->getPeak(i); - instrument = peak.getInstrument(); - LoadISawDetCal(instrument, bankNames, T0, L0, DetCalFileName, "bank"); - peak.setInstrument(instrument); - peak.setDetectorID(peak.getDetectorID()); - } + auto &outSpec = q3DWS->getSpectrum(0); + MantidVec &yVec = outSpec.dataY(); + MantidVec &xVec = outSpec.dataX(); - //-----------------------Save new instrument to xml(for LoadParameterFile) - // files---------- - this->progress(.96, "Saving xml param file"); - string XmlFileName = getProperty("XmlFilename"); - saveXmlFile(XmlFileName, Groups, peaksWs->getInstrument()); - - IFunction_sptr fn = - FunctionFactory::Instance().createFunction("LatticeFunction"); - fn->setAttributeValue("LatticeSystem", cell_type); - fn->addTies("ZeroShift=0.0"); - fn->setParameter("a", a); - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::MONOCLINIC() || - cell_type == ReducedCell::ORTHORHOMBIC()) { - fn->setParameter("b", b); - } - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::TETRAGONAL() || - cell_type == ReducedCell::ORTHORHOMBIC() || - cell_type == ReducedCell::HEXAGONAL() || - cell_type == ReducedCell::MONOCLINIC()) { - fn->setParameter("c", c); - } - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::RHOMBOHEDRAL()) { - fn->setParameter("Alpha", alpha); - } - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::MONOCLINIC()) { - fn->setParameter("Beta", beta); - } - if (cell_type == ReducedCell::TRICLINIC()) { - fn->setParameter("Gamma", gamma); + OrientedLattice lattice = peaksWs->mutableSample().getOrientedLattice(); + for (int i = 0; i < nPeaks; i++) { + Peak peak = peaksWs->getPeak(i); + V3D hkl = V3D(boost::math::iround(peak.getH()), boost::math::iround(peak.getK()), + boost::math::iround(peak.getL())); + V3D Q2 = lattice.qFromHKL(hkl); + xVec[i*3] = i*3; + xVec[i*3+1] = i*3+1; + xVec[i*3+2] = i*3+2; + yVec[i*3] = Q2.X(); + yVec[i*3+1] = Q2.Y(); + yVec[i*3+2] = Q2.Z(); } - IAlgorithm_sptr fit = - Mantid::API::AlgorithmFactory::Instance().create("Fit", -1); - fit->initialize(); - fit->setChild(true); - fit->setLogging(false); - fit->setProperty("Function", fn); - fit->setProperty("InputWorkspace", peaksWs); - fit->setProperty("CostFunction", "Unweighted least squares"); - fit->setProperty("CreateOutput", true); - fit->execute(); - - IAlgorithm_sptr ub_alg; + IAlgorithm_sptr fit_alg; try { - ub_alg = createChildAlgorithm("CalculateUMatrix", -1, -1, false); + fit_alg = createChildAlgorithm("Fit", -1, -1, false); } catch (Exception::NotFoundError &) { - g_log.error("Can't locate CalculateUMatrix algorithm"); + g_log.error("Can't locate Fit algorithm"); throw; } + std::ostringstream fun_str; + fun_str << "name=SCDPanelErrors,Workspace="<<peaksWs->name()<<",Bank=bank13"; + fit_alg->setPropertyValue("Function", fun_str.str()); + fit_alg->setProperty("InputWorkspace", q3DWS); + fit_alg->setProperty("CreateOutput", true); + fit_alg->setProperty("Output", "fit"); + fit_alg->setProperty("MaxIterations", 0); + fit_alg->executeAsChildAlg(); + MatrixWorkspace_sptr fitWS = fit_alg->getProperty("OutputWorkspace"); + AnalysisDataService::Instance().addOrReplace("fit", fitWS); + ITableWorkspace_sptr paramsWS = fit_alg->getProperty("OutputParameters"); + AnalysisDataService::Instance().addOrReplace("params", paramsWS); + double xShift = paramsWS->getRef<double>("Value",0); + double yShift = paramsWS->getRef<double>("Value",1); + double zShift = paramsWS->getRef<double>("Value",2); + double xRotate = paramsWS->getRef<double>("Value",3); + double yRotate = paramsWS->getRef<double>("Value",4); + double zRotate = paramsWS->getRef<double>("Value",5); + SCDPanelErrors det; + det.moveDetector(xShift, yShift, zShift, xRotate, yRotate, zRotate, "bank13", peaksWs); - ub_alg->setProperty("PeaksWorkspace", peaksWs); - ub_alg->setProperty("a", fn->getParameter("a")); - double sigabc[6]; - sigabc[0] = fn->getError(0); - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::MONOCLINIC() || - cell_type == ReducedCell::ORTHORHOMBIC()) { - ub_alg->setProperty("b", fn->getParameter("b")); - sigabc[1] = fn->getError(1); - } else { - ub_alg->setProperty("b", fn->getParameter("a")); - sigabc[1] = fn->getError(0); - } - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::TETRAGONAL() || - cell_type == ReducedCell::ORTHORHOMBIC() || - cell_type == ReducedCell::HEXAGONAL() || - cell_type == ReducedCell::MONOCLINIC()) { - ub_alg->setProperty("c", fn->getParameter("c")); - sigabc[2] = fn->getError(2); - } else { - ub_alg->setProperty("c", fn->getParameter("a")); - sigabc[2] = fn->getError(0); - } - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::RHOMBOHEDRAL()) { - ub_alg->setProperty("alpha", fn->getParameter("Alpha")); - sigabc[3] = fn->getError(3); - } else { - ub_alg->setProperty("alpha", 90.0); - sigabc[3] = 0.0; - } - if (cell_type == ReducedCell::TRICLINIC() || - cell_type == ReducedCell::MONOCLINIC()) { - ub_alg->setProperty("beta", fn->getParameter("Beta")); - sigabc[4] = fn->getError(4); - } else { - ub_alg->setProperty("beta", 90.0); - sigabc[4] = 0.0; - } - if (cell_type == ReducedCell::TRICLINIC()) { - ub_alg->setProperty("gamma", fn->getParameter("Gamma")); - sigabc[5] = fn->getError(5); - } else if (cell_type == ReducedCell::HEXAGONAL()) { - ub_alg->setProperty("gamma", 120.0); - sigabc[5] = 0.0; - } else { - ub_alg->setProperty("gamma", 90.0); - sigabc[5] = 0.0; - } - ub_alg->executeAsChildAlg(); - OrientedLattice lattice = peaksWs->mutableSample().getOrientedLattice(); - DblMatrix UB = lattice.getUB(); - lattice.setError(sigabc[0], sigabc[1], sigabc[2], sigabc[3], sigabc[4], - sigabc[5]); - peaksWs->mutableSample().setOrientedLattice(&lattice); - g_log.notice() << "Lattice after optimization: " << lattice << "\n"; - - // We must sort the peaks - // std::vector<std::pair<std::string, bool>> criteria; - // criteria.push_back(std::pair<std::string, bool>("BankName", true)); - criteria.push_back(std::pair<std::string, bool>("RunNumber", true)); - criteria.push_back(std::pair<std::string, bool>("h", true)); - criteria.push_back(std::pair<std::string, bool>("k", true)); - criteria.push_back(std::pair<std::string, bool>("l", true)); - peaksWs->sort(criteria); - - // create table of theoretical vs calculated - int bankLast = -1; - int iSpectrum = -1; - int icount = 0; - - for (int j = 0; j < nPeaks; ++j) { - const Geometry::IPeak &peak = peaksWs->getPeak(j); - string bankName = peak.getBankName(); - size_t k = bankName.find_last_not_of("0123456789"); - int bank = 0; - if (k < bankName.length()) - bank = boost::lexical_cast<int>(bankName.substr(k + 1)); - if (bank != bankLast) { - iSpectrum++; - ColWksp->getSpectrum(iSpectrum).setSpectrumNo(specnum_t(bank)); - RowWksp->getSpectrum(iSpectrum).setSpectrumNo(specnum_t(bank)); - TofWksp->getSpectrum(iSpectrum).setSpectrumNo(specnum_t(bank)); - bankLast = bank; - icount = 0; - } - - try { - V3D q_lab = (peak.getGoniometerMatrix() * UB) * peak.getHKL() * M_2_PI; - Peak theoretical(peak.getInstrument(), q_lab); - ColWksp->dataX(iSpectrum)[icount] = peak.getCol(); - ColWksp->dataY(iSpectrum)[icount] = theoretical.getCol(); - RowWksp->dataX(iSpectrum)[icount] = peak.getRow(); - RowWksp->dataY(iSpectrum)[icount] = theoretical.getRow(); - TofWksp->dataX(iSpectrum)[icount] = peak.getTOF(); - TofWksp->dataY(iSpectrum)[icount] = theoretical.getTOF(); - icount++; - } catch (...) { - // g_log.debug() << "Problem only in printing peaks\n"; - } - } + string DetCalFileName = getProperty("DetCalFilename"); + set<string> MyBankNames; + MyBankNames.insert("bank13"); + Instrument_sptr inst = boost::const_pointer_cast<Instrument>(peaksWs->getInstrument()); + saveIsawDetCal(inst, MyBankNames, 0.0, + DetCalFileName); } /** @@ -1487,7 +917,7 @@ void SCDCalibratePanels::createResultWorkspace(const int numGroups, Result->cell<double>(rowNum + 10 + nn, colNum) = errs[p]; } - setProperty("ResultWorkspace", Result); + //setProperty("ResultWorkspace", Result); } /** @@ -1501,7 +931,7 @@ void SCDCalibratePanels::createResultWorkspace(const int numGroups, * @param filename -The name of the DetCal file to save the results to */ void SCDCalibratePanels::saveIsawDetCal( - boost::shared_ptr<const Instrument> &instrument, set<string> &AllBankName, + boost::shared_ptr<Instrument> &instrument, set<string> &AllBankName, double T0, string filename) { // having a filename triggers doing the work if (filename.empty()) @@ -1629,7 +1059,7 @@ void SCDCalibratePanels::init() { "Path to an Mantid .xml description(for LoadParameterFile) file to " "save."); - declareProperty( + /*declareProperty( Kernel::make_unique<WorkspaceProperty<ITableWorkspace>>( "ResultWorkspace", "ResultWorkspace", Kernel::Direction::Output), "Workspace of Results"); @@ -1647,15 +1077,15 @@ void SCDCalibratePanels::init() { declareProperty( Kernel::make_unique<WorkspaceProperty<MatrixWorkspace>>( "TofWorkspace", "TofWorkspace", Kernel::Direction::Output), - "Workspace comparing calculated and theoretical TOF of each peak."); + "Workspace comparing calculated and theoretical TOF of each peak.");*/ const string OUTPUTS("Outputs"); setPropertyGroup("DetCalFilename", OUTPUTS); setPropertyGroup("XmlFilename", OUTPUTS); - setPropertyGroup("ResultWorkspace", OUTPUTS); + /*setPropertyGroup("ResultWorkspace", OUTPUTS); setPropertyGroup("ColWorkspace", OUTPUTS); setPropertyGroup("RowWorkspace", OUTPUTS); - setPropertyGroup("TofWorkspace", OUTPUTS); + setPropertyGroup("TofWorkspace", OUTPUTS);*/ //------------------------------------ Tolerance // settings------------------------- diff --git a/Framework/Crystal/src/SCDPanelErrors.cpp b/Framework/Crystal/src/SCDPanelErrors.cpp index b1a2a2a48b6..47cc7b06634 100644 --- a/Framework/Crystal/src/SCDPanelErrors.cpp +++ b/Framework/Crystal/src/SCDPanelErrors.cpp @@ -1,711 +1,286 @@ +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- #include "MantidCrystal/SCDPanelErrors.h" -#include "MantidCrystal/SCDCalibratePanels.h" +#include "MantidKernel/FileValidator.h" +#include "MantidAPI/Algorithm.h" +#include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/FunctionFactory.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidGeometry/Crystal/OrientedLattice.h" -#include "MantidGeometry/Crystal/IndexingUtils.h" -#include "MantidKernel/ConfigService.h" - -using namespace Mantid::API; -using namespace Mantid::DataObjects; -using namespace Mantid::Geometry; -using namespace Mantid::Kernel; -using namespace Mantid::Kernel::Units; -using std::invalid_argument; -using std::logic_error; -using std::map; -using std::runtime_error; -using std::setw; -using std::string; -using std::vector; - -// TODO: add const's and & to arguments. PeaksWorkspace_ptr should be const_ptr +#include "MantidGeometry/Instrument.h" +#include "MantidDataObjects/PeaksWorkspace.h" +#include "MantidDataObjects/Peak.h" +#include <algorithm> +#include <cmath> +#include <fstream> +#include <sstream> namespace Mantid { namespace Crystal { -namespace { -Kernel::Logger g_log("SCDPanelErrors"); -} - -DECLARE_FUNCTION(SCDPanelErrors) - -// Assumes UB from optimize UB maps hkl to qxyz/2PI. So conversion factors to an -// from -// UB ified q's are below. - -namespace { // anonymous namespace -// static const double ONE_OVER_TWO_PI = 1. / M_2_PI; -const string LATTICE_A("a"); -const string LATTICE_B("b"); -const string LATTICE_C("c"); -const string LATTICE_ALPHA("alpha"); -const string LATTICE_BETA("beta"); -const string LATTICE_GAMMA("gamma"); -const string BANK_NAMES("BankNames"); -const string NUM_GROUPS("NGroups"); -const string X_START("startX"); -const string X_END("endX"); -const string PEAKS_WKSP("PeakWorkspaceName"); -const string ROTATE_CEN("RotateCenters"); -const string SAMPLE_OFF("SampleOffsets"); -const string SAMPLE_X("SampleX"); -const string SAMPLE_Y("SampleY"); -const string SAMPLE_Z("SampleZ"); -} - -void initializeAttributeList(vector<string> &attrs) { - attrs.clear(); - attrs.push_back(LATTICE_A); - attrs.push_back(LATTICE_B); - attrs.push_back(LATTICE_C); - attrs.push_back(LATTICE_ALPHA); - attrs.push_back(LATTICE_BETA); - attrs.push_back(LATTICE_GAMMA); - attrs.push_back(PEAKS_WKSP); - attrs.push_back(BANK_NAMES); - attrs.push_back(X_START); - attrs.push_back(X_END); - attrs.push_back(NUM_GROUPS); - attrs.push_back(ROTATE_CEN); - attrs.push_back(SAMPLE_OFF); - attrs.push_back(SAMPLE_X); - attrs.push_back(SAMPLE_Y); - attrs.push_back(SAMPLE_Z); -} - -SCDPanelErrors::SCDPanelErrors() - : API::ParamFunction(), IFunction1D(), tolerance(.6), m_startX(-1), - m_endX(-1) { - convention = Kernel::ConfigService::Instance().getString("Q.convention"); - initializeAttributeList(m_attrNames); - - SampleX = SampleY = SampleZ = 0.; - - a_set = b_set = c_set = alpha_set = beta_set = gamma_set = PeakName_set = - BankNames_set = endX_set = startX_set = NGroups_set = sampleX_set = - sampleY_set = sampleZ_set = false; - - // g_log.setLevel(7); - - BankNames = ""; - - PeakName = ""; - - a = b = c = alpha = beta = gamma = 0; - - NGroups = 1; - RotateCenters = false; - SampleOffsets = false; -} - -size_t SCDPanelErrors::nAttributes() const { return m_attrNames.size(); } - -std::vector<std::string> SCDPanelErrors::getAttributeNames() const { - return m_attrNames; -} - -IFunction::Attribute -SCDPanelErrors::getAttribute(const std::string &attName) const { - if (!hasAttribute(attName)) - throw std::invalid_argument("Not a valid attribute name \"" + attName + - "\""); - if (attName == LATTICE_A) - return Attribute(a); - if (attName == LATTICE_B) - return Attribute(b); - if (attName == LATTICE_C) - return Attribute(c); - if (attName == LATTICE_ALPHA) - return Attribute(alpha); - if (attName == LATTICE_BETA) - return Attribute(beta); - if (attName == LATTICE_GAMMA) - return Attribute(gamma); - if (attName == (BANK_NAMES)) - return Attribute(BankNames); - else if (attName == PEAKS_WKSP) - return Attribute(PeakName); - else if (attName == NUM_GROUPS) - return Attribute(NGroups); - else if (attName == ROTATE_CEN) { - if (RotateCenters) - return Attribute(1); - else - return Attribute(0); - } else if (attName == SAMPLE_OFF) { - if (SampleOffsets) +using namespace CurveFitting; - return Attribute(1); - else - return Attribute(0); - } else if (attName == X_START) - return Attribute(static_cast<int>(m_startX)); - else if (attName == X_END) - return Attribute(static_cast<int>(m_endX)); - else if (attName == SAMPLE_X) - return Attribute(SampleX); - else if (attName == SAMPLE_Y) - return Attribute(SampleY); - else if (attName == SAMPLE_Z) - return Attribute(SampleZ); +using namespace Kernel; - throw std::invalid_argument("Not a valid attribute name \"" + attName + "\""); -} +using namespace API; -bool SCDPanelErrors::hasAttribute(const std::string &attName) const { - return (std::find(m_attrNames.begin(), m_attrNames.end(), attName) != - m_attrNames.end()); +namespace { +/// static logger +Logger g_log("SCDPanelErrors"); } -SCDPanelErrors::SCDPanelErrors(DataObjects::PeaksWorkspace_sptr &pwk, - std::string &Component_name, double ax, - double bx, double cx, double alphax, - double betax, double gammax, double tolerance1) - : API::ParamFunction(), IFunction1D() { - initializeAttributeList(m_attrNames); - - m_peaks = pwk; - BankNames = Component_name; - - tolerance = tolerance1; - NGroups = 1; - a_set = b_set = c_set = alpha_set = beta_set = gamma_set = PeakName_set = - BankNames_set = endX_set = startX_set = NGroups_set = false; - - setAttribute(LATTICE_A, Attribute(ax)); - setAttribute(LATTICE_B, Attribute(bx)); - setAttribute(LATTICE_C, Attribute(cx)); - setAttribute(LATTICE_ALPHA, Attribute(alphax)); - setAttribute(LATTICE_BETA, Attribute(betax)); - setAttribute(LATTICE_GAMMA, Attribute(gammax)); +DECLARE_FUNCTION(SCDPanelErrors) - setAttribute(PEAKS_WKSP, Attribute("xxx")); - setAttribute(BANK_NAMES, Attribute(Component_name)); - setAttribute(X_START, Attribute(-1)); - setAttribute(X_END, Attribute(-1)); - setAttribute(ROTATE_CEN, Attribute(0)); - setAttribute(SAMPLE_OFF, Attribute(0)); - setAttribute(SAMPLE_X, Attribute(0.0)); - setAttribute(SAMPLE_Y, Attribute(0.0)); - setAttribute(SAMPLE_Z, Attribute(0.0)); - init(); +const int SCDPanelErrors::defaultIndexValue = 0; + +/// Constructor +SCDPanelErrors::SCDPanelErrors() : m_setupFinished(false) { + declareParameter("XShift", 0.0, "Shift factor in X"); + declareParameter("YShift", 0.0, "Shift factor in Y"); + declareParameter("ZShift", 0.0, "Shift factor in Z"); + declareParameter("XRotate", 0.0, "Rotate angle in X"); + declareParameter("YRotate", 0.0, "Rotate angle in Y"); + declareParameter("ZRotate", 0.0, "Rotate angle in Z"); + declareAttribute("FileName", Attribute("", true)); + declareAttribute("Workspace", Attribute("")); + declareAttribute("Bank", Attribute("")); } - -void SCDPanelErrors::init() { - - declareParameter("f0_detWidthScale", 1.0, "panel Width"); - declareParameter("f0_detHeightScale", 1.0, "panel Height"); - - declareParameter("f0_Xoffset", 0.0, "Panel Center x offset"); - declareParameter("f0_Yoffset", 0.0, "Panel Center y offset"); - declareParameter("f0_Zoffset", 0.0, "Panel Center z offset"); - - declareParameter("f0_Xrot", 0.0, - "Rotation(degrees) Panel Center in x axis direction"); - declareParameter("f0_Yrot", 0.0, - "Rotation(degrees) Panel Center in y axis direction"); - declareParameter("f0_Zrot", 0.0, - "Rotation(degrees) Panel Center in z axis direction"); - - declareParameter("l0", 0.0, "Initial Flight Path"); - declareParameter("t0", 0.0, "Time offset"); - declareParameter("SampleX", 0.0, "Sample x offset"); - declareParameter("SampleY", 0.0, "Sample y offset"); - declareParameter("SampleZ", 0.0, "Sample z offset"); +/** + * The movedetector function changes detector position and angles + * @param x :: The shift along the X-axis + * @param y :: The shift along the Y-axis + * @param z :: The shift along the Z-axis + * @param rotx :: The rotation around the X-axis + * @param roty :: The rotation around the Y-axis + * @param rotz :: The rotation around the Z-axis + * @param detname :: The detector name + * @param inputW :: The workspace + */ + +void SCDPanelErrors::moveDetector( + double x, double y, double z, double rotx, double roty, double rotz, + std::string detname, Workspace_sptr inputW) const { + + IAlgorithm_sptr alg1 = Mantid::API::AlgorithmFactory::Instance().create("MoveInstrumentComponent", -1); + alg1->initialize(); + alg1->setChild(true); + alg1->setLogging(false); + alg1->setProperty<Workspace_sptr>("Workspace", inputW); + alg1->setPropertyValue("ComponentName", detname); + // Move in cm for small shifts + alg1->setProperty("X", x * 0.01); + alg1->setProperty("Y", y * 0.01); + alg1->setProperty("Z", z * 0.01); + alg1->setPropertyValue("RelativePosition", "1"); + alg1->execute(); + + IAlgorithm_sptr algx = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1); + algx->initialize(); + algx->setChild(true); + algx->setLogging(false); + algx->setProperty<Workspace_sptr>("Workspace", inputW); + algx->setPropertyValue("ComponentName", detname); + algx->setProperty("X", 1.0); + algx->setProperty("Y", 0.0); + algx->setProperty("Z", 0.0); + algx->setProperty("Angle", rotx); + algx->setPropertyValue("RelativeRotation", "1"); + algx->execute(); + + IAlgorithm_sptr algy = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1); + algy->initialize(); + algy->setChild(true); + algy->setLogging(false); + algy->setProperty<Workspace_sptr>("Workspace", inputW); + algy->setPropertyValue("ComponentName", detname); + algy->setProperty("X", 0.0); + algy->setProperty("Y", 1.0); + algy->setProperty("Z", 0.0); + algy->setProperty("Angle", roty); + algy->setPropertyValue("RelativeRotation", "1"); + algy->execute(); + + IAlgorithm_sptr algz = Mantid::API::AlgorithmFactory::Instance().create("RotateInstrumentComponent", -1); + algz->initialize(); + algz->setChild(true); + algz->setLogging(false); + algz->setProperty<Workspace_sptr>("Workspace", inputW); + algz->setPropertyValue("ComponentName", detname); + algz->setProperty("X", 0.0); + algz->setProperty("Y", 0.0); + algz->setProperty("Z", 1.0); + algz->setProperty("Angle", rotz); + algz->setPropertyValue("RelativeRotation", "1"); + algz->execute(); } -void SCDPanelErrors::getPeaks() const { - // if the pointer is set just return - if (m_peaks && m_peaks->rowCount() > 0) +/// Evaluate the function for a list of arguments and given scaling factor +void SCDPanelErrors::eval(double xrotate, double yrotate, double zrotate, double xshift, double yshift, double zshift, + double *out, const double *xValues, + const size_t nData) const { + UNUSED_ARG(xValues); + if (nData == 0) return; - if (PeakName.empty()) - throw std::invalid_argument( - "Cannot retrieve peaks workspace from empty string"); - - // get the workspace from the framework - m_peaks = - AnalysisDataService::Instance().retrieveWS<PeaksWorkspace>(PeakName); - - // error check it - if (!m_peaks || m_peaks->rowCount() < 1) - throw std::invalid_argument("There are no peaks in the peaks workspace or " - "no PeakWorkspace named \"" + - PeakName + "\""); -} - -void SCDPanelErrors::Check(DataObjects::PeaksWorkspace_sptr &pkwsp, - const double *xValues, const size_t nData, - size_t &StartX, size_t &EndX) const { - // TODO need to error check this - // if (NLatticeParametersSet < (int) nAttributes()-2) - // { - // g_log.error("Not all lattice parameters have been set"); - // throw std::invalid_argument("Not all lattice parameters have been set"); - // } - - if (!pkwsp) { - throw std::invalid_argument("Cannot find a PeaksWorkspace "); - } - - if (pkwsp->getNumberPeaks() < 4) { - throw std::invalid_argument("Not enough peaks to fit "); - } - - if ((m_startX > static_cast<int>(nData) - 1) || - (m_endX > static_cast<int>(nData) - 1)) { - throw std::invalid_argument(X_START + " and " + X_END + - " attributes are out of range"); - } - - StartX = 0; - if (m_startX > 0) - StartX = static_cast<size_t>(m_startX); - EndX = nData - 1; - if (m_endX > static_cast<int>(StartX)) - EndX = static_cast<size_t>(m_endX); - - if (xValues[StartX] != floor(xValues[StartX])) { - throw std::invalid_argument("Improper workspace. xVals must be integer"); - } - - if (xValues[StartX] < 0 || xValues[StartX] >= pkwsp->rowCount()) { - - throw std::invalid_argument("Improper workspace. xVals correspond to an " - "index in the PeaksWorkspace"); - } - - if ((EndX - StartX + 1) / 3 < 4) { - throw std::invalid_argument("Not enough peaks to process banks " + - BankNames); + setupData(); + + moveDetector(xrotate, yrotate, zrotate, xshift, yshift, zshift,m_bank,m_workspace); + DataObjects::PeaksWorkspace_sptr inputP = + boost::dynamic_pointer_cast<DataObjects::PeaksWorkspace>(m_workspace); + Geometry::Instrument_sptr inst = boost::const_pointer_cast<Geometry::Instrument>(inputP->getInstrument()); + int j = 0; + for (size_t i = 0; i < nData; i += 3) { + DataObjects::Peak peak = inputP->getPeak(j); + j++; + V3D Q1 = peak.getQSampleFrame(); + DataObjects::Peak peak2(inst,Q1,peak.getGoniometerMatrix()); + peak2.setDetectorID(peak.getDetectorID()); + V3D Q3 = peak2.getQSampleFrame(); + out[i] = Q3[0]; + out [i+1] = Q3[1]; + out[i+2] = Q3[2]; } + moveDetector(-xrotate, -yrotate, -zrotate, -xshift, -yshift, -zshift,m_bank,m_workspace); } -Instrument_sptr -SCDPanelErrors::getNewInstrument(const Geometry::IPeak &peak) const { - - Geometry::Instrument_const_sptr instSave = peak.getInstrument(); - auto pmap = boost::make_shared<ParameterMap>(); - boost::shared_ptr<const Geometry::ParameterMap> pmapSv = - instSave->getParameterMap(); - - if (!instSave) { - g_log.error(" Not all peaks have an instrument"); - throw std::invalid_argument(" Not all peaks have an instrument"); - } - auto instChange = boost::make_shared<Geometry::Instrument>(); - - if (!instSave->isParametrized()) { - boost::shared_ptr<Geometry::Instrument> instClone(instSave->clone()); - auto Pinsta = boost::make_shared<Geometry::Instrument>(instSave, pmap); - - instChange = Pinsta; - } else // catch(...) - { - // TODO eliminate next 2 lines. not used - boost::shared_ptr<const IComponent> inst3 = - boost::dynamic_pointer_cast<const IComponent>(instSave); - // updateParams(pmapSv, pmap, inst3); - - auto P1 = boost::make_shared<Geometry::Instrument>( - instSave->baseInstrument(), pmap); - instChange = P1; - } - - if (!instChange) { - g_log.error("Cannot 'clone' instrument"); - throw logic_error("Cannot clone instrument"); - } - std::vector<std::string> GroupBanks; - - boost::split(GroupBanks, BankNames, boost::is_any_of("!")); - - for (size_t group = 0; group < (size_t)GroupBanks.size(); ++group) { - string prefix = "f" + std::to_string(group) + "_"; - - std::vector<std::string> bankNames; - Quat rot = Quat(getParameter(prefix + "Xrot"), Kernel::V3D(1.0, 0.0, 0.0)) * - Quat(getParameter(prefix + "Yrot"), Kernel::V3D(0.0, 1.0, 0.0)) * - Quat(getParameter(prefix + "Zrot"), Kernel::V3D(0.0, 0.0, 1.0)); - - boost::split(bankNames, GroupBanks[group], boost::is_any_of("/")); - - SCDCalibratePanels::FixUpBankParameterMap( - bankNames, instChange, - V3D(getParameter(prefix + "Xoffset"), getParameter(prefix + "Yoffset"), - getParameter(prefix + "Zoffset")), - rot, getParameter(prefix + "detWidthScale"), - getParameter(prefix + "detHeightScale"), pmapSv, RotateCenters); - - } // for each group - - V3D SampPos = instChange->getSample()->getPos(); - SampPos[0] += getParameter("SampleX") + SampleX; - SampPos[1] += getParameter("SampleY") + SampleY; - SampPos[2] += getParameter("SampleZ") + SampleZ; - - SCDCalibratePanels::FixUpSourceParameterMap(instChange, getParameter("l0"), - SampPos, pmapSv); - - return instChange; +/** + * Calculate the function values. + * @param out :: The output buffer for the calculated values. + * @param xValues :: The array of x-values. + * @param nData :: The size of the data. + */ +void SCDPanelErrors::function1D(double *out, const double *xValues, + const size_t nData) const { + const double xrotate = getParameter("XRotate"); + const double yrotate = getParameter("YRotate"); + const double zrotate = getParameter("ZRotate"); + const double xshift = getParameter("XShift"); + const double yshift = getParameter("YShift"); + const double zshift = getParameter("ZShift"); + eval(xrotate, yrotate, zrotate, xshift, yshift, zshift, out, xValues, nData); } -Peak SCDPanelErrors::createNewPeak(const Geometry::IPeak &peak_old, - Geometry::Instrument_sptr instrNew, - double T0, double L0) { - Geometry::Instrument_const_sptr inst = peak_old.getInstrument(); - if (inst->getComponentID() != instrNew->getComponentID()) { - g_log.error("All peaks must have the same instrument"); - throw invalid_argument("All peaks must have the same instrument"); - } - - double T = peak_old.getTOF() + T0; - - int ID = peak_old.getDetectorID(); - - Kernel::V3D hkl = peak_old.getHKL(); - // peak_old.setDetectorID(ID); //set det positions - Peak peak(instrNew, ID, peak_old.getWavelength(), hkl, - peak_old.getGoniometerMatrix()); - - Wavelength wl; - - wl.initialize(L0, peak.getL2(), peak.getScattering(), 0, - peak_old.getInitialEnergy(), 0.0); - - peak.setWavelength(wl.singleFromTOF(T)); - peak.setIntensity(peak_old.getIntensity()); - peak.setSigmaIntensity(peak_old.getSigmaIntensity()); - peak.setRunNumber(peak_old.getRunNumber()); - peak.setBinCount(peak_old.getBinCount()); - - //!!!peak.setDetectorID(ID); - return peak; +/** + * function derivatives + * @param out :: The output Jacobian matrix: function derivatives over its + * parameters. + * @param xValues :: The function arguments + * @param nData :: The size of xValues. + */ +void SCDPanelErrors::functionDeriv1D(API::Jacobian *out, + const double *xValues, + const size_t nData) { + FunctionDomain1DView domain(xValues, nData); + this->calNumericalDeriv(domain, *out); } -void SCDPanelErrors::function1D(double *out, const double *xValues, - const size_t nData) const { - g_log.debug() << "Start function 1D\n"; - - // return early if there is nothing to do - if (nData == 0) - return; - - if (!m_unitCell) - throw runtime_error( - "Cannot evaluate function without setting the lattice constants"); - - // error check the parameters - double r = checkForNonsenseParameters(); - if (r != 0) { - for (size_t i = 0; i < nData; ++i) - out[i] = 100 + r; - - g_log.debug() << "Parametersxx for " << BankNames << ">="; - for (size_t i = 0; i < nParams(); ++i) - g_log.debug() << getParameter(i) << ","; - g_log.debug() << "\n"; - - return; - } - - // determine the range of data to fit by index - size_t StartX; - size_t EndX; - this->getPeaks(); - Check(m_peaks, xValues, nData, StartX, EndX); - - g_log.debug() << "BankNames " << BankNames << " Number of peaks" - << (EndX - StartX + 1) / 3 << '\n'; - - // some pointers for the updated instrument - boost::shared_ptr<Geometry::Instrument> instChange = - getNewInstrument(m_peaks->getPeak(0)); - - //---------------------------- Calculate q and hkl vectors----------------- - - vector<Kernel::V3D> hkl_vectors; - vector<Kernel::V3D> q_vectors; - double t0 = getParameter("t0"); - double l0 = getParameter("l0"); - for (size_t i = StartX; i <= EndX; i += 3) { - // the x-values are the peak indices as triplets, convert them to size_t - if (xValues[i] < 0.) - throw invalid_argument( - "Improper workspace. xVals must be positive integers"); - size_t pkIndex = std::lround(xValues[i]); // just round to nearest int - if (pkIndex >= m_peaks->rowCount()) { +/// Clear all data +void SCDPanelErrors::clear() const { + m_setupFinished = false; +} - g_log.error() << "Improper workspace set " << pkIndex << "\n"; - throw invalid_argument("Improper workspace. xVals correspond to an index " - "in the PeaksWorkspace"); +/** Set a value to attribute attName + * @param attName :: The attribute name + * @param value :: The new value + */ +void SCDPanelErrors::setAttribute(const std::string &attName, + const IFunction::Attribute &value) { + if (attName == "FileName") { + std::string fileName = value.asUnquotedString(); + if (fileName.empty()) { + storeAttributeValue("FileName", Attribute("", true)); + return; } - - IPeak &peak_old = m_peaks->getPeak(static_cast<int>(pkIndex)); - Kernel::V3D hkl = peak_old.getHKL(); - - // eliminate tolerance cause only those peaks that are OK should be here - if (IndexingUtils::ValidIndex(hkl, tolerance)) { - hkl_vectors.push_back(hkl); - Peak peak = createNewPeak(peak_old, instChange, t0, l0); - q_vectors.push_back(peak.getQSampleFrame()); + FileValidator fval; + std::string error = fval.isValid(fileName); + if (error == "") { + storeAttributeValue(attName, Attribute(fileName, true)); + storeAttributeValue("Workspace", Attribute("")); + } else { + // file not found + throw Kernel::Exception::FileError(error, fileName); + } + load(fileName); + } else if (attName == "Workspace") { + std::string wsName = value.asString(); + if (!wsName.empty()) { + storeAttributeValue(attName, value); + storeAttributeValue("FileName", Attribute("", true)); + loadWorkspace(wsName); } + } else { + IFunction::setAttribute(attName, value); + m_setupFinished = false; } +} - //----------------------------------Calculate out - //---------------------------------- - - // determine the OrientedLattice for converting to Q-sample - Geometry::OrientedLattice lattice(*m_unitCell); - lattice.setUB(m_peaks->sample().getOrientedLattice().getUB()); - - // cumulative error - double chiSq = 0; // for debug log message - - for (size_t i = 0; i < StartX; ++i) - out[i] = 0.; - for (size_t i = 0; i < q_vectors.size(); ++i) { - Kernel::V3D err = q_vectors[i] - lattice.qFromHKL(hkl_vectors[i]); - size_t outIndex = 3 * i + StartX; - out[outIndex + 0] = err[0]; - out[outIndex + 1] = err[1]; - out[outIndex + 2] = err[2]; - chiSq += err[0] * err[0] + err[1] * err[1] + err[2] * err[2]; +/** + * Load input file as a Nexus file. + * @param fname :: The file name + */ +void SCDPanelErrors::load(const std::string &fname) { + IAlgorithm_sptr loadAlg = + Mantid::API::AlgorithmFactory::Instance().create("Load", -1); + loadAlg->initialize(); + loadAlg->setChild(true); + loadAlg->setLogging(false); + try { + loadAlg->setPropertyValue("Filename", fname); + loadAlg->setPropertyValue("OutputWorkspace", + "_SCDPanelErrors_fit_data_"); + loadAlg->execute(); + } catch (std::runtime_error &) { + throw std::runtime_error( + "Unable to load Nexus file for SCDPanelErrors function."); } - for (size_t i = EndX; i < nData; ++i) - out[i] = 0.; - - g_log.debug() << "Parameters\n"; - - for (size_t i = 0; i < this->nParams(); ++i) - g_log.debug() << setw(20) << parameterName(i) << setw(20) << getParameter(i) - << '\n'; - - g_log.debug() << " chi Squared=" << std::setprecision(12) << chiSq - << '\n'; - - // Get values for test program. TODO eliminate - g_log.debug() << " out[evenxx]="; - for (size_t i = 0; i < std::min<size_t>(nData, 30); ++i) - g_log.debug() << out[i] << " "; - - g_log.debug() << '\n'; + Workspace_sptr ws = loadAlg->getProperty("OutputWorkspace"); + API::Workspace_sptr resData = + boost::dynamic_pointer_cast<Mantid::API::Workspace>(ws); + loadWorkspace(resData); } -double SCDPanelErrors::checkForNonsenseParameters() const { - - double Dwdth = getParameter(0); - double Dhght = getParameter(1); - double x = getParameter(2); - double y = getParameter(3); - double z = getParameter(4); - double rx = getParameter(5); - double ry = getParameter(6); - double rz = getParameter(7); - double L0 = getParameter(8); - double T0 = getParameter(9); - - double r = 0.; - if (L0 < 1.) - r = 1. - L0; - - if (fabs(T0) > 20.) - r += (T0 - 20.) * 2.; - - if (Dwdth < .5 || Dwdth > 2.) - r += 3. * fabs(1 - Dwdth); - - if (Dhght < .5 || Dhght > 2.) - r += 3. * fabs(1. - Dhght); - - if (fabs(x) > .35) - r += fabs(x) * .2; - - if (fabs(y) > .35) - r += fabs(y) * .2; - - if (fabs(z) > .35) - r += fabs(z) * .2; - - if (fabs(rx) > 15.) - r += fabs(rx) * .02; - - if (fabs(ry) > 15.) - r += fabs(ry) * .02; - - if (fabs(rz) > 15.) - r += fabs(rz) * .02; - - return 5. * r; +/** + * Load the points from a PeaksWorkspace + * @param wsName :: The workspace to load from + */ +void SCDPanelErrors::loadWorkspace(const std::string &wsName) const { + auto ws = AnalysisDataService::Instance().retrieveWS<API::Workspace>(wsName); + loadWorkspace(ws); } -void updateDerivResult(PeaksWorkspace_sptr peaks, V3D &unRotDeriv, - Matrix<double> &Result, size_t peak, - vector<int> &peakIndx) { - Matrix<double> GonMatrix = - peaks->getPeak(peakIndx[peak]).getGoniometerMatrix(); - GonMatrix.Invert(); - - V3D RotDeriv = GonMatrix * unRotDeriv; - - for (int kk = 0; kk < 3; ++kk) - Result[kk][peak] = RotDeriv[kk]; +/** + * Load the points from a PeaksWorkspace + * @param ws :: The workspace to load from + */ +void SCDPanelErrors::loadWorkspace( + boost::shared_ptr<API::Workspace> ws) const { + m_workspace = ws; + m_setupFinished = false; } -void SCDPanelErrors::functionDeriv1D(Jacobian *out, const double *xValues, - const size_t nData) { - if (nData <= 0) +/** + * Fill in the workspace name and bank + */ +void SCDPanelErrors::setupData() const { + if (m_setupFinished) { + g_log.debug() << "Re-setting isn't required."; return; - FunctionDomain1DView domain(xValues, nData); - calNumericalDeriv(domain, *out); -} - -DataObjects::Workspace2D_sptr -SCDPanelErrors::calcWorkspace(DataObjects::PeaksWorkspace_sptr &pwks, - std::vector<std::string> &bankNames, - double tolerance) { - int N = 0; - if (tolerance < 0) - tolerance = .5; - tolerance = std::min<double>(.5, tolerance); - - Mantid::MantidVec xRef; - - for (auto &bankName : bankNames) - for (size_t j = 0; j < pwks->rowCount(); ++j) { - Geometry::IPeak &peak = pwks->getPeak(static_cast<int>(j)); - if (peak.getBankName().compare(bankName) == 0) - if (peak.getH() != 0 || peak.getK() != 0 || peak.getL() != 0) - if (peak.getH() - floor(peak.getH()) < tolerance || - floor(peak.getH() + 1) - peak.getH() < tolerance) - if (peak.getK() - floor(peak.getK()) < tolerance || - floor(peak.getK() + 1) - peak.getK() < tolerance) - if (peak.getL() - floor(peak.getL()) < tolerance || - floor(peak.getL() + 1) - peak.getL() < tolerance) { - N++; - xRef.push_back(static_cast<double>(j)); - xRef.push_back(static_cast<double>(j)); - xRef.push_back(static_cast<double>(j)); - } - } - - MatrixWorkspace_sptr mwkspc = API::WorkspaceFactory::Instance().create( - "Workspace2D", static_cast<size_t>(3), 3 * N, 3 * N); - - auto pX = Kernel::make_cow<HistogramData::HistogramX>(std::move(xRef)); - mwkspc->setX(0, pX); - mwkspc->setX(1, pX); - mwkspc->setX(2, pX); - - return boost::dynamic_pointer_cast<DataObjects::Workspace2D>(mwkspc); -} - -void SCDPanelErrors::setAttribute(const std::string &attName, - const Attribute &value) { - if (!hasAttribute(attName)) - throw std::invalid_argument("Not a valid attribute name \"" + attName + - "\""); - - bool recalcB = false; - if (attName == LATTICE_A) { - a = value.asDouble(); - a_set = true; - recalcB = true; - } else if (attName == LATTICE_B) { - b = value.asDouble(); - b_set = true; - recalcB = true; - } else if (attName == LATTICE_C) { - c = value.asDouble(); - c_set = true; - recalcB = true; - } else if (attName == LATTICE_ALPHA) { - alpha = value.asDouble(); - alpha_set = true; - recalcB = true; - } else if (attName == LATTICE_BETA) { - beta = value.asDouble(); - beta_set = true; - recalcB = true; - } else if (attName == LATTICE_GAMMA) { - gamma = value.asDouble(); - gamma_set = true; - recalcB = true; - } else if (attName == (BANK_NAMES)) { - BankNames = value.asString(); - BankNames_set = true; - } else if (attName == PEAKS_WKSP) { - PeakName = value.asString(); - PeakName_set = true; - } else if (attName == NUM_GROUPS) { - if (NGroups_set) { - g_log.error("Cannot set NGroups more than once"); - throw new std::invalid_argument("Cannot set NGroups more than once"); - } - NGroups = value.asInt(); - for (int k = 1; k < NGroups; ++k) { - std::string prefix = "f" + std::to_string(k) + "_"; - declareParameter(prefix + "detWidthScale", 1.0, "panel Width"); - declareParameter(prefix + "detHeightScale", 1.0, "panelHeight"); - - declareParameter(prefix + "Xoffset", 0.0, "Panel Center x offset"); - declareParameter(prefix + "Yoffset", 0.0, "Panel Center y offset"); - declareParameter(prefix + "Zoffset", 0.0, "Panel Center z offset"); - - declareParameter(prefix + "Xrot", 0.0, - "Rotation(degrees) Panel Center in x axis direction"); - declareParameter(prefix + "Yrot", 0.0, - "Rotation(degrees) Panel Center in y axis direction"); - declareParameter(prefix + "Zrot", 0.0, - "Rotation(degrees) Panel Center in z axis direction"); - } - NGroups_set = true; - } else if (attName == ROTATE_CEN) { - int v = value.asInt(); - if (v == 0) - RotateCenters = false; - else - RotateCenters = true; + } - } else if (attName == SAMPLE_OFF) { - int v = value.asInt(); - if (v == 0) - SampleOffsets = false; + if (!m_workspace) { + std::string wsName = getAttribute("Workspace").asString(); + if (wsName.empty()) + throw std::invalid_argument("Data not set for function " + this->name()); else - SampleOffsets = true; + loadWorkspace(wsName); + } - } else if (attName == SAMPLE_X) { - SampleX = value.asDouble(); - sampleX_set = true; - } else if (attName == SAMPLE_Y) { - SampleY = value.asDouble(); - sampleY_set = true; - } else if (attName == SAMPLE_Z) { - SampleZ = value.asDouble(); - sampleZ_set = true; - } else if (attName == X_START) { - m_startX = value.asInt(); - startX_set = true; - } else if (attName == "endX") { - m_endX = value.asInt(); - endX_set = true; - } else - throw std::invalid_argument("Not a valid attribute name \"" + attName + - "\""); + m_bank = getAttribute("Bank").asString(); - if (recalcB) { - if (a_set && b_set && c_set && alpha_set && beta_set && gamma_set) { - m_unitCell = - boost::make_shared<Geometry::UnitCell>(a, b, c, alpha, beta, gamma); - } - } -} + g_log.debug() << "Setting up " << m_workspace->name() << " bank " << m_bank + << '\n'; -boost::shared_ptr<const Geometry::IComponent> -SCDPanelErrors::findBank(std::string bankName) { - return bankDetMap.find(bankName)->second; + m_setupFinished = true; } } // namespace Crystal diff --git a/Framework/DataHandling/src/MoveInstrumentComponent.cpp b/Framework/DataHandling/src/MoveInstrumentComponent.cpp index ef67846d94c..8f7f7ecaf64 100644 --- a/Framework/DataHandling/src/MoveInstrumentComponent.cpp +++ b/Framework/DataHandling/src/MoveInstrumentComponent.cpp @@ -5,6 +5,7 @@ #include "MantidDataObjects/Workspace2D.h" #include "MantidKernel/Exception.h" #include "MantidGeometry/Instrument/ComponentHelper.h" +#include "MantidDataObjects/PeaksWorkspace.h" namespace Mantid { namespace DataHandling { @@ -23,7 +24,7 @@ MoveInstrumentComponent::MoveInstrumentComponent() {} void MoveInstrumentComponent::init() { // When used as a Child Algorithm the workspace name is not used - hence the // "Anonymous" to satisfy the validator - declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>( + declareProperty(make_unique<WorkspaceProperty<Workspace>>( "Workspace", "Anonymous", Direction::InOut), "The name of the workspace for which the new instrument " "configuration will have an effect. Any other workspaces " @@ -50,8 +51,32 @@ void MoveInstrumentComponent::init() { * @throw std::runtime_error Thrown with Workspace problems */ void MoveInstrumentComponent::exec() { - // Get the workspace - MatrixWorkspace_sptr WS = getProperty("Workspace"); + // Get the input workspace + Workspace_sptr ws = getProperty("Workspace"); + MatrixWorkspace_sptr inputW = + boost::dynamic_pointer_cast<MatrixWorkspace>(ws); + DataObjects::PeaksWorkspace_sptr inputP = + boost::dynamic_pointer_cast<DataObjects::PeaksWorkspace>(ws); + + // Get some stuff from the input workspace + Instrument_sptr inst; + if (inputW) { + inst = boost::const_pointer_cast<Instrument>(inputW->getInstrument()); + if (!inst) + throw std::runtime_error("Could not get a valid instrument from the " + "MatrixWorkspace provided as input"); + } else if (inputP) { + inst = boost::const_pointer_cast<Instrument>(inputP->getInstrument()); + if (!inst) + throw std::runtime_error("Could not get a valid instrument from the " + "PeaksWorkspace provided as input"); + } else { + if (!inst) + throw std::runtime_error("Could not get a valid instrument from the " + "workspace and it does not seem to be valid as " + "input (must be either MatrixWorkspace or " + "PeaksWorkspace"); + } const std::string ComponentName = getProperty("ComponentName"); const int DetID = getProperty("DetectorID"); const double X = getProperty("X"); @@ -59,10 +84,6 @@ void MoveInstrumentComponent::exec() { const double Z = getProperty("Z"); const bool relativePosition = getProperty("RelativePosition"); - // Get the ParameterMap reference before the instrument so that - // we avoid a copy - Geometry::ParameterMap &pmap = WS->instrumentParameters(); - Instrument_const_sptr inst = WS->getInstrument(); IComponent_const_sptr comp; // Find the component to move @@ -92,8 +113,15 @@ void MoveInstrumentComponent::exec() { TransformType positionType = Absolute; if (relativePosition) positionType = Relative; - Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(X, Y, Z), - positionType); + if (inputW) { + Geometry::ParameterMap &pmap = inputW->instrumentParameters(); + Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(X, Y, Z), + positionType); + } else if (inputP) { + Geometry::ParameterMap &pmap = inputP->instrumentParameters(); + Geometry::ComponentHelper::moveComponent(*comp, pmap, V3D(X, Y, Z), + positionType); + } } } // namespace DataHandling -- GitLab