pypdb 2.2__tar.gz → 2.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.
- pypdb-2.4/PKG-INFO +59 -0
- {pypdb-2.2 → pypdb-2.4}/README.md +8 -12
- pypdb-2.4/pypdb/clients/data/data_types.py +192 -0
- pypdb-2.4/pypdb/clients/data/graphql/graphql.py +35 -0
- pypdb-2.4/pypdb/clients/data/graphql/test_graphql.py +25 -0
- pypdb-2.4/pypdb/clients/data/test_data_types.py +122 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/fasta/fasta_client.py +6 -2
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/fasta/fasta_client_test.py +1 -1
- pypdb-2.4/pypdb/clients/search/operators/__init__.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/text_operators.py +2 -1
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/search_client.py +12 -5
- {pypdb-2.2 → pypdb-2.4}/pypdb/pypdb.py +24 -20
- pypdb-2.4/pypdb/util/__init__.py +0 -0
- pypdb-2.4/pypdb.egg-info/PKG-INFO +59 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb.egg-info/SOURCES.txt +8 -1
- {pypdb-2.2 → pypdb-2.4}/setup.py +9 -1
- pypdb-2.4/tests/test_pypdb.py +67 -0
- pypdb-2.2/PKG-INFO +0 -15
- pypdb-2.2/pypdb.egg-info/PKG-INFO +0 -15
- {pypdb-2.2 → pypdb-2.4}/LICENSE +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/__init__.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/__init__.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/data/__init__.py +0 -0
- {pypdb-2.2/pypdb/clients/fasta → pypdb-2.4/pypdb/clients/data/graphql}/__init__.py +0 -0
- {pypdb-2.2/pypdb/clients/pdb → pypdb-2.4/pypdb/clients/fasta}/__init__.py +0 -0
- {pypdb-2.2/pypdb/clients/search → pypdb-2.4/pypdb/clients/pdb}/__init__.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/pdb/pdb_client.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/pdb/pdb_client_test.py +0 -0
- {pypdb-2.2/pypdb/util → pypdb-2.4/pypdb/clients/search}/__init__.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/chemical_operators.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/chemical_operators_test.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/seqmotif_operators.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/seqmotif_operators_test.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/sequence_operators.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/sequence_operators_test.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/structure_operators.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/structure_operators_test.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/operators/text_operators_test.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/clients/search/search_client_test.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/conftest.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/util/http_requests.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb/util/test_http_requests.py +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb.egg-info/.ipynb_checkpoints/dependency_links-checkpoint.txt +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb.egg-info/dependency_links.txt +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb.egg-info/requires.txt +0 -0
- {pypdb-2.2 → pypdb-2.4}/pypdb.egg-info/top_level.txt +0 -0
- {pypdb-2.2 → pypdb-2.4}/setup.cfg +0 -0
pypdb-2.4/PKG-INFO
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pypdb
|
|
3
|
+
Version: 2.4
|
|
4
|
+
Summary: A Python wrapper for the RCSB Protein Data Bank (PDB) API
|
|
5
|
+
Home-page: https://github.com/williamgilpin/pypdb
|
|
6
|
+
Download-URL: https://github.com/williamgilpin/pypdb/tarball/0.6
|
|
7
|
+
Author: William Gilpin
|
|
8
|
+
Author-email: firstnamelastname@gmail.com
|
|
9
|
+
Keywords: protein,data,RESTful,api
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: requests
|
|
13
|
+
|
|
14
|
+
# PyPDB
|
|
15
|
+
|
|
16
|
+
A Python 3 toolkit for performing searches with the RCSB Protein Data Bank (PDB). This can be used to perform advanced searches for PDB IDs matching various criteria, as well as to look up information associated with specific PDB IDs. This tool allows standard operations that can be perfomed from within the PDB website (BLAST, PFAM lookup, etc.) to be performed from within Python scripts.
|
|
17
|
+
|
|
18
|
+
If you use this module for any published work, please consider citing the accompanying paper
|
|
19
|
+
|
|
20
|
+
Gilpin, W. "PyPDB: A Python API for the Protein Data Bank."
|
|
21
|
+
Bioinformatics, Oxford Journals, 2016.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Install using pip:
|
|
26
|
+
|
|
27
|
+
$ pip install pypdb
|
|
28
|
+
|
|
29
|
+
To install the development version, which contains the latest features and fixes, install directly from GitHub using
|
|
30
|
+
|
|
31
|
+
$ pip install git+https://github.com/williamgilpin/pypdb
|
|
32
|
+
|
|
33
|
+
If you need to install directly from setup.py,
|
|
34
|
+
|
|
35
|
+
$ python setup.py install
|
|
36
|
+
|
|
37
|
+
Test the installation, and check that the code successfully connects to the PDB, navigate to the root directory and run
|
|
38
|
+
|
|
39
|
+
$ pytest
|
|
40
|
+
|
|
41
|
+
This code has been designed and tested for Python 3.
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### PDB Text Search
|
|
46
|
+
This package can be used to get lists of PDB IDs associated with specific search terms, experiment types, structures, and other common criteria. To use the simple API, see the examples in [`demos/demos.ipynb`](demos/demos.ipynb). For advanced search and query logic, see the examples in [`search/EXAMPLES.md`](pypdb/clients/search/EXAMPLES.md).
|
|
47
|
+
|
|
48
|
+
### PDB Data Fetch
|
|
49
|
+
Given a list of PDBs, this package can be used to fetch data associated with those PDBs, including their dates of deposition, lists of authors and associated publications, their sequences or structures, their top BLAST matches, and other query-specific attributes like lists of a ligands or chemical structure. To use the simple API, see the examples in [`demos/demos.ipynb`](demos/demos.ipynb). For advanced search and query logic, see the examples in [`data/EXAMPLES.md`](pypdb/clients/data/EXAMPLES.md).
|
|
50
|
+
|
|
51
|
+
## Issues and Feature Requests
|
|
52
|
+
|
|
53
|
+
If you run into an issue, or if you find a workaround for an existing issue, we would very much appreciate it if you could post your question or code as a GitHub issue.
|
|
54
|
+
|
|
55
|
+
If posting a feature request, please check that your request is possible using [the current GUI on current RCSB website](https://www.rcsb.org/search/advanced). If so, please perform your search, and then click the link that says `JSON` in the upper right hand corner of the Advanced Search box. Please post that JSON code with your feature request.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
@@ -2,24 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
A Python 3 toolkit for performing searches with the RCSB Protein Data Bank (PDB). This can be used to perform advanced searches for PDB IDs matching various criteria, as well as to look up information associated with specific PDB IDs. This tool allows standard operations that can be perfomed from within the PDB website (BLAST, PFAM lookup, etc.) to be performed from within Python scripts.
|
|
4
4
|
|
|
5
|
-
Examples of each function and its associated output can be found in [`demos/demos.ipynb`](demos/demos.ipynb).
|
|
6
|
-
|
|
7
5
|
If you use this module for any published work, please consider citing the accompanying paper
|
|
8
6
|
|
|
9
|
-
Gilpin, W. "PyPDB: A Python API for the Protein Data Bank."
|
|
7
|
+
Gilpin, W. "PyPDB: A Python API for the Protein Data Bank."
|
|
10
8
|
Bioinformatics, Oxford Journals, 2016.
|
|
11
9
|
|
|
12
|
-
**We very much welcome contributors and pull requests**
|
|
13
|
-
|
|
14
10
|
## Installation
|
|
15
11
|
|
|
16
12
|
Install using pip:
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
$ pip install pypdb
|
|
19
15
|
|
|
20
16
|
To install the development version, which contains the latest features and fixes, install directly from GitHub using
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
$ pip install git+https://github.com/williamgilpin/pypdb
|
|
23
19
|
|
|
24
20
|
If you need to install directly from setup.py,
|
|
25
21
|
|
|
@@ -27,17 +23,17 @@ If you need to install directly from setup.py,
|
|
|
27
23
|
|
|
28
24
|
Test the installation, and check that the code successfully connects to the PDB, navigate to the root directory and run
|
|
29
25
|
|
|
30
|
-
|
|
26
|
+
$ pytest
|
|
31
27
|
|
|
32
28
|
This code has been designed and tested for Python 3.
|
|
33
29
|
|
|
34
30
|
## Usage
|
|
35
31
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
Given a list of PDBs, this package can be used to fetch any data associated with those PDBs, including their dates of deposition, lists of authors and associated publications, their sequences or structures, their top BLAST matches, and other query-specific attributes like lists of a ligands or chemical structure.
|
|
32
|
+
### PDB Text Search
|
|
33
|
+
This package can be used to get lists of PDB IDs associated with specific search terms, experiment types, structures, and other common criteria. To use the simple API, see the examples in [`demos/demos.ipynb`](demos/demos.ipynb). For advanced search and query logic, see the examples in [`search/EXAMPLES.md`](pypdb/clients/search/EXAMPLES.md).
|
|
39
34
|
|
|
40
|
-
|
|
35
|
+
### PDB Data Fetch
|
|
36
|
+
Given a list of PDBs, this package can be used to fetch data associated with those PDBs, including their dates of deposition, lists of authors and associated publications, their sequences or structures, their top BLAST matches, and other query-specific attributes like lists of a ligands or chemical structure. To use the simple API, see the examples in [`demos/demos.ipynb`](demos/demos.ipynb). For advanced search and query logic, see the examples in [`data/EXAMPLES.md`](pypdb/clients/data/EXAMPLES.md).
|
|
41
37
|
|
|
42
38
|
## Issues and Feature Requests
|
|
43
39
|
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Class for data types that can be accessed in the PDB DATA-API
|
|
3
|
+
https://data.rcsb.org/#data-organization
|
|
4
|
+
|
|
5
|
+
Namely:
|
|
6
|
+
- entry
|
|
7
|
+
- polymer entity
|
|
8
|
+
- branched entity
|
|
9
|
+
- non-polymer entity
|
|
10
|
+
- polymer instance
|
|
11
|
+
- branched instance
|
|
12
|
+
- non-polymer instance
|
|
13
|
+
- assembly
|
|
14
|
+
- chemical component
|
|
15
|
+
(currently not implemented:)
|
|
16
|
+
- PubMed integrated data
|
|
17
|
+
- UniProt integrated data
|
|
18
|
+
- DrugBank integrated data
|
|
19
|
+
"""
|
|
20
|
+
from dataclasses import dataclass, field
|
|
21
|
+
from enum import Enum
|
|
22
|
+
|
|
23
|
+
#TODO: handle batch requests
|
|
24
|
+
|
|
25
|
+
from pypdb.clients.data.graphql.graphql import search_graphql
|
|
26
|
+
|
|
27
|
+
class DataType(Enum):
|
|
28
|
+
ENTRY = "entries"
|
|
29
|
+
POLYMER_ENTITY = "polymer_entities"
|
|
30
|
+
BRANCHED_ENTITY = "branched_entities"
|
|
31
|
+
NONPOLYMER_ENTITY = "nonpolymer_entities"
|
|
32
|
+
POLYMER_ENTITY_INSTANCE = "polymer_entity_instances"
|
|
33
|
+
BRANCHED_ENTITY_INSTANCE = "branched_entity_instances"
|
|
34
|
+
NONPOLYMER_ENTITY_INSTANCE = "nonpolymer_entity_instances"
|
|
35
|
+
ASSEMBLY = "assemblies"
|
|
36
|
+
CHEMICAL_COMPONENT = "chem_comps"
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class DataFetcher:
|
|
40
|
+
"""
|
|
41
|
+
General class that will host various data types, as detailed above.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
id: str | list
|
|
45
|
+
data_type: DataType
|
|
46
|
+
|
|
47
|
+
properties: dict = field(default_factory=dict)
|
|
48
|
+
json_query: dict = field(default_factory=dict)
|
|
49
|
+
response: dict = field(default_factory=dict)
|
|
50
|
+
|
|
51
|
+
def __post_init__(self):
|
|
52
|
+
"""
|
|
53
|
+
Check types of IDs given, format accordingly.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
if isinstance(self.id, str):
|
|
57
|
+
self.id = [self.id]
|
|
58
|
+
|
|
59
|
+
if "entit" in self.data_type.value and "instance" not in self.data_type.value:
|
|
60
|
+
for id in self.id:
|
|
61
|
+
if '_' not in id:
|
|
62
|
+
print(f"WARNING: {id} not valid for {self.data_type.value}.")
|
|
63
|
+
elif "instance" in self.data_type.value:
|
|
64
|
+
for id in self.id:
|
|
65
|
+
if '.' not in id:
|
|
66
|
+
print(f"WARNING: {id} not valid for {self.data_type.value}.")
|
|
67
|
+
elif self.data_type == DataType.ASSEMBLY:
|
|
68
|
+
for id in self.id:
|
|
69
|
+
if '-' not in id:
|
|
70
|
+
print(f"WARNING: {id} not valid for {self.data_type.value}.")
|
|
71
|
+
|
|
72
|
+
def add_property(self, property):
|
|
73
|
+
"""
|
|
74
|
+
Add property to the list of data to fetch from the PDB.
|
|
75
|
+
|
|
76
|
+
property is a python dict, with keys as properties, and
|
|
77
|
+
values as subproperties.
|
|
78
|
+
|
|
79
|
+
e.g.:
|
|
80
|
+
|
|
81
|
+
{"cell": ["volume", "angle_beta"], "exptl": ["method"]}
|
|
82
|
+
|
|
83
|
+
If the user is trying to add a property that already exists,
|
|
84
|
+
the subproperties are merged.
|
|
85
|
+
"""
|
|
86
|
+
# check input data type
|
|
87
|
+
if not isinstance(property, dict):
|
|
88
|
+
raise TypeError
|
|
89
|
+
# check data types of keys in dict
|
|
90
|
+
if not all([isinstance(key, str) for key in property.keys()]):
|
|
91
|
+
raise TypeError
|
|
92
|
+
# check that values are lists of strings
|
|
93
|
+
for key, value in property.items():
|
|
94
|
+
if isinstance(value, str):
|
|
95
|
+
property[key] = [value]
|
|
96
|
+
elif not isinstance(value, list):
|
|
97
|
+
raise TypeError
|
|
98
|
+
else:
|
|
99
|
+
if not all([isinstance(val, str) for val in value]):
|
|
100
|
+
raise TypeError
|
|
101
|
+
|
|
102
|
+
# add properties to the dict
|
|
103
|
+
for key, value in property.items():
|
|
104
|
+
if key not in self.properties:
|
|
105
|
+
self.properties[key] = value
|
|
106
|
+
else:
|
|
107
|
+
self.properties[key] += value
|
|
108
|
+
self.properties[key] = list(set(self.properties[key]))
|
|
109
|
+
|
|
110
|
+
def generate_json_query(self):
|
|
111
|
+
"""
|
|
112
|
+
Given IDs, data type, and properties to fetch, create JSON query that
|
|
113
|
+
will utilize graphql.
|
|
114
|
+
"""
|
|
115
|
+
if not self.properties:
|
|
116
|
+
print("ERROR: no properties given to generate JSON query.")
|
|
117
|
+
raise ValueError
|
|
118
|
+
|
|
119
|
+
if self.data_type == DataType.ENTRY:
|
|
120
|
+
q_str = "entry_ids"
|
|
121
|
+
elif "entit" in self.data_type.value:
|
|
122
|
+
if "instance" in self.data_type.value:
|
|
123
|
+
q_str = "instance_ids"
|
|
124
|
+
else:
|
|
125
|
+
q_str = "entity_ids"
|
|
126
|
+
elif self.data_type == DataType.ASSEMBLY:
|
|
127
|
+
q_str = "assembly_ids"
|
|
128
|
+
elif self.data_type == DataType.CHEMICAL_COMPONENT:
|
|
129
|
+
q_str = "comp_ids"
|
|
130
|
+
|
|
131
|
+
data_str = f"{self.data_type.value}({q_str}: [" + ",".join(f"\"{w}\"" for w in self.id) + "])"
|
|
132
|
+
|
|
133
|
+
props_string = ""
|
|
134
|
+
for key, val in self.properties.items():
|
|
135
|
+
if len(val) == 0:
|
|
136
|
+
props_string += f"{key},"
|
|
137
|
+
else:
|
|
138
|
+
props_string += f"{key} {{" + ",".join(val) + "}"
|
|
139
|
+
|
|
140
|
+
self.json_query = {'query': "{" + data_str + "{" + props_string + "}}"}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def fetch_data(self):
|
|
144
|
+
"""
|
|
145
|
+
Once the JSON query is created, fetch data from the PDB, using graphql.
|
|
146
|
+
"""
|
|
147
|
+
if not self.json_query:
|
|
148
|
+
self.generate_json_query()
|
|
149
|
+
|
|
150
|
+
response = search_graphql(self.json_query)
|
|
151
|
+
|
|
152
|
+
if "errors" in response:
|
|
153
|
+
print("ERROR encountered in fetch_data().")
|
|
154
|
+
for error in response['errors']:
|
|
155
|
+
print(error['message'])
|
|
156
|
+
|
|
157
|
+
return
|
|
158
|
+
|
|
159
|
+
self.response = response
|
|
160
|
+
|
|
161
|
+
if len(self.response['data'][self.data_type.value]) != len(self.id):
|
|
162
|
+
print("WARNING: one or more IDs not found in the PDB.")
|
|
163
|
+
|
|
164
|
+
def return_data_as_df_dict(self):
|
|
165
|
+
"""
|
|
166
|
+
Return the fetched data as a dict usable by pandas or polars.
|
|
167
|
+
"""
|
|
168
|
+
if not self.response:
|
|
169
|
+
return None
|
|
170
|
+
|
|
171
|
+
data = self.response['data'][self.data_type.value]
|
|
172
|
+
|
|
173
|
+
# flatten data dictionary by joining property and subproperty names
|
|
174
|
+
data_flat = {}
|
|
175
|
+
for i, entry in enumerate(data):
|
|
176
|
+
id = self.id[i]
|
|
177
|
+
curr_dict = {}
|
|
178
|
+
for key, values in entry.items():
|
|
179
|
+
if isinstance(values, list):
|
|
180
|
+
v = values[0]
|
|
181
|
+
else:
|
|
182
|
+
v = values
|
|
183
|
+
if isinstance(v, str):
|
|
184
|
+
new_key = f"{key}"
|
|
185
|
+
curr_dict[new_key] = v
|
|
186
|
+
else:
|
|
187
|
+
for subprop, val in v.items():
|
|
188
|
+
new_key = f"{key}.{subprop}"
|
|
189
|
+
curr_dict[new_key] = val
|
|
190
|
+
data_flat[id] = curr_dict
|
|
191
|
+
|
|
192
|
+
return data_flat
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Contains logic to perform arbitrary GraphQL searches against RCSB.
|
|
2
|
+
|
|
3
|
+
For the differences between the GraphQL and RESTful searches, see:
|
|
4
|
+
https://data.rcsb.org/index.html#gql-vs-rest
|
|
5
|
+
"""
|
|
6
|
+
import requests
|
|
7
|
+
import warnings
|
|
8
|
+
from typing import Any # DO NOT APPROVE: fix this to actual type
|
|
9
|
+
|
|
10
|
+
RSCB_GRAPHQL_URL = "https://data.rcsb.org/graphql?query="
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def search_graphql(graphql_json_query: str) -> Any:
|
|
14
|
+
"""Performs RCSB search with JSON query using GraphQL.
|
|
15
|
+
|
|
16
|
+
For details on what the RCSB GraphQL interface is, see:
|
|
17
|
+
https://data.rcsb.org/index.html#gql-api
|
|
18
|
+
|
|
19
|
+
This function should return the equivalent information as this site:
|
|
20
|
+
https://data.rcsb.org/graphql/index.html
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
graphql_json_query: GraphQL JSON query, as a string. Whitespace doesn't
|
|
24
|
+
matter. e.g. "{entry(entry_id:"4HHB"){exptl{method}}}"
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
response = requests.post(url=RSCB_GRAPHQL_URL,
|
|
28
|
+
json=graphql_json_query)
|
|
29
|
+
|
|
30
|
+
if not response.ok:
|
|
31
|
+
warnings.warn(f"It appears request failed with: {response.text}")
|
|
32
|
+
response.raise_for_status()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
return response.json()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Unit tests for RCSB DATA API Python wrapper."""
|
|
2
|
+
import unittest
|
|
3
|
+
from unittest import mock
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
from pypdb.clients.data.graphql import graphql
|
|
7
|
+
|
|
8
|
+
class TestGraphQL(unittest.TestCase):
|
|
9
|
+
@mock.patch.object(requests, "post")
|
|
10
|
+
def test_simple_search(self, mock_post):
|
|
11
|
+
json_query = {'query': '{ entry(entry_id: "4HHB"){struct {title}} }'}
|
|
12
|
+
expected_return_json_as_dict = {'data': {'entry': {'struct': {'title': 'THE CRYSTAL STRUCTURE OF HUMAN DEOXYHAEMOGLOBIN AT 1.74 ANGSTROMS RESOLUTION'}}}}
|
|
13
|
+
|
|
14
|
+
mock_response = mock.create_autospec(requests.Response, instance=True)
|
|
15
|
+
mock_response.json.return_value = expected_return_json_as_dict
|
|
16
|
+
mock_post.return_value = mock_response
|
|
17
|
+
|
|
18
|
+
results = graphql.search_graphql(json_query)
|
|
19
|
+
|
|
20
|
+
mock_post.assert_called_once_with(url=graphql.RSCB_GRAPHQL_URL, json=json_query)
|
|
21
|
+
self.assertEqual(results, expected_return_json_as_dict)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == '__main__':
|
|
25
|
+
unittest.main()
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for the data_types classes.
|
|
3
|
+
"""
|
|
4
|
+
import unittest
|
|
5
|
+
from unittest import mock
|
|
6
|
+
import requests
|
|
7
|
+
from pypdb.clients.data.graphql.graphql import RSCB_GRAPHQL_URL
|
|
8
|
+
|
|
9
|
+
from pypdb.clients.data.data_types import DataFetcher, DataType
|
|
10
|
+
|
|
11
|
+
class TestEntry(unittest.TestCase):
|
|
12
|
+
def test_create(self):
|
|
13
|
+
entry = DataFetcher("4HHB", DataType.ENTRY)
|
|
14
|
+
|
|
15
|
+
self.assertTrue(isinstance(entry.properties, dict))
|
|
16
|
+
self.assertTrue(not entry.properties)
|
|
17
|
+
|
|
18
|
+
self.assertTrue(isinstance(entry.json_query, dict))
|
|
19
|
+
self.assertTrue(not entry.json_query)
|
|
20
|
+
|
|
21
|
+
self.assertTrue(isinstance(entry.response, dict))
|
|
22
|
+
self.assertTrue(not entry.response)
|
|
23
|
+
|
|
24
|
+
self.assertEqual(entry.id, ["4HHB"])
|
|
25
|
+
|
|
26
|
+
def test_generate_json_query(self):
|
|
27
|
+
entry = DataFetcher("4HHB", DataType.ENTRY)
|
|
28
|
+
|
|
29
|
+
property = {"exptl":["method", "details"]}
|
|
30
|
+
|
|
31
|
+
entry.add_property(property)
|
|
32
|
+
|
|
33
|
+
self.assertIsNotNone(entry.properties)
|
|
34
|
+
|
|
35
|
+
entry.generate_json_query()
|
|
36
|
+
|
|
37
|
+
self.assertTrue(isinstance(entry.json_query, dict))
|
|
38
|
+
self.assertTrue("query" in entry.json_query)
|
|
39
|
+
|
|
40
|
+
def test_fetch_entry(self):
|
|
41
|
+
entry = DataFetcher("4HHB", DataType.ENTRY)
|
|
42
|
+
property = {"exptl":["method", "details"]}
|
|
43
|
+
|
|
44
|
+
entry.add_property(property)
|
|
45
|
+
|
|
46
|
+
entry.fetch_data()
|
|
47
|
+
|
|
48
|
+
self.assertTrue(entry.response)
|
|
49
|
+
|
|
50
|
+
def test_return_data_as_pandas_df(self):
|
|
51
|
+
entry = DataFetcher(["4HHB", "12CA", "3PQR"], DataType.ENTRY)
|
|
52
|
+
property = {"exptl":["method", "details"]}
|
|
53
|
+
|
|
54
|
+
entry.add_property(property)
|
|
55
|
+
|
|
56
|
+
entry.fetch_data()
|
|
57
|
+
df = entry.return_data_as_pandas_df()
|
|
58
|
+
|
|
59
|
+
self.assertTrue(df is not None)
|
|
60
|
+
|
|
61
|
+
def test_assembly_fetch(self):
|
|
62
|
+
assembly = DataFetcher(["4HHB-1", "12CA-1", "3PQR-1"], DataType.ASSEMBLY)
|
|
63
|
+
property = {"rcsb_assembly_info": ["entry_id", "assembly_id", "polymer_entity_instance_count"]}
|
|
64
|
+
|
|
65
|
+
assembly.add_property(property)
|
|
66
|
+
assembly.fetch_data()
|
|
67
|
+
|
|
68
|
+
self.assertFalse(not assembly.response)
|
|
69
|
+
|
|
70
|
+
def test_polymer_entity_fetch(self):
|
|
71
|
+
fetcher = DataFetcher(["2CPK_1","3WHM_1","2D5Z_1"], DataType.POLYMER_ENTITY)
|
|
72
|
+
|
|
73
|
+
property = {"rcsb_id": [],
|
|
74
|
+
"rcsb_entity_source_organism": ["ncbi_taxonomy_id", "ncbi_scientific_name"],
|
|
75
|
+
"rcsb_cluster_membership": ["cluster_id", "identity"]}
|
|
76
|
+
|
|
77
|
+
fetcher.add_property(property)
|
|
78
|
+
fetcher.fetch_data()
|
|
79
|
+
|
|
80
|
+
self.assertFalse(not fetcher.response)
|
|
81
|
+
|
|
82
|
+
df = fetcher.return_data_as_pandas_df()
|
|
83
|
+
self.assertFalse(df is None)
|
|
84
|
+
|
|
85
|
+
def test_polymer_instance_fetch(self):
|
|
86
|
+
fetcher = DataFetcher(["4HHB.A", "12CA.A", "3PQR.A"], DataType.POLYMER_ENTITY_INSTANCE)
|
|
87
|
+
property = {"rcsb_id": [],
|
|
88
|
+
"rcsb_polymer_instance_annotation": ["annotation_id", "name", "type"]}
|
|
89
|
+
fetcher.add_property(property)
|
|
90
|
+
fetcher.fetch_data()
|
|
91
|
+
|
|
92
|
+
self.assertFalse(not fetcher.response)
|
|
93
|
+
|
|
94
|
+
df = fetcher.return_data_as_pandas_df()
|
|
95
|
+
self.assertFalse(df is None)
|
|
96
|
+
|
|
97
|
+
def test_branched_entity_fetch(self):
|
|
98
|
+
fetcher = DataFetcher(["5FMB_2", "6L63_3"], DataType.BRANCHED_ENTITY)
|
|
99
|
+
property = {"pdbx_entity_branch": ["type"],
|
|
100
|
+
"pdbx_entity_branch_descriptor": ["type", "descriptor"]}
|
|
101
|
+
|
|
102
|
+
fetcher.add_property(property)
|
|
103
|
+
fetcher.fetch_data()
|
|
104
|
+
|
|
105
|
+
self.assertFalse(not fetcher.response)
|
|
106
|
+
|
|
107
|
+
df = fetcher.return_data_as_pandas_df()
|
|
108
|
+
self.assertFalse(df is None)
|
|
109
|
+
|
|
110
|
+
def test_chem_comps_fetch(self):
|
|
111
|
+
fetcher = DataFetcher(["NAG","EBW"], DataType.CHEMICAL_COMPONENT)
|
|
112
|
+
property = {"rcsb_id":[], "chem_comp": ["type", "formula_weight","name","formula"],
|
|
113
|
+
"rcsb_chem_comp_info":["initial_release_date"]}
|
|
114
|
+
fetcher.add_property(property)
|
|
115
|
+
fetcher.fetch_data()
|
|
116
|
+
self.assertFalse(not fetcher.response)
|
|
117
|
+
|
|
118
|
+
df = fetcher.return_data_as_pandas_df()
|
|
119
|
+
self.assertFalse(df is None)
|
|
120
|
+
|
|
121
|
+
if __name__ == '__main__':
|
|
122
|
+
unittest.main()
|
|
@@ -51,18 +51,22 @@ def _parse_fasta_text_to_list(raw_fasta_text: str) -> List[FastaSequence]:
|
|
|
51
51
|
return fasta_list
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
def get_fasta_from_rcsb_entry(rcsb_id: str
|
|
54
|
+
def get_fasta_from_rcsb_entry(rcsb_id: str,
|
|
55
|
+
verbosity: bool = True,
|
|
56
|
+
) -> List[FastaSequence]:
|
|
55
57
|
"""Fetches FASTA sequence associated with PDB structure from RCSB.
|
|
56
58
|
|
|
57
59
|
Args:
|
|
58
60
|
rcsb_id: RCSB accession code of the structure of interest. E.g. `"5RU3"`
|
|
61
|
+
verbosity: Print out the search query to the console (default: True)
|
|
59
62
|
|
|
60
63
|
Returns:
|
|
61
64
|
Dictionary containing FASTA result, from polymer entity id to the
|
|
62
65
|
`FastaSequence` object associated with that entity.
|
|
63
66
|
"""
|
|
64
67
|
|
|
65
|
-
|
|
68
|
+
if verbosity:
|
|
69
|
+
print("Querying RCSB for the '{}' FASTA file.".format(rcsb_id))
|
|
66
70
|
response = requests.get(FASTA_BASE_URL + rcsb_id)
|
|
67
71
|
|
|
68
72
|
if not response.ok:
|
|
@@ -16,7 +16,7 @@ class TestFastaLogic(unittest.TestCase):
|
|
|
16
16
|
mock_response.text = "fake_fasta_response"
|
|
17
17
|
mock_get.return_value = mock_response
|
|
18
18
|
|
|
19
|
-
fasta_client.get_fasta_from_rcsb_entry("6TML")
|
|
19
|
+
fasta_client.get_fasta_from_rcsb_entry("6TML", verbosity=True)
|
|
20
20
|
mock_get.assert_called_once_with(
|
|
21
21
|
"https://www.rcsb.org/fasta/entry/6TML")
|
|
22
22
|
mock_parse_fasta.assert_called_once_with("fake_fasta_response")
|
|
File without changes
|
|
@@ -132,7 +132,8 @@ def perform_search(
|
|
|
132
132
|
return_type: ReturnType = ReturnType.ENTRY,
|
|
133
133
|
request_options: Optional[RequestOptions] = None,
|
|
134
134
|
return_with_scores: bool = False,
|
|
135
|
-
return_raw_json_dict: bool = False
|
|
135
|
+
return_raw_json_dict: bool = False,
|
|
136
|
+
verbosity: bool = True,
|
|
136
137
|
) -> Union[List[str], List[ScoredResult], RawJSONDictResponse]:
|
|
137
138
|
"""Performs search specified by `search_operator`.
|
|
138
139
|
Returns entity strings of type `return_type` that match the resulting hits.
|
|
@@ -156,6 +157,7 @@ def perform_search(
|
|
|
156
157
|
(if this is true, returns List[ScoredResult] instead of List[str])
|
|
157
158
|
return_raw_json_dict: If True, this function returns the raw JSON
|
|
158
159
|
response from RCSB, instead of a
|
|
160
|
+
verbosity: Print out the search query to the console (default: True)
|
|
159
161
|
|
|
160
162
|
Returns:
|
|
161
163
|
List of entity ids, corresponding to entities that match the given
|
|
@@ -184,7 +186,8 @@ def perform_search(
|
|
|
184
186
|
return_type=return_type,
|
|
185
187
|
request_options=request_options,
|
|
186
188
|
return_with_scores=return_with_scores,
|
|
187
|
-
return_raw_json_dict=return_raw_json_dict
|
|
189
|
+
return_raw_json_dict=return_raw_json_dict,
|
|
190
|
+
verbosity=verbosity)
|
|
188
191
|
|
|
189
192
|
|
|
190
193
|
_SEARCH_OPERATORS = text_operators.TEXT_SEARCH_OPERATORS + [
|
|
@@ -197,7 +200,8 @@ def perform_search_with_graph(
|
|
|
197
200
|
return_type: ReturnType = ReturnType.ENTRY,
|
|
198
201
|
request_options: Optional[RequestOptions] = None,
|
|
199
202
|
return_with_scores: bool = False,
|
|
200
|
-
return_raw_json_dict: bool = False
|
|
203
|
+
return_raw_json_dict: bool = False,
|
|
204
|
+
verbosity: bool = True,
|
|
201
205
|
) -> Union[List[str], RawJSONDictResponse, List[ScoredResult]]:
|
|
202
206
|
"""Performs specified search using RCSB's search node logic.
|
|
203
207
|
|
|
@@ -222,6 +226,7 @@ def perform_search_with_graph(
|
|
|
222
226
|
get the top X hits that are similar to a certain protein sequence.
|
|
223
227
|
return_raw_json_dict: Whether to return raw JSON response.
|
|
224
228
|
(for example, to analyze the scores of various matches)
|
|
229
|
+
verbosity: Print out the search query to the console (default: True)
|
|
225
230
|
|
|
226
231
|
Returns:
|
|
227
232
|
List of strings, corresponding to hits in the database. Will be of the
|
|
@@ -234,6 +239,7 @@ def perform_search_with_graph(
|
|
|
234
239
|
if type(query_object) in _SEARCH_OPERATORS:
|
|
235
240
|
cast_query_object = _QueryNode(query_object) # type: ignore
|
|
236
241
|
else:
|
|
242
|
+
# print(type(query_object))
|
|
237
243
|
cast_query_object = query_object # type: ignore
|
|
238
244
|
|
|
239
245
|
if request_options is not None:
|
|
@@ -247,8 +253,9 @@ def perform_search_with_graph(
|
|
|
247
253
|
"return_type": return_type.value
|
|
248
254
|
}
|
|
249
255
|
|
|
250
|
-
|
|
251
|
-
|
|
256
|
+
if verbosity:
|
|
257
|
+
print("Querying RCSB Search using the following parameters:\n %s \n" %
|
|
258
|
+
json.dumps(rcsb_query_dict))
|
|
252
259
|
|
|
253
260
|
response = requests.post(url=SEARCH_URL_ENDPOINT,
|
|
254
261
|
data=json.dumps(rcsb_query_dict))
|
|
@@ -17,7 +17,6 @@ If you find this code useful, please consider citing the paper:
|
|
|
17
17
|
'''
|
|
18
18
|
from collections import OrderedDict, Counter
|
|
19
19
|
from itertools import repeat, chain
|
|
20
|
-
import requests
|
|
21
20
|
import time
|
|
22
21
|
import re
|
|
23
22
|
import json
|
|
@@ -139,6 +138,9 @@ class Query(object):
|
|
|
139
138
|
elif query_type == "pfam":
|
|
140
139
|
query_type = "text"
|
|
141
140
|
query_subtype = "pfam"
|
|
141
|
+
elif query_type == "uniprot":
|
|
142
|
+
query_type = "text"
|
|
143
|
+
query_subtype = "uniprot"
|
|
142
144
|
else:
|
|
143
145
|
query_subtype = None
|
|
144
146
|
|
|
@@ -258,6 +260,14 @@ class Query(object):
|
|
|
258
260
|
"attribute":
|
|
259
261
|
"rcsb_polymer_entity_annotation.annotation_id"
|
|
260
262
|
}
|
|
263
|
+
if query_subtype == "uniprot":
|
|
264
|
+
query_params['parameters'] = {
|
|
265
|
+
"operator": "exact_match",
|
|
266
|
+
"negation": False,
|
|
267
|
+
"value": str(search_term),
|
|
268
|
+
"attribute":
|
|
269
|
+
"rcsb_polymer_entity_container_identifiers.reference_sequence_identifiers.database_accession"
|
|
270
|
+
}
|
|
261
271
|
|
|
262
272
|
self.scan_params = dict()
|
|
263
273
|
self.scan_params["query"] = query_params
|
|
@@ -489,13 +499,13 @@ def get_pdb_file(pdb_id: str, filetype='pdb', compression=False):
|
|
|
489
499
|
"See `pypdb/clients/pdb/pdb_client.py` for a near-identical "
|
|
490
500
|
"function to use", DeprecationWarning)
|
|
491
501
|
|
|
492
|
-
if filetype
|
|
502
|
+
if filetype == 'pdb':
|
|
493
503
|
filetype_enum = pdb_client.PDBFileType.PDB
|
|
494
|
-
elif filetype
|
|
504
|
+
elif filetype == 'cif':
|
|
495
505
|
filetype_enum = pdb_client.PDBFileType.CIF
|
|
496
|
-
elif filetype
|
|
506
|
+
elif filetype == 'xml':
|
|
497
507
|
filetype_enum = pdb_client.PDBFileType.XML
|
|
498
|
-
elif filetype
|
|
508
|
+
elif filetype == 'structfact':
|
|
499
509
|
filetype_enum = pdb_client.PDBFileType.STRUCTFACT
|
|
500
510
|
else:
|
|
501
511
|
warnings.warn(
|
|
@@ -505,14 +515,14 @@ def get_pdb_file(pdb_id: str, filetype='pdb', compression=False):
|
|
|
505
515
|
|
|
506
516
|
|
|
507
517
|
# https://data.rcsb.org/migration-guide.html#chem-comp-description
|
|
508
|
-
|
|
518
|
+
def describe_chemical(chem_id):
|
|
509
519
|
# """
|
|
510
520
|
|
|
511
521
|
# Parameters
|
|
512
522
|
# ----------
|
|
513
523
|
|
|
514
524
|
# chem_id : string
|
|
515
|
-
# A
|
|
525
|
+
# A 3 character string representing the full chemical sequence of interest (ie, NAG)
|
|
516
526
|
|
|
517
527
|
# Returns
|
|
518
528
|
# -------
|
|
@@ -523,19 +533,13 @@ def get_pdb_file(pdb_id: str, filetype='pdb', compression=False):
|
|
|
523
533
|
# Examples
|
|
524
534
|
# --------
|
|
525
535
|
# >>> chem_desc = describe_chemical('NAG')
|
|
526
|
-
# >>> print(chem_desc)
|
|
527
|
-
#
|
|
528
|
-
# 'InChIKey': 'OVRNDRQMDRJTHS-FMDGEEDCSA-N', '@type': 'D-saccharide',
|
|
529
|
-
# 'chemicalName': 'N-ACETYL-D-GLUCOSAMINE', '@chemicalID': 'NAG',
|
|
530
|
-
# 'smiles': 'CC(=O)N[C@@H]1[C@H]([C@@H]([C@H](O[C@H]1O)CO)O)O', '
|
|
531
|
-
# InChI': 'InChI=1S/C8H15NO6/c1-3(11)9-5-7(13)6(12)4(2-10)15-8(5)14/
|
|
532
|
-
# h4-8,10,12-14H,2H2,1H3,(H,9,11)/t4-,5-,6-,7-,8-/m1/s1',
|
|
533
|
-
# 'formula': 'C8 H15 N O6'}}}}
|
|
534
|
-
|
|
536
|
+
# >>> print(chem_desc["rcsb_chem_comp_descriptor"]["smiles"])
|
|
537
|
+
# 'CC(=O)NC1C(C(C(OC1O)CO)O)O'
|
|
535
538
|
# """
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
+
if (len(chem_id) > 3):
|
|
540
|
+
raise Exception("Ligand id with more than 3 characters provided")
|
|
541
|
+
|
|
542
|
+
return get_info(chem_id, url_root = 'https://data.rcsb.org/rest/v1/core/chemcomp/')
|
|
539
543
|
|
|
540
544
|
# def get_ligands(pdb_id):
|
|
541
545
|
# """Return ligands of given PDB ID
|
|
@@ -653,7 +657,7 @@ def get_pdb_file(pdb_id: str, filetype='pdb', compression=False):
|
|
|
653
657
|
# return remove_at_sign(out['sequenceCluster'])
|
|
654
658
|
|
|
655
659
|
|
|
656
|
-
def get_blast(pdb_id, chain_id='A', identity_cutoff=0.99):
|
|
660
|
+
def get_blast(pdb_id, chain_id='A', identity_cutoff=0.99, verbosity=True):
|
|
657
661
|
"""
|
|
658
662
|
---
|
|
659
663
|
WARNING: this function is deprecated and slated to be deleted due to RCSB
|
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: pypdb
|
|
3
|
+
Version: 2.4
|
|
4
|
+
Summary: A Python wrapper for the RCSB Protein Data Bank (PDB) API
|
|
5
|
+
Home-page: https://github.com/williamgilpin/pypdb
|
|
6
|
+
Download-URL: https://github.com/williamgilpin/pypdb/tarball/0.6
|
|
7
|
+
Author: William Gilpin
|
|
8
|
+
Author-email: firstnamelastname@gmail.com
|
|
9
|
+
Keywords: protein,data,RESTful,api
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: requests
|
|
13
|
+
|
|
14
|
+
# PyPDB
|
|
15
|
+
|
|
16
|
+
A Python 3 toolkit for performing searches with the RCSB Protein Data Bank (PDB). This can be used to perform advanced searches for PDB IDs matching various criteria, as well as to look up information associated with specific PDB IDs. This tool allows standard operations that can be perfomed from within the PDB website (BLAST, PFAM lookup, etc.) to be performed from within Python scripts.
|
|
17
|
+
|
|
18
|
+
If you use this module for any published work, please consider citing the accompanying paper
|
|
19
|
+
|
|
20
|
+
Gilpin, W. "PyPDB: A Python API for the Protein Data Bank."
|
|
21
|
+
Bioinformatics, Oxford Journals, 2016.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Install using pip:
|
|
26
|
+
|
|
27
|
+
$ pip install pypdb
|
|
28
|
+
|
|
29
|
+
To install the development version, which contains the latest features and fixes, install directly from GitHub using
|
|
30
|
+
|
|
31
|
+
$ pip install git+https://github.com/williamgilpin/pypdb
|
|
32
|
+
|
|
33
|
+
If you need to install directly from setup.py,
|
|
34
|
+
|
|
35
|
+
$ python setup.py install
|
|
36
|
+
|
|
37
|
+
Test the installation, and check that the code successfully connects to the PDB, navigate to the root directory and run
|
|
38
|
+
|
|
39
|
+
$ pytest
|
|
40
|
+
|
|
41
|
+
This code has been designed and tested for Python 3.
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### PDB Text Search
|
|
46
|
+
This package can be used to get lists of PDB IDs associated with specific search terms, experiment types, structures, and other common criteria. To use the simple API, see the examples in [`demos/demos.ipynb`](demos/demos.ipynb). For advanced search and query logic, see the examples in [`search/EXAMPLES.md`](pypdb/clients/search/EXAMPLES.md).
|
|
47
|
+
|
|
48
|
+
### PDB Data Fetch
|
|
49
|
+
Given a list of PDBs, this package can be used to fetch data associated with those PDBs, including their dates of deposition, lists of authors and associated publications, their sequences or structures, their top BLAST matches, and other query-specific attributes like lists of a ligands or chemical structure. To use the simple API, see the examples in [`demos/demos.ipynb`](demos/demos.ipynb). For advanced search and query logic, see the examples in [`data/EXAMPLES.md`](pypdb/clients/data/EXAMPLES.md).
|
|
50
|
+
|
|
51
|
+
## Issues and Feature Requests
|
|
52
|
+
|
|
53
|
+
If you run into an issue, or if you find a workaround for an existing issue, we would very much appreciate it if you could post your question or code as a GitHub issue.
|
|
54
|
+
|
|
55
|
+
If posting a feature request, please check that your request is possible using [the current GUI on current RCSB website](https://www.rcsb.org/search/advanced). If so, please perform your search, and then click the link that says `JSON` in the upper right hand corner of the Advanced Search box. Please post that JSON code with your feature request.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
@@ -13,6 +13,11 @@ pypdb.egg-info/top_level.txt
|
|
|
13
13
|
pypdb.egg-info/.ipynb_checkpoints/dependency_links-checkpoint.txt
|
|
14
14
|
pypdb/clients/__init__.py
|
|
15
15
|
pypdb/clients/data/__init__.py
|
|
16
|
+
pypdb/clients/data/data_types.py
|
|
17
|
+
pypdb/clients/data/test_data_types.py
|
|
18
|
+
pypdb/clients/data/graphql/__init__.py
|
|
19
|
+
pypdb/clients/data/graphql/graphql.py
|
|
20
|
+
pypdb/clients/data/graphql/test_graphql.py
|
|
16
21
|
pypdb/clients/fasta/__init__.py
|
|
17
22
|
pypdb/clients/fasta/fasta_client.py
|
|
18
23
|
pypdb/clients/fasta/fasta_client_test.py
|
|
@@ -22,6 +27,7 @@ pypdb/clients/pdb/pdb_client_test.py
|
|
|
22
27
|
pypdb/clients/search/__init__.py
|
|
23
28
|
pypdb/clients/search/search_client.py
|
|
24
29
|
pypdb/clients/search/search_client_test.py
|
|
30
|
+
pypdb/clients/search/operators/__init__.py
|
|
25
31
|
pypdb/clients/search/operators/chemical_operators.py
|
|
26
32
|
pypdb/clients/search/operators/chemical_operators_test.py
|
|
27
33
|
pypdb/clients/search/operators/seqmotif_operators.py
|
|
@@ -34,4 +40,5 @@ pypdb/clients/search/operators/text_operators.py
|
|
|
34
40
|
pypdb/clients/search/operators/text_operators_test.py
|
|
35
41
|
pypdb/util/__init__.py
|
|
36
42
|
pypdb/util/http_requests.py
|
|
37
|
-
pypdb/util/test_http_requests.py
|
|
43
|
+
pypdb/util/test_http_requests.py
|
|
44
|
+
tests/test_pypdb.py
|
{pypdb-2.2 → pypdb-2.4}/setup.py
RENAMED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
from setuptools import setup
|
|
2
2
|
|
|
3
|
+
# read the contents of the README file so that PyPI can use it as the long description
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
this_directory = Path(__file__).parent
|
|
6
|
+
long_description = (this_directory / "README.md").read_text()
|
|
7
|
+
|
|
3
8
|
modules_list = [
|
|
4
9
|
"pypdb",
|
|
5
10
|
"pypdb.util",
|
|
@@ -7,6 +12,7 @@ modules_list = [
|
|
|
7
12
|
"pypdb.clients.search",
|
|
8
13
|
"pypdb.clients.search.operators",
|
|
9
14
|
"pypdb.clients.data",
|
|
15
|
+
"pypdb.clients.data.graphql",
|
|
10
16
|
"pypdb.clients.fasta",
|
|
11
17
|
"pypdb.clients.pdb",
|
|
12
18
|
]
|
|
@@ -15,7 +21,7 @@ setup(
|
|
|
15
21
|
name='pypdb',
|
|
16
22
|
packages=modules_list, # same as 'name'
|
|
17
23
|
py_modules=modules_list,
|
|
18
|
-
version='2.
|
|
24
|
+
version='2.04',
|
|
19
25
|
install_requires=['requests'],
|
|
20
26
|
description='A Python wrapper for the RCSB Protein Data Bank (PDB) API',
|
|
21
27
|
author='William Gilpin',
|
|
@@ -24,4 +30,6 @@ setup(
|
|
|
24
30
|
download_url='https://github.com/williamgilpin/pypdb/tarball/0.6',
|
|
25
31
|
keywords=['protein', 'data', 'RESTful', 'api'],
|
|
26
32
|
classifiers=[],
|
|
33
|
+
long_description=long_description,
|
|
34
|
+
long_description_content_type='text/markdown'
|
|
27
35
|
)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
## Import from local directory
|
|
4
|
+
import sys
|
|
5
|
+
sys.path.insert(0, '../pypdb')
|
|
6
|
+
from pypdb import *
|
|
7
|
+
|
|
8
|
+
# TODO(ejwilliams): Write generic logic, to execute `test_*.py` files
|
|
9
|
+
# within the pypdb directory (removing need for sys.path hack)
|
|
10
|
+
|
|
11
|
+
# aa_index[s] for s in seq_dict[k] if s in aa_index.keys()]
|
|
12
|
+
|
|
13
|
+
class TestSearchFunctions(unittest.TestCase):
|
|
14
|
+
|
|
15
|
+
def test_searchterm(self):
|
|
16
|
+
found_pdbs = Query('ribosome').search()
|
|
17
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
18
|
+
self.assertTrue(type(found_pdbs[0]) == str)
|
|
19
|
+
|
|
20
|
+
# an error page would be a longer string
|
|
21
|
+
self.assertTrue(len(found_pdbs[0]) < 10)
|
|
22
|
+
|
|
23
|
+
def test_pubmed(self):
|
|
24
|
+
found_pdbs = Query(27499440, "PubmedIdQuery").search()
|
|
25
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
26
|
+
|
|
27
|
+
def test_treeentity(self):
|
|
28
|
+
found_pdbs = Query('6239', 'TreeEntityQuery').search()
|
|
29
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
30
|
+
|
|
31
|
+
def test_exptype(self):
|
|
32
|
+
found_pdbs = Query('SOLID-STATE NMR', 'ExpTypeQuery').search()
|
|
33
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
34
|
+
|
|
35
|
+
def test_structure(self):
|
|
36
|
+
found_pdbs = Query('2E8D', 'structure').search()
|
|
37
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
38
|
+
|
|
39
|
+
def test_advancedauthor(self):
|
|
40
|
+
found_pdbs = Query('Perutz, M.F.', 'AdvancedAuthorQuery').search()
|
|
41
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
42
|
+
|
|
43
|
+
def test_organism(self):
|
|
44
|
+
found_pdbs = Query('Dictyostelium', 'OrganismQuery').search()
|
|
45
|
+
self.assertTrue(len(found_pdbs) > 0)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# def test_blast(self):
|
|
50
|
+
# found_pdbs = blast_from_sequence(
|
|
51
|
+
# 'MTKIANKYEVIDNVEKLEKALKRLREAQSVYATYTQEQVDKIFFEAAMAANKMRIPLAKMAVE'
|
|
52
|
+
# + 'ETGMGVVEDKVIKNHYASEYIYNAYKNTKTCGVIEEDPAFGIKKIAEPLGVIAAVIPTTNP'
|
|
53
|
+
# + 'TSTAIFKTLIALKTRNAIIISPHPRAKNSTIEAAKIVLEAAVKAGAPEGIIGWIDVPSLEL'
|
|
54
|
+
# + 'TNLVMREADVILATGGPGLVKAAYSSGKPAIGVGAGNTPAIIDDSADIVLAVNSIIHSKTF'
|
|
55
|
+
# + 'DNGMICASEQSVIVLDGVYKEVKKEFEKRGCYFLNEDETEKVRKTIIINGALNAKIVGQKA'
|
|
56
|
+
# + 'HTIANLAGFEVPETTKILIGEVTSVDISEEFAHEKLCPVLAMYRAKDFDDALDKAERLVAD'
|
|
57
|
+
# + 'GGFGHTSSLYIDTVTQKEKLQKFSERMKTCRILVNTPSSQGGIGDLYNFKLAPSL',
|
|
58
|
+
# 1e-20)
|
|
59
|
+
# self.assertTrue(len(found_pdbs) > 0)
|
|
60
|
+
# self.assertTrue(type(found_pdbs[0][0]) == str)
|
|
61
|
+
|
|
62
|
+
# # an error page would be a longer string
|
|
63
|
+
# self.assertTrue(len(found_pdbs[0][0]) < 10)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == '__main__':
|
|
67
|
+
unittest.main()
|
pypdb-2.2/PKG-INFO
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: pypdb
|
|
3
|
-
Version: 2.2
|
|
4
|
-
Summary: A Python wrapper for the RCSB Protein Data Bank (PDB) API
|
|
5
|
-
Home-page: https://github.com/williamgilpin/pypdb
|
|
6
|
-
Download-URL: https://github.com/williamgilpin/pypdb/tarball/0.6
|
|
7
|
-
Author: William Gilpin
|
|
8
|
-
Author-email: firstnamelastname@gmail.com
|
|
9
|
-
License: UNKNOWN
|
|
10
|
-
Keywords: protein,data,RESTful,api
|
|
11
|
-
Platform: UNKNOWN
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
|
|
14
|
-
UNKNOWN
|
|
15
|
-
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: pypdb
|
|
3
|
-
Version: 2.2
|
|
4
|
-
Summary: A Python wrapper for the RCSB Protein Data Bank (PDB) API
|
|
5
|
-
Home-page: https://github.com/williamgilpin/pypdb
|
|
6
|
-
Download-URL: https://github.com/williamgilpin/pypdb/tarball/0.6
|
|
7
|
-
Author: William Gilpin
|
|
8
|
-
Author-email: firstnamelastname@gmail.com
|
|
9
|
-
License: UNKNOWN
|
|
10
|
-
Keywords: protein,data,RESTful,api
|
|
11
|
-
Platform: UNKNOWN
|
|
12
|
-
License-File: LICENSE
|
|
13
|
-
|
|
14
|
-
UNKNOWN
|
|
15
|
-
|
{pypdb-2.2 → pypdb-2.4}/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|