Getting closer to a subanalysis mode
[mussa.git] / alg / glseqbrowser.hpp
1 #ifndef _GLTRACKS_H_
2 #define _GLTRACKS_H_
3 #include <boost/shared_ptr.hpp>
4
5 #include <map>
6 #include <set>
7 #include <vector>
8
9 #include "alg/annotation_colors.hpp"
10 #include "alg/sequence.hpp"
11 #include "alg/glsequence.hpp"
12 #include "alg/sequence_location.hpp"
13
14 //! Manage rendering a collection of glSequences
15 class GlSeqBrowser
16 {
17 public:
18   GlSeqBrowser();
19   GlSeqBrowser(const GlSeqBrowser&);
20
21   //! setup the opengl canvas
22   void initializeGL();
23   //! called when our screen canvas is resized
24   void resizeGL(int width, int height);
25   //! render our scene
26   void paintGL() const;
27
28   //! select a region (using canvas coordinates)
29   void selectRegion(int top, int left, int bottom, int right);
30
31   //! border size
32   float border() const;
33
34   //! max world left coordinate
35   float left() const;
36   //! max world right coordinate
37   float right() const;
38
39   void setViewportCenter(float x);
40   //! return world coordinate of the left side of the viewport
41   float viewportLeft() const;
42   //! return world coordinate of the center of the viewport
43   float viewportCenter() const;
44   //! return world coordinate of the right side of the viewport
45   float viewportRight() const;
46   //! return height of the viewport in world coordinates
47   float viewportHeight() const;
48   //! return width of the viewport in world coordinates
49   float viewportWidth() const;
50
51   //! zoom out far enough to show the full size of the sequence
52   double zoomOut();
53   //! zoom in to a reasonable sequence view
54   double zoomToSequence();
55   //! set the current zoom level in (base pairs / pix )
56   //! its a double as zoom levels of [0.01, 1.0] make nice sequence views
57   void setZoom(double zoom_level);
58   //! returns the current zoom level as basepairs per pixel
59   double zoom() const;
60   //! center the provided path in the current viewport
61   void centerOnPath(const std::vector<int>&);
62
63   void setColorMapper(boost::shared_ptr<AnnotationColors> cm);
64   const AnnotationColors& colorMapper();
65
66   //! clear our tracks and connections
67   void clear();
68   //! clear everything related to a selection
69   void clear_selection();
70
71   //! add a sequence to the back of our track container (makes copy of s)
72   void push_sequence(const Sequence& s);
73   //! add a sequence to the back of our track container
74   void push_sequence(boost::shared_ptr<Sequence> s);
75   //! add a glsequence to the back of our track container
76   void push_sequence(GlSequence s);
77   //! return our track container
78   const std::vector<GlSequence>& sequences() const;
79
80   //! clear all the line segments between all the sequences
81   void clear_links();
82   //! define a path
83   void link(const std::vector<int>& path, const std::vector<bool>& isRC, int length);
84   //! returns the index of pathids based on order added by link
85   const std::set<int>& selectedPaths() const;
86   //! copy sequence from selected track using formating function
87   template<class Item>
88   void copySelectedTracks(std::list<Item>& result, 
89              Item (*format_track)(const Sequence& s, int left, int right));
90   //! copy sequence from selected tracks as FASTA sequences
91   void copySelectedTracksAsFasta(std::string& copy_buffer);
92   //! copy sequence from selected tracks as a list of sequences
93   void copySelectedTracksAsSequences(std::list<Sequence>& result);
94   //! copy sequence from selected tracks as plain sequences
95   void copySelectedTracksAsString(std::string& copy_buffer);
96
97   //! copy tracks as a sequence and its coordinates
98   void copySelectedTracksAsSeqLocation(std::list<SequenceLocation>& result);
99   
100   
101   //! Provide a logical name for a type discriminator for our glName stack
102   enum FeatureType { MussaTrack, MussaSegment };
103
104   //! a useful point class
105   template<class T> struct point {
106     T x;
107     T y;
108
109     point(T x_, T y_):x(x_), y(y_) {}
110   };
111
112   //! a useful rectangle, where 0,0 is in the lower left
113   template<class T> struct rect {
114     T top;
115     T left;
116     T bottom;
117     T right;
118
119     rect() {}
120     rect(T t, T l, T b, T r) : top(t), left(l), bottom(b), right(r) {}
121     T width() { return right - left; }
122     T height() { return top - bottom; }
123     void clear() { top=0; left=0; bottom=0; right=0; }
124   };
125
126   struct Segment
127   {
128     point<float> start;
129     point<float> end;
130     bool reversed;
131     std::set<int> path_ids;
132
133     Segment() : start(0.0, 0.0), end(0.0, 0.0) {}
134     Segment(float x1, float y1, float x2, float y2, bool isRC) 
135       : start(x1, y1), end(x2, y2), reversed(isRC) {}
136   };
137
138   //! data structure holding our line segments
139   /*! the vector is of size track_container.size()-1
140    *  it's indexed by the pair x1, x2 (the two x coordinates between
141    *  the two tracks
142    */
143   typedef std::pair<int, int> segment_key;
144   typedef std::map<segment_key, Segment> pair_segment_map;
145   typedef std::vector<pair_segment_map> path_segment_map_vector;
146   path_segment_map_vector path_segments;
147
148   struct TrackRegion
149   {
150     GLuint track_id;
151     int left;
152     int right;
153
154     TrackRegion():track_id(0), left(0), right(0) {};
155     TrackRegion(const TrackRegion& o)
156       : track_id(o.track_id), left(o.left), right(o.right) {}
157     TrackRegion(GLuint id, int l, int r)
158       : track_id(id), left(l), right(r) {}
159     void set(GLuint id, int l, int r) { track_id = id; left=l; right=r; };
160   };
161
162 private:
163   //! recalculate the viewable world
164   /*! depending on the size of our canvas, our zoom level and
165    *  how far we've been offset
166    */
167   void update_viewport(float center, double new_zoom);
168
169   //! determine where all the tracks should be placed
170   void update_layout();
171
172   //! convert opengl selections into the list of paths we should highlight
173   void processSelection(GLuint hits, 
174                         GLuint buffer[], 
175                         GLuint bufsize, 
176                         const rect<float>& r);
177
178   //! master scene drawing function
179   /*! draw is broken out for the opengl selection code
180    */
181   void draw() const;
182   //! draw glsequence tracks
183   void draw_tracks() const;
184   //! draw line segments between tracks
185   void draw_segments() const;
186   //! draw selection box
187   void draw_selection() const;
188
189   //! number of pixels to reserve around the edges of our canvas
190   const int border_width;
191   //! the current viewable region (world coord)
192   rect<float> cur_ortho;
193   //! how many pixels our viewport is (screen coord)
194   point<int> viewport_size;
195   //! the center of our current viewport (world coord) (used for scrollbar)
196   float viewport_center;
197   double zoom_level;
198   boost::shared_ptr<AnnotationColors> color_mapper;
199   //! container of all the GlSequences loaded into our scene
200   std::vector<GlSequence> track_container;
201   //! counter for each path added to us via connect
202   int pathid;
203
204 protected:
205   //! where to draw our box (world coordinates)
206   rect<float> selectedRegion;
207   //! true if we have a selection
208   bool selectedMode;
209   //! indicate which paths are selected
210   std::set<int> selected_paths;
211   //! which track is selected (it only makes sense to have one track selected).
212   std::list<TrackRegion> selected_tracks;
213   typedef std::list<TrackRegion>::iterator selected_track_iterator;
214 };
215 #endif