void TestWritingBinaryFormat()
    {
        //Read as ascii
        TrianglesMeshReader<2,2> reader("mesh/test/data/mixed_dimension_meshes/2D_0_to_1mm_200_elements");

        //Write as binary
        TrianglesMeshWriter<2,2> writer_from_reader("TestMixedDimensionMesh", "CableMeshBinary", false);
        writer_from_reader.SetWriteFilesAsBinary();
        writer_from_reader.WriteFilesUsingMeshReader(reader);

        PetscTools::Barrier();
        //Read created binary file into a mesh
        std::string results_dir = OutputFileHandler::GetChasteTestOutputDirectory() + "TestMixedDimensionMesh/";
        TrianglesMeshReader<2,2> binary_reader(results_dir + "CableMeshBinary");
        MixedDimensionMesh<2,2> binary_mesh(DistributedTetrahedralMeshPartitionType::DUMB);
        binary_mesh.ConstructFromMeshReader(binary_reader);

        //Read original file into a mesh
        std::string mesh_base("mesh/test/data/mixed_dimension_meshes/2D_0_to_1mm_200_elements");
        TrianglesMeshReader<2,2> original_reader(mesh_base);
        MixedDimensionMesh<2,2> original_mesh(DistributedTetrahedralMeshPartitionType::DUMB);
        original_mesh.ConstructFromMeshReader(original_reader);

        //Compare to original
        TS_ASSERT_EQUALS(binary_mesh.GetNumNodes(), original_mesh.GetNumNodes());
        TS_ASSERT_EQUALS(binary_mesh.GetNumElements(), original_mesh.GetNumElements());

        TS_ASSERT_EQUALS(binary_mesh.GetNumCableElements(), original_mesh.GetNumCableElements());

        MixedDimensionMesh<2,2>::CableElementIterator original_iter = original_mesh.GetCableElementIteratorBegin();
        for (MixedDimensionMesh<2,2>::CableElementIterator binary_iter = binary_mesh.GetCableElementIteratorBegin();
             binary_iter != binary_mesh.GetCableElementIteratorEnd();
             ++binary_iter)
        {
            TS_ASSERT_EQUALS((*binary_iter)->GetNumNodes(), (*original_iter)->GetNumNodes());
            TS_ASSERT_EQUALS((*binary_iter)->GetNodeGlobalIndex(0u), (*original_iter)->GetNodeGlobalIndex(0u));
            TS_ASSERT_EQUALS((*binary_iter)->GetNodeGlobalIndex(1u), (*original_iter)->GetNodeGlobalIndex(1u));
            TS_ASSERT_DELTA((*binary_iter)->GetAttribute(), (*original_iter)->GetAttribute(), 1e-12);

            ++original_iter;
        }

        //Write a binary from the original mesh
        TrianglesMeshWriter<2,2> writer_from_mesh("TestMixedDimensionMesh", "CableMeshBinaryFromMesh", false);
        writer_from_mesh.SetWriteFilesAsBinary();
        writer_from_mesh.WriteFilesUsingMesh(original_mesh);

        //Compare the binary written from the reader to the binary written from the mesh
        FileFinder generated(results_dir + "/CableMeshBinary.cable");
        FileFinder reference(results_dir + "/CableMeshBinaryFromMesh.cable");
        FileComparison comparer(generated,reference);
        TS_ASSERT(comparer.CompareFiles());
    }
    bool make_statistic::run(viennamesh::algorithm_handle &)
    {
        info(1) << "make_statistic started:" << std::endl;

        mesh_handle input_mesh = get_required_input<mesh_handle>("mesh");

        /*original mesh for comparison statistics (hausdorff distance, curvature difference...)*/
        mesh_handle original_mesh = get_input<mesh_handle>("original_mesh");

        /*All provided cell quality metric types are implemented as header files, which are located in statistics/metrics.
         * Note that most metrics are only implemented for triangles*/
        data_handle<viennamesh_string> metric_type = get_required_input<viennamesh_string>("metric_type");

        /*Decision threshold for triangle qualitity classification
         * E.g., radius_ratio < 1.5
         * Whether '<' or '>' is used for comparison is deduced from metric_ordering_tag*/
        data_handle<viennagrid_numeric> good_element_threshold = get_input<viennagrid_numeric>("good_element_threshold");

        /* comprehensive mesh quality metric is defined as
             alpha * (1 - good_elements_counted/count) + beta * min_dist_rms + gamma * mean_curvature + delta * volume_deviation;
        */
        data_handle<viennagrid_numeric> alpha = get_input<viennagrid_numeric>("alpha");
        data_handle<viennagrid_numeric> beta = get_input<viennagrid_numeric>("beta");
        data_handle<viennagrid_numeric> gamma = get_input<viennagrid_numeric>("gamma");
        data_handle<viennagrid_numeric> delta = get_input<viennagrid_numeric>("delta");

#if HIST
        data_handle<viennagrid_numeric> histogram_bins = get_input<viennagrid_numeric>("histogram_bin");
        data_handle<viennagrid_numeric> histogram_min = get_input<viennagrid_numeric>("histogram_min");
        data_handle<viennagrid_numeric> histogram_max = get_input<viennagrid_numeric>("histogram_max");
        data_handle<int> histogram_bin_count = get_input<int>("histogram_bin_count");
#endif


        typedef viennagrid::mesh                                  MeshType;
        typedef viennagrid::result_of::element<MeshType>::type    ElementType; //=Triangle or Tetrahedron

        typedef viennamesh::statistic<viennagrid_numeric>         StatisticType;
        StatisticType statistic;

#if HIST
        typedef StatisticType::histogram_type                     HistogramType;


        if (histogram_bins.valid())
        {
            std::vector<viennagrid_numeric> bins;
            for (int i = 0; i != histogram_bins.size(); ++i)
                bins.push_back( histogram_bins(i) );

            statistic.set_histogram( StatisticType::histogram_type::make(bins.begin(), bins.end()) );
        }
        else if (histogram_min.valid() && histogram_max.valid() && histogram_bin_count.valid())
        {
            statistic.set_histogram( StatisticType::histogram_type::make_uniform(histogram_min(), histogram_max(), histogram_bin_count()) );
        }
        else
        {
            //If histograms are about to be added again, returing false here will prevent the basic statistics features from working!
            error(1) << "No histogram configuration provided" << std::endl;
            return false;
        }
#endif





        //Good element threshold input was set, call statistics with the appropriate metric
        if(good_element_threshold.valid())
        {
            viennamesh::LoggingStack stack( std::string("High quality cell counter with metric type \"") + metric_type() + "\"" );

            if (metric_type() == "aspect_ratio")
                statistic.cell_quality_count<viennamesh::aspect_ratio_tag>( input_mesh(), viennamesh::aspect_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "min_angle")
                statistic.cell_quality_count<viennamesh::min_angle_tag>( input_mesh(), viennamesh::min_angle<ElementType>, good_element_threshold());
            else if (metric_type() == "max_angle")
                statistic.cell_quality_count<viennamesh::max_angle_tag>( input_mesh(), viennamesh::max_angle<ElementType>, good_element_threshold());
            else if (metric_type() == "min_dihedral_angle")
                statistic.cell_quality_count<viennamesh::min_dihedral_angle_tag>( input_mesh(), viennamesh::min_dihedral_angle<ElementType>, good_element_threshold());
            else if (metric_type() == "radius_edge_ratio")
                statistic.cell_quality_count<viennamesh::radius_edge_ratio_tag>( input_mesh(), viennamesh::radius_edge_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "radius_ratio")
                statistic.cell_quality_count<viennamesh::radius_ratio_tag>( input_mesh(), viennamesh::radius_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "perimeter_inradius_ratio")
                statistic.cell_quality_count<viennamesh::perimeter_inradius_ratio_tag>( input_mesh(), viennamesh::perimeter_inradius_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "edge_ratio")
                statistic.cell_quality_count<viennamesh::edge_ratio_tag>( input_mesh(), viennamesh::edge_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "circum_perimeter_ratio")
                statistic.cell_quality_count<viennamesh::circum_perimeter_ratio_tag>( input_mesh(), viennamesh::circum_perimeter_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "stretch")
                statistic.cell_quality_count<viennamesh::stretch_tag>( input_mesh(), viennamesh::stretch<ElementType>, good_element_threshold());
            else if (metric_type() == "skewness")
                statistic.cell_quality_count<viennamesh::skewness_tag>( input_mesh(), viennamesh::skewness<ElementType>, good_element_threshold());
            else
            {
                error(1) << "Metric type \"" << metric_type() << "\" is not supported for cell quality classifaction" << std::endl;
                return false;
            }
        }
        else //no triangle classifiction takes place
        {
            viennamesh::LoggingStack stack( std::string("Cell statistics with metric type \"") + metric_type() + "\"" );

            if (metric_type() == "aspect_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::aspect_ratio<ElementType> );
            else if (metric_type() == "min_angle")
                statistic.cell_stats( input_mesh(), viennamesh::min_angle<ElementType> );
            else if (metric_type() == "max_angle")
                statistic.cell_stats( input_mesh(), viennamesh::max_angle<ElementType> );
            else if (metric_type() == "min_dihedral_angle")
                statistic.cell_stats( input_mesh(), viennamesh::min_dihedral_angle<ElementType> );
            else if (metric_type() == "radius_edge_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::radius_edge_ratio<ElementType> );
            else if (metric_type() == "radius_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::radius_ratio<ElementType> );
            else if (metric_type() == "perimeter_inradius_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::perimeter_inradius_ratio<ElementType> );
            else if (metric_type() == "edge_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::edge_ratio<ElementType> );
            else if (metric_type() == "circum_perimeter_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::circum_perimeter_ratio<ElementType> );
            else if (metric_type() == "stretch")
                statistic.cell_stats( input_mesh(), viennamesh::stretch<ElementType> );
            else if (metric_type() == "skewness")
                statistic.cell_stats( input_mesh(), viennamesh::skewness<ElementType> );
            else
            {
                error(1) << "Metric type \"" << metric_type() << "\" is not supported" << std::endl;
                return false;
            }
        }

        if(original_mesh.valid())//a second mesh is set, calculate mesh comparison measures
        {
            viennamesh::LoggingStack stack( std::string("Calculation of Mesh Comparison Measures") );

            statistic.mesh_comparison_quality(input_mesh(), original_mesh());



            ConstTriangleRange tr_orig(original_mesh());
            ConstTriangleRange tr(input_mesh());

            StatisticType statistic_orig;
            statistic_orig.cell_stats( original_mesh(), viennamesh::aspect_ratio<ElementType> );


            //use median of orig mesh for input mesh triangle shape characterization
            statistic.cell_quality_count<viennamesh::aspect_ratio_tag>( input_mesh(), viennamesh::aspect_ratio<ElementType>, statistic_orig.median());

            if(alpha.valid() && beta.valid() && gamma.valid() && delta.valid() )
            {
                statistic.set_mesh_quality_weights(alpha(), beta(), gamma(), delta());
                info(5) << "values for comprehensive mesh quality metric: alpha = " << alpha()
                        << ", beta = " << beta() << ", gamma = " << gamma() << ", delta = "<< delta() <<  std::endl;

            }
            else
            {
                info(5) << "default values for comprehensive mesh quality metric used: alpha = 0.25, beta = 20, gamma = 1.0, delta = 1.3" << std::endl;
            }

            set_output("minimum_distance_rms", statistic.min_dist_rms());
            set_output("mean_curvature_difference", statistic.mean_curvature());
            set_output("area_deviation", statistic.volume_deviation());
            set_output("triangle_shape", statistic.good_elements()/statistic.count());
            set_output("mesh_quality_metric", statistic.mesh_quality_metric());
        }


        info(5) << statistic << "\n";

#if HIST
        statistic.normalize();
        std::vector<viennagrid_numeric> bins;
        for (HistogramType::const_iterator bit = statistic.histogram().begin(); bit != statistic.histogram().end(); ++bit)
            bins.push_back( (*bit).second );
        bins.push_back( statistic.histogram().overflow_bin() );

        data_handle<viennagrid_numeric> output_bins = make_data<viennagrid_numeric>();
        output_bins.set( bins );
        set_output( "bins", output_bins );
#endif

        set_output( "min", statistic.min() );
        set_output( "max", statistic.max() );
        set_output( "mean", statistic.mean() );
        set_output( "median", statistic.median());

        return true;
    }