#ifndef IO_OUTPUT_DEBUG_TRACES_TO_HTML_H_ #define IO_OUTPUT_DEBUG_TRACES_TO_HTML_H_ #ifdef DEBUG_TRACES // All this part of code can be skipped if DEBUG_TRACES are not ON - cmake -DDEBUG_TRACES=ON . #include #include #include #include #include #include #include namespace Gudhi { namespace coxeter_triangulation { template std::ostream& operator<<(std::ostream& os, const std::vector& vector) { os << "("; if (vector.empty()) { os << ")"; return os; } auto v_it = vector.begin(); os << *v_it++; for (; v_it != vector.end(); ++v_it) os << ", " << *v_it; os << ")"; return os; } /* A class to make the vector horizontal instead of vertical */ struct Straighten { Straighten(const Eigen::VectorXd& vector) : vector_(vector) {} const Eigen::VectorXd& vector_; }; std::ostream& operator<<(std::ostream& os, const Straighten& str) { std::size_t size = str.vector_.size(); os << "(" << str.vector_(0); if (size == 0) { os << ")"; return os; } for (std::size_t i = 1; i < size; ++i) os << ", " << str.vector_(i); os << ")"; return os; } std::string id_from_simplex(const std::string& simplex) { std::regex r("\\s+"), r2("\\(|\\)|\\{|\\}"), r3(","), r4("\\["), r5("\\]"); std::string output = std::regex_replace(simplex, r, ""); output = std::regex_replace(output, r2, ":"); output = std::regex_replace(output, r3, "."); output = std::regex_replace(output, r4, "_"); output = std::regex_replace(output, r5, ""); return output; } template std::string to_string(const T& t) { std::ostringstream oss; oss << t; return oss.str(); } struct MT_inserted_info { std::string qr_face_, init_face_, qr_intersection_; bool qr_success_, is_boundary_; template MT_inserted_info(const Query_result& qr, const Simplex_handle& face, bool is_boundary) : qr_face_(to_string(face)), init_face_(to_string(face)), qr_intersection_(to_string(qr.intersection)), qr_success_(qr.success), is_boundary_(is_boundary) {} }; std::list mt_seed_inserted_list, mt_inserted_list; struct CC_summary_info { std::string face_, cell_; template CC_summary_info(const SC_pair& sc_pair) : face_(to_string(sc_pair.first)), cell_(to_string(sc_pair.second)) {} }; using CC_summary_list = std::list; std::vector cc_interior_summary_lists, cc_boundary_summary_lists; struct CC_detail_info { enum class Result_type { self, face, coface, inserted, join_single, join_is_face }; std::string simplex_, trigger_, init_simplex_; Result_type status_; bool join_trigger_ = false; std::list faces_, post_faces_, cofaces_; template CC_detail_info(const Simplex_handle& simplex) : simplex_(to_string(simplex)) {} }; using CC_detail_list = std::list; std::vector cc_interior_detail_lists, cc_boundary_detail_lists; std::vector cc_interior_insert_detail_lists, cc_boundary_insert_detail_lists; struct CC_prejoin_info { enum class Result_type { join_single, join_is_face, join_different, join_same }; std::string simplex_, join_; std::vector faces_; std::size_t dimension_; Result_type status_; template CC_prejoin_info(const Simplex_handle& simplex) : simplex_(to_string(simplex)), dimension_(simplex.dimension()) {} }; using CC_prejoin_list = std::list; std::vector cc_interior_prejoin_lists, cc_boundary_prejoin_lists; struct CC_join_info { enum class Result_type { self, face, coface, inserted, join_single, join_is_face }; std::string simplex_, join_, trigger_; Result_type status_; std::list boundary_faces_; std::list faces_, post_faces_, cofaces_; template CC_join_info(const Simplex_handle& simplex) : simplex_(to_string(simplex)) {} }; bool join_switch = false; std::vector cc_interior_join_detail_lists, cc_boundary_join_detail_lists; std::map cell_vlist_map; std::map simplex_vlist_map; std::ostringstream mt_ostream, vis_ostream; std::vector cc_summary_ostream, cc_traces_ostream; std::string simplex_format(const std::string& simplex, bool is_boundary) { std::string b_simplex = (is_boundary ? "B" : "I") + simplex; std::string tooltiptext; auto it = simplex_vlist_map.find(b_simplex); if (it == simplex_vlist_map.end()) tooltiptext = "deleted"; else tooltiptext = simplex_vlist_map.at(b_simplex); return (std::string) "" + b_simplex + "" + tooltiptext + ""; } std::string simplex_format(const std::string& b_simplex) { bool is_boundary = b_simplex[0] == 'B'; std::string tooltiptext; auto it = simplex_vlist_map.find(b_simplex); if (it == simplex_vlist_map.end()) tooltiptext = "deleted"; else tooltiptext = simplex_vlist_map.at(b_simplex); return (std::string) "" + b_simplex + "" + tooltiptext + ""; } void write_head(std::ofstream& ofs) { ofs << " \n" << " Cell complex debug trace\n" << " \n" << " \n"; } void write_nav(std::ofstream& ofs) { ofs << "
\n" << " \n" << "
\n"; } void write_mt(std::ofstream& ofs) { ofs << "
\n"; ofs << "

