GtNodeVisitor* gt_snp_annotator_visitor_new(GtFeatureNode *gene, GtTransTable *trans_table, GtRegionMapping *rmap, GtError *err) { GtNodeVisitor *nv; GtSNPAnnotatorVisitor *sav; gt_assert(gene && gt_feature_node_get_type(gene) == gt_symbol(gt_ft_gene)); nv = gt_node_visitor_create(gt_snp_annotator_visitor_class()); sav = snp_annotator_visitor_cast(nv); sav->gene = (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) gene); sav->rmap = gt_region_mapping_ref(rmap); sav->mRNA_type = gt_symbol(gt_ft_mRNA); sav->CDS_type = gt_symbol(gt_ft_CDS); sav->SNV_type = gt_symbol(gt_ft_SNV); sav->SNP_type = gt_symbol(gt_ft_SNP); sav->rnaseqs = gt_hashmap_new(GT_HASH_DIRECT, NULL, gt_free_func); if (trans_table) { sav->tt = trans_table; sav->own_tt = false; } else { sav->tt = gt_trans_table_new_standard(err); sav->own_tt = true; } if (!sav->tt || gt_snp_annotator_visitor_prepare_gene(sav, err) != 0) { gt_node_visitor_delete(nv); return NULL; } return nv; }
GtBlock* gt_block_clone(GtBlock *block) { GtBlock* newblock; GtUword i; gt_assert(block); newblock = gt_block_new(); for (i=0;i<gt_array_size(block->elements);i++) { GtElement *elem; elem = gt_element_ref(*(GtElement**) gt_array_get(block->elements, i)); gt_assert(elem); gt_array_add(newblock->elements, elem); } gt_assert(gt_block_get_size(newblock) == gt_block_get_size(block)); newblock->caption = gt_str_ref(block->caption); newblock->type = block->type; newblock->range.start = block->range.start; newblock->range.end = block->range.end; newblock->show_caption = block->show_caption; newblock->strand = block->strand; newblock->top_level_feature = (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) block->top_level_feature); return newblock; }
void gt_feature_info_add(GtFeatureInfo *fi, const char *id, GtFeatureNode *fn) { gt_assert(fi && id && fn); gt_assert(!gt_feature_node_is_pseudo((GtFeatureNode*) fn)); gt_hashmap_add(fi->id_to_genome_node, gt_cstr_dup(id), gt_genome_node_ref((GtGenomeNode*) fn)); }
static int lua_custom_visitor_visit_node_generic(GT_UNUSED GtNodeVisitor *nv, GtGenomeNode *fn, const char *function, GtError *err) { GT_UNUSED GtNodeVisitor **vis; GtLuaCustomVisitor *lcv; GT_UNUSED GtGenomeNode **node; int had_err = 0; gt_assert(nv); lcv = lua_custom_visitor_cast(nv); node = check_genome_node(lcv->L, 1); vis = check_genome_visitor(lcv->L, 2); gt_assert(*node == (GtGenomeNode*) fn); gt_assert(*vis == (GtNodeVisitor*) nv); lua_pushvalue(lcv->L, 2); lua_pushstring(lcv->L, function); lua_gettable(lcv->L, 2); if (lua_isnil(lcv->L, -1)) { lua_pop(lcv->L, 1); return had_err; } lua_pushvalue(lcv->L, 2); gt_lua_genome_node_push(lcv->L, gt_genome_node_ref((GtGenomeNode*) fn)); if (lua_pcall(lcv->L, 2, 0, 0)) { const char *error = lua_tostring(lcv->L, -1); gt_error_set(err, "%s", error); had_err = -1; } return had_err; }
void gt_feature_info_add_pseudo_parent(GtFeatureInfo *fi, const char *id, GtFeatureNode *pseudo_parent) { gt_assert(fi && id && pseudo_parent); gt_assert(gt_feature_node_is_pseudo((GtFeatureNode*) pseudo_parent)); gt_hashmap_add(fi->id_to_pseudo_parent, gt_cstr_dup(id), gt_genome_node_ref((GtGenomeNode*) pseudo_parent)); }
static GtFeatureNodeIterator* feature_node_iterator_new_base(const GtFeatureNode *fn) { GtFeatureNodeIterator *fni; gt_assert(fn); fni = gt_malloc(sizeof *fni); fni->fn = (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) fn); fni->feature_stack = gt_array_new(sizeof (GtFeatureNode*)); return fni; }
static int filter_stream_next(GtNodeStream *ns, GtGenomeNode **gn, GtError *error) { AgnFilterStream *stream; GtFeatureNode *fn; int had_err; gt_error_check(error); stream = filter_stream_cast(ns); if(gt_queue_size(stream->cache) > 0) { *gn = gt_queue_get(stream->cache); return 0; } while(1) { had_err = gt_node_stream_next(stream->in_stream, gn, error); if(had_err) return had_err; if(!*gn) return 0; fn = gt_feature_node_try_cast(*gn); if(!fn) return 0; GtFeatureNode *current; GtFeatureNodeIterator *iter = gt_feature_node_iterator_new(fn); for(current = gt_feature_node_iterator_next(iter); current != NULL; current = gt_feature_node_iterator_next(iter)) { const char *type = gt_feature_node_get_type(current); bool keepfeature = false; if(gt_hashmap_get(stream->typestokeep, type) != NULL) keepfeature = true; if(keepfeature) { gt_genome_node_ref((GtGenomeNode *)current); gt_queue_add(stream->cache, current); } } gt_feature_node_iterator_delete(iter); gt_genome_node_delete((GtGenomeNode *)fn); if(gt_queue_size(stream->cache) > 0) { *gn = gt_queue_get(stream->cache); return 0; } } return 0; }
static int gt_ltr_cluster_stream_next(GtNodeStream *ns, GtGenomeNode **gn, GtError *err) { GtLTRClusterStream *lcs; GtGenomeNode *ref_gn; int had_err = 0; unsigned long i = 0; gt_error_check(err); lcs = gt_ltr_cluster_stream_cast(ns); if (lcs->first_next) { while (!(had_err = gt_node_stream_next(lcs->in_stream, gn, err)) && *gn) { gt_assert(*gn && !had_err); ref_gn = gt_genome_node_ref(*gn); gt_array_add(lcs->nodes, ref_gn); had_err = gt_genome_node_accept(*gn, (GtNodeVisitor*) lcs->lcv, err); if (had_err) { gt_genome_node_delete(*gn); *gn = NULL; break; } } lcs->feat_to_encseq = gt_ltr_cluster_prepare_seq_visitor_get_encseqs(lcs->lcv); lcs->feat_to_encseq_keys = gt_ltr_cluster_prepare_seq_visitor_get_features(lcs->lcv); if (!had_err) { for (i = 0; i < gt_str_array_size(lcs->feat_to_encseq_keys); i++) { had_err = process_feature(lcs, gt_str_array_get(lcs->feat_to_encseq_keys, i), err); if (had_err) break; } } if (!had_err) { *gn = *(GtGenomeNode**) gt_array_get(lcs->nodes, lcs->next_index); lcs->next_index++; lcs->first_next = false; return 0; } } else { if (lcs->next_index >= gt_array_size(lcs->nodes)) *gn = NULL; else { *gn = *(GtGenomeNode**) gt_array_get(lcs->nodes, lcs->next_index); lcs->next_index++; } return 0; } return had_err; }
static int feature_node_iterator_lua_next(lua_State *L) { GtFeatureNodeIterator **fni; GtFeatureNode *fn; fni = check_gt_feature_node_iterator(L, 1); fn = gt_feature_node_iterator_next(*fni); if (fn) gt_lua_genome_node_push(L, gt_genome_node_ref((GtGenomeNode*) fn)); else lua_pushnil(L); return 1; }
GtRecMap* gt_rec_map_new(double nw_x, double nw_y, double se_x, double se_y, GtFeatureNode *node) { GtRecMap *rm = gt_calloc(1, sizeof (GtRecMap)); rm->nw_x = nw_x; rm->nw_y = nw_y; rm->se_x = se_x; rm->se_y = se_y; rm->fn = (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) node); rm->has_omitted_children = false; return rm; }
GtBlock* gt_block_new_from_node(GtFeatureNode *node) { GtBlock *block; gt_assert(node); block = gt_block_new(); block->range = gt_genome_node_get_range((GtGenomeNode*) node); block->strand = gt_feature_node_get_strand(node); block->type = gt_feature_node_get_type(node); if (!gt_feature_node_is_pseudo(node)) { block->top_level_feature = (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) node); } return block; }
static int genome_node_lua_add_child(lua_State *L) { GtGenomeNode **parent, **child; GtFeatureNode *pf, *cf; parent = check_genome_node(L, 1); child = check_genome_node(L, 2); pf = gt_feature_node_try_cast(*parent); luaL_argcheck(L, pf, 1, "not a feature node"); cf = gt_feature_node_try_cast(*child); luaL_argcheck(L, cf, 2, "not a feature node"); gt_feature_node_add_child(pf, (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) cf)); return 0; }
void gt_block_insert_element(GtBlock *block, GtFeatureNode *node) { GtElement *element; gt_assert(block && node); if (!block->top_level_feature) { block->top_level_feature = (GtFeatureNode*) gt_genome_node_ref((GtGenomeNode*) node); } element = gt_element_new(node); /* invalidate sortedness flag because insertion of element at the end may break ordering */ block->sorted = false; gt_array_add(block->elements, element); }
int gt_script_filter_run(GtScriptFilter *sf, GtFeatureNode *gf, bool *select_node, GtError *err) { int had_err = 0; #ifndef NDEBUG int stack_size; #endif GtGenomeNode *gn_lua; #ifndef NDEBUG stack_size = lua_gettop(sf->L); #endif if (!had_err) { lua_getglobal(sf->L, "filter"); if (lua_isnil(sf->L, -1)) { gt_error_set(err, "function 'filter' is not defined"); had_err = -1; lua_pop(sf->L, 1); } } if (!had_err) { gn_lua = gt_genome_node_ref((GtGenomeNode*) gf); gt_lua_genome_node_push(sf->L, gn_lua); if (lua_pcall(sf->L, 1, 1, 0) != 0) { gt_error_set(err, "error running function 'filter': %s", lua_tostring(sf->L, -1)); lua_pop(sf->L, 1); had_err = -1; } } if (!had_err && !lua_isboolean(sf->L, -1)) { gt_error_set(err, "function 'filter' must return boolean"); lua_pop(sf->L, 1); had_err = -1; } if (!had_err) { *select_node = lua_toboolean(sf->L, -1); lua_pop(sf->L, 1); } gt_assert(lua_gettop(sf->L) == stack_size); return had_err; }
static void push_features_as_table(lua_State *L, GtArray *features) { unsigned long i; if (features && gt_array_size(features)) { /* push table containing feature references onto the stack */ lua_newtable(L); for (i = 0; i < gt_array_size(features); i++) { lua_pushinteger(L, i+1); /* in Lua we index from 1 on */ gt_lua_genome_node_push(L, gt_genome_node_ref(*(GtGenomeNode**) gt_array_get(features, i))); lua_rawset(L, -3); } } else lua_pushnil(L); }
static int buffer_stream_next(GtNodeStream *ns, GtGenomeNode **gn, GtError *err) { GtBufferStream *bs; gt_error_check(err); bs = buffer_stream_cast(ns); if (bs->buffering) { int had_err = gt_node_stream_next(bs->in_stream, gn, err); if (!had_err && *gn) gt_queue_add(bs->node_buffer, gt_genome_node_ref(*gn)); return had_err; } else { *gn = gt_queue_size(bs->node_buffer) ? gt_queue_get(bs->node_buffer) : NULL; return 0; } }
static int lua_custom_stream_next(GtNodeStream *ns, GtGenomeNode **gn, GtError *err) { GT_UNUSED GtNodeStream **s; GtGenomeNode **retnode; GtLuaCustomStream *lcs; int had_err = 0; gt_assert(ns); gt_error_check(err); lcs = lua_custom_stream_cast(ns); /* push correct Lua object for this stream */ lua_rawgeti(lcs->L, LUA_REGISTRYINDEX, lcs->ref); s = check_genome_stream(lcs->L, -1); /* get overridden next_tree method */ lua_pushstring(lcs->L, "next_tree"); lua_gettable(lcs->L, -2); /* make sure there is one */ gt_assert(!lua_isnil(lcs->L, -1)); lua_pushvalue(lcs->L, -2); if (lua_pcall(lcs->L, 1, 1, 0)) { const char *error = lua_tostring(lcs->L, -1); gt_error_set(err, "%s", error); had_err = -1; } if (!had_err) { if (lua_isnil(lcs->L, -1)) { *gn = NULL; } else { retnode = gt_lua_try_checkudata(lcs->L, -1, GENOME_NODE_METATABLE); if (!retnode) { const char *type; type = lua_tostring(lcs->L, -1); gt_error_set(err, "custom 'next_tree' method must return a genome " "node or nil, was %s", type); had_err = -1; } else { *gn = gt_genome_node_ref(*retnode); } } } return had_err; }
static int feature_in_stream_next(GtNodeStream *ns, GtGenomeNode **gn, GtError *error) { GtFeatureInStream *stream = feature_in_stream_cast(ns); gt_error_check(error); if (!stream->init) { feature_in_stream_init(stream); stream->init = true; } if (gt_queue_size(stream->regioncache) > 0) { GtGenomeNode *region = gt_queue_get(stream->regioncache); *gn = region; return 0; } if (stream->featurecache == NULL || gt_array_size(stream->featurecache) == 0) { if (stream->featurecache != NULL) { gt_array_delete(stream->featurecache); stream->featurecache = NULL; } if (stream->seqindex == gt_str_array_size(stream->seqids)) { *gn = NULL; return 0; } const char *seqid = gt_str_array_get(stream->seqids, stream->seqindex++); stream->featurecache = gt_feature_index_get_features_for_seqid(stream->fi, seqid, error); gt_array_sort(stream->featurecache, (GtCompare)gt_genome_node_compare); gt_array_reverse(stream->featurecache); } GtGenomeNode *feat = *(GtGenomeNode **)gt_array_pop(stream->featurecache); *gn = gt_genome_node_ref(feat); return 0; }
static int gt_array_out_stream_next(GtNodeStream *gs, GtGenomeNode **gn, GtError *err) { GtArrayOutStream *aos; GtGenomeNode *node, *gn_ref; int had_err = 0; gt_error_check(err); aos = gt_array_out_stream_cast(gs); had_err = gt_node_stream_next(aos->in_stream, gn, err); if (!had_err && *gn) { if ((node = gt_feature_node_try_cast(*gn))) { gn_ref = gt_genome_node_ref(*gn); gt_array_add(aos->nodes, gn_ref); } } return had_err; }
static void push_recmap_as_table(lua_State *L, const GtRecMap *rm) { gt_assert(rm); lua_newtable(L); lua_pushstring(L, "nw_x"); lua_pushnumber(L, gt_rec_map_get_northwest_x(rm)); lua_rawset(L, -3); lua_pushstring(L, "nw_y"); lua_pushnumber(L, gt_rec_map_get_northwest_y(rm)); lua_rawset(L, -3); lua_pushstring(L, "se_x"); lua_pushnumber(L, gt_rec_map_get_southeast_x(rm)); lua_rawset(L, -3); lua_pushstring(L, "se_y"); lua_pushnumber(L, gt_rec_map_get_southeast_y(rm)); lua_rawset(L, -3); lua_pushstring(L, "feature_ref"); gt_lua_genome_node_push(L, gt_genome_node_ref((GtGenomeNode*) gt_rec_map_get_genome_feature(rm))); lua_rawset(L, -3); }
static int feature_node_lua_get_exons(lua_State *L) { GtGenomeNode **gn = check_genome_node(L, 1); GtArray *exons = gt_array_new(sizeof (GtGenomeNode*)); GtUword i = 0; GtFeatureNode *fn; /* make sure we get a feature node */ fn = gt_feature_node_try_cast(*gn); luaL_argcheck(L, fn, 1, "not a feature node"); gt_feature_node_get_exons(fn, exons); lua_newtable(L); for (i = 0; i < gt_array_size(exons); i++) { lua_pushnumber(L, i+1); gt_lua_genome_node_push(L, (GtGenomeNode*) gt_genome_node_ref(*(GtGenomeNode**) gt_array_get(exons, i))); lua_rawset(L, -3); } gt_array_delete(exons); return 1; }
static int snp_annotator_stream_next(GtNodeStream *ns, GtGenomeNode **gn, GtError *err) { GtSNPAnnotatorStream *sas; int had_err = 0; bool complete_cluster = false; GtGenomeNode *mygn = NULL; GtFeatureNode *fn = NULL; const char *snv_type = gt_symbol(gt_ft_SNV), *snp_type = gt_symbol(gt_ft_SNP), *gene_type = gt_symbol(gt_ft_gene); gt_error_check(err); sas = gt_snp_annotator_stream_cast(ns); /* if there are still SNPs left in the buffer, output them */ if (gt_queue_size(sas->outqueue) > 0) { *gn = (GtGenomeNode*) gt_queue_get(sas->outqueue); return had_err; } else complete_cluster = false; while (!had_err && !complete_cluster) { had_err = gt_node_stream_next(sas->merge_stream, &mygn, err); /* stop if stream is at the end */ if (had_err || !mygn) break; /* process all feature nodes */ if ((fn = gt_feature_node_try_cast(mygn))) { GtGenomeNode *addgn; const char *type = gt_feature_node_get_type(fn); GtRange new_rng = gt_genome_node_get_range(mygn); if (type == snv_type || type == snp_type) { /* -----> this is a SNP <----- */ if (gt_range_overlap(&new_rng, &sas->cur_gene_range)) { /* it falls into the currently observed range */ gt_queue_add(sas->snps, gt_genome_node_ref((GtGenomeNode*) fn)); } else { /* SNP outside a gene, this cluster is done add to out queue and start serving */ gt_assert(gt_queue_size(sas->outqueue) == 0); had_err = snp_annotator_stream_process_current_gene(sas, err); gt_queue_add(sas->outqueue, mygn); if (gt_queue_size(sas->outqueue) > 0) { *gn = (GtGenomeNode*) gt_queue_get(sas->outqueue); complete_cluster = true; } } } else if (type == gene_type) { /* -----> this is a gene <----- */ if (gt_array_size(sas->cur_gene_set) == 0UL) { /* new overlapping gene cluster */ addgn = gt_genome_node_ref(mygn); gt_array_add(sas->cur_gene_set, addgn); sas->cur_gene_range = gt_genome_node_get_range(mygn); } else { if (gt_range_overlap(&new_rng, &sas->cur_gene_range)) { /* gene overlaps with current one, add to cluster */ addgn = gt_genome_node_ref(mygn); gt_array_add(sas->cur_gene_set, addgn); sas->cur_gene_range = gt_range_join(&sas->cur_gene_range, &new_rng); } else { /* finish current cluster and start a new one */ had_err = snp_annotator_stream_process_current_gene(sas, err); if (!had_err) { addgn = gt_genome_node_ref(mygn); gt_array_add(sas->cur_gene_set, addgn); sas->cur_gene_range = gt_genome_node_get_range(mygn); } if (gt_queue_size(sas->outqueue) > 0) { *gn = (GtGenomeNode*) gt_queue_get(sas->outqueue); complete_cluster = true; } } } /* from now on, genes are kept in gene cluster arrays only */ gt_genome_node_delete(mygn); } } else { /* meta node */ had_err = snp_annotator_stream_process_current_gene(sas, err); if (!had_err) { gt_queue_add(sas->outqueue, mygn); } if (gt_queue_size(sas->outqueue) > 0) { *gn = (GtGenomeNode*) gt_queue_get(sas->outqueue); complete_cluster = true; } } } return had_err; }
static int construct_mRNAs(GT_UNUSED void *key, void *value, void *data, GtError *err) { ConstructionInfo *cinfo = (ConstructionInfo*) data; GtArray *gt_genome_node_array = (GtArray*) value, *mRNAs = (GtArray*) cinfo->mRNAs; GtGenomeNode *mRNA_node, *first_node, *gn; const char *tname; GtStrand mRNA_strand; GtRange mRNA_range; GtStr *mRNA_seqid; GtUword i; int had_err = 0; gt_error_check(err); gt_assert(key && value && data); /* at least one node in array */ gt_assert(gt_array_size(gt_genome_node_array)); /* determine the range and the strand of the mRNA */ first_node = *(GtGenomeNode**) gt_array_get(gt_genome_node_array, 0); mRNA_range = gt_genome_node_get_range(first_node); mRNA_strand = gt_feature_node_get_strand((GtFeatureNode*) first_node); mRNA_seqid = gt_genome_node_get_seqid(first_node); /* TODO: support discontinuous start/stop codons */ for (i = 0; !had_err && i < gt_array_size(gt_genome_node_array); i++) { gn = *(GtGenomeNode**) gt_array_get(gt_genome_node_array, i); if (gt_feature_node_get_attribute((GtFeatureNode*) gn, GTF_PARSER_STOP_CODON_FLAG)) { GtUword j; GtRange stop_codon_rng = gt_genome_node_get_range(gn); bool found_cds = false; for (j = 0; !had_err && j < gt_array_size(gt_genome_node_array); j++) { GtGenomeNode* gn2; GtRange this_rng; const char *this_type; gn2 = *(GtGenomeNode**) gt_array_get(gt_genome_node_array, j); if (gn == gn2) continue; this_rng = gt_genome_node_get_range(gn2); this_type = gt_feature_node_get_type((GtFeatureNode*) gn2); if (this_type == gt_symbol(gt_ft_CDS)) { if (gt_range_contains(&this_rng, &stop_codon_rng)) { if (cinfo->tidy) { gt_warning("stop codon on line %u in file %s is contained in " "CDS in line %u", gt_genome_node_get_line_number(gn), gt_genome_node_get_filename(gn), gt_genome_node_get_line_number(gn2)); found_cds = true; } else { gt_error_set(err, "stop codon on line %u in file %s is " "contained in CDS in line %u", gt_genome_node_get_line_number(gn), gt_genome_node_get_filename(gn), gt_genome_node_get_line_number(gn2)); had_err = -1; } break; } if (this_rng.end + 1 == stop_codon_rng.start) { this_rng.end = stop_codon_rng.end; gt_genome_node_set_range(gn2, &this_rng); found_cds = true; break; } if (this_rng.start == stop_codon_rng.end + 1) { this_rng.start = stop_codon_rng.start; gt_genome_node_set_range(gn2, &this_rng); found_cds = true; break; } } } if (!found_cds) { if (!had_err) { if (cinfo->tidy) { gt_warning("found stop codon on line %u in file %s with no " "flanking CDS, ignoring it", gt_genome_node_get_line_number(gn), gt_genome_node_get_filename(gn)); } else { gt_error_set(err, "found stop codon on line %u in file %s with no " "flanking CDS", gt_genome_node_get_line_number(gn), gt_genome_node_get_filename(gn)); had_err = -1; break; } } } else { gt_array_rem(gt_genome_node_array, i); gt_genome_node_delete(gn); } } } for (i = 1; !had_err && i < gt_array_size(gt_genome_node_array); i++) { GtRange range; GtStrand strand; gn = *(GtGenomeNode**) gt_array_get(gt_genome_node_array, i); range = gt_genome_node_get_range(gn); mRNA_range = gt_range_join(&mRNA_range, &range); strand = gt_feature_node_get_strand((GtFeatureNode*) gn); if (strand != mRNA_strand) { gt_error_set(err, "feature %s on line %u has strand %c, but the " "parent transcript has strand %c", (const char*) key, gt_genome_node_get_line_number(gn), GT_STRAND_CHARS[strand], GT_STRAND_CHARS[mRNA_strand]); had_err = -1; break; } else { mRNA_strand = gt_strand_join(mRNA_strand, strand); } if (!had_err && gt_str_cmp(mRNA_seqid, gt_genome_node_get_seqid(gn))) { gt_error_set(err, "The features on lines %u and %u refer to different " "genomic sequences (``seqname''), although they have the same " "gene IDs (``gene_id'') which must be globally unique", gt_genome_node_get_line_number(first_node), gt_genome_node_get_line_number(gn)); had_err = -1; break; } } if (!had_err) { mRNA_node = gt_feature_node_new(mRNA_seqid, gt_ft_mRNA, mRNA_range.start, mRNA_range.end, mRNA_strand); gt_feature_node_add_attribute(((GtFeatureNode*) mRNA_node), "ID", key); gt_feature_node_add_attribute(((GtFeatureNode*) mRNA_node), "transcript_id", key); if ((tname = gt_hashmap_get(cinfo->transcript_id_to_name_mapping, (const char*) key)) && strlen(tname) > 0) { gt_feature_node_add_attribute((GtFeatureNode*) mRNA_node, GT_GFF_NAME, tname); } /* register children */ for (i = 0; i < gt_array_size(gt_genome_node_array); i++) { gn = *(GtGenomeNode**) gt_array_get(gt_genome_node_array, i); gt_feature_node_add_child((GtFeatureNode*) mRNA_node, (GtFeatureNode*) gt_genome_node_ref(gn)); } /* store the mRNA */ gt_array_add(mRNAs, mRNA_node); } return had_err; }