def from_xml(cls, xmls_or_etrees): """Create a gmso.Forcefield object from XML File(s) This class method creates a ForceFiled object from the reference XML file. This method takes in a single or collection of XML files with information about gmso.AtomTypes, gmso.BondTypes, gmso.AngleTypes and gmso.DihedralTypes to create the ForceField object. Parameters ---------- xmls_or_etrees : Union[str, Iterable[str], etree._ElementTree, Iterable[etree._ElementTree]] The forcefield XML locations or XML Element Trees Returns -------- forcefield : gmso.ForceField A gmso.Forcefield object with a collection of Potential objects created using the information in the XML file """ if not isinstance(xmls_or_etrees, typing.Iterable) or isinstance(xmls_or_etrees, str): xmls_or_etrees = [xmls_or_etrees] should_parse_xml = False if not (all(map(lambda x: isinstance(x, str), xmls_or_etrees)) or all(map(lambda x: isinstance(x, etree._ElementTree), xmls_or_etrees))): raise TypeError('Please provide an iterable of strings ' 'as locations of the XML files ' 'or equivalent element Trees') if all(map(lambda x: isinstance(x, str), xmls_or_etrees)): should_parse_xml = True versions = [] names = [] ff_atomtypes_list = [] ff_bondtypes_list = [] ff_angletypes_list = [] ff_dihedraltypes_list = [] atom_types_dict = ChainMap() bond_types_dict = {} angle_types_dict = {} dihedral_types_dict = {} improper_types_dict = {} potential_groups = {} for loc_or_etree in set(xmls_or_etrees): validate(loc_or_etree) ff_tree = loc_or_etree if should_parse_xml: ff_tree = etree.parse(loc_or_etree) ff_el = ff_tree.getroot() versions.append(ff_el.attrib['version']) names.append(ff_el.attrib['name']) ff_meta_tree = ff_tree.find('FFMetaData') if ff_meta_tree is not None: ff_meta_map = parse_ff_metadata(ff_meta_tree) ff_atomtypes_list.extend(ff_tree.findall('AtomTypes')) ff_bondtypes_list.extend(ff_tree.findall('BondTypes')) ff_angletypes_list.extend(ff_tree.findall('AngleTypes')) ff_dihedraltypes_list.extend(ff_tree.findall('DihedralTypes')) # Consolidate AtomTypes for atom_types in ff_atomtypes_list: this_atom_types_group = parse_ff_atomtypes(atom_types, ff_meta_map) this_atom_group_name = atom_types.attrib.get('name', None) if this_atom_group_name: potential_groups[this_atom_group_name] = this_atom_types_group atom_types_dict.update(this_atom_types_group) # Consolidate BondTypes for bond_types in ff_bondtypes_list: this_bond_types_group = parse_ff_connection_types( bond_types, atom_types_dict, child_tag='BondType' ) this_bond_types_group_name = bond_types.attrib.get('name', None) if this_bond_types_group_name: potential_groups[this_bond_types_group_name] = this_bond_types_group bond_types_dict.update(this_bond_types_group) # Consolidate AngleTypes for angle_types in ff_angletypes_list: this_angle_types_group = parse_ff_connection_types( angle_types, atom_types_dict, child_tag='AngleType' ) this_angle_types_group_name = angle_types.attrib.get('name', None) if this_angle_types_group_name: potential_groups[this_angle_types_group_name] = this_angle_types_group angle_types_dict.update(this_angle_types_group) # Consolidate DihedralTypes for dihedral_types in ff_dihedraltypes_list: this_dihedral_types_group = parse_ff_connection_types( dihedral_types, atom_types_dict, child_tag='DihedralType' ) this_improper_types_group = parse_ff_connection_types( dihedral_types, atom_types_dict, child_tag='ImproperType' ) this_group_name = dihedral_types.attrib.get('name', None) dihedral_types_dict.update(this_dihedral_types_group) improper_types_dict.update(this_improper_types_group) if this_group_name: this_dihedral_types_group.update(this_improper_types_group) potential_groups[this_group_name] = this_dihedral_types_group ff = cls() ff.name = names[0] ff.version = versions[0] ff.scaling_factors = ff_meta_map['scaling_factors'] ff.units = ff_meta_map['Units'] ff.atom_types = atom_types_dict.maps[0] ff.bond_types = bond_types_dict ff.angle_types = angle_types_dict ff.dihedral_types = dihedral_types_dict ff.improper_types = improper_types_dict ff.potential_groups = potential_groups return ff
def from_xml(cls, xml_locs): """Create a gmso.Forcefield object from XML File(s) This class method creates a ForceFiled object from the reference XML file. This method takes in a single or collection of XML files with information about gmso.AtomTypes, gmso.BondTypes, gmso.AngleTypes and gmso.DihedralTypes to create the ForceField object. Parameters ---------- xml_locs : str or iterable of str string or iterable of strings containing the forcefield XML locations Returns -------- forcefield : gmso.ForceField A gmso.Forcefield object with a collection of Potential objects created using the information in the XML file """ if not hasattr(xml_locs, '__iter__'): xml_locs = [].append(xml_locs) if isinstance(xml_locs, str): xml_locs = [xml_locs] versions = [] names = [] ff_atomtypes_list = [] ff_bondtypes_list = [] ff_angletypes_list = [] ff_dihedraltypes_list = [] atom_types_dict = ChainMap() bond_types_dict = {} angle_types_dict = {} dihedral_types_dict = {} improper_types_dict = {} potential_groups = {} for loc in xml_locs: validate(loc) ff_tree = etree.parse(loc) ff_el = ff_tree.getroot() versions.append(ff_el.attrib['version']) names.append(ff_el.attrib['name']) ff_meta_tree = ff_tree.find('FFMetaData') if ff_meta_tree is not None: ff_meta_map = parse_ff_metadata(ff_meta_tree) ff_atomtypes_list.extend(ff_tree.findall('AtomTypes')) ff_bondtypes_list.extend(ff_tree.findall('BondTypes')) ff_angletypes_list.extend(ff_tree.findall('AngleTypes')) ff_dihedraltypes_list.extend(ff_tree.findall('DihedralTypes')) # Consolidate AtomTypes for atom_types in ff_atomtypes_list: this_atom_types_group = parse_ff_atomtypes(atom_types, ff_meta_map) this_atom_group_name = atom_types.attrib.get('name', None) if this_atom_group_name: potential_groups[this_atom_group_name] = this_atom_types_group atom_types_dict.update(this_atom_types_group) # Consolidate BondTypes for bond_types in ff_bondtypes_list: this_bond_types_group = parse_ff_connection_types( bond_types, atom_types_dict, child_tag='BondType') this_bond_types_group_name = bond_types.attrib.get('name', None) if this_bond_types_group_name: potential_groups[ this_bond_types_group_name] = this_bond_types_group bond_types_dict.update(this_bond_types_group) # Consolidate AngleTypes for angle_types in ff_angletypes_list: this_angle_types_group = parse_ff_connection_types( angle_types, atom_types_dict, child_tag='AngleType') this_angle_types_group_name = angle_types.attrib.get('name', None) if this_angle_types_group_name: potential_groups[ this_angle_types_group_name] = this_angle_types_group angle_types_dict.update(this_angle_types_group) # Consolidate DihedralTypes for dihedral_types in ff_dihedraltypes_list: this_dihedral_types_group = parse_ff_connection_types( dihedral_types, atom_types_dict, child_tag='DihedralType') this_improper_types_group = parse_ff_connection_types( dihedral_types, atom_types_dict, child_tag='ImproperType') this_group_name = dihedral_types.attrib.get('name', None) dihedral_types_dict.update(this_dihedral_types_group) improper_types_dict.update(this_improper_types_group) if this_group_name: this_dihedral_types_group.update(this_improper_types_group) potential_groups[this_group_name] = this_dihedral_types_group ff = cls() ff.name = names[0] ff.version = versions[0] ff.scaling_factors = ff_meta_map['scaling_factors'] ff.units = ff_meta_map['Units'] ff.atom_types = atom_types_dict.maps[0] ff.bond_types = bond_types_dict ff.angle_types = angle_types_dict ff.dihedral_types = dihedral_types_dict ff.improper_types = improper_types_dict ff.potential_groups = potential_groups return ff
def from_xml(cls, xmls_or_etrees, strict=True, greedy=True): """Create a gmso.Forcefield object from XML File(s). This class method creates a ForceField object from the reference XML file. This method takes in a single or collection of XML files with information about gmso.AtomTypes, gmso.BondTypes, gmso.AngleTypes and gmso.DihedralTypes to create the ForceField object. Parameters ---------- xmls_or_etrees : Union[str, Iterable[str], etree._ElementTree, Iterable[etree._ElementTree]] The forcefield XML locations or XML Element Trees strict: bool, default=True If true, perform a strict validation of the forcefield XML file greedy: bool, default=True If True, when using strict mode, fail on the first error/mismatch Returns ------- forcefield : gmso.ForceField A gmso.Forcefield object with a collection of Potential objects created using the information in the XML file """ if not isinstance(xmls_or_etrees, Iterable) or isinstance( xmls_or_etrees, str ): xmls_or_etrees = [xmls_or_etrees] should_parse_xml = False if not ( all(map(lambda x: isinstance(x, str), xmls_or_etrees)) or all( map(lambda x: isinstance(x, etree._ElementTree), xmls_or_etrees) ) ): raise TypeError( "Please provide an iterable of strings " "as locations of the XML files " "or equivalent element Trees" ) if all(map(lambda x: isinstance(x, str), xmls_or_etrees)): should_parse_xml = True versions = [] names = [] ff_atomtypes_list = [] ff_bondtypes_list = [] ff_angletypes_list = [] ff_dihedraltypes_list = [] atom_types_dict = ChainMap() bond_types_dict = {} angle_types_dict = {} dihedral_types_dict = {} improper_types_dict = {} potential_groups = {} for loc_or_etree in set(xmls_or_etrees): validate(loc_or_etree, strict=strict, greedy=greedy) ff_tree = loc_or_etree if should_parse_xml: ff_tree = etree.parse(loc_or_etree) ff_el = ff_tree.getroot() versions.append(ff_el.attrib["version"]) names.append(ff_el.attrib["name"]) ff_meta_tree = ff_tree.find("FFMetaData") if ff_meta_tree is not None: ff_meta_map = parse_ff_metadata(ff_meta_tree) ff_atomtypes_list.extend(ff_tree.findall("AtomTypes")) ff_bondtypes_list.extend(ff_tree.findall("BondTypes")) ff_angletypes_list.extend(ff_tree.findall("AngleTypes")) ff_dihedraltypes_list.extend(ff_tree.findall("DihedralTypes")) # Consolidate AtomTypes for atom_types in ff_atomtypes_list: this_atom_types_group = parse_ff_atomtypes(atom_types, ff_meta_map) this_atom_group_name = atom_types.attrib.get("name", None) if this_atom_group_name: potential_groups[this_atom_group_name] = this_atom_types_group atom_types_dict.update(this_atom_types_group) # Consolidate BondTypes for bond_types in ff_bondtypes_list: this_bond_types_group = parse_ff_connection_types( bond_types, child_tag="BondType" ) this_bond_types_group_name = bond_types.attrib.get("name", None) if this_bond_types_group_name: potential_groups[ this_bond_types_group_name ] = this_bond_types_group bond_types_dict.update(this_bond_types_group) # Consolidate AngleTypes for angle_types in ff_angletypes_list: this_angle_types_group = parse_ff_connection_types( angle_types, child_tag="AngleType" ) this_angle_types_group_name = angle_types.attrib.get("name", None) if this_angle_types_group_name: potential_groups[ this_angle_types_group_name ] = this_angle_types_group angle_types_dict.update(this_angle_types_group) # Consolidate DihedralTypes for dihedral_types in ff_dihedraltypes_list: this_dihedral_types_group = parse_ff_connection_types( dihedral_types, child_tag="DihedralType" ) this_improper_types_group = parse_ff_connection_types( dihedral_types, child_tag="ImproperType" ) this_group_name = dihedral_types.attrib.get("name", None) dihedral_types_dict.update(this_dihedral_types_group) improper_types_dict.update(this_improper_types_group) if this_group_name: this_dihedral_types_group.update(this_improper_types_group) potential_groups[this_group_name] = this_dihedral_types_group ff = cls() ff.name = names[0] ff.version = versions[0] ff.scaling_factors = ff_meta_map["scaling_factors"] ff.units = ff_meta_map["Units"] ff.atom_types = atom_types_dict.maps[0] ff.bond_types = bond_types_dict ff.angle_types = angle_types_dict ff.dihedral_types = dihedral_types_dict ff.improper_types = improper_types_dict ff.potential_groups = potential_groups return ff