// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void readPipeline(QFilterParametersReader::Pointer paramsReader, FilterPipeline::Pointer pipeline)
{
  FilterManager* filtManager = FilterManager::Instance();
  QSettings* prefs = paramsReader->getPrefs();
  prefs->beginGroup(DREAM3D::Settings::PipelineBuilderGroup);
  bool ok = false;
  int filterCount = prefs->value("Number_Filters").toInt(&ok);
  prefs->endGroup();
  if (false == ok) {filterCount = 0;}

  for (int i = 0; i < filterCount; ++i)
  {
    QString gName = QString::number(i);

    // Open the group to get the name of the filter then close again.
    prefs->beginGroup(gName);
    QString filterName = prefs->value("Filter_Name", "").toString();
    prefs->endGroup();
    //  qDebug() << filterName;

    IFilterFactory::Pointer factory = filtManager->getFactoryForFilter(filterName);
    AbstractFilter::Pointer filter = factory->create();

    if(NULL != filter.get())
    {
      filter->readFilterParameters(paramsReader.get(), i);
      pipeline->pushBack(filter);
    }
  }
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int QFilterParametersWriter::WritePipelineToFile(FilterPipeline::Pointer pipeline, const QString& filePath, const QString& name, QSettings::Format format, IObserver* obs)
{

  if(NULL == pipeline.get())
  {
    if(NULL != obs)
    {
      PipelineMessage pm(QFilterParametersWriter::ClassName(), "FilterPipeline Object was NULL for writing", -1, PipelineMessage::Error);
      obs->processPipelineMessage(pm);
    }
    return -1;
  }

  FilterPipeline::FilterContainerType& filters = pipeline->getFilterContainer();

  QFilterParametersWriter::Pointer writer = QFilterParametersWriter::New();
  // This will open the file, and write/update the initial group of settings like the name and DREAM3D Version
  writer->openFile(filePath, format);
  // Loop over each filter and write it's input parameters to the file
  int count = filters.size();
  int index = 0;
  for(qint32 i = 0; i < count; ++i)
  {
    AbstractFilter::Pointer filter = filters.at(i);
    if(NULL != filter.get())
    {
      index = filter->writeFilterParameters(writer.get(), index);
    }
    else
    {
      AbstractFilter::Pointer badFilter = AbstractFilter::New();
      writer->openFilterGroup(badFilter.get(), i);
      writer->writeValue("Unkown Filter", "ERROR: Filter instance was NULL within the PipelineFilterWidget instance. Report this error to the DREAM3D Developers");
      writer->closeFilterGroup();
    }
  }

  writer->setNumberOfFilters(index);
  writer->setPipelineName(name);
  writer->closeFile(); // Close the file
  return 0;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void ExecutePipeline(const QString& pipelineFile)
{
  int err = EXIT_SUCCESS;

  // Sanity Check the filepath to make sure it exists, Report an error and bail if it does not
  QFileInfo fi(pipelineFile);
  std::cout << "<--------------Test Pipeline File: " << fi.absoluteFilePath().toStdString() << " --------------------------->" << std::endl;
  if(fi.exists() == false)
  {
    std::cout << "The input file '" << pipelineFile.toStdString() << "' does not exist" << std::endl;
    err = EXIT_FAILURE;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)

  QString ext = fi.completeSuffix();

  // Use the static method to read the Pipeline file and return a Filter Pipeline
  FilterPipeline::Pointer pipeline;
  if (ext == "ini" || ext == "txt")
  {
    pipeline = QFilterParametersReader::ReadPipelineFromFile(pipelineFile, QSettings::IniFormat);
  }
  else if (ext == "dream3d")
  {
    pipeline = H5FilterParametersReader::ReadPipelineFromFile(pipelineFile);
  }
  else if (ext == "json")
  {
    pipeline = JsonFilterParametersReader::ReadPipelineFromFile(pipelineFile);
  }

  if (NULL == pipeline.get())
  {
    std::cout << "An error occurred trying to read the pipeline file. Exiting now." << std::endl;
    err = EXIT_FAILURE;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)


  Observer obs; // Create an Observer to report errors/progress from the executing pipeline
  pipeline->addMessageReceiver(&obs);
  // Preflight the pipeline
  err = pipeline->preflightPipeline();
  if (err < 0)
  {
    std::cout << "Errors preflighting the pipeline. Exiting Now." << std::endl;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)

  // Now actually execute the pipeline
  pipeline->execute();
  err = pipeline->getErrorCondition();
  if (err < 0)
  {
    std::cout << "Error Condition of Pipeline: " << err << std::endl;
    err = EXIT_FAILURE;
  }
  DREAM3D_REQUIRE_EQUAL(err, EXIT_SUCCESS)

}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
int H5FilterParametersWriter::WritePipelineToFile(FilterPipeline::Pointer pipeline, QString filePath, QString name, IObserver* obs)
{
  if (NULL == pipeline.get())
  {
    if (NULL != obs)
    {
      PipelineMessage pm(H5FilterParametersWriter::ClassName(), "FilterPipeline Object was NULL for writing", -1, PipelineMessage::Error);
      obs->processPipelineMessage(pm);
    }
    return -1;
  }

  QFileInfo fileInfo(filePath);

  // WRITE THE PIPELINE TO THE HDF5 FILE
  H5FilterParametersWriter::Pointer writer = H5FilterParametersWriter::New();

  hid_t fileId = -1;

  fileId = QH5Utilities::createFile(filePath);
  if (fileId < 0)
  {
    if (NULL != obs)
    {
      PipelineMessage pm(H5FilterParametersWriter::ClassName(), "Output .dream3d file could not be created.", -1, PipelineMessage::Error);
      obs->processPipelineMessage(pm);
    }
    return -1;
  }

  // This will make sure if we return early from this method that the HDF5 File is properly closed.
  // This will also take care of making sure all groups and file ids are closed
  // before this method returns.
  HDF5ScopedFileSentinel scopedFileSentinel(&fileId, true);

  // Write our File Version string to the Root "/" group
  QH5Lite::writeStringAttribute(fileId, "/", DREAM3D::HDF5::FileVersionName, DREAM3D::HDF5::FileVersion);
  QH5Lite::writeStringAttribute(fileId, "/", DREAM3D::HDF5::DREAM3DVersion, DREAM3DLib::Version::Complete() );

  hid_t pipelineGroupId = QH5Utilities::createGroup(fileId, DREAM3D::StringConstants::PipelineGroupName);
  scopedFileSentinel.addGroupId(&pipelineGroupId);
  writer->setGroupId(pipelineGroupId);

  FilterPipeline::FilterContainerType& filters = pipeline->getFilterContainer();

  // Loop over each filter and write it's input parameters to the file
  int count = filters.size();
  int index = 0;
  for (qint32 i = 0; i < count; ++i)
  {
    AbstractFilter::Pointer filter = filters.at(i);
    if (NULL != filter.get())
    {
      index = filter->writeFilterParameters(writer.get(), index);
    }
    else
    {
      AbstractFilter::Pointer badFilter = AbstractFilter::New();
      writer->openFilterGroup(badFilter.get(), i);
      writer->writeValue("Unknown Filter", "ERROR: Filter instance was NULL within the PipelineFilterWidget instance. Report this error to the DREAM3D Developers");
      writer->closeFilterGroup();
    }
  }

  return 0;
}
void CropVolumePipeline::execute()
{
    VoxelDataContainer* m = getVoxelDataContainer();
  float m_MisorientationTolerance = 5.0f;
  float m_AlignMisorientationTolerance = 5.0f;
  float m_Zres = 4.0f;
  int m_MinAllowedGrainSize = 10;
  int m_MinNumNeighbors = 1;
  int m_PhaseNumberMinSize = 1;
  int m_NumIterations_Erode = 3;
  int NUM_OF_CROPS = getNumLinesinFile(m_InputFile);

  std::vector<int> m_Xmin(NUM_OF_CROPS+1, 0);
  std::vector<int> m_Ymin(NUM_OF_CROPS+1, 0);
  std::vector<int> m_Zmin(NUM_OF_CROPS+1, 0);
  std::vector<int> m_Xmax(NUM_OF_CROPS+1, 0);
  std::vector<int> m_Ymax(NUM_OF_CROPS+1, 0);
  std::vector<int> m_Zmax(NUM_OF_CROPS+1, 0);

  get_max_and_min_xyz_for_crop(m_Xmax, m_Ymax, m_Zmax, m_Xmin, m_Ymin, m_Zmin);

  /*  int m_Zmin = 1 ;
  int m_Xmax = 495;
  int m_Ymax = 355;
  int m_Zmax = 163;*/

for (DimType i = 1; i < NUM_OF_CROPS+1; i++)
{


      // Create our Pipeline object
      FilterPipeline::Pointer pipeline = FilterPipeline::New();




     // updateProgressAndMessage(("Loading Slices"), 10);
      ReadH5Ebsd::Pointer read_h5ebsd = ReadH5Ebsd::New();

      read_h5ebsd->setH5EbsdFile(getH5EbsdFile());
      //read_h5ebsd->setRefFrameZDir(Ebsd::LowtoHigh);
      read_h5ebsd->setZStartIndex(getZStartIndex());
      read_h5ebsd->setZEndIndex(getZEndIndex());
      read_h5ebsd->setPTypes(getPhaseTypes());
      read_h5ebsd->setQualityMetricFilters(getQualityMetricFilters());
      read_h5ebsd->setVoxelDataContainer(m);
      read_h5ebsd->execute();
      pipeline->pushBack(read_h5ebsd);



      ConvertEulerAngles::Pointer convert_euler = ConvertEulerAngles::New();
      convert_euler->setConversionType(DREAM3D::EulerAngleConversionType::DegreesToRadians);
      convert_euler->setVoxelDataContainer(m);
      convert_euler->execute();
      pipeline->pushBack(convert_euler);


      AlignSectionsMisorientation::Pointer align_sections = AlignSectionsMisorientation::New();
      align_sections->setMisorientationTolerance(m_AlignMisorientationTolerance);
      align_sections->setVoxelDataContainer(m);
      align_sections->execute();
      pipeline->pushBack(align_sections);

      CropVolume::Pointer crop_volume = CropVolume::New();
      crop_volume->setXMin(m_Xmin[i]);
      crop_volume->setYMin(m_Ymin[i]);
      crop_volume->setZMin(m_Zmin[i]);
      crop_volume->setXMax(m_Xmax[i]);
      crop_volume->setYMax(m_Ymax[i]);
      crop_volume->setZMax(m_Zmax[i]);
      crop_volume->setRenumberGrains(false);
      crop_volume->setVoxelDataContainer(m);
      crop_volume->execute();
      pipeline->pushBack(crop_volume);

      RegularizeZSpacing::Pointer regularize_z = RegularizeZSpacing::New();
      regularize_z->setInputFile(getZ_spacingfile());
      regularize_z->setZRes(m_Zres);
      regularize_z->setVoxelDataContainer(m);
      regularize_z->execute();
      pipeline->pushBack(regularize_z);

      EBSDSegmentGrains::Pointer ebsdsegment_grains = EBSDSegmentGrains::New();
      ebsdsegment_grains->setMisorientationTolerance(m_MisorientationTolerance);
      ebsdsegment_grains->setVoxelDataContainer(m);
      ebsdsegment_grains->execute();
      pipeline->pushBack(ebsdsegment_grains);

      OpenCloseBadData::Pointer erode_dilate = OpenCloseBadData::New();
      erode_dilate->setDirection(1); // 1 is erode.
      erode_dilate->setNumIterations(m_NumIterations_Erode);
      erode_dilate->setVoxelDataContainer(m);
      erode_dilate->execute();
      pipeline->pushBack(erode_dilate);

      FindNeighbors::Pointer find_neighbors = FindNeighbors::New();
      find_neighbors->setVoxelDataContainer(m);
      find_neighbors->execute();
      pipeline->pushBack(find_neighbors);


      PerPhaseMinSize::Pointer min_size = PerPhaseMinSize::New();
      min_size->setMinAllowedGrainSize(m_MinAllowedGrainSize);
      min_size->setPhaseNumber(m_PhaseNumberMinSize);
      min_size->setVoxelDataContainer(m);
      min_size->execute();
      pipeline->pushBack(min_size);

      MinNeighbors::Pointer min_neighbors = MinNeighbors::New();
      min_neighbors->setMinNumNeighbors(m_MinNumNeighbors);
      min_neighbors->setVoxelDataContainer(m);
      min_neighbors->execute();
      pipeline->pushBack(min_neighbors);

      FindSizes::Pointer find_sizes = FindSizes::New();
      //find_sizes->setDistributionType(DREAM3D::DistributionType::Beta);
      find_sizes->setVoxelDataContainer(m);
      find_sizes->execute();
      pipeline->pushBack(find_sizes);


      FindShapes::Pointer find_shapes = FindShapes::New();
      //find_shapes->setDistributionType(DREAM3D::DistributionType::Beta);
      find_shapes->setVoxelDataContainer(m);
      find_shapes->execute();
      pipeline->pushBack(find_shapes);



      FieldDataCSVWriter::Pointer field_data_write_csv = FieldDataCSVWriter::New();
      std::string field_csv =  "D:/IN100_run1/DREAM3D_files/crop_line_"+ convertIntToString(i) +".csv";
      field_data_write_csv->setFieldDataFile(field_csv);
      field_data_write_csv->setVoxelDataContainer(m);
      field_data_write_csv->execute();
      pipeline->pushBack(field_data_write_csv);



      bool m_WriteVtkFile = true ;
      bool m_WriteBinaryVTKFiles= true ;
      bool m_WriteGrainID= true;
      bool m_WritePhaseId= true ;
      bool m_WriteIPFColor= true ;
      bool m_WriteGoodVoxels= true ;
      bool m_WriteGrainSizes = true ;
      bool m_WriteBandContrasts = true ;

      VtkRectilinearGridWriter::Pointer vtkWriter = VtkRectilinearGridWriter::New();

      if(m_WriteVtkFile)
      {
        std::string vtk_file = "D:/IN100_run1/DREAM3D_files/crop_line_" + convertIntToString(i) + ".vtk";
        vtkWriter->setOutputFile(vtk_file);
        vtkWriter->setWriteGrainIds(m_WriteGrainID);
        vtkWriter->setWritePhaseIds(m_WritePhaseId);
        vtkWriter->setWriteBandContrasts(m_WriteBandContrasts);
        vtkWriter->setWriteGoodVoxels(m_WriteGoodVoxels);
        vtkWriter->setWriteIPFColors(m_WriteIPFColor);
        vtkWriter->setWriteBinaryFile(m_WriteBinaryVTKFiles);
        vtkWriter->setWriteBinaryFile(m_WriteGrainSizes);
        vtkWriter->setVoxelDataContainer(m);
        vtkWriter->execute();
        pipeline->pushBack(vtkWriter);
      }

      DataContainerWriter::Pointer writer = DataContainerWriter::New();
      std::string dream_3d_file = "D:/IN100_run1/DREAM3D_files/crop_line_" + convertIntToString(i) + ".dream3d";
      writer->setOutputFile(dream_3d_file);
      writer->setVoxelDataContainer(m);
      pipeline->pushBack(writer);
      writer->execute();



    //  std::cout << "********* RUNNING PIPELINE **********************" << std::endl;
    // // pipeline->run();
      pipeline->clear();


      //delete [] m;
      m->clearCellData();
      m->clearEnsembleData();
      m->clearFieldData();



}
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void TestSyntheticBuilder()
{

  MXADir::mkdir(m_OutputDirectory, true);

  Observer* observer = new Observer;


  int err = 0;

  // Create our Pipeline object
  FilterPipeline::Pointer pipeline = FilterPipeline::New();
  VoxelDataContainer::Pointer m = VoxelDataContainer::New();
  pipeline->setVoxelDataContainer(m);

    ShapeTypeArrayType::Pointer m_ShapeTypes = ShapeTypeArrayType::CreateArray(4, DREAM3D::EnsembleData::ShapeTypes);
    m_ShapeTypes->SetValue(0, DREAM3D::ShapeType::UnknownShapeType);
    m_ShapeTypes->SetValue(1, DREAM3D::ShapeType::EllipsoidShape);
    m_ShapeTypes->SetValue(2, DREAM3D::ShapeType::EllipsoidShape);
    m_ShapeTypes->SetValue(3, DREAM3D::ShapeType::EllipsoidShape);

    InitializeSyntheticVolume::Pointer init_volume = InitializeSyntheticVolume::New();
    init_volume->setShapeTypes(m_ShapeTypes);
    init_volume->setInputFile(getH5StatsFile());
    init_volume->setXVoxels(m_XPoints);
    init_volume->setYVoxels(m_YPoints);
    init_volume->setZVoxels(m_ZPoints);
    init_volume->setXRes(m_XResolution);
    init_volume->setYRes(m_YResolution);
    init_volume->setZRes(m_ZResolution);
	pipeline->pushBack(init_volume);

    PackPrimaryPhases::Pointer pack_grains = PackPrimaryPhases::New();
    pack_grains->setPeriodicBoundaries(m_PeriodicBoundary);
    pack_grains->setNeighborhoodErrorWeight(m_NeighborhoodErrorWeight);
#if PACK_GRAINS_ERROR_TXT_OUT
    MAKE_OUTPUT_FILE_PATH( errorFile, DREAM3D::SyntheticBuilder::ErrorFile)
    pack_grains->setErrorOutputFile(errorFile);
#endif
#if PACK_GRAINS_VTK_FILE_OUT
    MAKE_OUTPUT_FILE_PATH( vtkFile, DREAM3D::SyntheticBuilder::VtkFile)
    pack_grains->setVtkOutputFile(vtkFile);
#endif
    pipeline->pushBack(pack_grains);

    AdjustVolume::Pointer adjust_grains = AdjustVolume::New();
    pipeline->pushBack(adjust_grains);

    InsertPrecipitatePhases::Pointer place_precipitates = InsertPrecipitatePhases::New();
    place_precipitates->setPeriodicBoundaries(m_PeriodicBoundary);
    pipeline->pushBack(place_precipitates);

  MatchCrystallography::Pointer match_crystallography = MatchCrystallography::New();
//  pipeline->pushBack(match_crystallography);

  FieldDataCSVWriter::Pointer write_fielddata = FieldDataCSVWriter::New();
  write_fielddata->setFieldDataFile(UnitTest::SyntheticBuilderTest::CsvFile);
  pipeline->pushBack(write_fielddata);

  DataContainerWriter::Pointer writer = DataContainerWriter::New();
  writer->setOutputFile(UnitTest::SyntheticBuilderTest::OutputFile);
  pipeline->pushBack(writer);

  bool m_WriteVtkFile(true);
  bool m_WriteBinaryVTKFiles(true);
  bool m_WritePhaseId(true);
  bool m_WriteIPFColor(false);

  if(m_WriteVtkFile)
  {
    VtkRectilinearGridWriter::Pointer vtkWriter = VtkRectilinearGridWriter::New();
    vtkWriter->setOutputFile(UnitTest::SyntheticBuilderTest::VtkOutputFile);
    vtkWriter->setWriteGrainIds(true);
    vtkWriter->setWritePhaseIds(m_WritePhaseId);
   // vtkWriter->setWriteGoodVoxels(m_WriteGoodVoxels);
    vtkWriter->setWriteIPFColors(m_WriteIPFColor);
    vtkWriter->setWriteBinaryFile(m_WriteBinaryVTKFiles);
    pipeline->pushBack(vtkWriter);
  }

  std::cout << "********* RUNNING PIPELINE **********************" << std::endl;

  m = VoxelDataContainer::New();

  pipeline->setVoxelDataContainer(m);
  pipeline->run();
  err = pipeline->getErrorCondition();
  DREAM3D_REQUIRE_EQUAL(err, 0);

  DREAM3D_REQUIRE_EQUAL(false, pipeline->empty());

  pipeline->clear();
  DREAM3D_REQUIRE_EQUAL(0, pipeline->size());
  DREAM3D_REQUIRE_EQUAL(true, pipeline->empty());

  delete observer;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
FilterPipeline::Pointer JsonFilterParametersReader::ReadPipelineFromFile(QString filePath, IObserver* obs)
{
    QFileInfo fInfo(filePath);

    if (filePath.isEmpty() == true)
    {
        return FilterPipeline::NullPointer();
    }
    QFileInfo fi(filePath);
    if (fi.exists() == false)
    {
        return FilterPipeline::NullPointer();
    }

    FilterManager* filtManager = FilterManager::Instance();
    FilterFactory<EmptyFilter>::Pointer emptyFilterFactory = FilterFactory<EmptyFilter>::New();
    filtManager->addFilterFactory("EmptyFilter", emptyFilterFactory);

    JsonFilterParametersReader::Pointer reader = JsonFilterParametersReader::New();
    int err = reader->openFile(filePath);

    if (err < 0)
    {
        if (NULL != obs)
        {
            PipelineMessage pm(JsonFilterParametersReader::ClassName(), "File '" + fInfo.fileName() + "' could not be opened for reading.", -1, PipelineMessage::Error);
            obs->processPipelineMessage(pm);
        }
        return FilterPipeline::NullPointer();
    }

    reader->openGroup(DREAM3D::Settings::PipelineBuilderGroup);
    int filterCount = reader->readValue(DREAM3D::Settings::NumFilters, 0);
    reader->closeGroup();

    FilterPipeline::Pointer pipeline = FilterPipeline::New();

    for (int i = 0; i < filterCount; ++i)
    {
        // Open the group to get the name of the filter then close again.
        reader->openFilterGroup(NULL, i);
        QString filterName = reader->readString(DREAM3D::Settings::FilterName, "");
        reader->closeFilterGroup();
        //qDebug() << "Group: " << gName << " FilterName: " << filterName;
        if (filterName.isEmpty() == false)
        {
            IFilterFactory::Pointer factory = filtManager->getFactoryForFilter(filterName);
            if (factory.get() != NULL)
            {
                AbstractFilter::Pointer filter = factory->create();

                if (NULL != filter.get())
                {
                    filter->readFilterParameters(reader.get(), i);
                    pipeline->pushBack(filter);
                }
            }
            else // Could not find the filter because the specific name has not been registered. This could
                // be due to a name change for the filter.
            {
                EmptyFilter::Pointer filter = EmptyFilter::New();
                QString humanLabel = QString("UNKNOWN FILTER: ") + filterName;
                filter->setHumanLabel(humanLabel);
                filter->setOriginalFilterName(filterName);
                pipeline->pushBack(filter);

                if (NULL != obs)
                {
                    QString ss = QObject::tr("An implementation for filter '%1' could not be located. Possible reasons include a name change of the filter, plugin not loading or a simple spelling mistake? A blank filter has been inserted in its place.").arg(filterName);
                    PipelineMessage pm(filterName, ss, -66066, PipelineMessage::Error);
                    pm.setPrefix("JsonFilterParametersReader::ReadPipelineFromFile()");
                    obs->processPipelineMessage(pm);
                }
            }
        }
        else
        {
            EmptyFilter::Pointer filter = EmptyFilter::New();
            QString humanLabel = QString("MISSING FILTER: ") + filterName;
            filter->setHumanLabel(humanLabel);
            filter->setOriginalFilterName(filterName);
            pipeline->pushBack(filter);

            if (NULL != obs)
            {
                QString gName = QString::number(i);
                QString ss = QObject::tr("A filter for index '%1' is missing in the file. Is the numbering of the filters correct in the pipeline file?").arg(gName);
                PipelineMessage pm(filterName, ss, -66067, PipelineMessage::Error);
                pm.setPrefix("JsonFilterParametersReader::ReadPipelineFromFile()");
                obs->processPipelineMessage(pm);
            }
        }
    }
    return pipeline;
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void FilterParametersRWTest()
{
  // Create our Pipeline object
  FilterPipeline::Pointer pipeline = FilterPipeline::New();


  GenericFilter::Pointer filt = GenericFilter::New();

  // Set something for each and every property so you have something to compare against.
  // You may want to make some constants for these values
  filt->setStlFilePrefix(StlFilePrefixTestValue);
  filt->setMaxIterations(MaxIterationsTestValue);
  filt->setMisorientationTolerance(MisorientationToleranceTestValue);
  filt->setInputFile(InputFileTestValue);
  filt->setInputPath(InputPathTestValue);
  filt->setOutputFile(OutputFileTestValue);
  filt->setOutputPath(OutputPathTestValue);
  filt->setWriteAlignmentShifts(WriteAlignmentShiftsTestValue);
  filt->setConversionType(ConversionTypeTestValue);
  filt->setSelectedCellArrayName(SelectedCellArrayNameTestValue);
  filt->setSelectedFieldArrayName(SelectedFieldArrayNameTestValue);
  filt->setSelectedEnsembleArrayName(SelectedEnsembleArrayNameTestValue);
  filt->setSurfaceMeshPointArrayName(SurfaceMeshPointArrayNameTestValue);
  filt->setSurfaceMeshFaceArrayName(SurfaceMeshFaceArrayNameTestValue);
  filt->setSurfaceMeshEdgeArrayName(SurfaceMeshEdgeArrayNameTestValue);
  filt->setSolidMeshPointArrayName(SolidMeshPointArrayNameTestValue);
  filt->setSolidMeshFaceArrayName(SolidMeshFaceArrayNameTestValue);
  filt->setSolidMeshEdgeArrayName(SolidMeshEdgeArrayNameTestValue);

  ComparisonInput_t comparison1;
  comparison1.arrayName = Comparison1InputArrayNameTestValue;
  comparison1.compOperator = Comparison1CompOperatorTestValue;
  comparison1.compValue = Comparison1CompValueTestValue;

  ComparisonInput_t comparison2;
  comparison2.arrayName = Comparison2InputArrayNameTestValue;
  comparison2.compOperator = Comparison2CompOperatorTestValue;
  comparison2.compValue = Comparison2CompValueTestValue;

  std::vector<ComparisonInput_t> comparisonVector;
  comparisonVector.push_back(comparison1);
  comparisonVector.push_back(comparison2);
  filt->setCellComparisonInputs(comparisonVector);

  AxisAngleInput_t axisAngles1;
  axisAngles1.angle = AxisAngles1AngleTestValue;
  axisAngles1.h = AxisAngles1HTestValue;
  axisAngles1.k = AxisAngles1KTestValue;
  axisAngles1.l = AxisAngles1LTestValue;

  AxisAngleInput_t axisAngles2;
  axisAngles2.angle = AxisAngles2AngleTestValue;
  axisAngles2.h = AxisAngles2HTestValue;
  axisAngles2.k = AxisAngles2KTestValue;
  axisAngles2.l = AxisAngles2LTestValue;

  std::vector<AxisAngleInput_t> axisAngleInputsVector;
  axisAngleInputsVector.push_back(axisAngles1);
  axisAngleInputsVector.push_back(axisAngles2);
  filt->setAxisAngleRotations(axisAngleInputsVector);

  DataContainerWriter::Pointer writer = DataContainerWriter::New();
  writer->setOutputFile(UnitTest::FilterParametersRWTest::OutputFile);

  pipeline->pushBack(filt);
  pipeline->pushBack(writer);

  pipeline->execute();
  int err = pipeline->getErrorCondition();
  DREAM3D_REQUIRED(err, >= , 0)


  // We are done writing a file, now we need to read the file using raw HDF5 codes

  hid_t fid = H5Utilities::openFile(UnitTest::FilterParametersRWTest::OutputFile);
  DREAM3D_REQUIRED(fid, >, 0)

  H5FilterParametersReader::Pointer reader = H5FilterParametersReader::New();

  hid_t pipelineGroupId = H5Gopen(fid, DREAM3D::HDF5::PipelineGroupName.c_str(), H5P_DEFAULT);
  reader->setGroupId(pipelineGroupId);

  err = reader->openFilterGroup( filt.get(), 0); // Open the HDF5 Group for this filter
  DREAM3D_REQUIRED(err, >=, 0)

  // This next line should read all the filter parameters into the filter.
  filt->readFilterParameters( reader.get(), 0);

  // Now one by one, compare each of the filter parameters that you have stored in some constant somewhere to the values that are now in the filt variable.
  // Use DREAM3D_REQUIRED() to make sure each one is what you think it is.
  DREAM3D_REQUIRED(StlFilePrefixTestValue, ==, filt->getStlFilePrefix() )
  DREAM3D_REQUIRED(MaxIterationsTestValue, ==, filt->getMaxIterations() )
  DREAM3D_REQUIRED(MisorientationToleranceTestValue, ==, filt->getMisorientationTolerance() )
  DREAM3D_REQUIRED(InputFileTestValue, ==, filt->getInputFile() )
  DREAM3D_REQUIRED(InputPathTestValue, ==, filt->getInputPath() )
  DREAM3D_REQUIRED(OutputFileTestValue, ==, filt->getOutputFile() )
  DREAM3D_REQUIRED(OutputPathTestValue, ==, filt->getOutputPath() )
  DREAM3D_REQUIRED(WriteAlignmentShiftsTestValue, ==, filt->getWriteAlignmentShifts() )
  DREAM3D_REQUIRED(ConversionTypeTestValue, ==, filt->getConversionType() )
  DREAM3D_REQUIRED(SelectedCellArrayNameTestValue, ==, filt->getSelectedCellArrayName() )
  DREAM3D_REQUIRED(SelectedFieldArrayNameTestValue, ==, filt->getSelectedFieldArrayName() )
  DREAM3D_REQUIRED(SelectedEnsembleArrayNameTestValue, ==, filt->getSelectedEnsembleArrayName() )
  DREAM3D_REQUIRED(SurfaceMeshPointArrayNameTestValue, ==, filt->getSurfaceMeshPointArrayName() )
  DREAM3D_REQUIRED(SurfaceMeshFaceArrayNameTestValue, ==, filt->getSurfaceMeshFaceArrayName() )
  DREAM3D_REQUIRED(SurfaceMeshEdgeArrayNameTestValue, ==, filt->getSurfaceMeshEdgeArrayName() )
  DREAM3D_REQUIRED(SolidMeshPointArrayNameTestValue, ==, filt->getSolidMeshPointArrayName() )
  DREAM3D_REQUIRED(SolidMeshFaceArrayNameTestValue, ==, filt->getSolidMeshFaceArrayName() )
  DREAM3D_REQUIRED(SolidMeshEdgeArrayNameTestValue, ==, filt->getSolidMeshEdgeArrayName() )

  // Test the CellComparisonInputs widget
  std::vector<ComparisonInput_t> comparisonVectorRead = filt->getCellComparisonInputs();
  ComparisonInput_t comparison1Read = comparisonVectorRead[0];
  ComparisonInput_t comparison2Read = comparisonVectorRead[1];

  DREAM3D_REQUIRED(comparison1.arrayName, ==, comparison1Read.arrayName)
  DREAM3D_REQUIRED(comparison1.compOperator, ==, comparison1Read.compOperator)
  DREAM3D_REQUIRED(comparison1.compValue, ==, comparison1Read.compValue)
  DREAM3D_REQUIRED(comparison2.arrayName, ==, comparison2Read.arrayName)
  DREAM3D_REQUIRED(comparison2.compOperator, ==, comparison2Read.compOperator)
  DREAM3D_REQUIRED(comparison2.compValue, ==, comparison2Read.compValue)

  // Test the AxisAngleInput widget
  std::vector<AxisAngleInput_t> axisAngleVectorRead = filt->getAxisAngleRotations();
  AxisAngleInput_t axisAngles1Read = axisAngleVectorRead[0];
  AxisAngleInput_t axisAngles2Read = axisAngleVectorRead[1];

  DREAM3D_REQUIRED(axisAngles1.angle, ==, axisAngles1Read.angle)
  DREAM3D_REQUIRED(axisAngles1.h, ==, axisAngles1Read.h)
  DREAM3D_REQUIRED(axisAngles1.k, ==, axisAngles1Read.k)
  DREAM3D_REQUIRED(axisAngles1.l, ==, axisAngles1Read.l)
  DREAM3D_REQUIRED(axisAngles2.angle, ==, axisAngles2Read.angle)
  DREAM3D_REQUIRED(axisAngles2.h, ==, axisAngles2Read.h)
  DREAM3D_REQUIRED(axisAngles2.k, ==, axisAngles2Read.k)
  DREAM3D_REQUIRED(axisAngles2.l, ==, axisAngles2Read.l)

  err = reader->closeFilterGroup(); // Close the HDF5 group for this filter
  DREAM3D_REQUIRED(err, >=, 0)


  H5Gclose(pipelineGroupId); // Closes the "Pipeline" group
  H5Fclose(fid); // Closes the file
}