Getting closer to a subanalysis mode
authorDiane Trout <diane@caltech.edu>
Fri, 23 Jun 2006 01:56:58 +0000 (01:56 +0000)
committerDiane Trout <diane@caltech.edu>
Fri, 23 Jun 2006 01:56:58 +0000 (01:56 +0000)
This is a big patch, in order to create the subanalysis mode I wanted a
class that'd hold a reference to a sequence and some start/stop locations
which'd let the user edit what region they want to use in the subanalysis
before creating the new analysis.

I started setting up a SequenceLocation and SequenceLocationModel (for
the qt MVC classes) but then I learned that C++ reference types aren't
particularly good things to store in containers, as when the original
variable that all the references are pointing to goes away you get
invalid memory exceptions.

So I went through and switched most of those references to the
boost::shared_ptr which is a fairly simple reference counted pointer.

This did make most of the C++ code happy, but my python wrapping
is increasingly losing functionality.

Also as a bonus this increased use of pointers I think will improve the
sharing of the AnnotationColors color mappers.

26 files changed:
alg/CMakeLists.txt
alg/glseqbrowser.cpp
alg/glseqbrowser.hpp
alg/glsequence.cpp
alg/glsequence.hpp
alg/mussa.cpp
alg/mussa.hpp
alg/sequence.cpp
alg/sequence_location.cpp [new file with mode: 0644]
alg/sequence_location.hpp [new file with mode: 0644]
alg/test/CMakeLists.txt
alg/test/test_glseqbrowser.cpp
alg/test/test_glsequence.cpp
alg/test/test_mussa.cpp
alg/test/test_sequence_location.cpp [new file with mode: 0644]
py/glsequence.cpp
py/mussa.cpp
qui/CMakeLists.txt
qui/MussaWindow.cpp
qui/SequenceLocationModel.cpp [new file with mode: 0644]
qui/SequenceLocationModel.hpp [new file with mode: 0644]
qui/SubanalysisWindow.cpp
qui/SubanalysisWindow.hpp
qui/motif_editor/MotifEditor.cpp
qui/seqbrowser/SequenceBrowserWidget.cpp
qui/seqbrowser/SequenceBrowserWidget.hpp

index 299a3f3cb144931800d1ab1447b34b2a5e1a5f67..5eeb55513d800591cdc2d55cb0537b16e49096af 100644 (file)
@@ -21,7 +21,8 @@ SET(SOURCES annotation_colors.cpp
             nway_other.cpp 
             nway_paths.cpp
             parse_options.cpp 
-            sequence.cpp)
+            sequence.cpp
+            sequence_location.cpp )
 
 ADD_LIBRARY( mussa_core STATIC ${SOURCES} ${MOC_SOURCES})
 INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR}
index 2a159afd05b1690acc95aa111c74e40c797f4687..4e18733fbc7c7d7805593dfda8a6ea1d42276bd2 100644 (file)
@@ -7,14 +7,6 @@
 
 using namespace std;
 
-GlSeqBrowser::SequenceLocation::SequenceLocation(
-    const Sequence& s, 
-    int l, 
-    int c
-) : sequence(s), left(l), count(c)
-{
-}
-
 GlSeqBrowser::GlSeqBrowser()
   : border_width(25),
     cur_ortho(400.0, 0.0, 600.0, 0.0),
@@ -293,14 +285,14 @@ double GlSeqBrowser::zoom() const
   return zoom_level;
 }
 
-void GlSeqBrowser::setColorMapper(AnnotationColors& cm)
+void GlSeqBrowser::setColorMapper(boost::shared_ptr<AnnotationColors> cm)
 {
   color_mapper = cm;
 }
 
-AnnotationColors& GlSeqBrowser::colorMapper()
+const AnnotationColors& GlSeqBrowser::colorMapper()
 {
-  return color_mapper;
+  return *color_mapper;
 }
 
 void GlSeqBrowser::clear()
@@ -319,13 +311,21 @@ void GlSeqBrowser::clear_selection()
   selected_tracks.clear();
 }
 
-void GlSeqBrowser::push_sequence(const Sequence &s)
+void GlSeqBrowser::push_sequence(const Sequence& s)
+{
+  boost::shared_ptr<Sequence> seq_copy(new Sequence(s));
+  GlSequence gs(seq_copy, color_mapper);
+  push_sequence(gs);
+}
+
+
+void GlSeqBrowser::push_sequence(boost::shared_ptr<Sequence> s)
 {
   GlSequence gs(s, color_mapper);
   push_sequence(gs);
 }
 
