Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
StructureFile | 45 | 136 | 70 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.io; | |
22 | ||
23 | import java.awt.Color; | |
24 | import java.io.IOException; | |
25 | import java.lang.reflect.Constructor; | |
26 | import java.net.MalformedURLException; | |
27 | import java.util.List; | |
28 | import java.util.Vector; | |
29 | ||
30 | import jalview.analysis.AlignSeq; | |
31 | import jalview.api.FeatureSettingsModelI; | |
32 | import jalview.datamodel.Alignment; | |
33 | import jalview.datamodel.AlignmentAnnotation; | |
34 | import jalview.datamodel.AlignmentI; | |
35 | import jalview.datamodel.DBRefEntry; | |
36 | import jalview.datamodel.DBRefSource; | |
37 | import jalview.datamodel.PDBEntry; | |
38 | import jalview.datamodel.PDBEntry.Type; | |
39 | import jalview.datamodel.SequenceI; | |
40 | import jalview.ext.jmol.JmolParser; | |
41 | import jalview.structure.StructureImportSettings; | |
42 | import jalview.structure.StructureImportSettings.TFType; | |
43 | import mc_view.PDBChain; | |
44 | ||
45 | public abstract class StructureFile extends AlignFile | |
46 | { | |
47 | private String id; | |
48 | ||
49 | private PDBEntry.Type dbRefType; | |
50 | ||
51 | /** | |
52 | * set to true to add derived sequence annotations (temp factor read from | |
53 | * file, or computed secondary structure) to the alignment | |
54 | */ | |
55 | protected boolean visibleChainAnnotation = false; | |
56 | ||
57 | /** | |
58 | * Set true to predict secondary structure (using JMol for protein, Annotate3D | |
59 | * for RNA) | |
60 | */ | |
61 | protected boolean predictSecondaryStructure = false; | |
62 | ||
63 | /** | |
64 | * Set true (with predictSecondaryStructure=true) to predict secondary | |
65 | * structure using an external service (currently Annotate3D for RNA only) | |
66 | */ | |
67 | protected boolean externalSecondaryStructure = false; | |
68 | ||
69 | private Vector<PDBChain> chains; | |
70 | ||
71 | private boolean pdbIdAvailable; | |
72 | ||
73 | private TFType temperatureFactorType = TFType.DEFAULT; | |
74 | ||
75 | private String paeMatrix = null; | |
76 | ||
77 | private boolean alphaFoldModel; | |
78 | ||
79 | 42 | public void setPAEMatrix(String paeFilename) |
80 | { | |
81 | 42 | paeMatrix = paeFilename; |
82 | } | |
83 | ||
84 | 42 | public String getPAEMatrix() |
85 | { | |
86 | 42 | return paeMatrix; |
87 | } | |
88 | ||
89 | 193 | public boolean hasPAEMatrix() |
90 | { | |
91 | 193 | return paeMatrix != null; |
92 | } | |
93 | ||
94 | 170 | public void setTemperatureFactorType(TFType t) |
95 | { | |
96 | 170 | this.temperatureFactorType = t; |
97 | } | |
98 | ||
99 | 249 | public TFType getTemperatureFactorType() |
100 | { | |
101 | 249 | return temperatureFactorType; |
102 | } | |
103 | ||
104 | 115 | public void setAlphafoldModel(boolean afm) |
105 | { | |
106 | 115 | alphaFoldModel = afm; |
107 | } | |
108 | ||
109 | 442 | public boolean isAlphafoldModel() |
110 | { | |
111 | 442 | return alphaFoldModel; |
112 | } | |
113 | ||
114 | 0 | public StructureFile(Object inFile, DataSourceType sourceType) |
115 | throws IOException | |
116 | { | |
117 | 0 | this(inFile, sourceType, null); |
118 | } | |
119 | ||
120 | 21 | public StructureFile(Object inFile, DataSourceType sourceType, |
121 | TFType tempfacType) throws IOException | |
122 | { | |
123 | 21 | super(false, inFile, sourceType); |
124 | 21 | this.setTemperatureFactorType(tempfacType); |
125 | 21 | doParse(); |
126 | } | |
127 | ||
128 | 0 | public StructureFile(FileParse fp) throws IOException |
129 | { | |
130 | 0 | this(fp, true); |
131 | } | |
132 | ||
133 | 5 | public StructureFile(FileParse fp, boolean doXferSettings) |
134 | throws IOException | |
135 | { | |
136 | 5 | super(fp, doXferSettings); |
137 | } | |
138 | ||
139 | 165 | public void addSettings(boolean addAlignmentAnnotations, |
140 | boolean predictSecondaryStructure, boolean externalSecStr) | |
141 | { | |
142 | 165 | this.visibleChainAnnotation = addAlignmentAnnotations; |
143 | 165 | this.predictSecondaryStructure = predictSecondaryStructure; |
144 | 165 | this.externalSecondaryStructure = externalSecStr; |
145 | } | |
146 | ||
147 | 118 | public void xferSettings() |
148 | { | |
149 | 118 | if (this.getDoXferSettings()) |
150 | { | |
151 | 118 | this.visibleChainAnnotation = StructureImportSettings |
152 | .isVisibleChainAnnotation(); | |
153 | 118 | this.predictSecondaryStructure = StructureImportSettings |
154 | .isProcessSecondaryStructure(); | |
155 | 118 | this.externalSecondaryStructure = StructureImportSettings |
156 | .isExternalSecondaryStructure(); | |
157 | 118 | this.temperatureFactorType = StructureImportSettings |
158 | .getTemperatureFactorType(); | |
159 | } | |
160 | } | |
161 | ||
162 | 165 | public StructureFile(boolean parseImmediately, Object dataObject, |
163 | DataSourceType sourceType) throws IOException | |
164 | { | |
165 | 165 | super(parseImmediately, dataObject, sourceType); |
166 | } | |
167 | ||
168 | 0 | public StructureFile(boolean a, FileParse fp) throws IOException |
169 | { | |
170 | 0 | super(a, fp); |
171 | } | |
172 | ||
173 | 1 | public StructureFile() |
174 | { | |
175 | } | |
176 | ||
177 | 302 | protected SequenceI postProcessChain(PDBChain chain) |
178 | { | |
179 | 302 | SequenceI pdbSequence = chain.sequence; |
180 | 302 | pdbSequence.setName(getId() + "|" + pdbSequence.getName()); |
181 | 302 | PDBEntry entry = new PDBEntry(); |
182 | 302 | entry.setId(getId()); |
183 | 302 | entry.setFakedPDBId(!isPPDBIdAvailable()); |
184 | 302 | entry.setType(getStructureFileType()); |
185 | 302 | if (chain.id != null) |
186 | { | |
187 | 302 | entry.setChainCode(chain.id); |
188 | } | |
189 | 302 | if (inFile != null) |
190 | { | |
191 | 278 | entry.setFile(inFile.getAbsolutePath()); |
192 | } | |
193 | else | |
194 | { | |
195 | 24 | entry.setFile(getDataName()); |
196 | } | |
197 | ||
198 | 302 | DBRefEntry sourceDBRef = new DBRefEntry(); |
199 | 302 | sourceDBRef.setAccessionId(getId()); |
200 | 302 | sourceDBRef.setSource(DBRefSource.PDB); |
201 | // TODO: specify version for 'PDB' database ref if it is read from a file. | |
202 | // TODO: decide if jalview.io should be creating primary refs! | |
203 | 302 | sourceDBRef.setVersion(""); |
204 | 302 | pdbSequence.addPDBId(entry); |
205 | 302 | pdbSequence.addDBRef(sourceDBRef); |
206 | 302 | SequenceI chainseq = pdbSequence; |
207 | 302 | seqs.addElement(chainseq); |
208 | 302 | AlignmentAnnotation[] chainannot = chainseq.getAnnotation(); |
209 | ||
210 | 302 | if (chainannot != null && visibleChainAnnotation) |
211 | { | |
212 | 404 | for (int ai = 0; ai < chainannot.length; ai++) |
213 | { | |
214 | 202 | chainannot[ai].visible = visibleChainAnnotation; |
215 | 202 | annotations.addElement(chainannot[ai]); |
216 | } | |
217 | } | |
218 | 302 | return chainseq; |
219 | } | |
220 | ||
221 | /** | |
222 | * filetype of structure file - default is PDB | |
223 | */ | |
224 | String structureFileType = PDBEntry.Type.PDB.toString(); | |
225 | ||
226 | 350 | protected void setStructureFileType(String structureFileType) |
227 | { | |
228 | 350 | this.structureFileType = structureFileType; |
229 | } | |
230 | ||
231 | /** | |
232 | * filetype of last file processed | |
233 | * | |
234 | * @return | |
235 | */ | |
236 | 302 | public String getStructureFileType() |
237 | { | |
238 | 302 | return structureFileType; |
239 | } | |
240 | ||
241 | 0 | @SuppressWarnings({ "unchecked", "rawtypes" }) |
242 | protected void processPdbFileWithAnnotate3d(List<SequenceI> rna) | |
243 | throws Exception | |
244 | { | |
245 | // jalview.bin.Console.outPrintln("this is a PDB format and RNA sequence"); | |
246 | // note: we use reflection here so that the applet can compile and run | |
247 | // without the HTTPClient bits and pieces needed for accessing Annotate3D | |
248 | // web service | |
249 | 0 | try |
250 | { | |
251 | 0 | Class cl = Class.forName("jalview.ws.jws1.Annotate3D"); |
252 | 0 | if (cl != null) |
253 | { | |
254 | // TODO: use the PDB ID of the structure if one is available, to save | |
255 | // bandwidth and avoid uploading the whole structure to the service | |
256 | 0 | Object annotate3d = cl.getConstructor(new Class[] {}) |
257 | .newInstance(new Object[] {}); | |
258 | 0 | AlignmentI al = ((AlignmentI) cl |
259 | .getMethod("getRNAMLFor", new Class[] | |
260 | { FileParse.class }) | |
261 | .invoke(annotate3d, new Object[] | |
262 | { new FileParse(getDataName(), dataSourceType) })); | |
263 | 0 | for (SequenceI sq : al.getSequences()) |
264 | { | |
265 | 0 | if (sq.getDatasetSequence() != null) |
266 | { | |
267 | 0 | if (sq.getDatasetSequence().getAllPDBEntries() != null) |
268 | { | |
269 | 0 | sq.getDatasetSequence().getAllPDBEntries().clear(); |
270 | } | |
271 | } | |
272 | else | |
273 | { | |
274 | 0 | if (sq.getAllPDBEntries() != null) |
275 | { | |
276 | 0 | sq.getAllPDBEntries().clear(); |
277 | } | |
278 | } | |
279 | } | |
280 | 0 | replaceAndUpdateChains(rna, al, AlignSeq.DNA, false); |
281 | } | |
282 | } catch (ClassNotFoundException x) | |
283 | { | |
284 | // ignore classnotfounds - occurs in applet | |
285 | } | |
286 | } | |
287 | ||
288 | 5 | @SuppressWarnings("unchecked") |
289 | protected void replaceAndUpdateChains(List<SequenceI> prot, AlignmentI al, | |
290 | String pep, boolean b) | |
291 | { | |
292 | 5 | List<List<? extends Object>> replaced = AlignSeq |
293 | .replaceMatchingSeqsWith(seqs, annotations, prot, al, pep, | |
294 | false); | |
295 | 5 | for (PDBChain ch : getChains()) |
296 | { | |
297 | 14 | int p = 0; |
298 | 14 | for (SequenceI sq : (List<SequenceI>) replaced.get(0)) |
299 | { | |
300 | 30 | p++; |
301 | 30 | if (sq == ch.sequence || sq.getDatasetSequence() == ch.sequence) |
302 | { | |
303 | 14 | p = -p; |
304 | 14 | break; |
305 | } | |
306 | } | |
307 | 14 | if (p < 0) |
308 | { | |
309 | 14 | p = -p - 1; |
310 | // set shadow entry for chains | |
311 | 14 | ch.shadow = (SequenceI) replaced.get(1).get(p); |
312 | 14 | ch.shadowMap = ((AlignSeq) replaced.get(2).get(p)) |
313 | .getMappingFromS1(false); | |
314 | } | |
315 | } | |
316 | } | |
317 | ||
318 | /** | |
319 | * Predict secondary structure for RNA and/or protein sequences and add as | |
320 | * annotations | |
321 | * | |
322 | * @param rnaSequences | |
323 | * @param proteinSequences | |
324 | */ | |
325 | 5 | protected void addSecondaryStructure(List<SequenceI> rnaSequences, |
326 | List<SequenceI> proteinSequences) | |
327 | { | |
328 | /* | |
329 | * Currently using Annotate3D for RNA, but only if the 'use external | |
330 | * prediction' flag is set | |
331 | */ | |
332 | 5 | if (externalSecondaryStructure && rnaSequences.size() > 0) |
333 | { | |
334 | 0 | try |
335 | { | |
336 | 0 | processPdbFileWithAnnotate3d(rnaSequences); |
337 | } catch (Exception x) | |
338 | { | |
339 | 0 | jalview.bin.Console |
340 | .errPrintln("Exceptions when dealing with RNA in pdb file"); | |
341 | 0 | x.printStackTrace(); |
342 | ||
343 | } | |
344 | } | |
345 | ||
346 | /* | |
347 | * Currently using JMol PDB parser for peptide | |
348 | */ | |
349 | 5 | if (proteinSequences.size() > 0) |
350 | { | |
351 | 5 | try |
352 | { | |
353 | 5 | processWithJmolParser(proteinSequences, true); |
354 | } catch (Exception x) | |
355 | { | |
356 | 0 | jalview.bin.Console.errPrintln( |
357 | "Exceptions from Jmol when processing data in pdb file"); | |
358 | 0 | x.printStackTrace(); |
359 | } | |
360 | } | |
361 | } | |
362 | ||
363 | 5 | private void processWithJmolParser(List<SequenceI> prot, |
364 | boolean doXferSettings) throws MalformedURLException, IOException | |
365 | { | |
366 | 5 | FileParse fp = new FileParse(getDataName(), dataSourceType); |
367 | ||
368 | 5 | StructureImportSettings.setShowSeqFeatures(false); |
369 | 5 | StructureImportSettings.setVisibleChainAnnotation(false); |
370 | 5 | StructureImportSettings |
371 | .setProcessSecondaryStructure(predictSecondaryStructure); | |
372 | 5 | StructureImportSettings |
373 | .setExternalSecondaryStructure(externalSecondaryStructure); | |
374 | 5 | StructureImportSettings.setTemperatureFactorType(temperatureFactorType); |
375 | 5 | JmolParser jmf = new JmolParser(fp, doXferSettings); |
376 | 5 | AlignmentI al = new Alignment((SequenceI[]) jmf.getSeqsAsArray()); |
377 | 5 | jmf.addAnnotations(al); |
378 | 5 | for (SequenceI sq : al.getSequences()) |
379 | { | |
380 | 14 | if (sq.getDatasetSequence() != null) |
381 | { | |
382 | 0 | sq.getDatasetSequence().getAllPDBEntries().clear(); |
383 | } | |
384 | else | |
385 | { | |
386 | 14 | sq.getAllPDBEntries().clear(); |
387 | } | |
388 | } | |
389 | 5 | replaceAndUpdateChains(prot, al, AlignSeq.PEP, false); |
390 | 5 | StructureImportSettings.setShowSeqFeatures(true); |
391 | } | |
392 | ||
393 | /** | |
394 | * Answers the first PDBChain found matching the given id, or null if none is | |
395 | * found | |
396 | * | |
397 | * @param id | |
398 | * @return | |
399 | */ | |
400 | 48045 | public PDBChain findChain(String id) |
401 | { | |
402 | 48045 | for (PDBChain chain : getChains()) |
403 | { | |
404 | 82640 | if (chain.id.equals(id)) |
405 | { | |
406 | 47743 | return chain; |
407 | } | |
408 | } | |
409 | 302 | return null; |
410 | } | |
411 | ||
412 | 191 | public void makeResidueList() |
413 | { | |
414 | 191 | for (PDBChain chain : getChains()) |
415 | { | |
416 | 302 | chain.makeResidueList(visibleChainAnnotation); |
417 | } | |
418 | } | |
419 | ||
420 | 191 | public void makeCaBondList() |
421 | { | |
422 | 191 | for (PDBChain chain : getChains()) |
423 | { | |
424 | 302 | chain.makeCaBondList(); |
425 | } | |
426 | } | |
427 | ||
428 | 0 | public void setChargeColours() |
429 | { | |
430 | 0 | for (PDBChain chain : getChains()) |
431 | { | |
432 | 0 | chain.setChargeColours(); |
433 | } | |
434 | } | |
435 | ||
436 | 0 | public void setColours(jalview.schemes.ColourSchemeI cs) |
437 | { | |
438 | 0 | for (PDBChain chain : getChains()) |
439 | { | |
440 | 0 | chain.setChainColours(cs); |
441 | } | |
442 | } | |
443 | ||
444 | 0 | public void setChainColours() |
445 | { | |
446 | 0 | int i = 0; |
447 | 0 | for (PDBChain chain : getChains()) |
448 | { | |
449 | 0 | chain.setChainColours(Color.getHSBColor(1.0f / i++, .4f, 1.0f)); |
450 | } | |
451 | } | |
452 | ||
453 | 306 | public static boolean isRNA(SequenceI seq) |
454 | { | |
455 | 306 | int length = seq.getLength(); |
456 | 466 | for (int i = 0; i < length; i++) |
457 | { | |
458 | 465 | char c = seq.getCharAt(i); |
459 | 465 | if ((c != 'A') && (c != 'C') && (c != 'G') && (c != 'U')) |
460 | { | |
461 | 305 | return false; |
462 | } | |
463 | } | |
464 | 1 | return true; |
465 | } | |
466 | ||
467 | /** | |
468 | * make a friendly ID string. | |
469 | * | |
470 | * @param dataName | |
471 | * @return truncated dataName to after last '/' and pruned .extension if | |
472 | * present | |
473 | */ | |
474 | 76 | protected String safeName(String dataName) |
475 | { | |
476 | 76 | int p = 0; |
477 | ? | while ((p = dataName.indexOf("/")) > -1 && p < dataName.length()) |
478 | { | |
479 | 656 | dataName = dataName.substring(p + 1); |
480 | } | |
481 | 76 | if (dataName.indexOf(".") > -1) |
482 | { | |
483 | 74 | dataName = dataName.substring(0, dataName.lastIndexOf(".")); |
484 | } | |
485 | 76 | return dataName; |
486 | } | |
487 | ||
488 | 2263 | public String getId() |
489 | { | |
490 | 2263 | return id; |
491 | } | |
492 | ||
493 | 207 | public void setId(String id) |
494 | { | |
495 | 207 | this.id = id; |
496 | } | |
497 | ||
498 | 49298 | public Vector<PDBChain> getChains() |
499 | { | |
500 | 49298 | return chains; |
501 | } | |
502 | ||
503 | 191 | public void setChains(Vector<PDBChain> chains) |
504 | { | |
505 | 191 | this.chains = chains; |
506 | } | |
507 | ||
508 | 0 | public Type getDbRefType() |
509 | { | |
510 | 0 | return dbRefType; |
511 | } | |
512 | ||
513 | 16 | public void setDbRefType(String dbRefType) |
514 | { | |
515 | 16 | this.dbRefType = Type.getType(dbRefType); |
516 | } | |
517 | ||
518 | 18 | public void setDbRefType(Type dbRefType) |
519 | { | |
520 | 18 | this.dbRefType = dbRefType; |
521 | } | |
522 | ||
523 | /** | |
524 | * Returns a descriptor for suitable feature display settings with | |
525 | * <ul> | |
526 | * <li>ResNums or insertions features visible</li> | |
527 | * <li>insertions features coloured red</li> | |
528 | * <li>ResNum features coloured by label</li> | |
529 | * <li>Insertions displayed above (on top of) ResNums</li> | |
530 | * </ul> | |
531 | */ | |
532 | 17 | @Override |
533 | public FeatureSettingsModelI getFeatureColourScheme() | |
534 | { | |
535 | 17 | return new PDBFeatureSettings(); |
536 | } | |
537 | ||
538 | /** | |
539 | * Answers true if the structure file has a PDBId | |
540 | * | |
541 | * @return | |
542 | */ | |
543 | 302 | public boolean isPPDBIdAvailable() |
544 | { | |
545 | 302 | return pdbIdAvailable; |
546 | } | |
547 | ||
548 | 175 | public void setPDBIdAvailable(boolean pdbIdAvailable) |
549 | { | |
550 | 175 | this.pdbIdAvailable = pdbIdAvailable; |
551 | } | |
552 | } |