(メッセージはありません)
@@ -0,0 +1,1111 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.text.*; | |
3 | +import java.awt.*; | |
4 | +import java.awt.event.*; | |
5 | +import javax.swing.*; | |
6 | +import java.util.*; | |
7 | +import javax.swing.table.*; | |
8 | +import java.util.concurrent.*; | |
9 | +import java.lang.management.*; | |
10 | + | |
11 | +/** | |
12 | + * 候補構造を表すクラスです. | |
13 | + * @author 横井一仁 | |
14 | + * @version 20081221 | |
15 | + */ | |
16 | +class Candidate extends Glycan | |
17 | +{ | |
18 | + java.util.List<Composition> frags_t; // 理論上のフラグメント組成 | |
19 | + double[] masses_t; // 理論上のフラグメントの分子量 | |
20 | + static double[] masses_a; // 実測フラグメントの分子量(インスタンス間で共有) | |
21 | + static double[] freq; // 出現確率を格納した配列(インスタンス間で共有) | |
22 | + static String adduct = MassCalc.Na_ION; // 付加イオン(デフォルトはNa+) | |
23 | + static boolean monoavg = MassCalc.MONO_MASS; // Monoisotopic(ture),Averaget(false) | |
24 | + static double tolerance_psd = 1.0; // 実測値と理論値の許容誤差(PSD) | |
25 | + Fragmentation fg = new Fragmentation(); // フラグメント化するクラス | |
26 | + | |
27 | + static int window = 1; // 出現確率の区分け幅(Da) | |
28 | + static final int POSITIVE_SCORING = 0; // ポジティブなフラグメントのみしか考えないスコアリング | |
29 | + static final int TFIDF_SCORING = 1; // tf-idfのスコアリング | |
30 | + static final int PENALTY01_SCORING = 2; // ペナルティに係数0.1をかけたスコアリング | |
31 | + static final int PENALTY001_SCORING = 3; // ペナルティに係数0.01をかけたスコアリング | |
32 | + static final int PMF_SCORING = 4; // 主にPMF法に用いられているスコアリング | |
33 | + static final int GEOMETRICAVG_SCORING = 5; // 確率の相乗平均を用いたスコアリング | |
34 | + static int formula = TFIDF_SCORING; // 予測に用いるスコア式(デフォルトはTFIDF_SCORING) | |
35 | + | |
36 | + public Candidate() | |
37 | + { | |
38 | + // 現在のところ継承に必要である以外,処理は何もしない. | |
39 | + } | |
40 | + | |
41 | + public Candidate(Glycan gc) throws Exception | |
42 | + { | |
43 | + this.setNode(gc.getNode()); // 構造を登録する. | |
44 | + this.setEdge(gc.getEdge()); | |
45 | + this.setChildren(gc.getChildren()); | |
46 | + | |
47 | + Glycan temp_gc = new Glycan(gc); | |
48 | + temp_gc.toHexose(); // "Glc", "Gal"などを"Hex"に変換 | |
49 | + fg.setGlycan(temp_gc); | |
50 | + this.frags_t = fg.getComposition(); // それぞれのフラグメントを取得する. | |
51 | + this.masses_t = new double[this.frags_t.size()]; // フラグメント数と同じサイズの配列を用意 | |
52 | + | |
53 | + int i = 0; | |
54 | + for (Composition temp_cp : this.frags_t) | |
55 | + masses_t[i++] = temp_cp.getMass(monoavg, adduct); // フラグメントの分子量を計算しておく | |
56 | + } | |
57 | + | |
58 | + /** | |
59 | + * 実測フラグメントの値を登録します. | |
60 | + * @param temp_freq 実測フラグメントの値を格納した配列 | |
61 | + */ | |
62 | + public synchronized static void setMasses_a(double[] masses_a) | |
63 | + { | |
64 | + Candidate.masses_a = masses_a; | |
65 | + } | |
66 | + | |
67 | + /** | |
68 | + * 出現確率を格納した配列を登録します. | |
69 | + * @param freq 出現確率を格納した配列 | |
70 | + */ | |
71 | + public synchronized static void setFreq(double[] freq) | |
72 | + { | |
73 | + Candidate.freq = freq; | |
74 | + } | |
75 | + | |
76 | + /** | |
77 | + * 出現確率を格納した配列を返します. | |
78 | + * @return 出現確率を格納した配列 | |
79 | + */ | |
80 | + public synchronized static double[] getFreq() | |
81 | + { | |
82 | + return Candidate.freq; | |
83 | + } | |
84 | + | |
85 | + /** | |
86 | + * モノアイソトープ,またはアベレージで計算するかを設定します. | |
87 | + * @param monoavg モノアイソトピックまたはアベレージ | |
88 | + */ | |
89 | + public synchronized static void setMonoavg(boolean monoavg) throws Exception | |
90 | + { | |
91 | + Candidate.monoavg = monoavg; // クラスメンバとする. | |
92 | + } | |
93 | + | |
94 | + /** | |
95 | + * 予測に用いる付加イオンを指定します. | |
96 | + * @param adduct 付加イオン(デフォルトはNa+) | |
97 | + */ | |
98 | + public synchronized static void setAdduct(String adduct) | |
99 | + { | |
100 | + Candidate.adduct = adduct; // クラスメンバとする. | |
101 | + } | |
102 | + | |
103 | + /** | |
104 | + * 予測に用いる付加イオンを指定します. | |
105 | + * @param adduct 付加イオン(デフォルトはNa+) | |
106 | + */ | |
107 | + public synchronized static void setPsdTolerance(double tolerance_psd) | |
108 | + { | |
109 | + Candidate.tolerance_psd = tolerance_psd; // クラスメンバとする. | |
110 | + } | |
111 | + | |
112 | + /** | |
113 | + * 予測に用いるスコア式を指定します. | |
114 | + * @param formula スコア式 | |
115 | + */ | |
116 | + public synchronized static void setScoringFormula(int formula) | |
117 | + { | |
118 | + Candidate.formula = formula; // クラスメンバとする. | |
119 | + } | |
120 | + | |
121 | + /** | |
122 | + * 予測に用いるスコア式を返します. | |
123 | + * @return 指定されたスコア式を表す数字 | |
124 | + */ | |
125 | + public synchronized static int getScoringFormula() | |
126 | + { | |
127 | + return Candidate.formula; | |
128 | + } | |
129 | + | |
130 | + /** | |
131 | + * 出現確率分布のウィンドウサイズを指定します. | |
132 | + * @param window ウィンドウサイズ | |
133 | + */ | |
134 | + public synchronized static void setWindowSize(int window) | |
135 | + { | |
136 | + Candidate.window = window; // クラスメンバとする. | |
137 | + } | |
138 | + | |
139 | + /** | |
140 | + * 現在登録されている出現確率分布のウィンドウサイズを取得します. | |
141 | + * @return ウィンドウサイズ | |
142 | + */ | |
143 | + public synchronized static int getWindowSize() | |
144 | + { | |
145 | + return window; // Candidateクラスのstatic変数を呼び出す. | |
146 | + } | |
147 | + | |
148 | + // 実測値と出現頻度値より,糖鎖構造のスコアを計算します. | |
149 | + public synchronized double getScore() throws Exception | |
150 | + { | |
151 | + double score = 0.0; | |
152 | + double penalty = 0.0; | |
153 | + boolean[] check = new boolean[freq.length]; // 再度利用しないようにフラッグを立てる. | |
154 | + int count_posi = 0, count_nega = 0; // ペナルティに用いる. | |
155 | + | |
156 | + for (double mass_t : masses_t) // 糖鎖のフラグメント分子量を取得する. | |
157 | + for (double mass_a : masses_a) // 実測値と理論値とのマッチング | |
158 | + if (!check[(int)(mass_t/window)] && Math.abs(mass_a - mass_t) < tolerance_psd) | |
159 | + { | |
160 | + score += -Math.log(freq[(int)(mass_t/window)]); | |
161 | + check[(int)(mass_t/window)] = true; // 再度利用しないようにフラッグを立てる. | |
162 | + count_posi++; | |
163 | + } | |
164 | + else | |
165 | + { | |
166 | + penalty += -Math.log(1.1 - freq[(int)(mass_t/window)]); | |
167 | + count_nega++; // マッチしなかった実測値の個数を数える | |
168 | + } | |
169 | + | |
170 | + if (formula == Candidate.POSITIVE_SCORING) // ポジティブなフラグメントのみしか考えないスコアリング | |
171 | + return score; // 出現確率が低い,珍しいものの値を上げる. | |
172 | + else if (formula == Candidate.TFIDF_SCORING) // tf-idfのスコアリング | |
173 | + return (score + 1.0) * count_posi / masses_t.length; | |
174 | + else if (formula == Candidate.PENALTY01_SCORING) // ペナルティに係数0.1をかけたスコアリング | |
175 | + return score - 0.1 * penalty; | |
176 | + else if (formula == Candidate.PENALTY001_SCORING) // ペナルティに係数0.01をかけたスコアリング | |
177 | + return score - 0.01 * penalty; | |
178 | + else if (formula == Candidate.PMF_SCORING) // 主にPMF法に用いられているスコアリング | |
179 | + return score + penalty; | |
180 | + else if (formula == Candidate.GEOMETRICAVG_SCORING) // 確率の相乗平均を用いたスコアリング | |
181 | + return (score + penalty) / masses_t.length; | |
182 | + else | |
183 | + throw new Exception("unknown scoring formula number: " + formula); | |
184 | + } | |
185 | + | |
186 | + /** | |
187 | + * 候補構造のフラグメントが実測フラグメントと何個一致したかを返します. | |
188 | + * @return マッチしたフラグメント数 | |
189 | + */ | |
190 | + public int countMatch() | |
191 | + { | |
192 | + int count = 0; | |
193 | + for (double mass : this.masses_t) | |
194 | + { | |
195 | + boolean check = false; | |
196 | + for (int i = 0; i < masses_a.length && !check; i++) | |
197 | + if (mass - 1.0 < masses_a[i] && masses_a[i] < mass + 1.0) | |
198 | + { | |
199 | + count++; // 実測値と理論値がいくつマッチするか数える. | |
200 | + check = true; // 同じフラグメントで2回数えないようにする. | |
201 | + } | |
202 | + } | |
203 | + | |
204 | + return count; | |
205 | + } | |
206 | + | |
207 | + /** | |
208 | + * 候補構造のフラグメントの何%が実測フラグメントと一致したかを返します. | |
209 | + * @return 理論上のフラグメント数に対するマッチしたフラグメントの割合 | |
210 | + */ | |
211 | + public double getOccupancy() | |
212 | + { | |
213 | + return 100.0 * this.countMatch() / this.masses_t.length; // (100 * 一致数 / 理論フラグメント数) | |
214 | + } | |
215 | + | |
216 | + /** | |
217 | + * 候補構造のフラグメントのm/zを返します. | |
218 | + * @return フラグメントのm/zの配列 | |
219 | + */ | |
220 | + public double[] getFragMasses() | |
221 | + { | |
222 | + return this.masses_t; | |
223 | + } | |
224 | +} | |
225 | + | |
226 | +/** | |
227 | + * フラグメントイオンから糖鎖構造を予測するクラスです. | |
228 | + * @author 横井一仁 | |
229 | + * @version 20080425 | |
230 | + */ | |
231 | +public class Prediction extends Observable // 進行状況の監視を可能とする. | |
232 | +{ | |
233 | + CompositionTools cp_agg = new CompositionTools(); // 継承の代わりに集約を用いる. | |
234 | + double precursor = 0.0; // プレカーサーイオンの実測値 | |
235 | + double[] masses_a; // フラグメント分子量の実測値 | |
236 | + double tolerance_psd; // 実測値と理論値の許容誤差(PSD) | |
237 | + double tolerance_ms = 1.0; // 指定がなければ,1.0とする. | |
238 | + Glycan known_gc; // 既知構造 | |
239 | + Composition known_cp; // 既知組成 | |
240 | + int percent; // 進捗情報表示するために用いる. | |
241 | + boolean flag = true; // キャンセルされた時に断片化処理を抜けるためのフラッグ | |
242 | + | |
243 | + /** | |
244 | + * モノアイソトープ,またはアベレージで計算するかを設定します. | |
245 | + * @param monoavg モノアイソトピックまたはアベレージ. | |
246 | + */ | |
247 | + public void setMonoavg(boolean monoavg) throws Exception | |
248 | + { | |
249 | + Candidate.setMonoavg(monoavg); // Candidateクラスのstatic変数として登録する. | |
250 | + cp_agg.setMonoavg(monoavg); // 組成を予測するクラスのメソッドを利用して登録する. | |
251 | + } | |
252 | + | |
253 | + /** | |
254 | + * 予測に用いる付加イオンを指定します. | |
255 | + * @param adduct 付加イオン(デフォルトはNa+) | |
256 | + */ | |
257 | + public void setAdduct(String adduct) throws Exception | |
258 | + { | |
259 | + Candidate.setAdduct(adduct); // Candidateクラスのstatic変数として登録する. | |
260 | + cp_agg.setAdduct(adduct); // 組成を予測するクラスのメソッドを利用して登録する. | |
261 | + } | |
262 | + | |
263 | + /** | |
264 | + * PSDスペクトルの実測値と理論値の許容誤差を登録します. | |
265 | + * @param tolerance_psd 実測値と理論値の許容誤差 | |
266 | + */ | |
267 | + public void setPsdTolerance(double tolerance_psd) throws Exception | |
268 | + { | |
269 | + this.tolerance_psd = tolerance_psd; // クラスメンバとする. | |
270 | + Candidate.setPsdTolerance(tolerance_psd); // Candidateクラスのstatic変数として登録する. | |
271 | + } | |
272 | + | |
273 | + /** | |
274 | + * フラグメントにおける実測の<I>m/z</I> を登録します. | |
275 | + * @param masses_a フラグメントにおける実測の<I>m/z</I> | |
276 | + */ | |
277 | + public void setFragments(double[] masses_a) | |
278 | + { | |
279 | + this.masses_a = masses_a; // メンバ変数として格納 | |
280 | + Candidate.setMasses_a(masses_a); // Candidateクラスのstatic変数として登録する. | |
281 | + } | |
282 | + | |
283 | + /** | |
284 | + * 予測に用いるスコア式を指定します. | |
285 | + * @param formula スコア式 | |
286 | + */ | |
287 | + public void setScoringFormula(int formula) | |
288 | + { | |
289 | + Candidate.setScoringFormula(formula); // Candidateクラスのstatic変数として登録する. | |
290 | + } | |
291 | + | |
292 | + /** | |
293 | + * 出現確率分布のウィンドウサイズを指定します. | |
294 | + * @param window ウィンドウサイズ | |
295 | + */ | |
296 | + public void setWindowSize(int window) | |
297 | + { | |
298 | + Candidate.setWindowSize(window); // Candidateクラスのstatic変数として登録する. | |
299 | + } | |
300 | + | |
301 | + /** | |
302 | + * 現在登録されている出現確率分布のウィンドウサイズを取得します. | |
303 | + * @return ウィンドウサイズ | |
304 | + */ | |
305 | + public int getWindowSize() | |
306 | + { | |
307 | + return Candidate.getWindowSize(); // Candidateクラスのstatic変数を呼び出す. | |
308 | + } | |
309 | + | |
310 | + /** | |
311 | + * プレカーサーマスの<I>m/z</I> を登録します. | |
312 | + * @param precursor プレカーサーマスの<I>m/z</I> | |
313 | + */ | |
314 | + public void setPrecursorMass(double precursor) | |
315 | + { | |
316 | + this.precursor = precursor; // メンバ変数として格納 | |
317 | + } | |
318 | + | |
319 | + /** | |
320 | + * 糖鎖組成の予測に用いる許容誤差を登録します. | |
321 | + * @param tolerance_ms 許容誤差 | |
322 | + */ | |
323 | + public void setMsTolerance(double tolerance_ms) | |
324 | + { | |
325 | + this.tolerance_ms = tolerance_ms; | |
326 | + } | |
327 | + | |
328 | + /** | |
329 | + * 既知糖鎖構造を登録します. | |
330 | + * @param known_gc 既知構造 | |
331 | + */ | |
332 | + public void setGlycan(Glycan known_gc) | |
333 | + { | |
334 | + this.known_gc = known_gc; | |
335 | + } | |
336 | + | |
337 | + /** | |
338 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
339 | + * @param lcb 長鎖塩基組成 | |
340 | + */ | |
341 | + public void setLongChainBase(java.util.List<String> lcb) throws Exception | |
342 | + { | |
343 | + cp_agg.setLongChainBase(lcb); | |
344 | + } | |
345 | + | |
346 | + /** | |
347 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
348 | + * @param fa 脂肪酸組成 | |
349 | + */ | |
350 | + public void setFattyAcid(java.util.List<String> fa) throws Exception | |
351 | + { | |
352 | + cp_agg.setFattyAcid(fa); | |
353 | + } | |
354 | + | |
355 | + /** | |
356 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
357 | + * @param min 炭素数の最小値 | |
358 | + * @param max 炭素数の最大値 | |
359 | + */ | |
360 | + public void setLongChainBase(int min, int max) throws Exception | |
361 | + { | |
362 | + cp_agg.setLongChainBase(min, max); | |
363 | + } | |
364 | + | |
365 | + /** | |
366 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
367 | + * @param min 炭素数の最小値 | |
368 | + * @param max 炭素数の最大値 | |
369 | + */ | |
370 | + public void setFattyAcid(int min, int max, int bond) throws Exception | |
371 | + { | |
372 | + cp_agg.setFattyAcid(min, max, bond); | |
373 | + } | |
374 | + | |
375 | + /** | |
376 | + * 糖鎖組成の予測に用いるセラミド組成を登録します. | |
377 | + * @param ceramide セラミド組成 | |
378 | + */ | |
379 | + public void setCeramide(java.util.List<String> ceramide) throws Exception | |
380 | + { | |
381 | + cp_agg.setCeramide(ceramide); | |
382 | + } | |
383 | + | |
384 | + /** | |
385 | + * 糖鎖組成の予測に用いるセラミド組成を登録します. | |
386 | + * @param min 炭素数の最小値 | |
387 | + * @param max 炭素数の最大値 | |
388 | + * @param bond 脂肪酸の二重結合の最大値 | |
389 | + */ | |
390 | + public void setCeramide(int min, int max, int bond) | |
391 | + { | |
392 | + cp_agg.setCeramide(min, max, bond); | |
393 | + } | |
394 | + | |
395 | + /** | |
396 | + * 予測で考慮する各糖の糖数を指定します. | |
397 | + * @param str 糖数を指定する糖 | |
398 | + * @param max 指定する糖数 | |
399 | + */ | |
400 | + public void setMax(String str, int max) throws Exception | |
401 | + { // デフォルトはhex_max = 10, hexnac_max = 10, dhex_max = 10, dhexme_max = 0, pen_max = 0 | |
402 | + cp_agg.setMax(str, max); | |
403 | + } | |
404 | + | |
405 | + /** | |
406 | + * 予測で考慮する各糖の糖数を指定します. | |
407 | + * @param str 指定する糖 | |
408 | + * @param bl 糖を存在させるかを指定 | |
409 | + */ | |
410 | + public void setMax(String str, boolean bl) throws Exception | |
411 | + { | |
412 | + cp_agg.setMax(str, bl); | |
413 | + } | |
414 | + | |
415 | + /** | |
416 | + * 予測された候補構造を返します. | |
417 | + * @return スコアが高い順に予想構造を返します. | |
418 | + */ | |
419 | + public java.util.List<? extends Candidate> getPrediction() throws Exception | |
420 | + { // 指定された条件から候補構造を生成します. | |
421 | + java.util.List<Composition> cps = getCandidateComposition(); // 候補組成を作成 | |
422 | + java.util.List<Glycan> candi = this.getCandidateGlycan2(cps); // 候補構造を生成し,リストに格納 | |
423 | + java.util.List<Candidate> al = this.toCandidateInstance2(candi); // Glycanを,Candidateの候補構造として登録 | |
424 | + Candidate.setFreq(this.getFreqency(al)); // 出現確率を計算し, | |
425 | + // Candidateクラスのstatic変数として登録 | |
426 | + Collections.sort(al, new Comparator<Candidate>() // スコア順にソート | |
427 | + { | |
428 | + public int compare(Candidate cp1, Candidate cp2) | |
429 | + { | |
430 | + double sub = 0.0; // スコアの差 | |
431 | + try | |
432 | + { | |
433 | + double score1 = cp1.getScore(); | |
434 | + double score2 = cp2.getScore(); | |
435 | + | |
436 | + if (score1 == score2) // スコアが等しい構造は,分岐数の少ない | |
437 | + sub = cp1.countLeaf() - cp2.countLeaf(); // (葉ノードの数が少ない)構造を上位に表示 | |
438 | + else | |
439 | + sub = score2 - score1; | |
440 | + | |
441 | + } | |
442 | + catch (Exception e) | |
443 | + { | |
444 | + System.err.println("Prediction.getPrediction(): score compare error"); | |
445 | + } | |
446 | + | |
447 | + return (int)(sub*1024); // 精度を1024倍に上げる | |
448 | + } | |
449 | + }); // スコアが高い順にソートを行う. | |
450 | + | |
451 | + return al; | |
452 | + } | |
453 | + | |
454 | + /** | |
455 | + * 候補組成を生成し,リストに格納します. | |
456 | + */ | |
457 | + protected java.util.List<Composition> getCandidateComposition() throws Exception | |
458 | + { | |
459 | + java.util.List<Composition> cps; // 考えられる組成を格納するリスト | |
460 | + | |
461 | + cp_agg.setComposition(known_cp); | |
462 | + cp_agg.setGlycan(known_gc); | |
463 | + cp_agg.setMsTolerance(tolerance_ms); | |
464 | + | |
465 | + if (precursor == 0.0) // 親マスの分子量が登録されていない場合, | |
466 | + { // フラグメント分子量の最大実測値から計算する. | |
467 | + cp_agg.setMass(masses_a); // フラグメントのm/zを配列のまま入力する. | |
468 | + cps = cp_agg.getComposition(); | |
469 | + } | |
470 | + else // 親マスの分子量が登録されている場合 | |
471 | + { | |
472 | + cp_agg.setMass(precursor); | |
473 | + java.util.List<Double> masses_a_li = new ArrayList<Double>(); // プレカーサマスとPSDスペクトルの親マスとの | |
474 | + for (double temp : masses_a) // 誤差がPSDスペクトルの許容誤差以内の場合, | |
475 | + if (temp < precursor - tolerance_psd) // かつ,親マスのm/zより,小さなm/z | |
476 | + masses_a_li.add(temp); // を持つPSDフラグメントから組成を予測する. | |
477 | + | |
478 | + double[] masses_a_temp = new double[masses_a_li.size()]; // リストと同じ大きさの配列を用意する. | |
479 | + Iterator<Double> it = masses_a_li.iterator(); | |
480 | + for (int i = 0; it.hasNext(); i++) // リストの内容を配列にコピー | |
481 | + masses_a_temp[i] = it.next(); | |
482 | + | |
483 | + cp_agg.setMass(masses_a_temp); // フラグメントのm/zを配列として入力 | |
484 | + cps = cp_agg.getComposition(); | |
485 | + } | |
486 | + | |
487 | + return cps; | |
488 | + } | |
489 | + | |
490 | + /** | |
491 | + * 候補構造を生成し,リストに格納します.(シングルスレッド版) | |
492 | + */ | |
493 | + protected java.util.List<Glycan> getCandidateGlycan(java.util.List<Composition> cps) throws Exception | |
494 | + { | |
495 | + java.util.List<Glycan> candi = new ArrayList<Glycan>(); // 候補構造を格納するリスト | |
496 | + Iterator<Composition> it = cps.iterator(); | |
497 | + for (int i = 1; it.hasNext() && flag; i++) // プレカーサーマスとフラグメントから求めた候補組成 | |
498 | + { | |
499 | + Composition cp = it.next(); // 候補組成を取得 | |
500 | + | |
501 | + percent = (int)(i * 99.0 / cps.size()); // 処理が何%進んだかを格納(表示が消えるため99%) | |
502 | + String messege = (int)(i*100.0/cps.size()) + "% Creating candidate structure... " + "[" + cp + "]"; | |
503 | + this.setChanged(); // 変更があったことを明示する. | |
504 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
505 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
506 | + | |
507 | + CandidateTools ct = new CandidateTools(); // 候補構造を生成するためにインスタンスを生成 | |
508 | + ct.setComposition(cp); // 既知構造の登録であるsetGlycan()は処理済み. | |
509 | + ct.setGlycan(known_gc); // 既知糖鎖構造を登録 | |
510 | + candi.addAll(ct.getGlycan()); // 候補構造を取得し,全てHashSetに格納 | |
511 | + } | |
512 | + | |
513 | + if (!flag) // 処理が中断された場合, | |
514 | + candi.clear(); // Glycanインスタンスの候補構造を削除 | |
515 | + | |
516 | + return candi; | |
517 | + } | |
518 | + | |
519 | + /** | |
520 | + * 候補構造を生成し,リストに格納します.(マルチスレッド版) | |
521 | + */ | |
522 | + protected java.util.List<Glycan> getCandidateGlycan2(java.util.List<Composition> cps) throws Exception | |
523 | + { | |
524 | + java.util.List<Glycan> candi = new ArrayList<Glycan>(); // 候補構造を格納するリスト | |
525 | + Iterator<Composition> it = cps.iterator(); | |
526 | + for (int i = 1; it.hasNext() && flag; i++) // プレカーサーマスとフラグメントから求めた候補組成 | |
527 | + { | |
528 | + StringBuffer cp_messege = new StringBuffer(); // 現在処理中の糖鎖を文字列表示にて格納 | |
529 | + java.util.List<Composition> cp_thread = new ArrayList<Composition>(); // 1回の処理で並列計算させるタスク | |
530 | + for (int j = 0; j < 8 && it.hasNext(); j++) // 8スレッドを並列 | |
531 | + { | |
532 | + Composition temp = it.next(); // 候補組成を取得 | |
533 | + cp_messege.append("[" + temp + "], "); | |
534 | + cp_thread.add(temp); // マルチスレッドのタスクに追加 | |
535 | + | |
536 | + i++; // 処理済みの個数を増加させる. | |
537 | + } | |
538 | + i--; // for文の中で値が1つ多くなるため,削除 | |
539 | + | |
540 | + percent = (int)(i * 99.0 / cps.size()); // 処理が何%進んだかを格納(表示が消えるため99%) | |
541 | + String messege = (int)(i*100.0/cps.size()) | |
542 | + + "% Creating candidate structures. " | |
543 | + + cp_messege.toString(); | |
544 | + this.setChanged(); // 変更があったことを明示する. | |
545 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
546 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
547 | + | |
548 | + java.util.List<Callable<java.util.List<Glycan>>> tasks | |
549 | + = new ArrayList<Callable<java.util.List<Glycan>>>(); // タスクを格納するリスト | |
550 | + for (Composition temp : cp_thread) | |
551 | + { | |
552 | + Callable<java.util.List<Glycan>> task | |
553 | + = new MultiThreadTool2(new Composition(temp), new Glycan(known_gc)); | |
554 | + tasks.add(task); | |
555 | + } | |
556 | + ExecutorService es = Executors.newFixedThreadPool(8); // 8スレッドで実行 | |
557 | + java.util.List<Future<java.util.List<Glycan>>> futures = es.invokeAll(tasks); // タスクの実行 | |
558 | + | |
559 | + for (Future<java.util.List<Glycan>> future : futures) // 実行結果の回収 | |
560 | + candi.addAll(future.get()); // 候補構造を取得し,全てHashSetに格納 | |
561 | + es.shutdown(); // 並列処理の終了 | |
562 | + } | |
563 | + | |
564 | + if (!flag) // 処理が中断された場合, | |
565 | + candi.clear(); // Glycanインスタンスの候補構造を削除 | |
566 | + | |
567 | + return candi; | |
568 | + } | |
569 | + | |
570 | + /** | |
571 | + * Glycanインスタンスを,Candidateインスタンスとし,フラグメント化を行います.(シングルスレッド版) | |
572 | + */ | |
573 | + protected java.util.List<Candidate> toCandidateInstance(java.util.List<Glycan> candi) throws Exception | |
574 | + { | |
575 | + java.util.List<Candidate> al = new ArrayList<Candidate>(); // スコア付けを行う候補構造 | |
576 | + long start = new Date().getTime(); // プログラム開始時刻 | |
577 | + int candi_size = candi.size(); // 候補構造数を格納 | |
578 | + ListIterator<Glycan> it2 = candi.listIterator(); // 候補構造のイテレータを取得 | |
579 | + for (int i = 1; it2.hasNext() && flag; i++) // 考えられる組成のとり得る構造をArrayListに格納 | |
580 | + { | |
581 | + Glycan temp = it2.next(); | |
582 | + it2.remove(); // 不必要であるGlycanインスタンスを削除する. | |
583 | + | |
584 | + percent = (int)(i * 99.0 / candi_size); // 処理が何%進んだかを格納(表示が消えるため99%) | |
585 | + String messege = progress(i, candi_size, start); // オブザーバに送るメッセージを作成する. | |
586 | + try | |
587 | + { | |
588 | + messege = messege + " [" + temp.toNormalFormat() + "]"; // ノーマルのフォーマットで格納する. | |
589 | + } | |
590 | + catch (Exception e) | |
591 | + { | |
592 | + messege = messege + " [" + temp.toString() + "]"; // 二分岐以上の構造はLinucs形式で格納する. | |
593 | + } | |
594 | + this.setChanged(); // 変更があったことを明示する. | |
595 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
596 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
597 | + | |
598 | + Candidate cd = new Candidate(temp); | |
599 | + al.add(cd); | |
600 | + } | |
601 | + | |
602 | + if (!flag) // 処理が中断された場合, | |
603 | + al.clear(); // Candidateインスタンスの候補構造を削除 | |
604 | + else // 処理が正常に完了した場合, | |
605 | + { | |
606 | + percent = 100; // ProgressMonitorを終了するために100%にする. | |
607 | + this.setChanged(); // 変更があったことを明示する. | |
608 | + this.notifyObservers(progress(candi.size(), candi.size(), start)); // 監視者に進行状況を通知 | |
609 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
610 | + } | |
611 | + | |
612 | + return al; | |
613 | + } | |
614 | + | |
615 | + /** | |
616 | + * Glycanインスタンスを,Candidateインスタンスとし,フラグメント化を行います.(マルチスレッド版) | |
617 | + */ | |
618 | + protected java.util.List<Candidate> toCandidateInstance2(java.util.List<Glycan> candi) throws Exception | |
619 | + { | |
620 | + java.util.List<Candidate> al = new ArrayList<Candidate>(); // スコア付けを行う候補構造 | |
621 | + long start = new Date().getTime(); // プログラム開始時刻 | |
622 | + int candi_size = candi.size(); // 候補構造数を格納 | |
623 | + ListIterator<Glycan> it2 = candi.listIterator(); // 候補構造のイテレータを取得 | |
624 | + for (int i = 1; it2.hasNext() && flag; i++) // 考えられる組成のとり得る構造をArrayListに格納. | |
625 | + { | |
626 | + StringBuffer gc_messege = new StringBuffer(); // 現在処理中の糖鎖を文字列表示にて格納する. | |
627 | + java.util.List<Glycan> gc_thread = new ArrayList<Glycan>(); // 1回の処理で並列計算させるGlycanインスタンス | |
628 | + for (int j = 0; j < 8 && it2.hasNext(); j++) // 8スレッドを並列させるので,8個ずつ処理する. | |
629 | + { | |
630 | + Glycan temp = it2.next(); | |
631 | + try | |
632 | + { | |
633 | + gc_messege.append(temp.toNormalFormat() + ", "); // ノーマルのフォーマットで格納する. | |
634 | + } | |
635 | + catch (Exception e) | |
636 | + { | |
637 | + gc_messege.append(temp.toString() + ", "); // 二分岐以上の構造はLinucs形式で格納する. | |
638 | + } | |
639 | + gc_thread.add(temp); // マルチスレッドのタスクに追加 | |
640 | + it2.remove(); // 不必要であるGlycanインスタンスを削除する. | |
641 | + | |
642 | + i++; // 処理済みの個数を増加させる. | |
643 | + } | |
644 | + i--; // for文の中で値が1つ多くなるため,削除 | |
645 | + | |
646 | + percent = (int)(i * 99.0 / candi_size); // 処理が何%進んだかを格納(表示が消えるため99%) | |
647 | + String messege = progress(i, candi_size, start); // オブザーバに送るメッセージ | |
648 | + messege = messege + " " + gc_messege.toString(); | |
649 | + this.setChanged(); // 変更があったことを明示する. | |
650 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
651 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
652 | + | |
653 | + java.util.List<Callable<Candidate>> tasks = new ArrayList<Callable<Candidate>>(); // タスクを格納するリスト | |
654 | + for (Glycan temp : gc_thread) | |
655 | + { | |
656 | + Callable<Candidate> task = new MultiThreadTool1(new Glycan(temp)); | |
657 | + tasks.add(task); | |
658 | + } | |
659 | + ExecutorService es = Executors.newFixedThreadPool(8); // 8スレッドで実行 | |
660 | + java.util.List<Future<Candidate>> futures = es.invokeAll(tasks); // タスクの実行 | |
661 | + | |
662 | + for (Future<Candidate> future : futures) // 実行結果の回収 | |
663 | + { | |
664 | + Candidate cd = future.get(); | |
665 | + al.add(cd); | |
666 | + } | |
667 | + es.shutdown(); // 並列処理の終了 | |
668 | + } | |
669 | + | |
670 | + if (!flag) // 処理が中断された場合, | |
671 | + al.clear(); // Candidateインスタンスの候補構造を削除する | |
672 | + else // 処理が正常に完了した場合, | |
673 | + { | |
674 | + percent = 100; // ProgressMonitorを終了するために100%にする. | |
675 | + this.setChanged(); // 変更があったことを明示する. | |
676 | + this.notifyObservers(progress(candi.size(), candi.size(), start)); // 監視者に進行状況を通知 | |
677 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
678 | + } | |
679 | + | |
680 | + return al; | |
681 | + } | |
682 | + | |
683 | + /** | |
684 | + * フラグメントの出現確率の計算値を返します. | |
685 | + */ | |
686 | + public double[] getFreqency(java.util.List<? extends Candidate> al) throws Exception | |
687 | + { | |
688 | + double[] freq; // returnする確率分布 | |
689 | + | |
690 | + if (precursor == 0.0) // 親マスの分子量が登録されていない場合, | |
691 | + { // フラグメント分子量の最大実測値から計算 | |
692 | + Arrays.sort(masses_a); // 最大値を取り出すために昇順にソート. | |
693 | + freq = new double[(int)(masses_a[masses_a.length-1]/this.getWindowSize())+100]; // 10Daずつ出現頻度を計算 | |
694 | + } | |
695 | + else // 親マスの分子量が登録されている場合 | |
696 | + freq = new double[(int)(precursor/this.getWindowSize())+100]; // 10Daずつ出現頻度を計算する. | |
697 | + | |
698 | + for (Candidate cd : al) | |
699 | + { | |
700 | + boolean[] check = new boolean[freq.length]; // 1構造で質量が重複させないために使用 | |
701 | + | |
702 | + double[] masses = cd.getFragMasses(); | |
703 | + for (int i = 0; i < masses.length; i++) // それぞれのフラグメントを取得し, | |
704 | + { // フラグメントが存在したらtrueとする. | |
705 | + if ((int)(masses[i]/this.getWindowSize()) > 0) | |
706 | + check[(int)(masses[i]/this.getWindowSize()) - 1] = true; // 前のフラッグを立てる. | |
707 | + | |
708 | + check[(int)(masses[i]/this.getWindowSize())] = true; // 現在の位置のフラッグを立てる. | |
709 | + | |
710 | + if (i+1 < freq.length) | |
711 | + check[(int)(masses[i]/this.getWindowSize()) + 1] = true; // 後ろのフラッグも立てる. | |
712 | + } | |
713 | + | |
714 | + for (int i = 0; i < freq.length; i++) // フラッグを出現確率の配列へコピー | |
715 | + if (check[i]) // フラグメントが存在したら1個増加 | |
716 | + freq[i] += 1.0; | |
717 | + } | |
718 | + | |
719 | + double max = 1.0; // 0で割らないために初期値は1とする. | |
720 | + for (double temp : freq) // 最大値を探す. | |
721 | + max = Math.max(temp,max); | |
722 | + | |
723 | + for (int i = 0; i < freq.length; i++) // 最大値で割り,0.0〜1.0の範囲に変換. | |
724 | + freq[i] = freq[i] / max; | |
725 | + | |
726 | + return freq; | |
727 | + } | |
728 | + | |
729 | + /** | |
730 | + * 進捗情報の表示 | |
731 | + * @parm prog 処理の終わった個数 | |
732 | + * @parm total 処理する個数 | |
733 | + * @parm strat 処理開始時間 | |
734 | + */ | |
735 | + protected String progress(int prog, int total, long start) | |
736 | + { | |
737 | + Calendar cd; | |
738 | + StringBuilder temp = new StringBuilder(64); // リターンする文字列 | |
739 | + | |
740 | + if (total != 0) // 0で割らないための処理 | |
741 | + temp.append((int)(prog*100/total)); | |
742 | + else | |
743 | + temp.append("100"); | |
744 | + temp.append("%"); | |
745 | + | |
746 | + cd = Calendar.getInstance(); | |
747 | + cd.set(Calendar.DAY_OF_YEAR, 1); | |
748 | + cd.set(Calendar.HOUR_OF_DAY, 0); | |
749 | + cd.set(Calendar.MINUTE, 0); | |
750 | + cd.set(Calendar.SECOND, 0); | |
751 | + if (prog != 0) // 0で割らないための処理 | |
752 | + cd.set(Calendar.MILLISECOND, (int)((new Date().getTime() - start)*(total-prog)/prog)); | |
753 | + else | |
754 | + cd.set(Calendar.MILLISECOND, 0); | |
755 | + temp.append(" Remain: "); | |
756 | + temp.append(cd.get(Calendar.DAY_OF_YEAR)-1); | |
757 | + temp.append(":"); | |
758 | + temp.append(new SimpleDateFormat("HH:mm:ss").format(cd.getTime())); | |
759 | + | |
760 | + cd = Calendar.getInstance(); | |
761 | + cd.set(Calendar.DAY_OF_YEAR, 1); | |
762 | + cd.set(Calendar.HOUR_OF_DAY, 0); | |
763 | + cd.set(Calendar.MINUTE, 0); | |
764 | + cd.set(Calendar.SECOND, 0); | |
765 | + cd.set(Calendar.MILLISECOND, (int)(new Date().getTime() - start)); | |
766 | + temp.append(" Current: "); | |
767 | + temp.append(cd.get(Calendar.DAY_OF_YEAR)-1); | |
768 | + temp.append(":"); | |
769 | + temp.append(new SimpleDateFormat("HH:mm:ss").format(cd.getTime())); | |
770 | + | |
771 | + cd = Calendar.getInstance(); | |
772 | + cd.set(Calendar.DAY_OF_YEAR, 1); | |
773 | + cd.set(Calendar.HOUR_OF_DAY, 0); | |
774 | + cd.set(Calendar.MINUTE, 0); | |
775 | + cd.set(Calendar.SECOND, 0); | |
776 | + if (prog != 0) // 0で割らないための処理 | |
777 | + cd.set(Calendar.MILLISECOND, (int)((new Date().getTime() - start)*(total)/prog)); | |
778 | + else | |
779 | + cd.set(Calendar.MILLISECOND, 0); | |
780 | + temp.append(" Total: "); | |
781 | + temp.append(cd.get(Calendar.DAY_OF_YEAR)-1); | |
782 | + temp.append(":"); | |
783 | + temp.append(new SimpleDateFormat("HH:mm:ss").format(cd.getTime())); | |
784 | + | |
785 | + return temp.toString(); | |
786 | + } | |
787 | + | |
788 | + /** | |
789 | + * 理論値による検証(実験結果出力用メソッド) | |
790 | + * @parm args 検証を始める構造のm/z | |
791 | + */ | |
792 | + private static void runSimulation(double args) throws Exception | |
793 | + { | |
794 | + System.out.println("Da,\t選択flag数,\t理論flag数,\t予測可否,\t予測順位,\t出力順位,\t同スコア構造数,\t候補構造数,\tスコア,\t" | |
795 | + + "糖数(ノード数-1),\t予測時間(msec),\t予測時間,\tメモリ使用量,\t分子量,\t構造"); | |
796 | + CompositionTools ci = new CompositionTools(); | |
797 | + for (double d = args; ; d++) // 指定した分子量からシミュレーションを行う. | |
798 | + { | |
799 | + ci.setMass(d); | |
800 | + ci.setGlycan(new Glycan("[][hex]{}")); | |
801 | + java.util.List<String> ceramide = new ArrayList<String>(); | |
802 | + ceramide.add("dc34:1"); | |
803 | + ci.setCeramide(ceramide); // セラミド組成は"dc34:1"のみとする. | |
804 | + ci.setMax("pen", 0); // 各糖数の上限まを指定 | |
805 | + ci.setMax("dhex", 10); | |
806 | + ci.setMax("dhexme", 0); | |
807 | + ci.setMax("hex", 10); | |
808 | + ci.setMax("hexnac", 10); | |
809 | + ci.setMsTolerance(0.5); | |
810 | + for (Composition cp : ci.getComposition()) // 親マスから組成を予測 | |
811 | + { | |
812 | + CandidateTools ct = new CandidateTools(); | |
813 | + ct.setGlycan(new Glycan("[][hex]{}")); | |
814 | + ct.setComposition(cp); | |
815 | + for (Glycan gc : ct.getGlycan()) // 組成から検証構造を生成 | |
816 | + { | |
817 | + java.util.List<Composition> li = gc.getCompositionFragment() ; // 検証構造のフラグメントを得る. | |
818 | + | |
819 | + double[] masses = new double[li.size()]; // 検証構造の全てのフラグメント分子量を格納する. | |
820 | + int i = 0; | |
821 | + for (Composition frags : li) // フラグメント組成のリストから分子量のリストに変換 | |
822 | + { | |
823 | + masses[i] = frags.getMass(MassCalc.MONO_MASS, MassCalc.Na_ION); | |
824 | + i++; | |
825 | + } | |
826 | + | |
827 | + System.out.print(d + "\t"); // Daを表示する. | |
828 | + System.out.print(masses.length + "\t" + li.size() + "\t"); // フラグメント数を表示 | |
829 | + runPrediction(masses, gc); // 与えられたフラグメント分子量から構造を予測 | |
830 | + } | |
831 | + } | |
832 | + } | |
833 | + } | |
834 | + | |
835 | + /** | |
836 | + * 理論値による検証(実験結果出力用メソッド) | |
837 | + * @parm args 検証を始める構造のm/z | |
838 | + * @parm percent 検証構造の何%のフラグメントをランダムに選択するかを指定 | |
839 | + */ | |
840 | + private static void runSimulation(double args, double percent) throws Exception | |
841 | + { | |
842 | + System.out.println("Da,\t選択flag数,\t理論flag数,\t予測可否,\t予測順位,\t出力順位,\t" | |
843 | + + "同スコア構造数,\t候補構造数,\tスコア,\t糖数(ノード数-1),\t" | |
844 | + + "予測時間(msec),\t予測時間,\tメモリ使用量,\t分子量,\t構造"); | |
845 | + CompositionTools ci = new CompositionTools(); | |
846 | + for (double d = args; ; d++) // 指定した分子量からシミュレーションを行う. | |
847 | + { | |
848 | + ci.setMass(d); | |
849 | + ci.setGlycan(new Glycan("[][hex]{}")); | |
850 | + java.util.List<String> ceramide = new ArrayList<String>(); | |
851 | + ceramide.add("dc34:1"); | |
852 | + ci.setCeramide(ceramide); // セラミド組成は"dc34:1"のみとする. | |
853 | + ci.setMax("pen", 0); // 各糖数の上限まを指定 | |
854 | + ci.setMax("dhex", 10); | |
855 | + ci.setMax("dhexme", 0); | |
856 | + ci.setMax("hex", 10); | |
857 | + ci.setMax("hexnac", 10); | |
858 | + ci.setMsTolerance(0.5); | |
859 | + for (Composition cp : ci.getComposition()) // 親マスから組成を予測 | |
860 | + { | |
861 | + CandidateTools ct = new CandidateTools(); | |
862 | + ct.setGlycan(new Glycan("[][hex]{}")); | |
863 | + ct.setComposition(cp); | |
864 | + for (Glycan gc : ct.getGlycan()) // 組成から検証構造を生成 | |
865 | + { | |
866 | + java.util.List<Composition> li = gc.getCompositionFragment() ; // 検証構造のフラグメントを得る. | |
867 | + | |
868 | + double[] masses = new double[(int)((li.size()-1)*percent/100.0)+1]; | |
869 | + // プレカーサーマスは必ず選択する. | |
870 | + masses[0] = li.remove(li.size()-1).getMass(MassCalc.MONO_MASS, MassCalc.Na_ION); | |
871 | + | |
872 | + int i = 1; // 既にプレカーサーマスを登録しているので,1からスタート | |
873 | + while (i < masses.length) // 分子量を格納する配列が一杯になるまで繰り返す. | |
874 | + { // ランダムにフラグメントを選択 | |
875 | + int index = (int)(Math.random() * (li.size()-2)); | |
876 | + masses[i] = li.remove(index).getMass(MassCalc.MONO_MASS, MassCalc.Na_ION); | |
877 | + i++; | |
878 | + } | |
879 | + | |
880 | + for (int j = 1; j < masses.length; j++) // masses[0]がプレカーサーマスであるかどうか | |
881 | + if (masses[j] > masses[0]) // (masses[0]より大きなm/zが存在していないか) | |
882 | + { | |
883 | + throw new Exception("Fragment selection error: " // 念のためチェックする. | |
884 | + + masses[0] + " is not precursor mass."); | |
885 | + } | |
886 | + | |
887 | + System.out.print(d + "\t"); // Daを表示 | |
888 | + System.out.print(masses.length + "\t" + (li.size()+masses.length) + "\t"); // フラグメント数を表示 | |
889 | + runPrediction(masses, gc); // 与えられたフラグメント質量から | |
890 | + } // 構造を予測 | |
891 | + } | |
892 | + } | |
893 | + } | |
894 | + | |
895 | + /** | |
896 | + * 理論値による検証(実験結果出力用メソッド) | |
897 | + * @parm args 検証を始める構造のm/z | |
898 | + */ | |
899 | + private static void runNoiseSimulation(double args) throws Exception | |
900 | + { | |
901 | + System.out.println("条件1,\t条件2,\tDa,\t選択flag数,\t理論flag数,\tノイズflag数,\t予測可否,\t" | |
902 | + + "予測順位,\t出力順位,\t同スコア構造数,\t候補構造数,\tスコア,\t糖数(ノード数-1),\t" | |
903 | + + "予測時間(msec),\t予測時間,\tメモリ使用量,\t分子量,\t構造"); | |
904 | + | |
905 | + int[] percent = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10}; // 検証構造の何%のフラグメントを選択するかを指定 | |
906 | + int[] noise = {2048, 1024, 512, 256, 128, 64, 32, 16, 8}; // 何Daごとに1本のノイズが存在するかを指定 | |
907 | + | |
908 | + for (double d = args; ; d++) // 指定した分子量からシミュレーションを行う. | |
909 | + for (int m = 0; m < percent.length; m++) | |
910 | + for (int n = 0; n < noise.length; n++) | |
911 | + { | |
912 | + CompositionTools ci = new CompositionTools(); | |
913 | + ci.setMass(d); | |
914 | + ci.setGlycan(new Glycan("[][hex]{}")); | |
915 | + java.util.List<String> ceramide = new ArrayList<String>(); | |
916 | + ceramide.add("dc34:1"); | |
917 | + ci.setCeramide(ceramide); // セラミド組成は"dc34:1"のみとする. | |
918 | + ci.setMax("pen", 0); // 各糖数の上限まを指定 | |
919 | + ci.setMax("dhex", 10); | |
920 | + ci.setMax("dhexme", 0); | |
921 | + ci.setMax("hex", 10); | |
922 | + ci.setMax("hexnac", 10); | |
923 | + ci.setMsTolerance(0.5); | |
924 | + for (Composition cp : ci.getComposition()) // 親マスから組成を予測 | |
925 | + { | |
926 | + CandidateTools ct = new CandidateTools(); | |
927 | + ct.setGlycan(new Glycan("[][hex]{}")); | |
928 | + ct.setComposition(cp); | |
929 | + for (Glycan gc : ct.getGlycan()) // 組成から検証構造を生成 | |
930 | + { | |
931 | + java.util.List<Composition> li = gc.getCompositionFragment() ; // 検証構造のフラグメントを得る. | |
932 | + // 検証構造の50%のフラグメント分子量を格納する. | |
933 | + double[] masses = new double[(int)((li.size()-1)*percent[m]/100.0)+1]; | |
934 | + // プレカーサーマスは必ず選択する. | |
935 | + masses[0] = li.remove(li.size()-1).getMass(MassCalc.MONO_MASS, MassCalc.Na_ION); | |
936 | + | |
937 | + int i = 1; // 既にプレカーサーマスを登録しているので,1からスタート | |
938 | + while (i < masses.length) // 分子量を格納する配列が一杯になるまで繰り返す. | |
939 | + { // ランダムにフラグメントを選択 | |
940 | + int index = (int)(Math.random() * (li.size()-2)); | |
941 | + masses[i] = li.remove(index).getMass(MassCalc.MONO_MASS, MassCalc.Na_ION); | |
942 | + i++; | |
943 | + } | |
944 | + | |
945 | + // ノイズを挿入 | |
946 | + double mass = gc.getMass(MassCalc.MONO_MASS, MassCalc.Na_ION); | |
947 | + int noise_count = (int)(mass / noise[n]); // ノイズ数 | |
948 | + double[] noise_masses = new double[masses.length + noise_count]; // ノイズ入りフラグメントを再定義 | |
949 | + for (int j = 0; j < masses.length; j++) // ノイズ挿入前フラグメントをコピー | |
950 | + noise_masses[j] = masses[j]; | |
951 | + for (int j = masses.length; j < noise_masses.length; j++) // ノイズを追加 | |
952 | + noise_masses[j] = Math.random() * mass; | |
953 | + | |
954 | + for (int j = 1; j < masses.length; j++) // masses[0]がプレカーサーマスであるかどうか | |
955 | + if (masses[j] > masses[0]) // (masses[0]より大きなm/zが存在していないか) | |
956 | + throw new Exception("Fragment selection error: " // 念のためチェックする. | |
957 | + + masses[0] + " is not precursor mass."); | |
958 | + | |
959 | + System.out.print(percent[m] + "\t" + noise[n] + "\t"); // 予測条件を表示する. | |
960 | + System.out.print(d + "\t"); // Daを表示する. | |
961 | + System.out.print(masses.length + "\t" + (li.size()+masses.length) + "\t"); // フラグメント数 | |
962 | + System.out.print(noise_count + "\t"); // ノイズフラグメント数 | |
963 | + runPrediction(noise_masses, gc); // 与えられたフラグメント分子量から | |
964 | + } // 構造を予測 | |
965 | + } | |
966 | + } | |
967 | + } | |
968 | + | |
969 | + /** | |
970 | + * 与えられたフラグメントの質量から構造を予測し,その統計情報を出力します. | |
971 | + * @parm masses 予測に用いるフラグメント分子量 | |
972 | + * @parm gc 正解構造 | |
973 | + */ | |
974 | + private static void runPrediction(double[] masses, Glycan gc) throws Exception | |
975 | + { | |
976 | + /**/long start = new Date().getTime(); // 開始時刻 | |
977 | + | |
978 | + Prediction pd = new Prediction(); // ここから予測 | |
979 | + pd.setFragments(masses); // フラグメントの実測値の配列を登録 | |
980 | + pd.setMsTolerance(0.5); // 許容誤差を格納 | |
981 | + pd.setGlycan(new Glycan("[][hex]{}")); // 既知構造を登録 | |
982 | + pd.setCeramide(30,44,0); // セラミド組成は炭素数30-44とする. | |
983 | + pd.setMax("pen", 0); // 各糖数の上限まを指定 | |
984 | + pd.setMax("dhex", 10); | |
985 | + pd.setMax("dhexme", 0); | |
986 | + pd.setMax("hex", 10); | |
987 | + pd.setMax("hexnac", 10); | |
988 | + pd.setScoringFormula(Candidate.TFIDF_SCORING); | |
989 | + | |
990 | + Iterator<? extends Candidate> it = pd.getPrediction().iterator(); // 結果を表示 | |
991 | + boolean success = false; // 予測が成功したか否かを格納する. | |
992 | + boolean flag = true; // while文を抜けるのに用いる. | |
993 | + int rank = 0, count = 0; // 予測順位と候補構造数 | |
994 | + int rank2 = 0, same_score = 1; | |
995 | + double score = 0.0, previous_score = 0.0; | |
996 | + while (it.hasNext()) | |
997 | + { | |
998 | + Candidate cd = it.next(); | |
999 | + | |
1000 | + if (flag) // まだ入力構造が現れなかった場合,予測順位の値を更新 | |
1001 | + rank++; | |
1002 | + | |
1003 | + if (previous_score != cd.getScore() && flag) // 前回のスコアと異なる場合 | |
1004 | + { | |
1005 | + rank2++; // ランクが下がる. | |
1006 | + same_score = 1; // 数をクリア | |
1007 | + } | |
1008 | + | |
1009 | + // 前のスコアと同じスコアである場合,かつ[まだ入力構造しない場合,または入力構造と同じスコアである場合] | |
1010 | + if (previous_score == cd.getScore() && (flag || score == cd.getScore())) | |
1011 | + same_score++; | |
1012 | + | |
1013 | + if (new Glycan(cd.toString()).equals(gc)) // 入力構造が存在した場合 | |
1014 | + { | |
1015 | + success = true; // 予測に成功 | |
1016 | + score = cd.getScore(); // スコアの値を保存 | |
1017 | + flag = false; | |
1018 | + } | |
1019 | + | |
1020 | + previous_score = cd.getScore(); // スコアの値を保存 | |
1021 | + count++; // 候補構造数 | |
1022 | + } | |
1023 | + | |
1024 | + /**/long end = new Date().getTime(); // 終了時刻 | |
1025 | + /**/long time = end - start; // 処理時間を表示 | |
1026 | + Calendar cd = Calendar.getInstance(); | |
1027 | + cd.set(Calendar.DAY_OF_YEAR, 1); | |
1028 | + cd.set(Calendar.HOUR_OF_DAY, 0); | |
1029 | + cd.set(Calendar.MINUTE, 0); | |
1030 | + cd.set(Calendar.SECOND, 0); | |
1031 | + cd.set(Calendar.MILLISECOND, (int)(new Date().getTime() - start)); | |
1032 | + | |
1033 | + MemoryMXBean mm = ManagementFactory.getMemoryMXBean(); | |
1034 | + MemoryUsage mu = mm.getHeapMemoryUsage(); | |
1035 | + | |
1036 | + // 予測可否,予測順位,出力順位,同スコア構造数,候補構造数,スコア | |
1037 | + // 糖数(ノード数-1),予測時間(msec),予測時間,メモリ使用量,分子量,構造 | |
1038 | + System.out.println(success | |
1039 | + + "\t" + rank2 + "\t" + rank | |
1040 | + + "\t" + same_score + "\t" + count | |
1041 | + + "\t" + String.format("%.4f", score) | |
1042 | + + "\t" + (gc.size()-1) | |
1043 | + + "\t" + time | |
1044 | + + "\t" + new SimpleDateFormat("HH:mm:ss").format(cd.getTime()) | |
1045 | + + "\t" + String.format("%.1f/", mu.getUsed() / 1024.0 / 1024) | |
1046 | + + String.format("%.1fMB", mu.getMax() / 1024.0 / 1024) | |
1047 | + + "\t" + String.format("%.4f", gc.getMass(MassCalc.MONO_MASS, MassCalc.Na_ION)) | |
1048 | + + "\t" + gc.toNormalFormat()); | |
1049 | + it.hasNext(); // ここの行までに候補構造による使用済みメモリを解放しないために実行 | |
1050 | + System.gc(); // ガーベジコレクタによるメモリの解放 | |
1051 | + } | |
1052 | + | |
1053 | + /** | |
1054 | + * 遊離糖鎖の構造予測 | |
1055 | + */ | |
1056 | + private static void runFreeGlycanTest() throws Exception | |
1057 | + { // HexNAc-HexNAc-HexNAc-HexNAc-HexNAcの実測フラグメント | |
1058 | + double[] masses = {227.1, 346.3, 429.3, 447.1, 548.5, 631.4, 649.3, 833.8, 851.7, 1054.2}; | |
1059 | + Prediction pd = new Prediction(); // ここから予測 | |
1060 | + pd.setPrecursorMass(1056.4008); | |
1061 | + pd.setMsTolerance(0.5); // 許容誤差を格納 | |
1062 | + pd.setFragments(masses); // フラグメントの実測値の配列を登録 | |
1063 | + pd.setPsdTolerance(1.0); | |
1064 | + pd.setGlycan(new Glycan("[][hexnac]{}")); // 既知構造を登録 | |
1065 | + pd.setMax("pen", false); // 各糖数の上限まを指定 | |
1066 | + pd.setMax("dhex", false); | |
1067 | + pd.setMax("dhexme", false); | |
1068 | + pd.setMax("hex", false); | |
1069 | + pd.setMax("hexnac", true); | |
1070 | + pd.setScoringFormula(Candidate.TFIDF_SCORING); | |
1071 | + | |
1072 | + for (Candidate cd : pd.getPrediction()) | |
1073 | + System.out.println(cd); | |
1074 | + } | |
1075 | +} | |
1076 | + | |
1077 | +class MultiThreadTool1 implements Callable<Candidate> | |
1078 | +{ | |
1079 | + Glycan gc; // 並列処理のために保存しておく候補構造 | |
1080 | + | |
1081 | + public MultiThreadTool1(Glycan gc) throws Exception | |
1082 | + { | |
1083 | + this.gc = gc; // 候補構造を登録 | |
1084 | + } | |
1085 | + | |
1086 | + public Candidate call() throws Exception | |
1087 | + { | |
1088 | + return new Candidate(gc); // フラグメント化後の分子量の計算済みの候補構造を返す. | |
1089 | + } | |
1090 | +} | |
1091 | + | |
1092 | +class MultiThreadTool2 implements Callable<java.util.List<Glycan>> | |
1093 | +{ | |
1094 | + Composition cp; // 並列処理のために保存しておく候補組成 | |
1095 | + Glycan known_gc; | |
1096 | + | |
1097 | + public MultiThreadTool2(Composition cp, Glycan known_gc) throws Exception | |
1098 | + { | |
1099 | + this.cp = cp; | |
1100 | + this.known_gc = known_gc; | |
1101 | + } | |
1102 | + | |
1103 | + public java.util.List<Glycan> call() throws Exception | |
1104 | + { | |
1105 | + CandidateTools ct = new CandidateTools(); // 候補構造を生成するためにインスタンスを生成 | |
1106 | + ct.setComposition(cp); // 既知構造の登録であるsetGlycan()は処理済み. | |
1107 | + ct.setGlycan(known_gc); // 既知糖鎖構造を登録 | |
1108 | + | |
1109 | + return ct.getGlycan(); | |
1110 | + } | |
1111 | +} |
@@ -0,0 +1,238 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | +import java.io.*; | |
5 | +import javax.servlet.*; | |
6 | +import javax.servlet.http.*; | |
7 | + | |
8 | +/** | |
9 | + * フラグメントイオンの組成と理論上の<I>m/z</I> を計算するServletクラスです. | |
10 | + * @author 横井一仁 | |
11 | + * @version 20090102 | |
12 | + */ | |
13 | +public class FragmentationServlet extends HttpServlet | |
14 | +{ | |
15 | + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException | |
16 | + { | |
17 | + response.setContentType("text/html"); | |
18 | + PrintWriter out = response.getWriter(); | |
19 | + | |
20 | + try | |
21 | + { | |
22 | + Glycan gc; // 開裂させたい構造 | |
23 | + String adduct = ""; // 付加イオン | |
24 | + boolean monoavg = true; // Monoisotopic(ture),Averaget(false) | |
25 | + | |
26 | + try | |
27 | + { | |
28 | + gc = new Glycan(request.getParameter("struct")); // 何も指定されない場合,例外 | |
29 | + } | |
30 | + catch (Exception e1) | |
31 | + { | |
32 | + try | |
33 | + { | |
34 | + GlycanTools gi = new GlycanTools(); // Linucs形式以外の形式で試してみる. | |
35 | + gc = gi.readNormalFormat(request.getParameter("struct")); | |
36 | + } | |
37 | + catch (Exception e2) | |
38 | + { | |
39 | + GlycanTools gi = new GlycanTools(); // 全てにおいて失敗した場合,L5を表示する. | |
40 | + gc = gi.readNormalFormat("dc34:1-glc-man-glcnac-galnac-galnac"); | |
41 | + } | |
42 | + } | |
43 | + | |
44 | + try | |
45 | + { | |
46 | + adduct = request.getParameter("adduct"); | |
47 | + | |
48 | + if (adduct == null) // 何も指定されなかった場合, | |
49 | + adduct = MassCalc.Na_ION; // 左のイオンを初期付加イオンとする. | |
50 | + } | |
51 | + catch (Exception e) | |
52 | + { | |
53 | + adduct = MassCalc.Na_ION; // 左のイオンを初期付加イオンとする. | |
54 | + } | |
55 | + | |
56 | + try | |
57 | + { | |
58 | + String temp = request.getParameter("monoavg"); | |
59 | + if (temp.equals("mono")) | |
60 | + monoavg = true; | |
61 | + else if (temp.equals("avg")) | |
62 | + monoavg = false; | |
63 | + else | |
64 | + monoavg = true; // その他の場合Monoisotopicとする. | |
65 | + } | |
66 | + catch (Exception e) | |
67 | + { | |
68 | + monoavg = true; // その他の場合Monoisotopicとする. | |
69 | + } | |
70 | + | |
71 | + out.println("<HTML><HEAD><TITLE>Fragmentation</TITLE></HEAD><BODY>"); // 入力部 | |
72 | + out.println("<FONT SIZE=+2>Fragmentation</FONT><BR><BR>"); | |
73 | + out.println("<FORM>"); | |
74 | + | |
75 | + try | |
76 | + { | |
77 | + String normal = gc.toNormalFormat(); // ノーマル形式を取得し, | |
78 | + if (normal.length() <= 60) // 入力部のサイズを調節する. | |
79 | + out.println("Structure: <INPUT TYPE=text NAME=struct VALUE='" | |
80 | + + normal + "' SIZE=90><BR>"); | |
81 | + else | |
82 | + out.println("Structure: <INPUT TYPE=text NAME=struct VALUE='" | |
83 | + + normal + "' SIZE=" + (normal.length() + 30) + "><BR>"); | |
84 | + } | |
85 | + catch (Exception e) // 3分岐以上の場合,Linucs形式で表示 | |
86 | + { | |
87 | + String linucs = gc.toString(); // Linucs形式を取得し, | |
88 | + if (linucs.length() <= 60) // 入力部のサイズを調節する. | |
89 | + out.println("Structure: <INPUT TYPE=text NAME=struct VALUE='" | |
90 | + + linucs + "' SIZE=80><BR>"); | |
91 | + else | |
92 | + out.println("Structure: <INPUT TYPE=text NAME=struct VALUE='" | |
93 | + + linucs + "' SIZE=" + (linucs.length()+20) + "><BR>"); | |
94 | + } | |
95 | + | |
96 | + out.println("Adduct ion: <SELECT NAME=adduct>"+adduct); // 前回の内容を初期値とする. | |
97 | + if (adduct.equals(MassCalc.Na_ION)) | |
98 | + out.println("<OPTION VALUE="+MassCalc.Na_ION+" SELECTED>Na+"); | |
99 | + else | |
100 | + out.println("<OPTION VALUE="+MassCalc.Na_ION+">Na+"); | |
101 | + if (adduct.equals(MassCalc.H_ION)) | |
102 | + out.println("<OPTION VALUE="+MassCalc.H_ION+" SELECTED>H+"); | |
103 | + else | |
104 | + out.println("<OPTION VALUE="+MassCalc.H_ION+">H+"); | |
105 | + if (adduct.equals(MassCalc.Li_ION)) | |
106 | + out.println("<OPTION VALUE="+MassCalc.Li_ION+" SELECTED>Li+"); | |
107 | + else | |
108 | + out.println("<OPTION VALUE="+MassCalc.Li_ION+">Li+"); | |
109 | + if (adduct.equals(MassCalc.K_ION)) | |
110 | + out.println("<OPTION VALUE="+MassCalc.K_ION+" SELECTED>K+"); | |
111 | + else | |
112 | + out.println("<OPTION VALUE="+MassCalc.K_ION+">K+"); | |
113 | + if (adduct.equals(MassCalc.H_NION)) | |
114 | + out.println("<OPTION VALUE="+MassCalc.H_NION+" SELECTED>H-"); | |
115 | + else | |
116 | + out.println("<OPTION VALUE="+MassCalc.H_NION+">H-"); | |
117 | + if (adduct.equals("")) | |
118 | + out.println("<OPTION VALUE='' SELECTED>no adduct"); | |
119 | + else | |
120 | + out.println("<OPTION VALUE=''>No adduct"); | |
121 | + out.println("</SELECT><BR>"); | |
122 | + out.println("Mass mode: <SELECT NAME=monoavg>"); | |
123 | + if (monoavg) | |
124 | + { | |
125 | + out.println("<OPTION VALUE=mono SELECTED>Monoisotopic"); | |
126 | + out.println("<OPTION VALUE=avg>Average"); | |
127 | + } | |
128 | + else | |
129 | + { | |
130 | + out.println("<OPTION VALUE=mono>Monoisotopic"); | |
131 | + out.println("<OPTION VALUE=avg SELECTED>Average"); | |
132 | + } | |
133 | + out.println("</SELECT><BR>"); | |
134 | + out.println("<INPUT TYPE=submit>"); | |
135 | + out.println("</FORM><BR>"); | |
136 | + | |
137 | + out.println("<B>Result</B><BR>"); // 表示部 | |
138 | + out.println("LINUCS: " + gc + "<BR>"); | |
139 | + try | |
140 | + { | |
141 | + out.println("NORMAL: " + gc.toNormalFormat() + "<BR>"); | |
142 | + } | |
143 | + catch (Exception e) | |
144 | + { | |
145 | + out.println("NORMAL: " + e + "<BR>"); // 3分岐以上の場合 | |
146 | + } | |
147 | + | |
148 | + if (adduct.equals(MassCalc.Na_ION)) | |
149 | + out.println("Adduct ion: Na+<BR>"); | |
150 | + else if (adduct.equals(MassCalc.H_ION)) | |
151 | + out.println("Adduct ion: H+<BR>"); | |
152 | + else if (adduct.equals(MassCalc.Li_ION)) | |
153 | + out.println("Adduct ion: Li+<BR>"); | |
154 | + else if (adduct.equals(MassCalc.K_ION)) | |
155 | + out.println("Adduct ion: K+<BR>"); | |
156 | + else if (adduct.equals(MassCalc.H_NION)) | |
157 | + out.println("Adduct ion: H-<BR>"); | |
158 | + else if (adduct.equals("")) | |
159 | + out.println("Adduct ion: No adduct<BR>"); | |
160 | + else | |
161 | + out.println("Adduct ion: "+adduct+"<BR>"); | |
162 | + if (monoavg) | |
163 | + out.println("Mass mode: Monoisotopic<BR><BR>"); | |
164 | + else | |
165 | + out.println("Mass mode: Average<BR><BR>"); | |
166 | + out.println("<B>Fragment table</B><BR><TABLE border=1><TR>"); | |
167 | + out.println("<TH>Composition</TH>"); | |
168 | + out.println("<TH><I>m/z</I></TH>"); | |
169 | + out.println("</TR>"); | |
170 | + | |
171 | + Fragmentation fg = new Fragmentation(); | |
172 | + Glycan temp = new Glycan(gc.toString()); // Hexへ変換するためにインスタンスを生成 | |
173 | + temp.toHexose(); // Glc->Hexへ変換します. | |
174 | + fg.setGlycan(temp); | |
175 | + | |
176 | + int dehydrate = 0; // 脱水糖を含んだ組成の数 | |
177 | + int oligo = 0; // フリーの糖鎖の組成の数 | |
178 | + int ceramide = 0; // セラミドを含んだ組成の数 | |
179 | + | |
180 | + for (Composition cp : fg.getComposition()) | |
181 | + { | |
182 | + if (cp.hasCeramide()) | |
183 | + { | |
184 | + out.print("<TR bgcolor=#B0C4DE>"); // セラミドを含んだ組成は,背景色を青にする. | |
185 | + ceramide++; | |
186 | + } | |
187 | + else if (cp.contains("-h2o")) | |
188 | + { | |
189 | + out.print("<TR bgcolor=#DCDCDC>"); // 脱水糖を含んだ組成は,背景色を灰色にする. | |
190 | + dehydrate++; | |
191 | + } | |
192 | + else | |
193 | + { | |
194 | + out.print("<TR bgcolor=#98FB98>"); // フリーの糖鎖の組成は,背景色を緑にする. | |
195 | + oligo++; | |
196 | + } | |
197 | + out.print("<TD>" + cp + "</TD>"); | |
198 | + out.print(String.format("<TD align=right>%.4f</TD>", cp.getMass(monoavg, adduct))); | |
199 | + out.println("</TR>"); | |
200 | + } | |
201 | + out.println("</TABLE><BR>"); | |
202 | + | |
203 | + out.println("<B>Number of fragment</B><BR><TABLE border=1><TR>"); // フラグメントの内訳 | |
204 | + out.print("<TH bgcolor=#DCDCDC>Dehydrated<BR>oligosaccharide</TH>"); | |
205 | + out.print("<TH bgcolor=#98FB98>Oligosaccharide</TH>"); | |
206 | + if (ceramide != 0) // 糖脂質の組成数が0の場合は,非表示 | |
207 | + out.print("<TH bgcolor=#B0C4DE>Glycosphingolipid</TH>"); | |
208 | + out.print("<TH>Total</TH>"); | |
209 | + out.println("</TR>"); | |
210 | + out.print("<TR>"); | |
211 | + out.print("<TD bgcolor=#DCDCDC align=center>" + dehydrate + "</TD>"); // 脱水糖を含む組成は,背景色を灰色 | |
212 | + out.print("<TD bgcolor=#98FB98 align=center>" + oligo + "</TD>"); // フリーの糖鎖の組成は,背景色を緑 | |
213 | + if (ceramide != 0) // 糖脂質の組成数が0の場合は,非表示 | |
214 | + out.print("<TD bgcolor=#B0C4DE align=center>" + ceramide + "</TD>"); // 糖脂質の組成は,背景色を青 | |
215 | + out.print("<TD align=center>" + (dehydrate + oligo + ceramide) + "</TD>"); // 合計 | |
216 | + out.println("</TR>"); | |
217 | + out.println("</TABLE><BR><BR>"); | |
218 | + } | |
219 | + catch (Exception e) | |
220 | + { | |
221 | + out.println("ERROR:"+e.getMessage()); | |
222 | + } | |
223 | + | |
224 | + out.println("<Div Align=right><FONT color=gray>(c) Kazuhito Yokoi</FONT></Div><BR>"); | |
225 | + out.println("<A HREF=../>Back</A>"); // トップページへのリンク | |
226 | + | |
227 | + out.println("<script type=\"text/javascript\">"); | |
228 | + out.println("var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");"); | |
229 | + out.println("document.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));"); | |
230 | + out.println("</script>"); | |
231 | + out.println("<script type=\"text/javascript\">"); | |
232 | + out.println("try {"); | |
233 | + out.println("var pageTracker = _gat._getTracker(\"UA-1643740-14\");"); | |
234 | + out.println("pageTracker._trackPageview();"); | |
235 | + out.println("} catch(err) {}</script>"); | |
236 | + out.println("</BODY></HTML>"); // 終了タグ | |
237 | + } | |
238 | +} |
@@ -0,0 +1,403 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.io.*; | |
3 | +import java.util.*; | |
4 | +import java.awt.*; | |
5 | +import java.awt.event.*; | |
6 | +import java.util.regex.*; | |
7 | +import org.jfree.chart.*; | |
8 | +import org.jfree.data.xy.*; | |
9 | +import org.jfree.chart.plot.*; | |
10 | +import org.jfree.ui.*; | |
11 | +import org.jfree.chart.entity.*; | |
12 | +import javax.swing.*; | |
13 | +import javax.swing.table.*; | |
14 | + | |
15 | +/** | |
16 | + * フラグメントイオンにおける理論上の<I>m/z</I> と実測スペクトルを重ね合わせするクラスです. | |
17 | + * @author 横井一仁 | |
18 | + * @version 20090102 | |
19 | + */ | |
20 | +public class FragmentationGUI implements ActionListener, ItemListener, WindowListener | |
21 | +{ | |
22 | + XYSeries xs; // 実測値のスペクトルを格納 | |
23 | + XYSeriesCollection xc; | |
24 | + JFreeChart jc; | |
25 | + JTextField inpit_tf; // 糖鎖構造を格納 | |
26 | + JComboBox ion_ch; // 付加イオンを格納 | |
27 | + JComboBox ma_ch; // MONO/AVGを格納 | |
28 | + JButton theory_bt; // Calculateボタン | |
29 | + JButton actual_bt; // 実測値読み込みボタン(Plot dataボタン) | |
30 | + | |
31 | + String[] title = {"m/z", "Composition"}; // 断片化後の組成の出力部 | |
32 | + DefaultTableModel tm = new DefaultTableModel(title, 0); | |
33 | + JTable theory_tb = new JTable(tm); // PSD壊裂データを格納 | |
34 | + | |
35 | + TextArea actual_ta; // 実測値を格納 | |
36 | + | |
37 | + FragmentationGUI() // フレームの表示 | |
38 | + { | |
39 | + byte[] bytes = {40, 99, 41, 32, 75, 97, 122, 117, 104, 105, 116, 111, 32, 89, 111, 107, 111, 105}; | |
40 | + | |
41 | + JFrame fr = new JFrame("Fragment Matcher"); | |
42 | + xc = new XYSeriesCollection(); // グラフ部の設定 | |
43 | + jc = ChartFactory.createXYBarChart("", "m/z", false, "Intensity (%)", xc, PlotOrientation.VERTICAL, | |
44 | + false, false, false); | |
45 | + // 糖鎖構造入力部 | |
46 | + inpit_tf = new JTextField("dc34:1-Glc-Man-GlcNAc-GalNAc-GalNAc-Gal-GlcNAc", 40); | |
47 | + inpit_tf.addActionListener(this); | |
48 | + JPanel input_pn = new JPanel(); | |
49 | + input_pn.setLayout(new FlowLayout()); | |
50 | + input_pn.add(new JLabel("Structure:")); | |
51 | + input_pn.add(inpit_tf); | |
52 | + | |
53 | + // 付加イオン選択部 | |
54 | + ion_ch = new JComboBox(new String[] {"Na+", | |
55 | + "H+", | |
56 | + "Li+", | |
57 | + "K+", | |
58 | + "H-", | |
59 | + "No adduct"}); | |
60 | + ion_ch.addItemListener(this); | |
61 | + | |
62 | + JPanel ion_pn = new JPanel(); | |
63 | + ion_pn.setLayout(new FlowLayout()); | |
64 | + ion_pn.add(new JLabel("Adduct ion:")); | |
65 | + ion_pn.add(ion_ch); | |
66 | + | |
67 | + // MONO/AVG選択部 | |
68 | + ma_ch = new JComboBox(new String[] {"Monoisotopic", "Average"}); | |
69 | + ma_ch.addItemListener(this); | |
70 | + JPanel ma_pn = new JPanel(); | |
71 | + ma_pn.setLayout(new FlowLayout()); | |
72 | + ma_pn.add(new JLabel("Mass mode: ")); | |
73 | + ma_pn.add(ma_ch); | |
74 | + | |
75 | + // フラグメント計算ボタン | |
76 | + theory_bt = new JButton("Calculate"); | |
77 | + theory_bt.addActionListener(this); | |
78 | + | |
79 | + // 条件設定部 | |
80 | + JPanel condi_pn = new JPanel(); | |
81 | + condi_pn.setLayout(new FlowLayout()); | |
82 | + condi_pn.add(input_pn); | |
83 | + condi_pn.add(ion_pn); | |
84 | + condi_pn.add(ma_pn); | |
85 | + condi_pn.add(theory_bt); | |
86 | + | |
87 | + // 理論ピーク出力部 | |
88 | + JPanel theory_pn_north = new JPanel(); | |
89 | + theory_pn_north.setLayout(new BorderLayout()); | |
90 | + theory_pn_north.add(new JLabel("Calculated fragments:"), BorderLayout.WEST); | |
91 | + | |
92 | + JPanel theory_pn = new JPanel(); | |
93 | + theory_pn.setLayout(new BorderLayout()); | |
94 | + theory_pn.add(theory_pn_north, BorderLayout.NORTH); | |
95 | + resetTableColumnSize(); // テーブルのカラム幅を調節 | |
96 | + | |
97 | + // 組成に従ってセルに色を付ける.(セラミド付き…青,糖鎖のみ…緑,脱水糖…灰色) | |
98 | + TableColumn tc = theory_tb.getColumnModel().getColumn(0); | |
99 | + tc.setCellRenderer(new DefaultTableCellRenderer() | |
100 | + { | |
101 | + | |
102 | + }); | |
103 | + | |
104 | + JScrollPane theory_sp = new JScrollPane(theory_tb); // JTableへスクロールバーをつける. | |
105 | + theory_sp.addMouseListener(new MouseListener() // 表を右クリックすると印刷する. | |
106 | + { | |
107 | + public void mouseExited(MouseEvent me){} | |
108 | + public void mouseEntered(MouseEvent me){} | |
109 | + public void mousePressed(MouseEvent me){} | |
110 | + public void mouseReleased(MouseEvent me){} | |
111 | + public void mouseClicked(MouseEvent me) | |
112 | + { | |
113 | + if (me.getButton() == MouseEvent.BUTTON3) // 右クリック | |
114 | + { | |
115 | + try | |
116 | + { | |
117 | + theory_tb.print(); // 印刷ダイアログを表示 | |
118 | + } | |
119 | + catch (Exception e) | |
120 | + { | |
121 | + System.out.println("Cannot print: " + e); | |
122 | + } | |
123 | + } | |
124 | + } | |
125 | + }); | |
126 | + theory_pn.add(theory_sp, BorderLayout.CENTER); | |
127 | + | |
128 | + | |
129 | + actual_bt = new JButton("Plot data"); // 実測ピーク入力部 | |
130 | + actual_bt.addActionListener(this); | |
131 | + | |
132 | + try // 実測データの読み込み | |
133 | + { | |
134 | + File fi = new File("L7.dat"); | |
135 | + FileReader rd = new FileReader(fi); | |
136 | + BufferedReader br = new BufferedReader(rd); | |
137 | + String line; | |
138 | + StringBuilder sb = new StringBuilder(); | |
139 | + while ((line = br.readLine()) != null) | |
140 | + sb.append(line + "\n"); | |
141 | + actual_ta = new TextArea(sb.toString()); | |
142 | + } | |
143 | + catch (Exception e) | |
144 | + { | |
145 | + System.err.println(e); | |
146 | + actual_ta = new TextArea("Index Centroid Mass Lower Bound Upper Bound Charge (z) Height Relative Intensity Area\n" | |
147 | + + "1 226.086656 214.70 239.20 0 114 10.96 34568.98\n" | |
148 | + + "2 387.921207 386.08 389.29 0 213 20.48 14047.02\n" | |
149 | + + "3 405.818468 404.62 406.39 0 498 47.84 15389.71\n" | |
150 | + + "4 428.798146 427.14 429.52 0 721 69.26 36846.05\n" | |
151 | + + "5 429.659166 429.52 430.33 0 227 21.78 4598.69\n" | |
152 | + + "6 591.182879 589.05 594.66 0 168 16.15 10405.74\n" | |
153 | + + "7 631.871619 629.39 632.56 0 172 16.57 6567.95\n" | |
154 | + + "8 667.634938 645.90 695.00 0 35 3.40 3256.74\n" | |
155 | + + "9 723.822798 697.10 752.20 0 125 12.03 13931.21\n" | |
156 | + + "10 794.294571 791.94 794.56 0 376 36.11 9785.54\n" | |
157 | + + "11 866.510011 852.50 875.70 0 31 2.96 2429.69\n" | |
158 | + + "12 888.507352 866.70 917.90 0 109 10.45 13012.58\n" | |
159 | + + "13 953.956244 926.00 971.00 0 98 9.42 8019.90\n" | |
160 | + + "14 996.455212 993.22 997.08 1 908 87.21 25463.38\n" | |
161 | + + "15 1087.733154 1086.34 1088.26 0 161 15.49 3065.23\n" | |
162 | + + "16 1159.078169 1157.70 1159.41 0 556 53.40 8082.03\n" | |
163 | + + "17 1161.051801 1160.86 1163.34 0 224 21.56 4189.52\n" | |
164 | + + "18 1177.134560 1167.00 1193.70 0 39 3.71 3051.84\n" | |
165 | + + "19 1236.261198 1214.10 1261.10 0 35 3.37 3128.91\n" | |
166 | + + "20 1290.025315 1288.32 1290.50 0 294 28.26 4952.25\n" | |
167 | + + "21 1323.832952 1314.20 1337.40 0 63 6.03 3641.91\n" | |
168 | + + "22 1333.465729 1308.20 1371.40 0 126 12.12 14288.28\n" | |
169 | + + "23 1473.616981 1457.30 1485.90 0 46 4.38 4034.31\n" | |
170 | + + "24 1493.937713 1492.41 1494.44 0 422 40.60 5174.78\n" | |
171 | + + "25 1513.374222 1500.30 1533.00 0 75 7.21 9087.53\n" | |
172 | + + "26 1859.320454 1858.70 1859.85 1 1041 100.00 6482.10\n" | |
173 | + + "27 1877.614229 1870.20 1893.40 0 153 14.70 6686.62"); | |
174 | + } | |
175 | + | |
176 | + JPanel actual_pn = new JPanel(); | |
177 | + actual_pn.setLayout(new BorderLayout()); | |
178 | + actual_pn.add(new JLabel("Measured data:"), BorderLayout.WEST); | |
179 | + actual_pn.add(actual_bt, BorderLayout.EAST); | |
180 | + actual_pn.add(actual_ta, BorderLayout.SOUTH); | |
181 | + | |
182 | + | |
183 | + JPanel south_pn = new JPanel(); // SOUTH部の設定 | |
184 | + south_pn.setLayout(new BorderLayout()); | |
185 | + south_pn.add(new ChartPanel(jc), BorderLayout.CENTER); | |
186 | + south_pn.add(actual_pn, BorderLayout.SOUTH); | |
187 | + | |
188 | + fr.add(condi_pn, BorderLayout.NORTH); | |
189 | + fr.add(theory_pn, BorderLayout.WEST); | |
190 | + fr.add(south_pn, BorderLayout.CENTER); | |
191 | + JLabel author = new JLabel(new String(bytes)); | |
192 | + author.setForeground(Color.gray); | |
193 | + fr.add(author, BorderLayout.SOUTH); | |
194 | + fr.addWindowListener(this); | |
195 | + fr.pack(); | |
196 | + //jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ウインドウが閉じられた時に終了 | |
197 | + | |
198 | + try // Swingのデザインから,Windowsのデザインへ変更する(Linuxの場合は例外が発生し,Swing表示となる) | |
199 | + { | |
200 | + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); // 外観を設定 | |
201 | + SwingUtilities.updateComponentTreeUI(fr); // 外観変更 | |
202 | + } | |
203 | + catch (Exception e) | |
204 | + { | |
205 | + System.err.println("Cannot use WindowsLookAndFeel: " + e); | |
206 | + } | |
207 | + | |
208 | + int width = fr.getWidth() / 3; // 表のサイズを横幅の1/3のサイズとする. | |
209 | + theory_pn.setPreferredSize(new Dimension(width, width)); | |
210 | + | |
211 | + fr.setVisible(true); | |
212 | + } | |
213 | + | |
214 | + public void actionPerformed(ActionEvent ae) | |
215 | + { | |
216 | + if (ae.getSource() == actual_bt) // "Plot peaks"ボタンがクリックされた時 | |
217 | + { | |
218 | + xc.removeAllSeries(); // 前回のXYSeriesを削除 | |
219 | + xs = new XYSeries(""); | |
220 | + | |
221 | + double temp = 0.0; | |
222 | + BufferedReader br = new BufferedReader(new StringReader(actual_ta.getText())); | |
223 | + boolean flag = true; // BarChartかLineChartかを指定する.(trueがBarChart) | |
224 | + try | |
225 | + { | |
226 | + String str; | |
227 | + while ((str = br.readLine()) != null) | |
228 | + { | |
229 | + Pattern pt1 = Pattern.compile("^(\\d+)[\\t|\\s]+(\\d+\\.\\d+)[\\t|\\s]+" | |
230 | + + "(\\d+\\.\\d+)[\\t|\\s]+(\\d+\\.\\d+)[\\t|\\s]+" | |
231 | + + "(\\d+)[\\t|\\s]+(\\d+)[\\t|\\s]+" | |
232 | + + "(\\d+\\.\\d+)[\\t|\\s]+(\\d+\\.\\d+).*"); | |
233 | + Matcher mt1 = pt1.matcher(str); | |
234 | + | |
235 | + if (mt1.matches()) // 先頭の条件を読み飛ばし, | |
236 | + { // 数字,'.',タブで構成されている行を読み込む. | |
237 | + xs.add(Double.parseDouble(mt1.group(2)), Double.parseDouble(mt1.group(7))); | |
238 | + flag = true; // BarChartで表示 | |
239 | + } | |
240 | + | |
241 | + Pattern pt2 = Pattern.compile("^(\\d+\\.\\d+)[\\t|\\s]+(\\d+\\.\\d+).*"); | |
242 | + Matcher mt2 = pt2.matcher(str); | |
243 | + | |
244 | + if (mt2.matches()) // 先頭の条件を読み飛ばし, | |
245 | + { // 数字,'.',タブで構成されている行を読み込む. | |
246 | + xs.add(Double.parseDouble(mt2.group(1)), Double.parseDouble(mt2.group(2))); | |
247 | + flag = false; // LineChartで表示 | |
248 | + } | |
249 | + } | |
250 | + } | |
251 | + catch (Exception e) | |
252 | + { | |
253 | + System.err.println("markPeaks error1 : " + e); | |
254 | + e.printStackTrace(); | |
255 | + } | |
256 | + | |
257 | + actual_bt.setText("Plot data"); // ボタンを元に戻す | |
258 | + xc.addSeries(xs); | |
259 | + } | |
260 | + | |
261 | + // "Mark peaks"ボタンがクリックされた時 | |
262 | + if (ae.getSource() == theory_bt || ae.getSource() == inpit_tf) | |
263 | + try | |
264 | + { | |
265 | + markPeaks(); | |
266 | + } | |
267 | + catch (Exception e) | |
268 | + { | |
269 | + System.err.println("markPeaks error2 : " + e); | |
270 | + e.printStackTrace(); | |
271 | + } | |
272 | + } | |
273 | + | |
274 | + public void itemStateChanged(ItemEvent ie) | |
275 | + { | |
276 | + if (ie.getSource() == ion_ch || ie.getSource() == ma_ch) | |
277 | + try | |
278 | + { | |
279 | + markPeaks(); | |
280 | + } | |
281 | + catch (Exception e) | |
282 | + { | |
283 | + System.err.println("markPeaks error3 : " + e); | |
284 | + e.printStackTrace(); | |
285 | + } | |
286 | + } | |
287 | + | |
288 | + void markPeaks() throws Exception | |
289 | + { | |
290 | + XYPlot xp = jc.getXYPlot(); | |
291 | + xp.clearDomainMarkers(); // 既に表示されているマーカーを削除 | |
292 | + | |
293 | + DefaultTableModel tm = (DefaultTableModel)theory_tb.getModel(); // テーブルモデルを取得し, | |
294 | + tm.setRowCount(0); // 表の内容を削除する. | |
295 | + | |
296 | + String adduct; | |
297 | + if (ion_ch.getSelectedItem().equals("Na+")) | |
298 | + adduct = MassCalc.Na_ION; | |
299 | + else if (ion_ch.getSelectedItem().equals("H+")) | |
300 | + adduct = MassCalc.H_ION; | |
301 | + else if (ion_ch.getSelectedItem().equals("Li+")) | |
302 | + adduct = MassCalc.Li_ION; | |
303 | + else if (ion_ch.getSelectedItem().equals("K+")) | |
304 | + adduct = MassCalc.K_ION; | |
305 | + else if (ion_ch.getSelectedItem().equals("H-")) | |
306 | + adduct = MassCalc.H_NION; | |
307 | + else if (ion_ch.getSelectedItem().equals("No adduct")) | |
308 | + adduct = ""; | |
309 | + else | |
310 | + adduct = ""; | |
311 | + | |
312 | + boolean monoavg; | |
313 | + if (ma_ch.getSelectedItem().equals("Monoisotopic")) | |
314 | + monoavg = true; | |
315 | + else | |
316 | + monoavg = false; | |
317 | + | |
318 | + Glycan gc = null; | |
319 | + try | |
320 | + { | |
321 | + gc = new Glycan(inpit_tf.getText()); | |
322 | + } | |
323 | + catch (Exception e1) | |
324 | + { | |
325 | + try | |
326 | + { | |
327 | + GlycanTools gi = new GlycanTools(); | |
328 | + gc = gi.readNormalFormat(inpit_tf.getText()); | |
329 | + } | |
330 | + catch (Exception e2) | |
331 | + { | |
332 | + System.err.println("Input format error: " + e1 + e2); | |
333 | + } | |
334 | + } | |
335 | + | |
336 | + try // 入力した糖鎖構造文字列を正しく修正する.(hex,hexnacなどをHex,HexNAcに修正) | |
337 | + { | |
338 | + inpit_tf.setText(gc.toNormalFormat()); // Linucs形式でない表示方法が可能であるかを試してみる. | |
339 | + } | |
340 | + catch (Exception e) | |
341 | + { | |
342 | + inpit_tf.setText(gc.toString()); // 失敗した場合は,Linucs形式を用いて表示する. | |
343 | + } | |
344 | + | |
345 | + gc.toHexose(); // Glc->Hexへ変換します. | |
346 | + Fragmentation fg = new Fragmentation(); | |
347 | + fg.setGlycan(gc); | |
348 | + for (Composition cp : fg.getComposition()) | |
349 | + { | |
350 | + System.out.println(cp); | |
351 | + String[] table = new String[2]; // カラムの追加時は,配列の大きさに注意する. | |
352 | + table[0] = String.format("%.4f", cp.getMass(monoavg, adduct)); | |
353 | + table[1] = cp.toString(); | |
354 | + tm.addRow(table); // テーブルに追加 | |
355 | + | |
356 | + ValueMarker mk1 = new ValueMarker(cp.getMass(monoavg, adduct) - 1); | |
357 | + ValueMarker mk2 = new ValueMarker(cp.getMass(monoavg, adduct) + 1); | |
358 | + if (cp.hasCeramide()) | |
359 | + { | |
360 | + mk1.setPaint(Color.blue); | |
361 | + mk2.setPaint(Color.blue); | |
362 | + } | |
363 | + else if(!cp.contains("-h2o")) | |
364 | + { | |
365 | + mk1.setPaint(Color.green); | |
366 | + mk2.setPaint(Color.green); | |
367 | + } | |
368 | + xp.addDomainMarker(mk1); // マーカーを追加 | |
369 | + xp.addDomainMarker(mk2); | |
370 | + } | |
371 | + | |
372 | + resetTableColumnSize(); // テーブルのカラム幅を調節 | |
373 | + } | |
374 | + | |
375 | + /* | |
376 | + * テーブルのカラム幅を調節します. | |
377 | + */ | |
378 | + private void resetTableColumnSize() | |
379 | + { | |
380 | + DefaultTableCellRenderer tr = new DefaultTableCellRenderer(); // テーブルのカラム幅を調整する | |
381 | + tr.setHorizontalAlignment(SwingConstants.RIGHT); | |
382 | + TableColumn tc0 = theory_tb.getColumnModel().getColumn(0); // m/zのカラム(0番目)のサイズを固定 | |
383 | + tc0.setMinWidth(70); | |
384 | + tc0.setMaxWidth(70); | |
385 | + tc0.setCellRenderer(tr); // カラムを右寄せする | |
386 | + } | |
387 | + | |
388 | + public void windowOpened(WindowEvent evt){} | |
389 | + public void windowClosing(WindowEvent evt) | |
390 | + { | |
391 | + System.exit(0); | |
392 | + } | |
393 | + public void windowClosed(WindowEvent evt){} | |
394 | + public void windowIconified(WindowEvent evt){} | |
395 | + public void windowDeiconified(WindowEvent evt){} | |
396 | + public void windowActivated(WindowEvent evt){} | |
397 | + public void windowDeactivated(WindowEvent evt) {} | |
398 | + | |
399 | + public static void main(String[] args) | |
400 | + { | |
401 | + new FragmentationGUI(); | |
402 | + } | |
403 | +} |
@@ -0,0 +1,346 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | +import java.io.*; | |
5 | +import javax.servlet.*; | |
6 | +import javax.servlet.http.*; | |
7 | + | |
8 | +/** | |
9 | + * 2つの糖鎖構造を比較し,特徴的なフラグメントイオンを探し出すServletクラスです. | |
10 | + * @author 横井一仁 | |
11 | + * @version 20090102 | |
12 | + */ | |
13 | +public class FragmentComparing extends HttpServlet | |
14 | +{ | |
15 | + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException | |
16 | + { | |
17 | + response.setContentType("text/html"); | |
18 | + PrintWriter out = response.getWriter(); | |
19 | + | |
20 | + try | |
21 | + { | |
22 | + Glycan gc1; // 開裂させたい構造 | |
23 | + Glycan gc2; // 開裂させたい構造 | |
24 | + String adduct = ""; // 付加イオン | |
25 | + boolean monoavg = true; // Monoisotopic(ture), Average(false) | |
26 | + | |
27 | + try | |
28 | + { | |
29 | + gc1 = new Glycan(request.getParameter("struct1")); // 何も指定されない場合,例外 | |
30 | + } | |
31 | + catch (Exception e1) | |
32 | + { | |
33 | + try | |
34 | + { | |
35 | + GlycanTools gi = new GlycanTools(); // Linucs形式以外の形式で試してみる. | |
36 | + gc1 = gi.readNormalFormat(request.getParameter("struct1")); | |
37 | + } | |
38 | + catch (Exception e2) | |
39 | + { | |
40 | + GlycanTools gi = new GlycanTools(); // 全てにおいて失敗した場合,L5を表示する. | |
41 | + gc1 = gi.readNormalFormat("dc36:1-hex3me-hex3me-hexnac3me-hexnac3me-hexnac4me"); | |
42 | + } | |
43 | + } | |
44 | + | |
45 | + try | |
46 | + { | |
47 | + gc2 = new Glycan(request.getParameter("struct2")); // 何も指定されない場合,例外 | |
48 | + } | |
49 | + catch (Exception e1) | |
50 | + { | |
51 | + try | |
52 | + { | |
53 | + GlycanTools gi = new GlycanTools(); // Linucs形式以外の形式で試してみる. | |
54 | + gc2 = gi.readNormalFormat(request.getParameter("struct2")); | |
55 | + } | |
56 | + catch (Exception e2) | |
57 | + { // 全てにおいて失敗した場合, | |
58 | + GlycanTools gi = new GlycanTools(); // L5と同じフラグメントを持つ構造を表示する. | |
59 | + gc2 = gi.readNormalFormat("dc36:1-hex3me-hex3me-hexnac2me(-hexnac4me)-hexnac4me"); | |
60 | + } | |
61 | + } | |
62 | + | |
63 | + try | |
64 | + { | |
65 | + adduct = request.getParameter("adduct"); | |
66 | + | |
67 | + if (adduct == null) // 何も指定されなかった場合, | |
68 | + adduct = MassCalc.Na_ION; // 左のイオンを初期付加イオンとする. | |
69 | + } | |
70 | + catch (Exception e) | |
71 | + { | |
72 | + adduct = MassCalc.Na_ION; // 左のイオンを初期付加イオンとする. | |
73 | + } | |
74 | + | |
75 | + try | |
76 | + { | |
77 | + String temp = request.getParameter("monoavg"); | |
78 | + if (temp.equals("mono")) | |
79 | + monoavg = true; | |
80 | + else if (temp.equals("avg")) | |
81 | + monoavg = false; | |
82 | + else | |
83 | + monoavg = true; // その他の場合Monoisotopicとする. | |
84 | + } | |
85 | + catch (Exception e) | |
86 | + { | |
87 | + monoavg = true; // その他の場合Monoisotopicとする. | |
88 | + } | |
89 | + | |
90 | + out.println("<HTML><HEAD><TITLE>Fragment Comparing</TITLE></HEAD><BODY>"); // 入力部 | |
91 | + out.println("<FONT SIZE=+2>Fragment Comparing</FONT><BR><BR>"); | |
92 | + out.println("<FORM><BR>"); | |
93 | + | |
94 | + try | |
95 | + { | |
96 | + String normal = gc1.toNormalFormat(); // ノーマル形式を取得し, | |
97 | + if (normal.length() <= 60) // 入力部のサイズを調節する. | |
98 | + out.println("Structure1: <INPUT TYPE=text NAME=struct1 VALUE='" | |
99 | + + normal + "' SIZE=100><BR>"); | |
100 | + else | |
101 | + out.println("Structure1: <INPUT TYPE=text NAME=struct1 VALUE='" | |
102 | + + normal + "' SIZE=" + (normal.length() + 40) + "><BR>"); | |
103 | + } | |
104 | + catch (Exception e) // 3分岐以上の場合,Linucs形式で表示 | |
105 | + { | |
106 | + String linucs = gc1.toString(); // Linucs形式を取得し, | |
107 | + if (linucs.length() <= 60) // 入力部のサイズを調節する. | |
108 | + out.println("Structure1: <INPUT TYPE=text NAME=struct1 VALUE='" | |
109 | + + linucs + "' SIZE=100><BR>"); | |
110 | + else | |
111 | + out.println("Structure1: <INPUT TYPE=text NAME=struct1 VALUE='" | |
112 | + + linucs + "' SIZE=" + (linucs.length() + 40) + "><BR>"); | |
113 | + } | |
114 | + | |
115 | + try | |
116 | + { | |
117 | + String normal = gc2.toNormalFormat(); // ノーマル形式を取得し, | |
118 | + if (normal.length() <= 60) // 入力部のサイズを調節する. | |
119 | + out.println("Structure2: <INPUT TYPE=text NAME=struct2 VALUE='" | |
120 | + + normal + "' SIZE=100><BR>"); | |
121 | + else | |
122 | + out.println("Structure2: <INPUT TYPE=text NAME=struct2 VALUE='" | |
123 | + + normal + "' SIZE=" + (normal.length() + 40) + "><BR>"); | |
124 | + } | |
125 | + catch (Exception e) // 3分岐以上の場合,Linucs形式で表示 | |
126 | + { | |
127 | + String linucs = gc2.toString(); // Linucs形式を取得し, | |
128 | + if (linucs.length() <= 60) // 入力部のサイズを調節する. | |
129 | + out.println("Structure2: <INPUT TYPE=text NAME=struct2 VALUE='" | |
130 | + + linucs + "' SIZE=100><BR>"); | |
131 | + else | |
132 | + out.println("Structure2: <INPUT TYPE=text NAME=struct2 VALUE='" | |
133 | + + linucs + "' SIZE=" + (linucs.length() + 40) + "><BR>"); | |
134 | + } | |
135 | + | |
136 | + out.println("Adduct ion: <SELECT NAME=adduct>"+adduct); // 前回の内容を初期値とする. | |
137 | + if (adduct.equals(MassCalc.Na_ION)) | |
138 | + out.println("<OPTION VALUE="+MassCalc.Na_ION+" SELECTED>Na+"); | |
139 | + else | |
140 | + out.println("<OPTION VALUE="+MassCalc.Na_ION+">Na+"); | |
141 | + if (adduct.equals(MassCalc.H_ION)) | |
142 | + out.println("<OPTION VALUE="+MassCalc.H_ION+" SELECTED>H+"); | |
143 | + else | |
144 | + out.println("<OPTION VALUE="+MassCalc.H_ION+">H+"); | |
145 | + if (adduct.equals(MassCalc.Li_ION)) | |
146 | + out.println("<OPTION VALUE="+MassCalc.Li_ION+" SELECTED>Li+"); | |
147 | + else | |
148 | + out.println("<OPTION VALUE="+MassCalc.Li_ION+">Li+"); | |
149 | + if (adduct.equals(MassCalc.K_ION)) | |
150 | + out.println("<OPTION VALUE="+MassCalc.K_ION+" SELECTED>K+"); | |
151 | + else | |
152 | + out.println("<OPTION VALUE="+MassCalc.K_ION+">K+"); | |
153 | + if (adduct.equals(MassCalc.H_NION)) | |
154 | + out.println("<OPTION VALUE="+MassCalc.H_NION+" SELECTED>H-"); | |
155 | + else | |
156 | + out.println("<OPTION VALUE="+MassCalc.H_NION+">H-"); | |
157 | + if (adduct.equals("")) | |
158 | + out.println("<OPTION VALUE='' SELECTED>No adduct"); | |
159 | + else | |
160 | + out.println("<OPTION VALUE=''>No adduct"); | |
161 | + out.println("</SELECT><BR>"); | |
162 | + out.println("Mass mode: <SELECT NAME=monoavg>"); | |
163 | + if (monoavg) | |
164 | + { | |
165 | + out.println("<OPTION VALUE=mono SELECTED>Monoisotopic"); | |
166 | + out.println("<OPTION VALUE=avg>Average"); | |
167 | + } | |
168 | + else | |
169 | + { | |
170 | + out.println("<OPTION VALUE=mono>Monoisotopic"); | |
171 | + out.println("<OPTION VALUE=avg SELECTED>Average"); | |
172 | + } | |
173 | + out.println("</SELECT><BR>"); | |
174 | + out.println("<INPUT TYPE=submit>"); | |
175 | + out.println("</FORM><BR>"); | |
176 | + | |
177 | + out.println("<B>Result</B><BR>"); // 表示部 | |
178 | + try | |
179 | + { | |
180 | + out.println("Structure1: " + gc1.toNormalFormat() + "<BR>"); | |
181 | + } | |
182 | + catch (Exception e) | |
183 | + { | |
184 | + out.println("Structure1: " + e + "<BR>"); // 3分岐以上の場合 | |
185 | + } | |
186 | + try | |
187 | + { | |
188 | + out.println("Structure2: " + gc2.toNormalFormat() + "<BR>"); | |
189 | + } | |
190 | + catch (Exception e) | |
191 | + { | |
192 | + out.println("Structure2: " + e + "<BR>"); // 3分岐以上の場合 | |
193 | + } | |
194 | + | |
195 | + if (adduct.equals(MassCalc.Na_ION)) | |
196 | + out.println("Adduct ion: Na+<BR>"); | |
197 | + else if (adduct.equals(MassCalc.H_ION)) | |
198 | + out.println("Adduct ion: H+<BR>"); | |
199 | + else if (adduct.equals(MassCalc.Li_ION)) | |
200 | + out.println("Adduct ion: Li+<BR>"); | |
201 | + else if (adduct.equals(MassCalc.K_ION)) | |
202 | + out.println("Adduct ion: K+<BR>"); | |
203 | + else if (adduct.equals(MassCalc.H_NION)) | |
204 | + out.println("Adduct ion: H-<BR>"); | |
205 | + else if (adduct.equals("")) | |
206 | + out.println("Adduct ion: No adduct<BR>"); | |
207 | + else | |
208 | + out.println("Adduct ion: "+adduct+"<BR>"); | |
209 | + if (monoavg) | |
210 | + out.println("Mass mode: Monoisotopic<BR><BR>"); | |
211 | + else | |
212 | + out.println("Mass mode: Average<BR><BR>"); | |
213 | + out.println("<B>Fragment table</B><BR><TABLE border=1><TR>"); | |
214 | + out.println("<TH>Fragment composition<BR>(Structure1)</TH>"); | |
215 | + out.println("<TH><I>m/z</I></TH>"); | |
216 | + out.println("<TH>Fragment composition<BR>(Structure2)</TH>"); | |
217 | + out.println("<TH><I>m/z</I></TH>"); | |
218 | + out.println("</TR>"); | |
219 | + | |
220 | + Fragmentation fg1 = new Fragmentation(); | |
221 | + Glycan temp1 = new Glycan(gc1.toString()); // Hexへ変換するためにインスタンスを生成 | |
222 | + temp1.toHexose(); // Glc->Hexへ変換します. | |
223 | + fg1.setGlycan(temp1); | |
224 | + List<Composition> cps1 = fg1.getComposition(); | |
225 | + | |
226 | + Fragmentation fg2 = new Fragmentation(); | |
227 | + Glycan temp2 = new Glycan(gc2.toString()); // Hexへ変換するためにインスタンスを生成 | |
228 | + temp2.toHexose(); // Glc->Hexへ変換します. | |
229 | + fg2.setGlycan(temp2); | |
230 | + List<Composition> cps2 = fg2.getComposition(); | |
231 | + | |
232 | + Set<Double> temp_st = new HashSet<Double>(); // 2つの構造のフラグメントの質量を重複を除いて足し合わせる. | |
233 | + for (Composition cp : cps1) | |
234 | + temp_st.add(cp.getMass(monoavg, adduct)); | |
235 | + for (Composition cp : cps2) | |
236 | + temp_st.add(cp.getMass(monoavg, adduct)); | |
237 | + List<Double> temp_li = new ArrayList<Double>(temp_st); // ソートのため,リストに変換 | |
238 | + | |
239 | + Collections.sort(temp_li, new Comparator<Double>() // ソートを行う. | |
240 | + { | |
241 | + public int compare(Double db1, Double db2) | |
242 | + { | |
243 | + double sub = db1 - db2; | |
244 | + // compareメソッドの返り値がint型しか受け付けないので1024倍して精度を上げる. | |
245 | + return (int)(sub*1024); | |
246 | + } | |
247 | + }); | |
248 | + | |
249 | + for (Double db : temp_li) | |
250 | + { | |
251 | + List<Composition> output1 = new ArrayList<Composition>(); // 同じ質量の組成を格納する. | |
252 | + List<Composition> output2 = new ArrayList<Composition>(); | |
253 | + | |
254 | + for (Composition cp : cps1) // 質量が一致した組成をリストに格納する. | |
255 | + if (cp.getMass(monoavg, adduct) == db) | |
256 | + output1.add(cp); | |
257 | + | |
258 | + for (Composition cp : cps2) // 質量が一致した組成をリストに格納する. | |
259 | + if (cp.getMass(monoavg, adduct) == db) | |
260 | + output2.add(cp); | |
261 | + | |
262 | + if (!output1.isEmpty()) | |
263 | + { | |
264 | + if (!output2.isEmpty()) // 両方の構造が持つフラグメントであった場合 | |
265 | + { | |
266 | + out.print("<TR>"); | |
267 | + out.print("<TD>"); // セルの開始 | |
268 | + Iterator<Composition> it1 = output1.iterator(); | |
269 | + while (it1.hasNext()) | |
270 | + { | |
271 | + out.print(it1.next()); | |
272 | + if (it1.hasNext()) // 組成を複数持っている場合はセル内で改行 | |
273 | + out.print("<BR>"); | |
274 | + } | |
275 | + out.print("</TD>"); // セルの終わり | |
276 | + out.print(String.format("<TD align=right>%.4f</TD>", db)); | |
277 | + out.print("<TD>"); // セルの開始 | |
278 | + Iterator<Composition> it2 = output2.iterator(); | |
279 | + while (it2.hasNext()) | |
280 | + { | |
281 | + out.print(it2.next()); | |
282 | + if (it2.hasNext()) // 組成を複数持っている場合はセル内で改行 | |
283 | + out.print("<BR>"); | |
284 | + } | |
285 | + out.print("</TD>"); // セルの終わり | |
286 | + out.print(String.format("<TD align=right>%.4f</TD>", db)); | |
287 | + out.println("</TR>"); | |
288 | + } | |
289 | + else // cp1のみが持つフラグメントであった場合 | |
290 | + { | |
291 | + out.print("<TR>"); | |
292 | + out.print("<TD bgcolor=#FF99FF>"); // セルの開始 | |
293 | + Iterator<Composition> it1 = output1.iterator(); | |
294 | + while (it1.hasNext()) | |
295 | + { | |
296 | + out.print(it1.next()); | |
297 | + if (it1.hasNext()) // 組成を複数持っている場合はセル内で改行 | |
298 | + out.print("<BR>"); | |
299 | + } | |
300 | + out.print("</TD>"); // セルの終わり | |
301 | + out.print(String.format("<TD bgcolor=#FF99FF align=right>%.4f</TD>", db)); | |
302 | + out.print("<TD></TD><TD></TD>"); | |
303 | + out.println("</TR>"); | |
304 | + } | |
305 | + } | |
306 | + else if (!output2.isEmpty()) // cp2のみが持つフラグメントであった場合 | |
307 | + { | |
308 | + out.print("<TR>"); | |
309 | + out.print("<TD></TD><TD></TD>"); | |
310 | + out.print("<TD bgcolor=#99FFFF>"); // セルの開始 | |
311 | + Iterator<Composition> it2 = output2.iterator(); | |
312 | + while (it2.hasNext()) | |
313 | + { | |
314 | + out.print(it2.next()); | |
315 | + if (it2.hasNext()) // 組成を複数持っている場合はセル内で改行 | |
316 | + out.print("<BR>"); | |
317 | + } | |
318 | + out.print("</TD>"); // セルの終わり | |
319 | + out.print(String.format("<TD bgcolor=#99FFFF align=right>%.4f</TD>", db)); | |
320 | + out.println("</TR>"); | |
321 | + } | |
322 | + else | |
323 | + throw new Exception("else if error!"); | |
324 | + } | |
325 | + } | |
326 | + catch (Exception e) | |
327 | + { | |
328 | + out.println("ERROR:"+e.getMessage()); | |
329 | + } | |
330 | + out.println("</TABLE><BR>"); | |
331 | + | |
332 | + out.println("<Div Align=right><FONT color=gray>(c) Kazuhito Yokoi</FONT></Div><BR>"); | |
333 | + out.println("<A HREF=../>Back</A>"); // トップページへのリンク | |
334 | + | |
335 | + out.println("<script type=\"text/javascript\">"); | |
336 | + out.println("var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");"); | |
337 | + out.println("document.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));"); | |
338 | + out.println("</script>"); | |
339 | + out.println("<script type=\"text/javascript\">"); | |
340 | + out.println("try {"); | |
341 | + out.println("var pageTracker = _gat._getTracker(\"UA-1643740-14\");"); | |
342 | + out.println("pageTracker._trackPageview();"); | |
343 | + out.println("} catch(err) {}</script>"); | |
344 | + out.println("</BODY></HTML>"); // 終了タグ | |
345 | + } | |
346 | +} |
@@ -0,0 +1,605 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | + | |
5 | +/** | |
6 | + * 糖鎖の組成を扱うクラスです. | |
7 | + * @author 横井一仁 | |
8 | + * @version 20081218 | |
9 | + */ | |
10 | +public class Composition extends ArrayList<String> | |
11 | +{ | |
12 | + /** | |
13 | + * 要素がないクラスを作ります. | |
14 | + */ | |
15 | + public Composition() throws Exception | |
16 | + { | |
17 | + super(); | |
18 | + } | |
19 | + | |
20 | + /** | |
21 | + * Compositionクラスから新しいCompositionインスタンスを作成します. | |
22 | + * @param cp 新しく作成するCompositionクラス | |
23 | + */ | |
24 | + public Composition(Composition cp) throws Exception | |
25 | + { | |
26 | + super(cp); | |
27 | + } | |
28 | + | |
29 | + /** | |
30 | + * 文字列からCompositionインスタンスを作成します. | |
31 | + * @param str "Hex, dHex, th38:0"と組成を列挙した文字列 | |
32 | + */ | |
33 | + public Composition(String str) throws Exception | |
34 | + { | |
35 | + str = str.toLowerCase(); // 全て小文字に変換 | |
36 | + String[] strs = str.split("[^\\w:\\-*]"); // 単語構成文字と':','-','*'以外の文字列で分割 | |
37 | + | |
38 | + for (int i = 0; i < strs.length; i++) // cd->dc, hd->dh, ct->tc, ht->thへ入力ミスを訂正 | |
39 | + { | |
40 | + Pattern pt = Pattern.compile("^([ch])([dt])([0-9]+:[0-9])$"); // 長鎖塩基と脂肪酸の順番が逆 | |
41 | + Matcher mt = pt.matcher(strs[i]); | |
42 | + | |
43 | + if (mt.matches()) // セラミド組成の入力にミスが存在した場合, | |
44 | + strs[i] = mt.group(2) + mt.group(1) + mt.group(3); // "([dt])"+"([ch])"+"([0-9]+:[0-9])"とする. | |
45 | + } | |
46 | + | |
47 | + for (int i = 0; i < strs.length; i++) | |
48 | + if (!strs[i].equals("")) // 文字列が格納されていない場合は除く. | |
49 | + if (strs[i].matches("[\\w:\\-]+\\*\\d+")) // 掛け算が存在する場合 | |
50 | + { | |
51 | + String[] temps = strs[i].split("\\*"); | |
52 | + for (int j = 0; j < Integer.parseInt(temps[1]); j++) | |
53 | + this.add(temps[0]); // 個数分の組成を格納する. | |
54 | + } | |
55 | + else | |
56 | + this.add(strs[i]); // 掛け算が存在する場合,そのまま格納する. | |
57 | + } | |
58 | + | |
59 | + /** | |
60 | + * Glycanクラスから新しいCompositionインスタンスを作成します. | |
61 | + * @param gc Glycanクラス | |
62 | + */ | |
63 | + public Composition(Glycan gc) throws Exception | |
64 | + { | |
65 | + search(gc); // 深さ優先探索を行い,組成をListへ追加 | |
66 | + } | |
67 | + | |
68 | + /** | |
69 | + * 糖鎖の組成を追加します. | |
70 | + * @param gc 追加するGlycanクラス | |
71 | + */ | |
72 | + public void add(Glycan gc) throws Exception | |
73 | + { | |
74 | + search(gc); // 深さ優先探索を行い,組成をListへ追加 | |
75 | + } | |
76 | + | |
77 | + /** | |
78 | + * Glycanクラスに対し、深さ優先探索を行い組成を求めます. | |
79 | + * @param root Treeクラスのルート | |
80 | + * @param pointer Treeクラスのポインタ | |
81 | + */ | |
82 | + private void search(Glycan pointer) | |
83 | + { | |
84 | + super.add(pointer.getNode()); // 組成をListへ追加 | |
85 | + | |
86 | + for (Glycan gc : pointer.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
87 | + search(gc); | |
88 | + } | |
89 | + | |
90 | + /** | |
91 | + * 理論上の<I>m/z</I> を返します. | |
92 | + * @param monoisotopic モノアイソトピックかアベレージかをMassCalc.MONO_MASSで指定 | |
93 | + * @param adduct 付加イオンをMassCalc.Na_IONで指定 | |
94 | + * @return 理論上の<I>m/z</I> | |
95 | + */ | |
96 | + public double getMass(boolean monoisotopic, String adduct) throws Exception | |
97 | + { | |
98 | + MassCalc mc = new MassCalc(monoisotopic, adduct); | |
99 | + return mc.getMass(this); | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * セラミドを含んでいるかを返します. | |
104 | + * @return セラミドを含んでいるか | |
105 | + */ | |
106 | + public boolean hasCeramide() throws Exception | |
107 | + { | |
108 | + for (String str : this) | |
109 | + if (str.matches("^([dt])([ch][0-9]+:[0-9])$")) // セラミドが存在した場合 | |
110 | + return true; | |
111 | + | |
112 | + return false; // セラミドが存在しなかった場合 | |
113 | + } | |
114 | + | |
115 | + /** | |
116 | + * 組成の中からセラミドを取得します. | |
117 | + * @return セラミド | |
118 | + */ | |
119 | + public String getCeramide() throws Exception | |
120 | + { | |
121 | + Iterator<String> it = this.iterator(); | |
122 | + int count = 0; // 組成の中にセラミドが1個または0個であるかを確認する. | |
123 | + String ceramide = null; | |
124 | + for (String temp : this) | |
125 | + if (temp.matches("^([dt])([Cch][0-9]+:[0-9])$")) // セラミドが存在した場合, | |
126 | + { | |
127 | + ceramide = temp; | |
128 | + count++; | |
129 | + } | |
130 | + | |
131 | + if (count == 1) // 1個の時 | |
132 | + return ceramide; | |
133 | + else // セラミドの個数が1個でない時 | |
134 | + throw new Exception("Exception at Composition.getCeramide()"); | |
135 | + } | |
136 | + | |
137 | + /** | |
138 | + * ヒドロキシル基の数を返します. | |
139 | + * @return ヒドロキシル基の数 | |
140 | + */ | |
141 | + public int countHydroxy() throws Exception | |
142 | + { | |
143 | + Pattern pt1 = Pattern.compile("^(pen|xyl|ara|dhex|fuc|rha|hex|glc|gal|man|hexnac|glcnac|galnac|glca|hexa|neuac|kdn|neugc)([0-9]*)(me)*$"); // アセチル基には未対応 | |
144 | + Pattern pt2 = Pattern.compile("^([dt])([ch])([0-9]+):([0-9])$"); | |
145 | + int count = 0; // ヒドロキシル基の数 | |
146 | + int bound = 0; // グリコシド結合の数 | |
147 | + | |
148 | + for (String str : this) | |
149 | + { | |
150 | + Matcher mt1 = pt1.matcher(str); | |
151 | + Matcher mt2 = pt2.matcher(str); | |
152 | + | |
153 | + if (mt1.matches()) // 糖のメチル化 | |
154 | + { | |
155 | + if (mt1.group(1).matches("^(pen|xyl|ara|dhex|fuc|rha)$")) // デオキシヘキソースとペントースの場合, | |
156 | + count += 3; // 修飾基の付加できる部分は最大3ヶ所 | |
157 | + else if (mt1.group(1).matches("^(hex|glc|gal|man|hexnac|glcnac|galnac|glca|hexa)$")) // 他の糖の場合, | |
158 | + count += 4; // 最大4ヶ所 | |
159 | + else if (mt1.group(1).matches("^(neuac|kdn)$")) // NeuAc,KDNは,6個のメチル基が入る. | |
160 | + count += 6; | |
161 | + else if (mt1.group(1).equals("neugc")) // NeuGcは,NeuAcからさらにOH基が1つ多いため, | |
162 | + count += 7; // 7個のメチル基が入る. | |
163 | + | |
164 | + int reduce = 0; // 現在の修飾基が付加できる数から,減らさなくてはならない数 | |
165 | + if (mt1.group(2).matches("^\\d$") && mt1.group(3).matches("^(me|ac)$")) // 修飾基の数を指定した場合, | |
166 | + reduce = Integer.parseInt(mt1.group(2)); // 指定された数を読み込む. | |
167 | + else if (mt1.group(3) != null && mt1.group(3).equals("me")) // 数が指定されていない場合は, | |
168 | + reduce = 1; // 1つ減らす. | |
169 | + count -= reduce; // 最後に指定された数を減らす. | |
170 | + | |
171 | + bound++; // グリコシド結合の数を1つ加算する. | |
172 | + } | |
173 | + else if (mt2.matches()) // セラミドのメチル化(長鎖塩基のNにもメチル基が入る) | |
174 | + { | |
175 | + if (mt2.group(1).equals("d")) // ジヒドロキシスフィンゴシンの場合, | |
176 | + count += 3; // メチル基が2つ増加(=炭素数が2つ増加) | |
177 | + else if (mt2.group(1).equals("t")) // トリヒドロキシスフィンゴシンの場合, | |
178 | + count += 4; // メチル基が3つ増加(=炭素数が3つ増加) | |
179 | + | |
180 | + if (mt2.group(2).equals("h")) // ヒドロキシ脂肪酸の場合, | |
181 | + count++; // メチル基が1つ増加(=炭素数が1つ増加) | |
182 | + | |
183 | + bound++; // グリコシド結合の数を1つ加算する. | |
184 | + } | |
185 | + else if (str.matches("^(me|ac)$")) // 修飾基の場合, | |
186 | + { | |
187 | + count += 0; // メチル基が入らない. | |
188 | + bound++; // グリコシド結合の数を1つ加算する. | |
189 | + } | |
190 | + else if (str.matches("^(-h|h|na|li|k|h2o|-h2o)$")) // 付加イオンの場合, | |
191 | + { | |
192 | + count += 0; // メチル基が入らない. | |
193 | + } | |
194 | + else // 全ての条件と一致しなかった場合 | |
195 | + throw new Exception("Unknown Composition in countHydroxy(): " + str); | |
196 | + } | |
197 | + | |
198 | + if (bound != 0) // 糖鎖が存在する場合 | |
199 | + count = count - bound + 1; // 結合に使うOH基を削除 | |
200 | + | |
201 | + if (!this.hasCeramide() && bound != 0) // 糖鎖が存在しており,セラミドが存在しない場合, | |
202 | + count++; // 還元末端側のOH基をカウントする. | |
203 | + | |
204 | + return count; | |
205 | + } | |
206 | + | |
207 | + /** | |
208 | + * 候補と数を文字列型として返します. | |
209 | + * @return 候補と数の文字列 | |
210 | + */ | |
211 | + public String toString() | |
212 | + { | |
213 | + StringBuilder str = new StringBuilder(); // リターンする文字列 | |
214 | + | |
215 | + try | |
216 | + { | |
217 | + List<String> li = new ArrayList<String>(new HashSet<String>(this)); // 要素の重複を削除し,ArrayListへ変換 | |
218 | + | |
219 | + Collections.sort(li, new Comparator<String>() // セラミド,長鎖塩基または脂肪酸,糖,その他の順にソート | |
220 | + { | |
221 | + public int compare(String str1, String str2) | |
222 | + { | |
223 | + return getSortScore(str1) - getSortScore(str2); // 各単糖の並び順のスコアを用いる. | |
224 | + } | |
225 | + }); | |
226 | + | |
227 | + Iterator<String> it = li.iterator(); | |
228 | + while (it.hasNext()) | |
229 | + { | |
230 | + String comp = it.next(); // 組成を取得 | |
231 | + int count = Collections.frequency(this, comp); // 要素を探索し,個数を数える. | |
232 | + | |
233 | + comp = Composition.toFixSignage(comp); // 正しい表記に変換 | |
234 | + | |
235 | + if (count == 1) | |
236 | + str.append(comp); // 要素が1つならばそのまま出力 | |
237 | + else | |
238 | + str.append(comp + "*" + count); // 要素が1つ以上ならば,個数を付加して出力 | |
239 | + | |
240 | + if (it.hasNext()) | |
241 | + str.append(", "); // 次の要素を持っていたら", "を追加する. | |
242 | + } | |
243 | + } | |
244 | + catch (Exception e) | |
245 | + { | |
246 | + System.out.println("Exception at Composition.toString()"); | |
247 | + } | |
248 | + | |
249 | + return str.toString(); | |
250 | + } | |
251 | + | |
252 | + /** | |
253 | + * toString()メソッドに用いる各単糖の並び順のスコアを返します. | |
254 | + * @parm str 文字列型の単糖 | |
255 | + */ | |
256 | + private int getSortScore(String str) | |
257 | + { | |
258 | + int score; // リターンするスコア | |
259 | + | |
260 | + // 大まかに10ずつ単糖を区別し,詳細に区別する場合は1ずつ区別する. | |
261 | + if (str.matches("^[dt][ch][0-9]+:[0-9]$") || str.matches("^.+pa$") || str.matches("^.+ab$") ) | |
262 | + score = 0; // セラミドまたはPA糖の場合 | |
263 | + else if (str.matches("^[dt][0-9]+:[0-9]$")) | |
264 | + score = 10; // 長鎖塩基の場合 | |
265 | + else if (str.matches("^[Cch][0-9]+:[0-9]$")) | |
266 | + score = 20; // 脂肪酸の場合 | |
267 | + else if (str.matches("^(pc|ins|hexa)$")) | |
268 | + score = 30; // 還元末端側である可能性の高い糖の場合 | |
269 | + else if (str.matches("^(gal|glc)$")) | |
270 | + score = 40; // 還元末端側である可能性の高い糖の場合 | |
271 | + else if (str.matches("^(man)$")) | |
272 | + score = 50; // 次に還元末端側である可能性の高い糖の場合 | |
273 | + else if (str.matches("^(hex)$")) | |
274 | + score = 60; | |
275 | + else if (str.matches("^(fuc|rha)$")) | |
276 | + score = 70; | |
277 | + else if (str.matches("^(dhex)$")) | |
278 | + score = 80; | |
279 | + else if (str.matches("^(xyl|rha)$")) | |
280 | + score = 90; | |
281 | + else if (str.matches("^(pen)$")) | |
282 | + score = 100; | |
283 | + else if (str.matches("^(galnac|glcnac)$")) | |
284 | + score = 110; | |
285 | + else if (str.matches("^(hexnac)$")) | |
286 | + score = 120; | |
287 | + else if (str.matches("^(gal|glc)\\d*(me|ac)$")) | |
288 | + score = 130 + countModification(str); // メチル化,アセチル化の個数で並び替える. | |
289 | + else if (str.matches("^man\\d*(me|ac)$")) | |
290 | + score = 140 + countModification(str); | |
291 | + else if (str.matches("^hex\\d*(me|ac)$")) | |
292 | + score = 150 + countModification(str); | |
293 | + else if (str.matches("^(fuc|rha)\\d*(me|ac)$")) | |
294 | + score = 160 + countModification(str); | |
295 | + else if (str.matches("^dhex\\d*(me|ac)$")) | |
296 | + score = 170 + countModification(str); | |
297 | + else if (str.matches("^(xyl|rha)\\d*(me|ac)$")) | |
298 | + score = 180 + countModification(str); | |
299 | + else if (str.matches("^pen\\d*(me|ac)$")) | |
300 | + score = 190 + countModification(str); | |
301 | + else if (str.matches("^(galnac|glcnac)\\d*(me|ac)$")) | |
302 | + score = 200 + countModification(str); | |
303 | + else if (str.matches("^hexnac\\d*(me|ac)$")) | |
304 | + score = 210 + countModification(str); | |
305 | + else if (str.matches("^(p|c|pea|aep|kdn|neuac|neugc)$")) | |
306 | + score = 220; // 糖の場合 | |
307 | + else if (str.matches("^(p|c|pea|aep|kdn|neuac|neugc)\\d*(me|ac)$")) | |
308 | + score = 230; // 糖の場合 | |
309 | + else | |
310 | + score = 240;// その他の修飾基など | |
311 | + | |
312 | + return score; | |
313 | + } | |
314 | + | |
315 | + /** | |
316 | + * 単糖のメチル基,アセチル基の個数を返します. | |
317 | + */ | |
318 | + private int countModification(String str) | |
319 | + { | |
320 | + Pattern pt = Pattern.compile("^\\D+(\\d*)(me|ac)$"); | |
321 | + Matcher mt = pt.matcher(str); | |
322 | + | |
323 | + if (mt.matches()) | |
324 | + { | |
325 | + String number = mt.group(1); | |
326 | + if (!number.equals("")) | |
327 | + return Integer.parseInt(number); // 個数が指定されている場合 | |
328 | + else | |
329 | + return 1; // 個数を指定していない場合は1個となる. | |
330 | + } | |
331 | + else | |
332 | + { | |
333 | + System.err.println("Monosacchride does not contain modification:" + str); | |
334 | + return 0; // メチル基,アセチル基を持っていない場合は,0個を返す. | |
335 | + } | |
336 | + } | |
337 | + | |
338 | + /** | |
339 | + * glcをGlcへ,hexnacpaをHexNAcPAなど,単糖の表記を正しく変換します. | |
340 | + */ | |
341 | + public static String toFixSignage(String before) | |
342 | + { | |
343 | + before = before.replace("nac", "NAc"); // "NAc"の置換後に"Ac"を置換 | |
344 | + before = before.replace("ac","Ac"); | |
345 | + | |
346 | + before = before.replace("me", "Me"); | |
347 | + before = before.replace("et", "Et"); | |
348 | + before = before.replace("tms", "TMS"); | |
349 | + before = before.replace("h2o", "H2O"); | |
350 | + before = before.replace("pa", "PA"); | |
351 | + before = before.replace("ab", "AB"); | |
352 | + | |
353 | + before = before.replace("pen", "Pen"); | |
354 | + before = before.replace("xyl", "Xyl"); | |
355 | + before = before.replace("ara", "Ara"); | |
356 | + | |
357 | + before = before.replace("lfuc", "LFuc"); // "LFuc"の置換後に"Fuc"を置換 | |
358 | + before = before.replace("fuc", "Fuc"); | |
359 | + before = before.replace("rha", "Rha"); | |
360 | + | |
361 | + before = before.replace("hexa", "HexA"); // "HexA"の置換後に"Hex"を置換 | |
362 | + before = before.replace("hex", "Hex"); // "dHex, HexNAcも同時に置換" | |
363 | + | |
364 | + before = before.replace("glca", "GlcA"); // "GlcA"の置換後に"Glc"を置換 | |
365 | + before = before.replace("glc", "Glc"); | |
366 | + before = before.replace("gal", "Gal"); | |
367 | + before = before.replace("man", "Man"); | |
368 | + | |
369 | + if (before.equals("s")) | |
370 | + before = "S"; | |
371 | + if (before.equals("p")) | |
372 | + before = "P"; | |
373 | + if (before.equals("c")) | |
374 | + before = "C"; | |
375 | + before = before.replace("pc", "PC"); | |
376 | + | |
377 | + before = before.replace("ins", "Ins"); | |
378 | + before = before.replace("aep", "AEP"); | |
379 | + before = before.replace("pea", "PEA"); | |
380 | + before = before.replace("kdn", "KDN"); | |
381 | + before = before.replace("neu", "Neu"); | |
382 | + before = before.replace("gc", "Gc"); | |
383 | + | |
384 | + if (before.equals("-h")) | |
385 | + before = "-H"; | |
386 | + if (before.equals("h")) | |
387 | + before = "H"; | |
388 | + if (before.equals("na")) | |
389 | + before = "Na"; | |
390 | + if (before.equals("li")) | |
391 | + before = "Li"; | |
392 | + if (before.equals("k")) | |
393 | + before = "K"; | |
394 | + | |
395 | + return before; | |
396 | + } | |
397 | + | |
398 | + /** | |
399 | + * 糖鎖組成が同じであるかを判定します. | |
400 | + * @param cp 比較する組成 | |
401 | + * @return 判定結果 | |
402 | + */ | |
403 | + public boolean equals(Composition cp) | |
404 | + { | |
405 | + try | |
406 | + { | |
407 | + Composition cp1 = new Composition(this); // 順番を変化させないよう | |
408 | + Composition cp2 = new Composition(cp); // コピーを作成 | |
409 | + Collections.sort(cp1); // ソート | |
410 | + Collections.sort(cp2); | |
411 | + return cp1.toString().equals(cp2.toString()); // Stringのメソッドで比較 | |
412 | + } | |
413 | + catch (Exception e) | |
414 | + { | |
415 | + System.out.println("Exception at Composition.equals()"); | |
416 | + return false; // 例外が発生した場合,戻り値はfalseとする. | |
417 | + } | |
418 | + } | |
419 | + | |
420 | + /** | |
421 | + * 組成のハッシュ値を返します. | |
422 | + * @return 判定結果 | |
423 | + */ | |
424 | + public int hashCode() | |
425 | + { | |
426 | + try | |
427 | + { | |
428 | + Composition cp = new Composition(this); // 順番を変化させないようコピーを作成 | |
429 | + Collections.sort(cp); // ソート | |
430 | + return cp.toString().hashCode(); // CompositionのhashCode()であると再帰してしまうため, | |
431 | + } // StringのhashCode()を使用 | |
432 | + catch (Exception e) | |
433 | + { | |
434 | + System.out.println("Exception at Composition.hashCode()"); | |
435 | + return 0; // 例外が発生した場合,戻り値は0とする. | |
436 | + } | |
437 | + } | |
438 | + | |
439 | + /** | |
440 | + * Glc,Gal,ManをHexへ,GlcNAc,GalNAcをHexNAcへ変換します. | |
441 | + */ | |
442 | + public void toHexose() | |
443 | + { | |
444 | + ListIterator<String> li = this.listIterator(); | |
445 | + | |
446 | + while (li.hasNext()) | |
447 | + { | |
448 | + String str = li.next(); | |
449 | + str = str.replaceAll("glc|man|gal", "hex"); // Hexへ変換 | |
450 | + str = str.replaceAll("lfuc|fuc|rha", "dhex"); // dHexへ変換 | |
451 | + str = str.replaceAll("xyl|ara", "pen"); // penへ変換 | |
452 | + li.set(str); // 変換した組成を格納する. | |
453 | + } | |
454 | + } | |
455 | + | |
456 | + /* | |
457 | + * GlcからHexなどの変換のテスト | |
458 | + */ | |
459 | + private static void testToHexose() throws Exception | |
460 | + { | |
461 | + Composition cp1 = new Composition(new Glycan("[][th39:0]{[][fuc]{}[][hex]{}}")); | |
462 | + Composition cp2 = new Composition("Hex, Hex*2, th38:0, c18:0, d17:0, Fuc"); | |
463 | + cp1.toHexose(); | |
464 | + cp2.toHexose(); | |
465 | + System.out.println(cp1); | |
466 | + System.out.println(cp2); | |
467 | + } | |
468 | + | |
469 | + /** | |
470 | + * 要素を含んでいるかを判定します. | |
471 | + * @param str 判定したい文字列 | |
472 | + * @return 判定結果 | |
473 | + */ | |
474 | + public boolean contains(String str) | |
475 | + { | |
476 | + return super.contains(str.toLowerCase()); // 引数の文字列を小文字に変換して,親クラスのメソッドに渡す. | |
477 | + } | |
478 | + | |
479 | + /** | |
480 | + * 指定した要素を削除します. | |
481 | + * @param str 削除したい文字列 | |
482 | + * @return 削除の成功したか否か | |
483 | + */ | |
484 | + public boolean remove(String str) | |
485 | + { | |
486 | + return super.remove(str.toLowerCase()); // 引数の文字列を小文字に変換して,親クラスのメソッドに渡す. | |
487 | + } | |
488 | + | |
489 | + /** | |
490 | + * Globo系列であるかを判定します. | |
491 | + * @return 指定した系列であるか否か | |
492 | + */ | |
493 | + public boolean isGloboSeries() throws Exception | |
494 | + { | |
495 | + return this.isSeries(new Composition("glc, gal, gal, galnac")); | |
496 | + } | |
497 | + | |
498 | + /** | |
499 | + * Lacto系列であるかを判定します. | |
500 | + * @return 指定した系列であるか否か | |
501 | + */ | |
502 | + public boolean isLactoSeries() throws Exception | |
503 | + { | |
504 | + return this.isSeries(new Composition("glc, gal, glcnac, gal")); | |
505 | + } | |
506 | + | |
507 | + /** | |
508 | + * Ganglio系列であるかを判定します. | |
509 | + * @return 指定した系列であるか否か | |
510 | + */ | |
511 | + public boolean isGanglioSeries() throws Exception | |
512 | + { | |
513 | + return this.isSeries(new Composition("glc, gal, galnac, gal")); | |
514 | + } | |
515 | + | |
516 | + /** | |
517 | + * Lactoganglio系列であるかを判定します. | |
518 | + * @return 指定した系列であるか否か | |
519 | + */ | |
520 | + public boolean isLactoganglioSeries() throws Exception | |
521 | + { | |
522 | + return this.isSeries(new Composition("glc, gal, galnac, glcnac")); | |
523 | + } | |
524 | + | |
525 | + /** | |
526 | + * Gala系列であるかを判定します. | |
527 | + * @return 指定した系列であるか否か | |
528 | + */ | |
529 | + public boolean isGalaSeries() throws Exception | |
530 | + { | |
531 | + return this.isSeries(new Composition("gal, gal")); | |
532 | + } | |
533 | + | |
534 | + /** | |
535 | + * Muco系列であるかを判定します. | |
536 | + * @return 指定した系列であるか否か | |
537 | + */ | |
538 | + public boolean isMucoSeries() throws Exception | |
539 | + { | |
540 | + return this.isSeries(new Composition("glc, gal, gal, gal")); | |
541 | + } | |
542 | + | |
543 | + /** | |
544 | + * Arthro系列であるかを判定します. | |
545 | + * @return 指定した系列であるか否か | |
546 | + */ | |
547 | + public boolean isArthroSeries() throws Exception | |
548 | + { | |
549 | + return this.isSeries(new Composition("glc, man, glcnac, galnac")); | |
550 | + } | |
551 | + | |
552 | + /** | |
553 | + * Mollu系列であるかを判定します. | |
554 | + * @return 指定した系列であるか否か | |
555 | + */ | |
556 | + public boolean isMolluSeries() throws Exception | |
557 | + { | |
558 | + return this.isSeries(new Composition("glc, man, man, glcnac")); | |
559 | + } | |
560 | + | |
561 | + /** | |
562 | + * 指定した系列であるかを判定します. | |
563 | + * @return 指定した系列であるか否か | |
564 | + */ | |
565 | + private boolean isSeries(Composition series) throws Exception | |
566 | + { | |
567 | + Composition cp = new Composition(this); // 新しいインスタンスを作成 | |
568 | + | |
569 | + for (String str : series) | |
570 | + { | |
571 | + if (cp.contains(str)) // "glc"が存在した場合,削除する. | |
572 | + cp.remove(str); | |
573 | + else | |
574 | + { | |
575 | + Composition temp = new Composition(str); // "Glc"->"Hex"に変換するためにインスタンスを作成 | |
576 | + temp.toHexose(); // "Glc"->"Hex"に変換 | |
577 | + | |
578 | + if (cp.contains(temp.toString())) // "glc"が存在せず"hex"が存在した場合,削除する. | |
579 | + cp.remove(temp.toString()); | |
580 | + else | |
581 | + return false; // "glc"も"hex"も存在しない場合,削除に失敗したとする. | |
582 | + } | |
583 | + } | |
584 | + | |
585 | + return true; // 全ての条件を満たした場合のみ,この系列であると判断する. | |
586 | + } | |
587 | + | |
588 | + /** | |
589 | + * 組成から糖鎖系列の判定を行います. | |
590 | + */ | |
591 | + private static void testSeries() throws Exception | |
592 | + { | |
593 | + Composition cp = new Composition("Glc, Glc, Hex, Hex, GlcNAc, -H2O"); | |
594 | + System.out.println(cp.isGloboSeries()); | |
595 | + } | |
596 | + | |
597 | + /** | |
598 | + * メチル基の入るヒドロキシル基の数を正しく数えているかをテストします. | |
599 | + */ | |
600 | + private static void testCountHydroxy() throws Exception | |
601 | + { | |
602 | + Composition cp = new Composition("NeuAc2Me"); | |
603 | + System.out.println(cp + " : " + cp.countHydroxy()); | |
604 | + } | |
605 | +} |
@@ -0,0 +1,600 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.text.*; | |
3 | +import java.awt.*; | |
4 | +import java.awt.event.*; | |
5 | +import javax.swing.*; | |
6 | +import java.util.*; | |
7 | +import javax.swing.table.*; | |
8 | +import java.util.concurrent.*; | |
9 | +import java.lang.management.*; | |
10 | + | |
11 | +/** | |
12 | + * 糖鎖,およびピリジルアミノ化糖鎖のフラグメントイオンから構造を予測するクラスです.(GUI版) | |
13 | + * @author 横井一仁 | |
14 | + * @version 20090202 | |
15 | + */ | |
16 | +public class PredictionGUIGlycan implements Observer, ActionListener, Runnable | |
17 | +{ | |
18 | + String adduct = MassCalc.Na_ION; // 付加イオン(デフォルトはNa+)選択部のコードの重複ためグローバル変数とする. | |
19 | + boolean monoavg = MassCalc.MONO_MASS; // Monoisotopic(ture),Averaget(false) | |
20 | + | |
21 | + JFrame jf = new JFrame("Structure Predictor (free/PA oligosaccharide ver)"); // メインのフレーム | |
22 | + | |
23 | + // HexNAc-HexNAc-HexNAc-HexNAc-HexNAcの実測フラグメント | |
24 | + JTextArea query_ta = new JTextArea("210.46\n226.40\n259.28\n304.23\n322.24\n347.22\n388.27\n406.33\n507.56\n" | |
25 | + + "512.00\n525.63\n532.50\n550.61\n568.62\n696.83\n712.80\n730.76\n753.75\n" | |
26 | + + "760.46\n786.82\n831.78\n849.81\n874.75\n915.72\n933.68\n975.46\n990.71\n" | |
27 | + + "993.66\n996.84\n1011.81\n1034.68\n1047.76\n1052.76\n1077.76\n1095.74\n" | |
28 | + + "1111.85\n1118.75\n1126.02\n1129.14\n1151.93\n1171.90\n1196.97\n1199.47\n" | |
29 | + + "1214.88\n1280.94\n1299.03\n1359.16\n1361.36\n1377.22\n1400.49\n1418.19\n" | |
30 | + + "1472.53\n1579.87"); | |
31 | + JTextField precursor_mass_tf = new JTextField(""); // プレカーサーマスのm/z | |
32 | + JTextField precursor_tolerance_tf = new JTextField("2.0"); // プレカーサーマスの許容誤差 | |
33 | + JTextField psd_tolerance_tf = new JTextField("2.0"); // PSDフラグメントの許容誤差 | |
34 | + JTextField known_gc_tf = new JTextField("GlcNAcPA-GlcNAc-Man(-Man)-Man"); // 既知構造 | |
35 | + JComboBox adduct_cb = new JComboBox(new String[]{"Na+","H+","Li+","K+","H-","No adduct"}); // 付加イオン | |
36 | + JComboBox pen_cb = new JComboBox(new String[] {"Yes", "No"}); // Penが存在しているか否かを指定 | |
37 | + JComboBox dhex_cb = new JComboBox(new String[] {"Yes", "No"}); // dHexが存在しているか否かを指定 | |
38 | + JComboBox hex_cb = new JComboBox(new String[] {"Yes", "No"}); // Hexが存在しているか否かを指定 | |
39 | + JComboBox hexnac_cb = new JComboBox(new String[] {"Yes", "No"}); // HexNAcが存在しているか否かを指定 | |
40 | + JComboBox penme_cb = new JComboBox(new String[] {"Yes", "No"}); // PenMeが存在しているか否かを指定 | |
41 | + JComboBox dhexme_cb = new JComboBox(new String[] {"Yes", "No"}); // dHexMeが存在しているか否かを指定 | |
42 | + JComboBox hexme_cb = new JComboBox(new String[] {"Yes", "No"}); // HexMeが存在しているか否かを指定 | |
43 | + JComboBox hexnacme_cb = new JComboBox(new String[] {"Yes", "No"}); // HexNAcMeが存在しているか否かを指定 | |
44 | + | |
45 | + JTextArea ceramide_tf = new JTextArea("dc30-44:1, dh30-44:1,\ntc30-44:0, th30-44:0"); // 既知セラミド組成 | |
46 | + JComboBox formula_cb = new JComboBox(new String[] // スコア計算式 | |
47 | + { | |
48 | + "POSITIVE", | |
49 | + "TFIDF", | |
50 | + "PENALTY01", | |
51 | + "PENALTY001", | |
52 | + "PMF", | |
53 | + "GEOMETRICAVG" | |
54 | + }); | |
55 | + JButton start = new JButton("Start search"); // 検索開始ボタン | |
56 | + JButton reset = new JButton("Reset form"); // リセットボタン | |
57 | + | |
58 | + String[] title = {"Score", "Candidate structure", "Occupancy", "m/z"}; // 予想構造出力部 | |
59 | + DefaultTableModel tm = new DefaultTableModel(title, 0); | |
60 | + JTable result_ta = new JTable(tm); | |
61 | + | |
62 | + ProgressMonitor pm; // 進捗バー | |
63 | + | |
64 | + /* | |
65 | + * 実測値を入力する部分のJPanelを取得します. | |
66 | + */ | |
67 | + protected JPanel getInputJPanel() | |
68 | + { | |
69 | + JPanel west_center = new JPanel(); // ウィンドウのWESTに貼り付けるパネルのCENTER | |
70 | + west_center.setLayout(new BorderLayout()); // ウィンドウの左上 | |
71 | + west_center.add(new JLabel("Fragment mass:"), BorderLayout.NORTH); | |
72 | + west_center.add(new JScrollPane(query_ta), BorderLayout.CENTER); // JTextAreaへスクロールバーをつける. | |
73 | + | |
74 | + return west_center; | |
75 | + } | |
76 | + | |
77 | + /* | |
78 | + * 実験的な予測条件を設定する部分のJPanelを取得します. | |
79 | + */ | |
80 | + protected JPanel getExperimentalConditionJPanel() | |
81 | + { | |
82 | + JPanel west_south_north = new JPanel(); // 予測条件入力部 ウィンドウのWESTに貼り付けるパネルのSOUTH | |
83 | + // ウィンドウの左下 | |
84 | + // JComboBoxの初期選択項目を指定する. | |
85 | + pen_cb.setSelectedItem("No"); // Penのデフォルトは"No" | |
86 | + dhex_cb.setSelectedItem("Yes"); // dHexのデフォルトは"Yes" | |
87 | + hex_cb.setSelectedItem("Yes"); // Hexのデフォルトは"Yes" | |
88 | + hexnac_cb.setSelectedItem("Yes"); // HexNAcのデフォルトは"Yes" | |
89 | + | |
90 | + penme_cb.setSelectedItem("No"); // PenMeのデフォルトは"No" | |
91 | + dhexme_cb.setSelectedItem("No"); // dHexMeのデフォルトは"No" | |
92 | + hexme_cb.setSelectedItem("No"); // HexMeのデフォルトは"No" | |
93 | + hexnacme_cb.setSelectedItem("No"); // HexNAcMeのデフォルトは"No" | |
94 | + | |
95 | + formula_cb.setSelectedItem("TFIDF"); // スコア計算式のデフォルトは"TFIDF" | |
96 | + | |
97 | + west_south_north.setLayout(new GridLayout(12, 2)); // 縦の数×横の数 | |
98 | + west_south_north.add(new JLabel("Fragment tolerance: ")); | |
99 | + west_south_north.add(psd_tolerance_tf); | |
100 | + west_south_north.add(new JLabel("Precursor mass: ")); | |
101 | + west_south_north.add(precursor_mass_tf); | |
102 | + west_south_north.add(new JLabel("Precursor tolerance: ")); | |
103 | + west_south_north.add(precursor_tolerance_tf); | |
104 | + west_south_north.add(new JLabel("Adduct ion: ")); | |
105 | + west_south_north.add(adduct_cb); | |
106 | + west_south_north.add(new JLabel("Pen: ")); | |
107 | + west_south_north.add(pen_cb); | |
108 | + west_south_north.add(new JLabel("dHex: ")); | |
109 | + west_south_north.add(dhex_cb); | |
110 | + west_south_north.add(new JLabel("Hex: ")); | |
111 | + west_south_north.add(hex_cb); | |
112 | + west_south_north.add(new JLabel("HexNAc: ")); | |
113 | + west_south_north.add(hexnac_cb); | |
114 | + west_south_north.add(new JLabel("PenMe: ")); | |
115 | + west_south_north.add(penme_cb); | |
116 | + west_south_north.add(new JLabel("dHexMe: ")); | |
117 | + west_south_north.add(dhexme_cb); | |
118 | + west_south_north.add(new JLabel("HexMe: ")); | |
119 | + west_south_north.add(hexme_cb); | |
120 | + west_south_north.add(new JLabel("HexNAcMe: ")); | |
121 | + west_south_north.add(hexnacme_cb); | |
122 | + | |
123 | + return west_south_north; | |
124 | + } | |
125 | + | |
126 | + /* | |
127 | + * 実験的な予測条件を設定する部分のJPanelを取得します. | |
128 | + */ | |
129 | + protected JPanel getKnownConditionJPanel() | |
130 | + { | |
131 | + JPanel west_south_center = new JPanel(); | |
132 | + west_south_center.setLayout(new GridBagLayout()); // 入力部を広くするためにGridBagLayoutを用いる. | |
133 | + | |
134 | + GridBagConstraints gb3 = new GridBagConstraints(); // 既知糖鎖組成入力部のラベル | |
135 | + gb3.gridx = 0; | |
136 | + gb3.gridy = 1; | |
137 | + gb3.anchor = GridBagConstraints.WEST; // 左寄せ | |
138 | + west_south_center.add(new JLabel("Known: "), gb3); | |
139 | + | |
140 | + GridBagConstraints gb4 = new GridBagConstraints(); // 既知糖鎖組成入力部 | |
141 | + gb4.gridx = 1; | |
142 | + gb4.gridy = 1; | |
143 | + gb4.fill = GridBagConstraints.HORIZONTAL; // 水平方向のみに塗りつぶしを行う. | |
144 | + gb4.weightx = 1.0; // 無いとレイアウトが崩れる. | |
145 | + west_south_center.add(known_gc_tf, gb4); | |
146 | + | |
147 | + return west_south_center; | |
148 | + } | |
149 | + | |
150 | + /* | |
151 | + * 計算機的な予測条件を設定する部分のJPanelを取得します. | |
152 | + */ | |
153 | + protected JPanel getComputationalConditionJPanel() | |
154 | + { | |
155 | + byte[] bytes = {40, 99, 41, 32, 75, 97, 122, 117, 104, 105, 116, 111, 32, 89, 111, 107, 111, 105}; | |
156 | + | |
157 | + // スコアリング選択部分をBorderLayoutのNORTHとし, | |
158 | + // 検索開始ボタンとリセットボタンをSOUTHとして返す. | |
159 | + JPanel west_south_south_north = new JPanel(); // スコアリングの選択 | |
160 | + west_south_south_north.setLayout(new GridLayout(1, 2)); // 縦の数×横の数 | |
161 | + | |
162 | + JPanel west_south_south_south = new JPanel(); // 検索開始ボタンとリセットボタン | |
163 | + west_south_south_south.setLayout(new GridLayout(1, 2)); // 縦の数×横の数 | |
164 | + start.addActionListener(this); // 検索開始ボタンにリスナを付ける. | |
165 | + reset.addActionListener(this); // リセットボタンにリスナを付ける. | |
166 | + | |
167 | + JLabel author = new JLabel(new String(bytes)); | |
168 | + author.setHorizontalAlignment(SwingConstants.CENTER); | |
169 | + author.setForeground(Color.gray); | |
170 | + west_south_south_south.add(author); | |
171 | + west_south_south_south.add(start); | |
172 | + | |
173 | + JPanel west_south_south = new JPanel(); // returnするJPanelインスタンス | |
174 | + west_south_south.setLayout(new BorderLayout()); | |
175 | + west_south_south.add(west_south_south_north, BorderLayout.NORTH); // スコアリングの選択部分を追加 | |
176 | + west_south_south.add(west_south_south_south, BorderLayout.SOUTH); // 検索開始ボタンとリセットボタンを追加 | |
177 | + | |
178 | + return west_south_south; | |
179 | + } | |
180 | + | |
181 | + /* | |
182 | + * 予測条件を設定する部分のJPanelを取得します. | |
183 | + */ | |
184 | + protected JPanel getConditionJPanel() | |
185 | + { // 予測条件入力部 | |
186 | + JPanel west_south = new JPanel(); // ウィンドウのWESTに貼り付ける | |
187 | + // パネルのSOUTH(ウィンドウの左下) | |
188 | + west_south.setLayout(new BorderLayout()); | |
189 | + | |
190 | + west_south.add(getExperimentalConditionJPanel(), BorderLayout.NORTH); // 実験的な予測条件を設定 | |
191 | + west_south.add(getKnownConditionJPanel(), BorderLayout.CENTER); // 実験的な予測条件を設定 | |
192 | + west_south.add(getComputationalConditionJPanel(), BorderLayout.SOUTH); // 計算機的な予測条件を設定 | |
193 | + | |
194 | + return west_south; | |
195 | + } | |
196 | + | |
197 | + /* | |
198 | + * 予測結果を出力する部分のJPanelを取得します. | |
199 | + */ | |
200 | + protected JPanel getOutputJPanel() | |
201 | + { | |
202 | + JPanel center = new JPanel(); // 予想構造出力部 | |
203 | + center.setLayout(new BorderLayout()); // ウィンドウのCENTERに貼り付けるパネル(ウィンドウの右) | |
204 | + this.resetTableColumnSize(); // カラム幅を指定する. | |
205 | + JScrollPane result_sp = new JScrollPane(result_ta); // JTableへスクロールバーをつける. | |
206 | + result_sp.addMouseListener(new MouseListener() // 表を右クリックすると印刷する. | |
207 | + { | |
208 | + public void mouseExited(MouseEvent me){} | |
209 | + public void mouseEntered(MouseEvent me){} | |
210 | + public void mousePressed(MouseEvent me){} | |
211 | + public void mouseReleased(MouseEvent me){} | |
212 | + public void mouseClicked(MouseEvent me) | |
213 | + { | |
214 | + if (me.getButton() == MouseEvent.BUTTON3) // 右クリック | |
215 | + { | |
216 | + try | |
217 | + { | |
218 | + result_ta.print(); // 印刷ダイアログを表示 | |
219 | + } | |
220 | + catch (Exception e) | |
221 | + { | |
222 | + System.out.println("Cannot print: " + e); | |
223 | + } | |
224 | + } | |
225 | + } | |
226 | + }); | |
227 | + center.add(new JLabel("Result:"), BorderLayout.NORTH); | |
228 | + center.add(result_sp, BorderLayout.CENTER); | |
229 | + | |
230 | + return center; | |
231 | + } | |
232 | + | |
233 | + /* | |
234 | + * テーブルのカラム幅を調節します. | |
235 | + */ | |
236 | + protected void resetTableColumnSize() | |
237 | + { | |
238 | + DefaultTableCellRenderer tr = new DefaultTableCellRenderer(); // カラムを右寄せするインスタンス | |
239 | + tr.setHorizontalAlignment(SwingConstants.RIGHT); | |
240 | + | |
241 | + TableColumn tc0 = result_ta.getColumnModel().getColumn(0); // スコアのカラム(0番目)のサイズを固定 | |
242 | + tc0.setMinWidth(70); | |
243 | + tc0.setMaxWidth(70); | |
244 | + tc0.setCellRenderer(tr); // カラムを右寄せ | |
245 | + // 候補構造のカラムはサイズを指定 | |
246 | + TableColumn tc2 = result_ta.getColumnModel().getColumn(2); // 占有率のカラム(2番目)のサイズを固定 | |
247 | + tc2.setMinWidth(70); | |
248 | + tc2.setMaxWidth(70); | |
249 | + tc2.setCellRenderer(tr); // カラムを右寄せ | |
250 | + TableColumn tc3 = result_ta.getColumnModel().getColumn(3); // m/zのカラム(3番目)のサイズを固定 | |
251 | + tc3.setMinWidth(80); | |
252 | + tc3.setMaxWidth(80); | |
253 | + tc3.setCellRenderer(tr); // カラムを右寄せ | |
254 | + } | |
255 | + | |
256 | + public PredictionGUIGlycan() throws Exception | |
257 | + { | |
258 | + jf.setLayout(new BorderLayout()); // ウィンドウへのコンポーネントの貼り付けは | |
259 | + // BorderLayoutを用いる. | |
260 | + JPanel west = new JPanel(); // ウィンドウのWESTに貼り付けるパネル | |
261 | + west.setLayout(new BorderLayout()); // ウィンドウの左 | |
262 | + west.add(getInputJPanel(), BorderLayout.CENTER); // 実測値を入力する部分をWESTのCENTERに配置 | |
263 | + west.add(getConditionJPanel(), BorderLayout.SOUTH); // 予測条件を設定する部分をWESTのNORTHに配置 | |
264 | + jf.getContentPane().add(west, BorderLayout.WEST); | |
265 | + | |
266 | + jf.getContentPane().add(getOutputJPanel(), BorderLayout.CENTER); // 予測結果を出力する部分をCENTERに配置 | |
267 | + | |
268 | + try // タスクトレイにアイコンを追加する. | |
269 | + { | |
270 | + SystemTray st = SystemTray.getSystemTray(); | |
271 | + ImageIcon ii = (ImageIcon)UIManager.getIcon("FileView.computerIcon"); // IconからImageIconへ型変換 | |
272 | + TrayIcon ti = new TrayIcon(ii.getImage()); | |
273 | + ti.addActionListener(new ActionListener() // トレイアイコンをダブルクリックすることで, | |
274 | + { // ウィンドウの表示/非表示を切り替える. | |
275 | + public void actionPerformed(ActionEvent e) | |
276 | + { | |
277 | + if (jf.isShowing()) // ウィンドウが表示されている場合は, | |
278 | + jf.setVisible(false); // 非表示にする. | |
279 | + else | |
280 | + { // 表示されていない場合は, | |
281 | + jf.setVisible(true); // 表示した後, | |
282 | + jf.toFront(); // このウィンドウにフォーカスを当てる. | |
283 | + } | |
284 | + } | |
285 | + }); | |
286 | + st.add(ti); | |
287 | + } | |
288 | + catch (Exception e) | |
289 | + { | |
290 | + System.err.println("Cannot use SystemTray: " + e); | |
291 | + } | |
292 | + | |
293 | + try // Swingから,Windowsのデザインへ変更 | |
294 | + { | |
295 | + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); // 外観を設定 | |
296 | + SwingUtilities.updateComponentTreeUI(jf); // 外観変更 | |
297 | + } | |
298 | + catch (Exception e) | |
299 | + { | |
300 | + System.err.println("Cannot use WindowsLookAndFeel: " + e); | |
301 | + } | |
302 | + | |
303 | + jf.setSize(900,700); | |
304 | + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ウインドウが閉じられた時に終了 | |
305 | + jf.setVisible(true); // 表示 | |
306 | + } | |
307 | + | |
308 | + /* | |
309 | + * Swingのアクションイベントが発生した時の動作を指定します. | |
310 | + * @parm ae 取得したアクションイベント | |
311 | + */ | |
312 | + public void actionPerformed(ActionEvent ae) | |
313 | + { | |
314 | + if (ae.getSource() == start) // Startボタンが押された時 | |
315 | + { | |
316 | + DefaultTableModel tm = (DefaultTableModel)result_ta.getModel(); // テーブルモデルを取得し, | |
317 | + tm.setRowCount(0); // 表の内容を削除する. | |
318 | + start.setEnabled(false); // ボタンを押せなくする. | |
319 | + reset.setEnabled(false); | |
320 | + | |
321 | + try // ProgressMonitorのタイトルなどは | |
322 | + { // デフォルトでは日本語のため,英語名に変更 | |
323 | + UIManager.put( "ProgressMonitor.progressText", "Progress Monitor" ); // ウィンドウ名 | |
324 | + UIManager.put( "OptionPane.cancelButtonText", "Cancel" ); // キャンセルボタン名 | |
325 | + } | |
326 | + catch (Exception e) | |
327 | + { | |
328 | + System.err.println("ProgressMonitor connot edit: " + e); | |
329 | + } | |
330 | + | |
331 | + // 表示する文字列のテンプレート | |
332 | + String length = "Creating Glycan Composition from precursor and fragment mass... "; | |
333 | + pm = new ProgressMonitor(jf, "Calculating...", length, 0, 100); // 進捗バー | |
334 | + pm.setMillisToDecideToPopup(0); | |
335 | + pm.setMillisToPopup(0); | |
336 | + pm.setProgress(0); // 監視対象のインスタンスから変数を取得 | |
337 | + Thread th = new Thread(this); | |
338 | + th.start(); | |
339 | + } | |
340 | + else if (ae.getSource() == reset) // Resetボタンが押された時 | |
341 | + { | |
342 | + query_ta.setText(""); // フラグメント分子量の内容を削除 | |
343 | + DefaultTableModel tm = (DefaultTableModel)result_ta.getModel(); // テーブルモデルを取得し, | |
344 | + tm.setRowCount(0); // 表の内容を削除する. | |
345 | + } | |
346 | + } | |
347 | + | |
348 | + /* | |
349 | + * 監視対象が更新された時の動作を指定します. | |
350 | + * @parm ae 取得したアクションイベント | |
351 | + */ | |
352 | + public void update(Observable ob, Object arg) | |
353 | + { | |
354 | + if (ob instanceof Prediction) // Predictionクラスのインスタンスであるかを判定 | |
355 | + { | |
356 | + Prediction temp = (Prediction)ob; // Observableインスタンスとして渡されるので型変換 | |
357 | + pm.setProgress(temp.percent); // 監視対象のインスタンスからメンバ変数を取得 | |
358 | + pm.setNote(arg.toString()); // 進捗情報の表示 | |
359 | + | |
360 | + StringBuilder line = new StringBuilder(32); // コマンドラインに表示する文字列 | |
361 | + MemoryMXBean mm = ManagementFactory.getMemoryMXBean(); | |
362 | + MemoryUsage mu = mm.getHeapMemoryUsage(); | |
363 | + line.append(" Memory: "); | |
364 | + line.append(String.format("%.1f/", mu.getUsed() / 1024.0 / 1024)); | |
365 | + line.append(String.format("%.1fMB", mu.getMax() / 1024.0 / 1024)); | |
366 | + | |
367 | + System.out.println(arg + " " + line); // 進捗情報の表示 | |
368 | + | |
369 | + if (pm.isCanceled()) // ProgressMonitorのキャンセルボタンが押された時 | |
370 | + { | |
371 | + pm.close(); // ProgressMonitorウィンドウを閉じる. | |
372 | + temp.flag = false; // 断片化処理を抜ける. | |
373 | + } | |
374 | + } | |
375 | + else | |
376 | + System.out.println("ERROR: unknown incetance of observerable class."); | |
377 | + } | |
378 | + | |
379 | + /* | |
380 | + * Startをクリックした時に実行されるスレッド | |
381 | + */ | |
382 | + public void run() | |
383 | + { | |
384 | + try | |
385 | + { | |
386 | + Prediction pd_agg = new Prediction(); // 継承の代わりに集約を用いる. | |
387 | + pd_agg.addObserver(this); // 進行状況をこのクラスへ伝えるために, | |
388 | + // このクラスをオブザーバとする. | |
389 | + // テキストエリアから実測値を取得 | |
390 | + String[] strs = query_ta.getText().split("[^\\.\\d]"); // '.'と数字以外の文字列で切り出す. | |
391 | + java.util.List<Double> massli = new ArrayList<Double>(); // 可変長配列を用意する. | |
392 | + for (String str : strs) | |
393 | + { | |
394 | + try | |
395 | + { | |
396 | + massli.add(Double.parseDouble(str)); | |
397 | + } | |
398 | + catch (Exception e) // 数字以外の文字が入っていた場合の時, | |
399 | + { // 無視したことを報告 | |
400 | + System.err.println(e); | |
401 | + } | |
402 | + } | |
403 | + double[] frags = new double[massli.size()]; // Listと同じ大きさの配列を用意する. | |
404 | + Iterator<Double> massit = massli.iterator(); | |
405 | + for (int i = 0; massit.hasNext(); i++) // double[]型のfragsへ配列の型変換 | |
406 | + frags[i] = massit.next(); | |
407 | + pd_agg.setFragments(frags); // フラグメントの実測値の配列を登録 | |
408 | + | |
409 | + try // プレカーサーマスを登録 | |
410 | + { | |
411 | + pd_agg.setPrecursorMass(Double.parseDouble(precursor_mass_tf.getText())); | |
412 | + } | |
413 | + catch (Exception e) | |
414 | + { // プレカーサーマスを登録しなかった場合, | |
415 | + System.err.println("Precursor mass is null."); // PSDフラグメントの最大値を | |
416 | + } // プレカーサーマスとして計算 | |
417 | + | |
418 | + try // プレカーサーマスの許容誤差を登録 | |
419 | + { | |
420 | + pd_agg.setMsTolerance(Double.parseDouble(precursor_tolerance_tf.getText())); // 許容誤差を格納 | |
421 | + } | |
422 | + catch (Exception e) | |
423 | + { | |
424 | + throw new Exception("'Precursor tolerance' contains error.\n" + e); | |
425 | + } | |
426 | + | |
427 | + try // PSDフラグメントの許容誤差を登録 | |
428 | + { | |
429 | + pd_agg.setPsdTolerance(Double.parseDouble(psd_tolerance_tf.getText())); // 許容誤差を格納 | |
430 | + } | |
431 | + catch (Exception e) | |
432 | + { | |
433 | + throw new Exception("'PSD tolerance' contains error.\n" + e); | |
434 | + } | |
435 | + | |
436 | + try // 付加イオンを登録 | |
437 | + { // 選択された付加イオンを取得する. | |
438 | + String temp = (String)adduct_cb.getSelectedItem(); // 表の部分でm/zを取得するのに必要なため, | |
439 | + if (temp.equals("Na+")) // adductはグローバル変数としている. | |
440 | + adduct = MassCalc.Na_ION; | |
441 | + else if (temp.equals("H+")) | |
442 | + adduct = MassCalc.H_ION; | |
443 | + else if (temp.equals("Li+")) | |
444 | + adduct = MassCalc.Li_ION; | |
445 | + else if (temp.equals("K+")) | |
446 | + adduct = MassCalc.K_ION; | |
447 | + else if (temp.equals("H-")) | |
448 | + adduct = MassCalc.H_NION; | |
449 | + else if (temp.equals("No adduct")) | |
450 | + adduct = ""; | |
451 | + else | |
452 | + throw new Exception(temp + " is unknown adduct ion."); | |
453 | + | |
454 | + pd_agg.setAdduct(adduct); | |
455 | + } | |
456 | + catch (Exception e) | |
457 | + { | |
458 | + throw new Exception("'Adduct ion' contains error.\n" + e); | |
459 | + } | |
460 | + | |
461 | + try // 既知構造を登録 | |
462 | + { | |
463 | + pd_agg.setGlycan(new Glycan(known_gc_tf.getText())); // Linucs形式から既知構造を登録 | |
464 | + } | |
465 | + catch (Exception e1) // Linucs形式の読み込みに失敗した場合, | |
466 | + { // ノーマル形式の読み込みを試す. | |
467 | + try | |
468 | + { | |
469 | + GlycanTools gi = new GlycanTools(); | |
470 | + pd_agg.setGlycan(gi.readNormalFormat(known_gc_tf.getText())); // 既知構造を登録 | |
471 | + } | |
472 | + catch (Exception e2) | |
473 | + { | |
474 | + throw new Exception("'Known structure' contains error.\n" + e1 + e2); | |
475 | + } | |
476 | + } | |
477 | + | |
478 | + try // 各糖の最大数を登録 | |
479 | + { | |
480 | + pd_agg.setMax("pen", ((String)pen_cb.getSelectedItem()).equals("Yes")); | |
481 | + pd_agg.setMax("dhex", ((String)dhex_cb.getSelectedItem()).equals("Yes")); | |
482 | + pd_agg.setMax("hex", ((String)hex_cb.getSelectedItem()).equals("Yes")); | |
483 | + pd_agg.setMax("hexnac", ((String)hexnac_cb.getSelectedItem()).equals("Yes")); | |
484 | + pd_agg.setMax("penme", ((String)penme_cb.getSelectedItem()).equals("Yes")); | |
485 | + pd_agg.setMax("dhexme", ((String)dhexme_cb.getSelectedItem()).equals("Yes")); | |
486 | + pd_agg.setMax("hexme", ((String)hexme_cb.getSelectedItem()).equals("Yes")); | |
487 | + pd_agg.setMax("hexnacme", ((String)hexnacme_cb.getSelectedItem()).equals("Yes")); | |
488 | + } | |
489 | + catch (Exception e) | |
490 | + { | |
491 | + throw new Exception("'max' contains error.\n" + e); | |
492 | + } | |
493 | + | |
494 | + try // スコアリングの式を登録 | |
495 | + { | |
496 | + String temp = (String)formula_cb.getSelectedItem(); // 選択されたスコアリングの式を取得 | |
497 | + if (temp.equals("POSITIVE")) | |
498 | + pd_agg.setScoringFormula(Candidate.POSITIVE_SCORING); | |
499 | + else if (temp.equals("TFIDF")) | |
500 | + pd_agg.setScoringFormula(Candidate.TFIDF_SCORING); | |
501 | + else if (temp.equals("PENALTY01")) | |
502 | + pd_agg.setScoringFormula(Candidate.PENALTY01_SCORING); | |
503 | + else if (temp.equals("PENALTY001")) | |
504 | + pd_agg.setScoringFormula(Candidate.PENALTY001_SCORING); | |
505 | + else if (temp.equals("PMF")) | |
506 | + pd_agg.setScoringFormula(Candidate.PMF_SCORING); | |
507 | + else if (temp.equals("GEOMETRICAVG")) | |
508 | + pd_agg.setScoringFormula(Candidate.GEOMETRICAVG_SCORING); | |
509 | + else | |
510 | + throw new Exception(temp + " is unknown adduct ion."); | |
511 | + } | |
512 | + catch (Exception e) | |
513 | + { | |
514 | + throw new Exception("'Scoring' contains error.\n" + e); | |
515 | + } | |
516 | + | |
517 | + try // 出現確率分布のウィンドウサイズを登録 | |
518 | + { | |
519 | + pd_agg.setWindowSize(1); | |
520 | + } | |
521 | + catch (Exception e) | |
522 | + { | |
523 | + throw new Exception("'Window size' contains error.\n" + e); | |
524 | + } | |
525 | + | |
526 | + // 出力部 | |
527 | + java.util.List<? extends Candidate> cds = pd_agg.getPrediction(); | |
528 | + Collections.sort(cds, new Comparator<Candidate>() // フラグメントの存在率の高い順にソート | |
529 | + { | |
530 | + public int compare(Candidate cp1, Candidate cp2) | |
531 | + { | |
532 | + double sub = 0.0; // 存在率の差 | |
533 | + try | |
534 | + { | |
535 | + double score1 = cp1.getOccupancy(); | |
536 | + double score2 = cp2.getOccupancy(); | |
537 | + | |
538 | + if (score1 == score2) // 存在率が等しい構造は,分岐数の少ない | |
539 | + sub = cp1.countLeaf() - cp2.countLeaf(); // (葉ノードの数が少ない)構造を上位に表示 | |
540 | + else | |
541 | + sub = score2 - score1; | |
542 | + } | |
543 | + catch (Exception e) | |
544 | + { | |
545 | + System.err.println("Prediction.getPrediction(): score compare error"); | |
546 | + } | |
547 | + | |
548 | + return (int)(sub*1024); // 精度を1024倍に上げる | |
549 | + } | |
550 | + }); // 存在率が高い順にソートを行う. | |
551 | + Iterator<? extends Candidate> it = cds.iterator(); | |
552 | + DefaultTableModel tm = new DefaultTableModel(title, 0); | |
553 | + for (int i = 0; i < 50 && it.hasNext(); i++) // 上位50候補を表示 | |
554 | + { | |
555 | + Candidate cd = it.next(); | |
556 | + | |
557 | + String[] table = new String[4]; // カラムの追加時は,配列の大きさに注意 | |
558 | + table[0] = String.format("%.4f", cd.getScore()); | |
559 | + | |
560 | + try | |
561 | + { | |
562 | + table[1] = cd.toNormalFormat(); // ノーマルのフォーマットで格納 | |
563 | + } | |
564 | + catch (Exception e) | |
565 | + { | |
566 | + table[1] = cd.toString(); // 二分岐以上の構造はLinucs形式で格納 | |
567 | + } | |
568 | + | |
569 | + table[2] = String.format("%.4f", cd.getOccupancy()); | |
570 | + table[3] = String.format("%.4f", cd.getMass(monoavg, adduct)); | |
571 | + tm.addRow(table); | |
572 | + } | |
573 | + result_ta.setModel(tm); | |
574 | + RowSorter<TableModel> rs = new TableRowSorter<TableModel>(tm); // ソート可能なテーブルにする. | |
575 | + result_ta.setRowSorter(rs); | |
576 | + this.resetTableColumnSize(); // カラム幅を指定する. | |
577 | + | |
578 | + java.awt.Toolkit.getDefaultToolkit().beep(); // 終了する時にビープ音を鳴らす. | |
579 | + | |
580 | + UIManager.put("OptionPane.messageDialogTitle", "Messege"); // "タイトルを"Messege"に変更する. | |
581 | + UIManager.put("OptionPane.okButtonText", "OK"); // "了解"の部分を"OK"に変更する. | |
582 | + JOptionPane.showMessageDialog(jf, "Calclation is finished.\n" + pm.getNote() + "\n" | |
583 | + + "Candidate structure: " + cds.size()); | |
584 | + start.setEnabled(true); // ボタンを押せるようにする. | |
585 | + reset.setEnabled(true); | |
586 | + } | |
587 | + catch (Exception e) // 処理の途中で例外が発生した場合, | |
588 | + { // 警告ダイアログを表示し処理を中断 | |
589 | + JOptionPane.showMessageDialog(jf, "ERROR: " + e); | |
590 | + e.printStackTrace(); | |
591 | + start.setEnabled(true); // ボタンを押せるようにする. | |
592 | + reset.setEnabled(true); | |
593 | + } | |
594 | + } | |
595 | + | |
596 | + public static void main(String[] args) throws Exception | |
597 | + { | |
598 | + new PredictionGUIGlycan(); | |
599 | + } | |
600 | +} |
@@ -0,0 +1,664 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.text.*; | |
3 | +import java.awt.*; | |
4 | +import java.awt.event.*; | |
5 | +import javax.swing.*; | |
6 | +import java.util.*; | |
7 | +import javax.swing.table.*; | |
8 | +import java.util.concurrent.*; | |
9 | +import java.lang.management.*; | |
10 | + | |
11 | +/** | |
12 | + * 糖脂質のフラグメントイオンから構造を予測するクラスです.(GUI版) | |
13 | + * @author 横井一仁 | |
14 | + * @version 20090129 | |
15 | + */ | |
16 | +public class PredictionGUI implements Observer, ActionListener, Runnable | |
17 | +{ | |
18 | + String adduct = MassCalc.Na_ION; // 付加イオン(デフォルトはNa+)選択部のコードの重複ためグローバル変数とする. | |
19 | + boolean monoavg = MassCalc.MONO_MASS; // Monoisotopic(ture),Averaget(false) | |
20 | + | |
21 | + JFrame jf = new JFrame("Structure Predictor"); // メインのフレーム | |
22 | + | |
23 | + // L5のフラグメント | |
24 | + JTextArea query_ta = new JTextArea("226.6\n346.4\n364.8\n429.3\n447.5\n590.5\n632.3\n722.2\n736.7\n793.6\n" | |
25 | + + "811.1\n884.5\n899.7\n956.5\n974.0\n1087.9\n1103.2\n1493.8\n1508.2"); | |
26 | + | |
27 | + JTextField precursor_mass_tf = new JTextField("1493.6327"); // プレカーサーマスのm/z | |
28 | + JTextField precursor_tolerance_tf = new JTextField("0.5"); // プレカーサーマスの許容誤差 | |
29 | + JTextField psd_tolerance_tf = new JTextField("1.0"); // PSDフラグメントの許容誤差 | |
30 | + JTextField known_gc_tf = new JTextField("Hex"); // 既知構造 | |
31 | + JComboBox adduct_cb = new JComboBox(new String[]{"Na+","H+","Li+","K+","H-","No adduct"}); // 付加イオン | |
32 | + JComboBox pen_cb = new JComboBox(new String[] {"Yes", "No"}); // Penが存在しているか否かを指定 | |
33 | + JComboBox dhex_cb = new JComboBox(new String[] {"Yes", "No"}); // dHexが存在しているか否かを指定 | |
34 | + JComboBox hex_cb = new JComboBox(new String[] {"Yes", "No"}); // Hexが存在しているか否かを指定 | |
35 | + JComboBox hexnac_cb = new JComboBox(new String[] {"Yes", "No"}); // HexNAcが存在しているか否かを指定 | |
36 | + JComboBox penme_cb = new JComboBox(new String[] {"Yes", "No"}); // Penが存在しているか否かを指定 | |
37 | + JComboBox dhexme_cb = new JComboBox(new String[] {"Yes", "No"}); // dHexMeが存在しているか否かを指定 | |
38 | + JComboBox hexme_cb = new JComboBox(new String[] {"Yes", "No"}); // HexMeが存在しているか否かを指定 | |
39 | + JComboBox hexnacme_cb = new JComboBox(new String[] {"Yes", "No"}); // HexNAcMeが存在しているか否かを指定 | |
40 | + | |
41 | + JTextArea ceramide_tf = new JTextArea("d14-20:1, c14-24:0,\n" | |
42 | + + "t14-20:0, h14-24:0"); // 既知セラミド組成 | |
43 | + JComboBox formula_cb = new JComboBox(new String[] // スコア計算式 | |
44 | + { | |
45 | + "POSITIVE", | |
46 | + "TFIDF", | |
47 | + "PENALTY01", | |
48 | + "PENALTY001", | |
49 | + "PMF", | |
50 | + "GEOMETRICAVG" | |
51 | + }); | |
52 | + JButton start = new JButton("Start search"); // 検索開始ボタン | |
53 | + JButton reset = new JButton("Reset form"); // リセットボタン | |
54 | + | |
55 | + String[] title = {"Score", "Candidate structure", "Occupancy", "m/z"}; // 予想構造出力部 | |
56 | + DefaultTableModel tm = new DefaultTableModel(title, 0); | |
57 | + JTable result_ta = new JTable(tm); | |
58 | + | |
59 | + ProgressMonitor pm; // 進捗バー | |
60 | + | |
61 | + /* | |
62 | + * 実測値を入力する部分のJPanelを取得します. | |
63 | + */ | |
64 | + protected JPanel getInputJPanel() | |
65 | + { | |
66 | + JPanel west_center = new JPanel(); // 実測値入力部 | |
67 | + west_center.setLayout(new BorderLayout()); // ウィンドウのWESTに貼り付けるパネルのCENTER | |
68 | + west_center.add(new JLabel("Fragment mass:"), BorderLayout.NORTH); | |
69 | + west_center.add(new JScrollPane(query_ta), BorderLayout.CENTER); // JTextAreaへスクロールバーをつける. | |
70 | + | |
71 | + return west_center; | |
72 | + } | |
73 | + | |
74 | + /* | |
75 | + * 実験的な予測条件を設定する部分のJPanelを取得します. | |
76 | + */ | |
77 | + protected JPanel getExperimentalConditionJPanel() | |
78 | + { | |
79 | + JPanel west_south_north = new JPanel(); // 予測条件入力部 ウィンドウのWESTに貼り付けるパネルのSOUTH | |
80 | + // JComboBoxの初期選択項目を指定する. | |
81 | + pen_cb.setSelectedItem("No"); // Penのデフォルトは"No" | |
82 | + dhex_cb.setSelectedItem("Yes"); // dHexのデフォルトは"Yes" | |
83 | + hex_cb.setSelectedItem("Yes"); // Hexのデフォルトは"Yes" | |
84 | + hexnac_cb.setSelectedItem("Yes"); // HexNAcのデフォルトは"Yes" | |
85 | + penme_cb.setSelectedItem("No"); // PenMeのデフォルトは"No" | |
86 | + dhexme_cb.setSelectedItem("No"); // dHexMeのデフォルトは"No" | |
87 | + hexme_cb.setSelectedItem("No"); // HexMeのデフォルトは"No" | |
88 | + hexnacme_cb.setSelectedItem("No"); // HexNAcMeのデフォルトは"No" | |
89 | + | |
90 | + formula_cb.setSelectedItem("TFIDF"); // スコア計算式のデフォルトは"TFIDF" | |
91 | + | |
92 | + west_south_north.setLayout(new GridLayout(12, 2)); // 縦の数×横の数 | |
93 | + west_south_north.add(new JLabel("Fragment tolerance: ")); | |
94 | + west_south_north.add(psd_tolerance_tf); | |
95 | + west_south_north.add(new JLabel("Precursor mass: ")); | |
96 | + west_south_north.add(precursor_mass_tf); | |
97 | + west_south_north.add(new JLabel("Precursor tolerance: ")); | |
98 | + west_south_north.add(precursor_tolerance_tf); | |
99 | + west_south_north.add(new JLabel("Adduct ion: ")); | |
100 | + west_south_north.add(adduct_cb); | |
101 | + west_south_north.add(new JLabel("Pen: ")); | |
102 | + west_south_north.add(pen_cb); | |
103 | + west_south_north.add(new JLabel("dHex: ")); | |
104 | + west_south_north.add(dhex_cb); | |
105 | + west_south_north.add(new JLabel("Hex: ")); | |
106 | + west_south_north.add(hex_cb); | |
107 | + west_south_north.add(new JLabel("HexNAc: ")); | |
108 | + west_south_north.add(hexnac_cb); | |
109 | + west_south_north.add(new JLabel("PenMe: ")); | |
110 | + west_south_north.add(penme_cb); | |
111 | + west_south_north.add(new JLabel("dHexMe: ")); | |
112 | + west_south_north.add(dhexme_cb); | |
113 | + west_south_north.add(new JLabel("HexMe: ")); | |
114 | + west_south_north.add(hexme_cb); | |
115 | + west_south_north.add(new JLabel("HexNAcMe: ")); | |
116 | + west_south_north.add(hexnacme_cb); | |
117 | + | |
118 | + return west_south_north; | |
119 | + } | |
120 | + | |
121 | + /* | |
122 | + * 実験的な予測条件を設定する部分のJPanelを取得します. | |
123 | + */ | |
124 | + protected JPanel getKnownConditionJPanel() | |
125 | + { | |
126 | + JPanel west_south_center = new JPanel(); | |
127 | + west_south_center.setLayout(new GridBagLayout()); // 入力部を広くするためにGridBagLayoutを用いる. | |
128 | + | |
129 | + GridBagConstraints gb1 = new GridBagConstraints(); // 糖鎖系列選択部のラベル | |
130 | + gb1.gridx = 0; | |
131 | + gb1.gridy = 0; | |
132 | + gb1.anchor = GridBagConstraints.WEST; // 左寄せ | |
133 | + west_south_center.add(new JLabel("Series: "), gb1); | |
134 | + | |
135 | + GridBagConstraints gb2 = new GridBagConstraints(); // 糖鎖系列入力部 | |
136 | + gb2.gridx = 1; | |
137 | + gb2.gridy = 0; | |
138 | + gb2.fill = GridBagConstraints.HORIZONTAL; // 水平方向のみに塗りつぶしを行う. | |
139 | + gb2.weightx = 1.0; // 無いとレイアウトが崩れる. | |
140 | + final JComboBox series_cb = new JComboBox(new String[] // 内部クラスからアクセスするためfinalで宣言 | |
141 | + { | |
142 | + "", | |
143 | + "Globo/Isoglobo", | |
144 | + "Lacto/Neolacto", | |
145 | + "Ganglio/Isoganglio", | |
146 | + "Lactoganglio", | |
147 | + "Gala", | |
148 | + "Muco", | |
149 | + "Arthro", | |
150 | + "Mollu" | |
151 | + }); | |
152 | + series_cb.addActionListener(new ActionListener() // 既知糖鎖構造のテキストエリアに入力する. | |
153 | + { | |
154 | + public void actionPerformed(ActionEvent e) | |
155 | + { | |
156 | + String temp = (String)series_cb.getSelectedItem(); | |
157 | + if (temp.equals("")) | |
158 | + known_gc_tf.setText(""); | |
159 | + else if (temp.equals("Globo/Isoglobo")) | |
160 | + known_gc_tf.setText("Glc-Gal-Gal-GalNAc"); | |
161 | + else if (temp.equals("Lacto/Neolacto")) | |
162 | + known_gc_tf.setText("Glc-Gal-GlcNAc-Gal"); | |
163 | + else if (temp.equals("Ganglio/Isoganglio")) | |
164 | + known_gc_tf.setText("Glc-Gal-GalNAc-Gal"); | |
165 | + else if (temp.equals("Lactoganglio")) | |
166 | + known_gc_tf.setText("Glc-Gal(-GlcNAc)-GalNAc"); | |
167 | + else if (temp.equals("Gala")) | |
168 | + known_gc_tf.setText("Gal-Gal"); | |
169 | + else if (temp.equals("Muco")) | |
170 | + known_gc_tf.setText("Glc-Gal-Gal-Gal"); | |
171 | + else if (temp.equals("Arthro")) | |
172 | + known_gc_tf.setText("Glc-Man-GlcNAc-GalNAc"); | |
173 | + else if (temp.equals("Mollu")) | |
174 | + known_gc_tf.setText("Glc-Man-Man-GlcNAc"); | |
175 | + else | |
176 | + { | |
177 | + System.err.println("unknown glycolipd series:" + temp); | |
178 | + known_gc_tf.setText(""); | |
179 | + } | |
180 | + } | |
181 | + }); | |
182 | + west_south_center.add(series_cb, gb2); | |
183 | + | |
184 | + GridBagConstraints gb3 = new GridBagConstraints(); // 既知糖鎖組成入力部のラベル | |
185 | + gb3.gridx = 0; | |
186 | + gb3.gridy = 1; | |
187 | + gb3.anchor = GridBagConstraints.WEST; // 左寄せ | |
188 | + west_south_center.add(new JLabel("Known: "), gb3); | |
189 | + | |
190 | + GridBagConstraints gb4 = new GridBagConstraints(); // 既知糖鎖組成入力部 | |
191 | + gb4.gridx = 1; | |
192 | + gb4.gridy = 1; | |
193 | + gb4.fill = GridBagConstraints.HORIZONTAL; // 水平方向のみに塗りつぶしを行う. | |
194 | + gb4.weightx = 1.0; // 無いとレイアウトが崩れる. | |
195 | + west_south_center.add(known_gc_tf, gb4); | |
196 | + | |
197 | + GridBagConstraints gb5 = new GridBagConstraints(); // セラミド組成入力部のラベル | |
198 | + gb5.gridx = 0; | |
199 | + gb5.gridy = 2; | |
200 | + gb5.anchor = GridBagConstraints.WEST; // 左寄せ | |
201 | + west_south_center.add(new JLabel("Ceramide: "), gb5); | |
202 | + | |
203 | + GridBagConstraints gb6 = new GridBagConstraints(); // セラミド組成入力部 | |
204 | + gb6.gridx = 1; | |
205 | + gb6.gridy = 2; | |
206 | + gb6.fill = GridBagConstraints.BOTH; // 垂直方向と水平方向の両方に対して塗りつぶしを行う. | |
207 | + gb6.weightx = 1.0; // 無いとレイアウトが崩れる. | |
208 | + west_south_center.add(new JScrollPane(ceramide_tf), gb6); | |
209 | + | |
210 | + return west_south_center; | |
211 | + } | |
212 | + | |
213 | + /* | |
214 | + * 計算機的な予測条件を設定する部分のJPanelを取得します. | |
215 | + */ | |
216 | + protected JPanel getComputationalConditionJPanel() | |
217 | + { | |
218 | + byte[] bytes = {40, 99, 41, 32, 75, 97, 122, 117, 104, 105, 116, 111, 32, 89, 111, 107, 111, 105}; | |
219 | + | |
220 | + // スコアリング選択部分をBorderLayoutのNORTHとし, | |
221 | + // 検索開始ボタンとリセットボタンをSOUTHとして返す. | |
222 | + JPanel west_south_south_north = new JPanel(); // スコアリングの選択 | |
223 | + west_south_south_north.setLayout(new GridLayout(1, 2)); // 縦の数×横の数 | |
224 | + | |
225 | + JPanel west_south_south_south = new JPanel(); // 検索開始ボタンとリセットボタン | |
226 | + west_south_south_south.setLayout(new GridLayout(1, 2)); // 縦の数×横の数 | |
227 | + start.addActionListener(this); // 検索開始ボタンにリスナを付ける. | |
228 | + reset.addActionListener(this); // リセットボタンにリスナを付ける. | |
229 | + | |
230 | + JLabel author = new JLabel(new String(bytes)); | |
231 | + author.setHorizontalAlignment(SwingConstants.CENTER); | |
232 | + author.setForeground(Color.gray); | |
233 | + west_south_south_south.add(author); | |
234 | + west_south_south_south.add(start); | |
235 | + | |
236 | + JPanel west_south_south = new JPanel(); // returnするJPanelインスタンス | |
237 | + west_south_south.setLayout(new BorderLayout()); | |
238 | + west_south_south.add(west_south_south_north, BorderLayout.NORTH); // スコアリングの選択部分を追加 | |
239 | + west_south_south.add(west_south_south_south, BorderLayout.SOUTH); // 検索開始ボタンとリセットボタンを追加 | |
240 | + | |
241 | + return west_south_south; | |
242 | + } | |
243 | + | |
244 | + /* | |
245 | + * 予測条件を設定する部分のJPanelを取得します. | |
246 | + */ | |
247 | + protected JPanel getConditionJPanel() | |
248 | + { | |
249 | + JPanel west_south = new JPanel(); // 予測条件入力部 ウィンドウのWESTに貼り付けるパネルのSOUTH部 | |
250 | + // ウィンドウの左下 | |
251 | + west_south.setLayout(new BorderLayout()); | |
252 | + | |
253 | + west_south.add(getExperimentalConditionJPanel(), BorderLayout.NORTH); // 実験的な予測条件を設定 | |
254 | + west_south.add(getKnownConditionJPanel(), BorderLayout.CENTER); // 実験的な予測条件を設定 | |
255 | + west_south.add(getComputationalConditionJPanel(), BorderLayout.SOUTH); // 計算機的な予測条件を設定 | |
256 | + | |
257 | + return west_south; | |
258 | + } | |
259 | + | |
260 | + /* | |
261 | + * 予測結果を出力する部分のJPanelを取得します. | |
262 | + */ | |
263 | + protected JPanel getOutputJPanel() | |
264 | + { | |
265 | + JPanel center = new JPanel(); // 予想構造出力部 | |
266 | + center.setLayout(new BorderLayout()); // ウィンドウのCENTERに貼り付けるパネル(ウィンドウの右) | |
267 | + this.resetTableColumnSize(); // カラム幅を指定する. | |
268 | + JScrollPane result_sp = new JScrollPane(result_ta); // JTableへスクロールバーをつける. | |
269 | + result_sp.addMouseListener(new MouseListener() // 表を右クリックすると印刷する. | |
270 | + { | |
271 | + public void mouseExited(MouseEvent me){} | |
272 | + public void mouseEntered(MouseEvent me){} | |
273 | + public void mousePressed(MouseEvent me){} | |
274 | + public void mouseReleased(MouseEvent me){} | |
275 | + public void mouseClicked(MouseEvent me) | |
276 | + { | |
277 | + if (me.getButton() == MouseEvent.BUTTON3) // 右クリック | |
278 | + { | |
279 | + try | |
280 | + { | |
281 | + result_ta.print(); // 印刷ダイアログを表示 | |
282 | + } | |
283 | + catch (Exception e) | |
284 | + { | |
285 | + System.out.println("Cannot print: " + e); | |
286 | + } | |
287 | + } | |
288 | + } | |
289 | + }); | |
290 | + center.add(new JLabel("Result:"), BorderLayout.NORTH); | |
291 | + center.add(result_sp, BorderLayout.CENTER); | |
292 | + | |
293 | + return center; | |
294 | + } | |
295 | + | |
296 | + /* | |
297 | + * テーブルのカラム幅を調節します. | |
298 | + */ | |
299 | + protected void resetTableColumnSize() | |
300 | + { | |
301 | + DefaultTableCellRenderer tr = new DefaultTableCellRenderer(); // カラムを右寄せするインスタンス | |
302 | + tr.setHorizontalAlignment(SwingConstants.RIGHT); | |
303 | + | |
304 | + TableColumn tc0 = result_ta.getColumnModel().getColumn(0); // スコアのカラム(0番目)のサイズを固定 | |
305 | + tc0.setMinWidth(70); | |
306 | + tc0.setMaxWidth(70); | |
307 | + tc0.setCellRenderer(tr); // カラムを右寄せする | |
308 | + // 候補構造のカラムはサイズを指定しない. | |
309 | + TableColumn tc2 = result_ta.getColumnModel().getColumn(2); // 占有率のカラム(2番目)のサイズを固定 | |
310 | + tc2.setMinWidth(70); | |
311 | + tc2.setMaxWidth(70); | |
312 | + tc2.setCellRenderer(tr); // カラムを右寄せする | |
313 | + TableColumn tc3 = result_ta.getColumnModel().getColumn(3); // m/zのカラム(3番目)のサイズを固定 | |
314 | + tc3.setMinWidth(80); | |
315 | + tc3.setMaxWidth(80); | |
316 | + tc3.setCellRenderer(tr); // カラムを右寄せする | |
317 | + } | |
318 | + | |
319 | + public PredictionGUI() throws Exception | |
320 | + { | |
321 | + jf.setLayout(new BorderLayout()); // ウィンドウへのコンポーネントの貼り付けは | |
322 | + // BorderLayoutを用いる. | |
323 | + JPanel west = new JPanel(); // ウィンドウのWESTに貼り付けるパネル(ウィンドウの左) | |
324 | + west.setLayout(new BorderLayout()); | |
325 | + west.add(getInputJPanel(), BorderLayout.CENTER); // 実測値を入力する部分をWESTのCENTERに配置 | |
326 | + west.add(getConditionJPanel(), BorderLayout.SOUTH); // 予測条件を設定する部分をWESTのNORTHに配置 | |
327 | + jf.getContentPane().add(west, BorderLayout.WEST); | |
328 | + | |
329 | + jf.getContentPane().add(getOutputJPanel(), BorderLayout.CENTER); // 予測結果を出力する部分をCENTERに配置 | |
330 | + | |
331 | + try // タスクトレイにアイコンを追加する. | |
332 | + { | |
333 | + SystemTray st = SystemTray.getSystemTray(); | |
334 | + ImageIcon ii = (ImageIcon)UIManager.getIcon("FileView.computerIcon"); // IconからImageIconへ型変換 | |
335 | + TrayIcon ti = new TrayIcon(ii.getImage()); | |
336 | + ti.addActionListener(new ActionListener() // トレイアイコンをダブルクリックすることで, | |
337 | + { // ウィンドウの表示/非表示を切り替える. | |
338 | + public void actionPerformed(ActionEvent e) | |
339 | + { | |
340 | + if (jf.isShowing()) // ウィンドウが表示されている場合は, | |
341 | + jf.setVisible(false); // 非表示にする. | |
342 | + else | |
343 | + { // 表示されていない場合は, | |
344 | + jf.setVisible(true); // 表示した後, | |
345 | + jf.toFront(); // このウィンドウにフォーカスを当てる. | |
346 | + } | |
347 | + } | |
348 | + }); | |
349 | + st.add(ti); | |
350 | + } | |
351 | + catch (Exception e) | |
352 | + { | |
353 | + System.err.println("Cannot use SystemTray: " + e); | |
354 | + } | |
355 | + | |
356 | + try // Swingから,Windowsのデザインへ変更 | |
357 | + { | |
358 | + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); // 外観を設定 | |
359 | + SwingUtilities.updateComponentTreeUI(jf); // 外観変更 | |
360 | + } | |
361 | + catch (Exception e) | |
362 | + { | |
363 | + System.err.println("Cannot use WindowsLookAndFeel: " + e); | |
364 | + } | |
365 | + | |
366 | + jf.setSize(900,700); | |
367 | + jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ウインドウが閉じられた時に終了 | |
368 | + jf.setVisible(true); // 表示 | |
369 | + } | |
370 | + | |
371 | + /* | |
372 | + * Swingのアクションイベントが発生した時の動作を指定します. | |
373 | + * @parm ae 取得したアクションイベント | |
374 | + */ | |
375 | + public void actionPerformed(ActionEvent ae) | |
376 | + { | |
377 | + if (ae.getSource() == start) // Startボタンが押された時 | |
378 | + { | |
379 | + DefaultTableModel tm = (DefaultTableModel)result_ta.getModel(); // テーブルモデルを取得し, | |
380 | + tm.setRowCount(0); // 表の内容を削除する. | |
381 | + start.setEnabled(false); // ボタンを押せなくする. | |
382 | + reset.setEnabled(false); | |
383 | + | |
384 | + try // ProgressMonitorのタイトルなどを | |
385 | + { // 日本語から英語名に変更 | |
386 | + UIManager.put( "ProgressMonitor.progressText", "Progress Monitor" ); // ウィンドウ名 | |
387 | + UIManager.put( "OptionPane.cancelButtonText", "Cancel" ); // キャンセルボタン名 | |
388 | + } | |
389 | + catch (Exception e) | |
390 | + { | |
391 | + System.err.println("ProgressMonitor connot edit: " + e); | |
392 | + } | |
393 | + // 表示する文字列のテンプレート | |
394 | + String length = "Creating candidate compositions from precursor and fragment mass."; | |
395 | + pm = new ProgressMonitor(jf, "Calculating...", length, 0, 100); // 進捗バー | |
396 | + pm.setMillisToDecideToPopup(0); | |
397 | + pm.setMillisToPopup(0); | |
398 | + pm.setProgress(0); // 監視対象インスタンスから変数を取得 | |
399 | + Thread th = new Thread(this); | |
400 | + th.start(); | |
401 | + } | |
402 | + else if (ae.getSource() == reset) // Resetボタンが押された時 | |
403 | + { | |
404 | + query_ta.setText(""); // フラグメント分子量の内容を削除 | |
405 | + DefaultTableModel tm = (DefaultTableModel)result_ta.getModel(); // テーブルモデルを取得し, | |
406 | + tm.setRowCount(0); // 表の内容を削除する. | |
407 | + } | |
408 | + } | |
409 | + | |
410 | + /* | |
411 | + * 監視対象が更新された時の動作を指定します. | |
412 | + * @parm ae 取得したアクションイベント | |
413 | + */ | |
414 | + public void update(Observable ob, Object arg) | |
415 | + { | |
416 | + if (ob instanceof Prediction) // Predictionクラスのインスタンスかを判定 | |
417 | + { | |
418 | + Prediction temp = (Prediction)ob; // Observableインスタンスを型変換する. | |
419 | + pm.setProgress(temp.percent); // 監視対象インスタンスから変数を取得 | |
420 | + pm.setNote(arg.toString()); // 進捗情報の表示 | |
421 | + | |
422 | + StringBuilder line = new StringBuilder(32); // コマンドラインに表示する文字列 | |
423 | + MemoryMXBean mm = ManagementFactory.getMemoryMXBean(); | |
424 | + MemoryUsage mu = mm.getHeapMemoryUsage(); | |
425 | + line.append(" Memory: "); | |
426 | + line.append(String.format("%.1f/", mu.getUsed() / 1024.0 / 1024)); | |
427 | + line.append(String.format("%.1fMB", mu.getMax() / 1024.0 / 1024)); | |
428 | + | |
429 | + System.out.println(arg + " " + line); // 進捗情報の表示 | |
430 | + | |
431 | + if (pm.isCanceled()) // ProgressMonitorの | |
432 | + { // キャンセルボタンが押された時 | |
433 | + pm.close(); // ProgressMonitorウィンドウを閉じる. | |
434 | + temp.flag = false; // 断片化処理を抜ける. | |
435 | + } | |
436 | + } | |
437 | + else | |
438 | + System.out.println("ERROR: unknown incetance of observerable class."); | |
439 | + } | |
440 | + | |
441 | + /* | |
442 | + * Startをクリックした時に実行されるスレッド | |
443 | + */ | |
444 | + public void run() | |
445 | + { | |
446 | + try | |
447 | + { | |
448 | + Prediction pd_agg = new Prediction(); // 継承の代わりに集約を用いる. | |
449 | + pd_agg.addObserver(this); // 進行状況をこのクラスへ伝えるために,このクラスをオブザーバとする. | |
450 | + // テキストエリアから実測値を取得 | |
451 | + String[] strs = query_ta.getText().split("[^\\.\\d]"); // '.'と数字以外の文字列で切り出す. | |
452 | + java.util.List<Double> massli = new ArrayList<Double>(); | |
453 | + for (String str : strs) | |
454 | + { | |
455 | + try | |
456 | + { | |
457 | + massli.add(Double.parseDouble(str)); | |
458 | + } | |
459 | + catch (Exception e) // 数字以外の文字が入っていた場合の時, | |
460 | + { // 無視したことを報告する. | |
461 | + System.err.println(e); | |
462 | + } | |
463 | + } | |
464 | + double[] frags = new double[massli.size()]; // Listと同じ大きさの配列を用意する. | |
465 | + Iterator<Double> massit = massli.iterator(); | |
466 | + for (int i = 0; massit.hasNext(); i++) // double[]型のfragsへ配列の型変換 | |
467 | + frags[i] = massit.next(); | |
468 | + pd_agg.setFragments(frags); // フラグメントの実測値の配列を登録 | |
469 | + | |
470 | + try // プレカーサーマスを登録 | |
471 | + { | |
472 | + pd_agg.setPrecursorMass(Double.parseDouble(precursor_mass_tf.getText())); | |
473 | + } | |
474 | + catch (Exception e) // プレカーサーマスを登録しなかった場合, | |
475 | + { // PSDフラグメントの最大値をプレカーサーマスとして計算 | |
476 | + System.err.println("Precursor mass is null."); | |
477 | + } | |
478 | + | |
479 | + try // プレカーサーマスの許容誤差を登録 | |
480 | + { | |
481 | + pd_agg.setMsTolerance(Double.parseDouble(precursor_tolerance_tf.getText())); // 許容誤差を格納 | |
482 | + } | |
483 | + catch (Exception e) | |
484 | + { | |
485 | + throw new Exception("'Precursor tolerance' contains error.\n" + e); | |
486 | + } | |
487 | + | |
488 | + try // PSDフラグメントの許容誤差を登録 | |
489 | + { | |
490 | + pd_agg.setPsdTolerance(Double.parseDouble(psd_tolerance_tf.getText())); // 許容誤差を格納 | |
491 | + } | |
492 | + catch (Exception e) | |
493 | + { | |
494 | + throw new Exception("'PSD tolerance' contains error.\n" + e); | |
495 | + } | |
496 | + | |
497 | + try // 付加イオンを登録 | |
498 | + { // 選択された付加イオンを取得する. | |
499 | + String temp = (String)adduct_cb.getSelectedItem(); // 表の部分でm/zを取得するのに必要なため, | |
500 | + if (temp.equals("Na+")) // adductはグローバル変数としている. | |
501 | + adduct = MassCalc.Na_ION; | |
502 | + else if (temp.equals("H+")) | |
503 | + adduct = MassCalc.H_ION; | |
504 | + else if (temp.equals("Li+")) | |
505 | + adduct = MassCalc.Li_ION; | |
506 | + else if (temp.equals("K+")) | |
507 | + adduct = MassCalc.K_ION; | |
508 | + else if (temp.equals("H-")) | |
509 | + adduct = MassCalc.H_NION; | |
510 | + else if (temp.equals("No adduct")) | |
511 | + adduct = ""; | |
512 | + else | |
513 | + throw new Exception(temp + " is unknown adduct ion."); | |
514 | + | |
515 | + pd_agg.setAdduct(adduct); | |
516 | + } | |
517 | + catch (Exception e) | |
518 | + { | |
519 | + throw new Exception("'Adduct ion' contains error.\n" + e); | |
520 | + } | |
521 | + | |
522 | + try // 既知構造を登録 | |
523 | + { | |
524 | + pd_agg.setGlycan(new Glycan(known_gc_tf.getText())); // Linucs形式から既知構造を登録 | |
525 | + } | |
526 | + catch (Exception e1) // Linucs形式の読み込みに失敗した場合, | |
527 | + { // ノーマル形式の読み込みを試す. | |
528 | + try | |
529 | + { | |
530 | + GlycanTools gi = new GlycanTools(); | |
531 | + pd_agg.setGlycan(gi.readNormalFormat(known_gc_tf.getText())); // 既知構造を登録 | |
532 | + } | |
533 | + catch (Exception e2) | |
534 | + { | |
535 | + throw new Exception("'Known structure' contains error.\n" + e1 + e2); | |
536 | + } | |
537 | + } | |
538 | + | |
539 | + try // 各糖の最大数を登録 | |
540 | + { | |
541 | + pd_agg.setMax("pen", ((String)pen_cb.getSelectedItem()).equals("Yes")); | |
542 | + pd_agg.setMax("dhex", ((String)dhex_cb.getSelectedItem()).equals("Yes")); | |
543 | + pd_agg.setMax("hex", ((String)hex_cb.getSelectedItem()).equals("Yes")); | |
544 | + pd_agg.setMax("hexnac", ((String)hexnac_cb.getSelectedItem()).equals("Yes")); | |
545 | + pd_agg.setMax("penme", ((String)penme_cb.getSelectedItem()).equals("Yes")); | |
546 | + pd_agg.setMax("dhexme", ((String)dhexme_cb.getSelectedItem()).equals("Yes")); | |
547 | + pd_agg.setMax("hexme", ((String)hexme_cb.getSelectedItem()).equals("Yes")); | |
548 | + pd_agg.setMax("hexnacme", ((String)hexnacme_cb.getSelectedItem()).equals("Yes")); | |
549 | + } | |
550 | + catch (Exception e) | |
551 | + { | |
552 | + throw new Exception("'max' contains error.\n" + e); | |
553 | + } | |
554 | + | |
555 | + try // セラミド組成を登録 | |
556 | + { | |
557 | + java.util.List<String> ceramide = new ArrayList<String>(); // 既知の長鎖塩基組成を格納する. | |
558 | + java.util.List<String> lcb = new ArrayList<String>(); // 既知の長鎖塩基組成を格納する. | |
559 | + java.util.List<String> fa = new ArrayList<String>(); // 既知の脂肪酸組成を格納する. | |
560 | + | |
561 | + for (String str : ceramide_tf.getText().split("[^\\w:-]")) // 単語構成文字と':','-'以外の文字列で分割 | |
562 | + if (str.matches("^[dt][ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // セラミドの場合 | |
563 | + ceramide.add(str); | |
564 | + else if (str.matches("^[dt][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 長鎖塩基の場合 | |
565 | + lcb.add(str); | |
566 | + else if (str.matches("^[ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 脂肪酸の場合 | |
567 | + fa.add(str); | |
568 | + | |
569 | + pd_agg.setCeramide(ceramide); // セラミド組成を登録 | |
570 | + pd_agg.setLongChainBase(lcb); // 長鎖塩基組成を登録 | |
571 | + pd_agg.setFattyAcid(fa); // 脂肪酸組成を登録 | |
572 | + } | |
573 | + catch (Exception e) | |
574 | + { | |
575 | + throw new Exception("'Ceramide' contains error.\n" + e); | |
576 | + } | |
577 | + | |
578 | + try // スコアリングの式を登録 | |
579 | + { | |
580 | + String temp = (String)formula_cb.getSelectedItem(); // 選択されたスコアリング式を取得 | |
581 | + if (temp.equals("POSITIVE")) | |
582 | + pd_agg.setScoringFormula(Candidate.POSITIVE_SCORING); | |
583 | + else if (temp.equals("TFIDF")) | |
584 | + pd_agg.setScoringFormula(Candidate.TFIDF_SCORING); | |
585 | + else if (temp.equals("PENALTY01")) | |
586 | + pd_agg.setScoringFormula(Candidate.PENALTY01_SCORING); | |
587 | + else if (temp.equals("PENALTY001")) | |
588 | + pd_agg.setScoringFormula(Candidate.PENALTY001_SCORING); | |
589 | + else if (temp.equals("PMF")) | |
590 | + pd_agg.setScoringFormula(Candidate.PMF_SCORING); | |
591 | + else if (temp.equals("GEOMETRICAVG")) | |
592 | + pd_agg.setScoringFormula(Candidate.GEOMETRICAVG_SCORING); | |
593 | + else | |
594 | + throw new Exception(temp + " is unknown adduct ion."); | |
595 | + } | |
596 | + catch (Exception e) | |
597 | + { | |
598 | + throw new Exception("'Scoring' contains error.\n" + e); | |
599 | + } | |
600 | + | |
601 | + try // 出現確率分布の | |
602 | + { // ウィンドウサイズを登録 | |
603 | + pd_agg.setWindowSize(1); | |
604 | + } | |
605 | + catch (Exception e) | |
606 | + { | |
607 | + throw new Exception("'Window size' contains error.\n" + e); | |
608 | + } | |
609 | + | |
610 | + java.util.List<? extends Candidate> cds = pd_agg.getPrediction(); // 出力部 | |
611 | + Iterator<? extends Candidate> it = cds.iterator(); | |
612 | + DefaultTableModel tm = new DefaultTableModel(title, 0); | |
613 | + for (int i = 0; i < 50 && it.hasNext(); i++) // 上位50候補を表示 | |
614 | + { | |
615 | + Candidate cd = it.next(); | |
616 | + | |
617 | + String[] table = new String[4]; // カラムの追加時は, | |
618 | + table[0] = String.format("%.4f", cd.getScore()); // 配列の大きさに注意 | |
619 | + | |
620 | + try | |
621 | + { | |
622 | + table[1] = cd.toNormalFormat(); // ノーマルのフォーマットで格納 | |
623 | + } | |
624 | + catch (Exception e) | |
625 | + { | |
626 | + table[1] = cd.toString(); // 二分岐以上はLinucs形式で格納 | |
627 | + } | |
628 | + | |
629 | + table[2] = String.format("%.4f", cd.getOccupancy()); | |
630 | + table[3] = String.format("%.4f", cd.getMass(monoavg, adduct)); | |
631 | + tm.addRow(table); | |
632 | + } | |
633 | + result_ta.setModel(tm); | |
634 | + RowSorter<TableModel> rs = new TableRowSorter<TableModel>(tm); // ソート可能なテーブルにする. | |
635 | + result_ta.setRowSorter(rs); | |
636 | + this.resetTableColumnSize(); // カラム幅を指定する. | |
637 | + | |
638 | + java.awt.Toolkit.getDefaultToolkit().beep(); // 終了する時にビープ音を鳴らす. | |
639 | + | |
640 | + UIManager.put("OptionPane.messageDialogTitle", "Messege"); // "タイトルを"Messege"に変更する. | |
641 | + UIManager.put("OptionPane.okButtonText", "OK"); // "了解"の部分を"OK"に変更する. | |
642 | + | |
643 | + JOptionPane.showMessageDialog(jf, "Calclation is finished.\n" | |
644 | + + pm.getNote() + "\n" | |
645 | + + "Candidate structure: " + cds.size()); | |
646 | + start.setEnabled(true); // ボタンを押せるようにする. | |
647 | + reset.setEnabled(true); | |
648 | + } | |
649 | + catch (Exception e) // 処理の途中で例外が発生した場合, | |
650 | + { // 警告ダイアログを表示し処理を中断 | |
651 | + UIManager.put("OptionPane.messageDialogTitle", "Messege"); // "タイトルを"Messege"に変更する. | |
652 | + UIManager.put("OptionPane.okButtonText", "OK"); // "了解"の部分を"OK"に変更する. | |
653 | + JOptionPane.showMessageDialog(jf, "ERROR: " + e); | |
654 | + e.printStackTrace(); | |
655 | + start.setEnabled(true); // ボタンを押せるようにする. | |
656 | + reset.setEnabled(true); | |
657 | + } | |
658 | + } | |
659 | + | |
660 | + public static void main(String[] args) throws Exception | |
661 | + { | |
662 | + new PredictionGUI(); | |
663 | + } | |
664 | +} |
@@ -0,0 +1,314 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | +import java.io.*; | |
5 | + | |
6 | +/** | |
7 | + * 実測の<I>m/z</I> からメチル化糖鎖,メチル化糖脂質の組成を予測するクラスです. | |
8 | + * @author 横井一仁 | |
9 | + * @version 20090128 | |
10 | + */ | |
11 | +public class CompositionToolsMe extends CompositionTools | |
12 | +{ | |
13 | + /** | |
14 | + * 予測された組成を返します. | |
15 | + * @return 質量誤差の少ない順に格納して返します. | |
16 | + */ | |
17 | + public List<Composition> getComposition() throws Exception | |
18 | + { | |
19 | + al_cp.clear(); // クラスの再利用の時のために要素を全て削除する. | |
20 | + | |
21 | + Composition cp = new Composition(); | |
22 | + if (known_cp != null) // 既知組成が登録されている場合 | |
23 | + cp.addAll(known_cp); | |
24 | + else if (known_gc != null) // 既知構造が登録されている場合 | |
25 | + cp.addAll(new Composition(known_gc)); | |
26 | + | |
27 | + // 継承による変更部分 | |
28 | + Composition temp_me = new Composition(cp); // 新たなインスタンスを作成する. | |
29 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
30 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
31 | + temp_me.add("me"); | |
32 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
33 | + // 継承による変更部分(ここまで) | |
34 | + | |
35 | + if (ceramide != null && ceramide.size() != 0) // セラミドが登録されている場合 | |
36 | + { | |
37 | + if (mass_a > mass_t) | |
38 | + addCer(cp); // セラミドから検索する. | |
39 | + } | |
40 | + else // セラミドが登録されていない場合は,糖鎖モードとする. | |
41 | + { | |
42 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
43 | + al_cp.add(cp); | |
44 | + else if (mass_a > mass_t) | |
45 | + addHex(cp); // Hexから検索する. | |
46 | + } | |
47 | + | |
48 | + final double temp_a = mass_a; // 内部クラスで用いる変数は,finalで宣言する必要がある. | |
49 | + Collections.sort(al_cp, new Comparator<Composition>() // ソートを行う. | |
50 | + { | |
51 | + public int compare(Composition cp1, Composition cp2) | |
52 | + { | |
53 | + double sub = 0.0; | |
54 | + | |
55 | + try | |
56 | + { | |
57 | + Composition temp1 = new Composition(cp1); // 新たなインスタンスを作成する. | |
58 | + int count1 = temp1.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
59 | + for (int i = 0; i < count1; i++) // OH基の数だけMe基を付加する. | |
60 | + temp1.add("me"); | |
61 | + | |
62 | + Composition temp2 = new Composition(cp2); // 新たなインスタンスを作成する. | |
63 | + int count2 = temp2.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
64 | + for (int i = 0; i < count2; i++) // OH基の数だけMe基を付加する. | |
65 | + temp2.add("me"); | |
66 | + | |
67 | + sub = Math.abs(temp1.getMass(monoavg, adduct) - temp_a) | |
68 | + - Math.abs(temp2.getMass(monoavg, adduct) - temp_a); | |
69 | + } | |
70 | + catch (Exception e) | |
71 | + { | |
72 | + | |
73 | + } | |
74 | + | |
75 | + return (int)(sub*1024); // compareメソッドの返り値がint型しか受け付けないので1024倍して精度を上げる. | |
76 | + } | |
77 | + }); | |
78 | + | |
79 | + ceramide.clear(); // 次回の実行する時に同じ組成を2回追加しないように | |
80 | + lcb.clear(); // 既知のセラミド組成,長鎖塩基組成,脂肪酸組成を削除しておく. | |
81 | + fa.clear(); // (これにより,次回実行時に通常通りセラミドを追加できる) | |
82 | + | |
83 | + return al_cp; | |
84 | + } | |
85 | + | |
86 | + protected void addCer(Composition cp) throws Exception | |
87 | + { | |
88 | + for (String str : ceramide) | |
89 | + { | |
90 | + Composition temp = new Composition(str); // セラミドを登録. | |
91 | + temp.addAll(cp); | |
92 | + | |
93 | + // 継承による変更部分 | |
94 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
95 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
96 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
97 | + temp_me.add("me"); | |
98 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
99 | + // 継承による変更部分(ここまで) | |
100 | + | |
101 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
102 | + al_cp.add(temp); | |
103 | + else | |
104 | + addHex(temp); | |
105 | + } | |
106 | + } | |
107 | + | |
108 | + protected void addHex(Composition cp) throws Exception | |
109 | + { | |
110 | + addHexNAc(cp); // HexNAcを追加した構造 | |
111 | + | |
112 | + Composition temp = new Composition(cp); | |
113 | + if (Collections.frequency(temp,"hex") < hex_max) // 要素を探索し,個数を数える. | |
114 | + { | |
115 | + temp.add("hex"); | |
116 | + | |
117 | + // 継承による変更部分 | |
118 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
119 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
120 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
121 | + temp_me.add("me"); | |
122 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
123 | + // 継承による変更部分(ここまで) | |
124 | + | |
125 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
126 | + al_cp.add(temp); | |
127 | + else if (mass_a > mass_t) | |
128 | + addHex(temp); | |
129 | + } | |
130 | + } | |
131 | + | |
132 | + protected void addHexNAc(Composition cp) throws Exception | |
133 | + { | |
134 | + adddHex(cp); // dHexを追加した構造 | |
135 | + | |
136 | + Composition temp = new Composition(cp); | |
137 | + if (Collections.frequency(temp,"hexnac") < hexnac_max) // 要素を探索し,個数を数える. | |
138 | + { | |
139 | + temp.add("hexnac"); | |
140 | + | |
141 | + // 継承による変更部分 | |
142 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
143 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
144 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
145 | + temp_me.add("me"); | |
146 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
147 | + // 継承による変更部分(ここまで) | |
148 | + | |
149 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
150 | + al_cp.add(temp); | |
151 | + else if (mass_a > mass_t) | |
152 | + addHexNAc(temp); | |
153 | + } | |
154 | + } | |
155 | + | |
156 | + protected void adddHex(Composition cp) throws Exception | |
157 | + { | |
158 | + addPen(cp); // dHexMeを追加した構造 | |
159 | + | |
160 | + Composition temp = new Composition(cp); | |
161 | + if (Collections.frequency(cp,"dhex") < dhex_max) // 要素を探索し,個数を数える. | |
162 | + { | |
163 | + temp.add("dhex"); | |
164 | + | |
165 | + // 継承による変更部分 | |
166 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
167 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
168 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
169 | + temp_me.add("me"); | |
170 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
171 | + // 継承による変更部分(ここまで) | |
172 | + | |
173 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
174 | + al_cp.add(temp); | |
175 | + else if (mass_a > mass_t) | |
176 | + adddHex(temp); | |
177 | + } | |
178 | + } | |
179 | + | |
180 | + protected void addPen(Composition cp) throws Exception | |
181 | + { | |
182 | + addKDN(cp); // KDNを追加した構造 | |
183 | + | |
184 | + Composition temp = new Composition(cp); | |
185 | + if (Collections.frequency(temp,"pen") < pen_max) // 要素を探索し,個数を数える. | |
186 | + { | |
187 | + temp.add("pen"); | |
188 | + | |
189 | + // 継承による変更部分 | |
190 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
191 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
192 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
193 | + temp_me.add("me"); | |
194 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
195 | + // 継承による変更部分(ここまで) | |
196 | + | |
197 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
198 | + al_cp.add(temp); | |
199 | + else if (mass_a > mass_t) | |
200 | + addPen(temp); | |
201 | + } | |
202 | + } | |
203 | + | |
204 | + protected void addKDN(Composition cp) throws Exception | |
205 | + { | |
206 | + addNeuAc(cp); // NeuAcを追加した構造 | |
207 | + | |
208 | + Composition temp = new Composition(cp); | |
209 | + if (Collections.frequency(temp,"kdn") < kdn_max) // 要素を探索し,個数を数える. | |
210 | + { | |
211 | + temp.add("kdn"); | |
212 | + | |
213 | + // 継承による変更部分 | |
214 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
215 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
216 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
217 | + temp_me.add("me"); | |
218 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
219 | + // 継承による変更部分(ここまで) | |
220 | + | |
221 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
222 | + al_cp.add(temp); | |
223 | + else if (mass_a > mass_t) | |
224 | + addKDN(temp); | |
225 | + } | |
226 | + } | |
227 | + | |
228 | + protected void addNeuAc(Composition cp) throws Exception | |
229 | + { | |
230 | + addNeuGc(cp); // NeuGcを追加した構造 | |
231 | + | |
232 | + Composition temp = new Composition(cp); | |
233 | + if (Collections.frequency(cp,"neuac") < neuac_max) // 要素を探索し,個数を数える. | |
234 | + { | |
235 | + temp.add("neuac"); | |
236 | + | |
237 | + // 継承による変更部分 | |
238 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
239 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
240 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
241 | + temp_me.add("me"); | |
242 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
243 | + // 継承による変更部分(ここまで) | |
244 | + | |
245 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
246 | + al_cp.add(temp); | |
247 | + else if (mass_a > mass_t) | |
248 | + addNeuAc(temp); | |
249 | + } | |
250 | + } | |
251 | + | |
252 | + protected void addNeuGc(Composition cp) throws Exception | |
253 | + { | |
254 | + Composition temp = new Composition(cp); | |
255 | + | |
256 | + if (Collections.frequency(temp,"neugc") < neugc_max) // 要素を探索し,個数を数える. | |
257 | + { | |
258 | + temp.add("neugc"); | |
259 | + | |
260 | + // 継承による変更部分 | |
261 | + Composition temp_me = new Composition(temp); // 新たなインスタンスを作成する. | |
262 | + int count = temp_me.countHydroxy(); // メチル基が附加できるOH基の数を数える. | |
263 | + for (int i = 0; i < count; i++) // OH基の数だけMe基を付加する. | |
264 | + temp_me.add("me"); | |
265 | + double mass_t = temp_me.getMass(monoavg, adduct); | |
266 | + // 継承による変更部分(ここまで) | |
267 | + | |
268 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
269 | + al_cp.add(temp); | |
270 | + else if (mass_a > mass_t) | |
271 | + addNeuGc(temp); | |
272 | + } | |
273 | + } | |
274 | + | |
275 | + /** | |
276 | + * メチル化糖の組成予測テスト | |
277 | + */ | |
278 | + private static void testPermetylatedGlycan() throws Exception | |
279 | + { | |
280 | + CompositionToolsMe cm = new CompositionToolsMe(); | |
281 | + cm.setCeramide(30, 44, 0); | |
282 | + cm.setMass(1746.0537); | |
283 | + for (Composition cp : cm.getComposition()) | |
284 | + System.out.println(cp); | |
285 | + } | |
286 | + | |
287 | + /** | |
288 | + * メチル化したガングリオシドの組成予測テスト | |
289 | + */ | |
290 | + private static void testPermethylatedGanglioside(double mass) throws Exception | |
291 | + { | |
292 | + double start = new Date().getTime(); | |
293 | + | |
294 | + CompositionToolsMe ci = new CompositionToolsMe(); | |
295 | + ci.setMsTolerance(0.5); | |
296 | + ci.setComposition(new Composition("neuac")); | |
297 | + ci.setCeramide(30, 44, 0); | |
298 | + ci.setMass(mass); | |
299 | + ci.setMax("hex", true); // 各糖の有無を指定する. | |
300 | + ci.setMax("hexnac", true); | |
301 | + ci.setMax("dhex", true); | |
302 | + ci.setMax("pen", true); | |
303 | + ci.setMax("kdn", false); | |
304 | + ci.setMax("neuac", true); | |
305 | + ci.setMax("neugc", false); | |
306 | + | |
307 | + List<Composition> li = ci.getComposition(); | |
308 | + for (Composition cp : li) | |
309 | + System.out.println(cp); | |
310 | + | |
311 | + System.out.println("予測組成数: " + li.size()); | |
312 | + System.out.println("計算時間: " + (new Date().getTime() - start)/1000 + "sec"); | |
313 | + } | |
314 | +} |
@@ -0,0 +1,444 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | +import java.io.*; | |
5 | +import javax.servlet.*; | |
6 | +import javax.servlet.http.*; | |
7 | + | |
8 | +/** | |
9 | + * 実測の<I>m/z</I> から糖鎖,糖脂質の組成を予測するServletクラスです. | |
10 | + * @author 横井一仁 | |
11 | + * @version 20090102 | |
12 | + */ | |
13 | +public class CompositionServlet extends HttpServlet | |
14 | +{ | |
15 | + public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException | |
16 | + { | |
17 | + response.setContentType("text/html"); | |
18 | + PrintWriter out = response.getWriter(); | |
19 | + | |
20 | + try | |
21 | + { | |
22 | + double mass_a, tolerance; // 実測m/z,許容誤差 | |
23 | + Composition known_cp; // 既知組成 | |
24 | + String adduct; // 付加イオン(デフォルトはNa+) | |
25 | + boolean monoavg; // Monoisotopic(ture),Averaget(false) | |
26 | + boolean present_hex, present_hexnac, present_dhex, present_pen; // 各糖の存在 | |
27 | + boolean present_hexme, present_hexnacme, present_dhexme, present_penme; // 各糖の存在 | |
28 | + int select; // 0…セラミド組成により計算,1…セラミドの炭素数により計算,2…糖鎖のみの分子として計算 | |
29 | + String known_cer; // セラミド組成を格納する.(セラミド,長鎖塩基,脂肪酸の区別はしない) | |
30 | + | |
31 | + try | |
32 | + { | |
33 | + mass_a = Double.parseDouble(request.getParameter("mass_a")); // 引数がない場合の初期値 | |
34 | + | |
35 | + if (mass_a > 3000) // m/z3000以上は計算しない | |
36 | + mass_a = 0; | |
37 | + } | |
38 | + catch (Exception e) | |
39 | + { | |
40 | + mass_a = 1493.8; | |
41 | + } | |
42 | + try | |
43 | + { | |
44 | + tolerance = Double.parseDouble(request.getParameter("tolerance")); | |
45 | + } | |
46 | + catch (Exception e) | |
47 | + { | |
48 | + tolerance = 1.0; | |
49 | + } | |
50 | + try | |
51 | + { | |
52 | + String temp = request.getParameter("known_cp"); | |
53 | + try | |
54 | + { | |
55 | + known_cp = new Composition(new Glycan(temp)); // Linucs形式として格納してみる. | |
56 | + } | |
57 | + catch (Exception e) | |
58 | + { | |
59 | + known_cp = new Composition(temp); // Linucs形式の格納に失敗したら,組成として格納 | |
60 | + } | |
61 | + } | |
62 | + catch (Exception e) | |
63 | + { | |
64 | + known_cp = new Composition("hex"); | |
65 | + } | |
66 | + try | |
67 | + { | |
68 | + adduct = request.getParameter("adduct"); | |
69 | + | |
70 | + if (adduct == null) // 何も指定されなかった場合, | |
71 | + adduct = MassCalc.Na_ION; // 左のイオンを初期付加イオンとする. | |
72 | + } | |
73 | + catch (Exception e) | |
74 | + { | |
75 | + adduct = MassCalc.Na_ION; // 左のイオンを初期付加イオンとする. | |
76 | + } | |
77 | + try | |
78 | + { | |
79 | + String temp = request.getParameter("monoavg"); | |
80 | + if (temp.equals("mono")) | |
81 | + monoavg = true; | |
82 | + else if (temp.equals("avg")) | |
83 | + monoavg = false; | |
84 | + else | |
85 | + monoavg = true; // その他の場合Monoisotopicとする. | |
86 | + } | |
87 | + catch (Exception e) | |
88 | + { | |
89 | + monoavg = true; // その他の場合Monoisotopicとする. | |
90 | + } | |
91 | + try | |
92 | + { | |
93 | + present_pen = request.getParameter("present_pen").equals("yes"); | |
94 | + present_dhex = request.getParameter("present_dhex").equals("yes"); | |
95 | + present_hex = request.getParameter("present_hex").equals("yes"); | |
96 | + present_hexnac = request.getParameter("present_hexnac").equals("yes"); | |
97 | + present_penme = request.getParameter("present_penme").equals("yes"); | |
98 | + present_dhexme = request.getParameter("present_dhexme").equals("yes"); | |
99 | + present_hexme = request.getParameter("present_hexme").equals("yes"); | |
100 | + present_hexnacme = request.getParameter("present_hexnacme").equals("yes"); | |
101 | + } | |
102 | + catch (Exception e) | |
103 | + { | |
104 | + present_pen = false; // 各糖が存在するかしないかを指定 | |
105 | + present_dhex = true; | |
106 | + present_hex = true; | |
107 | + present_hexnac = true; | |
108 | + present_penme = false; | |
109 | + present_dhexme = false; | |
110 | + present_hexme = false; | |
111 | + present_hexnacme = false; | |
112 | + } | |
113 | + try | |
114 | + { // 0…セラミド組成により計算,1…セラミドの炭素数により計算,2…糖鎖のみの分子として計算 | |
115 | + select = Integer.parseInt(request.getParameter("select")); | |
116 | + } | |
117 | + catch (Exception e) | |
118 | + { | |
119 | + select = 0; // その他の場合は,セラミド付きの糖脂質として計算する. | |
120 | + } | |
121 | + try | |
122 | + { | |
123 | + known_cer = request.getParameter("known_cer").toLowerCase(); // 小文字にする("C12:0"->"c12:0") | |
124 | + | |
125 | + if (known_cer == null) | |
126 | + known_cer = "d14-20:1, c12-26:0,\nt14-20:0, h12-26:0"; | |
127 | + } | |
128 | + catch (Exception e) | |
129 | + { | |
130 | + known_cer = "d14-20:1, c12-26:0,\nt14-20:0, h12-26:0"; | |
131 | + } | |
132 | + | |
133 | + out.println("<HTML><HEAD><TITLE>Composition Predictor</TITLE></HEAD><BODY>"); // 入力部 | |
134 | + out.println("<FONT SIZE=+2>Composition Predictor</FONT><BR><BR>"); | |
135 | + out.println("<FORM>"); | |
136 | + out.println("Measured <I>m/z</I> : <INPUT TYPE=text NAME=mass_a VALUE=" + mass_a + " SIZE=16>"); | |
137 | + out.println("Tolerance (Da): <INPUT TYPE=text NAME=tolerance VALUE=" + tolerance + " SIZE=4>"); | |
138 | + | |
139 | + out.println("Adduct ion: <SELECT NAME=adduct>"+adduct); // 前回の内容を初期値とする. | |
140 | + if (adduct.equals(MassCalc.Na_ION)) | |
141 | + out.println("<OPTION VALUE="+MassCalc.Na_ION+" SELECTED>Na+"); | |
142 | + else | |
143 | + out.println("<OPTION VALUE="+MassCalc.Na_ION+">Na+"); | |
144 | + if (adduct.equals(MassCalc.H_ION)) | |
145 | + out.println("<OPTION VALUE="+MassCalc.H_ION+" SELECTED>H+"); | |
146 | + else | |
147 | + out.println("<OPTION VALUE="+MassCalc.H_ION+">H+"); | |
148 | + if (adduct.equals(MassCalc.Li_ION)) | |
149 | + out.println("<OPTION VALUE="+MassCalc.Li_ION+" SELECTED>Li+"); | |
150 | + else | |
151 | + out.println("<OPTION VALUE="+MassCalc.Li_ION+">Li+"); | |
152 | + if (adduct.equals(MassCalc.K_ION)) | |
153 | + out.println("<OPTION VALUE="+MassCalc.K_ION+" SELECTED>K+"); | |
154 | + else | |
155 | + out.println("<OPTION VALUE="+MassCalc.K_ION+">K+"); | |
156 | + if (adduct.equals(MassCalc.H_NION)) | |
157 | + out.println("<OPTION VALUE="+MassCalc.H_NION+" SELECTED>H-"); | |
158 | + else | |
159 | + out.println("<OPTION VALUE="+MassCalc.H_NION+">H-"); | |
160 | + if (adduct.equals("")) | |
161 | + out.println("<OPTION VALUE='' SELECTED>No adduct (Molecular weight)"); | |
162 | + else | |
163 | + out.println("<OPTION VALUE=''>No adduct (Molecular weight)"); | |
164 | + out.println("</SELECT>"); | |
165 | + | |
166 | + out.println("Mass mode: <SELECT NAME=monoavg>"); | |
167 | + if (monoavg) | |
168 | + { | |
169 | + out.println("<OPTION VALUE=mono SELECTED>Monoisotopic"); | |
170 | + out.println("<OPTION VALUE=avg>Average"); | |
171 | + } | |
172 | + else | |
173 | + { | |
174 | + out.println("<OPTION VALUE=mono>Monoisotopic"); | |
175 | + out.println("<OPTION VALUE=avg SELECTED>Average"); | |
176 | + } | |
177 | + out.println("</SELECT><BR>"); | |
178 | + | |
179 | + | |
180 | + out.println("Known composition: <INPUT TYPE=text NAME=known_cp VALUE='" + known_cp + "' SIZE=64><BR><BR>"); | |
181 | + | |
182 | + out.println("Monosaccharide residues present<BR>"); | |
183 | + | |
184 | + out.println("Pen: <SELECT NAME=present_pen>"); // Penの存在を指定 | |
185 | + if (present_pen) | |
186 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
187 | + else | |
188 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
189 | + out.println("</SELECT>"); | |
190 | + | |
191 | + out.println("dHex: <SELECT NAME=present_dhex>"); // dHexの存在を指定 | |
192 | + if (present_dhex) | |
193 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
194 | + else | |
195 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
196 | + out.println("</SELECT>"); | |
197 | + | |
198 | + out.println("Hex: <SELECT NAME=present_hex>"); // Hexの存在を指定 | |
199 | + if (present_hex) | |
200 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
201 | + else | |
202 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
203 | + out.println("</SELECT>"); | |
204 | + | |
205 | + out.println("HexNAc: <SELECT NAME=present_hexnac>"); // HexNAcの存在を指定 | |
206 | + if (present_hexnac) | |
207 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
208 | + else | |
209 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
210 | + out.println("</SELECT>"); | |
211 | + | |
212 | + out.println("PenMe: <SELECT NAME=present_penme>"); // PenMeの存在を指定 | |
213 | + if (present_penme) | |
214 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
215 | + else | |
216 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
217 | + out.println("</SELECT>"); | |
218 | + | |
219 | + out.println("dHexMe: <SELECT NAME=present_dhexme>"); // dHexMeの存在を指定 | |
220 | + if (present_dhexme) | |
221 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
222 | + else | |
223 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
224 | + out.println("</SELECT>"); | |
225 | + | |
226 | + out.println("HexMe: <SELECT NAME=present_hexme>"); // HexMeの存在を指定 | |
227 | + if (present_hexme) | |
228 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
229 | + else | |
230 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
231 | + out.println("</SELECT>"); | |
232 | + | |
233 | + out.println("HexNAcMe: <SELECT NAME=present_hexnacme>"); // HexNAcMeの存在を指定 | |
234 | + if (present_hexnacme) | |
235 | + out.println("<OPTION VALUE=yes SELECTED>Yes\n<OPTION VALUE=no>No"); | |
236 | + else | |
237 | + out.println("<OPTION VALUE=yes>Yes\n<OPTION VALUE=no SELECTED>No"); | |
238 | + out.println("</SELECT>"); | |
239 | + | |
240 | + out.println("<BR><BR>"); | |
241 | + | |
242 | + // セラミド組成入力部 | |
243 | + if (select == 0) // 0ならば,セラミド組成により計算する. | |
244 | + out.println("<INPUT TYPE=radio NAME=select VALUE=0 CHECKED>Ceramide composition: "); | |
245 | + else | |
246 | + out.println("<INPUT TYPE=radio NAME=select VALUE=0>Ceramide composition: "); | |
247 | + | |
248 | + out.println("<TEXTAREA NAME=known_cer ROWS=4 COLS=36>" + known_cer + "</TEXTAREA><BR>"); | |
249 | + | |
250 | + if (select == 2) // 2ならば,糖鎖のみの分子として計算する. | |
251 | + out.println("<INPUT TYPE=radio NAME=select VALUE=2 CHECKED>Glycan only<BR>"); | |
252 | + else | |
253 | + out.println("<INPUT TYPE=radio NAME=select VALUE=2>Glycan only<BR>"); | |
254 | + | |
255 | + out.println("<INPUT TYPE=submit>"); | |
256 | + out.println("</FORM>"); | |
257 | + | |
258 | + // m/z1700以上はモノアイソトピックマスを正しく選択しているかを警告する. | |
259 | + if (mass_a > 1700) | |
260 | + out.println("<FONT color=red>Confirm measured <I>m/z</I> is monoisotopic mass.</FONT><BR><BR>"); | |
261 | + | |
262 | + out.println("<B>Predicted Compositions</B><BR><TABLE border=1>"); // 表示部 | |
263 | + out.print("<TR>"); | |
264 | + out.print("<TH>Calculated <I>m/z</I></TH>"); | |
265 | + out.print("<TH>+-</TH>"); | |
266 | + out.print("<TH>Modif</TH>"); | |
267 | + out.print("<TH>Ceramide</TH>"); | |
268 | + if (present_pen || known_cp.contains("pen")) // 条件で指定した糖のみを表示する. | |
269 | + out.print("<TH>Pen</TH>"); | |
270 | + if (present_dhex || known_cp.contains("dhex")) | |
271 | + out.print("<TH>dHex</TH>"); | |
272 | + if (present_hex || known_cp.contains("hex")) | |
273 | + out.print("<TH>Hex</TH>"); | |
274 | + if (present_hexnac || known_cp.contains("hexnac")) | |
275 | + out.print("<TH>HexNAc</TH>"); | |
276 | + if (present_penme || known_cp.contains("penme")) | |
277 | + out.print("<TH>PenMe</TH>"); | |
278 | + if (present_dhexme || known_cp.contains("dhexme")) | |
279 | + out.print("<TH>dHexMe</TH>"); | |
280 | + if (present_hexme || known_cp.contains("hexme")) | |
281 | + out.print("<TH>HexMe</TH>"); | |
282 | + if (present_hexnacme || known_cp.contains("hexnacme")) | |
283 | + out.print("<TH>HexNAcMe</TH>"); | |
284 | + | |
285 | + out.print("<TH>Total</TH>"); | |
286 | + out.print("<TD>Permethylated <I>m/z</I></TD>"); | |
287 | + out.print("<TD>Possible series</TD>"); | |
288 | + out.println("</TR>"); | |
289 | + | |
290 | + CompositionTools ci = new CompositionTools(); | |
291 | + ci.setComposition(known_cp); | |
292 | + ci.setMsTolerance(tolerance); | |
293 | + ci.setMass(mass_a); | |
294 | + ci.setMonoavg(monoavg); // モノアイソトピックマスで計算するか,アベレージで計算するかを指定 | |
295 | + ci.setAdduct(adduct); // 付加イオンを指定 | |
296 | + ci.setMax("pen", present_pen); // 各糖の最大値を設定する. | |
297 | + ci.setMax("dhex", present_dhex); | |
298 | + ci.setMax("hex", present_hex); | |
299 | + ci.setMax("hexnac", present_hexnac); | |
300 | + ci.setMax("penme", present_penme); | |
301 | + ci.setMax("dhexme", present_dhexme); | |
302 | + ci.setMax("hexme", present_hexme); | |
303 | + ci.setMax("hexnacme", present_hexnacme); | |
304 | + | |
305 | + if (select == 0) // 0ならば,セラミド組成により計算する. | |
306 | + { | |
307 | + List<String> ceramide = new ArrayList<String>(); // 既知の長鎖塩基組成を格納する. | |
308 | + List<String> lcb = new ArrayList<String>(); // 既知の長鎖塩基組成を格納する. | |
309 | + List<String> fa = new ArrayList<String>(); // 既知の脂肪酸組成を格納する. | |
310 | + | |
311 | + for (String str : known_cer.split("[^\\w:-]")) // 単語構成文字と':','-'以外の文字列で分割 | |
312 | + if (str.matches("^[dt][ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // セラミドの場合 | |
313 | + ceramide.add(str); | |
314 | + else if (str.matches("^[dt][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 長鎖塩基の場合 | |
315 | + lcb.add(str); | |
316 | + else if (str.matches("^[ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 脂肪酸の場合 | |
317 | + fa.add(str); | |
318 | + | |
319 | + ci.setCeramide(ceramide); // セラミド組成を登録 | |
320 | + ci.setLongChainBase(lcb); // 長鎖塩基組成を登録 | |
321 | + ci.setFattyAcid(fa); // 脂肪酸組成を登録 | |
322 | + } | |
323 | + | |
324 | + for (Composition cp : ci.getComposition()) | |
325 | + { | |
326 | + Composition cp_hex = new Composition(cp); // インスタンスをコピーする. | |
327 | + cp_hex.toHexose(); // "Glc"などを"Hex"へ変換 | |
328 | + | |
329 | + int pen = Collections.frequency(cp_hex, "pen"); // 指定した糖の個数を数える. | |
330 | + int dhex = Collections.frequency(cp_hex, "dhex"); | |
331 | + int hex = Collections.frequency(cp_hex, "hex"); | |
332 | + int hexnac = Collections.frequency(cp_hex, "hexnac"); | |
333 | + int penme = Collections.frequency(cp_hex, "penme"); | |
334 | + int dhexme = Collections.frequency(cp_hex, "dhexme"); | |
335 | + int hexme = Collections.frequency(cp_hex, "hexme"); | |
336 | + int hexnacme = Collections.frequency(cp_hex, "hexnacme"); | |
337 | + int total = pen + dhex + hex + hexnac + penme + dhexme + hexme + hexnacme; // 合計の糖数 | |
338 | + double mass_t = cp.getMass(monoavg, adduct); | |
339 | + double difference = mass_a - mass_t; | |
340 | + | |
341 | + Composition modif = new Composition(cp_hex); // 表に存在する以外の修飾基をmodifへ格納する. | |
342 | + // 単糖を削除 | |
343 | + modif.removeAll(new Composition("pen, dhex, hex, hexnac, penme, dhexme, hexme, hexnacme")); | |
344 | + if (select != 2) // セラミドが存在する場合, | |
345 | + modif.remove(modif.getCeramide()); // セラミドを削除 | |
346 | + | |
347 | + out.print("<TR>"); | |
348 | + out.print(String.format("<TD align=right>%.4f</TD>", mass_t)); | |
349 | + out.print(String.format("<TD align=right>%.4f</TD>", difference)); | |
350 | + | |
351 | + if (modif.size() > 0) // 表に存在する以外の修飾基が存在する場合, | |
352 | + out.print("<TD align=center>" + modif.toString() + "</TD>"); // 表示する. | |
353 | + else // 存在しない場合は, | |
354 | + out.print("<TD align=center>-</TD>"); // 表示しない. | |
355 | + | |
356 | + if (select != 2) // 糖鎖のみの予測でない場合, | |
357 | + out.print("<TD align=center>" + cp.getCeramide() + "</TD>"); // セラミドは存在する. | |
358 | + else // 糖鎖のみの予測の場合, | |
359 | + out.print("<TD align=center>-</TD>"); // セラミドは存在しない. | |
360 | + | |
361 | + if (present_pen || known_cp.contains("pen")) // 条件で指定した糖のみを表示する. | |
362 | + out.print("<TD align=right>" + pen + "</TD>"); // 各糖の個数 | |
363 | + if (present_dhex || known_cp.contains("dhex")) | |
364 | + out.print("<TD align=right>" + dhex + "</TD>"); | |
365 | + if (present_hex || known_cp.contains("hex")) | |
366 | + out.print("<TD align=right>" + hex + "</TD>"); | |
367 | + if (present_hexnac || known_cp.contains("hexnac")) | |
368 | + out.print("<TD align=right>" + hexnac + "</TD>"); | |
369 | + if (present_penme || known_cp.contains("penme")) | |
370 | + out.print("<TD align=right>" + penme + "</TD>"); | |
371 | + if (present_dhexme || known_cp.contains("dhexme")) | |
372 | + out.print("<TD align=right>" + dhexme + "</TD>"); | |
373 | + if (present_hexme || known_cp.contains("hexme")) | |
374 | + out.print("<TD align=right>" + hexme + "</TD>"); | |
375 | + if (present_hexnacme || known_cp.contains("hexnacme")) | |
376 | + out.print("<TD align=right>" + hexnacme + "</TD>"); | |
377 | + | |
378 | + out.print("<TD align=right>" + total + "</TD>"); // 糖数の合計 | |
379 | + | |
380 | + try // メチル化後の糖脂質のm/zを出力 | |
381 | + { | |
382 | + Composition methylated = new Composition(cp); | |
383 | + int count = methylated.countHydroxy(); // メチル基が入るOH基の数を数える. | |
384 | + methylated.addAll(new Composition("me*" + count)); // メチル基を追加する. | |
385 | + out.print(String.format("<TD align=right>%.4f</TD>", methylated.getMass(monoavg, adduct))); | |
386 | + } | |
387 | + catch (Exception e) | |
388 | + { | |
389 | + out.println("<TD align=center>-</TD>"); | |
390 | + } | |
391 | + | |
392 | + try // 可能性のある系列を表示する. | |
393 | + { | |
394 | + StringBuilder sb = new StringBuilder(); | |
395 | + if (cp.isGloboSeries()) | |
396 | + sb.append("Globo, "); | |
397 | + if (cp.isLactoSeries()) | |
398 | + sb.append("Lacto, "); | |
399 | + if (cp.isGanglioSeries()) | |
400 | + sb.append("Ganglio, "); | |
401 | + if (cp.isLactoganglioSeries()) | |
402 | + sb.append("Lactoganglio, "); | |
403 | + if (cp.isGalaSeries()) | |
404 | + sb.append("Gala, "); | |
405 | + if (cp.isMucoSeries()) | |
406 | + sb.append("Muco, "); | |
407 | + if (cp.isArthroSeries()) | |
408 | + sb.append("Arthro, "); | |
409 | + if (cp.isMolluSeries()) | |
410 | + sb.append("Mollu, "); | |
411 | + if (sb.length() > 2) | |
412 | + out.print("<TD>" + sb.substring(0, sb.length()-2) + "</TD>"); // 最後の", "を削除して表示 | |
413 | + else | |
414 | + out.print("<TD></TD>"); // 可能性のある系列が存在しなかった場合 | |
415 | + } | |
416 | + catch (Exception e) | |
417 | + { | |
418 | + out.println("<TD>" + e + "</TD>"); | |
419 | + } | |
420 | + | |
421 | + out.println("</TR>"); | |
422 | + } | |
423 | + } | |
424 | + catch (Exception e) | |
425 | + { | |
426 | + out.println("ERROR:" + e.getMessage()); | |
427 | + } | |
428 | + out.println("</TABLE><BR>"); | |
429 | + | |
430 | + out.println("<Div Align=right><FONT color=gray>(c) Kazuhito Yokoi</FONT></Div><BR>"); | |
431 | + out.println("<A HREF=../>Back</A>"); // トップページへのリンク | |
432 | + | |
433 | + out.println("<script type=\"text/javascript\">"); | |
434 | + out.println("var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");"); | |
435 | + out.println("document.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));"); | |
436 | + out.println("</script>"); | |
437 | + out.println("<script type=\"text/javascript\">"); | |
438 | + out.println("try {"); | |
439 | + out.println("var pageTracker = _gat._getTracker(\"UA-1643740-14\");"); | |
440 | + out.println("pageTracker._trackPageview();"); | |
441 | + out.println("} catch(err) {}</script>"); | |
442 | + out.println("</BODY></HTML>"); // 終了タグ | |
443 | + } | |
444 | +} |
@@ -0,0 +1,417 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.concurrent.*; | |
4 | + | |
5 | +/** | |
6 | + * メチル化後ガングリオシドのフラグメントイオンから構造を予測するクラスです. | |
7 | + * @author 横井一仁 | |
8 | + * @version 20090124 | |
9 | + */ | |
10 | +class CandidateGa extends Candidate | |
11 | +{ | |
12 | + Glycan before_gc; // メチル化前の糖鎖構造を格納 | |
13 | + | |
14 | + public CandidateGa(Glycan gc) throws Exception | |
15 | + { | |
16 | + super(); | |
17 | + before_gc = new Glycan(gc.toString()); // メチル化前の構造を格納しておく. | |
18 | + | |
19 | + gc.methylation(); // メチル化を行う. | |
20 | + | |
21 | + this.setNode(gc.getNode()); // メチル化後の構造を登録する. | |
22 | + this.setEdge(gc.getEdge()); | |
23 | + this.setChildren(gc.getChildren()); | |
24 | + | |
25 | + fg.setGlycan(this); | |
26 | + this.frags_t = fg.getComposition(); // それぞれのフラグメントを取得する. | |
27 | + this.masses_t = new double[this.frags_t.size()]; // フラグメント数と同じサイズの配列を用意 | |
28 | + | |
29 | + int i = 0; | |
30 | + for (Composition temp : this.frags_t) // フラグメントの分子量を計算しておく | |
31 | + masses_t[i++] = temp.getMass(monoavg, adduct); // メチル化糖のm/zを登録する. | |
32 | + } | |
33 | + | |
34 | + /* | |
35 | + * メチル化前の糖鎖構造を返します. | |
36 | + * @return メチル化前の糖鎖構造 | |
37 | + */ | |
38 | + public synchronized Glycan getIntactGlycan() throws Exception | |
39 | + { | |
40 | + return before_gc; | |
41 | + } | |
42 | +} | |
43 | + | |
44 | +/** | |
45 | + * メチル化ガングリオシドの構造予測を行うクラスです. | |
46 | + * @author 横井一仁 | |
47 | + * @version 20080725 | |
48 | + */ | |
49 | +public class PredictionGa extends Prediction | |
50 | +{ | |
51 | + double precursor_me = 0.0; // メチル化後の親マス | |
52 | + CompositionToolsMe cp_agg = new CompositionToolsMe(); // CompositionToolsをCompositionToolsMeにオーバーライド | |
53 | + | |
54 | + /** | |
55 | + * コンストラクタ | |
56 | + */ | |
57 | + public PredictionGa() | |
58 | + { | |
59 | + super(); | |
60 | + } | |
61 | + | |
62 | + /** | |
63 | + * 予測された候補構造を返します. | |
64 | + * @return スコアが高い順に予想構造を返します. | |
65 | + */ | |
66 | + public java.util.List<? extends Candidate> getPrediction() throws Exception | |
67 | + { // 指定された条件から候補構造を生成 | |
68 | + java.util.List<Composition> cps = getCandidateComposition(); // 候補組成を作成する. | |
69 | + java.util.List<Glycan> candi = this.getCandidateGlycan(cps); // 候補構造を生成し,リストに格納する. | |
70 | + java.util.List<CandidateGa> al = this.toCandidateMeInstance(candi); // Glycanの候補構造を, | |
71 | + // CandidateGaの候補構造として登録する. | |
72 | + CandidateGa.setFreq(this.getFreqency(al)); // 出現確率を計算し,CandidateMeクラスの | |
73 | + // static変数として登録する. | |
74 | + Collections.sort(al, new Comparator<CandidateGa>() // スコア順にソートする. | |
75 | + { | |
76 | + public int compare(CandidateGa cp1, CandidateGa cp2) | |
77 | + { | |
78 | + double sub = 0.0; // スコアの差 | |
79 | + try | |
80 | + { | |
81 | + double score1 = cp1.getScore(); | |
82 | + double score2 = cp2.getScore(); | |
83 | + | |
84 | + if (score1 == score2) // スコアが等しい構造は,分岐数の少ない | |
85 | + sub = cp1.countLeaf() - cp2.countLeaf(); // (葉ノード数が少ない)構造を上位に表示 | |
86 | + else | |
87 | + sub = score2 - score1; | |
88 | + | |
89 | + } | |
90 | + catch (Exception e) | |
91 | + { | |
92 | + System.err.println("Prediction.getPrediction(): score compare error"); | |
93 | + } | |
94 | + | |
95 | + return (int)(sub*1024); // 精度を1024倍に上げる | |
96 | + } | |
97 | + }); | |
98 | + | |
99 | + return al; | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * 候補組成を生成し,リストに格納する. | |
104 | + */ | |
105 | + protected java.util.List<Composition> getCandidateComposition() throws Exception | |
106 | + { // メチル化前の親マスのみから組成を予測する.親クラスはフラグメントからも予測 | |
107 | + java.util.List<Composition> cps; // 考えられる組成を格納するリスト | |
108 | + | |
109 | + cp_agg.setComposition(known_cp); | |
110 | + cp_agg.setGlycan(known_gc); | |
111 | + cp_agg.setMsTolerance(tolerance_ms); | |
112 | + | |
113 | + if (precursor == 0.0) // 親マスの分子量が登録されていない場合, | |
114 | + { // フラグメント分子量の最大実測値から計算する. | |
115 | + Arrays.sort(masses_a); // 最大値を取り出すために昇順にソート. | |
116 | + cp_agg.setMass(masses_a[masses_a.length-1]); | |
117 | + cps = cp_agg.getComposition(); | |
118 | + } | |
119 | + else // 親マスの分子量が登録されている場合 | |
120 | + { | |
121 | + cp_agg.setMass(precursor); | |
122 | + cps = cp_agg.getComposition(); | |
123 | + } | |
124 | + | |
125 | + ListIterator<Composition> it = cps.listIterator(); | |
126 | + while (it.hasNext()) | |
127 | + { | |
128 | + Composition cp = new Composition(it.next()); | |
129 | + System.out.println("candidate composition: " + cp); | |
130 | + if (!cp.contains("neuac")) // シアル酸を持っていない組成を排除する. | |
131 | + { | |
132 | + it.remove(); | |
133 | + System.out.println(cp + " is removed."); | |
134 | + } | |
135 | + } | |
136 | + | |
137 | + return cps; | |
138 | + } | |
139 | + | |
140 | + /** | |
141 | + * Glycanインスタンスの候補構造を,CandidateGaインスタンスの候補構造とし,フラグメント化を行う. | |
142 | + */ | |
143 | + protected java.util.List<CandidateGa> toCandidateMeInstance(java.util.List<Glycan> candi) throws Exception | |
144 | + { | |
145 | + java.util.List<CandidateGa> al = new ArrayList<CandidateGa>(); // スコア付けを行う候補構造 | |
146 | + long start = new Date().getTime(); // プログラム開始時刻 | |
147 | + int candi_size = candi.size(); // 候補構造数を格納 | |
148 | + ListIterator<Glycan> it2 = candi.listIterator(); // 候補構造のイテレータを取得 | |
149 | + for (int i = 1; it2.hasNext() && flag; i++) // 考えられる組成のとり得る構造をリストに格納 | |
150 | + { | |
151 | + Glycan temp = it2.next(); | |
152 | + it2.remove(); // 不必要であるGlycanインスタンスを削除する. | |
153 | + | |
154 | + percent = (int)(i * 99.0 / candi_size); // 処理が何%進んだかを格納 | |
155 | + //(途中で表示が消えるため99%) | |
156 | + String messege = progress(i, candi_size, start); // オブザーバに送るメッセージを作成する. | |
157 | + try | |
158 | + { | |
159 | + messege = messege + " [" + temp.toNormalFormat() + "]"; // ノーマルのフォーマットで格納する. | |
160 | + } | |
161 | + catch (Exception e) | |
162 | + { | |
163 | + messege = messege + " [" + temp.toString() + "]"; // 二分岐以上の構造はLinucs形式で格納する. | |
164 | + } | |
165 | + this.setChanged(); // 変更があったことを明示する. | |
166 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
167 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
168 | + | |
169 | + CandidateGa cd = new CandidateGa(temp); | |
170 | + al.add(cd); | |
171 | + } | |
172 | + | |
173 | + if (!flag) // 処理が中断された場合, | |
174 | + al.clear(); // CandidateMeインスタンスの候補構造を削除 | |
175 | + else // 処理が正常に完了した場合, | |
176 | + { | |
177 | + percent = 100; // ProgressMonitorを終了するために100%にする. | |
178 | + this.setChanged(); // 変更があったことを明示する. | |
179 | + this.notifyObservers(progress(candi.size(), candi.size(), start)); // 監視者に進行状況を通知 | |
180 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
181 | + } | |
182 | + | |
183 | + return al; | |
184 | + } | |
185 | + | |
186 | + /** | |
187 | + * Glycanインスタンスの候補構造を,Candidateインスタンスの候補構造とし,フラグメント化を行う. | |
188 | + */ | |
189 | + protected java.util.List<CandidateGa> toCandidateMeInstance2(java.util.List<Glycan> candi) throws Exception | |
190 | + { // マルチスレッド版 | |
191 | + java.util.List<CandidateGa> al = new ArrayList<CandidateGa>(); // スコア付けを行う候補構造 | |
192 | + long start = new Date().getTime(); // プログラム開始時刻 | |
193 | + int candi_size = candi.size(); // 候補構造数を格納 | |
194 | + ListIterator<Glycan> it2 = candi.listIterator(); // 候補構造のイテレータを取得 | |
195 | + for (int i = 1; it2.hasNext() && flag; i++) // 考えられる組成のとり得る構造をリストに格納 | |
196 | + { | |
197 | + StringBuffer gc_messege = new StringBuffer(); // 現在処理中の糖鎖を文字列表示にて格納 | |
198 | + java.util.List<Glycan> gc_thread = new ArrayList<Glycan>(); // 1回の処理で並列計算させるGlycanインスタンス | |
199 | + for (int j = 0; j < 8 && it2.hasNext(); j++) // 8スレッドを並列させるので,8個ずつ処理 | |
200 | + { | |
201 | + Glycan temp = it2.next(); | |
202 | + try | |
203 | + { | |
204 | + gc_messege.append(temp.toNormalFormat() + ", "); // ノーマルのフォーマットで格納 | |
205 | + } | |
206 | + catch (Exception e) | |
207 | + { | |
208 | + gc_messege.append(temp.toString() + ", "); // 二分岐以上の構造はLinucs形式で格納 | |
209 | + } | |
210 | + gc_thread.add(temp); // マルチスレッドのタスクに追加 | |
211 | + it2.remove(); // 不必要であるGlycanインスタンスを削除 | |
212 | + | |
213 | + i++; // 処理済みの個数を増加させる. | |
214 | + } | |
215 | + i--; // for文の中で値が1つ多くなるため,削除 | |
216 | + | |
217 | + System.out.println("!"+i+"/"+candi_size); | |
218 | + percent = (int)(i * 99.0 / candi_size); // 処理が何%進んだかを格納 | |
219 | + // 途中で表示が消えるため99% | |
220 | + String messege = progress(i, candi_size, start); // オブザーバに送るメッセージ | |
221 | + messege = messege + " [" + gc_messege.toString() + "]"; | |
222 | + this.setChanged(); // 変更があったことを明示する. | |
223 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
224 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
225 | + | |
226 | + java.util.List<Callable<CandidateGa>> tasks = new ArrayList<Callable<CandidateGa>>(); | |
227 | + // タスクを格納するリスト | |
228 | + for (Glycan temp : gc_thread) | |
229 | + { | |
230 | + Callable<CandidateGa> task = new MultiThreadTool3(new Glycan(temp)); | |
231 | + tasks.add(task); | |
232 | + } | |
233 | + ExecutorService es = Executors.newFixedThreadPool(8); // 8スレッドで実行 | |
234 | + java.util.List<Future<CandidateGa>> futures = es.invokeAll(tasks); // タスクの実行 | |
235 | + | |
236 | + for (Future<CandidateGa> future : futures) // 実行結果の回収 | |
237 | + { | |
238 | + CandidateGa cd = future.get(); | |
239 | + al.add(cd); | |
240 | + } | |
241 | + es.shutdown(); // 並列処理の終了 | |
242 | + } | |
243 | + | |
244 | + if (!flag) // 処理が中断された場合, | |
245 | + al.clear(); // Candidateインスタンスの候補構造を削除 | |
246 | + else // 処理が正常に完了した場合, | |
247 | + { | |
248 | + percent = 100; // ProgressMonitorを終了するために100%にする. | |
249 | + this.setChanged(); // 変更があったことを明示する. | |
250 | + this.notifyObservers(progress(candi.size(), candi.size(), start)); // 監視者に進行状況を通知 | |
251 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
252 | + } | |
253 | + | |
254 | + return al; | |
255 | + } | |
256 | + | |
257 | + /** | |
258 | + * モノアイソトープ,またはアベレージで計算するかを設定します. | |
259 | + * @param monoavg モノアイソトピックまたはアベレージ. | |
260 | + */ | |
261 | + public void setMonoavg(boolean monoavg) throws Exception | |
262 | + { | |
263 | + CandidateGa.setMonoavg(monoavg); // Candidateクラスのstatic変数として登録する. | |
264 | + cp_agg.setMonoavg(monoavg); // 組成を予測するクラスのメソッドを利用して登録する. | |
265 | + } | |
266 | + | |
267 | + /** | |
268 | + * 予測に用いる付加イオンを指定します. | |
269 | + * @param adduct 付加イオン(デフォルトはNa+) | |
270 | + */ | |
271 | + public void setAdduct(String adduct) throws Exception | |
272 | + { | |
273 | + CandidateGa.setAdduct(adduct); // Candidateクラスのstatic変数として登録する. | |
274 | + cp_agg.setAdduct(adduct); // 組成を予測するクラスのメソッドを利用して登録する. | |
275 | + } | |
276 | + | |
277 | + /** | |
278 | + * PSDスペクトルの実測値と理論値の許容誤差を登録します. | |
279 | + * @param tolerance_psd 実測値と理論値の許容誤差 | |
280 | + */ | |
281 | + public void setPsdTolerance(double tolerance_psd) throws Exception | |
282 | + { | |
283 | + this.tolerance_psd = tolerance_psd; // クラスメンバとする. | |
284 | + CandidateGa.setPsdTolerance(tolerance_psd); // Candidateクラスのstatic変数として登録する. | |
285 | + } | |
286 | + | |
287 | + /** | |
288 | + * フラグメント分子量の実測値を登録します. | |
289 | + * @param masses_a フラグメント分子量の実測値 | |
290 | + */ | |
291 | + public void setFragments(double[] masses_a) | |
292 | + { | |
293 | + this.masses_a = masses_a; // メンバ変数として格納 | |
294 | + CandidateGa.setMasses_a(masses_a); // Candidateクラスのstatic変数として登録する. | |
295 | + } | |
296 | + | |
297 | + /** | |
298 | + * 予測に用いるスコア式を指定します. | |
299 | + * @param formula スコア式 | |
300 | + */ | |
301 | + public void setScoringFormula(int formula) | |
302 | + { | |
303 | + CandidateGa.setScoringFormula(formula); // Candidateクラスのstatic変数として登録する. | |
304 | + } | |
305 | + | |
306 | + /** | |
307 | + * 出現確率分布のウィンドウサイズを指定します. | |
308 | + * @param window ウィンドウサイズ | |
309 | + */ | |
310 | + public void setWindowSize(int window) | |
311 | + { | |
312 | + CandidateGa.setWindowSize(window); // Candidateクラスのstatic変数として登録する. | |
313 | + } | |
314 | + | |
315 | + /** | |
316 | + * 現在登録されている出現確率分布のウィンドウサイズを取得します. | |
317 | + * @return ウィンドウサイズ | |
318 | + */ | |
319 | + public int getWindowSize() | |
320 | + { | |
321 | + return CandidateGa.getWindowSize(); // Candidateクラスのstatic変数を呼び出す. | |
322 | + } | |
323 | + | |
324 | + | |
325 | + /** | |
326 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
327 | + * @param lcb 長鎖塩基組成 | |
328 | + */ | |
329 | + public void setLongChainBase(java.util.List<String> lcb) throws Exception | |
330 | + { | |
331 | + cp_agg.setLongChainBase(lcb); | |
332 | + } | |
333 | + | |
334 | + /** | |
335 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
336 | + * @param fa 脂肪酸組成 | |
337 | + */ | |
338 | + public void setFattyAcid(java.util.List<String> fa) throws Exception | |
339 | + { | |
340 | + cp_agg.setFattyAcid(fa); | |
341 | + } | |
342 | + | |
343 | + /** | |
344 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
345 | + * @param min 炭素数の最小値 | |
346 | + * @param max 炭素数の最大値 | |
347 | + */ | |
348 | + public void setLongChainBase(int min, int max) throws Exception | |
349 | + { | |
350 | + cp_agg.setLongChainBase(min, max); | |
351 | + } | |
352 | + | |
353 | + /** | |
354 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
355 | + * @param min 炭素数の最小値 | |
356 | + * @param max 炭素数の最大値 | |
357 | + */ | |
358 | + public void setFattyAcid(int min, int max, int bond) throws Exception | |
359 | + { | |
360 | + cp_agg.setFattyAcid(min, max, bond); | |
361 | + } | |
362 | + | |
363 | + /** | |
364 | + * 糖鎖組成の予測に用いるセラミド組成を登録します. | |
365 | + * @param ceramide セラミド組成 | |
366 | + */ | |
367 | + public void setCeramide(java.util.List<String> ceramide) throws Exception | |
368 | + { | |
369 | + cp_agg.setCeramide(ceramide); | |
370 | + } | |
371 | + | |
372 | + /** | |
373 | + * 糖鎖組成の予測に用いるセラミド組成を登録します. | |
374 | + * @param min 炭素数の最小値 | |
375 | + * @param max 炭素数の最大値 | |
376 | + * @param bond 脂肪酸の二重結合の最大値 | |
377 | + */ | |
378 | + public void setCeramide(int min, int max, int bond) | |
379 | + { | |
380 | + cp_agg.setCeramide(min, max, bond); | |
381 | + } | |
382 | + | |
383 | + /** | |
384 | + * 予測で考慮する各糖の糖数を指定します. | |
385 | + * @param str 糖数を指定する糖 | |
386 | + * @param max 指定する糖数 | |
387 | + */ | |
388 | + public void setMax(String str, int max) throws Exception | |
389 | + { | |
390 | + cp_agg.setMax(str, max); | |
391 | + } | |
392 | + | |
393 | + /** | |
394 | + * 予測で考慮する各糖の糖数を指定します. | |
395 | + * @param str 指定する糖 | |
396 | + * @param bl 糖を存在させるかを指定 | |
397 | + */ | |
398 | + public void setMax(String str, boolean bl) throws Exception | |
399 | + { | |
400 | + cp_agg.setMax(str, bl); | |
401 | + } | |
402 | +} | |
403 | + | |
404 | +class MultiThreadTool3 implements Callable<CandidateGa> | |
405 | +{ | |
406 | + Glycan gc; // 並列処理のために保存しておく候補構造 | |
407 | + | |
408 | + public MultiThreadTool3(Glycan gc) throws Exception | |
409 | + { | |
410 | + this.gc = gc; // 候補構造を登録 | |
411 | + } | |
412 | + | |
413 | + public CandidateGa call() throws Exception | |
414 | + { | |
415 | + return new CandidateGa(gc); // フラグメント化後の分子量の計算済みの候補構造を返す. | |
416 | + } | |
417 | +} | |
\ No newline at end of file |
@@ -0,0 +1,525 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | + | |
5 | +/** | |
6 | + * 糖鎖構造のデータを扱うクラスです. | |
7 | + * @author 横井一仁 | |
8 | + * @version 20080514 | |
9 | + */ | |
10 | +public class Glycan | |
11 | +{ | |
12 | + String node = ""; // 格納するデータ | |
13 | + String edge = ""; // 結合の種類 | |
14 | + ArrayList<Glycan> al = new ArrayList<Glycan>(); // 結合する子ノードを格納するリスト | |
15 | + | |
16 | + /** | |
17 | + * コンストラクタ | |
18 | + */ | |
19 | + public Glycan() | |
20 | + { | |
21 | + | |
22 | + } | |
23 | + | |
24 | + /** | |
25 | + * 渡されたGlycanインスタンスから糖鎖構造を構築します. | |
26 | + * @param gc Glycanインスタンス | |
27 | + */ | |
28 | + public Glycan(Glycan gc) throws Exception | |
29 | + { | |
30 | + Glycan temp = new Glycan(gc.toString()); | |
31 | + this.setNode(temp.getNode()); // 構造を登録する. | |
32 | + this.setEdge(temp.getEdge()); | |
33 | + this.setChildren(temp.getChildren()); | |
34 | + } | |
35 | + | |
36 | + /** | |
37 | + * 渡された文字列から糖鎖構造を構築します. | |
38 | + * @param str Linucs形式で表した糖鎖構造("th38:0-Glc(-Fuc)-GalNAc-GlcNAc-Rha"なども入力可能) | |
39 | + */ | |
40 | + public Glycan(String str) throws Exception | |
41 | + { | |
42 | + str = str.replaceAll("\\s", ""); // 空白文字を削除(\sは改行も含む) | |
43 | + str = str.toLowerCase(); // 全て小文字に変換 | |
44 | + | |
45 | + Pattern pt = Pattern.compile("^\\[(.*?)\\]\\[(.*?)\\]\\{(.*)\\}$"); // 節情報と辺情報を切り出し,格納 | |
46 | + Matcher mt = pt.matcher(str); | |
47 | + | |
48 | + if (mt.matches()) // まず,Linucs形式で構文解析する. | |
49 | + { | |
50 | + edge = mt.group(1); // 1つ目の[]内の文字列 | |
51 | + node = mt.group(2); // 2つ目の[]内の文字列 | |
52 | + String child = mt.group(3); // 最後の{}内の文字列 | |
53 | + | |
54 | + for (int i = 0, j = 0; j <= child.length(); j++) | |
55 | + { | |
56 | + String temp = child.substring(i, j); | |
57 | + | |
58 | + if (isLinucs(temp)) | |
59 | + { | |
60 | + al.add(new Glycan(temp)); | |
61 | + i = j; // 次の構造へ移行する. | |
62 | + } | |
63 | + } | |
64 | + } | |
65 | + else // Linucs形式でない場合 | |
66 | + { | |
67 | + throw new Exception("Linucs format parse error : " + str); | |
68 | + } | |
69 | + } | |
70 | + | |
71 | + /** | |
72 | + * Linucs形式であるかを判定します. | |
73 | + * @param str Linucs形式の文字列 | |
74 | + */ | |
75 | + private boolean isLinucs(String str) | |
76 | + { | |
77 | + String temp = ""; | |
78 | + | |
79 | + for (int i = 0; i < str.split("\\{").length; i++) // 入れ子は"{"の数以下となる. | |
80 | + { | |
81 | + // "[^\\[\\]\\{\\}]"により,"[]{}"以外を指定. | |
82 | + String regex = "\\[([^\\[\\]\\{\\}])*?\\]\\[([^\\[\\]\\{\\}])*?\\]\\{" + temp + "\\}"; | |
83 | + | |
84 | + if (str.matches("^" + regex + "$")) | |
85 | + return true; | |
86 | + | |
87 | + temp = "(" + regex + ")*?"; | |
88 | + } | |
89 | + | |
90 | + return false; | |
91 | + } | |
92 | + | |
93 | + /** | |
94 | + * 登録されている単糖を変更します. | |
95 | + * @param node 節情報の文字列 | |
96 | + */ | |
97 | + public void setNode(String node) | |
98 | + { | |
99 | + this.node = node; | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * 登録されている結合情報を変更します. | |
104 | + * @param edge 辺情報の文字列 | |
105 | + */ | |
106 | + public void setEdge(String edge) | |
107 | + { | |
108 | + this.edge = edge; | |
109 | + } | |
110 | + | |
111 | + /** | |
112 | + * 登録されている単糖を返します. | |
113 | + * @return 節情報の文字列 | |
114 | + */ | |
115 | + public String getNode() | |
116 | + { | |
117 | + return node; | |
118 | + } | |
119 | + | |
120 | + /** | |
121 | + * 結合情報を返します. | |
122 | + * @return 辺情報の文字列 | |
123 | + */ | |
124 | + public String getEdge() | |
125 | + { | |
126 | + return edge; | |
127 | + } | |
128 | + | |
129 | + /** | |
130 | + * 結合情報が登録されているかを返します. | |
131 | + * @return 節情報が存在するか | |
132 | + */ | |
133 | + public boolean hasNode() | |
134 | + { | |
135 | + String temp = this.getNode(); | |
136 | + if (temp == null || temp.equals("") || temp.equals("0+0") || temp.equals("0-0")) | |
137 | + return false; | |
138 | + else | |
139 | + return true; | |
140 | + } | |
141 | + | |
142 | + /** | |
143 | + * 結合情報が登録されているかを返します. | |
144 | + * @return 辺情報が存在するか | |
145 | + */ | |
146 | + public boolean hasEdge() | |
147 | + { | |
148 | + String temp = this.getEdge(); | |
149 | + if (temp == null || temp.equals("") || temp.equals("0+0") || temp.equals("0-0")) | |
150 | + return false; | |
151 | + else | |
152 | + return true; | |
153 | + } | |
154 | + | |
155 | + /** | |
156 | + * セラミドを含んでいるかを返します. | |
157 | + * @return セラミドを含んでいるか | |
158 | + */ | |
159 | + public boolean hasCeramide() throws Exception | |
160 | + { | |
161 | + if (this.getNode().matches("^([dt])([ch][0-9]+:[0-9])$")) // ルートノードにセラミドが存在した場合 | |
162 | + return true; | |
163 | + else | |
164 | + { | |
165 | + boolean flag = false; // return用フラッグ | |
166 | + for (Glycan gc : this.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
167 | + if (gc.hasCeramide()) // 子ノードに1つでもセラミドが存在した場合, | |
168 | + flag = true; // trueとして返すために,親ノードに伝える. | |
169 | + return flag; | |
170 | + } | |
171 | + } | |
172 | + | |
173 | + /** | |
174 | + * 構造をLinucs形式で返します. | |
175 | + * @return Linucs形式の文字列 | |
176 | + */ | |
177 | + public String toString() | |
178 | + { | |
179 | + if (al.isEmpty()) | |
180 | + return Composition.toFixSignage("[" + getEdge() + "][" + getNode() + "]{}"); // 正しい表記で出力 | |
181 | + else // 子ノードがある場合,再帰する. | |
182 | + { | |
183 | + Iterator it = al.iterator(); | |
184 | + String temp = ""; | |
185 | + | |
186 | + while (it.hasNext()) // "{}"内の文字列を繋ぎ合わせる. | |
187 | + temp = temp + ((Glycan)it.next()).toString(); | |
188 | + | |
189 | + return Composition.toFixSignage("[" + getEdge() + "][" + getNode() + "]{" + temp + "}"); // 正しい表記で出力 | |
190 | + } | |
191 | + } | |
192 | + | |
193 | + /** | |
194 | + * 木構造を線形表示で返すメソッド | |
195 | + * @return 木構造を"th38:0-Glc(-Fuc)-GalNAc-GlcNAc-Rha"の線形表示で返す. | |
196 | + */ | |
197 | + public String toNormalFormat() throws Exception | |
198 | + { | |
199 | + GlycanTools gi = new GlycanTools(); | |
200 | + return Composition.toFixSignage(gi.toNormalFormat(this)); // 正しい表記で出力 | |
201 | + } | |
202 | + | |
203 | + /** | |
204 | + * 木構造における現在の要素が葉であるかを返します. | |
205 | + * @return 葉であるかを返す. | |
206 | + */ | |
207 | + public boolean isLeaf() | |
208 | + { | |
209 | + return al.isEmpty(); | |
210 | + } | |
211 | + | |
212 | + /** | |
213 | + * 葉以外に指定した要素が存在しないかを返します. | |
214 | + * @return 存在しないかを返す. | |
215 | + */ | |
216 | + public boolean containsOnlyLeaf(String str) throws Exception // 末端のみにFucMeが存在する構造はtrue | |
217 | + { | |
218 | + boolean flag = true; | |
219 | + | |
220 | + for (Glycan gc : this.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
221 | + if (!gc.isLeaf() && gc.getNode().equals(str)) | |
222 | + return false; | |
223 | + else if (!gc.containsOnlyLeaf(str)) // 再帰 | |
224 | + flag = false; // 再帰で1回でもfalseが返されたら,再帰元の関数はfalseを返す. | |
225 | + | |
226 | + return flag; // 再帰で葉以外に指定した要素が存在しなかった場合返される. | |
227 | + } | |
228 | + | |
229 | + /** | |
230 | + * Glc,Gal,ManをHexへ,GlcNAc,GalNAcをHexNAcへ変換します. | |
231 | + */ | |
232 | + public void toHexose() | |
233 | + { | |
234 | + node = node.replaceAll("glc|man|gal", "hex"); // Hexへ変換 | |
235 | + node = node.replaceAll("lfuc|fuc|rha", "dhex"); // dHexへ変換 | |
236 | + node = node.replaceAll("xyl|ara", "pen"); // penへ変換 | |
237 | + | |
238 | + for (Glycan gc : this.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
239 | + gc.toHexose(); | |
240 | + } | |
241 | + | |
242 | + /** | |
243 | + * 子ノードを返します. | |
244 | + * @return 子ノード | |
245 | + */ | |
246 | + public List<Glycan> getChildren() | |
247 | + { | |
248 | + return al; | |
249 | + } | |
250 | + | |
251 | + /** | |
252 | + * 子ノードを書き換えます. | |
253 | + * @param li 書き換える子ノード | |
254 | + */ | |
255 | + public void setChildren(List<Glycan> li) | |
256 | + { | |
257 | + al.clear(); // 子ノードを削除 | |
258 | + al.addAll(li); // 引数の子ノードを追加 | |
259 | + } | |
260 | + | |
261 | + /** | |
262 | + * 単糖の数を返します. | |
263 | + * @return 構造内のノード数 | |
264 | + */ | |
265 | + public int size() throws Exception | |
266 | + { | |
267 | + int sum = 1; // 再帰により,この1を順次sumへ加算していく. | |
268 | + for (Glycan gc : this.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
269 | + sum += gc.size(); // 再帰 | |
270 | + | |
271 | + return sum; | |
272 | + } | |
273 | + | |
274 | + /** | |
275 | + * 構造内の葉ノード数を返します. | |
276 | + * @return 構造内の葉ノード数 | |
277 | + */ | |
278 | + public int countLeaf() | |
279 | + { | |
280 | + int sum = 0; // 再帰により,sumへ加算していく. | |
281 | + | |
282 | + if (this.isLeaf()) | |
283 | + sum++; | |
284 | + | |
285 | + for (Glycan gc : this.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
286 | + sum += gc.countLeaf(); // 再帰 | |
287 | + | |
288 | + return sum; | |
289 | + } | |
290 | + | |
291 | + /** | |
292 | + * 理論上の<I>m/z</I> を返します. | |
293 | + * @param monoisotopic モノアイソトピックかアベレージかをMassCalc.MONO_MASSで指定 | |
294 | + * @param adduct 付加イオンをMassCalc.Na_IONで指定 | |
295 | + * @return 理論上の<I>m/z</I> | |
296 | + */ | |
297 | + public double getMass(boolean monoisotopic, String adduct) throws Exception | |
298 | + { | |
299 | + MassCalc mc = new MassCalc(monoisotopic, adduct); | |
300 | + return mc.getMass(this); | |
301 | + } | |
302 | + | |
303 | + /** | |
304 | + * 構造内に指定した文字列が存在するかを返します. | |
305 | + * @param str 検索したい文字列 | |
306 | + * @return 構造内に文字列が存在するか | |
307 | + */ | |
308 | + public boolean contains(String str) throws Exception | |
309 | + { | |
310 | + Composition cp = new Composition(this); // 組成を作成 | |
311 | + return cp.contains(str); | |
312 | + } | |
313 | + | |
314 | + /** | |
315 | + * 糖鎖構造に対し、辞書順に再構築を行います. | |
316 | + */ | |
317 | + public void reconstruct() | |
318 | + { | |
319 | + ArrayList<Glycan> al = new ArrayList<Glycan>(); // 結合する子ノードを格納するリスト(後に書き換えるため) | |
320 | + | |
321 | + for (Glycan gc : this.getChildren()) // 子ノードがあるならば,さらに探索を行う. | |
322 | + { | |
323 | + al.add(gc); // 後に書き換えるために保存する. | |
324 | + gc.reconstruct(); // 再帰 | |
325 | + } | |
326 | + | |
327 | + Collections.sort(al, new Comparator<Glycan>() // 探索した帰りに辞書順にソートし,ノードの順番を書き換える. | |
328 | + { | |
329 | + public int compare(Glycan gc1, Glycan gc2) | |
330 | + { | |
331 | + return gc1.toString().compareTo(gc2.toString()); | |
332 | + } | |
333 | + }); | |
334 | + | |
335 | + this.setChildren(al); // alの内容に書き換える. | |
336 | + } | |
337 | + | |
338 | + /** | |
339 | + * このクラスをコレクションへ格納できるようにequalsメソッドをオーバーライドします. | |
340 | + * @param gc 比較対象となるGlycanクラス | |
341 | + * @return それぞれをLinucs形式へ変換し,String型における比較結果を返す. | |
342 | + */ | |
343 | + public boolean equals(Object gc) // オーバーライドなので引数の型はObjectでなくてはならない. | |
344 | + { | |
345 | + try | |
346 | + { | |
347 | + Glycan temp1 = new Glycan(this.toString()); // Glycanインスタンスをコピーする. | |
348 | + Glycan temp2 = new Glycan(((Glycan)gc).toString()); // jvm1.5以下ではオブジェクトの型変換が必要. | |
349 | + temp1.reconstruct(); // それぞれのノードを辞書順に並び変えた後, | |
350 | + temp2.reconstruct(); // 比較を行う. | |
351 | + | |
352 | + return temp1.toString().equals(temp2.toString()); | |
353 | + } | |
354 | + catch (Exception e) | |
355 | + { | |
356 | + System.out.println("Exception at Glycan.equals(Glycan.java) " + e); // 例外が発生したら, | |
357 | + return false; // 同じ糖鎖構造であってもfalseを返す. | |
358 | + } | |
359 | + } | |
360 | + | |
361 | + /** | |
362 | + * このクラスをコレクションへ格納できるようにhashCodeメソッドをオーバーライドします. | |
363 | + * @return それぞれをLinucs形式へ変換し,String型におけるhashCodeメソッドの値を返す. | |
364 | + */ | |
365 | + public int hashCode() | |
366 | + { | |
367 | + try | |
368 | + { | |
369 | + Glycan temp = new Glycan(this.toString()); // Glycanインスタンスをコピーする. | |
370 | + temp.reconstruct(); // ノードを辞書順に並び変えた後,hashCode()を行う. | |
371 | + return temp.toString().hashCode(); | |
372 | + } | |
373 | + catch (Exception e) | |
374 | + { | |
375 | + System.out.println("Exception at Glycan.hashCode(Glycan.java)"); | |
376 | + return 0; // 例外が発生したら,0を返す. | |
377 | + } | |
378 | + } | |
379 | + | |
380 | + /** | |
381 | + * フラグメントをGlycanとして返します. | |
382 | + * @return GlycanのSet | |
383 | + */ | |
384 | + public List<Glycan> getGlycanFragment() throws Exception | |
385 | + { | |
386 | + Fragmentation fg = new Fragmentation(); | |
387 | + fg.setGlycan(new Glycan(this.toString())); | |
388 | + return fg.getGlycan(); | |
389 | + } | |
390 | + | |
391 | + /** | |
392 | + * フラグメントをCompositionとして返します. | |
393 | + * @return CompositionのSet | |
394 | + */ | |
395 | + public List<Composition> getCompositionFragment() throws Exception | |
396 | + { | |
397 | + Fragmentation fg = new Fragmentation(); | |
398 | + fg.setGlycan(new Glycan(this.toString())); | |
399 | + return fg.getComposition(); | |
400 | + } | |
401 | + | |
402 | + /** | |
403 | + * 子ノードとしてGlycanを追加します. | |
404 | + * @param gc 追加するGlycanクラス | |
405 | + */ | |
406 | + public void addChild(Glycan gc) | |
407 | + { | |
408 | + al.add(gc); | |
409 | + } | |
410 | + | |
411 | + /** | |
412 | + * 指定した子ノードを削除します. | |
413 | + * @param gc 削除するGlycanクラス | |
414 | + */ | |
415 | + public boolean removeChild(Glycan gc) | |
416 | + { | |
417 | + return al.remove(gc); // 成功したらtrueを返す. | |
418 | + } | |
419 | + | |
420 | + /** | |
421 | + * 全メチル化を行います. | |
422 | + */ | |
423 | + public void methylation() throws Exception // 還元末端側が糖鎖の場合, | |
424 | + { // 還元末端にメチル基が入ることを考慮するために関数を2重化 | |
425 | + this.methylation(false); // 親ノードが存在しない(=false)として実行. | |
426 | + } | |
427 | + | |
428 | + /** | |
429 | + * 全メチル化を行います. | |
430 | + * @parm flag 親ノードが存在するか | |
431 | + */ | |
432 | + private void methylation(boolean flag) throws Exception | |
433 | + { | |
434 | + Pattern pt1 = Pattern.compile("^(xyl|ara|pen|dhex|fuc|rha|hex|glc|gal|man|hexnac|glcnac|galnac|hexa|kdn|neuac|neugc)([0-9]*)((me)?)$"); | |
435 | + Matcher mt1 = pt1.matcher(node); // ↑アセチル基には未対応 | |
436 | + Pattern pt2 = Pattern.compile("^([dt])([ch])([0-9]+):([0-9])$"); | |
437 | + Matcher mt2 = pt2.matcher(node); | |
438 | + | |
439 | + if (mt1.matches()) // 糖のメチル化 | |
440 | + { | |
441 | + int count = 0; // メチル基が入る個数 | |
442 | + if (mt1.group(1).matches("^(xyl|ara|pen)$")) // ペントースの場合は, | |
443 | + count = 3 - this.getChildren().size(); // 修飾基の付加できる部分は最大3ヶ所 | |
444 | + else if (mt1.group(1).matches("^(dhex|fuc|rha)$")) // デオキシヘキソースの場合は, | |
445 | + count = 3 - this.getChildren().size(); // 修飾基の付加できる部分は最大3ヶ所 | |
446 | + else if (mt1.group(1).matches("^(hex|glc|gal|man|hexnac|glcnac|galnac|hexa)$")) // その他の場合は, | |
447 | + count = 4 - this.getChildren().size(); // 最大4ヶ所 | |
448 | + else if (mt1.group(1).matches("^(neuac|kdn)$")) // NeuAc,KDNは,最大6ヶ所 | |
449 | + count = 6 - this.getChildren().size(); | |
450 | + else if (mt1.group(1).matches("^(neugc)$")) // NeuGcは,NeuAcからさらにOH基が1つ多いため,最大7ヶ所 | |
451 | + count = 7 - this.getChildren().size(); | |
452 | + else | |
453 | + throw new Exception("Regular expression error in above program: + " + mt1.group(1)); | |
454 | + | |
455 | + if (!flag) // 親ノードが存在しない糖は還元末端側にメチル基が入る. | |
456 | + count++; | |
457 | + | |
458 | + node = mt1.group(1) + count + "me"; | |
459 | + } | |
460 | + else if (mt2.matches()) // セラミドのメチル化(長鎖塩基のNにもメチル基が入る) | |
461 | + { | |
462 | + int count = Integer.parseInt(mt2.group(3)); // セラミドの炭素数を格納 | |
463 | + if (mt2.group(1).equals("d")) // ジヒドロキシスフィンゴシンの場合, | |
464 | + count += 2; // メチル基が2つ増加(=炭素数が2つ増加) | |
465 | + else if (mt2.group(1).equals("t")) // トリヒドロキシスフィンゴシンの場合, | |
466 | + count += 3; // メチル基が3つ増加(=炭素数が3つ増加) | |
467 | + | |
468 | + if (mt2.group(2).equals("h")) // ヒドロキシ脂肪酸の場合, | |
469 | + count++; // メチル基が1つ増加(=炭素数が1つ増加) | |
470 | + | |
471 | + node = mt2.group(1) + mt2.group(2) + count + ":" + mt2.group(4); | |
472 | + } | |
473 | + else // 正規表現と一致しなかった場合 | |
474 | + throw new Exception("Unknown Composition: " + node); | |
475 | + | |
476 | + for (Glycan gc : this.getChildren()) // 子ノードにおいてもメチル化を行う. | |
477 | + gc.methylation(true); // 親ノードが存在する(=true)として再帰. | |
478 | + } | |
479 | + | |
480 | + | |
481 | + /** | |
482 | + * 指定した構造から伸長した構造であるかを返します. | |
483 | + * @param gc 検索対象とする糖鎖構造 | |
484 | + * @return 伸長した構造であるかを返す. | |
485 | + */ | |
486 | + public boolean contains(Glycan gc) throws Exception | |
487 | + { | |
488 | + if (gc == null) // 引数がnullの場合はfalse | |
489 | + return false; | |
490 | + | |
491 | + if (this.getNode().equals(gc.getNode())) // ノード名が一致した場合 | |
492 | + { | |
493 | + ArrayList<Glycan> al1 = new ArrayList<Glycan>(); // 子ノードを削除をするため, | |
494 | + ArrayList<Glycan> al2 = new ArrayList<Glycan>(); // ArrayList<Glycan>を用意. | |
495 | + for (Glycan gc1 : this.getChildren()) | |
496 | + al1.add(gc1); // それぞれの子ノードを格納. | |
497 | + for (Glycan gc2 : gc.getChildren()) | |
498 | + al2.add(gc2); | |
499 | + | |
500 | + if (al1.size() == 0 && al2.size() == 0) // ノード名が一致しており,ともに子ノードを持たない場合は | |
501 | + return true; // 以下のif(!flag)によりflaseとなるため,trueを返しておく. | |
502 | + else if (al1.size() >= al2.size()) // 引数であるGlycanの子ノード数の方が小さい場合か,等しい場合 | |
503 | + { | |
504 | + for (Glycan temp : al2) // 引数のGlycanの子ノードを調べる. | |
505 | + { | |
506 | + Iterator<Glycan> it1 = al1.iterator(); | |
507 | + boolean flag = false; // 引数であるGlycanの子ノードの要素を全て持っていない場合false | |
508 | + while (it1.hasNext() && !flag) // 余分に削除するのを避けるため,!flagを用いる. | |
509 | + if (temp.contains(it1.next())) | |
510 | + { | |
511 | + flag = true; // 一致する要素が左が1つ,右が2つ以上の場合, | |
512 | + it1.remove(); // 間違って判定されるので削除しておく. | |
513 | + } | |
514 | + if (!flag) | |
515 | + return false; // 引数であるGlycanの子ノードの要素を全て持っていない場合false | |
516 | + } | |
517 | + return true; // flaseが返されずこの行へ来た時のみtrue | |
518 | + } | |
519 | + else | |
520 | + return false; // 引数であるGlycanの子ノード数の方が大きい場合はfalse | |
521 | + } | |
522 | + else | |
523 | + return false; // ノード名が一致しない場合はfalse | |
524 | + } | |
525 | +} |
@@ -0,0 +1,314 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.text.*; | |
3 | +import java.awt.*; | |
4 | +import java.awt.event.*; | |
5 | +import javax.swing.*; | |
6 | +import java.util.*; | |
7 | +import javax.swing.table.*; | |
8 | +import java.util.concurrent.*; | |
9 | +import java.lang.management.*; | |
10 | + | |
11 | +/** | |
12 | + * メチル化後ガングリオシドのフラグメントイオンから構造を予測するクラスです.(GUI版) | |
13 | + * @author 横井一仁 | |
14 | + * @version 20081122 | |
15 | + */ | |
16 | +public class PredictionGUIGa extends PredictionGUI | |
17 | +{ | |
18 | + PredictionGUIGa() throws Exception | |
19 | + { | |
20 | + super(); | |
21 | + jf.setTitle("Structure Predictor (ganglioside ver)"); // タイトルの変更 | |
22 | + } | |
23 | + | |
24 | + /* | |
25 | + * 実測値を入力する部分のJPanelを取得します. | |
26 | + */ | |
27 | + protected JPanel getInputJPanel() | |
28 | + { | |
29 | + JPanel west_center = new JPanel(); // 実測値入力部 | |
30 | + west_center.setLayout(new BorderLayout()); // ウィンドウのWESTに貼り付けるパネルのCENTER(ウィンドウの左上) | |
31 | + west_center.add(new JLabel("Fragment mass (permethylated):"), BorderLayout.NORTH); | |
32 | + // メチル化後GM1のフラグメント | |
33 | + query_ta = new JTextArea("111.1\n154.0\n228.2\n259.5\n306.2\n343.8\n365.9\n375.8\n397.8\n415.7\n434.7\n" | |
34 | + + "457.6\n463.6\n486.6\n575.5\n588.2\n604.8\n675.8\n778.6\n794.4\n810.6\n819.5\n" | |
35 | + + "834.4\n848.9\n866.3\n898.2\n1009.4\n1023.7\n1039.7\n1241.6\n1257.7\n1273.6\n" | |
36 | + + "1385.3\n1400.4\n1414.8\n1474.0\n1488.1\n1502.7\n1862.6\n1877.2"); | |
37 | + west_center.add(new JScrollPane(query_ta), BorderLayout.CENTER); // JTextAreaへスクロールバーをつける. | |
38 | + | |
39 | + return west_center; | |
40 | + } | |
41 | + | |
42 | + /* | |
43 | + * 実験的な予測条件を設定する部分のJPanelを取得します. | |
44 | + */ | |
45 | + protected JPanel getExperimentalConditionJPanel() | |
46 | + { | |
47 | + JPanel west_south_north = new JPanel(); // 予測条件入力部 ウィンドウのWESTに貼り付けるパネルのSOUTH | |
48 | + // ウィンドウの左下 | |
49 | + // JComboBoxの初期選択項目を指定する. | |
50 | + pen_cb.setSelectedItem("No"); // Penのデフォルトは"No" | |
51 | + dhex_cb.setSelectedItem("Yes"); // dHexのデフォルトは"Yes" | |
52 | + hex_cb.setSelectedItem("Yes"); // Hexのデフォルトは"Yes" | |
53 | + hexnac_cb.setSelectedItem("Yes"); // HexNAcのデフォルトは"Yes" | |
54 | + penme_cb.setSelectedItem("No"); // PenMeのデフォルトは"No" | |
55 | + dhexme_cb.setSelectedItem("No"); // dHexMeのデフォルトは"No" | |
56 | + hexme_cb.setSelectedItem("No"); // HexMeのデフォルトは"No" | |
57 | + hexnacme_cb.setSelectedItem("No"); // HexNAcMeのデフォルトは"No" | |
58 | + | |
59 | + formula_cb.setSelectedItem("TFIDF"); // スコア計算式のデフォルトは"TFIDF" | |
60 | + | |
61 | + west_south_north.setLayout(new GridLayout(12, 2)); // 縦の数×横の数 | |
62 | + west_south_north.add(new JLabel("Fragment tolerance: ")); | |
63 | + west_south_north.add(psd_tolerance_tf); | |
64 | + west_south_north.add(new JLabel("Permethylated mass: ")); | |
65 | + precursor_mass_tf = new JTextField("1877.1972"); // メチル化後の親マスを登録(GM1) | |
66 | + west_south_north.add(precursor_mass_tf); | |
67 | + west_south_north.add(new JLabel("Precursor tolerance: ")); | |
68 | + west_south_north.add(precursor_tolerance_tf); | |
69 | + west_south_north.add(new JLabel("Adduct ion: ")); | |
70 | + west_south_north.add(adduct_cb); | |
71 | + west_south_north.add(new JLabel("Pen: ")); | |
72 | + west_south_north.add(pen_cb); | |
73 | + west_south_north.add(new JLabel("dHex: ")); | |
74 | + west_south_north.add(dhex_cb); | |
75 | + west_south_north.add(new JLabel("Hex: ")); | |
76 | + west_south_north.add(hex_cb); | |
77 | + west_south_north.add(new JLabel("HexNAc: ")); | |
78 | + west_south_north.add(hexnac_cb); | |
79 | + west_south_north.add(new JLabel("PenMe: ")); | |
80 | + west_south_north.add(penme_cb); | |
81 | + west_south_north.add(new JLabel("dHexMe: ")); | |
82 | + west_south_north.add(dhexme_cb); | |
83 | + west_south_north.add(new JLabel("HexMe: ")); | |
84 | + west_south_north.add(hexme_cb); | |
85 | + west_south_north.add(new JLabel("HexNAcMe: ")); | |
86 | + west_south_north.add(hexnacme_cb); | |
87 | + | |
88 | + return west_south_north; | |
89 | + } | |
90 | + | |
91 | + /* | |
92 | + * Startをクリックした時に実行されるスレッド | |
93 | + */ | |
94 | + public void run() | |
95 | + { | |
96 | + System.out.println("PredictionGa mode..."); | |
97 | + try | |
98 | + { | |
99 | + PredictionGa pd_agg = new PredictionGa(); // 継承の代わりに集約を用いる. | |
100 | + pd_agg.addObserver(this); // 進行状況をこのクラスへ伝えるために, | |
101 | + // このクラスをオブザーバとする. | |
102 | + // テキストエリアから実測値を取得 | |
103 | + String[] strs = query_ta.getText().split("[^\\.\\d]"); // '.'と数字以外の文字列で切り出す. | |
104 | + java.util.List<Double> massli = new ArrayList<Double>(); // 可変長配列を用意する. | |
105 | + for (String str : strs) | |
106 | + { | |
107 | + try | |
108 | + { | |
109 | + massli.add(Double.parseDouble(str)); | |
110 | + } | |
111 | + catch (Exception e) // 数字以外の文字が入っていた場合の時, | |
112 | + { // 無視したことを報告 | |
113 | + System.err.println(e); | |
114 | + } | |
115 | + } | |
116 | + double[] frags = new double[massli.size()]; // Listと同じ大きさの配列を用意 | |
117 | + Iterator<Double> massit = massli.iterator(); | |
118 | + for (int i = 0; massit.hasNext(); i++) // double[]型のfragsへ配列の型変換 | |
119 | + frags[i] = massit.next(); | |
120 | + pd_agg.setFragments(frags); // フラグメントの実測値の配列を登録 | |
121 | + | |
122 | + try // プレカーサーマスを登録 | |
123 | + { | |
124 | + pd_agg.setPrecursorMass(Double.parseDouble(precursor_mass_tf.getText())); | |
125 | + } | |
126 | + catch (Exception e) // プレカーサーマスを登録しなかった場合, | |
127 | + { // PSDフラグメントの最大値を | |
128 | + System.err.println("Precursor mass is null."); // プレカーサーマスとして計算 | |
129 | + } | |
130 | + | |
131 | + try // プレカーサーマスの許容誤差を登録 | |
132 | + { | |
133 | + pd_agg.setMsTolerance(Double.parseDouble(precursor_tolerance_tf.getText())); // 許容誤差を格納 | |
134 | + } | |
135 | + catch (Exception e) | |
136 | + { | |
137 | + throw new Exception("'Precursor tolerance' contains error.\n" + e); | |
138 | + } | |
139 | + | |
140 | + try // PSDフラグメントの許容誤差を登録 | |
141 | + { | |
142 | + pd_agg.setPsdTolerance(Double.parseDouble(psd_tolerance_tf.getText())); // 許容誤差を格納 | |
143 | + } | |
144 | + catch (Exception e) | |
145 | + { | |
146 | + throw new Exception("'PSD tolerance' contains error.\n" + e); | |
147 | + } | |
148 | + | |
149 | + try // 付加イオンを登録 | |
150 | + { // 選択された付加イオンを取得する. | |
151 | + String temp = (String)adduct_cb.getSelectedItem(); // 表の部分でm/zを取得するのに必要なため, | |
152 | + if (temp.equals("Na+")) // adductはグローバル変数としている. | |
153 | + adduct = MassCalc.Na_ION; | |
154 | + else if (temp.equals("H+")) | |
155 | + adduct = MassCalc.H_ION; | |
156 | + else if (temp.equals("Li+")) | |
157 | + adduct = MassCalc.Li_ION; | |
158 | + else if (temp.equals("K+")) | |
159 | + adduct = MassCalc.K_ION; | |
160 | + else if (temp.equals("H-")) | |
161 | + adduct = MassCalc.H_NION; | |
162 | + else if (temp.equals("no adduct")) | |
163 | + adduct = ""; | |
164 | + else | |
165 | + throw new Exception(temp + " is unknown adduct ion."); | |
166 | + | |
167 | + pd_agg.setAdduct(adduct); | |
168 | + } | |
169 | + catch (Exception e) | |
170 | + { | |
171 | + throw new Exception("'Adduct ion' contains error.\n" + e); | |
172 | + } | |
173 | + | |
174 | + try // 既知構造を登録 | |
175 | + { | |
176 | + pd_agg.setGlycan(new Glycan(known_gc_tf.getText())); // Linucs形式から既知構造を登録 | |
177 | + } | |
178 | + catch (Exception e1) // Linucs形式の読み込みに失敗した場合, | |
179 | + { // ノーマル形式の読み込みを試す. | |
180 | + try | |
181 | + { | |
182 | + GlycanTools gi = new GlycanTools(); | |
183 | + pd_agg.setGlycan(gi.readNormalFormat(known_gc_tf.getText())); // 既知構造を登録 | |
184 | + } | |
185 | + catch (Exception e2) | |
186 | + { | |
187 | + throw new Exception("'Known structure' contains error.\n" + e1 + e2); | |
188 | + } | |
189 | + } | |
190 | + | |
191 | + try // 各糖の最大数を登録 | |
192 | + { | |
193 | + pd_agg.setMax("pen", ((String)pen_cb.getSelectedItem()).equals("Yes")); | |
194 | + pd_agg.setMax("dhex", ((String)dhex_cb.getSelectedItem()).equals("Yes")); | |
195 | + pd_agg.setMax("hex", ((String)hex_cb.getSelectedItem()).equals("Yes")); | |
196 | + pd_agg.setMax("hexnac", ((String)hexnac_cb.getSelectedItem()).equals("Yes")); | |
197 | + pd_agg.setMax("penme", ((String)penme_cb.getSelectedItem()).equals("Yes")); | |
198 | + pd_agg.setMax("dhexme", ((String)dhexme_cb.getSelectedItem()).equals("Yes")); | |
199 | + pd_agg.setMax("hexme", ((String)hexme_cb.getSelectedItem()).equals("Yes")); | |
200 | + pd_agg.setMax("hexnacme", ((String)hexnacme_cb.getSelectedItem()).equals("Yes")); | |
201 | + | |
202 | + pd_agg.setMax("neuac", true); // ガングリオシドの予測なのでNeuAcを指定 | |
203 | + } | |
204 | + catch (Exception e) | |
205 | + { | |
206 | + throw new Exception("'max' contains error.\n" + e); | |
207 | + } | |
208 | + | |
209 | + try // セラミド組成を登録 | |
210 | + { | |
211 | + java.util.List<String> ceramide = new ArrayList<String>(); // 既知の長鎖塩基組成を格納する. | |
212 | + java.util.List<String> lcb = new ArrayList<String>(); // 既知の長鎖塩基組成を格納する. | |
213 | + java.util.List<String> fa = new ArrayList<String>(); // 既知の脂肪酸組成を格納する. | |
214 | + | |
215 | + for (String str : ceramide_tf.getText().split("[^\\w:-]")) // 単語構成文字と':','-'以外の文字列で分割 | |
216 | + if (str.matches("^[dt][ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // セラミドの場合 | |
217 | + ceramide.add(str); | |
218 | + else if (str.matches("^[dt][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 長鎖塩基の場合 | |
219 | + lcb.add(str); | |
220 | + else if (str.matches("^[ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 脂肪酸の場合 | |
221 | + fa.add(str); | |
222 | + | |
223 | + pd_agg.setCeramide(ceramide); // セラミド組成を登録 | |
224 | + pd_agg.setLongChainBase(lcb); // 長鎖塩基組成を登録 | |
225 | + pd_agg.setFattyAcid(fa); // 脂肪酸組成を登録 | |
226 | + } | |
227 | + catch (Exception e) | |
228 | + { | |
229 | + throw new Exception("'Ceramide' contains error.\n" + e); | |
230 | + } | |
231 | + | |
232 | + try // スコアリングの式を登録 | |
233 | + { | |
234 | + String temp = (String)formula_cb.getSelectedItem(); // 選択されたスコアリングの式を取得する. | |
235 | + if (temp.equals("POSITIVE")) | |
236 | + pd_agg.setScoringFormula(Candidate.POSITIVE_SCORING); | |
237 | + else if (temp.equals("TFIDF")) | |
238 | + pd_agg.setScoringFormula(Candidate.TFIDF_SCORING); | |
239 | + else if (temp.equals("PENALTY01")) | |
240 | + pd_agg.setScoringFormula(Candidate.PENALTY01_SCORING); | |
241 | + else if (temp.equals("PENALTY001")) | |
242 | + pd_agg.setScoringFormula(Candidate.PENALTY001_SCORING); | |
243 | + else if (temp.equals("PMF")) | |
244 | + pd_agg.setScoringFormula(Candidate.PMF_SCORING); | |
245 | + else if (temp.equals("GEOMETRICAVG")) | |
246 | + pd_agg.setScoringFormula(Candidate.GEOMETRICAVG_SCORING); | |
247 | + else | |
248 | + throw new Exception(temp + " is unknown adduct ion."); | |
249 | + } | |
250 | + catch (Exception e) | |
251 | + { | |
252 | + throw new Exception("'Scoring' contains error.\n" + e); | |
253 | + } | |
254 | + | |
255 | + try // 出現確率分布のウィンドウサイズを登録 | |
256 | + { | |
257 | + pd_agg.setWindowSize(1); | |
258 | + } | |
259 | + catch (Exception e) | |
260 | + { | |
261 | + throw new Exception("'Window size' contains error.\n" + e); | |
262 | + } | |
263 | + // 出力部 | |
264 | + java.util.List<? extends Candidate> cds = pd_agg.getPrediction(); | |
265 | + Iterator<? extends Candidate> it = cds.iterator(); | |
266 | + DefaultTableModel tm = new DefaultTableModel(title, 0); | |
267 | + for (int i = 0; i < 50 && it.hasNext(); i++) // 上位50候補を表示 | |
268 | + { | |
269 | + Candidate cd = it.next(); | |
270 | + | |
271 | + String[] table = new String[4]; // カラムの追加時は,配列の大きさに注意する. | |
272 | + table[0] = String.format("%.4f", cd.getScore()); | |
273 | + | |
274 | + try | |
275 | + { | |
276 | + table[1] = ((CandidateGa)cd).getIntactGlycan().toNormalFormat(); // ノーマルのフォーマットで格納 | |
277 | + } | |
278 | + catch (Exception e) | |
279 | + { | |
280 | + table[1] = ((CandidateGa)cd).getIntactGlycan().toString(); // 二分岐以上はLinucs形式で格納 | |
281 | + } | |
282 | + | |
283 | + table[2] = String.format("%.4f", cd.getOccupancy()); | |
284 | + table[3] = String.format("%.4f", ((CandidateGa)cd).getIntactGlycan().getMass(monoavg, adduct)); | |
285 | + tm.addRow(table); | |
286 | + } | |
287 | + result_ta.setModel(tm); | |
288 | + RowSorter<TableModel> rs = new TableRowSorter<TableModel>(tm); // ソート可能なテーブルにする. | |
289 | + result_ta.setRowSorter(rs); | |
290 | + super.resetTableColumnSize(); // カラム幅を指定する. | |
291 | + | |
292 | + java.awt.Toolkit.getDefaultToolkit().beep(); // 終了する時にビープ音を鳴らす. | |
293 | + | |
294 | + UIManager.put("OptionPane.messageDialogTitle", "Messege"); // "タイトルを"Messege"に変更 | |
295 | + UIManager.put("OptionPane.okButtonText", "OK"); // "了解"の部分を"OK"に変更 | |
296 | + JOptionPane.showMessageDialog(jf, "Calclation is finished.\n" + pm.getNote() + "\n" | |
297 | + + "Candidate structure: " + cds.size()); | |
298 | + start.setEnabled(true); // ボタンを押せるようにする. | |
299 | + reset.setEnabled(true); | |
300 | + } | |
301 | + catch (Exception e) // 処理中に例外が発生した場合, | |
302 | + { // 警告を表示し処理を中断 | |
303 | + JOptionPane.showMessageDialog(jf, "ERROR: " + e); | |
304 | + e.printStackTrace(); | |
305 | + start.setEnabled(true); // ボタンを押せるようにする. | |
306 | + reset.setEnabled(true); | |
307 | + } | |
308 | + } | |
309 | + | |
310 | + public static void main(String[] args) throws Exception | |
311 | + { | |
312 | + new PredictionGUIGa(); | |
313 | + } | |
314 | +} |
@@ -0,0 +1,110 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.io.*; | |
3 | +import java.util.*; | |
4 | +import javax.servlet.*; | |
5 | +import javax.servlet.http.*; | |
6 | +import org.jfree.chart.*; | |
7 | +import org.jfree.data.*; | |
8 | +import org.jfree.data.xy.*; | |
9 | +import org.jfree.data.general.*; | |
10 | +import org.jfree.chart.*; | |
11 | +import org.jfree.chart.plot.*; | |
12 | +import org.jfree.chart.axis.*; | |
13 | +import org.jfree.ui.*; | |
14 | + | |
15 | +class IsotopeXYDataset extends AbstractSeriesDataset implements XYDataset | |
16 | +{ | |
17 | + double[] mass = {812.0, 813.0, 814.0, 815.0, 816.0}; | |
18 | + double[] intensity = {0.1, 0.8, 0.7, 0.8, 1.0}; | |
19 | + double fwhm = 5000.0; // 半値幅(高いほど分解能が良い) | |
20 | + | |
21 | + public IsotopeXYDataset(double[] mass, double[] intensity) | |
22 | + { | |
23 | + this.mass = mass; | |
24 | + this.intensity = intensity; | |
25 | + } | |
26 | + | |
27 | + public int getItemCount(int series) | |
28 | + { | |
29 | + return 200; // 媒介変数の数 | |
30 | + } | |
31 | + | |
32 | + public double getXValue(int series, int item) | |
33 | + { | |
34 | + return ((double)item) / 100.0 + mass[series] - 1.0; // 1.0Da手前から表示 | |
35 | + } | |
36 | + | |
37 | + /** | |
38 | + * シリーズ,媒介変数を指定に応じたYの値. | |
39 | + */ | |
40 | + public double getYValue(int series, int item) | |
41 | + { | |
42 | + double x = ((double)item) / 100.0 + mass[series] - 1.0; // 1.0Da手前から表示 | |
43 | + return Math.exp(-1.0 * Math.pow((x - mass[series]) / (x / 10000), 2)) * intensity[series] * 100; | |
44 | + } | |
45 | + | |
46 | + /** | |
47 | + * 表示するグラフ数を返す. | |
48 | + */ | |
49 | + public int getSeriesCount() | |
50 | + { | |
51 | + return mass.length; // 配列に入っているグラフを表示する. | |
52 | + } | |
53 | + | |
54 | + public Comparable getSeriesKey(int key) | |
55 | + { | |
56 | + if (key == 0) | |
57 | + return "Monoisotopic"; | |
58 | + else if (key == 1) | |
59 | + return "1st isotopic"; | |
60 | + else if (key == 2) | |
61 | + return "2nd isotopic"; | |
62 | + else if (key == 3) | |
63 | + return "3rd isotopic"; | |
64 | + else | |
65 | + return key + "th isotopic"; | |
66 | + } | |
67 | + | |
68 | + public Number getX(int series, int item) {return getXValue(series, item);} | |
69 | + public Number getY(int series, int item) {return getYValue(series, item);} | |
70 | + public DomainOrder getDomainOrder() {return DomainOrder.NONE;} | |
71 | +} | |
72 | + | |
73 | +/** | |
74 | + * 同位体イオンのイオン化強度を表示するServletクラスです. | |
75 | + * @author 横井一仁 | |
76 | + * @version 20081216 | |
77 | + */ | |
78 | +public class Isotope extends HttpServlet | |
79 | +{ | |
80 | + public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException | |
81 | + { | |
82 | + List<Double> li_mass = new ArrayList<Double>(); | |
83 | + List<Double> li_intensity = new ArrayList<Double>(); | |
84 | + | |
85 | + String str; | |
86 | + for (int i = 0; (str = request.getParameter("mass" + i)) != null; i++) // 引数から読み取る. | |
87 | + li_mass.add(Double.parseDouble(str)); | |
88 | + | |
89 | + for (int i = 0; (str = request.getParameter("intensity" + i)) != null; i++) | |
90 | + li_intensity.add(Double.parseDouble(str)); | |
91 | + | |
92 | + double[] mass = new double[li_mass.size()]; // リストから配列へ変換 | |
93 | + Iterator<Double> it_mass = li_mass.iterator(); | |
94 | + for (int i = 0; it_mass.hasNext(); i++) | |
95 | + mass[i] = it_mass.next(); | |
96 | + | |
97 | + double[] intensity = new double[li_intensity.size()]; // リストから配列へ変換 | |
98 | + Iterator<Double> it_intensity = li_intensity.iterator(); | |
99 | + for (int i = 0; it_intensity.hasNext(); i++) | |
100 | + intensity[i] = it_intensity.next(); | |
101 | + | |
102 | + XYDataset xy = new IsotopeXYDataset(mass, intensity); | |
103 | + JFreeChart jc = ChartFactory.createXYLineChart("", "m/z", "Intensity (%)", | |
104 | + xy, PlotOrientation.VERTICAL, | |
105 | + true, true, true); | |
106 | + response.setContentType("image/png"); // PNG形式で画像を出力 | |
107 | + ServletOutputStream so = response.getOutputStream(); | |
108 | + ChartUtilities.writeChartAsPNG(so, jc, 500, 300); // 500×300ピクセル | |
109 | + } | |
110 | +} |
@@ -0,0 +1,392 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | + | |
4 | +/** | |
5 | + * メチル化後糖脂質のフラグメントイオンから構造を予測するクラスです. | |
6 | + * @author 横井一仁 | |
7 | + * @version 20090128 | |
8 | + */ | |
9 | +class CandidateMe extends Candidate | |
10 | +{ | |
11 | + Glycan before_gc; // メチル化前の糖鎖構造を格納 | |
12 | + static double precursor_me; // メチル化後のプレカーサーマス | |
13 | + | |
14 | + public CandidateMe(Glycan gc) throws Exception | |
15 | + { | |
16 | + super(); // 何もしないスーパークラスのコンストラクタ | |
17 | + before_gc = new Glycan(gc.toString()); // メチル化前の構造を格納しておく. | |
18 | + | |
19 | + gc.methylation(); // メチル化を行う. | |
20 | + | |
21 | + this.setNode(gc.getNode()); // メチル化後の構造を登録する. | |
22 | + this.setEdge(gc.getEdge()); | |
23 | + this.setChildren(gc.getChildren()); | |
24 | + | |
25 | + double ceramide_remove; // メチル化後の理論値と実測値から, | |
26 | + if (precursor_me != 0.0) // セラミドの分子量がどれだけ減少したかを計算する. | |
27 | + ceramide_remove = this.getMass(monoavg, adduct) - precursor_me; | |
28 | + else // メチル化後の実測値が登録されていない場合は,例外 | |
29 | + throw new Exception("Error: Set mathylated precursor mass, use setPrecursorMeMass()"); | |
30 | + | |
31 | + fg.setGlycan(this); | |
32 | + this.frags_t = fg.getComposition(); // それぞれのフラグメントを取得 | |
33 | + this.masses_t = new double[this.frags_t.size()]; // フラグメント数と同じサイズの配列を用意 | |
34 | + | |
35 | + int i = 0; | |
36 | + for (Composition temp : this.frags_t) // フラグメントの分子量を計算しておく | |
37 | + if (temp.hasCeramide()) // セラミドが存在する場合は,誤差を考慮 | |
38 | + masses_t[i++] = temp.getMass(monoavg, adduct) - ceramide_remove; | |
39 | + else | |
40 | + masses_t[i++] = temp.getMass(monoavg, adduct); // そのままメチル化糖のm/zを登録する. | |
41 | + } | |
42 | + | |
43 | + /** | |
44 | + * メチル化後の親マスを登録します. | |
45 | + * @param precursor_me メチル化後の親マス | |
46 | + */ | |
47 | + public static void setPrecursorMeMass(double precursor_me) | |
48 | + { | |
49 | + CandidateMe.precursor_me = precursor_me; // メンバ変数として格納 | |
50 | + } | |
51 | + | |
52 | + /* | |
53 | + * メチル化前の糖鎖構造を返します. | |
54 | + * @return メチル化前の糖鎖構造 | |
55 | + */ | |
56 | + public Glycan getIntactGlycan() | |
57 | + { | |
58 | + return before_gc; | |
59 | + } | |
60 | +} | |
61 | + | |
62 | +/** | |
63 | + * メチル化糖の構造予測を行うクラスです. | |
64 | + * @author 横井一仁 | |
65 | + * @version 20080725 | |
66 | + */ | |
67 | +public class PredictionMe extends Prediction | |
68 | +{ | |
69 | + double precursor_me = 0.0; // メチル化後の親マス | |
70 | + CompositionToolsMe cm_agg = new CompositionToolsMe(); // インタクトのプレカーサーマスが入力なしの場合に用いる. | |
71 | + | |
72 | + /** | |
73 | + * コンストラクタ | |
74 | + */ | |
75 | + public PredictionMe() | |
76 | + { | |
77 | + super(); | |
78 | + } | |
79 | + | |
80 | + /** | |
81 | + * モノアイソトープ,またはアベレージで計算するかを設定します. | |
82 | + * @param monoavg モノアイソトピックまたはアベレージ. | |
83 | + */ | |
84 | + public void setMonoavg(boolean monoavg) throws Exception | |
85 | + { | |
86 | + Candidate.setMonoavg(monoavg); // Candidateクラスのstatic変数として登録 | |
87 | + cp_agg.setMonoavg(monoavg); // 組成を予測するクラスのメソッドを利用して登録 | |
88 | + cm_agg.setMonoavg(monoavg); // 組成を予測するクラスのメソッドを利用して登録 | |
89 | + } | |
90 | + | |
91 | + /** | |
92 | + * 予測に用いる付加イオンを指定します. | |
93 | + * @param adduct 付加イオン(デフォルトはNa+) | |
94 | + */ | |
95 | + public void setAdduct(String adduct) throws Exception | |
96 | + { | |
97 | + Candidate.setAdduct(adduct); // Candidateクラスのstatic変数として登録 | |
98 | + cp_agg.setAdduct(adduct); // 組成を予測するクラスのメソッドを利用して登録 | |
99 | + cm_agg.setAdduct(adduct); // 組成を予測するクラスのメソッドを利用して登録 | |
100 | + } | |
101 | + | |
102 | + /** | |
103 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
104 | + * @param lcb 長鎖塩基組成 | |
105 | + */ | |
106 | + public void setLongChainBase(java.util.List<String> lcb) throws Exception | |
107 | + { | |
108 | + cp_agg.setLongChainBase(lcb); | |
109 | + cm_agg.setLongChainBase(lcb); | |
110 | + } | |
111 | + | |
112 | + /** | |
113 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
114 | + * @param fa 脂肪酸組成 | |
115 | + */ | |
116 | + public void setFattyAcid(java.util.List<String> fa) throws Exception | |
117 | + { | |
118 | + cp_agg.setFattyAcid(fa); | |
119 | + cm_agg.setFattyAcid(fa); | |
120 | + } | |
121 | + | |
122 | + /** | |
123 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
124 | + * @param min 炭素数の最小値 | |
125 | + * @param max 炭素数の最大値 | |
126 | + */ | |
127 | + public void setLongChainBase(int min, int max) throws Exception | |
128 | + { | |
129 | + cp_agg.setLongChainBase(min, max); | |
130 | + cm_agg.setLongChainBase(min, max); | |
131 | + } | |
132 | + | |
133 | + /** | |
134 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
135 | + * @param min 炭素数の最小値 | |
136 | + * @param max 炭素数の最大値 | |
137 | + */ | |
138 | + public void setFattyAcid(int min, int max, int bond) throws Exception | |
139 | + { | |
140 | + cp_agg.setFattyAcid(min, max, bond); | |
141 | + cm_agg.setFattyAcid(min, max, bond); | |
142 | + } | |
143 | + | |
144 | + /** | |
145 | + * 糖鎖組成の予測に用いるセラミド組成を登録します. | |
146 | + * @param ceramide セラミド組成 | |
147 | + */ | |
148 | + public void setCeramide(java.util.List<String> ceramide) throws Exception | |
149 | + { | |
150 | + cp_agg.setCeramide(ceramide); | |
151 | + cm_agg.setCeramide(ceramide); | |
152 | + } | |
153 | + | |
154 | + /** | |
155 | + * 糖鎖組成の予測に用いるセラミド組成を登録します. | |
156 | + * @param min 炭素数の最小値 | |
157 | + * @param max 炭素数の最大値 | |
158 | + * @param bond 脂肪酸の二重結合の最大値 | |
159 | + */ | |
160 | + public void setCeramide(int min, int max, int bond) | |
161 | + { | |
162 | + cp_agg.setCeramide(min, max, bond); | |
163 | + cm_agg.setCeramide(min, max, bond); | |
164 | + } | |
165 | + | |
166 | + /** | |
167 | + * 予測で考慮する各糖の糖数を指定します. | |
168 | + * @param str 糖数を指定する糖 | |
169 | + * @param max 指定する糖数 | |
170 | + */ | |
171 | + public void setMax(String str, int max) throws Exception | |
172 | + { | |
173 | + cp_agg.setMax(str, max); | |
174 | + cm_agg.setMax(str, max); | |
175 | + } | |
176 | + | |
177 | + /** | |
178 | + * 予測で考慮する各糖の糖数を指定します. | |
179 | + * @param str 指定する糖 | |
180 | + * @param bl 糖を存在させるかを指定 | |
181 | + */ | |
182 | + public void setMax(String str, boolean bl) throws Exception | |
183 | + { | |
184 | + cp_agg.setMax(str, bl); | |
185 | + cm_agg.setMax(str, bl); | |
186 | + } | |
187 | + | |
188 | + /** | |
189 | + * メチル化後の親マスを登録します. | |
190 | + * @param precursor_me メチル化後の親マス | |
191 | + */ | |
192 | + public void setPrecursorMeMass(double precursor_me) | |
193 | + { | |
194 | + this.precursor_me = precursor_me; // メンバ変数として格納 | |
195 | + CandidateMe.setPrecursorMeMass(precursor_me); // CandidateMeのスタティック変数としても登録 | |
196 | + } | |
197 | + | |
198 | + // 候補組成を生成し,リストに格納する. | |
199 | + protected java.util.List<Composition> getCandidateCompositionMe() throws Exception | |
200 | + { | |
201 | + System.out.print("canndidate compositions are predicting from only premethylaed precursor mass, "); | |
202 | + System.out.println("because intact precusor mass is null."); | |
203 | + java.util.List<Composition> cps; // 考えられる組成を格納するリスト | |
204 | + | |
205 | + cm_agg.setComposition(known_cp); | |
206 | + cm_agg.setGlycan(known_gc); | |
207 | + cm_agg.setMsTolerance(tolerance_ms); | |
208 | + cm_agg.setMass(precursor_me); | |
209 | + cps = cm_agg.getComposition(); | |
210 | + | |
211 | + return cps; | |
212 | + } | |
213 | + | |
214 | + /** | |
215 | + * 予測された候補構造を返します. | |
216 | + * @return スコアが高い順に予想構造を返します. | |
217 | + */ | |
218 | + public java.util.List<? extends Candidate> getPrediction() throws Exception | |
219 | + { // 指定された条件から候補構造を生成します. | |
220 | + java.util.List<Composition> cps; | |
221 | + if (precursor == 0.0) // インタクトのプレカーサーマスが登録されていない場合, | |
222 | + cps = getCandidateCompositionMe(); // メチル化後のプレカーサーマスのみから候補組成を作成 | |
223 | + else | |
224 | + cps = getCandidateComposition(); // 両方存在している場合は,両方から予測 | |
225 | + | |
226 | + java.util.List<Glycan> candi = this.getCandidateGlycan(cps); // 候補構造を生成し,リストに格納 | |
227 | + java.util.List<CandidateMe> al = this.toCandidateMeInstance(candi); // Glycanの候補構造を, | |
228 | + // CandidateMeの候補構造として登録 | |
229 | + CandidateMe.setFreq(this.getFreqency(al)); // 出現確率を計算し, | |
230 | + // CandidateMeクラスのstatic変数として登録 | |
231 | + Collections.sort(al, new Comparator<CandidateMe>() // スコア順にソート | |
232 | + { | |
233 | + public int compare(CandidateMe cp1, CandidateMe cp2) | |
234 | + { | |
235 | + double sub = 0.0; // スコアの差 | |
236 | + try | |
237 | + { | |
238 | + double score1 = cp1.getScore(); | |
239 | + double score2 = cp2.getScore(); | |
240 | + | |
241 | + if (score1 == score2) // スコアが等しい構造は,分岐数の少ない | |
242 | + sub = cp1.countLeaf() - cp2.countLeaf(); // (葉ノード数が少ない)構造を上位に表示 | |
243 | + else | |
244 | + sub = score2 - score1; | |
245 | + | |
246 | + } | |
247 | + catch (Exception e) | |
248 | + { | |
249 | + System.err.println("Prediction.getPrediction(): score compare error"); | |
250 | + } | |
251 | + | |
252 | + return (int)(sub*1024); // 精度を1024倍に上げる | |
253 | + } | |
254 | + }); | |
255 | + | |
256 | + return al; | |
257 | + } | |
258 | + | |
259 | + /** | |
260 | + * 候補組成を生成し,リストに格納する. | |
261 | + */ | |
262 | + protected java.util.List<Composition> getCandidateComposition() throws Exception | |
263 | + { // メチル化前の親マスのみから組成を予測する.親クラスはフラグメントからも予測 | |
264 | + java.util.List<Composition> cps; // 考えられる組成を格納するリスト | |
265 | + | |
266 | + cp_agg.setComposition(known_cp); | |
267 | + cp_agg.setGlycan(known_gc); | |
268 | + cp_agg.setMsTolerance(tolerance_ms); | |
269 | + | |
270 | + if (precursor == 0.0) // 親マスの分子量が登録されていない場合, | |
271 | + { // フラグメント分子量の最大実測値から計算 | |
272 | + Arrays.sort(masses_a); // 最大値を取り出すために昇順にソート | |
273 | + cp_agg.setMass(masses_a[masses_a.length-1]); | |
274 | + cps = cp_agg.getComposition(); | |
275 | + } | |
276 | + else // 親マスの分子量が登録されている場合 | |
277 | + { | |
278 | + cp_agg.setMass(precursor); | |
279 | + cps = cp_agg.getComposition(); | |
280 | + } | |
281 | + | |
282 | + ListIterator<Composition> it = cps.listIterator(); | |
283 | + while (it.hasNext()) | |
284 | + { | |
285 | + Composition cp = new Composition(it.next()); | |
286 | + | |
287 | + int count = cp.countHydroxy(); | |
288 | + for (int i = 0; i < count; i++) // ヒドロキシル基の個数分のメチル基を付加 | |
289 | + cp.add("me"); | |
290 | + | |
291 | + double mass = cp.getMass(true, MassCalc.Na_ION); // 理論上のメチル化物と実測のメチル化物との誤差が, | |
292 | + if (Math.abs(mass - precursor_me) > 20.0) // 指定した条件以上の組成を候補組成から除外する. | |
293 | + { | |
294 | + System.out.println(cp + "is removed." + mass + "-" + precursor_me + "=" + (mass - precursor_me)); | |
295 | + it.remove(); // メチル基1つ分のため,許容誤差は14〜28Daの範囲の値20.0 | |
296 | + } | |
297 | + } | |
298 | + | |
299 | + return cps; | |
300 | + } | |
301 | + | |
302 | + /** | |
303 | + * Glycanインスタンスの候補構造を,CandidateMeインスタンスの候補構造とし,フラグメント化を行う. | |
304 | + */ | |
305 | + protected java.util.List<CandidateMe> toCandidateMeInstance(java.util.List<Glycan> candi) throws Exception | |
306 | + { | |
307 | + java.util.List<CandidateMe> al = new ArrayList<CandidateMe>(); // スコア付けを行う候補構造 | |
308 | + long start = new Date().getTime(); // プログラム開始時刻 | |
309 | + int candi_size = candi.size(); // 候補構造数を格納 | |
310 | + ListIterator<Glycan> it2 = candi.listIterator(); // 候補構造のイテレータを取得 | |
311 | + for (int i = 1; it2.hasNext() && flag; i++) // 考えられる組成のとり得る構造をリストに格納 | |
312 | + { | |
313 | + Glycan temp = it2.next(); | |
314 | + it2.remove(); // 不必要であるGlycanインスタンスを削除 | |
315 | + | |
316 | + percent = (int)(i * 99.0 / candi_size); // 処理が何%進んだか(表示が消えるため99%) | |
317 | + String messege = progress(i, candi_size, start); // オブザーバに送るメッセージを作成する. | |
318 | + try | |
319 | + { | |
320 | + messege = messege + " [" + temp.toNormalFormat() + "]"; // ノーマルのフォーマットで格納する. | |
321 | + } | |
322 | + catch (Exception e) | |
323 | + { | |
324 | + messege = messege + " [" + temp.toString() + "]"; // 二分岐以上の構造はLinucs形式で格納する. | |
325 | + } | |
326 | + this.setChanged(); // 変更があったことを明示する. | |
327 | + this.notifyObservers(messege); // 監視者に進行状況を通知 | |
328 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
329 | + | |
330 | + CandidateMe cd = new CandidateMe(temp); | |
331 | + al.add(cd); | |
332 | + } | |
333 | + | |
334 | + if (!flag) // 処理が中断された場合, | |
335 | + al.clear(); // CandidateMeインスタンスの候補構造を削除 | |
336 | + else // 処理が正常に完了した場合, | |
337 | + { | |
338 | + percent = 100; // ProgressMonitorを終了するために100%にする. | |
339 | + this.setChanged(); // 変更があったことを明示する. | |
340 | + this.notifyObservers(progress(candi.size(), candi.size(), start)); // 監視者に進行状況を通知 | |
341 | + this.clearChanged(); // 変更された状態でないことを明示する. | |
342 | + } | |
343 | + | |
344 | + return al; | |
345 | + } | |
346 | + | |
347 | + /** | |
348 | + * フラグメントの出現確率の計算値を返します. | |
349 | + */ | |
350 | + public double[] getFreqency(java.util.List<? extends Candidate> al) throws Exception | |
351 | + { | |
352 | + double[] freq; // returnする確率分布 | |
353 | + | |
354 | + if (precursor_me == 0.0) // 親マスの分子量が登録されていない場合, | |
355 | + { // フラグメント分子量の最大実測値から計算 | |
356 | + Arrays.sort(masses_a); // 最大値を取り出すために昇順にソート. | |
357 | + freq = new double[(int)(masses_a[masses_a.length-1]/this.getWindowSize())+100]; // 1Daずつ出現頻度を計算 | |
358 | + } | |
359 | + else // 親マスの分子量が登録されている場合 | |
360 | + freq = new double[(int)(precursor_me/this.getWindowSize())+100]; // 1Daずつ出現頻度を計算する. | |
361 | + | |
362 | + for (Candidate cd : al) | |
363 | + { | |
364 | + boolean[] check = new boolean[freq.length]; // 1構造で重複しないようにするフラッグ | |
365 | + | |
366 | + double[] masses = cd.getFragMasses(); | |
367 | + for (int i = 0; i < masses.length; i++) // それぞれのフラグメントを取得し, | |
368 | + { // フラグメントが存在したらtrueとする. | |
369 | + if ((int)(masses[i]/this.getWindowSize()) > 0) | |
370 | + check[(int)(masses[i]/this.getWindowSize()) - 1] = true; // 前のフラッグを立てる. | |
371 | + | |
372 | + check[(int)(masses[i]/this.getWindowSize())] = true; // 現在の位置のフラッグを立てる. | |
373 | + | |
374 | + if (i+1 < freq.length) | |
375 | + check[(int)(masses[i]/this.getWindowSize()) + 1] = true; // 後ろのフラッグも立てる. | |
376 | + } | |
377 | + | |
378 | + for (int i = 0; i < freq.length; i++) // フラッグを出現確率の配列へコピー | |
379 | + if (check[i]) // フラグメントが存在したら1個増加 | |
380 | + freq[i] += 1.0; | |
381 | + } | |
382 | + | |
383 | + double max = 1.0; // 0で割らないために初期値は1 | |
384 | + for (double temp : freq) // 最大値を探す. | |
385 | + max = Math.max(temp,max); | |
386 | + | |
387 | + for (int i = 0; i < freq.length; i++) // 最大値で割ることで | |
388 | + freq[i] = freq[i] / max; // 0.0〜1.0をとるように変換 | |
389 | + | |
390 | + return freq; | |
391 | + } | |
392 | +} |
@@ -0,0 +1,1034 @@ | ||
1 | +package jp.ac.ritsumei.is.infobio; | |
2 | +import java.util.*; | |
3 | +import java.util.regex.*; | |
4 | +import java.io.*; | |
5 | + | |
6 | +/** | |
7 | + * 実測の<I>m/z</I> から糖鎖,糖脂質の組成を予測するクラスです. | |
8 | + * @author 横井一仁 | |
9 | + * @version 20081221 | |
10 | + */ | |
11 | +public class CompositionTools extends Observable // 進行状況の監視を可能とする. | |
12 | +{ | |
13 | + ArrayList<Composition> al_cp = new ArrayList<Composition>(); // Compositionを格納する. | |
14 | + double mass_a = 0.0; // m/zの実測値 | |
15 | + double[] masses_a; // m/zの実測値(複数のフラグメントから予測する場合に用いる) | |
16 | + double tolerance_ms = 0.5; // 指定がなければ,0.5とする. | |
17 | + double tolerance_psd = 1.0; // 実測値と理論値の許容誤差(PSD) | |
18 | + Set<String> ceramide = new HashSet<String>(); // 既知のセラミド組成を格納する. | |
19 | + Set<String> lcb = new HashSet<String>(); // 既知の長鎖塩基組成を格納する. | |
20 | + Set<String> fa = new HashSet<String>(); // 既知の脂肪酸組成を格納する. | |
21 | + Glycan known_gc; // 既知構造 | |
22 | + Composition known_cp; // 既知組成 | |
23 | + String adduct = MassCalc.Na_ION; // 付加イオン(デフォルトはNa+) | |
24 | + boolean monoavg = MassCalc.MONO_MASS; // Monoisotopic(ture), Average(false) | |
25 | + int hex_max = 10 ; | |
26 | + int hexnac_max = 10 ; | |
27 | + int dhex_max = 10 ; | |
28 | + int pen_max = 0 ; | |
29 | + int hexme_max = 0 ; | |
30 | + int hexnacme_max = 0 ; | |
31 | + int dhexme_max = 0 ; | |
32 | + int penme_max = 0 ; | |
33 | + int kdn_max = 0 ; | |
34 | + int neuac_max = 0 ; | |
35 | + int neugc_max = 0 ; | |
36 | + | |
37 | + /** | |
38 | + * 予測された組成を返します. | |
39 | + * @return 質量誤差の少ない順に格納して返します. | |
40 | + */ | |
41 | + public List<Composition> getComposition() throws Exception | |
42 | + { | |
43 | + if (masses_a != null && masses_a.length > 0) // 複数のフラグメントが入力されている場合 | |
44 | + return getCompositionFromMultiple(); | |
45 | + else | |
46 | + { | |
47 | + if (mass_a != 0.0) // mass_aにのみm/zが登録されている場合 | |
48 | + return getCompositionFromSingle(); | |
49 | + else // 予測に必要なm/zが登録されていない時,空のリストを返す. | |
50 | + { | |
51 | + System.err.println("CompositionTools returns null composition."); | |
52 | + return new ArrayList<Composition>(); | |
53 | + } | |
54 | + } | |
55 | + } | |
56 | + | |
57 | + /** | |
58 | + * 指定された条件から組成を予測します.(指定された<I>m/z</I> が複数存在する場合) | |
59 | + * @return Compositionを格納したList | |
60 | + */ | |
61 | + private List<Composition> getCompositionFromMultiple() throws Exception | |
62 | + { | |
63 | + al_cp.clear(); // クラスの再利用の時のために要素を全て削除する. | |
64 | + | |
65 | + CompositionTools ci = new CompositionTools(); // 組成を予測するインスタンスを作成する. | |
66 | + ci.setComposition(known_cp); // 既知組成を登録 | |
67 | + ci.setGlycan(known_gc); // 既知構造を登録 | |
68 | + ci.setCeramide(new ArrayList<String>(ceramide)); // 既知セラミド組成を登録(SetをArrayListに変換) | |
69 | + ci.setMsTolerance(tolerance_ms); // 許容誤差を登録 | |
70 | + ci.setAdduct(adduct); // 付加イオンを登録 | |
71 | + ci.setMonoavg(monoavg); // MonoisotopicかAverageを選択 | |
72 | + ci.setMax("hex", hex_max); // 各糖の最大数を指定する. | |
73 | + ci.setMax("hexnac", hexnac_max); | |
74 | + ci.setMax("dhex", dhex_max); | |
75 | + ci.setMax("pen", pen_max); | |
76 | + ci.setMax("hexme", hexme_max); | |
77 | + ci.setMax("hexnacme", hexnacme_max); | |
78 | + ci.setMax("dhexme", dhexme_max); | |
79 | + ci.setMax("penme", penme_max); | |
80 | + ci.setMax("kdn", kdn_max); | |
81 | + ci.setMax("neuac", neuac_max); | |
82 | + ci.setMax("neugc", neugc_max); | |
83 | + | |
84 | + int length; // 配列の何番目まで読み込むかを指定する. | |
85 | + if (mass_a != 0.0) // 予測したい質量が入力されている場合は, | |
86 | + { | |
87 | + ci.setMass(mass_a); // そのm/zから予測を行う. | |
88 | + length = masses_a.length; // 全てのフラグメントを読み込む | |
89 | + } | |
90 | + else // 入力されていない場合は, | |
91 | + { | |
92 | + Arrays.sort(masses_a); // フラグメントのm/zが登録されいる配列を昇順にソートし, | |
93 | + ci.setMass(masses_a[masses_a.length-1]); // 最大のm/zから組成を予測 | |
94 | + length = masses_a.length - 1; // 最後のフラグメントは読み込まない. | |
95 | + } | |
96 | + | |
97 | + Map<Integer, List<Composition>> mp = new HashMap<Integer, List<Composition>>(); // 各フラグメントの組成を格納 | |
98 | + for (int i = 0; i < length; i++) // 各フラグメントの組成を予測 | |
99 | + { | |
100 | + List<Composition> li = new ArrayList<Composition>(); // 格納用のList | |
101 | + CompositionTools ci2; | |
102 | + | |
103 | + if (ceramide != null && ceramide.size() != 0) // セラミドが登録されている場合 | |
104 | + { // フラグメントを糖脂質として組成予測を行う. | |
105 | + ci2 = new CompositionTools(); // 組成を予測するインスタンスを作成する. | |
106 | + ci2.setCeramide(new ArrayList<String>(ceramide)); // 既知セラミド組成を登録(SetをArrayListに変換) | |
107 | + ci2.setMsTolerance(tolerance_psd); // 許容誤差を登録(PSDであることに注意!) | |
108 | + ci2.setAdduct(adduct); // 付加イオンを登録 | |
109 | + ci2.setMonoavg(monoavg); // MonoisotopicかAverageを選択 | |
110 | + ci2.setMass(masses_a[i]); | |
111 | + ci2.setMax("hex", hex_max); // 各糖の最大数を指定する. | |
112 | + ci2.setMax("hexnac", hexnac_max); | |
113 | + ci2.setMax("dhex", dhex_max); | |
114 | + ci2.setMax("pen", pen_max); | |
115 | + ci2.setMax("hexme", hexme_max); | |
116 | + ci2.setMax("hexnacme", hexnacme_max); | |
117 | + ci2.setMax("dhexme", dhexme_max); | |
118 | + ci2.setMax("penme", penme_max); | |
119 | + ci2.setMax("kdn", kdn_max); | |
120 | + ci2.setMax("neuac", neuac_max); | |
121 | + ci2.setMax("neugc", neugc_max); | |
122 | + li.addAll(ci2.getComposition()); // 以上の条件から組成を予測する. | |
123 | + } | |
124 | + // フラグメントを糖鎖として組成予測を行う. | |
125 | + ci2 = new CompositionTools(); // 組成を予測するインスタンスを作成する. | |
126 | + ci2.setMsTolerance(tolerance_psd); // 許容誤差を登録(PSDであることに注意!) | |
127 | + ci2.setAdduct(adduct); // 付加イオンを登録 | |
128 | + ci2.setMonoavg(monoavg); // MonoisotopicかAverageを選択 | |
129 | + ci2.setMass(masses_a[i]); | |
130 | + ci2.setMax("hex", hex_max); // 各糖の最大数を指定する. | |
131 | + ci2.setMax("hexnac", hexnac_max); | |
132 | + ci2.setMax("dhex", dhex_max); | |
133 | + ci2.setMax("pen", pen_max); | |
134 | + ci2.setMax("hexme", hexme_max); | |
135 | + ci2.setMax("hexnacme", hexnacme_max); | |
136 | + ci2.setMax("dhexme", dhexme_max); | |
137 | + ci2.setMax("penme", penme_max); | |
138 | + ci2.setMax("kdn", kdn_max); | |
139 | + ci2.setMax("neuac", neuac_max); | |
140 | + ci2.setMax("neugc", neugc_max); | |
141 | + li.addAll(ci2.getComposition()); // 以上の条件から組成を予測する. | |
142 | + // フラグメントを脱水した糖鎖として組成予測を行う. | |
143 | + ci2 = new CompositionTools(); // 組成を予測するインスタンスを作成する. | |
144 | + Composition temp_cp = new Composition(); // 脱水した糖鎖に対応するために新しいインスタンスを生成 | |
145 | + temp_cp.add("-h2o"); // 脱水した糖鎖に対応するために"-h2o"を追加 | |
146 | + ci2.setComposition(temp_cp); // 既知組成を登録 | |
147 | + ci2.setMsTolerance(tolerance_psd); // 許容誤差を登録(PSDであることに注意!) | |
148 | + ci2.setAdduct(adduct); // 付加イオンを登録 | |
149 | + ci2.setMonoavg(monoavg); // MonoisotopicかAverageを選択 | |
150 | + ci2.setMass(masses_a[i]); | |
151 | + ci2.setMax("hex", hex_max); // 各糖の最大数を指定する. | |
152 | + ci2.setMax("hexnac", hexnac_max); | |
153 | + ci2.setMax("dhex", dhex_max); | |
154 | + ci2.setMax("pen", pen_max); | |
155 | + ci2.setMax("hexme", hexme_max); | |
156 | + ci2.setMax("hexnacme", hexnacme_max); | |
157 | + ci2.setMax("dhexme", dhexme_max); | |
158 | + ci2.setMax("penme", penme_max); | |
159 | + ci2.setMax("kdn", kdn_max); | |
160 | + ci2.setMax("neuac", neuac_max); | |
161 | + ci2.setMax("neugc", neugc_max); | |
162 | + for (Composition temp : ci2.getComposition()) // 以上の条件から組成を予測し, | |
163 | + { | |
164 | + temp.remove("-h2o"); // 水分子を削除した後, | |
165 | + li.add(temp); // リストへ追加. | |
166 | + } | |
167 | + | |
168 | + mp.put(i, li); // 以上の3種類のフラグメント組成をマップに格納する | |
169 | + } | |
170 | + | |
171 | + // 以下のプログラムは,3段階に分けて組成を予測している. | |
172 | + // まず実測フラグメントから考えられる組成を1/4以上持つ,親マスから計算した組成をリストに格納する. | |
173 | + // そして,1/4以上持つ組成が存在しない場合は,1/8以上持つ組成を格納する. | |
174 | + // 1/4も1/8も全ての組成が満たさない場合は,最終手段で1つ以上組成を持っているものを格納する. | |
175 | + ArrayList<Composition> al_cp1 = new ArrayList<Composition>(); // 補欠組成1 | |
176 | + ArrayList<Composition> al_cp2 = new ArrayList<Composition>(); // 補欠組成2 | |
177 | + for (Composition cp : ci.getComposition()) // 以上の条件から組成を予測する. | |
178 | + { | |
179 | + int count = 0; // 候補組成がフラグメントから得た組成を,いくつ持っているかをカウントする. | |
180 | + | |
181 | + for (int key : mp.keySet()) | |
182 | + { | |
183 | + Iterator<Composition> it = mp.get(key).iterator(); | |
184 | + boolean flag = true; // while文を抜けるためのフラッグ | |
185 | + while (it.hasNext() && flag) | |
186 | + { | |
187 | + Composition temp = new Composition(cp); | |
188 | + temp.toHexose(); // "Glc", "Gal"などを"Hex"へ変換 | |
189 | + if (temp.containsAll(it.next())) // cpに登録されている組成が,it.next()の組成を全て持っている時 | |
190 | + { | |
191 | + count++; // 一致したフラグメントの個数をカウントし, | |
192 | + flag = false; // while文を抜け,次のフラグメントとのマッチングを行う. | |
193 | + } | |
194 | + } | |
195 | + } | |
196 | + | |
197 | + if (count >= (int)(length / 2) + 1) // フラグメントから得た組成をx個以上もつ組成を候補組成とする. | |
198 | + al_cp.add(cp); // フラグメント2本のうち1本は試料由来であるという条件 | |
199 | + else if (count >= (int)(length / 4) + 1) // フラグメント4本のうち1本は試料由来であるという条件 | |
200 | + al_cp1.add(cp); // 出力する組成が存在しない場合に追加する補欠組成とする. | |
201 | + else if (count > 0) // 一致するフラグメントが1つ以上存在した場合は, | |
202 | + al_cp2.add(cp); // 出力する組成が存在しない場合に追加する補欠組成とする. | |
203 | + } | |
204 | + | |
205 | + if (al_cp.size() == 0) // フラグメント2本のうち1本は試料由来であるという条件の組成が存在しなかった時, | |
206 | + al_cp.addAll(al_cp1); // フラグメント4本のうち1本は試料由来であるという条件の組成を追加する. | |
207 | + | |
208 | + if (al_cp.size() == 0) // それでも条件を満たす組成が存在しなかった時, | |
209 | + al_cp.addAll(al_cp2); // 一致するフラグメントが1つ以上存在した組成を追加する. | |
210 | + | |
211 | + return al_cp; | |
212 | + } | |
213 | + | |
214 | + /** | |
215 | + * 指定された条件から組成を予測します.(指定された<I>m/z</I> が1つの場合) | |
216 | + * @return Compositionを格納したList | |
217 | + */ | |
218 | + private List<Composition> getCompositionFromSingle() throws Exception | |
219 | + { | |
220 | + al_cp.clear(); // クラスの再利用の時のために要素を全て削除する. | |
221 | + | |
222 | + Composition cp = new Composition(); | |
223 | + if (known_cp != null) // 既知組成が登録されている場合 | |
224 | + cp.addAll(known_cp); | |
225 | + else if (known_gc != null) // 既知構造が登録されている場合 | |
226 | + cp.addAll(new Composition(known_gc)); | |
227 | + | |
228 | + double mass_t = cp.getMass(monoavg, adduct); | |
229 | + | |
230 | + if (ceramide != null && ceramide.size() != 0) // セラミドが登録されている場合 | |
231 | + { | |
232 | + if (mass_a > mass_t) | |
233 | + addCer(cp); // セラミドから検索する. | |
234 | + } | |
235 | + else // セラミドが登録されていない場合は,糖鎖モードとする. | |
236 | + { | |
237 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
238 | + al_cp.add(cp); | |
239 | + else if (mass_a > mass_t) | |
240 | + addHex(cp); // Hexから検索する. | |
241 | + } | |
242 | + | |
243 | + final double temp_a = mass_a; // 内部クラスで用いる変数は,finalで宣言する必要がある. | |
244 | + Collections.sort(al_cp, new Comparator<Composition>() // ソートを行う. | |
245 | + { | |
246 | + public int compare(Composition cp1, Composition cp2) | |
247 | + { | |
248 | + double sub = 0.0; | |
249 | + | |
250 | + try | |
251 | + { | |
252 | + sub = Math.abs(cp1.getMass(monoavg, adduct) - temp_a) | |
253 | + - Math.abs(cp2.getMass(monoavg, adduct) - temp_a); | |
254 | + } catch (Exception e) {/**/} | |
255 | + | |
256 | + return (int)(sub*1024); // compareメソッドの返り値がint型しか受け付けないので1024倍して精度を上げる. | |
257 | + } | |
258 | + }); | |
259 | + | |
260 | + ceramide.clear(); // 次回の実行する時に同じ組成を2回追加しないように | |
261 | + lcb.clear(); // 既知のセラミド組成,長鎖塩基組成,脂肪酸組成を削除しておく. | |
262 | + fa.clear(); // (これにより,次回実行時に通常通りセラミドを追加できる) | |
263 | + | |
264 | + return al_cp; | |
265 | + } | |
266 | + | |
267 | + protected void addCer(Composition cp) throws Exception | |
268 | + { | |
269 | + for (String str : ceramide) | |
270 | + { | |
271 | + Composition temp = new Composition(str); // セラミドを登録. | |
272 | + temp.addAll(cp); | |
273 | + | |
274 | + double mass_t = temp.getMass(monoavg, adduct); | |
275 | + | |
276 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
277 | + al_cp.add(temp); | |
278 | + else | |
279 | + addHex(temp); | |
280 | + } | |
281 | + } | |
282 | + | |
283 | + protected void addHex(Composition cp) throws Exception | |
284 | + { | |
285 | + addHexNAc(cp); // HexNAcを追加した構造 | |
286 | + | |
287 | + Composition temp = new Composition(cp); | |
288 | + if (Collections.frequency(temp,"hex") < hex_max) // 要素を探索し,個数を数える. | |
289 | + { | |
290 | + temp.add("hex"); | |
291 | + double mass_t = temp.getMass(monoavg, adduct); | |
292 | + | |
293 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
294 | + al_cp.add(temp); | |
295 | + else if (mass_a > mass_t) | |
296 | + addHex(temp); | |
297 | + } | |
298 | + } | |
299 | + | |
300 | + protected void addHexNAc(Composition cp) throws Exception | |
301 | + { | |
302 | + adddHex(cp); // dHexを追加した構造 | |
303 | + | |
304 | + Composition temp = new Composition(cp); | |
305 | + if (Collections.frequency(temp,"hexnac") < hexnac_max) // 要素を探索し,個数を数える. | |
306 | + { | |
307 | + temp.add("hexnac"); | |
308 | + double mass_t = temp.getMass(monoavg, adduct); | |
309 | + | |
310 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
311 | + al_cp.add(temp); | |
312 | + else if (mass_a > mass_t) | |
313 | + addHexNAc(temp); | |
314 | + } | |
315 | + } | |
316 | + | |
317 | + protected void adddHex(Composition cp) throws Exception | |
318 | + { | |
319 | + addPen(cp); // dHexMeを追加した構造 | |
320 | + | |
321 | + Composition temp = new Composition(cp); | |
322 | + if (Collections.frequency(cp,"dhex") < dhex_max) // 要素を探索し,個数を数える. | |
323 | + { | |
324 | + temp.add("dhex"); | |
325 | + double mass_t = temp.getMass(monoavg, adduct); | |
326 | + | |
327 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
328 | + al_cp.add(temp); | |
329 | + else if (mass_a > mass_t) | |
330 | + adddHex(temp); | |
331 | + } | |
332 | + } | |
333 | + | |
334 | + protected void addPen(Composition cp) throws Exception | |
335 | + { | |
336 | + addHexMe(cp); // HexMeを追加した構造 | |
337 | + | |
338 | + Composition temp = new Composition(cp); | |
339 | + if (Collections.frequency(temp,"pen") < pen_max) // 要素を探索し,個数を数える. | |
340 | + { | |
341 | + temp.add("pen"); | |
342 | + double mass_t = temp.getMass(monoavg, adduct); | |
343 | + | |
344 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
345 | + al_cp.add(temp); | |
346 | + else if (mass_a > mass_t) | |
347 | + addPen(temp); | |
348 | + } | |
349 | + } | |
350 | + | |
351 | + protected void addHexMe(Composition cp) throws Exception | |
352 | + { | |
353 | + addHexNAcMe(cp); // HexNAcMeを追加した構造 | |
354 | + | |
355 | + Composition temp = new Composition(cp); | |
356 | + if (Collections.frequency(temp,"hexme") < hexme_max) // 要素を探索し,個数を数える. | |
357 | + { | |
358 | + temp.add("hexme"); | |
359 | + double mass_t = temp.getMass(monoavg, adduct); | |
360 | + | |
361 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
362 | + al_cp.add(temp); | |
363 | + else if (mass_a > mass_t) | |
364 | + addHexMe(temp); | |
365 | + } | |
366 | + } | |
367 | + | |
368 | + protected void addHexNAcMe(Composition cp) throws Exception | |
369 | + { | |
370 | + adddHexMe(cp); // dHexMeを追加した構造 | |
371 | + | |
372 | + Composition temp = new Composition(cp); | |
373 | + if (Collections.frequency(temp,"hexnacme") < hexnacme_max) // 要素を探索し,個数を数える. | |
374 | + { | |
375 | + temp.add("hexnacme"); | |
376 | + double mass_t = temp.getMass(monoavg, adduct); | |
377 | + | |
378 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
379 | + al_cp.add(temp); | |
380 | + else if (mass_a > mass_t) | |
381 | + addHexNAcMe(temp); | |
382 | + } | |
383 | + } | |
384 | + | |
385 | + protected void adddHexMe(Composition cp) throws Exception | |
386 | + { | |
387 | + addPenMe(cp); // PenMeを追加した構造 | |
388 | + | |
389 | + Composition temp = new Composition(cp); | |
390 | + if (Collections.frequency(cp,"dhexme") < dhexme_max) // 要素を探索し,個数を数える. | |
391 | + { | |
392 | + temp.add("dhexme"); | |
393 | + double mass_t = temp.getMass(monoavg, adduct); | |
394 | + | |
395 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
396 | + al_cp.add(temp); | |
397 | + else if (mass_a > mass_t) | |
398 | + adddHexMe(temp); | |
399 | + } | |
400 | + } | |
401 | + | |
402 | + protected void addPenMe(Composition cp) throws Exception | |
403 | + { | |
404 | + addKDN(cp); // KDNを追加した構造 | |
405 | + | |
406 | + Composition temp = new Composition(cp); | |
407 | + if (Collections.frequency(temp,"penme") < penme_max) // 要素を探索し,個数を数える. | |
408 | + { | |
409 | + temp.add("penme"); | |
410 | + double mass_t = temp.getMass(monoavg, adduct); | |
411 | + | |
412 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
413 | + al_cp.add(temp); | |
414 | + else if (mass_a > mass_t) | |
415 | + addPenMe(temp); | |
416 | + } | |
417 | + } | |
418 | + | |
419 | + protected void addKDN(Composition cp) throws Exception | |
420 | + { | |
421 | + addNeuAc(cp); // NeuAcを追加した構造 | |
422 | + | |
423 | + Composition temp = new Composition(cp); | |
424 | + if (Collections.frequency(temp,"kdn") < kdn_max) // 要素を探索し,個数を数える. | |
425 | + { | |
426 | + temp.add("kdn"); | |
427 | + double mass_t = temp.getMass(monoavg, adduct); | |
428 | + | |
429 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
430 | + al_cp.add(temp); | |
431 | + else if (mass_a > mass_t) | |
432 | + addKDN(temp); | |
433 | + } | |
434 | + } | |
435 | + | |
436 | + protected void addNeuAc(Composition cp) throws Exception | |
437 | + { | |
438 | + addNeuGc(cp); // NeuGcを追加した構造 | |
439 | + | |
440 | + Composition temp = new Composition(cp); | |
441 | + if (Collections.frequency(cp,"neuac") < neuac_max) // 要素を探索し,個数を数える. | |
442 | + { | |
443 | + temp.add("neuac"); | |
444 | + double mass_t = temp.getMass(monoavg, adduct); | |
445 | + | |
446 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
447 | + al_cp.add(temp); | |
448 | + else if (mass_a > mass_t) | |
449 | + addNeuAc(temp); | |
450 | + } | |
451 | + } | |
452 | + | |
453 | + protected void addNeuGc(Composition cp) throws Exception | |
454 | + { | |
455 | + Composition temp = new Composition(cp); | |
456 | + | |
457 | + if (Collections.frequency(temp,"neugc") < neugc_max) // 要素を探索し,個数を数える. | |
458 | + { | |
459 | + temp.add("neugc"); | |
460 | + double mass_t = temp.getMass(monoavg, adduct); | |
461 | + | |
462 | + if (Math.abs(mass_a - mass_t) < tolerance_ms) // 実測値と理論値との差が許容誤差以下ならば,追加 | |
463 | + al_cp.add(temp); | |
464 | + else if (mass_a > mass_t) | |
465 | + addNeuGc(temp); | |
466 | + } | |
467 | + } | |
468 | + | |
469 | + /** | |
470 | + * モノアイソトープ,またはアベレージで計算するかを設定します. | |
471 | + * @param monoavg モノアイソトピックまたはアベレージ. | |
472 | + */ | |
473 | + public void setMonoavg(boolean monoavg) throws Exception | |
474 | + { | |
475 | + this.monoavg = monoavg; // クラスメンバとする. | |
476 | + } | |
477 | + | |
478 | + /** | |
479 | + * 予測に用いる付加イオンを指定します. | |
480 | + * @param adduct 付加イオン(デフォルトはNa+) | |
481 | + */ | |
482 | + public void setAdduct(String adduct) throws Exception | |
483 | + { | |
484 | + this.adduct = adduct; // クラスメンバとする. | |
485 | + } | |
486 | + | |
487 | + /** | |
488 | + * 予測で考慮する各糖の糖数を指定します. | |
489 | + * @param str 糖数を指定する糖 | |
490 | + * @param max 指定する糖数 | |
491 | + */ | |
492 | + public void setMax(String str, int max) throws Exception | |
493 | + { // デフォルトはhex_max = 10, hexnac_max = 10, dhex_max = 10, dhexme_max = 0, pen_max = 0 | |
494 | + if (str.equals("hex")) | |
495 | + hex_max = max; | |
496 | + else if (str.equals("hexnac")) | |
497 | + hexnac_max = max; | |
498 | + else if (str.equals("dhex")) | |
499 | + dhex_max = max; | |
500 | + else if (str.equals("pen")) | |
501 | + pen_max = max; | |
502 | + else if (str.equals("hexme")) | |
503 | + hexme_max = max; | |
504 | + else if (str.equals("hexnacme")) | |
505 | + hexnacme_max = max; | |
506 | + else if (str.equals("dhexme")) | |
507 | + dhexme_max = max; | |
508 | + else if (str.equals("penme")) | |
509 | + penme_max = max; | |
510 | + else if (str.equals("kdn")) | |
511 | + kdn_max = max; | |
512 | + else if (str.equals("neuac")) | |
513 | + neuac_max = max; | |
514 | + else if (str.equals("neugc")) | |
515 | + neugc_max = max; | |
516 | + else | |
517 | + throw new Exception("Unknown glycan cannot setMax(): " + str); | |
518 | + } | |
519 | + | |
520 | + /** | |
521 | + * 予測で考慮する各糖の糖数を指定します.(糖数は自動入力) | |
522 | + * @param str 糖数を指定する糖 | |
523 | + */ | |
524 | + public void setMax(String str, boolean present) throws Exception | |
525 | + { | |
526 | + double temp = 0.0; // 予測に用いるm/zを格納する. | |
527 | + | |
528 | + if (mass_a != 0.0) // プレカーサーマスのm/zが登録されている場合, | |
529 | + temp = mass_a; | |
530 | + else if (masses_a != null) | |
531 | + { | |
532 | + Arrays.sort(masses_a); // フラグメントのm/zが登録されいる配列を昇順にソートし, | |
533 | + temp = masses_a[masses_a.length-1]; // 最大のm/zから組成を予測 | |
534 | + } | |
535 | + | |
536 | + if (present && temp != 0.0) // 予測したいm/zが登録されている場合は,その値から最大数を算出 | |
537 | + { | |
538 | + if (str.equals("hex")) | |
539 | + hex_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
540 | + else if (str.equals("hexnac")) | |
541 | + hexnac_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
542 | + else if (str.equals("dhex")) | |
543 | + dhex_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
544 | + else if (str.equals("pen")) | |
545 | + pen_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
546 | + else if (str.equals("hexme")) | |
547 | + hexme_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
548 | + else if (str.equals("hexnacme")) | |
549 | + hexnacme_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
550 | + else if (str.equals("dhexme")) | |
551 | + dhexme_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
552 | + else if (str.equals("penme")) | |
553 | + penme_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
554 | + else if (str.equals("kdn")) | |
555 | + kdn_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
556 | + else if (str.equals("neuac")) | |
557 | + neuac_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
558 | + else if (str.equals("neugc")) | |
559 | + neugc_max = (int)(temp / new Composition(str).getMass(monoavg, "")) + 1; | |
560 | + else | |
561 | + throw new Exception("Unknown glycan cannot setMax(): " + str); | |
562 | + } | |
563 | + else if (!present) // 糖が存在しないと指定された場合 | |
564 | + { | |
565 | + if (str.equals("hex")) // 糖数を0とする. | |
566 | + hex_max = 0; | |
567 | + else if (str.equals("hexnac")) | |
568 | + hexnac_max = 0; | |
569 | + else if (str.equals("dhex")) | |
570 | + dhex_max = 0; | |
571 | + else if (str.equals("pen")) | |
572 | + pen_max = 0; | |
573 | + else if (str.equals("hexme")) | |
574 | + hexme_max = 0; | |
575 | + else if (str.equals("hexnacme")) | |
576 | + hexnacme_max = 0; | |
577 | + else if (str.equals("dhexme")) | |
578 | + dhexme_max = 0; | |
579 | + else if (str.equals("penme")) | |
580 | + penme_max = 0; | |
581 | + else if (str.equals("kdn")) | |
582 | + kdn_max = 0; | |
583 | + else if (str.equals("neuac")) | |
584 | + neuac_max = 0; | |
585 | + else if (str.equals("neugc")) | |
586 | + neugc_max = 0; | |
587 | + else | |
588 | + throw new Exception("Unknown glycan cannot setMax(): " + str); | |
589 | + } | |
590 | + else // 登録されていない場合は,最大糖数を10とする. | |
591 | + { | |
592 | + if (str.equals("hex")) | |
593 | + hex_max = 10; | |
594 | + else if (str.equals("hexnac")) | |
595 | + hexnac_max = 10; | |
596 | + else if (str.equals("dhex")) | |
597 | + dhex_max = 10; | |
598 | + else if (str.equals("pen")) | |
599 | + pen_max = 10; | |
600 | + else if (str.equals("hexme")) | |
601 | + hexme_max = 10; | |
602 | + else if (str.equals("hexnacme")) | |
603 | + hexnacme_max = 10; | |
604 | + else if (str.equals("dhexme")) | |
605 | + dhexme_max = 10; | |
606 | + else if (str.equals("penme")) | |
607 | + penme_max = 10; | |
608 | + else if (str.equals("kdn")) | |
609 | + kdn_max = 10; | |
610 | + else if (str.equals("neuac")) | |
611 | + neuac_max = 10; | |
612 | + else if (str.equals("neugc")) | |
613 | + neugc_max = 10; | |
614 | + else | |
615 | + throw new Exception("Unknown glycan cannot setMax(): " + str); | |
616 | + } | |
617 | + } | |
618 | + | |
619 | + /** | |
620 | + * 既知糖鎖構造を追加します. | |
621 | + * @param known_gc 既知構造 | |
622 | + */ | |
623 | + public void setGlycan(Glycan known_gc) | |
624 | + { | |
625 | + this.known_gc = known_gc; | |
626 | + } | |
627 | + | |
628 | + /** | |
629 | + * 既知組成を追加します. | |
630 | + * @param known_cp 既知組成 | |
631 | + */ | |
632 | + public void setComposition(Composition known_cp) | |
633 | + { | |
634 | + this.known_cp = known_cp; | |
635 | + } | |
636 | + | |
637 | + /** | |
638 | + * 糖鎖組成の予測に用いるm/zを登録します. | |
639 | + * @param mass_a 組成を予測したいm/z | |
640 | + */ | |
641 | + public void setMass(double mass_a) | |
642 | + { | |
643 | + this.mass_a = mass_a; | |
644 | + } | |
645 | + | |
646 | + /** | |
647 | + * 糖鎖組成の予測に用いるm/zを登録します.(複数のm/zから組成まを予測する場合) | |
648 | + * @param masses_a 組成を予測したいm/zの配列 | |
649 | + */ | |
650 | + public void setMass(double[] masses_a) | |
651 | + { | |
652 | + this.masses_a = masses_a; | |
653 | + } | |
654 | + | |
655 | + /** | |
656 | + * 糖鎖組成の予測に用いる許容誤差を登録します. | |
657 | + * @param tolerance_ms 許容誤差 | |
658 | + */ | |
659 | + public void setMsTolerance(double tolerance_ms) | |
660 | + { | |
661 | + this.tolerance_ms = tolerance_ms; | |
662 | + } | |
663 | + | |
664 | + /** | |
665 | + * PSDスペクトルの実測値と理論値の許容誤差を登録します. | |
666 | + * @param tolerance_psd 実測値と理論値の許容誤差 | |
667 | + */ | |
668 | + public void setPsdTolerance(double tolerance_psd) throws Exception | |
669 | + { | |
670 | + this.tolerance_psd = tolerance_psd; // クラスメンバとする. | |
671 | + } | |
672 | + | |
673 | + /** | |
674 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
675 | + * @param lcb 長鎖塩基組成 | |
676 | + */ | |
677 | + public void setLongChainBase(List<String> lcb) throws Exception | |
678 | + { | |
679 | + for (String str : lcb) // 指定された長鎖塩基組成を登録 | |
680 | + if (str.matches("^[dt][0-9]+:[0-9]$")) // 通常の形式の場合 | |
681 | + this.lcb.add(str); | |
682 | + else if (str.matches("^[dt][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 個数に幅があった場合 | |
683 | + { | |
684 | + Pattern pt = Pattern.compile("^([dt])([0-9]+)(-([0-9]+))*:([0-9])(-([0-9]))*$"); | |
685 | + Matcher mt = pt.matcher(str); //( 1 )( 2 )(3( 4 )) ( 5 )(6( 7 ))でグループ化される. | |
686 | + | |
687 | + if (mt.matches()) | |
688 | + { | |
689 | + String temp = mt.group(1); // "([dt])"を取得 | |
690 | + int corbons_min = Integer.parseInt(mt.group(2)); // 最小炭素数(またはデフォルトの炭素数) | |
691 | + int corbons_max = corbons_min; // 何も指定されない場合は,デフォルトの炭素数 | |
692 | + if (mt.group(4) != null) | |
693 | + corbons_max = Integer.parseInt(mt.group(4)); // 最大炭素数を取得 | |
694 | + int bonds_min = Integer.parseInt(mt.group(5)); // 最小二重結合数(またはデフォルトの二重結合数) | |
695 | + int bonds_max = bonds_min; // 何も指定されない場合は,デフォルトの二重結合数 | |
696 | + if (mt.group(7) != null) | |
697 | + bonds_max = Integer.parseInt(mt.group(7)); // 最大二重結合数を取得 | |
698 | + | |
699 | + for (int corbons = corbons_min; corbons <= corbons_max; corbons++) | |
700 | + for (int bonds = bonds_min; bonds <= bonds_max; bonds++) | |
701 | + { | |
702 | + StringBuilder sb = new StringBuilder(temp); | |
703 | + sb.append(corbons); | |
704 | + sb.append(":"); | |
705 | + sb.append(bonds); | |
706 | + this.lcb.add(sb.toString()); // 1つずつ追加 | |
707 | + } | |
708 | + } | |
709 | + } | |
710 | + else | |
711 | + throw new Exception("Unknown lcb: " + str); | |
712 | + | |
713 | + if (fa.size() > 0) // 脂肪酸が登録されている場合, | |
714 | + setCeramide(); // 全セラミド組成を計算し,格納する. | |
715 | + } | |
716 | + | |
717 | + /** | |
718 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
719 | + * @param fa 脂肪酸組成 | |
720 | + */ | |
721 | + public void setFattyAcid(List<String> fa) throws Exception | |
722 | + { | |
723 | + for (String str : fa) // 指定された脂肪酸組成を登録 | |
724 | + if (str.matches("^[ch][0-9]+:[0-9]$")) // 通常の形式の場合 | |
725 | + this.fa.add(str); | |
726 | + else if (str.matches("^[ch][0-9]+(-[0-9]+)?:[0-9](-[0-9])?$")) // 個数に幅があった場合 | |
727 | + { | |
728 | + Pattern pt = Pattern.compile("^([ch])([0-9]+)(-([0-9]+))*:([0-9])(-([0-9]))*$"); | |
729 | + Matcher mt = pt.matcher(str); // ( 1 )( 2 )(3( 4 )) ( 5 )(6( 7 ))でグループ化される. | |
730 | + | |
731 | + if (mt.matches()) | |
732 | + { | |
733 | + String temp = mt.group(1); // "([ch])"を取得 | |
734 | + int corbons_min = Integer.parseInt(mt.group(2)); // 最小炭素数(またはデフォルトの炭素数) | |
735 | + int corbons_max = corbons_min; // 何も指定されない場合は,デフォルトの炭素数 | |
736 | + if (mt.group(4) != null) | |
737 | + corbons_max = Integer.parseInt(mt.group(4)); // 最大炭素数を取得 | |
738 | + int bonds_min = Integer.parseInt(mt.group(5)); // 最小二重結合数(またはデフォルトの二重結合数) | |
739 | + int bonds_max = bonds_min; // 何も指定されない場合は,デフォルトの二重結合数 | |
740 | + if (mt.group(7) != null) | |
741 | + bonds_max = Integer.parseInt(mt.group(7)); // 最大二重結合数を取得 | |
742 | + | |
743 | + for (int corbons = corbons_min; corbons <= corbons_max; corbons++) | |
744 | + for (int bonds = bonds_min; bonds <= bonds_max; bonds++) | |
745 | + { | |
746 | + StringBuilder sb = new StringBuilder(temp); | |
747 | + sb.append(corbons); | |
748 | + sb.append(":"); | |
749 | + sb.append(bonds); | |
750 | + this.fa.add(sb.toString()); // 1つずつ追加 | |
751 | + } | |
752 | + } | |
753 | + } | |
754 | + else | |
755 | + throw new Exception("Unknown fa: " + str); | |
756 | + | |
757 | + if (lcb.size() > 0) // 長鎖塩基が登録されている場合, | |
758 | + setCeramide(); // 全セラミド組成を計算し,格納する. | |
759 | + } | |
760 | + | |
761 | + /** | |
762 | + * 糖鎖組成の予測に用いる長鎖塩基組成を登録します. | |
763 | + * @param min 炭素数の最小値 | |
764 | + * @param max 炭素数の最大値 | |
765 | + */ | |
766 | + public void setLongChainBase(int min, int max) throws Exception | |
767 | + { | |
768 | + boolean flag = true; | |
769 | + | |
770 | + for (int i = 0, num = 0; flag; i++) | |
771 | + { | |
772 | + StringBuilder line = new StringBuilder(8); // lineに文字列を追加していく。 | |
773 | + num = i; // iの値を格納 | |
774 | + | |
775 | + // ノーマル型長鎖塩基かフィト型長鎖塩基か {0|1} | |
776 | + int lcbDoubleBonds = 0; | |
777 | + switch (num % 2) { | |
778 | + case 0 : line.append("d"); | |
779 | + lcbDoubleBonds++; | |
780 | + break; | |
781 | + case 1 : line.append("t"); | |
782 | + break; | |
783 | + } | |
784 | + num /= 2; | |
785 | + | |
786 | + // セラミドの炭素数 [max-min] | |
787 | + line.append(min + num % (max - min + 1)); | |
788 | + num /= max - min + 1; | |
789 | + | |
790 | + line.append(":"); | |
791 | + | |
792 | + // 長鎖塩基、脂肪酸の二重結合 [0-1],[0-1] | |
793 | + line.append(lcbDoubleBonds); | |
794 | + num /= 2; | |
795 | + | |
796 | + if (num == 0) | |
797 | + lcb.add(line.toString()); // セラミド組成をHashSetに追加 | |
798 | + else | |
799 | + flag = false; // for文を抜ける. | |
800 | + } | |
801 | + | |
802 | + if (fa.size() > 0) // 脂肪酸が登録されている場合, | |
803 | + setCeramide(); // 全セラミド組成を計算し,格納する. | |
804 | + } | |
805 | + | |
806 | + /** | |
807 | + * 糖鎖組成の予測に用いる脂肪酸組成を登録します. | |
808 | + * @param min 炭素数の最小値 | |
809 | + * @param max 炭素数の最大値 | |
810 | + */ | |
811 | + public void setFattyAcid(int min, int max, int bond) throws Exception | |
812 | + { | |
813 | + boolean flag = true; | |
814 | + | |
815 | + for (int i = 0, num = 0; flag; i++) | |
816 | + { | |
817 | + StringBuilder line = new StringBuilder(8); // lineに文字列を追加していく。 | |
818 | + num = i; // iの値を格納 | |
819 | + | |
820 | + // ノーマル脂肪酸かヒドロキシ脂肪酸か {0|1} | |
821 | + switch (num % 2) { | |
822 | + case 0 : line.append("c"); | |
823 | + break; | |
824 | + case 1 : line.append("h"); | |
825 | + break; | |
826 | + } | |
827 | + num /= 2; | |
828 | + | |
829 | + // セラミドの炭素数 [max-min] | |
830 | + line.append(min + num % (max - min + 1)); | |
831 | + num /= max - min + 1; | |
832 | + | |
833 | + line.append(":"); | |
834 | + | |
835 | + // 長鎖塩基、脂肪酸の二重結合 [0-1],[0-1] | |
836 | + line.append(num % (bond + 1)); | |
837 | + num /= bond + 1; | |
838 | + | |
839 | + if (num == 0) | |
840 | + fa.add(line.toString()); // セラミド組成をHashSetに追加 | |
841 | + else | |
842 | + flag = false; // for文を抜ける. | |
843 | + } | |
844 | + | |
845 | + if (lcb.size() > 0) // 長鎖塩基が登録されている場合, | |
846 | + setCeramide(); // 全セラミド組成を計算し,格納する. | |
847 | + } | |
848 | + | |
849 |