Skip to content

Commit 28dffb3

Browse files
committed
updating, adding to example notebooks
1 parent 8f1a216 commit 28dffb3

4 files changed

Lines changed: 756 additions & 210 deletions

File tree

docs/examples.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ Example Notebooks
1111
examples/example_005_chunked_data
1212
examples/example_006_yt_method_access
1313
examples/example_007_interpolation
14-
examples/example_007_interpolation_with_refinement
14+
examples/example_008_interpolation_with_refinement
15+
examples/example_010_custom_transformations
1516

1617
These notebooks demonstrate `yt_xarray` usage:
1718

@@ -23,3 +24,4 @@ These notebooks demonstrate `yt_xarray` usage:
2324
- Example 006: :doc:`examples/example_006_yt_method_access`
2425
- Example 007: :doc:`examples/example_007_interpolation`
2526
- Example 008: :doc:`examples/example_008_interpolation_with_refinement`
27+
- Example 010: :doc:`examples/example_010_custom_transformations`

docs/examples/example_007_interpolation.ipynb

Lines changed: 493 additions & 206 deletions
Large diffs are not rendered by default.
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "c8dd1a63-cf7d-4a28-878b-54167df286c1",
6+
"metadata": {},
7+
"source": [
8+
"## Customing transformations and interpolations\n",
9+
"\n",
10+
"The transformations and interpolation frameworks are intentionally written in an open-ended manner so that you can write your own transformations for your particular data. \n",
11+
"\n",
12+
"To write your own transformer class, you should inherit from the abstract `Transformer` and implement a number of methods: \n",
13+
"\n",
14+
"* `_calculate_transformed`\n",
15+
"* `_calculate_native`\n",
16+
"* `calculate_transformed_bbox`\n",
17+
"\n",
18+
"Additionally, the base `Transformer` allows arbitary coordinate names, so it is often helpful to override the `__init__` method in order to specify the expected coordinate names. \n",
19+
"\n",
20+
"So to get started, let's define a transformer to go from an arbitrary 2d coordinate system with coordinate axes `b` and `c` to 3D cartesian coordinates and being by overriding `__init__`:\n",
21+
"\n",
22+
"```python\n",
23+
"from yt_xarray.transformations import Transformer\n",
24+
"\n",
25+
"class MyTransformer(Transformer):\n",
26+
"\n",
27+
" def __init__(self): \n",
28+
" native_coords = ('b', 'c')\n",
29+
" transformed_coords = ('x', 'y', 'z')\n",
30+
" super().__init__(native_coords, transformed_coords)\n",
31+
"```\n",
32+
"\n",
33+
"\n",
34+
"Now let's define `_calculate_transformed` to describe the function x, y, z = f(b, c). `_calculate_transformed` must conform to a number of requirmements. First, `_calculate_transformed` must accept a `**coords` argument. That `**coords` keyword dictionary is **guaranteed** to have entries keyed by the `native_coords` tuple (validation is taken care by methods in the abstract class). `_calculate_transformed` must then return the coordinates in the transformed coordinate system. We'll do something competely arbitrary here... \n",
35+
"\n",
36+
"```python\n",
37+
"\n",
38+
" def _calculate_transformed(self, **coords):\n",
39+
" b = coords['b'] \n",
40+
" c = coords['c'] \n",
41+
" x = b * 2 \n",
42+
" y = c * 4\n",
43+
" z = np.sqrt(x**2 + y**2) \n",
44+
" return x, y, z\n",
45+
"```\n",
46+
"\n",
47+
"Now, add on `_calculate_native`, which in this exmaple will go from (x, y, z) to (b, c). \n",
48+
"\n",
49+
"```python \n",
50+
" \n",
51+
" def _calculate_native(self, **coords):\n",
52+
" x = coords['x']\n",
53+
" y = coords['y'] \n",
54+
" \n",
55+
" b = x / 2.0 \n",
56+
" c = y / 4.0 \n",
57+
" return b, c \n",
58+
"```\n",
59+
"\n",
60+
"And finally, `calculate_transformed_bbox` must provide a method for calculating the bounding range of coordinates in the transformed coordinate given bounds in the native coordinate system. In this arbitrary coordinate system, we can simply call the method's `to_transformed` at the bounds of the native range to get the bounding box in the transformed system: \n",
61+
"\n",
62+
"``` python\n",
63+
" def calculate_transformed_bbox(self, bbox_dict):\n",
64+
" b_min_max = bbox_dict['b']\n",
65+
" c_min_max = bbox_dict['c']\n",
66+
"\n",
67+
" xmin, ymin, zmin = self.to_transformed(b=b_min_max[0], \n",
68+
" c=c_min_max[0])\n",
69+
" xmax, ymax, zmax = self.to_transformed(b=b_min_max[1], \n",
70+
" c=c_min_max[1])\n",
71+
"```\n",
72+
"\n",
73+
"Putting it all together:\n"
74+
]
75+
},
76+
{
77+
"cell_type": "code",
78+
"execution_count": 4,
79+
"id": "2add05c6-e95e-4504-a3cb-85c6d3720968",
80+
"metadata": {},
81+
"outputs": [],
82+
"source": [
83+
"import numpy as np \n",
84+
"from yt_xarray.transformations import Transformer\n",
85+
"\n",
86+
"class MyTransformer(Transformer):\n",
87+
"\n",
88+
" def __init__(self): \n",
89+
" native_coords = ('b', 'c')\n",
90+
" transformed_coords = ('x', 'y', 'z')\n",
91+
" super().__init__(native_coords, transformed_coords)\n",
92+
"\n",
93+
" def _calculate_transformed(self, **coords):\n",
94+
" b = coords['b'] \n",
95+
" c = coords['c'] \n",
96+
" x = b * 2. \n",
97+
" y = c * 4.\n",
98+
" z = np.sqrt(x**2 + y**2) \n",
99+
" return x, y, z\n",
100+
"\n",
101+
" def _calculate_native(self, **coords):\n",
102+
" x = coords['x']\n",
103+
" y = coords['y'] \n",
104+
" \n",
105+
" b = x / 2.0 \n",
106+
" c = y / 4.0 \n",
107+
" return b, c \n",
108+
"\n",
109+
" def calculate_transformed_bbox(self, bbox_dict):\n",
110+
" b_min_max = bbox_dict['b']\n",
111+
" c_min_max = bbox_dict['c']\n",
112+
"\n",
113+
" xmin, ymin, zmin = self.to_transformed(b=b_min_max[0], \n",
114+
" c=c_min_max[0])\n",
115+
" xmax, ymax, zmax = self.to_transformed(b=b_min_max[1], \n",
116+
" c=c_min_max[1])"
117+
]
118+
},
119+
{
120+
"cell_type": "markdown",
121+
"id": "06eed913-00b3-4440-a166-04fd446f61da",
122+
"metadata": {},
123+
"source": [
124+
"our transformer is now available to use! "
125+
]
126+
},
127+
{
128+
"cell_type": "code",
129+
"execution_count": 5,
130+
"id": "bf9f528b-2bf4-45c6-81a9-a92bb7462608",
131+
"metadata": {},
132+
"outputs": [],
133+
"source": [
134+
"mtf = MyTransformer()"
135+
]
136+
},
137+
{
138+
"cell_type": "code",
139+
"execution_count": 6,
140+
"id": "c764bf56-b3c4-434f-9cb6-c0ca0113736c",
141+
"metadata": {},
142+
"outputs": [
143+
{
144+
"data": {
145+
"text/plain": [
146+
"(0.0, 0.0, 0.0)"
147+
]
148+
},
149+
"execution_count": 6,
150+
"metadata": {},
151+
"output_type": "execute_result"
152+
}
153+
],
154+
"source": [
155+
"x, y, z = mtf.to_transformed(b=0,c=0)\n",
156+
"x, y, z"
157+
]
158+
},
159+
{
160+
"cell_type": "code",
161+
"execution_count": 7,
162+
"id": "a5654087-b37a-460e-9034-e0792cd3a167",
163+
"metadata": {},
164+
"outputs": [
165+
{
166+
"data": {
167+
"text/plain": [
168+
"(0.0, 0.0)"
169+
]
170+
},
171+
"execution_count": 7,
172+
"metadata": {},
173+
"output_type": "execute_result"
174+
}
175+
],
176+
"source": [
177+
"mtf.to_native(x=x, y=y, z=z)"
178+
]
179+
},
180+
{
181+
"cell_type": "code",
182+
"execution_count": 8,
183+
"id": "f4933f94-6ab2-4827-8192-59363f116327",
184+
"metadata": {},
185+
"outputs": [
186+
{
187+
"name": "stdout",
188+
"output_type": "stream",
189+
"text": [
190+
"1.0 40.0 40.01249804748511\n"
191+
]
192+
},
193+
{
194+
"data": {
195+
"text/plain": [
196+
"(0.5, 10.0)"
197+
]
198+
},
199+
"execution_count": 8,
200+
"metadata": {},
201+
"output_type": "execute_result"
202+
}
203+
],
204+
"source": [
205+
"x, y, z = mtf.to_transformed(b=0.5,c=10.)\n",
206+
"print(x, y, z)\n",
207+
"mtf.to_native(x=x, y=y, z=z)"
208+
]
209+
},
210+
{
211+
"cell_type": "markdown",
212+
"id": "07be7296-4be3-4c62-9a3e-95941b1b73ef",
213+
"metadata": {},
214+
"source": [
215+
"Additionally, as long as your custom transformer transforms to and from 3D cartesian coordinates and if the \"native\" coordinates match an xarray dataset field's dimensions, **you can hand off your custom transformer to `build_interpolated_cartesian_ds`** and build a yt cartesian dataset that reads and interpolates from an arbitrary coordinate system! "
216+
]
217+
},
218+
{
219+
"cell_type": "markdown",
220+
"id": "fb1249fa-fcca-4fff-b0e5-5757cd6a3c81",
221+
"metadata": {},
222+
"source": [
223+
"### Custom interpolations\n",
224+
"\n"
225+
]
226+
},
227+
{
228+
"cell_type": "code",
229+
"execution_count": null,
230+
"id": "45203947-4152-4e68-a12f-274f8ee1a978",
231+
"metadata": {},
232+
"outputs": [],
233+
"source": []
234+
}
235+
],
236+
"metadata": {
237+
"kernelspec": {
238+
"display_name": "Python 3 (ipykernel)",
239+
"language": "python",
240+
"name": "python3"
241+
},
242+
"language_info": {
243+
"codemirror_mode": {
244+
"name": "ipython",
245+
"version": 3
246+
},
247+
"file_extension": ".py",
248+
"mimetype": "text/x-python",
249+
"name": "python",
250+
"nbconvert_exporter": "python",
251+
"pygments_lexer": "ipython3",
252+
"version": "3.10.11"
253+
}
254+
},
255+
"nbformat": 4,
256+
"nbformat_minor": 5
257+
}

