Ejemplo n.º 1
0
def save_muairss_batch(args, global_params):
    structures_path = args.structures

    all_files = glob.glob(os.path.join(structures_path, "*"))
    structure_files = [
        path for path in all_files if not os.path.splitext(path)[1] == '.yaml'
    ]

    global_params['out_folder'] = safe_create_folder(
        global_params['out_folder'])

    print("Beginning creation of {} structures".format(len(structure_files)))

    for path in structure_files:
        name = parse_structure_name(path)
        parameter_file = os.path.join(structures_path, "{}.yaml".format(name))
        if not os.path.isfile(parameter_file):
            parameter_file = None

        struct = io.read(path)
        params = dict(global_params)  # Copy
        params['name'] = name
        if parameter_file is not None:
            params = load_input_file(parameter_file,
                                     MuAirssSchema,
                                     merge=params)
        params['out_folder'] = params['name']

        print("Making {} ---------------------".format(name))
        save_muairss_collection(struct,
                                params,
                                batch_path=global_params['out_folder'])

    print("Done!")
Ejemplo n.º 2
0
def save_muairss_collection(struct, params, batch_path=""):
    """Generate input files for a single structure and configuration file"""

    dc = generate_muairss_collection(struct, params)
    # Just to keep track, add the parameters used to the collection
    dc.info["muairss_params"] = dict(params)

    # Output folder
    out_path = safe_create_folder(os.path.join(batch_path, params["out_folder"]))

    if not out_path:
        raise RuntimeError("Could not create folder {0}")

    io_formats = {
        "castep": ReadWriteCastep,
        "dftb+": ReadWriteDFTB,
        "uep": ReadWriteUEP,
    }

    calcs = [s.strip().lower() for s in params["calculator"].split(",")]
    if "all" in calcs:
        calcs = io_formats.keys()

    # Save LICENSE file for DFTB+ parameters
    if "dftb+" in calcs:
        from pymuonsuite.data.dftb_pars import get_license

        with open(os.path.join(out_path, "dftb.LICENSE"), "w") as f:
            f.write(get_license())

    for cname in calcs:
        rw = io_formats[cname](params, script=params.get("script_file"))
        calc_path = os.path.join(out_path, cname)
        dc.save_tree(
            calc_path,
            rw.write,
            name_root=params["name"],
            opt_args={"calc_type": "GEOM_OPT"},
            safety_check=2,
        )

    # Do we also save a collective structure?
    allf = params["allpos_filename"]
    if allf is not None:
        alls = struct.copy()
        csp = struct.get_chemical_symbols()
        for atoms in dc:
            # We rely on the fact the muon is always put at the end
            mu = atoms[-1]
            alls.append(mu)
            csp += [params["mu_symbol"]]

        alls.set_array("castep_custom_species", np.array(csp))
        with silence_stdio(True, True):
            io.write(allf, alls)
Ejemplo n.º 3
0
def save_muairss_collection(struct, params, batch_path=''):
    """Generate input files for a single structure and configuration file"""

    dc = generate_muairss_collection(struct, params)
    # Just to keep track, add the parameters used to the collection
    dc.info['muairss_params'] = dict(params)

    # Output folder
    out_path = os.path.join(batch_path, params['out_folder'])

    if not safe_create_folder(out_path):
        raise RuntimeError('Could not create folder {0}')

    # Now save in the appropriate format
    save_formats = {
        'castep': castep_write_input,
        'dftb+': dftb_write_input,
        'uep': uep_write_input
    }

    # Which calculators?
    calcs = [s.strip().lower() for s in params['calculator'].split(',')]
    if 'all' in calcs:
        calcs = save_formats.keys()

    # Make the actual calculators
    make_calcs = {
        'castep': create_muairss_castep_calculator,
        'dftb+': create_muairss_dftb_calculator,
        'uep': create_muairss_uep_calculator
    }

    calcs = {
        c: make_calcs[c](struct, params=params, calc=struct.calc)
        for c in calcs
    }

    # Save LICENSE file for DFTB+ parameters
    if 'dftb+' in calcs:
        from pymuonsuite.data.dftb_pars import get_license
        with open(os.path.join(out_path, 'dftb.LICENSE'), 'w') as f:
            f.write(get_license())

    for cname, calc in calcs.items():
        calc_path = os.path.join(out_path, cname)
        dc.save_tree(calc_path,
                     save_formats[cname],
                     name_root=params['name'],
                     opt_args={
                         'calc': calc,
                         'script': params['script_file']
                     },
                     safety_check=2)
