<commit_before>/*
 * Copyright (c) 2019 <NAME>
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <cereal/archives/portable_binary.hpp>
#include <cstdlib>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <range/v3/view/sliding.hpp>
#include <unistd.h>
#include <vcf2multialign/preprocess/variant_graph.hh>
#include <vcf2multialign/utility/read_single_fasta_seq.hh>
#include "cmdline.h"


namespace lb	= libbio;
namespace v2m	= vcf2multialign;


namespace {
	void output_for_gv(
		char const *reference_path,
		char const *input_graph_path,
		char const *output_graph_path,
		char const *reference_seq_name,
		bool const should_overwrite_files,
		bool const output_ref_labels
	)
	{
		v2m::vector_type reference;
		v2m::variant_graph graph;
		lb::file_ostream output_graph_stream;

		{
			lb::file_istream input_graph_stream;
			
			// Open the files.
			{
				auto const mode(lb::make_writing_open_mode({
					lb::writing_open_mode::CREATE,
					(should_overwrite_files ? lb::writing_open_mode::OVERWRITE : lb::writing_open_mode::NONE)
				}));
				lb::open_file_for_writing(output_graph_path, output_graph_stream, mode);
			}
			
			lb::open_file_for_reading(input_graph_path, input_graph_stream);
			
			lb::mmap_handle <char> ref_handle;
			ref_handle.open(reference_path);
			
			// Read the input FASTA.
			v2m::read_single_fasta_seq(ref_handle, reference, reference_seq_name);
			
			// Read the intermediate graph.
			cereal::PortableBinaryInputArchive iarchive(input_graph_stream);
			iarchive(graph);
		}
		
		// Output.
		auto const &ref_positions(graph.ref_positions());
		auto const &aligned_ref_positions(graph.aligned_ref_positions());
		auto const &subgraph_start_positions(graph.subgraph_start_positions());
		auto const &alt_edge_count_csum(graph.alt_edge_count_csum());
		auto const &alt_edge_targets(graph.alt_edge_targets());
		auto const &alt_edge_labels(graph.alt_edge_labels());
		output_graph_stream << "digraph variants {\n";
		output_graph_stream << "\trankdir = LR;\n";
		output_graph_stream << "\trank = same;\n";
		
		// Labels if needed, otherwise use node ID as the label.
		if (output_ref_labels)
		{
			// Since background colours are needed at subgraph start positions, handle them, too.
			auto sg_it(subgraph_start_positions.begin());
			auto const sg_end(subgraph_start_positions.end());
			std::size_t next_subgraph_start_idx(sg_it == sg_end ? SIZE_MAX : *sg_it++);
			auto const rsv(ranges::view::zip(ranges::view::ints(0), ref_positions | ranges::view::drop(1), aligned_ref_positions | ranges::view::drop(1)));
			for (auto const &[i, ref_pos, aligned_ref_pos] : rsv)
			{
				if (i == next_subgraph_start_idx)
				{
					next_subgraph_start_idx = (sg_it == sg_end ? SIZE_MAX : *sg_it++);
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << ", style = filled, fillcolor = grey95];\n";
				}
				else
				{
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << "];\n";
				}
			}
		}
		else
		{
			// Only subgraph start positions.
			for (auto const idx : subgraph_start_positions)
			{
				auto const aligned_ref_pos(aligned_ref_positions[1 + idx]);
				output_graph_stream << '\t' << aligned_ref_pos << " [style = filled, fillcolor = grey95];\n";
			}
		}
		output_graph_stream << '\n';

		// REF edges.
		{
			auto const rsv(ranges::view::zip(
				ref_positions | ranges::view::drop(1) | ranges::view::sliding(2),
				aligned_ref_positions | ranges::view::drop(1) | ranges::view::sliding(2)
			));
			for (auto const &[ref_pair, aligned_ref_pair] : rsv)
			{
				auto const aligned_lhs(aligned_ref_pair[0]);
				auto const aligned_rhs(aligned_ref_pair[1]);
				auto const ref_lhs(ref_pair[0]);
				auto const ref_rhs(ref_pair[1]);
				std::string_view const ref_sub(reference.data() + ref_lhs, ref_rhs - ref_lhs);
				
				output_graph_stream << '\t' << aligned_lhs << " -> " << aligned_rhs << " [label = \"";<commit_msg>Use ranges::view::tail instead of drop(1)<commit_after>/*
 * Copyright (c) 2019 <NAME>
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <cereal/archives/portable_binary.hpp>
#include <cstdlib>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <range/v3/view/sliding.hpp>
#include <unistd.h>
#include <vcf2multialign/preprocess/variant_graph.hh>
#include <vcf2multialign/utility/read_single_fasta_seq.hh>
#include "cmdline.h"


namespace lb	= libbio;
namespace v2m	= vcf2multialign;


namespace {
	void output_for_gv(
		char const *reference_path,
		char const *input_graph_path,
		char const *output_graph_path,
		char const *reference_seq_name,
		bool const should_overwrite_files,
		bool const output_ref_labels
	)
	{
		v2m::vector_type reference;
		v2m::variant_graph graph;
		lb::file_ostream output_graph_stream;

		{
			lb::file_istream input_graph_stream;
			
			// Open the files.
			{
				auto const mode(lb::make_writing_open_mode({
					lb::writing_open_mode::CREATE,
					(should_overwrite_files ? lb::writing_open_mode::OVERWRITE : lb::writing_open_mode::NONE)
				}));
				lb::open_file_for_writing(output_graph_path, output_graph_stream, mode);
			}
			
			lb::open_file_for_reading(input_graph_path, input_graph_stream);
			
			lb::mmap_handle <char> ref_handle;
			ref_handle.open(reference_path);
			
			// Read the input FASTA.
			v2m::read_single_fasta_seq(ref_handle, reference, reference_seq_name);
			
			// Read the intermediate graph.
			cereal::PortableBinaryInputArchive iarchive(input_graph_stream);
			iarchive(graph);
		}
		
		// Output.
		auto const &ref_positions(graph.ref_positions());
		auto const &aligned_ref_positions(graph.aligned_ref_positions());
		auto const &subgraph_start_positions(graph.subgraph_start_positions());
		auto const &alt_edge_count_csum(graph.alt_edge_count_csum());
		auto const &alt_edge_targets(graph.alt_edge_targets());
		auto const &alt_edge_labels(graph.alt_edge_labels());
		output_graph_stream << "digraph variants {\n";
		output_graph_stream << "\trankdir = LR;\n";
		output_graph_stream << "\trank = same;\n";
		
		// Labels if needed, otherwise use node ID as the label.
		if (output_ref_labels)
		{
			// Since background colours are needed at subgraph start positions, handle them, too.
			auto sg_it(subgraph_start_positions.begin());
			auto const sg_end(subgraph_start_positions.end());
			std::size_t next_subgraph_start_idx(sg_it == sg_end ? SIZE_MAX : *sg_it++);
			auto const rsv(ranges::view::zip(ranges::view::ints(0), ref_positions | ranges::view::tail, aligned_ref_positions | ranges::view::tail));
			for (auto const &[i, ref_pos, aligned_ref_pos] : rsv)
			{
				if (i == next_subgraph_start_idx)
				{
					next_subgraph_start_idx = (sg_it == sg_end ? SIZE_MAX : *sg_it++);
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << ", style = filled, fillcolor = grey95];\n";
				}
				else
				{
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << "];\n";
				}
			}
		}
		else
		{
			// Only subgraph start positions.
			for (auto const idx : subgraph_start_positions)
			{
				auto const aligned_ref_pos(aligned_ref_positions[1 + idx]);
				output_graph_stream << '\t' << aligned_ref_pos << " [style = filled, fillcolor = grey95];\n";
			}
		}
		output_graph_stream << '\n';

		// REF edges.
		{
			auto const rsv(ranges::view::zip(
				ref_positions | ranges::view::tail | ranges::view::sliding(2),
				aligned_ref_positions | ranges::view::tail | ranges::view::sliding(2)
			));
			for (auto const &[ref_pair, aligned_ref_pair] : rsv)
			{
				auto const aligned_lhs(aligned_ref_pair[0]);
				auto const aligned_rhs(aligned_ref_pair[1]);
				auto const ref_lhs(ref_pair[0]);
				auto const ref_rhs(ref_pair[1]);
				std::string_view const ref_sub(reference.data() + ref_lhs, ref_rhs - ref_lhs);
				
				output_graph_stream << '\t' << aligned_lhs << " -> " << aligned_rhs << " [label = \"";
{'fraction_non_alphanumeric': 0.133, 'fraction_numerical': 0.006625, 'mean_word_length': 4.461433447098976, 'pattern_counts': {'":': 0, '<': 113, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6584399', 'n_tokens_mistral': 3246, 'n_tokens_neox': 2790, 'n_words': 540}