Esempio n. 1
0
def attempt_to_load_top_from_simtk(topology):
    """
    Load topology from SIMTK.

    Parameters
    ----------
    topology : str or Path

    Returns
    -------
    topology from mdtraj.Topology.from_openmm`

    Raises
    ------
    Dependency error from :func:`_log_simtkimport_error`, program
    halts.
    """
    topp = Path(topology)

    if topp.suffix == '.cif' and SIMTK:
        mol = app.PDBxFile(topp.str())
        return mdtraj.Topology.from_openmm(mol.topology)

    elif topp.suffix == '.cif' and not SIMTK:
        _log_simtkimport_error()

    else:
        return topp.str()
Esempio n. 2
0
def test_save_refs():
    """Test save references."""
    references.add("zello world")
    lc.save_references()
    p1 = Path(CMDFILE)
    s = p1.open().readlines()
    assert s[-1].split(':')[1][1:] == 'zello world'
    p1.unlink()
Esempio n. 3
0
def test_save_refs():
    """Test save references."""
    references.add("zello world")
    lc.save_references()
    p1 = Path(CMDFILE)
    s = p1.read_text().strip().split('\n')
    s = [i for i in s]
    assert s[-1] == 'zello world'
    p1.unlink()
Esempio n. 4
0
def test_param():
    """Test param plot."""
    p = Path('param.pdf')
    lplt.param(
        list(range(10)),
        list(range(10)),
        filename='param.pdf',
    )
    assert p.exists()
    p.unlink()
Esempio n. 5
0
def test_label_dots():
    """Test label_dots plot."""
    p = Path('label_dots.pdf')
    lplt.param(
        ['a', 'b', 'c'],
        list(range(3)),
        filename='label_dots.pdf',
    )
    assert p.exists()
    p.unlink()
Esempio n. 6
0
def add_prefix_to_path(ipath, prefix):
    """
    Add prefix to file path.

    Example
    -------

        >>> mk_frame_path('traj_output.xtc', prefix='my_prefix')
        >>> my_prefixtraj_output.xtc

    Mind the ``_`` is not placed automatically.

        >>> mk_frame_path('traj_output.xtc', prefix='my_prefix_')
        >>> my_prefix_traj_output.xtc

    Parameters
    ----------
    ipath : str or Path
        The file path to alter.

    prefix : str
        The complete prefix for the file name.

    Returns
    -------
    :py:func:`taurenmd.core.Path`
        The new file path.
    """
    ipath_ = _get_ipath(ipath)
    return Path(
        ipath_.myparents(),
        '{}{}'.format(prefix, ipath_.name),
    )
Esempio n. 7
0
def parse_top_output(top_output, traj_output=None):
    """
    Parse different output definitions for topology output file name.

    If ``top_output`` startswith ``_`` uses :py:func:add_suffix_to_path.
    If ``top_output`` endswith ``_`` uses :py:func:add_prefix_to_path.
    Else: Return Path object of ``top_output``.


    Parameters
    ----------
    top_output : str or Path
        The string to evaluate.

    traj_output : str or Path
        The trajectory output file name. Return value depends on
        this parameters.

    Returns
    -------
    :py:func:`taurenmd.core.Path`
        The new topology file path.
    """
    if str(top_output).startswith('_'):
        return add_suffix_to_path(traj_output, suffix=top_output)

    elif str(top_output).endswith('_'):
        return add_prefix_to_path(traj_output, prefix=top_output)

    else:
        return Path(top_output)
