Esempio n. 1
0
def main(filename, ExpNMR, nfiles):

    print "=========================="
    print "PyDP4 script,\nintegrating Tinker/MacroModel,"
    print "Gaussian/NWChem/Jaguar and DP4\nv0.7"
    print "\nCopyright (c) 2015-2018 Kristaps Ermanis, Jonathan M. Goodman"
    print "Distributed under MIT license"
    print "==========================\n\n"

    if nfiles < settings.NTaut or nfiles % settings.NTaut != 0:
        print "Invalid number of tautomers/input files - number of input files\
        must be a multiple of number of tautomers"

        quit()

    SetTMSConstants()

    #Check the number of input files, generate some if necessary
    if nfiles == 1:
        import InchiGen
        if len(settings.SelectedStereocentres) > 0:
            numDS, inpfiles = InchiGen.GenSelectDiastereomers(
                filename, settings.SelectedStereocentres)
        else:
            numDS, inpfiles = InchiGen.GenDiastereomers(filename)
        if settings.GenTaut:
            newinpfiles = []
            for ds in inpfiles:
                print "Generating tautomers for " + ds
                settings.NTaut, files = InchiGen.GenTautomers(ds)
                newinpfiles.extend(files)
            inpfiles = list(newinpfiles)
        if settings.GenProt:
            newinpfiles = []
            for ds in inpfiles:
                print "Generating protomers for " + ds
                settings.NTaut, files = InchiGen.GenProtomers(
                    ds, settings.BasicAtoms)
                newinpfiles.extend(files)
            inpfiles = list(newinpfiles)
    else:
        inpfiles = filename
        if settings.GenTaut:
            numDS = nfiles
            import InchiGen
            newinpfiles = []
            for ds in inpfiles:
                print "Generating tautomers for " + ds
                settings.NTaut, files = InchiGen.GenTautomers(ds)
                newinpfiles.extend(files)
            inpfiles = list(newinpfiles)
        else:
            numDS = int(nfiles / settings.NTaut)
            if numDS == 1:
                import InchiGen
                for f in filename:
                    tdiastereomers = []
                    numDS, tinpfiles = InchiGen.GenDiastereomers(f)
                    tdiastereomers.append(tinpfiles)
                tinpfiles = zip(*tdiastereomers)
                inpfiles = []
                for ds in tinpfiles:
                    inpfiles.extend(list(ds))

    print inpfiles

    #Check the existence of mm output files
    MMRun = False

    if settings.MMTinker:
        #Check if there already are Tinker output files with the right names
        tinkfiles = glob.glob('*.tout')
        mminpfiles = []
        for f in inpfiles:
            if f + '.tout' in tinkfiles and (f + 'rot.tout' in tinkfiles
                                             or settings.Rot5Cycle is False):
                if len(mminpfiles) == 0:
                    MMRun = True
            else:
                MMRun = False
                mminpfiles.append(f)
    else:
        #Check if there already are MacroModel output files with the right names
        mmfiles = glob.glob('*.log')
        mminpfiles = []
        for f in inpfiles:
            if f + '.log' in mmfiles and (f + 'rot.log' in mmfiles
                                          or settings.Rot5Cycle is False):
                if len(mminpfiles) == 0:
                    MMRun = True
            else:
                MMRun = False
                mminpfiles.append(f)

    if MMRun or settings.AssumeDone or settings.UseExistingInputs:
        print 'Conformation search has already been run for these inputs.\
                \nSkipping...'

        if settings.GenOnly:
            print "Input files generated, quitting..."
            quit()
    else:
        if settings.MMTinker:
            print 'Some Tinker files missing.'
            print '\nSeting up Tinker files...'
            Tinker.SetupTinker(len(inpfiles), settings, *mminpfiles)
            if settings.GenOnly:
                print "Input files generated, quitting..."
                quit()
            print '\nRunning Tinker...'
            Tinker.RunTinker(len(inpfiles), settings, *mminpfiles)
        else:
            print 'Some Macromodel files missing.'
            print '\nSetting up Macromodel files...'
            MacroModel.SetupMacromodel(len(inpfiles), settings, *mminpfiles)
            if settings.GenOnly:
                print "Input files generated, quitting..."
                quit()
            print '\nRunning Macromodel...'
            MacroModel.RunMacromodel(len(inpfiles), settings, *mminpfiles)

    if settings.OnlyConfS:
        print "Conformational search completed, quitting as instructed."
        quit()

    if (not settings.AssumeDone) and (not settings.UseExistingInputs):
        if settings.ConfPrune and not settings.Cluster:
            if settings.DFT == 'z' or settings.DFT == 'g' or settings.DFT == 'd':
                adjRMSDcutoff = Gaussian.AdaptiveRMSD(inpfiles[0], settings)
            elif settings.DFT == 'n' or settings.DFT == 'w' or settings.DFT == 'm':
                adjRMSDcutoff = NWChem.AdaptiveRMSD(inpfiles[0], settings)
            elif settings.DFT == 'j':
                adjRMSDcutoff = Jaguar.AdaptiveRMSD(inpfiles[0], settings)

            print 'RMSD cutoff adjusted to ' + str(adjRMSDcutoff)
        else:
            adjRMSDcutoff = settings.InitialRMSDcutoff

        #Run DFT setup script for every diastereomer
        print '\nRunning DFT setup...'
        i = 1
        for ds in inpfiles:
            if settings.DFT == 'z' or settings.DFT == 'g' or settings.DFT == 'd':
                print "\nGaussian setup for file " + ds + " (" + str(i) +\
                    " of " +  str(len(inpfiles)) + ")"
                if settings.Cluster == False:
                    Gaussian.SetupGaussian(ds, ds + 'ginp', 3, settings,
                                           adjRMSDcutoff)
                else:
                    Gaussian.SetupGaussianCluster(ds, ds + 'ginp', 3, settings)
            elif settings.DFT == 'n' or settings.DFT == 'w' or settings.DFT == 'm':
                print "\nNWChem setup for file " + ds +\
                    " (" + str(i) + " of " + str(len(inpfiles)) + ")"
                NWChem.SetupNWChem(ds, ds + 'nwinp', 3, settings,
                                   adjRMSDcutoff)
            elif settings.DFT == 'j':
                print "\nJaguar setup for file " + ds +\
                    " (" + str(i) + " of " + str(len(inpfiles)) + ")"
                Jaguar.SetupJaguar(ds, ds + 'jinp', 3, settings, adjRMSDcutoff)

            i += 1
        QRun = False
    elif settings.AssumeDone:
        QRun = True
    else:
        QRun = False

    if settings.DFT == 'z' or settings.DFT == 'g' or settings.DFT == 'd':
        Files2Run = Gaussian.GetFiles2Run(inpfiles, settings)
    elif settings.DFT == 'n' or settings.DFT == 'w' or settings.DFT == 'm':
        Files2Run = NWChem.GetFiles2Run(inpfiles, settings)
    elif settings.DFT == 'j':
        Files2Run = Jaguar.GetFiles2Run(inpfiles, settings)

    print Files2Run

    if len(Files2Run) == 0:

        if (settings.DFT == 'z' or settings.DFT == 'g' or settings.DFT == 'd') and\
            (settings.DFTOpt or settings.PM6Opt or settings.HFOpt or settings.M06Opt)\
     and not settings.AssumeDone:
            print "Checking if all geometries have converged"
            Ngeoms, Nunconverged, unconverged = Gaussian.CheckConvergence(
                inpfiles)
            if Nunconverged > 0:
                print "WARNING: Not all geometries have achieved convergence!"
                print ','.join([x[:-8] for x in unconverged])
                print "Number of geometries: " + str(Ngeoms)
                print "Unconverged: " + str(Nunconverged)
                Gaussian.ResubGeOpt(unconverged, settings)
                Files2Run = Gaussian.GetFiles2Run(inpfiles, settings)
                QRun = False
            else:
                QRun = True
        else:
            QRun = True

        #QRun = True

    if len(Files2Run) > settings.HardConfLimit:
        print "Hard conformation count limit exceeded, DFT calculations aborted."
        quit()

    if QRun:
        print 'DFT has already been run for these inputs. Skipping...'
    else:
        if settings.DFT == 'g':
            print '\nRunning Gaussian locally...'
            Gaussian.RunLocally(Files2Run, settings)

        elif settings.DFT == 'z':
            print '\nRunning Gaussian on Ziggy...'

            #Run Gaussian jobs on Ziggy cluster in folder named after date
            #and time in the short 1processor job queue
            #and wait until the last file is completed
            MaxCon = settings.MaxConcurrentJobs
            if settings.DFTOpt or settings.PM6Opt or settings.HFOpt or settings.M06Opt:
                for i in range(len(Files2Run)):
                    Files2Run[i] = Files2Run[i][:-5] + '.com'
            if len(Files2Run) < MaxCon:
                Gaussian.RunOnZiggy(0, settings.queue, Files2Run, settings)
            else:
                print "The DFT calculations will be done in " +\
                    str(math.ceil(len(Files2Run)/MaxCon)) + " batches"
                i = 0
                while (i + 1) * MaxCon < len(Files2Run):
                    print "Starting batch nr " + str(i + 1)
                    Gaussian.RunOnZiggy(
                        str(i + 1), settings.queue,
                        Files2Run[(i * MaxCon):((i + 1) * MaxCon)], settings)
                    i += 1
                print "Starting batch nr " + str(i + 1)
                Gaussian.RunOnZiggy(str(i + 1), settings.queue,
                                    Files2Run[(i * MaxCon):], settings)
        elif settings.DFT == 'd':
            print '\nRunning Gaussian on Darwin...'

            #Run Gaussian jobs on Darwin cluster in folder named after date
            #and title and wait until the last file is completed
            MaxCon = settings.MaxConcurrentJobsDarwin

            if settings.DFTOpt or settings.PM6Opt or settings.HFOpt or settings.M06Opt:
                for i in range(len(Files2Run)):
                    Files2Run[i] = Files2Run[i][:-5] + '.com'

            if len(Files2Run) < MaxCon:
                Gaussian.RunOnDarwin(0, Files2Run, settings)
            else:
                print "The DFT calculations will be done in " +\
                    str(math.ceil(len(Files2Run)/MaxCon)) + " batches"
                i = 0
                while (i + 1) * MaxCon < len(Files2Run):
                    print "Starting batch nr " + str(i + 1)
                    Gaussian.RunOnDarwin(
                        str(i + 1), Files2Run[(i * MaxCon):((i + 1) * MaxCon)],
                        settings)
                    i += 1
                print "Starting batch nr " + str(i + 1)
                Gaussian.RunOnDarwin(str(i + 1), Files2Run[(i * MaxCon):],
                                     settings)

        elif settings.DFT == 'n':
            print '\nRunning NWChem locally...'
            NWChem.RunNWChem(Files2Run, settings)

        elif settings.DFT == 'w':
            print '\nRunning NWChem on Ziggy...'

            #Run NWChem jobs on Ziggy cluster in folder named after date
            #and time in the short 1 processor job queue
            #and wait until the last file is completed
            now = datetime.datetime.now()
            MaxCon = settings.MaxConcurrentJobs
            if len(Files2Run) < MaxCon:
                NWChem.RunOnZiggy(now.strftime('%d%b%H%M'), settings.queue,
                                  Files2Run, settings)
            else:
                print "The DFT calculations will be done in " +\
                    str(math.ceil(len(Files2Run)/MaxCon)) + " batches"
                i = 0
                while (i + 1) * MaxCon < len(Files2Run):
                    print "Starting batch nr " + str(i + 1)
                    NWChem.RunOnZiggy(
                        now.strftime('%d%b%H%M') + str(i + 1), settings.queue,
                        Files2Run[(i * MaxCon):((i + 1) * MaxCon)], settings)
                    i += 1
                print "Starting batch nr " + str(i + 1)
                NWChem.RunOnZiggy(
                    now.strftime('%d%b%H%M') + str(i + 1), settings.queue,
                    Files2Run[(i * MaxCon):], settings)

        elif settings.DFT == 'm':
            print '\nRunning NWChem on Medivir cluster...'

            #Run NWChem jobs on Medivir cluster
            MaxCon = settings.MaxConcurrentJobs
            if len(Files2Run) < MaxCon:
                NWChem.RunOnMedivir(Files2Run, settings)
            else:
                print "The DFT calculations will be done in " +\
                    str(math.ceil(len(Files2Run)/MaxCon)) + " batches"
                i = 0
                while (i + 1) * MaxCon < len(Files2Run):
                    print "Starting batch nr " + str(i + 1)
                    NWChem.RunOnMedivir(
                        Files2Run[(i * MaxCon):((i + 1) * MaxCon)], settings)
                    i += 1
                print "Starting batch nr " + str(i + 1)
                NWChem.RunOnMedivir(Files2Run[(i * MaxCon):], settings)

        elif settings.DFT == 'j':
            print '\nRunning Jaguar locally...'
            Jaguar.RunJaguar(Files2Run, settings)

    if numDS < 2:
        print "DP4 requires at least 2 candidate structures!"
    else:
        allargs = []
        for i in range(numDS):
            allargs.append(settings.NTaut)
            allargs.extend(inpfiles[i * settings.NTaut:(i + 1) *
                                    settings.NTaut])
        allargs.append(ExpNMR)
        DP4outp = NMRAnalysis.main(numDS, settings, *allargs)
        print '\nWriting the DP4 output to DP4outp'
        DP4_ofile = open(allargs[-1] + '.dp4', 'w')
        DP4_ofile.write(DP4outp)
        DP4_ofile.close()
        print 'DP4 process completed successfully.'
