Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An update in the ReadMe.md to be more specific with the element composition function. #58

Merged
merged 8 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- vdW radii scaling parameter can now be adjusted via `mindlessgen.toml` or CLI
- The check_distance function now checks based on the sum of the van der Waals radii and a scaling factor acessible via `mindlessgen.toml` or CLI
- better type hints for `Callables`
- A clearer differentiation between the distinct scaling factors for the van der Waals radii.
- `README.md` with more detailed explanation of the element composition function.

### Fixed
- Unit conversion for (currenly unused) vdW radii from the original Fortran project
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ If the path is not specified with `-c/--config`, `mindlessgen.toml` will be sear

The active configuration can be printed using `--print-config`.

### Element composition
There are two related aspects of the element composition:
1. _Which elements_ should occur within the generated molecule?
2. **How many atoms** of the specified element should occur?
- **Example 1**: `C:1-3, O:1-1, H:1-*` would result in a molecule with 1, 2, or 3 carbon atoms, exactly 1 oxygen atom, and between 1 and an undefined number of hydrogen atoms (i.e., at least 1).
- **Example 2**: `Na:10-10, In:10-10, O:20-20`. This example would result in a molecule with exactly 10 sodium atoms, 10 indium atoms, and 20 oxygen atoms. **For a fixed element composition, the number of atoms (40) has to be within the min_num_atoms and max_num_atom interval.** `mindlessgen` will consequently always return a molecule with exactly 40 atoms.

## Citation

When using the program for academic purposes, please cite:
Expand Down
8 changes: 4 additions & 4 deletions mindlessgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ max_num_atoms = 10
init_scaling = 3.0
# > Increase in the coordinate scaling factor per trial after check_distance was not met. Options: <float>
increase_scaling_factor = 1.3
# > Scaling factor for the employed van der Waals radii. Options: <float>
scale_vdw_radii = 1.25
# > Scaling factor for the minimal bondlength based on the sum of the van der Waals radii. Options: <float>
scale_minimal_bondlength = 0.8
# > Scaling factor for the van der Waals radii employed for the fragment detection. Options: <float>
scale_fragment_detection = 1.25
# > Scaling factor for the minimal distance between two atoms based on the sum of the van der Waals radii. Options: <float>
scale_minimal_distance = 0.8
# > Contract the coordinates after the initial generation. Leads to more cluster-like and less extended structures. Options: <bool>
contract_coords = false
# > Atom types and their minimum and maximum occurrences. Format: "<element>:<min_count>-<max_count>"
Expand Down
12 changes: 6 additions & 6 deletions src/mindlessgen/cli/cli_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,16 @@ def cli_parser(argv: Sequence[str] | None = None) -> dict:
help="Do not write the molecules to xyz files.",
)
parser.add_argument(
"--scale-vdw-radii",
"--scale-fragment-detection",
type=float,
required=False,
help="Scaling factor for van der Waals radii.",
help="Scaling factor for the fragment detection based on the van der Waals radii.",
)
parser.add_argument(
"--scale-minimal-bondlength",
"--scale-minimal-distance",
type=float,
required=False,
help="Minimum bond length scaling factor.",
help="Minimum atom distance scaling factor.",
)