Esempio n. 8
0
def load_universe(topology, *trajectories, insort=False):
    """
    Load MDAnalysis universe.

    Accepts MDAnalysis compatible `topology formats`_ and
    `trajectory formats`_. Read further on the `MDAnalysis Universe`_.

    .. _topology formats: https://www.mdanalysis.org/docs/documentation_pages/topology/init.html
    .. _trajectory formats: https://www.mdanalysis.org/docs/documentation_pages/coordinates/init.html#supported-coordinate-formats
    .. _MDAnalysis Universe: https://www.mdanalysis.org/docs/documentation_pages/core/universe.html?highlight=universe#core-object-universe-mdanalysis-core-universe

    Examples
    --------

        >>> libmda.load_universe('topology.pdb', 'trajectory.dcd')

        >>> libmda.load_universe(
                'topology.pdb',
                'traj_part_1.xtc',
                'traj_part_2.xtc',
                Path('my', 'md', 'folder', 'traj_part_3.xtc'),
                )

    Parameters
    ----------
    topology : str or Path object
        Path to topology file.

    trajectories* : str of Path objects
        Paths to trajectory file(s). Trajectory files will be used
        sequentially to create the Universe.

    Return
    ------
    MDAnalysis Universe
    """  # noqa: E501 D412
    if insort:
        trajectories = libio.sort_numbered_input(*trajectories)

    libio.report_input(topology, trajectories)
    universe = mda.Universe(
        Path(topology).str(),
        [Path(i).str() for i in trajectories],
        )
    report(universe)
    return universe
Esempio n. 9
0
def add_suffix_to_path(ipath, suffix):
    """
    Add suffix to file path.

    If suffix has extention, updates the path extension, otherwise
    keeps the original extension.

    Examples
    --------

        >>> mk_frame_path('traj_output.xtc', suffix='my_suffix')
        >>> traj_outputmy_suffix.xtc

    Mind the underscore is not placed automatically:

        >>> mk_frame_path('traj_output.xtc', suffix='_my_suffix')
        >>> traj_output_my_suffix.xtc

    Updating extensions:

        >>> mk_frame_path('traj_output.xtc', suffix='_my_suffix.pdb')
        >>> traj_output_my_suffix.pdb

    Parameters
    ----------
    ipath : str or Path
        The file path to alter.

    suffix : str
        The complete suffix for the file name, extension should be
        included in the suffix, extension of the ``ipath`` is
        ignored.

    Returns
    -------
    :py:func:`taurenmd.core.Path`
        The new file path.
    """
    ipath_ = _get_ipath(ipath)
    result = Path(
        ipath_.myparents(),
        '{}{}'.format(ipath_.stem, suffix),
    )

    extension = Path(suffix).suffix or ipath_.suffix
    return result.with_suffix(extension)
Esempio n. 10
0
def mk_frame_path(ipath, frame=0, ext='.pdb', leading=0, suffix=None):
    """
    Create the path name for a frame.

    Given an input_path ``ipath`` (usually the name of the trajectory),
    create the corresponding frame file name.

    Example
    -------

        >>> mk_frame_path('traj_output.xtc')
        >>> traj_output_frame0.pdb

        >>> mk_frame_path('traj_output.xtc', frame=4, leading=4)
        >>> traj_output_frame0004.pdb

    Parameters
    ----------
    ipath : str or Path
        The file path. Normally, trajectory file path.

    frame : int, optional
        The frame to label the new path.
        Defaults to ``0``.

    ext : str, optional
        The returned file desired extension.
        Defaults to ``.pdb``.

    leading : int
        The leading zeros to left append to the frame number.
        Defaults to ``0``.

    suffix : str
        Complete specifications of the desired suffix.
        If ``suffix`` is given, ``frame`` and ``ext`` and ``leading``
        are ignored and :py:func:`add_suffix_to_path` is used directly.

    Returns
    -------
    :py:func:`taurenmd.core.Path`
        The new file path.
    """
    if suffix:
        return add_suffix_to_path(ipath, suffix)
    else:
        ipath_ = _get_ipath(ipath)
        return Path(
            ipath_.myparents(),
            '{}_frame{}'.format(ipath_.stem,
                                str(frame).zfill(leading)),
        ).with_suffix('.{}'.format(ext.lstrip('.')))
