mf6adj 1.0.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.
Files changed (74) hide show
  1. mf6adj-1.0.0/.gitignore +145 -0
  2. mf6adj-1.0.0/PKG-INFO +178 -0
  3. mf6adj-1.0.0/README.md +76 -0
  4. mf6adj-1.0.0/examples/clear_output_all.py +58 -0
  5. mf6adj-1.0.0/examples/dewater_demo.ipynb +661 -0
  6. mf6adj-1.0.0/examples/sanpedro_demo.ipynb +477 -0
  7. mf6adj-1.0.0/examples/structured_freyberg_demo.ipynb +700 -0
  8. mf6adj-1.0.0/examples/synthdewater/buildmodel_workflow.py.txt +3980 -0
  9. mf6adj-1.0.0/examples/synthdewater/dewater.wel +28 -0
  10. mf6adj-1.0.0/examples/synthdewater/dewater.wel_stress_period_data_1.txt +40 -0
  11. mf6adj-1.0.0/examples/synthdewater/dewater.wel_stress_period_data_2.txt +40 -0
  12. mf6adj-1.0.0/examples/synthdewater/dewater.wel_stress_period_data_3.txt +40 -0
  13. mf6adj-1.0.0/examples/synthdewater/dewater.wel_stress_period_data_4.txt +40 -0
  14. mf6adj-1.0.0/examples/synthdewater/inflow.ghb +11 -0
  15. mf6adj-1.0.0/examples/synthdewater/inflow.ghb_stress_period_data_1.txt +100 -0
  16. mf6adj-1.0.0/examples/synthdewater/mar.wel +26 -0
  17. mf6adj-1.0.0/examples/synthdewater/mar.wel_stress_period_data_1.txt +10 -0
  18. mf6adj-1.0.0/examples/synthdewater/mar.wel_stress_period_data_2.txt +10 -0
  19. mf6adj-1.0.0/examples/synthdewater/mar.wel_stress_period_data_3.txt +10 -0
  20. mf6adj-1.0.0/examples/synthdewater/mar.wel_stress_period_data_4.txt +10 -0
  21. mf6adj-1.0.0/examples/synthdewater/mfsim.nam +20 -0
  22. mf6adj-1.0.0/examples/synthdewater/model.dis +24 -0
  23. mf6adj-1.0.0/examples/synthdewater/model.dis_botm.txt +500 -0
  24. mf6adj-1.0.0/examples/synthdewater/model.dis_delc.txt +5 -0
  25. mf6adj-1.0.0/examples/synthdewater/model.dis_delr.txt +5 -0
  26. mf6adj-1.0.0/examples/synthdewater/model.dis_idomain.txt +500 -0
  27. mf6adj-1.0.0/examples/synthdewater/model.dis_top.txt +500 -0
  28. mf6adj-1.0.0/examples/synthdewater/model.drn +13 -0
  29. mf6adj-1.0.0/examples/synthdewater/model.drn.obs +9 -0
  30. mf6adj-1.0.0/examples/synthdewater/model.drn.obs_continuous_model.obs.drn.csv.txt +1 -0
  31. mf6adj-1.0.0/examples/synthdewater/model.drn_stress_period_data_1.txt +100 -0
  32. mf6adj-1.0.0/examples/synthdewater/model.ic +6 -0
  33. mf6adj-1.0.0/examples/synthdewater/model.ic_strt.txt +500 -0
  34. mf6adj-1.0.0/examples/synthdewater/model.nam +20 -0
  35. mf6adj-1.0.0/examples/synthdewater/model.npf +11 -0
  36. mf6adj-1.0.0/examples/synthdewater/model.npf_icelltype.txt +500 -0
  37. mf6adj-1.0.0/examples/synthdewater/model.npf_k.txt +100 -0
  38. mf6adj-1.0.0/examples/synthdewater/model.obs +13 -0
  39. mf6adj-1.0.0/examples/synthdewater/model.obs_continuous_model.obs.head.pit.csv.txt +100 -0
  40. mf6adj-1.0.0/examples/synthdewater/model.obs_continuous_model.obs.head.wel-mar.csv.txt +10 -0
  41. mf6adj-1.0.0/examples/synthdewater/model.oc +11 -0
  42. mf6adj-1.0.0/examples/synthdewater/model.rcha +10 -0
  43. mf6adj-1.0.0/examples/synthdewater/model.rcha_recharge_1.txt +500 -0
  44. mf6adj-1.0.0/examples/synthdewater/model.sto +22 -0
  45. mf6adj-1.0.0/examples/synthdewater/model.sto_iconvert.txt +500 -0
  46. mf6adj-1.0.0/examples/synthdewater/model.sto_ss.txt +500 -0
  47. mf6adj-1.0.0/examples/synthdewater/model.sto_sy.txt +500 -0
  48. mf6adj-1.0.0/examples/synthdewater/sim.ims +21 -0
  49. mf6adj-1.0.0/examples/synthdewater/sim.tdis +16 -0
  50. mf6adj-1.0.0/examples/xd_box_chd_ana/mfsim.nam +21 -0
  51. mf6adj-1.0.0/examples/xd_box_chd_ana/test.adj +9 -0
  52. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.cbb +0 -0
  53. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.chd +171 -0
  54. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.dis +103 -0
  55. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.ic +89 -0
  56. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.ims +16 -0
  57. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.nam +16 -0
  58. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.npf +13 -0
  59. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.oc +12 -0
  60. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.sto +17 -0
  61. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.tdis +13 -0
  62. mf6adj-1.0.0/examples/xd_box_chd_ana/xdbox.wel +8011 -0
  63. mf6adj-1.0.0/examples/xdbox_demo.ipynb +555 -0
  64. mf6adj-1.0.0/examples/zaidel_demo.ipynb +739 -0
  65. mf6adj-1.0.0/mf6adj/__init__.py +14 -0
  66. mf6adj-1.0.0/mf6adj/adj.py +1324 -0
  67. mf6adj-1.0.0/mf6adj/pm.py +1454 -0
  68. mf6adj-1.0.0/mf6adj/utils/utils.py +197 -0
  69. mf6adj-1.0.0/mf6adj/utils/utils_fileio.py +126 -0
  70. mf6adj-1.0.0/mf6adj/utils/utils_logger.py +95 -0
  71. mf6adj-1.0.0/mf6adj/utils/utils_modflow.py +280 -0
  72. mf6adj-1.0.0/mf6adj/utils/utils_pm_read.py +633 -0
  73. mf6adj-1.0.0/mf6adj/version.py +4 -0
  74. mf6adj-1.0.0/pyproject.toml +163 -0
