// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void GenerateFaceSchuhMisorientationColoring::execute()
{
  int err = 0;
  setErrorCondition(err);
  dataCheckSurfaceMesh();
  if(getErrorCondition() < 0) { return; }

  dataCheckVoxel();
  if(getErrorCondition() < 0) { return; }

  notifyStatusMessage(getMessagePrefix(), getHumanLabel(), "Starting");

  // Run the data check to allocate the memory for the centroid array
  int64_t numTriangles = m_SurfaceMeshFaceLabelsPtr.lock()->getNumberOfTuples();

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  bool doParallel = true;
#endif

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  if (doParallel == true)
  {
    tbb::parallel_for(tbb::blocked_range<size_t>(0, numTriangles),
                      CalculateFaceSchuhMisorientationColorsImpl(m_SurfaceMeshFaceLabels, m_FeaturePhases, m_AvgQuats, m_SurfaceMeshFaceSchuhMisorientationColors, m_CrystalStructures), tbb::auto_partitioner());
  }
  else
#endif
  {
    CalculateFaceSchuhMisorientationColorsImpl serial(m_SurfaceMeshFaceLabels, m_FeaturePhases, m_AvgQuats, m_SurfaceMeshFaceSchuhMisorientationColors, m_CrystalStructures);
    serial.generate(0, numTriangles);
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Example #2
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void PerPhaseMinSize::preflight()
{
  dataCheck(true, 1, 1, 1);

  VoxelDataContainer* m = getVoxelDataContainer();
  if(NULL == m)
  {
    setErrorCondition(-999);
    notifyErrorMessage("The DataContainer Object was NULL", -999);
    return;
  }

  RenumberGrains::Pointer renumber_grains = RenumberGrains::New();
  renumber_grains->setObservers(this->getObservers());
  renumber_grains->setVoxelDataContainer(m);
  renumber_grains->setMessagePrefix(getMessagePrefix());
  renumber_grains->preflight();
  int err = renumber_grains->getErrorCondition();
  if (err < 0)
  {
    setErrorCondition(renumber_grains->getErrorCondition());
    addErrorMessages(renumber_grains->getPipelineMessages());
    return;
  }
}
void FeatureFaceCurvatureFilter::tbbTaskProgress()
{
  m_CompletedFeatureFaces++;

  QString ss = QObject::tr("%1/%2 Complete").arg(m_CompletedFeatureFaces).arg(m_TotalFeatureFaces);
  notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void MultiEmmpmFilter::execute()
{
  setErrorCondition(0);
  dataCheck();
  if (getErrorCondition() < 0) { return; }

  DataArrayPath inputAMPath = DataArrayPath::GetAttributeMatrixPath(getInputDataArrayVector());

  QList<QString> arrayNames = DataArrayPath::GetDataArrayNames(getInputDataArrayVector());
  QListIterator<QString> iter(arrayNames);

  QString msgPrefix = getMessagePrefix();
  int32_t i = 1;
  // This is the routine that sets up the EM/MPM to segment the image
  while (iter.hasNext())
  {
    DataArrayPath arrayPath = inputAMPath;
    QString name = iter.next();

    arrayPath.setDataArrayName(name);
    setInputDataArrayPath(arrayPath);

    // Change the output AttributeMatrix
    arrayPath.setAttributeMatrixName(getOutputAttributeMatrixName());
    QString outName = getOutputArrayPrefix() + arrayPath.getDataArrayName();
    arrayPath.setDataArrayName(outName);
    // Remove the array if it already exists ; this would be very strange but check for it anyway
    getDataContainerArray()->getAttributeMatrix(arrayPath)->removeAttributeArray(outName);
    setOutputDataArrayPath(arrayPath);

    QString prefix = QObject::tr("%1 (Array %2 of %3)").arg(msgPrefix).arg(i).arg(arrayNames.size());
    setMessagePrefix(prefix);
    if ( i == 2 && getUsePreviousMuSigma())
    {
      setEmmpmInitType(EMMPM_ManualInit);
    }
    else
    {
      setEmmpmInitType(EMMPM_Basic);
    }

    EMMPMFilter::execute();
    if (getErrorCondition() < 0) { break; }
    i++;

    if (getCancel()) { break; }
  }

  if (getErrorCondition() < 0)
  {
    QString ss = QObject::tr("Error occurred running the EM/MPM algorithm");
    setErrorCondition(-60009);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Example #5
0
void Logger::logToStream(std::ostream& stream, LogLevel level, const char* filename, 
        int lineNumber, const std::string& message)
    {
    indentLogOstream(
        message,
        getMessagePrefix(logLevelToString(level), filename, lineNumber), 
        stream
        );
    }
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void GenerateSurfaceMeshConnectivity::execute()
{
  int err = 0;
  std::stringstream ss;
  setErrorCondition(err);
  VoxelDataContainer* m = getVoxelDataContainer();
  if(NULL == m)
  {
    setErrorCondition(-999);
    notifyErrorMessage("The Voxel DataContainer Object was NULL", -999);
    return;
  }
  setErrorCondition(0);
  dataCheck(false, 1, 1, 1);
  if (getErrorCondition() < 0)
  {
    return;
  }
  // We need the vertex->Triangle Lists to build the Triangle Neighbor lists so if either
  // of those are true then build the vertex->triangle lists
  if (m_GenerateVertexTriangleLists == true || m_GenerateTriangleNeighbors == true)
  {
    notifyStatusMessage("Generating Vertex Triangle List");
    getSurfaceMeshDataContainer()->buildMeshVertLinks();
  }
  if (m_GenerateTriangleNeighbors == true)
  {
    notifyStatusMessage("Generating Face Neighbors List");
    getSurfaceMeshDataContainer()->buildMeshFaceNeighborLists();
  }

  if (m_GenerateEdgeIdList == true)
  {
    // There was no Edge connectivity before this filter so delete it when we are done with it
    GenerateUniqueEdges::Pointer conn = GenerateUniqueEdges::New();
    ss.str("");
    ss << getMessagePrefix() << " |->Generating Unique Edge Ids |->";
    conn->setMessagePrefix(ss.str());
    conn->setObservers(getObservers());
    conn->setVoxelDataContainer(getVoxelDataContainer());
    conn->setSurfaceMeshDataContainer(getSurfaceMeshDataContainer());
    conn->setSolidMeshDataContainer(getSolidMeshDataContainer());
    conn->execute();
    if(conn->getErrorCondition() < 0)
    {
      setErrorCondition(conn->getErrorCondition());
      return;
    }
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage("Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void WritePoleFigure::writeImage(QImage image, QString label)
{
  QString filename = generateImagePath(label);
  QString ss = QObject::tr("Writing Image %1").arg(filename);
  notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
  bool saved = image.save(filename);
  if (!saved)
  {
    setErrorCondition(-90011);
    QString ss = QObject::tr("The Pole Figure image file '%1' was not saved").arg(filename);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void SineParamsSegmentFeatures::execute()
{
  setErrorCondition(0);

  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  QVector<size_t> tDims(1, 1);
  m->getAttributeMatrix(getCellFeatureAttributeMatrixName())->resizeAttributeArrays(tDims);

  // This runs a subfilter
  int64_t totalPoints = m_FeatureIdsPtr.lock()->getNumberOfTuples();

  // Tell the user we are starting the filter
  notifyStatusMessage(getMessagePrefix(), getHumanLabel(), "Starting");

  //Convert user defined tolerance to radians.
  //angleTolerance = m_AngleTolerance * SIMPLib::Constants::k_Pi / 180.0f;
  for(int64_t i = 0; i < totalPoints; i++)
  {
    m_FeatureIds[i] = 0;
  }

  // Generate the random voxel indices that will be used for the seed points to start a new grain growth/agglomeration
  const size_t rangeMin = 0;
  const size_t rangeMax = totalPoints - 1;
  initializeVoxelSeedGenerator(rangeMin, rangeMax);

  SegmentFeatures::execute();

  size_t totalFeatures = m->getAttributeMatrix(getCellFeatureAttributeMatrixName())->getNumTuples();
  if (totalFeatures < 2)
  {
    setErrorCondition(-87000);
    notifyErrorMessage(getHumanLabel(), "The number of Features was 0 or 1 which means no features were detected. Is a threshold value set to high?", getErrorCondition());
    return;
  }

  // By default we randomize grains
  if (true == m_RandomizeFeatureIds)
  {
    randomizeFeatureIds(totalPoints, totalFeatures);
  }

  // If there is an error set this to something negative and also set a message
  notifyStatusMessage(getHumanLabel(), "Completed");
}
Example #9
0
void writeLog(
        LogLevel level, 
        const char*  filename, 
        int lineNumber, 
        const std::string& message)
    {
    std::string logLevelLabel(Ufora::Logging::Logger::logLevelToString(level));
    std::string firstLinePrefix(getMessagePrefix(logLevelLabel, filename, lineNumber));

    static boost::mutex m;
    boost::lock_guard<boost::mutex> g(m);
    std::ostringstream stream;

    indentLogOstream(message, firstLinePrefix, stream);

    std::cerr << stream.str() << std::endl;
    }
Example #10
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AlignSectionsFeature::find_shifts(std::vector<int64_t>& xshifts, std::vector<int64_t>& yshifts)
{
  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  std::ofstream outFile;
  if (getWriteAlignmentShifts() == true)
  {
    outFile.open(getAlignmentShiftFileName().toLatin1().data());
  }
  size_t udims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);

  int64_t dims[3] =
  {
    static_cast<int64_t>(udims[0]),
    static_cast<int64_t>(udims[1]),
    static_cast<int64_t>(udims[2]),
  };

  float disorientation = 0.0f;
  float mindisorientation = std::numeric_limits<float>::max();
  int32_t newxshift = 0;
  int32_t newyshift = 0;
  int32_t oldxshift = 0;
  int32_t oldyshift = 0;
  float count = 0.0f;
  int64_t slice = 0;
  int64_t refposition = 0;
  int64_t curposition = 0;
  std::vector<std::vector<float> >  misorients(dims[0]);

  for (int64_t a = 0; a < dims[0]; a++)
  {
    misorients[a].assign(dims[1], 0.0f);
  }

  for (int64_t iter = 1; iter < dims[2]; iter++)
  {
    QString ss = QObject::tr("Aligning Sections || Determining Shifts || %1% Complete").arg(((float)iter / dims[2]) * 100);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    mindisorientation = std::numeric_limits<float>::max();
    slice = (dims[2] - 1) - iter;
    oldxshift = -1;
    oldyshift = -1;
    newxshift = 0;
    newyshift = 0;
    for (int64_t a = 0; a < dims[0]; a++)
    {
      for (int64_t b = 0; b < dims[1]; b++)
      {
        misorients[a][b] = 0;
      }
    }
    while (newxshift != oldxshift || newyshift != oldyshift)
    {
      oldxshift = newxshift;
      oldyshift = newyshift;
      for (int32_t j = -3; j < 4; j++)
      {
        for (int32_t k = -3; k < 4; k++)
        {
          disorientation = 0.0f;
          count = 0.0f;
          if (misorients[k + oldxshift + dims[0] / 2][j + oldyshift + dims[1] / 2] == 0.0f && abs(k + oldxshift) < (dims[0] / 2)
              && (j + oldyshift) < (dims[1] / 2))
          {
            for (int64_t l = 0; l < dims[1]; l = l + 4)
            {
              for (int64_t n = 0; n < dims[0]; n = n + 4)
              {
                if ((l + j + oldyshift) >= 0 && (l + j + oldyshift) < dims[1] && (n + k + oldxshift) >= 0 && (n + k + oldxshift) < dims[0])
                {
                  refposition = ((slice + 1) * dims[0] * dims[1]) + (l * dims[0]) + n;
                  curposition = (slice * dims[0] * dims[1]) + ((l + j + oldyshift) * dims[0]) + (n + k + oldxshift);
                  if (m_GoodVoxels[refposition] != m_GoodVoxels[curposition]) { disorientation++; }
                  count++;
                }
                else
                {

                }
              }
            }
            disorientation = disorientation / count;
            misorients[k + oldxshift + dims[0] / 2][j + oldyshift + dims[1] / 2] = disorientation;
            if (disorientation < mindisorientation)
            {
              newxshift = k + oldxshift;
              newyshift = j + oldyshift;
              mindisorientation = disorientation;
            }
          }
        }
      }
    }
    xshifts[iter] = xshifts[iter - 1] + newxshift;
    yshifts[iter] = yshifts[iter - 1] + newyshift;
    if (getWriteAlignmentShifts() == true)
    {
      outFile << slice << "	" << slice + 1 << "	" << newxshift << "	" << newyshift << "	" << xshifts[iter] << "	" << yshifts[iter] << std::endl;
    }
  }
  if (getWriteAlignmentShifts() == true)
  {
    outFile.close();
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void SobelEdge::execute()
{
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getSelectedCellArrayPath().getDataContainerName());
  QString attrMatName = getSelectedCellArrayPath().getAttributeMatrixName();

  //wrap m_RawImageData as itk::image
  ImageProcessing::DefaultImageType::Pointer inputImage = ITKUtilitiesType::CreateItkWrapperForDataPointer(m, attrMatName, m_SelectedCellArray);

  if(m_Slice)
  {
    //wrap output array
    ImageProcessing::DefaultImageType::Pointer outputImage = ITKUtilitiesType::CreateItkWrapperForDataPointer(m, attrMatName, m_NewCellArray);

    //get dimensions
    size_t udims[3] = {0, 0, 0};
    m->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
    typedef int32_t DimType;
#else
    typedef int64_t DimType;
#endif
    DimType dims[3] =
    {
      static_cast<DimType>(udims[0]),
      static_cast<DimType>(udims[1]),
      static_cast<DimType>(udims[2]),
    };

    //create edge filter
    typedef itk::SobelEdgeDetectionImageFilter<ImageProcessing::DefaultSliceType, ImageProcessing::FloatSliceType> SobelFilterType;
    SobelFilterType::Pointer sobelFilter = SobelFilterType::New();

    //convert result back to uint8
    typedef itk::RescaleIntensityImageFilter<ImageProcessing::FloatSliceType, ImageProcessing::DefaultSliceType> RescaleImageType;
    RescaleImageType::Pointer rescaleFilter = RescaleImageType::New();
    rescaleFilter->SetOutputMinimum(0);
    rescaleFilter->SetOutputMaximum(255);

    //loop over slices applying filters
    for(int i = 0; i < dims[2]; ++i)
    {
      QString ss = QObject::tr("Finding Edges On Slice: %1").arg(i + 1);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

      //get slice
      ImageProcessing::DefaultSliceType::Pointer inputSlice = ITKUtilitiesType::ExtractSlice(inputImage, ImageProcessing::ZSlice, i);

      //run filters
      sobelFilter->SetInput(inputSlice);
      rescaleFilter->SetInput(sobelFilter->GetOutput());


      //execute filters
      try
      {
        sobelFilter->Update();
        rescaleFilter->Update();
      }
      catch( itk::ExceptionObject& err )
      {
        setErrorCondition(-5);
        QString ss = QObject::tr("Failed to execute itk::SobelEdgeDetectionImageFilter filter. Error Message returned from ITK:\n   %1").arg(err.GetDescription());
        notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
      }

      //copy into volume
      ITKUtilitiesType::SetSlice(outputImage, rescaleFilter->GetOutput(), ImageProcessing::ZSlice, i);
    }
  }
  else
  {
    //create edge filter
    typedef itk::SobelEdgeDetectionImageFilter<ImageProcessing::DefaultImageType, ImageProcessing::FloatImageType> SobelFilterType;
    SobelFilterType::Pointer sobelFilter = SobelFilterType::New();
    sobelFilter->SetInput(inputImage);

    //convert result back to uint8
    typedef itk::RescaleIntensityImageFilter<ImageProcessing::FloatImageType, ImageProcessing::DefaultImageType> RescaleImageType;
    RescaleImageType::Pointer rescaleFilter = RescaleImageType::New();
    rescaleFilter->SetInput(sobelFilter->GetOutput());
    rescaleFilter->SetOutputMinimum(0);
    rescaleFilter->SetOutputMaximum(255);

    //have filter write to dream3d array instead of creating its own buffer
    ITKUtilitiesType::SetITKFilterOutput(rescaleFilter->GetOutput(), m_NewCellArrayPtr.lock());

    //execute filters
    try
    {
      sobelFilter->Update();
      rescaleFilter->Update();
    }
    catch( itk::ExceptionObject& err )
    {
      setErrorCondition(-5);
      QString ss = QObject::tr("Failed to execute itk::SobelEdgeDetectionImageFilter filter. Error Message returned from ITK:\n   %1").arg(err.GetDescription());
      notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    }

  }

  //array name changing/cleanup
  if(m_SaveAsNewArray == false)
  {
    AttributeMatrix::Pointer attrMat = m->getAttributeMatrix(m_SelectedCellArrayPath.getAttributeMatrixName());
    attrMat->removeAttributeArray(m_SelectedCellArrayPath.getDataArrayName());
    attrMat->renameAttributeArray(m_NewCellArrayName, m_SelectedCellArrayPath.getDataArrayName());
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AdaptiveAlignmentMutualInformation::find_shifts(std::vector<int64_t>& xshifts, std::vector<int64_t>& yshifts, std::vector<float>& xneedshifts, std::vector<float>& yneedshifts)
{
	DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

	int64_t totalPoints = m->getAttributeMatrix(getCellAttributeMatrixName())->getNumTuples();
	m_MIFeaturesPtr = Int32ArrayType::CreateArray((totalPoints * 1), "_INTERNAL_USE_ONLY_MIFeatureIds");
	m_MIFeaturesPtr->initializeWithZeros();
	int32_t* miFeatureIds = m_MIFeaturesPtr->getPointer(0);

	size_t udims[3] = { 0, 0, 0 };
	m->getGeometryAs<ImageGeom>()->getDimensions(udims);

	uint64_t dims[3] =
	{
		static_cast<uint64_t>(udims[0]),
		static_cast<uint64_t>(udims[1]),
		static_cast<uint64_t>(udims[2]),
	};

	uint64_t maxstoredshifts = 1;
	if (xneedshifts.size() > 0) maxstoredshifts = 20;

	float disorientation = 0.0f;

	std::vector<std::vector<int64_t>>  newxshift(dims[2]);
	std::vector<std::vector<int64_t>>  newyshift(dims[2]);
	std::vector<std::vector<float>>  mindisorientation(dims[2]);
	for (uint64_t a = 1; a < dims[2]; a++)
	{
		newxshift[a].resize(maxstoredshifts, 0);
		newyshift[a].resize(maxstoredshifts, 0);
		mindisorientation[a].resize(maxstoredshifts, std::numeric_limits<float>::max());
	}

	float** mutualinfo12 = NULL;
	float* mutualinfo1 = NULL;
	float* mutualinfo2 = NULL;
	int32_t featurecount1 = 0, featurecount2 = 0;
	int64_t oldxshift = 0;
	int64_t oldyshift = 0;
	float count = 0.0f;
	uint64_t slice = 0;

	int32_t refgnum = 0, curgnum = 0;
	uint64_t refposition = 0;
	uint64_t curposition = 0;

	form_features_sections();

	// Allocate a 2D Array which will be reused from slice to slice
	// second dimension is assigned in each cycle separately
	std::vector<std::vector<bool> >  misorients(dims[0]);

	const uint64_t halfDim0 = static_cast<uint64_t>(dims[0] * 0.5f);
	const uint64_t halfDim1 = static_cast<uint64_t>(dims[1] * 0.5f);
	uint64_t progInt = 0;

	for (uint64_t iter = 1; iter < dims[2]; iter++)
	{
		progInt = static_cast<uint64_t>(iter * 100 / static_cast<float>(dims[2]));
		QString ss = QObject::tr("Aligning Anisotropic Sections || Determining Shifts || %1% Complete").arg(progInt);
		notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

		slice = (dims[2] - 1) - iter;
		featurecount1 = featurecounts[slice];
		featurecount2 = featurecounts[slice + 1];
		mutualinfo12 = new float *[featurecount1];
		mutualinfo1 = new float[featurecount1];
		mutualinfo2 = new float[featurecount2];

		for (int32_t a = 0; a < featurecount1; a++)
		{
			mutualinfo1[a] = 0.0f;
			mutualinfo12[a] = new float[featurecount2];
			for (int32_t b = 0; b < featurecount2; b++)
			{
				mutualinfo12[a][b] = 0.0f;
				mutualinfo2[b] = 0.0f;
			}
		}
		oldxshift = -1;
		oldyshift = -1;

		for (uint64_t i = 0; i < dims[0]; i++)
		{
			misorients[i].assign(dims[1], false);
		}

		while (newxshift[iter][0] != oldxshift || newyshift[iter][0] != oldyshift)
		{
			oldxshift = newxshift[iter][0];
			oldyshift = newyshift[iter][0];

			for (int32_t j = -3; j < 4; j++)
			{
				for (int32_t k = -3; k < 4; k++)
				{
					disorientation = 0;
					count = 0;
					if (llabs(k + oldxshift) < halfDim0 && llabs(j + oldyshift) < halfDim1 && misorients[k + oldxshift + halfDim0][j + oldyshift + halfDim1] == false)
					{
						for (uint64_t l = 0; l < dims[1]; l = l + 4)
						{
							for (uint64_t n = 0; n < dims[0]; n = n + 4)
							{
								if ((l + j + oldyshift) >= 0 && (l + j + oldyshift) < dims[1] && (n + k + oldxshift) >= 0 && (n + k + oldxshift) < dims[0])
								{
									refposition = ((slice + 1) * dims[0] * dims[1]) + (l * dims[0]) + n;
									curposition = (slice * dims[0] * dims[1]) + ((l + j + oldyshift) * dims[0]) + (n + k + oldxshift);
									refgnum = miFeatureIds[refposition];
									curgnum = miFeatureIds[curposition];
									if (curgnum >= 0 && refgnum >= 0)
									{
										mutualinfo12[curgnum][refgnum]++;
										mutualinfo1[curgnum]++;
										mutualinfo2[refgnum]++;
										count++;
									}
								}
								else
								{
									mutualinfo12[0][0]++;
									mutualinfo1[0]++;
									mutualinfo2[0]++;
								}
							}
						}
						float ha = 0.0f;
						float hb = 0.0f;
						float hab = 0.0f;
						for (int32_t b = 0; b < featurecount1; b++)
						{
							mutualinfo1[b] = mutualinfo1[b] / count;
							if (mutualinfo1[b] != 0) { ha = ha + mutualinfo1[b] * logf(mutualinfo1[b]); }
						}
						for (int32_t c = 0; c < featurecount2; c++)
						{
							mutualinfo2[c] = mutualinfo2[c] / float(count);
							if (mutualinfo2[c] != 0) { hb = hb + mutualinfo2[c] * logf(mutualinfo2[c]); }
						}
						for (int32_t b = 0; b < featurecount1; b++)
						{
							for (int32_t c = 0; c < featurecount2; c++)
							{
								mutualinfo12[b][c] = mutualinfo12[b][c] / count;
								if (mutualinfo12[b][c] != 0) { hab = hab + mutualinfo12[b][c] * logf(mutualinfo12[b][c]); }
								float value = 0.0f;
								if (mutualinfo1[b] > 0 && mutualinfo2[c] > 0) { value = (mutualinfo12[b][c] / (mutualinfo1[b] * mutualinfo2[c])); }
								if (value != 0) { disorientation = disorientation + (mutualinfo12[b][c] * logf(value)); }
							}
						}
						for (int32_t b = 0; b < featurecount1; b++)
						{
							for (int32_t c = 0; c < featurecount2; c++)
							{
								mutualinfo12[b][c] = 0.0f;
								mutualinfo1[b] = 0.0f;
								mutualinfo2[c] = 0.0f;
							}
						}
						disorientation = 1.0f / disorientation;
						misorients[k + oldxshift + halfDim0][j + oldyshift + halfDim1] = true;

						// compare the new shift with currently stored ones
						int64_t s = maxstoredshifts;
						while (s - 1 >= 0 && disorientation < mindisorientation[iter][s - 1])
						{
							s--;
						}

						// new shift is stored with index 's' in the arrays
						if (s < maxstoredshifts)
						{
							// lag the shifts already stored
							for (int64_t t = maxstoredshifts - 1; t > s; t--)
							{
								newxshift[iter][t] = newxshift[iter][t - 1];
								newyshift[iter][t] = newyshift[iter][t - 1];
								mindisorientation[iter][t] = mindisorientation[iter][t - 1];
							}
							// store the new shift
							newxshift[iter][s] = k + oldxshift;
							newyshift[iter][s] = j + oldyshift;
							mindisorientation[iter][s] = disorientation;
						}
					}
				}
			}
		}
		xshifts[iter] = xshifts[iter - 1] + newxshift[iter][0];
		yshifts[iter] = yshifts[iter - 1] + newyshift[iter][0];

		delete[] mutualinfo1;
		delete[] mutualinfo2;
		for (int32_t i = 0; i < featurecount1; i++)
		{
			delete mutualinfo12[i];
		}
		delete[] mutualinfo12;
		mutualinfo1 = NULL;
		mutualinfo2 = NULL;
		mutualinfo12 = NULL;
	}

	std::vector<uint64_t> curindex(dims[2], 0);

	// find corrected shifts
	if (xneedshifts.size() > 0)
	{
		QString ss = QObject::tr("Aligning Anisotropic Sections || Correcting shifts");
		notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

		std::vector<float> changedisorientation(dims[2], 0);
		std::vector<uint64_t> changeindex(dims[2], 0);
		std::vector<float> changeerror(dims[2], 0);

		std::vector<float> xshiftsest;	// cumulative x-shifts estimated from SEM images
		std::vector<float> yshiftsest;	// cumulative y-shifts estimated from SEM images

		float curerror = 0;
		float tolerance = 1.0f / static_cast<float>(dims[2]);

		// evaluate error between current shifts and desired shifts
		if (xneedshifts.size() == 1)      // error is computed as misagreement between slopes
		{
			curerror = compute_error1(dims[2], 0, xneedshifts[0], yneedshifts[0], newxshift, newyshift, curindex);
		}
		else if (xneedshifts.size() > 1)  // error is computed as misagreement with shifts estimated from SEM images
		{
			xshiftsest.resize(dims[2], 0);
			yshiftsest.resize(dims[2], 0);
			for (uint64_t iter = 1; iter < dims[2]; iter++)
			{
				xshiftsest[iter] = xshiftsest[iter - 1] + xneedshifts[iter - 1];
				yshiftsest[iter] = yshiftsest[iter - 1] + yneedshifts[iter - 1];
			}
			curerror = compute_error2(dims[2], 0, xshiftsest, yshiftsest, newxshift, newyshift, curindex);
		}

		// iterative selection of a candidate shift, recomputing of current candidates, evaluation of error
		if (curerror > tolerance)
		{
			float minchangedisorientation = 0;
			float minchangeerror = 0;
			int64_t minchangeindex = 0;
			int64_t minchangeiter = 0;
			float olderror = 0;
			float newerror = 0;
			uint64_t progInt = 0;

			do
			{
				QString ss = QObject::tr("Aligning Anisotropic Sections || Correcting Shifts || Iteration %1").arg(++progInt);;
				notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
				if (getCancel() == true)
				{
					return;
				}

				olderror = curerror;
				for (uint64_t iter = 1; iter < dims[2]; iter++)
				{
					float newminerror = std::numeric_limits<float>::max();
					float newmindisorientation = std::numeric_limits<float>::max();
					uint64_t newminindex = 0;
					for (uint64_t index = curindex[iter] + 1; index < maxstoredshifts; index++)
					{
						// recompute error for the configuration with this candidate changed
						if (xneedshifts.size() == 1)
						{
							newerror = compute_error1(iter, index, xneedshifts[0], yneedshifts[0], newxshift, newyshift, curindex);
						}
						else if (xneedshifts.size() > 1)
						{
							newerror = compute_error2(iter, index, xshiftsest, yshiftsest, newxshift, newyshift, curindex);
						}

						// compare the new error with the best current error
						if (newerror < curerror &&
							mindisorientation[iter][index] / mindisorientation[iter][0] < newmindisorientation)
						{
							newminerror = newerror;
							newminindex = index;
							newmindisorientation = mindisorientation[iter][index] / mindisorientation[iter][0];
						}
					}
					// assign best error, corresponding index and disorientation value for this slice
					changeerror[iter] = newminerror;
					changeindex[iter] = newminindex;
					changedisorientation[iter] = newmindisorientation;
				}

				// among all slices, find the best candidate (with minimum disorientation change)
				minchangedisorientation = std::numeric_limits<float>::max() - 1;
				minchangeerror = std::numeric_limits<float>::max();
				minchangeindex = 0;
				minchangeiter = 0;
				for (uint64_t iter = 1; iter < dims[2]; iter++)
				{
					if (changeerror[iter] < curerror &&
						(changedisorientation[iter] < minchangedisorientation ||
						(changedisorientation[iter] == minchangedisorientation &&
						llabs(newxshift[iter][changeindex[iter]]) + llabs(newyshift[iter][changeindex[iter]]) < llabs(newxshift[iter][minchangeindex]) + llabs(newyshift[iter][minchangeindex]))))
					{
						minchangeiter = iter;
						minchangeindex = changeindex[iter];
						minchangedisorientation = changedisorientation[iter];
						minchangeerror = changeerror[iter];
					}
				}

				if (minchangeerror < curerror && minchangeerror >= tolerance)
				{
					// assign the best candidate
					changedisorientation[minchangeiter] = minchangedisorientation;
					curindex[minchangeiter] = minchangeindex;
					// reassign current error
					curerror = minchangeerror;
				}

			} while (minchangedisorientation < std::numeric_limits<float>::max() - 1 && curerror < olderror && curerror > tolerance);
		}
	}


	if (getWriteAlignmentShifts() == true)
	{
		std::ofstream outFile;
		outFile.open(getAlignmentShiftFileName().toLatin1().data());
		for (uint64_t iter = 1; iter < dims[2]; iter++)
		{
			slice = (dims[2] - 1) - iter;
			xshifts[iter] = xshifts[iter - 1] + newxshift[iter][curindex[iter]];
			yshifts[iter] = yshifts[iter - 1] + newyshift[iter][curindex[iter]];
			outFile << slice << "	" << slice + 1 << "	" << newxshift[iter][curindex[iter]] << "	" << newyshift[iter][curindex[iter]] << "	" << xshifts[iter] << "	" << yshifts[iter] << "\n";
		}
		outFile.close();
	}

	m->getAttributeMatrix(getCellAttributeMatrixName())->removeAttributeArray(DREAM3D::CellData::FeatureIds);

}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void WarpRegularGrid::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m;
  if (m_SaveAsNewDataContainer == false) { m = getDataContainerArray()->getDataContainer(getCellAttributeMatrixPath().getDataContainerName()); }
  else { m = getDataContainerArray()->getDataContainer(getNewDataContainerName()); }

  AttributeMatrix::Pointer cellAttrMat = m->getAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
  AttributeMatrix::Pointer newCellAttrMat = cellAttrMat->deepCopy();

  size_t dims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(dims);
  float res[3] = { 0.0f, 0.0f, 0.0f };
  m->getGeometryAs<ImageGeom>()->getResolution(res);
  size_t totalPoints = m->getGeometryAs<ImageGeom>()->getNumberOfElements();

  float x = 0.0f, y = 0.0f, z = 0.0f;
  float newX = 0.0f, newY = 0.0f;
  int col = 0.0f, row = 0.0f, plane = 0.0f;
  size_t index;
  size_t index_old;
  std::vector<size_t> newindicies(totalPoints);
  std::vector<bool> goodPoint(totalPoints, true);

  for (size_t i = 0; i < dims[2]; i++)
  {
    QString ss = QObject::tr("Warping Data - %1 Percent Complete").arg(((float)i / dims[2]) * 100);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    for (size_t j = 0; j < dims[1]; j++)
    {
      for (size_t k = 0; k < dims[0]; k++)
      {
        x = static_cast<float>((k * res[0]));
        y = static_cast<float>((j * res[1]));
        z = static_cast<float>((i * res[2]));
        index = (i * dims[0] * dims[1]) + (j * dims[0]) + k;

        determine_warped_coordinates(x, y, newX, newY);
        col = newX / res[0];
        row = newY / res[1];
        plane = i;

        index_old = (plane * dims[0] * dims[1]) + (row * dims[0]) + col;
        newindicies[index] = index_old;
        if (col > 0 && col < dims[0] && row > 0 && row < dims[1]) { goodPoint[index] = true; }
        else { goodPoint[index] = false; }
      }
    }
  }

  QList<QString> voxelArrayNames = cellAttrMat->getAttributeArrayNames();
  for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
  {
    IDataArray::Pointer p = cellAttrMat->getAttributeArray(*iter);
    // Make a copy of the 'p' array that has the same name. When placed into
    // the data container this will over write the current array with
    // the same name. At least in theory
    IDataArray::Pointer data = p->createNewArray(p->getNumberOfTuples(), p->getComponentDimensions(), p->getName());
    data->resize(totalPoints);
    void* source = NULL;
    void* destination = NULL;
    size_t newIndicies_I = 0;
    int nComp = data->getNumberOfComponents();
    for (size_t i = 0; i < static_cast<size_t>(totalPoints); i++)
    {
      newIndicies_I = newindicies[i];

      if(goodPoint[i] == true)
      {
        source = p->getVoidPointer((nComp * newIndicies_I));
        destination = data->getVoidPointer((data->getNumberOfComponents() * i));
        ::memcpy(destination, source, p->getTypeSize() * data->getNumberOfComponents());
      }
      else
      {
        int var = 0;
        data->initializeTuple(i, &var);
      }
    }
    cellAttrMat->removeAttributeArray(*iter);
    newCellAttrMat->addAttributeArray(*iter, data);
  }
  m->removeAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
  m->addAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName(), newCellAttrMat);

  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int32_t AbaqusSurfaceMeshWriter::writeFeatures(FILE* f)
{
  //*Elset, elset=Feature1
  //1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
  int32_t err = 0;

  TriangleGeom::Pointer triangleGeo = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();

  int64_t nTriangles = triangleGeo->getNumberOfTris();

  // Store all the unique Spins
  std::set<int32_t> uniqueSpins;
  for (int64_t i = 0; i < nTriangles; i++)
  {
    uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2]);
    uniqueSpins.insert(m_SurfaceMeshFaceLabels[i * 2 + 1]);
  }

  int32_t spin = 0;

  //Loop over the unique Spins
  for (std::set<int32_t>::iterator spinIter = uniqueSpins.begin(); spinIter != uniqueSpins.end(); ++spinIter )
  {
    spin = *spinIter;
    if (spin < 0) { continue; }

    fprintf(f, "*ELSET, ELSET=Feature%d\n", spin);

    {
      QString ss = QObject::tr("Writing ELSET for Feature Id %1").arg(spin);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }

    // Loop over all the triangles for this spin
    int64_t lineCount = 0;
    for (int64_t t = 0; t < nTriangles; ++t)
    {
      if (m_SurfaceMeshFaceLabels[t * 2] != spin && m_SurfaceMeshFaceLabels[t * 2 + 1] != spin)
      {
        continue; // We do not match either spin so move to the next triangle
      }

      // Only print 15 Triangles per line
      if (lineCount == 15)
      {
        fprintf (f, ", %lld\n", (long long int)(t));
        lineCount = 0;
      }
      else if(lineCount == 0) // First value on the line
      {
        fprintf(f, "%lld", (long long int)(t));
        lineCount++;
      }
      else
      {
        fprintf(f, ", %lld", (long long int)(t));
        lineCount++;
      }

    }
    // Make sure we have a new line at the end of the section
    if (lineCount != 0)
    {
      fprintf(f, "\n");
    }
  }
  return err;
}
Example #15
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AlignSections::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  size_t udims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
  typedef int32_t DimType;
#else
  typedef int64_t DimType;
#endif
  DimType dims[3] =
  {
    static_cast<DimType>(udims[0]),
    static_cast<DimType>(udims[1]),
    static_cast<DimType>(udims[2]),
  };

  DimType slice = 0;
  DimType xspot = 0, yspot = 0;
  DimType newPosition = 0;
  DimType currentPosition = 0;

  std::vector<int64_t> xshifts(dims[2], 0);
  std::vector<int64_t> yshifts(dims[2], 0);

  find_shifts(xshifts, yshifts);

  if (getSubtractBackground())
  {
    /**fit x and y shifts to lines
     *
     * y = mx + b
     *
     * m = (n*sum(x_i * y_i) - sum(x_i) * sum(y_i)) / (n*sum(x_i^2)-sum(x_i)^2
     *
     * b = (sum(y_i)-m*sum(x_i))/n
     *
     */

    // same for both
    double sumX = 0.0; // sum(x_i)
    double sumX_2 = 0.0; // sum(x_i^2)

    // x shift line
    double x_sumY = 0.0; // sum(y_i)
    double x_sumXY = 0.0; // sum(x_i * y_i)

    // y shift line
    double y_sumY = 0.0; // sum(y_i)
    double y_sumXY = 0.0; // sum(x_i * y_i)

    for (DimType iter = 0; iter < dims[2]; iter++)
    {
      slice = static_cast<DimType>( (dims[2] - 1) - iter );
      sumX = static_cast<double>(sumX + iter);
      sumX_2 = static_cast<double>(sumX_2 + iter * iter);
      x_sumY = static_cast<double>(x_sumY + xshifts[iter]);
      x_sumXY = static_cast<double>(x_sumXY + iter * xshifts[iter]);
      y_sumY = static_cast<double>(y_sumY + yshifts[iter]);
      y_sumXY = static_cast<double>(y_sumXY + iter * yshifts[iter]);
    }

    double mx = static_cast<double>((dims[2] * x_sumXY - x_sumXY) / (dims[2] * sumX_2 - sumX));
    double my = static_cast<double>((dims[2] * y_sumXY - y_sumXY) / (dims[2] * sumX_2 - sumX));

    // adjust shifts so that fit line has 0 slope (~ends of the sample are fixed)
    for (DimType iter = 1; iter < dims[2]; iter++)
    {
      slice = (dims[2] - 1) - iter;
      xshifts[iter] = static_cast<int64_t>(xshifts[iter] - iter * mx);
      yshifts[iter] = static_cast<int64_t>(yshifts[iter] - iter * my);
    }
  }

  QList<QString> voxelArrayNames = m->getAttributeMatrix(getCellAttributeMatrixName())->getAttributeArrayNames();
  DimType progIncrement = dims[2] / 100;
  DimType prog = 1;
  DimType progressInt = 0;

  for (DimType i = 1; i < dims[2]; i++)
  {
    if (i > prog)
    {

      progressInt = ((float)i / dims[2]) * 100.0f;
      QString ss = QObject::tr("Transferring Cell Data || %1% Complete").arg(progressInt);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
      prog = prog + progIncrement;
    }
    if (getCancel() == true)
    {
      return;
    }
    slice = (dims[2] - 1) - i;
    for (DimType l = 0; l < dims[1]; l++)
    {
      for (DimType n = 0; n < dims[0]; n++)
      {
        if (yshifts[i] >= 0) { yspot = l; }
        else if (yshifts[i] < 0) { yspot = dims[1] - 1 - l; }
        if (xshifts[i] >= 0) { xspot = n; }
        else if (xshifts[i] < 0) { xspot = dims[0] - 1 - n; }
        newPosition = (slice * dims[0] * dims[1]) + (yspot * dims[0]) + xspot;
        currentPosition = (slice * dims[0] * dims[1]) + ((yspot + yshifts[i]) * dims[0]) + (xspot + xshifts[i]);
        if ((yspot + yshifts[i]) >= 0 && (yspot + yshifts[i]) <= dims[1] - 1 && (xspot + xshifts[i]) >= 0
            && (xspot + xshifts[i]) <= dims[0] - 1)
        {
          for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
          {
            IDataArray::Pointer p = m->getAttributeMatrix(getCellAttributeMatrixName())->getAttributeArray(*iter);
            p->copyTuple(currentPosition, newPosition);
          }
        }
        if ((yspot + yshifts[i]) < 0 || (yspot + yshifts[i]) > dims[1] - 1 || (xspot + xshifts[i]) < 0
            || (xspot + xshifts[i]) > dims[0] - 1)
        {
          for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
          {
            IDataArray::Pointer p = m->getAttributeMatrix(getCellAttributeMatrixName())->getAttributeArray(*iter);
            p->initializeTuple(newPosition, 0);
          }
        }
      }
    }
  }

  // If there is an error set this to something negative and also set a message
  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FindFeatureReferenceCAxisMisorientations::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(m_FeatureIdsArrayPath.getDataContainerName());
  size_t totalPoints = m_FeatureIdsPtr.lock()->getNumberOfTuples();
  size_t totalFeatures = m_AvgCAxesPtr.lock()->getNumberOfTuples();

  int32_t avgMisoComps = 3;
  QVector<size_t> dims(1, avgMisoComps);
  FloatArrayType::Pointer avgmisoPtr = FloatArrayType::CreateArray(totalFeatures, dims, "_INTERNAL_USE_ONLY_AvgMiso_Temp");
  avgmisoPtr->initializeWithZeros();
  float* avgmiso = avgmisoPtr->getPointer(0);

  QuatF q1 = QuaternionMathF::New();
  QuatF* quats = reinterpret_cast<QuatF*>(m_Quats);

  float w = 0.0f;
  size_t udims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
  typedef uint32_t DimType;
  uint32_t maxUInt32 = std::numeric_limits<uint32_t>::max();
  // We have more points than can be allocated on a 32 bit machine. Assert Now.
  if(totalPoints > maxUInt32)
  {
    QString ss = QObject::tr("The volume is too large for a 32 bit machine. Try reducing the input volume size. Total Voxels: %1").arg(totalPoints);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    return;
  }
#else
  typedef int64_t DimType;
#endif

  DimType xPoints = static_cast<DimType>(udims[0]);
  DimType yPoints = static_cast<DimType>(udims[1]);
  DimType zPoints = static_cast<DimType>(udims[2]);
  DimType point = 0;

  float g1[3][3] = { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } };
  float g1t[3][3] = { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } };
  float caxis[3] = {0.0f, 0.0f, 1.0f};
  float c1[3] = {0.0f, 0.0f, 0.0f};
  float AvgCAxis[3] = {0.0f, 0.0f, 0.0f};
  size_t index = 0;

  for (DimType col = 0; col < xPoints; col++)
  {
    for (DimType row = 0; row < yPoints; row++)
    {
      for (DimType plane = 0; plane < zPoints; plane++)
      {
        point = (plane * xPoints * yPoints) + (row * xPoints) + col;
        if (m_FeatureIds[point] > 0 && m_CellPhases[point] > 0)
        {
          QuaternionMathF::Copy(quats[point], q1);
          FOrientArrayType om(9);
          FOrientTransformsType::qu2om(FOrientArrayType(q1), om);
          om.toGMatrix(g1);
          // transpose the g matricies so when caxis is multiplied by it
          // it will give the sample direction that the caxis is along
          MatrixMath::Transpose3x3(g1, g1t);
          MatrixMath::Multiply3x3with3x1(g1t, caxis, c1);
          // normalize so that the magnitude is 1
          MatrixMath::Normalize3x1(c1);

          AvgCAxis[0] = m_AvgCAxes[3 * m_FeatureIds[point]];
          AvgCAxis[1] = m_AvgCAxes[3 * m_FeatureIds[point] + 1];
          AvgCAxis[2] = m_AvgCAxes[3 * m_FeatureIds[point] + 2];
          // normalize so that the magnitude is 1
          MatrixMath::Normalize3x1(AvgCAxis);
          w = GeometryMath::CosThetaBetweenVectors(c1, AvgCAxis);
          DREAM3DMath::boundF(w, -1, 1);
          w = acosf(w);
          w = w * DREAM3D::Constants::k_180OverPi;
          if (w > 90.0) { w = 180.0 - w; }

          m_FeatureReferenceCAxisMisorientations[point] = w;
          index = m_FeatureIds[point] * avgMisoComps;
          avgmiso[index]++;
          avgmiso[index + 1] += w;
        }
        if (m_FeatureIds[point] == 0 || m_CellPhases[point] == 0)
        {
          m_FeatureReferenceCAxisMisorientations[point] = 0;
        }
      }
    }
  }

  for (size_t i = 1; i < totalFeatures; i++)
  {
    if (i % 1000 == 0)
    {
      QString ss = QObject::tr("Working On Feature %1 of %2").arg(i).arg(totalFeatures);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }
    index = i * avgMisoComps;
    m_FeatureAvgCAxisMisorientations[i] = avgmiso[index + 1] / avgmiso[index];
    if (avgmiso[index] == 0) { m_FeatureAvgCAxisMisorientations[i] = 0.0; }
  }


  int32_t gNum = 0;
  for (size_t j = 0; j < totalPoints; j++)
  {
    gNum = m_FeatureIds[j];
    avgmiso[(gNum * avgMisoComps) + 2] += ((m_FeatureReferenceCAxisMisorientations[j] - m_FeatureAvgCAxisMisorientations[gNum]) * (m_FeatureReferenceCAxisMisorientations[j] - m_FeatureAvgCAxisMisorientations[gNum]));
  }

  for (size_t i = 1; i < totalFeatures; i++)
  {
    index = i * avgMisoComps;
    m_FeatureStdevCAxisMisorientations[i] = sqrtf((1 / avgmiso[index]) * avgmiso[index + 2]);
  }

  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FindFeatureClustering::find_clustering()
{
  bool writeErrorFile = true;
  std::ofstream outFile;

  if (m_ErrorOutputFile.isEmpty() == false)
  {
    outFile.open(m_ErrorOutputFile.toLatin1().data(), std::ios_base::binary);
    writeErrorFile = true;
  }

  float x = 0.0f, y = 0.0f, z = 0.0f;
  float xn = 0.0f, yn = 0.0f, zn = 0.0f;
  float r = 0.0f;

  int32_t bin = 0;
  int32_t ensemble = 0;
  int32_t totalPPTfeatures = 0;
  float min = std::numeric_limits<float>::max();
  float max = 0.0f;
  float value = 0.0f;
  float sizex = 0.0f, sizey = 0.0f, sizez = 0.0f, totalvol = 0.0f, totalpoints = 0.0f;
  float normFactor = 0.0f;

  std::vector<std::vector<float> > clusteringlist;
  std::vector<float> oldcount(m_NumberOfBins);
  std::vector<float> randomRDF;

  size_t totalFeatures = m_FeaturePhasesPtr.lock()->getNumberOfTuples();
  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(m_EquivalentDiametersArrayPath.getDataContainerName());

  size_t dims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(dims);

  sizex = float(dims[0]) * m->getGeometryAs<ImageGeom>()->getXRes();
  sizey = float(dims[1]) * m->getGeometryAs<ImageGeom>()->getYRes();
  sizez = float(dims[2]) * m->getGeometryAs<ImageGeom>()->getZRes();
  totalvol = sizex * sizey * sizez;
  totalpoints = static_cast<float>(dims[0] * dims[1] * dims[2]);

  // initialize boxdims and boxres vectors
  std::vector<float> boxdims(3);
  boxdims[0] = sizex;
  boxdims[1] = sizey;
  boxdims[2] = sizez;

  std::vector<float> boxres(3);
  boxres[0] = m->getGeometryAs<ImageGeom>()->getXRes();
  boxres[1] = m->getGeometryAs<ImageGeom>()->getYRes();
  boxres[2] = m->getGeometryAs<ImageGeom>()->getZRes();

  for (size_t i = 1; i < totalFeatures; i++)
  {
    if (m_FeaturePhases[i] == m_PhaseNumber) {totalPPTfeatures++;}
  }

  clusteringlist.resize(totalFeatures);

  for (size_t i = 1; i < totalFeatures; i++)
  {
    if (m_FeaturePhases[i] == m_PhaseNumber)
    {
      if (i % 1000 == 0)
      {
        QString ss = QObject::tr("Working on Feature %1 of %2").arg(i).arg(totalPPTfeatures);
        notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
      }

      x = m_Centroids[3 * i];
      y = m_Centroids[3 * i + 1];
      z = m_Centroids[3 * i + 2];

      for (size_t j = i + 1; j < totalFeatures; j++)
      {
        if (m_FeaturePhases[i] == m_FeaturePhases[j])
        {
          xn = m_Centroids[3 * j];
          yn = m_Centroids[3 * j + 1];
          zn = m_Centroids[3 * j + 2];

          r = sqrtf((x - xn) * (x - xn) + (y - yn) * (y - yn) + (z - zn) * (z - zn));

          clusteringlist[i].push_back(r);
          clusteringlist[j].push_back(r);

          if (writeErrorFile == true && m_FeaturePhases[j] == 2)
          {
            outFile << r << "\n" << r << "\n";
          }
        }
      }
    }
  }

  for (size_t i = 1; i < totalFeatures; i++)
  {
    for (size_t j = 0; j < clusteringlist[i].size(); j++)
    {
      if (m_FeaturePhases[i] == m_PhaseNumber)
      {
        value = clusteringlist[i][j];
        if (value > max) { max = value; }
        if (value < min) { min = value; }
      }
    }
  }

  float stepsize = (max - min) / m_NumberOfBins;

  m_MaxMinArray[(m_PhaseNumber * 2)] = max;
  m_MaxMinArray[(m_PhaseNumber * 2) + 1] = min;

  for (size_t i = 1; i < totalFeatures; i++)
  {
    for (size_t j = 0; j < clusteringlist[i].size(); j++)
    {
      if (m_FeaturePhases[i] == m_PhaseNumber)
      {
        if (m_RemoveBiasedFeatures == false || m_BiasedFeatures[i] == false)
        {
          ensemble = m_FeaturePhases[i];
          bin = (clusteringlist[i][j] - min) / stepsize;
          if(bin >= m_NumberOfBins) { bin = m_NumberOfBins - 1; }
          m_NewEnsembleArray[(m_NumberOfBins * ensemble) + bin]++;
        }
      }
    }
  }

  // Generate random distribution based on same box size and same stepsize
  float max_box_distance = sqrtf((sizex * sizex) + (sizey * sizey) + (sizez * sizez));
  int32_t current_num_bins = ceilf((max_box_distance - min) / (stepsize));

  randomRDF.resize(current_num_bins + 1);
  // Call this function to generate the random distribution, which is normalized by the total number of distances
  randomRDF = RadialDistributionFunction::GenerateRandomDistribution(min, max, m_NumberOfBins, boxdims, boxres);

  // Scale the random distribution by the number of distances in this particular instance
  normFactor = totalPPTfeatures * (totalPPTfeatures - 1);
  for (size_t i = 0; i < randomRDF.size(); i++)
  {
    randomRDF[i] = randomRDF[i] * normFactor;
  }

  for (size_t i = 0; i < m_NumberOfBins; i++)
  {
    oldcount[i] = m_NewEnsembleArray[(m_NumberOfBins * m_PhaseNumber) + i];
    m_NewEnsembleArray[(m_NumberOfBins * m_PhaseNumber) + i] = oldcount[i] / randomRDF[i + 1];
  }

//    std::ofstream testFile3;
//    testFile3.open("/Users/Shared/Data/PW_Work/OUTFILE/normalized_target.txt");
//    for (size_t i = 0; i < m_NumberOfBins; i++)
//    {
//    testFile3 << "\n" << m_NewEnsembleArray[(m_NumberOfBins*m_PhaseNumber) + i];
//    }
//    testFile3.close();

//    std::ofstream testFile4;
//    testFile4.open("/Users/Shared/Data/PW_Work/OUTFILE/randomrdf_target.txt");
//    for (size_t i = 0; i < randomRDF.size(); i++)
//    {
//    testFile4 << "\n" << randomRDF[i];
//    }
//    testFile4.close();

//    std::ofstream testFile7;
//    testFile7.open("/Users/Shared/Data/PW_Work/OUTFILE/targetRaw.txt");
//    for (size_t i = 0; i < oldcount.size(); i++)
//    {
//    testFile7 << "\n" << oldcount[i];
//    }
//    testFile7.close();

  for (size_t i = 1; i < totalFeatures; i++)
  {
    // Set the vector for each list into the Clustering Object
    NeighborList<float>::SharedVectorType sharedClustLst(new std::vector<float>);
    sharedClustLst->assign(clusteringlist[i].begin(), clusteringlist[i].end());
    m_ClusteringList.lock()->setList(static_cast<int>(i), sharedClustLst);
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AlignSectionsMutualInformation::find_shifts(std::vector<int64_t>& xshifts, std::vector<int64_t>& yshifts)
{
  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  int64_t totalPoints = m->getAttributeMatrix(getCellAttributeMatrixName())->getNumTuples();
  Int32ArrayType::Pointer p = Int32ArrayType::CreateArray((totalPoints * 1), "_INTERNAL_USE_ONLY_MIFeatureIds");
  m_FeatureIds = p->getPointer(0);

  std::ofstream outFile;
  if (getWriteAlignmentShifts() == true)
  {
    outFile.open(getAlignmentShiftFileName().toLatin1().data());
  }

  size_t udims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
  typedef int32_t DimType;
#else
  typedef int64_t DimType;
#endif
  DimType dims[3] =
  {
    static_cast<DimType>(udims[0]),
    static_cast<DimType>(udims[1]),
    static_cast<DimType>(udims[2]),
  };

  float disorientation = 0.0f;
  float mindisorientation = std::numeric_limits<float>::max();
  float** mutualinfo12 = NULL;
  float* mutualinfo1 = NULL;
  float* mutualinfo2 = NULL;
  int32_t featurecount1 = 0, featurecount2 = 0;
  int64_t newxshift = 0;
  int64_t newyshift = 0;
  int64_t oldxshift = 0;
  int64_t oldyshift = 0;
  float count = 0.0f;
  DimType slice = 0;

  int32_t refgnum = 0, curgnum = 0;
  DimType refposition = 0;
  DimType curposition = 0;

  form_features_sections();

  std::vector<std::vector<float> >  misorients;
  misorients.resize(dims[0]);
  for (DimType a = 0; a < dims[0]; a++)
  {
    misorients[a].assign(dims[1], 0.0f);
  }

  for (DimType iter = 1; iter < dims[2]; iter++)
  {
    QString ss = QObject::tr("Aligning Sections || Determining Shifts || %1% Complete").arg(((float)iter / dims[2]) * 100);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    mindisorientation = std::numeric_limits<float>::max();
    slice = (dims[2] - 1) - iter;
    featurecount1 = featurecounts[slice];
    featurecount2 = featurecounts[slice + 1];
    mutualinfo12 = new float *[featurecount1];
    mutualinfo1 = new float[featurecount1];
    mutualinfo2 = new float[featurecount2];

    for (int32_t a = 0; a < featurecount1; a++)
    {
      mutualinfo1[a] = 0.0f;
      mutualinfo12[a] = new float[featurecount2];
      for (int32_t b = 0; b < featurecount2; b++)
      {
        mutualinfo12[a][b] = 0.0f;
        mutualinfo2[b] = 0.0f;
      }
    }
    oldxshift = -1;
    oldyshift = -1;
    newxshift = 0;
    newyshift = 0;
    for (DimType a = 0; a < dims[0]; a++)
    {
      for (DimType b = 0; b < dims[1]; b++)
      {
        misorients[a][b] = 0;
      }
    }
    while (newxshift != oldxshift || newyshift != oldyshift)
    {
      oldxshift = newxshift;
      oldyshift = newyshift;
      for (int32_t j = -3; j < 4; j++)
      {
        for (int32_t k = -3; k < 4; k++)
        {
          disorientation = 0;
          count = 0;
          if (misorients[k + oldxshift + dims[0] / 2][j + oldyshift + dims[1] / 2] == 0 && abs(k + oldxshift) < (dims[0] / 2)
              && (j + oldyshift) < (dims[1] / 2))
          {
            for (DimType l = 0; l < dims[1]; l = l + 4)
            {
              for (DimType n = 0; n < dims[0]; n = n + 4)
              {
                if ((l + j + oldyshift) >= 0 && (l + j + oldyshift) < dims[1] && (n + k + oldxshift) >= 0 && (n + k + oldxshift) < dims[0])
                {
                  refposition = ((slice + 1) * dims[0] * dims[1]) + (l * dims[0]) + n;
                  curposition = (slice * dims[0] * dims[1]) + ((l + j + oldyshift) * dims[0]) + (n + k + oldxshift);
                  refgnum = m_FeatureIds[refposition];
                  curgnum = m_FeatureIds[curposition];
                  if (curgnum >= 0 && refgnum >= 0)
                  {
                    mutualinfo12[curgnum][refgnum]++;
                    mutualinfo1[curgnum]++;
                    mutualinfo2[refgnum]++;
                    count++;
                  }
                }
                else
                {
                  mutualinfo12[0][0]++;
                  mutualinfo1[0]++;
                  mutualinfo2[0]++;
                }
              }
            }
            float ha = 0.0f;
            float hb = 0.0f;
            float hab = 0.0f;
            for (int32_t b = 0; b < featurecount1; b++)
            {
              mutualinfo1[b] = mutualinfo1[b] / count;
              if (mutualinfo1[b] != 0) { ha = ha + mutualinfo1[b] * logf(mutualinfo1[b]); }
            }
            for (int32_t c = 0; c < featurecount2; c++)
            {
              mutualinfo2[c] = mutualinfo2[c] / float(count);
              if (mutualinfo2[c] != 0) { hb = hb + mutualinfo2[c] * logf(mutualinfo2[c]); }
            }
            for (int32_t b = 0; b < featurecount1; b++)
            {
              for (int32_t c = 0; c < featurecount2; c++)
              {
                mutualinfo12[b][c] = mutualinfo12[b][c] / count;
                if (mutualinfo12[b][c] != 0) { hab = hab + mutualinfo12[b][c] * logf(mutualinfo12[b][c]); }
                float value = 0.0f;
                if (mutualinfo1[b] > 0 && mutualinfo2[c] > 0) { value = (mutualinfo12[b][c] / (mutualinfo1[b] * mutualinfo2[c])); }
                if (value != 0) { disorientation = disorientation + (mutualinfo12[b][c] * logf(value)); }
              }
            }
            for (int32_t b = 0; b < featurecount1; b++)
            {
              for (int32_t c = 0; c < featurecount2; c++)
              {
                mutualinfo12[b][c] = 0.0f;
                mutualinfo1[b] = 0.0f;
                mutualinfo2[c] = 0.0f;
              }
            }
            disorientation = 1.0f / disorientation;
            misorients[k + oldxshift + dims[0] / 2][j + oldyshift + dims[1] / 2] = disorientation;
            if (disorientation < mindisorientation)
            {
              newxshift = k + oldxshift;
              newyshift = j + oldyshift;
              mindisorientation = disorientation;
            }
          }
        }
      }
    }
    xshifts[iter] = xshifts[iter - 1] + newxshift;
    yshifts[iter] = yshifts[iter - 1] + newyshift;
    if (getWriteAlignmentShifts() == true)
    {
      outFile << slice << "	" << slice + 1 << "	" << newxshift << "	" << newyshift << "	" << xshifts[iter] << "	" << yshifts[iter] << "\n";
    }
    delete[] mutualinfo1;
    delete[] mutualinfo2;
    for (int32_t i = 0; i < featurecount1; i++)
    {
      delete mutualinfo12[i];
    }
    delete[] mutualinfo12;
    mutualinfo1 = NULL;
    mutualinfo2 = NULL;
    mutualinfo12 = NULL;
  }

  m->getAttributeMatrix(getCellAttributeMatrixName())->removeAttributeArray(DREAM3D::CellData::FeatureIds);

  if (getWriteAlignmentShifts() == true)
  {
    outFile.close();
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AlignSections::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  size_t dims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(dims);

  int64_t xspot = 0, yspot = 0;
  int64_t newPosition = 0;
  int64_t currentPosition = 0;

  std::vector<int64_t> xshifts(dims[2], 0);
  std::vector<int64_t> yshifts(dims[2], 0);

  find_shifts(xshifts, yshifts);


  QList<QString> voxelArrayNames = m->getAttributeMatrix(getCellAttributeMatrixName())->getAttributeArrayNames();
  size_t progIncrement = dims[2] / 100;
  size_t prog = 1;
  size_t progressInt = 0;
  size_t slice = 0;

  for (size_t i = 1; i < dims[2]; i++)
  {
    if (i > prog)
    {

      progressInt = ((float)i / dims[2]) * 100.0f;
      QString ss = QObject::tr("Transferring Cell Data || %1% Complete").arg(progressInt);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
      prog = prog + progIncrement;
    }
    if (getCancel() == true)
    {
      return;
    }
    slice = (dims[2] - 1) - i;
    for (size_t l = 0; l < dims[1]; l++)
    {
      for (size_t n = 0; n < dims[0]; n++)
      {
        if (yshifts[i] >= 0) { yspot = l; }
        else if (yshifts[i] < 0) { yspot = dims[1] - 1 - l; }
        if (xshifts[i] >= 0) { xspot = n; }
        else if (xshifts[i] < 0) { xspot = dims[0] - 1 - n; }
        newPosition = (slice * dims[0] * dims[1]) + (yspot * dims[0]) + xspot;
        currentPosition = (slice * dims[0] * dims[1]) + ((yspot + yshifts[i]) * dims[0]) + (xspot + xshifts[i]);
        if ((yspot + yshifts[i]) >= 0 && (yspot + yshifts[i]) <= static_cast<int64_t>(dims[1]) - 1 && (xspot + xshifts[i]) >= 0
            && (xspot + xshifts[i]) <= static_cast<int64_t>(dims[0]) - 1)
        {
          for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
          {
            IDataArray::Pointer p = m->getAttributeMatrix(getCellAttributeMatrixName())->getAttributeArray(*iter);
            p->copyTuple( static_cast<size_t>(currentPosition), static_cast<size_t>(newPosition));
          }
        }
        if ((yspot + yshifts[i]) < 0 || (yspot + yshifts[i]) > static_cast<int64_t>(dims[1] - 1) || (xspot + xshifts[i]) < 0
            || (xspot + xshifts[i]) > static_cast<int64_t>(dims[0]) - 1)
        {
          for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
          {
            IDataArray::Pointer p = m->getAttributeMatrix(getCellAttributeMatrixName())->getAttributeArray(*iter);
            EXECUTE_FUNCTION_TEMPLATE(this, initializeArrayValues, p, p, newPosition)
          }
        }
      }
    }
  }

  // If there is an error set this to something negative and also set a message
  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FindBoundingBoxFeatures::find_boundingboxfeatures()
{
  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getCentroidsArrayPath().getDataContainerName());

  size_t size = m_CentroidsPtr.lock()->getNumberOfTuples();
  float boundbox[7] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
  float coords[7] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
  float x = 0.0f;
  float y = 0.0f;
  float z = 0.0f;
  float dist[7] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, };
  float mindist = std::numeric_limits<float>::max();
  int32_t sidetomove = 0;
  int32_t move = 0;

  // loop first to determine number of phases if calcByPhase is being used
  int32_t numPhases = 1;
  if (m_CalcByPhase == true)
  {
    for (size_t i = 1; i < size; i++)
    {
      if (m_Phases[i] > numPhases) { numPhases = m_Phases[i]; }
    }
  }
  for (int32_t iter = 1; iter <= numPhases; iter++)
  {
    if (m_CalcByPhase == true)
    {
      QString ss = QObject::tr("Working on Phase %1 of %2").arg(iter).arg(numPhases);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }
    // reset boundbox for each phase
    boundbox[1] = 0;
    boundbox[2] = m->getGeometryAs<ImageGeom>()->getXPoints() * m->getGeometryAs<ImageGeom>()->getXRes();
    boundbox[3] = 0;
    boundbox[4] = m->getGeometryAs<ImageGeom>()->getYPoints() * m->getGeometryAs<ImageGeom>()->getYRes();
    boundbox[5] = 0;
    boundbox[6] = m->getGeometryAs<ImageGeom>()->getZPoints() * m->getGeometryAs<ImageGeom>()->getZRes();
    for (size_t i = 1; i < size; i++)
    {
      if (m_SurfaceFeatures[i] == true && (m_CalcByPhase == false || m_Phases[i] == iter))
      {
        move = 1;
        mindist = std::numeric_limits<float>::max();
        x = m_Centroids[3 * i];
        y = m_Centroids[3 * i + 1];
        z = m_Centroids[3 * i + 2];
        coords[1] = x;
        coords[2] = x;
        coords[3] = y;
        coords[4] = y;
        coords[5] = z;
        coords[6] = z;
        for (int32_t j = 1; j < 7; j++)
        {
          dist[j] = std::numeric_limits<float>::max();
          if (j % 2 == 1)
          {
            if (coords[j] > boundbox[j]) { dist[j] = (coords[j] - boundbox[j]); }
            if (coords[j] <= boundbox[j]) { move = 0; }
          }
          if (j % 2 == 0)
          {
            if (coords[j] < boundbox[j]) { dist[j] = (boundbox[j] - coords[j]); }
            if (coords[j] >= boundbox[j]) { move = 0; }
          }
          if (dist[j] < mindist) { mindist = dist[j], sidetomove = j; }
        }
        if (move == 1) { boundbox[sidetomove] = coords[sidetomove]; }
      }
    }
    for (size_t j = 1; j < size; j++)
    {
      if (m_CalcByPhase == false || m_Phases[j] == iter)
      {
        if (m_Centroids[3 * j] <= boundbox[1])
        { m_BiasedFeatures[j] = true; }
        if (m_Centroids[3 * j] >= boundbox[2])
        { m_BiasedFeatures[j] = true; }
        if (m_Centroids[3 * j + 1] <= boundbox[3])
        { m_BiasedFeatures[j] = true; }
        if (m_Centroids[3 * j + 1] >= boundbox[4])
        { m_BiasedFeatures[j] = true; }
        if (m_Centroids[3 * j + 2] <= boundbox[5])
        { m_BiasedFeatures[j] = true; }
        if (m_Centroids[3 * j + 2] >= boundbox[6])
        { m_BiasedFeatures[j] = true; }
      }
    }
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FeatureFaceCurvatureFilter::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName());

  // Get our Reference counted Array of Face Structures
  TriangleGeom::Pointer triangleGeom = sm->getGeometryAs<TriangleGeom>();

  // Just to double check we have everything.
  int64_t numTriangles = triangleGeom->getNumberOfTris();

  // Make sure the Face Connectivity is created because the FindNRing algorithm needs this and will
  // assert if the data is NOT in the SurfaceMesh Data Container
  ElementDynamicList::Pointer vertLinks = triangleGeom->getElementsContainingVert();
  if (NULL == vertLinks.get())
  {
    triangleGeom->findElementsContainingVert();
  }

  // get the QMap from the SharedFeatureFaces filter
  SharedFeatureFaces_t sharedFeatureFaces;

  int32_t maxFaceId = 0;
  for (int64_t t = 0; t < numTriangles; ++t)
  {
    if (m_SurfaceMeshFeatureFaceIds[t] > maxFaceId) { maxFaceId = m_SurfaceMeshFeatureFaceIds[t]; }
  }
  std::vector<int32_t> faceSizes(maxFaceId + 1, 0);
  // Loop through all the Triangles and assign each one to a unique Feature Face Id.
  for (int64_t t = 0; t < numTriangles; ++t)
  {
    faceSizes[m_SurfaceMeshFeatureFaceIds[t]]++;
  }

  // Allocate all the vectors that we need
  for (size_t iter = 0; iter < faceSizes.size(); ++iter)
  {
    FaceIds_t v;
    v.reserve(faceSizes[iter]);
    sharedFeatureFaces[iter] = v;
  }

  // Loop through all the Triangles and assign each one to a unique Feature Face Id.
  for(int64_t t = 0; t < numTriangles; ++t)
  {
    sharedFeatureFaces[m_SurfaceMeshFeatureFaceIds[t]].push_back(t);
  }

  m_TotalFeatureFaces = sharedFeatureFaces.size();
  m_CompletedFeatureFaces = 0;

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  tbb::task_scheduler_init init;
  bool doParallel = true;
#endif


#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  tbb::task_group* g = new tbb::task_group;
#else

#endif
  // typedef here for conveneince
  typedef SharedFeatureFaces_t::iterator SharedFeatureFaceIterator_t;

  for(SharedFeatureFaceIterator_t iter = sharedFeatureFaces.begin(); iter != sharedFeatureFaces.end(); ++iter)
  {
    QString ss = QObject::tr("Working on Face Id %1/%2").arg((*iter).first).arg(maxFaceId);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

    FaceIds_t& triangleIds = (*iter).second;
#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
    if (doParallel == true)
    {
      g->run(CalculateTriangleGroupCurvatures(m_NRing, triangleIds, m_UseNormalsForCurveFitting,
                                              m_SurfaceMeshPrincipalCurvature1sPtr.lock(), m_SurfaceMeshPrincipalCurvature2sPtr.lock(),
                                              m_SurfaceMeshPrincipalDirection1sPtr.lock(), m_SurfaceMeshPrincipalDirection2sPtr.lock(),
                                              m_SurfaceMeshGaussianCurvaturesPtr.lock(), m_SurfaceMeshMeanCurvaturesPtr.lock(), triangleGeom,
                                              m_SurfaceMeshFaceLabelsPtr.lock(),
                                              m_SurfaceMeshFaceNormalsPtr.lock(),
                                              m_SurfaceMeshTriangleCentroidsPtr.lock(),
                                              this ) );
    }
    else
#endif
    {
      CalculateTriangleGroupCurvatures curvature(m_NRing, triangleIds, m_UseNormalsForCurveFitting,
                                                 m_SurfaceMeshPrincipalCurvature1sPtr.lock(), m_SurfaceMeshPrincipalCurvature2sPtr.lock(),
                                                 m_SurfaceMeshPrincipalDirection1sPtr.lock(), m_SurfaceMeshPrincipalDirection2sPtr.lock(),
                                                 m_SurfaceMeshGaussianCurvaturesPtr.lock(), m_SurfaceMeshMeanCurvaturesPtr.lock(), triangleGeom,
                                                 m_SurfaceMeshFaceLabelsPtr.lock(),
                                                 m_SurfaceMeshFaceNormalsPtr.lock(),
                                                 m_SurfaceMeshTriangleCentroidsPtr.lock(),
                                                 this );
      curvature();
    }
  }
  // *********************** END END END END END END  ********************************************************************

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  g->wait(); // Wait for all the threads to complete before moving on.
  delete g;
#endif

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void WritePoleFigure::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(m_CellPhasesArrayPath.getDataContainerName());

  size_t dims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(dims);

  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  QDir path(getOutputPath());

  if (!path.mkpath(".") )
  {
    QString ss = QObject::tr("Error creating parent path '%1'").arg(path.absolutePath());
    setErrorCondition(-1);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  bool missingGoodVoxels = true;

  if (NULL != m_GoodVoxels)
  {
    missingGoodVoxels = false;
  }

  // Find how many phases we have by getting the number of Crystal Structures
  size_t numPoints = m->getGeometryAs<ImageGeom>()->getNumberOfElements();
  size_t numPhases = m_CrystalStructuresPtr.lock()->getNumberOfTuples();

  // Loop over all the voxels gathering the Eulers for a specific phase into an array
  for (size_t phase = 1; phase < numPhases; ++phase)
  {
    size_t count = 0;
    // First find out how many voxels we are going to have. This is probably faster to loop twice than to
    // keep allocating memory everytime we find one.
    for (size_t i = 0; i < numPoints; ++i)
    {
      if (m_CellPhases[i] == phase)
      {
        if (missingGoodVoxels == true || m_GoodVoxels[i] == true)
        {
          count++;
        }
      }
    }
    QVector<size_t> eulerCompDim(1, 3);
    FloatArrayType::Pointer subEulers = FloatArrayType::CreateArray(count, eulerCompDim, "Eulers_Per_Phase");
    subEulers->initializeWithValue(std::numeric_limits<float>::signaling_NaN());
    float* eu = subEulers->getPointer(0);

    // Now loop through the eulers again and this time add them to the subEulers Array
    count = 0;
    for (size_t i = 0; i < numPoints; ++i)
    {
      if (m_CellPhases[i] == phase)
      {
        if (missingGoodVoxels == true || m_GoodVoxels[i] == true)
        {
          eu[count * 3] = m_CellEulerAngles[i * 3];
          eu[count * 3 + 1] = m_CellEulerAngles[i * 3 + 1];
          eu[count * 3 + 2] = m_CellEulerAngles[i * 3 + 2];
          count++;
        }
      }
    }
    if (subEulers->getNumberOfTuples() == 0) { continue; } // Skip because we have no Pole Figure data

    QVector<UInt8ArrayType::Pointer> figures;

    PoleFigureConfiguration_t config;
    config.eulers = subEulers.get();
    config.imageDim = getImageSize();
    config.lambertDim = getLambertSize();
    config.numColors = getNumColors();

    QString label("Phase_");
    label.append(QString::number(phase));

    QString ss = QObject::tr("Generating Pole Figures for Phase %1").arg(phase);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

    switch(m_CrystalStructures[phase])
    {
      case Ebsd::CrystalStructure::Cubic_High:
        figures = makePoleFigures<CubicOps>(config);
        break;
      case Ebsd::CrystalStructure::Cubic_Low:
        figures = makePoleFigures<CubicLowOps>(config);
        break;
      case Ebsd::CrystalStructure::Hexagonal_High:
        figures = makePoleFigures<HexagonalOps>(config);
        break;
      case Ebsd::CrystalStructure::Hexagonal_Low:
        figures = makePoleFigures<HexagonalLowOps>(config);
        break;
      case Ebsd::CrystalStructure::Trigonal_High:
        //   figures = makePoleFigures<TrigonalOps>(config);
        notifyWarningMessage(getHumanLabel(), "Trigonal High Symmetry is not supported for Pole figures. This phase will be omitted from results", -1010);
        break;
      case Ebsd::CrystalStructure::Trigonal_Low:
        //  figures = makePoleFigures<TrigonalLowOps>(config);
        notifyWarningMessage(getHumanLabel(), "Trigonal Low Symmetry is not supported for Pole figures. This phase will be omitted from results", -1010);
        break;
      case Ebsd::CrystalStructure::Tetragonal_High:
        //  figures = makePoleFigures<TetragonalOps>(config);
        notifyWarningMessage(getHumanLabel(), "Tetragonal High Symmetry is not supported for Pole figures. This phase will be omitted from results", -1010);
        break;
      case Ebsd::CrystalStructure::Tetragonal_Low:
        //  figures = makePoleFigures<TetragonalLowOps>(config);
        notifyWarningMessage(getHumanLabel(), "Tetragonal Low Symmetry is not supported for Pole figures. This phase will be omitted from results", -1010);
        break;
      case Ebsd::CrystalStructure::OrthoRhombic:
        figures = makePoleFigures<OrthoRhombicOps>(config);
        break;
      case Ebsd::CrystalStructure::Monoclinic:
        figures = makePoleFigures<MonoclinicOps>(config);
        break;
      case Ebsd::CrystalStructure::Triclinic:
        figures = makePoleFigures<TriclinicOps>(config);
        break;
      default:
        break;

    }

    if (figures.size() == 3)
    {
      QImage combinedImage = PoleFigureImageUtilities::Create3ImagePoleFigure(figures[0].get(), figures[1].get(), figures[2].get(), config, getImageLayout());
      writeImage(combinedImage, label);
    }
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
Example #23
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void WriteStlFile::execute()
{
  int32_t err = 0;
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  // Make sure any directory path is also available as the user may have just typed
  // in a path without actually creating the full path
  QDir stlDir(getOutputStlDirectory());
  if (!stlDir.mkpath("."))
  {
    QString ss = QObject::tr("Error creating parent path '%1'").arg(getOutputStlDirectory());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }

  TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>();
  float* nodes = triangleGeom->getVertexPointer(0);
  int64_t* triangles = triangleGeom->getTriPointer(0);
  int64_t nTriangles = triangleGeom->getNumberOfTris();

  if (nTriangles > std::numeric_limits<int32_t>::max())
  {
    QString ss = QObject::tr("The number of triangles is %1, but the STL specification only supports triangle counts up to %2").arg(nTriangles).arg(std::numeric_limits<int32_t>::max());
    notifyErrorMessage(getHumanLabel(), ss, -1);
    setErrorCondition(-1);
    return;
  }

  // Store all the unique Spins
  QMap<int32_t, int32_t> uniqueGrainIdtoPhase;
  if (m_GroupByPhase == true)
  {
    for (int64_t i = 0; i < nTriangles; i++)
    {
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], m_SurfaceMeshFacePhases[i * 2]);
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], m_SurfaceMeshFacePhases[i * 2 + 1]);
    }
  }
  else
  {
    for (int64_t i = 0; i < nTriangles; i++)
    {
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], 0);
      uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], 0);
    }
  }

  unsigned char data[50];
  float* normal = (float*)data;
  float* vert1 = (float*)(data + 12);
  float* vert2 = (float*)(data + 24);
  float* vert3 = (float*)(data + 36);
  uint16_t* attrByteCount = (uint16_t*)(data + 48);
  *attrByteCount = 0;

  size_t totalWritten = 0;
  float u[3] = { 0.0f, 0.0f, 0.0f }, w[3] = { 0.0f, 0.0f, 0.0f };
  float length = 0.0f;

  int32_t spin = 0;
  int32_t triCount = 0;

  //Loop over the unique Spins
  for (QMap<int32_t, int32_t>::iterator spinIter = uniqueGrainIdtoPhase.begin(); spinIter != uniqueGrainIdtoPhase.end(); ++spinIter )
  {
    spin = spinIter.key();

    // Generate the output file name
    QString filename = getOutputStlDirectory() + "/" + getOutputStlPrefix();
    if (m_GroupByPhase == true)
    {
      filename = filename + QString("Ensemble_") + QString::number(spinIter.value()) + QString("_");
    }
    filename = filename + QString("Feature_") + QString::number(spin) + ".stl";
    FILE* f = fopen(filename.toLatin1().data(), "wb");
    {
      QString ss = QObject::tr("Writing STL for Feature Id %1").arg(spin);
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }

    QString header = "DREAM3D Generated For Feature ID " + QString::number(spin);
    if (m_GroupByPhase == true)
    {
      header = header + " Phase " + QString::number(spinIter.value());
    }
    err = writeHeader(f, header, 0);
    if (err < 0)
    {
    }
    triCount = 0; // Reset this to Zero. Increment for every triangle written

    // Loop over all the triangles for this spin
    for (int64_t t = 0; t < nTriangles; ++t)
    {
      // Get the true indices of the 3 nodes
      int64_t nId0 = triangles[t * 3];
      int64_t nId1 = triangles[t * 3 + 1];
      int64_t nId2 = triangles[t * 3 + 2];

      vert1[0] = static_cast<float>(nodes[nId0 * 3]);
      vert1[1] = static_cast<float>(nodes[nId0 * 3 + 1]);
      vert1[2] = static_cast<float>(nodes[nId0 * 3 + 2]);

      if (m_SurfaceMeshFaceLabels[t * 2] == spin)
      {
        //winding = 0; // 0 = Write it using forward spin
      }
      else if (m_SurfaceMeshFaceLabels[t * 2 + 1] == spin)
      {
        //winding = 1; // Write it using backward spin
        // Switch the 2 node indices
        int64_t temp = nId1;
        nId1 = nId2;
        nId2 = temp;
      }
      else
      {
        continue; // We do not match either spin so move to the next triangle
      }

      vert2[0] = static_cast<float>(nodes[nId1 * 3]);
      vert2[1] = static_cast<float>(nodes[nId1 * 3 + 1]);
      vert2[2] = static_cast<float>(nodes[nId1 * 3 + 2]);

      vert3[0] = static_cast<float>(nodes[nId2 * 3]);
      vert3[1] = static_cast<float>(nodes[nId2 * 3 + 1]);
      vert3[2] = static_cast<float>(nodes[nId2 * 3 + 2]);

      // Compute the normal
      u[0] = vert2[0] - vert1[0];
      u[1] = vert2[1] - vert1[1];
      u[2] = vert2[2] - vert1[2];

      w[0] = vert3[0] - vert1[0];
      w[1] = vert3[1] - vert1[1];
      w[2] = vert3[2] - vert1[2];

      normal[0] = u[1] * w[2] - u[2] * w[1];
      normal[1] = u[2] * w[0] - u[0] * w[2];
      normal[2] = u[0] * w[1] - u[1] * w[0];

      length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]);
      normal[0] = normal[0] / length;
      normal[1] = normal[1] / length;
      normal[2] = normal[2] / length;

      totalWritten = fwrite(data, 1, 50, f);
      if (totalWritten != 50)
      {
        QString ss = QObject::tr("Error Writing STL File. Not enough elements written for Feature Id %1. Wrote %2 of 50.").arg(spin).arg(totalWritten);
        notifyErrorMessage(getHumanLabel(), ss, -1201);
      }
      triCount++;
    }
    fclose(f);
    err = writeNumTrianglesToFile(filename, triCount);
  }

  setErrorCondition(0);
  notifyStatusMessage(getHumanLabel(), "Complete");

  return;
}
Example #24
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void CropImageGeometry::execute()
{
  setErrorCondition(0);

  /* Normally, filters call dataCheck during the execute to reuse code.  Unfortunately, this cannot happen for this filter, because calling dataCheck
       would destroy an Attribute Matrix that we need during the execute.  Do not uncomment the code, and be careful when reusing code from either of
        these functions.  Make sure you understand how this works before you reuse any code. */
  //dataCheck();
  //if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer srcCellDataContainer = getDataContainerArray()->getPrereqDataContainer<AbstractFilter>(this, getCellAttributeMatrixPath().getDataContainerName());
  AttributeMatrix::Pointer cellAttrMat = srcCellDataContainer->getAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
  DataContainer::Pointer destCellDataContainer = srcCellDataContainer;

  if (m_SaveAsNewDataContainer == true)
  {
    float ox = 0.0f, oy = 0.0f, oz = 0.0f, rx = 0.0f, ry = 0.0f, rz = 0.0f;
    srcCellDataContainer->getGeometryAs<ImageGeom>()->getOrigin(ox, oy, oz);
    srcCellDataContainer->getGeometryAs<ImageGeom>()->getResolution(rx, ry, rz);

    destCellDataContainer = getDataContainerArray()->createNonPrereqDataContainer<AbstractFilter>(this, getNewDataContainerName());
    ImageGeom::Pointer image = ImageGeom::CreateGeometry(DREAM3D::Geometry::ImageGeometry);
    destCellDataContainer->setGeometry(image);

    destCellDataContainer->getGeometryAs<ImageGeom>()->setOrigin(ox, oy, oz);
    destCellDataContainer->getGeometryAs<ImageGeom>()->setResolution(rx, ry, rz);

    AttributeMatrix::Pointer cellAttrMatCopy = cellAttrMat->deepCopy();
    destCellDataContainer->addAttributeMatrix(cellAttrMatCopy->getName(), cellAttrMatCopy);
    cellAttrMat = destCellDataContainer->getAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
  }

  if(NULL == destCellDataContainer.get() || NULL == cellAttrMat.get() || getErrorCondition() < 0)
  {
    return;
  }


  // No matter where the AM is (same DC or new DC), we have the correct DC and AM pointers...now it's time to crop
  int64_t totalPoints = cellAttrMat->getNumTuples();

  size_t udims[3] =
  { 0, 0, 0 };
  srcCellDataContainer->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
  typedef int32_t DimType;
#else
  typedef int64_t DimType;
#endif
  DimType dims[3] =
  { static_cast<DimType>(udims[0]), static_cast<DimType>(udims[1]), static_cast<DimType>(udims[2]), };

  // Check to see if the dims have actually changed.
  if(dims[0] == (m_XMax - m_XMin) && dims[1] == (m_YMax - m_YMin) && dims[2] == (m_ZMax - m_ZMin))
  {
    return;
  }

  // Get current origin
  float oldOrigin[3] = {0.0f, 0.0f, 0.0f};
  destCellDataContainer->getGeometryAs<ImageGeom>()->getOrigin(oldOrigin);

  // Check to make sure the new dimensions are not "out of bounds" and warn the user if they are
  if (dims[0] <= m_XMax)
  {
    QString ss = QObject::tr("The Max X value (%1) is greater than the Image Geometry X entent (%2)."
                             " This may lead to junk data being filled into the extra space.").arg(m_XMax).arg(dims[0]);
    setErrorCondition(-950);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }
  if (dims[1] <= m_YMax)
  {

    QString ss = QObject::tr("The Max Y value (%1) is greater than the Image Geometry Y entent (%2)."
                             " This may lead to junk data being filled into the extra space.").arg(m_YMax).arg(dims[1]);
    setErrorCondition(-951);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }
  if (dims[2] <= m_ZMax)
  {

    QString ss = QObject::tr("The Max Z value (%1) is greater than the Image Geometry Z entent (%2)."
                             " This may lead to junk data being filled into the extra space.").arg(m_ZMax).arg(dims[2]);
    setErrorCondition(-952);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return;
  }

  int64_t XP = ( (m_XMax - m_XMin) + 1 );
  int64_t YP = ( (m_YMax - m_YMin) + 1 );
  int64_t ZP = ( (m_ZMax - m_ZMin) + 1 );

  int64_t col = 0, row = 0, plane = 0;
  int64_t colold = 0, rowold = 0, planeold = 0;
  int64_t index = 0;
  int64_t index_old = 0;
  QList<QString> voxelArrayNames = cellAttrMat->getAttributeArrayNames();
  for (int64_t i = 0; i < ZP; i++)
  {
    QString ss = QObject::tr("Cropping Volume - Slice %1 of %2 Complete").arg(i).arg(ZP);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    planeold = (i + m_ZMin) * (srcCellDataContainer->getGeometryAs<ImageGeom>()->getXPoints() * srcCellDataContainer->getGeometryAs<ImageGeom>()->getYPoints());
    plane = (i * XP * YP);
    for (int64_t j = 0; j < YP; j++)
    {
      rowold = (j + m_YMin) * srcCellDataContainer->getGeometryAs<ImageGeom>()->getXPoints();
      row = (j * XP);
      for (int64_t k = 0; k < XP; k++)
      {
        colold = (k + m_XMin);
        col = k;
        index_old = planeold + rowold + colold;
        index = plane + row + col;
        for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
        {
          IDataArray::Pointer p = cellAttrMat->getAttributeArray(*iter);
          p->copyTuple(index_old, index);
        }
      }
    }
  }
  destCellDataContainer->getGeometryAs<ImageGeom>()->setDimensions(static_cast<size_t>(XP), static_cast<size_t>(YP), static_cast<size_t>(ZP));
  totalPoints = destCellDataContainer->getGeometryAs<ImageGeom>()->getNumberOfElements();
  QVector<size_t> tDims(3, 0);
  tDims[0] = XP;
  tDims[1] = YP;
  tDims[2] = ZP;
  cellAttrMat->setTupleDimensions(tDims); // THIS WILL CAUSE A RESIZE of all the underlying data arrays.

  if (m_RenumberFeatures == true)
  {
    totalPoints = destCellDataContainer->getGeometryAs<ImageGeom>()->getNumberOfElements();

    // This just sanity checks to make sure there were existing features before the cropping
    AttributeMatrix::Pointer cellFeatureAttrMat = srcCellDataContainer->getAttributeMatrix(getCellFeatureAttributeMatrixPath().getAttributeMatrixName());
    size_t totalFeatures = cellFeatureAttrMat->getNumTuples();
    QVector<bool> activeObjects(totalFeatures, false);
    if (0 == totalFeatures)
    {
      setErrorCondition(-600);
      notifyErrorMessage(getHumanLabel(), "The number of Features is 0 and should be greater than 0", getErrorCondition());
      return;
    }

    //QVector<size_t> cDims(1, 1);
    DataArrayPath dap = getFeatureIdsArrayPath();
    if(getSaveAsNewDataContainer())
    {
      dap.setDataContainerName(getNewDataContainerName());
    }
    m_FeatureIdsPtr = cellAttrMat->getAttributeArrayAs<Int32ArrayType>(dap.getDataArrayName()); /* Assigns the shared_ptr<> to an instance variable that is a weak_ptr<> */
    if( NULL != m_FeatureIdsPtr.lock().get() ) /* Validate the Weak Pointer wraps a non-NULL pointer to a DataArray<T> object */
    { m_FeatureIds = m_FeatureIdsPtr.lock()->getPointer(0); } /* Now assign the raw pointer to data from the DataArray<T> object */
    else
    {
      setErrorCondition(-601);
      QString ss = QObject::tr("The FeatureIds array with name '%1' was not found in the destination DataContainer. The expected path was '%2'")
                   .arg(dap.getDataArrayName()).arg(dap.serialize("/"));
      notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
      return;
    }

    // Find the unique set of feature ids
    for (int64_t i = 0; i < totalPoints; ++i)
    {
      int32_t currentFeatureId = m_FeatureIds[i];
      if (currentFeatureId < totalFeatures)
      {
        activeObjects[currentFeatureId] = true;
      }
      else
      {
        setErrorCondition(-601);
        QString ss = QObject::tr("The total number of Features from %1 is %2, but a value of %3 was found in DataArray %4.").arg(cellFeatureAttrMat->getName()).arg(totalFeatures).arg(currentFeatureId).arg(getFeatureIdsArrayPath().serialize("/"));
        qDebug() << ss;
        notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
        return;
      }
    }
    cellFeatureAttrMat->removeInactiveObjects(activeObjects, m_FeatureIdsPtr.lock());
  }

  if(m_UpdateOrigin == true)
  {
    float resolution[3] = {0.0f, 0.0f, 0.0f};
    destCellDataContainer->getGeometryAs<ImageGeom>()->getResolution(resolution);

    float origin[3] = {0.0f, 0.0f, 0.0f};
    destCellDataContainer->getGeometryAs<ImageGeom>()->getOrigin(origin);

    origin[0] = m_XMin * resolution[0] + oldOrigin[0];
    origin[1] = m_YMin * resolution[1] + oldOrigin[1];
    origin[2] = m_ZMin * resolution[2] + oldOrigin[2];

    destCellDataContainer->getGeometryAs<ImageGeom>()->setOrigin(origin);
  }

  notifyStatusMessage(getHumanLabel(), "Complete");
}
Example #25
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int32_t SPParksWriter::writeFile()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return getErrorCondition(); }

  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(m_FeatureIdsArrayPath.getDataContainerName());

  size_t udims[3] = {0, 0, 0};
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);

  size_t totalpoints = m->getGeometryAs<ImageGeom>()->getNumberOfElements();

  std::ofstream outfile;
  outfile.open(getOutputFile().toLatin1().data(), std::ios_base::binary | std::ios_base::app);
  if (!outfile)
  {
    QString ss = QObject::tr("Error opening output file '%1'").arg(getOutputFile());
    setErrorCondition(-100);
    notifyErrorMessage(getHumanLabel(), ss, getErrorCondition());
    return getErrorCondition();
  }

  uint64_t millis = QDateTime::currentMSecsSinceEpoch();
  uint64_t currentMillis = millis;
  uint64_t startMillis = millis;
  uint64_t estimatedTime = 0;
  float timeDiff = 0.0f;

  int64_t increment = static_cast<int64_t>(totalpoints * 0.01f);
  size_t count = 0;
  QString buf;
  QTextStream ss(&buf);
  // Buffer the output with 4096 Bytes which is typically the size of a "Block" on a
  // modern Hard Drive. This should speed up the writes considerably
  char buffer[4096];
  outfile.rdbuf()->pubsetbuf(buffer, 4096);
  for (size_t k = 0; k < totalpoints; k++)
  {
    if (count % increment == 0)
    {
      currentMillis = QDateTime::currentMSecsSinceEpoch();
      if (currentMillis - millis > 1000)
      {
        buf.clear();
        ss << getMessagePrefix() << " " << static_cast<int>((float)(k) / (float)(totalpoints) * 100) << " % Completed ";
        timeDiff = ((float)k / (float)(currentMillis - startMillis));
        estimatedTime = (float)(totalpoints - k) / timeDiff;
        ss << " || Est. Time Remain: " << DREAM3D::convertMillisToHrsMinSecs(estimatedTime);
        notifyStatusMessage(getHumanLabel(),  buf );
        millis = QDateTime::currentMSecsSinceEpoch();
      }
    }
    count++;
    double temp0 = 0.0;
    double temp1 = 0.0;
    outfile << k + 1 << " " << m_FeatureIds[k] << " " << temp0 << " " << temp1 << "\n";
  }
  outfile.close();

  // If there is an error set this to something negative and also set a message
  notifyStatusMessage(getHumanLabel(), "Complete");
  return 0;
}
Example #26
0
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FindGBCD::execute()
{
  setErrorCondition(0);
  dataCheckVoxel();
  if(getErrorCondition() < 0) { return; }
  // order here matters...because we are going to use the size of the crystal structures out of the dataCheckVoxel to size the faceAttrMat in dataCheckSurfaceMesh
  dataCheckSurfaceMesh();
  if(getErrorCondition() < 0) { return; }

#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
  tbb::task_scheduler_init init;
  bool doParallel = true;
#endif

  size_t totalPhases = m_CrystalStructuresPtr.lock()->getNumberOfTuples();
  size_t totalFaces = m_SurfaceMeshFaceLabelsPtr.lock()->getNumberOfTuples();
  size_t faceChunkSize = 50000;
  size_t numMisoReps = 576 * 4;
  if (totalFaces < faceChunkSize) { faceChunkSize = totalFaces; }
  // call the sizeGBCD function with proper chunkSize and numMisoReps to get Bins array set up properly
  sizeGBCD(faceChunkSize, numMisoReps);
  int32_t totalGBCDBins = m_GbcdSizes[0] * m_GbcdSizes[1] * m_GbcdSizes[2] * m_GbcdSizes[3] * m_GbcdSizes[4] * 2;

  uint64_t millis = QDateTime::currentMSecsSinceEpoch();
  uint64_t currentMillis = millis;
  uint64_t startMillis = millis;
  uint64_t estimatedTime = 0;
  float timeDiff = 0.0f;
  startMillis =  QDateTime::currentMSecsSinceEpoch();
  int32_t hemisphere = 0;

  //create an array to hold the total face area for each phase and initialize the array to 0.0
  DoubleArrayType::Pointer totalFaceAreaPtr = DoubleArrayType::CreateArray(totalPhases, "totalFaceArea");
  totalFaceAreaPtr->initializeWithValue(0.0);
  double* totalFaceArea = totalFaceAreaPtr->getPointer(0);

  QString ss = QObject::tr("Calculating GBCD || 0/%1 Completed").arg(totalFaces);
  for (size_t i = 0; i < totalFaces; i = i + faceChunkSize)
  {
    if(getCancel() == true) { return; }
    if (i + faceChunkSize >= totalFaces)
    {
      faceChunkSize = totalFaces - i;
    }
    m_GbcdBinsArray->initializeWithValue(-1);
#ifdef SIMPLib_USE_PARALLEL_ALGORITHMS
    if (doParallel == true)
    {
      tbb::parallel_for(tbb::blocked_range<size_t>(i, i + faceChunkSize),
                        CalculateGBCDImpl(i, numMisoReps, m_SurfaceMeshFaceLabelsPtr.lock(), m_SurfaceMeshFaceNormalsPtr.lock(), m_FeatureEulerAnglesPtr.lock(), m_FeaturePhasesPtr.lock(), m_CrystalStructuresPtr.lock(), m_GbcdBinsArray, m_GbcdHemiCheckArray, m_GbcdDeltasArray, m_GbcdSizesArray, m_GbcdLimitsArray), tbb::auto_partitioner());

    }
    else
#endif
    {
      CalculateGBCDImpl serial(i, numMisoReps, m_SurfaceMeshFaceLabelsPtr.lock(), m_SurfaceMeshFaceNormalsPtr.lock(), m_FeatureEulerAnglesPtr.lock(), m_FeaturePhasesPtr.lock(), m_CrystalStructuresPtr.lock(), m_GbcdBinsArray, m_GbcdHemiCheckArray, m_GbcdDeltasArray, m_GbcdSizesArray, m_GbcdLimitsArray);
      serial.generate(i, i + faceChunkSize);
    }

    currentMillis = QDateTime::currentMSecsSinceEpoch();
    if (currentMillis - millis > 1000)
    {
      QString ss = QObject::tr("Calculating GBCD || Triangles %1/%2 Completed").arg(i).arg(totalFaces);
      timeDiff = ((float)i / (float)(currentMillis - startMillis));
      estimatedTime = (float)(totalFaces - i) / timeDiff;
      ss = ss + QObject::tr(" || Est. Time Remain: %1").arg(DREAM3D::convertMillisToHrsMinSecs(estimatedTime));
      millis = QDateTime::currentMSecsSinceEpoch();
      notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    }

    if(getCancel() == true) { return; }

    int32_t phase = 0;
    int32_t feature = 0;
    double area = 0.0;
    for (size_t j = 0; j < faceChunkSize; j++)
    {
      area = m_SurfaceMeshFaceAreas[i + j];
      feature = m_SurfaceMeshFaceLabels[2 * (i + j)];
      phase = m_FeaturePhases[feature];
      for (size_t k = 0; k < numMisoReps; k++)
      {
        if (m_GbcdBins[(j * numMisoReps) + (k)] >= 0)
        {
          hemisphere = 0;
          if (m_HemiCheck[(j * numMisoReps) + k] == false) { hemisphere = 1; }
          m_GBCD[(phase * totalGBCDBins) + (2 * m_GbcdBins[(j * numMisoReps) + (k)] + hemisphere)] += area;
          totalFaceArea[phase] += area;
        }
      }
    }
  }

  ss = QObject::tr("Starting GBCD Normalization");
  notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);

  for (int32_t i = 0; i < totalPhases; i++)
  {
    size_t phaseShift = i * totalGBCDBins;
    double MRDfactor = double(totalGBCDBins) / totalFaceArea[i];
    for (int32_t j = 0; j < totalGBCDBins; j++)
    {
      m_GBCD[phaseShift + j] *= MRDfactor;
    }
  }

  /* Let the GUI know we are done with this filter */
  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AlignSectionsMutualInformation::form_features_sections()
{
  DREAM3D_RANDOMNG_NEW()
  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  size_t udims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
  typedef int32_t DimType;
#else
  typedef int64_t DimType;
#endif
  DimType dims[3] =
  {
    static_cast<DimType>(udims[0]),
    static_cast<DimType>(udims[1]),
    static_cast<DimType>(udims[2]),
  };

  DimType point = 0;
  DimType seed = 0;
  bool noseeds = false;
  int32_t featurecount = 1;
  DimType neighbor = 0;
  QuatF q1 = QuaternionMathF::New();
  QuatF q2 = QuaternionMathF::New();
  QuatF* quats = reinterpret_cast<QuatF*>(m_Quats);
  float w = 0.0f;
  float n1 = 0.0f;
  float n2 = 0.0f;
  float n3 = 0.0f;
  DimType randx = 0;
  DimType randy = 0;
  bool good = false;
  DimType x = 0, y = 0, z = 0;
  DimType col = 0, row = 0;
  size_t size = 0;
  size_t initialVoxelsListSize = 1000;

  m_FeatureCounts->resize(dims[2]);
  featurecounts = m_FeatureCounts->getPointer(0);

  std::vector<DimType> voxelslist(initialVoxelsListSize, -1);
  DimType neighpoints[4] = { 0, 0, 0, 0 };
  neighpoints[0] = -dims[0];
  neighpoints[1] = -1;
  neighpoints[2] = 1;
  neighpoints[3] = dims[0];

  uint32_t phase1 = 0, phase2 = 0;

  for (DimType slice = 0; slice < dims[2]; slice++)
  {
    QString ss = QObject::tr("Aligning Sections || Identifying Features on Sections || %1% Complete").arg(((float)slice / dims[2]) * 100);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    featurecount = 1;
    noseeds = false;
    while (noseeds == false)
    {
      seed = -1;
      randx = DimType(float(rg.genrand_res53()) * float(dims[0]));
      randy = DimType(float(rg.genrand_res53()) * float(dims[1]));
      for (DimType j = 0; j < dims[1]; ++j)
      {
        for (DimType i = 0; i < dims[0]; ++i)
        {
          x = randx + i;
          y = randy + j;
          z = slice;
          if (x > dims[0] - 1) { x = x - dims[0]; }
          if (y > dims[1] - 1) { y = y - dims[1]; }
          point = (z * dims[0] * dims[1]) + (y * dims[0]) + x;
          if ((m_UseGoodVoxels == false || m_GoodVoxels[point] == true) && m_FeatureIds[point] == 0 && m_CellPhases[point] > 0)
          {
            seed = point;
          }
          if (seed > -1) { break; }
        }
        if( seed > -1) { break; }
      }
      if (seed == -1) { noseeds = true; }
      if (seed >= 0)
      {
        size = 0;
        m_FeatureIds[seed] = featurecount;
        voxelslist[size] = seed;
        size++;
        for (size_t j = 0; j < size; ++j)
        {
          DimType currentpoint = voxelslist[j];
          col = currentpoint % dims[0];
          row = (currentpoint / dims[0]) % dims[1];
          QuaternionMathF::Copy(quats[currentpoint], q1);
          phase1 = m_CrystalStructures[m_CellPhases[currentpoint]];
          for (int32_t i = 0; i < 4; i++)
          {
            good = true;
            neighbor = currentpoint + neighpoints[i];
            if ((i == 0) && row == 0) { good = false; }
            if ((i == 3) && row == (dims[1] - 1)) { good = false; }
            if ((i == 1) && col == 0) { good = false; }
            if ((i == 2) && col == (dims[0] - 1)) { good = false; }
            if (good == true && m_FeatureIds[neighbor] <= 0 && m_CellPhases[neighbor] > 0)
            {
              w = std::numeric_limits<float>::max();
              QuaternionMathF::Copy(quats[neighbor], q2);
              phase2 = m_CrystalStructures[m_CellPhases[neighbor]];
              if (phase1 == phase2)
              {
                w = m_OrientationOps[phase1]->getMisoQuat(q1, q2, n1, n2, n3);
              }
              if (w < m_MisorientationTolerance)
              {
                m_FeatureIds[neighbor] = featurecount;
                voxelslist[size] = neighbor;
                size++;
                if (std::vector<DimType>::size_type(size) >= voxelslist.size())
                {
                  size = voxelslist.size();
                  voxelslist.resize(size + initialVoxelsListSize);
                  for (std::vector<DimType>::size_type v = size; v < voxelslist.size(); ++v) { voxelslist[v] = -1; }
                }
              }
            }
          }
        }
        voxelslist.erase(std::remove(voxelslist.begin(), voxelslist.end(), -1), voxelslist.end());
        featurecount++;
        voxelslist.assign(initialVoxelsListSize, -1);
      }
    }
    featurecounts[slice] = featurecount;
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AlignSectionsFeatureCentroid::find_shifts(std::vector<int64_t>& xshifts, std::vector<int64_t>& yshifts)
{
  DataContainer::Pointer m = getDataContainerArray()->getDataContainer(getDataContainerName());

  std::ofstream outFile;
  if (getWriteAlignmentShifts() == true)
  {
    outFile.open(getAlignmentShiftFileName().toLatin1().data());
  }
  size_t udims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(udims);
#if (CMP_SIZEOF_SIZE_T == 4)
  typedef int32_t DimType;
#else
  typedef int64_t DimType;
#endif
  DimType dims[3] =
  {
    static_cast<DimType>(udims[0]),
    static_cast<DimType>(udims[1]),
    static_cast<DimType>(udims[2]),
  };

  int64_t newxshift = 0;
  int64_t newyshift = 0;
  int64_t count = 0;
  DimType slice = 0;
  DimType point = 0;
  float xRes = m->getGeometryAs<ImageGeom>()->getXRes();
  float yRes = m->getGeometryAs<ImageGeom>()->getYRes();
  std::vector<float> xCentroid(dims[2], 0.0f);
  std::vector<float> yCentroid(dims[2], 0.0f);

  for (DimType iter = 0; iter < dims[2]; iter++)
  {
    count = 0;
    xCentroid[iter] = 0;
    yCentroid[iter] = 0;

    QString ss = QObject::tr("Aligning Sections || Determining Shifts || %1% Complete").arg(((float)iter / dims[2]) * 100);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    slice = static_cast<int>( (dims[2] - 1) - iter );
    for (DimType l = 0; l < dims[1]; l++)
    {
      for (DimType n = 0; n < dims[0]; n++)
      {
        point = ((slice) * dims[0] * dims[1]) + (l * dims[0]) + n;
        if (m_GoodVoxels[point] == true)
        {
          xCentroid[iter] = xCentroid[iter] + (float(n) * xRes);
          yCentroid[iter] = yCentroid[iter] + (float(l) * yRes);
          count++;
        }
      }
    }
    xCentroid[iter] = xCentroid[iter] / float(count);
    yCentroid[iter] = yCentroid[iter] / float(count);
  }
  for (DimType iter = 1; iter < dims[2]; iter++)
  {
    slice = (dims[2] - 1) - iter;
    if (m_UseReferenceSlice == true)
    {
      xshifts[iter] = static_cast<int64_t>((xCentroid[iter] - xCentroid[m_ReferenceSlice]) / xRes);
      yshifts[iter] = static_cast<int64_t>((yCentroid[iter] - yCentroid[m_ReferenceSlice]) / yRes);
    }
    else
    {
      xshifts[iter] = xshifts[iter - 1] + static_cast<int64_t>((xCentroid[iter] - xCentroid[iter - 1]) / xRes);
      yshifts[iter] = yshifts[iter - 1] + static_cast<int64_t>((yCentroid[iter] - yCentroid[iter - 1]) / yRes);
    }
    if (getWriteAlignmentShifts() == true)
    {
      outFile << slice << "	" << slice + 1 << "	" << newxshift << "	" << newyshift << "	" << xshifts[iter] << "	" << yshifts[iter] << " " << xCentroid[iter] << " " << yCentroid[iter] << std::endl;
    }
  }
  if (getWriteAlignmentShifts() == true)
  {
    outFile.close();
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void ChangeResolution::execute()
{
  setErrorCondition(0);
  dataCheck();
  if(getErrorCondition() < 0) { return; }

  DataContainer::Pointer m;
  if(m_SaveAsNewDataContainer == false)
  {
    m = getDataContainerArray()->getDataContainer(getCellAttributeMatrixPath().getDataContainerName());
  }
  else
  {
    m = getDataContainerArray()->getDataContainer(getNewDataContainerName());
  }

  if(m->getGeometryAs<ImageGeom>()->getXRes() == m_Resolution.x
      && m->getGeometryAs<ImageGeom>()->getYRes() == m_Resolution.y
      && m->getGeometryAs<ImageGeom>()->getZRes() == m_Resolution.z)
  {
    return;
  }

  AttributeMatrix::Pointer cellAttrMat = m->getAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());

  size_t dims[3] = { 0, 0, 0 };
  m->getGeometryAs<ImageGeom>()->getDimensions(dims);

  float sizex = (dims[0]) * m->getGeometryAs<ImageGeom>()->getXRes();
  float sizey = (dims[1]) * m->getGeometryAs<ImageGeom>()->getYRes();
  float sizez = (dims[2]) * m->getGeometryAs<ImageGeom>()->getZRes();
  size_t m_XP = size_t(sizex / m_Resolution.x);
  size_t m_YP = size_t(sizey / m_Resolution.y);
  size_t m_ZP = size_t(sizez / m_Resolution.z);
  if (m_XP == 0) { m_XP = 1; }
  if (m_YP == 0) { m_YP = 1; }
  if (m_ZP == 0) { m_ZP = 1; }
  size_t totalPoints = m_XP * m_YP * m_ZP;

  float x = 0.0f, y = 0.0f, z = 0.0f;
  size_t col = 0, row = 0, plane = 0;
  size_t index;
  size_t index_old;
  std::vector<size_t> newindicies(totalPoints);

  for (size_t i = 0; i < m_ZP; i++)
  {
    QString ss = QObject::tr("Changing Resolution - %1 Percent Complete").arg(((float)i / m->getGeometryAs<ImageGeom>()->getZPoints()) * 100);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    for (size_t j = 0; j < m_YP; j++)
    {
      for (size_t k = 0; k < m_XP; k++)
      {
        x = (k * m_Resolution.x);
        y = (j * m_Resolution.y);
        z = (i * m_Resolution.z);
        col = size_t(x / m->getGeometryAs<ImageGeom>()->getXRes());
        row = size_t(y / m->getGeometryAs<ImageGeom>()->getYRes());
        plane = size_t(z / m->getGeometryAs<ImageGeom>()->getZRes());
        index_old = (plane * m->getGeometryAs<ImageGeom>()->getXPoints() * m->getGeometryAs<ImageGeom>()->getYPoints()) + (row * m->getGeometryAs<ImageGeom>()->getXPoints()) + col;
        index = (i * m_XP * m_YP) + (j * m_XP) + k;
        newindicies[index] = index_old;
      }
    }
  }

  QVector<size_t> tDims(3, 0);
  tDims[0] = m_XP;
  tDims[1] = m_YP;
  tDims[2] = m_ZP;
  AttributeMatrix::Pointer newCellAttrMat = AttributeMatrix::New(tDims, cellAttrMat->getName(), cellAttrMat->getType());

  QList<QString> voxelArrayNames = cellAttrMat->getAttributeArrayNames();
  for (QList<QString>::iterator iter = voxelArrayNames.begin(); iter != voxelArrayNames.end(); ++iter)
  {
    IDataArray::Pointer p = cellAttrMat->getAttributeArray(*iter);
    // Make a copy of the 'p' array that has the same name. When placed into
    // the data container this will over write the current array with
    // the same name. At least in theory.
    IDataArray::Pointer data = p->createNewArray(p->getNumberOfTuples(), p->getComponentDimensions(), p->getName());
    data->resize(totalPoints);
    void* source = NULL;
    void* destination = NULL;
    size_t newIndicies_I = 0;
    int nComp = data->getNumberOfComponents();
    for (size_t i = 0; i < static_cast<size_t>(totalPoints); i++)
    {
      newIndicies_I = newindicies[i];
      source = p->getVoidPointer((nComp * newIndicies_I));
      destination = data->getVoidPointer((data->getNumberOfComponents() * i));
      ::memcpy(destination, source, p->getTypeSize() * data->getNumberOfComponents());
    }
    cellAttrMat->removeAttributeArray(*iter);
    newCellAttrMat->addAttributeArray(*iter, data);
  }
  m->getGeometryAs<ImageGeom>()->setResolution(m_Resolution.x, m_Resolution.y, m_Resolution.z);
  m->getGeometryAs<ImageGeom>()->setDimensions(m_XP, m_YP, m_ZP);
  m->removeAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
  m->addAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName(), newCellAttrMat);

  // Feature Ids MUST already be renumbered.
  if (m_RenumberFeatures == true)
  {
    totalPoints = m->getGeometryAs<ImageGeom>()->getNumberOfElements();
    AttributeMatrix::Pointer cellFeatureAttrMat = m->getAttributeMatrix(getCellFeatureAttributeMatrixPath().getAttributeMatrixName());
    size_t totalFeatures = cellFeatureAttrMat->getNumTuples();
    QVector<bool> activeObjects(totalFeatures, false);
    if (0 == totalFeatures)
    {
      notifyErrorMessage(getHumanLabel(), "The number of Features is 0 and should be greater than 0", -600);
      return;
    }

    updateCellInstancePointers();

    // Find the unique set of feature ids
    for (size_t i = 0; i < totalPoints; ++i)
    {
      activeObjects[m_FeatureIds[i]] = true;
    }
    cellFeatureAttrMat->removeInactiveObjects(activeObjects, m_FeatureIdsPtr.lock());
  }

  notifyStatusMessage(getHumanLabel(), "Complete");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int32_t LaplacianSmoothing::edgeBasedSmoothing()
{
  int32_t err = 0;
  DataContainer::Pointer sm = getDataContainerArray()->getDataContainer(getSurfaceDataContainerName());
  IGeometry2D::Pointer surfaceMesh = sm->getGeometryAs<IGeometry2D>();
  float* verts = surfaceMesh->getVertexPointer(0);
  int64_t nvert = surfaceMesh->getNumberOfVertices();

  // Generate the Lambda Array
  err = generateLambdaArray();
  if (err < 0)
  {
    setErrorCondition(-557);
    notifyErrorMessage(getHumanLabel(), "Error generating the lambda array", getErrorCondition());
    return err;
  }

  // Get a Pointer to the Lambda array for conveneince
  DataArray<float>::Pointer lambdas = getLambdaArray();
  float* lambda = lambdas->getPointer(0);

  //  Generate the Unique Edges
  if (NULL == surfaceMesh->getEdges().get())
  {
    err = surfaceMesh->findEdges();
  }
  if (err < 0)
  {
    setErrorCondition(-560);
    notifyErrorMessage(getHumanLabel(), "Error retrieving the shared edge list", getErrorCondition());
    return getErrorCondition();
  }

  int64_t* uedges = surfaceMesh->getEdgePointer(0);
  int64_t nedges = surfaceMesh->getNumberOfEdges();

  DataArray<int32_t>::Pointer numConnections = DataArray<int32_t>::CreateArray(nvert, "_INTERNAL_USE_ONLY_Laplacian_Smoothing_NumberConnections_Array");
  numConnections->initializeWithZeros();
  int32_t* ncon = numConnections->getPointer(0);

  QVector<size_t> cDims(1, 3);
  DataArray<double>::Pointer deltaArray = DataArray<double>::CreateArray(nvert, cDims, "_INTERNAL_USE_ONLY_Laplacian_Smoothing_Delta_Array");
  deltaArray->initializeWithZeros();
  double* delta = deltaArray->getPointer(0);

  double dlta = 0.0;
  for (int32_t q = 0; q < m_IterationSteps; q++)
  {
    if (getCancel() == true) { return -1; }
    QString ss = QObject::tr("Iteration %1").arg(q);
    notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss);
    for (int64_t i = 0; i < nedges; i++)
    {
      int64_t in1 = uedges[2 * i];   // row of the first vertex
      int64_t in2 = uedges[2 * i + 1]; // row the second vertex

      for (int32_t j = 0; j < 3; j++)
      {
        BOOST_ASSERT( static_cast<size_t>(3 * in1 + j) < static_cast<size_t>(nvert * 3) );
        BOOST_ASSERT( static_cast<size_t>(3 * in2 + j) < static_cast<size_t>(nvert * 3) );
        dlta = verts[3 * in2 + j] - verts[3 * in1 + j];
        delta[3 * in1 + j] += dlta;
        delta[3 * in2 + j] += -1.0 * dlta;
      }
      ncon[in1] += 1;
      ncon[in2] += 1;
    }

    float ll = 0.0f;
    for (int64_t i = 0; i < nvert; i++)
    {
      for (int32_t j = 0; j < 3; j++)
      {
        int64_t in0 = 3 * i + j;
        dlta = delta[in0] / ncon[i];

        ll = lambda[i];
        verts[3 * i + j] += ll * dlta;
        delta[in0] = 0.0; // reset for next iteration
      }
      ncon[i] = 0; // reset for next iteration
    }
  }

  return err;
}