Skip to content

Commit 658da8f

Browse files
authored
7.2 Deployment (#207)
2 parents 37bb52e + c3feac7 commit 658da8f

38 files changed

Lines changed: 979 additions & 88 deletions

.ci/BHoMBot/Nuget/BHoM.Interop.LadybugTools.nuspec

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,18 @@
1919
<dependency id="NETStandard.Library" version="2.0.3" />
2020
</group>
2121
</dependencies>
22+
<contentFiles>
23+
<files include="any\any\PythonCode\**\*.*" buildAction="Content" copyToOutput="true" flatten="false"/>
24+
<files include="any\any\PythonEnvironment\**\*" buildAction="Content" copyToOutput="true" flatten="false"/>
25+
</contentFiles>
2226
</metadata>
2327
<files>
2428
<file src="licence/licence.txt" target="" />
2529
<file src="images/icon.png" target="" />
2630
<file src="docs/readme.md" target="" />
31+
<!--lib\**\* is a workaround for contentfiles not including dll files-->
32+
<file src="lib\**\*" target="lib" />
33+
<file src="C:\ProgramData\BHoM\Extensions\PythonCode\LadybugTools_Toolkit\src\ladybugtools_toolkit\bhom\wrapped\**\*.*" exclude="**\__pycache__\*;**\docs\**\*" target="contentFiles\any\any\PythonCode\LadybugTools_Toolkit\src\ladybugtools_toolkit\bhom\wrapped"/>
34+
<file src="C:\ProgramData\BHoM\Extensions\PythonCode\LadybugTools_Toolkit\src\**\*.*" exclude="**\__pycache__\*;**\docs\**\*" target="contentFiles\any\any\PythonEnvironment\Lib\site-packages" />
2735
</files>
28-
</package>
36+
</package>

LadybugTools_Adapter/AdapterActions/Execute.cs

Lines changed: 204 additions & 28 deletions
Large diffs are not rendered by default.

LadybugTools_Adapter/LadybugTools_Adapter.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
*/
2222

2323
using System.ComponentModel;
24+
using BH.Engine.Python;
25+
using System.IO;
2426
using BH.oM.Base.Attributes;
2527
using BH.oM.Python;
2628

@@ -38,6 +40,13 @@ public LadybugToolsAdapter()
3840
BH.Engine.Python.Compute.BasePythonEnvironment(run: true);
3941
m_environment = BH.Engine.LadybugTools.Compute.InstallPythonEnv_LBT(run: true);
4042
}
43+
44+
public LadybugToolsAdapter(PythonEnvironment environment)
45+
{
46+
m_AdapterSettings.DefaultPushType = oM.Adapter.PushType.CreateOnly;
47+
m_environment = environment;
48+
}
49+
4150
private readonly PythonEnvironment m_environment;
4251
}
4352
}

LadybugTools_Adapter/LadybugTools_Adapter.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<Authors>BHoM</Authors>
99
<Copyright>Copyright © https://github.com/BHoM</Copyright>
1010
<RootNamespace>BH.Adapter.LadybugTools</RootNamespace>
11-
<FileVersion>7.1.0.0</FileVersion>
11+
<FileVersion>7.2.0.0</FileVersion>
1212
<OutputPath>..\Build\</OutputPath>
1313
</PropertyGroup>
1414

LadybugTools_Engine/Create/Typology.cs

Lines changed: 149 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@
2020
* along with this code. If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
2121
*/
2222

23+
using BH.Engine.Base;
24+
using BH.Engine.Environment;
25+
using BH.Engine.Geometry;
2326
using BH.oM.Base.Attributes;
27+
using BH.oM.Environment.Elements;
28+
using BH.oM.Geometry;
2429
using BH.oM.LadybugTools;
2530
using System.Collections.Generic;
2631
using System.ComponentModel;
2732
using System.Linq;
33+
using System.Security.Cryptography;
2834

2935
namespace BH.Engine.LadybugTools
3036
{
@@ -117,6 +123,147 @@ public static Typology Typology(
117123
RadiantTemperatureAdjustment = radiantTemperatureAdjustment
118124
};
119125
}
120-
}
121-
}
122126

