From fa841045e2a48bc987a1573c31771f0bfeee3710 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Fri, 31 Oct 2014 17:34:20 +0000 Subject: [PATCH 01/41] Formatting changes only. Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 122 +-- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 918 +++++++++--------- 2 files changed, 526 insertions(+), 514 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index a6d7c3e12182..20b2f4c822fd 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -1,77 +1,77 @@ #ifndef MANTID_MDALGORITHMS_SXDMDNORM_H_ #define MANTID_MDALGORITHMS_SXDMDNORM_H_ -#include "MantidKernel/System.h" #include "MantidAPI/Algorithm.h" #include "MantidMDAlgorithms/SlicingAlgorithm.h" + namespace Mantid { -namespace MDAlgorithms -{ - - /** SXDMDNorm : Generate MD normalization for single crystal diffraction - - Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory - - 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 . - - File change history is stored at: - Code Documentation is available at: - */ - bool compareMomentum(Mantid::Kernel::VMD v1, Mantid::Kernel::VMD v2); - - class DLLExport SXDMDNorm :public SlicingAlgorithm + namespace MDAlgorithms { - public: - SXDMDNorm(); - virtual ~SXDMDNorm(); + bool compareMomentum(Mantid::Kernel::VMD v1, Mantid::Kernel::VMD v2); - virtual const std::string name() const; - virtual int version() const; - virtual const std::string category() const; - virtual const std::string summary() const; + /** + + SXDMDNorm : Generate MD normalization for single crystal diffraction + + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + 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. - private: - void init(); - void exec(); + You should have received a copy of the GNU General Public License + along with this program. If not, see . - /// function to calculate intersections of teh trajectory with MDBoxes - std::vector calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector); - /// number of MD dimensions - size_t m_nDims; - /// Normalization workspace - Mantid::MDEvents::MDHistoWorkspace_sptr m_normWS; - /// Input workspace - Mantid::API::IMDEventWorkspace_sptr m_inputWS; - ///limits for h,k,l dimensions - coord_t hMin,hMax,kMin,kMax,lMin,lMax; - ///flag for integrated h,k,l dimensions - bool hIntegrated,kIntegrated,lIntegrated; - ///(2*PiRUBW)^-1 - Mantid::Kernel::DblMatrix transf; - /// limits for momentum - double KincidentMin,KincidentMax; - ///index of h,k,l dimensions in the output workspaces - size_t hIndex,kIndex,lIndex; - /// cached x values along dimensions h,k,l - std::vector m_hX, m_kX, m_lX; - }; + File change history is stored at: + Code Documentation is available at: + */ + class DLLExport SXDMDNorm : public SlicingAlgorithm + { + public: + SXDMDNorm(); + + virtual const std::string name() const; + virtual int version() const; + virtual const std::string category() const; + virtual const std::string summary() const; + + private: + void init(); + void exec(); + + /// function to calculate intersections of teh trajectory with MDBoxes + std::vector calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector); + /// number of MD dimensions + size_t m_nDims; + /// Normalization workspace + Mantid::MDEvents::MDHistoWorkspace_sptr m_normWS; + /// Input workspace + Mantid::API::IMDEventWorkspace_sptr m_inputWS; + ///limits for h,k,l dimensions + coord_t hMin,hMax,kMin,kMax,lMin,lMax; + ///flag for integrated h,k,l dimensions + bool hIntegrated,kIntegrated,lIntegrated; + ///(2*PiRUBW)^-1 + Mantid::Kernel::DblMatrix transf; + /// limits for momentum + double KincidentMin,KincidentMax; + ///index of h,k,l dimensions in the output workspaces + size_t hIndex,kIndex,lIndex; + /// cached x values along dimensions h,k,l + std::vector m_hX, m_kX, m_lX; + }; -} // namespace MDAlgorithms + } // namespace MDAlgorithms } // namespace Mantid #endif /* MANTID_MDALGORITHMS_SXDMDNORM_H_ */ diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index db7097947641..0bf45a63c653 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -1,572 +1,584 @@ #include "MantidMDAlgorithms/SXDMDNorm.h" + +#include "MantidAPI/WorkspaceValidators.h" +#include "MantidDataObjects/EventWorkspace.h" #include "MantidMDEvents/MDEventWorkspace.h" #include "MantidMDEvents/MDHistoWorkspace.h" -#include "MantidAPI/WorkspaceValidators.h" #include "MantidKernel/TimeSeriesProperty.h" -#include "MantidDataObjects/EventWorkspace.h" namespace Mantid { -namespace MDAlgorithms -{ - - using Mantid::Kernel::Direction; - using Mantid::API::WorkspaceProperty; - using namespace Mantid::MDEvents; - using namespace Mantid::API; - using namespace Mantid::Kernel; - - ///function to compare two intersections (h,k,l,Momentum) by Momentum - bool compareMomentum(const Mantid::Kernel::VMD &v1, const Mantid::Kernel::VMD &v2) + namespace MDAlgorithms { - return (v1[3]("InputWorkspace","",Direction::Input), "An input MDWorkspace."); - + void SXDMDNorm::init() + { + declareProperty(new WorkspaceProperty("InputWorkspace","",Direction::Input), + "An input MDWorkspace."); + std::string dimChars = getDimensionChars(); // --------------- Axis-aligned properties --------------------------------------- - for (size_t i=0; i(propName,"",Direction::Input), - "Binning parameters for the " + Strings::toString(i) + "th dimension.\n" - "Enter it as a comma-separated list of values with the format: 'name,minimum,maximum,number_of_bins'. Leave blank for NONE."); + std::string dim(" "); dim[0] = dimChars[i]; + std::string propName = "AlignedDim" + dim; + declareProperty(new PropertyWithValue(propName,"",Direction::Input), + "Binning parameters for the " + Strings::toString(i) + "th dimension.\n" + "Enter it as a comma-separated list of values with the format: 'name,minimum,maximum,number_of_bins'. Leave blank for NONE."); } - + auto wsValidator = boost::make_shared(); wsValidator->add("Momentum"); wsValidator->add(); wsValidator->add(); - - declareProperty(new WorkspaceProperty<>("FluxWorkspace","",Direction::Input,wsValidator), "An input workspace containing momentum dependent flux."); - declareProperty(new WorkspaceProperty<>("SolidAngleWorkspace","",Direction::Input,wsValidator->clone()), "An input workspace containing momentum integrated vanadium (a measure of the solid angle)."); - - declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), "A name for the output data MDHistoWorkspace."); - declareProperty(new WorkspaceProperty("OutputNormalizationWorkspace","",Direction::Output), "A name for the output normalization MDHistoWorkspace."); - } - - //---------------------------------------------------------------------------------------------- - /** Execute the algorithm. + + declareProperty(new WorkspaceProperty<>("FluxWorkspace","",Direction::Input,wsValidator), + "An input workspace containing momentum dependent flux."); + declareProperty(new WorkspaceProperty<>("SolidAngleWorkspace","",Direction::Input,wsValidator->clone()), + "An input workspace containing momentum integrated vanadium (a measure of the solid angle)."); + + declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), + "A name for the output data MDHistoWorkspace."); + declareProperty(new WorkspaceProperty("OutputNormalizationWorkspace","",Direction::Output), + "A name for the output normalization MDHistoWorkspace."); + } + + //---------------------------------------------------------------------------------------------- + /** Execute the algorithm. */ - void SXDMDNorm::exec() - { - bool skipProcessing=false; - m_inputWS=getProperty("InputWorkspace"); - WorkspaceHistory hist=m_inputWS->getHistory(); + void SXDMDNorm::exec() + { + bool skipProcessing = false; + m_inputWS = getProperty("InputWorkspace"); + WorkspaceHistory hist = m_inputWS->getHistory(); std::string dEMode(""); if (hist.lastAlgorithm()->name()=="ConvertToMD") { - dEMode=hist.lastAlgorithm()->getPropertyValue("dEAnalysisMode"); + dEMode = hist.lastAlgorithm()->getPropertyValue("dEAnalysisMode"); } - else if (((hist.lastAlgorithm()->name()=="Load")||(hist.lastAlgorithm()->name()=="LoadMD"))&&(hist.getAlgorithmHistory(hist.size()-2)->name()=="ConvertToMD")) + else if ( ((hist.lastAlgorithm()->name() == "Load") || (hist.lastAlgorithm()->name() == "LoadMD")) && + (hist.getAlgorithmHistory(hist.size()-2)->name() == "ConvertToMD") ) { - //get dEAnalysisMode - PropertyHistories histvec=hist.getAlgorithmHistory(hist.size()-2)->getProperties(); - for(auto it=histvec.begin();it!=histvec.end();++it) + //get dEAnalysisMode + PropertyHistories histvec = hist.getAlgorithmHistory(hist.size()-2)->getProperties(); + for(auto it = histvec.begin();it != histvec.end(); ++it) + { + if((*it)->name()=="dEAnalysisMode") { - if((*it)->name()=="dEAnalysisMode") - { - dEMode=(*it)->value(); - } + dEMode=(*it)->value(); } + } } else { - throw std::runtime_error("The last algorithm in the history of the input workspace is not ConvertToMD"); + throw std::runtime_error("The last algorithm in the history of the input workspace is not ConvertToMD"); } if (dEMode!="Elastic") { - throw std::runtime_error("This is not elastic scattering data"); + throw std::runtime_error("This is not elastic scattering data"); } - hMin=m_inputWS->getDimension(0)->getMinimum(); - kMin=m_inputWS->getDimension(1)->getMinimum(); - lMin=m_inputWS->getDimension(2)->getMinimum(); - hMax=m_inputWS->getDimension(0)->getMaximum(); - kMax=m_inputWS->getDimension(1)->getMaximum(); - lMax=m_inputWS->getDimension(2)->getMaximum(); - + hMin = m_inputWS->getDimension(0)->getMinimum(); + kMin = m_inputWS->getDimension(1)->getMinimum(); + lMin = m_inputWS->getDimension(2)->getMinimum(); + hMax = m_inputWS->getDimension(0)->getMaximum(); + kMax = m_inputWS->getDimension(1)->getMaximum(); + lMax = m_inputWS->getDimension(2)->getMaximum(); + //initialize some variables - hIntegrated=true; - kIntegrated=true; - lIntegrated=true; - hIndex=-1; - kIndex=-1; - lIndex=-1; - + hIntegrated = true; + kIntegrated = true; + lIntegrated = true; + hIndex = -1; + kIndex = -1; + lIndex = -1; + //check for other dimensions if we could measure anything in the original data std::vector otherValues; - for(size_t i=3;igetNumDims();i++) + for(size_t i = 3;i < m_inputWS->getNumDims(); i++) { - float dimMin=static_cast(m_inputWS->getDimension(i)->getMinimum()); - float dimMax=static_cast(m_inputWS->getDimension(i)->getMaximum()); - Kernel::TimeSeriesProperty *run_property = dynamic_cast *>(m_inputWS->getExperimentInfo(0)->run().getProperty(m_inputWS->getDimension(i)->getName())); - if (run_property!=NULL) + float dimMin = static_cast(m_inputWS->getDimension(i)->getMinimum()); + float dimMax = static_cast(m_inputWS->getDimension(i)->getMaximum()); + Kernel::TimeSeriesProperty *run_property = \ + dynamic_cast *>(m_inputWS->getExperimentInfo(0)->run().getProperty(m_inputWS->getDimension(i)->getName())); + if (run_property!=NULL) + { + coord_t value = static_cast(run_property->firstValue()); + otherValues.push_back(value); + //in the original MD data no time was spent measuring between dimMin and dimMax + if (value < dimMin || value > dimMax) { - coord_t value=static_cast(run_property->firstValue()); - otherValues.push_back(value); - //in the original MD data no time was spent measuring between dimMin and dimMax - if ((valuedimMax)) - { - skipProcessing=true; - } + skipProcessing = true; } - delete run_property; + } + delete run_property; } - + // Run BinMD Workspace_sptr outputWS = getProperty("OutputWorkspace"); - auto props=getProperties(); + auto props = getProperties(); IAlgorithm_sptr bin = createChildAlgorithm("BinMD",0.0,0.3); bin->setPropertyValue("AxisAligned","1"); - for(auto it=props.begin();it!=props.end();++it) + for(auto it = props.begin(); it != props.end(); ++it) { - if(((*it)->name()!="FluxWorkspace")&&((*it)->name()!="SolidAngleWorkspace")&&((*it)->name()!="OutputNormalizationWorkspace")) - bin->setPropertyValue((*it)->name(),(*it)->value()); + if(((*it)->name() != "FluxWorkspace") && ((*it)->name()!="SolidAngleWorkspace") && + ((*it)->name() != "OutputNormalizationWorkspace")) + bin->setPropertyValue((*it)->name(),(*it)->value()); } bin->executeAsChildAlg(); - outputWS=bin->getProperty("OutputWorkspace"); + outputWS = bin->getProperty("OutputWorkspace"); this->setProperty("OutputWorkspace", outputWS); - + //copy the MDHisto workspace, and change signals and errors to 0. - m_normWS=MDHistoWorkspace_sptr(new MDHistoWorkspace(*(boost::dynamic_pointer_cast(outputWS)))); + m_normWS = MDHistoWorkspace_sptr(new MDHistoWorkspace(*(boost::dynamic_pointer_cast(outputWS)))); m_normWS->setTo(0.,0.,0.); - + //get indices of the original dimensions in the output workspace, and if not found, the corresponding dimension is integrated - Mantid::Kernel::Matrix mat=m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); - - for (size_t row=0; row mat = m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); + + for (size_t row = 0; rowgetDimension(row)->getMinimum()) hMin = m_normWS->getDimension(row)->getMinimum(); + if(hMax>m_normWS->getDimension(row)->getMaximum()) hMax = m_normWS->getDimension(row)->getMaximum(); + if((hMin>m_normWS->getDimension(row)->getMaximum())||(hMaxgetDimension(row)->getMinimum())) { - hIntegrated=false; - hIndex=row; - if(hMingetDimension(row)->getMinimum()) hMin=m_normWS->getDimension(row)->getMinimum(); - if(hMax>m_normWS->getDimension(row)->getMaximum()) hMax=m_normWS->getDimension(row)->getMaximum(); - if((hMin>m_normWS->getDimension(row)->getMaximum())||(hMaxgetDimension(row)->getMinimum())) - { - skipProcessing=true; - } + skipProcessing = true; } - if(mat[row][1]==1.) + } + if(mat[row][1]==1.) + { + kIntegrated = false; + kIndex = row; + if(kMingetDimension(row)->getMinimum()) kMin = m_normWS->getDimension(row)->getMinimum(); + if(kMax>m_normWS->getDimension(row)->getMaximum()) kMax = m_normWS->getDimension(row)->getMaximum(); + if((kMin>m_normWS->getDimension(row)->getMaximum())||(kMaxgetDimension(row)->getMinimum())) { - kIntegrated=false; - kIndex=row; - if(kMingetDimension(row)->getMinimum()) kMin=m_normWS->getDimension(row)->getMinimum(); - if(kMax>m_normWS->getDimension(row)->getMaximum()) kMax=m_normWS->getDimension(row)->getMaximum(); - if((kMin>m_normWS->getDimension(row)->getMaximum())||(kMaxgetDimension(row)->getMinimum())) - { - skipProcessing=true; - } + skipProcessing = true; } - if(mat[row][2]==1.) + } + if(mat[row][2]==1.) + { + lIntegrated = false; + lIndex = row; + if(lMingetDimension(row)->getMinimum()) lMin = m_normWS->getDimension(row)->getMinimum(); + if(lMax>m_normWS->getDimension(row)->getMaximum()) lMax = m_normWS->getDimension(row)->getMaximum(); + if((lMin>m_normWS->getDimension(row)->getMaximum())||(lMaxgetDimension(row)->getMinimum())) { - lIntegrated=false; - lIndex=row; - if(lMingetDimension(row)->getMinimum()) lMin=m_normWS->getDimension(row)->getMinimum(); - if(lMax>m_normWS->getDimension(row)->getMaximum()) lMax=m_normWS->getDimension(row)->getMaximum(); - if((lMin>m_normWS->getDimension(row)->getMaximum())||(lMaxgetDimension(row)->getMinimum())) - { - skipProcessing=true; - } - - for(size_t col=3;colm_normWS->getDimension(row)->getMaximum())||(valgetDimension(row)->getMinimum())) { - if(mat[row][col]==1.) - { - double val=otherValues.at(col-3); - if((val>m_normWS->getDimension(row)->getMaximum())||(valgetDimension(row)->getMinimum())) - { - skipProcessing=true; - } - } + skipProcessing = true; } + } } + } } - + auto &hDim = *m_normWS->getDimension(hIndex); m_hX.resize( hDim.getNBins() ); for(size_t i = 0; i < m_hX.size(); ++i) { m_hX[i] = hDim.getX(i); } - + auto &kDim = *m_normWS->getDimension(kIndex); m_kX.resize( kDim.getNBins() ); for(size_t i = 0; i < m_kX.size(); ++i) { m_kX[i] = kDim.getX(i); } - + auto &lDim = *m_normWS->getDimension(lIndex); m_lX.resize( lDim.getNBins() ); for(size_t i = 0; i < m_lX.size(); ++i) { m_lX[i] = lDim.getX(i); } - - Mantid::API::MatrixWorkspace_const_sptr fW=getProperty("FluxWorkspace"); + + Mantid::API::MatrixWorkspace_const_sptr fW = getProperty("FluxWorkspace"); Mantid::DataObjects::EventWorkspace_const_sptr fluxW = boost::dynamic_pointer_cast(fW); - KincidentMin=fluxW->getEventXMin(); - KincidentMax=fluxW->getEventXMax(); - Mantid::API::MatrixWorkspace_const_sptr sA=getProperty("SolidAngleWorkspace"); - - + KincidentMin = fluxW->getEventXMin(); + KincidentMax = fluxW->getEventXMax(); + Mantid::API::MatrixWorkspace_const_sptr sA = getProperty("SolidAngleWorkspace"); + + if (skipProcessing) { - g_log.warning("Binning limits are outside the limits of the MDWorkspace\n"); + g_log.warning("Binning limits are outside the limits of the MDWorkspace\n"); } else { - double PC=m_normWS->getExperimentInfo(0)->run().getProtonCharge(); - Kernel::PropertyWithValue< std::vector > *prop=dynamic_cast< Mantid::Kernel::PropertyWithValue >*>(m_normWS->getExperimentInfo(0)->getLog("RUBW_MATRIX")); - if (prop==NULL) - { - throw std::runtime_error("No RUBW_MATRIX"); - } - else - { - Mantid::Kernel::DblMatrix RUBW((*prop)()); //includes the 2*pi factor but not goniometer for now :) - transf=m_normWS->getExperimentInfo(0)->run().getGoniometerMatrix()*RUBW; - transf.Invert(); - } - //FIXME: the detector positions are from the IDF. Need to account for calibration - std::vector detIDS=m_normWS->getExperimentInfo(0)->getInstrument()->getDetectorIDs(true); - - Mantid::API::Progress *prog=new Mantid::API::Progress(this,0.3,1,static_cast(detIDS.size())); - const detid2index_map d2m=fluxW->getDetectorIDToWorkspaceIndexMap(); - const detid2index_map d2mSA=sA->getDetectorIDToWorkspaceIndexMap(); - auto instrument = m_normWS->getExperimentInfo(0)->getInstrument(); - - PARALLEL_FOR1(m_normWS) - for(int i=0;i(detIDS.size());i++) + double PC = m_normWS->getExperimentInfo(0)->run().getProtonCharge(); + Kernel::PropertyWithValue< std::vector > *prop = dynamic_cast< Mantid::Kernel::PropertyWithValue >*>(m_normWS->getExperimentInfo(0)->getLog("RUBW_MATRIX")); + if (prop==NULL) + { + throw std::runtime_error("No RUBW_MATRIX"); + } + else + { + Mantid::Kernel::DblMatrix RUBW((*prop)()); //includes the 2*pi factor but not goniometer for now :) + transf = m_normWS->getExperimentInfo(0)->run().getGoniometerMatrix()*RUBW; + transf.Invert(); + } + //FIXME: the detector positions are from the IDF. Need to account for calibration + std::vector detIDS = m_normWS->getExperimentInfo(0)->getInstrument()->getDetectorIDs(true); + + Mantid::API::Progress *prog = new Mantid::API::Progress(this,0.3,1,static_cast(detIDS.size())); + const detid2index_map d2m = fluxW->getDetectorIDToWorkspaceIndexMap(); + const detid2index_map d2mSA = sA->getDetectorIDToWorkspaceIndexMap(); + auto instrument = m_normWS->getExperimentInfo(0)->getInstrument(); + + PARALLEL_FOR1(m_normWS) + for(int i = 0;i(detIDS.size());i++) + { + PARALLEL_START_INTERUPT_REGION + Mantid::Geometry::IDetector_const_sptr detector = instrument->getDetector(detIDS[i]); + if(!detector->isMonitor()&&!detector->isMasked()) { - PARALLEL_START_INTERUPT_REGION - Mantid::Geometry::IDetector_const_sptr detector=instrument->getDetector(detIDS[i]); - if(!detector->isMonitor()&&!detector->isMasked()) + //get intersections + std::vector intersections = calculateIntersections(detector); + + if(!intersections.empty()) + { + //calculate indices + //add to the correct signal at that particular index + //NOTE: if parallel it has to be atomic/critical + + //get event vector + size_t sp = d2m.find(detIDS[i])->second; + std::vector el = fluxW->getEventList(sp).getWeightedEventsNoTime(); + //get iterator to the first event that has momentum >= (*intersections.begin())[3] + std::vector::iterator start = el.begin(); + // check that el isn't empty + if ( start == el.end() ) continue; + while((*start).tof()<(*intersections.begin())[3]) ++start; + + double solid = sA->readY(d2mSA.find(detIDS[i])->second)[0]*PC; + + const size_t sizeOfMVD = intersections.front().size(); + // pre-allocate for efficiency + std::vector pos( sizeOfMVD + otherValues.size() ); + + for (auto it = intersections.begin()+1;it!=intersections.end();++it) { - //get intersections - std::vector intersections=calculateIntersections(detector); - - if(!intersections.empty()) + //Mantid::Kernel::VMD deltav=(*it)-(*(it-1));//difference between consecutive intersections + // the full vector isn't used so compute only what is necessary + double delta = (*it)[3] - (*(it-1))[3]; + + double eps = 1e-7;//do not integrate if momemntum difference is smaller than eps, assume contribution is 0 + if (delta > eps) + { + //Mantid::Kernel::VMD avev=((*it)+(*(it-1)))*0.5;//average between two intersection (to get position) + //std::vector pos = avev.toVector(); + //pos.insert(pos.end()-1,otherValues.begin(),otherValues.end()); + // a bit longer and less readable but faster version of the above + std::transform( it->getBareArray(), it->getBareArray() + sizeOfMVD, (it-1)->getBareArray(), pos.begin(), std::plus() ); + std::transform( pos.begin(), pos.begin() + sizeOfMVD, pos.begin(), std::bind2nd( std::multiplies(), 0.5 ) ); + std::copy( otherValues.begin(), otherValues.end(), pos.begin() + sizeOfMVD ); + + std::vector posNew = mat*pos; + size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data()); + + if(linIndex!=size_t(-1)) { - //calculate indices - //add to the correct signal at that particular index - //NOTE: if parallel it has to be atomic/critical - - //get event vector - size_t sp=d2m.find(detIDS[i])->second; - std::vector el=fluxW->getEventList(sp).getWeightedEventsNoTime(); - //get iterator to the first event that has momentum >= (*intersections.begin())[3] - std::vector::iterator start=el.begin(); - // check that el isn't empty - if ( start == el.end() ) continue; - while((*start).tof()<(*intersections.begin())[3]) ++start; - - double solid=sA->readY(d2mSA.find(detIDS[i])->second)[0]*PC; - - const size_t sizeOfMVD = intersections.front().size(); - // pre-allocate for efficiency - std::vector pos( sizeOfMVD + otherValues.size() ); - - for (auto it=intersections.begin()+1;it!=intersections.end();++it) - { - //Mantid::Kernel::VMD deltav=(*it)-(*(it-1));//difference between consecutive intersections - // the full vector isn't used so compute only what is necessary - double delta = (*it)[3] - (*(it-1))[3]; - - double eps=1e-7;//do not integrate if momemntum difference is smaller than eps, assume contribution is 0 - if (delta > eps) - { - //Mantid::Kernel::VMD avev=((*it)+(*(it-1)))*0.5;//average between two intersection (to get position) - //std::vector pos=avev.toVector(); - //pos.insert(pos.end()-1,otherValues.begin(),otherValues.end()); - // a bit longer and less readable but faster version of the above - std::transform( it->getBareArray(), it->getBareArray() + sizeOfMVD, (it-1)->getBareArray(), pos.begin(), std::plus() ); - std::transform( pos.begin(), pos.begin() + sizeOfMVD, pos.begin(), std::bind2nd( std::multiplies(), 0.5 ) ); - std::copy( otherValues.begin(), otherValues.end(), pos.begin() + sizeOfMVD ); - - std::vector posNew = mat*pos; - size_t linIndex=m_normWS->getLinearIndexAtCoord(posNew.data()); - - if(linIndex!=size_t(-1)) - { - double signal=0.; - while((*start).tof()<(*it)[3]) - { - if (start==el.end()) - break; - signal+=(*start).weight(); - ++start; - } - signal*=solid; - - PARALLEL_CRITICAL(updateMD) - { - signal+=m_normWS->getSignalAt(linIndex); - m_normWS->setSignalAt(linIndex,signal); - } - } - } - } - + double signal = 0.; + while((*start).tof()<(*it)[3]) + { + if (start==el.end()) + break; + signal+=(*start).weight(); + ++start; + } + signal*=solid; + + PARALLEL_CRITICAL(updateMD) + { + signal+=m_normWS->getSignalAt(linIndex); + m_normWS->setSignalAt(linIndex,signal); + } } + } } - prog->report(); - PARALLEL_END_INTERUPT_REGION + + } } - PARALLEL_CHECK_INTERUPT_REGION - delete prog; + prog->report(); + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + delete prog; } - + this->setProperty("OutputNormalizationWorkspace",m_normWS); - - } - - - std::vector SXDMDNorm::calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector) - { - std::vector intersections; - double th=detector->getTwoTheta(V3D(0,0,0),V3D(0,0,1)); - double phi=detector->getPhi(); - V3D q(-sin(th)*cos(phi),-sin(th)*sin(phi),1.-cos(th)); - q=transf*q; - double hStart=q.X()*KincidentMin,hEnd=q.X()*KincidentMax; - double kStart=q.Y()*KincidentMin,kEnd=q.Y()*KincidentMax; - double lStart=q.Z()*KincidentMin,lEnd=q.Z()*KincidentMax; - - double eps=1e-7; - - auto hNBins = m_hX.size(); - auto kNBins = m_kX.size(); - auto lNBins = m_lX.size(); - intersections.reserve( hNBins + kNBins + lNBins + 8 ); - - //calculate intersections with planes perpendicular to h - if (fabs(hStart-hEnd)>eps) + + } + + + std::vector SXDMDNorm::calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector) + { + std::vector intersections; + double th = detector->getTwoTheta(V3D(0,0,0),V3D(0,0,1)); + double phi = detector->getPhi(); + V3D q(-sin(th)*cos(phi),-sin(th)*sin(phi),1.-cos(th)); + q = transf*q; + double hStart = q.X()*KincidentMin,hEnd = q.X()*KincidentMax; + double kStart = q.Y()*KincidentMin,kEnd = q.Y()*KincidentMax; + double lStart = q.Z()*KincidentMin,lEnd = q.Z()*KincidentMax; + + double eps = 1e-7; + + auto hNBins = m_hX.size(); + auto kNBins = m_kX.size(); + auto lNBins = m_lX.size(); + intersections.reserve( hNBins + kNBins + lNBins + 8 ); + + //calculate intersections with planes perpendicular to h + if (fabs(hStart-hEnd)>eps) + { + double fmom=(KincidentMax-KincidentMin)/(hEnd-hStart); + double fk=(kEnd-kStart)/(hEnd-hStart); + double fl=(lEnd-lStart)/(hEnd-hStart); + if(!hIntegrated) { - double fmom=(KincidentMax-KincidentMin)/(hEnd-hStart); - double fk=(kEnd-kStart)/(hEnd-hStart); - double fl=(lEnd-lStart)/(hEnd-hStart); - if(!hIntegrated) + for(size_t i = 0;i=hMin)&&(hi<=hMax)&&((hStart-hi)*(hEnd-hi)<0)) { - for(size_t i=0;i=kMin)&&(ki<=kMax)&&(li>=lMin)&&(li<=lMax)) { - double hi = m_hX[i]; - if ((hi>=hMin)&&(hi<=hMax)&&((hStart-hi)*(hEnd-hi)<0)) - { - // if hi is between hStart and hEnd, then ki and li will be between kStart, kEnd and lStart, lEnd and momi will be between KincidentMin and KnincidemtmMax - double ki=fk*(hi-hStart)+kStart; - double li=fl*(hi-hStart)+lStart; - if ((ki>=kMin)&&(ki<=kMax)&&(li>=lMin)&&(li<=lMax)) - { - double momi=fmom*(hi-hStart)+KincidentMin; - Mantid::Kernel::VMD v(hi,ki,li,momi); - intersections.push_back(v); - } - } + double momi = fmom*(hi-hStart)+KincidentMin; + Mantid::Kernel::VMD v(hi,ki,li,momi); + intersections.push_back(v); } } - - double momhMin=fmom*(hMin-hStart)+KincidentMin; - if ((momhMin>KincidentMin)&&(momhMin=kMin)&&(khmin<=kMax)&&(lhmin>=lMin)&&(lhmin<=lMax)) - { - Mantid::Kernel::VMD v(hMin,khmin,lhmin,momhMin); - intersections.push_back(v); - } - } - double momhMax=fmom*(hMax-hStart)+KincidentMin; - if ((momhMax>KincidentMin)&&(momhMax=kMin)&&(khmax<=kMax)&&(lhmax>=lMin)&&(lhmax<=lMax)) - { - Mantid::Kernel::VMD v(hMax,khmax,lhmax,momhMax); - intersections.push_back(v); - } - } + } } - - //calculate intersections with planes perpendicular to k - if (fabs(kStart-kEnd)>eps) + + double momhMin = fmom*(hMin-hStart)+KincidentMin; + if ((momhMin>KincidentMin)&&(momhMin=kMin)&&(khmin<=kMax)&&(lhmin>=lMin)&&(lhmin<=lMax)) + { + Mantid::Kernel::VMD v(hMin,khmin,lhmin,momhMin); + intersections.push_back(v); + } + } + double momhMax = fmom*(hMax-hStart)+KincidentMin; + if ((momhMax>KincidentMin)&&(momhMax=kMin)&&(khmax<=kMax)&&(lhmax>=lMin)&&(lhmax<=lMax)) + { + Mantid::Kernel::VMD v(hMax,khmax,lhmax,momhMax); + intersections.push_back(v); + } + } + } + + //calculate intersections with planes perpendicular to k + if (fabs(kStart-kEnd)>eps) + { + double fmom=(KincidentMax-KincidentMin)/(kEnd-kStart); + double fh=(hEnd-hStart)/(kEnd-kStart); + double fl=(lEnd-lStart)/(kEnd-kStart); + if(!kIntegrated) { - double fmom=(KincidentMax-KincidentMin)/(kEnd-kStart); - double fh=(hEnd-hStart)/(kEnd-kStart); - double fl=(lEnd-lStart)/(kEnd-kStart); - if(!kIntegrated) + for(size_t i = 0;i=kMin)&&(ki<=kMax)&&((kStart-ki)*(kEnd-ki)<0)) { - for(size_t i=0;i=hMin)&&(hi<=hMax)&&(li>=lMin)&&(li<=lMax)) { - double ki = m_kX[i]; - if ((ki>=kMin)&&(ki<=kMax)&&((kStart-ki)*(kEnd-ki)<0)) - { - // if ki is between kStart and kEnd, then hi and li will be between hStart, hEnd and lStart, lEnd - double hi=fh*(ki-kStart)+hStart; - double li=fl*(ki-kStart)+lStart; - if ((hi>=hMin)&&(hi<=hMax)&&(li>=lMin)&&(li<=lMax)) - { - double momi=fmom*(ki-kStart)+KincidentMin; - Mantid::Kernel::VMD v(hi,ki,li,momi); - intersections.push_back(v); - } - } + double momi = fmom*(ki-kStart)+KincidentMin; + Mantid::Kernel::VMD v(hi,ki,li,momi); + intersections.push_back(v); } } - - double momkMin=fmom*(kMin-kStart)+KincidentMin; - if ((momkMin>KincidentMin)&&(momkMin=hMin)&&(hkmin<=hMax)&&(lkmin>=lMin)&&(lkmin<=lMax)) - { - Mantid::Kernel::VMD v(hkmin,kMin,lkmin,momkMin); - intersections.push_back(v); - } - } - double momkMax=fmom*(kMax-kStart)+KincidentMin; - if ((momkMax>KincidentMin)&&(momkMax=hMin)&&(hkmax<=hMax)&&(lkmax>=lMin)&&(lkmax<=lMax)) - { - Mantid::Kernel::VMD v(hkmax,kMax,lkmax,momkMax); - intersections.push_back(v); - } - } + } } - - //calculate intersections with planes perpendicular to l - if (fabs(lStart-lEnd)>eps) + + double momkMin = fmom*(kMin-kStart)+KincidentMin; + if ((momkMin>KincidentMin)&&(momkMin=hMin)&&(hkmin<=hMax)&&(lkmin>=lMin)&&(lkmin<=lMax)) + { + Mantid::Kernel::VMD v(hkmin,kMin,lkmin,momkMin); + intersections.push_back(v); + } + } + double momkMax = fmom*(kMax-kStart)+KincidentMin; + if ((momkMax>KincidentMin)&&(momkMax=hMin)&&(hkmax<=hMax)&&(lkmax>=lMin)&&(lkmax<=lMax)) + { + Mantid::Kernel::VMD v(hkmax,kMax,lkmax,momkMax); + intersections.push_back(v); + } + } + } + + //calculate intersections with planes perpendicular to l + if (fabs(lStart-lEnd)>eps) + { + double fmom=(KincidentMax-KincidentMin)/(lEnd-lStart); + double fh=(hEnd-hStart)/(lEnd-lStart); + double fk=(kEnd-kStart)/(lEnd-lStart); + if(!lIntegrated) + { + for(size_t i = 0;i=lMin)&&(li<=lMax)&&((lStart-li)*(lEnd-li)<0)) { - for(size_t i=0;i=hMin)&&(hi<=hMax)&&(ki>=kMin)&&(ki<=kMax)) { - double li = m_lX[i]; - if ((li>=lMin)&&(li<=lMax)&&((lStart-li)*(lEnd-li)<0)) - { - // if li is between lStart and lEnd, then hi and ki will be between hStart, hEnd and kStart, kEnd - double hi=fh*(li-lStart)+hStart; - double ki=fk*(li-lStart)+kStart; - if ((hi>=hMin)&&(hi<=hMax)&&(ki>=kMin)&&(ki<=kMax)) - { - double momi=fmom*(li-lStart)+KincidentMin; - Mantid::Kernel::VMD v(hi,ki,li,momi); - intersections.push_back(v); - } - } + double momi = fmom*(li-lStart)+KincidentMin; + Mantid::Kernel::VMD v(hi,ki,li,momi); + intersections.push_back(v); } } - - double momlMin=fmom*(lMin-lStart)+KincidentMin; - if ((momlMin>KincidentMin)&&(momlMin=hMin)&&(hlmin<=hMax)&&(klmin>=kMin)&&(klmin<=kMax)) - { - Mantid::Kernel::VMD v(hlmin,klmin,lMin,momlMin); - intersections.push_back(v); - } - } - double momlMax=fmom*(lMax-lStart)+KincidentMin; - if ((momlMax>KincidentMin)&&(momlMax=hMin)&&(hlmax<=hMax)&&(klmax>=kMin)&&(klmax<=kMax)) - { - Mantid::Kernel::VMD v(hlmax,klmax,lMax,momlMax); - intersections.push_back(v); - } - } + } } - - //add endpoints - if ((hStart>=hMin)&&(hStart<=hMax)&&(kStart>=kMin)&&(kStart<=kMax)&&(lStart>=lMin)&&(lStart<=lMax)) + + double momlMin = fmom*(lMin-lStart)+KincidentMin; + if ((momlMin>KincidentMin)&&(momlMin=hMin)&&(hlmin<=hMax)&&(klmin>=kMin)&&(klmin<=kMax)) + { + Mantid::Kernel::VMD v(hlmin,klmin,lMin,momlMin); intersections.push_back(v); + } } - if ((hEnd>=hMin)&&(hEnd<=hMax)&&(kEnd>=kMin)&&(kEnd<=kMax)&&(lEnd>=lMin)&&(lEnd<=lMax)) + double momlMax = fmom*(lMax-lStart)+KincidentMin; + if ((momlMax>KincidentMin)&&(momlMax=hMin)&&(hlmax<=hMax)&&(klmax>=kMin)&&(klmax<=kMax)) + { + Mantid::Kernel::VMD v(hlmax,klmax,lMax,momlMax); intersections.push_back(v); + } } - - //sort intersections by momentum - typedef std::vector::iterator IterType; - std::stable_sort(intersections.begin(),intersections.end(),compareMomentum); - - return intersections; - } - -} // namespace MDAlgorithms + } + + //add endpoints + if ((hStart>=hMin)&&(hStart<=hMax)&&(kStart>=kMin)&&(kStart<=kMax)&&(lStart>=lMin)&&(lStart<=lMax)) + { + Mantid::Kernel::VMD v(hStart,kStart,lStart,KincidentMin); + intersections.push_back(v); + } + if ((hEnd>=hMin)&&(hEnd<=hMax)&&(kEnd>=kMin)&&(kEnd<=kMax)&&(lEnd>=lMin)&&(lEnd<=lMax)) + { + Mantid::Kernel::VMD v(hEnd,kEnd,lEnd,KincidentMax); + intersections.push_back(v); + } + + //sort intersections by momentum + typedef std::vector::iterator IterType; + std::stable_sort(intersections.begin(),intersections.end(),compareMomentum); + + return intersections; + } + + } // namespace MDAlgorithms } // namespace Mantid From 16939fe2c709d2f88d3a34d13ca301be8877ab02 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Mon, 3 Nov 2014 14:17:54 +0000 Subject: [PATCH 02/41] Fix coverity warning about variable initiliaization. Refs #10470 --- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 0bf45a63c653..b8e3ac3dc627 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -26,36 +26,18 @@ namespace Mantid // Register the algorithm into the AlgorithmFactory DECLARE_ALGORITHM(SXDMDNorm) - - //---------------------------------------------------------------------------------------------- /** Constructor */ - SXDMDNorm::SXDMDNorm() + SXDMDNorm::SXDMDNorm() : + m_nDims(0), m_normWS(), m_inputWS(), hMin(0.0f), hMax(0.0f), + kMin(0.0f), kMax(0.0f), lMin(0.0f), lMax(0.0f), hIntegrated(true), + kIntegrated(true), lIntegrated(true), transf(3,3), + KincidentMin(0.0), KincidentMax(EMPTY_DBL()), hIndex(-1), kIndex(-1), lIndex(-1), + m_hX(), m_kX(), m_lX() { - hIndex = -1; - kIndex = -1; - lIndex = -1; - hIntegrated = true; - kIntegrated = true; - lIntegrated = true; - m_nDims = 0; - transf = Mantid::Kernel::DblMatrix(3,3); - KincidentMin = 0; - KincidentMax = EMPTY_DBL(); } - //---------------------------------------------------------------------------------------------- - /** Destructor - */ - SXDMDNorm::~SXDMDNorm() - { - } - - - //---------------------------------------------------------------------------------------------- - - /// Algorithm's version for identification. @see Algorithm::version int SXDMDNorm::version() const { return 1; } From 6b342300794f6c877595cf7a523b9f28b2e69492 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Mon, 3 Nov 2014 14:19:51 +0000 Subject: [PATCH 03/41] Use int64 for omp loop variable. Refs #10470 --- Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index b8e3ac3dc627..2ba216a84774 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -284,7 +284,7 @@ namespace Mantid auto instrument = m_normWS->getExperimentInfo(0)->getInstrument(); PARALLEL_FOR1(m_normWS) - for(int i = 0;i(detIDS.size());i++) + for(int64_t i = 0;i < static_cast(detIDS.size()); i++) { PARALLEL_START_INTERUPT_REGION Mantid::Geometry::IDetector_const_sptr detector = instrument->getDetector(detIDS[i]); From 39f2d5e214b6cccc115b47b4064701f557fd23e3 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Mon, 3 Nov 2014 16:01:26 +0000 Subject: [PATCH 04/41] First set of refactorings. Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 11 +- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 166 ++++++++++-------- 2 files changed, 102 insertions(+), 75 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index 20b2f4c822fd..14da959f7e64 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -8,8 +8,6 @@ namespace Mantid { namespace MDAlgorithms { - bool compareMomentum(Mantid::Kernel::VMD v1, Mantid::Kernel::VMD v2); - /** SXDMDNorm : Generate MD normalization for single crystal diffraction @@ -47,16 +45,19 @@ namespace Mantid private: void init(); void exec(); + + /// Retrieve the energy transfer mode of the input workspace data + std::string inputEnergyMode() const; /// function to calculate intersections of teh trajectory with MDBoxes - std::vector calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector); + std::vector calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector); /// number of MD dimensions size_t m_nDims; /// Normalization workspace - Mantid::MDEvents::MDHistoWorkspace_sptr m_normWS; + MDEvents::MDHistoWorkspace_sptr m_normWS; /// Input workspace - Mantid::API::IMDEventWorkspace_sptr m_inputWS; + API::IMDEventWorkspace_sptr m_inputWS; ///limits for h,k,l dimensions coord_t hMin,hMax,kMin,kMax,lMin,lMax; ///flag for integrated h,k,l dimensions diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 2ba216a84774..ec227e897974 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -17,18 +17,22 @@ namespace Mantid using namespace Mantid::API; using namespace Mantid::Kernel; - ///function to compare two intersections (h,k,l,Momentum) by Momentum - bool compareMomentum(const Mantid::Kernel::VMD &v1, const Mantid::Kernel::VMD &v2) + namespace { - return (v1[3]("InputWorkspace","",Direction::Input), @@ -89,38 +94,15 @@ namespace Mantid } //---------------------------------------------------------------------------------------------- - /** Execute the algorithm. - */ + /** + * Execute the algorithm. + */ void SXDMDNorm::exec() { - bool skipProcessing = false; m_inputWS = getProperty("InputWorkspace"); - WorkspaceHistory hist = m_inputWS->getHistory(); - std::string dEMode(""); - if (hist.lastAlgorithm()->name()=="ConvertToMD") - { - dEMode = hist.lastAlgorithm()->getPropertyValue("dEAnalysisMode"); - } - else if ( ((hist.lastAlgorithm()->name() == "Load") || (hist.lastAlgorithm()->name() == "LoadMD")) && - (hist.getAlgorithmHistory(hist.size()-2)->name() == "ConvertToMD") ) - { - //get dEAnalysisMode - PropertyHistories histvec = hist.getAlgorithmHistory(hist.size()-2)->getProperties(); - for(auto it = histvec.begin();it != histvec.end(); ++it) - { - if((*it)->name()=="dEAnalysisMode") - { - dEMode=(*it)->value(); - } - } - } - else - { - throw std::runtime_error("The last algorithm in the history of the input workspace is not ConvertToMD"); - } - if (dEMode!="Elastic") + if( inputEnergyMode() != "Elastic" ) { - throw std::runtime_error("This is not elastic scattering data"); + throw std::invalid_argument("Invalid energy transfer mode. Algorithm currently only supports elastic data."); } hMin = m_inputWS->getDimension(0)->getMinimum(); kMin = m_inputWS->getDimension(1)->getMinimum(); @@ -138,16 +120,18 @@ namespace Mantid lIndex = -1; //check for other dimensions if we could measure anything in the original data + bool skipProcessing = false; + const auto exptInfoZero = m_inputWS->getExperimentInfo(0); std::vector otherValues; - for(size_t i = 3;i < m_inputWS->getNumDims(); i++) + for(size_t i = 3; i < m_inputWS->getNumDims(); i++) { - float dimMin = static_cast(m_inputWS->getDimension(i)->getMinimum()); - float dimMax = static_cast(m_inputWS->getDimension(i)->getMaximum()); - Kernel::TimeSeriesProperty *run_property = \ - dynamic_cast *>(m_inputWS->getExperimentInfo(0)->run().getProperty(m_inputWS->getDimension(i)->getName())); - if (run_property!=NULL) + const auto dimension = m_inputWS->getDimension(i); + float dimMin = static_cast(dimension->getMinimum()); + float dimMax = static_cast(dimension->getMaximum()); + auto *dimProp = dynamic_cast *>(exptInfoZero->run().getProperty(dimension->getName())); + if (dimProp) { - coord_t value = static_cast(run_property->firstValue()); + coord_t value = static_cast(dimProp->firstValue()); otherValues.push_back(value); //in the original MD data no time was spent measuring between dimMin and dimMax if (value < dimMin || value > dimMax) @@ -155,7 +139,6 @@ namespace Mantid skipProcessing = true; } } - delete run_property; } // Run BinMD @@ -174,13 +157,13 @@ namespace Mantid this->setProperty("OutputWorkspace", outputWS); //copy the MDHisto workspace, and change signals and errors to 0. - m_normWS = MDHistoWorkspace_sptr(new MDHistoWorkspace(*(boost::dynamic_pointer_cast(outputWS)))); + m_normWS = boost::make_shared(*(boost::dynamic_pointer_cast(outputWS))); m_normWS->setTo(0.,0.,0.); //get indices of the original dimensions in the output workspace, and if not found, the corresponding dimension is integrated - Mantid::Kernel::Matrix mat = m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); + Kernel::Matrix mat = m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); - for (size_t row = 0; rowgetDimension(row)->getMinimum()) hMin = m_normWS->getDimension(row)->getMinimum(); if(hMax>m_normWS->getDimension(row)->getMaximum()) hMax = m_normWS->getDimension(row)->getMaximum(); - if((hMin>m_normWS->getDimension(row)->getMaximum())||(hMaxgetDimension(row)->getMinimum())) + if((hMin>m_normWS->getDimension(row)->getMaximum()) || (hMaxgetDimension(row)->getMinimum())) { skipProcessing = true; } } - if(mat[row][1]==1.) + if(mat[row][1] == 1.) { kIntegrated = false; kIndex = row; if(kMingetDimension(row)->getMinimum()) kMin = m_normWS->getDimension(row)->getMinimum(); if(kMax>m_normWS->getDimension(row)->getMaximum()) kMax = m_normWS->getDimension(row)->getMaximum(); - if((kMin>m_normWS->getDimension(row)->getMaximum())||(kMaxgetDimension(row)->getMinimum())) + if((kMin>m_normWS->getDimension(row)->getMaximum()) || (kMaxgetDimension(row)->getMinimum())) { skipProcessing = true; } } - if(mat[row][2]==1.) + if(mat[row][2] == 1.) { lIntegrated = false; lIndex = row; if(lMingetDimension(row)->getMinimum()) lMin = m_normWS->getDimension(row)->getMinimum(); if(lMax>m_normWS->getDimension(row)->getMaximum()) lMax = m_normWS->getDimension(row)->getMaximum(); - if((lMin>m_normWS->getDimension(row)->getMaximum())||(lMaxgetDimension(row)->getMinimum())) + if((lMin>m_normWS->getDimension(row)->getMaximum()) || (lMaxgetDimension(row)->getMinimum())) { skipProcessing = true; } - for(size_t col = 3;colm_normWS->getDimension(row)->getMaximum())||(valgetDimension(row)->getMinimum())) + double val = otherValues.at(col - 3); + if((val>m_normWS->getDimension(row)->getMaximum()) || (valgetDimension(row)->getMinimum())) { skipProcessing = true; } @@ -250,14 +233,13 @@ namespace Mantid m_lX[i] = lDim.getX(i); } - Mantid::API::MatrixWorkspace_const_sptr fW = getProperty("FluxWorkspace"); - Mantid::DataObjects::EventWorkspace_const_sptr fluxW = boost::dynamic_pointer_cast(fW); + API::MatrixWorkspace_const_sptr fW = getProperty("FluxWorkspace"); + DataObjects::EventWorkspace_const_sptr fluxW = boost::dynamic_pointer_cast(fW); KincidentMin = fluxW->getEventXMin(); KincidentMax = fluxW->getEventXMax(); - Mantid::API::MatrixWorkspace_const_sptr sA = getProperty("SolidAngleWorkspace"); - - - if (skipProcessing) + API::MatrixWorkspace_const_sptr sA = getProperty("SolidAngleWorkspace"); + + if(skipProcessing) { g_log.warning("Binning limits are outside the limits of the MDWorkspace\n"); } @@ -287,8 +269,9 @@ namespace Mantid for(int64_t i = 0;i < static_cast(detIDS.size()); i++) { PARALLEL_START_INTERUPT_REGION - Mantid::Geometry::IDetector_const_sptr detector = instrument->getDetector(detIDS[i]); - if(!detector->isMonitor()&&!detector->isMasked()) + + Mantid::Geometry::IDetector_const_sptr detector = instrument->getDetector(detIDS[i]); + if(!detector->isMonitor() && !detector->isMasked()) { //get intersections std::vector intersections = calculateIntersections(detector); @@ -358,20 +341,63 @@ namespace Mantid } } prog->report(); + PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION - delete prog; + + delete prog; } this->setProperty("OutputNormalizationWorkspace",m_normWS); } - - std::vector SXDMDNorm::calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector) + /** + * Currently looks for the ConvertToMD algorithm in the history + * @return A string donating the energy transfer mode of the input workspace + */ + std::string SXDMDNorm::inputEnergyMode() const + { + const auto & hist = m_inputWS->getHistory(); + const size_t nalgs = hist.size(); + const auto & lastAlgorithm = hist.lastAlgorithm(); + + std::string emode(""); + if(lastAlgorithm->name() == "ConvertToMD") + { + emode = lastAlgorithm->getPropertyValue("dEAnalysisMode"); + } + else if ( (lastAlgorithm->name() == "Load" || hist.lastAlgorithm()->name() == "LoadMD") && + hist.getAlgorithmHistory(nalgs - 2)->name() == "ConvertToMD" ) + { + //get dEAnalysisMode + PropertyHistories histvec = hist.getAlgorithmHistory(nalgs - 2)->getProperties(); + for(auto it = histvec.begin(); it != histvec.end(); ++it) + { + if((*it)->name() == "dEAnalysisMode") + { + emode = (*it)->value(); + break; + } + } + } + else + { + throw std::invalid_argument("The last algorithm in the history of the input workspace is not ConvertToMD"); + } + return emode; + } + + /** + * Calculate the points of intersection for the given detector with cuboid surrounding the + * detector position in HKL + * @param detector A pointer to a detectir object + * @return A list of intersections in HKL space + */ + std::vector SXDMDNorm::calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector) { - std::vector intersections; + std::vector intersections; double th = detector->getTwoTheta(V3D(0,0,0),V3D(0,0,1)); double phi = detector->getPhi(); V3D q(-sin(th)*cos(phi),-sin(th)*sin(phi),1.-cos(th)); @@ -385,10 +411,10 @@ namespace Mantid auto hNBins = m_hX.size(); auto kNBins = m_kX.size(); auto lNBins = m_lX.size(); - intersections.reserve( hNBins + kNBins + lNBins + 8 ); + intersections.reserve(hNBins + kNBins + lNBins + 8); //calculate intersections with planes perpendicular to h - if (fabs(hStart-hEnd)>eps) + if (fabs(hStart-hEnd) > eps) { double fmom=(KincidentMax-KincidentMin)/(hEnd-hStart); double fk=(kEnd-kStart)/(hEnd-hStart); @@ -398,7 +424,7 @@ namespace Mantid for(size_t i = 0;i=hMin)&&(hi<=hMax)&&((hStart-hi)*(hEnd-hi)<0)) + if((hi>=hMin)&&(hi<=hMax) && ((hStart-hi)*(hEnd-hi)<0)) { // if hi is between hStart and hEnd, then ki and li will be between kStart, kEnd and lStart, lEnd and momi will be between KincidentMin and KnincidemtmMax double ki = fk*(hi-hStart)+kStart; From c6ecf32eae8a4ae9667d8bfae003490b4782cfdf Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Mon, 3 Nov 2014 17:51:05 +0000 Subject: [PATCH 05/41] Continuing with refactoring: * Start to functionalise the algorithm * Follow coding standard for member variables names Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 28 +- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 333 ++++++++++-------- 2 files changed, 195 insertions(+), 166 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index 14da959f7e64..e70e217d7b0c 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -46,11 +46,13 @@ namespace Mantid void init(); void exec(); - /// Retrieve the energy transfer mode of the input workspace data std::string inputEnergyMode() const; - - /// function to calculate intersections of teh trajectory with MDBoxes - std::vector calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector); + void initCaches(); + std::vector getValuesFromOtherDimensions(bool & skipNormalization) const; + MDEvents::MDHistoWorkspace_sptr binInputWS(); + + /// function to calculate intersections of the trajectory with MDBoxes + std::vector calculateIntersections(const Geometry::IDetector_const_sptr &detector); /// number of MD dimensions size_t m_nDims; @@ -58,17 +60,17 @@ namespace Mantid MDEvents::MDHistoWorkspace_sptr m_normWS; /// Input workspace API::IMDEventWorkspace_sptr m_inputWS; - ///limits for h,k,l dimensions - coord_t hMin,hMax,kMin,kMax,lMin,lMax; - ///flag for integrated h,k,l dimensions - bool hIntegrated,kIntegrated,lIntegrated; - ///(2*PiRUBW)^-1 - Mantid::Kernel::DblMatrix transf; + /// limits for h,k,l dimensions + coord_t m_hmin, m_hmax, m_kmin, m_kmax, m_lmin, m_lmax; + /// flag for integrated h,k,l dimensions + bool m_hIntegrated, m_kIntegrated, m_lIntegrated; + /// (2*PiRUBW)^-1 + Mantid::Kernel::DblMatrix m_rubw; /// limits for momentum - double KincidentMin,KincidentMax; + double m_kiMin, m_kiMax; ///index of h,k,l dimensions in the output workspaces - size_t hIndex,kIndex,lIndex; - /// cached x values along dimensions h,k,l + size_t m_hIdx, m_kIdx, m_lIdx; + /// cached X values along dimensions h,k,l std::vector m_hX, m_kX, m_lX; }; diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index ec227e897974..25f4504a31b8 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -34,10 +34,10 @@ namespace Mantid * Constructor */ SXDMDNorm::SXDMDNorm() : - m_nDims(0), m_normWS(), m_inputWS(), hMin(0.0f), hMax(0.0f), - kMin(0.0f), kMax(0.0f), lMin(0.0f), lMax(0.0f), hIntegrated(true), - kIntegrated(true), lIntegrated(true), transf(3,3), - KincidentMin(0.0), KincidentMax(EMPTY_DBL()), hIndex(-1), kIndex(-1), lIndex(-1), + m_nDims(0), m_normWS(), m_inputWS(), m_hmin(0.0f), m_hmax(0.0f), + m_kmin(0.0f), m_kmax(0.0f), m_lmin(0.0f), m_lmax(0.0f), m_hIntegrated(true), + m_kIntegrated(true), m_lIntegrated(true), m_rubw(3,3), + m_kiMin(0.0), m_kiMax(EMPTY_DBL()), m_hIdx(-1), m_kIdx(-1), m_lIdx(-1), m_hX(), m_kX(), m_lX() { } @@ -99,65 +99,16 @@ namespace Mantid */ void SXDMDNorm::exec() { - m_inputWS = getProperty("InputWorkspace"); - if( inputEnergyMode() != "Elastic" ) - { - throw std::invalid_argument("Invalid energy transfer mode. Algorithm currently only supports elastic data."); - } - hMin = m_inputWS->getDimension(0)->getMinimum(); - kMin = m_inputWS->getDimension(1)->getMinimum(); - lMin = m_inputWS->getDimension(2)->getMinimum(); - hMax = m_inputWS->getDimension(0)->getMaximum(); - kMax = m_inputWS->getDimension(1)->getMaximum(); - lMax = m_inputWS->getDimension(2)->getMaximum(); - - //initialize some variables - hIntegrated = true; - kIntegrated = true; - lIntegrated = true; - hIndex = -1; - kIndex = -1; - lIndex = -1; - - //check for other dimensions if we could measure anything in the original data - bool skipProcessing = false; - const auto exptInfoZero = m_inputWS->getExperimentInfo(0); - std::vector otherValues; - for(size_t i = 3; i < m_inputWS->getNumDims(); i++) - { - const auto dimension = m_inputWS->getDimension(i); - float dimMin = static_cast(dimension->getMinimum()); - float dimMax = static_cast(dimension->getMaximum()); - auto *dimProp = dynamic_cast *>(exptInfoZero->run().getProperty(dimension->getName())); - if (dimProp) - { - coord_t value = static_cast(dimProp->firstValue()); - otherValues.push_back(value); - //in the original MD data no time was spent measuring between dimMin and dimMax - if (value < dimMin || value > dimMax) - { - skipProcessing = true; - } - } - } - - // Run BinMD - Workspace_sptr outputWS = getProperty("OutputWorkspace"); - auto props = getProperties(); - IAlgorithm_sptr bin = createChildAlgorithm("BinMD",0.0,0.3); - bin->setPropertyValue("AxisAligned","1"); - for(auto it = props.begin(); it != props.end(); ++it) - { - if(((*it)->name() != "FluxWorkspace") && ((*it)->name()!="SolidAngleWorkspace") && - ((*it)->name() != "OutputNormalizationWorkspace")) - bin->setPropertyValue((*it)->name(),(*it)->value()); - } - bin->executeAsChildAlg(); - outputWS = bin->getProperty("OutputWorkspace"); - this->setProperty("OutputWorkspace", outputWS); + initCaches(); + + // Check for other dimensions if we could measure anything in the original data + bool skipNormalization = false; + const std::vector otherValues = getValuesFromOtherDimensions(skipNormalization); + auto outputWS = binInputWS(); + this->setProperty("OutputWorkspace", outputWS); - //copy the MDHisto workspace, and change signals and errors to 0. - m_normWS = boost::make_shared(*(boost::dynamic_pointer_cast(outputWS))); + // Copy the MDHisto workspace, and change signals and errors to 0. + m_normWS = boost::make_shared(*outputWS); m_normWS->setTo(0.,0.,0.); //get indices of the original dimensions in the output workspace, and if not found, the corresponding dimension is integrated @@ -167,35 +118,35 @@ namespace Mantid { if(mat[row][0]==1.) { - hIntegrated = false; - hIndex = row; - if(hMingetDimension(row)->getMinimum()) hMin = m_normWS->getDimension(row)->getMinimum(); - if(hMax>m_normWS->getDimension(row)->getMaximum()) hMax = m_normWS->getDimension(row)->getMaximum(); - if((hMin>m_normWS->getDimension(row)->getMaximum()) || (hMaxgetDimension(row)->getMinimum())) + m_hIntegrated = false; + m_hIdx = row; + if(m_hmingetDimension(row)->getMinimum()) m_hmin = m_normWS->getDimension(row)->getMinimum(); + if(m_hmax>m_normWS->getDimension(row)->getMaximum()) m_hmax = m_normWS->getDimension(row)->getMaximum(); + if((m_hmin>m_normWS->getDimension(row)->getMaximum()) || (m_hmaxgetDimension(row)->getMinimum())) { - skipProcessing = true; + skipNormalization = true; } } if(mat[row][1] == 1.) { - kIntegrated = false; - kIndex = row; - if(kMingetDimension(row)->getMinimum()) kMin = m_normWS->getDimension(row)->getMinimum(); - if(kMax>m_normWS->getDimension(row)->getMaximum()) kMax = m_normWS->getDimension(row)->getMaximum(); - if((kMin>m_normWS->getDimension(row)->getMaximum()) || (kMaxgetDimension(row)->getMinimum())) + m_kIntegrated = false; + m_kIdx = row; + if(m_kmingetDimension(row)->getMinimum()) m_kmin = m_normWS->getDimension(row)->getMinimum(); + if(m_kmax>m_normWS->getDimension(row)->getMaximum()) m_kmax = m_normWS->getDimension(row)->getMaximum(); + if((m_kmin>m_normWS->getDimension(row)->getMaximum()) || (m_kmaxgetDimension(row)->getMinimum())) { - skipProcessing = true; + skipNormalization = true; } } if(mat[row][2] == 1.) { - lIntegrated = false; - lIndex = row; - if(lMingetDimension(row)->getMinimum()) lMin = m_normWS->getDimension(row)->getMinimum(); - if(lMax>m_normWS->getDimension(row)->getMaximum()) lMax = m_normWS->getDimension(row)->getMaximum(); - if((lMin>m_normWS->getDimension(row)->getMaximum()) || (lMaxgetDimension(row)->getMinimum())) + m_lIntegrated = false; + m_lIdx = row; + if(m_lmingetDimension(row)->getMinimum()) m_lmin = m_normWS->getDimension(row)->getMinimum(); + if(m_lmax>m_normWS->getDimension(row)->getMaximum()) m_lmax = m_normWS->getDimension(row)->getMaximum(); + if((m_lmin>m_normWS->getDimension(row)->getMaximum()) || (m_lmaxgetDimension(row)->getMinimum())) { - skipProcessing = true; + skipNormalization = true; } for(size_t col = 3;col < mat.numCols()-1; col++) //affine matrix, ignore last column @@ -205,28 +156,28 @@ namespace Mantid double val = otherValues.at(col - 3); if((val>m_normWS->getDimension(row)->getMaximum()) || (valgetDimension(row)->getMinimum())) { - skipProcessing = true; + skipNormalization = true; } } } } } - auto &hDim = *m_normWS->getDimension(hIndex); + auto &hDim = *m_normWS->getDimension(m_hIdx); m_hX.resize( hDim.getNBins() ); for(size_t i = 0; i < m_hX.size(); ++i) { m_hX[i] = hDim.getX(i); } - auto &kDim = *m_normWS->getDimension(kIndex); + auto &kDim = *m_normWS->getDimension(m_kIdx); m_kX.resize( kDim.getNBins() ); for(size_t i = 0; i < m_kX.size(); ++i) { m_kX[i] = kDim.getX(i); } - auto &lDim = *m_normWS->getDimension(lIndex); + auto &lDim = *m_normWS->getDimension(m_lIdx); m_lX.resize( lDim.getNBins() ); for(size_t i = 0; i < m_lX.size(); ++i) { @@ -235,11 +186,11 @@ namespace Mantid API::MatrixWorkspace_const_sptr fW = getProperty("FluxWorkspace"); DataObjects::EventWorkspace_const_sptr fluxW = boost::dynamic_pointer_cast(fW); - KincidentMin = fluxW->getEventXMin(); - KincidentMax = fluxW->getEventXMax(); + m_kiMin = fluxW->getEventXMin(); + m_kiMax = fluxW->getEventXMax(); API::MatrixWorkspace_const_sptr sA = getProperty("SolidAngleWorkspace"); - if(skipProcessing) + if(skipNormalization) { g_log.warning("Binning limits are outside the limits of the MDWorkspace\n"); } @@ -254,8 +205,8 @@ namespace Mantid else { Mantid::Kernel::DblMatrix RUBW((*prop)()); //includes the 2*pi factor but not goniometer for now :) - transf = m_normWS->getExperimentInfo(0)->run().getGoniometerMatrix()*RUBW; - transf.Invert(); + m_rubw = m_normWS->getExperimentInfo(0)->run().getGoniometerMatrix()*RUBW; + m_rubw.Invert(); } //FIXME: the detector positions are from the IDF. Need to account for calibration std::vector detIDS = m_normWS->getExperimentInfo(0)->getInstrument()->getDetectorIDs(true); @@ -266,7 +217,7 @@ namespace Mantid auto instrument = m_normWS->getExperimentInfo(0)->getInstrument(); PARALLEL_FOR1(m_normWS) - for(int64_t i = 0;i < static_cast(detIDS.size()); i++) + for(int64_t i = 0; i < static_cast(detIDS.size()); i++) { PARALLEL_START_INTERUPT_REGION @@ -389,49 +340,125 @@ namespace Mantid return emode; } + /** + * Set up starting values for cached variables + */ + void SXDMDNorm::initCaches() + { + m_inputWS = getProperty("InputWorkspace"); + if( inputEnergyMode() != "Elastic" ) + { + throw std::invalid_argument("Invalid energy transfer mode. Algorithm currently only supports elastic data."); + } + // Min/max dimension values + const auto hdim(m_inputWS->getDimension(0)), kdim(m_inputWS->getDimension(1)), + ldim(m_inputWS->getDimension(2)); + m_hmin = hdim->getMinimum(); + m_kmin = kdim->getMinimum(); + m_lmin = ldim->getMinimum(); + m_hmax = hdim->getMaximum(); + m_kmax = kdim->getMaximum(); + m_lmax = ldim->getMaximum(); + } + + /** + * Retrieve logged values from non-HKL dimensions + * @param skipNormalization [InOut] Updated to false if any values are outside range measured by input workspace + * @return A vector of values from other dimensions to be include in normalized MD position calculation + */ + std::vector SXDMDNorm::getValuesFromOtherDimensions(bool &skipNormalization) const + { + const auto & runZero = m_inputWS->getExperimentInfo(0)->run(); + + std::vector otherDimValues; + for(size_t i = 3; i < m_inputWS->getNumDims(); i++) + { + const auto dimension = m_inputWS->getDimension(i); + float dimMin = static_cast(dimension->getMinimum()); + float dimMax = static_cast(dimension->getMaximum()); + auto *dimProp = \ + dynamic_cast *>(runZero.getProperty(dimension->getName())); + if (dimProp) + { + coord_t value = static_cast(dimProp->firstValue()); + otherDimValues.push_back(value); + //in the original MD data no time was spent measuring between dimMin and dimMax + if (value < dimMin || value > dimMax) + { + skipNormalization = true; + } + } + } + return otherDimValues; + } + + /** + * Runs the BinMD algorithm on the input to provide the output workspace + * All slicing algorithm properties are passed along + * @return MDHistoWorkspace as a result of the binning + */ + MDHistoWorkspace_sptr SXDMDNorm::binInputWS() + { + const auto & props = getProperties(); + IAlgorithm_sptr binMD = createChildAlgorithm("BinMD", 0.0, 0.3); + binMD->setPropertyValue("AxisAligned","1"); + for(auto it = props.begin(); it != props.end(); ++it) + { + const auto & propName = (*it)->name(); + if(propName != "FluxWorkspace" && propName != "SolidAngleWorkspace" && + propName != "OutputNormalizationWorkspace") + { + binMD->setPropertyValue(propName,(*it)->value()); + } + } + binMD->executeAsChildAlg(); + Workspace_sptr outputWS = binMD->getProperty("OutputWorkspace"); + return boost::dynamic_pointer_cast(outputWS); + } + /** * Calculate the points of intersection for the given detector with cuboid surrounding the * detector position in HKL - * @param detector A pointer to a detectir object + * @param detector A pointer to a detector object * @return A list of intersections in HKL space */ - std::vector SXDMDNorm::calculateIntersections(Mantid::Geometry::IDetector_const_sptr detector) + std::vector SXDMDNorm::calculateIntersections(const Geometry::IDetector_const_sptr & detector) { - std::vector intersections; double th = detector->getTwoTheta(V3D(0,0,0),V3D(0,0,1)); double phi = detector->getPhi(); V3D q(-sin(th)*cos(phi),-sin(th)*sin(phi),1.-cos(th)); - q = transf*q; - double hStart = q.X()*KincidentMin,hEnd = q.X()*KincidentMax; - double kStart = q.Y()*KincidentMin,kEnd = q.Y()*KincidentMax; - double lStart = q.Z()*KincidentMin,lEnd = q.Z()*KincidentMax; + q = m_rubw*q; + double hStart = q.X()*m_kiMin,hEnd = q.X()*m_kiMax; + double kStart = q.Y()*m_kiMin,kEnd = q.Y()*m_kiMax; + double lStart = q.Z()*m_kiMin,lEnd = q.Z()*m_kiMax; double eps = 1e-7; auto hNBins = m_hX.size(); auto kNBins = m_kX.size(); auto lNBins = m_lX.size(); + std::vector intersections; intersections.reserve(hNBins + kNBins + lNBins + 8); //calculate intersections with planes perpendicular to h if (fabs(hStart-hEnd) > eps) { - double fmom=(KincidentMax-KincidentMin)/(hEnd-hStart); + double fmom=(m_kiMax-m_kiMin)/(hEnd-hStart); double fk=(kEnd-kStart)/(hEnd-hStart); double fl=(lEnd-lStart)/(hEnd-hStart); - if(!hIntegrated) + if(!m_hIntegrated) { for(size_t i = 0;i=hMin)&&(hi<=hMax) && ((hStart-hi)*(hEnd-hi)<0)) + if((hi>=m_hmin)&&(hi<=m_hmax) && ((hStart-hi)*(hEnd-hi)<0)) { - // if hi is between hStart and hEnd, then ki and li will be between kStart, kEnd and lStart, lEnd and momi will be between KincidentMin and KnincidemtmMax + // if hi is between hStart and hEnd, then ki and li will be between kStart, kEnd and lStart, lEnd and momi will be between m_kiMin and KnincidemtmMax double ki = fk*(hi-hStart)+kStart; double li = fl*(hi-hStart)+lStart; - if ((ki>=kMin)&&(ki<=kMax)&&(li>=lMin)&&(li<=lMax)) + if ((ki>=m_kmin)&&(ki<=m_kmax)&&(li>=m_lmin)&&(li<=m_lmax)) { - double momi = fmom*(hi-hStart)+KincidentMin; + double momi = fmom*(hi-hStart)+m_kiMin; Mantid::Kernel::VMD v(hi,ki,li,momi); intersections.push_back(v); } @@ -439,27 +466,27 @@ namespace Mantid } } - double momhMin = fmom*(hMin-hStart)+KincidentMin; - if ((momhMin>KincidentMin)&&(momhMinm_kiMin)&&(momhMin=kMin)&&(khmin<=kMax)&&(lhmin>=lMin)&&(lhmin<=lMax)) + double khmin = fk*(m_hmin-hStart)+kStart; + double lhmin = fl*(m_hmin-hStart)+lStart; + if((khmin>=m_kmin)&&(khmin<=m_kmax)&&(lhmin>=m_lmin)&&(lhmin<=m_lmax)) { - Mantid::Kernel::VMD v(hMin,khmin,lhmin,momhMin); + Mantid::Kernel::VMD v(m_hmin,khmin,lhmin,momhMin); intersections.push_back(v); } } - double momhMax = fmom*(hMax-hStart)+KincidentMin; - if ((momhMax>KincidentMin)&&(momhMaxm_kiMin)&&(momhMax=kMin)&&(khmax<=kMax)&&(lhmax>=lMin)&&(lhmax<=lMax)) + double khmax = fk*(m_hmax-hStart)+kStart; + double lhmax = fl*(m_hmax-hStart)+lStart; + if((khmax>=m_kmin)&&(khmax<=m_kmax)&&(lhmax>=m_lmin)&&(lhmax<=m_lmax)) { - Mantid::Kernel::VMD v(hMax,khmax,lhmax,momhMax); + Mantid::Kernel::VMD v(m_hmax,khmax,lhmax,momhMax); intersections.push_back(v); } } @@ -468,22 +495,22 @@ namespace Mantid //calculate intersections with planes perpendicular to k if (fabs(kStart-kEnd)>eps) { - double fmom=(KincidentMax-KincidentMin)/(kEnd-kStart); + double fmom=(m_kiMax-m_kiMin)/(kEnd-kStart); double fh=(hEnd-hStart)/(kEnd-kStart); double fl=(lEnd-lStart)/(kEnd-kStart); - if(!kIntegrated) + if(!m_kIntegrated) { for(size_t i = 0;i=kMin)&&(ki<=kMax)&&((kStart-ki)*(kEnd-ki)<0)) + if ((ki>=m_kmin)&&(ki<=m_kmax)&&((kStart-ki)*(kEnd-ki)<0)) { // if ki is between kStart and kEnd, then hi and li will be between hStart, hEnd and lStart, lEnd double hi = fh*(ki-kStart)+hStart; double li = fl*(ki-kStart)+lStart; - if ((hi>=hMin)&&(hi<=hMax)&&(li>=lMin)&&(li<=lMax)) + if ((hi>=m_hmin)&&(hi<=m_hmax)&&(li>=m_lmin)&&(li<=m_lmax)) { - double momi = fmom*(ki-kStart)+KincidentMin; + double momi = fmom*(ki-kStart)+m_kiMin; Mantid::Kernel::VMD v(hi,ki,li,momi); intersections.push_back(v); } @@ -491,27 +518,27 @@ namespace Mantid } } - double momkMin = fmom*(kMin-kStart)+KincidentMin; - if ((momkMin>KincidentMin)&&(momkMinm_kiMin)&&(momkMin=hMin)&&(hkmin<=hMax)&&(lkmin>=lMin)&&(lkmin<=lMax)) + double hkmin = fh*(m_kmin-kStart)+hStart; + double lkmin = fl*(m_kmin-kStart)+lStart; + if((hkmin>=m_hmin)&&(hkmin<=m_hmax)&&(lkmin>=m_lmin)&&(lkmin<=m_lmax)) { - Mantid::Kernel::VMD v(hkmin,kMin,lkmin,momkMin); + Mantid::Kernel::VMD v(hkmin,m_kmin,lkmin,momkMin); intersections.push_back(v); } } - double momkMax = fmom*(kMax-kStart)+KincidentMin; - if ((momkMax>KincidentMin)&&(momkMaxm_kiMin)&&(momkMax=hMin)&&(hkmax<=hMax)&&(lkmax>=lMin)&&(lkmax<=lMax)) + double hkmax = fh*(m_kmax-kStart)+hStart; + double lkmax = fl*(m_kmax-kStart)+lStart; + if((hkmax>=m_hmin)&&(hkmax<=m_hmax)&&(lkmax>=m_lmin)&&(lkmax<=m_lmax)) { - Mantid::Kernel::VMD v(hkmax,kMax,lkmax,momkMax); + Mantid::Kernel::VMD v(hkmax,m_kmax,lkmax,momkMax); intersections.push_back(v); } } @@ -520,22 +547,22 @@ namespace Mantid //calculate intersections with planes perpendicular to l if (fabs(lStart-lEnd)>eps) { - double fmom=(KincidentMax-KincidentMin)/(lEnd-lStart); + double fmom=(m_kiMax-m_kiMin)/(lEnd-lStart); double fh=(hEnd-hStart)/(lEnd-lStart); double fk=(kEnd-kStart)/(lEnd-lStart); - if(!lIntegrated) + if(!m_lIntegrated) { for(size_t i = 0;i=lMin)&&(li<=lMax)&&((lStart-li)*(lEnd-li)<0)) + if ((li>=m_lmin)&&(li<=m_lmax)&&((lStart-li)*(lEnd-li)<0)) { // if li is between lStart and lEnd, then hi and ki will be between hStart, hEnd and kStart, kEnd double hi = fh*(li-lStart)+hStart; double ki = fk*(li-lStart)+kStart; - if ((hi>=hMin)&&(hi<=hMax)&&(ki>=kMin)&&(ki<=kMax)) + if ((hi>=m_hmin)&&(hi<=m_hmax)&&(ki>=m_kmin)&&(ki<=m_kmax)) { - double momi = fmom*(li-lStart)+KincidentMin; + double momi = fmom*(li-lStart)+m_kiMin; Mantid::Kernel::VMD v(hi,ki,li,momi); intersections.push_back(v); } @@ -543,41 +570,41 @@ namespace Mantid } } - double momlMin = fmom*(lMin-lStart)+KincidentMin; - if ((momlMin>KincidentMin)&&(momlMinm_kiMin)&&(momlMin=hMin)&&(hlmin<=hMax)&&(klmin>=kMin)&&(klmin<=kMax)) + double hlmin = fh*(m_lmin-lStart)+hStart; + double klmin = fk*(m_lmin-lStart)+kStart; + if((hlmin>=m_hmin)&&(hlmin<=m_hmax)&&(klmin>=m_kmin)&&(klmin<=m_kmax)) { - Mantid::Kernel::VMD v(hlmin,klmin,lMin,momlMin); + Mantid::Kernel::VMD v(hlmin,klmin,m_lmin,momlMin); intersections.push_back(v); } } - double momlMax = fmom*(lMax-lStart)+KincidentMin; - if ((momlMax>KincidentMin)&&(momlMaxm_kiMin)&&(momlMax=hMin)&&(hlmax<=hMax)&&(klmax>=kMin)&&(klmax<=kMax)) + double hlmax = fh*(m_lmax-lStart)+hStart; + double klmax = fk*(m_lmax-lStart)+kStart; + if((hlmax>=m_hmin)&&(hlmax<=m_hmax)&&(klmax>=m_kmin)&&(klmax<=m_kmax)) { - Mantid::Kernel::VMD v(hlmax,klmax,lMax,momlMax); + Mantid::Kernel::VMD v(hlmax,klmax,m_lmax,momlMax); intersections.push_back(v); } } } //add endpoints - if ((hStart>=hMin)&&(hStart<=hMax)&&(kStart>=kMin)&&(kStart<=kMax)&&(lStart>=lMin)&&(lStart<=lMax)) + if ((hStart>=m_hmin)&&(hStart<=m_hmax)&&(kStart>=m_kmin)&&(kStart<=m_kmax)&&(lStart>=m_lmin)&&(lStart<=m_lmax)) { - Mantid::Kernel::VMD v(hStart,kStart,lStart,KincidentMin); + Mantid::Kernel::VMD v(hStart,kStart,lStart,m_kiMin); intersections.push_back(v); } - if ((hEnd>=hMin)&&(hEnd<=hMax)&&(kEnd>=kMin)&&(kEnd<=kMax)&&(lEnd>=lMin)&&(lEnd<=lMax)) + if ((hEnd>=m_hmin)&&(hEnd<=m_hmax)&&(kEnd>=m_kmin)&&(kEnd<=m_kmax)&&(lEnd>=m_lmin)&&(lEnd<=m_lmax)) { - Mantid::Kernel::VMD v(hEnd,kEnd,lEnd,KincidentMax); + Mantid::Kernel::VMD v(hEnd,kEnd,lEnd,m_kiMax); intersections.push_back(v); } From a32dcb48ea5eccd6ffb62b79073b175c178734ba Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Tue, 4 Nov 2014 10:23:18 +0000 Subject: [PATCH 06/41] Refactor a few more parts in to methods. Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 8 +- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 211 ++++++++++-------- 2 files changed, 123 insertions(+), 96 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index e70e217d7b0c..65513055cf4a 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -46,11 +46,13 @@ namespace Mantid void init(); void exec(); - std::string inputEnergyMode() const; void initCaches(); - std::vector getValuesFromOtherDimensions(bool & skipNormalization) const; + std::string inputEnergyMode() const; MDEvents::MDHistoWorkspace_sptr binInputWS(); - + void createNormalizationWS(const MDEvents::MDHistoWorkspace & dataWS); + std::vector getValuesFromOtherDimensions(bool & skipNormalization) const; + Kernel::Matrix findIntergratedDimensions(const std::vector & otherDimValues, + bool & skipNormalization); /// function to calculate intersections of the trajectory with MDBoxes std::vector calculateIntersections(const Geometry::IDetector_const_sptr &detector); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 25f4504a31b8..f3d4c9964783 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -100,90 +100,34 @@ namespace Mantid void SXDMDNorm::exec() { initCaches(); + auto outputWS = binInputWS(); + setProperty("OutputWorkspace", outputWS); + createNormalizationWS(*outputWS); // Check for other dimensions if we could measure anything in the original data bool skipNormalization = false; const std::vector otherValues = getValuesFromOtherDimensions(skipNormalization); - auto outputWS = binInputWS(); - this->setProperty("OutputWorkspace", outputWS); - - // Copy the MDHisto workspace, and change signals and errors to 0. - m_normWS = boost::make_shared(*outputWS); - m_normWS->setTo(0.,0.,0.); - - //get indices of the original dimensions in the output workspace, and if not found, the corresponding dimension is integrated - Kernel::Matrix mat = m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); - - for (size_t row = 0; row < mat.numRows()-1; row++)//affine matrix, ignore last row - { - if(mat[row][0]==1.) - { - m_hIntegrated = false; - m_hIdx = row; - if(m_hmingetDimension(row)->getMinimum()) m_hmin = m_normWS->getDimension(row)->getMinimum(); - if(m_hmax>m_normWS->getDimension(row)->getMaximum()) m_hmax = m_normWS->getDimension(row)->getMaximum(); - if((m_hmin>m_normWS->getDimension(row)->getMaximum()) || (m_hmaxgetDimension(row)->getMinimum())) - { - skipNormalization = true; - } - } - if(mat[row][1] == 1.) - { - m_kIntegrated = false; - m_kIdx = row; - if(m_kmingetDimension(row)->getMinimum()) m_kmin = m_normWS->getDimension(row)->getMinimum(); - if(m_kmax>m_normWS->getDimension(row)->getMaximum()) m_kmax = m_normWS->getDimension(row)->getMaximum(); - if((m_kmin>m_normWS->getDimension(row)->getMaximum()) || (m_kmaxgetDimension(row)->getMinimum())) - { - skipNormalization = true; - } - } - if(mat[row][2] == 1.) - { - m_lIntegrated = false; - m_lIdx = row; - if(m_lmingetDimension(row)->getMinimum()) m_lmin = m_normWS->getDimension(row)->getMinimum(); - if(m_lmax>m_normWS->getDimension(row)->getMaximum()) m_lmax = m_normWS->getDimension(row)->getMaximum(); - if((m_lmin>m_normWS->getDimension(row)->getMaximum()) || (m_lmaxgetDimension(row)->getMinimum())) - { - skipNormalization = true; - } - - for(size_t col = 3;col < mat.numCols()-1; col++) //affine matrix, ignore last column - { - if(mat[row][col] == 1.) - { - double val = otherValues.at(col - 3); - if((val>m_normWS->getDimension(row)->getMaximum()) || (valgetDimension(row)->getMinimum())) - { - skipNormalization = true; - } - } - } - } - } - + const auto affineMat = findIntergratedDimensions(otherValues, skipNormalization); + auto &hDim = *m_normWS->getDimension(m_hIdx); m_hX.resize( hDim.getNBins() ); for(size_t i = 0; i < m_hX.size(); ++i) { m_hX[i] = hDim.getX(i); } - auto &kDim = *m_normWS->getDimension(m_kIdx); m_kX.resize( kDim.getNBins() ); for(size_t i = 0; i < m_kX.size(); ++i) { m_kX[i] = kDim.getX(i); } - auto &lDim = *m_normWS->getDimension(m_lIdx); m_lX.resize( lDim.getNBins() ); for(size_t i = 0; i < m_lX.size(); ++i) { m_lX[i] = lDim.getX(i); } - + API::MatrixWorkspace_const_sptr fW = getProperty("FluxWorkspace"); DataObjects::EventWorkspace_const_sptr fluxW = boost::dynamic_pointer_cast(fW); m_kiMin = fluxW->getEventXMin(); @@ -265,7 +209,7 @@ namespace Mantid std::transform( pos.begin(), pos.begin() + sizeOfMVD, pos.begin(), std::bind2nd( std::multiplies(), 0.5 ) ); std::copy( otherValues.begin(), otherValues.end(), pos.begin() + sizeOfMVD ); - std::vector posNew = mat*pos; + std::vector posNew = affineMat*pos; size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data()); if(linIndex!=size_t(-1)) @@ -303,7 +247,28 @@ namespace Mantid this->setProperty("OutputNormalizationWorkspace",m_normWS); } - + + /** + * Set up starting values for cached variables + */ + void SXDMDNorm::initCaches() + { + m_inputWS = getProperty("InputWorkspace"); + if( inputEnergyMode() != "Elastic" ) + { + throw std::invalid_argument("Invalid energy transfer mode. Algorithm currently only supports elastic data."); + } + // Min/max dimension values + const auto hdim(m_inputWS->getDimension(0)), kdim(m_inputWS->getDimension(1)), + ldim(m_inputWS->getDimension(2)); + m_hmin = hdim->getMinimum(); + m_kmin = kdim->getMinimum(); + m_lmin = ldim->getMinimum(); + m_hmax = hdim->getMaximum(); + m_kmax = kdim->getMaximum(); + m_lmax = ldim->getMaximum(); + } + /** * Currently looks for the ConvertToMD algorithm in the history * @return A string donating the energy transfer mode of the input workspace @@ -341,24 +306,38 @@ namespace Mantid } /** - * Set up starting values for cached variables + * Runs the BinMD algorithm on the input to provide the output workspace + * All slicing algorithm properties are passed along + * @return MDHistoWorkspace as a result of the binning */ - void SXDMDNorm::initCaches() + MDHistoWorkspace_sptr SXDMDNorm::binInputWS() { - m_inputWS = getProperty("InputWorkspace"); - if( inputEnergyMode() != "Elastic" ) + const auto & props = getProperties(); + IAlgorithm_sptr binMD = createChildAlgorithm("BinMD", 0.0, 0.3); + binMD->setPropertyValue("AxisAligned","1"); + for(auto it = props.begin(); it != props.end(); ++it) { - throw std::invalid_argument("Invalid energy transfer mode. Algorithm currently only supports elastic data."); + const auto & propName = (*it)->name(); + if(propName != "FluxWorkspace" && propName != "SolidAngleWorkspace" && + propName != "OutputNormalizationWorkspace") + { + binMD->setPropertyValue(propName,(*it)->value()); + } } - // Min/max dimension values - const auto hdim(m_inputWS->getDimension(0)), kdim(m_inputWS->getDimension(1)), - ldim(m_inputWS->getDimension(2)); - m_hmin = hdim->getMinimum(); - m_kmin = kdim->getMinimum(); - m_lmin = ldim->getMinimum(); - m_hmax = hdim->getMaximum(); - m_kmax = kdim->getMaximum(); - m_lmax = ldim->getMaximum(); + binMD->executeAsChildAlg(); + Workspace_sptr outputWS = binMD->getProperty("OutputWorkspace"); + return boost::dynamic_pointer_cast(outputWS); + } + + /** + * Create & cached the normalization workspace + * @param dataWS The binned workspace that will be used for the data + */ + void SXDMDNorm::createNormalizationWS(const MDHistoWorkspace &dataWS) + { + // Copy the MDHisto workspace, and change signals and errors to 0. + m_normWS = boost::make_shared(dataWS); + m_normWS->setTo(0.,0.,0.); } /** @@ -393,27 +372,73 @@ namespace Mantid } /** - * Runs the BinMD algorithm on the input to provide the output workspace - * All slicing algorithm properties are passed along - * @return MDHistoWorkspace as a result of the binning + * Checks the normalization workspace against the indices of the original dimensions. + * If not found, the corresponding dimension is integrated + * @param otherDimValues Values from non-HKL dimensions + * @param skipNormalization [InOut] Sets the flag true if normalization values are outside of original inputs + * @return Affine trasform matrix */ - MDHistoWorkspace_sptr SXDMDNorm::binInputWS() + Kernel::Matrix SXDMDNorm::findIntergratedDimensions(const std::vector &otherDimValues, + bool &skipNormalization) { - const auto & props = getProperties(); - IAlgorithm_sptr binMD = createChildAlgorithm("BinMD", 0.0, 0.3); - binMD->setPropertyValue("AxisAligned","1"); - for(auto it = props.begin(); it != props.end(); ++it) + // Get indices of the original dimensions in the output workspace, + // and if not found, the corresponding dimension is integrated + Kernel::Matrix affineMat = m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); + + const size_t nrm1 = affineMat.numRows() - 1; + const size_t ncm1 = affineMat.numCols() - 1; + for( size_t row = 0; row < nrm1; row++ ) //affine matrix, ignore last row { - const auto & propName = (*it)->name(); - if(propName != "FluxWorkspace" && propName != "SolidAngleWorkspace" && - propName != "OutputNormalizationWorkspace") + const auto dimen = m_normWS->getDimension(row); + const auto dimMin(dimen->getMinimum()), dimMax(dimen->getMaximum()); + if(affineMat[row][0] == 1.) { - binMD->setPropertyValue(propName,(*it)->value()); + m_hIntegrated = false; + m_hIdx = row; + if( m_hmin < dimMin ) m_hmin = dimMin; + if( m_hmax > dimMax ) m_hmax = dimMax; + if( m_hmin > dimMax || m_hmax < dimMin) + { + skipNormalization = true; + } + } + if(affineMat[row][1] == 1.) + { + m_kIntegrated = false; + m_kIdx = row; + if( m_kmin < dimMin ) m_kmin = dimMin; + if( m_kmax > dimMax ) m_kmax = dimMax; + if( m_kmin > dimMax || m_kmax < dimMin ) + { + skipNormalization = true; + } + } + if(affineMat[row][2] == 1.) + { + m_lIntegrated = false; + m_lIdx = row; + if( m_lmin < dimMin ) m_lmin = dimMin; + if( m_lmax > dimMax ) m_lmax = dimMax; + if( m_lmin > dimMax || m_lmax < dimMin ) + { + skipNormalization = true; + } + + for(size_t col = 3; col < ncm1; col++) //affine matrix, ignore last column + { + if(affineMat[row][col] == 1.) + { + double val = otherDimValues.at(col - 3); + if( val > dimMax || val < dimMin ) + { + skipNormalization = true; + } + } + } } } - binMD->executeAsChildAlg(); - Workspace_sptr outputWS = binMD->getProperty("OutputWorkspace"); - return boost::dynamic_pointer_cast(outputWS); + + return affineMat; } /** From 83ccfe1d5a1c091e00912f093da05a1e0718d6c0 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Tue, 4 Nov 2014 12:33:40 +0000 Subject: [PATCH 07/41] Move main calculation into a method. Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 6 +- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 308 +++++++++--------- 2 files changed, 164 insertions(+), 150 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index 65513055cf4a..d7818806c9cf 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -46,14 +46,16 @@ namespace Mantid void init(); void exec(); - void initCaches(); + void cacheInputs(); std::string inputEnergyMode() const; MDEvents::MDHistoWorkspace_sptr binInputWS(); void createNormalizationWS(const MDEvents::MDHistoWorkspace & dataWS); std::vector getValuesFromOtherDimensions(bool & skipNormalization) const; Kernel::Matrix findIntergratedDimensions(const std::vector & otherDimValues, bool & skipNormalization); - /// function to calculate intersections of the trajectory with MDBoxes + void cacheDimensionXValues(); + void calculateNormalization(const std::vector &otherValues, + const Kernel::Matrix &affineTrans); std::vector calculateIntersections(const Geometry::IDetector_const_sptr &detector); /// number of MD dimensions diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index f3d4c9964783..81cda4747442 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -99,159 +99,32 @@ namespace Mantid */ void SXDMDNorm::exec() { - initCaches(); + cacheInputs(); auto outputWS = binInputWS(); setProperty("OutputWorkspace", outputWS); createNormalizationWS(*outputWS); + setProperty("OutputNormalizationWorkspace", m_normWS); // Check for other dimensions if we could measure anything in the original data bool skipNormalization = false; const std::vector otherValues = getValuesFromOtherDimensions(skipNormalization); - const auto affineMat = findIntergratedDimensions(otherValues, skipNormalization); + const auto affineTrans = findIntergratedDimensions(otherValues, skipNormalization); + cacheDimensionXValues(); - auto &hDim = *m_normWS->getDimension(m_hIdx); - m_hX.resize( hDim.getNBins() ); - for(size_t i = 0; i < m_hX.size(); ++i) - { - m_hX[i] = hDim.getX(i); - } - auto &kDim = *m_normWS->getDimension(m_kIdx); - m_kX.resize( kDim.getNBins() ); - for(size_t i = 0; i < m_kX.size(); ++i) - { - m_kX[i] = kDim.getX(i); - } - auto &lDim = *m_normWS->getDimension(m_lIdx); - m_lX.resize( lDim.getNBins() ); - for(size_t i = 0; i < m_lX.size(); ++i) + if(!skipNormalization) { - m_lX[i] = lDim.getX(i); - } - - API::MatrixWorkspace_const_sptr fW = getProperty("FluxWorkspace"); - DataObjects::EventWorkspace_const_sptr fluxW = boost::dynamic_pointer_cast(fW); - m_kiMin = fluxW->getEventXMin(); - m_kiMax = fluxW->getEventXMax(); - API::MatrixWorkspace_const_sptr sA = getProperty("SolidAngleWorkspace"); - - if(skipNormalization) - { - g_log.warning("Binning limits are outside the limits of the MDWorkspace\n"); + calculateNormalization(otherValues, affineTrans); } else { - double PC = m_normWS->getExperimentInfo(0)->run().getProtonCharge(); - Kernel::PropertyWithValue< std::vector > *prop = dynamic_cast< Mantid::Kernel::PropertyWithValue >*>(m_normWS->getExperimentInfo(0)->getLog("RUBW_MATRIX")); - if (prop==NULL) - { - throw std::runtime_error("No RUBW_MATRIX"); - } - else - { - Mantid::Kernel::DblMatrix RUBW((*prop)()); //includes the 2*pi factor but not goniometer for now :) - m_rubw = m_normWS->getExperimentInfo(0)->run().getGoniometerMatrix()*RUBW; - m_rubw.Invert(); - } - //FIXME: the detector positions are from the IDF. Need to account for calibration - std::vector detIDS = m_normWS->getExperimentInfo(0)->getInstrument()->getDetectorIDs(true); - - Mantid::API::Progress *prog = new Mantid::API::Progress(this,0.3,1,static_cast(detIDS.size())); - const detid2index_map d2m = fluxW->getDetectorIDToWorkspaceIndexMap(); - const detid2index_map d2mSA = sA->getDetectorIDToWorkspaceIndexMap(); - auto instrument = m_normWS->getExperimentInfo(0)->getInstrument(); - - PARALLEL_FOR1(m_normWS) - for(int64_t i = 0; i < static_cast(detIDS.size()); i++) - { - PARALLEL_START_INTERUPT_REGION - - Mantid::Geometry::IDetector_const_sptr detector = instrument->getDetector(detIDS[i]); - if(!detector->isMonitor() && !detector->isMasked()) - { - //get intersections - std::vector intersections = calculateIntersections(detector); - - if(!intersections.empty()) - { - //calculate indices - //add to the correct signal at that particular index - //NOTE: if parallel it has to be atomic/critical - - //get event vector - size_t sp = d2m.find(detIDS[i])->second; - std::vector el = fluxW->getEventList(sp).getWeightedEventsNoTime(); - //get iterator to the first event that has momentum >= (*intersections.begin())[3] - std::vector::iterator start = el.begin(); - // check that el isn't empty - if ( start == el.end() ) continue; - while((*start).tof()<(*intersections.begin())[3]) ++start; - - double solid = sA->readY(d2mSA.find(detIDS[i])->second)[0]*PC; - - const size_t sizeOfMVD = intersections.front().size(); - // pre-allocate for efficiency - std::vector pos( sizeOfMVD + otherValues.size() ); - - for (auto it = intersections.begin()+1;it!=intersections.end();++it) - { - //Mantid::Kernel::VMD deltav=(*it)-(*(it-1));//difference between consecutive intersections - // the full vector isn't used so compute only what is necessary - double delta = (*it)[3] - (*(it-1))[3]; - - double eps = 1e-7;//do not integrate if momemntum difference is smaller than eps, assume contribution is 0 - if (delta > eps) - { - //Mantid::Kernel::VMD avev=((*it)+(*(it-1)))*0.5;//average between two intersection (to get position) - //std::vector pos = avev.toVector(); - //pos.insert(pos.end()-1,otherValues.begin(),otherValues.end()); - // a bit longer and less readable but faster version of the above - std::transform( it->getBareArray(), it->getBareArray() + sizeOfMVD, (it-1)->getBareArray(), pos.begin(), std::plus() ); - std::transform( pos.begin(), pos.begin() + sizeOfMVD, pos.begin(), std::bind2nd( std::multiplies(), 0.5 ) ); - std::copy( otherValues.begin(), otherValues.end(), pos.begin() + sizeOfMVD ); - - std::vector posNew = affineMat*pos; - size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data()); - - if(linIndex!=size_t(-1)) - { - double signal = 0.; - while((*start).tof()<(*it)[3]) - { - if (start==el.end()) - break; - signal+=(*start).weight(); - ++start; - } - signal*=solid; - - PARALLEL_CRITICAL(updateMD) - { - signal+=m_normWS->getSignalAt(linIndex); - m_normWS->setSignalAt(linIndex,signal); - } - } - } - } - - } - } - prog->report(); - - PARALLEL_END_INTERUPT_REGION - } - PARALLEL_CHECK_INTERUPT_REGION - - delete prog; + g_log.warning("Binning limits are outside the limits of the MDWorkspace. Not applying normalization."); } - - this->setProperty("OutputNormalizationWorkspace",m_normWS); - } /** * Set up starting values for cached variables */ - void SXDMDNorm::initCaches() + void SXDMDNorm::cacheInputs() { m_inputWS = getProperty("InputWorkspace"); if( inputEnergyMode() != "Elastic" ) @@ -395,9 +268,9 @@ namespace Mantid { m_hIntegrated = false; m_hIdx = row; - if( m_hmin < dimMin ) m_hmin = dimMin; - if( m_hmax > dimMax ) m_hmax = dimMax; - if( m_hmin > dimMax || m_hmax < dimMin) + if(m_hmin < dimMin) m_hmin = dimMin; + if(m_hmax > dimMax) m_hmax = dimMax; + if(m_hmin > dimMax || m_hmax < dimMin) { skipNormalization = true; } @@ -406,9 +279,9 @@ namespace Mantid { m_kIntegrated = false; m_kIdx = row; - if( m_kmin < dimMin ) m_kmin = dimMin; - if( m_kmax > dimMax ) m_kmax = dimMax; - if( m_kmin > dimMax || m_kmax < dimMin ) + if(m_kmin < dimMin) m_kmin = dimMin; + if(m_kmax > dimMax) m_kmax = dimMax; + if(m_kmin > dimMax || m_kmax < dimMin) { skipNormalization = true; } @@ -417,9 +290,9 @@ namespace Mantid { m_lIntegrated = false; m_lIdx = row; - if( m_lmin < dimMin ) m_lmin = dimMin; - if( m_lmax > dimMax ) m_lmax = dimMax; - if( m_lmin > dimMax || m_lmax < dimMin ) + if(m_lmin < dimMin) m_lmin = dimMin; + if(m_lmax > dimMax) m_lmax = dimMax; + if(m_lmin > dimMax || m_lmax < dimMin) { skipNormalization = true; } @@ -429,7 +302,7 @@ namespace Mantid if(affineMat[row][col] == 1.) { double val = otherDimValues.at(col - 3); - if( val > dimMax || val < dimMin ) + if(val > dimMax || val < dimMin) { skipNormalization = true; } @@ -441,6 +314,145 @@ namespace Mantid return affineMat; } + /** + * Stores the X values from each H,K,L dimension as member variables + */ + void SXDMDNorm::cacheDimensionXValues() + { + auto &hDim = *m_normWS->getDimension(m_hIdx); + m_hX.resize(hDim.getNBins()); + for(size_t i = 0; i < m_hX.size(); ++i) + { + m_hX[i] = hDim.getX(i); + } + auto &kDim = *m_normWS->getDimension(m_kIdx); + m_kX.resize( kDim.getNBins() ); + for(size_t i = 0; i < m_kX.size(); ++i) + { + m_kX[i] = kDim.getX(i); + } + auto &lDim = *m_normWS->getDimension(m_lIdx); + m_lX.resize( lDim.getNBins() ); + for(size_t i = 0; i < m_lX.size(); ++i) + { + m_lX[i] = lDim.getX(i); + } + } + + /** + * Computed the normalization for the input workspace. Results are stored in m_normWS + * @param otherValues + * @param affineTrans + */ + void SXDMDNorm::calculateNormalization(const std::vector &otherValues, + const Kernel::Matrix &affineTrans) + { + API::MatrixWorkspace_const_sptr fluxMatrixWS = getProperty("FluxWorkspace"); + auto fluxEventWS = boost::dynamic_pointer_cast(fluxMatrixWS); + m_kiMin = fluxEventWS->getEventXMin(); + m_kiMax = fluxEventWS->getEventXMax(); + API::MatrixWorkspace_const_sptr solidAngleWS = getProperty("SolidAngleWorkspace"); + + const auto & exptInfoZero = *(m_normWS->getExperimentInfo(0)); + typedef Kernel::PropertyWithValue > VectorDoubleProperty; + auto *rubwLog = dynamic_cast(exptInfoZero.getLog("RUBW_MATRIX")); + if(!rubwLog) + { + throw std::runtime_error("Wokspace does not contain a log entry for the RUBW matrix." + "Cannot continue."); + } + else + { + Kernel::DblMatrix rubwValue((*rubwLog)()); //includes the 2*pi factor but not goniometer for now :) + m_rubw = exptInfoZero.run().getGoniometerMatrix()*rubwValue; + m_rubw.Invert(); + } + const double protonCharge = exptInfoZero.run().getProtonCharge(); + auto instrument = exptInfoZero.getInstrument(); + std::vector detIDS = instrument->getDetectorIDs(true); + const int64_t ndets = static_cast(detIDS.size()); + // detector->workspace index map + const detid2index_map d2m = fluxEventWS->getDetectorIDToWorkspaceIndexMap(); + const detid2index_map d2mSA = solidAngleWS->getDetectorIDToWorkspaceIndexMap(); + + auto *prog = new API::Progress(this, 0.3, 1.0, ndets); + PARALLEL_FOR1(m_normWS) + for(int64_t i = 0; i < ndets; i++) + { + PARALLEL_START_INTERUPT_REGION + + const auto detID = detIDS[i]; + auto detector = instrument->getDetector(detID); + if(detector->isMonitor() || detector->isMasked()) continue; + + std::vector intersections = calculateIntersections(detector); + if(intersections.empty()) continue; + + //calculate indices + //add to the correct signal at that particular index + + // get event vector + size_t wsIdx = d2m.find(detID)->second; + std::vector events = fluxEventWS->getEventList(wsIdx).getWeightedEventsNoTime(); + if(events.empty()) continue; + //get iterator to the first event that has momentum >= (*intersections.begin())[3] + auto eventStart = events.begin(); + const auto & firstIntersectTime = intersections.front()[3]; + while(eventStart->tof() < firstIntersectTime) ++eventStart; + + double solid = solidAngleWS->readY(d2mSA.find(detID)->second)[0]*protonCharge; + + const size_t sizeOfMVD = intersections.front().size(); + // pre-allocate for efficiency + std::vector pos(sizeOfMVD + otherValues.size()); + + for (auto it = intersections.begin() + 1; it != intersections.end(); ++it) + { + // the full vector isn't used so compute only what is necessary + double delta = (*it)[3] - (*(it-1))[3]; + + if (delta > 1e-07) //no integration if momemntum difference is smaller than eps, assume contribution is 0 + { + //Mantid::Kernel::VMD avev=((*it)+(*(it-1)))*0.5;//average between two intersection (to get position) + //std::vector pos = avev.toVector(); + //pos.insert(pos.end()-1,otherValues.begin(),otherValues.end()); + // a bit longer and less readable but faster version of the above + std::transform( it->getBareArray(), it->getBareArray() + sizeOfMVD, (it-1)->getBareArray(), pos.begin(), std::plus() ); + std::transform( pos.begin(), pos.begin() + sizeOfMVD, pos.begin(), std::bind2nd( std::multiplies(), 0.5 ) ); + std::copy( otherValues.begin(), otherValues.end(), pos.begin() + sizeOfMVD ); + + std::vector posNew = affineTrans*pos; + size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data()); + + if(linIndex!=size_t(-1)) + { + double signal = 0.; + while(eventStart->tof() < (*it)[3]) + { + if (eventStart == events.end()) + break; + signal += (*eventStart).weight(); + ++eventStart; + } + signal *= solid; + + PARALLEL_CRITICAL(updateMD) + { + signal += m_normWS->getSignalAt(linIndex); + m_normWS->setSignalAt(linIndex,signal); + } + } + } + } + prog->report(); + + PARALLEL_END_INTERUPT_REGION + } + PARALLEL_CHECK_INTERUPT_REGION + + delete prog; + } + /** * Calculate the points of intersection for the given detector with cuboid surrounding the * detector position in HKL @@ -453,9 +465,9 @@ namespace Mantid double phi = detector->getPhi(); V3D q(-sin(th)*cos(phi),-sin(th)*sin(phi),1.-cos(th)); q = m_rubw*q; - double hStart = q.X()*m_kiMin,hEnd = q.X()*m_kiMax; - double kStart = q.Y()*m_kiMin,kEnd = q.Y()*m_kiMax; - double lStart = q.Z()*m_kiMin,lEnd = q.Z()*m_kiMax; + double hStart = q.X()*m_kiMin, hEnd = q.X()*m_kiMax; + double kStart = q.Y()*m_kiMin, kEnd = q.Y()*m_kiMax; + double lStart = q.Z()*m_kiMin, lEnd = q.Z()*m_kiMax; double eps = 1e-7; From cb4841a8589e5957827e943cd9158ee9ad80b6cf Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Tue, 4 Nov 2014 14:44:54 +0000 Subject: [PATCH 08/41] Use references when returning event lists. This gives a speed gain ~80% Refs #10470 --- Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 81cda4747442..5f0cc8ab64fd 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -393,7 +393,7 @@ namespace Mantid // get event vector size_t wsIdx = d2m.find(detID)->second; - std::vector events = fluxEventWS->getEventList(wsIdx).getWeightedEventsNoTime(); + const auto &events = fluxEventWS->getEventList(wsIdx).getWeightedEventsNoTime(); if(events.empty()) continue; //get iterator to the first event that has momentum >= (*intersections.begin())[3] auto eventStart = events.begin(); From 77364809b8fb50ac8561be814cf631e4050398aa Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Tue, 4 Nov 2014 16:36:17 +0000 Subject: [PATCH 09/41] Use VectorHelper::SimpleAverage functor in computing average position. This avoids 2 loops over the same data. Also, the non-HKL dimension values don't change with each intersection so only copy them over once. Refs #10470 --- .../Kernel/inc/MantidKernel/VectorHelper.h | 2 +- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 68 +++++++++---------- 2 files changed, 33 insertions(+), 37 deletions(-) diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/VectorHelper.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/VectorHelper.h index db3ea28b9f3f..57a482f5cb09 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/VectorHelper.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/VectorHelper.h @@ -234,7 +234,7 @@ namespace VectorHelper /// Return the average of the two arguments T operator()(const T & x, const T & y) const { - return 0.5 * (x + y); + return static_cast(0.5) * (x + y); } }; diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 5f0cc8ab64fd..261b81a52b55 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -5,6 +5,7 @@ #include "MantidMDEvents/MDEventWorkspace.h" #include "MantidMDEvents/MDHistoWorkspace.h" #include "MantidKernel/TimeSeriesProperty.h" +#include "MantidKernel/VectorHelper.h" namespace Mantid { @@ -399,49 +400,44 @@ namespace Mantid auto eventStart = events.begin(); const auto & firstIntersectTime = intersections.front()[3]; while(eventStart->tof() < firstIntersectTime) ++eventStart; - + // Get solid angle for this contribution double solid = solidAngleWS->readY(d2mSA.find(detID)->second)[0]*protonCharge; - - const size_t sizeOfMVD = intersections.front().size(); - // pre-allocate for efficiency - std::vector pos(sizeOfMVD + otherValues.size()); - + // Compute final position in HKL + const size_t vmdDims = intersections.front().size(); + // pre-allocate for efficiency and copy non-hkl dim values into place + std::vector pos(vmdDims + otherValues.size()); + std::copy(otherValues.begin(), otherValues.end(), pos.begin() + vmdDims); + for (auto it = intersections.begin() + 1; it != intersections.end(); ++it) { + const auto & curIntSec = *it; + const auto & prevIntSec = *(it-1); // the full vector isn't used so compute only what is necessary - double delta = (*it)[3] - (*(it-1))[3]; + double delta = curIntSec[3] - prevIntSec[3]; + if(delta < 1e-07) continue; // Assume zero contribution if difference is small + + // Average between two intersections for final position + std::transform(curIntSec.getBareArray(), curIntSec.getBareArray() + vmdDims, + prevIntSec.getBareArray(), pos.begin(), + VectorHelper::SimpleAverage()); + std::vector posNew = affineTrans*pos; + size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data()); + if(linIndex == size_t(-1)) continue; - if (delta > 1e-07) //no integration if momemntum difference is smaller than eps, assume contribution is 0 + double signal = 0.; + while(eventStart->tof() < (*it)[3]) { - //Mantid::Kernel::VMD avev=((*it)+(*(it-1)))*0.5;//average between two intersection (to get position) - //std::vector pos = avev.toVector(); - //pos.insert(pos.end()-1,otherValues.begin(),otherValues.end()); - // a bit longer and less readable but faster version of the above - std::transform( it->getBareArray(), it->getBareArray() + sizeOfMVD, (it-1)->getBareArray(), pos.begin(), std::plus() ); - std::transform( pos.begin(), pos.begin() + sizeOfMVD, pos.begin(), std::bind2nd( std::multiplies(), 0.5 ) ); - std::copy( otherValues.begin(), otherValues.end(), pos.begin() + sizeOfMVD ); - - std::vector posNew = affineTrans*pos; - size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data()); + if (eventStart == events.end()) + break; + signal += (*eventStart).weight(); + ++eventStart; + } + signal *= solid; - if(linIndex!=size_t(-1)) - { - double signal = 0.; - while(eventStart->tof() < (*it)[3]) - { - if (eventStart == events.end()) - break; - signal += (*eventStart).weight(); - ++eventStart; - } - signal *= solid; - - PARALLEL_CRITICAL(updateMD) - { - signal += m_normWS->getSignalAt(linIndex); - m_normWS->setSignalAt(linIndex,signal); - } - } + PARALLEL_CRITICAL(updateMD) + { + signal += m_normWS->getSignalAt(linIndex); + m_normWS->setSignalAt(linIndex, signal); } } prog->report(); From cddbdc99df8ac3b57d935b4748b21896b7d570dd Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 6 Nov 2014 15:20:00 +0000 Subject: [PATCH 10/41] Alter function signature to just accept theta and phi Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 6 ++- .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 39 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index d7818806c9cf..df169b38999b 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -56,7 +56,7 @@ namespace Mantid void cacheDimensionXValues(); void calculateNormalization(const std::vector &otherValues, const Kernel::Matrix &affineTrans); - std::vector calculateIntersections(const Geometry::IDetector_const_sptr &detector); + std::vector calculateIntersections(const double theta, const double phi); /// number of MD dimensions size_t m_nDims; @@ -76,6 +76,10 @@ namespace Mantid size_t m_hIdx, m_kIdx, m_lIdx; /// cached X values along dimensions h,k,l std::vector m_hX, m_kX, m_lX; + /// Sample position + Kernel::V3D m_samplePos; + /// Beam direction + Kernel::V3D m_beamDir; }; } // namespace MDAlgorithms diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 261b81a52b55..4cadedc9b679 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -39,7 +39,7 @@ namespace Mantid m_kmin(0.0f), m_kmax(0.0f), m_lmin(0.0f), m_lmax(0.0f), m_hIntegrated(true), m_kIntegrated(true), m_lIntegrated(true), m_rubw(3,3), m_kiMin(0.0), m_kiMax(EMPTY_DBL()), m_hIdx(-1), m_kIdx(-1), m_lIdx(-1), - m_hX(), m_kX(), m_lX() + m_hX(), m_kX(), m_lX(), m_samplePos(), m_beamDir() { } @@ -141,6 +141,17 @@ namespace Mantid m_hmax = hdim->getMaximum(); m_kmax = kdim->getMaximum(); m_lmax = ldim->getMaximum(); + + const auto & exptInfoZero = *(m_inputWS->getExperimentInfo(0)); + auto source = exptInfoZero.getInstrument()->getSource(); + auto sample = exptInfoZero.getInstrument()->getSample(); + if(source == NULL || sample == NULL) + { + throw Kernel::Exception::InstrumentDefinitionError("Instrument not sufficiently defined: failed to get source and/or sample"); + } + m_samplePos = sample->getPos(); + m_beamDir = m_samplePos - source->getPos(); + m_beamDir.normalize(); } /** @@ -369,15 +380,16 @@ namespace Mantid m_rubw.Invert(); } const double protonCharge = exptInfoZero.run().getProtonCharge(); + auto instrument = exptInfoZero.getInstrument(); std::vector detIDS = instrument->getDetectorIDs(true); const int64_t ndets = static_cast(detIDS.size()); // detector->workspace index map - const detid2index_map d2m = fluxEventWS->getDetectorIDToWorkspaceIndexMap(); - const detid2index_map d2mSA = solidAngleWS->getDetectorIDToWorkspaceIndexMap(); + const detid2index_map fluxDetToIdx = fluxEventWS->getDetectorIDToWorkspaceIndexMap(); + const detid2index_map solidAngDetToIdx = solidAngleWS->getDetectorIDToWorkspaceIndexMap(); auto *prog = new API::Progress(this, 0.3, 1.0, ndets); - PARALLEL_FOR1(m_normWS) + PARALLEL_FOR1(fluxEventWS) for(int64_t i = 0; i < ndets; i++) { PARALLEL_START_INTERUPT_REGION @@ -386,14 +398,14 @@ namespace Mantid auto detector = instrument->getDetector(detID); if(detector->isMonitor() || detector->isMasked()) continue; - std::vector intersections = calculateIntersections(detector); + const double theta = detector->getTwoTheta(m_samplePos, m_beamDir); + const double phi = detector->getPhi(); + auto intersections = calculateIntersections(theta, phi); if(intersections.empty()) continue; //calculate indices //add to the correct signal at that particular index - - // get event vector - size_t wsIdx = d2m.find(detID)->second; + size_t wsIdx = fluxDetToIdx.find(detID)->second; const auto &events = fluxEventWS->getEventList(wsIdx).getWeightedEventsNoTime(); if(events.empty()) continue; //get iterator to the first event that has momentum >= (*intersections.begin())[3] @@ -401,7 +413,7 @@ namespace Mantid const auto & firstIntersectTime = intersections.front()[3]; while(eventStart->tof() < firstIntersectTime) ++eventStart; // Get solid angle for this contribution - double solid = solidAngleWS->readY(d2mSA.find(detID)->second)[0]*protonCharge; + double solid = solidAngleWS->readY(solidAngDetToIdx.find(detID)->second)[0]*protonCharge; // Compute final position in HKL const size_t vmdDims = intersections.front().size(); // pre-allocate for efficiency and copy non-hkl dim values into place @@ -452,14 +464,13 @@ namespace Mantid /** * Calculate the points of intersection for the given detector with cuboid surrounding the * detector position in HKL - * @param detector A pointer to a detector object + * @param theta Polar angle withd detector + * @param phi Azimuthal angle with detector * @return A list of intersections in HKL space */ - std::vector SXDMDNorm::calculateIntersections(const Geometry::IDetector_const_sptr & detector) + std::vector SXDMDNorm::calculateIntersections(const double theta, const double phi) { - double th = detector->getTwoTheta(V3D(0,0,0),V3D(0,0,1)); - double phi = detector->getPhi(); - V3D q(-sin(th)*cos(phi),-sin(th)*sin(phi),1.-cos(th)); + V3D q(-sin(theta)*cos(phi), -sin(theta)*sin(phi), 1.-cos(theta)); q = m_rubw*q; double hStart = q.X()*m_kiMin, hEnd = q.X()*m_kiMax; double kStart = q.Y()*m_kiMin, kEnd = q.Y()*m_kiMax; From c16f78c90b2a705394d4fa05f62d91ade465e2f0 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Thu, 6 Nov 2014 16:35:09 +0000 Subject: [PATCH 11/41] Use detector grouping from ExperimentInfo For workspaces with grouped detectors it now only considers the first one from the group in the main loop but calculates the intersections using the whole group. Refs #10470 --- .../inc/MantidMDAlgorithms/SXDMDNorm.h | 5 ++ .../Framework/MDAlgorithms/src/SXDMDNorm.cpp | 65 ++++++++++++++++--- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h index df169b38999b..084b120d7583 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/SXDMDNorm.h @@ -56,6 +56,11 @@ namespace Mantid void cacheDimensionXValues(); void calculateNormalization(const std::vector &otherValues, const Kernel::Matrix &affineTrans); + std::vector removeGroupedIDs(const API::ExperimentInfo & exptInfo, + const std::vector &detIDs); + Geometry::IDetector_const_sptr getThetaPhi(const detid_t detID, + const API::ExperimentInfo & exptInfo, + double &theta, double &phi); std::vector calculateIntersections(const double theta, const double phi); /// number of MD dimensions diff --git a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp index 4cadedc9b679..7918a0c74b84 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/SXDMDNorm.cpp @@ -382,9 +382,12 @@ namespace Mantid const double protonCharge = exptInfoZero.run().getProtonCharge(); auto instrument = exptInfoZero.getInstrument(); - std::vector detIDS = instrument->getDetectorIDs(true); - const int64_t ndets = static_cast(detIDS.size()); - // detector->workspace index map + std::vector detIDs = instrument->getDetectorIDs(true); + // Prune out those that are part of a group and simply leave the head of the group + detIDs = removeGroupedIDs(exptInfoZero, detIDs); + + // Mappings + const int64_t ndets = static_cast(detIDs.size()); const detid2index_map fluxDetToIdx = fluxEventWS->getDetectorIDToWorkspaceIndexMap(); const detid2index_map solidAngDetToIdx = solidAngleWS->getDetectorIDToWorkspaceIndexMap(); @@ -394,12 +397,11 @@ namespace Mantid { PARALLEL_START_INTERUPT_REGION - const auto detID = detIDS[i]; - auto detector = instrument->getDetector(detID); - if(detector->isMonitor() || detector->isMasked()) continue; - - const double theta = detector->getTwoTheta(m_samplePos, m_beamDir); - const double phi = detector->getPhi(); + const auto detID = detIDs[i]; + double theta(0.0), phi(0.0); + auto spectrum = getThetaPhi(detID, exptInfoZero, theta, phi); + if(spectrum->isMonitor() || spectrum->isMasked()) continue; + // Intersections auto intersections = calculateIntersections(theta, phi); if(intersections.empty()) continue; @@ -458,7 +460,50 @@ namespace Mantid } PARALLEL_CHECK_INTERUPT_REGION - delete prog; + delete prog; + } + + /** + * Checks for IDs that are actually part of the same group and just keeps one from the group. + * For a 1:1 map, none will be removed. + * @param exptInfo An ExperimentInfo object that defines the grouping + * @param detIDs A list of existing IDs + * @return A new list of IDs + */ + std::vector SXDMDNorm::removeGroupedIDs(const ExperimentInfo &exptInfo, const std::vector &detIDs) + { + const size_t ntotal = detIDs.size(); + std::vector singleIDs; + singleIDs.reserve(ntotal/2); // reserve half. In the case of 1:1 it will double to the correct size once + + for(auto iter = detIDs.begin(); iter != detIDs.end(); ++iter) + { + const auto & members = exptInfo.getGroupMembers(*iter); + singleIDs.push_back(members.front()); + } + + return singleIDs; + } + + /** + * Get the theta and phi angles for the given ID. If the detector was part of a group, + * as defined in the ExperimentInfo object, then the theta/phi are for the whole set. + * @param detID A reference to a single ID + * @param exptInfo A reference to the ExperimentInfo that defines that spectrum->detector mapping + * @param theta [Output] Set to the theta angle for the detector (set) + * @param phi [Output] Set to the phi angle for the detector (set) + * @return A poiner to the Detector object for this spectrum as a whole + * (may be a single pixel or group) + */ + Geometry::IDetector_const_sptr + SXDMDNorm::getThetaPhi(const detid_t detID, + const ExperimentInfo &exptInfo, + double &theta, double &phi) + { + const auto spectrum = exptInfo.getDetectorByID(detID); + theta = spectrum->getTwoTheta(m_samplePos, m_beamDir); + phi = spectrum->getPhi(); + return spectrum; } /** From 940880d697a744a9df79fc6e7b6828def3cd8d13 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 20 Nov 2014 13:56:37 +0000 Subject: [PATCH 12/41] Refs #10600 Add purpose section --- .../docs/source/interfaces/ISIS_Reflectometry.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst index 0a0bad429fbe..48b4b5b0a811 100644 --- a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst +++ b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst @@ -4,6 +4,20 @@ ISIS Reflectometry (Polref) Interface .. contents:: Table of Contents :local: +Purpose +------- +This user interface allows for batch processing of data reduction for +reflectometry data. The actual data reduction is performed with +:ref:`ReflectometryReductionOne `. +Wherever possible, this interface attempts to use reasonable defaults, +either loaded from the instruments' parameter files, or calculated from +the provided data, to minimise the amount of user input required. +This interface also strives to be transparent, making it clear how your +data is being processed, and easy to adjust any of the options used. + +Integration with data archives is also provided, allowing for data to +be located and prepared in the processing table automatically. + Layout ------ From 671f217c249720a99fddfed80718eb1a3640957f Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 20 Nov 2014 14:37:39 +0000 Subject: [PATCH 13/41] Refs #10600 Move example workflow to top of refl ui docs --- .../source/interfaces/ISIS_Reflectometry.rst | 124 +++++++++--------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst index 48b4b5b0a811..f27e93b9b1a2 100644 --- a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst +++ b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst @@ -18,6 +18,69 @@ data is being processed, and easy to adjust any of the options used. Integration with data archives is also provided, allowing for data to be located and prepared in the processing table automatically. +Example Workflow +---------------- + +To follow this example you will need to ISIS reflectometry example materials: + +* ``INTER_NR_test2.tbl`` +* ``INTER00013460.nxs`` +* ``INTER00013462.nxs`` +* ``INTER00013463.nxs`` +* ``INTER00013464.nxs`` +* ``INTER00013469.nxs`` +* ``INTER00013470.nxs`` + +These can be downloaded as part of the `ISIS example data `_. + +Once they are downloaded, place the nxs files in one of Mantid's user directories. +(To see a list of directories, click on *File -> Manager User Directories*) +The tbl file can be left anywhere you like, as long as you know where it is. + +You can then open MantidPlot, and open the ISIS Reflectometry (Polref) interface. +(*Interfaces -> Reflectometry -> ISIS Reflectometry (Polref)*) + +Within the interface, we first want to import the tbl file as a TableWorkspace. +To do this, go to *Reflectometry -> Import .TBL*. A :ref:`LoadReflTBL ` +dialog will open. Select ``INTER_NR_test2.tbl`` as the file, and enter ``MyTable`` +as the output workspace. + +A table workspace called ``MyTable`` should now exist in the ADS (:ref:`Analysis Data Service `). +To open the table workspace go to *Reflectometry -> Open Table -> MyTable*. +The processing table (shown below) should now contain four rows (13460, 13462, 13469, 13470). + +.. interface:: ISIS Reflectometry (Polref) + :widget: viewTable + +We want to process the first two rows, which are in group 1. The simplest way to do this is +simply to select the two rows we want to process, and then press *Process*. + +.. tip:: + If you receive an error, consult the `Troubleshooting`_ section of this document for guidance on fixing it. + +If the processing was successful, you should now have ten more workspaces in the ADS. + +Amongst them should be: + +TOF_13460 + This is the data before processing. The X axis is time of flight in µs. + +TRANS_13463_13464 + This is a transmission run, created by running :ref:`CreateTransmissionWorkspace ` + on ``TOF_13463`` and ``TOF_13464``. The X axis is wavelength in Ã…. + +IvsQ_13460 + This is the output workspace of :ref:`ReflectometryReductionOne `. The X + axis is momentum transfer in Ã…\ :sup:`-1`\ . + +IvsLam_13460 + This is the wavelength output workspace of :ref:`ReflectometryReductionOne `. + The X axis is wavelength in Ã…. + +IvsQ_13460_13462 + This workspace is the result of stitching ``IvsQ_13460`` and ``IvsQ_13462`` together using + :ref:`Stitch1D `. The X axis is momentum transfer in Ã…\ :sup:`-1`\ . + Layout ------ @@ -202,7 +265,7 @@ Columns | | | group number are stitched together. | +---------------------+-----------+-----------------------------------------------+ | Options | No | Contains options that allow you to override | -| | | ReflectometryReductionOneAuto's properties. | +| | | ReflectometryReductionOne's properties. | | | | Options are given as ``key=value`` pairs, | | | | separated by commas. Values containing commas | | | | must be quoted. | @@ -243,65 +306,6 @@ the behaviour of the interface. | | decimal places. | +-------------------------------+------------------------------------------------------+ -Example Workflow ----------------- - -To follow this example you will need to ISIS reflectometry example materials: - -* ``INTER_NR_test2.tbl`` -* ``INTER00013460.nxs`` -* ``INTER00013462.nxs`` -* ``INTER00013463.nxs`` -* ``INTER00013464.nxs`` -* ``INTER00013469.nxs`` -* ``INTER00013470.nxs`` - -These can be downloaded as part of the `ISIS example data `. - -Once they are downloaded, place the nxs files in one of Mantid's user directories. -(To see a list of directories, click on *File -> Manager User Directories*) -The tbl file can be left anywhere you like, as long as you know where it is. - -You can then open MantidPlot, and open the ISIS Reflectometry (Polref) interface. -(*Interfaces -> Reflectometry -> ISIS Reflectometry (Polref)*) - -Within the interface, we first want to import the tbl file as a TableWorkspace. -To do this, go to *Reflectometry -> Import .TBL*. A :ref:`LoadReflTBL ` -dialog will open. Select ``INTER_NR_test2.tbl`` as the file, and enter ``MyTable`` -as the output workspace. - -A table workspace called ``MyTable`` should now exist in the :ref:`ADS `. -To open the table workspace go to *Reflectometry -> Open Table -> MyTable*. -The processing table (shown below) should now contain four rows (13460, 13462, 13469, 13470). - -.. interface:: ISIS Reflectometry (Polref) - :widget: viewTable - -We want to process the first two rows, which are in group 1. The simplest way to do this is -simply to select the two rows we want to process, and then press *Process*. If you receive -an error, consult the `_Troubleshooting` section of this document for guidance on fixing it. - -If the processing was successful, you should now have ten more workspaces in the ADS. - -Among them shall be: - -TOF_13460 - This is the data before processing. - -TRANS_13463_13464 - This is a transmission run, created by running :ref:`CreateTransmissionWorkspace ` - on ``TOF_13463`` and ``TOF_13464``. - -IvsQ_13460 - This is the output workspace of :ref:`ReflectometryReductionOneAuto `. - -IvsLam_13460 - This is the wavelength output workspace of :ref:`ReflectometryReductionOneAuto `. - -IvsQ_13460_13462 - This is the result of stitching ``IvsQ_13460`` and ``IvsQ_13462`` together using - :ref:`Stitch1D `. - Troubleshooting --------------- From 56b6abdba1c91f4efedfe60f9d8ca89e82e356a4 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 20 Nov 2014 15:36:19 +0000 Subject: [PATCH 14/41] Add proper detector mapping to SofQW Refs #10598 --- Code/Mantid/Framework/Algorithms/src/SofQW.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp index 77b5368bb0e7..9d46375e691f 100644 --- a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp @@ -6,6 +6,7 @@ #include "MantidAlgorithms/SofQW.h" #include "MantidDataObjects/Histogram1D.h" #include "MantidAPI/BinEdgeAxis.h" +#include "MantidAPI/SpectrumDetectorMapping.h" #include "MantidAPI/WorkspaceValidators.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/RebinParamsValidator.h" @@ -79,6 +80,7 @@ void SofQW::exec() using namespace Geometry; MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); + // Do the full check for common binning if ( ! WorkspaceHelpers::commonBoundaries(inputWorkspace) ) { @@ -90,6 +92,9 @@ void SofQW::exec() MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace(inputWorkspace, getProperty("QAxisBinning"), verticalAxis); setProperty("OutputWorkspace",outputWorkspace); + std::vector specNumberMapping; + std::vector detIDMapping; + m_EmodeProperties.initCachedValues(inputWorkspace,this); int emode = m_EmodeProperties.m_emode; @@ -202,6 +207,10 @@ void SofQW::exec() const MantidVec::difference_type qIndex = std::upper_bound(verticalAxis.begin(),verticalAxis.end(),q) - verticalAxis.begin() - 1; + // Add this spectra-detector pair to the mapping + specNumberMapping.push_back(qIndex); + detIDMapping.push_back(det->getID()); + // And add the data and it's error to that bin, taking into account the number of detectors contributing to this bin outputWorkspace->dataY(qIndex)[j] += Y[j]/numDets_d; // Standard error on the average @@ -219,6 +228,10 @@ void SofQW::exec() // If the input workspace was a distribution, need to divide by q bin width if (inputWorkspace->isDistribution()) this->makeDistribution(outputWorkspace,verticalAxis); + + // Set the output spectrum-detector mapping + SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); + outputWorkspace->updateSpectraUsing(outputDetectorMap); } /** Creates the output workspace, setting the axes according to the input binning parameters From e406cc50a6cc2938a2d4efb9fabe5481bc25b53e Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 20 Nov 2014 15:47:57 +0000 Subject: [PATCH 15/41] Build the spectra-detector map correctly Refs #10598 --- Code/Mantid/Framework/Algorithms/src/SofQW.cpp | 2 +- Code/Mantid/Framework/Algorithms/src/SofQW2.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp index 9d46375e691f..8ce0928488e1 100644 --- a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp @@ -208,7 +208,7 @@ void SofQW::exec() std::upper_bound(verticalAxis.begin(),verticalAxis.end(),q) - verticalAxis.begin() - 1; // Add this spectra-detector pair to the mapping - specNumberMapping.push_back(qIndex); + specNumberMapping.push_back(outputWorkspace->getSpectrum(qIndex)->getSpectrumNo()); detIDMapping.push_back(det->getID()); // And add the data and it's error to that bin, taking into account the number of detectors contributing to this bin diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp index 6ae7b906fd65..40a81f1dc6d9 100755 --- a/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp @@ -96,6 +96,7 @@ namespace Mantid const double thetaLower = theta - halfWidth; const double thetaUpper = theta + halfWidth; const double efixed = m_EmodeProperties.getEFixed(inputWS->getDetector(i)); + for(size_t j = 0; j < nenergyBins; ++j) { m_progress->report("Computing polygon intersections"); From d04818307eb975e69422db6af965d50218960d5e Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 20 Nov 2014 15:28:37 +0000 Subject: [PATCH 16/41] Refs #10600 Further refine Refl UI documentation --- .../source/interfaces/ISIS_Reflectometry.rst | 147 ++++++++++-------- 1 file changed, 80 insertions(+), 67 deletions(-) diff --git a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst index f27e93b9b1a2..1290aa215edf 100644 --- a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst +++ b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst @@ -16,49 +16,51 @@ This interface also strives to be transparent, making it clear how your data is being processed, and easy to adjust any of the options used. Integration with data archives is also provided, allowing for data to -be located and prepared in the processing table automatically. +be located and prepared for reduction automatically. + +Information on how to resolve common problems can be found in the +`Troubleshooting`_ section of this document. Example Workflow ---------------- -To follow this example you will need to ISIS reflectometry example materials: +To follow this example you will need the ISIS reflectometry example materials: * ``INTER_NR_test2.tbl`` * ``INTER00013460.nxs`` * ``INTER00013462.nxs`` * ``INTER00013463.nxs`` * ``INTER00013464.nxs`` -* ``INTER00013469.nxs`` -* ``INTER00013470.nxs`` These can be downloaded as part of the `ISIS example data `_. Once they are downloaded, place the nxs files in one of Mantid's user directories. -(To see a list of directories, click on *File -> Manager User Directories*) -The tbl file can be left anywhere you like, as long as you know where it is. +To see a list of directories, click on **File -> Manage User Directories**. +``INTER_NR_test2.tbl`` can be saved anywhere you like, as long as you know where it is. -You can then open MantidPlot, and open the ISIS Reflectometry (Polref) interface. -(*Interfaces -> Reflectometry -> ISIS Reflectometry (Polref)*) +Open MantidPlot, and open the ISIS Reflectometry (Polref) interface. +**Interfaces -> Reflectometry -> ISIS Reflectometry (Polref)** Within the interface, we first want to import the tbl file as a TableWorkspace. -To do this, go to *Reflectometry -> Import .TBL*. A :ref:`LoadReflTBL ` +To do this, click on **Reflectometry -> Import .TBL**. A :ref:`LoadReflTBL ` dialog will open. Select ``INTER_NR_test2.tbl`` as the file, and enter ``MyTable`` as the output workspace. A table workspace called ``MyTable`` should now exist in the ADS (:ref:`Analysis Data Service `). -To open the table workspace go to *Reflectometry -> Open Table -> MyTable*. +To open the table workspace go to **Reflectometry -> Open Table -> MyTable**. The processing table (shown below) should now contain four rows (13460, 13462, 13469, 13470). .. interface:: ISIS Reflectometry (Polref) :widget: viewTable -We want to process the first two rows, which are in group 1. The simplest way to do this is -simply to select the two rows we want to process, and then press *Process*. +Let's process the first group, which consists of the first two rows of the +table (13460 and 13462). The simplest way to do this is simply to select the +two rows we want to process, and then click on **Process**. .. tip:: If you receive an error, consult the `Troubleshooting`_ section of this document for guidance on fixing it. -If the processing was successful, you should now have ten more workspaces in the ADS. +You should now have eleven workspaces in the ADS. Amongst them should be: @@ -94,44 +96,13 @@ start a new table, open an existing table from a :ref:`workspace `, or save your current table to a :ref:`workspace `. You are also able to import or export .TBL files from disk using the -*Import .TBL* and *Export .TBL* options. These options will run the +**Import .TBL** and **Export .TBL** options. These options will run the :ref:`LoadReflTBL ` and :ref:`SaveReflTBL ` algorithms as appropriate. The menu bar also provides access to the options menu, and many actions pertaining to the processing table. -Search Interface -~~~~~~~~~~~~~~~~ - -.. interface:: ISIS Reflectometry (Polref) - :widget: groupSearchPane - :align: right - -To search for runs, select the instrument the runs are from, enter the id of -the investigation the runs are part of, and hit *Search*. - -In the table below, valid runs and their descriptions will be listed. You -can then transfer runs to the processing table by selecting the runs you -wish to transfer, and hit the *Transfer* button. You can also right-click -on one of the selected runs and select *Transfer* in the context menu that -appears. - -If a run's description contains the text ``in 0.7 theta``, or ``th=0.7``, or -``th:0.7``, then the interface will deduce that the run's angle (also known -as theta), was ``0.7``, and enter this value into the angle column for you. -This holds true for any numeric value. - -When multiple runs are selected and transferred simultaneously, the interface -will attempt to organise them appropriately in the processing table. The exact -behaviour of this is as follows: - -- Any runs with the same description, excluding their theta value, will be - placed into the same group. -- Any runs with the same description, including their theta value, will be - merged into a single row, with all the runs listed in the *Run(s)* column - in the format, ``123+124+125``. - Processing Table ~~~~~~~~~~~~~~~~ @@ -139,15 +110,22 @@ Processing Table :widget: groupProcessPane The processing table is where the bulk of the work takes place. It is used to -specify which runs to process, the parameters that should be used to process +specify which runs to process, the properties that should be used to process them, and how the different runs should be joined together. -Above the processing table is a tool bar providing a number of useful actions. +Each row represents a single reduction (i.e. execution of +:ref:`ReflectometryReductionOne `). +Rows may be grouped together by setting their **Group** column to the same +value. Rows that are grouped together will have their output stitched +together using :ref:`Stitch1D `. -Below the table is a progress bar, showing the current progress of any -processing that is taking place, and a processing instrument selector. -The processing instrument is used by the interface to help load the correct -files from disk when processing. +Above the processing table is a tool bar containing various actions for +manipulating the processing table. + +Below the table is a progress bar, which shows the current progress of any +processing that is in progress. And at the bottom right, by the **Process** +button is the processing instrument selector. The processing instrument is +used to help identify the correct data to load when processing runs. Actions ~~~~~~~ @@ -192,7 +170,7 @@ This table details the behaviour of the actions in the tool bar, from left to ri +------------------+----------------------------------------------------------+ | Help | Opens this documentation for viewing. | +------------------+----------------------------------------------------------+ -| Whats This | Provides guidance on what various parts of the interface | +| What's This | Provides guidance on what various parts of the interface | | | are for. | +------------------+----------------------------------------------------------+ @@ -204,7 +182,7 @@ Columns +---------------------+-----------+-----------------------------------------------+ | Column Title | Required? | Description | +=====================+===========+===============================================+ -| Run(s) | Yes | Contains the sample runs to be processed. | +| Run(s) | **Yes** | Contains the sample runs to be processed. | | | | Runs may be given as run numbers or workspace | | | | names. Multiple runs may be added together by | | | | separating them with a '+'. | @@ -213,7 +191,7 @@ Columns +---------------------+-----------+-----------------------------------------------+ | Angle | No | Contains the angle used during the run, in | | | | degrees. If left blank, this is set to the | -| | | last value for 'THETA' in the run's sample | +| | | last value for ``THETA`` in the run's sample | | | | log. If multiple runs were given in the Run(s)| | | | column, the first listed run's sample log will| | | | be used. | @@ -251,22 +229,25 @@ Columns | | | | | | | Example: ``0.9`` | +---------------------+-----------+-----------------------------------------------+ -| Scale | Yes | Contains the factor used to scale output | +| Scale | **Yes** | Contains the factor used to scale output | | | | IvsQ workspaces. The IvsQ workspaces are | | | | scaled by ``1/i`` where i is the value of | | | | this column. | | | | | | | | Example: ``1.0`` | +---------------------+-----------+-----------------------------------------------+ -| Group | Yes | Contains the group number used for stitching | +| Group | **Yes** | Contains the group number used for stitching | | | | output workspaces. The value of this column | | | | determines which other rows this row's output | | | | will be stitched with. All rows with the same | | | | group number are stitched together. | +---------------------+-----------+-----------------------------------------------+ | Options | No | Contains options that allow you to override | -| | | ReflectometryReductionOne's properties. | -| | | Options are given as ``key=value`` pairs, | +| | | ReflectometryReductionOne's properties. To | +| | | override a property, just use the property's | +| | | name as a key, and the desired value as the | +| | | value. | +| | | Options are specified in ``key=value`` pairs, | | | | separated by commas. Values containing commas | | | | must be quoted. | | | | | @@ -274,23 +255,55 @@ Columns | | | ``RegionOfDirectBeam="0,2", Params="1,2,3"`` | +---------------------+-----------+-----------------------------------------------+ +Search Interface +~~~~~~~~~~~~~~~~ + +.. interface:: ISIS Reflectometry (Polref) + :widget: groupSearchPane + :align: right + +To search for runs, select the instrument the runs are from, enter the id of +the investigation the runs are part of, and click on **Search**. + +In the table below, valid runs and their descriptions will be listed. You +can then transfer runs to the processing table by selecting the runs you +wish to transfer, and click the **Transfer** button. You can also right-click +on one of the selected runs and select *Transfer* in the context menu that +appears. + +If a run's description contains the text ``in 0.7 theta``, or ``th=0.7``, or +``th:0.7``, then the interface will deduce that the run's angle (also known +as theta), was ``0.7``, and enter this value into the angle column for you. +This holds true for any numeric value. + +When multiple runs are selected and transferred simultaneously, the interface +will attempt to organise them appropriately in the processing table. The exact +behaviour of this is as follows: + +- Any runs with the same description, excluding their theta value, will be + placed into the same group. +- Any runs with the same description, including their theta value, will be + merged into a single row, with all the runs listed in the **Run(s)** column + in the format, ``123+124+125``. + Options ~~~~~~~ Through the options menu, a small number of options may be configured to adjust the behaviour of the interface. +To open the options menu, click on **Reflectometry -> Options**. +-------------------------------+------------------------------------------------------+ | Name | Description | +===============================+======================================================+ -| Warn when processing all rows | When the *Process* button is pressed with no rows | +| Warn when processing all rows | When the **Process** button is pressed with no rows | | | selected, all rows will be processed. | | | If this is enabled, you will be asked if you're sure | | | you want to process all rows first. | +-------------------------------+------------------------------------------------------+ -| Warn when processing only | If this is enabled and you press *Process* with only | -| part of a group | a subset of a group's rows selected, you will be | +| Warn when processing only | If this is enabled and you press **Process** with | +| part of a group | only a subset of a group's rows selected, you will be| | | asked if you're sure you that's what you intended to | | | do. | +-------------------------------+------------------------------------------------------+ @@ -315,14 +328,14 @@ When I try to process I get an error: "Invalid value for property Filename (list This occurs when Mantid is unable to load a run. If the run was given as a workspace name, check the spelling. If the run was given as a number, check that the run number is correct. If the run number is incorrect, check the -number given in the *Run(s)* or *Transmission Run(s)* columns. If the run +number given in the **Run(s)** or **Transmission Run(s)** columns. If the run number is correct, check the instrument named in the error message is correct. If the instrument is incorrect, check that the processing instrument selector (at the bottom right of the interface) is correct. If the run still isn't loading check Mantid's user directories are set correctly, and that the desired run is in one of the given directories. To -manage the user directories, open *File -> Manage User Directories*. +manage the user directories, open **File -> Manage User Directories**. When I try to process I get an error: "Invalid key value pair, '...'" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -334,9 +347,9 @@ contains commas it **must** be quoted, like so: ``key = "v,a,l,u,e"``. The *Open Table* menu doesn't do anything ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The *Open Table* menu contains a list of valid table workspaces to open in the +The **Open Table** menu contains a list of valid table workspaces to open in the processing table. If a workspace is not compatible, it will not be listed. So, -if there are no compatible workspaces the *Open Table* menu will be empty. +if there are no compatible workspaces the **Open Table** menu will be empty. My IvsQ workspaces are not being stitched correctly ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -345,9 +358,9 @@ Stitching is controlled by the group a row is in. For stitching to occur, the rows must be in the same group, and be processed simultaneously. An easy way to check the runs are in the same group is to select one of the -rows you want stitched, and then in the menu bar select *Edit -> Expand Selection*. +rows you want stitched, and then in the menu bar select **Edit -> Expand Selection**. All the rows in that group will be selected. If you have another row that you would like to add to the group, you can do this easily by adding it to the -selection, and then in the menu bar selecting *Edit -> Group Selected*. +selection, and then in the menu bar selecting **Edit -> Group Selected**. .. categories:: Interfaces Reflectometry From 4217e919b9e3e435994631df6945451c6ed1b08d Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 20 Nov 2014 16:16:43 +0000 Subject: [PATCH 17/41] Refs #10600 Improve menu bar documentation --- .../source/interfaces/ISIS_Reflectometry.rst | 45 ++++++++++++++----- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst index 1290aa215edf..9508c9b04292 100644 --- a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst +++ b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst @@ -91,17 +91,40 @@ Layout Menu bar ~~~~~~~~ -At the top of the interface is a menu bar. Through this menu bar you can -start a new table, open an existing table from a :ref:`workspace `, -or save your current table to a :ref:`workspace `. +.. interface:: ISIS Reflectometry (Polref) + :widget: menuBar + +The **Reflectometry** menu provides access to the following functionality: -You are also able to import or export .TBL files from disk using the -**Import .TBL** and **Export .TBL** options. These options will run the -:ref:`LoadReflTBL ` and :ref:`SaveReflTBL ` -algorithms as appropriate. ++------------------+----------------------------------------------------------+ +| Action | Effect | ++==================+==========================================================+ +| Open Table | Opens a valid *TableWorkspace* in the `Processing Table`_| +| | for processing. | ++------------------+----------------------------------------------------------+ +| New Table | Discards the current contents of the `Processing Table`_,| +| | presenting a blank table. | ++------------------+----------------------------------------------------------+ +| Save Table | Saves the current contents of the `Processing Table`_ to | +| | the *TableWorkspace* it came from. If no such workspace | +| | already exists, a new one can be created. | ++------------------+----------------------------------------------------------+ +| Save Table As | Saves the current contents of the `Processing Table`_ to | +| | a new *TableWorkspace*. | ++------------------+----------------------------------------------------------+ +| Import .TBL | Opens a :ref:`LoadReflTBL ` dialog, | +| | enabling you to load a ``.tbl`` file into a | +| | *TableWorkspace*. | ++------------------+----------------------------------------------------------+ +| Export .TBL | Opens a :ref:`SaveReflTBL ` dialog, | +| | enabling you to save a *TableWorkspace* to a ``.tbl`` | +| | file. | ++------------------+----------------------------------------------------------+ +| Options | Opens the `Options`_ menu. | ++------------------+----------------------------------------------------------+ -The menu bar also provides access to the options menu, and many actions -pertaining to the processing table. +The **Edit** menu provides access to the same actions found in the tool bar. +These are documented in the `Tool Bar`_ section of this document. Processing Table ~~~~~~~~~~~~~~~~ @@ -127,8 +150,8 @@ processing that is in progress. And at the bottom right, by the **Process** button is the processing instrument selector. The processing instrument is used to help identify the correct data to load when processing runs. -Actions -~~~~~~~ +Tool Bar +~~~~~~~~ This table details the behaviour of the actions in the tool bar, from left to right. From 18c2c3cb84e3c9625f439ba39e8a157b9cf14c8d Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Thu, 20 Nov 2014 16:27:30 +0000 Subject: [PATCH 18/41] Add proper mapping to SofQW2 and 3 Refs #10598 --- .../Mantid/Framework/Algorithms/src/SofQW.cpp | 3 +- .../Framework/Algorithms/src/SofQW2.cpp | 34 +++++++++++++++---- .../Framework/Algorithms/src/SofQW3.cpp | 30 +++++++++++++--- 3 files changed, 55 insertions(+), 12 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp index 8ce0928488e1..774fb8fcf308 100644 --- a/Code/Mantid/Framework/Algorithms/src/SofQW.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW.cpp @@ -92,6 +92,7 @@ void SofQW::exec() MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace(inputWorkspace, getProperty("QAxisBinning"), verticalAxis); setProperty("OutputWorkspace",outputWorkspace); + // Holds the spectrum-detector mapping std::vector specNumberMapping; std::vector detIDMapping; @@ -205,7 +206,7 @@ void SofQW::exec() if ( q < verticalAxis.front() || q > verticalAxis.back() ) continue; // Find which q bin this point lies in const MantidVec::difference_type qIndex = - std::upper_bound(verticalAxis.begin(),verticalAxis.end(),q) - verticalAxis.begin() - 1; + std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) - verticalAxis.begin() - 1; // Add this spectra-detector pair to the mapping specNumberMapping.push_back(outputWorkspace->getSpectrum(qIndex)->getSpectrumNo()); diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp index 40a81f1dc6d9..ad6ec7f9aadd 100755 --- a/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW2.cpp @@ -4,6 +4,7 @@ #include "MantidAlgorithms/SofQW2.h" #include "MantidAlgorithms/SofQW.h" #include "MantidAPI/SpectraAxis.h" +#include "MantidAPI/SpectrumDetectorMapping.h" #include "MantidGeometry/Math/LaszloIntersection.h" #include "MantidGeometry/Math/Quadrilateral.h" #include "MantidGeometry/Math/Vertex2D.h" @@ -68,6 +69,10 @@ namespace Mantid const size_t nTheta = m_thetaPts.size(); const MantidVec & X = inputWS->readX(0); + + // Holds the spectrum-detector mapping + std::vector specNumberMapping; + std::vector detIDMapping; // Select the calculate Q method based on the mode // rather than doing this repeatedly in the loop @@ -82,20 +87,22 @@ namespace Mantid qCalculator = &SofQW2::calculateIndirectQ; } - PARALLEL_FOR2(inputWS, outputWS) + /* PARALLEL_FOR2(inputWS, outputWS) */ for(int64_t i = 0; i < static_cast(nTheta); ++i) // signed for openmp { - PARALLEL_START_INTERUPT_REGION + /* PARALLEL_START_INTERUPT_REGION */ const double theta = m_thetaPts[i]; if( theta < 0.0 ) // One to skip { continue; } + + IDetector_const_sptr det = inputWS->getDetector(i); double halfWidth(0.5*m_thetaWidth); const double thetaLower = theta - halfWidth; const double thetaUpper = theta + halfWidth; - const double efixed = m_EmodeProperties.getEFixed(inputWS->getDetector(i)); + const double efixed = m_EmodeProperties.getEFixed(det); for(size_t j = 0; j < nenergyBins; ++j) { @@ -105,20 +112,35 @@ namespace Mantid const double dE_j = X[j]; const double dE_jp1 = X[j+1]; + const double lrQ = (this->*qCalculator)(efixed, dE_jp1,thetaLower,0.0); + const V2D ll(dE_j, (this->*qCalculator)(efixed, dE_j,thetaLower,0.0)); - const V2D lr(dE_jp1, (this->*qCalculator)(efixed, dE_jp1,thetaLower,0.0)); + const V2D lr(dE_jp1, lrQ); const V2D ur(dE_jp1, (this->*qCalculator)(efixed, dE_jp1,thetaUpper,0.0)); const V2D ul(dE_j, (this->*qCalculator)(efixed, dE_j,thetaUpper,0.0)); Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul); rebinToOutput(inputQ, inputWS, i, j, outputWS, m_Qout); + + // Find which q bin this point lies in + const MantidVec::difference_type qIndex = std::upper_bound(m_Qout.begin(), m_Qout.end(), lrQ) - m_Qout.begin(); + if(qIndex != 0 && qIndex < static_cast(m_Qout.size())) + { + // Add this spectra-detector pair to the mapping + specNumberMapping.push_back(outputWS->getSpectrum(qIndex - 1)->getSpectrumNo()); + detIDMapping.push_back(det->getID()); + } } - PARALLEL_END_INTERUPT_REGION + /* PARALLEL_END_INTERUPT_REGION */ } - PARALLEL_CHECK_INTERUPT_REGION + /* PARALLEL_CHECK_INTERUPT_REGION */ normaliseOutput(outputWS, inputWS); + + // Set the output spectrum-detector mapping + SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); + outputWS->updateSpectraUsing(outputDetectorMap); } diff --git a/Code/Mantid/Framework/Algorithms/src/SofQW3.cpp b/Code/Mantid/Framework/Algorithms/src/SofQW3.cpp index 6aedbce62164..5c8cff0b80d0 100644 --- a/Code/Mantid/Framework/Algorithms/src/SofQW3.cpp +++ b/Code/Mantid/Framework/Algorithms/src/SofQW3.cpp @@ -4,6 +4,7 @@ #include "MantidAlgorithms/SofQW3.h" #include "MantidAlgorithms/SofQW.h" #include "MantidAPI/BinEdgeAxis.h" +#include "MantidAPI/SpectrumDetectorMapping.h" #include "MantidAPI/WorkspaceFactory.h" #include "MantidGeometry/Instrument/DetectorGroup.h" #include "MantidGeometry/Instrument/ReferenceFrame.h" @@ -96,6 +97,10 @@ namespace Algorithms const size_t nEnergyBins = inputWS->blocksize(); const size_t nHistos = inputWS->getNumberHistograms(); + // Holds the spectrum-detector mapping + std::vector specNumberMapping; + std::vector detIDMapping; + // Progress reports & cancellation const size_t nreports(nHistos * nEnergyBins); m_progress = boost::shared_ptr(new API::Progress(this, 0.0, @@ -121,10 +126,10 @@ namespace Algorithms const MantidVec & X = inputWS->readX(0); int emode = m_EmodeProperties.m_emode; - PARALLEL_FOR2(inputWS, outputWS) + /* PARALLEL_FOR2(inputWS, outputWS) */ for (int64_t i = 0; i < static_cast(nHistos); ++i) // signed for openmp { - PARALLEL_START_INTERUPT_REGION + /* PARALLEL_START_INTERUPT_REGION */ DetConstPtr detector = inputWS->getDetector(i); if (detector->isMasked() || detector->isMonitor()) @@ -158,8 +163,10 @@ namespace Algorithms const double dE_j = X[j]; const double dE_jp1 = X[j+1]; + const double lrQ = this->calculateQ(efixed,emode, dE_jp1, thetaLower, phiLower); + const V2D ll(dE_j, this->calculateQ(efixed, emode,dE_j, thetaLower, phiLower)); - const V2D lr(dE_jp1, this->calculateQ(efixed,emode, dE_jp1, thetaLower, phiLower)); + const V2D lr(dE_jp1, lrQ); const V2D ur(dE_jp1, this->calculateQ(efixed,emode, dE_jp1, thetaUpper, phiUpper)); const V2D ul(dE_j, this->calculateQ(efixed,emode, dE_j, thetaUpper, phiUpper)); if(g_log.is(Logger::Priority::PRIO_DEBUG)) @@ -172,18 +179,31 @@ namespace Algorithms Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul); this->rebinToFractionalOutput(inputQ, inputWS, i, j, outputWS, m_Qout); + + // Find which q bin this point lies in + const MantidVec::difference_type qIndex = std::upper_bound(m_Qout.begin(), m_Qout.end(), lrQ) - m_Qout.begin(); + if(qIndex != 0 && qIndex < static_cast(m_Qout.size())) + { + // Add this spectra-detector pair to the mapping + specNumberMapping.push_back(outputWS->getSpectrum(qIndex - 1)->getSpectrumNo()); + detIDMapping.push_back(detector->getID()); + } } if(g_log.is(Logger::Priority::PRIO_DEBUG)) { g_log.debug(logStream.str()); } - PARALLEL_END_INTERUPT_REGION + /* PARALLEL_END_INTERUPT_REGION */ } - PARALLEL_CHECK_INTERUPT_REGION + /* PARALLEL_CHECK_INTERUPT_REGION */ outputWS->finalize(); this->normaliseOutput(outputWS, inputWS); + + // Set the output spectrum-detector mapping + SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); + outputWS->updateSpectraUsing(outputDetectorMap); } From bf9023d516f6ee3dec24313b930f07585e14e061 Mon Sep 17 00:00:00 2001 From: Andrei Savici Date: Fri, 21 Nov 2014 10:54:17 -0500 Subject: [PATCH 19/41] Added new dependencies to Ubuntu dev package. Refs #10592 Added version requirement for poco, jsoncpp, and a few debug libraries --- .../Build/dev-packages/deb/mantid-developer/README | 4 ++-- .../mantid-developer-1.2.2/DEBIAN/control | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control diff --git a/Code/Mantid/Build/dev-packages/deb/mantid-developer/README b/Code/Mantid/Build/dev-packages/deb/mantid-developer/README index f722e6b9324c..b7f32473f9ef 100644 --- a/Code/Mantid/Build/dev-packages/deb/mantid-developer/README +++ b/Code/Mantid/Build/dev-packages/deb/mantid-developer/README @@ -2,5 +2,5 @@ This directory contains the structure required to build the simple mantid-develo To build the package: * Switch to the directory containing this file - * Run "dpkg --build mantid-developer-1.2.1" - * A file called mantid-developer-1.2.1.deb will appear in the current directory. + * Run "dpkg --build mantid-developer-1.2.2" + * A file called mantid-developer-1.2.2.deb will appear in the current directory. diff --git a/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control b/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control new file mode 100644 index 000000000000..66bb465911a0 --- /dev/null +++ b/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control @@ -0,0 +1,13 @@ +Package: mantid-developer +Version: 1.2.2 +Section: main +Priority: optional +Architecture: all +Depends: git, cmake-qt-gui(>=2.8.12), qt4-qmake, qt4-dev-tools, libqt4-dbg, libpoco-dev(>=1.4.2), libboost-all-dev, libboost-dbg, libnexus0-dev, libgoogle-perftools-dev, libqwt5-qt4-dev, libqwtplot3d-qt4-dev, python-qt4-dev, libgsl0-dev, liboce-visualization-dev, libmuparser-dev, python-numpy, libssl-dev, libqscintilla2-dev, texlive,texlive-latex-extra, dvipng, libhdf4-dev, doxygen, python-sphinx, python-scipy, ipython-qtconsole (>=1.2.0), libhdf5-dev, libhdf4-dev, libpococrypto11-dbg, libpocodata11-dbg, libpocofoundation11-dbg, libpocomysql11-dbg, libpoconet11-dbg, libpoconetssl11-dbg, libpocoodbc11-dbg, libpocosqlite11-dbg, libpocoutil11-dbg, libpocoxml11-dbg, libpocozip11-dbg, python-qt4-dbg, qt4-default, ninja-build, libjsoncpp-dev +Installed-Size: 0 +Maintainer: Mantid Project +Description: Installs all packages required for a Mantid developer + A metapackage which requires all the dependencies and tools that are + required for Mantid development. It works for Ubuntu version 14.04, 14.10 + Some packages (poco) must be newer than thiose in the Ubuntu repository. Please + follow instructions at http://www.mantidproject.org/Mantid_Prerequisites#Repositories From b3d72eabeb50168dad35f4b239641ba7e6d9ca21 Mon Sep 17 00:00:00 2001 From: Andrei Savici Date: Fri, 21 Nov 2014 11:15:16 -0500 Subject: [PATCH 20/41] Add python-dateutil. Refs #10592 --- .../deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control b/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control index 66bb465911a0..1f541e4af9b7 100644 --- a/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control +++ b/Code/Mantid/Build/dev-packages/deb/mantid-developer/mantid-developer-1.2.2/DEBIAN/control @@ -3,7 +3,7 @@ Version: 1.2.2 Section: main Priority: optional Architecture: all -Depends: git, cmake-qt-gui(>=2.8.12), qt4-qmake, qt4-dev-tools, libqt4-dbg, libpoco-dev(>=1.4.2), libboost-all-dev, libboost-dbg, libnexus0-dev, libgoogle-perftools-dev, libqwt5-qt4-dev, libqwtplot3d-qt4-dev, python-qt4-dev, libgsl0-dev, liboce-visualization-dev, libmuparser-dev, python-numpy, libssl-dev, libqscintilla2-dev, texlive,texlive-latex-extra, dvipng, libhdf4-dev, doxygen, python-sphinx, python-scipy, ipython-qtconsole (>=1.2.0), libhdf5-dev, libhdf4-dev, libpococrypto11-dbg, libpocodata11-dbg, libpocofoundation11-dbg, libpocomysql11-dbg, libpoconet11-dbg, libpoconetssl11-dbg, libpocoodbc11-dbg, libpocosqlite11-dbg, libpocoutil11-dbg, libpocoxml11-dbg, libpocozip11-dbg, python-qt4-dbg, qt4-default, ninja-build, libjsoncpp-dev +Depends: git, cmake-qt-gui(>=2.8.12), qt4-qmake, qt4-dev-tools, libqt4-dbg, libpoco-dev(>=1.4.2), libboost-all-dev, libboost-dbg, libnexus0-dev, libgoogle-perftools-dev, libqwt5-qt4-dev, libqwtplot3d-qt4-dev, python-qt4-dev, libgsl0-dev, liboce-visualization-dev, libmuparser-dev, python-numpy, libssl-dev, libqscintilla2-dev, texlive,texlive-latex-extra, dvipng, libhdf4-dev, doxygen, python-sphinx, python-scipy, ipython-qtconsole (>=1.2.0), libhdf5-dev, libhdf4-dev, libpococrypto11-dbg, libpocodata11-dbg, libpocofoundation11-dbg, libpocomysql11-dbg, libpoconet11-dbg, libpoconetssl11-dbg, libpocoodbc11-dbg, libpocosqlite11-dbg, libpocoutil11-dbg, libpocoxml11-dbg, libpocozip11-dbg, python-qt4-dbg, qt4-default, ninja-build, libjsoncpp-dev, python-dateutil Installed-Size: 0 Maintainer: Mantid Project Description: Installs all packages required for a Mantid developer From 1bebfc7254b0acf7d2a9d7a94e977a2adcf7a54e Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Mon, 24 Nov 2014 10:46:00 +0000 Subject: [PATCH 21/41] Fix bug for 1:1 detector mapping. ExperimentInfo throws if no mappings are defined. Refs #10470 --- Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp index 0208067eb8ae..9e1575a6054d 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp @@ -568,8 +568,15 @@ namespace Mantid for(auto iter = detIDs.begin(); iter != detIDs.end(); ++iter) { - const auto & members = exptInfo.getGroupMembers(*iter); - singleIDs.push_back(members.front()); + detid_t frontID = *iter; + try + { + const auto & members = exptInfo.getGroupMembers(*iter); + frontID = members.front(); + } + catch (std::runtime_error &) + {} + singleIDs.push_back(frontID); } return singleIDs; From 128ec77e01c7097c355cd77de454bda7dcc1fcfd Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 13 Nov 2014 14:26:46 +0000 Subject: [PATCH 22/41] Refs #10238 Remove unneeded virtual keywords These won't be inherted. They don't need to be virtual. --- .../ReflMainViewPresenter.h | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h index 40f39615db35..c9f19b602b9d 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h @@ -71,7 +71,7 @@ namespace MantidQt boost::shared_ptr m_transferStrategy; //process selected rows - virtual void process(); + void process(); //Reduce a row void reduceRow(int rowNo); //prepare a run or list of runs for processing @@ -95,34 +95,34 @@ namespace MantidQt //Stitch some rows void stitchRows(std::set rows); //insert a row in the model before the given index - virtual void insertRow(int index); + void insertRow(int index); //add row(s) to the model - virtual void appendRow(); - virtual void prependRow(); + void appendRow(); + void prependRow(); //delete row(s) from the model - virtual void deleteRow(); + void deleteRow(); //clear selected row(s) in the model - virtual void clearSelected(); + void clearSelected(); //copy selected rows to clipboard - virtual void copySelected(); + void copySelected(); //copy selected rows to clipboard and then delete them - virtual void cutSelected(); + void cutSelected(); //paste clipboard into selected rows - virtual void pasteSelected(); + void pasteSelected(); //group selected rows together - virtual void groupRows(); + void groupRows(); //expand selection to group - virtual void expandSelection(); + void expandSelection(); //table io methods - virtual void newTable(); - virtual void openTable(); - virtual void saveTable(); - virtual void saveTableAs(); - virtual void importTable(); - virtual void exportTable(); + void newTable(); + void openTable(); + void saveTable(); + void saveTableAs(); + void importTable(); + void exportTable(); //searching - virtual void search(); - virtual void transfer(); + void search(); + void transfer(); //options void showOptionsDialog(); void initOptions(); From 899a6329b60e7070c6864d80fb8cc28d51d597c9 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 13 Nov 2014 16:23:02 +0000 Subject: [PATCH 23/41] Refs #10238 Add plotWorkspaces method to QtReflMainView --- .../MantidQtCustomInterfaces/QtReflMainView.h | 3 +++ .../MantidQtCustomInterfaces/ReflMainView.h | 3 +++ .../CustomInterfaces/src/QtReflMainView.cpp | 18 ++++++++++++++++++ .../test/ReflMainViewMockObjects.h | 1 + 4 files changed, 25 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h index 9b4e0064a886..c8dbc1724631 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h @@ -62,6 +62,9 @@ namespace MantidQt virtual void giveUserCritical(std::string prompt, std::string title); virtual void showAlgorithmDialog(const std::string& algorithm); + //Plotting + virtual void plotWorkspaces(const std::set& workspaces); + //Set the status of the progress bar virtual void setProgressRange(int min, int max); virtual void setProgress(int progress); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h index e92a8ca7fe73..3ae6fd78dfa3 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainView.h @@ -54,6 +54,9 @@ namespace MantidQt virtual void giveUserCritical(std::string prompt, std::string title) = 0; virtual void showAlgorithmDialog(const std::string& algorithm) = 0; + //Plotting + virtual void plotWorkspaces(const std::set& workspaces) = 0; + //Set the status of the progress bar virtual void setProgressRange(int min, int max) = 0; virtual void setProgress(int progress) = 0; diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp index bec40479a80d..a6dcc9dd29c6 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp @@ -407,6 +407,24 @@ namespace MantidQt runPythonCode(QString::fromStdString(pythonSrc.str())); } + /** + Plot a workspace + */ + void QtReflMainView::plotWorkspaces(const std::set& workspaces) + { + if(workspaces.empty()) + return; + + std::stringstream pythonSrc; + pythonSrc << "base_graph = None\n"; + for(auto ws = workspaces.begin(); ws != workspaces.end(); ++ws) + pythonSrc << "base_graph = plotSpectrum(\"" << *ws << "\", 0, True, window = base_graph)\n"; + + pythonSrc << "base_graph.activeLayer().logLogAxes()\n"; + + runPythonCode(QString::fromStdString(pythonSrc.str())); + } + /** Set the range of the progress bar @param min : The minimum value of the bar diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h b/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h index af9ae2078629..1c2e058bef04 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewMockObjects.h @@ -35,6 +35,7 @@ class MockView : public ReflMainView MOCK_METHOD2(giveUserWarning, void(std::string, std::string)); MOCK_METHOD1(showAlgorithmDialog, void(const std::string&)); + MOCK_METHOD1(plotWorkspaces, void(const std::set&)); //IO MOCK_CONST_METHOD0(getWorkspaceToOpen, std::string()); From 2f54216cb0f600859b963c946f9ce458f6ae4ac6 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 13 Nov 2014 16:36:12 +0000 Subject: [PATCH 24/41] Refs #10238 Add plotting actions to Refl UI --- .../ReflMainWidget.ui | 36 +++++++++++++++++++ .../CustomInterfaces/src/QtReflMainView.cpp | 3 ++ 2 files changed, 39 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainWidget.ui b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainWidget.ui index b7f3b8cc187f..fed9132ab6db 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainWidget.ui +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainWidget.ui @@ -223,6 +223,9 @@ + + + @@ -374,6 +377,9 @@ + + + @@ -649,6 +655,36 @@ F1 + + + + :/graph.png:/graph.png + + + Plot Selected Rows + + + Plot the selected rows + + + Creates a plot of the IvsQ workspaces produced by the selected rows. + + + + + + :/trajectory.png:/trajectory.png + + + Plot Selected Groups + + + Plot the selected groups + + + Creates a plot of the stitched IvsQ workspaces produced by any groups any selected rows are in. + + comboSearchInstrument diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp index a6dcc9dd29c6..2b94c49953b9 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp @@ -303,6 +303,9 @@ namespace MantidQt menu->addAction(ui.actionProcess); menu->addAction(ui.actionExpandSelection); menu->addSeparator(); + menu->addAction(ui.actionPlotRow); + menu->addAction(ui.actionPlotGroup); + menu->addSeparator(); menu->addAction(ui.actionPrependRow); menu->addAction(ui.actionAppendRow); menu->addSeparator(); From 9771db7e61322a68c64e683d8f64cd74f281001e Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Thu, 13 Nov 2014 16:36:30 +0000 Subject: [PATCH 25/41] Refs #10238 Implement plotting in Refl UI --- .../MantidQtCustomInterfaces/IReflPresenter.h | 2 + .../MantidQtCustomInterfaces/QtReflMainView.h | 2 + .../ReflMainViewPresenter.h | 3 ++ .../CustomInterfaces/src/QtReflMainView.cpp | 16 ++++++ .../src/ReflMainViewPresenter.cpp | 51 +++++++++++++++++++ 5 files changed, 74 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IReflPresenter.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IReflPresenter.h index 06539eaf39e5..977f9456efa9 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IReflPresenter.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/IReflPresenter.h @@ -63,6 +63,8 @@ namespace MantidQt TransferFlag, ImportTableFlag, ExportTableFlag, + PlotRowFlag, + PlotGroupFlag, }; //Tell the presenter something happened diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h index c8dbc1724631..cb15c86c458d 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/QtReflMainView.h @@ -121,6 +121,8 @@ namespace MantidQt void on_actionImportTable_triggered(); void on_actionExportTable_triggered(); void on_actionHelp_triggered(); + void on_actionPlotRow_triggered(); + void on_actionPlotGroup_triggered(); void on_comboSearchInstrument_currentIndexChanged(int index); void on_comboProcessInstrument_currentIndexChanged(int index); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h index c9f19b602b9d..4cf8162b15dd 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/ReflMainViewPresenter.h @@ -123,6 +123,9 @@ namespace MantidQt //searching void search(); void transfer(); + //plotting + void plotRow(); + void plotGroup(); //options void showOptionsDialog(); void initOptions(); diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp index 2b94c49953b9..447c556521bf 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/QtReflMainView.cpp @@ -278,6 +278,22 @@ namespace MantidQt MantidQt::API::HelpWindow::showPage(this, QString("qthelp://org.mantidproject/doc/interfaces/ISIS_Reflectometry.html")); } + /** + This slot notifies the presenter that the "plot selected rows" button has been pressed + */ + void QtReflMainView::on_actionPlotRow_triggered() + { + m_presenter->notify(IReflPresenter::PlotRowFlag); + } + + /** + This slot notifies the presenter that the "plot selected groups" button has been pressed + */ + void QtReflMainView::on_actionPlotGroup_triggered() + { + m_presenter->notify(IReflPresenter::PlotGroupFlag); + } + /** This slot notifies the presenter that the table has been updated/changed by the user */ diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp index ce194a0f9db2..145cd4de0674 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp @@ -941,6 +941,8 @@ namespace MantidQt case IReflPresenter::TransferFlag: transfer(); break; case IReflPresenter::ImportTableFlag: importTable(); break; case IReflPresenter::ExportTableFlag: exportTable(); break; + case IReflPresenter::PlotRowFlag: plotRow(); break; + case IReflPresenter::PlotGroupFlag: plotGroup(); break; } //Not having a 'default' case is deliberate. gcc issues a warning if there's a flag we aren't handling. } @@ -1288,6 +1290,55 @@ namespace MantidQt } } + /** Plots any currently selected rows */ + void ReflMainViewPresenter::plotRow() + { + auto selectedRows = m_view->getSelectedRows(); + + if(selectedRows.empty()) + return; + + std::set workspaces; + + for(auto row = selectedRows.begin(); row != selectedRows.end(); ++row) + workspaces.insert("IvsQ_" + m_model->data(m_model->index(*row, COL_RUNS)).toString().toStdString()); + + m_view->plotWorkspaces(workspaces); + } + + /** Plots any currently selected groups */ + void ReflMainViewPresenter::plotGroup() + { + auto selectedRows = m_view->getSelectedRows(); + + if(selectedRows.empty()) + return; + + std::set selectedGroups; + for(auto row = selectedRows.begin(); row != selectedRows.end(); ++row) + selectedGroups.insert(m_model->data(m_model->index(*row, COL_GROUP)).toInt()); + + //Now, get the names of the stitched workspace, one per group + std::map> runsByGroup; + const int numRows = m_model->rowCount(); + for(int row = 0; row < numRows; ++row) + { + int group = m_model->data(m_model->index(row, COL_GROUP)).toInt(); + + //Skip groups we don't care about + if(selectedGroups.find(group) == selectedGroups.end()) + continue; + + //Add this to the list of runs + runsByGroup[group].push_back(m_model->data(m_model->index(row, COL_RUNS)).toString().toStdString()); + } + + std::set workspaces; + for(auto runsMap = runsByGroup.begin(); runsMap != runsByGroup.end(); ++runsMap) + workspaces.insert("IvsQ_" + boost::algorithm::join(runsMap->second, "_")); + m_view->plotWorkspaces(workspaces); + } + /** Shows the Refl Options dialog */ void ReflMainViewPresenter::showOptionsDialog() { From 67655d1970b77cedfffe48db8dca97b93dad7625 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Mon, 24 Nov 2014 10:26:52 +0000 Subject: [PATCH 26/41] Refs #10238 Support multi-run rows for group plotting --- .../MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp index 145cd4de0674..a3be11106566 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp @@ -1301,7 +1301,7 @@ namespace MantidQt std::set workspaces; for(auto row = selectedRows.begin(); row != selectedRows.end(); ++row) - workspaces.insert("IvsQ_" + m_model->data(m_model->index(*row, COL_RUNS)).toString().toStdString()); + workspaces.insert("IvsQ_" + getRunNumber(prepareRunWorkspace(m_model->data(m_model->index(*row, COL_RUNS)).toString().toStdString()))); m_view->plotWorkspaces(workspaces); } @@ -1330,7 +1330,7 @@ namespace MantidQt continue; //Add this to the list of runs - runsByGroup[group].push_back(m_model->data(m_model->index(row, COL_RUNS)).toString().toStdString()); + runsByGroup[group].push_back(getRunNumber(prepareRunWorkspace(m_model->data(m_model->index(row, COL_RUNS)).toString().toStdString()))); } std::set workspaces; From a737b066e19f479b43ae77bd9145ae89b858f460 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Mon, 24 Nov 2014 10:31:06 +0000 Subject: [PATCH 27/41] Refs #10238 Document new plot actions --- Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst index 0a0bad429fbe..367b67496b4a 100644 --- a/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst +++ b/Code/Mantid/docs/source/interfaces/ISIS_Reflectometry.rst @@ -92,6 +92,12 @@ This table details the behaviour of the actions in the tool bar, from left to ri | | group as a row you have selected are added to your | | | selection. | +------------------+----------------------------------------------------------+ +| Plot Selected | Creates a plot of the IvsQ workspaces generated by any of| +| Rows | the selected rows. | ++------------------+----------------------------------------------------------+ +| Plot Selected | Creates a plot of the stitched IvsQ workspaces generated | +| Groups | by any of the selected groups. | ++------------------+----------------------------------------------------------+ | Insert Row | Adds a new row after the first selected row, or at the | | | end of the table if no rows are selected. | +------------------+----------------------------------------------------------+ From d50604ea3d93eee1ae0f7fa6ee4f285a85af468d Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Mon, 24 Nov 2014 11:16:01 +0000 Subject: [PATCH 28/41] Refs #10238 Don't attempt to plot non-existant workspaces --- .../CustomInterfaces/src/ReflMainViewPresenter.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp index a3be11106566..0d83bd9fa002 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp @@ -1301,7 +1301,11 @@ namespace MantidQt std::set workspaces; for(auto row = selectedRows.begin(); row != selectedRows.end(); ++row) - workspaces.insert("IvsQ_" + getRunNumber(prepareRunWorkspace(m_model->data(m_model->index(*row, COL_RUNS)).toString().toStdString()))); + { + const std::string wsName = "IvsQ_" + getRunNumber(prepareRunWorkspace(m_model->data(m_model->index(*row, COL_RUNS)).toString().toStdString())); + if(AnalysisDataService::Instance().doesExist(wsName)) + workspaces.insert(wsName); + } m_view->plotWorkspaces(workspaces); } @@ -1335,7 +1339,11 @@ namespace MantidQt std::set workspaces; for(auto runsMap = runsByGroup.begin(); runsMap != runsByGroup.end(); ++runsMap) - workspaces.insert("IvsQ_" + boost::algorithm::join(runsMap->second, "_")); + { + const std::string wsName = "IvsQ_" + boost::algorithm::join(runsMap->second, "_"); + if(AnalysisDataService::Instance().doesExist(wsName)) + workspaces.insert(wsName); + } m_view->plotWorkspaces(workspaces); } From 68aaa1ff3af1c56e7299bc76f6f1319c1237c9be Mon Sep 17 00:00:00 2001 From: Federico Montesino Pouzols Date: Tue, 25 Nov 2014 15:04:45 +0000 Subject: [PATCH 29/41] AssocDialog needs to be modal, like PlotDialog, re #7113 --- Code/Mantid/MantidPlot/src/AssociationsDialog.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp b/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp index b3757eb9ae0b..a0531f6bd72b 100644 --- a/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp +++ b/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp @@ -48,8 +48,9 @@ AssociationsDialog::AssociationsDialog( Graph* g, Qt::WFlags fl ) : QDialog( g, fl ) { - setName( "AssociationsDialog" ); - setWindowTitle( tr( "MantidPlot - Plot Associations" ) ); + setName( "AssociationsDialog" ); + setWindowTitle( tr( "MantidPlot - Plot Associations" ) ); + setModal(true); setSizeGripEnabled(true); setFocus(); From c74a9a403df8ded05f2cc847cb973c5e2f889fe6 Mon Sep 17 00:00:00 2001 From: Federico Montesino Pouzols Date: Tue, 25 Nov 2014 16:33:18 +0000 Subject: [PATCH 30/41] in AssocDialog table disable rows that are empty data, re #7133 --- .../MantidPlot/src/AssociationsDialog.cpp | 95 ++++++++++++------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp b/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp index a0531f6bd72b..583686c45c4b 100644 --- a/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp +++ b/Code/Mantid/MantidPlot/src/AssociationsDialog.cpp @@ -57,11 +57,11 @@ AssociationsDialog::AssociationsDialog( Graph* g, Qt::WFlags fl ) QVBoxLayout *vl = new QVBoxLayout(); QHBoxLayout *hbox1 = new QHBoxLayout (); - hbox1->addWidget(new QLabel(tr( "Spreadsheet: " ))); + hbox1->addWidget(new QLabel(tr( "Spreadsheet: " ))); tableCaptionLabel = new QLabel(); - hbox1->addWidget(tableCaptionLabel); - vl->addLayout(hbox1); + hbox1->addWidget(tableCaptionLabel); + vl->addLayout(hbox1); table = new QTableWidget(3, 5); table->horizontalHeader()->setClickable( false ); @@ -70,26 +70,26 @@ AssociationsDialog::AssociationsDialog( Graph* g, Qt::WFlags fl ) table->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); table->setMaximumHeight(8*table->rowHeight(0)); table->setHorizontalHeaderLabels(QStringList() << tr("Column") << tr("X") << tr("Y") << tr("xErr") << tr("yErr")); - vl->addWidget(table); + vl->addWidget(table); connect(table, SIGNAL(itemClicked(QTableWidgetItem*)), this, SLOT(processStateChange(QTableWidgetItem*))); associations = new QListWidget(); associations->setSelectionMode ( QListWidget::SingleSelection ); - vl->addWidget(associations); + vl->addWidget(associations); btnApply = new QPushButton(tr( "&Update curves" )); - btnOK = new QPushButton( tr( "&OK" ) ); + btnOK = new QPushButton( tr( "&OK" ) ); btnOK->setDefault( true ); - btnCancel = new QPushButton( tr( "&Cancel" ) ); + btnCancel = new QPushButton( tr( "&Cancel" ) ); - QHBoxLayout *hbox2 = new QHBoxLayout (); + QHBoxLayout *hbox2 = new QHBoxLayout (); hbox2->addStretch(); - hbox2->addWidget(btnApply); - hbox2->addWidget(btnOK); - hbox2->addWidget(btnCancel); - vl->addStretch(); - vl->addLayout(hbox2); + hbox2->addWidget(btnApply); + hbox2->addWidget(btnOK); + hbox2->addWidget(btnCancel); + vl->addStretch(); + vl->addLayout(hbox2); setLayout(vl); active_table = 0; @@ -213,35 +213,58 @@ Table * AssociationsDialog::findTable(int index) void AssociationsDialog::updateTable(int index) { -Table *t = findTable(index); -if (!t) - return; - -if (active_table != t){ - active_table = t; - tableCaptionLabel->setText(t->objectName()); - table->clearContents(); - table->setRowCount(t->numCols()); - - QStringList colNames = t->colNames(); - for (int i=0; irowCount(); i++ ){ - QTableWidgetItem *cell = new QTableWidgetItem(colNames[i]); - cell->setBackground (QBrush(Qt::lightGray)); - cell->setFlags (Qt::ItemIsEnabled); - table->setItem(i, 0, cell); + Table *t = findTable(index); + if (!t) + return; + + if (active_table != t) + { + active_table = t; + tableCaptionLabel->setText(t->objectName()); + table->clearContents(); + table->setRowCount(t->numCols()); + + QStringList colNames = t->colNames(); + // this vector will tell which rows should be disabled (cause there's no data in them) + std::vector disableRow; + disableRow.resize(table->rowCount(), false); + for (int i=0; irowCount(); i++ ) + { + QTableWidgetItem *cell = new QTableWidgetItem(colNames[i]); + cell->setBackground (QBrush(Qt::lightGray)); + cell->setFlags (Qt::ItemIsEnabled); + table->setItem(i, 0, cell); + + // do we need to disable this row cause the corresponding curve it's empty? + // (empty curves could cause crashes in many other places) + bool allEmpty = true; + // Note possible confusion, here 'table' is the table that you see in the AssociationsDialog, + // whereas t is the underlying data table (spreadsheet). + for (int dataRow = 0; dataRow < t->numRows() && allEmpty; dataRow++) + { + // use i (row in the associations table) as column index + allEmpty = allEmpty & t->text(dataRow, i).isEmpty(); } + if (allEmpty) + disableRow[i] = true; + } - for (int j=1; j < table->columnCount(); j++){ - for (int i=0; i < table->rowCount(); i++ ) + for (int j=1; j < table->columnCount(); j++) + { + for (int i=0; i < table->rowCount(); i++ ) { - QTableWidgetItem *cell = new QTableWidgetItem(); - cell->setBackground(QBrush(Qt::lightGray)); - cell->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - table->setItem(i, j, cell); + QTableWidgetItem *cell = new QTableWidgetItem(); + cell->setBackground(QBrush(Qt::lightGray)); + cell->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + table->setItem(i, j, cell); + + // disable (but keep the checkbox, as set above) + if (disableRow[i]) + cell->setFlags(Qt::NoItemFlags); } } } -updateColumnTypes(); + updateColumnTypes(); } void AssociationsDialog::updateColumnTypes() From fb3dc00e34c32fb80a8df0a4735015546392701a Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Tue, 25 Nov 2014 16:25:07 +0000 Subject: [PATCH 31/41] Refs #10524 Translate existing pos parameters... ... instead of creating new ones from the position. Seems like generating new ones is wildly inaccuarate. --- .../DataHandling/src/SaveParameterFile.cpp | 82 +++++++------------ 1 file changed, 29 insertions(+), 53 deletions(-) diff --git a/Code/Mantid/Framework/DataHandling/src/SaveParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/SaveParameterFile.cpp index 690eb5a44961..3d99443e9ec4 100644 --- a/Code/Mantid/Framework/DataHandling/src/SaveParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/SaveParameterFile.cpp @@ -95,17 +95,41 @@ namespace DataHandling const std::string pType = (*paramsIt).second->type(); const std::string pValue = (*paramsIt).second->asString(); - if(pName == "x" || pName == "y" || pName == "z" || - pName == "r-position" || pName == "t-position" || pName == "p-position" || - pName == "rotx" || pName == "roty" || pName == "rotz" ) - { + if(pName == "x" || pName == "y" || pName == "z" || + pName == "r-position" || pName == "t-position" || pName == "p-position" || + pName == "rotx" || pName == "roty" || pName == "rotz" ) + { g_log.warning() << "The parameter name '" << pName << "' is reserved and has not been saved. " << "Please contact the Mantid team for more information."; continue; } + if(pName == "pos") + { + if(saveLocationParams) + { + V3D pos; + std::istringstream pValueSS(pValue); + pos.readPrinted(pValueSS); + toSave[cID].push_back(boost::make_tuple("x", "double", boost::lexical_cast(pos.X()))); + toSave[cID].push_back(boost::make_tuple("y", "double", boost::lexical_cast(pos.Y()))); + toSave[cID].push_back(boost::make_tuple("z", "double", boost::lexical_cast(pos.Z()))); + } + } + else if(pName == "rot") + { + if(saveLocationParams) + { + V3D rot; + std::istringstream pValueSS(pValue); + rot.readPrinted(pValueSS); + toSave[cID].push_back(boost::make_tuple("rotx", "double", boost::lexical_cast(rot.X()))); + toSave[cID].push_back(boost::make_tuple("roty", "double", boost::lexical_cast(rot.Y()))); + toSave[cID].push_back(boost::make_tuple("rotz", "double", boost::lexical_cast(rot.Z()))); + } + } //If it isn't a position or rotation parameter, we can just add it to the list to save directly and move on. - if(pName != "pos" && pName != "rot") + else { if(pType == "fitting") { @@ -126,54 +150,6 @@ namespace DataHandling } } - std::vector components; - //If we're saving location parameters we'll check every component to see if its location has been changed - if(saveLocationParams) - { - //Get all the components in the instrument - instrument->getChildren(components, true); - prog.resetNumSteps((int64_t)components.size(), 0.3, 0.6); - - for(auto cIt = components.begin(); cIt != components.end(); ++cIt) - { - if(prog.hasCancellationBeenRequested()) - break; - prog.report("Generating location parameters"); - const IComponent* comp = cIt->get(); - const IComponent* baseComp = comp->getBaseComponent(); - const ComponentID cID = const_cast(comp); - - //Check if the position has been changed by a parameter - //If so, check each axis and add the relevant adjustment parameters to the to-save list. - const V3D basePos = baseComp->getPos(); - const V3D absPos = comp->getPos(); - const V3D posDiff = absPos - basePos; - - const double threshold = 0.0001; - - if(std::abs(posDiff.X()) > threshold) - toSave[cID].push_back(boost::make_tuple("x", "double", Strings::toString(absPos.X()))); - if(std::abs(posDiff.Y()) > threshold) - toSave[cID].push_back(boost::make_tuple("y", "double", Strings::toString(absPos.Y()))); - if(std::abs(posDiff.Z()) > threshold) - toSave[cID].push_back(boost::make_tuple("z", "double", Strings::toString(absPos.Z()))); - - //Check if the rotation has been changed by a parameter - //If so, convert to Euler (XYZ order) and output each component that differs - const Quat baseRot = baseComp->getRotation(); - const Quat absRot = comp->getRotation(); - - if(baseRot != absRot) - { - //Euler rotation components are not independent so write them all out to be safe. - std::vector absEuler = absRot.getEulerAngles("XYZ"); - toSave[cID].push_back(boost::make_tuple("rotx", "double", Strings::toString(absEuler[0]))); - toSave[cID].push_back(boost::make_tuple("roty", "double", Strings::toString(absEuler[1]))); - toSave[cID].push_back(boost::make_tuple("rotz", "double", Strings::toString(absEuler[2]))); - } - } - } - //Begin writing the XML manually std::ofstream file(filename.c_str(), std::ofstream::trunc); file << "\n"; From 8db13010ac3571c761aa65ad42b34b9d88765b00 Mon Sep 17 00:00:00 2001 From: Dan Nixon Date: Wed, 26 Nov 2014 13:45:43 +0000 Subject: [PATCH 32/41] Set output workspace for ET tab Refs #10492 --- .../MantidQt/CustomInterfaces/src/IndirectConvertToEnergy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectConvertToEnergy.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectConvertToEnergy.cpp index d43be1b3d414..05a1f2c51e94 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectConvertToEnergy.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/IndirectConvertToEnergy.cpp @@ -181,6 +181,9 @@ namespace CustomInterfaces m_batchAlgoRunner->addAlgorithm(reductionAlg, reductionRuntimeProps); m_batchAlgoRunner->executeBatchAsync(); + + // Set output workspace name for Python export + m_pythonExportWsName = "IndirectInergyTransfer_Workspaces"; } bool IndirectConvertToEnergy::validate() From 34bff70ca9204b1b7e4635badf410ef9cb65f32f Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Wed, 26 Nov 2014 15:32:13 +0000 Subject: [PATCH 33/41] Refs #10238 Warn when plotting unprocessed rows --- .../src/ReflMainViewPresenter.cpp | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp index 0d83bd9fa002..f5e4108de01c 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp +++ b/Code/Mantid/MantidQt/CustomInterfaces/src/ReflMainViewPresenter.cpp @@ -1298,15 +1298,23 @@ namespace MantidQt if(selectedRows.empty()) return; - std::set workspaces; - + std::set workspaces, notFound; for(auto row = selectedRows.begin(); row != selectedRows.end(); ++row) { const std::string wsName = "IvsQ_" + getRunNumber(prepareRunWorkspace(m_model->data(m_model->index(*row, COL_RUNS)).toString().toStdString())); if(AnalysisDataService::Instance().doesExist(wsName)) workspaces.insert(wsName); + else + notFound.insert(wsName); } + if(!notFound.empty()) + m_view->giveUserWarning( + "The following workspaces were not plotted because they were not found:\n" + + boost::algorithm::join(notFound, "\n") + + "\n\nPlease check that the rows you are trying to plot have been fully processed.", + "Error plotting rows."); + m_view->plotWorkspaces(workspaces); } @@ -1337,13 +1345,23 @@ namespace MantidQt runsByGroup[group].push_back(getRunNumber(prepareRunWorkspace(m_model->data(m_model->index(row, COL_RUNS)).toString().toStdString()))); } - std::set workspaces; + std::set workspaces, notFound; for(auto runsMap = runsByGroup.begin(); runsMap != runsByGroup.end(); ++runsMap) { const std::string wsName = "IvsQ_" + boost::algorithm::join(runsMap->second, "_"); if(AnalysisDataService::Instance().doesExist(wsName)) workspaces.insert(wsName); + else + notFound.insert(wsName); } + + if(!notFound.empty()) + m_view->giveUserWarning( + "The following workspaces were not plotted because they were not found:\n" + + boost::algorithm::join(notFound, "\n") + + "\n\nPlease check that the groups you are trying to plot have been fully processed.", + "Error plotting groups."); + m_view->plotWorkspaces(workspaces); } From a8c85dad72b323251adbc6bf8f26e07485eb6809 Mon Sep 17 00:00:00 2001 From: Harry Jeffery Date: Wed, 26 Nov 2014 15:37:32 +0000 Subject: [PATCH 34/41] Refs #10238 Test plotting warnings --- .../test/ReflMainViewPresenterTest.h | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewPresenterTest.h b/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewPresenterTest.h index 5963ba6cd317..cd5fc7c00910 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewPresenterTest.h +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/ReflMainViewPresenterTest.h @@ -1204,6 +1204,58 @@ class ReflMainViewPresenterTest : public CxxTest::TestSuite EXPECT_CALL(mockView, showAlgorithmDialog("SaveReflTBL")); presenter.notify(IReflPresenter::ExportTableFlag); } + + void testPlotRowWarn() + { + MockView mockView; + ReflMainViewPresenter presenter(&mockView); + + createPrefilledWorkspace("TestWorkspace"); + createTOFWorkspace("TOF_12345", "12345"); + EXPECT_CALL(mockView, getWorkspaceToOpen()).Times(1).WillRepeatedly(Return("TestWorkspace")); + presenter.notify(IReflPresenter::OpenTableFlag); + + std::set rowlist; + rowlist.insert(0); + + //We should be warned + EXPECT_CALL(mockView, giveUserWarning(_,_)); + + //The user hits "plot rows" with the first row selected + EXPECT_CALL(mockView, getSelectedRows()).Times(1).WillRepeatedly(Return(rowlist)); + presenter.notify(IReflPresenter::PlotRowFlag); + + //Tidy up + AnalysisDataService::Instance().remove("TestWorkspace"); + AnalysisDataService::Instance().remove("TOF_12345"); + } + + void testPlotGroupWarn() + { + MockView mockView; + ReflMainViewPresenter presenter(&mockView); + + createPrefilledWorkspace("TestWorkspace"); + createTOFWorkspace("TOF_12345", "12345"); + createTOFWorkspace("TOF_12346", "12346"); + EXPECT_CALL(mockView, getWorkspaceToOpen()).Times(1).WillRepeatedly(Return("TestWorkspace")); + presenter.notify(IReflPresenter::OpenTableFlag); + + std::set rowlist; + rowlist.insert(0); + + //We should be warned + EXPECT_CALL(mockView, giveUserWarning(_,_)); + + //The user hits "plot groups" with the first row selected + EXPECT_CALL(mockView, getSelectedRows()).Times(1).WillRepeatedly(Return(rowlist)); + presenter.notify(IReflPresenter::PlotGroupFlag); + + //Tidy up + AnalysisDataService::Instance().remove("TestWorkspace"); + AnalysisDataService::Instance().remove("TOF_12345"); + AnalysisDataService::Instance().remove("TOF_12346"); + } }; #endif /* MANTID_CUSTOMINTERFACES_REFLMAINVIEWPRESENTERTEST_H */ From 1b994cc4f788c5b1f8327a6595827a681f0c7621 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 26 Nov 2014 17:12:53 +0000 Subject: [PATCH 35/41] Fix bug with removing grouped detector ids Refs #10470 --- .../Framework/MDAlgorithms/src/MDNormSXD.cpp | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp b/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp index 9e1575a6054d..f09c2d42862d 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/MDNormSXD.cpp @@ -364,7 +364,7 @@ namespace Mantid integrFlux->getXMinMax(m_kiMin, m_kiMax); API::MatrixWorkspace_const_sptr solidAngleWS = getProperty("SolidAngleWorkspace"); - const auto & exptInfoZero = *(m_normWS->getExperimentInfo(0)); + const auto & exptInfoZero = *(m_inputWS->getExperimentInfo(0)); typedef Kernel::PropertyWithValue > VectorDoubleProperty; auto *rubwLog = dynamic_cast(exptInfoZero.getLog("RUBW_MATRIX")); if(!rubwLog) @@ -398,8 +398,18 @@ namespace Mantid const auto detID = detIDs[i]; double theta(0.0), phi(0.0); - auto spectrum = getThetaPhi(detID, exptInfoZero, theta, phi); - if(spectrum->isMonitor() || spectrum->isMasked()) continue; + bool skip(false); + try + { + auto spectrum = getThetaPhi(detID, exptInfoZero, theta, phi); + if(spectrum->isMonitor() || spectrum->isMasked()) continue; + } + catch(std::exception&) // detector might not exist or has no been included in grouping + { + skip = true;// Intel compiler has a problem with continue inside a catch inside openmp... + } + if(skip) continue; + // Intersections auto intersections = calculateIntersections(theta, phi); if(intersections.empty()) continue; @@ -565,20 +575,27 @@ namespace Mantid const size_t ntotal = detIDs.size(); std::vector singleIDs; singleIDs.reserve(ntotal/2); // reserve half. In the case of 1:1 it will double to the correct size once + std::set groupedIDs; for(auto iter = detIDs.begin(); iter != detIDs.end(); ++iter) { - detid_t frontID = *iter; + detid_t curID = *iter; + if(groupedIDs.count(curID) == 1) continue; // Already been processed + try { - const auto & members = exptInfo.getGroupMembers(*iter); - frontID = members.front(); + const auto & members = exptInfo.getGroupMembers(curID); + singleIDs.push_back(members.front()); + std::copy(members.begin() + 1, members.end(), + std::inserter(groupedIDs, groupedIDs.begin())); } catch (std::runtime_error &) - {} - singleIDs.push_back(frontID); + { + singleIDs.push_back(curID); + } } + g_log.debug() << "Found " << singleIDs.size() << " spectra from " << detIDs.size() << " IDs\n"; return singleIDs; } From bbe3809fdd4378519781309b0d7c76ef9d60b874 Mon Sep 17 00:00:00 2001 From: Martyn Gigg Date: Wed, 26 Nov 2014 17:13:31 +0000 Subject: [PATCH 36/41] Remove a debug statement. The method is most often called in a loop so floods the log messages. Refs #10470 --- Code/Mantid/Framework/API/src/ExperimentInfo.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp index 3a4b3eec95e6..dc140f29be07 100644 --- a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp +++ b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp @@ -365,7 +365,6 @@ namespace API { if(m_detgroups.empty()) { - g_log.debug("No detector mapping cached, getting detector from instrument"); return getInstrument()->getDetector(detID); } else From 6474391b37e2deb7db9d33fc8abd4241886eedd9 Mon Sep 17 00:00:00 2001 From: Owen Arnold Date: Thu, 27 Nov 2014 13:26:23 +0000 Subject: [PATCH 37/41] refs #10643. Add dependencies. --- Code/Mantid/docs/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/docs/CMakeLists.txt b/Code/Mantid/docs/CMakeLists.txt index c2ea1eb661a7..8d4269ddb906 100644 --- a/Code/Mantid/docs/CMakeLists.txt +++ b/Code/Mantid/docs/CMakeLists.txt @@ -43,7 +43,7 @@ if ( SPHINX_FOUND ) add_custom_command ( OUTPUT qthelp/MantidProject.qhcp qthelp/MantidProject.qhp COMMAND ${DOCS_RUNNER_EXE} -xq runsphinx_qthelp.py - DEPENDS Framework MantidPlot ${CMAKE_CURRENT_BINARY_DIR}/runsphinx_qthelp.py + DEPENDS Framework MantidPlot MantidQt ${CMAKE_CURRENT_BINARY_DIR}/runsphinx_qthelp.py COMMENT "Building qt-assistant index files") add_custom_command ( OUTPUT qthelp/MantidProject.qhc @@ -72,7 +72,7 @@ if ( SPHINX_FOUND ) configure_file ( runsphinx.py.in runsphinx_html.py @ONLY ) add_custom_target ( ${TARGET_PREFIX}-html COMMAND ${DOCS_RUNNER_EXE} -xq runsphinx_html.py - DEPENDS Framework MantidPlot ${CMAKE_CURRENT_BINARY_DIR}/runsphinx_html.py ${SPHINX_CONF_DIR}/conf.py conf-html.py + DEPENDS Framework MantidPlot MantidQt ${CMAKE_CURRENT_BINARY_DIR}/runsphinx_html.py ${SPHINX_CONF_DIR}/conf.py conf-html.py COMMENT "Building html documentation" ) # Group within VS and exclude from whole build From 791a73e5507748767424f40ff323ee0e7598b725 Mon Sep 17 00:00:00 2001 From: Nick Draper Date: Thu, 27 Nov 2014 15:15:27 +0000 Subject: [PATCH 38/41] re #10509 Add Instrument From to workspace details --- Code/Mantid/Framework/API/src/ExperimentInfo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp index f353ef0cb2c6..78ea319d7afe 100644 --- a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp +++ b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp @@ -114,6 +114,8 @@ namespace API << inst->getValidFromDate().toFormattedString("%Y-%b-%d") << " to " << inst->getValidToDate().toFormattedString("%Y-%b-%d") << ")"; out << "\n"; + out << "Instrument from: " << inst->getFilename(); + out << "\n"; std::string runStart = getAvailableWorkspaceStartDate(); std::string runEnd = getAvailableWorkspaceEndDate(); From b846000a488939707060cd126fa5c2b5ff723591 Mon Sep 17 00:00:00 2001 From: Nick Draper Date: Thu, 27 Nov 2014 16:04:47 +0000 Subject: [PATCH 39/41] re #10509 extend to support parameter files --- .../Framework/API/src/ExperimentInfo.cpp | 8 ++++++++ .../DataHandling/src/LoadParameterFile.cpp | 4 ++++ .../MantidGeometry/Instrument/ParameterMap.h | 8 ++++++++ .../Geometry/src/Instrument/ParameterMap.cpp | 18 +++++++++++++++++- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp index 78ea319d7afe..a77fb9a692aa 100644 --- a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp +++ b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp @@ -117,6 +117,14 @@ namespace API out << "Instrument from: " << inst->getFilename(); out << "\n"; + //parameter files loaded + auto paramFileVector = this->instrumentParameters().getParameterFilenames(); + for (auto itFilename = paramFileVector.begin(); itFilename != paramFileVector.end(); ++itFilename) + { + out << "Parameters from: " << *itFilename; + out << "\n"; + } + std::string runStart = getAvailableWorkspaceStartDate(); std::string runEnd = getAvailableWorkspaceEndDate(); std::string msgNA = "not available"; diff --git a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp index e297a119680f..50f65dbec575 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadParameterFile.cpp @@ -141,6 +141,10 @@ void LoadParameterFile::exec() // populate parameter map of workspace localWorkspace->populateInstrumentParameters(); + if (!filename.empty()) + { + localWorkspace->instrumentParameters().addParameterFilename(filename); + } prog.resetNumSteps(1, 0.0, 1.0); prog.report("Done"); diff --git a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h index 238d434d893c..9f071302f0db 100644 --- a/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h +++ b/Code/Mantid/Framework/Geometry/inc/MantidGeometry/Instrument/ParameterMap.h @@ -265,6 +265,12 @@ namespace Geometry void saveNexus(::NeXus::File * file, const std::string & group) const; /// Copy pairs (oldComp->id,Parameter) to the m_map assigning the new newComp->id void copyFromParameterMap(const IComponent* oldComp,const IComponent* newComp, const ParameterMap *oldPMap); + + /// Returns a list of all the parameter files loaded + const std::vector& getParameterFilenames() const; + /// adds a parameter filename that has been loaded + void addParameterFilename(const std::string& filename); + /// access iterators. begin; pmap_it begin(){return m_map.begin();} pmap_cit begin()const{return m_map.begin();} @@ -280,6 +286,8 @@ namespace Geometry ///const version of the internal function to get position of the parameter in the parameter map component_map_cit positionOf(const IComponent* comp,const char *name, const char * type) const; + /// internal list of parameter files loaded + std::vector m_parameterFileNames; /// internal parameter map instance pmap m_map; diff --git a/Code/Mantid/Framework/Geometry/src/Instrument/ParameterMap.cpp b/Code/Mantid/Framework/Geometry/src/Instrument/ParameterMap.cpp index 9741362db103..93f0e7b16a38 100644 --- a/Code/Mantid/Framework/Geometry/src/Instrument/ParameterMap.cpp +++ b/Code/Mantid/Framework/Geometry/src/Instrument/ParameterMap.cpp @@ -45,7 +45,7 @@ namespace Mantid * Default constructor */ ParameterMap::ParameterMap() - : m_map() + : m_parameterFileNames(), m_map() {} /** @@ -1026,5 +1026,21 @@ namespace Mantid file->closeGroup(); } + /** Returns a list of all the parameter files loaded + * @returns a vector of the filenames + */ + const std::vector& ParameterMap::getParameterFilenames() const + { + return m_parameterFileNames; + } + /// + /** adds a parameter filename that has been loaded + * @param filename the filename to add + */ + void ParameterMap::addParameterFilename(const std::string& filename) + { + m_parameterFileNames.push_back(filename); + } + } // Namespace Geometry } // Namespace Mantid From 6cbea49264901efb71945a3986d78a29c1c7d5d2 Mon Sep 17 00:00:00 2001 From: Nick Draper Date: Thu, 27 Nov 2014 16:08:59 +0000 Subject: [PATCH 40/41] re #10509 solve failing test --- Code/Mantid/Framework/API/src/ExperimentInfo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp index a77fb9a692aa..bc6e25f8e937 100644 --- a/Code/Mantid/Framework/API/src/ExperimentInfo.cpp +++ b/Code/Mantid/Framework/API/src/ExperimentInfo.cpp @@ -114,8 +114,11 @@ namespace API << inst->getValidFromDate().toFormattedString("%Y-%b-%d") << " to " << inst->getValidToDate().toFormattedString("%Y-%b-%d") << ")"; out << "\n"; - out << "Instrument from: " << inst->getFilename(); - out << "\n"; + if (!inst->getFilename().empty()) + { + out << "Instrument from: " << inst->getFilename(); + out << "\n"; + } //parameter files loaded auto paramFileVector = this->instrumentParameters().getParameterFilenames(); From c6a90e9e81a407850f940b2a339e5e4790bd92ed Mon Sep 17 00:00:00 2001 From: Federico Montesino Pouzols Date: Thu, 27 Nov 2014 17:17:28 +0000 Subject: [PATCH 41/41] use AutoPtr to handle mem in poco xml objects, cut headers, re #8484 --- .../Framework/Algorithms/src/CreateDummyCalFile.cpp | 9 +-------- .../Framework/Algorithms/src/ReadGroupsFromFile.cpp | 4 ++-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/Code/Mantid/Framework/Algorithms/src/CreateDummyCalFile.cpp b/Code/Mantid/Framework/Algorithms/src/CreateDummyCalFile.cpp index 3415f9089f3c..ec980415f9d5 100644 --- a/Code/Mantid/Framework/Algorithms/src/CreateDummyCalFile.cpp +++ b/Code/Mantid/Framework/Algorithms/src/CreateDummyCalFile.cpp @@ -14,9 +14,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -25,10 +22,6 @@ using Poco::XML::DOMParser; using Poco::XML::Document; using Poco::XML::Element; -using Poco::XML::Node; -using Poco::XML::NodeList; -using Poco::XML::NodeIterator; -using Poco::XML::NodeFilter; namespace Mantid @@ -87,7 +80,7 @@ namespace Mantid // Set up the DOM parser and parse xml file DOMParser pParser; - Document* pDoc; + Poco::AutoPtr pDoc; try { pDoc = pParser.parse(directoryName+instshort); diff --git a/Code/Mantid/Framework/Algorithms/src/ReadGroupsFromFile.cpp b/Code/Mantid/Framework/Algorithms/src/ReadGroupsFromFile.cpp index b045f98e20cc..d2b22a36a0c1 100644 --- a/Code/Mantid/Framework/Algorithms/src/ReadGroupsFromFile.cpp +++ b/Code/Mantid/Framework/Algorithms/src/ReadGroupsFromFile.cpp @@ -203,7 +203,7 @@ namespace Algorithms void ReadGroupsFromFile::readXMLGroupingFile(const std::string& filename) { Poco::XML::DOMParser xmlParser; - Poco::XML::Document* file; + Poco::AutoPtr file; try { file = xmlParser.parse(filename); @@ -220,7 +220,7 @@ namespace Algorithms throw Kernel::Exception::FileError("No root element in XML grouping file: ", filename); } - Poco::XML::NodeList* groups = root->getElementsByTagName("group"); + Poco::AutoPtr groups = root->getElementsByTagName("group"); if ( groups->length() == 0 ) {