forked from DLR-RM/BlenderProc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAttributeMerger.py
136 lines (110 loc) · 4.71 KB
/
AttributeMerger.py
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
import mathutils
from src.main.Provider import Provider
from src.utility.Config import Config
class AttributeMerger(Provider):
""" Similarly to getter.Attribute Provider, getter.AttributeMerger returns the result of processing of the list of
values, but the list is comprised of the return values of invoked providers. All return values in the list must
comply with the requirements. See tables below for more info.
Example 1: Get a mathutils.Vector which represents an average vector of two Uniform3d sampler return values
{
"provider": "getter.AttributeMerger",
"elements": [
{
"provider": "sampler.Uniform3d",
"min": [0, 0, 0],
"max": [1, 1, 1]
},
{
"provider": "sampler.Uniform3d",
"min": [2, 2, 2],
"max": [3, 3, 3]
}
],
"transform_by": "avg"
}
Example 2: Get a value which is a sum of a point sampled by sampler.Uniform3d, of an average location of all
objects with names matching the pattern, and of a constant location.
{
"provider": "getter.AttributeMerger",
"elements": [
{
"provider": "sampler.Uniform3d",
"min": [0, 0, 0],
"max": [1, 1, 1]
},
{
"provider": "getter.Attribute",
"entities": {
"provider": "getter.Entity",
"conditions": {
"name": "Icosphere.*"
}
},
"get": "location",
"transform_by": "avg"
},
[1, 2, 3]
],
"transform_by": "sum"
}
**Configuration**:
.. csv-table::
:header: "Parameter", "Description"
"elements", "List of user-configured Provider calls. Type: list."
"transform_by", "Name of the operation to perform on the list of Provider return values. See table below for "
"supported operation names. Type: string."
**Operations**:
.. csv-table::
:header: "Parameter", "Description"
"sum", "Returns the sum of all values of the input list. Type: float (return)."
"avg", "Returns the average value of all values of the input list. Type: float (return)."
"""
def __init__(self, config):
Provider.__init__(self, config)
def run(self):
""" Returns the result of processing of the list of values. """
transform_by = self.config.get_string("transform_by")
elements = self.config.get_list("elements")
raw_result = []
for element in elements:
element_conf = Config({"element": element})
if isinstance(element, list):
raw_result.append(element_conf.get_vector3d("element"))
else:
raw_result.append(element_conf.get_raw_value("element"))
if len(raw_result) > 0:
if self._check_compatibility(raw_result):
if transform_by == "sum":
ref_result = self._sum(raw_result)
elif transform_by == "avg":
ref_result = self._avg(raw_result)
else:
raise RuntimeError("Unknown 'transform_by' operation: " + transform_by)
else:
raise RuntimeError("Provider output types don't match. All must either int, float, or mathutils.Vector.")
else:
raise RuntimeError("List of resulting values of `elements` is empty. Please, check Provider configuration.")
return ref_result
@staticmethod
def _check_compatibility(raw_result):
""" Checks if the list of values contains appropriate data of int/float, or mathutils.Vector type.
:param raw_result: list of provider output values. Type: List
:return: True if list is of of int (and/or) float, or mathutils.Vector data type. False if not. Type: bool.
"""
return any([all(isinstance(item, mathutils.Vector) for item in raw_result),
all(isinstance(item, (int, float)) for item in raw_result)])
def _sum(self, raw_result):
""" Sums up the values of the list.
:return: The sum of all values of the input list.
"""
ref_result = raw_result[0].copy()
for item in raw_result[1:]:
ref_result += item
return ref_result
def _avg(self, raw_result):
""" Sums up the values of the list and divides the sum by the amount of items in the list.
:return: The average value of all values of the input list.
"""
ref_result = self._sum(raw_result)
ref_result = ref_result/float(len(raw_result))
return ref_result