static int compute_statistics(GtFeatureNode *fn, void *data, GtError *err) { GtStatVisitor *sv; GT_UNUSED int rval; gt_error_check(err); gt_assert(data); sv = (GtStatVisitor*) data; if (gt_feature_node_is_multi(fn) && gt_feature_node_get_multi_representative(fn) == fn) { sv->number_of_multi_features++; } if (sv->used_sources) compute_source_statistics(fn, sv->used_sources); compute_type_statistics(fn, sv); if (sv->exon_number_distribution || sv->cds_length_distribution) { sv->exon_number_for_distri = 0; sv->cds_length_for_distri = 0; rval = gt_feature_node_traverse_direct_children(fn, sv, add_exon_or_cds_number, err); gt_assert(!rval); /* add_exon_or_cds_number() is sane */ if (sv->exon_number_distribution && sv->exon_number_for_distri) { gt_disc_distri_add(sv->exon_number_distribution, sv->exon_number_for_distri); } if (sv->cds_length_distribution && sv->cds_length_for_distri) { gt_disc_distri_add(sv->cds_length_distribution, sv->cds_length_for_distri); } } return 0; }
static void infer_cds_visitor_check_cds_multi(AgnInferCDSVisitor *v) { if(gt_array_size(v->cds) <= 1) { return; } GtFeatureNode **firstsegment = gt_array_get(v->cds, 0); const char *id = gt_feature_node_get_attribute(*firstsegment, "ID"); if(id == NULL) { char newid[64]; sprintf(newid, "CDS%lu", v->cdscounter++); gt_feature_node_add_attribute(*firstsegment, "ID", newid); } gt_feature_node_make_multi_representative(*firstsegment); GtUword i; for(i = 0; i < gt_array_size(v->cds); i++) { GtFeatureNode **segment = gt_array_get(v->cds, i); if(!gt_feature_node_is_multi(*segment)) { gt_feature_node_set_multi_representative(*segment, *firstsegment); } } }
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 check_cds_phases_if_necessary(GtFeatureNode *fn, GtCDSCheckVisitor *v, bool second_pass, GtError *err) { GtFeatureNodeIterator *fni; GtFeatureNode *node; GtArray *cds_features = NULL; GtHashmap *multi_features = NULL; int had_err = 0; gt_error_check(err); gt_assert(fn); fni = gt_feature_node_iterator_new_direct(fn); while ((node = gt_feature_node_iterator_next(fni))) { if (gt_feature_node_has_type(node, gt_ft_CDS)) { if (gt_feature_node_is_multi(node)) { GtArray *features; if (!multi_features) multi_features = gt_hashmap_new(GT_HASH_DIRECT, NULL, (GtFree) gt_array_delete); if ((features = gt_hashmap_get(multi_features, gt_feature_node_get_multi_representative(node)))) { gt_array_add(features, node); } else { GtFeatureNode *representative; features = gt_array_new(sizeof (GtFeatureNode*)); representative = gt_feature_node_get_multi_representative(node); gt_array_add(features, representative); gt_hashmap_add(multi_features, representative, features); } } else { if (!cds_features) cds_features = gt_array_new(sizeof (GtFeatureNode*)); gt_array_add(cds_features, node); } } } if (cds_features) had_err = check_cds_phases(cds_features, v, false, second_pass, err); if (!had_err && multi_features) had_err = gt_hashmap_foreach(multi_features, check_cds_phases_hm, v, err); gt_array_delete(cds_features); gt_hashmap_delete(multi_features); gt_feature_node_iterator_delete(fni); return had_err; }
static void add_recursive(GtDiagram *d, GtFeatureNode *node, GtFeatureNode* parent, GtFeatureNode *original_node) { NodeInfoElement *ni; GtFeatureNode *rep = GT_UNDEF_REPR; gt_assert(d && node && original_node); if (!parent) return; ni = nodeinfo_get(d, node); if (gt_feature_node_is_multi(original_node)) { rep = gt_feature_node_get_multi_representative(original_node); } /* end of recursion, insert into target block */ if (parent == node) { GtBlock *block ; block = nodeinfo_find_block(ni, gt_feature_node_get_type(node), rep); if (!block) { block = gt_block_new_from_node(node); nodeinfo_add_block(ni, gt_feature_node_get_type(node), rep, block); } gt_block_insert_element(block, original_node); gt_log_log("add %s to target %s", gt_feature_node_get_type(original_node), gt_block_get_type(block)); } else { /* not at target type block yet, set up reverse entry and follow */ NodeInfoElement *parent_ni; /* set up reverse entry */ ni->parent = parent; parent_ni = gt_hashmap_get(d->nodeinfo, parent); if (parent_ni) { gt_log_log("recursion: %s -> %s", gt_feature_node_get_type(node), gt_feature_node_get_type(parent)); add_recursive(d, parent, parent_ni->parent, original_node); } } }
static int add_to_rep(GtDiagram *d, GtFeatureNode *node, GtFeatureNode* parent, GtError *err) { GtBlock *block = NULL; GtFeatureNode *rep = GT_UNDEF_REPR; NodeInfoElement *ni; gt_assert(d && node && gt_feature_node_is_multi(node)); rep = gt_feature_node_get_multi_representative(node); gt_log_log("adding %s to representative %p", gt_feature_node_get_type(node), rep); ni = nodeinfo_get(d, rep); block = nodeinfo_find_block(ni, gt_feature_node_get_type(node), rep); if (!block) { block = gt_block_new_from_node(parent); gt_block_set_type(block, gt_feature_node_get_type(node)); /* if parent is a pseudonode, then we have a multiline feature without a parent. we must not access the parent in this case! */ if (gt_feature_node_is_pseudo(parent)) { if (assign_block_caption(d, node, NULL, block, err) < 0) { gt_block_delete(block); return -1; } } else { if (assign_block_caption(d, node, parent, block, err) < 0) { gt_block_delete(block); return -1; } } nodeinfo_add_block(ni, gt_feature_node_get_type(node), rep, block); } gt_assert(block); gt_block_insert_element(block, node); return 0; }
static int process_node(GtDiagram *d, GtFeatureNode *node, GtFeatureNode *parent, GtError *err) { GtRange elem_range; bool *collapse; GtShouldGroupByParent *group; const char *feature_type = NULL, *parent_gft = NULL; double tmp; GtStyleQueryStatus rval; GtUword max_show_width = GT_UNDEF_UWORD, par_max_show_width = GT_UNDEF_UWORD; gt_assert(d && node); gt_log_log(">> getting '%s'", gt_feature_node_get_type(node)); /* skip pseudonodes */ if (gt_feature_node_is_pseudo(node)) return 0; feature_type = gt_feature_node_get_type(node); gt_assert(feature_type); /* discard elements that do not overlap with visible range */ elem_range = gt_genome_node_get_range((GtGenomeNode*) node); if (!gt_range_overlap(&d->range, &elem_range)) return 0; /* get maximal view widths in nucleotides to show this type */ rval = gt_style_get_num(d->style, feature_type, "max_show_width", &tmp, NULL, err); switch (rval) { case GT_STYLE_QUERY_OK: max_show_width = tmp; break; case GT_STYLE_QUERY_ERROR: return -1; break; /* should never be reached */ default: /* do not change default value */ break; } /* for non-root nodes, get maximal view with to show parent */ if (parent) { if (!gt_feature_node_is_pseudo(parent)) { parent_gft = gt_feature_node_get_type(parent); rval = gt_style_get_num(d->style, parent_gft, "max_show_width", &tmp, NULL, err); switch (rval) { case GT_STYLE_QUERY_OK: par_max_show_width = tmp; break; case GT_STYLE_QUERY_ERROR: return -1; break; /* should never be reached */ default: /* do not change default value */ break; } } else par_max_show_width = GT_UNDEF_UWORD; } /* check if this type is to be displayed at all */ if (max_show_width != GT_UNDEF_UWORD && gt_range_length(&d->range) > max_show_width) { return 0; } /* disregard parent node if it is configured not to be shown */ if (parent && par_max_show_width != GT_UNDEF_UWORD && gt_range_length(&d->range) > par_max_show_width) { parent = NULL; } /* check if this is a collapsing type, cache result */ if ((collapse = (bool*) gt_hashmap_get(d->collapsingtypes, feature_type)) == NULL) { collapse = gt_malloc(sizeof (bool)); *collapse = false; if (gt_style_get_bool(d->style, feature_type, "collapse_to_parent", collapse, NULL, err) == GT_STYLE_QUERY_ERROR) { gt_free(collapse); return -1; } gt_hashmap_add(d->collapsingtypes, (void*) feature_type, collapse); } /* check if type should be grouped by parent, cache result */ if ((group = (GtShouldGroupByParent*) gt_hashmap_get(d->groupedtypes, feature_type)) == NULL) { bool tmp; group = gt_malloc(sizeof (GtShouldGroupByParent)); rval = gt_style_get_bool(d->style, feature_type, "group_by_parent", &tmp, NULL, err); switch (rval) { case GT_STYLE_QUERY_OK: if (tmp) *group = GT_GROUP_BY_PARENT; else *group = GT_DO_NOT_GROUP_BY_PARENT; break; case GT_STYLE_QUERY_NOT_SET: *group = GT_UNDEFINED_GROUPING; break; case GT_STYLE_QUERY_ERROR: gt_free(group); return -1; break; /* should never be reached */ } gt_hashmap_add(d->groupedtypes, (void*) feature_type, group); } /* decide where to place this feature: */ if (*collapse) { /* user has specified collapsing to parent for this type */ if (parent && !gt_feature_node_is_pseudo(parent)) { /* collapsing child nodes are added to upwards blocks, but never collapse into pseudo nodes */ add_recursive(d, node, parent, node); } else { /* if no parent or only pseudo-parent, do not collapse */ if (add_to_current(d, node, parent, err) < 0) { return -1; } } } else /* (!*collapse) */ { if (parent) { bool do_not_overlap = false; do_not_overlap = gt_feature_node_direct_children_do_not_overlap_st(parent, node); if (*group == GT_GROUP_BY_PARENT || (do_not_overlap && *group == GT_UNDEFINED_GROUPING)) { if (gt_feature_node_is_pseudo(parent) && gt_feature_node_is_multi(node)) { if (add_to_rep(d, node, parent, err) < 0) { return -1; } } else if (gt_feature_node_number_of_children(parent) > 1) { if (add_to_parent(d, node, parent, err) < 0) { return -1; } } else { if (add_to_current(d, node, parent, err) < 0) { return -1; } } } else { if (gt_feature_node_is_pseudo(parent) && gt_feature_node_is_multi(node)) { if (add_to_rep(d, node, parent, err) < 0) { return -1; } } else { if (add_to_current(d, node, parent, err) < 0) { return -1; } } } } else { /* root nodes always get their own block */ if (add_to_current(d, node, parent, err) < 0) { return -1; } } } /* we can now assume that this node (or its representative) has been processed into the reverse lookup structure */ #ifndef NDEBUG if (gt_feature_node_is_multi(node)) { GtFeatureNode *rep; rep = gt_feature_node_get_multi_representative((GtFeatureNode*) node); gt_assert(gt_hashmap_get(d->nodeinfo, rep)); } else gt_assert(gt_hashmap_get(d->nodeinfo, node)); #endif return 0; }