Exemple #1
0
void fillInGene(struct chain *chain, struct genePred *gene, struct genePred **pGene)
/** Fill in syntenic gene structure with initial information for gene. */
{
FILE *cdsErrorFp;
struct genePred *synGene = NULL;
int qs, qe;
struct chain *subChain=NULL, *toFree=NULL;
AllocVar(synGene);
chainSubSetForRegion(chain, gene->txStart, gene->txEnd , &subChain, &toFree);    
if(subChain == NULL)
    {
    *pGene= NULL;
    return;
    }
qChainRangePlusStrand(subChain, &qs, &qe);
synGene->chrom = cloneString(subChain->qName);
synGene->name = cloneString(gene->name);
synGene->txStart = qs;
synGene->txEnd = qe;
AllocArray(synGene->exonStarts, gene->exonCount);
AllocArray(synGene->exonEnds, gene->exonCount);
if(chain->qStrand == '+')
    strncpy(synGene->strand,  gene->strand, sizeof(synGene->strand));
else
    {
    if(gene->strand[0] == '+')
	strncpy(synGene->strand,  "-", sizeof(synGene->strand));
    else if(gene->strand[0] == '-')
	strncpy(synGene->strand,  "+", sizeof(synGene->strand));
    else
	errAbort("Don't recognize strand %s from gene %s", gene->strand, gene->name);
    }
chainFree(&toFree);
chainSubSetForRegion(chain, gene->cdsStart, gene->cdsEnd , &subChain, &toFree);    
if(subChain == NULL )
    {
    if(optionExists("cdsErrorFile"))
        {
        cdsErrorFp = fopen( optionVal("cdsErrorFile",NULL), "a" );
        fprintf( cdsErrorFp, "%s\t%s\t%u\t%u\t%u\t%u\t%s\t%d\n", gene->name, gene->chrom, gene->txStart, 
		 gene->txEnd, gene->cdsStart, gene->cdsEnd, gene->strand, gene->exonCount );
        fclose(cdsErrorFp);
        }
    *pGene = NULL;
    genePredFree(&synGene); 
    return;
    }
qChainRangePlusStrand(subChain, &qs, &qe);
synGene->cdsStart = qs;
synGene->cdsEnd = qe;
chainFree(&toFree);
*pGene = synGene;
}
Exemple #2
0
enum remapResult remapBase(struct hash *chainHash, char *orig_chrom, int orig_base, char **dest_chrom, int *dest_base)
{
    struct liftOverChromMap *map = hashFindVal(chainHash, orig_chrom);
    struct binElement *list = NULL;
    struct chain *chainHit = NULL;
    struct chain *toFree;
    struct chain *subChain;
    int start = orig_base, end = start+1;
    if (map)
	list = binKeeperFind(map->bk, start, start+1);
    if (!list)
	return deleted;
    else if (list->next != NULL)
    {
	slFreeList(&list);
	return duplicated;    
    }
    chainHit = list->val;
    if (!mapThroughChain(chainHit, 1, &start, &end, &subChain, &toFree))
    {
	slFreeList(&list);
	return problem;
    }
    chainFree(&toFree);
    *dest_base = start;
    *dest_chrom = chainHit->qName;
    slFreeList(&list);
    return lifted;
}
Exemple #3
0
void chainToPsl(char *inName, char *tSizeFile, char *qSizeFile,  char *targetList, char *queryList, char *outName)
/* chainToPsl - Convert chain file to psl format. */
{
struct hash *tSizeHash = readSizes(tSizeFile);
struct hash *qSizeHash = readSizes(qSizeFile);
struct lineFile *lf = lineFileOpen(inName, TRUE);
FILE *f = mustOpen(outName, "w");
struct hash *fileHash = newHash(0);  /* No value. */
struct hash *tHash = newHash(20);  /* seqFilePos value. */
struct hash *qHash = newHash(20);  /* seqFilePos value. */
struct dlList *fileCache = newDlList();
struct chain *chain;
int q,t;

verbose(1, "Scanning %s\n", targetList);
hashFileList(targetList, fileHash, tHash);
verbose(1, "Scanning %s\n", queryList);
hashFileList(queryList, fileHash, qHash);
verbose(1, "Converting %s\n", inName);

while ((chain = chainRead(lf)) != NULL)
    {
    //uglyf("chain %s %s \n",chain->tName,chain->qName); 
    q = findSize(qSizeHash, chain->qName);
    t = findSize(tSizeHash, chain->tName);
    aliStringToPsl(lf, chain->qName, chain->tName, chain->qSize, chain->tSize,
	min(chain->tEnd-chain->tStart, chain->qEnd-chain->qStart), chain->qStart, chain->qEnd, chain->tStart, chain->tEnd,
        chain->qStrand, f, chain, tHash, qHash, fileCache);
    chainFree(&chain);
    }
lineFileClose(&lf);
carefulClose(&f);
}
Exemple #4
0
struct hash *chainReadUsedSwapLf(char *fileName, boolean swapQ, Bits *bits, struct lineFile *lf)
/* Read chains that are marked as used in the 
 * bits array (which may be NULL) into a hash keyed by id. */
{
char nameBuf[16];
struct hash *hash = hashNew(18);
struct chain *chain;
int usedCount = 0, count = 0;

while ((chain = chainRead(lf)) != NULL)
    {
    ++count;
    if (bits != NULL && !bitReadOne(bits, chain->id))
	{
	chainFree(&chain);
        continue;
	}
    safef(nameBuf, sizeof(nameBuf), "%x", chain->id);
    if (hashLookup(hash, nameBuf))
        errAbort("Duplicate chain %d ending line %d of %s", 
		chain->id, lf->lineIx, lf->fileName);
    if (swapQ)
        chainSwap(chain);
    hashAdd(hash, nameBuf, chain);
    ++usedCount;
    }
return hash;
}
void chainPair(struct seqPair *sp,
	struct dnaSeq *qSeq, struct dnaSeq *tSeq, struct chain **pChainList,
	FILE *details)
/* Chain up blocks and output. */
{
struct chain *chainList, *chain, *next;
struct cBlock *b;
long startTime, dt;
int size = 0;
struct chainConnect cc;

verbose(1, "chainPair %s\n", sp->name);

/* Set up info for connect function. */
ZeroVar(&cc);
cc.query = qSeq;
cc.target = tSeq;
cc.ss = scoreScheme;
cc.gapCalc = gapCalc;

/* Score blocks. */
for (b = sp->blockList; b != NULL; b = b->next)
    {
    size = b->qEnd - b->qStart;
    checkBlockRange("query", qSeq, b->qStart, b->qEnd);
    checkBlockRange("target", tSeq, b->tStart, b->tEnd);
    b->score = axtScoreUngapped(scoreScheme, qSeq->dna + b->qStart, tSeq->dna + b->tStart, size);
    }


/* Get chain list and clean it up a little. */
startTime = clock1000();
chainList = chainBlocks(sp->qName, qSeq->size, sp->qStrand,
	sp->tName, tSeq->size, &sp->blockList,
	(ConnectCost)chainConnectCost, (GapCost)chainConnectGapCost,
	&cc, details);
dt = clock1000() - startTime;
verbose(1, "Main chaining step done in %ld milliseconds\n", dt);
for (chain = chainList; chain != NULL; chain = chain->next)
    {
    chainRemovePartialOverlaps(chain, qSeq, tSeq, scoreScheme->matrix);
    chainMergeAbutting(chain);
    chain->score = chainCalcScore(chain, scoreScheme, gapCalc,
    	qSeq, tSeq);
    }

/* Move chains scoring over threshold to master list. */
for (chain = chainList; chain != NULL; chain = next)
    {
    next = chain->next;
    if (chain->score >= minScore)
        {
	slAddHead(pChainList, chain);
	}
    else
        {
	chainFree(&chain);
	}
    }
}
void writeChainPart(struct dnaSeq *tChrom,
	struct nibTwoCache *qNtc, char *nibDir,
	struct chain *chain, int tStart, int tEnd, FILE *f, FILE *gapFile)
