Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 56 additions & 48 deletions src/matUtils/convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ MAT::Tree load_mat_from_json(std::string json_filename) {
return T;
}

json get_json_entry(MAT::Node* n, std::vector<std::unordered_map<std::string,std::unordered_map<std::string,std::string>>>* catmeta, size_t div = 0, bool use_clade_zero = false, bool use_clade_one = false) {
json get_json_entry(MAT::Node* n, std::vector<std::unordered_map<std::string,std::unordered_map<std::string,std::string>>>* catmeta, size_t div = 0, std::vector<bool> use_clade_n = {false}, std::vector<std::map<std::string, std::string>> parent_cav = {} ) {
//each node has 3 constituent attributes
//node_attrs, branch_attrs, and children. If its a leaf,
//it also has a simple name attribute.
Expand All @@ -532,35 +532,36 @@ json get_json_entry(MAT::Node* n, std::vector<std::unordered_map<std::string,std
//note: the below is pretty much sars-cov-2 specific. but so is all json-related things.
//need to declare maps to get nlohmann to interpret these as key pairs.
div += mutids.size();
std::string c1av = "";
std::string c2av = "";
if (n->clade_annotations.size() >= 1) {
c1av = n->clade_annotations[0];
}
if (n->clade_annotations.size() >= 2) {
//json output supports two simultaneous clade annotations
//being nextstrain and pangolin, since this is very specific
//to sars-cov-2 phylogenomics. Additional fields are ignored
//at this point.
c1av = n->clade_annotations[1];
}
std::unordered_map<std::string,std::string> c1a {{"value",c1av}};
std::unordered_map<std::string,std::string> c2a {{"value",c2av}};

int annot_size = n->clade_annotations.size();
std::vector<std::map<std::string, std::string>> cav(annot_size);
for ( int c=0; c < annot_size; c++) {

if (use_clade_n[c]) {

if (n->clade_annotations[c] == ""){
cav[c] = parent_cav[c];
} else {
cav[c] = {{"value",n->clade_annotations[c]}};
}
}
}

std::string country = n->identifier.substr(0, n->identifier.find("/"));
std::string date = n->identifier.substr( n->identifier.find_last_of("|")+1, n->identifier.size() );
std::unordered_map<std::string,std::string> com {{"value",country}};
std::unordered_map<std::string,std::string> dam {{"value",date}};
if ((n->is_leaf()) && (country.length() != n->identifier.size()) && (date.length() != n->identifier.size()) ) {
sj["node_attrs"] = { {"country",com}, {"date",dam},{"div", div}, {"MAT_Clade_0", c1a}, {"MAT_Clade_1", c2a} };
sj["node_attrs"] = { {"country",com}, {"date",dam},{"div", div}};
} else {
sj["node_attrs"]["div"] = div;
if (use_clade_zero) {
sj["node_attrs"]["MAT_Clade_0"] = c1a;
}
if (use_clade_one) {
sj["node_attrs"]["MAT_Clade_1"] = c2a;
}
}

for (int c=0; c < annot_size; c++){
if (use_clade_n[c])
sj["node_attrs"]["MAT_Clade_"+std::to_string(c)] = cav[c];
}

for (const auto& cmet: *catmeta) {
for (const auto& cmi: cmet) {
if (cmi.second.find(n->identifier) != cmi.second.end()) {
Expand All @@ -573,7 +574,7 @@ json get_json_entry(MAT::Node* n, std::vector<std::unordered_map<std::string,std
sj["name"] = n->identifier;
std::vector<json> child_json;
for (auto cn: n->children) {
json cj = get_json_entry(cn, catmeta, div, use_clade_zero, use_clade_one);
json cj = get_json_entry(cn, catmeta, div, use_clade_n, cav );
child_json.push_back(cj);
sj["children"] = child_json;
}
Expand All @@ -585,6 +586,26 @@ void write_json_from_mat(MAT::Tree* T, std::string output_filename, std::vector<
json nj;
std::string desc = "JSON generated by matUtils. If you have metadata you wish to display, you can now drag on a CSV/TSV file and it will be added into this view, [see here](https://docs.nextstrain.org/projects/auspice/en/latest/advanced-functionality/drag-drop-csv-tsv.html) for more info.";
std::unordered_map<std::string,std::string> lm = {{"branch_label", "none"}};
int annot_size = T->root->clade_annotations.size();

// check clade annotations that should be written
std::vector<bool> use_clades(annot_size,{false});

for (auto n: T->depth_first_expansion()) {
int idx = 0;
for (const auto& c: n->clade_annotations) {
++idx;

if (!c.empty()) {
use_clades[idx] = true;
}
}
if (std::all_of(use_clades.begin(), use_clades.end(), [](bool b) { return b;})) {
break;
}
}

// set Nextclade extension configurations
nj = {
{"version","v2"},
{
Expand All @@ -604,6 +625,7 @@ void write_json_from_mat(MAT::Tree* T, std::string output_filename, std::vector<
}
}
};

//add metadata to the header colorings if any exist
if (catmeta->size()>0) {
for (const auto& cmet: *catmeta) {
Expand All @@ -619,33 +641,19 @@ void write_json_from_mat(MAT::Tree* T, std::string output_filename, std::vector<
}
}
}
//check whether each of the mat clade annotation fields are used by any sample.
bool uses_clade_0 = false;
bool uses_clade_1 = false;
for (auto n: T->depth_first_expansion()) {
if (n->clade_annotations.size() >= 1) {
if (n->clade_annotations[0] != "") {
uses_clade_0 = true;
}
if (n->clade_annotations.size() >= 2) {
if (n->clade_annotations[1] != "") {
uses_clade_1 = true;
}
}
}
if ((uses_clade_0) && (uses_clade_1)) {
break;

int idx = 0;
for (const bool& c: use_clades) {
if (c) {
nj["meta"]["extensions"]["nextclade"]["clade_node_attrs"].push_back({{"name","MAT_Clade_" + std::to_string(idx)},{"displayName","MAT_Clade_"+ std::to_string(idx+1)},{"description","MAT_Clade_" + std::to_string(idx+1) + "as inferred or proposed by UShER, matUtils, or Autolin."},{"hideInWeb",false},{"skipAsReference",true}} );

std::unordered_map<std::string,std::string> cmap {{"key","MAT_Clade_" + std::to_string(idx)},{"title","MAT_Clade_" + std::to_string(idx+1)},{"type","categorical"}};
nj["meta"]["colorings"].push_back(cmap);
}
++idx;
}
if (uses_clade_0) {
std::unordered_map<std::string,std::string> c1map {{"key","MAT_Clade_0"},{"title","MAT_Clade_1"},{"type","categorical"}};
nj["meta"]["colorings"].push_back(c1map);
}
if (uses_clade_1) {
std::unordered_map<std::string,std::string> c2map {{"key","MAT_Clade_1"},{"title","MAT_Clade_2"},{"type","categorical"}};
nj["meta"]["colorings"].push_back(c2map);
}
auto treestuff = get_json_entry(T->root, catmeta, 0, uses_clade_0, uses_clade_1);

auto treestuff = get_json_entry(T->root, catmeta, 0, use_clades);
nj["tree"]["children"] = json::array({treestuff});
std::ofstream out(output_filename);
// out << std::setw(4) << nj << std::endl;
Expand Down