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)); }
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)); }
void gt_feature_info_replace_pseudo_parent(GtFeatureInfo *fi, GtFeatureNode *child, GtFeatureNode *new_pseudo_parent) { const char *id; gt_assert(fi && child && new_pseudo_parent); gt_assert(gt_feature_node_is_pseudo((GtFeatureNode*) new_pseudo_parent)); id = gt_feature_node_get_attribute(child, GT_GFF_ID); gt_assert(id); gt_hashmap_remove(fi->id_to_pseudo_parent, id); gt_feature_info_add_pseudo_parent(fi, id, new_pseudo_parent); }
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; }
GtFeatureNodeIterator* gt_feature_node_iterator_new(const GtFeatureNode *fn) { GtFeatureNodeIterator *fni; GtFeatureNode *child_feature; GtDlistelem *dlistelem; gt_assert(fn); fni = feature_node_iterator_new_base(fn); if (gt_feature_node_is_pseudo((GtFeatureNode*) fn)) { /* add the children backwards to traverse in order */ for (dlistelem = gt_dlist_last(fn->children); dlistelem != NULL; dlistelem = gt_dlistelem_previous(dlistelem)) { child_feature = (GtFeatureNode*) gt_dlistelem_get_data(dlistelem); gt_array_add(fni->feature_stack, child_feature); } } else gt_array_add(fni->feature_stack, fni->fn); gt_assert(gt_array_size(fni->feature_stack)); fni->direct = false; return fni; }
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 CpGIOverlap_stream_next(GtNodeStream * ns, GtGenomeNode ** gn, GtError * err) { GtGenomeNode * cur_node, * next_node; GtFeatureNodeIterator * iter; int err_num = 0; *gn = NULL; CpGIOverlap_stream * context; const char * gene_name = NULL; const char * overlap_name = NULL; char chr_str[255]; int chr_num; unsigned int TSS; float CpGIOverlap; context = CpGIOverlap_stream_cast(ns); // find the genes, determine expression level if(!gt_node_stream_next(context->in_stream, &cur_node, err ) && cur_node != NULL ) { *gn = cur_node; // try casting as a feature node so we can test type if(!gt_genome_node_try_cast(gt_feature_node_class(), cur_node)) { return 0; } else // we found a feature node { // first check if it is a pseudo node, if so find the gene in it if available if (gt_feature_node_is_pseudo(cur_node)) { iter = gt_feature_node_iterator_new(cur_node); if (iter == NULL) return; while ((next_node = gt_feature_node_iterator_next(iter)) && !gt_feature_node_has_type(next_node, feature_type_gene)); gt_feature_node_iterator_delete(iter); if (NULL == (cur_node = next_node)) return 0; } if(!gt_feature_node_has_type(cur_node, feature_type_gene)) return 0; // find name of gene gene_name = gt_feature_node_get_attribute(cur_node, "Name"); if (gene_name == NULL) return; if ( 1 != sscanf(gt_str_get(gt_genome_node_get_seqid(cur_node)), "Chr%d", &chr_num)) return 0; TSS = (gt_feature_node_get_strand(cur_node) == GT_STRAND_FORWARD) ? gt_genome_node_get_start(cur_node) : gt_genome_node_get_end(cur_node); // now figure out the overlapping gene if (! (overlap_name = CpGIOverlap_stream_find_gene_overlap( context, TSS, chr_num))) return 0; // save the score into the node gt_feature_node_set_attribute(cur_node, "cpgi_at_tss", overlap_name); return 0; } } return err_num; }
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; }