Esempio n. 2
0
def main(settings):
    print("Current working directory: " + os.getcwd())
    print("Initial input files: " + str(settings.InputFiles))
    print("NMR file: " + str(settings.NMRsource))
    print("Workflow: " + str(settings.Workflow))

    # Read in any text inputs and add these to the input file list

    import StructureInput

    if settings.Smiles:
        settings.InputFiles.extend(
            StructureInput.GenerateSDFFromTxt(settings.Smiles, 'Smiles'))

    if settings.Smarts:
        settings.InputFiles.extend(
            StructureInput.GenerateSDFFromTxt(settings.Smarts, 'Smarts'))

    if settings.InChIs:
        settings.InputFiles.extend(
            StructureInput.GenerateSDFFromTxt(settings.InChIs, 'InChI'))

    # Clean up input files if c in workflow - this generates a new set of 3d coordinates as a starting point

    if 'c' in settings.Workflow and len(settings.InputFiles) > 0:
        import StructureInput

        # if requested generate 3d coordinates to define any stereochemistry

        settings.InputFiles = StructureInput.CleanUp(settings.InputFiles)

    # if no structure inputs have been found at this point quit

    if len(settings.InputFiles) == 0:
        print(
            "\nNo input files were found please use -h for help with input options quitting..."
        )

        quit()

    # if g in workflow check number of stereocentres for each input and generate and diastereomers

    if ('g' in settings.Workflow):

        import InchiGen
        print("\nGenerating diastereomers...")

        FinalInputFiles = []

        nStereo = [
            StructureInput.NumberofStereoCentres(InpFile)
            for InpFile in settings.InputFiles
        ]

        if len(settings.InputFiles) == 1:

            FinalInputFiles.extend(
                InchiGen.GenDiastereomers(settings.InputFiles[0], nStereo[0],
                                          settings.SelectedStereocentres))

        else:

            for InpFile, nStereoCentres in zip(settings.InputFiles, nStereo):
                FinalInputFiles.extend(
                    InchiGen.GenDiastereomers(InpFile, nStereoCentres, []))

        settings.InputFiles = list(FinalInputFiles)

    print("Generated input files: " + str(settings.InputFiles) + '\n')

    # Create isomer data structures
    Isomers = [Isomer(f.split('.sdf')[0]) for f in settings.InputFiles]

    print("Assuming all computations are done? ... ", settings.AssumeDone)
    print("Using preexisting DFT data? ... ", settings.UseExistingInputs)

    # Run conformational search, if requested
    if ('m' in settings.Workflow) and not (settings.AssumeDone
                                           or settings.UseExistingInputs):

        print("Performing conformational search using ", end="")

        if settings.MM == 't':
            print("Tinker")
            print('\nSetting up Tinker files...')
            TinkerInputs = Tinker.SetupTinker(settings)

            print('\nRunning Tinker...')
            TinkerOutputs = Tinker.RunTinker(TinkerInputs, settings)

            Isomers = Tinker.ReadConformers(TinkerOutputs, Isomers, settings)

        elif settings.MM == 'm':
            print("MacroModel")
            print('\nSetting up MacroModel files...')
            MacroModelInputs = MacroModel.SetupMacroModel(settings)
            print("MacroModel inputs: " + str(MacroModelInputs))
            print('Running MacroModel...')
            MacroModelOutputs = MacroModel.RunMacroModel(
                MacroModelInputs, settings)
            print('\nReading conformers...')
            Isomers = MacroModel.ReadConformers(MacroModelOutputs, Isomers,
                                                settings)
            print('Energy window: ' + str(settings.MaxCutoffEnergy) +
                  ' kJ/mol')
            for iso in Isomers:
                print(iso.InputFile + ": " + str(len(iso.Conformers)) +
                      ' conformers read within energy window')
    else:
        print('No conformational search was requested. Skipping...')
        settings.ConfPrune = False

    # Prune conformations, if requested.
    # For each isomer, the conformers list is replaced with a smaller list of conformers
    if (settings.ConfPrune) and not (settings.AssumeDone
                                     or settings.UseExistingInputs):
        print('\nPruning conformers...')
        Isomers = ConfPrune.RMSDPrune(Isomers, settings)
        for iso in Isomers:
            print(iso.InputFile + ": " + str(len(iso.Conformers)) +
                  ' conformers after pruning with ' + str(iso.RMSDCutoff) +
                  'A RMSD cutoff')

    if ('n' in settings.Workflow) or ('o' in settings.Workflow) \
            or ('e' in settings.Workflow) or settings.AssumeDone:
        DFT = ImportDFT(settings.DFT)
    else:
        print('\nNo DFT calculations were requested. Skipping...')

    if not (settings.AssumeDone):

        # Run DFT optimizations, if requested
        if ('o' in settings.Workflow):

            now = datetime.datetime.now()
            settings.StartTime = now.strftime('%d%b%H%M')

            print('\nSetting up geometry optimization calculations...')
            Isomers = DFT.SetupOptCalcs(Isomers, settings)
            print('\nRunning geometry optimization calculations...')
            Isomers = DFT.RunOptCalcs(Isomers, settings)

            print('\nReading DFT optimized geometries...')

            Isomers = DFT.ReadGeometries(Isomers, settings)

            # Add convergence check here before continuing with calcs!
            if (DFT.Converged(Isomers) == False) and (settings.AssumeConverged
                                                      == False):
                print('Some of the conformers did not converge, quitting...')
                quit()

        # Run DFT single-point energy calculations, if requested
        if ('e' in settings.Workflow):

            now = datetime.datetime.now()
            settings.StartTime = now.strftime('%d%b%H%M')

            print('\nSetting up energy calculations...')
            Isomers = DFT.SetupECalcs(Isomers, settings)
            print('\nRunning energy calculations...')
            Isomers = DFT.RunECalcs(Isomers, settings)
            print('\nReading data from the output files...')
            Isomers = DFT.ReadEnergies(Isomers, settings)
            print("Energies: ")
            for iso in Isomers:
                print(iso.InputFile + ": " + str(iso.DFTEnergies))

        # Run DFT NMR calculations, if requested
        if ('n' in settings.Workflow):

            now = datetime.datetime.now()
            settings.StartTime = now.strftime('%d%b%H%M')

            print('\nSetting up NMR calculations...')
            Isomers = DFT.SetupNMRCalcs(Isomers, settings)
            print('\nRunning NMR calculations...')
            Isomers = DFT.RunNMRCalcs(Isomers, settings)
            print('\nReading data from the output files...')
            Isomers = DFT.ReadShieldings(Isomers)
            print("Shieldings: ")
            for iso in Isomers:
                print(iso.InputFile + ": ")
                for conf in iso.ConformerShieldings:
                    print(str(conf))

            Isomers = DFT.ReadEnergies(Isomers, settings)
            print("Energies: ")
            for iso in Isomers:
                print(iso.InputFile + ": " + str(iso.DFTEnergies))

    else:
        # Read DFT optimized geometries, if requested
        if ('o' in settings.Workflow):
            Isomers = DFT.GetPrerunOptCalcs(Isomers)
        if ('e' in settings.Workflow):
            Isomers = DFT.GetPrerunECalcs(Isomers)
        if ('n' in settings.Workflow):
            Isomers = DFT.GetPrerunNMRCalcs(Isomers)

        Isomers = DFT.ReadGeometries(Isomers, settings)

        # Read DFT NMR data, if requested
        if ('n' in settings.Workflow):
            Isomers = DFT.ReadShieldings(Isomers)
            Isomers = DFT.ReadEnergies(Isomers, settings)

    if not (NMR.NMRDataValid(Isomers)) or ('n' not in settings.Workflow):
        print('\nNo NMR data calculated, quitting...')
        quit()

    if ('s' in settings.Workflow) or ('a' in settings.Workflow):

        print('\nSetting TMS computational NMR shielding constant references')
        settings.TMS_SC_C13, settings.TMS_SC_H1 = NMR.GetTMSConstants(settings)

        print('\nConverting DFT data to NMR shifts...')
        Isomers = NMR.CalcBoltzmannWeightedShieldings(Isomers)
        Isomers = NMR.CalcNMRShifts(Isomers, settings)

        print('\nReading experimental NMR data...')
        NMRData = NMR.NMRData(settings)
        """
        print("Conformation data:")
        NMR.PrintConformationData(Isomers)
        """

        if NMRData.Type == 'desc':

            print('Experimental NMR description found and read.')

            # performs a pairwise assignment
            Isomers = NMR.PairwiseAssignment(Isomers, NMRData)

            print('Cshifts: ' + str(NMRData.Cshifts))
            print('Hshifts: ' + str(NMRData.Hshifts))

            print('Equivalents: ' + str(NMRData.Equivalents))
            print('Omits: ' + str(NMRData.Omits))

        elif NMRData.Type == "fid":

            for f in settings.NMRsource:

                if f.name == "Proton" or f.name == "proton":

                    from Proton_assignment import AssignProton
                    from Proton_plotting import PlotProton

                    print('\nAssigning proton spectrum...')
                    Isomers = AssignProton(NMRData, Isomers, settings)

                    if settings.GUIRunning == False:
                        print('\nPlotting proton spectrum...')
                        PlotProton(NMRData, Isomers, settings)

                elif f.name == "Carbon" or f.name == "carbon":

                    from Carbon_assignment import AssignCarbon
                    from Carbon_plotting import PlotCarbon

                    print('\nAssigning carbon spectrum...')
                    Isomers = AssignCarbon(NMRData, Isomers, settings)

                    if settings.GUIRunning == False:
                        print('\nPlotting carbon spectrum...')
                        PlotCarbon(NMRData, Isomers, settings)

        elif NMRData.Type == "jcamp":

            for f in settings.NMRsource:

                if f.name == "Proton.dx" or f.name == "proton.dx":

                    from Proton_assignment import AssignProton
                    from Proton_plotting import PlotProton

                    print('\nAssigning proton spectrum...')
                    Isomers = AssignProton(NMRData, Isomers, settings)

                    if settings.GUIRunning == False:
                        print('\nPlotting proton spectrum...')
                        PlotProton(NMRData, Isomers, settings)

                elif f.name == "Carbon.dx" or f.name == "carbon.dx":

                    from Carbon_assignment import AssignCarbon
                    from Carbon_plotting import PlotCarbon

                    print('\nAssigning carbon spectrum...')
                    Isomers = AssignCarbon(NMRData, Isomers, settings)

                    if settings.GUIRunning == False:
                        print('\nPlotting carbon spectrum...')
                        PlotCarbon(NMRData, Isomers, settings)

            print('Raw FID NMR datafound and read.')

        # print('\nProcessing experimental NMR data...')

        # NMRdata = NMR.ProcessNMRData(Isomers, settings.NMRsource, settings)

    if 's' in settings.Workflow:

        print('\nCalculating DP4 probabilities...')
        DP4data = DP4.DP4data()
        DP4data = DP4.ProcessIsomers(DP4data, Isomers)
        DP4data = DP4.InternalScaling(DP4data)
        DP4data = DP4.CalcProbs(DP4data, settings)
        DP4data = DP4.CalcDP4(DP4data)
        DP4data = DP4.MakeOutput(DP4data, Isomers, settings)

        # print(DP4.FormatData(DP4data))

    else:
        print('\nNo DP4 analysis requested.')
        NMRData = []
        DP4data = []

    print('\nPyDP4 process completed successfully.')

    return NMRData, Isomers, settings, DP4data