/* write out axt's from subset of chain */
{
struct dnaSeq *qSeq;
boolean isRev = (chain->qStrand == '-');
struct chain *subChain, *chainToFree;
int fullSeqSize;
int qStart;

chainSubsetOnT(chain, tStart, tEnd, &subChain, &chainToFree);
if (subChain == NULL)
    errAbort("null subchain in chain ID %d\n", chain->id);

/* Get query sequence fragment. */
nibTwoCacheSeqPart(qNtc, chain->qName, 1, 1, &fullSeqSize);
qStart = (isRev ? fullSeqSize - subChain->qEnd : subChain->qStart);
qSeq = nibTwoCacheSeqPart(qNtc, subChain->qName, qStart, 
                                subChain->qEnd - subChain->qStart, NULL);
if (isRev)
    reverseComplement(qSeq->dna, qSeq->size);

verbose(9, "fill chain id, subchain %d %s %d %d %c qOffset=%d\n", 
                subChain->id, subChain->qName,
                tStart, tEnd, subChain->qStrand, qStart);
writeAxtFromChain(subChain, qSeq, subChain->qStart, tChrom, 0, f, gapFile);
chainFree(&chainToFree);
freeDnaSeq(&qSeq);
}
void scorePair(struct seqPair *sp,
	struct dnaSeq *qSeq, struct dnaSeq *tSeq, struct chain **pChainList,
	struct chain *chainList)
/* Chain up blocks and output. */
{
struct chain  *chain, *next;
struct cBlock *b;

/* Set up info for connect function. */
scoreData.qSeq = qSeq;
scoreData.tSeq = tSeq;
scoreData.ss = scoreScheme;
scoreData.gapPower = 1.0/2.5;

for (chain = chainList; chain != NULL; chain = chain->next)
    {
    chain->score = chainScore(chain, qSeq, tSeq, scoreData.ss->matrix, gapCost);
    }

/* Move chains scoring over threshold to master list. */
for (chain = chainList; chain != NULL; chain = next)
    {
    next = chain->next;
    if (chain->score >= minScore)
        {
	slAddHead(pChainList, chain);
	}
    else 
        {
	chainFree(&chain);
	}
    }
}
Exemple #8
0
void chainIndex(char *inChain, char *outIndex)
/* chainIndex - Create simple two column file index for chain. */
{
struct lineFile *lf = lineFileOpen(inChain, TRUE);
FILE *f = mustOpen(outIndex, "w");
struct chain *chain, *lastChain = NULL;
long pos = 0;
struct hash *uniqHash = hashNew(16);

while ((chain = chainRead(lf)) != NULL)
    {
    if (lastChain == NULL || !sameString(chain->tName, lastChain->tName))
	{
	if (hashLookup(uniqHash, chain->tName))
	    {
	    errAbort("%s is not sorted, %s repeated with intervening %s", 
	    	inChain, chain->tName, lastChain->tName);
	    }
	hashAddInt(uniqHash, chain->tName, pos);
        fprintf(f, "%lx\t%s\n", pos, chain->tName);
	}
    chainFree(&lastChain);
    lastChain = chain;
    pos = lineFileTell(lf);
    }
}
void splatAlignFree(struct splatAlign **pAli)
/* Free up a splatAlign. */
{
struct splatAlign *ali = *pAli;
if (ali != NULL)
    {
    chainFree(&ali->chain);
    freez(pAli);
    }
}
Exemple #10
0
void chainFreeList(struct chain **pList)
/* Free a list of dynamically allocated chain's */
{
struct chain *el, *next;

for (el = *pList; el != NULL; el = next)
    {
    next = el->next;
    chainFree(&el);
    }
*pList = NULL;
}
void writeChainPart(struct chain *chain, int tStart, int tEnd, FILE *f,
	FILE *gapFile)
/* Write out part of a chain. */
{
struct chain *subChain, *chainToFree;

chainSubsetOnT(chain, tStart, tEnd, &subChain, &chainToFree);
assert(subChain != NULL);
chainWrite(subChain, f);
if (gapFile != NULL)
    gapWrite(subChain, gapFile);
chainFree(&chainToFree);
}
void chainStitchId(char *inChain, char *outChain)
/* chainStitchId - Join chain fragments with the same chain ID into a single chain per ID. */
{
struct lineFile *lf = lineFileOpen(inChain, TRUE);
struct chain *chain = NULL, *chainList = NULL;
FILE *f = mustOpen(outChain, "w");
int idArrLen = 64 * 1024 * 1024;
struct chain **idArr = needLargeZeroedMem(idArrLen * sizeof(struct chain *));
int i=0;

/* Build up an array of chains, indexed by IDs.  Agglomerate chains with same 
 * ID as we go. */
while ((chain = chainRead(lf)) != NULL)
    {
    while (chain->id >= idArrLen)
	{
	idArr = needMoreMem(idArr, idArrLen, idArrLen*2*sizeof(idArr[0]));
	idArrLen *= 2;
	}
    if (idArr[chain->id] == NULL)
	idArr[chain->id] = chain;
    else
	{
	tackOnFrag(idArr[chain->id], chain);
	chainFree(&chain);
	}
    }
lineFileClose(&lf);

/* Clean up each agglomerated chain and add to head of list (but step 
 * backwards so the resulting list is in order by chain id). */
for (i = idArrLen-1;  i >= 0;  i--)
    {
    chain = idArr[i];
    if (chain != NULL)
	{
	slSort(&(chain->blockList), cBlockCmpTarget);
	slAddHead(&chainList, chain);
	}
    }

/* Ordering by original chain id gets us most of the way to sorting by 
 * score, but not all the way: sort and finally write out the chains. */
slSort(&chainList, chainCmpScore);
for (chain = chainList;  chain != NULL;  chain = chain->next)
    {
    chainWrite(chain, f);
    /* could free here, but program is about to end so why waste the time. */
    }
carefulClose(&f);
}
static struct chromBins* loadMapChains(char *chainFile)
/* read a chain file, convert to mapAln object and chromBins by query locations. */
{
struct chromBins* mapAlns = chromBinsNew((chromBinsFreeFunc*)pslFree);
struct chain *ch;
struct lineFile *chLf = lineFileOpen(chainFile, TRUE);
while ((ch = chainRead(chLf)) != NULL)
    {
    struct mapAln *mapAln = chainToPsl(ch);
    chromBinsAdd(mapAlns, mapAln->psl->qName, mapAln->psl->qStart, mapAln->psl->qEnd, mapAln);
    chainFree(&ch);
    }
lineFileClose(&chLf);
return mapAlns;
}
Exemple #14
0
void addExonToGene(struct chain *chain, struct genePred *gene, struct genePred *synGene, int block)
/** Converte block in genePred to block in orthologous genome for synGene using chain. */
{
struct chain *subChain=NULL, *toFree=NULL;
int qs, qe;
int end = gene->exonEnds[block];
chainSubSetForRegion(chain, gene->exonStarts[block], end , &subChain, &toFree);    
if(subChain == NULL)
    return;
qChainRangePlusStrand(subChain, &qs, &qe);
synGene->exonStarts[synGene->exonCount] = qs; //- synGene->txStart;
synGene->exonEnds[synGene->exonCount] = qe;
synGene->exonCount++;
chainFree(&toFree);
}
Exemple #15
0
void addExonToBedFromBlock(struct chain *chain, struct bed *bed, int blockStart, int blockEnd)
/** Convert block to block in orthologous genome for bed using chain. */
{
struct chain *subChain=NULL, *toFree=NULL;
int qs, qe;
chainSubSetForRegion(chain, blockStart,blockEnd , &subChain, &toFree);    
if(subChain == NULL)
    return;
qChainRangePlusStrand(subChain, &qs, &qe);

bed->chromStarts[bed->blockCount] = qs - bed->chromStart;
bed->blockSizes[bed->blockCount] = abs(qe-qs);
bed->blockCount++;
chainFree(&toFree);
}
Exemple #16
0
struct axt *netFillToAxt(struct cnFill *fill, struct dnaSeq *tChrom , int tSize,
	struct hash *qChromHash, char *nibDir,
	struct chain *chain, boolean swap)
