Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/extended/medical/dna/pdb4dna/src/PDBlib.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 // This example is provided by the Geant4-DNA collaboration
 27 // Any report or published results obtained using the Geant4-DNA software
 28 // shall cite the following Geant4-DNA collaboration publication:
 29 // Med. Phys. 37 (2010) 4692-4708
 30 // Delage et al. PDB4DNA: implementation of DNA geometry from the Protein Data
 31 //                  Bank (PDB) description for Geant4-DNA Monte-Carlo
 32 //                  simulations (submitted to Comput. Phys. Commun.)
 33 // The Geant4-DNA web site is available at http://geant4-dna.org
 34 //
 35 //
 36 /// \file PDBlib.cc
 37 /// \brief Implementation file for PDBlib class
 38 
 39 #include "PDBlib.hh"
 40 
 41 // define if the program is running with Geant4
 42 #define GEANT4
 43 
 44 #ifdef GEANT4
 45 // Specific to Geant4, globals.hh is used for G4cout
 46 #  include "globals.hh"
 47 #else
 48 #  define G4cout std::cout
 49 #  define G4cerr std::cerr
 50 #  define G4endl std::endl
 51 #  define G4String std::string  // string included in PDBatom.hh
 52 #  include <cfloat>
 53 #endif
 54 #include <cmath>
 55 #include <fstream>
 56 #include <iostream>
 57 #include <limits>
 58 #include <sstream>
 59 #include <stdlib.h>
 60 
 61 using namespace std;
 62 
 63 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 64 
 65 PDBlib::PDBlib() : fNbNucleotidsPerStrand(0) {}
 66 
 67 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 68 
 69 /**
 70  * \brief    Load a PDB file into memory
 71  * \details  molecule (polymer,?),
 72  *                  read line, key words
 73  * \param    filename    G4String for filename
 74  * \param    isDNA
 75  * \param    verbose
 76  * \return   List of molecules
 77  */
 78 
 79 Molecule* PDBlib::Load(const std::string& filename, unsigned short int& isDNA,
 80                        unsigned short int verbose = 0)
 81 {
 82   G4String sLine = "";
 83   ifstream infile;
 84   infile.open(filename.c_str());
 85   if (!infile) {
 86     G4cout << "PDBlib::load >> file " << filename << " not found !!!!" << G4endl;
 87   }
 88   else {
 89     int nbAtom = 0;  // total number of atoms in a residue
 90     int numAtomInRes = 0;  // number of an atom in a residue
 91     int nbResidue = 0;  // total number of residues
 92     int nbMolecule = 0;  // total number of molecule
 93 
 94     Atom* AtomicOld = nullptr;
 95     Atom* AtomicNext = nullptr;
 96 
 97     int serial;  // Atom serial number
 98     G4String atomName;  // Atom name
 99     G4String element;  // Element Symbol
100     G4String resName;  // Residue name for this atom
101     double x, y, z;  // Orthogonal coordinates in Angstroms
102     double occupancy;  // Occupancy
103 
104     Residue* residueOld = nullptr;
105     Residue* residueFirst = nullptr;
106     Residue* residueNext = nullptr;
107 
108     Molecule* moleculeFirst = nullptr;
109     Molecule* moleculeOld = nullptr;
110     Molecule* moleculeNext = nullptr;
111 
112     /////////////////////////////////
113     // NEW variable to draw a fitting cylinder if z oriented
114     //=> fitting box
115     double minGlobZ, maxGlobZ;
116     double minGlobX, maxGlobX;
117     double minGlobY, maxGlobY;
118     double minX, maxX, minY, maxY, minZ, maxZ;  // Sort of 'mother volume' box
119 
120     minGlobZ = -DBL_MAX;
121     minGlobX = -DBL_MAX;
122     minGlobY = -DBL_MAX;
123     maxGlobZ = DBL_MAX;
124     maxGlobX = DBL_MAX;
125     maxGlobY = DBL_MAX;
126     minX = -DBL_MAX;
127     minY = -DBL_MAX;
128     minZ = -DBL_MAX;
129     maxX = DBL_MAX;
130     maxY = DBL_MAX;
131     maxZ = DBL_MAX;
132 
133     int lastResSeq = -1;
134     int resSeq = 0;
135 
136     G4String nameMol;
137 
138     unsigned short int numModel = 0;
139     unsigned short int model = 0;
140 
141     // Number of TER
142     int ter = 0;
143     // Number of TER (chain) max for this file
144 
145     int terMax = INT_MAX;
146 
147     if (!infile.eof()) {
148       getline(infile, sLine);
149       std::size_t found = sLine.find("DNA");
150       if (found != G4String::npos) {
151         terMax = 2;
152         isDNA = 1;
153       }
154       else
155         isDNA = 0;
156       // If PDB file have not a header line
157       found = sLine.find("HEADER");
158       if (found == G4String::npos) {
159         infile.close();
160         infile.open(filename.c_str());
161 
162         G4cout << "PDBlib::load >> No header found !!!!" << G4endl;
163       }
164     }
165 
166     while (!infile.eof()) {
167       getline(infile, sLine);
168       // In the case of several models
169       if ((sLine.substr(0, 6)).compare("NUMMDL") == 0) {
170         istringstream((sLine.substr(10, 4))) >> numModel;
171       }
172       if ((numModel > 0) && ((sLine.substr(0, 6)).compare("MODEL ") == 0)) {
173         istringstream((sLine.substr(10, 4))) >> model;
174         //////////////////////////////////////////
175         if (model > 1) break;
176         //////////////////////////////////////////
177       }
178       // For verification of residue sequence
179       if ((sLine.substr(0, 6)).compare("SEQRES") == 0) {
180         // Create list of molecule here
181         if (verbose > 1) G4cout << sLine << G4endl;
182       }
183 
184       // Coordinate section
185       if ((numModel > 0) && ((sLine.substr(0, 6)).compare("ENDMDL") == 0)) {
186         ;
187       }
188       else if ((sLine.substr(0, 6)).compare("TER   ") == 0)  // 3 spaces
189       {
190         //////////////////////////////////////////
191         // Currently retrieve only the two first chains(TER) => two DNA strands
192         ter++;
193         if (ter > terMax) break;
194         //////////////////////////////////////////
195 
196         // if (verbose>1) G4cout << sLine << G4endl;
197         /************ Begin TER ******************/
198         lastResSeq = -1;
199         resSeq = 0;
200 
201         AtomicOld->SetNext(NULL);
202         residueOld->SetNext(NULL);
203         residueOld->fNbAtom = nbAtom;
204 
205         // Molecule creation:
206         if (moleculeOld == NULL) {
207           nameMol = filename;  //+numModel
208           moleculeOld = new Molecule(nameMol, nbMolecule);
209           moleculeOld->SetFirst(residueFirst);
210           moleculeOld->fNbResidue = nbResidue;
211           moleculeFirst = moleculeOld;
212         }
213         else {
214           moleculeNext = new Molecule(nameMol, nbMolecule);
215           moleculeOld->SetNext(moleculeNext);
216           moleculeNext->SetFirst(residueFirst);
217           moleculeNext->fNbResidue = nbResidue;
218           moleculeOld = moleculeNext;
219         }
220 
221         nbMolecule++;
222         moleculeOld->SetNext(NULL);
223         moleculeOld->fCenterX = (int)((minX + maxX) / 2.);
224         moleculeOld->fCenterY = (int)((minY + maxY) / 2.);
225         moleculeOld->fCenterZ = (int)((minZ + maxZ) / 2.);
226         moleculeOld->fMaxGlobZ = maxGlobZ;
227         moleculeOld->fMinGlobZ = minGlobZ;
228         moleculeOld->fMaxGlobX = maxGlobX;
229         moleculeOld->fMinGlobX = minGlobX;
230         moleculeOld->fMaxGlobY = maxGlobY;
231         moleculeOld->fMinGlobY = minGlobY;
232 
233         minGlobZ = -DBL_MAX;
234         minGlobX = -DBL_MAX;
235         minGlobY = -DBL_MAX;
236         maxGlobZ = DBL_MAX;
237         maxGlobX = DBL_MAX;
238         maxGlobY = DBL_MAX;
239         minX = -DBL_MAX;
240         minY = -DBL_MAX;
241         minZ = -DBL_MAX;
242         maxX = DBL_MAX;
243         maxY = DBL_MAX;
244         maxZ = DBL_MAX;
245 
246         nbAtom = 0;
247         numAtomInRes = 0;
248         nbResidue = 0;
249         AtomicOld = NULL;
250         AtomicNext = NULL;
251         residueOld = NULL;
252         residueFirst = NULL;
253         residueNext = NULL;
254 
255         ///////////// End TER ///////////////////
256       }
257       else if ((sLine.substr(0, 6)).compare("ATOM  ") == 0) {
258         /************ Begin ATOM ******************/
259         // serial
260         istringstream((sLine.substr(6, 5))) >> serial;
261 
262         // To be improved
263         // atomName :
264         atomName = sLine.substr(12, 4);
265         if (atomName.substr(0, 1).compare(" ") == 0)
266           element = sLine.substr(13, 1);
267         else
268           element = sLine.substr(12, 1);
269 
270         // set Van der Waals radius expressed in Angstrom
271         double vdwRadius = -1.;
272         if (element == "H") {
273           vdwRadius = 1.2;
274         }
275         else if (element == "C") {
276           vdwRadius = 1.7;
277         }
278         else if (element == "N") {
279           vdwRadius = 1.55;
280         }
281         else if (element == "O") {
282           vdwRadius = 1.52;
283         }
284         else if (element == "P") {
285           vdwRadius = 1.8;
286         }
287         else if (element == "S") {
288           vdwRadius = 1.8;
289         }
290         else {
291 #ifndef GEANT4
292           G4cerr << "Element not recognized : " << element << G4endl;
293           G4cerr << "Stop now" << G4endl;
294           exit(1);
295 #else
296           G4ExceptionDescription errMsg;
297           errMsg << "Element not recognized : " << element << G4endl;
298 
299           G4Exception("PDBlib::Load", "ELEM_NOT_RECOGNIZED", FatalException, errMsg);
300 #endif
301         }
302 
303         {
304           // resName :
305           resName = sLine.substr(17, 3);
306           // resSeq :
307           istringstream((sLine.substr(22, 4))) >> resSeq;
308           // x,y,z :
309           stringstream((sLine.substr(30, 8))) >> x;
310           stringstream((sLine.substr(38, 8))) >> y;
311           stringstream((sLine.substr(46, 8))) >> z;
312           // occupancy :
313           occupancy = 1.;
314 
315           if (minGlobZ < z) minGlobZ = z;
316           if (maxGlobZ > z) maxGlobZ = z;
317           if (minGlobX < x) minGlobX = x;
318           if (maxGlobX > x) maxGlobX = x;
319           if (minGlobY < y) minGlobY = y;
320           if (maxGlobY > y) maxGlobY = y;
321           if (minX > x) minX = x;
322           if (maxX < x) maxX = x;
323           if (minY > y) minY = y;
324           if (maxY < y) maxY = y;
325           if (minZ > z) minZ = z;
326           if (maxZ < z) maxZ = z;
327 
328           // treatment for Atoms:
329           if (AtomicOld == NULL) {
330             AtomicOld =
331               new Atom(serial, atomName, "", 0, 0, x, y, z, vdwRadius, occupancy, 0, element);
332             AtomicOld->SetNext(NULL);  // If only one Atom inside residue
333           }
334           else {
335             AtomicNext =
336               new Atom(serial, atomName, "", 0, 0, x, y, z, vdwRadius, occupancy, 0, element);
337             AtomicOld->SetNext(AtomicNext);
338             AtomicOld = AtomicNext;
339           }
340           nbAtom++;
341         }  // END if (element!="H")
342         /****************************Begin Residue************************/
343         // treatment for residues:
344         if (residueOld == NULL) {
345           if (verbose > 2) G4cout << "residueOld == NULL" << G4endl;
346 
347           AtomicOld->fNumInRes = 0;
348           residueOld = new Residue(resName, resSeq);
349           residueOld->SetFirst(AtomicOld);
350           residueOld->SetNext(NULL);
351           residueFirst = residueOld;
352           lastResSeq = resSeq;
353           nbResidue++;
354         }
355         else {
356           if (lastResSeq == resSeq) {
357             numAtomInRes++;
358             AtomicOld->fNumInRes = numAtomInRes;
359           }
360           else {
361             numAtomInRes = 0;
362             AtomicOld->fNumInRes = numAtomInRes;
363 
364             residueNext = new Residue(resName, resSeq);
365             residueNext->SetFirst(AtomicOld);
366             residueOld->SetNext(residueNext);
367             residueOld->fNbAtom = nbAtom - 1;
368 
369             nbAtom = 1;
370             residueOld = residueNext;
371             lastResSeq = resSeq;
372             nbResidue++;
373           }
374         }
375         /////////////////////////End Residue////////////
376         ///////////// End ATOM ///////////////////
377       }  // END if Atom
378     }  // END while (!infile.eof())
379 
380     infile.close();
381     return moleculeFirst;
382   }  // END else if (!infile)
383   return NULL;
384 }
385 
386 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
387 
388 /**
389  * \brief    Compute barycenters
390  * \details  Compute barycenters and its coordinate
391  *                  for nucleotides
392  * \param    moleculeListTemp *    moleculeList
393  * \return   Barycenter *
394  */
395 Barycenter* PDBlib::ComputeNucleotideBarycenters(Molecule* moleculeListTemp)
396 {
397   ///////////////////////////////////////////////////////
398   // Placement and physical volume construction from memory
399   Barycenter* BarycenterFirst = NULL;
400   Barycenter* BarycenterOld = NULL;
401   Barycenter* BarycenterNext = NULL;
402 
403   // Residue (Base, Phosphate,sugar) list
404   Residue* residueListTemp;
405   // Atom list inside a residu
406   Atom* AtomTemp;
407 
408   int k = 0;
409   int j_old = 0;
410 
411   while (moleculeListTemp) {
412     residueListTemp = moleculeListTemp->GetFirst();
413 
414     k++;
415     int j = 0;
416 
417     // Check numerotation style (1->n per strand or 1->2n for two strand)
418     int correctNumerotationNumber = 0;
419     if (k == 2 && residueListTemp->fResSeq > 1) {
420       correctNumerotationNumber = residueListTemp->fResSeq;
421     }
422 
423     while (residueListTemp) {
424       AtomTemp = residueListTemp->GetFirst();
425       j++;
426 
427       // Correction consequently to numerotation check
428       if (correctNumerotationNumber != 0) {
429         residueListTemp->fResSeq = residueListTemp->fResSeq - correctNumerotationNumber + 1;
430       }
431 
432       // Barycenter computation
433       double baryX = 0., baryY = 0., baryZ = 0.;
434       double baryBaseX = 0., baryBaseY = 0., baryBaseZ = 0.;
435       double barySugX = 0., barySugY = 0., barySugZ = 0.;
436       double baryPhosX = 0., baryPhosY = 0., baryPhosZ = 0.;
437       unsigned short int nbAtomInBase = 0;
438 
439       for (int i = 0; i < residueListTemp->fNbAtom; i++) {
440         // Compute barycenter of the nucletotide
441         baryX += AtomTemp->fX;
442         baryY += AtomTemp->fY;
443         baryZ += AtomTemp->fZ;
444         // Compute barycenters for Base Sugar Phosphat
445         if (residueListTemp->fResSeq == 1) {
446           if (i == 0) {
447             baryPhosX += AtomTemp->fX;
448             baryPhosY += AtomTemp->fY;
449             baryPhosZ += AtomTemp->fZ;
450           }
451           else if (i < 8) {
452             barySugX += AtomTemp->fX;
453             barySugY += AtomTemp->fY;
454             barySugZ += AtomTemp->fZ;
455           }
456           else {
457             // hydrogen are placed at the end of the residue in a PDB file
458             // We don't want them for this calculation
459             if (AtomTemp->fElement != "H") {
460               baryBaseX += AtomTemp->fX;
461               baryBaseY += AtomTemp->fY;
462               baryBaseZ += AtomTemp->fZ;
463               nbAtomInBase++;
464             }
465           }
466         }
467         else {
468           if (i < 4) {
469             baryPhosX += AtomTemp->fX;
470             baryPhosY += AtomTemp->fY;
471             baryPhosZ += AtomTemp->fZ;
472           }
473           else if (i < 11) {
474             barySugX += AtomTemp->fX;
475             barySugY += AtomTemp->fY;
476             barySugZ += AtomTemp->fZ;
477           }
478           else {
479             // hydrogen are placed at the end of the residue in a PDB file
480             // We don't want them for this calculation
481             if (AtomTemp->fElement != "H") {  // break;
482               baryBaseX += AtomTemp->fX;
483               baryBaseY += AtomTemp->fY;
484               baryBaseZ += AtomTemp->fZ;
485               nbAtomInBase++;
486             }
487           }
488         }
489         AtomTemp = AtomTemp->GetNext();
490       }  // end of for (  i=0 ; i < residueListTemp->nbAtom ; i++)
491 
492       baryX = baryX / (double)residueListTemp->fNbAtom;
493       baryY = baryY / (double)residueListTemp->fNbAtom;
494       baryZ = baryZ / (double)residueListTemp->fNbAtom;
495 
496       if (residueListTemp->fResSeq != 1)  // Special case first Phosphate
497       {
498         baryPhosX = baryPhosX / 4.;
499         baryPhosY = baryPhosY / 4.;
500         baryPhosZ = baryPhosZ / 4.;
501       }
502       barySugX = barySugX / 7.;
503       barySugY = barySugY / 7.;
504       barySugZ = barySugZ / 7.;
505       baryBaseX = baryBaseX / (double)nbAtomInBase;
506       baryBaseY = baryBaseY / (double)nbAtomInBase;
507       baryBaseZ = baryBaseZ / (double)nbAtomInBase;
508 
509       // Barycenter creation:
510       if (BarycenterOld == NULL) {
511         BarycenterOld = new Barycenter(j + j_old, baryX, baryY, baryZ,  // j [1..n]
512                                        baryBaseX, baryBaseY, baryBaseZ, barySugX, barySugY,
513                                        barySugZ, baryPhosX, baryPhosY, baryPhosZ);
514         BarycenterFirst = BarycenterOld;
515       }
516       else {
517         BarycenterNext =
518           new Barycenter(j + j_old, baryX, baryY, baryZ, baryBaseX, baryBaseY, baryBaseZ, barySugX,
519                          barySugY, barySugZ, baryPhosX, baryPhosY, baryPhosZ);
520         BarycenterOld->SetNext(BarycenterNext);
521         BarycenterOld = BarycenterNext;
522       }
523 
524       /////////////////////////////////////////////////
525       // distance computation between all atoms inside
526       // a residue and the barycenter
527       AtomTemp = residueListTemp->GetFirst();
528       double dT3Dp;
529       double max = 0.;
530       for (int ii = 0; ii < residueListTemp->fNbAtom; ii++) {
531         dT3Dp = DistanceTwo3Dpoints(AtomTemp->fX, BarycenterOld->fCenterX, AtomTemp->fY,
532                                     BarycenterOld->fCenterY, AtomTemp->fZ, BarycenterOld->fCenterZ);
533         BarycenterOld->SetDistance(ii, dT3Dp);
534         if (dT3Dp > max) max = dT3Dp;
535         AtomTemp = AtomTemp->GetNext();
536       }  // end of for (  i=0 ; i < residueListTemp->nbAtom ; i++)
537 
538       BarycenterOld->SetRadius(max + 1.8);
539       residueListTemp = residueListTemp->GetNext();
540 
541     }  // end of while sur residueListTemp
542 
543     j_old += j;
544 
545     /// molecs->push_back(*moleculeListTemp);
546     moleculeListTemp = moleculeListTemp->GetNext();
547   }  // end of while sur moleculeListTemp
548 
549   if (BarycenterNext != NULL) {
550     BarycenterNext->SetNext(NULL);
551   }
552 
553   return BarycenterFirst;
554 }
555 
556 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
557 
558 /**
559  * \brief    the corresponding bounding volume parameters
560  * \details  the corresponding bounding volume parameters
561  *            to build a box from atoms coordinates
562  */
563 void PDBlib::ComputeBoundingVolumeParams(Molecule* moleculeListTemp, double& dX, double& dY,
564                                          double& dZ,  // Dimensions for bounding volume
565                                          double& tX, double& tY,
566                                          double& tZ)  // Translation for bounding volume
567 {
568   double minminX, minminY, minminZ;  // minimum minimorum
569   double maxmaxX, maxmaxY, maxmaxZ;  // maximum maximorum
570 
571   minminX = DBL_MAX;
572   minminY = DBL_MAX;
573   minminZ = DBL_MAX;
574   maxmaxX = -DBL_MAX;
575   maxmaxY = -DBL_MAX;
576   maxmaxZ = -DBL_MAX;
577 
578   while (moleculeListTemp) {
579     if (minminX > moleculeListTemp->fMaxGlobX) {
580       minminX = moleculeListTemp->fMaxGlobX;
581     }
582     if (minminY > moleculeListTemp->fMaxGlobY) {
583       minminY = moleculeListTemp->fMaxGlobY;
584     }
585     if (minminZ > moleculeListTemp->fMaxGlobZ) {
586       minminZ = moleculeListTemp->fMaxGlobZ;
587     }
588     if (maxmaxX < moleculeListTemp->fMinGlobX) {
589       maxmaxX = moleculeListTemp->fMinGlobX;
590     }
591     if (maxmaxY < moleculeListTemp->fMinGlobY) {
592       maxmaxY = moleculeListTemp->fMinGlobY;
593     }
594     if (maxmaxZ < moleculeListTemp->fMinGlobZ) {
595       maxmaxZ = moleculeListTemp->fMinGlobZ;
596     }
597 
598     moleculeListTemp = moleculeListTemp->GetNext();
599   }  // end of while sur moleculeListTemp
600 
601   dX = (maxmaxX - minminX) / 2. + 1.8;  // 1.8 => size of biggest radius for atoms
602   dY = (maxmaxY - minminY) / 2. + 1.8;
603   dZ = (maxmaxZ - minminZ) / 2. + 1.8;
604 
605   tX = minminX + (maxmaxX - minminX) / 2.;
606   tY = minminY + (maxmaxY - minminY) / 2.;
607   tZ = minminZ + (maxmaxZ - minminZ) / 2.;
608 }
609 
610 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
611 
612 /**
613  * \brief    Compute number of nucleotide per strand
614  * \details  Compute number of nucleotide per strand
615  *                  for DNA
616  */
617 void PDBlib::ComputeNbNucleotidsPerStrand(Molecule* moleculeListTemp)
618 {
619   Residue* residueListTemp;
620 
621   int j_old = 0;
622 
623   while (moleculeListTemp) {
624     residueListTemp = moleculeListTemp->GetFirst();
625 
626     int j = 0;
627 
628     while (residueListTemp) {
629       j++;
630       residueListTemp = residueListTemp->GetNext();
631     }  // end of while sur residueListTemp
632 
633     j_old += j;
634     moleculeListTemp = moleculeListTemp->GetNext();
635   }  // end of while sur moleculeListTemp
636 
637   fNbNucleotidsPerStrand = j_old / 2;
638 }
639 
640 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
641 
642 /**
643  * \brief    Compute barycenters
644  * \details  Compute barycenters and its coordinate
645  *                  for nucleotides
646  */
647 unsigned short int PDBlib::ComputeMatchEdepDNA(Barycenter* BarycenterList,
648                                                Molecule* moleculeListTemp, double x, double y,
649                                                double z, int& numStrand, int& numNucleotid,
650                                                int& codeResidue)
651 {
652   unsigned short int matchFound = 0;
653 
654   Molecule* mLTsavedPointer = moleculeListTemp;
655   Barycenter* BLsavedPointer = BarycenterList;
656 
657   short int strandNum = 0;  // Strand number
658   int residueNum = 1;  // Residue (nucleotide) number
659   G4String baseName;  // Base name [A,C,T,G]
660   unsigned short int BSP = 2;  // Base (default value), Sugar, Phosphat
661 
662   double smallestDist;  // smallest dist Atom <-> edep coordinates
663   double distEdepDNA;
664   double distEdepAtom;
665 
666   // Residue (Base, Phosphate,suggar) list
667   Residue* residueListTemp;
668   // Atom list inside a residue
669   Atom* AtomTemp;
670 
671   int k = 0;  // Molecule number
672   moleculeListTemp = mLTsavedPointer;
673   BarycenterList = BLsavedPointer;
674 
675   smallestDist = 33.0;  // Sufficiently large value
676   while (moleculeListTemp) {
677     k++;
678     residueListTemp = moleculeListTemp->GetFirst();
679 
680     int j = 0;  // Residue number
681 
682     int j_save = INT_MAX;  // Saved res. number if match found
683 
684     while (residueListTemp) {
685       j++;
686 
687       if (j - j_save > 2) break;
688 
689       distEdepDNA = DistanceTwo3Dpoints(x, BarycenterList->fCenterX, y, BarycenterList->fCenterY, z,
690                                         BarycenterList->fCenterZ);
691       if (distEdepDNA < BarycenterList->GetRadius()) {
692         // Find the closest atom
693         // Compute distance between energy deposited and atoms for a residue
694         // if distance <1.8 then match OK but search inside 2 next residues
695         AtomTemp = residueListTemp->GetFirst();
696         for (int iii = 0; iii < residueListTemp->fNbAtom; iii++) {
697           distEdepAtom =
698             DistanceTwo3Dpoints(x, AtomTemp->GetX(), y, AtomTemp->GetY(), z, AtomTemp->GetZ());
699 
700           if ((distEdepAtom < AtomTemp->GetVanDerWaalsRadius()) && (smallestDist > distEdepAtom)) {
701             strandNum = k;
702 
703             if (k == 2) {
704               residueNum = fNbNucleotidsPerStrand + 1 - residueListTemp->fResSeq;
705             }
706             else {
707               residueNum = residueListTemp->fResSeq;
708             }
709 
710             baseName = (residueListTemp->fResName)[2];
711             if (residueListTemp->fResSeq == 1) {
712               if (iii == 0)
713                 BSP = 0;  //"Phosphate"
714               else if (iii < 8)
715                 BSP = 1;  //"Sugar"
716               else
717                 BSP = 2;  //"Base"
718             }
719             else {
720               if (iii < 4)
721                 BSP = 0;  //"Phosphate"
722               else if (iii < 11)
723                 BSP = 1;  //"Sugar"
724               else
725                 BSP = 2;  //"Base"
726             }
727 
728             smallestDist = distEdepAtom;
729 
730             int j_max_value = INT_MAX;
731 
732             if (j_save == j_max_value) j_save = j;
733             matchFound = 1;
734           }
735           AtomTemp = AtomTemp->GetNext();
736         }  // end of for (  iii=0 ; iii < residueListTemp->nbAtom ; iii++)
737       }  // end for if (distEdepDNA < BarycenterList->GetRadius())
738       BarycenterList = BarycenterList->GetNext();
739       residueListTemp = residueListTemp->GetNext();
740     }  // end of while sur residueListTemp
741     moleculeListTemp = moleculeListTemp->GetNext();
742   }  // end of while sur moleculeListTemp
743 
744   numStrand = strandNum;
745   numNucleotid = residueNum;
746   codeResidue = BSP;
747 
748   return matchFound;
749 }
750 
751 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
752 
753 double PDBlib::DistanceTwo3Dpoints(double xA, double xB, double yA, double yB, double zA, double zB)
754 {
755   return sqrt((xA - xB) * (xA - xB) + (yA - yB) * (yA - yB) + (zA - zB) * (zA - zB));
756 }
757