diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 47c4cd5211..2f37f76d23 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -14,6 +14,7 @@ add_subdirectory(pipeline) add_subdirectory(sequence) add_subdirectory(assembly_graph) add_subdirectory(alignment) +add_subdirectory(auxiliary_graphs) add_subdirectory(modules/path_extend) add_subdirectory(modules) add_subdirectory(paired_info) @@ -29,7 +30,7 @@ add_library(common_modules adt/concurrent_dsu.cpp) target_link_libraries(common_modules library - assembly_graph input pipeline sequence - coverage_model paired_info path_extend - stages mph_index modules + assembly_graph auxiliary_graphs input + pipeline sequence coverage_model + paired_info path_extend stages mph_index modules utils configs alignment) diff --git a/src/common/auxiliary_graphs/CMakeLists.txt b/src/common/auxiliary_graphs/CMakeLists.txt new file mode 100644 index 0000000000..f5c0545501 --- /dev/null +++ b/src/common/auxiliary_graphs/CMakeLists.txt @@ -0,0 +1,19 @@ +############################################################################ +# Copyright (c) 2023-2025 SPAdes team +# Copyright (c) 2019-2022 Saint Petersburg State University +# All Rights Reserved +# See file LICENSE for details. +############################################################################ + +project(auxiliary_graphs CXX) + +add_library(auxiliary_graphs STATIC + contracted_graph/contracted_graph.cpp + contracted_graph/contracted_graph_builder.cpp + contracted_graph/contracted_graph_helper.cpp + contracted_graph/graph_condensation.cpp + contracted_graph/contracted_statistics.cpp + scaffold_graph/scaffold_vertex.cpp +) + +target_link_libraries(auxiliary_graphs assembly_graph) diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_graph.cpp b/src/common/auxiliary_graphs/contracted_graph/contracted_graph.cpp new file mode 100644 index 0000000000..ab6aa3a526 --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_graph.cpp @@ -0,0 +1,115 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "contracted_graph.hpp" + +namespace contracted_graph { + +void AdjacencyMap::RemovePair(VertexId vertex, const AdjacencyMap::ScaffoldVertex &edge) { + data_.at(vertex).erase(edge); + if (data_.at(vertex).empty()) { + data_.erase(vertex); + } +} +bool AdjacencyMap::Contains(VertexId vertex, const AdjacencyMap::ScaffoldVertex &edge) { + auto vertex_entry = data_.find(vertex); + if (vertex_entry == data_.end()) { + return false; + } + return vertex_entry->second.find(edge) != vertex_entry->second.end(); +} + +void ContractedGraph::InsertVertex(const ContractedGraph::VertexId vertex) { + if (vertices_.insert(vertex).second) { + AdjacencyMap empty; + incoming_[vertex] = empty; + outcoming_[vertex] = empty; + } +} +void ContractedGraph::InsertEdge(const ContractedGraph::VertexId head, const ContractedGraph::VertexId tail, + const ContractedGraph::ScaffoldVertex &edge) { + VERIFY_DEV(vertices_.find(head) != vertices_.end()); + VERIFY_DEV(vertices_.find(tail) != vertices_.end()); + outcoming_[head].InsertPair(tail, edge); + incoming_[tail].InsertPair(head, edge); +} + +size_t ContractedGraph::GetOutDegree(const ContractedGraph::VertexId vertex) const { + size_t result = 0; + for (const auto &entry: outcoming_.at(vertex)) { + result += entry.second.size(); + } + return result; +} +size_t ContractedGraph::GetInDegree(const ContractedGraph::VertexId vertex) const { + size_t result = 0; + for (const auto &entry: incoming_.at(vertex)) { + result += entry.second.size(); + } + return result; +} + +size_t ContractedGraph::CountEdges() const { + size_t result = 0; + for (const auto &vertex: vertices()) { + result += GetOutDegree(vertex); + } + return result; +} +void ContractedGraph::RemoveEdge(VertexId head, VertexId tail, const ContractedGraph::ScaffoldVertex &edge) { + VERIFY_DEV(ContainsVertex(head)); + VERIFY_DEV(ContainsVertex(tail)); + auto &head_outcoming = outcoming_.at(head); + auto &tail_incoming = incoming_.at(tail); + if (not head_outcoming.Contains(tail, edge)) { + return; + } + VERIFY_DEV(tail_incoming.Contains(head, edge)); + head_outcoming.RemovePair(tail, edge); + tail_incoming.RemovePair(head, edge); +} + +ContractedGraph::ContractedGraph(const Graph &assembly_graph) : assembly_graph_(assembly_graph) {} + +ContractedGraph::const_edge_iterator ContractedGraph::in_edge_begin(VertexId vertex) const { + auto entry_begin = in_entry_begin(vertex); + if (not incoming_.at(vertex).empty()) { + return ContractedGraph::const_edge_iterator(entry_begin, entry_begin->second.begin(), in_entry_end(vertex)); + } + return const_edge_iterator(entry_begin, empty_.end(), in_entry_end(vertex)); +} +ContractedGraph::const_edge_iterator ContractedGraph::in_edge_end(VertexId vertex) const { + auto entry_end = in_entry_end(vertex); + auto entry_last = std::prev(entry_end); + if (not incoming_.at(vertex).empty()) { + return const_edge_iterator(entry_end, entry_last->second.end(), entry_end); + } + return const_edge_iterator(entry_end, empty_.end(), entry_end); +} + +ContractedGraph::const_edge_iterator ContractedGraph::out_edge_begin(VertexId vertex) const { + auto entry_begin = out_entry_begin(vertex); + if (not outcoming_.at(vertex).empty()) { + return ContractedGraph::const_edge_iterator(entry_begin, entry_begin->second.begin(), out_entry_end(vertex)); + } + return const_edge_iterator(entry_begin, empty_.end(), out_entry_end(vertex)); +} +ContractedGraph::const_edge_iterator ContractedGraph::out_edge_end(VertexId vertex) const { + auto entry_end = out_entry_end(vertex); + auto entry_last = std::prev(entry_end); + if (not outcoming_.at(vertex).empty()) { + return const_edge_iterator(entry_end, entry_last->second.end(), entry_end); + } + return const_edge_iterator(entry_end, empty_.end(), entry_end); +} + +Sequence ContractedGraph::EdgeNucls(ContractedGraph::EdgeId edge) const { + VERIFY(edge.GetType() == scaffold_graph::ScaffoldVertexT::Edge); + return assembly_graph_.EdgeNucls(edge.GetFirstEdge()); +} + +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_graph.hpp b/src/common/auxiliary_graphs/contracted_graph/contracted_graph.hpp new file mode 100644 index 0000000000..fcf4cf75ce --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_graph.hpp @@ -0,0 +1,160 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "auxiliary_graphs/scaffold_graph/scaffold_vertex.hpp" +#include "adt/iterator_range.hpp" +#include "assembly_graph/core/graph.hpp" + +namespace contracted_graph { +class AdjacencyMap { + public: + typedef debruijn_graph::VertexId VertexId; + typedef debruijn_graph::EdgeId EdgeId; + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + typedef std::map> ContractedMap; + typedef ContractedMap::const_iterator const_iterator; + typedef ContractedMap::value_type value_type; + typedef ContractedMap::mapped_type mapped_type; + + AdjacencyMap() = default; + AdjacencyMap(VertexId vertex, const ScaffoldVertex &edge) : data_({{vertex, {edge}}}) {} + void InsertPair(VertexId vertex, const ScaffoldVertex &edge) { data_[vertex].insert(edge); } + void RemovePair(VertexId vertex, const ScaffoldVertex &edge); + bool Contains(VertexId vertex, const ScaffoldVertex &edge); + bool empty() const { return data_.empty(); } + size_t size() const { return data_.size(); } + + const_iterator begin() const { return data_.begin(); } + const_iterator end() const { return data_.end(); } + + private: + ContractedMap data_; +}; + +class ContractedGraph { + public: + typedef debruijn_graph::VertexId VertexId; + typedef debruijn_graph::Graph Graph; + typedef std::unordered_set VertexContainer; + typedef std::unordered_map EdgeContainer; + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + typedef AdjacencyMap::const_iterator const_entry_iterator; + typedef VertexContainer::const_iterator const_vertex_iterator; + typedef AdjacencyMap::mapped_type::const_iterator internal_edge_iterator; + typedef ScaffoldVertex EdgeId; + + class const_edge_iterator : public boost::iterator_facade { + public: + explicit const_edge_iterator(const_entry_iterator entry_it, + internal_edge_iterator edge_it, + const_entry_iterator entry_end): + entry_it_(entry_it), + edge_it_(edge_it), + entry_end_(entry_end) {} + + private: + friend class boost::iterator_core_access; + + bool equal(const const_edge_iterator &other) const { + return entry_it_ == other.entry_it_ and edge_it_ == other.edge_it_ and entry_end_ == other.entry_end_; + } + + const ScaffoldVertex &dereference() const { + return *edge_it_; + } + + void increment() { + ++edge_it_; + if (edge_it_ == entry_it_->second.end()) { + ++entry_it_; + if (entry_it_ != entry_end_) { + edge_it_ = entry_it_->second.begin(); + } + } + } + + const_entry_iterator entry_it_; + internal_edge_iterator edge_it_; + const_entry_iterator entry_end_; + }; + + explicit ContractedGraph(const Graph &assembly_graph); + virtual ~ContractedGraph() = default; + ContractedGraph(ContractedGraph &&other) = default; + + void InsertVertex(VertexId vertex); + void InsertEdge(VertexId head, VertexId tail, const ScaffoldVertex &edge); + void RemoveEdge(VertexId head, VertexId tail, const ScaffoldVertex &edge); + size_t GetOutDegree(VertexId vertex) const; + size_t GetInDegree(VertexId vertex) const; + size_t GetCapacity(VertexId vertex) const { return capacity_.at(vertex); } + void InsertCapacity(VertexId vertex, size_t capacity) { capacity_[vertex] = capacity; } + bool ContainsVertex(VertexId vertex) const { return vertices_.find(vertex) != vertices_.end(); } + + const_entry_iterator in_entry_begin(VertexId vertex) const { return incoming_.at(vertex).begin(); } + const_entry_iterator in_entry_end(VertexId vertex) const { return incoming_.at(vertex).end(); } + adt::iterator_range IncomingEntries(VertexId vertex) const { + return adt::make_range(in_entry_begin(vertex), + in_entry_end(vertex)); + } + const_entry_iterator out_entry_begin(VertexId vertex) const { return outcoming_.at(vertex).begin(); } + const_entry_iterator out_entry_end(VertexId vertex) const { return outcoming_.at(vertex).end(); } + adt::iterator_range OutcomingEntries(VertexId vertex) const { + return adt::make_range(out_entry_begin(vertex), out_entry_end(vertex)); + } + + const_edge_iterator in_edge_begin(VertexId vertex) const; + const_edge_iterator in_edge_end(VertexId vertex) const; + adt::iterator_range IncomingEdges(VertexId vertex) const { + return adt::make_range(in_edge_begin(vertex), in_edge_end(vertex)); + } + size_t IncomingEdgeCount(VertexId vertex) const { return incoming_.at(vertex).size(); } + const_edge_iterator out_edge_begin(VertexId vertex) const; + const_edge_iterator out_edge_end(VertexId vertex) const; + adt::iterator_range OutgoingEdges(VertexId vertex) const { + return adt::make_range(out_edge_begin(vertex), + out_edge_end(vertex)); + } + size_t OutgoingEdgeCount(VertexId vertex) const { return outcoming_.at(vertex).size(); } + + const_vertex_iterator begin() const { return vertices_.begin(); } + const_vertex_iterator end() const { return vertices_.end(); } + adt::iterator_range vertices() const { return adt::make_range(begin(), end()); } + size_t size() const { return vertices_.size(); } + size_t CountEdges() const; + + //fixme also iterates over short edges + auto canonical_edges () const { return assembly_graph_.canonical_edges(); } + + const Graph &GetAssemblyGraph() const { return assembly_graph_; } +// std::string EdgeNucls(EdgeId edge) const; +// std::string VertexNucls(VertexId vertex) const; + Sequence EdgeNucls(EdgeId edge) const; + double coverage(EdgeId edge) const { return edge.GetCoverageFromGraph(assembly_graph_); } + size_t length(EdgeId edge) const { return edge.GetLengthFromGraph(assembly_graph_); } + size_t int_id(EdgeId edge) const { return edge.int_id(); } + + ScaffoldVertex conjugate(ScaffoldVertex edge) const { return edge.GetConjugateFromGraph(assembly_graph_); } + VertexId conjugate(VertexId vertex) const { return assembly_graph_.conjugate(vertex); } + + protected: + EdgeContainer outcoming_; + EdgeContainer incoming_; + VertexContainer vertices_; + std::unordered_map capacity_; + + //for edge iterator + std::unordered_set empty_; + + //for compatibility with visualizers and stuff + const Graph &assembly_graph_; + }; +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_graph_builder.cpp b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_builder.cpp new file mode 100644 index 0000000000..2a63c4916b --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_builder.cpp @@ -0,0 +1,119 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "contracted_graph_builder.hpp" + +namespace contracted_graph { + +void PartsBasedContractedFactory::ConstructFromParts(PartsBasedContractedFactory::ContractedGraphParts &&parts) { + DEBUG("Constructing from parts"); + const auto &vertex_to_root = parts.vertex_to_root_; + const auto &long_edges = parts.long_edges_; + const auto &vertex_to_capacity = parts.vertex_to_capacity_; + DEBUG("Vertex to root size: " << vertex_to_root.size()); + DEBUG("Vertex to capacity: " << vertex_to_capacity.size()); + for (const auto &entry: vertex_to_root) { + this->graph_ptr_->InsertVertex(entry.second); + } + for (const auto &edge: long_edges) { + DEBUG("Processing edge " << edge.int_id()); + DEBUG(edge.GetStartGraphVertex(g_) << " -> " << edge.GetEndGraphVertex(g_)); + VertexId start_root = vertex_to_root.at(edge.GetStartGraphVertex(g_)); + VertexId end_root = vertex_to_root.at(edge.GetEndGraphVertex(g_)); + DEBUG("Inserting vertices and edges"); + this->graph_ptr_->InsertEdge(start_root, end_root, edge); + + } + for (const auto &entry: parts.vertex_to_capacity_) { + this->graph_ptr_->InsertCapacity(entry.first, entry.second); + } +} +void PartsBasedContractedFactory::Construct() { + ConstructFromParts(ConstructParts()); +} + +PartsBasedContractedFactory::ContractedGraphParts DBGContractedGraphFactory::ConstructParts() const { + omnigraph::IterationHelper edge_iteration_helper(g_); + omnigraph::IterationHelper vertex_iteration_helper(g_); + DEBUG("Preparing parts"); + ContractedGraphParts graph_parts; + + contracted_dsu_t graph_dsu(g_.size()); + std::unordered_map vertex_to_id; + std::unordered_map id_to_vertex; + + size_t counter = 0; + for (auto vertex : vertex_iteration_helper) { + vertex_to_id.insert({vertex, counter}); + id_to_vertex.insert({counter, vertex}); + graph_parts.vertex_to_capacity_.insert({vertex, 0}); + ++counter; + } + + DEBUG("Filling parts"); + for (const auto &edge: edge_iteration_helper) { + ProcessEdge(graph_dsu, graph_parts, vertex_to_id, id_to_vertex, edge); + } + DEBUG(graph_dsu.num_sets() << " sets in dsu"); + for (const auto &vertex: vertex_iteration_helper) { + VertexId root_vertex = id_to_vertex.at(graph_dsu.find_set(vertex_to_id.at(vertex))); + DEBUG("Inserting vertex and root: " << vertex.int_id() << ", " << root_vertex.int_id()); + graph_parts.vertex_to_root_.insert({vertex, root_vertex}); + } + return graph_parts; +} +void DBGContractedGraphFactory::ProcessEdge(DBGContractedGraphFactory::contracted_dsu_t &graph_dsu, + PartsBasedContractedFactory::ContractedGraphParts &parts, + const std::unordered_map &vertex_to_id, + const std::unordered_map &id_to_vertex, + EdgeId edge) const { + VertexId start = g_.EdgeStart(edge); + VertexId end = g_.EdgeEnd(edge); + size_t start_id = vertex_to_id.at(start); + size_t end_id = vertex_to_id.at(end); + size_t start_root = graph_dsu.find_set(start_id); + size_t end_root = graph_dsu.find_set(end_id); + VertexId start_root_vertex = id_to_vertex.at(start_root); + VertexId end_root_vertex = id_to_vertex.at(start_root); + if (not edge_predicate_(edge)) { + if (start_root == end_root) { + parts.vertex_to_capacity_.at(start_root_vertex) += g_.length(edge); + } else { + size_t start_capacity = parts.vertex_to_capacity_[start_root_vertex]; + size_t end_capacity = parts.vertex_to_capacity_[end_root_vertex]; + graph_dsu.unite(start_root, end_root); + VertexId new_vertex = id_to_vertex.at(graph_dsu.find_set(start_root)); + parts.vertex_to_capacity_.at(new_vertex) = start_capacity + end_capacity + g_.length(edge); + } + } else { + parts.long_edge_ends_.insert(start_root_vertex); + parts.long_edge_ends_.insert(end_root_vertex); + parts.long_edges_.emplace_back(edge); + } +} +void SubgraphContractedGraphFactory::Construct() { + ExtractSubgraphFromContractedGraph(other_, vertices_); +} +void SubgraphContractedGraphFactory::ExtractSubgraphFromContractedGraph(const ContractedGraph &other, + const std::unordered_set &vertices) { + for (const auto &vertex: vertices) { + VERIFY(other.ContainsVertex(vertex)); + graph_ptr_->InsertVertex(vertex); + } + + for (const auto &vertex: vertices) { + for (const auto &adj_list: other.OutcomingEntries(vertex)) { + VertexId next = adj_list.first; + if (vertices.find(next) != vertices.end()) { + for (const auto &edge: adj_list.second) { + graph_ptr_->InsertEdge(vertex, next, edge); + } + } + } + } +} +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_graph_builder.hpp b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_builder.hpp new file mode 100644 index 0000000000..2e9bdd67f2 --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_builder.hpp @@ -0,0 +1,101 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "contracted_graph.hpp" + +#include "adt/concurrent_dsu.hpp" + +#include + +namespace contracted_graph { + +class ContractedGraphFactory { + public: + using Graph = debruijn_graph::Graph; + + ContractedGraphFactory(const Graph &g) : + g_(g), graph_ptr_(std::make_shared(g)) {} + virtual ~ContractedGraphFactory() = default; + virtual void Construct() = 0; + std::shared_ptr GetGraph() { + return graph_ptr_; + } + protected: + const Graph &g_; + std::shared_ptr graph_ptr_; +}; + +class PartsBasedContractedFactory : public ContractedGraphFactory { + public: + using VertexId = debruijn_graph::VertexId; + using ContractedGraphFactory::Graph; + + PartsBasedContractedFactory(const Graph &g): ContractedGraphFactory(g) {} + virtual ~PartsBasedContractedFactory() {} + + void Construct() override; + protected: + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + + struct ContractedGraphParts { + std::vector long_edges_; + std::unordered_set long_edge_ends_; + std::unordered_map vertex_to_capacity_; + std::unordered_map vertex_to_root_; + }; + + virtual ContractedGraphParts ConstructParts() const = 0; + void ConstructFromParts(ContractedGraphParts &&parts); + + using ContractedGraphFactory::graph_ptr_; + using ContractedGraphFactory::g_; + DECL_LOGGER("DSUBasedContractedGraphFactory"); +}; + +class DBGContractedGraphFactory : public PartsBasedContractedFactory { + public: + using contracted_dsu_t = dsu::ConcurrentDSU; + using EdgeId = debruijn_graph::EdgeId; + using PartsBasedContractedFactory::Graph; + + DBGContractedGraphFactory(const Graph &g, const std::function &edge_predicate) : + PartsBasedContractedFactory(g), edge_predicate_(edge_predicate) {} + + private: + ContractedGraphParts ConstructParts() const override; + + void ProcessEdge(contracted_dsu_t &graph_dsu, ContractedGraphParts &parts, + const std::unordered_map &vertex_to_id, + const std::unordered_map &id_to_vertex, EdgeId edge) const; + + using PartsBasedContractedFactory::g_; + using PartsBasedContractedFactory::graph_ptr_; + using PartsBasedContractedFactory::ContractedGraphParts; + const std::function edge_predicate_; + + DECL_LOGGER("DBGContractedGraphFactory"); +}; + +class SubgraphContractedGraphFactory: public ContractedGraphFactory { + public: + using VertexId = debruijn_graph::VertexId; + + SubgraphContractedGraphFactory(const ContractedGraph &other, const std::unordered_set &vertices) : + ContractedGraphFactory(other.GetAssemblyGraph()), other_(other), vertices_(vertices) {} + + void Construct() override; + + private: + void ExtractSubgraphFromContractedGraph(const ContractedGraph &other, const std::unordered_set &vertices); + + const ContractedGraph &other_; + const std::unordered_set &vertices_; +}; + +} //contracted_graph diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_graph_helper.cpp b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_helper.cpp new file mode 100644 index 0000000000..52995c7dd9 --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_helper.cpp @@ -0,0 +1,28 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "contracted_graph_helper.hpp" + +namespace contracted_graph { + +//std::shared_ptr ContractedGraphFactoryHelper::ConstructFromUniqueStorage( +// const UniqueStorage &unique_storage) const { +// std::function edge_predicate = [&unique_storage](debruijn_graph::EdgeId edge) { +// return unique_storage.IsUnique(edge); +// }; +// DBGContractedGraphFactory factory(g_, edge_predicate); +// factory.Construct(); +// return factory.GetGraph(); +//} +std::shared_ptr ContractedGraphFactoryHelper::ExtractContractedSubgraph( + const ContractedGraph &other, + const std::unordered_set &vertices) const { + SubgraphContractedGraphFactory factory(other, vertices); + factory.Construct(); + return factory.GetGraph(); +} +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_graph_helper.hpp b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_helper.hpp new file mode 100644 index 0000000000..cc03028ddf --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_graph_helper.hpp @@ -0,0 +1,27 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "contracted_graph_builder.hpp" + +namespace contracted_graph { + +class ContractedGraphFactoryHelper { + public: + typedef debruijn_graph::VertexId VertexId; + typedef debruijn_graph::Graph Graph; + + explicit ContractedGraphFactoryHelper(const debruijn_graph::Graph &g) : g_(g) {} + + std::shared_ptr ExtractContractedSubgraph(const ContractedGraph &other, + const std::unordered_set &vertices) const; + + private: + const Graph& g_; +}; +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_statistics.cpp b/src/common/auxiliary_graphs/contracted_graph/contracted_statistics.cpp new file mode 100644 index 0000000000..ddd044fce3 --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_statistics.cpp @@ -0,0 +1,68 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "contracted_statistics.hpp" + +#include "contracted_graph_builder.hpp" + +namespace contracted_graph { +size_t ContractedStatisticsExtractor::CountLoops(const ContractedGraph &graph) const { + size_t result = 0; + for (const auto &vertex: graph) { + for (const auto &entry: graph.OutcomingEntries(vertex)) { + auto next_vertex = entry.first; + if (vertex == next_vertex) { + ++result; + } + } + } + return result; +} +double ContractedStatisticsExtractor::GetMeanWeight(const ContractedGraph &graph) const { + size_t total_capacity = 0; + size_t non_isolated = 0; + for (const auto &vertex: graph) { + if (graph.GetOutDegree(vertex) > 0 or graph.GetInDegree(vertex) > 0) { + total_capacity += graph.GetCapacity(vertex); + ++non_isolated; + } + } + INFO("Total capacity: " << total_capacity << ", Non isolated: " << non_isolated); + return static_cast(total_capacity) / static_cast(non_isolated); +} +void ContractedStatisticsExtractor::GetMeanWeights(std::vector thresholds, + const std::string &output_path) const { + std::map threshold_to_mean_weight; + for (const size_t threshold: thresholds) { + INFO("Constructing graph for " << threshold); + auto length_predicate = [this, threshold](debruijn_graph::EdgeId edge) { + return assembly_graph_.length(edge) >= threshold; + }; + DBGContractedGraphFactory factory(assembly_graph_, length_predicate); + factory.Construct(); + INFO("Constructed graph"); + auto graph = factory.GetGraph(); + double mean_weight = GetMeanWeight(*graph); + INFO("Mean weight " << mean_weight); + threshold_to_mean_weight.insert({threshold, mean_weight}); + } + std::ofstream fout(output_path); + for (const auto &entry: threshold_to_mean_weight) { + fout << entry.first << " " << entry.second << "\n"; + } +} + +size_t ContractedStatisticsExtractor::CountNonIsolated(const ContractedGraph &graph) const { + size_t result = 0; + for (const auto &vertex: graph) { + if (graph.GetInDegree(vertex) > 0 or graph.GetOutDegree(vertex) > 0) { + ++result; + } + } + return result; +} +} diff --git a/src/common/auxiliary_graphs/contracted_graph/contracted_statistics.hpp b/src/common/auxiliary_graphs/contracted_graph/contracted_statistics.hpp new file mode 100644 index 0000000000..83942b2756 --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/contracted_statistics.hpp @@ -0,0 +1,28 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "contracted_graph.hpp" + +namespace contracted_graph { +class ContractedStatisticsExtractor { + public: + using Graph = debruijn_graph::Graph; + + explicit ContractedStatisticsExtractor(const Graph &assembly_graph) : assembly_graph_(assembly_graph) {} + + size_t CountLoops(const ContractedGraph &graph) const; + size_t CountNonIsolated(const ContractedGraph &graph) const; + double GetMeanWeight(const ContractedGraph &graph) const; + + void GetMeanWeights(std::vector thresholds, const std::string &output_path) const; + + private: + const Graph &assembly_graph_; +}; +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/contracted_graph/graph_condensation.cpp b/src/common/auxiliary_graphs/contracted_graph/graph_condensation.cpp new file mode 100644 index 0000000000..a8e287c35a --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/graph_condensation.cpp @@ -0,0 +1,67 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "graph_condensation.hpp" + +namespace contracted_graph { + +std::vector UnbranchingPathExtractor::ExtractUnbranchingPaths( + const ContractedGraph &graph) const { + std::unordered_map edge_to_next; + std::unordered_set unbranching_vertices; + std::unordered_set starts; + for (const auto &vertex: graph) { + if (graph.GetOutDegree(vertex) == 1 and graph.GetInDegree(vertex) == 1) { + auto incoming_edge = *(graph.in_edge_begin(vertex)); + auto outcoming_edge = *(graph.out_edge_begin(vertex)); + if (incoming_edge != outcoming_edge) { + edge_to_next[incoming_edge] = outcoming_edge; + unbranching_vertices.insert(incoming_edge); + unbranching_vertices.insert(outcoming_edge); + starts.insert(incoming_edge); + starts.erase(outcoming_edge); + } + } + } + + std::vector result; + std::unordered_set visited; + size_t inserted = 0; + for (const auto &start: starts) { + SimplePath path; + path.push_back(start); + ++inserted; + visited.insert(start); + ScaffoldVertex curr_vertex = start; + for (auto it = edge_to_next.find(curr_vertex); it != edge_to_next.end(); it = edge_to_next.find(it->second)) { + curr_vertex = it->second; + path.push_back(curr_vertex); + visited.insert(curr_vertex); + ++inserted; + } + result.push_back(path); + } + INFO("Inserted " << inserted << " out of " << unbranching_vertices.size() << " unbranching vertices") + INFO(result.size() << " unbranching simple paths") + for (const auto &vertex: unbranching_vertices) { + if (visited.insert(vertex).second) { + DEBUG("Unvisited"); + SimplePath cycle; + cycle.push_back(vertex); + ScaffoldVertex curr_vertex = edge_to_next.at(vertex); + while (curr_vertex != vertex) { + visited.insert(curr_vertex); + cycle.push_back(curr_vertex); + } + result.push_back(cycle); + } + + } + INFO(result.size() << " total simple paths"); + return result; +} +} diff --git a/src/common/auxiliary_graphs/contracted_graph/graph_condensation.hpp b/src/common/auxiliary_graphs/contracted_graph/graph_condensation.hpp new file mode 100644 index 0000000000..ef16fc7cdb --- /dev/null +++ b/src/common/auxiliary_graphs/contracted_graph/graph_condensation.hpp @@ -0,0 +1,21 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "contracted_graph.hpp" + +namespace contracted_graph { + +class UnbranchingPathExtractor { + public: + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + typedef std::vector SimplePath; + std::vector ExtractUnbranchingPaths(const ContractedGraph &graph) const; +}; + +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex.cpp b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex.cpp new file mode 100644 index 0000000000..0d614f22d7 --- /dev/null +++ b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex.cpp @@ -0,0 +1,122 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "scaffold_vertex.hpp" + +#include "assembly_graph/paths/bidirectional_path_io/io_support.hpp" + +namespace scaffold_graph { + +std::shared_ptr EdgeIdVertex::GetConjugateFromGraph(const debruijn_graph::Graph &g) const { + return std::make_shared(g.conjugate(get())); +} + +path_extend::BidirectionalPath* EdgeIdVertex::ToPath(const debruijn_graph::Graph &g) const { + //fixme think of a better way + VERIFY(false); + path_extend::BidirectionalPath* result; +// path_extend::BidirectionalPath* result = new path_extend::BidirectionalPath (g); +// path_extend::Gap gap(0); +// result->PushBack(edge_, gap); + return result; +} + +std::optional EdgeIdVertex::GetLastEdgeWithPredicate( + const func::TypedPredicate &pred) const { + std::optional result; + if (pred(edge_)) { + result = edge_; + } + return result; +} +std::optional EdgeIdVertex::GetFirstEdgeWithPredicate( + const func::TypedPredicate &pred) const { + std::optional result; + if (pred(edge_)) { + result = edge_; + } + return result; +} +std::unordered_set EdgeIdVertex::GetAllEdges() const { + std::unordered_set result; + result.insert(edge_); + return result; +} +std::string EdgeIdVertex::GetSequence(const debruijn_graph::Graph &g) const { + return g.EdgeNucls(edge_).str(); +} + +std::shared_ptr PathVertex::GetConjugateFromGraph(const debruijn_graph::Graph &/*g*/) const { + return std::make_shared(get()->GetConjPath()); +} + +debruijn_graph::VertexId PathVertex::GetEndGraphVertex(const debruijn_graph::Graph &g) const { + VERIFY(path_->Size() > 0); + return g.EdgeEnd(path_->Back()); +} +debruijn_graph::VertexId PathVertex::GetStartGraphVertex(const debruijn_graph::Graph &g) const { + VERIFY(path_->Size() > 0); + return g.EdgeStart(path_->Front()); +} + +debruijn_graph::EdgeId PathVertex::GetLastEdge() const { + const size_t path_size = path_->Size(); + VERIFY(path_size > 0); + return path_->Back(); +} +debruijn_graph::EdgeId PathVertex::GetFirstEdge() const { + const size_t path_size = path_->Size(); + VERIFY(path_size > 0); + return path_->Front(); +} +std::optional PathVertex::GetLastEdgeWithPredicate( + const func::TypedPredicate &pred) const { + std::optional result; + for (int i = static_cast(path_->Size()) - 1; i >= 0; --i) { + EdgeId current = path_->At(i); + if (pred(current)) { + result = current; + return result; + } + } + return result; +} +std::optional PathVertex::GetFirstEdgeWithPredicate( + const func::TypedPredicate &pred) const { + std::optional result; + for (size_t i = 0; i < path_->Size(); ++i) { + EdgeId current = path_->At(i); + if (pred(current)) { + result = current; + return result; + } + } + return result; +} +std::unordered_set PathVertex::GetAllEdges() const { + std::unordered_set result; + for (const auto &edge: *path_) { + result.insert(edge); + } + return result; +} +std::string PathVertex::GetSequence(const debruijn_graph::Graph &g) const { + path_extend::ScaffoldSequenceMaker sequence_maker(g); + return sequence_maker.MakeSequence(*path_); +} + +ScaffoldVertex::ScaffoldVertex(std::shared_ptr vertex_ptr_) : vertex_ptr_(vertex_ptr_) {} + +ScaffoldVertex ScaffoldVertex::GetConjugateFromGraph(const debruijn_graph::Graph &g) const { + auto inner_vertex = vertex_ptr_->GetConjugateFromGraph(g); + ScaffoldVertex result(inner_vertex); + return result; +} + +ScaffoldVertex::ScaffoldVertex(EdgeId edge) : vertex_ptr_(std::make_shared(edge)) {} +ScaffoldVertex::ScaffoldVertex(path_extend::BidirectionalPath *path) : vertex_ptr_(std::make_shared(path)) {} +} diff --git a/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex.hpp b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex.hpp new file mode 100644 index 0000000000..9e04690e45 --- /dev/null +++ b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex.hpp @@ -0,0 +1,188 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "assembly_graph/paths/bidirectional_path.hpp" +#include "assembly_graph/core/graph.hpp" + +#include +#include + +namespace scaffold_graph { + +enum ScaffoldVertexT { Edge = 0, Path = 1 }; + +class InnerScaffoldVertex { + public: + using EdgeId = debruijn_graph::EdgeId; + + virtual ~InnerScaffoldVertex() = default; + + virtual size_t GetId() const = 0; + virtual ScaffoldVertexT GetType() const = 0; + virtual size_t GetLengthFromGraph(const debruijn_graph::Graph &g) const = 0; + virtual double GetCoverageFromGraph(const debruijn_graph::Graph &g) const = 0; + virtual std::shared_ptr GetConjugateFromGraph(const debruijn_graph::Graph &g) const = 0; + virtual debruijn_graph::VertexId GetEndGraphVertex(const debruijn_graph::Graph &g) const = 0; + virtual debruijn_graph::VertexId GetStartGraphVertex(const debruijn_graph::Graph &g) const = 0; + virtual std::optional GetLastEdgeWithPredicate(const func::TypedPredicate &pred) const = 0; + virtual std::optional GetFirstEdgeWithPredicate(const func::TypedPredicate &pred) const = 0; + virtual std::string GetSequence(const debruijn_graph::Graph &g) const = 0; + virtual size_t GetSize() const = 0; + + virtual debruijn_graph::EdgeId GetLastEdge() const = 0; + virtual EdgeId GetFirstEdge() const = 0; + virtual std::unordered_set GetAllEdges() const = 0; + + virtual path_extend::BidirectionalPath* ToPath(const debruijn_graph::Graph &g) const = 0; + virtual std::string str(const debruijn_graph::Graph& g) const = 0; +}; + +class EdgeIdVertex : public InnerScaffoldVertex { + private: + debruijn_graph::EdgeId edge_; + + public: + explicit EdgeIdVertex(EdgeId edge_) : edge_(edge_) {} + + size_t GetId() const override { return edge_.int_id(); } + ScaffoldVertexT GetType() const override { return Edge; } + size_t GetLengthFromGraph(const debruijn_graph::Graph &g) const override { return g.length(edge_); } + double GetCoverageFromGraph(const debruijn_graph::Graph &g) const override { return g.coverage(edge_); } + std::shared_ptr GetConjugateFromGraph(const debruijn_graph::Graph &g) const override; + debruijn_graph::VertexId GetEndGraphVertex(const debruijn_graph::Graph &g) const override { return g.EdgeEnd(edge_); } + debruijn_graph::VertexId GetStartGraphVertex(const debruijn_graph::Graph &g) const override { return g.EdgeStart(edge_); } + std::optional GetLastEdgeWithPredicate(const func::TypedPredicate &pred) const override; + std::optional GetFirstEdgeWithPredicate(const func::TypedPredicate &pred) const override; + std::string GetSequence(const debruijn_graph::Graph &g) const override; + size_t GetSize() const override { return 1; } + + EdgeId GetLastEdge() const override { return edge_; } + EdgeId GetFirstEdge() const override { return edge_; } + std::unordered_set GetAllEdges() const override; + + std::string str(const debruijn_graph::Graph &g) const override { return g.str(edge_); } + path_extend::BidirectionalPath* ToPath(const debruijn_graph::Graph &g) const override; + + EdgeId get() const { return edge_; } +}; + +class PathVertex : public InnerScaffoldVertex { + private: + path_extend::BidirectionalPath *path_; + + public: + using VertexId = debruijn_graph::VertexId; + using InnerScaffoldVertex::EdgeId; + + explicit PathVertex(path_extend::BidirectionalPath *path_) : path_(path_) {} + + size_t GetId() const override { return path_->GetId(); } + ScaffoldVertexT GetType() const override { return Path; } + size_t GetLengthFromGraph(const debruijn_graph::Graph &/*g*/) const override { return path_->Length(); } + double GetCoverageFromGraph(const debruijn_graph::Graph &/*g*/) const override { return path_->Coverage(); } + std::shared_ptr GetConjugateFromGraph(const debruijn_graph::Graph &/*g*/) const override; + VertexId GetEndGraphVertex(const debruijn_graph::Graph &g) const override; + VertexId GetStartGraphVertex(const debruijn_graph::Graph &g) const override; + std::optional GetLastEdgeWithPredicate(const func::TypedPredicate &pred) const override; + std::optional GetFirstEdgeWithPredicate(const func::TypedPredicate &pred) const override; + std::string GetSequence(const debruijn_graph::Graph &g) const override; + size_t GetSize() const override { return path_->Size(); } + + EdgeId GetLastEdge() const override; + EdgeId GetFirstEdge() const override; + std::unordered_set GetAllEdges() const override; + + std::string str(const debruijn_graph::Graph &/*g*/) const override { return path_->str(); } + path_extend::BidirectionalPath* ToPath(const debruijn_graph::Graph &/*g*/) const override { return path_; } + + path_extend::BidirectionalPath *get() const { return path_; } +}; + +class ScaffoldVertex { + std::shared_ptr vertex_ptr_; + + public: + using EdgeId = debruijn_graph::EdgeId; + using VertexId = debruijn_graph::VertexId; + + explicit ScaffoldVertex(std::shared_ptr vertex_ptr_); + + ScaffoldVertex(const ScaffoldVertex& other) = default; + + //make implicit for easy scaffold edge construction + ScaffoldVertex(EdgeId edge); + ScaffoldVertex(path_extend::BidirectionalPath *path); + + ScaffoldVertex() : vertex_ptr_(nullptr) {} + + //deviate from surrounding style to make compatible with generic graph algorithms + size_t int_id() const { return vertex_ptr_->GetId(); } + + ScaffoldVertexT GetType() const { return vertex_ptr_->GetType(); } + size_t GetLengthFromGraph(const debruijn_graph::Graph &g) const { return vertex_ptr_->GetLengthFromGraph(g); } + double GetCoverageFromGraph(const debruijn_graph::Graph &g) const { return vertex_ptr_->GetCoverageFromGraph(g); } + ScaffoldVertex GetConjugateFromGraph(const debruijn_graph::Graph &g) const; + VertexId GetEndGraphVertex(const debruijn_graph::Graph &g) const { return vertex_ptr_->GetEndGraphVertex(g); } + VertexId GetStartGraphVertex(const debruijn_graph::Graph &g) const { return vertex_ptr_->GetStartGraphVertex(g); } + std::optional GetLastEdgeWithPredicate(const func::TypedPredicate &pred) const { + return vertex_ptr_->GetLastEdgeWithPredicate(pred); + } + std::optional GetFirstEdgeWithPredicate(const func::TypedPredicate &pred) const { + return vertex_ptr_->GetFirstEdgeWithPredicate(pred); + } + std::string GetSequence(const debruijn_graph::Graph &g) const { return vertex_ptr_->GetSequence(g); } + size_t GetSize() const { return vertex_ptr_->GetSize(); } + + EdgeId GetLastEdge() const { return vertex_ptr_->GetLastEdge(); } + EdgeId GetFirstEdge() const { return vertex_ptr_->GetFirstEdge(); } + std::unordered_set GetAllEdges() const { return vertex_ptr_->GetAllEdges(); } + + std::string str(const debruijn_graph::Graph &g) const { return vertex_ptr_->str(g); } + path_extend::BidirectionalPath* ToPath(const debruijn_graph::Graph &g) const { return vertex_ptr_->ToPath(g); } + + std::shared_ptr GetInnerVertex() const { return vertex_ptr_; } + + bool operator==(const ScaffoldVertex &rhs) const { return GetType() == rhs.GetType() and int_id() == rhs.int_id(); } + bool operator!=(const ScaffoldVertex &rhs) const { return !(rhs == *this); } + bool operator<(const ScaffoldVertex &rhs) const { + return GetType() < rhs.GetType() or (GetType() == rhs.GetType() and int_id() < rhs.int_id()); + } + bool operator>(const ScaffoldVertex &rhs) const { return rhs < *this; } + bool operator<=(const ScaffoldVertex &rhs) const { return !(rhs < *this); } + bool operator>=(const ScaffoldVertex &rhs) const { return !(*this < rhs); } +}; + +class EdgeGetter { + public: + debruijn_graph::EdgeId GetEdgeFromScaffoldVertex(const ScaffoldVertex& vertex) { + VERIFY_DEV(vertex.GetType() == Edge); + auto inner_vertex = std::static_pointer_cast(vertex.GetInnerVertex()); + return inner_vertex->get(); + } +}; + +} + +namespace std { +template<> +struct hash { + size_t operator()(const scaffold_graph::ScaffoldVertex& vertex) const { + return vertex.int_id(); + } +}; + +template<> +struct less { + bool operator()(const scaffold_graph::ScaffoldVertex& lhs, + const scaffold_graph::ScaffoldVertex& rhs) const { + return lhs < rhs; + } +}; + +} diff --git a/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex_index.hpp b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex_index.hpp new file mode 100644 index 0000000000..cd5265b6fe --- /dev/null +++ b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex_index.hpp @@ -0,0 +1,240 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "barcode_info_extractor.hpp" +#include "auxiliary_graphs/scaffold_graph/scaffold_vertex.hpp" +#include "assembly_graph/core/graph.hpp" +#include "adt/iterator_range.hpp" + +namespace barcode_index { + +template +class ScaffoldVertexIndexBuilder; + +template +class ScaffoldVertexIndex { + friend class ScaffoldVertexIndexBuilder; + public: + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + typedef typename VertexEntryT::const_iterator const_iterator; + typedef debruijn_graph::Graph Graph; + + ScaffoldVertexIndex(const Graph &g): g_(g), vertex_to_entry_() {} + + const VertexEntryT& GetHeadEntry(const ScaffoldVertex& vertex) const { + return vertex_to_entry_.at(vertex); + } + const VertexEntryT& GetTailEntry(const ScaffoldVertex& vertex) const { + return vertex_to_entry_.at(vertex.GetConjugateFromGraph(g_)); + } + + const_iterator GetHeadBegin(const ScaffoldVertex& vertex) const { + return vertex_to_entry_.at(vertex).begin(); + } + const_iterator GetHeadEnd(const ScaffoldVertex& vertex) const { + return vertex_to_entry_.at(vertex).end(); + } + adt::iterator_range GetHeadRange(const ScaffoldVertex& vertex) const { + return adt::make_range(GetHeadBegin(vertex), GetHeadEnd(vertex)); + } + const_iterator GetTailBegin(const ScaffoldVertex& vertex) const { + return vertex_to_entry_.at(vertex.GetConjugateFromGraph(g_)).begin(); + } + const_iterator GetTailEnd(const ScaffoldVertex& vertex) const { + return vertex_to_entry_.at(vertex.GetConjugateFromGraph(g_)).end(); + } + adt::iterator_range GetTailRange(const ScaffoldVertex& vertex) const { + return adt::make_range(GetTailBegin(vertex.GetConjugateFromGraph(g_)), + GetTailEnd(vertex.GetConjugateFromGraph(g_))); + } + + bool Contains(const ScaffoldVertex &vertex) const { + return vertex_to_entry_.find(vertex) != vertex_to_entry_.end(); + } + private: + void InsertEntry(const ScaffoldVertex& vertex, VertexEntryT&& entry) { + vertex_to_entry_.insert({vertex, entry}); + } + + const Graph& g_; + std::unordered_map vertex_to_entry_; +}; + +typedef std::set SimpleVertexEntry; + +typedef ScaffoldVertexIndex SimpleScaffoldVertexIndex; + +class ScaffoldVertexIndexInfoExtractor { + public: + typedef typename scaffold_graph::ScaffoldVertex ScaffoldVertex; + public: + virtual size_t GetHeadSize(const ScaffoldVertex &vertex) const = 0; + virtual size_t GetTailSize(const ScaffoldVertex &vertex) const = 0; + + virtual size_t GetIntersectionSize(const ScaffoldVertex &first, const ScaffoldVertex &second) const = 0; + + /** + * @note second is supposed to be between first and third + */ + virtual size_t GetIntersectionSize(const ScaffoldVertex &first, const ScaffoldVertex &second, + const ScaffoldVertex &third) const = 0; +}; + +template +class IntersectingScaffoldVertexIndexInfoExtractor: public ScaffoldVertexIndexInfoExtractor { + public: + using ScaffoldVertexIndexInfoExtractor::ScaffoldVertex; + + public: + virtual SimpleVertexEntry GetIntersection(const VertexEntryT &first, const VertexEntryT &second) const = 0; + virtual SimpleVertexEntry GetIntersection(const ScaffoldVertex &first, const ScaffoldVertex &second) const = 0; + /** + * @note second is supposed to be between first and third + */ + virtual size_t GetIntersectionSize(const ScaffoldVertex &middle, const VertexEntryT &entry) const = 0; + size_t GetIntersectionSize(const VertexEntryT &first, const VertexEntryT &second) { + return GetIntersection(first, second).size(); + } + + virtual SimpleVertexEntry GetHeadEntry(const ScaffoldVertex &vertex) = 0; + virtual SimpleVertexEntry GetTailEntry(const ScaffoldVertex &vertex) = 0; +}; + +class BarcodeIndexInfoExtractorWrapper: public IntersectingScaffoldVertexIndexInfoExtractor { + public: + using Graph = debruijn_graph::Graph; + + BarcodeIndexInfoExtractorWrapper(const Graph &g, std::shared_ptr barcode_index_) + : g_(g), barcode_extractor_(barcode_index_) {} + + size_t GetHeadSize(const ScaffoldVertex &vertex) const override { + return barcode_extractor_->GetNumberOfBarcodes(vertex.GetFirstEdge()); + } + size_t GetTailSize(const ScaffoldVertex &vertex) const override { + return barcode_extractor_->GetNumberOfBarcodes(vertex.GetConjugateFromGraph(g_).GetFirstEdge()); + } + size_t GetIntersectionSize(const ScaffoldVertex &first, const ScaffoldVertex &second) const override { + return barcode_extractor_->GetNumberOfSharedBarcodes(first.GetLastEdge(), second.GetFirstEdge()); + } + size_t GetIntersectionSize(const ScaffoldVertex &first, + const ScaffoldVertex &second, + const ScaffoldVertex &third) const override { + return GetIntersectionSize(third, GetIntersection(first, second)); + } + + SimpleVertexEntry GetIntersection(const SimpleVertexEntry &first, + const SimpleVertexEntry &second) const override { + SimpleVertexEntry result; + std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), + std::inserter(result, result.end())); + return result; + } + SimpleVertexEntry GetIntersection(const ScaffoldVertex &first, const ScaffoldVertex &second) const override { + auto intersection = barcode_extractor_->GetSharedBarcodes(first.GetLastEdge(), second.GetFirstEdge()); + std::set result; + std::copy(intersection.begin(), intersection.end(), std::inserter(result, result.begin())); + return result; + } + size_t GetIntersectionSize(const ScaffoldVertex &middle, const SimpleVertexEntry &entry) const override { + auto barcodes = barcode_extractor_->GetBarcodes(middle.GetFirstEdge()); + SimpleVertexEntry intersection; + std::set_intersection(barcodes.begin(), barcodes.end(), entry.begin(), entry.end(), + std::inserter(intersection, intersection.begin())); + return intersection.size(); + } + SimpleVertexEntry GetHeadEntry(const ScaffoldVertex &/*vertex*/) override { + VERIFY_MSG(false, "Head entry extractor from BarcodeIndexInfoExtractorWrapper is currently not supported"); + SimpleVertexEntry result; + return result; + } + SimpleVertexEntry GetTailEntry(const ScaffoldVertex &vertex) override { + return GetHeadEntry(vertex); + } + + private: + const Graph &g_; + std::shared_ptr barcode_extractor_; +}; + +class SimpleScaffoldVertexIndexInfoExtractor: public IntersectingScaffoldVertexIndexInfoExtractor { + public: + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + + explicit SimpleScaffoldVertexIndexInfoExtractor(std::shared_ptr> index_) + : index_(index_) {} + + SimpleVertexEntry GetIntersection(const ScaffoldVertex &first, const ScaffoldVertex &second) const override { + SimpleVertexEntry result; + auto first_begin = index_->GetTailBegin(first); + auto first_end = index_->GetTailEnd(first); + auto second_begin = index_->GetHeadBegin(second); + auto second_end = index_->GetHeadEnd(second); + std::set_intersection(first_begin, first_end, second_begin, second_end, std::inserter(result, result.end())); + return result; + } + size_t GetIntersectionSize(const ScaffoldVertex &first, const ScaffoldVertex &second) const override { + auto first_begin = index_->GetTailBegin(first); + auto first_end = index_->GetTailEnd(first); + auto second_begin = index_->GetHeadBegin(second); + auto second_end = index_->GetHeadEnd(second); + auto first_it = first_begin; + auto second_it = second_begin; + size_t current_intersection = 0; + while (first_it != first_end and second_it != second_end) { + if (*first_it == *second_it) { + ++current_intersection; + ++first_it; + ++second_it; + } else if (*first_it < *second_it) { + ++first_it; + } else { + ++second_it; + } + } + return current_intersection; + } + size_t GetIntersectionSize(const ScaffoldVertex &middle, const SimpleVertexEntry &entry) const override { + auto middle_begin = index_->GetHeadBegin(middle); + auto middle_end = index_->GetHeadEnd(middle); + SimpleVertexEntry intersection; + std::set_intersection(entry.begin(), entry.end(), middle_begin, middle_end, std::inserter(intersection, intersection.end())); + return intersection.size(); + } + size_t GetIntersectionSize(const ScaffoldVertex &first, + const ScaffoldVertex &second, + const ScaffoldVertex &third) const override { + const auto& entry = GetIntersection(first, third); + return GetIntersectionSize(second, entry); + } + + size_t GetHeadSize(const ScaffoldVertex &vertex) const override { + return (index_->GetHeadEntry(vertex)).size(); + } + size_t GetTailSize(const ScaffoldVertex &vertex) const override { + return (index_->GetTailEntry(vertex)).size(); + } + SimpleVertexEntry GetIntersection(const SimpleVertexEntry &first, + const SimpleVertexEntry &second) const override { + SimpleVertexEntry result; + std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), std::inserter(result, result.end())); + return result; + } + SimpleVertexEntry GetHeadEntry(const ScaffoldVertex &vertex) override { + return index_->GetHeadEntry(vertex); + } + SimpleVertexEntry GetTailEntry(const ScaffoldVertex &vertex) override { + return index_->GetTailEntry(vertex); + } + + private: + std::shared_ptr> index_; +}; + +typedef IntersectingScaffoldVertexIndexInfoExtractor SimpleIntersectingScaffoldVertexExtractor; +} \ No newline at end of file diff --git a/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex_index_builder.hpp b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex_index_builder.hpp new file mode 100644 index 0000000000..07356373a1 --- /dev/null +++ b/src/common/auxiliary_graphs/scaffold_graph/scaffold_vertex_index_builder.hpp @@ -0,0 +1,239 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "scaffold_vertex_index.hpp" +#include "barcode_info_extractor.hpp" + +namespace barcode_index { + + template + class AbstractScaffoldVertexEntryExtractor { + public: + virtual EdgeEntryT ExtractEntry(const scaffold_graph::ScaffoldVertex &vertex) const = 0; + }; + + class TailThresholdGetter { + public: + virtual size_t GetTailThreshold(const scaffold_graph::ScaffoldVertex &vertex) const = 0; + }; + + class ConstTailThresholdGetter: public TailThresholdGetter { + public: + explicit ConstTailThresholdGetter(const size_t tail_threshold_) : tail_threshold_(tail_threshold_) {} + size_t GetTailThreshold(const scaffold_graph::ScaffoldVertex &/*vertex*/) const override { + return tail_threshold_; + } + private: + const size_t tail_threshold_; + }; + + class FractionTailThresholdGetter: public TailThresholdGetter { + public: + typedef debruijn_graph::Graph Graph; + + FractionTailThresholdGetter(const Graph &g_, const double edge_length_fraction_) + : g_(g_), edge_length_fraction_(edge_length_fraction_) {} + + size_t GetTailThreshold(const scaffold_graph::ScaffoldVertex &vertex) const override { + return static_cast(static_cast(vertex.GetLengthFromGraph(g_)) * edge_length_fraction_); + } + private: + const Graph& g_; + const double edge_length_fraction_; + }; + + class ScaffoldVertexSimpleEntryExtractor: public AbstractScaffoldVertexEntryExtractor { + public: + typedef debruijn_graph::Graph Graph; + typedef debruijn_graph::EdgeId EdgeId; + typedef typename scaffold_graph::EdgeIdVertex EdgeIdVertex; + typedef typename scaffold_graph::PathVertex PathVertex; + + ScaffoldVertexSimpleEntryExtractor(const Graph &g_, + const FrameBarcodeIndexInfoExtractor &barcode_extractor_, + std::shared_ptr tail_threshold_getter, + const size_t count_threshold_, + const size_t length_threshold_) + : g_(g_), + barcode_extractor_(barcode_extractor_), + tail_threshold_getter_(tail_threshold_getter), + count_threshold_(count_threshold_), + length_threshold_(length_threshold_) {} + + SimpleVertexEntry ExtractEntry(const scaffold_graph::ScaffoldVertex &vertex) const override { + auto inner_vertex = vertex.GetInnerVertex(); + + SimpleVertexEntry empty; + auto type = vertex.GetType(); + switch (type) { + case scaffold_graph::ScaffoldVertexT::Edge: { + auto edge_vertex = std::static_pointer_cast(inner_vertex); + return ExtractEntryInner(edge_vertex); + } + case scaffold_graph::ScaffoldVertexT::Path: { + auto path_vertex = std::static_pointer_cast(inner_vertex); + return ExtractEntryInner(path_vertex); + } + } + WARN("ScaffoldVertex of unknown type"); + return empty; + } + + private: + SimpleVertexEntry ExtractEntryInner(std::shared_ptr simple_edge_vertex) const { + SimpleVertexEntry result; + TRACE("Extracting entry from edge"); + auto edge = simple_edge_vertex->get(); + size_t tail_threshold = tail_threshold_getter_->GetTailThreshold(edge); + TRACE("Tail threshold: " << tail_threshold); + auto entry = barcode_extractor_.GetBarcodesFromHead(edge, count_threshold_, tail_threshold); + std::copy(entry.begin(), entry.end(), std::inserter(result, result.end())); + TRACE("Entry size: " << entry.size()); + return result; + } + + //fixme optimize later + SimpleVertexEntry ExtractEntryInner(std::shared_ptr path_vertex) const { + TRACE("Extracting entry from path"); + size_t current_prefix = 0; + path_extend::BidirectionalPath* path = path_vertex->get(); + size_t path_size = path->Size(); + SimpleVertexEntry result; + const size_t global_count_threshold = 5; + std::unordered_map barcode_to_count; + size_t tail_threshold = tail_threshold_getter_->GetTailThreshold(path_vertex->get()); + TRACE("Tail threshold: " << tail_threshold); + for (size_t i = 0; i < path_size and current_prefix <= tail_threshold; ++i) { + EdgeId current_edge = path->At(i); + if (g_.length(current_edge) < length_threshold_) { + current_prefix += g_.length(current_edge); + continue; + } + size_t current_tail = tail_threshold - current_prefix; + TRACE("Current tail: " << current_tail); + const auto ¤t_entry = barcode_extractor_.GetBarcodesAndCountsFromHead(current_edge, + count_threshold_, + current_tail); + for (const auto& barcode_and_reads: current_entry) { + barcode_to_count[barcode_and_reads.first] += barcode_and_reads.second; + } + TRACE("Current entry size: " << barcode_to_count.size()); + current_prefix += g_.length(current_edge); + } + for (const auto& barcode_and_count: barcode_to_count) { + if (barcode_and_count.second >= global_count_threshold) { + result.insert(barcode_and_count.first); + } + } + TRACE("Result size: " << result.size()); + return result; + } + + const debruijn_graph::Graph &g_; + const FrameBarcodeIndexInfoExtractor& barcode_extractor_; + std::shared_ptr tail_threshold_getter_; + const size_t count_threshold_; + const size_t length_threshold_; + + DECL_LOGGER("ScaffoldVertexSimpleEntryExtractor"); + }; + + template + class ScaffoldVertexIndexBuilder { + public: + typedef debruijn_graph::Graph Graph; + typedef debruijn_graph::EdgeId EdgeId; + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + typedef std::shared_ptr> EntryExtractorPtr; + + ScaffoldVertexIndexBuilder(const Graph &g, EntryExtractorPtr vertex_entry_extractor, size_t max_threads) + : g_(g), vertex_entry_extractor_(vertex_entry_extractor), + index_(std::make_shared>(g_)), max_threads_(max_threads) {} + + template + std::shared_ptr> GetConstructedIndex(const ContainerT& vertex_container) { + + //todo make parallel using iterator chunks + DEBUG("Constructing long edge index in " << max_threads_ << " threads"); +// size_t counter = 0; +// size_t block_size = vertex_container.size() / 10; + for (const auto& vertex: vertex_container) + { + auto entry = vertex_entry_extractor_->ExtractEntry(vertex); + TRACE("Entry size: " << entry.size()); + { + index_->InsertEntry(vertex, std::move(entry)); +// ++counter; + } +// if (counter % block_size == 0) { +// INFO("Processed " << counter << " edges out of " << vertex_container.size()); +// } + } + DEBUG("Constructed long edge index"); + return index_; + } + + private: + const Graph& g_; + EntryExtractorPtr vertex_entry_extractor_; + std::shared_ptr> index_; + size_t max_threads_; + }; + + class SimpleScaffoldVertexIndexBuilderHelper { + public: + typedef debruijn_graph::Graph Graph; + typedef std::shared_ptr ScaffoldIndexPtr; + typedef scaffold_graph::ScaffoldVertex ScaffoldVertex; + + template + ScaffoldIndexPtr ConstructScaffoldVertexIndex(const Graph& g_, const FrameBarcodeIndexInfoExtractor& extractor, + std::shared_ptr tail_threshold_getter, + size_t count_threshold, size_t length_threshold, + size_t max_threads, const ContainerT& vertex_container) { + DEBUG("Building simple long edge barcode index with parameters"); + DEBUG("Count threshold: " << count_threshold); + DEBUG("Length threshold: " << length_threshold); + auto entry_extractor = std::make_shared(g_, extractor, + tail_threshold_getter, + count_threshold, + length_threshold); + ScaffoldVertexIndexBuilder builder(g_, entry_extractor, max_threads); + return builder.GetConstructedIndex(vertex_container); + } + + template + ScaffoldIndexPtr HalfEdgeScaffoldVertexIndex(const Graph& g, const FrameBarcodeIndexInfoExtractor& extractor, + const ContainerT& vertex_container, size_t count_threshold, + size_t max_threads) { + const size_t length_threshold = 1000; + const size_t linkage_distance = 10; + const double EDGE_LENGTH_FRACTION = 0.5; + auto threshold_getter = std::make_shared(g, EDGE_LENGTH_FRACTION); + auto split_scaffold_vertex_index = ConstructScaffoldVertexIndex(g, extractor, + threshold_getter, + count_threshold, length_threshold, + max_threads, vertex_container); + return split_scaffold_vertex_index; + } + + template + ScaffoldIndexPtr TailEdgeScaffoldVertexIndex(const Graph& g, const FrameBarcodeIndexInfoExtractor& extractor, + const ContainerT& vertex_container, size_t count_threshold, + size_t tail_threshold, size_t max_threads) { + const size_t length_threshold = 1000; + auto tail_threshold_getter = std::make_shared(tail_threshold); + auto scaffold_vertex_index = ConstructScaffoldVertexIndex(g, extractor, tail_threshold_getter, + count_threshold, length_threshold, + max_threads, vertex_container); + return scaffold_vertex_index; + } + }; + +} \ No newline at end of file diff --git a/src/common/barcode_index/barcode_index.hpp b/src/common/barcode_index/barcode_index.hpp new file mode 100644 index 0000000000..a6c203c677 --- /dev/null +++ b/src/common/barcode_index/barcode_index.hpp @@ -0,0 +1,814 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2017-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "assembly_graph/core/graph.hpp" +#include "assembly_graph/index/edge_index_builders.hpp" +#include "assembly_graph/paths/mapping_path.hpp" +#include "io/binary/binary.hpp" +#include "io/reads/paired_readers.hpp" +#include "sequence/range.hpp" + +#include +#include + +using namespace omnigraph; + +namespace barcode_index { +typedef RtSeq Kmer; + +class FrameBarcodeIndexBuilder; +template +class BarcodeIndexInfoExtractor; +typedef uint64_t BarcodeId; + +/** + This class provides partial interface to BarcodeIndex. +*/ +template +class AbstractBarcodeIndex { +public: + typedef typename Graph::EdgeId EdgeId; + +protected: + const Graph& g_; +public: + AbstractBarcodeIndex (const Graph &g) : + g_(g) {} + virtual ~AbstractBarcodeIndex() {} + + //Number of entries in the barcode map. Currently equals to the number of edges. + virtual size_t size() const = 0; + + //Number of barcodes on the beginning/end of the edge + virtual size_t GetBarcodeNumber(EdgeId edge) const = 0; + + virtual void ReadEntry(std::ifstream& fin, EdgeId edge) = 0; + virtual void WriteEntry(std::ofstream& fin, EdgeId edge) = 0; + + //Remove low abundant barcodes + virtual void Filter(size_t abundancy_threshold, size_t gap_threshold) = 0; + + virtual bool IsEmpty() = 0; + +}; + +template +class ConcurrentBarcodeIndexBuffer { + public: + typedef typename Graph::EdgeId EdgeId; + typedef libcuckoo::cuckoohash_map StorageMap; + + ConcurrentBarcodeIndexBuffer(const Graph &g) : g_(g), edge_to_entry_() {} + virtual ~ConcurrentBarcodeIndexBuffer() {clear();} + + void clear() { + edge_to_entry_.clear(); + } + + typename StorageMap::locked_table lock_table() { + return edge_to_entry_.lock_table(); + } + + void InsertEntry(EdgeEntryT &&entry) { + edge_to_entry_.insert(entry); + } + + void InsertBarcode(BarcodeId barcode, EdgeId edge, size_t count, const Range &range) { + edge_to_entry_.update_fn(edge, + [&](EdgeEntryT &second) { + second.InsertBarcode(barcode, count, range); + }); + } + protected: + const Graph &g_; + StorageMap edge_to_entry_; +}; + +/** + * BarcodeIndex stores information provided by alignment of read clouds to the graph. + * For every edge we store barcoded reads which are contained on the edge along with additional info. + * Read cloud is represented by its barcode + * The edge contains the cloud if there is a read barcoded by cloud's barcode which is aligned to the edge. + * Info example: FrameBarcodeInfo + */ +template +class BarcodeIndex: public AbstractBarcodeIndex { +friend class BarcodeIndexInfoExtractor; + +public: + typedef typename Graph::EdgeId EdgeId; + typedef typename Graph::VertexId VertexId; + typedef std::unordered_map barcode_map_t; + + BarcodeIndex (const Graph &g) : + AbstractBarcodeIndex(g), + edge_to_entry_(), + number_of_barcodes_(0) + {} + + BarcodeIndex (const BarcodeIndex& other) = default; + + virtual ~BarcodeIndex() {} + + size_t size() const { + return edge_to_entry_.size(); + } + + bool empty() const { + return size() == 0; + } + + typename barcode_map_t::iterator begin() noexcept { + return edge_to_entry_.begin(); + } + typename barcode_map_t::iterator end() noexcept { + return edge_to_entry_.end(); + } + typename barcode_map_t::iterator begin() const noexcept { + return edge_to_entry_.begin(); + } + typename barcode_map_t::iterator end() const noexcept { + return edge_to_entry_.end(); + } + typename barcode_map_t::const_iterator cbegin() const noexcept { + return edge_to_entry_.cbegin(); + } + typename barcode_map_t::const_iterator cend() const noexcept { + return edge_to_entry_.cend(); + } + + size_t GetBarcodeNumber(EdgeId edge) const override { + return GetEntry(edge).Size(); + } + + bool IsEmpty() override { + return size() == 0; + } + + //Delete low abundant barcodes from every edge + void Filter(size_t trimming_threshold, size_t gap_threshold) override { + for (auto &entry: edge_to_entry_) { + entry.second.Filter(trimming_threshold, gap_threshold); + } + } + + void ReadEntry (std::ifstream& fin, EdgeId edge) override { + DEBUG("Reading entry") + DEBUG("Edge: " << edge.int_id()); + DEBUG("Length: " << g_.length(edge)); + edge_to_entry_[edge].Deserialize(fin); + } + void WriteEntry (std::ofstream& fout, EdgeId edge) override { + fout << g_.int_id(edge) << std::endl; + GetEntry(edge).Serialize(fout); + } + + virtual void BinRead(std::istream &str) { + using io::binary::BinRead; + + edge_to_entry_.clear(); + size_t size; + BinRead(str, size); + for (size_t i = 0; i < size; ++i) { + EdgeId edge_id = BinRead(str); + edge_to_entry_.emplace(edge_id, BinRead(str)); + } + } + virtual void BinWrite(std::ostream &str) const { + using io::binary::BinWrite; + BinWrite(str, edge_to_entry_.size()); + for (const auto &edge_and_entry: edge_to_entry_) { + BinWrite(str, edge_and_entry.first.int_id(), edge_and_entry.second); + } + } + + typename barcode_map_t::const_iterator GetEntryTailsIterator(EdgeId edge) const { + return edge_to_entry_.find(g_.conjugate(edge)); + } + typename barcode_map_t::const_iterator GetEntryHeadsIterator(EdgeId edge) const { + return edge_to_entry_.find(edge); + } + + void InsertEntry(EdgeId edge, const EdgeEntryT &entry) { + edge_to_entry_.insert({edge, entry}); + } + const EdgeEntryT& GetEntry(EdgeId edge) const { + return edge_to_entry_.at(edge); + } + + void MoveAssign(ConcurrentBarcodeIndexBuffer &from) { + this->edge_to_entry_.clear(); + auto locked_table = from.lock_table(); + DEBUG(locked_table.size()); + for (auto& kvpair : locked_table) { + TRACE(kvpair.first.int_id()); + TRACE("Length: " << g_.length(kvpair.first)); + TRACE(kvpair.second.Size() << " barcodes"); + this->edge_to_entry_[kvpair.first] = std::move(kvpair.second); + } + } + + void MoveUpdate(ConcurrentBarcodeIndexBuffer &from) { + auto locked_table = from.lock_table(); + for (auto &kvpair: locked_table) { + this->edge_to_entry_[kvpair.first].MoveUpdate(kvpair.second); + } + } + + void Update(ConcurrentBarcodeIndexBuffer &from) { + auto locked_table = from.lock_table(); + for (const auto &kvpair: locked_table) { + this->edge_to_entry_[kvpair.first].Update(kvpair.second); + } + } + + void SetNumberOfBarcodes(size_t number_of_barcodes) { + number_of_barcodes_ = number_of_barcodes; + } + size_t GetNumberOfBarcodes() { + return number_of_barcodes_; + } + + const Graph& GetGraph() const { + return g_; + } + + protected: + using AbstractBarcodeIndex::g_; + barcode_map_t edge_to_entry_; + size_t number_of_barcodes_; + + DECL_LOGGER("BarcodeIndex"); +}; + +class SimpleBarcodeInfo { + size_t count_; + Range range_; +public: + SimpleBarcodeInfo(): count_(0), range_() {} + SimpleBarcodeInfo(size_t count, const Range& range): count_(count), range_(range) {} + + void Update(size_t count, const Range& range) { + count_ += count; + range_.start_pos = std::min(range_.start_pos, range.start_pos); + range_.end_pos = std::max(range_.end_pos, range.end_pos); + } + + void Update(const SimpleBarcodeInfo& other) { + count_ += other.GetCount(); + Range range; + range_.start_pos = std::min(range_.start_pos, other.GetRange().start_pos); + range_.end_pos = std::max(range_.end_pos, other.GetRange().end_pos); + } + + size_t GetCount() const { + return count_; + } + + Range GetRange() const { + return range_; + } + friend std::ostream &operator<<(std::ostream &os, const SimpleBarcodeInfo &info); + friend std::istream &operator>>(std::istream &is, SimpleBarcodeInfo &info); +}; + +inline std::ostream &operator<<(std::ostream &os, const SimpleBarcodeInfo &info) +{ + os << info.count_ << " " << info.range_.start_pos << " " << info.range_.end_pos; + return os; +} + +inline std::istream &operator>>(std::istream &is, SimpleBarcodeInfo &info) +{ + size_t range_start; + size_t range_end; + is >> info.count_; + is >> range_start; + is >> range_end; + info.range_ = Range(range_start, range_end); + return is; +} + +/** + * FrameBarcodeInfo approximates the read cloud defined by the barcode and the edge. + * The edge is split into several bins. + * Bin is barcoded iff there is at least one barcoded read which aligns to the bin. + * + * We store the set of barcoded bins and the number of reads aligned to the edge. + */ +class FrameBarcodeInfo { +public: + /** + * + * @param frames Number of bin in the edge + * @return empty info + */ + FrameBarcodeInfo(size_t frames = 0): count_(0), covered_bins_(), leftmost_index_(frames), rightmost_index_(0) {} + + void Update(size_t count, size_t left_frame, size_t right_frame) { + count_ += count; + for (size_t i = left_frame; i <= right_frame; ++i) { + covered_bins_.insert(i); + } + leftmost_index_ = std::min(left_frame, leftmost_index_); + rightmost_index_ = std::max(right_frame, rightmost_index_); + } + + void Update(const FrameBarcodeInfo& other) { + TRACE(count_); + TRACE(other.count_); + TRACE(covered_bins_.size()); + TRACE(other.covered_bins_.size()); + for (const auto &frame: other.covered_bins_) { + covered_bins_.insert(frame); + } + leftmost_index_ = std::min(leftmost_index_, other.leftmost_index_); + rightmost_index_ = std::max(rightmost_index_, other.rightmost_index_); + count_ += other.count_; + } + + /** + * @return number of barcoded reads aligned to the edge + */ + size_t GetCount() const { + return count_; + } + + /** + * @return Leftmost barcoded bin + */ + size_t GetLeftMost() const { + return leftmost_index_; + } + + /** + * @return Rightmost barcoded bin + */ + size_t GetRightMost() const { + return rightmost_index_; + } + + /** + * + * @return number of barcoded bins + */ + size_t GetCovered() const { + return covered_bins_.size(); + } + + void SetCount(size_t count) { + count_ = count; + } + + void SetLeftMost(size_t index) { + leftmost_index_ = index; + } + + void SetRightMost(size_t index) { + rightmost_index_ = index; + } + + void BinRead(std::istream &str) { + using io::binary::BinRead; + auto count = BinRead(str); + SetCount(count); + + auto num_positions = BinRead(str); + size_t min_pos = std::numeric_limits::max(); + size_t max_pos = 0; + for (size_t i = 0; i < num_positions; ++i) { + auto pos = BinRead(str); + TRACE("Position: " << pos); + covered_bins_.insert(pos); + if (pos < min_pos) { + min_pos = pos; + } + if (pos > max_pos) { + max_pos = pos; + } + } + + SetLeftMost(min_pos); + SetRightMost(max_pos); + TRACE("Leftmost: " << GetLeftMost()); + TRACE("Rightmost: " << GetRightMost()); + } + + void BinWrite(std::ostream &str) const { + using io::binary::BinWrite; + BinWrite(str, GetCount()); + BinWrite(str, GetCovered()); + + for (const size_t &pos: covered_bins_) { + BinWrite(str, pos); + } + } + + friend std::ostream &operator<<(std::ostream &os, const FrameBarcodeInfo &info); + friend std::istream &operator>>(std::istream &is, FrameBarcodeInfo &info); + + private: + /** + * Number of reads aligned to the edge + */ + size_t count_; + /** + * Bins covered by the barcode + */ + std::unordered_set covered_bins_; + /** + * Leftmost barcoded bin + */ + size_t leftmost_index_; + /** + * Rightmost barcoded bin + */ + size_t rightmost_index_; + + DECL_LOGGER("FrameBarcodeInfo"); +}; + +inline std::ostream &operator<<(std::ostream &os, const FrameBarcodeInfo &info) +{ + os << info.count_ << " " << info.covered_bins_.size(); + for (const auto &bin: info.covered_bins_) { + os << bin << " "; + } + return os; +} + +inline std::istream &operator>>(std::istream &is, FrameBarcodeInfo &info) +{ + using io::binary::BinRead; + size_t count; + is >> count; + info.SetCount(count); + + size_t num_of_bins; + is >> num_of_bins; + size_t min_pos = std::numeric_limits::max(); + size_t max_pos = 0; + for (size_t i = 0; i < num_of_bins; ++i) { + size_t pos = 0; + is >> pos; + TRACE("Position: " << pos); + if (pos < min_pos) { + min_pos = pos; + } + if (pos > max_pos) { + max_pos = pos; + } + info.covered_bins_.insert(pos); + } + info.SetLeftMost(min_pos); + info.SetRightMost(max_pos); + TRACE("Leftmost: " << info.GetLeftMost()); + TRACE("Rightmost: " << info.GetRightMost()); + return is; +} + +template +class EdgeEntry { +public: + typedef typename Graph::EdgeId EdgeId; + typedef std::map barcode_distribution_t; + typedef EntryInfoT barcode_info_t; + + EdgeEntry(): + edge_(), barcode_distribution_() {}; + EdgeEntry(EdgeId edge) : + edge_(edge), barcode_distribution_() {} + + virtual ~EdgeEntry() {} + + const barcode_distribution_t& GetDistribution() const { + return barcode_distribution_; + } + + EdgeId GetEdge() const { + return edge_; + } + + size_t Size() const { + return barcode_distribution_.size(); + } + + virtual void Serialize(std::ofstream& fout) const { + SerializeDistribution(fout); + } + + virtual void Deserialize(std::ifstream& fin) { + DeserializeDistribution(fin); + } + + typename barcode_distribution_t::const_iterator begin() const { + return barcode_distribution_.begin(); + } + + typename barcode_distribution_t::const_iterator end() const { + return barcode_distribution_.end(); + } + + typename barcode_distribution_t::const_iterator cbegin() const { + return barcode_distribution_.cbegin(); + } + + typename barcode_distribution_t::const_iterator cend() const { + return barcode_distribution_.cend(); + } + + bool HasBarcode(BarcodeId barcode) const { + return barcode_distribution_.find(barcode) != barcode_distribution_.end(); + } + + typename barcode_distribution_t::const_iterator GetBarcode(BarcodeId barcode) const { + return barcode_distribution_.find(barcode); + } + + virtual void BinRead(std::istream &str) { + barcode_distribution_ = io::binary::BinRead(str); + } + + virtual void BinWrite(std::ostream &str) const { + io::binary::BinWrite(str, barcode_distribution_); + } + +protected: + void SerializeDistribution(std::ofstream &fout) const { + fout << barcode_distribution_.size() << std::endl; + for (auto entry : barcode_distribution_) { + fout << entry.first << ' ' << entry.second << std::endl; + } + } + + void DeserializeDistribution(std::ifstream &fin) { + size_t distr_size; + fin >> distr_size; + for (size_t i = 0; i < distr_size; ++i) { + uint64_t int_id; + EntryInfoT info; + fin >> int_id >> info; + BarcodeId bid(int_id); + InsertInfo(bid, info); + } + } + + void InsertInfo(BarcodeId barcode, const barcode_info_t &info) { + auto barcode_result = barcode_distribution_.find(barcode); + if (barcode_result == barcode_distribution_.end()) { + barcode_distribution_.insert({barcode, info}); + } + else { + barcode_result->second.Update(info); + } + } + virtual void InsertBarcode(BarcodeId code, const size_t count, const Range &range) = 0; + + EdgeId edge_; + barcode_distribution_t barcode_distribution_; +}; + +template +class SimpleEdgeEntry : public EdgeEntry { + friend class BarcodeIndex; + friend class BarcodeIndexInfoExtractor; +protected: + typedef typename Graph::EdgeId EdgeId; + using EdgeEntry::barcode_distribution_; + using EdgeEntry::edge_; + +public: + SimpleEdgeEntry(): + EdgeEntry() {} + SimpleEdgeEntry(EdgeId edge) : + EdgeEntry(edge) {} + + ~SimpleEdgeEntry() {} + + void Filter(size_t trimming_threshold, size_t gap_threshold) { + for (auto it = barcode_distribution_.begin(); it != barcode_distribution_.end() ;) { + if (IsLowReadCount(trimming_threshold, it->second) or + IsFarFromEdgeHead(gap_threshold, it->second)) { + barcode_distribution_.erase(it++); + } + else { + ++it; + } + } + } + +protected: + void InsertBarcode(BarcodeId barcode, const size_t count, const Range& range) { + if (barcode_distribution_.find(barcode) == barcode_distribution_.end()) { + SimpleBarcodeInfo info(count, range); + barcode_distribution_.insert({barcode, info}); + } + else { + barcode_distribution_.at(barcode).Update(count, range); + } + } + + bool IsFarFromEdgeHead(size_t gap_threshold, const SimpleBarcodeInfo& info) { + return info.GetRange().start_pos > gap_threshold; + } + + bool IsLowReadCount(size_t trimming_threshold, const SimpleBarcodeInfo& info) { + return info.GetCount() < trimming_threshold; + } +}; + +template +class FrameEdgeEntry : public EdgeEntry { + friend class BarcodeIndex; + friend class FrameBarcodeIndexBuilder; + friend class BarcodeIndexInfoExtractor; + friend class ConcurrentBarcodeIndexBuffer; +protected: + typedef typename Graph::EdgeId EdgeId; + using EdgeEntry::barcode_distribution_; + using EdgeEntry::edge_; + size_t edge_length_; + size_t frame_size_; + size_t number_of_frames_; + +public: + FrameEdgeEntry(): + EdgeEntry(), + edge_length_(0), + frame_size_(0), + number_of_frames_(0) {} + FrameEdgeEntry(EdgeId edge, size_t edge_length, size_t frame_size) : + EdgeEntry(edge), + edge_length_(edge_length), + frame_size_(frame_size), + number_of_frames_(edge_length / frame_size + 1) {} + + ~FrameEdgeEntry() {} + + void Filter(size_t trimming_threshold, size_t gap_threshold) { + for (auto it = barcode_distribution_.begin(); it != barcode_distribution_.end() ;) { + if (IsLowReadCount(trimming_threshold, it->second) or + IsFarFromEdgeHead(gap_threshold, it->second)) { + barcode_distribution_.erase(it++); + } + else { + ++it; + } + } + } + + size_t GetFrameSize() const { + return frame_size_; + } + + size_t GetNumberOfFrames() const { + return number_of_frames_; + } + + void BinRead(std::istream &str) override { + using io::binary::BinRead; + edge_length_ = BinRead(str); + frame_size_ = BinRead(str); + number_of_frames_ = BinRead(str); + + barcode_distribution_.clear(); + size_t size; + BinRead(str, size); + for (size_t i = 0; i < size; ++i) { + BarcodeId barcode; + FrameBarcodeInfo info(number_of_frames_); + BinRead(str, barcode); + barcode_distribution_.emplace(barcode, BinRead(str)); + } + } + + void BinWrite(std::ostream &str) const override { + using io::binary::BinWrite; + BinWrite(str, edge_length_); + BinWrite(str, frame_size_); + BinWrite(str, number_of_frames_); + + size_t size = barcode_distribution_.size(); + BinWrite(str, size); + for (const auto &entry : barcode_distribution_) { + BinWrite(str, entry.first, entry.second); + } + } + +protected: + void InsertBarcode(BarcodeId barcode, const size_t count, const Range& range) override { + DEBUG("Inserting barcode"); + if (barcode_distribution_.find(barcode) == barcode_distribution_.end()) { + FrameBarcodeInfo info(number_of_frames_); + barcode_distribution_.insert({barcode, info}); + } + size_t left_frame = GetFrameFromPos(range.start_pos); + size_t right_frame = GetFrameFromPos(range.end_pos); + DEBUG("Range: " << range); + DEBUG("Frames: " << left_frame << " " << right_frame); + DEBUG("Count: " << count); + VERIFY_DEV(barcode_distribution_.find(barcode) != barcode_distribution_.end()); + barcode_distribution_.at(barcode).Update(count, left_frame, right_frame); + } + + void MoveUpdate(FrameEdgeEntry &other) { + for (auto it = other.begin(); it != other.end(); ++it) { + barcode_distribution_[it->first] = std::move(it->second); + } + } + + void Update(const FrameEdgeEntry &other) { + for (auto it = other.begin(); it != other.end(); ++it) { + barcode_distribution_[it->first] = it->second; + } + } + + bool IsFarFromEdgeHead(size_t gap_threshold, const FrameBarcodeInfo& info) { + return info.GetLeftMost() > gap_threshold / frame_size_; + } + + bool IsLowReadCount(size_t trimming_threshold, const FrameBarcodeInfo& info) { + return info.GetCount() < trimming_threshold; + } + + void SetFrameSize(size_t frame_size) { + frame_size_ = frame_size; + } + +private: + //fixme last frame is larger than the others + size_t GetFrameFromPos(size_t pos) { + return pos / frame_size_; + } + + DECL_LOGGER("FrameEdgeEntry"); +}; + +template +class FrameConcurrentBarcodeIndexBuffer: public ConcurrentBarcodeIndexBuffer> { + public: + FrameConcurrentBarcodeIndexBuffer(const Graph &g, size_t frame_size): + ConcurrentBarcodeIndexBuffer>(g), frame_size_(frame_size) { + } + + void InitialFillMap() { + VERIFY_DEV(frame_size_ != 0); + VERIFY_DEV(edge_to_entry_.empty()); + for (const debruijn_graph::EdgeId edge: g_.canonical_edges()) { + edge_to_entry_.insert(edge, FrameEdgeEntry(edge, g_.length(edge), frame_size_)); + debruijn_graph::EdgeId conj = g_.conjugate(edge); + edge_to_entry_.insert(conj, FrameEdgeEntry(conj, g_.length(edge), frame_size_)); + } + } + + size_t GetFrameSize() { + return frame_size_; + } + + private: + using ConcurrentBarcodeIndexBuffer>::g_; + using ConcurrentBarcodeIndexBuffer>::edge_to_entry_; + size_t frame_size_; +}; + +template +class FrameBarcodeIndex: public BarcodeIndex> { + friend class FrameBarcodeIndexBuilder; + friend class BarcodeIndexInfoExtractor>; + public: + typedef typename Graph::EdgeId EdgeId; + + FrameBarcodeIndex(const Graph &g, size_t frame_size): + BarcodeIndex>(g), frame_size_(frame_size) { + } + + size_t GetFrameSize() const { + return frame_size_; + } + + void SetFrameSize(size_t frame_size) { + VERIFY_DEV(frame_size_ == 0); + frame_size_ = frame_size; + } + + void InitialFillMap() { + VERIFY_DEV(frame_size_ != 0); + VERIFY_DEV(edge_to_entry_.empty()); + for (const EdgeId &edge: g_.edges()) { + FrameEdgeEntry entry(edge, g_.length(edge), frame_size_); + this->InsertEntry(edge, entry); + } + } + + private: + using BarcodeIndex>::g_; + using BarcodeIndex>::edge_to_entry_; + size_t frame_size_; +}; +} //barcode_index diff --git a/src/common/barcode_index/barcode_index_builder.hpp b/src/common/barcode_index/barcode_index_builder.hpp new file mode 100644 index 0000000000..11f5c3484f --- /dev/null +++ b/src/common/barcode_index/barcode_index_builder.hpp @@ -0,0 +1,272 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2017-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "barcode_index.hpp" + +#include "io/dataset_support/dataset_readers.hpp" +#include "io/reads/read_processor.hpp" +#include "alignment/sequence_mapper_notifier.hpp" +#include "alignment/sequence_mapper.hpp" + +#include +#include +#include + +namespace barcode_index { + +//todo templatize +class ConcurrentBufferFiller { + public: + using EdgeId = debruijn_graph::EdgeId; + using Graph = debruijn_graph::Graph; + using FrameConcurrentBuffer = FrameConcurrentBarcodeIndexBuffer; + using SequenceMapper = debruijn_graph::SequenceMapper; + using MappingPath = omnigraph::MappingPath; + using MappingRange = omnigraph::MappingRange; + using BarcodeMap = libcuckoo::cuckoohash_map; + + class BarcodeEncoder { + public: + explicit BarcodeEncoder(size_t start): + barcodes_map_(), + start_(start) + { } + + BarcodeId find_or_insert(const std::string &barcode_string) { + try { + return barcodes_map_.find(barcode_string); + } + catch (std::out_of_range&) { + size_t num_barcodes = barcodes_map_.size(); + barcodes_map_.insert(barcode_string, num_barcodes + start_); + return num_barcodes; + } + } + + auto begin() { + return barcodes_map_.lock_table().begin(); + } + auto end() { + return barcodes_map_.lock_table().end(); + } + auto find(const std::string& barcode) { + return barcodes_map_.find(barcode); + } + size_t size() const { + return barcodes_map_.size(); + } + private: + BarcodeMap barcodes_map_; + const size_t start_; + }; + + ConcurrentBufferFiller(const Graph &g, + FrameConcurrentBuffer &buf, + const SequenceMapper &mapper, + const std::vector &barcode_prefices, + size_t starting_barcode, bool is_tellseq) : g_(g), + buf_(buf), + mapper_(mapper), + barcode_prefices_(barcode_prefices), + encoder_(starting_barcode), + is_tellseq_(is_tellseq) { Init(); } + + bool operator()(std::unique_ptr r) { + const Sequence& read1 = r->first().sequence(); + const Sequence& read2 = r->second().sequence(); + MappingPath path1 = mapper_.MapSequence(read1); + MappingPath path2 = mapper_.MapSequence(read2); + auto barcode = GetBarcode(std::move(r)); + if (barcode.empty()) { + TRACE("Empty barcode") + return false; + } + if (path1.size() > 0 and path2.size() > 0) { + TRACE("non-empty pair"); + } + + ProcessPairedRead(barcode, path1, path2); + return false; + } + + size_t GetNumberOfBarcodes() const { + return encoder_.size(); + } + + FrameConcurrentBuffer& GetBuffer() { + return buf_; + } + + private: + void ProcessPairedRead(const std::string &barcode_string, + const MappingPath& path1, + const MappingPath& path2) { + + BarcodeId barcode = encoder_.find_or_insert(barcode_string); + InsertMappingPath(barcode, path1); + InsertMappingPath(barcode, path2); + } + void Init() { + buf_.InitialFillMap(); + } + + std::string GetBarcode(std::unique_ptr r) { + if (not is_tellseq_) { + TRACE("Getting barcode") + auto left_barcode_string = GetTenXBarcodeFromRead(r->first().comment(), barcode_prefices_); + auto right_barcode_string = GetTenXBarcodeFromRead(r->second().comment(), barcode_prefices_); + + if (left_barcode_string.empty() or left_barcode_string != right_barcode_string) { + TRACE(left_barcode_string); + TRACE(right_barcode_string); + std::string empty; + return empty; + } + return left_barcode_string; + } else { + io::PairedRead* paired = r.get(); + return static_cast(paired)->aux().sequence().str(); + } + } + + std::string GetTenXBarcodeFromRead(const std::string &read_name, const std::vector& barcode_prefixes) { + for (const auto& prefix: barcode_prefixes) { + size_t prefix_len = prefix.size(); + size_t start_pos = read_name.find(prefix); + if (start_pos != std::string::npos) { + std::string barcode = GetBarcodeFromStartPos(start_pos + prefix_len, read_name); + TRACE(barcode); + return barcode; + } + } + return ""; + } + std::string GetBarcodeFromStartPos(const size_t start_pos, const std::string& read_id) { + std::string result = ""; + for (auto it = read_id.begin() + start_pos; it != read_id.end(); ++it) { + if (not is_nucl(*it)) { + return result; + } + result.push_back(*it); + } + return result; + } + + void InsertMappingPath(BarcodeId &barcode, const MappingPath &path) { + for (size_t i = 0; i < path.size(); i++) { + //todo restore tail threshold if needed + EdgeId edge = path[i].first; + const auto &range = path[i].second.mapped_range; + buf_.InsertBarcode(barcode, edge, 1, range); + buf_.InsertBarcode(barcode, g_.conjugate(edge), 1, range.Invert(g_.length(edge))); + } + } + + const Graph& g_; + FrameConcurrentBuffer &buf_; + const SequenceMapper &mapper_; + const std::vector barcode_prefices_; + BarcodeEncoder encoder_; + bool is_tellseq_; + + DECL_LOGGER("ConcurrentBufferFiller"); +}; + +class FrameBarcodeIndexBuilder { + public: + using EdgeId = debruijn_graph::EdgeId; + using Graph = debruijn_graph::Graph; + using SequenceMapper = debruijn_graph::SequenceMapper; + + FrameBarcodeIndexBuilder(const Graph &g, + const SequenceMapper &mapper, + const std::vector &barcode_prefices, + size_t frame_size, + size_t num_threads) : + g_(g), + mapper_(mapper), + barcode_prefices_(barcode_prefices), + frame_size_(frame_size), + num_threads_(num_threads) {} + + template + void ConstructBarcodeIndex(io::ReadStreamList read_streams, + FrameBarcodeIndex &barcode_index, + const io::SequencingLibraryBase &lib, + bool is_tellseq); + + void DownsampleBarcodeIndex(FrameBarcodeIndex &downsampled_index, FrameBarcodeIndex &original_index, double sampling_factor) { + std::unordered_set barcodes; + std::unordered_set passed_barcodes; + BarcodeId min_barcode = std::numeric_limits::max(); + BarcodeId max_barcode = std::numeric_limits::min(); + for (auto it = original_index.begin(); it != original_index.end(); ++it) { + const auto &barcode_distribution = it->second.GetDistribution(); + for (const auto &entry: barcode_distribution) { + BarcodeId current_barcode = entry.first; + barcodes.insert(current_barcode); + min_barcode = std::min(min_barcode, current_barcode); + max_barcode = std::max(max_barcode, current_barcode); + } + } + INFO("Number of encountered barcodes: " << barcodes.size()); + INFO("Barcode id range: " << min_barcode << ", " << max_barcode); + double barcode_thr = static_cast(max_barcode - min_barcode) * sampling_factor; + for (const auto &barcode: barcodes) { + if (math::le(barcode - min_barcode, barcode_thr)) { + passed_barcodes.insert(barcode); + } + } + INFO("Passed barcodes: " << passed_barcodes.size()); + + downsampled_index.InitialFillMap(); + auto barcode_filter = [&passed_barcodes](const auto &barcode_entry) { + return passed_barcodes.find(barcode_entry.first) != passed_barcodes.end(); + }; + for (auto it = original_index.begin(); it != original_index.end(); ++it) { + auto &to = downsampled_index.edge_to_entry_[it->first].barcode_distribution_; + auto &from = it->second.barcode_distribution_; + std::copy_if(std::make_move_iterator(from.begin()), std::make_move_iterator(from.end()), + std::inserter(to, to.end()), barcode_filter); + } + } + + private: + const Graph& g_; + const SequenceMapper &mapper_; + const std::vector barcode_prefices_; + size_t frame_size_; + size_t num_threads_; +}; +template +void FrameBarcodeIndexBuilder::ConstructBarcodeIndex(io::ReadStreamList read_streams, + FrameBarcodeIndex &barcode_index, + const io::SequencingLibraryBase &lib, + bool is_tellseq) { + { + size_t starting_barcode = 0; + size_t counter = 0; + barcode_index.SetFrameSize(frame_size_); + barcode_index.InitialFillMap(); + for (auto &stream: read_streams) { + DEBUG("Processing stream " << counter << " , currently " << starting_barcode << " barcodes"); + FrameConcurrentBarcodeIndexBuffer buffer(g_, frame_size_); + ConcurrentBufferFiller buffer_filler(g_, buffer, mapper_, barcode_prefices_, starting_barcode, is_tellseq); + hammer::ReadProcessor read_processor(static_cast(num_threads_)); + read_processor.Run(stream, buffer_filler); + starting_barcode += buffer_filler.GetNumberOfBarcodes(); + DEBUG("Update"); + barcode_index.Update(buffer); + DEBUG("Finished update"); + } + INFO(starting_barcode << " total barcodes in the barcode index"); + } + +} +} //namespace barcode index diff --git a/src/common/barcode_index/barcode_info_extractor.hpp b/src/common/barcode_index/barcode_info_extractor.hpp new file mode 100644 index 0000000000..1f4969c355 --- /dev/null +++ b/src/common/barcode_index/barcode_info_extractor.hpp @@ -0,0 +1,510 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2017-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "barcode_index.hpp" + +namespace barcode_index { + + /** + * BarcodeIndexInfoExtractor extracts information from BarcodeIndex + */ + template + class BarcodeIndexInfoExtractor { + public: + typedef typename BarcodeEntryT::barcode_distribution_t distribution_t; + typedef typename BarcodeEntryT::barcode_info_t barcode_info_t; + typedef typename distribution_t::key_type barcode_info_key_t; + typedef typename distribution_t::mapped_type barcode_info_value_t; + typedef typename distribution_t::value_type barcode_info_pair_t; + typedef typename barcode_index::BarcodeIndex BarcodeIndexT; + typedef typename Graph::EdgeId EdgeId; + typedef typename omnigraph::IterationHelper edge_it_helper; + protected: + const BarcodeIndexT &index_; + const Graph &g_; + public: + BarcodeIndexInfoExtractor(const BarcodeIndexT &index, const Graph &g) : + index_(index), g_(g) {} + + /** + * + * @param edge + * @return Number of barcodes contained by the edge + */ + size_t GetNumberOfBarcodes(EdgeId edge) const { + return index_.GetEntry(edge).Size(); + } + + /** + * + * @param edge1 + * @param edge2 + * @return List of barcodes shared by edge1 and edge2 + */ + std::vector GetSharedBarcodes (EdgeId edge1, EdgeId edge2) const { + std::vector intersection; + for (auto it = intersection_iterator_begin(edge1, edge2); it != intersection_iterator_end(edge1, edge2); ++it) { + intersection.push_back((*it).key_); + } + return intersection; + } + + /** + * + * @param edge1 + * @param edge2 + * @return Number of barcodes shared by edge1 and edge2 + */ + size_t GetNumberOfSharedBarcodes (EdgeId edge1, EdgeId edge2) const { + size_t result = 0; + for (auto it = intersection_iterator_begin(edge1, edge2); it != intersection_iterator_end(edge1, edge2); ++it) { + ++result; + } + return result; + } + + /** + * @param edge + * @param barcode + * @return True if the edge contains the barcode + */ + bool HasBarcode(EdgeId edge, BarcodeId barcode) const { + return index_.GetEntry(edge).HasBarcode(barcode); + } + + /** + * + * @return Average number of barcodes contained on the long edges of the graph + */ + double AverageBarcodeCoverage(size_t length_threshold) const { + edge_it_helper helper(g_); + size_t barcodes_overall = 0; + size_t long_edges = 0; + for (auto it = helper.begin(); it != helper.end(); ++it) { + if (g_.length(*it) > length_threshold) { + long_edges++; + barcodes_overall += GetNumberOfBarcodes(*it); + } + } + DEBUG("tails: " + std::to_string(barcodes_overall)); + DEBUG("Long edges" + long_edges); + return static_cast (barcodes_overall) / static_cast (long_edges); + } + + double GetIntersectionSizeNormalizedByUnion(EdgeId edge1, EdgeId edge2) const { + if (GetUnionSize(edge1, edge2)) { + return static_cast (GetNumberOfSharedBarcodes(edge1, edge2)) / + static_cast (GetUnionSize(edge1, edge2)); + } + return 0; + } + + virtual double GetIntersectionSizeNormalizedBySecond(EdgeId edge1, EdgeId edge2) const { + if (GetNumberOfBarcodes(edge2) > 0) { + return static_cast (GetNumberOfSharedBarcodes(edge1, edge2)) / + static_cast (GetNumberOfBarcodes(edge2)); + } + return 0; + } + + size_t GetUnionSize(EdgeId edge1, EdgeId edge2) const { + auto it_tail = index_.GetEntryTailsIterator(edge1); + auto it_head = index_.GetEntryHeadsIterator(edge2); + return (it_tail->second).GetUnionSize(it_head->second); + } + + std::vector GetBarcodes(EdgeId edge) const { + std::vector result; + auto copy_barcode_id = [&result](const barcode_info_pair_t& entry) + {result.push_back(entry.first); }; + std::for_each(barcode_iterator_begin(edge), barcode_iterator_end(edge), copy_barcode_id); + return result; + } + + typename distribution_t::const_iterator barcode_iterator_begin(EdgeId edge) const { + auto entry_it = index_.GetEntryHeadsIterator(edge); + return entry_it->second.begin(); + } + + typename distribution_t::const_iterator barcode_iterator_end(EdgeId edge) const { + auto entry_it = index_.GetEntryHeadsIterator(edge); + return entry_it->second.end(); + } + + /** + * Proxy class representing a pair of references to BarcodeInfo + */ + struct IntersectionData { + /** + * BarcodeId of the shared barcode + */ + const barcode_info_key_t key_; + /** + * Info corresponding to the shared barcode and the first edge + */ + const barcode_info_value_t& info_first_; + + /** + * Info corresponding to the shared barcode and the second edge + */ + const barcode_info_value_t& info_second_; + + IntersectionData(const barcode_info_key_t key, + const barcode_info_value_t& info_first, + const barcode_info_value_t& info_second) : + key_(key), info_first_(info_first), info_second_(info_second) {} + }; + + /** + * Iterator over shared barcodes of two edges. + * Dereferencing returns proxy object of type IntersectionData + * @note Since it is not an iterator over a container there is no -> operator. + */ + class const_intersection_iterator { + public: + typedef IntersectionData value_type; + typedef IntersectionData reference; + typedef IntersectionData* pointer; + typedef int difference_type; + typedef std::input_iterator_tag iterator_category; + typedef typename distribution_t::const_iterator entry_iterator; + + public: + const_intersection_iterator(entry_iterator first, entry_iterator second, + entry_iterator first_end, entry_iterator second_end) : + first_(first), second_(second), first_end_(first_end), second_end_(second_end) {} + + //todo optimize with lower bounds? + const_intersection_iterator operator++() { + if (first_ == first_end_ and second_ == second_end_) { + ++first_; + ++second_; + return *this; + } + if (get_first_key() == get_second_key()) { + if (second_ != second_end_) { + ++second_; + } else { + ++first_; + } + } + while (get_first_key() != get_second_key() and (first_ != first_end_ or second_ != second_end_)) { + while (get_first_key() < get_second_key() and first_ != first_end_) { + ++first_; + } + while (get_second_key() < get_first_key() and second_ != second_end_) { + ++second_; + } + if ((first_ == first_end_ and get_second_key() > get_first_key()) or + (second_ == second_end_ and get_first_key() > get_second_key())) { + first_ = first_end_; + second_ = second_end_; + } + } + if (get_first_key() == get_second_key()) { + return *this; + } + VERIFY(first_ == first_end_ and second_ == second_end_); + if (get_first_key() != get_second_key()) { + ++first_; + ++second_; + } + return *this; + } + + const_intersection_iterator operator++(int) { + const_intersection_iterator result = *this; + ++(*this); + return result; + } + + reference operator* () { + VERIFY(get_first_key() == get_second_key()); + return IntersectionData(get_first_key(), first_->second, second_->second); + } + + bool operator== (const const_intersection_iterator& other) { + return first_ == other.first_ and second_ == other.second_ and + first_end_ == other.first_end_ and second_end_ == other.second_end_; + } + + bool operator!= (const const_intersection_iterator& other) { + return *this != other; + } + + private: + entry_iterator first_; + entry_iterator second_; + entry_iterator first_end_; + entry_iterator second_end_; + + inline barcode_info_key_t get_first_key() { + return first_->first; + } + inline barcode_info_key_t get_second_key() { + return second_->first; + } + }; + + //todo remove end decrement? + const_intersection_iterator intersection_iterator_begin(EdgeId first, EdgeId second) const { + if (GetNumberOfBarcodes(first) == 0 or GetNumberOfBarcodes(second) == 0) { + return intersection_iterator_end(first, second); + } + auto first_begin = barcode_iterator_begin(first); + auto first_end = barcode_iterator_end(first); + auto second_begin = barcode_iterator_begin(second); + auto second_end = barcode_iterator_end(second); + const_intersection_iterator prebegin(first_begin, second_begin, --first_end, --second_end); + if (barcode_iterator_begin(first)->first == barcode_iterator_begin(second)->first) + return prebegin; + return ++prebegin; + } + + const_intersection_iterator intersection_iterator_end(EdgeId first, EdgeId second) const { + auto first_end = barcode_iterator_end(first); + auto second_end = barcode_iterator_end(second); + if (GetNumberOfBarcodes(first) == 0 or GetNumberOfBarcodes(second) == 0) { + return const_intersection_iterator(first_end, second_end, first_end, second_end); + } + auto first_end_copy = first_end; + auto second_end_copy = second_end; + const_intersection_iterator result(first_end_copy, second_end_copy, --first_end, --second_end); + return result; + } + + protected: + + /** + * + * @param edge + * @param barcode + * @return barcode info corresponding to given edge + */ + const barcode_info_t& GetInfo(EdgeId edge, BarcodeId barcode) const { + VERIFY(HasBarcode(edge, barcode)); + const BarcodeEntryT& entry = GetEntry(edge); + return entry.GetBarcode(barcode)->second; + } + + const BarcodeEntryT& GetEntry(EdgeId edge) const { + return index_.GetEntry(edge); + } + + }; + +/** + * Specialization of BarcodeIndexInfoExtractor for FrameBarcodeInfo type. + * @see FrameBarcodeInfo + */ +template +class FrameBarcodeIndexInfoExtractorTemplate : public BarcodeIndexInfoExtractor> { +public: + typedef typename Graph::EdgeId EdgeId; + typedef typename barcode_index::FrameBarcodeIndex FrameBarcodeIndexT; + + FrameBarcodeIndexInfoExtractorTemplate(const FrameBarcodeIndexT &index, const Graph &g) : + BarcodeIndexInfoExtractor>(index, g) {} + + /** + * + * @param edge + * @param barcode + * @return number of barcoded reads aligned to the edge + */ + size_t GetNumberOfReads(EdgeId edge, const BarcodeId &barcode) const { + return this->GetInfo(edge, barcode).GetCount(); + } + + /** + * + * @param edge + * @param barcode + * @return leftmost barcoded bin of the edge + */ + size_t GetLeftBin(EdgeId edge, const BarcodeId &barcode) const { + return this->GetInfo(edge, barcode).GetLeftMost(); + } + + /** + * + * @param edge + * @param barcode + * @return rightmost barcoded bin of the edge + */ + size_t GetRightBin(EdgeId edge, const BarcodeId &barcode) const { + return this->GetInfo(edge, barcode).GetRightMost(); + } + + /** + * @param edge + * @return length of the bin + */ + size_t GetBinLength(EdgeId edge) const { + return this->GetEntry(edge).GetFrameSize(); + } + + /** + * + * @param edge + * @return number of bins on the edge + */ + size_t GetNumberOfBins(EdgeId edge) const { + return this->GetEntry(edge).GetNumberOfFrames(); + } + + /** + * @param first first edge + * @param second second edge + * @param shared_threshold minimal number of barcodes shared by first and second + * @param count_threshold edge contains barcode iff there are at least count_threshold reads aligned to the edge + * @param gap_threshold clouds located at the beginning of the first or at the end of the second edge are discarded. + * Cloud is located in the beginning of the edge if it is not aligned to the last gap_threshold nucleotides of the edge. + * @return true if there are at least shared_threshold barcodes which pass requirements determined by count_threshold and gap_threshold. + */ + bool AreEnoughSharedBarcodesWithFilter (EdgeId first, + EdgeId second, + size_t shared_threshold, + size_t count_threshold, + size_t gap_threshold) const { + size_t current = 0; + for (auto it = intersection_iterator_begin(first, second); it != intersection_iterator_end(first, second); ++it) { + BarcodeId barcode = (*it).key_; + bool is_in_the_end_of_first = g_.length(first) <= gap_threshold or + GetMaxPos(first, barcode) + gap_threshold > g_.length(first); + bool is_in_the_beginning_of_second = g_.length(second) <= gap_threshold or + GetMinPos(second, barcode) < gap_threshold; + bool enough_count = (*it).info_first_.GetCount() >= count_threshold and + (*it).info_second_.GetCount() >= count_threshold; + if (is_in_the_end_of_first and is_in_the_beginning_of_second and enough_count) { + ++current; + } + if (current > shared_threshold) { + return true; + } + } + return false; + } + + /** + * @param first first edge + * @param second second edge + * @param count_threshold edge contains barcode iff there are at least count_threshold reads aligned to the edge + * @param gap_threshold clouds located at the beginning of the first or at the end of the second edge are discarded. + * Cloud is located in the beginning of the edge if it is not aligned to the last gap_threshold nucleotides of the edge. + * @return number of barcodes which pass requirements determined by count_threshold and gap_threshold. + */ + size_t CountSharedBarcodesWithFilter (EdgeId first, + EdgeId second, + size_t count_threshold, + size_t gap_threshold) const { + return GetSharedBarcodesWithFilter(first, second, count_threshold, gap_threshold).size(); + } + + std::vector GetSharedBarcodesWithFilter(EdgeId first, EdgeId second, + size_t count_threshold, size_t gap_threshold) const { + std::vector intersection; + for (auto it = this->intersection_iterator_begin(first, second); it != this->intersection_iterator_end(first, second); ++it) { + auto barcode = (*it).key_; + bool is_in_the_end_of_first = g_.length(first) <= gap_threshold or + GetMaxPos(first, barcode) + gap_threshold > g_.length(first); + bool is_in_the_beginning_of_second = g_.length(second) <= gap_threshold or + GetMinPos(second, barcode) < gap_threshold; + bool enough_count = (*it).info_first_.GetCount() >= count_threshold and + (*it).info_second_.GetCount() >= count_threshold; + if (is_in_the_end_of_first and is_in_the_beginning_of_second and enough_count) { + intersection.push_back(barcode); + } + } + return intersection; + } + + std::vector GetBarcodesFromHead(EdgeId edge, size_t count_threshold, size_t right) const { + std::vector barcodes; + size_t bin_length = GetBinLength(edge); + for (auto it = this->barcode_iterator_begin(edge); it != this->barcode_iterator_end(edge); ++it) { + BarcodeId barcode = it->first; + size_t left_pos = it->second.GetLeftMost() * bin_length; + size_t reads = it->second.GetCount(); + if (left_pos <= right and reads >= count_threshold) { + barcodes.push_back(barcode); + } + } + return barcodes; + } + + std::vector> GetBarcodesAndCountsFromHead(EdgeId edge, + size_t count_threshold, + size_t right) const { + std::vector> barcodes; + size_t bin_length = GetBinLength(edge); + for (auto it = this->barcode_iterator_begin(edge); it != this->barcode_iterator_end(edge); ++it) { + BarcodeId barcode = it->first; + size_t left_pos = it->second.GetLeftMost() * bin_length; + size_t reads = it->second.GetCount(); + if (left_pos <= right and reads >= count_threshold) { + barcodes.emplace_back(barcode, reads); + } + } + return barcodes; + }; + + std::vector GetBarcodesFromRange(EdgeId edge, size_t count_threshold, + size_t left, size_t right) const { + std::vector barcodes; + size_t bin_length = GetBinLength(edge); + for (auto it = this->barcode_iterator_begin(edge); it != this->barcode_iterator_end(edge); ++it) { + BarcodeId barcode = it->first; + size_t left_pos = it->second.GetLeftMost() * bin_length; + size_t right_pos = it->second.GetRightMost() * bin_length; + TRACE("Bin length: " << bin_length); + TRACE("Left raw: " << left_pos); + TRACE("Leftmost position: " << left_pos); + TRACE("Rightmost position: " << right_pos); + size_t reads = it->second.GetCount(); + TRACE("Reads: " << reads); + if (left_pos <= right and right_pos >= left and reads >= count_threshold) { + barcodes.push_back(barcode); + } + } + return barcodes; + } + + /** + * + * @param edge + * @param barcode + * @return Estimated first position of the cloud defined by the barcode and the edge (not the first bin, but the first nucleotide) + */ + size_t GetMinPos(EdgeId edge, BarcodeId barcode) const { + const FrameEdgeEntry &entry = this->GetEntry(edge); + const FrameBarcodeInfo& info = this->GetInfo(edge, barcode); + size_t frame_size = entry.GetFrameSize(); + return info.GetLeftMost() * frame_size; + } + + /** + * + * @param edge + * @param barcode + * @return Estimated last position of the cloud defined by the barcode and the edge (not the last bin, but the last nucleotide) + */ + size_t GetMaxPos(EdgeId edge, BarcodeId barcode) const { + const FrameEdgeEntry &entry = this->GetEntry(edge); + const FrameBarcodeInfo& info = this->GetInfo(edge, barcode); + size_t frame_size = entry.GetFrameSize(); + return info.GetRightMost() * frame_size; + } + + private: + using BarcodeIndexInfoExtractor>::g_; + +}; +typedef FrameBarcodeIndexInfoExtractorTemplate FrameBarcodeIndexInfoExtractor; +} \ No newline at end of file diff --git a/src/common/io/binary/graph_pack.cpp b/src/common/io/binary/graph_pack.cpp index a9b681201a..8f143f9110 100644 --- a/src/common/io/binary/graph_pack.cpp +++ b/src/common/io/binary/graph_pack.cpp @@ -16,6 +16,7 @@ #include "ss_coverage.hpp" #include "paired_index.hpp" #include "positions.hpp" +#include "read_cloud.hpp" #include "trusted_paths.hpp" #include "utils/stl_utils.hpp" diff --git a/src/common/io/binary/read_cloud.hpp b/src/common/io/binary/read_cloud.hpp new file mode 100644 index 0000000000..7f11ae6d4c --- /dev/null +++ b/src/common/io/binary/read_cloud.hpp @@ -0,0 +1,47 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#pragma once + +#include "io_base.hpp" +#include "barcode_index/barcode_index.hpp" +//fixme added temporarily to compile, remove later +#include "barcode_index/barcode_index_builder.hpp" +#include "barcode_index/barcode_info_extractor.hpp" + +namespace io { + +namespace binary { + +template +class BarcodeMapperIO : public IOSingle> { +public: + typedef barcode_index::FrameBarcodeIndex Type; + BarcodeMapperIO() + : IOSingle("barcode index", ".bmap") { + } + + void SaveImpl(BinOStream &str, const Type &mapper) override { + str << mapper.GetFrameSize() << mapper; + } + + void LoadImpl(BinIStream &str, Type &mapper) override { + size_t frame_size; + str >> frame_size; + mapper.SetFrameSize(frame_size); + str >> mapper; + } +}; + +template +struct IOTraits> { + typedef BarcodeMapperIO Type; +}; + +} + +} \ No newline at end of file diff --git a/src/common/library/library.cpp b/src/common/library/library.cpp index b1416d520f..0622f4b409 100644 --- a/src/common/library/library.cpp +++ b/src/common/library/library.cpp @@ -48,6 +48,7 @@ struct ScalarEnumerationTraits { io.enumCase(value, "path-extend-contigs", LibraryType::PathExtendContigs); io.enumCase(value, "fl-rna", LibraryType::FLRNAReads); io.enumCase(value, "assembly-graph", LibraryType::AssemblyGraph); + io.enumCase(value, "clouds10x", LibraryType::Clouds10x); } }; }} @@ -81,6 +82,7 @@ void SequencingLibraryBase::validate(llvm::yaml::IO &, llvm::StringRef &res) { case LibraryType::MatePairs: case LibraryType::HQMatePairs: case LibraryType::TellSeqReads: + case LibraryType::Clouds10x: if (left_paired_reads_.size() != right_paired_reads_.size()) { res = "Left and right reads lists should have equal length"; return; diff --git a/src/common/library/library.hpp b/src/common/library/library.hpp index 601afaf541..a2e497006a 100644 --- a/src/common/library/library.hpp +++ b/src/common/library/library.hpp @@ -197,7 +197,8 @@ class SequencingLibraryBase { bool is_graph_constructable() const { return type_ == io::LibraryType::PairedEnd || type_ == io::LibraryType::SingleReads || - type_ == io::LibraryType::HQMatePairs; + type_ == io::LibraryType::HQMatePairs || + type_ == io::LibraryType::Clouds10x; } bool is_bwa_alignable() const { @@ -215,7 +216,8 @@ class SequencingLibraryBase { bool is_paired() const { return type_ == io::LibraryType::PairedEnd || type_ == io::LibraryType::MatePairs || - type_ == io::LibraryType::HQMatePairs; + type_ == io::LibraryType::HQMatePairs || + type_ == io::LibraryType::Clouds10x; } bool is_single() const { diff --git a/src/common/library/library_data.cpp b/src/common/library/library_data.cpp index ba37dfcf78..4c4a8a3b3a 100644 --- a/src/common/library/library_data.cpp +++ b/src/common/library/library_data.cpp @@ -22,6 +22,10 @@ void MappingTraits::mapping(IO &io, LibraryData::B io.mapRequired("chunk num", info.chunk_num); } +void MappingTraits::mapping(IO &io, LibraryData::ReadCloudInfo &info) { + io.mapRequired("fragment length distribution", info.fragment_length_distribution); +} + void MappingTraits::mapping(IO &io, debruijn_graph::config::LibraryData &data) { io.mapRequired("unmerged read length", data.unmerged_read_length); io.mapRequired("merged read length", data.merged_read_length); @@ -38,6 +42,7 @@ void MappingTraits::mapping(IO &io, debruijn_graph::config::Library io.mapRequired("library index", data.lib_index); io.mapRequired("number of reads", data.read_count); io.mapRequired("total nucleotides", data.total_nucls); + io.mapRequired("read cloud info", data.read_cloud_info); } } } diff --git a/src/common/library/library_data.hpp b/src/common/library/library_data.hpp index 586fb7c096..2f11146426 100644 --- a/src/common/library/library_data.hpp +++ b/src/common/library/library_data.hpp @@ -55,6 +55,12 @@ struct LibraryData { size_t chunk_num = 0; } binary_reads_info; + struct ReadCloudInfo { + ReadCloudInfo() + : fragment_length_distribution() {} + std::map fragment_length_distribution; + } read_cloud_info; + void clear() { unmerged_read_length = merged_read_length = 0; mean_insert_size = insert_size_deviation @@ -68,6 +74,7 @@ struct LibraryData { total_nucls = read_count = 0; pi_threshold = 0.0; binary_reads_info = BinaryReadsInfo(); + read_cloud_info = ReadCloudInfo(); } LibraryData() { @@ -86,6 +93,11 @@ struct MappingTraits { static void mapping(IO &io, debruijn_graph::config::LibraryData::BinaryReadsInfo &info); }; +template<> +struct MappingTraits { + static void mapping(IO &io, debruijn_graph::config::LibraryData::ReadCloudInfo &info); +}; + template<> struct MappingTraits { static void mapping(IO &io, debruijn_graph::config::LibraryData &data); diff --git a/src/common/library/library_fwd.hpp b/src/common/library/library_fwd.hpp index bb63d0da36..f2e01f2015 100644 --- a/src/common/library/library_fwd.hpp +++ b/src/common/library/library_fwd.hpp @@ -26,6 +26,7 @@ enum class LibraryType { MatePairs, TrustedContigs, TSLReads, + Clouds10x, PathExtendContigs, UntrustedContigs, FLRNAReads, diff --git a/src/test/debruijn/CMakeLists.txt b/src/test/debruijn/CMakeLists.txt index bb9e6fa2fc..de33a55e0c 100644 --- a/src/test/debruijn/CMakeLists.txt +++ b/src/test/debruijn/CMakeLists.txt @@ -11,6 +11,6 @@ add_executable(debruijn_test graph_core_test.cpp histogram_test.cpp paired_info_test.cpp overlap_analysis_test.cpp simplification_test.cpp test_utils.cpp construction_test.cpp io_test.cpp path_extend_test.cpp graphio.cpp overlap_removal_test.cpp graph_alignment_test.cpp v_overlaps.cpp - test.cpp) + contracted_graph_test.cpp barcode_index.cpp test.cpp) target_link_libraries(debruijn_test common_modules input ${COMMON_LIBRARIES} graphio teamcity_gtest gtest) add_test(NAME debruijn_test COMMAND debruijn_test) diff --git a/src/test/debruijn/barcode_index.cpp b/src/test/debruijn/barcode_index.cpp new file mode 100644 index 0000000000..6fbea5664a --- /dev/null +++ b/src/test/debruijn/barcode_index.cpp @@ -0,0 +1,189 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2019-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "graphio.hpp" +#include "test_utils.hpp" +#include "barcode_index/barcode_index.hpp" +#include "barcode_index/barcode_index_builder.hpp" +#include "io/binary/read_cloud.hpp" +#include "random_graph.hpp" + +#include +#include + +using namespace debruijn_graph; +using namespace barcode_index; + +TEST(BarcodeIndex, BasicConstruction) { + size_t K = 55; + Graph graph(K); + size_t frame_size = 100; + + FrameBarcodeIndex barcode_index(graph, frame_size); + + EXPECT_EQ(barcode_index.GetFrameSize(), frame_size); + EXPECT_TRUE(barcode_index.empty()); + EXPECT_EQ(barcode_index.size(), 0); +} + +TEST(BarcodeIndex, InitialFillMap) { + size_t K = 55; + Graph graph(K); + + auto v1 = graph.AddVertex(); + auto v2 = graph.AddVertex(); + auto v3 = graph.AddVertex(); + + Sequence seq1 = RandomSequence(100); + Sequence seq2 = RandomSequence(150); + + auto e1 = graph.AddEdge(v1, v2, seq1); + auto e2 = graph.AddEdge(v2, v3, seq2); + + size_t frame_size = 50; + FrameBarcodeIndex barcode_index(graph, frame_size); + barcode_index.InitialFillMap(); + + EXPECT_FALSE(barcode_index.empty()); + EXPECT_EQ(barcode_index.size(), graph.e_size()); + EXPECT_EQ(barcode_index.GetBarcodeNumber(e1), 0); + EXPECT_EQ(barcode_index.GetBarcodeNumber(e2), 0); +} + +TEST(BarcodeIndex, EdgeEntryConstruction) { + size_t K = 55; + Graph graph(K); + auto v1 = graph.AddVertex(); + auto v2 = graph.AddVertex(); + Sequence seq = RandomSequence(200); + auto edge = graph.AddEdge(v1, v2, seq); + + size_t frame_size = 50; + size_t edge_length = graph.length(edge); + + FrameEdgeEntry entry(edge, edge_length, frame_size); + + EXPECT_EQ(entry.GetEdge(), edge); + EXPECT_EQ(entry.GetFrameSize(), frame_size); + EXPECT_EQ(entry.Size(), 0); + size_t expected_frames = edge_length / frame_size + 1; + EXPECT_EQ(entry.GetNumberOfFrames(), expected_frames); +} + +TEST(BarcodeIndex, BarcodeInfoUpdate) { + size_t num_frames = 10; + FrameBarcodeInfo info(num_frames); + + EXPECT_EQ(info.GetCount(), 0); + EXPECT_EQ(info.GetCovered(), 0); + + info.Update(3, 2, 4); + + EXPECT_EQ(info.GetCount(), 3); + EXPECT_EQ(info.GetCovered(), 3); + EXPECT_EQ(info.GetLeftMost(), 2); + EXPECT_EQ(info.GetRightMost(), 4); + + info.Update(2, 5, 7); + + EXPECT_EQ(info.GetCount(), 5); + EXPECT_EQ(info.GetCovered(), 6); + EXPECT_EQ(info.GetLeftMost(), 2); + EXPECT_EQ(info.GetRightMost(), 7); +} + +TEST(BarcodeIndex, ConcurrentBufferIO) { + size_t K = 55; + Graph graph(K); + + auto v1 = graph.AddVertex(); + auto v2 = graph.AddVertex(); + Sequence seq = RandomSequence(200); + auto edge = graph.AddEdge(v1, v2, seq); + + size_t frame_size = 50; + FrameConcurrentBarcodeIndexBuffer buffer(graph, frame_size); + buffer.InitialFillMap(); + + FrameBarcodeIndex barcode_index(graph, frame_size); + barcode_index.InitialFillMap(); + + EXPECT_EQ(buffer.GetFrameSize(), frame_size); + + BarcodeId barcode1 = 100; + BarcodeId barcode2 = 200; + Range range1(10, 60); + Range range2(80, 120); + buffer.InsertBarcode(barcode1, edge, 5, range1); + buffer.InsertBarcode(barcode2, edge, 3, range2); + + barcode_index.Update(buffer); + + std::filesystem::path bmap_file = std::filesystem::temp_directory_path() / "test.bmap"; + io::binary::BarcodeMapperIO io; + io.Save(bmap_file, barcode_index); + + FrameBarcodeIndex loaded_index(graph, 0); + io.Load(bmap_file, loaded_index); + + EXPECT_EQ(loaded_index.GetFrameSize(), frame_size); + EXPECT_EQ(loaded_index.size(), barcode_index.size()); + EXPECT_EQ(loaded_index.GetBarcodeNumber(edge), 2); +} + +TEST(BarcodeIndex, BarcodeFiltering) { + size_t K = 55; + Graph graph(K); + + auto v1 = graph.AddVertex(); + auto v2 = graph.AddVertex(); + Sequence seq = RandomSequence(200); + auto edge = graph.AddEdge(v1, v2, seq); + + size_t frame_size = 50; + FrameBarcodeIndex barcode_index(graph, frame_size); + barcode_index.InitialFillMap(); + + FrameConcurrentBarcodeIndexBuffer buffer(graph, frame_size); + buffer.InitialFillMap(); + + buffer.InsertBarcode(100, edge, 10, Range(0, 50)); + buffer.InsertBarcode(200, edge, 2, Range(60, 100)); + buffer.InsertBarcode(300, edge, 8, Range(150, 180)); + + barcode_index.Update(buffer); + + EXPECT_EQ(barcode_index.GetBarcodeNumber(edge), 3); + + size_t trimming_threshold = 5; + size_t gap_threshold = 100; + barcode_index.Filter(trimming_threshold, gap_threshold); + + EXPECT_EQ(barcode_index.GetBarcodeNumber(edge), 1); +} + +TEST(BarcodeIndex, SimpleBarcodeInfo) { + SimpleBarcodeInfo info(5, Range(10, 50)); + + EXPECT_EQ(info.GetCount(), 5); + EXPECT_EQ(info.GetRange().start_pos, 10); + EXPECT_EQ(info.GetRange().end_pos, 50); + + info.Update(3, Range(5, 60)); + + EXPECT_EQ(info.GetCount(), 8); + EXPECT_EQ(info.GetRange().start_pos, 5); + EXPECT_EQ(info.GetRange().end_pos, 60); + + SimpleBarcodeInfo other(2, Range(0, 40)); + info.Update(other); + + EXPECT_EQ(info.GetCount(), 10); + EXPECT_EQ(info.GetRange().start_pos, 0); + EXPECT_EQ(info.GetRange().end_pos, 60); +} + diff --git a/src/test/debruijn/contracted_graph_test.cpp b/src/test/debruijn/contracted_graph_test.cpp new file mode 100644 index 0000000000..ee361de4d7 --- /dev/null +++ b/src/test/debruijn/contracted_graph_test.cpp @@ -0,0 +1,146 @@ +//*************************************************************************** +//* Copyright (c) 2023-2025 SPAdes team +//* Copyright (c) 2021-2022 Saint Petersburg State University +//* All Rights Reserved +//* See file LICENSE for details. +//*************************************************************************** + +#include "auxiliary_graphs/contracted_graph/contracted_graph_helper.hpp" +#include "graphio.hpp" + +#include +#include + +using namespace debruijn_graph; + +std::shared_ptr CreateContractedGraph(const Graph& g, size_t length_threshold) { + auto length_predicate = [length_threshold, &g](EdgeId edge) { + return g.length(edge) >= length_threshold; + }; + + contracted_graph::DBGContractedGraphFactory graph_factory(g, length_predicate); + graph_factory.Construct(); + auto contracted_graph = graph_factory.GetGraph(); + + return contracted_graph; +} + +TEST(ContractedGraph, Construction) { + Graph g(55); + std::string save_path = "src/test/debruijn/graph_fragments/contracted_graph/simple_bulge"; + graphio::ScanBasicGraph(save_path, g); + EXPECT_EQ(g.size(), 8); + EXPECT_EQ(g.k(), 55); + + size_t contraction_threshold = 80; + auto contracted_graph = CreateContractedGraph(g, contraction_threshold); + + EXPECT_EQ(contracted_graph->size(), g.size()); + EXPECT_EQ(contracted_graph->CountEdges(), 10); + omnigraph::IterationHelper vertex_it_helper(g); + for (const auto& vertex: vertex_it_helper) { + EXPECT_TRUE(contracted_graph->ContainsVertex(vertex)); + } + + const size_t first_id = 132238743; + const size_t second_id = 102357497; + const size_t third_id = 243148631; + const size_t fourth_id = 170924699; + + std::map simple_vertex_map; + for (const auto& vertex: vertex_it_helper) { + simple_vertex_map.insert({vertex.int_id(), vertex}); + } + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(first_id)), 2); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(first_id)), 0); + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(second_id)), 1); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(second_id)), 2); + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(third_id)), 2); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(third_id)), 1); + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(fourth_id)), 0); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(fourth_id)), 2); + + contraction_threshold = 200; + contracted_graph = CreateContractedGraph(g, contraction_threshold); + EXPECT_EQ(contracted_graph->size(), 6); + EXPECT_EQ(contracted_graph->CountEdges(), 8); + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(first_id)), 2); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(first_id)), 0); + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(fourth_id)), 0); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(fourth_id)), 2); + std::vector out_edges; + for (const auto &edge: contracted_graph->OutgoingEdges(simple_vertex_map.at(first_id))) { + out_edges.emplace_back(edge); + } + EXPECT_EQ(out_edges.size(), 2); + out_edges.clear(); + for (const auto &edge: contracted_graph->OutgoingEdges(simple_vertex_map.at(fourth_id))) { + out_edges.emplace_back(edge); + } + EXPECT_EQ(out_edges.size(), 0); + + std::vector in_edges; + for (const auto &edge: contracted_graph->IncomingEdges(simple_vertex_map.at(first_id))) { + in_edges.emplace_back(edge); + } + EXPECT_EQ(in_edges.size(), 0); + in_edges.clear(); + for (const auto &edge: contracted_graph->IncomingEdges(simple_vertex_map.at(fourth_id))) { + in_edges.emplace_back(edge); + } + EXPECT_EQ(in_edges.size(), 2); + + contraction_threshold = 5000; + contracted_graph = CreateContractedGraph(g, contraction_threshold); + EXPECT_EQ(contracted_graph->size(), 4); + EXPECT_EQ(contracted_graph->CountEdges(), 4); + EXPECT_EQ(contracted_graph->GetOutDegree(simple_vertex_map.at(first_id)), 2); + EXPECT_EQ(contracted_graph->GetInDegree(simple_vertex_map.at(first_id)), 0); + + contraction_threshold = 25000; + contracted_graph = std::move(CreateContractedGraph(g, contraction_threshold)); + EXPECT_EQ(contracted_graph->size(), 2); + EXPECT_EQ(contracted_graph->CountEdges(), 0); +} + +TEST(ContractedGraph, Subgraph) { + typedef contracted_graph::ContractedGraphFactoryHelper ContractedGraphFactoryHelper; + Graph g(55); + std::string save_path = "./src/test/debruijn/graph_fragments/contracted_graph/simple_bulge"; + graphio::ScanBasicGraph(save_path, g); + + size_t contraction_threshold = 80; + auto contracted_graph = CreateContractedGraph(g, contraction_threshold); + + const size_t first_id = 132238743; + const size_t second_id = 102357497; + const size_t third_id = 243148631; + const size_t fourth_id = 170924699; + + omnigraph::IterationHelper vertex_it_helper(g); + + std::map vertex_map; + for (const auto& vertex: vertex_it_helper) { + vertex_map.insert({vertex.int_id(), vertex}); + } + ContractedGraphFactoryHelper helper(g); + + std::unordered_set no_fourth_subset({vertex_map.at(first_id), + vertex_map.at(second_id), + vertex_map.at(third_id)}); + auto first_subgraph = helper.ExtractContractedSubgraph(*contracted_graph, no_fourth_subset); + EXPECT_EQ(first_subgraph->size(), 3); + EXPECT_EQ(first_subgraph->CountEdges(), 3); + + std::unordered_set first_third_subset({vertex_map.at(first_id), vertex_map.at(third_id)}); + auto second_subgraph = helper.ExtractContractedSubgraph(*contracted_graph, first_third_subset); + EXPECT_EQ(second_subgraph->size(), 2); + EXPECT_EQ(second_subgraph->CountEdges(), 0); + + std::unordered_set no_third_subset({vertex_map.at(first_id), + vertex_map.at(second_id), + vertex_map.at(fourth_id)}); + auto third_subgraph = helper.ExtractContractedSubgraph(*contracted_graph, no_third_subset); + EXPECT_EQ(third_subgraph->size(), 3); + EXPECT_EQ(third_subgraph->CountEdges(), 2); +} diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.cvr b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.cvr new file mode 100644 index 0000000000..167bc99502 --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.cvr @@ -0,0 +1,11 @@ +10 +419360740 176.768502 . +419360741 176.768502 . +419388514 464.834644 . +419388515 464.834644 . +419433555 528.524995 . +419433556 528.524995 . +419434025 727.076923 . +419434026 727.076923 . +419442075 179.959408 . +419442076 179.959408 . diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.dot b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.dot new file mode 100644 index 0000000000..c2b87822aa --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.dot @@ -0,0 +1,24 @@ +digraph graph_picture { +node[fontname= ,penwidth=<1.8> ,shape= ] +vertex_102357496_102357497[label=<<TABLE BORDER="1" CELLSPACING="0" > +<TR><TD BORDER="0" PORT = "port_102357497_in" color="white" bgcolor="white" ></TD><TD BORDER="0" color="white" bgcolor="white" >102357497</TD><TD BORDER="0" PORT = "port_102357497_out" color="white" bgcolor="white" ></TD></TR> +<TR><TD BORDER="0" PORT = "port_102357496_out" color="white" bgcolor="white" ></TD><TD BORDER="0" color="white" bgcolor="white" >102357496</TD><TD BORDER="0" PORT = "port_102357496_in" color="white" bgcolor="white" ></TD></TR> +</TABLE>> ,color=<black> ,URL=</vertex/102357497.svg> ] +vertex_132238742_132238743[label=<<TABLE BORDER="1" CELLSPACING="0" > +<TR><TD BORDER="0" PORT = "port_132238743_in" color="yellow" bgcolor="yellow" ></TD><TD BORDER="0" color="yellow" bgcolor="yellow" >132238743</TD><TD BORDER="0" PORT = "port_132238743_out" color="yellow" bgcolor="yellow" ></TD></TR> +<TR><TD BORDER="0" PORT = "port_132238742_out" color="white" bgcolor="white" ></TD><TD BORDER="0" color="white" bgcolor="white" >132238742</TD><TD BORDER="0" PORT = "port_132238742_in" color="white" bgcolor="white" ></TD></TR> +</TABLE>> ,color=<black> ,URL=</vertex/132238743.svg> ] +vertex_170924698_170924699[label=<<TABLE BORDER="1" CELLSPACING="0" > +<TR><TD BORDER="0" PORT = "port_170924699_in" color="yellow" bgcolor="yellow" ></TD><TD BORDER="0" color="yellow" bgcolor="yellow" >170924699</TD><TD BORDER="0" PORT = "port_170924699_out" color="yellow" bgcolor="yellow" ></TD></TR> +<TR><TD BORDER="0" PORT = "port_170924698_out" color="white" bgcolor="white" ></TD><TD BORDER="0" color="white" bgcolor="white" >170924698</TD><TD BORDER="0" PORT = "port_170924698_in" color="white" bgcolor="white" ></TD></TR> +</TABLE>> ,color=<black> ,URL=</vertex/170924699.svg> ] +vertex_243148630_243148631[label=<<TABLE BORDER="1" CELLSPACING="0" > +<TR><TD BORDER="0" PORT = "port_243148631_in" color="white" bgcolor="white" ></TD><TD BORDER="0" color="white" bgcolor="white" >243148631</TD><TD BORDER="0" PORT = "port_243148631_out" color="white" bgcolor="white" ></TD></TR> +<TR><TD BORDER="0" PORT = "port_243148630_out" color="white" bgcolor="white" ></TD><TD BORDER="0" color="white" bgcolor="white" >243148630</TD><TD BORDER="0" PORT = "port_243148630_in" color="white" bgcolor="white" ></TD></TR> +</TABLE>> ,color=<black> ,URL=</vertex/243148631.svg> ] +vertex_243148630_243148631:port_243148631_out->vertex_170924698_170924699:port_170924699_in[label="Id 419360740 (3905)\nPositions:\nLen(cov): 3905(176.768502)" ,color=<black> ] +vertex_243148630_243148631:port_243148631_out->vertex_170924698_170924699:port_170924699_in[label="Id 419388515 (3943)\nPositions:\nLen(cov): 3943(464.834644)" ,color=<black> ] +vertex_132238742_132238743:port_132238743_out->vertex_102357496_102357497:port_102357497_in[label="Id 419433555 (20284)\nPositions:\nLen(cov): 20284(528.524995)" ,color=<black> ] +vertex_102357496_102357497:port_102357497_out->vertex_243148630_243148631:port_243148631_in[label="Id 419434025 (104)\nPositions:\nLen(cov): 104(727.076923)" ,color=<black> ] +vertex_132238742_132238743:port_132238743_out->vertex_102357496_102357497:port_102357497_in[label="Id 419442076 (19388)\nPositions:\nLen(cov): 19388(179.959408)" ,color=<black> ] +} diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.flcvr b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.flcvr new file mode 100644 index 0000000000..87d5e34fd8 --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.flcvr @@ -0,0 +1,11 @@ +10 +419360740 6909 . +419360741 5834 . +419388514 15538 . +419388515 13733 . +419433555 16557 . +419433556 13501 . +419434025 20217 . +419434026 22879 . +419442075 5129 . +419442076 6935 . diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.gid b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.gid new file mode 100644 index 0000000000..0c085a2b9f --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.gid @@ -0,0 +1 @@ +419462720 diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.grp b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.grp new file mode 100644 index 0000000000..f735ae15f5 --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.grp @@ -0,0 +1,20 @@ +8 10 +Vertex 102357496 ~ 102357497 . +Vertex 102357497 ~ 102357496 . +Vertex 132238742 ~ 132238743 . +Vertex 132238743 ~ 132238742 . +Vertex 170924698 ~ 170924699 . +Vertex 170924699 ~ 170924698 . +Vertex 243148630 ~ 243148631 . +Vertex 243148631 ~ 243148630 . + +Edge 419360740 : 243148631 -> 170924699, l = 3905 ~ 419360741 . +Edge 419360741 : 170924698 -> 243148630, l = 3905 ~ 419360740 . +Edge 419388514 : 170924698 -> 243148630, l = 3943 ~ 419388515 . +Edge 419388515 : 243148631 -> 170924699, l = 3943 ~ 419388514 . +Edge 419433555 : 132238743 -> 102357497, l = 20284 ~ 419433556 . +Edge 419433556 : 102357496 -> 132238742, l = 20284 ~ 419433555 . +Edge 419434025 : 102357497 -> 243148631, l = 104 ~ 419434026 . +Edge 419434026 : 243148630 -> 102357496, l = 104 ~ 419434025 . +Edge 419442075 : 102357496 -> 132238742, l = 19388 ~ 419442076 . +Edge 419442076 : 132238743 -> 102357497, l = 19388 ~ 419442075 . diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.pos b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.pos new file mode 100644 index 0000000000..91072269d7 --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.pos @@ -0,0 +1,11 @@ +10 +419360740 0 +419360741 0 +419388514 0 +419388515 0 +419433555 0 +419433556 0 +419434025 0 +419434026 0 +419442075 0 +419442076 0 diff --git a/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.sqn b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.sqn new file mode 100644 index 0000000000..d57ed587ca --- /dev/null +++ b/src/test/debruijn/graph_fragments/contracted_graph/simple_bulge.sqn @@ -0,0 +1,20 @@ +>419360740 +TTTACCTTCGTCACCCCATTGGGTGCCCAGTACGACGACGTTGTTACCCATTTTTTTCAAAATCACCGTTTGCTTAAAAATGGATTCTACCATCGCTTTTTCAGATATACAGCACTTTTTGACCCCAAAATATGCCAAAACCGATCACTTTTTGATCAGCCAATCGTTTTCCTCAACATGTAGTAGATAACAATGCCAGCAACCACAAGACCGCCGCCGAATCGGCGCAAAATATTATCCGGCAACTGGCTCAGGGTGGCGATCATGCGACGCCAGGCGCGCGGATAGAGCATCGGGCCCAGGCCTTCCAGGACTAAAACCAGCGCCAGTGCCAGCCAGATCGTTGAATTCATTTTTAATCCTTATAAAAGAAAACCACCGCTCCGTTAAGAGCGGTGGTTTGAATACTCAAACGAGACTGAGTTTATCGCGTTGCGTTAGTCGGCGTCTTCATATAACGGAAGAAATCGCTGTCCGGGCTGAGCACCATCACATCCTGGTTGCTCTGGAAGCTATTCTCGTAAGCACGCAGGCTACGGATAAAGGCGTAGAAGTCTGGATCCTGGCTAAACGCATCGGCGAACAGTTTCGCGGCTTCCGCATCACCTTCACCACGCAGGATACGGCCCTGACGCTCAGATTCCGCCAGCGTCTTGGTCACTTCGTAGTCCGCGGCCGCACGAAGTTTTTCCGCTTCTTCCTGACCCTGTGAACGGTGACGACGGGCTACCGCTTCACGCTCGGCGCGCATACGGTTGTAAATCGCCTCAGACACTTCCGCCGGCAGGTTGATCTGCTTAATACGCACATCCACCACTTCGATACCCAGCGCAGCCATACTGTTCGGGTTGATTACAGGCACTTTACCATTGGTTTCAGCCTGAACACGTTCCGCCGCTTTAGCAATTGCATCGTCCGCTGCTGGCGTTTCAACTTCGTCTTCCGTACCCGCGGTGCCGGAGTTCAGCGCATCGCGCACTTCCAGCGTCAGACGACCACGAGAGTCGGTCACGATGTCTTTCACATCCAGACGACCAATTTCAGAACGCAGACGGTCAGAGAATTTACGTTTCAACAGCACTTCCGCCTGAGAAACATCACCGCCGCCCGTTGCCAGGAAGTAACGGCTGAAATCACTGATACGCCACTTGATATAAGAGTCAACGATCAGGTCTTTCTTCTCTTTAGTCACGAAACGGTCGGCCTGGTTATCCATGGTCTGGATACGCGCATCAAGCGTCTTCACTGACTGGATAAAAGGAACCTTGAAGTGCAGACCCGGCTCATAAATCACCGGACGCTTGTCACTGTCACGGACGACGCTGCTGAACTGGAACTTAATCCCGCGCTCGCCCTCTTTCACCACAAAGATAGAGGTATAAAGTACGACCAGTACGATGACGATGATCGCAATAACTGACTTACGCATCCTTATTCCCCCTGACGCTGGTAGTCGTTACGCTGCGCGTTAGCACGGCGTTGGTCCATAATGTCACCATCGTTCGAAGAAGGCGTGGTTGTTGCGCTGGAGCTACCGGACGATGCAGGTGGCAGACGCAGCAGGTTATTCGCACCGCTGTTGTCTTTTGCTGCCGGTGCAGAACCGCCTTTCAGCATCTGATCCAGCGGCAGTACCATCAGGTTTCCACCTTTGCTGTCGTTAACCAGCACTTTACGTGTATGGCTCAGCACTTTTTCCATGGTTTCGATATAGAGACGCTCGCGGGTAATTTCCGGAGCCGCTTTATATTCCGGCAGGATTTTCGCGAAACGAGCCACCTCACCCTGCGCTTCCAGGATGGTCTGGGTCTTATACGCGCGTGCTTCTTCAAGAATACGCTGCGCCTGACCGTTAGCACGTGGCTGAACTTCGTTGGCGTACGCTTCCGCTTCACGGATGTACTGCTGTTCGTTCTCACGCGCGGCAATCGCGTCATCAAACGCGGCTTTCACCTCTTCCGGCGGACGAGCAGCCTGGAAGTTGACGTCCAGCAGGGTGATACCCATGTTGTACGGACGAATGGTCTCTTCCAGCTCACGCTGTGTATCGCTACGAATAACGGTACGACCTTCAGTCAGAATGCGGTCCATGGTGTATTTACCGATCACACCACGCAGGGCGCTGTCGGTCGCCTGACGCAGACTGTCATCGGCACTGGTTACGCTAAACAGATAACGTTCTGGATCCGTAACACGATATTGCACGTTCATCTCAACGCGCACTACGTTCTCATCAGAGGTCAGCATCACGCCGGAAGCAGCCAGCTCACGCACCGACTCCACGTTCACTGCAGTGACGTCGTCAATGAAGGTCGGTTTCCAGTTCAGGCCCGGCTCAACCAGATGGCTGAACTTACCAAAACGGGTGACCACGCCGCGCTCGGCTTCTTTAATGGTGTAGAACCCGCTGGCAGCCCAGATGATGACCACAGCAGCGGCCACAATGCCCACGATGCGACCACCCATTTGCGGGCGCGGGCCCTGGGTAGAATTGCCACCCGAGCCAGACCCTTTTCCTCCACCAAGCCCACCAAGCTTCTTGCTTAGCTTGCGGAAGATATCATCCAGATCCGGCGGCCCCTGATCGCGACCACCTTTGTTGCCATTTCCCCCAGAGTTGCCGCCTTGATTATTGCTGCTTCCCCACGGGTCGCGGTCCTGTCCGTTATTACCGGGCTGATTCCACGCCATGTATATGCTCCATATTTGTTATGCAAGGGCGAATTATTCAGGCATCCCCTTTCCGATCAGACGATATAGTCGACCAGCGCAGGTTCTTGTTTACAGAGGCGACGCCAGTCAACGATCGGCATACGCACCTGCATCCCCACGCTGCCGTCATCCTCCATCCACTCTTTTTCTATCGCCTGAAGCTGATAAAACCGGCTGCGCAGCCTGCCTTCCTGTGGTGGCAGTCGCAGCGTGTGCTGGGCTACCTCACCGGAAAGACGTTCTGTCAAAGCCTGGAAAAGCAGTGGCACGCCAATACCGGTCTGGGCGGAAAGCCAGACCCGAATTGGTTTGTTTTCTTCATCACGATCGATACGCGGCTCAAAATCATCCAGCATGTCGATCTTGTTCATCACCAACAGCGTTGGGATCTCGTGGGCCTCGATCTCTTCGAGCACCACATTCACCGCGTCGATGTTTTCCTGCACGCGAACATCTGCAGCATCAATCACGTGCAGCAGCAGGGTCGCCTGACGCGTCTCCTGCAGGGTGGCTTTAAACGCGGCCACCAGATCATGCGGCAGGTGGCGGATAAACCCTACGGTATCCGCCAGCACGGTTTCACCCACATCCGCCACGTCGATACGACGCAACGTCGGGTCCAGGGTCGCAAACAGCTGGTCTGCGGCATAGACCTGGGCCTCGGTAATCTGGTTAAACAGGGTGGATTTACCGGCGTTGGTATACCCCACCAGCGACACCGTCGGGATGTCGGCTTTCGTACGCGCCCGACGTCCCTGCTCACGCTGTTTCTCGACTCTTTCCAGACGAGAGAGGATCTGAGTAATACGGCCGCGCAGCAAACGGCGGTCGGTTTCGAGCTGGGTTTCACCCGGACCGCGCAAACCAATCCCGCCTTTTTGTCGTTCAAGGTGGGTCCAGCCACGTACAAGACGCGTGGCCAGATGGCGCAACTGCGCCAGCTCAACCTGCAGCTTACCCTCGTGGGTACGTGCACGCTGAGCAAAAATATCTAAAATCAACCCCGTGCGATCGATAACACGGCATTCGCAAAGCGCTTCCAGGTTACGCTCCTGAGCCGGAGACAGCGCATGATCAAACAACACGACTGAAGCACCGGTTGCTTTTACGGCATCCGCAATTTCTACTGCTTTACCTTCACCAACAAAATACTTTGGGTGCGGCGCTTTACGGCTACCGGTAATCACCTGCATTGCTTCGACACCGGCGGAAGAGACCAGAGATTCAAACTCCTGGAGGTCTTCCATA +>419360741 +TATGGAAGACCTCCAGGAGTTTGAATCTCTGGTCTCTTCCGCCGGTGTCGAAGCAATGCAGGTGATTACCGGTAGCCGTAAAGCGCCGCACCCAAAGTATTTTGTTGGTGAAGGTAAAGCAGTAGAAATTGCGGATGCCGTAAAAGCAACCGGTGCTTCAGTCGTGTTGTTTGATCATGCGCTGTCTCCGGCTCAGGAGCGTAACCTGGAAGCGCTTTGCGAATGCCGTGTTATCGATCGCACGGGGTTGATTTTAGATATTTTTGCTCAGCGTGCACGTACCCACGAGGGTAAGCTGCAGGTTGAGCTGGCGCAGTTGCGCCATCTGGCCACGCGTCTTGTACGTGGCTGGACCCACCTTGAACGACAAAAAGGCGGGATTGGTTTGCGCGGTCCGGGTGAAACCCAGCTCGAAACCGACCGCCGTTTGCTGCGCGGCCGTATTACTCAGATCCTCTCTCGTCTGGAAAGAGTCGAGAAACAGCGTGAGCAGGGACGTCGGGCGCGTACGAAAGCCGACATCCCGACGGTGTCGCTGGTGGGGTATACCAACGCCGGTAAATCCACCCTGTTTAACCAGATTACCGAGGCCCAGGTCTATGCCGCAGACCAGCTGTTTGCGACCCTGGACCCGACGTTGCGTCGTATCGACGTGGCGGATGTGGGTGAAACCGTGCTGGCGGATACCGTAGGGTTTATCCGCCACCTGCCGCATGATCTGGTGGCCGCGTTTAAAGCCACCCTGCAGGAGACGCGTCAGGCGACCCTGCTGCTGCACGTGATTGATGCTGCAGATGTTCGCGTGCAGGAAAACATCGACGCGGTGAATGTGGTGCTCGAAGAGATCGAGGCCCACGAGATCCCAACGCTGTTGGTGATGAACAAGATCGACATGCTGGATGATTTTGAGCCGCGTATCGATCGTGATGAAGAAAACAAACCAATTCGGGTCTGGCTTTCCGCCCAGACCGGTATTGGCGTGCCACTGCTTTTCCAGGCTTTGACAGAACGTCTTTCCGGTGAGGTAGCCCAGCACACGCTGCGACTGCCACCACAGGAAGGCAGGCTGCGCAGCCGGTTTTATCAGCTTCAGGCGATAGAAAAAGAGTGGATGGAGGATGACGGCAGCGTGGGGATGCAGGTGCGTATGCCGATCGTTGACTGGCGTCGCCTCTGTAAACAAGAACCTGCGCTGGTCGACTATATCGTCTGATCGGAAAGGGGATGCCTGAATAATTCGCCCTTGCATAACAAATATGGAGCATATACATGGCGTGGAATCAGCCCGGTAATAACGGACAGGACCGCGACCCGTGGGGAAGCAGCAATAATCAAGGCGGCAACTCTGGGGGAAATGGCAACAAAGGTGGTCGCGATCAGGGGCCGCCGGATCTGGATGATATCTTCCGCAAGCTAAGCAAGAAGCTTGGTGGGCTTGGTGGAGGAAAAGGGTCTGGCTCGGGTGGCAATTCTACCCAGGGCCCGCGCCCGCAAATGGGTGGTCGCATCGTGGGCATTGTGGCCGCTGCTGTGGTCATCATCTGGGCTGCCAGCGGGTTCTACACCATTAAAGAAGCCGAGCGCGGCGTGGTCACCCGTTTTGGTAAGTTCAGCCATCTGGTTGAGCCGGGCCTGAACTGGAAACCGACCTTCATTGACGACGTCACTGCAGTGAACGTGGAGTCGGTGCGTGAGCTGGCTGCTTCCGGCGTGATGCTGACCTCTGATGAGAACGTAGTGCGCGTTGAGATGAACGTGCAATATCGTGTTACGGATCCAGAACGTTATCTGTTTAGCGTAACCAGTGCCGATGACAGTCTGCGTCAGGCGACCGACAGCGCCCTGCGTGGTGTGATCGGTAAATACACCATGGACCGCATTCTGACTGAAGGTCGTACCGTTATTCGTAGCGATACACAGCGTGAGCTGGAAGAGACCATTCGTCCGTACAACATGGGTATCACCCTGCTGGACGTCAACTTCCAGGCTGCTCGTCCGCCGGAAGAGGTGAAAGCCGCGTTTGATGACGCGATTGCCGCGCGTGAGAACGAACAGCAGTACATCCGTGAAGCGGAAGCGTACGCCAACGAAGTTCAGCCACGTGCTAACGGTCAGGCGCAGCGTATTCTTGAAGAAGCACGCGCGTATAAGACCCAGACCATCCTGGAAGCGCAGGGTGAGGTGGCTCGTTTCGCGAAAATCCTGCCGGAATATAAAGCGGCTCCGGAAATTACCCGCGAGCGTCTCTATATCGAAACCATGGAAAAAGTGCTGAGCCATACACGTAAAGTGCTGGTTAACGACAGCAAAGGTGGAAACCTGATGGTACTGCCGCTGGATCAGATGCTGAAAGGCGGTTCTGCACCGGCAGCAAAAGACAACAGCGGTGCGAATAACCTGCTGCGTCTGCCACCTGCATCGTCCGGTAGCTCCAGCGCAACAACCACGCCTTCTTCGAACGATGGTGACATTATGGACCAACGCCGTGCTAACGCGCAGCGTAACGACTACCAGCGTCAGGGGGAATAAGGATGCGTAAGTCAGTTATTGCGATCATCGTCATCGTACTGGTCGTACTTTATACCTCTATCTTTGTGGTGAAAGAGGGCGAGCGCGGGATTAAGTTCCAGTTCAGCAGCGTCGTCCGTGACAGTGACAAGCGTCCGGTGATTTATGAGCCGGGTCTGCACTTCAAGGTTCCTTTTATCCAGTCAGTGAAGACGCTTGATGCGCGTATCCAGACCATGGATAACCAGGCCGACCGTTTCGTGACTAAAGAGAAGAAAGACCTGATCGTTGACTCTTATATCAAGTGGCGTATCAGTGATTTCAGCCGTTACTTCCTGGCAACGGGCGGCGGTGATGTTTCTCAGGCGGAAGTGCTGTTGAAACGTAAATTCTCTGACCGTCTGCGTTCTGAAATTGGTCGTCTGGATGTGAAAGACATCGTGACCGACTCTCGTGGTCGTCTGACGCTGGAAGTGCGCGATGCGCTGAACTCCGGCACCGCGGGTACGGAAGACGAAGTTGAAACGCCAGCAGCGGACGATGCAATTGCTAAAGCGGCGGAACGTGTTCAGGCTGAAACCAATGGTAAAGTGCCTGTAATCAACCCGAACAGTATGGCTGCGCTGGGTATCGAAGTGGTGGATGTGCGTATTAAGCAGATCAACCTGCCGGCGGAAGTGTCTGAGGCGATTTACAACCGTATGCGCGCCGAGCGTGAAGCGGTAGCCCGTCGTCACCGTTCACAGGGTCAGGAAGAAGCGGAAAAACTTCGTGCGGCCGCGGACTACGAAGTGACCAAGACGCTGGCGGAATCTGAGCGTCAGGGCCGTATCCTGCGTGGTGAAGGTGATGCGGAAGCCGCGAAACTGTTCGCCGATGCGTTTAGCCAGGATCCAGACTTCTACGCCTTTATCCGTAGCCTGCGTGCTTACGAGAATAGCTTCCAGAGCAACCAGGATGTGATGGTGCTCAGCCCGGACAGCGATTTCTTCCGTTATATGAAGACGCCGACTAACGCAACGCGATAAACTCAGTCTCGTTTGAGTATTCAAACCACCGCTCTTAACGGAGCGGTGGTTTTCTTTTATAAGGATTAAAAATGAATTCAACGATCTGGCTGGCACTGGCGCTGGTTTTAGTCCTGGAAGGCCTGGGCCCGATGCTCTATCCGCGCGCCTGGCGTCGCATGATCGCCACCCTGAGCCAGTTGCCGGATAATATTTTGCGCCGATTCGGCGGCGGTCTTGTGGTTGCTGGCATTGTTATCTACTACATGTTGAGGAAAACGATTGGCTGATCAAAAAGTGATCGGTTTTGGCATATTTTGGGGTCAAAAAGTGCTGTATATCTGAAAAAGCGATGGTAGAATCCATTTTTAAGCAAACGGTGATTTTGAAAAAAATGGGTAACAACGTCGTCGTACTGGGCACCCAATGGGGTGACGAAGGTAAA +>419388514 +TATGGAAGACCTCCAGGAGTTTGAATCTCTGGTCTCTTCCGCCGGTGTCGAAGCATTGCAGGTGATTACCGGTAGCCGTAAAGCGCCGCACCCAAAGTATTTTGTAGGTGAAGGTAAAGCAGTTGAAATTGCGGAAGCTGTCAAAGCGACGGGTGCTTCGGTCGTTCTTTTTGACCATGCCCTGAGCCCGGCGCAAGAGCGTAACCTGGAGCGTTTGTGCGAGTGTCGTGTTATCGACCGCACCGGCCTTATTTTAGATATTTTCGCCCAACGTGCGCGTACCCATGAGGGTAAGTTGCAGGTTGAGCTGGCGCAGCTGCGCCATCTGGCTACGCGCCTGGTGCGTGGCTGGACCCACCTTGAAAGACAGAAAGGCGGGATAGGTTTGCGTGGTCCGGGTGAAACCCAGCTCGAAACCGACCGTCGTTTGTTGCGTAATCGCATCGTGCAGATACAGTCGCGCCTGGAAAGAGTTGAAAAGCAGCGTGAGCAGGGGCGGCAATCGCGTATCAAAGCCGACGTTCCTACTGTTTCGCTGGTGGGATATACCAACGCCGGTAAATCTACCCTTTTCAATCGCATCACCGAAGCGCGGGTCTACGCGGCAGACCAGTTGTTTGCCACCCTCGACCCGACGTTGCGGCGTATTGACGTTGCAGATGTCGGTGAAACCGTACTTGCAGATACCGTAGGGTTTATTCGCCACCTGCCGCACGATCTGGTGGCGGCATTTAAAGCCACGTTACAAGAGACGCGGCAAGCCACATTACTGCTGCACGTCATTGATGCGGCGGATGTGCGTGTACAAGAAAACATCGAAGCGGTGAATACGGTTCTTGAAGAGATCGACGCTCACGAGATCCCAACCCTGCTGGTGATGAACAAGATCGATATGCTGGAAGATTTCGAACCGCGTATTGATCGGGACGAAGAGAACAAACCGAACCGTGTCTGGCTTTCCGCACAGACCGGAGCGGGGATACCACAGCTTTTTCAGGCTTTGACGGAGCGGCTTTCCGGCGAGGTGGCGCAGCATACATTGCGTCTGCCACCGCAGGAAGGGCGTCTGAGAAGTCGTTTTTATCAGCTTCAGGCAATAGAAAAAGAGTGGATGGAGGAGGACGGCAGCGTAAGTCTGCAAGTTCGTATGCCGATCGTTGACTGGCGTCGCCTCTGTAAACAAGAACCGGCGTTGATCGATTACCTGATCTAACGGCGTAGCGTCTGAAGCGTGGAGTCATATCCTCTGGCGTCGAAAGACAACAGGGATCACCGCATAACAAATATGGAGCACAAACATGGCGTGGAATCAGCCCGGTAATAACGGACAAGACCGCGACCCGTGGGGAAGCAGCAAACCTGGCGGCAACTCTGAGGGAAATGGAAACAAAGGCGGTCGCGATCAAGGGCCACCTGATTTAGATGATATCTTCCGCAAACTGAGCAAAAAGCTCGGTGGTCTGGGCGGCGGTAAAGGCACCGGATCTGGCGGTGGCAGTTCATCGCAAGGCCCGCGCCCGCAGCTTGGCGGTCGTGTCGTTACCATCGCAGCGGCAGCGATTGTCATTATCTGGGCGGCCAGTGGTTTCTATACCATTAAAGAAGCCGAACGCGGCGTGGTAACACGCTTTGGTAAATTCAGCCATCTGGTTGAGCCGGGTCTGAACTGGAAACCGACGTTTATCGACGAAGTCAAACCGGTGAACGTGGAAGCCGTGCGTGAACTGGCCGCTTCTGGTGTGATGCTGACGTCGGACGAGAACGTAGTGCGCGTTGAGATGAACGTGCAGTACCGCGTCACCAATCCGGAAAAATATCTGTATAGCGTGACCAGCCCGGATGACAGCCTGCGTCAGGCTACCGACAGCGCCCTGCGTGGAGTTATCGGTAAATACACCATGGACCGCATTCTGACGGAAGGTCGTACCGTGATTCGTAGCGATACTCAGCGCGAACTGGAAGAGACGATTCGTCCGTATGACATGGGTATCACGCTGCTGGACGTCAACTTCCAGGCTGCTCGTCCGCCGGAAGAAGTAAAAGCGGCGTTTGACGATGCGATTGCCGCGCGTGAAAACGAACAGCAATACATTCGTGAAGCAGAAGCGTATACCAACGAAGTTCAGCCGCGTGCGAACGGTCAGGCGCAACGTATCCTCGAAGAGGCGCGTGCGTACAAGGCCCAGACCATCCTGGAAGCTCAGGGTGAAGTGGCGCGCTTTGCTAAACTTCTGCCGGAATATAAAGCCGCGCCGGAAATTACTCGCGAGCGTCTGTATATCGAGACGATGGAAAAAGTGTTGGGTAACACCCGCAAAGTGCTGGTTAACGATAAAGGTGGCAACCTGATGGTTCTGCCGTTAGACCAGATGCTGAAAGGTGGTAACGCCCCTGCGGCGAAGAGCGATAACGGTGCCAGCAATCTGCTGCGTCTGCCGCCAGCCTCTTCCTCCACAACCAGTGGAGCAAGCAACACGTCGTCCACCAGTCAGGGCGATATTATGGACCAACGCCGCGCCAACGCGCAGCGTAACGACTACCAGCGTCAGGGGGAATAACGATGCGTAAGTCAGTTATCGCGATTATCATCATCGTGCTGGTAGTGCTTTACATGTCTGTCTTTGTCGTCAAAGAAGGTGAGCGCGGTATTACGCTGCGTTTTGGTAAGGTACTGCGTGACGATGACAACAAACCTCTGGTTTATGAGCCGGGTCTGCATTTCAAGATACCGTTCATTGAAACGGTGAAAATGCTCGACGCACGTATTCAGACCATGGACAACCAGGCCGACCGCTTTGTGACCAAAGAGAAGAAAGACCTGATCGTCGACTCTTACATCAAATGGCGCATCAGCGATTTCAGCCGTTACTACCTGGCAACGGGTGGTGGCGACATTTCGCAAGCGGAAGTGCTGTTGAAACGTAAGTTCTCTGACCGTCTGCGTTCTGAAATTGGTCGCCTGGACGTGAAAGATATCGTCACCGATTCCCGTGGTCGTCTGACCCTCGAAGTACGTGACGCGCTGAACTCCGGTTCTGCGGGTACAGAAGATGAAGTTACTACCCCGGCGGCAGATAACGCCATTGCCGAAGCGGCAGAGCGCGTAACGGCTGAGACGAAGGGCAAAGTTCCGGTCATCAACCCGAACAGTATGGCGGCGCTGGGTATTGAAGTTGTCGATGTGCGTATCAAGCAGATCAACCTGCCGACCGAAGTGTCTGAAGCGATCTACAACCGTATGCGCGCCGAGCGTGAAGCGGTAGCGCGTCGTCACCGTTCACAAGGTCAGGAAGAAGCGGAAAAACTGCGCGCGACTGCCGACTATGAAGTGACCAGAACGCTGGCAGAAGCTGAGCGTCAGGGCCGCATCATGCGTGGTGAAGGCGATGCCGAAGCAGCCAAACTGTTTGCTGATGCATTCAGTAAAGATCCGGACTTCTACGCATTCATCCGTAGCCTGCGTGCTTATGAGAACAGCTTCTCTGGCAATCAGGACGTGATGGTCATGAGCCCGGATAGCGATTTCTTCCGCTACATGAAGACGCCGACTTCCGCAACGCGTTAATATAACGACTGCGGTACAGGTCAATAAAGCCACCGCATCCTCAGGGATGTCGGTGGTTTTCTTTTTCTATAAGGATAATGAATGAATTCGACAATCTGGCTGGCGCTTGCCCTGGTTTTGGTACTGGAAGGTTTAGGGCCGATGCTTTACCCGAAGGCATGGAAGAAGATGATCTCTGCGATGACCAATTTGCCCGATAATATTTTACGTCGTTTTGGCGGTGGACTTGTGGTTGCGGGCGTTGTGGTCTACTACATGTTGAGGAAAACGATTGGCTGAACAAAAAACAGACTGATCGAGGTCATTTTTGAGTGCAAAAAGTGCTGTAACTCTGAAAAAGCGATGGTAGAATCCATTTTTAAGCAAACGGTGATTTTGAAAAATGGGTAACAACGTCGTCGTACTGGGCACCCAATGGGGTGACGAAGGTAAA +>419388515 +TTTACCTTCGTCACCCCATTGGGTGCCCAGTACGACGACGTTGTTACCCATTTTTCAAAATCACCGTTTGCTTAAAAATGGATTCTACCATCGCTTTTTCAGAGTTACAGCACTTTTTGCACTCAAAAATGACCTCGATCAGTCTGTTTTTTGTTCAGCCAATCGTTTTCCTCAACATGTAGTAGACCACAACGCCCGCAACCACAAGTCCACCGCCAAAACGACGTAAAATATTATCGGGCAAATTGGTCATCGCAGAGATCATCTTCTTCCATGCCTTCGGGTAAAGCATCGGCCCTAAACCTTCCAGTACCAAAACCAGGGCAAGCGCCAGCCAGATTGTCGAATTCATTCATTATCCTTATAGAAAAAGAAAACCACCGACATCCCTGAGGATGCGGTGGCTTTATTGACCTGTACCGCAGTCGTTATATTAACGCGTTGCGGAAGTCGGCGTCTTCATGTAGCGGAAGAAATCGCTATCCGGGCTCATGACCATCACGTCCTGATTGCCAGAGAAGCTGTTCTCATAAGCACGCAGGCTACGGATGAATGCGTAGAAGTCCGGATCTTTACTGAATGCATCAGCAAACAGTTTGGCTGCTTCGGCATCGCCTTCACCACGCATGATGCGGCCCTGACGCTCAGCTTCTGCCAGCGTTCTGGTCACTTCATAGTCGGCAGTCGCGCGCAGTTTTTCCGCTTCTTCCTGACCTTGTGAACGGTGACGACGCGCTACCGCTTCACGCTCGGCGCGCATACGGTTGTAGATCGCTTCAGACACTTCGGTCGGCAGGTTGATCTGCTTGATACGCACATCGACAACTTCAATACCCAGCGCCGCCATACTGTTCGGGTTGATGACCGGAACTTTGCCCTTCGTCTCAGCCGTTACGCGCTCTGCCGCTTCGGCAATGGCGTTATCTGCCGCCGGGGTAGTAACTTCATCTTCTGTACCCGCAGAACCGGAGTTCAGCGCGTCACGTACTTCGAGGGTCAGACGACCACGGGAATCGGTGACGATATCTTTCACGTCCAGGCGACCAATTTCAGAACGCAGACGGTCAGAGAACTTACGTTTCAACAGCACTTCCGCTTGCGAAATGTCGCCACCACCCGTTGCCAGGTAGTAACGGCTGAAATCGCTGATGCGCCATTTGATGTAAGAGTCGACGATCAGGTCTTTCTTCTCTTTGGTCACAAAGCGGTCGGCCTGGTTGTCCATGGTCTGAATACGTGCGTCGAGCATTTTCACCGTTTCAATGAACGGTATCTTGAAATGCAGACCCGGCTCATAAACCAGAGGTTTGTTGTCATCGTCACGCAGTACCTTACCAAAACGCAGCGTAATACCGCGCTCACCTTCTTTGACGACAAAGACAGACATGTAAAGCACTACCAGCACGATGATGATAATCGCGATAACTGACTTACGCATCGTTATTCCCCCTGACGCTGGTAGTCGTTACGCTGCGCGTTGGCGCGGCGTTGGTCCATAATATCGCCCTGACTGGTGGACGACGTGTTGCTTGCTCCACTGGTTGTGGAGGAAGAGGCTGGCGGCAGACGCAGCAGATTGCTGGCACCGTTATCGCTCTTCGCCGCAGGGGCGTTACCACCTTTCAGCATCTGGTCTAACGGCAGAACCATCAGGTTGCCACCTTTATCGTTAACCAGCACTTTGCGGGTGTTACCCAACACTTTTTCCATCGTCTCGATATACAGACGCTCGCGAGTAATTTCCGGCGCGGCTTTATATTCCGGCAGAAGTTTAGCAAAGCGCGCCACTTCACCCTGAGCTTCCAGGATGGTCTGGGCCTTGTACGCACGCGCCTCTTCGAGGATACGTTGCGCCTGACCGTTCGCACGCGGCTGAACTTCGTTGGTATACGCTTCTGCTTCACGAATGTATTGCTGTTCGTTTTCACGCGCGGCAATCGCATCGTCAAACGCCGCTTTTACTTCTTCCGGCGGACGAGCAGCCTGGAAGTTGACGTCCAGCAGCGTGATACCCATGTCATACGGACGAATCGTCTCTTCCAGTTCGCGCTGAGTATCGCTACGAATCACGGTACGACCTTCCGTCAGAATGCGGTCCATGGTGTATTTACCGATAACTCCACGCAGGGCGCTGTCGGTAGCCTGACGCAGGCTGTCATCCGGGCTGGTCACGCTATACAGATATTTTTCCGGATTGGTGACGCGGTACTGCACGTTCATCTCAACGCGCACTACGTTCTCGTCCGACGTCAGCATCACACCAGAAGCGGCCAGTTCACGCACGGCTTCCACGTTCACCGGTTTGACTTCGTCGATAAACGTCGGTTTCCAGTTCAGACCCGGCTCAACCAGATGGCTGAATTTACCAAAGCGTGTTACCACGCCGCGTTCGGCTTCTTTAATGGTATAGAAACCACTGGCCGCCCAGATAATGACAATCGCTGCCGCTGCGATGGTAACGACACGACCGCCAAGCTGCGGGCGCGGGCCTTGCGATGAACTGCCACCGCCAGATCCGGTGCCTTTACCGCCGCCCAGACCACCGAGCTTTTTGCTCAGTTTGCGGAAGATATCATCTAAATCAGGTGGCCCTTGATCGCGACCGCCTTTGTTTCCATTTCCCTCAGAGTTGCCGCCAGGTTTGCTGCTTCCCCACGGGTCGCGGTCTTGTCCGTTATTACCGGGCTGATTCCACGCCATGTTTGTGCTCCATATTTGTTATGCGGTGATCCCTGTTGTCTTTCGACGCCAGAGGATATGACTCCACGCTTCAGACGCTACGCCGTTAGATCAGGTAATCGATCAACGCCGGTTCTTGTTTACAGAGGCGACGCCAGTCAACGATCGGCATACGAACTTGCAGACTTACGCTGCCGTCCTCCTCCATCCACTCTTTTTCTATTGCCTGAAGCTGATAAAAACGACTTCTCAGACGCCCTTCCTGCGGTGGCAGACGCAATGTATGCTGCGCCACCTCGCCGGAAAGCCGCTCCGTCAAAGCCTGAAAAAGCTGTGGTATCCCCGCTCCGGTCTGTGCGGAAAGCCAGACACGGTTCGGTTTGTTCTCTTCGTCCCGATCAATACGCGGTTCGAAATCTTCCAGCATATCGATCTTGTTCATCACCAGCAGGGTTGGGATCTCGTGAGCGTCGATCTCTTCAAGAACCGTATTCACCGCTTCGATGTTTTCTTGTACACGCACATCCGCCGCATCAATGACGTGCAGCAGTAATGTGGCTTGCCGCGTCTCTTGTAACGTGGCTTTAAATGCCGCCACCAGATCGTGCGGCAGGTGGCGAATAAACCCTACGGTATCTGCAAGTACGGTTTCACCGACATCTGCAACGTCAATACGCCGCAACGTCGGGTCGAGGGTGGCAAACAACTGGTCTGCCGCGTAGACCCGCGCTTCGGTGATGCGATTGAAAAGGGTAGATTTACCGGCGTTGGTATATCCCACCAGCGAAACAGTAGGAACGTCGGCTTTGATACGCGATTGCCGCCCCTGCTCACGCTGCTTTTCAACTCTTTCCAGGCGCGACTGTATCTGCACGATGCGATTACGCAACAAACGACGGTCGGTTTCGAGCTGGGTTTCACCCGGACCACGCAAACCTATCCCGCCTTTCTGTCTTTCAAGGTGGGTCCAGCCACGCACCAGGCGCGTAGCCAGATGGCGCAGCTGCGCCAGCTCAACCTGCAACTTACCCTCATGGGTACGCGCACGTTGGGCGAAAATATCTAAAATAAGGCCGGTGCGGTCGATAACACGACACTCGCACAAACGCTCCAGGTTACGCTCTTGCGCCGGGCTCAGGGCATGGTCAAAAAGAACGACCGAAGCACCCGTCGCTTTGACAGCTTCCGCAATTTCAACTGCTTTACCTTCACCTACAAAATACTTTGGGTGCGGCGCTTTACGGCTACCGGTAATCACCTGCAATGCTTCGACACCGGCGGAAGAGACCAGAGATTCAAACTCCTGGAGGTCTTCCATA +>419433555 +TGACGCATCGAATTGCTCCTTACGGATTATTCAGCCTCCTGTCTGGGTCAGCCGAATCCCGGGGAGGCAAGGAACGTGTTAAAGGTCGGCTGAAAAATGACGCGTTATAGTACTTGTATGCCTCGCTAAACTCAAGGGCAGAGCCGAAATAAATCTCCCCTTTCGCAATTAACCTCTAACACGCTGATTTGAAGTTCATCACACTTCATCATGGTGTTTTTTTGAACAACTGCATCAGAAATGGTCACCATCAACTTCTTTATCATTGATTAAAATTAAATCAGAAGATCATCACAGAGGAGAGCACACAAAGTCAGCCGTCGAGGAGGTATCTATGTTCAGTCGTGTTTTAGCCCTTCTGGCTGTGCTTTTGCTAAGTGCAAATACATGGGCAGCCATTGAAATTAATAACCACCAGGCCAGAAATATGGACGATGTGCAAAGCTTAGGCGTGATTTATATCAATCATAATTTCGCCACTGAAAGCGAAGCACGTCAGGCATTAAATGAAGAAACAGATGCGCAAGGCGCAACGTACTACCACGTAATTCTGATGCGGGAACCGGGGAGTAACGGCAATATGCACGCCAGCGCGGATATTTATCGCTAGCACCAGGTATAACCAACGAAACATTGCCATAGTTTGCTTTGCCCCCTTCGCAGGGGGCTTTTTTTTGAAAAACGGCTGCGGAATTAGACCAGTTATCTCCCGAGGAAGGAAATTTCCGCAGCGCGTGTTCTACTTCTGCCCGTAATAAGCGTTAGGACCGTGTTTACGCATGAAGTGTTTATTCATCAGGAAGCTGTCGATGTGATTGAGTTGTGGGTTAATGCCGCGGGCAATCCACGCCATTTTCGCCACTTCTTCCATCACCACCGCGTTATGCACCGCATCGTGAGCATCTTTCCCCCAGGCGAACGGCCCGTGCTGATACACCACAATTCCCGGCGTATGCAGCGGCTCGGCGTTGCCCAGCGTTTCGATAATCACTTTGCCGGTGTTCAGTTCATACTCGCCCTGCACCTCTTCTTCGCTTAACCCGCGCGTACACGGAATGTCGCCAAAGAAGTAGTCGGCGTGCGTGGTGCCTAACGCCGGGATCGCCAGCCCCGCCTGCGCCCATGCGGTGGCATGAGTGGAGTGGGTATGGACAATGCCACCAAGCGACGGGTAACGACGGTAGAGTTCGAGATGCGTCGCAGTGTCGGAAGATGGGCGATACTCCCCTTCCACCACCTTGCCGCTCATATCAACCACCACCATATCGGCCGCTTTCATGGTTTCGTAGGCAACGCCGCTGGGCTTGATCACCACCAGCCCGCGTTCGCGGTCGATAGCGCTGACGTTGCCCCAGGTAAAGGTCACCAGCCCGTAGCGCGGCAGCTCCATGTTGGCTTCAAATACCTGCTGTTTTAGCTTTTGCATTATGCCGCCTCCACCATGCCCGCTTTCGCCATGCGCGCTTTCACCCAATCACGCGCTTTCGCCACTTCTGCCGCCGGGTCTTCCGCCGTTTCGCTCCACATCTCAATCAGGTACGGCCCGCAATAGCCACTCTGTTTGAGCGTTTCGAAACAACGTTCGAAATCCACTACACCTTCGCCAAACGGCACGTTTTTGAAGACGCCAGGTTTGGTGTCTTTCACATGTACCGCGACGATATGCCCGATTCCGGCCTGCAACTCCATCTGCACATCGTTGTCCCACGCCGACAGGTTGCCGATATCCGGGTAGAGCTGGAACCACGGATTGTTGAGATAGTGCGCGTATCCCAGCGCCTTGCTGATGGAGCTCATCAACGGATAATCCATGATCTCCATCGCCAGCGTCACCTGCGCGCGGCTTGCCATCTCAACGCTCTCTTTCAGGCCGTCACGGAAACGACGACGCGTTTCGTTATTGGCTTCCTGATAGTAAACGTCATAGCCCGCCAGCTGGATCACGCGAATACCGACATCCTGGGCGAACTGGATAGCTTTACGCATAATCTCCAGCCCCTGCGCCCGCACCGCGTCATCTTCACTGCCCAGCGGGAAACGACGATGAGCAGAAAGGCACATGGACGGCACGCGCACGCCGGTTTCAACAATCGCATTGACCAGCGCCAGACGCTGCTCGCGGCTCCAGTTGAGGCGCGACAGGCGATCGTCAGTTTCATCTACCGACATTTCGACAAAATCGAAGCCTAACGTTTTTGCCAGTTGCAGGCGTTCCAGCCAGCACTCCCCGGCGGGGAGCGCTTTTTCATAGATGCCAAGCGGGATTTGTTTGGACAACATATCCGCTCCTTAGCCCCACAGTTCAGCGATGGAACGTTTGAACTGACGTGCGGCTTCCACCGGAGAAGCGGCATCACGGATACTACGGCCCGCGATAAAGACGTGAATCGGAATACCCTTGAACAGCGGCAGATCTTCCAGCGCCAGGCCTCCGGTGACGGTGACTTTGAAGCCCATATCGGAAAGACGTTTGATCGCGGTGATGTCCGCTTCGCCCCACGCCACGCCTGCGGCCTGCGCGTCACGGCTGCGGTGATAAACCACCTGCCCAATGCCTGCATCGCGCCACTGTTGCGCCTGTTCCCAGGTCCAGTAACCGGTCAGTTCGATCTGCACGTCGCCGTTAAACTCTTTTGCCACGTCCAGCGCGCCTTTGGCGGTGTTGATATCCGCACAGCAAATTACCGTCACCCAGTCAGCGTTGGCTTCGAAGCACATACGCGAAAGGATTTTGCCTGCATCGGCAATTTTGGCGTCTGCCAGTACGATTTTGTGCGGGTAGAGCGCTTTCAGGTCACGAACCGCACGCACGCCTTCGCCCACGCACAGAATGGTGCCCACTTCGATAATGTCGACTTCTTCGGCAATCAGGCGAGTGGTTTCGTAGGCGCTATCCATAGTCTGGTTGTCCAGCGCGACTTGCAACATCGGTAATGACATGTTCAATTCCTTCTTAAGCTGCCGCGTTGGTGCGGTCAATGAGATCCAGTACTTCCTGCTCGGTACGGCAGGCGCGTAAACGGTCAAAATTCTCTTCATCTTCAAACAGGTTGACGATCTGCATGATGCCCACTTCCTGGTGAGTATTGGCATCGACCGCCGCCATGGTGATGAGGATATCCACCGGATCGTTGTCATCGTGGTTGAACTCCAGCGGCTTTTTCAGCGTTACCAGAGAGAAACCGGTTTTCTTAACGCCCTCTTCCGGACGCCCGTGCGGCATTGCCAGGCCCGGAGCGATAACGAAATAAGGACCGAACTGTTCAACGCCATCCAGAATCGCCTGGTAGTAACGCGGCTCTACCACATCTGCCGCCACCAGCAGGTCAACGCCGATTTTCACCGCTTCCTGCCATGTCTCTGCTTCAGCCTGCAGGCGGATGGATTTATTTTCCGCCAGCGAATCACGTAATTTCATGGCGCGTCCTTACTTCACATCCTGCGGGAAATGCTCTTTGATCACTTCCAGCAGTTTCGGGCCAAAGTCGGCAGGAGAGAGCATGTTGCGCACGCCAACCACGTATTTGTTGCCGGTCACGGTGATTTCGCCCGCAATGTGCGTAGAAGCGATGATGATATCCGCGCCACTCAACTCGCTTTTGTACTCGCCAACCGCGCAGCTGTTTACCGTATGGTCAATGTTTGATTGGGTTAAAAACTGGTCCACTTTCATCTTCATGATCATGGAACTGCCTTGTCCGTTGCCACACACAGCCAGAATACGTACGGTCATAATCAAAACTCCTTATTAAGCAGACTGTTCTGCCAGTTGTTTTTCTGCATCTTCTTCTGCGCGCAGCGCGCGGCCAGCGAAGAACATATAAGCCAGTGCAATTACAATGATGACGGCCATAAAGGCGATACCGATGGAGAAGAAGCCTTGCATCATCGGCGGTGCCAGAATCGACCAGTCCGCCATGCCCATCCAGGCACTCATACCGGTGAGTTTCACCGCCCAGACGCAACCAAAGATTTCGATCATCCCCATCACCAGACAAATCTTCAGCGCCGCACGCCAGCCGCCGAAGTGGTTAGCGAACACGCCGATGGTGGCGTTAGAGAAGAACATCGGGATAAAGCCAGGAATAATCAGGATCGAGGAGCCGCAGGCGACCAGGATGCCAACCGCAATCAGCTGACCGATGGTGCCCCACATAAAGCCCCAGACCACGGCGTTCGGCGCGAAGCTATAGATAGCTGCACAGTCAATCGCCAGAACCGCACCTGGGATCAGGCGCTGGGAAATGCCGTTAAATGCTTCAGAGAGTTCCGCCACAAACATGCGCACACCCTGCGTGATGATGAAGATCGCCACCGCAAAGGAGAAACCAGTTTGCAGGATGTACACCGTCCAGTGCACTTTGCCTGCCATCGCCTGCACGGTGTCGATACCGAAGGAGAGCAGAATGGCACCAAAGAAGATGGTCATCACAATCGCCGTGGAGACGATGTTGTCGTGGAAAATGTTCAGCCAGCCCGGCAATTTGAGGTCTTCAACGCTCTCCTCTTTTTTGCCGAGGAACGGCGCGACTTTATAGGCAATCCATGATGCAAACTGCTGCTGGTGACCGATGGAGAAACCACAGCCATCCGTCACTTCCTGAGTCGGCTTGTACATCATGTTGGAAGTGATGCCCCAGTAGAGCGAAACCAGAATCGCGGTACAGATAATGGTGGTCCACATGGAGTAGCCGAAGATAAACAGCGTAACGGCAATCAACCCGGCCTGCTGGAACATGATGTGGCCGGTCAACATGATTGTGCGAATGCCGGTAATGCGACGCAACAGCACGTAACAGATGTTCAGCGCCAGCGCTAACAATACGGCGTAACCCACCCAGCTATAGGCATCGCCCATGCGGTCGATGGTTGCCATCATTGAAGCGTAGGTATCGGAAATTGCGCCGTTAATGCCGTAGACTTCGGACATTTTCGCCACCACCGGTTTGAAGGTGCTGGTGAGGATGCCGGACCCTGCCTGCAACAACATGAAACCAATTATGGTTTTAATCGTGCCTTTAATAATAACGCTGACACTTTTGCGCAGTAGGATGTAGCCCAGACAGGTCACAATACCCAGCAACAACGGGGCATTGGTCATGACCTGGTTAAAAAACACGGTAAAGATGTTGTAGAGGATCTCCATAACGATCTCCTGAAGAAGAGGTAACCGGGTATTCCACACACCCGGAATGTTGTGCACTCACTCTAATTTTCAAAAGTAATCACAACAAGATTATTTATGATTAAATGTGACGCGACCCGCAAATAATTCCACATGGATAGAGTGGGATTCACACAACGAAACAATTATCCATTTAAATTCATTTAGTTAATTGAATTACACATTCCATTAAATCTTTCCATACTCAAAATCAACAACAACTTCCCTGGCAAAAAGTCAAAAAATGGTCATTGCCTTCCTGAAAAAATAGTGTCAGGATTAATCAAAACCAATCACATATTGATTCGAATTGAACTATCATGAAGGTAAATGGCGATGAGTAAAGTGAAAAGTATCACCCGTGAATCCTGGATCCTGAGCACTTTCCCGGAGTGGGGTAGCTGGTTGAATGAAGAAATTGAACAAGAACAGGTCGCTCCTGGCACATTTGCGATGTGGTGGCTTGGCTGCACCGGGATCTGGTTGAAATCGGAAGGTGGCACCAACGTTTGCGTTGATTTCTGGTGCGGCACTGGCAAACAAAGTCACGGTAACCCGTTAATGAAACAGGGTCACCAGATGCAGCGCATGGCTGGCGTGAAAAAACTGCAGCCAAACCTGCGTACCACCCCGTTTGTTCTTGATCCGTTTGCGATTCGCCAGATCGACGCGGTACTGGCGACTCACGATCACAACGATCATATCGACGTTAACGTCGCTGCTGCCGTGATGCAGAATTGTGCAGATGACGTACCGTTTATCGGACCGAAAACCTGTGTGGATTTGTGGATTGGCTGGGGCGTACCGAAAGAGCGTTGCATCGTGGTCAAACCGGGCGATGTAGTAAAAGTGAAAGACATTGAAATTCATGCGCTTGATGCTTTCGACCGTACTGCACTGATCACCCTGCCTGCCGATCAAAAAGCGGCTGGCGTACTGCCAGATGGCATGGACGATCGCGCGGTGAACTACCTGTTCAAAACGCCTGGCGGCTCCCTGTATCACAGCGGCGACTCCCACTACTCTAACTATTATGCGAAGCACGGTAACGAACATCAGATCGACGTGGCGTTAGGATCGTACGGCGAAAACCCGCGCGGTATCACCGACAAAATGACCAGCGCCGATATGCTGCGTATGGGTGAAGCGCTGAATGCGAAAGTAGTGATCCCGTTCCACCACGATATCTGGTCAAACTTCCAGGCCGATCCGCAAGAGATCCGCGTGCTGTGGGAGATGAAAAAAGATCGCCTGAAGTATGGCTTCAAGCCGTTTATCTGGCAGGTGGGTGGCAAATTTACCTGGCCGCTGGATAAAGACAACTTCGAGTACCACTATCCGCGCGGTTTCGATGATTGCTTCACTATTGAACCGGATCTGCCGTTCAAGTCATTCCTGTAATCTGTCGTTTATACCGGGTAGCGTGGAGAAGTTCGCGCTATCCGGCGTAGTATTTCCTGGCTATTTCAAATATCATCTAAAAAAATCAAATTTTATCGGAATAGCTCATGACTGAAGCACAAAGACATCAAATCCTCCTGGAAATGCTCGCACAATTGGGCTTTGTGACCGTTGAGAAAGTCGTTGAGCGTCTGGGAATTTCGCCTGCCACTGCGCGACGCGATATCAATAAACTTGACGAAAGCGGCAAACTGAAAAAAGTGCGCAATGGCGCAGAAGCTATTACCCAACAGCGCCCGCGCTGGACGCCGATGAATCTGCATCAGGCGCAGAATCACGATGAAAAAGTACGTATCGCTAAAGCGGCCTCGCAGCTGGTTAATCCGGGCGAAAGCGTAGTCATCAACTGCGGCTCCACCGCGTTTCTGCTTGGGCGGGAAATGTGTGGCAAGCCAGTGCAAATCATCACTAATTATCTACCGCTGGCAAATTACCTGATCGATCAAGAACATGACAGCGTGATCATTATGGGCGGACAGTACAACAAAAGTCAGTCCATCACTTTAAGCCCGCAGGGCAGCGAAAACAGTCTCTATGCCGGGCACTGGATGTTTACCAGCGGAAAAGGGCTGACCGCAGAAGGGTTGTATAAAACCGATATGCTGACAGCAATGGCAGAGCAGAAGATGCTGAGCGTGGTAGGGAAACTGGTGGTACTGGTTGATAGCAGTAAGATTGGCGAACGCGCGGGAATGCTTTTTAGCCGTGCCGATCAAATCGATATGCTTATCACCGGCAAAAATGCTAACCCGGAAATCCTGCAACAACTGGAAGCGCAAGGGGTCAGCATTCTGCGTGTTTAAAGATGCTGGCGGAAAAATGTCACGGCAGCATCTAACGCCTCAGGCGTAATGCGGTGACGCACGCCTGGCTGCCATGAACAGGTTAGCAGTTTATCCCGTCCCGTCTCGCTTAAGGCCTGCTGCAAACGTAGTGATTCGTCGGCAGGCACAACGTCATCGTCGAGGCCATGCCACAGCAGTAGAGGTCTGTCACTAAGTTGTTCCAGGTGGTTTGTCGCTTCCCACTCTGCCAGTGGCGCGACAATGTTATTGAATTCATTCTGCTGTGCTGCCGTTTCAGGTATCAGCGGTGGAAACAGTGAACGGGCGAGTGATGTAAAATAGCCCGATCCCATCATGCTGGCGGTACATCTCACCGTGGGGTGGCGAGCGGTAATCCCCAGTGCCGTCATCGCGCCCATCGACGCGCCACCGACTGCCAGACGGTCATCAAGCAGCCAGTTTTCTTCGGCTATTGCCGCACGTAAAGTAGTGAATTCCTGCATACTTTGTAGCAAGATTTGCCAGAATTGATTTAACCGCCGCGCTGCGTCACCACTAAAACGGCTACCGTGATCGGGCGCATCCGGCATGATCACCCGCAAACCAGCCTGCGCCAGCGCAACGGCAAAATAGCTATACACCAGACTGGATGAAGTAAAGCCGTGATAAAAAATTACGCACGGTAACGGGGTATCTTTTTGCCCGACAGGATAAGCATGAAGAACGGGAATATCTGCCAGCTCGCGTGATTCTATTTCAATCATCTGTCTCTCCTTTTTGTCTGGTATGACATGAAGAAATCCTTAGCACAAGTTTCTGCTGGCGGTATTAGTTCATAATGTTGAGATGTGGGTTACGCTTTCGTCACGTTTTCATTCGAAAATCGCGTACCAGGTAACAATTCGGGAACATTCCCCCAAAGTTAAATTAATAAGGCACTACACTATGGTTAGCAGGAAACGTAATAGCGTTATTTACCGGTTTGCCAGTTTATTATTGGTGTTGATGTTAAGTGCCTGTAGCGCACTGCAAGGTACGCCACAGCCAGCACCGCCAGTAACGGACCATCCGCAAGAGATTCGCCGCGACCAGACGCAAGGGTTACAGCGAATAGGTAGCGTAAGCACGATGGTTCGGGGTTCTCCGGATGACGCATTAGCAGAAATCAAAGCGAAAGCTGTCGCTGCAAAAGCTGATTATTACGTTGTCGTCATGGTGGACGAAACCATCGTGACAGGACAGTGGTATTCACAAGCCATTTTGTACCGTAAATAAATCAGACAACTTACATAGTCAGCTTTACATTGCTTTGCGTCCCTATGCGTTTACCTGTGCACAATAAATTACCGGCTGGAAGCCTGGGCGTTTATTACCGCGATGGAATGCCCTGCAACATGTGGGGAAACGAAAAATGGAGCTGACGATGAAACAATTACTTGCCTCACCCTCGCTGCAATTAGTGACTTATCCTGCGAGCGCCACGGCACAGTCTGCAGAATTCGCCAGTGCTGACTGCGTGACGGGCCTGAATGAAATAGGTCAGATCTCAGTTAGCAATATTTCAGGGGATCCGCAGGACGTGGAACGTATCGTGGCGTTAAAGGCCGATGAACAAGGTGCGTCATGGTACCGCATTATTACCATGTACGAAGACCAGCAGCCTGATAACTGGCGCGTACAGGCGATACTGTATGCATGAGTGTCATCTACAGCAAATGAACAATGCCGGATGCGGCGCGAGCGCCTTGTCCGGCCTACAATTTTCACATATTTCATTTAGTTAATCGAAACCAGCGTCGCATCAGTCGTATACGCTTACACACACACTCCCCCCGTCGCCCGCAGCAATAAATCATTCTGGATCTGCTCTGACAACCGTACGCCGCCGCGCGTATCTAACATCACCTGACACCACGCCTGCGCCATTGGCGGAGAAGCATATTTCAACATTTGCGCACCGCAGCCCAGCAGGAATAGCTGATGAGTAATCTCTCGCCCCAGTTCTTCAGCTGGCTTACGCAGCTGCTGCTGTAAACGACGAACCGCGCGATCAAAATAGCGATCCTGCCCTTTCACTTCCACAAATGCTTCCGACAATAAGTCGTATACGCCCGCTTGCTTATTGAGAACGCGCAACACATCCAGGCACATAATATTGCCGGAACCTTCCCAAATACTGTTTACCGGCATCTCCCGGTAAAGCCGCGGCAGCTCACTCTCCTCGCAATAACCAATGCCGCCCAGCACCTCCATCGCTTCGGCCACAAACGGCATACCTCTTTTGCAGATCACAAATTTTGCCGCAGGCGTAAATAAACGCGCCCACAGGGCTTCTTTGGCATCGGCACGCCGGTCCCACGCTCGCGCAAGACGAAACAGCAACGCCGTTTGCCCTTCAAGCTGAAGTGCCATGCGACTTAAGACATGACGCATAAGGGGCTGTTGGATCAATGGATTACCAAAAACATGGCGTTGATGTGCATGATAAATCGCCAGCGAAAATGCACGGCGCATCATGGCATGGCTACCCAGGGCGCAATCAAAACGCGTCATCCCACCCATTTTCAGGATCAGACGAATTCCTTCCCCTTCCAGCCCCAACAACCAACCAATGGCATCCTGAAACTCCACTTCGCAACTGGCGTTAGAGCGATTACCCAGCTTATCTTTCAGCCGCTCGAGGCGAATCGCGTTGCGTTGCCCGTCAGGCAAAAAGCGCGGCACAAAAAAGCAGGACAGACCACCCGCGGTCTGCGCCAGCACCAGATGCGCATCGCTTTGCGGAACCGAGAAAAACCATTTATGCCCCACCAGCCGATAAGAGCCATCTTCCAGACGCTCTGCACGGGTGGTGTTGCTCATAACATCGGAACCGCCCTGCTTTTCCGTCATTCCCATGCCAATCAACAAACCGCGTTTTTGCCCACCTGGCAATAAGTGAGAATCGTAGCGATCGCTCAATAGCGGCGTGGTCCAGTCCTGAAACGGCGCGGGTAACATCTGTAACAACAATGGCGTGGCGGCAAAGGTCATGGTTATCGGACATAACGACCCTGCCTCAACCTGCGCATGTAACATAAAACGCGCCGCGCGCGCCACAAATGCGCCGGAGCGAGCGTCTTCTTCCCAGGCAAGATTGTGCACCCGATTGGTACATAGCGCCTGCATCAGCAGGTGCCAGGCGGGGTGAAAACGCACATCGTCCAGACGGCGTCCTTGCGCATCGTAGCGCAATAATTCAGGCGGATTCACATTCGCCAGCCGCCCCAGTTCAAGGGATTCAGCCGTTCCTAACTGCTGACCAATACTGGCTAGAAAATCGCTATCCCAGCCAGCACCTTCACGCGTTACCGCTTCGCAGAGCGCGCCATCAGACAGGTATAAGTTGCTGTTATTTAATGGTATAGGTTGATTAAAAACGGTGTGAGTTTGCCAGTGCACTGTGTCTCCCTCCATCAATGGCAGTCACCATTAGTATGGTCACTGCCATGGATTCATGACAGAAAGAGATTGCTAAAACATTCTTATCCAGCAATGTAATGCGGAACGAAACGTGAGGTGTCTTTGGTGATCAGTGTGTTATCTTCACGGATCCCCATTCCGCACGCTTCATCATCGACAATCCAGCTACCGATGAGTGTGTAGCTATCGCCAAACCGCGGCAGAGGTTGAAACGCCTGGTAGATCATCGGTTCATCGGCGTAATCACCATCAGCGTGGTCAACAACGTTATTCTTGCCGTCAAAAATGGTGACGTTGCCGCCTTCGCGCGAATAGATTGGTTTACGCACATAGCTTTCGCCAGCGGCAATCTGCGGTTTCTCGCCATCGAACCAGGACGCAAGAAGATTAGGATGACCAGGGAAGAAGCGCCAAAGCAGCGGCATTAGCCCTTTATTACTCAAGATACTTTTCCATAACGGCTCCACCCATTGCTCGCGACGCTTGCGCAGCAGCGGACCGTTATCGTCACGCATCATCCACTCCAGCGGATACAGCTTAAATGCACGCTGGATGACATTATCATCAAGATCGGTCAGTACGCCGCCGACGCCCAAACCGAGATCTTCAATGTAGATAAACCGCGACTCCTGCCCTGCCTGCTGGGCGCAGTCCTGCAAGTACAGCACGGTACTCCTGTCTTCATCGGTGTCCTGACAGCAGCAAAAATAAAACGGTTCCCGACTGTAAAGCTCGCTAAAGCGTGAAATCAGGCGTTCCTGAATAGCATTGTACTGATCGGCATCACGCGGAATAATGCCGCTGCGCCGGGCATCCTCCAGCCACAGCCACTGGAAATAAGCCGACTCGTACAATGAAGTTGGCGTATCGGCGTTGTACTCCAGCAGCTTCACCGGCGCATTGCCACACCAGGCAAAATCCATCCGTCCATACAGCGAAGGATCGCGGGCGCGCCAGCTTTCAGCGATCACATCCCAGTACAACGGCGGGATCGCCAGTTGCGTCAGGATCTCTTCATCTTTTACCGCGCGATCCACCACCTCAAGGCACATCTGATGCAGTTCCGCAGTCGGTTTTTCGATCTGCTCTTCAATCTGGCGCAGAGTAAAACGGTAAGCCCGACTCTCATCCCAATAGATTTCATTGTCGATGATATGAAAGTCGAAACCGTTGTCAGCGGCGATCTGGTCCAGATCCCGTCGCACAGGAACGTTGTGTCTCAGCATGATTAGCCTCCCCAATGCCCACGGGCGCTGGAAGAACGACCATAGCCGCCGCGAGAAACGGTAGACGCTTTTTTGGTGGTAAAGCCGCCCGAAGAGTAAGACTCTTTTTTGCCAGAACCGGAGCGCCAGGAGTAATCACCAGAAGTGCTGCGCCAGACTGGGCGCGAAGCAAAAGAGGAACCGCCGCTGTTATAAACAAACGGCTCATCGCGATCTTTACGAATAACCCGGCTTAACAAAAATCCAGAAACGACCGGGATCCAACTCTGTTCAACATTGTCGTAGTAGCAATTTTCGTACTTAGACTGACAGTTCTGCTGAGTCATATTCTTCGGAACATCGGCATAAAATGCCGTTTTGGCGTTGTTCCAGCCACGCGCGCAAATGTCGGCATTATTACCGTCATCAATACAATCCTGCACTGTCGCGTAAAACGTTCCGTCGCCGTCGTTATCGACATCGCTACTATCGCTACAACCTTTCAATACGAAAAAAGCGGCACCGCCCATTAGCGCCAACGTTAAGTATTTTTGTGCGTAGCGATTGCGGCACGGTTCAAAAGGATTATTCGGTCTACCAATGCGACTAATCGCTCCGTGACCAATTTTACTGTTATTTCTTGATTTGCGTTTTCTGGCCATGATCGTCCATTACCATGTCATACAAGCTGCGTTAAAAATACCGCCAGCCAGCGCGGCGGTTCCCATAAACATTCCTGCTGCGGTATTGTGATTAATAATTTTTTCGCTTAATGCGGGCATATAAAGTCTGACACCAGCAAAAACGAGTAACTGAATCACCAGTGCAATCCCGCCCCAGGCGAAATAGTCTGGAATACTCACCGCATTGATTGCCGCACTGGATAAGGGGATAACGTAACCCAACAATGTACCGCTGAACGCCAGTGACGCCGCGGTATTATTGTTTTTGATTAACTGCCATTCGTTGTGCGGTGTAATTTTAGAATAGATAAACAGAAAAATAATCACCATAGCCACGCCAATAAAAAAATAGGCGCTAAAGGCAAGAAGTGAATCCAGTATATGCATTGTAAACGTCCTTGTAATTAACCAATAATATGAAGTGATGTCAGCGGGATATCGACACCCAACGCGCGCGAAAATAACCACTCTGGCTCGCCGAGATCGTTAAAAGATTCCTCACCATTTAGCAGCAAATATTCGTAAGTATCTTCGGTTACTTGCCGTTGGTAGCCCATGGTAAAATTATGGACCTCCCATTTGGCATGGTTTTGATTTTCTACTTTTTCCAGCATGTAGACGGGTTCGATATTTCCCGGTTCTTCGCTGTTAAAAAATCGCTGCCAGCGTTTTTCCTGCCAGTTTAAGGTCATTGCTCCCATCGCTTTGGCGTTGATCGCCTCGCGCCAGTGACTCTCTTTACTGATACCGTAGCTCTCTTCATAGACAAAGAGCTTGATATCATCAATGTCATCAATATCTTCGCCGCCGGTGGTATTGATTTGCAGAAACTCATCGCCTGAAGTGTAGTAGCGGAAAATCTGACTACCGCCGCCCAGATCGATGTGGCTGACGGCGGCTACCGTAAATTCCTCACCCGGCAGCGCAATCAGCAATTCATCTTCCAGCAAACGAAACGCTAACGTGTCGAGCGTAAAGCCACTATTGAGATGAAGTCCCAGCGGACCACGAGCGATAGCTGGCTTATTATCCTTGCCAAACAGACGCTGGAAAAAACCAGACATATTTTATCCTTAAAATAGTTGCCAGCCTTTTAGCGAGGCTGGCAAAAAAATTACTCGCCCTGTTGGCGTTGCAGTCTTGCTAATACATCCTGGGCGCTACTTTTATTGCTACCGCCAATTCCGGCTTCCGCCAGCTTTTCGTCAAGGTCGCGACCGTCTGCGACTTTCTCCAACTGTGCGGCAGCATCCAGGCGAGCCTGACGTTCGGCCTGACGCGTTTGCAGGCGTTTTAAGGATTCTGCCGCTGTCGAAACGCTGGAAGATGCGCCAACGGTAGAGGTTGTTACAGCCTGTTGTGCACGCTGCATGGCTTCAGTGGCTTTAACGACTTCCATTTGCTGCTCAAACTGAGCGATACGCTGCGCTGTCGCTGTAACTGCTTTTTCCACGCCATCACGGGAGACTTCCAGATTCGACAACACTTGCTCTTCAGCGGTAATGAGATTCTCAAGGCGCGCGATTTCTTCAGCAACTTCGTTAATCAACGACGGATTAACGTTCTTGCTTAACGCTTCCAGCGCACGGGCTTCCAGACTGGCTTTGCGCTCACGTAAATCTTTCAGCTTATCGTGACTTAATTTCACCCGCGCCAGCAGATCAACGCGAGATTTTCCGGCTTTATCGAGTTCAGCTTTAGCGTCACGAATATGCTGTTCCAGCATGCGCACGCCCTGGGTTTCTTCAATGGATTCTTCCGCCTGGGAGATAAACGATTTCCCCAGCGTAAATAAACTTTTTAAAATTCCCATAAATACCCGTCCTTGTAATTAGTGTGAATATTCTTCTGTAATTTCAGCCAGATCCAATGCGTTATCTACCAGCGAGGTTATCTCAAGCAGGATATCTTCAAGAGAAGATTTAAGCGATAACGCCCCGAAAACAATGTAATACTCTTCCTGTTGTACGCTGGAGATCCCTACCGATGACAACGGCATCATCTTCTGATTTCTTAATAAGAAGGTATTAAATTCATCTGGATTGCTGATACTACTCACCGGACAAATAAAGGTTTCGATAATCATTTGGCGGGAAGTAAAAAGAATATTGATTTGCAAATCGCCATAATCATTCATTTTAATAATTAATGCGTTCTCGCTATTTGTTACATCAATATTTTGTTCAGGTACAGTTTGCAGCGCCGTCGCTAGCGCCAACGGATTCCATGTCATATATTATTCCATATAGATTAAGTTTAAATATTAATAAAATGAATATTTGCAATACGTAATTATCTTACCAGCTATAGACAAAAAAAAACCATCCAAATCTGGATGGCTTTTCATAATTCTGAGAAATTAGCTGCGCTGGCGCACCGCTTCAAATAAGCAAATTCCGGTCGCAACCGAAACGTTCAGGGAAGAAACGCTTCCAGCCATCGGGATGCTGATCAACTCATCGCAATGTTCACGAGTCAGGCGACGCATACCTTCACCTTCCGCACCCATCACCAGCGCCAGGCGTCCGGTCATTTTGCTCTGATAGAGTGTATGATCCGCCTCGCCTGCCGTACCGACGATCCAGATATTCTCTTCCTGCAACATACGCATGGTGCGCGCAAGGTTAGTCACCCGAATCAGCGGAACGCTTTCTGCCGCGCCGCAGGCTACTTTTTTCGCCGTAGCGTTGAGCTGTGCGGAGCGATCTTTCGGCACAATCACCGCATGAACGCCTGCGGCGTCCGCACTACGCAGGCACGCGCCGAGGTTGTGCGGATCGGTTACGCCGTCGAGGATCAGCAGGAACGGTTGATCGAGCGAAGCGATCAGATCCGGCAGATCGTTTTCCTGATACTGACGTCCTGGCTTCACGCGGGCGATAATGCCCTGATGCACGGCACCGTCGCTTTTCTCGTCGAGATATTGGCGGTTTGCCAACTGGATAACCACGCCCTGAGACTCAAGGGCGTGAATCAGCGGTAACAGACGTTTATCTTCACGGCCTTTTAAAATAAAGACTTCCTGAAAACGTTCAGGGGCGCGCTCCAGCAGGGCCTGCACTGCGTGGATGCCGTAAATCATTTCGCTCATTAATGTACTCGTTGTTTACGTTTTGCCTGATGCACTACGTTTATCCGGCCTACATGATCTCTGCAATATATTGAATTTGCGTGATTATGTAGGCCGGATAAGGCGTTCACGCCGCATCCGGCATGAACAAAGCGCATTTTGTCAGCAATCTAACCCTCTTCTTTTAAAGAGGGTATTGATCACTCTGCCACTTTTTTCTTCGCCGCACGCTTCGCTTTGGTCGCTGCAGCTATTTTCTGCGTTTTCGCCGATGGCTTTTTCGCTTTTCTCGCGTCTTTCTTCGCCGCTTTCGGCTTCGTTTTTTTCTCACCGCGGAAGGCGCTGTCTGGCTCAAAGTTTACCTTTTTACCGACCTGACGACGCTTGCCGCCTTTTTTACCTGCATCGCCTTTTTTCGCTTTCTCGCGCGCCGTTTTACCGACGTTGCGCGGTGCGCGTTCGCTGGAGATCAGGCTAAAGTCGATTTTGCGCTCGTCCATATTAACCGCTTCGACGCGAACTTCCACGCGATCGCCCAGGCGATAAGTCTGGCCGCTGGATTCCCCCATCAGGCGTTGCCCTACCTGGTCAAAGCGATAGTAGTCATTGTCCAGCGAAGAGACATGGACCAGACCATCAATGAACAAGTCGTCCAGACGGACGAAGAAGCCAAAGCCAGTGACGCTGGAAATTACGCCTTTAAAGACGTTACCTACCTGGTCGAGCATGAAGTCACACTTCAGCCAGTCAGCCACATCGCGCGTTGCTTCGTCGGCACGACGTTCCGCCATCGAACAGTGCTGACCCAGTTGCAGCATCTCTTCCATCGAATAATGGTAGCCGCCGGTTTCAGTGGTGTTGCCCTGATGCCCCTGCTCTTTCGCCAGCAGATATTTAATGGCGCGGTGCAGCGTCAGGTCTGGATAACGACGAATCGGCGAAGTAAAGTGCGCATAGGACTGCAATGCCAGGCCAAAGTGACCACGGTTTTCTGGATCGTAAATCGCCTGTTTCATCGAGCGCAGCAGCATGGTTTGCAGCATTTCTGCATCAGGACGATCGGCAACCGACTCCAGCAGCTCCGCGTAGTCACGCGGTTCCGGCTTGTTACCGCCCGGCAGTTCCAGCCCCAGCTCCGCCAGCACTGAACGGAAAGAGGTAATCGCTTCGGTGCTCGGCTTGTCGTGAATACGGAACAGTGCCGGTTCTTTCGCTTTCTCAACGAAACGCGCCGCCGAGATATTCGCCAGAATCATGCACTCTTCAATTAATTTGTGCGCGTCGTTACGCTGGGTCTGTTCGATACGTTCAATACGGCGTTCAGCGTTGAAAATGAACTTCGCTTCTTCGCTCTCAAATGAGATCCCACCGCGTTCTTCACGGGCTTTATCCAGCACTTTATAGAGGTTATGCAACTCTTCGAGATGCTTAACCAGCGGGGCGTACTGCTCGCGCAGATCCTGATCGCCCTGCAGAATATGCCAGACTTTGGTGTAGGTCAGACGCGCGTGAGAGCTCATCACCGCTTCGTAGAATTTGTAGCCCGTCAGGCGGCCTTTCGACGAAACCGTCATCTCGCACACCATACACAGGCGGTCTACCTGCGGGTTGAGCGAACACAGGCCGTTAGAGAGCACTTCCGGCAGCATCGGGATAACCTGCGAAGGGAAGTACACCGACGTGCCACGGTTACGCGCTTCTCTGTCCAGCGGCGTTGACGGACGCACATAGTAGCTGACGTCGGCAATCGCGACCCATAAACGCCAGCCGCCGCCGCGTTTTTTCTCGCAGTAAACTGCATCGTCAAAGTCACGGGCGTCTTCGCCATCAATGGTGACCAGCGGTAAATCGCGCAGATCAACACGGCCCGCTTTTGCTTCTTCCGGCACTTCTTCTTTCAGCCCGGCAACCTGTTGCTCAACAGCCTGCGGCCAGATGTACGGAATTTCATGGGTACGCAGAGCGATATCAACCGCCATGCCGGTGCCCATATTGTCGCCCAGCACTTCGACGATTTTACCCACCGCTTTGGTGCGGCGAGTCGGACGCTGAGTCAGTTCGACTACGACCACAAAGCCCATCCGCGCGCCCATGATCTGATCGGGCGGGATTAAGATATCGAAGCTCAGACGGCTGTCGTCAGGAACCACAAAGCCGACGCCCGCTTCGGTAAAGTAGCGACCAACAATCTGGCTGGTTTTTGGCACCAGTACGCGGACAATACGCGCTTCACGACGACCTTTACGGTCAGCACCCAGCGGCTGAGCCAGCACCTGATCGCCATGAATGCAGGTTTTCATCTGCTCGCTGGAGAGATACAAATCATCTTTACGCCCTTCAACCCGCAGAAAGCCGTAGCCATCACGGTGGCCAATAACGGTACCTTTCACCAGGTCGAGGCGTTCCGGCAGCGCATAGCACTGACGACGAGTGAAGACCAGTTGACCATCGCGCTCCATCGCGCGCAGGCGGCGACGCAGGCCTTCAAGCTGCTCTTCGCCTTCAATGTGCAGTTCTACCGCCAGCTCATCACGGCTGGCCGGTTTTTCACGTTTGGTTAAATGTTCGAGGATAAATTCCCGACTAGGGATGGGATTCGCGTATTTTTCAGCTTCGCGTTCCTGGAAAGGATCTTGTGACATCTCGGTTCCTCCGTTGTCATCTCTGATGAAGATTTTCGTCACTCCACCAGCAATAATTTATAAAGCGGTTGATTCTCTTCAACCAAATCGGCAAGCGTGTAGTTATCCAGTTCCGTAAGAAAACTTTGCACGGCCTTAGAAAGTGCCTGTTTCAACCTACAGGCAGGTGTAATGTGGCAAAACTCACTGCTGCAATTCACCAGCGATAAGGGCTCCAGCTCGCGCACCACATCACCAATACGTATCGCACTCGCCGGTTTACCCAGGCGAATGCCGCCATTTTTTCCACGAACAGCAGTCACGTAGCCGGCACGACTAAGTTGATTGATTATTTTGACCATATGATTACGGGAGACGCCGTAGACGTCAGTCACTTCAGAAATACTGGTCATCCGCCCTTCTGGCAATGACGCCATGTAGATCAGCGCACGTAATCCGTAATCAGTGAAACTCGTTAACTGCACATCAACCTCAAAAGGGAAATCGGGAAAAAATACATTTATATTGATGATAAACCAGCCACAAGCTGTGTCGCTAATTTATTTCAGTTCGGGGAAGGAAAAAAGCGAGGATTTAACACTGTGTCGGATAGCGTAATGGCTTACCCGACACAGCAATGTATCACACTGTTCGCCCGGCAGGCAAAATATCTGCCAGGCGTACCAGAATTACGCGTCGAACGGGTCGCGCAGAATCATGGTTTCAGTACGATCCGGACCGGTAGAGATGATATCGATCGGCACACCAGTCAGCTCTTCAATACGCTTGATATAGTTCAGCGCCGCCTGCGGCAGGCCGCTACGATCTTTCACGCCGAAGGTGGATTCAGACCAGCCCGGCATGGTTTCGTAAATCGGCTCTACACCTTTCCAGTCGTCAGCTGCCAGCGGAGTGGTAGTCACTTCGCGACCATCCGGCATACGGTAAGCCACGCAGAGTTTAACCTCTTTCAGGCCATCCAGAACGTCCAGTTTAGTCAGGCAGAAGCCAGACAGGGAGTTCAGCTGTACCGCACGACGAACGGCAACGGTGTCCAGCCAGCCGGTACGACGACGACGCCCCGTAGTTGCGCCGAATTCGTTACCCTGCTTGCAGAGGAACTCGCCAGTTTCATCAAACAGTTCGGTCGGGAACGGACCTGCACCTACACGAGTGGAGTAAGCTTTGAGGATACCCAGAACGTAATCAACATAACGCGGGCCCAGGCCGGAACCGGTCGCCACGCCACCAGCAGTGGTGTTGGAAGAAGTTACGTACGGATAAGTACCGTGGTCGATATCCAGCAGCGTACCCTGCGCACCTTCAAACATGACGAAATCGCCACGCTGACGCGCCTGGTCGAGCAGGTCAGAAACGTCAACCACCATAGAAGTCAGGATGTCGGCAACAGCCATCGTATCATCCAGAACTTTCTGGTAATCAACCGCTTCAGCTTTGTAGTAGTTAACCAACTGGAAGTTGTGATATTCCATCACTTCTTTCAGTTTTTCAGCGAAGGTTTCTTTGTCGAAAAGGTCGCCAACACGCAGACCGCGACGTGCTACTTTATCTTCATAAGCAGGCCCGATACCACGACCGGTGGTGCCGATCGCTTTCGCGCCACGCGCTTTCTCACGCGCGTTATCCAGCGCAACGTGATAATCAAGGATCAGCGGACATGCTTCAGACAGCAGCAGACGCTCACGAACGGGGATGCCACGGTCTTCCAGTTCTTTCATCTCTTTCATCAGCGCGGCCGGAGACAGCACAACACCGTTACCGATGATGCTGGTTACATTCTCGCGGAGAATACCTGATGGAATAAGATGGAGAACGGTTTTTTCACCGTTGATTACGAGAGTATGGCCTGCGTTGTGACCGCCCTGGT +>419433556 +ACCAGGGCGGTCACAACGCAGGCCATACTCTCGTAATCAACGGTGAAAAAACCGTTCTCCATCTTATTCCATCAGGTATTCTCCGCGAGAATGTAACCAGCATCATCGGTAACGGTGTTGTGCTGTCTCCGGCCGCGCTGATGAAAGAGATGAAAGAACTGGAAGACCGTGGCATCCCCGTTCGTGAGCGTCTGCTGCTGTCTGAAGCATGTCCGCTGATCCTTGATTATCACGTTGCGCTGGATAACGCGCGTGAGAAAGCGCGTGGCGCGAAAGCGATCGGCACCACCGGTCGTGGTATCGGGCCTGCTTATGAAGATAAAGTAGCACGTCGCGGTCTGCGTGTTGGCGACCTTTTCGACAAAGAAACCTTCGCTGAAAAACTGAAAGAAGTGATGGAATATCACAACTTCCAGTTGGTTAACTACTACAAAGCTGAAGCGGTTGATTACCAGAAAGTTCTGGATGATACGATGGCTGTTGCCGACATCCTGACTTCTATGGTGGTTGACGTTTCTGACCTGCTCGACCAGGCGCGTCAGCGTGGCGATTTCGTCATGTTTGAAGGTGCGCAGGGTACGCTGCTGGATATCGACCACGGTACTTATCCGTACGTAACTTCTTCCAACACCACTGCTGGTGGCGTGGCGACCGGTTCCGGCCTGGGCCCGCGTTATGTTGATTACGTTCTGGGTATCCTCAAAGCTTACTCCACTCGTGTAGGTGCAGGTCCGTTCCCGACCGAACTGTTTGATGAAACTGGCGAGTTCCTCTGCAAGCAGGGTAACGAATTCGGCGCAACTACGGGGCGTCGTCGTCGTACCGGCTGGCTGGACACCGTTGCCGTTCGTCGTGCGGTACAGCTGAACTCCCTGTCTGGCTTCTGCCTGACTAAACTGGACGTTCTGGATGGCCTGAAAGAGGTTAAACTCTGCGTGGCTTACCGTATGCCGGATGGTCGCGAAGTGACTACCACTCCGCTGGCAGCTGACGACTGGAAAGGTGTAGAGCCGATTTACGAAACCATGCCGGGCTGGTCTGAATCCACCTTCGGCGTGAAAGATCGTAGCGGCCTGCCGCAGGCGGCGCTGAACTATATCAAGCGTATTGAAGAGCTGACTGGTGTGCCGATCGATATCATCTCTACCGGTCCGGATCGTACTGAAACCATGATTCTGCGCGACCCGTTCGACGCGTAATTCTGGTACGCCTGGCAGATATTTTGCCTGCCGGGCGAACAGTGTGATACATTGCTGTGTCGGGTAAGCCATTACGCTATCCGACACAGTGTTAAATCCTCGCTTTTTTCCTTCCCCGAACTGAAATAAATTAGCGACACAGCTTGTGGCTGGTTTATCATCAATATAAATGTATTTTTTCCCGATTTCCCTTTTGAGGTTGATGTGCAGTTAACGAGTTTCACTGATTACGGATTACGTGCGCTGATCTACATGGCGTCATTGCCAGAAGGGCGGATGACCAGTATTTCTGAAGTGACTGACGTCTACGGCGTCTCCCGTAATCATATGGTCAAAATAATCAATCAACTTAGTCGTGCCGGCTACGTGACTGCTGTTCGTGGAAAAAATGGCGGCATTCGCCTGGGTAAACCGGCGAGTGCGATACGTATTGGTGATGTGGTGCGCGAGCTGGAGCCCTTATCGCTGGTGAATTGCAGCAGTGAGTTTTGCCACATTACACCTGCCTGTAGGTTGAAACAGGCACTTTCTAAGGCCGTGCAAAGTTTTCTTACGGAACTGGATAACTACACGCTTGCCGATTTGGTTGAAGAGAATCAACCGCTTTATAAATTATTGCTGGTGGAGTGACGAAAATCTTCATCAGAGATGACAACGGAGGAACCGAGATGTCACAAGATCCTTTCCAGGAACGCGAAGCTGAAAAATACGCGAATCCCATCCCTAGTCGGGAATTTATCCTCGAACATTTAACCAAACGTGAAAAACCGGCCAGCCGTGATGAGCTGGCGGTAGAACTGCACATTGAAGGCGAAGAGCAGCTTGAAGGCCTGCGTCGCCGCCTGCGCGCGATGGAGCGCGATGGTCAACTGGTCTTCACTCGTCGTCAGTGCTATGCGCTGCCGGAACGCCTCGACCTGGTGAAAGGTACCGTTATTGGCCACCGTGATGGCTACGGCTTTCTGCGGGTTGAAGGGCGTAAAGATGATTTGTATCTCTCCAGCGAGCAGATGAAAACCTGCATTCATGGCGATCAGGTGCTGGCTCAGCCGCTGGGTGCTGACCGTAAAGGTCGTCGTGAAGCGCGTATTGTCCGCGTACTGGTGCCAAAAACCAGCCAGATTGTTGGTCGCTACTTTACCGAAGCGGGCGTCGGCTTTGTGGTTCCTGACGACAGCCGTCTGAGCTTCGATATCTTAATCCCGCCCGATCAGATCATGGGCGCGCGGATGGGCTTTGTGGTCGTAGTCGAACTGACTCAGCGTCCGACTCGCCGCACCAAAGCGGTGGGTAAAATCGTCGAAGTGCTGGGCGACAATATGGGCACCGGCATGGCGGTTGATATCGCTCTGCGTACCCATGAAATTCCGTACATCTGGCCGCAGGCTGTTGAGCAACAGGTTGCCGGGCTGAAAGAAGAAGTGCCGGAAGAAGCAAAAGCGGGCCGTGTTGATCTGCGCGATTTACCGCTGGTCACCATTGATGGCGAAGACGCCCGTGACTTTGACGATGCAGTTTACTGCGAGAAAAAACGCGGCGGCGGCTGGCGTTTATGGGTCGCGATTGCCGACGTCAGCTACTATGTGCGTCCGTCAACGCCGCTGGACAGAGAAGCGCGTAACCGTGGCACGTCGGTGTACTTCCCTTCGCAGGTTATCCCGATGCTGCCGGAAGTGCTCTCTAACGGCCTGTGTTCGCTCAACCCGCAGGTAGACCGCCTGTGTATGGTGTGCGAGATGACGGTTTCGTCGAAAGGCCGCCTGACGGGCTACAAATTCTACGAAGCGGTGATGAGCTCTCACGCGCGTCTGACCTACACCAAAGTCTGGCATATTCTGCAGGGCGATCAGGATCTGCGCGAGCAGTACGCCCCGCTGGTTAAGCATCTCGAAGAGTTGCATAACCTCTATAAAGTGCTGGATAAAGCCCGTGAAGAACGCGGTGGGATCTCATTTGAGAGCGAAGAAGCGAAGTTCATTTTCAACGCTGAACGCCGTATTGAACGTATCGAACAGACCCAGCGTAACGACGCGCACAAATTAATTGAAGAGTGCATGATTCTGGCGAATATCTCGGCGGCGCGTTTCGTTGAGAAAGCGAAAGAACCGGCACTGTTCCGTATTCACGACAAGCCGAGCACCGAAGCGATTACCTCTTTCCGTTCAGTGCTGGCGGAGCTGGGGCTGGAACTGCCGGGCGGTAACAAGCCGGAACCGCGTGACTACGCGGAGCTGCTGGAGTCGGTTGCCGATCGTCCTGATGCAGAAATGCTGCAAACCATGCTGCTGCGCTCGATGAAACAGGCGATTTACGATCCAGAAAACCGTGGTCACTTTGGCCTGGCATTGCAGTCCTATGCGCACTTTACTTCGCCGATTCGTCGTTATCCAGACCTGACGCTGCACCGCGCCATTAAATATCTGCTGGCGAAAGAGCAGGGGCATCAGGGCAACACCACTGAAACCGGCGGCTACCATTATTCGATGGAAGAGATGCTGCAACTGGGTCAGCACTGTTCGATGGCGGAACGTCGTGCCGACGAAGCAACGCGCGATGTGGCTGACTGGCTGAAGTGTGACTTCATGCTCGACCAGGTAGGTAACGTCTTTAAAGGCGTAATTTCCAGCGTCACTGGCTTTGGCTTCTTCGTCCGTCTGGACGACTTGTTCATTGATGGTCTGGTCCATGTCTCTTCGCTGGACAATGACTACTATCGCTTTGACCAGGTAGGGCAACGCCTGATGGGGGAATCCAGCGGCCAGACTTATCGCCTGGGCGATCGCGTGGAAGTTCGCGTCGAAGCGGTTAATATGGACGAGCGCAAAATCGACTTTAGCCTGATCTCCAGCGAACGCGCACCGCGCAACGTCGGTAAAACGGCGCGCGAGAAAGCGAAAAAAGGCGATGCAGGTAAAAAAGGCGGCAAGCGTCGTCAGGTCGGTAAAAAGGTAAACTTTGAGCCAGACAGCGCCTTCCGCGGTGAGAAAAAAACGAAGCCGAAAGCGGCGAAGAAAGACGCGAGAAAAGCGAAAAAGCCATCGGCGAAAACGCAGAAAATAGCTGCAGCGACCAAAGCGAAGCGTGCGGCGAAGAAAAAAGTGGCAGAGTGATCAATACCCTCTTTAAAAGAAGAGGGTTAGATTGCTGACAAAATGCGCTTTGTTCATGCCGGATGCGGCGTGAACGCCTTATCCGGCCTACATAATCACGCAAATTCAATATATTGCAGAGATCATGTAGGCCGGATAAACGTAGTGCATCAGGCAAAACGTAAACAACGAGTACATTAATGAGCGAAATGATTTACGGCATCCACGCAGTGCAGGCCCTGCTGGAGCGCGCCCCTGAACGTTTTCAGGAAGTCTTTATTTTAAAAGGCCGTGAAGATAAACGTCTGTTACCGCTGATTCACGCCCTTGAGTCTCAGGGCGTGGTTATCCAGTTGGCAAACCGCCAATATCTCGACGAGAAAAGCGACGGTGCCGTGCATCAGGGCATTATCGCCCGCGTGAAGCCAGGACGTCAGTATCAGGAAAACGATCTGCCGGATCTGATCGCTTCGCTCGATCAACCGTTCCTGCTGATCCTCGACGGCGTAACCGATCCGCACAACCTCGGCGCGTGCCTGCGTAGTGCGGACGCCGCAGGCGTTCATGCGGTGATTGTGCCGAAAGATCGCTCCGCACAGCTCAACGCTACGGCGAAAAAAGTAGCCTGCGGCGCGGCAGAAAGCGTTCCGCTGATTCGGGTGACTAACCTTGCGCGCACCATGCGTATGTTGCAGGAAGAGAATATCTGGATCGTCGGTACGGCAGGCGAGGCGGATCATACACTCTATCAGAGCAAAATGACCGGACGCCTGGCGCTGGTGATGGGTGCGGAAGGTGAAGGTATGCGTCGCCTGACTCGTGAACATTGCGATGAGTTGATCAGCATCCCGATGGCTGGAAGCGTTTCTTCCCTGAACGTTTCGGTTGCGACCGGAATTTGCTTATTTGAAGCGGTGCGCCAGCGCAGCTAATTTCTCAGAATTATGAAAAGCCATCCAGATTTGGATGGTTTTTTTTTGTCTATAGCTGGTAAGATAATTACGTATTGCAAATATTCATTTTATTAATATTTAAACTTAATCTATATGGAATAATATATGACATGGAATCCGTTGGCGCTAGCGACGGCGCTGCAAACTGTACCTGAACAAAATATTGATGTAACAAATAGCGAGAACGCATTAATTATTAAAATGAATGATTATGGCGATTTGCAAATCAATATTCTTTTTACTTCCCGCCAAATGATTATCGAAACCTTTATTTGTCCGGTGAGTAGTATCAGCAATCCAGATGAATTTAATACCTTCTTATTAAGAAATCAGAAGATGATGCCGTTGTCATCGGTAGGGATCTCCAGCGTACAACAGGAAGAGTATTACATTGTTTTCGGGGCGTTATCGCTTAAATCTTCTCTTGAAGATATCCTGCTTGAGATAACCTCGCTGGTAGATAACGCATTGGATCTGGCTGAAATTACAGAAGAATATTCACACTAATTACAAGGACGGGTATTTATGGGAATTTTAAAAAGTTTATTTACGCTGGGGAAATCGTTTATCTCCCAGGCGGAAGAATCCATTGAAGAAACCCAGGGCGTGCGCATGCTGGAACAGCATATTCGTGACGCTAAAGCTGAACTCGATAAAGCCGGAAAATCTCGCGTTGATCTGCTGGCGCGGGTGAAATTAAGTCACGATAAGCTGAAAGATTTACGTGAGCGCAAAGCCAGTCTGGAAGCCCGTGCGCTGGAAGCGTTAAGCAAGAACGTTAATCCGTCGTTGATTAACGAAGTTGCTGAAGAAATCGCGCGCCTTGAGAATCTCATTACCGCTGAAGAGCAAGTGTTGTCGAATCTGGAAGTCTCCCGTGATGGCGTGGAAAAAGCAGTTACAGCGACAGCGCAGCGTATCGCTCAGTTTGAGCAGCAAATGGAAGTCGTTAAAGCCACTGAAGCCATGCAGCGTGCACAACAGGCTGTAACAACCTCTACCGTTGGCGCATCTTCCAGCGTTTCGACAGCGGCAGAATCCTTAAAACGCCTGCAAACGCGTCAGGCCGAACGTCAGGCTCGCCTGGATGCTGCCGCACAGTTGGAGAAAGTCGCAGACGGTCGCGACCTTGACGAAAAGCTGGCGGAAGCCGGAATTGGCGGTAGCAATAAAAGTAGCGCCCAGGATGTATTAGCAAGACTGCAACGCCAACAGGGCGAGTAATTTTTTTGCCAGCCTCGCTAAAAGGCTGGCAACTATTTTAAGGATAAAATATGTCTGGTTTTTTCCAGCGTCTGTTTGGCAAGGATAATAAGCCAGCTATCGCTCGTGGTCCGCTGGGACTTCATCTCAATAGTGGCTTTACGCTCGACACGTTAGCGTTTCGTTTGCTGGAAGATGAATTGCTGATTGCGCTGCCGGGTGAGGAATTTACGGTAGCCGCCGTCAGCCACATCGATCTGGGCGGCGGTAGTCAGATTTTCCGCTACTACACTTCAGGCGATGAGTTTCTGCAAATCAATACCACCGGCGGCGAAGATATTGATGACATTGATGATATCAAGCTCTTTGTCTATGAAGAGAGCTACGGTATCAGTAAAGAGAGTCACTGGCGCGAGGCGATCAACGCCAAAGCGATGGGAGCAATGACCTTAAACTGGCAGGAAAAACGCTGGCAGCGATTTTTTAACAGCGAAGAACCGGGAAATATCGAACCCGTCTACATGCTGGAAAAAGTAGAAAATCAAAACCATGCCAAATGGGAGGTCCATAATTTTACCATGGGCTACCAACGGCAAGTAACCGAAGATACTTACGAATATTTGCTGCTAAATGGTGAGGAATCTTTTAACGATCTCGGCGAGCCAGAGTGGTTATTTTCGCGCGCGTTGGGTGTCGATATCCCGCTGACATCACTTCATATTATTGGTTAATTACAAGGACGTTTACAATGCATATACTGGATTCACTTCTTGCCTTTAGCGCCTATTTTTTTATTGGCGTGGCTATGGTGATTATTTTTCTGTTTATCTATTCTAAAATTACACCGCACAACGAATGGCAGTTAATCAAAAACAATAATACCGCGGCGTCACTGGCGTTCAGCGGTACATTGTTGGGTTACGTTATCCCCTTATCCAGTGCGGCAATCAATGCGGTGAGTATTCCAGACTATTTCGCCTGGGGCGGGATTGCACTGGTGATTCAGTTACTCGTTTTTGCTGGTGTCAGACTTTATATGCCCGCATTAAGCGAAAAAATTATTAATCACAATACCGCAGCAGGAATGTTTATGGGAACCGCCGCGCTGGCTGGCGGTATTTTTAACGCAGCTTGTATGACATGGTAATGGACGATCATGGCCAGAAAACGCAAATCAAGAAATAACAGTAAAATTGGTCACGGAGCGATTAGTCGCATTGGTAGACCGAATAATCCTTTTGAACCGTGCCGCAATCGCTACGCACAAAAATACTTAACGTTGGCGCTAATGGGCGGTGCCGCTTTTTTCGTATTGAAAGGTTGTAGCGATAGTAGCGATGTCGATAACGACGGCGACGGAACGTTTTACGCGACAGTGCAGGATTGTATTGATGACGGTAATAATGCCGACATTTGCGCGCGTGGCTGGAACAACGCCAAAACGGCATTTTATGCCGATGTTCCGAAGAATATGACTCAGCAGAACTGTCAGTCTAAGTACGAAAATTGCTACTACGACAATGTTGAACAGAGTTGGATCCCGGTCGTTTCTGGATTTTTGTTAAGCCGGGTTATTCGTAAAGATCGCGATGAGCCGTTTGTTTATAACAGCGGCGGTTCCTCTTTTGCTTCGCGCCCAGTCTGGCGCAGCACTTCTGGTGATTACTCCTGGCGCTCCGGTTCTGGCAAAAAAGAGTCTTACTCTTCGGGCGGCTTTACCACCAAAAAAGCGTCTACCGTTTCTCGCGGCGGCTATGGTCGTTCTTCCAGCGCCCGTGGGCATTGGGGAGGCTAATCATGCTGAGACACAACGTTCCTGTGCGACGGGATCTGGACCAGATCGCCGCTGACAACGGTTTCGACTTTCATATCATCGACAATGAAATCTATTGGGATGAGAGTCGGGCTTACCGTTTTACTCTGCGCCAGATTGAAGAGCAGATCGAAAAACCGACTGCGGAACTGCATCAGATGTGCCTTGAGGTGGTGGATCGCGCGGTAAAAGATGAAGAGATCCTGACGCAACTGGCGATCCCGCCGTTGTACTGGGATGTGATCGCTGAAAGCTGGCGCGCCCGCGATCCTTCGCTGTATGGACGGATGGATTTTGCCTGGTGTGGCAATGCGCCGGTGAAGCTGCTGGAGTACAACGCCGATACGCCAACTTCATTGTACGAGTCGGCTTATTTCCAGTGGCTGTGGCTGGAGGATGCCCGGCGCAGCGGCATTATTCCGCGTGATGCCGATCAGTACAATGCTATTCAGGAACGCCTGATTTCACGCTTTAGCGAGCTTTACAGTCGGGAACCGTTTTATTTTTGCTGCTGTCAGGACACCGATGAAGACAGGAGTACCGTGCTGTACTTGCAGGACTGCGCCCAGCAGGCAGGGCAGGAGTCGCGGTTTATCTACATTGAAGATCTCGGTTTGGGCGTCGGCGGCGTACTGACCGATCTTGATGATAATGTCATCCAGCGTGCATTTAAGCTGTATCCGCTGGAGTGGATGATGCGTGACGATAACGGTCCGCTGCTGCGCAAGCGTCGCGAGCAATGGGTGGAGCCGTTATGGAAAAGTATCTTGAGTAATAAAGGGCTAATGCCGCTGCTTTGGCGCTTCTTCCCTGGTCATCCTAATCTTCTTGCGTCCTGGTTCGATGGCGAGAAACCGCAGATTGCCGCTGGCGAAAGCTATGTGCGTAAACCAATCTATTCGCGCGAAGGCGGCAACGTCACCATTTTTGACGGCAAGAATAACGTTGTTGACCACGCTGATGGTGATTACGCCGATGAACCGATGATCTACCAGGCGTTTCAACCTCTGCCGCGGTTTGGCGATAGCTACACACTCATCGGTAGCTGGATTGTCGATGATGAAGCGTGCGGAATGGGGATCCGTGAAGATAACACACTGATCACCAAAGACACCTCACGTTTCGTTCCGCATTACATTGCTGGATAAGAATGTTTTAGCAATCTCTTTCTGTCATGAATCCATGGCAGTGACCATACTAATGGTGACTGCCATTGATGGAGGGAGACACAGTGCACTGGCAAACTCACACCGTTTTTAATCAACCTATACCATTAAATAACAGCAACTTATACCTGTCTGATGGCGCGCTCTGCGAAGCGGTAACGCGTGAAGGTGCTGGCTGGGATAGCGATTTTCTAGCCAGTATTGGTCAGCAGTTAGGAACGGCTGAATCCCTTGAACTGGGGCGGCTGGCGAATGTGAATCCGCCTGAATTATTGCGCTACGATGCGCAAGGACGCCGTCTGGACGATGTGCGTTTTCACCCCGCCTGGCACCTGCTGATGCAGGCGCTATGTACCAATCGGGTGCACAATCTTGCCTGGGAAGAAGACGCTCGCTCCGGCGCATTTGTGGCGCGCGCGGCGCGTTTTATGTTACATGCGCAGGTTGAGGCAGGGTCGTTATGTCCGATAACCATGACCTTTGCCGCCACGCCATTGTTGTTACAGATGTTACCCGCGCCGTTTCAGGACTGGACCACGCCGCTATTGAGCGATCGCTACGATTCTCACTTATTGCCAGGTGGGCAAAAACGCGGTTTGTTGATTGGCATGGGAATGACGGAAAAGCAGGGCGGTTCCGATGTTATGAGCAACACCACCCGTGCAGAGCGTCTGGAAGATGGCTCTTATCGGCTGGTGGGGCATAAATGGTTTTTCTCGGTTCCGCAAAGCGATGCGCATCTGGTGCTGGCGCAGACCGCGGGTGGTCTGTCCTGCTTTTTTGTGCCGCGCTTTTTGCCTGACGGGCAACGCAACGCGATTCGCCTCGAGCGGCTGAAAGATAAGCTGGGTAATCGCTCTAACGCCAGTTGCGAAGTGGAGTTTCAGGATGCCATTGGTTGGTTGTTGGGGCTGGAAGGGGAAGGAATTCGTCTGATCCTGAAAATGGGTGGGATGACGCGTTTTGATTGCGCCCTGGGTAGCCATGCCATGATGCGCCGTGCATTTTCGCTGGCGATTTATCATGCACATCAACGCCATGTTTTTGGTAATCCATTGATCCAACAGCCCCTTATGCGTCATGTCTTAAGTCGCATGGCACTTCAGCTTGAAGGGCAAACGGCGTTGCTGTTTCGTCTTGCGCGAGCGTGGGACCGGCGTGCCGATGCCAAAGAAGCCCTGTGGGCGCGTTTATTTACGCCTGCGGCAAAATTTGTGATCTGCAAAAGAGGTATGCCGTTTGTGGCCGAAGCGATGGAGGTGCTGGGCGGCATTGGTTATTGCGAGGAGAGTGAGCTGCCGCGGCTTTACCGGGAGATGCCGGTAAACAGTATTTGGGAAGGTTCCGGCAATATTATGTGCCTGGATGTGTTGCGCGTTCTCAATAAGCAAGCGGGCGTATACGACTTATTGTCGGAAGCATTTGTGGAAGTGAAAGGGCAGGATCGCTATTTTGATCGCGCGGTTCGTCGTTTACAGCAGCAGCTGCGTAAGCCAGCTGAAGAACTGGGGCGAGAGATTACTCATCAGCTATTCCTGCTGGGCTGCGGTGCGCAAATGTTGAAATATGCTTCTCCGCCAATGGCGCAGGCGTGGTGTCAGGTGATGTTAGATACGCGCGGCGGCGTACGGTTGTCAGAGCAGATCCAGAATGATTTATTGCTGCGGGCGACGGGGGGAGTGTGTGTGTAAGCGTATACGACTGATGCGACGCTGGTTTCGATTAACTAAATGAAATATGTGAAAATTGTAGGCCGGACAAGGCGCTCGCGCCGCATCCGGCATTGTTCATTTGCTGTAGATGACACTCATGCATACAGTATCGCCTGTACGCGCCAGTTATCAGGCTGCTGGTCTTCGTACATGGTAATAATGCGGTACCATGACGCACCTTGTTCATCGGCCTTTAACGCCACGATACGTTCCACGTCCTGCGGATCCCCTGAAATATTGCTAACTGAGATCTGACCTATTTCATTCAGGCCCGTCACGCAGTCAGCACTGGCGAATTCTGCAGACTGTGCCGTGGCGCTCGCAGGATAAGTCACTAATTGCAGCGAGGGTGAGGCAAGTAATTGTTTCATCGTCAGCTCCATTTTTCGTTTCCCCACATGTTGCAGGGCATTCCATCGCGGTAATAAACGCCCAGGCTTCCAGCCGGTAATTTATTGTGCACAGGTAAACGCATAGGGACGCAAAGCAATGTAAAGCTGACTATGTAAGTTGTCTGATTTATTTACGGTACAAAATGGCTTGTGAATACCACTGTCCTGTCACGATGGTTTCGTCCACCATGACGACAACGTAATAATCAGCTTTTGCAGCGACAGCTTTCGCTTTGATTTCTGCTAATGCGTCATCCGGAGAACCCCGAACCATCGTGCTTACGCTACCTATTCGCTGTAACCCTTGCGTCTGGTCGCGGCGAATCTCTTGCGGATGGTCCGTTACTGGCGGTGCTGGCTGTGGCGTACCTTGCAGTGCGCTACAGGCACTTAACATCAACACCAATAATAAACTGGCAAACCGGTAAATAACGCTATTACGTTTCCTGCTAACCATAGTGTAGTGCCTTATTAATTTAACTTTGGGGGAATGTTCCCGAATTGTTACCTGGTACGCGATTTTCGAATGAAAACGTGACGAAAGCGTAACCCACATCTCAACATTATGAACTAATACCGCCAGCAGAAACTTGTGCTAAGGATTTCTTCATGTCATACCAGACAAAAAGGAGAGACAGATGATTGAAATAGAATCACGCGAGCTGGCAGATATTCCCGTTCTTCATGCTTATCCTGTCGGGCAAAAAGATACCCCGTTACCGTGCGTAATTTTTTATCACGGCTTTACTTCATCCAGTCTGGTGTATAGCTATTTTGCCGTTGCGCTGGCGCAGGCTGGTTTGCGGGTGATCATGCCGGATGCGCCCGATCACGGTAGCCGTTTTAGTGGTGACGCAGCGCGGCGGTTAAATCAATTCTGGCAAATCTTGCTACAAAGTATGCAGGAATTCACTACTTTACGTGCGGCAATAGCCGAAGAAAACTGGCTGCTTGATGACCGTCTGGCAGTCGGTGGCGCGTCGATGGGCGCGATGACGGCACTGGGGATTACCGCTCGCCACCCCACGGTGAGATGTACCGCCAGCATGATGGGATCGGGCTATTTTACATCACTCGCCCGTTCACTGTTTCCACCGCTGATACCTGAAACGGCAGCACAGCAGAATGAATTCAATAACATTGTCGCGCCACTGGCAGAGTGGGAAGCGACAAACCACCTGGAACAACTTAGTGACAGACCTCTACTGCTGTGGCATGGCCTCGACGATGACGTTGTGCCTGCCGACGAATCACTACGTTTGCAGCAGGCCTTAAGCGAGACGGGACGGGATAAACTGCTAACCTGTTCATGGCAGCCAGGCGTGCGTCACCGCATTACGCCTGAGGCGTTAGATGCTGCCGTGACATTTTTCCGCCAGCATCTTTAAACACGCAGAATGCTGACCCCTTGCGCTTCCAGTTGTTGCAGGATTTCCGGGTTAGCATTTTTGCCGGTGATAAGCATATCGATTTGATCGGCACGGCTAAAAAGCATTCCCGCGCGTTCGCCAATCTTACTGCTATCAACCAGTACCACCAGTTTCCCTACCACGCTCAGCATCTTCTGCTCTGCCATTGCTGTCAGCATATCGGTTTTATACAACCCTTCTGCGGTCAGCCCTTTTCCGCTGGTAAACATCCAGTGCCCGGCATAGAGACTGTTTTCGCTGCCCTGCGGGCTTAAAGTGATGGACTGACTTTTGTTGTACTGTCCGCCCATAATGATCACGCTGTCATGTTCTTGATCGATCAGGTAATTTGCCAGCGGTAGATAATTAGTGATGATTTGCACTGGCTTGCCACACATTTCCCGCCCAAGCAGAAACGCGGTGGAGCCGCAGTTGATGACTACGCTTTCGCCCGGATTAACCAGCTGCGAGGCCGCTTTAGCGATACGTACTTTTTCATCGTGATTCTGCGCCTGATGCAGATTCATCGGCGTCCAGCGCGGGCGCTGTTGGGTAATAGCTTCTGCGCCATTGCGCACTTTTTTCAGTTTGCCGCTTTCGTCAAGTTTATTGATATCGCGTCGCGCAGTGGCAGGCGAAATTCCCAGACGCTCAACGACTTTCTCAACGGTCACAAAGCCCAATTGTGCGAGCATTTCCAGGAGGATTTGATGTCTTTGTGCTTCAGTCATGAGCTATTCCGATAAAATTTGATTTTTTTAGATGATATTTGAAATAGCCAGGAAATACTACGCCGGATAGCGCGAACTTCTCCACGCTACCCGGTATAAACGACAGATTACAGGAATGACTTGAACGGCAGATCCGGTTCAATAGTGAAGCAATCATCGAAACCGCGCGGATAGTGGTACTCGAAGTTGTCTTTATCCAGCGGCCAGGTAAATTTGCCACCCACCTGCCAGATAAACGGCTTGAAGCCATACTTCAGGCGATCTTTTTTCATCTCCCACAGCACGCGGATCTCTTGCGGATCGGCCTGGAAGTTTGACCAGATATCGTGGTGGAACGGGATCACTACTTTCGCATTCAGCGCTTCACCCATACGCAGCATATCGGCGCTGGTCATTTTGTCGGTGATACCGCGCGGGTTTTCGCCGTACGATCCTAACGCCACGTCGATCTGATGTTCGTTACCGTGCTTCGCATAATAGTTAGAGTAGTGGGAGTCGCCGCTGTGATACAGGGAGCCGCCAGGCGTTTTGAACAGGTAGTTCACCGCGCGATCGTCCATGCCATCTGGCAGTACGCCAGCCGCTTTTTGATCGGCAGGCAGGGTGATCAGTGCAGTACGGTCGAAAGCATCAAGCGCATGAATTTCAATGTCTTTCACTTTTACTACATCGCCCGGTTTGACCACGATGCAACGCTCTTTCGGTACGCCCCAGCCAATCCACAAATCCACACAGGTTTTCGGTCCGATAAACGGTACGTCATCTGCACAATTCTGCATCACGGCAGCAGCGACGTTAACGTCGATATGATCGTTGTGATCGTGAGTCGCCAGTACCGCGTCGATCTGGCGAATCGCAAACGGATCAAGAACAAACGGGGTGGTACGCAGGTTTGGCTGCAGTTTTTTCACGCCAGCCATGCGCTGCATCTGGTGACCCTGTTTCATTAACGGGTTACCGTGACTTTGTTTGCCAGTGCCGCACCAGAAATCAACGCAAACGTTGGTGCCACCTTCCGATTTCAACCAGATCCCGGTGCAGCCAAGCCACCACATCGCAAATGTGCCAGGAGCGACCTGTTCTTGTTCAATTTCTTCATTCAACCAGCTACCCCACTCCGGGAAAGTGCTCAGGATCCAGGATTCACGGGTGATACTTTTCACTTTACTCATCGCCATTTACCTTCATGATAGTTCAATTCGAATCAATATGTGATTGGTTTTGATTAATCCTGACACTATTTTTTCAGGAAGGCAATGACCATTTTTTGACTTTTTGCCAGGGAAGTTGTTGTTGATTTTGAGTATGGAAAGATTTAATGGAATGTGTAATTCAATTAACTAAATGAATTTAAATGGATAATTGTTTCGTTGTGTGAATCCCACTCTATCCATGTGGAATTATTTGCGGGTCGCGTCACATTTAATCATAAATAATCTTGTTGTGATTACTTTTGAAAATTAGAGTGAGTGCACAACATTCCGGGTGTGTGGAATACCCGGTTACCTCTTCTTCAGGAGATCGTTATGGAGATCCTCTACAACATCTTTACCGTGTTTTTTAACCAGGTCATGACCAATGCCCCGTTGTTGCTGGGTATTGTGACCTGTCTGGGCTACATCCTACTGCGCAAAAGTGTCAGCGTTATTATTAAAGGCACGATTAAAACCATAATTGGTTTCATGTTGTTGCAGGCAGGGTCCGGCATCCTCACCAGCACCTTCAAACCGGTGGTGGCGAAAATGTCCGAAGTCTACGGCATTAACGGCGCAATTTCCGATACCTACGCTTCAATGATGGCAACCATCGACCGCATGGGCGATGCCTATAGCTGGGTGGGTTACGCCGTATTGTTAGCGCTGGCGCTGAACATCTGTTACGTGCTGTTGCGTCGCATTACCGGCATTCGCACAATCATGTTGACCGGCCACATCATGTTCCAGCAGGCCGGGTTGATTGCCGTTACGCTGTTTATCTTCGGCTACTCCATGTGGACCACCATTATCTGTACCGCGATTCTGGTTTCGCTCTACTGGGGCATCACTTCCAACATGATGTACAAGCCGACTCAGGAAGTGACGGATGGCTGTGGTTTCTCCATCGGTCACCAGCAGCAGTTTGCATCATGGATTGCCTATAAAGTCGCGCCGTTCCTCGGCAAAAAAGAGGAGAGCGTTGAAGACCTCAAATTGCCGGGCTGGCTGAACATTTTCCACGACAACATCGTCTCCACGGCGATTGTGATGACCATCTTCTTTGGTGCCATTCTGCTCTCCTTCGGTATCGACACCGTGCAGGCGATGGCAGGCAAAGTGCACTGGACGGTGTACATCCTGCAAACTGGTTTCTCCTTTGCGGTGGCGATCTTCATCATCACGCAGGGTGTGCGCATGTTTGTGGCGGAACTCTCTGAAGCATTTAACGGCATTTCCCAGCGCCTGATCCCAGGTGCGGTTCTGGCGATTGACTGTGCAGCTATCTATAGCTTCGCGCCGAACGCCGTGGTCTGGGGCTTTATGTGGGGCACCATCGGTCAGCTGATTGCGGTTGGCATCCTGGTCGCCTGCGGCTCCTCGATCCTGATTATTCCTGGCTTTATCCCGATGTTCTTCTCTAACGCCACCATCGGCGTGTTCGCTAACCACTTCGGCGGCTGGCGTGCGGCGCTGAAGATTTGTCTGGTGATGGGGATGATCGAAATCTTTGGTTGCGTCTGGGCGGTGAAACTCACCGGTATGAGTGCCTGGATGGGCATGGCGGACTGGTCGATTCTGGCACCGCCGATGATGCAAGGCTTCTTCTCCATCGGTATCGCCTTTATGGCCGTCATCATTGTAATTGCACTGGCTTATATGTTCTTCGCTGGCCGCGCGCTGCGCGCAGAAGAAGATGCAGAAAAACAACTGGCAGAACAGTCTGCTTAATAAGGAGTTTTGATTATGACCGTACGTATTCTGGCTGTGTGTGGCAACGGACAAGGCAGTTCCATGATCATGAAGATGAAAGTGGACCAGTTTTTAACCCAATCAAACATTGACCATACGGTAAACAGCTGCGCGGTTGGCGAGTACAAAAGCGAGTTGAGTGGCGCGGATATCATCATCGCTTCTACGCACATTGCGGGCGAAATCACCGTGACCGGCAACAAATACGTGGTTGGCGTGCGCAACATGCTCTCTCCTGCCGACTTTGGCCCGAAACTGCTGGAAGTGATCAAAGAGCATTTCCCGCAGGATGTGAAGTAAGGACGCGCCATGAAATTACGTGATTCGCTGGCGGAAAATAAATCCATCCGCCTGCAGGCTGAAGCAGAGACATGGCAGGAAGCGGTGAAAATCGGCGTTGACCTGCTGGTGGCGGCAGATGTGGTAGAGCCGCGTTACTACCAGGCGATTCTGGATGGCGTTGAACAGTTCGGTCCTTATTTCGTTATCGCTCCGGGCCTGGCAATGCCGCACGGGCGTCCGGAAGAGGGCGTTAAGAAAACCGGTTTCTCTCTGGTAACGCTGAAAAAGCCGCTGGAGTTCAACCACGATGACAACGATCCGGTGGATATCCTCATCACCATGGCGGCGGTCGATGCCAATACTCACCAGGAAGTGGGCATCATGCAGATCGTCAACCTGTTTGAAGATGAAGAGAATTTTGACCGTTTACGCGCCTGCCGTACCGAGCAGGAAGTACTGGATCTCATTGACCGCACCAACGCGGCAGCTTAAGAAGGAATTGAACATGTCATTACCGATGTTGCAAGTCGCGCTGGACAACCAGACTATGGATAGCGCCTACGAAACCACTCGCCTGATTGCCGAAGAAGTCGACATTATCGAAGTGGGCACCATTCTGTGCGTGGGCGAAGGCGTGCGTGCGGTTCGTGACCTGAAAGCGCTCTACCCGCACAAAATCGTACTGGCAGACGCCAAAATTGCCGATGCAGGCAAAATCCTTTCGCGTATGTGCTTCGAAGCCAACGCTGACTGGGTGACGGTAATTTGCTGTGCGGATATCAACACCGCCAAAGGCGCGCTGGACGTGGCAAAAGAGTTTAACGGCGACGTGCAGATCGAACTGACCGGTTACTGGACCTGGGAACAGGCGCAACAGTGGCGCGATGCAGGCATTGGGCAGGTGGTTTATCACCGCAGCCGTGACGCGCAGGCCGCAGGCGTGGCGTGGGGCGAAGCGGACATCACCGCGATCAAACGTCTTTCCGATATGGGCTTCAAAGTCACCGTCACCGGAGGCCTGGCGCTGGAAGATCTGCCGCTGTTCAAGGGTATTCCGATTCACGTCTTTATCGCGGGCCGTAGTATCCGTGATGCCGCTTCTCCGGTGGAAGCCGCACGTCAGTTCAAACGTTCCATCGCTGAACTGTGGGGCTAAGGAGCGGATATGTTGTCCAAACAAATCCCGCTTGGCATCTATGAAAAAGCGCTCCCCGCCGGGGAGTGCTGGCTGGAACGCCTGCAACTGGCAAAAACGTTAGGCTTCGATTTTGTCGAAATGTCGGTAGATGAAACTGACGATCGCCTGTCGCGCCTCAACTGGAGCCGCGAGCAGCGTCTGGCGCTGGTCAATGCGATTGTTGAAACCGGCGTGCGCGTGCCGTCCATGTGCCTTTCTGCTCATCGTCGTTTCCCGCTGGGCAGTGAAGATGACGCGGTGCGGGCGCAGGGGCTGGAGATTATGCGTAAAGCTATCCAGTTCGCCCAGGATGTCGGTATTCGCGTGATCCAGCTGGCGGGCTATGACGTTTACTATCAGGAAGCCAATAACGAAACGCGTCGTCGTTTCCGTGACGGCCTGAAAGAGAGCGTTGAGATGGCAAGCCGCGCGCAGGTGACGCTGGCGATGGAGATCATGGATTATCCGTTGATGAGCTCCATCAGCAAGGCGCTGGGATACGCGCACTATCTCAACAATCCGTGGTTCCAGCTCTACCCGGATATCGGCAACCTGTCGGCGTGGGACAACGATGTGCAGATGGAGTTGCAGGCCGGAATCGGGCATATCGTCGCGGTACATGTGAAAGACACCAAACCTGGCGTCTTCAAAAACGTGCCGTTTGGCGAAGGTGTAGTGGATTTCGAACGTTGTTTCGAAACGCTCAAACAGAGTGGCTATTGCGGGCCGTACCTGATTGAGATGTGGAGCGAAACGGCGGAAGACCCGGCGGCAGAAGTGGCGAAAGCGCGTGATTGGGTGAAAGCGCGCATGGCGAAAGCGGGCATGGTGGAGGCGGCATAATGCAAAAGCTAAAACAGCAGGTATTTGAAGCCAACATGGAGCTGCCGCGCTACGGGCTGGTGACCTTTACCTGGGGCAACGTCAGCGCTATCGACCGCGAACGCGGGCTGGTGGTGATCAAGCCCAGCGGCGTTGCCTACGAAACCATGAAAGCGGCCGATATGGTGGTGGTTGATATGAGCGGCAAGGTGGTGGAAGGGGAGTATCGCCCATCTTCCGACACTGCGACGCATCTCGAACTCTACCGTCGTTACCCGTCGCTTGGTGGCATTGTCCATACCCACTCCACTCATGCCACCGCATGGGCGCAGGCGGGGCTGGCGATCCCGGCGTTAGGCACCACGCACGCCGACTACTTCTTTGGCGACATTCCGTGTACGCGCGGGTTAAGCGAAGAAGAGGTGCAGGGCGAGTATGAACTGAACACCGGCAAAGTGATTATCGAAACGCTGGGCAACGCCGAGCCGCTGCATACGCCGGGAATTGTGGTGTATCAGCACGGGCCGTTCGCCTGGGGGAAAGATGCTCACGATGCGGTGCATAACGCGGTGGTGATGGAAGAAGTGGCGAAAATGGCGTGGATTGCCCGCGGCATTAACCCACAACTCAATCACATCGACAGCTTCCTGATGAATAAACACTTCATGCGTAAACACGGTCCTAACGCTTATTACGGGCAGAAGTAGAACACGCGCTGCGGAAATTTCCTTCCTCGGGAGATAACTGGTCTAATTCCGCAGCCGTTTTTCAAAAAAAAGCCCCCTGCGAAGGGGGCAAAGCAAACTATGGCAATGTTTCGTTGGTTATACCTGGTGCTAGCGATAAATATCCGCGCTGGCGTGCATATTGCCGTTACTCCCCGGTTCCCGCATCAGAATTACGTGGTAGTACGTTGCGCCTTGCGCATCTGTTTCTTCATTTAATGCCTGACGTGCTTCGCTTTCAGTGGCGAAATTATGATTGATATAAATCACGCCTAAGCTTTGCACATCGTCCATATTTCTGGCCTGGTGGTTATTAATTTCAATGGCTGCCCATGTATTTGCACTTAGCAAAAGCACAGCCAGAAGGGCTAAAACACGACTGAACATAGATACCTCCTCGACGGCTGACTTTGTGTGCTCTCCTCTGTGATGATCTTCTGATTTAATTTTAATCAATGATAAAGAAGTTGATGGTGACCATTTCTGATGCAGTTGTTCAAAAAAACACCATGATGAAGTGTGATGAACTTCAAATCAGCGTGTTAGAGGTTAATTGCGAAAGGGGAGATTTATTTCGGCTCTGCCCTTGAGTTTAGCGAGGCATACAAGTACTATAACGCGTCATTTTTCAGCCGACCTTTAACACGTTCCTTGCCTCCCCGGGATTCGGCTGACCCAGACAGGAGGCTGAATAATCCGTAAGGAGCAATTCGATGCGTCA +>419434025 +ACGGTTTTTTCACCGTTGATTACGAGAGTATGGCCTGCGTTGTGACCGCCCTGGTAGCGTACAACATATTTAGCCCGTTCAGTCAGAAGATCGACGATCTTACCTTTACCTTCGTCACCCCATTGGGTGCCCAGTACGACGACGTTGTTACCCATTTTT +>419434026 +AAAAATGGGTAACAACGTCGTCGTACTGGGCACCCAATGGGGTGACGAAGGTAAAGGTAAGATCGTCGATCTTCTGACTGAACGGGCTAAATATGTTGTACGCTACCAGGGCGGTCACAACGCAGGCCATACTCTCGTAATCAACGGTGAAAAAACCGT +>419442075 +ACCAGGGCGGTCACAACGCAGGCCATACTCTCGTAATCAACGGTGAAAAAACCGTCCTCCATCTTATTCCATCAGGCATTCTCCGCGAAAACGTCACCAGCATCATCGGTAACGGCGTAGTGCTGTCTCCGGCTGCGCTGATGAAAGAGATGAAAGGTCTGGAAGACCGTGGTATCCCGGTTCGCGAGCGTCTGCTGCTCTCCGAAGCCTGCCCGCTGATCCTTGATTATCACGTGGCGCTGGACGTTGCGCGTGAAAAAGCGCGTGGCGCGAAAGCGATCGGCACCACCGGTCGTGGTATCGGCCCGGCTTATGAAGACAAAGTGGCTCGTCGCGGTCTGCGCGTGGGCGACCTGTTCGATAAAGCCACCTTCGCTGAAAAACTGAAAGAAGTGATGGAATATCACAACTTCCAGTTGGTGAACTTCTACAAAGCAGACGCTGTTGACTACCAGAAAGTGCTGGATGATGTCATGGCGATTGCAGACATTCTGACCGGCATGGTAGTTGATGTGTCCGATCTGCTGGACCAGGCGCGCAAGCGTGGCGATTTCGTCATGTTCGAAGGTGCGCAGGGTACGCTGCTGGATATCGACCACGGTACCTATCCGTACGTAACCTCCTCTAACACCACCGCAGGTGGCGTGGCGACCGGCTCTGGCCTGGGTCCACGTTATGTGGATTACGTTCTGGGCATCATCAAAGCGTACTCCACTCGCGTGGGTGCGGGTCCATTCCCGACCGAACTGTTTGATGAAACCGGCGAGTTCCTGTGCAAGCAGGGTAACGAGTTTGGCGCGACCACCGGTCGTCGTCGTCGTACCGGCTGGCTGGATGCAGTGGCTGTGCGTCGTGCAGTGCAGATCAACTCCCTGTCTGGCTTCTGCCTGACCAAACTGGACGTCCTGGACGGGCTGAAAGAGGTGAAAATCTGCGTCGGCTACCGCATGCCAGATGGCCGTGAAGTGACCACCACTCCGCTGGCTGCTGACGACTGGGAAGGTATCGAGCCAATCTACGAAACCATGCCAGGCTGGTCTGAGACCACTTTCGGTGTGAAAGAGCGTAGCGGCCTGCCACAGGCAGCGCTGGATTACATCAAGCGCATTGAAGAACTGACCGAAGTGCCGATCGACATTATCTCTACCGGCCCGGATCGTACTGAAACGATGATCCTGCGCGACCCGTTCGACGCATAATCTTCGTGACTGCTGGCCTGCGGGGAAACCCGTAGGCCGGATAAGCGTAGCGCCATCCGGCGACCGCTCCTGGATATCCGCTTTTTCGCCCCGTCTGTCAAATAAATTAGCCCCTAACTATCTGGCTGGTTTATCATCATTAATGAATATCTCTGCGGTTTTACCGCGTTTTCCCTTTTTTCCTGAGGTTGATGTGCAGTTAACAAGTTTCACCGATTACGGCTTACGCGCGCTAATCTACATGGCGTCGTTACCCGATGGGAAAATGACCAGTATCTCTGAAGTGACAGAGGTCTACGGCGTGTCCCGTAATCATATGGTCAAAATAATCAATCAACTTAGTCGTGCCGGATACGTTGCTGCCGTCCGCGGGAAAAATGGTGGGATCCGTCTCGGTAAACCGGCGCAAAGTATTCGTATTGGGGATGTGGTGCGTGAACTGGAGCCTTTGTCTCTGGTGAACTGCAGCAGTGAGTTCTGCCACATTACACCCGCTTGTCGCCTGAAACAGGCGCTTTCTCTGGCCGTGCAAAGTTTTCTTAAGGAACTGGATAACTACACGCTGGCCGATTTGGTTGAAGAGAATCAACCGCTTTATAAATTATTGCTGGTGGAATGAAGAAAATTTCCACCGGAGCTGACAACGGAGGAACCGATATGTCACATGATCCTTTCCAGGAACGCGAAGCTGAAAAATACGCGAATCCTATCCCCAGCCGCGAGTTCATCATTGAACACTTAACAAAACGCGAAAAACCCGCCAATCGTGAAGAACTTGCTGTTGAATTAAACATTGAAGGTGAAGAGCAAACTGAAGCCCTTCGCCGCCGCCTGCGCGCCATGGAGCGCGACGGGCAACTGGTCTTTACCCGTCGCCAGTGCTATGCGCTGCCAGAACGCCTCGACCTGTTGAAAGGGACCGTCATTGGTCACCGCGACGGTTACGGTTTTTTGCGCGTAGAGGGCCGCAAAGACGACCTCTACCTCTCATCCGAACAGATGAAAATGTGTATTCACGGCGACCAGATCCTGGCGCAGCCGCTGGGTGCCGATCGTAAAGGCCGTCGCGAAGCACGCGTGGTTCGCGTGCTGGTGCCAAAAACCAGCCAGATCGTTGGCCGCTACTTTACCGATGCCGGTGTAGGCTTTGTGGTACCGGATGACAGCCGTCTGAGCTTCGATATCCTGATCCCGCCTGAAGAGGTGATGGGCGCGCGCATGGGCTTTGTGGTAGTAGTGGAGCTTACCCAACGTCCAACGCGTCGCACCAAAGCGGTAGGTAAAATCGTCGAAGTGCTGGGCGATAACATGGGTACCGGCATGGCTGTTGATATGGCCCTGCGTACACATGAGATCCCCTACATCTGGCCAAAAGCGGTTGAAGAGCAGATTGTGGGTCTGAAGGAAGAGGTTCCGGAAGAGTCCAAAGCGGGACGCGTGGATCTCCGCAGTTTGCCGCTGGTCACCATTGATGGAGAAGATGCCCGCGACTTTGATGACGCCGTATACTGCGAGAAAAAACGCGGTGGCGGCTGGCGTCTGTGGGTTGCTATCGCCGACGTGAGCTATTACGTTCGTCCCCACACGCCGCTCGATAACGAAGCGCGCAGCCGTGGTACGTCGGTTTACTTCCCGTCTCAGGTGGTACCGATGCTGCCGGAAGTGCTCTCCAACGGCCTCTGTTCCCTGAACCCGCAGGTTGATCGCCTGTGTATGGTTTGCGAGATGACCATCTCCAGTAAAGGTCGCTTAACCGGTTATAAATTCTACGAAGCGGTAATGAGCTCCCATGCGCGTCTGACCTATACCAAGGTCTGGCATATGCTGCAGGGCGATCAGGACCTGCGTGAACAGTATGCGCCGCTGGTGAAGCACATCGAAGAGTTGCATAACCTCTACAAAACGCTGGATCAGGCGCGTGAAGAGCGCGGTGGGATCTCGTTTGAGAGCGAAGAGGCGAAGTTCATTTTCAACGCTGAACGCCGCATTGAGCGTATTGAACAGACCCAGCGTAACGATGCGCATAAGCTGATCGAAGAGTGTATGATCCTGGCGAACATCTCGGCGGCCCGTTTTGTCGAGAAAGCTAAAGAGCCGGCGCTGTTCCGTATCCACGATAAACCGTCGACGGAAGCCATTACCGCGTTCCGCTCCGTACTGGCTGAACTCGGTCTGGAGCTGCCTGGCGGTAACAAGCCAGAGCCGCGCGATTATGCCGAGCTGCTGGAATCCATTGGCGATCGTCCGGATGCAGAAATGCTGCAGACCATGCTGCTGCGCTCCATGAAACAGGCGATTTACGACCCGGAAAACCGGGGTCACTTCGGTCTGGCGCTGCAGTCTTACGCGCACTTTACGTCGCCGATCCGCCGTTATCCGGACCTGTCTTTGCACCGTGCGATCAAGTATCTGCTGGCGCAGGAGCAGGGCCATAAAGGGAACACGACTGAAACCGGCGGGTACCACTATTCAATGGAAGAGATGCTGCAGCTTGGCCAGCACTGTTCCATGACCGAACGCCGTGCCGATGAAGCGACGCGCGAAGTCTCTGACTGGCTGAAATGCGACTTTATGCTGGATCAGGTCGGTAACATTTTCAAAGGTGTTATCGCCAGCGTGACCGGGTTTGGTTTCTTTGTTCGCCTTGACGAGCTGTTTATCGACGGTCTGGTGCATGTCTCCAGCCTCGATAACGACTATTATCGTTTCGACCAGGTTGGACAGCGCCTGATTGGTGAGTCGGGTGGACAGACCTATCGCCTTGGCGACCGGGTGGAAGTCAAAGTCGAAGCCGTCAACATGGACGAGCGTAAGATTGACTTCAGTCTGATCTCCAGCGAGCGCGCGCCGCGCAACGTAGGTAAAACCGCGCGTGAGAAGGCGAAAAAAGGCGGTAACGGCAACGCGAGCGGCAAACGTCGTCAGGCGGGTAAGAAAGTGAACTTCGAGCCAGACAGCGCCTTCCGCGGTGAGAAAAAGCAGAAGCCAAAAGCGGCGAAGAAAGAGGCTCGCAAGGCGAAAAAGCCGTCCGCGAAAACACAGAAAATTGCTGCTGCGACCAAAGCGAAGCGCGCAGCGAAGAAACAGCAGGCGGAGTAAATTCTCCCCTCACCCTGACCCTCTCCCCACTGGGGAGAGGGGGAAATACCTATTATGAGAATCATCAATGAGTGAAATGATTTACGGCATCCACGCGGTGCAGGCCCTGCTGGAGCGCGCACCGGAGCGTTTTCAGGAAGTGTTCATTCTGAAAGGGCGTGAAGACAAACGTCTGATGCCGCTGATCCACGCACTGGAAGCGCAGGGCGTGGTGATCCAGCTGGCCAACCGTCAGTTCCTGGATGAGAAAAGTGAAGGCGCGGTTCACCAGGGGATTATTGCCCGCGTGAAGCCAGGCCGTCAGTATCAGGAAAACGATCTGCCGGATTTGATCGCTGCACTGGATAACCCGTTCTTCCTGATCCTTGATGGCGTGACCGATCCGCACAACCTCGGCGCGTGCCTGCGCAGCGCCGATGCGGCGGGCGTGCACGCGGTGATCGTACCGAAAGATCGTTCTGCACAACTGAACGCAACGGCGAAGAAAGTGGCCTGCGGTGCAGCAGAAAACGTTCCGCTGATCCGCGTCACCAACCTGGCGCGCACCATGCGTATGCTGCAGGAAGAGAATATCTGGATCGTCGGTACCGCCGGTGAAGCGGATCATACTCTGTATCAGAGCAAAATGACCGGCCGTCTGGCGCTGGTGATGGGTGCGGAAGGTGAAGGCATGCGTCGCCTGACGCGTGAGCACTGCGACGAGCTGATAAGCATCCCGATGGCGGGCAGCGTGTCGTCCCTGAACGTTTCTGTTGCAACGGGTATTTGCCTGTTTGAAGCGGTACGTCAGCGCGGCGAATAAACAGCAAGGCCGTCCTGTGGACGGCCTTTTGTGTTTTATCTCTCTCCCGGTGGGTGAGGGCACCAGACGGTGACAACCTTACTCCTCTAACGTCCGCAAATGGTCATCCTTCCTGAGCGTCATCAGCGCCACAATACTCACCACCGCCGTCGCCATGACGTAATATGCCGGAATGTCGAGGTTTCCCGTCTCCTTAATCAACCCGGTAATAATAAGCCCCGCACACCCCGAGAAAATGGCATTCGACAAGGAATACGCCAGACCAAGCCCGGTATAGCGCACACGCGTCGGGAACATCTCTGAGAGCATTGCCGGCCCTGGACCTGCCAGCATGCCCACCAGACCGCCAGCTATCAATACCACGATCGCTTTTACCGCGAGGGTACTGGACTCCGCCTGCAGAATTTTCAGCAGCGGCAGGGCGAGGATCAGCAGTAACGCGGTGGCGATAATCATCACCGTGCGGCGGCCAATCCTGTCGCTCAGGATCCCCGACGGAATAATGGTGAGCGCAAAGCCGACATTCGAAATCACGGCTATCAACAGTGCCTGGTTAAATCCGGTGTGCAGTGCCGATTGCAGATAGGTCGGCATAATCACCAGATAGGTATATCCCGCCGCCGACCAGACCATCACCCGGCCAATTCCCATCACGATCGCTTTAATTGTGGCGACGGTACTGGCCTGCGCGATCAGCGGTTTTTCCTGCTGCTGCACGAAGCTCGGCGTCTCTTCCATACTCACCCGCAACCAGAGCGCCACCACCCCCATAGGCAGGGCCAGGAAAAATGGGATACGCCAGCCCCAGTCATGCAGGGCTTCCGGTGTCAGTAAGGCAGAAAGCAAGGCGACAATACCCGCGCCCGCTAATAGCCCCAGCGCCACCGTGAACGATTGCCATGCGCCATACAGACCACGTTTACCGCGTGGTGCAAATTCCGTCATCAAGGAAACCGCACCACCGTACTCACCCCCCGCGAACAATCCCTGCAGGATGCGCAGCAACGTAACGATCAGCGGCGCAGCGATACCGATGCTGGCATAGACTGGCACAACACCGATGGCGGCGGTGGCGAGCGTCATCAGCACCAGCACAATAATCAGCGTCGGTTTGCGGCCAATACGGTCACCGATGCGGCCAAACACCACCGCCCCCAGTGGGCGGAAAAAGAAAGCGATGGCAAACGAGGCGTAGGTGAGGATCAGGCTGGTCAGCCCCGACTCGCCTTCAAGCTGGAAGAAGTTTTTCGCAATCACGGTGGCCAGAAAGCCGTAGACCGCAAACTCATACCACTCGATGAAATTACCAATGGAGCCTGCAATTAACGCACGCTTATGCGCATTCGGTTGCATAACTTTCCTCACTGAAAGGGGTAAGAATAAATTATTCAATAAAAGTGAAGTGATGAAATAGTTTATTCTTATGTTCTGTGAGCTATTTCACGAATGATATCAGCGGGATCGCTACCGTGTGACCTTACTCCCATGCAGCGTGCACAGGGTCTGTCCATACTTATCTTCATTGCCACTGAAGGAGGGAGACAGCATGCACTGGCAAACACATACCGTTTTTAACCAACCCGCACCGCTTTCGAACAGCAACCTTTTTCTCTCTGATTGTGCCCTGCGTGACGCGGTGGCCCGCGAAGGCGCGGAGTGGGATAGCGAGTTGCTGGCCAGTATAGGCCAGCAGTTAGGTACGGCGGAGTCGCTGGAGCTTGGCAGGCTGGCGAACGTCAATCCGCCGGAGTTACTTCGCTATGACCCCACCGGTGAGCGGCTGGATGATGTCCGTTTTCACCCCGCCTGGCATCTTCTGATGCAGGGGCTGTGCGCTAACCGGGTGCATAACCTGGCGTGGGAAGAGGAGGCGCGTAAAGGCTCCTTTGTCGCTCGCGCCGCGCGCTTCGTGTTGCATGCTCAGGTTGAGGCCGGAACGCTGTGCCCCGTGACCATGACGTTTGCCGCCACGCCGCTGCTGCAACAGGCGCTCCCTGAACCTTTCCAGAACTGGCTCACGCCGCTACTGAGCGATCGTTATGATCCTCACCTTGCCCCTGGAGCCCAAAAGCGCGGCCTGCTGATCGGCATGGGGATGACGGAAAAACAGGGCGGCTCGGACGTGCTCAGCAACACTACCAAAGCAGAAAAGTGCAGCGACGGCAGCTACCGGCTGGTGGGTCATAAGTGGTTTTTCTCTGTGCCACAAAGCGATGCGCATCTGGTGCTGGCGCAGGCGAAAGGCGGGTTGTCCTGCTTTTTTGTTCCTCGCTTTTTGCCTGACGGGCAGCGCAACGCCGTGCGCCTGGAGCGGCTGAAAGACAAGCTCGGCAACCGCTCTAACGCCAGCAGTGAAGCGGAGTTTCTGGATGCGTCCGGCTGGCTGTTAGGGGAAGAGGGGGAAGGGGTACGACAGATCCTTCGCATGGGCGGGTTAACGCGTTTTGACTGCGCTCTGGGCAGCCATGGGTTGATGCGTCGGGCATTATCCGTGGCGCTGTACCACGCCCATCAGCGGCAGACGTTCGGGAAAAACCTCATCGATCAGCCACTGATGCGCGACGTCCTGAGCCGCATGGCGCTGGTGCTGGAGGGGCAAACGGCGCTGCTGTTTCGTCTTGCCCGGGCGTGGGATAAACGCGCCGATCCGCAGGAGGCGGCCTGGGCGCGGCTTTTCACGCCAGCCGCGAAATTCAGCGTCTGCAAAGCGGGTATCCCGTTCGTGGCAGAGGCGATGGAGGTGTTGGGCGGCATCGGGTACTGTGAGGAGAGTGAACTCCCCCGCCTGTATCGCGAGATGCCGGTGAACAGCATCTGGGAAGGCTCAGGGAACATCATGTGTCTGGATGTTCTGCGCGTTCTGGCGAAGCAGCCGGGTATGTTCGATCTGCTGGCAGAGGATTTTGCGCAGGTGAAAGGTCAGGACAGACACTTCGATCGTAGCTGGCGGCAGCTGCAGCAAAAACTGCGTAAACCGCAGGAGGCGCAGGGGCGGGAGATTGCGCATCAGCTATTCCTGCTGGGCGCCGGAAGCCAGATGCTGCGGCACGCCTCTCCGCCCGTCGCGCAGGCGTGGTGCCGCATGATGCTGGATACCCGTGGCGGCACGCTGATGACAGAGCAGGTTCAAAGCGATCTTCTGCTGCGCGCCACGGGCAGGGTAGGCTAGTTTTTAAGCTGGAACAGGCTCACCAGTTGAGTGAGGTGCGACCCTTTCTCGCGCAGTGATTGTGCGGTTTGCTCGCTGCGCGAGACGCGATCGGCGTTGATGTGGGAGGCTTCACCAATATGGGTCATGGCCAGATTCACCTGACGGATCCCCGCCGACTGTTCGCGGGATGCATGGTTAATCTCGGTCACCAGTTGGTTGATGTTATCGATGTGCGCGATGATGGCATCCATCGCCAGACGCGTCTGCTCTGAGAGCGCATGGCCTTCACTCACCTCGTTCAGCGTGTCGCCAATCAGCTGCTCAATCTCTTTCACCGCATTAGCGCTGCGTGCCGCCAGGGCGCGCACTTCCTGCGCGACCACAGCAAACCCTTTTCCGTGTTCGCCGGCACGTGCTGCTTCAACCGCTGCATTAAGCGCCAGAATGTTAGTCTGGAAAGCAATCGACTCAATCACACGCGTGATGTCCTCGATGCGCTTTGAGGCGTCGCGAATATCGTCCATGGTGGAGACCGCGTGCGTCACCGTCTCGCCCCCCTGATGCACCGCGCGTGAGGTTTCCCCCACCAGCTGCTGCGTCTGTTCCATATTGGCCGCGTTTTGCTGCACGGTTGCGGCGAGTTGTTCCATACTCGCGGAGGTCTCTTCAACGCTACTGGCCTGTTTGTTGATCTGCTCTGAGATCTCACCGGTATCAGAGGCCAGGGCGTTAGTGCCCAGATGGATCTCGCCTGCGGCCTCGCGTACCTGCAGGACAATCTTTTGCAGACCGCCGCCGATCCCGTTGATGGCGTCGATAAGCTGGCCAACCTCATCCTGGCGGGTAACGGACAGGCTGGCACGCAGATCGCCTGCCGCATATTGTCGGGCAAGGTGAATGACGTTACGCAGCGGGCGCGTCAGCATGCGACGAATGATGATGACAAACAGCGCGGCAAACAGGACTGACAGCGCCACGCCTGCCAGCAGGAAGCGATCCCGCATCGTGGTGACGCTTGAGAGCAGGACCGATTTATCCACTTCCCCCACGATGGTCCAGTTCCAGCCCGGCAGCGGCGTGTAGGCCATTTTCAGTATGCGACCACCCTCACTTGTGCGTTCCAGCGTGCCCGGGGTATTGCTCAGCAACTGCTGCTGGGTGGCGCTATCCCACTCAGGAAGCTGGCCTTCCCGGTTCGAGTGGAACAGGAACTGTCCGCGCGTTTTACCGTTACTGCGATCCAGCACGAAGAAGTGTCCGCTGTCACCTAAACGACGATTGAGGATTTTTTCGCGCATCACGTTCCAGGAGTGGGTGATATCCACACCAACAAAAATGATCCCAATGACCTGGCCTTCTGCGTTTTTGAACGGCTGATACTGGGTGATATAGCGCTTACCGAACAGCAACGCCAGACCGCGATAGACCTCGCCTTTAGTGACGGCCGCATAGGCCGGGCTGGCAGTGTCCAGAACGGTACCCATTGCCCGATCGCCGTTCTCTTTGCGCAGGGAGGTGGCGACACGGACAAAGTCATTACCGCTGCGCACAAACAGGGTCGAGATTGCCCCTGTACGCGTCAGGAAGTCGTCAGAAAGTGCATTGTTTTCATGCAGGCCTGTTTCACCCCCTTTCAGAAGGGGAACGCTAAGCCCGTTAATGGTCTGGAGTTGATTGCTGTCGACGCTCAAAGGTTGCGGTAAAAAGGTGGTGAACAGCCGGGTATAGCTCTCGACCTCTTCGCTCAGACTGGTGTTAAACATCTGTACCATATCAACCATACCGGTGGACTGGTTATGCAGGTCTTCTACCGCAAGGGCTTCAAGCTGCTGGCTGGCTTTATGGCTGAGCAGAAAAGTGAAAAGCAGAAACAGCGTGGCGACACTCACGCCGGTAAGAAGCGATAGCTTTGCGCCCAGACCCGCACGGCGAAAAAAAGTGATCATAAATTGCTCATTATTGAAAAGGTATGGCTTTTCAACGGCAGGACAGAGCTAACATTTACTTAAATAATGTAACAAAATGTTATCAAATTGTTTTTAATGGGGTTGAAAGAAGATAAAAAATTTGCAAAAACGAAAAGCCACTAAAAATAAGTGGCTTTTATCGGAGGTGATTAGACGTAGAGAATAGCCTGTACGCGCCAATGATCGCTGCGGTTATCTTCCTGCATCTGAATAATTCGATACCAGGAAGCGCCCTGTTCATCGGCTTTTAGTGCCACGACACGTTCAACATCTTGCGGGCTCCCCGAAATGTTATTGACGGAGATCTGGCCAATTTCATTAAGGCCAGTGACGCAATCAGCACTGGCGAATTCTGCTGACTGTGCAGTCGTGCTCACAAGGCCTACTGAGAGCAACAGAGAGGTCAAAGCAAGAGTTCGTTTCATTGTCAGCTCCATTTCACATTTCTCCGGTATCCGCCGGGCACTCCTTCGCAAATAAACTCACTTCCATTGTCGCGGGCATGGAGTTTATTGTGGACAGGAAAATGTCTATGGACGCAAAGCAGTGTAAATGTCGTTCAAATGAAGATCGTTATTTACGGTACAATATAGCCTGTGAATACCACTGTCCCGTAATGATGGTTTCATCGATCATAATGATGACGTAATAATCTGCTTTGGCGGCGGCAGCTTGCGCCTTTATTGACTCCTCTGCGTCATCCGGGGATCCGCGAACCAGCGCGGAGACGGTACCCATTCGTTGTAATCCTTCCGTCTGATTACGACGAATCTCCTGCGGATGGTCGGCGACCGGGGGAGCGGGTTGCGGTGTCCCCTGTAGTGCACTACAGCCACTGAGCAGAACCAGCAACAATAAAGTAGCAAACCTGCGCATAACCATATCTCGTTTCCTGATAGCCATAGTGTAGTTGTCTGCGAATTTAGTTTTGGGGGAATGTTCCCGAAGTGTTATCTGGTACGTATATTTCGAATGAAAATATCGTGAAAGCGTAATCCAGTTCTCAACATTATGAATCATTCATCAGCACAGGGTCGACAATGATTGAAATTGAAACTCGCCGCCTCGGCAATCATGAAATATTACACGCTATCCCTGCGGGAAAAAGTGCACACCCGCTGCCTGTTGTGGTTTTTTATCATGGCTTTACTTCATCGAAGCTGGTGTACAGCTACTTTGCGGTGGCGCTGGCGCAGGCCGGTTTTCGGGTAGTGATGCCGGATGCGCCCGATCACGGTGCACGTTTTACCGGTGATGAACAGGTGCGACTGGGGCAGTTCTGGCAGATTTTGCACGGTAGCCTGAGCGAATTTGCCGGGCTGCGCGATGCGCTTTACCAGGCGGGGCTGGTGGCGGATCAACGGCTGTCGGTGGCCGGCGCATCGATGGGGGGAATGACGGCGCTCGGGATCATGGCTCGTCACCCTGAGGTGACCTCCGTGGCGTGCCTGATGGGCTCGGGCTATTTTACGTCATTGTCAAAAACGCTGTTTCCACCGCAAGACGCGACGGAGATTGATGCGTTGCTGGCCGAATGGGAAGTGACCCGGGCGTTACCGCGTCTGGCCGATCGCCCGTTGCTGTTGTGGCATGGTGACGCGGATGATGTGGTGCCCCCTGGCGAAACCTTCCGTCTCCAGCAGGCACTACAGCGCGAAGGGCTGGACGGCAACCTGACCTGTCTGTGGGAAGCGGGGGTTCGCCACCGTATCACGCCAGCGGCACTGGACGCGACGGTGGACTTTTTCCGCCAGCATCTTTAAACGCGCAGAATTTTGACGCCCTGATCTTCCAGCTTCTGGAGGATCTCTGGATTGGCATGTTTGCCGGTGATCACCATGTCAATCTGTTCGGCGCGGCTGAACAACATGCCAGCTCGCTCGCCGACTTTGCTGCTGTCGACCAGTACGACGAGCTTGCCCACGACGTTAAGCATATTTTGCTCTGCCATCGCGGTTAACATGTCGGTTTTGTAGAGCCCGTCCGCGGTCAGGCCTTTGCCGCTGGTAAACATCCAGTGCCCGGCATAGAGGCTGTTTTCGCTATCCTGGGGACTGAGGGTAATGGATTGGCTCTTATTATACTGGCCGCCCATGATCACCACGCTTTCATGTTCCTGATCGATAAGATAGTTAGCCAGCGGCAGATAGTTGGTGATGATTTGCACCGGTTTACCGCACATCTCGCGGCCCAGCAGAAATGCCGTGGAGCCGCAGTTGATCACCACGCTCTCACCCGGGTTGACCAGCTGTGATGCGGCTCTGGCAATGCGCACTTTTTCATCGTGGTTTTGCGCCTGATGGATGTTCATCGGCGTCCAGCGGGGGCGCTGCTGGCTGATGGCTTCCGCGCCGTTACGGACTTTTTTCAGCTTACCGCTCTCATCCAGCTTGTTGATATCGCGTCGTGCCGTCGCGGGTGAAATCCCTAAACGTTCGATCACTTTCTCGACGGTGATAAACCCTGTTTGCGCCAGGAGTTCCAGTAATATTTGATGCCGTTGCGCTTCCGTCATGAGCTATTCCGATAAGAATTGATTTGAAAAGATGATATTTGAAATAGCGTGAAATTACTAAAATAAATATGAAATCGCCAGACGCAAGGTCTGGCGATGGGGGTTCACAATCAGAGGAATGACTTGAACGGCAGGTCTGGCTCAATGGTGAAGCAATCATCGAAACCGCGTGGGTAGTGATACTCAAGATTGTCTTTGTCCAGCGGCCAGGTGAACTTGCCGCCTACCTGCCAGATAAATGGCTTGAAGCCATACTTCAGACGGTCTTTTTTCATCTCCCACAGTACGCGGATTTCCTGCGGATCGGCCTGGAAGTTTGACCAGATATCGTGGTGGAAAGGAATCACTACTTTGGTGTTCAGTGCTTCCGCCATGCGCAGCATATCGGCGCTGGTCATTTTGTCGGTAATGCCGCGTGGGTTCTCGCCGTAGGAGCCCAGCGCCACGTCAATCTGATGCTCGTTACCATGCTTCGCATAGTAGTTGGAGTAGTGAGAATCACCGCTGTGGTACAGGGAACCGCCAGGGGTTTTAAACAGATAGTTCACTGCTCGCTCATCCATGCCGTCTGGCAGGACGCCTGCGGCTTTCTGGTCAGCAGGCAGGGTGATCAGCGCGGTGCGGTCAAAGGCGTCCAGCGCATGGATTTCAATGTCTTTAATTTTCACCACGTCGCCTGGCTTCATGACGATGCAGCGCTCTTTCGGCACGCCCCAGCCAATCCAGAGATCCACGCAGGTCTGCGGTCCGATAAACGGCACGTCGTCCGCGCAGTTTTGCATCACCGCTGCCGCCACGTTTACATCGATGTGATCGTTATGATCGTGGGTGGAAAGGACGGCGTCGATCTGGCGAATGGCAAAAGGATCAAGAACAAACGGCGTGGTGCGCAGGTTCGGCTGCAATTTTTCGACACCTGCCATGCGCTGCATCTGATGACCTTTTTTCATCAGCGGATTGCCGTGGCTCTGTTTGCCGGTACCGCACCAGAAATCAACGCAAATATTGGCGCCACCCTCGGATTTCAGCCAGATGCCGGTGCAACCCAGCCACCACATTGCAAACGTACCAGGAGCAACCTGTTCCTGCTCAATCTCTTCATTCAGCCAGCTGCCCCATTCCGGGAAGGTGCTCAGAATCCATGATTCACGGGTGATGGTGTTCACTTTACTCATCGTTTTGACTCCTGGTTTAATCAAAAGTAATCATTTGGTGATTTGTTGTGATTAATGCTGGCACTCTTTGAATCGGTTTGCAACGAGTAAATTGAGGAAATTTATCTTCGCCATGTCACAGATAATCTATTTCTACGTTGTTAGAATATCCGCTATCAATGATTAATTGTATGAATTATAAGAAATAATTTATGCGTGGGAATCGATAGTGAAAATCATTACTAACACCATGGAAATAATTTGCGTGATACGTCACAAATAATCAAATGCAATCTTGTGGTGATTATTTGTGATTAATAGAGTGATGGCACCAACCGAACAGGGATTACCCCCTCGTGTTCTCATTTCTGGAGAGAGTTATGGAGATCCTCTACAACGTCTTTACCGTTTTTTTTAATCAGGTAATGACTAACGCCCCGCTTTTGCTGGGTATCGTGACGTGCCTGGGCTACATCCTTCTGCGCAAAAGCGTCAGCGTCATCATCAAAGGCACAATCAAAACCATCATCGGTTTCATGCTGTTGCAGGCGGGTTCAGGCATTCTGACCAGCACGTTTAAGCCTGTGGTTGCGAAGATGTCGGAGGTGTATGGCATCAACGGCGCCATCTCTGACACCTACGCGTCGATGATGGCCACCATTGACCGCATGGGAGATGCCTACAGTTGGGTGGGGTACGCGGTACTGCTCGCGCTGGCGTTGAACATCATTTACGTTCTGCTGCGCCGCATTACCGGCATCCGCACCATCATGCTGACTGGCCACATTATGTTCCAGCAGGCCGGGCTGATTGCGGTGTCTCTCTATATCTTCGGCTACCCCATGTGGACCACGATTATCTGCACCGCCGTGCTGGTATCGCTCTACTGGGGTATCACCTCCAACATGATGTACAAGCCGACGCAGGAGGTCACCGACGGCTGCGGTTTCTCCATCGGCCATCAGCAGCAATTCGCCGCCTGGCTCGCTTACAAGGTCGCACCGTACCTGGGTAAAAAAGAGGACAGCGTAGAAGATCTCAAGCTGCCGGGCTGGCTGAATATCTTCCACGACAACATCGTCTCAACCGCCATTGTGATGACCATCTTCTTCGGCGCCATTCTGCTCTCCTTCGGGATTGATGTGGTGCAGGCGATGGCGGGGAAAACGCACTGGACGGTTTATATCCTGCAGACCGGTTTCTCCTTCGCGGTAGCCATTTTCATCATTACCCAGGGCGTCCGTATGTTTGTTGCCGAACTGTCTGAAGCCTTTAATGGGATCTCCCAACGCCTGATTCCTGGTGCGGTGCTGGCCATTGACTGTGCGGCTATCTACAGCTTTGCGCCAAACGCGGTGGTCTGGGGCTTCATGTGGGGCACCATCGGCCAGTTGATTGCGGTAGGCATTCTGGTCGGCTGCGGCTCATCCATTCTGATTATTCCTGGCTTTATCCCAATGTTCTTCTCCAACGCCACCATTGGCGTCTTTGCTAACCACTTTGGCGGCTGGCGCGCGGCGCTCAAGATCTGTCTGGTGATGGGCATGGTGGAGATCTTCGGTTGCGTGTGGGCGGTCAAGCTCACCGGTATGAGCGCCTGGATGGGCATGGCGGACTGGTCAATCCTGGCACCGCCAATGATGCAGGGCTTTGCGTCCGTCGGGCTGGTCTTTATGGCCGTCATCATCCTGATTGCTCTGGCTTATATGTTCTTCGCTGGCCGTTCTCTGCGAGCTGAAGAAGATGCGGAAAAACAAACAGCAGAAGTTTCTGCTCACTAAGGAGTTTCGATTATGACCGTACGTATCCTGGCTGTGTGTGGCAATGGGCAAGGTAGCTCCATGATCATGAAGATGAAAGTGGACCAGTTTTTAACCCAGTCAAACATTGACCACACGGTGAACAGCTGCGCGGTGGGTGAATACAAAAGTGAACTGAACGGCGCCGATATCATCATCGCGTCTACCCATATCGCCGGTGAAATTAGCGTTTCTGGCAACAAATATGTCGTGGGGGTACGCAACATGCTCTCCCCTGCGGATTTCGGCCCAAAACTGCTGGAAGTGATCAAAGCGCACTTCCCCCAGGACGTGAAGTAAGGACGCCACATGAAACTACGTGATTCGCTGGCAGAGAATAACTCCATCCTTTTACAGGCTGAGGCCAGCACCTGGCAGGAGGCGGTCAAGCTGAGTGTGGATCTGCTGGTTAAGGCTGACGTTGTCGAGCCGCGGTATTACCAGGCCATTCTTGATGGTGTGGCGCAGCATGGTCCTTATTTTGTCATCGCGCCAGGCCTTGCAATGCCGCACGGTCGCCCGGAAGAGGGCGTGAAGAAAACCGGCTTCGCGCTGGTAACGCTGAAAACGCCTTTGGTGTTTAACCATGAAGATAACGACCCGGTCGACATCCTGATCACCATGGCGGCCGTCGATGCCAATACCCATCAGGAGGTTGGCATCATGCAGATCGTTAACCTGTTTGATGACGAAGCGAATTTTGATCGTTTACGCGCCTGCCGCACCGAGCAGGAAGTGCTGGATTTAATTGATAACGCCACAGCGGCGGCAGTTTAAGAAGGAATTGAAAATGTCATTACCAATGTTGCAGGTTGCGCTGGATAACCAGACTCTGTCCGATGCGTATGAAACCACCCGCTTGATTGCGGAAGAGGTGGATATTATCGAAGTTGGCACCATTCTGTGCGTAGGCGAAGGCGTGCGCGCCGTTCGCGATCTGAAAGCGCTCTACCCGCATAAAATCGTGCTGGCCGATGCCAAGATTGCCGATGCAGGCAAAATTCTCTCCCGCATGTGTTTTGAAGCCAATGCCGACTGGGTCACTGTGATCTGCTGTGCAGATATCAACACCGCGAAAGGCGCGCTGGATGTGGCGAAAGAGTTCAACGGCGATGTGCAGATTGAACTGACCGGTTTCTGGACCTGGGAACAGGCCCAGGCGTGGCGCGATGCTGGCATTCAGCAGGTCGTTTATCACCGCAGCCGTGATGCGCAGGCCGCCGGCGTGGCGTGGGGAGACGCGGATATCAGCGCCATTAAACGTCTTGCTGACATGGGCTTTAAAGTGACCGTTACCGGTGGCCTGGCACTGGAAGATCTGCCGCTGTTTAAAGGTATCCCTATTCACGTCTTTATCGCGGGTCGCAGCATTCGTGATGCCGCGTCTCCGGTGGAAGCGGCACGTCAGTTCAAACGTTCAATCGCTCAGCTTTGGGGCTAAGGAGCGGGTATGTTGTCTAAACAGGTCCCGCTTGGCATCTATGAAAAGGCACTCCCCGCGGGGGAGTGCTGGCTGGAGCGGCTGAAACTGGCGAAACAGTTGGGCTTCGATTTTGTCGAAATGTCCGTGGATGAGACCGATGAACGTCTTTCTCGCCTCGACTGGAGCCAGGAGCAGCGTCTGGCGCTGGTGAGTGCGGTCGCCGAAACGGGCGTACGCGTGCCGTCTATGTGCCTCAGTGCCCACCGCCGTTTTCCGCTTGGCAGTGAAGATGATACGGTGCGCGCGCAGGGGCTGGAGATCATGCGTAAAGCCATTCGTTTTGCGCAGGATGTCGGTATTCGCGTGATACAGCTTGCCGGGTATGACGTTTACTATCAGGAAGCCAATGACGAAACGCGTCGTCGTTTTCGTGATGGCCTGAAAGAGAGCGTTGAAATGGCTAGCCGCGCGCAGGTGACGCTGGCGATGGAGATCATGGACTATCCGTTAATGAACTCGATCAGCAAGGCGCTGGGCTACGCGCATTACCTGAACAATCCGTGGTTCCAGCTCTATCCTGATATCGGCAACCTGTCGGCGTGGGATAACGACGTACAAATGGAACTGCTGGCGGGGATGGGCCATATCGTCGCGGTTCATGTCAAAGATACACGTCCTGGGGTATTCAAAAACGTTCCGTTCGGCACCGGGGTGGTGGATTTCGAACGGTGCTTCCAGACGCTCAAACAGGCGGGGTATTGCGGACCTTACCTGATTGAGATGTGGAGCGAAACGTCAGATGACCCGGCAGGTGAAGTGGCTAACGCTCGCGACTGGGTACGGGAACGTATGGCACGGGCCGGCTTACTGGAGGCTGAATATGCTTAAGCTTAAGCAGCAGGTCTTTGACGCTAATATGGATCTCCCGCGCTATGGGCTGGTGACCTTCACCTGGGGAAACGTCAGTGCTATCGACCGAGAGCAGGGACTCGTGGTGATTAAGCCCAGCGGCGTGGCATATGACGCTATGAGCCCTGACGATATGGTGGTGGTTGATCTTGAGGGTAACGTTGTCGACGGCAAATGGCGCCCTTCTTCAGATACAGCCACCCATCTGGCGCTCTACCGGCGTTACCCTTCTCTGGGCGGCGTAGTGCATACGCACTCTACGCATGCCACAGCCTGGGCACAGGCGGGGCGGGCCATTCCGGCTCTGGGAACCACGCATGCGGACTACTTCTTTGGTGACATTCCGTGCACGCGGGCACTCACGCAGACCGAAGTGGAAGGCGAGTACGAGCTCAACACCGGCAACGTCATTATCGAAACGCTGGGTGAGAGCGAACCGCTGCATACGCCGGGCATTGTGGTCTATCAGCACGGTCCGTTCGCCTGGGGAAAAGATGCGCATGACGCTGTCCATAACGCGGTAGTCATGGAGGAGGTGGCACGCATGGCGTGGATTGCTCGCGGCATCAACCCACAGCTTCAGGGCATTGATGATTACCTGATGAACAAGCATTTCATGCGCAAGCACGGTCCAAACGCCTATTACGGGCAGAAGTGAATAAGTGCTCTGGAATACCGAAAACAGTTGTAACCGGTGGTATTTCAGAGCCATTCATAAAAAAAATCCCCCGGGCAGGGGGCAAGTAAAACGATGGCTATATTCTTTTTGTTGGCTTTCCTGGTGCTAGCGTCAAAGCGTTATCGGTAAATATCTGCACTGGCGTGCATGTTGCCGTTGCTGCCGGGCTCACGCATCAGAATAACGTGGTAGTAATTTGCCCCCTGAGCATCGGTTTCTTTATTAAGCGCCTGATCTGCTTCGCTCTCTGTGGCGAAATGGTGATTGATGTAAATAACGCCTAAGCTCTGCACATCATCCATGTTTCTGGCCTGTCGGCTGTCTATCTTGATGGCTGCCATCGCGTTTGCACTGAGCAAAAGCGCAGCCATTACGGCAATTGCGATTTTTTTCATGATATGCGCTCCACGACTGCGTGCTGTGAGACGGTTGTTTGCTCCCCTCCGGTATTTATATGGTCTCTGATTAAAGTGTAATCACTTATCCGGCGAGGATGCGTGACCATTTCTGATGCAGTTGTTCAAAAAAACAACGCTTCCTGATGTGGTTAATTTTAAATCACCCACTTAGACCAGCTTTGCGGTTTGTGCGAATTATTTGTGCAATCAGCTTGAGTTTCCTGGGGGGCGCAAGTATTATGACGCGTCAATTTTTCAGCCGACCTTTAACACGTTCCTTGCCTCCCCGGGCCTCGGCTGACCCAGACAGGAGGCTGAATAATCCGTAAGGAGCAATTCGATGCGTCA +>419442076 +TGACGCATCGAATTGCTCCTTACGGATTATTCAGCCTCCTGTCTGGGTCAGCCGAGGCCCGGGGAGGCAAGGAACGTGTTAAAGGTCGGCTGAAAAATTGACGCGTCATAATACTTGCGCCCCCCAGGAAACTCAAGCTGATTGCACAAATAATTCGCACAAACCGCAAAGCTGGTCTAAGTGGGTGATTTAAAATTAACCACATCAGGAAGCGTTGTTTTTTTGAACAACTGCATCAGAAATGGTCACGCATCCTCGCCGGATAAGTGATTACACTTTAATCAGAGACCATATAAATACCGGAGGGGAGCAAACAACCGTCTCACAGCACGCAGTCGTGGAGCGCATATCATGAAAAAAATCGCAATTGCCGTAATGGCTGCGCTTTTGCTCAGTGCAAACGCGATGGCAGCCATCAAGATAGACAGCCGACAGGCCAGAAACATGGATGATGTGCAGAGCTTAGGCGTTATTTACATCAATCACCATTTCGCCACAGAGAGCGAAGCAGATCAGGCGCTTAATAAAGAAACCGATGCTCAGGGGGCAAATTACTACCACGTTATTCTGATGCGTGAGCCCGGCAGCAACGGCAACATGCACGCCAGTGCAGATATTTACCGATAACGCTTTGACGCTAGCACCAGGAAAGCCAACAAAAAGAATATAGCCATCGTTTTACTTGCCCCCTGCCCGGGGGATTTTTTTTATGAATGGCTCTGAAATACCACCGGTTACAACTGTTTTCGGTATTCCAGAGCACTTATTCACTTCTGCCCGTAATAGGCGTTTGGACCGTGCTTGCGCATGAAATGCTTGTTCATCAGGTAATCATCAATGCCCTGAAGCTGTGGGTTGATGCCGCGAGCAATCCACGCCATGCGTGCCACCTCCTCCATGACTACCGCGTTATGGACAGCGTCATGCGCATCTTTTCCCCAGGCGAACGGACCGTGCTGATAGACCACAATGCCCGGCGTATGCAGCGGTTCGCTCTCACCCAGCGTTTCGATAATGACGTTGCCGGTGTTGAGCTCGTACTCGCCTTCCACTTCGGTCTGCGTGAGTGCCCGCGTGCACGGAATGTCACCAAAGAAGTAGTCCGCATGCGTGGTTCCCAGAGCCGGAATGGCCCGCCCCGCCTGTGCCCAGGCTGTGGCATGCGTAGAGTGCGTATGCACTACGCCGCCCAGAGAAGGGTAACGCCGGTAGAGCGCCAGATGGGTGGCTGTATCTGAAGAAGGGCGCCATTTGCCGTCGACAACGTTACCCTCAAGATCAACCACCACCATATCGTCAGGGCTCATAGCGTCATATGCCACGCCGCTGGGCTTAATCACCACGAGTCCCTGCTCTCGGTCGATAGCACTGACGTTTCCCCAGGTGAAGGTCACCAGCCCATAGCGCGGGAGATCCATATTAGCGTCAAAGACCTGCTGCTTAAGCTTAAGCATATTCAGCCTCCAGTAAGCCGGCCCGTGCCATACGTTCCCGTACCCAGTCGCGAGCGTTAGCCACTTCACCTGCCGGGTCATCTGACGTTTCGCTCCACATCTCAATCAGGTAAGGTCCGCAATACCCCGCCTGTTTGAGCGTCTGGAAGCACCGTTCGAAATCCACCACCCCGGTGCCGAACGGAACGTTTTTGAATACCCCAGGACGTGTATCTTTGACATGAACCGCGACGATATGGCCCATCCCCGCCAGCAGTTCCATTTGTACGTCGTTATCCCACGCCGACAGGTTGCCGATATCAGGATAGAGCTGGAACCACGGATTGTTCAGGTAATGCGCGTAGCCCAGCGCCTTGCTGATCGAGTTCATTAACGGATAGTCCATGATCTCCATCGCCAGCGTCACCTGCGCGCGGCTAGCCATTTCAACGCTCTCTTTCAGGCCATCACGAAAACGACGACGCGTTTCGTCATTGGCTTCCTGATAGTAAACGTCATACCCGGCAAGCTGTATCACGCGAATACCGACATCCTGCGCAAAACGAATGGCTTTACGCATGATCTCCAGCCCCTGCGCGCGCACCGTATCATCTTCACTGCCAAGCGGAAAACGGCGGTGGGCACTGAGGCACATAGACGGCACGCGTACGCCCGTTTCGGCGACCGCACTCACCAGCGCCAGACGCTGCTCCTGGCTCCAGTCGAGGCGAGAAAGACGTTCATCGGTCTCATCCACGGACATTTCGACAAAATCGAAGCCCAACTGTTTCGCCAGTTTCAGCCGCTCCAGCCAGCACTCCCCCGCGGGGAGTGCCTTTTCATAGATGCCAAGCGGGACCTGTTTAGACAACATACCCGCTCCTTAGCCCCAAAGCTGAGCGATTGAACGTTTGAACTGACGTGCCGCTTCCACCGGAGACGCGGCATCACGAATGCTGCGACCCGCGATAAAGACGTGAATAGGGATACCTTTAAACAGCGGCAGATCTTCCAGTGCCAGGCCACCGGTAACGGTCACTTTAAAGCCCATGTCAGCAAGACGTTTAATGGCGCTGATATCCGCGTCTCCCCACGCCACGCCGGCGGCCTGCGCATCACGGCTGCGGTGATAAACGACCTGCTGAATGCCAGCATCGCGCCACGCCTGGGCCTGTTCCCAGGTCCAGAAACCGGTCAGTTCAATCTGCACATCGCCGTTGAACTCTTTCGCCACATCCAGCGCGCCTTTCGCGGTGTTGATATCTGCACAGCAGATCACAGTGACCCAGTCGGCATTGGCTTCAAAACACATGCGGGAGAGAATTTTGCCTGCATCGGCAATCTTGGCATCGGCCAGCACGATTTTATGCGGGTAGAGCGCTTTCAGATCGCGAACGGCGCGCACGCCTTCGCCTACGCACAGAATGGTGCCAACTTCGATAATATCCACCTCTTCCGCAATCAAGCGGGTGGTTTCATACGCATCGGACAGAGTCTGGTTATCCAGCGCAACCTGCAACATTGGTAATGACATTTTCAATTCCTTCTTAAACTGCCGCCGCTGTGGCGTTATCAATTAAATCCAGCACTTCCTGCTCGGTGCGGCAGGCGCGTAAACGATCAAAATTCGCTTCGTCATCAAACAGGTTAACGATCTGCATGATGCCAACCTCCTGATGGGTATTGGCATCGACGGCCGCCATGGTGATCAGGATGTCGACCGGGTCGTTATCTTCATGGTTAAACACCAAAGGCGTTTTCAGCGTTACCAGCGCGAAGCCGGTTTTCTTCACGCCCTCTTCCGGGCGACCGTGCGGCATTGCAAGGCCTGGCGCGATGACAAAATAAGGACCATGCTGCGCCACACCATCAAGAATGGCCTGGTAATACCGCGGCTCGACAACGTCAGCCTTAACCAGCAGATCCACACTCAGCTTGACCGCCTCCTGCCAGGTGCTGGCCTCAGCCTGTAAAAGGATGGAGTTATTCTCTGCCAGCGAATCACGTAGTTTCATGTGGCGTCCTTACTTCACGTCCTGGGGGAAGTGCGCTTTGATCACTTCCAGCAGTTTTGGGCCGAAATCCGCAGGGGAGAGCATGTTGCGTACCCCCACGACATATTTGTTGCCAGAAACGCTAATTTCACCGGCGATATGGGTAGACGCGATGATGATATCGGCGCCGTTCAGTTCACTTTTGTATTCACCCACCGCGCAGCTGTTCACCGTGTGGTCAATGTTTGACTGGGTTAAAAACTGGTCCACTTTCATCTTCATGATCATGGAGCTACCTTGCCCATTGCCACACACAGCCAGGATACGTACGGTCATAATCGAAACTCCTTAGTGAGCAGAAACTTCTGCTGTTTGTTTTTCCGCATCTTCTTCAGCTCGCAGAGAACGGCCAGCGAAGAACATATAAGCCAGAGCAATCAGGATGATGACGGCCATAAAGACCAGCCCGACGGACGCAAAGCCCTGCATCATTGGCGGTGCCAGGATTGACCAGTCCGCCATGCCCATCCAGGCGCTCATACCGGTGAGCTTGACCGCCCACACGCAACCGAAGATCTCCACCATGCCCATCACCAGACAGATCTTGAGCGCCGCGCGCCAGCCGCCAAAGTGGTTAGCAAAGACGCCAATGGTGGCGTTGGAGAAGAACATTGGGATAAAGCCAGGAATAATCAGAATGGATGAGCCGCAGCCGACCAGAATGCCTACCGCAATCAACTGGCCGATGGTGCCCCACATGAAGCCCCAGACCACCGCGTTTGGCGCAAAGCTGTAGATAGCCGCACAGTCAATGGCCAGCACCGCACCAGGAATCAGGCGTTGGGAGATCCCATTAAAGGCTTCAGACAGTTCGGCAACAAACATACGGACGCCCTGGGTAATGATGAAAATGGCTACCGCGAAGGAGAAACCGGTCTGCAGGATATAAACCGTCCAGTGCGTTTTCCCCGCCATCGCCTGCACCACATCAATCCCGAAGGAGAGCAGAATGGCGCCGAAGAAGATGGTCATCACAATGGCGGTTGAGACGATGTTGTCGTGGAAGATATTCAGCCAGCCCGGCAGCTTGAGATCTTCTACGCTGTCCTCTTTTTTACCCAGGTACGGTGCGACCTTGTAAGCGAGCCAGGCGGCGAATTGCTGCTGATGGCCGATGGAGAAACCGCAGCCGTCGGTGACCTCCTGCGTCGGCTTGTACATCATGTTGGAGGTGATACCCCAGTAGAGCGATACCAGCACGGCGGTGCAGATAATCGTGGTCCACATGGGGTAGCCGAAGATATAGAGAGACACCGCAATCAGCCCGGCCTGCTGGAACATAATGTGGCCAGTCAGCATGATGGTGCGGATGCCGGTAATGCGGCGCAGCAGAACGTAAATGATGTTCAACGCCAGCGCGAGCAGTACCGCGTACCCCACCCAACTGTAGGCATCTCCCATGCGGTCAATGGTGGCCATCATCGACGCGTAGGTGTCAGAGATGGCGCCGTTGATGCCATACACCTCCGACATCTTCGCAACCACAGGCTTAAACGTGCTGGTCAGAATGCCTGAACCCGCCTGCAACAGCATGAAACCGATGATGGTTTTGATTGTGCCTTTGATGATGACGCTGACGCTTTTGCGCAGAAGGATGTAGCCCAGGCACGTCACGATACCCAGCAAAAGCGGGGCGTTAGTCATTACCTGATTAAAAAAAACGGTAAAGACGTTGTAGAGGATCTCCATAACTCTCTCCAGAAATGAGAACACGAGGGGGTAATCCCTGTTCGGTTGGTGCCATCACTCTATTAATCACAAATAATCACCACAAGATTGCATTTGATTATTTGTGACGTATCACGCAAATTATTTCCATGGTGTTAGTAATGATTTTCACTATCGATTCCCACGCATAAATTATTTCTTATAATTCATACAATTAATCATTGATAGCGGATATTCTAACAACGTAGAAATAGATTATCTGTGACATGGCGAAGATAAATTTCCTCAATTTACTCGTTGCAAACCGATTCAAAGAGTGCCAGCATTAATCACAACAAATCACCAAATGATTACTTTTGATTAAACCAGGAGTCAAAACGATGAGTAAAGTGAACACCATCACCCGTGAATCATGGATTCTGAGCACCTTCCCGGAATGGGGCAGCTGGCTGAATGAAGAGATTGAGCAGGAACAGGTTGCTCCTGGTACGTTTGCAATGTGGTGGCTGGGTTGCACCGGCATCTGGCTGAAATCCGAGGGTGGCGCCAATATTTGCGTTGATTTCTGGTGCGGTACCGGCAAACAGAGCCACGGCAATCCGCTGATGAAAAAAGGTCATCAGATGCAGCGCATGGCAGGTGTCGAAAAATTGCAGCCGAACCTGCGCACCACGCCGTTTGTTCTTGATCCTTTTGCCATTCGCCAGATCGACGCCGTCCTTTCCACCCACGATCATAACGATCACATCGATGTAAACGTGGCGGCAGCGGTGATGCAAAACTGCGCGGACGACGTGCCGTTTATCGGACCGCAGACCTGCGTGGATCTCTGGATTGGCTGGGGCGTGCCGAAAGAGCGCTGCATCGTCATGAAGCCAGGCGACGTGGTGAAAATTAAAGACATTGAAATCCATGCGCTGGACGCCTTTGACCGCACCGCGCTGATCACCCTGCCTGCTGACCAGAAAGCCGCAGGCGTCCTGCCAGACGGCATGGATGAGCGAGCAGTGAACTATCTGTTTAAAACCCCTGGCGGTTCCCTGTACCACAGCGGTGATTCTCACTACTCCAACTACTATGCGAAGCATGGTAACGAGCATCAGATTGACGTGGCGCTGGGCTCCTACGGCGAGAACCCACGCGGCATTACCGACAAAATGACCAGCGCCGATATGCTGCGCATGGCGGAAGCACTGAACACCAAAGTAGTGATTCCTTTCCACCACGATATCTGGTCAAACTTCCAGGCCGATCCGCAGGAAATCCGCGTACTGTGGGAGATGAAAAAAGACCGTCTGAAGTATGGCTTCAAGCCATTTATCTGGCAGGTAGGCGGCAAGTTCACCTGGCCGCTGGACAAAGACAATCTTGAGTATCACTACCCACGCGGTTTCGATGATTGCTTCACCATTGAGCCAGACCTGCCGTTCAAGTCATTCCTCTGATTGTGAACCCCCATCGCCAGACCTTGCGTCTGGCGATTTCATATTTATTTTAGTAATTTCACGCTATTTCAAATATCATCTTTTCAAATCAATTCTTATCGGAATAGCTCATGACGGAAGCGCAACGGCATCAAATATTACTGGAACTCCTGGCGCAAACAGGGTTTATCACCGTCGAGAAAGTGATCGAACGTTTAGGGATTTCACCCGCGACGGCACGACGCGATATCAACAAGCTGGATGAGAGCGGTAAGCTGAAAAAAGTCCGTAACGGCGCGGAAGCCATCAGCCAGCAGCGCCCCCGCTGGACGCCGATGAACATCCATCAGGCGCAAAACCACGATGAAAAAGTGCGCATTGCCAGAGCCGCATCACAGCTGGTCAACCCGGGTGAGAGCGTGGTGATCAACTGCGGCTCCACGGCATTTCTGCTGGGCCGCGAGATGTGCGGTAAACCGGTGCAAATCATCACCAACTATCTGCCGCTGGCTAACTATCTTATCGATCAGGAACATGAAAGCGTGGTGATCATGGGCGGCCAGTATAATAAGAGCCAATCCATTACCCTCAGTCCCCAGGATAGCGAAAACAGCCTCTATGCCGGGCACTGGATGTTTACCAGCGGCAAAGGCCTGACCGCGGACGGGCTCTACAAAACCGACATGTTAACCGCGATGGCAGAGCAAAATATGCTTAACGTCGTGGGCAAGCTCGTCGTACTGGTCGACAGCAGCAAAGTCGGCGAGCGAGCTGGCATGTTGTTCAGCCGCGCCGAACAGATTGACATGGTGATCACCGGCAAACATGCCAATCCAGAGATCCTCCAGAAGCTGGAAGATCAGGGCGTCAAAATTCTGCGCGTTTAAAGATGCTGGCGGAAAAAGTCCACCGTCGCGTCCAGTGCCGCTGGCGTGATACGGTGGCGAACCCCCGCTTCCCACAGACAGGTCAGGTTGCCGTCCAGCCCTTCGCGCTGTAGTGCCTGCTGGAGACGGAAGGTTTCGCCAGGGGGCACCACATCATCCGCGTCACCATGCCACAACAGCAACGGGCGATCGGCCAGACGCGGTAACGCCCGGGTCACTTCCCATTCGGCCAGCAACGCATCAATCTCCGTCGCGTCTTGCGGTGGAAACAGCGTTTTTGACAATGACGTAAAATAGCCCGAGCCCATCAGGCACGCCACGGAGGTCACCTCAGGGTGACGAGCCATGATCCCGAGCGCCGTCATTCCCCCCATCGATGCGCCGGCCACCGACAGCCGTTGATCCGCCACCAGCCCCGCCTGGTAAAGCGCATCGCGCAGCCCGGCAAATTCGCTCAGGCTACCGTGCAAAATCTGCCAGAACTGCCCCAGTCGCACCTGTTCATCACCGGTAAAACGTGCACCGTGATCGGGCGCATCCGGCATCACTACCCGAAAACCGGCCTGCGCCAGCGCCACCGCAAAGTAGCTGTACACCAGCTTCGATGAAGTAAAGCCATGATAAAAAACCACAACAGGCAGCGGGTGTGCACTTTTTCCCGCAGGGATAGCGTGTAATATTTCATGATTGCCGAGGCGGCGAGTTTCAATTTCAATCATTGTCGACCCTGTGCTGATGAATGATTCATAATGTTGAGAACTGGATTACGCTTTCACGATATTTTCATTCGAAATATACGTACCAGATAACACTTCGGGAACATTCCCCCAAAACTAAATTCGCAGACAACTACACTATGGCTATCAGGAAACGAGATATGGTTATGCGCAGGTTTGCTACTTTATTGTTGCTGGTTCTGCTCAGTGGCTGTAGTGCACTACAGGGGACACCGCAACCCGCTCCCCCGGTCGCCGACCATCCGCAGGAGATTCGTCGTAATCAGACGGAAGGATTACAACGAATGGGTACCGTCTCCGCGCTGGTTCGCGGATCCCCGGATGACGCAGAGGAGTCAATAAAGGCGCAAGCTGCCGCCGCCAAAGCAGATTATTACGTCATCATTATGATCGATGAAACCATCATTACGGGACAGTGGTATTCACAGGCTATATTGTACCGTAAATAACGATCTTCATTTGAACGACATTTACACTGCTTTGCGTCCATAGACATTTTCCTGTCCACAATAAACTCCATGCCCGCGACAATGGAAGTGAGTTTATTTGCGAAGGAGTGCCCGGCGGATACCGGAGAAATGTGAAATGGAGCTGACAATGAAACGAACTCTTGCTTTGACCTCTCTGTTGCTCTCAGTAGGCCTTGTGAGCACGACTGCACAGTCAGCAGAATTCGCCAGTGCTGATTGCGTCACTGGCCTTAATGAAATTGGCCAGATCTCCGTCAATAACATTTCGGGGAGCCCGCAAGATGTTGAACGTGTCGTGGCACTAAAAGCCGATGAACAGGGCGCTTCCTGGTATCGAATTATTCAGATGCAGGAAGATAACCGCAGCGATCATTGGCGCGTACAGGCTATTCTCTACGTCTAATCACCTCCGATAAAAGCCACTTATTTTTAGTGGCTTTTCGTTTTTGCAAATTTTTTATCTTCTTTCAACCCCATTAAAAACAATTTGATAACATTTTGTTACATTATTTAAGTAAATGTTAGCTCTGTCCTGCCGTTGAAAAGCCATACCTTTTCAATAATGAGCAATTTATGATCACTTTTTTTCGCCGTGCGGGTCTGGGCGCAAAGCTATCGCTTCTTACCGGCGTGAGTGTCGCCACGCTGTTTCTGCTTTTCACTTTTCTGCTCAGCCATAAAGCCAGCCAGCAGCTTGAAGCCCTTGCGGTAGAAGACCTGCATAACCAGTCCACCGGTATGGTTGATATGGTACAGATGTTTAACACCAGTCTGAGCGAAGAGGTCGAGAGCTATACCCGGCTGTTCACCACCTTTTTACCGCAACCTTTGAGCGTCGACAGCAATCAACTCCAGACCATTAACGGGCTTAGCGTTCCCCTTCTGAAAGGGGGTGAAACAGGCCTGCATGAAAACAATGCACTTTCTGACGACTTCCTGACGCGTACAGGGGCAATCTCGACCCTGTTTGTGCGCAGCGGTAATGACTTTGTCCGTGTCGCCACCTCCCTGCGCAAAGAGAACGGCGATCGGGCAATGGGTACCGTTCTGGACACTGCCAGCCCGGCCTATGCGGCCGTCACTAAAGGCGAGGTCTATCGCGGTCTGGCGTTGCTGTTCGGTAAGCGCTATATCACCCAGTATCAGCCGTTCAAAAACGCAGAAGGCCAGGTCATTGGGATCATTTTTGTTGGTGTGGATATCACCCACTCCTGGAACGTGATGCGCGAAAAAATCCTCAATCGTCGTTTAGGTGACAGCGGACACTTCTTCGTGCTGGATCGCAGTAACGGTAAAACGCGCGGACAGTTCCTGTTCCACTCGAACCGGGAAGGCCAGCTTCCTGAGTGGGATAGCGCCACCCAGCAGCAGTTGCTGAGCAATACCCCGGGCACGCTGGAACGCACAAGTGAGGGTGGTCGCATACTGAAAATGGCCTACACGCCGCTGCCGGGCTGGAACTGGACCATCGTGGGGGAAGTGGATAAATCGGTCCTGCTCTCAAGCGTCACCACGATGCGGGATCGCTTCCTGCTGGCAGGCGTGGCGCTGTCAGTCCTGTTTGCCGCGCTGTTTGTCATCATCATTCGTCGCATGCTGACGCGCCCGCTGCGTAACGTCATTCACCTTGCCCGACAATATGCGGCAGGCGATCTGCGTGCCAGCCTGTCCGTTACCCGCCAGGATGAGGTTGGCCAGCTTATCGACGCCATCAACGGGATCGGCGGCGGTCTGCAAAAGATTGTCCTGCAGGTACGCGAGGCCGCAGGCGAGATCCATCTGGGCACTAACGCCCTGGCCTCTGATACCGGTGAGATCTCAGAGCAGATCAACAAACAGGCCAGTAGCGTTGAAGAGACCTCCGCGAGTATGGAACAACTCGCCGCAACCGTGCAGCAAAACGCGGCCAATATGGAACAGACGCAGCAGCTGGTGGGGGAAACCTCACGCGCGGTGCATCAGGGGGGCGAGACGGTGACGCACGCGGTCTCCACCATGGACGATATTCGCGACGCCTCAAAGCGCATCGAGGACATCACGCGTGTGATTGAGTCGATTGCTTTCCAGACTAACATTCTGGCGCTTAATGCAGCGGTTGAAGCAGCACGTGCCGGCGAACACGGAAAAGGGTTTGCTGTGGTCGCGCAGGAAGTGCGCGCCCTGGCGGCACGCAGCGCTAATGCGGTGAAAGAGATTGAGCAGCTGATTGGCGACACGCTGAACGAGGTGAGTGAAGGCCATGCGCTCTCAGAGCAGACGCGTCTGGCGATGGATGCCATCATCGCGCACATCGATAACATCAACCAACTGGTGACCGAGATTAACCATGCATCCCGCGAACAGTCGGCGGGGATCCGTCAGGTGAATCTGGCCATGACCCATATTGGTGAAGCCTCCCACATCAACGCCGATCGCGTCTCGCGCAGCGAGCAAACCGCACAATCACTGCGCGAGAAAGGGTCGCACCTCACTCAACTGGTGAGCCTGTTCCAGCTTAAAAACTAGCCTACCCTGCCCGTGGCGCGCAGCAGAAGATCGCTTTGAACCTGCTCTGTCATCAGCGTGCCGCCACGGGTATCCAGCATCATGCGGCACCACGCCTGCGCGACGGGCGGAGAGGCGTGCCGCAGCATCTGGCTTCCGGCGCCCAGCAGGAATAGCTGATGCGCAATCTCCCGCCCCTGCGCCTCCTGCGGTTTACGCAGTTTTTGCTGCAGCTGCCGCCAGCTACGATCGAAGTGTCTGTCCTGACCTTTCACCTGCGCAAAATCCTCTGCCAGCAGATCGAACATACCCGGCTGCTTCGCCAGAACGCGCAGAACATCCAGACACATGATGTTCCCTGAGCCTTCCCAGATGCTGTTCACCGGCATCTCGCGATACAGGCGGGGGAGTTCACTCTCCTCACAGTACCCGATGCCGCCCAACACCTCCATCGCCTCTGCCACGAACGGGATACCCGCTTTGCAGACGCTGAATTTCGCGGCTGGCGTGAAAAGCCGCGCCCAGGCCGCCTCCTGCGGATCGGCGCGTTTATCCCACGCCCGGGCAAGACGAAACAGCAGCGCCGTTTGCCCCTCCAGCACCAGCGCCATGCGGCTCAGGACGTCGCGCATCAGTGGCTGATCGATGAGGTTTTTCCCGAACGTCTGCCGCTGATGGGCGTGGTACAGCGCCACGGATAATGCCCGACGCATCAACCCATGGCTGCCCAGAGCGCAGTCAAAACGCGTTAACCCGCCCATGCGAAGGATCTGTCGTACCCCTTCCCCCTCTTCCCCTAACAGCCAGCCGGACGCATCCAGAAACTCCGCTTCACTGCTGGCGTTAGAGCGGTTGCCGAGCTTGTCTTTCAGCCGCTCCAGGCGCACGGCGTTGCGCTGCCCGTCAGGCAAAAAGCGAGGAACAAAAAAGCAGGACAACCCGCCTTTCGCCTGCGCCAGCACCAGATGCGCATCGCTTTGTGGCACAGAGAAAAACCACTTATGACCCACCAGCCGGTAGCTGCCGTCGCTGCACTTTTCTGCTTTGGTAGTGTTGCTGAGCACGTCCGAGCCGCCCTGTTTTTCCGTCATCCCCATGCCGATCAGCAGGCCGCGCTTTTGGGCTCCAGGGGCAAGGTGAGGATCATAACGATCGCTCAGTAGCGGCGTGAGCCAGTTCTGGAAAGGTTCAGGGAGCGCCTGTTGCAGCAGCGGCGTGGCGGCAAACGTCATGGTCACGGGGCACAGCGTTCCGGCCTCAACCTGAGCATGCAACACGAAGCGCGCGGCGCGAGCGACAAAGGAGCCTTTACGCGCCTCCTCTTCCCACGCCAGGTTATGCACCCGGTTAGCGCACAGCCCCTGCATCAGAAGATGCCAGGCGGGGTGAAAACGGACATCATCCAGCCGCTCACCGGTGGGGTCATAGCGAAGTAACTCCGGCGGATTGACGTTCGCCAGCCTGCCAAGCTCCAGCGACTCCGCCGTACCTAACTGCTGGCCTATACTGGCCAGCAACTCGCTATCCCACTCCGCGCCTTCGCGGGCCACCGCGTCACGCAGGGCACAATCAGAGAGAAAAAGGTTGCTGTTCGAAAGCGGTGCGGGTTGGTTAAAAACGGTATGTGTTTGCCAGTGCATGCTGTCTCCCTCCTTCAGTGGCAATGAAGATAAGTATGGACAGACCCTGTGCACGCTGCATGGGAGTAAGGTCACACGGTAGCGATCCCGCTGATATCATTCGTGAAATAGCTCACAGAACATAAGAATAAACTATTTCATCACTTCACTTTTATTGAATAATTTATTCTTACCCCTTTCAGTGAGGAAAGTTATGCAACCGAATGCGCATAAGCGTGCGTTAATTGCAGGCTCCATTGGTAATTTCATCGAGTGGTATGAGTTTGCGGTCTACGGCTTTCTGGCCACCGTGATTGCGAAAAACTTCTTCCAGCTTGAAGGCGAGTCGGGGCTGACCAGCCTGATCCTCACCTACGCCTCGTTTGCCATCGCTTTCTTTTTCCGCCCACTGGGGGCGGTGGTGTTTGGCCGCATCGGTGACCGTATTGGCCGCAAACCGACGCTGATTATTGTGCTGGTGCTGATGACGCTCGCCACCGCCGCCATCGGTGTTGTGCCAGTCTATGCCAGCATCGGTATCGCTGCGCCGCTGATCGTTACGTTGCTGCGCATCCTGCAGGGATTGTTCGCGGGGGGTGAGTACGGTGGTGCGGTTTCCTTGATGACGGAATTTGCACCACGCGGTAAACGTGGTCTGTATGGCGCATGGCAATCGTTCACGGTGGCGCTGGGGCTATTAGCGGGCGCGGGTATTGTCGCCTTGCTTTCTGCCTTACTGACACCGGAAGCCCTGCATGACTGGGGCTGGCGTATCCCATTTTTCCTGGCCCTGCCTATGGGGGTGGTGGCGCTCTGGTTGCGGGTGAGTATGGAAGAGACGCCGAGCTTCGTGCAGCAGCAGGAAAAACCGCTGATCGCGCAGGCCAGTACCGTCGCCACAATTAAAGCGATCGTGATGGGAATTGGCCGGGTGATGGTCTGGTCGGCGGCGGGATATACCTATCTGGTGATTATGCCGACCTATCTGCAATCGGCACTGCACACCGGATTTAACCAGGCACTGTTGATAGCCGTGATTTCGAATGTCGGCTTTGCGCTCACCATTATTCCGTCGGGGATCCTGAGCGACAGGATTGGCCGCCGCACGGTGATGATTATCGCCACCGCGTTACTGCTGATCCTCGCCCTGCCGCTGCTGAAAATTCTGCAGGCGGAGTCCAGTACCCTCGCGGTAAAAGCGATCGTGGTATTGATAGCTGGCGGTCTGGTGGGCATGCTGGCAGGTCCAGGGCCGGCAATGCTCTCAGAGATGTTCCCGACGCGTGTGCGCTATACCGGGCTTGGTCTGGCGTATTCCTTGTCGAATGCCATTTTCTCGGGGTGTGCGGGGCTTATTATTACCGGGTTGATTAAGGAGACGGGAAACCTCGACATTCCGGCATATTACGTCATGGCGACGGCGGTGGTGAGTATTGTGGCGCTGATGACGCTCAGGAAGGATGACCATTTGCGGACGTTAGAGGAGTAAGGTTGTCACCGTCTGGTGCCCTCACCCACCGGGAGAGAGATAAAACACAAAAGGCCGTCCACAGGACGGCCTTGCTGTTTATTCGCCGCGCTGACGTACCGCTTCAAACAGGCAAATACCCGTTGCAACAGAAACGTTCAGGGACGACACGCTGCCCGCCATCGGGATGCTTATCAGCTCGTCGCAGTGCTCACGCGTCAGGCGACGCATGCCTTCACCTTCCGCACCCATCACCAGCGCCAGACGGCCGGTCATTTTGCTCTGATACAGAGTATGATCCGCTTCACCGGCGGTACCGACGATCCAGATATTCTCTTCCTGCAGCATACGCATGGTGCGCGCCAGGTTGGTGACGCGGATCAGCGGAACGTTTTCTGCTGCACCGCAGGCCACTTTCTTCGCCGTTGCGTTCAGTTGTGCAGAACGATCTTTCGGTACGATCACCGCGTGCACGCCCGCCGCATCGGCGCTGCGCAGGCACGCGCCGAGGTTGTGCGGATCGGTCACGCCATCAAGGATCAGGAAGAACGGGTTATCCAGTGCAGCGATCAAATCCGGCAGATCGTTTTCCTGATACTGACGGCCTGGCTTCACGCGGGCAATAATCCCCTGGTGAACCGCGCCTTCACTTTTCTCATCCAGGAACTGACGGTTGGCCAGCTGGATCACCACGCCCTGCGCTTCCAGTGCGTGGATCAGCGGCATCAGACGTTTGTCTTCACGCCCTTTCAGAATGAACACTTCCTGAAAACGCTCCGGTGCGCGCTCCAGCAGGGCCTGCACCGCGTGGATGCCGTAAATCATTTCACTCATTGATGATTCTCATAATAGGTATTTCCCCCTCTCCCCAGTGGGGAGAGGGTCAGGGTGAGGGGAGAATTTACTCCGCCTGCTGTTTCTTCGCTGCGCGCTTCGCTTTGGTCGCAGCAGCAATTTTCTGTGTTTTCGCGGACGGCTTTTTCGCCTTGCGAGCCTCTTTCTTCGCCGCTTTTGGCTTCTGCTTTTTCTCACCGCGGAAGGCGCTGTCTGGCTCGAAGTTCACTTTCTTACCCGCCTGACGACGTTTGCCGCTCGCGTTGCCGTTACCGCCTTTTTTCGCCTTCTCACGCGCGGTTTTACCTACGTTGCGCGGCGCGCGCTCGCTGGAGATCAGACTGAAGTCAATCTTACGCTCGTCCATGTTGACGGCTTCGACTTTGACTTCCACCCGGTCGCCAAGGCGATAGGTCTGTCCACCCGACTCACCAATCAGGCGCTGTCCAACCTGGTCGAAACGATAATAGTCGTTATCGAGGCTGGAGACATGCACCAGACCGTCGATAAACAGCTCGTCAAGGCGAACAAAGAAACCAAACCCGGTCACGCTGGCGATAACACCTTTGAAAATGTTACCGACCTGATCCAGCATAAAGTCGCATTTCAGCCAGTCAGAGACTTCGCGCGTCGCTTCATCGGCACGGCGTTCGGTCATGGAACAGTGCTGGCCAAGCTGCAGCATCTCTTCCATTGAATAGTGGTACCCGCCGGTTTCAGTCGTGTTCCCTTTATGGCCCTGCTCCTGCGCCAGCAGATACTTGATCGCACGGTGCAAAGACAGGTCCGGATAACGGCGGATCGGCGACGTAAAGTGCGCGTAAGACTGCAGCGCCAGACCGAAGTGACCCCGGTTTTCCGGGTCGTAAATCGCCTGTTTCATGGAGCGCAGCAGCATGGTCTGCAGCATTTCTGCATCCGGACGATCGCCAATGGATTCCAGCAGCTCGGCATAATCGCGCGGCTCTGGCTTGTTACCGCCAGGCAGCTCCAGACCGAGTTCAGCCAGTACGGAGCGGAACGCGGTAATGGCTTCCGTCGACGGTTTATCGTGGATACGGAACAGCGCCGGCTCTTTAGCTTTCTCGACAAAACGGGCCGCCGAGATGTTCGCCAGGATCATACACTCTTCGATCAGCTTATGCGCATCGTTACGCTGGGTCTGTTCAATACGCTCAATGCGGCGTTCAGCGTTGAAAATGAACTTCGCCTCTTCGCTCTCAAACGAGATCCCACCGCGCTCTTCACGCGCCTGATCCAGCGTTTTGTAGAGGTTATGCAACTCTTCGATGTGCTTCACCAGCGGCGCATACTGTTCACGCAGGTCCTGATCGCCCTGCAGCATATGCCAGACCTTGGTATAGGTCAGACGCGCATGGGAGCTCATTACCGCTTCGTAGAATTTATAACCGGTTAAGCGACCTTTACTGGAGATGGTCATCTCGCAAACCATACACAGGCGATCAACCTGCGGGTTCAGGGAACAGAGGCCGTTGGAGAGCACTTCCGGCAGCATCGGTACCACCTGAGACGGGAAGTAAACCGACGTACCACGGCTGCGCGCTTCGTTATCGAGCGGCGTGTGGGGACGAACGTAATAGCTCACGTCGGCGATAGCAACCCACAGACGCCAGCCGCCACCGCGTTTTTTCTCGCAGTATACGGCGTCATCAAAGTCGCGGGCATCTTCTCCATCAATGGTGACCAGCGGCAAACTGCGGAGATCCACGCGTCCCGCTTTGGACTCTTCCGGAACCTCTTCCTTCAGACCCACAATCTGCTCTTCAACCGCTTTTGGCCAGATGTAGGGGATCTCATGTGTACGCAGGGCCATATCAACAGCCATGCCGGTACCCATGTTATCGCCCAGCACTTCGACGATTTTACCTACCGCTTTGGTGCGACGCGTTGGACGTTGGGTAAGCTCCACTACTACCACAAAGCCCATGCGCGCGCCCATCACCTCTTCAGGCGGGATCAGGATATCGAAGCTCAGACGGCTGTCATCCGGTACCACAAAGCCTACACCGGCATCGGTAAAGTAGCGGCCAACGATCTGGCTGGTTTTTGGCACCAGCACGCGAACCACGCGTGCTTCGCGACGGCCTTTACGATCGGCACCCAGCGGCTGCGCCAGGATCTGGTCGCCGTGAATACACATTTTCATCTGTTCGGATGAGAGGTAGAGGTCGTCTTTGCGGCCCTCTACGCGCAAAAAACCGTAACCGTCGCGGTGACCAATGACGGTCCCTTTCAACAGGTCGAGGCGTTCTGGCAGCGCATAGCACTGGCGACGGGTAAAGACCAGTTGCCCGTCGCGCTCCATGGCGCGCAGGCGGCGGCGAAGGGCTTCAGTTTGCTCTTCACCTTCAATGTTTAATTCAACAGCAAGTTCTTCACGATTGGCGGGTTTTTCGCGTTTTGTTAAGTGTTCAATGATGAACTCGCGGCTGGGGATAGGATTCGCGTATTTTTCAGCTTCGCGTTCCTGGAAAGGATCATGTGACATATCGGTTCCTCCGTTGTCAGCTCCGGTGGAAATTTTCTTCATTCCACCAGCAATAATTTATAAAGCGGTTGATTCTCTTCAACCAAATCGGCCAGCGTGTAGTTATCCAGTTCCTTAAGAAAACTTTGCACGGCCAGAGAAAGCGCCTGTTTCAGGCGACAAGCGGGTGTAATGTGGCAGAACTCACTGCTGCAGTTCACCAGAGACAAAGGCTCCAGTTCACGCACCACATCCCCAATACGAATACTTTGCGCCGGTTTACCGAGACGGATCCCACCATTTTTCCCGCGGACGGCAGCAACGTATCCGGCACGACTAAGTTGATTGATTATTTTGACCATATGATTACGGGACACGCCGTAGACCTCTGTCACTTCAGAGATACTGGTCATTTTCCCATCGGGTAACGACGCCATGTAGATTAGCGCGCGTAAGCCGTAATCGGTGAAACTTGTTAACTGCACATCAACCTCAGGAAAAAAGGGAAAACGCGGTAAAACCGCAGAGATATTCATTAATGATGATAAACCAGCCAGATAGTTAGGGGCTAATTTATTTGACAGACGGGGCGAAAAAGCGGATATCCAGGAGCGGTCGCCGGATGGCGCTACGCTTATCCGGCCTACGGGTTTCCCCGCAGGCCAGCAGTCACGAAGATTATGCGTCGAACGGGTCGCGCAGGATCATCGTTTCAGTACGATCCGGGCCGGTAGAGATAATGTCGATCGGCACTTCGGTCAGTTCTTCAATGCGCTTGATGTAATCCAGCGCTGCCTGTGGCAGGCCGCTACGCTCTTTCACACCGAAAGTGGTCTCAGACCAGCCTGGCATGGTTTCGTAGATTGGCTCGATACCTTCCCAGTCGTCAGCAGCCAGCGGAGTGGTGGTCACTTCACGGCCATCTGGCATGCGGTAGCCGACGCAGATTTTCACCTCTTTCAGCCCGTCCAGGACGTCCAGTTTGGTCAGGCAGAAGCCAGACAGGGAGTTGATCTGCACTGCACGACGCACAGCCACTGCATCCAGCCAGCCGGTACGACGACGACGACCGGTGGTCGCGCCAAACTCGTTACCCTGCTTGCACAGGAACTCGCCGGTTTCATCAAACAGTTCGGTCGGGAATGGACCCGCACCCACGCGAGTGGAGTACGCTTTGATGATGCCCAGAACGTAATCCACATAACGTGGACCCAGGCCAGAGCCGGTCGCCACGCCACCTGCGGTGGTGTTAGAGGAGGTTACGTACGGATAGGTACCGTGGTCGATATCCAGCAGCGTACCCTGCGCACCTTCGAACATGACGAAATCGCCACGCTTGCGCGCCTGGTCCAGCAGATCGGACACATCAACTACCATGCCGGTCAGAATGTCTGCAATCGCCATGACATCATCCAGCACTTTCTGGTAGTCAACAGCGTCTGCTTTGTAGAAGTTCACCAACTGGAAGTTGTGATATTCCATCACTTCTTTCAGTTTTTCAGCGAAGGTGGCTTTATCGAACAGGTCGCCCACGCGCAGACCGCGACGAGCCACTTTGTCTTCATAAGCCGGGCCGATACCACGACCGGTGGTGCCGATCGCTTTCGCGCCACGCGCTTTTTCACGCGCAACGTCCAGCGCCACGTGATAATCAAGGATCAGCGGGCAGGCTTCGGAGAGCAGCAGACGCTCGCGAACCGGGATACCACGGTCTTCCAGACCTTTCATCTCTTTCATCAGCGCAGCCGGAGACAGCACTACGCCGTTACCGATGATGCTGGTGACGTTTTCGCGGAGAATGCCTGATGGAATAAGATGGAGGACGGTTTTTTCACCGTTGATTACGAGAGTATGGCCTGCGTTGTGACCGCCCTGGT