<commit_before>#include "mapper.hpp"

namespace vg {

Mapper::Mapper(Index* idex)
    : index(idex)
    , best_clusters(0)
    , hit_max(100) {
    kmer_sizes = index->stored_kmer_sizes();
    if (kmer_sizes.empty()) {
        cerr << "error:[vg::Mapper] the index ("
             << index->name << ") does not include kmers" << endl;
        exit(1);
    }
}

Mapper::~Mapper(void) {
    // noop
}

Alignment Mapper::align(string& sequence, int stride) {
    Alignment alignment;
    alignment.set_sequence(sequence);
    return align_threaded(alignment, stride);
}

Alignment& Mapper::align_threaded(Alignment& alignment, int stride) {

    // parameters, some of which should probably be modifiable
    // TODO -- move to Mapper object

    if (index == NULL) {
        cerr << "error:[vg::Mapper] no index loaded, cannot map alignment!" << endl;
        exit(1);
    }

    // establish kmers

    const string& sequence = alignment.sequence();
    auto kmers = kmers_of(sequence, stride);

    vector<map<int64_t, set<int32_t> > > positions(kmers.size());
    int i = 0;
    for (auto& k : kmers) {
        index->get_kmer_positions(k, positions.at(i));
        if (positions.at(i).size() > hit_max) positions.at(i).clear();
        ++i;
    }

    // make threads
    // these start whenever we have a kmer match which is outside of
    // one of the last positions (for the previous kmer) + the kmer stride % wobble (hmm)

    map<int64_t, vector<int> > node_kmer_order;
    map<pair<int64_t, int32_t>, vector<int64_t> > position_threads;
    map<int64_t, vector<int64_t> > node_threads;
    //int node_wobble = 0; // turned off...
    int position_wobble = 2;
    int kmer_size = *kmer_sizes.begin(); // for simplicity, use the first available kmer size

    int max_iter = sequence.size();
    int iter = 0;
    int context_step = 1;
    int64_t max_subgraph_size = 0;
    int max_thread_gap = 30; // counted in nodes

    i = 0;
    for (auto& p : positions) {
        auto& kmer = kmers.at(i++);
        for (auto& x : p) {
            int64_t id = x.first;
            set<int32_t>& pos = x.second;
            node_kmer_order[id].push_back(i-1);
            for (auto& y : pos) {
                //cerr << kmer << "\t" << i << "\t" << id << "\t" << y << endl;
                // thread rules
                // if we find the previous position
                int m = 0;
                vector<int64_t> thread;
                for (int j = 0; j < 2*position_wobble + 1; ++j) {
                    if (j == 0) { // on point
                    } else if (j % 2 == 0) { // subtract
                        m *= -1;
                    } else { // add
                        m *= -1; ++m;
                    }
                    //cerr << "checking " << id << " " << y << " - " << kmer_size << " + " << m << endl;
                    auto previous = position_threads.find(make_pair(id, y - stride + m));
                    if (previous != position_threads.end()) {
                        //length = position_threads[make_pair(id, y - stride + m)] + 1;
                        thread = previous->second;
                        position_threads.erase(previous);
                        //cerr << "thread is " << thread.size() << " long" << endl;
                        break;
                    }
                }

                thread.push_back(id);
                position_threads[make_pair(id, y)] = thread;
                node_threads[id] = thread;
            }
        }
    }

    map<int, vector<vector<int64_t> > > threads_by_length;
    for (auto& t : node_threads) {
        auto& thread = t.second;
        auto& threads = threads_by_length[thread.size()];
        threads.push_back(thread);
    }

    // now sort the threads and re-cluster them

    // for debugging
    /*
    for (auto& t : threads_by_length) {
        auto& length = t.first;
        auto& threads = t.second;
        cerr << length << ":" << endl;
        for (auto& thread : threads) {
            cerr << "\t";
            for (auto& id : thread) {
                cerr << id << " ";
            }
            cerr << endl;
        }
        cerr << endl;
    }
    */

    // sort threads by ids
    // if they are at least 2 hits long
    set<vector<int64_t> > sorted_threads;
    auto tl = threads_by_length.rbegin();
    for (auto& t : node_threads) {
        auto& thread = t.second;
        // if you use very short kmers, this may become necessary
        //if (thread.size() > 1) {
        sorted_threads.insert(thread);
        //}
    }
    // clean up
    threads_by_length.clear();

    // go back through and combine closely-linked threads
    // ... but only if their kmer order is proper
    map<int64_t, vector<int64_t> > threads_by_last;
    for (auto& thread : sorted_threads) {
        //cerr << thread.front() << "-" << thread.back() << endl;
        auto prev = threads_by_last.upper_bound(thread.front()-max_thread_gap);
        //if (prev != threads_by_last.begin()) --prev;
        // now we should be at the highest thread within the bounds
        //cerr << prev->first << " " << thread.front() << endl;
        // todo: it may also make sense to check that the kmer order makes sense
        // what does this mean? it means that the previous
        if (prev != threads_by_last.end()
            && prev->first > thread.front() - max_thread_gap) {
            vector<int64_t> new_thread;
            auto& prev_thread = prev->second;
            new_thread.reserve(prev_thread.size() + thread.size());
            new_thread.insert(new_thread.end(), prev_thread.begin(), prev_thread.end());
            new_thread.insert(new_thread.end(), thread.begin(), thread.end());
            threads_by_last.erase(prev);
            // this will clobber... not good
            // maybe overwrite only if longer?
            threads_by_last[new_thread.back()] = new_thread;
        } else {
            threads_by_last[thread.back()] = thread;
        }
    }

    // debugging
    /*
    for (auto& t : threads_by_last) {
        auto& thread = t.second;
        cerr << t.first << "\t";
        for (auto& id : thread) {
            cerr << id << " ";
        }
        cerr << endl;
    }
    */

    // rebuild our threads_by_length set
    for (auto& t : threads_by_last) {
        auto& thread = t.second;
        auto& threads = threads_by_length[thread.size()];
        threads.push_back(thread);
    }

    // collect the nodes from the best N threads by length
    // and expand subgraphs as before
    VG* graph = new VG;
    tl = threads_by_length.rbegin();
    for (int i = 0; tl != threads_by_length.rend() && (best_clusters == 0 || i < best_clusters); ++i, ++tl) {
        auto& threads = tl->second;
        for (auto& thread : threads) {
            VG g;
            set<int64_t> nodes;
            for (auto& id : thread) {
                if (!nodes.count(id)) {
                    nodes.insert(id);
                    index->get_context(id, g);
                }
            }
            // by definition, our thread should construct a contiguous graph
            // however, it might not due to complexities of thread determination
            // so, enforce this here
            list<VG> subgraphs;
            int c = 0;
            do {
                subgraphs.clear();
                index->expand_context(g, 1);
                // to find the disjoint subgraphs we need a complete graph (no orphan edges)
                // so we make a temporary copy of the graph
                VG gprime = g;
                index->get_connected_nodes(gprime);
                gprime.disjoint_subgraphs(subgraphs);
            } while(subgraphs.size() > 1 && c++ < max_thread_gap);
            // now that we have a completed graph for our thread, save it
            graph->extend(g);
        }
    }

    auto get_max_subgraph_size = [this, &max_subgraph_size, &graph]() {
        list<VG> subgraphs;
        graph->disjoint_subgraphs(subgraphs);
        for (auto& subgraph : subgraphs) {
            max_subgraph_size = max(subgraph.total_length_of_nodes(), max_subgraph_size);
        }
    };

    get_max_subgraph_size();
    while (max_subgraph_size < sequence.size()*2 && iter < max_iter) {
        index->expand_context(*graph, context_step);
        index->get_connected_nodes(*graph);
        get_max_subgraph_size();
        ++iter;
    }
    // ensure we have a complete graph prior to alignment
    index->get_connected_nodes(*graph);

    // align, check for soft clipping, and expand context against the target if needed

    graph->align(alignment);

    // check if we start or end with soft clips
    // if so, try to expand the graph until we don't have any more (or we hit a threshold)

    int sc_start = softclip_start(alignment);
    int sc_end = softclip_end(alignment);
    //cerr << alignment.score() << " " << sc_start << " " << sc_end << endl;

    // NB it will probably be faster here to not query the DB again,
    // but instead to grow the matching graph in the right direction
    if (sc_start > 0 || sc_end > 0) {
        // get the target graph
        delete graph;
        graph = new VG;
        // nodes
        Path* path = alignment.mutable_path();
        for (int i = 0; i < path->mapping_size(); ++i) {
            index->get_context(path->mutable_mapping(i)->node_id(), *graph);
        }
        while (graph->total_length_of_nodes() < sequence.size() * 2) {
            index->expand_context(*graph, context_step); // expand faster here
        }
        index->get_connected_nodes(*graph);

        /*
        cerr << "graph " << graph->size() << endl;
        ofstream f("vg_align.vg");
        graph->serialize_to_ostream(f);
        f.close();
        */

        alignment.clear_path();
        graph->align(alignment);

    }

    return alignment;

}

int Mapper::softclip_start(Alignment& alignment) {
    if (alignment.mutable_path()->mapping_size() > 0) {
        Path* path = alignment.mutable_path();
        Mapping* first_mapping = path->mutable_mapping(0);
        Edit* first_edit = first_mapping->mutable_edit(0);
        if (first_edit->type() == Edit_Type_SOFTCLIP) {
            return first_edit->length();
        }
    }
    return 0;
}

int Mapper::softclip_end(Alignment& alignment) {
    if (alignment.mutable_path()->mapping_size() > 0) {
        Path* path = alignment.mutable_path();
        Mapping* last_mapping = path->mutable_mapping(path->mapping_size()-1);
        Edit* last_edit = last_mapping->mutable_edit(last_mapping->edit_size()-1);
        if (last_edit->type() == Edit_Type_SOFTCLIP) {
            return last_edit->length();
        }
    }
    return 0;
}

Alignment& Mapper::align_simple(Alignment& alignment, int stride) {

    if (index == NULL) {
        cerr << "error:[vg::Mapper] no index loaded, cannot map alignment!" << endl;
        exit(1);
    }

    // establish kmers

    const string& sequence = alignment.sequence();
    auto kmers = kmers_of(sequence, stride);

    map<string, int32_t> kmer_counts;
    vector<map<int64_t, set<int32_t> > > positions(kmers.size());
    int i = 0;
    for (auto& k : kmers) {
        index->get_kmer_positions(k, positions.at(i++));
        kmer_counts[k] = positions.at(i-1).size();
    }
    positions.clear();
    VG* graph = new VG;
    for (auto& c : kmer_counts) {
        if (c.second < hit_max) {
            index->get_kmer_subgraph(c.first, *graph);
        }
    }

    int max_iter = sequence.size();
    int iter = 0;
    int context_step = 1;
    int64_t max_subgraph_size = 0;

    // use kmers which are informative
    // and build up the graph

    auto get_max_subgraph_size = [this, &max_subgraph_size, &graph]() {
        list<VG> subgraphs;
        graph->disjoint_subgraphs(subgraphs);
        for (auto& subgraph : subgraphs) {
            max_subgraph_size = max(subgraph.total_length_of_nodes(), max_subgraph_size);
        }
    };

    get_max_subgraph_size();

    while (max_subgraph_size < sequence.size()*2 && iter < max_iter) {
        index->expand_context(*graph, context_step);
        index->get_connected_nodes(*graph);
        get_max_subgraph_size();
        ++iter;
    }
    // ensure we have a complete graph prior to alignment
    index->get_connected_nodes(*graph);

    /*
    ofstream f("vg_align.vg");
    graph->serialize_to_ostream(f);
    f.close();
    */

    graph->align(alignment);

    return alignment;

}

vector<string> Mapper::kmers_of(const string& seq, const int stride) {
    vector<string> kmers;
    if (!seq.empty()) {
        for (int kmer_size : kmer_sizes) {
            for (int i = 0; i < seq.size()-kmer_size; i+=stride) {
                kmers.push_back(seq.substr(i,kmer_size));
            }
        }
    }
    return kmers;
}

}
<commit_msg>require at least two consecutive kmer hits to build a thread<commit_after>#include "mapper.hpp"

