Exemplo n.º 1
0
def cg_by_index(trj,
                atom_indices_list,
                bead_label_list,
                chain_list=None,
                segment_id_list=None,
                resSeq_list=None,
                inplace=False,
                bonds=None,
                split_shared_atoms=False,
                mod_weights_list=None,
                mapping_function="com",
                charge_tol=1e-5,
                center_postwrap=False):
    """Create a coarse grained (CG) trajectory from subsets of atoms by
        computing centers of mass of selected sets of atoms.
    Parameters
    ----------
    atom_indices_list :
        list of array-like, dtype=int, shape=(n_beads,n_atoms)
        List of indices of atoms to combine into CG sites
    bead_label_list :
        list of maximum 4-letter strings to label CG sites
    chain_list :
        optional list of chain id's to split resulting beads into separate
        chains
    resSeq_list :
        optional list of residue sequence id's to assign cg residues
    segment_id_list :
        optional list of segment id's to assign cg residues
    inplace :
        bool, default=False
        If ``True``, the operation is done inplace, modifying ``trj``.
        Otherwise, a copy is returned with the sliced atoms, and
        ``trj`` is not modified.
    bonds : array-like,dtype=int, shape=(n_bonds,2), default=None
        If specified, sets these bonds in new topology
    split_shared_atoms: boolean
        If specified, check to see if atoms are shared per molecule in beads. If
        so, equally divide their weight accordingly for each bead.
    mapping_function: string, default='com': how to map xyz coordinates
        options: %s
    center_postwrap: Boolean
        Whether to wrap the CG system after it is mapped. Assumes that box is
        centered at 0, and only has effect if periodic information is present.

    Note - If repeated resSeq values are used, as for a repeated motiff
        in a CG polymer, those sections most be broken into separate
        chains or an incorrect topology will result

    Returns
    -------
    traj : md.Trajectory
        The return value is either ``trj``, or the new trajectory,
        depending on the value of ``inplace``.
    """ % mapping_options.keys()

    if not len(atom_indices_list) == len(bead_label_list):
        raise ValueError("Must supply a list of bead labels of the "
                         "same length as a list of selected atom indices")
    for bead_label in bead_label_list:
        if not (type(bead_label) is
                str) or len(bead_label) > 4 or len(bead_label) < 1:
            raise ValueError("Specified bead label '%s' is not valid, \
                             must be a string between 1 and 4 characters" %
                             bead_label)

    bead_label_list = [bead_label.upper() for bead_label in bead_label_list]

    if mapping_function not in mapping_options:
        raise ValueError("Must select a mapping function from: %s"\
                         %mapping_options.keys())

    if chain_list is None:
        chain_list = np.ones(len(atom_indices_list), dtype=int)
    elif len(chain_list) != len(atom_indices_list):
        raise ValueError("Supplied chain_list must be of the same length "
                         "as a list of selected atom indices")

    if segment_id_list is not None and len(segment_id_list) != len(
            atom_indices_list):
        raise ValueError("Supplied segment_id_list must be of the same "
                         "length as a list of selected atom indices")

    if resSeq_list is not None and len(resSeq_list) != len(atom_indices_list):
        raise ValueError("Supplied resSeq_list must be of the same "
                         "length as a list of selected atom indices")

    n_beads = len(atom_indices_list)

    xyz = np.zeros((trj.xyz.shape[0], n_beads, trj.xyz.shape[2]),
                   dtype=trj.xyz.dtype,
                   order='C')

    forces = np.zeros((trj.xyz.shape[0], n_beads, trj.xyz.shape[2]),
                      dtype=np.double,
                      order='C')

    columns = ["serial", "name", "element", "resSeq", "resName", "chainID"]

    #total masse for each cg bead.
    masses = np.zeros((n_beads), dtype=np.float64)
    #list of masses for elements in cg bead.
    masses_i = []
    #masses
    for ii in range(n_beads):
        #atoms in curent cg bead.
        atom_indices = atom_indices_list[ii]
        #first, construct lists of masses in current cg bead.
        temp_masses = np.array([])
        for jj in atom_indices:
            temp_masses = np.append(temp_masses, trj.top.atom(jj).element.mass)

        masses_i.append(temp_masses)
        masses[ii] = masses_i[ii].sum()

    if hasattr(trj.top.atom(1), 'charge'):
        #total charge for each cg bead.
        charges = np.zeros((n_beads), dtype=np.float64)
        #lists of charges for in current cg bead
        charges_i = []

        #charges
        for ii in range(n_beads):

            #atoms in curent cg bead.
            atom_indices = atom_indices_list[ii]

            #first, construct lists of masses in current cg bead.
            temp_charges = np.array([])

            for jj in atom_indices:
                temp_charges = np.append(temp_charges, trj.top.atom(jj).charge)

            charges_i.append(temp_charges)
            charges[ii] = charges_i[ii].sum()

    forcenorm_i = []
    if mapping_function == 'cof' or mapping_function == 'center_of_force':
        for ii in range(n_beads):
            atom_indices = atom_indices_list[ii]
            forcenorm_i.append(get_forcenorms(trj, atom_indices))

    if mapping_function == 'coc' or mapping_function == 'center_of_charge':
        for charge in charges:
            if np.absolute(charge) < charge_tol:
                raise ValueError("Total charge on site %i is near zero" % ii)

    topology_labels = []
    element_label_dict = {}

    if (split_shared_atoms):
        mod_weights_list = gen_unique_overlap_mod_weights(atom_indices_list)

    has_forces = False
    try:
        trj.__dict__['forces']
        test_forces = map_forces(trj, (0, ))
        has_forces = True
    except TypeError:
        print("WARNING: Invalid Forces\nNo Map applied to forces")
    except KeyError:
        pass
    except:
        print("Unknown error, check your forces\nexiting...")
        raise

    for i in range(n_beads):
        atom_indices = atom_indices_list[i]
        bead_label = bead_label_list[i]
        xyz_i = xyz[:, i, :]

        if mapping_function == 'coc' or mapping_function == 'center_of_charge':
            weights = charges_i[i]
        elif mapping_function == 'com' or mapping_function == 'center_of_mass':
            weights = masses_i[i]
        elif mapping_function == 'cof' or mapping_function == 'center_of_force':
            weights = forcenorm_i[i]
        elif mapping_function == 'center':
            weights = np.ones(len(atom_indices))

        if (mod_weights_list is not None):
            weights[:] = np.multiply(weights, mod_weights_list[i])

        compute_center_weighted(xyz_i,
                                trj.xyz,
                                atom_indices,
                                weights,
                                unitcell_lengths=trj.unitcell_lengths,
                                center_postwrap=center_postwrap)

        if has_forces:
            forces_i = map_forces(trj, atom_indices)
            forces[:, i, :] = forces_i

        if resSeq_list is not None:
            resSeq = resSeq_list[i]
        else:
            resSeq = i + 1

        #element_label='%4s'%('B%i'%(resSeq))
        if not bead_label in element_label_dict:
            element_label = '%2s' % ('B%i' % (len(element_label_dict) % 10))
            element_label_dict[bead_label] = element_label
        else:
            element_label = element_label_dict[bead_label]

        if element_label.strip().upper(
        ) not in element.Element._elements_by_symbol:
            element.Element(1000 + resSeq, element_label, element_label,
                            masses[i], 1.0)

        topology_labels.append([
            i, bead_label, element_label, resSeq,
            '%3s' % bead_label, chain_list[i]
        ])

    df = pd.DataFrame(topology_labels, columns=columns)
    topology = Topology.from_dataframe(df, bonds=bonds)

    if segment_id_list is not None:
        for beadidx, bead in enumerate(topology.atoms):
            bead.residue.segment_id = segment_id_list[beadidx]

    if inplace:
        if trj._topology is not None:
            trj._topology = topology
        trj._xyz = xyz

        return trj

    unitcell_lengths = unitcell_angles = None
    if trj._have_unitcell:
        unitcell_lengths = trj._unitcell_lengths.copy()
        unitcell_angles = trj._unitcell_angles.copy()

    time = trj._time.copy()

    new_trj = Trajectory(xyz=xyz,
                         topology=topology,
                         time=time,
                         unitcell_lengths=unitcell_lengths,
                         unitcell_angles=unitcell_angles)

    new_trj.forces = forces
    return new_trj
