459 Index_ test_nrow = 0;
461 test_nrow = inputs.front().test_nrow;
462 for (
const auto& in : inputs) {
463 if (!sanisizer::is_equal(in.test_nrow, test_nrow)) {
464 throw std::runtime_error(
"inconsistent number of rows in the test dataset across entries of 'inputs'");
470 const auto nrefs = inputs.size();
471 std::vector<std::vector<Index_> > remap_intersection_to_test_index;
472 for (I<
decltype(nrefs)> r = 0; r < nrefs; ++r) {
473 if (inputs[r].intersection.has_value()) {
474 sanisizer::resize(remap_intersection_to_test_index, nrefs);
482 std::vector<Index_> universe;
483 auto remap_test_to_universe = sanisizer::create<std::vector<Index_> >(test_nrow, test_nrow);
485 auto present = sanisizer::create<std::vector<char> >(test_nrow);
486 auto count_refs = sanisizer::create<std::vector<I<
decltype(nrefs)> > >(test_nrow);
487 universe.reserve(test_nrow);
489 for (I<
decltype(nrefs)> r = 0; r < nrefs; ++r) {
490 const auto& markers = inputs[r].markers;
491 const auto& inter = inputs[r].intersection;
493 if (inter.has_value()) {
494 auto& cur_test_remap = remap_intersection_to_test_index[r];
495 sanisizer::resize(cur_test_remap, inputs[r].ref->nrow(), test_nrow);
496 for (
const auto& pp : *inter) {
497 cur_test_remap[pp.second] = pp.first;
498 count_refs[pp.first] += 1;
501 for (
const auto& labmrk : markers) {
502 for (
const auto y : labmrk) {
503 const auto ty = cur_test_remap[y];
504 if (ty != test_nrow && !present[ty]) {
506 universe.push_back(ty);
512 for (
const auto& labmrk : markers) {
513 for (
const auto y : labmrk) {
516 universe.push_back(y);
521 for (
auto& x : count_refs) {
527 std::sort(universe.begin(), universe.end());
528 const auto num_universe = universe.size();
529 I<
decltype(num_universe)> keep = 0;
530 for (I<
decltype(num_universe)> u = 0; u < num_universe; ++u) {
531 const auto marker = universe[u];
532 if (count_refs[marker] == nrefs) {
533 universe[keep] = marker;
534 remap_test_to_universe[marker] = keep;
538 universe.resize(keep);
539 universe.shrink_to_fit();
543 auto references = sanisizer::create<std::vector<IntegratedReference<Index_> > >(nrefs);
544 for (I<
decltype(nrefs)> r = 0; r < nrefs; ++r) {
545 const auto& curinput = inputs[r];
546 const auto& currefmarkers = curinput.markers;
547 const auto nlabels = currefmarkers.size();
548 auto& currefout = references[r];
550 const bool is_sparse = curinput.ref->is_sparse();
552 currefout.sparse.emplace(sanisizer::as_size_type<I<
decltype(*(currefout.sparse))> >(nlabels));
554 currefout.dense.emplace(sanisizer::as_size_type<I<
decltype(*(currefout.dense))> >(nlabels));
557 auto get_markers = [&](I<
decltype(nlabels)> l) -> std::vector<Index_>& {
559 return (*(currefout.sparse))[l].markers;
561 return (*(currefout.dense))[l].markers;
565 if (curinput.intersection.has_value()) {
566 auto& cur_test_remap = remap_intersection_to_test_index[r];
567 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
568 const auto& curlabmarkers = currefmarkers[l];
569 auto& markers = get_markers(l);
570 markers.reserve(curlabmarkers.size());
571 for (
const auto y : curlabmarkers) {
572 const auto ty = cur_test_remap[y];
573 if (ty != test_nrow) {
574 const auto universe_index = remap_test_to_universe[ty];
575 if (universe_index != test_nrow) {
576 markers.push_back(universe_index);
583 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
584 const auto& curlabmarkers = currefmarkers[l];
585 auto& markers = get_markers(l);
586 markers.reserve(curlabmarkers.size());
587 for (
const auto y : curlabmarkers) {
588 const auto universe_index = remap_test_to_universe[y];
589 if (universe_index != test_nrow) {
590 markers.push_back(universe_index);
599 remap_intersection_to_test_index.clear();
602 for (I<
decltype(nrefs)> r = 0; r < nrefs; ++r) {
603 const auto& curinput = inputs[r];
604 auto& currefout = references[r];
609 const Index_ NC = curinput.ref->ncol();
611 throw std::runtime_error(
"reference dataset must have at least one column");
613 std::vector<Index_> positions;
614 sanisizer::reserve(positions, NC);
616 const auto nlabels = curinput.markers.size();
617 auto samples_per_label = sanisizer::create<std::vector<Index_> >(nlabels);
618 for (Index_ c = 0; c < NC; ++c) {
619 auto& pos = samples_per_label[curinput.labels[c]];
620 positions.push_back(pos);
627 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
628 if (samples_per_label[l] == 0) {
629 throw std::runtime_error(
"no profiles available for label " + std::to_string(l) +
" in reference " + std::to_string(r));
633 if (curinput.ref->is_sparse()) {
634 auto negative_ranked = sanisizer::create<std::vector<std::vector<RankedVector<Index_, Index_> > > >(nlabels);
635 auto positive_ranked = sanisizer::create<std::vector<std::vector<RankedVector<Index_, Index_> > > >(nlabels);
636 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
637 const auto num_samples = samples_per_label[l];
638 sanisizer::resize(negative_ranked[l], num_samples);
639 sanisizer::resize(positive_ranked[l], num_samples);
642 if (curinput.intersection) {
643 train_integrated_per_reference_intersect<true>(curinput, remap_test_to_universe, test_nrow, options, positions, negative_ranked, positive_ranked);
645 train_integrated_per_reference_simple<true, Value_>(curinput, universe, remap_test_to_universe, options, positions, negative_ranked, positive_ranked);
648 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
649 auto& curlabout = (*(currefout.sparse))[l];
650 const auto num_samples = samples_per_label[l];
651 curlabout.num_samples = num_samples;
653 I<
decltype(curlabout.negative_ranked.size())> num_neg = 0;
654 for (
const auto& x : negative_ranked[l]) {
655 num_neg = sanisizer::sum<I<
decltype(num_neg)> >(num_neg, x.size());
658 I<
decltype(curlabout.positive_ranked.size())> num_pos = 0;
659 for (
const auto& x : positive_ranked[l]) {
660 num_pos = sanisizer::sum<I<
decltype(num_pos)> >(num_pos, x.size());
663 curlabout.negative_ranked.reserve(num_neg);
664 curlabout.negative_indptrs.reserve(sanisizer::sum<I<
decltype(curlabout.negative_indptrs.size())> >(num_samples, 1));
665 curlabout.negative_indptrs.push_back(0);
666 for (
const auto& x : negative_ranked[l]) {
667 curlabout.negative_ranked.insert(curlabout.negative_ranked.end(), x.begin(), x.end());
668 curlabout.negative_indptrs.push_back(curlabout.negative_ranked.size());
671 curlabout.positive_ranked.reserve(num_pos);
672 curlabout.positive_indptrs.reserve(sanisizer::sum<I<
decltype(curlabout.positive_indptrs.size())> >(num_samples, 1));
673 curlabout.positive_indptrs.push_back(0);
674 for (
const auto& x : positive_ranked[l]) {
675 curlabout.positive_ranked.insert(curlabout.positive_ranked.end(), x.begin(), x.end());
676 curlabout.positive_indptrs.push_back(curlabout.positive_ranked.size());
681 auto out_ranked = sanisizer::create<std::vector<std::vector<RankedVector<Index_, Index_> > > >(nlabels);
682 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
683 const auto num_samples = samples_per_label[l];
684 sanisizer::resize(out_ranked[l], num_samples);
687 if (curinput.intersection) {
688 train_integrated_per_reference_intersect<false>(curinput, remap_test_to_universe, test_nrow, options, positions, out_ranked,
true);
690 train_integrated_per_reference_simple<false, Value_>(curinput, universe, remap_test_to_universe, options, positions, out_ranked,
true);
693 for (I<
decltype(nlabels)> l = 0; l < nlabels; ++l) {
694 auto& curlabout = (*(currefout.dense))[l];
695 curlabout.num_samples = samples_per_label[l];
696 curlabout.all_ranked.reserve(sanisizer::product<I<
decltype(curlabout.all_ranked.size())> >(universe.size(), curlabout.num_samples));
697 for (
const auto& x : out_ranked[l]) {
698 curlabout.all_ranked.insert(curlabout.all_ranked.end(), x.begin(), x.end());