127+
/******************************************************/
128+
129+
[Description("Create a typology from a set of inputs.")]
130+
[Input("name", "The identifier of the typology created.")]
131+
[Input("hasSkyShelter", "Whether the typology has a circular sky shelter.")]
132+
[Input("skyShelterRadius", "The Radius of the circular sky shelter.")]
133+
[Input("skyShelterHeight", "The height the sky shelter is above the ground.")]
134+
[Input("hasNorthShelter", "Whether the typology has a north-facing shelter wall.")]
135+
[Input("northShelterHeight", "The height that the northern shelter wall extends to.")]
136+
[Input("hasEastShelter", "Whether the typology has an east-facing shelter wall.")]
137+
[Input("eastShelterHeight", "The height that the eastern shelter wall extends to.")]
138+
[Input("hasSouthShelter", "Whether the typology has a south-facing shelter wall.")]
139+
[Input("southShelterHeight", "The eight that the southern shelter wall extends to.")]
140+
[Input("hasWestShelter", "Whether the typology has a west-facing shelter wall.")]
141+
[Input("westShelterHeight", "The height that the western shelter wall extends to.")]
142+
[Input("shelterWindPorosity", "The wind porosity of all shelters (must be between 0 and 1 inclusive).")]
143+
[Input("shelterRadiationPorosity", "The radiation porosity of all shelters (must be between 0 and 1 inclusive).")]
144+
[Input("evaporativeCoolingEffect", "The effective evaporative cooling that is present in this typology (must be between 0 and 1 inclusive).")]
145+
[Input("radiantTemperatureAdjustment", "Any radiant temperature adjustment to apply to the resultant typology.")]
146+
[Input("targetWindSpeed", "List of wind speeds to be used in this typology (will replace wind speeds present in the epw when calculating UTCI).")]
147+
[Output("typology", "The generated typology.")]
148+
public static Typology Typology(
149+
string name,
150+
bool hasSkyShelter = false,
151+
double skyShelterRadius = 5,
152+
double skyShelterHeight = 2.5,
153+
bool hasNorthShelter = false,
154+
double northShelterHeight = 2.5,
155+
bool hasEastShelter = false,
156+
double eastShelterHeight = 2.5,
157+
bool hasSouthShelter = false,
158+
double southShelterHeight = 2.5,
159+
bool hasWestShelter = false,
160+
double westShelterHeight = 2.5,
161+
double shelterWindPorosity = 0,
162+
double shelterRadiationPorosity = 0,
163+
double evaporativeCoolingEffect = 0,
164+
double radiantTemperatureAdjustment = 0,
165+
double? targetWindSpeed = null
166+
)
167+
{
168+
if (hasSkyShelter && skyShelterRadius < 0)
169+
{
170+
BH.Engine.Base.Compute.RecordError("The sky shelter radius must be greater than or equal to 0.");
171+
return null;
172+
}
173+
174+
if (hasSkyShelter && skyShelterHeight < 0)
175+
{
176+
BH.Engine.Base.Compute.RecordError("The sky shelter height must be greater than or equal to 0.");
177+
return null;
178+
}
179+
180+
if (hasNorthShelter && northShelterHeight < 0)
181+
{
182+
BH.Engine.Base.Compute.RecordError("The north shelter height must be greater than or equal to 0.");
183+
return null;
184+
}
185+
186+
if (hasEastShelter && eastShelterHeight < 0)
187+
{
188+
BH.Engine.Base.Compute.RecordError("The east shelter height must be greater than or equal to 0.");
189+
return null;
190+
}
191+
192+
if (hasSouthShelter && southShelterHeight < 0)
193+
{
194+
BH.Engine.Base.Compute.RecordError("The south shelter height must be greater than or equal to 0.");
195+
return null;
196+
}
197+
198+
if (hasWestShelter && westShelterHeight < 0)
199+
{
200+
BH.Engine.Base.Compute.RecordError("The west shelter height must be greater than or equal to 0.");
201+
return null;
202+
}
203+
204+
if (shelterWindPorosity < 0 || shelterWindPorosity > 1)
205+
{
206+
BH.Engine.Base.Compute.RecordError("The shelter wind porosity must be between 0 and 1 inclusive.");
207+
return null;
208+
}
209+
210+
if (shelterRadiationPorosity < 0 || shelterRadiationPorosity > 1)
211+
{
212+
BH.Engine.Base.Compute.RecordError("The shelter radiation porosity must be between 0 and 1 inclusive.");
213+
return null;
214+
}
215+
216+
if (evaporativeCoolingEffect < 0 || evaporativeCoolingEffect > 1)
217+
{
218+
BH.Engine.Base.Compute.RecordError("The evaporative cooling effect must be between 0 and 1 inclusive.");
219+
return null;
220+
}
221+
222+
if (targetWindSpeed != null && targetWindSpeed < 0)
223+
{
224+
BH.Engine.Base.Compute.RecordError("The target wind speed must be greater than or equal to 0, or be null.");
225+
return null;
226+
}
227+
228+
Polyline perimeter = Geometry.Create.Polyline(new List<Point>() { Geometry.Create.Point(x: 1, y: 1), Geometry.Create.Point(x: 1, y: -1), Geometry.Create.Point(x: -1, y: -1), Geometry.Create.Point(x: -1, y: 1), Geometry.Create.Point(x: 1, y: 1) });
229+
List<Panel> panels = Environment.Compute.ExtrudeToVolume(perimeter, "temp", 2).Where(x => x.Type == PanelType.Wall).ToList();
230+
231+
List<double> radiationPorosity = Enumerable.Repeat(shelterRadiationPorosity, 8760).ToList();
232+
List<double> windPorosity = Enumerable.Repeat(shelterWindPorosity, 8760).ToList();
233+
List<double> radiantTemperature = Enumerable.Repeat(radiantTemperatureAdjustment, 8760).ToList();
234+
List<double> evaporativeCooling = Enumerable.Repeat(evaporativeCoolingEffect, 8760).ToList();
235+
List<double?> windSpeed = Enumerable.Repeat(targetWindSpeed, 8760).ToList();
236+
List<Shelter> shelters = new List<Shelter>();
237+
238+
if (hasEastShelter)
239+
shelters.Add(Convert.ToShelter(panels[0].ChangeHeight(eastShelterHeight), radiationPorosity, windPorosity));
240+
if (hasSouthShelter)
241+
shelters.Add(Convert.ToShelter(panels[1].ChangeHeight(southShelterHeight), radiationPorosity, windPorosity));
242+
if (hasWestShelter)
243+
shelters.Add(Convert.ToShelter(panels[2].ChangeHeight(westShelterHeight), radiationPorosity, windPorosity));
244+
if (hasNorthShelter)
245+
shelters.Add(Convert.ToShelter(panels[3].ChangeHeight(northShelterHeight), radiationPorosity, windPorosity));
246+
247+
if (hasSkyShelter)
248+
{
249+
shelters.Add(
250+
Convert.ToShelter(
251+
new Panel() { ExternalEdges = Geometry.Create.Circle(Geometry.Create.Point(x: 0, y: 0, z: skyShelterHeight), skyShelterRadius).CollapseToPolyline(Tolerance.Angle, 36).ToEdges() },
252+
radiationPorosity,
253+
windPorosity
254+
)
255+
);
256+
}
257+
258+
return Create.Typology(name, shelters, evaporativeCooling, windSpeed, radiantTemperature);
259+
}
260+
261+
private static Panel ChangeHeight(this Panel panel, double height)
262+
{
263+
Polyline pLine = panel.Polyline();
264+
//Change Z values of control points that have a z value that isn't equal to 0
265+
pLine.ControlPoints = pLine.ControlPoints.Select(x => Geometry.Create.Point(x: x.X, y: x.Y, z: x.Z == 0 ? 0 : height)).ToList();
266+
return new Panel() { ExternalEdges = pLine.ToEdges() };
267+
}
268+
}
269+
}