yt_xarray/transformations.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ def to_transformed(self, **coords):
169169
return self._calculate_transformed(**new_coords)
170170

171171
@abc.abstractmethod
172-
def calculate_transformed_bbox(self, bbox_dict: dict):
172+
def calculate_transformed_bbox(self, bbox_dict: dict) -> np.ndarray:
173173
"""
174174
Calculates a bounding box in transformed coordinates for a bounding box dictionary
175175
in native coordinates.
@@ -247,7 +247,7 @@ def _calculate_native(self, **coords):
247247
native.append(np.asarray(coords[nc + "_sc"]) / self.scale[nc])
248248
return native
249249

250-
def calculate_transformed_bbox(self, bbox_dict: dict):
250+
def calculate_transformed_bbox(self, bbox_dict: dict) -> np.ndarray:
251251
"""
252252
Calculates a bounding box in transformed coordinates for a bounding box dictionary
253253
in native coordinates.
@@ -393,7 +393,7 @@ def _calculate_native(self, **coords):
393393
r = self._r_o - r
394394
return r, lat, lon
395395

396-
def calculate_transformed_bbox(self, bbox_dict: dict):
396+
def calculate_transformed_bbox(self, bbox_dict: dict) -> np.ndarray:
397397
"""
398398
Calculates a bounding box in transformed coordinates for a bounding box dictionary
399399
in native coordinates.

0 commit comments

Comments
 (0)