void addCloneInfo(char *glFileName, struct hash *cloneHash, struct clonePos **pCloneList)
/* Add in clone info from one .gl file. */
{
    char dir[256], chrom[128], ext[64];
    struct gl gl;
    struct lineFile *lf = lineFileOpen(glFileName, TRUE);
    struct clonePos *clone;
    char *line, *words[8];
    int lineSize, wordCount;
    char cloneVerName[128];
    char cloneName[128];

    printf("Processing %s\n", glFileName);
    splitPath(glFileName, dir, chrom, ext);
    while (lineFileNext(lf, &line, &lineSize))
    {
        wordCount = chopLine(line, words);
        if (wordCount == 0)
            continue;
        if (wordCount != 4)
            errAbort("Expecting %d words line %d of %s", 4, lf->lineIx, lf->fileName);
        glStaticLoad(words, &gl);
        fragToCloneVerName(gl.frag, cloneVerName);
        fragToCloneName(gl.frag, cloneName);
        if ((clone = hashFindVal(cloneHash, cloneName)) == NULL)
        {
            AllocVar(clone);
            clone->name = cloneString(cloneVerName);
            clone->chrom = cloneString(chrom);
            clone->chromStart = gl.start;
            clone->chromEnd = gl.end;
            clone->faFile = cloneString("");
            slAddHead(pCloneList, clone);
            hashAdd(cloneHash, cloneName, clone);
        }
        else
        {
            if (!sameString(clone->chrom, chrom))
            {
                warn("Clone %s is on chromosomes %s and %s.  Ignoring %s",
                     cloneName, clone->chrom, chrom, chrom);
                continue;
            }
            if (clone->chromStart > gl.start)
                clone->chromStart = gl.start;
            if (clone->chromEnd < gl.end)
                clone->chromEnd = gl.end;
        }
    }
    lineFileClose(&lf);
}
void addStretchInfo(char *fileName, struct chromInfo *ctg)
/* Add info about how much clones are stretched from gl file. */
{
struct hash *cloneHash = newHash(12);
struct lineFile *lf = lineFileOpen(fileName, TRUE);
char *row[4];
struct gl gl;
struct clone *cloneList = NULL, *clone;

while (lineFileRow(lf, row))
    {
    glStaticLoad(row, &gl);
    chopSuffix(gl.frag);
    if ((clone = hashFindVal(cloneHash, gl.frag)) == NULL)
        {
	AllocVar(clone);
	slAddHead(&cloneList, clone);
	hashAddSaveName(cloneHash, gl.frag, clone, &clone->name);
	clone->start = gl.start;
	clone->end = gl.end;
	}
    else
        {
	if (gl.start < clone->start) clone->start = gl.start;
	if (gl.end > clone->end) clone->end = gl.end;
	}
    clone->totalSize += gl.end - gl.start;
    }
for (clone = cloneList; clone != NULL; clone = clone->next)
    {
    int stretchSize = clone->end - clone->start;
    double stretchRatio;
    ctg->cloneCount += 1;
    ctg->totalStretch += stretchSize - clone->totalSize;
    stretchRatio = stretchSize / clone->totalSize;
    if (stretchRatio > 1.3)
        ctg->stretchedClones += 1;
    if (stretchRatio > 2.0)
        ctg->wayStretchedClones += 1;
    }
lineFileClose(&lf);
hashFree(&cloneHash);
slFreeList(&cloneList);
}
void clonePosTab(char *fileName, struct hash *cloneHash)
/* Write out clonePos.tab. */
{
char query[256];
struct sqlResult *sr;
char **row;
struct clonePos *posList = NULL, *pos;
struct gl gl;
struct cloneInfo *info;
struct sqlConnection *conn = hAllocConn();

sprintf(query, "select * from chr18_gl");
sr = sqlGetResult(conn, query);
while ((row = sqlNextRow(sr)) != NULL)
    {
    glStaticLoad(row, &gl);
    fragNameToCloneName(gl.frag);
    info = findClone(cloneHash, gl.frag);
    if ((pos = info->pos) == NULL)
	{
	AllocVar(pos);
	pos->info = info;
	info->pos = pos;
	pos->start = gl.start;
	pos->end = gl.end;
	slAddHead(&posList, pos);
	}
    else
	{
	if (pos->start > gl.start)
	    pos->start = gl.start;
	if (pos->end < gl.end)
	    pos->end = gl.end;
	}
    }
sqlFreeResult(&sr);
hFreeConn(&conn);
slSort(&posList, cmpClonePos);
writePosList(fileName, posList, "chr18");
}