LadybugTools_Engine/LadybugTools_Engine.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<Authors>BHoM</Authors>
88
<Copyright>Copyright © https://github.com/BHoM</Copyright>
99
<RootNamespace>BH.Engine.LadyBugTools</RootNamespace>
10-
<FileVersion>7.1.0.0</FileVersion>
10+
<FileVersion>7.2.0.0</FileVersion>
1111
<OutputPath>..\Build\</OutputPath>
1212
</PropertyGroup>
1313
<ItemGroup>
@@ -81,9 +81,9 @@
8181
</Reference>
8282
</ItemGroup>
8383
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
84-
<Exec Command="xcopy $(ProjectDir)Convert\System.Web.Extensions.dll $(ProgramData)\BHoM\Assemblies /Y&#xD;&#xA;&#xD;&#xA;if not exist $(ProgramData)\BHoM\Extensions\PythonEnvironments mkdir $(ProgramData)\BHoM\Extensions\PythonEnvironments&#xD;&#xA;if not exist $(ProgramData)\BHoM\Extensions\PythonCode mkdir $(ProgramData)\BHoM\Extensions\PythonCode&#xD;&#xA; &#xD;&#xA;if exist $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) rmdir $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) /S /Q&#xD;&#xA;mkdir $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName)&#xD;&#xA;&#xD;&#xA;robocopy $(ProjectDir)Python $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) /mir /xf &quot;*.pyc&quot; &quot;*.ipynb&quot; /xd &quot;__*__&quot; &quot;.*&quot; &gt; output.log&#xD;&#xA;del output.log" />
84+
<Exec Command="if not exist $(ProgramData)\BHoM\Extensions\PythonEnvironments mkdir $(ProgramData)\BHoM\Extensions\PythonEnvironments&#xD;&#xA;if not exist $(ProgramData)\BHoM\Extensions\PythonCode mkdir $(ProgramData)\BHoM\Extensions\PythonCode&#xD;&#xA; &#xD;&#xA;if exist $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) rmdir $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) /S /Q&#xD;&#xA;mkdir $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName)&#xD;&#xA;&#xD;&#xA;robocopy &quot;$(ProjectDir)Python&quot; $(ProgramData)\BHoM\Extensions\PythonCode\$(SolutionName) /mir /xf &quot;*.pyc&quot; &quot;*.ipynb&quot; /xd &quot;__*__&quot; &quot;.*&quot; &gt; output.log&#xD;&#xA;del output.log" />
8585
</Target>
8686
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
87-
<Exec Command="xcopy $(TargetDir)$(TargetFileName) $(ProgramData)\BHoM\Assemblies /Y" />
87+
<Exec Command="xcopy &quot;$(TargetDir)$(TargetFileName)&quot; &quot;$(ProgramData)\BHoM\Assemblies&quot; /Y" />
8888
</Target>
8989
</Project>

