Exemplo n.º 1
0
/*
Generate the vtkDataSet from the objects input IMDEventWorkspace
@param progressUpdating: Reporting object to pass progress information up the
stack.
@Return a fully constructed vtkUnstructuredGrid containing geometric and scalar
data.
*/
vtkSmartPointer<vtkDataSet>
vtkMDHexFactory::create(ProgressAction &progressUpdating) const {
  this->dataSet = tryDelegatingCreation<IMDEventWorkspace, 3>(
      m_workspace, progressUpdating, false);
  if (this->dataSet) {
    return this->dataSet;
  } else {
    IMDEventWorkspace_sptr imdws =
        this->castAndCheck<IMDEventWorkspace, 3>(m_workspace, false);

    size_t nd = imdws->getNumDims();
    if (nd > 3) {
      // Slice from >3D down to 3D
      this->slice = true;
      this->sliceMask = Mantid::Kernel::make_unique<bool[]>(nd);
      this->sliceImplicitFunction = boost::make_shared<MDImplicitFunction>();

      // Make the mask of dimensions
      for (size_t d = 0; d < nd; d++)
        this->sliceMask[d] = (d < 3);

      // Define where the slice is in 4D
      std::vector<coord_t> point(nd, 0);

      // Define two opposing planes that point in all higher dimensions
      std::vector<coord_t> normal1(nd, 0);
      std::vector<coord_t> normal2(nd, 0);
      for (size_t d = 3; d < nd; d++) {
        normal1[d] = +1.0;
        normal2[d] = -1.0;
      }
      // This creates a slice which is one bin thick in the 4th dimension
      // m_time assumed to satisfy: dim_min <= m_time < dim_max
      // but does not have to be a bin centre
      point[3] = getPreviousBinBoundary(imdws);
      sliceImplicitFunction->addPlane(MDPlane(normal1, point));
      point[3] = getNextBinBoundary(imdws);
      sliceImplicitFunction->addPlane(MDPlane(normal2, point));

    } else {
      // Direct 3D, so no slicing
      this->slice = false;
    }
    progressUpdating.eventRaised(0.1);
    // Macro to call the right instance of the
    CALL_MDEVENT_FUNCTION(this->doCreate, imdws);
    progressUpdating.eventRaised(1.0);

    // The macro does not allow return calls, so we used a member variable.
    return this->dataSet;
  }
}
Exemplo 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;
  }
}
Exemplo n.º 3
0
/**
Create the vtkStructuredGrid from the provided workspace
@param progressUpdating: Reporting object to pass progress information up the
stack.
@return vtkPolyData glyph.
*/
vtkSmartPointer<vtkPolyData>
vtkPeakMarkerFactory::create(ProgressAction &progressUpdating) const {
  validate();

  int numPeaks = m_workspace->getNumberPeaks();

  // Acquire a scoped read-only lock to the workspace (prevent segfault from
  // algos modifying ws)
  Mantid::Kernel::ReadLock lock(*m_workspace);

  const int resolution = 100;
  double progressFactor = 1.0 / static_cast<double>(numPeaks);

  vtkAppendPolyData *appendFilter = vtkAppendPolyData::New();
  // Go peak-by-peak
  for (int i = 0; i < numPeaks; i++) {
    progressUpdating.eventRaised(double(i) * progressFactor);

    // Point
    vtkNew<vtkPoints> peakPoint;
    peakPoint->Allocate(1);

    // What we'll return
    vtkNew<vtkPolyData> peakDataSet;
    peakDataSet->Allocate(1);
    peakDataSet->SetPoints(peakPoint.GetPointer());

    const IPeak &peak = m_workspace->getPeak(i);

    // Choose the dimensionality of the position to show
    V3D pos = getPosition(peak);
    peakPoint->InsertNextPoint(pos.X(), pos.Y(), pos.Z());

    peakPoint->Squeeze();
    peakDataSet->Squeeze();

    // Add a glyph and append to the appendFilter
    const Mantid::Geometry::PeakShape &shape =
        m_workspace->getPeak(i).getPeakShape();

    // Pick the radius up from the factory if possible, otherwise use the
    // user-provided value.
    if (shape.shapeName() ==
        Mantid::DataObjects::PeakShapeSpherical::sphereShapeName()) {
      double peakRadius =
          shape.radius(Mantid::Geometry::PeakShape::Radius).get();

      vtkNew<vtkRegularPolygonSource> polygonSource;
      polygonSource->GeneratePolygonOff();
      polygonSource->SetNumberOfSides(resolution);
      polygonSource->SetRadius(peakRadius);
      polygonSource->SetCenter(0., 0., 0.);

      for (unsigned axis = 0; axis < 3; ++axis) {
        vtkNew<vtkPVGlyphFilter> glyphFilter;
        setNormal(polygonSource.GetPointer(), axis);
        glyphFilter->SetInputData(peakDataSet.GetPointer());
        glyphFilter->SetSourceConnection(polygonSource->GetOutputPort());
        glyphFilter->Update();
        appendFilter->AddInputData(glyphFilter->GetOutput());
        appendFilter->Update();
      }
    } else if (shape.shapeName() ==
               Mantid::DataObjects::PeakShapeEllipsoid::ellipsoidShapeName()) {
      vtkNew<vtkFloatArray> transformSignal;
      transformSignal->SetNumberOfComponents(9);
      transformSignal->SetNumberOfTuples(1);
      auto tensor = getTransformTensor(
          dynamic_cast<const Mantid::DataObjects::PeakShapeEllipsoid &>(shape),
          peak);
      transformSignal->SetTypedTuple(0, tensor.data());
      peakDataSet->GetPointData()->SetTensors(transformSignal.GetPointer());

      vtkNew<vtkRegularPolygonSource> polygonSource;
      polygonSource->GeneratePolygonOff();
      polygonSource->SetNumberOfSides(resolution);
      polygonSource->SetRadius(1.);
      polygonSource->SetCenter(0., 0., 0.);

      for (unsigned axis = 0; axis < 3; ++axis) {
        vtkNew<vtkTensorGlyph> glyphFilter;
        setNormal(polygonSource.GetPointer(), axis);
        glyphFilter->SetInputData(peakDataSet.GetPointer());
        glyphFilter->SetSourceConnection(polygonSource->GetOutputPort());
        glyphFilter->ExtractEigenvaluesOff();
        glyphFilter->Update();
        appendFilter->AddInputData(glyphFilter->GetOutput());
        appendFilter->Update();
      }
    } else {
      vtkNew<vtkAxes> axis;
      axis->SymmetricOn();
      axis->SetScaleFactor(0.2);

      vtkNew<vtkPVGlyphFilter> glyphFilter;
      glyphFilter->SetInputData(peakDataSet.GetPointer());
      glyphFilter->SetSourceConnection(axis->GetOutputPort());
      glyphFilter->Update();
      appendFilter->AddInputData(glyphFilter->GetOutput());
      appendFilter->Update();
    }

  } // for each peak

  return vtkSmartPointer<vtkPolyData>::Take(appendFilter->GetOutput());
}
Exemplo n.º 4
0
/** Method for creating a 3D or 4D data set
 *
 * @param timestep :: index of the time step (4th dimension) in the workspace.
 *        Set to 0 for a 3D workspace.
 * @param progressUpdate: Progress updating. passes progress information up the
 *stack.
 * @return the vtkDataSet created
 */
