Skip to content

chemical_shifts Module

The chemical_shifts module provides utilities for predicting NMR chemical shifts from protein structures.

Overview

Chemical shifts are highly sensitive indicators of local secondary structure and environment. This module provides shims to synth-nmr for predicting these values.

Main Functions

predict_chemical_shifts(structure, use_shiftx2=True)

Predict chemical shifts for a protein structure from Cartesian coordinates.

SCIENTIFIC BACKGROUND:

Chemical shift prediction is the "bridge" between the static atomic coordinates of a structural model and the experimental NMR observables. Empirical predictors like SHIFTX2 and SPARTA+ use machine-learning models trained on a vast database of experimentally solved structures. These models primarily evaluate: - Backbone Dihedral Angles (Phi, Psi, Omega) - Sidechain Dihedrals (Chi) - Hydrogen Bonding Geometry (O-H distances) - Ring Current Effects (proximity to aromatic rings)

Because these engines are parameterized exclusively on the Protein Data Bank (which predominantly contains naturally occurring L-amino acids), they are "blind" to the inverted chirality of D-amino acids. A right-handed D-alpha helix, perfectly stable physically, is viewed by an L-biased engine as a highly disallowed random coil state.

To solve this, this function implements a rigorous Dual-Pass Coordinate Inversion pipeline: 1. Base Pass: Standard prediction for L-amino acids. 2. Inversion Pass: The Cartesian coordinates are mathematically inverted (coord = -coord) through the origin. This reflects the D-enantiomers into their exact L-enantiomer geometric equivalents, perfectly preserving all inter-atomic distances and angular magnitudes. 3. The base predictor evaluates the inverted structure, and the resulting shifts are merged back for the D-residues.

Technical Implementation Details: - CLONING: We perform an 'in-memory' rename on a copy of the structure to prevent side-effects on the original structural ensemble. This ensures thread-safety in parallel generation workflows. - MASKING: residue-wise renaming is performed using vectorized NumPy boolean masks for maximum performance on large datasets (10^4+ atoms). - GEOMETRY: This strategy captures the primary phi/psi/chi dependence of the chemical shift, providing a robust first-order estimate even for heavily modified synthetic peptides.

ALGORITHM SELECTION & PRECISION:

The module supports two primary prediction engines: 1. SHIFTX2 (use_shiftx2=True): A hybrid machine-learning/empirical method that uses sequence-profile and ensemble-based refinement. It is considered the gold standard for accuracy (RMSD ~0.04 ppm for 1H). 2. SPARTA+ (use_shiftx2=False): A robust empirical method based on a neural network trained on local geometry. It is highly reproducible and has no external binary dependencies, making it ideal for CI/CD.

Parameters:

Name Type Description Default
structure Any

The Biotite AtomArray to predict shifts for. Must contain at least backbone N, CA, and C atoms.

required
use_shiftx2 bool

If True, attempts to use the SHIFTX2 engine. If False, forces the use of the empirical SPARTA+ engine. Defaults to True.

True

Returns:

Name Type Description
Dict dict[str, dict[int, dict[str, float]]]

A nested dictionary structure {chain: {res_id: {atom: value}}}. Values are in parts-per-million (ppm).