LadybugTools_Engine/Python/src/ladybugtools_toolkit/bhom/__init__.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@
66
from win32api import HIWORD, LOWORD, GetFileVersionInfo
77

88
BHOM_ASSEMBLIES_DIRECTORY = Path(path.expandvars("%PROGRAMDATA%/BHoM/Assemblies"))
9-
BHOM_DIRECTORY = Path(path.expandvars("%PROGRAMDATA%/BHoM"))
109
BHOM_LOG_FOLDER = Path(path.expandvars("%PROGRAMDATA%/BHoM/Logs"))
11-
12-
PYTHON_CODE_DIRECTORY = Path(path.expandvars("%PROGRAMDATA%/BHoM/Extensions/PythonCode"))
13-
PYTHON_ENVIRONMENTS_DIRECTORY = Path(path.expandvars("%PROGRAMDATA%/BHoM/Extensions/PythonEnvironments"))
14-
1510
TOOLKIT_NAME = "LadybugTools_Toolkit"
1611

17-
_file_version_ms = GetFileVersionInfo(
18-
(BHOM_ASSEMBLIES_DIRECTORY / "BHoM.dll").as_posix(), "\\"
19-
)["FileVersionMS"]
12+
if not BHOM_LOG_FOLDER.exists():
13+
BHOM_LOG_FOLDER = Path(path.expandvars("%TEMP%/BHoMLogs"))
14+
BHOM_LOG_FOLDER.mkdir(exist_ok=True)
15+
16+
if not BHOM_ASSEMBLIES_DIRECTORY.exists():
17+
BHOM_VERSION = ""
18+
else:
19+
_file_version_ms = GetFileVersionInfo(
20+
(BHOM_ASSEMBLIES_DIRECTORY / "BHoM.dll").as_posix(), "\\"
21+
)["FileVersionMS"]
2022

