From ff8d018ab5570a5744e2704a90d48acf3349c501 Mon Sep 17 00:00:00 2001 From: Diane Trout Date: Tue, 14 Mar 2006 07:57:20 +0000 Subject: [PATCH] load and display a motif list Mussagl can now load a motif list from a text file in the form AAGGGCCTT 1.0 0.5 0.0 (The trailing numbers are the red, green, blue channels) and motifs are properly displayed on the sequence tracks. I did this by attaching an AnnotationColors color mapper to the mussa analysis and passing it to the glsequence class for rendering. --- alg/annotation_colors.cpp | 16 +++-- alg/annotation_colors.hpp | 9 ++- alg/glsequence.cpp | 21 ++++++- alg/glsequence.hpp | 4 +- alg/mussa.cpp | 93 ++++++++++++++++++++++++++++++ alg/mussa.hpp | 26 ++++++++- alg/sequence.cpp | 23 +++++--- alg/sequence.hpp | 18 +++++- alg/test/test_annotation_color.cpp | 3 + alg/test/test_glsequence.cpp | 18 ++++-- alg/test/test_mussa.cpp | 25 ++++++++ alg/test/test_sequence.cpp | 2 + examples/test_motif.txt | 2 + mussa_exceptions.hpp | 7 +++ py/glsequence.cpp | 3 +- qui/PathScene.cpp | 26 ++++++++- qui/PathScene.hpp | 4 +- qui/PathWindow.cpp | 7 +-- qui/PathWindow.hpp | 1 - 19 files changed, 268 insertions(+), 40 deletions(-) create mode 100644 examples/test_motif.txt diff --git a/alg/annotation_colors.cpp b/alg/annotation_colors.cpp index aab22d1..a84d459 100644 --- a/alg/annotation_colors.cpp +++ b/alg/annotation_colors.cpp @@ -22,11 +22,17 @@ AnnotationColors::AnnotationColors() { } -AnnotationColors::AnnotationColors(AnnotationColors &ac) +AnnotationColors::AnnotationColors(const AnnotationColors &ac) : root_map(ac.root_map) { } +void AnnotationColors::clear() +{ + root_map.cm.clear(); + root_map.defaultColor = Color(0.0, 0.0, 0.0); +} + void AnnotationColors::setColor(Color &c) { root_map.defaultColor = c; @@ -71,19 +77,19 @@ void AnnotationColors::erase(const string &type, root_map.cm[type].cm.erase(instance); } -Color AnnotationColors::lookup(const annot &a) +Color AnnotationColors::lookup(const annot &a) const { return lookup(a.type, a.name); } -Color AnnotationColors::lookup(const string &type, const string &instance) +Color AnnotationColors::lookup(const string &type, const string &instance) const { // Yeah, there's probably a nicer looking recursive solution // to this problem. - DefaultColorMap::iterator type_map = root_map.cm.find(type); + DefaultColorMap::const_iterator type_map = root_map.cm.find(type); if (type_map != root_map.cm.end() ) { // found lookup instance - DefaultColorMap::iterator instance_map = type_map->second.cm.find(instance); + DefaultColorMap::const_iterator instance_map = type_map->second.cm.find(instance); if (instance_map != type_map->second.cm.end() ) { return instance_map->second.defaultColor; } else { diff --git a/alg/annotation_colors.hpp b/alg/annotation_colors.hpp index 96efa25..2fdb4f1 100644 --- a/alg/annotation_colors.hpp +++ b/alg/annotation_colors.hpp @@ -12,6 +12,7 @@ struct DefaultColorMap { typedef std::map color_map_type; typedef color_map_type::iterator iterator; + typedef color_map_type::const_iterator const_iterator; DefaultColorMap(); //! initialize color map with a default color DefaultColorMap(const Color &); @@ -27,8 +28,10 @@ class AnnotationColors { public: AnnotationColors(); - AnnotationColors(AnnotationColors &); + AnnotationColors(const AnnotationColors &); + // clear all the contents of our mappers + void clear(); //! set default color void setColor(Color &); //! retreive default color @@ -52,8 +55,8 @@ public: void erase(const std::string &type, const std::string& instance); //! lookup an annotation color - Color lookup(const annot &); - Color lookup(const std::string &, const std::string &); + Color lookup(const annot &) const; + Color lookup(const std::string &, const std::string &) const; private: // nested maps, with default? DefaultColorMap root_map; diff --git a/alg/glsequence.cpp b/alg/glsequence.cpp index 62896aa..674dcb0 100644 --- a/alg/glsequence.cpp +++ b/alg/glsequence.cpp @@ -6,23 +6,25 @@ #include using namespace std; -GlSequence::GlSequence(const Sequence &s) +GlSequence::GlSequence(const Sequence &s, AnnotationColors& cm) : seq(s), seq_x(0.0), seq_y(0.0), seq_z(1.0), seq_height(12.0), + color_mapper(cm), drawColor(0.0, 0.0, 0.0), char_pix_per_world_unit(5.0) { } -GlSequence::GlSequence(const GlSequence &s) +GlSequence::GlSequence(const GlSequence &s) : seq(s.seq), seq_x(s.seq_x), seq_y(s.seq_y), seq_z(s.seq_z), seq_height(s.seq_height), + color_mapper(s.color_mapper), drawColor(s.drawColor), char_pix_per_world_unit(s.char_pix_per_world_unit) { @@ -36,6 +38,7 @@ GlSequence &GlSequence::operator=(const GlSequence & s) seq_y = s.seq_y; seq_z = s.seq_z; seq_height = s.seq_height; + color_mapper = s.color_mapper; drawColor = s.drawColor; assert(char_pix_per_world_unit == s.char_pix_per_world_unit); } @@ -203,7 +206,8 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const // draw annotations glLineWidth(seq_height); GLfloat annotation_z = seq_z + 1.0; - std::list annots = seq.annotations(); + const std::list& annots = seq.annotations(); + const std::list& motifs = seq.motifs(); for (std::list::const_iterator annot_itor = annots.begin(); annot_itor != annots.end(); ++annot_itor, ++annotation_z) @@ -212,8 +216,19 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const draw_box(seq_x+annot_itor->start, seq_x+annot_itor->end, seq_height, annotation_z); } + // if motifs? + for (std::list::const_iterator motifs_itor = motifs.begin(); + motifs_itor != motifs.end(); + ++motifs_itor, ++annotation_z) + { + glColor3fv(color_mapper.lookup("motif", motifs_itor->sequence).get()); + draw_box(seq_x+motifs_itor->start, seq_x+motifs_itor->end, + seq_height, annotation_z); + } + } + const int PT = 1; const int STROKE = 2; const int END =3; diff --git a/alg/glsequence.hpp b/alg/glsequence.hpp index aeedf47..c8c9b2b 100644 --- a/alg/glsequence.hpp +++ b/alg/glsequence.hpp @@ -1,6 +1,7 @@ #ifndef _GL_SEQUENCE_H_ #define _GL_SEQUENCE_H_ +#include "alg/annotation_colors.hpp" #include "alg/sequence.hpp" #include "alg/color.hpp" #include @@ -11,7 +12,7 @@ class GlSequence { public: - GlSequence(const Sequence & s); + GlSequence(const Sequence & s, AnnotationColors &cm); GlSequence(const GlSequence & s); GlSequence &operator=(const GlSequence &s); @@ -73,6 +74,7 @@ protected: GLfloat seq_y; GLfloat seq_z; GLfloat seq_height; + AnnotationColors& color_mapper; Color drawColor; const GLfloat char_pix_per_world_unit; diff --git a/alg/mussa.cpp b/alg/mussa.cpp index 224daa7..fa54eb2 100644 --- a/alg/mussa.cpp +++ b/alg/mussa.cpp @@ -27,6 +27,19 @@ Mussa::Mussa() clear(); } +Mussa::Mussa(const Mussa& m) + : analysis_name(m.analysis_name), + window(m.window), + threshold(m.threshold), + soft_thres(m.soft_thres), + ana_mode(m.ana_mode), + win_append(m.win_append), + thres_append(m.thres_append), + motif_sequences(m.motif_sequences), + color_mapper(m.color_mapper) +{ +} + // set all parameters to null state void Mussa::clear() @@ -38,6 +51,8 @@ Mussa::clear() soft_thres = 0; win_append = false; thres_append = false; + motif_sequences.clear(); + color_mapper.clear(); } // these 5 simple methods manually set the parameters for doing an analysis @@ -628,3 +643,81 @@ Mussa::load_old(char * load_file_path, int s_num) //the_paths.save("tmp.save"); } + +// I mostly split the ifstream out so I can use a stringstream to test it. +void Mussa::load_motifs(std::istream &in) +{ + string seq; + float red; + float green; + float blue; + + while(in.good()) + { + in >> seq >> red >> green >> blue; + // if we couldn't read this line 'cause we're like at the end of the file + // try to exit the loop + if (!in.good()) + break; + try { + seq = Sequence::motif_normalize(seq); + } catch(motif_normalize_error e) { + clog << "unable to parse " << seq << " skipping" << endl; + clog << e.what() << endl; + continue; + } + if (red < 0.0 or red > 1.0) { + clog << "invalid red value " << red << ". must be in range [0..1]" + << endl; + continue; + } + if (green < 0.0 or green > 1.0) { + clog << "invalid green value " << green << ". must be in range [0..1]" + << endl; + continue; + } + if (blue < 0.0 or blue > 1.0) { + clog << "invalid blue value " << blue << ". must be in range [0..1]" + << endl; + continue; + } + if (motif_sequences.find(seq) == motif_sequences.end()) { + // sequence wasn't found + motif_sequences.insert(seq); + Color c(red, green, blue); + color_mapper.appendInstanceColor("motif", seq, c); + } else { + clog << "sequence " << seq << " was already defined skipping" + << endl; + continue; + } + } + // once we've loaded all the motifs from the file, + // lets attach them to the sequences + for(vector::iterator seq_i = the_seqs.begin(); + seq_i != the_seqs.end(); + ++seq_i) + { + // clear out old motifs + seq_i->clear_motifs(); + // for all the motifs in our set, attach them to the current sequence + for(set::iterator motif_i = motif_sequences.begin(); + motif_i != motif_sequences.end(); + ++motif_i) + { + seq_i->add_motif(*motif_i); + } + } +} + +void Mussa::load_motifs(string filename) +{ + ifstream f; + f.open(filename.c_str(), ifstream::in); + load_motifs(f); +} + +AnnotationColors& Mussa::colorMapper() +{ + return color_mapper; +} diff --git a/alg/mussa.hpp b/alg/mussa.hpp index c5a5ba0..ded2a8b 100644 --- a/alg/mussa.hpp +++ b/alg/mussa.hpp @@ -17,7 +17,10 @@ #include #include #include +#include +#include +#include "alg/annotation_colors.hpp" #include "alg/nway_paths.hpp" #include "alg/sequence.hpp" @@ -30,7 +33,8 @@ class Mussa enum analysis_modes { TransitiveNway, RadialNway, EntropyNway, RecursiveNway }; - Mussa(); + Mussa(); + Mussa(const Mussa &); void save(); void save_muway(std::string save_path); @@ -110,6 +114,21 @@ class Mussa void save_old(); void load_old(char * load_file_path, int s_num); + // manage motif lists + //! load motifs from an ifstream + /*! The file should look something like + * + * where sequence is a string of IUPAC symbols + * and red,green,blue are a white space separated list of floats + * in the range [0.0, 1.0] + */ + void load_motifs(std::istream &); + //! load a list of motifs from a file named filename + void load_motifs(std::string filename); + + //! return color mapper + AnnotationColors& colorMapper(); + private: // Private variables // parameters needed for a mussa analysis @@ -135,6 +154,11 @@ class Mussa //! N-way data, ie the mussa results NwayPaths the_paths; + //! motif list + std::set motif_sequences; + //! color manager + AnnotationColors color_mapper; + // Private methods //! loads sequence and annotations from fasta and annotation file void seqcomp(); diff --git a/alg/sequence.cpp b/alg/sequence.cpp index 5c7f069..4161bfc 100644 --- a/alg/sequence.cpp +++ b/alg/sequence.cpp @@ -584,7 +584,7 @@ Sequence::rc_motif(string a_motif) } string -Sequence::motif_validate(string a_motif) +Sequence::motif_normalize(string a_motif) { string valid_motif; int seq_i, len; @@ -596,7 +596,7 @@ Sequence::motif_validate(string a_motif) // current nonIUPAC symbols are omitted, which is not reported atm for(seq_i = 0; seq_i < len; seq_i++) { - if ((a_motif[seq_i] == 'a') || (a_motif[seq_i] == 'A')) + if ((a_motif[seq_i] == 'a') || (a_motif[seq_i] == 'A')) valid_motif += 'A'; else if ((a_motif[seq_i] == 't') || (a_motif[seq_i] == 'T')) valid_motif += 'T'; @@ -626,10 +626,14 @@ Sequence::motif_validate(string a_motif) valid_motif += 'D'; else if ((a_motif[seq_i] == 'b') || (a_motif[seq_i] == 'B')) valid_motif += 'B'; - } - + else { + string msg = "Letter "; + msg += a_motif[seq_i]; + msg += " is not a valid IUPAC symbol"; + throw motif_normalize_error(msg); + } + } //cout << "valid_motif is: " << valid_motif << endl; - return valid_motif; } @@ -637,7 +641,6 @@ void Sequence::add_motif(string a_motif) { vector motif_starts = find_motif(a_motif); - for(vector::iterator motif_start_i = motif_starts.begin(); motif_start_i != motif_starts.end(); ++motif_start_i) @@ -646,6 +649,11 @@ void Sequence::add_motif(string a_motif) } } +void Sequence::clear_motifs() +{ + motif_list.clear(); +} + const list& Sequence::motifs() const { return motif_list; @@ -660,10 +668,9 @@ Sequence::find_motif(string a_motif) motif_match_starts.clear(); //cout << "motif is: " << a_motif << endl; - a_motif = motif_validate(a_motif); + a_motif = motif_normalize(a_motif); //cout << "motif is: " << a_motif << endl; - if (a_motif != "") { //cout << "Sequence: none blank motif\n"; diff --git a/alg/sequence.hpp b/alg/sequence.hpp index 9b52497..e4771f2 100644 --- a/alg/sequence.hpp +++ b/alg/sequence.hpp @@ -28,8 +28,10 @@ struct annot annot(); annot(int start, int end, std::string type, std::string name); - int start, end; - std::string name, type; + int start; + int end; + std::string type; + std::string name; }; /* The way that motifs are found currently doesn't really @@ -59,7 +61,6 @@ class Sequence void motif_scan(std::string a_motif, std::vector * motif_match_starts); std::string rc_motif(std::string a_motif); - std::string motif_validate(std::string a_motif); public: typedef std::string::iterator iterator; typedef std::string::const_iterator const_iterator; @@ -109,8 +110,19 @@ class Sequence const std::string& get_header() const; //! add a motif to our list of motifs + /*! \throws motif_normalize_error if there's something wrong with a_motif + */ void add_motif(std::string a_motif); + //! clear our list of found motifs + void clear_motifs(); + //! search a sequence for a_motif + /*! \throws motif_normalize_error if there's something wrong with a_motif + */ std::vector find_motif(std::string a_motif); + //! convert IUPAC symbols to upperase + /*! \throws motif_normalize_error if there is an invalid symbol + */ + static std::string motif_normalize(std::string a_motif); void save(std::fstream &save_file); void load_museq(std::string load_file_path, int seq_num); }; diff --git a/alg/test/test_annotation_color.cpp b/alg/test/test_annotation_color.cpp index af7035b..2e2a56e 100644 --- a/alg/test/test_annotation_color.cpp +++ b/alg/test/test_annotation_color.cpp @@ -36,5 +36,8 @@ BOOST_AUTO_TEST_CASE( simple_annot_colors ) BOOST_CHECK_EQUAL( ac.lookup(a), black ); a.type = "venchent"; BOOST_CHECK_EQUAL( ac.lookup(a), white ); + + ac.clear(); + BOOST_CHECK_EQUAL( ac.lookup("bleem", "a"), black); } diff --git a/alg/test/test_glsequence.cpp b/alg/test/test_glsequence.cpp index 220b455..563af53 100644 --- a/alg/test/test_glsequence.cpp +++ b/alg/test/test_glsequence.cpp @@ -2,6 +2,7 @@ #include +#include "alg/annotation_colors.hpp" #include "alg/glsequence.hpp" #include "alg/sequence.hpp" @@ -9,15 +10,16 @@ using namespace std; BOOST_AUTO_TEST_CASE ( glsequence_operator_equal ) { + AnnotationColors cm; // I don't trust my operator = hack so lets make sure it works. string s0("AAGGCCTT"); string s1("TTGGCCAA"); Sequence seq0(s0); Sequence seq1(s1); - GlSequence glseq0(seq0); + GlSequence glseq0(seq0, cm); BOOST_CHECK (glseq0.sequence().get_seq() == s0); - GlSequence glseq1(seq1); + GlSequence glseq1(seq1, cm); GlSequence glseq_copy0(glseq0); BOOST_CHECK(glseq_copy0.sequence().get_seq() == glseq0.sequence().get_seq()); @@ -30,10 +32,11 @@ BOOST_AUTO_TEST_CASE ( glsequence_operator_equal ) BOOST_AUTO_TEST_CASE( glsequence_color ) { + AnnotationColors cm; Color black(0.0, 0.0, 0.0, 0.0); Color c(0.1, 0.2, 0.3, 0.4); Sequence seq("AAGGCCTT"); - GlSequence s(seq); + GlSequence s(seq, cm); BOOST_CHECK_EQUAL(s.color(), black ); s.setColor( c ); @@ -42,8 +45,9 @@ BOOST_AUTO_TEST_CASE( glsequence_color ) BOOST_AUTO_TEST_CASE( glsequence_renderable ) { + AnnotationColors cm; Sequence seq("AAGGCCTT"); - GlSequence s(seq); + GlSequence s(seq, cm); // way more base pairs than viewport pixel width BOOST_CHECK_EQUAL(s.is_sequence_renderable( 0, 1000, 500), false ); @@ -53,10 +57,11 @@ BOOST_AUTO_TEST_CASE( glsequence_renderable ) BOOST_AUTO_TEST_CASE( glsequence_sequence ) { + AnnotationColors cm; string seq_string("AAGGCCTTNNAAGGCCTTNNAAGGCCTTNN"); string::size_type seqlen = seq_string.size(); Sequence seq(seq_string); - GlSequence glseq(seq); + GlSequence glseq(seq, cm); BOOST_CHECK( glseq.sequence_begin(0, 50) == seq.begin() ); // always make sure we return seq.end() regardless of how much extra @@ -94,9 +99,10 @@ BOOST_AUTO_TEST_CASE( glsequence_sequence ) // make sure the computation of the leftmost and rightmost base is correct BOOST_AUTO_TEST_CASE( glsequence_leftright_base ) { + AnnotationColors cm; std::string seq_string = "AAGGCCTT"; Sequence seq(seq_string); - GlSequence glseq(seq); + GlSequence glseq(seq, cm); BOOST_CHECK_EQUAL( glseq.leftbase( -50.0 ), 0 ); BOOST_CHECK_EQUAL( glseq.leftbase( 0.5 ), 1 ); diff --git a/alg/test/test_mussa.cpp b/alg/test/test_mussa.cpp index 6d9036f..1ca85a4 100644 --- a/alg/test/test_mussa.cpp +++ b/alg/test/test_mussa.cpp @@ -1,9 +1,13 @@ #include #include +#include +#include #include "alg/mussa.hpp" +using namespace std; + //! can we initialize a mussa object? BOOST_AUTO_TEST_CASE( mussa_simple ) { @@ -106,3 +110,24 @@ BOOST_AUTO_TEST_CASE( mussa_load_full_path ) BOOST_CHECK( m1.size() > 0); } + +BOOST_AUTO_TEST_CASE( mussa_load_motif ) +{ + string data = "AAGG 1.0 1.0 0.0\n" + "GGTT 0.0 0.1 1.0\n" + "ZXY 2 1.9 0\n"; + + istringstream test_istream(data); + + Mussa m1; + m1.add_a_seq("AAAAGGGGTTTT"); + m1.add_a_seq("GGGCCCCTTGGTT"); + m1.load_motifs(test_istream); + + for (vector::const_iterator seq_i = m1.sequences().begin(); + seq_i != m1.sequences().end(); + ++seq_i) + { + BOOST_CHECK( seq_i->motifs().size() > 0 ); + } +} diff --git a/alg/test/test_sequence.cpp b/alg/test/test_sequence.cpp index 0a5cab2..bbc5068 100644 --- a/alg/test/test_sequence.cpp +++ b/alg/test/test_sequence.cpp @@ -123,6 +123,8 @@ BOOST_AUTO_TEST_CASE( sequence_motifs ) BOOST_CHECK_EQUAL( motif_i->sequence, m); } + s1.clear_motifs(); + BOOST_CHECK( s1.motifs().begin() == s1.motifs().end() ); } BOOST_AUTO_TEST_CASE( annot_test ) diff --git a/examples/test_motif.txt b/examples/test_motif.txt new file mode 100644 index 0000000..3a692e1 --- /dev/null +++ b/examples/test_motif.txt @@ -0,0 +1,2 @@ +TATAAA 0.9 0 0.9 +GGCC 0.0 1 1 diff --git a/mussa_exceptions.hpp b/mussa_exceptions.hpp index 701c5e5..53c167c 100644 --- a/mussa_exceptions.hpp +++ b/mussa_exceptions.hpp @@ -24,4 +24,11 @@ public: explicit mussa_analysis_error(const std::string& msg) : std::runtime_error(msg) {}; }; + +class motif_normalize_error : public std::runtime_error +{ +public: + explicit motif_normalize_error(const std::string& msg) : + std::runtime_error(msg) {}; +}; #endif diff --git a/py/glsequence.cpp b/py/glsequence.cpp index 213ce63..cd43244 100644 --- a/py/glsequence.cpp +++ b/py/glsequence.cpp @@ -1,12 +1,13 @@ #include using namespace boost::python; +#include "alg/annotation_colors.hpp" #include "alg/glsequence.hpp" #include "alg/sequence.hpp" void export_glsequence() { - class_("GlSequence", init()) + class_("GlSequence", init()) .def(init()) .def("draw", &GlSequence::draw) .def("sequence", &GlSequence::sequence, diff --git a/qui/PathScene.cpp b/qui/PathScene.cpp index 3f0e335..7040b69 100644 --- a/qui/PathScene.cpp +++ b/qui/PathScene.cpp @@ -112,6 +112,30 @@ void PathScene::setClipPlane(int newZ) } } +void PathScene::loadMotifList() +{ + QString caption("Load a motif list"); + QString filter("Motif list(*.txt *.mtl)"); + QString path = QFileDialog::getOpenFileName(this, + caption, + QDir::currentPath(), + filter); + // user hit cancel? + if (path.isNull()) + return; + // try to load safely + try { + mussaAnalysis->load_motifs(path.toStdString()); + updateScene(); + } catch (runtime_error e) { + QString msg("Unable to load "); + msg += path; + msg += "\n"; + msg += e.what(); + QMessageBox::warning(this, "Load Motifs", msg); + } + assert (mussaAnalysis != 0); +} void PathScene::loadMupa() { QString caption("Load a mussa parameter file"); @@ -245,7 +269,7 @@ void PathScene::updateScene() ++seq_itor) { y = y - 100; - gl_seq = new GlSequence(*seq_itor); + gl_seq = new GlSequence(*seq_itor, mussaAnalysis->colorMapper()); gl_seq->setX(0); gl_seq->setY(y); if (gl_seq->length() > max_base_pairs ) max_base_pairs = gl_seq->length(); diff --git a/qui/PathScene.hpp b/qui/PathScene.hpp index 98e5ad5..547e113 100644 --- a/qui/PathScene.hpp +++ b/qui/PathScene.hpp @@ -39,8 +39,10 @@ public slots: void setViewportX(float x); //! set our magnification level void setZoom(int); + //! load motifs + void loadMotifList(); //! load a mussa parameter file (which specifies an analysis to run) - void loadMupa( ); + void loadMupa(); //! load a previously run analysis void loadSavedAnalysis(); //! set the soft threshold used by the Nway_Path algorithm diff --git a/qui/PathWindow.cpp b/qui/PathWindow.cpp index 5a7c47f..67ce139 100644 --- a/qui/PathWindow.cpp +++ b/qui/PathWindow.cpp @@ -91,7 +91,7 @@ void PathWindow::setupActions() loadMotifListAction = new QAction(tr("Load Motif List"), this); connect(loadMotifListAction, SIGNAL(triggered()), - this, SLOT(loadMotifList())); + scene, SLOT(loadMotifList())); loadMupaAction = new QAction(tr("Load Mussa Parameters"), this); connect(loadMupaAction, SIGNAL(triggered()), @@ -178,11 +178,6 @@ void PathWindow::createSubAnalysis() NotImplementedBox(); } -void PathWindow::loadMotifList() -{ - NotImplementedBox(); -} - void PathWindow::saveMotifList() { NotImplementedBox(); diff --git a/qui/PathWindow.hpp b/qui/PathWindow.hpp index ce63d18..96048b8 100644 --- a/qui/PathWindow.hpp +++ b/qui/PathWindow.hpp @@ -29,7 +29,6 @@ public slots: //! \defgroup MotifHandling Handling of motif lists //\@{ - void loadMotifList(); void saveMotifList(); void toggleMotifs(); //\@} -- 2.30.2