From e0c113b8930402ab52684ffa39b2f21c29a149ad Mon Sep 17 00:00:00 2001
From: Bonan Zhu <33688599+zhubonan@users.noreply.github.com>
Date: Wed, 28 Jun 2023 13:14:05 +0100
Subject: [PATCH] Code clean-up, CI update and add custom matplotlib stylesheet
(#24)
* Clean up code and add pre-commit CI action
* README.md update
* Added option to use custom mpl style sheet
* Update pylintrc
* Update pylintrc
* Clarify the `--no-expand` option
---
.github/workflows/ci.yaml | 20 +++++++-
.pylintrc | 24 ++++-----
README.md | 52 +++++++++++---------
docs/examples/example_si222.md | 18 ++++++-
docs/tutorial.md | 10 ++++
easyunfold/cli.py | 24 ++++++---
easyunfold/plotting.py | 68 +++++++++++++-------------
easyunfold/procar.py | 3 +-
easyunfold/unfold.py | 21 --------
pyproject.toml | 1 +
tests/test_cli.py | 6 +++
tests/test_data/Si-project/my.mplstyle | 1 +
12 files changed, 146 insertions(+), 102 deletions(-)
create mode 100644 tests/test_data/Si-project/my.mplstyle
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index ce66a4c..3136a78 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -6,6 +6,25 @@ name: Python package
on: [push, pull_request]
jobs:
+
+ pre-commit:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: "3.9"
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install ".[pre-commit]"
+
+ - name: Run pre-commit
+ run: "pre-commit run --all"
+
build:
runs-on: ubuntu-latest
@@ -23,7 +42,6 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
- pip install git+https://github.com/zhubonan/castepxbin.git@pr-checkfile
pip install ".[test]"
- name: Test with pytest
run: |
diff --git a/.pylintrc b/.pylintrc
index 1cfab67..5f9f31b 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -50,7 +50,7 @@ confidence=
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
-disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,fixme
+# disable=import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,fixme
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
@@ -93,13 +93,13 @@ max-nested-blocks=5
[BASIC]
# Naming hint for argument names
-argument-name-hint=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
+#argument-name-hint=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
# Regular expression matching correct argument names
argument-rgx=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
# Naming hint for attribute names
-attr-name-hint=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
+#attr-name-hint=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
# Regular expression matching correct attribute names
attr-rgx=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
@@ -108,19 +108,19 @@ attr-rgx=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
bad-names=foo,bar,baz,toto,tutu,tata
# Naming hint for class attribute names
-class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{1,30}|(__.*__))$
+#class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{1,30}|(__.*__))$
# Regular expression matching correct class attribute names
class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{1,30}|(__.*__))$
# Naming hint for class names
-class-name-hint=[A-Z_][a-zA-Z0-9]+$
+#class-name-hint=[A-Z_][a-zA-Z0-9]+$
# Regular expression matching correct class names
class-rgx=[A-Z_][a-zA-Z0-9]+$
# Naming hint for constant names
-const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+#const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$
# Regular expression matching correct constant names
const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
@@ -130,7 +130,7 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
docstring-min-length=6
# Naming hint for function names
-function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+# function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct function names
function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
@@ -142,19 +142,19 @@ good-names=x,y,z,X,Y,Z,tmp,ax,i,j,k,ex,Run,_, _INPUT_FILE_NAME, _OUTPUT_FILE_NAM
include-naming-hint=no
# Naming hint for inline iteration names
-inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
+#inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$
# Regular expression matching correct inline iteration names
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
# Naming hint for method names
-method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
+#method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$
# Regular expression matching correct method names
method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*)|(setUp)|(tearDown))$
# Naming hint for module names
-module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+#module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
# Regular expression matching correct module names
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
@@ -172,7 +172,7 @@ no-docstring-rgx=^_,setUp,tearDown
property-classes=abc.abstractproperty
# Naming hint for variable names
-variable-name-hint=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
+#variable-name-hint=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
# Regular expression matching correct variable names
variable-rgx=(([a-z][a-z0-9_]{1,30})|(_[a-z0-9_]*))$
@@ -203,7 +203,7 @@ max-module-lines=4000
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
-no-space-check=trailing-comma,dict-separator
+# no-space-check=trailing-comma,dict-separator
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
diff --git a/README.md b/README.md
index 97e18a7..1800485 100644
--- a/README.md
+++ b/README.md
@@ -9,41 +9,41 @@ svg)](https://doi.org/10.21105/joss.)--->
[![easyunfold](docs/img/logo.svg)](https://smtg-ucl.github.io/easyunfold/)
`Easyunfold` is intended for obtaining the effective band structure of a supercell for a certain _k_-point
-path of the primitive cell. It was originally based on
-[PyVaspwfc](https://github.com/QijingZheng/VaspBandUnfolding) for reading VASP wavefunction outputs,
-with a notable improvement being that symmetry-breaking is properly accounted for by sampling necessary
-additional _k_-points and averaging accordingly. Documentation site
+path of the primitive cell. It was originally based on
+[PyVaspwfc](https://github.com/QijingZheng/VaspBandUnfolding) for reading VASP wavefunction outputs,
+with a notable improvement being that symmetry-breaking is properly accounted for by sampling necessary
+additional _k_-points and averaging accordingly. Documentation site
[here](https://smtg-ucl.github.io/easyunfold/)!
-Our goal is to implement the band structure unfolding workflow in a robust and user-friendly software
+Our goal is to implement the band structure unfolding workflow in a robust and user-friendly software
package.
-For the methodology of supercell band unfolding, see
+For the methodology of supercell band unfolding, see
[here](https://link.aps.org/doi/10.1103/PhysRevB.85.085201).
## Usage
To generate an unfolded band structure, one typically needs to perform the following steps:
-1. Create a primitive unit cell, and generate a band structure _k_-point path corresponding to this
+1. Create a primitive unit cell, and generate a band structure _k_-point path corresponding to this
primitive cell.
2. Create a supercell (e.g. disordered, defective, surface slab etc.), and obtain its optimised structure.
3. Generate a series of _k_-points for the supercell to be calculated.
4. Perform a band structure calculation with the supercell, and save its wavefunction output to file.
-5. Post-process the supercell wavefunction to obtain the unfolded band structure in the _k_-point path
+5. Post-process the supercell wavefunction to obtain the unfolded band structure in the _k_-point path
of the primitive unit cell.
-These generation and analysis steps are automated in `easyunfold`, with only the primitive unit cell and
+These generation and analysis steps are automated in `easyunfold`, with only the primitive unit cell and
supercell structures required as inputs from the user.
-Typically, the supercell comprises some form of symmetry-breaking relative to the primitive cell, such
-as defects, disorder (e.g. special quasi-random structures (SQS) for site disorder – other forms of
-disorder such as magnetic, dynamic/vibrational, polar, elastic etc. also possible), or a surface/interface
+Typically, the supercell comprises some form of symmetry-breaking relative to the primitive cell, such
+as defects, disorder (e.g. special quasi-random structures (SQS) for site disorder – other forms of
+disorder such as magnetic, dynamic/vibrational, polar, elastic etc. also possible), or a surface/interface
slab.
In all cases, the supercell symmetry is lowered compared to the pristine primitive cell.
-Hence, for a given _k_-point path in the primitive cell Brillouin Zone, additional _k_-points are
-required to be sampled for the supercell, and the extracted spectral weights need to be appropriately
-averaged to obtain the correct effective band structure (EBS). See the docs
+Hence, for a given _k_-point path in the primitive cell Brillouin Zone, additional _k_-points are
+required to be sampled for the supercell, and the extracted spectral weights need to be appropriately
+averaged to obtain the correct effective band structure (EBS). See the docs
[Theory](https://smtg-ucl.github.io/easyunfold/theory.html) page for more details.
@@ -78,7 +78,8 @@ Commands:
```
### Developer Installation (from source)
-A recent version of `pip` is needed to do this, due to the new style of the `pyproject.toml` configuration
+
+A recent version of `pip` is needed to do this, due to the new style of the `pyproject.toml` configuration
file.
To upgrade your `pip`, do:
@@ -89,9 +90,12 @@ pip install -U pip
Assuming the package is in the `easyunfold` folder, use the following command to install:
```
-pip install ./easyunfold
+pip install "./easyunfold[test,doc,pre-commit]"
```
+which also installs additional dependencies for building documentation (`doc`), running tests (`test`) and
+dependencies for using pre-commit hooks (`pre-commit`).
+
## Studies using `easyunfold`
We'll add papers that use `easyunfold` to this list as they come out!
@@ -108,21 +112,21 @@ In principle, support for other plane wave DFT code can be added by:
- Implementing a subclass of `WaveFunction` that handles reading the wave function output.
- Implementing functions for reading/writing _k_-points.
-- Adding branches for dispatching based on the `dft_code` attribute of the `UnfoldKSet` object in
+- Adding branches for dispatching based on the `dft_code` attribute of the `UnfoldKSet` object in
various places within the code.
-The Atomic Simulation Environment ([ASE](https://wiki.fysik.dtu.dk/ase/)) is used by `easyunfold` for
+The Atomic Simulation Environment ([ASE](https://wiki.fysik.dtu.dk/ase/)) is used by `easyunfold` for
reading in structures, so structure file IO is natively supported for essentially all public DFT codes.
### Code Compatibility Notes
- Atom-projected band structures are currently only supported for `VASP` calculation outputs.
-- Gamma-only and non-collinear spin calculations are not supported for `CASTEP`.
+- Gamma-only and non-collinear spin calculations are not supported for `CASTEP`.
## Contributors
-- [Bonan Zhu](https://github.com/zhubonan)
-- [Seán Kavanagh](https://github.com/kavanase)
-- [Adair Nicolson](https://github.com/adair-nicolson)
+- [Bonan Zhu](https://github.com/zhubonan)
+- [Seán Kavanagh](https://github.com/kavanase)
+- [Adair Nicolson](https://github.com/adair-nicolson)
And those who helped in the development:
-- [Joe Willis](https://github.com/joebesity)
+- [Joe Willis](https://github.com/joebesity)
- [David O. Scanlon](http://davidscanlon.com/?page_id=5)
diff --git a/docs/examples/example_si222.md b/docs/examples/example_si222.md
index c120aff..9f28dfe 100644
--- a/docs/examples/example_si222.md
+++ b/docs/examples/example_si222.md
@@ -137,6 +137,11 @@ Primitive cell band structure of Si.
## What happens if symmetry is not properly taken into account?
+It is quite common that the supercell has lower symmetry compared to the primitive cell.
+By default, `easyunfold` takes account of such symmetry breaking effect by including
+additional _k_-points that no longer equivalent under the symmetry of the supercell cell.
+
+In this example, we show what happens if we **do not** include the additional kpoints.
We can create a new unfolding project (`json` data file) using the following command:
```bash
@@ -189,7 +194,7 @@ Primitive cell information:
Point group: m-3m
No. of k points in the primitive cell : 73
-No. of (non-symmetry-reduced) supercell kpoints : 70 (73)
+No. of supercell kpoints : 70
No. of primitive cell symmetry operations : 48
No. of supercell symmetry operations : 6
@@ -200,4 +205,13 @@ Path in the primitive cell:
X : 50
\Gamma : 73
Unfolding had been performed - use `unfold plot` to plot the spectral function.
-```
\ No newline at end of file
+```
+
+Note that in most cases one would always want to include the additional kpoints to correctly capture the effect of symmetry breaking.
+The `--no-expand` option should be used with care and **only when there is no alternative**,
+for example,
+when the expansion gives too many kpoints for very large supercells of special quasi-random structures.
+
+:::{note}
+One can always split the workload into multiple calculations with `--nk-per-split` to fit the computational resources available for individual calculations.
+:::
diff --git a/docs/tutorial.md b/docs/tutorial.md
index c49f792..097e762 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -189,6 +189,16 @@ BuPu `cmap` | viridis `cmap` |
:-------------------------:|:-------------------------------------------------------:|:-------------------------:
![](../examples/NaBiS2/NaBiS2_unfold-plot_BuPu.png) | ![](../examples/NaBiS2/NaBiS2_unfold-plot_viridis.png) |
+:::{tip}
+Figure can be further customised by passing a path to a matplotlib style sheet file, for example:
+
+```
+easyunfold unfold --mpl-style-file plot
+```
+
+which can be used to change the font, font sizes, ticks styles etc.
+Read more on [the matplotlib tutorial page](https://matplotlib.org/stable/tutorials/introductory/customizing.html#using-style-sheets).
+:::
[^vasp]: https://www.vasp.at
[^castep]: http://www.castep.org
\ No newline at end of file
diff --git a/easyunfold/cli.py b/easyunfold/cli.py
index bfc805b..0d7220b 100644
--- a/easyunfold/cli.py
+++ b/easyunfold/cli.py
@@ -18,7 +18,7 @@
'BuGn', 'YlGn'
]
-CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
+CONTEXT_SETTINGS = {'help_option_names': ['-h', '--help']}
@click.group('easyunfold', context_settings=CONTEXT_SETTINGS)
@@ -143,8 +143,13 @@ def generate(pc_file, code, sc_file, matrix, kpoints, time_reversal, out_file, n
@easyunfold.group('unfold')
@click.option('--data-file', default='easyunfold.json', type=click.Path(exists=True, file_okay=True, dir_okay=False), show_default=True)
+@click.option('--mpl-style-file',
+ type=click.Path(exists=True, file_okay=True, dir_okay=False),
+ show_default=True,
+ required=False,
+ help='Use this file to customise the matplotlib style sheet')
@click.pass_context
-def unfold(ctx, data_file):
+def unfold(ctx, data_file, mpl_style_file):
"""
Perform unfolding and plotting
@@ -154,6 +159,10 @@ def unfold(ctx, data_file):
unfoldset = loadfn(data_file)
click.echo(f'Loaded data from {data_file}')
ctx.obj = {'obj': unfoldset, 'fname': data_file}
+ if mpl_style_file:
+ click.echo(f'Using custom plotting style from {mpl_style_file}')
+ import matplotlib.style
+ matplotlib.style.use(mpl_style_file)
@unfold.command('status')
@@ -234,6 +243,7 @@ def add_plot_options(func):
click.option('--title', help='Title to be used')(func)
click.option('--width', help='Width of the figure', type=float, default=4., show_default=True)(func)
click.option('--height', help='Height of the figure', type=float, default=3., show_default=True)(func)
+ click.option('--dpi', help='DPI for the figure when saved as raster image.', type=int, default=300, show_default=True)(func)
return func
@@ -341,14 +351,14 @@ def print_data(entries, tag='me'):
@click.pass_context
@add_plot_options
def unfold_plot(ctx, gamma, npoints, sigma, eref, out_file, show, emin, emax, cmap, ncl, no_symm_average, vscale, procar, atoms_idx,
- orbitals, title, width, height):
+ orbitals, title, width, height, dpi):
"""
Plot the spectral function
This command uses the stored unfolding data to plot the effective bands structure (EBS) using the spectral function.
"""
_unfold_plot(ctx, gamma, npoints, sigma, eref, out_file, show, emin, emax, cmap, ncl, no_symm_average, vscale, procar, atoms_idx,
- orbitals, title, width, height)
+ orbitals, title, width, height, dpi)
@unfold.command('plot-projections')
@@ -358,7 +368,7 @@ def unfold_plot(ctx, gamma, npoints, sigma, eref, out_file, show, emin, emax, cm
@click.option('--intensity', default=1.0, help='Color intensity for combined plot', type=float, show_default=True)
@click.option('--colors', help='Colors to be used for combined plot, comma separated.', default='r,g,b,purple', show_default=True)
def unfold_plot_projections(ctx, gamma, npoints, sigma, eref, out_file, show, emin, emax, cmap, ncl, no_symm_average, vscale, procar,
- atoms_idx, orbitals, title, combined, intensity, colors, width, height):
+ atoms_idx, orbitals, title, combined, intensity, colors, width, height, dpi):
"""
Plot the effective band structure with atomic projections.
"""
@@ -389,7 +399,7 @@ def unfold_plot_projections(ctx, gamma, npoints, sigma, eref, out_file, show, em
colors=colors.split(',') if colors is not None else None)
if out_file:
- fig.savefig(out_file, dpi=300)
+ fig.savefig(out_file, dpi=dpi)
click.echo(f'Unfolded band structure saved to {out_file}')
if show:
@@ -415,6 +425,7 @@ def _unfold_plot(ctx,
title,
width,
height,
+ dpi,
ax=None):
"""
Routine for plotting the spectral function.
@@ -466,6 +477,7 @@ def _unfold_plot(ctx,
vscale=vscale,
cmap=cmap,
title=title,
+ dpi=dpi,
ax=ax)
if out_file:
diff --git a/easyunfold/plotting.py b/easyunfold/plotting.py
index 484ac32..0152503 100644
--- a/easyunfold/plotting.py
+++ b/easyunfold/plotting.py
@@ -1,7 +1,7 @@
"""
Plotting utilities
"""
-from typing import Union
+from typing import Union, Sequence
import matplotlib.pyplot as plt
import numpy as np
@@ -122,7 +122,7 @@ def plot_spectral_function(
fig.tight_layout(pad=0.2)
if save:
- fig.savefig(save, dpi=300)
+ fig.savefig(save, dpi=dpi)
if show:
fig.show()
return fig
@@ -207,7 +207,7 @@ def _plot_spectral_function_rgba(
fig.tight_layout(pad=0.2)
if save:
- fig.savefig(save, dpi=300)
+ fig.savefig(save, dpi=dpi)
if show:
fig.show()
return fig
@@ -395,39 +395,39 @@ def plot_spectral_weights(
fig.tight_layout(pad=0.2)
if save:
- fig.savefig(save, dpi=300)
+ fig.savefig(save, dpi=dpi)
if show:
fig.show()
return fig
def plot_projected(
- self,
- procar: Union[str, list],
- eref=None,
- gamma=False,
- npoints=2000,
- sigma=0.2,
- ncl=False,
- symm_average=True,
- figsize=(4, 3),
- ylim=(-3, 3),
- dpi=150,
- vscale=1.0,
- contour_plot=False,
- alpha=1.0,
- save=False,
- ax=None,
- vmin=None,
- vmax=None,
- cmap='PuRd',
- show=False,
- title=None,
- atoms_idx=None,
- orbitals=None,
- intensity=1.0,
- use_subplot=False,
- colors=["r", "g", "b", "purple"],
- colorspace='lab',
+ self,
+ procar: Union[str, list],
+ eref=None,
+ gamma=False,
+ npoints=2000,
+ sigma=0.2,
+ ncl=False,
+ symm_average=True,
+ figsize=(4, 3),
+ ylim=(-3, 3),
+ dpi=150,
+ vscale=1.0,
+ contour_plot=False,
+ alpha=1.0,
+ save=False,
+ ax=None,
+ vmin=None,
+ vmax=None,
+ cmap='PuRd',
+ show=False,
+ title=None,
+ atoms_idx=None,
+ orbitals=None,
+ intensity=1.0,
+ use_subplot=False,
+ colors=('r', 'g', 'b', 'purple'),
+ colorspace='lab',
):
"""
Plot projected spectral function onto multiple subplots or a single plot with color mapping.
@@ -522,7 +522,7 @@ def plot_projected(
stacked_sf = np.stack(all_sf, axis=-1).reshape(np.prod(sf_size), len(all_sf))
# Construct the color basis
- colors = colors[0:len(all_sf)]
+ colors = colors[:len(all_sf)]
# Compute spectral weight data with RGB reshape it back into the shape (nengs, nk, 3)
sf_rgb = interpolate_colors(colors, stacked_sf, colorspace, normalize=True).reshape(sf_size + (3,))
sf_sum = np.sum(all_sf, axis=0)[:, :, :, None]
@@ -584,7 +584,7 @@ def plot_effective_mass_fit(efm: EffectiveMass,
return fig
-def interpolate_colors(colors: list, weights: list, colorspace='lab', normalize=True):
+def interpolate_colors(colors: Sequence, weights: list, colorspace='lab', normalize=True):
"""
Interpolate colors at a number of points within a colorspace.
@@ -607,7 +607,7 @@ def interpolate_colors(colors: list, weights: list, colorspace='lab', normalize=
'xyz': XYZColor,
}
- if colorspace not in list(colorspace_mapping.keys()):
+ if colorspace not in colorspace_mapping:
raise ValueError(f'colorspace must be one of {colorspace_mapping.keys()}')
colorspace = colorspace_mapping[colorspace]
diff --git a/easyunfold/procar.py b/easyunfold/procar.py
index 1a01013..212b272 100644
--- a/easyunfold/procar.py
+++ b/easyunfold/procar.py
@@ -82,8 +82,7 @@ def _read(self, fobj):
self.nspins = proj_data.shape[0] // (self.nion * self.nbands * self.nkpts)
self.nspins //= 4 if self._is_soc else 1
- if self._is_soc:
- self.spin = self.spin // 4
+
# Reshape
self.occs.resize((self.nspins, self.nkpts, self.nbands))
self.kvecs.resize((self.nspins, self.nkpts, 3))
diff --git a/easyunfold/unfold.py b/easyunfold/unfold.py
index c38bc71..2acf0c8 100644
--- a/easyunfold/unfold.py
+++ b/easyunfold/unfold.py
@@ -289,7 +289,6 @@ def generate_sc_kpoints(self) -> None:
# We now have bunch of supercell kpoints for each set of expanded kpoints
# Try to find duplicated SC kpoints
- # TODO: We can further reduce this by time-reversal symmetry here
all_sc = np.array(all_sc)
reduced_sckpts, _, sc_kpts_map = reduce_kpoints(all_sc, time_reversal=self.time_reversal)
sc_kpts_map = list(sc_kpts_map)
@@ -632,26 +631,6 @@ def GaussianSmearing(x, x0, sigma=0.02):
return 1. / (np.sqrt(2 * np.pi) * sigma) * np.exp(-(x - x0)**2 / (2 * sigma**2))
-def remove_duplicated_kpoints(kpoints: list, return_map=False, decimals=6):
- """
- remove duplicate kpoints in the list.
-
- TODO: improve this implementation by clipping the range of the fractional coorindates
- """
- kpoints = np.asarray(kpoints)
- _, kid, inv_kid = np.unique(
- np.round(kpoints, decimals),
- axis=0,
- return_index=True,
- return_inverse=True,
- )
- reducedK = kpoints[kid]
-
- if return_map:
- return reducedK, inv_kid
- return reducedK
-
-
def make_kpath(kbound: List[float], nseg=40):
"""
Return a list of kpoints defining the path between the given kpoints.
diff --git a/pyproject.toml b/pyproject.toml
index 5d9d6a1..05d4889 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,3 +31,4 @@ doc = [
"sphinx-copybutton>=0.3,<0.4", "myst-parser[linkify]", "sphinx>=6,<7"
]
test = ["pytest", "pytest-cov", "coverage"]
+pre-commit = ["pre-commit", "pylint~=2.11"]
diff --git a/tests/test_cli.py b/tests/test_cli.py
index cf7c328..cc8cfb8 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -67,6 +67,12 @@ def test_unfold(si_project_dir, tag):
assert output.exit_code == 0
assert 'Please run the supercell' in output.stdout
+ # matplotlib customisation check
+ args_calc = ['unfold', '--data-file', 'test.json', '--mpl-style-file', 'my.mplstyle', 'status']
+ output = runner.invoke(easyunfold, args_calc)
+ assert output.exit_code == 0
+ assert 'Using custom plotting style' in output.stdout
+
# Perform the unfold
args_calc = ['unfold', '--data-file', 'test.json', 'calculate', f'Si_super_deformed{tag}/WAVECAR']
if 'soc' in tag:
diff --git a/tests/test_data/Si-project/my.mplstyle b/tests/test_data/Si-project/my.mplstyle
new file mode 100644
index 0000000..932415f
--- /dev/null
+++ b/tests/test_data/Si-project/my.mplstyle
@@ -0,0 +1 @@
+figure.dpi : 120