// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int AttributeMatrix::addAttributeArrayFromHDF5Path(hid_t gid, QString name, bool preflight)
{
    int err = 0;
    QString classType;
    QH5Lite::readStringAttribute(gid, name, DREAM3D::HDF5::ObjectType, classType);
    //   qDebug() << groupName << " Array: " << *iter << " with C++ ClassType of " << classType << "\n";
    IDataArray::Pointer dPtr = IDataArray::NullPointer();

    if(classType.startsWith("DataArray") == true)
    {
        dPtr = H5DataArrayReader::ReadIDataArray(gid, name, preflight);
        if(preflight == true)
        {
            dPtr->resize(getNumTuples());
        }
    }
    else if(classType.compare("StringDataArray") == 0)
    {
        dPtr = H5DataArrayReader::ReadStringDataArray(gid, name, preflight);
        if (preflight == true)
        {
            dPtr->resize(getNumTuples());
        }
    }
    else if(classType.compare("vector") == 0)
    {

    }
    else if(classType.compare("NeighborList<T>") == 0)
    {
        dPtr = H5DataArrayReader::ReadNeighborListData(gid, name, preflight);
        if (preflight == true)
        {
            dPtr->resize(getNumTuples());
        }
    }
    else if ( name.compare(DREAM3D::EnsembleData::Statistics) == 0)
    {
        StatsDataArray::Pointer statsData = StatsDataArray::New();
        statsData->setName(DREAM3D::EnsembleData::Statistics);
        statsData->readH5Data(gid);
        dPtr = statsData;
        if (preflight == true)
        {
            dPtr->resize(getNumTuples());
        }
    }

    if (NULL != dPtr.get())
    {
        addAttributeArray(dPtr->getName(), dPtr);
    }

    return err;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void AttributeMatrix::resizeAttributeArrays(QVector<size_t> tDims)
{
    // int success = 0;
    m_TupleDims = tDims;
    size_t numTuples = m_TupleDims[0];
    for(int i = 1; i < m_TupleDims.size(); i++)
    {
        numTuples *= m_TupleDims[i];
    }

    for(QMap<QString, IDataArray::Pointer>::iterator iter = m_AttributeArrays.begin(); iter != m_AttributeArrays.end(); ++iter)
    {
        //std::cout << "Resizing Array '" << (*iter).first << "' : " << success << std::endl;
        IDataArray::Pointer d = iter.value();
        d->resize(numTuples);
    }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
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");
}
    // -----------------------------------------------------------------------------
    // This is the actual templated algorithm
    // -----------------------------------------------------------------------------
    void static Execute(ReadImage* filter, QString inputFile, IDataArray::Pointer outputIDataArray, DataContainer::Pointer m, QString attrMatName)
    {
      typename DataArrayType::Pointer outputDataPtr = boost::dynamic_pointer_cast<DataArrayType>(outputIDataArray);

      //convert arrays to correct type
      PixelType* outputData = static_cast<PixelType*>(outputDataPtr->getPointer(0));
      size_t numVoxels = outputDataPtr->getNumberOfTuples();

      //read image meta data and get pixel type
      itk::ImageIOBase::Pointer imageIO = itk::ImageIOFactory::CreateImageIO(inputFile.toLocal8Bit().constData(), itk::ImageIOFactory::ReadMode);
      imageIO->SetFileName(inputFile.toLocal8Bit().data());
      imageIO->ReadImageInformation();
      itk::ImageIOBase::IOPixelType pixelType = imageIO->GetPixelType();

      itk::ProcessObject::Pointer readerObject;

      //read based on pixel type
      switch(pixelType)
      {
        case itk::ImageIOBase::SCALAR:
        {
          typedef itk::Image<PixelType, ImageProcessing::ImageDimension> ImageType;
          typedef itk::ImageFileReader<ImageType> ReaderType;
          typename ReaderType::Pointer reader = ReaderType::New();
          reader->SetFileName(inputFile.toLocal8Bit().constData());
          reader->GetOutput()->GetPixelContainer()->SetImportPointer(outputData, numVoxels, false);
          readerObject = reader;
        }
        break;

        case itk::ImageIOBase::RGB:
        {
          typedef itk::Image<itk::RGBPixel<PixelType>, ImageProcessing::ImageDimension> ImageType;
          typedef itk::ImageFileReader<ImageType> ReaderType;
          typename ReaderType::Pointer reader = ReaderType::New();
          reader->SetFileName(inputFile.toLocal8Bit().constData());
          reader->GetOutput()->GetPixelContainer()->SetImportPointer(reinterpret_cast<itk::RGBPixel<PixelType>*>(outputData), numVoxels, false);
          readerObject = reader;
        }
        break;

        case itk::ImageIOBase::RGBA:
        {
          typedef itk::Image<itk::RGBAPixel<PixelType>, ImageProcessing::ImageDimension> ImageType;
          typedef itk::ImageFileReader<ImageType> ReaderType;
          typename ReaderType::Pointer reader = ReaderType::New();
          reader->SetFileName(inputFile.toLocal8Bit().constData());
          reader->GetOutput()->GetPixelContainer()->SetImportPointer(reinterpret_cast<itk::RGBAPixel<PixelType>*>(outputData), numVoxels, false);
          readerObject = reader;
        }
        break;
        /**
        case itk::ImageIOBase::FIXEDARRAY:
          {
            typedef itk::VectorImage<PixelType>, ImageProcessing::ImageDimension> ImageType;
            typedef itk::ImageFileReader<ImageType> ReaderType;
            typename ReaderType::Pointer reader = ReaderType::New();
            reader->SetFileName(inputFile.toLocal8Bit().constData());
            reader->GetOutput()->GetPixelContainer()->SetImportPointer(outputData, numVoxels, false);
            readerObject=reader;
          }break;
          */
        case itk::ImageIOBase::UNKNOWNPIXELTYPE:
        case itk::ImageIOBase::OFFSET:
        case itk::ImageIOBase::VECTOR:
        case itk::ImageIOBase::POINT:
        case itk::ImageIOBase::COVARIANTVECTOR:
        case itk::ImageIOBase::SYMMETRICSECONDRANKTENSOR:
        case itk::ImageIOBase::DIFFUSIONTENSOR3D:
        case itk::ImageIOBase::COMPLEX:
        case itk::ImageIOBase::FIXEDARRAY:
        case itk::ImageIOBase::MATRIX:
          break;
        default:
          filter->setErrorCondition(-2);
          QString message = QObject::tr("Unable to read image '%1'").arg(filter->getInputFileName());
          filter->notifyErrorMessage(filter->getHumanLabel(), message, filter->getErrorCondition());
          outputIDataArray->resize(0);
      }

      try
      {
        readerObject->Update();
      }
      catch( itk::ExceptionObject& err )
      {
        filter->setErrorCondition(-5);
        QString ss = QObject::tr("Failed to read image '%1': %2").arg(inputFile).arg(err.GetDescription());
        filter->notifyErrorMessage(filter->getHumanLabel(), ss, filter->getErrorCondition());
      }
    }
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void RegularizeZSpacing::execute()
{
    setErrorCondition(0);
    dataCheck();
    if(getErrorCondition() < 0) {
        return;
    }

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

    size_t dims[3];
    m->getGeometryAs<ImageGeom>()->getDimensions(dims);

    std::ifstream inFile;
    inFile.open(m_InputFile.toLatin1().data());

    float zval = 0.0f;
    std::vector<float> zboundvalues(dims[2] + 1, 0.0);
    for (size_t iter = 0; iter < dims[2] + 1; iter++)
    {
        inFile >> zval;
        zboundvalues[iter] = zval;
    }
    inFile.close();

    float xRes = m->getGeometryAs<ImageGeom>()->getXRes();
    float yRes = m->getGeometryAs<ImageGeom>()->getYRes();

    float sizez = zboundvalues[dims[2]];
    size_t m_XP = dims[0];
    size_t m_YP = dims[1];
    size_t m_ZP = static_cast<size_t>(sizez / m_NewZRes);
    if (m_ZP == 0) {
        m_ZP = 1;
    }
    size_t totalPoints = m_XP * m_YP * m_ZP;

    size_t index = 0, oldindex = 0;
    size_t plane = 0;
    std::vector<size_t> newindicies(totalPoints, 0);
    for (size_t i = 0; i < m_ZP; i++)
    {
        plane = 0;
        for (size_t iter = 1; iter < dims[2]; iter++)
        {
            if ((i * m_NewZRes) > zboundvalues[iter]) {
                plane = iter;
            }
        }
        for (size_t j = 0; j < m_YP; j++)
        {
            for (size_t k = 0; k < m_XP; k++)
            {
                oldindex = (plane * dims[0] * dims[1]) + (j * dims[0]) + k;
                index = (i * dims[0] * dims[1]) + (j * dims[0]) + k;
                newindicies[index] = oldindex;
            }
        }
    }

    AttributeMatrix::Pointer cellAttrMat = m->getAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
    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(xRes, yRes, m_NewZRes);
    m->getGeometryAs<ImageGeom>()->setDimensions(m_XP, m_YP, m_ZP);
    m->removeAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName());
    m->addAttributeMatrix(getCellAttributeMatrixPath().getAttributeMatrixName(), newCellAttrMat);

    notifyStatusMessage(getHumanLabel(), "Complete");
}