From 7a72cc60e7e814697bec6898f97817a1928dafd8 Mon Sep 17 00:00:00 2001
From: Russell Taylor <taylorrj@ornl.gov>
Date: Wed, 24 Mar 2010 17:08:45 +0000
Subject: [PATCH] Improve the speed of LoadRaw in the presence of multiple
 periods, particularly in the case where the monitors are loaded separately
 where memory usage is also significantly reduced if there are large log
 files. Also fixed a minor bug in the attachment of period logs to workspaces.
 Re #1154.

---
 .../API/inc/MantidAPI/MatrixWorkspace.h       |  11 +-
 Code/Mantid/API/src/MatrixWorkspace.cpp       |  22 ++-
 Code/Mantid/API/src/WorkspaceFactory.cpp      |   2 +-
 Code/Mantid/API/test/MatrixWorkspaceTest.h    |   8 +-
 Code/Mantid/Algorithms/Algorithms.vcproj      |   4 +
 .../Algorithms/src/HRPDSlabCanAbsorption.cpp  |  14 +-
 Code/Mantid/CurveFitting/src/Linear.cpp       |  10 +-
 Code/Mantid/DataHandling/src/LoadRaw3.cpp     | 131 +++++++-----------
 Code/Mantid/Kernel/src/PropertyManager.cpp    |   4 +-
 9 files changed, 83 insertions(+), 123 deletions(-)

diff --git a/Code/Mantid/API/inc/MantidAPI/MatrixWorkspace.h b/Code/Mantid/API/inc/MantidAPI/MatrixWorkspace.h
index 6a84dc5df3f..126c5f91ecc 100644
--- a/Code/Mantid/API/inc/MantidAPI/MatrixWorkspace.h
+++ b/Code/Mantid/API/inc/MantidAPI/MatrixWorkspace.h
@@ -69,8 +69,6 @@ public:
   virtual ~MatrixWorkspace();
 
   void setInstrument(const IInstrument_sptr&);
-  /// setting the sample object
-  void setSample(const Sample& sample);
   IInstrument_sptr getInstrument() const;
   boost::shared_ptr<Instrument> getBaseInstrument()const;
 
@@ -78,12 +76,10 @@ public:
   const SpectraDetectorMap& spectraMap() const;
   SpectraDetectorMap& mutableSpectraMap();
 
-  /// Sample accessors  
+  /// Sample accessors
   const  Sample& sample() const;
-  ///  mutable accessor
   Sample& mutableSample();
- 
-  
+
   /// Get a detector object (Detector or DetectorGroup) for the given spectrum index
   Geometry::IDetector_sptr getDetector(const int index) const;
   double detectorTwoTheta(Geometry::IDetector_const_sptr det) const;
@@ -95,7 +91,6 @@ public:
   Geometry::ParameterMap& instrumentParameters()const;
   /// Const version
   const Geometry::ParameterMap& constInstrumentParameters() const;
-  //void newInstrumentParameters();
   // Add parameters to the instrument parameter map
   void populateInstrumentParameters();
 
@@ -194,7 +189,7 @@ private:
   bool m_isDistribution;
 
   /// Parameters modifying the base instrument
- mutable Kernel::cow_ptr<Geometry::ParameterMap> m_parmap;
+  mutable Kernel::cow_ptr<Geometry::ParameterMap> m_parmap;
 
   /// The set of masked bins in a map keyed on spectrum index
   std::map< int, MaskList > m_masks;
diff --git a/Code/Mantid/API/src/MatrixWorkspace.cpp b/Code/Mantid/API/src/MatrixWorkspace.cpp
index 987f5a50a59..69655735765 100644
--- a/Code/Mantid/API/src/MatrixWorkspace.cpp
+++ b/Code/Mantid/API/src/MatrixWorkspace.cpp
@@ -87,13 +87,6 @@ void MatrixWorkspace::setInstrument(const IInstrument_sptr& instr)
     }
   }
 }