Source code in synth_pdb/chemical_shifts.py
def predict_chemical_shifts(
    structure: Any, use_shiftx2: bool = True
) -> dict[str, dict[int, dict[str, float]]]:
    """
    Predict chemical shifts for a protein structure from Cartesian coordinates.

    SCIENTIFIC BACKGROUND:
    ----------------------
    Chemical shift prediction is the "bridge" between the static atomic
    coordinates of a structural model and the experimental NMR observables.
    Empirical predictors like SHIFTX2 and SPARTA+ use machine-learning models
    trained on a vast database of experimentally solved structures.
    These models primarily evaluate:
    - Backbone Dihedral Angles (Phi, Psi, Omega)
    - Sidechain Dihedrals (Chi)
    - Hydrogen Bonding Geometry (O-H distances)
    - Ring Current Effects (proximity to aromatic rings)

    Because these engines are parameterized exclusively on the Protein Data Bank
    (which predominantly contains naturally occurring L-amino acids), they are
    "blind" to the inverted chirality of D-amino acids. A right-handed D-alpha
    helix, perfectly stable physically, is viewed by an L-biased engine as a
    highly disallowed random coil state.

    To solve this, this function implements a rigorous Dual-Pass Coordinate
    Inversion pipeline:
    1. Base Pass: Standard prediction for L-amino acids.
    2. Inversion Pass: The Cartesian coordinates are mathematically inverted
       (coord = -coord) through the origin. This reflects the D-enantiomers
       into their exact L-enantiomer geometric equivalents, perfectly preserving
       all inter-atomic distances and angular magnitudes.
    3. The base predictor evaluates the inverted structure, and the resulting
       shifts are merged back for the D-residues.

    Technical Implementation Details:
    - CLONING: We perform an 'in-memory' rename on a copy of the structure to
      prevent side-effects on the original structural ensemble. This ensures
      thread-safety in parallel generation workflows.
    - MASKING: residue-wise renaming is performed using vectorized NumPy
      boolean masks for maximum performance on large datasets (10^4+ atoms).
    - GEOMETRY: This strategy captures the primary phi/psi/chi dependence
      of the chemical shift, providing a robust first-order estimate even
      for heavily modified synthetic peptides.

    ALGORITHM SELECTION & PRECISION:
    -------------------------------
    The module supports two primary prediction engines:
    1. SHIFTX2 (use_shiftx2=True): A hybrid machine-learning/empirical method
       that uses sequence-profile and ensemble-based refinement. It is
       considered the gold standard for accuracy (RMSD ~0.04 ppm for 1H).
    2. SPARTA+ (use_shiftx2=False): A robust empirical method based on a
       neural network trained on local geometry. It is highly reproducible
       and has no external binary dependencies, making it ideal for CI/CD.

    Args:
        structure: The Biotite AtomArray to predict shifts for. Must contain
                  at least backbone N, CA, and C atoms.
        use_shiftx2 (bool): If True, attempts to use the SHIFTX2 engine.
                    If False, forces the use of the empirical SPARTA+ engine.
                    Defaults to True.

    Returns:
        Dict: A nested dictionary structure {chain: {res_id: {atom: value}}}.
             Values are in parts-per-million (ppm).
    """
    # -- PRE-PROCESSING: RESIDUE MAPPING --------------------------------------
    # To support non-standard residues (D-amino acids, PTMs) we must ensure
    # the underlying engine recognizes all residues in the chain.
    #
    # IMPLEMENTATION LOGIC:
    # 1. Clone the input structure object to ensure immutability.
    # 2. Iterate over the mapping dictionary defined above.
    # 3. Use NumPy masking to identify residues needing conversion.
    # 4. Replace residue names in-place on the cloned structure.
    # 5. This approach avoids side-effects on the user's AtomArray.
    # 6. NumPy masking is used for performance on large structure arrays.
    # 7. ResName attribute is modified to match the parent amino acid.
    # 8. All standard atoms (N, CA, C, O, CB) are preserved for the engine.
    # -- 1. PRE-PROCESSING: RESIDUE MAPPING -----------------------------------
    # To support non-standard residues (D-amino acids, PTMs) we must ensure
    # the underlying engine recognizes all residues in the chain.
    working_struc = structure.copy()
    has_d_amino_acids = False

    for res_name, parent_name in _PARENT_MAP.items():
        mask = working_struc.res_name == res_name
        if np.any(mask):
            logger.debug(f"Mapping {res_name} -> {parent_name} for shift prediction.")
            working_struc.res_name[mask] = parent_name
            if res_name in _D_AMINO_ACIDS:
                has_d_amino_acids = True

    # Inner helper to dispatch to the correct synth-nmr engine
    def _dispatch_predictor(struc_to_predict: Any) -> dict[str, dict[int, dict[str, float]]]:
        if not use_shiftx2:
            logger.debug("Dispatching to empirical shift predictor.")
            return cast(
                dict[str, dict[int, dict[str, float]]],
                _cs.predict_empirical_shifts(struc_to_predict),
            )
        try:
            logger.debug("Dispatching to SHIFTX2-aware prediction engine.")
            return cast(
                dict[str, dict[int, dict[str, float]]],
                _cs.predict_chemical_shifts(struc_to_predict, use_shiftx2=use_shiftx2),
            )
        except TypeError:
            logger.warning(
                "Underlying engine does not support use_shiftx2; falling back to default."
            )
            return cast(
                dict[str, dict[int, dict[str, float]]],
                _cs.predict_chemical_shifts(struc_to_predict),
            )

    # -- 2. PASS 1: STANDARD PREDICTION ---------------------------------------
    # Predict shifts for the mapped structure. This provides physically accurate
    # results for all standard L-amino acids and PTMs.
    base_shifts = _dispatch_predictor(working_struc)

    # -- 3. PASS 2: COORDINATE INVERSION FOR D-PEPTIDES -----------------------
    # If D-amino acids are present, their local geometry is inverted relative to
    # the L-parameterized training data. We invert the entire coordinate space
    # (mirror image) and run a second prediction pass. The shifts of an enantiomer
    # in an achiral environment are identical, so this perfectly captures the
    # true chemical shifts of the D-peptide geometry.
    if not has_d_amino_acids:
        return base_shifts

    # -- 3. INVERTED PREDICTION PASS (D-AMINO ACIDS) --------------------------
    # SCIENTIFIC BACKGROUND FOR INVERTED PASS:
    # ----------------------------------------
    # Empirical chemical shift predictors (like SHIFTX2 and SPARTA+) are
    # strictly trained on the Protein Data Bank (PDB), which almost exclusively
    # contains naturally occurring L-amino acids. Therefore, their internal
    # neural networks and statistical tables inherently expect left-handed
    # alpha helices (phi ~ -60, psi ~ -45) and standard right-handed twists
    # in beta sheets.
    #
    # When presented with a D-amino acid peptide, the backbone torsion angles
    # are mathematically mirrored (e.g., a D-alpha helix has phi ~ +60, psi ~ +45).
    # If passed directly to standard empirical predictors, these angles fall into
    # sparsely populated or "unallowed" regions of the classical Ramachandran
    # plot. As a result, the engines fail to recognize the secondary structure
    # and default to predicting "random coil" shifts (0.0 deviation).
    #
    # THE SOLUTION: Mathematical Enantiomer Mapping
    # Because chemical shifts (scalar values) are isotropic with respect to
    # global chirality, a D-peptide and its exact L-peptide mirror image
    # should, in a vacuum, produce identical isotropic shifts (ignoring
    # higher-order chiral solvent interactions and asymmetric chiral fields).
    #
    # Therefore, we can accurately predict the shifts of a D-peptide by:
    # 1. Mathematically inverting the Cartesian coordinates (coord = -coord).
    #    This perfectly converts the D-peptide back into an L-peptide geometry.
    #    It reflects all atoms across the origin, effectively converting
    #    D-chirality to L-chirality while perfectly preserving all internal
    #    distances (bond lengths, hydrogen bonds) and absolute angular geometries.
    # 2. Running the standard L-based empirical predictor on this inverted structure.
    # 3. Mapping the resulting shifts back to the original D-residues in the output.
    #
    # This dual-pass approach elegantly bypasses the training data limitations
    # of the underlying prediction engines without requiring any retraining.
    # This ensures high-fidelity predictions for researchers studying synthetic
    # peptide therapeutics and non-ribosomal peptides.
    logger.info("D-amino acids detected. Running dual-pass coordinate inversion predictor.")
    inverted_struc = working_struc.copy()

    # Apply the mathematical inversion transformation (parity operation).
    inverted_struc.coord = -inverted_struc.coord

    # Dispatch the inverted structure to the core prediction engine.
    inverted_shifts = _dispatch_predictor(inverted_struc)

    # -- 4. MERGE RESULTS -----------------------------------------------------
    # We selectively pull the predicted shifts for D-residues from the inverted
    # pass, and L-residues from the standard pass, returning a unified dictionary.
    merged_shifts: dict[str, dict[int, dict[str, float]]] = {}

    # Use synth-nmr's get_residue_info to safely iterate the original structure
    from synth_nmr.structure_utils import get_residue_info

    chain_ids, res_ids, res_names, _ = get_residue_info(structure)

    for c_id, r_id_str, r_name in zip(chain_ids, res_ids, res_names, strict=False):
        r_id = int(r_id_str)
        if c_id not in merged_shifts:
            merged_shifts[c_id] = {}

        is_d_amino_acid = r_name in _D_AMINO_ACIDS
        source_shifts = inverted_shifts if is_d_amino_acid else base_shifts

        # Only copy if the residue was actually predicted by the engine
        if c_id in source_shifts and r_id in source_shifts[c_id]:
            merged_shifts[c_id][r_id] = source_shifts[c_id][r_id]

    return merged_shifts

