diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h index 368353fdaa571c05cffb86c1ec7e60e872fb75f0..82799b51f9005a965cb3d7d1bc78ad6251b6b510 100644 --- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h +++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadMuonNexus1.h @@ -110,7 +110,7 @@ namespace Mantid std::vector<double>::const_iterator end); /// Loads detector grouping information - void loadDetectorGrouping(Mantid::NeXus::NXRoot& root); + API::Workspace_sptr loadDetectorGrouping(Mantid::NeXus::NXRoot& root); /// Creates Detector Grouping Table using all the data from the range TableWorkspace_sptr createDetectorGroupingTable(std::vector<int>::const_iterator begin, diff --git a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp index b8cd8f2cbe62be708e5676978cf3ec5977d29dca..26df5bb184a83977fe36aad24c0d045e932386d0 100644 --- a/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp +++ b/Code/Mantid/Framework/DataHandling/src/LoadMuonNexus1.cpp @@ -176,12 +176,30 @@ namespace Mantid // Try to load dead time info loadDeadTimes(root); - // Try to load detector grouping info - loadDetectorGrouping(root); + bool autoGroup = getProperty("AutoGroup"); + + // Grouping info should be returned if user has set the property + bool returnGrouping = !getPropertyValue("DetectorGroupingTable").empty(); + + Workspace_sptr loadedGrouping; + + // Try to load detector grouping info, if needed for auto-grouping or user requested it + if ( autoGroup || returnGrouping ) + { + loadedGrouping = loadDetectorGrouping(root); + + if ( loadedGrouping ) + { + // Return loaded grouping, if requested + if ( returnGrouping ) + setProperty("DetectorGroupingTable", loadedGrouping); + } + else + { + g_log.warning("Unable to load grouping from the file. Grouping not applied."); + } + } - // Need to extract the user-defined output workspace name - Property *ws = getProperty("OutputWorkspace"); - std::string localWSName = ws->value(); // If multiperiod, will need to hold the Instrument & Sample for copying boost::shared_ptr<Instrument> instrument; boost::shared_ptr<Sample> sample; @@ -233,10 +251,6 @@ namespace Mantid localWorkspace->setYUnit("Counts"); WorkspaceGroup_sptr wsGrpSptr=WorkspaceGroup_sptr(new WorkspaceGroup); - if(m_numberOfPeriods>1) - { - setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(wsGrpSptr)); - } API::Progress progress(this,0.,1.,m_numberOfPeriods * total_specs); // Loop over the number of periods in the Nexus file, putting each period in a separate workspace @@ -265,24 +279,6 @@ namespace Mantid (WorkspaceFactory::Instance().create(localWorkspace)); localWorkspace->setTitle(title); localWorkspace->setComment(notes); - //localWorkspace->newInstrumentParameters(); ??? - - } - - - std::string outws(""); - if(m_numberOfPeriods>1) - { - std::string outputWorkspace = "OutputWorkspace"; - std::stringstream suffix; - suffix << (period+1); - outws =outputWorkspace+"_"+suffix.str(); - std::string WSName = localWSName + "_" + suffix.str(); - declareProperty(new WorkspaceProperty<Workspace>(outws,WSName,Direction::Output)); - if (wsGrpSptr) - { - wsGrpSptr->addWorkspace( localWorkspace ); - } } size_t counter = 0; @@ -307,156 +303,49 @@ namespace Mantid // Just a sanity check assert(counter == size_t(total_specs) ); - bool autogroup = getProperty("AutoGroup"); + Workspace_sptr outWs; - if (autogroup) + if (autoGroup && loadedGrouping) { + TableWorkspace_sptr groupingTable; - //Get the groupings - int64_t max_group = 0; - // use a map for mapping group number and output workspace index in case - // there are group numbers > number of groups - std::map<int64_t,int64_t> groups; - m_groupings.resize(nxload.numDetectors); - bool thereAreZeroes = false; - for (int64_t i =0; i < static_cast<int64_t>(nxload.numDetectors); ++i) + if ( auto table = boost::dynamic_pointer_cast<TableWorkspace>(loadedGrouping) ) + { + groupingTable = table; + } + else if ( auto group = boost::dynamic_pointer_cast<WorkspaceGroup>(loadedGrouping) ) { - int64_t ig = static_cast<int64_t>(nxload.detectorGroupings[i]); - if (ig == 0) - { - thereAreZeroes = true; - continue; - } - m_groupings[i] = static_cast<specid_t>(ig); - if (groups.find(ig) == groups.end()) - groups[ig] = static_cast<int64_t>(groups.size()); - if (ig > max_group) max_group = ig; + groupingTable = boost::dynamic_pointer_cast<TableWorkspace>( group->getItem(period) ); } - if (thereAreZeroes) - for (int64_t i =0; i < static_cast<int64_t>(nxload.numDetectors); ++i) - { - int64_t ig = static_cast<int64_t>(nxload.detectorGroupings[i]); - if (ig == 0) - { - ig = ++max_group; - m_groupings[i] = static_cast<specid_t>(ig); - groups[ig] = groups.size(); - } - } - - int numHists = static_cast<int>(localWorkspace->getNumberHistograms()); - size_t ngroups = groups.size(); // number of groups - - // to output groups in ascending order - { - int64_t i=0; - for(std::map<int64_t,int64_t>::iterator it=groups.begin();it!=groups.end();++it,++i) - { - it->second = i; - g_log.information()<<"group "<<it->first<<": "; - bool first = true; - int64_t first_i = -1 * std::numeric_limits<int64_t>::max(); - int64_t last_i = -1 * std::numeric_limits<int64_t>::max(); - for(int64_t i=0;i<static_cast<int64_t>(numHists);i++) - if (m_groupings[i] == it->first) - { - if (first) - { - first = false; - g_log.information()<<i; - first_i = i; - } - else - { - if (first_i >= 0) - { - if (i > last_i + 1) - { - g_log.information()<<'-'<<i; - first_i = -1; - } - } - else - { - g_log.information()<<','<<i; - first_i = i; - } - } - last_i = i; - } - else - { - if (!first && first_i >= 0) - { - if (last_i > first_i) - g_log.information()<<'-'<<last_i; - first_i = -1; - } - } - if (first_i >= 0 && last_i > first_i) - g_log.information()<<'-'<<last_i; - g_log.information()<<'\n'; - } - } - - //Create a workspace with only two spectra for forward and back - DataObjects::Workspace2D_sptr groupedWS = boost::dynamic_pointer_cast<DataObjects::Workspace2D> - (API::WorkspaceFactory::Instance().create(localWorkspace, ngroups, localWorkspace->dataX(0).size(), localWorkspace->blocksize())); - - //Compile the groups - for (int i = 0; i < numHists; ++i) - { - specid_t k = static_cast<specid_t>(groups[ m_groupings[numHists*period + i] ]); - - for (detid_t j = 0; j < static_cast<detid_t>(localWorkspace->blocksize()); ++j) - { - groupedWS->dataY(k)[j] = groupedWS->dataY(k)[j] + localWorkspace->dataY(i)[j]; - - //Add the errors in quadrature - groupedWS->dataE(k)[j] - = sqrt(pow(groupedWS->dataE(k)[j], 2) + pow(localWorkspace->dataE(i)[j], 2)); - } - - //Copy all the X data - groupedWS->dataX(k) = localWorkspace->dataX(i); - ISpectrum * spec = groupedWS->getSpectrum(k); - spec->setSpectrumNo(k+1); - spec->setDetectorID(i+1); - } - - m_groupings.clear(); - - // All two spectra - for(detid_t k=0; k<static_cast<detid_t>(ngroups); k++) - { - groupedWS->getAxis(1)->setValue(k, k + 1); - } - - // Assign the result to the output workspace property - if(m_numberOfPeriods>1) - setProperty(outws, boost::dynamic_pointer_cast<Workspace>(groupedWS)); - else - { - setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(groupedWS)); - - } + Algorithm_sptr groupDet = createChildAlgorithm("MuonGroupDetectors"); + groupDet->setProperty("InputWorkspace", localWorkspace); + groupDet->setProperty("DetectorGroupingTable", groupingTable); + groupDet->execute(); + MatrixWorkspace_sptr groupedWs = groupDet->getProperty("OutputWorkspace"); + + outWs = groupedWs; } else { - // Assign the result to the output workspace property - if(m_numberOfPeriods>1) - setProperty(outws,boost::dynamic_pointer_cast<Workspace>(localWorkspace)); - else - { - setProperty("OutputWorkspace",boost::dynamic_pointer_cast<Workspace>(localWorkspace)); - } - + outWs = localWorkspace; } + if ( m_numberOfPeriods == 1 ) + setProperty("OutputWorkspace", outWs); + else + // In case of multiple periods, just add workspace to the group, and we will return the + // group later + wsGrpSptr->addWorkspace(outWs); + } // loop over periods + if(m_numberOfPeriods>1) + { + setProperty("OutputWorkspace", boost::dynamic_pointer_cast<Workspace>(wsGrpSptr)); + } + // Clean up delete[] timeChannels; } @@ -530,11 +419,8 @@ namespace Mantid * Loads detector grouping. * @param root :: Root entry of the Nexus file to read from */ - void LoadMuonNexus1::loadDetectorGrouping(NXRoot& root) + Workspace_sptr LoadMuonNexus1::loadDetectorGrouping(NXRoot& root) { - if ( getPropertyValue("DetectorGroupingTable").empty() ) - return; - NXEntry dataEntry = root.openEntry("run/histogram_data_1"); NXInfo infoGrouping = dataEntry.getDataSetInfo("grouping"); @@ -562,7 +448,7 @@ namespace Mantid TableWorkspace_sptr table = createDetectorGroupingTable( grouping.begin(), grouping.end() ); if ( table->rowCount() != 0 ) - setProperty("DetectorGroupingTable", table); + return table; } else { @@ -589,10 +475,12 @@ namespace Mantid if ( tableGroup->size() != static_cast<size_t>(m_numberOfPeriods) ) throw Exception::FileError("Zero grouping for some of the periods", m_filename); - setProperty("DetectorGroupingTable", tableGroup); + return tableGroup; } } } + + return Workspace_sptr(); } /** diff --git a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h index 175529d06ef4129b22182edce7be2dd22a80dc70..f796c0d1b020b001bc9224b530e2c1491bb4a523 100644 --- a/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h +++ b/Code/Mantid/Framework/DataHandling/test/LoadMuonNexus1Test.h @@ -86,30 +86,9 @@ public: TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); TS_ASSERT( ! output-> isDistribution() ); - /* - other tests from LoadRawTest - These test data not in current Nexus files - //---------------------------------------------------------------------- - // Tests taken from LoadInstrumentTest to check Child Algorithm is running properly - //---------------------------------------------------------------------- - boost::shared_ptr<Instrument> i = output->getInstrument(); - Mantid::Geometry::Component* source = i->getSource(); - - TS_ASSERT_EQUALS( source->getName(), "undulator"); - TS_ASSERT_DELTA( source->getPos().Y(), 0.0,0.01); - - Mantid::Geometry::Component* samplepos = i->getSample(); - TS_ASSERT_EQUALS( samplepos->getName(), "nickel-holder"); - TS_ASSERT_DELTA( samplepos->getPos().Y(), 10.0,0.01); - - Mantid::Geometry::Detector *ptrDet103 = dynamic_cast<Mantid::Geometry::Detector*>(i->getDetector(103)); - TS_ASSERT_EQUALS( ptrDet103->getID(), 103); - TS_ASSERT_EQUALS( ptrDet103->getName(), "pixel"); - TS_ASSERT_DELTA( ptrDet103->getPos().X(), 0.4013,0.01); - TS_ASSERT_DELTA( ptrDet103->getPos().Z(), 2.4470,0.01); - */ //---------------------------------------------------------------------- // Test code copied from LoadLogTest to check Child Algorithm is running properly //---------------------------------------------------------------------- - //boost::shared_ptr<Sample> sample = output->getSample(); Property *l_property = output->run().getLogData( std::string("beamlog_current") ); TimeSeriesProperty<double> *l_timeSeriesDouble = dynamic_cast<TimeSeriesProperty<double>*>(l_property); std::string timeSeriesString = l_timeSeriesDouble->value(); @@ -117,54 +96,7 @@ public: //check that sample name has been set correctly TS_ASSERT_EQUALS(output->sample().getName(), "Cr2.7Co0.3Si"); - /* - //---------------------------------------------------------------------- - // Tests to check that spectra-detector mapping is done correctly - //---------------------------------------------------------------------- - map= output->getSpectraMap(); - - // Check the total number of elements in the map for HET - TS_ASSERT_EQUALS(map->nElements(),24964); - - // Test one to one mapping, for example spectra 6 has only 1 pixel - TS_ASSERT_EQUALS(map->ndet(6),1); - - // Test one to many mapping, for example 10 pixels contribute to spectra 2084 - TS_ASSERT_EQUALS(map->ndet(2084),10); - // Check the id number of all pixels contributing - std::vector<Mantid::Geometry::IDetector*> detectorgroup; - detectorgroup=map->getDetectors(2084); - std::vector<Mantid::Geometry::IDetector*>::iterator it; - int pixnum=101191; - for (it=detectorgroup.begin();it!=detectorgroup.end();it++) - TS_ASSERT_EQUALS((*it)->getID(),pixnum++); - - // Test with spectra that does not exist - // Test that number of pixel=0 - TS_ASSERT_EQUALS(map->ndet(5),0); - // Test that trying to get the Detector throws. - boost::shared_ptr<Mantid::Geometry::IDetector> test; - TS_ASSERT_THROWS(test=map->getDetector(5),std::runtime_error); - */ - } -// void testWithManagedWorkspace() -// { -// ConfigService::Instance().updateConfig("UseManagedWS.properties"); -// //LoadRaw loader4; -// //loader4.initialize(); -// //loader4.setPropertyValue("Filename", inputFile); -// //loader4.setPropertyValue("OutputWorkspace", "managedws"); -// // TS_ASSERT_THROWS_NOTHING( loader4.execute() ) -// //TS_ASSERT( loader4.isExecuted() ) -// -// // Get back workspace and check it really is a ManagedWorkspace2D -// MatrixWorkspace_sptr output; -// TS_ASSERT_THROWS_NOTHING( output = AnalysisDataService::Instance().retrieve("managedws") ); -// TS_ASSERT( dynamic_cast<ManagedWorkspace2D*>(output.get()) ) -// } - - void testTransvereDataset() { @@ -237,11 +169,7 @@ public: TS_ASSERT_EQUALS( output->getAxis(0)->unit()->unitID(), "Label" ); TS_ASSERT( ! output-> isDistribution() ); - //check that sample name has been set correctly - //boost::shared_ptr<Sample> sample,sample2; - //sample = output->getSample(); - //sample2 = output2->getSample(); - //TS_ASSERT_EQUALS(sample->getName(), sample2->getName()); + //check that sample name has been set correctly TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); } @@ -277,12 +205,8 @@ public: TS_ASSERT( ! output-> isDistribution() ); //check that sample name has been set correctly - // boost::shared_ptr<Sample> sample,sample2; - //sample = output->getSample(); - // sample2 = output2->getSample(); TS_ASSERT_EQUALS(output->sample().getName(), output2->sample().getName()); TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); - } } void testExec2withZeroEntryNumber() @@ -313,8 +237,6 @@ public: //if no entry number load the group workspace if(entryNumber==0) { - //TS_ASSERT_THROWS_NOTHING(outGrp = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(outputSpace)); - (output = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_1")); (output2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_2")); (output3 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outputSpace+"_3")); @@ -340,9 +262,6 @@ public: TS_ASSERT( ! output-> isDistribution() ); //check that sample name has been set correctly - //boost::shared_ptr<Sample> sample,sample2; - // sample = output->getSample(); - // sample2 = output2->getSample(); TS_ASSERT_EQUALS(output->sample().getName(), output2->sample().getName()); TS_ASSERT_EQUALS(output->sample().getName(), "ptfe test"); @@ -622,6 +541,106 @@ public: AnalysisDataService::Instance().deepRemoveGroup(detectorGroupingWSName); } + void test_autoGroup_singlePeriod() + { + ScopedWorkspace outWsEntry; + + try + { + LoadMuonNexus1 alg; + alg.initialize(); + alg.setRethrows(true); + alg.setPropertyValue("Filename", "emu00006473.nxs"); + alg.setProperty("AutoGroup", true); + alg.setPropertyValue("OutputWorkspace", outWsEntry.name()); + alg.execute(); + } + catch(std::exception& e) + { + TS_FAIL(e.what()); + return; + } + + auto outWs = boost::dynamic_pointer_cast<MatrixWorkspace>( outWsEntry.retrieve() ); + TS_ASSERT(outWs); + + if ( ! outWs ) + return; // Nothing to check + + TS_ASSERT_EQUALS( outWs->getNumberHistograms(), 2); + TS_ASSERT_EQUALS( outWs->blocksize(), 2000); + + TS_ASSERT_EQUALS( outWs->readY(0)[0], 461 ); + TS_ASSERT_EQUALS( outWs->readY(0)[1000], 192 ); + TS_ASSERT_EQUALS( outWs->readY(0)[1998], 1 ); + + TS_ASSERT_EQUALS( outWs->readY(1)[0], 252 ); + TS_ASSERT_EQUALS( outWs->readY(1)[1000], 87 ); + TS_ASSERT_EQUALS( outWs->readY(1)[1998], 2 ); + } + + void test_autoGroup_multiPeriod() + { + ScopedWorkspace outWsEntry; + + try + { + LoadMuonNexus1 alg; + alg.initialize(); + alg.setRethrows(true); + alg.setPropertyValue("Filename", "MUSR00015189.nxs"); + alg.setProperty("AutoGroup", true); + alg.setPropertyValue("OutputWorkspace", outWsEntry.name()); + alg.execute(); + } + catch(std::exception& e) + { + TS_FAIL(e.what()); + return; + } + + auto outWs = boost::dynamic_pointer_cast<WorkspaceGroup>( outWsEntry.retrieve() ); + TS_ASSERT(outWs); + + if ( ! outWs ) + return; // Nothing to check + + TS_ASSERT_EQUALS( outWs->size(), 2 ); + + auto outWs1 = boost::dynamic_pointer_cast<MatrixWorkspace>( outWs->getItem(0) ); + TS_ASSERT(outWs1); + + if (outWs1) + { + TS_ASSERT_EQUALS( outWs1->getNumberHistograms(), 2); + TS_ASSERT_EQUALS( outWs1->blocksize(), 2000); + + TS_ASSERT_EQUALS( outWs1->readY(0)[0], 82 ); + TS_ASSERT_EQUALS( outWs1->readY(0)[458], 115 ); + TS_ASSERT_EQUALS( outWs1->readY(0)[1997], 1 ); + + TS_ASSERT_EQUALS( outWs1->readY(1)[0], 6 ); + TS_ASSERT_EQUALS( outWs1->readY(1)[458], 91 ); + TS_ASSERT_EQUALS( outWs1->readY(1)[1997], 0 ); + } + + auto outWs2 = boost::dynamic_pointer_cast<MatrixWorkspace>( outWs->getItem(1) ); + TS_ASSERT(outWs2); + + if (outWs2) { + TS_ASSERT_EQUALS( outWs2->getNumberHistograms(), 2); + TS_ASSERT_EQUALS( outWs2->blocksize(), 2000); + + TS_ASSERT_EQUALS( outWs2->readY(0)[0], 16 ); + TS_ASSERT_EQUALS( outWs2->readY(0)[458], 132 ); + TS_ASSERT_EQUALS( outWs2->readY(0)[1930], 0 ); + + TS_ASSERT_EQUALS( outWs2->readY(1)[0], 17 ); + TS_ASSERT_EQUALS( outWs2->readY(1)[458], 81 ); + TS_ASSERT_EQUALS( outWs2->readY(1)[1930], 1 ); + } + } + void test_loadRunInformation() { ScopedWorkspace outWsEntry; @@ -664,6 +683,14 @@ public: checkProperty(run, "sample_magn_field", 5.0); } + +private: + LoadMuonNexus1 nxLoad,nxload2,nxload3; + std::string outputSpace; + std::string entryName; + std::string inputFile; + std::string inputFile2; + template<typename T> void checkProperty(const Run& run, const std::string& property, const T& expectedValue) { @@ -688,13 +715,6 @@ public: TS_FAIL("No property: " + property); } } - -private: - LoadMuonNexus1 nxLoad,nxload2,nxload3; - std::string outputSpace; - std::string entryName; - std::string inputFile; - std::string inputFile2; }; //------------------------------------------------------------------------------