13407761de80485e6d82d05387698910fa309502
galt
  Tue Jan 28 17:30:54 2014 -0800
Fixes #12509. Create special chrom ordering for hg38 as specified in the ticket.
diff --git src/hg/lib/hdb.c src/hg/lib/hdb.c
index d9d66f3..46c8187 100644
--- src/hg/lib/hdb.c
+++ src/hg/lib/hdb.c
@@ -5024,37 +5024,138 @@
 	return 0;
     }
 else if (sameString(str1, "M") && !sameString(str2, "M"))
     return 1;
 else if (!sameString(str1, "M") && sameString(str2, "M"))
     return -1;
 else if (str1[0] == 'U' && str2[0] != 'U')
     return 1;
 else if (str1[0] != 'U' && str2[0] == 'U')
     return -1;
 else
     return strcmp(str1, str2);
 }
 
 int chrSlNameCmp(const void *el1, const void *el2)
+/* Compare chromosome or linkage group names str1 and str2 
+ * to achieve this order:
+ * chr1 .. chr22
+ * chrX
+ * chrY
+ * chrM
+ * chr1_{alt, random} .. chr22_{alt, random}
+ * chrUns
+ */
+{
+struct slName *sln1 = *(struct slName **)el1;
+struct slName *sln2 = *(struct slName **)el2;
+return chrNameCmp(sln1->name, sln2->name);
+}
+
+int chrNameCmpWithAltRandom(char *str1, char *str2)
+/* Compare chromosome or linkage group names str1 and str2 
+ * to achieve this order:
+ * chr1 .. chr22
+ * chrX
+ * chrY
+ * chrM
+ * chr1_{alt, random} .. chr22_{alt, random}
+ * chrUns
+ */
+{
+int num1 = 0, num2 = 0;
+int match1 = 0, match2 = 0;
+char suffix1[512], suffix2[512];
+
+/* put chrUn at the bottom */
+if (startsWith("chrUn", str1) && !startsWith("chrUn", str2))
+    return 1;
+if (!startsWith("chrUn", str1) && startsWith("chrUn", str2))
+    return  -1;
+
+/* if it is _alt or _random then it goes at the end */
+if ( (endsWith(str1, "_alt")||endsWith(str1, "_random")) && !(endsWith(str2, "_alt") || endsWith(str2, "_random")))
+    return 1;
+if (!(endsWith(str1, "_alt")||endsWith(str1, "_random")) &&  (endsWith(str2, "_alt") || endsWith(str2, "_random")))
+    return -1;
+
+/* get past "chr" or "Group" prefix: */
+if (startsWith("chr", str1))
+    str1 += 3;
+else if (startsWith("Group", str1))
+    str1 += 5;
+else
+    return -1;
+if (startsWith("chr", str2))
+    str2 += 3;
+else if (startsWith("Group", str2))
+    str2 += 5;
+else
+    return 1;
+/* If only one is numeric, that one goes first. 
+ * If both are numeric, compare by number; 
+ * If same number, put _randoms at end, then look at suffix. 
+ * Otherwise go alph. but put M and U/Un/Un_random at end. */
+match1 = sscanf(str1, "%d%s", &num1, suffix1);
+match2 = sscanf(str2, "%d%s", &num2, suffix2);
+if (match1 && !match2)
+    return -1;
+else if (!match1 && match2)
+    return 1;
+else if (match1 && match2)
+    {
+    int diff = num1 - num2;
+    if (diff != 0)
+	return diff;
+
+    /* within groups with the same number, organize with random last */
+    if (endsWith(str1, "_random") && !endsWith(str2, "_random"))
+	return 1;
+    if (!endsWith(str1, "_random") && endsWith(str2, "_random"))
+	return -1;
+
+    /* same chrom number... got suffix? */
+    if (match1 > 1 && match2 <= 1)
+	return 1;
+    else if (match1 <= 1 && match2 > 1)
+	return -1;
+    else if (match1 > 1 && match2 > 1)
+	return strcmp(suffix1, suffix2);
+    else
+	/* This shouldn't happen (duplicate chrom name passed in) */
+	return 0;
+    }
+else if (str1[0] == 'U' && str2[0] != 'U')
+    return 1;
+else if (str1[0] != 'U' && str2[0] == 'U')
+    return -1;
+else if (sameString(str1, "M") && !sameString(str2, "M"))
+    return 1;
+else if (!sameString(str1, "M") && sameString(str2, "M"))
+    return -1;
+else
+    return strcmp(str1, str2);
+}
+
+int chrSlNameCmpWithAltRandom(const void *el1, const void *el2)
 /* Compare chromosome names by number, then suffix.  el1 and el2 must be
  * slName **s (as passed in by slSort) whose names match the regex
  * "chr([0-9]+|[A-Za-z0-9]+)(_[A-Za-z0-9_]+)?". */
 {
 struct slName *sln1 = *(struct slName **)el1;
 struct slName *sln2 = *(struct slName **)el2;
-return chrNameCmp(sln1->name, sln2->name);
+return chrNameCmpWithAltRandom(sln1->name, sln2->name);
 }
 
 int bedCmpExtendedChr(const void *va, const void *vb)
 /* Compare to sort based on chrom,chromStart.  Use extended
  * chrom name comparison, that strip prefixes and does numeric compare */
 {
 const struct bed *a = *((struct bed **)va);
 const struct bed *b = *((struct bed **)vb);
 int dif;
 dif = chrNameCmp(a->chrom, b->chrom);
 if (dif == 0)
     dif = a->chromStart - b->chromStart;
 return dif;
 }