Esempio n. 11
0
def load_traj(topology, trajectory):
    """
    Load trajectory with `MDTraj <http://mdtraj.org/1.9.3/index.html>`_.
    
    Uses `mdtraj.load <http://mdtraj.org/1.9.3/api/generated/mdtraj.load.html?highlight=load#mdtraj.load>`_.
    
    Example
    -------
        
        >>> libmdt.load_traj('bigtopology.cif', 'trajectory.dcd')

    Parameters
    ----------
    topology : str or Path
        Path to the topology file. Accepts MDTraj compatible `topology files <http://mdtraj.org/1.9.3/load_functions.html#trajectory-reference>`_. mmCIF format is loaded using `OpenMM <http://mdtraj.org/1.9.3/api/generated/mdtraj.Topology.html?highlight=from_openmm#mdtraj.Topology.from_openmm>`_.

    trajectory : str or Path
        Path to the trajectory file. Accepts MDTraj compatible `files <http://mdtraj.org/1.9.3/load_functions.html#trajectory-reference>`_

    Returns
    -------
    MDTraj trajectory
        `Trajectory object <http://mdtraj.org/1.9.3/api/generated/mdtraj.Trajectory.html#mdtraj-trajectory>`_.
    """  # noqa: E501
    libio.report_input(topology, trajectory)

    topp = Path(topology)
    if topp.suffix == '.cif' and SIMTK:
        mol = app.PDBxFile(topp.str())
        top = mdtraj.Topology.from_openmm(mol.topology)
    elif topp.suffix == '.cif' and not SIMTK:
        _log_simtkimport_error()
    else:
        top = topp.str()

    mdtrajectory = mdtraj.load(Path(trajectory).str(), top=top)

    return mdtrajectory
Esempio n. 12
0
def main(
        topology,
        trajectories,
        insort=False,
        start=None,
        stop=None,
        step=None,
        flist=None,
        prefix='frame_',
        ext='pdb',
        selection='all',
        **kwargs):
    """Execute main client logic."""
    log.info('Starting...')

    u = libmda.load_universe(topology, *trajectories, insort=insort)

    frames_to_extract = libio.frame_list(
        len(u.trajectory),
        start=start,
        stop=stop,
        step=step,
        flist=flist,
        )

    log.info(S('extracting {} frames', len(frames_to_extract)))

    zeros = len(str(len(u.trajectory)))
    ext = ext.lstrip('.').strip()

    atom_group = u.select_atoms(selection)

    with libcli.ProgressBar(len(frames_to_extract), suffix='frames') as pb:
        for frame in frames_to_extract:
            file_name = '{}{}.{}'.format(
                prefix,
                str(frame).zfill(zeros),
                ext,
                )

            atom_group.write(
                filename=Path(file_name),
                frames=[frame],
                )

        log.info(S('writen frame {}, to {}', frame, file_name))
        pb.increment()

    return
Esempio n. 13
0
def get_number(path):
    """
    Extract tail number from path.

    Examples
    --------

        >>> get_number('traj_1.dcd')
        >>> 1

        >>> get_number('traj_3.dcd')
        >>> 3

        >>> get_number('traj_1231.dcd')
        >>> 1231

        >>> get_number('traj_0011.dcd')
        >>> 11

        >>> get_number('traj_1_.dcd')
        >>> 1

        >>> get_number('traj_20200101_1.dcd')
        >>> 1

    Parameters
    ----------
    path : str or Path obj
        The path to evaluate.

    Returns
    -------
    int
        The tail integer of the path.
    """
    stem = Path(path).stem
    number = re.findall(r'\d+', stem)[-1]
    return int(number)