namespace vg {

Mapper::Mapper(Index* idex)
    : index(idex)
    , best_clusters(0)
    , hit_max(100) {
    kmer_sizes = index->stored_kmer_sizes();
    if (kmer_sizes.empty()) {
        cerr << "error:[vg::Mapper] the index ("
             << index->name << ") does not include kmers" << endl;
        exit(1);
    }
}

Mapper::~Mapper(void) {
    // noop
}

Alignment Mapper::align(string& sequence, int stride) {
    Alignment alignment;
    alignment.set_sequence(sequence);
    return align_threaded(alignment, stride);
}

Alignment& Mapper::align_threaded(Alignment& alignment, int stride) {

    // parameters, some of which should probably be modifiable
    // TODO -- move to Mapper object

    if (index == NULL) {
        cerr << "error:[vg::Mapper] no index loaded, cannot map alignment!" << endl;
        exit(1);
    }

    // establish kmers

    const string& sequence = alignment.sequence();
    auto kmers = kmers_of(sequence, stride);

    vector<map<int64_t, set<int32_t> > > positions(kmers.size());
    int i = 0;
    for (auto& k : kmers) {
        index->get_kmer_positions(k, positions.at(i));
        if (positions.at(i).size() > hit_max) positions.at(i).clear();
        ++i;
    }

    // make threads
    // these start whenever we have a kmer match which is outside of
    // one of the last positions (for the previous kmer) + the kmer stride % wobble (hmm)

    map<int64_t, vector<int> > node_kmer_order;
    map<pair<int64_t, int32_t>, vector<int64_t> > position_threads;
    map<int64_t, vector<int64_t> > node_threads;
    //int node_wobble = 0; // turned off...
    int position_wobble = 2;
    // if kmer size is not specified, pick it up from the index
    int kmer_size = *kmer_sizes.begin(); // for simplicity, use the first available kmer size

    int max_iter = sequence.size();
    int iter = 0;
    int context_step = 1;
    int64_t max_subgraph_size = 0;
    int max_thread_gap = 30; // counted in nodes

    i = 0;
    for (auto& p : positions) {
        auto& kmer = kmers.at(i++);
        for (auto& x : p) {
            int64_t id = x.first;
            set<int32_t>& pos = x.second;
            node_kmer_order[id].push_back(i-1);
            for (auto& y : pos) {
                //cerr << kmer << "\t" << i << "\t" << id << "\t" << y << endl;
                // thread rules
                // if we find the previous position
                int m = 0;
                vector<int64_t> thread;
                for (int j = 0; j < 2*position_wobble + 1; ++j) {
                    if (j == 0) { // on point
                    } else if (j % 2 == 0) { // subtract
                        m *= -1;
                    } else { // add
                        m *= -1; ++m;
                    }
                    //cerr << "checking " << id << " " << y << " - " << kmer_size << " + " << m << endl;
                    auto previous = position_threads.find(make_pair(id, y - stride + m));
                    if (previous != position_threads.end()) {
                        //length = position_threads[make_pair(id, y - stride + m)] + 1;
                        thread = previous->second;
                        position_threads.erase(previous);
                        //cerr << "thread is " << thread.size() << " long" << endl;
                        break;
                    }
                }

                thread.push_back(id);
                position_threads[make_pair(id, y)] = thread;
                node_threads[id] = thread;
            }
        }
    }

    map<int, vector<vector<int64_t> > > threads_by_length;
    for (auto& t : node_threads) {
        auto& thread = t.second;
        auto& threads = threads_by_length[thread.size()];
        threads.push_back(thread);
    }

    // now sort the threads and re-cluster them

    // for debugging
    /*
    for (auto& t : threads_by_length) {
        auto& length = t.first;
        auto& threads = t.second;
        cerr << length << ":" << endl;
        for (auto& thread : threads) {
            cerr << "\t";
            for (auto& id : thread) {
                cerr << id << " ";
            }
            cerr << endl;
        }
        cerr << endl;
    }
    */

    // sort threads by ids
    // if they are at least 2 hits long
    set<vector<int64_t> > sorted_threads;
    auto tl = threads_by_length.rbegin();
    for (auto& t : node_threads) {
        auto& thread = t.second;
        // if you use very short kmers, this may become necessary
        if (thread.size() > 1) {
            sorted_threads.insert(thread);
        }
    }
    // clean up
    threads_by_length.clear();

    // go back through and combine closely-linked threads
    // ... but only if their kmer order is proper
    map<int64_t, vector<int64_t> > threads_by_last;
    for (auto& thread : sorted_threads) {
        //cerr << thread.front() << "-" << thread.back() << endl;
        auto prev = threads_by_last.upper_bound(thread.front()-max_thread_gap);
        //if (prev != threads_by_last.begin()) --prev;
        // now we should be at the highest thread within the bounds
        //cerr << prev->first << " " << thread.front() << endl;
        // todo: it may also make sense to check that the kmer order makes sense
        // what does this mean? it means that the previous
        if (prev != threads_by_last.end()
            && prev->first > thread.front() - max_thread_gap) {
            vector<int64_t> new_thread;
            auto& prev_thread = prev->second;
            new_thread.reserve(prev_thread.size() + thread.size());
            new_thread.insert(new_thread.end(), prev_thread.begin(), prev_thread.end());
            new_thread.insert(new_thread.end(), thread.begin(), thread.end());
            threads_by_last.erase(prev);
            // this will clobber... not good
            // maybe overwrite only if longer?
            threads_by_last[new_thread.back()] = new_thread;
        } else {
            threads_by_last[thread.back()] = thread;
        }
    }

    // debugging
    /*
    for (auto& t : threads_by_last) {
        auto& thread = t.second;
        cerr << t.first << "\t";
        for (auto& id : thread) {
            cerr << id << " ";
        }
        cerr << endl;
    }
    */

    // rebuild our threads_by_length set
    for (auto& t : threads_by_last) {
        auto& thread = t.second;
        auto& threads = threads_by_length[thread.size()];
        threads.push_back(thread);
    }

    // collect the nodes from the best N threads by length
    // and expand subgraphs as before
    VG* graph = new VG;
    tl = threads_by_length.rbegin();
    for (int i = 0; tl != threads_by_length.rend() && (best_clusters == 0 || i < best_clusters); ++i, ++tl) {
        auto& threads = tl->second;
        for (auto& thread : threads) {
            VG g;
            set<int64_t> nodes;
            for (auto& id : thread) {
                if (!nodes.count(id)) {
                    nodes.insert(id);
                    index->get_context(id, g);
                }
            }
            // by definition, our thread should construct a contiguous graph
            // however, it might not due to complexities of thread determination
            // so, enforce this here
            list<VG> subgraphs;
            int c = 0;
            do {
                subgraphs.clear();
                index->expand_context(g, 1);
                // to find the disjoint subgraphs we need a complete graph (no orphan edges)
                // so we make a temporary copy of the graph
                VG gprime = g;
                index->get_connected_nodes(gprime);
                gprime.disjoint_subgraphs(subgraphs);
            } while(subgraphs.size() > 1 && c++ < max_thread_gap);
            // now that we have a completed graph for our thread, save it
            graph->extend(g);
        }
    }

    auto get_max_subgraph_size = [this, &max_subgraph_size, &graph]() {
        list<VG> subgraphs;
        graph->disjoint_subgraphs(subgraphs);
        for (auto& subgraph : subgraphs) {
            max_subgraph_size = max(subgraph.total_length_of_nodes(), max_subgraph_size);
        }
    };

    get_max_subgraph_size();
    while (max_subgraph_size < sequence.size()*2 && iter < max_iter) {
        index->expand_context(*graph, context_step);
        index->get_connected_nodes(*graph);
        get_max_subgraph_size();
        ++iter;
    }
    // ensure we have a complete graph prior to alignment
    index->get_connected_nodes(*graph);

    // align, check for soft clipping, and expand context against the target if needed

    graph->align(alignment);

    // check if we start or end with soft clips
    // if so, try to expand the graph until we don't have any more (or we hit a threshold)

    int sc_start = softclip_start(alignment);
    int sc_end = softclip_end(alignment);
    //cerr << alignment.score() << " " << sc_start << " " << sc_end << endl;

    // NB it will probably be faster here to not query the DB again,
    // but instead to grow the matching graph in the right direction
    if (sc_start > 0 || sc_end > 0) {
        // get the target graph
        delete graph;
        graph = new VG;
        // nodes
        Path* path = alignment.mutable_path();
        for (int i = 0; i < path->mapping_size(); ++i) {
            index->get_context(path->mutable_mapping(i)->node_id(), *graph);
        }
        while (graph->total_length_of_nodes() < sequence.size() * 3) {
            index->expand_context(*graph, context_step); // expand faster here
        }
        index->get_connected_nodes(*graph);

        /*
        cerr << "graph " << graph->size() << endl;
        ofstream f("vg_align.vg");
        graph->serialize_to_ostream(f);
        f.close();
        */

        alignment.clear_path();
        graph->align(alignment);

    }

    return alignment;

}

int Mapper::softclip_start(Alignment& alignment) {
    if (alignment.mutable_path()->mapping_size() > 0) {
        Path* path = alignment.mutable_path();
        Mapping* first_mapping = path->mutable_mapping(0);
        Edit* first_edit = first_mapping->mutable_edit(0);
        if (first_edit->type() == Edit_Type_SOFTCLIP) {
            return first_edit->length();
        }
    }
    return 0;
}

int Mapper::softclip_end(Alignment& alignment) {
    if (alignment.mutable_path()->mapping_size() > 0) {
        Path* path = alignment.mutable_path();
        Mapping* last_mapping = path->mutable_mapping(path->mapping_size()-1);
        Edit* last_edit = last_mapping->mutable_edit(last_mapping->edit_size()-1);
        if (last_edit->type() == Edit_Type_SOFTCLIP) {
            return last_edit->length();
        }
    }
    return 0;
}

Alignment& Mapper::align_simple(Alignment& alignment, int stride) {

    if (index == NULL) {
        cerr << "error:[vg::Mapper] no index loaded, cannot map alignment!" << endl;
        exit(1);
    }

    // establish kmers

    const string& sequence = alignment.sequence();
    auto kmers = kmers_of(sequence, stride);

    map<string, int32_t> kmer_counts;
    vector<map<int64_t, set<int32_t> > > positions(kmers.size());
    int i = 0;
    for (auto& k : kmers) {
        index->get_kmer_positions(k, positions.at(i++));
        kmer_counts[k] = positions.at(i-1).size();
    }
    positions.clear();
    VG* graph = new VG;
    for (auto& c : kmer_counts) {
        if (c.second < hit_max) {
            index->get_kmer_subgraph(c.first, *graph);
        }
    }

    int max_iter = sequence.size();
    int iter = 0;
    int context_step = 1;
    int64_t max_subgraph_size = 0;

    // use kmers which are informative
    // and build up the graph

    auto get_max_subgraph_size = [this, &max_subgraph_size, &graph]() {
        list<VG> subgraphs;
        graph->disjoint_subgraphs(subgraphs);
        for (auto& subgraph : subgraphs) {
            max_subgraph_size = max(subgraph.total_length_of_nodes(), max_subgraph_size);
        }
    };

    get_max_subgraph_size();

    while (max_subgraph_size < sequence.size()*2 && iter < max_iter) {
        index->expand_context(*graph, context_step);
        index->get_connected_nodes(*graph);
        get_max_subgraph_size();
        ++iter;
    }
    // ensure we have a complete graph prior to alignment
    index->get_connected_nodes(*graph);

    /*
    ofstream f("vg_align.vg");
    graph->serialize_to_ostream(f);
    f.close();
    */

    graph->align(alignment);

    return alignment;

}

vector<string> Mapper::kmers_of(const string& seq, const int stride) {
    vector<string> kmers;
    if (!seq.empty()) {
        for (int kmer_size : kmer_sizes) {
            for (int i = 0; i < seq.size()-kmer_size; i+=stride) {
                kmers.push_back(seq.substr(i,kmer_size));
            }
        }
    }
    return kmers;
}

}
<|endoftext|>


