diff --git a/lib/galaxy/config/sample/datatypes_conf.xml.sample b/lib/galaxy/config/sample/datatypes_conf.xml.sample
index 20fc5031485..f97bf1f54c7 100644
--- a/lib/galaxy/config/sample/datatypes_conf.xml.sample
+++ b/lib/galaxy/config/sample/datatypes_conf.xml.sample
@@ -950,6 +950,13 @@
+
+
+
+
+
+
+
@@ -1210,6 +1217,8 @@
+
+
diff --git a/lib/galaxy/datatypes/larch.py b/lib/galaxy/datatypes/larch.py
new file mode 100644
index 00000000000..212f41af1a0
--- /dev/null
+++ b/lib/galaxy/datatypes/larch.py
@@ -0,0 +1,218 @@
+from typing import List
+
+from galaxy.datatypes.data import (
+ get_file_peek,
+ Text,
+)
+from galaxy.datatypes.metadata import MetadataElement
+from galaxy.datatypes.protocols import DatasetProtocol
+from galaxy.datatypes.sniff import (
+ build_sniff_from_prefix,
+ FilePrefix,
+ get_headers,
+)
+
+
+@build_sniff_from_prefix
+class AthenaProject(Text):
+ """
+ Athena project format
+ """
+
+ file_ext = "prj"
+ compressed = True
+ compressed_format = "gzip"
+
+ MetadataElement(
+ name="atsym",
+ desc="Atom symbol",
+ readonly=True,
+ visible=True,
+ )
+ MetadataElement(
+ name="bkg_e0",
+ desc="Edge energy (eV)",
+ readonly=True,
+ visible=True,
+ )
+ MetadataElement(
+ name="edge",
+ desc="Edge",
+ readonly=True,
+ visible=True,
+ )
+ MetadataElement(
+ name="npts",
+ desc="Number of points",
+ readonly=True,
+ visible=True,
+ )
+ MetadataElement(
+ name="xmax",
+ desc="Maximum energy (eV)",
+ readonly=True,
+ visible=True,
+ )
+ MetadataElement(
+ name="xmin",
+ desc="Minimum energy (eV)",
+ readonly=True,
+ visible=True,
+ )
+
+ def sniff_prefix(self, file_prefix: FilePrefix) -> bool:
+ """
+ Try to guess if the file is an Athena project file.
+
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('test.prj')
+ >>> AthenaProject().sniff(fname)
+ True
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('Si.cif')
+ >>> AthenaProject().sniff(fname)
+ False
+ """
+
+ return file_prefix.startswith("# Athena project file")
+
+ def set_meta(self, dataset: DatasetProtocol, *, overwrite: bool = True, **kwd) -> None:
+ """
+ Extract metadata from @args
+ """
+
+ def extract_arg(args: List[str], arg_name: str):
+ try:
+ index = args.index(f"'{arg_name}'")
+ setattr(dataset.metadata, arg_name, args[index + 1].replace("'", ""))
+ except ValueError:
+ return
+
+ headers = get_headers(dataset.file_name, sep=" = ", count=3, comment_designator="#")
+ args = []
+ for header in headers:
+ if header[0] == "@args":
+ args = header[1][1:-2].split(",")
+ break
+
+ extract_arg(args, "atsym")
+ extract_arg(args, "bkg_e0")
+ extract_arg(args, "edge")
+ extract_arg(args, "npts")
+ extract_arg(args, "xmax")
+ extract_arg(args, "xmin")
+
+ def set_peek(self, dataset: DatasetProtocol, **kwd) -> None:
+ if not dataset.dataset.purged:
+ dataset.peek = get_file_peek(dataset.file_name)
+ dataset.info = (
+ f"atsym: {dataset.metadata.atsym}\n"
+ f"bkg_e0: {dataset.metadata.bkg_e0}\n"
+ f"edge: {dataset.metadata.edge}\n"
+ f"npts: {dataset.metadata.npts}\n"
+ f"xmax: {dataset.metadata.xmax}\n"
+ f"xmin: {dataset.metadata.xmin}"
+ )
+ dataset.blurb = f"Athena project file of {dataset.metadata.atsym} {dataset.metadata.edge} edge"
+
+ else:
+ dataset.peek = "file does not exist"
+ dataset.blurb = "file purged from disk"
+
+
+@build_sniff_from_prefix
+class FEFFInput(Text):
+ """
+ FEFF input format
+ """
+
+ file_ext = "inp"
+
+ MetadataElement(
+ name="title_block",
+ desc="Title block",
+ readonly=True,
+ visible=True,
+ )
+
+ def sniff_prefix(self, file_prefix: FilePrefix) -> bool:
+ """
+ Try to guess if the file is an FEFF input file.
+
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('larch_pymatgen.inp')
+ >>> FEFFInput().sniff(fname)
+ True
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('larch_atoms.inp')
+ >>> FEFFInput().sniff(fname)
+ True
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('larch_potentials.inp')
+ >>> FEFFInput().sniff(fname)
+ True
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('larch_bad_atoms.txt')
+ >>> FEFFInput().sniff(fname)
+ False
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('larch_bad_potentials.txt')
+ >>> FEFFInput().sniff(fname)
+ False
+ >>> from galaxy.datatypes.sniff import get_test_fname
+ >>> fname = get_test_fname('Si.cif')
+ >>> FEFFInput().sniff(fname)
+ False
+ """
+ # pymatgen marks generated FEFF inputs, but user might also upload from another source
+ if file_prefix.startswith("* This FEFF.inp file generated by pymatgen"):
+ return True
+
+ generator = file_prefix.line_iterator()
+ try:
+ line = next(generator).strip()
+ while line is not None:
+ if line == "POTENTIALS":
+ line = next(generator).strip()
+ if line[0] == "*":
+ words = line[1:].split()
+ if (words[0] in ["potential-index", "ipot"]) and (words[1] == "Z"):
+ return True
+ return False
+
+ elif line == "ATOMS":
+ line = next(generator).strip()
+ if line[0] == "*":
+ words = line[1:].split()
+ if words[:4] == ["x", "y", "z", "ipot"]:
+ return True
+ return False
+
+ else:
+ line = next(generator).strip()
+
+ except StopIteration:
+ return False
+
+ return False
+
+ def set_meta(self, dataset: DatasetProtocol, overwrite: bool = True, **kwd) -> None:
+ """
+ Extract metadata from TITLE
+ """
+ title_block = ""
+ headers = get_headers(dataset.file_name, sep=None, comment_designator="*")
+ for header in headers:
+ if header and header[0] == "TITLE":
+ title_block += " ".join(header[1:]) + "\n"
+
+ dataset.metadata.title_block = title_block
+
+ def set_peek(self, dataset: DatasetProtocol, **kwd) -> None:
+ if not dataset.dataset.purged:
+ dataset.peek = get_file_peek(dataset.file_name)
+ dataset.info = dataset.metadata.title_block
+
+ else:
+ dataset.peek = "file does not exist"
+ dataset.blurb = "file purged from disk"
diff --git a/lib/galaxy/datatypes/test/larch_atoms.inp b/lib/galaxy/datatypes/test/larch_atoms.inp
new file mode 100644
index 00000000000..6deb2fb4635
--- /dev/null
+++ b/lib/galaxy/datatypes/test/larch_atoms.inp
@@ -0,0 +1,44 @@
+TITLE comment: None given
+TITLE Source:
+TITLE Structure Summary: Fe2 S4
+TITLE Reduced formula: FeS2
+TITLE space group: (Pnnm), space number: (58)
+TITLE abc: 3.385200 4.447400 5.428700
+TITLE angles: 90.000000 90.000000 90.000000
+TITLE sites: 6
+* 1 Fe 0.000000 0.000000 0.000000
+* 2 Fe 0.500000 0.500000 0.500000
+* 3 S 0.000000 0.199900 0.378040
+* 4 S 0.000000 0.800100 0.621960
+* 5 S 0.500000 0.699900 0.121960
+* 6 S 0.500000 0.300100 0.878040
+
+ATOMS
+ * x y z ipot Atom Distance Number
+**********- ********- ******- ****** ****** ********** ********
+ 0 0 0 0 Fe 0 0
+ -0.889035 -2.05227 -0 2 S 2.23656 4
+ 0.889035 2.05227 0 2 S 2.23656 22
+ -1.33466 0.662084 -1.6926 2 S 2.2549 6
+ -1.33466 0.662084 1.6926 2 S 2.2549 8
+ 1.33466 -0.662084 -1.6926 2 S 2.2549 11
+ 1.33466 -0.662084 1.6926 2 S 2.2549 13
+ 0 0 -3.3852 1 Fe 3.3852 18
+ 0 0 3.3852 1 Fe 3.3852 19
+ -0.889035 3.37643 0 2 S 3.49152 9
+ 0.889035 -3.37643 -0 2 S 3.49152 15
+ -3.11273 -0.662084 -1.6926 2 S 3.60449 1
+ -3.11273 -0.662084 1.6926 2 S 3.60449 3
+ 3.11273 0.662084 -1.6926 2 S 3.60449 16
+ 3.11273 0.662084 1.6926 2 S 3.60449 20
+ -2.2237 -2.71435 -1.6926 1 Fe 3.89582 2
+ -2.2237 -2.71435 1.6926 1 Fe 3.89582 5
+ -2.2237 2.71435 -1.6926 1 Fe 3.89582 7
+ -2.2237 2.71435 1.6926 1 Fe 3.89582 10
+ 2.2237 -2.71435 -1.6926 1 Fe 3.89582 12
+ 2.2237 -2.71435 1.6926 1 Fe 3.89582 14
+ 2.2237 2.71435 -1.6926 1 Fe 3.89582 17
+ 2.2237 2.71435 1.6926 1 Fe 3.89582 21
+END
+
+
diff --git a/lib/galaxy/datatypes/test/larch_bad_atoms.txt b/lib/galaxy/datatypes/test/larch_bad_atoms.txt
new file mode 100644
index 00000000000..b801beb1bd1
--- /dev/null
+++ b/lib/galaxy/datatypes/test/larch_bad_atoms.txt
@@ -0,0 +1,44 @@
+TITLE comment: None given
+TITLE Source:
+TITLE Structure Summary: Fe2 S4
+TITLE Reduced formula: FeS2
+TITLE space group: (Pnnm), space number: (58)
+TITLE abc: 3.385200 4.447400 5.428700
+TITLE angles: 90.000000 90.000000 90.000000
+TITLE sites: 6
+* 1 Fe 0.000000 0.000000 0.000000
+* 2 Fe 0.500000 0.500000 0.500000
+* 3 S 0.000000 0.199900 0.378040
+* 4 S 0.000000 0.800100 0.621960
+* 5 S 0.500000 0.699900 0.121960
+* 6 S 0.500000 0.300100 0.878040
+
+ATOMS
+ * a b c ipot Atom Distance Number
+**********- ********- ******- ****** ****** ********** ********
+ 0 0 0 0 Fe 0 0
+ -0.889035 -2.05227 -0 2 S 2.23656 4
+ 0.889035 2.05227 0 2 S 2.23656 22
+ -1.33466 0.662084 -1.6926 2 S 2.2549 6
+ -1.33466 0.662084 1.6926 2 S 2.2549 8
+ 1.33466 -0.662084 -1.6926 2 S 2.2549 11
+ 1.33466 -0.662084 1.6926 2 S 2.2549 13
+ 0 0 -3.3852 1 Fe 3.3852 18
+ 0 0 3.3852 1 Fe 3.3852 19
+ -0.889035 3.37643 0 2 S 3.49152 9
+ 0.889035 -3.37643 -0 2 S 3.49152 15
+ -3.11273 -0.662084 -1.6926 2 S 3.60449 1
+ -3.11273 -0.662084 1.6926 2 S 3.60449 3
+ 3.11273 0.662084 -1.6926 2 S 3.60449 16
+ 3.11273 0.662084 1.6926 2 S 3.60449 20
+ -2.2237 -2.71435 -1.6926 1 Fe 3.89582 2
+ -2.2237 -2.71435 1.6926 1 Fe 3.89582 5
+ -2.2237 2.71435 -1.6926 1 Fe 3.89582 7
+ -2.2237 2.71435 1.6926 1 Fe 3.89582 10
+ 2.2237 -2.71435 -1.6926 1 Fe 3.89582 12
+ 2.2237 -2.71435 1.6926 1 Fe 3.89582 14
+ 2.2237 2.71435 -1.6926 1 Fe 3.89582 17
+ 2.2237 2.71435 1.6926 1 Fe 3.89582 21
+END
+
+
diff --git a/lib/galaxy/datatypes/test/larch_bad_potentials.txt b/lib/galaxy/datatypes/test/larch_bad_potentials.txt
new file mode 100644
index 00000000000..e0c3a4f13f8
--- /dev/null
+++ b/lib/galaxy/datatypes/test/larch_bad_potentials.txt
@@ -0,0 +1,24 @@
+TITLE comment: None given
+TITLE Source:
+TITLE Structure Summary: Fe2 S4
+TITLE Reduced formula: FeS2
+TITLE space group: (Pnnm), space number: (58)
+TITLE abc: 3.385200 4.447400 5.428700
+TITLE angles: 90.000000 90.000000 90.000000
+TITLE sites: 6
+* 1 Fe 0.000000 0.000000 0.000000
+* 2 Fe 0.500000 0.500000 0.500000
+* 3 S 0.000000 0.199900 0.378040
+* 4 S 0.000000 0.800100 0.621960
+* 5 S 0.500000 0.699900 0.121960
+* 6 S 0.500000 0.300100 0.878040
+
+POTENTIALS
+ * pot Z tag lmax1 lmax2 xnatph(stoichometry) spinph
+******- **- ****- ******- ******- ********************** ********
+ 0 26 Fe -1 -1 0.0001 0
+ 1 26 Fe -1 -1 2 0
+ 2 16 S -1 -1 4 0
+END
+
+
diff --git a/lib/galaxy/datatypes/test/larch_potentials.inp b/lib/galaxy/datatypes/test/larch_potentials.inp
new file mode 100644
index 00000000000..cc96ad4cd11
--- /dev/null
+++ b/lib/galaxy/datatypes/test/larch_potentials.inp
@@ -0,0 +1,24 @@
+TITLE comment: None given
+TITLE Source:
+TITLE Structure Summary: Fe2 S4
+TITLE Reduced formula: FeS2
+TITLE space group: (Pnnm), space number: (58)
+TITLE abc: 3.385200 4.447400 5.428700
+TITLE angles: 90.000000 90.000000 90.000000
+TITLE sites: 6
+* 1 Fe 0.000000 0.000000 0.000000
+* 2 Fe 0.500000 0.500000 0.500000
+* 3 S 0.000000 0.199900 0.378040
+* 4 S 0.000000 0.800100 0.621960
+* 5 S 0.500000 0.699900 0.121960
+* 6 S 0.500000 0.300100 0.878040
+
+POTENTIALS
+ *ipot Z tag lmax1 lmax2 xnatph(stoichometry) spinph
+******- **- ****- ******- ******- ********************** ********
+ 0 26 Fe -1 -1 0.0001 0
+ 1 26 Fe -1 -1 2 0
+ 2 16 S -1 -1 4 0
+END
+
+
diff --git a/lib/galaxy/datatypes/test/larch_pymatgen.inp b/lib/galaxy/datatypes/test/larch_pymatgen.inp
new file mode 100644
index 00000000000..522743703c3
--- /dev/null
+++ b/lib/galaxy/datatypes/test/larch_pymatgen.inp
@@ -0,0 +1,52 @@
+* This FEFF.inp file generated by pymatgen
+TITLE comment: None given
+TITLE Source:
+TITLE Structure Summary: Fe2 S4
+TITLE Reduced formula: FeS2
+TITLE space group: (Pnnm), space number: (58)
+TITLE abc: 3.385200 4.447400 5.428700
+TITLE angles: 90.000000 90.000000 90.000000
+TITLE sites: 6
+* 1 Fe 0.000000 0.000000 0.000000
+* 2 Fe 0.500000 0.500000 0.500000
+* 3 S 0.000000 0.199900 0.378040
+* 4 S 0.000000 0.800100 0.621960
+* 5 S 0.500000 0.699900 0.121960
+* 6 S 0.500000 0.300100 0.878040
+
+POTENTIALS
+ *ipot Z tag lmax1 lmax2 xnatph(stoichometry) spinph
+******- **- ****- ******- ******- ********************** ********
+ 0 26 Fe -1 -1 0.0001 0
+ 1 26 Fe -1 -1 2 0
+ 2 16 S -1 -1 4 0
+
+ATOMS
+ * x y z ipot Atom Distance Number
+**********- ********- ******- ****** ****** ********** ********
+ 0 0 0 0 Fe 0 0
+ -0.889035 -2.05227 -0 2 S 2.23656 4
+ 0.889035 2.05227 0 2 S 2.23656 22
+ -1.33466 0.662084 -1.6926 2 S 2.2549 6
+ -1.33466 0.662084 1.6926 2 S 2.2549 8
+ 1.33466 -0.662084 -1.6926 2 S 2.2549 11
+ 1.33466 -0.662084 1.6926 2 S 2.2549 13
+ 0 0 -3.3852 1 Fe 3.3852 18
+ 0 0 3.3852 1 Fe 3.3852 19
+ -0.889035 3.37643 0 2 S 3.49152 9
+ 0.889035 -3.37643 -0 2 S 3.49152 15
+ -3.11273 -0.662084 -1.6926 2 S 3.60449 1
+ -3.11273 -0.662084 1.6926 2 S 3.60449 3
+ 3.11273 0.662084 -1.6926 2 S 3.60449 16
+ 3.11273 0.662084 1.6926 2 S 3.60449 20
+ -2.2237 -2.71435 -1.6926 1 Fe 3.89582 2
+ -2.2237 -2.71435 1.6926 1 Fe 3.89582 5
+ -2.2237 2.71435 -1.6926 1 Fe 3.89582 7
+ -2.2237 2.71435 1.6926 1 Fe 3.89582 10
+ 2.2237 -2.71435 -1.6926 1 Fe 3.89582 12
+ 2.2237 -2.71435 1.6926 1 Fe 3.89582 14
+ 2.2237 2.71435 -1.6926 1 Fe 3.89582 17
+ 2.2237 2.71435 1.6926 1 Fe 3.89582 21
+END
+
+
diff --git a/lib/galaxy/datatypes/test/test.prj b/lib/galaxy/datatypes/test/test.prj
new file mode 100644
index 00000000000..55b0926c871
Binary files /dev/null and b/lib/galaxy/datatypes/test/test.prj differ