/** * Apply the created mapping to the workspace */ void CreateSimulationWorkspace::applyDetectorMapping() { size_t wsIndex(0); for (auto iter = m_detGroups.begin(); iter != m_detGroups.end(); ++iter) { ISpectrum *spectrum = m_outputWS->getSpectrum(wsIndex); spectrum->setSpectrumNo( static_cast<specid_t>(wsIndex + 1)); // Ensure a contiguous mapping spectrum->clearDetectorIDs(); spectrum->addDetectorIDs(iter->second); ++wsIndex; } }
/** * Only to be used if the KeepUnGrouped property is true, moves the spectra that were not selected * to be in a group to the end of the output spectrum * @param unGroupedSet :: list of WORKSPACE indexes that were included in a group * @param inputWS :: user selected input workspace for the algorithm * @param outputWS :: user selected output workspace for the algorithm * @param outIndex :: the next spectra index available after the grouped spectra */ void GroupDetectors2::moveOthers(const std::set<int64_t> &unGroupedSet, API::MatrixWorkspace_const_sptr inputWS, API::MatrixWorkspace_sptr outputWS, size_t outIndex) { g_log.debug() << "Starting to copy the ungrouped spectra" << std::endl; double prog4Copy = (1. - 1.*static_cast<double>(m_FracCompl))/static_cast<double>(unGroupedSet.size()); std::set<int64_t>::const_iterator copyFrIt = unGroupedSet.begin(); // go thorugh all the spectra in the input workspace for ( ; copyFrIt != unGroupedSet.end(); ++copyFrIt ) { if( *copyFrIt == USED ) continue; //Marked as not to be used size_t sourceIndex = static_cast<size_t>(*copyFrIt); // The input spectrum we'll copy const ISpectrum * inputSpec = inputWS->getSpectrum(sourceIndex); // Destination of the copying ISpectrum * outputSpec = outputWS->getSpectrum(outIndex); // Copy the data outputSpec->dataX() = inputSpec->dataX(); outputSpec->dataY() = inputSpec->dataY(); outputSpec->dataE() = inputSpec->dataE(); // Spectrum numbers etc. outputSpec->setSpectrumNo(inputSpec->getSpectrumNo()); outputSpec->clearDetectorIDs(); outputSpec->addDetectorIDs( inputSpec->getDetectorIDs() ); // go to the next free index in the output workspace outIndex ++; // make regular progress reports and check for cancelling the algorithm if ( outIndex % INTERVAL == 0 ) { m_FracCompl += INTERVAL*prog4Copy; if ( m_FracCompl > 1.0 ) { m_FracCompl = 1.0; } progress(m_FracCompl); interruption_point(); } } // Refresh the spectraDetectorMap outputWS->generateSpectraMap(); g_log.debug() << name() << " copied " << unGroupedSet.size()-1 << " ungrouped spectra\n"; }
/** * Move the user selected spectra in the input workspace into groups in the output workspace * @param inputWS :: user selected input workspace for the algorithm * @param outputWS :: user selected output workspace for the algorithm * @param prog4Copy :: the amount of algorithm progress to attribute to moving a single spectra * @return number of new grouped spectra */ size_t GroupDetectors2::formGroups( API::MatrixWorkspace_const_sptr inputWS, API::MatrixWorkspace_sptr outputWS, const double prog4Copy) { // get "Behaviour" string const std::string behaviour = getProperty("Behaviour"); int bhv = 0; if ( behaviour == "Average" ) bhv = 1; API::MatrixWorkspace_sptr beh = API::WorkspaceFactory::Instance().create( "Workspace2D", static_cast<int>(m_GroupSpecInds.size()), 1, 1); g_log.debug() << name() << ": Preparing to group spectra into " << m_GroupSpecInds.size() << " groups\n"; // where we are copying spectra to, we start copying to the start of the output workspace size_t outIndex = 0; // Only used for averaging behaviour. We may have a 1:1 map where a Divide would be waste as it would be just dividing by 1 bool requireDivide(false); for ( storage_map::const_iterator it = m_GroupSpecInds.begin(); it != m_GroupSpecInds.end() ; ++it ) { // This is the grouped spectrum ISpectrum * outSpec = outputWS->getSpectrum(outIndex); // The spectrum number of the group is the key outSpec->setSpectrumNo(it->first); // Start fresh with no detector IDs outSpec->clearDetectorIDs(); // Copy over X data from first spectrum, the bin boundaries for all spectra are assumed to be the same here outSpec->dataX() = inputWS->readX(0); // the Y values and errors from spectra being grouped are combined in the output spectrum // Keep track of number of detectors required for masking size_t nonMaskedSpectra(0); beh->dataX(outIndex)[0] = 0.0; beh->dataE(outIndex)[0] = 0.0; for( std::vector<size_t>::const_iterator wsIter = it->second.begin(); wsIter != it->second.end(); ++wsIter) { const size_t originalWI = *wsIter; // detectors to add to firstSpecNum const ISpectrum * fromSpectrum = inputWS->getSpectrum(originalWI); // Add up all the Y spectra and store the result in the first one // Need to keep the next 3 lines inside loop for now until ManagedWorkspace mru-list works properly MantidVec &firstY = outSpec->dataY(); MantidVec::iterator fYit; MantidVec::iterator fEit = outSpec->dataE().begin(); MantidVec::const_iterator Yit = fromSpectrum->dataY().begin(); MantidVec::const_iterator Eit = fromSpectrum->dataE().begin(); for (fYit = firstY.begin(); fYit != firstY.end(); ++fYit, ++fEit, ++Yit, ++Eit) { *fYit += *Yit; // Assume 'normal' (i.e. Gaussian) combination of errors *fEit = std::sqrt( (*fEit)*(*fEit) + (*Eit)*(*Eit) ); } // detectors to add to the output spectrum outSpec->addDetectorIDs(fromSpectrum->getDetectorIDs() ); try { Geometry::IDetector_const_sptr det = inputWS->getDetector(originalWI); if( !det->isMasked() ) ++nonMaskedSpectra; } catch(Exception::NotFoundError&) { // If a detector cannot be found, it cannot be masked ++nonMaskedSpectra; } } if( nonMaskedSpectra == 0 ) ++nonMaskedSpectra; // Avoid possible divide by zero if(!requireDivide) requireDivide = (nonMaskedSpectra > 1); beh->dataY(outIndex)[0] = static_cast<double>(nonMaskedSpectra); // make regular progress reports and check for cancelling the algorithm if ( outIndex % INTERVAL == 0 ) { m_FracCompl += INTERVAL*prog4Copy; if ( m_FracCompl > 1.0 ) m_FracCompl = 1.0; progress(m_FracCompl); interruption_point(); } outIndex ++; } // Refresh the spectraDetectorMap outputWS->generateSpectraMap(); if ( bhv == 1 && requireDivide ) { g_log.debug() << "Running Divide algorithm to perform averaging.\n"; Mantid::API::IAlgorithm_sptr divide = createChildAlgorithm("Divide"); divide->initialize(); divide->setProperty<API::MatrixWorkspace_sptr>("LHSWorkspace", outputWS); divide->setProperty<API::MatrixWorkspace_sptr>("RHSWorkspace", beh); divide->setProperty<API::MatrixWorkspace_sptr>("OutputWorkspace", outputWS); divide->execute(); } g_log.debug() << name() << " created " << outIndex << " new grouped spectra\n"; return outIndex; }
/** Load a single bank into the workspace * * @param nexusfilename :: file to open * @param entry_name :: NXentry name * @param bankName :: NXdata bank name * @param WS :: workspace to modify * @param id_to_wi :: det ID to workspace index mapping */ void LoadTOFRawNexus::loadBank(const std::string &nexusfilename, const std::string &entry_name, const std::string &bankName, API::MatrixWorkspace_sptr WS, const detid2index_map &id_to_wi) { g_log.debug() << "Loading bank " << bankName << std::endl; // To avoid segfaults on RHEL5/6 and Fedora m_fileMutex.lock(); // Navigate to the point in the file auto file = new ::NeXus::File(nexusfilename); file->openGroup(entry_name, "NXentry"); file->openGroup("instrument", "NXinstrument"); file->openGroup(bankName, "NXdetector"); size_t m_numPixels = 0; std::vector<uint32_t> pixel_id; if (!m_assumeOldFile) { // Load the pixel IDs file->readData("pixel_id", pixel_id); m_numPixels = pixel_id.size(); if (m_numPixels == 0) { file->close(); m_fileMutex.unlock(); g_log.warning() << "Invalid pixel_id data in " << bankName << std::endl; return; } } else { // Load the x and y pixel offsets std::vector<float> xoffsets; std::vector<float> yoffsets; file->readData("x_pixel_offset", xoffsets); file->readData("y_pixel_offset", yoffsets); m_numPixels = xoffsets.size() * yoffsets.size(); if (0 == m_numPixels) { file->close(); m_fileMutex.unlock(); g_log.warning() << "Invalid (x,y) offsets in " << bankName << std::endl; return; } size_t bankNum = 0; if (bankName.size() > 4) { if (bankName.substr(0, 4) == "bank") { bankNum = boost::lexical_cast<size_t>(bankName.substr(4)); bankNum--; } else { file->close(); m_fileMutex.unlock(); g_log.warning() << "Invalid bank number for " << bankName << std::endl; return; } } // All good, so construct the pixel ID listing size_t numX = xoffsets.size(); size_t numY = yoffsets.size(); for (size_t i = 0; i < numX; i++) { for (size_t j = 0; j < numY; j++) { pixel_id.push_back( static_cast<uint32_t>(j + numY * (i + numX * bankNum))); } } } size_t iPart = 0; if (m_spec_max != Mantid::EMPTY_INT()) { uint32_t ifirst = pixel_id[0]; range_check out_range(m_spec_min, m_spec_max, id_to_wi); auto newEnd = std::remove_if(pixel_id.begin(), pixel_id.end(), out_range); pixel_id.erase(newEnd, pixel_id.end()); // check if beginning or end of array was erased if (ifirst != pixel_id[0]) iPart = m_numPixels - pixel_id.size(); m_numPixels = pixel_id.size(); if (m_numPixels == 0) { file->close(); m_fileMutex.unlock(); g_log.warning() << "No pixels from " << bankName << std::endl; return; }; } // Load the TOF vector std::vector<float> tof; file->readData(m_axisField, tof); size_t m_numBins = tof.size() - 1; if (tof.size() <= 1) { file->close(); m_fileMutex.unlock(); g_log.warning() << "Invalid " << m_axisField << " data in " << bankName << std::endl; return; } // Make a shared pointer MantidVecPtr Xptr; MantidVec &X = Xptr.access(); X.resize(tof.size(), 0); X.assign(tof.begin(), tof.end()); // Load the data. Coerce ints into double. std::string errorsField = ""; std::vector<double> data; file->openData(m_dataField); file->getDataCoerce(data); if (file->hasAttr("errors")) file->getAttr("errors", errorsField); file->closeData(); // Load the errors bool hasErrors = !errorsField.empty(); std::vector<double> errors; if (hasErrors) { try { file->openData(errorsField); file->getDataCoerce(errors); file->closeData(); } catch (...) { g_log.information() << "Error loading the errors field, '" << errorsField << "' for bank " << bankName << ". Will use sqrt(counts). " << std::endl; hasErrors = false; } } /*if (data.size() != m_numBins * m_numPixels) { file->close(); m_fileMutex.unlock(); g_log.warning() << "Invalid size of '" << m_dataField << "' data in " << bankName << std::endl; return; } if (hasErrors && (errors.size() != m_numBins * m_numPixels)) { file->close(); m_fileMutex.unlock(); g_log.warning() << "Invalid size of '" << errorsField << "' errors in " << bankName << std::endl; return; } */ // Have all the data I need m_fileMutex.unlock(); file->close(); for (size_t i = iPart; i < iPart + m_numPixels; i++) { // Find the workspace index for this detector detid_t pixelID = pixel_id[i - iPart]; size_t wi = id_to_wi.find(pixelID)->second; // Set the basic info of that spectrum ISpectrum *spec = WS->getSpectrum(wi); spec->setSpectrumNo(specid_t(wi + 1)); spec->setDetectorID(pixel_id[i - iPart]); // Set the shared X pointer spec->setX(X); // Extract the Y MantidVec &Y = spec->dataY(); Y.assign(data.begin() + i * m_numBins, data.begin() + (i + 1) * m_numBins); MantidVec &E = spec->dataE(); if (hasErrors) { // Copy the errors from the loaded document E.assign(errors.begin() + i * m_numBins, errors.begin() + (i + 1) * m_numBins); } else { // Now take the sqrt(Y) to give E E = Y; std::transform(E.begin(), E.end(), E.begin(), (double (*)(double))sqrt); } } // Done! }
/** Executes the algorithm * */ void SumSpectra::exec() { // Try and retrieve the optional properties m_MinSpec = getProperty("StartWorkspaceIndex"); m_MaxSpec = getProperty("EndWorkspaceIndex"); const std::vector<int> indices_list = getProperty("ListOfWorkspaceIndices"); keepMonitors = getProperty("IncludeMonitors"); // Get the input workspace MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace"); numberOfSpectra = static_cast<int>(localworkspace->getNumberHistograms()); this->yLength = static_cast<int>(localworkspace->blocksize()); // Check 'StartSpectrum' is in range 0-numberOfSpectra if ( m_MinSpec > numberOfSpectra ) { g_log.warning("StartWorkspaceIndex out of range! Set to 0."); m_MinSpec = 0; } if (indices_list.empty()) { //If no list was given and no max, just do all. if ( isEmpty(m_MaxSpec) ) m_MaxSpec = numberOfSpectra-1; } //Something for m_MaxSpec was given but it is out of range? if (!isEmpty(m_MaxSpec) && ( m_MaxSpec > numberOfSpectra-1 || m_MaxSpec < m_MinSpec )) { g_log.warning("EndWorkspaceIndex out of range! Set to max Workspace Index"); m_MaxSpec = numberOfSpectra; } //Make the set of indices to sum up from the list this->indices.insert(indices_list.begin(), indices_list.end()); //And add the range too, if any if (!isEmpty(m_MaxSpec)) { for (int i = m_MinSpec; i <= m_MaxSpec; i++) this->indices.insert(i); } //determine the output spectrum id m_outSpecId = this->getOutputSpecId(localworkspace); g_log.information() << "Spectra remapping gives single spectra with spectra number: " << m_outSpecId << "\n"; m_CalculateWeightedSum = getProperty("WeightedSum"); EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(localworkspace); if (eventW) { m_CalculateWeightedSum = false; this->execEvent(eventW, this->indices); } else { //-------Workspace 2D mode ----- // Create the 2D workspace for the output MatrixWorkspace_sptr outputWorkspace = API::WorkspaceFactory::Instance().create(localworkspace, 1,localworkspace->readX(0).size(),this->yLength); size_t numSpectra(0); // total number of processed spectra size_t numMasked(0); // total number of the masked and skipped spectra size_t numZeros(0); // number of spectra which have 0 value in the first column (used in special cases of evaluating how good Puasonian statistics is) Progress progress(this, 0, 1, this->indices.size()); // This is the (only) output spectrum ISpectrum * outSpec = outputWorkspace->getSpectrum(0); // Copy over the bin boundaries outSpec->dataX() = localworkspace->readX(0); //Build a new spectra map outSpec->setSpectrumNo(m_outSpecId); outSpec->clearDetectorIDs(); if (localworkspace->id() == "RebinnedOutput") { this->doRebinnedOutput(outputWorkspace, progress,numSpectra,numMasked,numZeros); } else { this->doWorkspace2D(localworkspace, outSpec, progress,numSpectra,numMasked,numZeros); } // Pointer to sqrt function MantidVec& YError = outSpec->dataE(); typedef double (*uf)(double); uf rs=std::sqrt; //take the square root of all the accumulated squared errors - Assumes Gaussian errors std::transform(YError.begin(), YError.end(), YError.begin(), rs); outputWorkspace->generateSpectraMap(); // set up the summing statistics outputWorkspace->mutableRun().addProperty("NumAllSpectra",int(numSpectra),"",true); outputWorkspace->mutableRun().addProperty("NumMaskSpectra",int(numMasked),"",true); outputWorkspace->mutableRun().addProperty("NumZeroSpectra",int(numZeros),"",true); // Assign it to the output workspace property setProperty("OutputWorkspace", outputWorkspace); } }
void GroupDetectors::exec() { // Get the input workspace const MatrixWorkspace_sptr WS = getProperty("Workspace"); std::vector<size_t> indexList = getProperty("WorkspaceIndexList"); std::vector<specid_t> spectraList = getProperty("SpectraList"); const std::vector<detid_t> detectorList = getProperty("DetectorList"); // Could create a Validator to replace the below if ( indexList.empty() && spectraList.empty() && detectorList.empty() ) { g_log.information(name() + ": WorkspaceIndexList, SpectraList, and DetectorList properties are all empty, no grouping done"); return; } // Bin boundaries need to be the same, so check if they actually are if (!API::WorkspaceHelpers::commonBoundaries(WS)) { g_log.error("Can only group if the histograms have common bin boundaries"); throw std::runtime_error("Can only group if the histograms have common bin boundaries"); } // If the spectraList property has been set, need to loop over the workspace looking for the // appropriate spectra number and adding the indices they are linked to the list to be processed if ( ! spectraList.empty() ) { WS->getIndicesFromSpectra(spectraList,indexList); }// End dealing with spectraList else if ( ! detectorList.empty() ) { // Dealing with DetectorList //convert from detectors to workspace indices WS->getIndicesFromDetectorIDs(detectorList, indexList); } if ( indexList.empty() ) { g_log.warning("Nothing to group"); return; } const size_t vectorSize = WS->blocksize(); const specid_t firstIndex = static_cast<specid_t>(indexList[0]); ISpectrum * firstSpectrum = WS->getSpectrum(firstIndex); setProperty("ResultIndex",firstIndex); // loop over the spectra to group Progress progress(this, 0.0, 1.0, static_cast<int>(indexList.size()-1)); for (size_t i = 0; i < indexList.size()-1; ++i) { // The current spectrum const size_t currentIndex = indexList[i+1]; ISpectrum * spec = WS->getSpectrum(currentIndex); // Add the current detector to belong to the first spectrum firstSpectrum->addDetectorIDs(spec->getDetectorIDs()); // Add up all the Y spectra and store the result in the first one // Need to keep the next 3 lines inside loop for now until ManagedWorkspace mru-list works properly MantidVec &firstY = WS->dataY(firstIndex); MantidVec::iterator fYit; MantidVec::iterator fEit = firstSpectrum->dataE().begin(); MantidVec::iterator Yit = spec->dataY().begin(); MantidVec::iterator Eit = spec->dataE().begin(); for (fYit = firstY.begin(); fYit != firstY.end(); ++fYit, ++fEit, ++Yit, ++Eit) { *fYit += *Yit; // Assume 'normal' (i.e. Gaussian) combination of errors *fEit = sqrt( (*fEit)*(*fEit) + (*Eit)*(*Eit) ); } // Now zero the now redundant spectrum and set its spectraNo to indicate this (using -1) // N.B. Deleting spectra would cause issues for ManagedWorkspace2D, hence the the approach taken here spec->dataY().assign(vectorSize,0.0); spec->dataE().assign(vectorSize,0.0); spec->setSpectrumNo(-1); spec->clearDetectorIDs(); progress.report(); } }