/** Execute the algorithm. */ void TransformMD::exec() { Mantid::API::IMDWorkspace_sptr inWS; Mantid::API::IMDWorkspace_sptr outWS; inWS = getProperty("InputWorkspace"); outWS = getProperty("OutputWorkspace"); std::string outName = getPropertyValue("OutputWorkspace"); if (boost::dynamic_pointer_cast<MatrixWorkspace>(inWS)) throw std::runtime_error("TransformMD can only transform a " "MDHistoWorkspace or a MDEventWorkspace."); if (outWS != inWS) { // NOT in-place. So first we clone inWS into outWS IAlgorithm_sptr clone = this->createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true); clone->setProperty("InputWorkspace", inWS); clone->executeAsChildAlg(); outWS = clone->getProperty("OutputWorkspace"); } if (!outWS) throw std::runtime_error("Invalid output workspace."); size_t nd = outWS->getNumDims(); m_scaling = getProperty("Scaling"); m_offset = getProperty("Offset"); // Replicate single values if (m_scaling.size() == 1) m_scaling = std::vector<double>(nd, m_scaling[0]); if (m_offset.size() == 1) m_offset = std::vector<double>(nd, m_offset[0]); // Check the size if (m_scaling.size() != nd) throw std::invalid_argument("Scaling argument must be either length 1 or " "match the number of dimensions."); if (m_offset.size() != nd) throw std::invalid_argument("Offset argument must be either length 1 or " "match the number of dimensions."); // Transform the dimensions outWS->transformDimensions(m_scaling, m_offset); MDHistoWorkspace_sptr histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(outWS); IMDEventWorkspace_sptr event = boost::dynamic_pointer_cast<IMDEventWorkspace>(outWS); if (histo) { // Recalculate all the values since the dimensions changed. histo->cacheValues(); // Expect first 3 dimensions to be -1 for changing conventions for (int i = 0; i < static_cast<int>(m_scaling.size()); i++) if (m_scaling[i] < 0) { std::vector<int> axes(m_scaling.size()); // vector with ints. std::iota(std::begin(axes), std::end(axes), 0); // Fill with 0, 1, ... axes[0] = i; axes[i] = 0; if (i > 0) histo = transposeMD(histo, axes); signal_t *signals = histo->getSignalArray(); signal_t *errorsSq = histo->getErrorSquaredArray(); signal_t *numEvents = histo->getNumEventsArray(); // Find the extents size_t nPoints = static_cast<size_t>(histo->getDimension(0)->getNBins()); size_t mPoints = 1; for (size_t k = 1; k < histo->getNumDims(); k++) { mPoints *= static_cast<size_t>(histo->getDimension(k)->getNBins()); } // other dimensions for (size_t j = 0; j < mPoints; j++) { this->reverse(signals + j * nPoints, nPoints); this->reverse(errorsSq + j * nPoints, nPoints); this->reverse(numEvents + j * nPoints, nPoints); } histo = transposeMD(histo, axes); } // Pass on the display normalization from the input workspace histo->setDisplayNormalization(inWS->displayNormalizationHisto()); this->setProperty("OutputWorkspace", histo); } else if (event) { // Call the method for this type of MDEventWorkspace. CALL_MDEVENT_FUNCTION(this->doTransform, outWS); Progress *prog2 = nullptr; ThreadScheduler *ts = new ThreadSchedulerFIFO(); ThreadPool tp(ts, 0, prog2); event->splitAllIfNeeded(ts); // prog2->resetNumSteps( ts->size(), 0.4, 0.6); tp.joinAll(); event->refreshCache(); // Set the special coordinate system. IMDEventWorkspace_sptr inEvent = boost::dynamic_pointer_cast<IMDEventWorkspace>(inWS); event->setCoordinateSystem(inEvent->getSpecialCoordinateSystem()); if (m_scaling[0] < 0) { // Only need these 2 algorithms for transforming with negative number std::vector<double> extents; std::vector<std::string> names, units; for (size_t d = 0; d < nd; d++) { Geometry::IMDDimension_const_sptr dim = event->getDimension(d); // Find the extents extents.push_back(dim->getMinimum()); extents.push_back(dim->getMaximum()); names.push_back(std::string(dim->getName())); units.push_back(dim->getUnits()); } Algorithm_sptr create_alg = createChildAlgorithm("CreateMDWorkspace"); create_alg->setProperty("Dimensions", static_cast<int>(nd)); create_alg->setProperty("EventType", event->getEventTypeName()); create_alg->setProperty("Extents", extents); create_alg->setProperty("Names", names); create_alg->setProperty("Units", units); create_alg->setPropertyValue("OutputWorkspace", "__none"); create_alg->executeAsChildAlg(); Workspace_sptr none = create_alg->getProperty("OutputWorkspace"); AnalysisDataService::Instance().addOrReplace(outName, event); AnalysisDataService::Instance().addOrReplace("__none", none); Mantid::API::BoxController_sptr boxController = event->getBoxController(); std::vector<int> splits; for (size_t d = 0; d < nd; d++) { splits.push_back(static_cast<int>(boxController->getSplitInto(d))); } Algorithm_sptr merge_alg = createChildAlgorithm("MergeMD"); merge_alg->setPropertyValue("InputWorkspaces", outName + ",__none"); merge_alg->setProperty("SplitInto", splits); merge_alg->setProperty( "SplitThreshold", static_cast<int>(boxController->getSplitThreshold())); merge_alg->setProperty("MaxRecursionDepth", 13); merge_alg->executeAsChildAlg(); event = merge_alg->getProperty("OutputWorkspace"); AnalysisDataService::Instance().remove("__none"); } this->setProperty("OutputWorkspace", event); } }
/** Execute the algorithm. */ void ConvertToDetectorFaceMD::exec() { // TODO convert matrix to event as needed MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace"); in_ws = boost::dynamic_pointer_cast<EventWorkspace>(mws); if (!in_ws) throw std::runtime_error("InputWorkspace is not an EventWorkspace"); // Fill the map, throw if there are grouped pixels. m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true); // Get the map of the banks we'll display std::map<int, RectangularDetector_const_sptr> banks = this->getBanks(); // Find the size in the TOF dimension double tof_min, tof_max; Axis *ax0 = in_ws->getAxis(0); in_ws->getXMinMax(tof_min, tof_max); if (ax0->getValue(0) < tof_min) tof_min = ax0->getValue(0); if (ax0->getValue(ax0->length() - 1) > tof_max) tof_max = ax0->getValue(ax0->length() - 1); // Get MDFrame of General Frame type Mantid::Geometry::GeneralFrame framePixel( Mantid::Geometry::GeneralFrame::GeneralFrameName, "pixel"); Mantid::Geometry::GeneralFrame frameTOF( Mantid::Geometry::GeneralFrame::GeneralFrameName, ax0->unit()->label()); // ------------------ Build all the dimensions ---------------------------- MDHistoDimension_sptr dimX( new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numXPixels), m_numXPixels)); MDHistoDimension_sptr dimY( new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numYPixels), m_numYPixels)); std::string TOFname = ax0->title(); if (TOFname.empty()) TOFname = ax0->unit()->unitID(); MDHistoDimension_sptr dimTOF(new MDHistoDimension( TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min), static_cast<coord_t>(tof_max), ax0->length())); std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF}; if (banks.size() > 1) { Mantid::Geometry::GeneralFrame frameNumber( Mantid::Geometry::GeneralFrame::GeneralFrameName, "number"); int min = banks.begin()->first; int max = banks.rbegin()->first + 1; MDHistoDimension_sptr dimBanks(new MDHistoDimension( "bank", "bank", frameNumber, static_cast<coord_t>(min), static_cast<coord_t>(max), max - min)); dims.push_back(dimBanks); } // --------- Create the workspace with the right number of dimensions // ---------- size_t nd = dims.size(); IMDEventWorkspace_sptr outWS = MDEventFactory::CreateMDWorkspace(nd, "MDEvent"); outWS->initGeometry(dims); outWS->initialize(); this->setBoxController(outWS->getBoxController(), mws->getInstrument()); outWS->splitBox(); MDEventWorkspace3::sptr outWS3 = boost::dynamic_pointer_cast<MDEventWorkspace3>(outWS); MDEventWorkspace4::sptr outWS4 = boost::dynamic_pointer_cast<MDEventWorkspace4>(outWS); // Copy ExperimentInfo (instrument, run, sample) to the output WS ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo()); uint16_t runIndex = outWS->addExperimentInfo(ei); // ---------------- Convert each bank -------------------------------------- for (auto &bank : banks) { int bankNum = bank.first; RectangularDetector_const_sptr det = bank.second; for (int x = 0; x < det->xpixels(); x++) for (int y = 0; y < det->ypixels(); y++) { // Find the workspace index for this pixel coordinate detid_t detID = det->getDetectorIDAtXY(x, y); size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset]; if (wi >= in_ws->getNumberHistograms()) throw std::runtime_error("Invalid workspace index found in bank " + det->getName() + "!"); coord_t xPos = static_cast<coord_t>(x); coord_t yPos = static_cast<coord_t>(y); coord_t bankPos = static_cast<coord_t>(bankNum); EventList &el = in_ws->getSpectrum(wi); // We want to bind to the right templated function, so we have to know // the type of TofEvent contained in the EventList. boost::function<void()> func; switch (el.getEventType()) { case TOF: if (nd == 3) this->convertEventList<TofEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<TofEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED: if (nd == 3) this->convertEventList<WeightedEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED_NOTIME: if (nd == 3) this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; default: throw std::runtime_error("EventList had an unexpected data type!"); } } } // ---------------------- Perform all box splitting --------------- ThreadScheduler *ts = new ThreadSchedulerLargestCost(); ThreadPool tp(ts); outWS->splitAllIfNeeded(ts); tp.joinAll(); outWS->refreshCache(); // Save the output workspace this->setProperty("OutputWorkspace", outWS); }