Skip to content

Commit cb672c0

Browse files
authored
Add initial notebook tests (#63)
* Add notebook tests first pass * Add test-tags to all cells that need to be tested. * Reintroduce create_new_stage() for better interactive notebook experience. Signed-off-by: Matias Codesal <mcodesal@nvidia.com> * Improve notebook tests and cleanup AI mess. Signed-off-by: Matias Codesal <mcodesal@nvidia.com> * Bug fix Signed-off-by: Matias Codesal <mcodesal@nvidia.com> --------- Signed-off-by: Matias Codesal <mcodesal@nvidia.com>
1 parent 967dacb commit cb672c0

26 files changed

Lines changed: 1068 additions & 68 deletions

docs/beyond-basics/active-inactive-prims.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,24 @@ We can use the following Python functions to set the "active" metadata on a prim
6363
* `UsdPrim.IsActive()` - Return whether a prim is currently active on the stage
6464

6565
## Examples
66+
+++ {"tags": ["remove-cell"]}
67+
>**NOTE**: Before starting make sure to run the cell below. This will install the relevant OpenUSD libraries that will be used through this notebook.
68+
+++
69+
```{code-cell}
70+
:tags: [remove-input]
71+
:test-tags: [active-inactive-setup]
72+
from lousd.utils.helperfunctions import create_new_stage
73+
```
74+
6675

6776
### Example 1: Setting Prims as Active/Inactive
6877

6978
+++ {"tags": ["remove-cell"]}
70-
>**NOTE**: The next cell is content setup for this example..
79+
>**NOTE**: The next cell is content setup for this example.
7180
+++
7281
```{code-cell}
7382
:tags: [remove-input]
83+
:test-tags: [active-inactive-content-setup]
7484
7585
from pxr import Usd, UsdGeom, UsdLux, UsdShade
7686
@@ -102,6 +112,7 @@ stage.Save()
102112
In this example, we will print out the contents of a stage at the start and then see how the contents change after deactivating a prim. Here's is what the USDA for this stage looks like:
103113

104114
```{code-cell}
115+
:test-tags: [active-inactive-deactivate]
105116
:emphasize-lines: 15-16
106117
107118
from pxr import Usd

docs/beyond-basics/custom-properties.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ Lastly, notice the `my_namespace:` prefix on the attribute. It's good practice t
106106
+++
107107
```{code-cell}
108108
:tags: [remove-input]
109+
:test-tags: [custom-properties-setup]
109110
from lousd.utils.visualization import DisplayUSD, DisplayCode
111+
from lousd.utils.helperfunctions import create_new_stage
110112
```
111113

112114
### Example 1: Creating Custom Attributes
@@ -116,6 +118,7 @@ from lousd.utils.visualization import DisplayUSD, DisplayCode
116118
+++
117119
```{code-cell}
118120
:tags: [remove-input, remove-output]
121+
:test-tags: [custom-properties-setup-asset]
119122
import shutil
120123
# cleanup any existing copy
121124
try:
@@ -131,12 +134,13 @@ Custom attributes in OpenUSD are used to define additional, user-specific proper
131134
In this example, we will author custom attributes to add more contextual information to a package asset.
132135

133136
```{code-cell}
137+
:test-tags: [custom-properties-create-attributes]
134138
:emphasize-lines: 13-23
135139
136140
from pxr import Usd, UsdGeom, Sdf
137141
138142
file_path = "_assets/custom_attributes.usda"
139-
stage: Usd.Stage = Usd.Stage.CreateNew(file_path)
143+
stage: Usd.Stage = create_new_stage(file_path)
140144
141145
world_xform: UsdGeom.Xform = UsdGeom.Xform.Define(stage, "/World")
142146
geometry_xform: UsdGeom.Xform = UsdGeom.Xform.Define(stage, world_xform.GetPath().AppendPath("Packages"))
@@ -176,7 +180,8 @@ After creating an attribute, we can set and get the value of the attribute, simi
176180

177181
Try applying the same logic to the other attributes.
178182

179-
```{code-cell}
183+
```{code-cell}
184+
:test-tags: [custom-properties-modify-attributes]
180185
:emphasize-lines: 7-10
181186
182187
from pxr import Usd
@@ -207,12 +212,13 @@ When working with grouped or compound data from other sources, namespace-prefixe
207212
Notice the double namespacing pattern `acme:sensor:temperature`. The first namespace (`acme:`) identifies the organization that created these custom properties, while the second namespace (`sensor:`) groups related properties together. This hierarchical approach allows you to both claim ownership of your custom properties and logically organize them into functional groups. It's a common pattern when mapping compound data types from other formats into USD.
208213

209214
```{code-cell}
215+
:test-tags: [custom-properties-namespaces]
210216
:emphasize-lines: 9-20
211217
212218
from pxr import Usd, UsdGeom, Sdf
213219
214220
file_path = "_assets/sensor_data.usda"
215-
stage: Usd.Stage = Usd.Stage.CreateNew(file_path)
221+
stage: Usd.Stage = create_new_stage(file_path)
216222
217223
# Create a prim to represent a sensor device
218224
sensor_prim = stage.DefinePrim("/EnvironmentSensor", "Xform")

docs/beyond-basics/model-kinds.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ prim.IsModel()
122122
+++
123123
```{code-cell}
124124
:tags: [remove-input]
125+
:test-tags: [model-kinds-setup]
125126
from lousd.utils.visualization import DisplayUSD, DisplayCode
126127
from lousd.utils.helperfunctions import create_new_stage
127128
```
@@ -131,12 +132,13 @@ from lousd.utils.helperfunctions import create_new_stage
131132
This example shows the practical benefit of Model Kinds. `/World` is marked as a group so children can qualify as models, `/World/Component` is classified as a component, and `/World/Markers` is left untagged. Model‑only traversal allow for edits only to the component while the markers remain untouched.
132133

133134
```{code-cell}
135+
:test-tags: [model-kinds-component-traversal]
134136
:emphasize-lines: 9-40
135137
from pxr import Usd, UsdGeom, Kind, Gf
136138
137139
# Create stage and model root
138140
file_path = "_assets/model_kinds_component.usda"
139-
stage = Usd.Stage.CreateNew(file_path)
141+
stage = create_new_stage(file_path)
140142
world_xform = UsdGeom.Xform.Define(stage, "/World")
141143
stage.SetDefaultPrim(world_xform.GetPrim())
142144

docs/beyond-basics/primvars.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ values = primvar.Get()
8484
+++
8585
```{code-cell}
8686
:tags: [remove-input]
87+
:test-tags: [primvars-setup]
8788
from lousd.utils.visualization import DisplayUSD, DisplayCode
8889
from lousd.utils.helperfunctions import create_new_stage
8990
```
@@ -93,12 +94,13 @@ from lousd.utils.helperfunctions import create_new_stage
9394
This example builds the same two‑quad mesh three times and authors the displayColor primvar with three {term}`interpolation <Interpolation>` modes: constant (one value for the whole gprim), uniform (one per face), and vertex (one per point).
9495

9596
```{code-cell}
97+
:test-tags: [primvars-displaycolor-interpolation]
9698
:emphasize-lines: 28-53
9799
from pxr import Usd, UsdGeom, Gf
98100
99101
# Create stage and default prim
100102
file_path = "_assets/primvars_displaycolor.usda"
101-
stage = Usd.Stage.CreateNew(file_path)
103+
stage = create_new_stage(file_path)
102104
world = UsdGeom.Xform.Define(stage, "/World")
103105
stage.SetDefaultPrim(world.GetPrim())
104106
@@ -164,6 +166,7 @@ DisplayCode(file_path)
164166
This example writes two vertex primvars on a quad: rest_state and deformation. It computes new points as rest_state + deformation, then {term}`time samples <Time Sample>` Mesh.points
165167

166168
```{code-cell}
169+
:test-tags: [primvars-mesh-deformation]
167170
:emphasize-lines: 34-57
168171
from pxr import Usd, UsdGeom, Sdf, Gf
169172
@@ -174,7 +177,7 @@ time_code_per_second = 30
174177
175178
# create stage and default prim
176179
file_path = "_assets/primvars_mesh_deformation.usda"
177-
stage = Usd.Stage.CreateNew(file_path)
180+
stage = create_new_stage(file_path)
178181
stage.SetStartTimeCode(start_tc)
179182
stage.SetEndTimeCode(end_tc)
180183
stage.SetTimeCodesPerSecond(time_code_per_second)

docs/beyond-basics/stage-traversal.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,15 @@ BAD_predicate = Usd.PrimIsActive and Usd.PrimIsLoaded
108108
+++
109109
```{code-cell}
110110
:tags: [remove-input]
111+
:test-tags: [stage-traversal-setup]
111112
from lousd.utils.visualization import DisplayUSD, DisplayCode
113+
from lousd.utils.helperfunctions import create_new_stage
112114
113115
114116
from pxr import Usd, UsdGeom, UsdLux, UsdShade
115117
116118
file_path = "_assets/stage_traversal.usda"
117-
stage: Usd.Stage = Usd.Stage.CreateNew(file_path)
119+
stage: Usd.Stage = create_new_stage(file_path)
118120
119121
world: UsdGeom.Xform = UsdGeom.Xform.Define(stage, "/World")
120122
stage.SetDefaultPrim(world.GetPrim())
@@ -146,6 +148,7 @@ DisplayCode(file_path)
146148
To traverse through the stage, we can use the [`Traverse()`](https://openusd.org/release/api/class_usd_stage.html#adba675b55f41cc1b305bed414fc4f178) method. This traversal will yield prims that are active, loaded, defined, non-abstract on the stage in depth-first order.
147149

148150
```{code-cell}
151+
:test-tags: [stage-traversal-traverse]
149152
:emphasize-lines: 7-10
150153
151154
# Import the Usd module from the pxr package
@@ -169,6 +172,7 @@ For this practical example, we will traverse the stage to operate on specific pr
169172
We can filter based on the type of the prim. For example, we can check if the prim is of type `scope` or `xform`. To do this we pass the prim into the constructor method for the prim type we are interested in. For example,`UsdGeom.Scope(prim)` is equivalent to [`UsdGeom.Scope.Get(prim.GetStage(), prim.GetPath())`](https://openusd.org/release/api/class_usd_geom_scope.html#a538339c2aa462ebcf1eb07fed16f9be4) for a valid prim. If the prim's type does not match, it will return an invalid prim.
170173

171174
```{code-cell}
175+
:test-tags: [stage-traversal-filter-types]
172176
:emphasize-lines: 7-21
173177
174178
# Import necessary modules from the pxr package
@@ -201,6 +205,7 @@ Using [`Traverse()`](https://openusd.org/release/api/class_usd_stage.html#adba67
201205
If you need to work within a specific scope or hierarchy in the stage, you can perform a traversal starting from a particular prim. Let's take a look at how we can traverse through the children of the default prim.
202206

203207
```{code-cell}
208+
:test-tags: [stage-traversal-children]
204209
:emphasize-lines: 10-13
205210
206211
# Import the `Usd` module from the `pxr` package:
@@ -227,6 +232,7 @@ Let's see an example of [`UsdPrimRange`](https://openusd.org/release/api/class_u
227232

228233

229234
```{code-cell}
235+
:test-tags: [stage-traversal-prim-range]
230236
:emphasize-lines: 7-9
231237
232238
# Import the Usd module from the pxr package

docs/beyond-basics/units.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ print(f"Updated to: {UsdPhysics.GetStageKilogramsPerUnit(stage)}")
152152
+++
153153
```{code-cell}
154154
:tags: [remove-input]
155+
:test-tags: [units-setup]
155156
from lousd.utils.visualization import DisplayUSD, DisplayCode
157+
from lousd.utils.helperfunctions import create_new_stage
156158
```
157159

158160
### Example 1: Demonstrating metersPerUnit Composition Behavior
@@ -165,12 +167,13 @@ This example shows what happens when assets with different `metersPerUnit` value
165167
Both cubes represent the same real-world size—1 meter. If USD automatically converted units during composition, both cubes would appear identical when referenced into any scene regardless of that scene's `metersPerUnit`. Let's see what actually happens when we reference both into a millimeter-scale scene.
166168

167169
```{code-cell}
170+
:test-tags: [units-meters-per-unit]
168171
:emphasize-lines: 7,10-11,25,28-29,50-51,54-55
169172
from pxr import Usd, UsdGeom, Sdf, Gf
170173
171174
# Create a cube asset in CENTIMETERS (metersPerUnit = 0.01)
172175
cm_asset_path = "_assets/1m_cube_centimeters.usda"
173-
cm_stage = Usd.Stage.CreateNew(cm_asset_path)
176+
cm_stage = create_new_stage(cm_asset_path)
174177
UsdGeom.SetStageUpAxis(cm_stage, UsdGeom.Tokens.y)
175178
UsdGeom.SetStageMetersPerUnit(cm_stage, 0.01) # Centimeters
176179
@@ -188,7 +191,7 @@ print(f" -> Represents a {cube_in_cm.GetSizeAttr().Get() * UsdGeom.GetStageMete
188191
189192
# Create a cube asset in MILLIMETERS (metersPerUnit = 0.001)
190193
mm_asset_path = "_assets/cube_in_millimeters.usda"
191-
mm_stage = Usd.Stage.CreateNew(mm_asset_path)
194+
mm_stage = create_new_stage(mm_asset_path)
192195
UsdGeom.SetStageUpAxis(mm_stage, UsdGeom.Tokens.y)
193196
UsdGeom.SetStageMetersPerUnit(mm_stage, 0.001) # Millimeters
194197
@@ -206,7 +209,7 @@ print(f" -> Represents a {cube_in_mm.GetSizeAttr().Get() * UsdGeom.GetStageMete
206209
207210
# Create a scene that references both cubes (using millimeter scale)
208211
scene_path = "_assets/units_mismatch_scene.usda"
209-
scene_stage = Usd.Stage.CreateNew(scene_path)
212+
scene_stage = create_new_stage(scene_path)
210213
UsdGeom.SetStageUpAxis(scene_stage, UsdGeom.Tokens.y)
211214
UsdGeom.SetStageMetersPerUnit(scene_stage, 0.001) # Scene is in millimeters
212215
@@ -253,12 +256,13 @@ print(scene_stage.ExportToString(addSourceFileComment=False))
253256
This example demonstrates that USD **does** automatically handle `timeCodesPerSecond` differences during composition. We'll create an animated asset at 60 fps and reference it into a 24 fps scene.
254257

255258
```{code-cell}
259+
:test-tags: [units-timecodes-per-second]
256260
:emphasize-lines: 8-10, 17-20, 25-27, 34-36, 52-55, 57-59, 63-67
257261
from pxr import Usd, UsdGeom, Gf
258262
259263
# Create animated asset at 60 fps
260264
anim_asset_path = "_assets/animated_60fps.usda"
261-
anim_stage = Usd.Stage.CreateNew(anim_asset_path)
265+
anim_stage = create_new_stage(anim_asset_path)
262266
UsdGeom.SetStageUpAxis(anim_stage, UsdGeom.Tokens.y)
263267
UsdGeom.SetStageMetersPerUnit(anim_stage, 1.0)
264268
anim_stage.SetTimeCodesPerSecond(60) # 60 fps
@@ -284,7 +288,7 @@ print(f" -> Animates from x=-5 to x=5\n")
284288
285289
# Create scene at 24 fps that references the 60fps animation
286290
scene_24fps_path = "_assets/units_timecode_scene.usda"
287-
scene_stage = Usd.Stage.CreateNew(scene_24fps_path)
291+
scene_stage = create_new_stage(scene_24fps_path)
288292
UsdGeom.SetStageUpAxis(scene_stage, UsdGeom.Tokens.y)
289293
UsdGeom.SetStageMetersPerUnit(scene_stage, 1.0)
290294
scene_stage.SetTimeCodesPerSecond(24) # Scene is 24 fps

docs/beyond-basics/value-resolution.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ When you get an attribute value without an explicit time code, the default time
108108
+++
109109
```{code-cell}
110110
:tags: [remove-input]
111+
:test-tags: [value-resolution-setup]
111112
from lousd.utils.visualization import DisplayUSD, DisplayCode
112113
from lousd.utils.helperfunctions import create_new_stage
113114
```
@@ -117,6 +118,7 @@ from lousd.utils.helperfunctions import create_new_stage
117118
This example shows how a transform attribute (the `xformOp:scale` authored by `XformCommonAPI`) resolves from four sources: a {term}`fallback <Fallback>` value when no authored value exists, an authored default value, authored time sample values, and interpolated values between time samples.
118119

119120
```{code-cell}
121+
:test-tags: [value-resolution-attribute-animation]
120122
:emphasize-lines: 27-67
121123
from pxr import Usd, UsdGeom
122124
@@ -208,13 +210,14 @@ Notice `Get(..., Usd.TimeCode.Default())` returns the user defined default (non
208210
This example composes {term}`layers <Layer>` to show two resolution rules for dictionary metadata like `customData` (per key by strength) as well as relationships `list editing semantics`.
209211

210212
```{code-cell}
213+
:test-tags: [value-resolution-customdata-relationship]
211214
:emphasize-lines: 37-60
212215
from pxr import Usd, UsdGeom
213216
import os
214217
215218
# --- Layer 1 (weaker)
216219
layer_1_path = "_assets/value_resolution_layer_1.usda"
217-
layer_1_stage = Usd.Stage.CreateNew(layer_1_path)
220+
layer_1_stage = create_new_stage(layer_1_path)
218221
219222
layer_1_xform = UsdGeom.Xform.Define(layer_1_stage, "/World/XformPrim")
220223
layer_1_xform_prim = layer_1_xform.GetPrim()
@@ -231,7 +234,7 @@ layer_1_stage.Save()
231234
232235
# --- Layer 2 (stronger)
233236
layer_2_path = "_assets/value_resolution_layer_2.usda"
234-
layer_2_stage = Usd.Stage.CreateNew(layer_2_path)
237+
layer_2_stage = create_new_stage(layer_2_path)
235238
236239
layer_2_xform = UsdGeom.Xform.Define(layer_2_stage, "/World/XformPrim")
237240
layer_2_xform_prim = layer_2_xform.GetPrim()
@@ -247,7 +250,7 @@ layer_2_stage.Save()
247250
248251
# --- Composed stage. First sublayer listed (layer_2) is strongest
249252
composed_path = "_assets/value_resolution_composed.usda"
250-
composed_stage = Usd.Stage.CreateNew(composed_path)
253+
composed_stage = create_new_stage(composed_path)
251254
composed_stage.GetRootLayer().subLayerPaths = [os.path.basename(layer_2_path), os.path.basename(layer_1_path)]
252255
253256
xform_prim = composed_stage.GetPrimAtPath("/World/XformPrim")

docs/composition-basics/default-prim.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ assert stage.GetDefaultPrim() == default_prim
9898
+++
9999
```{code-cell}
100100
:tags: [remove-input]
101+
:test-tags: [default-prim-setup]
101102
from lousd.utils.visualization import DisplayUSD, DisplayCode
103+
from lousd.utils.helperfunctions import create_new_stage
102104
```
103105

104106
### Example 1: Setting a Default Prim
@@ -109,12 +111,13 @@ A `defaultPrim` is layer metadata. If the stage's root layer is used as a refere
109111

110112

111113
```{code-cell}
114+
:test-tags: [default-prim-set]
112115
:emphasize-lines: 9-10
113116
114117
from pxr import Usd
115118
116119
file_path = "_assets/default_prim.usda"
117-
stage: Usd.Stage = Usd.Stage.CreateNew(file_path)
120+
stage: Usd.Stage = create_new_stage(file_path)
118121
stage.DefinePrim("/hello")
119122
stage.DefinePrim("/hello/world")
120123
hello_prim: Usd.Prim = stage.GetPrimAtPath("/hello")

0 commit comments

Comments
 (0)