94a2d41644d235ec3702d8189ec52036e739000a
Merge parents f7d5770 b5ba1cd
markd
  Sun Feb 28 14:23:10 2021 -0800
merge master into branch

diff --cc src/hg/hgPcr/hgPcr.c
index f08b185,685d0da..802ce67
--- src/hg/hgPcr/hgPcr.c
+++ src/hg/hgPcr/hgPcr.c
@@@ -508,102 -490,141 +508,145 @@@
  {
  char *cartVar = pcrResultCartVar(db);
  struct tempName bedTn, primerTn;
  char buf[2048];
  trashDirFile(&bedTn, "hgPcr", "hgPcr", ".psl");
  trashDirFile(&primerTn, "hgPcr", "hgPcr", ".txt");
  gfPcrOutputWriteAll(gpoList, "psl", NULL, bedTn.forCgi);
  writePrimers(gpoList, primerTn.forCgi);
  if (isNotEmpty(target))
      safef(buf, sizeof(buf), "%s %s %s", bedTn.forCgi, primerTn.forCgi, target);
  else
      safef(buf, sizeof(buf), "%s %s", bedTn.forCgi, primerTn.forCgi);
  cartSetString(cart, cartVar, buf);
  }
  
+ static void printHelpLinks(struct gfPcrOutput *gpoList) {
+     /* print links to our docs for special chromosome names */
+     // if you modify this, also modify hgBlat.c:showAliPlaces, which implements a similar feature, for hgBlat
+     boolean isAlt = FALSE;
+     boolean isFix = FALSE;
+     boolean isRandom = FALSE;
+     boolean isChrUn = FALSE;
+ 
+     if (gpoList != NULL)
+         {
+         struct gfPcrOutput *gpo;
+         for (gpo = gpoList;  gpo != NULL;  gpo = gpo->next)
+             {
+             char *seq = gpo->seqName;
+             if (endsWith(seq, "_fix"))
+                 isFix = TRUE;
+             else if (endsWith(seq, "_alt"))
+                 isAlt = TRUE;
+             else if (endsWith(seq, "_random"))
+                 isRandom = TRUE;
+             else if (startsWith(seq, "chrUn"))
+                 isChrUn = TRUE;
+             }
+         }
+ 
+     if (isFix || isRandom || isAlt || isChrUn)
+         webNewSection("Notes on the results above");
+ 
+     if (isFix)
+         printf("<A target=_blank HREF=\"../FAQ/FAQdownloads#downloadFix\">What is chrom_fix?</A><BR>");
+     if (isAlt)
+         printf("<A target=_blank HREF=\"../FAQ/FAQdownloads#downloadAlt\">What is chrom_alt?</A><BR>");
+     if (isRandom)
+         printf("<A target=_blank HREF=\"../FAQ/FAQdownloads#download10\">What is chrom_random?</A><BR>");
+     if (isChrUn)
+         printf("<A target=_blank HREF=\"../FAQ/FAQdownloads#download11\">What is a chrUn sequence?</A><BR>");
+ }
  
  void doQuery(struct pcrServer *server, struct gfPcrInput *gpi,
  	     int maxSize, int minPerfect, int minGood)
  /* Send a query to a genomic assembly PCR server and print the results. */
  {
 +struct gfConnection *conn = gfConnect(server->host, server->port,
 +                                      trackHubDatabaseToGenome(server->db), server->genomeDataDir);
  struct gfPcrOutput *gpoList =
 -    gfPcrViaNet(server->host, server->port, server->seqDir, gpi,
 +    gfPcrViaNet(conn, server->seqDir, gpi,
  		maxSize, minPerfect, minGood);
+ 
+ 
  if (gpoList != NULL)
      {
      char urlFormat[2048];
      safef(urlFormat, sizeof(urlFormat), "%s?%s&db=%s&position=%%s:%%d-%%d"
  	  "&hgPcrResult=pack", 
  	  hgTracksName(), cartSidUrlString(cart), server->db);
      printf("<TT><PRE>");
      gfPcrOutputWriteAll(gpoList, "fa", urlFormat, "stdout");
      printf("</PRE></TT>");
+     
+     printHelpLinks(gpoList);
      writePcrResultTrack(gpoList, server->db, NULL);
      }
  else
      {
      printf("No matches to %s %s in %s %s", gpi->fPrimer, gpi->rPrimer, 
  	   server->genome, server->description);
      }
 +gfDisconnect(&conn);
  }
  
  void doTargetQuery(struct targetPcrServer *server, struct gfPcrInput *gpi,
  		   int maxSize, int minPerfect, int minGood)
  /* Send a query to a non-genomic target PCR server and print the results. */
  {
 +struct gfConnection *conn = gfConnect(server->host, server->port, NULL, NULL);
  struct gfPcrOutput *gpoList;
  char seqDir[PATH_LEN];
  splitPath(server->targetDb->seqFile, seqDir, NULL, NULL);
  if (endsWith("/", seqDir))
      seqDir[strlen(seqDir) - 1] = '\0';
 -gpoList = gfPcrViaNet(server->host, server->port, seqDir, gpi,
 -		      maxSize, minPerfect, minGood);
 +gpoList = gfPcrViaNet(conn, seqDir, gpi, maxSize, minPerfect, minGood);
+ 
  if (gpoList != NULL)
      {
      struct gfPcrOutput *gpo;
      char urlFormat[2048];
      printf("The sequences and coordinates shown below are from %s, "
  	   "not from the genome assembly.  The links lead to the "
  	   "Genome Browser at the position of the entire target "
  	   "sequence.<BR>\n",
  	   server->targetDb->description);
      printf("<TT><PRE>");
      for (gpo = gpoList;  gpo != NULL;  gpo = gpo->next)
  	{
  	/* Not used as a format here; we modify the name used for position: */
  	safef(urlFormat, sizeof(urlFormat), "%s?%s&db=%s&position=%s"
  	      "&hgPcrResult=pack", 
  	      hgTracksName(), cartSidUrlString(cart), server->targetDb->db,
  	      pcrResultItemAccession(gpo->seqName));
  	if (gpo->strand == '-')
  	    printf("<EM>Warning: this amplification is on the reverse-"
  		   "complement of %s</EM>.\n", gpo->seqName);
  	gfPcrOutputWriteOne(gpo, "fa", urlFormat, stdout);
  	printf("\n");
  	}
+ 
      printf("</PRE></TT>");
      writePcrResultTrack(gpoList, server->targetDb->db, server->targetDb->name);
      }
  else
      {
      printf("No matches to %s %s in %s", gpi->fPrimer, gpi->rPrimer, 
  	   server->targetDb->description);
      }
 +gfDisconnect(&conn);
  }
  
  boolean doPcr(struct pcrServer *server, struct targetPcrServer *targetServer,
  	char *fPrimer, char *rPrimer, 
  	int maxSize, int minPerfect, int minGood, boolean flipReverse)
  /* Do the PCR, and show results. */
  {
  struct errCatch *errCatch = errCatchNew();
  boolean ok = FALSE;
  
  hgBotDelay();
  if (flipReverse)
      reverseComplement(rPrimer, strlen(rPrimer));
  if (errCatchStart(errCatch))
      {