honeybee-radiance-postprocess 0.4.543__tar.gz → 0.4.544__tar.gz
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.
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/PKG-INFO +1 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/annual.py +11 -4
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/annualdaylight.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/breeam/breeam.py +10 -5
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/abnt.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/datacollection.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/grid.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/merge.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/mtxop.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/postprocess.py +8 -3
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/translate.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/two_phase.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/viewfactor.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/data_type.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/electriclight.py +7 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/en17037.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/helper.py +17 -3
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/ies/lm.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/ies/lm_schedule.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/leed/leed.py +38 -32
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/leed/leed_schedule.py +20 -7
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/metrics.py +33 -12
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/reader.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/results/annual_daylight.py +17 -17
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/results/annual_irradiance.py +6 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/results/results.py +49 -29
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/type_hints.py +8 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/util.py +30 -2
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess.egg-info/PKG-INFO +1 -1
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/CODE_OF_CONDUCT.md +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/CONTRIBUTING.md +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/LICENSE +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/MANIFEST.in +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/README.md +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/dev-requirements.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/__main__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/annualirradiance.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/breeam/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/breeam.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/leed.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/schedule.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/util.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/cli/well.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/dynamic.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/ies/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/leed/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/results/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/vis_metadata.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/well/__init__.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess/well/well.py +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess.egg-info/SOURCES.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess.egg-info/dependency_links.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess.egg-info/entry_points.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess.egg-info/requires.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/honeybee_radiance_postprocess.egg-info/top_level.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/requirements.txt +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/setup.cfg +0 -0
- {honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/setup.py +0 -0
@@ -1,10 +1,17 @@
|
|
1
1
|
"""Shared functions for post-processing annual results."""
|
2
2
|
from typing import Union
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
4
9
|
|
5
10
|
from ladybug.analysisperiod import AnalysisPeriod
|
6
11
|
from .util import filter_array
|
7
12
|
|
13
|
+
is_cpu = not is_gpu
|
14
|
+
|
8
15
|
|
9
16
|
def occupancy_schedule_8_to_6(
|
10
17
|
timestep: int = 1, as_list: bool = False) -> Union[np.ndarray, list]:
|
@@ -19,10 +26,10 @@ def occupancy_schedule_8_to_6(
|
|
19
26
|
Returns:
|
20
27
|
A schedule as an array or list.
|
21
28
|
"""
|
22
|
-
full_analysis_period = AnalysisPeriod(timestep=timestep)
|
23
|
-
analysis_period = AnalysisPeriod(st_hour=8, end_hour=17, timestep=timestep)
|
29
|
+
full_analysis_period = np.array(AnalysisPeriod(timestep=timestep).hoys)
|
30
|
+
analysis_period = np.array(AnalysisPeriod(st_hour=8, end_hour=17, timestep=timestep).hoys)
|
24
31
|
schedule = np.zeros(8760 * timestep).astype(int)
|
25
|
-
hours = np.where(np.isin(full_analysis_period
|
32
|
+
hours = np.where(np.isin(full_analysis_period, analysis_period))[0]
|
26
33
|
schedule[hours] = 1
|
27
34
|
if as_list:
|
28
35
|
schedule = schedule.tolist()
|
@@ -4,7 +4,12 @@ Note: These functions will most likely be moved to a separate package in the nea
|
|
4
4
|
"""
|
5
5
|
import json
|
6
6
|
import os
|
7
|
-
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from ladybug.color import Colorset
|
10
15
|
from ladybug.datatype.fraction import Fraction
|
@@ -2,7 +2,12 @@
|
|
2
2
|
from typing import Union
|
3
3
|
from pathlib import Path
|
4
4
|
import json
|
5
|
-
|
5
|
+
try:
|
6
|
+
import cupy as np
|
7
|
+
is_gpu = True
|
8
|
+
except ImportError:
|
9
|
+
is_gpu = False
|
10
|
+
import numpy as np
|
6
11
|
|
7
12
|
from honeybee.model import Model
|
8
13
|
from honeybee_radiance.writer import _filter_by_pattern
|
@@ -339,7 +344,7 @@ def breeam_daylight_assessment_4b(
|
|
339
344
|
hb_model.properties.radiance.sensor_grids, filter=grids_filter)
|
340
345
|
for s_grid in filt_grids:
|
341
346
|
if s_grid.mesh is not None:
|
342
|
-
grid_areas[s_grid.identifier] = np.array(s_grid.mesh.face_areas).sum()
|
347
|
+
grid_areas[s_grid.identifier] = int(np.array(s_grid.mesh.face_areas).sum())
|
343
348
|
else:
|
344
349
|
grid_areas[s_grid.identifier] = None
|
345
350
|
hb_room = hb_model.rooms_by_identifier([s_grid.room_identifier])[0]
|
@@ -397,7 +402,7 @@ def breeam_daylight_assessment_4b(
|
|
397
402
|
target_hrs = metrics['minimum_daylight_illuminance']['hours']
|
398
403
|
min_comply = hrs_abv_min >= target_hrs
|
399
404
|
|
400
|
-
minimum_illuminance_index = np.argsort(hrs_abv_target)[0]
|
405
|
+
minimum_illuminance_index = int(np.argsort(hrs_abv_target)[0])
|
401
406
|
minimum_illuminance_sensor = \
|
402
407
|
sensor_grid_mapper[grid_info['full_id']].sensors[minimum_illuminance_index]
|
403
408
|
minimum_illuminance_sensors[grid_info['full_id']] = \
|
@@ -482,11 +487,11 @@ def breeam_daylight_assessment_4b(
|
|
482
487
|
area_proportions = np.array(areas) / program_type_summary['total_area']
|
483
488
|
|
484
489
|
weighted_hours_avg = area_proportions * np.array(avg_hrs)
|
485
|
-
total_weighted_hours_avg = np.sum(weighted_hours_avg)
|
490
|
+
total_weighted_hours_avg = int(np.sum(weighted_hours_avg))
|
486
491
|
program_type_summary['average-illuminance-hours'] = total_weighted_hours_avg
|
487
492
|
|
488
493
|
weighted_hours_min = area_proportions * np.array(min_hrs)
|
489
|
-
total_weighted_hours_min = np.sum(weighted_hours_min)
|
494
|
+
total_weighted_hours_min = int(np.sum(weighted_hours_min))
|
490
495
|
program_type_summary['minimum-illuminance-hours'] = total_weighted_hours_min
|
491
496
|
|
492
497
|
program_summary.append(program_type_summary)
|
@@ -4,7 +4,12 @@ import sys
|
|
4
4
|
import logging
|
5
5
|
from pathlib import Path
|
6
6
|
import click
|
7
|
-
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from honeybee.model import Model
|
10
15
|
from honeybee.room import Room
|
@@ -1,10 +1,15 @@
|
|
1
1
|
"""Commands to work with data collections."""
|
2
2
|
import sys
|
3
3
|
import logging
|
4
|
-
import numpy as np
|
5
4
|
from pathlib import Path
|
6
5
|
import click
|
7
6
|
import json
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from ladybug.datacollection import HourlyContinuousCollection, \
|
10
15
|
HourlyDiscontinuousCollection
|
@@ -3,8 +3,13 @@ import click
|
|
3
3
|
import sys
|
4
4
|
import logging
|
5
5
|
import json
|
6
|
-
import numpy as np
|
7
6
|
from pathlib import Path
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from honeybee_radiance_postprocess.reader import binary_to_array
|
10
15
|
from ..annualdaylight import _annual_daylight_vis_metadata
|
@@ -3,8 +3,13 @@ import click
|
|
3
3
|
import sys
|
4
4
|
import logging
|
5
5
|
import json
|
6
|
-
import numpy as np
|
7
6
|
from pathlib import Path
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from honeybee_radiance_postprocess.reader import binary_to_array
|
10
15
|
|
@@ -2,8 +2,13 @@
|
|
2
2
|
import sys
|
3
3
|
import logging
|
4
4
|
from pathlib import Path
|
5
|
-
import numpy as np
|
6
5
|
import click
|
6
|
+
try:
|
7
|
+
import cupy as np
|
8
|
+
is_gpu = True
|
9
|
+
except ImportError:
|
10
|
+
is_gpu = False
|
11
|
+
import numpy as np
|
7
12
|
|
8
13
|
from ..reader import binary_to_array, ascii_to_array
|
9
14
|
|
@@ -5,7 +5,12 @@ import os
|
|
5
5
|
import logging
|
6
6
|
import json
|
7
7
|
import click
|
8
|
-
|
8
|
+
try:
|
9
|
+
import cupy as np
|
10
|
+
is_gpu = True
|
11
|
+
except ImportError:
|
12
|
+
is_gpu = False
|
13
|
+
import numpy as np
|
9
14
|
|
10
15
|
from ladybug.location import Location
|
11
16
|
from ladybug.wea import Wea
|
@@ -721,8 +726,8 @@ def annual_metrics_file(
|
|
721
726
|
if grid_name is None:
|
722
727
|
grid_name = file.stem
|
723
728
|
|
724
|
-
sun_up_hours_mask = np.where(np.isin(study_hours, sun_up_hours))[0]
|
725
|
-
sun_down_hours_mask = np.where(~np.isin(study_hours, sun_up_hours))[0]
|
729
|
+
sun_up_hours_mask = np.where(np.isin(np.array(study_hours), np.array(sun_up_hours)))[0]
|
730
|
+
sun_down_hours_mask = np.where(~np.isin(np.array(study_hours), np.array(sun_up_hours)))[0]
|
726
731
|
occ_mask = np.array(schedule, dtype=int)[sun_up_hours_mask]
|
727
732
|
sun_down_occ_hours = np.array(schedule, dtype=int)[sun_down_hours_mask].sum()
|
728
733
|
total_hours = sum(schedule)
|
@@ -3,9 +3,14 @@ import sys
|
|
3
3
|
import logging
|
4
4
|
from pathlib import Path
|
5
5
|
import shutil
|
6
|
-
import numpy as np
|
7
6
|
import click
|
8
7
|
import json
|
8
|
+
try:
|
9
|
+
import cupy as np
|
10
|
+
is_gpu = True
|
11
|
+
except ImportError:
|
12
|
+
is_gpu = False
|
13
|
+
import numpy as np
|
9
14
|
|
10
15
|
from ..reader import binary_to_array
|
11
16
|
from ..util import get_delimiter
|
@@ -2,8 +2,13 @@
|
|
2
2
|
import sys
|
3
3
|
import logging
|
4
4
|
from pathlib import Path
|
5
|
-
import numpy as np
|
6
5
|
import click
|
6
|
+
try:
|
7
|
+
import cupy as np
|
8
|
+
is_gpu = True
|
9
|
+
except ImportError:
|
10
|
+
is_gpu = False
|
11
|
+
import numpy as np
|
7
12
|
|
8
13
|
from ..reader import binary_to_array, ascii_to_array
|
9
14
|
|
@@ -1,6 +1,11 @@
|
|
1
1
|
"""Functions for NumPy data type (dtype)."""
|
2
2
|
from typing import Tuple
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
4
9
|
|
5
10
|
|
6
11
|
def smallest_integer_dtype(array: np.ndarray) -> np.signedinteger:
|
@@ -1,6 +1,12 @@
|
|
1
1
|
"""Functions for post-processing daylight outputs into electric lighting schedules."""
|
2
2
|
from typing import List
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
9
|
+
|
4
10
|
|
5
11
|
def array_to_dimming_fraction(
|
6
12
|
array: np.ndarray, su_pattern: List[int], setpt: float, m_pow: float,
|
@@ -2,7 +2,12 @@
|
|
2
2
|
from typing import Union
|
3
3
|
from pathlib import Path
|
4
4
|
import json
|
5
|
-
|
5
|
+
try:
|
6
|
+
import cupy as np
|
7
|
+
is_gpu = True
|
8
|
+
except ImportError:
|
9
|
+
is_gpu = False
|
10
|
+
import numpy as np
|
6
11
|
|
7
12
|
from ladybug.color import Colorset
|
8
13
|
from ladybug.datatype.fraction import Fraction
|
@@ -1,7 +1,12 @@
|
|
1
1
|
"""Helper functions."""
|
2
2
|
import json
|
3
|
-
import numpy as np
|
4
3
|
from pathlib import Path
|
4
|
+
try:
|
5
|
+
import cupy as np
|
6
|
+
is_gpu = True
|
7
|
+
except ImportError:
|
8
|
+
is_gpu = False
|
9
|
+
import numpy as np
|
5
10
|
|
6
11
|
from honeybee.model import Model
|
7
12
|
|
@@ -144,7 +149,10 @@ def grid_summary(
|
|
144
149
|
arrays.append(tuple(data))
|
145
150
|
|
146
151
|
# create structured array
|
147
|
-
|
152
|
+
if is_gpu:
|
153
|
+
struct_array = None
|
154
|
+
else:
|
155
|
+
struct_array = np.array(arrays, dtype=dtype)
|
148
156
|
|
149
157
|
header = [dt[0] for dt in dtype]
|
150
158
|
# write header to file
|
@@ -153,7 +161,13 @@ def grid_summary(
|
|
153
161
|
# write structured array to grid_summary_file
|
154
162
|
with open(folder.joinpath(f'{name}.csv'), 'a') as grid_summary_file:
|
155
163
|
grid_summary_file.write('\n')
|
156
|
-
|
164
|
+
if is_gpu:
|
165
|
+
# CuPy doesn't support structured arrays; manually format rows
|
166
|
+
for row in arrays:
|
167
|
+
row_str = ','.join(fmt_val % val for fmt_val, val in zip(fmt, row))
|
168
|
+
grid_summary_file.write(row_str + '\n')
|
169
|
+
else:
|
170
|
+
np.savetxt(grid_summary_file, struct_array, delimiter=',', fmt=fmt)
|
157
171
|
|
158
172
|
return grid_summary_file
|
159
173
|
|
@@ -2,7 +2,12 @@
|
|
2
2
|
from typing import Tuple, Union
|
3
3
|
from collections import defaultdict
|
4
4
|
import itertools
|
5
|
-
|
5
|
+
try:
|
6
|
+
import cupy as np
|
7
|
+
is_gpu = True
|
8
|
+
except ImportError:
|
9
|
+
is_gpu = False
|
10
|
+
import numpy as np
|
6
11
|
|
7
12
|
from honeybee_radiance.postprocess.annual import filter_schedule_by_hours
|
8
13
|
|
@@ -1,6 +1,11 @@
|
|
1
1
|
"""Module for dynamic LM schedules."""
|
2
2
|
from typing import Tuple
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
4
9
|
|
5
10
|
from ..results.annual_daylight import AnnualDaylight
|
6
11
|
from ..util import filter_array
|
@@ -4,7 +4,12 @@ from pathlib import Path
|
|
4
4
|
from collections import defaultdict
|
5
5
|
import json
|
6
6
|
import itertools
|
7
|
-
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from ladybug.analysisperiod import AnalysisPeriod
|
10
15
|
from ladybug.datatype.generic import GenericType
|
@@ -22,10 +27,12 @@ from honeybee_radiance.postprocess.annual import filter_schedule_by_hours
|
|
22
27
|
from ..metrics import da_array2d, ase_array2d
|
23
28
|
from ..annual import schedule_to_hoys, occupancy_schedule_8_to_6
|
24
29
|
from ..results.annual_daylight import AnnualDaylight
|
25
|
-
from ..util import
|
30
|
+
from ..util import recursive_dict_merge, filter_array2d
|
26
31
|
from ..dynamic import DynamicSchedule, ApertureGroupSchedule
|
27
32
|
from .leed_schedule import shd_trans_schedule_descending, states_schedule_descending
|
28
33
|
|
34
|
+
is_cpu = not is_gpu
|
35
|
+
|
29
36
|
|
30
37
|
def _create_grid_summary(
|
31
38
|
grid_info, sda_grid, sda_blinds_up_grid, sda_blinds_down_grid, ase_grid,
|
@@ -117,7 +124,6 @@ def _leed_summary(
|
|
117
124
|
"""
|
118
125
|
summary = {}
|
119
126
|
summary_grid = {}
|
120
|
-
|
121
127
|
if all(grid_area is not None for grid_area in grid_areas):
|
122
128
|
# weighted by mesh face area
|
123
129
|
total_area = 0
|
@@ -127,17 +133,17 @@ def _leed_summary(
|
|
127
133
|
pass_sda_blinds_down) in \
|
128
134
|
zip(pass_ase_grids, pass_sda_grids, grid_areas, grids_info,
|
129
135
|
pass_sda_blinds_up_grids, pass_sda_blinds_down_grids):
|
130
|
-
total_grid_area = grid_area.sum()
|
136
|
+
total_grid_area = float(grid_area.sum())
|
131
137
|
|
132
|
-
area_pass_ase = grid_area[pass_ase].sum()
|
133
|
-
ase_grid = (total_grid_area - area_pass_ase) / total_grid_area * 100
|
138
|
+
area_pass_ase = float(grid_area[pass_ase].sum())
|
139
|
+
ase_grid = float((total_grid_area - area_pass_ase) / total_grid_area * 100)
|
134
140
|
|
135
|
-
area_pass_sda = grid_area[pass_sda].sum()
|
141
|
+
area_pass_sda = float(grid_area[pass_sda].sum())
|
136
142
|
area_pass_sda_blind_up = grid_area[pass_sda_blinds_up].sum()
|
137
143
|
area_pass_sda_blinds_down = grid_area[pass_sda_blinds_down].sum()
|
138
|
-
sda_grid = area_pass_sda / total_grid_area * 100
|
139
|
-
sda_blinds_up_grid = area_pass_sda_blind_up / total_grid_area * 100
|
140
|
-
sda_blinds_down_grid = area_pass_sda_blinds_down / total_grid_area * 100
|
144
|
+
sda_grid = float(area_pass_sda / total_grid_area * 100)
|
145
|
+
sda_blinds_up_grid = float(area_pass_sda_blind_up / total_grid_area * 100)
|
146
|
+
sda_blinds_down_grid = float(area_pass_sda_blinds_down / total_grid_area * 100)
|
141
147
|
|
142
148
|
# grid summary
|
143
149
|
grid_summary = \
|
@@ -298,8 +304,7 @@ def shade_transmittance_per_light_path(
|
|
298
304
|
def leed_states_schedule(
|
299
305
|
results: Union[str, AnnualDaylight], grids_filter: str = '*',
|
300
306
|
shade_transmittance: Union[float, dict] = 0.05,
|
301
|
-
use_states: bool = False
|
302
|
-
) -> Tuple[dict, dict]:
|
307
|
+
use_states: bool = False) -> Tuple[dict, dict, dict]:
|
303
308
|
"""Calculate a schedule of each aperture group for LEED compliant sDA.
|
304
309
|
|
305
310
|
This function calculates an annual shading schedule of each aperture
|
@@ -404,11 +409,9 @@ def leed_states_schedule(
|
|
404
409
|
fail_to_comply[grid_info['name']] = \
|
405
410
|
[int(hoy) for hoy in grid_comply]
|
406
411
|
|
407
|
-
array_combinations_filter =
|
408
|
-
|
409
|
-
)
|
410
|
-
max_indices = array_combinations_filter.argmax(axis=0)
|
411
|
-
# select the combination for each hour
|
412
|
+
array_combinations_filter = filter_array2d(array_combinations, occ_mask)
|
413
|
+
|
414
|
+
max_indices = [int(i) for i in array_combinations_filter.argmax(axis=0)]
|
412
415
|
combinations = [combinations[idx] for idx in max_indices]
|
413
416
|
# merge the combinations of dicts
|
414
417
|
for combination in combinations:
|
@@ -416,6 +419,8 @@ def leed_states_schedule(
|
|
416
419
|
if light_path != '__static_apertures__':
|
417
420
|
grid_states_schedule[light_path].append(value)
|
418
421
|
|
422
|
+
del array_list_combinations, array_combinations, array_combinations_filter, combination_arrays
|
423
|
+
|
419
424
|
for key, value in grid_states_schedule.items():
|
420
425
|
if key not in states_schedule:
|
421
426
|
states_schedule[key] = value
|
@@ -502,7 +507,7 @@ def leed_option_one(
|
|
502
507
|
schedule = occupancy_schedule_8_to_6(as_list=True)
|
503
508
|
|
504
509
|
if not isinstance(results, AnnualDaylight):
|
505
|
-
results = AnnualDaylight(results, schedule=schedule, cache_arrays=
|
510
|
+
results = AnnualDaylight(results, schedule=schedule, cache_arrays=True)
|
506
511
|
else:
|
507
512
|
# set schedule to default leed schedule
|
508
513
|
results.schedule = schedule
|
@@ -555,8 +560,7 @@ def leed_option_one(
|
|
555
560
|
for light_path in light_paths:
|
556
561
|
array = results._get_array(
|
557
562
|
grid_info, light_path, res_type='direct')
|
558
|
-
array_filter =
|
559
|
-
filter_array, 1, array, occ_mask)
|
563
|
+
array_filter = filter_array2d(array, occ_mask)
|
560
564
|
arrays.append(array_filter)
|
561
565
|
array = sum(arrays)
|
562
566
|
# calculate ase per grid
|
@@ -575,6 +579,7 @@ def leed_option_one(
|
|
575
579
|
hours_above.append(h_above)
|
576
580
|
pass_ase = h_above < occ_hours
|
577
581
|
pass_ase_grids.append(pass_ase)
|
582
|
+
results.clear_cached_arrays(res_type='direct') # don't need direct arrays
|
578
583
|
|
579
584
|
# spatial daylight autonomy
|
580
585
|
da_grids = []
|
@@ -589,42 +594,40 @@ def leed_option_one(
|
|
589
594
|
pass
|
590
595
|
else:
|
591
596
|
light_paths.append(_lp)
|
592
|
-
base_zero_array =
|
593
|
-
(grid_info['count'], len(results.sun_up_hours))), occ_mask)
|
597
|
+
base_zero_array = filter_array2d(
|
598
|
+
np.zeros((grid_info['count'], len(results.sun_up_hours))), occ_mask)
|
594
599
|
arrays = [base_zero_array.copy()]
|
595
600
|
arrays_blinds_up = [base_zero_array.copy()]
|
596
601
|
arrays_blinds_down = [base_zero_array.copy()]
|
597
602
|
# combine total array for all light paths
|
598
603
|
if use_states:
|
599
604
|
array = results._array_from_states(grid_info, states=states_schedule, zero_array=True)
|
600
|
-
array =
|
605
|
+
array = filter_array2d(array, occ_mask)
|
601
606
|
|
602
607
|
for light_path in light_paths:
|
603
608
|
# do an extra pass to calculate with blinds always up or down
|
604
609
|
if light_path != '__static_apertures__':
|
605
610
|
array_blinds_up = results._get_array(
|
606
611
|
grid_info, light_path, state=0, res_type='total')
|
607
|
-
array_filter =
|
608
|
-
filter_array, 1, array_blinds_up, occ_mask)
|
612
|
+
array_filter = filter_array2d(array_blinds_up, occ_mask)
|
609
613
|
arrays_blinds_up.append(array_filter)
|
610
614
|
array_blinds_down = results._get_array(
|
611
615
|
grid_info, light_path, state=1, res_type='total')
|
612
|
-
array_filter =
|
613
|
-
|
616
|
+
array_filter = filter_array2d(array_blinds_down, occ_mask)
|
617
|
+
arrays_blinds_down.append(array_filter)
|
614
618
|
arrays_blinds_down.append(array_filter)
|
615
619
|
else:
|
616
620
|
static_array = results._get_array(
|
617
621
|
grid_info, light_path, state=0, res_type='total')
|
618
|
-
array_filter =
|
619
|
-
|
622
|
+
array_filter = filter_array2d(static_array, occ_mask)
|
623
|
+
arrays.append(array_filter)
|
620
624
|
arrays_blinds_up.append(array_filter)
|
621
625
|
arrays_blinds_down.append(array_filter)
|
622
626
|
else:
|
623
627
|
for light_path in light_paths:
|
624
628
|
array = results._get_array(
|
625
629
|
grid_info, light_path, res_type='total')
|
626
|
-
array_filter =
|
627
|
-
filter_array, 1, array, occ_mask)
|
630
|
+
array_filter = filter_array2d(array, occ_mask)
|
628
631
|
if light_path != '__static_apertures__':
|
629
632
|
sun_up_hours = np.array(results.sun_up_hours).astype(int)
|
630
633
|
shd_trans_array = states_schedule[light_path][sun_up_hours]
|
@@ -652,6 +655,7 @@ def leed_option_one(
|
|
652
655
|
pass_sda_grids.append(da_grid >= target_time)
|
653
656
|
pass_sda_blinds_up_grids.append(da_blinds_up_grid >= target_time)
|
654
657
|
pass_sda_blinds_down_grids.append(da_blinds_down_grid >= target_time)
|
658
|
+
results.clear_cached_arrays(res_type='total')
|
655
659
|
|
656
660
|
# create summaries for all grids and each grid individually
|
657
661
|
summary, summary_grid = _leed_summary(
|
@@ -701,7 +705,9 @@ def leed_option_one(
|
|
701
705
|
return hourly_data.to_dict()
|
702
706
|
|
703
707
|
if use_states:
|
704
|
-
states_schedule = {
|
708
|
+
states_schedule = {
|
709
|
+
k: to_datacollection(k, v['schedule']) for k,
|
710
|
+
v in states_schedule.to_dict().items()}
|
705
711
|
else:
|
706
712
|
states_schedule = {k:to_datacollection(k, v) for k, v in states_schedule.items()}
|
707
713
|
|
@@ -1,9 +1,14 @@
|
|
1
1
|
"""Module for dynamic LEED schedules."""
|
2
2
|
from typing import Tuple
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
4
9
|
|
5
10
|
from ..results.annual_daylight import AnnualDaylight
|
6
|
-
from ..util import
|
11
|
+
from ..util import filter_array2d
|
7
12
|
|
8
13
|
|
9
14
|
def shd_trans_schedule_descending(
|
@@ -16,7 +21,7 @@ def shd_trans_schedule_descending(
|
|
16
21
|
full_shd_trans_array = []
|
17
22
|
for light_path in light_paths:
|
18
23
|
array = results._get_array(grid_info, light_path, res_type="direct")
|
19
|
-
array =
|
24
|
+
array = filter_array2d(array, occ_mask)
|
20
25
|
full_direct.append(array)
|
21
26
|
full_thresh.append((array >= 1000).sum(axis=0))
|
22
27
|
full_shd_trans_array.append(shade_transmittances[light_path][1])
|
@@ -50,6 +55,7 @@ def shd_trans_schedule_descending(
|
|
50
55
|
# Use the indices to get the relevant hours.
|
51
56
|
thresh = np.take(full_thresh, above_2_indices, axis=1)
|
52
57
|
|
58
|
+
del full_direct, full_thresh
|
53
59
|
# Sort and get indices. Negate the array to get descending order.
|
54
60
|
# Descending order puts the "highest offender" light path first.
|
55
61
|
sort_thresh = np.argsort(-thresh, axis=0).transpose()
|
@@ -59,6 +65,8 @@ def shd_trans_schedule_descending(
|
|
59
65
|
0, (np.arange(full_direct_sum.shape[1]), combinations)
|
60
66
|
)
|
61
67
|
|
68
|
+
del full_direct_sum
|
69
|
+
|
62
70
|
if np.any(above_2_indices):
|
63
71
|
# There are hours where the percentage of floor area is > 2%.
|
64
72
|
for idx, lp in enumerate(light_paths):
|
@@ -142,6 +150,8 @@ def shd_trans_schedule_descending(
|
|
142
150
|
|
143
151
|
combinations = _combination
|
144
152
|
|
153
|
+
del full_shd_trans_array, direct_sum, direct, thresh, sort_thresh
|
154
|
+
|
145
155
|
# Merge the combinations of dicts.
|
146
156
|
for combination in combinations:
|
147
157
|
for light_path, shd_trans in combination.items():
|
@@ -162,27 +172,26 @@ def states_schedule_descending(
|
|
162
172
|
for light_path in light_paths:
|
163
173
|
array = results._get_array(
|
164
174
|
grid_info, light_path, state=0, res_type="direct")
|
165
|
-
array =
|
175
|
+
array = filter_array2d(array, occ_mask)
|
166
176
|
full_direct.append(array)
|
167
177
|
full_thresh.append((array >= 1000).sum(axis=0))
|
168
178
|
|
169
179
|
array = results._get_array(
|
170
180
|
grid_info, light_path, state=1, res_type="direct")
|
171
|
-
array =
|
181
|
+
array = filter_array2d(array, occ_mask)
|
172
182
|
full_direct_blinds.append(array)
|
173
183
|
|
174
184
|
full_direct = np.array(full_direct)
|
175
185
|
full_direct_blinds = np.array(full_direct_blinds)
|
176
186
|
full_direct_sum = full_direct.sum(axis=0)
|
177
187
|
|
178
|
-
new_array = full_direct.copy()
|
179
|
-
|
180
188
|
percentage_sensors = (full_direct_sum >= 1000).sum(axis=0) / grid_count
|
181
189
|
if not np.any(percentage_sensors > 0.02):
|
182
190
|
combinations = [
|
183
191
|
{light_path: 0 for light_path in light_paths}
|
184
192
|
for i in range(full_direct_sum.shape[1])]
|
185
193
|
else:
|
194
|
+
new_array = full_direct.copy()
|
186
195
|
tracking_array = np.zeros(
|
187
196
|
(new_array.shape[0], new_array.shape[2]), dtype=int)
|
188
197
|
|
@@ -235,6 +244,10 @@ def states_schedule_descending(
|
|
235
244
|
fail_to_comply[grid_info['name']] = [
|
236
245
|
int(hoy) for hoy in grid_comply]
|
237
246
|
|
247
|
+
del new_array, tracking_array, percentage_sensors, ranking_indices, final_summed_array
|
248
|
+
|
249
|
+
del full_direct, full_thresh, full_direct_blinds, full_direct_sum
|
250
|
+
|
238
251
|
for combination in combinations:
|
239
252
|
for light_path, value in combination.items():
|
240
253
|
if light_path != '__static_apertures__':
|
@@ -1,13 +1,19 @@
|
|
1
1
|
"""Functions to calculate various metrics for 1D and 2D NumPy arrays."""
|
2
2
|
from typing import Tuple, Union
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
4
9
|
|
5
10
|
from .util import check_array_dim
|
6
11
|
|
12
|
+
is_cpu = not is_gpu
|
13
|
+
|
7
14
|
|
8
15
|
def da_array2d(
|
9
|
-
array: np.ndarray, total_occ: int = None,
|
10
|
-
threshold: float = 300) -> np.ndarray:
|
16
|
+
array: np.ndarray, total_occ: int = None, threshold: float = 300) -> np.ndarray:
|
11
17
|
"""Calculate daylight autonomy for a 2D NumPy array.
|
12
18
|
|
13
19
|
Args:
|
@@ -74,8 +80,11 @@ def cda_array2d(
|
|
74
80
|
# set total_occ to number of columns in array
|
75
81
|
total_occ = array.shape[1]
|
76
82
|
|
77
|
-
|
78
|
-
|
83
|
+
if is_cpu:
|
84
|
+
cda = np.apply_along_axis(
|
85
|
+
cda_array1d, 1, array, total_occ=total_occ, threshold=threshold)
|
86
|
+
else:
|
87
|
+
cda = np.where(array >= threshold, 1, array / threshold).sum(axis=1) / total_occ * 100
|
79
88
|
|
80
89
|
return cda
|
81
90
|
|
@@ -124,8 +133,11 @@ def udi_array2d(
|
|
124
133
|
# set total_occ to number of columns in array
|
125
134
|
total_occ = array.shape[1]
|
126
135
|
|
127
|
-
|
128
|
-
|
136
|
+
if is_cpu:
|
137
|
+
udi = np.apply_along_axis(
|
138
|
+
udi_array1d, 1, array, total_occ=total_occ, min_t=min_t, max_t=max_t)
|
139
|
+
else:
|
140
|
+
udi = ((array >= min_t) & (array <= max_t)).sum(axis=1) / total_occ * 100
|
129
141
|
|
130
142
|
return udi
|
131
143
|
|
@@ -174,9 +186,15 @@ def udi_lower_array2d(
|
|
174
186
|
# set total_occ to number of columns in array
|
175
187
|
total_occ = array.shape[1]
|
176
188
|
|
177
|
-
|
178
|
-
|
179
|
-
|
189
|
+
if is_cpu:
|
190
|
+
udi = np.apply_along_axis(
|
191
|
+
udi_lower_array1d, 1, array, total_occ=total_occ, min_t=min_t,
|
192
|
+
sun_down_occ_hours=sun_down_occ_hours)
|
193
|
+
else:
|
194
|
+
if min_t == 0:
|
195
|
+
return np.zeros(array.shape[0], dtype=np.float32)
|
196
|
+
|
197
|
+
udi = ((array < min_t).sum(axis=1) + sun_down_occ_hours) / total_occ * 100
|
180
198
|
|
181
199
|
return udi
|
182
200
|
|
@@ -227,8 +245,11 @@ def udi_upper_array2d(
|
|
227
245
|
# set total_occ to number of columns in array
|
228
246
|
total_occ = array.shape[1]
|
229
247
|
|
230
|
-
|
231
|
-
|
248
|
+
if is_cpu:
|
249
|
+
udi = np.apply_along_axis(
|
250
|
+
udi_upper_array1d, 1, array, total_occ=total_occ, max_t=max_t)
|
251
|
+
else:
|
252
|
+
udi = (array > max_t).sum(axis=1) / total_occ * 100
|
232
253
|
|
233
254
|
return udi
|
234
255
|
|
@@ -1,8 +1,13 @@
|
|
1
1
|
import json
|
2
2
|
from pathlib import Path
|
3
3
|
from typing import Tuple, List
|
4
|
-
|
5
|
-
import
|
4
|
+
try:
|
5
|
+
import cupy as np
|
6
|
+
is_gpu = True
|
7
|
+
except ImportError:
|
8
|
+
is_gpu = False
|
9
|
+
import numpy as np
|
10
|
+
|
6
11
|
from collections import defaultdict
|
7
12
|
|
8
13
|
from ladybug.analysisperiod import AnalysisPeriod
|
@@ -14,13 +19,15 @@ from ladybug.header import Header
|
|
14
19
|
from ..annual import occupancy_schedule_8_to_6
|
15
20
|
from ..metrics import da_array2d, cda_array2d, udi_array2d, udi_lower_array2d, \
|
16
21
|
udi_upper_array2d, ase_array2d
|
17
|
-
from ..util import filter_array
|
22
|
+
from ..util import filter_array, filter_array2d
|
18
23
|
from ..annualdaylight import _annual_daylight_vis_metadata
|
19
24
|
from ..electriclight import array_to_dimming_fraction
|
20
25
|
from .. import type_hints
|
21
26
|
from ..dynamic import DynamicSchedule, ApertureGroupSchedule
|
22
27
|
from .results import Results
|
23
28
|
|
29
|
+
is_cpu = not is_gpu
|
30
|
+
|
24
31
|
|
25
32
|
class AnnualDaylight(Results):
|
26
33
|
"""Annual Daylight Results class.
|
@@ -71,8 +78,7 @@ class AnnualDaylight(Results):
|
|
71
78
|
for grid_info in grids_info:
|
72
79
|
array = self._array_from_states(grid_info, states=states, res_type='total')
|
73
80
|
if np.any(array):
|
74
|
-
array_filter =
|
75
|
-
filter_array, 1, array, mask=self.occ_mask)
|
81
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
76
82
|
results = da_array2d(
|
77
83
|
array_filter, total_occ=self.total_occ, threshold=threshold)
|
78
84
|
else:
|
@@ -102,8 +108,7 @@ class AnnualDaylight(Results):
|
|
102
108
|
for grid_info in grids_info:
|
103
109
|
array = self._array_from_states(grid_info, states=states, res_type='total')
|
104
110
|
if np.any(array):
|
105
|
-
array_filter =
|
106
|
-
filter_array, 1, array, mask=self.occ_mask)
|
111
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
107
112
|
results = cda_array2d(
|
108
113
|
array_filter, total_occ=self.total_occ, threshold=threshold)
|
109
114
|
else:
|
@@ -133,8 +138,7 @@ class AnnualDaylight(Results):
|
|
133
138
|
for grid_info in grids_info:
|
134
139
|
array = self._array_from_states(grid_info, states=states, res_type='total')
|
135
140
|
if np.any(array):
|
136
|
-
array_filter =
|
137
|
-
filter_array, 1, array, mask=self.occ_mask)
|
141
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
138
142
|
results = udi_array2d(
|
139
143
|
array_filter, total_occ=self.total_occ, min_t=min_t, max_t=max_t)
|
140
144
|
else:
|
@@ -165,8 +169,7 @@ class AnnualDaylight(Results):
|
|
165
169
|
for grid_info in grids_info:
|
166
170
|
array = self._array_from_states(grid_info, states=states, res_type='total')
|
167
171
|
if np.any(array):
|
168
|
-
array_filter =
|
169
|
-
filter_array, 1, array, mask=self.occ_mask)
|
172
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
170
173
|
results = udi_lower_array2d(
|
171
174
|
array_filter, total_occ=self.total_occ,
|
172
175
|
min_t=min_t, sun_down_occ_hours=sun_down_occ_hours)
|
@@ -197,8 +200,7 @@ class AnnualDaylight(Results):
|
|
197
200
|
for grid_info in grids_info:
|
198
201
|
array = self._array_from_states(grid_info, states=states, res_type='total')
|
199
202
|
if np.any(array):
|
200
|
-
array_filter =
|
201
|
-
filter_array, 1, array, mask=self.occ_mask)
|
203
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
202
204
|
results = udi_upper_array2d(
|
203
205
|
array_filter, total_occ=self.total_occ, max_t=max_t)
|
204
206
|
else:
|
@@ -242,8 +244,7 @@ class AnnualDaylight(Results):
|
|
242
244
|
for grid_info in grids_info:
|
243
245
|
array = self._array_from_states(grid_info, states=states, res_type='total')
|
244
246
|
if np.any(array):
|
245
|
-
array_filter =
|
246
|
-
filter_array, 1, array, mask=self.occ_mask)
|
247
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
247
248
|
da_results = da_array2d(
|
248
249
|
array_filter, total_occ=self.total_occ, threshold=threshold)
|
249
250
|
cda_results = cda_array2d(
|
@@ -379,8 +380,7 @@ class AnnualDaylight(Results):
|
|
379
380
|
array = self._array_from_states(
|
380
381
|
grid_info, states=states, res_type='direct')
|
381
382
|
if np.any(array):
|
382
|
-
array_filter =
|
383
|
-
filter_array, 1, array, mask=self.occ_mask)
|
383
|
+
array_filter = filter_array2d(array, mask=self.occ_mask)
|
384
384
|
results, h_above = ase_array2d(
|
385
385
|
array_filter, occ_hours=occ_hours,
|
386
386
|
direct_threshold=direct_threshold)
|
@@ -3,8 +3,13 @@ import json
|
|
3
3
|
from pathlib import Path
|
4
4
|
from itertools import islice, cycle
|
5
5
|
from typing import Tuple, Union, List
|
6
|
-
import numpy as np
|
7
6
|
import itertools
|
7
|
+
try:
|
8
|
+
import cupy as np
|
9
|
+
is_gpu = True
|
10
|
+
except ImportError:
|
11
|
+
is_gpu = False
|
12
|
+
import numpy as np
|
8
13
|
|
9
14
|
from ladybug.analysisperiod import AnalysisPeriod
|
10
15
|
from ladybug.datacollection import HourlyContinuousCollection
|
@@ -21,6 +26,8 @@ from ..util import filter_array, hoys_mask, check_array_dim, \
|
|
21
26
|
from .. import type_hints
|
22
27
|
from ..dynamic import DynamicSchedule, ApertureGroupSchedule
|
23
28
|
|
29
|
+
is_cpu = not is_gpu
|
30
|
+
|
24
31
|
|
25
32
|
class _ResultsFolder(object):
|
26
33
|
"""Base class for ResultsFolder.
|
@@ -239,14 +246,14 @@ class _ResultsFolder(object):
|
|
239
246
|
def _get_sun_up_hours_mask(self) -> List[int]:
|
240
247
|
"""Get a sun up hours masking array of the study hours."""
|
241
248
|
sun_up_hours_mask = \
|
242
|
-
np.where(np.isin(self.study_hours, self.sun_up_hours))[0]
|
249
|
+
np.where(np.isin(np.array(self.study_hours), np.array(self.sun_up_hours)))[0]
|
243
250
|
|
244
251
|
return sun_up_hours_mask
|
245
252
|
|
246
253
|
def _get_sun_down_hours_mask(self) -> List[int]:
|
247
254
|
"""Get a sun down hours masking array of the study hours."""
|
248
255
|
sun_down_hours_mask = \
|
249
|
-
np.where(~np.isin(self.study_hours, self.sun_up_hours))[0]
|
256
|
+
np.where(~np.isin(np.array(self.study_hours), np.array(self.sun_up_hours)))[0]
|
250
257
|
|
251
258
|
return sun_down_hours_mask
|
252
259
|
|
@@ -277,10 +284,11 @@ class Results(_ResultsFolder):
|
|
277
284
|
* datatype
|
278
285
|
* unit
|
279
286
|
* cache_arrays
|
287
|
+
* use_gpu
|
280
288
|
"""
|
281
289
|
__slots__ = ('_schedule', '_occ_pattern', '_total_occ', '_sun_down_occ_hours',
|
282
290
|
'_occ_mask', '_arrays', '_valid_states', '_datatype', '_unit',
|
283
|
-
'_cache_arrays')
|
291
|
+
'_cache_arrays', '_use_gpu')
|
284
292
|
|
285
293
|
def __init__(self, folder, datatype: DataTypeBase = None,
|
286
294
|
schedule: list = None, unit: str = None,
|
@@ -958,19 +966,23 @@ class Results(_ResultsFolder):
|
|
958
966
|
values: A list of values to map to an annual array. This can be a
|
959
967
|
regular list or a 1D NumPy array.
|
960
968
|
timestep: Time step of the simulation.
|
961
|
-
base_value: A value that will be applied for
|
969
|
+
base_value: A value that will be applied for the base array.
|
962
970
|
dtype: A NumPy dtype for the annual array.
|
963
971
|
|
964
972
|
Returns:
|
965
973
|
A 1D NumPy array.
|
966
974
|
"""
|
967
|
-
values
|
975
|
+
if not isinstance(values, np.ndarray):
|
976
|
+
values = np.array(values)
|
977
|
+
if not isinstance(hours, np.ndarray):
|
978
|
+
hours = np.array(hours)
|
968
979
|
check_array_dim(values, 1)
|
969
|
-
hours = np.array(hours)
|
970
980
|
assert hours.shape == values.shape
|
971
|
-
|
972
|
-
|
973
|
-
|
981
|
+
|
982
|
+
full_ap = np.array(AnalysisPeriod(timestep=timestep).hoys)
|
983
|
+
indices = np.where(np.isin(full_ap, hours))[0]
|
984
|
+
annual_array = np.repeat(np.array(base_value), 8760 * timestep).astype(dtype)
|
985
|
+
|
974
986
|
annual_array[indices] = values
|
975
987
|
|
976
988
|
return annual_array
|
@@ -1019,7 +1031,6 @@ class Results(_ResultsFolder):
|
|
1019
1031
|
grid_id = grid_info['full_id']
|
1020
1032
|
|
1021
1033
|
state_identifier = self._state_identifier(grid_id, light_path, state=state)
|
1022
|
-
|
1023
1034
|
try:
|
1024
1035
|
array = self.arrays[grid_id][light_path][state_identifier][res_type]
|
1025
1036
|
except Exception:
|
@@ -1064,6 +1075,7 @@ class Results(_ResultsFolder):
|
|
1064
1075
|
state_identifier = self._state_identifier(grid_id, light_path, state=state)
|
1065
1076
|
file = self._get_file(grid_id, light_path, state_identifier, res_type,
|
1066
1077
|
extension=extension)
|
1078
|
+
|
1067
1079
|
array = np.load(file)
|
1068
1080
|
|
1069
1081
|
if self.cache_arrays:
|
@@ -1073,12 +1085,12 @@ class Results(_ResultsFolder):
|
|
1073
1085
|
|
1074
1086
|
return array
|
1075
1087
|
|
1076
|
-
def
|
1088
|
+
def clear_cached_arrays(self, res_type: str = None):
|
1077
1089
|
"""Clear the cached arrays.
|
1078
1090
|
|
1079
|
-
This method will simply
|
1080
|
-
unless the res_type is selected in which case only 'total' or
|
1081
|
-
arrays will be deleted.
|
1091
|
+
This method will simply clear the arrays property to remove arrays from
|
1092
|
+
memory, unless the res_type is selected in which case only 'total' or
|
1093
|
+
'direct' arrays will be deleted.
|
1082
1094
|
|
1083
1095
|
Args:
|
1084
1096
|
res_type: Which type of results to clear. This can be either
|
@@ -1276,29 +1288,37 @@ class Results(_ResultsFolder):
|
|
1276
1288
|
grid_info, light_path, state=state, res_type=res_type)
|
1277
1289
|
arrays.append(array)
|
1278
1290
|
else:
|
1279
|
-
# create default 0 array, we will add to this later
|
1280
|
-
array = np.zeros((grid_info['count'], len(self.sun_up_hours)))
|
1281
1291
|
# slice states to match sun up hours
|
1282
1292
|
states_array = np.array(gr_schedule.schedule)[
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1293
|
+
np.array(self.sun_up_hours, int)]
|
1294
|
+
|
1295
|
+
unique_states = np.unique(states_array)
|
1296
|
+
unique_states = unique_states[unique_states != -1] # skip -1
|
1297
|
+
temp_arrays = []
|
1298
|
+
for state in unique_states:
|
1299
|
+
state = int(state)
|
1288
1300
|
# load static array (state is static)
|
1289
1301
|
_array = self._get_array(
|
1290
1302
|
grid_info, light_path, state=state, res_type=res_type)
|
1291
1303
|
# get indices and add values to base array
|
1292
|
-
|
1293
|
-
|
1304
|
+
state_indices = (states_array == state)
|
1305
|
+
masked_array = np.zeros_like(_array)
|
1306
|
+
masked_array[:, state_indices] = _array[:, state_indices]
|
1307
|
+
temp_arrays.append(masked_array)
|
1308
|
+
if temp_arrays:
|
1309
|
+
array = np.sum(np.stack(temp_arrays), axis=0)
|
1310
|
+
else:
|
1311
|
+
array = np.zeros((grid_info['count'], len(self.sun_up_hours)))
|
1294
1312
|
arrays.append(array)
|
1295
|
-
|
1313
|
+
|
1314
|
+
if len(arrays) == 0:
|
1315
|
+
array = np.zeros((grid_info['count'], len(self.sun_up_hours)))
|
1316
|
+
else:
|
1317
|
+
array = np.sum(np.stack(arrays, axis=0), axis=0)
|
1296
1318
|
|
1297
1319
|
if not np.any(array):
|
1298
|
-
if zero_array:
|
1299
|
-
array = np.
|
1300
|
-
else:
|
1301
|
-
array = np.array([])
|
1320
|
+
if not zero_array:
|
1321
|
+
array = np.asarray([])
|
1302
1322
|
|
1303
1323
|
return array
|
1304
1324
|
|
@@ -1,8 +1,15 @@
|
|
1
1
|
"""Type hints for honeybee-radiance-postprocess."""
|
2
2
|
from typing import Tuple, List
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
9
|
+
|
4
10
|
from ladybug.datacollection import HourlyContinuousCollection
|
5
11
|
|
12
|
+
|
6
13
|
annual_metric = Tuple[List[np.ndarray], List[dict]]
|
7
14
|
annual_daylight_metrics = Tuple[
|
8
15
|
List[np.ndarray],
|
@@ -1,9 +1,16 @@
|
|
1
1
|
"""Post-processing utility functions."""
|
2
2
|
from typing import Tuple
|
3
|
-
|
3
|
+
try:
|
4
|
+
import cupy as np
|
5
|
+
is_gpu = True
|
6
|
+
except ImportError:
|
7
|
+
is_gpu = False
|
8
|
+
import numpy as np
|
4
9
|
|
5
10
|
from honeybee_radiance.writer import _filter_by_pattern
|
6
11
|
|
12
|
+
is_cpu = not is_gpu
|
13
|
+
|
7
14
|
|
8
15
|
def binary_mtx_dimension(filepath: str) -> Tuple[int, int, int, int, str]:
|
9
16
|
"""Return binary Radiance matrix dimensions if exist.
|
@@ -68,6 +75,27 @@ def check_array_dim(array: np.ndarray, dim: int):
|
|
68
75
|
f'Expected {dim}-dimensional array. Dimension of array is {array.ndim}'
|
69
76
|
|
70
77
|
|
78
|
+
def filter_array2d(array: np.ndarray, mask: np.ndarray) -> np.ndarray:
|
79
|
+
"""Filter a NumPy array by a masking array. The array will be passed as is
|
80
|
+
if the mask is None.
|
81
|
+
|
82
|
+
Args:
|
83
|
+
array: A NumPy array to filter.
|
84
|
+
mask: A NumPy array of ones/zeros or True/False.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
A filtered NumPy array.
|
88
|
+
"""
|
89
|
+
if is_cpu:
|
90
|
+
array_filter = np.apply_along_axis(
|
91
|
+
filter_array, 1, array, mask=mask)
|
92
|
+
else:
|
93
|
+
mask = np.asarray(mask).astype(bool)
|
94
|
+
array_filter = array[:, mask]
|
95
|
+
|
96
|
+
return array_filter
|
97
|
+
|
98
|
+
|
71
99
|
def filter_array(array: np.ndarray, mask: np.ndarray) -> np.ndarray:
|
72
100
|
"""Filter a NumPy array by a masking array. The array will be passed as is
|
73
101
|
if the mask is None.
|
@@ -95,7 +123,7 @@ def hoys_mask(sun_up_hours: list, hoys: list) -> np.ndarray:
|
|
95
123
|
A NumPy array of booleans.
|
96
124
|
"""
|
97
125
|
if len(hoys) != 0:
|
98
|
-
hoys_mask = np.where(np.isin(sun_up_hours, hoys), True, False)
|
126
|
+
hoys_mask = np.where(np.isin(np.array(sun_up_hours), np.array(hoys)), True, False)
|
99
127
|
return hoys_mask
|
100
128
|
|
101
129
|
|
{honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/CODE_OF_CONDUCT.md
RENAMED
File without changes
|
{honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/CONTRIBUTING.md
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/dev-requirements.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{honeybee_radiance_postprocess-0.4.543 → honeybee_radiance_postprocess-0.4.544}/requirements.txt
RENAMED
File without changes
|
File without changes
|
File without changes
|