{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f1de3e2e-cc89-4b12-a2fb-42c1270755ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import scipy as sc\n",
    "\n",
    "import os\n",
    "import glob\n",
    "from pathlib import Path\n",
    "import warnings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "38262129-8cd6-447a-b0b5-554ab370f153",
   "metadata": {},
   "outputs": [],
   "source": [
    "def list_files_pathlib(\n",
    "    directory_path, \n",
    "    verbose=None,\n",
    "):\n",
    "    \"\"\"\n",
    "    Lists files using the modern pathlib module and returns them as a list.\n",
    "    \n",
    "    Args:\n",
    "        directory_path (str): The path to the directory to inspect.\n",
    "        verbose (bool): If True, prints detailed output to the console. \n",
    "                        Defaults to False.\n",
    "\n",
    "    Returns:\n",
    "        list: A list of file names (str) found in the directory. \n",
    "              Returns an empty list if the directory is not found or is empty.\n",
    "    \"\"\"\n",
    "\n",
    "    import os\n",
    "    import glob\n",
    "    from pathlib import Path\n",
    "    import warnings\n",
    "    \n",
    "    if verbose is None:\n",
    "        verbose = False\n",
    "    elif verbose is True:\n",
    "        print(f\"--- Listing contents in '{directory_path}' using pathlib ---\")\n",
    "    \n",
    "    try:\n",
    "\n",
    "        # Step 1 - Check if the directory_path is valid\n",
    "        # Note - this code is almost too bulletproof? I love it :D\n",
    "        path_obj = Path(directory_path)\n",
    "        if not path_obj.exists():\n",
    "            warnings.warn(f\"Directory not found at '{directory_path}'\", UserWarning)\n",
    "            return []  # Return empty list on error\n",
    "        if not path_obj.is_dir():\n",
    "            warnings.warn(f\"The path '{directory_path}' is not a directory.\", UserWarning)\n",
    "            return []  # Return empty list on error\n",
    "        entries = sorted(list(path_obj.iterdir()))\n",
    "        if not entries:\n",
    "            warnings.warn(f\"The directory at '{directory_path}' is empty.\", UserWarning)\n",
    "            return []  # Return empty list on error\n",
    "        \n",
    "\n",
    "        # Step 2 - Collect all the files in the directory\n",
    "        files_list = []\n",
    "        entries = sorted(list(path_obj.iterdir()))\n",
    "        for entry in entries:\n",
    "            if entry.is_file():\n",
    "                files_list.append(str(entry))\n",
    "            if verbose:\n",
    "                entry_type = \"dir\" if entry.is_dir() else \"file\"\n",
    "                print(f\"- {entry.name:<20} ({entry_type})\")        \n",
    "        return files_list\n",
    "\n",
    "    except Exception as e:\n",
    "        warnings.warn(f\"An unexpected error occurred: {e}\", RuntimeWarning)\n",
    "        return [] # Return empty list on unexpected exception\n",
    "    finally:\n",
    "        if verbose:\n",
    "            print(\"-\" * 50)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "76cae071-2cee-48e5-9465-e7c392ed135d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['HIPed_Stellite1/EDS_Point_Carbide1.txt',\n",
       " 'HIPed_Stellite1/EDS_Point_Carbide2.txt',\n",
       " 'HIPed_Stellite1/EDS_Point_Carbide3.txt',\n",
       " 'HIPed_Stellite1/EDS_Point_SolidSolution1.txt',\n",
       " 'HIPed_Stellite1/EDS_Point_SolidSolution2.txt',\n",
       " 'HIPed_Stellite1/EDS_Point_SolidSolution3.txt']"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "filenames = list_files_pathlib(\"HIPed_Stellite1\")\n",
    "filenames"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "b9825c82-42b0-47b2-afca-81466478f841",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>cps/eV</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>keV</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>-0.20</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>-0.19</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>-0.18</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>-0.17</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>-0.16</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20.23</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20.24</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20.25</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20.26</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20.27</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2048 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "        cps/eV\n",
       "keV           \n",
       "-0.20      0.0\n",
       "-0.19      0.0\n",
       "-0.18      0.0\n",
       "-0.17      0.0\n",
       "-0.16      0.0\n",
       "...        ...\n",
       " 20.23     0.0\n",
       " 20.24     0.0\n",
       " 20.25     0.0\n",
       " 20.26     0.0\n",
       " 20.27     0.0\n",
       "\n",
       "[2048 rows x 1 columns]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def import_commented_file_to_df(file_path):\n",
    "    \"\"\"\n",
    "    Imports a two-column, comma-separated file into a pandas DataFrame,\n",
    "    ignoring any lines that start with a '#' character.\n",
    "\n",
    "    Args:\n",
    "        file_path (str or file-like object): The full path to the data file \n",
    "                                             or a file-like object.\n",
    "        column_names (list of str): A list of names to assign to the columns.\n",
    "                                    The number of names should match the number\n",
    "                                    of columns in the data.\n",
    "\n",
    "    Returns:\n",
    "        pandas.DataFrame: A DataFrame containing the imported data. \n",
    "                          Returns an empty DataFrame if an error occurs \n",
    "                          (e.g., file not found).\n",
    "    \"\"\"\n",
    "\n",
    "    import pandas as pd\n",
    "\n",
    "    try:\n",
    "\n",
    "        df = pd.read_csv(\n",
    "            file_path,\n",
    "            header=None,\n",
    "            names=[\"keV\", \"cps/eV\"],\n",
    "            sep=',',\n",
    "            comment='#'\n",
    "        )\n",
    "\n",
    "        df.set_index(\"keV\", inplace=True)\n",
    "        \n",
    "        return df\n",
    "    except FileNotFoundError:\n",
    "        print(f\"Error: The file was not found at '{file_path}'\")\n",
    "        return pd.DataFrame() # Return an empty DataFrame on error\n",
    "    except Exception as e:\n",
    "        print(f\"An unexpected error occurred: {e}\")\n",
    "        return pd.DataFrame() # Return an empty DataFrame on error\n",
    "\n",
    "\n",
    "import_commented_file_to_df(filenames[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d5cb1098-cd15-491b-bad3-cbd915859179",
   "metadata": {},
   "outputs": [],
   "source": [
    "def import_eds_emsa(file_path: str | Path) -> tuple[pd.DataFrame | None, dict | None]:\n",
    "    \"\"\"\n",
    "    Parses an EMSA/MAS spectral data file robustly, handling common format errors\n",
    "    and structured multi-line metadata (e.g., ##OXINSTLABEL).\n",
    "\n",
    "    This function extracts:\n",
    "    1. Repeatable '##OXINSTLABEL' annotation lines into a 'ANNOTATIONS' dictionary.\n",
    "    2. Standard metadata from '#' lines into a dictionary.\n",
    "    3. Spectral data into a pandas DataFrame.\n",
    "\n",
    "    Args:\n",
    "        file_path (str or Path): The path to the EMSA file.\n",
    "\n",
    "    Returns:\n",
    "        tuple[pd.DataFrame | None, dict | None]: A tuple containing:\n",
    "            - A DataFrame of the spectral data.\n",
    "            - A dictionary of the header metadata, including annotations.\n",
    "        Returns (None, None) if a critical error occurs.\n",
    "    \"\"\"\n",
    "\n",
    "    import pandas as pd\n",
    "    import io\n",
    "    import warnings\n",
    "    from pathlib import Path\n",
    "    \n",
    "    metadata = {'ANNOTATIONS': {}}\n",
    "    data_lines = []\n",
    "    \n",
    "    try:\n",
    "        file_path = Path(file_path)\n",
    "        with file_path.open('r', encoding='utf-8', errors='ignore') as f:\n",
    "            \n",
    "            for i, line in enumerate(f, 1):\n",
    "                line = line.strip()\n",
    "                if not line: continue\n",
    "\n",
    "                # --- Handle element annotation ---\n",
    "                if line.startswith('##OXINSTLABEL'): \n",
    "                    \n",
    "                    parts = line.split(':', 1)\n",
    "                    if len(parts) != 2: continue # Skip malformed annotation lines\n",
    "                    \n",
    "                    # value_parts: e.g., ['27', '6.930', 'Co']\n",
    "                    value_parts = [p.strip() for p in parts[1].split(',')]\n",
    "                    \n",
    "                    if len(value_parts) == 3:\n",
    "                        try:\n",
    "                            atomic_num = int(value_parts[0])\n",
    "                            energy_kev = float(value_parts[1])\n",
    "                            element = value_parts[2]\n",
    "\n",
    "                            # Ensure the element entry exists in the ANNOTATIONS dict\n",
    "                            if element not in metadata['ANNOTATIONS']:\n",
    "                                metadata['ANNOTATIONS'][element] = []\n",
    "                            \n",
    "                            # Append the structured annotation\n",
    "                            metadata['ANNOTATIONS'][element].append(energy_kev)\n",
    "                            \n",
    "                        except (ValueError, IndexError) as e:\n",
    "                            warnings.warn(f\"Could not parse annotation on line {i}: '{line}'. Reason: {e}\", UserWarning)\n",
    "\n",
    "                # --- Handle standard single-line metadata ---\n",
    "                elif line.startswith('#'):\n",
    "                    \n",
    "                    parts = line[1:].split(':', 1)\n",
    "                    if len(parts) == 2:\n",
    "                        key = parts[0].strip().upper()\n",
    "                        value = parts[1].strip()\n",
    "                        metadata[key] = value\n",
    "\n",
    "                # --- Collect potential data lines ---        \n",
    "                else:\n",
    "                    data_lines.append(line)\n",
    "\n",
    "        # --- Sort the collected annotation lists numerically ---\n",
    "        for element in metadata['ANNOTATIONS']: metadata['ANNOTATIONS'][element].sort()        \n",
    "        \n",
    "        # --- Data Parsing and Validation ---\n",
    "        if not data_lines:\n",
    "            warnings.warn(f\"No data lines found in '{file_path.name}'.\", UserWarning)\n",
    "            return pd.DataFrame(), metadata\n",
    "\n",
    "        df = pd.read_csv(\n",
    "            io.StringIO('\\n'.join(data_lines)),\n",
    "            header=None,\n",
    "            sep=r'\\s*,\\s*',\n",
    "            engine='python',\n",
    "            names=['keV', 'counts'],\n",
    "            comment='#'\n",
    "        ).dropna()\n",
    "\n",
    "        df['keV'] = pd.to_numeric(df['keV'], errors='coerce')\n",
    "        df['counts'] = pd.to_numeric(df['counts'], errors='coerce')\n",
    "\n",
    "        original_rows = len(df)\n",
    "        df.dropna(inplace=True)\n",
    "        if len(df) < original_rows:\n",
    "            warnings.warn(f\"Removed {original_rows - len(df)} non-numeric data rows.\", UserWarning)\n",
    "\n",
    "        # Please warn if the datalines are missing data for whatever reason.\n",
    "        if 'NPOINTS' in metadata:\n",
    "            try:\n",
    "                try:\n",
    "                    npoints_meta = int(metadata['NPOINTS'].strip())\n",
    "                except ValueError:                \n",
    "                    npoints_meta = int(float(metadata['NPOINTS'].strip()))\n",
    "\n",
    "                if npoints_meta != len(df):\n",
    "                    warnings.warn(f\"Header #NPOINTS ({npoints_meta}) does not match actual data points ({len(df)}).\", UserWarning)\n",
    "            except ValueError:\n",
    "                warnings.warn(f\"#NPOINTS value '{metadata['NPOINTS']}' is not a valid integer.\", UserWarning)\n",
    "\n",
    "        df.set_index('keV', inplace=True)\n",
    "        return df, metadata\n",
    "\n",
    "    except FileNotFoundError:\n",
    "        warnings.warn(f\"Error: The file was not found at '{file_path}'\", UserWarning)\n",
    "        return None, None\n",
    "    except Exception as e:\n",
    "        warnings.warn(f\"An unexpected error occurred: {e}\", RuntimeWarning)\n",
    "        return None, None\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8b609f36-55a6-419c-8f18-162e53b1e3df",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "        counts\n",
      "keV           \n",
      "-0.20      0.0\n",
      "-0.19      0.0\n",
      "-0.18      0.0\n",
      "-0.17      0.0\n",
      "-0.16      0.0\n",
      "...        ...\n",
      " 20.23     0.0\n",
      " 20.24     0.0\n",
      " 20.25     0.0\n",
      " 20.26     0.0\n",
      " 20.27     0.0\n",
      "\n",
      "[2048 rows x 1 columns]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'ANNOTATIONS': {'Co': [0.678, 0.694, 0.776, 6.93, 7.65],\n",
       "  'W': [0.21,\n",
       "   0.222,\n",
       "   1.379,\n",
       "   1.775,\n",
       "   2.035,\n",
       "   7.388,\n",
       "   8.398,\n",
       "   8.724,\n",
       "   9.673,\n",
       "   9.962,\n",
       "   11.286,\n",
       "   11.608],\n",
       "  'Cr': [0.5, 0.573, 5.415, 5.947],\n",
       "  'C': [0.277]},\n",
       " 'FORMAT': 'EMSA/MAS Spectral Data File',\n",
       " 'VERSION': '1.0',\n",
       " 'TITLE': 'Spectrum 1',\n",
       " 'DATE': '21-JUL-2025',\n",
       " 'TIME': '12:52',\n",
       " 'OWNER': '',\n",
       " 'NPOINTS': '2048.0',\n",
       " 'NCOLUMNS': '1.0',\n",
       " 'XUNITS': 'keV',\n",
       " 'YUNITS': 'counts',\n",
       " 'DATATYPE': 'XY',\n",
       " 'XPERCHAN': '0.01',\n",
       " 'OFFSET': '-0.2',\n",
       " 'SIGNALTYPE': 'EDS',\n",
       " 'CHOFFSET': '20.0',\n",
       " 'LIVETIME': '30.0',\n",
       " 'REALTIME': '30.062997818',\n",
       " 'BEAMKV': '20.0',\n",
       " 'PROBECUR': '0.0',\n",
       " 'MAGCAM': '5000.0',\n",
       " 'XTILTSTGE': '0.0',\n",
       " 'AZIMANGLE': '0.0',\n",
       " 'ELEVANGLE': '35.0',\n",
       " 'XPOSITION MM': '-3.9563',\n",
       " 'YPOSITION MM': '1.9538',\n",
       " 'ZPOSITION MM': '14.8410',\n",
       " '#OXINSTPT': '2',\n",
       " '#OXINSTSTROB': '76.71',\n",
       " '#OXINSTELEMS': '27,74,24,6',\n",
       " 'SPECTRUM': 'Spectral Data Starts Here',\n",
       " 'ENDOFDATA': ''}"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eds_df, eds_metadata = import_eds_emsa(filenames[0])\n",
    "print(eds_df)\n",
    "eds_metadata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "03c73d3d-e4af-46cc-9844-b6392a0007be",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='keV'>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 21680 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "eds_df.plot()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "id": "5ef92a88-f39e-48ba-bbca-c6364a0a9b36",
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_eds_spectrum(\n",
    "    df: pd.DataFrame, \n",
    "    metadata: dict, \n",
    "    fig=None, \n",
    "    ax=None, \n",
    "    label=None,\n",
    "    color=None,\n",
    "):\n",
    "    \"\"\"\n",
    "    Plots the EDS spectrum and annotates elemental peaks on a given or new axis.\n",
    "\n",
    "    Args:\n",
    "        df (pd.DataFrame): DataFrame containing the spectral data with 'keV' as the index\n",
    "                           and 'counts' as a column.\n",
    "        metadata (dict): Dictionary containing metadata, including 'ANNOTATIONS'\n",
    "                         for elemental peaks.\n",
    "        fig (matplotlib.figure.Figure, optional): The figure to plot on. If None, a new\n",
    "                                                   figure is created. Defaults to None.\n",
    "        ax (matplotlib.axes.Axes, optional): The axes to plot on. If None, a new\n",
    "                                             axes object is created. Defaults to None.\n",
    "    \n",
    "    Returns:\n",
    "        tuple: A tuple containing the figure and axes objects used for plotting.\n",
    "    \"\"\"\n",
    "\n",
    "    import pandas as pd\n",
    "    import matplotlib.pyplot as plt\n",
    "    import warnings\n",
    "    from pathlib import Path\n",
    "    import io\n",
    "    \n",
    "    if df is None or df.empty:\n",
    "        print(\"DataFrame is empty or None. Cannot plot.\")\n",
    "        return\n",
    "\n",
    "    # If no axes are provided, create a new figure and axes\n",
    "    if ax is None or fig is None:\n",
    "        plt.style.use('seaborn-v0_8-whitegrid')\n",
    "        fig, ax = plt.subplots(figsize=(12, 7))\n",
    "        show_plot = True\n",
    "    else:\n",
    "        show_plot = False # Don't call plt.show() if using existing axes\n",
    "\n",
    "    if label is None: \n",
    "        label = \"EDS Spectrum\"\n",
    "\n",
    "    if color is None: \n",
    "        color = \"royalblue\"\n",
    "    \n",
    "\n",
    "    # Plot the primary spectrum data\n",
    "    ax.plot(\n",
    "        df.index, df['counts'], \n",
    "        label=label, color=color, linewidth=1,\n",
    "    )\n",
    "\n",
    "    # --- Labeling and Formatting ---\n",
    "    ax.set_xlabel('Energy (keV)', fontsize=12)\n",
    "    ax.set_ylabel('Counts', fontsize=12)\n",
    "    ax.tick_params(axis='both', which='major', labelsize=10)\n",
    "    \n",
    "    # Set a lower limit for y-axis to avoid cutting off baseline\n",
    "    ax.set_ylim(bottom=0, top=90)\n",
    "    ax.set_xlim(left=0, right=12)\n",
    "\n",
    "    # Create a legend, avoiding duplicate labels\n",
    "    handles, labels = ax.get_legend_handles_labels()\n",
    "    by_label = dict(zip(labels, handles))\n",
    "    ax.legend(by_label.values(), by_label.keys(), fontsize=10)\n",
    "\n",
    "    if show_plot:\n",
    "        plt.tight_layout()\n",
    "        plt.show()\n",
    "\n",
    "    return fig, ax\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "id": "3f9428e6-2da2-456f-8564-f9cadde7c4f7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 218476 characters]",
      "text/plain": [
       "<Figure size 1800x1200 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import warnings\n",
    "from pathlib import Path\n",
    "import io\n",
    "\n",
    "plt.style.use('seaborn-v0_8-whitegrid')\n",
    "fig, ax = plt.subplots(figsize=(6, 4), dpi=300)\n",
    "\n",
    "# --- Read and Plot the data ---\n",
    "\n",
    "eds_dfs = [None for filename in filenames]\n",
    "eds_metadatas = [None for filename in filenames]\n",
    "\n",
    "for i, filename in enumerate(filenames[:3]):\n",
    "    eds_df, eds_metadata = import_eds_emsa(filename)\n",
    "    if eds_df is not None:\n",
    "        eds_dfs[i] = eds_df\n",
    "        eds_metadatas[i] = eds_metadata\n",
    "        plot_eds_spectrum(eds_df, eds_metadata, fig=fig, ax=ax, label=\"Carbide\", color=\"royalblue\")\n",
    "\n",
    "for i, filename in enumerate(filenames[3:]):\n",
    "    eds_df, eds_metadata = import_eds_emsa(filename)\n",
    "    if eds_df is not None:\n",
    "        eds_dfs[i+3] = eds_df\n",
    "        eds_metadatas[i+3] = eds_metadata\n",
    "        plot_eds_spectrum(eds_df, eds_metadata, fig=fig, ax=ax, label=\"Solid Solution\", color=\"firebrick\")\n",
    "\n",
    "# --- Annotate Elemental Peaks ---\n",
    "#for df, metadata in zip(eds_dfs, eds_metadatas):\n",
    "#    if 'ANNOTATIONS' in eds_metadata and eds_metadata['ANNOTATIONS']:           \n",
    "\n",
    "# Find unique elements\n",
    "annotations = [meta['ANNOTATIONS'] for meta in eds_metadatas]\n",
    "nested_list = [list(annotation.keys()) for annotation in annotations]\n",
    "unique_elements = list(set(item for sublist in nested_list for item in sublist))\n",
    "\n",
    "\n",
    "    \n",
    "maximum_profile = np.max([np.interp(np.arange(0,20,0.05), eds_df.index, eds_df['counts']) for eds_df in eds_dfs], axis=0)\n",
    "\n",
    "lines = {}\n",
    "\n",
    "lines[\"C\"] = [\n",
    "    (r'K$\\alpha_1$', 0.277, 10)                            ##OXINSTLABEL: 6, 0.277, C\n",
    "]\n",
    "\n",
    "\n",
    "\n",
    "##OXINSTLABEL: 24, 0.500, Cr\n",
    "lines[\"Cr\"] = [\n",
    "    (r'K$\\alpha_1$, K$\\alpha_2$', 5.41472, 63),            ##OXINSTLABEL: 24, 5.415, Cr\n",
    "    (None, 5.405509, 63), \n",
    "    (r'K$\\beta_1$',  5.94671, 14),                         ##OXINSTLABEL: 24, 5.947, Cr\n",
    "    (r'L$\\alpha_1$, L$\\alpha_2$, L$\\beta_1$', 0.5728, 20), ##OXINSTLABEL: 24, 0.573, Cr\n",
    "    (None, 0.5728, 20), \n",
    "    (None, 0.5828, 20), \n",
    "]\n",
    "\n",
    "\n",
    "\n",
    "##OXINSTLABEL: 27, 0.694, Co\n",
    "##OXINSTLABEL: 27, 0.678, Co\n",
    "lines[\"Co\"] = [\n",
    "    (r'K$\\alpha_1$, $\\alpha_2$', 6.93032, 25),              ##OXINSTLABEL: 27, 6.930, Co\n",
    "    (None, 6.91530, 25),     \n",
    "    (r'K$\\beta_1$',  7.64943, 10),                          ##OXINSTLABEL: 27, 7.650, Co    \n",
    "    (r'L$\\alpha_1$, L$\\alpha_2$, L$\\beta_1$',  0.7762, 25), ##OXINSTLABEL: 27, 0.776, Co\n",
    "    (None,  0.7762, 25),     \n",
    "    (None,  0.7914, 25), \n",
    "]\n",
    "\n",
    "\n",
    "\n",
    "##OXINSTLABEL: 74, 8.724, W\n",
    "\n",
    "##OXINSTLABEL: 74, 11.608, W\n",
    "##OXINSTLABEL: 74, 7.388, W\n",
    "\n",
    "##OXINSTLABEL: 74, 2.035, W\n",
    "##OXINSTLABEL: 74, 1.379, W\n",
    "##OXINSTLABEL: 74, 0.222, W\n",
    "##OXINSTLABEL: 74, 0.210, W\n",
    "lines[\"W\"] = [\n",
    "    (r'K$\\alpha_1$', 59.31824, 20), \n",
    "    (r'K$\\alpha_2$', 57.9817, 20), \n",
    "    (r'K$\\beta_1$',  67.2443, 20),         \n",
    "    (r'L$\\alpha_1$, L$\\alpha_2$', 8.3976, 10), ##OXINSTLABEL: 74, 8.398, W\n",
    "    (None, 8.3352, 10), \n",
    "    (r'L$\\beta_1$',  9.67235, 5),              ##OXINSTLABEL: 74, 9.673, W\n",
    "    (r'L$\\beta_2$',  9.9615, 5),               ##OXINSTLABEL: 74, 9.962, W\n",
    "    (r'L$\\gamma_1$',  11.2859, 5),             ##OXINSTLABEL: 74, 11.286, W\n",
    "    (r'M$\\alpha_1$',  1.7754, 41),             ##OXINSTLABEL: 74, 1.775, W\n",
    "] \n",
    "\n",
    "# Iterate through your 'lines' dictionary to plot each element's lines\n",
    "for element, spectral_lines in lines.items():\n",
    "    for line_name, energy, y_height in spectral_lines:\n",
    "        # Only plot lines that are within the energy range of your spectrum\n",
    "        if 0 <= energy < 15:\n",
    "                        \n",
    "            # Plot the vertical line from the x-axis to the spectrum\n",
    "            ax.plot(\n",
    "                [energy, energy], \n",
    "                [0, y_height], \n",
    "                linestyle='--', color='black', linewidth=0.5)\n",
    "\n",
    "            # Plot the triangle marker at the top of the line\n",
    "            ax.plot(\n",
    "                energy, \n",
    "                y_height, \n",
    "                marker='^', markersize=4, color='red', markeredgecolor='black')\n",
    "\n",
    "            if line_name is not None:\n",
    "                # Add the text label for the element and line type\n",
    "                ax.text(energy, \n",
    "                    y_height+1.5, \n",
    "                    f'{element} {line_name}', rotation=90,\n",
    "                    verticalalignment='bottom', horizontalalignment='center', fontsize=8)\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4312541b-6f43-4977-ab24-ac496effdd49",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24023520-d1ae-4c33-ae0b-d66fbfdb585e",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:.conda-EIS]",
   "language": "python",
   "name": "conda-env-.conda-EIS-py"
  },
  "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.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