vtkSmartPointer<vtkDataSet>
vtkMDHistoHexFactory::create3Dor4D(size_t timestep,
                                   ProgressAction &progressUpdate) const {
  // Acquire a scoped read-only lock to the workspace (prevent segfault from
  // algos modifying ws)
  ReadLock lock(*m_workspace);

  const size_t nDims = m_workspace->getNonIntegratedDimensions().size();

  std::vector<size_t> indexMultiplier(nDims, 0);

  // For quick indexing, accumulate these values
  // First multiplier
  indexMultiplier[0] = m_workspace->getDimension(0)->getNBins();
  for (size_t d = 1; d < nDims; d++) {
    indexMultiplier[d] =
        indexMultiplier[d - 1] * m_workspace->getDimension(d)->getNBins();
  }

  const int nBinsX = static_cast<int>(m_workspace->getXDimension()->getNBins());
  const int nBinsY = static_cast<int>(m_workspace->getYDimension()->getNBins());
  const int nBinsZ = static_cast<int>(m_workspace->getZDimension()->getNBins());

  const int imageSize = (nBinsX) * (nBinsY) * (nBinsZ);

  vtkSmartPointer<vtkStructuredGrid> visualDataSet =
      vtkSmartPointer<vtkStructuredGrid>::New();
  visualDataSet->SetDimensions(nBinsX + 1, nBinsY + 1, nBinsZ + 1);

  // Array with true where the voxel should be shown
  double progressFactor = 0.5 / static_cast<double>(imageSize);

  std::size_t offset = 0;
  if (nDims == 4) {
    offset = timestep * indexMultiplier[2];
  }

  vtkNew<vtkMDHWSignalArray<double>> signal;

  signal->SetName(vtkDataSetFactory::ScalarName.c_str());
  signal->InitializeArray(m_workspace.get(), m_normalizationOption, offset);
  visualDataSet->GetCellData()->SetScalars(signal.GetPointer());

  // update progress after a 1% change
  vtkIdType progressIncrement = std::max(1, imageSize / 50);
  for (vtkIdType index = 0; index < imageSize; ++index) {
    if (index % progressIncrement == 0)
      progressUpdate.eventRaised(static_cast<double>(index) * progressFactor);
    double signalScalar = signal->GetValue(index);
    if (!std::isfinite(signalScalar)) {
      visualDataSet->BlankCell(index);
    }
  }

  vtkNew<vtkPoints> points;

  Mantid::coord_t in[2];

  const coord_t maxX = m_workspace->getXDimension()->getMaximum();
  const coord_t minX = m_workspace->getXDimension()->getMinimum();
  const coord_t maxY = m_workspace->getYDimension()->getMaximum();
  const coord_t minY = m_workspace->getYDimension()->getMinimum();
  const coord_t maxZ = m_workspace->getZDimension()->getMaximum();
  const coord_t minZ = m_workspace->getZDimension()->getMinimum();

  const coord_t incrementX = (maxX - minX) / static_cast<coord_t>(nBinsX);
  const coord_t incrementY = (maxY - minY) / static_cast<coord_t>(nBinsY);
  const coord_t incrementZ = (maxZ - minZ) / static_cast<coord_t>(nBinsZ);

  const vtkIdType nPointsX = nBinsX + 1;
  const vtkIdType nPointsY = nBinsY + 1;
  const vtkIdType nPointsZ = nBinsZ + 1;

  vtkFloatArray *pointsarray = vtkFloatArray::FastDownCast(points->GetData());
  if (!pointsarray) {
    throw std::runtime_error("Failed to cast vtkDataArray to vtkFloatArray.");
  } else if (pointsarray->GetNumberOfComponents() != 3) {
    throw std::runtime_error("points array must have 3 components.");
  }
  float *it = pointsarray->WritePointer(0, nPointsX * nPointsY * nPointsZ * 3);
  // Array with the point IDs (only set where needed)
  progressFactor = 0.25 / static_cast<double>(nPointsZ);
  double progressOffset = 0.5;
  for (int z = 0; z < nPointsZ; z++) {
    // Report progress updates for the last 50%
    progressUpdate.eventRaised(double(z) * progressFactor + progressOffset);
    in[1] = (minZ + (static_cast<coord_t>(z) *
                     incrementZ)); // Calculate increment in z;
    for (int y = 0; y < nPointsY; y++) {
      in[0] = (minY + (static_cast<coord_t>(y) *
                       incrementY)); // Calculate increment in y;
      for (int x = 0; x < nPointsX; x++) {
        it[0] = (minX + (static_cast<coord_t>(x) *
                         incrementX)); // Calculate increment in x;
        it[1] = in[0];
        it[2] = in[1];
        std::advance(it, 3);
      }
    }
  }

  visualDataSet->SetPoints(points.GetPointer());
  visualDataSet->Register(nullptr);
  visualDataSet->Squeeze();

  // Hedge against empty data sets
  if (visualDataSet->GetNumberOfPoints() <= 0) {
    vtkNullStructuredGrid nullGrid;
    visualDataSet = nullGrid.createNullData();
  }

  vtkSmartPointer<vtkDataSet> dataset = visualDataSet;
  return dataset;
}
Exemplo n.º 5
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>
vtkMDHistoLineFactory::create(ProgressAction &progressUpdating) const {
  auto product =
      tryDelegatingCreation<MDHistoWorkspace, 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";

    Mantid::Kernel::ReadLock lock(*m_workspace);
    const int nBinsX =
        static_cast<int>(m_workspace->getXDimension()->getNBins());

    const coord_t minX = m_workspace->getXDimension()->getMinimum();

    coord_t incrementX = m_workspace->getXDimension()->getBinWidth();

    const int imageSize = nBinsX;
    vtkNew<vtkPoints> points;
    points->Allocate(static_cast<int>(imageSize));

    vtkNew<vtkFloatArray> signal;
    signal->Allocate(imageSize);
    signal->SetName(vtkDataSetFactory::ScalarName.c_str());
    signal->SetNumberOfComponents(1);

    UnstructuredPoint unstructPoint;
    const int nPointsX = nBinsX;
    Column column(nPointsX);

    NullCoordTransform transform;
    // Mantid::API::CoordTransform* transform =
    // m_workspace->getTransformFromOriginal();
    Mantid::coord_t in[3];
    Mantid::coord_t out[3];

    double progressFactor = 0.5 / double(nBinsX);
    double progressOffset = 0.5;

    // Loop through dimensions
    for (int i = 0; i < nPointsX; i++) {
      progressUpdating.eventRaised(progressFactor * double(i));
      in[0] = minX +
              static_cast<coord_t>(i) * incrementX; // Calculate increment in x;

      float signalScalar =
          static_cast<float>(m_workspace->getSignalNormalizedAt(i));

      if (!std::isfinite(signalScalar)) {
        // Flagged so that topological and scalar data is not applied.
        unstructPoint.isSparse = true;
      } else {
        if (i < (nBinsX - 1)) {
          signal->InsertNextValue(static_cast<float>(signalScalar));
        }
        unstructPoint.isSparse = false;
      }

      transform.apply(in, out);

      unstructPoint.pointId = points->InsertNextPoint(out);
      column[i] = unstructPoint;
    }

    points->Squeeze();
    signal->Squeeze();

    auto visualDataSet = vtkSmartPointer<vtkUnstructuredGrid>::New();
    visualDataSet->Allocate(imageSize);
    visualDataSet->SetPoints(points.GetPointer());
    visualDataSet->GetCellData()->SetScalars(signal.GetPointer());

    for (int i = 0; i < nBinsX - 1; i++) {
      progressUpdating.eventRaised((progressFactor * double(i)) +
                                   progressOffset);
      // Only create topologies for those cells which are not sparse.
      if (!column[i].isSparse) {
        vtkLine *line = vtkLine::New();
        line->GetPointIds()->SetId(0, column[i].pointId);
        line->GetPointIds()->SetId(1, column[i + 1].pointId);
        visualDataSet->InsertNextCell(VTK_LINE, line->GetPointIds());
      }
    }

    visualDataSet->Squeeze();

    // Hedge against empty data sets
    if (visualDataSet->GetNumberOfPoints() <= 0) {
      vtkNullUnstructuredGrid nullGrid;
      visualDataSet = nullGrid.createNullData();
    }

    vtkSmartPointer<vtkDataSet> dataset = visualDataSet;
    return dataset;
  }
}