f3bb2615e7f7d1df3dc6084ab0c5694679a536e7
angie
  Wed Dec 18 14:36:01 2024 -0800
If unable to connect to what looks like it should be a GenArk hub, don't try to write custom tracks (or else we'll get an error trying to connect to a nonexistent db).

diff --git src/hg/hgPhyloPlace/phyloPlace.c src/hg/hgPhyloPlace/phyloPlace.c
index f87dd7f..8093299 100644
--- src/hg/hgPhyloPlace/phyloPlace.c
+++ src/hg/hgPhyloPlace/phyloPlace.c
@@ -178,32 +178,34 @@
             regexSubstringCopy(db, substrs[3], mid3, sizeof mid3);
             regexSubstringCopy(db, substrs[4], last3, sizeof last3);
             struct dyString *dy = dyStringCreate("https://hgdownload.gi.ucsc.edu/hubs/%s/%s/%s/"
                                                  "%s/%s/hub.txt",
                                                  gcPrefix, first3, mid3, last3, db);
             // Use cart variables to pretend user clicked to connect to this hub.
             cartSetString(cart, hgHubDataText, dy->string);
             cartSetString(cart, hgHubGenome, db);
             struct errCatch *errCatch = errCatchNew();
             char *hubDb = NULL;
             if (errCatchStart(errCatch))
                 {
                 hubDb = hubConnectLoadHubs(cart);
                 }
             errCatchEnd(errCatch);
-            if (hubDb != NULL)
+
             maybeHubDb = hubDb;
+            if (errCatch->gotError)
+                warn("%s", errCatch->message->string);
             }
         }
     }
 return maybeHubDb;
 }
 
 static char *finalDirName(char *path)
 /* Clone & return the final directory name from a path to a file. */
 {
 char dir[PATH_LEN], name[FILENAME_LEN], extension[FILEEXT_LEN];
 splitPath(path, dir, name, extension);
 if (endsWith(dir, "/"))
     dir[strlen(dir)-1] = '\0';
 char *finalDir = strrchr(dir, '/');
 if (finalDir == NULL)
@@ -260,30 +262,32 @@
         {
         // Old-style single-reference directory with config.ra instead of organism.ra; get label
         // from config.ra and add {symbol, label} to list.
         char *db = finalDirName(path->name);
         char *label = phyloPlaceRefSetting(db, db, "name");
         if (isEmpty(label))
             label = hGenome(db);
         char *description = phyloPlaceRefSetting(db, db, "description");
         if (isNotEmpty(description))
             {
             struct dyString *dy = dyStringCreate("%s %s", label, description);
             label = dyStringCannibalize(&dy);
             }
         // If it's a hub, use its full hub_... name:
         char *maybeHubDb = connectIfHub(cart, db);
+        if (maybeHubDb == NULL)
+            maybeHubDb = db;
         slAddHead(&orgList, slPairNew(maybeHubDb, label));
         }
     }
 // Sort by label, putting SARS-CoV-2 first and then others in alphabetical order.
 slSort(&orgList, labelCmp);
 return orgList;
 }
 
 char *getUsherPath(boolean abortIfNotFound)
 /* Return hgPhyloPlaceData/usher-sampled if it exists, else try hgPhyloPlaceData/usher, else NULL.
  * Do not free the returned value. */
 {
 char *usherPath = PHYLOPLACE_DATA_DIR "/usher-sampled";
 if (fileExists(usherPath))
     return usherPath;
@@ -3485,39 +3489,41 @@
         // Add a link for every sample to this subtree, so the single-subtree JSON can
         // link to subtree JSONs
         char *subtreeUrl = nextstrainUrlFromTn(jsonTns[ix]);
         struct slName *sample;
         for (sample = ti->subtreeUserSampleIds;  sample != NULL;  sample = sample->next)
             hashAdd(sampleUrls, sample->name, subtreeUrl);
         }
     struct tempName *singleSubtreeJsonTn;
     AllocVar(singleSubtreeJsonTn);
     trashDirFile(singleSubtreeJsonTn, "hgPhyloPlace", "singleSubtreeAuspice", ".json.gz");
     treeToAuspiceJson(results->singleSubtreeInfo, org, refName, geneInfoList, gSeqWin, sampleMetadata,
                       sampleUrls, results->samplePlacements, singleSubtreeJsonTn->forCgi, source);
     if (subtreePersist)
         saveTrashFile(singleSubtreeJsonTn);
     reportTiming(&startTime, "make Auspice JSON");
+    char *ctDb = db;
     char *dbSetting = phyloPlaceRefSetting(org, refName, "db");
     if (dbSetting)
