Skip to content

Commit dfc4664

Browse files
Merge pull request #264 from LeoLuosifen/yluo0664
Fixed the issues of number 1, 3, 5, and 6
2 parents f9465e6 + 6a385a9 commit dfc4664

7 files changed

Lines changed: 74 additions & 62 deletions

File tree

config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Assets:
5454
class PageInfo:
5555
"""Stores page names and orders for registration."""
5656

57-
SELECT_NAME = "Select Weather File"
57+
SELECT_NAME = "Select weather file"
5858
SELECT_ORDER = 0
5959
SUMMARY_NAME = "Climate Summary"
6060
SUMMARY_ORDER = 1

pages/lib/layout.py

Lines changed: 48 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
class NavBarIcons:
1616
_ICON_MAP = {
17-
"Select Weather File": "tabler:upload",
1817
"Climate Summary": "tabler:chart-bar",
1918
"Temperature and Humidity": "tabler:temperature",
2019
"Sun and Clouds": "tabler:sun",
@@ -26,7 +25,6 @@ class NavBarIcons:
2625
"Changelog": "tabler:history",
2726
}
2827

29-
SELECT_WEATHER_FILE = _ICON_MAP["Select Weather File"]
3028
CLIMATE_SUMMARY = _ICON_MAP["Climate Summary"]
3129
TEMPERATURE_AND_HUMIDITY = _ICON_MAP["Temperature and Humidity"]
3230
SUN_AND_CLOUDS = _ICON_MAP["Sun and Clouds"]
@@ -49,14 +47,7 @@ def create_tools_filter_components():
4947
return dmc.Stack(
5048
id=ElementIds.TOOLS_MONTH_HOUR_SECTION,
5149
children=[
52-
dmc.Divider(label="Filter function", size="xs", color="blue"),
53-
dmc.Button(
54-
"Apply month and hour filter",
55-
id=ElementIds.TOOLS_APPLY_MONTH_HOUR_FILTER,
56-
color="blue",
57-
variant="light",
58-
size="xs",
59-
),
50+
dmc.Divider(label="Filters", size="xs", color="blue"),
6051
# Month controls
6152
dmc.Text("Month Range:", size="xs", c="dimmed"),
6253
dcc.RangeSlider(
@@ -113,6 +104,13 @@ def create_tools_filter_components():
113104
],
114105
justify="flex-end",
115106
),
107+
dmc.Button(
108+
"Apply month and hour filter",
109+
id=ElementIds.TOOLS_APPLY_MONTH_HOUR_FILTER,
110+
color="blue",
111+
variant="filled",
112+
size="xs",
113+
),
116114
],
117115
gap="xs",
118116
p="xs",
@@ -137,7 +135,28 @@ def create_navbar():
137135
}
138136
}
139137

140-
# Secondary Menu
138+
# Select weather file - top-level menu item
139+
select_weather_file_page = next(
140+
(
141+
page
142+
for page in dash.page_registry.values()
143+
if page[Variables.NAME.col_name] == "Select weather file"
144+
),
145+
None,
146+
)
147+
select_weather_file_link = (
148+
dmc.NavLink(
149+
label=select_weather_file_page[Variables.NAME.col_name],
150+
href=select_weather_file_page[Variables.PATH.col_name],
151+
id=f"nav-{select_weather_file_page[Variables.PATH.col_name].replace('/', '')}",
152+
active=False,
153+
styles=nav_link_styles,
154+
)
155+
if select_weather_file_page
156+
else None
157+
)
158+
159+
# Secondary Menu - exclude "Select weather file" as it will be a top-level menu
141160
sub_links = [
142161
dmc.NavLink(
143162
label=page[Variables.NAME.col_name],
@@ -150,11 +169,12 @@ def create_navbar():
150169
styles=nav_link_styles,
151170
)
152171
for page in dash.page_registry.values()
153-
if page[Variables.NAME.col_name] not in ["404", "Changelog"]
172+
if page[Variables.NAME.col_name]
173+
not in ["404", "Changelog", "Select weather file"]
154174
]
155175