<commit_before>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/grappler/costs/virtual_placer.h"
#include "tensorflow/core/framework/node_def.pb.h"
#include "tensorflow/core/grappler/clusters/cluster.h"
#include "tensorflow/core/grappler/devices.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/util/device_name_utils.h"

namespace tensorflow {
namespace grappler {

VirtualPlacer::VirtualPlacer(const Cluster* cluster) {
  CHECK(cluster);
  devices_ = cluster->GetDevices();

  if (devices_.empty()) {
    // If there are no devices in the cluster, add a single device, "UNKNOWN" to
    // the cluster.
    default_device_ = "UNKNOWN";
    DeviceProperties& prop = devices_["UNKNOWN"];
    prop.set_type("UNKNOWN");

  } else {
    default_device_ = devices_.begin()->first;
    VLOG(1) << "Number of devices: " << devices_.size();
    for (const auto& device : devices_) {
      if (str_util::Lowercase(device.first).find("gpu") != string::npos) {
        default_device_ = device.first;
      }
      break;
    }
  }
}

const DeviceProperties& VirtualPlacer::get_device(const NodeDef& node) const {
  string device = get_canonical_device_name(node);
  VLOG(3) << "Device name: " << device;
  auto it = devices_.find(device);
  DCHECK(it != devices_.end());
  return it->second;
}

string VirtualPlacer::get_canonical_device_name(const NodeDef& node) const {
  string device;
  if (!node.device().empty()) {
    if (devices_.find(node.device()) != devices_.end()) {
      return node.device();
    }
    DeviceNameUtils::ParsedName parsed_name;
    bool parsed = DeviceNameUtils::ParseFullName(node.device(), &parsed_name);
    if (!parsed) {
      parsed = DeviceNameUtils::ParseLocalName(node.device(), &parsed_name);
      parsed_name.job = "localhost";
    }
    if (!parsed) {
      if (node.device() == "GPU" || node.device() == "CPU" ||
          node.device() == "gpu" || node.device() == "cpu") {
        parsed_name.job = "localhost";
        parsed_name.type = node.device();
        parsed = true;
      }
    }
    if (!parsed) {
      return get_default_device_name();
    } else {
      device = strings::StrCat(
          "/job:", parsed_name.job, "/replica:", parsed_name.replica,
          "/task:", parsed_name.task, "/",
          str_util::Lowercase(parsed_name.type), ":", parsed_name.id);
    }
  } else {
    return get_default_device_name();
  }
  if (devices_.find(device) == devices_.end()) {
    return get_default_device_name();
  }
  return device;
}

const string& VirtualPlacer::get_default_device_name() const {
  return default_device_;
}

}  // end namespace grappler
}  // end namespace tensorflow
<commit_msg>Fixed a typo<commit_after>/* Copyright 2017 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/grappler/costs/virtual_placer.h"
#include "tensorflow/core/framework/node_def.pb.h"
#include "tensorflow/core/grappler/clusters/cluster.h"
#include "tensorflow/core/grappler/devices.h"
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/core/util/device_name_utils.h"

namespace tensorflow {
namespace grappler {

VirtualPlacer::VirtualPlacer(const Cluster* cluster) {
  CHECK(cluster);
  devices_ = cluster->GetDevices();

  if (devices_.empty()) {
    // If there are no devices in the cluster, add a single device, "UNKNOWN" to
    // the cluster.
    default_device_ = "UNKNOWN";
    DeviceProperties& prop = devices_["UNKNOWN"];
    prop.set_type("UNKNOWN");

  } else {
    default_device_ = devices_.begin()->first;
    VLOG(1) << "Number of devices: " << devices_.size();
    for (const auto& device : devices_) {
      if (str_util::Lowercase(device.first).find("gpu") != string::npos) {
        default_device_ = device.first;
        break;
      }
    }
  }
}

const DeviceProperties& VirtualPlacer::get_device(const NodeDef& node) const {
  string device = get_canonical_device_name(node);
  VLOG(3) << "Device name: " << device;
  auto it = devices_.find(device);
  DCHECK(it != devices_.end());
  return it->second;
}

string VirtualPlacer::get_canonical_device_name(const NodeDef& node) const {
  string device;
  if (!node.device().empty()) {
    if (devices_.find(node.device()) != devices_.end()) {
      return node.device();
    }
    DeviceNameUtils::ParsedName parsed_name;
    bool parsed = DeviceNameUtils::ParseFullName(node.device(), &parsed_name);
    if (!parsed) {
      parsed = DeviceNameUtils::ParseLocalName(node.device(), &parsed_name);
      parsed_name.job = "localhost";
    }
    if (!parsed) {
      if (node.device() == "GPU" || node.device() == "CPU" ||
          node.device() == "gpu" || node.device() == "cpu") {
        parsed_name.job = "localhost";
        parsed_name.type = node.device();
        parsed = true;
      }
    }
    if (!parsed) {
      return get_default_device_name();
    } else {
      device = strings::StrCat(
          "/job:", parsed_name.job, "/replica:", parsed_name.replica,
          "/task:", parsed_name.task, "/",
          str_util::Lowercase(parsed_name.type), ":", parsed_name.id);
    }
  } else {
    return get_default_device_name();
  }
  if (devices_.find(device) == devices_.end()) {
    return get_default_device_name();
  }
  return device;
}

const string& VirtualPlacer::get_default_device_name() const {
  return default_device_;
}

}  // end namespace grappler
}  // end namespace tensorflow
<|endoftext|>


<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes   -----------------------------------
#include <map>

// Local Includes -----------------------------------
#include "libmesh/libmesh_config.h"
#include "libmesh/mesh_base.h"
#include "libmesh/metis_partitioner.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/elem.h"
#include "libmesh/mesh_communication.h"
#include "libmesh/error_vector.h"
#include "libmesh/vectormap.h"

#ifdef LIBMESH_HAVE_METIS
// MIPSPro 7.4.2 gets confused about these nested namespaces
# ifdef __sgi
#  include <cstdarg>
# endif
  namespace Metis {
    extern "C" {
#     include "libmesh/ignore_warnings.h"
#     include "metis.h"
#     include "libmesh/restore_warnings.h"
    }
  }
#else
#  include "libmesh/sfc_partitioner.h"
#endif

namespace libMesh
{

// ------------------------------------------------------------
// MetisPartitioner implementation
void MetisPartitioner::_do_partition (MeshBase& mesh,
				      const unsigned int n_pieces)
{
  libmesh_assert_greater (n_pieces, 0);
  libmesh_assert (mesh.is_serial());

  // Check for an easy return
  if (n_pieces == 1)
    {
      this->single_partition (mesh);
      return;
    }

// What to do if the Metis library IS NOT present
#ifndef LIBMESH_HAVE_METIS

  libmesh_here();
  libMesh::err << "ERROR: The library has been built without"    << std::endl
	        << "Metis support.  Using a space-filling curve"  << std::endl
	        << "partitioner instead!"                         << std::endl;

  SFCPartitioner sfcp;

  sfcp.partition (mesh, n_pieces);

// What to do if the Metis library IS present
#else

  START_LOG("partition()", "MetisPartitioner");

  const dof_id_type n_active_elem = mesh.n_active_elem();

  // build the graph
  // std::vector<int> options(5);
  std::vector<int> vwgt(n_active_elem);
  std::vector<int> part(n_active_elem);

  int
    n = static_cast<int>(n_active_elem),  // number of "nodes" (elements)
                                          //   in the graph
//    wgtflag = 2,                          // weights on vertices only,
//                                          //   none on edges
//    numflag = 0,                          // C-style 0-based numbering
    nparts  = static_cast<int>(n_pieces), // number of subdomains to create
    edgecut = 0;                          // the numbers of edges cut by the
                                          //   resulting partition

  // Set the options
  // options[0] = 0; // use default options

  // Metis will only consider the active elements.
  // We need to map the active element ids into a
  // contiguous range.  Further, we want the unique range indexing to be
  // independednt of the element ordering, otherwise a circular dependency
  // can result in which the partitioning depends on the ordering which
  // depends on the partitioning...
  vectormap<dof_id_type, dof_id_type> global_index_map;
  global_index_map.reserve (n_active_elem);

  {
    std::vector<dof_id_type> global_index;

    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    MeshCommunication().find_global_indices (mesh.comm(),
					     MeshTools::bounding_box(mesh),
					     it, end, global_index);

    libmesh_assert_equal_to (global_index.size(), n_active_elem);

    for (std::size_t cnt=0; it != end; ++it)
      {
	const Elem *elem = *it;

	global_index_map.insert (std::make_pair(elem->id(), global_index[cnt++]));
      }
    libmesh_assert_equal_to (global_index_map.size(), n_active_elem);
  }

  // Invoke METIS, but only on processor 0.
  // Then broadcast the resulting decomposition
  if (mesh.processor_id() == 0)
    {
      std::vector<int> xadj, adjncy;

      // Local scope for these
      {
	// build the graph in CSR format.  Note that
	// the edges in the graph will correspond to
	// face neighbors
	std::vector<const Elem*> neighbors_offspring;

	MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
	const MeshBase::element_iterator elem_end = mesh.active_elements_end();

	// This will be exact when there is no refinement and all the
	// elements are of the same type.
	std::size_t graph_size=0;
	std::vector<std::vector<dof_id_type> > graph(n_active_elem);

	for (; elem_it != elem_end; ++elem_it)
	  {
	    const Elem* elem = *elem_it;

	    libmesh_assert (global_index_map.count(elem->id()));

	    const dof_id_type elem_global_index =
	      global_index_map[elem->id()];

	    libmesh_assert_less (elem_global_index, vwgt.size());
	    libmesh_assert_less (elem_global_index, graph.size());

	    // maybe there is a better weight?
	    // The weight is used to define what a balanced graph is
	    if(!_weights)
	      vwgt[elem_global_index] = elem->n_nodes();
	    else
	      vwgt[elem_global_index] = static_cast<int>((*_weights)[elem->id()]);

	    // Loop over the element's neighbors.  An element
	    // adjacency corresponds to a face neighbor
	    for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
	      {
		const Elem* neighbor = elem->neighbor(ms);

		if (neighbor != NULL)
		  {
		    // If the neighbor is active treat it
		    // as a connection
		    if (neighbor->active())
		      {
			libmesh_assert (global_index_map.count(neighbor->id()));

			const dof_id_type neighbor_global_index =
			  global_index_map[neighbor->id()];

			graph[elem_global_index].push_back(neighbor_global_index);
			graph_size++;
		      }

#ifdef LIBMESH_ENABLE_AMR

		    // Otherwise we need to find all of the
		    // neighbor's children that are connected to
		    // us and add them
		    else
		      {
			// The side of the neighbor to which
			// we are connected
			const unsigned int ns =
			  neighbor->which_neighbor_am_i (elem);
			libmesh_assert_less (ns, neighbor->n_neighbors());

			// Get all the active children (& grandchildren, etc...)
			// of the neighbor.
			neighbor->active_family_tree (neighbors_offspring);

			// Get all the neighbor's children that
			// live on that side and are thus connected
			// to us
			for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
			  {
			    const Elem* child =
			      neighbors_offspring[nc];

			    // This does not assume a level-1 mesh.
			    // Note that since children have sides numbered
			    // coincident with the parent then this is a sufficient test.
			    if (child->neighbor(ns) == elem)
			      {
				libmesh_assert (child->active());
				libmesh_assert (global_index_map.count(child->id()));

				const dof_id_type child_global_index =
				  global_index_map[child->id()];

				graph[elem_global_index].push_back(child_global_index);
				graph_size++;
			      }
			  }
		      }

#endif /* ifdef LIBMESH_ENABLE_AMR */

		  }
	      }
	  }

	// Convert the graph into the format Metis wants
	xadj.reserve(n_active_elem+1);
	adjncy.reserve(graph_size);

	for (std::size_t r=0; r<graph.size(); r++)
	  {
	    xadj.push_back(adjncy.size());
	    std::vector<dof_id_type> graph_row; // build this emtpy
	    graph_row.swap(graph[r]); // this will deallocate at the end of scope
	    adjncy.insert(adjncy.end(),
			  graph_row.begin(),
			  graph_row.end());
	  }

	// The end of the adjacency array for the last elem
	xadj.push_back(adjncy.size());

	libmesh_assert_equal_to (adjncy.size(), graph_size);
	libmesh_assert_equal_to (xadj.size(), n_active_elem+1);
      } // done building the graph

      if (adjncy.empty())
	adjncy.push_back(0);

      int ncon = 1;

      // Select which type of partitioning to create

      // Use recursive if the number of partitions is less than or equal to 8
      if (n_pieces <= 8)
	Metis::METIS_PartGraphRecursive(&n, &ncon, &xadj[0], &adjncy[0], &vwgt[0], NULL,
					NULL, &nparts, NULL, NULL, NULL,
					&edgecut, &part[0]);

      // Otherwise  use kway
      else
	Metis::METIS_PartGraphKway(&n, &ncon, &xadj[0], &adjncy[0], &vwgt[0], NULL,
				   NULL, &nparts, NULL, NULL, NULL,
				   &edgecut, &part[0]);

    } // end processor 0 part

  // Broadcase the resutling partition
  mesh.comm().broadcast(part);

  // Assign the returned processor ids.  The part array contains
  // the processor id for each active element, but in terms of
  // the contiguous indexing we defined above
  {
    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    for (; it!=end; ++it)
      {
	Elem* elem = *it;

	libmesh_assert (global_index_map.count(elem->id()));

	const dof_id_type elem_global_index =
	  global_index_map[elem->id()];

	libmesh_assert_less (elem_global_index, part.size());
	const processor_id_type elem_procid =
	  static_cast<processor_id_type>(part[elem_global_index]);

	elem->processor_id() = elem_procid;
      }
  }

  STOP_LOG("partition()", "MetisPartitioner");
