Spaces:
Sleeping
Sleeping
# src/models.py | |
import numpy as np | |
import pandas as pd | |
from typing import List, Dict | |
import logging | |
from src.utils.logger import setup_logger | |
logger = setup_logger(__name__) | |
class TrafficData: | |
def __init__(self, axle_loads: List[float], traffic_growth_rate: float, analysis_period: int): | |
""" | |
Initialize TrafficData with axle loads, growth rate, and analysis period. | |
:param axle_loads: List of axle loads in kN. | |
:param traffic_growth_rate: Annual traffic growth rate (decimal, e.g., 0.02 for 2%). | |
:param analysis_period: Number of years for analysis. | |
""" | |
self.axle_loads = axle_loads | |
self.traffic_growth_rate = traffic_growth_rate | |
self.analysis_period = analysis_period | |
def get_total_axle_loads(self) -> List[List[float]]: | |
""" | |
Project total axle loads over the analysis period considering growth rate. | |
:return: A list of lists, each sublist represents axle loads for a year. | |
""" | |
total_loads = [] | |
for year in range(self.analysis_period): | |
growth_factor = (1 + self.traffic_growth_rate) ** year | |
projected_loads = [load * growth_factor for load in self.axle_loads] | |
total_loads.append(projected_loads) | |
logger.debug(f"Year {year + 1}: {projected_loads}") | |
return total_loads | |
def from_dataframe(df: pd.DataFrame) -> 'TrafficData': | |
""" | |
Create TrafficData instance from a pandas DataFrame. | |
:param df: DataFrame with columns 'Axle_Loads', 'Traffic_Growth_Rate', 'Analysis_Period'. | |
:return: TrafficData instance. | |
""" | |
try: | |
axle_loads = df['Axle_Loads'].dropna().tolist() | |
traffic_growth_rate = float(df['Traffic_Growth_Rate'].iloc[0]) | |
analysis_period = int(df['Analysis_Period'].iloc[0]) | |
logger.info("TrafficData loaded successfully from DataFrame.") | |
return TrafficData(axle_loads, traffic_growth_rate, analysis_period) | |
except Exception as e: | |
logger.error(f"Error creating TrafficData from DataFrame: {e}") | |
raise ValueError(f"Invalid Traffic Data: {e}") | |
class ClimateData: | |
def __init__(self, average_temperature: float, temperature_variation: float, rainfall: float): | |
""" | |
Initialize ClimateData with average temperature, temperature variation, and rainfall. | |
:param average_temperature: Average temperature in °C. | |
:param temperature_variation: Temperature variation in °C. | |
:param rainfall: Annual rainfall in mm. | |
""" | |
self.average_temperature = average_temperature | |
self.temperature_variation = temperature_variation | |
self.rainfall = rainfall | |
def from_dataframe(df: pd.DataFrame) -> 'ClimateData': | |
""" | |
Create ClimateData instance from a pandas DataFrame. | |
:param df: DataFrame with columns 'Average_Temperature', 'Temperature_Variation', 'Rainfall'. | |
:return: ClimateData instance. | |
""" | |
try: | |
average_temperature = float(df['Average_Temperature'].iloc[0]) | |
temperature_variation = float(df['Temperature_Variation'].iloc[0]) | |
rainfall = float(df['Rainfall'].iloc[0]) | |
logger.info("ClimateData loaded successfully from DataFrame.") | |
return ClimateData(average_temperature, temperature_variation, rainfall) | |
except Exception as e: | |
logger.error(f"Error creating ClimateData from DataFrame: {e}") | |
raise ValueError(f"Invalid Climate Data: {e}") | |
class SubgradeProperties: | |
def __init__(self, modulus: float, CBR: float): | |
""" | |
Initialize SubgradeProperties with modulus and California Bearing Ratio (CBR). | |
:param modulus: Modulus of subgrade reaction in kPa/m. | |
:param CBR: California Bearing Ratio in %. | |
""" | |
self.modulus = modulus | |
self.CBR = CBR | |
def from_dataframe(df: pd.DataFrame) -> 'SubgradeProperties': | |
""" | |
Create SubgradeProperties instance from a pandas DataFrame. | |
:param df: DataFrame with columns 'Modulus', 'CBR'. | |
:return: SubgradeProperties instance. | |
""" | |
try: | |
modulus = float(df['Modulus'].iloc[0]) | |
CBR = float(df['CBR'].iloc[0]) | |
logger.info("SubgradeProperties loaded successfully from DataFrame.") | |
return SubgradeProperties(modulus, CBR) | |
except Exception as e: | |
logger.error(f"Error creating SubgradeProperties from DataFrame: {e}") | |
raise ValueError(f"Invalid Subgrade Properties Data: {e}") | |
class MaterialProperties: | |
def __init__(self, asphalt_modulus: float, concrete_strength: float, thermal_coeff: float): | |
""" | |
Initialize MaterialProperties with asphalt modulus, concrete strength, and thermal coefficient. | |
:param asphalt_modulus: Asphalt modulus in MPa. | |
:param concrete_strength: Concrete strength in MPa. | |
:param thermal_coeff: Thermal coefficient (°C^-1). | |
""" | |
self.asphalt_modulus = asphalt_modulus | |
self.concrete_strength = concrete_strength | |
self.thermal_coeff = thermal_coeff | |
def from_dataframe(df: pd.DataFrame) -> 'MaterialProperties': | |
""" | |
Create MaterialProperties instance from a pandas DataFrame. | |
:param df: DataFrame with columns 'Asphalt_Modulus', 'Concrete_Strength', 'Thermal_Coeff'. | |
:return: MaterialProperties instance. | |
""" | |
try: | |
asphalt_modulus = float(df['Asphalt_Modulus'].iloc[0]) | |
concrete_strength = float(df['Concrete_Strength'].iloc[0]) | |
thermal_coeff = float(df['Thermal_Coeff'].iloc[0]) | |
logger.info("MaterialProperties loaded successfully from DataFrame.") | |
return MaterialProperties(asphalt_modulus, concrete_strength, thermal_coeff) | |
except Exception as e: | |
logger.error(f"Error creating MaterialProperties from DataFrame: {e}") | |
raise ValueError(f"Invalid Material Properties Data: {e}") | |
class Pavement: | |
def __init__(self, layers: List[float], pavement_type: str = 'Flexible'): | |
""" | |
Initialize Pavement structure. | |
:param layers: List of layer thicknesses in mm. | |
:param pavement_type: Type of pavement ('Flexible', 'Rigid', 'Composite'). | |
""" | |
self.layers = layers | |
self.pavement_type = pavement_type | |
def add_layer(self, thickness: float): | |
""" | |
Add a new layer to the pavement structure. | |
:param thickness: Thickness of the new layer in mm. | |
""" | |
self.layers.append(thickness) | |
logger.debug(f"Added layer: {thickness} mm. Total layers: {self.layers}") | |
def remove_layer(self, index: int): | |
""" | |
Remove a layer from the pavement structure by index. | |
:param index: Index of the layer to remove. | |
""" | |
if 0 <= index < len(self.layers): | |
removed = self.layers.pop(index) | |
logger.debug(f"Removed layer at index {index}: {removed} mm. Remaining layers: {self.layers}") | |
else: | |
logger.warning(f"Attempted to remove non-existent layer at index {index}.") | |
def set_pavement_type(self, pavement_type: str): | |
""" | |
Set the type of pavement. | |
:param pavement_type: Type of pavement ('Flexible', 'Rigid', 'Composite'). | |
""" | |
if pavement_type in ['Flexible', 'Rigid', 'Composite']: | |
self.pavement_type = pavement_type | |
logger.debug(f"Pavement type set to {pavement_type}.") | |
else: | |
logger.error(f"Invalid pavement type: {pavement_type}. Must be 'Flexible', 'Rigid', or 'Composite'.") | |
raise ValueError("Invalid pavement type. Choose from 'Flexible', 'Rigid', or 'Composite'.") | |