156176
parent_group = dmc.NavLink(
157-
label="Pages Menu",
177+
label="Visualize weather file",
158178
children=sub_links,
159179
id=ElementIds.NAV_GROUP_MAIN,
160180
variant="light",
@@ -168,17 +188,11 @@ def create_navbar():
168188

169189
controls_stack = dmc.Stack(
170190
gap="xs",
171-
py="xs",
191+
p="xs",
172192
children=[
193+
dmc.Divider(label="Units and Ranges", size="xs", color="blue"),
173194
dmc.Tooltip(
174-
label=dmc.Stack(
175-
gap="xs",
176-
children=[
177-
dmc.Text(
178-
"You can choose value ranges between Global and Local"
179-
),
180-
],
181-
),
195+
label=dmc.Text("You can choose value ranges between Global and Local"),
182196
position="right",
183197
withArrow=True,
184198
children=dmc.SegmentedControl(
@@ -189,18 +203,13 @@ def create_navbar():
189203
{"label": "Global", "value": "global"},
190204
{"label": "Local", "value": "local"},
191205
],
192-
w=220,
206+
w=210,
193207
size="sm",
194208
styles=segmented_control_styles,
195209
),
196210
),
197211
dmc.Tooltip(
198-
label=dmc.Stack(
199-
gap="xs",
200-
children=[
201-
dmc.Text("You can choose units between SI and IP"),
202-
],
203-
),
212+
label=dmc.Text("You can choose units between SI and IP"),
204213
position="right",
205214
withArrow=True,
206215
children=dmc.SegmentedControl(
@@ -211,7 +220,7 @@ def create_navbar():
211220
{"label": "SI", "value": UnitSystem.SI},
212221
{"label": "IP", "value": UnitSystem.IP},
213222
],
214-
w=220,
223+
w=210,
215224
size="sm",
216225
styles=segmented_control_styles,
217226
),
@@ -223,11 +232,12 @@ def create_navbar():
223232

224233
# Tools
225234
controls_group = dmc.NavLink(
226-
label="Tools Menu",
227-
children=[controls_stack, filter_components],
235+
label="Filters and units",
236+
children=[filter_components, controls_stack],
228237
id=ElementIds.NAV_GROUP_CONTROLS,
229238
variant="light",
230239
childrenOffset=0,
240+
opened=True,
231241
)
232242

233243
# Documentation
@@ -240,7 +250,12 @@ def create_navbar():
240250
)
241251

242252
return dmc.ScrollArea(
243-
children=[parent_group, controls_group, doc_link],
253+
children=[
254+
select_weather_file_link,
255+
parent_group,
256+
controls_group,
257+
doc_link,
258+
],
244259
)
245260

246261

pages/lib/template_graphs.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,9 @@ def heatmap_with_filter(
405405
),
406406
)
407407

408-
if global_local == "global":
408+
# For category variables (e.g., UTCI categories), always use global range
409+
# to ensure consistent color mapping regardless of data range
410+
if "_categories" in var or global_local == "global":
409411
# Set Global values for Max and minimum
410412
range_z = var_range
411413
else:
@@ -712,7 +714,9 @@ def wind_rose(df, title, month, hour, labels, si_ip, skip_time_filter=False):
712714

713715
spd_colors = wind_speed_variable.get_color()
714716
spd_unit = wind_speed_variable.get_unit(si_ip)
715-
spd_bins = WIND_ROSE_BINS
717+
spd_bins = list(
718+
WIND_ROSE_BINS
719+
) # Create a copy to avoid modifying the global constant
716720
if si_ip == UnitSystem.IP:
717721
spd_bins = convert_bins(spd_bins)
718722

@@ -810,12 +814,18 @@ def wind_rose(df, title, month, hour, labels, si_ip, skip_time_filter=False):
810814

811815

