/** * @brief CompareWorkspaces::processGroups * @param groupOne * @param groupTwo */ void CompareWorkspaces::processGroups( boost::shared_ptr<const API::WorkspaceGroup> groupOne, boost::shared_ptr<const API::WorkspaceGroup> groupTwo) { // Check their sizes const size_t totalNum = static_cast<size_t>(groupOne->getNumberOfEntries()); if (groupOne->getNumberOfEntries() != groupTwo->getNumberOfEntries()) { recordMismatch("GroupWorkspaces size mismatch."); return; } // See if there are any other properties that require setting const std::vector<Property *> &allProps = this->getProperties(); std::vector<Property *> nonDefaultProps; nonDefaultProps.reserve(allProps.size()); for (auto p : allProps) { const std::string &propName = p->name(); // Skip those not set and the input workspaces if (p->isDefault() || propName == "Workspace1" || propName == "Workspace2") continue; nonDefaultProps.push_back(p); } const size_t numNonDefault = nonDefaultProps.size(); const double progressFraction = 1.0 / static_cast<double>(totalNum); std::vector<std::string> namesOne = groupOne->getNames(); std::vector<std::string> namesTwo = groupTwo->getNames(); for (size_t i = 0; i < totalNum; ++i) { // We should use an algorithm for each so that the output properties are // reset properly Algorithm_sptr checker = this->createChildAlgorithm( this->name(), progressFraction * static_cast<double>(i), progressFraction * static_cast<double>(i + 1), false, this->version()); checker->setPropertyValue("Workspace1", namesOne[i]); checker->setPropertyValue("Workspace2", namesTwo[i]); for (size_t j = 0; j < numNonDefault; ++j) { Property *p = nonDefaultProps[j]; checker->setPropertyValue(p->name(), p->value()); } checker->execute(); bool success = checker->getProperty("Result"); if (!success) { ITableWorkspace_sptr table = checker->getProperty("Messages"); recordMismatch(table->cell<std::string>(0, 0), namesOne[i], namesTwo[i]); } } }
/** * Process two groups and ensure the Result string is set properly on the final * algorithm. * * @return A boolean true if execution was sucessful, false otherwise */ bool CompareWorkspaces::processGroups() { m_Result = true; m_Messages->setRowCount(0); // Clear table // Get workspaces Workspace_const_sptr w1 = getProperty("Workspace1"); Workspace_const_sptr w2 = getProperty("Workspace2"); // Attempt to cast to WorkspaceGroups (will be nullptr on failure) WorkspaceGroup_const_sptr ws1 = boost::dynamic_pointer_cast<const WorkspaceGroup>(w1); WorkspaceGroup_const_sptr ws2 = boost::dynamic_pointer_cast<const WorkspaceGroup>(w2); if (ws1 && ws2) { // Both are groups processGroups(ws1, ws2); } else if (!ws1 && !ws2) { // Neither are groups (shouldn't happen) m_Result = false; throw std::runtime_error("CompareWorkspaces::processGroups - Neither " "input is a WorkspaceGroup. This is a logical " "error in the code."); } else if (!ws1 || !ws2) { recordMismatch( "Type mismatch. One workspace is a group, the other is not."); } if (m_Result && ws1 && ws2) { g_log.notice() << "All workspaces in workspace groups \"" << ws1->name() << "\" and \"" << ws2->name() << "\" matched!" << std::endl; } setProperty("Result", m_Result); setProperty("Messages", m_Messages); // Store output workspace in AnalysisDataService if (!isChild()) this->store(); setExecuted(true); notificationCenter().postNotification( new FinishedNotification(this, this->isExecuted())); return true; }
/** * Process two groups and ensure the Result string is set properly on the final * algorithm. * * @return A boolean true if execution was sucessful, false otherwise */ bool CompareWorkspaces::processGroups() { m_result = true; m_messages->setRowCount(0); // Clear table // Get workspaces Workspace_const_sptr w1 = getProperty("Workspace1"); Workspace_const_sptr w2 = getProperty("Workspace2"); // Attempt to cast to WorkspaceGroups (will be nullptr on failure) WorkspaceGroup_const_sptr ws1 = boost::dynamic_pointer_cast<const WorkspaceGroup>(w1); WorkspaceGroup_const_sptr ws2 = boost::dynamic_pointer_cast<const WorkspaceGroup>(w2); if (ws1 && ws2) { // Both are groups processGroups(ws1, ws2); } else if (!ws1 && !ws2) { // Neither are groups (shouldn't happen) m_result = false; throw std::runtime_error("CompareWorkspaces::processGroups - Neither " "input is a WorkspaceGroup. This is a logical " "error in the code."); } else if (!ws1 || !ws2) { recordMismatch( "Type mismatch. One workspace is a group, the other is not."); } if (m_result && ws1 && ws2) { g_log.notice() << "All workspaces in workspace groups \"" << ws1->getName() << "\" and \"" << ws2->getName() << "\" matched!\n"; } setProperty("Result", m_result); setProperty("Messages", m_messages); return true; }
/** Check whether 2 event lists are identical */ bool CompareWorkspaces::compareEventWorkspaces( DataObjects::EventWorkspace_const_sptr ews1, DataObjects::EventWorkspace_const_sptr ews2) { bool checkallspectra = getProperty("CheckAllData"); int numspec2print = getProperty("NumberMismatchedSpectraToPrint"); int wsindex2print = getProperty("DetailedPrintIndex"); // Compare number of spectra if (ews1->getNumberHistograms() != ews2->getNumberHistograms()) { recordMismatch("Mismatched number of histograms."); return false; } if (ews1->getEventType() != ews2->getEventType()) { recordMismatch("Mismatched type of events in the EventWorkspaces."); return false; } // Both will end up sorted anyway ews1->sortAll(PULSETIMETOF_SORT, m_Prog); ews2->sortAll(PULSETIMETOF_SORT, m_Prog); // Determine the tolerance for "tof" attribute and "weight" of events double toleranceWeight = Tolerance; // Standard tolerance int64_t tolerancePulse = 1; double toleranceTOF = 0.05; if ((ews1->getAxis(0)->unit()->label().ascii() != "microsecond") || (ews2->getAxis(0)->unit()->label().ascii() != "microsecond")) { g_log.warning() << "Event workspace has unit as " << ews1->getAxis(0)->unit()->label().ascii() << " and " << ews2->getAxis(0)->unit()->label().ascii() << ". Tolerance of TOF is set to 0.05 still. " << "\n"; toleranceTOF = 0.05; } g_log.notice() << "TOF Tolerance = " << toleranceTOF << "\n"; bool mismatchedEvent = false; int mismatchedEventWI = 0; size_t numUnequalNumEventsSpectra = 0; size_t numUnequalEvents = 0; size_t numUnequalTOFEvents = 0; size_t numUnequalPulseEvents = 0; size_t numUnequalBothEvents = 0; std::vector<int> vec_mismatchedwsindex; PARALLEL_FOR_IF(m_ParallelComparison && ews1->threadSafe() && ews2->threadSafe()) for (int i = 0; i < static_cast<int>(ews1->getNumberHistograms()); ++i) { PARALLEL_START_INTERUPT_REGION m_Prog->report("EventLists"); if (!mismatchedEvent || checkallspectra) // This guard will avoid checking unnecessarily { const EventList &el1 = ews1->getEventList(i); const EventList &el2 = ews2->getEventList(i); bool printdetail = (i == wsindex2print); if (printdetail) { g_log.information() << "Spectrum " << i << " is set to print out in details. " << "\n"; } if (!el1.equals(el2, toleranceTOF, toleranceWeight, tolerancePulse)) { size_t tempNumTof = 0; size_t tempNumPulses = 0; size_t tempNumBoth = 0; int tempNumUnequal = 0; if (el1.getNumberEvents() != el2.getNumberEvents()) { // Number of events are different tempNumUnequal = -1; } else { tempNumUnequal = compareEventsListInDetails( el1, el2, toleranceTOF, toleranceWeight, tolerancePulse, printdetail, tempNumPulses, tempNumTof, tempNumBoth); } mismatchedEvent = true; mismatchedEventWI = i; PARALLEL_CRITICAL(CompareWorkspaces) { if (tempNumUnequal == -1) { // 2 spectra have different number of events ++numUnequalNumEventsSpectra; } else { // 2 spectra have some events different to each other numUnequalEvents += static_cast<size_t>(tempNumUnequal); numUnequalTOFEvents += tempNumTof; numUnequalPulseEvents += tempNumPulses; numUnequalBothEvents += tempNumBoth; } vec_mismatchedwsindex.push_back(i); } // Parallel critical region } // If elist 1 is not equal to elist 2 } PARALLEL_END_INTERUPT_REGION }
/** * @brief CompareWorkspaces::doComparison */ void CompareWorkspaces::doComparison() { Workspace_sptr w1 = getProperty("Workspace1"); Workspace_sptr w2 = getProperty("Workspace2"); // ============================================================================== // Peaks workspaces // ============================================================================== // Check that both workspaces are the same type IPeaksWorkspace_sptr pws1 = boost::dynamic_pointer_cast<IPeaksWorkspace>(w1); IPeaksWorkspace_sptr pws2 = boost::dynamic_pointer_cast<IPeaksWorkspace>(w2); if ((pws1 && !pws2) || (!pws1 && pws2)) { recordMismatch("One workspace is a PeaksWorkspace and the other is not."); return; } // Check some peak-based stuff if (pws1 && pws2) { doPeaksComparison(pws1, pws2); return; } // ============================================================================== // Table workspaces // ============================================================================== // Check that both workspaces are the same type auto tws1 = boost::dynamic_pointer_cast<const ITableWorkspace>(w1); auto tws2 = boost::dynamic_pointer_cast<const ITableWorkspace>(w2); if ((tws1 && !tws2) || (!tws1 && tws2)) { recordMismatch("One workspace is a TableWorkspace and the other is not."); return; } if (tws1 && tws2) { doTableComparison(tws1, tws2); return; } // ============================================================================== // MD workspaces // ============================================================================== // Check things for IMDEventWorkspaces IMDEventWorkspace_const_sptr mdews1 = boost::dynamic_pointer_cast<const IMDEventWorkspace>(w1); IMDEventWorkspace_const_sptr mdews2 = boost::dynamic_pointer_cast<const IMDEventWorkspace>(w2); if ((mdews1 && !mdews2) || (!mdews1 && mdews2)) { recordMismatch( "One workspace is an IMDEventWorkspace and the other is not."); return; } // Check things for IMDHistoWorkspaces IMDHistoWorkspace_const_sptr mdhws1 = boost::dynamic_pointer_cast<const IMDHistoWorkspace>(w1); IMDHistoWorkspace_const_sptr mdhws2 = boost::dynamic_pointer_cast<const IMDHistoWorkspace>(w2); if ((mdhws1 && !mdhws2) || (!mdhws1 && mdhws2)) { recordMismatch( "One workspace is an IMDHistoWorkspace and the other is not."); return; } if (mdhws1 || mdews1) // The '2' workspaces must match because of the checks above { this->doMDComparison(w1, w2); return; } // ============================================================================== // Event workspaces // ============================================================================== // These casts must succeed or there's a logical problem in the code MatrixWorkspace_const_sptr ws1 = boost::dynamic_pointer_cast<const MatrixWorkspace>(w1); MatrixWorkspace_const_sptr ws2 = boost::dynamic_pointer_cast<const MatrixWorkspace>(w2); EventWorkspace_const_sptr ews1 = boost::dynamic_pointer_cast<const EventWorkspace>(ws1); EventWorkspace_const_sptr ews2 = boost::dynamic_pointer_cast<const EventWorkspace>(ws2); if (getProperty("CheckType")) { if ((ews1 && !ews2) || (!ews1 && ews2)) { recordMismatch( "One workspace is an EventWorkspace and the other is not."); return; } } size_t numhist = ws1->getNumberHistograms(); if (ews1 && ews2) { m_Prog = new Progress(this, 0.0, 1.0, numhist * 5); // Compare event lists to see whether 2 event workspaces match each other if (!compareEventWorkspaces(ews1, ews2)) return; } else { // Fewer steps if not events m_Prog = new Progress(this, 0.0, 1.0, numhist * 2); } // ============================================================================== // Matrix workspaces (Event & 2D) // ============================================================================== // First check the data - always do this if (!checkData(ws1, ws2)) return; // Now do the other ones if requested. Bail out as soon as we see a failure. m_Prog->reportIncrement(numhist / 5, "Axes"); if (static_cast<bool>(getProperty("CheckAxes")) && !checkAxes(ws1, ws2)) return; m_Prog->reportIncrement(numhist / 5, "SpectraMap"); if (static_cast<bool>(getProperty("CheckSpectraMap")) && !checkSpectraMap(ws1, ws2)) return; m_Prog->reportIncrement(numhist / 5, "Instrument"); if (static_cast<bool>(getProperty("CheckInstrument")) && !checkInstrument(ws1, ws2)) return; m_Prog->reportIncrement(numhist / 5, "Masking"); if (static_cast<bool>(getProperty("CheckMasking")) && !checkMasking(ws1, ws2)) return; m_Prog->reportIncrement(numhist / 5, "Sample"); if (static_cast<bool>(getProperty("CheckSample"))) { if (!checkSample(ws1->sample(), ws2->sample())) return; if (!checkRunProperties(ws1->run(), ws2->run())) return; } }