View Javadoc

1   //--------------------------------------
2   //
3   // ChromosomeMap.java
4   // Since: 2009/07/29
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   * draw chromosome map
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); // 1-origin
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); // 1-origin
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 					// make chromosome range
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 					// make chromosome window
187 					ChromosomeWindow window = new ChromosomeWindow(cytoBand.getStart(), cytoBand.getEnd());
188 					chromWindows.put(cytoBand.getChrom(), window);
189 
190 					// make chromosome name list
191 					chrNames.add(cytoBand.getChrom());
192 				}
193 			}
194 
195 			Comparator comparator = new Comparator4ChrName();
196 			Collections.sort(chrNames, comparator);
197 
198 			// make chromosome rank
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 			// draw chromosome map canvas
208 			ChromosomeMapCanvas canvas = new ChromosomeMapCanvas(width, 100, chromWindows);
209 
210 			//drawBlastResult(canvas);
211 
212 			// draw cytoband
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 			// query alignment result
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 					//_logger.info(Lens.toJSON(result));
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 }