dfcc30cdb7e4d1afe1ea106162e294791eb64e76
chmalee
  Mon Jun 29 16:54:03 2020 -0700
Fix 'trio' ordering bug when there is only one parent and we are drawing in child,parent order, refs #25813

diff --git src/hg/hgTracks/vcfTrack.c src/hg/hgTracks/vcfTrack.c
index e2d02f6..f495b74 100644
--- src/hg/hgTracks/vcfTrack.c
+++ src/hg/hgTracks/vcfTrack.c
@@ -1728,53 +1728,69 @@
 }
 
 static void fillOutHapOrder(unsigned int  *hapOrder, unsigned int hapCount, struct hapDistanceMatrixCell *c1, struct hapDistanceMatrixCell *c2, char **sampleDrawOrder)
 /* Assign indices to hapOrder in the order we should draw the alleles. Allows for the second parent
  * cell to be NULL */
 {
 if (c1 == NULL)
     errAbort("Error: fillOutHapOrder passed NULL parent");
 int numSamplesToDraw = hapCount / 2;
 char *childSampleName = c1->otherId;
 int childIx = stringArrayIx(childSampleName, sampleDrawOrder, numSamplesToDraw);
 int i;
 for (i = 0; i < numSamplesToDraw; i++)
     {
     char *thisSample = sampleDrawOrder[i];
-    struct hapDistanceMatrixCell *thisCell = c2 != NULL && sameString(c2->sampleId,thisSample) ? c2 : c1;
     short hapIx = 2*i;
     if (i != childIx) // fill out the parent indices, which may be above or below the child
         {
+        struct hapDistanceMatrixCell *thisCell = c2 != NULL && sameString(c2->sampleId,thisSample) ? c2 : c1;
         if (i < childIx)
             {
             hapOrder[hapIx] = toggleInt(thisCell->alleleIx);
             hapOrder[hapIx+1] = thisCell->alleleIx;
             }
         else // below the child
             {
             hapOrder[hapIx] = thisCell->alleleIx;
             hapOrder[hapIx+1] = toggleInt(thisCell->alleleIx);
             }
         }
     else // fill out the child indices
         {
+        if (i == 0)
+            {
+            if (c2)
+                hapOrder[hapIx] = c2->otherAlleleIx;
+            else
+                hapOrder[hapIx] = toggleInt(c1->otherAlleleIx);
+            hapOrder[hapIx+1] = c1->otherAlleleIx;
+            }
+        else if (i == 1)
+            {
             hapOrder[hapIx] = c1->otherAlleleIx;
             if (c2)
                 hapOrder[hapIx+1] = c2->otherAlleleIx;
             else
                 hapOrder[hapIx+1] = toggleInt(c1->otherAlleleIx);
             }
+        else
+            {
+            hapOrder[hapIx] = c2->otherAlleleIx;
+            hapOrder[hapIx+1] = c1->otherAlleleIx;
+            }
+        }
     }
 }
 
 static void maybeRollBackCell(struct hapDistanceMatrixCell *c1, struct hapDistanceMatrixCell *c2,
                               struct hapDistanceMatrixCell *c1Copy, struct hapDistanceMatrixCell *c2Copy)
 /* At this point c1->otherAlleleIx != c2->otherAlleleIx, however, it may be the case that c2 has a
  * better scoring match to c1->otherAlleleIx, so try to find it and reset the values */
 {
 struct hapDistanceMatrixCell *tmp = c2;
 while (tmp->otherAlleleIx != c1->otherAlleleIx)
     tmp = tmp->next;
 if (tmp->dist < c1->dist)
     {
     *c2 = *tmp;
     *c1 = *c1Copy;
@@ -1976,51 +1992,57 @@
 }
 
 #define VCFPHASED_UNPHASED_COLOR MG_RED
 
 
 static int getChildAlleleColor(struct track *track, struct vcfRecord *rec, int childHapIx,
                                int alleleIx, int nameIx, int gtHapCount, unsigned int *gtHapOrder,
                                char *sampleOrder[])
 /* Return the color we should use for this variant, depending on whether the allele
  * of the child matches what the parent transmitted or if there was some kind of
  * 'mendelian inconsistency' */
 {
 // if there are no parents to draw then no concept of transmitted vs unstransmitted
 if (gtHapCount <= 2)
     return MG_BLACK;
-int parIx = 0;
+int parIx = alleleIx;
+int numSamples = gtHapCount / 2;
+boolean isEven = (alleleIx % 2) == 0;
+const int adjacentLineSet = 1;
+// how many haplotype "lines" away is the second parent if we are drawing in either
+// parent1,parent2,child or child,parent1,parent2 order:
+const int otherLineSet = 4;
 if (nameIx == 0)
     {
-    if (alleleIx % 2 == 0)
-        parIx = alleleIx + 2;
-    else
-        parIx = alleleIx + 3;
+    if (!isEven)
+        parIx = alleleIx + adjacentLineSet;
+    else if (numSamples > 2)
+            parIx = alleleIx + otherLineSet;
     }
 else if (nameIx == 1)
     {
-    if (alleleIx % 2 == 0)
-        parIx = alleleIx - 1;
-    else
-        parIx = alleleIx + 1;
+    if (isEven)
+        parIx = alleleIx - adjacentLineSet;
+    else if (numSamples > 2) // don't compare the allele the child to a missing parent
+        parIx = alleleIx + adjacentLineSet;
     }
 else
     {
-    if (alleleIx % 2 == 0)
-        parIx = alleleIx - 3;
+    if (isEven)
+        parIx = alleleIx - adjacentLineSet;
     else
-        parIx = alleleIx - 2;
+        parIx = alleleIx - otherLineSet;
     }
 struct vcfGenotype *parentGt = &(rec->genotypes[gtHapOrder[parIx] >> 1]);
 if (parentGt->isPhased || (parentGt->hapIxA == 1 && parentGt->hapIxB == 1))
     {
     int parentAlleleIx = gtHapOrder[parIx] & 1 ? parentGt->hapIxB : parentGt->hapIxA;
     if (rec->alleles[childHapIx] != rec->alleles[parentAlleleIx]) // if they disagree mark as red
         return MG_RED;
     else
         return MG_BLACK;
     }
 return MG_BLACK;
 }
 
 void vcfPhasedDrawOneRecord(struct track *track, struct hvGfx *hvg, struct vcfRecord *rec, void *item,
                             unsigned int *gtHapOrder, int gtHapCount, int xOff, int yOffsets[],