aldepyde 0.0.0a38__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. aldepyde-0.0.0a38/LICENSE +21 -0
  2. aldepyde-0.0.0a38/PKG-INFO +48 -0
  3. aldepyde-0.0.0a38/README.md +9 -0
  4. aldepyde-0.0.0a38/aldepyde/Parsers/_mmcif_parser.py +0 -0
  5. aldepyde-0.0.0a38/aldepyde/Parsers/_pdb_parser.py +0 -0
  6. aldepyde-0.0.0a38/aldepyde/__init__.py +31 -0
  7. aldepyde-0.0.0a38/aldepyde/_config.py +113 -0
  8. aldepyde-0.0.0a38/aldepyde/biomolecule/Residue.py +9 -0
  9. aldepyde-0.0.0a38/aldepyde/biomolecule/_Atom.py +95 -0
  10. aldepyde-0.0.0a38/aldepyde/biomolecule/_AtomFactory.py +71 -0
  11. aldepyde-0.0.0a38/aldepyde/biomolecule/__init__.py +18 -0
  12. aldepyde-0.0.0a38/aldepyde/biomolecule/_amino_acid.py +6 -0
  13. aldepyde-0.0.0a38/aldepyde/biomolecule/_dna.py +6 -0
  14. aldepyde-0.0.0a38/aldepyde/biomolecule/_pdb.py +455 -0
  15. aldepyde-0.0.0a38/aldepyde/biomolecule/_rna.py +6 -0
  16. aldepyde-0.0.0a38/aldepyde/biomolecule/utils.py +60 -0
  17. aldepyde-0.0.0a38/aldepyde/cache/__init__.py +2 -0
  18. aldepyde-0.0.0a38/aldepyde/cache/_cache.py +257 -0
  19. aldepyde-0.0.0a38/aldepyde/cache/cachemanager.py +212 -0
  20. aldepyde-0.0.0a38/aldepyde/cache/downloader.py +13 -0
  21. aldepyde-0.0.0a38/aldepyde/cache/utils.py +32 -0
  22. aldepyde-0.0.0a38/aldepyde/configurable.py +7 -0
  23. aldepyde-0.0.0a38/aldepyde/data/RemoteFileHandler.py +32 -0
  24. aldepyde-0.0.0a38/aldepyde/data/__init__.py +1 -0
  25. aldepyde-0.0.0a38/aldepyde/data.py +148 -0
  26. aldepyde-0.0.0a38/aldepyde/databases/PDB.py +0 -0
  27. aldepyde-0.0.0a38/aldepyde/databases/RemoteFileHandler.py +43 -0
  28. aldepyde-0.0.0a38/aldepyde/databases/SCOPe_Astral.py +163 -0
  29. aldepyde-0.0.0a38/aldepyde/databases/UniRef.py +114 -0
  30. aldepyde-0.0.0a38/aldepyde/databases/__init__.py +0 -0
  31. aldepyde-0.0.0a38/aldepyde/databases/_database.py +76 -0
  32. aldepyde-0.0.0a38/aldepyde/env.py +43 -0
  33. aldepyde-0.0.0a38/aldepyde/fetcher/__init__.py +0 -0
  34. aldepyde-0.0.0a38/aldepyde/fetcher/test.py +2 -0
  35. aldepyde-0.0.0a38/aldepyde/json/CHG.json +25 -0
  36. aldepyde-0.0.0a38/aldepyde/json/Swiss_Prot.json +25 -0
  37. aldepyde-0.0.0a38/aldepyde/json/chemistry.json +4622 -0
  38. aldepyde-0.0.0a38/aldepyde/rand_utils/PolymerClassifier.py +94 -0
  39. aldepyde-0.0.0a38/aldepyde/rand_utils/PolymerConstraints.py +5 -0
  40. aldepyde-0.0.0a38/aldepyde/rand_utils/ProteinClassifier.py +39 -0
  41. aldepyde-0.0.0a38/aldepyde/rand_utils/ProteinGenerator.py +17 -0
  42. aldepyde-0.0.0a38/aldepyde/rand_utils/RandomProtein.py +404 -0
  43. aldepyde-0.0.0a38/aldepyde/rand_utils/ResidueGenerator.py +9 -0
  44. aldepyde-0.0.0a38/aldepyde/rand_utils/Sequence.py +2 -0
  45. aldepyde-0.0.0a38/aldepyde/rand_utils/__init__.py +7 -0
  46. aldepyde-0.0.0a38/aldepyde/stats/ProteinStats.py +89 -0
  47. aldepyde-0.0.0a38/aldepyde/stats/__init__.py +0 -0
  48. aldepyde-0.0.0a38/aldepyde/utils.py +275 -0
  49. aldepyde-0.0.0a38/aldepyde.egg-info/PKG-INFO +48 -0
  50. aldepyde-0.0.0a38/aldepyde.egg-info/SOURCES.txt +52 -0
  51. aldepyde-0.0.0a38/aldepyde.egg-info/dependency_links.txt +1 -0
  52. aldepyde-0.0.0a38/aldepyde.egg-info/top_level.txt +1 -0
  53. aldepyde-0.0.0a38/pyproject.toml +31 -0
  54. aldepyde-0.0.0a38/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Nate McMurray
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,48 @@
1
+ Metadata-Version: 2.4
2
+ Name: aldepyde
3
+ Version: 0.0.0a38
4
+ Summary: A package of chemistry and biochemical tools
5
+ Author-email: Nate McMurray <nate.mcmurray13@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2024 Nate McMurray
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: Homepage, https://github.com/cathepsin/aldepyde
29
+ Project-URL: Issues, https://github.com/cathepsin/aldepyde/issues
30
+ Project-URL: Changelog, https://github.com/cathepsin/aldepyde/blob/main/Changelog.md
31
+ Keywords: chemistry,biochemistry,protein,dna,rna,pdb,mmcif
32
+ Classifier: Programming Language :: Python :: 3
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Requires-Python: >=3.8
36
+ Description-Content-Type: text/markdown
37
+ License-File: LICENSE
38
+ Dynamic: license-file
39
+
40
+ <p align="left"><img src="https://github.com/cathepsin/aldepyde/blob/main/Aldepyde%20rough.png" height="250"/></p>
41
+
42
+ ### A module for mangling biomolecules
43
+ ---
44
+ AldePYde is a module of spite. Being frustrated with either the lack of obscure potential or the difficult and steep learning curve of other similar modules,
45
+ I made this. Here I present my various tools for chem/bioinformatics. This is all very much a work-in-progress, especially as I move over functionality from my
46
+ [deprecated module.](https://github.com/cathepsin/apalib)
47
+
48
+ Documentation to come soon 🎉
@@ -0,0 +1,9 @@
1
+ <p align="left"><img src="https://github.com/cathepsin/aldepyde/blob/main/Aldepyde%20rough.png" height="250"/></p>
2
+
3
+ ### A module for mangling biomolecules
4
+ ---
5
+ AldePYde is a module of spite. Being frustrated with either the lack of obscure potential or the difficult and steep learning curve of other similar modules,
6
+ I made this. Here I present my various tools for chem/bioinformatics. This is all very much a work-in-progress, especially as I move over functionality from my
7
+ [deprecated module.](https://github.com/cathepsin/apalib)
8
+
9
+ Documentation to come soon 🎉
File without changes
File without changes
@@ -0,0 +1,31 @@
1
+ __version__ = "0.0.0a2"
2
+ __author__ = "Nate McMurray"
3
+ __description__ = "A module for mangling biomolecules"
4
+
5
+ from ._config import _configuration
6
+ from aldepyde.cache.cachemanager import CacheManager
7
+
8
+
9
+ _cache_manager = CacheManager(initialize=False)
10
+ def create_cache(max_memory="2gib") -> CacheManager:
11
+ global _cache_manager
12
+ _cache_manager = _cache_manager(max_memory=max_memory,
13
+ initialize=True)
14
+ return _cache_manager
15
+
16
+ def get_cache() -> CacheManager:
17
+ global _cache_manager
18
+ return _cache_manager
19
+
20
+
21
+ from importlib import import_module
22
+
23
+ __all__ = ["rand_utils", "biomolecule", "fetcher"]
24
+
25
+ def __getattr__(name):
26
+ if name in __all__:
27
+ return import_module(f".{name}", __name__)
28
+ raise AttributeError(name)
29
+
30
+ def __dir__():
31
+ return sorted(list(globals().keys()) + __all__)
@@ -0,0 +1,113 @@
1
+ import re
2
+ import sys
3
+ import os
4
+ import json
5
+ # TODO Consider version information in config
6
+ # from aldepyde import __version__
7
+
8
+ class _configuration():
9
+
10
+ class VERSION_SETTINGS(): # There's probably a better way to do this, but it feels neat so I'm keeping it for now
11
+ def __init__(self):
12
+ self.settings = {
13
+ "verbose": False,
14
+ "angle_mode": "degrees",
15
+ "enable_cache": True,
16
+ "cache_path": os.path.join(os.getcwd(), "aldepyde_cache"),
17
+ "cache_max_memory": "500mib"
18
+ }
19
+ def __init__(self):
20
+ s = self.VERSION_SETTINGS()
21
+ self._settings = s.settings
22
+ self._setters = { # TODO Finish fixing this
23
+ "verbose": self.SetVerbose,
24
+ "angle_mode": self.SetAngleMode,
25
+ "enable_cache": self.SetEnableCache,
26
+ "cache_path": self.SetCachePath,
27
+ "cache_max_memory": self.SetCacheMaxMemory
28
+ }
29
+
30
+ # def _Verify(self, key, value) -> None:
31
+ # if value not in self._setters[key][1]:
32
+ # print(f"Incorrect value for ({key} <-- {value})\n\tAllowed values: {self._setters[key][1]}", file=sys.stderr)
33
+ # raise ValueError("See above")
34
+
35
+ def _Verify(self, key: str, accepted: list, value: object) -> None:
36
+ if True not in [True for x in accepted if value == x or (isinstance(x, type) and isinstance(value, x))]:
37
+ raise ValueError
38
+ # if value not in accepted:
39
+ # # print(f"Incorrect value for ({key} <-- {value})\n\tAllowed values: {accepted}", file=sys.stderr)
40
+ # raise ValueError(f"Incorrect value for ({key} <-- {value})\n\tAllowed values: {accepted}")
41
+
42
+ def __getitem__(self, item):
43
+ return self._settings[item]
44
+
45
+ def GetVerbose(self) -> bool:
46
+ return self._settings['verbose']
47
+
48
+ def SetVerbose(self, enabled: bool) -> None:
49
+ # I'm choosing to not be defensive here.
50
+ # Ima be honest, if you break the module with a verbosity boolean, that's on you
51
+ self._settings['verbose'] = enabled
52
+
53
+ def GetAngleMode(self) -> str:
54
+ return self._settings['angle_mode']
55
+
56
+ def SetAngleMode(self, a_type: str) -> None:
57
+ self._Verify('angle_mode', a_type)
58
+ self._settings['angle_mode'] = a_type
59
+
60
+ def SetEnableCache(self, enabled:bool) -> None:
61
+ self._Verify('enable_cache', [bool], enabled)
62
+ self._settings['enable_cache'] = enabled
63
+
64
+ def SetCachePath(self, path: str) -> None:
65
+ # TODO Consider making the new cache directory immediately
66
+ self._settings['cache_path'] = path
67
+
68
+ def GetCachePath(self) -> str:
69
+ return self._settings['cache_path']
70
+
71
+ def GetEnabledCache(self) -> bool:
72
+ return self._settings['enable_cache']
73
+
74
+ def SetCacheMaxMemory(self, max_memory: str|int) -> None:
75
+ max_memory = str(max_memory)
76
+ if re.fullmatch("[0-9]*[kmg]i?b", max_memory) is None:
77
+ raise ValueError
78
+ self._settings['cache_max_memory'] = max_memory
79
+
80
+ def GetCacheMaxMemory(self) -> str:
81
+ return self._settings['cache_max_memory']
82
+
83
+ ####################
84
+ def Load(self, s: dict | str, ignore_missing=False) -> None:
85
+ if isinstance(s, str):
86
+ if os.path.exists(s): # Try and read as a json file
87
+ with open(s, "r") as jp:
88
+ s = json.load(jp)
89
+ else: # Try and read as a json string
90
+ s = json.loads(s)
91
+ extra_settings = "".join([f"\t-{k}\n" for k in s.keys() if k not in self._setters.keys()])
92
+ if len(extra_settings) != 0:
93
+ print(f"Please remove the following config settings:\n{extra_settings}", file=sys.stderr)
94
+ raise KeyError("Input config does not match expectations")
95
+ missing_settings = "".join([f"\t-{k} : {v[1]}\n" for k, v in self._setters.items() if k not in s.keys()])
96
+ if len(missing_settings) != 0 and not ignore_missing:
97
+ print(f"Please include the following config settings:\n{missing_settings}", end="", file=sys.stderr)
98
+ raise KeyError("Input config does not match expectations")
99
+ if ignore_missing:
100
+ vs = self.VERSION_SETTINGS()
101
+ self._settings = vs.settings
102
+ for key in s.keys():
103
+ self._setters[key][0](s[key])
104
+
105
+ def GetConfig(self, as_string=False, indent="") -> dict | str:
106
+ if as_string:
107
+ return json.dumps(self._settings, indent=indent)
108
+ return self._settings
109
+
110
+ def Save(self, path: str="config.json", indent: str=""):
111
+ with open(path, "w") as jp:
112
+ json.dump(self._settings, jp, indent=indent)
113
+
@@ -0,0 +1,9 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ class Residue(ABC):
4
+
5
+ def __init__(self):
6
+ self.atoms = None
7
+ self.resID = None
8
+ self.resName = None
9
+
@@ -0,0 +1,95 @@
1
+ __all__ = ['Atom']
2
+
3
+ class Atom():
4
+ def __init__(self,
5
+ record_name: str = None,
6
+ serial: str = None,
7
+ name: str = None,
8
+ altLoc: str = None,
9
+ resName: str = None,
10
+ chainID: str = None,
11
+ resSeq: str = None,
12
+ iCode: str = None,
13
+ x: str = None,
14
+ y: str = None,
15
+ z: str = None,
16
+ occupancy: str = None,
17
+ tempFactor: str = None,
18
+ element: str = None,
19
+ charge: str = None
20
+ ):
21
+ self.SetRecordName(record_name)
22
+ self.SetSerial(serial)
23
+ self.SetAltLoc(altLoc)
24
+ self.SetResName(resName)
25
+ self.SetChainID(chainID)
26
+ self.SetResSeq(resSeq)
27
+ self.SetiCode(iCode)
28
+ self.SetXYZ(x, y, z)
29
+ self.SetOccupancy(occupancy)
30
+ self.SetTempFactor(tempFactor)
31
+ self.SetElement(element)
32
+ self.SetCharge(charge)
33
+ self.SetName(name) # Do this last to extract the element
34
+
35
+ def SetRecordName(self, record_name: str) -> None:
36
+ self.record_name = record_name
37
+
38
+ def SetSerial(self, serial: str | int | None) -> None:
39
+ self.serial = int(serial)
40
+
41
+ def SetName(self, name) -> None:
42
+ # TODO Extrapolate the element from the name
43
+ self.name = name
44
+
45
+ def SetAltLoc(self, altLoc: str | None) -> None:
46
+ self.altLoc = altLoc
47
+
48
+ def SetResName(self, resName: str | None) -> None:
49
+ self.resName = resName
50
+
51
+ def SetChainID(self, chainID: str | None) -> None:
52
+ self.chainID = chainID
53
+
54
+ def SetResSeq(self, resSeq: str | None) -> None:
55
+ self.resSeq = resSeq
56
+
57
+ def SetiCode(self, iCode: str | None) -> None:
58
+ self.iCode = iCode
59
+
60
+ def SetXYZ(self, x: str | float | None, y: str | float | None, z: str | float | None) -> None:
61
+ self.x = float(x) if x is not None else None
62
+ self.y = float(y) if y is not None else None
63
+ self.z = float(z) if z is not None else None
64
+
65
+ def SetX(self, x: str | float | None):
66
+ self.x = float(x) if x is not None else None
67
+
68
+ def SetY(self, x: str | float | None):
69
+ self.x = float(x) if x is not None else None
70
+
71
+ def SetZ(self, x: str | float | None):
72
+ self.x = float(x) if x is not None else None
73
+
74
+ def SetOccupancy(self, occupancy: str | float | None) -> None:
75
+ self.occupancy = float(occupancy) if occupancy is not None else None
76
+
77
+ def SetTempFactor(self, tempFactor: str | float | None) -> None:
78
+ self.tempFactor = float(tempFactor) if tempFactor is not None else None
79
+
80
+ def SetElement(self, element: str | None) -> None:
81
+ self.element = element
82
+
83
+ def SetCharge(self, charge: str | None) -> None:
84
+ self.charge = charge
85
+
86
+ def Distance(self, other: 'Atom') -> float:
87
+ return ((self.x - other.x)**2 + (self.y - other.y)**2 + (self.z - other.z)**2)**(.5)
88
+
89
+ # In case you want to treat aldepyde like that other importable module that shall not be named
90
+ def __sub__(self, other):
91
+ return self.Distance(other)
92
+
93
+ def __str__(self):
94
+ return f"{self.record_name} {self.serial} {self.resName}"
95
+
@@ -0,0 +1,71 @@
1
+ from aldepyde.biomolecule._Atom import Atom as atom
2
+
3
+ __all__ = ['CreateAtom', 'CreateEnforced', 'CreateDummy']
4
+
5
+ def CreateAtom( # General atom
6
+ record_name: str| None = None,
7
+ serial: str | int | None = None,
8
+ name: str | None = None,
9
+ altLoc: str | None = None,
10
+ resName: str | None = None,
11
+ chainID: str | None = None,
12
+ resSeq: str | None = None,
13
+ iCode: str | None = None,
14
+ x: str | float | None = None,
15
+ y: str | float | None = None,
16
+ z: str | float | None = None,
17
+ occupancy: str | float | None = None,
18
+ tempFactor: str | float | None = None,
19
+ element: str | None = None,
20
+ charge: str | None = None
21
+ ) -> atom:
22
+ return atom(record_name=record_name, serial=serial, name=name, altLoc=altLoc, resName=resName,
23
+ chainID=chainID, resSeq=resSeq, iCode=iCode, x=x, y=y, z=z,
24
+ occupancy=occupancy, tempFactor=tempFactor, element=element,
25
+ charge=charge)
26
+
27
+ def CreateEnforced( # The type of atom from the parsers. Enforce what's required by PDB standard
28
+ serial: str,
29
+ name: str,
30
+ altLoc: str,
31
+ resName: str,
32
+ chainID: str,
33
+ resSeq: str,
34
+ iCode: str,
35
+ x: str,
36
+ y: str,
37
+ z: str,
38
+ occupancy: str,
39
+ tempFactor: str,
40
+ record_name: str = None,
41
+ element: str | None = None,
42
+ charge: str | None = None
43
+ ) -> atom:
44
+ return atom(serial=serial, name=name, altLoc=altLoc, resName=resName,
45
+ chainID=chainID, resSeq=resSeq, iCode=iCode, x=x, y=y, z=z,
46
+ occupancy=occupancy, tempFactor=tempFactor, element=element,
47
+ charge=charge, record_name=record_name)
48
+
49
+
50
+ def CreateDummy( # As the name implies
51
+ record_name: str| None = "HETATM",
52
+ serial: str | int = "-1",
53
+ name: str = "PS",
54
+ altLoc: str = "",
55
+ resName: str = "PSD",
56
+ chainID: str = "$P",
57
+ resSeq: str = "PSD",
58
+ iCode: str = "",
59
+ x: str | float = "0.0",
60
+ y: str | float = "0.0",
61
+ z: str | float = "0.0",
62
+ occupancy: str | float = "0.0",
63
+ tempFactor: str | float = "0.0",
64
+ element: str | None = "PS",
65
+ charge: str | None = None
66
+ ) -> atom:
67
+ return atom(record_name=record_name, serial=serial, name=name, altLoc=altLoc, resName=resName,
68
+ chainID=chainID, resSeq=resSeq, iCode=iCode, x=x, y=y, z=z,
69
+ occupancy=occupancy, tempFactor=tempFactor, element=element,
70
+ charge=charge)
71
+
@@ -0,0 +1,18 @@
1
+ from ._amino_acid import *
2
+ from ._Atom import *
3
+ from ._AtomFactory import *
4
+ from ._dna import *
5
+ from ._pdb import *
6
+ # from .Residue import * # This probably doesn't need to be revealed to the user
7
+ from ._rna import *
8
+
9
+ __all__ = list(set(_amino_acid.__all__.copy()) |
10
+ set(_Atom.__all__.copy()) |
11
+ set(_AtomFactory.__all__.copy()) |
12
+ set(_dna.__all__.copy()) |
13
+ set(_pdb.__all__.copy()) |
14
+ set(_rna.__all__.copy()))
15
+
16
+ import sys
17
+
18
+ sys.stderr.write("Note that the `biomolecule` submodule is not yet fully tested and may be unstable")
@@ -0,0 +1,6 @@
1
+ from aldepyde.biomolecule.Residue import Residue
2
+
3
+ __all__ = ['amino_acid']
4
+
5
+ class amino_acid(Residue):
6
+ pass
@@ -0,0 +1,6 @@
1
+ from aldepyde.biomolecule.Residue import Residue
2
+
3
+ __all__ = ['dna']
4
+
5
+ class dna(Residue):
6
+ pass