1 |
gpertea |
40 |
/******************************************************************************** |
2 |
|
|
* * |
3 |
|
|
* (light) Table W i d g e t * |
4 |
|
|
* * |
5 |
|
|
*********************************************************************************/ |
6 |
|
|
#ifndef FXCLVIEW_H |
7 |
|
|
#define FXCLVIEW_H |
8 |
|
|
#include "GList.hh" |
9 |
|
|
#include <ctype.h> |
10 |
|
|
#include "LayoutParser.h" |
11 |
|
|
#define MISMATCH_CLRIDX 16 |
12 |
|
|
#define NOCTG_CLRIDX 16 |
13 |
|
|
|
14 |
|
|
struct FXTimer; |
15 |
|
|
|
16 |
|
|
struct CScale { |
17 |
|
|
double sx; |
18 |
|
|
double sy; |
19 |
|
|
}; |
20 |
|
|
|
21 |
|
|
struct CRect { |
22 |
|
|
double x,y; |
23 |
|
|
double w,h; |
24 |
|
|
CRect() { |
25 |
|
|
x=0;y=0;w=0;h=0; |
26 |
|
|
} |
27 |
|
|
CRect(FXint ax,FXint ay,FXint aw,FXint ah) { |
28 |
|
|
x=ax;y=ay;w=aw;h=ah; |
29 |
|
|
} |
30 |
|
|
CRect(const FXRectangle& r) { |
31 |
|
|
x=r.x;y=r.y;w=r.w;h=r.h; |
32 |
|
|
} |
33 |
|
|
int ix() { return (int)x; }; |
34 |
|
|
int iy() { return (int)y; }; |
35 |
|
|
int iw() { return (int)w; }; |
36 |
|
|
int ih() { return (int)h; }; |
37 |
|
|
}; |
38 |
|
|
|
39 |
|
|
class FXClView; |
40 |
|
|
class ClSeq; |
41 |
|
|
/* |
42 |
|
|
class ClAlign { |
43 |
|
|
public: |
44 |
|
|
ClSeq* seq1; //pointers to ClSeq objects sharing this overlap |
45 |
|
|
ClSeq* seq2; |
46 |
|
|
FXint l1,r1; // left/right overlap coordinates on seq1 |
47 |
|
|
FXint l2,r2; // left/right overlap coordinates on seq2 |
48 |
|
|
FXdouble pid; |
49 |
|
|
FXint score; |
50 |
|
|
FXdouble pvalue; |
51 |
|
|
ClAlign(ClSeq* nseq1, ClSeq* nseq2, |
52 |
|
|
FXint nl1, FXint nr1, FXint nl2, FXint nr2, |
53 |
|
|
FXdouble npid,FXint nscore,FXdouble npvalue) { |
54 |
|
|
seq1=nseq1;seq2=nseq2; l1=nl1; r1=nr1; |
55 |
|
|
l2=nl2; r2=nr2; pid=npid; score=nscore; pvalue=npvalue; |
56 |
|
|
} |
57 |
|
|
bool operator==(const ClAlign& s) const { |
58 |
|
|
return pvalue==s.pvalue; |
59 |
|
|
} |
60 |
|
|
bool operator<(const ClAlign& s) const { |
61 |
|
|
return pvalue<s.pvalue; |
62 |
|
|
} |
63 |
|
|
bool operator>(const ClAlign& s) const { |
64 |
|
|
return pvalue>s.pvalue; |
65 |
|
|
} |
66 |
|
|
};*/ |
67 |
|
|
|
68 |
|
|
|
69 |
|
|
class ClSeqSegment { |
70 |
|
|
public: |
71 |
|
|
char splL, splR; |
72 |
|
|
FXint xL,xR; // left/right column coordinates in the layout |
73 |
|
|
FXint clipL,clipR; // left/right end clipping length |
74 |
|
|
FXint len() { return xR-xL+1; } |
75 |
|
|
int seqofs; //offset to the first nucleotide of this segment in the sequence string |
76 |
|
|
ClSeqSegment(FXint xl, FXint xr, FXint cl=0, FXint cr=0, |
77 |
|
|
char sl=0, char sr=0, int segpos=0) { |
78 |
|
|
xL=xl;xR=xr; |
79 |
|
|
clipL=cl;clipR=cr; |
80 |
|
|
splL=sl;splR=sr; |
81 |
|
|
seqofs=segpos; |
82 |
|
|
} |
83 |
|
|
/* |
84 |
|
|
bool operator==(const ClSeqSegment& s) const { |
85 |
|
|
return xL==s.xL; |
86 |
|
|
} |
87 |
|
|
bool operator<(const ClSeqSegment& s) const { |
88 |
|
|
return xL<s.xL; |
89 |
|
|
} |
90 |
|
|
bool operator>(const ClSeqSegment& s) const { |
91 |
|
|
return xL>s.xL; |
92 |
|
|
}*/ |
93 |
|
|
}; |
94 |
|
|
|
95 |
|
|
|
96 |
|
|
|
97 |
|
|
class ClSeq { |
98 |
|
|
public: |
99 |
|
|
FXClView* view; |
100 |
|
|
//GList<ClAlign> aligns; //list of pointers to ClAlign objects |
101 |
|
|
FXString name; |
102 |
|
|
//FXString sequence; //nt sequence itself! |
103 |
|
|
char* sequence; //nt sequence could be in fact pulled from the contig sequence |
104 |
|
|
// e.g. in the case of GFF files |
105 |
|
|
FXString comment; //any annotation given |
106 |
|
|
FXint len; //total length of sequence [in chars = column span], |
107 |
|
|
//includes clipping |
108 |
|
|
//if segmented: total span of all segments+inter-segment gaps |
109 |
|
|
FXint slen; //like len, but without intron (sum of segment lengths) |
110 |
|
|
int numsegs; //numsegs MUST be at least 1 |
111 |
|
|
// >1 means segmented! |
112 |
|
|
ClSeqSegment* segs; //array of seq segments -- with at least one element! |
113 |
|
|
FXint cl_xpos; //left position in cluster [in chars] (to be determined) |
114 |
|
|
FXint cl_ypos; //line order number in cluster (to be determined) |
115 |
|
|
unsigned int ins, dels; //gaps and deletions for this within the assembly |
116 |
|
|
FXint clipL; |
117 |
|
|
FXint clipR; |
118 |
|
|
short group; //or track_id for GFF files |
119 |
|
|
int cdsofs; //offset of cds start, relative to the beginning of this ClSeq |
120 |
|
|
unsigned char reversed; |
121 |
|
|
unsigned char isET; |
122 |
|
|
FXint flag; |
123 |
|
|
ClSeq(FXClView* v, const char* vname, FXint vlen, FXint offs=0, |
124 |
|
|
bool minus=false, int l_clip=0, int r_clip=0, const char* seq=NULL, |
125 |
|
|
unsigned int ains=0, unsigned int adels=0) { |
126 |
|
|
name=vname; |
127 |
|
|
len=vlen; |
128 |
|
|
//sequence=seq; |
129 |
|
|
sequence=Gstrdup(seq); //no need to make a copy? |
130 |
|
|
view=v; |
131 |
|
|
flag=0; |
132 |
|
|
group = -1; |
133 |
|
|
cdsofs=0; |
134 |
|
|
clipL=l_clip; |
135 |
|
|
clipR=r_clip; |
136 |
|
|
cl_xpos=offs; |
137 |
|
|
cl_ypos=-1; |
138 |
|
|
ins=ains; |
139 |
|
|
numsegs=0; |
140 |
|
|
segs=NULL; |
141 |
|
|
addSegment(offs,offs+len-1,clipL, clipR); |
142 |
|
|
reversed=minus?1:0; |
143 |
|
|
|
144 |
|
|
isET= (name.find("np|")>=0 || name.find("et|")>=0 || |
145 |
|
|
name.find("egad|")>=0)?1:0; |
146 |
|
|
dels=adels; |
147 |
|
|
} |
148 |
|
|
void addSegment(int xl, int xr, int clipl=0, int clipr=0, |
149 |
|
|
char lspl=0, char rspl=0, int seqp=0) { |
150 |
|
|
GREALLOC(segs,(numsegs+1)*sizeof(ClSeqSegment)); |
151 |
|
|
segs[numsegs].xL=xl; segs[numsegs].xR=xr; |
152 |
|
|
segs[numsegs].clipL=clipl; |
153 |
|
|
segs[numsegs].clipR=clipr; |
154 |
|
|
segs[numsegs].splL=lspl; |
155 |
|
|
segs[numsegs].splR=rspl; |
156 |
|
|
segs[numsegs].seqofs=seqp; |
157 |
|
|
slen+=xr-xl+1; |
158 |
|
|
numsegs++; |
159 |
|
|
} |
160 |
|
|
~ClSeq() { |
161 |
|
|
GFREE(segs); |
162 |
|
|
GFREE(sequence); |
163 |
|
|
} |
164 |
|
|
ClSeq(FXClView* v, LytSeqInfo* seqinfo, const char* seq=NULL); |
165 |
|
|
//FXbool InRect(const CRect& rect, CRect& seqrect); |
166 |
|
|
//for testing if repainting is needed for this object |
167 |
|
|
//rect is in pixels, but already offset to the whole cluster area |
168 |
|
|
|
169 |
|
|
//sort by y coordinate |
170 |
|
|
void calcViewRect(CRect& seqrect); //compute the sequence position |
171 |
|
|
//within the view |
172 |
|
|
void calcSegView(int segidx, CRect& segrect);//compute a seq segment's position |
173 |
|
|
//within the view |
174 |
|
|
bool operator==(const ClSeq& s) const { |
175 |
|
|
return (name==s.name); |
176 |
|
|
} |
177 |
|
|
bool operator>(const ClSeq& s) const { |
178 |
|
|
return name>s.name; |
179 |
|
|
} |
180 |
|
|
bool operator<(const ClSeq& s) const { |
181 |
|
|
return name<s.name; |
182 |
|
|
} |
183 |
|
|
}; |
184 |
|
|
|
185 |
|
|
// utility class for layout compaction: |
186 |
|
|
// a collection of these must always be stored and kept in cl_ypos order |
187 |
|
|
class CLayoutRow { |
188 |
|
|
public: |
189 |
|
|
GList<ClSeq> seqs; //sequences shown on this row |
190 |
|
|
int rpos; //coordinate for the righmost end for any of seqs |
191 |
|
|
//(where the room starts) |
192 |
|
|
CLayoutRow(ClSeq* s, int idx): seqs(false,false,false) { |
193 |
|
|
s->cl_ypos=idx; |
194 |
|
|
seqs.Add(s); |
195 |
|
|
rpos=s->cl_xpos + s->len; |
196 |
|
|
} |
197 |
|
|
|
198 |
|
|
void addSeq(ClSeq* s, int idx) { |
199 |
|
|
s->cl_ypos=idx; |
200 |
|
|
seqs.Add(s); |
201 |
|
|
rpos=s->cl_xpos + s->len; |
202 |
|
|
} |
203 |
|
|
|
204 |
|
|
char getNuc(int c) { |
205 |
|
|
for (int i=0;i<seqs.Count(); i++) { |
206 |
|
|
ClSeq* s=seqs[i]; |
207 |
|
|
if (c<s->cl_xpos) return 0; |
208 |
|
|
if (c>=s->cl_xpos+s->clipL && c<s->cl_xpos+s->len-s->clipR) |
209 |
|
|
//return s->sequence.empty() ? ' ' : |
210 |
|
|
return s->sequence==NULL ? ' ' : |
211 |
|
|
toupper(s->sequence[c-s->cl_xpos]); |
212 |
|
|
// toupper(s->getNuc(c-s->cl_xpos)); |
213 |
|
|
} |
214 |
|
|
return 0; |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
bool operator==(const CLayoutRow& s) const { |
218 |
|
|
return this==&s; |
219 |
|
|
} |
220 |
|
|
bool operator<(const CLayoutRow& s) const { |
221 |
|
|
return this<&s; |
222 |
|
|
} |
223 |
|
|
bool operator>(const CLayoutRow& s) const { |
224 |
|
|
return this>&s; |
225 |
|
|
} |
226 |
|
|
}; |
227 |
|
|
|
228 |
|
|
//layout column info: |
229 |
|
|
//this is extended to include SNP candidate detection |
230 |
|
|
|
231 |
|
|
struct NTColumn { |
232 |
|
|
char letter; |
233 |
|
|
int count; |
234 |
|
|
}; |
235 |
|
|
|
236 |
|
|
class ColumnData { |
237 |
|
|
public: |
238 |
|
|
char letter; //the consensus letter |
239 |
|
|
int thickness; //how many active layers in this column |
240 |
|
|
int mismatches; //how many mismatches among these |
241 |
|
|
NTColumn ntdata[5]; //sorted - largest counts first! |
242 |
|
|
int nN; |
243 |
|
|
int gap; |
244 |
|
|
ColumnData() { |
245 |
|
|
letter=0; |
246 |
|
|
thickness=0; |
247 |
|
|
mismatches=0; |
248 |
|
|
memset(&ntdata,0,5*sizeof(NTColumn)); |
249 |
|
|
nN=0; |
250 |
|
|
gap=0; |
251 |
|
|
} |
252 |
|
|
bool operator==(const ColumnData& s) const { |
253 |
|
|
return this==&s; |
254 |
|
|
} |
255 |
|
|
bool operator<(const ColumnData& s) const { |
256 |
|
|
return this<&s; |
257 |
|
|
} |
258 |
|
|
bool operator>(const ColumnData& s) const { |
259 |
|
|
return this>&s; |
260 |
|
|
} |
261 |
|
|
}; |
262 |
|
|
|
263 |
|
|
class FXAPI FXClView : public FXScrollArea { |
264 |
|
|
FXDECLARE(FXClView) |
265 |
|
|
friend class ClSeq; |
266 |
|
|
protected: |
267 |
|
|
FXFont *font; // Font |
268 |
|
|
FXFont *seqfont; // Font |
269 |
|
|
FXColor textColor; // Text color |
270 |
|
|
FXImage *backbuf; |
271 |
|
|
CScale scale; |
272 |
|
|
FXColor* grpColors[2]; |
273 |
|
|
bool hasSeqs; |
274 |
|
|
bool canShowSeq; |
275 |
|
|
int maxThickness; |
276 |
|
|
// non-scrollable grid area at the top |
277 |
|
|
FXColor gridColor; |
278 |
|
|
FXColor gridColorSh; //shadow |
279 |
|
|
FXColor gridColorH; //highlight |
280 |
|
|
int content_w; |
281 |
|
|
int content_h; |
282 |
|
|
int gridStep; |
283 |
|
|
int gridH; |
284 |
|
|
/* -- this section was moved to mainwin.h : |
285 |
|
|
FXColor baseColors[6]; //base colors |
286 |
|
|
FXColor seqColors[12]; |
287 |
|
|
buffer for color array to pass to |
288 |
|
|
the Seq Paint method |
289 |
|
|
0 = seq color |
290 |
|
|
1 = seq highlight |
291 |
|
|
2 = seq shadow |
292 |
|
|
3 = seqtext color |
293 |
|
|
4 = seqtrim color |
294 |
|
|
5 = seq range color |
295 |
|
|
6 = seq select color |
296 |
|
|
7 = alternate seq color (ET) |
297 |
|
|
8 = inter-segment connector color |
298 |
|
|
9 = internal trim color |
299 |
|
|
10 = major consensus splice site |
300 |
|
|
11 = minor consensus splice site |
301 |
|
|
|
302 |
|
|
|
303 |
|
|
FXColor matchColors[MISMATCH_CLRIDX+1]; //luminance ramp |
304 |
|
|
FXColor ctgQuals[NOCTG_CLRIDX+1]; //also a ramp, for contig |
305 |
|
|
*/ |
306 |
|
|
FXColor* baseColors; |
307 |
|
|
FXColor* seqColors; |
308 |
|
|
FXColor* matchColors; //luminance ramp for coverage |
309 |
|
|
FXColor* ctgQuals; //luminance ramp for contig colors |
310 |
|
|
protected: |
311 |
|
|
FXClView(); |
312 |
|
|
void calcLayout(); |
313 |
|
|
private: |
314 |
|
|
FXClView(const FXClView&); |
315 |
|
|
FXClView &operator=(const FXClView&); |
316 |
|
|
FXPoint lastMousePos; |
317 |
|
|
public: |
318 |
|
|
enum { |
319 |
|
|
ID_TIPTIMER=FXScrollArea::ID_LAST, |
320 |
|
|
ID_LOOKUPTIMER, |
321 |
|
|
ID_TREELIST, |
322 |
|
|
ID_LAST |
323 |
|
|
}; |
324 |
|
|
enum ColorStyle { |
325 |
|
|
csDefault, |
326 |
|
|
csBaseColor, |
327 |
|
|
csDensity, |
328 |
|
|
csMismatch //only if contig is available |
329 |
|
|
}; |
330 |
|
|
protected: |
331 |
|
|
ColorStyle colorStyle; |
332 |
|
|
public: |
333 |
|
|
void initColors(FXColor* seqcolors, FXColor* basecolors, |
334 |
|
|
FXColor* matchcolors, FXColor* ctgquals, FXColor* grpcolors, FXColor* grpgapcolors); |
335 |
|
|
void scrollBy(int x,int y); |
336 |
|
|
//void initGrpColors(int num); |
337 |
|
|
bool setSeqGrp(FXString& seq, int grp); |
338 |
|
|
void paintGrid(FXDCWindow* dc, FXRectangle& gridR); |
339 |
|
|
void paintGap(FXDCWindow* dc, FXColor gapcolor, FXRectangle& ClpRct, int y, int x1, int x2, |
340 |
|
|
int gapl, int gapr, char splL, char splR); |
341 |
|
|
void paintSeq(FXDCWindow* dc, FXRectangle& clipR, ClSeq* seq, |
342 |
|
|
ColorStyle colorstyle); |
343 |
|
|
void paintSeqBorder(FXDCWindow* dc, FXRectangle& clipR, ClSeq* seq, |
344 |
|
|
ColorStyle colorstyle); |
345 |
|
|
long onPaint(FXObject*,FXSelector,void*); |
346 |
|
|
long onLeftBtnPress(FXObject*,FXSelector,void*); |
347 |
|
|
long onLeftBtnRelease(FXObject*,FXSelector,void*); |
348 |
|
|
long onClicked(FXObject*,FXSelector,void*); |
349 |
|
|
long onCommand(FXObject*,FXSelector,void*); |
350 |
|
|
long onMotion(FXObject*,FXSelector,void*); |
351 |
|
|
long onEnter(FXObject*,FXSelector,void*); |
352 |
|
|
long onLeave(FXObject*,FXSelector,void*); |
353 |
|
|
long onQueryTip(FXObject*,FXSelector,void*); |
354 |
|
|
long onQueryHelp(FXObject*,FXSelector,void*); |
355 |
|
|
long onTipTimer(FXObject*,FXSelector,void*); |
356 |
|
|
virtual bool canFocus() const {return true;} |
357 |
|
|
|
358 |
|
|
ClSeq* getSeqAt(int x, int y, int& colno); |
359 |
|
|
void drawColumn(int colno); |
360 |
|
|
void drawSeq(ClSeq* seq); |
361 |
|
|
void makeVisible(ClSeq* seq); |
362 |
|
|
void selectSeq(ClSeq* seq, bool showIt=false); |
363 |
|
|
void drawTriangle(FXDCWindow& dc, FXColor color, FXint l,FXint t,FXint r,FXint b); |
364 |
|
|
public: |
365 |
|
|
/// Constructor |
366 |
|
|
GList<ClSeq>* seqlist; |
367 |
|
|
GList<CLayoutRow> rows; |
368 |
|
|
GList<ColumnData> columns; |
369 |
|
|
char filetype; //type of the file loaded in the view ('L'=*.lyt, 'A'=*.ace) |
370 |
|
|
bool showContig; //if true, only shown within the grid, if canShowSeq |
371 |
|
|
ClSeq* contig; // this will point to the sequence which is actually |
372 |
|
|
// the contig (if loaded) |
373 |
|
|
ClSeq* selSeq; //selected sequence |
374 |
|
|
ClSeq* btnSeq; //seq which was pressed left btn on |
375 |
|
|
int selCol; |
376 |
|
|
int btnCol; |
377 |
|
|
//default values |
378 |
|
|
int seqfntW; //seqfont char width |
379 |
|
|
int seqfntH; //seqfont char height |
380 |
|
|
|
381 |
|
|
int seqH; //sequence bar height (pixels) |
382 |
|
|
double seqW; //sequence char width (pixels) |
383 |
|
|
int vSpace; |
384 |
|
|
FXint XRight; //maximum right margin (in chars) |
385 |
|
|
//given by max(cl_xpos+len) |
386 |
|
|
FXint XLeft; //maximum left column (in chars) |
387 |
|
|
//minimum offset |
388 |
|
|
ClSeq* addSeq(const char* name, FXint len, FXint offs, bool reversed=false, |
389 |
|
|
int trim_l=0, int trim_r=0, const char* sequence=NULL, |
390 |
|
|
unsigned int ains=0, unsigned int adels=0); |
391 |
|
|
//supporting segmented sequence addition: |
392 |
|
|
ClSeq* addSeq(LytSeqInfo* seqinfo, const char* sequence=NULL); |
393 |
|
|
void addContig(const char* name, FXint len, const char* sequence=NULL, FXint offs=0); |
394 |
|
|
void buildLayout(); |
395 |
|
|
FXClView(FXComposite *p,FXObject* tgt=NULL,FXSelector sel=0,FXuint opts=0,FXint x=0,FXint y=0,FXint w=0,FXint h=0); |
396 |
|
|
/// Destructor |
397 |
|
|
virtual ~FXClView(); |
398 |
|
|
/// Save list to a stream |
399 |
|
|
virtual void save(FXStream& store) const; |
400 |
|
|
/// Load list from a stream |
401 |
|
|
virtual void load(FXStream& store); |
402 |
|
|
virtual void create(); |
403 |
|
|
virtual void detach(); |
404 |
|
|
virtual void resize(FXint w,FXint h); |
405 |
|
|
virtual void position(FXint x, FXint y, FXint w,FXint h); |
406 |
|
|
virtual void moveContents(FXint x,FXint y); |
407 |
|
|
//--------------- |
408 |
|
|
/// Change text font |
409 |
|
|
void setFont(FXFont* fnt); |
410 |
|
|
/// Return text font |
411 |
|
|
FXFont* getFont() const { return font; } |
412 |
|
|
/// Return normal text color |
413 |
|
|
FXColor getTextColor() const { return textColor; } |
414 |
|
|
/// Change normal text color |
415 |
|
|
void setTextColor(FXColor clr); |
416 |
|
|
//determine when to show scroll bars |
417 |
|
|
|
418 |
|
|
virtual FXint getContentWidth(); |
419 |
|
|
virtual FXint getContentHeight(); |
420 |
|
|
|
421 |
|
|
void RecalcContent(bool repaint=true); |
422 |
|
|
FXdouble getZoomX() { return scale.sx; } |
423 |
|
|
FXdouble getZoomY() { return scale.sy; } |
424 |
|
|
void ZoomX(FXdouble zx, int fromX=-1); |
425 |
|
|
void ZoomY(FXdouble zy, int fromY=-1); |
426 |
|
|
void Zoom(FXdouble zx, FXdouble zy, int fromX=-1, int fromY=-1); |
427 |
|
|
void setColorStyle(ColorStyle cs) { colorStyle=cs; update(); } |
428 |
|
|
void Clear() { |
429 |
|
|
rows.Clear(); |
430 |
|
|
seqlist->Clear(); |
431 |
|
|
//seqaligns->Clear(); |
432 |
|
|
XRight=XLeft=0; |
433 |
|
|
columns.Clear(); |
434 |
|
|
hasSeqs=false; |
435 |
|
|
selSeq=NULL; |
436 |
|
|
selCol=-1; |
437 |
|
|
RecalcContent(); |
438 |
|
|
} |
439 |
|
|
int getXLeft() { return XLeft; } |
440 |
|
|
bool HasSeqs() { return hasSeqs; } |
441 |
|
|
int getSelCol() { return selCol; } |
442 |
|
|
void set1pxZoom(int fromX=-1, int fromY=-1) { |
443 |
|
|
if (rows.Count()==0 || XRight-XLeft==0) return; |
444 |
|
|
Zoom(1.00/(double)seqfntW, 1.00/(double)seqfntH, |
445 |
|
|
fromX, fromY); |
446 |
|
|
} |
447 |
|
|
ColumnData* getColumnData(int cidx) { return columns[cidx]; } |
448 |
|
|
}; |
449 |
|
|
|
450 |
|
|
#endif |