1 |
/******************************************************************************** |
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 FXGView; |
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 |
FXGView* 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(FXGView* 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(FXGView* 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 FXGView : public FXScrollArea { |
264 |
FXDECLARE(FXGView) |
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 |
FXGView(); |
312 |
void calcLayout(); |
313 |
private: |
314 |
FXGView(const FXGView&); |
315 |
FXGView &operator=(const FXGView&); |
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 |
FXGView(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 ~FXGView(); |
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 |