21-
BHOM_VERSION = f"{HIWORD(_file_version_ms)}.{LOWORD(_file_version_ms)}"
23+
BHOM_VERSION = f"{HIWORD(_file_version_ms)}.{LOWORD(_file_version_ms)}"
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"""Method to wrap creation of panel orientation plots"""
2+
# pylint: disable=C0415,E0401,W0703
3+
import argparse
4+
import traceback
5+
from pathlib import Path
6+
import os
7+
8+
def directional_solar_radiation(epw_file, azimuths, altitudes, ground_reflectance, irradiance_type, isotropic, analysis_period, title, save_path):
9+
try:
10+
from ladybugtools_toolkit.solar import Solar, IrradianceType
11+
from ladybug.wea import EPW, AnalysisPeriod
12+
from ladybugtools_toolkit.plot.utilities import figure_to_base64
13+
import matplotlib.pyplot as plt
14+
from pathlib import Path
15+
import json
16+
17+
analysis_period = AnalysisPeriod.from_dict(json.loads(analysis_period))
18+
19+
if irradiance_type == "Total":
20+
irradiance_type = IrradianceType.TOTAL
21+
elif irradiance_type == "Diffuse":
22+
irradiance_type = IrradianceType.DIFFUSE
23+
elif irradiance_type == "Direct":
24+
irradiance_type = IrradianceType.DIRECT
25+
elif irradiance_type == "Reflected":
26+
irradiance_type = IrradianceType.REFLECTED
27+
28+
epw = EPW(epw_file)
29+
solar = Solar.from_epw(epw)
30+
fig, ax = plt.subplots(1, 1, figsize=(22.8/2, 7.6/2))
31+
solar.plot_tilt_orientation_factor(location=epw.location, ax=ax, azimuths=azimuths, altitudes=altitudes, isotropic=isotropic, irradiance_type=irradiance_type, analysis_period=analysis_period, ground_reflectance=ground_reflectance).get_figure()
32+
ax.set_title(title)
33+
34+
35+
if save_path is None or save_path == "":
36+
base64 = figure_to_base64(fig, html=False)
37+
print(base64)
38+
else:
39+
fig.savefig(save_path, dpi=150, transparent=True)
40+
print(save_path)
41+
except Exception as ex:
42+
print(traceback.format_exc())
43+
44+
if __name__ == "__main__":
45+
parser = argparse.ArgumentParser(
46+
description=(
47+
"Given an EPW file path, extract a heatmap"
48+
)
49+
)
50+
parser.add_argument(
51+
"-e",
52+
"--epw_file",
53+
help="The EPW file to extract a heatmap from",
54+
type=str,
55+
required=True,
56+
)
57+
parser.add_argument(
58+
"-az",
59+
"--azimuths",
60+
help="The azimuths to use when plotting orientations",
61+
type=int,
62+
required=True,
63+
)
64+
parser.add_argument(
65+
"-al",
66+
"--altitudes",
67+
help="The altitudes to use when plotting orientations",
68+
type=int,
69+
required=True,
70+
)
71+
parser.add_argument(
72+
"-gr",
73+
"--ground_reflectance",
74+
help="The ground reflectance, between 0 and 1",
75+
type=float,
76+
required=True,
77+
)
78+
parser.add_argument(
79+
"-ir",
80+
"--irradiance_type",
81+
help="The irradiance type to plot",
82+
type=str,
83+
required=True,
84+
)
85+
parser.add_argument(
86+
"-iso",
87+
"--isotropic",
88+
help="Whether the method should calculate isotropic diffuse irradiance",
89+
default=False,
90+
action="store_true",
91+
)
92+
parser.add_argument(
93+
"-ap",
94+
"--analysis_period",
95+
help="Analysis period",
96+
type=str,
97+
required=True,
98+
)
99+
parser.add_argument(
100+
"-t",
101+
"--title",
102+
help="The title displayed on the plot",
103+
type=str,
104+
required=True,
105+
)
106+
parser.add_argument(
107+
"-p",
108+
"--save_path",
109+
help="Path where to save the output image.",
110+
type=str,
111+
required=False,
112+
)
113+
114+
args = parser.parse_args()
115+
116+
os.environ["TQDM_DISABLE"] = "1" # set an environment variable so that progress bars are disabled for the simulation process
117+
directional_solar_radiation(args.epw_file, args.azimuths, args.altitudes, args.ground_reflectance, args.irradiance_type, args.isotropic, args.analysis_period, args.title, args.save_path)
118+
del os.environ["TQDM_DISABLE"] # unset the env variable

0 commit comments

Comments
 (0)