Exemplo n.º 2
0
def cg_by_index(trj,
                atom_indices_list,
                bead_label_list,
                chain_list=None,
                segment_id_list=None,
                resSeq_list=None,
                inplace=False,
                bonds=None,
                mapping_function="com"):
    """Create a coarse grained (CG) trajectory from subsets of atoms by 
        computing centers of mass of selected sets of atoms.
    Parameters
    ----------
    atom_indices_list : list of array-like, dtype=int, shape=(n_beads,n_atoms)
        List of indices of atoms to combine into CG sites
    bead_label_list : list of maximum 4-letter strings to label CG sites
    chain_list : optional list of chain id's to split resulting beads into separate chains
    resSeq_list : optional list of residue sequence id's to assign cg residues
    segment_id_list : optional list of segment id's to assign cg residues
    inplace : bool, default=False
        If ``True``, the operation is done inplace, modifying ``trj``.
        Otherwise, a copy is returned with the sliced atoms, and
        ``trj`` is not modified.
    bonds : array-like,dtype=int, shape=(n_bonds,2), default=None
        If specified, sets these bonds in new topology 
    mapping_function: string, default='com': how to map xyz coordinates
        options: %s

    Note - If repeated resSeq values are used, as for a repeated motiff in a CG polymer, 
        those sections most be broken into separate chains or an incorrect topology will result
 
    Returns
    -------
    traj : md.Trajectory
        The return value is either ``trj``, or the new trajectory,
        depending on the value of ``inplace``.
    """ % mapping_options.keys()
    if not len(atom_indices_list) == len(bead_label_list):
        raise ValueError(
            "Must supply a list of bead labels of the same length as a list of selected atom indices"
        )
    for bead_label in bead_label_list:
        if not (type(bead_label) is
                str) or len(bead_label) > 4 or len(bead_label) < 1:
            raise ValueError(
                "Specified bead label '%s' is not valid, must be a string between 1 and 4 characters"
                % bead_label)
    bead_label_list = [bead_label.upper() for bead_label in bead_label_list]

    if mapping_function not in mapping_options:
        raise ValueError("Must select a mapping function from: %s" %
                         mapping_options.keys())
    map_coords = mapping_options[mapping_function]

    if chain_list is None:
        chain_list = np.ones(len(atom_indices_list), dtype=int)
    elif len(chain_list) != len(atom_indices_list):
        raise ValueError(
            "Supplied chain_list must be of the same length as a list of selected atom indices"
        )

    if segment_id_list is not None and len(segment_id_list) != len(
            atom_indices_list):
        raise ValueError(
            "Supplied segment_id_list must be of the same length as a list of selected atom indices"
        )

    if resSeq_list is not None and len(resSeq_list) != len(atom_indices_list):
        raise ValueError(
            "Supplied resSeq_list must be of the same length as a list of selected atom indices"
        )

    n_beads = len(atom_indices_list)
    xyz = np.zeros((trj.xyz.shape[0], n_beads, trj.xyz.shape[2]),
                   dtype=trj.xyz.dtype,
                   order='C')
    forces = np.zeros((trj.xyz.shape[0], n_beads, trj.xyz.shape[2]),
                      dtype=np.double,
                      order='C')
    columns = ["serial", "name", "element", "resSeq", "resName", "chainID"]
    masses = np.array([
        np.sum([a.mass for a in trj.top.atoms if a.index in atom_indices])
        for atom_indices in atom_indices_list
    ],
                      dtype=np.float64)
    charges = np.array([
        np.sum([a.charge for a in trj.top.atoms if a.index in atom_indices])
        for atom_indices in atom_indices_list
    ],
                       dtype=np.float64)

    topology_labels = []
    element_label_dict = {}

    xyz_i = np.zeros((trj.xyz.shape[0], trj.xyz.shape[2]),
                     dtype=trj.xyz.dtype,
                     order='C')

    for i in range(n_beads):
        atom_indices = atom_indices_list[i]
        bead_label = bead_label_list[i]
        #xyz_i = map_coords(trj,atom_indices)

        masses_i = np.array(
            [a.mass for a in trj.top.atoms if a.index in atom_indices_list[i]],
            dtype=np.float64)

        map_coords(xyz_i,
                   trj.xyz,
                   atom_indices,
                   masses_i,
                   unitcell_lengths=trj.unitcell_lengths)

        xyz[:, i, :] = xyz_i

        if "forces" in trj.__dict__ and len(trj.forces) > 0:
            forces_i = map_forces(trj, atom_indices)
            forces[:, i, :] = forces_i

        if resSeq_list is not None:
            resSeq = resSeq_list[i]
        else:
            resSeq = i + 1

        #element_label='%4s'%('B%i'%(resSeq))
        if not bead_label in element_label_dict:
            element_label = '%2s' % ('B%i' % (len(element_label_dict) % 10))
            element_label_dict[bead_label] = element_label
        else:
            element_label = element_label_dict[bead_label]

        if element_label.strip().upper(
        ) not in element.Element._elements_by_symbol:
            element.Element(1000 + resSeq, element_label, element_label,
                            masses[i], 1.0)

        topology_labels.append([
            i, bead_label, element_label, resSeq,
            '%3s' % bead_label, chain_list[i]
        ])

    df = pd.DataFrame(topology_labels, columns=columns)
    topology = Topology.from_dataframe(df, bonds=bonds)

    if segment_id_list is not None:
        for beadidx, bead in enumerate(topology.atoms):
            bead.residue.segment_id = segment_id_list[beadidx]

    if inplace:
        if trj._topology is not None:
            trj._topology = topology
        trj._xyz = xyz

        return trj

    unitcell_lengths = unitcell_angles = None
    if trj._have_unitcell:
        unitcell_lengths = trj._unitcell_lengths.copy()
        unitcell_angles = trj._unitcell_angles.copy()
    time = trj._time.copy()

    new_trj = Trajectory(xyz=xyz,
                         topology=topology,
                         time=time,
                         unitcell_lengths=unitcell_lengths,
                         unitcell_angles=unitcell_angles)
    new_trj.forces = forces
    return new_trj
