ensemble-analyzer 0.0.10a6__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.
Potentially problematic release.
This version of ensemble-analyzer might be problematic. Click here for more details.
- ensemble_analyzer/__init__.py +0 -0
- ensemble_analyzer/__main__.py +5 -0
- ensemble_analyzer/_calculators/__init__.py +12 -0
- ensemble_analyzer/_calculators/_gaussian.py +91 -0
- ensemble_analyzer/_calculators/_orca.py +91 -0
- ensemble_analyzer/_calculators/base.py +44 -0
- ensemble_analyzer/_clustering/__init__.py +0 -0
- ensemble_analyzer/_clustering/cluster_config.py +27 -0
- ensemble_analyzer/_clustering/cluster_manager.py +471 -0
- ensemble_analyzer/_conformer/__init__.py +0 -0
- ensemble_analyzer/_conformer/conformer.py +183 -0
- ensemble_analyzer/_conformer/energy_data.py +108 -0
- ensemble_analyzer/_conformer/spectral_data.py +79 -0
- ensemble_analyzer/_logger/__init__.py +0 -0
- ensemble_analyzer/_logger/create_log.py +44 -0
- ensemble_analyzer/_logger/formatter.py +36 -0
- ensemble_analyzer/_logger/logger.py +261 -0
- ensemble_analyzer/_managers/__init__.py +0 -0
- ensemble_analyzer/_managers/calculation_config.py +230 -0
- ensemble_analyzer/_managers/calculation_executor.py +109 -0
- ensemble_analyzer/_managers/calculator_orchestration.py +114 -0
- ensemble_analyzer/_managers/checkpoint_manager.py +68 -0
- ensemble_analyzer/_managers/protocol_executor.py +272 -0
- ensemble_analyzer/_managers/protocol_manager.py +45 -0
- ensemble_analyzer/_managers/pruning_manager.py +267 -0
- ensemble_analyzer/_parsers/__init__.py +12 -0
- ensemble_analyzer/_parsers/_gaussian.py +144 -0
- ensemble_analyzer/_parsers/_orca.py +220 -0
- ensemble_analyzer/_parsers/base.py +72 -0
- ensemble_analyzer/_protocol/__init__.py +0 -0
- ensemble_analyzer/_protocol/protocol.py +220 -0
- ensemble_analyzer/_protocol/solvent.py +19 -0
- ensemble_analyzer/_spectral/__init__.py +0 -0
- ensemble_analyzer/_spectral/base.py +260 -0
- ensemble_analyzer/_spectral/comp_electronic.py +23 -0
- ensemble_analyzer/_spectral/comp_vibronic.py +21 -0
- ensemble_analyzer/_spectral/compare.py +195 -0
- ensemble_analyzer/_spectral/experimental.py +122 -0
- ensemble_analyzer/_spectral/graph_default.py +95 -0
- ensemble_analyzer/cli/__init__.py +0 -0
- ensemble_analyzer/cli/get_av_energy.py +342 -0
- ensemble_analyzer/cli/pickle_editor/__init__.py +11 -0
- ensemble_analyzer/cli/pickle_editor/cli.py +269 -0
- ensemble_analyzer/cli/pickle_editor/core.py +397 -0
- ensemble_analyzer/cli/pickle_editor/tui.py +465 -0
- ensemble_analyzer/cli/protocol_wizard.py +513 -0
- ensemble_analyzer/cli/regraph.py +83 -0
- ensemble_analyzer/clustering.py +253 -0
- ensemble_analyzer/constants.py +78 -0
- ensemble_analyzer/ensemble_io.py +92 -0
- ensemble_analyzer/graph.py +61 -0
- ensemble_analyzer/io_utils.py +61 -0
- ensemble_analyzer/launch.py +75 -0
- ensemble_analyzer/parameters_file/basis_sets +436 -0
- ensemble_analyzer/parameters_file/default_protocol.json +16 -0
- ensemble_analyzer/parameters_file/default_threshold.json +26 -0
- ensemble_analyzer/parameters_file/functionals +144 -0
- ensemble_analyzer/parser_arguments.py +287 -0
- ensemble_analyzer/parser_parameter.py +137 -0
- ensemble_analyzer/rrho.py +382 -0
- ensemble_analyzer/title.py +29 -0
- ensemble_analyzer-0.0.10a6.dist-info/METADATA +240 -0
- ensemble_analyzer-0.0.10a6.dist-info/RECORD +67 -0
- ensemble_analyzer-0.0.10a6.dist-info/WHEEL +5 -0
- ensemble_analyzer-0.0.10a6.dist-info/entry_points.txt +6 -0
- ensemble_analyzer-0.0.10a6.dist-info/licenses/LICENSE +21 -0
- ensemble_analyzer-0.0.10a6.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import importlib
|
|
2
|
+
import pkgutil
|
|
3
|
+
|
|
4
|
+
# Importa automaticamente tutti i moduli nella cartella
|
|
5
|
+
for module_info in pkgutil.iter_modules(__path__):
|
|
6
|
+
if module_info.name != "base": # evita di ricaricare base.py
|
|
7
|
+
importlib.import_module(f"{__name__}.{module_info.name}")
|
|
8
|
+
|
|
9
|
+
# Espone il registro globale
|
|
10
|
+
from .base import CALCULATOR_REGISTRY, BaseCalc, register_calculator
|
|
11
|
+
|
|
12
|
+
__all__ = ["CALCULATOR_REGISTRY", "BaseCalc", "register_calculator"]
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from ase.calculators.gaussian import Gaussian
|
|
3
|
+
from ensemble_analyzer._calculators.base import BaseCalc, register_calculator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@register_calculator("gaussian")
|
|
7
|
+
class GaussianCalc(BaseCalc):
|
|
8
|
+
"""
|
|
9
|
+
ASE-compatible Gaussian calculator wrapper.
|
|
10
|
+
This class follows the same structure as OrcaCalc,
|
|
11
|
+
encapsulating the logic for SP, OPT, and FREQ calculations.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def common_str(self):
|
|
15
|
+
"""
|
|
16
|
+
Build the common Gaussian input string (route section)
|
|
17
|
+
based on the Protocol parameters.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
# Construct solvent model (if any)
|
|
21
|
+
solv = ""
|
|
22
|
+
if self.protocol.solvent:
|
|
23
|
+
if self.protocol.solvent.smd:
|
|
24
|
+
solv = f" SCRF=(SMD,Solvent={self.protocol.solvent.solvent})"
|
|
25
|
+
else:
|
|
26
|
+
solv = f" SCRF=(CPCM,Solvent={self.protocol.solvent.solvent})"
|
|
27
|
+
|
|
28
|
+
# Basic route section
|
|
29
|
+
route = f"# {self.protocol.functional}/{self.protocol.basis}{solv}"
|
|
30
|
+
|
|
31
|
+
# Add user-specified custom input
|
|
32
|
+
if self.protocol.add_input.strip():
|
|
33
|
+
route += " " + self.protocol.add_input.strip()
|
|
34
|
+
|
|
35
|
+
if self.protocol.read_orbitals:
|
|
36
|
+
route += " guess=read"
|
|
37
|
+
|
|
38
|
+
# Default options: no population output
|
|
39
|
+
# route += " pop=none"
|
|
40
|
+
|
|
41
|
+
return route
|
|
42
|
+
|
|
43
|
+
def _std_calc(self):
|
|
44
|
+
route = self.common_str()
|
|
45
|
+
|
|
46
|
+
calc = Gaussian(
|
|
47
|
+
label="gaussian",
|
|
48
|
+
output_type='N',
|
|
49
|
+
mem=f"{self.cpu*2}GB",
|
|
50
|
+
extra=route,
|
|
51
|
+
charge=self.protocol.charge,
|
|
52
|
+
mult=self.protocol.mult,
|
|
53
|
+
nprocshared=self.cpu,
|
|
54
|
+
)
|
|
55
|
+
if self.protocol.read_orbitals:
|
|
56
|
+
calc.oldchk = (
|
|
57
|
+
f"{self.conf.folder}/protocol_{self.protocol.read_orbitals}.chk"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return calc, "gaussian"
|
|
61
|
+
|
|
62
|
+
def single_point(self):
|
|
63
|
+
|
|
64
|
+
calc, label = self._std_calc()
|
|
65
|
+
return calc, label
|
|
66
|
+
|
|
67
|
+
def optimisation(self):
|
|
68
|
+
|
|
69
|
+
calc, label = self._std_calc()
|
|
70
|
+
if not self.protocol.constrains:
|
|
71
|
+
calc.parameters["extra"] += " opt"
|
|
72
|
+
else:
|
|
73
|
+
calc.parameters["extra"] += " opt=(modredudant)"
|
|
74
|
+
redundant = "\n".join([f"X {i+1} F" for i in self.protocol.constrains])
|
|
75
|
+
# Counting in gaussian starts at 1
|
|
76
|
+
|
|
77
|
+
if calc.parameters.get("addsec"):
|
|
78
|
+
calc.parameters["addsec"] += redundant
|
|
79
|
+
else:
|
|
80
|
+
calc.parameters["addsec"] = redundant
|
|
81
|
+
|
|
82
|
+
if self.protocol.freq:
|
|
83
|
+
calc.parameters["extra"] += " freq=(HPModes,vcd)"
|
|
84
|
+
|
|
85
|
+
return calc, label
|
|
86
|
+
|
|
87
|
+
def frequency(self):
|
|
88
|
+
|
|
89
|
+
calc, label = self._std_calc()
|
|
90
|
+
calc.parameters["extra"] += " freq=(HPModes,vcd)"
|
|
91
|
+
return calc, label
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from ase.calculators.orca import ORCA, OrcaProfile
|
|
2
|
+
from ensemble_analyzer._calculators.base import BaseCalc, register_calculator
|
|
3
|
+
import shutil
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
VERSION = None
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
ORCA_COMMAND = os.getenv("ORCACOMMAND") or shutil.which("orca")
|
|
10
|
+
orca_profile = OrcaProfile(command=ORCA_COMMAND)
|
|
11
|
+
VERSION = int(os.getenv("ORCAVERSION")[0])
|
|
12
|
+
except Exception:
|
|
13
|
+
orca_profile = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@register_calculator("orca")
|
|
17
|
+
class OrcaCalc(BaseCalc):
|
|
18
|
+
label = "orca"
|
|
19
|
+
VERSION = VERSION if VERSION else 0
|
|
20
|
+
|
|
21
|
+
def common_str(self):
|
|
22
|
+
|
|
23
|
+
if self.protocol.solvent:
|
|
24
|
+
if "xtb" in self.protocol.functional.lower():
|
|
25
|
+
solv = f"ALPB({self.protocol.solvent.solvent})"
|
|
26
|
+
elif self.protocol.solvent.solvent.strip():
|
|
27
|
+
solv = f" {self.protocol.solvent}"
|
|
28
|
+
else:
|
|
29
|
+
solv = f" CPCM"
|
|
30
|
+
else:
|
|
31
|
+
solv = ""
|
|
32
|
+
|
|
33
|
+
si = f"{self.protocol.functional} {self.protocol.basis} {solv} nopop"
|
|
34
|
+
|
|
35
|
+
ob = (
|
|
36
|
+
f"%pal nprocs {self.cpu} end "
|
|
37
|
+
+ self.protocol.add_input.format(CONF=self.conf.folder)
|
|
38
|
+
+ (" %maxcore 5000" if "maxcore" not in self.protocol.add_input else "")
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return si, ob
|
|
42
|
+
|
|
43
|
+
def _std_calc(self):
|
|
44
|
+
si, ob = self.common_str()
|
|
45
|
+
|
|
46
|
+
calculator = ORCA(
|
|
47
|
+
profile=orca_profile,
|
|
48
|
+
label="orca",
|
|
49
|
+
orcasimpleinput=si,
|
|
50
|
+
orcablocks=ob,
|
|
51
|
+
charge=self.protocol.charge,
|
|
52
|
+
mult=self.protocol.mult,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
if self.protocol.read_orbitals:
|
|
56
|
+
calculator.parameters["orcasimpleinput"] += " moread"
|
|
57
|
+
calculator.parameters[
|
|
58
|
+
"orcablocks"
|
|
59
|
+
] += f'\n%moinp "{self.conf.folder}/protocol_{self.protocol.read_orbitals}/{self.conf.number}_p{self.protocol.read_orbitals}_orca.gbw"\n'
|
|
60
|
+
|
|
61
|
+
if "freq" in self.protocol.add_input.lower():
|
|
62
|
+
calculator.parameters["orcablocks"] += "\n%freq vcd true end\n"
|
|
63
|
+
|
|
64
|
+
return calculator, "orca"
|
|
65
|
+
|
|
66
|
+
def single_point(self):
|
|
67
|
+
return self._std_calc()
|
|
68
|
+
|
|
69
|
+
def optimisation(self):
|
|
70
|
+
calc, label = self._std_calc()
|
|
71
|
+
calc.parameters["orcasimpleinput"] += " opt"
|
|
72
|
+
if self.constrains:
|
|
73
|
+
text = "\n%geom Constraints "
|
|
74
|
+
for i in self.constrains:
|
|
75
|
+
text += " {C " + str(i) + " C}"
|
|
76
|
+
text += "end end\n"
|
|
77
|
+
calc.parameters["orcasimpleinput"] += text
|
|
78
|
+
|
|
79
|
+
if self.protocol.freq:
|
|
80
|
+
calc.parameters["orcasimpleinput"] += " freq"
|
|
81
|
+
if self.VERSION > 5:
|
|
82
|
+
calc.parameters["orcablocks"] += "\n%freq vcd true end\n"
|
|
83
|
+
|
|
84
|
+
return calc, label
|
|
85
|
+
|
|
86
|
+
def frequency(self):
|
|
87
|
+
calc, label = self._std_calc()
|
|
88
|
+
calc.parameters["orcasimpleinput"] += " freq"
|
|
89
|
+
if self.VERSION > 5:
|
|
90
|
+
calc.parameters["orcablocks"] += "\n%freq vcd true end\n"
|
|
91
|
+
return calc, label
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
from typing import Dict
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def register_calculator(name):
|
|
7
|
+
"""Decorator to register each calculator"""
|
|
8
|
+
|
|
9
|
+
def decorator(cls):
|
|
10
|
+
CALCULATOR_REGISTRY[name.lower()] = cls
|
|
11
|
+
return cls
|
|
12
|
+
|
|
13
|
+
return decorator
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseCalc(ABC):
|
|
17
|
+
|
|
18
|
+
def __init__(self, protocol, cpu: int, conf=None):
|
|
19
|
+
self.protocol = protocol
|
|
20
|
+
self.cpu = cpu
|
|
21
|
+
self.conf = conf
|
|
22
|
+
self.constrains = protocol.constrains
|
|
23
|
+
|
|
24
|
+
@abstractmethod
|
|
25
|
+
def common_str(self):
|
|
26
|
+
"""String for the solvent definition"""
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def single_point(self):
|
|
31
|
+
"""Create the common ASE calculator"""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def optimisation(self):
|
|
36
|
+
"""Add to the calculator the opt flag"""
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def frequency(self):
|
|
41
|
+
"""Add to the calculator the opt flag"""
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
CALCULATOR_REGISTRY : Dict[str, BaseCalc]= {}
|
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class PCAResult:
|
|
9
|
+
"""Results from PCA analysis"""
|
|
10
|
+
scores : np.ndarray # PCA-transformed coordinates (n_conformers, n_components)
|
|
11
|
+
clusters : np.ndarray # Cluster assignments (n_conformers,)
|
|
12
|
+
colors : List[str] # Conformer colors
|
|
13
|
+
numbers : List[int] # Conformer IDs
|
|
14
|
+
energies : np.ndarray # Relative energies [Eh]
|
|
15
|
+
explained_variance : np.ndarray # Variance explained by each component
|
|
16
|
+
n_clusters : Optional[int] = None # Number of clusters used
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class ClusteringConfig:
|
|
21
|
+
"""Configuration for clustering operations"""
|
|
22
|
+
n_clusters : Optional[int] = None # If None, auto-detect optimal
|
|
23
|
+
include_H : bool = True # Include hydrogen in distance matrix
|
|
24
|
+
set_cluster_attribute : bool = True # Set cluster ID on Conformer objects
|
|
25
|
+
min_k : int = 2 # Minimum clusters for silhouette search
|
|
26
|
+
max_k : int = 30 # Maximum clusters for silhouette search
|
|
27
|
+
random_state : int = 42 # Fix value for reproducibility of the random initiation of cluster points
|