Esempio n. 1
0
    def create_hull(self):
        """ Begin the hull creation routines and perform the
        post-processing specified by initial arguments.

        """
        if self.args.get('uniq'):
            from matador.utils.cursor_utils import filter_unique_structures
            if self.args.get('uniq') is True:
                sim_tol = 0.1
            else:
                sim_tol = self.args.get('uniq')
            print_notify('Filtering for unique structures...')
            self.cursor = filter_unique_structures(self.cursor,
                                                   args=self.args,
                                                   quiet=True,
                                                   sim_tol=sim_tol,
                                                   hull=True,
                                                   energy_key=self.energy_key)

        self.construct_phase_diagram()

        if not self.hull_cursor:
            print_warning(
                'No structures on hull with chosen chemical potentials.')
        else:
            print_notify(
                '{} structures found within {} eV of the hull, including chemical potentials.'
                .format(len(self.hull_cursor), self.hull_cutoff))

        display_results(self.hull_cursor,
                        hull=True,
                        energy_key=self.energy_key,
                        **self.args)

        if self.compute_voltages:
            print("Constructing electrode system with active ion: {}".format(
                self.species[0]))
            self.voltage_curve()

        if self.compute_volumes:
            self.volume_curve()

        if not self.args.get('no_plot'):
            if self.compute_voltages and self.voltage_data:
                self.plot_voltage_curve(show=False)
            if self.compute_volumes and self.volume_data:
                self.plot_volume_curve(show=False)

            self.plot_hull(**self.args['plot_kwargs'],
                           debug=self.args.get('debug'),
                           show=True)
Esempio n. 2
0
 def print_diff(self, **args):
     """ Use the display_results function to print the diff. """
     display_results(self.cursor,
                     hull=True,
                     additions=self.additions,
                     deletions=self.deletions)
     if self.additions is not None:
         if args.get('summary'):
             print(
                 '{} additions and {} replacements as best at stoichiometry.'
                 .format(len(self.additions), len(self.deletions)))
         else:
             print('{} additions and {} deletions.'.format(
                 len(self.additions), len(self.deletions)))
Esempio n. 3
0
 def __str__(self):
     """ Print underlying phase diagram. """
     return display_results(self.cursor,
                            hull=True,
                            colour=False,
                            energy_key=self.formation_key,
                            sort=False,
                            return_str=True)
Esempio n. 4
0
    def perform_id_query(self):
        """ Query the `text_id` field for the ID provided in the args for a calc_match
        or hull/voltage query. Use the results of the text_id query to match to other
        entries that have the same calculation parameters. Sets self.query_dict and
        self.calc_dict.

        Raises:
            RuntimeError: if no structures are found.

        """

        self.cursor = []
        query_dict = dict()
        query_dict['$and'] = []
        query_dict['$and'].append(self._query_id())
        if not self.args.get('ignore_warnings'):
            query_dict['$and'].append(self._query_quality())
        self.repo = self._collection
        self.cursor = list(self._find_and_sort(query_dict))

        if not self.cursor:
            raise RuntimeError('Could not find a match with {} try widening your search.'.format(self.args.get('id')))

        if len(self.cursor) >= 1:
            display_results(list(self.cursor)[:self.top], **self.args)

            if len(self.cursor) > 1:
                print_warning('Matched multiple structures with same text_id. The first one will be used.')

            # save special copy of calc_dict for hulls
            self.calc_dict = dict()
            self.calc_dict['$and'] = []
            # to avoid deep recursion, and since this is always called first
            # don't append, just set
            self.query_dict = self._query_calc(self.cursor[0])
            if self.args.get('composition'):
                self.args['intersection'] = True
                self.query_dict['$and'].append(self._query_composition())
            self.calc_dict['$and'] = list(self.query_dict['$and'])
Esempio n. 5
0
    def perform_query(self):
        """ Find results that match the query_dict
        inside the MongoDB database.
        """
        # if no query submitted, find all
        if self._empty_query and self.args.get('id') is None:
            self.repo = self._collection
            self.cursor, cursor_count = self._perform_empty_query()

        # if no special query has been made already, begin executing the query
        if not self._empty_query:
            self.repo = self._collection
            if self.debug:
                print('Query dict:')
                print(dumps(self.query_dict, indent=1))

            # execute query
            self.cursor, cursor_count = self._find_and_sort(self.query_dict)
            if self._non_elemental:
                self.cursor = filter_cursor_by_chempots(self._chempots, self.cursor)

        print('{} results found for query in {}.'.format(cursor_count, self.repo.name))
        self._num_to_display = cursor_count
        if self.args.get('subcmd') != 'swaps' and not self._create_hull:
            self._set_filter_display_results(cursor_count)

        # if a summary has been requested, cursor must be converted to list
        if self.args.get('summary'):
            self.cursor = list(self.cursor)

        if self.args.get('subcmd') != 'swaps' and not self._create_hull:
            if self._num_to_display >= 1 or self._num_to_display is None:
                if self._num_to_display == cursor_count:
                    display_results(self.cursor, **self.args)
                else:
                    display_results(self.cursor[:self._num_to_display], **self.args)

        if isinstance(self.cursor, pm.cursor.Cursor):
            self.cursor.rewind()
