1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.utgenome.gwt.utgb.client.canvas;
26
27 import java.util.List;
28
29 import org.utgenome.gwt.utgb.client.bio.SAMRead;
30 import org.utgenome.gwt.utgb.client.track.TrackWindow;
31 import org.utgenome.gwt.utgb.client.ui.FormLabel;
32
33 import com.google.gwt.core.client.GWT;
34 import com.google.gwt.dom.client.ImageElement;
35 import com.google.gwt.user.client.Event;
36 import com.google.gwt.user.client.ui.AbsolutePanel;
37 import com.google.gwt.user.client.ui.Composite;
38 import com.google.gwt.user.client.ui.FlexTable;
39 import com.google.gwt.widgetideas.graphics.client.Color;
40 import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
41 import com.google.gwt.widgetideas.graphics.client.ImageLoader;
42
43
44
45
46
47
48
49 public class SAMCanvas extends Composite {
50 private static final boolean isDebug = true;
51 private TrackWindow window;
52 private int windowWidth = 800;
53 private int windowHeight = 200;
54 private int labelWidth = 100;
55
56 private boolean isC2T = false;
57
58 public boolean isC2T() {
59 return isC2T;
60 }
61
62 public void setC2T(boolean isC2T) {
63 this.isC2T = isC2T;
64 }
65
66 private String colorMode = null;
67
68 public String getColorMode() {
69 return colorMode;
70 }
71
72 public void setColorMode(String colorMode) {
73 this.colorMode = colorMode;
74 }
75
76
77 private FlexTable layoutTable = new FlexTable();
78 private GWTCanvas canvas = new GWTCanvas();
79 private AbsolutePanel panel = new AbsolutePanel();
80
81
82 private ImageElement[] fontPanel = null;
83
84
85
86 private void initWidget() {
87 layoutTable.setBorderWidth(0);
88 layoutTable.setCellPadding(0);
89 layoutTable.setCellSpacing(0);
90
91 panel.add(canvas, 0, 0);
92 layoutTable.setWidget(0, 1, panel);
93 initWidget(layoutTable);
94
95 sinkEvents(Event.ONMOUSEMOVE | Event.ONMOUSEOVER | Event.ONMOUSEDOWN);
96 }
97
98 public SAMCanvas() {
99 initWidget();
100
101 }
102
103 private final int _OFFSET = 6;
104 private final int _HEIGHT = 17;
105 private int fontWidth = 7;
106 private int fontHeight = 13;
107
108 public void clear() {
109 canvas.clear();
110 }
111
112 void redraw() {
113 canvas.clear();
114 canvas.setCoordSize(window.getPixelWidth(), windowHeight);
115 canvas.setPixelSize(window.getPixelWidth(), windowHeight);
116 panel.setPixelSize(window.getPixelWidth(), windowHeight);
117 }
118
119 public void setWindow(TrackWindow w, int leftMargin) {
120 this.window = new TrackWindow(w.getPixelWidth(), w.getStartOnGenome(), w.getEndOnGenome());
121
122 redraw();
123 }
124
125 public void setPixelHeight(int height) {
126 canvas.setCoordHeight(height);
127 canvas.setPixelHeight(height);
128 panel.setHeight(height + "px");
129 }
130
131 public void setPixelWidth(int width) {
132 canvas.setCoordWidth(width);
133 canvas.setPixelWidth(width);
134
135 panel.setPixelSize(width, windowHeight);
136 }
137
138 public void drawSAMRead(final int count, final SAMRead read) {
139 windowHeight = (count + 1) * (_HEIGHT * _OFFSET);
140 setPixelHeight(windowHeight);
141
142 if (isDebug) {
143 GWT.log("draw read : " + read.qname, null);
144 GWT.log("read : " + read.seq, null);
145 GWT.log("ref : " + read.refSeq, null);
146 GWT.log("CIGAR : " + read.cigar, null);
147 }
148
149 if (fontPanel == null) {
150
151 if (isDebug)
152 GWT.log("get images:" + count, null);
153
154 ImageLoader.loadImages(new String[] { GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0x000000",
155 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0xe0a000",
156 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0x0000ff",
157 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0x00a000",
158 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0xff0000" },
159 new ImageLoader.CallBack() {
160 public void onImagesLoaded(ImageElement[] imageElements) {
161 fontPanel = imageElements;
162 if (isDebug)
163 GWT.log("draw images:" + count, null);
164
165 drawSAMCanvas(count, read);
166 }
167 });
168 }
169 else {
170 drawSAMCanvas(count, read);
171 }
172 }
173
174 public void drawSAMRead(final List<SAMRead> readList) {
175 windowHeight = readList.size() * (_HEIGHT * _OFFSET);
176 setPixelHeight(windowHeight);
177
178 if (fontPanel == null) {
179
180 if (isDebug)
181 GWT.log("get images", null);
182
183 ImageLoader.loadImages(new String[] { GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0x000000",
184 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0xe0a000",
185 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0x0000ff",
186 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0x00a000",
187 GWT.getModuleBaseURL() + "utgb-core/FontPanel?fontsize=9.5&color=0xff0000" },
188 new ImageLoader.CallBack() {
189 public void onImagesLoaded(ImageElement[] imageElements) {
190 fontPanel = imageElements;
191 draw(readList);
192 }
193 });
194 }
195 else {
196 draw(readList);
197 }
198 }
199
200 private void draw(List<SAMRead> readList) {
201 int count = 0;
202
203 for (SAMRead read : readList) {
204 if (isDebug) {
205 GWT.log("draw read : " + read.qname, null);
206 GWT.log("read : " + read.seq, null);
207 GWT.log("ref : " + read.refSeq, null);
208 GWT.log("CIGAR : " + read.cigar, null);
209 }
210
211 drawSAMCanvas(count, read);
212 count++;
213 }
214 }
215
216 public void drawSAMCanvas(int count, SAMRead read) {
217 StringBuilder num = new StringBuilder();
218 char readc, refc, diffc;
219 int readi = 0, refi = 0, position = 0;
220
221 for (int cursor = 0; cursor < read.cigar.length(); cursor++) {
222 char temp = read.cigar.charAt(cursor);
223 if ('0' <= temp && temp <= '9') {
224 num.append(temp);
225 }
226 else {
227 for (int i = 0; i < Integer.valueOf(num.toString()); i++, position++) {
228
229 if (temp == 'I') {
230 readc = read.seq.charAt(readi++);
231 refc = '*';
232 }
233 else if (temp == 'S') {
234 refc = ' ';
235 readc = read.seq.toLowerCase().charAt(readi++);
236 }
237 else if (temp == 'D') {
238 refc = read.refSeq.charAt(refi++);
239 readc = '*';
240 }
241 else if (temp == 'P') {
242 refc = '*';
243 readc = '*';
244 }
245 else if (temp == 'H') {
246 position--;
247 continue;
248 }
249 else {
250 refc = read.refSeq.charAt(refi++);
251 readc = read.seq.charAt(readi++);
252 }
253
254 if (temp == 'P' || temp == 'S')
255 diffc = ' ';
256 else if (refc != readc)
257 if (isC2T && readc == 'T' && refc == 'C')
258 diffc = 'T';
259 else
260 diffc = 'X';
261 else
262 diffc = '|';
263
264
265 canvas.setFillStyle(Color.BLACK);
266 if (refc != ' ' && refc != '*') {
267 canvas.fillRect(position * fontWidth + 3, _HEIGHT * (count * _OFFSET + 1), fontWidth, 1);
268 String indent = String.valueOf(read.getStart() + refi - 1);
269 if ((read.getStart() + refi - 1) % (int) (Math.ceil(indent.length() / 5.0) * 5) == 0) {
270 canvas.fillRect((position + 0.5) * fontWidth + 2, _HEIGHT * (count * _OFFSET + 1) - 3, 1, 5);
271 for (int j = 0; j < indent.length(); j++)
272 canvas.drawImage(fontPanel[0], (indent.charAt(j)) * fontWidth, 0, fontWidth, fontHeight, (position + j) * fontWidth + 2,
273 _HEIGHT * (count * _OFFSET), fontWidth, fontHeight);
274 }
275 }
276
277
278 canvas.drawImage(fontPanel[getColorInt(refc)], (refc) * fontWidth, 0, fontWidth, fontHeight, position * fontWidth + 3, _HEIGHT
279 * (count * _OFFSET + 1) + 3, fontWidth, fontHeight);
280
281 canvas.drawImage(fontPanel[0], (diffc) * fontWidth, 0, fontWidth, fontHeight, position * fontWidth + 3, _HEIGHT * (count * _OFFSET + 2),
282 fontWidth, fontHeight);
283
284 canvas.drawImage(fontPanel[getColorInt(readc)], (readc) * fontWidth, 0, fontWidth, fontHeight, position * fontWidth + 3, _HEIGHT
285 * (count * _OFFSET + 3) - 3, fontWidth, fontHeight);
286 }
287
288 num = new StringBuilder();
289 }
290 }
291
292
293 for (int cursor = 0; cursor < read.toString().length(); cursor++) {
294 canvas.drawImage(fontPanel[0], (read.toString().charAt(cursor)) * fontWidth, 0, fontWidth, fontHeight, cursor * fontWidth + 3, _HEIGHT
295 * (count * _OFFSET + 4) - 6, fontWidth, fontHeight);
296 }
297 }
298
299 public void drawLabelPanel(int count, SAMRead read, AbsolutePanel panel, int leftMargin) {
300 panel.setHeight(windowHeight + "px");
301
302
303
304 FormLabel refSeqLabel = new FormLabel(read.rname);
305 refSeqLabel.setStyleName("search-label");
306
307
308 FormLabel readLabel = new FormLabel(read.qname);
309 readLabel.setStyleName("search-label");
310
311 panel.add(refSeqLabel);
312 panel.setWidgetPosition(refSeqLabel, 0, _HEIGHT * (count * _OFFSET + 1) + 5);
313 panel.add(readLabel);
314 panel.setWidgetPosition(readLabel, 0, _HEIGHT * (count * _OFFSET + 3) - 1);
315 }
316
317 public void drawLabelPanel(List<SAMRead> readList, AbsolutePanel panel, int leftMargin) {
318 panel.setHeight(windowHeight + "px");
319
320
321
322
323 FormLabel[] refSeqLabel = new FormLabel[readList.size()];
324 FormLabel[] readLabel = new FormLabel[readList.size()];
325
326 int count = 0;
327 for (SAMRead read : readList) {
328
329 refSeqLabel[count] = new FormLabel(read.rname);
330 refSeqLabel[count].setStyleName("search-label");
331
332 readLabel[count] = new FormLabel(read.qname);
333 readLabel[count].setStyleName("search-label");
334
335 panel.add(refSeqLabel[count]);
336 panel.setWidgetPosition(refSeqLabel[count], 0, _HEIGHT * (count * _OFFSET + 1) + 5);
337 panel.add(readLabel[count]);
338 panel.setWidgetPosition(readLabel[count], 0, _HEIGHT * (count * _OFFSET + 3) - 1);
339
340 count++;
341 }
342 }
343
344 private int getColorInt(char nucleotide) {
345 int color = 0;
346 if (colorMode.equals("nucleotide")) {
347 if (nucleotide == 'G' || nucleotide == 'g')
348 color = 1;
349 else if (nucleotide == 'C' || nucleotide == 'c')
350 color = 2;
351 else if (nucleotide == 'A' || nucleotide == 'a')
352 color = 3;
353 else if (nucleotide == 'T' || nucleotide == 't')
354 color = 4;
355 }
356 return color;
357 }
358
359 public int countNucleotides(String cigar) {
360 int count = 0;
361 StringBuilder num = new StringBuilder();
362 for (int cursor = 0; cursor < cigar.length(); cursor++) {
363 char temp = cigar.charAt(cursor);
364 if ('0' <= temp && temp <= '9') {
365 num.append(temp);
366 }
367 else if (temp != 'H') {
368 count += Integer.valueOf(num.toString()).intValue();
369 num = new StringBuilder();
370 }
371 }
372 return count;
373 }
374
375 public int getReadWidth(String cigar) {
376 return (countNucleotides(cigar) + 1) * fontWidth + 3;
377 }
378 }