# HG changeset patch # User muon-spectroscopy-computational-project # Date 1701867835 0 # Node ID 2b3115342fefa3380809dfb6eaae2510894b7b76 # Parent ae2f265ecf8e44aba222029414226d8815895e94 planemo upload for repository https://github.com/MaterialsGalaxy/larch-tools/tree/main/larch_athena commit 1cf6d7160497ba58fe16a51f00d088a20934eba6 diff -r ae2f265ecf8e -r 2b3115342fef common.py --- 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]: diff -r ae2f265ecf8e -r 2b3115342fef larch_athena.py --- 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, ) diff -r ae2f265ecf8e -r 2b3115342fef larch_athena.xml --- 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 @@ 0.9.71 - 0 + 1 10.1088/1742-6596/430/1/012007 @@ -15,11 +15,26 @@ - + + + + + + + + + + + + + + + + - - + + @@ -40,6 +55,7 @@ + -
- - - - -
- -
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- @@ -129,53 +184,53 @@ zip_outputs - + not zip_outputs - merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "") + 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")) plot_graph not zip_outputs - merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "") + 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")) plot_graph not zip_outputs - merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "") + 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")) plot_graph not zip_outputs - merge_inputs["merge_inputs"] or merge_inputs["format"]["dat_file"].extension != "zip" - merge_inputs["merge_inputs"] or (merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] == "") + 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")) - + not zip_outputs - merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] + 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") plot_graph not zip_outputs - merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] + 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") plot_graph not zip_outputs - merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] + 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") plot_graph not zip_outputs - merge_inputs["merge_inputs"] == "" and merge_inputs["format"]["format"] == "plaintext" and merge_inputs["format"]["is_zipped"]["is_zipped"] + 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") + @@ -184,6 +239,7 @@ + @@ -192,12 +248,22 @@ + + + + + + + + + + - + @@ -216,6 +282,7 @@ + @@ -225,6 +292,7 @@ + @@ -236,9 +304,10 @@ + - + @@ -246,9 +315,10 @@ + - + @@ -259,32 +329,34 @@ - + - + - + + - - + + - + + @@ -294,6 +366,7 @@ + @@ -303,6 +376,7 @@ + @@ -313,6 +387,7 @@ + @@ -322,6 +397,22 @@ + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + \ No newline at end of file diff -r ae2f265ecf8e -r 2b3115342fef test-data/ffi1.tabular --- /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 diff -r ae2f265ecf8e -r 2b3115342fef test-data/multiple.prj Binary file test-data/multiple.prj has changed