示例#1
0
def diff_hulls(client, collections, **args):
    """ Helper function to diff hulls from cmd-line args.

    Parameters:
        client (MongoClient): connection to database
        collections (dict of Collection): dict of collections to query

    Keyword arguments:
        args: dict, command-line arguments to select hulls.

    """
    from matador.query import DBQuery
    from matador.hull import QueryConvexHull
    diff_args = args['compare']
    del args['compare']
    args['no_plot'] = True
    if args.get('verbosity') in [0, None] and not args.get('debug'):
        args['quiet'] = True

    diff_args = sorted(diff_args)
    args['time'] = diff_args[0]
    print('Calculating hull {} days ago...'.format(args['time']))
    query_old = DBQuery(client, collections, **args)
    hull_old = QueryConvexHull(query_old, **args)
    if len(diff_args) == 1 or isinstance(diff_args, str):
        args['time'] = '0'
    else:
        args['time'] = diff_args[1]
    if args['time'] == '0':
        print('... to compare with up-to-date hull.')
    else:
        print('... to compare with hull {} days ago.'.format(args['time']))
    query_new = DBQuery(client, collections, **args)
    hull_new = QueryConvexHull(query_new, **args)
    HullDiff(hull_old, hull_new, **args)
示例#2
0
def import_res():
    """ Import from res files, returning data to be checked. """
    # import from combined res/cell/param files
    os.chdir(REAL_PATH + "/data/res_files")

    sys.argv = ["matador", "import", "--force", "--db", DB_NAME]

    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]

    if DEBUG:
        sys.argv += ["--debug"]

    matador.cli.cli.main(no_quickstart=True)

    query_1 = DBQuery(db=DB_NAME,
                      config=CONFIG_FNAME,
                      details=True,
                      source=True)
    query_2 = DBQuery(db=DB_NAME,
                      composition="KSnP",
                      config=CONFIG_FNAME,
                      details=True,
                      source=True)

    files_to_delete = glob.glob("*spatula*")
    for f in files_to_delete:
        os.remove(f)

    os.chdir(OUTPUT_DIR)

    return query_1, query_2
示例#3
0
def pseudoternary_hull():
    """ Import some other res files ready to make a hull. """
    os.chdir(REAL_PATH + "/data/hull-LLZO")
    sys.argv = ["matador", "import", "--force", "--db", DB_NAME]

    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]

    if DEBUG:
        sys.argv += ["--debug"]

    matador.cli.cli.main(no_quickstart=True)

    query = DBQuery(
        db=DB_NAME,
        subcmd="hull",
        composition="La2O3:Li2O:ZrO2",
        config=CONFIG_FNAME,
        details=True,
        source=True,
        no_plot=True,
    )
    hull = QueryConvexHull(query=query)

    os.chdir(OUTPUT_DIR)

    return query, hull
示例#4
0
    def test_binary_from_fake_query(self):
        cursor, s = res2dict(REAL_PATH + "data/hull-KP-KSnP_pub/*.res")
        print()
        print(80 * "-")
        self.assertEqual(
            len(cursor), 295,
            "Error with test res files, please check installation...")
        hull = QueryConvexHull(cursor=cursor, elements=["KP"], no_plot=True)
        self.assertEqual(len(hull.cursor), 295)
        self.assertEqual(len(hull.hull_cursor), 7)

        fake_query = DBQuery.__new__(DBQuery)
        fake_query.cursor = hull.cursor
        for ind, doc in enumerate(fake_query.cursor):
            fake_query.cursor[ind]["_id"] = None
            fake_query.cursor[ind]["text_id"] = [doc["source"][0], "."]
            del fake_query.cursor[ind]["hull_distance"]
            del fake_query.cursor[ind]["concentration"]

        fake_query._non_elemental = False
        fake_query._create_hull = True
        fake_query.args = dict()
        fake_query.args["intersection"] = False
        fake_query.args["subcmd"] = "hull"
        fake_query.args["composition"] = ["KP"]
        hull = QueryConvexHull(query=fake_query,
                               chempots=[-791.456765, -219.58161025],
                               no_plot=True)
        # now need to include custom chempots in counts
        self.assertEqual(len(hull.cursor), 297)
        self.assertEqual(len(hull.hull_cursor), 9)
