f749015964226458297282a66117dd0e6c84142c
larrym
  Wed Jan 4 14:05:55 2012 -0800
add bamChromList
diff --git src/lib/bamFile.c src/lib/bamFile.c
index 94da58a..15877bd 100644
--- src/lib/bamFile.c
+++ src/lib/bamFile.c
@@ -477,30 +477,75 @@
     else if (type == 'c') { dyStringPrintf(dy, "%d", *s); ++s; }
     else if (type == 'S') { dyStringPrintf(dy, "%u", *(uint16_t*)s); s += 2; }
     else if (type == 's') { dyStringPrintf(dy, "%d", *(int16_t*)s); s += 2; }
     else if (type == 'I') { dyStringPrintf(dy, "%u", *(uint32_t*)s); s += 4; }
     else if (type == 'i') { dyStringPrintf(dy, "%d", *(int32_t*)s); s += 4; }
     else if (type == 'f') { dyStringPrintf(dy, "%g", *(float*)s); s += 4; }
     else if (type == 'd') { dyStringPrintf(dy, "%lg", *(double*)s); s += 8; }
     else if (type == 'Z' || type == 'H')
 	{
 	dyStringAppend(dy, (char *)s);
 	s += strlen((char *)s) + 1;
 	}
     }
 }
 
+struct bamChromInfo *bamChromList(samfile_t *fh)
+{
+/* Return list of chromosomes from bam header. We normalize chromosome names to UCSC format. */
+int i;
+struct bamChromInfo *list = NULL;
+bam_header_t *bamHeader = fh->header;
+if(bamHeader == NULL)
+    return NULL;
+for(i = 0; i < bamHeader->n_targets; i++)
+    {
+    struct bamChromInfo *info = NULL;
+    char chrom[512];
+    uint32_t size = bamHeader->target_len[i];
+    safecpy(chrom, sizeof(chrom), bamHeader->target_name[i]);
+
+    // normalize to UCSC chrom naming conventions
+    if(sameString(chrom, "MT"))
+        strcpy(chrom, "chrM");
+    else if(sameString(chrom, "X"))
+        strcpy(chrom, "chrX");
+    else if(sameString(chrom, "Y"))
+        strcpy(chrom, "chrY");
+    else
+        {
+        // convert "1" => "chr1"
+        boolean allDigits = TRUE;
+        int j;
+        for(j = 0; chrom[j] && allDigits; j++)
+            allDigits = isdigit(chrom[j]);
+        if(allDigits)
+            {
+            char *copy = cloneString(chrom);
+            safef(chrom, sizeof(chrom), "chr%s", copy);
+            freeMem(copy);
+            }
+        }
+    AllocVar(info);
+    info->name = cloneString(chrom);
+    info->size = size;
+    slAddHead(&list, info);
+    }
+slReverse(&list);
+return list;
+}
+
 #else
 // If we're not compiling with samtools, make stub routines so compile won't fail:
 
 boolean bamFileExists(char *bamFileName)
 /* Return TRUE if we can successfully open the bam file and its index file. */
 {
 warn(COMPILE_WITH_SAMTOOLS, "bamFileExists");
 return FALSE;
 }
 
 samfile_t *bamOpen(char *fileOrUrl, char **retBamFileName)
 /* Return an open bam file */
 {
 warn(COMPILE_WITH_SAMTOOLS, "bamOpenUdc");
 return FALSE;
@@ -593,16 +638,47 @@
 void bamShowTags(const bam1_t *bam)
 /* Print out tags in HTML: bold key, no type indicator for brevity. */
 {
 errAbort(COMPILE_WITH_SAMTOOLS, "bamShowTags");
 }
 
 char *bamGetTagString(const bam1_t *bam, char *tag, char *buf, size_t bufSize)
 /* If bam's tags include the given 2-character tag, place the value into
  * buf (zero-terminated, trunc'd if nec) and return a pointer to buf,
  * or NULL if tag is not present. */
 {
 errAbort(COMPILE_WITH_SAMTOOLS, "bamGetTagString");
 return NULL;
 }
 
+struct bamChromInfo *bamChromList(samfile_t *fh)
+{
+errAbort(COMPILE_WITH_SAMTOOLS, "bamChromList");
+return NULL;
+}
+
 #endif//ndef USE_BAM
+
+static void bamChromInfoFree(struct bamChromInfo **pInfo)
+/* Free up one chromInfo */
+{
+struct bamChromInfo *info = *pInfo;
+if (info != NULL)
+    {
+    freeMem(info->name);
+    freez(pInfo);
+    }
+}
+
+void bamChromInfoFreeList(struct bamChromInfo **pList)
+/* Free a list of dynamically allocated bamChromInfo's */
+{
+struct bamChromInfo *el, *next;
+
+for (el = *pList; el != NULL; el = next)
+    {
+    next = el->next;
+    bamChromInfoFree(&el);
+    }
+*pList = NULL;
+}
+