Esempio n. 14
0
def main(topology,
         trajectories,
         insort=False,
         sel1='all',
         sel2='all',
         start=None,
         stop=None,
         step=None,
         export=False,
         plot=False,
         plotvars=None,
         **kwargs):
    """Execute main client logic."""
    log.info(T('measuring distances'))

    topology = Path(topology)
    trajectories = [Path(t) for t in trajectories]

    u = libmda.load_universe(topology, *trajectories, insort=insort)

    frame_slice = libio.frame_slice(
        start=start,
        stop=stop,
        step=step,
    )

    log.info(T('defining atom seletions'))
    log.info(S('atom selection #1: {}', sel1))
    log.info(S('atom selection #2: {}', sel2))
    atom_sel1 = u.select_atoms(sel1)
    atom_sel2 = u.select_atoms(sel2)

    distances = np.ones(len(u.trajectory[frame_slice]), dtype=np.float32)

    log.info(T('Calculating distances'))
    # https://www.mdanalysis.org/MDAnalysisTutorial/atomgroups.html
    # https://www.mdanalysis.org/docs/documentation_pages/core/groups.html#MDAnalysis.core.groups.AtomGroup.center_of_geometry

    with libcli.ProgressBar(distances.size, suffix='frames') as pb:
        for i, _ts in enumerate(u.trajectory[frame_slice]):

            distances[i] = np.linalg.norm(
                np.subtract(
                    atom_sel1.center_of_geometry(),
                    atom_sel2.center_of_geometry(),
                ))
            pb.increment()

    log.info(S('calculated a total of {} distances.', len(distances)))

    if export:
        libio.export_data_to_file(
            list(range(len(u.trajectory))[frame_slice]),
            distances,
            fname=export,
            header=('# Distances between two selections centers of geomemtry\n'
                    '# topology: {}\n'
                    '# trajectories: {}\n'
                    '# selection #1: {}\n'
                    '# selection #2: {}\n'
                    '# frame,distance\n').format(
                        topology,
                        ', '.join(t.resolve().str() for t in trajectories),
                        sel1,
                        sel2,
                    ),
        )

    if plot:
        plotvars = plotvars or dict()
        plotvars.setdefault('labels', '{} dist {}'.format(sel1, sel2))

        log.info(T('plot params:'))
        for k, v in plotvars.items():
            log.info(S('{} = {!r}', k, v))

        libplot.param(
            list(range(len(u.trajectory))[frame_slice]),
            distances,
            **plotvars,
        )

    log.info(S('done'))
    return
Esempio n. 15
0
def _get_ipath(ipath):
    try:
        return Path(ipath)
    except TypeError as err:
        log.exception(err)
        return Path()
Esempio n. 16
0
def test_save_command():
    """Tests only the interface."""
    lc.save_command('testcommandsave', 1, 2, 3, 4)
    Path('testcommandsave').unlink()
Esempio n. 17
0
def main(
    topology,
    trajectories,
    insort=None,
    start=None,
    stop=None,
    step=None,
    selection='all',
    traj_output='traj_out.dcd',
    top_output=None,
    unwrap=False,
    unwrap_reference=None,
    unwrap_compound='fragments',
    align=False,
    **kwargs,
):
    """Execute main client logic."""
    log.info(T('editing trajectory'))

    topology = Path(topology)
    trajectories = [Path(t) for t in trajectories]

    if insort:
        trajectories = libio.sort_numbered_input(*trajectories)

    u = libmda.load_universe(topology, *trajectories)

    if unwrap:
        log.info(T('unwrapping'))
        log.info(S('set to: {}', unwrap))
        log.info(S('reference: {}', unwrap_reference))
        log.info(S('compound: {}', unwrap_compound))

    if align:
        log.info(T('Alignment'))
        log.info(S('trajectory selection will be aligned to subselection:'))
        log.info(S('- {}', align, indent=2))
        align_reference = mda.Universe(Path(topology).str())

    log.info(T('transformation'))
    sliceObj = libio.frame_slice(start, stop, step)

    log.info(S('selecting: {}', selection))
    atom_selection = u.select_atoms(selection)
    log.info(S('with {} atoms', atom_selection.n_atoms, indent=2))

    log.info(T('saving trajectory'))
    traj_output = Path(traj_output)
    log.info(S('destination: {}', traj_output.resolve().str()))

    with mda.Writer(traj_output.str(), atom_selection.n_atoms) as W:
        for i, _ts in zip(
                range(len(u.trajectory))[sliceObj],
                u.trajectory[sliceObj],
        ):

            log.info(S('working on frame: {}', i))

            if unwrap:
                log.debug(S('unwrapping', indent=2))
                atom_selection.unwrap(
                    reference=unwrap_reference,
                    compound=unwrap_compound,
                )

            if align:
                try:
                    libmda.mdaalignto(u, align_reference, selection=align)
                except ZeroDivisionError:
                    _controlled_exit()

            W.write(atom_selection)

    log.info(S('trajectory saved'))

    if top_output:
        log.info(T('saving topology'))
        fout = libio.parse_top_output(top_output, traj_output)
        log.info(S('saving frame 0 to: {}', fout.resolve()))
        with mda.Writer(fout.str(), atom_selection.n_atoms) as W:
            for _ts in u.trajectory[sliceObj][0:1]:
                if unwrap:
                    log.debug(S('unwrapping for topology', indent=2))
                    atom_selection.unwrap(
                        reference=unwrap_reference,
                        compound=unwrap_compound,
                    )
                W.write(atom_selection)

    log.info(S('Done'))
    return