Esempio n. 6
0
def query2files(cursor,
                dirname=None,
                max_files=10000,
                top=None,
                prefix=None,
                cell=None,
                param=None,
                res=None,
                pdb=None,
                json=None,
                xsf=None,
                markdown=True,
                latex=False,
                subcmd=None,
                argstr=None,
                **kwargs):
    """ Many-to-many convenience function for many structures being written to
    many file types.

    Parameters:
        cursor (:obj:`list` of :obj:`dict`/:class:`AtomicSwapper`): list of matador dictionaries to write out.

    Keyword arguments:
        dirname (str): the folder to save the results into. Will be created if non-existent.
            Will have integer appended to it if already existing.
        max_files (int): if the number of files to be written exceeds this number, then raise RuntimeError.
        **kwargs (dict): dictionary of {filetype: bool(whether to write)}. Accepted file types
            are cell, param, res, pdb, json, xsf, markdown and latex.

    """
    multiple_files = any((cell, param, res, pdb, xsf))
    prefix = prefix + '-' if prefix is not None else ''

    if isinstance(cursor, AtomicSwapper):
        cursor = cursor.cursor
        subcmd = "swaps"

    if subcmd in ['polish', 'swaps']:
        info = False
        hash_dupe = False
    else:
        info = True
        hash_dupe = False

    if isinstance(cursor, list):
        num = len(cursor)
    else:
        num = cursor.count()

    if top is not None:
        if top < num:
            num = top

    num_files = num * sum(1 for ext in [cell, param, res, pdb, xsf] if ext)

    if multiple_files:
        print('Intending to write', num, 'structures to file...')
        if num_files > max_files:
            raise RuntimeError(
                "Not writing {} files as it exceeds argument `max_files` limit of {}"
                .format(num_files, max_files))

    if dirname is None:
        dirname = generate_relevant_path(subcmd=subcmd, **kwargs)

    _dir = False
    dir_counter = 0
    # postfix integer on end of directory name if it exists
    while not _dir:
        if dir_counter != 0:
            directory = dirname + str(dir_counter)
        else:
            directory = dirname
        if not os.path.isdir(directory):
            os.makedirs(directory)
            _dir = True
        else:
            dir_counter += 1

    for _, doc in enumerate(cursor[:num]):
        # generate an appropriate filename for the structure
        root_source = get_root_source(doc)

        if '_swapped_stoichiometry' in doc:
            formula = get_formula_from_stoich(doc['_swapped_stoichiometry'])
        else:
            formula = get_formula_from_stoich(doc['stoichiometry'])

        if subcmd == 'swaps':
            root_source = root_source.replace('-swap-', '-')

        name = root_source

        if 'OQMD ' in root_source:
            name = '{formula}-OQMD_{src}'.format(
                formula=formula, src=root_source.split(' ')[-1])
        elif 'mp-' in root_source:
            name = '{formula}-MP_{src}'.format(formula=formula,
                                               src=root_source.split('-')[-1])
        if 'icsd' in doc and 'CollCode' not in name:
            name += '-CollCode{}'.format(doc['icsd'])
        else:
            pf_id = None
            for source in doc['source']:
                if 'pf-' in source:
                    pf_id = source.split('-')[-1]
                    break
            else:
                if 'pf_ids' in doc:
                    pf_id = doc['pf_ids'][0]
            if pf_id is not None:
                name += '-PF-{}'.format(pf_id)

        # if swaps, prepend new composition
        if subcmd == 'swaps':
            new_formula = get_formula_from_stoich(get_stoich(
                doc['atom_types']))
            name = '{}-swap-{}'.format(new_formula, name)

        path = "{directory}/{prefix}{name}".format(directory=directory,
                                                   prefix=prefix,
                                                   name=name)

        if param:
            doc2param(doc, path, hash_dupe=hash_dupe)
        if cell:
            doc2cell(doc, path, hash_dupe=hash_dupe)
        if res:
            doc2res(doc, path, info=info, hash_dupe=hash_dupe)
        if json:
            doc2json(doc, path, hash_dupe=hash_dupe)
        if pdb:
            doc2pdb(doc, path, hash_dupe=hash_dupe)
        if xsf:
            doc2xsf(doc, path)

    hull = subcmd in ['hull', 'voltage']
    if isinstance(cursor, pm.cursor.Cursor):
        cursor.rewind()
    md_path = "{directory}/{directory}.md".format(directory=directory)
    md_kwargs = {}
    md_kwargs.update(kwargs)
    md_kwargs.update({
        'markdown': True,
        'latex': False,
        'argstr': argstr,
        'hull': hull
    })
    md_string = display_results(cursor, **md_kwargs)
    with open(md_path, 'w') as f:
        f.write(md_string)

    if latex:
        if isinstance(cursor, pm.cursor.Cursor):
            cursor.rewind()
        tex_path = "{directory}/{directory}.tex".format(directory=directory)
        print('Writing LaTeX file', tex_path + '...')
        tex_kwargs = {}
        tex_kwargs.update(kwargs)
        tex_kwargs.update({
            'latex': True,
            'markdown': False,
            'argstr': argstr,
            'hull': hull
        })
        tex_string = display_results(cursor, **tex_kwargs)
        with open(tex_path, 'w') as f:
            f.write(tex_string)

    print('Done!')
Esempio n. 7
0
 def __repr__(self):
     return display_results(self.hull_cursor, args=self.args, hull=True, energy_key=self.energy_key, return_str=True)