1
2
3
4
5
6
7 package org.utgenome.gwt.utgb.server.app;
8
9 import java.awt.Font;
10 import java.awt.FontMetrics;
11 import java.awt.Graphics2D;
12 import java.awt.image.BufferedImage;
13 import java.io.BufferedReader;
14 import java.io.File;
15 import java.io.FileReader;
16 import java.io.IOException;
17 import java.sql.ResultSet;
18 import java.sql.SQLException;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.List;
24
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.utgenome.format.fasta.CompactFASTAIndex;
30 import org.utgenome.graphics.ChromosomeMapCanvas;
31 import org.utgenome.graphics.ChromosomeWindow;
32 import org.utgenome.gwt.utgb.client.bio.ChrLoc;
33 import org.utgenome.gwt.utgb.client.bio.ChrRange;
34 import org.utgenome.gwt.utgb.client.bio.CytoBand;
35 import org.utgenome.gwt.utgb.client.bio.Read;
36 import org.utgenome.gwt.utgb.server.WebTrackBase;
37 import org.xerial.db.sql.DatabaseAccess;
38 import org.xerial.db.sql.ResultSetHandler;
39 import org.xerial.db.sql.sqlite.SQLiteAccess;
40 import org.xerial.util.log.Logger;
41
42
43
44
45
46 public class ChromosomeMap extends WebTrackBase {
47 private static final long serialVersionUID = 1L;
48 private static Logger _logger = Logger.getLogger(ChromosomeMap.class);
49
50 public String species = "human";
51 public String revision = "hg19";
52 public String displayType = "normal";
53 public int width = 700;
54 public long start;
55 public long end;
56 public String dbGroup;
57 public String dbName;
58 public String bssQuery;
59 public String name;
60
61 private HashMap<String, ChromosomeWindow> chromWindows = new HashMap<String, ChromosomeWindow>();
62
63 public ChromosomeMap() {
64 }
65
66 private static File getCyteBandDB(String species, String revision) {
67 return new File(getProjectRootPath(), "db/" + species + "/" + revision + "/cytoBand/cytoBand.db");
68 }
69
70 private static File getPackIndexFile(String species, String revision) {
71 return new File(getProjectRootPath(), String.format("db/%s/%s.i.silk", species, revision));
72 }
73
74 private static List<CytoBand> getCytoBand(String species, String revision) throws Exception {
75 File cytoBandDb = getCyteBandDB(species, revision);
76 File packIndex = getPackIndexFile(species, revision);
77
78 final List<CytoBand> cytoBandList = new ArrayList<CytoBand>();
79
80 if (cytoBandDb.exists()) {
81 DatabaseAccess dbAccess = new SQLiteAccess(cytoBandDb.getAbsolutePath());
82 String sql = createSQLStatement("select * from entry");
83 if (_logger.isDebugEnabled())
84 _logger.debug(sql);
85
86 dbAccess.query(sql, new ResultSetHandler<Object>() {
87 @Override
88 public Object handle(ResultSet rs) throws SQLException {
89 CytoBand cytoBand = new CytoBand();
90 cytoBand.setChrom(rs.getString(1));
91 cytoBand.setStart(rs.getInt(2) + 1);
92 cytoBand.setEnd(rs.getInt(3));
93 cytoBand.setName(rs.getString(4));
94 cytoBand.setGieStain(rs.getString(5));
95 cytoBandList.add(cytoBand);
96 return null;
97 }
98 });
99
100 }
101 else if (packIndex.exists()) {
102
103 FileReader f = new FileReader(packIndex);
104 try {
105 List<CompactFASTAIndex> index = CompactFASTAIndex.load(new BufferedReader(f));
106 for (CompactFASTAIndex each : index) {
107 CytoBand cytoBand = each.toCytoBand();
108 cytoBandList.add(cytoBand);
109 }
110 }
111 finally {
112 f.close();
113 }
114 }
115
116 Collections.sort(cytoBandList, new CytoBandComprator());
117
118 return cytoBandList;
119
120 }
121
122 private static List<CytoBand> getCytoBandOfMaximumWidth(String species, String revision) throws Exception {
123
124 File cytoBandDb = getCyteBandDB(species, revision);
125 File packIndex = getPackIndexFile(species, revision);
126
127 final List<CytoBand> cytoBandList = new ArrayList<CytoBand>();
128
129 if (cytoBandDb.exists()) {
130 DatabaseAccess dbAccess = new SQLiteAccess(cytoBandDb.getAbsolutePath());
131 String sql = createSQLStatement("select chrom, min(chromStart), max(chromEnd) from entry group by chrom");
132 if (_logger.isDebugEnabled())
133 _logger.debug(sql);
134
135 dbAccess.query(sql, new ResultSetHandler<Object>() {
136 @Override
137 public Object handle(ResultSet rs) throws SQLException {
138 CytoBand cytoBand = new CytoBand();
139 cytoBand.setChrom(rs.getString(1));
140 cytoBand.setStart(rs.getInt(2) + 1);
141 cytoBand.setEnd(rs.getInt(3));
142 cytoBandList.add(cytoBand);
143 return null;
144 }
145 });
146
147 }
148 else if (packIndex.exists()) {
149 FileReader f = new FileReader(packIndex);
150 try {
151 List<CompactFASTAIndex> index = CompactFASTAIndex.load(new BufferedReader(new FileReader(packIndex)));
152 for (CompactFASTAIndex each : index) {
153 CytoBand cytoBand = each.toCytoBand();
154 cytoBandList.add(cytoBand);
155 }
156 }
157 finally {
158 f.close();
159 }
160 }
161
162 Collections.sort(cytoBandList, new CytoBandComprator());
163
164 return cytoBandList;
165 }
166
167 @Override
168 @SuppressWarnings("unchecked")
169 public void handle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
170 try {
171
172 List<CytoBand> cytoBandList = getCytoBand(species, revision);
173 List<String> chrNames = new ArrayList<String>();
174
175 for (CytoBand cytoBand : cytoBandList) {
176 if (chromWindows.containsKey(cytoBand.getChrom())) {
177
178 if (chromWindows.get(cytoBand.getChrom()).getChromosomeStart() > cytoBand.getStart()) {
179 chromWindows.get(cytoBand.getChrom()).setChromosomeStart(cytoBand.getStart());
180 }
181 if (chromWindows.get(cytoBand.getChrom()).getChromosomeEnd() < cytoBand.getEnd()) {
182 chromWindows.get(cytoBand.getChrom()).setChromosomeEnd(cytoBand.getEnd());
183 }
184 }
185 else {
186
187 ChromosomeWindow window = new ChromosomeWindow(cytoBand.getStart(), cytoBand.getEnd());
188 chromWindows.put(cytoBand.getChrom(), window);
189
190
191 chrNames.add(cytoBand.getChrom());
192 }
193 }
194
195 Comparator comparator = new Comparator4ChrName();
196 Collections.sort(chrNames, comparator);
197
198
199 int rank = 0;
200 for (String each : chrNames) {
201 if (_logger.isTraceEnabled())
202 _logger.trace(rank);
203 chromWindows.get(each).setRank(rank);
204 rank++;
205 }
206
207
208 ChromosomeMapCanvas canvas = new ChromosomeMapCanvas(width, 100, chromWindows);
209
210
211
212
213 if (displayType.equals("compact")) {
214 canvas.setChromHeight(7);
215 canvas.setChromMargin(3);
216 }
217 else if (displayType.equals("rotate")) {
218 canvas.setRotate();
219 canvas.setPixelHeight(300);
220 }
221 else {
222 canvas.setChromHeight(10);
223 canvas.setChromMargin(10);
224 }
225
226 canvas.setLighter(true);
227 canvas.draw(cytoBandList);
228
229 if (name != null)
230 canvas.drawGenomeWindow(name, start, end);
231
232
233 if (bssQuery != null) {
234 String dbFolder = getTrackConfigProperty("utgb.db.folder", getProjectRootPath() + "/db");
235 File dbFile = new File(dbFolder, dbGroup + "/" + dbName);
236
237 if (dbFile.exists()) {
238 SQLiteAccess dbAccess = new SQLiteAccess(dbFile.getAbsolutePath());
239 String sql = createSQLFromFile("bss_whole.sql", bssQuery);
240 List<ReadLocus> result = dbAccess.query(sql, ReadLocus.class);
241
242
243 for (ReadLocus each : result)
244 canvas.drawMapping(each.target, each.getStart(), each.getEnd(), each.getStrand());
245 }
246 }
247 response.setContentType("image/png");
248 canvas.toPNG(response.getOutputStream());
249 }
250 catch (Exception e) {
251 _logger.error(e);
252 e.printStackTrace();
253 }
254 }
255
256 public static ChrRange getChrRegion(String species, String revision) {
257 final ChrRange chrRanges = new ChrRange();
258 chrRanges.ranges = new ArrayList<ChrLoc>();
259 chrRanges.maxLength = -1;
260
261 if (_logger.isTraceEnabled())
262 _logger.trace(String.format("%s(%s)", species, revision));
263
264 try {
265
266 List<CytoBand> maxCytoBands = getCytoBandOfMaximumWidth(species, revision);
267
268 for (CytoBand each : maxCytoBands) {
269 ChrLoc chrLoc = new ChrLoc();
270 chrLoc.chr = each.getChrom();
271 chrLoc.start = each.getStart();
272 chrLoc.end = each.getEnd();
273 chrRanges.ranges.add(chrLoc);
274 if (_logger.isTraceEnabled())
275 _logger.trace(String.format("%s:%d-%d", chrLoc.chr, chrLoc.start, chrLoc.end));
276
277 chrRanges.maxLength = Math.max(chrRanges.maxLength, chrLoc.end - chrLoc.start);
278
279 BufferedImage image = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
280 Graphics2D g = image.createGraphics();
281 Font f = new Font("SansSerif", Font.PLAIN, 10);
282 g.setFont(f);
283 FontMetrics fontMetrics = g.getFontMetrics();
284
285 chrRanges.chrNameWidth = Math.max(chrRanges.chrNameWidth, fontMetrics.stringWidth(chrLoc.chr));
286
287 if (_logger.isTraceEnabled())
288 _logger.trace(String.format("max length : %d", chrRanges.maxLength));
289 }
290 }
291 catch (Exception e) {
292 _logger.error(e);
293 e.printStackTrace(System.err);
294 }
295
296 return chrRanges;
297
298 }
299
300 public static class ReadLocus extends Read {
301 private static final long serialVersionUID = 1L;
302 public String target;
303
304 public void setTarget(String target) {
305 this.target = target;
306 }
307 }
308
309 public static class CytoBandComprator implements Comparator<CytoBand> {
310
311 public int compare(CytoBand o1, CytoBand o2) {
312 return Comparator4ChrName.compareChrName(o1.getChrom(), o2.getChrom());
313 }
314
315 }
316
317 public static class Comparator4ChrName implements Comparator<String> {
318
319 public static int compareChrName(String p, String q) {
320 int x = p.length();
321 int y = q.length();
322 int n = Math.min(x, y);
323 for (int i = 0; i < n; i++) {
324 char c = p.charAt(i);
325 char d = q.charAt(i);
326 if (c != d) {
327 boolean f = (c >= '0' && c <= '9');
328 boolean g = (d >= '0' && d <= '9');
329 if (f && !g) {
330 return -1;
331 }
332 else if (!f && g) {
333 return 1;
334 }
335 else if (!f && !g) {
336 return c - d;
337 }
338 if (x != y) {
339 return x - y;
340 }
341 return c - d;
342 }
343 }
344 return x - y;
345 }
346
347 public int compare(String a, String b) {
348 return compareChrName(a, b);
349 }
350 }
351
352 }