Esempio n. 18
0
def main(topology,
         trajectories,
         plane_selection,
         aunit='degrees',
         ref_frame=0,
         start=None,
         stop=None,
         step=None,
         export=False,
         plot=False,
         plotvars=None,
         **kwargs):
    """Execute main client logic."""
    log.info(T('calculating angles'))

    topology = Path(topology)
    trajectories = [Path(t) for t in trajectories]

    u = libmda.load_universe(topology, *trajectories)

    frame_slice = libio.frame_slice(
        start=start,
        stop=stop,
        step=step,
    )
    log.info(S('for slice {}', frame_slice))

    log.info(T('calculating plane eq. for reference frame'))
    log.info(S('using frame: {}', ref_frame))
    u.trajectory[ref_frame]
    reference_point_1 = u.select_atoms(plane_selection[0]).center_of_geometry()
    reference_point_2 = u.select_atoms(plane_selection[1]).center_of_geometry()
    reference_point_3 = u.select_atoms(plane_selection[2]).center_of_geometry()

    ra, rb, rc, rd = libcalc.calc_plane_eq(
        reference_point_1,
        reference_point_2,
        reference_point_3,
    )
    log.info(S('the equation is {}x + {}y + {}z = {}', ra, rb, rc, rd))

    log.info(T('Calculating angles'))
    angles = []
    for _ts in u.trajectory[frame_slice]:

        point1 = u.select_atoms(plane_selection[0]).center_of_geometry()
        point2 = u.select_atoms(plane_selection[1]).center_of_geometry()
        point3 = u.select_atoms(plane_selection[2]).center_of_geometry()

        a, b, c, d = libcalc.calc_plane_eq(point1, point2, point3)

        angles.append(
            libcalc.calc_planes_angle(
                ra,
                rb,
                rc,
                a,
                b,
                c,
                aunit=aunit,
            ))

    log.info(S('calculated a total of {} angles.', len(angles)))

    if export:
        libio.export_data_to_file(
            list(range(len(u.trajectory))[frame_slice]),
            angles,
            fname=export,
            header=('# Angular oscillation between a plane representatives\n'
                    '# topology: {}\n'
                    '# trajectories: {}\n'
                    '# selections: {}\n'
                    '# frame,angle({})\n').format(
                        topology,
                        ', '.join(t.resolve().str() for t in trajectories),
                        plane_selection,
                        aunit,
                    ),
        )

    if plot:
        plotvars = plotvars or dict()
        plotvars.setdefault(
            'labels',
            'plane: {}'.format(' and '.join(plane_selection)),
        )

        log.info(T('plot params:'))
        for k, v in plotvars.items():
            log.info(S('{} = {!r}', k, v))

        libplot.param(
            list(range(len(u.trajectory))[frame_slice]),
            angles,
            **plotvars,
        )

    log.info(S('done'))
    return