@@ -0,0 +1,145 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+ docs/source/_api/
74
+ docs/source/examples/
75
+
76
+ # PyBuilder
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ .python-version
88
+
89
+ # pipenv
90
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
92
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
93
+ # install all needed dependencies.
94
+ #Pipfile.lock
95
+
96
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
97
+ __pypackages__/
98
+
99
+ # Celery stuff
100
+ celerybeat-schedule
101
+ celerybeat.pid
102
+
103
+ # SageMath parsed files
104
+ *.sage.py
105
+
106
+ # Environments
107
+ .env
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+ .dmypy.json
128
+ dmypy.json
129
+
130
+ # Pyre type checker
131
+ .pyre/
132
+
133
+ # MacOS files
134
+ .DS_Store
135
+
136
+ # Examples result directories
137
+ examples/ex-gwf-zaidel/
138
+ examples/freyberg/
139
+ examples/sanpedro/
140
+ examples/xd_box_chd_ana_working
141
+ examples/synthdewater_working
142
+ autotest/*_test*/
143
+ .figures/
144
+
145
+ .temp/
mf6adj-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: mf6adj
3
+ Version: 1.0.0
4
+ Summary: mf6adj is a Python package for adjoint-state sensitivity analysis with MODFLOW 6
5
+ Project-URL: Documentation, https://mf6adj.readthedocs.io
6
+ Project-URL: Bug Tracker, https://github.com/INTERA-Inc/mf6adj/issues
7
+ Project-URL: Source Code, https://github.com/INTERA-Inc/mf6adj
8
+ Author: INTERA Incorporated
9
+ Maintainer: INTERA Incorporated
10
+ License: CC0-1.0
11
+ Keywords: MODFLOW,adjoint,groundwater,hydrogeology
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Scientific/Engineering :: Hydrology
20
+ Requires-Python: >=3.10
21
+ Requires-Dist: flopy>=3.10.0
22
+ Requires-Dist: geopandas>=1.0.0
23
+ Requires-Dist: h5py>=3.0.0
24
+ Requires-Dist: matplotlib>=3.5.0
25
+ Requires-Dist: modflowapi>=0.2.0
26
+ Requires-Dist: numpy>=2.0
27
+ Requires-Dist: pandas>=2.0.0
28
+ Requires-Dist: pyemu>=1.4.0
29
+ Requires-Dist: scipy>=1.7.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: boltons; extra == 'dev'
32
+ Requires-Dist: codespell[toml]>=2.2.2; extra == 'dev'
33
+ Requires-Dist: filelock; extra == 'dev'
34
+ Requires-Dist: flaky; extra == 'dev'
35
+ Requires-Dist: ipykernel; extra == 'dev'
36
+ Requires-Dist: jupyter; extra == 'dev'
37
+ Requires-Dist: jupyter-client>=8.4.0; extra == 'dev'
38
+ Requires-Dist: modflow-devtools>=1.9.1; extra == 'dev'
39
+ Requires-Dist: myst-parser; extra == 'dev'
40
+ Requires-Dist: nbconvert; extra == 'dev'
41
+ Requires-Dist: nbmake; extra == 'dev'
42
+ Requires-Dist: nbsphinx; extra == 'dev'
43
+ Requires-Dist: pytest-cov; extra == 'dev'
44
+ Requires-Dist: pytest-dotenv; extra == 'dev'
45
+ Requires-Dist: pytest-order; extra == 'dev'
46
+ Requires-Dist: pytest-xdist; extra == 'dev'
47
+ Requires-Dist: pytest>=9.0.2; extra == 'dev'
48
+ Requires-Dist: pyyaml; extra == 'dev'
49
+ Requires-Dist: rtds-action; extra == 'dev'
50
+ Requires-Dist: ruff; extra == 'dev'
51
+ Requires-Dist: shapely; extra == 'dev'
52
+ Requires-Dist: sphinx-rtd-theme>=1; extra == 'dev'
53
+ Requires-Dist: sphinx>=7.1.2; extra == 'dev'
54
+ Requires-Dist: tomli-w; extra == 'dev'
55
+ Provides-Extra: doc
56
+ Requires-Dist: boltons; extra == 'doc'
57
+ Requires-Dist: codespell[toml]>=2.2.2; extra == 'doc'
58
+ Requires-Dist: filelock; extra == 'doc'
59
+ Requires-Dist: flaky; extra == 'doc'
60
+ Requires-Dist: ipykernel; extra == 'doc'
61
+ Requires-Dist: jupyter; extra == 'doc'
62
+ Requires-Dist: jupyter-client>=8.4.0; extra == 'doc'
63
+ Requires-Dist: modflow-devtools>=1.9.1; extra == 'doc'
64
+ Requires-Dist: myst-parser; extra == 'doc'
65
+ Requires-Dist: nbconvert; extra == 'doc'
66
+ Requires-Dist: nbmake; extra == 'doc'
67
+ Requires-Dist: nbsphinx; extra == 'doc'
68
+ Requires-Dist: pytest-cov; extra == 'doc'
69
+ Requires-Dist: pytest-dotenv; extra == 'doc'
70
+ Requires-Dist: pytest-order; extra == 'doc'
71
+ Requires-Dist: pytest-xdist; extra == 'doc'
72
+ Requires-Dist: pytest>=9.0.2; extra == 'doc'
73
+ Requires-Dist: pyyaml; extra == 'doc'
74
+ Requires-Dist: rtds-action; extra == 'doc'
75
+ Requires-Dist: ruff; extra == 'doc'
76
+ Requires-Dist: shapely; extra == 'doc'
77
+ Requires-Dist: sphinx-rtd-theme>=1; extra == 'doc'
78
+ Requires-Dist: sphinx>=7.1.2; extra == 'doc'
79
+ Requires-Dist: tomli-w; extra == 'doc'
80
+ Provides-Extra: lint
81
+ Requires-Dist: codespell[toml]>=2.2.2; extra == 'lint'
82
+ Requires-Dist: ruff; extra == 'lint'
83
+ Provides-Extra: test
84
+ Requires-Dist: boltons; extra == 'test'
85
+ Requires-Dist: codespell[toml]>=2.2.2; extra == 'test'
86
+ Requires-Dist: filelock; extra == 'test'
87
+ Requires-Dist: flaky; extra == 'test'
88
+ Requires-Dist: ipykernel; extra == 'test'
89
+ Requires-Dist: jupyter; extra == 'test'
90
+ Requires-Dist: jupyter-client>=8.4.0; extra == 'test'
91
+ Requires-Dist: modflow-devtools>=1.9.1; extra == 'test'
92
+ Requires-Dist: nbmake; extra == 'test'
93
+ Requires-Dist: pytest-cov; extra == 'test'
94
+ Requires-Dist: pytest-dotenv; extra == 'test'
95
+ Requires-Dist: pytest-order; extra == 'test'
96
+ Requires-Dist: pytest-xdist; extra == 'test'
97
+ Requires-Dist: pytest>=9.0.2; extra == 'test'
98
+ Requires-Dist: ruff; extra == 'test'
99
+ Requires-Dist: shapely; extra == 'test'
100
+ Requires-Dist: tomli-w; extra == 'test'
101
+ Description-Content-Type: text/markdown
102
+
103
+ # mf6adj
104
+
105
+ ![mf6adj](https://raw.githubusercontent.com/INTERA-Inc/mf6adj/master/.images/mf6adj.png)
106
+
107
+ **mf6adj** is a Python package for adjoint-state sensitivity analysis with
108
+ MODFLOW 6. It uses the [MODFLOW 6 API](https://github.com/MODFLOW-USGS/modflowapi)
109
+ to access the internal solution components at run time — no modifications to
110
+ MODFLOW 6 are required. Given one or more user-defined performance measures
111
+ (heads, boundary fluxes, or composite objectives), mf6adj computes the
112
+ sensitivity of each measure to model parameters across the full model domain.
113
+
114
+ ## Installation
115
+
116
+ **pip**
117
+
118
+ ```bash
119
+ pip install mf6adj
120
+ ```
121
+
122
+ **conda-forge**
123
+
124
+ ```bash
125
+ conda install -c conda-forge mf6adj
126
+ ```
127
+
128
+ mf6adj drives MODFLOW 6 through its shared library (`libmf6`). The easiest
129
+ way to get both is through the
130
+ [`flopy`](https://github.com/modflowpy/flopy) helper:
131
+
132
+ ```bash
133
+ get-modflow --subset mf6,libmf6 :python
134
+ ```
135
+
136
+ ## Quick start
137
+
138
+ ```python
139
+ import flopy
140
+ import mf6adj
141
+
142
+ # locate the MF6 binary and shared library in the active conda environment
143
+ mf6_bin, lib_name = mf6adj.get_conda_mf6_paths()
144
+
145
+ # run the baseline forward model
146
+ flopy.run_model(exe_name=mf6_bin, namefile=None, model_ws="path/to/model")
147
+
148
+ # write a performance-measure file
149
+ with open("path/to/model/model.adj", "w") as f:
150
+ f.write("begin performance_measure head_obs\n")
151
+ f.write("1 1 1 5 5 head direct 1.0 -1.0e+30\n")
152
+ f.write("end performance_measure\n")
153
+
154
+ # solve forward and adjoint
155
+ adj = mf6adj.Mf6Adj("model.adj", str(lib_name), working_directory="path/to/model")
156
+ adj.solve_forward_model()
157
+ sensitivity_dfs = adj.solve_adjoint()
158
+ adj.finalize()
159
+
160
+ print(sensitivity_dfs["head_obs"])
161
+ ```
162
+
163
+ ## Documentation
164
+
165
+ Full documentation, including API reference and example notebooks, is available
166
+ at [mf6adj.readthedocs.io](https://md6adj.readthedocs.io).
167
+
168
+ ## How to cite
169
+
170
+ If you use mf6adj in your work, please cite:
171
+
172
+ > Hayek, M., White, J. T., Markovich, K. H., Hughes, J. D., & Lavenue, M. (2025).
173
+ > MF6-ADJ: A Non-Intrusive Adjoint Sensitivity Capability for MODFLOW 6.
174
+ > *Groundwater*, 63(6), 874–888. https://doi.org/10.1111/gwat.70025
175
+
176
+ ## License
177
+
178
+ [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/)
mf6adj-1.0.0/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # mf6adj
2
+
3
+ ![mf6adj](https://raw.githubusercontent.com/INTERA-Inc/mf6adj/master/.images/mf6adj.png)
4
+
5
+ **mf6adj** is a Python package for adjoint-state sensitivity analysis with
6
+ MODFLOW 6. It uses the [MODFLOW 6 API](https://github.com/MODFLOW-USGS/modflowapi)
7
+ to access the internal solution components at run time — no modifications to
8
+ MODFLOW 6 are required. Given one or more user-defined performance measures
9
+ (heads, boundary fluxes, or composite objectives), mf6adj computes the
10
+ sensitivity of each measure to model parameters across the full model domain.
11
+
12
+ ## Installation
13
+
14
+ **pip**
15
+
16
+ ```bash
17
+ pip install mf6adj
18
+ ```
19
+
20
+ **conda-forge**
21
+
22
+ ```bash
23
+ conda install -c conda-forge mf6adj
24
+ ```
25
+
26
+ mf6adj drives MODFLOW 6 through its shared library (`libmf6`). The easiest
27
+ way to get both is through the
28
+ [`flopy`](https://github.com/modflowpy/flopy) helper:
29
+
30
+ ```bash
31
+ get-modflow --subset mf6,libmf6 :python
32
+ ```
33
+
34
+ ## Quick start
35
+
36
+ ```python
37
+ import flopy
38
+ import mf6adj
39
+
40
+ # locate the MF6 binary and shared library in the active conda environment
41
+ mf6_bin, lib_name = mf6adj.get_conda_mf6_paths()
42
+
43
+ # run the baseline forward model
44
+ flopy.run_model(exe_name=mf6_bin, namefile=None, model_ws="path/to/model")
45
+
46
+ # write a performance-measure file
47
+ with open("path/to/model/model.adj", "w") as f:
48
+ f.write("begin performance_measure head_obs\n")
49
+ f.write("1 1 1 5 5 head direct 1.0 -1.0e+30\n")
50
+ f.write("end performance_measure\n")
51
+
52
+ # solve forward and adjoint
53
+ adj = mf6adj.Mf6Adj("model.adj", str(lib_name), working_directory="path/to/model")
54
+ adj.solve_forward_model()
55
+ sensitivity_dfs = adj.solve_adjoint()
56
+ adj.finalize()
57
+
58
+ print(sensitivity_dfs["head_obs"])
59
+ ```
60
+
61
+ ## Documentation
62
+
63
+ Full documentation, including API reference and example notebooks, is available
64
+ at [mf6adj.readthedocs.io](https://md6adj.readthedocs.io).
65
+
66
+ ## How to cite
67
+
68
+ If you use mf6adj in your work, please cite:
69
+
70
+ > Hayek, M., White, J. T., Markovich, K. H., Hughes, J. D., & Lavenue, M. (2025).
71
+ > MF6-ADJ: A Non-Intrusive Adjoint Sensitivity Capability for MODFLOW 6.
72
+ > *Groundwater*, 63(6), 874–888. https://doi.org/10.1111/gwat.70025
73
+
74
+ ## License
75
+
76
+ [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/)
@@ -0,0 +1,58 @@
1
+ import os
2
+ import pathlib as pl
3
+
4
+
5
+ def find_files_with_extension(directory, extension):
6
+ """
7
+ Finds all files with the specified extension in the given directory and
8
+ its subdirectories.
9
+
10
+ Args:
11
+ directory: The path to the directory to search.
12
+ extension: The file extension to search for (e.g., ".txt", ".pdf").
13
+
14
+ Returns:
15
+ A list of Path objects representing the files found.
16
+ """
17
+ path = pl.Path(directory)
18
+ if not path.is_dir():
19
+ raise NotADirectoryError(f"'{directory}' is not a valid directory.")
20
+
21
+ return list(path.rglob(f"*{extension}"))
22
+
23
+
24
+ directory_path = ".."
25
+ file_extension = ".ipynb"
26
+ exclude_paths = (
27
+ ".ipynb_checkpoints",
28
+ "site-packages",
29
+ ".temp",
30
+ )
31
+ notebook_count = 0
32
+ try:
33
+ files = find_files_with_extension(directory_path, file_extension)
34
+ if files:
35
+ print(f"Files with extension '{file_extension}' found in '{directory_path}':")
36
+ for file in files:
37
+ exclude = False
38
+ for epath in exclude_paths:
39
+ if epath in str(file):
40
+ exclude = True
41
+ break
42
+ if exclude:
43
+ print(f"skipping...{file}")
44
+ else:
45
+ print(f"clearing...{file}")
46
+ os.system(
47
+ "jupyter nbconvert --ClearOutputPreprocessor.enabled=True "
48
+ + f"--ClearMetadataPreprocessor.enabled=True --inplace {file}"
49
+ )
50
+ notebook_count += 1
51
+ else:
52
+ print(
53
+ f"No files with extension '{file_extension}' found in '{directory_path}'."
54
+ )
55
+ print(f"notebooks cleared...{notebook_count}")
56
+
57
+ except NotADirectoryError as e:
58
+ print(e)