Пример #1
0
void CoordSearchDialog::EditCompleted( Edit& sender ){
   m_targetObj=sender.Text();
}
Пример #2
0
void NewImageInterface::UpdateInitialValue( Edit& e, Slider& s, double v )
{
   e.SetText( String().Format( "%.8lf", v ) );
   s.SetValue( RoundI( v*s.MaxValue() ) );
}
Пример #3
0
// merge that properly handles long indels
// assumes that alignments should line up end-to-end
Alignment merge_alignments(const vector<Alignment>& alns, bool debug) {

    if (alns.size() == 0) {
        Alignment aln;
        return aln;
    } else if (alns.size() == 1) {
        return alns.front();
    }

    // where possible get node and target lengths
    // to validate after merge
    /*
    map<int64_t, map<size_t, set<const Alignment*> > > node_lengths;
    map<int64_t, map<size_t, set<const Alignment*> > > to_lengths;
    for (auto& aln : alns) {
        auto& path = aln.path();
        // find a mapping that overlaps the whole node
        // note that edits aren't simplified
        // so deletions are intact
        for (size_t i = 0; i < path.mapping_size(); ++i) {
            auto& m = path.mapping(i);
            if (m.position().offset() == 0) {
                // can we see if the next mapping is on the following node
                if (i < path.mapping_size()-1 && path.mapping(i+1).position().offset() == 0
                    && mapping_from_length(path.mapping(i+1)) && mapping_from_length(m)) {
                    // we cover the node, record the to_length and from_length
                    set<const Alignment*>& n = node_lengths[m.position().node_id()][from_length(m)];
                    n.insert(&aln);
                    set<const Alignment*>& t = to_lengths[m.position().node_id()][to_length(m)];
                    t.insert(&aln);
                }
            }
        }
    }
    // verify our input by checking for disagreements
    for (auto& n : node_lengths) {
        auto& node_id = n.first;
        if (n.second.size() > 1) {
            cerr << "disagreement in node lengths for " << node_id << endl;
            for (auto& l : n.second) {
                cerr << "alignments that report length of " << l.first << endl;
                for (auto& a : l.second) {
                    cerr << pb2json(*a) << endl;
                }
            }
        } else {
            //cerr << n.second.begin()->second.size() << " alignments support "
            //     << n.second.begin()->first << " as length for " << node_id << endl;
        }
    }
    */
    
    // parallel merge algorithm
    // for each generation
    // merge 0<-0+1, 1<-2+3, ...
    // until there is only one alignment
    vector<Alignment> last = alns;

    // get the alignments ready for merge
#pragma omp parallel for
    for (size_t i = 0; i < last.size(); ++i) {
        Alignment& aln = last[i];
        //cerr << "on " << i << "th aln" << endl
        //     << pb2json(aln) << endl;
        if (!aln.has_path()) {
            Mapping m;
            Edit* e = m.add_edit();
            e->set_to_length(aln.sequence().size());
            e->set_sequence(aln.sequence());
            *aln.mutable_path()->add_mapping() = m;
        }
    }

    while (last.size() > 1) {
        //cerr << "last size " << last.size() << endl;
        size_t new_count = last.size()/2;
        //cerr << "new count b4 " << new_count << endl;
        new_count += last.size() % 2; // force binary
        //cerr << "New count = " << new_count << endl;
        vector<Alignment> curr; curr.resize(new_count);
#pragma omp parallel for
        for (size_t i = 0; i < curr.size(); ++i) {
            //cerr << "merging " << 2*i << " and " << 2*i+1 << endl;
            // take a pair from the old alignments
            // merge them into this one
            if (2*i+1 < last.size()) {
                auto& a1 = last[2*i];
                auto& a2 = last[2*i+1];
                curr[i] = merge_alignments(a1, a2, debug);
                // check that the merge did the right thing
                /*
                auto& a3 = curr[i];
                for (size_t j = 0; j < a3.path().mapping_size()-1; ++j) {
                    // look up reported node length
                    // and compare to what we saw
                    // skips last mapping
                    auto& m = a3.path().mapping(j);
                    if (from_length(m) == to_length(m)
                        && m.has_position()
                        && m.position().offset()==0
                        && a3.path().mapping(j+1).has_position()
                        && a3.path().mapping(j+1).position().offset()==0) {
                        auto nl = node_lengths.find(m.position().node_id());
                        if (nl != node_lengths.end()) {
                            if (nl->second.find(from_length(m)) == nl->second.end()) {
                                cerr << "node length is not consistent for " << m.position().node_id() << endl;
                                cerr << "expected " << nl->second.begin()->first << endl;
                                cerr << "got " << from_length(m) << endl;
                                cerr << "inputs:" << endl << pb2json(a1) << endl << pb2json(a2)
                                     << endl << "output: " << endl << pb2json(a3) << endl;
                                //exit(1);
                            }
                        }
                    }
                }
                */
            } else {
                auto& a1 = last[2*i];
                //cerr << "no need to merge" << endl;
                curr[i] = a1;
            }
        }
        last = curr;
    }
    Alignment res = last.front();
    *res.mutable_path() = simplify(res.path());
    return res;
}
Пример #4
0
pair<size_t, size_t> Simplifier::simplify_once(size_t iteration) {

    // Set up the deleted node and edge counts
    pair<size_t, size_t> to_return {0, 0};
    auto& deleted_nodes = to_return.first;
    auto& deleted_edges = to_return.second;

    if(!graph.is_valid(true, true, true, true)) {
        // Make sure the graph is valid and not missing nodes or edges
        cerr << "error:[vg::Simplifier] Invalid graph on iteration " << iteration << endl;
        exit(1);
    }

    // Make a list of leaf sites
    list<const Snarl*> leaves;
    
    if (show_progress) {
        cerr << "Iteration " << iteration << ": Scanning " << graph.node_count() << " nodes and "
            << graph.edge_count() << " edges for sites..." << endl;
    }
    
    for (const Snarl* top_level_site : site_manager.top_level_snarls()) {
        list<const Snarl*> queue {top_level_site};
        
        while (queue.size()) {
            const Snarl* site = queue.front();
            queue.pop_front();
            
            if (site_manager.is_leaf(site)) {
                // It's a leaf. Filter it out if it is trivial
                
                if (site->type() == ULTRABUBBLE) {
                    auto contents = site_manager.shallow_contents(site, graph, false);
                    if (contents.first.empty()) {
                        // Nothing but the boundary nodes in this snarl
                        continue;
                    }
                }
            
                // Not trivial. Keep it.
                leaves.push_back(site);
            }
            else {
                for (const Snarl* child_site : site_manager.children_of(site)) {
                    queue.push_back(child_site);
                }
            }
        }
    }
    
    if (show_progress) {
        cerr << "Found " << leaves.size() << " leaves" << endl;
    }
    
    // Index all the graph paths
    map<string, unique_ptr<PathIndex>> path_indexes;
    graph.paths.for_each_name([&](const string& name) {
        // For every path name, go index it and put it in this collection
        path_indexes.insert(make_pair(name, move(unique_ptr<PathIndex>(new PathIndex(graph, name)))));
    });
    
    // Now we have a list of all the leaf sites.
    create_progress("simplifying leaves", leaves.size());
    
    // We can't use the SnarlManager after we modify the graph, so we load the
    // contents of all the leaves we're going to modify first.
    map<const Snarl*, pair<unordered_set<Node*>, unordered_set<Edge*>>> leaf_contents;
    
    // How big is each leaf in bp
    map<const Snarl*, size_t> leaf_sizes;
    
    // We also need to pre-calculate the traversals for the snarls that are the
    // right size, since the traversal finder uses the snarl manager amd might
    // not work if we modify the graph.
    map<const Snarl*, vector<SnarlTraversal>> leaf_traversals;
    
    for (const Snarl* leaf : leaves) {
        // Look at all the leaves
        
        // Get the contents of the bubble, excluding the boundary nodes
        leaf_contents[leaf] = site_manager.deep_contents(leaf, graph, false);
        
        // For each leaf, calculate its total size.
        unordered_set<Node*>& nodes = leaf_contents[leaf].first;
        size_t& total_size = leaf_sizes[leaf];
        for (Node* node : nodes) {
            // For each node include it in the size figure
            total_size += node->sequence().size();
        }
        
        if (total_size == 0) {
            // This site is just the start and end nodes, so it doesn't make
            // sense to try and remove it.
            continue;
        }
        
        if (total_size >= min_size) {
            // This site is too big to remove
            continue;
        }
        
        // Identify the replacement traversal for the bubble if it's the right size.
        // We can't necessarily do this after we've modified the graph.
        vector<SnarlTraversal>& traversals = leaf_traversals[leaf];
        traversals = traversal_finder.find_traversals(*leaf);
    }
    
    for (const Snarl* leaf : leaves) {
        // Look at all the leaves
        
        // Get the contents of the bubble, excluding the boundary nodes
        unordered_set<Node*>& nodes = leaf_contents[leaf].first;
        unordered_set<Edge*>& edges = leaf_contents[leaf].second;
        
        // For each leaf, grab its total size.
        size_t& total_size = leaf_sizes[leaf];
        
        if (total_size == 0) {
            // This site is just the start and end nodes, so it doesn't make
            // sense to try and remove it.
            continue;
        }
        
        if (total_size >= min_size) {
            // This site is too big to remove
            continue;
        }
        
#ifdef debug
        cerr << "Found " << total_size << " bp leaf" << endl;
        for (auto* node : nodes) {
            cerr << "\t" << node->id() << ": " << node->sequence() << endl;
        }
#endif
        
        // Otherwise we want to simplify this site away
        
        // Grab the replacement traversal for the bubble
        vector<SnarlTraversal>& traversals = leaf_traversals[leaf];
        
        if (traversals.empty()) {
            // We couldn't find any paths through the site.
            continue;
        }
        
        // Get the traversal out of the vector
        SnarlTraversal& traversal = traversals.front();
        
        // Determine the length of the new traversal
        size_t new_site_length = 0;
        for (size_t i = 1; i < traversal.visit_size() - 1; i++) {
            // For every non-anchoring node
            const Visit& visit = traversal.visit(i);
            // Total up the lengths of all the nodes that are newly visited.
            assert(visit.node_id());
            new_site_length += graph.get_node(visit.node_id())->sequence().size();
        }

#ifdef debug
        cerr << "Chosen traversal is " << new_site_length << " bp" << endl;
#endif
        
        // Now we have to rewrite paths that visit nodes/edges not on this
        // traversal, or in a different order, or whatever. To be safe we'll
        // just rewrite all paths.
        
        // Find all the paths that traverse this region.
        
        // We start at the start node. Copy out all the mapping pointers on that
        // node, so we can go through them while tampering with them.
        map<string, set<Mapping*> > mappings_by_path = graph.paths.get_node_mapping(graph.get_node(leaf->start().node_id()));
        
        // It's possible a path can enter the site through the end node and
        // never hit the start. So we're going to trim those back before we delete nodes and edges.
        map<string, set<Mapping*> > end_mappings_by_path = graph.paths.get_node_mapping(graph.get_node(leaf->end().node_id()));
        
        if (!drop_hairpin_paths) {
            // We shouldn't drop paths if they hairpin and can't be represented
            // in a simplified bubble. So we instead have to not simplify
            // bubbles that would have that problem.
            bool found_hairpin = false;
            
            for (auto& kv : mappings_by_path) {
                // For each path that hits the start node
                
                if (found_hairpin) {
                    // We only care if there are 1 or more hairpins, not how many
                    break;    
                }
                
                // Unpack the name
                auto& path_name = kv.first;
                
                for (Mapping* start_mapping : kv.second) {
                    // For each visit to the start node
                
                    if (found_hairpin) {
                        // We only care if there are 1 or more hairpins, not how many
                        break;    
                    }
                
                    // Determine what orientation we're going to scan in
                    bool backward = start_mapping->position().is_reverse();
                    
                    // Start at the start node
                    Mapping* here = start_mapping;
                    
                    while (here) {
                        // Until we hit the start/end of the path or the mapping we want
                        if (here->position().node_id() == leaf->end().node_id() &&
                            here->position().is_reverse() == (leaf->end().backward() != backward)) {
                            // We made it out.
                            // Stop scanning!
                            break;
                        }
                        
                        if (here->position().node_id() == leaf->start().node_id() &&
                            here->position().is_reverse() != (leaf->start().backward() != backward)) {
                            // We have encountered the start node with an incorrect orientation.
                            cerr << "warning:[vg simplify] Path " << path_name
                                << " doubles back through start of site "
                                << to_node_traversal(leaf->start(), graph) << " - "
                                << to_node_traversal(leaf->end(), graph) << "; skipping site!" << endl;
                                
                            found_hairpin = true;
                            break;
                        }
                        
                        // Scan left along ther path if we found the site start backwards, and right if we found it forwards.
                        here = backward ? graph.paths.traverse_left(here) : graph.paths.traverse_right(here);
                    }
                }
            }
            
            for (auto& kv : end_mappings_by_path) {
                // For each path that hits the end node
                
                if (found_hairpin) {
                    // We only care if there are 1 or more hairpins, not how many
                    break;
                }
                
                // Unpack the name
                auto& path_name = kv.first;
                
                for (Mapping* end_mapping : kv.second) {
                    
                    if (found_hairpin) {
                        // We only care if there are 1 or more hairpins, not how many
                        break;
                    }
                    
                    // Determine what orientation we're going to scan in
                    bool backward = end_mapping->position().is_reverse();
                    
                    // Start at the end
                    Mapping* here = end_mapping;
                    
                    while (here) {
                        
                        if (here->position().node_id() == leaf->start().node_id() &&
                            here->position().is_reverse() == (leaf->start().backward() != backward)) {
                            // We made it out.
                            // Stop scanning!
                            break;
                        }
                        
                        if (here->position().node_id() == leaf->end().node_id() &&
                            here->position().is_reverse() != (leaf->end().backward() != backward)) {
                            // We have encountered the end node with an incorrect orientation.
                            cerr << "warning:[vg simplify] Path " << path_name
                                << " doubles back through end of site "
                                << to_node_traversal(leaf->start(), graph) << " - "
                                << to_node_traversal(leaf->end(), graph) << "; dropping site!" << endl;
                            
                            found_hairpin = true;
                            break;
                        }
                        
                        // Scan right along the path if we found the site end backwards, and left if we found it forwards.
                        here = backward ? graph.paths.traverse_right(here) : graph.paths.traverse_left(here);
                        
                    }
                    
                }
                    
            }
            
            if (found_hairpin) {
                // We found a hairpin, so we want to skip the site.
                cerr << "warning:[vg simplify] Site " << to_node_traversal(leaf->start(), graph) << " - " << to_node_traversal(leaf->end(), graph) << " skipped due to hairpin path." << endl;
                continue;
            }
            
        }
        
        // We'll keep a set of the end mappings we managed to find, starting from the start
        set<Mapping*> found_end_mappings;
        
        for (auto& kv : mappings_by_path) {
            // For each path that hits the start node
            
            // Unpack the name
            auto& path_name = kv.first;
            
            // If a path can't be represented after a bubble is popped
            // (because the path reversed and came out the same side as it
            // went in), we just clobber the path entirely. TODO: handle
            // out-the-same-side traversals as valid genotypes somehow..
            bool kill_path = false;
            
            for (Mapping* start_mapping : kv.second) {
                // For each visit to the start node
                
                // Determine what orientation we're going to scan in
                bool backward = start_mapping->position().is_reverse();
                
                // We're going to fill this list with the mappings we need to
                // remove and replace in this path for this traversal. Initially
                // runs from start of site to end of site, but later gets
                // flipped into path-local orientation.
                list<Mapping*> existing_mappings;
                
                // Tracing along forward/backward from each as appropriate, see
                // if the end of the site is found in the expected orientation
                // (or if the path ends first).
                bool found_end = false;
                Mapping* here = start_mapping;
                
                // We want to remember the end mapping when we find it
                Mapping* end_mapping = nullptr;
                
#ifdef debug
                cerr << "Scanning " << path_name << " from " << pb2json(*here)
                    << " for " << to_node_traversal(leaf->end(), graph) << " orientation " << backward << endl;
#endif
                
                while (here) {
                    // Until we hit the start/end of the path or the mapping we want
                    
#ifdef debug
                    cerr << "\tat " << pb2json(*here) << endl;
#endif
                    
                    if (here->position().node_id() == leaf->end().node_id() &&
                        here->position().is_reverse() == (leaf->end().backward() != backward)) {
                        // We have encountered the end of the site in the
                        // orientation we expect, given the orientation we saw
                        // for the start.
                        
                        found_end = true;
                        end_mapping = here;
                        
                        // Know we got to this mapping at the end from the
                        // start, so we don't need to clobber everything
                        // before it.
                        found_end_mappings.insert(here);
                        
                        // Stop scanning!
                        break;
                    }
                    
                    if (here->position().node_id() == leaf->start().node_id() &&
                        here->position().is_reverse() != (leaf->start().backward() != backward)) {
                        // We have encountered the start node with an incorrect orientation.
                        cerr << "warning:[vg simplify] Path " << path_name
                            << " doubles back through start of site "
                            << to_node_traversal(leaf->start(), graph) << " - "
                            << to_node_traversal(leaf->end(), graph) << "; dropping!" << endl;
                            
                        assert(drop_hairpin_paths);
                        kill_path = true;
                        break;
                    }
                    
                    if (!nodes.count(graph.get_node(here->position().node_id()))) {
                        // We really should stay inside the site!
                        cerr << "error:[vg simplify] Path " << path_name
                            << " somehow escapes site " << to_node_traversal(leaf->start(), graph)
                            << " - " << to_node_traversal(leaf->end(), graph) << endl;
                            
                        exit(1);
                    }
                    
                    if (here != start_mapping) {
                        // Remember the mappings that aren't to the start or
                        // end of the site, so we can remove them later.
                        existing_mappings.push_back(here);
                    }
                    
                    // Scan left along ther path if we found the site start backwards, and right if we found it forwards.
                    Mapping* next = backward ? graph.paths.traverse_left(here) : graph.paths.traverse_right(here);
                    
                    if (next == nullptr) {
                        // We hit the end of the path without finding the end of the site.
                        // We've found all the existing mappings, so we can stop.
                        break;
                    }
                    
                    // Make into NodeTraversals
                    NodeTraversal here_traversal(graph.get_node(here->position().node_id()), here->position().is_reverse());
                    NodeTraversal next_traversal(graph.get_node(next->position().node_id()), next->position().is_reverse());
                    
                    if (backward) {
                        // We're scanning the other way
                        std::swap(here_traversal, next_traversal);
                    }
                    
                    // Make sure we have an edge so we can traverse this node and then the node we're going to.
                    if(graph.get_edge(here_traversal, next_traversal) == nullptr) {
                        cerr << "error:[vg::Simplifier] No edge " << here_traversal << " to " << next_traversal << endl;
                        exit(1);
                    }
                    
                    here = next;
                }
                
                if (kill_path) {
                    // This path can't exist after we pop this bubble.
                    break;
                }
                
                
                if (!found_end) {
                    // This path only partly traverses the site, and is
                    // anchored at the start. Remove the part inside the site.
                    
                    // TODO: let it stay if it matches the one true traversal.
                                 
                    for(auto* mapping : existing_mappings) {
                        // Trim the path out of the site
                        graph.paths.remove_mapping(mapping);
                    }
                    
                    // TODO: update feature positions if we trim off the start of a path

                    // Maybe the next time the path visits the site it will go
                    // all the way through.
                    continue;
                }
                
                // If we found the end, remove all the mappings encountered, in
                // order so that the last one removed is the last one along the
                // path.
                if (backward) {
                    // Make sure the last mapping in the list is the last
                    // mapping to occur along the path.
                    existing_mappings.reverse();
                }
                
                // Where does the variable region of the site start for this
                // traversal of the path? If there are no existing mappings,
                // it's the start mapping's position if we traverse the site
                // backwards and the end mapping's position if we traverse
                // the site forwards. If there are existing mappings, it's
                // the first existing mapping's position in the path. TODO:
                // This is super ugly. Can we view the site in path
                // coordinates or something?
                PathIndex& path_index = *path_indexes.at(path_name).get();
                Mapping* mapping_after_first = existing_mappings.empty() ?
                    (backward ? start_mapping : end_mapping) : existing_mappings.front();
                assert(path_index.mapping_positions.count(mapping_after_first));
                size_t variable_start = path_index.mapping_positions.at(mapping_after_first); 
                
                
                
                // Determine the total length of the old traversal of the site
                size_t old_site_length = 0;
                for (auto* mapping : existing_mappings) {
                    // Add in the lengths of all the mappings that will get
                    // removed.
                    old_site_length += mapping_from_length(*mapping);
                }
#ifdef debug
                cerr << "Replacing " << old_site_length << " bp at " << variable_start
                    << " with " << new_site_length << " bp" << endl;
#endif

                // Actually update any BED features
                features.on_path_edit(path_name, variable_start, old_site_length, new_site_length);
                
                // Where will we insert the new site traversal into the path?
                list<Mapping>::iterator insert_position;
                
                if (!existing_mappings.empty()) {
                    // If there are existing internal mappings, we'll insert right where they were
                    
                    for (auto* mapping : existing_mappings) {
                        // Remove each mapping from left to right along the
                        // path, saving the position after the mapping we just
                        // removed. At the end we'll have the position of the
                        // mapping to the end of the site.
                        
#ifdef debug
                        cerr << path_name << ": Drop mapping " << pb2json(*mapping) << endl;
#endif
                        
                        insert_position = graph.paths.remove_mapping(mapping);
                    }
                } else {
                    // Otherwise we'll insert right before the mapping to
                    // the start or end of the site (whichever occurs last
                    // along the path)
                    insert_position = graph.paths.find_mapping(backward ? start_mapping : here);
                }
                
                // Make sure we're going to insert starting from the correct end of the site.
                if (backward) {
                    assert(insert_position->position().node_id() == leaf->start().node_id());
                } else {
                    assert(insert_position->position().node_id() == leaf->end().node_id());
                }
                
                // Loop through the internal visits in the canonical
                // traversal backwards along the path we are splicing. If
                // it's a forward path this is just right to left, but if
                // it's a reverse path it has to be left to right.
                for (size_t i = 0; i < traversal.visit_size(); i++) {
                    // Find the visit we need next, as a function of which
                    // way we need to insert this run of visits. Normally we
                    // go through the visits right to left, but when we have
                    // a backward path we go left to right.
                    const Visit& visit = backward ? traversal.visit(i)
                                                  : traversal.visit(traversal.visit_size() - i - 1);
                    
                    // Make a Mapping to represent it
                    Mapping new_mapping;
                    new_mapping.mutable_position()->set_node_id(visit.node_id());
                    // We hit this node backward if it's backward along the
                    // traversal, xor if we are traversing the traversal
                    // backward
                    new_mapping.mutable_position()->set_is_reverse(visit.backward() != backward);
                    
                    // Add an edit
                    Edit* edit = new_mapping.add_edit();
                    size_t node_seq_length = graph.get_node(visit.node_id())->sequence().size();
                    edit->set_from_length(node_seq_length);
                    edit->set_to_length(node_seq_length);
                    
#ifdef debug
                    cerr << path_name << ": Add mapping " << pb2json(new_mapping) << endl;
#endif
                    
                    // Insert the mapping in the path, moving right to left
                    insert_position = graph.paths.insert_mapping(insert_position, path_name, new_mapping);
                    
                }
                
                // Now we've corrected this site on this path. Update its index.
                // TODO: right now this means retracing the entire path.
                path_indexes[path_name].get()->update_mapping_positions(graph, path_name);
            }
            
            if (kill_path) {
                // Destroy the path completely, because it needs to reverse
                // inside a site that we have popped.
                graph.paths.remove_path(path_name);
            }
            
        }
        
        for (auto& kv : end_mappings_by_path) {
            // Now we handle the end mappings not reachable from the start. For each path that touches the end...
        
            // Unpack the name
            auto& path_name = kv.first;
            
            // We might have to kill the path, if it reverses inside a
            // bubble we're popping
            bool kill_path = false;
            
            for (Mapping* end_mapping : kv.second) {
                if (found_end_mappings.count(end_mapping)) {
                    // Skip the traversals of the site that we handled.
                    continue;
                }
                
                // Now we're left with paths that leave the site but don't
                // enter. We're going to clobber everything before the path
                // leaves the site.
                
                // Determine what orientation we're going to scan in
                bool backward = end_mapping->position().is_reverse();
                
                // Start at the end
                Mapping* here = end_mapping;
                
                // Keep a list of mappings we need to remove
                list<Mapping*> to_remove;
                
                while (here) {
                    
                    if (here->position().node_id() == leaf->end().node_id() &&
                        here->position().is_reverse() != (leaf->end().backward() != backward)) {
                        // We have encountered the end node with an incorrect orientation.
                        cerr << "warning:[vg simplify] Path " << path_name
                            << " doubles back through end of site "
                            << to_node_traversal(leaf->start(), graph) << " - "
                            << to_node_traversal(leaf->end(), graph) << "; dropping!" << endl;
                            
                        assert(drop_hairpin_paths);
                        kill_path = true;
                        break;
                    }
                    
                    // Say we should remove the mapping.
                    to_remove.push_back(here);
                    
                    // Scan right along the path if we found the site end backwards, and left if we found it forwards.
                    here = backward ? graph.paths.traverse_right(here) : graph.paths.traverse_left(here);
                    
                    // Eventually we should hit the end of the path, or the
                    // end of the site, since we don't hit the start.
                    
                }
                
                if (kill_path) {
                    // Just go kill the whole path
                    break;
                }
                
                for (auto* mapping: to_remove) {
                    // Get rid of all the mappings once we're done tracing them out.
                    graph.paths.remove_mapping(mapping);
                }
                
            }
            
            if (kill_path) {
                // Destroy the path completely, because it needs to reverse
                // inside a site that we have popped.
                graph.paths.remove_path(path_name);
            }
        }
        
        // Now delete all edges that aren't connecting adjacent nodes on the
        // blessed traversal (before we delete their nodes).
        set<Edge*> blessed_edges;
        for (int i = 0; i < traversal.visit_size() - 1; ++i) {
            // For each node and the next node (which won't be the end)
            
            const Visit visit = traversal.visit(i);
            const Visit next = traversal.visit(i);
            
            // Find the edge between them
            NodeTraversal here(graph.get_node(visit.node_id()), visit.backward());
            NodeTraversal next_traversal(graph.get_node(next.node_id()), next.backward());
            Edge* edge = graph.get_edge(here, next_traversal);
            assert(edge != nullptr);
            
            // Remember we need it
            blessed_edges.insert(edge);
        }
        
        // Also get the edges from the boundary nodes into the traversal
        if (traversal.visit_size() > 0) {
            NodeTraversal first_visit = to_node_traversal(traversal.visit(0), graph);
            NodeTraversal last_visit = to_node_traversal(traversal.visit(traversal.visit_size() - 1),
                                                         graph);
            blessed_edges.insert(graph.get_edge(to_node_traversal(leaf->start(), graph), first_visit));
            blessed_edges.insert(graph.get_edge(last_visit, to_node_traversal(leaf->end(), graph)));
        }
        else {
            // This is a deletion traversal, so get the edge from the start to end of the site
            blessed_edges.insert(graph.get_edge(to_node_traversal(leaf->start(), graph),
                                                to_node_traversal(leaf->end(), graph)));
        }
        
        for (auto* edge : edges) {
            if (!blessed_edges.count(edge)) {
                // Get rid of all the edges not needed for the one true traversal
#ifdef debug
                cerr << to_node_traversal(leaf->start(), graph) << " - "
                     << to_node_traversal(leaf->end(), graph) << ": Delete edge: "
                     << pb2json(*edge) << endl;
#endif
                graph.destroy_edge(edge);
                deleted_edges++;
            }
        }
       
           
        // Now delete all the nodes that aren't on the blessed traversal.
        
        // What nodes are on it?
        set<Node*> blessed_nodes;
        for (int i = 0; i < traversal.visit_size(); i++) {
            const Visit& visit = traversal.visit(i);
            blessed_nodes.insert(graph.get_node(visit.node_id()));
        }
        
        for (auto* node : nodes) {
            // For every node in the site
            if (!blessed_nodes.count(node)) {
                // If we don't need it for the chosen path, destroy it
#ifdef debug
                cerr << to_node_traversal(leaf->start(), graph) << " - "
                     << to_node_traversal(leaf->end(), graph) << ": Delete node: "
                     << pb2json(*node) << endl;
#endif
                // There may be paths still touching this node, if they
                // managed to get into the site without touching the start
                // node. We'll delete those paths.
                set<string> paths_to_kill;
                for (auto& kv : graph.paths.get_node_mapping(node)) {
                
                    if (mappings_by_path.count(kv.first)) {
                        // We've already actually updated this path; the
                        // node_mapping data is just out of date.
                        continue;
                    }
                
                    paths_to_kill.insert(kv.first);
                }
                for (auto& path : paths_to_kill) {
                    graph.paths.remove_path(path);
                    cerr << "warning:[vg simplify] Path " << path << " removed" << endl;
                }

                graph.destroy_node(node);
                
                deleted_nodes++;
            }
        }
        
        // OK we finished a leaf
        increment_progress();
    }
    
    destroy_progress();
    
    // Reset the ranks in the graph, since we rewrote paths
    graph.paths.clear_mapping_ranks();
    
    // Return the statistics.
    return to_return;

}
Пример #5
0
bool edit_is_insertion(const Edit& e) {
    return e.from_length() == 0 && e.to_length() > 0 && !e.sequence().empty();
}
Пример #6
0
void ColorCalibrationInterface::__GetFocus( Control& sender )
{
   Edit* e = dynamic_cast<Edit*>( &sender );
   if ( e != 0 && e->Text() == TARGET_IMAGE )
      e->Clear();
}
Пример #7
0
int Edits::load_edit(FileXML *file, int64_t &startproject, int track_offset)
{
	Edit* current;

	current = append_new_edit();

	current->load_properties(file, startproject);

	startproject += current->length;

	int result = 0;

	do{
		result = file->read_tag();

		if(!result)
		{
			if(file->tag.title_is("NESTED_EDL"))
			{
				char path[BCTEXTLEN];
				path[0] = 0;
				file->tag.get_property("SRC", path);

//printf("Edits::load_edit %d path=%s\n", __LINE__, path);

				if(path[0] != 0)
				{
					current->nested_edl = edl->nested_edls->get(path);
				}
// printf("Edits::load_edit %d nested_edl->path=%s\n", 
// __LINE__, 
// current->nested_edl->path);
			}
			else
			if(file->tag.title_is("FILE"))
			{
				char filename[BCTEXTLEN];
				filename[0] = 0;
				file->tag.get_property("SRC", filename);
// Extend path
				if(filename[0] != 0)
				{
					char directory[BCTEXTLEN], edl_directory[BCTEXTLEN];
					FileSystem fs;
					fs.set_current_dir("");
					fs.extract_dir(directory, filename);
					if(!strlen(directory))
					{
						fs.extract_dir(edl_directory, file->filename);
						fs.join_names(directory, edl_directory, filename);
						strcpy(filename, directory);
					}
					current->asset = edl->assets->get_asset(filename);
				}
				else
				{
					current->asset = 0;
				}
//printf("Edits::load_edit 5\n");
			}
			else
			if(file->tag.title_is("TRANSITION"))
			{
				current->transition = new Transition(edl,
					current, 
					"",
					track->to_units(edl->session->default_transition_length, 1));
				current->transition->load_xml(file);
			}
			else
			if(file->tag.title_is("/EDIT"))
			{
				result = 1;
			}
		}
	}while(!result);

//printf("Edits::load_edit %d\n", __LINE__);
//track->dump();
//printf("Edits::load_edit %d\n", __LINE__);
	return 0;
}
Пример #8
0
LRESULT CALLBACK 
Edit::SubClassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  Edit *iam = (Edit *)GetWindowLong(hwnd, GWL_USERDATA);

  switch (msg) 
  { 
    case WM_GETDLGCODE:
      return CallWindowProc(iam->wndproc, hwnd, msg, wParam, lParam) | DLGC_WANTALLKEYS;

    case WM_KILLFOCUS:
      if (iam->editing)
      {
        if (iam->read_value())
        {
          iam->write_value();
          SendMessage(iam->dlg, WM_COMMAND, MAKEWPARAM(iam->item, CB_ENTER), 0); 
        }
        else
        {
          iam->restore_value();
          iam->write_value();
          MessageBox(0, iam->incorrect_value(), "Error", MB_ICONEXCLAMATION | MB_OK);
        }
        iam->editing = false;
      }
      break;

    case WM_KEYDOWN: 
      if (!iam->editing)
      {
        iam->backup_value();
        iam->editing = true;
      } 

      if (iam->editing && wParam == VK_RETURN)
      {
        if (iam->read_value())
        {
          iam->editing = false;
          SendMessage(iam->dlg, WM_COMMAND, MAKEWPARAM(iam->item, CB_ENTER), 0); 
        }
        else
          MessageBox(0, iam->incorrect_value(), "Error", MB_ICONEXCLAMATION | MB_OK);
        return 0; 
      }

      if (iam->editing && wParam == VK_ESCAPE)
      {
        iam->restore_value();
        iam->write_value();
        iam->editing = false;
        return 0;
      }

      break;
                            
    case WM_KEYUP: 
    case WM_CHAR: 
      switch (wParam) 
      { 
        case VK_RETURN: 
        case VK_ESCAPE: 
          return 0; 
      }
      break;

  } // switch  (msg)

  // Call the original window procedure for default processing. 
  return CallWindowProc(iam->wndproc, hwnd, msg, wParam, lParam); 
}
Пример #9
0
Edit::Edit(const Edit &copy) : QObject(copy.parent())
{
	this->localVersion = copy.localVersion;
	this->patches = copy.patches;
}
Пример #10
0
int Edits::optimize()
{
	int result = 1;
	Edit *current;


//printf("Edits::optimize %d\n", __LINE__);
// Sort edits by starting point
	while(result)
	{
		result = 0;
		
		for(current = first; current; current = NEXT)
		{
			Edit *next_edit = NEXT;
			
			if(next_edit && next_edit->startproject < current->startproject)
			{
				swap(next_edit, current);
				result = 1;
			}
		}
	}

// Insert silence between edits which aren't consecutive
	for(current = last; current; current = current->previous)
	{
		if(current->previous)
		{
			Edit *previous_edit = current->previous;
			if(current->startproject - 
				previous_edit->startproject -
				previous_edit->length > 0)
			{
				Edit *new_edit = create_edit();
				insert_before(current, new_edit);
				new_edit->startproject = previous_edit->startproject + previous_edit->length;
				new_edit->length = current->startproject - 
					previous_edit->startproject -
					previous_edit->length;
			}
		}
		else
		if(current->startproject > 0)
		{
			Edit *new_edit = create_edit();
			insert_before(current, new_edit);
			new_edit->length = current->startproject;
		}
	}

	result = 1;
	while(result)
	{
		result = 0;


// delete 0 length edits
		for(current = first; 
			current && !result; )
		{
			if(current->length == 0)
			{
				Edit* next = current->next;
				delete current;
				result = 1;
				current = next;
			}
			else
				current = current->next;
		}

//printf("Edits::optimize %d result=%d\n", __LINE__, result);
// merge same files or transitions
		for(current = first; 
			current && current->next && !result; )
		{
			Edit *next_edit = current->next;

// printf("Edits::optimize %d %lld=%lld %d=%d %p=%p %p=%p\n", 
// __LINE__,
// current->startsource + current->length,
// next_edit->startsource,
// current->channel,
// next_edit->channel,
// current->asset,
// next_edit->asset,
// current->nested_edl,
// next_edit->nested_edl);


	   		if(
// both edits are silence & not a plugin
				(current->silence() && next_edit->silence() && !current->is_plugin) ||
				(current->startsource + current->length == next_edit->startsource &&
// source channels are identical
	       		current->channel == next_edit->channel &&
// assets are identical
				current->asset == next_edit->asset && 
    		   	current->nested_edl == next_edit->nested_edl))
			{
//printf("Edits::optimize %d\n", __LINE__);
        		current->length += next_edit->length;
        		remove(next_edit);
        		result = 1;
        	}

    		current = current->next;
		}

// delete last edit of 0 length or silence
		if(last && 
			(last->silence() || 
			!last->length))
		{
			delete last;
			result = 1;
		}
	}

//track->dump();
	return 0;
}
Пример #11
0
    Alignment Filter::depth_filter(Alignment& aln){
        if (use_avg && window_length != 0){

        }
        else if (use_avg != 0){

        }
        else{

        }

        Path path = aln.path();
        //TODO handle reversing mappings
        vector<int>* qual_window;
        if (window_length > 0){
            qual_window = new vector<int>();
        }

        for (int i = 0; i < path.mapping_size(); i++){
            Mapping mapping = path.mapping(i);
            Position start_pos = mapping.position();
            int64_t start_node = start_pos.node_id();
            int64_t start_offset = start_pos.offset();
            int64_t curr_offset_in_graph = 0;
            int64_t curr_offset_in_alignment = 0;
            stringstream pst;

            pst << start_node << "_" << curr_offset_in_graph;
            string p_hash = pst.str();
            for (int j = 0; j < mapping.edit_size(); j++){
                Edit ee = mapping.edit(j);
                if (ee.from_length() == ee.to_length() && ee.sequence() == ""){
                    if (!filter_matches){
                        continue;
                    }
                }
                stringstream est;
                est <<  ee.from_length() << "_" << ee.to_length() << "_" + ee.sequence();
                string e_hash = est.str();
#pragma omp critical(write)
                pos_to_edit_to_depth[p_hash][e_hash] += 1;
                /**
                 * If an edit fails the filter, either return a new empty alignment
                 * OR
                 * return a new alignment identical to the old one EXCEPT where
                 * the offending edit has been replaced by a match to the reference.
                 */
                if (pos_to_edit_to_depth[p_hash][e_hash] < min_depth){
                    if (!remove_failing_edits){
                        return inverse ? aln : Alignment();
                    }

                    else {
                        Alignment edited_aln = Alignment(aln);
                        edited_aln.mutable_path()->mutable_mapping(i)->mutable_edit(j)->set_sequence("");
                        edited_aln.mutable_path()->mutable_mapping(i)->mutable_edit(j)->set_from_length(ee.from_length());
                        edited_aln.mutable_path()->mutable_mapping(i)->mutable_edit(j)->set_to_length(ee.from_length());
                        return edited_aln;
                    }
                }
            }
            return inverse ? Alignment() : aln;
        }


    }
