Download app/data_validation.py from mabuseif/test-29: direct link, hf CLI and curl.
- Browser
- Download file 12.1 kB
-
https://huggingface.co/spaces/mabuseif/test-29/resolve/main/app/data_validation.py
- Command line
-
hf download hf://spaces/mabuseif/test-29/app/data_validation.py
-
curl -L -o data_validation.py https://huggingface.co/spaces/mabuseif/test-29/resolve/main/app/data_validation.py
12.1 kB
| """ | |
| Data validation module for HVAC Load Calculator. | |
| This module provides validation functions for user inputs. | |
| """ | |
| import streamlit as st | |
| import pandas as pd | |
| import numpy as np | |
| from typing import Dict, List, Any, Optional, Tuple, Callable | |
| import json | |
| import os | |
| class DataValidation: | |
| """Class for data validation functionality.""" | |
| def validate_building_info(building_info: Dict[str, Any]) -> Tuple[bool, List[str]]: | |
| """ | |
| Validate building information inputs. | |
| Args: | |
| building_info: Dictionary with building information | |
| Returns: | |
| Tuple containing validation result (True if valid) and list of validation messages | |
| """ | |
| is_valid = True | |
| messages = [] | |
| # Check required fields | |
| required_fields = [ | |
| ("project_name", "Project Name"), | |
| ("building_name", "Building Name"), | |
| ("location", "Location"), | |
| ("climate_zone", "Climate Zone"), | |
| ("building_type", "Building Type") | |
| ] | |
| for field, display_name in required_fields: | |
| if field not in building_info or not building_info[field]: | |
| is_valid = False | |
| messages.append(f"{display_name} is required.") | |
| # Check numeric fields | |
| numeric_fields = [ | |
| ("floor_area", "Floor Area", 0, None), | |
| ("num_floors", "Number of Floors", 1, None), | |
| ("floor_height", "Floor Height", 2.0, 10.0), | |
| ("occupancy", "Occupancy", 0, None) | |
| ] | |
| for field, display_name, min_val, max_val in numeric_fields: | |
| if field in building_info: | |
| try: | |
| value = float(building_info[field]) | |
| if min_val is not None and value < min_val: | |
| is_valid = False | |
| messages.append(f"{display_name} must be at least {min_val}.") | |
| if max_val is not None and value > max_val: | |
| is_valid = False | |
| messages.append(f"{display_name} must be at most {max_val}.") | |
| except (ValueError, TypeError): | |
| is_valid = False | |
| messages.append(f"{display_name} must be a number.") | |
| # Check design conditions | |
| if "design_conditions" in building_info: | |
| design_conditions = building_info["design_conditions"] | |
| # Check summer conditions | |
| summer_fields = [ | |
| ("summer_outdoor_db", "Summer Outdoor Dry-Bulb", -10.0, 50.0), | |
| ("summer_outdoor_wb", "Summer Outdoor Wet-Bulb", -10.0, 40.0), | |
| ("summer_indoor_db", "Summer Indoor Dry-Bulb", 18.0, 30.0), | |
| ("summer_indoor_rh", "Summer Indoor RH", 30.0, 70.0) | |
| ] | |
| for field, display_name, min_val, max_val in summer_fields: | |
| if field in design_conditions: | |
| try: | |
| value = float(design_conditions[field]) | |
| if min_val is not None and value < min_val: | |
| is_valid = False | |
| messages.append(f"{display_name} must be at least {min_val}.") | |
| if max_val is not None and value > max_val: | |
| is_valid = False | |
| messages.append(f"{display_name} must be at most {max_val}.") | |
| except (ValueError, TypeError): | |
| is_valid = False | |
| messages.append(f"{display_name} must be a number.") | |
| # Check winter conditions | |
| winter_fields = [ | |
| ("winter_outdoor_db", "Winter Outdoor Dry-Bulb", -40.0, 20.0), | |
| ("winter_outdoor_rh", "Winter Outdoor RH", 0.0, 100.0), | |
| ("winter_indoor_db", "Winter Indoor Dry-Bulb", 18.0, 25.0), | |
| ("winter_indoor_rh", "Winter Indoor RH", 20.0, 60.0) | |
| ] | |
| for field, display_name, min_val, max_val in winter_fields: | |
| if field in design_conditions: | |
| try: | |
| value = float(design_conditions[field]) | |
| if min_val is not None and value < min_val: | |
| is_valid = False | |
| messages.append(f"{display_name} must be at least {min_val}.") | |
| if max_val is not None and value > max_val: | |
| is_valid = False | |
| messages.append(f"{display_name} must be at most {max_val}.") | |
| except (ValueError, TypeError): | |
| is_valid = False | |
| messages.append(f"{display_name} must be a number.") | |
| # Check that wet-bulb is less than dry-bulb | |
| if "summer_outdoor_db" in design_conditions and "summer_outdoor_wb" in design_conditions: | |
| try: | |
| db = float(design_conditions["summer_outdoor_db"]) | |
| wb = float(design_conditions["summer_outdoor_wb"]) | |
| if wb > db: | |
| is_valid = False | |
| messages.append("Summer Outdoor Wet-Bulb temperature must be less than or equal to Dry-Bulb temperature.") | |
| except (ValueError, TypeError): | |
| pass # Already handled above | |
| return is_valid, messages | |
| def validate_components(components: Dict[str, List[Any]]) -> Tuple[bool, List[str]]: | |
| """ | |
| Validate building components. | |
| Args: | |
| components: Dictionary with building components | |
| Returns: | |
| Tuple containing validation result (True if valid) and list of validation messages | |
| """ | |
| is_valid = True | |
| messages = [] | |
| # Check if any components exist | |
| if not any(components.values()): | |
| is_valid = False | |
| messages.append("At least one building component (wall, roof, floor, window, or door) is required.") | |
| # Check wall components | |
| for i, wall in enumerate(components.get("walls", [])): | |
| # Check required fields | |
| if not wall.name: | |
| is_valid = False | |
| messages.append(f"Wall #{i+1}: Name is required.") | |
| # Check numeric fields | |
| if wall.area <= 0: | |
| is_valid = False | |
| messages.append(f"Wall #{i+1}: Area must be greater than zero.") | |
| if wall.u_value <= 0: | |
| is_valid = False | |
| messages.append(f"Wall #{i+1}: U-value must be greater than zero.") | |
| # Check roof components | |
| for i, roof in enumerate(components.get("roofs", [])): | |
| # Check required fields | |
| if not roof.name: | |
| is_valid = False | |
| messages.append(f"Roof #{i+1}: Name is required.") | |
| # Check numeric fields | |
| if roof.area <= 0: | |
| is_valid = False | |
| messages.append(f"Roof #{i+1}: Area must be greater than zero.") | |
| if roof.u_value <= 0: | |
| is_valid = False | |
| messages.append(f"Roof #{i+1}: U-value must be greater than zero.") | |
| # Check floor components | |
| for i, floor in enumerate(components.get("floors", [])): | |
| # Check required fields | |
| if not floor.name: | |
| is_valid = False | |
| messages.append(f"Floor #{i+1}: Name is required.") | |
| # Check numeric fields | |
| if floor.area <= 0: | |
| is_valid = False | |
| messages.append(f"Floor #{i+1}: Area must be greater than zero.") | |
| if floor.u_value <= 0: | |
| is_valid = False | |
| messages.append(f"Floor #{i+1}: U-value must be greater than zero.") | |
| # Check window components | |
| for i, window in enumerate(components.get("windows", [])): | |
| # Check required fields | |
| if not window.name: | |
| is_valid = False | |
| messages.append(f"Window #{i+1}: Name is required.") | |
| # Check numeric fields | |
| if window.area <= 0: | |
| is_valid = False | |
| messages.append(f"Window #{i+1}: Area must be greater than zero.") | |
| if window.u_value <= 0: | |
| is_valid = False | |
| messages.append(f"Window #{i+1}: U-value must be greater than zero.") | |
| if window.shgc <= 0 or window.shgc > 1: | |
| is_valid = False | |
| messages.append(f"Window #{i+1}: SHGC must be between 0 and 1.") | |
| # Check door components | |
| for i, door in enumerate(components.get("doors", [])): | |
| # Check required fields | |
| if not door.name: | |
| is_valid = False | |
| messages.append(f"Door #{i+1}: Name is required.") | |
| # Check numeric fields | |
| if door.area <= 0: | |
| is_valid = False | |
| messages.append(f"Door #{i+1}: Area must be greater than zero.") | |
| if door.u_value <= 0: | |
| is_valid = False | |
| messages.append(f"Door #{i+1}: U-value must be greater than zero.") | |
| # Check for minimum requirements | |
| if not components.get("walls", []): | |
| messages.append("Warning: No walls defined. At least one wall is recommended.") | |
| if not components.get("roofs", []): | |
| messages.append("Warning: No roofs defined. At least one roof is recommended.") | |
| if not components.get("floors", []): | |
| messages.append("Warning: No floors defined. At least one floor is recommended.") | |
| return is_valid, messages | |
| def validate_calculation_inputs(self, session_state: Dict[str, Any]) -> bool: | |
| """ | |
| Validate inputs required for HVAC load calculations. | |
| Args: | |
| session_state: Streamlit session state containing all inputs | |
| Returns: | |
| Boolean indicating whether inputs are valid for calculations | |
| """ | |
| # Check if building information exists | |
| if not session_state.get("building_info"): | |
| st.error("Building information is required for calculations.") | |
| return False | |
| # Validate building information | |
| building_info_valid, building_info_messages = self.validate_building_info(session_state["building_info"]) | |
| if not building_info_valid: | |
| st.error("Building information is incomplete or invalid:") | |
| for message in building_info_messages: | |
| st.error(f"- {message}") | |
| return False | |
| # Check if design conditions exist | |
| if "design_conditions" not in session_state["building_info"]: | |
| st.error("Design conditions are required for calculations.") | |
| return False | |
| # Check if components exist | |
| if not session_state.get("components"): | |
| st.error("Building components are required for calculations.") | |
| return False | |
| # Validate components | |
| components_valid, components_messages = self.validate_components(session_state["components"]) | |
| if not components_valid: | |
| st.error("Building components are incomplete or invalid:") | |
| for message in components_messages: | |
| st.error(f"- {message}") | |
| return False | |
| # Check if at least one component exists | |
| if not any(session_state["components"].values()): | |
| st.error("At least one building component (wall, roof, floor, window, or door) is required.") | |
| return False | |
| # All validations passed | |
| return True | |