honeybee-radiance-postprocess 0.4.418__py2.py3-none-any.whl → 0.4.419__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -61,66 +61,133 @@ def abnt_nbr_15575(
61
61
  file is used to extract the center points of the sensor grids. It is
62
62
  a requirement that the sensor grids have Meshes.
63
63
  """
64
- def find_surrounding_points(x, y, x_coords, y_coords):
65
- """Find the four nearest points and return the minimum and maximum
66
- x and y values."""
67
- # calculate Euclidean distances
68
- distances = np.sqrt((x_coords - x)**2 + (y_coords - y)**2)
69
- # get the four nearest points
70
- if len(distances) < 4:
71
- # if the grid for some reason has less than four sensors
72
- nearest_indices = np.argsort(distances)[:len(distances)]
64
+ def find_surrounding_points(points, values, new_point):
65
+ """Find the four surrounding points for bilinear interpolation.
66
+
67
+ Args:
68
+ points: 2D array of points, shape.
69
+ values: 1D array of values at the points.
70
+ new_point: 1D array of the point to interpolate.
71
+
72
+ Returns:
73
+ tuple: (surrounding_points, surrounding_values) and their counts.
74
+ """
75
+ x, y = new_point
76
+ lower_left = None
77
+ upper_left = None
78
+ lower_right = None
79
+ upper_right = None
80
+
81
+ for i, (px, py) in enumerate(points):
82
+ if px <= x and py <= y:
83
+ if lower_left is None or (px >= lower_left[0] and py >= lower_left[1]):
84
+ lower_left = (px, py, values[i])
85
+ if px <= x and py >= y:
86
+ if upper_left is None or (px >= upper_left[0] and py <= upper_left[1]):
87
+ upper_left = (px, py, values[i])
88
+ if px >= x and py >= y:
89
+ if upper_right is None or (px <= upper_right[0] and py <= upper_right[1]):
90
+ upper_right = (px, py, values[i])
91
+ if px >= x and py <= y:
92
+ if lower_right is None or (px <= lower_right[0] and py >= lower_right[1]):
93
+ lower_right = (px, py, values[i])
94
+
95
+ surrounding_points = []
96
+ surrounding_values = []
97
+ if lower_left:
98
+ surrounding_points.append(lower_left[:2])
99
+ surrounding_values.append(lower_left[2])
100
+ if upper_left:
101
+ surrounding_points.append(upper_left[:2])
102
+ surrounding_values.append(upper_left[2])
103
+ if upper_right:
104
+ surrounding_points.append(upper_right[:2])
105
+ surrounding_values.append(upper_right[2])
106
+ if lower_right:
107
+ surrounding_points.append(lower_right[:2])
108
+ surrounding_values.append(lower_right[2])
109
+
110
+ return np.array(surrounding_points), np.array(surrounding_values)
111
+
112
+ def bilinear_interpolate(surrounding_points, surrounding_values, new_point):
113
+ """Perform bilinear interpolation given four surrounding points.
114
+
115
+ Args:
116
+ surrounding_points: 2D array of points.
117
+ surrounding_values: 1D array of values at the points.
118
+ new_point: 1D array of the point to interpolate.
119
+
120
+ Returns:
121
+ Interpolated value at the new_point.
122
+ """
123
+ x1, y1 = surrounding_points[0]
124
+ x2, y2 = surrounding_points[2]
125
+ x, y = new_point
126
+
127
+ fQ11 = surrounding_values[0]
128
+ fQ21 = surrounding_values[3]
129
+ fQ12 = surrounding_values[1]
130
+ fQ22 = surrounding_values[2]
131
+
132
+ interpolated_value = (
133
+ fQ11 * (x2 - x) * (y2 - y) +
134
+ fQ21 * (x - x1) * (y2 - y) +
135
+ fQ12 * (x2 - x) * (y - y1) +
136
+ fQ22 * (x - x1) * (y - y1)
137
+ ) / ((x2 - x1) * (y2 - y1))
138
+
139
+ return interpolated_value
140
+
141
+ def inverse_distance_weighting(points, values, new_point, n_nearest=4):
142
+ """Perform inverse distance weighting interpolation.
143
+
144
+ Args:
145
+ points: 2D array of points.
146
+ values: 1D array of values at the points
147
+ new_point: 1D array of the point to interpolate.
148
+ n_nearest: Number of nearest points to consider for interpolation.
149
+
150
+ Returns:
151
+ Interpolated value at the new_point.
152
+ """
153
+ distances = np.linalg.norm(points - new_point, axis=1)
154
+ nearest_indices = np.argsort(distances)[:min(n_nearest, len(points))]
155
+
156
+ nearest_values = values[nearest_indices]
157
+ nearest_distances = distances[nearest_indices]
158
+
159
+ if np.any(nearest_distances == 0):
160
+ # if the new point coincides with an existing point, return its value
161
+ return nearest_values[nearest_distances == 0][0]
162
+
163
+ weights = 1 / nearest_distances
164
+ weights /= weights.sum() # normalize weights
165
+ return np.dot(weights, nearest_values)
166
+
167
+ def perform_interpolation(x, y, x_coords, y_coords, pit_values):
168
+ points = np.column_stack((x_coords, y_coords))
169
+ values = np.array(pit_values)
170
+ new_point = np.array([x, y])
171
+
172
+ surrounding_points, surrounding_values = \
173
+ find_surrounding_points(points, values, new_point)
174
+
175
+ if len(surrounding_points) == 4:
176
+ interpolated_value = \
177
+ bilinear_interpolate(surrounding_points,
178
+ surrounding_values, new_point)
73
179
  else:
74
- nearest_indices = np.argsort(distances)[:4]
75
- x_values = x_coords[nearest_indices]
76
- y_values = y_coords[nearest_indices]
77
- x1, x2 = min(x_values), max(x_values)
78
- y1, y2 = min(y_values), max(y_values)
79
-
80
- return x1, x2, y1, y2
81
-
82
- def get_value(x, y, x_coords, y_coords, values):
83
- tolerance = 0.001
84
- index = np.where((np.abs(x_coords - x) <= tolerance) & (np.abs(y_coords - y) <= tolerance))
85
- return values[index][0]
86
-
87
- def perform_interpolation(x, y, x_coords, y_caoords, pit_values):
88
- x1, x2, y1, y2 = find_surrounding_points(x, y, x_coords, y_coords)
89
-
90
- # extract the illuminance values at the surrounding points
91
- f_Q11 = get_value(x1, y1, x_coords, y_coords, pit_values) # bottom-left
92
- f_Q21 = get_value(x2, y1, x_coords, y_coords, pit_values) # bottom-right
93
- f_Q12 = get_value(x1, y2, x_coords, y_coords, pit_values) # top-left
94
- f_Q22 = get_value(x2, y2, x_coords, y_coords, pit_values) # top-right
95
-
96
- # edge cases
97
- if x == x1 and y == y1:
98
- f_xy = f_Q11
99
- elif x == x2 and y == y1:
100
- f_xy = f_Q21
101
- elif x == x1 and y == y2:
102
- f_xy = f_Q12
103
- elif x == x2 and y == y2:
104
- f_xy = f_Q22
105
- elif x1 == x2:
106
- # linear interpolation in y direction
107
- f_xy = f_Q11 + (f_Q12 - f_Q11) * (y - y1) / (y2 - y1)
108
- elif y1 == y2:
109
- # linear interpolation in x direction
110
- f_xy = f_Q11 + (f_Q21 - f_Q11) * (x - x1) / (x2 - x1)
111
- else:
112
- # perform bilinear interpolation
113
- f_xy = (f_Q11 * (x2 - x) * (y2 - y) +
114
- f_Q21 * (x - x1) * (y2 - y) +
115
- f_Q12 * (x2 - x) * (y - y1) +
116
- f_Q22 * (x - x1) * (y - y1)) / ((x2 - x1) * (y2 - y1))
180
+ interpolated_value = \
181
+ inverse_distance_weighting(
182
+ points, values, new_point, n_nearest=4)
117
183
 
118
- return f_xy
184
+ return interpolated_value
119
185
 
120
186
  try:
121
187
  folder = Path(folder)
122
188
  hb_model: Model = Model.from_file(model_file)
123
- grouped_rooms, floor_heights = Room.group_by_floor_height(hb_model.rooms)
189
+ grouped_rooms, floor_heights = Room.group_by_floor_height(
190
+ hb_model.rooms)
124
191
 
125
192
  # pick the first group >= to ground level
126
193
  for gr, fh in zip(grouped_rooms, floor_heights):
@@ -157,14 +224,20 @@ def abnt_nbr_15575(
157
224
  sub_output = []
158
225
  for grid_info in grids_info:
159
226
  pit_values = \
160
- np.loadtxt(res_folder.joinpath(f'{grid_info["full_id"]}.res'))
227
+ np.loadtxt(res_folder.joinpath(
228
+ f'{grid_info["full_id"]}.res'))
161
229
  sensor_grid = sg_full_identifier[grid_info['full_id']]
162
230
  sensor_points = np.array(
163
- [[sensor.pos[0], sensor.pos[1]] for sensor in sensor_grid.sensors])
231
+ [[sensor.pos[0], sensor.pos[1], sensor.pos[2]]
232
+ for sensor in sensor_grid.sensors]
233
+ )
164
234
 
165
235
  x_coords = sensor_points[:, 0]
166
236
  y_coords = sensor_points[:, 1]
167
- room = hb_model.rooms_by_identifier([sensor_grid.room_identifier])[0]
237
+ z_coords = sensor_points[:, 2]
238
+
239
+ room = hb_model.rooms_by_identifier(
240
+ [sensor_grid.room_identifier])[0]
168
241
 
169
242
  pof_sensor_grid = \
170
243
  pof_sensor_grids.get(grid_info['full_id'], None)
@@ -175,25 +248,30 @@ def abnt_nbr_15575(
175
248
  room.horizontal_floor_boundaries(), 0.05
176
249
  )[0]
177
250
  if floor_face.is_convex:
178
- pof_sensor_grids[grid_info['full_id']] = \
179
- floor_face.centroid + Vector3D(0, 0, 0.75)
251
+ centroid = floor_face.centroid
180
252
  else:
181
- pof_sensor_grids[grid_info['full_id']] = \
182
- floor_face.pole_of_inaccessibility(0.01) + Vector3D(0, 0, 0.75)
253
+ centroid = floor_face.pole_of_inaccessibility(0.01)
254
+ dz = np.mean(z_coords) - centroid.z
255
+ pof_sensor_grids[grid_info['full_id']] = \
256
+ centroid + Vector3D(0, 0, dz)
183
257
  else:
184
- faces_3d = [Face3D(face_vertices) for face_vertices in sensor_grid.mesh.face_vertices]
185
- face_3d_union = Face3D.join_coplanar_faces(faces_3d, 0.05)
258
+ faces_3d = [
259
+ Face3D(face_vertices) for face_vertices in sensor_grid.mesh.face_vertices]
260
+ face_3d_union = Face3D.join_coplanar_faces(
261
+ faces_3d, 0.05)
186
262
  assert len(face_3d_union) == 1
187
263
  if face_3d_union[0].is_convex:
188
264
  centroid = face_3d_union[0].centroid
189
265
  pof_sensor_grids[grid_info['full_id']] = centroid
190
266
  else:
191
- pof = face_3d_union[0].pole_of_inaccessibility(0.01)
267
+ pof = face_3d_union[0].pole_of_inaccessibility(
268
+ 0.01)
192
269
  pof_sensor_grids[grid_info['full_id']] = pof
193
270
 
194
271
  x = pof_sensor_grids[grid_info['full_id']].x
195
272
  y = pof_sensor_grids[grid_info['full_id']].y
196
- f_xy = perform_interpolation(x, y, x_coords, y_coords, pit_values)
273
+ f_xy = perform_interpolation(
274
+ x, y, x_coords, y_coords, pit_values)
197
275
 
198
276
  if room in ground_level_rooms:
199
277
  minimo = 48
@@ -204,7 +282,7 @@ def abnt_nbr_15575(
204
282
  level = 'Superior'
205
283
  elif f_xy >= 90:
206
284
  level = 'Intermediário'
207
- elif f_xy >= minimo: # add check for ground floor (48 lux)
285
+ elif f_xy >= minimo: # add check for ground floor (48 lux)
208
286
  level = 'Mínimo'
209
287
  else:
210
288
  level = 'Não atende'
@@ -232,19 +310,23 @@ def abnt_nbr_15575(
232
310
  }
233
311
  )
234
312
 
235
- conditions = [pit_values >= 120, pit_values >= 90, pit_values >= 60, pit_values < 60]
313
+ conditions = [pit_values >= 120, pit_values >=
314
+ 90, pit_values >= 60, pit_values < 60]
236
315
  conditions_values = [3, 2, 1, 0]
237
316
  illuminance_level = np.select(conditions, conditions_values)
238
317
 
239
- ill_level_file = illuminance_levels_folder.joinpath(_subfolder, f'{grid_info["full_id"]}.res')
318
+ ill_level_file = illuminance_levels_folder.joinpath(
319
+ _subfolder, f'{grid_info["full_id"]}.res')
240
320
  ill_level_file.parent.mkdir(parents=True, exist_ok=True)
241
321
  np.savetxt(ill_level_file, illuminance_level, fmt='%d')
242
322
 
243
- grids_info_file = illuminance_levels_folder.joinpath(_subfolder, 'grids_info.json')
323
+ grids_info_file = illuminance_levels_folder.joinpath(
324
+ _subfolder, 'grids_info.json')
244
325
  grids_info_file.write_text(json.dumps(grids_info, indent=2))
245
326
 
246
327
  vis_data = metric_info_dict[_subfolder]
247
- vis_metadata_file = illuminance_levels_folder.joinpath(_subfolder, 'vis_metadata.json')
328
+ vis_metadata_file = illuminance_levels_folder.joinpath(
329
+ _subfolder, 'vis_metadata.json')
248
330
  vis_metadata_file.write_text(json.dumps(vis_data, indent=4))
249
331
 
250
332
  summary_output[_subfolder] = sub_output
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: honeybee-radiance-postprocess
3
- Version: 0.4.418
3
+ Version: 0.4.419
4
4
  Summary: Postprocessing of Radiance results and matrices
5
5
  Home-page: https://github.com/ladybug-tools/honeybee-radiance-postprocess
6
6
  Author: Ladybug Tools
@@ -15,7 +15,7 @@ honeybee_radiance_postprocess/type_hints.py,sha256=4R0kZgacQrqzoh8Tq7f8MVzUDzynV
15
15
  honeybee_radiance_postprocess/util.py,sha256=-J5k1dhvyYJkb42jvTS_xxtokfGbmcucVPXdMWU1jUk,5098
16
16
  honeybee_radiance_postprocess/vis_metadata.py,sha256=7ywIgdiuNKcctxifhpy7-Q2oaSX2ngQBeA0Kh7q1Gg0,1780
17
17
  honeybee_radiance_postprocess/cli/__init__.py,sha256=PVfwkuPFl4TnvQt8ovVm01JK0Alon81BaY-0tshAXyg,795
18
- honeybee_radiance_postprocess/cli/abnt.py,sha256=IEJdGi4fkLD75C833CVpk5WimMm7PVMGYV3QBNgVOGE,12785
18
+ honeybee_radiance_postprocess/cli/abnt.py,sha256=GNLmVVrEQ-1oKr5ZmBllY-KODhgJPjLVidQ_dQMcpFk,15537
19
19
  honeybee_radiance_postprocess/cli/grid.py,sha256=6peLEAPVe-iw05_wdRpFruZLqO8myvC-_QT5W1q5sk8,10677
20
20
  honeybee_radiance_postprocess/cli/leed.py,sha256=QBR6AMJJWuZ0TevyMi2tXCWMLdS-ZSqtVTZDgqxwa7M,3112
21
21
  honeybee_radiance_postprocess/cli/mtxop.py,sha256=UZJnjNpPjDmShy1-Mxos4H2vTUqk_yP3ZyaC1_LLFeI,5015
@@ -29,9 +29,9 @@ honeybee_radiance_postprocess/results/__init__.py,sha256=1agBQbfT4Tf8KqSZzlfKYX8
29
29
  honeybee_radiance_postprocess/results/annual_daylight.py,sha256=ohysFt4OWlWUn_IvM6pjmiQcRTq_x5b998Iv0pw8AEQ,34964
30
30
  honeybee_radiance_postprocess/results/annual_irradiance.py,sha256=5zwrr4MNeHUebbSRpSBbscPOZUs2AHmYCQfIIbdYImY,8298
31
31
  honeybee_radiance_postprocess/results/results.py,sha256=GwyjIYljaCShx1b6NlYUBcU_gHhckmLcCMNrQ6HVDdE,53507
32
- honeybee_radiance_postprocess-0.4.418.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
33
- honeybee_radiance_postprocess-0.4.418.dist-info/METADATA,sha256=EaZPDjNDUhsc3qgyqLJI1oLDJd010yi0yY0x3egJcdg,2245
34
- honeybee_radiance_postprocess-0.4.418.dist-info/WHEEL,sha256=unfA4MOaH0icIyIA5oH6E2sn2Hq5zKtLlHsWapZGwes,110
35
- honeybee_radiance_postprocess-0.4.418.dist-info/entry_points.txt,sha256=gFtVPx6UItXt27GfEZZO00eOZChJJEL6JwGSAB_O3rs,96
36
- honeybee_radiance_postprocess-0.4.418.dist-info/top_level.txt,sha256=4-sFbzy7ewP2EDqJV3jeFlAFx7SuxtoBBELWaKAnLdA,30
37
- honeybee_radiance_postprocess-0.4.418.dist-info/RECORD,,
32
+ honeybee_radiance_postprocess-0.4.419.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
33
+ honeybee_radiance_postprocess-0.4.419.dist-info/METADATA,sha256=T_Z-_o7VPTM0_PzjEIrSnpQ_OnAo8NjMPup9sQ3ccmE,2245
34
+ honeybee_radiance_postprocess-0.4.419.dist-info/WHEEL,sha256=unfA4MOaH0icIyIA5oH6E2sn2Hq5zKtLlHsWapZGwes,110
35
+ honeybee_radiance_postprocess-0.4.419.dist-info/entry_points.txt,sha256=gFtVPx6UItXt27GfEZZO00eOZChJJEL6JwGSAB_O3rs,96
36
+ honeybee_radiance_postprocess-0.4.419.dist-info/top_level.txt,sha256=4-sFbzy7ewP2EDqJV3jeFlAFx7SuxtoBBELWaKAnLdA,30
37
+ honeybee_radiance_postprocess-0.4.419.dist-info/RECORD,,