def __init__(self,
                 path: str,
                 multiconf: bool = True,
                 nr_mols: int = -1,
                 properties: list = None):
        """

        :param path:
        :param multiconf:
        :param nr_mols:
        :param properties: List of properties to be read from SDF file. Returns None if not found. Internally adds ' <'
        and '>' before and after the property names in order to comply with the toolkit.
        """
        self.r = Chem.FileSDFMoleculeReader(path)
        self.multiconf = multiconf
        self.nr_mols = nr_mols
        self.nr_samples = None
        self.properties = set([" <" + p + ">" for p in properties
                               ]) if properties is not None else None

        Chem.setMultiConfImportParameter(self.r, multiconf)
        if multiconf:
            Chem.setMultiConfInputProcessorParameter(
                self.r,
                Chem.DefaultMultiConfMoleculeInputProcessor(
                    False,
                    Chem.AtomPropertyFlag.TYPE | Chem.AtomPropertyFlag.ISOTOPE
                    | Chem.AtomPropertyFlag.FORMAL_CHARGE,
                    Chem.BondPropertyFlag.ORDER))
        self._gen = iter(self)
def process():
    if len(sys.argv) < 4:
        print(
            'Usage:',
            sys.argv[0],
            '[input torsion rules.xml] [structures.sdf] [output torsion histogram library.sdf]',
            file=sys.stderr)
        sys.exit(2)

    tor_lib = ConfGen.TorsionLibrary()

    try:
        tor_lib.load(Base.FileIOStream(sys.argv[1], 'r'))
    except:
        print('Error while loading input torsion rules:',
              sys.exc_info()[0],
              file=sys.stderr)
        sys.exit(2)

    tor_matcher = ConfGen.TorsionRuleMatcher(tor_lib)

    tor_matcher.findAllRuleMappings(True)
    tor_matcher.findUniqueMappingsOnly(True)
    tor_matcher.stopAtFirstMatchingRule(True)

    mol = Chem.BasicMolecule()
    mol_reader = Chem.FileSDFMoleculeReader(sys.argv[2])

    Chem.setMultiConfImportParameter(mol_reader, False)

    print('- Analyzing input structures...', file=sys.stderr)

    i = 1
    rule_to_angle_hists = {}
    coords = Math.Vector3DArray()

    while True:
        try:
            if not mol_reader.read(mol):
                break

        except IOError as e:
            print('Error while reading input molecule',
                  i,
                  ':',
                  e,
                  file=sys.stderr)
            i += 1
            continue

        if i % 500 == 0:
            print('   ... At input molecule', i, '...', file=sys.stderr)

        Chem.initSubstructureSearchTarget(mol, False)

        try:
            Chem.get3DCoordinates(mol, coords)

        except Base.ItemNotFound:
            print('Could not get 3D-coordinates for molecule',
                  i,
                  file=sys.stderr)
            i += 1
            continue

        for bond in mol.bonds:
            if Chem.getRingFlag(bond):
                continue

            if Chem.isHydrogenBond(bond):
                continue

            if Chem.getExplicitBondCount(
                    bond.getBegin()) <= 1 or Chem.getExplicitBondCount(
                        bond.getEnd()) <= 1:
                continue

            tor_matcher.findMatches(bond, mol, False)

            for match in tor_matcher:
                processMatch(i, match, mol, coords, rule_to_angle_hists)

        i += 1

    print('- Processing torsion angle histograms...', file=sys.stderr)

    processHistograms(tor_lib, rule_to_angle_hists)

    print('- Writing output torsion library...', file=sys.stderr)

    try:
        tor_lib.save(Base.FileIOStream(sys.argv[3], 'w+'))

    except:
        print('Error while writing torsion library:',
              sys.exc_info()[0],
              file=sys.stderr)
        sys.exit(2)

    print('DONE!', file=sys.stderr)