コード例 #1
0
def remove_ghost_particles(last_phase_xml, output_file_name, sigma=1.0):
    # Remove all the ghost particles from the morphology for the final output
    final_morphology = hf.load_morphology_xml(last_phase_xml)
    # Determine the atomIDs for each particle beginning with the letters 'X'
    # or 'R' - these are the ghost particles
    atom_IDs_to_remove = []
    for atom_ID, atom_type in enumerate(final_morphology["type"]):
        if (atom_type[0] == "X") or (atom_type[0] == "R"):
            # This is a ghost particle
            atom_IDs_to_remove.append(atom_ID)
    # Reverse sorting trick so that the location indices don't change as we
    # delete particles from the system
    atom_IDs_to_remove.sort(reverse=True)
    # Now delete the atoms from the morphology
    atom_attribs = ["position", "image", "type", "mass", "diameter", "body", "charge"]
    for atom_ID in atom_IDs_to_remove:
        for key in atom_attribs:
            final_morphology[key].pop(atom_ID)
    final_morphology["natoms"] -= len(atom_IDs_to_remove)
    # Delete any constraints associated with those atoms that have been removed
    atom_constraints = ["bond", "angle", "dihedral", "improper"]
    for key in atom_constraints:
        constraints_to_remove = []
        for constraint_no, constraint in enumerate(final_morphology[key]):
            for atom_ID in constraint[1:]:
                if (atom_ID in atom_IDs_to_remove) and (
                    constraint_no not in constraints_to_remove
                ):
                    constraints_to_remove.append(constraint_no)
        constraints_to_remove.sort(reverse=True)
        for constraint_no in constraints_to_remove:
            final_morphology[key].pop(constraint_no)
    # Output the final morphology
    hf.write_morphology_xml(final_morphology, output_file_name, sigma)
コード例 #2
0
def scale_morphology(initial_morphology, parameter_dict, s_scale, e_scale):
    # If sScale != 1.0, then scale the morphology and rewrite the phase0 xml
    print("Scaling morphology by sigma = {:f}...".format(1 / s_scale))
    if s_scale != 1.0:
        hf.scale(initial_morphology, s_scale)
    hf.write_morphology_xml(
        initial_morphology,
        os.path.join(
            parameter_dict["output_morph_dir"],
            os.path.splitext(parameter_dict["morphology"])[0],
            "morphology",
            "".join(["phase0_", parameter_dict["morphology"]]),
        ),
    )
コード例 #3
0
def main():
    list_of_files = sys.argv[1:]
    if len(list_of_files) < 1:
        print("No files requested to convert!")
        exit()
    for file_name in list_of_files:
        print("Fixing the images for {:s}...".format(file_name))
        morphology = hf.load_morphology_xml(file_name)
        morphology = zero_out_images(morphology)
        bond_dict = get_bond_dict(morphology)
        morphology = check_bonds(morphology, bond_dict)
        file_directory, split_file_name = os.path.split(file_name)
        hf.write_morphology_xml(
            morphology,
            os.path.join(file_directory, "".join(["image_fix_", split_file_name])),
        )
コード例 #4
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-m",
        "--molecule_source",
        required=False,
        help="""Specify the source of the add_hydrogens dictionary and sigma value.
        This can be in the form of a python script which returns a function of the
        dictionary and sigma or the name of the molecule.""",
    )
    args, input_files = parser.parse_known_args()
    hydrogens_to_add, sigma_val = find_information(args)
    for input_file in input_files:
        # This dictionary has keys of the atom type, and values where the first
        # element is the number of bonds required for us to add a hydrogen to
        # the atom and the second element of the value defines how many
        # hydrogens to add to said atom.
        print(
            "THIS FUNCTION IS SET UP TO USE A DICTIONARY TO DEFINE HOW MANY HYDROGENS "
            " TO ADD TO BONDS OF A SPECIFIC TYPE WITH A CERTAIN NUMBER OF BONDS"
        )
        print(hydrogens_to_add)
        print(
            "IF THE ABOVE DICTIONARY DOESN'T LOOK RIGHT, PLEASE TERMINATE NOW AND "
            " IGNORE ANY OUTPUTS UNTIL THE DICTIONARY HAS BEEN RECTIFIED"
        )
        print("Additionally, we're using a sigma value of", sigma_val)
        morphology_dict = hf.load_morphology_xml(input_file, sigma=sigma_val)
        # We MUST fix the images first, otherwise the hydrogens will be put in
        # incorrectly.
        morphology_dict = fi.zero_out_images(morphology_dict)
        bond_dict = fi.get_bond_dict(morphology_dict)
        morphology_dict = fi.check_bonds(morphology_dict, bond_dict)
        # Now we can safely obtain the unwrapped positions
        morphology_dict = hf.add_unwrapped_positions(morphology_dict)
        hydrogen_positions = calculate_hydrogen_positions(
            morphology_dict, hydrogens_to_add
        )
        morphology_dict = add_hydrogens_to_morph(
            morphology_dict, hydrogen_positions
        )
        morphology_dict = hf.add_wrapped_positions(morphology_dict)
        hf.write_morphology_xml(
            morphology_dict,
            input_file.replace(".xml", "_AA.xml"),
            check_wrapped_posns=False,
        )
