-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathREADME.qmd
More file actions
158 lines (114 loc) · 4.1 KB
/
Copy pathREADME.qmd
File metadata and controls
158 lines (114 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
---
format: gfm
jupyter: python3
title: databpy
---
[](https://codecov.io/gh/BradyAJohnston/databpy)
[](https://pypi.org/project/databpy/)



A set of data-oriented wrappers around the python API of Blender.
This was originally used internally inside of [Molecular Nodes](https://github.com/BradyAJohnston/MolecularNodes) but was broken out into a separate python module for re-use in other projects.
## Installation
Available on PyPI, install with pip:
```bash
pip install databpy
```
::: {.callout-caution}
`bpy` (Blender as a python module) is listed as an optional dependency, so that if you install `databpy` inside of Blender you won't install a redundant version of `bpy`. If you are using this outside of Blender, you will need to specifically request `bpy` with either of these methods:
```bash
# install wtih bpy dependency
pip install 'databpy[bpy]'
# install both packages
pip install databpy bpy
# install with all optional dependencies
pip install 'databpy[all]'
```
:::
## Usage
The main use cases are to create objects, store and retrieve attributes from them. The functions are named around nodes in Geometry Nodes `Store Named Attribute` and `Named Attribute`
```python
import databpy as db
db.store_named_attribute() # store a named attribute on a mesh object
db.named_attribute() # retrieve a named attribute from a mesh object
```
Here's an example on how to store an attribute:
```python
import numpy as np
import databpy as db
coords = np.array([
[0, 0, 0],
[0, 5, 0],
[5, 0, 0],
[5, 5, 0]
])
obj = db.create_object(coords, name="Box")
db.store_named_attribute(obj, np.array([10, 20, 31, 42]), "vals")
```

This module is mainly used to create mesh objects and work with their attributes. It is built to store and retrieve data using NumPy arrays:
```{python}
#| echo: false
#| output: false
import bpy
bpy.ops.wm.read_homefile(app_template="")
```
```{python}
import numpy as np
import databpy as db
np.random.seed(6)
# Create a mesh object
random_verts = np.random.rand(10, 3)
obj = db.create_object(random_verts, name="RandomMesh")
obj.name
```
Access attributes from the object's mesh.
```{python}
db.named_attribute(obj, 'position')
```
### `BlenderObject` class (bob)
This is a convenience class that wraps around the `bpy.types.Object`, and provides access to all of the useful functions. We can wrap an existing Object or return one when creating a new object.
This just gives us access to the `named_attribute()` and `store_named_attribute()` functions on the object class, but also provides a more intuitive way to access the object's attributes.
```{python}
bob = db.BlenderObject(obj) # wraps the existing object
bob = db.create_bob(random_verts) # creates a new object and returns it already wrapped
# these two are identical
bob.named_attribute('position')
bob.position
```
We can clear all of the data from the object and initialise a new mesh underneath:
```{python}
bob.new_from_pydata(np.random.randn(5, 3))
bob.position
```
## Example with Polars data
```{python}
import polars as pl
import databpy as db
from io import StringIO
json_file = StringIO("""
{
"Dino": [
[55.3846, 97.1795, 0.0],
[51.5385, 96.0256, 0.0]
],
"Star": [
[58.2136, 91.8819, 0.0],
[58.1961, 92.215, 0.0]
]
}
""")
df = pl.read_json(json_file)
columns_to_explode = [col for col in df.columns if df[col].dtype == pl.List(pl.List)]
df = df.explode(columns_to_explode)
vertices = np.zeros((len(df), 3), dtype=np.float32)
bob = db.create_bob(vertices, name="DinoStar")
for col in df.columns:
data = np.vstack(df.get_column(col).to_numpy())
bob.store_named_attribute(data, col)
bob.named_attribute("Dino")
```
```{python}
bob.named_attribute("Star")
```