voxcity 0.6.19__py3-none-any.whl → 0.6.21__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.
Potentially problematic release.
This version of voxcity might be problematic. Click here for more details.
- voxcity/downloader/citygml.py +32 -18
- voxcity/exporter/obj.py +1405 -1405
- voxcity/generator.py +1301 -1291
- voxcity/simulator/solar.py +12 -2
- voxcity/utils/visualization.py +2734 -2691
- voxcity/utils/weather.py +68 -6
- {voxcity-0.6.19.dist-info → voxcity-0.6.21.dist-info}/METADATA +2 -2
- {voxcity-0.6.19.dist-info → voxcity-0.6.21.dist-info}/RECORD +11 -11
- {voxcity-0.6.19.dist-info → voxcity-0.6.21.dist-info}/WHEEL +0 -0
- {voxcity-0.6.19.dist-info → voxcity-0.6.21.dist-info}/licenses/AUTHORS.rst +0 -0
- {voxcity-0.6.19.dist-info → voxcity-0.6.21.dist-info}/licenses/LICENSE +0 -0
voxcity/utils/weather.py
CHANGED
|
@@ -209,7 +209,9 @@ def process_epw(epw_path: Union[str, Path]) -> Tuple[pd.DataFrame, Dict]:
|
|
|
209
209
|
# =============================================================================
|
|
210
210
|
|
|
211
211
|
def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float, output_dir: str = "./", max_distance: Optional[float] = None,
|
|
212
|
-
extract_zip: bool = True, load_data: bool = True, region: Optional[Union[str, List[str]]] = None
|
|
212
|
+
extract_zip: bool = True, load_data: bool = True, region: Optional[Union[str, List[str]]] = None,
|
|
213
|
+
allow_insecure_ssl: bool = False, allow_http_fallback: bool = False,
|
|
214
|
+
ssl_verify: Union[bool, str] = True) -> Tuple[Optional[str], Optional[pd.DataFrame], Optional[Dict]]:
|
|
213
215
|
"""
|
|
214
216
|
Download and process EPW weather file from Climate.OneBuilding.Org based on coordinates.
|
|
215
217
|
|
|
@@ -243,6 +245,9 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
243
245
|
plus legacy "Canada", "USA", "Caribbean" (Region 4).
|
|
244
246
|
Use "all" to scan every dataset.
|
|
245
247
|
If None, will auto-detect region based on coordinates.
|
|
248
|
+
allow_insecure_ssl (bool): If True, on SSL errors retry with certificate verification disabled.
|
|
249
|
+
allow_http_fallback (bool): If True, on SSL/network errors, also try HTTP (insecure) fallback.
|
|
250
|
+
ssl_verify (bool|str): Passed to requests as 'verify' parameter for HTTPS; can be False or CA bundle path.
|
|
246
251
|
|
|
247
252
|
Returns:
|
|
248
253
|
Tuple containing:
|
|
@@ -629,9 +634,36 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
629
634
|
continue
|
|
630
635
|
tried.add(u)
|
|
631
636
|
try:
|
|
632
|
-
resp = requests.get(u, timeout=timeout_s)
|
|
637
|
+
resp = requests.get(u, timeout=timeout_s, verify=ssl_verify)
|
|
633
638
|
resp.raise_for_status()
|
|
634
639
|
return resp.content
|
|
640
|
+
except requests.exceptions.SSLError:
|
|
641
|
+
# Retry with user-controlled insecure SSL
|
|
642
|
+
if allow_insecure_ssl:
|
|
643
|
+
try:
|
|
644
|
+
resp = requests.get(u, timeout=timeout_s, verify=False)
|
|
645
|
+
resp.raise_for_status()
|
|
646
|
+
return resp.content
|
|
647
|
+
except requests.exceptions.RequestException:
|
|
648
|
+
if allow_http_fallback and u.lower().startswith("https://"):
|
|
649
|
+
insecure_url = "http://" + u.split("://", 1)[1]
|
|
650
|
+
try:
|
|
651
|
+
resp = requests.get(insecure_url, timeout=timeout_s)
|
|
652
|
+
resp.raise_for_status()
|
|
653
|
+
return resp.content
|
|
654
|
+
except requests.exceptions.RequestException:
|
|
655
|
+
pass
|
|
656
|
+
continue
|
|
657
|
+
else:
|
|
658
|
+
if allow_http_fallback and u.lower().startswith("https://"):
|
|
659
|
+
insecure_url = "http://" + u.split("://", 1)[1]
|
|
660
|
+
try:
|
|
661
|
+
resp = requests.get(insecure_url, timeout=timeout_s)
|
|
662
|
+
resp.raise_for_status()
|
|
663
|
+
return resp.content
|
|
664
|
+
except requests.exceptions.RequestException:
|
|
665
|
+
pass
|
|
666
|
+
continue
|
|
635
667
|
except requests.exceptions.HTTPError as he:
|
|
636
668
|
# Only continue on 404; raise on other HTTP errors
|
|
637
669
|
if getattr(he.response, "status_code", None) == 404:
|
|
@@ -658,9 +690,32 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
658
690
|
List of dictionaries containing station metadata
|
|
659
691
|
"""
|
|
660
692
|
try:
|
|
661
|
-
# Download KML file with timeout
|
|
662
|
-
|
|
663
|
-
|
|
693
|
+
# Download KML file with timeout (secure first)
|
|
694
|
+
try:
|
|
695
|
+
response = requests.get(kml_url, timeout=30, verify=ssl_verify)
|
|
696
|
+
response.raise_for_status()
|
|
697
|
+
except requests.exceptions.SSLError:
|
|
698
|
+
if allow_insecure_ssl:
|
|
699
|
+
# Retry with certificate verification disabled (last resort)
|
|
700
|
+
try:
|
|
701
|
+
response = requests.get(kml_url, timeout=30, verify=False)
|
|
702
|
+
response.raise_for_status()
|
|
703
|
+
except requests.exceptions.RequestException:
|
|
704
|
+
# Try HTTP fallback if original was HTTPS and allowed
|
|
705
|
+
if allow_http_fallback and kml_url.lower().startswith("https://"):
|
|
706
|
+
insecure_url = "http://" + kml_url.split("://", 1)[1]
|
|
707
|
+
response = requests.get(insecure_url, timeout=30)
|
|
708
|
+
response.raise_for_status()
|
|
709
|
+
else:
|
|
710
|
+
raise
|
|
711
|
+
else:
|
|
712
|
+
# Try HTTP fallback only if allowed and original was HTTPS
|
|
713
|
+
if allow_http_fallback and kml_url.lower().startswith("https://"):
|
|
714
|
+
insecure_url = "http://" + kml_url.split("://", 1)[1]
|
|
715
|
+
response = requests.get(insecure_url, timeout=30)
|
|
716
|
+
response.raise_for_status()
|
|
717
|
+
else:
|
|
718
|
+
raise
|
|
664
719
|
|
|
665
720
|
# Try to decode content with multiple encodings
|
|
666
721
|
content = try_decode(response.content)
|
|
@@ -917,8 +972,15 @@ def read_epw_for_solar_simulation(epw_file_path):
|
|
|
917
972
|
Raises:
|
|
918
973
|
ValueError: If LOCATION line not found or data parsing fails
|
|
919
974
|
"""
|
|
975
|
+
# Validate input path
|
|
976
|
+
if epw_file_path is None:
|
|
977
|
+
raise TypeError("EPW file path is None. Provide a valid path or ensure download succeeded.")
|
|
978
|
+
epw_path_obj = Path(epw_file_path)
|
|
979
|
+
if not epw_path_obj.exists() or not epw_path_obj.is_file():
|
|
980
|
+
raise FileNotFoundError(f"EPW file not found: {epw_file_path}")
|
|
981
|
+
|
|
920
982
|
# Read the entire EPW file
|
|
921
|
-
with open(
|
|
983
|
+
with open(epw_path_obj, 'r', encoding='utf-8') as f:
|
|
922
984
|
lines = f.readlines()
|
|
923
985
|
|
|
924
986
|
# Find the LOCATION line (first line in EPW format)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.21
|
|
4
4
|
Summary: voxcity is an easy and one-stop tool to output 3d city models for microclimate simulation by integrating multiple geospatial open-data
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: AUTHORS.rst
|
|
@@ -129,7 +129,7 @@ Make sure you have Python 3.12 installed. Install voxcity with:
|
|
|
129
129
|
```bash
|
|
130
130
|
conda create --name voxcity python=3.12
|
|
131
131
|
conda activate voxcity
|
|
132
|
-
conda install -c conda-forge gdal
|
|
132
|
+
conda install -c conda-forge gdal timezonefinder
|
|
133
133
|
pip install voxcity
|
|
134
134
|
```
|
|
135
135
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
voxcity/__init__.py,sha256=el9v3gfybHOF_GUYPeSOqN0-vCrTW0eU1mcvi0sEfeU,252
|
|
2
2
|
voxcity/downloader/__init__.py,sha256=o_T_EU7hZLGyXxX9wVWn1x-OAa3ThGYdnpgB1_2v3AE,151
|
|
3
|
-
voxcity/downloader/citygml.py,sha256=
|
|
3
|
+
voxcity/downloader/citygml.py,sha256=I8-wWijqVOA1VeH3nFP9ZlC3l6XvXfli6lB17ZIXHb0,42232
|
|
4
4
|
voxcity/downloader/eubucco.py,sha256=ln1YNaaOgJfxNfCtVbYaMm775-bUvpAA_LDv60_i22w,17875
|
|
5
5
|
voxcity/downloader/gee.py,sha256=nvJvYqcSZyyontRtG2cFeb__ZJfeY4rRN1NBPORxLwQ,23557
|
|
6
6
|
voxcity/downloader/mbfp.py,sha256=UXDVjsO0fnb0fSal9yqrSFEIBThnRmnutnp08kZTmCA,6595
|
|
@@ -13,8 +13,8 @@ voxcity/exporter/cityles.py,sha256=Kfl2PAn4WquqCdjOlyPrHysxPLaudh8QfsoC6WAXlvs,1
|
|
|
13
13
|
voxcity/exporter/envimet.py,sha256=Sh7s1JdQ6SgT_L2Xd_c4gtEGWK2hTS87bccaoIqik-s,31105
|
|
14
14
|
voxcity/exporter/magicavoxel.py,sha256=SfGEgTZRlossKx3Xrv9d3iKSX-HmfQJEL9lZHgWMDX4,12782
|
|
15
15
|
voxcity/exporter/netcdf.py,sha256=48rJ3wDsFhi9ANbElhMjXLxWMJoJzBt1gFbN0ekPp-A,7404
|
|
16
|
-
voxcity/exporter/obj.py,sha256=
|
|
17
|
-
voxcity/generator.py,sha256=
|
|
16
|
+
voxcity/exporter/obj.py,sha256=aiaG8hMuggNnyCwsFZVhisnHm3BbUHi8SX4m9CyCYgc,59565
|
|
17
|
+
voxcity/generator.py,sha256=Sw-PN0FNLbUPuawHv_tZZPrEkSnPgIc5DBAh3JUn1aY,68473
|
|
18
18
|
voxcity/geoprocessor/__init__.py,sha256=WYxcAQrjGucIvGHF0JTC6rONZzL3kCms1S2vpzS6KaU,127
|
|
19
19
|
voxcity/geoprocessor/draw.py,sha256=AZMWq23wxxDJygNloCbVzWAAr1JO7nC94umf9LSxJ5o,49248
|
|
20
20
|
voxcity/geoprocessor/grid.py,sha256=NmlQwl1nJpS7MduVtJeJCG-xBfVIwKTOip7pMm3RhsY,76722
|
|
@@ -23,16 +23,16 @@ voxcity/geoprocessor/network.py,sha256=YynqR0nq_NUra_cQ3Z_56KxfRia1b6-hIzGCj3QT-
|
|
|
23
23
|
voxcity/geoprocessor/polygon.py,sha256=DfzXf6R-qoWXEZv1z1aHCVfr-DCuCFw6lieQT5cNHPA,61188
|
|
24
24
|
voxcity/geoprocessor/utils.py,sha256=s17XpgkLBelmNCk2wcUwTK1tEiFpguWR2BF_n7K17jg,31378
|
|
25
25
|
voxcity/simulator/__init__.py,sha256=APdkcdaovj0v_RPOaA4SBvFUKT2RM7Hxuuz3Sux4gCo,65
|
|
26
|
-
voxcity/simulator/solar.py,sha256=
|
|
26
|
+
voxcity/simulator/solar.py,sha256=4D5t2I79vBW1qXd90BZR0tMiA9WOEXWLG5b-d6E2XbQ,107127
|
|
27
27
|
voxcity/simulator/utils.py,sha256=sEYBB2-hLJxTiXQps1_-Fi7t1HN3-1OPOvBCWtgIisA,130
|
|
28
28
|
voxcity/simulator/view.py,sha256=k3FoS6gsibR-eDrTHJivJSQfvN3Tg8R8eSTeMqd9ans,93942
|
|
29
29
|
voxcity/utils/__init__.py,sha256=Q-NYCqYnAAaF80KuNwpqIjbE7Ec3Gr4y_khMLIMhJrg,68
|
|
30
30
|
voxcity/utils/lc.py,sha256=722Gz3lPbgAp0mmTZ-g-QKBbAnbxrcgaYwb1sa7q8Sk,16189
|
|
31
31
|
voxcity/utils/material.py,sha256=H8K8Lq4wBL6dQtgj7esUW2U6wLCOTeOtelkTDJoRgMo,10007
|
|
32
|
-
voxcity/utils/visualization.py,sha256=
|
|
33
|
-
voxcity/utils/weather.py,sha256=
|
|
34
|
-
voxcity-0.6.
|
|
35
|
-
voxcity-0.6.
|
|
36
|
-
voxcity-0.6.
|
|
37
|
-
voxcity-0.6.
|
|
38
|
-
voxcity-0.6.
|
|
32
|
+
voxcity/utils/visualization.py,sha256=rPPxZeoMvzDblZe6A2vgRkX1PHXVdft6l36nLOuSRkU,114774
|
|
33
|
+
voxcity/utils/weather.py,sha256=cb6ZooL42Hc4214OtFiJ78cCgWYM6VE-DU8S3e-urRg,48449
|
|
34
|
+
voxcity-0.6.21.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
|
|
35
|
+
voxcity-0.6.21.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
|
|
36
|
+
voxcity-0.6.21.dist-info/METADATA,sha256=mt2V_ZeRFL7UUBuEeUUUc_Br_fhvB9pPtbXVTaTvobY,26227
|
|
37
|
+
voxcity-0.6.21.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
|
|
38
|
+
voxcity-0.6.21.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|