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