void testCap_segmentCoordinatesReverseStrand(CuTest* testCase) { /* * Tests the coordinates of an segment and its 5 and 3 prime caps. */ cactusCapTestSetup(); Block *block = block_construct(3, flower); Segment *segment = segment_construct2(block, 2, 0, sequence); Cap *_5Cap = segment_get5Cap(segment); Cap *_3Cap = segment_get3Cap(segment); CuAssertTrue(testCase, cap_getSide(_5Cap)); CuAssertTrue(testCase, !cap_getSide(_3Cap)); CuAssertTrue(testCase, !cap_getStrand(_5Cap)); CuAssertTrue(testCase, !cap_getStrand(_3Cap)); CuAssertIntEquals(testCase, 4, cap_getCoordinate(_5Cap)); CuAssertIntEquals(testCase, 2, cap_getCoordinate(_3Cap)); CuAssertTrue(testCase, !segment_getStrand(segment)); CuAssertIntEquals(testCase, 4, segment_getStart(segment)); CuAssertIntEquals(testCase, 3, segment_getLength(segment)); CuAssertTrue(testCase, !cap_getSide(cap_getReverse(_5Cap))); CuAssertTrue(testCase, cap_getSide(cap_getReverse(_3Cap))); CuAssertTrue(testCase, cap_getStrand(cap_getReverse(_5Cap))); CuAssertTrue(testCase, cap_getStrand(cap_getReverse(_3Cap))); CuAssertIntEquals(testCase, 4, cap_getCoordinate(cap_getReverse(_5Cap))); CuAssertIntEquals(testCase, 2, cap_getCoordinate(cap_getReverse(_3Cap))); CuAssertTrue(testCase, segment_getStrand(segment_getReverse(segment))); CuAssertIntEquals(testCase, 2, segment_getStart(segment_getReverse(segment))); CuAssertIntEquals(testCase, 3, segment_getLength(segment_getReverse(segment))); cactusCapTestTeardown(); }
static void setAdjacencyLength(Cap *cap, Cap *adjacentCap, int64_t adjacencyLength) { //Set the coordinates of the caps to the adjacency size cap_setCoordinates(cap, adjacencyLength, cap_getStrand(cap), NULL); cap_setCoordinates(adjacentCap, adjacencyLength, cap_getStrand(adjacentCap), NULL); assert(cap_getCoordinate(cap) == cap_getCoordinate(adjacentCap)); }
static int64_t traceThreadLength(Cap *cap, Cap **terminatingCap) { /* * Gets the length in bases of the thread in the flower, starting from a given attached stub cap. * The thread length includes the lengths of adjacencies that it contains. * * Terminating cap is initialised with the final cap on the thread from cap. */ assert(end_isStubEnd(cap_getEnd(cap))); int64_t threadLength = 0; while (1) { assert(cap_getCoordinate(cap) != INT64_MAX); int64_t adjacencyLength = cap_getCoordinate(cap); threadLength += adjacencyLength; Cap *adjacentCap = cap_getAdjacency(cap); assert(adjacentCap != NULL); assert(adjacencyLength == cap_getCoordinate(adjacentCap)); //Traverse any block.. if (cap_getSegment(adjacentCap) != NULL) { threadLength += segment_getLength(cap_getSegment(adjacentCap)); cap = cap_getOtherSegmentCap(adjacentCap); assert(cap != NULL); } else { assert(end_isStubEnd(cap_getEnd(adjacentCap))); *terminatingCap = adjacentCap; return threadLength; } } return 1; }
void printPositions(stList *positions, const char *substitutionType, FILE *fileHandle) { for (int64_t i = 0; i < stList_length(positions); i++) { SegmentHolder *segmentHolder = stList_get(positions, i); int64_t j = segment_getStart(segmentHolder->segment); if (segment_getStrand(segmentHolder->segment)) { j += segmentHolder->offset; assert( cap_getCoordinate(segment_get5Cap(segmentHolder->segment)) == segment_getStart( segmentHolder->segment)); assert( segment_getStart(segmentHolder->segment) + segment_getLength(segmentHolder->segment) - 1 == cap_getCoordinate(segment_get3Cap(segmentHolder->segment))); } else { j -= segmentHolder->offset; assert( segment_getStart(segmentHolder->segment) - segment_getLength(segmentHolder->segment) + 1 == cap_getCoordinate(segment_get3Cap(segmentHolder->segment))); } fprintf(fileHandle, "%s: %s_%" PRIi64 " %" PRIi64 " %c %c %c\n", substitutionType, event_getHeader(segment_getEvent(segmentHolder->segment)), sequence_getLength(segment_getSequence(segmentHolder->segment)), j, segmentHolder->base1, segmentHolder->base2, segmentHolder->base3); getMAFBlock(segment_getBlock(segmentHolder->segment), fileHandle); } }
static int64_t setCoordinates(Flower *flower, MetaSequence *metaSequence, Cap *cap, int64_t coordinate) { /* * Sets the coordinates of the reference thread and sets the bases of the actual sequence * that of the consensus. */ Sequence *sequence = flower_getSequence(flower, metaSequence_getName(metaSequence)); if (sequence == NULL) { sequence = sequence_construct(metaSequence, flower); } while (1) { assert(cap_getStrand(cap)); assert(!cap_getSide(cap)); Cap *adjacentCap = cap_getAdjacency(cap); assert(adjacentCap != NULL); assert(cap_getStrand(adjacentCap)); assert(cap_getSide(adjacentCap)); int64_t adjacencyLength = cap_getCoordinate(cap); assert(adjacencyLength == cap_getCoordinate(adjacentCap)); assert(adjacencyLength != INT64_MAX); assert(adjacencyLength >= 0); cap_setCoordinates(cap, coordinate, 1, sequence); coordinate += adjacencyLength + 1; cap_setCoordinates(adjacentCap, coordinate, 1, sequence); //Traverse any block.. if ((cap = cap_getOtherSegmentCap(adjacentCap)) == NULL) { break; } coordinate += segment_getLength(cap_getSegment(adjacentCap)) - 1; } return coordinate; }
void testCap_getCoordinate(CuTest* testCase) { cactusCapTestSetup(); CuAssertTrue(testCase, cap_getCoordinate(rootCap) == INT64_MAX); CuAssertTrue(testCase, cap_getCoordinate(cap_getReverse(rootCap)) == INT64_MAX); CuAssertTrue(testCase, cap_getCoordinate(leaf1Cap) == 4); CuAssertTrue(testCase, cap_getCoordinate(cap_getReverse(leaf1Cap)) == 4); cactusCapTestTeardown(); }
static void setAdjacencyLengthsAndRecoverNewCapsAndBrokenAdjacencies(Cap *cap, stList *recoveredCaps) { /* * Sets the coordinates of the caps to be equal to the length of the adjacency sequence between them. * Used to build the reference sequence bottom up. * * One complexity is that a reference thread between the two caps * in each flower f may be broken into two in the children of f. * Therefore, for each flower f first identify attached stub ends present in the children of f that are * not present in f and copy them into f, reattaching the reference caps as needed. */ while (1) { Cap *adjacentCap = cap_getAdjacency(cap); assert(adjacentCap != NULL); assert(cap_getCoordinate(cap) == INT64_MAX); assert(cap_getCoordinate(adjacentCap) == INT64_MAX); assert(cap_getStrand(cap) == cap_getStrand(adjacentCap)); assert(cap_getSide(cap) != cap_getSide(adjacentCap)); Group *group = end_getGroup(cap_getEnd(cap)); assert(group != NULL); if (!group_isLeaf(group)) { //Adjacency is not terminal, so establish its sequence. Flower *nestedFlower = group_getNestedFlower(group); Cap *nestedCap = flower_getCap(nestedFlower, cap_getName(cap)); assert(nestedCap != NULL); Cap *nestedAdjacentCap = flower_getCap(nestedFlower, cap_getName(adjacentCap)); assert(nestedAdjacentCap != NULL); Cap *breakerCap; int64_t adjacencyLength = traceThreadLength(nestedCap, &breakerCap); assert(cap_getOrientation(nestedAdjacentCap)); if (cap_getPositiveOrientation(breakerCap) != nestedAdjacentCap) { //The thread is broken at the lower level. //Copy cap into higher level graph. breakerCap = copyCapToParent(breakerCap, recoveredCaps); assert(cap_getSide(breakerCap)); cap_makeAdjacent(cap, breakerCap); setAdjacencyLength(cap, breakerCap, adjacencyLength); adjacencyLength = traceThreadLength(nestedAdjacentCap, &breakerCap); assert(cap_getPositiveOrientation(breakerCap) != cap); breakerCap = copyCapToParent(breakerCap, recoveredCaps); assert(!cap_getSide(breakerCap)); cap_makeAdjacent(breakerCap, adjacentCap); setAdjacencyLength(adjacentCap, breakerCap, adjacencyLength); } else { //The thread is not broken at the lower level setAdjacencyLength(cap, adjacentCap, adjacencyLength); } } else { //Set the coordinates of the caps to the adjacency size setAdjacencyLength(cap, adjacentCap, 0); } if ((cap = cap_getOtherSegmentCap(adjacentCap)) == NULL) { break; } } }
bool capsAreAdjacent(Cap *cap1, Cap *cap2, int64_t *separationDistance) { if (cap_getName(cap2) != cap_getName(cap1) && cap_getCoordinate(cap1) != cap_getCoordinate(cap2)) { //This can happen if end1 == end2 if (sequence_getMetaSequence(cap_getSequence(cap1)) == sequence_getMetaSequence(cap_getSequence(cap2))) { assert(strcmp(event_getHeader(cap_getEvent(cap1)), event_getHeader( cap_getEvent(cap2))) == 0); assert(cap_getPositiveOrientation(cap1) != cap_getPositiveOrientation(cap2)); assert(cap_getName(cap1) != cap_getName(cap2)); assert(sequence_getMetaSequence(cap_getSequence(cap1)) == sequence_getMetaSequence(cap_getSequence(cap2))); if (!cap_getStrand(cap1)) { cap1 = cap_getReverse(cap1); } if (!cap_getStrand(cap2)) { cap2 = cap_getReverse(cap2); } assert(cap_getStrand(cap1)); assert(cap_getStrand(cap2)); if (cap_getCoordinate(cap1) < cap_getCoordinate(cap2)) { if (!cap_getSide(cap1) && cap_getSide(cap2)) { *separationDistance = cap_getCoordinate(cap2) - cap_getCoordinate(cap1) - 1; //The minus 1, to give the length of the sequence between the two caps. return 1; } } else { if (cap_getSide(cap1) && !cap_getSide(cap2)) { *separationDistance = cap_getCoordinate(cap1) - cap_getCoordinate(cap2) - 1; return 1; } } } } return 0; }
void testCap_setCoordinate(CuTest* testCase) { cactusCapTestSetup(); CuAssertTrue(testCase, cap_getCoordinate(rootCap) == INT64_MAX); CuAssertTrue(testCase, cap_getStrand(rootCap)); CuAssertTrue(testCase, cap_getSequence(rootCap) == NULL); cap_setCoordinates(rootCap, 5, 0, NULL); CuAssertTrue(testCase, cap_getCoordinate(rootCap) == 5); CuAssertTrue(testCase, !cap_getStrand(rootCap)); CuAssertTrue(testCase, cap_getSequence(rootCap) == NULL); cap_setCoordinates(rootCap, INT64_MAX, 1, NULL); CuAssertTrue(testCase, cap_getCoordinate(rootCap) == INT64_MAX); CuAssertTrue(testCase, cap_getStrand(rootCap)); CuAssertTrue(testCase, cap_getSequence(rootCap) == NULL); cactusCapTestTeardown(); }
void mapBlockToExon(Cap *cap, int level, FILE *fileHandle){ fprintf(fileHandle, "\t\t\t<block>\n"); Block *block = end_getBlock(cap_getEnd(cap)); Chain *chain = block_getChain(block); int start = cap_getCoordinate(cap); int end = cap_getCoordinate(cap_getOtherSegmentCap(cap)) +1; fprintf(fileHandle, "\t\t\t\t<blockName>%s</blockName>\n", cactusMisc_nameToString(block_getName(block))); if(chain != NULL){ fprintf(fileHandle, "\t\t\t\t<chainName>%s</chainName>\n", cactusMisc_nameToString(chain_getName(chain))); }else{ fprintf(fileHandle, "\t\t\t\t<chainName>NA</chainName>\n"); } fprintf(fileHandle, "\t\t\t\t<level>%d</level>\n", level); fprintf(fileHandle, "\t\t\t\t<start>%d</start>\n", start); fprintf(fileHandle, "\t\t\t\t<end>%d</end>\n", end); fprintf(fileHandle, "\t\t\t</block>\n"); st_logInfo("mapBlockToExon: start: %d, end: %d\n", start, end); }
static int addAdjacenciesPP(Cap *cap1, Cap *cap2) { assert(cap_getStrand(cap1) && cap_getStrand(cap2)); Sequence *sequence1 = cap_getSequence(cap1); Sequence *sequence2 = cap_getSequence(cap2); int64_t i = cactusMisc_nameCompare(sequence_getName(sequence1), sequence_getName(sequence2)); if (i == 0) { int64_t j = cap_getCoordinate(cap1); int64_t k = cap_getCoordinate(cap2); i = j > k ? 1 : (j < k ? -1 : 0); if (i == 0) { assert(cap_getSegment(cap1) == cap_getSegment(cap2)); j = cap_getSide(cap1); k = cap_getSide(cap2); assert((j && !k) || (!j && k)); i = j ? -1 : 1; } } return i; }
char *getTerminalAdjacencySubString(Cap *cap) { if(getTerminalAdjacencyLength_ignoreAdjacencies) { return stString_copy(""); } cap = getTerminalCap(cap); cap = cap_getStrand(cap) ? cap : cap_getReverse(cap); //This ensures the asserts are as expected. Cap *adjacentCap = cap_getAdjacency(cap); int64_t i = cap_getCoordinate(cap) - cap_getCoordinate(adjacentCap); assert(i != 0); if (i > 0) { assert(cap_getSide(cap)); assert(!cap_getSide(adjacentCap)); return sequence_getString(cap_getSequence(cap), cap_getCoordinate(adjacentCap) + 1, i - 1, 1); } else { assert(cap_getSide(adjacentCap)); assert(!cap_getSide(cap)); return sequence_getString(cap_getSequence(cap), cap_getCoordinate(cap) + 1, -i - 1, 1); } }
int64_t flower_getTotalBaseLength(Flower *flower) { /* * The implementation of this function is very like that in group_getTotalBaseLength, with a few differences. Consider merging them. */ Flower_EndIterator *endIterator = flower_getEndIterator(flower); End *end; int64_t totalLength = 0; while ((end = flower_getNextEnd(endIterator)) != NULL) { if (!end_isBlockEnd(end)) { End_InstanceIterator *instanceIterator = end_getInstanceIterator(end); Cap *cap; while ((cap = end_getNext(instanceIterator)) != NULL) { cap = cap_getStrand(cap) ? cap : cap_getReverse(cap); if (!cap_getSide(cap) && cap_getSequence(cap) != NULL) { Cap *cap2 = cap_getAdjacency(cap); assert(cap2 != NULL); while (end_isBlockEnd(cap_getEnd(cap2))) { Segment *segment = cap_getSegment(cap2); assert(segment != NULL); assert(segment_get5Cap(segment) == cap2); cap2 = cap_getAdjacency(segment_get3Cap(segment)); assert(cap2 != NULL); assert(cap_getStrand(cap2)); assert(cap_getSide(cap2)); } assert(cap_getStrand(cap2)); assert(cap_getSide(cap2)); int64_t length = cap_getCoordinate(cap2) - cap_getCoordinate(cap) - 1; assert(length >= 0); totalLength += length; } } end_destructInstanceIterator(instanceIterator); } } flower_destructEndIterator(endIterator); return totalLength; }
static stList *getSubstringsForFlowers(stList *flowers) { /* * Get the set of substrings for sequence intervals in the given set of flowers. */ stList *substrings = stList_construct3(0, (void (*)(void *)) substring_destruct); for (int64_t i = 0; i < stList_length(flowers); i++) { Flower *flower = stList_get(flowers, i); Flower_EndIterator *endIt = flower_getEndIterator(flower); End *end; while ((end = flower_getNextEnd(endIt)) != NULL) { if (end_isStubEnd(end)) { End_InstanceIterator *instanceIt = end_getInstanceIterator(end); Cap *cap; while ((cap = end_getNext(instanceIt)) != NULL) { Sequence *sequence; if ((sequence = cap_getSequence(cap)) != NULL) { cap = cap_getStrand(cap) ? cap : cap_getReverse(cap); if (!cap_getSide(cap)) { //We have a sequence interval of interest Cap *adjacentCap = cap_getAdjacency(cap); assert(adjacentCap != NULL); int64_t length = cap_getCoordinate(adjacentCap) - cap_getCoordinate(cap) - 1; assert(length >= 0); if (length > 0) { stList_append(substrings, substring_construct(sequence_getMetaSequence(sequence)->stringName, cap_getCoordinate(cap) + 1 - sequence_getStart(sequence), length)); } } } } end_destructInstanceIterator(instanceIt); } } flower_destructEndIterator(endIt); } return substrings; }
void topDown(Flower *flower, Name referenceEventName) { /* * Run on each flower, top down. Sets the coordinates of each reference cap to the correct * sequence, and sets the bases of the reference sequence to be consensus bases. */ Flower_EndIterator *endIt = flower_getEndIterator(flower); End *end; while ((end = flower_getNextEnd(endIt)) != NULL) { Cap *cap = getCapForReferenceEvent(end, referenceEventName); //The cap in the reference if (cap != NULL) { cap = cap_getStrand(cap) ? cap : cap_getReverse(cap); if (!cap_getSide(cap)) { assert(cap_getCoordinate(cap) != INT64_MAX); Sequence *sequence = cap_getSequence(cap); assert(sequence != NULL); Group *group = end_getGroup(end); if (!group_isLeaf(group)) { Flower *nestedFlower = group_getNestedFlower(group); Cap *nestedCap = flower_getCap(nestedFlower, cap_getName(cap)); assert(nestedCap != NULL); nestedCap = cap_getStrand(nestedCap) ? nestedCap : cap_getReverse(nestedCap); assert(cap_getStrand(nestedCap)); assert(!cap_getSide(nestedCap)); int64_t endCoordinate = setCoordinates(nestedFlower, sequence_getMetaSequence(sequence), nestedCap, cap_getCoordinate(cap)); (void) endCoordinate; assert(endCoordinate == cap_getCoordinate(cap_getAdjacency(cap))); assert(endCoordinate == cap_getCoordinate( flower_getCap(nestedFlower, cap_getName(cap_getAdjacency(cap))))); } } } } flower_destructEndIterator(endIt); }
int main(int argc, char *argv[]) { st_setLogLevelFromString(argv[1]); st_logDebug("Set up logging\n"); stKVDatabaseConf *kvDatabaseConf = stKVDatabaseConf_constructFromString(argv[2]); CactusDisk *cactusDisk = cactusDisk_construct(kvDatabaseConf, 0); stKVDatabaseConf_destruct(kvDatabaseConf); st_logDebug("Set up the flower disk\n"); Name flowerName = cactusMisc_stringToName(argv[3]); Flower *flower = cactusDisk_getFlower(cactusDisk, flowerName); int64_t totalBases = flower_getTotalBaseLength(flower); int64_t totalEnds = flower_getEndNumber(flower); int64_t totalFreeEnds = flower_getFreeStubEndNumber(flower); int64_t totalAttachedEnds = flower_getAttachedStubEndNumber(flower); int64_t totalCaps = flower_getCapNumber(flower); int64_t totalBlocks = flower_getBlockNumber(flower); int64_t totalGroups = flower_getGroupNumber(flower); int64_t totalChains = flower_getChainNumber(flower); int64_t totalLinkGroups = 0; int64_t maxEndDegree = 0; int64_t maxAdjacencyLength = 0; int64_t totalEdges = 0; Flower_EndIterator *endIt = flower_getEndIterator(flower); End *end; while((end = flower_getNextEnd(endIt)) != NULL) { assert(end_getOrientation(end)); if(end_getInstanceNumber(end) > maxEndDegree) { maxEndDegree = end_getInstanceNumber(end); } stSortedSet *ends = stSortedSet_construct(); End_InstanceIterator *capIt = end_getInstanceIterator(end); Cap *cap; while((cap = end_getNext(capIt)) != NULL) { if(cap_getSequence(cap) != NULL) { Cap *adjacentCap = cap_getAdjacency(cap); assert(adjacentCap != NULL); End *adjacentEnd = end_getPositiveOrientation(cap_getEnd(adjacentCap)); stSortedSet_insert(ends, adjacentEnd); int64_t adjacencyLength = cap_getCoordinate(cap) - cap_getCoordinate(adjacentCap); if(adjacencyLength < 0) { adjacencyLength *= -1; } assert(adjacencyLength >= 1); if(adjacencyLength >= maxAdjacencyLength) { maxAdjacencyLength = adjacencyLength; } } } end_destructInstanceIterator(capIt); totalEdges += stSortedSet_size(ends); if(stSortedSet_search(ends, end) != NULL) { //This ensures we count self edges twice, so that the division works. totalEdges += 1; } stSortedSet_destruct(ends); } assert(totalEdges % 2 == 0); flower_destructEndIterator(endIt); Flower_GroupIterator *groupIt = flower_getGroupIterator(flower); Group *group; while((group = flower_getNextGroup(groupIt)) != NULL) { if(group_getLink(group) != NULL) { totalLinkGroups++; } } flower_destructGroupIterator(groupIt); printf("flower name: %" PRIi64 " total bases: %" PRIi64 " total-ends: %" PRIi64 " total-caps: %" PRIi64 " max-end-degree: %" PRIi64 " max-adjacency-length: %" PRIi64 " total-blocks: %" PRIi64 " total-groups: %" PRIi64 " total-edges: %" PRIi64 " total-free-ends: %" PRIi64 " total-attached-ends: %" PRIi64 " total-chains: %" PRIi64 " total-link groups: %" PRIi64 "\n", flower_getName(flower), totalBases, totalEnds, totalCaps, maxEndDegree, maxAdjacencyLength, totalBlocks, totalGroups, totalEdges/2, totalFreeEnds, totalAttachedEnds, totalChains, totalLinkGroups); return 0; }
int mapGene(Cap *cap, int level, int exon, struct bed *gene, FILE *fileHandle){ /* *Following cactus adjacencies, starting from 'cap', find regions that overlap with *exons of input gene. Report chain relations of these regions with the exons. *cap: current cap. Level = chain level. exon = exon number. gene = bed record of gene */ int64_t exonStart, exonEnd; if(isStubCap(cap)){ Group *group = end_getGroup(cap_getEnd(cap)); Flower *nestedFlower = group_getNestedFlower(group); if(nestedFlower != NULL){//recursive call Cap *childCap = flower_getCap(nestedFlower, cap_getName(cap)); assert(childCap != NULL); exon = mapGene(childCap, level + 1, exon, gene, fileHandle); exonStart = gene->chromStarts->list[exon] + gene->chromStart; exonEnd = exonStart + gene->blockSizes->list[exon]; } } cap = cap_getAdjacency(cap); Cap *nextcap; int64_t capCoor; exonStart = gene->chromStarts->list[exon] + gene->chromStart; exonEnd = exonStart + gene->blockSizes->list[exon]; Block *block = end_getBlock(cap_getEnd(cap)); if(block == NULL){ moveCapToNextBlock(&cap); } while(!isStubCap(cap) && exon < gene->blockCount){ End *cend = cap_getEnd(cap); capCoor = cap_getCoordinate(cap);//Cap coordinate is always the coordinate on + strand nextcap = cap_getAdjacency(cap_getOtherSegmentCap(cap)); st_logInfo("capCoor: %d, nextCap: %d, eStart: %d, eEnd: %d. Exon: %d\n", capCoor, cap_getCoordinate(nextcap), exonStart, exonEnd, exon); //keep moving if nextBlock Start is still upstream of current exon if(cap_getCoordinate(nextcap) <= exonStart){ moveCapToNextBlock(&cap); st_logInfo("Still upstream, nextcap <= exonStart. Move to next chainBlock\n"); }else if(capCoor >= exonEnd){//Done with current exon, move to next st_logInfo("Done with current exon, move to next one\n\n"); fprintf(fileHandle, "\t\t</exon>\n");//end previous exon exon++; if(exon < gene->blockCount){ exonStart = gene->chromStarts->list[exon] + gene->chromStart; exonEnd = exonStart + gene->blockSizes->list[exon]; fprintf(fileHandle, "\t\t<exon id=\"%d\" start=\"%" PRIi64 "\" end=\"%" PRIi64 "\">\n", exon, exonStart, exonEnd); } }else{//current exon overlaps with current block Or with lower level flower Cap *oppcap = cap_getOtherSegmentCap(cap); st_logInfo("Current exon overlaps with current block or with lower flower\n"); if(cap_getCoordinate(oppcap) >= exonStart && exonEnd > capCoor){ mapBlockToExon(cap, level, fileHandle); if(exonEnd <= cap_getCoordinate(oppcap) + 1){ st_logInfo("Done with current exon, move to next one\n\n"); fprintf(fileHandle, "\t\t</exon>\n");//end previous exon exon++; if(exon < gene->blockCount){ exonStart = gene->chromStarts->list[exon] + gene->chromStart; exonEnd = exonStart + gene->blockSizes->list[exon]; fprintf(fileHandle, "\t\t<exon id=\"%d\" start=\"%" PRIi64 "\" end=\"%" PRIi64 "\">\n", exon, exonStart, exonEnd); } continue; } } //Traverse lower level flowers if exists Group *group = end_getGroup(end_getOtherBlockEnd(cend)); Flower *nestedFlower = group_getNestedFlower(group); if(nestedFlower != NULL){//recursive call Cap *childCap = flower_getCap(nestedFlower, cap_getName(cap_getOtherSegmentCap(cap))); assert(childCap != NULL); exon = mapGene(childCap, level + 1, exon, gene, fileHandle); exonStart = gene->chromStarts->list[exon] + gene->chromStart; exonEnd = exonStart + gene->blockSizes->list[exon]; } moveCapToNextBlock(&cap); } } return exon; }