calculate_csi(shifts, structure)

Calculate the Chemical Shift Index (CSI) for a protein structure.

SCIENTIFIC BACKGROUND:

The Chemical Shift Index (CSI) is a robust empirical method for identifying secondary structure elements (helices, sheets) directly from NMR chemical shifts. The method relies on the observation that local backbone geometry exerts a predictable deshielding or shielding effect on specific nuclei relative to their "random coil" (unstructured) baseline values.

Continuous CSI values (often denoted as Delta-delta) are calculated by subtracting the sequence-specific random coil shift from the experimentally measured or predicted shift.

For the C-alpha (CA) nucleus: - Positive deviations (> +0.7 ppm) strongly indicate an alpha-helical conformation. This is because the compact helical geometry typically deshields the CA nucleus. - Negative deviations (< -0.7 ppm) strongly indicate a beta-sheet conformation. The extended geometry of a beta-strand shields the CA nucleus, resulting in an upfield shift.

For the C-beta (CB) nucleus, the pattern is reversed: - Negative deviations indicate an alpha-helix. - Positive deviations indicate a beta-sheet.

This implementation automatically calculates the deviations for all relevant nuclei present in the shifts dictionary, allowing researchers to build a consensus secondary structure map without requiring NOE distance restraints or full 3D coordinate generation.