コード例 #5
0
def main(
    AA_morphology_dict,
    CG_morphology_dict,
    CG_to_AAID_master,
    parameter_dict,
    chromophore_list,
):
    # Get the random seed now for all the child processes
    if parameter_dict["random_seed_override"] is not None:
        np.random.seed(parameter_dict["random_seed_override"])
    # Main execution function for run_HOOMD that performs the required MD phases
    # First, scale the input morphology based on the pair potentials such that
    # the distances and energies are normalised to the strongest pair
    # interaction and the diameter of the largest atom (makes it easier on
    # HOOMDs calculations and ensures that T = 1.0 is an interesting temperature
    # threshold)
    current_files = os.listdir(
        os.path.join(
            parameter_dict["output_morph_dir"],
            os.path.splitext(parameter_dict["morphology"])[0],
            "morphology",
        )
    )
    # sScale, eScale = obtainScaleFactors(parameterDict)
    print("Under the hood eScaling and sScaling has been disabled.")
    s_scale = 1.0
    e_scale = 1.0
    # Only scale the morphology if it hasn't been already
    if (parameter_dict["overwrite_current_data"] is False) and (
        "".join(["phase0_", parameter_dict["morphology"]]) in current_files
    ):
        pass
    else:
        scale_morphology(AA_morphology_dict, parameter_dict, s_scale, e_scale)
    # Reset logfile
    try:
        os.remove(
            os.path.join(
                parameter_dict["output_morph_dir"],
                os.path.splitext(parameter_dict["morphology"])[0],
                "morphology",
                "".join(
                    [
                        "energies_",
                        os.path.splitext(parameter_dict["morphology"])[0],
                        ".log",
                    ]
                ),
            )
        )
    except OSError:
        pass
    # Perform each molecular dynamics phase as specified in the parXX.py
    for phase_no in range(parameter_dict["number_of_phases"]):
        input_file = "phase{0:d}_{1:s}".format(phase_no, parameter_dict["morphology"])
        output_file = "phase{0:d}_{1:s}".format(
            phase_no + 1, parameter_dict["morphology"]
        )
        if output_file in current_files:
            if parameter_dict["overwrite_current_data"] is False:
                print(output_file, "already exists. Skipping...")
                continue
        md_phase(
            AA_morphology_dict,
            CG_morphology_dict,
            CG_to_AAID_master,
            parameter_dict,
            phase_no,
            os.path.join(
                parameter_dict["output_morph_dir"],
                os.path.splitext(parameter_dict["morphology"])[0],
                "morphology",
                input_file,
            ),
            os.path.join(
                parameter_dict["output_morph_dir"],
                os.path.splitext(parameter_dict["morphology"])[0],
                "morphology",
                output_file,
            ),
            s_scale,
            e_scale,
        ).optimise_structure()
    final_xml_name = os.path.join(
        parameter_dict["output_morph_dir"],
        os.path.splitext(parameter_dict["morphology"])[0],
        "morphology",
        "".join(["final_", parameter_dict["morphology"]]),
    )
    if "".join(["final_", parameter_dict["morphology"]]) not in current_files:
        # Now all phases are complete, remove the ghost particles from the
        # system
        print("Removing ghost particles to create final output...")
        remove_ghost_particles(
            os.path.join(
                parameter_dict["output_morph_dir"],
                os.path.splitext(parameter_dict["morphology"])[0],
                "morphology",
                output_file,
            ),
            final_xml_name,
            sigma=s_scale,
        )
    # Finally, update the pickle file with the most recent and realistic
    # AAMorphologyDict so that we can load it again further along the pipeline
    AA_morphology_dict = hf.load_morphology_xml(final_xml_name)
    # Now that we've obtained the final fine-grained morphology, we need to fix
    # the images to prevent issues with obtaining the chromophores and running
    # them through the ZINDO/S calculations later...
    AA_morphology_dict = hf.fix_images(AA_morphology_dict)
    # ...add in the unwrapped positions...
    AA_morphology_dict = hf.add_unwrapped_positions(AA_morphology_dict)
    # ...rewrite the final morphology xml...
    hf.write_morphology_xml(AA_morphology_dict, final_xml_name)
    # ...and write the pickle file.
    hf.write_pickle(
        (
            AA_morphology_dict,
            CG_morphology_dict,
            CG_to_AAID_master,
            parameter_dict,
            chromophore_list,
        ),
        os.path.join(
            parameter_dict["output_morph_dir"],
            os.path.splitext(parameter_dict["morphology"])[0],
            "code",
            "".join([os.path.splitext(parameter_dict["morphology"])[0], ".pickle"]),
        ),
    )
    return (
        AA_morphology_dict,
        CG_morphology_dict,
        CG_to_AAID_master,
        parameter_dict,
        chromophore_list,
    )
