chore: better project structure

This commit is contained in:
2026-02-26 18:02:50 -03:00
parent 5d76e49f89
commit cb4b21ab6c
25 changed files with 102 additions and 96 deletions

View File

@@ -0,0 +1,22 @@
from .logger import Logger, valid_logger
from .misc import (
compress_files_1mb,
date_time,
make_qm_dir,
make_step_dir,
weekday_date_time,
)
from .ptable import atommass, atomsymb
__all__ = [
"Logger",
"valid_logger",
"atomsymb",
"atommass",
"weekday_date_time",
"date_time",
"compress_files_1mb",
"make_step_dir",
"make_qm_dir",
]

View File

@@ -0,0 +1,6 @@
from typing_extensions import Protocol, runtime_checkable
@runtime_checkable
class Dataclass(Protocol):
__dataclass_fields__: dict

View File

@@ -0,0 +1,72 @@
import logging
from pathlib import Path
def valid_logger(func):
def wrapper(*args, **kwargs):
logger = args[0]
assert logger._was_set, "Logger is not set. Please call set_logger() first."
return func(*args, **kwargs)
return wrapper
class Logger:
outfile = None
_logger = None
_was_set = False
def __init__(self, logger_name):
if self._logger is None:
self._logger = logging.getLogger(logger_name)
def set_logger(self, outfile="run.log", level=logging.INFO, stream=None):
outfile_path = None
if outfile is not None and stream is None:
outfile_path = Path(outfile)
if outfile_path.exists():
outfile_path.rename(str(outfile_path) + ".backup")
if level is not None:
self._logger.setLevel(level)
self._create_handlers(outfile_path, stream)
self._was_set = True
@valid_logger
def info(self, message):
self._logger.info(message)
@valid_logger
def debug(self, message):
self._logger.debug(message)
@valid_logger
def warning(self, message):
self._logger.warning(message)
@valid_logger
def error(self, message):
self._logger.error(message)
def _create_handlers(self, outfile_path: Path, stream):
handlers = []
if outfile_path is not None:
handlers.append(logging.FileHandler(outfile_path, mode="a+"))
elif stream is not None:
handlers.append(logging.StreamHandler(stream))
else:
handlers.append(logging.StreamHandler())
for handler in handlers:
handler.setFormatter(logging.Formatter("%(message)s"))
self._logger.addHandler(handler)
def close(self):
for handler in self._logger.handlers:
handler.close()
self._logger.removeHandler(handler)

67
diceplayer/utils/misc.py Normal file
View File

@@ -0,0 +1,67 @@
from typing_extensions import Final
import gzip
import os
import shutil
import sys
import time
####################################### constants ######################################
BOHR2ANG: Final[float] = 0.52917721092
ANG2BOHR: Final[float] = 1 / BOHR2ANG
####################################### functions ######################################
def weekday_date_time():
return time.strftime("%A, %d %b %Y at %H:%M:%S")
def date_time():
return time.strftime("%d %b %Y at %H:%M:%S")
def compress_files_1mb(path):
working_dir = os.getcwd()
os.chdir(path)
files = filter(os.path.isfile, os.listdir(os.curdir))
for file in files:
if os.path.getsize(file) > 1024 * 1024: ## If bigger than 1MB
filegz = file + ".gz"
try:
with open(file, "rb") as f_in:
with gzip.open(filegz, "wb") as f_out:
shutil.copyfileobj(f_in, f_out)
except Exception as _:
sys.exit("Error: cannot compress file {}".format(file))
os.chdir(working_dir)
return
def make_step_dir(cycle):
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
path = sim_dir + os.sep + step_dir
if os.path.exists(path):
sys.exit("Error: a file or directory {} already exists".format(step_dir))
try:
os.makedirs(path)
except Exception as _:
sys.exit("Error: cannot make directory {}".format(step_dir))
def make_qm_dir(cycle):
sim_dir = "simfiles"
step_dir = "step{:02d}".format(cycle)
path = sim_dir + os.sep + step_dir + os.sep + "qm"
try:
os.makedirs(path)
except Exception as _:
sys.exit("Error: cannot make directory {}".format(path))

223
diceplayer/utils/ptable.py Normal file
View File

@@ -0,0 +1,223 @@
#### Label used in Dice for a ghost atom
dice_ghost_label = "Xx"
#### Tuple of atom symbols
atomsymb = (
"00",
"H ",
"He",
"Li",
"Be",
"B ",
"C ",
"N ",
"O ",
"F ",
"Ne",
"Na",
"Mg",
"Al",
"Si",
"P ",
"S ",
"Cl",
"Ar",
"K ",
"Ca",
"Sc",
"Ti",
"V ",
"Cr",
"Mn",
"Fe",
"Co",
"Ni",
"Cu",
"Zn",
"Ga",
"Ge",
"As",
"Se",
"Br",
"Kr",
"Rb",
"Sr",
"Y ",
"Zr",
"Nb",
"Mo",
"Tc",
"Ru",
"Rh",
"Pd",
"Ag",
"Cd",
"In",
"Sn",
"Sb",
"Te",
"I ",
"Xe",
"Cs",
"Ba",
"La",
"Ce",
"Pr",
"Nd",
"Pm",
"Sm",
"Eu",
"Gd",
"Tb",
"Dy",
"Ho",
"Er",
"Tm",
"Yb",
"Lu",
"Hf",
"Ta",
"W ",
"Re",
"Os",
"Ir",
"Pt",
"Au",
"Hg",
"Ti",
"Pb",
"Bi",
"Po",
"At",
"Rn",
"Fr",
"Ra",
"Ac",
"Th",
"Pa",
"U ",
"Np",
"Pu",
"Am",
"Cm",
"Bk",
"Cf",
"Es",
"Fm",
"Md",
"No",
"Lr",
dice_ghost_label,
)
#### Tuple of atom masses
atommass = (
0.0,
1.0079,
4.0026,
6.9410,
9.0122,
10.811,
12.011,
14.007,
15.999,
18.998,
20.180,
22.990,
24.305,
26.982,
28.086,
30.974,
32.065,
35.453,
39.948,
39.098,
40.078,
44.956,
47.867,
50.942,
51.996,
54.938,
55.845,
58.933,
58.693,
63.546,
65.409,
69.723,
72.640,
74.922,
78.960,
79.904,
83.798,
85.468,
87.620,
88.906,
91.224,
92.906,
95.940,
98.000,
101.07,
102.91,
106.42,
107.87,
112.41,
114.82,
118.71,
121.76,
127.60,
126.90,
131.29,
132.91,
137.33,
138.91,
140.12,
140.91,
144.24,
145.00,
150.36,
151.96,
157.25,
158.93,
162.50,
164.93,
167.26,
168.93,
173.04,
174.97,
178.49,
180.95,
183.84,
186.21,
190.23,
192.22,
195.08,
196.97,
200.59,
204.38,
207.20,
208.98,
209.00,
210.00,
222.00,
223.00,
226.00,
227.00,
232.04,
231.04,
238.03,
237.00,
244.00,
243.00,
247.00,
247.00,
251.00,
252.00,
257.00,
258.00,
259.00,
262.00,
0.000,
)
#### Number of the ghost atom
ghost_number = len(atomsymb) - 1