src/hg/hgc/parClick.c 1.1

1.1 2010/02/18 06:01:45 markd
added details page for PAR tracks
Index: src/hg/hgc/parClick.c
===================================================================
RCS file: src/hg/hgc/parClick.c
diff -N src/hg/hgc/parClick.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/hg/hgc/parClick.c	18 Feb 2010 06:01:45 -0000	1.1
@@ -0,0 +1,150 @@
+/* parClick - click handling for par track  */
+#include "common.h"
+#include "parClick.h"
+#include "hgc.h"
+#include "bed.h"
+#include "hdb.h"
+#include "web.h"
+#include "hCommon.h"
+
+static struct bed *loadParTable(struct trackDb *tdb)
+/* load all records in the par table */
+{
+struct bed *pars = NULL;
+struct sqlConnection *conn = hAllocConn(database);
+char query[512];
+safef(query, sizeof(query), "select * from %s", tdb->tableName);
+struct sqlResult *sr = sqlGetResult(conn, query);
+char **row;
+while ((row = sqlNextRow(sr)) != NULL)
+    slAddHead(&pars, bedLoadN(row, 4));
+sqlFreeResult(&sr);
+hFreeConn(&conn);
+return pars;
+}
+
+static int parCmp(const void *va, const void *vb)
+/* Compare by name, then by chrom */
+{
+const struct bed *a = *((struct bed **)va);
+const struct bed *b = *((struct bed **)vb);
+int dif = strcmp(a->name, b->name);
+if (dif == 0)
+    dif = strcmp(a->chrom, b->chrom);
+return dif;
+}
+
+static struct bed *getClickedPar(struct bed **pars)
+/* find par record that was clicked on, removing it from the list */
+{
+struct bed *clickedPar = NULL, *otherPars = NULL, *par;
+while ((par = slPopHead(pars)) != NULL)
+    {
+    if (sameString(par->chrom, seqName) && positiveRangeIntersection(par->chromStart, par->chromEnd, winStart, winEnd))
+        {
+        if (clickedPar != NULL)
+            errAbort("multiple par rows overlapping %s:%d-%d", seqName, winStart, winEnd);
+        clickedPar = par;
+        }
+    else
+        slAddHead(&otherPars, par);
+    }
+if (clickedPar == NULL)
+    errAbort("no par row overlapping %s:%d-%d", seqName, winStart, winEnd);
+*pars = otherPars;
+return clickedPar;
+}
+
+static struct bed *getHomologousPar(struct bed *clickedPar, struct bed **pars)
+/* find par record that was clicked on, removing it from the list */
+{
+struct bed *homPar = NULL, *otherPars = NULL, *par;
+while ((par = slPopHead(pars)) != NULL)
+    {
+    if (sameString(par->name, clickedPar->name))
+        {
+        if (homPar != NULL)
+            errAbort("multiple homologous par rows for %s", clickedPar->name);
+        homPar = par;
+        }
+    else
+        slAddHead(&otherPars, par);
+    }
+if (homPar == NULL)
+    errAbort("no homologous par row for %s", clickedPar->name);
+*pars = otherPars;
+return homPar;
+}
+
+static void printParLink(struct bed *par)
+/* print one par link back to the browser */
+{
+webPrintLinkCellStart();
+printf("<A HREF=\"%s?db=%s&position=%s:%d-%d\">%s:%d-%d</A>",
+       hgTracksName(), database, 
+       par->chrom, par->chromStart, par->chromEnd,
+       par->chrom, par->chromStart+1, par->chromEnd);
+webPrintLinkCellEnd();
+}
+
+static void printHomPairRow(struct bed *parA, struct bed *parB)
+/* print a homologous pair */
+{
+if (!sameString(parA->name, parB->name))
+    errAbort("invalid PAR homologous pair: %s and %s", parA->name, parB->name);
+webPrintLabelCell(parA->name);
+printParLink(parA);
+printParLink(parB);
+}
+
+static void printOtherPars(struct bed *clickedPar, struct bed *pars)
+/* pirnt out other pairs of pars, keeping chroms lined up that were not
+ * selected */
+{
+webPrintLinkTableNewRow();
+webPrintWideCenteredLabelCell("Other PARs", 3);
+struct bed *par1;
+for (par1 = pars; par1 != NULL; par1 = par1->next->next)
+    {
+    webPrintLinkTableNewRow();
+    if (sameString(par1->chrom, clickedPar->chrom))
+        printHomPairRow(par1, par1->next);
+    else
+        printHomPairRow(par1->next, par1);
+    }
+}
+
+void doParDetails(struct trackDb *tdb, char *name)
+/* show details of a PAR item. */
+{
+// load entire PAR table (t's tiny) and partition
+struct bed *pars = loadParTable(tdb);
+if (slCount(pars) & 1)
+    errAbort("par items not paired in %s", tdb->tableName);
+
+struct bed *clickedPar = getClickedPar(&pars);
+struct bed *homPar = getHomologousPar(clickedPar, &pars);
+slSort(&pars, parCmp);
+
+cartWebStart(cart, database, "Pseudoautosomal regions");
+webPrintLinkTableStart();
+
+// header
+webPrintLabelCell("");
+webPrintLabelCell("Selected PAR");
+webPrintLabelCell("Homologous PAR");
+
+// selected
+webPrintLinkTableNewRow();
+printHomPairRow(clickedPar, homPar);
+if (pars != NULL)
+    printOtherPars(clickedPar, pars);
+
+webPrintLinkTableEnd();
+printTrackHtml(tdb);
+webEnd();
+
+bedFreeList(&pars);
+bedFree(&clickedPar);
+bedFree(&homPar);
+}