pax_global_header00006660000000000000000000000064133006115230014504gustar00rootroot0000000000000052 comment=7fc851a692a4fc3916accf42866e870fb2120666 mmtf-python-1.1.2/000077500000000000000000000000001330061152300137675ustar00rootroot00000000000000mmtf-python-1.1.2/.gitignore000066400000000000000000000000311330061152300157510ustar00rootroot00000000000000docs/ .idea/ *.pyc *.pyo mmtf-python-1.1.2/.travis.yml000066400000000000000000000017521330061152300161050ustar00rootroot00000000000000os: - linux language: python python: - '2.7' - '3.3' - '3.4' - '3.5' install: - pip install -r requirements.txt script: nosetests deploy: provider: pypi user: abradle distributions: "sdist bdist_wheel" on: branch: master tags: true repo: rcsb/mmtf-python python: '3.5' password: secure: K770zHNs79Bg+EE+1DcMRoB4QZpTZdTrJRmu8o6dnVjQgz3ZaPFkPZnkQdfOAa9UUCfLaCREjCkMSvUOxO9u9ep7HkM7zMnk88DEiKgVgddzoNEUG/RB0oYf1+hyc3FLcb2FTCLMTV9vtqPp6kRBMmpGzcQnGVsEDJjv59ZW9w4fXBIopoLEBcmAN6LBy19r3Hq4uBJRiW17jvtkfBhRTXRcgT/bYO3UD1THveUnYUoJw/HD8LSLO+svhHRclY0AAOV09ZVI7IA2+HXhCvbWVOFtDOzY/0m2qwII8GmtzGgvn1/JFLIf3dnth6er+eZwYcdhTUAVIkApq5p2zcJhKLg79FK4NhllsqKu/cOwREyrxXNQn8SyfDREfkhRRuLQ7iLDHiXdFmJD6wfNlVVrFQJlv5lEFogUsxBind0M2JPi7PD4GvyYl6ZESGfuhZSBKnzfecll1/vZB1u6x4M7rApC6t8b/KN2yjfyxaL6n8oDJdzEo0/JvmiGYVUG5GvNVYrIWdrJWVN4mVJ/Y8s+69c+a0puDK3bVLTwH+hLoInKtZvxh5sh9EE80cXGUK23Su5jTRoNrH6nV+qXNMe1F+9GNELffzbI0/Nk+fYys+M9xidEJ/BJQgZjmPEIg0pZR+H8Bwik0bI/0EDSSCbKLcigkEyRUy1tg8TSpWf4nDw= mmtf-python-1.1.2/CHANGELOG.md000066400000000000000000000035221330061152300156020ustar00rootroot00000000000000# Change Log All notable changes to this project will be documented in this file, following the suggestions of [Keep a CHANGELOG](http://keepachangelog.com/). This project adheres to [Semantic Versioning](http://semver.org/). ## v1.1.2 - 2018-05-21 ### Changed - msgpack to new 0.5.6 ## v1.1.1 - 2018-04-27 ### Fixed - Imported BASE_URL_REDUCED to download reduced files ## v1.1.0 - 2018-04-04 ### Changed - Switch to msgpack-defaults for easier parsing #38 ### Removed - Mac testing from CI ## v1.0.11 - 2018-02-26 ### Added - Add option to get reduced files from API #36 ## v1.0.10 - 2018-03-01 ### Fixed - Don't leak open file handles #32 ## v1.0.8 - 2017-08-17 ### Fixed - Changing ascii to utf8 #29 ## v1.0.7 - 2017-06-28 ### Fixed - Resolve issue with get_coords ## v1.0.6 - 2017-06-02 ### Fixed - Resolve #22 #22 ## v1.0.5 - 2016-11-24 ### Added - Added files to manifest.in ### Changed - Classes to new style ## v1.0.4 - 2016-09-16 ### Added - Added pass_data_on and write_mmtf to the mmtf API - Added API functions to MMTFDecoder to get coordinates and bonds as a single list. get_coords and get_bonds ## v1.0.3 - 2016-09-16 ### Changed - Refactored MMTFDecoder to seperate file ### Added - API functions to write out MMTF files - Exposed TemplateEncoder, MMTFEncoder, write_mmtf and pass_data_on to API - Unit test of roundtripping data - Improved docs ## v1.0.2 - 2016-09-10 ### Changed - Bug fix for handling of null values ## v1.0.1 - 2016-08-19 ### Changed - Improved handling of missing values - Handle non-gzipped data from URL ## v1.0.0 - 2016-08-15 ### Changed - updated URL to new v1.0 data stores ## v0.2.2 - 2016-08-10 ### Changed - convert_ints_to_floats for old versions of numpy ## v0.2.1 - 2016-08-03 ### Added - API function (get_url) to get the URL of the data ## v0.2.0 - 2016-07-14 ### Added - Initial release of mmtf-python mmtf-python-1.1.2/LICENSE.txt000066400000000000000000000250021330061152300156110ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright 2016 RCSB PDB Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. mmtf-python-1.1.2/MANIFEST.in000066400000000000000000000002151330061152300155230ustar00rootroot00000000000000include README.md CHANGELOG.md LICENSE.txt include setup.py include mmtf/tests/testdatastore/4CUP.mmtf.gz mmtf/tests/testdatastore/4CUP.mmtf mmtf-python-1.1.2/README.md000066400000000000000000000031451330061152300152510ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/rcsb/mmtf-python.svg?branch=master)](https://travis-ci.org/rcsb/mmtf-python) [![Code Health](https://landscape.io/github/rcsb/mmtf-python/master/landscape.svg?style=flat)](https://landscape.io/github/rcsb/mmtf-python/master) [![Version](http://img.shields.io/badge/version-1.1.2-blue.svg?style=flat)](https://github.com/rcsb/mmtf-python/) [![License](http://img.shields.io/badge/license-Apache%202.0-blue.svg?style=flat)](https://github.com/rcsb/mmtf-python/blob/master/LICENSE.txt) [![Changelog](https://img.shields.io/badge/changelog--lightgrey.svg?style=flat)](https://github.com/rcsb/mmtf-python/blob/master/CHANGELOG.md) The **m**acro**m**olecular **t**ransmission **f**ormat (MMTF) is a binary encoding of biological structures. This repository holds the Python 2 and 3 compatible API, encoding and decoding libraries. The MMTF python API is available from pip: ``` pip install mmtf-python ``` Quick getting started. 1) Get the data for a PDB structure and print the number of chains: ```python from mmtf import fetch # Get the data for 4CUP decoded_data = fetch("4CUP") print("PDB Code: "+str(decoded_data.structure_id)+" has "+str(decoded_data.num_chains)+" chains") ``` 2) Show the charge information for the first group: ```python print("Group name: "+str(decoded_data.group_list[0]["groupName"])+" has the following atomic charges: "+",".join([str(x) for x in decoded_data.group_list[0]["formalChargeList"]])) ``` 3) Show how many bioassemblies it has: ```python print("PDB Code: "+str(decoded_data.structure_id)+" has "+str(len(decoded_data.bio_assembly))+" bioassemblies") ``` mmtf-python-1.1.2/README.rst000066400000000000000000000000001330061152300154440ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/000077500000000000000000000000001330061152300147325ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/__init__.py000066400000000000000000000001571330061152300170460ustar00rootroot00000000000000from .api import MMTFEncoder,TemplateEncoder,MMTFDecoder,parse,parse_gzip,fetch,get_url,pass_data_on,write_mmtfmmtf-python-1.1.2/mmtf/api/000077500000000000000000000000001330061152300155035ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/api/__init__.py000066400000000000000000000001671330061152300176200ustar00rootroot00000000000000from .default_api import parse,parse_gzip,fetch,MMTFDecoder,MMTFEncoder,TemplateEncoder,get_url,write_mmtf,pass_data_onmmtf-python-1.1.2/mmtf/api/default_api.py000066400000000000000000000070531330061152300203370ustar00rootroot00000000000000import gzip from mmtf.utils.constants import BASE_URL, BASE_URL_REDUCED try: import urllib2 from StringIO import StringIO except: import urllib.request as urllib2 from io import BytesIO as StringIO import msgpack from .mmtf_reader import MMTFDecoder from .mmtf_writer import MMTFEncoder,TemplateEncoder def _internet_on(address): """ Check to see if the internet is on by pinging a set address. :param address: the IP or address to hit :return: a boolean - true if can be reached, false if not. """ try: urllib2.urlopen(address, timeout=1) return True except urllib2.URLError as err: return False def write_mmtf(file_path, input_data, input_function): """API function to write data as MMTF to a file :param file_path the path of the file to write :param input_data the input data in any user format :param input_function a function to converte input_data to an output format. Must contain all methods in TemplateEncoder """ mmtf_encoder = MMTFEncoder() pass_data_on(input_data, input_function, mmtf_encoder) mmtf_encoder.write_file(file_path) def pass_data_on(input_data, input_function, output_data): """Helper to pass data from one data structure to another. :param input_data the input data in any user format :param input_function a function to converte input_data to an output format. Must contain all methods in TemplateEncoder. :param output_data a data holder for the data to be put into.""" input_function(input_data, output_data) return output_data def get_raw_data_from_url(pdb_id, reduced=False): """" Get the msgpack unpacked data given a PDB id. :param pdb_id: the input PDB id :return the unpacked data (a dict) """ url = get_url(pdb_id,reduced) request = urllib2.Request(url) request.add_header('Accept-encoding', 'gzip') response = urllib2.urlopen(request) if response.info().get('Content-Encoding') == 'gzip': data = ungzip_data(response.read()) else: data = response.read() return _unpack(data) def get_url(pdb_id,reduced=False): """Get the URL for the data for a given PDB id. :param pdb_id: the input PDB id :return the URL for this PDB id""" if reduced: return BASE_URL_REDUCED + pdb_id else: return BASE_URL + pdb_id def _unpack(data): out_data = msgpack.unpackb(data.read(), raw=False) return out_data def fetch(pdb_id): """Return a decoded API to the data from a PDB id. :param pdb_id: the input PDB id :return an API to decoded data """ decoder = MMTFDecoder() decoder.decode_data(get_raw_data_from_url(pdb_id)) return decoder def parse(file_path): """Return a decoded API to the data from a file path. :param file_path: the input file path. Data is not entropy compressed (e.g. gzip) :return an API to decoded data """ newDecoder = MMTFDecoder() with open(file_path, "rb") as fh: newDecoder.decode_data(_unpack(fh)) return newDecoder def parse_gzip(file_path): """Return a decoded API to the data from a file path. File is gzip compressed. :param file_path: the input file path. Data is gzip compressed. :return an API to decoded data""" newDecoder = MMTFDecoder() newDecoder.decode_data(_unpack(gzip.open(file_path, "rb"))) return newDecoder def ungzip_data(input_data): """Return a string of data after gzip decoding :param the input gziped data :return the gzip decoded data""" buf = StringIO(input_data) f = gzip.GzipFile(fileobj=buf) return f mmtf-python-1.1.2/mmtf/api/mmtf_reader.py000066400000000000000000000156231330061152300203510ustar00rootroot00000000000000from mmtf.codecs import decode_array from mmtf.utils import decoder_utils import sys class MMTFDecoder(object): """Class to decode raw mmtf data into a parsed data model that can be fed into other data model""" model_counter = 0 chain_counter = 0 group_counter = 0 atom_counter = 0 def get_coords(self): """Utility function to get the coordinates as a single list of tuples.""" out_list = [] for i in range(len(self.x_coord_list)): out_list.append((self.x_coord_list[i],self.y_coord_list[i],self.z_coord_list[i],)) return out_list def get_bonds(self): """Utility function to get all the inter group bonds for the structure in pairs.""" return decoder_utils.get_bonds(self) def decode_data(self, input_data): """Function to decode the input data and place it onto the class. :param input_data: the input data as a dict""" self.group_type_list = decode_array(input_data["groupTypeList"]) self.x_coord_list = decode_array(input_data["xCoordList"]) self.y_coord_list = decode_array(input_data["yCoordList"]) self.z_coord_list = decode_array(input_data["zCoordList"]) if "bFactorList" in input_data: self.b_factor_list = decode_array(input_data["bFactorList"]) else: self.b_factor_list = [] if "occupancyList" in input_data: self.occupancy_list = decode_array(input_data["occupancyList"]) else: self.occupancy_list = [] if "atomIdList" in input_data: self.atom_id_list = decode_array(input_data["atomIdList"]) else: self.atom_id_list = [] if "altLocList" in input_data: self.alt_loc_list = decode_array(input_data["altLocList"]) else: self.alt_loc_list = [] if "insCodeList" in input_data: self.ins_code_list = decode_array(input_data["insCodeList"]) else: self.ins_code_list = [] self.group_id_list = decode_array(input_data["groupIdList"]) self.group_list = input_data["groupList"] if "sequenceIndexList" in input_data: self.sequence_index_list = decode_array(input_data["sequenceIndexList"]) else: self.sequence_index_list = [] self.chains_per_model = input_data["chainsPerModel"] self.groups_per_chain = input_data["groupsPerChain"] if "chainNameList" in input_data: self.chain_name_list = decode_array(input_data["chainNameList"]) else: self.chain_name_list = [] self.chain_id_list = decode_array(input_data["chainIdList"]) if "spaceGroup" in input_data: self.space_group = input_data["spaceGroup"] else: self.space_group = None if "bondAtomList" in input_data: self.bond_atom_list = decode_array(input_data["bondAtomList"]) else: self.bond_atom_list = None if "bondOrderList" in input_data: self.bond_order_list = decode_array(input_data["bondOrderList"]) else: self.bond_order_list = None if sys.version_info[0] < 3: if "mmtfVersion" in input_data: self.mmtf_version = input_data["mmtfVersion"] else: self.mmtf_version = None if "mmtfProducer" in input_data: self.mmtf_producer = input_data["mmtfProducer"] else: self.mmtf_producer = None if "structureId" in input_data: self.structure_id = input_data["structureId"] else: self.structure_id = None else: if "mmtfVersion" in input_data: self.mmtf_version = input_data["mmtfVersion"] else: self.mmtf_version = None if "mmtfProducer" in input_data: self.mmtf_producer = input_data["mmtfProducer"] else: self.mmtf_producer = None if "structureId" in input_data: self.structure_id = input_data["structureId"] else: self.structure_id = None if "title" in input_data: if sys.version_info[0] < 3: self.title = input_data["title"] else: self.title = input_data["title"] if "experimentalMethods" in input_data: self.experimental_methods = input_data["experimentalMethods"] else: self.experimental_methods = None if "depositionDate" in input_data: self.deposition_date = input_data["depositionDate"] else: self.deposition_date = None if "releaseDate" in input_data: self.release_date = input_data["releaseDate"] else: self.release_date = None if "entityList" in input_data: self.entity_list = input_data["entityList"] else: self.entity_list = [] if "bioAssemblyList" in input_data: self.bio_assembly = input_data["bioAssemblyList"] else: self.bio_assembly = [] if "rFree" in input_data: self.r_free = input_data["rFree"] else: self.r_free = None if "rWork" in input_data: self.r_work = input_data["rWork"] else: self.r_work = None if "resolution" in input_data: self.resolution = input_data["resolution"] else: self.resolution = None if "unitCell" in input_data: self.unit_cell = input_data["unitCell"] else: self.unit_cell = None if "secStructList" in input_data: self.sec_struct_list = decode_array(input_data["secStructList"]) # Now all the numbers to defien the self.num_bonds = int(input_data["numBonds"]) self.num_chains = int(input_data["numChains"]) self.num_models = int(input_data["numModels"]) self.num_atoms = int(input_data["numAtoms"]) self.num_groups = int(input_data["numGroups"]) def pass_data_on(self, data_setters): """Write the data from the getters to the setters. :param data_setters: a series of functions that can fill a chemical data structure :type data_setters: DataTransferInterface """ data_setters.init_structure(self.num_bonds, len(self.x_coord_list), len(self.group_type_list), len(self.chain_id_list), len(self.chains_per_model), self.structure_id) decoder_utils.add_entity_info(self, data_setters) decoder_utils.add_atomic_information(self, data_setters) decoder_utils.add_header_info(self, data_setters) decoder_utils.add_xtalographic_info(self, data_setters) decoder_utils.generate_bio_assembly(self, data_setters) decoder_utils.add_inter_group_bonds(self, data_setters) data_setters.finalize_structure() mmtf-python-1.1.2/mmtf/api/mmtf_writer.py000066400000000000000000000520151330061152300204170ustar00rootroot00000000000000from mmtf.codecs import encode_array import msgpack from mmtf.utils import constants def make_entity_dict(chain_indices,sequence,description,entity_type): out_d = {} out_d["description"] = description out_d["type"] = entity_type out_d["chainIndexList"] = chain_indices out_d["sequence"] = sequence return out_d class Group(object): def __eq__(self, other): """Function to define equality""" if self.atom_name_list != other.atom_name_list: return False if self.charge_list != other.charge_list: return False if self.element_list != other.element_list: return False if self.group_type != other.group_type: return False if self.group_name != other.group_name: return False if self.single_letter_code != other.single_letter_code: return False if self.bond_atom_list != other.bond_atom_list: return False if self.bond_order_list != other.bond_order_list: return False return True def __init__(self): self.atom_name_list = [] self.bond_order_list = [] self.bond_atom_list = [] self.charge_list = [] self.element_list = [] self.group_name = constants.UNKOWN_GROUP_NAME self.group_type = constants.UNKOWN_GROUP_TYPE self.single_letter_code = constants.UNKNOWN_SL def convert_to_dict(self): """Convert the group object to an appropriate DICT""" out_dict = {} out_dict["groupName"] = self.group_name out_dict["atomNameList"] = self.atom_name_list out_dict["elementList"] = self.element_list out_dict["bondOrderList"] = self.bond_order_list out_dict["bondAtomList"] = self.bond_atom_list out_dict["formalChargeList"] = self.charge_list out_dict["singleLetterCode"] = self.single_letter_code out_dict["chemCompType"] = self.group_type return out_dict def get_unique_groups(input_list): """Function to get a unique list of groups.""" out_list = [] for item in input_list: if item not in out_list: out_list.append(item) return out_list class TemplateEncoder(object): """Template class to be used by third parties to pass data into other data structures.""" def init_structure(self, total_num_bonds, total_num_atoms, total_num_groups, total_num_chains, total_num_models, structure_id): """Initialise the structure object. :param total_num_bonds: the number of bonds in the structure :param total_num_atoms: the number of atoms in the structure :param total_num_groups: the number of groups in the structure :param total_num_chains: the number of chains in the structure :param total_num_models: the number of models in the structure :param structure_id the: id of the structure (e.g. PDB id) """ raise NotImplementedError def set_atom_info(self, atom_name, serial_number, alternative_location_id, x, y, z, occupancy, temperature_factor, element, charge): """Create an atom object an set the information. :param atom_name: the atom name, e.g. CA for this atom :param serial_number: the serial id of the atom (e.g. 1) :param alternative_location_id: the alternative location id for the atom, if present :param x: the x coordiante of the atom :param y: the y coordinate of the atom :param z: the z coordinate of the atom :param occupancy: the occupancy of the atom :param temperature_factor: the temperature factor of the atom :param element: the element of the atom, e.g. C for carbon. According to IUPAC. Calcium is Ca :param charge: the formal atomic charge of the atom """ raise NotImplementedError def set_chain_info(self, chain_id, chain_name, num_groups): """Set the chain information. :param chain_id: the asym chain id from mmCIF :param chain_name: the auth chain id from mmCIF :param num_groups: the number of groups this chain has """ raise NotImplementedError def set_entity_info(self, chain_indices, sequence, description, entity_type): """Set the entity level information for the structure. :param chain_indices: the indices of the chains for this entity :param sequence: the one letter code sequence for this entity :param description: the description for this entity :param entity_type: the entity type (polymer,non-polymer,water) """ raise NotImplementedError def set_group_info(self, group_name, group_number, insertion_code, group_type, atom_count, bond_count, single_letter_code, sequence_index, secondary_structure_type): """Set the information for a group :param group_name: the name of this group,e.g. LYS :param group_number: the residue number of this group :param insertion_code: the insertion code for this group :param group_type: a string indicating the type of group (as found in the chemcomp dictionary. Empty string if none available. :param atom_count: the number of atoms in the group :param bond_count: the number of unique bonds in the group :param single_letter_code: the single letter code of the group :param sequence_index: the index of this group in the sequence defined by the enttiy :param secondary_structure_type: the type of secondary structure used (types are according to DSSP and number to type mappings are defined in the specification) """ raise NotImplementedError def set_model_info(self, model_id, chain_count): # FIXME model_id here is meaningles and potentially misleading. """Set the information for a model. :param model_id: the index for the model :param chain_count: the number of chains in the model """ raise NotImplementedError def set_xtal_info(self, space_group, unit_cell): """Set the crystallographic information for the structure :param space_group: the space group name, e.g. "P 21 21 21" :param unit_cell: an array of length 6 with the unit cell parameters in order: a, b, c, alpha, beta, gamma """ raise NotImplementedError def set_header_info(self, r_free, r_work, resolution, title, deposition_date, release_date, experimental_methods): """Sets the header information. :param r_free: the measured R-Free for the structure :param r_work: the measure R-Work for the structure :param resolution: the resolution of the structure :param title: the title of the structure :param deposition_date: the deposition date of the structure :param release_date: the release date of the structure :param experimnetal_methods: the list of experimental methods in the structure """ raise NotImplementedError def set_bio_assembly_trans(self, bio_assembly_index, input_chain_indices, input_transform): """Set the Bioassembly transformation information. A single bioassembly can have multiple transforms, :param bio_assembly_index: the integer index of the bioassembly :param input_chain_indices: the list of integer indices for the chains of this bioassembly :param input_transformation: the list of doubles for the transform of this bioassmbly transform""" raise NotImplementedError def finalize_structure(self): """Any functions needed to cleanup the structure.""" raise NotImplementedError def set_group_bond(self, atom_index_one, atom_index_two, bond_order): """Add bonds within a group. :param atom_index_one: the integer atom index (in the group) of the first partner in the bond :param atom_index_two: the integer atom index (in the group) of the second partner in the bond :param bond_order: the integer bond order """ raise NotImplementedError def set_inter_group_bond(self, atom_index_one, atom_index_two, bond_order): """Add bonds between groups. :param atom_index_one: the integer atom index (in the structure) of the first partner in the bond :param atom_index_two: the integer atom index (in the structure) of the second partner in the bond :param bond_order the bond order """ raise NotImplementedError class MMTFEncoder(TemplateEncoder): def encode_data(self): """Encode the data back into a dict.""" output_data = {} output_data["groupTypeList"] = encode_array(self.group_type_list, 4, 0) output_data["xCoordList"] = encode_array(self.x_coord_list, 10, 1000) output_data["yCoordList"] = encode_array(self.y_coord_list, 10, 1000) output_data["zCoordList"] = encode_array(self.z_coord_list, 10, 1000) output_data["bFactorList"] = encode_array(self.b_factor_list, 10, 100) output_data["occupancyList"] = encode_array(self.occupancy_list, 9, 100) output_data["atomIdList"] = encode_array(self.atom_id_list, 8, 0) output_data["altLocList"] = encode_array(self.alt_loc_list, 6, 0) output_data["insCodeList"] = encode_array(self.ins_code_list, 6, 0) output_data["groupIdList"] = encode_array(self.group_id_list, 8, 0) output_data["groupList"] = self.group_list output_data["sequenceIndexList"] = encode_array(self.sequence_index_list, 8, 0) output_data["chainNameList"] = encode_array(self.chain_name_list, 5, 4) output_data["chainIdList"] = encode_array(self.chain_id_list, 5, 4) output_data["bondAtomList"] = encode_array(self.bond_atom_list, 4, 0) output_data["bondOrderList"] = encode_array(self.bond_order_list, 2, 0) output_data["secStructList"] = encode_array(self.sec_struct_list, 2, 0) output_data["chainsPerModel"] = self.chains_per_model output_data["groupsPerChain"] = self.groups_per_chain output_data["spaceGroup"] = self.space_group output_data["mmtfVersion"] = self.mmtf_version output_data["mmtfProducer"] = self.mmtf_producer output_data["structureId"] = self.structure_id output_data["entityList"] = self.entity_list output_data["bioAssemblyList"] = self.bio_assembly output_data["rFree"] = self.r_free output_data["rWork"] = self.r_work output_data["resolution"] = self.resolution output_data["title"] = self.title output_data["experimentalMethods"] = self.experimental_methods output_data["depositionDate"] = self.deposition_date output_data["releaseDate"] = self.release_date output_data["unitCell"] = self.unit_cell output_data["numBonds"] = self.num_bonds output_data["numChains"] = self.num_chains output_data["numModels"] = self.num_models output_data["numAtoms"] = self.num_atoms output_data["numGroups"] = self.num_groups return output_data def get_msgpack(self): """Get the msgpack of the encoded data.""" return msgpack.packb(self.encode_data(), use_bin_type=True) def write_file(self, file_path): with open(file_path, "wb") as out_f: out_f.write(self.get_msgpack()) def init_structure(self, total_num_bonds, total_num_atoms, total_num_groups, total_num_chains, total_num_models, structure_id): """Initialise the structure object. :param total_num_bonds: the number of bonds in the structure :param total_num_atoms: the number of atoms in the structure :param total_num_groups: the number of groups in the structure :param total_num_chains: the number of chains in the structure :param total_num_models: the number of models in the structure :param structure_id the: id of the structure (e.g. PDB id) """ self.mmtf_version = constants.MMTF_VERSION self.mmtf_producer = constants.PRODUCER self.num_atoms = total_num_atoms self.num_bonds = total_num_bonds self.num_groups = total_num_groups self.num_chains = total_num_chains self.num_models = total_num_models self.structure_id = structure_id # initialise the arrays self.x_coord_list = [] self.y_coord_list = [] self.z_coord_list = [] self.group_type_list = [] self.entity_list = [] self.b_factor_list = [] self.occupancy_list = [] self.atom_id_list = [] self.alt_loc_list = [] self.ins_code_list = [] self.group_id_list = [] self.sequence_index_list = [] self.group_list = [] self.chain_name_list = [] self.chain_id_list = [] self.bond_atom_list = [] self.bond_order_list = [] self.sec_struct_list = [] self.chains_per_model = [] self.groups_per_chain = [] self.current_group = None self.bio_assembly = [] def set_atom_info(self, atom_name, serial_number, alternative_location_id, x, y, z, occupancy, temperature_factor, element, charge): """Create an atom object an set the information. :param atom_name: the atom name, e.g. CA for this atom :param serial_number: the serial id of the atom (e.g. 1) :param alternative_location_id: the alternative location id for the atom, if present :param x: the x coordiante of the atom :param y: the y coordinate of the atom :param z: the z coordinate of the atom :param occupancy: the occupancy of the atom :param temperature_factor: the temperature factor of the atom :param element: the element of the atom, e.g. C for carbon. According to IUPAC. Calcium is Ca :param charge: the formal atomic charge of the atom """ self.x_coord_list.append(x) self.y_coord_list.append(y) self.z_coord_list.append(z) self.atom_id_list.append(serial_number) self.alt_loc_list.append(alternative_location_id) self.occupancy_list.append(occupancy) self.b_factor_list.append(temperature_factor) ## Now add the group level data self.current_group.atom_name_list.append(atom_name) self.current_group.charge_list.append(charge) self.current_group.element_list.append(element) def set_chain_info(self, chain_id, chain_name, num_groups): """Set the chain information. :param chain_id: the asym chain id from mmCIF :param chain_name: the auth chain id from mmCIF :param num_groups: the number of groups this chain has """ self.chain_id_list.append(chain_id) self.chain_name_list.append(chain_name) self.groups_per_chain.append(num_groups) def set_entity_info(self, chain_indices, sequence, description, entity_type): """Set the entity level information for the structure. :param chain_indices: the indices of the chains for this entity :param sequence: the one letter code sequence for this entity :param description: the description for this entity :param entity_type: the entity type (polymer,non-polymer,water) """ self.entity_list.append(make_entity_dict(chain_indices,sequence,description,entity_type)) def set_group_info(self, group_name, group_number, insertion_code, group_type, atom_count, bond_count, single_letter_code, sequence_index, secondary_structure_type): """Set the information for a group :param group_name: the name of this group,e.g. LYS :param group_number: the residue number of this group :param insertion_code: the insertion code for this group :param group_type: a string indicating the type of group (as found in the chemcomp dictionary. Empty string if none available. :param atom_count: the number of atoms in the group :param bond_count: the number of unique bonds in the group :param single_letter_code: the single letter code of the group :param sequence_index: the index of this group in the sequence defined by the enttiy :param secondary_structure_type: the type of secondary structure used (types are according to DSSP and number to type mappings are defined in the specification) """ # Add the group to the overall list - unless it's the first time round if self.current_group is not None: self.group_list.append(self.current_group) # Add the group level information self.group_id_list.append(group_number) self.ins_code_list.append(insertion_code) self.sequence_index_list.append(sequence_index) self.sec_struct_list.append(secondary_structure_type) self.current_group = Group() self.current_group.group_name = group_name self.current_group.group_type = group_type self.current_group.single_letter_code = single_letter_code def set_model_info(self, model_id, chain_count): # FIXME model_id here is meaningles and potentially misleading. """Set the information for a model. :param model_id: the index for the model :param chain_count: the number of chains in the model """ self.chains_per_model.append(chain_count) def set_xtal_info(self, space_group, unit_cell): """Set the crystallographic information for the structure :param space_group: the space group name, e.g. "P 21 21 21" :param unit_cell: an array of length 6 with the unit cell parameters in order: a, b, c, alpha, beta, gamma """ self.space_group = space_group self.unit_cell = unit_cell def set_header_info(self, r_free, r_work, resolution, title, deposition_date, release_date, experimental_methods): """Sets the header information. :param r_free: the measured R-Free for the structure :param r_work: the measure R-Work for the structure :param resolution: the resolution of the structure :param title: the title of the structure :param deposition_date: the deposition date of the structure :param release_date: the release date of the structure :param experimnetal_methods: the list of experimental methods in the structure """ self.r_free = r_free self.r_work = r_work self.resolution = resolution self.title = title self.deposition_date = deposition_date self.release_date = release_date self.experimental_methods = experimental_methods def set_bio_assembly_trans(self, bio_assembly_index, input_chain_indices, input_transform): """Set the Bioassembly transformation information. A single bioassembly can have multiple transforms, :param bio_assembly_index: the integer index of the bioassembly :param input_chain_indices: the list of integer indices for the chains of this bioassembly :param input_transformation: the list of doubles for the transform of this bioassmbly transform""" this_bioass = None for bioass in self.bio_assembly: if bioass['name'] == str(bio_assembly_index): this_bioass = bioass break if not this_bioass: this_bioass = {"name": str(bio_assembly_index), 'transformList': []} else: self.bio_assembly.remove(this_bioass) this_bioass['transformList'].append({'chainIndexList':input_chain_indices,'matrix': input_transform}) self.bio_assembly.append(this_bioass) def finalize_structure(self): """Any functions needed to cleanup the structure.""" self.group_list.append(self.current_group) group_set = get_unique_groups(self.group_list) for item in self.group_list: self.group_type_list.append(group_set.index(item)) self.group_list = [x.convert_to_dict() for x in group_set] def set_group_bond(self, atom_index_one, atom_index_two, bond_order): """Add bonds within a group. :param atom_index_one: the integer atom index (in the group) of the first partner in the bond :param atom_index_two: the integer atom index (in the group) of the second partner in the bond :param bond_order: the integer bond order """ self.current_group.bond_atom_list.append(atom_index_one) self.current_group.bond_atom_list.append(atom_index_two) self.current_group.bond_order_list.append(bond_order) def set_inter_group_bond(self, atom_index_one, atom_index_two, bond_order): """Add bonds between groups. :param atom_index_one: the integer atom index (in the structure) of the first partner in the bond :param atom_index_two: the integer atom index (in the structure) of the second partner in the bond :param bond_order the bond order """ self.bond_atom_list.append(atom_index_one) self.bond_atom_list.append(atom_index_two) self.bond_order_list.append(bond_order) mmtf-python-1.1.2/mmtf/codecs/000077500000000000000000000000001330061152300161725ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/codecs/__init__.py000066400000000000000000000000641330061152300203030ustar00rootroot00000000000000from .default_codec import decode_array,encode_arraymmtf-python-1.1.2/mmtf/codecs/codecs.py000066400000000000000000000065771330061152300200230ustar00rootroot00000000000000from mmtf import converters from .decoders import delta_decode,run_length_decode from .encoders import delta_encode,run_length_encode class DeltaRecursiveFloat(): """Covert an array of floats to integers, perform delta encoding and then use recursive indexing to store as 2 byte integers in a byte array.""" @staticmethod def decode(in_array, param): return converters.convert_ints_to_floats( delta_decode( converters.recursive_index_decode( converters.convert_bytes_to_ints(in_array,2))),param) @staticmethod def encode(in_array, param): return converters.convert_ints_to_bytes( converters.recursive_index_encode( delta_encode( converters.convert_floats_to_ints(in_array,param))),2) class RunLengthFloat(): """Covert an array of floats to integers, perform run-length encoding and then store as four byte integers in a byte array.""" @staticmethod def decode(in_array, param): return converters.convert_ints_to_floats( run_length_decode( converters.convert_bytes_to_ints(in_array,4)),param) @staticmethod def encode(in_array,param): return converters.convert_ints_to_bytes( run_length_encode( converters.convert_floats_to_ints(in_array,param)),4) class RunLengthDeltaInt(): """Delta encode an array of integers and then perform run-length encoding on this and then store as four byte integers in a byte array.""" @staticmethod def decode(in_array, param): return delta_decode( run_length_decode( converters.convert_bytes_to_ints(in_array, 4))) @staticmethod def encode(in_array,param): return converters.convert_ints_to_bytes( run_length_encode( delta_encode(in_array)),4) class RunLengthChar(): """Convert chars to integers and run-length encoode these and then store as four byte integers in a byte array.""" @staticmethod def decode(in_array, param): return converters.convert_ints_to_chars( run_length_decode( converters.convert_bytes_to_ints(in_array, 4))) @staticmethod def encode(in_array, param): return converters.convert_ints_to_bytes( run_length_encode( converters.convert_chars_to_ints(in_array)),4) class EncodeString(): """Convert strings to set length byte arrays (in this case four). If a string is of lenght less than four a null byte is used instead.""" @staticmethod def decode(in_array,param): return converters.decode_chain_list(in_array) @staticmethod def encode(in_array,param): return converters.encode_chain_list(in_array) class ByteToInt(): """Convert integers to single bytes and store in byte array.""" @staticmethod def decode(in_array,param): return converters.convert_bytes_to_ints(in_array, 1) @staticmethod def encode(in_array,param): return converters.convert_ints_to_bytes(in_array,1) class FourByteToInt(): """Convert integers to four bytes and store in byte array.""" @staticmethod def decode(in_array,param): return converters.convert_bytes_to_ints(in_array, 4) @staticmethod def encode(in_array, param): return converters.convert_ints_to_bytes(in_array, 4) mmtf-python-1.1.2/mmtf/codecs/decoders/000077500000000000000000000000001330061152300177625ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/codecs/decoders/__init__.py000066400000000000000000000002421330061152300220710ustar00rootroot00000000000000try: import numpy from .numpy_decoders import delta_decode,run_length_decode except ImportError: from .decoders import run_length_decode,delta_decodemmtf-python-1.1.2/mmtf/codecs/decoders/decoders.py000066400000000000000000000014431330061152300221260ustar00rootroot00000000000000def run_length_decode(in_array): """A function to run length decode an int array. :param in_array: the input array of integers :return the decoded array""" switch=False out_array=[] for item in in_array: if switch==False: this_item = item switch=True else: switch=False out_array.extend([this_item]*int(item)) return out_array def delta_decode(in_array): """A function to delta decode an int array. :param in_array: the input array of integers :return the decoded array""" if len(in_array) == 0: return [] this_ans = in_array[0] out_array = [this_ans] for i in range(1, len(in_array)): this_ans += in_array[i] out_array.append(this_ans) return out_arraymmtf-python-1.1.2/mmtf/codecs/decoders/numpy_decoders.py000066400000000000000000000012621330061152300233550ustar00rootroot00000000000000import numpy def delta_decode(in_array): """A function to delta decode an int array. :param in_array: the input array of integers :return the decoded array""" return in_array.cumsum() def run_length_decode(in_array): """A function to run length decode an int array. :param in_array: the input array of integers :return the decoded array""" switch=False out_array=[] in_array = in_array.tolist() for item in in_array: if switch==False: this_item = item switch=True else: switch=False out_array.extend([this_item]*int(item)) return numpy.asarray(out_array, dtype=numpy.int32)mmtf-python-1.1.2/mmtf/codecs/default_codec.py000066400000000000000000000023231330061152300213250ustar00rootroot00000000000000from mmtf.utils.codec_utils import parse_header,add_header from .codecs import DeltaRecursiveFloat,RunLengthFloat,RunLengthDeltaInt,RunLengthChar,EncodeString,ByteToInt,FourByteToInt codec_dict = {10: DeltaRecursiveFloat, 9: RunLengthFloat, 8: RunLengthDeltaInt, 6: RunLengthChar, 5: EncodeString, 2: ByteToInt, 4: FourByteToInt} def decode_array(input_array): """Parse the header of an input byte array and then decode using the input array, the codec and the appropirate parameter. :param input_array: the array to be decoded :return the decoded array""" codec, length, param, input_array = parse_header(input_array) return codec_dict[codec].decode(input_array, param) def encode_array(input_array, codec, param): """Encode the array using the method and then add the header to this array. :param input_array: the array to be encoded :param codec: the integer index of the codec to use :param param: the integer parameter to use in the function :return an array with the header added to the fornt""" return add_header(codec_dict[codec].encode(input_array, param), codec, len(input_array), param)mmtf-python-1.1.2/mmtf/codecs/encoders/000077500000000000000000000000001330061152300177745ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/codecs/encoders/__init__.py000066400000000000000000000000641330061152300221050ustar00rootroot00000000000000from .encoders import run_length_encode,delta_encodemmtf-python-1.1.2/mmtf/codecs/encoders/encoders.py000066400000000000000000000017411330061152300221530ustar00rootroot00000000000000def run_length_encode(in_array): """A function to run length decode an int array. :param in_array: the inptut array of integers :return the encoded integer array""" if(len(in_array)==0): return [] curr_ans = in_array[0] out_array = [curr_ans] counter = 1 for in_int in in_array[1:]: if in_int == curr_ans: counter+=1 else: out_array.append(counter) out_array.append(in_int) curr_ans = in_int counter = 1 # Add the final counter out_array.append(counter) return out_array def delta_encode(in_array): """A function to delta decode an int array. :param in_array: the inut array to be delta encoded :return the encoded integer array""" if(len(in_array)==0): return [] curr_ans = in_array[0] out_array = [curr_ans] for in_int in in_array[1:]: out_array.append(in_int-curr_ans) curr_ans = in_int return out_arraymmtf-python-1.1.2/mmtf/converters/000077500000000000000000000000001330061152300171245ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/converters/__init__.py000066400000000000000000000010661330061152300212400ustar00rootroot00000000000000try: import numpy from .numpy_converters import recursive_index_decode, convert_bytes_to_ints, convert_ints_to_floats, decode_chain_list from .converters import encode_chain_list,convert_chars_to_ints,recursive_index_encode,convert_floats_to_ints,convert_ints_to_bytes,convert_ints_to_chars except ImportError: from .converters import convert_bytes_to_ints,convert_ints_to_floats,decode_chain_list,recursive_index_decode,encode_chain_list,convert_chars_to_ints,recursive_index_encode,convert_floats_to_ints,convert_ints_to_bytes,convert_ints_to_charsmmtf-python-1.1.2/mmtf/converters/converters.py000066400000000000000000000105171330061152300216740ustar00rootroot00000000000000from __future__ import division import struct import mmtf import math import mmtf.utils.constants def convert_bytes_to_ints(in_bytes, num): """Convert a byte array into an integer array. The number of bytes forming an integer is defined by num :param in_bytes: the input bytes :param num: the number of bytes per int :return the integer array""" out_arr = [] for i in range(len(in_bytes)//num): val = in_bytes[i * num:i * num + num] unpacked = struct.unpack(mmtf.utils.constants.NUM_DICT[num], val) out_arr.append(unpacked[0]) return out_arr def convert_ints_to_bytes(in_ints, num): """Convert an integer array into a byte arrays. The number of bytes forming an integer is defined by num :param in_ints: the input integers :param num: the number of bytes per int :return the integer array""" out_bytes= b"" for val in in_ints: out_bytes+=struct.pack(mmtf.utils.constants.NUM_DICT[num], val) return out_bytes def decode_chain_list(in_bytes): """Convert a list of bytes to a list of strings. Each string is of length mmtf.CHAIN_LEN :param in_bytes: the input bytes :return the decoded list of strings""" tot_strings = len(in_bytes) // mmtf.utils.constants.CHAIN_LEN out_strings = [] for i in range(tot_strings): out_s = in_bytes[i * mmtf.utils.constants.CHAIN_LEN:i * mmtf.utils.constants.CHAIN_LEN + mmtf.utils.constants.CHAIN_LEN] out_strings.append(out_s.decode("ascii").strip(mmtf.utils.constants.NULL_BYTE)) return out_strings def encode_chain_list(in_strings): """Convert a list of strings to a list of byte arrays. :param in_strings: the input strings :return the encoded list of byte arrays""" out_bytes = b"" for in_s in in_strings: out_bytes+=in_s.encode('ascii') for i in range(mmtf.utils.constants.CHAIN_LEN -len(in_s)): out_bytes+= mmtf.utils.constants.NULL_BYTE.encode('ascii') return out_bytes def convert_ints_to_floats(in_ints, divider): """Convert integers to floats by division. :param in_ints: the integer array :param divider: the divider :return the array of floats produced""" return [x/divider for x in in_ints] def convert_ints_to_chars(in_ints): """Convert integers to chars. :param in_ints: input integers :return the character array converted""" return [chr(x) for x in in_ints] def convert_floats_to_ints(in_floats, multiplier): """Convert floating points to integers using a multiplier. :param in_floats: the input floats :param multiplier: the multiplier to be used for conversion. Corresponds to the precisison. :return the array of integers encoded""" return [int(round(x * multiplier)) for x in in_floats] def convert_chars_to_ints(in_chars): """Convert an array of chars to an array of ints. :param in_chars: the input characters :return the array of integers""" return [ord(x) for x in in_chars] def recursive_index_encode(int_array, max=32767, min=-32768): """Pack an integer array using recursive indexing. :param int_array: the input array of integers :param max: the maximum integer size :param min: the minimum integer size :return the array of integers after recursive index encoding""" out_arr = [] for curr in int_array: if curr >= 0 : while curr >= max: out_arr.append(max) curr -= max else: while curr <= min: out_arr.append(min) curr += int(math.fabs(min)) out_arr.append(curr) return out_arr def recursive_index_decode(int_array, max=32767, min=-32768): """Unpack an array of integers using recursive indexing. :param int_array: the input array of integers :param max: the maximum integer size :param min: the minimum integer size :return the array of integers after recursive index decoding""" out_arr = [] encoded_ind = 0 while encoded_ind < len(int_array): decoded_val = 0 while int_array[encoded_ind]==max or int_array[encoded_ind]==min: decoded_val += int_array[encoded_ind] encoded_ind+=1 if int_array[encoded_ind]==0: break decoded_val += int_array[encoded_ind] encoded_ind+=1 out_arr.append(decoded_val) return out_arrmmtf-python-1.1.2/mmtf/converters/numpy_converters.py000066400000000000000000000032721330061152300231240ustar00rootroot00000000000000from __future__ import division import numpy import mmtf import mmtf.utils.constants def convert_bytes_to_ints(in_bytes, num): """Convert a byte array into an integer array. The number of bytes forming an integer is defined by num :param in_bytes: the input bytes :param num: the number of bytes per int :return the integer array""" dt = numpy.dtype('>i' + str(num)) return numpy.frombuffer(in_bytes, dt) def decode_chain_list(in_bytes): """Convert a list of bytes to a list of strings. Each string is of length mmtf.CHAIN_LEN :param in_bytes: the input bytes :return the decoded list of strings""" bstrings = numpy.frombuffer(in_bytes, numpy.dtype('S' + str(mmtf.utils.constants.CHAIN_LEN))) return [s.decode("ascii").strip(mmtf.utils.constants.NULL_BYTE) for s in bstrings] def convert_ints_to_floats(in_ints, divider): """Convert integers to floats by division. :param in_ints: the integer array :param divider: the divider :return the array of floats produced""" return (in_ints.astype(numpy.float64) / divider) def recursive_index_decode(int_array, max=32767, min=-32768): """Unpack an array of integers using recursive indexing. :param int_array: the input array of integers :param max: the maximum integer size :param min: the minimum integer size :return the array of integers after recursive index decoding""" out_arr = [] decoded_val = 0 for item in int_array.tolist(): if item==max or item==min: decoded_val += item else: decoded_val += item out_arr.append(decoded_val) decoded_val = 0 return numpy.asarray(out_arr,dtype=numpy.int32) mmtf-python-1.1.2/mmtf/tests/000077500000000000000000000000001330061152300160745ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/tests/__init__.py000066400000000000000000000000001330061152300201730ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/tests/codec_tests.py000066400000000000000000000417711330061152300207570ustar00rootroot00000000000000import unittest import msgpack import numpy from mmtf import fetch,parse,parse_gzip, converters from mmtf.api.default_api import ungzip_data,write_mmtf,MMTFDecoder,_internet_on from mmtf.codecs import encoders from mmtf.utils.codec_utils import parse_header from mmtf.utils.constants import BASE_URL from mmtf.codecs.default_codec import codec_dict from mmtf.codecs.decoders import numpy_decoders as decoders def run_all(unit_test, encoded_data, decoded_data, param, codec_id): """Test that a given codec can work in the forward backward and round trip both ways.""" try: unit_test.assertEqual(codec_dict[codec_id].decode(encoded_data, param).tolist(), decoded_data.tolist()) except: unit_test.assertEqual(codec_dict[codec_id].decode(encoded_data, param), decoded_data.tolist()) try: unit_test.assertEqual( codec_dict[codec_id].decode(codec_dict[codec_id].encode(decoded_data, param), param).tolist(), decoded_data.tolist()) except: unit_test.assertEqual(codec_dict[codec_id].decode(codec_dict[codec_id].encode(decoded_data, param), param), decoded_data.tolist()) unit_test.assertEqual(codec_dict[codec_id].encode(decoded_data, param), encoded_data) unit_test.assertEqual(codec_dict[codec_id].encode(codec_dict[codec_id].decode(encoded_data, param), param), encoded_data) class CodecTest(unittest.TestCase): def test_delt_rec_float(self): test_data = b'\x7f\xffD\xab\x01\x8f\xff\xca' output_data = numpy.array([50.346, 50.745, 50.691]) run_all(self, test_data, output_data, 1000, 10) def test_run_len_float(self): test_data = b'\x00\x00\x00d\x00\x00\x00\x03' output_data = numpy.array([1.00,1.00,1.00]) run_all(self, test_data, output_data, 100, 9) def test_run_len_delta_int(self): test_data = b'\x00\x00\x00\x01\x00\x00\x00\x07' output_data = numpy.array([1,2,3,4,5,6,7]) run_all(self, test_data, output_data, 0, 8) def test_run_len_char(self): test_data = b'\x00\x00\x00\x41\x00\x00\x00\x04' output_data = numpy.array(["A","A","A","A"]) run_all(self, test_data, output_data, 0, 6) def test_enc_str(self): test_data = b'B\x00\x00\x00A\x00\x00\x00C\x00\x00\x00A\x00\x00\x00A\x00\x00\x00A\x00\x00\x00' output_data = numpy.array(["B","A","C","A","A","A"]) run_all(self, test_data, output_data, 0, 5) def test_byte_to_int(self): test_data = b'\x07\x06\x06\x07\x07' output_data = numpy.array([7,6,6,7,7]) run_all(self, test_data, output_data, 0, 2) def test_four_byte_int(self): test_data = b'\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02' output_data = numpy.array([1, 131073, 0, 2]) run_all(self, test_data, output_data, 0, 4) class DecoderTests(unittest.TestCase): def test_run_length_decode(self): input_data = numpy.array([15,3,100,2,111,4,10000,6]) output_data_test = [15,15,15,100,100,111,111,111,111,10000,10000,10000,10000,10000,10000] output_data = decoders.run_length_decode(input_data).tolist() self.assertEqual(output_data, output_data_test) def test_empty_run_length_decode(self): input_data = numpy.array([]) output_data_test = [] output_data = decoders.run_length_decode(input_data).tolist() self.assertEqual(output_data, output_data_test) def test_delta_decode(self): input_data = numpy.asarray([15,3,100,-1,11,4],dtype=numpy.int32) output_data_test = [15,18,118,117,128,132] output_data = decoders.delta_decode(input_data).tolist() self.assertEqual(output_data, output_data_test) def test_empty_delta_decode(self): input_data = numpy.asarray([],dtype=numpy.int32) output_data_test = [] output_data = decoders.delta_decode(input_data).tolist() self.assertEqual(output_data, output_data_test) class EncoderTests(unittest.TestCase): def test_run_length_encode(self): output_data_test = [15, 3, 100, 2, 111, 4, 10000, 6] input_data = [15, 15, 15, 100, 100, 111, 111, 111, 111, 10000, 10000, 10000, 10000, 10000, 10000] output_data = encoders.run_length_encode(input_data) self.assertEqual(output_data, output_data_test) def test_empty_run_length_encode(self): input_data = [] output_data_test = [] output_data = encoders.run_length_encode(input_data) self.assertEqual(output_data, output_data_test) def test_delta_encode(self): output_data_test = [15, 3, 100, -1, 11, 4] input_data = [15, 18, 118, 117, 128, 132] output_data = encoders.delta_encode(input_data) self.assertEqual(output_data, output_data_test) def test_empty_delta_encode(self): input_data = [] output_data_test = [] output_data = encoders.delta_encode(input_data) self.assertEqual(output_data, output_data_test) class ConverterTests(unittest.TestCase): def test_convert_chain_list(self): in_bytes = b'A\x00\x00\x00A\x00\x00\x00A\x00\x00\x00A\x00\x00\x00A\x00\x00\x00A\x00\x00\x00' out_strings_test = ["A", "A","A","A","A","A"] self.assertEqual(out_strings_test, converters.decode_chain_list(in_bytes)) self.assertEqual(in_bytes, converters.encode_chain_list(out_strings_test)) def test_convert_int_to_float(self): in_array = numpy.asarray([10001,100203,124542]) out_array_test = [10.001,100.203,124.542] converted = converters.convert_ints_to_floats(in_array, 1000.0).tolist() for i in range(len(out_array_test)): self.assertAlmostEqual(out_array_test[i], converted[i],places=3) self.assertEqual(in_array.tolist(), converters.convert_floats_to_ints(out_array_test, 1000.0)) def test_recursive_enc(self): in_arr = [1,420,32767,120,-32768,34767] out_array_test = [1,420,32767,0,120,-32768,0,32767,2000] self.assertEqual(out_array_test, converters.recursive_index_encode(in_arr)) def test_recursive_dec(self): in_arr = numpy.asarray([1,420,32767,0,120,-32768,0,32767,2000],dtype=numpy.int32) out_array_test = [1,420,32767,120,-32768,34767] self.assertEqual(out_array_test, converters.recursive_index_decode(in_arr).tolist()) def test_convert_one_byte_int(self): in_bytes = b'\x07\x06\x06\x07\x07' out_array_test = [7,6,6,7,7] self.assertEqual(out_array_test, converters.convert_bytes_to_ints(in_bytes,1).tolist()) self.assertEqual(in_bytes, converters.convert_ints_to_bytes(out_array_test,1)) self.assertEqual(in_bytes,converters.convert_ints_to_bytes(converters.convert_bytes_to_ints(in_bytes,1),1)) def test_convert_two_byte_int(self): in_bytes = b'\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02' out_array_test = [0,1,2,1,0,0,0,2] self.assertEqual(out_array_test, converters.convert_bytes_to_ints(in_bytes,2).tolist()) self.assertEqual(in_bytes, converters.convert_ints_to_bytes(out_array_test, 2)) self.assertEqual(in_bytes,converters.convert_ints_to_bytes(converters.convert_bytes_to_ints(in_bytes,2),2)) def test_convert_four_byte_int(self): in_bytes = b'\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02' out_array_test = [1, 131073, 0, 2] self.assertEqual(out_array_test, converters.convert_bytes_to_ints(in_bytes,4).tolist()) self.assertEqual(in_bytes, converters.convert_ints_to_bytes(out_array_test,4)) self.assertEqual(in_bytes,converters.convert_ints_to_bytes(converters.convert_bytes_to_ints(in_bytes,4),4)) def test_parse_header(self): in_bytes = b'\x00\x00\x00\x01\x00\x02\x00\x01\x00\x00\x00\x00\x00\x00\x00\x02' codec,length,param, bytearray = parse_header(in_bytes) self.assertEqual(length,131073) self.assertEqual(param,0) self.assertEqual(len(bytearray),4) def test_convert_int_to_char(self): int_array = [66,63,67] out_array_test = ["B", "?","C"] self.assertEqual(out_array_test, converters.convert_ints_to_chars(int_array)) self.assertEqual(int_array, converters.convert_chars_to_ints(out_array_test)) def test_decoder(self): decoded = parse("mmtf/tests/testdatastore/4CUP.mmtf") def test_gz_decoder(self): decoded = parse_gzip("mmtf/tests/testdatastore/4CUP.mmtf.gz") def test_round_trip(self): decoded = parse("mmtf/tests/testdatastore/4CUP.mmtf") packed = decoded.get_msgpack() decoded.decode_data(msgpack.unpackb(packed)) def test_gzip_open(self): with open("mmtf/tests/testdatastore/4CUP.mmtf.gz","rb") as fh: ungzip_data(fh.read()) def test_fetch(self): if _internet_on(BASE_URL): decoded = fetch("4CUP") else: print("Warning - cannot connect to "+BASE_URL) def array_eq(self,array_one, array_two): import numpy as np if [x for x in np.isclose(array_one,array_two) if x]: return True else: try: if not array_one and not array_two: return True except ValueError: pass print(array_one) print(array_two) print("Arrays not equal") return False def char_arr_eq(self,array_one, array_two): import numpy as np return np.array_equal(array_one,array_two) def dict_list_equal(self,list_one,list_two): list_one = sorted(list_one, key=lambda x:sorted(x.keys())) list_two = sorted(list_two, key=lambda x:sorted(x.keys())) len_one = len(list_one) if len_one != len(list_two): self.assertTrue(False,"Lists of different lengths") for i in range(len_one): if list_one[i]!=list_two[i]: print(list_one[i]) print(list_two[i]) self.assertTrue(list_one[i]==list_two[i]) def iterate(self, data_one, data_two): chain_ind = 0 group_ind = 0 atom_ind_one = 0 atom_ind_two = 0 for model in data_one.chains_per_model: for chain in range(model): for group in range(data_one.groups_per_chain[chain_ind]): self.char_arr_eq(data_one.group_list[data_one.group_type_list[group_ind]]["atomNameList"], data_two.group_list[data_two.group_type_list[group_ind]]["atomNameList"]) self.char_arr_eq(data_one.group_list[data_one.group_type_list[group_ind]]["elementList"], data_two.group_list[data_two.group_type_list[group_ind]]["elementList"]) self.array_eq(data_one.group_list[data_one.group_type_list[group_ind]]["bondOrderList"], data_two.group_list[data_two.group_type_list[group_ind]]["bondOrderList"]) self.array_eq(data_one.group_list[data_one.group_type_list[group_ind]]["bondAtomList"], data_two.group_list[data_two.group_type_list[group_ind]]["bondAtomList"]) self.array_eq(data_one.group_list[data_one.group_type_list[group_ind]]["formalChargeList"], data_two.group_list[data_two.group_type_list[group_ind]]["formalChargeList"]) self.assertEqual(data_one.group_list[data_one.group_type_list[group_ind]]["groupName"], data_two.group_list[data_two.group_type_list[group_ind]]["groupName"]) self.assertEqual(data_one.group_list[data_one.group_type_list[group_ind]]["singleLetterCode"], data_two.group_list[data_two.group_type_list[group_ind]]["singleLetterCode"]) self.assertEqual(data_one.group_list[data_one.group_type_list[group_ind]]["chemCompType"], data_two.group_list[data_two.group_type_list[group_ind]]["chemCompType"]) group_ind+=1 chain_ind+=1 return True def check_equal(self, data_one, data_two): self.assertTrue(self.array_eq(data_one.x_coord_list,data_two.x_coord_list)) self.assertTrue(self.array_eq(data_one.y_coord_list,data_two.y_coord_list)) self.assertTrue(self.array_eq(data_one.z_coord_list,data_two.z_coord_list)) self.assertTrue(self.array_eq(data_one.b_factor_list,data_two.b_factor_list)) self.assertTrue(self.array_eq(data_one.occupancy_list,data_two.occupancy_list)) self.assertTrue(self.array_eq(data_one.atom_id_list,data_two.atom_id_list)) self.assertTrue(self.char_arr_eq(data_one.alt_loc_list,data_two.alt_loc_list)) self.assertTrue(self.char_arr_eq(data_one.ins_code_list,data_two.ins_code_list)) self.assertTrue(self.array_eq(data_one.group_id_list,data_two.group_id_list)) self.dict_list_equal(data_one.entity_list,data_two.entity_list) self.dict_list_equal(data_one.bio_assembly,data_two.bio_assembly) self.assertTrue(self.array_eq(data_one.sequence_index_list,data_two.sequence_index_list)) self.assertEqual(data_one.chains_per_model, data_two.chains_per_model) self.assertEqual(data_one.groups_per_chain, data_two.groups_per_chain) self.assertEqual(data_one.chain_name_list, data_two.chain_name_list) self.assertEqual(data_one.chain_id_list, data_two.chain_id_list) self.assertEqual(data_one.space_group,data_two.space_group) self.assertTrue(self.array_eq(data_one.bond_atom_list,data_two.bond_atom_list)) self.assertTrue(self.array_eq(data_one.bond_order_list,data_two.bond_order_list)) self.assertEqual(data_one.structure_id,data_two.structure_id) self.assertEqual(data_one.title,data_two.title) self.assertTrue(self.char_arr_eq(data_one.experimental_methods,data_two.experimental_methods)) self.assertEqual(data_one.deposition_date,data_two.deposition_date) self.assertEqual(data_one.release_date,data_two.release_date) self.assertTrue(self.array_eq(data_one.sec_struct_list,data_two.sec_struct_list)) self.assertEqual(data_one.r_free,data_two.r_free) self.assertEqual(data_one.r_work,data_two.r_work) self.assertEqual(data_one.resolution,data_two.resolution) self.assertEqual(data_one.unit_cell,data_two.unit_cell) self.assertEqual(data_one.num_bonds, data_two.num_bonds) self.assertEqual(data_one.num_chains, data_two.num_chains) self.assertEqual(data_one.num_models, data_two.num_models) self.assertEqual(data_one.num_atoms, data_two.num_atoms) self.assertEqual(data_one.num_groups, data_two.num_groups) self.assertTrue(self.iterate(data_one, data_two)) def test_round_trip(self): data_in = parse_gzip("mmtf/tests/testdatastore/4CUP.mmtf.gz") write_mmtf("test.mmtf", data_in, MMTFDecoder.pass_data_on) data_rt = parse("test.mmtf") self.check_equal(data_in, data_rt) def round_trip(self,pdb_id): if _internet_on(BASE_URL): data_in = fetch(pdb_id) write_mmtf(pdb_id+".mmtf", data_in, MMTFDecoder.pass_data_on) data_rt = parse(pdb_id+".mmtf") self.check_equal(data_in, data_rt) else: print("Warning - cannot connect to "+BASE_URL) def test_round_trip_list(self): id_list = [ # "1a1q", # // Just added to check "9pti", # // An entity that has no chain "2ja5", # // A couple of examples of multiple disulpgide bonds being formed. "3zxw", "1nty", # // A weird residue case "2eax", # // A Deuterated Structure "4pdj", # // Weird bioassembly "4a1i", # // Multi model structure "1cdr", # // Another weird structure (jose's suggestion) "3zyb", # //Standard structure "4cup", # // Weird NMR structure "1o2f", # // B-DNA structure "1bna", # // DNA structure "4y60", # // Sugar structure "1skm", # // Calpha atom is missing (not marked as calpha) "1lpv", # // NMR structure with multiple models - one of which has chain missing "1msh", # // No ATOM records just HETATM records (in PDB). Opposite true for MMCif. It's a D-Peptide. "1r9v", # // Biosynthetic protein "5emg", # // Micro heterogenity "4ck4", # // Ribosome "4v5a", # // Negative residue numbers "5esw", # // A tiny example case "3njw", # // A GFP example with weird seqres records "1ema"] for pdb_id in id_list: self.round_trip(pdb_id) if __name__ == '__main__': unittest.main() mmtf-python-1.1.2/mmtf/tests/testdatastore/000077500000000000000000000000001330061152300207625ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/tests/testdatastore/4CUP.mmtf000066400000000000000000000457561330061152300224030ustar00rootroot00000000000000'mmtfVersion0.2.0mmtfProducerFRCSB-PDB Generator---version: 9e4d06f3ae054608c07119dcc6f71ca66031cec2numBondsҨnumAtomsSnumGroups numChainsnumModelsstructureId4CUPtitleBCrystal structure of human BAZ2B in complex with fragment-1 N09421chainsPerModelgroupsPerChains̒chainNameList$AAAAAAchainIdList$ABCDEFspaceGroupC 2 2 21unitCellBqB=qBfBBBbioAssemblyListtransformListchainIndexListmatrix????chainIndexListmatrix˿@TzH?˿@<\(?name1bondAtomList$-&4/96D;LFTNZVa\icqkvs~x ")$0+82@:IBQKXS_Zcaoexqz  #*%2,:4@<GBRIWT_Yganiyp{"*$2,=4D?PF[Rd]mfuowbondOrderList~rgroupListgroupNameGLUatomNameListNCACOCBCGCDOE1OE2CBCGCDOE1OE2elementListNCCOCCCOOCCCOObondOrderListbondAtomList  formalChargeListsingleLetterCodeEchemCompTypeL-PEPTIDE LINKINGgroupNameASNatomNameListNCACOCBCGOD1ND2elementListNCCOCCONbondOrderListbondAtomListformalChargeListsingleLetterCodeNchemCompTypeL-PEPTIDE LINKINGgroupNameVALatomNameListNCACOCBCG1CG2elementListNCCOCCCbondOrderListbondAtomListformalChargeListsingleLetterCodeVchemCompTypeL-PEPTIDE LINKINGgroupNameLYSatomNameListNCACOCBCGCDCEelementListNCCOCCCCbondOrderListbondAtomListformalChargeListsingleLetterCodeKchemCompTypeL-PEPTIDE LINKINGgroupNameGLYatomNameListNCACOelementListNCCObondOrderListbondAtomListformalChargeListsingleLetterCodeGchemCompTypePEPTIDE LINKINGgroupNameLYSatomNameListNCACOCBCGCDCENZelementListNCCOCCCCNbondOrderListbondAtomListformalChargeListsingleLetterCodeKchemCompTypeL-PEPTIDE LINKINGgroupNameGLUatomNameListNCACOCBCGCDOE1OE2elementListNCCOCCCOObondOrderListbondAtomListformalChargeListsingleLetterCodeEchemCompTypeL-PEPTIDE LINKINGgroupNameGLUatomNameListNCACOCBCGelementListNCCOCCbondOrderListbondAtomListformalChargeListsingleLetterCodeEchemCompTypeL-PEPTIDE LINKINGgroupNameMOHatomNameListCOelementListCObondOrderListbondAtomListformalChargeListsingleLetterCode?chemCompTypeNON-POLYMERgroupNameASPatomNameListNCACOCBCGOD1OD2elementListNCCOCCOObondOrderListbondAtomListformalChargeListsingleLetterCodeDchemCompTypeL-PEPTIDE LINKINGgroupNameCYSatomNameListNCACOCBSGelementListNCCOCSbondOrderListbondAtomListformalChargeListsingleLetterCodeCchemCompTypeL-PEPTIDE LINKINGgroupNameHOHatomNameListOelementListObondOrderListbondAtomListformalChargeListsingleLetterCode?chemCompTypeNON-POLYMERgroupNameLYSatomNameListNCACOCBCGCDelementListNCCOCCCbondOrderListbondAtomListformalChargeListsingleLetterCodeKchemCompTypeL-PEPTIDE LINKINGgroupNameLYSatomNameListNCACOCBelementListNCCOCbondOrderListbondAtomListformalChargeListsingleLetterCodeKchemCompTypeL-PEPTIDE LINKINGgroupNameLEUatomNameListNCACOCBCGCD1CD2elementListNCCOCCCCbondOrderListbondAtomListformalChargeListsingleLetterCodeLchemCompTypeL-PEPTIDE LINKINGgroupNameMETatomNameListNCACOCBCGSDCEelementListNCCOCCSCbondOrderListbondAtomListformalChargeListsingleLetterCodeMchemCompTypeL-PEPTIDE LINKINGgroupNameTRPatomNameListNCACOCBCGCD1CD2NE1CE2CE3CZ2CZ3CH2elementListNCCOCCCCNCCCCCbondOrderListbondAtomList    formalChargeListsingleLetterCodeWchemCompTypeL-PEPTIDE LINKINGgroupNameTYRatomNameListNCACOCBCGCD1CD2CE1CE2CZOHelementListNCCOCCCCCCCObondOrderListbondAtomList   formalChargeListsingleLetterCodeYchemCompTypeL-PEPTIDE LINKINGgroupNamePHEatomNameListNCACOCBCGCD1CD2CE1CE2CZelementListNCCOCCCCCCCbondOrderListbondAtomList   formalChargeListsingleLetterCodeFchemCompTypeL-PEPTIDE LINKINGgroupNamePROatomNameListNCACOCBCGCDelementListNCCOCCCbondOrderListbondAtomListformalChargeListsingleLetterCodePchemCompTypeL-PEPTIDE LINKINGgroupNameTHRatomNameListNCACOCBOG1CG2elementListNCCOCOCbondOrderListbondAtomListformalChargeListsingleLetterCodeTchemCompTypeL-PEPTIDE LINKINGgroupNameZYBatomNameListFC2C1C3C4C5CC6NN1OH1H3HH4HN1HN2HBelementListFCCCCCCCNNOHHHHHHHbondOrderListbondAtomList$     formalChargeListsingleLetterCode?chemCompTypenon-polymergroupNameMETatomNameListNCACOCBCGSDCENCACOCBCGSDCEelementListNCCOCCSCNCCOCCSCbondOrderListbondAtomList   formalChargeListsingleLetterCodeMchemCompTypeL-PEPTIDE LINKINGgroupNameSERatomNameListNCACOCBOGelementListNCCOCObondOrderListbondAtomListformalChargeListsingleLetterCodeSchemCompTypeL-PEPTIDE LINKINGgroupNameHISatomNameListNCACOCBCGND1CD2CE1NE2elementListNCCOCCNCCNbondOrderListbondAtomList  formalChargeListsingleLetterCodeHchemCompTypeL-PEPTIDE LINKINGgroupNameGLNatomNameListNCACOCBCGCDOE1NE2elementListNCCOCCCONbondOrderListbondAtomListformalChargeListsingleLetterCodeQchemCompTypeL-PEPTIDE LINKINGgroupNameARGatomNameListNCACOCBCGCDNECZNH1NH2elementListNCCOCCCNCNNbondOrderListbondAtomList  formalChargeListsingleLetterCodeRchemCompTypeL-PEPTIDE LINKINGgroupNameALAatomNameListNCACOCBelementListNCCOCbondOrderListbondAtomListformalChargeListsingleLetterCodeAchemCompTypeL-PEPTIDE LINKINGgroupNameILEatomNameListNCACOCBCG1CG2CD1elementListNCCOCCCCbondOrderListbondAtomListformalChargeListsingleLetterCodeIchemCompTypeL-PEPTIDE LINKINGxCoordList SDqRlJ51R L C&DN%&Vx]:@6vWxTOOn] avE g 3" 5QZ);V6! ++t" Y(xVO#|w g+'DE + k A_ PyxA u;4 +8|s&y75eX V9 M E8% !a}1c? > yYl,+8+s7p="eL=jHg  7G~rw>  ,Kg[\  8{t[fEcf]GAZ,&+x bE=G! J&5^! OlOL G(qWJg 9 , Lel(}3>"-9~7Qw7V)4 C\  6,!0l6@1;> N| xxh Rh|ie- \.^GnR Nw,*Uu4hGS#v %K=YOGEVT, T='9R C1IRvv . U.gRf- _ jQ@( u|_|1fiyIm7CU j\.x2 X ;NwY|x zxgKN1s 6l[P#nS[E{'?WI*hpY/Kwy(1z4 -C1iCOkoE5` rl uooa S[ R! n^ZY X8m s q 4nƛ'-.k xc'/V^| vLnI9 j l 7 fg a -%W *$EkЗ f McI.u+$6~ D26 W t2, !Q8 0~5'%C 'yCoordList SKW: CJb_wQIt!bp7zC]+*y'$sD3x Ut|s*oONklxWg +Wi?@tPR.zk&mUBnl5O4D ,2 ovlrur(D[INXiT6D P%,`rd _B,c_ p3hfw!O)X; z&-3<< W /H'*6l"bVr :kb&U" AWKCpj#kUh+<biEjJCwL'rZE_I"F[:3Na**b |`*HVho]6F=(V<u}Wbe> 8]s4F\& } -?;oa,, = [?aF;S A WTD,' Cz5<, ;*4!3 h1{;aUJ8W[KE4](@s9OK"o/S2f-{* )q K22Ogv">(  )! 'i 8b !{W@/+"^ _ 1 j K|-Z<s]Z 6R *@q q @vV V~uZQߕ zCoordList SC2mda7M].'H:x <["sak C 5 mr( 1\Z-V:]]chu[^)qI BMrGM{CnUOrsC o.~euS;9{mf`PFRv:QZ9!Z~#0W* 3yJ@T *w(P' 2Li gi1d $Il 1a"g/}6!;X'@_W'6:a qF(m ) X{Kx-+4lHf7Gj0 k j1_c@a~4SH n2N}tt$<QQ&VZ]#n M/ h&Au4@!;T*[%[`7OwRCV@B{vfWC94>\{#/ 'TA)%mG5q!-p 4F,4 'tDMN2"E*.2 ttv[}VMB7,z;\iP=ed}qg/ #aApW(PW W> q 1 sjq~< B UZ5!Cq[8,kh$""1( 9?.M(<c+^4ܟd]_L Z  9l 9  dXs]`[ #j !K(lH =   9 | 8j^<vbgGbFactorList Sd )sJz}qAz1P}N}!n HLOZ#!xcb:$]Cm U@U@zO?f@4W&C'9*+YYpk-L)# &a Z+}v%`&zK`57lrE}&[/+[_OaOG'IZ&%N@:C*K :QF6vAXsCiTck:4ucpm`F2RV{yDgG`B}1rrjHQ qT- :6%0GqG< HW[h$,2 *FQ@_(?$-9*Jnqw^&aw~"%z$}ZC O;9s|p/*,]n34~DkG|gEJ8 \'Kvg?swN[8 S"p7??adHBQ9ZK1&<4^$b}rM_Fpmy;LSkbVBO6&XBp|6]YL8}<b(Xt >V}%;qhL2r4| Q-o:[wW<:,ihN3H05abnIT@#t-1IIsW%tP =MP7j\QJ{h<0}9u>;0";Ca=L2.(u :b eGWkw3##[K&FA;f-cwyZNo`q7@ PrHPS#^I+ qlrk%k==C8S%bK9 RWC+cO=t7 MV[r ]|6 @r S-1T-/uvrNT ]No cK5secStructList occupancyList< Sdd2d&>dyaltLocListDS AB AB yinsCodeList  groupTypeList0                groupIdList< @r3atomIdListTSysequenceIndexList, rexperimentalMethodsX-RAY DIFFRACTIONresolution?ץrFree>TɆrWork>4entityListdescription5BROMODOMAIN ADJACENT TO ZINC FINGER DOMAIN PROTEIN 2BtypepolymerchainIndexListsequenceuSMSVKKPKRDDSKDLALCSMILTEMETHEDAWPFLLPVNLKLVPGYKKVIKKPMDFSTIREKLSSGQYPNLETFALDVRLVFDNCETFNEDDSDIGRAGHNMRKYFEKKWTDTFKVSdescription4-FLUOROBENZAMIDOXIMEtypenon-polymerchainIndexListsequencedescriptionMETHANOLtypenon-polymerchainIndexListsequencedescriptionwatertypewaterchainIndexListsequencedepositionDate2014-03-21releaseDate2014-04-02ncsOperatorListmmtf-python-1.1.2/mmtf/tests/testdatastore/4CUP.mmtf.gz000066400000000000000000000256411330061152300230110ustar00rootroot00000000000000w\ϔM,QIĂ=D5 "5QcL1{,Xcc={Aro@/1^ns̜{jd3.)-OjҺ{#Qi=&&omi7$)%)-!#5oг 6IjУn@ Iu68n#&=z6OL[?1)ZH?N~+H~Ƭ!iGK>)醂v=QfzFČiI=4tZ'#9|kKd߿M{`ց⛘گr}2zLK/)%7n$-*)^ kz"1=ՅE$K -P$ //#/" KHVOHL*ro?SdXiGZj!_z:z#^vԯ{Ђ;N:#-!%gjZɣi M4t@P~ i}\RG[fCr7';Vex i_%j]kZ+/IUw]`~2WC%N/,q$^R oIATIKHޕ4i& gA+tI$]%}$Atɧ!1$$$%_KfKJI l_QL$SGH>oK3ے+,]I *О'Fԏ<$fDUT->@u%%%$$M%xP{I$FDIHJ$R+>@$$%KHhDjGR/#zԋK^UA"%G$$JIKNKdݑX%.>v$1ecIYDju$R31~\"qDKd `wH8E"cHԏ~\J!VˆE,YBYGKp 3)9 ]'/m<0z|)ѧ]LB `2y]AIH33[IJ.OJ ce]*wR?ӱC'  )#G/*!zf ё #J Q(9ߗ jˉx 9q%(.g%_RBˌXRgUBbB 2fP)敕"q%!3Ubx* { 1!J)S%rCCJ5|>>_ѹճwmafo丹ke^fٝjֿz^3B )b4`"ۖ0}aMaRI'#x/e 2#"#"; .9D:Dg@k8\k.11ذmI%#cny߽`ԤvL<%x#StkV\CqO}!gi 6OwX-"[U-_%NWL̫21Lißu8BfTKp=IŖrY۾r`)I/IeR%kRNfqI.w.矕=KSLs_s^)lZ)!u"m+我#sPѹS*.6,2Y/4Xdiв EKmm [ԶD,,6!"-WR6^2y\FfgB\ nTTŖ*KʤOM/)UYHS^19^X2=:]}_^KPd2vZ.fW7Ww?;uYLp+ɑ;L c^gZr`77XQrr;DEl>d|y,۾qv:۾,74?7ۿG!̟Dˬ8Wr|xY"=_SJ,:_)Lh _0 | CÃ~'C<<$bIMM+-'@Ah8¦*#x}0hqҞ*C>%j᳝NBآ.qzPЏTʫVTqb7UgVemJiIbHISԧ|z^ nsm P|]ϯMSwk ,= UIbjg#]*D:kovc3-H͇b`JCYNbP54 Nñٗ{I/V۴(W b{Ս\NP_T?4G"U6tnRQu)lSf rL:,Jc>p5OK׫FА/mxn|]-3lզQhJ} wDKžZcS5*LkHGpvDRA>f2uɼ_Mwڼ1MʠtHDWp*9$:#I q4eqхȴ]{e2דv|{is8{:%t]O0il&EX5 7Ewծ7Jlδ1Y|Smjq~'@7ڃq"INU6QsG!MyN.]VS`_I0nA3;#$-C)^L fO. []UͦHH9M}gG8zN3n~i5Wa}.4Va}n(vaTl9 us8yB=vȔ,'V^(BvE闰[D\V>F>YcJ{`dcxhrx)l կh2༁uUG[wBDt5o!?#褣NZz2:m,PT[[Ÿ_Q|${E_(6Ұ s7>OMuh>v:rsh4{V=Ji.JW;Z9s)C4_3]B1Q>Q} E&Az)=ہ ) Qv=rİ7e ɝH5Faz(ZN)iBI?$-ƍ"X+!θa;+-tEhEC8-Vkb#}N%2 iZ}vOاrF=_^4偧* w"gc^,nJ9RUB>}y\mϷFBщ|F"Ne֯˻Qw VX(>odS9J62hJs6W39J'`mY& E͇o'mCo0e#KJad fS$DgHoMGW ~do077Mu 3lqE|-{Rqd-ja&C>>`9k@Kl?wl![QV |]:快>brat0kj>dXm73!Ec;0Z'5J0ܰ6Tȵ͢+"%cD>Nl*u& cb:_>ھ$A1;bHUX=O'S2Re'whmU+wk[~͇ܟ skQ;8zq5~9}8f/b[Oypb1٨=0_͝&6ŸWV\O^=3zp-o;mFIWS3zf唃|vJb>yhϽqj|+TS.ηyi$.:=˔3ɞq=^>w =-ӦjOeiG9a̛rhQ̏G1axTdB+ưqeCVu0]=\# ri9ݡIYʉ6baan6usv loz%]_icIyeXė Z*CTTϠ>0q-5t$H_|TT֒MCpz9\_\a=*U.sP?+;x9ZV,OS(G4wl;3$fV&dd;КdmcxC/Aڗ3r]Vm9ն8&$۩͝FvM; !S9Ҭ5Պ+ze ?f6>LA d+#Zu'ְT"Ȟ68V#ZR nb=aʇ59S1DțtW*ެ6:h w^o3#ko~L''x$ͱieFkzu|޼BdM!]U'2Dvy\gw&z>Y٨=},ϑ8~@ om4& A?R=&荵 k;7tܢɎ"}9:;o~%ue_+DAp5EK(i'UbO*q5X46?`? CXq+(64OYwR7uFoN ΄R?RWnǺ&y5^=y&TW%r2]c'Xly!Wll[J`)tRN"-;Kiuށ9A  yBǡZc fx+7N!edjϓ#3Zyӵ;lX-IdPCNiL4s]s{(LV΢Ya*i;ro{+⿈W\_6ko81[m<&>chzuCZeTĉx<# vm#X]IbSM.Ti _no:Q-1㨁0ٺUѬƮX̪׈|} q)-q3jLSGQuZ&wZ,-A'6f8F_MXG3vi?VN8<qQ7@x%Vٽ^SVnZ[k8[0'XhN-.`: bOaYܹoDPk͌ߢEp:,td4R_Cc=8Ҿޅ{Z6٭A7),J,zl 'I(OΑe+'!$W8Ҹ@1z*~_v_I-˜7d]Gؙy*V{) 㵛Šlv mܚOhUU{N([[|(e6!A7o 7e utfYd4~Ъ@goNbxG-Rl8P΁rvd}C+zބxR&ߊXZ8=Tza41=ʙjZJ .zsutCQyKէb uz#bvq 1ޕ #?#JN997Yj֛Y^ةvќKt-X4? dG9}'J(^Z8/sdl ƸPht<ǘghjv"wD>ⶬ >n+5 @.`]MpAlI>On>mE' o;mOPccwHVڊVzke2DJ7ȱ$)D{*П%+|fDp&G95X+։@VͫV~Pŗ"a$~e)ϫ< 즜Ά|sCp$:x o 9wEd!>^Z8I&&j"_cTWjc{{07wԣzgih>D֤ jȩ} Qj ''ae=*Óa2q3M1Z YM2p<=tL^4^7{$޻IJ+J8fNt;jz)oc=Xu2K+?|/9]^kUc=mrNãq}Jz@݆ʣX.u9߸N߫~UUO<:W߁nVj:7!0 Cb` /4 qQ(J#h#yk4DfH,.nh oBC b|&0$~GM[| -l7|+&f&c|;h+X{_\T[b7jXik%7b TlPV,Sw1Z?Q_q:ȓ0~;v0r\],/;|/ɀ$(QM.a/~8Fal؁*Sޅ]Q5gi[8.}I#C[qǮ kB7l{!3 5D n2rX]=Di9ۅW(.{įwHZІ/] kz ?hfo_a ~(DL4z*ljSdG5O@eKQڤ#?UQ5َ#Dg"\G_&.~ 0נ?[ػPKAy7ֱrԱ(P}\|l MpM}E*ϓt:^` >4fItE5X:A›ue(]|fbPCBl[V Pl1*ϲFB#-Lv&(@*T>lhˢŸ8u/#G?[/VZy%-<ݸ;SeJv|l=pL 1~eyGYr_p U; p#WPG BeMQE-pt@7I\Gb*j |)NFsWȇDq|y9-81mdٌ+H׃I(Mk p"ڣ&֠a2g.x0Wp~v.15mhk-_9<½#`ryQw)<q+&d ?Xxll, o&2pue-]O#9ɸˁڋ'7}oCt8+{=8h`hu1I{"+rZiBU5VʯϖWԖmn XX5_,vp&ұ OڷJhP\+ُ{/ N)lOsմXOZJvFƑcZ fqak 1taċrmi",gLfWcS.;Ŷqi7>V0 qacZ UJOsyN6#sLD᮶Ś[)D9rwF2fj8"2X~.F&Oir&x_Tvܬ7t0yjnt wZ4:=)1CT [cq`,Z \bA-J)BгTx9/,X,FrY8BJb519+`W=]dz_>Q9q4teBrFxjbaA0TT̊.ZXTP뢵oA}R TX׳_̫ U=Ju) TV^EE)q<[H9.E&U(Z;+bѱ"c `(/Wm.T}SW֫n}ziII I֦$GȮ?uqKmmtf-python-1.1.2/mmtf/utils/000077500000000000000000000000001330061152300160725ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/utils/__init__.py000066400000000000000000000000001330061152300201710ustar00rootroot00000000000000mmtf-python-1.1.2/mmtf/utils/codec_utils.py000066400000000000000000000021731330061152300207440ustar00rootroot00000000000000import struct import mmtf import mmtf.utils.constants def parse_header(input_array): """Parse the header and return it along with the input array minus the header. :param input_array the array to parse :return the codec, the length of the decoded array, the parameter and the remainder of the array""" codec = struct.unpack(mmtf.utils.constants.NUM_DICT[4], input_array[0:4])[0] length = struct.unpack(mmtf.utils.constants.NUM_DICT[4], input_array[4:8])[0] param = struct.unpack(mmtf.utils.constants.NUM_DICT[4], input_array[8:12])[0] return codec,length,param,input_array[12:] def add_header(input_array, codec, length, param): """Add the header to the appropriate array. :param the encoded array to add the header to :param the codec being used :param the length of the decoded array :param the parameter to add to the header :return the prepended encoded byte array""" return struct.pack(mmtf.utils.constants.NUM_DICT[4], codec) + \ struct.pack(mmtf.utils.constants.NUM_DICT[4], length) + \ struct.pack(mmtf.utils.constants.NUM_DICT[4], param) + input_arraymmtf-python-1.1.2/mmtf/utils/constants.py000066400000000000000000000006531330061152300204640ustar00rootroot00000000000000COORD_DIVIDER = 1000.0 OCC_B_FACTOR_DIVIDER = 100.0 MAX_SHORT = 32767 MIN_SHORT = -32768 NULL_BYTE = '\x00' CHAIN_LEN = 4 PRODUCER = "mmtf-python" MMTF_VERSION = "1.0.0" NUM_DICT = {1:'b',2:'>h',4:'>i'} BASE_URL = "https://mmtf.rcsb.org/v1.0/full/" BASE_URL_REDUCED = "https://mmtf.rcsb.org/v1.0/reduced/" UNKNOWN_SPACE_GROUP = "" UNKNOWN_UNIT_CELL = None UNKOWN_GROUP_NAME = "UNL" UNKOWN_GROUP_TYPE = "other" UNKNOWN_SL = "X" mmtf-python-1.1.2/mmtf/utils/decoder_utils.py000066400000000000000000000202721330061152300212740ustar00rootroot00000000000000import sys from mmtf.utils import constants def add_atom_data(data_api, data_setters, atom_names, element_names, atom_charges, group_atom_ind): """Add the atomic data to the DataTransferInterface. :param data_api the data api from where to get the data :param data_setters the class to push the data to :param atom_nams the list of atom names for the group :param element_names the list of element names for this group :param atom_charges the list formal atomic charges for this group :param group_atom_ind the index of this atom in the group""" atom_name = atom_names[group_atom_ind] element = element_names[group_atom_ind] charge = atom_charges[group_atom_ind] alternative_location_id = data_api.alt_loc_list[data_api.atom_counter] serial_number = data_api.atom_id_list[data_api.atom_counter] x = data_api.x_coord_list[data_api.atom_counter] y = data_api.y_coord_list[data_api.atom_counter] z = data_api.z_coord_list[data_api.atom_counter] occupancy = data_api.occupancy_list[data_api.atom_counter] temperature_factor = data_api.b_factor_list[data_api.atom_counter] data_setters.set_atom_info(atom_name, serial_number, alternative_location_id, x, y, z, occupancy, temperature_factor, element, charge) def add_group_bonds(data_setters, bond_indices, bond_orders): """Add the bonds for this group. :param data_setters the class to push the data to :param bond_indices the indices of the atoms in the group that are bonded (in pairs) :param bond_orders the orders of the bonds""" for bond_index in range(len(bond_orders)): data_setters.set_group_bond(bond_indices[bond_index*2],bond_indices[bond_index*2+1],bond_orders[bond_index]) def add_group(data_api, data_setters, group_index): """Add the data for a whole group. :param data_api the data api from where to get the data :param data_setters the class to push the data to :param group_index the index for this group""" group_type_ind = data_api.group_type_list[group_index] atom_count = len(data_api.group_list[group_type_ind]["atomNameList"]) insertion_code = data_api.ins_code_list[group_index] data_setters.set_group_info(data_api.group_list[group_type_ind]["groupName"], data_api.group_id_list[group_index], insertion_code, data_api.group_list[group_type_ind]["chemCompType"], atom_count, data_api.num_bonds, data_api.group_list[group_type_ind]["singleLetterCode"], data_api.sequence_index_list[group_index], data_api.sec_struct_list[group_index]) for group_atom_ind in range(atom_count): add_atom_data(data_api, data_setters, data_api.group_list[group_type_ind]["atomNameList"], data_api.group_list[group_type_ind]["elementList"], data_api.group_list[group_type_ind]["formalChargeList"], group_atom_ind) data_api.atom_counter +=1 add_group_bonds(data_setters, data_api.group_list[group_type_ind]["bondAtomList"], data_api.group_list[group_type_ind]["bondOrderList"]) return atom_count def add_chain_info(data_api, data_setters, chain_index): """Add the data for a whole chain. :param data_api the data api from where to get the data :param data_setters the class to push the data to :param chain_index the index for this chain""" chain_id = data_api.chain_id_list[chain_index] chain_name = data_api.chain_name_list[chain_index] num_groups = data_api.groups_per_chain[chain_index] data_setters.set_chain_info(chain_id, chain_name, num_groups) next_ind = data_api.group_counter + num_groups last_ind = data_api.group_counter for group_ind in range(last_ind, next_ind): add_group(data_api, data_setters, group_ind) data_api.group_counter +=1 data_api.chain_counter+=1 def add_atomic_information(data_api, data_setters): """Add all the structural information. :param data_api the data api from where to get the data :param data_setters the class to push the data to""" for model_chains in data_api.chains_per_model: data_setters.set_model_info(data_api.model_counter, model_chains) tot_chains_this_model = data_api.chain_counter + model_chains last_chain_counter = data_api.chain_counter for chain_index in range(last_chain_counter, tot_chains_this_model): add_chain_info(data_api, data_setters, chain_index) data_api.model_counter+=1 def generate_bio_assembly(data_api, struct_inflator): """Generate the bioassembly data. :param data_api the interface to the decoded data :param struct_inflator the interface to put the data into the client object""" bioassembly_count = 0 for bioassembly in data_api.bio_assembly: bioassembly_count += 1 for transform in bioassembly["transformList"]: struct_inflator.set_bio_assembly_trans(bioassembly_count, transform["chainIndexList"], transform["matrix"]) def add_inter_group_bonds(data_api, struct_inflator): """ Generate inter group bonds. Bond indices are specified within the whole structure and start at 0. :param data_api the interface to the decoded data :param struct_inflator the interface to put the data into the client object""" for i in range(len(data_api.bond_order_list)): struct_inflator.set_inter_group_bond(data_api.bond_atom_list[i * 2], data_api.bond_atom_list[i * 2 + 1], data_api.bond_order_list[i]) def add_header_info(data_api, struct_inflator): """ Add ancilliary header information to the structure. :param data_api the interface to the decoded data :param struct_inflator the interface to put the data into the client object """ struct_inflator.set_header_info(data_api.r_free, data_api.r_work, data_api.resolution, data_api.title, data_api.deposition_date, data_api.release_date, data_api.experimental_methods) def add_xtalographic_info(data_api, struct_inflator): """ Add the crystallographic data to the structure. :param data_api the interface to the decoded data :param struct_inflator the interface to put the data into the client object""" if data_api.unit_cell == None and data_api.space_group is not None: struct_inflator.set_xtal_info(data_api.space_group, constants.UNKNOWN_UNIT_CELL) elif data_api.unit_cell is not None and data_api.space_group is None: struct_inflator.set_xtal_info(constants.UNKNOWN_SPACE_GROUP, data_api.unit_cell) elif data_api.unit_cell is None and data_api.space_group is None: struct_inflator.set_xtal_info(constants.UNKNOWN_SPACE_GROUP, constants.UNKNOWN_UNIT_CELL) else: struct_inflator.set_xtal_info(data_api.space_group, data_api.unit_cell) def add_entity_info( data_api, struct_inflator): """Add the entity info to the structure. :param data_api the interface to the decoded data :param struct_inflator the interface to put the data into the client object """ for entity in data_api.entity_list: struct_inflator.set_entity_info(entity["chainIndexList"], entity["sequence"], entity["description"], entity["type"]) def get_bonds(input_group): """Utility function to get indices (in pairs) of the bonds.""" out_list = [] for i in range(len(input_group.bond_order_list)): out_list.append((input_group.bond_atom_list[i * 2], input_group.bond_atom_list[i * 2 + 1],)) return out_list mmtf-python-1.1.2/requirements.txt000066400000000000000000000000511330061152300172470ustar00rootroot00000000000000ipython==5.4.1 numpy nose msgpack>=0.5.6 mmtf-python-1.1.2/setup.cfg000066400000000000000000000003751330061152300156150ustar00rootroot00000000000000[bdist_wheel] # This flag says that the code is written to work on both Python 2 and Python # 3. If at all possible, it is good practice to do this. If you cannot, you # will need to generate wheels for each Python version that you support. universal=1 mmtf-python-1.1.2/setup.py000066400000000000000000000060501330061152300155020ustar00rootroot00000000000000 # Always prefer setuptools over distutils from setuptools import setup, find_packages # To use a consistent encoding from codecs import open from os import path here = path.abspath(path.dirname(__file__)) # Get the long description from the README file with open(path.join(here, 'README.rst'), encoding='utf-8') as f: long_description = f.read() print(find_packages(exclude=['contrib', 'docs', 'tests'])) setup( name='mmtf-python', # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html version='1.1.2', description='A decoding libary for the PDB mmtf format', long_description=long_description, # The project's main homepage. url='https://github.com/rcsb/mmtf-python.git', # Author details author='Anthony Bradley', author_email='anthony.bradley@rcsb.org', # Choose your license license='Apache 2.0', # See https://pypi.python.org/pypi?%3Aaction=list_classifiers classifiers=[ # How mature is this project? Common values are # 3 - Alpha # 4 - Beta # 5 - Production/Stable 'Development Status :: 5 - Production/Stable', # Indicate who your project is intended for 'Intended Audience :: Developers', 'Topic :: Software Development :: Build Tools', # Pick your license as you wish (should match "license" above) 'License :: OSI Approved :: MIT License', # Specify the Python versions you support here. In particular, ensure # that you indicate whether you support Python 2, Python 3 or both. 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', ], # What does your project relate to? keywords='', # You can just specify the packages manually here if your project is # simple. Or you can use find_packages(). packages=find_packages(exclude=['contrib', 'docs', 'tests']), # Alternatively, if you want to distribute just a my_module.py, uncomment # this: # py_modules=["my_module"], # List run-time dependencies here. These will be installed by pip when # your project is installed. For an analysis of "install_requires" vs pip's # requirements files see: # https://packaging.python.org/en/latest/requirements.html install_requires=['msgpack>=0.5.6'], # List additional groups of dependencies here (e.g. development # dependencies). You can install these using the following syntax, # for example: # $ pip install -e .[dev,test] extras_require={ 'dev': ['check-manifest'], 'test': ['coverage'], }, )