Xmipp  v3.23.11-Nereus
pdb.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * Authors: Carlos Oscar Sanchez Sorzano (coss@cnb.csic.es)
4  *
5  * Unidad de Bioinformatica of Centro Nacional de Biotecnologia , CSIC
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20  * 02111-1307 USA
21  *
22  * All comments concerning this program package may be sent to the
23  * e-mail address 'xmipp@cnb.csic.es'
24  ***************************************************************************/
25 
26 #include <filesystem>
27 #include <fstream>
28 #include <iomanip>
29 #include <sstream>
30 #include <string>
31 #include "cif++.hpp"
32 #include "pdb.h"
33 #include "core/matrix2d.h"
34 #include "core/multidim_array.h"
35 #include "core/transformations.h"
36 #include "core/xmipp_fftw.h"
37 #include "core/xmipp_strings.h"
39 #include "data/integration.h"
40 #include "data/mask.h"
41 #include "data/numerical_tools.h"
42 
43 /* If you change the include guards, please be sure to also rename the
44  functions below. Otherwise your project will clash with the original
45  iotbx declarations and definitions.
46  */
47 #ifndef IOTBX_PDB_HYBRID_36_C_H
48 #define IOTBX_PDB_HYBRID_36_C_H
49 
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53 
54 #define HY36_WIDTH_4_MIN -999
55 #define HY36_WIDTH_4_MAX 2436111 /* 10000 + 2*26*36*36*36 - 1 */
56 #define HY36_WIDTH_5_MIN -9999
57 #define HY36_WIDTH_5_MAX 87440031 /* 100000 + 2*26*36*36*36*36 - 1 */
58 
59 #ifdef __cplusplus
60 }
61 #endif
62 #endif /* IOTBX_PDB_HYBRID_36_C_H */
63 
64 void analyzePDBAtoms(const FileName &fn_pdb, const std::string &typeOfAtom, int &numberOfAtoms, pdbInfo &at_pos)
65 {
66  //Open the pdb file
67  std::ifstream f2parse;
68  f2parse.open(fn_pdb.c_str());
69 
70  numberOfAtoms = 0;
71 
72  // Initializing and reading pdb file
73  PDBRichPhantom pdbFile;
74 
75  // Read centered pdb
76  pdbFile.read(fn_pdb.c_str());
77 
78  // For each atom, store necessary info if type matches
79  for (auto& atom : pdbFile.atomList) {
80  if (atom.name == typeOfAtom) {
81  numberOfAtoms++;
82 
83  // Storing coordinates
84  at_pos.x.push_back(atom.x);
85  at_pos.y.push_back(atom.y);
86  at_pos.z.push_back(atom.z);
87  at_pos.chain.push_back(std::string(1, atom.chainid));
88 
89  // Residue Number
90  at_pos.residue.push_back(atom.resseq);
91 
92  // Getting the bfactor = 8pi^2*u
93  at_pos.b.push_back(atom.bfactor); //sqrt(atom.bfactor/(8*PI*PI));
94 
95  // Covalent radius of the atom
96  at_pos.atomCovRad.push_back(atomCovalentRadius(atom.name));
97  }
98  }
99 }
100 
101 double AtomInterpolator::volumeAtDistance(char atom, double r) const
102 {
103  int idx=getAtomIndex(atom);
104  if (r>radii[idx])
105  return 0;
106  else
107  return volumeProfileCoefficients[idx].
108  interpolatedElementBSpline1D(r*M,3);
109 }
110 
111 double AtomInterpolator::projectionAtDistance(char atom, double r) const
112 {
113  int idx=getAtomIndex(atom);
114  if (r>radii[idx])
115  return 0;
116  else
117  return projectionProfileCoefficients[idx].
118  interpolatedElementBSpline1D(r*M,3);
119 }
120 
121 /* Atom charge ------------------------------------------------------------- */
122 int atomCharge(const std::string &atom)
123 {
124  switch (atom[0])
125  {
126  case 'H':
127  return 1;
128  break;
129  case 'C':
130  return 6;
131  break;
132  case 'N':
133  return 7;
134  break;
135  case 'O':
136  return 8;
137  break;
138  case 'P':
139  return 15;
140  break;
141  case 'S':
142  return 16;
143  break;
144  case 'E': // Iron Fe
145  return 26;
146  break;
147  case 'K':
148  return 19;
149  break;
150  case 'F':
151  return 9;
152  break;
153  case 'G': // Magnesium Mg
154  return 12;
155  break;
156  case 'L': // Chlorine Cl
157  return 17;
158  break;
159  case 'A': // Calcium Ca
160  return 20;
161  break;
162  default:
163  return 0;
164  }
165 }
166 
167 /* Atom radius ------------------------------------------------------------- */
168 double atomRadius(const std::string &atom)
169 {
170  switch (atom[0])
171  {
172  case 'H':
173  return 0.25;
174  break;
175  case 'C':
176  return 0.70;
177  break;
178  case 'N':
179  return 0.65;
180  break;
181  case 'O':
182  return 0.60;
183  break;
184  case 'P':
185  return 1.00;
186  break;
187  case 'S':
188  return 1.00;
189  break;
190  case 'E': // Iron Fe
191  return 1.40;
192  break;
193  case 'K':
194  return 2.20;
195  break;
196  case 'F':
197  return 0.50;
198  break;
199  case 'G': // Magnesium Mg
200  return 1.50;
201  break;
202  case 'L': // Chlorine Cl
203  return 1.00;
204  break;
205  case 'A': // Calcium Ca
206  return 1.80;
207  break;
208  default:
209  return 0;
210  }
211 }
212 
213 /* Atom Covalent radius ------------------------------------------------------------- */
214 double atomCovalentRadius(const std::string &atom)
215 {
216  switch (atom[0])
217  {
218  case 'H':
219  return 0.38;
220  case 'C':
221  return 0.77;
222  case 'N':
223  return 0.75;
224  case 'O':
225  return 0.73;
226  case 'P':
227  return 1.06;
228  case 'S':
229  return 1.02;
230  case 'F': // Iron
231  return 1.25;
232  default:
233  return 0;
234  }
235 }
236 
237 /* Compute geometry -------------------------------------------------------- */
238 void computePDBgeometry(const std::string &fnPDB,
239  Matrix1D<double> &centerOfMass,
240  Matrix1D<double> &limit0, Matrix1D<double> &limitF,
241  const std::string &intensityColumn)
242 {
243  // Initialization
244  centerOfMass.initZeros(3);
245  limit0.resizeNoCopy(3);
246  limitF.resizeNoCopy(3);
247  limit0.initConstant(1e30);
248  limitF.initConstant(-1e30);
249  double total_mass = 0;
250 
251  // Initialize PDBRichPhantom and read atom struct file
252  PDBRichPhantom pdbFile;
253 
254  // Read centered pdb
255  pdbFile.read(fnPDB);
256 
257  // For each atom, correct necessary info
258  bool useBFactor = intensityColumn=="Bfactor";
259  for (auto& atom : pdbFile.atomList) {
260  // Update center of mass and limits
261  XX(limit0) = std::min(XX(limit0), atom.x);
262  YY(limit0) = std::min(YY(limit0), atom.y);
263  ZZ(limit0) = std::min(ZZ(limit0), atom.z);
264 
265  XX(limitF) = std::max(XX(limitF), atom.x);
266  YY(limitF) = std::max(YY(limitF), atom.y);
267  ZZ(limitF) = std::max(ZZ(limitF), atom.z);
268 
269  double weight;
270  if (atom.name == "EN")
271  {
272  if (useBFactor)
273  weight = atom.bfactor;
274  else
275  weight = atom.occupancy;
276  }
277  else
278  {
279  if (atom.record == "HETATM")
280  continue;
281  weight = (double) atomCharge(atom.name);
282  }
283  total_mass += weight;
284  XX(centerOfMass) += weight * atom.x;
285  YY(centerOfMass) += weight * atom.y;
286  ZZ(centerOfMass) += weight * atom.z;
287  }
288 
289  // Finish calculations
290  centerOfMass /= total_mass;
291 }
292 
293 /* Apply geometry ---------------------------------------------------------- */
294 void applyGeometryToPDBFile(const std::string &fn_in, const std::string &fn_out,
295  const Matrix2D<double> &A, bool centerPDB,
296  const std::string &intensityColumn)
297 {
298  Matrix1D<double> centerOfMass;
299  Matrix1D<double> limit0;
300  Matrix1D<double> limitF;
301  if (centerPDB)
302  {
303  computePDBgeometry(fn_in, centerOfMass,limit0, limitF,
304  intensityColumn);
305  limit0 -= centerOfMass;
306  limitF -= centerOfMass;
307  }
308 
309  // Open files
310  std::ifstream fh_in;
311  fh_in.open(fn_in.c_str());
312  if (!fh_in)
314  std::ofstream fh_out;
315  fh_out.open(fn_out.c_str());
316  if (!fh_out)
317  REPORT_ERROR(ERR_IO_NOWRITE, fn_out);
318 
319  // Process all lines of the file
320  while (!fh_in.eof())
321  {
322  // Read an ATOM line
323  std::string line;
324  getline(fh_in, line);
325  if (line == "")
326  {
327  fh_out << "\n";
328  continue;
329  }
330  std::string kind = line.substr(0,4);
331  if (kind != "ATOM" && kind != "HETA")
332  {
333  fh_out << line << std::endl;
334  continue;
335  }
336 
337  // Extract atom type and position
338  // Typical line:
339  // ATOM 909 CA ALA A 161 58.775 31.984 111.803 1.00 34.78
340  double x = textToFloat(line.substr(30,8));
341  double y = textToFloat(line.substr(38,8));
342  double z = textToFloat(line.substr(46,8));
343 
344  Matrix1D<double> v(4);
345  if (centerPDB)
346  {
347  VECTOR_R3(v,x-XX(centerOfMass),
348  y-YY(centerOfMass),z-ZZ(centerOfMass));
349  }
350  else
351  {
352  VECTOR_R3(v,x,y,z);
353  }
354  v(3)=1;
355  v=A*v;
356 
357  char aux[15];
358  sprintf(aux,"%8.3f",XX(v));
359  line.replace(30,8,aux);
360  sprintf(aux,"%8.3f",YY(v));
361  line.replace(38,8,aux);
362  sprintf(aux,"%8.3f",ZZ(v));
363  line.replace(46,8,aux);
364 
365  fh_out << line << std::endl;
366  }
367 
368  // Close files
369  fh_in.close();
370  fh_out.close();
371 }
372 
384 bool checkExtension(const std::filesystem::path &filePath, const std::list<std::string> &acceptedExtensions, const std::list<std::string> &acceptedCompressions) {
385  // File extension is invalid by default
386  bool validExtension = false;
387 
388  // Checking if file extension is in accepted extensions with or without an accepted compression
389  if (find(acceptedExtensions.begin(), acceptedExtensions.end(), filePath.extension()) != acceptedExtensions.end()) {
390  // Accepted extension without compression
391  validExtension = true;
392  } else {
393  if (find(acceptedCompressions.begin(), acceptedCompressions.end(), filePath.extension()) != acceptedCompressions.end()) {
394  // Accepted compression detected
395  // Checking if next extension is valid
396  const std::filesystem::path shortedPath = filePath.parent_path().u8string() + "/" + filePath.stem().u8string();
397  if (find(acceptedExtensions.begin(), acceptedExtensions.end(), shortedPath.extension()) != acceptedExtensions.end()) {
398  // Accepted extension with compression
399  validExtension = true;
400  }
401  }
402  }
403 
404  // Returning calculated validity
405  return validExtension;
406 }
407 
408 template<typename callable>
417 void readPDB(const FileName &fnPDB, const callable &addAtom)
418 {
419  // Open file
420  std::ifstream fh_in;
421  fh_in.open(fnPDB.c_str());
422  if (!fh_in)
424 
425  // Process all lines of the file
426  std::string line;
427  std::string kind;
428  Atom atom;
429  while (!fh_in.eof())
430  {
431  // Read an ATOM line
432  getline(fh_in, line);
433  if (line == "")
434  continue;
435  kind = line.substr(0, 4);
436  if (kind != "ATOM" && kind != "HETA")
437  continue;
438 
439  // Extract atom type and position
440  // Typical line:
441  // ATOM 909 CA ALA A 161 58.775 31.984 111.803 1.00 34.78
442  atom.atomType = line[13];
443  atom.x = textToFloat(line.substr(30, 8));
444  atom.y = textToFloat(line.substr(38, 8));
445  atom.z = textToFloat(line.substr(46, 8));
446  addAtom(atom);
447  }
448 
449  // Close files
450  fh_in.close();
451 }
452 
453 template<typename callable>
463 void readCIF(const std::string &fnCIF, const callable &addAtom, cif::datablock &dataBlock)
464 {
465  // Parsing mmCIF file
466  cif::file cifFile;
467  cifFile.load(fnCIF);
468 
469  // Extrayendo datos del archivo en un DataBlock
470  cif::datablock& db = cifFile.front();
471 
472  // Reading Atom section
473  // Typical line:
474  // ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
475  cif::category& atom_site = db["atom_site"];
476 
477  // Iterating through atoms and heteroatoms getting atom id and x,y,z positions
478  Atom atom;
479  for (const auto& [atom_id, x_pos, y_pos, z_pos]: atom_site.find
480  <std::string,float,float,float>
481  (
482  cif::key("group_PDB") == "ATOM" || cif::key("group_PDB") == "HETATM",
483  "label_atom_id",
484  "Cartn_x",
485  "Cartn_y",
486  "Cartn_z"
487  ))
488  {
489  // Obtaining:
490  // ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
491  // * ****** ******* ******
492  atom.atomType = atom_id[0];
493  atom.x = x_pos;
494  atom.y = y_pos;
495  atom.z = z_pos;
496  addAtom(atom);
497  }
498 
499  // Storing whole datablock
500  dataBlock = db;
501 }
502 
503 void PDBPhantom::read(const FileName &fnPDB)
504 {
505  // Checking if extension is .cif or .pdb
506  if (checkExtension(fnPDB.getString(), {".cif"}, {".gz"})) {
507  readCIF(fnPDB.getString(), bind(&PDBPhantom::addAtom, this, std::placeholders::_1), dataBlock);
508  } else {
509  readPDB(fnPDB, bind(&PDBPhantom::addAtom, this, std::placeholders::_1));
510  }
511 }
512 
513 /* Shift ------------------------------------------------------------------- */
514 void PDBPhantom::shift(double x, double y, double z)
515 {
516  int imax=atomList.size();
517  for (int i=0; i<imax; i++)
518  {
519  atomList[i].x+=x;
520  atomList[i].y+=y;
521  atomList[i].z+=z;
522  }
523 }
524 
525 template<typename callable>
538 void readRichPDB(const FileName &fnPDB, const callable &addAtom, std::vector<double> &intensities,
539  std::vector<std::string> &remarks, const bool pseudoatoms, const double threshold)
540 {
541  // Open file
542  std::ifstream fh_in;
543  fh_in.open(fnPDB.c_str());
544  if (!fh_in)
546 
547  // Process all lines of the file
548  auto line = std::string(80, ' ');
549  std::string kind;
550 
551  RichAtom atom;
552  while (!fh_in.eof())
553  {
554  // Read an ATOM line
555  getline(fh_in, line);
556  if (line == "")
557  {
558  continue;
559  }
560 
561  // Reading and storing type of atom
562  kind = simplify(line.substr(0, 6)); // Removing extra spaces if there are any
563 
564  if (kind == "ATOM" || kind == "HETATM")
565  {
566  line.resize (80,' ');
567 
568  // Extract atom type and position
569  // Typical line:
570  // ATOM 909 CA ALA A 161 58.775 31.984 111.803 1.00 34.78
571  // ATOM 2 CA ALA A 1 73.796 56.531 56.644 0.50 84.78 C
572  atom.record = kind;
573  hy36decodeSafe(5, line.substr(6, 5).c_str(), 5, &atom.serial);
574  atom.name = simplify(line.substr(12, 4)); // Removing extra spaces if there are any
575  atom.altloc = line[16];
576  atom.resname = line.substr(17, 3);
577  atom.chainid = line[21];
578  hy36decodeSafe(4, line.substr(22, 4).c_str(), 4, &atom.resseq);
579  atom.icode = line[26];
580  atom.x = textToFloat(line.substr(30, 8));
581  atom.y = textToFloat(line.substr(38, 8));
582  atom.z = textToFloat(line.substr(46, 8));
583  atom.occupancy = textToFloat(line.substr(54, 6));
584  atom.bfactor = textToFloat(line.substr(60, 6));
585  if (line.length() >= 76 && simplify(line.substr(72, 4)) != "")
586  atom.segment = line.substr(72, 4);
587  if (line.length() >= 78 && simplify(line.substr(77, 1)) != "")
588  atom.atomType = line.substr(77, 1);
589  else
590  atom.atomType = atom.name[0];
591  if (line.length() >= 80 && simplify(line.substr(79, 1)) != "")
592  atom.charge = simplify(line.substr(79, 1)); // Converting into empty string if it is a space
593 
594  if(pseudoatoms)
595  intensities.push_back(atom.bfactor);
596 
597  if(!pseudoatoms && atom.bfactor >= threshold)
598  addAtom(atom);
599 
600  } else if (kind == "REMARK")
601  remarks.push_back(line);
602  }
603 
604  // Close files
605  fh_in.close();
606 }
607 
608 template<typename callable>
622 void readRichCIF(const std::string &fnCIF, const callable &addAtom, std::vector<double> &intensities,
623  const bool pseudoatoms, const double threshold, cif::datablock &dataBlock)
624 {
625  // Parsing mmCIF file
626  cif::file cifFile;
627  cifFile.load(fnCIF);
628 
629  // Extrayendo datos del archivo en un DataBlock
630  cif::datablock& db = cifFile.front();
631 
632  // Reading Atom section
633  cif::category& atom_site = db["atom_site"];
634 
635  // Iterating through atoms and heteroatoms getting atom id and x,y,z positions
636  RichAtom atom;
637  for (const auto& [record, serialNumber, atomId, altId, resName, chain, resSeq, seqId, iCode, xPos, yPos, zPos,
638  occupancy, bFactor, charge, authSeqId, authCompId, authAsymId, authAtomId, pdbNum]:
639  atom_site.find<std::string,int,std::string,std::string,std::string,std::string,int,int,std::string,float,
640  float,float,float,float,std::string,int,std::string,std::string,std::string,int>
641  (
642  // Note: search by key is needed to iterate list of atoms. Workaround: use every possible record type for the search
643  cif::key("group_PDB") == "ATOM" || cif::key("group_PDB") == "HETATM",
644  "group_PDB", // Record: -->ATOM<-- 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
645  "id", // Serial number: ATOM -->8<-- C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
646  "label_atom_id", // Id: ATOM 8 C -->CD1<-- . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
647  "label_alt_id", // Alt id: ATOM 8 C CD1 -->.<-- ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
648  "label_comp_id", // Chain name: ATOM 8 C CD1 . -->ILE<-- A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
649  "label_asym_id", // Chain location: ATOM 8 C CD1 . ILE -->A<-- 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
650  "label_entity_id", // Residue sequence:ATOM 8 C CD1 . ILE A -->1<-- 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
651  "label_seq_id", // Sequence id: ATOM 8 C CD1 . ILE A 1 -->3<-- ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
652  "pdbx_PDB_ins_code", // Ins code: ATOM 8 C CD1 . ILE A 1 3 -->?<-- 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
653  "Cartn_x", // X position: ATOM 8 C CD1 . ILE A 1 3 ? -->48.271<-- 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 1
654  "Cartn_y", // Y position: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 -->183.605<-- 19.253 1.00 35.73 ? 3 ILE A CD1 1
655  "Cartn_z", // Z position: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 -->19.253<-- 1.00 35.73 ? 3 ILE A CD1 1
656  "occupancy", // Occupancy: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 -->1.00<-- 35.73 ? 3 ILE A CD1 1
657  "B_iso_or_equiv", // B factor: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 -->35.73<-- ? 3 ILE A CD1 1
658  "pdbx_formal_charge", // Author charge: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 -->?<-- 3 ILE A CD1 1
659  "auth_seq_id", // Author seq id: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? -->3<-- ILE A CD1 1
660  "auth_comp_id", // Author chainname:ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 -->ILE<-- A CD1 1
661  "auth_asym_id", // Author chain loc:ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE -->A<-- CD1 1
662  "auth_atom_id", // Author id: ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A -->CD1<-- 1
663  "pdbx_PDB_model_num" // PDB model number:ATOM 8 C CD1 . ILE A 1 3 ? 48.271 183.605 19.253 1.00 35.73 ? 3 ILE A CD1 -->1<--
664  ))
665  {
666  // Storing values in atom list
667  atom.record = record;
668  atom.serial = serialNumber;
669  atom.name = atomId;
670  atom.atomType = atomId;
671  atom.altId = altId;
672  atom.resname = resName;
673  atom.altloc = chain;
674  atom.chainid = chain[0];
675  atom.resseq = resSeq;
676  atom.seqId = seqId;
677  atom.icode = iCode;
678  atom.x = xPos;
679  atom.y = yPos;
680  atom.z = zPos;
681  atom.occupancy = occupancy;
682  atom.bfactor = bFactor;
683  atom.charge = charge;
684  atom.authSeqId = authSeqId;
685  atom.authCompId = authCompId;
686  atom.authAsymId = authAsymId;
687  atom.authAtomId = authAtomId;
688  atom.pdbNum = pdbNum;
689 
690  // If it is a pseudoatom, insert B factor into intensities
691  if(pseudoatoms) {
692  intensities.push_back(bFactor);
693  } else {
694  // Adding atom if is not pseudoatom and B factor is not greater than set threshold
695  if (bFactor >= threshold)
696  addAtom(atom);
697  }
698  }
699 
700  // Storing whole datablock
701  dataBlock = db;
702 }
703 
704 void PDBRichPhantom::read(const FileName &fnPDB, const bool pseudoatoms, const double threshold)
705 {
706  // Checking if extension is .cif or .pdb
707  if (checkExtension(fnPDB.getString(), {".cif"}, {".gz"})) {
708  readRichCIF(fnPDB.getString(), bind(&PDBRichPhantom::addAtom, this, std::placeholders::_1), intensities, pseudoatoms, threshold, dataBlock);
709  } else {
710  readRichPDB(fnPDB, bind(&PDBRichPhantom::addAtom, this, std::placeholders::_1), intensities, remarks, pseudoatoms, threshold);
711  }
712 }
713 
714 template<typename callable>
725 void writePDB(const FileName &fnPDB, bool renumber, const std::vector<std::string> &remarks, const callable &atomList)
726 {
727  FILE* fh_out=fopen(fnPDB.c_str(),"w");
728  if (!fh_out)
730  size_t imax=remarks.size();
731  for (size_t i=0; i<imax; ++i)
732  fprintf(fh_out,"%s\n",remarks[i].c_str());
733 
734  imax=atomList.size();
735  for (size_t i=0; i<imax; ++i)
736  {
737  const RichAtom &atom=atomList[i];
738  char serial[5+1];
739  if (!renumber) {
740  auto* errmsg3 = hy36encode(5, atom.serial, serial);
741  if (errmsg3) {
742  reportWarning("Failed to use atom.serial. Using i+1 instead.");
743  renumber=true;
744  hy36encodeSafe(5, (int)i + 1, serial);
745  }
746  }
747  else {
748  // use i+1 instead
749  hy36encodeSafe(5, (int)i + 1, serial);
750  }
751  char resseq[4+1];
752  hy36encodeSafe(4, atom.resseq, resseq);
753  fprintf (fh_out,"%-6s%5s %-4s%s%-4s%c%4s%s %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%-2s\n",
754  atom.record.c_str(),serial,atom.name.c_str(),
755  atom.altloc.c_str(),atom.resname.c_str(),atom.chainid,
756  resseq,atom.icode.c_str(),
757  atom.x,atom.y,atom.z,atom.occupancy,atom.bfactor,
758  atom.segment.c_str(),atom.atomType.c_str(),atom.charge.c_str());
759  }
760  fclose(fh_out);
761 }
762 
763 template<typename callable>
773 void writeCIF(const std::string &fnCIF, const callable &atomList, cif::datablock &dataBlock)
774 {
775  // Opening CIF file
776  std::ofstream cifFile(fnCIF);
777 
778  // Creating atom_site category
779  cif::category atomSite("atom_site");
780  cif::row_initializer atomSiteInserter;
781 
782  // Declaring temporary variables for occupancy, coords, and Bfactor
783  std::stringstream tempStream;
784  std::string occupancy;
785  std::string xPos;
786  std::string yPos;
787  std::string zPos;
788  std::string bFactor;
789 
790  // Inserting data from atom list
791  for (RichAtom atom : atomList) {
792  // Converting occupancy to string with 2 fixed decimals
793  tempStream << std::fixed << std::setprecision(2) << atom.occupancy;
794  occupancy = tempStream.str();
795  tempStream.clear();
796  tempStream.str("");
797 
798  // Converting xPos to string with 3 fixed decimals
799  tempStream << std::fixed << std::setprecision(3) << atom.x;
800  xPos = tempStream.str();
801  tempStream.clear();
802  tempStream.str("");
803 
804  // Converting yPos to string with 3 fixed decimals
805  tempStream << std::fixed << std::setprecision(3) << atom.y;
806  yPos = tempStream.str();
807  tempStream.clear();
808  tempStream.str("");
809 
810  // Converting zPos to string with 3 fixed decimals
811  tempStream << std::fixed << std::setprecision(3) << atom.z;
812  zPos = tempStream.str();
813  tempStream.clear();
814  tempStream.str("");
815 
816  // Converting bFactor to string with 2 fixed decimals
817  tempStream << std::fixed << std::setprecision(2) << atom.bfactor;
818  bFactor = tempStream.str();
819  tempStream.clear();
820  tempStream.str("");
821 
822  // Defining row
823  // Empty string or char values are substitued with "." or '.' (no value)
824  // No "?" are inserted since it is not allowed by spec
825  atomSiteInserter = {
826  {"group_PDB", atom.record.empty() ? "." : atom.record},
827  {"id", atom.serial},
828  {"type_symbol", atom.name.empty() ? '.' : atom.name[0]},
829  {"label_atom_id", atom.name.empty() ? "." : atom.name},
830  {"label_alt_id", atom.altId.empty() ? "." : atom.altId},
831  {"label_comp_id", atom.resname.empty() ? "." : atom.resname},
832  {"label_asym_id", atom.altloc.empty() ? "." : atom.altloc},
833  {"label_entity_id", atom.resseq},
834  {"label_seq_id", atom.seqId},
835  {"pdbx_PDB_ins_code", atom.icode.empty() ? "." : atom.icode},
836  {"Cartn_x", xPos},
837  {"Cartn_y", yPos},
838  {"Cartn_z", zPos},
839  {"occupancy", occupancy},
840  {"B_iso_or_equiv", bFactor},
841  {"pdbx_formal_charge", atom.charge.empty() ? "." : atom.charge},
842  {"auth_seq_id", atom.authSeqId},
843  {"auth_comp_id", atom.authCompId.empty() ? "." : atom.authCompId},
844  {"auth_asym_id", atom.authAsymId.empty() ? "." : atom.authAsymId},
845  {"auth_atom_id", atom.authAtomId.empty() ? "." : atom.authAtomId},
846  {"pdbx_PDB_model_num", atom.pdbNum}
847  };
848 
849  // Inserting row
850  atomSite.emplace(std::move(atomSiteInserter));
851  }
852 
853  // Updating atom list in stored data block
854  auto categoryInsertPosition = std::find_if(
855  dataBlock.cbegin(), dataBlock.cend(),
856  [](const cif::category& cat) {
857  return cat.name() == "atom_site";
858  }
859  );
860  if (categoryInsertPosition != dataBlock.cend()) {
861  categoryInsertPosition = dataBlock.erase(categoryInsertPosition);
862  }
863  dataBlock.insert(categoryInsertPosition, atomSite);
864 
865  // Writing datablock to file
866  dataBlock.write(cifFile);
867 
868  // Closing file
869  cifFile.close();
870 }
871 
872 void PDBRichPhantom::write(const FileName &fnPDB, const bool renumber)
873 {
874  // Checking if extension is .cif or .pdb
875  if (checkExtension(fnPDB.getString(), {".cif"}, {".gz"})) {
876  writeCIF(fnPDB.getString(), atomList, dataBlock);
877  } else {
878  writePDB(fnPDB, renumber, remarks, atomList);
879  }
880 }
881 
882 /* Atom descriptors -------------------------------------------------------- */
883 void atomDescriptors(const std::string &atom, Matrix1D<double> &descriptors)
884 {
885  descriptors.initZeros(11);
886  if (atom=="H")
887  {
888  descriptors( 0)= 1; // Z
889  descriptors( 1)= 0.0088; // a1
890  descriptors( 2)= 0.0449; // a2
891  descriptors( 3)= 0.1481; // a3
892  descriptors( 4)= 0.2356; // a4
893  descriptors( 5)= 0.0914; // a5
894  descriptors( 6)= 0.1152; // b1
895  descriptors( 7)= 1.0867; // b2
896  descriptors( 8)= 4.9755; // b3
897  descriptors( 9)=16.5591; // b4
898  descriptors(10)=43.2743; // b5
899  }
900  else if (atom=="C")
901  {
902  descriptors( 0)= 6; // Z
903  descriptors( 1)= 0.0489; // a1
904  descriptors( 2)= 0.2091; // a2
905  descriptors( 3)= 0.7537; // a3
906  descriptors( 4)= 1.1420; // a4
907  descriptors( 5)= 0.3555; // a5
908  descriptors( 6)= 0.1140; // b1
909  descriptors( 7)= 1.0825; // b2
910  descriptors( 8)= 5.4281; // b3
911  descriptors( 9)=17.8811; // b4
912  descriptors(10)=51.1341; // b5
913  }
914  else if (atom=="N")
915  {
916  descriptors( 0)= 7; // Z
917  descriptors( 1)= 0.0267; // a1
918  descriptors( 2)= 0.1328; // a2
919  descriptors( 3)= 0.5301; // a3
920  descriptors( 4)= 1.1020; // a4
921  descriptors( 5)= 0.4215; // a5
922  descriptors( 6)= 0.0541; // b1
923  descriptors( 7)= 0.5165; // b2
924  descriptors( 8)= 2.8207; // b3
925  descriptors( 9)=10.6297; // b4
926  descriptors(10)=34.3764; // b5
927  }
928  else if (atom=="O")
929  {
930  descriptors( 0)= 8; // Z
931  descriptors( 1)= 0.0365; // a1
932  descriptors( 2)= 0.1729; // a2
933  descriptors( 3)= 0.5805; // a3
934  descriptors( 4)= 0.8814; // a4
935  descriptors( 5)= 0.3121; // a5
936  descriptors( 6)= 0.0652; // b1
937  descriptors( 7)= 0.6184; // b2
938  descriptors( 8)= 2.9449; // b3
939  descriptors( 9)= 9.6298; // b4
940  descriptors(10)=28.2194; // b5
941  }
942  else if (atom=="P")
943  {
944  descriptors( 0)=15; // Z
945  descriptors( 1)= 0.1005; // a1
946  descriptors( 2)= 0.4615; // a2
947  descriptors( 3)= 1.0663; // a3
948  descriptors( 4)= 2.5854; // a4
949  descriptors( 5)= 1.2725; // a5
950  descriptors( 6)= 0.0977; // b1
951  descriptors( 7)= 0.9084; // b2
952  descriptors( 8)= 4.9654; // b3
953  descriptors( 9)=18.5471; // b4
954  descriptors(10)=54.3648; // b5
955  }
956  else if (atom=="S")
957  {
958  descriptors( 0)=16; // Z
959  descriptors( 1)= 0.0915; // a1
960  descriptors( 2)= 0.4312; // a2
961  descriptors( 3)= 1.0847; // a3
962  descriptors( 4)= 2.4671; // a4
963  descriptors( 5)= 1.0852; // a5
964  descriptors( 6)= 0.0838; // b1
965  descriptors( 7)= 0.7788; // b2
966  descriptors( 8)= 4.3462; // b3
967  descriptors( 9)=15.5846; // b4
968  descriptors(10)=44.6365; // b5
969  }
970  else if (atom=="Fe")
971  {
972  descriptors( 0)=26; // Z
973  descriptors( 1)= 0.1929; // a1
974  descriptors( 2)= 0.8239; // a2
975  descriptors( 3)= 1.8689; // a3
976  descriptors( 4)= 2.3694; // a4
977  descriptors( 5)= 1.9060; // a5
978  descriptors( 6)= 0.1087; // b1
979  descriptors( 7)= 1.0806; // b2
980  descriptors( 8)= 4.7637; // b3
981  descriptors( 9)=22.8500; // b4
982  descriptors(10)=76.7309; // b5
983  }
984  else if (atom=="K")
985  {
986  descriptors( 0)=19; // Z
987  descriptors( 1)= 0.2149; // a1
988  descriptors( 2)= 0.8703; // a2
989  descriptors( 3)= 2.4999; // a3
990  descriptors( 4)= 2.3591; // a4
991  descriptors( 5)= 3.0318; // a5
992  descriptors( 6)= 0.1660; // b1
993  descriptors( 7)= 1.6906; // b2
994  descriptors( 8)= 8.7447; // b3
995  descriptors( 9)=46.7825; // b4
996  descriptors(10)=165.6923; // b5
997  }
998  else if (atom=="F")
999  {
1000  descriptors( 0)=9; // Z
1001  descriptors( 1)= 0.0382; // a1
1002  descriptors( 2)= 0.1822; // a2
1003  descriptors( 3)= 0.5972; // a3
1004  descriptors( 4)= 0.7707; // a4
1005  descriptors( 5)= 0.2130; // a5
1006  descriptors( 6)= 0.0613; // b1
1007  descriptors( 7)= 0.5753; // b2
1008  descriptors( 8)= 2.6858; // b3
1009  descriptors( 9)= 8.8214; // b4
1010  descriptors(10)=25.6668; // b5
1011  }
1012  else if (atom=="Mg")
1013  {
1014  descriptors( 0)=12; // Z
1015  descriptors( 1)= 0.1130; // a1
1016  descriptors( 2)= 0.5575; // a2
1017  descriptors( 3)= 0.9046; // a3
1018  descriptors( 4)= 2.1580; // a4
1019  descriptors( 5)= 1.4735; // a5
1020  descriptors( 6)= 0.1356; // b1
1021  descriptors( 7)= 1.3579; // b2
1022  descriptors( 8)= 6.9255; // b3
1023  descriptors( 9)=32.3165; // b4
1024  descriptors(10)=92.1138; // b5
1025  }
1026  else if (atom=="Cl")
1027  {
1028  descriptors( 0)=17; // Z
1029  descriptors( 1)= 0.0799; // a1
1030  descriptors( 2)= 0.3891; // a2
1031  descriptors( 3)= 1.0037; // a3
1032  descriptors( 4)= 2.3332; // a4
1033  descriptors( 5)= 1.0507; // a5
1034  descriptors( 6)= 0.0694; // b1
1035  descriptors( 7)= 0.6443; // b2
1036  descriptors( 8)= 3.5351; // b3
1037  descriptors( 9)=12.5058; // b4
1038  descriptors(10)=35.8633; // b5
1039  }
1040  else if (atom=="Ca")
1041  {
1042  descriptors( 0)=20; // Z
1043  descriptors( 1)= 0.2355; // a1
1044  descriptors( 2)= 0.9916; // a2
1045  descriptors( 3)= 2.3959; // a3
1046  descriptors( 4)= 3.7252; // a4
1047  descriptors( 5)= 2.5647; // a5
1048  descriptors( 6)= 0.1742; // b1
1049  descriptors( 7)= 1.8329; // b2
1050  descriptors( 8)= 8.8407; // b3
1051  descriptors( 9)=47.4583; // b4
1052  descriptors(10)=134.9613; // b5
1053  }
1054  else
1055  REPORT_ERROR(ERR_VALUE_INCORRECT,(std::string)"atomDescriptors: Unknown atom "+atom);
1056 }
1057 
1058 /* Electron form factor in Fourier ----------------------------------------- */
1059 double electronFormFactorFourier(double f, const Matrix1D<double> &descriptors)
1060 {
1061  double retval=0;
1062  for (int i=1; i<=5; i++)
1063  {
1064  double ai=VEC_ELEM(descriptors,i);
1065  double bi=VEC_ELEM(descriptors,i+5);
1066  retval+=ai*exp(-bi*f*f);
1067  }
1068  return retval;
1069 }
1070 
1071 /* Electron form factor in real space -------------------------------------- */
1072 /* We know the transform pair
1073  sqrt(pi/b)*exp(-x^2/(4*b)) <----> exp(-b*W^2)
1074 
1075  We also know that
1076 
1077  X(f)=sum_i ai exp(-bi*f^2)
1078 
1079  Therefore, using W=2*pi*f
1080 
1081  X(W)=sum_i ai exp(-bi/(2*pi)^2*W^2)
1082 
1083  Thus, the actual b for the inverse Fourier transform is bi/(2*pi)^2
1084  And we have to divide by 2*pi to account for the Jacobian of the
1085  transformation.
1086 */
1088  const Matrix1D<double> &descriptors)
1089 {
1090  double retval=0;
1091  for (int i=1; i<=5; i++)
1092  {
1093  double ai=descriptors(i);
1094  double bi=descriptors(i+5);
1095  double b=bi/(4*PI*PI);
1096  retval+=ai*sqrt(PI/b)*exp(-r*r/(4*b));
1097  }
1098  retval/=2*PI;
1099  return retval;
1100 }
1101 
1102 /* Computation of the low pass filter -------------------------------------- */
1103 // Returns the impulse response of the lowpass filter
1104 void hlpf(MultidimArray<double> &f, int M, const std::string &filterType,
1105  MultidimArray<double> &filter, double reductionFactor=0.8,
1106  double ripple=0.01, double deltaw=1.0/8.0)
1107 {
1108  filter.initZeros(XSIZE(f));
1109  filter.setXmippOrigin();
1110 
1111  auto Nmax=(int)CEIL(M/2.0);
1112  if (filterType=="SimpleAveraging")
1113  {
1115  if (ABS(i)<=Nmax)
1116  filter(i)=1.0/(2*Nmax+1);
1117  }
1118  else if (filterType=="SincKaiser")
1119  {
1120  int lastIdx=FINISHINGX(filter);
1121  SincKaiserMask(filter,reductionFactor*PI/M,ripple,deltaw);
1122  int newLastIdx=FINISHINGX(filter);
1123  if (newLastIdx>3*lastIdx)
1124  filter.selfWindow(-lastIdx,lastIdx);
1125  filter/=filter.sum();
1126  if (FINISHINGX(f)>FINISHINGX(filter))
1127  filter.selfWindow(STARTINGX(f),FINISHINGX(f));
1128  else
1129  f.selfWindow(STARTINGX(filter),FINISHINGX(filter));
1130  }
1131 }
1132 
1133 /* Convolution between f and the hlpf -------------------------------------- */
1135  int M, MultidimArray<double> &convolution)
1136 {
1137  // Expand the two input signals
1138  int Nmax=FINISHINGX(filter);
1139  MultidimArray<double> auxF;
1140  MultidimArray<double> auxFilter;
1141  auxF=f;
1142  auxFilter=filter;
1143  auxF.selfWindow(STARTINGX(f)-Nmax,FINISHINGX(f)+Nmax);
1144  auxFilter.selfWindow(STARTINGX(filter)-Nmax,FINISHINGX(filter)+Nmax);
1145 
1146  // Convolve in Fourier
1149  FourierTransform(auxF,F);
1150  FourierTransform(auxFilter,Filter);
1151  F*=Filter;
1152 
1153  // Correction for the double phase factor and the double
1154  // amplitude factor
1155  const double K1=2*PI*(STARTINGX(auxFilter)-1);
1156  const double K2=XSIZE(auxFilter);
1157  std::complex<double> aux;
1158  auto * ptrAux=(double*)&aux;
1160  {
1161  double w;
1162  FFT_IDX2DIGFREQ(i,XSIZE(F),w);
1163  double arg=w*K1;
1164  sincos(arg,ptrAux+1,ptrAux);
1165  *ptrAux*=K2;
1166  *(ptrAux+1)*=K2;
1167  A1D_ELEM(F,i)*=aux;
1168  }
1169  InverseFourierTransform(F,convolution);
1170  convolution.setXmippOrigin();
1171 }
1172 
1173 /* Optimization of the low pass filter to fit a given atom ----------------- */
1177 double globalT;
1178 std::string globalAtom;
1179 
1180 //#define DEBUG
1181 double Hlpf_fitness(double *p, void *prm)
1182 {
1183  double reductionFactor=p[1];
1184  double ripple=p[2];
1185  double deltaw=p[3];
1186 
1187  if (reductionFactor<0.7 || reductionFactor>1.3)
1188  return 1e38;
1189  if (ripple<0 || ripple>0.2)
1190  return 1e38;
1191  if (deltaw<1e-3 || deltaw>0.2)
1192  return 1e38;
1193 
1194  // Construct the filter with the current parameters
1195  MultidimArray<double> filter;
1196  MultidimArray<double> auxf;
1197  auxf=globalf;
1198  hlpf(auxf, globalM, "SincKaiser", filter, reductionFactor,
1199  ripple, deltaw);
1200 
1201  // Convolve the filter with the atomic profile
1202  MultidimArray<double> fhlpfFinelySampled;
1203  fhlpf(auxf, filter, globalM, fhlpfFinelySampled);
1204 
1205  // Coarsely sample
1206  double Rmax=FINISHINGX(fhlpfFinelySampled)*globalT;
1207  int imax=CEIL(Rmax/(globalM*globalT));
1208  MultidimArray<double> fhlpfCoarselySampled(2*imax+1);
1209  MultidimArray<double> splineCoeffsfhlpfFinelySampled;
1210  produceSplineCoefficients(xmipp_transformation::BSPLINE3,splineCoeffsfhlpfFinelySampled,fhlpfFinelySampled);
1211  fhlpfCoarselySampled.setXmippOrigin();
1212  FOR_ALL_ELEMENTS_IN_ARRAY1D(fhlpfCoarselySampled)
1213  {
1214  double r=i*(globalM*globalT)/globalT;
1215  fhlpfCoarselySampled(i)=
1216  splineCoeffsfhlpfFinelySampled.interpolatedElementBSpline1D(r,3);
1217  }
1218 
1219  // Build the frequency response of the convolved and coarsely sampled
1220  // atom
1222  MultidimArray<double> FfilterMag;
1223  MultidimArray<double> freq;
1225  aux=fhlpfCoarselySampled;
1226  aux.selfWindow(-10*FINISHINGX(aux),10*FINISHINGX(aux));
1227  FourierTransform(aux,Ffilter);
1228  FFT_magnitude(Ffilter,FfilterMag);
1229  freq.initZeros(XSIZE(Ffilter));
1230 
1231  FOR_ALL_ELEMENTS_IN_ARRAY1D(FfilterMag)
1232  FFT_IDX2DIGFREQ(i,XSIZE(FfilterMag),freq(i));
1233  freq/=globalM*globalT;
1234  double amplitudeFactor=fhlpfFinelySampled.sum()/
1235  fhlpfCoarselySampled.sum();
1236 
1237  // Compute the error in representation
1238  double error=0;
1239  Matrix1D<double> descriptors;
1240  atomDescriptors(globalAtom, descriptors);
1241  double iglobalT=1.0/globalT;
1242 #ifdef DEBUG
1243  MultidimArray<double> f1array, f2array;
1244  f1array.initZeros(FfilterMag);
1245  f2array.initZeros(FfilterMag);
1246 #endif
1247  double Npoints=0;
1248  FOR_ALL_ELEMENTS_IN_ARRAY1D(FfilterMag)
1249  if (A1D_ELEM(freq,i)>=0)
1250  {
1251  double f1=log10(A1D_ELEM(FfilterMag,i)*XSIZE(FfilterMag)*amplitudeFactor);
1252  double f2=log10(iglobalT*
1253  electronFormFactorFourier(A1D_ELEM(freq,i),descriptors));
1254  Npoints++;
1255  double diff=(f1-f2);
1256  error+=diff*diff;
1257 #ifdef DEBUG
1258  f1array(i)=f1;
1259  f2array(i)=f2;
1260  std::cout << "i=" << i << " wi=" << A1D_ELEM(freq,i) << " f1=" << f1 << " f2=" << f2 << " diff=" << diff << " err2=" << diff*diff << std::endl;
1261 #endif
1262  }
1263 #ifdef DEBUG
1264  f1array.write("PPPf1.txt");
1265  f2array.write("PPPf2.txt");
1266  std::cout << "Error " << error/Npoints << " " << Npoints << " M=" << globalM << " T=" << globalT << std::endl;
1267 #endif
1268 
1269  return error/Npoints;
1270 }
1271 
1285 void optimizeHlpf(MultidimArray<double> &f, int M, double T, const std::string &atom,
1286  MultidimArray<double> &filter, Matrix1D<double> &bestPrm)
1287 {
1288  globalHlpfPrm(0)=1.0; // reduction factor
1289  globalHlpfPrm(1)=0.01; // ripple
1290  globalHlpfPrm(2)=1.0/8.0; // deltaw
1291  globalf=f;
1292  globalM=M;
1293  globalT=T;
1294  globalAtom=atom;
1295  double fitness;
1296  int iter;
1298  steps.initConstant(1);
1299  powellOptimizer(globalHlpfPrm, 1, 3,
1300  &Hlpf_fitness, nullptr, 0.05, fitness, iter, steps, false);
1301  bestPrm=globalHlpfPrm;
1302  hlpf(f, M, "SincKaiser", filter, bestPrm(0), bestPrm(1), bestPrm(2));
1303 }
1304 
1305 /* Atom radial profile ----------------------------------------------------- */
1306 void atomRadialProfile(int M, double T, const std::string &atom,
1307  MultidimArray<double> &profile)
1308 {
1309  // Compute the electron form factor in real space
1310  double largestb1=76.7309/(4*PI*PI);
1311  double Rmax=4*sqrt(2*largestb1);
1312  auto imax=(int)CEIL(Rmax/T);
1313  Matrix1D<double> descriptors;
1314  atomDescriptors(atom, descriptors);
1315  MultidimArray<double> f(2*imax+1);
1316  f.setXmippOrigin();
1317  for (int i=-imax; i<=imax; i++)
1318  {
1319  double r=i*T;
1320  f(i)=electronFormFactorRealSpace(r,descriptors);
1321  }
1322 
1323  // Compute the optimal filter
1324  MultidimArray<double> filter;
1325  Matrix1D<double> bestPrm;
1326  optimizeHlpf(f, M, T, atom, filter, bestPrm);
1327 
1328  // Perform the convolution
1329  fhlpf(f, filter, M, profile);
1330 
1331  // Remove zero values
1332  int ileft=STARTINGX(profile);
1333  if (fabs(profile(ileft))<1e-3)
1334  for (ileft=STARTINGX(profile)+1; ileft<=0; ileft++)
1335  if (fabs(profile(ileft))>1e-3)
1336  break;
1337  int iright=FINISHINGX(profile);
1338  if (fabs(profile(iright))<1e-3)
1339  for (iright=FINISHINGX(profile)-1; iright>=0; iright--)
1340  if (fabs(profile(iright))>1e-3)
1341  break;
1342  profile.selfWindow(ileft,iright);
1343 }
1344 
1347 {
1348 public:
1349  int M;
1350  double r0_2;
1351  double z;
1353  virtual double operator()()
1354  {
1355  double r=M*sqrt(r0_2+z*z);
1356  if (ABS(r)>FINISHINGX(*profileCoefficients))
1357  return 0;
1358  return profileCoefficients->interpolatedElementBSpline1D(r,3);
1359  }
1360 };
1361 
1362 #define INTEGRATION 2
1364  const MultidimArray<double> &profileCoefficients,
1365  MultidimArray<double> &projectionProfile)
1366 {
1367  AtomValueFunc atomValue;
1368  atomValue.profileCoefficients=&profileCoefficients;
1369  atomValue.M=M;
1370  double radius=(double)FINISHINGX(profileCoefficients)/M;
1371  double r2=radius*radius;
1372 
1373  projectionProfile.initZeros(profileCoefficients);
1374  FOR_ALL_ELEMENTS_IN_ARRAY1D(projectionProfile)
1375  {
1376  double r0=(double)i/M;
1377  atomValue.r0_2=r0*r0;
1378  if (atomValue.r0_2>r2)
1379  continue; // Because of numerical instabilities
1380 
1381  double maxZ=sqrt(r2-atomValue.r0_2);
1382 
1383 #if INTEGRATION==1
1384 
1385  double dz=1/24.0;
1386  double integral=0;
1387  for (atomValue.z=-maxZ; atomValue.z<=maxZ; atomValue.z+=dz)
1388  {
1389  projectionProfile(i)+=atomValue();
1390  }
1391  projectionProfile(i)*=dz;
1392 #else
1393 
1394  Romberg Rom(atomValue, atomValue.z,-maxZ,maxZ);
1395  projectionProfile(i) = Rom();
1396 #endif
1397 
1398  }
1399 }
1400 
1402 void AtomInterpolator::setup(int m, double hights, bool computeProjection)
1403 {
1404  M=m;
1405  highTs=hights;
1406  if (volumeProfileCoefficients.size()==12)
1407  return;
1408  addAtom("H",computeProjection);
1409  addAtom("C",computeProjection);
1410  addAtom("N",computeProjection);
1411  addAtom("O",computeProjection);
1412  addAtom("P",computeProjection);
1413  addAtom("S",computeProjection);
1414  addAtom("Fe",computeProjection);
1415  addAtom("K",computeProjection);
1416  addAtom("F",computeProjection);
1417  addAtom("Mg",computeProjection);
1418  addAtom("Cl",computeProjection);
1419  addAtom("Ca",computeProjection);
1420 }
1421 
1422 void AtomInterpolator::addAtom(const std::string &atom, bool computeProjection)
1423 {
1424  MultidimArray<double> profile;
1425  MultidimArray<double> splineCoeffs;
1426 
1427  // Atomic profile
1428  atomRadialProfile(M, highTs, atom, profile);
1430  volumeProfileCoefficients.push_back(splineCoeffs);
1431 
1432  // Radius
1433  radii.push_back((double)FINISHINGX(profile)/M);
1434 
1435  // Projection profile
1436  if (computeProjection)
1437  {
1438  atomProjectionRadialProfile(M, splineCoeffs, profile);
1440  projectionProfileCoefficients.push_back(splineCoeffs);
1441  }
1442 }
1443 
1445 // Taken from phantom.cpp, Feature::project_to
1446 void projectAtom(const Atom &atom, Projection &P,
1447  const Matrix2D<double> &VP, const Matrix2D<double> &PV,
1448  const AtomInterpolator &interpolator)
1449 {
1450 constexpr float SUBSAMPLING = 2; // for every measure 2x2 line
1451  // integrals will be taken to
1452  // avoid numerical errors
1453 constexpr float SUBSTEP = 1/(SUBSAMPLING*2.0);
1454 
1455  Matrix1D<double> origin(3);
1457  VP.getRow(2, direction);
1458  direction.selfTranspose();
1459  Matrix1D<double> corner1(3);
1460  Matrix1D<double> corner2(3);
1461  Matrix1D<double> act(3);
1463 
1464  // Find center of the feature in the projection plane ...................
1465  // Step 1). Project the center to the plane, the result is in the
1466  // universal coord system
1467  Matrix1D<double> Center(3);
1468  VECTOR_R3(Center, atom.x, atom.y, atom.z);
1469  double max_distance=interpolator.atomRadius(atom.atomType);
1470  M3x3_BY_V3x1(origin, VP, Center);
1471 
1472  //#define DEBUG_LITTLE
1473 #ifdef DEBUG_LITTLE
1474 
1475  std::cout << "Actual atom\n" << atom.atomType << " ("
1476  << atom.x << "," << atom.y << "," << atom.z << ")\n";
1477  std::cout << "Center " << Center.transpose() << std::endl;
1478  std::cout << "VP matrix\n" << VP << std::endl;
1479  std::cout << "P.direction " << P.direction.transpose() << std::endl;
1480  std::cout << "direction " << direction.transpose() << std::endl;
1481  std::cout << "P.euler matrix " << P.euler << std::endl;
1482  std::cout << "max_distance " << max_distance << std::endl;
1483  std::cout << "origin " << origin.transpose() << std::endl;
1484 #endif
1485 
1486  // Find limits for projection ...........................................
1487  // Choose corners for the projection of this feature. It is supposed
1488  // to have at the worst case a projection of size max_distance
1489  VECTOR_R3(corner1, max_distance, max_distance, max_distance);
1490  VECTOR_R3(corner2, -max_distance, -max_distance, -max_distance);
1491 #ifdef DEBUG_LITTLE
1492 
1493  std::cout << "Corner1 : " << corner1.transpose() << std::endl
1494  << "Corner2 : " << corner2.transpose() << std::endl;
1495 #endif
1496 
1497  box_enclosing(corner1, corner2, VP, corner1, corner2);
1498 #ifdef DEBUG_LITTLE
1499 
1500  std::cout << "Corner1 moves to : " << corner1.transpose() << std::endl
1501  << "Corner2 moves to : " << corner2.transpose() << std::endl;
1502 #endif
1503 
1504  V3_PLUS_V3(corner1, origin, corner1);
1505  V3_PLUS_V3(corner2, origin, corner2);
1506 #ifdef DEBUG_LITTLE
1507 
1508  std::cout << "Corner1 finally is : " << corner1.transpose() << std::endl
1509  << "Corner2 finally is : " << corner2.transpose() << std::endl;
1510 #endif
1511  // Discard not necessary components
1512  corner1.resize(2);
1513  corner2.resize(2);
1514 
1515  // Clip to image size
1516  sortTwoVectors(corner1, corner2);
1517  XX(corner1) = CLIP(ROUND(XX(corner1)), STARTINGX(P()), FINISHINGX(P()));
1518  YY(corner1) = CLIP(ROUND(YY(corner1)), STARTINGY(P()), FINISHINGY(P()));
1519  XX(corner2) = CLIP(ROUND(XX(corner2)), STARTINGX(P()), FINISHINGX(P()));
1520  YY(corner2) = CLIP(ROUND(YY(corner2)), STARTINGY(P()), FINISHINGY(P()));
1521 
1522 #ifdef DEBUG_LITTLE
1523 
1524  std::cout << "corner1 " << corner1.transpose() << std::endl;
1525  std::cout << "corner2 " << corner2.transpose() << std::endl;
1526  std::cout.flush();
1527 #endif
1528 
1529  // Check if there is something to project
1530  if (XX(corner1) == XX(corner2))
1531  return;
1532  if (YY(corner1) == YY(corner2))
1533  return;
1534 
1535  // Study the projection for each point in the projection plane ..........
1536  // (u,v) are in the deformed projection plane (if any deformation)
1537  for (auto v = (int)YY(corner1); v <= (int)YY(corner2); v++)
1538  for (auto u = (int)XX(corner1); u <= (int)XX(corner2); u++)
1539  {
1540  double length = 0;
1541  //#define DEBUG_EVEN_MORE
1542 #ifdef DEBUG_EVEN_MORE
1543 
1544  std::cout << "Studying point (" << u << "," << v << ")\n";
1545  std::cout.flush();
1546 #endif
1547 
1548  // Perform subsampling ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
1549  double u0 = u - (int)(SUBSAMPLING / 2.0) * SUBSTEP;
1550  double v0 = v - (int)(SUBSAMPLING / 2.0) * SUBSTEP;
1551  double actv = v0;
1552  for (int subv = 0; subv < SUBSAMPLING; subv++)
1553  {
1554  double actu = u0;
1555  for (int subu = 0; subu < SUBSAMPLING; subu++)
1556  {
1557  // Compute the coordinates of point (subu,subv) which is
1558  // within the plane in the universal coordinate system
1559  XX(act) = actu;
1560  YY(act) = actv;
1561  ZZ(act) = 0;
1562  M3x3_BY_V3x1(act, PV, act);
1563 
1564  // Compute the intersection of a ray which passes through
1565  // this point and its direction is perpendicular to the
1566  // projection plane
1567  double r=point_line_distance_3D(Center, act, direction);
1568  double possible_length=interpolator.
1570  if (possible_length > 0)
1571  length += possible_length;
1572 
1573 #ifdef DEBUG_EVEN_MORE
1574 
1575  std::cout << "Averaging at (" << actu << "," << actv << ")\n";
1576  std::cout << " which in univ. coords is " << act.transpose() << std::endl;
1577  std::cout << " r=" << r << std::endl;
1578  std::cout << " intersection there " << possible_length << std::endl;
1579  std::cout.flush();
1580 #endif
1581  // Prepare for next iteration
1582  actu += SUBSTEP * 2.0;
1583  }
1584  actv += SUBSTEP * 2.0;
1585  }
1586  length /= (SUBSAMPLING * SUBSAMPLING);
1587  //#define DEBUG
1588 #ifdef DEBUG
1589 
1590  std::cout << "Final value added at position (" << u << "," << v << ")="
1591  << length << std::endl;
1592  std::cout.flush();
1593 #endif
1594 
1595  // Add at the correspondent pixel the found intersection ,,,,,,,,,,
1596  IMGPIXEL(P, v, u) += length;
1597  }
1598 }
1599 #undef DEBUG
1600 #undef DEBUG_LITTLE
1601 #undef DEBUG_EVEN_MORE
1602 
1603 void projectPDB(const PDBPhantom &phantomPDB,
1604  const AtomInterpolator &interpolator, Projection &proj,
1605  int Ydim, int Xdim, double rot, double tilt, double psi)
1606 {
1607  // Initialise projection
1608  proj().initZeros(Ydim, Xdim);
1609  proj().setXmippOrigin();
1610  proj.setAngles(rot, tilt, psi);
1611 
1612  // Compute volume to Projection matrix
1613  Matrix2D<double> VP = proj.euler;
1614  Matrix2D<double> PV = VP.inv();
1615 
1616  // Project all elements
1617  for (size_t i = 0; i < phantomPDB.getNumberOfAtoms(); i++)
1618  {
1619  try
1620  {
1621  projectAtom(phantomPDB.getAtom(i), proj, VP, PV, interpolator);
1622  }
1623  catch (XmippError &XE) {}
1624  }
1625 }
1626 
1627 void distanceHistogramPDB(const PDBPhantom &phantomPDB, size_t Nnearest, double maxDistance, int Nbins, Histogram1D &hist)
1628 {
1629  // Compute the histogram of distances
1630  const std::vector<Atom> &atoms=phantomPDB.atomList;
1631  int Natoms=atoms.size();
1632  MultidimArray<double> NnearestDistances;
1633  NnearestDistances.resize((Natoms-1)*Nnearest);
1634  for (int i=0; i<Natoms; i++)
1635  {
1636  std::vector<double> NnearestToThisAtom;
1637  const Atom& atom_i=atoms[i];
1638  for (int j=i+1; j<Natoms; j++)
1639  {
1640  const Atom& atom_j=atoms[j];
1641  double diffx=atom_i.x-atom_j.x;
1642  double diffy=atom_i.y-atom_j.y;
1643  double diffz=atom_i.z-atom_j.z;
1644  double dist=sqrt(diffx*diffx+diffy*diffy+diffz*diffz);
1645  if (maxDistance>0 && dist>maxDistance)
1646  continue;
1647  //std::cout << "Analyzing " << i << " and " << j << " -> d=" << dist << std::endl;
1648  size_t nearestSoFar=NnearestToThisAtom.size();
1649  if (nearestSoFar==0)
1650  {
1651  NnearestToThisAtom.push_back(dist);
1652  //std::cout << "Pushing d" << std::endl;
1653  }
1654  else
1655  {
1656  size_t idx=0;
1657  while (idx<nearestSoFar && NnearestToThisAtom[idx]<dist)
1658  idx++;
1659  if (idx<nearestSoFar)
1660  {
1661  NnearestToThisAtom.insert(NnearestToThisAtom.begin()+idx,1,dist);
1662  if (NnearestToThisAtom.size()>Nnearest)
1663  NnearestToThisAtom.erase(NnearestToThisAtom.begin()+Nnearest);
1664  }
1665  if (idx==nearestSoFar && nearestSoFar<Nnearest)
1666  {
1667  NnearestToThisAtom.push_back(dist);
1668  //std::cout << "Pushing d" << std::endl;
1669  }
1670  }
1671  }
1672  if (i<Natoms-1)
1673  for (size_t k=0; k<Nnearest; k++)
1674  NnearestDistances(i*Nnearest+k)=NnearestToThisAtom[k];
1675  }
1676  compute_hist(NnearestDistances, hist, 0, NnearestDistances.computeMax(), Nbins);
1677 }
1678 
1679 
1692 /* The following #include may be commented out.
1693  It is here only to enforce consistency of the declarations
1694  and the definitions.
1695  */
1696 // #include <iotbx/pdb/hybrid_36_c.h>
1697 
1698 /* All static functions below are implementation details
1699  (and not accessible from other translation units).
1700  */
1701 
1702 static
1703 const char*
1704 digits_upper() { return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
1705 
1706 static
1707 const char*
1708 digits_lower() { return "0123456789abcdefghijklmnopqrstuvwxyz"; }
1709 
1710 static
1711 const char*
1712 value_out_of_range() { return "value out of range."; }
1713 
1714 static
1715 const char* invalid_number_literal() { return "invalid number literal."; }
1716 
1717 static
1718 const char* unsupported_width() { return "unsupported width."; }
1719 
1720 static
1721 void
1722 fill_with_stars(unsigned width, char* result)
1723 {
1724  while (width) {
1725  *result++ = '*';
1726  width--;
1727  }
1728  *result = '\0';
1729 }
1730 
1731 static
1732 void
1733 encode_pure(
1734  const char* digits,
1735  unsigned digits_size,
1736  unsigned width,
1737  int value,
1738  char* result)
1739 {
1740  char buf[16];
1741  int rest;
1742  unsigned i, j;
1743  i = 0;
1744  j = 0;
1745  if (value < 0) {
1746  j = 1;
1747  value = -value;
1748  }
1749  while (1) {
1750  rest = value / digits_size;
1751  buf[i++] = digits[value - rest * digits_size];
1752  if (rest == 0) break;
1753  value = rest;
1754  }
1755  if (j) buf[i++] = '-';
1756  for(j=i;j<width;j++) *result++ = ' ';
1757  while (i != 0) *result++ = buf[--i];
1758  *result = '\0';
1759 }
1760 
1761 static
1762 const char*
1763 decode_pure(
1764  const int* digits_values,
1765  unsigned digits_size,
1766  const char* s,
1767  unsigned s_size,
1768  int* result)
1769 {
1770  int si, dv;
1771  int have_minus = 0;
1772  int have_non_blank = 0;
1773  int value = 0;
1774  unsigned i = 0;
1775  for(;i<s_size;i++) {
1776  si = s[i];
1777  if (si < 0 || si > 127) {
1778  *result = 0;
1779  return invalid_number_literal();
1780  }
1781  if (si == ' ') {
1782  if (!have_non_blank) continue;
1783  value *= digits_size;
1784  }
1785  else if (si == '-') {
1786  if (have_non_blank) {
1787  *result = 0;
1788  return invalid_number_literal();
1789  }
1790  have_non_blank = 1;
1791  have_minus = 1;
1792  continue;
1793  }
1794  else {
1795  have_non_blank = 1;
1796  dv = digits_values[si];
1797  if (dv < 0 || dv >= digits_size) {
1798  *result = 0;
1799  return invalid_number_literal();
1800  }
1801  value *= digits_size;
1802  value += dv;
1803  }
1804  }
1805  if (have_minus) value = -value;
1806  *result = value;
1807  return 0;
1808 }
1809 
1823 const char*
1824 hy36encode(unsigned width, int value, char* result)
1825 {
1826  int i = value;
1827  if (width == 4U) {
1828  if (i >= -999) {
1829  if (i < 10000) {
1830  encode_pure(digits_upper(), 10U, 4U, i, result);
1831  return 0;
1832  }
1833  i -= 10000;
1834  if (i < 1213056 /* 26*36**3 */) {
1835  i += 466560 /* 10*36**3 */;
1836  encode_pure(digits_upper(), 36U, 0U, i, result);
1837  return 0;
1838  }
1839  i -= 1213056;
1840  if (i < 1213056) {
1841  i += 466560;
1842  encode_pure(digits_lower(), 36U, 0U, i, result);
1843  return 0;
1844  }
1845  }
1846  }
1847  else if (width == 5U) {
1848  if (i >= -9999) {
1849  if (i < 100000) {
1850  encode_pure(digits_upper(), 10U, 5U, i, result);
1851  return 0;
1852  }
1853  i -= 100000;
1854  if (i < 43670016 /* 26*36**4 */) {
1855  i += 16796160 /* 10*36**4 */;
1856  encode_pure(digits_upper(), 36U, 0U, i, result);
1857  return 0;
1858  }
1859  i -= 43670016;
1860  if (i < 43670016) {
1861  i += 16796160;
1862  encode_pure(digits_lower(), 36U, 0U, i, result);
1863  return 0;
1864  }
1865  }
1866  }
1867  else {
1868  fill_with_stars(width, result);
1869  return unsupported_width();
1870  }
1871  fill_with_stars(width, result);
1872  return value_out_of_range();
1873 }
1874 
1891 const char*
1892 hy36decode(unsigned width, const char* s, unsigned s_size, int* result)
1893 {
1894  static int first_call = 1;
1895  static int digits_values_upper[128U];
1896  static int digits_values_lower[128U];
1897  static const char*
1898  ie_range = "internal error hy36decode: integer value out of range.";
1899  unsigned i;
1900  int di;
1901  const char* errmsg;
1902  if (first_call) {
1903  first_call = 0;
1904  for(i=0;i<128U;i++) digits_values_upper[i] = -1;
1905  for(i=0;i<128U;i++) digits_values_lower[i] = -1;
1906  for(i=0;i<36U;i++) {
1907  di = digits_upper()[i];
1908  if (di < 0 || di > 127) {
1909  *result = 0;
1910  return ie_range;
1911  }
1912  digits_values_upper[di] = i;
1913  }
1914  for(i=0;i<36U;i++) {
1915  di = digits_lower()[i];
1916  if (di < 0 || di > 127) {
1917  *result = 0;
1918  return ie_range;
1919  }
1920  digits_values_lower[di] = i;
1921  }
1922  }
1923  if (s_size == width) {
1924  di = s[0];
1925  if (di >= 0 && di <= 127) {
1926  if (digits_values_upper[di] >= 10) {
1927  errmsg = decode_pure(digits_values_upper, 36U, s, s_size, result);
1928  if (errmsg == 0) {
1929  /* result - 10*36**(width-1) + 10**width */
1930  if (width == 4U) (*result) -= 456560;
1931  else if (width == 5U) (*result) -= 16696160;
1932  else {
1933  *result = 0;
1934  return unsupported_width();
1935  }
1936  return 0;
1937  }
1938  }
1939  else if (digits_values_lower[di] >= 10) {
1940  errmsg = decode_pure(digits_values_lower, 36U, s, s_size, result);
1941  if (errmsg == 0) {
1942  /* result + 16*36**(width-1) + 10**width */
1943  if (width == 4U) (*result) += 756496;
1944  else if (width == 5U) (*result) += 26973856;
1945  else {
1946  *result = 0;
1947  return unsupported_width();
1948  }
1949  return 0;
1950  }
1951  }
1952  else {
1953  errmsg = decode_pure(digits_values_upper, 10U, s, s_size, result);
1954  if (errmsg) return errmsg;
1955  if (!(width == 4U || width == 5U)) {
1956  *result = 0;
1957  return unsupported_width();
1958  }
1959  return 0;
1960  }
1961  }
1962  }
1963  *result = 0;
1964  return invalid_number_literal();
1965 }
1966 
1967 // safe function for hy36decode
1968 void hy36decodeSafe(unsigned width, const char* s, unsigned s_size, int* result)
1969 {
1970  auto* errmsg = hy36decode(width, s, s_size, result);
1971  if (errmsg) {
1973  }
1974 }
1975 
1976 // safe function for hy36encode
1977 void hy36encodeSafe(unsigned width, int value, char* result)
1978 {
1979  const char* errmsg = hy36encode(width, value, result);
1980  if (errmsg) {
1982  }
1983 }
void read(const FileName &fnPDB)
Read phantom from either a PDB of CIF file.
Definition: pdb.cpp:503
double z
Position Z.
Definition: pdb.h:123
void selfWindow(int n0, int z0, int y0, int x0, int nF, int zF, int yF, int xF, T init_value=0)
T interpolatedElementBSpline1D(double x, int SplineDegree=3) const
void min(Image< double > &op1, const Image< double > &op2)
void read(const FileName &fnPDB, const bool pseudoatoms=false, const double threshold=0.0)
Read rich phantom from either a PDB of CIF file.
Definition: pdb.cpp:704
#define VEC_ELEM(v, i)
Definition: matrix1d.h:245
const char * hy36encode(unsigned width, int value, char *result)
Definition: pdb.cpp:1824
void atomProjectionRadialProfile(int M, const MultidimArray< double > &profileCoefficients, MultidimArray< double > &projectionProfile)
Definition: pdb.cpp:1363
void resize(size_t Ndim, size_t Zdim, size_t Ydim, size_t Xdim, bool copy=true)
double electronFormFactorRealSpace(double r, const Matrix1D< double > &descriptors)
Definition: pdb.cpp:1087
double point_line_distance_3D(const Matrix1D< double > &p, const Matrix1D< double > &a, const Matrix1D< double > &v)
Definition: geometry.cpp:85
void reportWarning(const String &what)
void applyGeometryToPDBFile(const std::string &fn_in, const std::string &fn_out, const Matrix2D< double > &A, bool centerPDB, const std::string &intensityColumn)
Definition: pdb.cpp:294
void sortTwoVectors(Matrix1D< T > &v1, Matrix1D< T > &v2)
Definition: matrix1d.h:1206
std::vector< MultidimArray< double > > projectionProfileCoefficients
Definition: pdb.h:348
void projectPDB(const PDBPhantom &phantomPDB, const AtomInterpolator &interpolator, Projection &proj, int Ydim, int Xdim, double rot, double tilt, double psi)
Definition: pdb.cpp:1603
std::string segment
segment name
Definition: pdb.h:224
#define FINISHINGX(v)
double z
Definition: pdb.cpp:1351
#define REPORT_ERROR(nerr, ErrormMsg)
Definition: xmipp_error.h:211
void write(const FileName &fnPDB, const bool renumber=false)
Write rich phantom to PDB or CIF file.
Definition: pdb.cpp:872
void writeCIF(const std::string &fnCIF, const callable &atomList, cif::datablock &dataBlock)
Write rich phantom to CIF file.
Definition: pdb.cpp:773
std::vector< double > z
Definition: pdb.h:95
int seqId
Definition: pdb.h:231
void sqrt(Image< double > &op)
void hlpf(MultidimArray< double > &f, int M, const std::string &filterType, MultidimArray< double > &filter, double reductionFactor=0.8, double ripple=0.01, double deltaw=1.0/8.0)
Definition: pdb.cpp:1104
std::string charge
2-char charge with sign 2nd (e.g. 1- or 2+)
Definition: pdb.h:220
std::vector< SelLine >::iterator find(std::vector< SelLine > &text, const std::string &img_name)
Definition: selfile.cpp:553
void readCIF(const std::string &fnCIF, const callable &addAtom, cif::datablock &dataBlock)
Read phantom from CIF.
Definition: pdb.cpp:463
static double * y
Couldn&#39;t write to file.
Definition: xmipp_error.h:140
std::string record
Record Type ("ATOM " or "HETATM")
Definition: pdb.h:178
Matrix2D< double > euler
MultidimArray< double > globalf
Definition: pdb.cpp:1175
#define A1D_ELEM(v, i)
char chainid
ChainId.
Definition: pdb.h:202
int serial
atom serial number
Definition: pdb.h:181
Definition: pdb.h:91
double x
Position X.
Definition: pdb.h:117
void inv(Matrix2D< T > &result) const
Definition: matrix2d.cpp:663
doublereal * w
std::vector< std::string > chain
Definition: pdb.h:97
void addAtom(const Atom &atom)
Add Atom.
Definition: pdb.h:137
void powellOptimizer(Matrix1D< double > &p, int i0, int n, double(*f)(double *x, void *), void *prm, double ftol, double &fret, int &iter, const Matrix1D< double > &steps, bool show)
Definition: pdb.h:174
char atomType
Type.
Definition: pdb.h:114
void InverseFourierTransform(const MultidimArray< std::complex< double > > &in, MultidimArray< double > &out)
Definition: xmipp_fft.cpp:155
glob_prnt iter
std::string resname
Residue name.
Definition: pdb.h:199
std::string authCompId
Definition: pdb.h:237
void selfTranspose()
Definition: matrix1d.h:944
std::string atomType
atom element type
Definition: pdb.h:217
double * di
double Hlpf_fitness(double *p, void *prm)
Definition: pdb.cpp:1181
#define STARTINGX(v)
void hy36encodeSafe(unsigned width, int value, char *result)
Definition: pdb.cpp:1977
doublereal * x
#define i
ql0001_ & k(htemp+1),(cvec+1),(atemp+1),(bj+1),(bl+1),(bu+1),(x+1),(clamda+1), &iout, infoqp, &zero,(w+1), &lenw,(iw+1), &leniw, &glob_grd.epsmac
void readRichCIF(const std::string &fnCIF, const callable &addAtom, std::vector< double > &intensities, const bool pseudoatoms, const double threshold, cif::datablock &dataBlock)
Read rich phantom from CIF.
Definition: pdb.cpp:622
int atomCharge(const std::string &atom)
Definition: pdb.cpp:122
Matrix1D< T > transpose() const
Definition: matrix1d.cpp:644
void setup(int m, double hights, bool computeProjection=false)
Definition: pdb.cpp:1402
#define STARTINGY(v)
#define CLIP(x, x0, xF)
Definition: xmipp_macros.h:260
void threshold(double *phi, unsigned long nvox, double limit)
Definition: lib_vwk.cpp:524
int resseq
Residue sequence.
Definition: pdb.h:205
double r0_2
Definition: pdb.cpp:1350
doublereal * b
void box_enclosing(const Matrix1D< double > &v0, const Matrix1D< double > &vF, const Matrix2D< double > &V, Matrix1D< double > &corner1, Matrix1D< double > &corner2)
Definition: geometry.cpp:366
const Atom & getAtom(int i) const
Get Atom at position i.
Definition: pdb.h:143
int globalM
Definition: pdb.cpp:1176
void compute_hist(const MultidimArrayGeneric &array, Histogram1D &hist, int no_steps)
Definition: histogram.cpp:572
double y
Position Y.
Definition: pdb.h:187
size_t getNumberOfAtoms() const
Get number of atoms.
Definition: pdb.h:149
#define XX(v)
Definition: matrix1d.h:85
void distanceHistogramPDB(const PDBPhantom &phantomPDB, size_t Nnearest, double maxDistance, int Nbins, Histogram1D &hist)
Definition: pdb.cpp:1627
double projectionAtDistance(char atom, double r) const
Definition: pdb.cpp:111
#define CEIL(x)
Definition: xmipp_macros.h:225
std::vector< double > x
Definition: pdb.h:93
float textToFloat(const char *str)
double * f
double occupancy
Occupancy.
Definition: pdb.h:211
std::string altId
Definition: pdb.h:228
virtual double operator()()
Definition: pdb.cpp:1353
String simplify(const String &str)
int pdbNum
Definition: pdb.h:246
void produceSplineCoefficients(int SplineDegree, MultidimArray< double > &coeffs, const MultidimArray< T > &V1)
void resize(size_t Xdim, bool copy=true)
Definition: matrix1d.h:410
void atomRadialProfile(int M, double T, const std::string &atom, MultidimArray< double > &profile)
Definition: pdb.cpp:1306
#define XSIZE(v)
void computePDBgeometry(const std::string &fnPDB, Matrix1D< double > &centerOfMass, Matrix1D< double > &limit0, Matrix1D< double > &limitF, const std::string &intensityColumn)
Definition: pdb.cpp:238
void write(const FileName &fn) const
double globalT
Definition: pdb.cpp:1177
void max(Image< double > &op1, const Image< double > &op2)
void sincos(const MultidimArray< double > &x, MultidimArray< double > &s, MultidimArray< double > &c)
#define ABS(x)
Definition: xmipp_macros.h:142
double z
__host__ __device__ float length(float2 v)
#define ROUND(x)
Definition: xmipp_macros.h:210
File or directory does not exist.
Definition: xmipp_error.h:136
double bfactor
Bfactor.
Definition: pdb.h:214
std::vector< MultidimArray< double > > volumeProfileCoefficients
Definition: pdb.h:346
std::vector< double > b
Definition: pdb.h:96
void direction(const MultidimArray< double > &orMap, MultidimArray< double > &qualityMap, double lambda, int size, MultidimArray< double > &dirMap, int x, int y)
void log10(Image< double > &op)
const char * hy36decode(unsigned width, const char *s, unsigned s_size, int *result)
Definition: pdb.cpp:1892
int getAtomIndex(char atom) const
Get atom index.
Definition: pdb.h:365
void shift(double x, double y, double z)
Apply a shift to all atoms.
Definition: pdb.cpp:514
std::vector< double > y
Definition: pdb.h:94
void FourierTransform(const MultidimArray< double > &in, MultidimArray< std::complex< double > > &out)
Definition: xmipp_fft.cpp:124
double electronFormFactorFourier(double f, const Matrix1D< double > &descriptors)
Definition: pdb.cpp:1059
void initZeros()
Definition: matrix1d.h:592
void atomDescriptors(const std::string &atom, Matrix1D< double > &descriptors)
Definition: pdb.cpp:883
Matrix1D< double > direction
double x
Position X.
Definition: pdb.h:184
std::vector< int > residue
Definition: pdb.h:98
__device__ float FFT_IDX2DIGFREQ(int idx, int size)
Definition: pdb.h:110
std::string authAsymId
Definition: pdb.h:240
void optimizeHlpf(MultidimArray< double > &f, int M, double T, const std::string &atom, MultidimArray< double > &filter, Matrix1D< double > &bestPrm)
Definition: pdb.cpp:1285
#define j
void fhlpf(const MultidimArray< double > &f, const MultidimArray< double > &filter, int M, MultidimArray< double > &convolution)
Definition: pdb.cpp:1134
#define M3x3_BY_V3x1(a, M, b)
Definition: matrix2d.h:170
void hy36decodeSafe(unsigned width, const char *s, unsigned s_size, int *result)
Definition: pdb.cpp:1968
double steps
#define YY(v)
Definition: matrix1d.h:93
int m
int authSeqId
Definition: pdb.h:234
void addAtom(const std::string &atomType, bool computeProjection=false)
Add atom.
Definition: pdb.cpp:1422
std::vector< RichAtom > atomList
List of atoms.
Definition: pdb.h:257
#define FINISHINGY(v)
#define FOR_ALL_ELEMENTS_IN_ARRAY1D(v)
std::string name
Name.
Definition: pdb.h:193
double y
Position Y.
Definition: pdb.h:120
bool checkExtension(const std::filesystem::path &filePath, const std::list< std::string > &acceptedExtensions, const std::list< std::string > &acceptedCompressions)
Checks if the file uses a supported extension type.
Definition: pdb.cpp:384
double psi(const double x)
std::vector< Atom > atomList
List of atoms.
Definition: pdb.h:131
#define VECTOR_R3(v, x, y, z)
Definition: matrix1d.h:124
String getString() const
const MultidimArray< double > * profileCoefficients
Definition: pdb.cpp:1352
void resizeNoCopy(int Xdim)
Definition: matrix1d.h:458
doublereal * u
void analyzePDBAtoms(const FileName &fn_pdb, const std::string &typeOfAtom, int &numberOfAtoms, pdbInfo &at_pos)
Definition: pdb.cpp:64
void readRichPDB(const FileName &fnPDB, const callable &addAtom, std::vector< double > &intensities, std::vector< std::string > &remarks, const bool pseudoatoms, const double threshold)
Read rich phantom from either a PDB of CIF file.
Definition: pdb.cpp:538
Matrix1D< double > globalHlpfPrm(3)
double volumeAtDistance(char atom, double r) const
Definition: pdb.cpp:101
fprintf(glob_prnt.io, "\)
double highTs
Definition: pdb.h:354
float r2
ProgClassifyCL2D * prm
double atomRadius(char atom) const
Definition: pdb.h:414
std::vector< double > radii
Definition: pdb.h:350
std::vector< double > atomCovRad
Definition: pdb.h:99
void setAngles(double _rot, double _tilt, double _psi)
void initZeros(const MultidimArray< T1 > &op)
double atomCovalentRadius(const std::string &atom)
Definition: pdb.cpp:214
void projectAtom(const Atom &atom, Projection &P, const Matrix2D< double > &VP, const Matrix2D< double > &PV, const AtomInterpolator &interpolator)
Definition: pdb.cpp:1446
void addAtom(const RichAtom &atom)
Add Atom.
Definition: pdb.h:264
#define PI
Definition: tools.h:43
std::string icode
Icode.
Definition: pdb.h:208
double v0
void FFT_magnitude(const MultidimArray< std::complex< double > > &v, MultidimArray< double > &mag)
Definition: xmipp_fftw.cpp:393
Incorrect value received.
Definition: xmipp_error.h:195
void writePDB(const FileName &fnPDB, bool renumber, const std::vector< std::string > &remarks, const callable &atomList)
Write rich phantom to PDB file.
Definition: pdb.cpp:725
void getRow(size_t i, Matrix1D< T > &v) const
Definition: matrix2d.cpp:871
void initConstant(T val)
Definition: matrix1d.cpp:83
std::string authAtomId
Definition: pdb.h:243
double fitness(double *p)
#define ZZ(v)
Definition: matrix1d.h:101
double sum() const
void readPDB(const FileName &fnPDB, const callable &addAtom)
Read phantom from PDB.
Definition: pdb.cpp:417
std::string globalAtom
Definition: pdb.cpp:1178
#define V3_PLUS_V3(a, b, c)
Definition: matrix1d.h:190
#define IMGPIXEL(I, i, j)
T computeMax() const
#define SPEED_UP_temps012
Definition: xmipp_macros.h:403
double z
Position Z.
Definition: pdb.h:190
std::string altloc
Alternate location.
Definition: pdb.h:196
void SincKaiserMask(MultidimArray< double > &mask, double omega, double delta, double Deltaw)
Definition: mask.cpp:139