Skip to content

Commit d2cfe38

Browse files
authored
add Matlab example to the README (#300)
1 parent 54f109d commit d2cfe38

File tree

2 files changed

+74
-11
lines changed

2 files changed

+74
-11
lines changed

.github/workflows/readme_listings.yml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ jobs:
9595

9696
assert:
9797
runs-on: ubuntu-latest
98-
needs: [julia, python, matlab-draft, fortran]
98+
needs: [julia, python, matlab, fortran]
9999
steps:
100100
- uses: actions/setup-python@v2
101101
- run: pip install numpy
@@ -105,8 +105,8 @@ jobs:
105105
path: readme_output
106106
- run : python -c 'import numpy as np; import os; dir="readme_output/"; data=[float(np.loadtxt(dir+file)) for file in os.listdir(dir)]; print("data:", data); similar_as_first = np.array([abs(data[0]-k)/data[0] for k in data[1:]]); print("similar_as_first", similar_as_first); assert((similar_as_first < .5).all())'
107107

108-
matlab-draft:
109-
runs-on: ubuntu-latest
108+
matlab:
109+
runs-on: ubuntu-20.04
110110

111111
steps:
112112
- uses: actions/checkout@v2
@@ -130,10 +130,24 @@ jobs:
130130
- run: python -c "import pytest_codeblocks; code=pytest_codeblocks.extract_from_file('README.md'); f=open('readme.m', 'w'); f.writelines(block.code for block in code if block.syntax=='Matlab'); f.close()"
131131
- run: cat -n readme.m
132132

133+
# see https://github.com/pybind/cmake_example/pull/164
134+
- run: |
135+
echo "pybind11_type=type" > pybind11_builtins.py
136+
echo "PYTHONPATH=." >> $GITHUB_ENV
137+
133138
- uses: matlab-actions/setup-matlab@v0
134139
with:
135140
release: R2022a
136141

142+
- run: mkdir readme_output
143+
137144
- uses: matlab-actions/run-command@v0
138145
with:
139-
command: readme
146+
startup-options: -nojvm
147+
command: diary('readme_output/matlab.txt'), readme
148+
149+
- uses: actions/upload-artifact@v2
150+
with:
151+
name: readme_output
152+
path: readme_output
153+

README.md

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
PyPartMC is a Python interface to [PartMC](https://lagrange.mechse.illinois.edu/partmc/),
66
a particle-resolved Monte-Carlo code for atmospheric aerosol simulation.
77
PyPartMC is implemented in C++ and it also constitutes a C++ API to the PartMC Fortran internals.
8-
The Python API can facilitate using PartMC from other environments - see, e.g., Julia example below.
8+
The Python API can facilitate using PartMC from other environments - see, e.g., Julia and Matlab examples below.
99

1010
For an outline of the project, rationale, architecture, and features, refer to: [D'Aquino et al., 2023 (arXiv)](https://doi.org/10.48550/arXiv.2308.02052) (please cite if PyPartMC is used in your research).
1111
For a list of talks and other relevant resources, please see [project Wiki](https://github.com/open-atmos/PyPartMC/wiki/).
@@ -52,7 +52,7 @@ import PyPartMC
5252
- ships with [a set of examples](https://github.com/open-atmos/PyPartMC/tree/main/examples) maintained in a form of Jupyter notebooks
5353
- Pythonic API (but retaining PartMC jargon) incl. Python GC deallocation of Fortran objects
5454
- specification of parameters using native Python datatypes (lists, dicts) in place of PartMC spec files
55-
- code snippets in README depicting how to use PyPartMC from Julia (also executed on CI)
55+
- code snippets in README depicting how to use PyPartMC from Julia and Matlab (also executed on CI)
5656
- auto-generated [API docs on the web](https://open-atmos.github.io/PyPartMC/)
5757
- support for [de]serialization of selected wrapped structures using JSON
5858
- based on [unmodified PartMC code](https://github.com/open-atmos/PyPartMC/tree/main/gitmodules)
@@ -62,9 +62,9 @@ import PyPartMC
6262
## Usage examples
6363

6464
The listings below depict how the identical task of randomly sampling particles from an aerosol size distribution in PartMC can be
65-
done in three different programming languages.
65+
done in different programming languages.
6666

67-
For a Fortran equivalent of the Python and Julia programs below, see the [`readme_fortran` folder](https://github.com/open-atmos/PyPartMC/tree/main/readme_fortran).
67+
For a Fortran equivalent of the Python, Julia and Matlab programs below, see the [`readme_fortran` folder](https://github.com/open-atmos/PyPartMC/tree/main/readme_fortran).
6868

6969
#### Python
7070

@@ -110,7 +110,7 @@ aero_state.dist_sample(aero_dist)
110110
print(np.dot(aero_state.masses(), aero_state.num_concs), "# kg/m3")
111111
```
112112

113-
#### Julia
113+
#### Julia (using [PyCall.jl](https://github.com/JuliaPy/PyCall.jl))
114114
```Julia
115115
using Pkg
116116
Pkg.add("PyCall")
@@ -154,6 +154,51 @@ aero_state.dist_sample(aero_dist)
154154
print(aero_state.masses()'aero_state.num_concs, "# kg/m3")
155155
```
156156

157+
#### Matlab (using [Matlab's built-in Python interface](https://www.mathworks.com/help/matlab/python-language.html))
158+
159+
````Matlab
160+
ppmc = py.importlib.import_module('PyPartMC');
161+
si = py.importlib.import_module('PyPartMC').si;
162+
163+
aero_data = ppmc.AeroData(py.tuple({ ...
164+
py.dict(pyargs("OC", py.tuple({1000 * si.kg/si.m^3, 0, 1e-3 * si.kg/si.mol, 0.001}))), ...
165+
py.dict(pyargs("BC", py.tuple({1800 * si.kg/si.m^3, 0, 1e-3 * si.kg/si.mol, 0}))) ...
166+
}));
167+
168+
aero_dist = ppmc.AeroDist(aero_data, py.tuple({ ...
169+
py.dict(pyargs( ...
170+
"cooking", py.dict(pyargs( ...
171+
"mass_frac", py.tuple({py.dict(pyargs("OC", py.tuple({1})))}), ...
172+
"diam_type", "geometric", ...
173+
"mode_type", "log_normal", ...
174+
"num_conc", 3200 / si.cm^3, ...
175+
"geom_mean_diam", 8.64 * si.nm, ...
176+
"log10_geom_std_dev", .28 ...
177+
)) ...
178+
)), ...
179+
py.dict(pyargs( ...
180+
"diesel", py.dict(pyargs( ...
181+
"mass_frac", py.tuple({ ...
182+
py.dict(pyargs("OC", py.tuple({.3}))), ...
183+
py.dict(pyargs("BC", py.tuple({.7}))), ...
184+
}), ...
185+
"diam_type", "geometric", ...
186+
"mode_type", "log_normal", ...
187+
"num_conc", 2900 / si.cm^3, ...
188+
"geom_mean_diam", 50 * si.nm, ...
189+
"log10_geom_std_dev", .24 ...
190+
)) ...
191+
)) ...
192+
}));
193+
194+
n_part = 100;
195+
aero_state = ppmc.AeroState(aero_data, n_part, "nummass_source");
196+
aero_state.dist_sample(aero_dist);
197+
masses = cell(aero_state.masses());
198+
num_concs = cell(aero_state.num_concs);
199+
fprintf('%g # kg/m3\n', dot([masses{:}], [num_concs{:}]))
200+
````
201+
157202
#### usage in other projects
158203

159204
PyPartMC is used within the [test workflow of the PySDM project](https://github.com/atmos-cloud-sim-uj/PySDM/tree/main/tests/smoke_tests/box/partmc).
@@ -174,10 +219,14 @@ flowchart TD
174219
subgraph J ["Julia"]
175220
julia_user_code["Julia user code"] --> PyCall.jl
176221
end
222+
subgraph M ["Matlab"]
223+
matlab_user_code["Matlab user code"] --> matlab_python["Matlab built-in\nPython interface"]
224+
end
177225
subgraph P ["Python"]
178-
PyCall.jl --> PyPartMC
179226
python_user_code -.-> NumPy
180-
python_user_code["Python user code"] ---> PyPartMC["pubind11-generated PyPartMC module"]
227+
python_user_code["Python user code"] ---> PyPartMC["pubind11-generated\nPyPartMC module"]
228+
matlab_python --> PyPartMC
229+
PyCall.jl --> PyPartMC
181230
end
182231
subgraph Cpp ["C++"]
183232
cpp_user_code["C++ user code"] ----> ppmc_cpp

0 commit comments

Comments
 (0)