Esempio n. 19
0
def main(
        topology,
        trajectories,
        insort=False,
        start=None,
        stop=None,
        step=None,
        ref_frame=0,
        selections=None,
        export=False,
        plot=False,
        plotvars=None,
        **kwargs
        ):
    """Execute main client logic."""
    log.info(T('starting'))

    u = libmda.load_universe(topology, *trajectories, insort=insort)

    frame_slice = libio.frame_slice(
        start=start,
        stop=stop,
        step=step,
        )

    if selections is None:
        selections = ['all']

    rmsds = []
    for selection in selections:
        rmsds.append(
            libcalc.mda_rmsd(
                u,
                frame_slice=frame_slice,
                selection=selection,
                ref_frame=ref_frame,
                )
            )
    if export:
        libio.export_data_to_file(
            list(range(len(u.trajectory))[frame_slice]),
            *rmsds,
            fname=export,
            delimiter=',',
            header=(
                "# Date: {}\n'"
                "# Topology: {}\n"
                "# Trajectories : {}\n"
                "# ref frame: {}\n"
                "# frame number,{}\n"
                ).format(
                    datetime.now(),
                    Path(topology).resolve(),
                    ', '.join(f.resolve().str() for f in trajectories),
                    ref_frame,
                    ','.join(selections),
                    ),
            )

    if plot:
        plotvars = plotvars or dict()
        plotvars.setdefault('labels', selections)

        log.info(T('plot params:'))
        for k, v in plotvars.items():
            log.info(S('{} = {!r}', k, v))

        libplot.param(
            list(range(len(u.trajectory))[frame_slice]),
            rmsds,
            **plotvars,
            )

    return
Esempio n. 20
0
def main(topology,
         trajectories,
         start=None,
         stop=None,
         step=None,
         selections=None,
         export=False,
         plot=False,
         plotvars=None,
         **kwargs):
    """Execute client main logic."""
    log.info(T('starting RMSFs calculation'))

    topology = Path(topology)
    trajectories = [Path(t) for t in trajectories]

    u = libmda.load_universe(topology, *trajectories)

    frame_slice = libio.frame_slice(
        start=start,
        stop=stop,
        step=step,
    )

    if selections is None:
        selections = ['all']

    if not isinstance(selections, list) or len(selections) == 0:
        raise TypeError('selections must be LIST with at least one element')

    log.info(T('calculating'))
    for sel in selections:
        labels = []
        rmsfs = []
        log.info(S('for selection: {}', sel))
        atom_group = u.select_atoms(sel)
        labels = libmda.draw_atom_label_from_atom_group(atom_group)

        rmsfs = libcalc.mda_rmsf(
            atom_group,
            frame_slice=frame_slice,
        )

        if export:
            libio.export_data_to_file(
                labels,
                rmsfs,
                fname=export,
                header=("# Date: {}\n"
                        "# Topology: {}\n"
                        "# Trajectories {}\n"
                        "# Atom,RMSF\n").format(
                            datetime.now().strftime("%d/%m/%Y, %H:%M:%S"),
                            Path(topology).resolve(),
                            ', '.join(f.resolve().str() for f in trajectories),
                        ),
            )

        if plot:
            plotvars = plotvars or dict()
            plotvars.setdefault('series_labels', selections)

            log.info(T('plot params:'))
            for k, v in plotvars.items():
                log.info(S('{} = {!r}', k, v))

            libplot.label_dots(
                labels,
                rmsfs,
                **plotvars,
            )

    return
