cosmopharm 0.1.0a1__py3-none-any.whl → 0.1.2__py3-none-any.whl
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.
- cosmopharm/actmodels/actmodel.py +11 -0
- cosmopharm/actmodels/cosmo.py +2 -4
- cosmopharm/equilibrium/lle.py +122 -70
- cosmopharm/equilibrium/sle.py +1 -1
- cosmopharm-0.1.2.dist-info/METADATA +39 -0
- cosmopharm-0.1.2.dist-info/RECORD +18 -0
- {cosmopharm-0.1.0a1.dist-info → cosmopharm-0.1.2.dist-info}/WHEEL +1 -1
- cosmopharm-0.1.0a1.dist-info/METADATA +0 -150
- cosmopharm-0.1.0a1.dist-info/RECORD +0 -18
- {cosmopharm-0.1.0a1.dist-info → cosmopharm-0.1.2.dist-info/licenses}/LICENSE +0 -0
- {cosmopharm-0.1.0a1.dist-info → cosmopharm-0.1.2.dist-info}/top_level.txt +0 -0
cosmopharm/actmodels/actmodel.py
CHANGED
@@ -35,6 +35,17 @@ class ActModel:
|
|
35
35
|
# Fill gmix with calculated values where the mask is True
|
36
36
|
gmix[mask] = _gmix
|
37
37
|
return gmix[0] if is_scalar else gmix
|
38
|
+
|
39
|
+
def thermofac(self, T, x):
|
40
|
+
""" Approximate thermodynamic factor
|
41
|
+
Simple derivative form, when no analytical equation is available.
|
42
|
+
"""
|
43
|
+
def f(x1):
|
44
|
+
x = np.array([x1, 1-x1])
|
45
|
+
return self.lngamma(T, x)[0]
|
46
|
+
h, x = 0.0001, x[0]
|
47
|
+
dy = (f(x+h)-f(x-h))/(2*h)
|
48
|
+
return 1 + x * dy
|
38
49
|
|
39
50
|
|
40
51
|
# =============================================================================
|
cosmopharm/actmodels/cosmo.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
import numpy as np
|
3
2
|
import cCOSMO
|
4
3
|
|
@@ -6,9 +5,9 @@ from typing import List, Union, Literal
|
|
6
5
|
from .actmodel import ActModel
|
7
6
|
from ..components import Component
|
8
7
|
|
9
|
-
|
10
8
|
class COSMOSAC(ActModel):
|
11
|
-
|
9
|
+
|
10
|
+
# Handle invalid values for free volume calculation
|
12
11
|
class InvalidFreeVolumeParametersException(Exception):
|
13
12
|
pass
|
14
13
|
|
@@ -67,7 +66,6 @@ class COSMOSAC(ActModel):
|
|
67
66
|
(can replace ln_gamma_comb of normal COSMO-SAC) - Kuo2013
|
68
67
|
x, v_298, v_hc are 1D arrays (number of elements = number of components)
|
69
68
|
"""
|
70
|
-
# TODO: Make sure, that v_298 and v_hc are provided, else "FV" not possible
|
71
69
|
self.validate_free_volume_parameters() # Ensure components are valid before proceeding
|
72
70
|
v_298 = np.array([comp.v_298 for comp in self.mixture])
|
73
71
|
v_hc = np.array([comp.v_hc for comp in self.mixture])
|
cosmopharm/equilibrium/lle.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import numpy as np
|
2
2
|
import pandas as pd
|
3
3
|
from scipy.optimize import least_squares, root
|
4
|
-
from typing import Union, Optional, Type, List
|
4
|
+
from typing import Union, Optional, Type, List, Dict
|
5
5
|
|
6
6
|
from ..components import Component
|
7
7
|
from ..actmodels import ActModel
|
@@ -17,6 +17,104 @@ class LLE:
|
|
17
17
|
self.mixture = mixture
|
18
18
|
self._validate_arguments()
|
19
19
|
|
20
|
+
def miscibility(self,
|
21
|
+
T: float,
|
22
|
+
x0: np.ndarray = None,
|
23
|
+
x0_type: str = 'mole',
|
24
|
+
max_gap: float = 0.1,
|
25
|
+
max_gap_type: str = 'mole',
|
26
|
+
max_T: float = 1000,
|
27
|
+
dT: float = 10,
|
28
|
+
exponent: float = 1
|
29
|
+
) -> pd.DataFrame:
|
30
|
+
""" Calculate miscibility """
|
31
|
+
self.config = getattr(self.actmodel, 'config', '')
|
32
|
+
Mw = np.array([c.Mw for c in self.mixture])
|
33
|
+
self.is_valid_Mw = self.is_valid_numpy_array(Mw)
|
34
|
+
res = {'binodal':[], 'spinodal':[]}
|
35
|
+
var = 'x' if max_gap_type == 'mole' else 'w'
|
36
|
+
print()
|
37
|
+
print("Calculating LLE...")
|
38
|
+
|
39
|
+
# Define column names
|
40
|
+
binodal_columns = ['T', 'xL1', 'xL2']
|
41
|
+
if self.is_valid_Mw:
|
42
|
+
binodal_columns += ['wL1', 'wL2']
|
43
|
+
|
44
|
+
# Check for valid molar masses
|
45
|
+
if x0_type == 'weight':
|
46
|
+
if self.is_valid_Mw:
|
47
|
+
x0 = self.convert_to_mole_fractions(x0, self.mixture.Mw)
|
48
|
+
else:
|
49
|
+
raise ValueError("Molar masses are not available for conversion from weight to mole fraction.")
|
50
|
+
# =============================================================================
|
51
|
+
# TODO: Implement all edge cases (no LLE, bad approximation, ....)
|
52
|
+
# TODO: Improve code structure
|
53
|
+
# Approximate initial value for LLE
|
54
|
+
if x0 is None:
|
55
|
+
print("...searching for suitable initial value...")
|
56
|
+
x0 = self.approx_init_x0(T)
|
57
|
+
|
58
|
+
if any(x is None for x in x0):
|
59
|
+
print("...no initial value at T0 was found. Try another T0.")
|
60
|
+
return pd.DataFrame(columns=binodal_columns)
|
61
|
+
|
62
|
+
# Check if initial guess is reasonable - otherwise increase T
|
63
|
+
# TODO: Check whether it might be an LCST if isLower
|
64
|
+
binodal = self.solve_lle(T, x0, show_output=False)
|
65
|
+
isEqual = np.diff(binodal['x'])[0] < 1e-8 # check if both phases have equal composition
|
66
|
+
if isEqual:
|
67
|
+
print("...no initial value at T0 was found. Try another T0.")
|
68
|
+
return pd.DataFrame(columns=binodal_columns)
|
69
|
+
isLower = min(binodal['x']) < min(x0) # lower bound below min(x0)
|
70
|
+
while isLower and T <= max_T:
|
71
|
+
print('LLE: ', f"{T=:.2f}", "...no feasbible initial value found.")
|
72
|
+
T += 10 # Increase T by 10
|
73
|
+
x0 = self.approx_init_x0(T)
|
74
|
+
binodal = self.solve_lle(T, x0, show_output=False)
|
75
|
+
print("Suitable initial value found! Proceed with calculating LLE...")
|
76
|
+
# =============================================================================
|
77
|
+
# First iteration step
|
78
|
+
binodal = self.solve_lle(T, x0)
|
79
|
+
gap = np.diff(binodal[var])[0]
|
80
|
+
res['binodal'].append((T, *[val for vals in binodal.values() for val in vals]))
|
81
|
+
|
82
|
+
# Subsequent iteration steps
|
83
|
+
while gap > max_gap and T <= max_T:
|
84
|
+
T += dT * gap**exponent
|
85
|
+
x0 = binodal['x']
|
86
|
+
binodal = self.solve_lle(T, x0)
|
87
|
+
gap = np.diff(binodal[var])[0]
|
88
|
+
res['binodal'].append((T, *[val for vals in binodal.values() for val in vals]))
|
89
|
+
|
90
|
+
# Convert lists to DataFrames
|
91
|
+
res = pd.DataFrame(res['binodal'], columns=binodal_columns)
|
92
|
+
return res
|
93
|
+
|
94
|
+
# =============================================================================
|
95
|
+
# MATHEMATICS
|
96
|
+
# =============================================================================
|
97
|
+
|
98
|
+
def solve_lle(self, T: float, x0: np.ndarray, show_output=True) -> Dict[str, np.ndarray]:
|
99
|
+
""" Solve for liquid-liquid equilibrium (LLE) at a given temperature and initial composition. """
|
100
|
+
binodal = {'x': self.binodal(T, x0)}
|
101
|
+
output = [f"{k}={v:.4f}" for k,v in zip(['xL1', 'xL2'], binodal['x'])]
|
102
|
+
|
103
|
+
if self.is_valid_Mw:
|
104
|
+
binodal['w'] = self.actmodel._convert(binodal['x'])
|
105
|
+
output += [f"{k}={v:.4f}" for k,v in zip(['wL1', 'wL2'], binodal['w'])]
|
106
|
+
|
107
|
+
if show_output:
|
108
|
+
prefix = f'LLE ({self.config})' if self.config else 'LLE'
|
109
|
+
print(f'{prefix}: ', f"{T=:.2f}", *output)
|
110
|
+
return binodal
|
111
|
+
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
# =============================================================================
|
116
|
+
# THERMODYNAMICS
|
117
|
+
# =============================================================================
|
20
118
|
def fobj_binodal(self, x1, T):
|
21
119
|
# Equilibrium: Isoactivity criterion (aL1 - aL2 = 0)
|
22
120
|
x = np.array([x1, 1-x1])
|
@@ -29,29 +127,23 @@ class LLE:
|
|
29
127
|
x = np.array([x1, 1-x1])
|
30
128
|
return self.actmodel.thermofac(T, x)
|
31
129
|
|
32
|
-
def binodal(self, T, x0=None
|
130
|
+
def binodal(self, T, x0=None):
|
33
131
|
if x0 is None:
|
34
|
-
x0 = [0.1, 0.999]
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
res = least_squares(self.fobj_binodal, x0, args=(T,), **kwargs)
|
39
|
-
# print(res.nfev)
|
40
|
-
return res.x, res.nfev
|
41
|
-
else:
|
42
|
-
kwargs = dict(method='krylov', options={'maxiter': 5})
|
43
|
-
res = root(self.fobj_binodal, x0, args=(T,), **kwargs)
|
44
|
-
# print(res.nit)
|
45
|
-
return res.x, 30
|
132
|
+
x0 = [0.1, 0.999]
|
133
|
+
kwargs = dict(bounds=(0,1), ftol=1e-15, xtol=1e-15)
|
134
|
+
res = least_squares(self.fobj_binodal, x0, args=(T,), **kwargs)
|
135
|
+
return res.x
|
46
136
|
|
47
|
-
def spinodal(self, x0=None):
|
137
|
+
def spinodal(self, T, x0=None):
|
48
138
|
if x0 is None:
|
49
|
-
x0 = self.binodal()
|
50
|
-
|
139
|
+
x0 = self.binodal(T, x0)
|
140
|
+
kwargs = dict(bounds=(0,1), ftol=1e-15, xtol=1e-15)
|
141
|
+
res = least_squares(self.fobj_spinodal, x0, args=(T,), **kwargs)
|
142
|
+
return res.x
|
143
|
+
|
51
144
|
|
52
145
|
# =============================================================================
|
53
|
-
#
|
54
|
-
# TODO: (2) Overall improve this code to match the SLE code
|
146
|
+
# AUXILLIARY FUNCTIONS
|
55
147
|
# =============================================================================
|
56
148
|
def approx_init_x0(self, T):
|
57
149
|
x1 = spacing(0,1,51,'poly',n=3)
|
@@ -59,59 +151,10 @@ class LLE:
|
|
59
151
|
xL, xR, yL, yR = estimate_lle_from_gmix(x1, gmix, rough=True)
|
60
152
|
return xL, xR
|
61
153
|
|
62
|
-
def solve_lle(self, T, x0, solver='least_squares', info=True):
|
63
|
-
binodal_x, nfev = self.binodal(T, x0, solver)
|
64
|
-
binodal_w = self.actmodel._convert(binodal_x)
|
65
|
-
formatted_w_binodal = [f"wL{i+1}={value:.4f}" for i, value in enumerate(binodal_w)]
|
66
|
-
formatted_x_binodal = [f"xL{i+1}={value:.6f}" for i, value in enumerate(binodal_x)]
|
67
|
-
msg = ('LLE: ', f"{T=:.2f}", *formatted_w_binodal, *formatted_x_binodal)
|
68
|
-
if info:
|
69
|
-
print(*msg)
|
70
|
-
return binodal_x, binodal_w, nfev
|
71
|
-
return binodal_x, binodal_w, nfev, msg
|
72
|
-
|
73
|
-
def miscibility(self, T, x0=None, max_gap=0.1, max_T=500, dT=25, exponent=2):
|
74
|
-
""" Calculate miscibility """
|
75
|
-
print()
|
76
|
-
print("Calculating LLE...")
|
77
|
-
res = []
|
78
|
-
|
79
|
-
if x0 is None:
|
80
|
-
print("...searching for suitable initial value...")
|
81
|
-
x0 = self.approx_init_x0(T)
|
82
|
-
binodal_x, binodal_w, nfev, msg = self.solve_lle(T, x0, info=False)
|
83
|
-
|
84
|
-
# Check if initial guess is reasonalble - otherwise increase T
|
85
|
-
while binodal_x[0] < x0[0] and T <= max_T:
|
86
|
-
print('LLE: ', f"{T=:.2f}", "...no feasbible initial value found.")
|
87
|
-
T += 10 # Increase T by 10
|
88
|
-
x0 = self.approx_init_x0(T)
|
89
|
-
binodal_x, binodal_w, nfev, msg = self.solve_lle(T, x0, info=False)
|
90
|
-
print("Suitable initial value found! Proceed with calculating LLE...")
|
91
|
-
print(*msg)
|
92
|
-
gap = np.diff(binodal_w)[0]
|
93
|
-
res.append((T, *binodal_w, *binodal_x))
|
94
|
-
|
95
|
-
while gap > max_gap and T <= max_T:
|
96
|
-
solver = 'least_squares' if nfev <= 30 else 'root'
|
97
|
-
solver = 'least_squares'
|
98
|
-
# print(solver)
|
99
|
-
T += dT * gap**exponent
|
100
|
-
x0 = binodal_x
|
101
|
-
binodal_x, binodal_w, nfev = self.solve_lle(T, x0, solver)
|
102
|
-
gap = np.diff(binodal_w)[0]
|
103
|
-
res.append((T, *binodal_w, *binodal_x))
|
104
|
-
|
105
|
-
columns = ['T', 'wL1', 'wL2', 'xL1', 'xL2']
|
106
|
-
res = pd.DataFrame(res, columns=columns)
|
107
|
-
return res
|
108
|
-
|
109
|
-
# =============================================================================
|
110
|
-
# AUXILLIARY FUNCTIONS
|
111
|
-
# =============================================================================
|
112
154
|
def _validate_arguments(self):
|
113
155
|
"""Validate the arguments for the LLE class."""
|
114
|
-
# TODO: Insert case where both actmodel and mixture are provided
|
156
|
+
# TODO: Insert case where both actmodel and mixture are provided
|
157
|
+
# (check if acmodel.mixture == mixture, if not raise warning)
|
115
158
|
if isinstance(self.actmodel, ActModel):
|
116
159
|
# If actmodel is an instance of ActModel
|
117
160
|
self.mixture: List[Component] = self.mixture or self.actmodel.mixture
|
@@ -124,3 +167,12 @@ class LLE:
|
|
124
167
|
# If actmodel is neither an instance nor a subclass of ActModel
|
125
168
|
err = "'actmodel' must be an instance or a subclass of 'ActModel'"
|
126
169
|
raise ValueError(err)
|
170
|
+
|
171
|
+
def is_valid_numpy_array(self, arr: np.ndarray) -> bool:
|
172
|
+
"""Check if a numpy array contains only numbers and no None values."""
|
173
|
+
if not isinstance(arr, np.ndarray):
|
174
|
+
return False
|
175
|
+
if arr.dtype == object: # Check if the array contains objects (which could include None)
|
176
|
+
return not np.any(arr == None)
|
177
|
+
else:
|
178
|
+
return np.issubdtype(arr.dtype, np.number)
|
cosmopharm/equilibrium/sle.py
CHANGED
@@ -77,7 +77,7 @@ class SLE:
|
|
77
77
|
x0 = out if not is_iterable else x0
|
78
78
|
res = {key: arg, lock: out, 'vary': self._vary}
|
79
79
|
res['w'] = self.actmodel._convert(res['x'])[0]
|
80
|
-
text = (f"T={res['T']:.2f}", f"
|
80
|
+
text = (f"T={res['T']:.2f}", f"x={res['x']:.4f}", f"w={res['w']:.4f}")
|
81
81
|
if self.show_progress:
|
82
82
|
print(f'SLE ({self.config}): ', *text)
|
83
83
|
yield res
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: cosmopharm
|
3
|
+
Version: 0.1.2
|
4
|
+
Summary: Predictive modeling for drug-polymer compatibility in pharmaceutical formulations using COSMO-SAC.
|
5
|
+
Home-page: https://github.com/ivanantolo/cosmopharm
|
6
|
+
Author: Ivan Antolovic
|
7
|
+
Author-email: Ivan.Antolovic@tu-berlin.de
|
8
|
+
Maintainer: Martin Klajmon
|
9
|
+
Maintainer-email: Martin.Klajmon@vscht.cz
|
10
|
+
License: MIT
|
11
|
+
Keywords: Drug-Polymer Compatibility,Amorphous Solid Dispersions,Pharmaceutical Formulation,COSMO-SAC Model,Solubility Prediction,Miscibility Analysis,Phase Behavior Prediction,Pharmaceutical Sciences,Drug Formulation Research,Polymer Science,Predictive Modeling in Pharma,Drug Development Tools,Biopharmaceuticals
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
14
|
+
Classifier: Intended Audience :: Healthcare Industry
|
15
|
+
Classifier: Intended Audience :: Developers
|
16
|
+
Classifier: Intended Audience :: Education
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
22
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
23
|
+
Classifier: Programming Language :: Python :: 3.8
|
24
|
+
Classifier: Programming Language :: Python :: 3.9
|
25
|
+
Classifier: Programming Language :: Python :: 3.10
|
26
|
+
Classifier: Programming Language :: Python :: 3.11
|
27
|
+
Classifier: Programming Language :: Python :: 3.12
|
28
|
+
Classifier: Programming Language :: Python :: 3.13
|
29
|
+
Requires-Python: >=3.8
|
30
|
+
Description-Content-Type: text/markdown
|
31
|
+
License-File: LICENSE
|
32
|
+
Requires-Dist: numpy>=1.15
|
33
|
+
Requires-Dist: pandas>=1.0
|
34
|
+
Requires-Dist: scipy>=1.4
|
35
|
+
Requires-Dist: openpyxl>=3.0
|
36
|
+
Provides-Extra: examples
|
37
|
+
Requires-Dist: matplotlib>=3.0; extra == "examples"
|
38
|
+
Dynamic: description-content-type
|
39
|
+
Dynamic: license-file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
cosmopharm/__init__.py,sha256=sdgLzbqylG8DDAJ5J96YiO4egn9xVJTx2uzaIZ8qj4g,68
|
2
|
+
cosmopharm/components.py,sha256=wEQQ0ZNOrFvG9SdhKAzBgqTbT6DtuoTreNBEdLw8Lm0,981
|
3
|
+
cosmopharm/actmodels/__init__.py,sha256=9iH67yrdSaf10Fj8LwRikUDUMeMxsvUHRPEaWc3384k,59
|
4
|
+
cosmopharm/actmodels/actmodel.py,sha256=rm3-3oWX71IrgdxjcO90bAtlBBsYWOu4cr_oIQH-zZ4,5437
|
5
|
+
cosmopharm/actmodels/cosmo.py,sha256=Dj7kjFYSvJWESG2Y_dP5b6yCCpWYzD5tkh3ATvXIfjg,5873
|
6
|
+
cosmopharm/equilibrium/__init__.py,sha256=5NsIbQEwELjeeoFEiWelnzHnhTzt5zsBh3r5icn_AIQ,44
|
7
|
+
cosmopharm/equilibrium/lle.py,sha256=-xGnJg_7paMPMVaL1pzkF1UNWtnAPSnk1UbMPB11eqM,7814
|
8
|
+
cosmopharm/equilibrium/sle.py,sha256=ScyVq0hNqpWgAbWSKoPARZdO2wf3I9uGzv8L9oDlCtY,11187
|
9
|
+
cosmopharm/utils/__init__.py,sha256=qfUPovmZ9ukj6ZbTfndUOH6EX0ZrzRNjLZEDIVS8UvM,113
|
10
|
+
cosmopharm/utils/convert.py,sha256=V-7jY-Sb7C38N5bQcp1c27EOiVJfriP6zRbLAIKgrdE,2470
|
11
|
+
cosmopharm/utils/helpers.py,sha256=CXUTh3jVStHno_W_Z7o8RvQ6SveSjw_Ss31CkvfROfs,1460
|
12
|
+
cosmopharm/utils/lle_scanner.py,sha256=So9FCxLLcHmBkuF6zggMo3W3gFBocEmuRzyxVGy69JM,6587
|
13
|
+
cosmopharm/utils/spacing.py,sha256=vtM9b4wodpFGkZFGGLhiSXT51Zl6fNK2Og4oRcbLFH4,9222
|
14
|
+
cosmopharm-0.1.2.dist-info/licenses/LICENSE,sha256=25ZCycfBgonIECGYnZTy72eJVfzcHCEOz3DM9sTx7do,1162
|
15
|
+
cosmopharm-0.1.2.dist-info/METADATA,sha256=D_zX08jgnOexeqVxwOjb1xh2hGsNrlicM0znVmAWEmY,1899
|
16
|
+
cosmopharm-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
17
|
+
cosmopharm-0.1.2.dist-info/top_level.txt,sha256=MGniVgvs1yq4sn6HQ7ErDVYV_g3st3Fs8TTFHOJVQ9I,11
|
18
|
+
cosmopharm-0.1.2.dist-info/RECORD,,
|
@@ -1,150 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.1
|
2
|
-
Name: cosmopharm
|
3
|
-
Version: 0.1.0a1
|
4
|
-
Summary: Predictive modeling for drug-polymer compatibility in pharmaceutical formulations using COSMO-SAC.
|
5
|
-
Home-page: https://github.com/ivanantolo/cosmopharm,
|
6
|
-
Author: Ivan Antolovic
|
7
|
-
Author-email: Ivan.Antolovic@tu-berlin.de
|
8
|
-
Maintainer: Martin Klajmon
|
9
|
-
Maintainer-email: Martin.Klajmon@vscht.cz
|
10
|
-
License: MIT
|
11
|
-
Keywords: Drug-Polymer Compatibility,Amorphous Solid Dispersions,Pharmaceutical Formulation,COSMO-SAC Model,Solubility Prediction,Miscibility Analysis,Phase Behavior Prediction,Pharmaceutical Sciences,Drug Formulation Research,Polymer Science,Predictive Modeling in Pharma,Drug Development Tools,Biopharmaceuticals
|
12
|
-
Classifier: Development Status :: 3 - Alpha
|
13
|
-
Classifier: Intended Audience :: Science/Research
|
14
|
-
Classifier: Intended Audience :: Healthcare Industry
|
15
|
-
Classifier: Intended Audience :: Developers
|
16
|
-
Classifier: Intended Audience :: Education
|
17
|
-
Classifier: License :: OSI Approved :: MIT License
|
18
|
-
Classifier: Topic :: Scientific/Engineering
|
19
|
-
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
20
|
-
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
21
|
-
Classifier: Programming Language :: Python :: 3
|
22
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
23
|
-
Classifier: Programming Language :: Python :: 3.8
|
24
|
-
Classifier: Programming Language :: Python :: 3.9
|
25
|
-
Classifier: Programming Language :: Python :: 3.10
|
26
|
-
Classifier: Programming Language :: Python :: 3.11
|
27
|
-
Classifier: Programming Language :: Python :: 3.12
|
28
|
-
Classifier: Programming Language :: Python :: 3.13
|
29
|
-
Requires-Python: >=3.8
|
30
|
-
Description-Content-Type: text/markdown
|
31
|
-
License-File: LICENSE
|
32
|
-
Requires-Dist: numpy >=1.15
|
33
|
-
Requires-Dist: pandas >=1.0
|
34
|
-
Requires-Dist: scipy >=1.4
|
35
|
-
Requires-Dist: openpyxl >=3.0
|
36
|
-
Provides-Extra: examples
|
37
|
-
Requires-Dist: matplotlib >=3.0 ; extra == 'examples'
|
38
|
-
|
39
|
-
# COSMOPharm
|
40
|
-
|
41
|
-
Welcome to the COSMOPharm package, accompanying [our paper in *Molecular Pharmaceutics*](https://dx.doi.org/10.1021/acs.jctc.9b01016). This project and its associated publication offer insights and a practical toolkit for researching drug-polymer and drug-solvent systems, aiming to provide the scientific community with the means to reproduce our findings and further the development of COSMO-SAC-based models.
|
42
|
-
|
43
|
-
<p align="center">
|
44
|
-
<!-- <img src="https://github.com/usnistgov/COSMOSAC/raw/master/JCTC2020.PNG" alt="TOC Figure" width="500"> -->
|
45
|
-
<img src="https://github.com/usnistgov/COSMOSAC/raw/master/JCTC2020.PNG" alt="TOC Figure">
|
46
|
-
</p>
|
47
|
-
|
48
|
-
## About
|
49
|
-
|
50
|
-
COSMOPharm is a Python package designed to streamline the predictive modeling of drug-polymer compatibility, crucial for the development of pharmaceutical amorphous solid dispersions. Apart from that, it can also be used for the miscibility/solubility of drugs with/in common solvents. Leveraging the COSMO-SAC (Conductor-like Screening Model Segment Activity Coefficient) model, COSMOPharm offers a robust platform for scientists and researchers to predict solubility, miscibility, and phase behavior in drug formulation processes.
|
51
|
-
|
52
|
-
## Features
|
53
|
-
|
54
|
-
- **Compatibility Prediction**: Utilize open-source COSMO-SAC model for prediction of drug-polymer compatibility.
|
55
|
-
- **Solubility Calculation**: Calculate drug-polymer solubilities to guide the selection of suitable polymers for drug formulations.
|
56
|
-
- **Miscibility and Phase Behavior Analysis**: Analyze the miscibility of drug-polymer pairs and understand their phase behavior under various conditions.
|
57
|
-
- **User-friendly Interface**: Easy-to-use functions and comprehensive documentation to facilitate research and development in pharmaceutical sciences.
|
58
|
-
|
59
|
-
## Installation
|
60
|
-
|
61
|
-
Install COSMOPharm with pip:
|
62
|
-
|
63
|
-
`pip install cosmopharm`
|
64
|
-
|
65
|
-
Ensure you have installed the `cCOSMO` library as per instructions on the [COSMOSAC GitHub page](https://github.com/usnistgov/COSMOSAC).
|
66
|
-
|
67
|
-
## Quick Start
|
68
|
-
|
69
|
-
Get started with COSMOPharm using the minimal example below, which demonstrates how to calculate the solubility of a drug in a polymer. This example succinctly showcases the use of COSMOPharm for solubility calculations:
|
70
|
-
|
71
|
-
|
72
|
-
```python
|
73
|
-
import matplotlib.pyplot as plt
|
74
|
-
import cCOSMO
|
75
|
-
from cosmopharm import SLE, COSMOSAC
|
76
|
-
from cosmopharm.utils import create_components, read_params
|
77
|
-
|
78
|
-
# Define components
|
79
|
-
names = ['SIM','PLGA50']
|
80
|
-
params_file = "data/sle/table_params.xlsx"
|
81
|
-
|
82
|
-
# Load parameters and create components
|
83
|
-
parameters = read_params(params_file)
|
84
|
-
mixture = create_components(names, parameters)
|
85
|
-
|
86
|
-
# Initialize COSMO-SAC model - replace paths with your local paths to COSMO profiles
|
87
|
-
db = cCOSMO.DelawareProfileDatabase(
|
88
|
-
"./profiles/_import_methods/UD/complist.txt",
|
89
|
-
"./profiles/_import_methods/UD/sigma3/")
|
90
|
-
|
91
|
-
for name in names:
|
92
|
-
iden = db.normalize_identifier(name)
|
93
|
-
db.add_profile(iden)
|
94
|
-
COSMO = cCOSMO.COSMO3(names, db)
|
95
|
-
|
96
|
-
# Setup the COSMO-SAC model with components
|
97
|
-
actmodel = COSMOSAC(COSMO, mixture=mixture)
|
98
|
-
|
99
|
-
# Calculate solubility (SLE)
|
100
|
-
sle = SLE(actmodel=actmodel)
|
101
|
-
solubility = sle.solubility(mix='real')
|
102
|
-
|
103
|
-
# Output the solubility
|
104
|
-
print(solubility[['T', 'w', 'x']].to_string(index=False))
|
105
|
-
|
106
|
-
# Plot results
|
107
|
-
plt.plot(*solubility[['w','T']].values.T,'.-', label='Solubility (w)')
|
108
|
-
|
109
|
-
# Settings
|
110
|
-
plt.xlim(0,1)
|
111
|
-
plt.ylim(300,500)
|
112
|
-
# Adding title and labels
|
113
|
-
plt.title('Solubility vs. Temperature')
|
114
|
-
plt.ylabel("T / K")
|
115
|
-
xlabel = {'w':'Weight', 'x':'Mole'}
|
116
|
-
plt.xlabel(f"Weight fraction {mixture[0].name}")
|
117
|
-
plt.legend()
|
118
|
-
# Save the figure to a PNG or PDF file
|
119
|
-
plt.savefig('solubility_plot.png') # Saves the plot as a PNG file
|
120
|
-
# plt.savefig('solubility_plot.pdf') # Saves the plot as a PDF file
|
121
|
-
plt.show()
|
122
|
-
```
|
123
|
-
|
124
|
-
For a more comprehensive demonstration, including advanced functionalities and plotting results, please see the [example_usage.py](https://github.com/ivanantolo/cosmopharm/blob/main/example_usage.py) script in this repository. This detailed example walks through the process of setting up COSMOPharm, initializing models, and visualizing the results of solubility and miscibility calculations.
|
125
|
-
|
126
|
-
## Contributing
|
127
|
-
|
128
|
-
Contributions are welcome! Please refer to our [GitHub repository](https://github.com/ivanantolo/cosmopharm) for more information.
|
129
|
-
|
130
|
-
## Citation
|
131
|
-
|
132
|
-
We appreciate citations to our work as they help acknowledge and spread our research contributions. If you use COSMOPharm in your research, please cite the associated paper as follows:
|
133
|
-
|
134
|
-
```bibtex
|
135
|
-
@article{Antolovic2024COSMOPharm,
|
136
|
-
title={COSMOPharm: Drug--Polymer Compatibility of Pharmaceutical Amorphous Solid Dispersions from COSMO-SAC},
|
137
|
-
author={Antolovic, Ivan and Vrabec, Jadran and Klajmon, Martin},
|
138
|
-
journal={Molecular Pharmaceutics},
|
139
|
-
year={2024},
|
140
|
-
volume={1}, # Will be adjusted accordingly
|
141
|
-
issue={1}, # Will be adjusted accordingly
|
142
|
-
month={3}, # Will be adjusted accordingly
|
143
|
-
pages={1--10}, # Will be adjusted accordingly
|
144
|
-
doi={10.1021/acs.molpharmaceut.3c12345} # Will be adjusted accordingly
|
145
|
-
}
|
146
|
-
```
|
147
|
-
|
148
|
-
## License
|
149
|
-
|
150
|
-
COSMOPharm is released under the MIT License. For more details, see the [LICENSE](https://github.com/ivanantolo/cosmopharm/LICENSE) file.
|
@@ -1,18 +0,0 @@
|
|
1
|
-
cosmopharm/__init__.py,sha256=sdgLzbqylG8DDAJ5J96YiO4egn9xVJTx2uzaIZ8qj4g,68
|
2
|
-
cosmopharm/components.py,sha256=wEQQ0ZNOrFvG9SdhKAzBgqTbT6DtuoTreNBEdLw8Lm0,981
|
3
|
-
cosmopharm/actmodels/__init__.py,sha256=9iH67yrdSaf10Fj8LwRikUDUMeMxsvUHRPEaWc3384k,59
|
4
|
-
cosmopharm/actmodels/actmodel.py,sha256=69jluNR7Tb4BHwtkCQLI3NQ_0AEZcTDM69IdRPz9--w,5072
|
5
|
-
cosmopharm/actmodels/cosmo.py,sha256=tpYboI369rEOIkYgGqLyqgQSfKEgxwONULC4ZKDKIHI,5962
|
6
|
-
cosmopharm/equilibrium/__init__.py,sha256=5NsIbQEwELjeeoFEiWelnzHnhTzt5zsBh3r5icn_AIQ,44
|
7
|
-
cosmopharm/equilibrium/lle.py,sha256=Ru0_mso43vZNjy8ybdVQeweAsaZoa_yJiUBljn8qoNU,5472
|
8
|
-
cosmopharm/equilibrium/sle.py,sha256=E89JHAq-0XpJvSf2ybeVoNuV8OH55DHiJL6-8r33ggc,11187
|
9
|
-
cosmopharm/utils/__init__.py,sha256=qfUPovmZ9ukj6ZbTfndUOH6EX0ZrzRNjLZEDIVS8UvM,113
|
10
|
-
cosmopharm/utils/convert.py,sha256=V-7jY-Sb7C38N5bQcp1c27EOiVJfriP6zRbLAIKgrdE,2470
|
11
|
-
cosmopharm/utils/helpers.py,sha256=CXUTh3jVStHno_W_Z7o8RvQ6SveSjw_Ss31CkvfROfs,1460
|
12
|
-
cosmopharm/utils/lle_scanner.py,sha256=So9FCxLLcHmBkuF6zggMo3W3gFBocEmuRzyxVGy69JM,6587
|
13
|
-
cosmopharm/utils/spacing.py,sha256=vtM9b4wodpFGkZFGGLhiSXT51Zl6fNK2Og4oRcbLFH4,9222
|
14
|
-
cosmopharm-0.1.0a1.dist-info/LICENSE,sha256=25ZCycfBgonIECGYnZTy72eJVfzcHCEOz3DM9sTx7do,1162
|
15
|
-
cosmopharm-0.1.0a1.dist-info/METADATA,sha256=HVEIlN1fJvtp5Ruf-cfKPIXfYvMRjrqVlR1WZL-etfI,7098
|
16
|
-
cosmopharm-0.1.0a1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
17
|
-
cosmopharm-0.1.0a1.dist-info/top_level.txt,sha256=MGniVgvs1yq4sn6HQ7ErDVYV_g3st3Fs8TTFHOJVQ9I,11
|
18
|
-
cosmopharm-0.1.0a1.dist-info/RECORD,,
|
File without changes
|
File without changes
|