示例#5
0
    def test_pseudoternary_from_fake_query(self):
        cursor, s = res2dict(REAL_PATH + "data/hull-LLZO/*.res")
        print()
        print(80 * "-")
        self.assertEqual(
            len(cursor), 12,
            "Error with test res files, please check installation...")
        hull = QueryConvexHull(cursor=cursor,
                               elements=["La2O3", "ZrO2", "Li2O"],
                               no_plot=True)
        self.assertEqual(len(hull.cursor), 7)

        fake_query = DBQuery.__new__(DBQuery)
        fake_query.cursor = hull.cursor
        for ind, doc in enumerate(fake_query.cursor):
            fake_query.cursor[ind]["_id"] = None
            fake_query.cursor[ind]["text_id"] = [doc["source"][0], "."]
        fake_query._non_elemental = True
        fake_query._create_hull = True
        fake_query.args = dict()
        fake_query.args["intersection"] = True
        fake_query.args["subcmd"] = "hull"
        fake_query.args["composition"] = ["La2O3:ZrO2:Li2O"]
        hull = QueryConvexHull(
            query=fake_query,
            hull_cutoff=0.01,
            chempots=[26200.3194 / 40, -8715.94784 / 12, -3392.59361 / 12],
            no_plot=True,
        )
        self.assertEqual(len(hull.cursor), 10)
        self.assertEqual(len(hull.hull_cursor), 9)
示例#6
0
def changes():
    """ Test matador changes functionality by undoing the second
    change (i.e. the res import).
    """
    sys.argv = ["matador", "changes", "--db", DB_NAME, "-c", "2", "--undo"]

    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]

    matador.cli.cli.main(no_quickstart=True)

    query_1 = DBQuery(db=DB_NAME, config=CONFIG_FNAME)
    query_2 = DBQuery(db=DB_NAME, composition="KSnP", config=CONFIG_FNAME)
    changes_count = MONGO_CLIENT.crystals["__changelog_" +
                                          DB_NAME].count_documents({})

    return query_1, query_2, changes_count
示例#7
0
def id_query():
    """ Test a simple ID query, and that nothing is found... """
    sys.argv = ["matador", "query", "--db", DB_NAME, "-i", "testing testing"]

    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]

    matador.cli.cli.main(no_quickstart=True)

    query = DBQuery(db=DB_NAME, config=CONFIG_FNAME, id="testing testing")
    return query
示例#8
0
def import_castep(extra_flags=None):
    """ Import from castep files, returning data to be checked. """
    # import from CASTEP files only
    os.chdir(REAL_PATH + "/data/castep_files")
    sys.argv = ["matador", "import", "--force", "--db", DB_NAME]

    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]

    if DEBUG:
        sys.argv += ["--debug"]

    matador.cli.cli.main(no_quickstart=True)

    query = DBQuery(db=DB_NAME, config=CONFIG_FNAME, details=True, source=True)

    files_to_delete = glob.glob("*spatula*")
    for f in files_to_delete:
        os.remove(f)
    os.chdir(OUTPUT_DIR)

    return query
