<commit_before>#include "acmacs-base/pybind11.hh"
#include "locationdb/locdb.hh"

#include "chart.hh"
#include "ace.hh"
#include "lispmds.hh"

// ----------------------------------------------------------------------

// static inline PointStyle& point_style_shape(PointStyle& aStyle, std::string aShape)
// {
//     if (aShape == "circle")
//         return aStyle.shape(PointStyle::Shape::Circle);
//     if (aShape == "box")
//         return aStyle.shape(PointStyle::Shape::Box);
//     if (aShape == "triangle")
//         return aStyle.shape(PointStyle::Shape::Triangle);
//     throw std::runtime_error("Unrecognized point style shape: " + aShape);
// }

// ----------------------------------------------------------------------

// static inline PointStyle* point_style_kw(PointStyle& aStyle, py::args args, py::kwargs kwargs)
// {
//     PointStyle* obj = new (&aStyle) PointStyle(PointStyle::Empty);
//     std::cerr << "point_style_kw" << std::endl;
//     return obj;
// }

// static inline PointStyle* point_style_modify_kw(PointStyle* aStyle, py::args args, py::kwargs kwargs)
// {
//     std::cerr << "point_style_modify_kw" << std::endl;
//     return aStyle;
// }

// static inline PointStyle* new_point_style_kw(py::args args, py::kwargs kwargs)
// {
//     PointStyle* style = new PointStyle(PointStyle::Empty);
//     std::cerr << "new_point_style_kw" << std::endl;
//     return style;
// }

// ----------------------------------------------------------------------

