Intra-chain distance ==================== The ``idist`` tool computes **intra-chain distance profiles** for a list of atom-pair selections, where each pair consists of exactly two atoms per chain. Distances may be averaged over time, averaged over chains, written as verbose per-frame matrices, or summarized statistically. This tool is implemented in ``intra_distance.py``. Overview -------- Many LLPS or polymer-like systems require monitoring distances such as: - pairwise distances between two residues per chain - distances between two labeled atoms - distances between bead pairs along a chain - diagnostic pair distances across multiple chains ``dps idist`` provides: 1. Load TPR + XTC (+ NDX) 2. Select groups of atom pairs (each group must contain **2 atoms × N chains**) 3. Split each group into chains via ``splitch`` 4. Verify *every* chain contributes exactly 2 atoms 5. Compute pairwise intra-chain distances for each frame 6. Generate any combination of: - verbose per-pair time series - distance vs time plots (chain-averaged) - distance vs pair index (time-averaged) - statistics (mean & std per pair) Distances are reported in **nanometers**. Usage ----- .. code-block:: bash dps idist -s run.tpr -f run.xtc -sel 10 11 12 -ot time.xvg Arguments --------- Required -------- .. option:: -s, --run-input TPR TPR file with topology and initial coordinates. .. option:: -f, --input XTC Trajectory used for distance analysis. Optional -------- Index file ~~~~~~~~~~ .. option:: -n, --index NDX Optional NDX file containing custom index groups. Pair selection ~~~~~~~~~~~~~~ .. option:: -sel, --selection INT INT ... List of group indices. Each group must contain **2 atoms per chain**. (Example: selecting residue-pair groups such as ``CA(i)–CA(j)``.) If omitted, interactive multi-pair selection is used. Time control ~~~~~~~~~~~~ .. option:: -b, --start-time INT .. option:: -e, --end-time INT .. option:: -dt, --delta-time INT Converted to frame indices via ``trajectory.time2frame``. PBC unwrapping ~~~~~~~~~~~~~~ .. option:: -pbc, --treat-pbc Apply MDAnalysis coordinate unwrapping so broken molecules are made whole. Output files ~~~~~~~~~~~~ You may request any number of the following: .. option:: -ot, --output-time FILE Chain-averaged distance for each pair as a function of **time** (one curve per pair). .. option:: -op, --output-pair FILE Time-averaged distance as a function of **pair index** (one curve per chain). .. option:: -ops, --output-pair-statistic FILE Mean and standard deviation for each pair across all frames/chains. .. option:: -ov, --output-verbose FILE Full verbose matrix: - x-axis: time - y-axis: each chain & each pair - one column per (chain, pair) entry Program Workflow ---------------- (1) **Load trajectory** .. code-block:: python trajectory = trajectory_class(tpr, ndx, xtc) Errors during loading stop the program. (2) **PBC handling** .. code-block:: python unwrap(trajectory.Universe.atoms) printed depending on ``--treat-pbc``. (3) **Frame list** .. code-block:: python start, end, step = trajectory.time2frame(b, e, dt) frame_list = range(start, end, step) (4) **Selection of atom pairs** If ``--sel`` provided: .. code-block:: python groups = [trajectory.getSelection(f"group {gid}")[0] for gid in args.selection] Else: .. code-block:: python groups, groups_names = trajectory.getSelection_interactive_multiple() (5) **Splitting into chains** .. code-block:: python groups_splitchains = [splitch(group.indices) for group in groups] This produces: :: n_pairs × n_chains × 2 Validation: - all pairs must have the same number of chains - each chain must contain exactly **2 atoms** (6) **Distance calculation** Flattened pairs: .. code-block:: python groups_splitchains_flatten = groups_splitchains.reshape(-1, 2) For each frame: .. code-block:: python pos1 = atoms[pair[:,0]].positions pos2 = atoms[pair[:,1]].positions distances = norm(pos1 - pos2) All distances combined: :: distances[time, pair_index] Reshape to: :: distances[n_time, n_pairs, n_chains] / 10.0 # nm (7) **Output generation** Verbose ~~~~~~~ .. option:: -ov FILE One column per (chain, pair) combination. Legends follow: :: Chain X Pair groupY Time-averaged per frame ~~~~~~~~~~~~~~~~~~~~~~~ .. option:: -ot FILE .. code-block:: python np.mean(distances, axis=2) # average over chains Pair-averaged per index ~~~~~~~~~~~~~~~~~~~~~~~ .. option:: -op FILE .. code-block:: python np.mean(distances, axis=0) # average over time Statistics ~~~~~~~~~~ .. option:: -ops FILE Mean and standard deviation across all time × chain points: .. code-block:: python distance_per_residue = distances.transpose(1,0,2).reshape(n_pairs,-1) mean = distance_per_residue.mean() std = distance_per_residue.std() Legends: - Mean - Standard error Examples -------- Compute intra-chain distances for three atom-pairs: .. code-block:: bash dps idist \ -s run.tpr \ -f run.xtc \ -sel 5 6 7 \ -ot dist_vs_time.xvg Compute verbose matrix: .. code-block:: bash dps idist \ -s run.tpr \ -f run.xtc \ -sel 10 11 \ -ov verbose_pairs.xvg Chain-averaged distance over pairs: .. code-block:: bash dps idist \ -s run.tpr \ -f run.xtc \ -sel 3 4 5 \ -op pair_avg.xvg Error Messages -------------- **“At least two of your input groups contain different number of chains.”** Each group must span the same chain count. **“Element at [i][j] is not of length 2.”** Each chain must contain exactly 2 atoms. **“Distance will be calculated without periodic boundary conditions.”** Printed when ``--treat-pbc`` is absent. **Trajectory loading failure** If TPR or XTC cannot be opened, the program exits. Summary ------- ``dps idist`` computes detailed intra-chain distance profiles from arbitrary user-defined atom pairs. It offers: - pair-wise/chain-wise distance traces - time-averaged or pair-averaged summaries - full verbose matrices - statistical summaries - optional PBC unwrapping - flexible selection of multiple atom-pair definitions This makes it a powerful tool for characterizing polymer morphology, residue contact evolution, and structural dynamics in LLPS simulations.