From 03e6de8c117e2bae70e7b48c0880ceb3f90da39a Mon Sep 17 00:00:00 2001 From: Ramil Nugmanov Date: Tue, 30 Dec 2025 19:04:48 +0100 Subject: [PATCH 1/3] fixup --- chython/files/opsin.py | 3 ++- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/chython/files/opsin.py b/chython/files/opsin.py index 78e12e05..c2aa320e 100644 --- a/chython/files/opsin.py +++ b/chython/files/opsin.py @@ -16,7 +16,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, see . # -from jpype import JPackage, isJVMStarted, startJVM from .daylight import smiles @@ -29,6 +28,8 @@ def opsin(string): global _opsin, _nametostruct if _opsin is None: + from jpype import JPackage, isJVMStarted, startJVM + if not isJVMStarted(): from chython import class_paths diff --git a/pyproject.toml b/pyproject.toml index fc6ebe76..fca34ad6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = 'chython' -version = '2.15' +version = '2.15.1' description = 'Library for processing molecules and reactions in python way' authors = ['Ramil Nugmanov '] license = 'LGPLv3' From 7c760e11acb2791ca0be69be10adec0d601e2388 Mon Sep 17 00:00:00 2001 From: Aigul Khakimova <40434269+aigulkhkmv@users.noreply.github.com> Date: Thu, 15 Jan 2026 11:37:21 +0300 Subject: [PATCH 2/3] UPD: workflow for macos arm and x86 (#64) Co-authored-by: khakimova --- .github/workflows/python-package.yml | 7 ++++++- pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index fbf5af1c..8d0bcb93 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -10,8 +10,13 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [windows-latest, macos-latest, ubuntu-22.04] + os: [windows-latest, macos-latest, macos-12, ubuntu-22.04] python-version: ["3.10", "3.11", "3.12"] + include: + - os: macos-latest + architecture: aarch64-apple-darwin + - os: macos-12 + architecture: x86_64-apple-darwin steps: - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} diff --git a/pyproject.toml b/pyproject.toml index fca34ad6..c62a8c20 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = 'chython' -version = '2.15.1' +version = '2.15.2-a1' description = 'Library for processing molecules and reactions in python way' authors = ['Ramil Nugmanov '] license = 'LGPLv3' From 284b929be524f24801bfa7039e0a9ec9033a9335 Mon Sep 17 00:00:00 2001 From: Ramil Nugmanov Date: Sat, 7 Mar 2026 16:49:51 +0100 Subject: [PATCH 3/3] added skip_elements support for metal handling functions; introduced bond rescaling helper. --- README.rst | 2 +- chython/algorithms/calculate2d/molecule.py | 34 +++++++++++++--------- chython/algorithms/standardize/salts.py | 20 +++++++++---- pyproject.toml | 2 +- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/README.rst b/README.rst index 0317e70e..def470ed 100644 --- a/README.rst +++ b/README.rst @@ -36,7 +36,7 @@ Only python 3.8+. Copyright ========= -* 2014-2025 Ramil Nugmanov nougmanoff@protonmail.com main developer +* 2014-2026 Ramil Nugmanov nougmanoff@protonmail.com main developer Contributors ============ diff --git a/chython/algorithms/calculate2d/molecule.py b/chython/algorithms/calculate2d/molecule.py index 282451e1..99717424 100644 --- a/chython/algorithms/calculate2d/molecule.py +++ b/chython/algorithms/calculate2d/molecule.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2019-2025 Ramil Nugmanov +# Copyright 2019-2026 Ramil Nugmanov # Copyright 2019, 2020 Dinar Batyrshin # This file is part of chython. # @@ -17,7 +17,6 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program; if not, see . # -from math import sqrt from random import random from typing import TYPE_CHECKING, Union, Dict, Literal from ...exceptions import ImplementationError @@ -112,19 +111,10 @@ def clean2d(self: Union['MoleculeContainer', 'Calculate2DMolecule'], plane[n] = (x, y) else: raise ValueError(f'Invalid clean2d engine: {engine}') - bonds = [] - for n, m, _ in self.bonds(): - xn, yn = plane[n] - xm, ym = plane[m] - bonds.append(sqrt((xm - xn) ** 2 + (ym - yn) ** 2)) - if bonds: - bond_reduce = sum(bonds) / len(bonds) / .825 - else: - bond_reduce = 1. - atoms = self._atoms - for n, (x, y) in plane.items(): - atoms[n].xy = (x / bond_reduce, y / bond_reduce) + for n, xy in plane.items(): + atoms[n].xy = xy + self.rescale2d() if self.connected_components_count > 1: shift_x = 0. @@ -132,6 +122,22 @@ def clean2d(self: Union['MoleculeContainer', 'Calculate2DMolecule'], shift_x = self._fix_plane_mean(shift_x, component=c) + .9 self.__dict__.pop('__cached_method__repr_svg_', None) + def rescale2d(self: 'MoleculeContainer'): + """ + Rescale coordinates to average bond length 0.825. + """ + bonds = [] + atoms = self._atoms + for n, m, _ in self.bonds(): + bonds.append(float(atoms[n].xy - atoms[m].xy)) + if bonds: + bond_reduce = sum(bonds) / len(bonds) / .825 + if bond_reduce > .5: # check for singularity + for a in atoms.values(): + a.xy /= bond_reduce + return True + return False + def _fix_plane_mean(self, shift_x: float, shift_y=0., component=None) -> float: atoms = self._atoms if component is None: diff --git a/chython/algorithms/standardize/salts.py b/chython/algorithms/standardize/salts.py index 48cec856..29cccdaf 100644 --- a/chython/algorithms/standardize/salts.py +++ b/chython/algorithms/standardize/salts.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright 2021-2024 Ramil Nugmanov +# Copyright 2021-2026 Ramil Nugmanov # This file is part of chython. # # chython is free software; you can redistribute it and/or modify @@ -18,7 +18,6 @@ # from typing import TYPE_CHECKING, List, Tuple, Union from ._salts import acids, rules -from ...periodictable import GroupI, GroupII if TYPE_CHECKING: @@ -28,23 +27,28 @@ # atomic number constants H = 1 N = 7 +s_metals = {3, 4, 11, 12, 19, 20, 37, 38, 55, 56, 87, 88} +s_metals_ammonia = {3, 4, 7, 11, 12, 19, 20, 37, 38, 55, 56, 87, 88} class Salts: __slots__ = () - def remove_metals(self: 'MoleculeContainer', *, logging=False) -> Union[bool, List]: + def remove_metals(self: 'MoleculeContainer', *, + skip_elements: List[int] = None, logging=False) -> Union[bool, List]: """ Remove disconnected S-metals and ammonia. :param logging: return deleted atoms list. + :param skip_elements: skip elements from removing. """ atoms = self._atoms bonds = self._bonds + filters = s_metals_ammonia.difference(skip_elements) if skip_elements else s_metals_ammonia metals = [] for n, a in atoms.items(): - if not bonds[n] and (a == N or isinstance(a, (GroupI, GroupII)) and a != H): + if not bonds[n] and a.atomic_number in filters: metals.append(n) if 0 < len(metals) < len(self): @@ -88,16 +92,20 @@ def remove_acids(self: 'MoleculeContainer', *, logging=False) -> Union[bool, Lis return [] return False - def split_metal_salts(self: 'MoleculeContainer', *, logging=False) -> Union[bool, List[Tuple[int, int]]]: + def split_metal_salts(self: 'MoleculeContainer', *, + skip_elements: List[int] = None, + logging=False) -> Union[bool, List[Tuple[int, int]]]: """ Split connected S-metal salts to cation/anion pairs. :param logging: return deleted bonds list. + :param skip_elements: skip elements from splitting. """ atoms = self._atoms bonds = self._bonds + filters = s_metals.difference(skip_elements) if skip_elements else s_metals - metals = [n for n, a in atoms.items() if isinstance(a, (GroupI, GroupII)) and a != H] + metals = [n for n, a in atoms.items() if a.atomic_number in filters] if metals: acceptors = set() log = [] diff --git a/pyproject.toml b/pyproject.toml index c62a8c20..3244f4f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = 'chython' -version = '2.15.2-a1' +version = '2.16' description = 'Library for processing molecules and reactions in python way' authors = ['Ramil Nugmanov '] license = 'LGPLv3'