Thank you for your help! From testing on a few noodly structures, the function now behaves as intended. The link to the updated script is here in case any one wants to play around with the function:

I implemented the logic of for moving either N or C-term. like this:
```
    for i, res in enumerate(mobile_sel):
        # find backbone C-alpha
        atom = res.find_atom("CA")

        # list containing 'small side' atom w.r.t C-alpha
        small_side_atoms = []

        # handle proline differently (for now)
        if res.name != "PRO":
            for nb, bond in zip(atom.neighbors, atom.bonds):
                if nb.name == "N":
                    small_side_atoms.append(bond.smaller_side.name)
                elif nb.name == "C":
                    small_side_atoms.append(bond.smaller_side.name)
            # if we want to move the 'N' terminus
            if mobile_terminal == "N":
                # residue is near N-term (phi & psi is the smaller side)
                move_smaller = set(small_side_atoms) == {"N", "CA"}
            elif mobile_terminal == "C":
                # residue is near C-term (phi & psi is the smaller side)
                move_smaller = set(small_side_atoms) == {"CA", "C"}

            psi_assgn = random.normalvariate(mu=135.0, sigma=noise)
            res.set_psi(psi_assgn, move_smaller_side=move_smaller)

            phi_assgn = random.normalvariate(mu=-139.0, sigma=noise)
            res.set_phi(phi_assgn, move_smaller_side=move_smaller)

```

Thanks Eric and Elaine!
-Daniel



On Dec 19, 2024, at 5:17 PM, Eric Pettersen <pett@cgl.ucsf.edu> wrote:

Hi Daniel,
Your code looks good to me except that, as Elaine pointed out, you have phi and psi inverted.

—Eric

On Dec 19, 2024, at 3:51 PM, Daniel Elnatan via ChimeraX-users <chimerax-users@cgl.ucsf.edu> wrote:

Hi Eric! thanks for the tips! 

Being able to specify N/C terminus as the ‘mobile’ part is easier to think about! 

If I understand correctly, I need to pass the correct side of the bond for being smaller to make use of the “move_smaller_side” argument. 

So, if I’m looking at the C-alpha, then the psi angle would be on the N-terminal side and the phi angle would be on the C-terminal side?

So I’ve got this written up (can’t afford to get fancy at the moment) to just assign the angles and move either the N/C terminal side:

```
def straighten_v2(session, mobile_sel, mobile_terminal, noise=5.0):
    """
    Args:
    mobile_sel (selection): selection of residue regions to be moved, must be a
    single
    contiguous region
    mobile_terminal (str): 'N' or 'C' terminal side
    noise (float): gaussian standard deviation to 'jitter' angles
    """
    import random

    mobile_terminal = mobile_terminal.upper()

    assert mobile_terminal.lower() in (
        "c",
        "n",
    ), "mobile_terminal can only be N or C"

    for i, res in enumerate(mobile_sel):
        # find backbone C-alpha
        atom = res.find_atom("CA")

        # handle proline differently (for now)
        if res.name != "PRO":
            # bond.smaller_side returns the atom that is on the smaller side
            for nb, bond in zip(atom.neighbors, atom.bonds):
                # look at peptide bond atoms only (no beta-carbons)
                if nb.name == "N":
                    # N-CA -> psi bond (N-terminal)
                    move_smaller_psi = (
                        bond.smaller_side.name == mobile_terminal
                    )
                elif nb.name == "C":
                    # Ca-C -> phi bond (C-terminal)
                    move_smaller_phi = (
                        bond.smaller_side.name == mobile_terminal
                    )

            psi_assgn = random.normalvariate(mu=165.0, sigma=noise)
            phi_assgn = random.normalvariate(mu=-165.0, sigma=noise)
            res.set_psi(psi_assgn, move_smaller_side=move_smaller_psi)
            res.set_phi(phi_assgn, move_smaller_side=move_smaller_phi)

```

It seems to work correctly in some small test cases… but I’ve got a feeling that I did not implement what you meant properly. Is this roughly what you were thinking?

Thanks for your help!
-D

On Dec 18, 2024, at 1:31 PM, Eric Pettersen <pett@cgl.ucsf.edu> wrote:



On Dec 18, 2024, at 1:26 PM, Eric Pettersen via ChimeraX-users <chimerax-users@cgl.ucsf.edu> wrote:

so if you use "for i, nb in enumerate(atom.neighbors):" to loop through the neighbor atoms

Probably even better:  for nb, bond in zip(atom.neighbors, atom.bonds):

--Eric



_______________________________________________
ChimeraX-users mailing list -- chimerax-users@cgl.ucsf.edu
To unsubscribe send an email to chimerax-users-leave@cgl.ucsf.edu
Archives: https://mail.cgl.ucsf.edu/mailman/archives/list/chimerax-users@cgl.ucsf.edu/