17cdc50389b482ee9f3f1ce649ed297201269d53 angie Thu Feb 25 20:41:01 2021 -0800 If usher's output includes clade and lineage assignments, parse them and include them in the summary table. diff --git src/hg/hgPhyloPlace/phyloPlace.c src/hg/hgPhyloPlace/phyloPlace.c index c63468d..7fc3fe5 100644 --- src/hg/hgPhyloPlace/phyloPlace.c +++ src/hg/hgPhyloPlace/phyloPlace.c @@ -1033,30 +1033,53 @@ int *retIx) /* Find the subtree that contains sample name and set *retIx to its index in the list. * If we can't find it, return NULL and set *retIx to -1. */ { struct subtreeInfo *ti; int ix; for (ti = subtreeInfoList, ix = 0; ti != NULL; ti = ti->next, ix++) if (slNameInList(ti->subtreeUserSampleIds, name)) break; if (ti == NULL) ix = -1; *retIx = ix; return ti; } +static void lookForCladesAndLineages(struct seqInfo *seqInfoList, struct hash *samplePlacements, + boolean *retGotClades, boolean *retGotLineages) +/* See if UShER has annotated any clades and/or lineages for seqs. */ +{ +boolean gotClades = FALSE, gotLineages = FALSE; +struct seqInfo *si; +for (si = seqInfoList; si != NULL; si = si->next) + { + struct placementInfo *pi = hashFindVal(samplePlacements, si->seq->name); + if (pi) + { + if (isNotEmpty(pi->nextClade)) + gotClades = TRUE; + if (isNotEmpty(pi->pangoLineage)) + gotLineages = TRUE; + if (gotClades && gotLineages) + break; + } + } +*retGotClades = gotClades; +*retGotLineages = gotLineages; +} + static char *nextstrainHost() /* Return the nextstrain hostname from an hg.conf param, or NULL if missing. */ { return cfgOption("nextstrainHost"); } static char *nextstrainUrlFromTn(struct tempName *jsonTn) /* Return a link to Nextstrain to view an annotated subtree. */ { char *jsonUrlForNextstrain = urlFromTn(jsonTn); char *protocol = strstr(jsonUrlForNextstrain, "://"); if (protocol) jsonUrlForNextstrain = protocol + strlen("://"); struct dyString *dy = dyStringCreate("%s/fetch/%s", nextstrainHost(), jsonUrlForNextstrain); return dyStringCannibalize(&dy); @@ -1107,31 +1130,31 @@ } } if (0 && isFasta) { printf(" "); struct dyString *js = dyStringCreate("window.open('https://master.clades.nextstrain.org/" "?input-fasta=%s');", "needATn"); //#*** TODO: save FASTA to file cgiMakeOnClickButton("viewNextclade", js->string, "view sequences in Nextclade"); } puts("
"); } #define TOOLTIP(text) "%s", replaceChars(si->seq->name, "|", " | ")); if (isFasta) { if (si->nCountStart || si->nCountEnd) { int effectiveLength = si->seq->size - (si->nCountStart + si->nCountEnd); dyStringClear(dy); dyStringPrintf(dy, "%d ", effectiveLength); appendExcludingNs(dy, si); @@ -1477,57 +1510,67 @@ dyStringPrintf(dy, "%c%d%c (%s", snc->refBase, snc->chromStart+1, snc->newBase, reasonList->name); for (reason = reasonList->next; reason != NULL; reason = reason->next) { replaceChar(reason->name, '_', ' '); dyStringPrintf(dy, ", %s", reason->name); } dyStringAppendC(dy, ')'); } printTooltip(dy->string); } printf(""); struct placementInfo *pi = hashFindVal(ur->samplePlacements, si->seq->name); if (pi) { + if (gotClades) + printf(" | %s | ", pi->nextClade ? pi->nextClade : "n/a"); + if (gotLineages) + printf("%s | ", pi->pangoLineage ? pi->pangoLineage : "n/a"); struct slName *neighbor = findNearestNeighbor(bigTree, pi->sampleId, pi->variantPath); char *lineage = neighbor ? lineageForSample(sampleMetadata, neighbor->name) : "?"; printf("%s | %s | ", neighbor ? replaceChars(neighbor->name, "|", " | ") : "?", lineage ? lineage : "?"); int imputedCount = slCount(pi->imputedBases); printf("%d", qcClassForImputedBases(imputedCount), imputedCount); if (imputedCount > 0) { dyStringClear(dy); struct baseVal *bv; for (bv = pi->imputedBases; bv != NULL; bv = bv->next) { dyStringAppendSep(dy, ", "); dyStringPrintf(dy, "%d: %s", bv->chromStart+1, bv->val); } printTooltip(dy->string); } printf(" | %d", qcClassForPlacements(pi->bestNodeCount), pi->bestNodeCount); printf(" | %d", qcClassForPScore(pi->parsimonyScore), pi->parsimonyScore); printf(" | "); } else + { + if (gotClades) + printf("n/a> | "); + if (gotLineages) + printf("n/a> | "); printf("n/a | n/a | n/a | n/a | n/a | "); + } int ix; struct subtreeInfo *ti = subtreeInfoForSample(ur->subtreeInfoList, si->seq->name, &ix); if (ix < 0) //#*** Probably an error. printf("n/a | "); else { printf("%d", ix+1); if (ti && nextstrainHost()) { char *nextstrainUrl = nextstrainUrlFromTn(jsonTns[ix]); printf(" (view in Nextstrain)", nextstrainUrl); } printf(" | "); }
---|