示例#9
0
    def __init__(self, *args, **kwargs):
        """ Initialise the query with command line arguments and return
        results.

        """
        # read args
        self.kwargs = kwargs
        self.args = vars(args[0])
        self.args['no_quickstart'] = self.kwargs.get('no_quickstart')
        self.argstr = kwargs.get('argstr')

        file_exts = ['cell', 'res', 'pdb', 'markdown', 'latex', 'param', 'xsf']
        self.export = any([self.args.get(ext) for ext in file_exts])

        self.subcommand = self.args.pop("subcmd")

        if self.subcommand != 'import':
            self.settings = load_custom_settings(
                config_fname=self.args.get('config'),
                debug=self.args.get('debug'),
                no_quickstart=self.args.get('no_quickstart'))
            result = make_connection_to_collection(
                self.args.get('db'),
                check_collection=(self.subcommand != "stats"),
                mongo_settings=self.settings)
            self.client, self.db, self.collections = result

        if self.subcommand == 'stats':
            self.stats()

        try:
            if self.subcommand == 'import':
                from matador.db import Spatula
                self.importer = Spatula(self.args)

            if self.subcommand == 'query':
                self.query = DBQuery(self.client, self.collections,
                                     **self.args)
                self.cursor = self.query.cursor

            if self.subcommand == 'swaps':
                from matador.swaps import AtomicSwapper
                self.query = DBQuery(self.client, self.collections,
                                     **self.args)
                if self.args.get('hull_cutoff') is not None:
                    self.hull = QueryConvexHull(query=self.query, **self.args)
                    self.swapper = AtomicSwapper(self.hull.hull_cursor,
                                                 **self.args)
                else:
                    self.swapper = AtomicSwapper(self.query.cursor,
                                                 **self.args)
                self.cursor = self.swapper.cursor

            if self.subcommand == 'refine':
                from matador.db import Refiner
                self.query = DBQuery(self.client, self.collections,
                                     **self.args)
                if self.args.get('hull_cutoff') is not None:
                    self.hull = QueryConvexHull(self.query, **self.args)
                    self.refiner = Refiner(self.hull.cursor, self.query.repo,
                                           **self.args)
                else:
                    self.refiner = Refiner(self.query.cursor, self.query.repo,
                                           **self.args)

                self.cursor = self.refiner.cursor

            if self.subcommand == 'hull' or self.subcommand == 'voltage':
                self.hull = QueryConvexHull(**self.args,
                                            voltage=self.subcommand ==
                                            'voltage',
                                            client=self.client,
                                            collections=self.collections)
                self.cursor = self.hull.hull_cursor

            if self.subcommand == 'changes':
                from matador.db import DatabaseChanges
                if len(self.collections) != 1:
                    raise SystemExit(
                        'Cannot view changes of more than one collection at once.'
                    )
                if self.args.get('undo'):
                    action = 'undo'
                else:
                    action = 'view'
                changeset = self.args.get('changeset')
                if changeset is None:
                    changeset = 0
                DatabaseChanges([key for key in self.collections][0],
                                changeset_ind=changeset,
                                action=action,
                                mongo_settings=self.settings,
                                override=kwargs.get('no_quickstart'))

            if self.subcommand == 'hulldiff':
                from matador.hull.hull_diff import diff_hulls
                if self.args.get('compare') is None:
                    raise SystemExit(
                        'Please specify which hulls to query with --compare.')
                diff_hulls(self.client, self.collections, **self.args)

            if self.export and self.cursor:
                from matador.export import query2files
                if self.args.get('write_n') is not None:
                    self.cursor = [
                        doc for doc in self.cursor if len(doc['stoichiometry'])
                        == self.args.get('write_n')
                    ]
                if not self.cursor:
                    print_failure('No structures left to export.')
                query2files(self.cursor,
                            **self.args,
                            argstr=self.argstr,
                            subcmd=self.subcommand,
                            hash_dupe=True)

            if self.args.get('view'):
                from matador.utils.viz_utils import viz
                if self.args.get('top') is None:
                    self.top = len(self.cursor)
                else:
                    self.top = self.args.get('top')
                if len(self.cursor[:self.top]) > 10:
                    from time import sleep
                    print_warning(
                        'WARNING: opening {} files with ase-gui...'.format(
                            len(self.cursor)))
                    print_warning(
                        'Please kill script within 3 seconds if undesired...')
                    sleep(3)
                if len(self.cursor[:self.top]) > 20:
                    print_failure(
                        'You will literally be opening that many windows, ' +
                        'I\'ll give you another 5 seconds to reconsider...')

                    sleep(5)
                    print_notify('It\'s your funeral...')
                    sleep(1)
                for doc in self.cursor[:self.top]:
                    viz(doc)

            if self.subcommand != 'import':
                self.client.close()

        except (RuntimeError, SystemExit, KeyboardInterrupt) as oops:
            if isinstance(oops, RuntimeError):
                print_failure(oops)
            elif isinstance(oops, SystemExit):
                print_warning(oops)
            try:
                self.client.close()
            except AttributeError:
                pass
            raise oops