Пример #12
0
bool edit_is_sub(const Edit& e) {
    return e.from_length() == e.to_length() && !e.sequence().empty();
}
Пример #13
0
bool edit_is_deletion(const Edit& e) {
    return e.from_length() > 0 && e.to_length() == 0;
}
void ChannelCombinationInterface::__ChannelId_GetFocus( Control& sender )
{
   Edit* e = dynamic_cast<Edit*>( &sender );
   if ( e != 0 && e->Text() == AUTO_ID )
      e->Clear();
}
Пример #15
0
void Aligner::gssw_mapping_to_alignment(gssw_graph* graph,
                                        gssw_graph_mapping* gm,
                                        Alignment& alignment,
                                        bool print_score_matrices) {
    alignment.clear_path();
    alignment.set_score(gm->score);
    alignment.set_query_position(0);
    Path* path = alignment.mutable_path();
    //alignment.set_cigar(graph_cigar(gm));

    gssw_graph_cigar* gc = &gm->cigar;
    gssw_node_cigar* nc = gc->elements;
    int to_pos = 0;
    int from_pos = gm->position;
    //cerr << "gm->position " << gm->position << endl;
    string& to_seq = *alignment.mutable_sequence();
    //cerr << "-------------" << endl;

    if (print_score_matrices) {
        gssw_graph_print_score_matrices(graph, to_seq.c_str(), to_seq.size(), stderr);
        //cerr << alignment.DebugString() << endl;
    }

    for (int i = 0; i < gc->length; ++i, ++nc) {

        if (i > 0) from_pos = 0; // reset for each node after the first
        // check that the current alignment has a non-zero length
        gssw_cigar* c = nc->cigar;
        int l = c->length;
        if (l == 0) continue;
        gssw_cigar_element* e = c->elements;

        Node* from_node = (Node*) nc->node->data;
        string& from_seq = *from_node->mutable_sequence();
        Mapping* mapping = path->add_mapping();
        mapping->mutable_position()->set_node_id(nc->node->id);
        mapping->mutable_position()->set_offset(from_pos);
        mapping->set_rank(path->mapping_size());

        //cerr << from_node->id() << ":" << endl;

        for (int j=0; j < l; ++j, ++e) {
            Edit* edit;
            int32_t length = e->length;
            //cerr << e->length << e->type << endl;

            switch (e->type) {
            case 'M':
            case 'X':
            case 'N': {
                // do the sequences match?
                // emit a stream of "SNPs" and matches
                int h = from_pos;
                int last_start = from_pos;
                int k = to_pos;
                for ( ; h < from_pos + length; ++h, ++k) {
                    //cerr << h << ":" << k << " " << from_seq[h] << " " << to_seq[k] << endl;
                    if (from_seq[h] != to_seq[k]) {
                        // emit the last "match" region
                        if (h-last_start > 0) {
                            edit = mapping->add_edit();
                            edit->set_from_length(h-last_start);
                            edit->set_to_length(h-last_start);
                        }
                        // set up the SNP
                        edit = mapping->add_edit();
                        edit->set_from_length(1);
                        edit->set_to_length(1);
                        edit->set_sequence(to_seq.substr(k,1));
                        last_start = h+1;
                    }
                }
                // handles the match at the end or the case of no SNP
                if (h-last_start > 0) {
                    edit = mapping->add_edit();
                    edit->set_from_length(h-last_start);
                    edit->set_to_length(h-last_start);
                }
                to_pos += length;
                from_pos += length;
            }
            break;
            case 'D':
                edit = mapping->add_edit();
                edit->set_from_length(length);
                edit->set_to_length(0);
                from_pos += length;
                break;
            case 'I':
                edit = mapping->add_edit();
                edit->set_from_length(0);
                edit->set_to_length(length);
                edit->set_sequence(to_seq.substr(to_pos, length));
                to_pos += length;
                break;
            case 'S':
                // note that soft clips and insertions are semantically equivalent
                // and can only be differentiated by their position in the read
                // with soft clips coming at the start or end
                edit = mapping->add_edit();
                edit->set_from_length(0);
                edit->set_to_length(length);
                edit->set_sequence(to_seq.substr(to_pos, length));
                to_pos += length;
                break;
            default:
                cerr << "error:[Aligner::gssw_mapping_to_alignment] "
                     << "unsupported cigar op type " << e->type << endl;
                exit(1);
                break;

            }

        }
        //cerr << "path to_length " << path_to_length(*path) << endl;
    }

    // set identity
    alignment.set_identity(identity(alignment.path()));
}
Пример #16
0
vector<Edit> Sampler::mutate_edit(const Edit& edit,
                                  const pos_t& position,
                                  double base_error,
                                  double indel_error,
                                  const string& bases,
                                  uniform_real_distribution<double>& rprob,
                                  uniform_int_distribution<int>& rbase) {

    // we will build up a mapping representing the modified edit
    Mapping new_mapping;
    //*new_mapping.mutable_position() = make_position(position);
    // determine to-length of edit
    size_t to_length = edit.to_length();
    // we will keep track of the current base using this
    pos_t curr_pos = position;
    /// TODO we should punt if we aren't a pure edit
    // as in, we are something with mixed to and from lengths; like a block sub with an indel
    if (edit_is_match(edit) || edit_is_sub(edit)
        || edit_is_insertion(edit)) {
        // distribute mutations across this length
        for (size_t k = 0; k < to_length; ++k) {
            char c = 'N'; // in the case that we are in an insertion
            if (!edit_is_insertion(edit)) {
                c = pos_char(curr_pos);
                ++get_offset(curr_pos);
            }
            if (rprob(rng) <= base_error) {
                // pick another base than what c is
                char n;
                do {
                    n = bases[rbase(rng)];
                } while (n == c);
                // make the edit for the sub
                Edit* e = new_mapping.add_edit();
                string s(1, n);
                e->set_sequence(s);
                e->set_from_length(1);
                e->set_to_length(1);
            // if we've got a indel
            // note that we're using a simple geometric indel dsitribution here
            } else if (rprob(rng) <= indel_error) {
                if (rprob(rng) < 0.5) {
                    char n = bases[rbase(rng)];
                    Edit* e = new_mapping.add_edit();
                    string s(1, c);
                    e->set_sequence(s);
                    e->set_to_length(1);
                } else {
                    Edit* e = new_mapping.add_edit();
                    e->set_from_length(1);
                }
            } else {
                // make the edit for the 1bp match
                Edit* e = new_mapping.add_edit();
                e->set_from_length(1);
                e->set_to_length(1);
            }

        }
    } else if (edit_is_deletion(edit)) {
        // special case: 0 (deletion)
        // maybe we do nothing; as there is no length in the read
    }
    // simplify the mapping
    new_mapping = simplify(new_mapping);
    // copy the new edits
    vector<Edit> new_edits;
    for (size_t i = 0; i < new_mapping.edit_size(); ++i) {
        new_edits.push_back(new_mapping.edit(i));
    }
    // and send them back
    return new_edits;
}
Пример #17
0
void Aligner::align_internal(Alignment& alignment, vector<Alignment>* multi_alignments, Graph& g,
                             int64_t pinned_node_id, bool pin_left, int32_t max_alt_alns, bool print_score_matrices) {

    // check input integrity
    if (pin_left && !pinned_node_id) {
        cerr << "error:[Aligner] cannot choose pinned end in non-pinned alignment" << endl;
        exit(EXIT_FAILURE);
    }
    if (multi_alignments && !pinned_node_id) {
        cerr << "error:[Aligner] multiple traceback is not valid in local alignment, only pinned and global" << endl;
        exit(EXIT_FAILURE);
    }
    if (!(multi_alignments) && max_alt_alns != 1) {
        cerr << "error:[Aligner] cannot specify maximum number of alignments in single alignment" << endl;
        exit(EXIT_FAILURE);
    }


    // alignment pinning algorithm is based on pinning in bottom right corner, if pinning in top
    // left we need to reverse all the sequences first and translate the alignment back later

    // create reversed objects if necessary
    Graph reversed_graph;
    string reversed_sequence;
    if (pin_left) {
        reversed_sequence.resize(alignment.sequence().length());

        reverse_copy(alignment.sequence().begin(), alignment.sequence().end(), reversed_sequence.begin());
        reverse_graph(g, reversed_graph);
    }

    // choose forward or reversed objects
    Graph* align_graph;
    string* align_sequence;
    if (pin_left) {
        align_graph = &reversed_graph;
        align_sequence = &reversed_sequence;
    }
    else {
        align_graph = &g;
        align_sequence = alignment.mutable_sequence();
    }

    // convert into gssw graph and get the counterpart to pinned node (if pinning)
    gssw_node* pinned_node = nullptr;
    gssw_graph* graph = create_gssw_graph(*align_graph, pinned_node_id, &pinned_node);

    if (pinned_node_id & !pinned_node) {
        cerr << "error:[Aligner] pinned node for pinned alignment is not in graph" << endl;
        exit(EXIT_FAILURE);
    }

    // perform dynamic programming
    gssw_graph_fill(graph, (*align_sequence).c_str(),
                    nt_table, score_matrix,
                    gap_open, gap_extension, 15, 2);

    // traceback either from pinned position or optimal local alignment
    if (pinned_node) {
        // trace back pinned alignment
        gssw_graph_mapping** gms = gssw_graph_trace_back_pinned_multi (graph,
                                   pinned_node,
                                   max_alt_alns,
                                   (*align_sequence).c_str(),
                                   (*align_sequence).size(),
                                   nt_table,
                                   score_matrix,
                                   gap_open,
                                   gap_extension);

        if (pin_left) {
            // translate graph and mappings into original node space
            unreverse_graph(reversed_graph);
            for (int32_t i = 0; i < max_alt_alns; i++) {
                unreverse_graph_mapping(gms[i]);
            }
        }

        // convert optimal alignment and store it in the input Alignment object (in the multi alignment,
        // this will have been set to the first in the vector)
        if (gms[0]->score > 0) {
            // have a mapping, can just convert normally
            gssw_mapping_to_alignment(graph, gms[0], alignment, print_score_matrices);
        }
        else {
            // gssw will not identify mappings with 0 score, infer location based on pinning

            Mapping* mapping = alignment.mutable_path()->add_mapping();
            mapping->set_rank(1);

            // locate at the end of the node
            Position* position = mapping->mutable_position();
            position->set_node_id(pinned_node_id);
            position->set_offset(pin_left ? 0 : pinned_node->len);

            // soft clip
            Edit* edit = mapping->add_edit();
            edit->set_to_length(alignment.sequence().length());
            edit->set_sequence(alignment.sequence());
        }


        if (multi_alignments) {
            // determine how many non-null alignments were returned
            int32_t num_non_null = max_alt_alns;
            for (int32_t i = 1; i < max_alt_alns; i++) {
                if (gms[i]->score <= 0) {
                    num_non_null = i;
                    break;
                }
            }

            // reserve to avoid illegal access errors that occur when the vector reallocates
            multi_alignments->reserve(num_non_null);

            // copy the primary alignment
            multi_alignments->emplace_back(alignment);

            // convert the alternate alignments and store them at the back of the vector (this will not
            // execute if we are doing single alignment)
            for (int32_t i = 1; i < num_non_null; i++) {
                gssw_graph_mapping* gm = gms[i];

                // make new alignment object
                multi_alignments->emplace_back();
                Alignment& next_alignment = multi_alignments->back();

                // copy over sequence information from the primary alignment
                next_alignment.set_sequence(alignment.sequence());
                next_alignment.set_quality(alignment.quality());

                // get path of the alternate alignment
                gssw_mapping_to_alignment(graph, gm, next_alignment, print_score_matrices);

            }
        }

        for (int32_t i = 0; i < max_alt_alns; i++) {
            gssw_graph_mapping_destroy(gms[i]);
        }
        free(gms);
    }
    else {
        // trace back local alignment
        gssw_graph_mapping* gm = gssw_graph_trace_back (graph,
                                 (*align_sequence).c_str(),
                                 (*align_sequence).size(),
                                 nt_table,
                                 score_matrix,
                                 gap_open,
                                 gap_extension);

        gssw_mapping_to_alignment(graph, gm, alignment, print_score_matrices);
        gssw_graph_mapping_destroy(gm);
    }

    //gssw_graph_print_score_matrices(graph, sequence.c_str(), sequence.size(), stderr);

    gssw_graph_destroy(graph);

}
Пример #18
0
void Pileups::compute_from_edit(NodePileup& pileup, int64_t& node_offset,
                                int64_t& read_offset,
                                const Node& node, const Alignment& alignment,
                                const Mapping& mapping, const Edit& edit) {
    string seq = edit.sequence();
    bool is_reverse = mapping.position().is_reverse();
    
    // ***** MATCH *****
    if (edit.from_length() == edit.to_length()) {
        assert (edit.from_length() > 0);
        make_match(seq, edit.from_length(), is_reverse);
        assert(seq.length() == edit.from_length());            
        int64_t delta = 1;
        for (int64_t i = 0; i < edit.from_length(); ++i) {
            BasePileup* base_pileup = get_create_base_pileup(pileup, node_offset);
            // reference_base if empty
            if (base_pileup->num_bases() == 0) {
                base_pileup->set_ref_base(node.sequence()[node_offset]);
            } else {
                assert(base_pileup->ref_base() == node.sequence()[node_offset]);
            }
            // add base to bases field (converting to ,. if match)
            char base = seq[i];
            if (!edit.sequence().empty() &&
                base_equal(seq[i], node.sequence()[node_offset], is_reverse)) {
                base = is_reverse ? ',' : '.';
            }
            *base_pileup->mutable_bases() += base;
            // add quality if there
            if (!alignment.quality().empty()) {
                *base_pileup->mutable_qualities() += alignment.quality()[read_offset];
            }
            // pileup size increases by 1
            base_pileup->set_num_bases(base_pileup->num_bases() + 1);
            // move right along read, and left/right depending on strand on reference
            node_offset += delta;
            ++read_offset;
        }
    }
    // ***** INSERT *****
    else if (edit.from_length() < edit.to_length()) {
        make_insert(seq, is_reverse);
        assert(edit.from_length() == 0);
        // we define insert (like sam) as insertion between current and next
        // position (on forward node coordinates). this means an insertion before
        // offset 0 is invalid! 
        int64_t insert_offset =  is_reverse ? node_offset : node_offset - 1;
        if (insert_offset >= 0) {        
            BasePileup* base_pileup = get_create_base_pileup(pileup, insert_offset);
            // reference_base if empty
            if (base_pileup->num_bases() == 0) {
                base_pileup->set_ref_base(node.sequence()[insert_offset]);
            } else {
                assert(base_pileup->ref_base() == node.sequence()[insert_offset]);
            }
            // add insertion string to bases field
            // todo: should we reverse complement this if mapping is reversed ??? 
            base_pileup->mutable_bases()->append(seq);
            if (!alignment.quality().empty()) {
                *base_pileup->mutable_qualities() += alignment.quality()[read_offset];
            }
            // pileup size increases by 1
            base_pileup->set_num_bases(base_pileup->num_bases() + 1);
        }
        else {
            // todo: need to either forget about these, or extend pileup format.
            // easy solution: change insert to come before position, and just add
            // optional pileup at n+1st base of node.  would like to figure out
            // how samtools does it first...
            /*
            stringstream ss;
            ss << "Warning: pileup does not support insertions before 0th base in node."
               << " Offending edit: " << pb2json(edit) << endl;
#pragma omp critical(cerr)
            cerr << ss.str();
            */
        }
        // move right along read (and stay put on reference)
        read_offset += edit.to_length();
    }
    // ***** DELETE *****
    else {
        assert(edit.to_length() == 0);
        assert(edit.sequence().empty());
        int64_t del_start = !is_reverse ? node_offset :
            node_offset - edit.from_length() + 1;
        seq = node.sequence().substr(del_start, edit.from_length());
        make_delete(seq, is_reverse);
        BasePileup* base_pileup = get_create_base_pileup(pileup, node_offset);
        // reference_base if empty
        if (base_pileup->num_bases() == 0) {
            base_pileup->set_ref_base(node.sequence()[node_offset]);
        } else {
            assert(base_pileup->ref_base() == node.sequence()[node_offset]);
        }
        // add deletion string to bases field
        // todo: should we reverse complement this if mapping is reversed ??? 
        base_pileup->mutable_bases()->append(seq);
        if (!alignment.quality().empty()) {
            *base_pileup->mutable_qualities() += alignment.quality()[read_offset];
        }
        // pileup size increases by 1
        base_pileup->set_num_bases(base_pileup->num_bases() + 1);
        int64_t delta = edit.from_length();
        // stay put on read, move left/right depending on strand on reference
        node_offset += delta;
    }
}
Пример #19
0
void Tracks::move_edits(ArrayList<Edit*> *edits, 
	Track *track,
	double position,
	int edit_labels,  // Ignored
	int edit_plugins,  // Ignored
	int edit_autos) // Ignored
{
//printf("Tracks::move_edits 1\n");
	for(Track *dest_track = track; dest_track; dest_track = dest_track->next)
	{
		if(dest_track->record)
		{
// Need a local copy of the source edit since the original source edit may
// change in the editing operation.
			Edit *source_edit = 0;
			Track *source_track = 0;


// Get source track
			if(dest_track->data_type == TRACK_AUDIO)
			{
				int current_aedit = 0;

				while(current_aedit < edits->total &&
					edits->values[current_aedit]->track->data_type != TRACK_AUDIO)
					current_aedit++;

				if(current_aedit < edits->total)
				{
					source_edit = edits->values[current_aedit];
					source_track = source_edit->track;
					edits->remove_number(current_aedit);
				}
			}
			else
			if(dest_track->data_type == TRACK_VIDEO)
			{
				int current_vedit = 0;
				while(current_vedit < edits->total &&
					edits->values[current_vedit]->track->data_type != TRACK_VIDEO)
					current_vedit++;

				if(current_vedit < edits->total)
				{
					source_edit = edits->values[current_vedit];
					source_track = source_edit->track;
					edits->remove_number(current_vedit);
				}
			}

//printf("Tracks::move_edits 2 %s %s %d\n", source_track->title, dest_track->title, source_edit->length);
			if(source_edit)
			{
// Copy keyframes
				FileXML temp;
				AutoConf temp_autoconf;
				int64_t position_i = source_track->to_units(position, 0);
// Source edit changes
				int64_t source_length = source_edit->length;

				temp_autoconf.set_all(1);

				source_track->automation->copy(source_edit->startproject, 
					source_edit->startproject + source_edit->length, 
					&temp, 
					0,
					1);
				temp.terminate_string();
				temp.rewind();
// Insert new keyframes
//printf("Tracks::move_edits 2 %d %p\n", result->startproject, result->asset);
				source_track->automation->clear(source_edit->startproject,
					source_edit->startproject + source_edit->length, 
					&temp_autoconf,
					1);
				int64_t position_a = position_i;
				if (dest_track == source_track)
                {
                    if (position_a > source_edit->startproject)
                            position_a -= source_length;
                }	        

				dest_track->automation->paste_silence(position_a, 
					position_a + source_length);
				while(!temp.read_tag())
					dest_track->automation->paste(position_a, 
						source_length, 
						1.0, 
						&temp, 
						0,
						1,
						&temp_autoconf);



// Insert new edit
				Edit *dest_edit = dest_track->edits->shift(position_i, 
					source_length);
				Edit *result = dest_track->edits->insert_before(dest_edit, 
					new Edit(edl, dest_track));
				result->copy_from(source_edit);
				result->startproject = position_i;
				result->length = source_length;

// Clear source
				source_track->edits->clear(source_edit->startproject, 
					source_edit->startproject + source_length);
				source_track->optimize();
				dest_track->optimize();
			}
		}
	}
}