{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a4df47d9-0db1-4d1b-b31c-6b38d9bdb5fb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/Users/mguillermo/Desktop/MGPH/Maestria/Hydrogen_Exp/Analysis/2nd_AMIDIQ_Analysis\n",
      "(1, 1) (68, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(1, 2) (66, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(1, 3) (68, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(1, 4) (67, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(2, 1) (62, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(2, 2) (62, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(2, 3) (63, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n",
      "(2, 4) (63, 11) cols: ['No Muestra', 'volt_iny', 'volt_elec', 'curr_elec', 'curr_iny', 'res', 'temp', 'Observaciones', 'ronda', 'experimento', 'archivo']\n"
     ]
    }
   ],
   "source": [
    "from    pathlib import Path\n",
    "import  re\n",
    "import  pandas  as  pd\n",
    "\n",
    "# Configuration project\n",
    "\n",
    "PROJECT_ROOT    =   Path.cwd().parent   if Path.cwd().name  ==  \"Notebooks\" else    Path.cwd()\n",
    "print(PROJECT_ROOT)\n",
    "DATA_DIR        =   PROJECT_ROOT / \"Data\" \n",
    "\n",
    "# Mapping \"possible names\" - \"standard names\"\n",
    "\n",
    "column_aliases =   {\n",
    "    \"volt_iny\"  :   [\"Voltaje Inyectado (V)\"],\n",
    "    \"volt_elec\" :   [\"Voltaje Electrodos (V)\"],\n",
    "    \"curr_elec\" :   [\"Corriente Electrodos (A)\"],\n",
    "    \"curr_iny\"  :   [\"Corriente Inyectada (A)\"],\n",
    "    \"res\"       :   [\"Resistencia\"],\n",
    "    \"temp\"      :   [\"Temperatura\"],\n",
    "} \n",
    "\n",
    "def _clean_name(name:   str) -> str:\n",
    "    \"\"\"Normaliza un encabezado: minisculas, sin espacios dobles, sin simbolos raros.\"\"\"\n",
    "    name    =   name.replace(\"\\ufeff\", \"\")\n",
    "    name    =   name.strip().lower()\n",
    "    name    =   re.sub(r\"\\s+\", \"\", name)\n",
    "    name    =   re.sub(r\"[^a-z0-9áéíóúñ _\\-]\", \"\", name)\n",
    "    return name\n",
    "\n",
    "def normalize_columns(df: pd.DataFrame) -> pd.DataFrame:\n",
    "    \"\"\"Rename columns to standard names as alias\"\"\"\n",
    "\n",
    "    df.columns      =   [str(c) for c in df.columns]\n",
    "\n",
    "    ## Print the information in the columns\n",
    "    #print(\"Originals Columns:\", df.columns)\n",
    "    #print(\"Types:\", [type(c) for c in df.columns])\n",
    "\n",
    "    original_cols   =   list(df.columns)\n",
    "    cleaned         =   {_clean_name(c): c for c in original_cols}\n",
    "\n",
    "    rename_map      =   {}\n",
    "    for std, aliases in column_aliases.items():\n",
    "        for a in aliases:\n",
    "            a_clean =   _clean_name(a)\n",
    "            if  a_clean in cleaned:\n",
    "                rename_map[cleaned[a_clean]]    =   std\n",
    "                break\n",
    "    df  =   df.rename(columns=rename_map)\n",
    "\n",
    "    return  df\n",
    "\n",
    "def load_experiment(csv_path: Path, ronda: int, experimento: int) -> pd.DataFrame:\n",
    "    \"\"\"Upload a CSV, normalize columns and add metadata.\"\"\"\n",
    "    df  =   pd.read_csv(csv_path, sep=None, engine=\"python\", encoding=\"utf-8-sig\")\n",
    "\n",
    "    df  =   normalize_columns(df)\n",
    "\n",
    "    # Adding metadata for comparative analysis\n",
    "    df[\"ronda\"]         =   ronda\n",
    "    df[\"experimento\"]   =   experimento\n",
    "    df[\"archivo\"]       =   csv_path.name\n",
    "\n",
    "    return  df\n",
    "\n",
    "def apply_filter(\n",
    "        df: pd.DataFrame,\n",
    "        row_start:  int     |   None    =   None,\n",
    "        row_end:    int     |   None    =   None,\n",
    "        time_col:   str     =   \"tiempo\",\n",
    "        t_min:      float   |   None    =   None,\n",
    "        t_max:      float   |   None    =   None,   \n",
    ")   ->  pd.DataFrame:\n",
    "    \"\"\"\n",
    "    Filtro Flexible:\n",
    "    -   por índices de fila [row_start:row_end]\n",
    "    -   por rango de tiempo [t_min, t_max] si existe columna 'tiempo'\n",
    "    \"\"\"\n",
    "\n",
    "    out =   df.copy()\n",
    "\n",
    "    if  row_start is not None or row_end is not None:\n",
    "        out =   out.iloc[row_start:row_end]\n",
    "\n",
    "    if time_col in out.columns  and (t_min  is not  None    or t_max is not None):\n",
    "        if  t_min   is not  None:\n",
    "            out =   out[out[time_col]   >=  t_min]\n",
    "        if  t_max   is not  None:\n",
    "            out =   out[out[time_col]   <=  t_max]\n",
    "    \n",
    "    return   out.reset_index(drop=True)\n",
    "\n",
    "def load_all(data_dir: Path)    -> dict[tuple[int, int], pd.DataFrame]:\n",
    "    \"\"\"\n",
    "    Carga todo en un diccionario:\n",
    "    key     =   (ronda, experimento)\n",
    "    value   =   DataFrame \n",
    "    \"\"\"\n",
    "    data = {}\n",
    "\n",
    "    #Find files like: data/round1/*.csv and data/round2/*.csv\n",
    "    for ronda in [1,2]:\n",
    "        ronda_dir   =   data_dir / f\"Rnd_{ronda}\"\n",
    "        csvs        =   sorted(ronda_dir.glob(\"*.csv\"))\n",
    "\n",
    "        if not csvs:\n",
    "            print(f\"Theres no CSVs in: {ronda_dir}\")\n",
    "            continue\n",
    "        \n",
    "        for i, csv_path in enumerate(csvs, start=1):\n",
    "            df  =   load_experiment(csv_path, ronda=ronda, experimento=i)\n",
    "            data[(ronda, i)]    =   df\n",
    "    \n",
    "    return data\n",
    "\n",
    "#   =========================\n",
    "#   Ejecución\n",
    "#   =========================\n",
    "\n",
    "data    =   load_all(DATA_DIR)\n",
    "\n",
    "#   Fast View\n",
    "\n",
    "for key, df in data.items():\n",
    "    print(key, df.shape, \"cols:\", list(df.columns))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c792a234",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python_Data_Analysis",
   "language": "python",
   "name": "python_data_analysis"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.14.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