#endif
}

} // namespace libMesh
<commit_msg>construct the CSR graph representation in-place<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

// C++ Includes   -----------------------------------
#include <map>

// Local Includes -----------------------------------
#include "libmesh/libmesh_config.h"
#include "libmesh/mesh_base.h"
#include "libmesh/metis_partitioner.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/elem.h"
#include "libmesh/mesh_communication.h"
#include "libmesh/error_vector.h"
#include "libmesh/vectormap.h"

#ifdef LIBMESH_HAVE_METIS
// MIPSPro 7.4.2 gets confused about these nested namespaces
# ifdef __sgi
#  include <cstdarg>
# endif
  namespace Metis {
    extern "C" {
#     include "libmesh/ignore_warnings.h"
#     include "metis.h"
#     include "libmesh/restore_warnings.h"
    }
  }
#else
#  include "libmesh/sfc_partitioner.h"
#endif

namespace
{
  class CSRGraph
  {
  public:
    std::vector<int> offsets, vals;

    void prep_n_nonzeros(const libMesh::dof_id_type row, const libMesh::dof_id_type n_nonzeros)
    {
      libmesh_assert_less (row+1, offsets.size());
      offsets[row+1] = n_nonzeros;
    }

    libMesh::dof_id_type n_nonzeros (const libMesh::dof_id_type row) const
    {
      libmesh_assert_less (row+1, offsets.size());
      return (offsets[row+1] - offsets[row]);
    }

    void prepare_for_use()
    {
      std::partial_sum (offsets.begin(), offsets.end(), offsets.begin());
      libmesh_assert (!offsets.empty());
      vals.resize(offsets.back());

      if (vals.empty())
	vals.push_back(0);
    }

    int& operator()(const libMesh::dof_id_type row, const libMesh::dof_id_type nonzero)
    {
      libmesh_assert_greater (vals.size(), offsets[row]+nonzero);

      return vals[offsets[row]+nonzero];
    }

    const int& operator()(const libMesh::dof_id_type row, const libMesh::dof_id_type nonzero) const
    {
      libmesh_assert_greater (vals.size(), offsets[row]+nonzero);

      return vals[offsets[row]+nonzero];
    }

  };
}

namespace libMesh
{

// ------------------------------------------------------------
// MetisPartitioner implementation
void MetisPartitioner::_do_partition (MeshBase& mesh,
				      const unsigned int n_pieces)
{
  libmesh_assert_greater (n_pieces, 0);
  libmesh_assert (mesh.is_serial());

  // Check for an easy return
  if (n_pieces == 1)
    {
      this->single_partition (mesh);
      return;
    }

// What to do if the Metis library IS NOT present
#ifndef LIBMESH_HAVE_METIS

  libmesh_here();
  libMesh::err << "ERROR: The library has been built without"    << std::endl
	        << "Metis support.  Using a space-filling curve"  << std::endl
	        << "partitioner instead!"                         << std::endl;

  SFCPartitioner sfcp;

  sfcp.partition (mesh, n_pieces);

// What to do if the Metis library IS present
#else

  START_LOG("partition()", "MetisPartitioner");

  const dof_id_type n_active_elem = mesh.n_active_elem();

  // build the graph
  // std::vector<int> options(5);
  std::vector<int> vwgt(n_active_elem);
  std::vector<int> part(n_active_elem);

  int
    n = static_cast<int>(n_active_elem),  // number of "nodes" (elements)
                                          //   in the graph
//    wgtflag = 2,                          // weights on vertices only,
//                                          //   none on edges
//    numflag = 0,                          // C-style 0-based numbering
    nparts  = static_cast<int>(n_pieces), // number of subdomains to create
    edgecut = 0;                          // the numbers of edges cut by the
                                          //   resulting partition

  // Set the options
  // options[0] = 0; // use default options

  // Metis will only consider the active elements.
  // We need to map the active element ids into a
  // contiguous range.  Further, we want the unique range indexing to be
  // independednt of the element ordering, otherwise a circular dependency
  // can result in which the partitioning depends on the ordering which
  // depends on the partitioning...
  vectormap<dof_id_type, dof_id_type> global_index_map;
  global_index_map.reserve (n_active_elem);

  {
    std::vector<dof_id_type> global_index;

    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    MeshCommunication().find_global_indices (mesh.comm(),
					     MeshTools::bounding_box(mesh),
					     it, end, global_index);

    libmesh_assert_equal_to (global_index.size(), n_active_elem);

    for (std::size_t cnt=0; it != end; ++it)
      {
	const Elem *elem = *it;

	global_index_map.insert (std::make_pair(elem->id(), global_index[cnt++]));
      }
    libmesh_assert_equal_to (global_index_map.size(), n_active_elem);
  }

  // Invoke METIS, but only on processor 0.
  // Then broadcast the resulting decomposition
  if (mesh.processor_id() == 0)
    {
      CSRGraph csr_graph;

      csr_graph.offsets.resize(n_active_elem+1, 0);

      // Local scope for these
      {
	// build the graph in CSR format.  Note that
	// the edges in the graph will correspond to
	// face neighbors
	std::vector<const Elem*> neighbors_offspring;

	MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
	const MeshBase::element_iterator elem_end = mesh.active_elements_end();

	std::size_t graph_size=0;

	// (1) first pass - get the row sizes for each element by counting the number
	// of face neighbors.  Also populate the vwght array if necessary
	for (; elem_it != elem_end; ++elem_it)
	  {
	    const Elem* elem = *elem_it;

	    const dof_id_type elem_global_index =
	      global_index_map[elem->id()];

	    libmesh_assert_less (elem_global_index, vwgt.size());

	    // maybe there is a better weight?
	    // The weight is used to define what a balanced graph is
	    if(!_weights)
	      vwgt[elem_global_index] = elem->n_nodes();
	    else
	      vwgt[elem_global_index] = static_cast<int>((*_weights)[elem->id()]);

	    unsigned int num_neighbors = 0;

	    // Loop over the element's neighbors.  An element
	    // adjacency corresponds to a face neighbor
	    for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
	      {
		const Elem* neighbor = elem->neighbor(ms);

		if (neighbor != NULL)
		  {
		    // If the neighbor is active treat it
		    // as a connection
		    if (neighbor->active())
		      num_neighbors++;

#ifdef LIBMESH_ENABLE_AMR

		    // Otherwise we need to find all of the
		    // neighbor's children that are connected to
		    // us and add them
		    else
		      {
			// The side of the neighbor to which
			// we are connected
			const unsigned int ns =
			  neighbor->which_neighbor_am_i (elem);
			libmesh_assert_less (ns, neighbor->n_neighbors());

			// Get all the active children (& grandchildren, etc...)
			// of the neighbor.
			neighbor->active_family_tree (neighbors_offspring);

			// Get all the neighbor's children that
			// live on that side and are thus connected
			// to us
			for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
			  {
			    const Elem* child =
			      neighbors_offspring[nc];

			    // This does not assume a level-1 mesh.
			    // Note that since children have sides numbered
			    // coincident with the parent then this is a sufficient test.
			    if (child->neighbor(ns) == elem)
			      {
				libmesh_assert (child->active());
				num_neighbors++;
			      }
			  }
		      }

#endif /* ifdef LIBMESH_ENABLE_AMR */

		  }
	      }

	    csr_graph.prep_n_nonzeros(elem_global_index, num_neighbors);
	    graph_size += num_neighbors;
	  }

	csr_graph.prepare_for_use();

	// (2) second pass - fill the compressed adjacency array
	elem_it  = mesh.active_elements_begin();

	for (; elem_it != elem_end; ++elem_it)
	  {
	    const Elem* elem = *elem_it;

	    const dof_id_type elem_global_index =
	      global_index_map[elem->id()];

	    unsigned int connection=0;

	    // Loop over the element's neighbors.  An element
	    // adjacency corresponds to a face neighbor
	    for (unsigned int ms=0; ms<elem->n_neighbors(); ms++)
	      {
		const Elem* neighbor = elem->neighbor(ms);

		if (neighbor != NULL)
		  {
		    // If the neighbor is active treat it
		    // as a connection
		    if (neighbor->active())
		      csr_graph(elem_global_index, connection++) = global_index_map[neighbor->id()];

#ifdef LIBMESH_ENABLE_AMR

		    // Otherwise we need to find all of the
		    // neighbor's children that are connected to
		    // us and add them
		    else
		      {
			// The side of the neighbor to which
			// we are connected
			const unsigned int ns =
			  neighbor->which_neighbor_am_i (elem);
			libmesh_assert_less (ns, neighbor->n_neighbors());

			// Get all the active children (& grandchildren, etc...)
			// of the neighbor.
			neighbor->active_family_tree (neighbors_offspring);

			// Get all the neighbor's children that
			// live on that side and are thus connected
			// to us
			for (unsigned int nc=0; nc<neighbors_offspring.size(); nc++)
			  {
			    const Elem* child =
			      neighbors_offspring[nc];

			    // This does not assume a level-1 mesh.
			    // Note that since children have sides numbered
			    // coincident with the parent then this is a sufficient test.
			    if (child->neighbor(ns) == elem)
			      {
				libmesh_assert (child->active());

				csr_graph(elem_global_index, connection++) = global_index_map[child->id()];
			      }
			  }
		      }

#endif /* ifdef LIBMESH_ENABLE_AMR */

		  }
	      }
	  }

	libmesh_assert_equal_to (csr_graph.vals.size(), graph_size);
      } // done building the graph

      int ncon = 1;

      // Select which type of partitioning to create

      // Use recursive if the number of partitions is less than or equal to 8
      if (n_pieces <= 8)
	Metis::METIS_PartGraphRecursive(&n, &ncon, &csr_graph.offsets[0], &csr_graph.vals[0], &vwgt[0], NULL,
					NULL, &nparts, NULL, NULL, NULL,
					&edgecut, &part[0]);

      // Otherwise  use kway
      else
	Metis::METIS_PartGraphKway(&n, &ncon, &csr_graph.offsets[0], &csr_graph.vals[0], &vwgt[0], NULL,
				   NULL, &nparts, NULL, NULL, NULL,
				   &edgecut, &part[0]);

    } // end processor 0 part

  // Broadcase the resutling partition
  mesh.comm().broadcast(part);

  // Assign the returned processor ids.  The part array contains
  // the processor id for each active element, but in terms of
  // the contiguous indexing we defined above
  {
    MeshBase::element_iterator       it  = mesh.active_elements_begin();
    const MeshBase::element_iterator end = mesh.active_elements_end();

    for (; it!=end; ++it)
      {
	Elem* elem = *it;

	libmesh_assert (global_index_map.count(elem->id()));

	const dof_id_type elem_global_index =
	  global_index_map[elem->id()];

	libmesh_assert_less (elem_global_index, part.size());
	const processor_id_type elem_procid =
	  static_cast<processor_id_type>(part[elem_global_index]);

	elem->processor_id() = elem_procid;
      }
  }

  STOP_LOG("partition()", "MetisPartitioner");
#endif
}

} // namespace libMesh
<|endoftext|>