Parameters:

Name Type Description Default
shifts dict[str, dict[int, dict[str, float]]]

Predicted or experimental shifts in the nested dictionary format.

required
structure Any

The Biotite AtomArray used for sequence and residue mapping.

required

Returns:

Name Type Description
Dict dict[str, dict[int, float]]

Nested dictionary {chain: {res_id: deviation}}.

Source code in synth_pdb/chemical_shifts.py
def calculate_csi(
    shifts: dict[str, dict[int, dict[str, float]]], structure: Any
) -> dict[str, dict[int, float]]:
    """
    Calculate the Chemical Shift Index (CSI) for a protein structure.

    SCIENTIFIC BACKGROUND:
    ----------------------
    The Chemical Shift Index (CSI) is a robust empirical method for identifying
    secondary structure elements (helices, sheets) directly from NMR chemical
    shifts. The method relies on the observation that local backbone geometry
    exerts a predictable deshielding or shielding effect on specific nuclei
    relative to their "random coil" (unstructured) baseline values.

    Continuous CSI values (often denoted as Delta-delta) are calculated by
    subtracting the sequence-specific random coil shift from the experimentally
    measured or predicted shift.

    For the C-alpha (CA) nucleus:
    - Positive deviations (> +0.7 ppm) strongly indicate an alpha-helical conformation.
      This is because the compact helical geometry typically deshields the CA nucleus.
    - Negative deviations (< -0.7 ppm) strongly indicate a beta-sheet conformation.
      The extended geometry of a beta-strand shields the CA nucleus, resulting in
      an upfield shift.

    For the C-beta (CB) nucleus, the pattern is reversed:
    - Negative deviations indicate an alpha-helix.
    - Positive deviations indicate a beta-sheet.

    This implementation automatically calculates the deviations for all relevant
    nuclei present in the `shifts` dictionary, allowing researchers to build
    a consensus secondary structure map without requiring NOE distance restraints
    or full 3D coordinate generation.

    Args:
        shifts: Predicted or experimental shifts in the nested dictionary format.
        structure: The Biotite AtomArray used for sequence and residue mapping.

    Returns:
        Dict: Nested dictionary {chain: {res_id: deviation}}.
    """
    # -- PRE-PROCESSING: RESIDUE MAPPING --------------------------------------
    # The core CSI calculation relies on looking up the empirically derived
    # random-coil reference values for each specific amino acid type. Because
    # non-standard residues (like D-amino acids or phosphorylated sidechains)
    # typically lack dedicated random-coil reference tables in standard BMRB
    # datasets, we must rigorously map them back to their structurally closest
    # standard parent residue.
    #
    # For example, D-alanine ("DAL") is mapped to L-alanine ("ALA"). The
    # electronic shielding environment of the CA nucleus in a random coil is
    # dominated by the local covalent bonding (C-N, C-C, C-CB), which is
    # identical in both enantiomers. Therefore, the L-amino acid random coil
    # values serve as a highly accurate baseline for D-peptides.
    working_struc = structure.copy()
    for res_name, parent_name in _PARENT_MAP.items():
        mask = working_struc.res_name == res_name
        if np.any(mask):
            logger.debug(f"Mapping {res_name} -> {parent_name} for CSI calculation.")
            working_struc.res_name[mask] = parent_name

    return cast(dict[str, dict[int, float]], _calculate_csi(shifts, working_struc))

