/** * @brief IntegratePeaksCWSD::simplePeakIntegration * Purpose: * Integrate a single crystal peak with the simplest algorithm, i.e., * by adding all the signal with normalization to monitor counts * Requirements: * Valid MDEventWorkspace * Valid PeaksWorkspace * Guarantees: * A valid value is given */ void IntegratePeaksCWSD::simplePeakIntegration( const std::vector<detid_t> &vecMaskedDetID, const std::map<int, signal_t> &run_monitor_map) { // Check requirements if (!m_inputWS) throw std::runtime_error("MDEventWorkspace is not defined."); // Go through to get value auto mditer = m_inputWS->createIterator(); size_t nextindex = 1; bool scancell = true; // size_t currindex = 0; // Assuming that MDEvents are grouped by run number, there is no need to // loop up the map for peak center and monitor counts each time int current_run_number = -1; signal_t current_monitor_counts = 0; Kernel::V3D current_peak_center = m_peakCenter; // signal_t total_signal = 0; double min_distance = 10000000; double max_distance = -1; while (scancell) { // Go through all the MDEvents in one cell. size_t numeventincell = mditer->getNumEvents(); for (size_t iev = 0; iev < numeventincell; ++iev) { // Get signal to add and skip if signal is zero signal_t signal = mditer->getInnerSignal(iev); if (signal <= THRESHOLD_SIGNAL) continue; uint16_t run_number = mditer->getInnerRunIndex(iev); int run_number_i = static_cast<int>(run_number); /* debug: record raw signals if (run_number_i % 1000 == testrunnumber) { total_signal += signal; ++ num_det; } // ... debug */ // Check whether this detector is masked if (!vecMaskedDetID.empty()) { detid_t detid = mditer->getInnerDetectorID(iev); std::vector<detid_t>::const_iterator it; it = find(vecMaskedDetID.begin(), vecMaskedDetID.end(), detid); if (it != vecMaskedDetID.end()) { // The detector ID is found among masked detector IDs // Skip this event and move to next /* debug: record masked detectors if (run_number_i % 1000 == testrunnumber) { num_masked_det += 1; g_log.warning() << "Masked detector ID = " << detid << ", Signal = " << signal << "\n"; } // ... debug */ continue; } } /* debug: record unmasked detectors if (run_number_i % 1000 == testrunnumber) num_unmasked_det += 1; // ... debug */ // Check whether to update monitor counts and peak center if (current_run_number != run_number_i) { // update run number current_run_number = run_number_i; // update monitor counts if (m_normalizeByMonitor) { std::map<int, signal_t>::const_iterator m_finder = run_monitor_map.find(current_run_number); if (m_finder != run_monitor_map.end()) current_monitor_counts = m_finder->second; else { std::stringstream errss; errss << "Unable to find run number " << current_run_number << " in monitor counts map"; throw std::runtime_error(errss.str()); } } else { current_monitor_counts = 1.; } // update peak center if (!m_useSinglePeakCenterFmUser) current_peak_center = m_runPeakCenterMap[current_run_number]; } // calculate distance float tempx = mditer->getInnerPosition(iev, 0); float tempy = mditer->getInnerPosition(iev, 1); float tempz = mditer->getInnerPosition(iev, 2); Kernel::V3D pixel_pos(tempx, tempy, tempz); double distance = current_peak_center.distance(pixel_pos); /* debug: record unmasked signal if (run_number_i % 1000 == testrunnumber) { total_unmasked_signal += signal; } // ... debug */ if (distance < m_peakRadius) { // FIXME - Is it very costly to use map each time??? // total_signal += signal/current_monitor_counts; m_runPeakCountsMap[run_number] += signal / current_monitor_counts; } else { g_log.debug() << "Out of radius " << distance << " > " << m_peakRadius << ": Center = " << current_peak_center.toString() << ", Pixel = " << pixel_pos.toString() << "\n"; } if (distance < min_distance) min_distance = distance; if (distance > max_distance) max_distance = distance; } // Advance to next cell if (mditer->next()) { // advance to next cell mditer->jumpTo(nextindex); ++nextindex; } else { // break the loop scancell = false; } } // END-WHILE (scan-cell) // Summarize g_log.notice() << "Distance range is " << min_distance << ", " << max_distance << "\n"; /* g_log.warning() << "Debug output: run 13: Number masked detectors = " << num_masked_det << ", Total signal = " << total_signal << "\n"; g_log.warning() << " Number of unmasked detectors = " << num_unmasked_det << ", Total unmasked signal = " << total_unmasked_signal << "\n"; g_log.warning() << " Number of total detectors = " << num_det << "\n"; */ }
/** * Create an output event workspace filled with data simulated with the fitting * function. * @param baseName :: The base name for the workspace * @param inputWorkspace :: The input workspace. * @param values :: The calculated values * @param outputWorkspacePropertyName :: The property name */ boost::shared_ptr<API::Workspace> FitMD::createEventOutputWorkspace( const std::string &baseName, const API::IMDEventWorkspace &inputWorkspace, const API::FunctionValues &values, const std::string &outputWorkspacePropertyName) { auto outputWS = MDEventFactory::CreateMDWorkspace(inputWorkspace.getNumDims(), "MDEvent"); // Add events // TODO: Generalize to ND (the current framework is a bit limiting) auto mdWS = boost::dynamic_pointer_cast< DataObjects::MDEventWorkspace<DataObjects::MDEvent<4>, 4>>(outputWS); if (!mdWS) { return boost::shared_ptr<API::Workspace>(); } // Bins extents and meta data for (size_t i = 0; i < 4; ++i) { boost::shared_ptr<const Geometry::IMDDimension> inputDim = inputWorkspace.getDimension(i); Geometry::MDHistoDimensionBuilder builder; builder.setName(inputDim->getName()); builder.setId(inputDim->getDimensionId()); builder.setUnits(inputDim->getUnits()); builder.setNumBins(inputDim->getNBins()); builder.setMin(inputDim->getMinimum()); builder.setMax(inputDim->getMaximum()); builder.setFrameName(inputDim->getMDFrame().name()); outputWS->addDimension(builder.create()); } // Run information outputWS->copyExperimentInfos(inputWorkspace); // Coordinates outputWS->setCoordinateSystem(inputWorkspace.getSpecialCoordinateSystem()); // Set sensible defaults for splitting behaviour BoxController_sptr bc = outputWS->getBoxController(); bc->setSplitInto(3); bc->setSplitThreshold(3000); outputWS->initialize(); outputWS->splitBox(); auto inputIter = inputWorkspace.createIterator(); size_t resultValueIndex(0); const float errorSq = 0.0; do { const size_t numEvents = inputIter->getNumEvents(); const float signal = static_cast<float>(values.getCalculated(resultValueIndex)); for (size_t i = 0; i < numEvents; ++i) { coord_t centers[4] = { inputIter->getInnerPosition(i, 0), inputIter->getInnerPosition(i, 1), inputIter->getInnerPosition(i, 2), inputIter->getInnerPosition(i, 3)}; mdWS->addEvent(MDEvent<4>(signal, errorSq, inputIter->getInnerRunIndex(i), inputIter->getInnerDetectorID(i), centers)); } ++resultValueIndex; } while (inputIter->next()); delete inputIter; // This splits up all the boxes according to split thresholds and sizes. auto threadScheduler = new Kernel::ThreadSchedulerFIFO(); Kernel::ThreadPool threadPool(threadScheduler); outputWS->splitAllIfNeeded(threadScheduler); threadPool.joinAll(); outputWS->refreshCache(); // Store it if (!outputWorkspacePropertyName.empty()) { declareProperty( new API::WorkspaceProperty<API::IMDEventWorkspace>( outputWorkspacePropertyName, "", Direction::Output), "Name of the output Workspace holding resulting simulated spectrum"); m_manager->setPropertyValue(outputWorkspacePropertyName, baseName + "Workspace"); m_manager->setProperty(outputWorkspacePropertyName, outputWS); } return outputWS; }