コード例 #6
0
ファイル: fine_grainer.py プロジェクト: erjank/morphct
    def analyse_morphology(self):
        # Split the morphology into individual molecules
        print("Finding molecules...")
        molecule_IDs, molecule_lengths = self.split_molecules()
        rolling_AA_index = 0
        CG_morphology_dict = {}
        AA_morphology_dict = {}
        # Set the AAMorphology and CGMorphology system sizes to the same as the
        # input file system size
        for box_dimension in ["lx", "ly", "lz", "xy", "xz", "yz"]:
            CG_morphology_dict[box_dimension] = self.CG_dictionary[
                box_dimension
            ]
            AA_morphology_dict[box_dimension] = self.CG_dictionary[
                box_dimension
            ]
        CG_to_AAID_master = []  # This is a list of dictionaries. Elements in
        # the list correspond to molecules (useful for splitting out individual
        # molecules for the xyz conversion) within the element, the dictionary
        # key is the CG site, the value is a list containing the CG type (e.g.
        # 'thio') as the first element and then another list of all the AAIDs
        # corresponding to that CG site as the second element.

        # If no CG_to_template info is present in the parameter dict, then we
        # can assume that the morphology is already fine-grained and so we can
        # just return the important information and skip this module
        if len(self.CG_to_template_dirs) == 0:
            print(
                "No CG to AA data found in parameter file - the morphology is already"
                " fine-grained! Skipping this module..."
            )
            # Write the xml file and create the pickle
            print("Writing xml file...")
            AA_file_name = os.path.join(
                self.output_morph_dir,
                self.morphology_name,
                "morphology",
                "".join([self.morphology_name, ".xml"]),
            )
            atomistic_morphology = hf.add_unwrapped_positions(
                self.CG_dictionary
            )
            # Now write the morphology xml
            hf.write_morphology_xml(atomistic_morphology, AA_file_name)
            # And finally write the pickle with the CGDictionary as None (to
            # indicate to MorphCT that no fine-graining has taken place), but
            # the other parameters assigned as required.
            pickle_location = os.path.join(
                self.output_morph_dir,
                self.morphology_name,
                "code",
                "".join([self.morphology_name, ".pickle"]),
            )
            hf.write_pickle(
                (
                    atomistic_morphology,
                    None,
                    None,
                    self.parameter_dict,
                    self.chromophore_list,
                ),
                pickle_location,
            )
            return (
                atomistic_morphology,
                None,
                None,
                self.parameter_dict,
                self.chromophore_list,
            )

        # Create a ghost particle dictionary to be added at the end of the
        # morphology. This way, we don't mess up the order of atoms later on
        # when trying to split back up into individual molecules and monomers.
        # The ghost dictionary contains all of the type T and type X particles
        # that will anchor the thiophene rings to the CG COM positions.
        ghost_dictionary = {
            "position": [],
            "image": [],
            "unwrapped_position": [],
            "mass": [],
            "diameter": [],
            "type": [],
            "body": [],
            "bond": [],
            "angle": [],
            "dihedral": [],
            "improper": [],
            "charge": [],
        }

        # Need to check for atom-type conflicts and suitably increment the
        # type indices if more than one molecule type is being fine-grained
        new_type_mappings = self.get_new_type_mappings(
            self.CG_to_template_dirs, self.CG_to_template_force_fields
        )
        # Need to update the self.parameterDict, which will be rewritten at the
        # end of this module
        self.parameter_dict["new_type_mappings"] = new_type_mappings
        molecule = []
        unique_mappings = []
        CG_sites, mappings = hf.parallel_sort(
            list(new_type_mappings.keys()), list(new_type_mappings.values())
        )
        for index, mapping in enumerate(mappings):
            if mapping not in unique_mappings:
                molecule.append([])
                unique_mappings.append(mapping)
            molecule[-1].append(CG_sites[index])
        printExplanation = True
        for index, CG_sites in enumerate(molecule):
            printMol = True
            initial_atoms, final_atoms = hf.parallel_sort(
                list(unique_mappings[index].keys()),
                list(unique_mappings[index].values()),
            )
            for index, initial_atom in enumerate(initial_atoms):
                if initial_atom == final_atoms[index]:
                    continue
                if printExplanation is True:
                    print(
                        "The following atom types have been remapped due to conflicting"
                        " typenames in the atomistic templates:"
                    )
                    printExplanation = False
                if printMol is True:
                    print(
                        "Atom types belonging the molecule described by",
                        "".join([repr(CG_sites), ":"]),
                    )
                    printMol = False
                print(initialAtom, "--->", finalAtoms[index])
        print("Adding", len(molecule_IDs), "molecules to the system...")
        for molecule_number in range(len(molecule_IDs)):
            print("Adding molecule number", molecule_number, "\r", end=" ")
            if sys.stdout is not None:
                sys.stdout.flush()
            # Obtain the AA dictionary for each molecule using the
            # fine-graining procedure
            AA_molecule_dict, C_gto_AAIDs, ghost_dictionary = atomistic(
                molecule_number,
                molecule_IDs[molecule_number],
                self.CG_dictionary,
                molecule_lengths,
                rolling_AA_index,
                ghost_dictionary,
                self.parameter_dict,
            ).return_data()
            CG_to_AAID_master.append(C_gto_AAIDs)
            # Update the morphology dictionaries with this new molecule
            for key in list(self.CG_dictionary.keys()):
                if key not in [
                    "lx",
                    "ly",
                    "lz",
                    "xy",
                    "xz",
                    "yz",
                    "time_step",
                    "dimensions",
                ]:
                    if key not in list(AA_morphology_dict.keys()):
                        AA_morphology_dict[key] = AA_molecule_dict[key]
                    else:
                        AA_morphology_dict[key] += AA_molecule_dict[key]
            rolling_AA_index += len(AA_molecule_dict["type"])
        # Now add the ghost dictionary to the end of the morphology file
        # total_number_of_atoms should be == rolling_AA_index, but don't want
        # to take any chances.
        total_number_of_atoms = len(AA_morphology_dict["type"])
        # Add in the wrapped positions of the ghosts. Need to know sim dims for
        # this
        for key in ["lx", "ly", "lz", "xy", "xz", "yz"]:
            ghost_dictionary[key] = AA_morphology_dict[key]
        ghost_dictionary = hf.add_wrapped_positions(ghost_dictionary)
        for key in ["lx", "ly", "lz", "xy", "xz", "yz"]:
            ghost_dictionary.pop(key)
        # The real atoms that the ghost particles are bonded to are already
        # correct and no longer need to be changed.
        # However, the ghost particles themselves will have the wrong indices
        # if we were to add them to the system directly.
        # Therefore, increment all of the ghost bond indices that begin with a
        # * (ghost particle) by the total number of atoms already in the
        # system.
        for bond_no, bond in enumerate(ghost_dictionary["bond"]):
            if str(bond[1])[0] == "*":
                ghost_dictionary["bond"][bond_no][1] = (
                    int(bond[1][1:]) + total_number_of_atoms
                )
            if str(bond[2])[0] == "*":
                ghost_dictionary["bond"][bond_no][2] = (
                    int(bond[2][1:]) + total_number_of_atoms
                )
        # Now append all ghosts to morphology
        for key in list(ghost_dictionary.keys()):
            AA_morphology_dict[key] += ghost_dictionary[key]
        # Finally, update the number of atoms
        AA_morphology_dict["natoms"] += len(ghost_dictionary["type"])
        print("\n")
        # Now write the xml file and create the pickle
        print("Writing xml file...")
        AA_file_name = os.path.join(
            self.output_morph_dir,
            self.morphology_name,
            "morphology",
            "".join([self.morphology_name, ".xml"]),
        )
        # Replace the `positions' with the `unwrapped_positions' ready for
        # writing
        AA_morphology_dict = hf.replace_wrapped_positions(AA_morphology_dict)
        # Update the additional_constraints that we put in by checking all of
        # the constraints have the correct names before writing
        AA_morphology_dict = hf.check_constraint_names(AA_morphology_dict)
        # Now write the morphology xml
        hf.write_morphology_xml(AA_morphology_dict, AA_file_name)
        # And finally write the pickle
        pickle_location = os.path.join(
            self.output_morph_dir,
            self.morphology_name,
            "code",
            "".join([self.morphology_name, ".pickle"]),
        )
        hf.write_pickle(
            (
                AA_morphology_dict,
                self.CG_dictionary,
                CG_to_AAID_master,
                self.parameter_dict,
                self.chromophore_list,
            ),
            pickle_location,
        )
        return (
            AA_morphology_dict,
            self.CG_dictionary,
            CG_to_AAID_master,
            self.parameter_dict,
            self.chromophore_list,
        )