static int visit_child(GtFeatureNode* fn, void *nti, GtError *err) { NodeTraverseInfo* gt_genome_node_info; int had_err = 0; gt_genome_node_info = (NodeTraverseInfo*) nti; gt_error_check(err); if (gt_feature_node_has_children(fn)) { GtFeatureNode *oldparent = gt_genome_node_info->parent; had_err = process_node(gt_genome_node_info->diagram, fn, gt_genome_node_info->parent, err); if (!had_err) { gt_genome_node_info->parent = fn; had_err = gt_feature_node_traverse_direct_children(fn, gt_genome_node_info, visit_child, err); } if (!had_err) { gt_genome_node_info->parent = oldparent; } } else { had_err = process_node(gt_genome_node_info->diagram, fn, gt_genome_node_info->parent, err); } return had_err; }
static int add_to_current(GtDiagram *d, GtFeatureNode *node, GtFeatureNode *parent, GtError *err) { GtBlock *block; NodeInfoElement *ni; GtStyleQueryStatus rval; GtStr *caption = NULL; bool status = true; const char *nnid_p = NULL, *nnid_n = NULL, *nodetype; gt_assert(d && node); nodetype = gt_feature_node_get_type(node); if (get_caption_display_status(d, nodetype, &status, err) < 0) { return -1; } /* Get nodeinfo element and set itself as parent */ ni = nodeinfo_get(d, node); gt_log_log("adding %s to self", nodetype); ni->parent = node; /* create new GtBlock tuple and add to node info */ block = gt_block_new_from_node(node); caption = gt_str_new(); rval = gt_style_get_str(d->style, nodetype, "block_caption", caption, node, err); if (rval == GT_STYLE_QUERY_ERROR) { gt_str_delete(caption); gt_block_delete(block); return -1; } else if (rval == GT_STYLE_QUERY_NOT_SET) { nnid_p = get_node_name_or_id(parent); nnid_n = get_node_name_or_id(node); if ((nnid_p || nnid_n) && status) { if (parent) { if (nnid_p && gt_feature_node_has_children(parent)) gt_str_append_cstr(caption, nnid_p); else gt_str_append_cstr(caption, "-"); gt_str_append_cstr(caption, "/"); } if (nnid_n) gt_str_append_cstr(caption, nnid_n); } else { gt_str_delete(caption); caption = NULL; } } gt_block_set_caption(block, caption); gt_block_insert_element(block, node); nodeinfo_add_block(ni, gt_feature_node_get_type(node), GT_UNDEF_REPR, block); return 0; }
static int gt_orf_finder_visitor_feature_node(GtNodeVisitor *gv, GtFeatureNode *gf, GtError *err) { GtORFFinderVisitor *lv; const char *gft = NULL; GtFeatureNodeIterator *gfi; GtFeatureNode *curnode = NULL; int had_err = 0; GtRange rng; lv = gt_orf_finder_visitor_cast(gv); gt_assert(lv); gt_error_check(err); gfi = gt_feature_node_iterator_new(gf); while (!had_err && (curnode = gt_feature_node_iterator_next(gfi))) { gft = gt_feature_node_get_type(curnode); if (gt_hashmap_get(lv->types, (void*) gft) != NULL || gt_hashmap_get(lv->types, (void*) "all") == (void*) 1) { if (!had_err) { rng = gt_genome_node_get_range((GtGenomeNode*) curnode); had_err = run_orffinder(lv->rmap, curnode, rng.start - 1, rng.end - 1, lv->min, lv->max, lv->all, err); if (gt_hashmap_get(lv->types, (void*) "all") == (void*) 1) { break; } else if (gt_feature_node_has_children(curnode)) { GtFeatureNode *tmpnode = NULL; GtFeatureNodeIterator *tmpgfi = gt_feature_node_iterator_new(curnode); (void) gt_feature_node_iterator_next(tmpgfi); while ((tmpnode = gt_feature_node_iterator_next(tmpgfi))) { gft = gt_feature_node_get_type(tmpnode); if (strcmp(gft, (const char*) GT_ORF_TYPE) == 0) { continue; } /* curnode = gt_feature_node_iterator_next(gfi); */ } gt_feature_node_iterator_delete(tmpgfi); } } } } gt_feature_node_iterator_delete(gfi); return had_err; }
static int store_ids(GtFeatureNode *fn, void *data, GtError *err) { GtGFF3Visitor *gff3_visitor = (GtGFF3Visitor*) data; AddIDInfo add_id_info; int had_err = 0; GtStr *id; gt_error_check(err); gt_assert(fn && gff3_visitor); if (gt_feature_node_has_children(fn) || gt_feature_node_is_multi(fn) || (gff3_visitor->retain_ids && gt_feature_node_get_attribute(fn, "ID"))) { if (gt_feature_node_is_multi(fn)) { id = gt_hashmap_get(gff3_visitor->feature_node_to_unique_id_str, gt_feature_node_get_multi_representative(fn)); if (!id) { /* the representative does not have its own id yet -> create it */ if (gff3_visitor->retain_ids) { id = make_id_unique(gff3_visitor, gt_feature_node_get_multi_representative(fn)); } else { id = create_unique_id(gff3_visitor, gt_feature_node_get_multi_representative(fn)); } } /* store id for feature, if the feature was not the representative */ if (gt_feature_node_get_multi_representative(fn) != fn) { gt_hashmap_add(gff3_visitor->feature_node_to_unique_id_str, fn, gt_str_ref(id)); } } else { if (gff3_visitor->retain_ids) id = make_id_unique(gff3_visitor, fn); else id = create_unique_id(gff3_visitor, fn); } /* for each child -> store the parent feature in the hash map */ add_id_info.gt_feature_node_to_id_array = gff3_visitor->feature_node_to_id_array, add_id_info.id = gt_str_get(id); had_err = gt_feature_node_traverse_direct_children(fn, &add_id_info, add_id, err); } return had_err; }
static int gff3_visitor_feature_node(GtNodeVisitor *nv, GtFeatureNode *fn, GtError *err) { GtGFF3Visitor *gff3_visitor; int had_err; gt_error_check(err); gff3_visitor = gff3_visitor_cast(nv); gff3_version_string(nv); had_err = gt_feature_node_traverse_children(fn, gff3_visitor, store_ids, true, err); if (!had_err) { if (gt_feature_node_is_tree(fn)) { had_err = gt_feature_node_traverse_children(fn, gff3_visitor, gff3_show_feature_node, true, err); } else { /* got a DAG -> traverse in topologically sorted depth first fashion to make sure that the 'Parent' attributes are shown in correct order */ had_err = gt_feature_node_traverse_children_top(fn, gff3_visitor, gff3_show_feature_node, err); } } /* reset hashmaps */ gt_hashmap_reset(gff3_visitor->feature_node_to_id_array); gt_hashmap_reset(gff3_visitor->feature_node_to_unique_id_str); /* show terminator, if the feature has children (otherwise it is clear that the feature is complete, because no ID attribute has been shown) */ if (gt_feature_node_has_children(fn) || (gff3_visitor->retain_ids && gt_feature_node_get_attribute(fn, "ID"))) { if (!gff3_visitor->outstr) gt_file_xprintf(gff3_visitor->outfp, "%s\n", GT_GFF_TERMINATOR); else { gt_str_append_cstr(gff3_visitor->outstr, GT_GFF_TERMINATOR); gt_str_append_char(gff3_visitor->outstr, '\n'); } } return had_err; }
/* Traverse a genome node graph with depth first search. */ static int traverse_genome_nodes(GtFeatureNode *fn, void *nti) { NodeTraverseInfo* gt_genome_node_info; int had_err = 0; gt_assert(nti); gt_genome_node_info = (NodeTraverseInfo*) nti; gt_genome_node_info->parent = fn; /* handle root nodes */ had_err = process_node(gt_genome_node_info->diagram, fn, NULL, gt_genome_node_info->err); if (!had_err && gt_feature_node_has_children(fn)) { had_err = gt_feature_node_traverse_direct_children(fn, gt_genome_node_info, visit_child, gt_genome_node_info ->err); } return had_err; }
static int assign_block_caption(GtDiagram *d, GtFeatureNode *node, GtFeatureNode *parent, GtBlock *block, GtError *err) { const char *nnid_p = NULL, *nnid_n = NULL; GtStr *caption = NULL; bool status = true; int rval; caption = gt_str_new(); rval = gt_style_get_str(d->style, gt_feature_node_get_type(node), "block_caption", caption, node, err); if (rval == GT_STYLE_QUERY_ERROR) { gt_str_delete(caption); return -1; } else if (rval == GT_STYLE_QUERY_NOT_SET) { nnid_p = get_node_name_or_id(parent); nnid_n = get_node_name_or_id(node); if ((nnid_p || nnid_n) && status) { if (parent) { if (nnid_p && gt_feature_node_has_children(parent)) gt_str_append_cstr(caption, nnid_p); else gt_str_append_cstr(caption, "-"); gt_str_append_cstr(caption, "/"); } if (nnid_n) gt_str_append_cstr(caption, nnid_n); } else { gt_str_delete(caption); caption = NULL; } } gt_block_set_caption(block, caption); return 0; }
static int check_cds_phases(GtArray *cds_features, GtCDSCheckVisitor *v, bool is_multi, bool second_pass, GtError *err) { GtPhase current_phase, correct_phase = GT_PHASE_ZERO; GtFeatureNode *fn; GtStrand strand; unsigned long i, current_length; int had_err = 0; gt_error_check(err); gt_assert(cds_features); gt_assert(gt_array_size(cds_features)); fn = *(GtFeatureNode**) gt_array_get_first(cds_features); strand = gt_feature_node_get_strand(fn); if (strand == GT_STRAND_REVERSE) gt_array_reverse(cds_features); for (i = 0; !had_err && i < gt_array_size(cds_features); i++) { fn = *(GtFeatureNode**) gt_array_get(cds_features, i); /* the first phase can be anything (except being undefined), because the GFF3 spec says: NOTE 4 - CDS features MUST have have a defined phase field. Otherwise it is not possible to infer the correct polypeptides corresponding to partially annotated genes. */ if ((!i && gt_feature_node_get_phase(fn) == GT_PHASE_UNDEFINED) || (i && gt_feature_node_get_phase(fn) != correct_phase)) { if (gt_hashmap_get(v->cds_features, fn)) { if (v->tidy && !is_multi && !gt_feature_node_has_children(fn)) { /* we can split the feature */ gt_warning("%s feature on line %u in file \"%s\" has multiple " "parents which require different phases; split feature", gt_ft_CDS, gt_genome_node_get_line_number((GtGenomeNode*) fn), gt_genome_node_get_filename((GtGenomeNode*) fn)); gt_hashmap_add(v->cds_features_to_split, fn, fn); v->splitting_is_necessary = true; /* split later */ } else { gt_error_set(err, "%s feature on line %u in file \"%s\" has multiple " "parents which require different phases", gt_ft_CDS, gt_genome_node_get_line_number((GtGenomeNode*) fn), gt_genome_node_get_filename((GtGenomeNode*) fn)); had_err = -1; } } else { if (v->tidy) { if (!second_pass) { gt_warning("%s feature on line %u in file \"%s\" has the wrong " "phase %c -> correcting it to %c", gt_ft_CDS, gt_genome_node_get_line_number((GtGenomeNode*) fn), gt_genome_node_get_filename((GtGenomeNode*) fn), GT_PHASE_CHARS[gt_feature_node_get_phase(fn)], GT_PHASE_CHARS[correct_phase]); } gt_feature_node_set_phase(fn, correct_phase); } else { gt_error_set(err, "%s feature on line %u in file \"%s\" has the " "wrong phase %c (should be %c)", gt_ft_CDS, gt_genome_node_get_line_number((GtGenomeNode*) fn), gt_genome_node_get_filename((GtGenomeNode*) fn), GT_PHASE_CHARS[gt_feature_node_get_phase(fn)], GT_PHASE_CHARS[correct_phase]); had_err = -1; } } } if (!had_err) { current_phase = gt_feature_node_get_phase(fn); current_length = gt_genome_node_get_length((GtGenomeNode*) fn); correct_phase = (3 - (current_length - current_phase) % 3) % 3; gt_hashmap_add(v->cds_features, fn, fn); /* record CDS feature */ } } return had_err; }