/** 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); } }
/** Create the vtkStructuredGrid from the provided workspace @param progressUpdating: Reporting object to pass progress information up the stack. @return fully constructed vtkDataSet. */ vtkSmartPointer<vtkDataSet> vtkMDLineFactory::create(ProgressAction &progressUpdating) const { auto product = tryDelegatingCreation<IMDEventWorkspace, 1>(m_workspace, progressUpdating); if (product != nullptr) { return product; } else { g_log.warning() << "Factory " << this->getFactoryTypeName() << " is being used. You are viewing data with less than " "three dimensions in the VSI. \n"; IMDEventWorkspace_sptr imdws = doInitialize<IMDEventWorkspace, 1>(m_workspace); // Acquire a scoped read-only lock to the workspace (prevent segfault from // algos modifying ws) Mantid::Kernel::ReadLock lock(*imdws); const size_t nDims = imdws->getNumDims(); size_t nNonIntegrated = imdws->getNonIntegratedDimensions().size(); /* Write mask array with correct order for each internal dimension. */ auto masks = Mantid::Kernel::make_unique<bool[]>(nDims); for (size_t i_dim = 0; i_dim < nDims; ++i_dim) { bool bIntegrated = imdws->getDimension(i_dim)->getIsIntegrated(); masks[i_dim] = !bIntegrated; // TRUE for unmaksed, integrated dimensions are masked. } // Ensure destruction in any event. boost::scoped_ptr<IMDIterator> it( createIteratorWithNormalization(m_normalizationOption, imdws.get())); // Create 2 points per box. vtkNew<vtkPoints> points; points->SetNumberOfPoints(it->getDataSize() * 2); // One scalar per box vtkNew<vtkFloatArray> signals; signals->Allocate(it->getDataSize()); signals->SetName(vtkDataSetFactory::ScalarName.c_str()); signals->SetNumberOfComponents(1); size_t nVertexes; auto visualDataSet = vtkSmartPointer<vtkUnstructuredGrid>::New(); visualDataSet->Allocate(it->getDataSize()); vtkNew<vtkIdList> linePointList; linePointList->SetNumberOfIds(2); Mantid::API::CoordTransform const *transform = NULL; if (m_useTransform) { transform = imdws->getTransformToOriginal(); } Mantid::coord_t out[1]; auto useBox = std::vector<bool>(it->getDataSize()); double progressFactor = 0.5 / double(it->getDataSize()); double progressOffset = 0.5; size_t iBox = 0; do { progressUpdating.eventRaised(double(iBox) * progressFactor); Mantid::signal_t signal_normalized = it->getNormalizedSignal(); if (std::isfinite(signal_normalized) && m_thresholdRange->inRange(signal_normalized)) { useBox[iBox] = true; signals->InsertNextValue(static_cast<float>(signal_normalized)); auto coords = std::unique_ptr<coord_t[]>( it->getVertexesArray(nVertexes, nNonIntegrated, masks.get())); // Iterate through all coordinates. Candidate for speed improvement. for (size_t v = 0; v < nVertexes; ++v) { coord_t *coord = coords.get() + v * 1; size_t id = iBox * 2 + v; if (m_useTransform) { transform->apply(coord, out); points->SetPoint(id, out[0], 0, 0); } else { points->SetPoint(id, coord[0], 0, 0); } } } // valid number of vertexes returned else { useBox[iBox] = false; } ++iBox; } while (it->next()); for (size_t ii = 0; ii < it->getDataSize(); ++ii) { progressUpdating.eventRaised((double(ii) * progressFactor) + progressOffset); if (useBox[ii] == true) { vtkIdType pointIds = ii * 2; linePointList->SetId(0, pointIds + 0); // xyx linePointList->SetId(1, pointIds + 1); // dxyz visualDataSet->InsertNextCell(VTK_LINE, linePointList.GetPointer()); } // valid number of vertexes returned } signals->Squeeze(); points->Squeeze(); visualDataSet->SetPoints(points.GetPointer()); visualDataSet->GetCellData()->SetScalars(signals.GetPointer()); visualDataSet->Squeeze(); // Hedge against empty data sets if (visualDataSet->GetNumberOfPoints() <= 0) { vtkNullUnstructuredGrid nullGrid; visualDataSet = nullGrid.createNullData(); } vtkSmartPointer<vtkDataSet> dataset = visualDataSet; return dataset; } }
/** Create the vtkStructuredGrid from the provided workspace @param progressUpdating: Reporting object to pass progress information up the stack. @return fully constructed vtkDataSet. */ vtkDataSet* vtkMDQuadFactory::create(ProgressAction& progressUpdating) const { vtkDataSet* product = tryDelegatingCreation<IMDEventWorkspace, 2>(m_workspace, progressUpdating); if(product != NULL) { return product; } else { IMDEventWorkspace_sptr imdws = this->castAndCheck<IMDEventWorkspace, 2>(m_workspace); // Acquire a scoped read-only lock to the workspace (prevent segfault from algos modifying ws) Mantid::Kernel::ReadLock lock(*imdws); const size_t nDims = imdws->getNumDims(); size_t nNonIntegrated = imdws->getNonIntegratedDimensions().size(); /* Write mask array with correct order for each internal dimension. */ bool* masks = new bool[nDims]; for(size_t i_dim = 0; i_dim < nDims; ++i_dim) { bool bIntegrated = imdws->getDimension(i_dim)->getIsIntegrated(); masks[i_dim] = !bIntegrated; //TRUE for unmaksed, integrated dimensions are masked. } //Ensure destruction in any event. boost::scoped_ptr<IMDIterator> it(imdws->createIterator()); // Create 4 points per box. vtkPoints *points = vtkPoints::New(); points->SetNumberOfPoints(it->getDataSize() * 4); // One scalar per box vtkFloatArray * signals = vtkFloatArray::New(); signals->Allocate(it->getDataSize()); signals->SetName(m_scalarName.c_str()); signals->SetNumberOfComponents(1); size_t nVertexes; vtkUnstructuredGrid *visualDataSet = vtkUnstructuredGrid::New(); visualDataSet->Allocate(it->getDataSize()); vtkIdList * quadPointList = vtkIdList::New(); quadPointList->SetNumberOfIds(4); Mantid::API::CoordTransform* transform = NULL; if (m_useTransform) { transform = imdws->getTransformToOriginal(); } Mantid::coord_t out[2]; bool* useBox = new bool[it->getDataSize()]; double progressFactor = 0.5/double(it->getDataSize()); double progressOffset = 0.5; size_t iBox = 0; do { progressUpdating.eventRaised(progressFactor * double(iBox)); Mantid::signal_t signal_normalized= it->getNormalizedSignal(); if (!isSpecial( signal_normalized ) && m_thresholdRange->inRange(signal_normalized)) { useBox[iBox] = true; signals->InsertNextValue(static_cast<float>(signal_normalized)); coord_t* coords = it->getVertexesArray(nVertexes, nNonIntegrated, masks); delete [] coords; coords = it->getVertexesArray(nVertexes, nNonIntegrated, masks); //Iterate through all coordinates. Candidate for speed improvement. for(size_t v = 0; v < nVertexes; ++v) { coord_t * coord = coords + v*2; size_t id = iBox*4 + v; if(m_useTransform) { transform->apply(coord, out); points->SetPoint(id, out[0], out[1], 0); } else { points->SetPoint(id, coord[0], coord[1], 0); } } // Free memory delete [] coords; } // valid number of vertexes returned else { useBox[iBox] = false; } ++iBox; } while (it->next()); delete[] masks; for(size_t ii = 0; ii < it->getDataSize() ; ++ii) { progressUpdating.eventRaised((progressFactor * double(ii)) + progressOffset); if (useBox[ii] == true) { vtkIdType pointIds = vtkIdType(ii * 4); quadPointList->SetId(0, pointIds + 0); //xyx quadPointList->SetId(1, pointIds + 1); //dxyz quadPointList->SetId(2, pointIds + 3); //dxdyz quadPointList->SetId(3, pointIds + 2); //xdyz visualDataSet->InsertNextCell(VTK_QUAD, quadPointList); } // valid number of vertexes returned } delete[] useBox; signals->Squeeze(); points->Squeeze(); visualDataSet->SetPoints(points); visualDataSet->GetCellData()->SetScalars(signals); visualDataSet->Squeeze(); signals->Delete(); points->Delete(); quadPointList->Delete(); return visualDataSet; } }