<commit_before><commit_msg>Fix crash when interacting with terminal with UI hidden<commit_after><|endoftext|>


<commit_before>#include <SDL/SDL.h>
#include "SDL_SaveJPEG.cpp"
SDL_SaveJPEG worker;
#define print_surface_info(surface,info) printf(#surface"->"#info"=%d\n",surface->info);
int main()
{
	SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *bmp = SDL_LoadBMP("lena.bmp");
	if (bmp == NULL)
		return -1;
	SDL_Surface *s =
		SDL_SetVideoMode(bmp->w, bmp->h, bmp->format->BitsPerPixel, SDL_SWSURFACE | SDL_DOUBLEBUF);
	if (s == NULL)
		return -1;
//	freopen("sdl.log", "w", stdout);
//	printf("BMP BitsPerPixel=%d\n", bmp->format->BitsPerPixel);

print_surface_info(bmp,w);
print_surface_info(bmp,h);
print_surface_info(bmp,format->BitsPerPixel);
print_surface_info(bmp,pitch);

//print_surface_info(s,w);
//print_surface_info(s,h);
//print_surface_info(s,format->BitsPerPixel);
	SDL_BlitSurface(bmp, NULL, s, NULL);
	SDL_FreeSurface(bmp);
	SDL_Flip(s);
	clock_t t=clock();
	worker.save(s,"lena.jpg");
	printf("jpeg save time: %ld\n",clock()-t);
	fflush(stdout);
	fclose(stdout);
	SDL_Quit();
	return 0;
}<commit_msg>undef print_surface_info at the end<commit_after>#include <SDL/SDL.h>
#include "SDL_SaveJPEG.cpp"
SDL_SaveJPEG worker;
#define print_surface_info(surface,info) printf(#surface"->"#info"=%d\n",surface->info);
int main()
{
	SDL_Init(SDL_INIT_VIDEO);
SDL_Surface *bmp = SDL_LoadBMP("lena.bmp");
	if (bmp == NULL)
		return -1;
	SDL_Surface *s =
		SDL_SetVideoMode(bmp->w, bmp->h, bmp->format->BitsPerPixel, SDL_SWSURFACE | SDL_DOUBLEBUF);
	if (s == NULL)
		return -1;
//	freopen("sdl.log", "w", stdout);
//	printf("BMP BitsPerPixel=%d\n", bmp->format->BitsPerPixel);

print_surface_info(bmp,w);
print_surface_info(bmp,h);
print_surface_info(bmp,format->BitsPerPixel);
print_surface_info(bmp,pitch);

//print_surface_info(s,w);
//print_surface_info(s,h);
//print_surface_info(s,format->BitsPerPixel);
	SDL_BlitSurface(bmp, NULL, s, NULL);
	SDL_FreeSurface(bmp);
	SDL_Flip(s);
	clock_t t=clock();
	worker.save(s,"lena.jpg");
	printf("jpeg save time: %ld\n",clock()-t);
	fflush(stdout);
	fclose(stdout);
	SDL_Quit();
	return 0;
}
#undef print_surface_info<|endoftext|>


<commit_before>#include <QDebug>
#include <iostream>
#include "block.h"
#include "cornerblock.h"
#include "player.h"
#include "dice.h"
#include "localgame.h"
#include <QMessageBox>
#include <QFileInfo>

using namespace std;

CornerBlock::CornerBlock(QGameItem * parent,CornerType::Type type)
    : Block(parent)
{
    corner_type = type;
    block_type = BlockType::CORNER;
    effect_player = new QMediaPlayer();
}

CornerBlock::~CornerBlock()
{
    delete effect_player;
}

// Methods
void CornerBlock::enter(Player* player)
{
    qDebug() << "In corner block " << corner_type;
    using namespace CornerType;
    switch(corner_type)
    {
    case DORM : inDormitory(player);
        break;
    case CALLTAXI : in61Call(player);
        break;
    case BREAKSEM : inBreakSemester(player);
        break;
    case PLURAL : inPluralMajor(player);
        break;
    default : qDebug() << "CornerBlock error!" << endl;
        break;
    }
}
//when arrived at dormitory block, give oppertunity to learn one subject again
void CornerBlock::inDormitory(Player* player)
{
    using namespace CharacterType;
    QMessageBox warn_box;
    warn_box.setStandardButtons(QMessageBox::Ok);
    warn_box.setDefaultButton(QMessageBox::Ok);

    std::list<Block*> block_list = player->getBlocks();
    if(block_list.size() > 0) {

        warn_box.setText("재수강할 과목을 선택해주세요.");
        warn_box.exec();
        LocalGame::getInst()->setGameState(LocalGameState::CORNER_RETAKE_SUBJECT);
    }
    else {
        warn_box.setText("재수강할 과목이 없네요. 공부좀 하세요.");
        warn_box.exec();
        LocalGame::getInst()->turnOver();
    }
}

//when arrived at 61call block, give oppertunity to move other block which you want to move (p=1/4)
void CornerBlock::in61Call(Player* player)
{
    QMessageBox warn_box;
    warn_box.setStandardButtons(QMessageBox::Ok);
    warn_box.setDefaultButton(QMessageBox::Ok);
    if((rand() % 1)==0)
    {
        // play 61call sound
        effect_player->setMedia(QUrl::fromLocalFile(QFileInfo("sound/61call.wav").absoluteFilePath()));
        effect_player->play();

        warn_box.setText("61콜 택시 성공! 이동하고 싶은 블럭을 선택하세요!");
        warn_box.exec();
        LocalGame::getInst()->setGameState(LocalGameState::JUMP_PLAYER);
    }

    else
    {
        warn_box.setText("61콜 택시 실패! 다음 기회에...");
        warn_box.exec();
        LocalGame::getInst()->turnOver();
    }

}

//in breaksemester, rest 3 turns. If dice were double at rest, you would be able to escape..
void CornerBlock::inBreakSemester(Player* player)
{
    // play 61call sound
    effect_player->setMedia(QUrl::fromLocalFile(QFileInfo("sound/no.wav").absoluteFilePath()));
    effect_player->play();

    //LocalGame에서 모두 구현되어 있음
    player->setMouindo(3);
    LocalGame::getInst()->turnOver();

    //1.원래 무인도에 있다가 다시 턴이 된 경우 -> 주사위를 굴릴 수 있게 한다.
    //2.다른 칸에 있다가 갑자기 무인도에 온 경우->바로 쉬게 한다.
    //3.휴식 횟수 새는 기능.
}

//in pluralmajor block, stochastically you should monopolize 2 department (odds=1/6)
void CornerBlock::inPluralMajor(Player* player)
{
    QMessageBox warn_box;
    warn_box.setStandardButtons(QMessageBox::Ok);
    warn_box.setDefaultButton(QMessageBox::Ok);
    warn_box.setText(QString("복수전공 당첨! 승리하려면 두 가지 전공을 이수해야 합니다."));
    warn_box.exec();

    switch((rand() % 6)==1) {
        case 1:
            qDebug() <<"You have to take plural major.";
            player->setPlural(true);
            break;

        default:
        qDebug()<<"You don't have to take plural major.";
    }
    //학과 1개 독점 시에 복수전공 해제& 두개 독점 시에 승리 그리고 만약에 한개 독점 하고 두개째 도전중일 때다른 누군가가 독점된 학과를 뺏어가는 경우!?

    LocalGame::getInst()->turnOver();
}
<commit_msg>ConerBlock: sound effect added<commit_after>#include <QDebug>
#include <iostream>
#include "block.h"
#include "cornerblock.h"
#include "player.h"
#include "dice.h"
#include "localgame.h"
#include <QMessageBox>
#include <QFileInfo>

using namespace std;

CornerBlock::CornerBlock(QGameItem * parent,CornerType::Type type)
    : Block(parent)
{
    corner_type = type;
    block_type = BlockType::CORNER;
    effect_player = new QMediaPlayer();
}

CornerBlock::~CornerBlock()
{
    delete effect_player;
}

// Methods
void CornerBlock::enter(Player* player)
{
    qDebug() << "In corner block " << corner_type;
    using namespace CornerType;
    switch(corner_type) {
        case DORM : inDormitory(player);
            break;
        case CALLTAXI : in61Call(player);
            break;
        case BREAKSEM : inBreakSemester(player);
            break;
        case PLURAL : inPluralMajor(player);
            break;
        default : qDebug() << "CornerBlock error!" << endl;
            break;
    }
}

//when arrived at dormitory block, give oppertunity to learn one subject again
void CornerBlock::inDormitory(Player* player)
{
    using namespace CharacterType;
    QMessageBox warn_box;
    warn_box.setStandardButtons(QMessageBox::Ok);
    warn_box.setDefaultButton(QMessageBox::Ok);

    std::list<Block*> block_list = player->getBlocks();
    if(block_list.size() > 0) {

        warn_box.setText("재수강할 과목을 선택해주세요.");
        warn_box.exec();
        LocalGame::getInst()->setGameState(LocalGameState::CORNER_RETAKE_SUBJECT);
    }
    else {
        warn_box.setText("재수강할 과목이 없네요. 공부좀 하세요.");
        warn_box.exec();
        LocalGame::getInst()->turnOver();
    }
}

//when arrived at 61call block, give oppertunity to move other block which you want to move (p=1/4)
void CornerBlock::in61Call(Player* player)
{
    QMessageBox warn_box;
    warn_box.setStandardButtons(QMessageBox::Ok);
    warn_box.setDefaultButton(QMessageBox::Ok);
    if((rand() % 1)==0)
    {
        // play 61call sound
        effect_player->setMedia(QUrl::fromLocalFile(QFileInfo("sound/61call.wav").absoluteFilePath()));
        effect_player->play();

        warn_box.setText("61콜 택시 성공! 이동하고 싶은 블럭을 선택하세요!");
        warn_box.exec();
        LocalGame::getInst()->setGameState(LocalGameState::JUMP_PLAYER);
    }

    else
    {
        warn_box.setText("61콜 택시 실패! 다음 기회에...");
        warn_box.exec();
        LocalGame::getInst()->turnOver();
    }

}

//in breaksemester, rest 3 turns. If dice were double at rest, you would be able to escape..
void CornerBlock::inBreakSemester(Player* player)
{
    // play 61call sound
    effect_player->setMedia(QUrl::fromLocalFile(QFileInfo("sound/no.wav").absoluteFilePath()));
    effect_player->play();

    //LocalGame에서 모두 구현되어 있음
    player->setMouindo(2);
    LocalGame::getInst()->turnOver();

    //1.원래 무인도에 있다가 다시 턴이 된 경우 -> 주사위를 굴릴 수 있게 한다.
    //2.다른 칸에 있다가 갑자기 무인도에 온 경우->바로 쉬게 한다.
    //3.휴식 횟수 새는 기능.
}

