From 46cd905d8061c7d2a07bf57bce421a2e2bd2428c Mon Sep 17 00:00:00 2001 From: mane292 Date: Mon, 2 Feb 2026 18:20:55 -0500 Subject: [PATCH] updated readthedocs --- docs/api.rst | 124 +++++++++++++++++++++++-- docs/conf.py | 4 +- docs/getting_started.rst | 190 +++++++++++++++++++++++++++++++++------ docs/index.rst | 40 +++++++-- 4 files changed, 313 insertions(+), 45 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index 11ab918..35e7604 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -4,6 +4,36 @@ API Reference This page documents the main classes and functions for computing electric fields, electrostatic potentials, and partial charges. +.. _quick-reference: + +Quick Reference +--------------- + +.. list-table:: + :widths: 20 35 25 20 + :header-rows: 1 + + * - Function + - Key Inputs + - Output + - Requirements + * - :ref:`getEfield() ` + - ``charge_types``, ``input_bond_indices``, ``multiwfn_path`` + - DataFrame with E-field (V/Å) + - Molden + XYZ files + * - :ref:`getESP() ` + - ``charge_types``, ``multiwfn_path`` + - DataFrame with ESP (V) + - ``esp_atom_idx`` at init + * - :ref:`getCharges() ` + - ``charge_types``, ``multiwfn_path``, ``write_pdb`` + - DataFrame with charges + - Molden + XYZ files + * - :ref:`getElectrostatic_stabilization() ` + - ``substrate_idxs``, ``charge_type``, ``multipole_order`` + - DataFrame with energies (kcal/mol) + - Molden + XYZ files + Electrostatics Class -------------------- @@ -19,8 +49,7 @@ Initialization es = Electrostatics( molden_paths, # List of .molden file paths xyz_paths, # List of .xyz file paths - lst_of_tmcm_idx=None, # Metal atom indices for ESP (0-indexed) - dielectric=1, # Dielectric constant + esp_atom_idx=None, # Atom indices for ESP (0-indexed) ptchg_paths=None # Point charge files for QM/MM ) @@ -31,10 +60,11 @@ Initialization **Optional parameters:** -- ``lst_of_tmcm_idx`` (list of int): Metal atom indices for ESP calculations -- ``dielectric`` (float): Dielectric constant (1=vacuum, 4=protein, 78.5=water) +- ``esp_atom_idx`` (list of int): Atom indices for ESP calculations (0-indexed) - ``ptchg_paths`` (list): Point charge file paths for QM/MM calculations +.. _getefield-electric-field: + getEfield() - Electric Field ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -60,6 +90,8 @@ getEfield() - Electric Field **Returns:** DataFrame with electric field results +.. _getesp-electrostatic-potential: + getESP() - Electrostatic Potential ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -83,16 +115,92 @@ getESP() - Electrostatic Potential **Returns:** DataFrame with ESP results -**Note:** Requires ``lst_of_tmcm_idx`` to be set during initialization. +**Note:** Requires ``esp_atom_idx`` to be set during initialization. + +.. _getcharges-partial-charges: + +getCharges() - Partial Charges +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + df = es.getCharges( + charge_types='Hirshfeld_I', # Charge scheme(s) + multiwfn_path='/path/to/multiwfn', + output_filename='charges', # Output filename prefix + write_pdb=False # Write PDB files with charges + ) + +**Parameters:** + +- ``charge_types`` (str or list): Charge scheme(s) to use +- ``multiwfn_path`` (str): Path to Multiwfn executable +- ``output_filename`` (str): Output CSV filename prefix +- ``write_pdb`` (bool): If True, write PDB files with charges in B-factor column + +**Returns:** DataFrame with columns: Job, Charge_Type, Atom_Index, Element, x, y, z, Charge, Molden_Path, XYZ_Path + +.. _getelectrostatic-stabilization-electrostatic-stabilization: + +getElectrostatic_stabilization() - Electrostatic Stabilization +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: python + + df = es.getElectrostatic_stabilization( + multiwfn_path='/path/to/multiwfn', + substrate_idxs=[], # Substrate atom indices per structure + charge_type='Hirshfeld_I', # Charge scheme + multipole_order=2, # 1 for monopole, 2 for dipole + dielectric=1 # Dielectric constant + ) + +**Parameters:** + +- ``multiwfn_path`` (str): Path to Multiwfn executable +- ``substrate_idxs`` (list): List of atom indices for substrate per structure +- ``charge_type`` (str): Charge scheme (Hirshfeld, Hirshfeld_I, or Becke for multipole_order=2) +- ``multipole_order`` (int): 1 for monopole, 2 for dipole corrections +- ``dielectric`` (float): Dielectric constant + +**Returns:** DataFrame with electrostatic stabilization energies Charge Schemes -------------- **Available schemes:** -- Hirshfeld, Hirshfeld_I, Voronoi, Mulliken, Lowdin -- SCPA, Becke, ADCH, CHELPG, MK, AIM -- CM5, EEM, RESP, PEOE ++---------------+------------------------------------------+--------------------------------------------------+ +| Charge Type | Description | Notes | ++===============+==========================================+==================================================+ +| Hirshfeld_I | Iterative Hirshfeld | Recommended for most systems | ++---------------+------------------------------------------+--------------------------------------------------+ +| Hirshfeld | Standard Hirshfeld partitioning | Fast, good for most systems | ++---------------+------------------------------------------+--------------------------------------------------+ +| RESP | Restrained ESP fitting | Standard for force field development | ++---------------+------------------------------------------+--------------------------------------------------+ +| CHELPG | ESP fitting (Breneman) | Good for molecular mechanics | ++---------------+------------------------------------------+--------------------------------------------------+ +| MK | Merz-Kollmann ESP fitting | Alternative ESP method | ++---------------+------------------------------------------+--------------------------------------------------+ +| CM5 | Charge Model 5 | Good balance of accuracy/speed | ++---------------+------------------------------------------+--------------------------------------------------+ +| ADCH | Atomic dipole corrected Hirshfeld | Recommended by Multiwfn | ++---------------+------------------------------------------+--------------------------------------------------+ +| Mulliken | Mulliken population | Fast but basis-set dependent | ++---------------+------------------------------------------+--------------------------------------------------+ +| Lowdin | Löwdin population | Orthogonalized basis | ++---------------+------------------------------------------+--------------------------------------------------+ +| Voronoi | Voronoi deformation density | Space partitioning method | ++---------------+------------------------------------------+--------------------------------------------------+ +| SCPA | Ros & Schuit modified Mulliken | Modified Mulliken scheme | ++---------------+------------------------------------------+--------------------------------------------------+ +| Becke | Becke partitioning with dipole corr. | Real-space integration | ++---------------+------------------------------------------+--------------------------------------------------+ +| EEM | Electronegativity equalization | ⚠️ Requires bonded atoms (fails for ionic) | ++---------------+------------------------------------------+--------------------------------------------------+ +| PEOE | Gasteiger charges | ⚠️ Missing parameters for Na, transition metals | ++---------------+------------------------------------------+--------------------------------------------------+ **Multipole-capable schemes** (for ``multipole_bool=True`` or ``use_multipole=True``): diff --git a/docs/conf.py b/docs/conf.py index 777bf5b..031d3c3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ # -- Project information ----------------------------------------------------- project = "PyEF" -copyright = '{}, Melissa Manetsch and David W. Kastner'.format( +copyright = '{}, Melissa Manetsch and David W. Kastner'.format( datetime.datetime.now().year ) author = "Melissa Manetsch and David W. Kastner" @@ -98,7 +98,7 @@ html_theme = "revitron_sphinx_theme" html_theme_options = { "navigation_depth": 5, - "github_url": "https://github.com/davidkastner/pyef", + "github_url": "https://github.com/hjkgrp/pyEF", "color_scheme": "dark", } diff --git a/docs/getting_started.rst b/docs/getting_started.rst index f5f3477..1589fac 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -1,16 +1,23 @@ Getting Started =============== +**Jump to:** `Installation`_ · `getCharges()`_ · `getEfield()`_ · `getESP()`_ · `getElectrostatic_stabilization()`_ + +.. _getCharges(): `Computing Partial Charges`_ +.. _getEfield(): `Computing Electric Fields`_ +.. _getESP(): `Computing Electrostatic Potentials`_ +.. _getElectrostatic_stabilization(): `Computing Electrostatic Stabilization`_ + Installation ------------ .. code-block:: bash - git clone git@github.com:davidkastner/pyEF.git + git clone git@github.com:hjkgrp/pyEF.git cd pyEF - ./install.sh - -This creates a conda environment with all dependencies and installs PyEF. + conda env create -f environment.yml + conda activate pyef + pip install -e . Requirements ~~~~~~~~~~~~ @@ -18,6 +25,34 @@ Requirements - Python 3.8+ - `Multiwfn `_ (for charge calculations) +Installing Multiwfn +~~~~~~~~~~~~~~~~~~~ + +PyEF requires `Multiwfn `_ for charge partitioning and wavefunction analysis. + +.. note:: + Currently Multiwfn is NOT supported on macOS. We recommend using a Linux or Windows system. + +**Download and compile:** + +.. code-block:: bash + + # Download from http://sobereva.com/multiwfn/ + wget http://sobereva.com/multiwfn/misc/Multiwfn_3.8_bin_Linux_noGUI.zip + unzip Multiwfn_3.8_bin_Linux_noGUI.zip + cd Multiwfn_3.8_bin_Linux_noGUI + + # Give executable permission to the Multiwfn executable file + chmod +x Multiwfn_noGUI + +**Add to your PATH (add to ~/.bashrc):** + +.. code-block:: bash + + export PATH=/path/to/Multiwfn_3.8_bin_Linux_noGUI/Multiwfn_noGUI:$PATH + +Or use the full path when running PyEF (e.g., ``multiwfn_path: /path/to/Multiwfn_3.8_bin_Linux_noGUI/Multiwfn_noGUI``). + Core Concepts ------------- @@ -67,17 +102,38 @@ Supported Charge Schemes Computing Partial Charges ------------------------- -Partial charges are computed automatically when calculating electric fields or ESP. -The charges are obtained via Multiwfn using your specified charge scheme. +Compute partial charges for all atoms using specified charge partitioning scheme(s). +Charges can optionally be written to PDB files for visualization. + +Python API +~~~~~~~~~~ .. code-block:: python from pyef.analysis import Electrostatics - es = Electrostatics(['structure.molden'], ['structure.xyz']) + molden_paths = ['/path/to/structure.molden'] + xyz_paths = ['/path/to/structure.xyz'] + + es = Electrostatics(molden_paths, xyz_paths) - # Charges are computed as part of E-field or ESP calculations - # and stored internally in the Electrostatics object + # Get multiple charge types with PDB output for visualization + df = es.getCharges( + charge_types=['RESP', 'Hirshfeld_I'], + multiwfn_path='/path/to/multiwfn', + output_filename='my_charges', + write_pdb=True + ) + +**Output:** Returns a DataFrame with columns: ``Job``, ``Charge_Type``, ``Atom_Index``, +``Element``, ``x``, ``y``, ``z``, ``Charge``, ``Molden_Path``, ``XYZ_Path``. + +**PDB Visualization:** When ``write_pdb=True``, creates PDB files with charges in the +B-factor column. Visualize in PyMOL with: + +.. code-block:: text + + spectrum b, blue_white_red, minimum=-1, maximum=1 Computing Electric Fields ------------------------- @@ -90,26 +146,36 @@ Python API .. code-block:: python from pyef.analysis import Electrostatics + import numpy as np - # Initialize with molden and xyz files - es = Electrostatics( - molden_paths=['job1/optim.molden', 'job2/optim.molden'], - xyz_paths=['job1/optim.xyz', 'job2/optim.xyz'], - dielectric=4.0 # optional: protein dielectric - ) + molden_paths = ['/path/to/structure1.molden', '/path/to/structure2.molden'] + xyz_paths = ['/path/to/structure1.xyz', '/path/to/structure2.xyz'] + + # Create an electrostatics object + es = Electrostatics(molden_paths, xyz_paths, dielectric=1.0) + + # Record the indices (0-indexed) for the bonds to project E-field across + # Here: one bond (0, 10) in structure 1 and two bonds (20, 21), (25, 26) in structure 2 + ef_bond = [[(0, 10)], [(20, 21), (25, 26)]] - # Calculate E-field at bonds (atom indices are 0-indexed) + # Record indices of the substrate containing bonds of interest + sub_indices = [np.arange(0, 10), np.arange(10, 25)] + + # Exclude substrates from E-field calc (only probe environment impact, not intramolecular) + es.setExcludeAtomFromCalc(sub_indices) + + # Calculate E-field (charge_types can be a list or single value) df = es.getEfield( charge_types='Hirshfeld_I', - Efielddata_filename='efield_results', + Efielddata_filename='output', multiwfn_path='/path/to/multiwfn', - input_bond_indices=[(25, 26), (25, 27)] # bonds to analyze + input_bond_indices=ef_bond ) **Key parameters:** -- ``charge_types``: Charge scheme ('Hirshfeld_I', 'CHELPG', etc.) -- ``input_bond_indices``: List of (atom1, atom2) tuples defining bonds +- ``charge_types``: Charge scheme ('Hirshfeld_I', 'CHELPG', etc.) - can be string or list +- ``input_bond_indices``: List of (atom1, atom2) tuples defining bonds per structure - ``multipole_bool``: Use multipole expansion (default: False) - ``dielectric``: Dielectric constant (1=vacuum, 4=protein, 78.5=water) @@ -150,23 +216,25 @@ Python API from pyef.analysis import Electrostatics - # Initialize with metal center index (0-indexed) - es = Electrostatics( - molden_paths=['optim.molden'], - xyz_paths=['optim.xyz'], - lst_of_tmcm_idx=[30] # metal atom index - ) + molden_paths = ['/path/to/structure1.molden', '/path/to/structure2.molden'] + xyz_paths = ['/path/to/structure1.xyz', '/path/to/structure2.xyz'] + + # One atom index per file (0-indexed) + metal_indices = [30, 0] # atom 30 for structure1, atom 0 for structure2 + + # Create an electrostatics object with esp_atom_idx + es = Electrostatics(molden_paths, xyz_paths, esp_atom_idx=metal_indices, dielectric=1.0) - # Calculate ESP + # Run electrostatic potential calculations df = es.getESP( - charge_types='Hirshfeld_I', + charge_types=['Hirshfeld_I'], ESPdata_filename='esp_results', multiwfn_path='/path/to/multiwfn' ) **Key parameters:** -- ``lst_of_tmcm_idx``: Metal atom indices where ESP is calculated (set at initialization) +- ``esp_atom_idx``: Atom indices where ESP is calculated (set at initialization, 0-indexed) - ``charge_types``: Charge scheme - ``use_multipole``: Use multipole expansion (default: False) - ``dielectric``: Dielectric constant @@ -186,6 +254,70 @@ Run with config: pyef -c config.yaml +Computing Electrostatic Stabilization +------------------------------------- + +Calculate electrostatic stabilization energy between substrate and environment. + +CLI +~~~ + +Create a jobs file: + +.. code-block:: text + + estab, /path/to/structure.molden, /path/to/structure.xyz + +Create a config file (``config.yaml``): + +.. code-block:: yaml + + input: jobs.csv + dielectric: 1 + multiwfn_path: /path/to/multiwfn + charge_types: + - Hirshfeld_I + multipole_order: 2 + substrate_idxs: [1, 2, 3, 4, 5] + +Run: + +.. code-block:: bash + + pyef -c config.yaml + +Python API +~~~~~~~~~~ + +.. code-block:: python + + from pyef.analysis import Electrostatics + import numpy as np + + molden_paths = ['/path/to/structure1.molden', '/path/to/structure2.molden'] + xyz_paths = ['/path/to/structure1.xyz', '/path/to/structure2.xyz'] + + es = Electrostatics(molden_paths, xyz_paths, dielectric=1.0) + + # Record indices of the substrate in structure 1 and structure 2 + sub_indices = [np.arange(0, 10), np.arange(10, 25)] + + # Only Hirshfeld, Hirshfeld_I, and Becke are compatible with multipole_order=2 + # Otherwise will default to multipole_order=1 + df = es.getElectrostatic_stabilization( + charge_types='Hirshfeld', + multiwfn_path='/path/to/multiwfn', + substrate_idxs=sub_indices, + multipole_order=2 + ) + +**Key parameters:** + +- ``substrate_idxs``: List of atom indices for the substrate (one per structure) +- ``charge_types``: Charge scheme (Hirshfeld, Hirshfeld_I, or Becke for multipole_order=2) +- ``multipole_order``: 1 for monopole, 2 for dipole corrections +- ``dielectric``: Dielectric constant + Dielectric Constants -------------------- diff --git a/docs/index.rst b/docs/index.rst index 455e889..8c1d0ce 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,7 +15,7 @@ PyEF: Electric Field Analysis for Molecular Systems `Getting Started `_ `API Reference `_ - `GitHub `_ + `GitHub `_ Overview -------- @@ -29,6 +29,31 @@ PyEF processes molden files from QM calculations to compute: The package provides both a command-line interface for batch processing and a Python API for interactive analysis. +Main Functions +-------------- + +All functions are methods of the ``Electrostatics`` class. Click the links for full documentation. + +.. list-table:: + :widths: 25 50 25 + :header-rows: 1 + + * - Function + - Description + - Documentation + * - ``getEfield()`` + - Calculate electric fields at specific bonds + - `Guide `_ · `API `_ + * - ``getESP()`` + - Calculate electrostatic potential at atomic sites + - `Guide `_ · `API `_ + * - ``getCharges()`` + - Compute partial charges for all atoms + - `Guide `_ · `API `_ + * - ``getElectrostatic_stabilization()`` + - Calculate electrostatic stabilization energy + - `Guide `_ · `API `_ + Quick Start ----------- @@ -37,9 +62,11 @@ Installation .. code-block:: bash - git clone git@github.com:davidkastner/pyEF.git + git clone git@github.com:hjkgrp/pyEF.git cd pyEF - ./install.sh + conda env create -f environment.yml + conda activate pyef + pip install -e . Python API Example ~~~~~~~~~~~~~~~~~~ @@ -55,8 +82,9 @@ Python API Example df = es.getEfield('Hirshfeld_I', 'output', '/path/to/multiwfn', input_bond_indices=[(25, 26)]) - # Calculate ESP at metal center - esp_df = es.getESP('Hirshfeld_I', 'esp_output', '/path/to/multiwfn') + # For ESP, initialize with esp_atom_idx + es_esp = Electrostatics(['optim.molden'], ['optim.xyz'], esp_atom_idx=[30]) + esp_df = es_esp.getESP('Hirshfeld_I', 'esp_output', '/path/to/multiwfn') Documentation ------------- @@ -76,7 +104,7 @@ Citation title = {PyEF: Electric Field Analysis for Molecular Systems}, author = {Manetsch, Melissa and Kastner, David W.}, year = {2025}, - url = {https://github.com/davidkastner/pyef} + url = {https://github.com/hjkgrp/pyEF} } License