Esempio n. 21
0
def main(
        topology,
        trajectories,
        plane_selection,
        aunit='degrees',
        start=None,
        stop=None,
        step=None,
        export=False,
        **kwargs,
        ):
    """Execute main client logic."""
    log.info(T('starting'))
    
    topology = Path(topology)
    trajectories = [Path(t) for t in trajectories]

    u = libmda.load_universe(topology, *trajectories)

    log.info(T('transformation'))
    fSlice = libio.frame_slice(start=start, stop=stop, step=step)
    
    origin_selection = ' or '.join(plane_selection)
    pABC_atomG = u.select_atoms(origin_selection)
    ABC_selections = plane_selection
    # p stands for point
    pA_atomG = u.select_atoms(ABC_selections[0])
    pB_atomG = u.select_atoms(ABC_selections[1])
    pC_atomG = u.select_atoms(ABC_selections[2])

    u.trajectory[0]
    
    # defining the center of reference
    pABC_cog = pABC_atomG.center_of_geometry()
    log.info(T('Original Center of Geometry'))
    log.info(S('for frame: 0'))
    log.info(S('for selection: {}', origin_selection))
    log.info(S('pABC_cog: {}', pABC_cog))
    
    log.info(T('Transfering'))
    log.info(S('all coordinates of reference frame to the origin 0, 0, 0'))
    pABC_atomG.positions = pABC_atomG.positions - pABC_cog
    log.info(S('COG in origin: {}', pABC_atomG.center_of_geometry()))

    log.info(T('defining the reference axes'))
    pA_cog = pA_atomG.center_of_geometry()
    pB_cog = pB_atomG.center_of_geometry()
    pC_cog = pC_atomG.center_of_geometry()
    log.info(S('plane points definition:'))
    log.info(S('pA: {}', pA_cog))
    log.info(S('pB: {}', pB_cog))
    log.info(S('pC: {}', pC_cog))

    log.info(T('defining the normal vector to reference plane'))
    ref_plane_normal = libcalc.calc_plane_normal(pA_cog, pB_cog, pC_cog)
    log.info(S('plane normal: {}', ref_plane_normal))
    log.info(S('done'))

    log.info(T('defining the cross product vector'))
    ref_plane_cross = np.cross(pA_cog, ref_plane_normal)
    log.info(S('np cross: {}', ref_plane_cross))
    
    roll_angles = []
    pitch_angles = []
    yaw_angles = []

    for i, _ts in enumerate(u.trajectory[fSlice]):
        print(f'.. working for frame :{i}')

        pABC_cog_ts = pABC_atomG.center_of_geometry()
        pABC_atomG.positions = pABC_atomG.positions - pABC_cog_ts

        pA_cog_ts = pA_atomG.center_of_geometry()
        pB_cog_ts = pB_atomG.center_of_geometry()
        pC_cog_ts = pC_atomG.center_of_geometry()

        ts_plane_normal = libcalc.calc_plane_normal(
            pA_cog_ts,
            pB_cog_ts,
            pC_cog_ts,
            )

        ts_plane_cross = np.cross(pA_cog_ts, ts_plane_normal)

        # Calculating Quaternion Rotations
        roll_Qs_tuples = libcalc.generate_quaternion_rotations(
            ref_plane_normal,
            pA_cog_ts,
            )

        pitch_Qs_tuples = libcalc.generate_quaternion_rotations(
            ref_plane_cross,
            ts_plane_normal,
            )

        yaw_Qs_tuples = libcalc.generate_quaternion_rotations(
            pA_cog,
            ts_plane_cross,
            )

        roll_minimum = libcalc.sort_by_minimum_Qdistances(
            roll_Qs_tuples,
            pA_cog,
            )[0][0]

        pitch_minimum = libcalc.sort_by_minimum_Qdistances(
            pitch_Qs_tuples,
            ref_plane_normal,
            )[0][0]

        yaw_minimum = libcalc.sort_by_minimum_Qdistances(
            yaw_Qs_tuples,
            ref_plane_cross,
            )[0][0]
        
        if aunit == 'degrees':
            roll_angles.append(round(roll_minimum.degrees, 3))
            pitch_angles.append(round(pitch_minimum.degrees, 3))
            yaw_angles.append(round(yaw_minimum.degrees, 3))
        else:
            roll_angles.append(round(roll_minimum.radians, 3))
            pitch_angles.append(round(pitch_minimum.radians, 3))
            yaw_angles.append(round(yaw_minimum.radians, 3))
    
    if export:
        file_names = []
        for _fname in ['roll', 'pitch', 'yaw']:
            file_names.append(
                libio.add_prefix_to_path(
                    export,
                    f"{_fname}_angles_",
                    )
                )

        log.info(T('Saving data to files'))
        for data, fname in zip(
                [roll_angles, pitch_angles, yaw_angles],
                file_names,
                ):

            log.info(S('saving {}', fname))
            libio.export_data_to_file(
                list(range(len(u.trajectory))[fSlice]),
                data,
                fname=fname,
                header=(
                    '# Topology: {}\n'
                    '# Trajectories: {}\n'
                    '# Plane Selection: {}\n'
                    '# frame,ange{}\n'
                    ).format(
                        topology,
                        ', '.join(t.resolve().str() for t in trajectories),
                        origin_selection,
                        aunit,
                        ),
                )
        log.info(S('done'))

    return