Ejemplo n.º 1
0
/** 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);
  }
}
Ejemplo n.º 2
0
/**
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;
  }
}
Ejemplo n.º 3
0
    /**
    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;
      }
    }