buildstock-fetch 1.1.0__py3-none-any.whl → 1.3.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 +503 -115
- buildstock_fetch/main_cli.py +171 -58
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.3.0.dist-info}/METADATA +1 -1
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.3.0.dist-info}/RECORD +10 -10
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.3.0.dist-info}/WHEEL +0 -0
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.3.0.dist-info}/entry_points.txt +0 -0
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {buildstock_fetch-1.1.0.dist-info → buildstock_fetch-1.3.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_daily"]
|
|
33
|
+
|
|
31
34
|
|
|
32
35
|
class InvalidProductError(Exception):
|
|
33
36
|
"""Exception raised when an invalid product is provided."""
|
|
@@ -122,6 +125,14 @@ def _get_release_versions_options(
|
|
|
122
125
|
)
|
|
123
126
|
available_release_versions = list({parsed_releases[release]["release_version"] for release in available_releases})
|
|
124
127
|
|
|
128
|
+
if (
|
|
129
|
+
product_type == "resstock"
|
|
130
|
+
and weather_file == "tmy3"
|
|
131
|
+
and release_year == "2024"
|
|
132
|
+
and "1" in available_release_versions
|
|
133
|
+
):
|
|
134
|
+
available_release_versions.remove("1")
|
|
135
|
+
|
|
125
136
|
# Define the desired order: "2", "1.1", "1"
|
|
126
137
|
display_order = ["2", "1.1", "1"]
|
|
127
138
|
|
|
@@ -222,6 +233,7 @@ def _get_file_type_options_grouped(release_name: str) -> list[dict]:
|
|
|
222
233
|
"load_curve_annual",
|
|
223
234
|
],
|
|
224
235
|
"Metadata": ["metadata"],
|
|
236
|
+
"Weather": ["weather"],
|
|
225
237
|
}
|
|
226
238
|
|
|
227
239
|
choices = []
|
|
@@ -431,18 +443,80 @@ def _print_data_processing_info(inputs: Mapping[str, Union[str, list[str]]]) ->
|
|
|
431
443
|
print(f"Output directory: {inputs['output_directory']}")
|
|
432
444
|
|
|
433
445
|
|
|
434
|
-
def
|
|
435
|
-
"""Check
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
446
|
+
def _check_weather_map_available_states(inputs: Mapping[str, Union[str, list[str]]]) -> tuple[list[str], list[str]]:
|
|
447
|
+
"""Check if the weather map is available for the given release and state."""
|
|
448
|
+
available_states: list[str] = []
|
|
449
|
+
unavailable_states: list[str] = []
|
|
450
|
+
product_short_name = "res" if inputs["product"] == "resstock" else "com"
|
|
451
|
+
release_name = f"{product_short_name}_{inputs['release_year']}_{inputs['weather_file']}_{inputs['release_version']}"
|
|
452
|
+
selected_release = _get_all_available_releases()[release_name]
|
|
453
|
+
if "weather_map_available_states" not in selected_release:
|
|
454
|
+
unavailable_states = inputs["states"] if isinstance(inputs["states"], list) else [inputs["states"]]
|
|
455
|
+
else:
|
|
456
|
+
unavailable_states = [
|
|
457
|
+
state for state in inputs["states"] if state not in selected_release["weather_map_available_states"]
|
|
458
|
+
]
|
|
459
|
+
available_states = [
|
|
460
|
+
state for state in inputs["states"] if state in selected_release["weather_map_available_states"]
|
|
461
|
+
]
|
|
462
|
+
return available_states, unavailable_states
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def _check_weather_file_availability(
|
|
466
|
+
inputs: Mapping[str, Union[str, list[str]]],
|
|
467
|
+
available_file_types: list[str],
|
|
468
|
+
selected_unavailable_file_types: list[str],
|
|
469
|
+
) -> None:
|
|
470
|
+
"""Check weather file availability and update file type lists."""
|
|
471
|
+
available_states, unavailable_states = _check_weather_map_available_states(inputs)
|
|
472
|
+
|
|
473
|
+
if len(unavailable_states) > 0:
|
|
474
|
+
selected_unavailable_file_types.append("weather")
|
|
475
|
+
if len(unavailable_states) == len(inputs["states"]) and "weather" in available_file_types:
|
|
476
|
+
available_file_types.remove("weather")
|
|
477
|
+
|
|
478
|
+
if len(unavailable_states) > 0:
|
|
479
|
+
console.print(
|
|
480
|
+
f"\n[yellow]The weather map is not available for the following states: {unavailable_states}[/yellow]"
|
|
481
|
+
)
|
|
482
|
+
console.print(
|
|
483
|
+
"\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]"
|
|
484
|
+
)
|
|
485
|
+
for state in unavailable_states:
|
|
486
|
+
selected_unavailable_file_types.append(f"weather: {state}")
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def _print_unavailable_file_types_warning(selected_unavailable_file_types: list[str]) -> None:
|
|
490
|
+
"""Print warning for unavailable file types."""
|
|
491
|
+
if selected_unavailable_file_types:
|
|
440
492
|
console.print("\n[yellow]The following file types are not available yet:[/yellow]")
|
|
441
|
-
for file_type in
|
|
493
|
+
for file_type in selected_unavailable_file_types:
|
|
442
494
|
console.print(f" • {file_type}")
|
|
443
495
|
console.print("")
|
|
444
496
|
|
|
445
497
|
|
|
498
|
+
def _check_unavailable_file_types(inputs: Mapping[str, Union[str, list[str]]]) -> tuple[list[str], list[str]]:
|
|
499
|
+
"""Check and print warning for unavailable file types."""
|
|
500
|
+
selected_file_types = inputs["file_type"].split() if isinstance(inputs["file_type"], str) else inputs["file_type"]
|
|
501
|
+
# Create a copy to avoid modifying the original list
|
|
502
|
+
available_file_types = selected_file_types.copy()
|
|
503
|
+
selected_unavailable_file_types = []
|
|
504
|
+
|
|
505
|
+
for ft in selected_file_types:
|
|
506
|
+
if ft in UNAVAILABLE_FILE_TYPES:
|
|
507
|
+
selected_unavailable_file_types.append(ft)
|
|
508
|
+
# Only remove if it exists in available_file_types
|
|
509
|
+
if ft in available_file_types:
|
|
510
|
+
available_file_types.remove(ft)
|
|
511
|
+
|
|
512
|
+
if "weather" in selected_file_types:
|
|
513
|
+
_check_weather_file_availability(inputs, available_file_types, selected_unavailable_file_types)
|
|
514
|
+
|
|
515
|
+
_print_unavailable_file_types_warning(selected_unavailable_file_types)
|
|
516
|
+
|
|
517
|
+
return available_file_types, selected_unavailable_file_types
|
|
518
|
+
|
|
519
|
+
|
|
446
520
|
def _fetch_all_building_ids(inputs: Mapping[str, Union[str, list[str]]]) -> list:
|
|
447
521
|
"""Fetch building IDs for all states and upgrade IDs."""
|
|
448
522
|
bldg_ids = []
|
|
@@ -643,6 +717,91 @@ UPGRADE_ID_OPTION = typer.Option(
|
|
|
643
717
|
OUTPUT_DIRECTORY_OPTION = typer.Option(None, "--output_directory", "-o", help='e.g., "data" or "../output"')
|
|
644
718
|
|
|
645
719
|
|
|
720
|
+
def _run_interactive_mode_wrapper() -> dict[str, Union[str, list[str]]]:
|
|
721
|
+
"""Run interactive mode with error handling."""
|
|
722
|
+
try:
|
|
723
|
+
while True:
|
|
724
|
+
inputs = _run_interactive_mode()
|
|
725
|
+
if _verify_interactive_inputs(inputs):
|
|
726
|
+
return inputs
|
|
727
|
+
console.print("[yellow]Let's try again...[/yellow]")
|
|
728
|
+
except KeyboardInterrupt:
|
|
729
|
+
console.print("\n[red]Operation cancelled by user.[/red]")
|
|
730
|
+
raise typer.Exit(0) from None
|
|
731
|
+
|
|
732
|
+
|
|
733
|
+
def _process_direct_inputs(
|
|
734
|
+
product: str,
|
|
735
|
+
release_year: str,
|
|
736
|
+
weather_file: str,
|
|
737
|
+
release_version: float,
|
|
738
|
+
states: str,
|
|
739
|
+
file_type: str,
|
|
740
|
+
upgrade_id: str,
|
|
741
|
+
output_directory: str,
|
|
742
|
+
) -> dict[str, Union[str, list[str]]]:
|
|
743
|
+
"""Process direct command line inputs."""
|
|
744
|
+
states_list = states.split() if states else []
|
|
745
|
+
upgrade_ids_list = upgrade_id.split() if upgrade_id else ["0"]
|
|
746
|
+
file_type_list = file_type.split() if file_type else []
|
|
747
|
+
|
|
748
|
+
direct_inputs: dict[str, Union[str, list[str]]] = {
|
|
749
|
+
"product": product,
|
|
750
|
+
"release_year": release_year,
|
|
751
|
+
"weather_file": weather_file,
|
|
752
|
+
"release_version": _normalize_release_version(release_version),
|
|
753
|
+
"states": states_list,
|
|
754
|
+
"file_type": file_type_list,
|
|
755
|
+
"upgrade_ids": upgrade_ids_list,
|
|
756
|
+
"output_directory": output_directory,
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
try:
|
|
760
|
+
validation_result = _validate_direct_inputs(direct_inputs)
|
|
761
|
+
if validation_result is not True:
|
|
762
|
+
console.print(f"\n[red]{validation_result}[/red]")
|
|
763
|
+
raise typer.Exit(1) from None
|
|
764
|
+
except InvalidProductError:
|
|
765
|
+
console.print(f"\n[red]Invalid product: {direct_inputs['product']}[/red]")
|
|
766
|
+
raise typer.Exit(1) from None
|
|
767
|
+
|
|
768
|
+
return direct_inputs
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
def _process_data_download(inputs: dict[str, Union[str, list[str]]]) -> None:
|
|
772
|
+
"""Process data download based on available file types."""
|
|
773
|
+
available_file_types, unavailable_file_types = _check_unavailable_file_types(inputs)
|
|
774
|
+
if "weather" in inputs["file_type"]:
|
|
775
|
+
available_weather_states, unavailable_weather_states = _check_weather_map_available_states(inputs)
|
|
776
|
+
else:
|
|
777
|
+
available_weather_states = None
|
|
778
|
+
|
|
779
|
+
if len(available_file_types) > 0:
|
|
780
|
+
# Fetch the building ids and download data
|
|
781
|
+
bldg_ids = _fetch_all_building_ids(inputs)
|
|
782
|
+
|
|
783
|
+
# Ask user about download choice
|
|
784
|
+
selected_bldg_ids = _get_user_download_choice(bldg_ids)
|
|
785
|
+
|
|
786
|
+
if selected_bldg_ids:
|
|
787
|
+
file_type_tuple = (
|
|
788
|
+
tuple(inputs["file_type"].split())
|
|
789
|
+
if isinstance(inputs["file_type"], str)
|
|
790
|
+
else tuple(inputs["file_type"])
|
|
791
|
+
)
|
|
792
|
+
output_dir = inputs["output_directory"]
|
|
793
|
+
if isinstance(output_dir, list):
|
|
794
|
+
output_dir = output_dir[0] if output_dir else "."
|
|
795
|
+
|
|
796
|
+
fetch_bldg_data(
|
|
797
|
+
selected_bldg_ids, file_type_tuple, Path(output_dir), weather_states=available_weather_states
|
|
798
|
+
)
|
|
799
|
+
else:
|
|
800
|
+
console.print("[yellow]No files selected for download.[/yellow]")
|
|
801
|
+
else:
|
|
802
|
+
console.print("[yellow]None of the selected file types are available for download.[/yellow]")
|
|
803
|
+
|
|
804
|
+
|
|
646
805
|
def main_callback(
|
|
647
806
|
product: str = PRODUCT_OPTION,
|
|
648
807
|
release_year: str = RELEASE_YEAR_OPTION,
|
|
@@ -659,61 +818,15 @@ def main_callback(
|
|
|
659
818
|
|
|
660
819
|
# If no arguments provided, run interactive mode
|
|
661
820
|
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
|
|
821
|
+
inputs = _run_interactive_mode_wrapper()
|
|
671
822
|
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
|
|
823
|
+
inputs = _process_direct_inputs(
|
|
824
|
+
product, release_year, weather_file, release_version, states, file_type, upgrade_id, output_directory
|
|
825
|
+
)
|
|
696
826
|
|
|
697
827
|
# Process the data
|
|
698
828
|
_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]")
|
|
829
|
+
_process_data_download(inputs)
|
|
717
830
|
|
|
718
831
|
|
|
719
832
|
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.3.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=6NAYxs_5yW0PpNgPdCgmaJJUqgSF-InrMO8xZJe4npQ,73839
|
|
4
|
+
buildstock_fetch/main_cli.py,sha256=3zKJ5sXG2QGmAs--kZPQy1qhLEnaw5gvi4RoH_q65dI,31891
|
|
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.3.0.dist-info/licenses/LICENSE,sha256=TJeh2yvO8__8Rbamd8r48-zvlFCINAsu9nOo5QdMRX8,1066
|
|
1604
|
+
buildstock_fetch-1.3.0.dist-info/METADATA,sha256=Ifx3dv3sp1coZB7-umz3kdpk3NEILXnZSjTdrIRYFOg,7607
|
|
1605
|
+
buildstock_fetch-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
1606
|
+
buildstock_fetch-1.3.0.dist-info/entry_points.txt,sha256=C7zPk3BSLcI47ymvYKI05nvfRJMEXz4BPIIDKsjePn8,54
|
|
1607
|
+
buildstock_fetch-1.3.0.dist-info/top_level.txt,sha256=-PGb2C-Tb3O-wPqUHSOBrvJqRzNHgY_KTbTsXaHIo5M,17
|
|
1608
|
+
buildstock_fetch-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|