ac23b2beea95c281450dcbbaa40b2a03c2f8d141
angie
  Wed Nov 25 12:09:48 2020 -0800
Add 'view subtree in Nextstrain' button to each subtree section in results (user request).

diff --git src/hg/hgPhyloPlace/phyloPlace.c src/hg/hgPhyloPlace/phyloPlace.c
index 01ebcb2..c73fbec 100644
--- src/hg/hgPhyloPlace/phyloPlace.c
+++ src/hg/hgPhyloPlace/phyloPlace.c
@@ -850,53 +850,58 @@
 {
 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);
 }
 
-static void makeButtonRow(struct subtreeInfo *subtreeInfoList, struct tempName *jsonTns[],
-                          boolean isFasta)
-/* Russ's suggestion: row of buttons at the top to view results in GB, Nextstrain, Nextclade. */
-{
-puts("<p>");
-cgiMakeButton("submit", "view in Genome Browser");
-if (nextstrainHost())
+static void makeNextstrainButton(char *idBase, int ix, struct tempName *jsonTns[])
+/* Make a button to view results in Nextstrain.  idBase is a short string and
+ * ix is 0-based subtree number. */
 {
-    struct subtreeInfo *ti;
-    int ix;
-    for (ix = 0, ti = subtreeInfoList;  ti != NULL;  ti = ti->next, ix++)
-        {
-        printf("&nbsp;");
 char buttonId[256];
-        safef(buttonId, sizeof buttonId, "viewNextstrain%d", ix+1);
+safef(buttonId, sizeof buttonId, "%s%d", idBase, ix+1);
 char buttonLabel[256];
 safef(buttonLabel, sizeof buttonLabel, "view subtree %d in Nextstrain", ix+1);
 char *nextstrainUrl = nextstrainUrlFromTn(jsonTns[ix]);
 struct dyString *js = dyStringCreate("window.open('%s');", nextstrainUrl);
 cgiMakeOnClickButton(buttonId, js->string, buttonLabel);
 dyStringFree(&js);
 freeMem(nextstrainUrl);
 }
+
+static void makeButtonRow(struct tempName *jsonTns[], int subtreeCount, boolean isFasta)
+/* Russ's suggestion: row of buttons at the top to view results in GB, Nextstrain, Nextclade. */
+{
+puts("<p>");
+cgiMakeButton("submit", "view in Genome Browser");
+if (nextstrainHost())
+    {
+    int ix;
+    for (ix = 0;  ix < subtreeCount;  ix++)
+        {
+        printf("&nbsp;");
+        makeNextstrainButton("viewNextstrainTopRow", ix, jsonTns);
+        }
     }
 if (0 && isFasta)
     {
     printf("&nbsp;");
     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("</p>");
 }
 
 #define TOOLTIP(text) " <div class='tooltip'>(?)<span class='tooltiptext'>" text "</span></div>"
 
 static void printSummaryHeader(boolean isFasta)
@@ -1365,42 +1370,44 @@
         // Sort subtrees by number of user samples (largest first).
         slSort(&results->subtreeInfoList, subTreeInfoUserSampleCmp);
         // Make Nextstrain/auspice JSON file for each subtree.
         char *bigGenePredFile = phyloPlaceDbSettingPath(db, "bigGenePredFile");
         char *metadataFile = phyloPlaceDbSettingPath(db, "metadataFile");
         struct tempName *jsonTns[subtreeCount];
         struct subtreeInfo *ti;
         int ix;
         for (ix = 0, ti = results->subtreeInfoList;  ti != NULL;  ti = ti->next, ix++)
             {
             AllocVar(jsonTns[ix]);
             trashDirFile(jsonTns[ix], "ct", "subtreeAuspice", ".json");
             treeToAuspiceJson(ti, db, refGenome, bigGenePredFile, metadataFile, jsonTns[ix]->forCgi);
             }
         puts("<p></p>");
-        makeButtonRow(results->subtreeInfoList, jsonTns, isFasta);
+        makeButtonRow(jsonTns, subtreeCount, isFasta);
         summarizeSequences(seqInfoList, isFasta, results, jsonTns, db, bigTree);
         reportTiming(&startTime, "write summary table (including reading in lineages)");
         for (ix = 0, ti = results->subtreeInfoList;  ti != NULL;  ti = ti->next, ix++)
             {
             int subtreeUserSampleCount = slCount(ti->subtreeUserSampleIds);
             printf("<h3>Subtree %d: ", ix+1);
             if (subtreeUserSampleCount > 1)
                 printf("%d related samples", subtreeUserSampleCount);
             else if (subtreeCount > 1)
                 printf("Unrelated sample");
             printf("</h3>\n");
+            makeNextstrainButton("viewNextstrainSub", ix, jsonTns);
+            puts("<br>");
             // Make a sub-subtree with only user samples for display:
             struct phyloTree *subtree = phyloOpenTree(ti->subtreeTn->forCgi);
             subtree = phyloPruneToIds(subtree, ti->subtreeUserSampleIds);
             describeSamplePlacements(ti->subtreeUserSampleIds, results->samplePlacements, subtree,
                                      bigTree, db);
             }
         reportTiming(&startTime, "describe placements");
 
         // Make custom tracks for uploaded samples and subtree(s).
         struct tempName *ctTn = writeCustomTracks(vcfTn, results, sampleIds, bigTree->tree,
                                                   fontHeight, &startTime);
                                
         // Offer big tree w/new samples for download
         puts("<h3>Downloads</h3>");
         puts("<ul>");