示例#10
0
文件: hull.py 项目: mkhorton/matador
    def __init__(self, query=None, cursor=None, elements=None, species=None, voltage=False, volume=False, subcmd=None,
                 plot_kwargs=None, lazy=False, energy_key='enthalpy_per_atom', client=None, collections=None, db=None,
                 **kwargs):
        """ Initialise the class from either a DBQuery or a cursor (list
        of matador dicts) and construct the appropriate phase diagram.

        Keyword arguments:
            query (matador.query.DBQuery): object containing structures,
            cursor (list(dict)): alternatively specify list of matador documents.
            species (list(str)): list of elements/chempots to use, used to provide a useful order,
            voltage (bool): whether or nto to compute voltages relative for insertion of first entry in species,
            volume (bool): whether or not to compute volume expansion relative to first entry in species,
            energy_key (str): key under which the desired energy *per atom* is stored.
            lazy (bool): if True, do not create hull until `self.create_hull()` is called
            chempots (list(float)): list of chemical potential values to use.
            elements (list(str)): deprecated form `species`.
            kwargs (dict): mostly CLI arguments, see matador hull --help for full options.
            plot_kwargs (dict): arguments to pass to plot_hull function
            client (pymongo.MongoClient): optional client to pass to DBQuery.
            collections (dict of pymongo.collections.Collection): optional dict of collections to pass to DBQuery.
            db (str): db name to connect to in DBQuery.

        """
        self.args = dict()
        if query is not None:
            self.args.update(query.args)
        self.args.update(kwargs)

        if subcmd is not None:
            warnings.warn("subcmd will soon be deprecated, please pass the equivalent flag as a kwarg (e.g. voltage=True)")
            if subcmd == 'voltage':
                voltage = True
        self.args['subcmd'] = subcmd

        if plot_kwargs is None:
            plot_kwargs = {}
        self.args['plot_kwargs'] = plot_kwargs

        self.from_cursor = False
        self.plot_params = False

        self.compute_voltages = voltage
        self.compute_volumes = volume

        if query is None and cursor is None:
            # if no query or cursor passed, push all kwargs to new query
            from matador.query import DBQuery
            kwargs.pop('intersection', None)
            query = DBQuery(
                subcmd='hull',
                intersection=True,
                client=client,
                collections=collections,
                **kwargs
            )

        self._query = query

        if self._query is not None:
            # this isn't strictly necessary but it maintains the sanctity of the query results
            self.cursor = list(deepcopy(query.cursor))
            self.args['use_source'] = False
            if self._query.args['subcmd'] not in ['hull', 'voltage', 'hulldiff']:
                print_warning('Query was not prepared with subcmd=hull, so cannot guarantee consistent formation energies.')
        else:
            self.cursor = list(cursor)
            self.from_cursor = True
            self.args['use_source'] = True

        # set up attributes for later
        self.structures = None
        self.convex_hull = None
        self.chempot_cursor = None
        self.hull_cursor = None
        self.phase_diagram = None
        self.hull_dist = None
        self.species = None
        self.voltage_data: List[VoltageProfile] = []
        self.volume_data = defaultdict(list)
        self.elements = []
        self.num_elements = 0
        self.species = self._get_species(species, elements)
        self._dimension = len(self.species)

        # tracker for whether per_b fields have been setup
        self._per_b_done = False

        self.energy_key = energy_key
        if not self.energy_key.endswith('_per_atom'):
            warnings.warn('Appending per_atom to energy_key {}'.format(self.energy_key))
            self.energy_key += '_per_atom'

        self._extensive_energy_key = self.energy_key.split('_per_atom')[0]

        if self.args.get('hull_cutoff') is not None:
            self.hull_cutoff = float(self.args['hull_cutoff'])
        else:
            self.hull_cutoff = 0.0

        if self.cursor is None:
            raise RuntimeError('Failed to find structures to create hull!')

        self._non_elemental = False
        assert isinstance(self.species, list)
        for _species in self.species:
            if len(parse_element_string(_species, stoich=True)) > 1:
                self._non_elemental = True

        if not lazy:
            self.create_hull()