/* Convert subset of chain as defined by fill to axt. swap query and target if swap is true*/
{
struct dnaSeq *qSeq;
boolean isRev = (chain->qStrand == '-');
struct chain *subChain, *chainToFree;
int qOffset;
struct axt *axtList = NULL , *axt;
struct nibInfo *nib = hashFindVal(qChromHash, fill->qName);

/* Get query sequence fragment. */
    {
    if (nib == NULL)
        {
	char path[512];
	AllocVar(nib);
	safef(path, sizeof(path), "%s/%s.nib", nibDir, fill->qName);
	nib->fileName = cloneString(path);
	nibOpenVerify(path, &nib->f, &nib->size);
	hashAdd(qChromHash, fill->qName, nib);
	}
    qSeq = nibLoadPartMasked(NIB_MASK_MIXED, nib->fileName, 
    	fill->qStart, fill->qSize);
    if (isRev)
	{
        reverseComplement(qSeq->dna, qSeq->size);
	qOffset = nib->size - (fill->qStart + fill->qSize);
	}
    else
	qOffset = fill->qStart;
    }
chainSubsetOnT(chain, fill->tStart, fill->tStart + fill->tSize, 
	&subChain, &chainToFree);
if (subChain != NULL)
    {
    axtList = chainToAxt(subChain, qSeq, qOffset, tChrom, fill->tStart, 100, BIGNUM);
    if (swap)
        {
        for (axt = axtList ; axt != NULL ; axt = axt->next)
            axtSwap(axt, tSize, nib->size);
        }
    }
chainFree(&chainToFree);
freeDnaSeq(&qSeq);
return axtList;
}
Exemple #17
0
void chainSubSetForRegion(struct chain *chain, int blockStart, int blockEnd,
			  struct chain **subChain, struct chain **toFree)
/* Call chainSubsetOnT and check to make sure that the change wasn't too great. */
{
int size = 0;
chainSubsetOnT(chain, blockStart, blockEnd, subChain, toFree);
if(*subChain == NULL)
    return;
size = abs((*subChain)->qEnd - (*subChain)->qStart);

/* If difference is too large don't believe it. */
if(abs(size - abs(blockEnd - blockStart)) > maxExonChange) 
    {
    chainFree(toFree);
    *subChain = NULL;
    }
}
Exemple #18
0
struct hash *qSizeHash(char *chainfile)
/* read the chain file and figure out what the chromosome sizes are on the query end */
{
    struct lineFile *lf = lineFileOpen(chainfile, TRUE);
    struct chain *ch;
    struct hash *csizes = hashNew(10);
    while ((ch = chainRead(lf)) != NULL)
    {
	char *chrom = ch->qName;
	int size = ch->qSize;
	if (!hashLookup(csizes, chrom))
	    hashAddInt(csizes, chrom, size);
	chainFree(&ch);
    }
    lineFileClose(&lf);
    return csizes;
}
Exemple #19
0
void chainMergeSort(int fileCount, char *files[], FILE *out, int level)
/* chainMergeSort - Combine sorted files into larger sorted file. */
{
int i;
struct chainFile *cf;
int id = 0;
struct quickHeap *h = NULL;

h = newQuickHeap(fileCount, &cmpChainScores);

/* Open up all input files and read first chain. */
for (i=0; i<fileCount; ++i)
    {
    AllocVar(cf);
    cf->lf = lineFileOpen(files[i], TRUE);
    lineFileSetMetaDataOutput(cf->lf, out);
    cf->chain = chainRead(cf->lf);
    if (cf->chain)
    	addToQuickHeap(h, cf);
    else
	cfEof(&cf,level);  /* deal with EOF */
    }

while (!quickHeapEmpty(h))
    {
    cf = peekQuickHeapTop(h);
    if (!saveId)
	cf->chain->id = ++id;		/* We reset id's here. */
    chainWrite(cf->chain, out);
    chainFree(&cf->chain);
    if ((cf->chain = chainRead(cf->lf)))
	{
	quickHeapTopChanged(h);
	}
    else
	{ /* deal with EOF */
	if (!removeFromQuickHeapByElem(h, cf))
	    errAbort("unexpected error: chainFile not found on heap");
	cfEof(&cf,level);  
	}
    }

freeQuickHeap(&h);

}
void doIt(char *inName, char *tNibDirOr2bit, char *qNibDirOr2bit, char *outName)
/* chainToAxt - Convert from chain to axt file. */
{
struct lineFile *lf = lineFileOpen(inName, TRUE);
struct nibTwoCache *tSeqCache = nibTwoCacheNew(tNibDirOr2bit);
struct nibTwoCache *qSeqCache = nibTwoCacheNew(qNibDirOr2bit);
struct chain *chain = NULL;
FILE *f = mustOpen(outName, "w");

while ((chain = chainRead(lf)) != NULL)
    {
    if (chain->score >= minScore)
        doAChain(chain, tSeqCache, qSeqCache, f);
    chainFree(&chain);
    }
lineFileClose(&lf);
carefulClose(&f);
}
Exemple #21
0
void chainSplit(char *outDir, int inCount, char *inFiles[])
/* chainSplit - Split chains up by target or query sequence. */
{
struct hash *hash = newHash(0);
int inIx;
char tpath[512];
FILE *meta ;
bool metaOpen = TRUE;
makeDir(outDir);
safef(tpath, sizeof(tpath), "%s/meta.tmp", outDir);
meta = mustOpen(tpath,"w");

for (inIx = 0; inIx < inCount; ++inIx)
    {
    struct lineFile *lf = lineFileOpen(inFiles[inIx], TRUE);
    struct chain *chain;
    FILE *f;
    lineFileSetMetaDataOutput(lf, meta);
    while ((chain = chainRead(lf)) != NULL)
        {
	char *name = (splitOnQ ? chain->qName : chain->tName);
	if (lump > 0)
	    name = lumpName(name);
	if ((f = hashFindVal(hash, name)) == NULL)
	    {
	    char path[512], cmd[512];
	    safef(path, sizeof(path),"%s/%s.chain", outDir, name);
            if (metaOpen)
                fclose(meta);
            metaOpen = FALSE;
	    safef(cmd,sizeof(cmd), "cat %s | sort -u > %s", tpath, path);
            mustSystem(cmd);
	    f = mustOpen(path, "a");
	    hashAdd(hash, name, f);
	    }
	chainWrite(chain, f);
	chainFree(&chain);
	}
    lineFileClose(&lf);
    }
}
Exemple #22
0
boolean edgeMap(int start, int end, struct indexedChain *ixc,
	int *retStart, int *retEnd, boolean *retRev,
	boolean *retStartExact, boolean *retEndExact,
	int *retCoverage)