Manifold debug trace

\n"; ofs << "

Simplices inserted during the seed phase

\n"; ofs << "
    \n"; for (const MT_inserted_info& mt_info : mt_seed_inserted_list) { if (mt_info.qr_success_) { ofs << "
  • Inserted " << simplex_format(mt_info.qr_face_, mt_info.is_boundary_); if (mt_info.qr_face_ != mt_info.init_face_) ofs << " (initially " << simplex_format(mt_info.init_face_, mt_info.is_boundary_) << ")"; ofs << " intersection point is " << mt_info.qr_intersection_ << "
  • \n"; } else ofs << "
  • Failed to insert " << mt_info.init_face_ << "
  • \n"; } ofs << "
\n"; ofs << "

Simplices inserted during the while loop phase

\n"; ofs << "
    \n"; for (const MT_inserted_info& mt_info : mt_inserted_list) { if (mt_info.qr_success_) { ofs << "
  • Inserted " << simplex_format(mt_info.qr_face_, mt_info.is_boundary_); if (mt_info.qr_face_ != mt_info.init_face_) ofs << " (initially " << simplex_format(mt_info.init_face_, mt_info.is_boundary_) << ")"; ofs << " intersection point is " << mt_info.qr_intersection_ << "
  • \n"; } else ofs << "
  • Failed to insert " << mt_info.init_face_ << ")
  • \n"; } ofs << "
\n"; ofs << "
\n"; } void write_cc(std::ofstream& ofs) { ofs << "
\n" << "

Cell complex debug trace

\n" << "

Go to:

\n" << "
    \n"; for (std::size_t i = 0; i < cc_interior_summary_lists.size(); ++i) { ofs << "
  • Dimension " << i << "
  • \n"; } ofs << "
\n"; for (std::size_t i = 0; i < cc_interior_summary_lists.size(); ++i) { ofs << "

Dimension " << i << "

\n"; ofs << "

Summary for interior simplices

\n"; if (i < cc_boundary_summary_lists.size()) ofs << "

Go to boundary

\n"; ofs << "
    \n"; for (const CC_summary_info& cc_info : cc_interior_summary_lists[i]) ofs << "
  • " << simplex_format(cc_info.face_, false) << " cell =" << cc_info.cell_ << "
  • \n"; ofs << "
\n"; ofs << "

Prejoin state of the interior cells of dimension " << i << "

\n"; auto prejoin_it = cc_interior_prejoin_lists[i].begin(); while (prejoin_it != cc_interior_prejoin_lists[i].end()) { std::size_t j = prejoin_it->dimension_; ofs << "
" << j << "-dimensional ambient simplices
\n"; ofs << "
    \n"; for (; prejoin_it->dimension_ == j; ++prejoin_it) { ofs << "
  • " << simplex_format(prejoin_it->simplex_, false) << " join = " << simplex_format(prejoin_it->join_, false) << " boundary:\n" << "
      \n"; for (const auto& face : prejoin_it->faces_) ofs << "
    • " << simplex_format(face) << "
    • "; ofs << "
    \n"; switch (prejoin_it->status_) { case (CC_prejoin_info::Result_type::join_single): ofs << "

    Deleted " << simplex_format(prejoin_it->simplex_, false) << " as it has a single face.

    "; break; case (CC_prejoin_info::Result_type::join_is_face): ofs << "

    Deleted " << simplex_format(prejoin_it->simplex_, false) << " as its join " << simplex_format(prejoin_it->join_, false) << " is one of the faces.

    "; break; case (CC_prejoin_info::Result_type::join_different): ofs << "

    Deleted " << simplex_format(prejoin_it->simplex_, false) << " and replaced by its join " << simplex_format(prejoin_it->join_, false) << ".

    "; break; case (CC_prejoin_info::Result_type::join_same): ofs << "

    Kept " << simplex_format(prejoin_it->simplex_, false) << ".

    "; } ofs << "
  • "; } ofs << "