get_secondary_structure(shifts, structure)

Infers categorical secondary structure (H, E, C) from chemical shifts.

SCIENTIFIC BACKGROUND:

Categorical secondary structure annotation is typically performed using geometric criteria (e.g., DSSP or P-SEA) evaluated directly on the 3D coordinates of a protein structure. However, it can also be inferred from chemical shift data using tools like TALOS or CSI, which map sequence-specific shifts to standard secondary structure alphabets.

In this implementation, we utilize Biotite's annotate_sse function, which implements a variant of the P-SEA algorithm. This algorithm defines elements based on continuous stretches of specific backbone dihedral angle pairs: - 'a' (Alpha Helix): Contiguous residues with phi ~ -60, psi ~ -45 - 'b' (Beta Strand): Contiguous residues with extended phi/psi angles - 'c' (Random Coil): Everything else

Because empirical secondary structure parsing tools are intrinsically formulated exclusively for naturally occurring L-amino acid geometries, they strictly evaluate structural signatures based on left-handed dihedral angular boundaries (e.g., phi < 0 for helices).

When a valid D-peptide (which possesses structurally sound right-handed geometry) is evaluated by standard P-SEA, its perfectly valid mirrored angles (phi > 0) fall drastically outside of the classical alpha-helical or beta-strand probability density boundaries. This causes the structural parser to erroneously classify perfectly stable D-structures as completely unstructured "random coil" ("C") regions.

To correctly infer categorical labels for non-natural geometries, we must: 1. Identify any D-amino acids in the input structure using the lookup map. 2. Rename D-residues back to their L-parents so the atomic parsing matches. 3. IF D-amino acids exist, mathematically invert the coordinates (coord = -coord) prior to evaluation.

This mathematical transformation perfectly reflects the D-enantiomeric structure through the origin. As a result, all internal physical geometries (hydrogen bond distances, backbone inter-atomic spacing) are identically preserved, but the global chirality is restored to left-handed geometry. The P-SEA algorithm can then successfully recognize the structural motifs and accurately classify the secondary structure.

Parameters:

Name Type Description Default
shifts dict[str, dict[int, dict[str, float]]]

Predicted or experimental shifts.

required
structure Any

The Biotite AtomArray used for mapping and sequence length.

required

Returns:

Type Description
list[str]

List[str]: A list of 3-state (H, E, C) or DSSP labels per residue.

