""" Database extraction utilities for validation. Extracts processed data from database tables for Python vs MATLAB comparison. """ import numpy as np from typing import Dict, List, Optional, Tuple, Any from datetime import datetime import logging from ..common.database import DatabaseConnection logger = logging.getLogger(__name__) class DataExtractor: """Extract processed data from database for validation.""" def __init__(self, conn: DatabaseConnection): """ Initialize extractor with database connection. Args: conn: DatabaseConnection instance """ self.conn = conn def extract_rsn_data(self, control_unit_id: str, chain: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract RSN elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier start_date: Optional start date filter (YYYY-MM-DD) end_date: Optional end date filter (YYYY-MM-DD) Returns: List of dictionaries with RSN data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, SensorType, RollAngle, InclinAngle, AzimuthAngle, RollAngleDiff, InclinAngleDiff, AzimuthAngleDiff, T_node, calcerr FROM ELABDATARSN WHERE UnitName = %s AND ToolNameID = %s """ params = [control_unit_id, chain] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} RSN records for {control_unit_id}/{chain}") return results def extract_tilt_data(self, control_unit_id: str, chain: str, sensor_type: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract Tilt elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier sensor_type: Sensor type (TLHR, BL, PL, KLHR) start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with Tilt data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, SensorType, X, Y, Z, X_local, Y_local, Z_local, XShift, YShift, ZShift, T_node, calcerr FROM ELABDATATILT WHERE UnitName = %s AND ToolNameID = %s AND SensorType = %s """ params = [control_unit_id, chain, sensor_type] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} Tilt {sensor_type} records for {control_unit_id}/{chain}") return results def extract_atd_radial_link_data(self, control_unit_id: str, chain: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD Radial Link (RL) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with RL data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, X, Y, Z, X_local, Y_local, Z_local, XShift, YShift, ZShift, T_node, calcerr FROM ELABDATARL WHERE UnitName = %s AND ToolNameID = %s """ params = [control_unit_id, chain] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} RL records for {control_unit_id}/{chain}") return results def extract_atd_load_link_data(self, control_unit_id: str, chain: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD Load Link (LL) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with LL data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, Load, LoadDiff, T_node, calcerr FROM ELABDATALL WHERE UnitName = %s AND ToolNameID = %s """ params = [control_unit_id, chain] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} LL records for {control_unit_id}/{chain}") return results def extract_atd_pressure_link_data(self, control_unit_id: str, chain: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD Pressure Link (PL) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with PL data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, Pressure, PressureDiff, T_node, calcerr FROM ELABDATAPL WHERE UnitName = %s AND ToolNameID = %s """ params = [control_unit_id, chain] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} PL records for {control_unit_id}/{chain}") return results def extract_atd_extensometer_3d_data(self, control_unit_id: str, chain: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD 3D Extensometer (3DEL) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with 3DEL data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, X, Y, Z, XShift, YShift, ZShift, T_node, calcerr FROM ELABDATA3DEL WHERE UnitName = %s AND ToolNameID = %s """ params = [control_unit_id, chain] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} 3DEL records for {control_unit_id}/{chain}") return results def extract_atd_crackmeter_data(self, control_unit_id: str, chain: str, sensor_type: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD Crackmeter (CrL/2DCrL/3DCrL) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier sensor_type: Sensor type (CrL, 2DCrL, 3DCrL) start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with crackmeter data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, SensorType, X, Y, Z, XShift, YShift, ZShift, T_node, calcerr FROM ELABDATACRL WHERE UnitName = %s AND ToolNameID = %s AND SensorType = %s """ params = [control_unit_id, chain, sensor_type] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} {sensor_type} records for {control_unit_id}/{chain}") return results def extract_atd_pcl_data(self, control_unit_id: str, chain: str, sensor_type: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD Perimeter Cable Link (PCL/PCLHR) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier sensor_type: Sensor type (PCL, PCLHR) start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with PCL data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, SensorType, Y, Z, Y_local, Z_local, AlphaX, AlphaY, YShift, ZShift, T_node, calcerr FROM ELABDATAPCL WHERE UnitName = %s AND ToolNameID = %s AND SensorType = %s """ params = [control_unit_id, chain, sensor_type] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} {sensor_type} records for {control_unit_id}/{chain}") return results def extract_atd_tube_link_data(self, control_unit_id: str, chain: str, start_date: Optional[str] = None, end_date: Optional[str] = None) -> List[Dict[str, Any]]: """ Extract ATD Tube Link (TuL) elaborated data. Args: control_unit_id: Control unit identifier chain: Chain identifier start_date: Optional start date filter end_date: Optional end date filter Returns: List of dictionaries with TuL data """ query = """ SELECT UnitName, ToolNameID, NodeNum, EventDate, EventTime, X, Y, Z, X_Star, Y_Star, Z_Star, XShift, YShift, ZShift, T_node, calcerr FROM ELABDATATUBE WHERE UnitName = %s AND ToolNameID = %s """ params = [control_unit_id, chain] if start_date: query += " AND EventDate >= %s" params.append(start_date) if end_date: query += " AND EventDate <= %s" params.append(end_date) query += " ORDER BY EventDate, EventTime, NodeNum" results = self.conn.execute_query(query, tuple(params)) logger.info(f"Extracted {len(results)} TuL records for {control_unit_id}/{chain}") return results def get_latest_timestamp(self, table: str, control_unit_id: str, chain: str) -> Optional[Tuple[str, str]]: """ Get the latest timestamp (date, time) for a given table and chain. Args: table: Table name (e.g., 'ELABDATARSN') control_unit_id: Control unit identifier chain: Chain identifier Returns: Tuple of (date, time) or None if no data """ query = f""" SELECT EventDate, EventTime FROM {table} WHERE UnitName = %s AND ToolNameID = %s ORDER BY EventDate DESC, EventTime DESC LIMIT 1 """ results = self.conn.execute_query(query, (control_unit_id, chain)) if results: return (results[0]['EventDate'], results[0]['EventTime']) return None