Esempio n. 3
0
def main(settings):

    print("==========================")
    print("PyDP4 script,\nintegrating Tinker/MacroModel,")
    print("Gaussian/NWChem and DP4\nv1.0")
    print("\nCopyright (c) 2015-2019 Kristaps Ermanis, Alexander Howarth, Jonathan M. Goodman")
    print("Distributed under MIT license")
    print("==========================\n\n")

    print("Initial input files: " + str(settings.InputFiles))
    print("NMR file: " + str(settings.NMRsource))
    print("Workflow: " + str(settings.Workflow))

    # Check the number of input files, generate some if necessary
    if ('g' in settings.Workflow) and len(settings.InputFiles) == 1:
        import InchiGen
        print("\nGenerating diastereomers...")
        settings.InputFiles = InchiGen.GenDiastereomers(settings.InputFiles[0], settings.SelectedStereocentres)

    print("Generated input files: " + str(settings.InputFiles) + '\n')

    # Create isomer data structures
    Isomers = [Isomer(f.split('.sdf')[0]) for f in settings.InputFiles]

    # Run conformational search, if requested

    print("assume",settings.AssumeDone )

    print("Use exist",settings.UseExistingInputs)

    if ('m' in settings.Workflow) and not (settings.AssumeDone or settings.UseExistingInputs):

        print("in")

        print(settings.MM)

        if settings.MM == 't':
            print('\nSetting up Tinker files...')
            TinkerInputs = Tinker.SetupTinker(settings)

            print('\nRunning Tinker...')
            TinkerOutputs = Tinker.RunTinker(TinkerInputs, settings)

            Isomers = Tinker.ReadConformers(TinkerOutputs, Isomers, settings)

        elif settings.MM == 'm':
            print('\nSetting up MacroModel files...')
            MacroModelInputs = MacroModel.SetupMacroModel(settings)
            print("MacroModel inputs: " + str(MacroModelInputs))
            print('Running MacroModel...')
            MacroModelOutputs = MacroModel.RunMacroModel(MacroModelInputs, settings)
            print('\nReading conformers...')
            Isomers = MacroModel.ReadConformers(MacroModelOutputs, Isomers, settings)
            print('Energy window: ' + str(settings.MaxCutoffEnergy) + ' kJ/mol')
            for iso in Isomers:
                print(iso.InputFile + ": "+ str(len(iso.Conformers)) + ' conformers read within energy window' )
    else:
        print('No conformational search was requested. Skipping...')
        settings.ConfPrune = False

    # Prune conformations, if requested.
    # For each isomer, the conformers list is replaced with a smaller list of conformers
    if (settings.ConfPrune) and not(settings.AssumeDone or settings.UseExistingInputs):
        print('\nPruning conformers...')
        Isomers = ConfPrune.RMSDPrune(Isomers, settings)
        for iso in Isomers:
            print(iso.InputFile + ": " + str(len(iso.Conformers)) + ' conformers after pruning with ' +
                  str(iso.RMSDCutoff) + 'A RMSD cutoff')

    if ('n' in settings.Workflow) or ('o' in settings.Workflow) \
            or ('e' in settings.Workflow) or settings.AssumeDone:
        DFT = ImportDFT(settings.DFT)
    else:
        print('\nNo DFT calculations were requested. Skipping...')

    if not(settings.AssumeDone):

        # Run DFT optimizations, if requested
        if ('o' in settings.Workflow):

            now = datetime.datetime.now()
            settings.StartTime = now.strftime('%d%b%H%M')

            print('\nSetting up geometry optimization calculations...')
            Isomers = DFT.SetupOptCalcs(Isomers, settings)
            print('\nRunning geometry optimization calculations...')
            Isomers = DFT.RunOptCalcs(Isomers, settings)

            print('\nReading DFT optimized geometries...')

            Isomers = DFT.ReadGeometries(Isomers,settings)

            #Add convergence check here before continuing with calcs!
            if (DFT.Converged(Isomers) == False) and (settings.AssumeConverged == False):
                print('Some of the conformers did not converge, quitting...')
                quit()

        # Run DFT single-point energy calculations, if requested
        if ('e' in settings.Workflow):

            now = datetime.datetime.now()
            settings.StartTime = now.strftime('%d%b%H%M')

            print('\nSetting up energy calculations...')
            Isomers = DFT.SetupECalcs(Isomers, settings)
            print('\nRunning energy calculations...')
            Isomers = DFT.RunECalcs(Isomers, settings)
            print('\nReading data from the output files...')
            Isomers = DFT.ReadEnergies(Isomers, settings)
            print("Energies: ")
            for iso in Isomers:
                print(iso.InputFile + ": " + str(iso.DFTEnergies))

        # Run DFT NMR calculations, if requested
        if ('n' in settings.Workflow):

            now = datetime.datetime.now()
            settings.StartTime = now.strftime('%d%b%H%M')

            print('\nSetting up NMR calculations...')
            Isomers = DFT.SetupNMRCalcs(Isomers, settings)
            print('\nRunning NMR calculations...')
            Isomers = DFT.RunNMRCalcs(Isomers, settings)
            print('\nReading data from the output files...')
            Isomers = DFT.ReadShieldings(Isomers)
            print("Shieldings: ")
            for iso in Isomers:
                print(iso.InputFile + ": ")
                for conf in iso.ConformerShieldings:
                    print(str(conf))

            Isomers = DFT.ReadEnergies(Isomers, settings)
            print("Energies: ")
            for iso in Isomers:
                print(iso.InputFile + ": " + str(iso.DFTEnergies))

    else:
        # Read DFT optimized geometries, if requested
        if ('o' in settings.Workflow):
            Isomers = DFT.GetPrerunOptCalcs(Isomers)
        if ('e' in settings.Workflow):
            Isomers = DFT.GetPrerunECalcs(Isomers)
        if ('n' in settings.Workflow):
            Isomers = DFT.GetPrerunNMRCalcs(Isomers)

        Isomers = DFT.ReadGeometries(Isomers, settings)

        # Read DFT NMR data, if requested
        if ('n' in settings.Workflow):
            Isomers = DFT.ReadShieldings(Isomers)
            Isomers = DFT.ReadEnergies(Isomers, settings)

    if not(NMR.NMRDataValid(Isomers)) or ('n' not in settings.Workflow):

        print('\nNo NMR data calculated, quitting...')
        quit()

    if ('s' in settings.Workflow) or ('a' in settings.Workflow):

        print('\nSetting TMS computational NMR shielding constant references')
        settings.TMS_SC_C13, settings.TMS_SC_H1 = NMR.GetTMSConstants(settings)

        print('\nConverting DFT data to NMR shifts...')
        Isomers = NMR.CalcBoltzmannWeightedShieldings(Isomers)
        Isomers = NMR.CalcNMRShifts(Isomers, settings)

        print('\nReading experimental NMR data...')
        NMRData = NMR.NMRData(settings)

        """
        print("Conformation data:")
        NMR.PrintConformationData(Isomers)
        """

        if NMRData.Type == 'desc':

            print('Experimental NMR description found and read.')

            # performs a pairwise assignment

            Isomers = NMR.PairwiseAssignment(Isomers,NMRData)

            print('Cshifts: ' + str(NMRData.Cshifts))
            print('Hshifts: ' + str(NMRData.Hshifts))

            print('Equivalents: ' + str(NMRData.Equivalents))
            print('Omits: ' + str(NMRData.Omits))

        elif NMRData.Type == "fid":

            if os.path.exists(str(settings.NMRsource) + "/Proton"):

                from Proton_assignment import AssignProton

                from Proton_plotting import PlotProton

                print('\nAssigning proton spectrum...')
                Isomers = AssignProton(NMRData,Isomers,settings)

                print('\nPlotting proton spectrum...')
                PlotProton(NMRData, Isomers, settings)

            if os.path.exists(str(settings.NMRsource) + "/Carbon"):

                from Carbon_assignment import AssignCarbon

                from Carbon_plotting import PlotCarbon

                print('\nAssigning carbon spectrum...')
                Isomers = AssignCarbon(NMRData,Isomers,settings)

                print('\nPlotting carbon spectrum...')
                PlotCarbon(NMRData, Isomers, settings)

        elif NMRData.Type == "jcamp":

            if os.path.exists(str(settings.NMRsource) + "/Proton.dx"):
                from Proton_assignment import AssignProton

                from Proton_plotting import PlotProton

                print('\nAssigning proton spectrum...')
                Isomers = AssignProton(NMRData, Isomers, settings)

                print('\nPlotting proton spectrum...')
                PlotProton(NMRData, Isomers, settings)

            if os.path.exists(str(settings.NMRsource) + "/Carbon.dx"):
                from Carbon_assignment import AssignCarbon

                from Carbon_plotting import PlotCarbon

                print('\nAssigning carbon spectrum...')
                Isomers = AssignCarbon(NMRData, Isomers, settings)

                print('\nPlotting carbon spectrum...')
                PlotCarbon(NMRData, Isomers, settings)

            print('Raw FID NMR datafound and read.')

        #print('\nProcessing experimental NMR data...')

        #NMRdata = NMR.ProcessNMRData(Isomers, settings.NMRsource, settings)

    if 's' in settings.Workflow:

        print('\nCalculating DP4 probabilities...')

        DP4data = DP4.DP4data()

        DP4data = DP4.ProcessIsomers(DP4data,Isomers)

        DP4data = DP4.InternalScaling(DP4data)

        DP4data = DP4.CalcProbs(DP4data,settings)

        DP4data = DP4.CalcDP4(DP4data)

        DP4data = DP4.MakeOutput(DP4data,Isomers,settings)

        #print(DP4.FormatData(DP4data))

    else:
        print('\nNo DP4 analysis requested.')
        NMRData = []
        DP4data = []

    print('\nPyDP4 process completed successfully.')

    return NMRData, Isomers, settings, DP4data