DescripyTor 0.3.2__tar.gz → 0.4.3__tar.gz
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 DescripyTor might be problematic. Click here for more details.
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/build.py +17 -6
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/cluster.py +8 -5
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/stages.py +2 -0
- descripytor-0.4.3/M2_data_extractor/alignment.py +277 -0
- descripytor-0.4.3/M2_data_extractor/atom_picker.html +6161 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/data_extractor.py +121 -57
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/descriptor_extractor.py +1 -1
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feather_extractor.py +12 -10
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/build.py +1 -2
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/feature_explorer.html +64 -22
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/scene.js +24 -5
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/template.html +38 -17
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/gaussian_handler.py +2 -2
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/gui_server.py +403 -861
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/ligand_topology.py +223 -223
- descripytor-0.4.3/M2_data_extractor/orca_reader.py +120 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/01_common_part.svg +206 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/02_complete_rings.svg +51 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/03_extend_mcs.svg +54 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/04_coords_proximity_any.svg +51 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/05_equivalent_atoms.svg +116 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/06_the_fit.svg +125 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/guide.json +32 -0
- descripytor-0.4.3/M2_data_extractor/static/align_guide/make_guide.py +239 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/theta_explorer/theta_explorer.html +64 -22
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/xtb_singlepoint.py +236 -236
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/xyz_io.py +308 -308
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/batch.py +2 -1
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/build_case.py +94 -16
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/engine.py +15 -1
- descripytor-0.4.3/M3_modeler/bassa_explorer/featurize.py +351 -0
- descripytor-0.4.3/M3_modeler/bassa_explorer/index.html +2264 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/running.py +61 -61
- descripytor-0.4.3/M3_modeler/bassa_explorer/server.py +278 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/settings.py +22 -2
- {descripytor-0.3.2 → descripytor-0.4.3}/PKG-INFO +7 -17
- {descripytor-0.3.2 → descripytor-0.4.3}/README.md +474 -481
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/__init__.py +5 -5
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/cli.py +755 -644
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/__init__.py +5 -0
- descripytor-0.4.3/descripytor/examples/conformaty_rings/README.md +17 -0
- descripytor-0.4.3/descripytor/examples/conformaty_rings/stage_order_query.xyz +21 -0
- descripytor-0.4.3/descripytor/examples/conformaty_rings/stage_order_ref.xyz +20 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor.egg-info/PKG-INFO +7 -17
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor.egg-info/SOURCES.txt +18 -11
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor.egg-info/requires.txt +0 -4
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor.egg-info/top_level.txt +0 -1
- {descripytor-0.3.2 → descripytor-0.4.3}/pyproject.toml +111 -111
- descripytor-0.4.3/tests/test_alignment.py +163 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_bassa_explorer.py +67 -0
- descripytor-0.4.3/tests/test_gaussian_info.py +30 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_gui_server.py +134 -23
- descripytor-0.4.3/tests/test_input_kinds.py +84 -0
- descripytor-0.4.3/tests/test_picker_logic.py +123 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_pipeline.py +49 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/help_functions.py +10 -13
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/mode_viewer.py +8 -2
- descripytor-0.3.2/M2_data_extractor/atom_picker.html +0 -5440
- descripytor-0.3.2/M2_data_extractor/feature_extraction_gui.html +0 -6682
- descripytor-0.3.2/M2_data_extractor/static/3Dmol-min.js +0 -2
- descripytor-0.3.2/M3_modeler/bassa_explorer/index.html +0 -884
- descripytor-0.3.2/M3_modeler/bassa_explorer/server.py +0 -175
- descripytor-0.3.2/MolAlign/MCS_optimization.py +0 -131
- descripytor-0.3.2/MolAlign/RDKIT_utils.py +0 -655
- descripytor-0.3.2/MolAlign/df_funs.py +0 -99
- descripytor-0.3.2/MolAlign/fmcs.py +0 -2654
- descripytor-0.3.2/MolAlign/gaussian_handler.py +0 -193
- descripytor-0.3.2/MolAlign/loss.py +0 -19
- descripytor-0.3.2/MolAlign/renumbering.py +0 -821
- descripytor-0.3.2/MolAlign/rotations.py +0 -14
- descripytor-0.3.2/utils/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/Getting_started_with_examples/descriptor_extraction_toolkit/config_example.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/Getting_started_with_examples/input_example.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/LICENSE +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/esp_grid_driver.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/main.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/outwards_senders.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/adopt.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/checks.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/examples/phosphines.csv +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/examples/protocol_bgu.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M1_pre_calculations/pipeline/protocol.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/_folder_dialog.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/crest_boltzmann_sterimol.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/cube_sterimol.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/bond_angle_length_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/bond_graph.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/dipole_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/esp_grid_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/sterimol_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/extractor_utils/vibrations_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/data.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/009_phos.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/009_phos_CuCl.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/026_box_CuCl.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/026_lig.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/032_lig.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/041_lig.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/045_box_CuCl.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/045_lig.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/046_lig.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/055_phos.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Cu_BOX_008.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Cu_BOX_018.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Cu_BOX_020.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Cu_BOX_047.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Cu_PyOx_041.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_1.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_1.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_12.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_12.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_13_str_target.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_13_str_target.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_7.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/FL_lig_7.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Ni_BOX_072.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/Ni_BOX_078.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/benzoic_acid.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-CN.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-CN.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-CN_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-CN_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-OMe.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-OMe.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-OMe_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-OMe_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-SO2Me_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/m-SO2Me_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/naphthyl_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/naphthyl_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/o-Me_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/o-Me_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-CF3.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-CF3.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-CF3_substrate.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-CO2Me_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-CO2Me_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-COMe_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-COMe_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-Cl_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-Cl_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-F_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-F_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-H_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-H_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-NO2.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-NO2.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-OMe_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-OMe_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-Otf.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-Otf.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-Otf_substrate.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-t-Bu_BA.data.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/fixtures/p-t-Bu_BA.xyz +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/gate.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/gate_pos.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/make_pos_refs.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/make_refs.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/pos_refs.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/promol.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/rdkit/RDKit_minimal.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/rdkit/RDKit_minimal.wasm +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/refs.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/render_presets.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/smarts.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/smoke.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/sterimol.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_explorer/vbur.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/feature_packages.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/metal_complex.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/morfeus_sterics.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/placement_search.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/sterimol_standalone.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/theta_explorer/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/theta_explorer/build.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/theta_explorer/data.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M2_data_extractor/theta_explorer/sterimol.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/core_fixed.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/example.js +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/example_cs2.csv +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/example_small.csv +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/influence_check.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/read_structures.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/bassa_explorer/test_page.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/modeling.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/modeling_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/nested_cv.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/plot.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/ridge_search.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/M3_modeler/validation.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/MANIFEST.in +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/__main__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/compat.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/README.md +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/m-CN.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/m-COMe.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/m-NO2.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/m-OMe.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/m-cyclo.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/o-CN.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/outcomes.csv +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-CF3.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-CHO.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-CN.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-COOMe.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-Cl.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-MeO.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-NO2.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-OMe.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/p-Otf.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/presets.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/pyridine-m-OMe.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/thiophene.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/baptiste_products/unsub.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/config_example.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/README.md +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/basic.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/input_example.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/m_Br.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/m_Cl.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/m_nitro.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/o_Br.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/o_Cl.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/o_F.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/p_Cl.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/p_F.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/p_I.feather +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/feather_example/presets.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor/examples/input_example.json +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor.egg-info/dependency_links.txt +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/descripytor.egg-info/entry_points.txt +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/setup.cfg +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/setup.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_arm_fixes.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_bond_graph.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_cli.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_compat.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_connectivity.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_esp_grid.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_examples.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_extract_and_model.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_feature_fixes.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_metal_complex.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_metal_complex_frame.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_ridge_search.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_sterimol_b1_normal.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_sterimol_loc_b1.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_two_csv.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/tests/test_validation.py +0 -0
- {descripytor-0.3.2/MolAlign → descripytor-0.4.3/utils}/__init__.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/console.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/constants.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/file_handlers.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/mode_viewer.html +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/rdkit_utils.py +0 -0
- {descripytor-0.3.2 → descripytor-0.4.3}/utils/visualize.py +0 -0
|
@@ -76,13 +76,17 @@ def _embed(smiles: str, n_conf: int, seed: int, pair=None, pair_range=(2.5, 3.0)
|
|
|
76
76
|
mol = Chem.AddHs(mol)
|
|
77
77
|
params = AllChem.ETKDGv3()
|
|
78
78
|
params.randomSeed = seed
|
|
79
|
+
pair_held = bool(pair)
|
|
79
80
|
if pair:
|
|
80
81
|
from rdkit import DistanceGeometry
|
|
81
82
|
from rdkit.Chem import rdDistGeom
|
|
82
83
|
i, j = sorted(pair)
|
|
83
84
|
bm = rdDistGeom.GetMoleculeBoundsMatrix(mol)
|
|
84
85
|
bm[i][j], bm[j][i] = pair_range[1], pair_range[0] # upper triangle = max, lower = min
|
|
85
|
-
DistanceGeometry.DoTriangleSmoothing(bm)
|
|
86
|
+
if not DistanceGeometry.DoTriangleSmoothing(bm):
|
|
87
|
+
# a rigid ligand (fused biimidazoline) fixes the donor distance outside this range: embed it as it is,
|
|
88
|
+
# and let the bite-angle test decide. Another donor pair must not win just because it is flexible.
|
|
89
|
+
bm = rdDistGeom.GetMoleculeBoundsMatrix(mol); DistanceGeometry.DoTriangleSmoothing(bm); pair_held = False
|
|
86
90
|
params.SetBoundsMat(bm)
|
|
87
91
|
params.useExpTorsionAnglePrefs = False # the torsion library holds bipyridine anti over the bound
|
|
88
92
|
cids = list(AllChem.EmbedMultipleConfs(mol, n_conf, params))
|
|
@@ -93,9 +97,9 @@ def _embed(smiles: str, n_conf: int, seed: int, pair=None, pair_range=(2.5, 3.0)
|
|
|
93
97
|
energy = {}
|
|
94
98
|
for cid in cids:
|
|
95
99
|
ff = AllChem.MMFFGetMoleculeForceField(mol, props, confId=cid) if mmff else AllChem.UFFGetMoleculeForceField(mol, confId=cid)
|
|
96
|
-
if
|
|
100
|
+
if pair_held and mmff:
|
|
97
101
|
ff.MMFFAddDistanceConstraint(pair[0], pair[1], False, pair_range[0], pair_range[1] - 0.1, 100.0)
|
|
98
|
-
elif
|
|
102
|
+
elif pair_held:
|
|
99
103
|
ff.UFFAddDistanceConstraint(pair[0], pair[1], False, pair_range[0], pair_range[1] - 0.1, 100.0)
|
|
100
104
|
ff.Minimize(maxIts=2000)
|
|
101
105
|
energy[cid] = ff.CalcEnergy()
|
|
@@ -131,6 +135,7 @@ def _relax_around_metal(mol, cid, m, donors, dists):
|
|
|
131
135
|
rw.AddBond(int(d), k, Chem.BondType.SINGLE)
|
|
132
136
|
cx = rw.GetMol()
|
|
133
137
|
cx.UpdatePropertyCache(strict=False)
|
|
138
|
+
Chem.FastFindRings(cx) # the stand-in closes a new ring (the chelate); UFF typing needs ring info
|
|
134
139
|
atom = cx.GetAtomWithIdx(k)
|
|
135
140
|
atom.SetHybridization(Chem.HybridizationType.SP3)
|
|
136
141
|
atom.SetNoImplicit(True)
|
|
@@ -182,14 +187,16 @@ def _ancillaries(m, d1, d2, ligand, dist, n, target):
|
|
|
182
187
|
out = []
|
|
183
188
|
for u in ideal:
|
|
184
189
|
best, bestd = u, -1.0
|
|
190
|
+
clear = np.vstack([ligand] + out) # the ancillaries placed so far count too: two tilting Cl ended up 1.1-2.3 A apart
|
|
185
191
|
perp = np.cross(nrm, u)
|
|
186
192
|
perp /= np.linalg.norm(perp)
|
|
187
193
|
for tilt in np.radians([0, 10, 20, 30]):
|
|
188
|
-
|
|
194
|
+
# square planar: tilt out of the plane only; an in-plane turn walks one Cl into the other's site
|
|
195
|
+
for phi in (np.pi / 2, 3 * np.pi / 2) if n == 2 else np.linspace(0, 2 * np.pi, 12, endpoint=False):
|
|
189
196
|
axis = np.cos(phi) * nrm + np.sin(phi) * perp
|
|
190
197
|
v = u * np.cos(tilt) + np.cross(axis, u) * np.sin(tilt)
|
|
191
198
|
v /= np.linalg.norm(v)
|
|
192
|
-
score = min(np.linalg.norm(
|
|
199
|
+
score = min(np.linalg.norm(clear - (m + v * dist), axis=1).min(), target) - 0.15 * tilt
|
|
193
200
|
if score > bestd:
|
|
194
201
|
best, bestd = v, score
|
|
195
202
|
if bestd > 0.9 * target:
|
|
@@ -297,7 +304,11 @@ def _build_chelate(smiles, b, n_conf, seed):
|
|
|
297
304
|
raise BuildError("no bidentate donor pair found")
|
|
298
305
|
tried = []
|
|
299
306
|
for i, j in pairs:
|
|
300
|
-
|
|
307
|
+
try:
|
|
308
|
+
mol, confs = _embed(smiles, n_conf, seed, pair=(i, j))
|
|
309
|
+
except BuildError as exc: # this pair cannot chelate: try the next candidate
|
|
310
|
+
tried.append(f"{i + 1}-{j + 1}: {exc}")
|
|
311
|
+
continue
|
|
301
312
|
sym = [a.GetSymbol() for a in mol.GetAtoms()]
|
|
302
313
|
n = len(sym)
|
|
303
314
|
key = {}
|
|
@@ -39,13 +39,13 @@ class Remote:
|
|
|
39
39
|
def __init__(self, host: str, key: str, timeout: int = 180):
|
|
40
40
|
self.host, self.key, self.timeout = host, os.path.expanduser(key), timeout
|
|
41
41
|
|
|
42
|
-
def _ssh(self, command: str) -> str:
|
|
42
|
+
def _ssh(self, command: str, timeout: int | None = None) -> str:
|
|
43
43
|
cmd = ["ssh", "-n", "-T", "-o", "BatchMode=yes", "-o", "ConnectTimeout=30", "-o", "IdentitiesOnly=yes",
|
|
44
44
|
"-i", self.key, self.host, command]
|
|
45
|
-
r = subprocess.run(cmd, capture_output=True, timeout=self.timeout)
|
|
45
|
+
r = subprocess.run(cmd, capture_output=True, timeout=timeout or self.timeout)
|
|
46
46
|
return (r.stdout or b"").decode("utf-8", "replace")
|
|
47
47
|
|
|
48
|
-
def run(self, script: str, tries: int = 3) -> str:
|
|
48
|
+
def run(self, script: str, tries: int = 3, timeout: int | None = None) -> str:
|
|
49
49
|
"""Run a bash script remotely; returns its stdout. Retries when the reply comes back empty
|
|
50
50
|
or cut short (the end marker is missing). Scripts must be safe to run twice."""
|
|
51
51
|
payload = base64.b64encode(f"echo {BEGIN}\n{script}\necho {END}\n".encode()).decode()
|
|
@@ -53,7 +53,7 @@ class Remote:
|
|
|
53
53
|
raise ClusterError("remote script too long for the tcsh login shell; upload it as a file instead")
|
|
54
54
|
last = ""
|
|
55
55
|
for _ in range(tries):
|
|
56
|
-
last = self._ssh(f"echo {payload} | base64 -d | bash")
|
|
56
|
+
last = self._ssh(f"echo {payload} | base64 -d | bash", timeout)
|
|
57
57
|
if BEGIN in last and END in last:
|
|
58
58
|
return last.split(BEGIN, 1)[1].rsplit(END, 1)[0].strip("\n")
|
|
59
59
|
time.sleep(2)
|
|
@@ -125,7 +125,10 @@ def _run_chain(r: Remote, p: Protocol, plan: str, plan_name: str) -> dict:
|
|
|
125
125
|
"""Upload a plan and submit it. Returns {task: {stage: job id}}. Raises on any qsub failure,
|
|
126
126
|
reporting what was submitted, and never resubmits blindly."""
|
|
127
127
|
_put_file(r, p.remote_root, plan_name, plan)
|
|
128
|
-
|
|
128
|
+
# one qsub takes about 2 s on hpcgate, so the reply time grows with the plan: with the default timeout a plan of
|
|
129
|
+
# more than about 30 three-stage molecules was cut off part-way, its job ids lost with the reply
|
|
130
|
+
n_qsub = sum(len(line.split()) - 1 for line in plan.splitlines())
|
|
131
|
+
out = r.run(f"bash {p.remote_root}/submit_chain.sh {p.remote_root}/{plan_name}", tries=1, timeout=max(r.timeout, 60 + 10 * n_qsub))
|
|
129
132
|
jobs, failed = {}, []
|
|
130
133
|
for line in out.splitlines():
|
|
131
134
|
f = line.split()
|
|
@@ -257,7 +257,9 @@ print("converged" if converged else "NOT converged", f, flush=True)
|
|
|
257
257
|
'''
|
|
258
258
|
|
|
259
259
|
GAUSSIAN_BODY = r"""export g16root=@@G16ROOT@@ GAUSS_SCRDIR="$W"
|
|
260
|
+
set +u # g16.profile reads variables that may be unset (PERLLIB); under set -u the job dies with its marker left at "running"
|
|
260
261
|
source "$g16root/g16/bsd/g16.profile"
|
|
262
|
+
set -u
|
|
261
263
|
{
|
|
262
264
|
printf '%%nprocshared=%s\n%%mem=%sGB\n%%chk=%s.chk\n' @@CORES@@ @@MEM@@ "$NAME"
|
|
263
265
|
cat <<'ROUTE'
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""Atom renumbering with Conformaty (github.com/Milo-group/Conformaty): every molecule of a folder numbered like a
|
|
2
|
+
reference, so a descriptor picked on the reference reads the same atom everywhere.
|
|
3
|
+
|
|
4
|
+
The result per molecule is the 1-based {old: new} dict ``Molecule.renumber_atoms`` takes. Conformaty matches the
|
|
5
|
+
largest common substructure, fits the molecule onto the reference and assigns the rest by position, so equivalent
|
|
6
|
+
atoms (the two H of a CH2) are told apart by where they sit. The reference must be the smaller molecule (it is the
|
|
7
|
+
common part); a molecule larger than it keeps its extra atoms after the reference's.
|
|
8
|
+
|
|
9
|
+
from M2_data_extractor.alignment import map_folder, write_renumbered
|
|
10
|
+
results = map_folder(mols, "basic") # mols: a Molecules
|
|
11
|
+
write_renumbered(mols, results, "renumbered")
|
|
12
|
+
"""
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import time
|
|
17
|
+
from concurrent.futures import ProcessPoolExecutor, as_completed
|
|
18
|
+
|
|
19
|
+
INSTALL = "pip install git+https://github.com/Milo-group/Conformaty" # shortcut: a git URL until Conformaty is on PyPI, then the [align] extra
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _conformaty():
|
|
23
|
+
try:
|
|
24
|
+
import conformaty
|
|
25
|
+
except ImportError as exc:
|
|
26
|
+
raise ImportError(f"Atom renumbering needs Conformaty: {INSTALL}") from exc
|
|
27
|
+
return conformaty
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _worker_threads(n):
|
|
31
|
+
import torch
|
|
32
|
+
|
|
33
|
+
torch.set_num_threads(n) # one: the fits are a few dozen atoms, where more threads only add overhead
|
|
34
|
+
_conformaty() # import torch and Conformaty once per process, not on every molecule
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
_POOL = {"pool": None, "n": 0} # the worker processes, kept between runs: starting one and importing costs ~5 s
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _pool(workers):
|
|
41
|
+
pool = _POOL["pool"]
|
|
42
|
+
if pool is None or _POOL["n"] != workers or getattr(pool, "_broken", False):
|
|
43
|
+
if pool is not None:
|
|
44
|
+
pool.shutdown(wait=False, cancel_futures=True)
|
|
45
|
+
pool = ProcessPoolExecutor(workers, initializer=_worker_threads, initargs=(1,))
|
|
46
|
+
_POOL.update(pool=pool, n=workers)
|
|
47
|
+
return pool
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# Conformaty's losses and Kabsch. rmsd is the default here. Since Conformaty starts its fits at the Kabsch pose (d74f074)
|
|
51
|
+
# none stalls on the example set; mixed and sig settle up to 0.5 A off Kabsch on o_Br/o_Cl, where their own losses prefer
|
|
52
|
+
# to be. Before, from its principal-axis seed, mixed and mad stalled about 6 A away on 5 of 9.
|
|
53
|
+
FITS = ("rmsd", "msd", "mixed", "mad", "sig", "kabsch")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def kabsch(moving, fixed, rows):
|
|
57
|
+
"""moving, rotated and moved onto fixed by the closed-form least-squares fit of `rows` (the smallest RMSD)."""
|
|
58
|
+
import numpy as np
|
|
59
|
+
|
|
60
|
+
a, b = moving[rows], fixed[rows]
|
|
61
|
+
ca, cb = a.mean(0), b.mean(0)
|
|
62
|
+
u, _s, vt = np.linalg.svd((a - ca).T @ (b - cb))
|
|
63
|
+
return (moving - ca) @ (u @ np.diag([1.0, 1.0, np.sign(np.linalg.det(u @ vt))]) @ vt) + cb
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def fit_onto(ref, symbols, coords, fit="rmsd", sigma=30, rows=None):
|
|
67
|
+
"""The molecule (symbols, coords in the reference's numbering) fitted onto the reference (symbols, coords) over
|
|
68
|
+
`rows` (0-based; default the heavy atoms holding the reference's element, as Conformaty's own align fits).
|
|
69
|
+
fit: one of FITS, Conformaty's rigid-body optimiser with that loss, or kabsch. Returns the fitted (n, 3) array, or
|
|
70
|
+
the coordinates unmoved if fewer than three rows match."""
|
|
71
|
+
import numpy as np
|
|
72
|
+
|
|
73
|
+
rs, rx = ref
|
|
74
|
+
rx, coords = np.asarray(rx, float), np.asarray(coords, float)
|
|
75
|
+
if rows is None:
|
|
76
|
+
rows = [i for i in range(len(rs)) if symbols[i] == rs[i]]
|
|
77
|
+
heavy = [i for i in rows if rs[i] != "H"]
|
|
78
|
+
rows = heavy if len(heavy) >= 3 else rows
|
|
79
|
+
if len(rows) < 3:
|
|
80
|
+
return coords
|
|
81
|
+
if fit == "kabsch":
|
|
82
|
+
return kabsch(coords, rx, rows)
|
|
83
|
+
cf = _conformaty()
|
|
84
|
+
moved = cf.fit_frames(cf.frame_from_atoms(rs, rx), cf.frame_from_atoms(symbols, coords), {i: i for i in rows},
|
|
85
|
+
loss_type=fit, sigma=sigma)
|
|
86
|
+
return moved.iloc[2:][["X", "Y", "Z"]].to_numpy(float)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def compare_fits(ref, symbols, coords, sigma=30):
|
|
90
|
+
"""Every fit (FITS) of one molecule, already in the reference's numbering, onto the reference: the RMSD over the
|
|
91
|
+
positions with the reference's element and over its heavy atoms, how many of them end within 0.25 A, the seconds,
|
|
92
|
+
and the fitted xyz. Kabsch has the smallest RMSD by construction; mixed favours atoms in near-exact overlap."""
|
|
93
|
+
import numpy as np
|
|
94
|
+
|
|
95
|
+
rs, rx = ref[0], np.asarray(ref[1], float)
|
|
96
|
+
same = [i for i in range(len(rs)) if symbols[i] == rs[i]]
|
|
97
|
+
heavy = [i for i in same if rs[i] != "H"]
|
|
98
|
+
out = []
|
|
99
|
+
for fit in FITS:
|
|
100
|
+
t0 = time.perf_counter()
|
|
101
|
+
xyz = fit_onto(ref, symbols, coords, fit, sigma)
|
|
102
|
+
d = np.linalg.norm(xyz[same] - rx[same], axis=1)
|
|
103
|
+
out.append({"fit": fit, "rmsd": float(np.sqrt((d ** 2).mean())) if same else None,
|
|
104
|
+
"rmsd_heavy": float(np.sqrt((np.linalg.norm(xyz[heavy] - rx[heavy], axis=1) ** 2).mean())) if heavy else None,
|
|
105
|
+
"within": int((d < 0.25).sum()), "n": len(same), "seconds": time.perf_counter() - t0,
|
|
106
|
+
"xyz": f"{len(symbols)}\nfitted ({fit})\n" + "\n".join(
|
|
107
|
+
f"{s} {x:.6f} {y:.6f} {z:.6f}" for s, (x, y, z) in zip(symbols, xyz))})
|
|
108
|
+
return out
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def map_atoms(ref, query, anchors=None, stages=None, match_charge=False, fit="rmsd", sigma=30, fit_atoms=None):
|
|
112
|
+
"""Number one molecule like the reference. ref, query: (symbols, coords) of each.
|
|
113
|
+
|
|
114
|
+
anchors: 1-based (reference atom, query atom) pairs that must correspond. stages: Conformaty's middle stages in
|
|
115
|
+
order (complete_rings, extend_mcs, coords_proximity_any; default all three). fit, sigma: the rigid-body fit of
|
|
116
|
+
the overlay (FITS); the numbering keeps Conformaty's own internal fit. fit_atoms: 1-based reference atoms the
|
|
117
|
+
overlay is fitted on (default its heavy atoms with the reference's element, as Conformaty's align).
|
|
118
|
+
Returns plain values (they cross a process boundary): old_to_new {old: new} (1-based), stage (the Conformaty stage
|
|
119
|
+
that matched each atom, in the new order), xyz (the molecule fitted onto the reference, new order), differs (reference
|
|
120
|
+
positions holding another element), rmsd over the positions with the same element (rmsd_kabsch: the same for
|
|
121
|
+
the Kabsch fit, the least-squares optimum, to tell a stalled fit), seconds.
|
|
122
|
+
"""
|
|
123
|
+
import numpy as np
|
|
124
|
+
|
|
125
|
+
cf = _conformaty()
|
|
126
|
+
(rs, rx), (qs, qx) = ref, query
|
|
127
|
+
if len(qs) < len(rs):
|
|
128
|
+
raise ValueError(f"it has fewer atoms ({len(qs)}) than the reference ({len(rs)}): choose the smaller molecule "
|
|
129
|
+
"as the reference")
|
|
130
|
+
t0 = time.perf_counter()
|
|
131
|
+
state = cf.map_frames(cf.frame_from_atoms(rs, rx), cf.frame_from_atoms(qs, qx),
|
|
132
|
+
anchors=[(r - 1, q - 1) for r, q in anchors] if anchors else None,
|
|
133
|
+
stage_order=stages, match_formal_charge=match_charge)
|
|
134
|
+
order = cf.query_order(state)
|
|
135
|
+
found = {q: entry.name for entry in state.log for q in entry.added}
|
|
136
|
+
syms = [str(qs[q]) for q in order]
|
|
137
|
+
same = [i for i in range(len(rs)) if syms[i] == rs[i]]
|
|
138
|
+
rows = [a - 1 for a in fit_atoms if a - 1 in same] if fit_atoms else None
|
|
139
|
+
rx = np.asarray(rx, float)
|
|
140
|
+
moving = np.asarray(qx, float)[order]
|
|
141
|
+
|
|
142
|
+
def dev(xyz):
|
|
143
|
+
return float(np.sqrt(((xyz[same] - rx[same]) ** 2).sum(1).mean())) if same else None
|
|
144
|
+
|
|
145
|
+
fitted = fit_onto((rs, rx), syms, moving, fit, sigma, rows)
|
|
146
|
+
rmsd = dev(fitted)
|
|
147
|
+
best = rmsd if fit == "kabsch" else dev(fit_onto((rs, rx), syms, moving, "kabsch", rows=rows))
|
|
148
|
+
return {
|
|
149
|
+
"old_to_new": {int(q) + 1: k + 1 for k, q in enumerate(order)},
|
|
150
|
+
"stage": [found.get(q, "") for q in order],
|
|
151
|
+
"xyz": f"{len(syms)}\nfitted onto the reference\n" + "\n".join(
|
|
152
|
+
f"{s} {x:.6f} {y:.6f} {z:.6f}" for s, (x, y, z) in zip(syms, fitted)),
|
|
153
|
+
"differs": [i + 1 for i in range(len(rs)) if syms[i] != rs[i]],
|
|
154
|
+
"rmsd": rmsd,
|
|
155
|
+
"rmsd_kabsch": best,
|
|
156
|
+
"fit": fit,
|
|
157
|
+
"seconds": time.perf_counter() - t0,
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _atoms(mol):
|
|
162
|
+
x = mol.xyz_df
|
|
163
|
+
return x["atom"].astype(str).tolist(), x[["x", "y", "z"]].to_numpy(float).tolist()
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def map_folder(mols, reference, anchors=None, stages=None, match_charge=False, workers=None, progress=None,
|
|
167
|
+
cancelled=lambda: False, fit="rmsd", sigma=30, fit_atoms=None, isolate=False, only=None):
|
|
168
|
+
"""Number every molecule of a Molecules like `reference` (one of its names). anchors: {name: [(ref atom, atom)]}.
|
|
169
|
+
|
|
170
|
+
workers > 1 runs that many molecules at once in separate processes, the cores shared between them; 1 (the default)
|
|
171
|
+
runs them here, one after the other, unless isolate (a server: RDKit's substructure search holds the interpreter
|
|
172
|
+
lock, which would stall its other threads). progress(event) gets one dict per molecule as it finishes; cancelled()
|
|
173
|
+
is asked between molecules. Returns {name: result of map_atoms, or {"error": text}};
|
|
174
|
+
the reference itself maps onto itself unchanged.
|
|
175
|
+
"""
|
|
176
|
+
_conformaty()
|
|
177
|
+
by = {m.molecule_name: m for m in mols.molecules}
|
|
178
|
+
if reference not in by:
|
|
179
|
+
raise ValueError(f"no molecule named {reference!r} in this folder")
|
|
180
|
+
ref = _atoms(by[reference])
|
|
181
|
+
n = len(ref[0])
|
|
182
|
+
results = {reference: {"old_to_new": {i: i for i in range(1, n + 1)}, "stage": ["reference"] * n, "differs": [],
|
|
183
|
+
"rmsd": 0.0, "seconds": 0.0, "xyz": None, "reference": True}}
|
|
184
|
+
todo = [name for name in by if name != reference and (only is None or name in only)] # only: these names, again
|
|
185
|
+
workers = max(1, min(len(todo), workers or 1))
|
|
186
|
+
if progress:
|
|
187
|
+
progress({"event": "start", "n": len(todo), "names": todo, "reference": reference, "workers": workers})
|
|
188
|
+
if fit not in FITS:
|
|
189
|
+
raise ValueError(f"fit must be one of {', '.join(FITS)}")
|
|
190
|
+
args = {name: (ref, _atoms(by[name]), (anchors or {}).get(name), stages, match_charge, fit, sigma, fit_atoms)
|
|
191
|
+
for name in todo}
|
|
192
|
+
|
|
193
|
+
def done(i, name, run):
|
|
194
|
+
try:
|
|
195
|
+
results[name] = run()
|
|
196
|
+
except Exception as exc: # one molecule that cannot be mapped does not stop the folder
|
|
197
|
+
results[name] = {"error": f"{type(exc).__name__}: {exc}"}
|
|
198
|
+
if progress:
|
|
199
|
+
progress({"event": "molecule", "i": i, "n": len(todo), "name": name, **_summary(results[name]),
|
|
200
|
+
"result": results[name]})
|
|
201
|
+
|
|
202
|
+
if workers == 1 and not isolate:
|
|
203
|
+
for i, name in enumerate(todo, 1):
|
|
204
|
+
if cancelled():
|
|
205
|
+
break
|
|
206
|
+
done(i, name, lambda: map_atoms(*args[name]))
|
|
207
|
+
return results
|
|
208
|
+
import threading
|
|
209
|
+
|
|
210
|
+
pool = _pool(workers)
|
|
211
|
+
# the pool outlives the run, so the next one starts warm; Stop ends its processes and the next run starts new ones
|
|
212
|
+
jobs = {pool.submit(map_atoms, *args[name]): name for name in todo}
|
|
213
|
+
|
|
214
|
+
def watch(): # one molecule can take minutes: Stop ends its process instead of waiting
|
|
215
|
+
while not all(j.done() for j in jobs):
|
|
216
|
+
if cancelled():
|
|
217
|
+
for other in jobs:
|
|
218
|
+
other.cancel()
|
|
219
|
+
for proc in list(getattr(pool, "_processes", {}).values()):
|
|
220
|
+
proc.terminate()
|
|
221
|
+
_POOL["pool"] = None
|
|
222
|
+
return
|
|
223
|
+
time.sleep(0.3)
|
|
224
|
+
|
|
225
|
+
threading.Thread(target=watch, daemon=True).start()
|
|
226
|
+
for i, job in enumerate(as_completed(jobs), 1):
|
|
227
|
+
if cancelled():
|
|
228
|
+
break
|
|
229
|
+
done(i, jobs[job], job.result)
|
|
230
|
+
return results
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _summary(result):
|
|
234
|
+
if "error" in result:
|
|
235
|
+
return {"error": result["error"]}
|
|
236
|
+
return {"moved": sum(o != n for o, n in result["old_to_new"].items()), "differs": result["differs"],
|
|
237
|
+
"rmsd": result["rmsd"], "rmsd_kabsch": result.get("rmsd_kabsch"), "seconds": result["seconds"]}
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def write_renumbered(mols, results, out_dir, reference=""):
|
|
241
|
+
"""Write each mapped molecule, renumbered, to out_dir/<name>.feather (the names unchanged, so outcomes.csv still
|
|
242
|
+
joins; it is copied along), and renumbering.json: the {old: new} dict of every molecule. Molecules without one
|
|
243
|
+
(failed) are not written. Returns (written names, skipped names)."""
|
|
244
|
+
import copy
|
|
245
|
+
import json
|
|
246
|
+
import shutil
|
|
247
|
+
|
|
248
|
+
from M2_data_extractor.data_extractor import _molecules_folder_files
|
|
249
|
+
|
|
250
|
+
os.makedirs(out_dir, exist_ok=True)
|
|
251
|
+
folder, files = _molecules_folder_files(mols.molecules_path)
|
|
252
|
+
xyz_in = {os.path.splitext(f)[0] for f, _s, _z in files if f.lower().endswith(".xyz")}
|
|
253
|
+
written, skipped = [], []
|
|
254
|
+
for mol in mols.molecules:
|
|
255
|
+
result = results.get(mol.molecule_name) or {}
|
|
256
|
+
if "old_to_new" not in result:
|
|
257
|
+
skipped.append(mol.molecule_name)
|
|
258
|
+
continue
|
|
259
|
+
m = copy.deepcopy(mol)
|
|
260
|
+
if mol.molecule_name in xyz_in: # coordinates stay coordinates; .log, .out and .json become .feather
|
|
261
|
+
m.renumber_atoms(result["old_to_new"], verbose=False, save_feather=False)
|
|
262
|
+
x = m.xyz_df
|
|
263
|
+
with open(os.path.join(out_dir, f"{mol.molecule_name}.xyz"), "w", encoding="utf-8") as fh:
|
|
264
|
+
fh.write(f"{len(x)}\nrenumbered like {reference}\n" + "".join(
|
|
265
|
+
f"{a} {float(px):.6f} {float(py):.6f} {float(pz):.6f}\n" for a, px, py, pz in x[["atom", "x", "y", "z"]].itertuples(index=False)))
|
|
266
|
+
else:
|
|
267
|
+
m.renumber_atoms(result["old_to_new"], verbose=False, save_feather=True,
|
|
268
|
+
out_file=os.path.join(out_dir, f"{mol.molecule_name}.feather"))
|
|
269
|
+
written.append(mol.molecule_name)
|
|
270
|
+
outcomes = os.path.join(mols.molecules_path, "outcomes.csv")
|
|
271
|
+
if os.path.isfile(outcomes):
|
|
272
|
+
shutil.copy(outcomes, out_dir)
|
|
273
|
+
keep = ("old_to_new", "stage", "differs", "rmsd", "rmsd_kabsch", "fit", "seconds", "error")
|
|
274
|
+
with open(os.path.join(out_dir, "renumbering.json"), "w", encoding="utf-8") as fh:
|
|
275
|
+
json.dump({"reference": reference, "folder": mols.molecules_path,
|
|
276
|
+
"molecules": {k: {f: v[f] for f in keep if f in v} for k, v in results.items()}}, fh, indent=1)
|
|
277
|
+
return written, skipped
|