//in pluralmajor block, stochastically you should monopolize 2 department (odds=1/6)
void CornerBlock::inPluralMajor(Player* player)
{
    QMessageBox warn_box;
    warn_box.setStandardButtons(QMessageBox::Ok);
    warn_box.setDefaultButton(QMessageBox::Ok);
    warn_box.setText(QString("복수전공 당첨! 승리하려면 두 가지 전공을 이수해야 합니다."));
    warn_box.exec();

    switch((rand() % 6)==1) {
        case 1:
            qDebug() <<"You have to take plural major.";

            // play 61call sound
            effect_player->setMedia(QUrl::fromLocalFile(QFileInfo("sound/no.wav").absoluteFilePath()));
            effect_player->play();

            player->setPlural(true);
            break;

        default:
            qDebug()<<"You don't have to take plural major.";
    }
    //학과 1개 독점 시에 복수전공 해제& 두개 독점 시에 승리 그리고 만약에 한개 독점 하고 두개째 도전중일 때다른 누군가가 독점된 학과를 뺏어가는 경우!?

    LocalGame::getInst()->turnOver();
}
<|endoftext|>


<commit_before>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CMetab.cpp,v $
   $Revision: 1.68 $
   $Name:  $
   $Author: gauges $
   $Date: 2004/10/08 13:06:56 $
   End CVS Header */

#include <iostream>
#include <string>
#include <vector>

#define  COPASI_TRACE_CONSTRUCTION

#include "copasi.h"
#include "utilities/CGlobals.h"
#include "utilities/utility.h"
#include "report/CCopasiObjectReference.h"
#include "report/CKeyFactory.h"
#include "CCompartment.h"
#include "CModel.h"
#include "CMetab.h"

//static
const CCompartment * CMetab::mpParentCompartment = NULL;

//static
const std::string CMetab::StatusName[] =
  {"fixed", "independent", "dependent", "unused", ""};

//static
const char * CMetab::XMLStatus[] =
  {"fixed", "variable", "variable", "variable", NULL};

//static
void CMetab::setParentCompartment(const CCompartment * parentCompartment)
{mpParentCompartment = parentCompartment;}

CMetab::CMetab(const std::string & name,
               const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Metabolite",
                     CCopasiObject::Container |
                     CCopasiObject::ValueDbl |
                     CCopasiObject::NonUniqueName),
    mKey(GlobalKeys.add("Metabolite", this)),
    mConc(1.0),
    mIConc(1.0),
    mNumber(1.0),
    mINumber(1.0),
    mRate(0.0),
    mTT(0.0),
    mStatus(METAB_VARIABLE)
{
  if (getObjectParent())
    {
      initModel();
      initCompartment(NULL);
    }

  initObjects();
  CONSTRUCTOR_TRACE;
}

CMetab::CMetab(const CMetab & src,
               const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mKey(GlobalKeys.add("Metabolite", this)),
    mConc(src.mConc),
    mIConc(src.mIConc),
    mNumber(src.mNumber),
    mINumber(src.mINumber),
    mRate(src.mRate),
    mTT(src.mTT),
    mStatus(src.mStatus)
{
  initModel();
  initCompartment(src.mpCompartment);
  initObjects();
  CONSTRUCTOR_TRACE;
}

CMetab &CMetab::operator=(const CMetabOld &RHS)
{
  setObjectName(RHS.getObjectName());

  setInitialConcentration(RHS.mIConc);
  setConcentration(RHS.mIConc);

  mRate = 0.0;
  mTT = 0.0;
  mStatus = RHS.mStatus;

  return *this;  // Assignment operator returns left side.
}

CMetab::~CMetab()
{
  GlobalKeys.remove(mKey);
  DESTRUCTOR_TRACE;
}

void CMetab::cleanup() {}

void CMetab::initModel()
{
  mpModel = dynamic_cast< CModel * >(getObjectAncestor("Model"));
  if (!mpModel && Copasi) mpModel = Copasi->pModel;
}

void CMetab::initCompartment(const CCompartment * pCompartment)
{
  mpCompartment = (const CCompartment *) getObjectAncestor("Compartment");
  if (!mpCompartment) mpCompartment = pCompartment;
  if (!mpCompartment) mpCompartment = mpParentCompartment;
}

const std::string & CMetab::getKey() const {return mKey;}

const C_FLOAT64 & CMetab::getConcentration() const {return mConc;}

const C_FLOAT64 & CMetab::getNumber() const {return mNumber;}

const C_FLOAT64 & CMetab::getInitialConcentration() const {return mIConc;}

const C_FLOAT64 & CMetab::getInitialNumber() const {return mINumber;}

const CMetab::Status & CMetab::getStatus() const {return mStatus;}

const CCompartment * CMetab::getCompartment() const {return mpCompartment;}

const CModel * CMetab::getModel() const {return mpModel;}

void CMetab::setTransitionTime(const C_FLOAT64 & transitionTime)
{mTT = transitionTime;}

const C_FLOAT64 & CMetab::getTransitionTime() const {return mTT;}

bool CMetab::setObjectParent(const CCopasiContainer * pParent)
{
  CCopasiObject::setObjectParent(pParent);

  initCompartment(NULL);
  initModel();

  return true;
}

// ***** set quantities ********

void CMetab::setConcentration(const C_FLOAT64 concentration)
{
  mConc = concentration;
  mNumber = concentration * mpCompartment->getVolume()
            * mpModel->getQuantity2NumberFactor();
}

void CMetab::setInitialConcentration(const C_FLOAT64 initialConcentration)
{
  mIConc = initialConcentration;
  mINumber = initialConcentration * mpCompartment->getVolume()
             * mpModel->getQuantity2NumberFactor();
}

void CMetab::setNumber(const C_FLOAT64 number)
{
  mConc = number * mpCompartment->getVolumeInv()
          * mpModel->getNumber2QuantityFactor();
  mNumber = number;
}

void CMetab::setInitialNumber(const C_FLOAT64 initialNumber)
{
  mIConc = initialNumber * mpCompartment->getVolumeInv()
           * mpModel->getNumber2QuantityFactor();
  mINumber = initialNumber;
}

//  ******************

void CMetab::setStatus(const CMetab::Status & status) {mStatus = status;}

void CMetab::setCompartment(const CCompartment * compartment)
{mpCompartment = compartment;}

void CMetab::setModel(CModel * model) {mpModel = model;}

void CMetab::initObjects()
{
  addObjectReference("Concentration", mConc, CCopasiObject::ValueDbl);
  addObjectReference("InitialConcentration", mIConc, CCopasiObject::ValueDbl);
  addObjectReference("ParticleNumber", mNumber, CCopasiObject::ValueDbl);
  addObjectReference("InitialParticleNumber", mINumber, CCopasiObject::ValueDbl);
  addObjectReference("TransitionTime", mTT, CCopasiObject::ValueDbl);
}

// non-member
/*bool operator<(const CMetab &lhs, const CMetab &rhs)
{
  // Do the comparison based on the name
  if (lhs.getObjectName() < rhs.getObjectName())
    {
      return true;
    }
  else
    {
      return false;
    }
}*/

/**
 * Return rate of production of this metaboLite
 */
const C_FLOAT64 & CMetab::getConcentrationRate() const
  {
    return mRate;
  }

C_FLOAT64 CMetab::getNumberRate() const
  {
    return mRate * getCompartment()->getVolume()
    * mpModel->getQuantity2NumberFactor();
  }

void CMetab::setNumberRate(const C_FLOAT64 & rate)
{
  //converts particles/time to concentration/time
  mRate = rate * getCompartment()->getVolumeInv()
          * mpModel->getNumber2QuantityFactor();
}

void CMetab::setConcentrationRate(const C_FLOAT64 & rate)
{mRate = rate;}

void * CMetab::getReference() const
  {return const_cast<C_FLOAT64 *>(&mConc);}

std::ostream & operator<<(std::ostream &os, const CMetab & d)
{
  os << "    ++++CMetab: " << d.getObjectName() << std::endl;
  os << "        mConc " << d.mConc << " mIConc " << d.mIConc << std::endl;
  os << "        mNumber " << d.mNumber << " mINumber " << d.mINumber << std::endl;
  os << "        mRate " << d.mRate << " mTT " << d.mTT << " mStatus " << d.mStatus << std::endl;

  if (d.mpCompartment)
    os << "        mpCompartment == " << d.mpCompartment << std::endl;
  else
    os << "        mpCompartment == 0 " << std::endl;

  if (d.mpModel)
    os << "        mpModel == " << d.mpModel << std::endl;
  else
    os << "        mpModel == 0 " << std::endl;

  os << "    ----CMetab " << std::endl;

  return os;
}

C_INT32 CMetab::load(CReadConfig &configbuffer)
{
  C_INT32 Fail = 0;

  std::string tmp;
  Fail = configbuffer.getVariable("Metabolite", "string",
                                  (void *) & tmp,
                                  CReadConfig::SEARCH);

  if (Fail)
    return Fail;
  setObjectName(tmp);

  Fail = configbuffer.getVariable("InitialConcentration", "C_FLOAT64",
                                  (void *) & mIConc);

  setInitialConcentration(mIConc);
  setConcentration(mIConc);

  Fail = configbuffer.getVariable("Type", "C_INT16",
                                  (void *) & mStatus);

  if (Fail)
    return Fail;

  // sanity check
  if ((mStatus < 0) || (mStatus > 7))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a non-existing type "
                     "for '%s'.\nReset to internal metabolite.",
                     getObjectName().c_str());
      mStatus = CMetab::METAB_VARIABLE;
    }

  // sanity check
  if ((mStatus != METAB_MOIETY) && (mIConc < 0.0))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a negative concentration "
                     "for '%s'.\nReset to default.",
                     getObjectName().c_str());
      mIConc = 1.0;
    }

  return Fail;
}

//******************* CMetabOld ***************************************************

CMetabOld::CMetabOld(const std::string & name,
                     const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Old Metabolite"),
    mIConc(1.0),
    mStatus(CMetab::METAB_VARIABLE),
    mCompartment()
{CONSTRUCTOR_TRACE;}

CMetabOld::CMetabOld(const CMetabOld & src,
                     const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mIConc(src.mIConc),
    mStatus(src.mStatus),
    mCompartment(src.mCompartment)
{CONSTRUCTOR_TRACE;}

CMetabOld::~CMetabOld() {DESTRUCTOR_TRACE;}

void CMetabOld::cleanup(){}

C_INT32 CMetabOld::load(CReadConfig &configbuffer)
{
  C_INT32 Fail = 0;
  std::string tmp;
  Fail = configbuffer.getVariable("Metabolite", "string",
                                  (void *) & tmp,
                                  CReadConfig::SEARCH);

  if (Fail)
    return Fail;
  setObjectName(tmp);

  Fail = configbuffer.getVariable("Concentration", "C_FLOAT64",
                                  (void *) & mIConc);

  if (Fail)
    return Fail;

  Fail = configbuffer.getVariable("Compartment", "C_INT32",
                                  (void *) & mCompartment);

  if (Fail)
    return Fail;

  C_INT32 Status;

  Fail = configbuffer.getVariable("Type", "C_INT32",
                                  (void *) & Status);

  mStatus = (CMetab::Status) Status;

  // sanity check
  if ((mStatus < 0) || (mStatus > 7))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a non-existing type "
                     "for '%s'.\nReset to internal metabolite.",
                     getObjectName().c_str());
      mStatus = CMetab::METAB_VARIABLE;
    }

  // sanity check
  if ((mStatus != METAB_MOIETY) && (mIConc < 0.0))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a negative concentration "
                     "for '%s'.\nReset to default.",
                     getObjectName().c_str());
      mIConc = 1.0;
    }

  return Fail;
}