### Molecule generation arguments ###
Expand Down Expand Up @@ -277,8 +277,8 @@ def cli_parser(argv: Sequence[str] | None = None) -> dict:
"increase_scaling_factor": args_dict["increase_scaling_factor"],
"element_composition": args_dict["element_composition"],
"forbidden_elements": args_dict["forbidden_elements"],
"scale_vdw_radii": args_dict["scale_vdw_radii"],
"scale_minimal_bondlength": args_dict["scale_minimal_bondlength"],
"scale_fragment_detection": args_dict["scale_fragment_detection"],
"scale_minimal_distance": args_dict["scale_minimal_distance"],
"contract_coords": args_dict["contract_coords"],
}
# XTB specific arguments
Expand Down
14 changes: 8 additions & 6 deletions src/mindlessgen/molecules/generate_molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ def generate_random_molecule(
scaling=config_generate.init_coord_scaling,
inc_scaling_factor=config_generate.increase_scaling_factor,
verbosity=verbosity,
scale_bondlength=config_generate.scale_minimal_bondlength,
scale_minimal_distance=config_generate.scale_minimal_distance,
)
if config_generate.contract_coords:
mol.xyz = contract_coordinates(
xyz=mol.xyz,
ati=mol.ati,
scale_minimal_distance=config_generate.scale_minimal_bondlength,
scale_minimal_distance=config_generate.scale_minimal_distance,
)
mol.charge, mol.uhf = set_random_charge(mol.ati, verbosity)
mol.set_name_from_formula()
Expand Down Expand Up @@ -331,7 +331,7 @@ def generate_coordinates(
scaling: float,
inc_scaling_factor: float = 1.3,
verbosity: int = 1,
scale_bondlength: float = 0.75,
scale_minimal_distance: float = 0.8,
) -> tuple[np.ndarray, np.ndarray]:
"""
Generate random coordinates for a molecule.
Expand All @@ -342,7 +342,7 @@ def generate_coordinates(
xyz, ati = generate_random_coordinates(at)
xyz = xyz * eff_scaling
# do while check_distances is False
while not check_distances(xyz, ati, scale_bondlength=scale_bondlength):
while not check_distances(xyz, ati, scale_minimal_distance=scale_minimal_distance):
if verbosity > 1:
print(
f"Distance check failed. Increasing expansion factor by {inc_scaling_factor}..."
Expand Down Expand Up @@ -410,7 +410,9 @@ def contract_coordinates(
return xyz


def check_distances(xyz: np.ndarray, ati: np.ndarray, scale_bondlength: float) -> bool:
def check_distances(
xyz: np.ndarray, ati: np.ndarray, scale_minimal_distance: float
) -> bool:
"""
Check if the distances between atoms are larger than a threshold.
"""
Expand All @@ -421,6 +423,6 @@ def check_distances(xyz: np.ndarray, ati: np.ndarray, scale_bondlength: float) -
sum_radii = get_cov_radii(ati[i], COV_RADII) + get_cov_radii(
ati[j], COV_RADII
)
if r < scale_bondlength * sum_radii:
if r < scale_minimal_distance * sum_radii:
return False
return True
2 changes: 1 addition & 1 deletion src/mindlessgen/molecules/refinement.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def iterative_optimization(
# Detect fragments from the optimized molecule
fragmols = detect_fragments(
mol=rev_mol,
vdw_scaling=config_generate.scale_vdw_radii,
vdw_scaling=config_generate.scale_fragment_detection,
verbosity=verbosity,
)

Expand Down
42 changes: 21 additions & 21 deletions src/mindlessgen/prog/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ def __init__(self: GenerateConfig) -> None:
self._increase_scaling_factor: float = 1.3
self._element_composition: dict[int, tuple[int | None, int | None]] = {}
self._forbidden_elements: list[int] | None = None
self._scale_vdw_radii: float = 1.25
self._scale_minimal_bondlength: float = 0.8
self._scale_fragment_detection: float = 1.25
self._scale_minimal_distance: float = 0.8
self._contract_coords: bool = False

def get_identifier(self) -> str:
Expand Down Expand Up @@ -349,40 +349,40 @@ def forbidden_elements(self: GenerateConfig, forbidden_str: str) -> None:
self._forbidden_elements = sorted(list(forbidden_set))

@property
def scale_vdw_radii(self):
def scale_fragment_detection(self):
"""
Get the scaling factor for van der Waals radii.
Get the scaling factor for the fracment detection based on the van der Waals radii.
"""
return self._scale_vdw_radii
return self._scale_fragment_detection

@scale_vdw_radii.setter
def scale_vdw_radii(self, scale_vdw_radii: float):
@scale_fragment_detection.setter
def scale_fragment_detection(self, scale_fragment_detection: float):
"""
Set the scaling factor for van der Waals radii.
"""
if not isinstance(scale_vdw_radii, float):
if not isinstance(scale_fragment_detection, float):
raise TypeError("Scale van der Waals radii should be a float.")
if scale_vdw_radii <= 0:
if scale_fragment_detection <= 0:
raise ValueError("Scale van der Waals radii should be greater than 0.")
self._scale_vdw_radii = scale_vdw_radii
self._scale_fragment_detection = scale_fragment_detection

@property
def scale_minimal_bondlength(self):
def scale_minimal_distance(self):
"""
Get the scaling factor for minimal bond length.
Get the scaling factor for minimal distance between two atoms.
"""
return self._scale_minimal_bondlength
return self._scale_minimal_distance

@scale_minimal_bondlength.setter
def scale_minimal_bondlength(self, scale_minimal_bondlength: float):
@scale_minimal_distance.setter
def scale_minimal_distance(self, scale_minimal_distance: float):
"""
Set the scaling factor for minimal bond length.
Set the scaling factor for minimal distance between two atoms.
"""
if not isinstance(scale_minimal_bondlength, float):
raise TypeError("Scale minimal bond length should be a float.")
if scale_minimal_bondlength <= 0:
raise ValueError("Scale minimal bond length should be greater than 0.")
self._scale_minimal_bondlength = scale_minimal_bondlength
if not isinstance(scale_minimal_distance, float):
raise TypeError("Scale minimal distance should be a float.")
if scale_minimal_distance <= 0:
raise ValueError("Scale minimal distance should be greater than 0.")
self._scale_minimal_distance = scale_minimal_distance

@property
def contract_coords(self):
Expand Down