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.

Files changed (67) hide show
  1. ensemble_analyzer/__init__.py +0 -0
  2. ensemble_analyzer/__main__.py +5 -0
  3. ensemble_analyzer/_calculators/__init__.py +12 -0
  4. ensemble_analyzer/_calculators/_gaussian.py +91 -0
  5. ensemble_analyzer/_calculators/_orca.py +91 -0
  6. ensemble_analyzer/_calculators/base.py +44 -0
  7. ensemble_analyzer/_clustering/__init__.py +0 -0
  8. ensemble_analyzer/_clustering/cluster_config.py +27 -0
  9. ensemble_analyzer/_clustering/cluster_manager.py +471 -0
  10. ensemble_analyzer/_conformer/__init__.py +0 -0
  11. ensemble_analyzer/_conformer/conformer.py +183 -0
  12. ensemble_analyzer/_conformer/energy_data.py +108 -0
  13. ensemble_analyzer/_conformer/spectral_data.py +79 -0
  14. ensemble_analyzer/_logger/__init__.py +0 -0
  15. ensemble_analyzer/_logger/create_log.py +44 -0
  16. ensemble_analyzer/_logger/formatter.py +36 -0
  17. ensemble_analyzer/_logger/logger.py +261 -0
  18. ensemble_analyzer/_managers/__init__.py +0 -0
  19. ensemble_analyzer/_managers/calculation_config.py +230 -0
  20. ensemble_analyzer/_managers/calculation_executor.py +109 -0
  21. ensemble_analyzer/_managers/calculator_orchestration.py +114 -0
  22. ensemble_analyzer/_managers/checkpoint_manager.py +68 -0
  23. ensemble_analyzer/_managers/protocol_executor.py +272 -0
  24. ensemble_analyzer/_managers/protocol_manager.py +45 -0
  25. ensemble_analyzer/_managers/pruning_manager.py +267 -0
  26. ensemble_analyzer/_parsers/__init__.py +12 -0
  27. ensemble_analyzer/_parsers/_gaussian.py +144 -0
  28. ensemble_analyzer/_parsers/_orca.py +220 -0
  29. ensemble_analyzer/_parsers/base.py +72 -0
  30. ensemble_analyzer/_protocol/__init__.py +0 -0
  31. ensemble_analyzer/_protocol/protocol.py +220 -0
  32. ensemble_analyzer/_protocol/solvent.py +19 -0
  33. ensemble_analyzer/_spectral/__init__.py +0 -0
  34. ensemble_analyzer/_spectral/base.py +260 -0
  35. ensemble_analyzer/_spectral/comp_electronic.py +23 -0
  36. ensemble_analyzer/_spectral/comp_vibronic.py +21 -0
  37. ensemble_analyzer/_spectral/compare.py +195 -0
  38. ensemble_analyzer/_spectral/experimental.py +122 -0
  39. ensemble_analyzer/_spectral/graph_default.py +95 -0
  40. ensemble_analyzer/cli/__init__.py +0 -0
  41. ensemble_analyzer/cli/get_av_energy.py +342 -0
  42. ensemble_analyzer/cli/pickle_editor/__init__.py +11 -0
  43. ensemble_analyzer/cli/pickle_editor/cli.py +269 -0
  44. ensemble_analyzer/cli/pickle_editor/core.py +397 -0
  45. ensemble_analyzer/cli/pickle_editor/tui.py +465 -0
  46. ensemble_analyzer/cli/protocol_wizard.py +513 -0
  47. ensemble_analyzer/cli/regraph.py +83 -0
  48. ensemble_analyzer/clustering.py +253 -0
  49. ensemble_analyzer/constants.py +78 -0
  50. ensemble_analyzer/ensemble_io.py +92 -0
  51. ensemble_analyzer/graph.py +61 -0
  52. ensemble_analyzer/io_utils.py +61 -0
  53. ensemble_analyzer/launch.py +75 -0
  54. ensemble_analyzer/parameters_file/basis_sets +436 -0
  55. ensemble_analyzer/parameters_file/default_protocol.json +16 -0
  56. ensemble_analyzer/parameters_file/default_threshold.json +26 -0
  57. ensemble_analyzer/parameters_file/functionals +144 -0
  58. ensemble_analyzer/parser_arguments.py +287 -0
  59. ensemble_analyzer/parser_parameter.py +137 -0
  60. ensemble_analyzer/rrho.py +382 -0
  61. ensemble_analyzer/title.py +29 -0
  62. ensemble_analyzer-0.0.10a6.dist-info/METADATA +240 -0
  63. ensemble_analyzer-0.0.10a6.dist-info/RECORD +67 -0
  64. ensemble_analyzer-0.0.10a6.dist-info/WHEEL +5 -0
  65. ensemble_analyzer-0.0.10a6.dist-info/entry_points.txt +6 -0
  66. ensemble_analyzer-0.0.10a6.dist-info/licenses/LICENSE +21 -0
  67. ensemble_analyzer-0.0.10a6.dist-info/top_level.txt +1 -0
File without changes
@@ -0,0 +1,5 @@
1
+ from ensemble_analyzer.launch import main
2
+
3
+ if __name__ == '__main__':
4
+
5
+ main()
@@ -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