Exemplo n.º 1
0
    def test_dump_bonds(self):
        measure = BondSet(self.data_dir.joinpath("sugar.bnd"), DummyOptions)
        frame = Frame(self.data_dir.joinpath("sugar.gro"),
                      self.data_dir.joinpath("sugar.xtc"))
        mapping = Mapping(self.data_dir.joinpath("sugar.map"), DummyOptions)

        cg_frame = mapping.apply(frame)

        measure.apply(cg_frame)
        measure.boltzmann_invert()
        measure.dump_values()

        filenames = ("ALLA_length.dat", "ALLA_angle.dat", "ALLA_dihedral.dat")
        for filename in filenames:
            self.assertTrue(
                cmp_file_whitespace_float(self.data_dir.joinpath(filename),
                                          filename,
                                          rtol=0.008,
                                          verbose=True))
            os.remove(filename)
Exemplo n.º 2
0
class PyCGTOOL:
    def __init__(self, config):
        self.config = config

        self.in_frame = Frame(
            topology_file=self.config.topology,
            trajectory_file=self.config.trajectory,  # May be None
            frame_start=self.config.begin,
            frame_end=self.config.end,
        )

        self.mapping = None
        self.out_frame = self.in_frame
        if self.config.mapping:
            self.mapping, self.out_frame = self.apply_mapping(self.in_frame)

        if self.out_frame.natoms == 0:
            # The following steps won't work with frames containing no atoms
            logger.warning(
                "Mapped trajectory contains no atoms - check your mapping file is correct!"
            )
            return

        self.bondset = None
        if self.config.bondset:
            self.bondset = BondSet(self.config.bondset, self.config)
            self.measure_bonds()

        if self.config.output_xtc:
            self.out_frame.save(self.get_output_filepath("xtc"))

    def get_output_filepath(self, ext: PathLike) -> pathlib.Path:
        """Get file path for an output file by extension.

        Creates the output directory if missing.
        """
        out_dir = pathlib.Path(self.config.out_dir)
        out_dir.mkdir(parents=True, exist_ok=True)
        return out_dir.joinpath(self.config.output_name + "." + ext)

    def apply_mapping(self, in_frame: Frame) -> typing.Tuple[Mapping, Frame]:
        """Map input frame to output using requested mapping file."""
        mapping = Mapping(self.config.mapping,
                          self.config,
                          itp_filename=self.config.itp)
        out_frame = mapping.apply(in_frame)
        out_frame.save(self.get_output_filepath("gro"), frame_number=0)

        if self.config.backmapper_resname and self.out_frame.n_frames > 1:
            try:
                self.train_backmapper(self.config.resname)

            except ImportError:
                logger.error("MDPlus must be installed to perform backmapping")

        return mapping, out_frame

    def measure_bonds(self) -> None:
        """Measure bonds at the end of a run."""
        self.bondset.apply(self.out_frame)

        if self.mapping is not None and self.out_frame.n_frames > 1:
            # Only perform Boltzmann Inversion if we have a mapping and a trajectory.
            # Otherwise we get infinite force constants.
            logger.info("Starting Boltzmann Inversion")
            self.bondset.boltzmann_invert()
            logger.info("Finished Boltzmann Inversion")

            if self.config.output_forcefield:
                logger.info("Writing GROMACS forcefield directory")
                out_dir = pathlib.Path(self.config.out_dir)
                forcefield = ForceField(self.config.output_name,
                                        dir_path=out_dir)
                forcefield.write(self.config.output_name, self.mapping,
                                 self.bondset)
                logger.info("Finished writing GROMACS forcefield directory")

            else:
                self.bondset.write_itp(self.get_output_filepath("itp"),
                                       mapping=self.mapping)

        if self.config.dump_measurements:
            logger.info("Writing bond measurements to file")
            self.bondset.dump_values(self.config.dump_n_values,
                                     self.config.out_dir)
            logger.info("Finished writing bond measurements to file")

    def train_backmapper(self, resname: str):
        from mdplus.multiscale import GLIMPS

        sel = f"resname {resname}"

        aa_subset_traj = self.in_frame._trajectory.atom_slice(
            self.in_frame._trajectory.topology.select(sel))
        cg_subset_traj = self.out_frame._trajectory.atom_slice(
            self.out_frame._trajectory.topology.select(sel))

        logger.info("Training backmapper")
        # Param x_valence is approximate number of bonds per CG bead
        # Values greater than 2 fail for small molecules e.g. sugar test case
        backmapper = GLIMPS(x_valence=2)
        backmapper.fit(cg_subset_traj.xyz, aa_subset_traj.xyz)
        logger.info("Finished training backmapper")

        backmapper.save(self.get_output_filepath("backmapper.pkl"))