Source code in synth_pdb/chemical_shifts.py
def get_secondary_structure(
    shifts: dict[str, dict[int, dict[str, float]]], structure: Any
) -> list[str]:
    """
    Infers categorical secondary structure (H, E, C) from chemical shifts.

    SCIENTIFIC BACKGROUND:
    ----------------------
    Categorical secondary structure annotation is typically performed using
    geometric criteria (e.g., DSSP or P-SEA) evaluated directly on the 3D
    coordinates of a protein structure. However, it can also be inferred from
    chemical shift data using tools like TALOS or CSI, which map sequence-specific
    shifts to standard secondary structure alphabets.

    In this implementation, we utilize Biotite's `annotate_sse` function, which
    implements a variant of the P-SEA algorithm. This algorithm defines elements
    based on continuous stretches of specific backbone dihedral angle pairs:
    - 'a' (Alpha Helix): Contiguous residues with phi ~ -60, psi ~ -45
    - 'b' (Beta Strand): Contiguous residues with extended phi/psi angles
    - 'c' (Random Coil): Everything else

    Because empirical secondary structure parsing tools are intrinsically
    formulated exclusively for naturally occurring L-amino acid geometries,
    they strictly evaluate structural signatures based on left-handed
    dihedral angular boundaries (e.g., phi < 0 for helices).

    When a valid D-peptide (which possesses structurally sound right-handed
    geometry) is evaluated by standard P-SEA, its perfectly valid
    mirrored angles (phi > 0) fall drastically outside of the classical
    alpha-helical or beta-strand probability density boundaries. This causes
    the structural parser to erroneously classify perfectly stable D-structures
    as completely unstructured "random coil" ("C") regions.

    To correctly infer categorical labels for non-natural geometries, we must:
    1. Identify any D-amino acids in the input structure using the lookup map.
    2. Rename D-residues back to their L-parents so the atomic parsing matches.
    3. IF D-amino acids exist, mathematically invert the coordinates
       (coord = -coord) prior to evaluation.

    This mathematical transformation perfectly reflects the D-enantiomeric
    structure through the origin. As a result, all internal physical geometries
    (hydrogen bond distances, backbone inter-atomic spacing) are identically
    preserved, but the global chirality is restored to left-handed geometry.
    The P-SEA algorithm can then successfully recognize the structural motifs
    and accurately classify the secondary structure.

    Args:
        shifts: Predicted or experimental shifts.
        structure: The Biotite AtomArray used for mapping and sequence length.

    Returns:
        List[str]: A list of 3-state (H, E, C) or DSSP labels per residue.
    """
    # -- PRE-PROCESSING: RESIDUE MAPPING --------------------------------------
    # Because empirical secondary structure parsing tools, such as the P-SEA
    # algorithm used natively by Biotite's `annotate_sse`, are intrinsically
    # formulated exclusively for naturally occurring L-amino acid geometries,
    # they strictly evaluate structural signatures based on left-handed
    # dihedral angular boundaries (e.g., phi < 0).
    #
    # When a valid D-peptide (which possesses structurally sound right-handed
    # right-handed geometry) is evaluated by standard P-SEA, its perfectly valid
    # mirrored angles (phi > 0) fall drastically outside of the classical
    # alpha-helical or beta-strand probability density boundaries. This causes
    # the structural parser to erroneously classify perfectly stable D-structures
    # as completely unstructured "random coil" ("C") regions.
    #
    # To correctly infer categorical labels for non-natural geometries, we must:
    # 1. Identify any D-amino acids in the input structure using the lookup map.
    # 2. Rename D-residues back to their L-parents so the atomic parsing matches.
    # 3. IF D-amino acids exist, mathematically invert the coordinates
    #    (coord = -coord) prior to evaluation.
    #
    # This mathematical transformation perfectly reflects the D-enantiomeric
    # structure through the origin. As a result, all internal physical geometries
    # (hydrogen bond distances, backbone inter-atomic spacing) are identically
    # preserved, but the global chirality is restored to left-handed geometry.
    # The P-SEA algorithm can then successfully recognize the structural motifs
    # and accurately classify the secondary structure.
    working_struc = structure.copy()
    has_d_amino_acids = False
    for res_name, parent_name in _PARENT_MAP.items():
        mask = working_struc.res_name == res_name
        if np.any(mask):
            logger.debug(f"Mapping {res_name} -> {parent_name} for SS assignment.")
            working_struc.res_name[mask] = parent_name
            if res_name in _D_AMINO_ACIDS:
                has_d_amino_acids = True

    if has_d_amino_acids:
        logger.info("D-amino acids detected. Running coordinate inversion for SS assignment.")
        working_struc.coord = -working_struc.coord

    # Latest synth-nmr might require structure for residue count consistency
    try:
        return cast(list[str], _get_secondary_structure(working_struc))
    except TypeError:
        # Fallback for older versions that might only take shifts
        return cast(list[str], _get_secondary_structure(shifts))

Usage Examples

Predicting Chemical Shifts

from synth_pdb.chemical_shifts import predict_chemical_shifts

# structure: biotite.structure.AtomArray
shifts = predict_chemical_shifts(structure)

# shifts: Dict[int, Dict[str, float]]
# {residue_id: {atom_name: shift_value}}

Chemical Shift Index (CSI)

Analyze secondary structure based on H-alpha, C-alpha, and C-beta shifts.

from synth_pdb.chemical_shifts import calculate_csi

csi = calculate_csi(shifts)
# Returns list of -1 (alpha), 1 (beta), 0 (coil)

References

  • Random Coil Shifts: Wishart, D. S., et al. (1995). "1H, 13C and 15N random coil NMR chemical shifts of the common amino acids. I. Investigations of nearest-neighbor effects." Journal of Biomolecular NMR. DOI: 10.1007/BF00211783
  • Ring Current Effects: Haigh, C. W., & Mallion, R. B. (1979). "Ring current theories in nuclear magnetic resonance." Progress in Nuclear Magnetic Resonance Spectroscopy. DOI: 10.1016/0079-6565(79)80010-2

See Also