be4311c07e14feb728abc6425ee606ffaa611a58 markd Fri Jan 22 06:46:58 2021 -0800 merge with master diff --git src/hg/hgPhyloPlace/writeCustomTracks.c src/hg/hgPhyloPlace/writeCustomTracks.c index 36399a6..6e98f88 100644 --- src/hg/hgPhyloPlace/writeCustomTracks.c +++ src/hg/hgPhyloPlace/writeCustomTracks.c @@ -249,52 +249,53 @@ static char *trackNameFromSampleIds(struct slName *sampleIds) /* Make a name for our subtree custom track by concatenating sample names. */ { struct dyString *dy = dyStringCreate("subtree_%s", sampleIds->name); struct slName *id; for (id = sampleIds->next; id != NULL; id = id->next) { dyStringPrintf(dy, "_%s", id->name); if (dy->stringSize > 200) break; } return dyStringCannibalize(&dy); } -static void writeSubtreeTrackLine(FILE *ctF, struct subtreeInfo *ti, int fontHeight) +static void writeSubtreeTrackLine(FILE *ctF, struct subtreeInfo *ti, char *source, int fontHeight) /* Write a custom track line to ctF for one subtree. */ { fprintf(ctF, "track name=%s", trackNameFromSampleIds(ti->subtreeUserSampleIds)); // Keep the description from being too long in order to avoid buffer overflow in hgTrackUi int descLen = fprintf(ctF, " description='Uploaded sample%s %s", (slCount(ti->subtreeUserSampleIds) > 1 ? "s" : ""), ti->subtreeUserSampleIds->name); struct slName *id; for (id = ti->subtreeUserSampleIds->next; id != NULL; id = id->next) { if (descLen > 200) { fprintf(ctF, " and %d other samples", slCount(id)); break; } descLen += fprintf(ctF, ", %s", id->name); } -fprintf(ctF, " and nearest neighboring sequences from GISAID' type=vcf visibility=pack " +int height = heightForSampleCount(fontHeight, slCount(ti->subtreeNameList)); +fprintf(ctF, " and nearest neighboring %s sequences' type=vcf visibility=pack " "hapClusterEnabled=on hapClusterHeight=%d hapClusterMethod='treeFile %s' " "highlightIds=%s", - heightForSampleCount(fontHeight, slCount(ti->subtreeNameList)), ti->subtreeTn->forHtml, + source, height, ti->subtreeTn->forHtml, slNameListToString(ti->subtreeUserSampleIds, ',')); if (isNotEmpty(geneTrack)) fprintf(ctF, " hapClusterColorBy=function geneTrack=%s", geneTrack); fputc('\n', ctF); } static void writeVcfHeader(FILE *f, struct slName *sampleNames) /* Write a minimal VCF header with sample names for genotype columns. */ { fprintf(f, "##fileformat=VCFv4.2\n"); fprintf(f, "#CHROM\tPOS\tID\tREF\tALT\tQUAL\tFILTER\tINFO\tFORMAT"); struct slName *s; for (s = sampleNames; s != NULL; s = s->next) fprintf(f, "\t%s", s->name); fputc('\n', f); @@ -513,56 +514,56 @@ char refBases[chromSize]; memset(refBases, 0, sizeof refBases); char *sampleBases[chromSize]; memset(sampleBases, 0, sizeof sampleBases); treeToBaseAlleles(bigTree, refBases, sampleBases, sampleToIx, NULL); vcfToBaseAlleles(userVcf, refBases, sampleBases, sampleToIx); int sampleCount = sampleToIx->elCount; baseAllelesToVcf(refBases, sampleBases, chromSize, sampleCount, f); int i; for (i = 0; i < chromSize; i++) freeMem(sampleBases[i]); } static void addSubtreeCustomTracks(FILE *ctF, char *userVcfFile, struct subtreeInfo *subtreeInfoList, struct hash *samplePlacements, struct phyloTree *bigTree, - int fontHeight, int *pStartTime) + char *source, int fontHeight, int *pStartTime) /* For each subtree trashfile, write VCF+treeFile custom track text to ctF. */ { struct vcfFile *userVcf = parseUserVcf(userVcfFile, pStartTime); if (! userVcf) { warn("Problem parsing VCF file with user variants '%s'; can't make subtree subtracks.", userVcfFile); return; } if (!bigTree) return; struct subtreeInfo *ti; for (ti = subtreeInfoList; ti != NULL; ti = ti->next) { - writeSubtreeTrackLine(ctF, ti, fontHeight); + writeSubtreeTrackLine(ctF, ti, source, fontHeight); writeVcfHeader(ctF, ti->subtreeNameList); writeSubtreeVcf(ctF, ti->subtreeIdToIx, userVcf, bigTree); fputc('\n', ctF); } vcfFileFree(&userVcf); reportTiming(pStartTime, "write subtree custom tracks"); } struct tempName *writeCustomTracks(struct tempName *vcfTn, struct usherResults *ur, struct slName *sampleIds, struct phyloTree *bigTree, - int fontHeight, int *pStartTime) + char *source, int fontHeight, int *pStartTime) /* Write one custom track per subtree, and one custom track with just the user's uploaded samples. */ { struct tempName *ctVcfTn = userVcfWithImputedBases(vcfTn, ur->samplePlacements, sampleIds); struct tempName *ctTn; AllocVar(ctTn); trashDirFile(ctTn, "ct", "ct_pp", ".ct"); FILE *ctF = mustOpen(ctTn->forCgi, "w"); addSubtreeCustomTracks(ctF, ctVcfTn->forCgi, ur->subtreeInfoList, ur->samplePlacements, bigTree, - fontHeight, pStartTime); + source, fontHeight, pStartTime); addSampleOnlyCustomTrack(ctF, ctVcfTn, ur->bigTreePlusTn->forCgi, sampleIds, fontHeight, pStartTime); carefulClose(&ctF); return ctTn; }