C_INT32 CMetabOld::getIndex() const {return mCompartment;}
<commit_msg>modified CMetab to keep the initial and transient state synchronized when the status is "fixed"<commit_after>/* Begin CVS Header
   $Source: /Volumes/Home/Users/shoops/cvs/copasi_dev/copasi/model/CMetab.cpp,v $
   $Revision: 1.69 $
   $Name:  $
   $Author: ssahle $
   $Date: 2004/10/14 21:06:23 $
   End CVS Header */

#include <iostream>
#include <string>
#include <vector>

#define  COPASI_TRACE_CONSTRUCTION

#include "copasi.h"
#include "utilities/CGlobals.h"
#include "utilities/utility.h"
#include "report/CCopasiObjectReference.h"
#include "report/CKeyFactory.h"
#include "CCompartment.h"
#include "CModel.h"
#include "CMetab.h"

//static
const CCompartment * CMetab::mpParentCompartment = NULL;

//static
const std::string CMetab::StatusName[] =
  {"fixed", "independent", "dependent", "unused", ""};

//static
const char * CMetab::XMLStatus[] =
  {"fixed", "variable", "variable", "variable", NULL};

//static
void CMetab::setParentCompartment(const CCompartment * parentCompartment)
{mpParentCompartment = parentCompartment;}

CMetab::CMetab(const std::string & name,
               const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Metabolite",
                     CCopasiObject::Container |
                     CCopasiObject::ValueDbl |
                     CCopasiObject::NonUniqueName),
    mKey(GlobalKeys.add("Metabolite", this)),
    mConc(1.0),
    mIConc(1.0),
    mNumber(1.0),
    mINumber(1.0),
    mRate(0.0),
    mTT(0.0),
    mStatus(METAB_VARIABLE)
{
  if (getObjectParent())
    {
      initModel();
      initCompartment(NULL);
    }
  else
    {
      mpCompartment = NULL;
    }

  initObjects();
  CONSTRUCTOR_TRACE;
}

CMetab::CMetab(const CMetab & src,
               const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mKey(GlobalKeys.add("Metabolite", this)),
    mConc(src.mConc),
    mIConc(src.mIConc),
    mNumber(src.mNumber),
    mINumber(src.mINumber),
    mRate(src.mRate),
    mTT(src.mTT),
    mStatus(src.mStatus)
{
  initModel();
  initCompartment(src.mpCompartment);
  initObjects();
  CONSTRUCTOR_TRACE;
}

CMetab &CMetab::operator=(const CMetabOld &RHS)
{
  setObjectName(RHS.getObjectName());

  setInitialConcentration(RHS.mIConc);
  setConcentration(RHS.mIConc);

  mRate = 0.0;
  mTT = 0.0;
  mStatus = RHS.mStatus;

  return *this;  // Assignment operator returns left side.
}

CMetab::~CMetab()
{
  GlobalKeys.remove(mKey);
  DESTRUCTOR_TRACE;
}

void CMetab::cleanup() {}

void CMetab::initModel()
{
  mpModel = dynamic_cast< CModel * >(getObjectAncestor("Model"));
  if (!mpModel && Copasi) mpModel = Copasi->pModel;
}

void CMetab::initCompartment(const CCompartment * pCompartment)
{
  mpCompartment = (const CCompartment *) getObjectAncestor("Compartment");
  if (!mpCompartment) mpCompartment = pCompartment;
  if (!mpCompartment) mpCompartment = mpParentCompartment;
}

const std::string & CMetab::getKey() const {return mKey;}

const C_FLOAT64 & CMetab::getConcentration() const {return mConc;}

const C_FLOAT64 & CMetab::getNumber() const {return mNumber;}

const C_FLOAT64 & CMetab::getInitialConcentration() const {return mIConc;}

const C_FLOAT64 & CMetab::getInitialNumber() const {return mINumber;}

const CMetab::Status & CMetab::getStatus() const {return mStatus;}

const CCompartment * CMetab::getCompartment() const {return mpCompartment;}

const CModel * CMetab::getModel() const {return mpModel;}

void CMetab::setTransitionTime(const C_FLOAT64 & transitionTime)
{mTT = transitionTime;}

const C_FLOAT64 & CMetab::getTransitionTime() const {return mTT;}

bool CMetab::setObjectParent(const CCopasiContainer * pParent)
{
  CCopasiObject::setObjectParent(pParent);

  initCompartment(NULL);
  initModel();

  return true;
}

// ***** set quantities ********

void CMetab::setConcentration(const C_FLOAT64 concentration)
{
  mConc = concentration;
  mNumber = concentration * mpCompartment->getVolume()
            * mpModel->getQuantity2NumberFactor();

#ifdef COPASI_DEBUG
  if (mStatus == METAB_FIXED)
    std::cout << "warning: set the transient concentration on a fixed metab" << std::endl;
#endif
}

void CMetab::setInitialConcentration(const C_FLOAT64 initialConcentration)
{
  mIConc = initialConcentration;
  mINumber = initialConcentration * mpCompartment->getVolume()
             * mpModel->getQuantity2NumberFactor();

  if (mStatus == METAB_FIXED)
    setConcentration(initialConcentration);
}

void CMetab::setNumber(const C_FLOAT64 number)
{
  mConc = number * mpCompartment->getVolumeInv()
          * mpModel->getNumber2QuantityFactor();
  mNumber = number;

#ifdef COPASI_DEBUG
  if (mStatus == METAB_FIXED)
    std::cout << "warning: set the transient particle number on a fixed metab" << std::endl;
#endif
}

void CMetab::setInitialNumber(const C_FLOAT64 initialNumber)
{
  mIConc = initialNumber * mpCompartment->getVolumeInv()
           * mpModel->getNumber2QuantityFactor();
  mINumber = initialNumber;

  if (mStatus == METAB_FIXED)
    setNumber(initialNumber);
}

//  ******************

void CMetab::setStatus(const CMetab::Status & status)
{
  mStatus = status;
  if (mStatus == METAB_FIXED)
    {
      if (mpCompartment)
        setNumber(getInitialNumber());
    }
}

void CMetab::setCompartment(const CCompartment * compartment)
{mpCompartment = compartment;}

void CMetab::setModel(CModel * model) {mpModel = model;}

void CMetab::initObjects()
{
  addObjectReference("Concentration", mConc, CCopasiObject::ValueDbl);
  addObjectReference("InitialConcentration", mIConc, CCopasiObject::ValueDbl);
  addObjectReference("ParticleNumber", mNumber, CCopasiObject::ValueDbl);
  addObjectReference("InitialParticleNumber", mINumber, CCopasiObject::ValueDbl);
  addObjectReference("TransitionTime", mTT, CCopasiObject::ValueDbl);
}

// non-member
/*bool operator<(const CMetab &lhs, const CMetab &rhs)
{
  // Do the comparison based on the name
  if (lhs.getObjectName() < rhs.getObjectName())
    {
      return true;
    }
  else
    {
      return false;
    }
}*/

/**
 * Return rate of production of this metaboLite
 */
const C_FLOAT64 & CMetab::getConcentrationRate() const
  {
    return mRate;
  }

C_FLOAT64 CMetab::getNumberRate() const
  {
    return mRate * getCompartment()->getVolume()
    * mpModel->getQuantity2NumberFactor();
  }

void CMetab::setNumberRate(const C_FLOAT64 & rate)
{
  //converts particles/time to concentration/time
  mRate = rate * getCompartment()->getVolumeInv()
          * mpModel->getNumber2QuantityFactor();
}

void CMetab::setConcentrationRate(const C_FLOAT64 & rate)
{mRate = rate;}

void * CMetab::getReference() const
  {return const_cast<C_FLOAT64 *>(&mConc);}

std::ostream & operator<<(std::ostream &os, const CMetab & d)
{
  os << "    ++++CMetab: " << d.getObjectName() << std::endl;
  os << "        mConc " << d.mConc << " mIConc " << d.mIConc << std::endl;
  os << "        mNumber " << d.mNumber << " mINumber " << d.mINumber << std::endl;
  os << "        mRate " << d.mRate << " mTT " << d.mTT << " mStatus " << d.mStatus << std::endl;

  if (d.mpCompartment)
    os << "        mpCompartment == " << d.mpCompartment << std::endl;
  else
    os << "        mpCompartment == 0 " << std::endl;

  if (d.mpModel)
    os << "        mpModel == " << d.mpModel << std::endl;
  else
    os << "        mpModel == 0 " << std::endl;

  os << "    ----CMetab " << std::endl;

  return os;
}

C_INT32 CMetab::load(CReadConfig &configbuffer)
{
  C_INT32 Fail = 0;

  std::string tmp;
  Fail = configbuffer.getVariable("Metabolite", "string",
                                  (void *) & tmp,
                                  CReadConfig::SEARCH);

  if (Fail)
    return Fail;
  setObjectName(tmp);

  Fail = configbuffer.getVariable("InitialConcentration", "C_FLOAT64",
                                  (void *) & mIConc);

  setInitialConcentration(mIConc);
  setConcentration(mIConc);

  Fail = configbuffer.getVariable("Type", "C_INT16",
                                  (void *) & mStatus);

  if (Fail)
    return Fail;

  // sanity check
  if ((mStatus < 0) || (mStatus > 7))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a non-existing type "
                     "for '%s'.\nReset to internal metabolite.",
                     getObjectName().c_str());
      mStatus = CMetab::METAB_VARIABLE;
    }

  // sanity check
  if ((mStatus != METAB_MOIETY) && (mIConc < 0.0))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a negative concentration "
                     "for '%s'.\nReset to default.",
                     getObjectName().c_str());
      mIConc = 1.0;
    }

  return Fail;
}

//******************* CMetabOld ***************************************************

CMetabOld::CMetabOld(const std::string & name,
                     const CCopasiContainer * pParent):
    CCopasiContainer(name, pParent, "Old Metabolite"),
    mIConc(1.0),
    mStatus(CMetab::METAB_VARIABLE),
    mCompartment()
{CONSTRUCTOR_TRACE;}

CMetabOld::CMetabOld(const CMetabOld & src,
                     const CCopasiContainer * pParent):
    CCopasiContainer(src, pParent),
    mIConc(src.mIConc),
    mStatus(src.mStatus),
    mCompartment(src.mCompartment)
{CONSTRUCTOR_TRACE;}

CMetabOld::~CMetabOld() {DESTRUCTOR_TRACE;}

void CMetabOld::cleanup(){}

C_INT32 CMetabOld::load(CReadConfig &configbuffer)
{
  C_INT32 Fail = 0;
  std::string tmp;
  Fail = configbuffer.getVariable("Metabolite", "string",
                                  (void *) & tmp,
                                  CReadConfig::SEARCH);

  if (Fail)
    return Fail;
  setObjectName(tmp);

  Fail = configbuffer.getVariable("Concentration", "C_FLOAT64",
                                  (void *) & mIConc);

  if (Fail)
    return Fail;

  Fail = configbuffer.getVariable("Compartment", "C_INT32",
                                  (void *) & mCompartment);

  if (Fail)
    return Fail;

  C_INT32 Status;

  Fail = configbuffer.getVariable("Type", "C_INT32",
                                  (void *) & Status);

  mStatus = (CMetab::Status) Status;

  // sanity check
  if ((mStatus < 0) || (mStatus > 7))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a non-existing type "
                     "for '%s'.\nReset to internal metabolite.",
                     getObjectName().c_str());
      mStatus = CMetab::METAB_VARIABLE;
    }

  // sanity check
  if ((mStatus != METAB_MOIETY) && (mIConc < 0.0))
    {
      CCopasiMessage(CCopasiMessage::WARNING,
                     "The file specifies a negative concentration "
                     "for '%s'.\nReset to default.",
                     getObjectName().c_str());
      mIConc = 1.0;
    }

  return Fail;
}

