voxcity 0.6.18__py3-none-any.whl → 0.6.19__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/exporter/obj.py +1405 -1191
- voxcity/utils/weather.py +209 -50
- {voxcity-0.6.18.dist-info → voxcity-0.6.19.dist-info}/METADATA +4 -2
- {voxcity-0.6.18.dist-info → voxcity-0.6.19.dist-info}/RECORD +7 -7
- {voxcity-0.6.18.dist-info → voxcity-0.6.19.dist-info}/WHEEL +1 -1
- {voxcity-0.6.18.dist-info → voxcity-0.6.19.dist-info/licenses}/AUTHORS.rst +0 -0
- {voxcity-0.6.18.dist-info → voxcity-0.6.19.dist-info/licenses}/LICENSE +0 -0
voxcity/utils/weather.py
CHANGED
|
@@ -233,10 +233,15 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
233
233
|
If no stations within this distance, uses closest available.
|
|
234
234
|
extract_zip (bool): Whether to extract the ZIP file (default True)
|
|
235
235
|
load_data (bool): Whether to load the EPW data into a DataFrame (default True)
|
|
236
|
-
region (str or List[str], optional): Specific region(s) to scan for stations.
|
|
237
|
-
|
|
238
|
-
"
|
|
239
|
-
"Europe", "Antarctica"
|
|
236
|
+
region (str or List[str], optional): Specific region(s) or dataset(s) to scan for stations.
|
|
237
|
+
Regions: "Africa", "Asia", "South_America",
|
|
238
|
+
"North_and_Central_America", "Southwest_Pacific",
|
|
239
|
+
"Europe", "Antarctica".
|
|
240
|
+
Sub-datasets (can be used alone or auto-included by region):
|
|
241
|
+
"Japan", "India", "CSWD", "CityUHK", "PHIKO",
|
|
242
|
+
"Argentina", "INMET_TRY", "AMTUes", "BrazFuture",
|
|
243
|
+
plus legacy "Canada", "USA", "Caribbean" (Region 4).
|
|
244
|
+
Use "all" to scan every dataset.
|
|
240
245
|
If None, will auto-detect region based on coordinates.
|
|
241
246
|
|
|
242
247
|
Returns:
|
|
@@ -250,35 +255,83 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
250
255
|
requests.exceptions.RequestException: If network requests fail
|
|
251
256
|
"""
|
|
252
257
|
|
|
253
|
-
# Regional KML sources from Climate.OneBuilding.Org
|
|
254
|
-
# Each region maintains
|
|
258
|
+
# Regional KML sources from Climate.OneBuilding.Org (2024+ TMYx structure)
|
|
259
|
+
# Each WMO region maintains a primary KML in /sources with the naming pattern:
|
|
260
|
+
# Region{N}_{Name}_TMYx_EPW_Processing_locations.kml
|
|
261
|
+
# Keep sub-region keys for backward compatibility (mapping to the Region KML where applicable)
|
|
255
262
|
KML_SOURCES = {
|
|
256
|
-
|
|
257
|
-
"
|
|
263
|
+
# WMO Region 1
|
|
264
|
+
"Africa": "https://climate.onebuilding.org/sources/Region1_Africa_TMYx_EPW_Processing_locations.kml",
|
|
265
|
+
# WMO Region 2
|
|
266
|
+
"Asia": "https://climate.onebuilding.org/sources/Region2_Asia_TMYx_EPW_Processing_locations.kml",
|
|
267
|
+
# Subsets/datasets within Asia that still publish dedicated KMLs
|
|
258
268
|
"Japan": "https://climate.onebuilding.org/sources/JGMY_EPW_Processing_locations.kml",
|
|
259
269
|
"India": "https://climate.onebuilding.org/sources/ITMY_EPW_Processing_locations.kml",
|
|
270
|
+
"CSWD": "https://climate.onebuilding.org/sources/CSWD_EPW_Processing_locations.kml",
|
|
271
|
+
"CityUHK": "https://climate.onebuilding.org/sources/CityUHK_EPW_Processing_locations.kml",
|
|
272
|
+
"PHIKO": "https://climate.onebuilding.org/sources/PHIKO_EPW_Processing_locations.kml",
|
|
273
|
+
# WMO Region 3
|
|
274
|
+
"South_America": "https://climate.onebuilding.org/sources/Region3_South_America_TMYx_EPW_Processing_locations.kml",
|
|
275
|
+
# Historical/legacy dataset for Argentina maintained separately
|
|
260
276
|
"Argentina": "https://climate.onebuilding.org/sources/ArgTMY_EPW_Processing_locations.kml",
|
|
277
|
+
"INMET_TRY": "https://climate.onebuilding.org/sources/INMET_TRY_EPW_Processing_locations.kml",
|
|
278
|
+
"AMTUes": "https://climate.onebuilding.org/sources/AMTUes_EPW_Processing_locations.kml",
|
|
279
|
+
"BrazFuture": "https://climate.onebuilding.org/sources/BrazFuture_EPW_Processing_locations.kml",
|
|
280
|
+
# WMO Region 4 (use subregion KMLs; umbrella selection expands to these)
|
|
281
|
+
# Note: There is no single unified Region 4 KML in /sources as of 2024.
|
|
282
|
+
# Use these three subregion KMLs instead.
|
|
261
283
|
"Canada": "https://climate.onebuilding.org/sources/Region4_Canada_TMYx_EPW_Processing_locations.kml",
|
|
262
284
|
"USA": "https://climate.onebuilding.org/sources/Region4_USA_TMYx_EPW_Processing_locations.kml",
|
|
263
285
|
"Caribbean": "https://climate.onebuilding.org/sources/Region4_NA_CA_Caribbean_TMYx_EPW_Processing_locations.kml",
|
|
286
|
+
# WMO Region 5
|
|
264
287
|
"Southwest_Pacific": "https://climate.onebuilding.org/sources/Region5_Southwest_Pacific_TMYx_EPW_Processing_locations.kml",
|
|
288
|
+
# WMO Region 6
|
|
265
289
|
"Europe": "https://climate.onebuilding.org/sources/Region6_Europe_TMYx_EPW_Processing_locations.kml",
|
|
266
|
-
|
|
290
|
+
# WMO Region 7
|
|
291
|
+
"Antarctica": "https://climate.onebuilding.org/sources/Region7_Antarctica_TMYx_EPW_Processing_locations.kml",
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
# Group region selections to include relevant sub-datasets automatically
|
|
295
|
+
REGION_DATASET_GROUPS = {
|
|
296
|
+
"Africa": ["Africa"],
|
|
297
|
+
"Asia": ["Asia", "Japan", "India", "CSWD", "CityUHK", "PHIKO"],
|
|
298
|
+
"South_America": ["South_America", "Argentina", "INMET_TRY", "AMTUes", "BrazFuture"],
|
|
299
|
+
"North_and_Central_America": ["North_and_Central_America", "Canada", "USA", "Caribbean"],
|
|
300
|
+
"Southwest_Pacific": ["Southwest_Pacific"],
|
|
301
|
+
"Europe": ["Europe"],
|
|
302
|
+
"Antarctica": ["Antarctica"],
|
|
267
303
|
}
|
|
268
304
|
|
|
269
305
|
# Define approximate geographical boundaries for automatic region detection
|
|
270
306
|
# These bounds help determine which regional KML files to scan based on coordinates
|
|
271
307
|
REGION_BOUNDS = {
|
|
272
|
-
|
|
273
|
-
"
|
|
308
|
+
# WMO Region 1 - Africa (includes islands in Indian Ocean and Spanish territories off N. Africa)
|
|
309
|
+
"Africa": {"lon_min": -25, "lon_max": 80, "lat_min": -55, "lat_max": 45},
|
|
310
|
+
# WMO Region 2 - Asia (includes SE Asia, West Asia, Asian Russia, and BIOT)
|
|
311
|
+
"Asia": {"lon_min": 20, "lon_max": 180, "lat_min": -10, "lat_max": 80},
|
|
312
|
+
# Subsets
|
|
274
313
|
"Japan": {"lon_min": 127, "lon_max": 146, "lat_min": 24, "lat_max": 46},
|
|
275
314
|
"India": {"lon_min": 68, "lon_max": 97, "lat_min": 6, "lat_max": 36},
|
|
315
|
+
# WMO Region 3 - South America (includes Falklands, South Georgia/Sandwich, Galapagos)
|
|
316
|
+
"South_America": {"lon_min": -92, "lon_max": -20, "lat_min": -60, "lat_max": 15},
|
|
317
|
+
# Legacy/compatibility subset
|
|
276
318
|
"Argentina": {"lon_min": -75, "lon_max": -53, "lat_min": -55, "lat_max": -22},
|
|
319
|
+
# WMO Region 4 - North and Central America (includes Greenland and Caribbean)
|
|
320
|
+
"North_and_Central_America": {"lon_min": -180, "lon_max": 20, "lat_min": -10, "lat_max": 85},
|
|
321
|
+
# Backward-compatible subsets mapped to Region 4 KML
|
|
277
322
|
"Canada": {"lon_min": -141, "lon_max": -52, "lat_min": 42, "lat_max": 83},
|
|
278
323
|
"USA": {"lon_min": -170, "lon_max": -65, "lat_min": 20, "lat_max": 72},
|
|
279
324
|
"Caribbean": {"lon_min": -90, "lon_max": -59, "lat_min": 10, "lat_max": 27},
|
|
280
|
-
|
|
281
|
-
"
|
|
325
|
+
# WMO Region 5 - Southwest Pacific (covers SE Asia + Pacific islands + Hawaii via antimeridian)
|
|
326
|
+
"Southwest_Pacific": {
|
|
327
|
+
"boxes": [
|
|
328
|
+
{"lon_min": 90, "lon_max": 180, "lat_min": -50, "lat_max": 25},
|
|
329
|
+
{"lon_min": -180, "lon_max": -140, "lat_min": -50, "lat_max": 25},
|
|
330
|
+
]
|
|
331
|
+
},
|
|
332
|
+
# WMO Region 6 - Europe (includes Middle East countries listed and Greenland)
|
|
333
|
+
"Europe": {"lon_min": -75, "lon_max": 60, "lat_min": 25, "lat_max": 85},
|
|
334
|
+
# WMO Region 7 - Antarctica
|
|
282
335
|
"Antarctica": {"lon_min": -180, "lon_max": 180, "lat_min": -90, "lat_max": -60}
|
|
283
336
|
}
|
|
284
337
|
|
|
@@ -306,34 +359,45 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
306
359
|
elif lon > 180:
|
|
307
360
|
lon_adjusted = lon - 360
|
|
308
361
|
|
|
309
|
-
#
|
|
362
|
+
# Helper to test point within a single box
|
|
363
|
+
def _in_box(bx: Dict[str, float], lon_v: float, lat_v: float) -> bool:
|
|
364
|
+
return (bx["lon_min"] <= lon_v <= bx["lon_max"] and
|
|
365
|
+
bx["lat_min"] <= lat_v <= bx["lat_max"])
|
|
366
|
+
|
|
367
|
+
# Check if coordinates fall within any region bounds (support multi-box)
|
|
310
368
|
for region_name, bounds in REGION_BOUNDS.items():
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
369
|
+
if "boxes" in bounds:
|
|
370
|
+
for bx in bounds["boxes"]:
|
|
371
|
+
if _in_box(bx, lon_adjusted, lat):
|
|
372
|
+
matching_regions.append(region_name)
|
|
373
|
+
break
|
|
374
|
+
else:
|
|
375
|
+
if _in_box(bounds, lon_adjusted, lat):
|
|
376
|
+
matching_regions.append(region_name)
|
|
315
377
|
|
|
316
378
|
# If no regions matched, find the closest regions by boundary distance
|
|
317
379
|
if not matching_regions:
|
|
318
380
|
# Calculate "distance" to each region's boundary (simplified metric)
|
|
319
381
|
region_distances = []
|
|
320
382
|
for region_name, bounds in REGION_BOUNDS.items():
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
383
|
+
def _box_distance(bx: Dict[str, float]) -> float:
|
|
384
|
+
lon_dist = 0
|
|
385
|
+
if lon_adjusted < bx["lon_min"]:
|
|
386
|
+
lon_dist = bx["lon_min"] - lon_adjusted
|
|
387
|
+
elif lon_adjusted > bx["lon_max"]:
|
|
388
|
+
lon_dist = lon_adjusted - bx["lon_max"]
|
|
389
|
+
lat_dist = 0
|
|
390
|
+
if lat < bx["lat_min"]:
|
|
391
|
+
lat_dist = bx["lat_min"] - lat
|
|
392
|
+
elif lat > bx["lat_max"]:
|
|
393
|
+
lat_dist = lat - bx["lat_max"]
|
|
394
|
+
return (lon_dist**2 + lat_dist**2)**0.5
|
|
395
|
+
|
|
396
|
+
if "boxes" in bounds:
|
|
397
|
+
d = min(_box_distance(bx) for bx in bounds["boxes"])
|
|
398
|
+
else:
|
|
399
|
+
d = _box_distance(bounds)
|
|
400
|
+
region_distances.append((region_name, d))
|
|
337
401
|
|
|
338
402
|
# Get 3 closest regions to ensure we find stations
|
|
339
403
|
closest_regions = sorted(region_distances, key=lambda x: x[1])[:3]
|
|
@@ -511,6 +575,74 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
511
575
|
|
|
512
576
|
return metadata
|
|
513
577
|
|
|
578
|
+
def try_download_station_zip(original_url: str, timeout_s: int = 30) -> Optional[bytes]:
|
|
579
|
+
"""
|
|
580
|
+
Try downloading station archive; on 404s, attempt smart fallbacks.
|
|
581
|
+
|
|
582
|
+
Fallback strategies:
|
|
583
|
+
- Country rename: /TUR_Turkey/ -> /TUR_Turkiye/ (per Oct 2024 site update)
|
|
584
|
+
- TMYx period variants: .2009-2023.zip, .2007-2021.zip, .zip, .2004-2018.zip
|
|
585
|
+
|
|
586
|
+
Args:
|
|
587
|
+
original_url: URL extracted from KML
|
|
588
|
+
timeout_s: request timeout seconds
|
|
589
|
+
Returns:
|
|
590
|
+
Bytes of the downloaded zip on success, otherwise None
|
|
591
|
+
"""
|
|
592
|
+
def candidate_urls(url: str) -> List[str]:
|
|
593
|
+
urls = []
|
|
594
|
+
urls.append(url)
|
|
595
|
+
# Country rename variants
|
|
596
|
+
if "/TUR_Turkey/" in url:
|
|
597
|
+
urls.append(url.replace("/TUR_Turkey/", "/TUR_Turkiye/"))
|
|
598
|
+
if "/TUR_Turkiye/" in url:
|
|
599
|
+
urls.append(url.replace("/TUR_Turkiye/", "/TUR_Turkey/"))
|
|
600
|
+
# TMYx period variants
|
|
601
|
+
m = re.search(r"(.*_TMYx)(?:\.(\d{4}-\d{4}))?\.zip$", url)
|
|
602
|
+
if m:
|
|
603
|
+
base = m.group(1)
|
|
604
|
+
suffix = m.group(2)
|
|
605
|
+
variants = [
|
|
606
|
+
f"{base}.2009-2023.zip",
|
|
607
|
+
f"{base}.2007-2021.zip",
|
|
608
|
+
f"{base}.zip",
|
|
609
|
+
f"{base}.2004-2018.zip",
|
|
610
|
+
]
|
|
611
|
+
for v in variants:
|
|
612
|
+
if v not in urls:
|
|
613
|
+
urls.append(v)
|
|
614
|
+
# Also apply country rename to each variant
|
|
615
|
+
extra = []
|
|
616
|
+
for v in variants:
|
|
617
|
+
if "/TUR_Turkey/" in url:
|
|
618
|
+
extra.append(v.replace("/TUR_Turkey/", "/TUR_Turkiye/"))
|
|
619
|
+
if "/TUR_Turkiye/" in url:
|
|
620
|
+
extra.append(v.replace("/TUR_Turkiye/", "/TUR_Turkey/"))
|
|
621
|
+
for v in extra:
|
|
622
|
+
if v not in urls:
|
|
623
|
+
urls.append(v)
|
|
624
|
+
return urls
|
|
625
|
+
|
|
626
|
+
tried = set()
|
|
627
|
+
for u in candidate_urls(original_url):
|
|
628
|
+
if u in tried:
|
|
629
|
+
continue
|
|
630
|
+
tried.add(u)
|
|
631
|
+
try:
|
|
632
|
+
resp = requests.get(u, timeout=timeout_s)
|
|
633
|
+
resp.raise_for_status()
|
|
634
|
+
return resp.content
|
|
635
|
+
except requests.exceptions.HTTPError as he:
|
|
636
|
+
# Only continue on 404; raise on other HTTP errors
|
|
637
|
+
if getattr(he.response, "status_code", None) == 404:
|
|
638
|
+
continue
|
|
639
|
+
else:
|
|
640
|
+
raise
|
|
641
|
+
except requests.exceptions.RequestException:
|
|
642
|
+
# On network errors, try next candidate
|
|
643
|
+
continue
|
|
644
|
+
return None
|
|
645
|
+
|
|
514
646
|
def get_stations_from_kml(kml_url: str) -> List[Dict]:
|
|
515
647
|
"""
|
|
516
648
|
Get weather stations from a KML file.
|
|
@@ -584,6 +716,18 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
584
716
|
|
|
585
717
|
# Determine which regions to scan based on user input or auto-detection
|
|
586
718
|
regions_to_scan = {}
|
|
719
|
+
def _add_selection(selection_name: str, mapping: Dict[str, str], out: Dict[str, str]):
|
|
720
|
+
"""Expand a region or dataset selection into concrete KML URLs."""
|
|
721
|
+
if selection_name in REGION_DATASET_GROUPS:
|
|
722
|
+
for key in REGION_DATASET_GROUPS[selection_name]:
|
|
723
|
+
if key in KML_SOURCES:
|
|
724
|
+
out[key] = KML_SOURCES[key]
|
|
725
|
+
elif selection_name in KML_SOURCES:
|
|
726
|
+
out[selection_name] = KML_SOURCES[selection_name]
|
|
727
|
+
else:
|
|
728
|
+
valid = sorted(list(REGION_DATASET_GROUPS.keys()) + list(KML_SOURCES.keys()))
|
|
729
|
+
raise ValueError(f"Invalid region/dataset: '{selection_name}'. Valid options include: {', '.join(valid)}")
|
|
730
|
+
|
|
587
731
|
if region is None:
|
|
588
732
|
# Auto-detect regions based on coordinates
|
|
589
733
|
detected_regions = detect_regions(longitude, latitude)
|
|
@@ -591,34 +735,32 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
591
735
|
if detected_regions:
|
|
592
736
|
print(f"Auto-detected regions: {', '.join(detected_regions)}")
|
|
593
737
|
for r in detected_regions:
|
|
594
|
-
|
|
738
|
+
_add_selection(r, KML_SOURCES, regions_to_scan)
|
|
595
739
|
else:
|
|
596
740
|
# Fallback to all regions if detection fails
|
|
597
741
|
print("Could not determine region from coordinates. Scanning all regions.")
|
|
598
|
-
regions_to_scan = KML_SOURCES
|
|
742
|
+
regions_to_scan = dict(KML_SOURCES)
|
|
599
743
|
elif isinstance(region, str):
|
|
600
744
|
# Handle string input for region selection
|
|
601
745
|
if region.lower() == "all":
|
|
602
|
-
regions_to_scan = KML_SOURCES
|
|
603
|
-
elif region in KML_SOURCES:
|
|
604
|
-
regions_to_scan[region] = KML_SOURCES[region]
|
|
746
|
+
regions_to_scan = dict(KML_SOURCES)
|
|
605
747
|
else:
|
|
606
|
-
|
|
607
|
-
raise ValueError(f"Invalid region: '{region}'. Valid regions are: {valid_regions}")
|
|
748
|
+
_add_selection(region, KML_SOURCES, regions_to_scan)
|
|
608
749
|
else:
|
|
609
750
|
# Handle list input for multiple regions
|
|
610
751
|
for r in region:
|
|
611
|
-
|
|
612
|
-
valid_regions = ", ".join(KML_SOURCES.keys())
|
|
613
|
-
raise ValueError(f"Invalid region: '{r}'. Valid regions are: {valid_regions}")
|
|
614
|
-
regions_to_scan[r] = KML_SOURCES[r]
|
|
752
|
+
_add_selection(r, KML_SOURCES, regions_to_scan)
|
|
615
753
|
|
|
616
754
|
# Get stations from selected KML sources
|
|
617
755
|
print("Fetching weather station data from Climate.OneBuilding.Org...")
|
|
618
756
|
all_stations = []
|
|
619
757
|
|
|
620
758
|
# Process each selected region
|
|
759
|
+
scanned_urls = set()
|
|
621
760
|
for region_name, url in regions_to_scan.items():
|
|
761
|
+
if url in scanned_urls:
|
|
762
|
+
continue
|
|
763
|
+
scanned_urls.add(url)
|
|
622
764
|
print(f"Scanning {region_name}...")
|
|
623
765
|
stations = get_stations_from_kml(url)
|
|
624
766
|
all_stations.extend(stations)
|
|
@@ -627,7 +769,23 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
627
769
|
print(f"\nTotal stations found: {len(all_stations)}")
|
|
628
770
|
|
|
629
771
|
if not all_stations:
|
|
630
|
-
|
|
772
|
+
# Fallback: if no stations found, try scanning all available datasets
|
|
773
|
+
if not (isinstance(region, str) and region.lower() == "all"):
|
|
774
|
+
print("No stations found from detected/selected regions. Falling back to global scan...")
|
|
775
|
+
regions_to_scan = dict(KML_SOURCES)
|
|
776
|
+
all_stations = []
|
|
777
|
+
scanned_urls = set()
|
|
778
|
+
for region_name, url in regions_to_scan.items():
|
|
779
|
+
if url in scanned_urls:
|
|
780
|
+
continue
|
|
781
|
+
scanned_urls.add(url)
|
|
782
|
+
print(f"Scanning {region_name}...")
|
|
783
|
+
stations = get_stations_from_kml(url)
|
|
784
|
+
all_stations.extend(stations)
|
|
785
|
+
print(f"Found {len(stations)} stations in {region_name}")
|
|
786
|
+
print(f"\nTotal stations found after global scan: {len(all_stations)}")
|
|
787
|
+
if not all_stations:
|
|
788
|
+
raise ValueError("No weather stations found")
|
|
631
789
|
|
|
632
790
|
# Calculate distances from target coordinates to all stations
|
|
633
791
|
stations_with_distances = [
|
|
@@ -654,10 +812,11 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
654
812
|
# Find the nearest weather station
|
|
655
813
|
nearest_station, distance = min(stations_with_distances, key=lambda x: x[1])
|
|
656
814
|
|
|
657
|
-
# Download the EPW
|
|
815
|
+
# Download the EPW archive from the nearest station with fallbacks
|
|
658
816
|
print(f"\nDownloading EPW file for {nearest_station['name']}...")
|
|
659
|
-
|
|
660
|
-
|
|
817
|
+
archive_bytes = try_download_station_zip(nearest_station['url'], timeout_s=30)
|
|
818
|
+
if archive_bytes is None:
|
|
819
|
+
raise ValueError(f"Failed to download EPW archive from station URL and fallbacks: {nearest_station['url']}")
|
|
661
820
|
|
|
662
821
|
# Create a temporary directory for zip extraction
|
|
663
822
|
temp_dir = Path(output_dir) / "temp"
|
|
@@ -666,7 +825,7 @@ def get_nearest_epw_from_climate_onebuilding(longitude: float, latitude: float,
|
|
|
666
825
|
# Save the downloaded zip file temporarily
|
|
667
826
|
zip_file = temp_dir / "weather_data.zip"
|
|
668
827
|
with open(zip_file, 'wb') as f:
|
|
669
|
-
f.write(
|
|
828
|
+
f.write(archive_bytes)
|
|
670
829
|
|
|
671
830
|
final_epw = None
|
|
672
831
|
try:
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: voxcity
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.19
|
|
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
|
+
License-File: AUTHORS.rst
|
|
7
|
+
License-File: LICENSE
|
|
6
8
|
Author: Kunihiko Fujiwara
|
|
7
9
|
Author-email: fujiwara.kunihiko@takenaka.co.jp
|
|
8
10
|
Maintainer: Kunihiko Fujiwara
|
|
@@ -13,7 +13,7 @@ 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=
|
|
16
|
+
voxcity/exporter/obj.py,sha256=7xmVSQ_y-X8QLjNdASDPsaltGvmyW9-yAacocByYKl4,58160
|
|
17
17
|
voxcity/generator.py,sha256=4WSjO09f8z3zt0tpKY0fyAfOMym1JT4VH3Tt1lOg2Bk,66900
|
|
18
18
|
voxcity/geoprocessor/__init__.py,sha256=WYxcAQrjGucIvGHF0JTC6rONZzL3kCms1S2vpzS6KaU,127
|
|
19
19
|
voxcity/geoprocessor/draw.py,sha256=AZMWq23wxxDJygNloCbVzWAAr1JO7nC94umf9LSxJ5o,49248
|
|
@@ -30,9 +30,9 @@ 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
32
|
voxcity/utils/visualization.py,sha256=_c5WnhA0fawkseUviKEIpUUsF-M-OOLOT9FrpgQIh1A,118556
|
|
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.
|
|
33
|
+
voxcity/utils/weather.py,sha256=WcmohW0yx2-uNMO5ffgxCtKUt32q6PQsAT43P5DwJx4,44760
|
|
34
|
+
voxcity-0.6.19.dist-info/licenses/AUTHORS.rst,sha256=m82vkI5QokEGdcHof2OxK39lf81w1P58kG9ZNNAKS9U,175
|
|
35
|
+
voxcity-0.6.19.dist-info/licenses/LICENSE,sha256=s_jE1Df1nTPL4A_5GCGic5Zwex0CVaPKcAmSilxJPPE,1089
|
|
36
|
+
voxcity-0.6.19.dist-info/METADATA,sha256=AUmkbdSOZM7RywhizzSM_xzphJ-QLbQEuHx9IjvGSKQ,26212
|
|
37
|
+
voxcity-0.6.19.dist-info/WHEEL,sha256=M5asmiAlL6HEcOq52Yi5mmk9KmTVjY2RDPtO4p9DMrc,88
|
|
38
|
+
voxcity-0.6.19.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|