Source code: joelib/io/types/PDB.java
1 ///////////////////////////////////////////////////////////////////////////////
2 // Filename: $RCSfile: PDB.java,v $
3 // Purpose: Reader/Writer for Undefined files.
4 // Language: Java
5 // Compiler: JDK 1.4
6 // Authors: Joerg K. Wegner
7 // Version: $Revision: 1.11 $
8 // $Date: 2003/08/22 15:56:18 $
9 // $Author: wegner $
10 //
11 // Copyright (c) Dept. Computer Architecture, University of Tuebingen, Germany
12 //
13 // This program is free software; you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation version 2 of the License.
16 //
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 ///////////////////////////////////////////////////////////////////////////////
22 package joelib.io.types;
23
24 import cformat.PrintfFormat;
25 import cformat.PrintfStream;
26
27 import joelib.data.JOEElementTable;
28
29 import joelib.io.MoleculeFileType;
30 import joelib.io.MoleculeIOException;
31
32 import joelib.molecule.JOEAtom;
33 import joelib.molecule.JOEMol;
34 import joelib.molecule.JOEResidue;
35
36 import joelib.util.iterator.NbrAtomIterator;
37
38 /*==========================================================================*
39 * IMPORTS
40 *==========================================================================*/
41 import java.io.IOException;
42 import java.io.InputStream;
43 import java.io.InputStreamReader;
44 import java.io.LineNumberReader;
45 import java.io.OutputStream;
46
47 import org.apache.log4j.Category;
48
49
50 /*==========================================================================*
51 * CLASS DECLARATION
52 *========================================================================== */
53
54 /**
55 * Reader/Writer for Protein DataBank (PDB) files.
56 *
57 * @author wegnerj
58 * @license GPL
59 * @cvsversion $Revision: 1.11 $, $Date: 2003/08/22 15:56:18 $
60 * @cite pdbFormat
61 */
62 public class PDB implements MoleculeFileType
63 {
64 //~ Static fields/initializers /////////////////////////////////////////////
65
66 /*-------------------------------------------------------------------------*
67 * private static member variables
68 *------------------------------------------------------------------------- */
69
70 /**
71 * Obtain a suitable logger.
72 */
73 private static Category logger = Category.getInstance("joelib.io.types.PDB");
74 private final static String description = new String("Protein Data Bank");
75 private final static String[] extensions = new String[]{"pdb"};
76
77 //~ Instance fields ////////////////////////////////////////////////////////
78
79 /*-------------------------------------------------------------------------*
80 * private member variables
81 *------------------------------------------------------------------------- */
82 private LineNumberReader lnr;
83 private PrintfStream ps;
84
85 //~ Constructors ///////////////////////////////////////////////////////////
86
87 /*-------------------------------------------------------------------------*
88 * constructor
89 *------------------------------------------------------------------------- */
90
91 /**
92 * Constructor for the Undefined object
93 */
94 public PDB()
95 {
96 }
97
98 //~ Methods ////////////////////////////////////////////////////////////////
99
100 /**
101 * Description of the Method
102 *
103 * @exception IOException Description of the Exception
104 */
105 public void closeReader() throws IOException
106 {
107 }
108
109 /**
110 * Description of the Method
111 *
112 * @exception IOException Description of the Exception
113 */
114 public void closeWriter() throws IOException
115 {
116 }
117
118 /**
119 * Description of the Method
120 *
121 * @param is Description of the Parameter
122 * @exception IOException Description of the Exception
123 */
124 public void initReader(InputStream is) throws IOException
125 {
126 lnr = new LineNumberReader(new InputStreamReader(is));
127 }
128
129 /**
130 * Description of the Method
131 *
132 * @param os Description of the Parameter
133 * @exception IOException Description of the Exception
134 */
135 public void initWriter(OutputStream os) throws IOException
136 {
137 ps = new PrintfStream(os);
138 }
139
140 /*-------------------------------------------------------------------------*
141 * public methods
142 *------------------------------------------------------------------------- */
143
144 /**
145 * Description of the Method
146 *
147 * @return Description of the Return Value
148 */
149 public String inputDescription()
150 {
151 return description;
152 }
153
154 /**
155 * Description of the Method
156 *
157 * @return Description of the Return Value
158 */
159 public String[] inputFileExtensions()
160 {
161 return extensions;
162 }
163
164 /**
165 * Description of the Method
166 *
167 * @return Description of the Return Value
168 */
169 public String outputDescription()
170 {
171 return description;
172 }
173
174 /**
175 * Description of the Method
176 *
177 * @return Description of the Return Value
178 */
179 public String[] outputFileExtensions()
180 {
181 return extensions;
182 }
183
184 /**
185 * Reads an molecule entry as (unparsed) <tt>String</tt> representation.
186 *
187 * @return <tt>null</tt> if the reader contains no more
188 * relevant data. Otherwise the <tt>String</tt> representation of the
189 * whole molecule entry is returned.
190 * @exception IOException typical IOException
191 */
192 public String read() throws IOException
193 {
194 logger.error(
195 "Reading protein database entry as String representation is not implemented yet !!!");
196
197 return null;
198 }
199
200 /**
201 * Description of the Method
202 *
203 * @param mol Description of the Parameter
204 * @return Description of the Return Value
205 * @exception IOException Description of the Exception
206 * @exception MoleculeIOException Description of the Exception
207 */
208 public boolean read(JOEMol mol) throws IOException, MoleculeIOException
209 {
210 return read(mol, null);
211 }
212
213 /**
214 * Description of the Method
215 *
216 * @param mol Description of the Parameter
217 * @param title Description of the Parameter
218 * @return Description of the Return Value
219 * @exception IOException Description of the Exception
220 * @exception MoleculeIOException Description of the Exception
221 */
222 public boolean read(JOEMol mol, String title)
223 throws IOException, MoleculeIOException
224 {
225 // resdat.Init();
226 // int chainNum = 1;
227 // char buffer[BUFF_SIZE];
228 // OEBitVec bs;
229 //
230 // mol.BeginModify();
231 // while (ifs.getline(buffer,BUFF_SIZE) && !EQn(buffer,"END",3))
232 // {
233 // if (EQn(buffer,"TER",3)) chainNum++;
234 // if (EQn(buffer,"ATOM",4) || EQn(buffer,"HETATM",6))
235 // {
236 // ParseAtomRecord(buffer,mol,chainNum);
237 // if (EQn(buffer,"ATOM",4))
238 // bs.SetBitOn(mol.NumAtoms());
239 // }
240 //
241 // if (EQn(buffer,"CONECT",6))
242 // ParseConectRecord(buffer,mol);
243 // }
244 //
245 // resdat.AssignBonds(mol,bs);
246 // /*assign hetatm bonds based on distance*/
247 // mol.ConnectTheDots();
248 //
249 // mol.EndModify();
250 // mol.SetAtomTypesPerceived();
251 // atomtyper.AssignImplicitValence(mol);
252 //
253 // if (!mol.NumAtoms()) return(false);
254 // return(true);
255 return (false);
256 }
257
258 /**
259 * Description of the Method
260 *
261 * @return Description of the Return Value
262 */
263 public boolean readable()
264 {
265 return false;
266 }
267
268 /**
269 * Description of the Method
270 *
271 * @return Description of the Return Value
272 * @exception IOException Description of the Exception
273 */
274 public boolean skipReaderEntry() throws IOException
275 {
276 String line;
277
278 while ((line = lnr.readLine()) != null)
279 {
280 if ((line.length() > 0) && (line.charAt(0) == 'E') &&
281 (line.indexOf("END") != -1))
282 {
283 break;
284 }
285 }
286
287 return true;
288 }
289
290 /**
291 * Description of the Method
292 *
293 * @param mol Description of the Parameter
294 * @return Description of the Return Value
295 * @exception IOException Description of the Exception
296 * @exception MoleculeIOException Description of the Exception
297 */
298 public boolean write(JOEMol mol) throws IOException, MoleculeIOException
299 {
300 return write(mol, null);
301 }
302
303 /**
304 * Description of the Method
305 *
306 * @param mol Description of the Parameter
307 * @param title Description of the Parameter
308 * @return Description of the Return Value
309 * @exception IOException Description of the Exception
310 * @exception MoleculeIOException Description of the Exception
311 */
312 public boolean write(JOEMol mol, String title)
313 throws IOException, MoleculeIOException
314 {
315 // write header
316 ps.println("HEADER PROTEIN");
317
318 // write title
319 String tmpTitle = null;
320
321 if (title == null)
322 {
323 tmpTitle = mol.getTitle();
324
325 if ((tmpTitle == null) || (tmpTitle.trim().length() == 0))
326 {
327 ps.println("COMPND UNNAMED");
328 }
329 }
330 else
331 {
332 tmpTitle = title;
333 }
334
335 if (tmpTitle != null)
336 {
337 ps.print("COMPND ");
338 ps.print(tmpTitle);
339 ps.println(' ');
340 }
341
342 // write author
343 ps.println("AUTHOR GENERATED BY JOELIB " /*+JHM.version() */);
344
345 // initialize helper classes
346 JOEElementTable etab = JOEElementTable.instance();
347 PrintfFormat d3 = new PrintfFormat("%3d");
348 PrintfFormat d4 = new PrintfFormat("%4d");
349 PrintfFormat d5 = new PrintfFormat("%5d");
350 PrintfFormat s3 = new PrintfFormat("%3s");
351 PrintfFormat s4 = new PrintfFormat("%-4s");
352 PrintfFormat f9_3 = new PrintfFormat("%9.3f");
353 PrintfFormat f8_3 = new PrintfFormat("%8.3f");
354
355 // write atoms
356 JOEAtom atom;
357 JOEResidue res;
358 String typeName;
359 String paddedName = null;
360 int resNumber;
361 String resName;
362
363 for (int i = 1; i <= mol.numAtoms(); i++)
364 {
365 atom = mol.getAtom(i);
366 typeName = etab.getSymbol(atom.getAtomicNum());
367
368 if (typeName.length() > 1)
369 {
370 typeName = typeName.toUpperCase();
371 }
372
373 // has nothing to do with PDB, only used for a qick and dirty autodock export
374 // else
375 // {
376 // if(typeName.charAt(0)='C' && atom.isAromatic())typeName="A";
377 // }
378 if (atom.hasResidue())
379 {
380 res = atom.getResidue();
381 resName = res.getName();
382 typeName = res.getAtomID(atom);
383 resNumber = res.getNum();
384 }
385 else
386 {
387 resName = "UNK";
388
389 if (typeName.length() == 2)
390 {
391 paddedName = typeName;
392 }
393 else if (typeName.length() == 1)
394 {
395 paddedName = " " + typeName;
396 }
397 else if (typeName.length() == 0)
398 {
399 paddedName = " ";
400 }
401 else
402 {
403 paddedName = typeName.substring(0, 2);
404 }
405
406 typeName = paddedName;
407 resNumber = 1;
408 }
409
410 ps.print("ATOM ");
411 ps.printf(d4, i);
412 ps.print(" ");
413 ps.printf(s4, typeName);
414 ps.printf(s3, resName);
415 ps.printf(s3, "");
416 ps.printf(d3, resNumber);
417 ps.print(" ");
418 ps.printf(f9_3, atom.getX());
419 ps.printf(f8_3, atom.getY());
420 ps.printf(f8_3, atom.getZ());
421 ps.print(" ");
422 ps.print("1.00");
423 ps.print(" ");
424 ps.print("0.00");
425 ps.println(" ");
426 }
427
428 // write bonds
429 JOEAtom nbr;
430 NbrAtomIterator nait;
431
432 for (int i = 1; i <= mol.numAtoms(); i++)
433 {
434 atom = mol.getAtom(i);
435
436 if (atom.getValence() != 0)
437 {
438 ps.print("CONECT ");
439 ps.printf(d5, i);
440 nait = atom.nbrAtomIterator();
441
442 while (nait.hasNext())
443 {
444 nbr = nait.nextNbrAtom();
445 ps.printf(d5, nbr.getIdx());
446 }
447
448 ps.println();
449 }
450 }
451
452 ps.print("MASTER 0 0 0 0 0 0 0 0 ");
453 ps.printf(d4, mol.numAtoms());
454 ps.print(" 0 ");
455 ps.printf(d4, mol.numAtoms());
456 ps.println(" 0");
457
458 ps.println("END");
459
460 return (true);
461 }
462
463 /**
464 * Description of the Method
465 *
466 * @return Description of the Return Value
467 */
468 public boolean writeable()
469 {
470 return true;
471 }
472
473 /*-------------------------------------------------------------------------*
474 * private methods
475 *------------------------------------------------------------------------- */
476 static boolean parseAtomRecord(String line, JOEMol mol, int chainNum)
477 {
478 //ATOMFORMAT "(i5,1x,a4,a1,a3,1x,a1,i4,a1,3x,3f8.3,2f6.2,1x,i3)"
479 // string sbuf = &buffer[6];
480 // if (sbuf.size() < 48) return(false);
481 //
482 // bool hetatm = (EQn(buffer,"HETATM",6)) ? true : false;
483 //
484 // /* serial number */
485 // string serno = sbuf.substr(0,5);
486 // //SerialNum(the_atom) = atoi(tmp_str);
487 //
488 // /* atom name */
489 // string atmid = sbuf.substr(6,4);
490 //
491 // //trim spaces on the right and left sides
492 // while (!atmid.empty() && atmid[0] == ' ')
493 // atmid = atmid.substr(1,atmid.size()-1);
494 //
495 // while (!atmid.empty() && atmid[atmid.size()-1] == ' ')
496 // atmid = atmid.substr(0,atmid.size()-1);
497 //
498 // /* residue name */
499 //
500 // string resname = sbuf.substr(11,3);
501 // if (resname == " ")
502 // resname = "UNK";
503 // else
504 // {
505 // while (!resname.empty() && resname[0] == ' ')
506 // resname = resname.substr(1,resname.size()-1);
507 //
508 // while (!resname.empty() && resname[resname.size()-1] == ' ')
509 // resname = resname.substr(0,resname.size()-1);
510 // }
511 //
512 // /* residue sequence number */
513 //
514 // string resnum = sbuf.substr(16,4);
515 //
516 // /* X, Y, Z */
517 // string xstr = sbuf.substr(24,8);
518 // string ystr = sbuf.substr(32,8);
519 // string zstr = sbuf.substr(40,8);
520 //
521 // string type;
522 //
523 // if (EQn(buffer,"ATOM",4))
524 // {
525 // type = atmid.substr(0,1);
526 // if (isdigit(type[0]))
527 // type = atmid.substr(1,1);
528 //
529 // if (resname.substr(0,2) == "AS" || resname[0] == 'N')
530 // {
531 // if (atmid == "AD1") type = "O";
532 // if (atmid == "AD2") type = "N";
533 // }
534 // if (resname.substr(0,3) == "HIS" || resname[0] == 'H')
535 // {
536 // if (atmid == "AD1" || atmid == "AE2") type = "N";
537 // if (atmid == "AE1" || atmid == "AD2") type = "C";
538 // }
539 // if (resname.substr(0,2) == "GL" || resname[0] == 'Q')
540 // {
541 // if (atmid == "AE1") type = "O";
542 // if (atmid == "AE2") type = "N";
543 // }
544 // }
545 // else //must be hetatm record
546 // {
547 // if (isalpha(atmid[0])) type = atmid.substr(0,1);
548 // else type = atmid.substr(1,1);
549 // if (atmid == resname)
550 // {
551 // type = atmid;
552 // if (type.size() == 2) type[1] = tolower(type[1]);
553 // }
554 // else
555 // if (resname == "ADR" || resname == "COA" || resname == "FAD" ||
556 // resname == "GPG" || resname == "NAD" || resname == "NAL" ||
557 // resname == "NDP")
558 // {
559 // if (type.size() > 1)
560 // type = type.substr(0,1);
561 // //type.erase(1,type.size()-1);
562 // }
563 // else
564 // if (isdigit(type[0]))
565 // {
566 // type = type.substr(1,1);
567 // //type.erase(0,1);
568 // //if (type.size() > 1) type.erase(1,type.size()-1);
569 // }
570 // else
571 // if (type.size() > 1 && isdigit(type[1]))
572 // type = type.substr(0,1);
573 // //type.erase(1,1);
574 // else
575 // if (type.size() > 1 && isalpha(type[1]) && isupper(type[1]))
576 // type[1] = tolower(type[1]);
577 //
578 // }
579 //
580 // OEAtom atom;
581 // Vector v(atof(xstr.c_str()),atof(ystr.c_str()),atof(zstr.c_str()));
582 // atom.SetVector(v);
583 //
584 // atom.SetAtomicNum(etab.GetAtomicNum(type.c_str()));
585 // atom.SetType(type);
586 //
587 // int rnum = atoi(resnum.c_str());
588 // OEResidue *res = (mol.NumResidues() > 0) ? mol.GetResidue(mol.NumResidues()-1) : NULL;
589 // if (res == NULL || res->GetName() != resname || res->GetNum() != rnum)
590 // {
591 // vector<OEResidue*>::iterator ri;
592 // for (res = mol.BeginResidue(ri) ; res ; res = mol.NextResidue(ri))
593 // if (res->GetName() == resname && res->GetNum() == rnum)
594 // break;
595 //
596 // if (res == NULL)
597 // {
598 // res = mol.NewResidue();
599 // res->SetChainNum(chainNum);
600 // res->SetName(resname);
601 // res->SetNum(rnum);
602 // }
603 // }
604 //
605 // if (!mol.AddAtom(atom))
606 // return(false);
607 // else
608 // {
609 // OEAtom *atom = mol.GetAtom(mol.NumAtoms());
610 //
611 // res->AddAtom(atom);
612 // res->SetSerialNum(atom, atoi(serno.c_str()));
613 // res->SetAtomID(atom, atmid);
614 // res->SetHetAtom(atom, hetatm);
615 //
616 // return(true);
617 // }
618 return false;
619 }
620
621 //
622 //static bool ParseConectRecord(char *buffer,OEMol &mol)
623 //{
624 // vector<string> vs;
625 //
626 // buffer[70] = '\0';
627 // tokenize(vs,buffer);
628 // if (vs.empty()) return(false);
629 // vs.erase(vs.begin());
630 // int con1,con2,con3,con4;
631 // con1 = con2 = con3 = con4 = 0;
632 // int start = atoi(vs[0].c_str());
633 //
634 // if (vs.size() > 1) con1 = atoi(vs[1].c_str());
635 // if (vs.size() > 2) con2 = atoi(vs[2].c_str());
636 // if (vs.size() > 3) con3 = atoi(vs[3].c_str());
637 // if (vs.size() > 4) con4 = atoi(vs[4].c_str());
638 // if (!con1) return(false);
639 //
640 // OEAtom *a1,*a2;
641 // OEResidue *r1,*r2;
642 // vector<OEAtom*>::iterator i,j;
643 // for (a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i))
644 // {
645 // r1 = a1->GetResidue();
646 // if (r1->GetSerialNum(a1) == start)
647 // for (a2 = mol.BeginAtom(j);a2;a2 = mol.NextAtom(j))
648 // {
649 // r2 = a2->GetResidue();
650 // if (con1 && r2->GetSerialNum(a2) == con1)
651 // mol.AddBond(a1->GetIdx(),a2->GetIdx(),1);
652 // if (con2 && r2->GetSerialNum(a2) == con2)
653 // mol.AddBond(a1->GetIdx(),a2->GetIdx(),1);
654 // if (con3 && r2->GetSerialNum(a2) == con3)
655 // mol.AddBond(a1->GetIdx(),a2->GetIdx(),1);
656 // if (con4 && r2->GetSerialNum(a2) == con4)
657 // mol.AddBond(a1->GetIdx(),a2->GetIdx(),1);
658 // }
659 // }
660 //
661 // return(true);
662 //}
663 }
664 ///////////////////////////////////////////////////////////////////////////////
665 // END OF FILE.
666 ///////////////////////////////////////////////////////////////////////////////