bond_order_processing.calculations
1__docformat__ = "google" 2"""Calculations module.""" 3import numpy as np 4from typing import Callable 5from abc import ABC 6from abc import abstractmethod 7from .input_data import MayerBondOrders 8from .input_data import CoordinatesOfAtoms 9from typing import TypeAlias 10from dataclasses import dataclass 11 12 13@dataclass 14class PairOfAtoms: 15 """PairOfAtoms. 16 17 Object represents Pair of Atoms 18 19 Attributes: 20 atom_1 (str): First atom name. 21 atom_2 (str): Second atom name. 22 MBO_min (float): Minimum Mayer bond order cut off. 23 MBO_max (float | str):Max Mayer bond order cut off. Float or 'INF' - for infinite value.capitalize() 24 id (str): Bond id eg. 'P-O' 25 26 """ 27 28 atom_1: str = '' 29 atom_2: str = '' 30 MBO_min: float | str | None = None 31 MBO_max: float | str | None = None 32 id: str = '' 33 34 35class Calculations(ABC): 36 """Calculations base class.""" 37 38 @abstractmethod 39 def calculate(cls, *args, **kwars) -> type: 40 pass 41 42 @abstractmethod 43 def to_string(self, *args, **kwars) -> str: 44 pass 45 46 47class Statistics(ABC): 48 """Statistics base class""" 49 @abstractmethod 50 def calculate_statistics(self) -> type: 51 pass 52 53 54class Histogram(Calculations): 55 """Object represents histogram.""" 56 _histogram: Callable = np.histogram 57 x: list[float] = [] 58 """Position of bin on x axis.""" 59 y: list[int] = [] 60 """Quantity.""" 61 62 @classmethod 63 def calculate(cls, values: list[float], bins: int): 64 """Calculate histogram. 65 66 Args: 67 values (list[float]): List of values. 68 bins (int): Number of bins in histogram. 69 70 Returns: 71 **Histogram**: Histogram object. 72 73 """ 74 histogram = cls._histogram(values, bins) 75 76 y = histogram[0] 77 x = histogram[1] 78 y = y.tolist() 79 x = x.tolist() 80 81 first_loop = True 82 new_x = [] 83 for item in x: 84 if first_loop: 85 first_loop = False 86 previous = item 87 else: 88 new_x.append((item 89 + previous) / 2) 90 previous = item 91 92 histogram = cls() 93 histogram.x = new_x 94 histogram.y = y 95 return histogram 96 97 def to_string(self, bond_id: str, atom_symbol_1: str, atom_symbol_2: str)\ 98 -> str: 99 """Make string from Histogram object 100 101 Args: 102 bond_id (str): eg. P-O. 103 atom_symbol_1 (str): Symbol of atom 1. 104 atom_symbol_2 (str): Symbol of atom 2. 105 Returns: 106 **str**: String. 107 108 """ 109 string = f'Bond id: {bond_id} - atom_1_id: {atom_symbol_1}, atom_2_id: {atom_symbol_2}\n\n' 110 string = string + 'Interval/2' + ' ' + 'Count' + '\n\n' 111 for i in range(len(self.x)): 112 string = string + \ 113 str(round(self.x[i], 9)) + ' ' + \ 114 str(round(self.y[i], 9)) + '\n' 115 116 string = string + '\n' 117 118 return string 119 120 121@dataclass 122class CoordinationNumber: 123 """Object stores coordination number of given atom and 124 Mayer bond orders corresponding to the bonds in the 125 coordination polyhedron.""" 126 127 id_atom_1: int 128 """Central atom id.""" 129 cn: int 130 """Value of coordination number.""" 131 bonds: dict[int, float] 132 """**Key** - ligand id, **value** - Mayer bond order.""" 133 134 135class CoordinationNumbers(Calculations, Statistics): 136 """Generate list of CoordinationNumber objects and processes it.""" 137 CoordinationNumber: type = CoordinationNumber 138 139 list_coordinations_number: list[CoordinationNumber] 140 """List of CoordinationNumber objects.""" 141 id_of_bond: str 142 """Id of bond eg. 'P-O'""" 143 atom_symbol: str 144 """Symbol of atom.""" 145 statistics: dict[int, float] | None = None 146 """**Key** - coordination number, **value** - percentages.""" 147 148 @classmethod 149 def calculate(cls, mayer_bond_orders: MayerBondOrders, 150 atom_symbol_1: str, atom_symbol_2: str, 151 max_mayer_bond_order: float | str, 152 min_mayer_bond_order: float, 153 id_of_bond: str): 154 """Calculate CoordinationNumbers object. 155 156 Args: 157 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 158 atom_symbol_1 (str): Central atom symbol. 159 atom_symbol_2 (str): Ligand symbol. 160 max_mayer_bond_order (float): Max cut of radius, float or 'INF" if infinite value. 161 min_mayer_bond_order (float): Min cut of radius. 162 id_of_bond (str): id of bond eg. 'P-O' 163 164 Returns: 165 **CoordinationNumbers**: CoordinationNumbers object 166 167 """ 168 169 if max_mayer_bond_order != "INF"\ 170 and not (type(max_mayer_bond_order) is float): 171 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 172 173 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 174 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 175 176 list_coordinations_number = [] 177 for atom_1_id in atom_1_ids: 178 179 coordination_number = cls.CoordinationNumber(atom_1_id, 0, {}) 180 181 for atom_2_id in atom_2_ids: 182 if atom_1_id != atom_2_id: 183 184 mbo = mayer_bond_orders\ 185 .get_mayer_bond_order_between_atoms(atom_1_id, 186 atom_2_id) 187 if (mbo > min_mayer_bond_order 188 and max_mayer_bond_order == 'INF'): 189 coordination_number.bonds.update({atom_2_id: mbo}) 190 coordination_number.cn += 1 191 elif (type(max_mayer_bond_order) is float): 192 if (mbo > min_mayer_bond_order 193 and mbo < max_mayer_bond_order): 194 coordination_number.bonds.update({atom_2_id: mbo}) 195 coordination_number.cn += 1 196 else: 197 continue 198 199 list_coordinations_number.append(coordination_number) 200 201 self = cls() 202 self.id_of_bond = id_of_bond 203 self.atom_symbol = atom_symbol_1 204 self.list_coordinations_number = list_coordinations_number 205 206 return self 207 208 def calculate_statistics(self): 209 """Calculate statistics of CoordinationNumbers. 210 211 Statistic are in "statistics" attribute. 212 213 Returns: 214 CoordinationNumbers: CoordinationNumbers object 215 216 """ 217 cns = self._get_list_of_coordination_numbers() 218 quantities: dict = {} 219 for cn in cns: 220 for item in self.list_coordinations_number: 221 if item.cn == cn: 222 if quantities.get(cn, None) is None: 223 quantities.update({cn: 1}) 224 else: 225 quantities[cn] = quantities[cn] + 1 226 227 number_of_atoms = len(self.list_coordinations_number) 228 statistics = {} 229 for key, value in quantities.items(): 230 statistics.update({key: (value/number_of_atoms) * 100}) 231 232 self.statistics = statistics 233 234 return self 235 236 def _get_list_of_coordination_numbers(self) -> list[int]: 237 cns = [] 238 for item in self.list_coordinations_number: 239 if item.cn not in cns: 240 cns += [item.cn] 241 242 return cns 243 244 def to_string(self) -> str: 245 """Make string from CoordinationNumbers object. 246 247 Returns: 248 **str**: String. 249 250 """ 251 string = "## CN of " + str(self.atom_symbol) + " bond: "\ 252 + str(self.id_of_bond) + "\n\n" 253 for item in self.list_coordinations_number: 254 string = string + "id: " + str(item.id_atom_1) + " "\ 255 + "CN: " + str(item.cn) 256 257 if item.cn != 0: 258 string += "\n" + "Bond orders (id: mbo): " 259 260 length = len(item.bonds) 261 i = 1 262 for key, value in item.bonds.items(): 263 string += str(key) + ': ' + str(value) 264 if i < length: 265 string += ', ' 266 else: 267 pass 268 i += 1 269 270 string += '\n' 271 string += '\n' 272 273 if self.statistics is not None: 274 string = string + "Statistics of: "\ 275 + str(self.atom_symbol) + "\n\n" + "CN %\n" 276 for key, value in self.statistics.items(): 277 string = string + str(key) + ' ' + str(round(value, 3)) + '\n' 278 279 string = string + '\n' 280 281 return string 282 283 284class QiUnits(Calculations, Statistics): 285 """Stores information about Qi units.""" 286 id_of_bond: str 287 """Id of bonds in Qⁱ unit""" 288 atom_symbol_1: str 289 """Symbol of central atom""" 290 atom_symbol_2: str 291 """Symbol of ligands""" 292 q_i_units: dict[int, int] = {} 293 """Dictionary stores values of i of Qⁱ units. key - central atom id.""" 294 statistics: dict[int, float] | None = None 295 """Dictionary stores percentages of Qⁱ units. key - value of i in Qⁱ""" 296 297 @classmethod 298 def calculate(cls, mayer_bond_orders: MayerBondOrders, 299 atom_symbol_1: str, 300 atom_symbol_2: str, 301 max_mayer_bond_order: float | str, 302 min_mayer_bond_order: float, 303 id_of_bond: str): 304 """Calculate QiUnits object. 305 306 Args: 307 mayer_bond_orders (MayerBondOrders): Object MayerBondOrders. 308 atom_symbol_1 (str): Symbol of central atom. 309 atom_symbol_2 (str): Symbol of ligands. 310 max_mayer_bond_order (float | str): Max Mayer bond order, float or 'INF' for infinite maximum value. 311 min_mayer_bond_order (float): Min Mayer bond order. 312 id_of_bond (str): Name of bond eg. 'P-O'. 313 314 Raises: 315 ValueError: "Wrong type of max_mayer_bond_order!!!!" 316 317 Returns: 318 **QiUnits**: Returns QiUnits object. 319 320 """ 321 322 if max_mayer_bond_order != "INF"\ 323 and not (type(max_mayer_bond_order) is float): 324 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 325 elif max_mayer_bond_order == "INF": 326 inf = True 327 max_mayer_bond_order = -1 328 # -1 to prevent exception 329 else: 330 inf = False 331 332 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 333 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 334 335 self = cls() 336 self.id_of_bond = id_of_bond 337 self.atom_symbol_1 = atom_symbol_1 338 self.atom_symbol_2 = atom_symbol_2 339 self.q_i_units = {} 340 for atom_1_id in atom_1_ids: 341 342 self.q_i_units.update({atom_1_id: 0}) 343 344 for atom_2_id in atom_2_ids: 345 mbo = mayer_bond_orders\ 346 .get_mayer_bond_order_between_atoms(atom_1_id, 347 atom_2_id) 348 if (mbo > min_mayer_bond_order 349 and (mbo < max_mayer_bond_order or inf)): 350 351 for atom_3_id in atom_1_ids: 352 mbo = mayer_bond_orders\ 353 .get_mayer_bond_order_between_atoms(atom_2_id, 354 atom_3_id) 355 if (mbo > min_mayer_bond_order 356 and (mbo < max_mayer_bond_order or inf) 357 and atom_3_id != atom_1_id): 358 359 self.q_i_units[atom_1_id] += 1 360 break 361 362 else: 363 continue 364 365 return self 366 367 def calculate_statistics(self): 368 """Calculate statistics in object QiUnits. 369 370 Returns: 371 **QiUnits**: QiUnits object. 372 373 """ 374 375 unique_values = [] 376 for value in self.q_i_units.values(): 377 if value not in unique_values: 378 unique_values.append(value) 379 380 quantities = {} 381 for unique in unique_values: 382 quantities.update({unique: 0}) 383 for value in self.q_i_units.values(): 384 if value == unique: 385 quantities[unique] += 1 386 else: 387 continue 388 389 quantity_of_all_Q_i = len(self.q_i_units) 390 391 self.statistics = {} 392 393 for key, value in quantities.items(): 394 self.statistics.update({key: (value/quantity_of_all_Q_i) * 100}) 395 396 return self 397 398 def to_string(self) -> str: 399 """Generate string representing object. 400 401 Returns: 402 **str**: String. 403 404 """ 405 string = "Q_i of " + str(self.atom_symbol_1) + ' bond id: '\ 406 + str(self.id_of_bond) + "\n\n" 407 408 string += "id Q_i[i]\n" 409 410 for key, value in self.q_i_units.items(): 411 string = string + str(key) + ' ' + str(value) + '\n' 412 413 string += '\n' 414 415 if self.statistics is not None: 416 string = string + 'Statistics of Q_i: ' + str(self.atom_symbol_1)\ 417 + ', bond id: ' + str(self.id_of_bond) + '\n\n' 418 419 string += 'Q_i[i] [%]\n' 420 421 for key, value in self.statistics.items(): 422 string = string + str(key) + ' ' + str(round(value, 3)) + '\n' 423 424 string += '\n' 425 426 return string 427 428 429@dataclass 430class Connection: 431 """An object represents connections between two elements.""" 432 id_atom_2 = int 433 mayer_bond_order = float 434 435 atom_symbol_2: str 436 """Ligant atom symbol.""" 437 bond_id: str 438 """Bond id eg. 'P-O'""" 439 quantity: int 440 """Quantity of given connections""" 441 bonds: dict[id_atom_2, mayer_bond_order] 442 """**key**- ligand id, **value**-mayer bond order.""" 443 444 445class Connections(Calculations): 446 """Object represents connections of given atom to nearest neighbors. 447 """ 448 atom_1_id: TypeAlias = int 449 Connection: type = Connection 450 451 connections: dict[atom_1_id, list[Connection]] 452 """Key - central atom, values - list to Connection objects.""" 453 atom_symbol_1: str 454 """Symbol of central atom.""" 455 456 @ classmethod 457 def calculate(cls, mayer_bond_orders: MayerBondOrders, 458 atom_symbol_1: str, 459 pairs_atoms_list: list[PairOfAtoms] 460 ): 461 """Calculate Connections object. 462 463 Args: 464 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 465 atom_symbol_1 (str): Central atom symbol. 466 pairs_atoms_list (list[PairOfAtoms]): list of PairsOfAtoms objects. 467 468 Raises: 469 ValueError: "Wrong type of max_mayer_bond_order!!!!" 470 471 Returns: 472 **Connections**: Connections object. 473 474 """ 475 476 pair_atom_list_containing_atom_1 = [] 477 for pair_atom in pairs_atoms_list: 478 if pair_atom.atom_1 == atom_symbol_1\ 479 or pair_atom.atom_2 == atom_symbol_1: 480 481 pair_atom_list_containing_atom_1.append(pair_atom) 482 else: 483 continue 484 485 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 486 connections = {} 487 for atom_1_id in atom_1_ids: 488 489 connections.update({atom_1_id: []}) 490 491 for pair_atoms in pair_atom_list_containing_atom_1: 492 if (v := pair_atoms.atom_1) != atom_symbol_1: 493 atom_symbol_2 = v 494 else: 495 atom_symbol_2 = pair_atoms.atom_2 496 497 connection = cls.Connection( 498 atom_symbol_2, pair_atoms.id, 0, {}) 499 500 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 501 502 for atom_2_id in atom_2_ids: 503 if pair_atoms.MBO_max != "INF"\ 504 and not (type(pair_atoms.MBO_max) is float): 505 raise ValueError( 506 "Wrong type of max_mayer_bond_order!!!!") 507 508 mbo = mayer_bond_orders\ 509 .get_mayer_bond_order_between_atoms(atom_1_id, 510 atom_2_id) 511 512 if (mbo > pair_atoms.MBO_min 513 and pair_atoms.MBO_max == 'INF'): 514 515 connection.quantity += 1 516 connection.bonds.update({atom_2_id: mbo}) 517 518 elif (pair_atoms.MBO_max != 'INF'): 519 if (mbo > pair_atoms.MBO_min 520 and pair_atoms.MBO_max > mbo): 521 522 connection.quantity += 1 523 connection.bonds.update({atom_2_id: mbo}) 524 525 connections[atom_1_id].append(connection) 526 527 self = cls() 528 self.connections = connections 529 self.atom_symbol_1 = atom_symbol_1 530 531 return self 532 533 def to_string(self) -> str: 534 """Generates string representation of object. 535 536 Returns: 537 **str**: string. 538 539 """ 540 string = '## Connections of: ' + str(self.atom_symbol_1) + '\n\n' 541 542 for atom_1_id, list_of_connections in self.connections.items(): 543 string = string + "### Central atom id: " + str(atom_1_id) + "\n" 544 545 for connection in list_of_connections: 546 547 string = string + f"Bond id: {str(connection.bond_id)} "\ 548 + f"(second atom: {str(connection.atom_symbol_2)})\n"\ 549 + f"quantity: {connection.quantity}\n"\ 550 + "Bonds:\n" 551 552 string_id_line = "id: " 553 string_mbo_line = "mbo: " 554 555 for id, mbo in connection.bonds.items(): 556 string_id_line += f"{id} " 557 string_mbo_line += f"{round(mbo, 3)} " 558 559 string = string + string_id_line + '\n'\ 560 + string_mbo_line + '\n\n' 561 562 return string 563 564 565class Covalence(Calculations): 566 """Object storages covalences of atoms""" 567 covalence: dict[int, float] 568 """Key - id of atom, value - covalence calculated from Mayer bond orders.""" 569 atom_symbol: str 570 """Atom symbol.""" 571 572 @ classmethod 573 def calculate(cls, mayer_bond_orders: MayerBondOrders, 574 atom_symbol: str): 575 """Calculate Covalence object. 576 577 Args: 578 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 579 atom_symbol (str): Atom symbol. 580 581 Returns: 582 **Covalence**: Covalence object. 583 584 """ 585 586 atom_ids = mayer_bond_orders.get_atoms_ids(atom_symbol) 587 588 self = cls() 589 self.atom_symbol = atom_symbol 590 self.covalence = {} 591 for id in atom_ids: 592 mbos = mayer_bond_orders.get_all_mayer_bond_orders_of_atom(id) 593 self.covalence.update({id: sum(mbos)}) 594 595 return self 596 597 def to_string(self) -> str: 598 """Generates string representation of object. 599 600 Returns: 601 **str**: String. 602 603 """ 604 string = f'Covalence of {self.atom_symbol}.\n\n'\ 605 + 'id COV\n' 606 607 for id, value in self.covalence.items(): 608 string = string + f'{id} {value:.3f}\n' 609 string += '\n' 610 611 return string 612 613 614class BondLength(Calculations): 615 """Object stored bond lengths of pairs of atoms.""" 616 atom_id_1: TypeAlias = int 617 atom_id_2: TypeAlias = int 618 619 id_of_bond: str 620 """Id of bond eg. 'P-O'""" 621 atom_symbol_1: str 622 """Atom 1 symbol.""" 623 atom_symbol_2: str 624 """Atom 2 symbol.""" 625 lengths: dict[atom_id_1, dict[atom_id_2, float]] 626 """**values**- length between atoms.""" 627 mbos: dict[atom_id_1, dict[atom_id_2, float]] 628 """**values**- Mayer bond orders""" 629 630 @ classmethod 631 def calculate(cls, 632 mayer_bond_orders: MayerBondOrders, 633 coordinates_of_atoms: CoordinatesOfAtoms, 634 atom_symbol_1: str, 635 atom_symbol_2: str, 636 max_mayer_bond_order: float | str, 637 min_mayer_bond_order: float, 638 id_of_bond: str): 639 """Calculate BondLength object. 640 641 Args: 642 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 643 coordinates_of_atoms (CoordinatesOfAtoms): CoordinatesOfAtom object. 644 atom_symbol_1 (str): Symbol of atom 1. 645 atom_symbol_2 (str): Symbol of atom 2. 646 max_mayer_bond_order (float | str): max value of Mayer bond order or 'INF for infinite value. 647 min_mayer_bond_order (float): min value of Mayer bond order. 648 id_of_bond (str): id of bond eg. 'P-O' 649 650 Raises: 651 ValueError: "Wrong type of max_mayer_bond_order!!!!" 652 653 Returns: 654 **BondLength**: BondLength object. 655 656 """ 657 658 if max_mayer_bond_order != "INF"\ 659 and not (type(max_mayer_bond_order) is float): 660 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 661 elif max_mayer_bond_order == "INF": 662 inf = True 663 max_mayer_bond_order = -1 664 # -1 to prevent exception 665 else: 666 inf = False 667 668 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 669 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 670 671 self = cls() 672 self.id_of_bond = id_of_bond 673 self.atom_symbol_1 = atom_symbol_1 674 self.atom_symbol_2 = atom_symbol_2 675 self.lengths = {} 676 self.mbos = {} 677 678 for atom_1_id in atom_1_ids: 679 self.lengths.update({atom_1_id: {}}) 680 self.mbos.update({atom_1_id: {}}) 681 for atom_2_id in atom_2_ids: 682 mbo = mayer_bond_orders\ 683 .get_mayer_bond_order_between_atoms(atom_1_id, 684 atom_2_id) 685 686 length = coordinates_of_atoms\ 687 .get_distance_between_atoms(atom_1_id, atom_2_id) 688 689 if mbo > min_mayer_bond_order and ( 690 mbo < max_mayer_bond_order 691 or inf is True 692 ): 693 self.lengths[atom_1_id].update({atom_2_id: length}) 694 self.mbos[atom_1_id].update({atom_2_id: mbo}) 695 else: 696 continue 697 698 # remove empty keys. 699 700 for key in list(self.lengths.keys()): 701 if self.lengths[key] == {}: 702 del self.lengths[key] 703 del self.mbos[key] 704 705 return self 706 707 def to_string(self) -> str: 708 """Generates string representation of object. 709 710 Returns: 711 **str**: String. 712 713 """ 714 string = f'Bond lengths of bond id: {self.id_of_bond} '\ 715 + f'(atoms: {self.atom_symbol_1}, {self.atom_symbol_2}):\n\n'\ 716 + 'id_1 id_2 length mbo\n' 717 718 for key_1 in self.lengths.keys(): 719 for key_2 in self.lengths[key_1].keys(): 720 string = string + f'{key_1} {key_2} '\ 721 + f'{self.lengths[key_1][key_2]} '\ 722 + f'{self.mbos[key_1][key_2]}\n' 723 724 string += '\n' 725 726 return string
14@dataclass 15class PairOfAtoms: 16 """PairOfAtoms. 17 18 Object represents Pair of Atoms 19 20 Attributes: 21 atom_1 (str): First atom name. 22 atom_2 (str): Second atom name. 23 MBO_min (float): Minimum Mayer bond order cut off. 24 MBO_max (float | str):Max Mayer bond order cut off. Float or 'INF' - for infinite value.capitalize() 25 id (str): Bond id eg. 'P-O' 26 27 """ 28 29 atom_1: str = '' 30 atom_2: str = '' 31 MBO_min: float | str | None = None 32 MBO_max: float | str | None = None 33 id: str = ''
PairOfAtoms.
Object represents Pair of Atoms
Attributes:
- atom_1 (str): First atom name.
- atom_2 (str): Second atom name.
- MBO_min (float): Minimum Mayer bond order cut off.
- MBO_max (float | str): Max Mayer bond order cut off. Float or 'INF' - for infinite value.capitalize()
- id (str): Bond id eg. 'P-O'
36class Calculations(ABC): 37 """Calculations base class.""" 38 39 @abstractmethod 40 def calculate(cls, *args, **kwars) -> type: 41 pass 42 43 @abstractmethod 44 def to_string(self, *args, **kwars) -> str: 45 pass
Calculations base class.
48class Statistics(ABC): 49 """Statistics base class""" 50 @abstractmethod 51 def calculate_statistics(self) -> type: 52 pass
Statistics base class
55class Histogram(Calculations): 56 """Object represents histogram.""" 57 _histogram: Callable = np.histogram 58 x: list[float] = [] 59 """Position of bin on x axis.""" 60 y: list[int] = [] 61 """Quantity.""" 62 63 @classmethod 64 def calculate(cls, values: list[float], bins: int): 65 """Calculate histogram. 66 67 Args: 68 values (list[float]): List of values. 69 bins (int): Number of bins in histogram. 70 71 Returns: 72 **Histogram**: Histogram object. 73 74 """ 75 histogram = cls._histogram(values, bins) 76 77 y = histogram[0] 78 x = histogram[1] 79 y = y.tolist() 80 x = x.tolist() 81 82 first_loop = True 83 new_x = [] 84 for item in x: 85 if first_loop: 86 first_loop = False 87 previous = item 88 else: 89 new_x.append((item 90 + previous) / 2) 91 previous = item 92 93 histogram = cls() 94 histogram.x = new_x 95 histogram.y = y 96 return histogram 97 98 def to_string(self, bond_id: str, atom_symbol_1: str, atom_symbol_2: str)\ 99 -> str: 100 """Make string from Histogram object 101 102 Args: 103 bond_id (str): eg. P-O. 104 atom_symbol_1 (str): Symbol of atom 1. 105 atom_symbol_2 (str): Symbol of atom 2. 106 Returns: 107 **str**: String. 108 109 """ 110 string = f'Bond id: {bond_id} - atom_1_id: {atom_symbol_1}, atom_2_id: {atom_symbol_2}\n\n' 111 string = string + 'Interval/2' + ' ' + 'Count' + '\n\n' 112 for i in range(len(self.x)): 113 string = string + \ 114 str(round(self.x[i], 9)) + ' ' + \ 115 str(round(self.y[i], 9)) + '\n' 116 117 string = string + '\n' 118 119 return string
Object represents histogram.
63 @classmethod 64 def calculate(cls, values: list[float], bins: int): 65 """Calculate histogram. 66 67 Args: 68 values (list[float]): List of values. 69 bins (int): Number of bins in histogram. 70 71 Returns: 72 **Histogram**: Histogram object. 73 74 """ 75 histogram = cls._histogram(values, bins) 76 77 y = histogram[0] 78 x = histogram[1] 79 y = y.tolist() 80 x = x.tolist() 81 82 first_loop = True 83 new_x = [] 84 for item in x: 85 if first_loop: 86 first_loop = False 87 previous = item 88 else: 89 new_x.append((item 90 + previous) / 2) 91 previous = item 92 93 histogram = cls() 94 histogram.x = new_x 95 histogram.y = y 96 return histogram
Calculate histogram.
Arguments:
- values (list[float]): List of values.
- bins (int): Number of bins in histogram.
Returns:
Histogram: Histogram object.
98 def to_string(self, bond_id: str, atom_symbol_1: str, atom_symbol_2: str)\ 99 -> str: 100 """Make string from Histogram object 101 102 Args: 103 bond_id (str): eg. P-O. 104 atom_symbol_1 (str): Symbol of atom 1. 105 atom_symbol_2 (str): Symbol of atom 2. 106 Returns: 107 **str**: String. 108 109 """ 110 string = f'Bond id: {bond_id} - atom_1_id: {atom_symbol_1}, atom_2_id: {atom_symbol_2}\n\n' 111 string = string + 'Interval/2' + ' ' + 'Count' + '\n\n' 112 for i in range(len(self.x)): 113 string = string + \ 114 str(round(self.x[i], 9)) + ' ' + \ 115 str(round(self.y[i], 9)) + '\n' 116 117 string = string + '\n' 118 119 return string
Make string from Histogram object
Arguments:
- bond_id (str): eg. P-O.
- atom_symbol_1 (str): Symbol of atom 1.
- atom_symbol_2 (str): Symbol of atom 2.
Returns:
str: String.
122@dataclass 123class CoordinationNumber: 124 """Object stores coordination number of given atom and 125 Mayer bond orders corresponding to the bonds in the 126 coordination polyhedron.""" 127 128 id_atom_1: int 129 """Central atom id.""" 130 cn: int 131 """Value of coordination number.""" 132 bonds: dict[int, float] 133 """**Key** - ligand id, **value** - Mayer bond order."""
Object stores coordination number of given atom and Mayer bond orders corresponding to the bonds in the coordination polyhedron.
136class CoordinationNumbers(Calculations, Statistics): 137 """Generate list of CoordinationNumber objects and processes it.""" 138 CoordinationNumber: type = CoordinationNumber 139 140 list_coordinations_number: list[CoordinationNumber] 141 """List of CoordinationNumber objects.""" 142 id_of_bond: str 143 """Id of bond eg. 'P-O'""" 144 atom_symbol: str 145 """Symbol of atom.""" 146 statistics: dict[int, float] | None = None 147 """**Key** - coordination number, **value** - percentages.""" 148 149 @classmethod 150 def calculate(cls, mayer_bond_orders: MayerBondOrders, 151 atom_symbol_1: str, atom_symbol_2: str, 152 max_mayer_bond_order: float | str, 153 min_mayer_bond_order: float, 154 id_of_bond: str): 155 """Calculate CoordinationNumbers object. 156 157 Args: 158 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 159 atom_symbol_1 (str): Central atom symbol. 160 atom_symbol_2 (str): Ligand symbol. 161 max_mayer_bond_order (float): Max cut of radius, float or 'INF" if infinite value. 162 min_mayer_bond_order (float): Min cut of radius. 163 id_of_bond (str): id of bond eg. 'P-O' 164 165 Returns: 166 **CoordinationNumbers**: CoordinationNumbers object 167 168 """ 169 170 if max_mayer_bond_order != "INF"\ 171 and not (type(max_mayer_bond_order) is float): 172 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 173 174 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 175 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 176 177 list_coordinations_number = [] 178 for atom_1_id in atom_1_ids: 179 180 coordination_number = cls.CoordinationNumber(atom_1_id, 0, {}) 181 182 for atom_2_id in atom_2_ids: 183 if atom_1_id != atom_2_id: 184 185 mbo = mayer_bond_orders\ 186 .get_mayer_bond_order_between_atoms(atom_1_id, 187 atom_2_id) 188 if (mbo > min_mayer_bond_order 189 and max_mayer_bond_order == 'INF'): 190 coordination_number.bonds.update({atom_2_id: mbo}) 191 coordination_number.cn += 1 192 elif (type(max_mayer_bond_order) is float): 193 if (mbo > min_mayer_bond_order 194 and mbo < max_mayer_bond_order): 195 coordination_number.bonds.update({atom_2_id: mbo}) 196 coordination_number.cn += 1 197 else: 198 continue 199 200 list_coordinations_number.append(coordination_number) 201 202 self = cls() 203 self.id_of_bond = id_of_bond 204 self.atom_symbol = atom_symbol_1 205 self.list_coordinations_number = list_coordinations_number 206 207 return self 208 209 def calculate_statistics(self): 210 """Calculate statistics of CoordinationNumbers. 211 212 Statistic are in "statistics" attribute. 213 214 Returns: 215 CoordinationNumbers: CoordinationNumbers object 216 217 """ 218 cns = self._get_list_of_coordination_numbers() 219 quantities: dict = {} 220 for cn in cns: 221 for item in self.list_coordinations_number: 222 if item.cn == cn: 223 if quantities.get(cn, None) is None: 224 quantities.update({cn: 1}) 225 else: 226 quantities[cn] = quantities[cn] + 1 227 228 number_of_atoms = len(self.list_coordinations_number) 229 statistics = {} 230 for key, value in quantities.items(): 231 statistics.update({key: (value/number_of_atoms) * 100}) 232 233 self.statistics = statistics 234 235 return self 236 237 def _get_list_of_coordination_numbers(self) -> list[int]: 238 cns = [] 239 for item in self.list_coordinations_number: 240 if item.cn not in cns: 241 cns += [item.cn] 242 243 return cns 244 245 def to_string(self) -> str: 246 """Make string from CoordinationNumbers object. 247 248 Returns: 249 **str**: String. 250 251 """ 252 string = "## CN of " + str(self.atom_symbol) + " bond: "\ 253 + str(self.id_of_bond) + "\n\n" 254 for item in self.list_coordinations_number: 255 string = string + "id: " + str(item.id_atom_1) + " "\ 256 + "CN: " + str(item.cn) 257 258 if item.cn != 0: 259 string += "\n" + "Bond orders (id: mbo): " 260 261 length = len(item.bonds) 262 i = 1 263 for key, value in item.bonds.items(): 264 string += str(key) + ': ' + str(value) 265 if i < length: 266 string += ', ' 267 else: 268 pass 269 i += 1 270 271 string += '\n' 272 string += '\n' 273 274 if self.statistics is not None: 275 string = string + "Statistics of: "\ 276 + str(self.atom_symbol) + "\n\n" + "CN %\n" 277 for key, value in self.statistics.items(): 278 string = string + str(key) + ' ' + str(round(value, 3)) + '\n' 279 280 string = string + '\n' 281 282 return string
Generate list of CoordinationNumber objects and processes it.
List of CoordinationNumber objects.
149 @classmethod 150 def calculate(cls, mayer_bond_orders: MayerBondOrders, 151 atom_symbol_1: str, atom_symbol_2: str, 152 max_mayer_bond_order: float | str, 153 min_mayer_bond_order: float, 154 id_of_bond: str): 155 """Calculate CoordinationNumbers object. 156 157 Args: 158 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 159 atom_symbol_1 (str): Central atom symbol. 160 atom_symbol_2 (str): Ligand symbol. 161 max_mayer_bond_order (float): Max cut of radius, float or 'INF" if infinite value. 162 min_mayer_bond_order (float): Min cut of radius. 163 id_of_bond (str): id of bond eg. 'P-O' 164 165 Returns: 166 **CoordinationNumbers**: CoordinationNumbers object 167 168 """ 169 170 if max_mayer_bond_order != "INF"\ 171 and not (type(max_mayer_bond_order) is float): 172 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 173 174 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 175 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 176 177 list_coordinations_number = [] 178 for atom_1_id in atom_1_ids: 179 180 coordination_number = cls.CoordinationNumber(atom_1_id, 0, {}) 181 182 for atom_2_id in atom_2_ids: 183 if atom_1_id != atom_2_id: 184 185 mbo = mayer_bond_orders\ 186 .get_mayer_bond_order_between_atoms(atom_1_id, 187 atom_2_id) 188 if (mbo > min_mayer_bond_order 189 and max_mayer_bond_order == 'INF'): 190 coordination_number.bonds.update({atom_2_id: mbo}) 191 coordination_number.cn += 1 192 elif (type(max_mayer_bond_order) is float): 193 if (mbo > min_mayer_bond_order 194 and mbo < max_mayer_bond_order): 195 coordination_number.bonds.update({atom_2_id: mbo}) 196 coordination_number.cn += 1 197 else: 198 continue 199 200 list_coordinations_number.append(coordination_number) 201 202 self = cls() 203 self.id_of_bond = id_of_bond 204 self.atom_symbol = atom_symbol_1 205 self.list_coordinations_number = list_coordinations_number 206 207 return self
Calculate CoordinationNumbers object.
Arguments:
- mayer_bond_orders (MayerBondOrders): MayerBondOrders object.
- atom_symbol_1 (str): Central atom symbol.
- atom_symbol_2 (str): Ligand symbol.
- max_mayer_bond_order (float): Max cut of radius, float or 'INF" if infinite value.
- min_mayer_bond_order (float): Min cut of radius.
- id_of_bond (str): id of bond eg. 'P-O'
Returns:
CoordinationNumbers: CoordinationNumbers object
209 def calculate_statistics(self): 210 """Calculate statistics of CoordinationNumbers. 211 212 Statistic are in "statistics" attribute. 213 214 Returns: 215 CoordinationNumbers: CoordinationNumbers object 216 217 """ 218 cns = self._get_list_of_coordination_numbers() 219 quantities: dict = {} 220 for cn in cns: 221 for item in self.list_coordinations_number: 222 if item.cn == cn: 223 if quantities.get(cn, None) is None: 224 quantities.update({cn: 1}) 225 else: 226 quantities[cn] = quantities[cn] + 1 227 228 number_of_atoms = len(self.list_coordinations_number) 229 statistics = {} 230 for key, value in quantities.items(): 231 statistics.update({key: (value/number_of_atoms) * 100}) 232 233 self.statistics = statistics 234 235 return self
Calculate statistics of CoordinationNumbers.
Statistic are in "statistics" attribute.
Returns:
CoordinationNumbers: CoordinationNumbers object
245 def to_string(self) -> str: 246 """Make string from CoordinationNumbers object. 247 248 Returns: 249 **str**: String. 250 251 """ 252 string = "## CN of " + str(self.atom_symbol) + " bond: "\ 253 + str(self.id_of_bond) + "\n\n" 254 for item in self.list_coordinations_number: 255 string = string + "id: " + str(item.id_atom_1) + " "\ 256 + "CN: " + str(item.cn) 257 258 if item.cn != 0: 259 string += "\n" + "Bond orders (id: mbo): " 260 261 length = len(item.bonds) 262 i = 1 263 for key, value in item.bonds.items(): 264 string += str(key) + ': ' + str(value) 265 if i < length: 266 string += ', ' 267 else: 268 pass 269 i += 1 270 271 string += '\n' 272 string += '\n' 273 274 if self.statistics is not None: 275 string = string + "Statistics of: "\ 276 + str(self.atom_symbol) + "\n\n" + "CN %\n" 277 for key, value in self.statistics.items(): 278 string = string + str(key) + ' ' + str(round(value, 3)) + '\n' 279 280 string = string + '\n' 281 282 return string
Make string from CoordinationNumbers object.
Returns:
str: String.
122@dataclass 123class CoordinationNumber: 124 """Object stores coordination number of given atom and 125 Mayer bond orders corresponding to the bonds in the 126 coordination polyhedron.""" 127 128 id_atom_1: int 129 """Central atom id.""" 130 cn: int 131 """Value of coordination number.""" 132 bonds: dict[int, float] 133 """**Key** - ligand id, **value** - Mayer bond order."""
Object stores coordination number of given atom and Mayer bond orders corresponding to the bonds in the coordination polyhedron.
Inherited Members
285class QiUnits(Calculations, Statistics): 286 """Stores information about Qi units.""" 287 id_of_bond: str 288 """Id of bonds in Qⁱ unit""" 289 atom_symbol_1: str 290 """Symbol of central atom""" 291 atom_symbol_2: str 292 """Symbol of ligands""" 293 q_i_units: dict[int, int] = {} 294 """Dictionary stores values of i of Qⁱ units. key - central atom id.""" 295 statistics: dict[int, float] | None = None 296 """Dictionary stores percentages of Qⁱ units. key - value of i in Qⁱ""" 297 298 @classmethod 299 def calculate(cls, mayer_bond_orders: MayerBondOrders, 300 atom_symbol_1: str, 301 atom_symbol_2: str, 302 max_mayer_bond_order: float | str, 303 min_mayer_bond_order: float, 304 id_of_bond: str): 305 """Calculate QiUnits object. 306 307 Args: 308 mayer_bond_orders (MayerBondOrders): Object MayerBondOrders. 309 atom_symbol_1 (str): Symbol of central atom. 310 atom_symbol_2 (str): Symbol of ligands. 311 max_mayer_bond_order (float | str): Max Mayer bond order, float or 'INF' for infinite maximum value. 312 min_mayer_bond_order (float): Min Mayer bond order. 313 id_of_bond (str): Name of bond eg. 'P-O'. 314 315 Raises: 316 ValueError: "Wrong type of max_mayer_bond_order!!!!" 317 318 Returns: 319 **QiUnits**: Returns QiUnits object. 320 321 """ 322 323 if max_mayer_bond_order != "INF"\ 324 and not (type(max_mayer_bond_order) is float): 325 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 326 elif max_mayer_bond_order == "INF": 327 inf = True 328 max_mayer_bond_order = -1 329 # -1 to prevent exception 330 else: 331 inf = False 332 333 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 334 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 335 336 self = cls() 337 self.id_of_bond = id_of_bond 338 self.atom_symbol_1 = atom_symbol_1 339 self.atom_symbol_2 = atom_symbol_2 340 self.q_i_units = {} 341 for atom_1_id in atom_1_ids: 342 343 self.q_i_units.update({atom_1_id: 0}) 344 345 for atom_2_id in atom_2_ids: 346 mbo = mayer_bond_orders\ 347 .get_mayer_bond_order_between_atoms(atom_1_id, 348 atom_2_id) 349 if (mbo > min_mayer_bond_order 350 and (mbo < max_mayer_bond_order or inf)): 351 352 for atom_3_id in atom_1_ids: 353 mbo = mayer_bond_orders\ 354 .get_mayer_bond_order_between_atoms(atom_2_id, 355 atom_3_id) 356 if (mbo > min_mayer_bond_order 357 and (mbo < max_mayer_bond_order or inf) 358 and atom_3_id != atom_1_id): 359 360 self.q_i_units[atom_1_id] += 1 361 break 362 363 else: 364 continue 365 366 return self 367 368 def calculate_statistics(self): 369 """Calculate statistics in object QiUnits. 370 371 Returns: 372 **QiUnits**: QiUnits object. 373 374 """ 375 376 unique_values = [] 377 for value in self.q_i_units.values(): 378 if value not in unique_values: 379 unique_values.append(value) 380 381 quantities = {} 382 for unique in unique_values: 383 quantities.update({unique: 0}) 384 for value in self.q_i_units.values(): 385 if value == unique: 386 quantities[unique] += 1 387 else: 388 continue 389 390 quantity_of_all_Q_i = len(self.q_i_units) 391 392 self.statistics = {} 393 394 for key, value in quantities.items(): 395 self.statistics.update({key: (value/quantity_of_all_Q_i) * 100}) 396 397 return self 398 399 def to_string(self) -> str: 400 """Generate string representing object. 401 402 Returns: 403 **str**: String. 404 405 """ 406 string = "Q_i of " + str(self.atom_symbol_1) + ' bond id: '\ 407 + str(self.id_of_bond) + "\n\n" 408 409 string += "id Q_i[i]\n" 410 411 for key, value in self.q_i_units.items(): 412 string = string + str(key) + ' ' + str(value) + '\n' 413 414 string += '\n' 415 416 if self.statistics is not None: 417 string = string + 'Statistics of Q_i: ' + str(self.atom_symbol_1)\ 418 + ', bond id: ' + str(self.id_of_bond) + '\n\n' 419 420 string += 'Q_i[i] [%]\n' 421 422 for key, value in self.statistics.items(): 423 string = string + str(key) + ' ' + str(round(value, 3)) + '\n' 424 425 string += '\n' 426 427 return string
Stores information about Qi units.
Dictionary stores percentages of Qⁱ units. key - value of i in Qⁱ
298 @classmethod 299 def calculate(cls, mayer_bond_orders: MayerBondOrders, 300 atom_symbol_1: str, 301 atom_symbol_2: str, 302 max_mayer_bond_order: float | str, 303 min_mayer_bond_order: float, 304 id_of_bond: str): 305 """Calculate QiUnits object. 306 307 Args: 308 mayer_bond_orders (MayerBondOrders): Object MayerBondOrders. 309 atom_symbol_1 (str): Symbol of central atom. 310 atom_symbol_2 (str): Symbol of ligands. 311 max_mayer_bond_order (float | str): Max Mayer bond order, float or 'INF' for infinite maximum value. 312 min_mayer_bond_order (float): Min Mayer bond order. 313 id_of_bond (str): Name of bond eg. 'P-O'. 314 315 Raises: 316 ValueError: "Wrong type of max_mayer_bond_order!!!!" 317 318 Returns: 319 **QiUnits**: Returns QiUnits object. 320 321 """ 322 323 if max_mayer_bond_order != "INF"\ 324 and not (type(max_mayer_bond_order) is float): 325 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 326 elif max_mayer_bond_order == "INF": 327 inf = True 328 max_mayer_bond_order = -1 329 # -1 to prevent exception 330 else: 331 inf = False 332 333 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 334 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 335 336 self = cls() 337 self.id_of_bond = id_of_bond 338 self.atom_symbol_1 = atom_symbol_1 339 self.atom_symbol_2 = atom_symbol_2 340 self.q_i_units = {} 341 for atom_1_id in atom_1_ids: 342 343 self.q_i_units.update({atom_1_id: 0}) 344 345 for atom_2_id in atom_2_ids: 346 mbo = mayer_bond_orders\ 347 .get_mayer_bond_order_between_atoms(atom_1_id, 348 atom_2_id) 349 if (mbo > min_mayer_bond_order 350 and (mbo < max_mayer_bond_order or inf)): 351 352 for atom_3_id in atom_1_ids: 353 mbo = mayer_bond_orders\ 354 .get_mayer_bond_order_between_atoms(atom_2_id, 355 atom_3_id) 356 if (mbo > min_mayer_bond_order 357 and (mbo < max_mayer_bond_order or inf) 358 and atom_3_id != atom_1_id): 359 360 self.q_i_units[atom_1_id] += 1 361 break 362 363 else: 364 continue 365 366 return self
Calculate QiUnits object.
Arguments:
- mayer_bond_orders (MayerBondOrders): Object MayerBondOrders.
- atom_symbol_1 (str): Symbol of central atom.
- atom_symbol_2 (str): Symbol of ligands.
- max_mayer_bond_order (float | str): Max Mayer bond order, float or 'INF' for infinite maximum value.
- min_mayer_bond_order (float): Min Mayer bond order.
- id_of_bond (str): Name of bond eg. 'P-O'.
Raises:
- ValueError: "Wrong type of max_mayer_bond_order!!!!"
Returns:
QiUnits: Returns QiUnits object.
368 def calculate_statistics(self): 369 """Calculate statistics in object QiUnits. 370 371 Returns: 372 **QiUnits**: QiUnits object. 373 374 """ 375 376 unique_values = [] 377 for value in self.q_i_units.values(): 378 if value not in unique_values: 379 unique_values.append(value) 380 381 quantities = {} 382 for unique in unique_values: 383 quantities.update({unique: 0}) 384 for value in self.q_i_units.values(): 385 if value == unique: 386 quantities[unique] += 1 387 else: 388 continue 389 390 quantity_of_all_Q_i = len(self.q_i_units) 391 392 self.statistics = {} 393 394 for key, value in quantities.items(): 395 self.statistics.update({key: (value/quantity_of_all_Q_i) * 100}) 396 397 return self
Calculate statistics in object QiUnits.
Returns:
QiUnits: QiUnits object.
399 def to_string(self) -> str: 400 """Generate string representing object. 401 402 Returns: 403 **str**: String. 404 405 """ 406 string = "Q_i of " + str(self.atom_symbol_1) + ' bond id: '\ 407 + str(self.id_of_bond) + "\n\n" 408 409 string += "id Q_i[i]\n" 410 411 for key, value in self.q_i_units.items(): 412 string = string + str(key) + ' ' + str(value) + '\n' 413 414 string += '\n' 415 416 if self.statistics is not None: 417 string = string + 'Statistics of Q_i: ' + str(self.atom_symbol_1)\ 418 + ', bond id: ' + str(self.id_of_bond) + '\n\n' 419 420 string += 'Q_i[i] [%]\n' 421 422 for key, value in self.statistics.items(): 423 string = string + str(key) + ' ' + str(round(value, 3)) + '\n' 424 425 string += '\n' 426 427 return string
Generate string representing object.
Returns:
str: String.
430@dataclass 431class Connection: 432 """An object represents connections between two elements.""" 433 id_atom_2 = int 434 mayer_bond_order = float 435 436 atom_symbol_2: str 437 """Ligant atom symbol.""" 438 bond_id: str 439 """Bond id eg. 'P-O'""" 440 quantity: int 441 """Quantity of given connections""" 442 bonds: dict[id_atom_2, mayer_bond_order] 443 """**key**- ligand id, **value**-mayer bond order."""
An object represents connections between two elements.
446class Connections(Calculations): 447 """Object represents connections of given atom to nearest neighbors. 448 """ 449 atom_1_id: TypeAlias = int 450 Connection: type = Connection 451 452 connections: dict[atom_1_id, list[Connection]] 453 """Key - central atom, values - list to Connection objects.""" 454 atom_symbol_1: str 455 """Symbol of central atom.""" 456 457 @ classmethod 458 def calculate(cls, mayer_bond_orders: MayerBondOrders, 459 atom_symbol_1: str, 460 pairs_atoms_list: list[PairOfAtoms] 461 ): 462 """Calculate Connections object. 463 464 Args: 465 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 466 atom_symbol_1 (str): Central atom symbol. 467 pairs_atoms_list (list[PairOfAtoms]): list of PairsOfAtoms objects. 468 469 Raises: 470 ValueError: "Wrong type of max_mayer_bond_order!!!!" 471 472 Returns: 473 **Connections**: Connections object. 474 475 """ 476 477 pair_atom_list_containing_atom_1 = [] 478 for pair_atom in pairs_atoms_list: 479 if pair_atom.atom_1 == atom_symbol_1\ 480 or pair_atom.atom_2 == atom_symbol_1: 481 482 pair_atom_list_containing_atom_1.append(pair_atom) 483 else: 484 continue 485 486 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 487 connections = {} 488 for atom_1_id in atom_1_ids: 489 490 connections.update({atom_1_id: []}) 491 492 for pair_atoms in pair_atom_list_containing_atom_1: 493 if (v := pair_atoms.atom_1) != atom_symbol_1: 494 atom_symbol_2 = v 495 else: 496 atom_symbol_2 = pair_atoms.atom_2 497 498 connection = cls.Connection( 499 atom_symbol_2, pair_atoms.id, 0, {}) 500 501 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 502 503 for atom_2_id in atom_2_ids: 504 if pair_atoms.MBO_max != "INF"\ 505 and not (type(pair_atoms.MBO_max) is float): 506 raise ValueError( 507 "Wrong type of max_mayer_bond_order!!!!") 508 509 mbo = mayer_bond_orders\ 510 .get_mayer_bond_order_between_atoms(atom_1_id, 511 atom_2_id) 512 513 if (mbo > pair_atoms.MBO_min 514 and pair_atoms.MBO_max == 'INF'): 515 516 connection.quantity += 1 517 connection.bonds.update({atom_2_id: mbo}) 518 519 elif (pair_atoms.MBO_max != 'INF'): 520 if (mbo > pair_atoms.MBO_min 521 and pair_atoms.MBO_max > mbo): 522 523 connection.quantity += 1 524 connection.bonds.update({atom_2_id: mbo}) 525 526 connections[atom_1_id].append(connection) 527 528 self = cls() 529 self.connections = connections 530 self.atom_symbol_1 = atom_symbol_1 531 532 return self 533 534 def to_string(self) -> str: 535 """Generates string representation of object. 536 537 Returns: 538 **str**: string. 539 540 """ 541 string = '## Connections of: ' + str(self.atom_symbol_1) + '\n\n' 542 543 for atom_1_id, list_of_connections in self.connections.items(): 544 string = string + "### Central atom id: " + str(atom_1_id) + "\n" 545 546 for connection in list_of_connections: 547 548 string = string + f"Bond id: {str(connection.bond_id)} "\ 549 + f"(second atom: {str(connection.atom_symbol_2)})\n"\ 550 + f"quantity: {connection.quantity}\n"\ 551 + "Bonds:\n" 552 553 string_id_line = "id: " 554 string_mbo_line = "mbo: " 555 556 for id, mbo in connection.bonds.items(): 557 string_id_line += f"{id} " 558 string_mbo_line += f"{round(mbo, 3)} " 559 560 string = string + string_id_line + '\n'\ 561 + string_mbo_line + '\n\n' 562 563 return string
Object represents connections of given atom to nearest neighbors.
Key - central atom, values - list to Connection objects.
457 @ classmethod 458 def calculate(cls, mayer_bond_orders: MayerBondOrders, 459 atom_symbol_1: str, 460 pairs_atoms_list: list[PairOfAtoms] 461 ): 462 """Calculate Connections object. 463 464 Args: 465 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 466 atom_symbol_1 (str): Central atom symbol. 467 pairs_atoms_list (list[PairOfAtoms]): list of PairsOfAtoms objects. 468 469 Raises: 470 ValueError: "Wrong type of max_mayer_bond_order!!!!" 471 472 Returns: 473 **Connections**: Connections object. 474 475 """ 476 477 pair_atom_list_containing_atom_1 = [] 478 for pair_atom in pairs_atoms_list: 479 if pair_atom.atom_1 == atom_symbol_1\ 480 or pair_atom.atom_2 == atom_symbol_1: 481 482 pair_atom_list_containing_atom_1.append(pair_atom) 483 else: 484 continue 485 486 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 487 connections = {} 488 for atom_1_id in atom_1_ids: 489 490 connections.update({atom_1_id: []}) 491 492 for pair_atoms in pair_atom_list_containing_atom_1: 493 if (v := pair_atoms.atom_1) != atom_symbol_1: 494 atom_symbol_2 = v 495 else: 496 atom_symbol_2 = pair_atoms.atom_2 497 498 connection = cls.Connection( 499 atom_symbol_2, pair_atoms.id, 0, {}) 500 501 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 502 503 for atom_2_id in atom_2_ids: 504 if pair_atoms.MBO_max != "INF"\ 505 and not (type(pair_atoms.MBO_max) is float): 506 raise ValueError( 507 "Wrong type of max_mayer_bond_order!!!!") 508 509 mbo = mayer_bond_orders\ 510 .get_mayer_bond_order_between_atoms(atom_1_id, 511 atom_2_id) 512 513 if (mbo > pair_atoms.MBO_min 514 and pair_atoms.MBO_max == 'INF'): 515 516 connection.quantity += 1 517 connection.bonds.update({atom_2_id: mbo}) 518 519 elif (pair_atoms.MBO_max != 'INF'): 520 if (mbo > pair_atoms.MBO_min 521 and pair_atoms.MBO_max > mbo): 522 523 connection.quantity += 1 524 connection.bonds.update({atom_2_id: mbo}) 525 526 connections[atom_1_id].append(connection) 527 528 self = cls() 529 self.connections = connections 530 self.atom_symbol_1 = atom_symbol_1 531 532 return self
Calculate Connections object.
Arguments:
- mayer_bond_orders (MayerBondOrders): MayerBondOrders object.
- atom_symbol_1 (str): Central atom symbol.
- pairs_atoms_list (list[PairOfAtoms]): list of PairsOfAtoms objects.
Raises:
- ValueError: "Wrong type of max_mayer_bond_order!!!!"
Returns:
Connections: Connections object.
534 def to_string(self) -> str: 535 """Generates string representation of object. 536 537 Returns: 538 **str**: string. 539 540 """ 541 string = '## Connections of: ' + str(self.atom_symbol_1) + '\n\n' 542 543 for atom_1_id, list_of_connections in self.connections.items(): 544 string = string + "### Central atom id: " + str(atom_1_id) + "\n" 545 546 for connection in list_of_connections: 547 548 string = string + f"Bond id: {str(connection.bond_id)} "\ 549 + f"(second atom: {str(connection.atom_symbol_2)})\n"\ 550 + f"quantity: {connection.quantity}\n"\ 551 + "Bonds:\n" 552 553 string_id_line = "id: " 554 string_mbo_line = "mbo: " 555 556 for id, mbo in connection.bonds.items(): 557 string_id_line += f"{id} " 558 string_mbo_line += f"{round(mbo, 3)} " 559 560 string = string + string_id_line + '\n'\ 561 + string_mbo_line + '\n\n' 562 563 return string
Generates string representation of object.
Returns:
str: string.
430@dataclass 431class Connection: 432 """An object represents connections between two elements.""" 433 id_atom_2 = int 434 mayer_bond_order = float 435 436 atom_symbol_2: str 437 """Ligant atom symbol.""" 438 bond_id: str 439 """Bond id eg. 'P-O'""" 440 quantity: int 441 """Quantity of given connections""" 442 bonds: dict[id_atom_2, mayer_bond_order] 443 """**key**- ligand id, **value**-mayer bond order."""
An object represents connections between two elements.
Inherited Members
566class Covalence(Calculations): 567 """Object storages covalences of atoms""" 568 covalence: dict[int, float] 569 """Key - id of atom, value - covalence calculated from Mayer bond orders.""" 570 atom_symbol: str 571 """Atom symbol.""" 572 573 @ classmethod 574 def calculate(cls, mayer_bond_orders: MayerBondOrders, 575 atom_symbol: str): 576 """Calculate Covalence object. 577 578 Args: 579 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 580 atom_symbol (str): Atom symbol. 581 582 Returns: 583 **Covalence**: Covalence object. 584 585 """ 586 587 atom_ids = mayer_bond_orders.get_atoms_ids(atom_symbol) 588 589 self = cls() 590 self.atom_symbol = atom_symbol 591 self.covalence = {} 592 for id in atom_ids: 593 mbos = mayer_bond_orders.get_all_mayer_bond_orders_of_atom(id) 594 self.covalence.update({id: sum(mbos)}) 595 596 return self 597 598 def to_string(self) -> str: 599 """Generates string representation of object. 600 601 Returns: 602 **str**: String. 603 604 """ 605 string = f'Covalence of {self.atom_symbol}.\n\n'\ 606 + 'id COV\n' 607 608 for id, value in self.covalence.items(): 609 string = string + f'{id} {value:.3f}\n' 610 string += '\n' 611 612 return string
Object storages covalences of atoms
573 @ classmethod 574 def calculate(cls, mayer_bond_orders: MayerBondOrders, 575 atom_symbol: str): 576 """Calculate Covalence object. 577 578 Args: 579 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 580 atom_symbol (str): Atom symbol. 581 582 Returns: 583 **Covalence**: Covalence object. 584 585 """ 586 587 atom_ids = mayer_bond_orders.get_atoms_ids(atom_symbol) 588 589 self = cls() 590 self.atom_symbol = atom_symbol 591 self.covalence = {} 592 for id in atom_ids: 593 mbos = mayer_bond_orders.get_all_mayer_bond_orders_of_atom(id) 594 self.covalence.update({id: sum(mbos)}) 595 596 return self
Calculate Covalence object.
Arguments:
- mayer_bond_orders (MayerBondOrders): MayerBondOrders object.
- atom_symbol (str): Atom symbol.
Returns:
Covalence: Covalence object.
598 def to_string(self) -> str: 599 """Generates string representation of object. 600 601 Returns: 602 **str**: String. 603 604 """ 605 string = f'Covalence of {self.atom_symbol}.\n\n'\ 606 + 'id COV\n' 607 608 for id, value in self.covalence.items(): 609 string = string + f'{id} {value:.3f}\n' 610 string += '\n' 611 612 return string
Generates string representation of object.
Returns:
str: String.
615class BondLength(Calculations): 616 """Object stored bond lengths of pairs of atoms.""" 617 atom_id_1: TypeAlias = int 618 atom_id_2: TypeAlias = int 619 620 id_of_bond: str 621 """Id of bond eg. 'P-O'""" 622 atom_symbol_1: str 623 """Atom 1 symbol.""" 624 atom_symbol_2: str 625 """Atom 2 symbol.""" 626 lengths: dict[atom_id_1, dict[atom_id_2, float]] 627 """**values**- length between atoms.""" 628 mbos: dict[atom_id_1, dict[atom_id_2, float]] 629 """**values**- Mayer bond orders""" 630 631 @ classmethod 632 def calculate(cls, 633 mayer_bond_orders: MayerBondOrders, 634 coordinates_of_atoms: CoordinatesOfAtoms, 635 atom_symbol_1: str, 636 atom_symbol_2: str, 637 max_mayer_bond_order: float | str, 638 min_mayer_bond_order: float, 639 id_of_bond: str): 640 """Calculate BondLength object. 641 642 Args: 643 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 644 coordinates_of_atoms (CoordinatesOfAtoms): CoordinatesOfAtom object. 645 atom_symbol_1 (str): Symbol of atom 1. 646 atom_symbol_2 (str): Symbol of atom 2. 647 max_mayer_bond_order (float | str): max value of Mayer bond order or 'INF for infinite value. 648 min_mayer_bond_order (float): min value of Mayer bond order. 649 id_of_bond (str): id of bond eg. 'P-O' 650 651 Raises: 652 ValueError: "Wrong type of max_mayer_bond_order!!!!" 653 654 Returns: 655 **BondLength**: BondLength object. 656 657 """ 658 659 if max_mayer_bond_order != "INF"\ 660 and not (type(max_mayer_bond_order) is float): 661 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 662 elif max_mayer_bond_order == "INF": 663 inf = True 664 max_mayer_bond_order = -1 665 # -1 to prevent exception 666 else: 667 inf = False 668 669 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 670 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 671 672 self = cls() 673 self.id_of_bond = id_of_bond 674 self.atom_symbol_1 = atom_symbol_1 675 self.atom_symbol_2 = atom_symbol_2 676 self.lengths = {} 677 self.mbos = {} 678 679 for atom_1_id in atom_1_ids: 680 self.lengths.update({atom_1_id: {}}) 681 self.mbos.update({atom_1_id: {}}) 682 for atom_2_id in atom_2_ids: 683 mbo = mayer_bond_orders\ 684 .get_mayer_bond_order_between_atoms(atom_1_id, 685 atom_2_id) 686 687 length = coordinates_of_atoms\ 688 .get_distance_between_atoms(atom_1_id, atom_2_id) 689 690 if mbo > min_mayer_bond_order and ( 691 mbo < max_mayer_bond_order 692 or inf is True 693 ): 694 self.lengths[atom_1_id].update({atom_2_id: length}) 695 self.mbos[atom_1_id].update({atom_2_id: mbo}) 696 else: 697 continue 698 699 # remove empty keys. 700 701 for key in list(self.lengths.keys()): 702 if self.lengths[key] == {}: 703 del self.lengths[key] 704 del self.mbos[key] 705 706 return self 707 708 def to_string(self) -> str: 709 """Generates string representation of object. 710 711 Returns: 712 **str**: String. 713 714 """ 715 string = f'Bond lengths of bond id: {self.id_of_bond} '\ 716 + f'(atoms: {self.atom_symbol_1}, {self.atom_symbol_2}):\n\n'\ 717 + 'id_1 id_2 length mbo\n' 718 719 for key_1 in self.lengths.keys(): 720 for key_2 in self.lengths[key_1].keys(): 721 string = string + f'{key_1} {key_2} '\ 722 + f'{self.lengths[key_1][key_2]} '\ 723 + f'{self.mbos[key_1][key_2]}\n' 724 725 string += '\n' 726 727 return string
Object stored bond lengths of pairs of atoms.
631 @ classmethod 632 def calculate(cls, 633 mayer_bond_orders: MayerBondOrders, 634 coordinates_of_atoms: CoordinatesOfAtoms, 635 atom_symbol_1: str, 636 atom_symbol_2: str, 637 max_mayer_bond_order: float | str, 638 min_mayer_bond_order: float, 639 id_of_bond: str): 640 """Calculate BondLength object. 641 642 Args: 643 mayer_bond_orders (MayerBondOrders): MayerBondOrders object. 644 coordinates_of_atoms (CoordinatesOfAtoms): CoordinatesOfAtom object. 645 atom_symbol_1 (str): Symbol of atom 1. 646 atom_symbol_2 (str): Symbol of atom 2. 647 max_mayer_bond_order (float | str): max value of Mayer bond order or 'INF for infinite value. 648 min_mayer_bond_order (float): min value of Mayer bond order. 649 id_of_bond (str): id of bond eg. 'P-O' 650 651 Raises: 652 ValueError: "Wrong type of max_mayer_bond_order!!!!" 653 654 Returns: 655 **BondLength**: BondLength object. 656 657 """ 658 659 if max_mayer_bond_order != "INF"\ 660 and not (type(max_mayer_bond_order) is float): 661 raise ValueError("Wrong type of max_mayer_bond_order!!!!") 662 elif max_mayer_bond_order == "INF": 663 inf = True 664 max_mayer_bond_order = -1 665 # -1 to prevent exception 666 else: 667 inf = False 668 669 atom_1_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_1) 670 atom_2_ids = mayer_bond_orders.get_atoms_ids(atom_symbol_2) 671 672 self = cls() 673 self.id_of_bond = id_of_bond 674 self.atom_symbol_1 = atom_symbol_1 675 self.atom_symbol_2 = atom_symbol_2 676 self.lengths = {} 677 self.mbos = {} 678 679 for atom_1_id in atom_1_ids: 680 self.lengths.update({atom_1_id: {}}) 681 self.mbos.update({atom_1_id: {}}) 682 for atom_2_id in atom_2_ids: 683 mbo = mayer_bond_orders\ 684 .get_mayer_bond_order_between_atoms(atom_1_id, 685 atom_2_id) 686 687 length = coordinates_of_atoms\ 688 .get_distance_between_atoms(atom_1_id, atom_2_id) 689 690 if mbo > min_mayer_bond_order and ( 691 mbo < max_mayer_bond_order 692 or inf is True 693 ): 694 self.lengths[atom_1_id].update({atom_2_id: length}) 695 self.mbos[atom_1_id].update({atom_2_id: mbo}) 696 else: 697 continue 698 699 # remove empty keys. 700 701 for key in list(self.lengths.keys()): 702 if self.lengths[key] == {}: 703 del self.lengths[key] 704 del self.mbos[key] 705 706 return self
Calculate BondLength object.
Arguments:
- mayer_bond_orders (MayerBondOrders): MayerBondOrders object.
- coordinates_of_atoms (CoordinatesOfAtoms): CoordinatesOfAtom object.
- atom_symbol_1 (str): Symbol of atom 1.
- atom_symbol_2 (str): Symbol of atom 2.
- max_mayer_bond_order (float | str): max value of Mayer bond order or 'INF for infinite value.
- min_mayer_bond_order (float): min value of Mayer bond order.
- id_of_bond (str): id of bond eg. 'P-O'
Raises:
- ValueError: "Wrong type of max_mayer_bond_order!!!!"
Returns:
BondLength: BondLength object.
708 def to_string(self) -> str: 709 """Generates string representation of object. 710 711 Returns: 712 **str**: String. 713 714 """ 715 string = f'Bond lengths of bond id: {self.id_of_bond} '\ 716 + f'(atoms: {self.atom_symbol_1}, {self.atom_symbol_2}):\n\n'\ 717 + 'id_1 id_2 length mbo\n' 718 719 for key_1 in self.lengths.keys(): 720 for key_2 in self.lengths[key_1].keys(): 721 string = string + f'{key_1} {key_2} '\ 722 + f'{self.lengths[key_1][key_2]} '\ 723 + f'{self.mbos[key_1][key_2]}\n' 724 725 string += '\n' 726 727 return string
Generates string representation of object.
Returns:
str: String.