PYBIND11_MODULE(acmacs_chart_backend, m)
{
    m.doc() = "Acmacs chart access plugin";

      // ----------------------------------------------------------------------
      // Antigen, Serum
      // ----------------------------------------------------------------------

    py::class_<Antigen>(m, "Antigen")
            .def("full_name", &Antigen::full_name)
            .def("abbreviated_name", &Antigen::abbreviated_name, py::arg("locdb"), py::doc("includes passage, reassortant, annotations"))
            .def("name_abbreviated", &Antigen::name_abbreviated, py::arg("locdb"), py::doc("just name without passage, reassortant, annotations"))
            .def("location_abbreviated", &Antigen::location_abbreviated, py::arg("locdb"))
            .def("name", py::overload_cast<>(&Antigen::name, py::const_))
            .def("lineage", py::overload_cast<>(&Antigen::lineage, py::const_))
            .def("passage", py::overload_cast<>(&Antigen::passage, py::const_))
            .def("passage_type", &Antigen::passage_type)
            .def("reassortant", py::overload_cast<>(&Antigen::reassortant, py::const_))
            .def("semantic", py::overload_cast<>(&Antigen::semantic, py::const_))
            .def("annotations", [](const Antigen &as) { py::list list; for (const auto& anno: as.annotations()) { list.append(py::str(anno)); } return list; }, py::doc("returns a copy of the annotation list, modifications to the returned list are not applied"))
            .def("abbreviated_name_with_passage_type", &Antigen::abbreviated_name_with_passage_type, py::arg("locdb"))
            .def("date", py::overload_cast<>(&Antigen::date, py::const_))
            .def("lab_id", [](const Antigen &a) { py::list list; for (const auto& li: a.lab_id()) { list.append(py::str(li)); } return list; }, py::doc("returns a copy of the lab_id list, modifications to the returned list are not applied"))
            // .def("find_in_hidb", &Antigen::find_in_hidb, py::arg("hidb"), py::return_value_policy::reference)
            ;

    py::class_<Serum>(m, "Serum")
            .def("full_name", &Serum::full_name)
            .def("abbreviated_name", &Serum::abbreviated_name, py::arg("locdb"), py::doc("includes passage, reassortant, annotations"))
            .def("name_abbreviated", &Serum::name_abbreviated, py::arg("locdb"), py::doc("just name without passage, reassortant, annotations"))
            .def("location_abbreviated", &Serum::location_abbreviated, py::arg("locdb"))
            .def("name", py::overload_cast<>(&Serum::name, py::const_))
            .def("lineage", py::overload_cast<>(&Serum::lineage, py::const_))
            .def("passage", py::overload_cast<>(&Serum::passage, py::const_))
            .def("passage_type", &Serum::passage_type)
            .def("reassortant", py::overload_cast<>(&Serum::reassortant, py::const_))
            .def("semantic", py::overload_cast<>(&Serum::semantic, py::const_))
            .def("annotations", [](const Serum &as) { py::list list; for (const auto& anno: as.annotations()) { list.append(py::str(anno)); } return list; }, py::doc("returns a copy of the annotation list, modifications to the returned list are not applied"))
            .def("serum_id", py::overload_cast<>(&Serum::serum_id, py::const_))
            .def("serum_species", py::overload_cast<>(&Serum::serum_species, py::const_))
            .def("homologous", py::overload_cast<>(&Serum::homologous, py::const_))
            // .def("find_in_hidb", &Serum::find_in_hidb, py::arg("hidb"), py::return_value_policy::reference)
            ;

    py::class_<Antigens>(m, "Antigens")
            .def("continents", [](const Antigens& antigens, const LocDb& aLocDb, bool aExcludeReference) { Antigens::ContinentData data; antigens.continents(data, aLocDb, aExcludeReference); return data; }, py::arg("locdb"), py::arg("exclude_reference") = true)
            .def("countries", [](const Antigens& antigens, const LocDb& aLocDb) { Antigens::CountryData data; antigens.countries(data, aLocDb); return data; })
            .def("country", [](const Antigens& antigens, std::string aCountry, const LocDb& aLocDb) { std::vector<size_t> indices; antigens.country(aCountry, indices, aLocDb); return indices; })
            .def("find_by_name_matching", [](const Antigens& antigens, std::string aName, string_match::score_t aScoreThreshold, bool aVerbose) { std::vector<size_t> indices; antigens.find_by_name_matching(aName, indices, aScoreThreshold, aVerbose); return indices; }, py::arg("name"), py::arg("score_threshold") = 0, py::arg("verbose") = false)
            .def("find_by_lab_id", [](const Antigens& antigens, std::string aLabId) { std::vector<size_t> indices; antigens.find_by_lab_id(aLabId, indices); return indices; }, py::arg("lab_id"))
            .def("find_by_lab_ids", [](const Antigens& antigens, std::vector<std::string> aLabIds) { std::vector<size_t> indices; for (const auto& lab_id: aLabIds) { antigens.find_by_lab_id(lab_id, indices); } return indices; }, py::arg("lab_ids"))
            .def("reference_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.reference_indices(indices); return indices; })
            .def("test_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.test_indices(indices); return indices; })
            .def("date_range_indices", [](const Antigens& antigens, std::string first_date, std::string after_last_date) { std::vector<size_t> indices; antigens.date_range_indices(first_date, after_last_date, indices); return indices; }, py::arg("first") = std::string(), py::arg("after_last") = std::string())
            .def("egg_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.egg_indices(indices); return indices; })
            .def("cell_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.cell_indices(indices); return indices; })
            .def("reassortant_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.reassortant_indices(indices); return indices; })
            .def("__getitem__", [](const Antigens& antigens, int aIndex) -> const Antigen& { if (aIndex >= 0) return antigens[static_cast<size_t>(aIndex)]; else return antigens[static_cast<size_t>(static_cast<int>(antigens.size()) + aIndex)]; })
            ;

    py::class_<Sera>(m, "Sera")
            .def("find_by_name_matching", [](const Sera& sera, std::string aName, string_match::score_t aScoreThreshold, bool aVerbose) { std::vector<size_t> indices; sera.find_by_name_matching(aName, indices, aScoreThreshold, aVerbose); return indices; }, py::arg("name"), py::arg("score_threshold") = 0, py::arg("verbose") = false)
            .def("__getitem__", [](const Sera& sera, int aIndex) -> const Serum& { if (aIndex >= 0) return sera[static_cast<size_t>(aIndex)]; else return sera[static_cast<size_t>(static_cast<int>(sera.size()) + aIndex)]; })
            ;

      // ----------------------------------------------------------------------
      // Chart
      // ----------------------------------------------------------------------

    py::class_<ChartInfo>(m, "ChartInfo")
            .def("virus", py::overload_cast<>(&ChartInfo::virus, py::const_))
            .def("virus_type", py::overload_cast<>(&ChartInfo::virus_type, py::const_))
            .def("assay", py::overload_cast<>(&ChartInfo::assay, py::const_))
            .def("date", py::overload_cast<>(&ChartInfo::date, py::const_))
            .def("lab", py::overload_cast<>(&ChartInfo::lab, py::const_))
            .def("rbc", py::overload_cast<>(&ChartInfo::rbc, py::const_))
            .def("name", py::overload_cast<>(&ChartInfo::name, py::const_))
            .def("subset", py::overload_cast<>(&ChartInfo::subset, py::const_))
            .def("type", &ChartInfo::type_as_string)
            .def("make_name", &ChartInfo::make_name)
            ;

    py::class_<Transformation>(m, "Transformation")
            ;

    py::class_<Titer>(m, "Titer")
            .def("__str__", [](const Titer& aTiter) -> std::string { return aTiter; })
            ;

    py::class_<ChartTiters>(m, "ChartTiters")
            .def("get", &ChartTiters::get, py::arg("ag_no"), py::arg("sr_no"))
            .def("max_for_serum", &ChartTiters::max_for_serum, py::arg("sr_no"))
            ;

    py::class_<Chart>(m, "Chart")
            .def("number_of_antigens", &Chart::number_of_antigens)
            .def("number_of_sera", &Chart::number_of_sera)
            .def("number_of_projections", &Chart::number_of_projections)
            .def("antigens", py::overload_cast<>(&Chart::antigens), py::return_value_policy::reference)
            .def("sera", py::overload_cast<>(&Chart::sera), py::return_value_policy::reference)
            .def("antigen", py::overload_cast<size_t>(&Chart::antigen, py::const_), py::arg("no"), py::return_value_policy::reference)
            .def("serum", py::overload_cast<size_t>(&Chart::serum, py::const_), py::arg("no"), py::return_value_policy::reference)
            .def("lineage", &Chart::lineage)
            .def("make_name", &Chart::make_name, py::arg("projection_no") = -1)
            // .def("vaccines", &Chart::vaccines, py::arg("name"), py::arg("hidb"))
            // .def("table_id", &Chart::table_id)
            .def("find_homologous_antigen_for_sera", &Chart::find_homologous_antigen_for_sera)
            .def("chart_info", py::overload_cast<>(&Chart::chart_info, py::const_), py::return_value_policy::reference)
            .def("titers", py::overload_cast<>(&Chart::titers, py::const_), py::return_value_policy::reference)
            .def("serum_circle_radius", &Chart::serum_circle_radius, py::arg("antigen_no"), py::arg("serum_no"), py::arg("projection_no") = 0, py::arg("verbose") = false)
            .def("serum_coverage", [](const Chart& aChart, size_t aAntigenNo, size_t aSerumNo) -> std::vector<std::vector<size_t>> { std::vector<size_t> within, outside; aChart.serum_coverage(aAntigenNo, aSerumNo, within, outside); return {within, outside}; } , py::arg("antigen_no"), py::arg("serum_no"))
            .def("antigens_not_found_in", [](const Chart& aChart, const Chart& aNother) -> std::vector<size_t> { auto gen = aChart.antigens_not_found_in(aNother); return {gen.begin(), gen.end()}; }, py::arg("another_chart"))
        ;

    m.def("import_chart", &import_chart, py::arg("data"), py::doc("Imports chart from a buffer or file in the ace format."));
    m.def("import_chart", [](py::bytes data) { return import_chart(data); }, py::arg("data"), py::doc("Imports chart from a buffer or file in the ace format."));
    m.def("export_chart", &export_chart, py::arg("filename"), py::arg("chart"), py::doc("Exports chart into a file in the ace format."));
    m.def("export_chart_lispmds", py::overload_cast<std::string, const Chart&>(&export_chart_lispmds), py::arg("filename"), py::arg("chart"), py::doc("Exports chart into a file in the lispmds save format."));

      // ----------------------------------------------------------------------
      //
      // ----------------------------------------------------------------------

    m.def("virus_name_match_threshold", &virus_name::match_threshold, py::arg("name"), py::doc("Extracts virus name without passage, reassortant, extra, etc. and calculates match threshold (to use with antigens.find_by_name_matching), match threshold is a square of virus name length."));
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>Projection and Layout access for python<commit_after>#include "acmacs-base/pybind11.hh"
#include "locationdb/locdb.hh"

#include "chart.hh"
#include "ace.hh"
#include "lispmds.hh"

// ----------------------------------------------------------------------

// static inline PointStyle& point_style_shape(PointStyle& aStyle, std::string aShape)
// {
//     if (aShape == "circle")
//         return aStyle.shape(PointStyle::Shape::Circle);
//     if (aShape == "box")
//         return aStyle.shape(PointStyle::Shape::Box);
//     if (aShape == "triangle")
//         return aStyle.shape(PointStyle::Shape::Triangle);
//     throw std::runtime_error("Unrecognized point style shape: " + aShape);
// }

// ----------------------------------------------------------------------

// static inline PointStyle* point_style_kw(PointStyle& aStyle, py::args args, py::kwargs kwargs)
// {
//     PointStyle* obj = new (&aStyle) PointStyle(PointStyle::Empty);
//     std::cerr << "point_style_kw" << std::endl;
//     return obj;
// }

// static inline PointStyle* point_style_modify_kw(PointStyle* aStyle, py::args args, py::kwargs kwargs)
// {
//     std::cerr << "point_style_modify_kw" << std::endl;
//     return aStyle;
// }

// static inline PointStyle* new_point_style_kw(py::args args, py::kwargs kwargs)
// {
//     PointStyle* style = new PointStyle(PointStyle::Empty);
//     std::cerr << "new_point_style_kw" << std::endl;
//     return style;
// }

// ----------------------------------------------------------------------

PYBIND11_MODULE(acmacs_chart_backend, m)
{
    m.doc() = "Acmacs chart access plugin";

      // ----------------------------------------------------------------------
      // Antigen, Serum
      // ----------------------------------------------------------------------

    py::class_<Antigen>(m, "Antigen")
            .def("full_name", &Antigen::full_name)
            .def("abbreviated_name", &Antigen::abbreviated_name, py::arg("locdb"), py::doc("includes passage, reassortant, annotations"))
            .def("name_abbreviated", &Antigen::name_abbreviated, py::arg("locdb"), py::doc("just name without passage, reassortant, annotations"))
            .def("location_abbreviated", &Antigen::location_abbreviated, py::arg("locdb"))
            .def("name", py::overload_cast<>(&Antigen::name, py::const_))
            .def("lineage", py::overload_cast<>(&Antigen::lineage, py::const_))
            .def("passage", py::overload_cast<>(&Antigen::passage, py::const_))
            .def("passage_type", &Antigen::passage_type)
            .def("reassortant", py::overload_cast<>(&Antigen::reassortant, py::const_))
            .def("semantic", py::overload_cast<>(&Antigen::semantic, py::const_))
            .def("annotations", [](const Antigen &as) { py::list list; for (const auto& anno: as.annotations()) { list.append(py::str(anno)); } return list; }, py::doc("returns a copy of the annotation list, modifications to the returned list are not applied"))
            .def("abbreviated_name_with_passage_type", &Antigen::abbreviated_name_with_passage_type, py::arg("locdb"))
            .def("date", py::overload_cast<>(&Antigen::date, py::const_))
            .def("lab_id", [](const Antigen &a) { py::list list; for (const auto& li: a.lab_id()) { list.append(py::str(li)); } return list; }, py::doc("returns a copy of the lab_id list, modifications to the returned list are not applied"))
            // .def("find_in_hidb", &Antigen::find_in_hidb, py::arg("hidb"), py::return_value_policy::reference)
            ;

    py::class_<Serum>(m, "Serum")
            .def("full_name", &Serum::full_name)
            .def("abbreviated_name", &Serum::abbreviated_name, py::arg("locdb"), py::doc("includes passage, reassortant, annotations"))
            .def("name_abbreviated", &Serum::name_abbreviated, py::arg("locdb"), py::doc("just name without passage, reassortant, annotations"))
            .def("location_abbreviated", &Serum::location_abbreviated, py::arg("locdb"))
            .def("name", py::overload_cast<>(&Serum::name, py::const_))
            .def("lineage", py::overload_cast<>(&Serum::lineage, py::const_))
            .def("passage", py::overload_cast<>(&Serum::passage, py::const_))
            .def("passage_type", &Serum::passage_type)
            .def("reassortant", py::overload_cast<>(&Serum::reassortant, py::const_))
            .def("semantic", py::overload_cast<>(&Serum::semantic, py::const_))
            .def("annotations", [](const Serum &as) { py::list list; for (const auto& anno: as.annotations()) { list.append(py::str(anno)); } return list; }, py::doc("returns a copy of the annotation list, modifications to the returned list are not applied"))
            .def("serum_id", py::overload_cast<>(&Serum::serum_id, py::const_))
            .def("serum_species", py::overload_cast<>(&Serum::serum_species, py::const_))
            .def("homologous", py::overload_cast<>(&Serum::homologous, py::const_))
            // .def("find_in_hidb", &Serum::find_in_hidb, py::arg("hidb"), py::return_value_policy::reference)
            ;

    py::class_<Antigens>(m, "Antigens")
            .def("continents", [](const Antigens& antigens, const LocDb& aLocDb, bool aExcludeReference) { Antigens::ContinentData data; antigens.continents(data, aLocDb, aExcludeReference); return data; }, py::arg("locdb"), py::arg("exclude_reference") = true)
            .def("countries", [](const Antigens& antigens, const LocDb& aLocDb) { Antigens::CountryData data; antigens.countries(data, aLocDb); return data; })
            .def("country", [](const Antigens& antigens, std::string aCountry, const LocDb& aLocDb) { std::vector<size_t> indices; antigens.country(aCountry, indices, aLocDb); return indices; })
            .def("find_by_name_matching", [](const Antigens& antigens, std::string aName, string_match::score_t aScoreThreshold, bool aVerbose) { std::vector<size_t> indices; antigens.find_by_name_matching(aName, indices, aScoreThreshold, aVerbose); return indices; }, py::arg("name"), py::arg("score_threshold") = 0, py::arg("verbose") = false)
            .def("find_by_lab_id", [](const Antigens& antigens, std::string aLabId) { std::vector<size_t> indices; antigens.find_by_lab_id(aLabId, indices); return indices; }, py::arg("lab_id"))
            .def("find_by_lab_ids", [](const Antigens& antigens, std::vector<std::string> aLabIds) { std::vector<size_t> indices; for (const auto& lab_id: aLabIds) { antigens.find_by_lab_id(lab_id, indices); } return indices; }, py::arg("lab_ids"))
            .def("reference_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.reference_indices(indices); return indices; })
            .def("test_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.test_indices(indices); return indices; })
            .def("date_range_indices", [](const Antigens& antigens, std::string first_date, std::string after_last_date) { std::vector<size_t> indices; antigens.date_range_indices(first_date, after_last_date, indices); return indices; }, py::arg("first") = std::string(), py::arg("after_last") = std::string())
            .def("egg_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.egg_indices(indices); return indices; })
            .def("cell_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.cell_indices(indices); return indices; })
            .def("reassortant_indices", [](const Antigens& antigens) { std::vector<size_t> indices; antigens.reassortant_indices(indices); return indices; })
            .def("__getitem__", [](const Antigens& antigens, int aIndex) -> const Antigen& { if (aIndex >= 0) return antigens[static_cast<size_t>(aIndex)]; else return antigens[static_cast<size_t>(static_cast<int>(antigens.size()) + aIndex)]; })
            ;

    py::class_<Sera>(m, "Sera")
            .def("find_by_name_matching", [](const Sera& sera, std::string aName, string_match::score_t aScoreThreshold, bool aVerbose) { std::vector<size_t> indices; sera.find_by_name_matching(aName, indices, aScoreThreshold, aVerbose); return indices; }, py::arg("name"), py::arg("score_threshold") = 0, py::arg("verbose") = false)
            .def("__getitem__", [](const Sera& sera, int aIndex) -> const Serum& { if (aIndex >= 0) return sera[static_cast<size_t>(aIndex)]; else return sera[static_cast<size_t>(static_cast<int>(sera.size()) + aIndex)]; })
            ;

      // ----------------------------------------------------------------------
      // Chart
      // ----------------------------------------------------------------------

    py::class_<ChartInfo>(m, "ChartInfo")
            .def("virus", py::overload_cast<>(&ChartInfo::virus, py::const_))
            .def("virus_type", py::overload_cast<>(&ChartInfo::virus_type, py::const_))
            .def("assay", py::overload_cast<>(&ChartInfo::assay, py::const_))
            .def("date", py::overload_cast<>(&ChartInfo::date, py::const_))
            .def("lab", py::overload_cast<>(&ChartInfo::lab, py::const_))
            .def("rbc", py::overload_cast<>(&ChartInfo::rbc, py::const_))
            .def("name", py::overload_cast<>(&ChartInfo::name, py::const_))
            .def("subset", py::overload_cast<>(&ChartInfo::subset, py::const_))
            .def("type", &ChartInfo::type_as_string)
            .def("make_name", &ChartInfo::make_name)
            ;

    py::class_<Transformation>(m, "Transformation")
            ;

    py::class_<LayoutBase>(m, "LayoutBase")
            .def("number_of_points", &LayoutBase::number_of_points)
            .def("number_of_dimensions", &LayoutBase::number_of_dimensions)
            .def("__getitem__", [](const LayoutBase& aLayout, size_t aIndex) -> std::vector<double> { return aLayout[aIndex]; }, py::arg("index"))
            ;

    py::class_<Projection>(m, "Projection")
            .def("stress", py::overload_cast<>(&Projection::stress, py::const_))
            .def("minimum_column_basis", &Projection::minimum_column_basis_for_json)
            .def("layout", py::overload_cast<>(&Projection::layout, py::const_), py::return_value_policy::reference)
            ;

    py::class_<Titer>(m, "Titer")
            .def("__str__", [](const Titer& aTiter) -> std::string { return aTiter; })
            ;

    py::class_<ChartTiters>(m, "ChartTiters")
            .def("get", &ChartTiters::get, py::arg("ag_no"), py::arg("sr_no"))
            .def("max_for_serum", &ChartTiters::max_for_serum, py::arg("sr_no"))
            ;

    py::class_<Chart>(m, "Chart")
            .def("number_of_antigens", &Chart::number_of_antigens)
            .def("number_of_sera", &Chart::number_of_sera)
            .def("number_of_projections", &Chart::number_of_projections)
            .def("antigens", py::overload_cast<>(&Chart::antigens), py::return_value_policy::reference)
            .def("sera", py::overload_cast<>(&Chart::sera), py::return_value_policy::reference)
            .def("antigen", py::overload_cast<size_t>(&Chart::antigen, py::const_), py::arg("no"), py::return_value_policy::reference)
            .def("serum", py::overload_cast<size_t>(&Chart::serum, py::const_), py::arg("no"), py::return_value_policy::reference)
            .def("lineage", &Chart::lineage)
            .def("make_name", &Chart::make_name, py::arg("projection_no") = -1)
            // .def("vaccines", &Chart::vaccines, py::arg("name"), py::arg("hidb"))
            // .def("table_id", &Chart::table_id)
            .def("find_homologous_antigen_for_sera", &Chart::find_homologous_antigen_for_sera)
            .def("chart_info", py::overload_cast<>(&Chart::chart_info, py::const_), py::return_value_policy::reference)
            .def("titers", py::overload_cast<>(&Chart::titers, py::const_), py::return_value_policy::reference)
            .def("serum_circle_radius", &Chart::serum_circle_radius, py::arg("antigen_no"), py::arg("serum_no"), py::arg("projection_no") = 0, py::arg("verbose") = false)
            .def("serum_coverage", [](const Chart& aChart, size_t aAntigenNo, size_t aSerumNo) -> std::vector<std::vector<size_t>> { std::vector<size_t> within, outside; aChart.serum_coverage(aAntigenNo, aSerumNo, within, outside); return {within, outside}; } , py::arg("antigen_no"), py::arg("serum_no"))
            .def("antigens_not_found_in", [](const Chart& aChart, const Chart& aNother) -> std::vector<size_t> { auto gen = aChart.antigens_not_found_in(aNother); return {gen.begin(), gen.end()}; }, py::arg("another_chart"))
            .def("projection", py::overload_cast<size_t>(&Chart::projection, py::const_), py::arg("projection_no") = 0, py::return_value_policy::reference)
        ;

    m.def("import_chart", &import_chart, py::arg("data"), py::doc("Imports chart from a buffer or file in the ace format."));
    m.def("import_chart", [](py::bytes data) { return import_chart(data); }, py::arg("data"), py::doc("Imports chart from a buffer or file in the ace format."));
    m.def("export_chart", &export_chart, py::arg("filename"), py::arg("chart"), py::doc("Exports chart into a file in the ace format."));
    m.def("export_chart_lispmds", py::overload_cast<std::string, const Chart&>(&export_chart_lispmds), py::arg("filename"), py::arg("chart"), py::doc("Exports chart into a file in the lispmds save format."));

      // ----------------------------------------------------------------------
      //
      // ----------------------------------------------------------------------

    m.def("virus_name_match_threshold", &virus_name::match_threshold, py::arg("name"), py::doc("Extracts virus name without passage, reassortant, extra, etc. and calculates match threshold (to use with antigens.find_by_name_matching), match threshold is a square of virus name length."));
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#ifndef CCSR_HPP
#define CCSR_HPP

/**
 * \file   ccsr.hpp
 * \author Denis Demidov <ddemidov@ksu.ru>
 * \brief  Compressed CSR format composition.
 *
 * Lossy compression for CSR format. Stores unique matrix rows, where
 * uniqueness is determined approximately. If the precision loss is not
 * important (e.g. coefficients come from an experiment with incorporated
 * observation error), it may result in significant storage savings for large
 * matrices.
 */

#include <vector>
#include <deque>
#include <type_traits>
#include <memory>
#include <functional>
#include <exception>
#include <cassert>

#include <boost/unordered_set.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>

namespace ccsr {

template <typename T>
struct hash_impl {
    static inline size_t get(T v) {
        return std::hash<T>()(v);
    }
};

template <>
struct hash_impl<double> {
    static inline size_t get(double v) {
        static const uint64_t mask = 0xffffffffff000000;
                                    // eeefffffffffffff;
        // Zero-out least significant bits and hash as uint64_t:
        return std::hash<uint64_t>()(*reinterpret_cast<const uint64_t*>(&v) & mask);
    }
};

template <>
struct hash_impl<float> {
    static inline size_t get(float v) {
        static const uint32_t mask = 0xfffffc00;
                                    // eeffffff;
        // Zero-out least significant bits and hash as uint64_t:
        return std::hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(&v) & mask);
    }
};

template <class T>
inline size_t hash(const T &v) {
    return hash_impl<T>::get(v);
}

template <
    typename val_t = double,
    typename row_t = size_t,
    typename col_t = ptrdiff_t,
    typename idx_t = row_t
    >
class matrix {
    static_assert(std::is_signed<col_t>::value, "Column type should be signed!");

    private:
        size_t rows, cols;

        std::vector< idx_t > idx;
        std::vector< row_t > row;
        std::vector< col_t > col;
        std::vector< val_t > val;

        struct shift {
            typedef col_t result_type;

            col_t s;

            shift(col_t s) : s(s) {}

            col_t operator()(col_t v) const {
                return v + s;
            }
        };

        struct builder_t {
            std::deque< idx_t > idx;
            std::deque< row_t > row;
            std::deque< col_t > col;
            std::deque< val_t > val;

            struct row_hasher {
                val_t eps;

                row_hasher(val_t eps) : eps(eps) {}

                template <class Range>
                size_t operator()(const Range &r) const {
                    using boost::get;

                    auto begin = get<0>(r);
                    auto end   = get<1>(r);

                    size_t h = hash(end - begin);

                    for(auto i = begin; i != end; ++i)
                        h ^= hash(get<0>(*i)) ^ hash(get<1>(*i));

                    return h;
                }

                template <class Range1, class Range2>
                bool operator()(const Range1 &r1, const Range2 &r2) const {
                    using boost::get;

                    auto i1 = get<0>(r1);
                    auto e1 = get<1>(r1);
                    auto i2 = get<0>(r2);
                    auto e2 = get<1>(r2);

                    if (e1 - i1 != e2 - i2) return false;

                    for(; i1 != e1; ++i1, ++i2) {
                        if (get<0>(*i1) != get<0>(*i2))
                            return false;

                        if (fabs(get<1>(*i1) - get<1>(*i2)) > eps)
                            return false;
                    }

                    return true;
                }
            } hasher;

            typedef boost::zip_iterator<
                        boost::tuple<
                            typename std::deque< col_t >::const_iterator,
                            typename std::deque< val_t >::const_iterator
                        >
                    > row_iterator;

            typedef boost::tuple< row_iterator, row_iterator, size_t > row_range;

            boost::unordered_set<row_range, row_hasher, row_hasher> index;

            builder_t(val_t eps = 1e-5f)
                : hasher(eps), index(1979, hasher, hasher)
            {
                row.push_back(0);
            }

            void insert(col_t row_begin, col_t row_end,
                    const row_t *r, const col_t *c, const val_t *v)
            {
                for(col_t i = row_begin, j = 0; i < row_end; ++i, ++j) {
                    shift s(-i);

                    auto range = boost::make_tuple(
                            boost::make_zip_iterator(
                                boost::make_tuple(
                                    boost::make_transform_iterator(c + r[j], s),
                                    v + r[j])
                                ),
                            boost::make_zip_iterator(
                                boost::make_tuple(
                                    boost::make_transform_iterator(c + r[j+1], s),
                                    v + r[j+1])
                                )
                            );

                    auto pos = index.find(range, hasher, hasher);

                    if (pos == index.end()) {
                        idx.push_back(index.size());

                        size_t start = val.size();

                        for(size_t k = r[j]; k < r[j+1]; ++k) {
                            col.push_back( c[k] - i );
                            val.push_back( v[k] );
                        }

                        index.insert(
                                boost::make_tuple(
                                    boost::make_zip_iterator(
                                        boost::make_tuple(
                                            col.begin() + start,
                                            val.begin() + start)
                                        ),
                                    boost::make_zip_iterator(
                                        boost::make_tuple(
                                            col.end(),
                                            val.end()
                                            )
                                        ),
                                    index.size()
                                    )
                                );

                        row.push_back(val.size());
                    } else {
                        idx.push_back(boost::get<2>(*pos));
                    }
                }
            }
        };

        std::unique_ptr<builder_t> builder;

    public:
        typedef boost::zip_iterator<
                    boost::tuple<
                        boost::transform_iterator<
                            shift, typename std::vector<col_t>::const_iterator
                        >,
                        typename std::vector<val_t>::const_iterator
                    >
                > const_row_iterator;

        /// Constructor.
        matrix(size_t rows, size_t cols, val_t eps = 1e-5)
            : rows(rows), cols(cols), builder(new builder_t(eps))
        {
        }

        void insert(col_t row_begin, col_t row_end,
                const row_t *r, const col_t *c, const val_t *v)
        {
            builder->insert(row_begin, row_end, r, c, v);
        }

        size_t finish() {
            if (builder->idx.size() != rows) throw std::logic_error(
                    "Matrix construction is incomplete "
                    "(some rows are left untouched)"
                    );

            idx.assign(builder->idx.begin(), builder->idx.end());
            row.assign(builder->row.begin(), builder->row.end());
            col.assign(builder->col.begin(), builder->col.end());
            val.assign(builder->val.begin(), builder->val.end());

            builder.reset();

            return row.size() - 1;
        }

        /// Begin boost::zip_iterator to columns/values for a given row.
        const_row_iterator begin(size_t i) const {
            assert(!builder && i < rows);

            return boost::make_zip_iterator(
                    boost::make_tuple(
                        boost::make_transform_iterator(
                            col.begin() + row[idx[i]],
                            shift(i)
                            ),
                        val.begin() + row[idx[i]]
                        )
                    );
        }

        /// End boost::zip_iterator to columns/values for a given row.
        const_row_iterator end(size_t i) const {
            assert(!builder && i < rows);

            return boost::make_zip_iterator(
                    boost::make_tuple(
                        boost::make_transform_iterator(
                            col.begin() + row[idx[i] + 1],
                            shift(i)
                            ),
                        val.begin() + row[idx[i] + 1]
                        )
                    );
        }
};

} // namespace ccsr

#endif
<commit_msg>Clarified comment<commit_after>#ifndef CCSR_HPP
#define CCSR_HPP

/**
 * \file   ccsr.hpp
 * \author Denis Demidov <ddemidov@ksu.ru>
 * \brief  Compressed CSR format composition.
 *
 * Lossy compression for CSR sparse matrix format. Stores unique matrix rows,
 * where uniqueness is determined approximately. If the precision loss is not
 * important (e.g. coefficients come from an experiment with incorporated
 * observation error), it may result in significant storage savings for large
 * matrices.
 */

#include <vector>
#include <deque>
#include <type_traits>
#include <memory>
#include <functional>
#include <exception>
#include <cassert>

#include <boost/unordered_set.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>

namespace ccsr {

template <typename T>
struct hash_impl {
    static inline size_t get(T v) {
        return std::hash<T>()(v);
    }
};

template <>
struct hash_impl<double> {
    static inline size_t get(double v) {
        static const uint64_t mask = 0xffffffffff000000;
                                    // eeefffffffffffff;
        // Zero-out least significant bits and hash as uint64_t:
        return std::hash<uint64_t>()(*reinterpret_cast<const uint64_t*>(&v) & mask);
    }
};

template <>
struct hash_impl<float> {
    static inline size_t get(float v) {
        static const uint32_t mask = 0xfffffc00;
                                    // eeffffff;
        // Zero-out least significant bits and hash as uint64_t:
        return std::hash<uint32_t>()(*reinterpret_cast<const uint32_t*>(&v) & mask);
    }
};

template <class T>
inline size_t hash(const T &v) {
    return hash_impl<T>::get(v);
}

template <
    typename val_t = double,
    typename row_t = size_t,
    typename col_t = ptrdiff_t,
    typename idx_t = row_t
    >
class matrix {
    static_assert(std::is_signed<col_t>::value, "Column type should be signed!");

    private:
        size_t rows, cols;

        std::vector< idx_t > idx;
        std::vector< row_t > row;
        std::vector< col_t > col;
        std::vector< val_t > val;

        struct shift {
            typedef col_t result_type;

            col_t s;

            shift(col_t s) : s(s) {}

            col_t operator()(col_t v) const {
                return v + s;
            }
        };

        struct builder_t {
            std::deque< idx_t > idx;
            std::deque< row_t > row;
            std::deque< col_t > col;
            std::deque< val_t > val;

            struct row_hasher {
                val_t eps;

                row_hasher(val_t eps) : eps(eps) {}

                template <class Range>
                size_t operator()(const Range &r) const {
                    using boost::get;

                    auto begin = get<0>(r);
                    auto end   = get<1>(r);

                    size_t h = hash(end - begin);

                    for(auto i = begin; i != end; ++i)
                        h ^= hash(get<0>(*i)) ^ hash(get<1>(*i));

                    return h;
                }

                template <class Range1, class Range2>
                bool operator()(const Range1 &r1, const Range2 &r2) const {
                    using boost::get;

                    auto i1 = get<0>(r1);
                    auto e1 = get<1>(r1);
                    auto i2 = get<0>(r2);
                    auto e2 = get<1>(r2);

                    if (e1 - i1 != e2 - i2) return false;

                    for(; i1 != e1; ++i1, ++i2) {
                        if (get<0>(*i1) != get<0>(*i2))
                            return false;

                        if (fabs(get<1>(*i1) - get<1>(*i2)) > eps)
                            return false;
                    }

                    return true;
                }
            } hasher;

            typedef boost::zip_iterator<
                        boost::tuple<
                            typename std::deque< col_t >::const_iterator,
                            typename std::deque< val_t >::const_iterator
                        >
                    > row_iterator;

            typedef boost::tuple< row_iterator, row_iterator, size_t > row_range;

            boost::unordered_set<row_range, row_hasher, row_hasher> index;

            builder_t(val_t eps = 1e-5f)
                : hasher(eps), index(1979, hasher, hasher)
            {
                row.push_back(0);
            }

            void insert(col_t row_begin, col_t row_end,
                    const row_t *r, const col_t *c, const val_t *v)
            {
                for(col_t i = row_begin, j = 0; i < row_end; ++i, ++j) {
                    shift s(-i);

                    auto range = boost::make_tuple(
                            boost::make_zip_iterator(
                                boost::make_tuple(
                                    boost::make_transform_iterator(c + r[j], s),
                                    v + r[j])
                                ),
                            boost::make_zip_iterator(
                                boost::make_tuple(
                                    boost::make_transform_iterator(c + r[j+1], s),
                                    v + r[j+1])
                                )
                            );

                    auto pos = index.find(range, hasher, hasher);

                    if (pos == index.end()) {
                        idx.push_back(index.size());

                        size_t start = val.size();

                        for(size_t k = r[j]; k < r[j+1]; ++k) {
                            col.push_back( c[k] - i );
                            val.push_back( v[k] );
                        }

                        index.insert(
                                boost::make_tuple(
                                    boost::make_zip_iterator(
                                        boost::make_tuple(
                                            col.begin() + start,
                                            val.begin() + start)
                                        ),
                                    boost::make_zip_iterator(
                                        boost::make_tuple(
                                            col.end(),
                                            val.end()
                                            )
                                        ),
                                    index.size()
                                    )
                                );

                        row.push_back(val.size());
                    } else {
                        idx.push_back(boost::get<2>(*pos));
                    }
                }
            }
        };

        std::unique_ptr<builder_t> builder;

    public:
        typedef boost::zip_iterator<
                    boost::tuple<
                        boost::transform_iterator<
                            shift, typename std::vector<col_t>::const_iterator
                        >,
                        typename std::vector<val_t>::const_iterator
                    >
                > const_row_iterator;

        /// Constructor.
        matrix(size_t rows, size_t cols, val_t eps = 1e-5)
            : rows(rows), cols(cols), builder(new builder_t(eps))
        {
        }

        void insert(col_t row_begin, col_t row_end,
                const row_t *r, const col_t *c, const val_t *v)
        {
            builder->insert(row_begin, row_end, r, c, v);
        }

        size_t finish() {
            if (builder->idx.size() != rows) throw std::logic_error(
                    "Matrix construction is incomplete "
                    "(some rows are left untouched)"
                    );

            idx.assign(builder->idx.begin(), builder->idx.end());
            row.assign(builder->row.begin(), builder->row.end());
            col.assign(builder->col.begin(), builder->col.end());
            val.assign(builder->val.begin(), builder->val.end());

            builder.reset();

            return row.size() - 1;
        }

        /// Begin boost::zip_iterator to columns/values for a given row.
        const_row_iterator begin(size_t i) const {
            assert(!builder && i < rows);

            return boost::make_zip_iterator(
                    boost::make_tuple(
                        boost::make_transform_iterator(
                            col.begin() + row[idx[i]],
                            shift(i)
                            ),
                        val.begin() + row[idx[i]]
                        )
                    );
        }

        /// End boost::zip_iterator to columns/values for a given row.
        const_row_iterator end(size_t i) const {
            assert(!builder && i < rows);

            return boost::make_zip_iterator(
                    boost::make_tuple(
                        boost::make_transform_iterator(
                            col.begin() + row[idx[i] + 1],
                            shift(i)
                            ),
                        val.begin() + row[idx[i] + 1]
                        )
                    );
        }
};

} // namespace ccsr

#endif
<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkImageDataItem.h"
#include "mitkMemoryUtilities.h"
#include <vtkImageData.h>
#include <vtkPointData.h>

#include <vtkBitArray.h>
#include <vtkCharArray.h>
#include <vtkDoubleArray.h>
#include <vtkFloatArray.h>
#include <vtkIntArray.h>
#include <vtkLongArray.h>
#include <vtkShortArray.h>
#include <vtkUnsignedCharArray.h>
#include <vtkUnsignedIntArray.h>
#include <vtkUnsignedLongArray.h>
#include <vtkUnsignedShortArray.h>

#include <mitkImageVtkAccessor.h>
#include <mitkImage.h>

mitk::ImageDataItem::ImageDataItem(const ImageDataItem& aParent, const mitk::ImageDescriptor::Pointer desc, unsigned int dimension, void *data, bool manageMemory, size_t offset) :
  m_Data(NULL), m_ManageMemory(false), m_VtkImageData(NULL), m_Offset(offset), m_IsComplete(false), m_Size(0),
  m_Parent(&aParent)
{
  m_PixelType = new mitk::PixelType(aParent.GetPixelType());
  m_Data = static_cast<unsigned char*>(aParent.m_Data)+offset;

  // compute size
  //const unsigned int *dims = desc->GetDimensions();
  m_Dimension = dimension;
  for( unsigned int i=0; i<dimension; i++)
    m_Dimensions[i] = desc->GetDimensions()[i];
  this->ComputeItemSize(m_Dimensions,dimension);

  if(data != NULL)
  {
    memcpy(m_Data, data, m_Size);
    if(manageMemory)
    {
      delete [] (unsigned char*) data;
    }
  }
  m_ReferenceCountLock.Lock();
  m_ReferenceCount = 0;
  m_ReferenceCountLock.Unlock();
}

mitk::ImageDataItem::~ImageDataItem()
{
  if(m_VtkImageData!=NULL)
    m_VtkImageData->Delete();
  if(m_Parent.IsNull())
  {
    if(m_ManageMemory)
      delete [] m_Data;
  }
  delete m_PixelType;
}

mitk::ImageDataItem::ImageDataItem(const mitk::ImageDescriptor::Pointer desc, void *data, bool manageMemory)
  : m_Data((unsigned char*)data), m_ManageMemory(manageMemory), m_VtkImageData(NULL), m_Offset(0), m_IsComplete(false), m_Size(0)
{
  m_PixelType = new mitk::PixelType(desc->GetChannelDescriptor(0).GetPixelType());

  // compute size
  const unsigned int *dimensions = desc->GetDimensions();

  m_Dimension = desc->GetNumberOfDimensions();
  for( unsigned int i=0; i<m_Dimension; i++)
    m_Dimensions[i] = dimensions[i];

  this->ComputeItemSize(m_Dimensions, m_Dimension );

  if(m_Data == NULL)
  {
    m_Data = mitk::MemoryUtilities::AllocateElements<unsigned char>( m_Size );
    m_ManageMemory = true;
  }

  m_ReferenceCountLock.Lock();
  m_ReferenceCount = 0;
  m_ReferenceCountLock.Unlock();

}

mitk::ImageDataItem::ImageDataItem(const mitk::PixelType& type, unsigned int dimension, unsigned int *dimensions, void *data, bool manageMemory) :
  m_Data((unsigned char*)data), m_ManageMemory(manageMemory), m_VtkImageData(NULL), m_Offset(0), m_IsComplete(false), m_Size(0),
  m_Parent(NULL)
{
  m_PixelType = new mitk::PixelType(type);

  m_Dimension = dimension;
  for( unsigned int i=0; i<m_Dimension; i++)
    m_Dimensions[i] = dimensions[i];

  this->ComputeItemSize(dimensions, dimension);

  if(m_Data == NULL)
  {
    m_Data = mitk::MemoryUtilities::AllocateElements<unsigned char>( m_Size );
    m_ManageMemory = true;
  }

  m_ReferenceCountLock.Lock();
  m_ReferenceCount = 0;
  m_ReferenceCountLock.Unlock();
}

mitk::ImageDataItem::ImageDataItem(const ImageDataItem &other)
  : itk::LightObject(), m_PixelType(other.m_PixelType), m_ManageMemory(other.m_ManageMemory), m_Offset(other.m_Offset),
    m_IsComplete(other.m_IsComplete), m_Size(other.m_Size)
{

}

void mitk::ImageDataItem::ComputeItemSize(const unsigned int *dimensions, unsigned int dimension)
{
  m_Size = m_PixelType->GetSize();
  for( unsigned int i=0; i<dimension; i++)
  {
    m_Size *= *(dimensions+i);
  }
}

void mitk::ImageDataItem::ConstructVtkImageData(ImagePointer iP) const
{
  mitk::ImageVtkAccessor *inData = ImageVtkAccessor::New(iP,this); //vtkImageData::New();
  vtkDataArray *scalars = NULL;

  const unsigned int *dims = m_Dimensions;
  const unsigned int dim = m_Dimension;

  unsigned long size = 0;
  if ( dim == 1 )
  {
    inData->SetDimensions( dims[0] -1, 1, 1);
    size = dims[0];
    inData->SetOrigin( ((float) dims[0]) / 2.0f, 0, 0 );
  }
  else
  if ( dim == 2 )
  {
    inData->SetDimensions( dims[0] , dims[1] , 1 );
    size = dims[0] * dims[1];
    inData->SetOrigin( ((float) dims[0]) / 2.0f, ((float) dims[1]) / 2.0f, 0 );
  }
  else
  if ( dim >= 3 )
  {
    inData->SetDimensions( dims[0], dims[1], dims[2] );
    size = dims[0] * dims[1] * dims[2];
    // Test
    //inData->SetOrigin( (float) dims[0] / 2.0f, (float) dims[1] / 2.0f, (float) dims[2] / 2.0f );
    inData->SetOrigin( 0, 0, 0 );
  }
  else
  {
    inData->Delete () ;
    return;
  }

  inData->SetNumberOfScalarComponents(m_PixelType->GetNumberOfComponents());

/*  if ( ( m_PixelType.GetType() == mitkIpPicInt || m_PixelType.GetType() == mitkIpPicUInt ) && m_PixelType.GetBitsPerComponent() == 1 )
  {
    inData->SetScalarType( VTK_BIT );
    scalars = vtkBitArray::New();
  }
  else*/ if ( m_PixelType->GetComponentType() == itk::ImageIOBase::CHAR )
  {
    inData->SetScalarType( VTK_CHAR );
    scalars = vtkCharArray::New();
  }
  else if (   m_PixelType->GetComponentType() == itk::ImageIOBase::UCHAR)
  {
    inData->SetScalarType( VTK_UNSIGNED_CHAR );
    scalars = vtkUnsignedCharArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::SHORT )
  {
    inData->SetScalarType( VTK_SHORT );
    scalars = vtkShortArray::New();
  }
  else if (   m_PixelType->GetComponentType() == itk::ImageIOBase::USHORT )
  {
    inData->SetScalarType( VTK_UNSIGNED_SHORT );
    scalars = vtkUnsignedShortArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::INT )
  {
    inData->SetScalarType( VTK_INT );
    scalars = vtkIntArray::New();
  }
  else if (   m_PixelType->GetComponentType() == itk::ImageIOBase::UINT )
  {
    inData->SetScalarType( VTK_UNSIGNED_INT );
    scalars = vtkUnsignedIntArray::New();
  }
  else if ( m_PixelType->GetComponentType() == itk::ImageIOBase::LONG )
  {
    inData->SetScalarType( VTK_LONG );
    scalars = vtkLongArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::ULONG )
  {
    inData->SetScalarType( VTK_UNSIGNED_LONG );
    scalars = vtkUnsignedLongArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::FLOAT  )
  {
    inData->SetScalarType( VTK_FLOAT );
    scalars = vtkFloatArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::DOUBLE  )
  {
    inData->SetScalarType( VTK_DOUBLE );
    scalars = vtkDoubleArray::New();
  }
  else
  {
    inData->Delete();
    return;
  }

  m_VtkImageData = inData;

  // allocate the new scalars
  scalars->SetNumberOfComponents(m_VtkImageData->GetNumberOfScalarComponents());

  scalars->SetVoidArray(m_Data, size * m_VtkImageData->GetNumberOfScalarComponents(), 1);

  m_VtkImageData->GetPointData()->SetScalars(scalars);
  scalars->Delete();

}

void mitk::ImageDataItem::Modified() const
{
  if(m_VtkImageData)
    m_VtkImageData->Modified();
}

mitk::ImageVtkAccessor* mitk::ImageDataItem::GetVtkImageData(mitk::ImagePointer iP) const
{
  if(m_VtkImageData==NULL)
    ConstructVtkImageData(iP);
  return m_VtkImageData;
}

<commit_msg>Change AllocateScalars method in mitkImageDataItem<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkImageDataItem.h"
#include "mitkMemoryUtilities.h"
#include <vtkImageData.h>
#include <vtkPointData.h>

#include <vtkBitArray.h>
#include <vtkCharArray.h>
#include <vtkDoubleArray.h>
#include <vtkFloatArray.h>
#include <vtkIntArray.h>
#include <vtkLongArray.h>
#include <vtkShortArray.h>
#include <vtkUnsignedCharArray.h>
#include <vtkUnsignedIntArray.h>
#include <vtkUnsignedLongArray.h>
#include <vtkUnsignedShortArray.h>

#include <mitkImageVtkAccessor.h>
#include <mitkImage.h>

mitk::ImageDataItem::ImageDataItem(const ImageDataItem& aParent, const mitk::ImageDescriptor::Pointer desc, unsigned int dimension, void *data, bool manageMemory, size_t offset) :
  m_Data(NULL), m_ManageMemory(false), m_VtkImageData(NULL), m_Offset(offset), m_IsComplete(false), m_Size(0),
  m_Parent(&aParent)
{
  m_PixelType = new mitk::PixelType(aParent.GetPixelType());
  m_Data = static_cast<unsigned char*>(aParent.m_Data)+offset;

  // compute size
  //const unsigned int *dims = desc->GetDimensions();
  m_Dimension = dimension;
  for( unsigned int i=0; i<dimension; i++)
    m_Dimensions[i] = desc->GetDimensions()[i];
  this->ComputeItemSize(m_Dimensions,dimension);

  if(data != NULL)
  {
    memcpy(m_Data, data, m_Size);
    if(manageMemory)
    {
      delete [] (unsigned char*) data;
    }
  }
  m_ReferenceCountLock.Lock();
  m_ReferenceCount = 0;
  m_ReferenceCountLock.Unlock();
}

mitk::ImageDataItem::~ImageDataItem()
{
  if(m_VtkImageData!=NULL)
    m_VtkImageData->Delete();
  if(m_Parent.IsNull())
  {
    if(m_ManageMemory)
      delete [] m_Data;
  }
  delete m_PixelType;
}

mitk::ImageDataItem::ImageDataItem(const mitk::ImageDescriptor::Pointer desc, void *data, bool manageMemory)
  : m_Data((unsigned char*)data), m_ManageMemory(manageMemory), m_VtkImageData(NULL), m_Offset(0), m_IsComplete(false), m_Size(0)
{
  m_PixelType = new mitk::PixelType(desc->GetChannelDescriptor(0).GetPixelType());

  // compute size
  const unsigned int *dimensions = desc->GetDimensions();

  m_Dimension = desc->GetNumberOfDimensions();
  for( unsigned int i=0; i<m_Dimension; i++)
    m_Dimensions[i] = dimensions[i];

  this->ComputeItemSize(m_Dimensions, m_Dimension );

  if(m_Data == NULL)
  {
    m_Data = mitk::MemoryUtilities::AllocateElements<unsigned char>( m_Size );
    m_ManageMemory = true;
  }

  m_ReferenceCountLock.Lock();
  m_ReferenceCount = 0;
  m_ReferenceCountLock.Unlock();

}

mitk::ImageDataItem::ImageDataItem(const mitk::PixelType& type, unsigned int dimension, unsigned int *dimensions, void *data, bool manageMemory) :
  m_Data((unsigned char*)data), m_ManageMemory(manageMemory), m_VtkImageData(NULL), m_Offset(0), m_IsComplete(false), m_Size(0),
  m_Parent(NULL)
{
  m_PixelType = new mitk::PixelType(type);

  m_Dimension = dimension;
  for( unsigned int i=0; i<m_Dimension; i++)
    m_Dimensions[i] = dimensions[i];

  this->ComputeItemSize(dimensions, dimension);

  if(m_Data == NULL)
  {
    m_Data = mitk::MemoryUtilities::AllocateElements<unsigned char>( m_Size );
    m_ManageMemory = true;
  }

  m_ReferenceCountLock.Lock();
  m_ReferenceCount = 0;
  m_ReferenceCountLock.Unlock();
}

mitk::ImageDataItem::ImageDataItem(const ImageDataItem &other)
  : itk::LightObject(), m_PixelType(other.m_PixelType), m_ManageMemory(other.m_ManageMemory), m_Offset(other.m_Offset),
    m_IsComplete(other.m_IsComplete), m_Size(other.m_Size)
{

}

void mitk::ImageDataItem::ComputeItemSize(const unsigned int *dimensions, unsigned int dimension)
{
  m_Size = m_PixelType->GetSize();
  for( unsigned int i=0; i<dimension; i++)
  {
    m_Size *= *(dimensions+i);
  }
}

void mitk::ImageDataItem::ConstructVtkImageData(ImagePointer iP) const
{
  mitk::ImageVtkAccessor *inData = ImageVtkAccessor::New(iP,this); //vtkImageData::New();
  vtkDataArray *scalars = NULL;

  const unsigned int *dims = m_Dimensions;
  const unsigned int dim = m_Dimension;

  unsigned long size = 0;
  if ( dim == 1 )
  {
    inData->SetDimensions( dims[0] -1, 1, 1);
    size = dims[0];
    inData->SetOrigin( ((float) dims[0]) / 2.0f, 0, 0 );
  }
  else
  if ( dim == 2 )
  {
    inData->SetDimensions( dims[0] , dims[1] , 1 );
    size = dims[0] * dims[1];
    inData->SetOrigin( ((float) dims[0]) / 2.0f, ((float) dims[1]) / 2.0f, 0 );
  }
  else
  if ( dim >= 3 )
  {
    inData->SetDimensions( dims[0], dims[1], dims[2] );
    size = dims[0] * dims[1] * dims[2];
    // Test
    //inData->SetOrigin( (float) dims[0] / 2.0f, (float) dims[1] / 2.0f, (float) dims[2] / 2.0f );
    inData->SetOrigin( 0, 0, 0 );
  }
  else
  {
    inData->Delete () ;
    return;
  }

  int datatype;

/*  if ( ( m_PixelType.GetType() == mitkIpPicInt || m_PixelType.GetType() == mitkIpPicUInt ) && m_PixelType.GetBitsPerComponent() == 1 )
  {
    datatype = VTK_BIT );
    scalars = vtkBitArray::New();
  }
  else*/ if ( m_PixelType->GetComponentType() == itk::ImageIOBase::CHAR )
  {
    datatype = VTK_CHAR;
    scalars = vtkCharArray::New();
  }
  else if (   m_PixelType->GetComponentType() == itk::ImageIOBase::UCHAR)
  {
    datatype = VTK_UNSIGNED_CHAR;
    scalars = vtkUnsignedCharArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::SHORT )
  {
    datatype = VTK_SHORT;
    scalars = vtkShortArray::New();
  }
  else if (   m_PixelType->GetComponentType() == itk::ImageIOBase::USHORT )
  {
    datatype = VTK_UNSIGNED_SHORT;
    scalars = vtkUnsignedShortArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::INT )
  {
    datatype = VTK_INT;
    scalars = vtkIntArray::New();
  }
  else if (   m_PixelType->GetComponentType() == itk::ImageIOBase::UINT )
  {
    datatype = VTK_UNSIGNED_INT;
    scalars = vtkUnsignedIntArray::New();
  }
  else if ( m_PixelType->GetComponentType() == itk::ImageIOBase::LONG )
  {
    datatype = VTK_LONG;
    scalars = vtkLongArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::ULONG )
  {
    datatype = VTK_UNSIGNED_LONG;
    scalars = vtkUnsignedLongArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::FLOAT  )
  {
    datatype = VTK_FLOAT;
    scalars = vtkFloatArray::New();
  }
  else if (  m_PixelType->GetComponentType() == itk::ImageIOBase::DOUBLE  )
  {
    datatype = VTK_DOUBLE;
    scalars = vtkDoubleArray::New();
  }
  else
  {
    inData->Delete();
    return;
  }

  inData->AllocateScalars(datatype,m_PixelType->GetNumberOfComponents());

  m_VtkImageData = inData;

  // allocate the new scalars
  scalars->SetNumberOfComponents(m_VtkImageData->GetNumberOfScalarComponents());

  scalars->SetVoidArray(m_Data, size * m_VtkImageData->GetNumberOfScalarComponents(), 1);

  m_VtkImageData->GetPointData()->SetScalars(scalars);
  scalars->Delete();

}

void mitk::ImageDataItem::Modified() const
{
  if(m_VtkImageData)
    m_VtkImageData->Modified();
}

mitk::ImageVtkAccessor* mitk::ImageDataItem::GetVtkImageData(mitk::ImagePointer iP) const
{
  if(m_VtkImageData==NULL)
    ConstructVtkImageData(iP);
  return m_VtkImageData;
}

<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/renderer/atom_render_view_observer.h"

#include <string>
#include <vector>

// Put this before event_emitter_caller.h to have string16 support.
#include "atom/common/native_mate_converters/string16_converter.h"

#include "atom/common/api/api_messages.h"
#include "atom/common/api/event_emitter_caller.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_renderer_client.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/renderer/render_view.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/net_module.h"
#include "net/grit/net_resources.h"
#include "third_party/WebKit/public/web/WebDraggableRegion.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/resource/resource_bundle.h"

namespace atom {

namespace {

bool GetIPCObject(v8::Isolate* isolate,
                  v8::Local<v8::Context> context,
                  v8::Local<v8::Object>* ipc) {
  v8::Local<v8::String> key = mate::StringToV8(isolate, "ipc");
  v8::Local<v8::Value> value = context->Global()->GetHiddenValue(key);
  if (value.IsEmpty() || !value->IsObject())
    return false;
  *ipc = value->ToObject();
  return true;
}

std::vector<v8::Local<v8::Value>> ListValueToVector(
    v8::Isolate* isolate,
    const base::ListValue& list) {
  v8::Local<v8::Value> array = mate::ConvertToV8(isolate, list);
  std::vector<v8::Local<v8::Value>> result;
  mate::ConvertFromV8(isolate, array, &result);
  return result;
}

base::StringPiece NetResourceProvider(int key) {
  if (key == IDR_DIR_HEADER_HTML) {
    base::StringPiece html_data =
        ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
            IDR_DIR_HEADER_HTML);
    return html_data;
  }
  return base::StringPiece();
}

}  // namespace

AtomRenderViewObserver::AtomRenderViewObserver(
    content::RenderView* render_view,
    AtomRendererClient* renderer_client)
    : content::RenderViewObserver(render_view),
      renderer_client_(renderer_client),
      document_created_(false) {
  // Initialise resource for directory listing.
  net::NetModule::SetResourceProvider(NetResourceProvider);
}

AtomRenderViewObserver::~AtomRenderViewObserver() {
}

void AtomRenderViewObserver::DidCreateDocumentElement(
    blink::WebLocalFrame* frame) {
  document_created_ = true;

  // Read --zoom-factor from command line.
  std::string zoom_factor_str = base::CommandLine::ForCurrentProcess()->
      GetSwitchValueASCII(switches::kZoomFactor);;
  if (zoom_factor_str.empty())
    return;
  double zoom_factor;
  if (!base::StringToDouble(zoom_factor_str, &zoom_factor))
    return;
  double zoom_level = blink::WebView::zoomFactorToZoomLevel(zoom_factor);
  frame->view()->setZoomLevel(zoom_level);
}

void AtomRenderViewObserver::DraggableRegionsChanged(blink::WebFrame* frame) {
  blink::WebVector<blink::WebDraggableRegion> webregions =
      frame->document().draggableRegions();
  std::vector<DraggableRegion> regions;
  for (size_t i = 0; i < webregions.size(); ++i) {
    DraggableRegion region;
    region.bounds = webregions[i].bounds;
    region.draggable = webregions[i].draggable;
    regions.push_back(region);
  }
  Send(new AtomViewHostMsg_UpdateDraggableRegions(routing_id(), regions));
}

bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
    IPC_MESSAGE_HANDLER(AtomViewMsg_Message, OnBrowserMessage)
    IPC_MESSAGE_HANDLER(AtomViewMsg_ExecuteJavaScript,
                        OnJavaScriptExecuteRequest)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel,
                                              const base::ListValue& args) {
  if (!document_created_)
    return;

  if (!render_view()->GetWebView())
    return;

  blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
  if (!frame || frame->isWebRemoteFrame())
    return;

  v8::Isolate* isolate = blink::mainThreadIsolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = frame->mainWorldScriptContext();
  v8::Context::Scope context_scope(context);

  v8::Local<v8::Object> ipc;
  if (GetIPCObject(isolate, context, &ipc)) {
    auto args_vector = ListValueToVector(isolate, args);
    // Insert a dummy Event object.
    args_vector.insert(args_vector.begin(), v8::Object::New(isolate));
    mate::EmitEvent(isolate, ipc, channel, args_vector);
  }
}

void AtomRenderViewObserver::OnJavaScriptExecuteRequest(
    const base::string16& code, bool has_user_gesture) {
  if (!document_created_)
    return;

  if (!render_view()->GetWebView())
    return;

  scoped_ptr<blink::WebScopedUserGesture> gesture(
      has_user_gesture ? new blink::WebScopedUserGesture : nullptr);

  v8::Isolate* isolate = blink::mainThreadIsolate();
  v8::HandleScope handle_scope(isolate);

  blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
  frame->executeScriptAndReturnValue(blink::WebScriptSource(code));
}

}  // namespace atom
<commit_msg>Implement event.sender for ipcRenderer<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/renderer/atom_render_view_observer.h"

#include <string>
#include <vector>

// Put this before event_emitter_caller.h to have string16 support.
#include "atom/common/native_mate_converters/string16_converter.h"

#include "atom/common/api/api_messages.h"
#include "atom/common/api/event_emitter_caller.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
#include "atom/renderer/atom_renderer_client.h"
#include "base/command_line.h"
#include "base/strings/string_number_conversions.h"
#include "content/public/renderer/render_view.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/net_module.h"
#include "net/grit/net_resources.h"
#include "third_party/WebKit/public/web/WebDraggableRegion.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "ui/base/resource/resource_bundle.h"
#include "native_mate/dictionary.h"

namespace atom {

namespace {

bool GetIPCObject(v8::Isolate* isolate,
                  v8::Local<v8::Context> context,
                  v8::Local<v8::Object>* ipc) {
  v8::Local<v8::String> key = mate::StringToV8(isolate, "ipc");
  v8::Local<v8::Value> value = context->Global()->GetHiddenValue(key);
  if (value.IsEmpty() || !value->IsObject())
    return false;
  *ipc = value->ToObject();
  return true;
}

std::vector<v8::Local<v8::Value>> ListValueToVector(
    v8::Isolate* isolate,
    const base::ListValue& list) {
  v8::Local<v8::Value> array = mate::ConvertToV8(isolate, list);
  std::vector<v8::Local<v8::Value>> result;
  mate::ConvertFromV8(isolate, array, &result);
  return result;
}

base::StringPiece NetResourceProvider(int key) {
  if (key == IDR_DIR_HEADER_HTML) {
    base::StringPiece html_data =
        ui::ResourceBundle::GetSharedInstance().GetRawDataResource(
            IDR_DIR_HEADER_HTML);
    return html_data;
  }
  return base::StringPiece();
}

}  // namespace

AtomRenderViewObserver::AtomRenderViewObserver(
    content::RenderView* render_view,
    AtomRendererClient* renderer_client)
    : content::RenderViewObserver(render_view),
      renderer_client_(renderer_client),
      document_created_(false) {
  // Initialise resource for directory listing.
  net::NetModule::SetResourceProvider(NetResourceProvider);
}

AtomRenderViewObserver::~AtomRenderViewObserver() {
}

void AtomRenderViewObserver::DidCreateDocumentElement(
    blink::WebLocalFrame* frame) {
  document_created_ = true;

  // Read --zoom-factor from command line.
  std::string zoom_factor_str = base::CommandLine::ForCurrentProcess()->
      GetSwitchValueASCII(switches::kZoomFactor);;
  if (zoom_factor_str.empty())
    return;
  double zoom_factor;
  if (!base::StringToDouble(zoom_factor_str, &zoom_factor))
    return;
  double zoom_level = blink::WebView::zoomFactorToZoomLevel(zoom_factor);
  frame->view()->setZoomLevel(zoom_level);
}

void AtomRenderViewObserver::DraggableRegionsChanged(blink::WebFrame* frame) {
  blink::WebVector<blink::WebDraggableRegion> webregions =
      frame->document().draggableRegions();
  std::vector<DraggableRegion> regions;
  for (size_t i = 0; i < webregions.size(); ++i) {
    DraggableRegion region;
    region.bounds = webregions[i].bounds;
    region.draggable = webregions[i].draggable;
    regions.push_back(region);
  }
  Send(new AtomViewHostMsg_UpdateDraggableRegions(routing_id(), regions));
}

bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(AtomRenderViewObserver, message)
    IPC_MESSAGE_HANDLER(AtomViewMsg_Message, OnBrowserMessage)
    IPC_MESSAGE_HANDLER(AtomViewMsg_ExecuteJavaScript,
                        OnJavaScriptExecuteRequest)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()

  return handled;
}

void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel,
                                              const base::ListValue& args) {
  if (!document_created_)
    return;

  if (!render_view()->GetWebView())
    return;

  blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
  if (!frame || frame->isWebRemoteFrame())
    return;

  v8::Isolate* isolate = blink::mainThreadIsolate();
  v8::HandleScope handle_scope(isolate);

  v8::Local<v8::Context> context = frame->mainWorldScriptContext();
  v8::Context::Scope context_scope(context);

  v8::Local<v8::Object> ipc;
  if (GetIPCObject(isolate, context, &ipc)) {
    auto args_vector = ListValueToVector(isolate, args);
    // Insert the Event object, event.sender is ipc.
    mate::Dictionary event = mate::Dictionary::CreateEmpty(isolate);
    event.Set("sender", ipc);
    args_vector.insert(args_vector.begin(), event.GetHandle());
    mate::EmitEvent(isolate, ipc, channel, args_vector);
  }
}

void AtomRenderViewObserver::OnJavaScriptExecuteRequest(
    const base::string16& code, bool has_user_gesture) {
  if (!document_created_)
    return;

  if (!render_view()->GetWebView())
    return;

  scoped_ptr<blink::WebScopedUserGesture> gesture(
      has_user_gesture ? new blink::WebScopedUserGesture : nullptr);

  v8::Isolate* isolate = blink::mainThreadIsolate();
  v8::HandleScope handle_scope(isolate);

  blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
  frame->executeScriptAndReturnValue(blink::WebScriptSource(code));
}

}  // namespace atom
<|endoftext|>


<commit_before>//
//  yas_audio_engine_io.cpp
//

#include "yas_audio_engine_io.h"

#include <cpp_utils/yas_result.h>
#include <iostream>
#include "yas_audio_engine_tap.h"
#include "yas_audio_graph.h"
#include "yas_audio_io.h"
#include "yas_audio_time.h"

using namespace yas;

#pragma mark - audio::engine::io

audio::engine::io::io() = default;

audio::engine::io::~io() = default;

void audio::engine::io::set_device(std::optional<audio::io_device_ptr> const &device) {
    this->_device = device;

    if (this->_raw_io) {
        this->_raw_io.value()->set_device(device);
    }

    if (device) {
        this->_io_observer = device.value()->io_device_chain().send_to(this->_notifier).end();
    } else {
        this->_io_observer = std::nullopt;
    }
}

std::optional<audio::io_device_ptr> const &audio::engine::io::device() const {
    return this->_device;
}

audio::engine::node_ptr const &audio::engine::io::node() const {
    return this->_node;
}

audio::io_ptr const &audio::engine::io::add_raw_io() {
    if (!this->_raw_io) {
        this->_raw_io = audio::io::make_shared(this->device());
    }
    return this->_raw_io.value();
}

void audio::engine::io::remove_raw_io() {
    this->_raw_io = std::nullopt;
}

std::optional<audio::io_ptr> const &audio::engine::io::raw_io() {
    return this->_raw_io;
}

chaining::chain_unsync_t<audio::io_device::method> audio::engine::io::io_device_chain() {
    return this->_notifier->chain();
}

void audio::engine::io::_prepare(io_ptr const &shared) {
    this->_weak_engine_io = to_weak(shared);

    this->_node->set_render_handler([weak_engine_io = this->_weak_engine_io](auto args) {
        auto &buffer = args.buffer;

        if (auto engine_io = weak_engine_io.lock()) {
            if (auto const &raw_io = engine_io->raw_io()) {
                auto const &input_buffer_opt = raw_io.value()->input_buffer_on_render();
                if (input_buffer_opt) {
                    auto const &input_buffer = *input_buffer_opt;
                    if (input_buffer->format() == buffer.format()) {
                        buffer.copy_from(*input_buffer);
                    }
                }
            }
        }
    });

    this->_connections_observer = this->_node->chain(node::method::update_connections)
                                      .perform([weak_engine_io = this->_weak_engine_io](auto const &) {
                                          if (auto engine_io = weak_engine_io.lock()) {
                                              engine_io->_update_io_connections();
                                          }
                                      })
                                      .end();
}

void audio::engine::io::_update_io_connections() {
    auto const &raw_io_opt = this->_raw_io;
    if (!raw_io_opt) {
        return;
    }

    auto const &raw_io = raw_io_opt.value();

    if (!this->_validate_connections()) {
        raw_io->set_render_handler(std::nullopt);
        return;
    }

    auto weak_io = to_weak(raw_io);

    auto render_handler = [weak_engine_io = this->_weak_engine_io, weak_io](auto args) {
        if (auto engine_io = weak_engine_io.lock()) {
            if (auto const kernel_opt = engine_io->node()->kernel()) {
                auto const &kernel = kernel_opt.value();
                auto const connections = kernel->input_connections();
                if (connections.count(0) > 0) {
                    auto const &connection = connections.at(0);
                    if (auto src_node = connection->source_node();
                        src_node && connection->format == src_node->output_format(connection->source_bus)) {
                        if (auto const when = args.when) {
                            src_node->render({.buffer = **args.output_buffer,
                                              .bus_idx = connection->source_bus,
                                              .when = *args.when});
                        }
                    }
                }

                if (auto io = weak_io.lock()) {
                    auto const connections = kernel->output_connections();
                    if (connections.count(0) > 0) {
                        auto const &connection = connections.at(0);
                        if (auto dst_node = connection->destination_node();
                            dst_node && dst_node->is_input_renderable()) {
                            auto const &input_buffer = io->input_buffer_on_render();
                            auto const &input_time = io->input_time_on_render();
                            if (input_buffer && input_time) {
                                if (connection->format == dst_node->input_format(connection->destination_bus)) {
                                    dst_node->render({.buffer = **input_buffer, .bus_idx = 0, .when = **input_time});
                                }
                            }
                        }
                    }
                }
            }
        }
    };

    raw_io->set_render_handler(std::move(render_handler));
}

bool audio::engine::io::_validate_connections() {
    if (auto const &raw_io_opt = this->_raw_io) {
        auto const &raw_io = raw_io_opt.value();

        auto &input_connections = manageable_node::cast(this->_node)->input_connections();
        if (input_connections.size() > 0) {
            auto const connections = lock_values(input_connections);
            if (connections.count(0) > 0) {
                auto const &connection = connections.at(0);
                auto const &connection_format = connection->format;
                auto const &device_opt = raw_io->device();
                if (!device_opt) {
                    std::cout << __PRETTY_FUNCTION__ << " : output device is null." << std::endl;
                    return false;
                }
                auto const &device = *device_opt;
                if (connection_format != device->output_format()) {
                    std::cout << __PRETTY_FUNCTION__ << " : output device io format is not match." << std::endl;
                    return false;
                }
            }
        }

        auto &output_connections = manageable_node::cast(this->_node)->output_connections();
        if (output_connections.size() > 0) {
            auto const connections = lock_values(output_connections);
            if (connections.count(0) > 0) {
                auto const &connection = connections.at(0);
                auto const &connection_format = connection->format;
                auto const &device_opt = raw_io->device();
                if (!device_opt) {
                    std::cout << __PRETTY_FUNCTION__ << " : output device is null." << std::endl;
                    return false;
                }
                auto const &device = *device_opt;
                if (connection_format != device->input_format()) {
                    std::cout << __PRETTY_FUNCTION__ << " : input device io format is not match." << std::endl;
                    return false;
                }
            }
        }
    }

    return true;
}

audio::engine::io_ptr audio::engine::io::make_shared() {
    auto shared = io_ptr(new audio::engine::io{});
    shared->_prepare(shared);
    return shared;
}
<commit_msg>add log<commit_after>//
//  yas_audio_engine_io.cpp
//

#include "yas_audio_engine_io.h"

#include <cpp_utils/yas_result.h>
#include <iostream>
#include "yas_audio_engine_tap.h"
#include "yas_audio_graph.h"
#include "yas_audio_io.h"
#include "yas_audio_time.h"

using namespace yas;

#pragma mark - audio::engine::io

audio::engine::io::io() = default;

audio::engine::io::~io() = default;

void audio::engine::io::set_device(std::optional<audio::io_device_ptr> const &device) {
    this->_device = device;

    if (this->_raw_io) {
        this->_raw_io.value()->set_device(device);
    }

    if (device) {
        this->_io_observer = device.value()->io_device_chain().send_to(this->_notifier).end();
    } else {
        this->_io_observer = std::nullopt;
    }
}

std::optional<audio::io_device_ptr> const &audio::engine::io::device() const {
    return this->_device;
}

audio::engine::node_ptr const &audio::engine::io::node() const {
    return this->_node;
}

audio::io_ptr const &audio::engine::io::add_raw_io() {
    if (!this->_raw_io) {
        this->_raw_io = audio::io::make_shared(this->device());
    }
    return this->_raw_io.value();
}

void audio::engine::io::remove_raw_io() {
    this->_raw_io = std::nullopt;
}

std::optional<audio::io_ptr> const &audio::engine::io::raw_io() {
    return this->_raw_io;
}

chaining::chain_unsync_t<audio::io_device::method> audio::engine::io::io_device_chain() {
    return this->_notifier->chain();
}

void audio::engine::io::_prepare(io_ptr const &shared) {
    this->_weak_engine_io = to_weak(shared);

    this->_node->set_render_handler([weak_engine_io = this->_weak_engine_io](auto args) {
        auto &buffer = args.buffer;

        if (auto engine_io = weak_engine_io.lock()) {
            if (auto const &raw_io = engine_io->raw_io()) {
                auto const &input_buffer_opt = raw_io.value()->input_buffer_on_render();
                if (input_buffer_opt) {
                    auto const &input_buffer = *input_buffer_opt;
                    if (input_buffer->format() == buffer.format()) {
                        buffer.copy_from(*input_buffer);
                    }
                }
            }
        }
    });

    this->_connections_observer = this->_node->chain(node::method::update_connections)
                                      .perform([weak_engine_io = this->_weak_engine_io](auto const &) {
                                          if (auto engine_io = weak_engine_io.lock()) {
                                              engine_io->_update_io_connections();
                                          }
                                      })
                                      .end();
}

void audio::engine::io::_update_io_connections() {
    auto const &raw_io_opt = this->_raw_io;
    if (!raw_io_opt) {
        return;
    }

    auto const &raw_io = raw_io_opt.value();

    if (!this->_validate_connections()) {
        raw_io->set_render_handler(std::nullopt);
        return;
    }

    auto weak_io = to_weak(raw_io);

    auto render_handler = [weak_engine_io = this->_weak_engine_io, weak_io](auto args) {
        if (auto engine_io = weak_engine_io.lock()) {
            if (auto const kernel_opt = engine_io->node()->kernel()) {
                auto const &kernel = kernel_opt.value();
                auto const connections = kernel->input_connections();
                if (connections.count(0) > 0) {
                    auto const &connection = connections.at(0);
                    if (auto src_node = connection->source_node();
                        src_node && connection->format == src_node->output_format(connection->source_bus)) {
                        if (auto const when = args.when) {
                            src_node->render({.buffer = **args.output_buffer,
                                              .bus_idx = connection->source_bus,
                                              .when = *args.when});
                        }
                    }
                }

                if (auto io = weak_io.lock()) {
                    auto const connections = kernel->output_connections();
                    if (connections.count(0) > 0) {
                        auto const &connection = connections.at(0);
                        if (auto dst_node = connection->destination_node();
                            dst_node && dst_node->is_input_renderable()) {
                            auto const &input_buffer = io->input_buffer_on_render();
                            auto const &input_time = io->input_time_on_render();
                            if (input_buffer && input_time) {
                                if (connection->format == dst_node->input_format(connection->destination_bus)) {
                                    dst_node->render({.buffer = **input_buffer, .bus_idx = 0, .when = **input_time});
                                }
                            }
                        }
                    }
                }
            }
        }
    };

    raw_io->set_render_handler(std::move(render_handler));
}

bool audio::engine::io::_validate_connections() {
    if (auto const &raw_io_opt = this->_raw_io) {
        auto const &raw_io = raw_io_opt.value();

        auto &input_connections = manageable_node::cast(this->_node)->input_connections();
        if (input_connections.size() > 0) {
            auto const connections = lock_values(input_connections);
            if (connections.count(0) > 0) {
                auto const &connection = connections.at(0);
                auto const &connection_format = connection->format;
                auto const &device_opt = raw_io->device();
                if (!device_opt) {
                    std::cout << __PRETTY_FUNCTION__ << " : output device is null." << std::endl;
                    return false;
                }
                auto const &device = *device_opt;
                if (connection_format != device->output_format()) {
                    std::cout << __PRETTY_FUNCTION__ << " : output device io format is not match.\n";
                    std::cout << "device output format : " << to_string(*device->output_format());
                    std::cout << "connection format : " << to_string(connection_format);
                    std::cout << std::endl;
                    return false;
                }
            }
        }

        auto &output_connections = manageable_node::cast(this->_node)->output_connections();
        if (output_connections.size() > 0) {
            auto const connections = lock_values(output_connections);
            if (connections.count(0) > 0) {
                auto const &connection = connections.at(0);
                auto const &connection_format = connection->format;
                auto const &device_opt = raw_io->device();
                if (!device_opt) {
                    std::cout << __PRETTY_FUNCTION__ << " : output device is null." << std::endl;
                    return false;
                }
                auto const &device = *device_opt;
                if (connection_format != device->input_format()) {
                    std::cout << __PRETTY_FUNCTION__ << " : input device io format is not match.\n";
                    std::cout << "device input format : " << to_string(*device->input_format());
                    std::cout << "connection format : " << to_string(connection_format);
                    std::cout << std::endl;
                    return false;
                }
            }
        }
    }

    return true;
}

audio::engine::io_ptr audio::engine::io::make_shared() {
    auto shared = io_ptr(new audio::engine::io{});
    shared->_prepare(shared);
    return shared;
}
<|endoftext|>