Ejemplo n.º 4
0
def muairss_batch_io(args, global_params, save=False):
    structures_path = args.structures

    all_files = glob.glob(os.path.join(structures_path, "*"))
    structure_files = [
        path for path in all_files if not os.path.splitext(path)[1] == ".yaml"
    ]

    if save:
        global_params["out_folder"] = safe_create_folder(global_params["out_folder"])

    print(
        "Beginning {0} of {1} structures".format(
            "creation" if save else "loading", len(structure_files)
        )
    )

    bpath = global_params["out_folder"]

    loaded = {}

    for path in structure_files:
        name = parse_structure_name(path)
        parameter_file = os.path.join(structures_path, "{}.yaml".format(name))
        if not os.path.isfile(parameter_file):
            parameter_file = None
        with silence_stdio():
            struct = io.read(path)
        params = dict(global_params)  # Copy
        params["name"] = name
        if parameter_file is not None:
            params = load_input_file(parameter_file, MuAirssSchema, merge=params)
        params["out_folder"] = params["name"]

        if save:
            print("Making {} ---------------------".format(name))
            save_muairss_collection(struct, params, batch_path=bpath)
        else:
            print("Loading {} ---------------------".format(name))
            coll = load_muairss_collection(struct, params, batch_path=bpath)
            loaded[name] = {"struct": struct, "collection": coll}

    print("Done!")

    if not save:
        return loaded
