/**
Create the vtkStructuredGrid from the provided workspace
@param progressUpdating: Reporting object to pass progress information up the stack.
@return fully constructed vtkDataSet.
*/
vtkDataSet* vtkMDHistoQuadFactory::create(ProgressAction& progressUpdating) const
{
    vtkDataSet* product = tryDelegatingCreation<MDHistoWorkspace, 2>(m_workspace, progressUpdating);
    if(product != NULL)
    {
        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);
        CPUTimer tim;
        const int nBinsX = static_cast<int>( m_workspace->getXDimension()->getNBins() );
        const int nBinsY = static_cast<int>( m_workspace->getYDimension()->getNBins() );

        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();

        coord_t incrementX = (maxX - minX) / static_cast<coord_t>(nBinsX);
        coord_t incrementY = (maxY - minY) / static_cast<coord_t>(nBinsY);

        boost::scoped_ptr<MDHistoWorkspaceIterator> iterator(dynamic_cast<MDHistoWorkspaceIterator*>(createIteratorWithNormalization(m_normalizationOption, m_workspace.get())));
        if (!iterator) {
            throw std::runtime_error(
                "Could not convert IMDIterator to a MDHistoWorkspaceIterator");
        }

        const int imageSize = (nBinsX ) * (nBinsY );
        vtkPoints *points = vtkPoints::New();
        points->Allocate(static_cast<int>(imageSize));

        vtkFloatArray * signal = vtkFloatArray::New();
        signal->Allocate(imageSize);
        signal->SetName(vtkDataSetFactory::ScalarName.c_str());
        signal->SetNumberOfComponents(1);

        //The following represent actual calculated positions.

        float signalScalar;
        const int nPointsX = nBinsX+1;
        const int nPointsY = nBinsY+1;

        /* The idea of the next chunk of code is that you should only
        create the points that will be needed; so an array of pointNeeded
        is set so that all required vertices are marked, and created in a second step. */

        // Array of the points that should be created, set to false
        bool * pointNeeded = new bool[nPointsX*nPointsY];
        memset(pointNeeded, 0, nPointsX*nPointsY*sizeof(bool));
        // Array with true where the voxel should be shown
        bool * voxelShown = new bool[nBinsX*nBinsY];

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

        size_t index = 0;
        for (int i = 0; i < nBinsX; i++)
        {
            progressUpdating.eventRaised(progressFactor*double(i));

            for (int j = 0; j < nBinsY; j++)
            {
                index = j + nBinsY*i;
                iterator->jumpTo(index);
                signalScalar = static_cast<float>(iterator->getNormalizedSignal()); // Get signal normalized as per m_normalizationOption

                if (isSpecial( signalScalar ) || !m_thresholdRange->inRange(signalScalar))
                {
                    // out of range
                    voxelShown[index] = false;
                }
                else
                {
                    // Valid data
                    voxelShown[index] = true;
                    signal->InsertNextValue(static_cast<float>(signalScalar));
                    // Make sure all 4 neighboring points are set to true
                    size_t pointIndex = i * nPointsY + j;
                    pointNeeded[pointIndex] = true;
                    pointIndex++;
                    pointNeeded[pointIndex] = true;
                    pointIndex += nPointsY-1;
                    pointNeeded[pointIndex] = true;
                    pointIndex++;
                    pointNeeded[pointIndex] = true;
                }
            }
        }

        std::cout << tim << " to check all the signal values." << std::endl;

        // Get the transformation that takes the points in the TRANSFORMED space back into the ORIGINAL (not-rotated) space.
        Mantid::API::CoordTransform const* transform = NULL;
        if (m_useTransform)
            transform = m_workspace->getTransformToOriginal();

        Mantid::coord_t in[3];
        Mantid::coord_t out[3];
        in[2] = 0;

        // Array with the point IDs (only set where needed)
        vtkIdType * pointIDs = new vtkIdType[nPointsX*nPointsY];
        index = 0;
        for (int i = 0; i < nPointsX; i++)
        {
            progressUpdating.eventRaised((progressFactor*double(i)) + progressOffset);
            in[0] = minX + (static_cast<coord_t>(i) * incrementX); //Calculate increment in x;
            for (int j = 0; j < nPointsY; j++)
            {
                // Create the point only when needed
                if (pointNeeded[index])
                {
                    in[1] = minY + (static_cast<coord_t>(j) * incrementY); //Calculate increment in y;
                    if (transform)
                    {
                        transform->apply(in, out);
                        pointIDs[index] = points->InsertNextPoint(out);
                    }
                    else
                        pointIDs[index] = points->InsertNextPoint(in);
                }
                index++;
            }
        }

        std::cout << tim << " to create the needed points." << std::endl;

        vtkUnstructuredGrid *visualDataSet = vtkUnstructuredGrid::New();
        visualDataSet->Allocate(imageSize);
        visualDataSet->SetPoints(points);
        visualDataSet->GetCellData()->SetScalars(signal);

        // ------ Quad creation ----------------
        vtkQuad* quad = vtkQuad::New(); // Significant speed increase by creating ONE quad
        index = 0;
        for (int i = 0; i < nBinsX; i++)
        {
            for (int j = 0; j < nBinsY; j++)
            {
                if (voxelShown[index])
                {
                    // The quad will be shown
                    quad->GetPointIds()->SetId(0, pointIDs[(i)*nPointsY + j]);
                    quad->GetPointIds()->SetId(1, pointIDs[(i+1)*nPointsY + j]);
                    quad->GetPointIds()->SetId(2, pointIDs[(i+1)*nPointsY + j+1]);
                    quad->GetPointIds()->SetId(3, pointIDs[(i)*nPointsY + j+1]);
                    visualDataSet->InsertNextCell(VTK_QUAD, quad->GetPointIds());
                }
                index++;
            }
        }
        quad->Delete();

        std::cout << tim << " to create and add the quads." << std::endl;

        points->Delete();
        signal->Delete();
        visualDataSet->Squeeze();
        delete [] pointIDs;
        delete [] voxelShown;
        delete [] pointNeeded;

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

        return visualDataSet;
    }
}
Esempio 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;
  }
}
Esempio n. 3
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 / double(imageSize);

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

  std::unique_ptr<MDHistoWorkspaceIterator> iterator(
      dynamic_cast<MDHistoWorkspaceIterator *>(createIteratorWithNormalization(
          m_normalizationOption, m_workspace.get())));

  vtkNew<vtkMDHWSignalArray<double>> signal;

  signal->SetName(vtkDataSetFactory::ScalarName.c_str());
  signal->InitializeArray(std::move(iterator), offset, imageSize);
  visualDataSet->GetCellData()->SetScalars(signal.GetPointer());

  for (vtkIdType index = 0; index < imageSize; ++index) {
    progressUpdate.eventRaised(double(index) * progressFactor);
    double signalScalar = signal->GetValue(index);
    bool maskValue = (!std::isfinite(signalScalar) ||
                      !m_thresholdRange->inRange(signalScalar));
    if (maskValue) {
      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::SafeDownCast(points->GetData());
  if (pointsarray == NULL) {
    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.5 / 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(NULL);
  visualDataSet->Squeeze();

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

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