示例#11
0
def refine():
    """ Test various matador refine tasks. """
    sys.argv = [
        "matador",
        "refine",
        "--db",
        DB_NAME,
        "--task",
        "sym",
        "--mode",
        "overwrite",
    ]
    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]
    matador.cli.cli.main(no_quickstart=True)

    sys.argv = [
        "matador",
        "refine",
        "--db",
        DB_NAME,
        "--task",
        "source",
        "--mode",
        "set",
    ]
    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]
    matador.cli.cli.main(no_quickstart=True)

    sys.argv = [
        "matador",
        "refine",
        "--db",
        DB_NAME,
        "--task",
        "doi",
        "--mode",
        "set",
        "--new_doi",
        "10/12345",
    ]
    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]
    matador.cli.cli.main(no_quickstart=True)

    sys.argv = [
        "matador",
        "refine",
        "--db",
        DB_NAME,
        "--task",
        "tag",
        "--mode",
        "overwrite",
        "--new_tag",
        "integration_test",
    ]
    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]
    matador.cli.cli.main(no_quickstart=True)

    sys.argv = [
        "matador",
        "refine",
        "--db",
        DB_NAME,
        "--task",
        "pspot",
        "--mode",
        "overwrite",
    ]
    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]
    matador.cli.cli.main(no_quickstart=True)

    sys.argv = [
        "matador",
        "refine",
        "--db",
        DB_NAME,
        "--task",
        "raw",
        "--mode",
        "overwrite",
    ]
    if CONFIG_FNAME is not None:
        sys.argv += ["--config", CONFIG_FNAME]
    matador.cli.cli.main(no_quickstart=True)

    query = DBQuery(db=DB_NAME, config=CONFIG_FNAME)

    return query
示例#12
0
        vornet = VoronoiNetwork(filename='Vropple.res')
        if debug:
            print(vornet.struc)
        vornet.computeVorNet()
        doc['voronoi_nodes'] = vornet.getNodeFracPos()
        doc['voronoi_face_midpoints'] = vornet.getFracFaceMidpoints()
        doc['voronoi_edge_midpoints'] = vornet.getFracEdgeMidpoints()
        if isfile('Vropple.res'):
            remove('Vropple.res')
        return doc['voronoi_nodes']
    except:
        if isfile('Vropple.res'):
            remove('Vropple.res')
        return False


if __name__ == '__main__':
    from matador.query import DBQuery
    from matador.hull import QueryConvexHull
    # test with LiAs
    query = DBQuery(composition=['LiAs'], subcmd='hull')
    hull = QueryConvexHull(query, no_plot=True, hull_cutoff=0)
    hull_cursor = hull.hull_cursor
    most_lithiated = hull_cursor[-2]
    most_lithiated_substruc = get_voronoi_substructure(most_lithiated)
    other_substruc = []
    for doc in hull_cursor:
        other_substruc.append(get_voronoi_substructure(doc))
    print(other_substruc)
    print(most_lithiated_substruc)
示例#13
0
#!/usr/bin/env python
""" This example runs directly from a matador DBQuery. """
from matador.query import DBQuery
from matador.hull import QueryConvexHull
from matador.fingerprints.similarity import get_uniq_cursor
from ilustrado.ilustrado import ArtificialSelector

# prepare best structures from hull as gene pool
query = DBQuery(composition=['KPSn'],
                db=['KP'],
                cutoff=[300, 301],
                intersection=True,
                kpoint_tolerance=0.03,
                subcmd='hull',
                biggest=True)
hull = QueryConvexHull(query,
                       intersection=True,
                       subcmd='hull',
                       no_plot=True,
                       kpoint_tolerance=0.03,
                       summary=True,
                       hull_cutoff=7.5e-2)

print('Filtering down to only ternary phases... {}'.format(
    len(hull.hull_cursor)))
hull.hull_cursor = [
    doc for doc in hull.hull_cursor if len(doc['stoichiometry']) == 3
]
print('Filtering unique structures... {}'.format(len(hull.hull_cursor)))
uniq_list, _, _, _ = list(get_uniq_cursor(hull.hull_cursor[1:-1], debug=False))
cursor = [hull.hull_cursor[1:-1][ind] for ind in uniq_list]