812816
def convert_bins(sbins):
813-
i = 0
817+
"""Convert wind speed bins from m/s to fpm (feet per minute).
818+
819+
Returns a new list without modifying the input list.
820+
"""
821+
result = []
814822
for x in sbins:
815-
x = x * 196.85039370078738
816-
sbins[i] = round(x, 1)
817-
i = i + 1
818-
return sbins
823+
if np.isfinite(x):
824+
converted = round(x * 196.85039370078738, 1)
825+
result.append(converted)
826+
else:
827+
result.append(x) # Preserve np.inf
828+
return result
819829

820830

821831
def thermal_stress_stacked_barchart(

pages/select.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,6 @@ def switch_si_ip(_, si_ip_input, url_store, lines):
248248

249249
@callback(
250250
[
251-
Output(ElementIds.NAV, "disabled"),
252251
Output(ElementIds.NAV_SUMMARY, "disabled"),
253252
Output(ElementIds.NAV_T_RH, "disabled"),
254253
Output(ElementIds.NAV_SUN, "disabled"),
@@ -277,7 +276,6 @@ def enable_tabs_when_data_is_loaded(meta, data):
277276
True,
278277
True,
279278
True,
280-
True,
281279
default,
282280
)
283281
else:
@@ -290,7 +288,6 @@ def enable_tabs_when_data_is_loaded(meta, data):
290288
False,
291289
False,
292290
False,
293-
False,
294291
"Current Location: "
295292
+ meta[Variables.CITY.col_name]
296293
+ ", "

pages/sun.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,15 +286,15 @@ def sun_path_chart(_, view, var, global_local, global_filter_data, df, meta, si_
286286
units = "" if var == "None" else generate_units(si_ip)
287287
if view == "polar":
288288
return dcc.Graph(
289-
style={"width": "100%", "height": "520px"},
289+
style={"maxWidth": "50em", "height": "520px"},
290290
config=generate_chart_name(
291291
TabNames.SPHERICAL_SUNPATH, meta, custom_inputs, units
292292
),
293293
figure=polar_graph(df, meta, global_local, var, si_ip),
294294
)
295295
else:
296296
return dcc.Graph(
297-
style={"width": "100%", "height": "520px"},
297+
style={"maxWidth": "50em", "height": "520px"},
298298
config=generate_chart_name(
299299
TabNames.CARTESIAN_SUNPATH, meta, custom_inputs, units
300300
),

tests/test_filter.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,8 @@ def ensure_local_mode_and_invert_off(page: Page):
2626

2727

2828
def open_tools_menu_and_filter_section(page: Page):
29-
"""Open Tools Menu → Filter function, using the simplest reliable click."""
30-
header = page.get_by_text("Tools Menu", exact=False).first
31-
header.scroll_into_view_if_needed()
32-
header.click()
33-
34-
try:
35-
page.get_by_text("Filter function", exact=False).first.click()
36-
except Exception:
37-
pass
38-
39-
expect(
40-
page.get_by_text("Apply month and hour filter", exact=False).first
41-
).to_be_visible()
29+
apply_btn = page.get_by_text("Apply month and hour filter", exact=False)
30+
expect(apply_btn.first).to_be_visible()
4231
ensure_local_mode_and_invert_off(page)
4332

4433

tests/test_summary.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,12 @@ def test_unit_switch(page: Page):
8282

8383
# Click the "IP" option
8484
ip_button = page.get_by_text("IP", exact=True)
85+
expect(ip_button).to_be_visible()
8586
ip_button.scroll_into_view_if_needed()
8687
ip_button.wait_for(state="visible")
8788
ip_button.click(force=True)
8889

8990
info_section = page.locator("#location-info")
90-
expect(info_section).to_contain_text("°F")
91-
expect(info_section).to_contain_text("ft")
92-
expect(info_section).to_contain_text("kBtu/ft2")
91+
expect(info_section.get_by_text("°F")).to_be_visible
92+
expect(info_section.get_by_text("ft")).to_be_visible
93+
expect(info_section.get_by_text("kBtu/ft2")).to_be_visible

0 commit comments

Comments
 (0)