\n"; } ofs << "

Details for interior simplices

\n"; ofs << "
    \n"; for (const CC_detail_info& cc_info : cc_interior_detail_lists[i]) { if (cc_info.status_ == CC_detail_info::Result_type::join_single) { ofs << "
  • Simplex " << simplex_format(cc_info.simplex_, false) << " has only one face (" << simplex_format(cc_info.trigger_, false) << ") and is deleted."; continue; } if (cc_info.status_ == CC_detail_info::Result_type::join_single) { ofs << "
  • The join of the simplex " << simplex_format(cc_info.simplex_, false) << " is one of its faces (" << simplex_format(cc_info.trigger_, false) << "), hence it is is deleted."; continue; } ofs << "
  • Insert_cell called for " << simplex_format(cc_info.simplex_, false) << "\n"; ofs << "
      \n"; // for (const std::string& cof: cc_info.faces_) // ofs << "
    • Checking if " << simplex_format(cc_info.simplex_, false) // << " is a face of " << simplex_format(cof, false) << "\n"; ofs << "
    \n"; ofs << "
      \n"; if (cc_info.status_ == CC_detail_info::Result_type::self) { ofs << "

      The simplex " << simplex_format(cc_info.simplex_, false) << " already exists in the cell complex!

      \n"; } if (cc_info.status_ == CC_detail_info::Result_type::face) { ofs << "

      The simplex " << simplex_format(cc_info.simplex_, false) << " is a face of the simplex " << simplex_format(cc_info.trigger_, false) << "!
      \n"; ofs << "

        \n"; for (const std::string post_face : cc_info.post_faces_) ofs << "
      • " << "Post deleting " << simplex_format(post_face, false) << "
      • \n"; ofs << "
      \n"; ofs << "

      \n"; ofs << "

      " << "Deleting " << simplex_format(cc_info.trigger_, false) << "

      \n"; } // for (const std::string& fac: cc_info.cofaces_) // ofs << "
    • Checking if " << simplex_format(cc_info.simplex_, false) // << " is a coface of " << simplex_format(fac, false) << "\n"; if (cc_info.status_ == CC_detail_info::Result_type::coface) { ofs << "

      The simplex " << simplex_format(cc_info.simplex_, false) << " is a coface of the simplex " << simplex_format(cc_info.trigger_, false) << "!

      \n"; } if (cc_info.status_ == CC_detail_info::Result_type::inserted) { ofs << "

      Successfully inserted " << simplex_format(cc_info.simplex_, false) << "!

      \n"; } ofs << "

    \n"; ofs << "
  • \n"; } ofs << "
\n"; if (i < cc_boundary_summary_lists.size()) { ofs << "

Summary for boundary simplices

\n"; ofs << "

Go to interior

\n"; ofs << "
    \n"; for (const CC_summary_info& cc_info : cc_boundary_summary_lists[i]) ofs << "
  • " << simplex_format(cc_info.face_, true) << " cell =" << cc_info.cell_ << "
  • \n"; ofs << "
\n"; ofs << "

Prejoin state of the boundary cells of dimension " << i << "

\n"; auto prejoin_it = cc_boundary_prejoin_lists[i].begin(); while (prejoin_it != cc_boundary_prejoin_lists[i].end()) { std::size_t j = prejoin_it->dimension_; ofs << "
" << j << "-dimensional ambient simplices
\n"; ofs << "
    \n"; for (; prejoin_it->dimension_ == j; ++prejoin_it) { ofs << "
  • " << simplex_format(prejoin_it->simplex_, true) << " join = " << simplex_format(prejoin_it->join_, true) << " boundary:\n" << "
      \n"; for (const auto& face : prejoin_it->faces_) ofs << "
    • " << simplex_format(face) << "
    • "; ofs << "
    \n"; switch (prejoin_it->status_) { case (CC_prejoin_info::Result_type::join_single): ofs << "

    Deleted " << simplex_format(prejoin_it->simplex_, true) << " as it has a single face.

    "; break; case (CC_prejoin_info::Result_type::join_is_face): ofs << "

    Deleted " << simplex_format(prejoin_it->simplex_, true) << " as its join " << simplex_format(prejoin_it->join_, true) << " is one of the faces.

    "; break; case (CC_prejoin_info::Result_type::join_different): ofs << "

    Deleted " << simplex_format(prejoin_it->simplex_, true) << " and replaced by its join " << simplex_format(prejoin_it->join_, true) << ".

    "; break; case (CC_prejoin_info::Result_type::join_same): ofs << "

    Kept " << simplex_format(prejoin_it->simplex_, true) << ".

    "; } ofs << "
  • "; } ofs << "