/* Map edge through chain. Return FALSE if no map. */
{
struct chain *subChain = NULL, *toFree = NULL;
indexedChainSubsetOnT(ixc, start, end, &subChain, &toFree);
if (!subChain)
    return FALSE;
*retRev = FALSE;
*retStartExact = *retEndExact = FALSE;
qChainRangePlusStrand(subChain, retStart, retEnd);
if (start == subChain->tStart)
    *retStartExact = TRUE;
if (end == subChain->tEnd)
    *retEndExact = TRUE;
if (subChain->qStrand == '-')
    *retRev = TRUE;
*retCoverage = chainBasesInBlocks(subChain);
chainFree(&toFree);
return TRUE;
}
void chainPreNet(char *inFile, char *targetSizes, char *querySizes, 
	char *outFile)
/* chainPreNet - Remove chains that don't have a chance of being netted. */
{
struct hash *tHash = setupChroms(targetSizes);
struct hash *qHash = setupChroms(querySizes);
struct lineFile *lf = lineFileOpen(inFile, TRUE);
FILE *f = mustOpen(outFile, "w");
struct chain *chain;
double score, lastScore = 9e99;
struct chrom *qChrom, *tChrom;

lineFileSetMetaDataOutput(lf, f);
while ((chain = chainRead(lf)) != NULL)
    {
    /* Report progress. */
    dotOut();

    /* Check to make sure it really is sorted by score. */
    score = chain->score;
    if (score > lastScore)
       {
       errAbort("%s not sorted by score line %d", 
       		lf->fileName, lf->lineIx);
       }
    lastScore = score;

    /* Output chain if necessary and then free it. */
    qChrom = hashMustFindVal(qHash, chain->qName);
    tChrom = hashMustFindVal(tHash, chain->tName);
    if (chainUsed(chain, qChrom, tChrom) && inclQuery(chain))
	{
	chainWrite(chain, f);
	}
    chainFree(&chain);
    }
}
static struct chromAnn* chromAnnChainReaderRead(struct chromAnnReader *car)
/* read a chromAnn object from a tab file or table */
{
struct chromAnnChainReader *carr = car->data;
struct chain *chain = chainRead(carr->lf);
if (chain == NULL)
    return NULL;

struct chromAnn* ca;
if (car->opts & chromAnnUseQSide)
    ca = chromAnnNew(chain->qName, '+', chain->tName,
                     ((car->opts & chromAnnSaveLines) ? chain : NULL),
                     chainRecWrite, chainRecFree);
else
    ca = chromAnnNew(chain->tName, chain->qStrand, chain->qName,
                     ((car->opts & chromAnnSaveLines) ? chain : NULL),
                     chainRecWrite, chainRecFree);

if (car->opts & chromAnnRange)
    {
    if (car->opts & chromAnnUseQSide)
        chromAnnBlkNew(ca, chain->qStart, chain->qEnd);
    else
        chromAnnBlkNew(ca, chain->tStart, chain->tEnd);
    }
else    
    {
    if (car->opts & chromAnnUseQSide)
        addChainQBlocks(ca, car->opts, chain);
    else
        addChainTBlocks(ca, car->opts, chain);
    }
chromAnnFinish(ca);
if (!(car->opts & chromAnnSaveLines))
    chainFree(&chain);
return ca;
}
Exemple #25
0
void fbOrChain(Bits *acc, char *track, char *chrom, int chromSize)
/* Or in a chain file. */
{
struct lineFile *lf;
char fileName[512];
struct chain *chain;
struct cBlock *b;

chromFileName(track, chrom, fileName);
if (!fileExists(fileName))
    return;
lf = lineFileOpen(fileName, TRUE);
while ((chain = chainRead(lf)) != NULL)
    {
    for (b = chain->blockList; b != NULL; b = b->next)
        {
	int s = b->tStart, e = b->tEnd;
	if (s < 0) outOfRange(lf, chrom, chromSize);
	if (e > chromSize) outOfRange(lf, chrom, chromSize);
	bitSetRange(acc, b->tStart, b->tEnd - b->tStart);
	}
    chainFree(&chain);
    }
}
Exemple #26
0
int main(int argc, char *argv[])
{
	FILE *f;
	struct chain *Chain;
	struct chain *SubChain, *chainToFree;
	struct chain *ch_p, *next_p;
	char buf[NUM_CHARS];
	struct lineFile *lf;
	int i = 0;
	int b = 0, e = 0;
	bool is_null = true;
	struct exons_list *homologs;
	int num_chains = 0;
	int num_homologs = 0;
	struct exons_list *repeats;
	int num_repeats = 0;
	char chr[LEN_NAME];

	strcpy(chr, "");
	if( argc == 3 ) {
		if( (f = ckopen(argv[2], "r")) ) {
			if( fgets(buf, NUM_CHARS, f) ) {
				if( sscanf(buf, "%s %d %d", chr, &b, &e) != 3 ) {
					fatalf("format errors: chr beg end in %s", buf);
				}
			}
			else {
				fatalf("%s is empty\n", argv[2]);
			}
		}
		fclose(f);
	}
	else if( argc != 4 ) {
		fatal("args: chain_file interval_text features_gff_file\n");
	}
	else {
		if( (f = ckopen(argv[2], "r")) ) {
			if( fgets(buf, NUM_CHARS, f) ) {
				if( sscanf(buf, "%s %d %d", chr, &b, &e) != 3 ) {
					fatalf("format errors: chr beg end in %s", buf);
				}
			}
			else {
				fatalf("%s is empty\n", argv[2]);
			}
		}
		fclose(f);
		
		if( (f = ckopen(argv[3], "r")) ) {
			while(fgets(buf, NUM_CHARS, f)) {
				i++;
			}
			num_repeats = i;
			repeats = (struct exons_list *) ckalloc(num_repeats * sizeof(struct exons_list));
			init_exons(repeats, 0, num_repeats-1);	
			fseek(f, 0, SEEK_SET);
			assign_gff_exons_chr(f, repeats, num_repeats, chr);
			quick_sort_inc_exons(repeats, 0, num_repeats-1, POS_BASE);
		}
		else {
			fatalf("file %s invalid\n", argv[4]);
		}
		fclose(f);
	}

	lf = lineFileOpen(argv[1], true);
	Chain = chainRead(lf);
	ch_p = Chain;
	while( (ch_p != NULL) && ((next_p = chainRead(lf)) != NULL) ) {
		ch_p->next = next_p;
		ch_p = ch_p->next;
		i++;
	}

//	printf("Number of chains: %d\n", i);
	i = 0;
	ch_p = Chain;
//	while( (i < NUM_LOOPS) && (ch_p != NULL)  ) {
	while( ch_p != NULL  ) {
//		printf("chain %d: %d-%d\n", ch_p->id, ch_p->tStart, ch_p->tEnd);	
		ch_p = ch_p->next;
		i++;
	}

	num_chains = i;
	homologs = (struct exons_list *) ckalloc(num_chains * sizeof(struct exons_list));
	i = 0;
	f = ckopen(argv[2], "r");
	while( fgets(buf, NUM_CHARS, f) ) { 	
		if( sscanf(buf, "%*s %d %d", &b, &e) != 2 ) {
			fatalf("format errors: chr beg end in %s", buf);
		}
		else {
			ch_p = Chain;

			if( ch_p != NULL ) {
				while( (ch_p != NULL) && (is_null == true) ) {
					chainSubsetOnT(ch_p, b, e, &SubChain, &chainToFree);
					if( SubChain != NULL ) is_null = false;
					ch_p = ch_p->next;
				}
			}

			if( is_null == false ) {
				if( (num_repeats == 0 ) || (is_repeats(repeats, num_repeats, SubChain->tName, SubChain->tStart, SubChain->tEnd) == false) ) {
					homologs[i].reg = assign_I(SubChain->qStart, SubChain->qEnd);
					homologs[i].dir = SubChain->qStrand;
					strcpy(homologs[i].chr, SubChain->qName);
					i++;
				}
//				printf("query: %s %d %d\n", SubChain->qName, SubChain->qStart, SubChain->qEnd);
				if( chainToFree != NULL ) {
					chainFree(&chainToFree);
				}

				while( ch_p != NULL ) {
					chainSubsetOnT(ch_p, b, e, &SubChain, &chainToFree);
					ch_p = ch_p->next;
					if( SubChain != NULL ) {
						if( (num_repeats == 0 ) || ( is_repeats(repeats, num_repeats, SubChain->tName, SubChain->tStart, SubChain->tEnd) == false )) {
							if( SubChain->qStrand == '-' ) {
								homologs[i].reg = assign_I(SubChain->qSize - SubChain->qEnd, SubChain->qSize - SubChain->qStart);
							}
							else {
								homologs[i].reg = assign_I(SubChain->qStart, SubChain->qEnd);
							}
							homologs[i].dir = SubChain->qStrand;
							strcpy(homologs[i].chr, SubChain->qName);
							i++;
						}
//						printf("query: %s %d %d\n", SubChain->qName, SubChain->qStart, SubChain->qEnd);
						if( chainToFree != NULL ) {
							chainFree(&chainToFree);
						}
					}
				}
			}
		}
	}

	num_homologs = i;
	selection_sort_exons(homologs, num_homologs);
//	print_exons_list(homologs, num_homologs);
	num_homologs = remove_redundant_intervals(homologs, num_homologs);
	print_exons_list(homologs, num_homologs);
	free(homologs);
	free(repeats);
	chainFreeList(&Chain);

	fclose(f);
	lineFileClose(&lf);

	return EXIT_SUCCESS;
}
Exemple #27
0
struct altGraphX *mapAltGraphX(struct altGraphX *ag, struct sqlConnection *conn,
			       char *db, char *netTable )