Exemplo n.º 3
0
def cg_by_index(trj, atom_indices_list, bead_label_list, chain_list=None, segment_id_list=None, resSeq_list=None, inplace=False, bonds=None, mapping_function="com"):
    """Create a coarse grained (CG) trajectory from subsets of atoms by 
        computing centers of mass of selected sets of atoms.
    Parameters
    ----------
    atom_indices_list : list of array-like, dtype=int, shape=(n_beads,n_atoms)
        List of indices of atoms to combine into CG sites
    bead_label_list : list of maximum 4-letter strings to label CG sites
    chain_list : optional list of chain id's to split resulting beads into separate chains
    resSeq_list : optional list of residue sequence id's to assign cg residues
    segment_id_list : optional list of segment id's to assign cg residues
    inplace : bool, default=False
        If ``True``, the operation is done inplace, modifying ``trj``.
        Otherwise, a copy is returned with the sliced atoms, and
        ``trj`` is not modified.
    bonds : array-like,dtype=int, shape=(n_bonds,2), default=None
        If specified, sets these bonds in new topology 
    mapping_function: string, default='com': how to map xyz coordinates
        options: %s

    Note - If repeated resSeq values are used, as for a repeated motiff in a CG polymer, 
        those sections most be broken into separate chains or an incorrect topology will result
 
    Returns
    -------
    traj : md.Trajectory
        The return value is either ``trj``, or the new trajectory,
        depending on the value of ``inplace``.
    """%mapping_options.keys()
    if not len(atom_indices_list)==len(bead_label_list):
        raise ValueError("Must supply a list of bead labels of the same length as a list of selected atom indices")
    for bead_label in bead_label_list:
        if not (type(bead_label) is str) or len(bead_label)>4 or len(bead_label)<1:
            raise ValueError("Specified bead label '%s' is not valid, must be a string between 1 and 4 characters"%bead_label)
    bead_label_list = [ bead_label.upper() for bead_label in bead_label_list ]

    if mapping_function not in mapping_options:
        raise ValueError("Must select a mapping function from: %s"%mapping_options.keys())
    map_coords = mapping_options[mapping_function]

    if chain_list is None:
        chain_list = np.ones(len(atom_indices_list),dtype=int)
    elif len(chain_list)!=len(atom_indices_list):
        raise ValueError("Supplied chain_list must be of the same length as a list of selected atom indices")

    if segment_id_list is not None and len(segment_id_list)!=len(atom_indices_list):
        raise ValueError("Supplied segment_id_list must be of the same length as a list of selected atom indices")

    if resSeq_list is not None and len(resSeq_list)!=len(atom_indices_list):
        raise ValueError("Supplied resSeq_list must be of the same length as a list of selected atom indices")

    n_beads = len(atom_indices_list)
    xyz = np.zeros((trj.xyz.shape[0],n_beads,trj.xyz.shape[2]),dtype=trj.xyz.dtype,order='C')
    forces = np.zeros((trj.xyz.shape[0],n_beads,trj.xyz.shape[2]),dtype=np.double,order='C')
    columns = ["serial","name","element","resSeq","resName","chainID"]
    masses = np.array([  np.sum([a.mass for a in trj.top.atoms if a.index in atom_indices]) for atom_indices in atom_indices_list],dtype=np.float64)
    charges = np.array([  np.sum([a.charge for a in trj.top.atoms if a.index in atom_indices]) for atom_indices in atom_indices_list],dtype=np.float64)

    topology_labels = []
    element_label_dict = {}

    xyz_i = np.zeros((trj.xyz.shape[0],trj.xyz.shape[2]),dtype=trj.xyz.dtype,order='C')

    for i in range(n_beads):
        atom_indices = atom_indices_list[i]
        bead_label = bead_label_list[i]
        #xyz_i = map_coords(trj,atom_indices)

        masses_i = np.array([a.mass for a in trj.top.atoms if a.index in atom_indices_list[i]],dtype=np.float64)

        map_coords(xyz_i,trj.xyz,atom_indices,masses_i,unitcell_lengths=trj.unitcell_lengths)

        xyz[:,i,:] = xyz_i

        if "forces" in trj.__dict__ and len(trj.forces)>0:
            forces_i = map_forces(trj,atom_indices)
            forces[:,i,:] = forces_i

        if resSeq_list is not None:
            resSeq = resSeq_list[i]
        else:
            resSeq = i + 1 

        #element_label='%4s'%('B%i'%(resSeq))
        if not bead_label in element_label_dict:
            element_label='%2s'%('B%i'%(len(element_label_dict)%10))
            element_label_dict[bead_label] = element_label
        else:
            element_label = element_label_dict[bead_label]

        if element_label.strip().upper() not in element.Element._elements_by_symbol:
            element.Element(1000+resSeq, element_label, element_label, masses[i], 1.0)

        topology_labels.append( [i,bead_label,element_label,resSeq,'%3s'%bead_label,chain_list[i]] )

    df = pd.DataFrame(topology_labels,columns=columns)
    topology = Topology.from_dataframe(df,bonds=bonds)
    
    if segment_id_list is not None:
        for beadidx,bead in enumerate(topology.atoms):
            bead.residue.segment_id = segment_id_list[beadidx]
        
    if inplace:
        if trj._topology is not None:
            trj._topology = topology
        trj._xyz = xyz

        return trj

    unitcell_lengths = unitcell_angles = None
    if trj._have_unitcell:
        unitcell_lengths = trj._unitcell_lengths.copy()
        unitcell_angles = trj._unitcell_angles.copy()
    time = trj._time.copy()

    new_trj = Trajectory(xyz=xyz, topology=topology, time=time,
                      unitcell_lengths=unitcell_lengths,
                      unitcell_angles=unitcell_angles)
    new_trj.forces = forces
    return new_trj