buildstock-fetch 1.1.0__py3-none-any.whl → 1.2.0__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 buildstock-fetch might be problematic. Click here for more details.
- buildstock_fetch/data/buildstock_releases.json +166 -77
- buildstock_fetch/data/weather_station_map/weather_station_map.parquet +0 -0
- buildstock_fetch/main.py +458 -99
- buildstock_fetch/main_cli.py +166 -58
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.2.0.dist-info}/METADATA +1 -1
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.2.0.dist-info}/RECORD +10 -10
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.2.0.dist-info}/WHEEL +0 -0
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.2.0.dist-info}/entry_points.txt +0 -0
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.2.0.dist-info}/top_level.txt +0 -0
buildstock_fetch/main_cli.py
CHANGED
|
@@ -28,6 +28,9 @@ app = typer.Typer(
|
|
|
28
28
|
# File configuration
|
|
29
29
|
BUILDSTOCK_RELEASES_FILE = str(files("buildstock_fetch").joinpath("data").joinpath("buildstock_releases.json"))
|
|
30
30
|
|
|
31
|
+
# File types that haven't been implemented yet
|
|
32
|
+
UNAVAILABLE_FILE_TYPES = ["load_curve_hourly", "load_curve_daily"]
|
|
33
|
+
|
|
31
34
|
|
|
32
35
|
class InvalidProductError(Exception):
|
|
33
36
|
"""Exception raised when an invalid product is provided."""
|
|
@@ -222,6 +225,7 @@ def _get_file_type_options_grouped(release_name: str) -> list[dict]:
|
|
|
222
225
|
"load_curve_annual",
|
|
223
226
|
],
|
|
224
227
|
"Metadata": ["metadata"],
|
|
228
|
+
"Weather": ["weather"],
|
|
225
229
|
}
|
|
226
230
|
|
|
227
231
|
choices = []
|
|
@@ -431,18 +435,80 @@ def _print_data_processing_info(inputs: Mapping[str, Union[str, list[str]]]) ->
|
|
|
431
435
|
print(f"Output directory: {inputs['output_directory']}")
|
|
432
436
|
|
|
433
437
|
|
|
434
|
-
def
|
|
435
|
-
"""Check
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
438
|
+
def _check_weather_map_available_states(inputs: Mapping[str, Union[str, list[str]]]) -> tuple[list[str], list[str]]:
|
|
439
|
+
"""Check if the weather map is available for the given release and state."""
|
|
440
|
+
available_states: list[str] = []
|
|
441
|
+
unavailable_states: list[str] = []
|
|
442
|
+
product_short_name = "res" if inputs["product"] == "resstock" else "com"
|
|
443
|
+
release_name = f"{product_short_name}_{inputs['release_year']}_{inputs['weather_file']}_{inputs['release_version']}"
|
|
444
|
+
selected_release = _get_all_available_releases()[release_name]
|
|
445
|
+
if "weather_map_available_states" not in selected_release:
|
|
446
|
+
unavailable_states = inputs["states"] if isinstance(inputs["states"], list) else [inputs["states"]]
|
|
447
|
+
else:
|
|
448
|
+
unavailable_states = [
|
|
449
|
+
state for state in inputs["states"] if state not in selected_release["weather_map_available_states"]
|
|
450
|
+
]
|
|
451
|
+
available_states = [
|
|
452
|
+
state for state in inputs["states"] if state in selected_release["weather_map_available_states"]
|
|
453
|
+
]
|
|
454
|
+
return available_states, unavailable_states
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def _check_weather_file_availability(
|
|
458
|
+
inputs: Mapping[str, Union[str, list[str]]],
|
|
459
|
+
available_file_types: list[str],
|
|
460
|
+
selected_unavailable_file_types: list[str],
|
|
461
|
+
) -> None:
|
|
462
|
+
"""Check weather file availability and update file type lists."""
|
|
463
|
+
available_states, unavailable_states = _check_weather_map_available_states(inputs)
|
|
464
|
+
|
|
465
|
+
if len(unavailable_states) > 0:
|
|
466
|
+
selected_unavailable_file_types.append("weather")
|
|
467
|
+
if len(unavailable_states) == len(inputs["states"]) and "weather" in available_file_types:
|
|
468
|
+
available_file_types.remove("weather")
|
|
469
|
+
|
|
470
|
+
if len(unavailable_states) > 0:
|
|
471
|
+
console.print(
|
|
472
|
+
f"\n[yellow]The weather map is not available for the following states: {unavailable_states}[/yellow]"
|
|
473
|
+
)
|
|
474
|
+
console.print(
|
|
475
|
+
"\n[yellow]Please first build the weather station mapping for this state using the weather station mapping CLI tool (just build-weather-station-map)[/yellow]"
|
|
476
|
+
)
|
|
477
|
+
for state in unavailable_states:
|
|
478
|
+
selected_unavailable_file_types.append(f"weather: {state}")
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
def _print_unavailable_file_types_warning(selected_unavailable_file_types: list[str]) -> None:
|
|
482
|
+
"""Print warning for unavailable file types."""
|
|
483
|
+
if selected_unavailable_file_types:
|
|
440
484
|
console.print("\n[yellow]The following file types are not available yet:[/yellow]")
|
|
441
|
-
for file_type in
|
|
485
|
+
for file_type in selected_unavailable_file_types:
|
|
442
486
|
console.print(f" • {file_type}")
|
|
443
487
|
console.print("")
|
|
444
488
|
|
|
445
489
|
|
|
490
|
+
def _check_unavailable_file_types(inputs: Mapping[str, Union[str, list[str]]]) -> tuple[list[str], list[str]]:
|
|
491
|
+
"""Check and print warning for unavailable file types."""
|
|
492
|
+
selected_file_types = inputs["file_type"].split() if isinstance(inputs["file_type"], str) else inputs["file_type"]
|
|
493
|
+
# Create a copy to avoid modifying the original list
|
|
494
|
+
available_file_types = selected_file_types.copy()
|
|
495
|
+
selected_unavailable_file_types = []
|
|
496
|
+
|
|
497
|
+
for ft in selected_file_types:
|
|
498
|
+
if ft in UNAVAILABLE_FILE_TYPES:
|
|
499
|
+
selected_unavailable_file_types.append(ft)
|
|
500
|
+
# Only remove if it exists in available_file_types
|
|
501
|
+
if ft in available_file_types:
|
|
502
|
+
available_file_types.remove(ft)
|
|
503
|
+
|
|
504
|
+
if "weather" in selected_file_types:
|
|
505
|
+
_check_weather_file_availability(inputs, available_file_types, selected_unavailable_file_types)
|
|
506
|
+
|
|
507
|
+
_print_unavailable_file_types_warning(selected_unavailable_file_types)
|
|
508
|
+
|
|
509
|
+
return available_file_types, selected_unavailable_file_types
|
|
510
|
+
|
|
511
|
+
|
|
446
512
|
def _fetch_all_building_ids(inputs: Mapping[str, Union[str, list[str]]]) -> list:
|
|
447
513
|
"""Fetch building IDs for all states and upgrade IDs."""
|
|
448
514
|
bldg_ids = []
|
|
@@ -643,6 +709,94 @@ UPGRADE_ID_OPTION = typer.Option(
|
|
|
643
709
|
OUTPUT_DIRECTORY_OPTION = typer.Option(None, "--output_directory", "-o", help='e.g., "data" or "../output"')
|
|
644
710
|
|
|
645
711
|
|
|
712
|
+
def _run_interactive_mode_wrapper() -> dict[str, Union[str, list[str]]]:
|
|
713
|
+
"""Run interactive mode with error handling."""
|
|
714
|
+
try:
|
|
715
|
+
while True:
|
|
716
|
+
inputs = _run_interactive_mode()
|
|
717
|
+
if _verify_interactive_inputs(inputs):
|
|
718
|
+
return inputs
|
|
719
|
+
console.print("[yellow]Let's try again...[/yellow]")
|
|
720
|
+
except KeyboardInterrupt:
|
|
721
|
+
console.print("\n[red]Operation cancelled by user.[/red]")
|
|
722
|
+
raise typer.Exit(0) from None
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
def _process_direct_inputs(
|
|
726
|
+
product: str,
|
|
727
|
+
release_year: str,
|
|
728
|
+
weather_file: str,
|
|
729
|
+
release_version: float,
|
|
730
|
+
states: str,
|
|
731
|
+
file_type: str,
|
|
732
|
+
upgrade_id: str,
|
|
733
|
+
output_directory: str,
|
|
734
|
+
) -> dict[str, Union[str, list[str]]]:
|
|
735
|
+
"""Process direct command line inputs."""
|
|
736
|
+
states_list = states.split() if states else []
|
|
737
|
+
upgrade_ids_list = upgrade_id.split() if upgrade_id else ["0"]
|
|
738
|
+
file_type_list = file_type.split() if file_type else []
|
|
739
|
+
|
|
740
|
+
direct_inputs: dict[str, Union[str, list[str]]] = {
|
|
741
|
+
"product": product,
|
|
742
|
+
"release_year": release_year,
|
|
743
|
+
"weather_file": weather_file,
|
|
744
|
+
"release_version": _normalize_release_version(release_version),
|
|
745
|
+
"states": states_list,
|
|
746
|
+
"file_type": file_type_list,
|
|
747
|
+
"upgrade_ids": upgrade_ids_list,
|
|
748
|
+
"output_directory": output_directory,
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
try:
|
|
752
|
+
validation_result = _validate_direct_inputs(direct_inputs)
|
|
753
|
+
if validation_result is not True:
|
|
754
|
+
console.print(f"\n[red]{validation_result}[/red]")
|
|
755
|
+
raise typer.Exit(1) from None
|
|
756
|
+
except InvalidProductError:
|
|
757
|
+
console.print(f"\n[red]Invalid product: {direct_inputs['product']}[/red]")
|
|
758
|
+
raise typer.Exit(1) from None
|
|
759
|
+
|
|
760
|
+
return direct_inputs
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
def _process_data_download(inputs: dict[str, Union[str, list[str]]]) -> None:
|
|
764
|
+
"""Process data download based on available file types."""
|
|
765
|
+
available_file_types, unavailable_file_types = _check_unavailable_file_types(inputs)
|
|
766
|
+
if "weather" in inputs["file_type"]:
|
|
767
|
+
available_weather_states, unavailable_weather_states = _check_weather_map_available_states(inputs)
|
|
768
|
+
else:
|
|
769
|
+
available_weather_states = None
|
|
770
|
+
|
|
771
|
+
if len(available_file_types) > 0:
|
|
772
|
+
# Fetch the building ids and download data
|
|
773
|
+
bldg_ids = _fetch_all_building_ids(inputs)
|
|
774
|
+
|
|
775
|
+
# Ask user about download choice
|
|
776
|
+
selected_bldg_ids = _get_user_download_choice(bldg_ids)
|
|
777
|
+
|
|
778
|
+
if selected_bldg_ids:
|
|
779
|
+
file_type_tuple = (
|
|
780
|
+
tuple(inputs["file_type"].split())
|
|
781
|
+
if isinstance(inputs["file_type"], str)
|
|
782
|
+
else tuple(inputs["file_type"])
|
|
783
|
+
)
|
|
784
|
+
output_dir = inputs["output_directory"]
|
|
785
|
+
if isinstance(output_dir, list):
|
|
786
|
+
output_dir = output_dir[0] if output_dir else "."
|
|
787
|
+
|
|
788
|
+
print(selected_bldg_ids)
|
|
789
|
+
print(available_weather_states)
|
|
790
|
+
print(file_type_tuple)
|
|
791
|
+
fetch_bldg_data(
|
|
792
|
+
selected_bldg_ids, file_type_tuple, Path(output_dir), weather_states=available_weather_states
|
|
793
|
+
)
|
|
794
|
+
else:
|
|
795
|
+
console.print("[yellow]No files selected for download.[/yellow]")
|
|
796
|
+
else:
|
|
797
|
+
console.print("[yellow]None of the selected file types are available for download.[/yellow]")
|
|
798
|
+
|
|
799
|
+
|
|
646
800
|
def main_callback(
|
|
647
801
|
product: str = PRODUCT_OPTION,
|
|
648
802
|
release_year: str = RELEASE_YEAR_OPTION,
|
|
@@ -659,61 +813,15 @@ def main_callback(
|
|
|
659
813
|
|
|
660
814
|
# If no arguments provided, run interactive mode
|
|
661
815
|
if not any([product, release_year, weather_file, release_version, states, file_type]):
|
|
662
|
-
|
|
663
|
-
while True:
|
|
664
|
-
inputs = _run_interactive_mode()
|
|
665
|
-
if _verify_interactive_inputs(inputs):
|
|
666
|
-
break
|
|
667
|
-
console.print("[yellow]Let's try again...[/yellow]")
|
|
668
|
-
except KeyboardInterrupt:
|
|
669
|
-
console.print("\n[red]Operation cancelled by user.[/red]")
|
|
670
|
-
raise typer.Exit(0) from None
|
|
816
|
+
inputs = _run_interactive_mode_wrapper()
|
|
671
817
|
else:
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
direct_inputs: dict[str, Union[str, list[str]]] = {
|
|
677
|
-
"product": product,
|
|
678
|
-
"release_year": release_year,
|
|
679
|
-
"weather_file": weather_file,
|
|
680
|
-
"release_version": _normalize_release_version(release_version),
|
|
681
|
-
"states": states_list,
|
|
682
|
-
"file_type": file_type_list,
|
|
683
|
-
"upgrade_ids": upgrade_ids_list,
|
|
684
|
-
"output_directory": output_directory,
|
|
685
|
-
}
|
|
686
|
-
try:
|
|
687
|
-
validation_result = _validate_direct_inputs(direct_inputs)
|
|
688
|
-
if validation_result is not True:
|
|
689
|
-
console.print(f"\n[red]{validation_result}[/red]")
|
|
690
|
-
raise typer.Exit(1) from None
|
|
691
|
-
except InvalidProductError:
|
|
692
|
-
console.print(f"\n[red]Invalid product: {direct_inputs['product']}[/red]")
|
|
693
|
-
raise typer.Exit(1) from None
|
|
694
|
-
|
|
695
|
-
inputs = direct_inputs
|
|
818
|
+
inputs = _process_direct_inputs(
|
|
819
|
+
product, release_year, weather_file, release_version, states, file_type, upgrade_id, output_directory
|
|
820
|
+
)
|
|
696
821
|
|
|
697
822
|
# Process the data
|
|
698
823
|
_print_data_processing_info(inputs)
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
# Fetch the building ids and download data
|
|
702
|
-
bldg_ids = _fetch_all_building_ids(inputs)
|
|
703
|
-
|
|
704
|
-
# Ask user about download choice
|
|
705
|
-
selected_bldg_ids = _get_user_download_choice(bldg_ids)
|
|
706
|
-
|
|
707
|
-
if selected_bldg_ids:
|
|
708
|
-
file_type_tuple = (
|
|
709
|
-
tuple(inputs["file_type"].split()) if isinstance(inputs["file_type"], str) else tuple(inputs["file_type"])
|
|
710
|
-
)
|
|
711
|
-
output_dir = inputs["output_directory"]
|
|
712
|
-
if isinstance(output_dir, list):
|
|
713
|
-
output_dir = output_dir[0] if output_dir else "."
|
|
714
|
-
fetch_bldg_data(selected_bldg_ids, file_type_tuple, Path(output_dir))
|
|
715
|
-
else:
|
|
716
|
-
console.print("[yellow]No files selected for download.[/yellow]")
|
|
824
|
+
_process_data_download(inputs)
|
|
717
825
|
|
|
718
826
|
|
|
719
827
|
app.command()(main_callback)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: buildstock-fetch
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: This library simplifies downloading building characteristics and load curve data from NREL's ResStock and ComStock projects.
|
|
5
5
|
Author-email: Switchbox <hello@switch.box>
|
|
6
6
|
Project-URL: Homepage, https://switchbox-data.github.io/buildstock-fetch/
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
buildstock_fetch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
buildstock_fetch/__main__.py,sha256=wEPNJ-s7F6KcRQ_4B5Xh08uqvYZHno5F2R8DU0BMBtk,80
|
|
3
|
-
buildstock_fetch/main.py,sha256=
|
|
4
|
-
buildstock_fetch/main_cli.py,sha256=
|
|
5
|
-
buildstock_fetch/data/buildstock_releases.json,sha256=
|
|
3
|
+
buildstock_fetch/main.py,sha256=J3C44xYW1MVe9CAtcJfyNwDeoJJ-XNRFVv7lAcmxH-0,72445
|
|
4
|
+
buildstock_fetch/main_cli.py,sha256=Qg2cXRuzMpMpm-eH567UrEY3HIoLYQtSLRWDYMNr6Y0,31813
|
|
5
|
+
buildstock_fetch/data/buildstock_releases.json,sha256=rHbNkWtTi6VXFim7xtvhwFWQUvtqvcbCfjtvRjkWV-4,10853
|
|
6
6
|
buildstock_fetch/data/building_data/combined_metadata.parquet/product=comstock/release_year=2021/weather_file=amy2018/release_version=1/state=AK/d1454abff0d94c8090af7b3e923c473b-0.parquet,sha256=nG6H3oGyDzPk1B15YmFd_U81PsA14uABqqwK7P30nKE,7059
|
|
7
7
|
buildstock_fetch/data/building_data/combined_metadata.parquet/product=comstock/release_year=2021/weather_file=amy2018/release_version=1/state=AK/dcd864cc169b4695be2b9775b1a054ae-0.parquet,sha256=fsREWV9g4fsA3cIWqyPnXVwd7FsJxED2btYpmyOvnbQ,7163
|
|
8
8
|
buildstock_fetch/data/building_data/combined_metadata.parquet/product=comstock/release_year=2021/weather_file=amy2018/release_version=1/state=AL/d1454abff0d94c8090af7b3e923c473b-0.parquet,sha256=jiTG48ly-LZwfwAL3THdfRzHDG1qEogoxO7P78U4WOU,41201
|
|
@@ -1599,10 +1599,10 @@ buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/r
|
|
|
1599
1599
|
buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/release_year=2024/weather_file=tmy3/release_version=2/state=WV/dcd864cc169b4695be2b9775b1a054ae-0.parquet,sha256=-taHsRgrCKXW_7QKoD8QwFBnavXSsSNc6ok3DHqZOXE,42818
|
|
1600
1600
|
buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/release_year=2024/weather_file=tmy3/release_version=2/state=WY/d1454abff0d94c8090af7b3e923c473b-0.parquet,sha256=bWuUnd02XJXYXkHqiXQuIidtm1be5yHmrz1-iFZ14ao,22304
|
|
1601
1601
|
buildstock_fetch/data/building_data/combined_metadata.parquet/product=resstock/release_year=2024/weather_file=tmy3/release_version=2/state=WY/dcd864cc169b4695be2b9775b1a054ae-0.parquet,sha256=EC1DGLtXqwF1slnnbuTJyQZF0Ox5hoDRDxgaF_SpN8g,21727
|
|
1602
|
-
buildstock_fetch/data/weather_station_map/weather_station_map.parquet,sha256=
|
|
1603
|
-
buildstock_fetch-1.
|
|
1604
|
-
buildstock_fetch-1.
|
|
1605
|
-
buildstock_fetch-1.
|
|
1606
|
-
buildstock_fetch-1.
|
|
1607
|
-
buildstock_fetch-1.
|
|
1608
|
-
buildstock_fetch-1.
|
|
1602
|
+
buildstock_fetch/data/weather_station_map/weather_station_map.parquet,sha256=igNrx-UGH20CqPcjANTDrrMyj6Z4_JcXIg2aaCNhFRg,346990
|
|
1603
|
+
buildstock_fetch-1.2.0.dist-info/licenses/LICENSE,sha256=TJeh2yvO8__8Rbamd8r48-zvlFCINAsu9nOo5QdMRX8,1066
|
|
1604
|
+
buildstock_fetch-1.2.0.dist-info/METADATA,sha256=6Px9cA0FJ9O16wBWSUQ9EKEDXNVG3tuMd-uMhaJmOv4,7607
|
|
1605
|
+
buildstock_fetch-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1606
|
+
buildstock_fetch-1.2.0.dist-info/entry_points.txt,sha256=C7zPk3BSLcI47ymvYKI05nvfRJMEXz4BPIIDKsjePn8,54
|
|
1607
|
+
buildstock_fetch-1.2.0.dist-info/top_level.txt,sha256=-PGb2C-Tb3O-wPqUHSOBrvJqRzNHgY_KTbTsXaHIo5M,17
|
|
1608
|
+
buildstock_fetch-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|