Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
libcifpp
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
libcifpp
Commits
f5016403
Unverified
Commit
f5016403
authored
Mar 02, 2022
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored mmcif::File
parent
c8f66ae6
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
277 additions
and
333 deletions
+277
-333
changelog
+3
-0
include/cif++/Cif++.hpp
+18
-5
include/cif++/Point.hpp
+9
-9
include/cif++/Structure.hpp
+72
-57
src/BondMap.cpp
+1
-1
src/Cif++.cpp
+43
-4
src/Point.cpp
+1
-1
src/Secondary.cpp
+2
-2
src/Structure.cpp
+122
-248
test/rename-compound-test.cpp
+1
-1
test/structure-test.cpp
+4
-4
test/unit-test.cpp
+1
-1
No files found.
changelog
View file @
f5016403
Version
3.0.5
-
mmcif
::
Structure
redesign
.
It
is
now
a
wrapper
around
a
cif
::
Datablock
.
Version
3.0.4
-
Fix
in
mmCIF
parser
,
now
correctly
handles
the
unquoted
string
??
...
...
include/cif++/Cif++.hpp
View file @
f5016403
...
...
@@ -2169,17 +2169,21 @@ class File
File
();
File
(
std
::
istream
&
is
,
bool
validate
=
false
);
File
(
const
std
::
filesystem
::
path
&
path
,
bool
validate
=
false
);
File
(
const
char
*
data
,
size_t
length
);
// good luck trying to find out what it is...
File
(
File
&&
rhs
);
File
(
const
File
&
rhs
)
=
delete
;
File
&
operator
=
(
const
File
&
rhs
)
=
delete
;
~
File
();
virtual
~
File
();
virtual
void
load
(
const
std
::
filesystem
::
path
&
p
);
virtual
void
save
(
const
std
::
filesystem
::
path
&
p
);
v
oid
load
(
const
std
::
filesystem
::
path
&
p
);
v
oid
save
(
const
std
::
filesystem
::
path
&
p
);
v
irtual
void
load
(
std
::
istream
&
is
);
v
irtual
void
save
(
std
::
ostream
&
os
);
void
load
(
std
::
istream
&
is
);
void
save
(
std
::
ostream
&
os
);
virtual
void
load
(
const
char
*
data
,
std
::
size_t
length
);
/// \brief Load only the data block \a datablock from the mmCIF file
void
load
(
std
::
istream
&
is
,
const
std
::
string
&
datablock
);
...
...
@@ -2211,6 +2215,12 @@ class File
void
append
(
Datablock
*
e
);
Datablock
&
emplace
(
std
::
string_view
name
)
{
append
(
new
Datablock
(
name
));
return
back
();
}
Datablock
*
get
(
std
::
string_view
name
)
const
;
Datablock
&
operator
[](
std
::
string_view
name
);
...
...
@@ -2248,6 +2258,9 @@ class File
iterator
begin
()
const
;
iterator
end
()
const
;
Datablock
&
front
();
Datablock
&
back
();
bool
empty
()
const
{
return
mHead
==
nullptr
;
}
const
Validator
&
getValidator
()
const
;
...
...
include/cif++/Point.hpp
View file @
f5016403
...
...
@@ -221,7 +221,7 @@ struct PointF
FType
length
()
const
{
return
sqrt
(
mX
*
mX
+
mY
*
mY
+
mZ
*
mZ
);
return
s
td
::
s
qrt
(
mX
*
mX
+
mY
*
mY
+
mZ
*
mZ
);
}
};
...
...
@@ -285,7 +285,7 @@ inline double DistanceSquared(const PointF<F> &a, const PointF<F> &b)
template
<
typename
F
>
inline
double
Distance
(
const
PointF
<
F
>
&
a
,
const
PointF
<
F
>
&
b
)
{
return
sqrt
(
return
s
td
::
s
qrt
(
(
a
.
mX
-
b
.
mX
)
*
(
a
.
mX
-
b
.
mX
)
+
(
a
.
mY
-
b
.
mY
)
*
(
a
.
mY
-
b
.
mY
)
+
(
a
.
mZ
-
b
.
mZ
)
*
(
a
.
mZ
-
b
.
mZ
));
...
...
@@ -332,10 +332,10 @@ double DihedralAngle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &
double
result
=
360
;
if
(
u
>
0
and
v
>
0
)
{
u
=
DotProduct
(
p
,
x
)
/
sqrt
(
u
);
v
=
DotProduct
(
p
,
y
)
/
sqrt
(
v
);
u
=
DotProduct
(
p
,
x
)
/
s
td
::
s
qrt
(
u
);
v
=
DotProduct
(
p
,
y
)
/
s
td
::
s
qrt
(
v
);
if
(
u
!=
0
or
v
!=
0
)
result
=
atan2
(
v
,
u
)
*
180
/
kPI
;
result
=
std
::
atan2
(
v
,
u
)
*
180
/
kPI
;
}
return
result
;
...
...
@@ -351,7 +351,7 @@ double CosinusAngle(const PointF<F> &p1, const PointF<F> &p2, const PointF<F> &p
double
x
=
DotProduct
(
v12
,
v12
)
*
DotProduct
(
v34
,
v34
);
if
(
x
>
0
)
result
=
DotProduct
(
v12
,
v34
)
/
sqrt
(
x
);
result
=
DotProduct
(
v12
,
v34
)
/
s
td
::
s
qrt
(
x
);
return
result
;
}
...
...
@@ -436,9 +436,9 @@ class SphericalDots
double
lat
=
std
::
asin
((
2.0
*
i
)
/
P
);
double
lon
=
std
::
fmod
(
i
,
kGoldenRatio
)
*
2
*
kPI
/
kGoldenRatio
;
p
->
mX
=
s
in
(
lon
)
*
cos
(
lat
);
p
->
mY
=
cos
(
lon
)
*
cos
(
lat
);
p
->
mZ
=
sin
(
lat
);
p
->
mX
=
s
td
::
sin
(
lon
)
*
std
::
cos
(
lat
);
p
->
mY
=
std
::
cos
(
lon
)
*
std
::
cos
(
lat
);
p
->
mZ
=
s
td
::
s
in
(
lat
);
++
p
;
}
...
...
include/cif++/Structure.hpp
View file @
f5016403
/*-
* SPDX-License-Identifier: BSD-2-Clause
*
*
* Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
...
...
@@ -34,16 +34,16 @@
#include "cif++/Point.hpp"
/*
To modify a structure, you will have to use actions.
The currently supported actions are:
To modify a structure, you will have to use actions.
The currently supported actions are:
// - Move atom to new location
- Remove atom
- Remove atom
// - Add new atom that was formerly missing
// - Add alternate Residue
-
-
*/
namespace
mmcif
...
...
@@ -61,7 +61,6 @@ class File;
class
Atom
{
private
:
struct
AtomImpl
:
public
std
::
enable_shared_from_this
<
AtomImpl
>
{
AtomImpl
(
cif
::
Datablock
&
db
,
const
std
::
string
&
id
,
cif
::
Row
row
);
...
...
@@ -99,7 +98,7 @@ class Atom
int
mRefcount
;
cif
::
Row
mRow
;
mutable
std
::
vector
<
std
::
tuple
<
std
::
string
,
cif
::
detail
::
ItemReference
>>
mCachedRefs
;
mutable
std
::
vector
<
std
::
tuple
<
std
::
string
,
cif
::
detail
::
ItemReference
>>
mCachedRefs
;
mutable
const
Compound
*
mCompound
=
nullptr
;
...
...
@@ -110,14 +109,17 @@ class Atom
};
public
:
Atom
()
{}
Atom
(
std
::
shared_ptr
<
AtomImpl
>
impl
)
:
mImpl
(
impl
)
{}
:
mImpl
(
impl
)
{
}
Atom
(
const
Atom
&
rhs
)
:
mImpl
(
rhs
.
mImpl
)
{}
:
mImpl
(
rhs
.
mImpl
)
{
}
Atom
(
cif
::
Datablock
&
db
,
cif
::
Row
&
row
);
...
...
@@ -152,10 +154,10 @@ class Atom
set_property
(
name
,
std
::
to_string
(
value
));
}
const
std
::
string
&
id
()
const
{
return
impl
().
mID
;
}
AtomType
type
()
const
{
return
impl
().
mType
;
}
const
std
::
string
&
id
()
const
{
return
impl
().
mID
;
}
AtomType
type
()
const
{
return
impl
().
mType
;
}
Point
location
()
const
{
return
impl
().
mLocation
;
}
Point
location
()
const
{
return
impl
().
mLocation
;
}
void
location
(
Point
p
)
{
if
(
not
mImpl
)
...
...
@@ -176,33 +178,33 @@ class Atom
void
translateRotateAndTranslate
(
Point
t1
,
Quaternion
q
,
Point
t2
);
// for direct access to underlying data, be careful!
const
cif
::
Row
getRow
()
const
{
return
impl
().
mRow
;
}
const
cif
::
Row
getRow
()
const
{
return
impl
().
mRow
;
}
const
cif
::
Row
getRowAniso
()
const
;
bool
isSymmetryCopy
()
const
{
return
impl
().
mSymmetryCopy
;
}
std
::
string
symmetry
()
const
{
return
impl
().
mSymmetryOperator
;
}
bool
isSymmetryCopy
()
const
{
return
impl
().
mSymmetryCopy
;
}
std
::
string
symmetry
()
const
{
return
impl
().
mSymmetryOperator
;
}
const
Compound
&
comp
()
const
{
return
impl
().
comp
();
}
bool
isWater
()
const
{
return
impl
().
mCompID
==
"HOH"
or
impl
().
mCompID
==
"H2O"
or
impl
().
mCompID
==
"WAT"
;
}
const
Compound
&
comp
()
const
{
return
impl
().
comp
();
}
bool
isWater
()
const
{
return
impl
().
mCompID
==
"HOH"
or
impl
().
mCompID
==
"H2O"
or
impl
().
mCompID
==
"WAT"
;
}
int
charge
()
const
;
float
uIso
()
const
;
bool
getAnisoU
(
float
anisou
[
6
])
const
{
return
impl
().
getAnisoU
(
anisou
);
}
bool
getAnisoU
(
float
anisou
[
6
])
const
{
return
impl
().
getAnisoU
(
anisou
);
}
float
occupancy
()
const
;
// specifications
const
std
::
string
&
labelAtomID
()
const
{
return
impl
().
mAtomID
;
}
const
std
::
string
&
labelCompID
()
const
{
return
impl
().
mCompID
;
}
const
std
::
string
&
labelAsymID
()
const
{
return
impl
().
mAsymID
;
}
const
std
::
string
&
labelAtomID
()
const
{
return
impl
().
mAtomID
;
}
const
std
::
string
&
labelCompID
()
const
{
return
impl
().
mCompID
;
}
const
std
::
string
&
labelAsymID
()
const
{
return
impl
().
mAsymID
;
}
std
::
string
labelEntityID
()
const
;
int
labelSeqID
()
const
{
return
impl
().
mSeqID
;
}
const
std
::
string
&
labelAltID
()
const
{
return
impl
().
mAltID
;
}
bool
isAlternate
()
const
{
return
not
impl
().
mAltID
.
empty
();
}
int
labelSeqID
()
const
{
return
impl
().
mSeqID
;
}
const
std
::
string
&
labelAltID
()
const
{
return
impl
().
mAltID
;
}
bool
isAlternate
()
const
{
return
not
impl
().
mAltID
.
empty
();
}
std
::
string
authAtomID
()
const
;
std
::
string
authCompID
()
const
;
std
::
string
authAsymID
()
const
;
const
std
::
string
&
authSeqID
()
const
{
return
impl
().
mAuthSeqID
;
}
const
std
::
string
&
authSeqID
()
const
{
return
impl
().
mAuthSeqID
;
}
std
::
string
pdbxAuthInsCode
()
const
;
std
::
string
pdbxAuthAltID
()
const
;
...
...
@@ -225,7 +227,7 @@ class Atom
std
::
swap
(
mImpl
,
b
.
mImpl
);
}
int
compare
(
const
Atom
&
b
)
const
{
return
impl
().
compare
(
*
b
.
mImpl
);
}
int
compare
(
const
Atom
&
b
)
const
{
return
impl
().
compare
(
*
b
.
mImpl
);
}
bool
operator
<
(
const
Atom
&
rhs
)
const
{
...
...
@@ -487,31 +489,33 @@ class Polymer : public std::vector<Monomer>
// file is a reference to the data stored in e.g. the cif file.
// This object is not copyable.
class
File
:
public
std
::
enable_shared_from_this
<
File
>
class
File
:
public
cif
::
File
{
public
:
File
();
File
(
const
std
::
filesystem
::
path
&
path
);
File
(
const
char
*
data
,
size_t
length
);
// good luck trying to find out what it is...
~
File
();
File
()
{}
File
(
const
File
&
)
=
delete
;
File
&
operator
=
(
const
File
&
)
=
delete
;
cif
::
Datablock
&
createDatablock
(
const
std
::
string_view
name
);
File
(
const
std
::
filesystem
::
path
&
path
)
{
load
(
path
);
}
void
load
(
const
std
::
filesystem
::
path
&
path
);
void
save
(
const
std
::
filesystem
::
path
&
path
);
File
(
const
char
*
data
,
size_t
length
)
{
load
(
data
,
length
);
}
Structure
*
model
(
size_t
nr
=
1
);
File
(
const
File
&
)
=
delete
;
File
&
operator
=
(
const
File
&
)
=
delete
;
struct
FileImpl
&
impl
()
const
{
return
*
mImpl
;
}
void
load
(
const
std
::
filesystem
::
path
&
p
)
override
;
void
save
(
const
std
::
filesystem
::
path
&
p
)
override
;
cif
::
Datablock
&
data
();
cif
::
File
&
file
();
void
load
(
std
::
istream
&
is
)
override
;
using
cif
::
File
::
save
;
using
cif
::
File
::
load
;
private
:
struct
FileImpl
*
mImpl
;
cif
::
Datablock
&
data
()
{
return
front
();
}
};
// --------------------------------------------------------------------
...
...
@@ -531,14 +535,18 @@ inline bool operator&(StructureOpenOptions a, StructureOpenOptions b)
class
Structure
{
public
:
Structure
(
File
&
p
,
size_t
modelNr
=
1
,
StructureOpenOptions
options
=
{});
Structure
&
operator
=
(
const
Structure
&
)
=
delete
;
~
Structure
();
Structure
(
File
&
p
,
size_t
modelNr
=
1
,
StructureOpenOptions
options
=
{})
:
Structure
(
p
.
firstDatablock
(),
modelNr
,
options
)
{
}
Structure
(
cif
::
Datablock
&
db
,
size_t
modelNr
=
1
,
StructureOpenOptions
options
=
{});
// Create a read-only clone of the current structure (for multithreaded calculations that move atoms)
Structure
(
const
Structure
&
);
File
&
getFile
()
const
;
Structure
&
operator
=
(
const
Structure
&
)
=
delete
;
~
Structure
();
const
AtomView
&
atoms
()
const
{
return
mAtoms
;
}
AtomView
waters
()
const
;
...
...
@@ -655,8 +663,15 @@ class Structure
void
cleanupEmptyCategories
();
/// \brief Direct access to underlying data
cif
::
Category
&
category
(
std
::
string_view
name
)
const
;
cif
::
Datablock
&
datablock
()
const
;
cif
::
Category
&
category
(
std
::
string_view
name
)
const
{
return
mDb
[
name
];
}
cif
::
Datablock
&
datablock
()
const
{
return
mDb
;
}
private
:
friend
Polymer
;
...
...
@@ -671,7 +686,7 @@ class Structure
void
loadAtomsForModel
(
StructureOpenOptions
options
);
File
&
mFile
;
cif
::
Datablock
&
mDb
;
size_t
mModelNr
;
AtomView
mAtoms
;
std
::
vector
<
size_t
>
mAtomIndex
;
...
...
src/BondMap.cpp
View file @
f5016403
...
...
@@ -233,7 +233,7 @@ BondMap::BondMap(const Structure &p)
link
[
b
].
insert
(
a
);
};
cif
::
Datablock
&
db
=
p
.
getFile
().
data
();
cif
::
Datablock
&
db
=
p
.
datablock
();
// collect all compounds first
std
::
set
<
std
::
string
>
compounds
;
...
...
src/Cif++.cpp
View file @
f5016403
...
...
@@ -2408,7 +2408,7 @@ namespace detail
size_t
writeValue
(
std
::
ostream
&
os
,
std
::
string
value
,
size_t
offset
,
size_t
width
)
{
if
(
value
.
find
(
'\n'
)
!=
std
::
string
::
npos
or
width
==
0
or
value
.
length
()
>
=
132
)
// write as text field
if
(
value
.
find
(
'\n'
)
!=
std
::
string
::
npos
or
width
==
0
or
value
.
length
()
>
132
)
// write as text field
{
ba
::
replace_all
(
value
,
"
\n
;"
,
"
\n\\
;"
);
...
...
@@ -2511,7 +2511,7 @@ void Category::write(std::ostream &os, const std::vector<size_t> &order, bool in
if
(
not
isUnquotedString
(
v
->
mText
))
l
+=
2
;
if
(
l
>
=
132
)
if
(
l
>
132
)
continue
;
if
(
columnWidths
[
v
->
mColumnIndex
]
<
l
+
1
)
...
...
@@ -2547,7 +2547,7 @@ void Category::write(std::ostream &os, const std::vector<size_t> &order, bool in
if
(
l
<
w
)
l
=
w
;
if
(
offset
+
l
>
=
132
and
offset
>
0
)
if
(
offset
+
l
>
132
and
offset
>
0
)
{
os
<<
std
::
endl
;
offset
=
0
;
...
...
@@ -2555,7 +2555,7 @@ void Category::write(std::ostream &os, const std::vector<size_t> &order, bool in
offset
=
detail
::
writeValue
(
os
,
s
,
offset
,
w
);
if
(
offset
>
=
132
)
if
(
offset
>
132
)
{
os
<<
std
::
endl
;
offset
=
0
;
...
...
@@ -3367,6 +3367,11 @@ File::File(const std::filesystem::path &path, bool validate)
}
}
File
::
File
(
const
char
*
data
,
std
::
size_t
length
)
{
load
(
data
,
length
);
}
File
::
File
(
File
&&
rhs
)
:
mHead
(
nullptr
)
,
mValidator
(
nullptr
)
...
...
@@ -3483,6 +3488,25 @@ void File::load(std::istream &is, const std::string &datablock)
}
}
void
File
::
load
(
const
char
*
data
,
std
::
size_t
length
)
{
bool
gzipped
=
length
>
2
and
data
[
0
]
==
static_cast
<
char
>
(
0x1f
)
and
data
[
1
]
==
static_cast
<
char
>
(
0x8b
);
struct
membuf
:
public
std
::
streambuf
{
membuf
(
char
*
data
,
size_t
length
)
{
this
->
setg
(
data
,
data
,
data
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
data
),
length
);
std
::
istream
is
(
&
buffer
);
io
::
filtering_stream
<
io
::
input
>
in
;
if
(
gzipped
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
is
);
load
(
is
);
}
void
File
::
save
(
std
::
ostream
&
os
)
{
Datablock
*
e
=
mHead
;
...
...
@@ -3523,6 +3547,21 @@ Datablock &File::operator[](std::string_view name)
return
*
result
;
}
Datablock
&
File
::
front
()
{
assert
(
mHead
);
return
*
mHead
;
}
Datablock
&
File
::
back
()
{
assert
(
mHead
);
auto
*
block
=
mHead
;
while
(
block
->
mNext
!=
nullptr
)
block
=
block
->
mNext
;
return
*
block
;
}
bool
File
::
isValid
()
{
if
(
mValidator
==
nullptr
)
...
...
src/Point.cpp
View file @
f5016403
...
...
@@ -301,7 +301,7 @@ std::tuple<double,Point> QuaternionToAngleAxis(Quaternion q)
q
=
Normalize
(
q
);
// angle:
double
angle
=
2
*
acos
(
q
.
R_component_1
());
double
angle
=
2
*
std
::
acos
(
q
.
R_component_1
());
angle
=
angle
*
180
/
kPI
;
// axis:
...
...
src/Secondary.cpp
View file @
f5016403
...
...
@@ -535,7 +535,7 @@ double CalculateHBondEnergy(Res &inDonor, Res &inAcceptor)
result
=
kCouplingConstant
/
distanceHO
-
kCouplingConstant
/
distanceHC
+
kCouplingConstant
/
distanceNC
-
kCouplingConstant
/
distanceNO
;
// DSSP compatibility mode:
result
=
round
(
result
*
1000
)
/
1000
;
result
=
std
::
round
(
result
*
1000
)
/
1000
;
if
(
result
<
kMinHBondEnergy
)
result
=
kMinHBondEnergy
;
...
...
@@ -1230,7 +1230,7 @@ DSSPImpl::DSSPImpl(const Structure &s, int min_poly_proline_stretch_length)
void
DSSPImpl
::
calculateSecondaryStructure
()
{
auto
&
db
=
mStructure
.
getFile
().
data
();
auto
&
db
=
mStructure
.
datablock
();
for
(
auto
r
:
db
[
"struct_conn"
].
find
(
cif
::
Key
(
"conn_type_id"
)
==
"disulf"
))
{
std
::
string
asym1
,
asym2
;
...
...
src/Structure.cpp
View file @
f5016403
...
...
@@ -50,157 +50,6 @@ namespace mmcif
{
// --------------------------------------------------------------------
// FileImpl
struct
FileImpl
{
cif
::
File
mData
;
cif
::
Datablock
*
mDb
=
nullptr
;
void
load_data
(
const
char
*
data
,
size_t
length
);
void
load
(
const
std
::
filesystem
::
path
&
path
);
void
save
(
const
std
::
filesystem
::
path
&
path
);
};
void
FileImpl
::
load_data
(
const
char
*
data
,
size_t
length
)
{
bool
gzipped
=
length
>
2
and
data
[
0
]
==
static_cast
<
char
>
(
0x1f
)
and
data
[
1
]
==
static_cast
<
char
>
(
0x8b
);
try
{
// First try mmCIF
struct
membuf
:
public
std
::
streambuf
{
membuf
(
char
*
data
,
size_t
length
)
{
this
->
setg
(
data
,
data
,
data
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
data
),
length
);
std
::
istream
is
(
&
buffer
);
io
::
filtering_stream
<
io
::
input
>
in
;
if
(
gzipped
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
is
);
mData
.
load
(
in
);
}
catch
(
const
cif
::
CifParserError
&
e
)
{
// First try mmCIF
struct
membuf
:
public
std
::
streambuf
{
membuf
(
char
*
data
,
size_t
length
)
{
this
->
setg
(
data
,
data
,
data
+
length
);
}
}
buffer
(
const_cast
<
char
*>
(
data
),
length
);
std
::
istream
is
(
&
buffer
);
io
::
filtering_stream
<
io
::
input
>
in
;
if
(
gzipped
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
is
);
ReadPDBFile
(
in
,
mData
);
}
// Yes, we've parsed the data. Now locate the datablock.
mDb
=
&
mData
.
firstDatablock
();
// And validate, otherwise lots of functionality won't work
// if (mData.getValidator() == nullptr)
mData
.
loadDictionary
(
"mmcif_pdbx_v50"
);
if
(
not
mData
.
isValid
()
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Invalid mmCIF file"
<<
(
cif
::
VERBOSE
>
0
?
"."
:
" use --verbose option to see errors"
)
<<
std
::
endl
;
}
void
FileImpl
::
load
(
const
std
::
filesystem
::
path
&
path
)
{
std
::
ifstream
inFile
(
path
,
std
::
ios_base
::
in
|
std
::
ios_base
::
binary
);
if
(
not
inFile
.
is_open
())
throw
std
::
runtime_error
(
"No such file: "
+
path
.
string
());
io
::
filtering_stream
<
io
::
input
>
in
;
std
::
string
ext
=
path
.
extension
().
string
();
if
(
path
.
extension
()
==
".gz"
)
{
in
.
push
(
io
::
gzip_decompressor
());
ext
=
path
.
stem
().
extension
().
string
();
}
in
.
push
(
inFile
);
try
{
// OK, we've got the file, now create a protein
if
(
ext
==
".cif"
)
mData
.
load
(
in
);
else
if
(
ext
==
".pdb"
or
ext
==
".ent"
)
ReadPDBFile
(
in
,
mData
);
else
{
try
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"unrecognized file extension, trying cif"
<<
std
::
endl
;
mData
.
load
(
in
);
}
catch
(
const
cif
::
CifParserError
&
e
)
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"Not cif, trying plain old PDB"
<<
std
::
endl
;
// pffft...
in
.
reset
();
if
(
inFile
.
is_open
())
inFile
.
seekg
(
0
);
else
inFile
.
open
(
path
,
std
::
ios_base
::
in
|
std
::
ios
::
binary
);
if
(
path
.
extension
()
==
".gz"
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
inFile
);
ReadPDBFile
(
in
,
mData
);
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
if
(
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Error trying to load file "
<<
path
<<
std
::
endl
;
throw
;
}
// Yes, we've parsed the data. Now locate the datablock.
mDb
=
&
mData
.
firstDatablock
();
// And validate, otherwise lots of functionality won't work
// if (mData.getValidator() == nullptr)
mData
.
loadDictionary
(
"mmcif_pdbx_v50"
);
if
(
not
mData
.
isValid
()
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Invalid mmCIF file"
<<
(
cif
::
VERBOSE
>
0
?
"."
:
" use --verbose option to see errors"
)
<<
std
::
endl
;
}
void
FileImpl
::
save
(
const
std
::
filesystem
::
path
&
path
)
{
std
::
ofstream
outFile
(
path
,
std
::
ios_base
::
out
|
std
::
ios_base
::
binary
);
io
::
filtering_stream
<
io
::
output
>
out
;
if
(
path
.
extension
()
==
".gz"
)
out
.
push
(
io
::
gzip_compressor
());
out
.
push
(
outFile
);
if
(
path
.
extension
()
==
".pdb"
)
WritePDBFile
(
out
,
mData
);
else
mData
.
save
(
out
);
}
// --------------------------------------------------------------------
// Atom
Atom
::
AtomImpl
::
AtomImpl
(
cif
::
Datablock
&
db
,
const
std
::
string
&
id
,
cif
::
Row
row
)
...
...
@@ -1131,10 +980,10 @@ bool Monomer::areBonded(const Monomer &a, const Monomer &b, float errorMargin)
auto
distanceCACA
=
Distance
(
atoms
[
0
],
atoms
[
3
]);
double
omega
=
DihedralAngle
(
atoms
[
0
],
atoms
[
1
],
atoms
[
2
],
atoms
[
3
]);
bool
cis
=
abs
(
omega
)
<=
30.0
;
bool
cis
=
std
::
abs
(
omega
)
<=
30.0
;
float
maxCACADistance
=
cis
?
3.0
f
:
3.8
f
;
result
=
abs
(
distanceCACA
-
maxCACADistance
)
<
errorMargin
;
result
=
std
::
abs
(
distanceCACA
-
maxCACADistance
)
<
errorMargin
;
}
catch
(...)
{
...
...
@@ -1242,7 +1091,7 @@ int Polymer::Distance(const Monomer &a, const Monomer &b) const
ixb
=
ix
,
++
f
;
if
(
f
==
2
)
{
result
=
abs
(
ixa
-
ixb
);
result
=
std
::
abs
(
ixa
-
ixb
);
break
;
}
}
...
...
@@ -1254,81 +1103,120 @@ int Polymer::Distance(const Monomer &a, const Monomer &b) const
// --------------------------------------------------------------------
// File
File
::
File
()
:
mImpl
(
new
FileImpl
)
void
File
::
load
(
const
std
::
filesystem
::
path
&
path
)
{
}
std
::
ifstream
inFile
(
path
,
std
::
ios_base
::
in
|
std
::
ios_base
::
binary
);
if
(
not
inFile
.
is_open
())
throw
std
::
runtime_error
(
"No such file: "
+
path
.
string
());
File
::
File
(
const
char
*
data
,
size_t
length
)
:
mImpl
(
new
FileImpl
)
{
mImpl
->
load_data
(
data
,
length
);
}
io
::
filtering_stream
<
io
::
input
>
in
;
std
::
string
ext
=
path
.
extension
().
string
();
File
::
File
(
const
std
::
filesystem
::
path
&
File
)
:
mImpl
(
new
FileImpl
)
{
load
(
File
);
}
if
(
path
.
extension
()
==
".gz"
)
{
in
.
push
(
io
::
gzip_decompressor
());
ext
=
path
.
stem
().
extension
().
string
(
);
}
File
::~
File
()
{
delete
mImpl
;
}
in
.
push
(
inFile
);
cif
::
Datablock
&
File
::
createDatablock
(
const
std
::
string_view
name
)
{
auto
db
=
new
cif
::
Datablock
(
name
);
try
{
// OK, we've got the file, now create a protein
if
(
ext
==
".cif"
)
load
(
in
);
else
if
(
ext
==
".pdb"
or
ext
==
".ent"
)
ReadPDBFile
(
in
,
*
this
);
else
{
try
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"unrecognized file extension, trying cif"
<<
std
::
endl
;
mImpl
->
mData
.
append
(
db
);
mImpl
->
mDb
=
db
;
cif
::
File
::
load
(
in
);
}
catch
(
const
cif
::
CifParserError
&
e
)
{
if
(
cif
::
VERBOSE
>
0
)
std
::
cerr
<<
"Not cif, trying plain old PDB"
<<
std
::
endl
;
return
*
mImpl
->
mDb
;
}
// pffft...
in
.
reset
();
void
File
::
load
(
const
std
::
filesystem
::
path
&
p
)
{
mImpl
->
load
(
p
);
}
if
(
inFile
.
is_open
()
)
inFile
.
seekg
(
0
);
else
inFile
.
open
(
path
,
std
::
ios_base
::
in
|
std
::
ios
::
binary
);
void
File
::
save
(
const
std
::
filesystem
::
path
&
file
)
{
mImpl
->
save
(
file
);
if
(
path
.
extension
()
==
".gz"
)
in
.
push
(
io
::
gzip_decompressor
());
in
.
push
(
inFile
);
ReadPDBFile
(
in
,
*
this
);
}
}
}
catch
(
const
std
::
exception
&
ex
)
{
if
(
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Error trying to load file "
<<
path
<<
std
::
endl
;
throw
;
}
// validate, otherwise lots of functionality won't work
loadDictionary
(
"mmcif_pdbx_v50"
);
if
(
not
isValid
()
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Invalid mmCIF file"
<<
(
cif
::
VERBOSE
>
0
?
"."
:
" use --verbose option to see errors"
)
<<
std
::
endl
;
}
cif
::
Datablock
&
File
::
data
(
)
void
File
::
load
(
std
::
istream
&
is
)
{
assert
(
mImpl
);
assert
(
mImpl
->
mDb
);
if
(
mImpl
==
nullptr
or
mImpl
->
mDb
==
nullptr
)
throw
std
::
runtime_error
(
"No data loaded"
);
try
{
cif
::
File
::
load
(
is
);
}
catch
(
const
cif
::
CifParserError
&
e
)
{
ReadPDBFile
(
is
,
*
this
);
}
return
*
mImpl
->
mDb
;
// validate, otherwise lots of functionality won't work
loadDictionary
(
"mmcif_pdbx_v50"
);
if
(
not
isValid
()
and
cif
::
VERBOSE
>=
0
)
std
::
cerr
<<
"Invalid mmCIF file"
<<
(
cif
::
VERBOSE
>
0
?
"."
:
" use --verbose option to see errors"
)
<<
std
::
endl
;
}
cif
::
File
&
File
::
file
(
)
void
File
::
save
(
const
std
::
filesystem
::
path
&
path
)
{
assert
(
mImpl
);
fs
::
path
file
=
path
.
filename
();
std
::
ofstream
outFile
(
path
,
std
::
ios_base
::
out
|
std
::
ios_base
::
binary
);
io
::
filtering_stream
<
io
::
output
>
out
;
if
(
file
.
extension
()
==
".gz"
)
{
out
.
push
(
io
::
gzip_compressor
());
file
.
replace_extension
(
""
);
}
if
(
mImpl
==
nullptr
)
throw
std
::
runtime_error
(
"No data loaded"
);
out
.
push
(
outFile
);
return
mImpl
->
mData
;
if
(
file
.
extension
()
==
".pdb"
)
WritePDBFile
(
out
,
*
this
);
else
cif
::
File
::
save
(
out
);
}
// --------------------------------------------------------------------
// Structure
Structure
::
Structure
(
File
&
f
,
size_t
modelNr
,
StructureOpenOptions
options
)
:
m
File
(
f
)
Structure
::
Structure
(
cif
::
Datablock
&
db
,
size_t
modelNr
,
StructureOpenOptions
options
)
:
m
Db
(
db
)
,
mModelNr
(
modelNr
)
{
auto
db
=
mFile
.
impl
().
mDb
;
if
(
db
==
nullptr
)
throw
std
::
logic_error
(
"Empty file!"
);
auto
&
atomCat
=
(
*
db
)[
"atom_site"
];
auto
&
atomCat
=
db
[
"atom_site"
];
loadAtomsForModel
(
options
);
...
...
@@ -1357,8 +1245,8 @@ Structure::Structure(File &f, size_t modelNr, StructureOpenOptions options)
void
Structure
::
loadAtomsForModel
(
StructureOpenOptions
options
)
{
auto
db
=
mFile
.
impl
().
mDb
;
auto
&
atomCat
=
(
*
db
)
[
"atom_site"
];
auto
&
db
=
datablock
()
;
auto
&
atomCat
=
db
[
"atom_site"
];
for
(
auto
&
a
:
atomCat
)
{
...
...
@@ -1373,12 +1261,12 @@ void Structure::loadAtomsForModel(StructureOpenOptions options)
if
((
options
bitand
StructureOpenOptions
::
SkipHydrogen
)
and
type_symbol
==
"H"
)
continue
;
mAtoms
.
emplace_back
(
std
::
make_shared
<
Atom
::
AtomImpl
>
(
*
db
,
id
,
a
));
mAtoms
.
emplace_back
(
std
::
make_shared
<
Atom
::
AtomImpl
>
(
db
,
id
,
a
));
}
}
Structure
::
Structure
(
const
Structure
&
s
)
:
m
File
(
s
.
mFile
)
:
m
Db
(
s
.
mDb
)
,
mModelNr
(
s
.
mModelNr
)
{
mAtoms
.
reserve
(
s
.
mAtoms
.
size
());
...
...
@@ -1677,21 +1565,10 @@ const Residue &Structure::getResidue(const mmcif::Atom &atom) const
return
getResidue
(
atom
.
labelAsymID
(),
atom
.
labelCompID
(),
atom
.
labelSeqID
());
}
File
&
Structure
::
getFile
()
const
{
return
mFile
;
}
cif
::
Category
&
Structure
::
category
(
std
::
string_view
name
)
const
{
auto
&
db
=
datablock
();
return
db
[
name
];
}
std
::
tuple
<
char
,
int
,
char
>
Structure
::
MapLabelToAuth
(
const
std
::
string
&
asymID
,
int
seqID
)
const
{
auto
&
db
=
*
getFile
().
impl
().
mDb
;
auto
&
db
=
datablock
()
;
std
::
tuple
<
char
,
int
,
char
>
result
;
bool
found
=
false
;
...
...
@@ -1841,11 +1718,6 @@ std::tuple<std::string, int, std::string> Structure::MapPDBToLabel(const std::st
return
result
;
}
cif
::
Datablock
&
Structure
::
datablock
()
const
{
return
*
mFile
.
impl
().
mDb
;
}
std
::
string
Structure
::
insertCompound
(
const
std
::
string
&
compoundID
,
bool
isEntity
)
{
using
namespace
cif
::
literals
;
...
...
@@ -1854,7 +1726,7 @@ std::string Structure::insertCompound(const std::string &compoundID, bool isEnti
if
(
compound
==
nullptr
)
throw
std
::
runtime_error
(
"Trying to insert unknown compound "
+
compoundID
+
" (not found in CCD)"
);
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
auto
&
chemComp
=
db
[
"chem_comp"
];
auto
r
=
chemComp
.
find
(
cif
::
Key
(
"id"
)
==
compoundID
);
...
...
@@ -1899,7 +1771,7 @@ std::string Structure::insertCompound(const std::string &compoundID, bool isEnti
void
Structure
::
removeAtom
(
Atom
&
a
)
{
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
auto
&
atomSites
=
db
[
"atom_site"
];
...
...
@@ -1922,12 +1794,11 @@ void Structure::removeAtom(Atom &a)
void
Structure
::
removeResidue
(
const
std
::
string
&
asym_id
,
int
seq_id
)
{
}
void
Structure
::
swapAtoms
(
Atom
&
a1
,
Atom
&
a2
)
{
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
auto
&
atomSites
=
db
[
"atom_site"
];
auto
rs1
=
atomSites
.
find
(
cif
::
Key
(
"id"
)
==
a1
.
id
());
...
...
@@ -1963,7 +1834,7 @@ void Structure::changeResidue(Residue &res, const std::string &newCompound,
{
using
namespace
cif
::
literals
;
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
std
::
string
asymID
=
res
.
asymID
();
const
auto
compound
=
CompoundFactory
::
instance
().
create
(
newCompound
);
...
...
@@ -2073,7 +1944,7 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve
{
using
namespace
cif
::
literals
;
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
auto
&
struct_asym
=
db
[
"struct_asym"
];
std
::
string
asym_id
=
struct_asym
.
getUniqueID
();
...
...
@@ -2093,8 +1964,7 @@ std::string Structure::createNonpoly(const std::string &entity_id, const std::ve
{
auto
atom_id
=
atom_site
.
getUniqueID
(
""
);
auto
&&
[
row
,
inserted
]
=
atom_site
.
emplace
({
{
"group_PDB"
,
atom
.
get_property
<
std
::
string
>
(
"group_PDB"
)},
auto
&&
[
row
,
inserted
]
=
atom_site
.
emplace
({{
"group_PDB"
,
atom
.
get_property
<
std
::
string
>
(
"group_PDB"
)},
{
"id"
,
atom_id
},
{
"type_symbol"
,
atom
.
get_property
<
std
::
string
>
(
"type_symbol"
)},
{
"label_atom_id"
,
atom
.
get_property
<
std
::
string
>
(
"label_atom_id"
)},
...
...
@@ -2127,7 +1997,7 @@ std::string Structure::createNonpoly(const std::string &entity_id, std::vector<s
{
using
namespace
cif
::
literals
;
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
auto
&
struct_asym
=
db
[
"struct_asym"
];
std
::
string
asym_id
=
struct_asym
.
getUniqueID
();
...
...
@@ -2143,23 +2013,27 @@ std::string Structure::createNonpoly(const std::string &entity_id, std::vector<s
auto
&
res
=
mNonPolymers
.
emplace_back
(
*
this
,
comp_id
,
asym_id
);
auto
appendUnlessSet
=
[](
std
::
vector
<
cif
::
Item
>
&
ai
,
cif
::
Item
&&
i
)
{
if
(
find_if
(
ai
.
begin
(),
ai
.
end
(),
[
name
=
i
.
name
()](
cif
::
Item
&
ci
)
{
return
ci
.
name
()
==
name
;
})
==
ai
.
end
())
ai
.
emplace_back
(
std
::
move
(
i
));
};
for
(
auto
&
atom
:
atom_info
)
{
auto
atom_id
=
atom_site
.
getUniqueID
(
""
);
atom
.
insert
(
atom
.
end
(),
{
{
"group_PDB"
,
"HETATM"
},
{
"id"
,
atom_id
},
{
"label_comp_id"
,
comp_id
},
{
"label_asym_id"
,
asym_id
},
{
"label_seq_id"
,
""
},
{
"label_entity_id"
,
entity_id
},
{
"auth_comp_id"
,
comp_id
},
{
"auth_asym_id"
,
asym_id
},
{
"auth_seq_id"
,
""
},
{
"pdbx_PDB_model_num"
,
1
},
{
"label_alt_id"
,
""
}
});
appendUnlessSet
(
atom
,
{
"group_PDB"
,
"HETATM"
}
);
appendUnlessSet
(
atom
,
{
"id"
,
atom_id
}
);
appendUnlessSet
(
atom
,
{
"label_comp_id"
,
comp_id
}
);
appendUnlessSet
(
atom
,
{
"label_asym_id"
,
asym_id
}
);
appendUnlessSet
(
atom
,
{
"label_seq_id"
,
""
}
);
appendUnlessSet
(
atom
,
{
"label_entity_id"
,
entity_id
}
);
appendUnlessSet
(
atom
,
{
"auth_comp_id"
,
comp_id
}
);
appendUnlessSet
(
atom
,
{
"auth_asym_id"
,
asym_id
}
);
appendUnlessSet
(
atom
,
{
"auth_seq_id"
,
""
}
);
appendUnlessSet
(
atom
,
{
"pdbx_PDB_model_num"
,
1
}
);
appendUnlessSet
(
atom
,
{
"label_alt_id"
,
""
}
);
auto
&&
[
row
,
inserted
]
=
atom_site
.
emplace
(
atom
.
begin
(),
atom
.
end
());
...
...
@@ -2174,7 +2048,7 @@ void Structure::cleanupEmptyCategories()
{
using
namespace
cif
::
literals
;
cif
::
Datablock
&
db
=
*
mFile
.
impl
().
mDb
;
cif
::
Datablock
&
db
=
datablock
()
;
auto
&
atomSite
=
db
[
"atom_site"
];
...
...
test/rename-compound-test.cpp
View file @
f5016403
...
...
@@ -37,7 +37,7 @@ int main(int argc, char* argv[])
structure
.
cleanupEmptyCategories
();
f
.
file
().
save
(
std
::
cout
);
f
.
save
(
std
::
cout
);
}
catch
(
const
std
::
exception
&
e
)
{
...
...
test/structure-test.cpp
View file @
f5016403
...
...
@@ -78,8 +78,8 @@ BOOST_AUTO_TEST_CASE(create_nonpoly_1)
cif
::
VERBOSE
=
1
;
mmcif
::
File
file
;
file
.
file
().
loadDictionary
(
"mmcif_pdbx_v50.dic"
);
file
.
createDatablock
(
"TEST"
);
// create a datablock
file
.
loadDictionary
(
"mmcif_pdbx_v50.dic"
);
file
.
emplace
(
"TEST"
);
// create a datablock
mmcif
::
Structure
structure
(
file
);
...
...
@@ -171,12 +171,12 @@ _struct_asym.details ?
expected
.
loadDictionary
(
"mmcif_pdbx_v50.dic"
);
if
(
not
(
expected
.
firstDatablock
()
==
structure
.
getFile
().
data
()))
if
(
not
(
expected
.
firstDatablock
()
==
structure
.
datablock
()))
{
BOOST_TEST
(
false
);
std
::
cout
<<
expected
.
firstDatablock
()
<<
std
::
endl
<<
std
::
endl
<<
structure
.
getFile
().
data
()
<<
std
::
endl
;
<<
structure
.
datablock
()
<<
std
::
endl
;
}
}
...
...
test/unit-test.cpp
View file @
f5016403
...
...
@@ -1626,7 +1626,7 @@ PRO OXT HXT SING N N 17
mmcif
::
File
file
(
example
.
string
());
mmcif
::
Structure
structure
(
file
);
(
void
)
file
.
file
().
isValid
();
(
void
)
file
.
isValid
();
mmcif
::
BondMap
bm
(
structure
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment