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
f4506438
Unverified
Commit
f4506438
authored
Jan 22, 2024
by
Maarten L. Hekkelman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added remove column
parent
fc14a655
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
179 additions
and
114 deletions
+179
-114
include/cif++/category.hpp
+36
-34
src/category.cpp
+100
-65
src/datablock.cpp
+4
-0
src/pdb/reconstruct.cpp
+39
-15
No files found.
include/cif++/category.hpp
View file @
f4506438
...
...
@@ -31,22 +31,22 @@
#include "cif++/condition.hpp"
#include "cif++/iterator.hpp"
#include "cif++/row.hpp"
#include "cif++/validate.hpp"
#include "cif++/text.hpp"
#include "cif++/validate.hpp"
#include <array>
/** \file category.hpp
* Documentation for the cif::category class
*
* The category class should meet the requirements of Container and
* SequenceContainer.
*
* TODO: implement all of:
* https://en.cppreference.com/w/cpp/named_req/Container
* https://en.cppreference.com/w/cpp/named_req/SequenceContainer
* and more?
*/
* Documentation for the cif::category class
*
* The category class should meet the requirements of Container and
* SequenceContainer.
*
* TODO: implement all of:
* https://en.cppreference.com/w/cpp/named_req/Container
* https://en.cppreference.com/w/cpp/named_req/SequenceContainer
* and more?
*/
namespace
cif
{
...
...
@@ -61,9 +61,9 @@ namespace cif
class
duplicate_key_error
:
public
std
::
runtime_error
{
public
:
/**
* @brief Construct a new duplicate key error object
*/
/**
* @brief Construct a new duplicate key error object
*/
duplicate_key_error
(
const
std
::
string
&
msg
)
:
std
::
runtime_error
(
msg
)
{
...
...
@@ -75,9 +75,9 @@ class duplicate_key_error : public std::runtime_error
class
missing_key_error
:
public
std
::
runtime_error
{
public
:
/**
* @brief Construct a new duplicate key error object
*/
/**
* @brief Construct a new duplicate key error object
*/
missing_key_error
(
const
std
::
string
&
msg
,
const
std
::
string
&
key
)
:
std
::
runtime_error
(
msg
)
,
m_key
(
key
)
...
...
@@ -95,9 +95,9 @@ class missing_key_error : public std::runtime_error
class
multiple_results_error
:
public
std
::
runtime_error
{
public
:
/**
* @brief Construct a new multiple results error object
*/
/**
* @brief Construct a new multiple results error object
*/
multiple_results_error
()
:
std
::
runtime_error
(
"query should have returned exactly one row"
)
{
...
...
@@ -156,8 +156,8 @@ class category
// --------------------------------------------------------------------
const
std
::
string
&
name
()
const
{
return
m_name
;
}
///< Returns the name of the category
iset
key_fields
()
const
;
///< Returns the cif::iset of key field names. Retrieved from the @ref category_validator for this category
std
::
set
<
uint16_t
>
key_field_indices
()
const
;
///< Returns a set of indices for the key fields.
iset
key_fields
()
const
;
///< Returns the cif::iset of key field names. Retrieved from the @ref category_validator for this category
std
::
set
<
uint16_t
>
key_field_indices
()
const
;
///< Returns a set of indices for the key fields.
/// @brief Set the validator for this category to @a v
/// @param v The category_validator to assign. A nullptr value is allowed.
...
...
@@ -182,7 +182,7 @@ class category
/// @brief Validate links, that means, values in this category should have an
/// accompanying value in parent categories.
///
///
/// @note
/// The code makes one exception when validating missing links and that's between
/// *atom_site* and a parent *pdbx_poly_seq_scheme* or *entity_poly_seq*.
...
...
@@ -285,7 +285,7 @@ class category
/// Return the theoretical maximum number or rows that can be stored
size_t
max_size
()
const
{
return
std
::
numeric_limits
<
size_t
>::
max
();
// this is a bit optimistic, I guess
return
std
::
numeric_limits
<
size_t
>::
max
();
// this is a bit optimistic, I guess
}
/// Return true if the category is empty
...
...
@@ -321,7 +321,7 @@ class category
/// @code{.cpp}
/// for (const auto &[name, value] : cat.rows<std::string,int>("item_name", "item_value"))
/// std::cout << name << ": " << value << '\n';
/// @endcode
/// @endcode
///
/// @tparam Ts The types for the columns requested
/// @param names The names for the columns requested
...
...
@@ -344,7 +344,7 @@ class category
///
/// for (int id : cat.rows<int>("id"))
/// std::cout << id << '\n';
/// @endcode
/// @endcode
///
/// @tparam Ts The types for the columns requested
/// @param names The names for the columns requested
...
...
@@ -363,7 +363,7 @@ class category
/// @code{.cpp}
/// for (row_handle rh : cat.find(cif::key("first_name") == "John" and cif::key("last_name") == "Doe"))
/// .. // do something with rh
/// @endcode
/// @endcode
///
/// @param cond The condition for the query
/// @return A special iterator that loops over all elements that match. The iterator can be dereferenced
...
...
@@ -417,7 +417,7 @@ class category
/// @code{.cpp}
/// for (const auto &[name, value] : cat.find<std::string,int>(cif::key("item_value") > 10, "item_name", "item_value"))
/// std::cout << name << ": " << value << '\n';
/// @endcode
/// @endcode
///
/// @param cond The condition for the query
/// @tparam Ts The types for the columns requested
...
...
@@ -776,8 +776,7 @@ class category
/// @brief Return whether a row exists that matches condition @a cond
/// @param cond The condition to match
/// @return True if a row exists
[[
deprecated
(
"Use contains instead"
)]]
bool
exists
(
condition
&&
cond
)
const
[[
deprecated
(
"Use contains instead"
)]]
bool
exists
(
condition
&&
cond
)
const
{
return
contains
(
std
::
move
(
cond
));
}
...
...
@@ -875,7 +874,7 @@ class category
// insert_impl(pos, std::move(row));
// }
/// Erase the row pointed to by @a pos and return the iterator to the
/// Erase the row pointed to by @a pos and return the iterator to the
/// row following pos.
iterator
erase
(
iterator
pos
);
...
...
@@ -941,7 +940,6 @@ class category
/// result is unique in the context of this category
std
::
string
get_unique_id
(
std
::
function
<
std
::
string
(
int
)
>
generator
=
cif
::
cif_id_for_number
);
/// @brief Generate a new, unique ID based on a string prefix followed by a number
/// @param prefix The string prefix
/// @return a new unique ID
...
...
@@ -1038,6 +1036,11 @@ class category
return
result
;
}
/** @brief Remove column name @a colum_name
* @param column_name The column to be removed
*/
void
remove_column
(
std
::
string_view
column_name
);
/// @brief Return whether a column with name @a name exists in this category
/// @param name The name of the column
/// @return True if the column exists
...
...
@@ -1082,11 +1085,10 @@ class category
void
write
(
std
::
ostream
&
os
,
const
std
::
vector
<
uint16_t
>
&
order
,
bool
includeEmptyColumns
)
const
;
public
:
/// friend function to make it possible to do:
/// @code {.cpp}
/// std::cout << my_category;
/// @endcode
/// @endcode
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
const
category
&
cat
)
{
cat
.
write
(
os
);
...
...
src/category.cpp
View file @
f4506438
...
...
@@ -111,7 +111,7 @@ class row_comparator
if
(
d
!=
0
)
break
;
++
ai
;
}
...
...
@@ -360,7 +360,8 @@ row *category_index::find_by_value(const category &cat, row_initializer k) const
{
auto
fld
=
cat
.
get_column_name
(
f
);
auto
ki
=
find_if
(
k
.
begin
(),
k
.
end
(),
[
&
fld
](
auto
&
i
)
{
return
i
.
name
()
==
fld
;
});
auto
ki
=
find_if
(
k
.
begin
(),
k
.
end
(),
[
&
fld
](
auto
&
i
)
{
return
i
.
name
()
==
fld
;
});
if
(
ki
==
k
.
end
())
k2
.
emplace_back
(
fld
,
""
);
else
...
...
@@ -594,6 +595,25 @@ category::~category()
// --------------------------------------------------------------------
void
category
::
remove_column
(
std
::
string_view
column_name
)
{
for
(
size_t
ix
=
0
;
ix
<
m_columns
.
size
();
++
ix
)
{
if
(
not
iequals
(
column_name
,
m_columns
[
ix
].
m_name
))
continue
;
for
(
row
*
r
=
m_head
;
r
!=
nullptr
;
r
=
r
->
m_next
)
{
if
(
r
->
size
()
>
ix
)
r
->
erase
(
r
->
begin
()
+
ix
);
}
m_columns
.
erase
(
m_columns
.
begin
()
+
ix
);
break
;
}
}
iset
category
::
get_columns
()
const
{
iset
result
;
...
...
@@ -671,7 +691,7 @@ void category::set_validator(const validator *v, datablock &db)
{
std
::
ostringstream
msg
;
msg
<<
"Cannot construct index since the key field"
<<
(
missing
.
size
()
>
1
?
"s"
:
""
)
<<
" "
<<
cif
::
join
(
missing
,
", "
)
<<
" in "
<<
m_name
<<
" "
<<
(
missing
.
size
()
==
1
?
"is"
:
"are"
)
<<
" missing
\n
"
;
<<
cif
::
join
(
missing
,
", "
)
<<
" in "
<<
m_name
<<
" "
<<
(
missing
.
size
()
==
1
?
"is"
:
"are"
)
<<
" missing
\n
"
;
throw
missing_key_error
(
msg
.
str
(),
*
missing
.
begin
());
}
}
...
...
@@ -873,12 +893,12 @@ bool category::validate_links() const
result
=
false
;
std
::
cerr
<<
"Links for "
<<
link
.
v
->
m_link_group_label
<<
" are incomplete
\n
"
<<
" There are "
<<
missing
<<
" items in "
<<
m_name
<<
" that don't have matching parent items in "
<<
parent
->
m_name
<<
'\n'
;
<<
" There are "
<<
missing
<<
" items in "
<<
m_name
<<
" that don't have matching parent items in "
<<
parent
->
m_name
<<
'\n'
;
if
(
VERBOSE
)
{
std
::
cerr
<<
"showing first "
<<
first_missing_rows
.
size
()
<<
" rows
\n
"
<<
'\n'
;
std
::
cerr
<<
"showing first "
<<
first_missing_rows
.
size
()
<<
" rows
\n
"
<<
'\n'
;
first_missing_rows
.
write
(
std
::
cerr
,
link
.
v
->
m_child_keys
,
false
);
...
...
@@ -919,7 +939,9 @@ condition category::get_parents_condition(row_handle rh, const category &parentC
condition
result
;
auto
links
=
m_validator
->
get_links_for_child
(
m_name
);
links
.
erase
(
remove_if
(
links
.
begin
(),
links
.
end
(),
[
n
=
parentCat
.
m_name
](
auto
&
l
)
{
return
l
->
m_parent_category
!=
n
;
}),
links
.
end
());
links
.
erase
(
remove_if
(
links
.
begin
(),
links
.
end
(),
[
n
=
parentCat
.
m_name
](
auto
&
l
)
{
return
l
->
m_parent_category
!=
n
;
}),
links
.
end
());
if
(
not
links
.
empty
())
{
...
...
@@ -959,7 +981,9 @@ condition category::get_children_condition(row_handle rh, const category &childC
mandatoryChildFields
=
childCatValidator
->
m_mandatory_fields
;
auto
links
=
m_validator
->
get_links_for_parent
(
m_name
);
links
.
erase
(
remove_if
(
links
.
begin
(),
links
.
end
(),
[
n
=
childCat
.
m_name
](
auto
&
l
)
{
return
l
->
m_child_category
!=
n
;
}),
links
.
end
());
links
.
erase
(
remove_if
(
links
.
begin
(),
links
.
end
(),
[
n
=
childCat
.
m_name
](
auto
&
l
)
{
return
l
->
m_child_category
!=
n
;
}),
links
.
end
());
if
(
not
links
.
empty
())
{
...
...
@@ -1123,7 +1147,7 @@ category::iterator category::erase(iterator pos)
return
result
;
}
template
<
typename
T
>
template
<
typename
T
>
class
save_value
{
public
:
...
...
@@ -1213,7 +1237,7 @@ void category::erase_orphans(condition &&cond, category &parent)
{
if
(
not
cond
(
r
))
continue
;
if
(
parent
.
contains
(
get_parents_condition
(
r
,
parent
)))
continue
;
...
...
@@ -1222,11 +1246,10 @@ void category::erase_orphans(condition &&cond, category &parent)
category
c
(
m_name
);
c
.
emplace
(
r
);
std
::
cerr
<<
"Removing orphaned record:
\n
"
<<
c
<<
'\n'
<<
'\n'
;
<<
c
<<
'\n'
<<
'\n'
;
}
remove
.
emplace_back
(
r
.
m_row
);
}
...
...
@@ -1251,10 +1274,10 @@ std::string category::get_unique_id(std::function<std::string(int)> generator)
if
(
m_index
==
nullptr
and
m_cat_validator
!=
nullptr
)
m_index
=
new
category_index
(
*
this
);
for
(;;)
{
if
(
m_index
->
find_by_value
(
*
this
,
{
{
id_tag
,
result
}
})
==
nullptr
)
if
(
m_index
->
find_by_value
(
*
this
,
{
{
id_tag
,
result
}
})
==
nullptr
)
break
;
result
=
generator
(
static_cast
<
int
>
(
m_last_unique_num
++
));
}
...
...
@@ -1265,7 +1288,7 @@ std::string category::get_unique_id(std::function<std::string(int)> generator)
{
if
(
not
contains
(
key
(
id_tag
)
==
result
))
break
;
result
=
generator
(
static_cast
<
int
>
(
m_last_unique_num
++
));
}
}
...
...
@@ -1571,8 +1594,8 @@ row *category::clone_row(const row &r)
auto
&
i
=
r
[
ix
];
if
(
not
i
)
continue
;
result
->
append
(
ix
,
{
i
.
text
()
});
result
->
append
(
ix
,
{
i
.
text
()
});
}
}
catch
(...)
...
...
@@ -1639,10 +1662,10 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
if
(
n
==
nullptr
)
throw
std
::
runtime_error
(
"Invalid pointer passed to insert"
);
// #ifndef NDEBUG
// if (m_validator)
// is_valid();
// #endif
// #ifndef NDEBUG
// if (m_validator)
// is_valid();
// #endif
try
{
...
...
@@ -1699,10 +1722,10 @@ category::iterator category::insert_impl(const_iterator pos, row *n)
throw
;
}
// #ifndef NDEBUG
// if (m_validator)
// is_valid();
// #endif
// #ifndef NDEBUG
// if (m_validator)
// is_valid();
// #endif
}
void
category
::
swap_item
(
uint16_t
column_ix
,
row_handle
&
a
,
row_handle
&
b
)
...
...
@@ -1716,7 +1739,7 @@ void category::swap_item(uint16_t column_ix, row_handle &a, row_handle &b)
std
::
swap
(
ra
.
at
(
column_ix
),
rb
.
at
(
column_ix
));
}
void
category
::
sort
(
std
::
function
<
int
(
row_handle
,
row_handle
)
>
f
)
void
category
::
sort
(
std
::
function
<
int
(
row_handle
,
row_handle
)
>
f
)
{
if
(
m_head
==
nullptr
)
return
;
...
...
@@ -1740,7 +1763,7 @@ void category::sort(std::function<int(row_handle,row_handle)> f)
r
->
m_next
=
nullptr
;
assert
(
r
==
m_tail
);
assert
(
size
()
==
rows
.
size
());
assert
(
size
()
==
rows
.
size
());
}
void
category
::
reorder_by_index
()
...
...
@@ -1903,8 +1926,8 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
{
auto
&
col
=
m_columns
[
cix
];
right_aligned
[
cix
]
=
col
.
m_validator
!=
nullptr
and
col
.
m_validator
->
m_type
!=
nullptr
and
col
.
m_validator
->
m_type
->
m_primitive_type
==
cif
::
DDL_PrimitiveType
::
Numb
;
col
.
m_validator
->
m_type
!=
nullptr
and
col
.
m_validator
->
m_type
->
m_primitive_type
==
cif
::
DDL_PrimitiveType
::
Numb
;
}
}
...
...
@@ -2062,32 +2085,37 @@ void category::write(std::ostream &os, const std::vector<uint16_t> &order, bool
bool
category
::
operator
==
(
const
category
&
rhs
)
const
{
// shortcut
if
(
this
==
&
rhs
)
return
true
;
auto
&
a
=
*
this
;
auto
&
b
=
rhs
;
using
namespace
std
::
placeholders
;
// set<std::string> tagsA(a.fields()), tagsB(b.fields());
//
// if (tagsA != tagsB)
// std::cout << "Unequal number of fields\n";
using
namespace
std
::
placeholders
;
// set<std::string> tagsA(a.fields()), tagsB(b.fields());
//
// if (tagsA != tagsB)
// std::cout << "Unequal number of fields\n";
const
category_validator
*
catValidator
=
nullptr
;
auto
validator
=
a
.
get_validator
();
if
(
validator
!=
nullptr
)
catValidator
=
validator
->
get_validator_for_category
(
a
.
name
());
typedef
std
::
function
<
int
(
std
::
string_view
,
std
::
string_view
)
>
compType
;
std
::
vector
<
std
::
tuple
<
std
::
string
,
compType
>>
tags
;
typedef
std
::
function
<
int
(
std
::
string_view
,
std
::
string_view
)
>
compType
;
std
::
vector
<
std
::
tuple
<
std
::
string
,
compType
>>
tags
;
std
::
vector
<
std
::
string
>
keys
;
std
::
vector
<
size_t
>
keyIx
;
if
(
catValidator
==
nullptr
)
{
for
(
auto
&
tag
:
a
.
get_columns
())
for
(
auto
&
tag
:
a
.
get_columns
())
{
tags
.
push_back
(
std
::
make_tuple
(
tag
,
[](
std
::
string_view
va
,
std
::
string_view
vb
)
{
return
va
.
compare
(
vb
);
}));
tags
.
push_back
(
std
::
make_tuple
(
tag
,
[](
std
::
string_view
va
,
std
::
string_view
vb
)
{
return
va
.
compare
(
vb
);
}));
keyIx
.
push_back
(
keys
.
size
());
keys
.
push_back
(
tag
);
}
...
...
@@ -2096,7 +2124,7 @@ bool category::operator==(const category &rhs) const
{
keys
=
catValidator
->
m_keys
;
for
(
auto
&
tag
:
a
.
key_fields
())
for
(
auto
&
tag
:
a
.
key_fields
())
{
auto
iv
=
catValidator
->
get_validator_for_item
(
tag
);
if
(
iv
==
nullptr
)
...
...
@@ -2105,25 +2133,28 @@ bool category::operator==(const category &rhs) const
if
(
tv
==
nullptr
)
throw
std
::
runtime_error
(
"missing type validator"
);
tags
.
push_back
(
std
::
make_tuple
(
tag
,
std
::
bind
(
&
cif
::
type_validator
::
compare
,
tv
,
std
::
placeholders
::
_1
,
std
::
placeholders
::
_2
)));
auto
pred
=
[
tag
](
const
std
::
string
&
s
)
->
bool
{
return
cif
::
iequals
(
tag
,
s
)
==
0
;
};
auto
pred
=
[
tag
](
const
std
::
string
&
s
)
->
bool
{
return
cif
::
iequals
(
tag
,
s
)
==
0
;
};
if
(
find_if
(
keys
.
begin
(),
keys
.
end
(),
pred
)
==
keys
.
end
())
keyIx
.
push_back
(
tags
.
size
()
-
1
);
}
}
// a.reorderByIndex();
// b.reorderByIndex();
auto
rowEqual
=
[
&
](
const
row_handle
&
a
,
const
row_handle
&
b
)
auto
rowEqual
=
[
&
](
const
row_handle
&
a
,
const
row_handle
&
b
)
{
int
d
=
0
;
for
(
auto
kix
:
keyIx
)
for
(
auto
kix
:
keyIx
)
{
std
::
string
tag
;
compType
compare
;
std
::
tie
(
tag
,
compare
)
=
tags
[
kix
];
d
=
compare
(
a
[
tag
].
text
(),
b
[
tag
].
text
());
...
...
@@ -2131,7 +2162,7 @@ bool category::operator==(const category &rhs) const
if
(
d
!=
0
)
break
;
}
return
d
==
0
;
};
...
...
@@ -2140,30 +2171,34 @@ bool category::operator==(const category &rhs) const
{
if
(
ai
==
a
.
end
()
or
bi
==
b
.
end
())
return
false
;
auto
ra
=
*
ai
,
rb
=
*
bi
;
if
(
not
rowEqual
(
ra
,
rb
))
return
false
;
std
::
vector
<
std
::
string
>
missingA
,
missingB
,
different
;
for
(
auto
&
tt
:
tags
)
for
(
auto
&
tt
:
tags
)
{
std
::
string
tag
;
compType
compare
;
std
::
tie
(
tag
,
compare
)
=
tt
;
// make it an option to compare unapplicable to empty or something
auto
ta
=
ra
[
tag
].
text
();
if
(
ta
==
"."
or
ta
==
"?"
)
ta
=
""
;
auto
tb
=
rb
[
tag
].
text
();
if
(
tb
==
"."
or
tb
==
"?"
)
tb
=
""
;
auto
ta
=
ra
[
tag
].
text
();
if
(
ta
==
"."
or
ta
==
"?"
)
ta
=
""
;
auto
tb
=
rb
[
tag
].
text
();
if
(
tb
==
"."
or
tb
==
"?"
)
tb
=
""
;
if
(
compare
(
ta
,
tb
)
!=
0
)
return
false
;
}
++
ai
;
++
bi
;
}
...
...
src/datablock.cpp
View file @
f4506438
...
...
@@ -374,6 +374,10 @@ void datablock::write(std::ostream &os, const std::vector<std::string> &tag_orde
bool
datablock
::
operator
==
(
const
datablock
&
rhs
)
const
{
// shortcut
if
(
this
==
&
rhs
)
return
true
;
auto
&
dbA
=
*
this
;
auto
&
dbB
=
rhs
;
...
...
src/pdb/reconstruct.cpp
View file @
f4506438
...
...
@@ -117,8 +117,8 @@ void fixNegativeSeqID(category &atom_site)
const
auto
&
[
auth_seq_id
,
label_seq_id
]
=
poly_seq
.
front
();
for
(
auto
row
:
atom_site
.
find
(
key
(
"label_asym_id"
)
==
asym_id
and
key
(
"auth_seq_id"
)
==
auth_seq_id
and
key
(
"label_seq_id"
)
==
label_seq_id
))
key
(
"auth_seq_id"
)
==
auth_seq_id
and
key
(
"label_seq_id"
)
==
label_seq_id
))
{
row
.
assign
(
"label_seq_id"
,
"."
,
false
,
false
);
}
...
...
@@ -236,20 +236,19 @@ void checkAtomRecords(datablock &db)
{
"auth_seq_id"
,
auth_seq_id
.
value_or
(
std
::
to_string
(
*
label_seq_id
))
},
{
"auth_comp_id"
,
auth_comp_id
.
value_or
(
*
label_comp_id
)
},
{
"auth_atom_id"
,
auth_atom_id
.
value_or
(
*
label_atom_id
)
}
});
// Rewrite the coordinates and other fields that look better in a fixed format
// Be careful not to nuke invalidly formatted data here
for
(
auto
[
tag
,
prec
]
:
std
::
vector
<
std
::
tuple
<
std
::
string_view
,
std
::
string
::
size_type
>>
{
{
"cartn_x"
,
3
},
{
"cartn_y"
,
3
},
{
"cartn_z"
,
3
},
{
"occupancy"
,
2
},
{
"b_iso_or_equiv"
,
2
}
})
for
(
auto
[
tag
,
prec
]
:
std
::
vector
<
std
::
tuple
<
std
::
string_view
,
std
::
string
::
size_type
>>
{
{
"cartn_x"
,
3
},
{
"cartn_y"
,
3
},
{
"cartn_z"
,
3
},
{
"occupancy"
,
2
},
{
"b_iso_or_equiv"
,
2
}
})
{
if
(
row
[
tag
].
empty
())
continue
;
float
v
;
auto
s
=
row
.
get
<
std
::
string
>
(
tag
);
if
(
auto
[
ptr
,
ec
]
=
cif
::
from_chars
(
s
.
data
(),
s
.
data
()
+
s
.
length
(),
v
);
ec
!=
std
::
errc
())
...
...
@@ -260,8 +259,30 @@ void checkAtomRecords(datablock &db)
char
b
[
12
];
if
(
auto
[
ptr
,
ec
]
=
cif
::
to_chars
(
b
,
b
+
sizeof
(
b
),
v
,
cif
::
chars_format
::
fixed
,
prec
);
ec
==
std
::
errc
())
row
.
assign
(
tag
,
{
b
,
static_cast
<
std
::
string
::
size_type
>
(
ptr
-
b
)},
false
,
false
);
row
.
assign
(
tag
,
{
b
,
static_cast
<
std
::
string
::
size_type
>
(
ptr
-
b
)
},
false
,
false
);
}
}
}
auto
*
cv
=
atom_site
.
get_cat_validator
();
if
(
cv
)
{
// See if there are columns that are no longer known
for
(
auto
tag
:
atom_site
.
get_columns
())
{
if
(
cv
->
get_validator_for_item
(
tag
)
!=
nullptr
)
continue
;
auto
r
=
atom_site
.
find_first
(
key
(
tag
)
!=
null
);
if
(
not
r
)
{
if
(
cif
::
VERBOSE
>
0
)
std
::
clog
<<
"Dropping unknown column "
<<
tag
<<
'\n'
;
atom_site
.
remove_column
(
tag
);
}
else
if
(
cif
::
VERBOSE
>
0
)
std
::
clog
<<
"Keeping unknown column "
<<
std
::
quoted
(
tag
)
<<
" in atom_site since it is not empty
\n
"
;
}
}
}
...
...
@@ -607,14 +628,14 @@ void comparePolySeqSchemes(datablock &db)
if
(
i
==
asym_ids_ndb
.
end
()
or
*
i
!=
asym_id
)
asym_ids_ndb
.
insert
(
i
,
asym_id
);
}
for
(
auto
asym_id
:
pdbx_poly_seq_scheme
.
rows
<
std
::
string
>
(
"asym_id"
))
{
auto
i
=
std
::
lower_bound
(
asym_ids_pdbx
.
begin
(),
asym_ids_pdbx
.
end
(),
asym_id
);
if
(
i
==
asym_ids_pdbx
.
end
()
or
*
i
!=
asym_id
)
asym_ids_pdbx
.
insert
(
i
,
asym_id
);
}
// If we have different Asym ID's assume the ndb is invalid.
if
(
asym_ids_ndb
!=
asym_ids_pdbx
)
{
...
...
@@ -632,7 +653,7 @@ void comparePolySeqSchemes(datablock &db)
auto
pdbx_range
=
pdbx_poly_seq_scheme
.
find
(
key
(
"asym_id"
)
==
asym_id
);
for
(
auto
ndb_i
=
ndb_range
.
begin
(),
pdbx_i
=
pdbx_range
.
begin
();
ndb_i
!=
ndb_range
.
end
()
or
pdbx_i
!=
pdbx_range
.
end
();
++
ndb_i
,
++
pdbx_i
)
ndb_i
!=
ndb_range
.
end
()
or
pdbx_i
!=
pdbx_range
.
end
();
++
ndb_i
,
++
pdbx_i
)
{
if
(
ndb_i
==
ndb_range
.
end
()
or
pdbx_i
==
pdbx_range
.
end
())
{
...
...
@@ -662,6 +683,9 @@ void comparePolySeqSchemes(datablock &db)
}
}
}
if
(
ndb_poly_seq_scheme
.
empty
())
db
.
erase
(
std
::
remove
(
db
.
begin
(),
db
.
end
(),
ndb_poly_seq_scheme
),
db
.
end
());
}
void
reconstruct_pdbx
(
file
&
file
,
std
::
string_view
dictionary
)
...
...
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