/* Map one altGraphX record. Return NULL if can't find. This function
 is getting a bit long but it isn't easy to do...*/
{
struct altGraphX *agNew = NULL;
struct chain *chain = NULL;
struct chain *workingChain = NULL, *workingChainFree = NULL;
struct chain *subChain = NULL, *toFree = NULL;
int i,j,k;
int edgeCountNew =0;
int vCountNew=0;
bool reverse = FALSE;
int *starts = NULL, *sizes = NULL;
int blockCount =0;

/* Find the best chain (one that overlaps the most exons. */
AllocArray(starts, ag->edgeCount);
AllocArray(sizes, ag->edgeCount);
for(i=0; i<ag->edgeCount; i++)
    {
    if(getSpliceEdgeType(ag, i) == ggExon)
	{
	starts[blockCount] = ag->vPositions[ag->edgeStarts[i]];
	sizes[blockCount] = ag->vPositions[ag->edgeEnds[i]] - ag->vPositions[ag->edgeStarts[i]];
	blockCount++;
	}
    }
chain = chainForBlocks(conn, db, netTable, ag->tName, ag->tStart, ag->tEnd,
		       starts, sizes, blockCount);
freez(&starts);
freez(&sizes);

if(chain == NULL)
    return NULL;
/* Make a smaller chain to work on... */
chainSubSetForRegion(chain, ag->tStart-1, ag->tEnd+1, &workingChain, &workingChainFree);
if(workingChain == NULL)
    return NULL;
if (chain->qStrand == '-')
    reverse = TRUE;
agNew = altGraphXClone(ag);
freez(&agNew->tName);
agNew->tName = cloneString(chain->qName);
/* Map vertex positions using chain. */
for(i = 0; i < agNew->vertexCount; i++)
    {
    struct cBlock *bi = NULL;
    int targetPos = agNew->vPositions[i];
    struct chain *subChain=NULL, *toFree=NULL;
    agNew->vPositions[i] = -1;
    chainSubSetForRegion(workingChain, targetPos , targetPos, &subChain, &toFree);    
    if(subChain != NULL)
	{
	int qs, qe;
	qChainRangePlusStrand(subChain, &qs, &qe);
	agNew->vPositions[i] = qs;
	}
    chainFree(&toFree);
    }
/* Prune out edges not found. */

/* Set up to remember how many edges we have and our start and stop. */
edgeCountNew = agNew->edgeCount;
vCountNew = agNew->vertexCount;
agNew->tStart = BIGNUM;
agNew->tEnd = 0;
for(i=0; i<agNew->vertexCount && i>= 0; i++)
    {
    struct evidence *ev = NULL;
    if(agNew->vPositions[i] == -1)
	{
	/* Adjust positions, overwriting one that isn't found. */
	vCountNew--;
	for(j=i; j<agNew->vertexCount-1; j++)
	    {
	    agNew->vPositions[j] = agNew->vPositions[j+1];
	    agNew->vTypes[j] = agNew->vTypes[j+1];
	    }
	/* Remove edges associated with this vertex. */
	for(j=0; j<agNew->edgeCount && j>=0; j++)
	    {
	    if(agNew->edgeStarts[j] == i || agNew->edgeEnds[j] == i)
		{
		edgeCountNew--;
		/* Remove evidence. */
		ev = slElementFromIx(agNew->evidence, j);
		slRemoveEl(&agNew->evidence, ev);
		for(k=j; k<agNew->edgeCount -1; k++)
		    {
		    agNew->edgeStarts[k] = agNew->edgeStarts[k+1];
		    agNew->edgeEnds[k] = agNew->edgeEnds[k+1];
		    agNew->edgeTypes[k] = agNew->edgeTypes[k+1];
		    }
		j--;
		agNew->edgeCount--;
		}
	    }
	/* Subtract off one vertex from all the others. */
	for(j=0; j<agNew->edgeCount; j++)
	    {
	    if(agNew->edgeStarts[j] > i)
		agNew->edgeStarts[j]--; 
	    if(agNew->edgeEnds[j] > i)
		agNew->edgeEnds[j]--; 
	    }
	i--;
	agNew->vertexCount--;
	}
    /* Else if vertex found set agNew start and ends. */
    else
	{
	agNew->tStart = min(agNew->vPositions[i], agNew->tStart);
	agNew->tEnd = max(agNew->vPositions[i], agNew->tEnd);
	}
    }
/* Not going to worry about mRNAs that aren't used anymore. Leave them in
   for now. */
agNew->vertexCount = vCountNew;
agNew->edgeCount = edgeCountNew;
if(agNew->vertexCount == 0 || agNew->edgeCount == 0)
    {
    altGraphXFree(&agNew);
    return NULL;
    }
for(i=0; i<agNew->edgeCount; i++)
    {
    if(agNew->edgeStarts[i] >= agNew->vertexCount ||
       agNew->edgeEnds[i] >= agNew->vertexCount)
	{
	warn("For %s vertexes occur at %d when in reality there are only %d vertices.",
	     agNew->name, max(agNew->edgeStarts[i], agNew->edgeEnds[i]), agNew->vertexCount);
	}
    }
/* If it is on the other strand reverse it. */
if(reverse)
    {
    altGraphXReverse(agNew);
    }
chainFree(&workingChainFree);
return agNew;
}
/* delete akima cache */
void akimaCacheFree(Item *c) {
    chainFree(c, akimaCacheItemFree);
}
Exemple #29
0
/*! 
* \ingroup      WlzBinaryOps
* \brief        Segment a domain into connected parts. Connectivity
 is defined by the connect parameter and can be 4- or 8-connected for
 2D objects and 6-, 18- or 26-connected for 3D objects. Note this
 version requires that there is sufficient space in the objects array
 defined by maxNumObjs and this is not extended. This should be changed
 in future so that the array is extended as required.
*
* \return       Error number.
* \param    obj	input object to be segmented
* \param    mm	number of objects return
* \param    dstArrayObjs	object array return, allocated in the
 procedure.
* \param    maxNumObjs	maximum number of object to return (determines
 the size of the array)
* \param    ignlns	ignore objects with num lines <= ignlns
* \param    connect	connectivity to determine connected regions
* \par      Source:
*                WlzLabel.c
*/
WlzErrorNum WlzLabel(
  WlzObject	*obj,
  int		*mm,
  WlzObject	***dstArrayObjs,
  int		maxNumObjs,
  int		ignlns,
  WlzConnectType connect)
{ 
  WlzIntervalDomain 	*jdp;
  WlzRagRValues 	*jvp;
  WlzIntervalWSpace 	iwsp;
  WlzInterval 		*itvl;
  WlzInterval 		*jtvl;
  WlzLAllocBuf 		*crntal, *altemp;
  WlzLAllocBuf		*al, *crntst, *crlast;
  WlzLAllocBuf		*precal, *precst, *prlast;
  int			nints, mkl;
  int			maxinline,nob,line,ended,lend,chainlistsize;
  WlzLLink		*freechain, *alprec, *alloc, *link1, *link2;
  int			lftcrn, lftprc, rtcrn, rtprec;
  int			jrtcrn, mxkl, jl, jr;
  int			oll, ofl, jjj;
  WlzDomain		domain;
  WlzValues		values;
  int			jdqt;
  WlzErrorNum		errNum=WLZ_ERR_NONE;
  WlzObject		**objlist;

  /* see HISTORY for comments from the FORTRAN version */

  /* now we allocate space for the objects */
  if( (objlist = (WlzObject **)AlcMalloc(sizeof(WlzObject *) * maxNumObjs))
     == NULL ){
    errNum = WLZ_ERR_MEM_ALLOC;
  }
  else {
    *dstArrayObjs = objlist;
  }
  

  /* check object note *mm is always set to zero on error
     return because the "Too many objects" error can return
     nobj valid objects therefore if *mm != 0 there are valid objects
     in objlist which must be freed */
  if( obj == NULL ){
    *mm = 0;
    return WLZ_ERR_OBJECT_NULL;
  }

  /* check types */
  switch( obj->type ){

  case WLZ_2D_DOMAINOBJ:
    if( obj->domain.core == NULL ){
      *mm = 0;
      return WLZ_ERR_DOMAIN_NULL;
    }

    switch( obj->domain.core->type ){

    case WLZ_INTERVALDOMAIN_INTVL:
      break;

    case WLZ_INTERVALDOMAIN_RECT:
      if( (obj->domain.i->lastln - obj->domain.i->line1) < ignlns ){
	*mm = 0;
	return( WLZ_ERR_NONE );
      }

      if( maxNumObjs < 1 ){
	*mm = 0;
	return( WLZ_ERR_INT_DATA );
      }

      objlist[0] = WlzAssignObject(
	WlzMakeMain(obj->type, obj->domain,
		    obj->values, NULL, NULL, &errNum), NULL);
      *mm = 1;
      return WLZ_ERR_NONE;
      
    default:
      *mm = 0;
      return WLZ_ERR_DOMAIN_TYPE;

    }
    break;

  case WLZ_3D_DOMAINOBJ:
    if( obj->domain.core == NULL ){
      *mm = 0;
      return WLZ_ERR_DOMAIN_NULL;
    }

    return WlzLabel3d(obj, mm, objlist, maxNumObjs, ignlns, connect);

  case WLZ_EMPTY_OBJ:
    *mm = 0;
    return WLZ_ERR_NONE;

  case WLZ_TRANS_OBJ:
    /* should be able to do this quite easily */
  default:
    *mm = 0;
    return WLZ_ERR_OBJECT_TYPE;

  }

  /* check connectivity parameter */
  switch( connect ){

  default:
    return WLZ_ERR_INT_DATA;

  case WLZ_8_CONNECTED:
    jdqt = 0;
    break;

  case WLZ_4_CONNECTED:
    jdqt = 1;
    break;

  }
    
  /*
   * Allocate and initialise the working spaces.
   *
   * The chain store size is not easily predictable.
   * Here we use ((twice the number of lines) plus (one third the
   * number of intervals)), very much smaller than the
   * previous allocation, but apparently adequate to
   * segment both metaphase spreads and single connected objects.
   * In any case, this version of label can if necessary allocate
   * more space when the original chain store fills up.
   */
  chainlistsize = mintcount(obj->domain.i, &maxinline) / 3;
  chainlistsize += (1 + obj->domain.i->lastln - obj->domain.i->line1)*2;
  if( (freechain = chainalloc(0,chainlistsize)) == NULL ){
    *mm = 0;
    return WLZ_ERR_MEM_ALLOC;
  }
  buckle(freechain, freechain, chainlistsize);
  /*
   * The allocation list size is determined as twice
   * (1 + maximum number of intervals in a line of input object).
   */
  if( (al = (WlzLAllocBuf *)
       AlcCalloc(2 * (maxinline+1), sizeof(WlzLAllocBuf))) == NULL ){
    chainFree();
    *mm = 0;
    return WLZ_ERR_MEM_ALLOC;
  }
  jvp = obj->values.v;

  /* initialise interval scanning */
  WlzInitRasterScan (obj, &iwsp, WLZ_RASTERDIR_ILIC);
  line = iwsp.linpos;
  ended = 0 ;
  lend = 0 ;
  WlzNextInterval(&iwsp);
  crntst = al + 1 + maxinline;
  nob = 0 ;
  prlast = al ;
  precst = al + 1 ;

  /* commence new line */
  while (!ended) {
    crntal = crntst-1 ;

    line++;
    if (lend) { 
      ended = 1 ;
      lend = 0 ;
    }
    else {
      /* read the intervals into the allocation buffer */
      while (iwsp.linpos <= line) {
	crntal++;
	crntal->a_int.ileft = iwsp.lftpos;
	crntal->a_int.iright = iwsp.rgtpos;
	if (WlzNextInterval(&iwsp) != 0) {
	  lend = 1 ;
	  break ;
	}
      }
    }
    crlast = crntal ;
    crntal = crntst ;
    precal = precst ;
    alloc = NULL ;

    /* test whether last interval in current line dealt with */
    while (crntal <= crlast) {
      lftcrn = crntal->a_int.ileft ;
      jrtcrn = crntal->a_int.iright ;
      rtcrn = jrtcrn+2 ;
      alprec = precal->a_link;
      lftprc = precal->a_int.ileft ;
      rtprec = precal->a_int.iright +2 ;

      /* test whether last interval in preceeding line dealt with */
      if (precal > prlast || rtcrn <= lftprc + jdqt) { 
	/* is interval in current line already allocated */
	if (!alloc) { 
	  /* start a new object and allocate this interval to it */
	  /* interval list */
	  link1 = newchain2(freechain,lftcrn,jrtcrn);
	  /* line-of-intervals list */
	  link2 = newchain1(freechain, (unsigned long) link1);
	  /* "object" -- first line, last line, line-of-intervals pointer */
	  crntal->a_link  = newchain1(freechain,line) ;
	  crntal->a_link = addlink1 (freechain, crntal->a_link, (unsigned long)line);
	  crntal->a_link = addlink1 (freechain, crntal->a_link, (unsigned long) link2);
	}
	/* move on to next interval in current line */
	crntal++ ;
	alloc = NULL;
      }
      else {
	if (rtprec > lftcrn+ (int )jdqt) { 
	  /* case of overlapping intervals: */
	  /* is intvl in current line already allocated ? */
	  if (!alloc) { 
	    /* allocate this interval and add to object list */
	    alloc = alprec ;
	    link1 = alloc->l_link ;
	    crntal->a_link = alloc ;
	    /* test whether this line has already been started for this object */
	    if (link1->l_u.line != line) {
	      /* update last line */
	      link1->l_u.line = line;
	      /* add a link to the line list for this line */
	      link1 = newchain2(freechain,lftcrn,jrtcrn);
	      alloc->l_u.u_link = addlink1 (freechain, alloc->l_u.u_link, (unsigned long) link1);
	    }
	    else {
	      /* add interval to interval list for last line */
	      link1 = alloc->l_u.u_link;
	      link1->l_u.u_link = addlink2 (freechain, link1->l_u.u_link, lftcrn, jrtcrn);
	    }
	  }
	  else {
	    /* merge lists and reallocate intervals */
	    /* test whether both already allocated to same object */
	    if (alprec != alloc) { 
	      merge (&alprec, &alloc, freechain);
	      /* reallocate intervals in preceding line */
	      for (altemp = precst; altemp <= prlast; altemp++)	{
		if (altemp->a_link == alloc) { 
		  altemp->a_link = alprec ;	
		}	
	      }
	      /* reallocate intervals in current line */
	      for (altemp = crntst; altemp <= crntal; altemp++)	{
		if (altemp->a_link == alloc) { 
		  altemp->a_link = alprec ;	
		}	
	      }
	      alloc = alprec ;
	    }
	  }
	  if (rtcrn < rtprec) { 
	    /* move to next interval in this line */
	    crntal++;
	    alloc = NULL ;
	    continue;	/* the outer while loop */
	  }
	}
	/* move on to next interval in preceding line */
	precal++ ;
      }
    }

    /* all intervals in current line dealt with: */
    /* find and construct any finished objects */
    if (precst <= prlast) { 
      for (precal = precst; precal <= prlast; precal++) {
	alprec = precal->a_link ;
	/* has the object to which this interval was allocated been dealt with */
	if (alprec) { 
	  /* remove any later intervals allocated to the same object */
	  for (altemp = precal; altemp <= prlast; altemp++) {
	    if (altemp->a_link == alprec) { 
	      altemp->a_link  = NULL ;	
	    }	
	  }
	  /* test if this object has intervals in the current line */
	  /* and if so skip to end of outer loop */
	  if (crntst <= crlast) { 
	    for (altemp = crntst; altemp <= crlast; altemp++)	{
	      if (altemp->a_link == alprec)
		goto loopend;
	    }
	  }
	  /* construct object - first find line and column bounds */
	  link1 = alprec->l_link;
	  oll = (int) link1->l_u.line;
	  link1 = link1->l_link;
	  ofl = (int) link1->l_u.line;
	  link1 = alprec->l_u.u_link;
	  mkl = 0; /* Just to keep lint happy. */
	  mxkl = 0; /* Just to keep lint happy. */
	  nints = 0;
	  for (jjj=ofl; jjj<=oll; jjj++) {
	    link1 = link1->l_link;
	    link2 = link1->l_u.u_link;
	    do {
	      link2 = link2->l_link;
	      jl = link2->l_u.intv.ileft;
	      jr = link2->l_u.intv.iright;
	      if (nints == 0 || jl < mkl)
		mkl = jl ;	
	      if (nints == 0 || jr > mxkl)
		mxkl = jr ;	
	      nints++;
	      /* test for end of line */
	    } 
	    while (link2 != link1->l_u.u_link);
	  }
	  /* test whether object large enough, if not ignore it */
	  /* test for height or width less than threshold */
	  if (oll-ofl < ignlns || mxkl-mkl < ignlns) {
	    for (jjj = ofl; jjj <= oll; jjj++)	{
	      link1 = link1->l_link;
	      link2 = link1->l_u.u_link;
	      /* recover chain space */
	      join (freechain, link2) ;
	    }
	  }
	  else {

	    /* test for object array overflow */
	    if (nob >= maxNumObjs) {
	      AlcFree((void *) al);
	      chainFree();
	      *mm = nob;
	      return(WLZ_ERR_INT_DATA);
	    }
	    link1 = alprec->l_u.u_link;
	    /* set up domain and object, and update counts
	       need to test successful space allocation here */
	    jdp = WlzMakeIntervalDomain(WLZ_INTERVALDOMAIN_INTVL,
					ofl,oll,mkl,mxkl, &errNum);
	    domain.i = jdp;
	    values.v = jvp;
	    *objlist = WlzAssignObject(
	      WlzMakeMain(WLZ_2D_DOMAINOBJ,
			  domain,values,NULL,obj,&errNum), NULL);
	    objlist++;
	    nob++;
	    /* get the size correct here !!! */
	    itvl = (WlzInterval *) AlcMalloc (nints * sizeof(WlzInterval));
	    jdp->freeptr = AlcFreeStackPush(jdp->freeptr, (void *)itvl, NULL);
	    /* write intervals and interval pointers lists */
	    for (jjj=ofl; jjj<=oll; jjj++) {
	      jtvl = itvl;
	      nints = 0;
	      link1 = link1->l_link;
	      link2 = link1->l_u.u_link;
	      do {
		/*
		 * the following increment since the interval
		 * list is circular, monotone increasing,
		 * but link2 originally points at the
		 * rightmost interval (see comment at top).
		 */
		link2 = link2->l_link;
		itvl->ileft = link2->l_u.intv.ileft - mkl;
		itvl->iright = link2->l_u.intv.iright - mkl;
		itvl++;
		nints++;
		/* test for end of line */
	      } 
	      while (link2 != link1->l_u.u_link);
	      WlzMakeInterval(jjj,jdp,nints,jtvl);
	      join (freechain, link2) ;
	    }
	  }
	  /* return line list etc to free-list store */
	  join (freechain, alprec->l_u.u_link);
	  join (freechain, alprec) ;
	}
      loopend:			 
	;
      }
    }

    /* update pointers - swap the two halves of the allocation list */
    /* before getting the intervals in the next line */
    altemp = crntst ;
    crntst = precst ;
    precst = altemp ;
    prlast = crlast ;
  }

  *mm = nob ;
  AlcFree((void *) al);
  chainFree();

  return WLZ_ERR_NONE;
} 
void liftChain(char *destFile, struct hash *liftHash, 
        int sourceCount, char *sources[], boolean querySide)