C_INT32 CMetabOld::getIndex() const {return mCompartment;}
<|endoftext|>


<commit_before>/*
  ==============================================================================

    This file was auto-generated!

    It contains the basic framework code for a JUCE plugin editor.

  ==============================================================================
*/

#include "PluginProcessor.h"
#include "PluginEditor.h"

//==============================================================================
VispiControllerVstAudioProcessorEditor::VispiControllerVstAudioProcessorEditor (VispiControllerVstAudioProcessor& p, AudioProcessorValueTreeState& vts)
    : AudioProcessorEditor(&p), processor(p), valueTreeState(vts), videoTable("Video list", nullptr)
{
    // Make sure that before the constructor has finished, you've set the
    // editor's size to whatever you need it to be.
    setSize (400, 300);

    //videoTableHeader = new VideoTableHeader();
    videoTable.setHeader(new VideoTableHeader());

    videoTableModel = new VideoTableContents(processor);
    videoTable.setModel(videoTableModel);
    addAndMakeVisible(videoTable);

    reloadButton.setButtonText("Reload Playlist");
    addAndMakeVisible(reloadButton);
    reloadButton.addListener(this);

    loopButton.setButtonText("Loop");
    addAndMakeVisible(loopButton);
    loopButtonAttachment = new ButtonAttachment (valueTreeState, "loop", loopButton);

    messenger = processor.getMessenger();
    messenger->addChangeListener(this);
}

VispiControllerVstAudioProcessorEditor::~VispiControllerVstAudioProcessorEditor()
{
    messenger->removeChangeListener(this);
    reloadButton.removeListener(this);

    loopButtonAttachment = nullptr;

    //videoTableHeader = nullptr;
    // delete this:
    videoTableModel = nullptr;
    // before the list it references
}

void VispiControllerVstAudioProcessorEditor::changeListenerCallback(ChangeBroadcaster *source) {
    if(source==messenger) {
        //std::cout << "word from the messenger" << std::endl;
        videoTable.selectRow(processor.getSelectedVideoIndex());
    }
}

void VispiControllerVstAudioProcessorEditor::buttonClicked(Button* button)
{
    if(button == &reloadButton) {
        reloadPlaylist();
    }

}

void VispiControllerVstAudioProcessorEditor::reloadPlaylist()
{
    processor.reloadPlaylist();
    videoTable.updateContent();
    videoTable.deselectAllRows();
    videoTable.autoSizeAllColumns();

}

//==============================================================================
void VispiControllerVstAudioProcessorEditor::paint (Graphics& g)
{
    g.fillAll (Colours::white);

    g.setColour (Colours::black);
    g.setFont (15.0f);
    //g.drawFittedText (String(processor.getVideoSelection()), getLocalBounds(), Justification::centred, 1);
}

void VispiControllerVstAudioProcessorEditor::resized()
{
    // This is generally where you'll want to lay out the positions of any
    // subcomponents in your editor..
    Rectangle<int> r (getLocalBounds().reduced(8));
    //videoListBox.setBounds(r.withSize(250, 180));
    videoTable.setBounds(r.removeFromLeft(220));
    videoTable.autoSizeAllColumns();
    reloadButton.setBounds(r.removeFromTop(40).reduced(10));
}

VispiControllerVstAudioProcessorEditor::VideoTableContents::VideoTableContents(VispiControllerVstAudioProcessor& p) : processor(p)
{}

int VispiControllerVstAudioProcessorEditor::VideoTableContents::getNumRows() {
    return processor.getNumFiles();
}

void VispiControllerVstAudioProcessorEditor::VideoTableContents::paintCell(Graphics& g, int rowNumber, int columnId, int width, int height, bool rowIsSelected)
{
    if(rowNumber >= getNumRows()) return;
    g.setColour(Colours::black);

    g.setFont(height * 0.7f);
    // ScopedLock...?
    String content;
    switch(columnId) {
        case INDEX_COLUMN:
            content = String(rowNumber);
            break;
        case NOTE_COLUMN:
            content = MidiMessage::getMidiNoteName(rowNumber, true, true, 3);
            break;
        case NAME_COLUMN:
            content = processor.getFileName(rowNumber);
            break;
        default:
            break;
    }
    g.drawText(content, 5, 0, width, height, Justification::centredLeft, true);
}

void VispiControllerVstAudioProcessorEditor::VideoTableContents::paintRowBackground(juce::Graphics & g, int rowNumber, int width, int height, bool rowIsSelected)
{
    //if(rowNumber >= getNumRows()) return;
    if(rowIsSelected) {
        g.fillAll(Colours::cornflowerblue);
    } else {
        g.fillAll(Colours::cornsilk);
    }

}

void VispiControllerVstAudioProcessorEditor::VideoTableContents::cellClicked(int rowNumber, int columnId, const MouseEvent& e)
{
    if(rowNumber != -1) {
        processor.processVideoSelection(rowNumber);
    }
}

VispiControllerVstAudioProcessorEditor::VideoTableHeader::VideoTableHeader()
{
    // gross - think more about where to set these things correctly
    // resized if possible
    addColumn("Index", INDEX_COLUMN, 50, 50, -1, defaultFlags);
    addColumn("Note", NOTE_COLUMN, 50, 50, -1, defaultFlags);
    addColumn("Name", NAME_COLUMN, 120, 50, -1, defaultFlags);
}
<commit_msg>another baby step after a mare<commit_after>/*
  ==============================================================================

    This file was auto-generated!

    It contains the basic framework code for a JUCE plugin editor.

  ==============================================================================
*/

#include "PluginProcessor.h"
#include "PluginEditor.h"

//==============================================================================
VispiControllerVstAudioProcessorEditor::VispiControllerVstAudioProcessorEditor (VispiControllerVstAudioProcessor& p, AudioProcessorValueTreeState& vts)
    : AudioProcessorEditor(&p), processor(p), valueTreeState(vts), videoTable("Video list", nullptr)
{
    // Make sure that before the constructor has finished, you've set the
    // editor's size to whatever you need it to be.
    setSize (400, 300);

    //videoTableHeader = new VideoTableHeader();
    videoTable.setHeader(new VideoTableHeader());

    videoTableModel = new VideoTableContents(processor);
    videoTable.setModel(videoTableModel);
    addAndMakeVisible(videoTable);

    reloadButton.setButtonText("Reload Playlist");
    addAndMakeVisible(reloadButton);
    reloadButton.addListener(this);

    loopButton.setButtonText("Loop");
    addAndMakeVisible(loopButton);
    loopButtonAttachment = new ButtonAttachment (valueTreeState, "loop", loopButton);

    messenger = processor.getMessenger();
    messenger->addChangeListener(this);
}

VispiControllerVstAudioProcessorEditor::~VispiControllerVstAudioProcessorEditor()
{
    messenger->removeChangeListener(this);
    reloadButton.removeListener(this);

    loopButtonAttachment = nullptr;

    //videoTableHeader = nullptr;
    // delete this:
    videoTableModel = nullptr;
    // before the list it references
}

void VispiControllerVstAudioProcessorEditor::changeListenerCallback(ChangeBroadcaster *source) {
    if(source==messenger) {
        //std::cout << "word from the messenger" << std::endl;
        videoTable.selectRow(processor.getSelectedVideoIndex());
    }
}

void VispiControllerVstAudioProcessorEditor::buttonClicked(Button* button)
{
    if(button == &reloadButton) {
        reloadPlaylist();
    }

}

void VispiControllerVstAudioProcessorEditor::reloadPlaylist()
{
    processor.reloadPlaylist();
    videoTable.updateContent();
    videoTable.deselectAllRows();
    videoTable.autoSizeAllColumns();

}

//==============================================================================
void VispiControllerVstAudioProcessorEditor::paint (Graphics& g)
{
    g.fillAll (Colours::white);

    g.setColour (Colours::black);
    g.setFont (15.0f);
    //g.drawFittedText (String(processor.getVideoSelection()), getLocalBounds(), Justification::centred, 1);
}

void VispiControllerVstAudioProcessorEditor::resized()
{
    // This is generally where you'll want to lay out the positions of any
    // subcomponents in your editor..
    Rectangle<int> r (getLocalBounds().reduced(8));
    //videoListBox.setBounds(r.withSize(250, 180));
    videoTable.setBounds(r.removeFromLeft(220));
    videoTable.autoSizeAllColumns();
    reloadButton.setBounds(r.removeFromTop(40).reduced(10));
    loopButton.setBounds(r.removeFromTop(40).reduced(10));
}

VispiControllerVstAudioProcessorEditor::VideoTableContents::VideoTableContents(VispiControllerVstAudioProcessor& p) : processor(p)
{}

int VispiControllerVstAudioProcessorEditor::VideoTableContents::getNumRows() {
    return processor.getNumFiles();
}

void VispiControllerVstAudioProcessorEditor::VideoTableContents::paintCell(Graphics& g, int rowNumber, int columnId, int width, int height, bool rowIsSelected)
{
    if(rowNumber >= getNumRows()) return;
    g.setColour(Colours::black);

    g.setFont(height * 0.7f);
    // ScopedLock...?
    String content;
    switch(columnId) {
        case INDEX_COLUMN:
            content = String(rowNumber);
            break;
        case NOTE_COLUMN:
            content = MidiMessage::getMidiNoteName(rowNumber, true, true, 3);
            break;
        case NAME_COLUMN:
            content = processor.getFileName(rowNumber);
            break;
        default:
            break;
    }
    g.drawText(content, 5, 0, width, height, Justification::centredLeft, true);
}

void VispiControllerVstAudioProcessorEditor::VideoTableContents::paintRowBackground(juce::Graphics & g, int rowNumber, int width, int height, bool rowIsSelected)
{
    //if(rowNumber >= getNumRows()) return;
    if(rowIsSelected) {
        g.fillAll(Colours::cornflowerblue);
    } else {
        g.fillAll(Colours::cornsilk);
    }

}

void VispiControllerVstAudioProcessorEditor::VideoTableContents::cellClicked(int rowNumber, int columnId, const MouseEvent& e)
{
    if(rowNumber != -1) {
        processor.processVideoSelection(rowNumber);
    }
}

VispiControllerVstAudioProcessorEditor::VideoTableHeader::VideoTableHeader()
{
    // gross - think more about where to set these things correctly
    // resized if possible
    addColumn("Index", INDEX_COLUMN, 50, 50, -1, defaultFlags);
    addColumn("Note", NOTE_COLUMN, 50, 50, -1, defaultFlags);
    addColumn("Name", NAME_COLUMN, 120, 50, -1, defaultFlags);
}
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2010 Aldebaran Robotics
*/

#include <iostream>
#include <gtest/gtest.h>
#include <protobuf/message.h>
#include <protobuf/dynamic_message.h>
#include <protobuf/descriptor.h>
#include "myproto.pb.h"

using namespace google::protobuf;

TEST(TestProtoSerialization, Basic) {
  testproto::Person p;
  p.set_name("toto");

  testproto::Person_PhoneNumber *phone = p.add_phone();
  phone->set_number("0642");

  std::cout << p.phone(0).number() << std::endl;

  std::cout << p.name() << std::endl;

  std::cout << "ProtoTest" << std::endl;
}
<commit_msg>lolcommit<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2010 Aldebaran Robotics
*/

#include <iostream>
#include <gtest/gtest.h>
#include <protobuf/message.h>
#include <protobuf/dynamic_message.h>
#include <protobuf/descriptor.h>
#include "myproto.pb.h"

using namespace google::protobuf;

int toto(int i)
{
  return i + 42;
}

TEST(TestProtoSerialization, Basic) {
  testproto::Person p;
  p.set_name("toto");

  testproto::Person_PhoneNumber *phone = p.add_phone();
  phone->set_number("0642");

  std::cout << p.phone(0).number() << std::endl;

  std::cout << p.name() << std::endl;

  std::cout << "ProtoTest" << std::endl;
}
<|endoftext|>