Mercurial > repos > muon-spectroscopy-computational-project > larch_athena
changeset 1:2b3115342fef draft
planemo upload for repository https://github.com/MaterialsGalaxy/larch-tools/tree/main/larch_athena commit 1cf6d7160497ba58fe16a51f00d088a20934eba6
author | muon-spectroscopy-computational-project |
---|---|
date | Wed, 06 Dec 2023 13:03:55 +0000 |
parents | ae2f265ecf8e |
children | a1e26990131c |
files | common.py larch_athena.py larch_athena.xml macros.xml test-data/ffi1.tabular test-data/multiple.prj |
diffstat | 6 files changed, 710 insertions(+), 169 deletions(-) [+] |
line wrap: on
line diff
--- a/common.py Tue Nov 14 15:34:40 2023 +0000 +++ b/common.py Wed Dec 06 13:03:55 2023 +0000 @@ -7,38 +7,145 @@ def get_group(athena_group: AthenaGroup, key: str = None) -> Group: + group_keys = list(athena_group._athena_groups.keys()) if key is None: - group_keys = list(athena_group._athena_groups.keys()) key = group_keys[0] - return extract_athenagroup(athena_group._athena_groups[key]) + else: + key = key.replace("-", "_") + + try: + return extract_athenagroup(athena_group._athena_groups[key]) + except KeyError as e: + raise KeyError(f"{key} not in {group_keys}") from e + + +def read_all_groups(dat_file: str, key: str = None) -> "dict[str, Group]": + # Cannot rely on do_ABC as _larch is None + athena_group = read_athena( + dat_file, + do_preedge=False, + do_bkg=False, + do_fft=False, + ) + all_groups = {} + for key in athena_group._athena_groups.keys(): + group = get_group(athena_group, key) + pre_edge_with_defaults(group=group) + xftf_with_defaults(group=group) + all_groups[key] = group + + return all_groups + + +def read_group(dat_file: str, key: str = None): + # Cannot rely on do_ABC as _larch is None + athena_group = read_athena( + dat_file, + do_preedge=False, + do_bkg=False, + do_fft=False, + ) + group = get_group(athena_group, key) + pre_edge_with_defaults(group=group) + xftf_with_defaults(group=group) + return group -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, +def pre_edge_with_defaults(group: Group, settings: dict = None): + merged_settings = {} + try: + bkg_parameters = group.athena_params.bkg + except AttributeError as e: + print(f"Cannot load group.athena_params.bkg from group:\n{e}") + bkg_parameters = None + + keys = ( + ("e0", "e0", None), + ("pre1", "pre1", None), + ("pre2", "pre2", None), + ("norm1", "nor1", None), + ("norm2", "nor2", None), + ("nnorm", "nnorm", None), + ("make_flat", "flatten", None), + ("step", "step", None), + # This cannot be read from file as it is not stored by Larch (0.9.71) + # ("nvict", "nvict", None), ) - 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 + for key, parameters_key, default in keys: + extract_attribute( + merged_settings, key, bkg_parameters, parameters_key, default + ) + + if settings: + for k, v in settings.items(): + if k == "nvict": + print( + "WARNING: `nvict` can be used for pre-edge but is not " + "saved to file, so value used will not be accessible in " + "future operations using this Athena .prj" + ) + merged_settings[k] = v + + print(f"Pre-edge normalization with {merged_settings}") + try: + pre_edge(group, **merged_settings) + except Warning as e: + raise Warning( + "Unable to perform pre-edge fitting with:\n\n" + f"energy:\n{group.energy}\n\nmu:{group.mu}\n\n" + "Consider checking the correct columns have been extracted" + ) from e + autobk(group, pre_edge_kws=merged_settings) + + +def xftf_with_defaults(group: Group, settings: dict = None): + merged_settings = {} + try: + fft_parameters = group.athena_params.fft + except AttributeError as e: + print(f"Cannot load group.athena_params.fft from group:\n{e}") + fft_parameters = None + + keys = ( + ("kmin", "kmin", 0), + ("kmax", "kmax", 20), + ("dk", "dk", 1), + ("kweight", "kw", 2), + ("kweight", "kweight", 2), + ("window", "kwindow", "kaiser"), + ) + for key, parameters_key, default in keys: + extract_attribute( + merged_settings, key, fft_parameters, parameters_key, default + ) + + if settings: + for k, v in settings.items(): + merged_settings[k] = v + + print(f"XFTF with {merged_settings}") + xftf(group, **merged_settings) + xftf_details = Group() + setattr(xftf_details, "call_args", merged_settings) + group.xftf_details = xftf_details + + +def extract_attribute( + merged_settings: dict, + key: str, + parameters_group: Group, + parameters_key: str, + default: "str|int" = None, +): + if parameters_group is not None: + try: + merged_settings[key] = getattr(parameters_group, parameters_key) + return + except AttributeError: + pass + + if default is not None: + merged_settings[key] = default def read_groups(dat_files: "list[str]", key: str = None) -> Iterable[Group]:
--- a/larch_athena.py Tue Nov 14 15:34:40 2023 +0000 +++ b/larch_athena.py Wed Dec 06 13:03:55 2023 +0000 @@ -4,7 +4,9 @@ import re import sys -from common import read_group +from common import ( + pre_edge_with_defaults, read_all_groups, read_group, xftf_with_defaults +) from larch.io import ( create_athena, @@ -14,7 +16,7 @@ set_array_labels, ) from larch.symboltable import Group -from larch.xafs import autobk, pre_edge, rebin_xafs, xftf +from larch.xafs import rebin_xafs import matplotlib import matplotlib.pyplot as plt @@ -27,13 +29,11 @@ self, energy_column: str, mu_column: str, - xftf_params: dict, data_format: str, - extract_group: str = None, + extract_group: "dict[str, str]" = None, ): self.energy_column = energy_column self.mu_column = mu_column - self.xftf_params = xftf_params self.data_format = data_format self.extract_group = extract_group @@ -72,13 +72,24 @@ self, filepath: str, is_zipped: bool = False, - ) -> "dict[str,Group]": + ) -> "tuple[dict, bool]": if is_zipped: return self.load_zipped_files() print(f"Attempting to read from {filepath}") if self.data_format == "athena": - group = read_group(filepath, self.extract_group, self.xftf_params) + if self.extract_group["extract_group"] == "single": + group = read_group(filepath, self.extract_group["group_name"]) + return {"out": group} + elif self.extract_group["extract_group"] == "multiple": + groups = {} + for repeat in self.extract_group["multiple"]: + name = repeat["group_name"] + groups[name] = read_group(filepath, name) + return groups + else: + return read_all_groups(filepath) + else: # Try ascii anyway try: @@ -90,7 +101,9 @@ except (UnicodeDecodeError, TypeError): # Indicates this isn't plaintext, try h5 group = self.load_h5(filepath) - return {"out": group} + pre_edge_with_defaults(group) + xftf_with_defaults(group) + return {"out": group} def load_ascii(self, dat_file): with open(dat_file) as f: @@ -156,27 +169,27 @@ if "energy" in labels: print("'energy' present in column headers") - elif self.energy_column is not None: + elif self.energy_column: if self.energy_column.lower() in labels: labels[labels.index(self.energy_column.lower())] = "energy" else: raise ValueError(f"{self.energy_column} not found in {labels}") else: for i, label in enumerate(labels): - if label == "col1" or label.endswith("energy"): + if label in ("col1", "ef") or label.endswith("energy"): labels[i] = "energy" break if "mu" in labels: print("'mu' present in column headers") - elif self.mu_column is not None: + elif self.mu_column: if self.mu_column.lower() in labels: labels[labels.index(self.mu_column.lower())] = "mu" else: raise ValueError(f"{self.mu_column} not found in {labels}") else: for i, label in enumerate(labels): - if label in ["col2", "xmu", "lni0it", "ffi0"]: + if label in ["col2", "xmu", "lni0it", "ffi0", "ff/i1"]: labels[i] = "mu" break @@ -189,29 +202,24 @@ def calibrate_energy( xafs_group: Group, - energy_0: float, - energy_min: float, - energy_max: float, - energy_format: str, + calibration_e0: float = None, + energy_min: float = None, + energy_max: float = None, ): - if energy_0 is not None: - print(f"Recalibrating energy edge from {xafs_group.e0} to {energy_0}") - xafs_group.energy = xafs_group.energy + energy_0 - xafs_group.e0 - xafs_group.e0 = energy_0 + if calibration_e0 is not None: + print(f"Recalibrating edge from {xafs_group.e0} to {calibration_e0}") + xafs_group.energy = xafs_group.energy + calibration_e0 - xafs_group.e0 + xafs_group.e0 = calibration_e0 if not (energy_min or energy_max): return xafs_group - if energy_min: - if energy_format == "relative": - energy_min += xafs_group.e0 + if energy_min is not None: index_min = np.searchsorted(xafs_group.energy, energy_min) else: index_min = 0 - if energy_max: - if energy_format == "relative": - energy_max += xafs_group.e0 + if energy_max is not None: index_max = np.searchsorted(xafs_group.energy, energy_max) else: index_max = len(xafs_group.energy) @@ -240,81 +248,57 @@ def main( xas_data: Group, - input_values: dict, + do_calibrate: bool, + calibrate_settings: dict, + do_rebin: bool, + do_pre_edge: bool, + pre_edge_settings: dict, + do_xftf: bool, + xftf_settings: dict, + plot_graph: bool, + annotation: str, path_key: str = "out", ): - energy_0 = input_values["variables"]["energy_0"] - if energy_0 is None and hasattr(xas_data, "e0"): - energy_0 = xas_data.e0 - - energy_format = input_values["variables"]["energy_format"] - pre1 = input_values["variables"]["pre1"] - pre2 = input_values["variables"]["pre2"] - pre1 = validate_pre(pre1, energy_0, energy_format) - pre2 = validate_pre(pre2, energy_0, energy_format) - - pre_edge( - energy=xas_data.energy, - mu=xas_data.mu, - group=xas_data, - e0=energy_0, - pre1=pre1, - pre2=pre2, - ) + if do_calibrate: + print(f"Calibrating energy with {calibrate_settings}") + xas_data = calibrate_energy(xas_data, **calibrate_settings) + # After re-calibrating, will need to redo pre-edge with new range + do_pre_edge = True - energy_min = input_values["variables"]["energy_min"] - energy_max = input_values["variables"]["energy_max"] - xas_data = calibrate_energy( - xas_data, - energy_0, - energy_min, - energy_max, - energy_format=energy_format, - ) + if do_rebin: + print("Re-binning data") + rebin_xafs( + energy=xas_data.energy, + mu=xas_data.mu, + group=xas_data, + **pre_edge_settings, + ) + xas_data = xas_data.rebinned + # After re-bin, will need to redo pre-edge + do_pre_edge = True - if input_values["rebin"]: - print(xas_data.energy, xas_data.mu) - rebin_xafs(energy=xas_data.energy, mu=xas_data.mu, group=xas_data) - xas_data = xas_data.rebinned - pre_edge(energy=xas_data.energy, mu=xas_data.mu, group=xas_data) + if do_pre_edge: + pre_edge_with_defaults(xas_data, pre_edge_settings) - try: - autobk(xas_data) - except ValueError as e: - raise ValueError( - f"autobk failed with energy={xas_data.energy}, mu={xas_data.mu}.\n" - "This may occur if the edge is not included in the above ranges." - ) from e - xftf(xas_data, **xftf_params) + if do_xftf: + xftf_with_defaults(xas_data, xftf_settings) - if input_values["plot_graph"]: + if plot_graph: plot_edge_fits(f"edge/{path_key}.png", xas_data) plot_flattened(f"flat/{path_key}.png", xas_data) plot_derivative(f"derivative/{path_key}.png", xas_data) xas_project = create_athena(f"prj/{path_key}.prj") xas_project.add_group(xas_data) - if input_values["annotation"]: + if annotation: group = next(iter(xas_project.groups.values())) - group.args["annotation"] = input_values["annotation"] + group.args["annotation"] = annotation xas_project.save() # Ensure that we do not run out of memory when running on large zips gc.collect() -def validate_pre(pre, energy_0, energy_format): - if pre is not None and energy_format == "absolute": - if energy_0 is None: - raise ValueError( - "Edge energy must be set manually or be present in the " - "existing Athena project if using absolute format." - ) - pre -= energy_0 - - return pre - - def plot_derivative(plot_path: str, xafs_group: Group): plt.figure() plt.plot(xafs_group.energy, xafs_group.dmude) @@ -363,9 +347,8 @@ ) else: is_zipped = False - xftf_params = input_values["variables"]["xftf"] + extract_group = None - if "extract_group" in input_values["merge_inputs"]["format"]: extract_group = input_values["merge_inputs"]["format"]["extract_group"] @@ -379,7 +362,6 @@ reader = Reader( energy_column=energy_column, mu_column=mu_column, - xftf_params=xftf_params, data_format=data_format, extract_group=extract_group, ) @@ -388,9 +370,35 @@ merge_inputs=merge_inputs, is_zipped=is_zipped, ) + + calibrate_items = input_values["processing"]["calibrate"].items() + calibrate_settings = {k: v for k, v in calibrate_items if v is not None} + do_calibrate = calibrate_settings.pop("calibrate") == "true" + + do_rebin = input_values["processing"].pop("rebin") + + pre_edge_items = input_values["processing"]["pre_edge"].items() + pre_edge_settings = {k: v for k, v in pre_edge_items if v is not None} + do_pre_edge = pre_edge_settings.pop("pre_edge") == "true" + + xftf_items = input_values["processing"]["xftf"].items() + xftf_settings = {k: v for k, v in xftf_items if v is not None} + do_xftf = xftf_settings.pop("xftf") == "true" + + plot_graph = input_values["plot_graph"] + annotation = input_values["annotation"] + for key, group in keyed_data.items(): main( group, - input_values=input_values, + do_calibrate=do_calibrate, + calibrate_settings=calibrate_settings, + do_rebin=do_rebin, + do_pre_edge=do_pre_edge, + pre_edge_settings=pre_edge_settings, + do_xftf=do_xftf, + xftf_settings=xftf_settings, + plot_graph=plot_graph, + annotation=annotation, path_key=key, )
--- a/larch_athena.xml Tue Nov 14 15:34:40 2023 +0000 +++ b/larch_athena.xml Wed Dec 06 13:03:55 2023 +0000 @@ -4,7 +4,7 @@ <!-- 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> + <token name="@WRAPPER_VERSION@">1</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> @@ -15,11 +15,26 @@ </param> </xml> <xml name="extract_group"> - <param name="extract_group" type="text" optional="true" label="Extract group" help="Which group to extract and process from the Athena project (will use first group in file if unset)"/> + <conditional name="extract_group"> + <param name="extract_group" type="select" label="Group extraction" help="Method of handling group extraction. Extracting all or multiple named groups will result in multiple outputs, unless merging groups is also true."> + <option value="single" selected="true">Extract single</option> + <option value="multiple">Extract multiple</option> + <option value="all">Extract all</option> + </param> + <when value="single"> + <param name="group_name" type="text" optional="true" label="Group label" help="Which group to extract and process from the Athena project (will use first group in file if unset)"/> + </when> + <when value="multiple"> + <repeat name="multiple" min="1" default="1" title="Groups"> + <param name="group_name" type="text" label="Group label" help="Which group to extract and process from the Athena project (will use first group in file if unset)"/> + </repeat> + </when> + <when value="all"/> + </conditional> </xml> <xml name="columns"> - <param name="energy_column" type="text" optional="true" label="Energy column" help="If set, this column we be used as 'energy'. Otherwise, will identify columns ending with 'energy' or labelled 'col1'."/> - <param name="mu_column" type="text" optional="true" label="μ column" help="If set, this column we be used as 'mu'. Otherwise, will identify the first column labelled as either 'col2', 'xmu', 'lni0it' or 'FFI0'."/> + <param name="energy_column" type="text" optional="true" label="Energy column" help="If set, this column we be used as 'energy'. Otherwise, will identify the first column ending with 'energy' or labelled 'col1' 'Ef'."/> + <param name="mu_column" type="text" optional="true" label="μ column" help="If set, this column we be used as 'mu'. Otherwise, will identify the first column labelled as either 'col2', 'xmu', 'lni0it', 'FFI0' or 'FF/I1'."/> </xml> <xml name="is_zipped"> <param name="is_zipped" type="select" display="radio" label="Inputs Zipped" help="Whether plaintext input files are zipped together into one directory, or not."> @@ -40,6 +55,7 @@ </requirements> <required_files> <include type="literal" path="larch_athena.py"/> + <include type="literal" path="common.py"/> </required_files> <command detect_errors="exit_code"><![CDATA[ mkdir prj edge flat derivative @@ -111,16 +127,55 @@ </when> </conditional> <param name="annotation" type="text" label="Annotation" optional="true" help="If set, will annotate the output project(s) with this string. This will be used to generate legends when plotting data."/> - <section name="variables" title="Processing Options"> - <param name="energy_0" type="float" label="Edge energy (eV)" optional="true" help="If set, data will be calibrated so that the edge occurs at this energy (after merging, if relevant)."/> - <expand macro="energy_limits"/> - <param name="pre1" type="float" label="Pre-edge fit lower energy (eV)" optional="true" help="The lower edge of the region used for the pre-edge fitting, if unset will either use existing value or a default based on the data."/> - <param name="pre2" type="float" label="Pre-edge fit upper energy (eV)" optional="true" help="The upper edge of the region used for the pre-edge fitting, if unset will either use existing value or a default based on the data."/> - <section name="xftf" title="XFTF"> - <expand macro="xftf_params"/> - </section> + <section name="processing" expanded="true" title="Processing Options" help="By default, the following processing steps will be performed either with default values, or those contained in the input Athena project (if used). If specified here, these values will be used instead for process in sequence."> + <conditional name="calibrate"> + <param name="calibrate" type="select" label="Calibrate energy" help="If set, will shift the spectrum so that its (automatically determined) edge occurs at the specified value, and any values outside the range will be discarded."> + <option value="" selected="true">False</option> + <option value="true">True</option> + </param> + <when value=""/> + <when value="true"> + <param name="calibration_e0" type="float" label="Calibration energy (eV)" optional="true" help="If set, data will be calibrated so that the edge occurs at this energy (after merging, if relevant). Note that this is different from specifying E0 in the pre-edge normalization, as this will the x-axis of the data (so that the Nth x point will no longer align with the Nth y point)."/> + <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 (after re-calibrating)."/> + <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 (after re-calibrating)."/> + </when> + </conditional> + <param name="rebin" type="boolean" label="Re-bin data" help="Whether to re-bin along the energy axis to automatically ensure appropriate levels of precision in the pre-edge, near-edge and extended region of the spectrum."/> + <conditional name="pre_edge"> + <param name="pre_edge" type="select" label="Pre-edge normalization" help="If set, will (re)perform forward pre-edge normalization using provided values."> + <option value="" selected="true">False</option> + <option value="true">True</option> + </param> + <when value=""/> + <when value="true"> + <param argument="e0" type="float" label="Edge energy (eV)" optional="true" help="If set, normalization will use this as the location of the edge rather than automatically determining it."/> + <param argument="pre1" type="float" max="0" label="Pre-edge fit lower energy (eV)" optional="true" help="The lower end of the region used for the pre-edge fitting, relative to the edge energy (and therefore negative)."/> + <param argument="pre2" type="float" max="0" label="Pre-edge fit upper energy (eV)" optional="true" help="The upper end of the region used for the pre-edge fitting, relative to the edge energy (and therefore negative)."/> + <param argument="nvict" type="integer" label="Energy exponent" optional="true" help="Edge fitting will be performed against μ*E**n where n is defined here. This is 0 by default."/> + </when> + </conditional> + <conditional name="xftf"> + <param name="xftf" type="select" label="XFTF" help="If set, will (re)perform forward Fourier Transform using provided values."> + <option value="" selected="true">False</option> + <option value="true">True</option> + </param> + <when value=""/> + <when value="true"> + <param argument="kmin" type="float" optional="true" min="0.0" help="Minimum k value."/> + <param argument="kmax" type="float" optional="true" min="0.0" help="Maximum k value."/> + <param argument="kweight" type="float" optional="true" help="Exponent for weighting spectra by raising k to this power."/> + <param argument="dk" type="float" optional="true" help="Tapering parameter for Fourier Transform window."/> + <param argument="window" type="select" optional="true" 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">Kaiser-Bessel function-derived window</option> + </param> + </when> + </conditional> </section> - <param name="rebin" type="boolean" label="Re-bin data" help="Whether to re-bin along the energy axis to ensure appropriate levels of precision in the pre-edge, near-edge and extended region of the spectrum."/> <param name="plot_graph" type="boolean" label="Plot graph" help="Whether to plot the pre/post edge fitting and the normalised xμ data."/> <param name="zip_outputs" type="boolean" label="Zip outputs" help="Whether to zip all outputs into one dataset."/> </inputs> @@ -129,53 +184,53 @@ <data name="out_zip" format="zip" from_work_dir="out_zip.zip" label="Zipped Athena project(s) ${annotation} ${on_string}"> <filter>zip_outputs</filter> </data> - <!-- Single outputs of differnt types if merging, or not using a zip --> + <!-- Single outputs of different types if merging, or not using a zip --> <data name="athena_project_file" format="prj" from_work_dir="prj/out.prj" label="Athena project ${annotation} ${on_string}"> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "")</filter> + <filter>not (merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single"))</filter> </data> <data name="edge_plot" format="png" from_work_dir="edge/out.png" label="Edge fitting ${annotation} ${on_string}"> <filter>plot_graph</filter> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "")</filter> + <filter>not (merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single"))</filter> </data> <data name="flat_plot" format="png" from_work_dir="flat/out.png" label="Flattened plot ${annotation} ${on_string}"> <filter>plot_graph</filter> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "")</filter> + <filter>not (merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single"))</filter> </data> <data name="derivative_plot" format="png" from_work_dir="derivative/out.png" label="Derivative plot ${annotation} ${on_string}"> <filter>plot_graph</filter> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] or merge_inputs["format"]["dat_file"].extension != "zip"</filter> - <filter>merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "")</filter> + <filter>not (merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single"))</filter> </data> - <!-- Directories of outputs if using single, non-merged zip as input --> + <!-- Directories of outputs if using single, non-merged zip as input or extracting multiple/all Athena groups --> <collection name="athena_project_file_collection" format="prj" type="list" label="Athena projects ${annotation} ${on_string}"> <discover_datasets pattern="__name_and_ext__" directory="prj"/> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]</filter> + <filter>merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single")</filter> </collection> <collection name="edge_plot_collection" format="png" type="list" label="Edge fittings ${annotation} ${on_string}"> <discover_datasets pattern="__name_and_ext__" directory="edge"/> <filter>plot_graph</filter> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]</filter> + <filter>merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single")</filter> </collection> <collection name="flat_plot_collection" format="png" type="list" label="Flattened plots ${annotation} ${on_string}"> <discover_datasets pattern="__name_and_ext__" directory="flat"/> <filter>plot_graph</filter> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]</filter> + <filter>merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single")</filter> </collection> <collection name="derivative_plot_collection" format="png" type="list" label="Derivative plots ${annotation} ${on_string}"> <discover_datasets pattern="__name_and_ext__" directory="derivative"/> <filter>plot_graph</filter> <filter>not zip_outputs</filter> - <filter>merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]</filter> + <filter>merge_inputs["merge_inputs"] == "" and (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"]) or (merge_inputs["format"]["format"] == "athena" and merge_inputs["format"]["extract_group"]["extract_group"] != "single")</filter> </collection> </outputs> <tests> + <!-- 1 --> <test expect_num_outputs="1"> <param name="dat_file" value="test.xmu"/> <output name="athena_project_file"> @@ -184,6 +239,7 @@ </assert_contents> </output> </test> + <!-- 2 --> <test expect_num_outputs="1"> <param name="dat_file" value="ffi0.tabular"/> <output name="athena_project_file"> @@ -192,12 +248,22 @@ </assert_contents> </output> </test> + <!-- 3 --> + <test expect_num_outputs="1"> + <param name="dat_file" value="ffi1.tabular"/> + <output name="athena_project_file"> + <assert_contents> + <has_size value="4400" delta="100"/> + </assert_contents> + </output> + </test> + <!-- 4 --> <test expect_num_outputs="4"> <param name="dat_file" value="test.xmu"/> <param name="plot_graph" value="true"/> <output name="athena_project_file"> <assert_contents> - <has_size value="5405" delta="10"/> + <has_size value="5400" delta="100"/> </assert_contents> </output> <output name="edge_plot"> @@ -216,6 +282,7 @@ </assert_contents> </output> </test> + <!-- 5 --> <test expect_num_outputs="4"> <param name="is_zipped" value="true"/> <param name="dat_file" value="test.zip"/> @@ -225,6 +292,7 @@ <output_collection name="flat_plot_collection" type="list" count="2"/> <output_collection name="derivative_plot_collection" type="list" count="2"/> </test> + <!-- 6 --> <test expect_num_outputs="1"> <param name="is_zipped" value="true"/> <param name="dat_file" value="h5.zip"/> @@ -236,9 +304,10 @@ </assert_contents> </output> </test> + <!-- 7 --> <test expect_num_outputs="1"> <param name="dat_file" value="test.xmu"/> - <param name="energy_format" value="absolute"/> + <param name="calibrate" value="true"/> <param name="energy_min" value="7000"/> <output name="athena_project_file"> <assert_contents> @@ -246,9 +315,10 @@ </assert_contents> </output> </test> + <!-- 8 --> <test expect_num_outputs="4"> <param name="dat_file" value="test.xmu"/> - <param name="energy_format" value="absolute"/> + <param name="calibrate" value="true"/> <param name="energy_min" value="7000"/> <param name="energy_max" value="7200"/> <param name="plot_graph" value="true"/> @@ -259,32 +329,34 @@ </output> <output name="edge_plot"> <assert_contents> - <has_size value="44430" delta="10"/> + <has_size value="44900" delta="100"/> </assert_contents> </output> <output name="flat_plot"> <assert_contents> - <has_size value="37310" delta="10"/> + <has_size value="39400" delta="100"/> </assert_contents> </output> <output name="derivative_plot"> <assert_contents> - <has_size value="46390" delta="10"/> + <has_size value="45900" delta="100"/> </assert_contents> </output> </test> + <!-- 9 --> <test expect_num_outputs="1"> <param name="dat_file" value="test.xmu"/> - <param name="energy_format" value="absolute"/> - <param name="energy_0" value="7050"/> + <param name="calibrate" value="true"/> + <param name="calibration_e0" value="7050"/> <param name="energy_min" value="7000"/> <param name="energy_max" value="7200"/> <output name="athena_project_file"> <assert_contents> - <has_size value="3300" delta="50"/> + <has_size value="3600" delta="100"/> </assert_contents> </output> </test> + <!-- 10 --> <test expect_num_outputs="1"> <param name="dat_file" value="test.xmu"/> <param name="rebin" value="true"/> @@ -294,6 +366,7 @@ </assert_contents> </output> </test> + <!-- 11 --> <test expect_num_outputs="1"> <param name="merge_inputs" value="true"/> <param name="dat_file" value="262875_PtSn_OCO_Abu_1.nxs,262876_PtSn_OCO_Abu_2.nxs"/> @@ -303,6 +376,7 @@ </assert_contents> </output> </test> + <!-- 12 --> <test expect_num_outputs="1"> <param name="merge_inputs" value="true"/> <param name="is_zipped" value="true"/> @@ -313,6 +387,7 @@ </assert_contents> </output> </test> + <!-- 13 --> <test expect_num_outputs="1"> <param name="format" value="athena"/> <param name="dat_file" value="test.prj"/> @@ -322,6 +397,22 @@ </assert_contents> </output> </test> + <!-- 14: Extract multiple groups from Athena .prj --> + <test expect_num_outputs="1"> + <param name="format" value="athena"/> + <param name="extract_group" value="multiple"/> + <param name="group_name" value="merge"/> + <param name="group_name" value="d__Ref_PtSn_OC_MERGE_CALIBRATE"/> + <param name="dat_file" value="multiple.prj"/> + <output_collection name="athena_project_file_collection" type="list" count="2"/> + </test> + <!-- 15: Extract all groups from Athena .prj --> + <test expect_num_outputs="1"> + <param name="format" value="athena"/> + <param name="extract_group" value="all"/> + <param name="dat_file" value="multiple.prj"/> + <output_collection name="athena_project_file_collection" type="list" count="9"/> + </test> </tests> <help><![CDATA[ Using Larch, create an Athena project file from the input X-ray Absorption Fine Structure (XAFS) data file.
--- a/macros.xml Tue Nov 14 15:34:40 2023 +0000 +++ b/macros.xml Wed Dec 06 13:03:55 2023 +0000 @@ -1,26 +1,6 @@ <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 name="plot_limits_energy"> + <param name="x_limit_min" type="float" label="Minimum plot energy (eV)" optional="true" help="If set, plot will be limited to this value on the x axis."/> + <param name="x_limit_max" type="float" label="Maximum plot energy (eV)" optional="true" help="If set, plot will be limited to this value on the x axis."/> </xml> </macros> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/ffi1.tabular Wed Dec 06 13:03:55 2023 +0000 @@ -0,0 +1,355 @@ +# Energy FF/I1 Time + 6911.8277 0.80926541 272002.00 + 6916.9236 0.80418730 270032.00 + 6921.7638 0.79959074 268827.00 + 6926.8750 0.79459529 267514.00 + 6931.7907 0.79004613 255214.00 + + 6962.0000 0.78791063 305150.00 + 6972.0000 0.77475191 306445.00 + 6982.0000 0.76169076 306446.00 + 6992.0000 0.74992551 306744.00 + 7002.0000 0.73660315 306246.00 + 7012.0000 0.72423404 306358.00 + 7022.0000 0.71196509 306309.00 + 7032.0000 0.70002723 306019.00 + 7042.0000 0.68735767 306529.00 + 7052.0000 0.67439453 306124.00 + 7062.0000 0.66235517 306188.00 + 7072.0000 0.65022361 306119.00 + 7082.0000 0.63942705 306143.00 + 7092.0000 0.62824650 306098.00 + 7092.5000 0.62753795 305825.00 + 7093.0000 0.62748380 305756.00 + 7093.5000 0.62785219 305745.00 + 7094.0000 0.62636441 305717.00 + 7094.5000 0.62575793 305670.00 + 7095.0000 0.62551244 305666.00 + 7095.5000 0.62515947 305631.00 + 7096.0000 0.62492947 305585.00 + 7096.5000 0.62367544 305536.00 + 7097.0000 0.62332504 305539.00 + 7097.5000 0.62259547 305510.00 + 7098.0000 0.62252464 305466.00 + 7098.5000 0.62240279 305494.00 + 7099.0000 0.62172416 305432.00 + 7099.5000 0.62098768 305503.00 + 7100.0000 0.62118707 305402.00 + 7100.5000 0.62045272 305414.00 + 7101.0000 0.62040785 305391.00 + 7101.5000 0.62002332 305400.00 + 7102.0000 0.61932445 305952.00 + 7102.5000 0.61954721 305420.00 + 7103.0000 0.61934375 304860.00 + 7103.5000 0.61907141 305180.00 + 7104.0000 0.61843263 305180.00 + 7104.5000 0.61879967 305435.00 + 7105.0000 0.61854579 305144.00 + 7105.5000 0.61837948 305045.00 + 7106.0000 0.61887282 304943.00 + 7106.5000 0.61837848 305015.00 + 7107.0000 0.61844121 305023.00 + 7107.5000 0.61908174 304990.00 + 7108.0000 0.62025344 305117.00 + 7108.5000 0.62083284 305305.00 + 7109.0000 0.62279082 304852.00 + 7109.5000 0.62484776 304938.00 + 7110.0000 0.63029578 305214.00 + 7110.5000 0.63827614 304831.00 + 7111.0000 0.65354125 304668.00 + 7111.5000 0.67171017 304489.00 + 7112.0000 0.68465719 304804.00 + 7112.5000 0.68977450 304821.00 + 7113.0000 0.68982223 304700.00 + 7113.5000 0.68880150 304652.00 + 7114.0000 0.68631667 304907.00 + 7114.5000 0.68636382 304536.00 + 7115.0000 0.69345881 305540.00 + 7115.5000 0.71368054 306249.00 + 7116.0000 0.75470012 306100.00 + 7116.5000 0.82334644 305917.00 + 7117.0000 0.91897755 306536.00 + 7117.5000 1.0048919 306925.00 + 7118.0000 1.0613446 306741.00 + 7118.5000 1.1171460 306475.00 + 7119.0000 1.1598287 306428.00 + 7119.5000 1.1845153 306460.00 + 7120.0000 1.1839175 306450.00 + 7120.5000 1.1705836 306582.00 + 7121.0000 1.1532435 306359.00 + 7121.5000 1.1455536 306364.00 + 7122.0000 1.1474359 306349.00 + 7122.5000 1.1522733 306255.00 + 7123.0000 1.1570854 306266.00 + 7123.5000 1.1609012 306230.00 + 7124.0000 1.1633654 306227.00 + 7124.5000 1.1626865 306371.00 + 7125.0000 1.1609214 306051.00 + 7125.5000 1.1630846 306141.00 + 7126.0000 1.1694208 306113.00 + 7126.5000 1.1791744 306099.00 + 7127.0000 1.1920499 306090.00 + 7127.5000 1.2050365 306010.00 + 7128.0000 1.2176110 306003.00 + 7128.5000 1.2307236 305954.00 + 7129.0000 1.2447142 305942.00 + 7129.5000 1.2590796 306047.00 + 7130.0000 1.2750382 305942.00 + 7130.5000 1.2916155 305940.00 + 7131.0000 1.3069910 305777.00 + 7131.5000 1.3214558 305771.00 + 7132.0000 1.3316754 305988.00 + 7132.8830 1.3507457 305946.00 + 7133.7850 1.3673679 305893.00 + 7134.7070 1.3796873 305719.00 + 7135.6470 1.3878931 305734.00 + 7136.6060 1.3912805 305686.00 + 7137.5840 1.3911931 305808.00 + 7138.5820 1.3880279 305655.00 + 7139.5990 1.3853474 305680.00 + 7140.6340 1.3831500 305655.00 + 7141.6890 1.3775299 305647.00 + 7142.7630 1.3673370 305546.00 + 7143.8560 1.3502223 305620.00 + 7144.9680 1.3336271 305565.00 + 7146.0990 1.3195536 305942.00 + 7147.2490 1.3074943 305369.00 + 7148.4180 1.2960234 305508.00 + 7149.6060 1.2858296 305329.00 + 7150.8140 1.2749358 305424.00 + 7152.0410 1.2649495 305227.00 + 7153.2860 1.2568554 305483.00 + 7154.5510 1.2512398 305317.00 + 7155.8340 1.2450083 305327.00 + 7157.1370 1.2358616 305362.00 + 7158.4590 1.2228915 305483.00 + 7159.8000 1.2062374 305185.00 + 7161.1600 1.1928682 305200.00 + 7162.5390 1.1842737 305144.00 + 7163.9370 1.1854668 305132.00 + 7165.3540 1.1935051 305025.00 + 7166.7910 1.2026287 305071.00 + 7168.2460 1.2093646 304988.00 + 7169.7200 1.2123004 304957.00 + 7171.2140 1.2128140 303977.00 + 7172.7260 1.2152670 306335.00 + 7174.2580 1.2206383 305331.00 + 7175.8090 1.2263235 305180.00 + 7177.3780 1.2348007 304691.00 + 7178.9670 1.2429421 304825.00 + 7180.5750 1.2486921 304819.00 + 7182.2030 1.2524190 304876.00 + 7183.8490 1.2555733 304881.00 + 7185.5140 1.2605700 304902.00 + 7187.1980 1.2658377 304750.00 + 7188.9010 1.2695672 304618.00 + 7190.6240 1.2740295 304729.00 + 7192.3650 1.2803476 304624.00 + 7194.1260 1.2881666 304796.00 + 7195.9060 1.2964693 304913.00 + 7197.7050 1.3028079 304714.00 + 7199.5220 1.3047468 304745.00 + 7201.3590 1.2989422 304572.00 + 7203.2150 1.2811419 304614.00 + 7205.0900 1.2574551 304650.00 + 7206.9840 1.2349254 304423.00 + 7208.8970 1.2149769 304251.00 + 7210.8300 1.1972301 304339.00 + 7212.7810 1.1791903 304465.00 + 7214.7510 1.1614710 304344.00 + 7216.7410 1.1469665 304357.00 + 7218.7500 1.1337012 304283.00 + 7220.7770 1.1251983 304310.00 + 7222.8240 1.1212105 304357.00 + 7224.8900 1.1226870 304315.00 + 7226.9750 1.1282596 304319.00 + 7229.0790 1.1361879 304265.00 + 7231.2020 1.1424448 304222.00 + 7233.3440 1.1466808 304141.00 + 7235.5050 1.1511667 304231.00 + 7237.6850 1.1551194 304163.00 + 7239.8850 1.1601517 304198.00 + 7242.1030 1.1647366 304019.00 + 7244.3410 1.1695266 304007.00 + 7246.5970 1.1755328 304050.00 + 7248.8730 1.1793338 303881.00 + 7251.1670 1.1781583 304021.00 + 7253.4810 1.1690464 303919.00 + 7255.8140 1.1563788 303971.00 + 7258.1660 1.1441121 303951.00 + 7260.5370 1.1370528 304123.00 + 7262.9270 1.1358182 303754.00 + 7265.3360 1.1375476 303422.00 + 7267.7650 1.1418590 304213.00 + 7270.2120 1.1460955 304372.00 + 7272.6790 1.1475066 303800.00 + 7275.1640 1.1464166 303768.00 + 7277.6680 1.1414081 303769.00 + 7280.1920 1.1335102 303936.00 + 7282.7350 1.1245373 303644.00 + 7285.2970 1.1166967 304254.00 + 7287.8770 1.1106422 305223.00 + 7290.4780 1.1053995 305548.00 + 7293.0970 1.0989324 305571.00 + 7295.7350 1.0898640 305599.00 + 7298.3920 1.0760697 305554.00 + 7301.0680 1.0625112 305441.00 + 7303.7640 1.0518639 304737.00 + 7306.4780 1.0452685 306215.00 + 7309.2110 1.0417105 305425.00 + 7311.9640 1.0391516 305631.00 + 7314.7360 1.0350223 305492.00 + 7317.5260 1.0307148 305331.00 + 7320.3360 1.0290354 305591.00 + 7323.1650 1.0291306 305413.00 + 7326.0130 1.0334814 305373.00 + 7328.8800 1.0392331 305099.00 + 7331.7660 1.0438424 305523.00 + 7334.6710 1.0471145 305074.00 + 7337.5960 1.0476086 305182.00 + 7340.5390 1.0452525 305300.00 + 7343.5010 1.0386325 305317.00 + 7346.4830 1.0312056 305293.00 + 7349.4830 1.0234727 305162.00 + 7352.5030 1.0164420 304986.00 + 7355.5420 1.0108031 304917.00 + 7358.6000 1.0079450 305066.00 + 7361.6760 1.0071789 305087.00 + 7364.7720 1.0058498 304731.00 + 7367.8870 1.0018487 304884.00 + 7371.0210 0.99480756 305111.00 + 7374.1750 0.98681002 304985.00 + 7377.3470 0.97984890 304910.00 + 7380.5380 0.97353699 304699.00 + 7383.7490 0.96852948 304984.00 + 7386.9780 0.96429334 304841.00 + 7390.2270 0.96072809 304467.00 + 7393.4940 0.95802094 304650.00 + 7396.7810 0.95230605 304697.00 + 7400.0870 0.94351175 304742.00 + 7403.4120 0.93363091 304816.00 + 7406.7550 0.92545595 304658.00 + 7410.1190 0.92119926 304605.00 + 7413.5000 0.91918832 303795.00 + 7416.9020 0.91651349 305304.00 + 7420.3220 0.91338736 304548.00 + 7423.7610 0.90989200 304397.00 + 7427.2200 0.90467023 304707.00 + 7430.6970 0.89954758 304458.00 + 7434.1940 0.89577218 304310.00 + 7437.7090 0.89366937 304338.00 + 7441.2440 0.89233424 304342.00 + 7444.7980 0.89109983 304576.00 + 7448.3710 0.88991984 304397.00 + 7451.9620 0.89021992 304464.00 + 7455.5740 0.88787942 304333.00 + 7459.2040 0.88208656 304131.00 + 7462.8530 0.87531841 304376.00 + 7466.5210 0.87040248 304297.00 + 7470.2080 0.86516782 304048.00 + 7473.9150 0.85785170 304975.00 + 7477.6400 0.85054938 305708.00 + 7481.3850 0.84453901 306082.00 + 7485.1480 0.83863201 305961.00 + 7488.9310 0.83371670 306201.00 + 7492.7330 0.82904991 306134.00 + 7496.5540 0.82459446 306039.00 + 7500.3940 0.82079844 305977.00 + 7504.2530 0.81677576 305156.00 + 7508.1310 0.81178911 306748.00 + 7512.0280 0.80667240 306054.00 + 7515.9440 0.80196850 305949.00 + 7519.8790 0.79709432 305906.00 + 7523.8340 0.79034294 305935.00 + 7527.8070 0.78287009 305891.00 + 7531.8000 0.77566164 305816.00 + 7535.8120 0.77172412 305895.00 + 7539.8420 0.76918155 305839.00 + 7543.8920 0.76588805 305840.00 + 7547.9610 0.76149338 305863.00 + 7552.0490 0.75668300 305740.00 + 7556.1560 0.75093523 305560.00 + 7560.2820 0.74539760 305668.00 + 7564.4270 0.74088376 305785.00 + 7568.5910 0.73831944 305684.00 + 7572.7740 0.73529922 305582.00 + 7576.9770 0.73187551 305523.00 + 7581.1980 0.72922440 305558.00 + 7585.4390 0.72676436 305647.00 + 7589.6980 0.72359612 305208.00 + 7593.9770 0.71807714 306038.00 + 7598.2750 0.71252104 305315.00 + 7602.5920 0.70549579 305573.00 + 7606.9280 0.69954396 305378.00 + 7611.2830 0.69265029 305425.00 + 7615.6570 0.68689223 305488.00 + 7620.0500 0.68092659 305297.00 + 7624.4620 0.67499882 305001.00 + 7628.8940 0.66889046 305246.00 + 7633.3440 0.66341014 305391.00 + 7637.8130 0.65798296 305277.00 + 7642.3020 0.65352747 305129.00 + 7646.8100 0.64842668 305185.00 + 7651.3360 0.64433064 305107.00 + 7655.8820 0.64130624 304968.00 + 7660.4470 0.63726602 303292.00 + 7665.0300 0.63282645 306701.00 + 7669.6340 0.62771419 304931.00 + 7674.2550 0.62136047 304917.00 + 7678.8960 0.61572914 304978.00 + 7683.5570 0.61094428 305007.00 + 7688.2360 0.60604922 304909.00 + 7692.9350 0.60062272 304867.00 + 7697.6520 0.59482509 304843.00 + 7702.3890 0.58954937 304732.00 + 7707.1440 0.58505148 304761.00 + 7711.9190 0.58034243 304780.00 + 7716.7120 0.57641028 304730.00 + 7721.5250 0.57240859 304752.00 + 7726.3570 0.56757710 304652.00 + 7731.2080 0.56298530 304949.00 + 7736.0780 0.55790407 301749.00 + 7740.9670 0.55415072 309843.00 + 7745.8750 0.55025596 306494.00 + 7750.8030 0.54458907 306086.00 + 7755.7500 0.53968840 306137.00 + 7760.7150 0.53400917 306150.00 + 7765.6990 0.52848485 306231.00 + 7770.7030 0.52243506 306178.00 + 7775.7260 0.51730921 305604.00 + 7780.7670 0.51119667 306396.00 + 7785.8280 0.50502129 306122.00 + 7790.9080 0.49915279 306044.00 + 7796.0070 0.49353357 305959.00 + 7801.1250 0.48866156 305944.00 + 7806.2620 0.48323724 305753.00 + 7811.4180 0.47782882 305897.00 + 7816.5940 0.47305934 305849.00 + 7821.7880 0.46837192 305834.00 + 7827.0010 0.46392860 305216.00 + 7832.2340 0.45913400 306347.00 + 7837.4850 0.45441121 305718.00 + 7842.7560 0.44961359 305672.00 + 7848.0460 0.44433501 305591.00 + 7853.3540 0.43874661 305721.00 + 7858.6830 0.43362602 305761.00 + 7864.0300 0.42833655 305543.00 + 7869.3960 0.42287776 305580.00 + 7874.7810 0.41790268 305561.00 + 7880.1850 0.41331540 305567.00 + 7885.6080 0.40736809 305548.00 + 7891.0510 0.40162419 305485.00 + 7896.5120 0.39641156 305410.00 + 7901.9920 0.39158402 305454.00 + 7907.4920 0.38664929 305471.00 + 7913.0110 0.38183248 305389.00 + 7918.5480 0.37664824 305311.00 + 7924.1050 0.37186542 305383.00 + 7929.6810 0.36622348 305224.00 + 7935.2760 0.36059857 305309.00 + 7940.8900 0.35529935 304801.00 + 7946.5230 0.34983333 305709.00 + 7952.1750 0.34434706 305185.00 + 7957.8470 0.33897801 305134.00 + 7963.5370 0.33392445 305037.00 + 7969.2470 0.32835579 305340.00 \ No newline at end of file