-void GlSeqBrowser::push_sequence(GlSequence &gs)
+void GlSeqBrowser::push_sequence(GlSequence gs)
 {
   clear_links();
   track_container.push_back(gs);
@@ -466,11 +466,10 @@ void GlSeqBrowser::copySelectedTracksAsSequences(std::list<Sequence>& result)
 }
 
 void GlSeqBrowser::copySelectedTracksAsSeqLocation(
-    std::list<GlSeqBrowser::SequenceLocation>& result)
+    std::list<SequenceLocation>& result)
 {
   struct AsSeqLocation {
-    static GlSeqBrowser::SequenceLocation 
-           formatter(const Sequence& seq, int left, int right)
+    static SequenceLocation formatter(const Sequence& seq, int left, int right)
     {
       return SequenceLocation(seq, left, right);
     }
index 80d80a810403f27106f86088c39a91f23248a3db..fab880fdba11c1ecae442e23a76e96811de2d35b 100644 (file)
@@ -1,5 +1,6 @@
 #ifndef _GLTRACKS_H_
 #define _GLTRACKS_H_
+#include <boost/shared_ptr.hpp>
 
 #include <map>
 #include <set>
@@ -8,6 +9,7 @@
 #include "alg/annotation_colors.hpp"
 #include "alg/sequence.hpp"
 #include "alg/glsequence.hpp"
+#include "alg/sequence_location.hpp"
 
 //! Manage rendering a collection of glSequences
 class GlSeqBrowser
@@ -58,18 +60,20 @@ public:
   //! center the provided path in the current viewport
   void centerOnPath(const std::vector<int>&);
 
-  void setColorMapper(AnnotationColors& cm);
-  AnnotationColors& colorMapper();
+  void setColorMapper(boost::shared_ptr<AnnotationColors> cm);
+  const AnnotationColors& colorMapper();
 
   //! clear our tracks and connections
   void clear();
   //! clear everything related to a selection
   void clear_selection();
 
+  //! add a sequence to the back of our track container (makes copy of s)
+  void push_sequence(const Sequence& s);
   //! add a sequence to the back of our track container
-  void push_sequence(const Sequence &s);
+  void push_sequence(boost::shared_ptr<Sequence> s);
   //! add a glsequence to the back of our track container
-  void push_sequence(GlSequence &s);
+  void push_sequence(GlSequence s);
   //! return our track container
   const std::vector<GlSequence>& sequences() const;
 
@@ -90,13 +94,6 @@ public:
   //! copy sequence from selected tracks as plain sequences
   void copySelectedTracksAsString(std::string& copy_buffer);
 
-  //! convenience structure for holding selected track segments
-  struct SequenceLocation {
-    const Sequence& sequence;
-    int left;
-    int count;
-    SequenceLocation(const Sequence& s, int l, int c);
-  };
   //! copy tracks as a sequence and its coordinates
   void copySelectedTracksAsSeqLocation(std::list<SequenceLocation>& result);
   
@@ -198,7 +195,7 @@ private:
   //! the center of our current viewport (world coord) (used for scrollbar)
   float viewport_center;
   double zoom_level;
-  AnnotationColors color_mapper;
+  boost::shared_ptr<AnnotationColors> color_mapper;
   //! container of all the GlSequences loaded into our scene
   std::vector<GlSequence> track_container;
   //! counter for each path added to us via connect
index 8af0adbe03fbdbc3af960e8efa9d40ad626f6af9..54a13fad5af915e8dd28190ceae135147e43b9ca 100644 (file)
@@ -6,7 +6,8 @@
 #include <stdexcept>
 using namespace std;
 
-GlSequence::GlSequence(const Sequence &s, AnnotationColors& cm) 
+GlSequence::GlSequence(boost::shared_ptr<Sequence> s, 
+                       boost::shared_ptr<AnnotationColors> cm) 
   : seq(s),
     seq_x(0.0), 
     seq_y(0.0), 
@@ -33,7 +34,7 @@ GlSequence::GlSequence(const GlSequence &s)
 GlSequence &GlSequence::operator=(const GlSequence & s)
 {
   if (this != &s) {
-    const_cast<Sequence &>(seq) = s.seq;
+    seq = s.seq;
     seq_x = s.seq_x;
     seq_y = s.seq_y;
     seq_z = s.seq_z;
@@ -47,7 +48,7 @@ GlSequence &GlSequence::operator=(const GlSequence & s)
 
 const Sequence& GlSequence::sequence() const
 {
-  return seq;
+  return *seq;
 }
 
 void GlSequence::setX(GLfloat value)
@@ -82,7 +83,7 @@ GLfloat GlSequence::height() const
 
 GLfloat GlSequence::length() const
 {
-  return seq.size();
+  return seq->size();
 }
 
 Sequence::size_type GlSequence::leftbase(GLfloat left) const
@@ -90,8 +91,8 @@ Sequence::size_type GlSequence::leftbase(GLfloat left) const
   left = ceil(left - seq_x);
   if (left < 0)
     return 0;
-  else if (left > seq.size() )
-    return seq.size();
+  else if (left > seq->size() )
+    return seq->size();
   else
     return (Sequence::size_type)left;
 }
@@ -99,8 +100,8 @@ Sequence::size_type GlSequence::leftbase(GLfloat left) const
 Sequence::size_type GlSequence::rightbase(GLfloat right) const
 {
   right = floor(right) - seq_x;
-  if (right > seq.size())
-    return seq.size();
+  if (right > seq->size())
+    return seq->size();
   else if ( right < 0) 
     return 0;
   else 
@@ -109,30 +110,30 @@ Sequence::size_type GlSequence::rightbase(GLfloat right) const
 
 Sequence::const_iterator GlSequence::sequence_begin() const
 {
-  return seq.begin();
+  return seq->begin();
 }
 
 Sequence::const_iterator GlSequence::sequence_end() const
 {
-  return seq.end();
+  return seq->end();
 }
 
 Sequence::const_iterator 
 GlSequence::sequence_begin(GLfloat left, GLfloat right) const
 {
-  if ( leftbase(left) > seq.size() or left > right )
-    return seq.end();
+  if ( leftbase(left) > seq->size() or left > right )
+    return seq->end();
   else
-    return seq.begin() + leftbase(left);
+    return seq->begin() + leftbase(left);
 }
 
 Sequence::const_iterator 
 GlSequence::sequence_end(GLfloat left, GLfloat right) const
 {
-  if ( rightbase(right) > seq.size() or left > right )
-    return seq.end();
+  if ( rightbase(right) > seq->size() or left > right )
+    return seq->end();
   else
-    return seq.begin() + rightbase(right); 
+    return seq->begin() + rightbase(right); 
 }
 
 
@@ -221,15 +222,15 @@ void GlSequence::draw_track(GLfloat left, GLfloat right) const
 {
   glColor3fv(drawColor.get());
   // draw main sequence track
-  draw_box(left, right, seq_x, seq_x+seq.size(), seq_height, 0.0);
+  draw_box(left, right, seq_x, seq_x+seq->size(), seq_height, 0.0);
 }
 
 void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
 {
   // draw annotations
   GLfloat annotation_z = seq_z + 10.0;
-  const std::list<annot>& annots = seq.annotations();
-  const std::list<motif>& motifs = seq.motifs();
+  const std::list<annot>& annots = seq->annotations();
+  const std::list<motif>& motifs = seq->motifs();
   for (std::list<annot>::const_iterator annot_itor = annots.begin();
        annot_itor != annots.end();
        ++annot_itor)
@@ -243,7 +244,7 @@ void GlSequence::draw_annotations(GLfloat left, GLfloat right) const
        motifs_itor != motifs.end();
        ++motifs_itor)
   {
-    glColor3fv(color_mapper.lookup("motif", motifs_itor->sequence).get());
+    glColor3fv(color_mapper->lookup("motif", motifs_itor->sequence).get());
     draw_box(left, right, seq_x+motifs_itor->start, seq_x+motifs_itor->end, 
              seq_height, annotation_z+1.0);
   }
@@ -321,7 +322,7 @@ void GlSequence::draw_sequence(GLfloat left, GLfloat right) const
   assert(seq_end - seq_itor >= 0);
   while(seq_itor != seq_end)
   {
-    assert ( basepair < seq.size() );
+    assert ( basepair < seq->size() );
     glPushMatrix();
     glTranslatef( seq_x+leftbase(left) + basepair, seq_y, 1.0 );
     glScalef(0.1, 1.0, 1.0);
index c20e1945b11414d0090e829c60d0abc2b87624ec..5b08fb31a272eacd48197b7a9bb23089c7ccfd32 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _GL_SEQUENCE_H_
 #define _GL_SEQUENCE_H_
 
+#include <boost/shared_ptr.hpp>
+
 #include "alg/annotation_colors.hpp"
 #include "alg/sequence.hpp"
 #include "alg/color.hpp"
@@ -18,7 +20,8 @@
 class GlSequence
 {
 public: 
-  GlSequence(const Sequence & s, AnnotationColors &cm);
+  GlSequence(boost::shared_ptr<Sequence> s, 
+             boost::shared_ptr<AnnotationColors> cm);
   GlSequence(const GlSequence & s);
   GlSequence &operator=(const GlSequence &s);
 
@@ -83,12 +86,12 @@ public:
   friend bool operator==(const GlSequence &left, const GlSequence &right);
 
 protected:
-  const Sequence& seq;
+  boost::shared_ptr<Sequence> seq;
   GLfloat seq_x;
   GLfloat seq_y;
   GLfloat seq_z;
   GLfloat seq_height;
-  AnnotationColors& color_mapper;
+  boost::shared_ptr<AnnotationColors> color_mapper;
   Color drawColor;
   const GLfloat char_pix_per_world_unit;
 
index 4677a6c84e871c0db9cac12dfa0ae20eedf76f18..79078b2cb1447b3ba4c2ca46d0a3500116fc2337 100644 (file)
@@ -27,6 +27,7 @@ using namespace std;
 
 
 Mussa::Mussa()
+  : color_mapper(new AnnotationColors)
 {
   clear();
   connect(&the_paths, SIGNAL(progress(const std::string&, int, int)), 
@@ -60,7 +61,7 @@ Mussa::clear()
   win_append = false;
   thres_append = false;
   motif_sequences.clear();
-  color_mapper.clear();
+  if(color_mapper) color_mapper->clear();
   the_paths.clear();
 }
 
@@ -173,7 +174,7 @@ void Mussa::createLocalAlignment(std::list<ConservedPath>::iterator begin,
                                  std::list<ConservedPath::path_type>& result,
                                  std::list<std::vector<bool> >& reversed)
 {
-  const vector<Sequence>& raw_seq = the_seqs;
+  const vector_sequence_type& raw_seq = the_seqs;
   ConservedPath::path_type aligned_path;
   size_t i2, i3;
   int x_start, x_end;
@@ -213,15 +214,17 @@ void Mussa::createLocalAlignment(std::list<ConservedPath>::iterator begin,
         x_start = (abs(a_path[i2]-rc_1+win_i));
         x_end =   (abs(a_path[i2+1]-rc_2+win_i));
         
+        boost::shared_ptr<Sequence> cur(raw_seq[i2]) ;
+        boost::shared_ptr<Sequence> next(raw_seq[i2+1]);
         // RC case handling
         // ugh, and xor...only want rc coloring if just one of the nodes is rc
         // if both nodes are rc, then they are 'normal' relative to each other
         if((rc_list[i2] || rc_list[i2+1] )&&!(rc_list[i2] && rc_list[i2+1]))
         { //the hideous rc matching logic - not complex, but annoying
-          if(!(( (raw_seq[i2][x_start]=='A')&&(raw_seq[i2+1][x_end]=='T')) ||
-                ((raw_seq[i2][x_start]=='T')&&(raw_seq[i2+1][x_end]=='A')) ||
-                ((raw_seq[i2][x_start]=='G')&&(raw_seq[i2+1][x_end]=='C')) ||
-                ((raw_seq[i2][x_start]=='C')&&(raw_seq[i2+1][x_end]=='G'))) ) 
+          if(!(( ((*cur)[x_start]=='A')&&((*next)[x_end]=='T')) ||
+                (((*cur)[x_start]=='T')&&((*next)[x_end]=='A')) ||
+                (((*cur)[x_start]=='G')&&((*next)[x_end]=='C')) ||
+                (((*cur)[x_start]=='C')&&((*next)[x_end]=='G'))) ) 
           {
             full_match = false;
           } else {
@@ -230,9 +233,8 @@ void Mussa::createLocalAlignment(std::list<ConservedPath>::iterator begin,
         }
         else
         { // forward match
-          if (!( (raw_seq[i2][x_start] == raw_seq[i2+1][x_end]) &&
-                (raw_seq[i2][x_start] != 'N') &&
-                (raw_seq[i2+1][x_end] != 'N') ) ) {
+          if (!( ((*cur)[x_start] == (*next)[x_end]) &&
+                ((*cur)[x_start] != 'N') && ((*next)[x_end] != 'N') ) ) {
             full_match = false;
           } else {
             aligned_path.push_back(x_start);
@@ -253,12 +255,19 @@ void Mussa::createLocalAlignment(std::list<ConservedPath>::iterator begin,
 }
 
 
-void Mussa::append_sequence(Sequence a_seq)
+void Mussa::append_sequence(const Sequence& a_seq)
+{
+  boost::shared_ptr<Sequence> seq_copy(new Sequence(a_seq));
+  the_seqs.push_back(seq_copy);
+}
+
+void Mussa::append_sequence(boost::shared_ptr<Sequence> a_seq)
 {
   the_seqs.push_back(a_seq);
 }
 
-const vector<Sequence>& 
+
+const vector<boost::shared_ptr<Sequence> >& 
 Mussa::sequences() const
 {
   return the_seqs;
@@ -267,10 +276,10 @@ Mussa::sequences() const
 void Mussa::load_sequence(fs::path seq_file, fs::path annot_file, 
                           int fasta_index, int sub_seq_start, int sub_seq_end)
 {
-  Sequence aseq;
-  aseq.load_fasta(seq_file, fasta_index, sub_seq_start, sub_seq_end);
+  boost::shared_ptr<Sequence> aseq(new Sequence);
+  aseq->load_fasta(seq_file, fasta_index, sub_seq_start, sub_seq_end);
   if ( not annot_file.empty() ) {
-    aseq.load_annot(annot_file, sub_seq_start, sub_seq_end);
+    aseq->load_annot(annot_file, sub_seq_start, sub_seq_end);
   }
   the_seqs.push_back(aseq);
 }
@@ -451,7 +460,7 @@ Mussa::seqcomp()
       all_comps[i].push_back(dummy_comp);
   }
   for(vector<Sequence>::size_type i = 0; i < the_seqs.size(); i++) {
-    seq_lens.push_back(the_seqs[i].size());
+    seq_lens.push_back(the_seqs[i]->size());
   }
   int seqcomps_done = 0;
   int seqcomps_todo = (the_seqs.size() * (the_seqs.size()-1)) / 2;
@@ -462,8 +471,8 @@ Mussa::seqcomp()
     {
       //cout << "seqcomping: " << i << " v. " << i2 << endl;
       all_comps[i][i2].setup(window, threshold);
-      all_comps[i][i2].seqcomp(the_seqs[i], the_seqs[i2], false);
-      all_comps[i][i2].seqcomp(the_seqs[i], the_seqs[i2].rev_comp(),true);
+      all_comps[i][i2].seqcomp(*the_seqs[i], *the_seqs[i2], false);
+      all_comps[i][i2].seqcomp(*the_seqs[i], the_seqs[i2]->rev_comp(),true);
       ++seqcomps_done;
       emit progress("seqcomp", seqcomps_done, seqcomps_todo);
     }
@@ -472,7 +481,6 @@ Mussa::seqcomp()
 void
 Mussa::nway()
 {
-  vector<string> some_Seqs;
 
   the_paths.set_soft_threshold(soft_thres);
 
@@ -484,11 +492,12 @@ Mussa::nway()
   }
   else if (ana_mode == EntropyNway)
   {
+    vector<string> some_Seqs;
     //unlike other methods, entropy needs to look at the sequence at this stage
     some_Seqs.clear();
     for(vector<Sequence>::size_type i = 0; i < the_seqs.size(); i++)
     {
-      some_Seqs.push_back(the_seqs[i]);
+      some_Seqs.push_back(*the_seqs[i]);
     }
 
     the_paths.setup_ent(ent_thres, some_Seqs); // ent analysis extra setup
@@ -541,7 +550,7 @@ Mussa::save()
 
     for(vector<Sequence>::size_type i = 0; i < the_seqs.size(); i++)
     {
-      the_seqs[i].save(save_file);
+      the_seqs[i]->save(save_file);
     }
 
     save_file << "</Mussa_Sequence>" << endl;
@@ -574,7 +583,6 @@ Mussa::load(fs::path ana_file)
   fs::path a_file_path; 
   fs::path ana_path(ana_file);
   bool parsing_path;
-  Sequence tmp_seq;
   string err_msg;
   ostringstream append_info;
   vector<FLPs> empty_FLP_vector;
@@ -600,9 +608,9 @@ Mussa::load(fs::path ana_file)
   // this is a bit of a hack due to C++ not acting like it should with files
   for (i = 1; i <= seq_num; i++)
   {
-    tmp_seq.clear();
+    boost::shared_ptr<Sequence> tmp_seq(new Sequence);
     //cout << "mussa_class: loading museq frag... " << a_file_path.string() << endl;
-    tmp_seq.load_museq(a_file_path, i);
+    tmp_seq->load_museq(a_file_path, i);
     the_seqs.push_back(tmp_seq);
   }
   
@@ -638,7 +646,7 @@ Mussa::save_old()
   save_file.open(analysis_name, ios::out);
 
   for(vector<Sequence>::size_type i = 0; i < the_seqs.size(); i++)
-    save_file << the_seqs[i] << endl;
+    save_file << *(the_seqs[i]) << endl;
 
   save_file << window << endl;
   save_file.close();
@@ -668,7 +676,7 @@ Mussa::load_old(char * load_file_path, int s_num)
   for(i = 0; i < seq_num; i++)
   {
     getline(save_file, file_data_line);
-    a_seq = file_data_line;
+    boost::shared_ptr<Sequence> a_seq(new Sequence(file_data_line));
     the_seqs.push_back(a_seq);
   }
 
@@ -712,7 +720,7 @@ void Mussa::add_motifs(const vector<string>& motifs,
   for(size_t i = 0; i != motifs.size(); ++i)
   {
     motif_sequences.insert(motifs[i]);
-    color_mapper.appendInstanceColor("motif", motifs[i], colors[i]);
+    color_mapper->appendInstanceColor("motif", motifs[i], colors[i]);
   }
   update_sequences_motifs();
 }
@@ -758,7 +766,7 @@ void Mussa::load_motifs(std::istream &in)
       // sequence wasn't found
       motif_sequences.insert(seq);
       Color c(red, green, blue);
-      color_mapper.appendInstanceColor("motif", seq, c);
+      color_mapper->appendInstanceColor("motif", seq, c);
     } else {
       clog << "sequence " << seq << " was already defined skipping" 
            << endl;
@@ -779,18 +787,18 @@ void Mussa::update_sequences_motifs()
 {
   // once we've loaded all the motifs from the file, 
   // lets attach them to the sequences
-  for(vector<Sequence>::iterator seq_i = the_seqs.begin();
+  for(vector<boost::shared_ptr<Sequence> >::iterator seq_i = the_seqs.begin();
       seq_i != the_seqs.end();
       ++seq_i)
   {
     // clear out old motifs
-    seq_i->clear_motifs();
+    (*seq_i)->clear_motifs();
     // for all the motifs in our set, attach them to the current sequence
     for(set<string>::iterator motif_i = motif_sequences.begin();
         motif_i != motif_sequences.end();
         ++motif_i)
     {
-      seq_i->add_motif(*motif_i);
+      (*seq_i)->add_motif(*motif_i);
     }
   }
 }
@@ -800,7 +808,7 @@ const set<string>& Mussa::motifs() const
   return motif_sequences;
 }
 
-AnnotationColors& Mussa::colorMapper()
+boost::shared_ptr<AnnotationColors> Mussa::colorMapper()
 {
   return color_mapper;
 }
index 6f7d0a33fb5c4846f6d252e953e9b8c83dad13b0..25663494bd339091f9056a07d920ec58b0d6cf6d 100644 (file)
@@ -16,6 +16,7 @@
 #include <QObject> 
 
 #include <boost/filesystem/path.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <list>
 #include <string>
@@ -113,8 +114,10 @@ public:
 
     //! appends a string sequence to the list of the_seqs
     // void append_sequence(std::string a_seq);
-    //! appends a sequence to the list of the_seqs
-    void append_sequence(Sequence a_seq);
+    //! appends a sequence to the list of the_seqs (makes copy)
+    void append_sequence(const Sequence& a_seq);
+    //! append a sequence to the list of seqs (shared)
+    void append_sequence(boost::shared_ptr<Sequence> a_seq);
 
     //! Load a sequence from a fasta file and any annotations
     /*! \param[in] seq_file the full path to the fasta file
@@ -131,7 +134,8 @@ public:
                        boost::filesystem::path annot_file, 
                        int fasta_index, int sub_seq_start=0, int sub_seq_end=0);
     //! allow examining the sequences we have loaded
-    const std::vector<Sequence>& sequences() const;
+    typedef std::vector<boost::shared_ptr<Sequence> > vector_sequence_type;
+    const vector_sequence_type& sequences() const;
 
     // deprecated - support bridge for python version of mussa
     // these save & load from the old file format
@@ -160,7 +164,7 @@ public:
     const std::set<std::string>& motifs() const;
 
     //! return color mapper
-    AnnotationColors& colorMapper();
+    boost::shared_ptr<AnnotationColors> colorMapper();
 
   private:
     //! push motifs to our attached sequences
@@ -184,7 +188,7 @@ public:
     bool thres_append;
 
     //! sequence data
-    std::vector<Sequence> the_seqs;
+    vector_sequence_type the_seqs;
     //! the seqcomp data
     std::vector<std::vector<FLPs> > all_comps;
     //! N-way data, ie the mussa results  
@@ -193,7 +197,7 @@ public:
     //! motif list
     std::set<std::string> motif_sequences;
     //! color manager
-    AnnotationColors color_mapper;
+    boost::shared_ptr<AnnotationColors> color_mapper;
 
     // Private methods
     //! runs all the seqcomps needed to support the nway comparison
index 56bad887f584252f289c6fa62bb1794d4c35fa22..3863346358c3cb1ba65154213f67dbf32c9d38fa 100644 (file)
@@ -89,8 +89,6 @@ Sequence::Sequence()
     header(""),
     species("")
 {
-  annots.clear();
-  motif_list.clear();
 }
 
 Sequence::~Sequence()
@@ -98,11 +96,15 @@ Sequence::~Sequence()
 }
 
 Sequence::Sequence(const char *seq)
+  : header(""),
+    species("")
 {
   set_filtered_sequence(seq);
 }
 
 Sequence::Sequence(const std::string& seq) 
+  : header(""),
+    species("")
 {
   set_filtered_sequence(seq);
 }
@@ -539,14 +541,6 @@ Sequence::get_header() const
 {
   return header;
 }
-/*
-//FIXME: i don't think this code is callable
-std::string 
-Sequence::sp_name() const
-{
-  return species;
-}
-*/
 
 /*
 std::string 
diff --git a/alg/sequence_location.cpp b/alg/sequence_location.cpp
new file mode 100644 (file)
index 0000000..cc92c2f
--- /dev/null
@@ -0,0 +1,76 @@
+#include "alg/sequence_location.hpp"
+    
+SequenceLocation::SequenceLocation(
+    const boost::shared_ptr<Sequence> s, 
+    int l, 
+    int c
+) : sequence(s), 
+    left(l), 
+    count(c)
+{
+}
+
+SequenceLocation::SequenceLocation(
+    const Sequence& s, 
+    int l, 
+    int c
+) : left(l), 
+    count(c)
+{
+  boost::shared_ptr<Sequence> copy(new Sequence(s));
+  sequence = copy;
+}
+
+
+SequenceLocation::SequenceLocation(const SequenceLocation& o) 
+  : sequence(o.sequence),
+    left(o.left),
+    count(o.count)
+{
+}
+
+SequenceLocation& SequenceLocation::operator=(const SequenceLocation& o)
+{
+  if (this != &o) {
+    sequence = o.sequence;
+    left = o.left;
+    count = o.count;
+  }
+  return *this;
+}
+
+
+const Sequence& SequenceLocation::getSequence() const
+{
+  return *sequence;
+}
+
+void SequenceLocation::setLeft(int l)
+{
+  left = l;
+}
+
+int SequenceLocation::getLeft() const
+{
+  return left;
+}
+
+void SequenceLocation::setCount(int c)
+{
+  count = c;
+}
+
+int SequenceLocation::getCount() const
+{
+  return count;
+}
+
+void SequenceLocation::setRight(int r)
+{
+  count = r-left;
+}
+
+int SequenceLocation::getRight() const
+{
+  return left+count;
+}
diff --git a/alg/sequence_location.hpp b/alg/sequence_location.hpp
new file mode 100644 (file)
index 0000000..12830f7
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _SEQUENCE_LOCATION_H_
+#define _SEQUENCE_LOCATION_H_
+
+#include <boost/shared_ptr.hpp>
+#include "alg/sequence.hpp"
+
+//! convenience structure for holding selected track segments
+class SequenceLocation {
+  public:
+    SequenceLocation(boost::shared_ptr<Sequence> s, int l, int c);
+    SequenceLocation(const Sequence& s, int l, int c);
+    SequenceLocation(const SequenceLocation& );
+    SequenceLocation& operator=(const SequenceLocation&);
+
+    const Sequence& getSequence() const;
+    void setLeft(int l);
+    int getLeft() const;
+    void setCount(int c);
+    int getCount() const ;
+    void setRight(int r);
+    int getRight() const;
+
+  private:
+    boost::shared_ptr<Sequence> sequence;
+    int left;
+    int count;
+  };
+#endif
index a8694e71a606807a085c4b54432cc766d11bdc53..70e505a6ce4745b80b24654223782a537b12c242 100644 (file)
@@ -1,6 +1,7 @@
 SET(SOURCES test_annotation_color.cpp test_color.cpp test_conserved_path.cpp
             test_flp.cpp test_glseqbrowser.cpp test_glsequence.cpp
-            test_main.cpp test_mussa.cpp test_nway.cpp test_sequence.cpp)
+            test_main.cpp test_mussa.cpp test_nway.cpp 
+            test_sequence.cpp test_sequence_location.cpp )
 
 # dont you love the number of \ you need to make sure the " shows up in
 # the C compiler?
index 0a3f8c976204f5313d8e1dd2a5123034ba9256b2..336d0052f6c7c0b4d15f82bb8e09ad8659a2c40e 100644 (file)
@@ -2,6 +2,8 @@
 #include <boost/assign/std/vector.hpp>
 using namespace boost::assign;
 
+#include <boost/shared_ptr.hpp>
+
 #include <string>
 #include <list>
 #include <vector>
@@ -50,10 +52,10 @@ BOOST_AUTO_TEST_CASE( glseqbrowser_center )
   string s0("AAGGCCTT");
   string s1("TTGGCCAA");
   string s2("GATTACAA");
-  Sequence seq0(s0);
-  Sequence seq1(s1);
-  Sequence seq2(s2);
-  AnnotationColors cm;
+  boost::shared_ptr<Sequence> seq0(new Sequence(s0));
+  boost::shared_ptr<Sequence> seq1(new Sequence(s1));
+  boost::shared_ptr<Sequence> seq2(new Sequence(s2));
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
   GlSequence glseq0(seq0, cm);
   GlSequence glseq1(seq1, cm);
   GlSequence glseq2(seq2, cm);
index 32fc0ad9cc10aa7f8624e3c5aeddff6aeee70003..b0aa6ad545a8d4ec2ab1a1610e458302a0e6cf8c 100644 (file)
@@ -1,5 +1,6 @@
 #include <boost/test/auto_unit_test.hpp>
 #include <boost/test/floating_point_comparison.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include <string>
 
 
 using namespace std;
 
-BOOST_AUTO_TEST_CASE ( glsequence_operator_equal )
+BOOST_AUTO_TEST_CASE ( glsequence_operator_assignment )
 {
-  AnnotationColors cm;
-  // I don't trust my operator = hack so lets make sure it works.
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
+  // 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);
+  boost::shared_ptr<Sequence> seq0(new Sequence(s0));
+  boost::shared_ptr<Sequence> seq1(new Sequence(s1));
 
   GlSequence glseq0(seq0, cm);
   BOOST_CHECK (glseq0.sequence() == s0);
@@ -27,16 +28,15 @@ BOOST_AUTO_TEST_CASE ( glsequence_operator_equal )
   BOOST_CHECK( &(glseq_copy0.sequence()) == &(glseq0.sequence()));
 
   glseq0 = glseq1;
-
   BOOST_CHECK( glseq0.sequence() == s1 );
 }
 
 BOOST_AUTO_TEST_CASE( glsequence_color )
 {
-  AnnotationColors cm;
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
   Color black(0.0, 0.0, 0.0, 0.0);
   Color c(0.1, 0.2, 0.3, 0.4);
-  Sequence seq("AAGGCCTT");
+  boost::shared_ptr<Sequence> seq(new Sequence("AAGGCCTT"));
   GlSequence s(seq, cm);
   
   BOOST_CHECK_EQUAL(s.color(), black );
@@ -46,8 +46,8 @@ BOOST_AUTO_TEST_CASE( glsequence_color )
 
 BOOST_AUTO_TEST_CASE( glsequence_renderable )
 {
-  AnnotationColors cm;
-  Sequence seq("AAGGCCTT");
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
+  boost::shared_ptr<Sequence> seq(new Sequence("AAGGCCTT"));
   GlSequence s(seq, cm);
 
   // way more base pairs than viewport pixel width 
@@ -61,26 +61,26 @@ BOOST_AUTO_TEST_CASE( glsequence_renderable )
 
 BOOST_AUTO_TEST_CASE( glsequence_sequence )
 {
-  AnnotationColors cm;
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
   string seq_string("AAGGCCTTNNAAGGCCTTNNAAGGCCTTNN");
   string::size_type seqlen = seq_string.size();
-  Sequence seq(seq_string);
+  boost::shared_ptr<Sequence> seq(new Sequence(seq_string));
   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
+  BOOST_CHECK( glseq.sequence_begin(0, 50) == seq->begin() );
+  // always make sure we return seq->end() regardless of how much extra
   // is asked for
-  BOOST_CHECK( glseq.sequence_end(0, seqlen+10) == seq.end() );
+  BOOST_CHECK( glseq.sequence_end(0, seqlen+10) == seq->end() );
   // do we get the right end pointer?
-  BOOST_CHECK( glseq.sequence_end(0, 5) == seq.begin()+5 );
+  BOOST_CHECK( glseq.sequence_end(0, 5) == seq->begin()+5 );
 
   // when we request far too much sequence what do we get?
-  BOOST_CHECK( glseq.sequence_begin(seqlen+10, seqlen+20) == seq.end() );
-  BOOST_CHECK( glseq.sequence_end(seqlen+10, seqlen+20) == seq.end() );
+  BOOST_CHECK( glseq.sequence_begin(seqlen+10, seqlen+20) == seq->end() );
+  BOOST_CHECK( glseq.sequence_end(seqlen+10, seqlen+20) == seq->end() );
 
   // we cant ask for reversed sequences with sequence_begin/end
-  BOOST_CHECK( glseq.sequence_begin(10, 5) == seq.end() );
-  BOOST_CHECK( glseq.sequence_end(10, 5) == seq.end() );
+  BOOST_CHECK( glseq.sequence_begin(10, 5) == seq->end() );
+  BOOST_CHECK( glseq.sequence_end(10, 5) == seq->end() );
 
   Sequence::const_iterator seq_itor;
 
@@ -90,9 +90,9 @@ BOOST_AUTO_TEST_CASE( glsequence_sequence )
 
   // reuse seq_itor downhere 
   string::const_iterator str_itor;
-  for(str_itor = seq.begin(),
+  for(str_itor = seq->begin(),
       seq_itor = glseq.sequence_begin();
-      str_itor != seq.end() and 
+      str_itor != seq->end() and 
       seq_itor != glseq.sequence_end();
       ++str_itor, ++seq_itor)
   {
@@ -103,9 +103,9 @@ 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;
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
   std::string seq_string = "AAGGCCTT";
-  Sequence seq(seq_string);
+  boost::shared_ptr<Sequence> seq(new Sequence(seq_string));
   GlSequence glseq(seq, cm);
 
   BOOST_CHECK_EQUAL( glseq.leftbase( -50.0 ), 0 );
@@ -122,9 +122,9 @@ BOOST_AUTO_TEST_CASE( glsequence_leftright_base )
 // we move the sequence around?
 BOOST_AUTO_TEST_CASE( glsequence_movex )
 {
-  AnnotationColors cm;
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
   std::string seq_string = "AAGGCCTTAAGGCCTT";
-  Sequence seq(seq_string);
+  boost::shared_ptr<Sequence> seq(new Sequence(seq_string));
   GlSequence glseq(seq, cm);
 
   glseq.setX(-5);
@@ -140,23 +140,51 @@ BOOST_AUTO_TEST_CASE( glsequence_movex )
 // Check iterators
 BOOST_AUTO_TEST_CASE( glsequence_check_iterators )
 {
-  AnnotationColors cm;
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
   std::string seq_string = "AAGGCCTTAAGGCCTT";
-  Sequence seq(seq_string);
+  boost::shared_ptr<Sequence> seq(new Sequence(seq_string));
   GlSequence glseq(seq, cm);
 
   Sequence::const_iterator seq_begin_i;
   Sequence::const_iterator seq_end_i;
 
-  BOOST_CHECK(glseq.sequence_begin(5, -5) == seq.end());
-  BOOST_CHECK(glseq.sequence_begin(0, 20) == seq.begin());
-  BOOST_CHECK(glseq.sequence_begin(10,20) == seq.begin()+10);
+  BOOST_CHECK(glseq.sequence_begin(5, -5) == seq->end());
+  BOOST_CHECK(glseq.sequence_begin(0, 20) == seq->begin());
+  BOOST_CHECK(glseq.sequence_begin(10,20) == seq->begin()+10);
 
-  BOOST_CHECK(glseq.sequence_end(5, -5) == seq.end());
-  BOOST_CHECK(glseq.sequence_end(0, 20) == seq.end());
-  BOOST_CHECK(glseq.sequence_end(0, 10) == seq.begin()+10);
+  BOOST_CHECK(glseq.sequence_end(5, -5) == seq->end());
+  BOOST_CHECK(glseq.sequence_end(0, 20) == seq->end());
+  BOOST_CHECK(glseq.sequence_end(0, 10) == seq->begin()+10);
 
   glseq.setX(-5);
-  BOOST_CHECK(glseq.sequence_begin(0, 10) == seq.begin()+5);
-  BOOST_CHECK(glseq.sequence_end(0, 15) == seq.end());
+  BOOST_CHECK(glseq.sequence_begin(0, 10) == seq->begin()+5);
+  BOOST_CHECK(glseq.sequence_end(0, 15) == seq->end());
 }
+
+BOOST_AUTO_TEST_CASE ( shared_ptr_test )
+{
+  boost::shared_ptr<AnnotationColors> cm(new AnnotationColors);
+  // I don't trust my operator= hack so lets make sure it works.
+  string s0("AAGGCCTT");
+  string s1("TTGGCCAA");
+  boost::shared_ptr<Sequence> seq0(new Sequence(s0));
+  BOOST_CHECK_EQUAL( seq0.use_count(), 1 );
+  boost::shared_ptr<Sequence> seq1(new Sequence(s1));
+  BOOST_CHECK_EQUAL( seq0.use_count(), 1 );
+
+  // make a block to test deallocation
+  {
+    GlSequence glseq0(seq0, cm);
+    BOOST_CHECK_EQUAL(seq0.use_count(), 2);
+    GlSequence glseq1(seq1, cm);
+    BOOST_CHECK_EQUAL(seq1.use_count(), 2);
+
+    glseq0 = glseq1;
+    BOOST_CHECK_EQUAL( seq0.use_count(), 1 );
+    BOOST_CHECK_EQUAL( seq1.use_count(), 3 );
+  }
+  BOOST_CHECK_EQUAL(seq0.use_count(), 1);
+  BOOST_CHECK_EQUAL(seq1.use_count(), 1);
+}
+
+
index 79356abcbe85ee46baddc0d406cefd1f74b0d4d0..2ab594a10107eb0bcd2c3bc82193ccad966722b7 100644 (file)
@@ -70,9 +70,9 @@ BOOST_AUTO_TEST_CASE( mussa_sequences )
   analysis.append_sequence(s2);
 
   BOOST_CHECK_EQUAL( analysis.sequences().size(), 3 );
-  BOOST_CHECK_EQUAL( analysis.sequences()[0], s0);
-  BOOST_CHECK_EQUAL( analysis.sequences()[1], s1);
-  BOOST_CHECK_EQUAL( analysis.sequences()[2], s2);
+  BOOST_CHECK_EQUAL( *(analysis.sequences()[0]), s0);
+  BOOST_CHECK_EQUAL( *(analysis.sequences()[1]), s1);
+  BOOST_CHECK_EQUAL( *(analysis.sequences()[2]), s2);
 }
 
 // for some reason we can call nway once safely but it
@@ -147,11 +147,11 @@ BOOST_AUTO_TEST_CASE( mussa_load_motif )
   m1.append_sequence("GGGCCCCTTGGTT");
   m1.load_motifs(test_istream);
 
-  for (vector<Sequence>::const_iterator seq_i = m1.sequences().begin();
+  for (Mussa::vector_sequence_type::const_iterator seq_i = m1.sequences().begin();
        seq_i != m1.sequences().end();
        ++seq_i)
   {
-    BOOST_CHECK( seq_i->motifs().size() > 0 );
+    BOOST_CHECK( (*seq_i)->motifs().size() > 0 );
   }
 }
 
@@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE( mussa_add_motif )
 }
 
 static void 
-local_align_test(const vector<Sequence> &seqs, 
+local_align_test(const Mussa::vector_sequence_type &seqs, 
                  const list<ConservedPath::path_type>& result,
                  const list<vector<bool> >& reversed)
 {
@@ -193,8 +193,8 @@ local_align_test(const vector<Sequence> &seqs,
     BOOST_CHECK_EQUAL( (*rc_i)[0], false );
     const int first_path_basepair_index = (*base_i)[0];
     const int second_path_basepair_index = (*base_i)[1];
-    const char first_basepair = seqs[0][first_path_basepair_index];
-    const char second_basepair = seqs[1][second_path_basepair_index];
+    const char first_basepair = (*seqs[0])[first_path_basepair_index];
+    const char second_basepair = (*seqs[1])[second_path_basepair_index];
     // get our index into our reverse compliment map m
     const int second_compliment_index = (*rc_i)[1];
     // lookup the forward or reverse compliment depending on our rc flag
diff --git a/alg/test/test_sequence_location.cpp b/alg/test/test_sequence_location.cpp
new file mode 100644 (file)
index 0000000..7154652
--- /dev/null
@@ -0,0 +1,34 @@
+#include <boost/test/auto_unit_test.hpp>
+
+#include "alg/sequence_location.hpp"
+#include "alg/sequence.hpp"
+
+BOOST_AUTO_TEST_CASE( basic_sequence_location )
+{
+  Sequence s("AAGGCCTT");
+
+  SequenceLocation sl(s, 0, 2);
+
+  BOOST_CHECK_EQUAL( sl.getLeft(), 0 );
+  BOOST_CHECK_EQUAL( sl.getRight(), 2 );
+  BOOST_CHECK_EQUAL( sl.getCount(), 2 );
+
+  sl.setLeft(1);
+  sl.setRight(3);
+
+  BOOST_CHECK_EQUAL( sl.getLeft(), 1 );
+  BOOST_CHECK_EQUAL( sl.getRight(), 3 );
+  BOOST_CHECK_EQUAL( sl.getCount(), 2 );
+}
+
+BOOST_AUTO_TEST_CASE( memory_test )
+{
+  SequenceLocation *sl;
+  // storing references is a bad idea
+  {
+    Sequence s("AAGGCCTT");
+    sl = new SequenceLocation(s, 0, 2);
+  }
+
+  BOOST_CHECK_EQUAL(sl->getSequence(), "AAGGCCTT");
+}
index cd432443db3849cb52d33951ef8118d5b38798cb..811e0dce7245770ae57c2c1e495aab43f9e5056c 100644 (file)
@@ -7,6 +7,7 @@ using namespace boost::python;
 
 void export_glsequence()
 {
+  /*
   class_<GlSequence>("GlSequence", init<Sequence &, AnnotationColors &>())
     .def(init<GlSequence &>())
     .def("draw", &GlSequence::draw)
@@ -16,4 +17,5 @@ void export_glsequence()
     .add_property("y", &GlSequence::y, &GlSequence::setY)
     .add_property("length", &GlSequence::length)
   ;
+  */
 }
index e0efaaeb9dcd8151d6062310d8bb89d6cfa33491..f38063e2c3ed7a9f5e49f38e109b25ae60b19cb1 100644 (file)
@@ -26,7 +26,7 @@ void export_mussa()
     .def("analyze", &Mussa::analyze, "Run the analysis")
     .def("paths", &Mussa::paths, py::return_internal_reference<>())
     //.def("sequences", &Mussa::sequences)
-    .def("addSequence", &Mussa::append_sequence)  
+    //.def("addSequence", &Mussa::append_sequence)  
   ;
 
   py::enum_<Mussa::analysis_modes>("analysis_modes")
index 9a261781f6e64d6580dab42c3c6ad82ae155de8a..b48cb33894eff25a48d2823fdc74322e492a38be 100644 (file)
@@ -19,6 +19,7 @@ SET(MOC_HEADERS
       IntAction.hpp           
       MussaAlignedWindow.hpp  
       MussaWindow.hpp
+      SequenceLocationModel.hpp
       SubanalysisWindow.hpp
       ThresholdWidget.hpp
       ZoomWidget.hpp
@@ -42,6 +43,7 @@ SET(GUI_SOURCES
       IntAction.cpp            
       MussaAlignedWindow.cpp
       MussaWindow.cpp
+      SequenceLocationModel.cpp
       SubanalysisWindow.cpp
       ThresholdWidget.cpp
       ZoomWidget.cpp
index de33b9d5dc9660317979afcaf52d66b0536a92f8..0fac525df6cc35be357565c91bf19f382715cbd0 100644 (file)
@@ -510,7 +510,7 @@ void MussaWindow::updateAnalysis()
 {
   threshold.setRange(analysis->get_threshold(),analysis->get_window());
 
-  const vector<Sequence>& seqs = analysis->sequences();
+  const Mussa::vector_sequence_type& seqs = analysis->sequences();
   browser.setSequences(seqs, analysis->colorMapper());
   updateLinks();
   browser.zoomOut();
diff --git a/qui/SequenceLocationModel.cpp b/qui/SequenceLocationModel.cpp
new file mode 100644 (file)
index 0000000..ebf1185
--- /dev/null
@@ -0,0 +1,78 @@
+#include "qui/SequenceLocationModel.hpp"
+
+SequenceLocationModel::SequenceLocationModel(QObject *parent) 
+  : QAbstractTableModel(parent)
+{
+  Sequence s("AGCT");
+  sequence_locations.push_back(SequenceLocation(s, 0, 1));
+  sequence_locations.push_back(SequenceLocation(s, 2, 2));
+}
+
+int 
+SequenceLocationModel::rowCount( const QModelIndex& parent) const
+{
+  return sequence_locations.size();
+}
+
+int 
+SequenceLocationModel::columnCount(const QModelIndex& parent) const
+{
+  return 3;
+}
+
+QVariant 
+SequenceLocationModel::data(const QModelIndex &index, int role) const
+{
+  if (!index.isValid())
+    return QVariant();
+  
+  if (index.row() >= sequence_locations.size())
+    return QVariant();
+
+  if (index.column() >= 3)
+    return QVariant();
+
+  if (role == Qt::DisplayRole) {
+    if (index.column() == 0 ) {
+      const Sequence& seq = sequence_locations[index.row()].getSequence();
+      std::string header(seq.get_header());
+      if (header.size() == 0) {
+        return QVariant(QString(tr("Sequence ")) + 
+                        QString().setNum(index.row())
+            );
+      } else {
+        return QVariant(QString(header.c_str()));
+      }
+    } else if (index.column() == 1) {
+      return QVariant(sequence_locations[index.row()].getLeft());
+    } else if (index.column() == 2) {
+      return QVariant(sequence_locations[index.row()].getRight());
+    }
+  }
+  return QVariant();
+}
+
+QVariant 
+SequenceLocationModel::headerData(
+    int section, 
+    Qt::Orientation orentation, 
+    int role
+)
+{
+  switch(section) {
+    case 0:
+      return QString("Sequence");
+      break;
+    case 1:
+      return QString("Left");
+      break;
+    case 2:
+      return QString("Right");
+      break;
+    default:
+      return QVariant();
+      break;
+  }
+}
+
+
diff --git a/qui/SequenceLocationModel.hpp b/qui/SequenceLocationModel.hpp
new file mode 100644 (file)
index 0000000..f8f7293
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _SEQUENCE_LOCATION_MODEL_HPP_
+#define _SEQUENCE_LOCATION_MODEL_HPP_
+
+#include <QAbstractTableModel>
+#include "alg/sequence_location.hpp"
+#include <vector>
+
+class SequenceLocationModel : public QAbstractTableModel
+{
+  Q_OBJECT
+
+  public:
+    SequenceLocationModel(QObject *parent = 0);
+
+    
+    int rowCount(const QModelIndex& parent=QModelIndex()) const;
+    int columnCount(const QModelIndex& parent=QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
+
+    QVariant headerData(int section, Qt::Orientation orentation, int role=Qt::DisplayRole);
+
+    //bool setData(const QModelIndex& index, const QVariant &value, 
+    //             int role=Qt::EditRole);
+    //Qt::ItemFlags flags(const QModelIndex& index) const;
+
+    //bool insertRows(int row, int count, 
+    //                const QModelIndex& parent=QModelIndex());
+    //bool removeRows(int row, int count);
+    //                const QModelIndex& parent=QModelIndex());
+  private:
+    std::vector<SequenceLocation> sequence_locations;
+};
+
+#endif
index bf32cd6e80aceb1a4cabdc8be846337d5d877e30..c6d0d13b71033438d405c4d02898a8df5ea22644 100644 (file)
@@ -1,27 +1,27 @@
 #include "qui/SubanalysisWindow.hpp"
 
-#include <QTextEdit>
-#include <QPushButton>
-
 #include <QVBoxLayout>
 #include <QHBoxLayout>
 
 SubanalysisWindow::SubanalysisWindow(QWidget *parent)
   : QWidget(parent),
-    text(0),
+    table(0),
     ok(0),
     cancel(0)
 {
+  //model.setStringList(string_list);
+
   QHBoxLayout *buttonLayout = new QHBoxLayout();
   QVBoxLayout *verticalLayout = new QVBoxLayout();
 
   ok = new QPushButton(tr("&OK"), this);
   cancel = new QPushButton(tr("Cancel"), this);
-  text = new QTextEdit(this);
+  table = new QTableView(this);
+  table->setModel(&model);
 
   buttonLayout->addWidget(ok);
   buttonLayout->addWidget(cancel);
-  verticalLayout->addWidget(text);
+  verticalLayout->addWidget(table);
   verticalLayout->addLayout(buttonLayout);
   setLayout(verticalLayout);
 }
index 043c2dcb7b55f393da5a8e936704de508b007740..883dda800bb3163eeaad7fcd9991055d40808d22 100644 (file)
@@ -1,10 +1,12 @@
 #ifndef _SUBANALYSIS_H_
 #define _SUBANALYSIS_H_
 
+#include <QTableView>
+#include <QPushButton>
+#include <QStringList>
 #include <QWidget>
 
-class QTextEdit;
-class QPushButton;
+#include "qui/SequenceLocationModel.hpp"
 
 class SubanalysisWindow : public QWidget
 {
@@ -14,8 +16,10 @@ public:
   SubanalysisWindow(QWidget *parent = 0);
 
 private:  
-  QTextEdit *text;
+  QTableView *table;
   QPushButton *ok;
   QPushButton *cancel;
+
+  SequenceLocationModel model;
 };
 #endif
index c1df29e4232b0f381b7a1606711d6393c3cb7fc4..b74826e43017299b0858a30c1f2234b013a52fe3 100644 (file)
@@ -23,7 +23,7 @@ MotifEditor::MotifEditor(Mussa *m, QWidget *parent)
     MotifDetail *detail = new MotifDetail;
     if (i < motif_seq.size()) {
       detail->setMotif(motif_seq[i]);
-      detail->setColor(analysis->colorMapper().lookup("motif", motif_seq[i]));
+      detail->setColor(analysis->colorMapper()->lookup("motif", motif_seq[i]));
     }
     motif_details.push_back(detail);
     layout.addWidget(detail);
@@ -42,9 +42,9 @@ void MotifEditor::updateMotifs()
 {
   // This function is _sooo_ not thread safe
   // erase motifs
-  Color motif_default = analysis->colorMapper().typeColor("motif");
-  analysis->colorMapper().erase("motif");
-  analysis->colorMapper().appendTypeColor("motif", motif_default);
+  Color motif_default = analysis->colorMapper()->typeColor("motif");
+  analysis->colorMapper()->erase("motif");
+  analysis->colorMapper()->appendTypeColor("motif", motif_default);
 
   // add our motifs back
   vector<string> motifs;
index 64bf0515b580f54fdab3be6092f64b2e9bdea04b..7ed2b4de31d5c0cfc6447aa02312880d4521b9fb 100644 (file)
@@ -57,16 +57,17 @@ void SequenceBrowserWidget::copySelectedSequenceAsFasta()
   scrollable_browser.browser().copySelectedSequenceAsFasta();
 }
 
-void SequenceBrowserWidget::setSequences(const std::vector<Sequence>& sequences,
-                                            AnnotationColors& cm)
+void SequenceBrowserWidget::setSequences(
+    const std::vector< boost::shared_ptr<Sequence> >& sequences,
+    boost::shared_ptr<AnnotationColors> cm)
 {
   SequenceBrowser& browser = scrollable_browser.browser();
   clear();
-  for(vector<Sequence>::const_iterator seq_i = sequences.begin();
+  for(Mussa::vector_sequence_type::const_iterator seq_i = sequences.begin();
       seq_i != sequences.end();
       ++seq_i)
   {
-    GlSequence *gs= new GlSequence(*seq_i, cm);
+    boost::shared_ptr<GlSequence> gs(new GlSequence(*seq_i, cm));
     converted_sequences.push_back(*gs);
     browser.push_sequence(*gs);
   }
index cde9a3307f1c28e2e4c243b75e1bbf67dea3663b..0fa7bdac3a0e709ff3ee763d94ffdb7a004a0675 100644 (file)
@@ -1,8 +1,9 @@
 #ifndef _PATH_WIDGET_H_
 #define _PATH_WIDGET_H_
-
 #include <vector>
 
+#include <boost/shared_ptr.hpp>
+
 #include <QWidget>
 
 #include "alg/sequence.hpp"
@@ -35,7 +36,9 @@ public:
    * positions.
    */
   //void push_sequences(std::vector<Sequence>& sequences);
-  void setSequences(const std::vector<Sequence>& sequences, AnnotationColors& cm);
+  void setSequences(
+      const std::vector< boost::shared_ptr<Sequence> >& sequences, 
+      boost::shared_ptr<AnnotationColors> cm);
   void setSequences(std::vector<GlSequence>& sequences);
   const std::vector<GlSequence>& sequences() const;