pidibble 1.5.2__tar.gz → 1.5.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pidibble-1.5.4/.envrc +4 -0
- pidibble-1.5.4/.github/workflows/release.yaml +29 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/.gitignore +3 -0
- pidibble-1.5.4/CHANGELOG.md +206 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/PKG-INFO +5 -63
- {pidibble-1.5.2 → pidibble-1.5.4}/README.md +2 -62
- pidibble-1.5.4/docs/requirements.txt +8 -0
- pidibble-1.5.4/docs/source/changelog.md +5 -0
- pidibble-1.5.4/docs/source/changelog.rst +7 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/conf.py +2 -1
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/index.rst +1 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/baseparsers.py +58 -57
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/baserecord.py +34 -37
- pidibble-1.5.4/pidibble/hex.py +68 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/mmcif_parse.py +143 -143
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/pdbparse.py +116 -108
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/pdbrecord.py +291 -265
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/resources/pdb_format.yaml +3 -3
- {pidibble-1.5.2 → pidibble-1.5.4}/pyproject.toml +4 -1
- pidibble-1.5.4/scripts/release.sh +88 -0
- pidibble-1.5.2/.github/workflows/release.yaml +0 -41
- pidibble-1.5.2/MANIFEST.in +0 -1
- pidibble-1.5.2/docs/requirements.txt +0 -15
- pidibble-1.5.2/pidibble/hex.py +0 -40
- pidibble-1.5.2/pidibble/resources/__init__.py +0 -6
- {pidibble-1.5.2 → pidibble-1.5.4}/.readthedocs.yaml +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/LICENSE +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/Makefile +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/make.bat +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/_static/css/custom.css +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/API.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.baseparsers.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.baserecord.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.hex.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.mmcif_parse.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.pdbparse.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.pdbrecord.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.resources.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/api/pidibble.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/installation.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/notes.md +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/docs/source/usage.rst +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/__init__.py +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/pidibble/resources/mmcif_format.yaml +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/__init__.py +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/conftest.py +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_hex/my_system.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_hex.py +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/4tvp.cif +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/4tvp.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/4zmj-newresnames.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/4zmj.cif +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/4zmj.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/6m0j.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/8fae.cif +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/G.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/GG.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/test.pdb +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb/test_pdb_format.yaml +0 -0
- {pidibble-1.5.2 → pidibble-1.5.4}/tests/unit/test_rcsb.py +0 -0
pidibble-1.5.4/.envrc
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Release & Upload to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
release:
|
|
11
|
+
uses: cameronabrams/workflows/.github/workflows/python-release.yml@main
|
|
12
|
+
with:
|
|
13
|
+
rtd_slug: pidibble
|
|
14
|
+
run_tests: true
|
|
15
|
+
secrets: inherit
|
|
16
|
+
|
|
17
|
+
publish:
|
|
18
|
+
needs: release
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
id-token: write
|
|
22
|
+
steps:
|
|
23
|
+
- name: Download dist artifacts
|
|
24
|
+
uses: actions/download-artifact@v4
|
|
25
|
+
with:
|
|
26
|
+
name: dist
|
|
27
|
+
path: dist/
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
+
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [1.5.4] - 2026-07-14
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- ATOM/HETATM/ANISOU `charge` field retyped from `Float` to `String`. The PDB charge column (79–80) is a formatted string (e.g. `1-`, `2+`), never a plain float, so every populated charge previously failed `float()` and emitted a spurious "Could not parse field charge" warning while discarding the value. Charges are now captured correctly (e.g. `1-`).
|
|
12
|
+
- Off-by-one in `StringParser.report_record_error()` highlight: the error display dropped the character at the field's first column and coloured a window shifted one column to the right of the offending field. The highlight now wraps exactly the columns given by the field's byte range.
|
|
13
|
+
|
|
14
|
+
## [1.5.3] - 2026-05-03
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- `PDBParser(PDBcode=...)` legacy parameter silently swallowed by `**kwargs`; restored via explicit mapping to `source_id`/`source_db='rcsb'`
|
|
18
|
+
- Eight bare `except:` clauses narrowed to specific exception types throughout
|
|
19
|
+
- Bitwise `&=` used as logical AND in `BaseRecord.empty()` replaced with `all()`
|
|
20
|
+
- `str2int_sig` raised `IndexError` on empty-string input; added guard before index access
|
|
21
|
+
- `!= None` / `== None` comparisons replaced with `is not None` / `is None` throughout
|
|
22
|
+
- `type(x) == T` identity comparisons replaced with `isinstance(x, T)` throughout
|
|
23
|
+
- `elif type(p) == list:` in `parse_tokens()` was unreachable; corrected to `isinstance(p, PDBRecordList)`
|
|
24
|
+
- Mutable default arguments `hold={}` and `hold=[]` in `gather_token` and `header_check` replaced with `None`
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Global hex-tripped flag in `hex.py` replaced with `AtomSerialParser` callable class; each `PDBParser` instance owns its own state, eliminating thread-safety hazard and cross-parse contamination
|
|
28
|
+
- `mappers` default argument changed from a mutable dict literal to `None`; default built inside `__init__`
|
|
29
|
+
- Resource YAML files now loaded via `importlib.resources.files()` instead of `os.path.dirname(resources.__file__)`, ensuring correct behavior inside wheels and zip archives
|
|
30
|
+
- `resources/__init__.py` removed; `resources/` is now a plain data directory, not a sub-package
|
|
31
|
+
- `MANIFEST.in` removed; hatchling auto-discovers package data from git-tracked files
|
|
32
|
+
- PEP 8 spacing applied throughout all source files
|
|
33
|
+
- `parse_embedded()` refactored: `triggered`/`capturing` boolean pair replaced with explicit `_EmbedState` enum (`SEARCHING`, `PRE_CAPTURE`, `CAPTURING`); setup phase extracted into `_setup_embed_context()`
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
- `CHANGELOG.md` with full release history
|
|
37
|
+
- `scripts/release.sh` for automated version rotation, tagging, and push
|
|
38
|
+
- `[test]` optional dependency group in `pyproject.toml`
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## [1.5.2] - 2025-09-16
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- Capability to download structures from OPM and split DUM residues into a separate PDB file
|
|
46
|
+
|
|
47
|
+
## [1.5.1] - 2025-09-15
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
- Minor fixes following 1.5.0
|
|
51
|
+
|
|
52
|
+
## [1.5.0] - 2025-09-15
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- Initial OPM support
|
|
56
|
+
|
|
57
|
+
## [1.4.2] - 2025-08-11
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
- Updated AlphaFold interface to current API
|
|
61
|
+
|
|
62
|
+
## [1.4.1] - 2025-08-07
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
- Parsing bug in `PDBRecordList`
|
|
66
|
+
|
|
67
|
+
## [1.4.0] - 2025-07-29
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
- `PDBRecordList` and `PDBRecordDict` classes
|
|
71
|
+
|
|
72
|
+
## [1.3.3] - 2025-07-29
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
- Bugs where missing records were incorrectly assumed present during mmCIF parsing
|
|
76
|
+
|
|
77
|
+
## [1.3.2] - 2025-07-25
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
- `filepath` parameter in `PDBParser()` for transparent reading of local files
|
|
81
|
+
|
|
82
|
+
## [1.3.1] - 2025-07-25
|
|
83
|
+
|
|
84
|
+
### Fixed
|
|
85
|
+
- Minor fixes following 1.3.0
|
|
86
|
+
|
|
87
|
+
## [1.3.0] - 2025-07-16
|
|
88
|
+
|
|
89
|
+
### Changed
|
|
90
|
+
- Streamlined class attribute usage throughout
|
|
91
|
+
- Full API documentation published
|
|
92
|
+
|
|
93
|
+
## [1.2.3] - 2025-03-06
|
|
94
|
+
|
|
95
|
+
### Fixed
|
|
96
|
+
- Negative residue sequence numbers now parsed correctly
|
|
97
|
+
|
|
98
|
+
## [1.2.2] - 2025-03-04
|
|
99
|
+
|
|
100
|
+
### Fixed
|
|
101
|
+
- Minor fixes following 1.2.1
|
|
102
|
+
|
|
103
|
+
## [1.2.1] - 2024-10-01
|
|
104
|
+
|
|
105
|
+
### Fixed
|
|
106
|
+
- Hexadecimal serial number parsing issues (again)
|
|
107
|
+
|
|
108
|
+
## [1.2.0] - 2024-09-08
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
- Hexadecimal serial number parsing issues
|
|
112
|
+
|
|
113
|
+
## [1.1.9] - 2024-08-08
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
- `nan` values and `*` filler characters in numeric fields now handled gracefully
|
|
117
|
+
|
|
118
|
+
## [1.1.8] - 2024-07-15
|
|
119
|
+
|
|
120
|
+
### Added
|
|
121
|
+
- Unstructured REMARK records (e.g. from PACKMOL output) parsed as `REMARK.-1`
|
|
122
|
+
|
|
123
|
+
## [1.1.6] - 2024-07-11
|
|
124
|
+
|
|
125
|
+
### Fixed
|
|
126
|
+
- Hexadecimal atom serial detection when no `a-f` characters are present, based on value exceeding 99999
|
|
127
|
+
|
|
128
|
+
## [1.1.5] - 2024-07-11
|
|
129
|
+
|
|
130
|
+
### Fixed
|
|
131
|
+
- Hex-or-integer detection now restricted to atom serial number fields only
|
|
132
|
+
|
|
133
|
+
## [1.1.4] - 2024-07-11
|
|
134
|
+
|
|
135
|
+
### Added
|
|
136
|
+
- Hexadecimal atom serial number support for files with more than 99999 atoms
|
|
137
|
+
|
|
138
|
+
## [1.1.3] - 2024-03-21
|
|
139
|
+
|
|
140
|
+
### Added
|
|
141
|
+
- Ability to group records into models for multi-model PDB entries
|
|
142
|
+
|
|
143
|
+
## [1.1.2] - 2024-02-28
|
|
144
|
+
|
|
145
|
+
### Added
|
|
146
|
+
- Ability to fetch structures from the AlphaFold database
|
|
147
|
+
|
|
148
|
+
## [1.1.1] - 2023-09-19
|
|
149
|
+
|
|
150
|
+
### Added
|
|
151
|
+
- Version detection via `importlib.metadata`
|
|
152
|
+
|
|
153
|
+
## [1.0.9.1] - 2023-08-28
|
|
154
|
+
|
|
155
|
+
### Added
|
|
156
|
+
- Limited mmCIF parsing: `ATOM`, `HETATM`, `SSBOND`, `LINK`, `SEQADV`, `REMARK 350`, and `REMARK 465` records
|
|
157
|
+
|
|
158
|
+
## [1.0.8] - 2023-08-23
|
|
159
|
+
|
|
160
|
+
### Fixed
|
|
161
|
+
- Variations in how symmetry operation matrices are represented in PDB files
|
|
162
|
+
|
|
163
|
+
## [1.0.7.7] - 2023-08-22
|
|
164
|
+
|
|
165
|
+
### Changed
|
|
166
|
+
- Cleaned up logging throughout
|
|
167
|
+
|
|
168
|
+
## [1.0.7.6] - 2023-08-22
|
|
169
|
+
|
|
170
|
+
### Fixed
|
|
171
|
+
- Leading whitespace in `resName` field of `Residue10` record sometimes ignored
|
|
172
|
+
|
|
173
|
+
## [1.0.7.5] - 2023-08-18
|
|
174
|
+
|
|
175
|
+
### Added
|
|
176
|
+
- Support for four-letter residue names
|
|
177
|
+
|
|
178
|
+
## [1.0.7.4] - 2023-08-04
|
|
179
|
+
|
|
180
|
+
### Added
|
|
181
|
+
- Logging functionality
|
|
182
|
+
|
|
183
|
+
## [1.0.7.3] - 2023-08-03
|
|
184
|
+
|
|
185
|
+
### Changed
|
|
186
|
+
- Improved parsing of BIOMT transforms
|
|
187
|
+
|
|
188
|
+
## [1.0.7.2] - 2023-08-03
|
|
189
|
+
|
|
190
|
+
### Added
|
|
191
|
+
- Documentation stub on ReadTheDocs
|
|
192
|
+
|
|
193
|
+
## [1.0.7.1] - 2023-08-03
|
|
194
|
+
|
|
195
|
+
### Added
|
|
196
|
+
- Support for split BIOMT tables and REMARK 280, 375, 650, and 700
|
|
197
|
+
|
|
198
|
+
## [1.0.7] - 2023-08-01
|
|
199
|
+
|
|
200
|
+
### Added
|
|
201
|
+
- Pretty-print support for parsed records
|
|
202
|
+
|
|
203
|
+
## [1.0] - 2023-07-01
|
|
204
|
+
|
|
205
|
+
### Added
|
|
206
|
+
- Initial release
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pidibble
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.4
|
|
4
4
|
Summary: A complete Protein Data Bank (PDB) file parser
|
|
5
5
|
Project-URL: Source, https://github.com/cameronabrams/pidibble
|
|
6
6
|
Project-URL: Documentation, https://pidibble.readthedocs.io/en/latest/
|
|
@@ -14,6 +14,8 @@ Requires-Python: >=3.7
|
|
|
14
14
|
Requires-Dist: mmcif
|
|
15
15
|
Requires-Dist: numpy>=1.24
|
|
16
16
|
Requires-Dist: pyyaml>=6
|
|
17
|
+
Provides-Extra: test
|
|
18
|
+
Requires-Dist: pytest; extra == 'test'
|
|
17
19
|
Description-Content-Type: text/markdown
|
|
18
20
|
|
|
19
21
|
# Pidibble
|
|
@@ -90,66 +92,6 @@ ATOM
|
|
|
90
92
|
|
|
91
93
|
```
|
|
92
94
|
|
|
93
|
-
##
|
|
94
|
-
* 1.5.2
|
|
95
|
-
* added capability to download from OPM and split out DUM resi's into a "dum" pdb
|
|
96
|
-
* 1.4.2
|
|
97
|
-
* updated alphafold interface
|
|
98
|
-
* 1.4.1
|
|
99
|
-
* Fixed parsing bug in `PDBRecordList`
|
|
100
|
-
* 1.4.0
|
|
101
|
-
* Introduced `PDBRecordList` and `PDBRecordDict` classes
|
|
102
|
-
* 1.3.3
|
|
103
|
-
* fixed bugs regarding assuming missing records actually present in mmcif parsing
|
|
104
|
-
* 1.3.2
|
|
105
|
-
* implemented `filepath` parameter in `PDBParser()` to make
|
|
106
|
-
reading local files more transparent
|
|
107
|
-
* 1.3.0
|
|
108
|
-
* streamline class attribute usage; full API documentation
|
|
109
|
-
* 1.2.3:
|
|
110
|
-
* bugfix: negative resids allowed
|
|
111
|
-
* 1.2.1:
|
|
112
|
-
* bugfix: hex issues AGAIN
|
|
113
|
-
* 1.2.0
|
|
114
|
-
* bugfix: hex issues again
|
|
115
|
-
* 1.1.9
|
|
116
|
-
* gently handles any nan values or '*' fillers
|
|
117
|
-
* 1.1.8
|
|
118
|
-
* Allow unstructured REMARK records (thanks a lot, packmol) to be parsed as REMARK.-1
|
|
119
|
-
* 1.1.6
|
|
120
|
-
* bugfix: detection of hex when no abcdef present based on a trip
|
|
121
|
-
* 1.1.5
|
|
122
|
-
* bugfix: allow for ONLY atom serial numbers to be hex-or-int
|
|
123
|
-
* 1.1.4
|
|
124
|
-
* Added ability to read hexadecimal atom indices for files with > 99999 atoms
|
|
125
|
-
* 1.1.3
|
|
126
|
-
* Added ability to group into models for multiple-model entries
|
|
127
|
-
* 1.1.2
|
|
128
|
-
* Added ability to retrieve pdbs from AlphaFold database
|
|
129
|
-
* 1.1.1
|
|
130
|
-
* version detection
|
|
131
|
-
* 1.0.9.1
|
|
132
|
-
* added limited functionality to parse mmCIF files, in particular to generate any
|
|
133
|
-
ATOM, HETATM, SSBOND, LINK, SEQADV, REMARK 350, and REMARK 465 records
|
|
134
|
-
* 1.0.8
|
|
135
|
-
* bug fix: handle variations in how symmetry operation matrices are represented
|
|
136
|
-
* 1.0.7.7
|
|
137
|
-
* cleaned up logging
|
|
138
|
-
* 1.0.7.6
|
|
139
|
-
* bug fix: leading whitespace in resname field of Residue10 record sometimes ignored
|
|
140
|
-
* 1.0.7.5
|
|
141
|
-
* support for four-letter residue names
|
|
142
|
-
* 1.0.7.4
|
|
143
|
-
* added logging functionality
|
|
144
|
-
* 1.0.7.3
|
|
145
|
-
* improved parsing of BIOMT transforms
|
|
146
|
-
* 1.0.7.2
|
|
147
|
-
* added documentation stub at readthedocs
|
|
148
|
-
* 1.0.7.1
|
|
149
|
-
* support for split BIOMT tables and REMARKS 280, 375, 650, and 700
|
|
150
|
-
* 1.0.7
|
|
151
|
-
* pretty-print enabled
|
|
152
|
-
* 1.0
|
|
153
|
-
* Initial version
|
|
154
|
-
|
|
95
|
+
## Changelog
|
|
155
96
|
|
|
97
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full release history.
|
|
@@ -72,66 +72,6 @@ ATOM
|
|
|
72
72
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
##
|
|
76
|
-
* 1.5.2
|
|
77
|
-
* added capability to download from OPM and split out DUM resi's into a "dum" pdb
|
|
78
|
-
* 1.4.2
|
|
79
|
-
* updated alphafold interface
|
|
80
|
-
* 1.4.1
|
|
81
|
-
* Fixed parsing bug in `PDBRecordList`
|
|
82
|
-
* 1.4.0
|
|
83
|
-
* Introduced `PDBRecordList` and `PDBRecordDict` classes
|
|
84
|
-
* 1.3.3
|
|
85
|
-
* fixed bugs regarding assuming missing records actually present in mmcif parsing
|
|
86
|
-
* 1.3.2
|
|
87
|
-
* implemented `filepath` parameter in `PDBParser()` to make
|
|
88
|
-
reading local files more transparent
|
|
89
|
-
* 1.3.0
|
|
90
|
-
* streamline class attribute usage; full API documentation
|
|
91
|
-
* 1.2.3:
|
|
92
|
-
* bugfix: negative resids allowed
|
|
93
|
-
* 1.2.1:
|
|
94
|
-
* bugfix: hex issues AGAIN
|
|
95
|
-
* 1.2.0
|
|
96
|
-
* bugfix: hex issues again
|
|
97
|
-
* 1.1.9
|
|
98
|
-
* gently handles any nan values or '*' fillers
|
|
99
|
-
* 1.1.8
|
|
100
|
-
* Allow unstructured REMARK records (thanks a lot, packmol) to be parsed as REMARK.-1
|
|
101
|
-
* 1.1.6
|
|
102
|
-
* bugfix: detection of hex when no abcdef present based on a trip
|
|
103
|
-
* 1.1.5
|
|
104
|
-
* bugfix: allow for ONLY atom serial numbers to be hex-or-int
|
|
105
|
-
* 1.1.4
|
|
106
|
-
* Added ability to read hexadecimal atom indices for files with > 99999 atoms
|
|
107
|
-
* 1.1.3
|
|
108
|
-
* Added ability to group into models for multiple-model entries
|
|
109
|
-
* 1.1.2
|
|
110
|
-
* Added ability to retrieve pdbs from AlphaFold database
|
|
111
|
-
* 1.1.1
|
|
112
|
-
* version detection
|
|
113
|
-
* 1.0.9.1
|
|
114
|
-
* added limited functionality to parse mmCIF files, in particular to generate any
|
|
115
|
-
ATOM, HETATM, SSBOND, LINK, SEQADV, REMARK 350, and REMARK 465 records
|
|
116
|
-
* 1.0.8
|
|
117
|
-
* bug fix: handle variations in how symmetry operation matrices are represented
|
|
118
|
-
* 1.0.7.7
|
|
119
|
-
* cleaned up logging
|
|
120
|
-
* 1.0.7.6
|
|
121
|
-
* bug fix: leading whitespace in resname field of Residue10 record sometimes ignored
|
|
122
|
-
* 1.0.7.5
|
|
123
|
-
* support for four-letter residue names
|
|
124
|
-
* 1.0.7.4
|
|
125
|
-
* added logging functionality
|
|
126
|
-
* 1.0.7.3
|
|
127
|
-
* improved parsing of BIOMT transforms
|
|
128
|
-
* 1.0.7.2
|
|
129
|
-
* added documentation stub at readthedocs
|
|
130
|
-
* 1.0.7.1
|
|
131
|
-
* support for split BIOMT tables and REMARKS 280, 375, 650, and 700
|
|
132
|
-
* 1.0.7
|
|
133
|
-
* pretty-print enabled
|
|
134
|
-
* 1.0
|
|
135
|
-
* Initial version
|
|
136
|
-
|
|
75
|
+
## Changelog
|
|
137
76
|
|
|
77
|
+
See [CHANGELOG.md](CHANGELOG.md) for the full release history.
|
|
@@ -22,6 +22,7 @@ extensions = [
|
|
|
22
22
|
'sphinxcontrib.mermaid',
|
|
23
23
|
'sphinx.ext.napoleon',
|
|
24
24
|
'sphinx.ext.viewcode',
|
|
25
|
+
'myst_parser',
|
|
25
26
|
]
|
|
26
27
|
|
|
27
28
|
autosummary_generate = True # Enable autosummary tables
|
|
@@ -49,7 +50,7 @@ html_theme_options = {
|
|
|
49
50
|
"footer_icons": [
|
|
50
51
|
{
|
|
51
52
|
"name": "GitHub",
|
|
52
|
-
"url": "https://github.com/cameronabrams/
|
|
53
|
+
"url": "https://github.com/cameronabrams/pidibble",
|
|
53
54
|
"html": """
|
|
54
55
|
<svg role="img" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="currentColor">
|
|
55
56
|
<title>GitHub</title>
|
|
@@ -7,21 +7,21 @@
|
|
|
7
7
|
|
|
8
8
|
"""
|
|
9
9
|
import logging
|
|
10
|
-
logger=logging.getLogger(__name__)
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
11
|
|
|
12
12
|
class ListParser:
|
|
13
13
|
"""
|
|
14
14
|
A simple parser for lists of strings, with a customizable delimiter.
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
|
-
def __init__(self,d=','):
|
|
18
|
-
self.d=d
|
|
19
|
-
|
|
20
|
-
def parse(self,string):
|
|
17
|
+
def __init__(self, d=','):
|
|
18
|
+
self.d = d
|
|
19
|
+
|
|
20
|
+
def parse(self, string):
|
|
21
21
|
"""
|
|
22
22
|
Parse a string into a list of strings, using the specified delimiter.
|
|
23
23
|
If no delimiter is specified, it splits on whitespace.
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
Parameters
|
|
26
26
|
----------
|
|
27
27
|
string : str
|
|
@@ -32,12 +32,12 @@ class ListParser:
|
|
|
32
32
|
list
|
|
33
33
|
A list of strings parsed from the input string.
|
|
34
34
|
"""
|
|
35
|
-
if self.d
|
|
36
|
-
return [x for x in string.split() if x.strip()!='']
|
|
35
|
+
if self.d is None:
|
|
36
|
+
return [x for x in string.split() if x.strip() != '']
|
|
37
37
|
else:
|
|
38
|
-
return [x.strip() for x in string.split(self.d) if x.strip()!='']
|
|
39
|
-
|
|
40
|
-
def list_parse(obj,d):
|
|
38
|
+
return [x.strip() for x in string.split(self.d) if x.strip() != '']
|
|
39
|
+
|
|
40
|
+
def list_parse(obj, d):
|
|
41
41
|
"""
|
|
42
42
|
A factory function to create a ListParser with a specific delimiter.
|
|
43
43
|
|
|
@@ -58,21 +58,21 @@ def list_parse(obj,d):
|
|
|
58
58
|
"""
|
|
59
59
|
Define a dictionary of parsers for different list formats
|
|
60
60
|
"""
|
|
61
|
-
ListParsers={
|
|
62
|
-
'CList':list_parse(ListParser,','),
|
|
63
|
-
'SList':list_parse(ListParser,';'),
|
|
64
|
-
'WList':list_parse(ListParser,None),
|
|
65
|
-
'DList':list_parse(ListParser,':'),
|
|
66
|
-
'LList':list_parse(ListParser,'\n')
|
|
61
|
+
ListParsers = {
|
|
62
|
+
'CList': list_parse(ListParser, ','),
|
|
63
|
+
'SList': list_parse(ListParser, ';'),
|
|
64
|
+
'WList': list_parse(ListParser, None),
|
|
65
|
+
'DList': list_parse(ListParser, ':'),
|
|
66
|
+
'LList': list_parse(ListParser, '\n')
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
_cols="""
|
|
69
|
+
_cols = """
|
|
70
70
|
1 2 3 4 5 6 7 8
|
|
71
71
|
12345678901234567890123456789012345678901234567890123456789012345678901234567890"""
|
|
72
72
|
class StringParser:
|
|
73
73
|
"""
|
|
74
74
|
A parser for fixed-width strings, with a customizable field map.
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
Parameters
|
|
77
77
|
----------
|
|
78
78
|
fmtdict : dict
|
|
@@ -82,15 +82,15 @@ class StringParser:
|
|
|
82
82
|
allowed : dict, optional
|
|
83
83
|
A dictionary mapping field values to allowed values, for validation.
|
|
84
84
|
"""
|
|
85
|
-
def __init__(self,fmtdict,typemap,allowed={}):
|
|
86
|
-
self.typemap=typemap
|
|
87
|
-
self.fields={k:v for k,v in fmtdict.items()}
|
|
88
|
-
self.allowed=allowed
|
|
85
|
+
def __init__(self, fmtdict, typemap, allowed={}):
|
|
86
|
+
self.typemap = typemap
|
|
87
|
+
self.fields = {k: v for k, v in fmtdict.items()}
|
|
88
|
+
self.allowed = allowed
|
|
89
89
|
|
|
90
90
|
def parse(self, record):
|
|
91
91
|
"""
|
|
92
92
|
Parse a fixed-width string record into a dictionary of fields.
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
Parameters
|
|
95
95
|
----------
|
|
96
96
|
record : str
|
|
@@ -101,39 +101,39 @@ class StringParser:
|
|
|
101
101
|
dict
|
|
102
102
|
A dictionary of fields parsed from the input record.
|
|
103
103
|
"""
|
|
104
|
-
if len(record)>80:
|
|
104
|
+
if len(record) > 80:
|
|
105
105
|
logger.warning('The following record exceeds 80 bytes in length:')
|
|
106
106
|
self.report_record_error(record)
|
|
107
107
|
logger.warning('Stripping...')
|
|
108
108
|
record = record.strip()
|
|
109
|
-
if len(record)>80:
|
|
110
|
-
|
|
111
|
-
input_dict={}
|
|
112
|
-
record+=' '*(80-len(record))
|
|
113
|
-
for k,v in self.fields.items():
|
|
114
|
-
typestring,byte_range=v
|
|
115
|
-
typ=self.typemap[typestring]
|
|
116
|
-
assert byte_range[1]<=len(record),f'{record} {byte_range}'
|
|
109
|
+
if len(record) > 80:
|
|
110
|
+
raise ValueError(f'Record is too long; something wrong with your PDB file?')
|
|
111
|
+
input_dict = {}
|
|
112
|
+
record += ' ' * (80 - len(record)) # pad
|
|
113
|
+
for k, v in self.fields.items():
|
|
114
|
+
typestring, byte_range = v
|
|
115
|
+
typ = self.typemap[typestring]
|
|
116
|
+
assert byte_range[1] <= len(record), f'{record} {byte_range}'
|
|
117
117
|
# using columns beginning with "1" not "0"
|
|
118
|
-
fieldstring=record[byte_range[0]-1:byte_range[1]]
|
|
119
|
-
fieldstring=fieldstring.rstrip()
|
|
118
|
+
fieldstring = record[byte_range[0] - 1:byte_range[1]]
|
|
119
|
+
fieldstring = fieldstring.rstrip()
|
|
120
120
|
try:
|
|
121
121
|
# if len(fieldstring)>0 and not typ==str:
|
|
122
122
|
# fieldstring=''
|
|
123
|
-
input_dict[k]='' if fieldstring=='' else typ(fieldstring)
|
|
124
|
-
except:
|
|
125
|
-
self.report_field_error(record,k)
|
|
126
|
-
input_dict[k]=''
|
|
127
|
-
if typ==str:
|
|
128
|
-
input_dict[k]=input_dict[k].strip()
|
|
123
|
+
input_dict[k] = '' if fieldstring == '' else typ(fieldstring)
|
|
124
|
+
except (ValueError, TypeError):
|
|
125
|
+
self.report_field_error(record, k)
|
|
126
|
+
input_dict[k] = ''
|
|
127
|
+
if typ == str:
|
|
128
|
+
input_dict[k] = input_dict[k].strip()
|
|
129
129
|
if fieldstring in self.allowed:
|
|
130
|
-
assert input_dict[k] in self.allowed[fieldstring],f'Value {input_dict[k]} is not allowed for field {k}; allowed values are {self.allowed[fieldstring]}'
|
|
130
|
+
assert input_dict[k] in self.allowed[fieldstring], f'Value {input_dict[k]} is not allowed for field {k}; allowed values are {self.allowed[fieldstring]}'
|
|
131
131
|
return input_dict
|
|
132
|
-
|
|
133
|
-
def report_record_error(self,record,byte_range=[]):
|
|
132
|
+
|
|
133
|
+
def report_record_error(self, record, byte_range=[]):
|
|
134
134
|
"""
|
|
135
135
|
Report an error in parsing a fixed-width string record.
|
|
136
|
-
|
|
136
|
+
|
|
137
137
|
Parameters
|
|
138
138
|
----------
|
|
139
139
|
record : str
|
|
@@ -143,14 +143,14 @@ class StringParser:
|
|
|
143
143
|
If empty, the entire record is reported.
|
|
144
144
|
"""
|
|
145
145
|
if byte_range:
|
|
146
|
-
record=record[:byte_range[0]-1]+'\033[91m'+record[byte_range[0]:byte_range[1]
|
|
147
|
-
repstr=_cols+'\n'+record+'|'
|
|
146
|
+
record = record[:byte_range[0] - 1] + '\033[91m' + record[byte_range[0] - 1:byte_range[1]] + '\033[0m' + record[byte_range[1]:]
|
|
147
|
+
repstr = _cols + '\n' + record + '|'
|
|
148
148
|
logger.warning(repstr)
|
|
149
|
-
|
|
150
|
-
def report_field_error(self,record,k):
|
|
149
|
+
|
|
150
|
+
def report_field_error(self, record, k):
|
|
151
151
|
"""
|
|
152
152
|
Report an error in parsing a specific field from a fixed-width string record.
|
|
153
|
-
|
|
153
|
+
|
|
154
154
|
Parameters
|
|
155
155
|
----------
|
|
156
156
|
record : str
|
|
@@ -158,26 +158,27 @@ class StringParser:
|
|
|
158
158
|
k : str
|
|
159
159
|
The field name that caused the error.
|
|
160
160
|
"""
|
|
161
|
-
byte_range=self.fields[k][1]
|
|
161
|
+
byte_range = self.fields[k][1]
|
|
162
162
|
logger.warning(f'Could not parse field {k} from bytes {byte_range}:')
|
|
163
|
-
self.report_record_error(record,byte_range=byte_range)
|
|
163
|
+
self.report_record_error(record, byte_range=byte_range)
|
|
164
164
|
|
|
165
165
|
def safe_float(x):
|
|
166
166
|
"""
|
|
167
167
|
Convert a string to a float, returning 0.0 if the string is 'nan'.
|
|
168
168
|
"""
|
|
169
|
-
if x=='nan':
|
|
169
|
+
if x == 'nan':
|
|
170
170
|
return 0.0
|
|
171
171
|
return float(x)
|
|
172
172
|
|
|
173
|
-
def str2int_sig(arg:str):
|
|
173
|
+
def str2int_sig(arg: str):
|
|
174
174
|
"""
|
|
175
175
|
Convert a string to an integer, returning -1 if the string is not numeric.
|
|
176
176
|
If the string starts with a '-', it is returned as an integer.
|
|
177
177
|
"""
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
stripped = arg.strip()
|
|
179
|
+
if not stripped.isnumeric():
|
|
180
|
+
if stripped and stripped[0] == '-':
|
|
180
181
|
return int(arg)
|
|
181
182
|
else:
|
|
182
183
|
return -1
|
|
183
|
-
return int(arg)
|
|
184
|
+
return int(arg)
|