-/** Set the sample
- *  @param sample constant reference to the sample object
- */
-void MatrixWorkspace::setSample(const Sample& sample)
-{ 
-  m_sample.access()=sample;
-}
 
 /** Get a const reference to the SpectraDetectorMap associated with this workspace.
  *  Can ONLY be taken as a const reference!
@@ -118,19 +111,22 @@ SpectraDetectorMap& MatrixWorkspace::mutableSpectraMap()
 }
 
 /** Get a constant reference to the Sample associated with this workspace.
-
-*/
+ */
 const  Sample& MatrixWorkspace::sample() const
 {
-	return *m_sample;
+  return *m_sample;
 }
-/** Get a reference to the Sample associated with this workspace.
 
-*/
+/** Get a reference to the Sample associated with this workspace.
+ *  This non-const method will copy the sample if it is shared between 
+ *  more than one workspace, and the reference returned will be to the copy.
+ *  Can ONLY be taken by reference!
+ */
 Sample& MatrixWorkspace::mutableSample()
 {
-	return m_sample.access();
+  return m_sample.access();
 }
+
 /** Get the effective detector for the given spectrum
  *  @param  index The workspace index for which the detector is required
  *  @return A single detector object representing the detector(s) contributing
diff --git a/Code/Mantid/API/src/WorkspaceFactory.cpp b/Code/Mantid/API/src/WorkspaceFactory.cpp
index 2765c353b80..22bb5e82609 100644
--- a/Code/Mantid/API/src/WorkspaceFactory.cpp
+++ b/Code/Mantid/API/src/WorkspaceFactory.cpp
@@ -68,7 +68,7 @@ MatrixWorkspace_sptr WorkspaceFactoryImpl::create(const MatrixWorkspace_const_sp
   ws->setComment(parent->getComment());
   ws->setInstrument(parent->getInstrument());  // This call also copies the parameter map
   ws->m_spectramap = parent->m_spectramap;
-  ws->setSample(parent->sample());
+  ws->m_sample = parent->m_sample;
   ws->setYUnit(parent->m_YUnit);
   ws->setYUnitLabel(parent->m_YUnitLabel);
   ws->isDistribution(parent->isDistribution());
diff --git a/Code/Mantid/API/test/MatrixWorkspaceTest.h b/Code/Mantid/API/test/MatrixWorkspaceTest.h
index e492ff5dfc8..8c8cdca8dd9 100644
--- a/Code/Mantid/API/test/MatrixWorkspaceTest.h
+++ b/Code/Mantid/API/test/MatrixWorkspaceTest.h
@@ -87,12 +87,8 @@ public:
 
   void testGetSetSample()
   {
-	TS_ASSERT( &ws->sample() )
-    //boost::shared_ptr<Sample> s(new Sample);
-	Sample s;
-	TS_ASSERT_THROWS_NOTHING( ws->setSample(s) )
-	//TS_ASSERT_EQUALS( &ws->sample(), &s )
- 
+    TS_ASSERT( &ws->sample() )
+
     ws->mutableSample().setName("test");
     TS_ASSERT_EQUALS( ws->sample().getName(), "test" )
   }
diff --git a/Code/Mantid/Algorithms/Algorithms.vcproj b/Code/Mantid/Algorithms/Algorithms.vcproj
index 4f6bc997f65..9d07b4f8ede 100644
--- a/Code/Mantid/Algorithms/Algorithms.vcproj
+++ b/Code/Mantid/Algorithms/Algorithms.vcproj
@@ -940,6 +940,10 @@
 				RelativePath=".\test\ReplaceSpecialValuesTest.h"
 				>
 			</File>
+			<File
+				RelativePath=".\inc\MantidAlgorithms\Scale.h"
+				>
+			</File>
 			<File
 				RelativePath=".\inc\MantidAlgorithms\SimpleIntegration.h"
 				>
diff --git a/Code/Mantid/Algorithms/src/HRPDSlabCanAbsorption.cpp b/Code/Mantid/Algorithms/src/HRPDSlabCanAbsorption.cpp
index ceac669e254..d178cb759a6 100644
--- a/Code/Mantid/Algorithms/src/HRPDSlabCanAbsorption.cpp
+++ b/Code/Mantid/Algorithms/src/HRPDSlabCanAbsorption.cpp
@@ -42,7 +42,12 @@ void HRPDSlabCanAbsorption::init()
     "Select the method to use to calculate exponentials, normal or a\n"
     "fast approximation (default: Normal)" );
 
-  declareProperty("Thickness", -1.0, mustBePositive->clone());
+  std::vector<std::string> thicknesses(4);
+  thicknesses[0] = "0.2";
+  thicknesses[1] = "0.5";
+  thicknesses[2] = "1.0";
+  thicknesses[3] = "1.5";
+  declareProperty("Thickness", "", new ListValidator(thicknesses));
   
   BoundedValidator<double> *moreThanZero = new BoundedValidator<double> ();
   moreThanZero->setLower(0.001);
@@ -83,6 +88,7 @@ void HRPDSlabCanAbsorption::exec()
   const int specSize = workspace->blocksize();
   const bool isHist = workspace->isHistogramData();
   //
+  Progress progress(this,0.91,1.0,numHists);
   for (int i = 0; i < numHists; ++i)
   {
     const MantidVec& X = workspace->readX(i);
@@ -138,6 +144,7 @@ void HRPDSlabCanAbsorption::exec()
       }
     }
 
+    progress.report();
   }
   
   setProperty("OutputWorkspace", workspace);
@@ -146,7 +153,7 @@ void HRPDSlabCanAbsorption::exec()
 API::MatrixWorkspace_sptr HRPDSlabCanAbsorption::runFlatPlateAbsorption()
 {
   // Call FlatPlateAbsorption as a sub-algorithm
-  IAlgorithm_sptr childAlg = createSubAlgorithm("FlatPlateAbsorption");
+  IAlgorithm_sptr childAlg = createSubAlgorithm("FlatPlateAbsorption",0.0,0.9);
   // Pass through all the properties
   childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", getProperty("InputWorkspace"));
   childAlg->setProperty<double>("AttenuationXSection", getProperty("SampleAttenuationXSection"));
@@ -160,7 +167,8 @@ API::MatrixWorkspace_sptr HRPDSlabCanAbsorption::runFlatPlateAbsorption()
   childAlg->setProperty("SampleHeight", HRPDCanHeight);
   childAlg->setProperty("SampleWidth", HRPDCanWidth);
   // Valid values are 0.2,0.5,1.0 & 1.5 - would be nice to have a numeric list validator
-  childAlg->setProperty<double>("SampleThickness", getProperty("Thickness"));
+  const std::string thickness = getPropertyValue("Thickness");
+  childAlg->setPropertyValue("SampleThickness", thickness);
 
   // Now execute the sub-algorithm. Catch and log any error
   try
diff --git a/Code/Mantid/CurveFitting/src/Linear.cpp b/Code/Mantid/CurveFitting/src/Linear.cpp
index 10599033625..76e07e71b40 100644
--- a/Code/Mantid/CurveFitting/src/Linear.cpp
+++ b/Code/Mantid/CurveFitting/src/Linear.cpp
@@ -171,15 +171,7 @@ void Linear::exec()
   
   // Create and fill a workspace2D with the same bins as the fitted spectrum and the value of the fit for the centre of each bin
   const int YSize = Y.size();
-  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create("Workspace2D",1,X.size(),YSize);
-  // Copy over various data members from the input workspace
-  outputWorkspace->setInstrument(inputWorkspace->getInstrument());
-  //outputWorkspace->setSample(inputWorkspace->getSample());
-  outputWorkspace->setSample(inputWorkspace->sample());
-  outputWorkspace->setYUnit(inputWorkspace->YUnit());
-  outputWorkspace->isDistribution(inputWorkspace->isDistribution());
-  outputWorkspace->getAxis(0)->unit() = inputWorkspace->getAxis(0)->unit();
-  outputWorkspace->getAxis(0)->title() = inputWorkspace->getAxis(0)->title();
+  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,1,X.size(),YSize);
   
   // Copy over the X bins
   outputWorkspace->dataX(0).assign(X.begin(),X.end());
diff --git a/Code/Mantid/DataHandling/src/LoadRaw3.cpp b/Code/Mantid/DataHandling/src/LoadRaw3.cpp
index 9ac007c8982..6ee97925ca8 100644
--- a/Code/Mantid/DataHandling/src/LoadRaw3.cpp
+++ b/Code/Mantid/DataHandling/src/LoadRaw3.cpp
@@ -166,8 +166,7 @@ void LoadRaw3::exec()
       getTimeChannels(noTimeRegimes, m_lengthIn);
 
   // Need to extract the user-defined output workspace name
-  Property *ws = getProperty("OutputWorkspace");
-  std::string localWSName = ws->value();
+  const std::string localWSName = getPropertyValue("OutputWorkspace");
 
   int histTotal = total_specs * m_numberOfPeriods;
   int histCurrent = -1;
@@ -176,8 +175,23 @@ void LoadRaw3::exec()
   DataObjects::Workspace2D_sptr localWorkspace = createWorkspace(total_specs, m_lengthIn);
   localWorkspace->setTitle(title);
 
+  // Only run the sub-algorithms once
   runLoadInstrument(localWorkspace);
   runLoadMappingTable(localWorkspace);
+  Sample& sample = localWorkspace->mutableSample();
+  if (bLoadlogFiles)
+  {
+    runLoadLog(localWorkspace);
+    Property* log = createPeriodLog(1);
+    if (log) sample.addLogData(log);
+  }
+  // Set the total proton charge for this run
+  sample.setProtonCharge(isisRaw->rpb.r_gd_prtn_chrg);
+
+  // populate instrument parameters
+  g_log.debug("Populating the instrument parameters...");
+  progress(m_prog, "Populating the instrument parameters...");
+  localWorkspace->populateInstrumentParameters();
 
   WorkspaceGroup_sptr sptrWSGrp = WorkspaceGroup_sptr(new WorkspaceGroup);
   WorkspaceGroup_sptr monitorWSGrp;
@@ -197,7 +211,8 @@ void LoadRaw3::exec()
     // now create a workspace of size normalwsSpecs and set it as outputworkspace
     if (normalwsSpecs > 0)
     {
-      localWorkspace = createWorkspace(normalwsSpecs, m_lengthIn);
+      localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>
+        (WorkspaceFactory::Instance().create(localWorkspace,normalwsSpecs,m_lengthIn,m_lengthIn-1));
       setWorkspaceProperty("OutputWorkspace", title, sptrWSGrp, localWorkspace, false);
     }
     if (normalwsSpecs <= 0 && bexcludeMonitors)
@@ -210,7 +225,8 @@ void LoadRaw3::exec()
     {
       if (monitorwsSpecs > 0)
       { //create monitor workspace
-        monitorWorkspace = createWorkspace(monitorwsSpecs, m_lengthIn);
+        monitorWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>
+          (WorkspaceFactory::Instance().create(localWorkspace,monitorwsSpecs,m_lengthIn,m_lengthIn-1));
         //create monitor workspace group
         monitorWSGrp = createGroupWorkspace();
         if (normalwsSpecs > 0)
@@ -238,15 +254,25 @@ void LoadRaw3::exec()
     {
       localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(
           WorkspaceFactory::Instance().create(localWorkspace));
-      //localWorkspace->newSample();
+
+      if (bLoadlogFiles)
+      {
+        //remove previous period data
+        std::stringstream prevPeriod;
+        prevPeriod << "PERIOD " << (period);
+        //std::string prevPeriod="PERIOD "+suffix.str();
+        Sample& sampleObj = localWorkspace->mutableSample();
+        sampleObj.removeLogData(prevPeriod.str());
+        //add current period data
+        Property* log = createPeriodLog(period+1);
+        if (log) sampleObj.addLogData(log);
+      }
 
       if (bseparateMonitors && monitorwsSpecs > 0)
       {
         monitorWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(
-            WorkspaceFactory::Instance().create(monitorWorkspace));
-        //monitorWorkspace->newSample();
+            WorkspaceFactory::Instance().create(localWorkspace,monitorwsSpecs,m_lengthIn,m_lengthIn-1));
       }
-      //localWorkspace->newInstrumentParameters(); ????
     }
     isisRaw->skipData(file, period * (m_numberOfSpectra + 1));
     int counter = 0;
@@ -308,58 +334,7 @@ void LoadRaw3::exec()
         isisRaw->skipData(file, histToRead);
       }
     }
-    if (period == 0)
-    {
-      // Only run the sub-algorithms once
-      if (bLoadlogFiles)
-      {
-        runLoadLog(localWorkspace);
-        Property* log=createPeriodLog(period+1);
-        if(log)localWorkspace->mutableSample().addLogData(log);
-      }
-
-      if (bseparateMonitors || bexcludeMonitors)
-      {
-        runLoadInstrument(localWorkspace);
-        runLoadMappingTable(localWorkspace);
-        if (monitorWorkspace)
-        { 
-          runLoadInstrument(monitorWorkspace);
-          runLoadMappingTable(monitorWorkspace);
-          if (bLoadlogFiles)monitorWorkspace->setSample(localWorkspace->sample());
-          monitorWorkspace->mutableSample().setProtonCharge(isisRaw->rpb.r_gd_prtn_chrg);
-        }
-      }
-      // Set the total proton charge for this run
-      // (not sure how this works for multi_period files)
-      localWorkspace->mutableSample().setProtonCharge(isisRaw->rpb.r_gd_prtn_chrg);
-    }
-    else // We are working on a higher period of a multiperiod raw file
-    {
-      if (bLoadlogFiles)
-      {
-        //remove previous period data
-        std::stringstream suffix;
-        suffix << (period);
-        std::string prevPeriod="PERIOD "+suffix.str();
-        localWorkspace->mutableSample().removeLogData(prevPeriod);
-        //add current period data
-        Property* log=createPeriodLog(period+1);
-        if(log)localWorkspace->mutableSample().addLogData(log);
-        if(monitorWorkspace)monitorWorkspace->setSample(localWorkspace->sample());
-      }
-    }
-
-    // populate instrument parameters
-
-    g_log.debug("Populating the instrument parameters...");
-    progress(m_prog, "Populating the instrument parameters...");
-    localWorkspace->populateInstrumentParameters();
-    if (monitorWorkspace)
-      monitorWorkspace->populateInstrumentParameters();
-
     // Assign the result to the output workspace property
-
     if (m_numberOfPeriods > 1)
     {
       if (bseparateMonitors)
@@ -392,19 +367,19 @@ void LoadRaw3::exec()
  */
 Kernel::Property*  LoadRaw3::createPeriodLog(int period)const
 {
-    Kernel::TimeSeriesProperty<int>* periods = dynamic_cast< Kernel::TimeSeriesProperty<int>* >(m_perioids.get());
-    if(!periods) return 0;
-    std::ostringstream ostr;
-    ostr<<period;
-    Kernel::TimeSeriesProperty<bool>* p = new Kernel::TimeSeriesProperty<bool> ("period "+ostr.str());
-    std::map<Kernel::dateAndTime, int> pMap = periods->valueAsMap();
-    std::map<Kernel::dateAndTime, int>::const_iterator it = pMap.begin();
-    if (it->second != period)
-        p->addValue(it->first,false);
-    for(;it!=pMap.end();it++)
-        p->addValue(it->first, (it->second == period) );
+  Kernel::TimeSeriesProperty<int>* periods = dynamic_cast< Kernel::TimeSeriesProperty<int>* >(m_perioids.get());
+  if(!periods) return 0;
+  std::ostringstream ostr;
+  ostr<<period;
+  Kernel::TimeSeriesProperty<bool>* p = new Kernel::TimeSeriesProperty<bool> ("period "+ostr.str());
+  std::map<Kernel::dateAndTime, int> pMap = periods->valueAsMap();
+  std::map<Kernel::dateAndTime, int>::const_iterator it = pMap.begin();
+  if (it->second != period)
+    p->addValue(it->first,false);
+  for(;it!=pMap.end();it++)
+    p->addValue(it->first, (it->second == period) );
 
-    return p;
+  return p;
 }
 
 /** sets the workspace properties
@@ -839,6 +814,7 @@ void LoadRaw3::goManagedRaw(bool bincludeMonitors, bool bexcludeMonitors, bool b
 }
 
 /** This method separates/excludes monitors from output workspace and creates a separate workspace for monitors
+ *  THIS METHOD IS ONLY CALLED BY THE goManagedRaw METHOD ABOVE AND NOT IN THE GENERAL CASE
  *  @param localWorkspace shared pointer to workspace
  *  @param bincludeMonitors boolean  variable for including monitors
  *  @param bexcludeMonitors  boolean variable for excluding monitors
@@ -862,8 +838,8 @@ void LoadRaw3::separateOrexcludeMonitors(DataObjects::Workspace2D_sptr localWork
     declareProperty(new WorkspaceProperty<Workspace> ("MonitorWorkspace", monitorWSName,
         Direction::Output));
     //create monitor workspace
-    monitorWorkspace = createWorkspace(monitorSpecList.size(), m_lengthIn);
-    monitorWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
+    monitorWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(
+      WorkspaceFactory::Instance().create(localWorkspace,monitorSpecList.size(),m_lengthIn,m_lengthIn-1));
     setProperty("MonitorWorkspace", boost::dynamic_pointer_cast<Workspace>(monitorWorkspace));
     file = fopen(m_filename.c_str(), "rb");
     if (file == NULL)
@@ -914,14 +890,6 @@ void LoadRaw3::separateOrexcludeMonitors(DataObjects::Workspace2D_sptr localWork
     if (bseparateMonitors)
     {
       fclose(file);
-      monitorWorkspace->mutableSample().setProtonCharge(isisRaw->rpb.r_gd_prtn_chrg);
-      if (monitorWorkspace)
-      {
-        runLoadInstrument(monitorWorkspace);
-        runLoadMappingTable(monitorWorkspace);
-        localWorkspace->setSample(localWorkspace->sample());
-        monitorWorkspace->populateInstrumentParameters();
-      }
     }
   }
 }
@@ -1112,6 +1080,5 @@ void LoadRaw3::runLoadLog(DataObjects::Workspace2D_sptr localWorkspace, int peri
   if(plog) m_perioids=plog->getPeriodsProperty();
 }
 
-
 } // namespace DataHandling
 } // namespace Mantid
diff --git a/Code/Mantid/Kernel/src/PropertyManager.cpp b/Code/Mantid/Kernel/src/PropertyManager.cpp
index 6b45b52fef2..33160e2f628 100644
--- a/Code/Mantid/Kernel/src/PropertyManager.cpp
+++ b/Code/Mantid/Kernel/src/PropertyManager.cpp
@@ -28,7 +28,9 @@ namespace Mantid
       {
         Property * p = other.m_orderedProperties[i]->clone();
         this->m_orderedProperties[i] = p;
-        this->m_properties[p->name()] = p;
+        std::string key = p->name();
+        std::transform(key.begin(), key.end(), key.begin(), toupper);
+        this->m_properties[key] = p;
       }
     }
 
-- 
GitLab