Ejemplo n.º 5
0
def write_cluster_report(args, params, clusters):

    if params['clustering_method'] == 'hier':
        clustinfo = """
Clustering method: Hierarchical
    t = {t}
""".format(t=params['clustering_hier_t'])
    elif params['clustering_method'] == 'kmeans':
        clustinfo = """
Clustering method: k-Means
    k = {k}
""".format(k=params['clustering_kmeans_k'])

    with open(params['name'] + '_clusters.txt', 'w') as f:

        f.write("""
****************************
|                          |
|         MUAIRSS          |
|    Clustering report     |
|                          |
****************************

Name: {name}
Date: {date}
Structure file(s): {structs}
Parameter file: {param}
{clustinfo}

*******************

""".format(name=params['name'],
           date=datetime.now(),
           structs=args.structures,
           param=args.parameter_file,
           clustinfo=clustinfo))

        for name, cdata in clusters.items():

            f.write('Clusters for {0}:\n'.format(name))

            if params['clustering_save_min'] is not None or \
                    params['clustering_save_type'] is not None:

                if params['clustering_save_folder'] is not None:
                    clustering_save_path = safe_create_folder(
                        params['clustering_save_folder'])
                else:
                    clustering_save_path = safe_create_folder(
                        '{0}_clusters'.format(params['name']))
                if not clustering_save_path:
                    raise RuntimeError('Could not create folder {0}')

            for calc, clusts in cdata.items():

                # Computer readable
                fdat = open(
                    params['name'] +
                    '_{0}_{1}_clusters.dat'.format(name, calc), 'w')

                f.write('CALCULATOR: {0}\n'.format(calc))
                (cinds, cgroups), ccolls, gvecs = clusts

                f.write('\t{0} clusters found\n'.format(max(cinds)))

                min_energy_structs = []

                for i, g in enumerate(cgroups):

                    f.write('\n\n\t-----------\n\tCluster '
                            '{0}\n\t-----------\n'.format(i + 1))
                    f.write('\tStructures: {0}\n'.format(len(g)))
                    coll = ccolls[i + 1]
                    E = gvecs[g, 0]
                    Emin = np.amin(E)
                    Eavg = np.average(E)
                    Estd = np.std(E)

                    f.write('\n\tEnergy (eV):\n')
                    f.write('\tMinimum\t\tAverage\t\tStDev\n')
                    f.write('\t{0:.2f}\t\t{1:.2f}\t\t{2:.2f}\n'.format(
                        Emin, Eavg, Estd))

                    fdat.write('\t'.join(
                        map(str, [
                            i + 1,
                            len(g), Emin, Eavg, Estd, coll[np.argmin(
                                E)].structures[0].positions[-1][0],
                            coll[np.argmin(E)].structures[0].positions[-1][1],
                            coll[np.argmin(E)].structures[0].positions[-1][2]
                        ])) + '\n')

                    f.write('\n\tMinimum energy structure: {0}\n'.format(
                        coll[np.argmin(E)].structures[0].info['name']))

                    # Save minimum energy structure
                    if params['clustering_save_type'] == 'structures' or \
                            params['clustering_save_min']:
                        # For backwards-compatability with old pymuonsuite
                        # versions
                        if params['clustering_save_min']:
                            if params['clustering_save_format'] is None:
                                params['clustering_save_format'] = 'cif'

                        try:
                            calc_path = os.path.join(clustering_save_path,
                                                     calc)
                            if not os.path.exists(calc_path):
                                os.mkdir(calc_path)
                            fname = ('{0}_{1}_min_cluster_'
                                     '{2}.{3}'.format(
                                         params['name'], calc, i + 1,
                                         params['clustering_save_format']))
                            with silence_stdio():
                                io.write(os.path.join(calc_path, fname),
                                         coll[np.argmin(E)].structures[0])
                        except (io.formats.UnknownFileTypeError) as e:
                            print("ERROR: File format '{0}' is not "
                                  "recognised. Modify 'clustering_save_format'"
                                  " and try again.".format(e))
                            return
                        except ValueError as e:
                            print("ERROR: {0}. Modify 'clustering_save_format'"
                                  "and try again.".format(e))
                            return

                    min_energy_structs.append(coll[np.argmin(E)].structures[0])

                    f.write('\n\n\tStructure list:')

                    for j, s in enumerate(coll):
                        if j % 4 == 0:
                            f.write('\n\t')
                        f.write('{0}\t'.format(s.info['name']))

                fdat.close()

                if params['clustering_save_type'] == 'input':
                    calc_path = os.path.join(clustering_save_path, calc)

                    sname = "{0}_min_cluster".format(params['name'])

                    io_formats = {
                        'castep': ReadWriteCastep,
                        'dftb+': ReadWriteDFTB,
                    }
                    try:
                        write_method = io_formats[
                            params['clustering_save_format']](params).write
                    except KeyError as e:
                        print("ERROR: Calculator type {0} is not "
                              "recognised. Modify 'clustering_save_format'"
                              " to be one of: {1}".format(
                                  e, list(io_formats.keys())))
                        return

                    if params['clustering_save_format'] == 'dftb+':
                        from pymuonsuite.data.dftb_pars import get_license
                        with open(
                                os.path.join(clustering_save_path,
                                             'dftb.LICENSE'),
                                'w') as license_file:
                            license_file.write(get_license())

                    min_energy_structs = AtomsCollection(min_energy_structs)
                    # here we remove the structure's name so the original
                    # numbering of the structs is removed:
                    for i, a in enumerate(min_energy_structs):
                        min_energy_structs.structures[i].info.pop('name', None)

                    min_energy_structs.save_tree(
                        calc_path,
                        write_method,
                        name_root=sname,
                        opt_args={'calc_type': 'GEOM_OPT'},
                        safety_check=2)

                # Print distance matrix

                f.write('\n\n\t----------\n\n\tSimilarity (ranked):\n')

                centers = np.array(
                    [np.average(gvecs[g], axis=0) for g in cgroups])
                dmat = np.linalg.norm(centers[:, None] - centers[None, :],
                                      axis=-1)

                inds = np.triu_indices(len(cgroups), k=1)
                for i in np.argsort(dmat[inds]):
                    c1 = inds[0][i]
                    c2 = inds[1][i]
                    d = dmat[c1, c2]
                    f.write('\t{0} <--> {1} (distance = {2:.3f})\n'.format(
                        c1 + 1, c2 + 1, d))

            f.write('\n--------------------------\n\n')

        f.write('\n==========================\n\n')