-        db = connectIfHub(cart, dbSetting);
-    boolean canDoCustomTracks = (!subtreesOnly &&
-                                 (sameString(db, refName) || isNotEmpty(dbSetting)));
+        {
+        ctDb = connectIfHub(cart, dbSetting);
+        }
+    boolean canDoCustomTracks = (!subtreesOnly && ctDb != NULL);
     if (canDoCustomTracks)
         // Form submits subtree custom tracks to hgTracks
         printf("<form action='%s' name='resultsForm_%s' method=%s>\n\n",
-               hgTracksName(), db, cartUsualString(cart, "formMethod", "POST"));
+               hgTracksName(), ctDb, cartUsualString(cart, "formMethod", "POST"));
 
     makeButtonRow(singleSubtreeJsonTn, jsonTns, results->subtreeInfoList, subtreeSize, isFasta,
                   canDoCustomTracks);
     printf("<p>If you have metadata you wish to display, click a 'view subtree in "
            "Nextstrain' button, and then you can drag on a CSV file to "
            "<a href='"NEXTSTRAIN_DRAG_DROP_DOC"' target=_blank>add it to the tree view</a>."
            "</p>\n");
     puts("<p><em>Note: "
          "The Nextstrain subtree views, and Download files below, are temporary files and will "
          "expire within two days.  "
          "Please download the Nextstrain subtree JSON files if you will want to view them "
          "again in the future.  The JSON files can be drag-dropped onto "
          "<a href='https://auspice.us/' target=_blank>https://auspice.us/</a>."
          "</em></p>");
 
@@ -3528,31 +3534,31 @@
     if (subtreesOnly)
         {
         summarizeSubtrees(sampleIds, results, sampleMetadata, jsonTns, refName, subtreeSize);
         reportTiming(&startTime, "describe subtrees");
         }
     else
         {
         findNearestNeighbors(results, sampleMetadata);
         reportTiming(&startTime, "find nearest neighbors");
 
         char *singleSubtreeFile = results->singleSubtreeInfo->subtreeTn->forCgi;
         struct phyloTree *sampleTree = uploadedSamplesTree(singleSubtreeFile, sampleIds);
         if (canDoCustomTracks)
             {
             // Make custom tracks for uploaded samples and subtree(s).
-            ctTn = writeCustomTracks(org, refName, db, vcfTn, results, sampleIds, source,
+            ctTn = writeCustomTracks(org, refName, ctDb, vcfTn, results, sampleIds, source,
                                      tl->fontHeight, sampleTree, &startTime);
             }
 
         // Make a sample summary TSV file and accumulate S gene changes
         struct hash *seqInfoHash = hashFromSeqInfoListAndIds(seqInfoList, sampleIds);
         addSampleMutsFromSeqInfo(results->samplePlacements, seqInfoHash);
         struct hash *spikeChanges = hashNew(0);
         tsvTn = writeTsvSummary(results, sampleTree, sampleIds, seqInfoHash,
                                 geneInfoList, gSeqWin, spikeChanges, &startTime);
         sTsvTn = writeSpikeChangeSummary(spikeChanges, slCount(sampleIds));
         downloadsRow(results->bigTreePlusTn->forHtml, tsvTn->forHtml, sTsvTn->forHtml,
                      zipTn->forHtml);
 
         int seqCount = slCount(seqInfoList);
         if (seqCount <= MAX_SEQ_DETAILS)
@@ -3635,31 +3641,31 @@
             }
         puts(" (JSON file)</a>");
         }
     puts("</ul>");
 
     if (ctTn != NULL)
         {
         // Notify in opposite order of custom track creation.
         puts("<h3>Custom tracks for viewing in the Genome Browser</h3>");
         printf("<p>Added custom track of uploaded samples.</p>\n");
         if (subtreeCount > 0 && subtreeCount <= MAX_SUBTREE_CTS)
             printf("<p>Added %d subtree custom track%s.</p>\n",
                    subtreeCount, (subtreeCount > 1 ? "s" : ""));
         ctFile = urlFromTn(ctTn);
         cartSaveSession(cart);
-        cgiMakeHiddenVar("db", db);
+        cgiMakeHiddenVar("db", ctDb);
         cgiMakeHiddenVar(CT_CUSTOM_TEXT_VAR, ctFile);
         if (tl->leftLabelWidthChars < 0 || tl->leftLabelWidthChars == leftLabelWidthDefaultChars)
             cgiMakeHiddenVar(leftLabelWidthVar, leftLabelWidthForLongNames);
         cgiMakeButton("submit", "view in Genome Browser");
         puts("</form>");
         }
     }
 }
 
 static char *dumpLfToTrashFile(struct lineFile *lf)
 /* Dump the contents of lf to a trash file (for passing to an executable). Return trash file name. */
 {
 struct tempName tmp;
 trashDirFile(&tmp, "ct", "usher_tmp", ".txt");
 FILE *f = mustOpen(tmp.forCgi, "w");