\n"; } } if (i < cc_boundary_detail_lists.size()) { ofs << "

Details for boundary simplices

\n" << "
    \n"; for (const CC_detail_info& cc_info : cc_boundary_detail_lists[i]) { if (cc_info.status_ == CC_detail_info::Result_type::join_single) { ofs << "
  • Simplex " << simplex_format(cc_info.simplex_, true) << " has only one face (" << simplex_format(cc_info.trigger_, true) << ") and is deleted."; continue; } if (cc_info.status_ == CC_detail_info::Result_type::join_single) { ofs << "
  • The join of the simplex " << simplex_format(cc_info.simplex_, true) << " is one of its faces (" << simplex_format(cc_info.trigger_, true) << "), hence it is is deleted."; continue; } ofs << "
  • Insert_simplex called on " << simplex_format(cc_info.simplex_, true); ofs << "
      \n"; // for (const std::string& cof: cc_info.faces_) // ofs << "
    • Checking if " << simplex_format(cc_info.simplex_, true) // << " is a face of " << simplex_format(cof, true) << "\n"; ofs << "
    \n"; ofs << "
      \n"; if (cc_info.status_ == CC_detail_info::Result_type::self) { ofs << "

      The simplex " << simplex_format(cc_info.simplex_, true) << " already exists in the cell complex!

      \n"; } if (cc_info.status_ == CC_detail_info::Result_type::face) { ofs << "

      The simplex " << simplex_format(cc_info.simplex_, true) << " is a face of the simplex " << simplex_format(cc_info.trigger_, true) << "!
      \n"; ofs << "

        \n"; for (const std::string post_face : cc_info.post_faces_) ofs << "
      • Post deleting " << simplex_format(post_face, true) << "
      • \n"; ofs << "
      \n"; ofs << "

      \n"; ofs << "

      Deleting " << simplex_format(cc_info.trigger_, true) << "

      \n"; } // for (const std::string& fac: cc_info.cofaces_) // ofs << "
    • Checking if " << simplex_format(cc_info.simplex_, true) // << " is a coface of " << simplex_format(fac, true) << "\n"; ofs << "
    \n"; ofs << "
  • \n"; if (cc_info.status_ == CC_detail_info::Result_type::coface) { ofs << "

    The simplex " << simplex_format(cc_info.simplex_, true) << " is a coface of the simplex " << simplex_format(cc_info.trigger_, true) << "!

    \n"; } if (cc_info.status_ == CC_detail_info::Result_type::inserted) { ofs << "

    Successfully inserted " << simplex_format(cc_info.simplex_, true) << "!

    \n"; } } ofs << "

\n"; } } ofs << "
\n"; } void write_visu(std::ofstream& ofs) { ofs << "
\n" << "

Visualization details debug trace

\n"; // std::vector > vs_maps(cc_interior_summary_lists.size()); std::map vs_map; for (const auto& sv_pair : simplex_vlist_map) vs_map.emplace(sv_pair.second, sv_pair.first); ofs << "
    \n"; for (const auto& vs_pair : vs_map) { std::string w_simplex = vs_pair.second.substr(1); bool is_boundary = vs_pair.second[0] == 'B'; ofs << "
  • " << vs_pair.first << ": " << simplex_format(w_simplex, is_boundary) << "
  • \n"; } ofs << "
\n"; ofs << "
\n"; } void write_to_html(std::string file_name) { std::ofstream ofs(file_name + ".html", std::ofstream::out); ofs << "\n" << "\n"; write_head(ofs); ofs << " \n"; write_nav(ofs); ofs << "

Debug traces for " << file_name << "

\n"; write_mt(ofs); write_cc(ofs); write_visu(ofs); ofs << " \n"; ofs << "\n"; ofs.close(); } } // namespace coxeter_triangulation } // namespace Gudhi #endif // DEBUG_TRACES #endif // IO_OUTPUT_DEBUG_TRACES_TO_HTML_H_