Skip to content

Commit

Permalink
Add CLI for analyze element result in a bar figure (#235)
Browse files Browse the repository at this point in the history
  • Loading branch information
unkcpz authored Dec 6, 2023
1 parent 0cccd5e commit 56de70a
Show file tree
Hide file tree
Showing 8 changed files with 246 additions and 5 deletions.
169 changes: 169 additions & 0 deletions aiida_sssp_workflow/cli/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
"""CLI to inspect the results of the workflow"""
import json
import random
from pathlib import Path

import click
Expand All @@ -14,6 +15,100 @@
from aiida_sssp_workflow.utils import HIGH_DUAL_ELEMENTS, get_protocol


def lighten_color(color, amount=0.5):
"""
Lightens the given color by multiplying (1-luminosity) by the given amount.
Input can be matplotlib color string, hex string, or RGB tuple.
REF from https://stackoverflow.com/questions/37765197/darken-or-lighten-a-color-in-matplotlib
Examples:
>> lighten_color('g', 0.3)
>> lighten_color('#F034A3', 0.6)
>> lighten_color((.3,.55,.1), 0.5)
"""
import colorsys

import matplotlib.colors as mc

try:
c = mc.cnames[color]
except Exception:
c = color
c = colorsys.rgb_to_hls(*mc.to_rgb(c))
return colorsys.hls_to_rgb(c[0], 1 - amount * (1 - c[1]), c[2])


def cmap(pseudo_info: dict) -> str:
"""Return RGB string of color for given pseudo info
Hardcoded at the momment.
"""
if pseudo_info["family"] == "sg15" and pseudo_info["version"] == "v0":
return "#000000"

if pseudo_info["family"] == "gbrv":
return "#4682B4"

if (
pseudo_info["family"] == "psl"
and pseudo_info["type"] == "us"
and pseudo_info["version"] == "v1.0.0-high"
):
return "#F50E02"

if (
pseudo_info["family"] == "psl"
and pseudo_info["type"] == "us"
and pseudo_info["version"] == "v1.0.0-low"
):
return lighten_color("#F50E02")

if (
pseudo_info["family"] == "psl"
and pseudo_info["type"] == "paw"
and pseudo_info["version"] == "v1.0.0-high"
):
return "#008B00"

if (
pseudo_info["family"] == "psl"
and pseudo_info["type"] == "paw"
and pseudo_info["version"] == "v1.0.0-low"
):
return lighten_color("#008B00")

if (
pseudo_info["family"] == "psl"
and pseudo_info["type"] == "paw"
and "v0." in pseudo_info["version"]
):
return "#FF00FF"

if (
pseudo_info["family"] == "psl"
and pseudo_info["type"] == "us"
and "v0." in pseudo_info["version"]
):
return lighten_color("#FF00FF")

if pseudo_info["family"] == "dojo" and pseudo_info["version"] == "v4-str":
return "#F9A501"

if pseudo_info["family"] == "dojo" and pseudo_info["version"] == "v4-std":
return lighten_color("#F9A501")

if pseudo_info["family"] == "jth" and pseudo_info["version"] == "v1.1-str":
return "#00C5ED"

if pseudo_info["family"] == "jth" and pseudo_info["version"] == "v1.1-std":
return lighten_color("#00C5ED")

# TODO: more mapping
# if a unknow type generate random color based on ascii sum
ascn = sum([ord(c) for c in pseudo_info["representive_label"]])
random.seed(ascn)
return f"#{random.randint(0, 16777215):06x}"


def birch_murnaghan(V, E0, V0, B0, B01):
"""
Return the energy for given volume (V - it can be a vector) according to
Expand Down Expand Up @@ -130,6 +225,80 @@ def convergence_plot(
ax.set_title(title, fontsize=8)


@cmd_root.command("analyze")
@click.argument("group") # The group to inspect, name or pk of the group
@click.option("--output", "-o", default="output", help="The output file name")
def analyze(group, output):
"""Render the plot for the given pseudos and measure type."""
from aiida_sssp_workflow.utils import ACWF_CONFIGURATIONS, parse_label

# landscape mode
fig, ax = plt.subplots(1, 1, figsize=(11.69, 8.27), dpi=100)

group_node = orm.load_group(group)

# Get all nodes in the output group (EOS workflows)
group_node_query = (
orm.QueryBuilder()
.append(orm.Group, filters={"id": group_node.id}, tag="groups")
.append(orm.Node, project="*", with_group="groups")
)

nodes_lst = group_node_query.all(flat=True)
width = 0.6 / len(nodes_lst)

for i, node in enumerate(nodes_lst):
pseudo_info = parse_label(node.base.extras.all["label"].split(" ")[-1])

# TODO assert element should not change
element = node.outputs.pseudo_info.get_dict()["element"]

y_nu = []
for configuration in ACWF_CONFIGURATIONS:
res = node.outputs.measure.precision[configuration]["output_parameters"]

nu = res["rel_errors_vec_length"]
y_nu.append(nu)

x = np.arange(len(ACWF_CONFIGURATIONS))

ax.bar(
x + width * i,
y_nu,
width,
color=cmap(pseudo_info),
edgecolor="black",
linewidth=1,
label=pseudo_info["representive_label"],
)
ax.set_title(f"X={element}")

d = 0.01 # offset for the text

ax.axhline(y=0.1, linestyle="--", color="green")
ax.text(0 - d, 0.1 + d, "0.1 excellent agreement", color="black")
ax.axhline(y=0.33, linestyle="--", color="red")
ax.text(0 - d, 0.33 + d, "0.33 good agreement", color="black")
ax.legend(loc="upper right", prop={"size": 10})
ax.set_ylabel("ν -factor")
ax.set_ylim([0, 0.5])

xticks_shift = len(nodes_lst) * width / 2
xticks = [i + xticks_shift for i in range(len(ACWF_CONFIGURATIONS))]
ax.set_xticks(xticks)
ax.set_xticklabels(ACWF_CONFIGURATIONS)

# fig to pdf
fig.tight_layout()
# fig.suptitle(
# f"Comparison on {element}",
# fontsize=10,
# )
fig.subplots_adjust(top=0.92)
fpath = Path.cwd() / f"{output}_{element}_fight.pdf"
fig.savefig(fpath.name, bbox_inches="tight")


@cmd_root.command("inspect")
@click.argument("node") # The node to inspect, uuid or pk
@click.option("--output", "-o", default="output", help="The output file name")
Expand Down
26 changes: 26 additions & 0 deletions aiida_sssp_workflow/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ def get_protocol(category, name=None):

OXIDE_CONFIGURATIONS = ["XO", "XO2", "XO3", "X2O", "X2O3", "X2O5"]
UNARIE_CONFIGURATIONS = ["BCC", "FCC", "SC", "Diamond"]
ACWF_CONFIGURATIONS = OXIDE_CONFIGURATIONS + UNARIE_CONFIGURATIONS


def update_dict(d, u):
Expand Down Expand Up @@ -230,6 +231,31 @@ def get_standard_structure(
return structure


def parse_label(label):
"""parse standard pseudo label to dict of pseudo info"""
element, type, z, tool, family, *version = label.split(".")
version = ".".join(version)

if type == "nc":
full_type = "NC"
if type == "us":
full_type = "Ultrasoft"
if type == "paw":
full_type = "PAW"

return {
"element": element,
"type": type,
"z": z,
"tool": tool,
"family": family,
"version": version,
"representive_label": f"{z}|{full_type}|{family}|{tool}|{version}",
"concise_label": f"{z}|{type}|{family}|{version}",
"full_label": f"{element}|{z}|{full_type}|{family}|{tool}|{version}",
}


def parse_upf(upf_content: str) -> dict:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ hostname: "eiger.cscs.ch"
description: Eiger is the production partition on Alps, the HPE Cray EX Supercomputer large mem nodes.
transport: "core.ssh"
scheduler: "core.slurm"
work_dir: "/scratch/e1000/{username}/aiida/"
work_dir: "/capstor/scratch/cscs/{username}/aiida/"
shebang: "#!/bin/bash"
mpirun_command: "srun -n {tot_num_mpiprocs}"
mpiprocs_per_machine: 128
Expand Down
22 changes: 22 additions & 0 deletions setup-yaml/computer-setup-eiger-mr33-mem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
label: "eiger-mc-mr33-mem"
hostname: "eiger.cscs.ch"
description: Eiger is the production partition on Alps, the HPE Cray EX Supercomputer large mem nodes.
transport: "core.ssh"
scheduler: "core.slurm"
work_dir: "/capstor/scratch/cscs/{username}/aiida/"
shebang: "#!/bin/bash"
mpirun_command: "srun -n {tot_num_mpiprocs}"
mpiprocs_per_machine: 128
prepend_text: |
### computer prepend_text start ###
#SBATCH --partition=normal
#SBATCH --account=mr33
#SBATCH --constraint=mc
#SBATCH --hint=nomultithread
#SBATCH --mem=497G
export OMP_PROC_BIND=close
export OMP_PLACES=cores
### computer prepend_text end ###
append_text: " "
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ label: "ph-7.0"
description: Quantum ESPRESSO ph.x v7.0 Compiled with CpeIntel v21.12
default_calc_job_plugin: "quantumespresso.ph"
computer: "eiger-mc-mr32-mem"
filepath_executable: "/apps/eiger/UES/jenkins/1.4.0/software/QuantumESPRESSO/7.0-cpeIntel-21.12/bin/ph.x"
filepath_executable: "/capstor/apps/cscs/eiger/easybuild/software/QuantumESPRESSO/7.0-cpeIntel-22.05/bin/ph.x"
prepend_text: |
module load cpeIntel/21.12
module load cray/22.05 cpeIntel/22.05
module load QuantumESPRESSO/7.0
export OMP_NUM_THREADS=1
Expand Down
12 changes: 12 additions & 0 deletions setup-yaml/ph7.0-eiger-mr33-mem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
label: "ph-7.0"
description: Quantum ESPRESSO ph.x v7.0 Compiled with CpeIntel v21.12
default_calc_job_plugin: "quantumespresso.ph"
computer: "eiger-mc-mr33-mem"
filepath_executable: "/capstor/apps/cscs/eiger/easybuild/software/QuantumESPRESSO/7.0-cpeIntel-22.05/bin/ph.x"
prepend_text: |
module load cray/22.05 cpeIntel/22.05
module load QuantumESPRESSO/7.0
export OMP_NUM_THREADS=1
append_text: " "
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ label: "pw-7.0"
description: Quantum ESPRESSO pw.x v7.0 Compiled with CpeIntel v21.12
default_calc_job_plugin: "quantumespresso.pw"
computer: "eiger-mc-mr32-mem"
filepath_executable: "/apps/eiger/UES/jenkins/1.4.0/software/QuantumESPRESSO/7.0-cpeIntel-21.12/bin/pw.x"
filepath_executable: "/capstor/apps/cscs/eiger/easybuild/software/QuantumESPRESSO/7.0-cpeIntel-22.05/bin/pw.x"
prepend_text: |
module load cpeIntel/21.12
module load cray/22.05 cpeIntel/22.05
module load QuantumESPRESSO/7.0
export OMP_NUM_THREADS=1
Expand Down
12 changes: 12 additions & 0 deletions setup-yaml/pw7.0-eiger-mr33-mem.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
label: "pw-7.0"
description: Quantum ESPRESSO pw.x v7.0 Compiled with CpeIntel v21.12
default_calc_job_plugin: "quantumespresso.pw"
computer: "eiger-mc-mr33-mem"
filepath_executable: "/capstor/apps/cscs/eiger/easybuild/software/QuantumESPRESSO/7.0-cpeIntel-22.05/bin/pw.x"
prepend_text: |
module load cray/22.05 cpeIntel/22.05
module load QuantumESPRESSO/7.0
export OMP_NUM_THREADS=1
append_text: " "

0 comments on commit 56de70a

Please sign in to comment.