Source code for galore.cli.galore

#! /usr/bin/env python3
###############################################################################
#                                                                             #
# GALORE: Gaussian and Lorentzian broadening for simulated spectra            #
#                                                                             #
# Developed by Adam J. Jackson and Alex Ganose                                #
# at University College London (2017)                                         #
#                                                                             #
###############################################################################
#                                                                             #
# This file is part of Galore. Galore is free software: you can redistribute  #
# it and/or modify it under the terms of the GNU General Public License as    #
# published by the Free Software Foundation, either version 3 of the License, #
# or (at your option) any later version.  This program is distributed in the  #
# hope that it will be useful, but WITHOUT ANY WARRANTY; without even the     #
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    #
# See the GNU General Public License for more details.  You should have       #
# received a copy of the GNU General Public License along with this program.  #
# If not, see <http://www.gnu.org/licenses/>.                                 #
#                                                                             #
###############################################################################
import os
import argparse
from collections import OrderedDict
from json import load as json_load
import logging
import warnings

import numpy as np

import galore
import galore.formats
import galore.plot
from galore import auto_limits

try:
    import matplotlib
    has_matplotlib = True
except ImportError:
    has_matplotlib = False


[docs]def main(): logging.basicConfig(filename='galore.log', level=logging.INFO) console = logging.StreamHandler() logging.getLogger().addHandler(console) warnings.filterwarnings("ignore", module="matplotlib") warnings.filterwarnings("ignore", module="pymatgen") parser = get_parser() args = parser.parse_args() args = vars(args) run(**args)
[docs]def run(**kwargs): if kwargs['sampling']: pass elif kwargs['units'] in ('cm', 'cm-1'): kwargs['sampling'] = 0.1 elif kwargs['units'] in ('THz', 'thz'): kwargs['sampling'] = 1e-3 elif kwargs['units'] in ('ev', 'eV'): kwargs['sampling'] = 1e-2 else: kwargs['sampling'] = 1e-2 if kwargs['pdos']: pdos_from_files(**kwargs) else: simple_dos_from_files(**kwargs)
[docs]def pdos_from_files(return_plt=False, **kwargs): """Read input data, process for PDOS before plotting and/or writing Args: return_plt (bool): If True, return the pyplot object instead of writing or displaying plot output. **kwargs: See command reference for full argument list """ pdos_plotting_data = galore.process_pdos(**kwargs) # For plotting and writing, "None" means "write to screen" # while False means "do nothing" if kwargs['plot'] or kwargs['plot'] is None: if 'style' in kwargs and kwargs['style'] is not None: import matplotlib.pyplot matplotlib.pyplot.style.use(kwargs['style']) plt = galore.plot.plot_pdos(pdos_plotting_data, **kwargs) # flipx is included in kwargs if kwargs['overlay'] is not None: plt = galore.plot.add_overlay( plt, kwargs['overlay'], overlay_offset=kwargs['overlay_offset'], overlay_scale=kwargs['overlay_scale'], overlay_style=kwargs['overlay_style'], overlay_label=kwargs['overlay_label']) plt.legend(loc='best') xlabel = galore.plot.guess_xlabel(units=kwargs['units'], flipx=kwargs['flipx'], energy_label=None) plt.xlabel(xlabel) if kwargs['ylabel'] is not None: plt.ylabel(kwargs['ylabel']) if return_plt: return plt elif kwargs['plot']: plt.savefig(kwargs['plot']) elif kwargs['plot'] is None: plt.show() if kwargs['csv'] or kwargs['csv'] is None: galore.formats.write_pdos(pdos_plotting_data, filename=kwargs['csv'], filetype='csv', flipx=kwargs['flipx']) if kwargs['txt'] or kwargs['txt'] is None: galore.formats.write_pdos(pdos_plotting_data, filename=kwargs['txt'], filetype='txt', flipx=kwargs['flipx'])
[docs]def simple_dos_from_files(return_plt=False, **kwargs): """Generate a spectrum or DOS over one data series kwargs['input'] can be a string or a list containing one string. In addition to main kwargs documented for CLI Args: return_plt (bool): If True, return the pyplot object instead of writing or displaying plot output. **kwargs: See command reference for full argument list """ x_values, broadened_data = galore.process_1d_data(**kwargs) if not any(((kwargs['csv'] is None), (kwargs['txt'] is None), (kwargs['plot'] is None), kwargs['csv'], kwargs['txt'], kwargs['plot'])): print("No output selected. Please use at least one of the output " "options (CSV, txt, plotting). For usage information, run " "galore with -h argument.") if kwargs['plot'] or kwargs['plot'] is None: if not has_matplotlib: print("Can't plot, no Matplotlib") else: if 'style' in kwargs and kwargs['style'] is not None: import matplotlib.pyplot matplotlib.pyplot.style.use(kwargs['style']) plt = galore.plot.plot_tdos(x_values, broadened_data, **kwargs) if kwargs['ylabel'] is not None: plt.ylabel(kwargs['ylabel']) if return_plt: return plt elif kwargs['plot']: plt.savefig(kwargs['plot']) else: plt.show() if kwargs['csv'] is None: galore.formats.write_csv(x_values, broadened_data, filename=None) elif kwargs['csv']: galore.formats.write_csv( x_values, broadened_data, filename=kwargs['csv']) if kwargs['txt'] is None: galore.formats.write_txt(x_values, broadened_data, filename=None) elif kwargs['txt']: galore.formats.write_txt( x_values, broadened_data, filename=kwargs['txt'])
[docs]def get_parser(): """Parse command-line arguments. Function is used to build the CLI docs.""" parser = argparse.ArgumentParser() parser.add_argument( 'input', type=str, default='vasprun.xml', nargs='+', help='Input data file. The supported formats are vasprun.xml (VASP ' 'output), *.gpw (GPAW output), *.csv (comma-delimited text) ' 'and *.txt (space-delimited text).') parser.add_argument( '-l', '--lorentzian', nargs='?', default=False, const=2, type=float, help='Apply Lorentzian broadening with specified width.') parser.add_argument( '-g', '--gaussian', nargs='?', default=False, const=2, type=float, help='Apply Gaussian broadening with specified width.') parser.add_argument( '-w', '--weighting', type=str, default=None, help='Apply cross-section weighting to data. "alka", "he2" and ' '"yeh_haxpes" select tabulated data for valence band at 1486.6 ' 'eV, 40.8 eV and 8047.8 eV respectively. ' 'Numerical values will be interpreted as an energy in keV; ' 'for energies from 1-1500 eV cross-sections will be determined ' 'using a parametrisation from tabulated data. ' 'Alternatively, provide ' 'path to a JSON file with cross-section data.') parser.add_argument( '--units', '--x_units', type=str, default='', choices=('cm', 'cm-1', 'thz', 'THz', 'ev', 'eV', 'ry', 'Ry', 'ha', 'Ha'), help='Units for x axis (usually frequency or energy)') parser.add_argument( '--ylabel', type=str, default=None, help='Label for plot y-axis') parser.add_argument( '--txt', nargs='?', default=False, const=None, help='Write broadened output as space-delimited text; file if path ' 'provided, otherwise write to standard output.') parser.add_argument( '--csv', nargs='?', default=False, const=None, help='Write broadened output as comma-separated values; file if path ' 'provided, otherwise write to standard output.') parser.add_argument( '-p', '--plot', nargs='?', default=False, const=None, help='Plot broadened spectrum. Plot to filename if provided,' ' otherwise display to screen.') parser.add_argument( '-d', '--sampling', type=float, default=False, help='Width, in units of x, of x-axis resolution. If not specified, ' 'default value is based on units. If units are not specified, ' 'default value is 1e-2.') parser.add_argument( '-k', '--spikes', '--spike', action='store_true', help='Resample data as "spikes" on a zero baseline. The default is to ' 'interpolate linearly between y-values, which is reasonable for ' 'distributions such as DOS. If the input data set only contains ' 'active energies/frequencies (e.g. IR modes) then you should use ' '--spike mode. See tutorials for examples.') parser.add_argument( '--pdos', action="store_true", help='Use orbital-projected data') parser.add_argument( '--flipx', '--xflip', action="store_true", help='Negate x-values in output; this may be helpful for comparison ' 'with binding energy measurments.') parser.add_argument( '--xmin', type=float, default=None, help='Minimum x axis value') parser.add_argument( '--xmax', type=float, default=None, help='Maximum x axis value') parser.add_argument( '--ymin', type=float, default=0, help='Minimum y axis value') parser.add_argument( '--ymax', type=float, default=None, help='Maximum y axis value') parser.add_argument( '--style', type=str, nargs='+', default=['seaborn-colorblind'], help='Plotting style: a sequence of matplotlib styles and paths to ' 'style files. The default palette is called "seaborn-colorblind".' ) parser.add_argument( '--overlay', type=str, default=None, help='Data file for overlay') parser.add_argument( '--overlay_scale', type=float, default=None, help='Y-axis scale factor for data overlay') parser.add_argument( '--overlay_offset', type=float, default=0, help='X-axis offset for data overlay') parser.add_argument( '--overlay_style', type=str, default='o', help='Matplotlib line style for overlay data. Default "o" for ' 'circles, "x:" for crosses joined by dotted lines, etc.') parser.add_argument( '--overlay_label', type=str, default=None, help='Legend label for data overlay' ) return parser
if __name__ == '__main__': main()