afa49f8318fdcd16205bc6cbc55d293d208fc5bd
angie
  Tue May 10 11:37:29 2011 -0700
Feature #3711 bugfix: handle 0 or 1 items correctly in hacTree andVCF track handler's haplotype clustering.

diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c
index de722ff..02c2a01 100644
--- src/hg/hgTracks/vcfTrack.c
+++ src/hg/hgTracks/vcfTrack.c
@@ -238,30 +238,34 @@
     dy2 = dyStringNew(0);
     }
 hapClusterToString(c1, dy1, helper->len);
 hapClusterToString(c2, dy2, helper->len);
 return strcmp(dy1->string, dy2->string);
 }
 
 void rSetGtHapOrder(struct hacTree *ht, unsigned short *gtHapOrder, unsigned short *retGtHapEnd)
 /* Traverse hacTree and build an ordered array of genotype + haplotype indices. */
 {
 if (ht->left == NULL && ht->right == NULL)
     {
     struct hapCluster *c = (struct hapCluster *)ht->itemOrCluster;
     gtHapOrder[(*retGtHapEnd)++] = c->gtHapIx;
     }
+else if (ht->left == NULL)
+    rSetGtHapOrder(ht->right, gtHapOrder, retGtHapEnd);
+else if (ht->right == NULL)
+    rSetGtHapOrder(ht->left, gtHapOrder, retGtHapEnd);
 else
     {
     struct hapCluster *cL = (struct hapCluster *)ht->left->itemOrCluster;
     struct hapCluster *cR = (struct hapCluster *)ht->right->itemOrCluster;
     if (cL->leafCount >= cR->leafCount)
 	{
 	rSetGtHapOrder(ht->left, gtHapOrder, retGtHapEnd);
 	rSetGtHapOrder(ht->right, gtHapOrder, retGtHapEnd);
 	}
     else
 	{
 	rSetGtHapOrder(ht->right, gtHapOrder, retGtHapEnd);
 	rSetGtHapOrder(ht->left, gtHapOrder, retGtHapEnd);
 	}
     }
@@ -440,30 +444,32 @@
 dyStringPrintf(dy, "%s/%s:%d %s/%s:%d %s/%s:%d", rec->ref, rec->ref, gtRefRefCount,
 	       rec->ref, altAlleles[0], gtRefAltCount,
 	       altAlleles[0], altAlleles[0], gtAltAltCount);
 if (gtOtherCount > 0)
     dyStringPrintf(dy, " other:%d", gtOtherCount);
 return dy->string;
 }
 
 static void vcfHapClusterDraw(struct track *tg, int seqStart, int seqEnd,
 			      struct hvGfx *hvg, int xOff, int yOff, int width,
 			      MgFont *font, Color color, enum trackVisibility vis)
 /* Split samples' chromosomes (haplotypes), cluster them by center-weighted
  * alpha similarity, and draw in the order determined by clustering. */
 {
 const struct vcfFile *vcff = tg->extraUiData;
+if (vcff->records == NULL)
+    return;
 unsigned short gtHapEnd = 0;
 unsigned short *gtHapOrder = clusterChroms(vcff, &gtHapEnd);
 struct dyString *tmp = dyStringNew(0);
 struct vcfRecord *rec;
 const int lineHeight = tg->lineHeight;
 const int itemHeight = tg->heightPer;
 const double scale = scaleForPixels(width);
 for (rec = vcff->records;  rec != NULL;  rec = rec->next)
     {
     dyStringClear(tmp);
     dyStringAppend(tmp, rec->alt);
     char *altAlleles[256];
     int altCount = chopCommas(tmp->string, altAlleles);
     int x1 = round((double)(rec->chromStart-winStart)*scale) + xOff;
     int x2 = round((double)(rec->chromEnd-winStart)*scale) + xOff;
@@ -482,30 +488,32 @@
 		       hvg, x1, y, w, itemHeight, lineHeight);
 	}
     mapBoxHgcOrHgGene(hvg, rec->chromStart, rec->chromEnd, x1, yOff, w, tg->height, tg->track,
 		      rec->name, gtSummaryString(rec, altAlleles, altCount),
 		      NULL, TRUE, NULL);
     }
 // left labels?
 }
 
 static int vcfHapClusterTotalHeight(struct track *tg, enum trackVisibility vis)
 /* Return height of haplotype graph (2 * #samples * lineHeight);
  * 2 because we're assuming diploid genomes here, no XXY, tetraploid etc. */
 {
 // Should we make it single-height when on chrY?
 const struct vcfFile *vcff = tg->extraUiData;
+if (vcff->records == NULL)
+    return 0;
 int ploidy = 2;
 tg->height = ploidy * vcff->genotypeCount * tg->lineHeight;
 return tg->height;
 }
 
 static char *vcfHapClusterTrackName(struct track *tg, void *item)
 /* If someone asks for itemName/mapItemName, just send name of track like wiggle. */
 {
 return tg->track;
 }
 
 static void vcfHapClusterOverloadMethods(struct track *tg, struct vcfFile *vcff)
 /* If we confirm at load time that we can draw a haplotype graph, use
  * this to overwrite the methods for the rest of execution: */
 {