xarpes 0.4.0__tar.gz → 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {xarpes-0.4.0 → xarpes-0.5.0}/.gitignore +8 -2
- {xarpes-0.4.0 → xarpes-0.5.0}/PKG-INFO +5 -4
- {xarpes-0.4.0 → xarpes-0.5.0}/README.md +3 -1
- xarpes-0.5.0/dev_tools/Rmd2ipynb.py +109 -0
- xarpes-0.4.0/dev_tools/Rmd2py.py → xarpes-0.5.0/dev_tools/ipynb2Rmd2py.py +167 -19
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/conf.py +2 -1
- xarpes-0.5.0/doc/index.rst +28 -0
- xarpes-0.5.0/doc/modules/bandmap.rst +5 -0
- xarpes-0.5.0/doc/modules/mdcs.rst +5 -0
- xarpes-0.5.0/doc/modules/selfenergies.rst +5 -0
- xarpes-0.5.0/doc/modules/settings_parameters.rst +7 -0
- xarpes-0.5.0/doc/modules/settings_plots.rst +8 -0
- xarpes-0.5.0/doc/notebooks/graphene.ipynb +584 -0
- xarpes-0.5.0/doc/notebooks/srtio3.ipynb +513 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/requirements.txt +2 -1
- xarpes-0.5.0/examples/graphene/data_sets/graphene_152_angles.npy +0 -0
- xarpes-0.5.0/examples/graphene/data_sets/graphene_152_ekin.npy +0 -0
- xarpes-0.5.0/examples/graphene/data_sets/graphene_152_intensities.npy +0 -0
- xarpes-0.5.0/examples/graphene/graphene.Rmd +266 -0
- xarpes-0.5.0/examples/graphene/graphene.py +211 -0
- xarpes-0.5.0/examples/srtio3/data_sets/STO_2_0010STO_2_angles.npy +0 -0
- xarpes-0.5.0/examples/srtio3/data_sets/STO_2_0010STO_2_ekin.npy +0 -0
- xarpes-0.5.0/examples/srtio3/data_sets/STO_2_0010STO_2_intensities.npy +0 -0
- xarpes-0.5.0/examples/srtio3/srtio3.Rmd +228 -0
- xarpes-0.5.0/examples/srtio3/srtio3.py +178 -0
- xarpes-0.5.0/xarpes/__init__.py +36 -0
- xarpes-0.5.0/xarpes/bandmap.py +829 -0
- xarpes-0.5.0/xarpes/constants.py +13 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/xarpes/distributions.py +45 -43
- {xarpes-0.4.0 → xarpes-0.5.0}/xarpes/functions.py +18 -6
- xarpes-0.5.0/xarpes/mdcs.py +1035 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/xarpes/plotting.py +1 -47
- xarpes-0.5.0/xarpes/selfenergies.py +621 -0
- xarpes-0.5.0/xarpes/settings_parameters.py +30 -0
- xarpes-0.5.0/xarpes/settings_plots.py +54 -0
- xarpes-0.4.0/doc/index.rst +0 -17
- xarpes-0.4.0/doc/modules/spectral.rst +0 -5
- xarpes-0.4.0/examples/graphene/graphene.Rmd +0 -431
- xarpes-0.4.0/examples/graphene/graphene.py +0 -348
- xarpes-0.4.0/examples/srtio3/srtio3.Rmd +0 -530
- xarpes-0.4.0/examples/srtio3/srtio3.py +0 -429
- xarpes-0.4.0/xarpes/__init__.py +0 -6
- xarpes-0.4.0/xarpes/constants.py +0 -12
- xarpes-0.4.0/xarpes/spectral.py +0 -2476
- {xarpes-0.4.0 → xarpes-0.5.0}/.readthedocs.yaml +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/LICENSE +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/Makefile +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/README.md +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/_static/xarpes_small.svg +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/modules/distributions.rst +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/modules/functions.rst +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/doc/modules/plotting.rst +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/examples/graphene/data_sets/graphene_152.ibw +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/examples/srtio3/data_sets/STO_2_0010STO_2_.ibw +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/logo/Makefile +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/logo/exubi.svg +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/logo/xarpes.svg +0 -0
- {xarpes-0.4.0 → xarpes-0.5.0}/pyproject.toml +0 -0
|
@@ -81,6 +81,10 @@ target/
|
|
|
81
81
|
.ipynb_checkpoints
|
|
82
82
|
*.ipynb
|
|
83
83
|
|
|
84
|
+
# --- allow tracked notebooks in documentation ---
|
|
85
|
+
!doc/notebooks/
|
|
86
|
+
!doc/notebooks/*.ipynb
|
|
87
|
+
|
|
84
88
|
# IPython
|
|
85
89
|
profile_default/
|
|
86
90
|
ipython_config.py
|
|
@@ -173,5 +177,7 @@ cython_debug/
|
|
|
173
177
|
# VS Code
|
|
174
178
|
.vscode/
|
|
175
179
|
|
|
176
|
-
# Ignore
|
|
177
|
-
examples/
|
|
180
|
+
# Ignore conversion scripts if placed in examples folder
|
|
181
|
+
examples/Rmd2ipynb.py
|
|
182
|
+
examples/ipynb2Rmd2py.py
|
|
183
|
+
examples/Rmd2py.py
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: xarpes
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Extraction from angle resolved photoemission spectra
|
|
5
5
|
Author: xARPES Developers
|
|
6
6
|
Requires-Python: >=3.7.0
|
|
7
7
|
Description-Content-Type: text/markdown
|
|
8
8
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
License-File: LICENSE
|
|
11
10
|
Requires-Dist: igor2>=0.5.8
|
|
12
11
|
Requires-Dist: jupyterlab
|
|
13
12
|
Requires-Dist: jupytext
|
|
@@ -33,7 +32,9 @@ This project is currently undergoing **beta testing**. Some of the functionaliti
|
|
|
33
32
|
|
|
34
33
|
# Contributing
|
|
35
34
|
|
|
36
|
-
Contributions to the code are most welcome. xARPES is intended to co-develop alongside the increasing complexity of experimental ARPES data sets. Contributions can be made by forking the code and creating a pull request. Importing of file formats from different beamlines is particularly encouraged.
|
|
35
|
+
Contributions to the code are most welcome. xARPES is intended to co-develop alongside the increasing complexity of experimental ARPES data sets. Contributions can be made by forking the code and creating a pull request. Importing of file formats from different beamlines is particularly encouraged. For development of the examples, the following scripts in `/dev_tools` could be useful:
|
|
36
|
+
- The `Rmd2ipynb.py` file, to generate the `.ipynb` from which the examples can conveniently be developed; to be executed after cloning/pulling updated `.Rmd` and `.py` files, or if you prefer developing with `.Rmd` files.
|
|
37
|
+
- The `ipynb2Rmd2py.py` file, to synchronise the `.Rmd` and `.py` files from the `.ipynb` file; to be executed right before pushing modifications to the repository. Note that this script resets some metadata in the `.Rmd` to prevent the tracking of their changes due to local virtual environments, etc.
|
|
37
38
|
|
|
38
39
|
# Installation
|
|
39
40
|
|
|
@@ -10,7 +10,9 @@ This project is currently undergoing **beta testing**. Some of the functionaliti
|
|
|
10
10
|
|
|
11
11
|
# Contributing
|
|
12
12
|
|
|
13
|
-
Contributions to the code are most welcome. xARPES is intended to co-develop alongside the increasing complexity of experimental ARPES data sets. Contributions can be made by forking the code and creating a pull request. Importing of file formats from different beamlines is particularly encouraged.
|
|
13
|
+
Contributions to the code are most welcome. xARPES is intended to co-develop alongside the increasing complexity of experimental ARPES data sets. Contributions can be made by forking the code and creating a pull request. Importing of file formats from different beamlines is particularly encouraged. For development of the examples, the following scripts in `/dev_tools` could be useful:
|
|
14
|
+
- The `Rmd2ipynb.py` file, to generate the `.ipynb` from which the examples can conveniently be developed; to be executed after cloning/pulling updated `.Rmd` and `.py` files, or if you prefer developing with `.Rmd` files.
|
|
15
|
+
- The `ipynb2Rmd2py.py` file, to synchronise the `.Rmd` and `.py` files from the `.ipynb` file; to be executed right before pushing modifications to the repository. Note that this script resets some metadata in the `.Rmd` to prevent the tracking of their changes due to local virtual environments, etc.
|
|
14
16
|
|
|
15
17
|
# Installation
|
|
16
18
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Generate .ipynb notebooks from .Rmd files using Jupytext.
|
|
4
|
+
|
|
5
|
+
- For every .Rmd (excluding hidden folders and .ipynb_checkpoints),
|
|
6
|
+
create or overwrite a sibling <notebook>.ipynb using Jupytext.
|
|
7
|
+
|
|
8
|
+
Dependencies:
|
|
9
|
+
pip install jupytext
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
Place Rmd2ipynb.py in the /examples directory, where it is .gitignored.
|
|
13
|
+
$ python Rmd2ipynb.py # run from anywhere; it operates where it exists.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def find_base_dir() -> str:
|
|
22
|
+
"""Return the directory where this script lives (or CWD in a REPL)."""
|
|
23
|
+
return (os.path.dirname(os.path.abspath(__file__))
|
|
24
|
+
if "__file__" in globals() else os.getcwd())
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def is_hidden(name: str) -> bool:
|
|
28
|
+
"""Return True if a file or directory name is considered hidden."""
|
|
29
|
+
return name.startswith(".")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_jupytext() -> Optional[object]:
|
|
33
|
+
"""
|
|
34
|
+
Try to import jupytext and return the module, or None if unavailable.
|
|
35
|
+
|
|
36
|
+
Prints a single warning if jupytext is not installed.
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
import jupytext # type: ignore
|
|
40
|
+
return jupytext
|
|
41
|
+
except ImportError:
|
|
42
|
+
print(
|
|
43
|
+
"[WARN] 'jupytext' is not installed. "
|
|
44
|
+
"Install it with 'pip install jupytext' to enable "
|
|
45
|
+
".Rmd -> .ipynb conversion.",
|
|
46
|
+
file=sys.stderr,
|
|
47
|
+
)
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def convert_rmd_to_ipynb(rmd_path: str, jupytext) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Convert a single .Rmd file to a .ipynb notebook using Jupytext.
|
|
54
|
+
|
|
55
|
+
The .ipynb file is written next to the .Rmd file. Existing notebooks
|
|
56
|
+
are overwritten.
|
|
57
|
+
"""
|
|
58
|
+
base, ext = os.path.splitext(rmd_path)
|
|
59
|
+
if ext.lower() != ".rmd":
|
|
60
|
+
return
|
|
61
|
+
|
|
62
|
+
ipynb_path = base + ".ipynb"
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
# Let Jupytext auto-detect the format from the extension
|
|
66
|
+
nb = jupytext.read(rmd_path)
|
|
67
|
+
jupytext.write(nb, ipynb_path)
|
|
68
|
+
print(f"Converted: {rmd_path} -> {ipynb_path}")
|
|
69
|
+
except Exception as exc:
|
|
70
|
+
print(
|
|
71
|
+
f"[ERROR] Failed to convert '{rmd_path}' to .ipynb: {exc}",
|
|
72
|
+
file=sys.stderr,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def main() -> None:
|
|
77
|
+
base_dir = find_base_dir()
|
|
78
|
+
jupytext = get_jupytext()
|
|
79
|
+
if jupytext is None:
|
|
80
|
+
# Nothing to do if we don't have jupytext
|
|
81
|
+
return
|
|
82
|
+
|
|
83
|
+
converted_any = False
|
|
84
|
+
|
|
85
|
+
for path, folders, files in os.walk(base_dir, topdown=True):
|
|
86
|
+
# Skip hidden folders and notebook checkpoint caches
|
|
87
|
+
folders[:] = [
|
|
88
|
+
name for name in folders
|
|
89
|
+
if not is_hidden(name) and name != ".ipynb_checkpoints"
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
for name in files:
|
|
93
|
+
if is_hidden(name):
|
|
94
|
+
continue
|
|
95
|
+
if not name.endswith(".Rmd"):
|
|
96
|
+
continue
|
|
97
|
+
if ".ipynb_checkpoints" in path:
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
rmd = os.path.join(path, name)
|
|
101
|
+
convert_rmd_to_ipynb(rmd, jupytext)
|
|
102
|
+
converted_any = True
|
|
103
|
+
|
|
104
|
+
if not converted_any:
|
|
105
|
+
print("No .Rmd files found to convert.")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == "__main__":
|
|
109
|
+
main()
|
|
@@ -15,17 +15,23 @@ Usage:
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
import os
|
|
18
|
+
import re
|
|
18
19
|
import shutil
|
|
19
20
|
import subprocess
|
|
20
21
|
import sys
|
|
21
22
|
|
|
23
|
+
|
|
22
24
|
def find_base_dir() -> str:
|
|
23
25
|
# Safe base directory (works both when run as script or in REPL)
|
|
24
|
-
return os.path.dirname(os.path.abspath(__file__))
|
|
26
|
+
return (os.path.dirname(os.path.abspath(__file__))
|
|
27
|
+
if "__file__" in globals()
|
|
28
|
+
else os.getcwd())
|
|
29
|
+
|
|
25
30
|
|
|
26
31
|
def is_hidden(name: str) -> bool:
|
|
27
32
|
return name.startswith(".")
|
|
28
33
|
|
|
34
|
+
|
|
29
35
|
def run_jupytext_ipynb_to_rmd(ipynb_path: str) -> bool:
|
|
30
36
|
"""
|
|
31
37
|
Use the jupytext CLI to convert .ipynb -> .Rmd next to it.
|
|
@@ -33,29 +39,40 @@ def run_jupytext_ipynb_to_rmd(ipynb_path: str) -> bool:
|
|
|
33
39
|
"""
|
|
34
40
|
jupytext = shutil.which("jupytext")
|
|
35
41
|
if not jupytext:
|
|
36
|
-
print("[WARN] 'jupytext' not found on PATH.
|
|
42
|
+
print("[WARN] 'jupytext' not found on PATH. "
|
|
43
|
+
"Skipping .ipynb -> .Rmd step for:",
|
|
37
44
|
ipynb_path, file=sys.stderr)
|
|
38
45
|
return False
|
|
39
46
|
|
|
40
47
|
cmd = [jupytext, "--to", "rmarkdown", ipynb_path]
|
|
41
48
|
try:
|
|
42
|
-
res = subprocess.run(
|
|
49
|
+
res = subprocess.run(
|
|
50
|
+
cmd,
|
|
51
|
+
check=True,
|
|
52
|
+
stdout=subprocess.PIPE,
|
|
53
|
+
stderr=subprocess.STDOUT,
|
|
54
|
+
text=True,
|
|
55
|
+
)
|
|
43
56
|
# Optional: uncomment to see jupytext output
|
|
44
57
|
# print(res.stdout, end="")
|
|
45
58
|
return True
|
|
46
59
|
except subprocess.CalledProcessError as e:
|
|
47
|
-
print(f"[ERROR] jupytext failed for {ipynb_path}\n{e.stdout}",
|
|
60
|
+
print(f"[ERROR] jupytext failed for {ipynb_path}\n{e.stdout}",
|
|
61
|
+
file=sys.stderr)
|
|
48
62
|
return False
|
|
49
63
|
|
|
64
|
+
|
|
50
65
|
def convert_rmd_to_py(rmd_path: str) -> None:
|
|
51
66
|
"""
|
|
52
67
|
Convert a single .Rmd file to a .py script:
|
|
53
68
|
- YAML front matter is skipped
|
|
54
69
|
- Markdown outside code fences is commented with '# '
|
|
55
|
-
- Code inside fences (``` or ~~~) is written verbatim (with existing magic
|
|
70
|
+
- Code inside fences (``` or ~~~) is written verbatim (with existing magic
|
|
71
|
+
handling)
|
|
56
72
|
"""
|
|
57
73
|
py_path = rmd_path[:-3] + "py" # replace .Rmd with .py
|
|
58
|
-
with open(rmd_path, "r", encoding="utf-8") as lines,
|
|
74
|
+
with open(rmd_path, "r", encoding="utf-8") as lines, \
|
|
75
|
+
open(py_path, "w", encoding="utf-8") as text:
|
|
59
76
|
text.write("#!/usr/bin/env python3\n")
|
|
60
77
|
first_magic_comment = True
|
|
61
78
|
in_yaml = False
|
|
@@ -64,31 +81,33 @@ def convert_rmd_to_py(rmd_path: str) -> None:
|
|
|
64
81
|
for raw in lines:
|
|
65
82
|
line = raw
|
|
66
83
|
|
|
67
|
-
# ---- YAML front matter
|
|
84
|
+
# ---- YAML front matter --------------------------------------------
|
|
68
85
|
if line.startswith("---") and not in_code:
|
|
69
86
|
in_yaml = not in_yaml
|
|
70
87
|
continue
|
|
71
88
|
if in_yaml:
|
|
72
89
|
continue
|
|
73
90
|
|
|
74
|
-
# ---- Fence open/close (```... or ~~~...)
|
|
91
|
+
# ---- Fence open/close (```... or ~~~...) --------------------------
|
|
75
92
|
# Rmd/Quarto code chunks: ```{python, echo=FALSE} ... ```
|
|
76
|
-
if (line.lstrip().startswith("```") or
|
|
93
|
+
if (line.lstrip().startswith("```") or
|
|
94
|
+
line.lstrip().startswith("~~~")) and not in_yaml:
|
|
77
95
|
in_code = not in_code
|
|
78
96
|
# Do not emit the fence line itself
|
|
79
97
|
continue
|
|
80
98
|
|
|
81
99
|
if in_code:
|
|
82
|
-
# ---- Inside code fence: keep code, apply your filters
|
|
100
|
+
# ---- Inside code fence: keep code, apply your filters ---------
|
|
83
101
|
# Skip lines marked as "Jupyter only"
|
|
84
102
|
if "Jupyter only" in line:
|
|
85
103
|
continue
|
|
86
104
|
|
|
87
105
|
# Remove IPython magics
|
|
88
|
-
if "%matplotlib widget" in line or
|
|
106
|
+
if ("%matplotlib widget" in line or
|
|
107
|
+
"%matplotlib inline" in line):
|
|
89
108
|
continue
|
|
90
109
|
|
|
91
|
-
# Remove global Jupyter hooks (e.g. get_ipython().events
|
|
110
|
+
# Remove global Jupyter hooks (e.g. get_ipython().events...)
|
|
92
111
|
if "get_ipython" in line:
|
|
93
112
|
continue
|
|
94
113
|
|
|
@@ -104,22 +123,104 @@ def convert_rmd_to_py(rmd_path: str) -> None:
|
|
|
104
123
|
text.write(line)
|
|
105
124
|
|
|
106
125
|
else:
|
|
107
|
-
# ---- Outside code fence: Markdown -> Python comments
|
|
126
|
+
# ---- Outside code fence: Markdown -> Python comments ----------
|
|
108
127
|
if line.strip() == "":
|
|
109
128
|
# Preserve blank lines (safe in Python)
|
|
110
129
|
text.write("\n")
|
|
111
130
|
else:
|
|
112
|
-
# Comment any Markdown/text line so it doesn't break
|
|
131
|
+
# Comment any Markdown/text line so it doesn't break
|
|
132
|
+
# execution
|
|
113
133
|
text.write("# " + line)
|
|
114
134
|
|
|
135
|
+
|
|
136
|
+
def normalise_rmd_metadata(rmd_path: str) -> None:
|
|
137
|
+
"""
|
|
138
|
+
Standardise the YAML metadata of the Rmd file (string-based, no yaml lib):
|
|
139
|
+
|
|
140
|
+
- jupytext_version: 1.15.2
|
|
141
|
+
- kernelspec.display_name: Python 3 (ipykernel)
|
|
142
|
+
- kernelspec.name: python3
|
|
143
|
+
|
|
144
|
+
Only modifies existing lines in the YAML header. If the keys do not exist,
|
|
145
|
+
nothing is added.
|
|
146
|
+
"""
|
|
147
|
+
try:
|
|
148
|
+
with open(rmd_path, "r", encoding="utf-8") as f:
|
|
149
|
+
lines = f.readlines()
|
|
150
|
+
except OSError:
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
if not lines:
|
|
154
|
+
return
|
|
155
|
+
|
|
156
|
+
# Find first two '---' lines that delimit the YAML front matter.
|
|
157
|
+
if not lines[0].startswith("---"):
|
|
158
|
+
return
|
|
159
|
+
|
|
160
|
+
yaml_start = 0
|
|
161
|
+
yaml_end = None
|
|
162
|
+
for i in range(1, len(lines)):
|
|
163
|
+
if lines[i].startswith("---"):
|
|
164
|
+
yaml_end = i
|
|
165
|
+
break
|
|
166
|
+
|
|
167
|
+
if yaml_end is None:
|
|
168
|
+
# Malformed header, bail out.
|
|
169
|
+
return
|
|
170
|
+
|
|
171
|
+
header_lines = lines[yaml_start + 1:yaml_end]
|
|
172
|
+
header = "".join(header_lines)
|
|
173
|
+
|
|
174
|
+
# Replace jupytext_version
|
|
175
|
+
header = re.sub(
|
|
176
|
+
r'^(\s*jupytext_version:\s*).*$',
|
|
177
|
+
r'\g<1>1.15.2',
|
|
178
|
+
header,
|
|
179
|
+
flags=re.MULTILINE,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Replace kernelspec.display_name
|
|
183
|
+
header = re.sub(
|
|
184
|
+
r'^(\s*display_name:\s*).*$',
|
|
185
|
+
r'\g<1>Python 3 (ipykernel)',
|
|
186
|
+
header,
|
|
187
|
+
flags=re.MULTILINE,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
# Replace kernelspec.name
|
|
191
|
+
header = re.sub(
|
|
192
|
+
r'^(\s*name:\s*).*$',
|
|
193
|
+
r'\g<1>python3',
|
|
194
|
+
header,
|
|
195
|
+
flags=re.MULTILINE,
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
new_header_lines = header.splitlines(keepends=True)
|
|
199
|
+
new_lines = (
|
|
200
|
+
lines[:yaml_start + 1] +
|
|
201
|
+
new_header_lines +
|
|
202
|
+
lines[yaml_end:]
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
try:
|
|
206
|
+
with open(rmd_path, "w", encoding="utf-8") as f:
|
|
207
|
+
f.writelines(new_lines)
|
|
208
|
+
except OSError:
|
|
209
|
+
# If we can't write, silently skip; script should still continue.
|
|
210
|
+
return
|
|
211
|
+
|
|
212
|
+
|
|
115
213
|
def main() -> None:
|
|
116
214
|
base_dir = find_base_dir()
|
|
117
215
|
|
|
118
|
-
# ---- Pass 1: .ipynb -> .Rmd via jupytext
|
|
216
|
+
# ---- Pass 1: .ipynb -> .Rmd via jupytext -------------------------------
|
|
119
217
|
converted_any = False
|
|
120
218
|
for path, folders, files in os.walk(base_dir, topdown=True):
|
|
121
219
|
# Skip hidden folders and notebook checkpoint caches
|
|
122
|
-
folders[:] = [
|
|
220
|
+
folders[:] = [
|
|
221
|
+
name for name in folders
|
|
222
|
+
if not is_hidden(name) and name != ".ipynb_checkpoints"
|
|
223
|
+
]
|
|
123
224
|
|
|
124
225
|
for name in files:
|
|
125
226
|
if is_hidden(name):
|
|
@@ -130,14 +231,18 @@ def main() -> None:
|
|
|
130
231
|
continue
|
|
131
232
|
|
|
132
233
|
ipynb = os.path.join(path, name)
|
|
234
|
+
|
|
235
|
+
copy_ipynb_to_docs(ipynb, base_dir)
|
|
236
|
+
|
|
133
237
|
ok = run_jupytext_ipynb_to_rmd(ipynb)
|
|
134
238
|
converted_any = converted_any or ok
|
|
135
239
|
|
|
136
240
|
if not converted_any:
|
|
137
|
-
# Not an error—maybe there are no ipynb files, or jupytext isn't
|
|
241
|
+
# Not an error—maybe there are no ipynb files, or jupytext isn't
|
|
242
|
+
# installed.
|
|
138
243
|
pass
|
|
139
244
|
|
|
140
|
-
# ---- Pass 2: .Rmd -> .py
|
|
245
|
+
# ---- Pass 2: .Rmd -> .py ----------------------------------------------
|
|
141
246
|
for path, folders, files in os.walk(base_dir, topdown=True):
|
|
142
247
|
folders[:] = [name for name in folders if not is_hidden(name)]
|
|
143
248
|
for name in files:
|
|
@@ -147,7 +252,50 @@ def main() -> None:
|
|
|
147
252
|
continue
|
|
148
253
|
|
|
149
254
|
rmd = os.path.join(path, name)
|
|
255
|
+
|
|
256
|
+
# Normalise jupytext/kernelspec metadata in YAML header
|
|
257
|
+
normalise_rmd_metadata(rmd)
|
|
258
|
+
|
|
259
|
+
# Convert .Rmd -> .py
|
|
150
260
|
convert_rmd_to_py(rmd)
|
|
151
261
|
|
|
262
|
+
|
|
263
|
+
def copy_ipynb_to_docs(ipynb_path: str, base_dir: str) -> None:
|
|
264
|
+
"""
|
|
265
|
+
Copy ipynb into <repo>/doc/notebooks, flattening any subfolders.
|
|
266
|
+
|
|
267
|
+
If two notebooks share the same filename, disambiguate by appending a
|
|
268
|
+
suffix derived from their relative directory.
|
|
269
|
+
"""
|
|
270
|
+
repo_root = os.path.dirname(base_dir)
|
|
271
|
+
dst_dir = os.path.join(repo_root, "doc", "notebooks")
|
|
272
|
+
os.makedirs(dst_dir, exist_ok=True)
|
|
273
|
+
|
|
274
|
+
name = os.path.basename(ipynb_path)
|
|
275
|
+
dst = os.path.join(dst_dir, name)
|
|
276
|
+
|
|
277
|
+
if os.path.exists(dst):
|
|
278
|
+
# Disambiguate collisions by using the relative folder path.
|
|
279
|
+
rel_dir = os.path.relpath(os.path.dirname(ipynb_path), base_dir)
|
|
280
|
+
rel_dir = "" if rel_dir == "." else rel_dir
|
|
281
|
+
suffix = re.sub(r"[^A-Za-z0-9]+", "_", rel_dir).strip("_")
|
|
282
|
+
root, ext = os.path.splitext(name)
|
|
283
|
+
new_name = f"{root}__{suffix}{ext}" if suffix else name
|
|
284
|
+
dst = os.path.join(dst_dir, new_name)
|
|
285
|
+
|
|
286
|
+
# If *still* colliding, add a numeric suffix.
|
|
287
|
+
if os.path.exists(dst):
|
|
288
|
+
i = 2
|
|
289
|
+
while True:
|
|
290
|
+
new_name = f"{root}__{suffix}__{i}{ext}" if suffix else \
|
|
291
|
+
f"{root}__{i}{ext}"
|
|
292
|
+
dst = os.path.join(dst_dir, new_name)
|
|
293
|
+
if not os.path.exists(dst):
|
|
294
|
+
break
|
|
295
|
+
i += 1
|
|
296
|
+
|
|
297
|
+
shutil.copy2(ipynb_path, dst)
|
|
298
|
+
|
|
299
|
+
|
|
152
300
|
if __name__ == "__main__":
|
|
153
|
-
main()
|
|
301
|
+
main()
|
|
@@ -24,6 +24,7 @@ extensions = [
|
|
|
24
24
|
'sphinx.ext.viewcode',
|
|
25
25
|
'numpydoc',
|
|
26
26
|
'myst_parser',
|
|
27
|
+
'nbsphinx',
|
|
27
28
|
]
|
|
28
29
|
|
|
29
30
|
exclude_patterns = ['README.md']
|
|
@@ -40,4 +41,4 @@ html_theme = 'sphinx_rtd_theme'
|
|
|
40
41
|
# The following setting specifies the order in which members are documented
|
|
41
42
|
autodoc_member_order = 'bysource'
|
|
42
43
|
|
|
43
|
-
numpydoc_show_class_members = False
|
|
44
|
+
numpydoc_show_class_members = False
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.. include:: ../README.md
|
|
2
|
+
:parser: myst_parser.sphinx_
|
|
3
|
+
|
|
4
|
+
.. toctree::
|
|
5
|
+
:caption: Modules
|
|
6
|
+
:hidden:
|
|
7
|
+
|
|
8
|
+
modules/bandmap
|
|
9
|
+
modules/mdcs
|
|
10
|
+
modules/selfenergies
|
|
11
|
+
modules/distributions
|
|
12
|
+
modules/functions
|
|
13
|
+
modules/plotting
|
|
14
|
+
modules/settings_parameters
|
|
15
|
+
modules/settings_plots
|
|
16
|
+
|
|
17
|
+
.. toctree::
|
|
18
|
+
:caption: Tutorials
|
|
19
|
+
:hidden:
|
|
20
|
+
|
|
21
|
+
notebooks/graphene
|
|
22
|
+
notebooks/srtio3
|
|
23
|
+
|
|
24
|
+
.. toctree::
|
|
25
|
+
:caption: More
|
|
26
|
+
:hidden:
|
|
27
|
+
|
|
28
|
+
genindex
|