changeset 0:886949a03377 draft

planemo upload for repository https://github.com/MaterialsGalaxy/larch-tools/tree/main/larch_plot commit 5be486890442dedfb327289d597e1c8110240735
author muon-spectroscopy-computational-project
date Tue, 14 Nov 2023 15:35:36 +0000
parents
children 002c18a3e642
files common.py larch_plot.py larch_plot.xml macros.xml test-data/test.prj
diffstat 5 files changed, 256 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common.py	Tue Nov 14 15:35:36 2023 +0000
@@ -0,0 +1,46 @@
+from typing import Iterable
+
+from larch.io import extract_athenagroup, read_athena
+from larch.io.athena_project import AthenaGroup
+from larch.symboltable import Group
+from larch.xafs import autobk, pre_edge, xftf
+
+
+def get_group(athena_group: AthenaGroup, key: str = None) -> Group:
+    if key is None:
+        group_keys = list(athena_group._athena_groups.keys())
+        key = group_keys[0]
+    return extract_athenagroup(athena_group._athena_groups[key])
+
+
+def read_group(dat_file: str, key: str = None, xftf_params: dict = None):
+    athena_group = read_athena(dat_file)
+    group = get_group(athena_group, key)
+    bkg_parameters = group.athena_params.bkg
+    print(group.athena_params.fft)
+    print(group.athena_params.fft.__dict__)
+    pre_edge(
+        group,
+        e0=bkg_parameters.e0,
+        pre1=bkg_parameters.pre1,
+        pre2=bkg_parameters.pre2,
+        norm1=bkg_parameters.nor1,
+        norm2=bkg_parameters.nor2,
+        nnorm=bkg_parameters.nnorm,
+        make_flat=bkg_parameters.flatten,
+    )
+    autobk(group)
+    if xftf_params is None:
+        xftf(group)
+    else:
+        print(xftf_params)
+        xftf(group, **xftf_params)
+        xftf_details = Group()
+        setattr(xftf_details, "call_args", xftf_params)
+        group.xftf_details = xftf_details
+    return group
+
+
+def read_groups(dat_files: "list[str]", key: str = None) -> Iterable[Group]:
+    for dat_file in dat_files:
+        yield read_group(dat_file=dat_file, key=key)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/larch_plot.py	Tue Nov 14 15:35:36 2023 +0000
@@ -0,0 +1,101 @@
+import json
+import sys
+
+from common import read_groups
+
+import matplotlib
+import matplotlib.pyplot as plt
+
+import numpy as np
+
+
+Y_LABELS = {
+    "norm": r"x$\mu$(E), normalised",
+    "dmude": r"d(x$\mu$(E))/dE, normalised",
+    "chir_mag": r"|$\chi$(r)|",
+}
+
+
+def main(dat_files: "list[str]", plot_settings: "list[dict]"):
+    groups = list(read_groups(dat_files))
+
+    for i, settings in enumerate(plot_settings):
+        data_list = []
+        e0_min = None
+        e0_max = None
+        variable = settings["variable"]["variable"]
+        x_min = settings["variable"]["energy_min"]
+        x_max = settings["variable"]["energy_max"]
+        plot_path = f"plots/{i}_{variable}.png"
+        plt.figure()
+
+        for group in groups:
+            label = group.athena_params.annotation or group.athena_params.id
+            if variable == "chir_mag":
+                x = group.r
+                energy_format = None
+            else:
+                x = group.energy
+                energy_format = settings["variable"]["energy_format"]
+                if energy_format == "relative":
+                    e0 = group.athena_params.bkg.e0
+                    e0_min = find_relative_limit(e0_min, e0, min)
+                    e0_max = find_relative_limit(e0_max, e0, max)
+
+            y = getattr(group, variable)
+            if x_min is None and x_max is None:
+                plt.plot(x, y, label=label)
+            else:
+                data_list.append({"x": x, "y": y, "label": label})
+
+        if variable != "chir_mag" and energy_format == "relative":
+            if x_min is not None:
+                x_min += e0_min
+            if x_max is not None:
+                x_max += e0_max
+
+        if x_min is not None or x_max is not None:
+            for data in data_list:
+                index_min = None
+                index_max = None
+                x = data["x"]
+                if x_min is not None:
+                    index_min = max(np.searchsorted(x, x_min) - 1, 0)
+                if x_max is not None:
+                    index_max = min(np.searchsorted(x, x_max) + 1, len(x))
+                plt.plot(
+                    x[index_min:index_max],
+                    data["y"][index_min:index_max],
+                    label=data["label"],
+                )
+
+        plt.xlim(x_min, x_max)
+
+        save_plot(variable, plot_path)
+
+
+def find_relative_limit(e0_min: "float|None", e0: float, function: callable):
+    if e0_min is None:
+        e0_min = e0
+    else:
+        e0_min = function(e0_min, e0)
+    return e0_min
+
+
+def save_plot(y_type: str, plot_path: str):
+    plt.grid(color="r", linestyle=":", linewidth=1)
+    plt.xlabel("Energy (eV)")
+    plt.ylabel(Y_LABELS[y_type])
+    plt.legend()
+    plt.savefig(plot_path, format="png")
+    plt.close("all")
+
+
+if __name__ == "__main__":
+    # larch imports set this to an interactive backend, so need to change it
+    matplotlib.use("Agg")
+
+    dat_files = sys.argv[1]
+    input_values = json.load(open(sys.argv[2], "r", encoding="utf-8"))
+
+    main(dat_files.split(","), input_values["plots"])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/larch_plot.xml	Tue Nov 14 15:35:36 2023 +0000
@@ -0,0 +1,83 @@
+<tool id="larch_plot" name="Larch Plot" version="@TOOL_VERSION@+galaxy@WRAPPER_VERSION@" python_template_version="3.5" profile="22.05" license="MIT">
+    <description>plot Athena projects</description>
+    <macros>
+        <!-- version of underlying tool (PEP 440) -->
+        <token name="@TOOL_VERSION@">0.9.71</token>
+        <!-- version of this tool wrapper (integer) -->
+        <token name="@WRAPPER_VERSION@">0</token>
+        <!-- citation should be updated with every underlying tool version -->
+        <!-- typical fields to update are version, month, year, and doi -->
+        <token name="@TOOL_CITATION@">10.1088/1742-6596/430/1/012007</token>
+        <import>macros.xml</import>
+    </macros>
+    <creator>
+        <person givenName="Patrick" familyName="Austin" url="https://github.com/patrick-austin" identifier="https://orcid.org/0000-0002-6279-7823"/>
+    </creator>
+    <requirements>
+        <requirement type="package" version="@TOOL_VERSION@">xraylarch</requirement>
+        <requirement type="package" version="3.5.2">matplotlib</requirement>
+    </requirements>
+    <required_files>
+        <include type="literal" path="larch_plot.py"/>
+        <include type="literal" path="common.py"/>
+    </required_files>
+    <command detect_errors="exit_code"><![CDATA[
+        mkdir plots
+        && python '${__tool_directory__}/larch_plot.py' '$dat_files' '$inputs'
+    ]]></command>
+    <configfiles>
+        <inputs name="inputs"/>
+    </configfiles>
+    <inputs>
+        <param name="dat_files" type="data" format="prj" multiple="true" min="1" label="Athena projects" help="X-ray Absorption Spectroscopy (XAS) data, in Athena project format"/>
+        <repeat name="plots" title="Plots" min="1" default="1" help="Each additional entry will create another output plot">
+            <conditional name="variable">
+                <param name="variable" type="select" display="radio" label="Variable" help="Variable to plot on the y axis">
+                    <option value="norm" selected="true">Normalised xμ</option>
+                    <option value="dmude">Derivative of xμ</option>
+                    <option value="chir_mag">Magnitude of χ(r)</option>
+                </param>
+                <when value="norm">
+                    <expand macro="energy_limits"/>
+                </when>
+                <when value="dmude">
+                    <expand macro="energy_limits"/>
+                </when>
+                <when value="chir_mag">
+                    <param name="energy_min" type="float" label="Minimum r (ang)" optional="true" help="If set, data will be cropped below this value in angstroms."/>
+                    <param name="energy_max" type="float" label="Maximum r (ang)" optional="true" help="If set, data will be cropped above this value in angstroms."/>
+                </when>
+            </conditional>
+        </repeat>
+    </inputs>
+    <outputs>
+        <collection name="plot_collection" format="png" type="list">
+            <discover_datasets pattern="__name_and_ext__" directory="plots"/>
+        </collection>
+    </outputs>
+    <tests>
+        <test expect_num_outputs="1">
+            <param name="dat_files" value="test.prj"/>
+            <param name="variable" value="norm"/>
+            <param name="energy_format" value="absolute"/>
+            <param name="energy_min" value="7000"/>
+            <param name="variable" value="dmude"/>
+            <param name="energy_format" value="relative"/>
+            <param name="energy_max" value="10"/>
+            <output_collection name="plot_collection" type="list" count="2"/>
+        </test>
+    </tests>
+    <help><![CDATA[
+        Using Larch, read Athena project files and plot data from them.
+
+        Only Athena project files are accepted as input. If data is plaintext,
+        first load it using the Larch Athena tool.
+        All input files will appear on the same plot(s).
+        To generate multiple types of plot with the same set of files,
+        add additional sections to the form.
+    ]]></help>
+    <citations>
+        <citation type="doi">@TOOL_CITATION@</citation>
+        <citation type="doi">10.1107/S0909049505012719</citation>
+    </citations>
+</tool>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/macros.xml	Tue Nov 14 15:35:36 2023 +0000
@@ -0,0 +1,26 @@
+<macros>
+    <xml name="energy_limits">
+        <param name="energy_format" type="select" display="radio" label="Energy limits" help="Whether to limit the energy relative to the absorption edge or with absolute values.">
+            <option value="relative" selected="true">Relative</option>
+            <option value="absolute">Absolute</option>
+        </param>
+        <param name="energy_min" type="float" label="Minimum energy (eV)" optional="true" help="If set, data will be cropped below this value in electron volts."/>
+        <param name="energy_max" type="float" label="Maximum energy (eV)" optional="true" help="If set, data will be cropped above this value in electron volts."/>
+    </xml>
+    <xml name="xftf_params">
+        <param argument="kmin" type="float" value="0" min="0.0" help="Minimum k value."/>
+        <param argument="kmax" type="float" value="20" min="0.0" help="Maximum k value."/>
+        <param argument="kweight" type="float" value="2" help="Exponent for weighting spectra by raising k to this power."/>
+        <param argument="dk" type="float" value="4" help="Tapering parameter for Fourier Transform window."/>
+        <param argument="window" type="select" help="Fourier Transform window type.">
+            <option value="hanning">Hanning (cosine-squared taper)</option>
+            <option value="parzen">Parzen (linear taper)</option>
+            <option value="welch">Welch (quadratic taper)</option>
+            <option value="gaussian">Gaussian function window</option>
+            <option value="sine">Sine function window</option>
+            <option value="kaiser" selected="true">Kaiser-Bessel function-derived window</option>
+        </param>
+        <param argument="rmin" type="float" value="0.0" min="0.0" help="Minimum radial distance."/>
+        <param argument="rmax" type="float" value="10.0" min="0.0" help="Maximum radial distance."/>
+    </xml>
+</macros>
\ No newline at end of file
Binary file test-data/test.prj has changed