/* Lift up coordinates in .chain file. */
{
FILE *f = mustOpen(destFile, "w");
int sourceIx;
int dotMod = dots;

for (sourceIx = 0; sourceIx < sourceCount; ++sourceIx)
    {
    char *source = sources[sourceIx];
    struct lineFile *lf = lineFileOpen(source, TRUE);
    struct chain *chain;
    lineFileSetMetaDataOutput(lf, f);
    verbose(1, "Lifting %s\n", source);
    while ((chain = chainRead(lf)) != NULL)
	{
	struct liftSpec *spec;
	char *seqName = querySide ? chain->qName : chain->tName;
	spec = findLift(liftHash, seqName, lf);
	if (spec == NULL)
	    {
	    if (how != carryMissing)
		{
		chainFree(&chain);
		continue;
		}
	    }
	else
	    {
	    struct cBlock *b = NULL;
	    int offset = spec->offset;
	    if (spec->strand == '-')
		{
		if (querySide)
		    {
		    int qSpan = chain->qEnd - chain->qStart;
		    if (chain->qStrand == '-')
		        chain->qStart += spec->offset;
		    else
		        {
			chain->qStart = spec->newSize - spec->offset 
				- (chain->qSize - chain->qStart);
			}
		    chain->qEnd = chain->qStart + qSpan;
		    chain->qStrand = flipStrand(chain->qStrand);
		    freeMem(chain->qName);
		    chain->qName = cloneString(spec->newName);
		    chain->qSize = spec->newSize;
		    /* We don't need to mess with the blocks here
		     * since they are all relative to the start. */
	            }
		else
		    {
		    /* We try and keep the target strand positive, so we end up
		     * flipping in both target and query and flipping the target
		     * strand. */
		    reverseIntRange(&chain->qStart, &chain->qEnd, chain->qSize);
		    reverseIntRange(&chain->tStart, &chain->tEnd, chain->tSize);
		    chain->qStrand = flipStrand(chain->qStrand);

		    /* Flip around blocks and add offset. */
		    for (b=chain->blockList;  b != NULL;  b=b->next)
			{
			reverseIntRange(&b->qStart, &b->qEnd, chain->qSize);
			reverseIntRange(&b->tStart, &b->tEnd, chain->tSize);
			b->tStart += offset;
			b->tEnd   += offset;
			}
		    slReverse(&chain->blockList);

		    /* On target side add offset as well and update name and size. */
		    chain->tStart += offset;
		    chain->tEnd   += offset;
		    freeMem(chain->tName);
		    chain->tName = cloneString(spec->newName);
		    chain->tSize = spec->newSize;
		    }
		}
	    else
		{
		if (querySide)
		    {
		    if (chain->qStrand == '-')
			offset = spec->newSize - (spec->offset + spec->oldSize);
		    freeMem(chain->qName);
		    chain->qName = cloneString(spec->newName);
		    chain->qSize = spec->newSize;
		    chain->qStart += offset;
		    chain->qEnd   += offset;
		    for (b=chain->blockList;  b != NULL;  b=b->next)
			{
			b->qStart += offset;
			b->qEnd   += offset;
			}
		    }
		else
		    {
		    freeMem(chain->tName);
		    chain->tName = cloneString(spec->newName);
		    chain->tSize = spec->newSize;
		    chain->tStart += offset;
		    chain->tEnd   += offset;
		    for (b=chain->blockList;  b != NULL;  b=b->next)
			{
			b->tStart += offset;
			b->tEnd   += offset;
			}
		    }
		}
	    }
	chainWrite(chain, f);
	chainFree(&chain);
	doDots(&dotMod);
	}
    lineFileClose(&lf);
    if (dots)
        verbose(1, "\n");
    }
}