{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "bed4637d-8e0c-42b4-9331-8a39ca2381a6",
      "metadata": {},
      "source": [
        "Copyright (c) 2025 Mitsuru Ohno  \n",
        "Use of this source code is governed by a BSD-3-style  \n",
        "license that can be found in the LICENSE file.  "
      ]
    },
    {
      "cell_type": "markdown",
      "id": "911d53c0",
      "metadata": {},
      "source": [
        "## 当ノートブックのワークフロー  \n",
        "速度定数がすべて既知で、初期濃度を与えた場合、各化学種の経時変化をシミュレーションする場合の事例。\n",
        "ただし、引用文献中の実験による化学種の濃度の経時変化もわかっており、シミュレーション結果にこれを重ね書きした。  \n",
        "04_example_script_classExpDataFitSci_ref3.ipynbでは、同じデータからフィッティングにより速度定数を求めており、文献記載の値との比較も可能。  \n",
        "1. csvに書き込んだ反応式を読み込む。ただし速度定数はすべて既知とする  \n",
        "2. RxnIVPsolv(\"sample_data.csv\")でインスタンス化し、化学種ごとの微分型の反応速度式を作成する  \n",
        "3. 作成した微分方程式を、数値解析可能な形式にする  \n",
        "4. 化学種ごとの濃度の経時変化を求める。数値積分では、get_ode_system()で必要なオブジェクトを取得する。   \n",
        "5. matplotlibで結果をプロットし、経時変化を図示する  \n",
        "\n",
        "## 引用文献  \n",
        "3) Kentaro TAMAKI, Seiichi YADA, Shiro KUDO, Reaction of 3- (1-Naphthyloxy) -2-hydroxy-1-propyltosylate with Isopropylamine, Journal of Synthetic Organic Chemistry, Japan, 1972, Volume 30, Issue 2, Pages 175-178, Released on J-STAGE November 13, 2009, Online ISSN 1883-6526, Print ISSN 0037-9980, https://doi.org/10.5059/yukigoseikyokaishi.30.175, https://www.jstage.jst.go.jp/article/yukigoseikyokaishi1943/30/2/30_2_175/_article/-char/en  \n",
        "\n",
        "- 文献中表1 アセトニトリル溶媒のデータ、および式 [1] の反応式を用いた。  \n",
        "- 併発反応と逐次反応が共存する系を例示した。  "
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f793b762-0cca-45f9-ad15-a0c092ac36e6",
      "metadata": {},
      "source": [
        "## 反応式を記載したcsvファイルを指定する  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "92b6caf1-fbe4-47c8-9bf7-15dc223b3b28",
      "metadata": {},
      "outputs": [],
      "source": [
        "file_path = './sample_data/ref3/sample_rxn_ref3AN_litk.csv'  # CSVファイルのパスを指定"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "95324112-077e-4f27-9529-2a86aaa179f2",
      "metadata": {},
      "source": [
        "## 反応速度式をscipy.integrate.solve_ivpで処理できる連立微分方程式にする  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "75e2680b-f29a-4109-8707-97deb1943716",
      "metadata": {},
      "outputs": [],
      "source": [
        "from dataclasses import dataclass, field\n",
        "from typing import Optional\n",
        "\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "import matplotlib.pyplot as plt\n",
        "from scipy.integrate import solve_ivp\n",
        "\n",
        "from rxnfit.build_ode import RxnODEbuild\n",
        "from rxnfit.solv_ode import SolverConfig, RxnODEsolver\n",
        "from rxnfit.expdata_reader import expdata_read"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "aeb55f6f-83d3-4689-9921-c0f9c3c7216f",
      "metadata": {},
      "outputs": [],
      "source": [
        "builded_rxnode = RxnODEbuild(file_path)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "dc5a5d88-0b5d-4f67-bd1c-81209bae4d0a",
      "metadata": {
        "scrolled": true
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "number of species: 3\n",
            "unique species: ['Tos', 'Prop', 'Nep']\n",
            "rate constant: {'k1': 0.004, 'k2': 0.009, 'k3': 0.02}\n",
            "\n",
            "=== debug info ===\n",
            "Successfully created function for Tos with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Prop with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Nep with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "order of args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "system of ODE: {'Tos': '-1/1*k1*Tos(t)-1/1*k2*Tos(t)', 'Prop': '1/1*k1*Tos(t)+1/1*k3*Nep(t)', 'Nep': '1/1*k2*Tos(t)-1/1*k3*Nep(t)'}\n"
          ]
        }
      ],
      "source": [
        "builded_rxnode.get_ode_info(debug_info=True)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "83f4a6f4-a58f-4731-8b63-51cbefebba72",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'k1': 0.004, 'k2': 0.009, 'k3': 0.02}"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "builded_rxnode.rate_consts_dict"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ffd9610e-40f3-40b1-aeee-2292e86b6a1c",
      "metadata": {},
      "source": [
        "## 数値積分を実行する  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "7f08357f-a23e-4356-8345-0b500760b15b",
      "metadata": {},
      "outputs": [],
      "source": [
        "# get_ode_infoの出力を参照して、初期値等の入力項目を渡す\n",
        "config = SolverConfig(\n",
        "    y0 = [0.3, 0.0, 0.0], # 初期濃度（必須）\n",
        "    t_span=(0, 240),         # 時間範囲（必須）\n",
        "    # t_eval: Optional[np.ndarray] = field(default=None),  # 任意\n",
        "    method = \"RK45\",  # 任意\n",
        "    rtol = 1e-6,    # 任意    \n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "cb900316-1b10-41d2-8254-0d1f0eef37f7",
      "metadata": {},
      "outputs": [],
      "source": [
        "# 基本的な数値積分 -インスタンス化-\n",
        "solved_rxnode = RxnODEsolver(builded_rxnode, config)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "f1797ffc-0371-489d-8baf-3646dec8cc61",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Successfully created function for Tos with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Prop with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Nep with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Tos with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Prop with args: ['t', 'Tos', 'Prop', 'Nep']\n",
            "Successfully created function for Nep with args: ['t', 'Tos', 'Prop', 'Nep']\n"
          ]
        }
      ],
      "source": [
        "ode_construct, sol = solved_rxnode.solve_system()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b39b9653",
      "metadata": {},
      "source": [
        "## 経時変化の実験データを読み込み　　\n",
        "### データフレーム化  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "1427a075-40ba-4760-bfb6-71708b3dd60c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[([array([ 15,  30,  60, 120, 240]),\n",
              "   array([ 15,  30,  60, 120, 240]),\n",
              "   array([ 15,  30,  60, 120, 240])],\n",
              "  [array([0.24, 0.22, 0.13, 0.04, 0.01]),\n",
              "   array([0.03 , 0.06 , 0.07 , 0.03 , 0.001]),\n",
              "   array([0.02, 0.05, 0.11, 0.22, 0.27])])]"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "file_path_data = './sample_data/ref3/sample_timecourse_ref3AN.csv' # データファイルのパス\n",
        "df1 = pd.read_csv(file_path_data)\n",
        "\n",
        "expdata_read([df1,])  # 複数データフレームのリストを渡すとまとめて読み込み可能"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "e182d817",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "=== Time-course plot ===\n"
          ]
        },
        {
          "data": {
            "image/png": "[encoded data, 47776 characters]",
            "text/plain": [
              "<Figure size 600x400 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "\n",
            "=== Concentration at the final time point ===\n",
            "Dataset 1:\n",
            "  Tos: 0.013247\n",
            "  Prop: 0.272895\n",
            "  Nep: 0.013858\n"
          ]
        }
      ],
      "source": [
        "solved_rxnode.solution_plot(expdata_df=df1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "72179a97",
      "metadata": {},
      "source": [
        "## 微分方程式の解を数値として表示する  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "f2d472f1",
      "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>min</th>\n",
              "      <th>Tos</th>\n",
              "      <th>Prop</th>\n",
              "      <th>Nep</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>0.000000</td>\n",
              "      <td>0.300000</td>\n",
              "      <td>0.000000</td>\n",
              "      <td>0.000000</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>0.083722</td>\n",
              "      <td>0.299674</td>\n",
              "      <td>0.000101</td>\n",
              "      <td>0.000226</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>0.920946</td>\n",
              "      <td>0.296430</td>\n",
              "      <td>0.001121</td>\n",
              "      <td>0.002449</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>9.293177</td>\n",
              "      <td>0.265860</td>\n",
              "      <td>0.012611</td>\n",
              "      <td>0.021528</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>24.572383</td>\n",
              "      <td>0.217967</td>\n",
              "      <td>0.037748</td>\n",
              "      <td>0.044286</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>5</th>\n",
              "      <td>40.298761</td>\n",
              "      <td>0.177665</td>\n",
              "      <td>0.066189</td>\n",
              "      <td>0.056146</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>6</th>\n",
              "      <td>57.136095</td>\n",
              "      <td>0.142738</td>\n",
              "      <td>0.096765</td>\n",
              "      <td>0.060497</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>7</th>\n",
              "      <td>75.172602</td>\n",
              "      <td>0.112904</td>\n",
              "      <td>0.127702</td>\n",
              "      <td>0.059394</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>8</th>\n",
              "      <td>94.583146</td>\n",
              "      <td>0.087725</td>\n",
              "      <td>0.157661</td>\n",
              "      <td>0.054615</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>9</th>\n",
              "      <td>115.583821</td>\n",
              "      <td>0.066766</td>\n",
              "      <td>0.185615</td>\n",
              "      <td>0.047619</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>10</th>\n",
              "      <td>138.440100</td>\n",
              "      <td>0.049604</td>\n",
              "      <td>0.210819</td>\n",
              "      <td>0.039577</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>11</th>\n",
              "      <td>163.498740</td>\n",
              "      <td>0.035813</td>\n",
              "      <td>0.232803</td>\n",
              "      <td>0.031384</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>12</th>\n",
              "      <td>191.220604</td>\n",
              "      <td>0.024976</td>\n",
              "      <td>0.251333</td>\n",
              "      <td>0.023691</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>13</th>\n",
              "      <td>222.229161</td>\n",
              "      <td>0.016690</td>\n",
              "      <td>0.266381</td>\n",
              "      <td>0.016929</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>14</th>\n",
              "      <td>240.000000</td>\n",
              "      <td>0.013247</td>\n",
              "      <td>0.272895</td>\n",
              "      <td>0.013858</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "           min       Tos      Prop       Nep\n",
              "0     0.000000  0.300000  0.000000  0.000000\n",
              "1     0.083722  0.299674  0.000101  0.000226\n",
              "2     0.920946  0.296430  0.001121  0.002449\n",
              "3     9.293177  0.265860  0.012611  0.021528\n",
              "4    24.572383  0.217967  0.037748  0.044286\n",
              "5    40.298761  0.177665  0.066189  0.056146\n",
              "6    57.136095  0.142738  0.096765  0.060497\n",
              "7    75.172602  0.112904  0.127702  0.059394\n",
              "8    94.583146  0.087725  0.157661  0.054615\n",
              "9   115.583821  0.066766  0.185615  0.047619\n",
              "10  138.440100  0.049604  0.210819  0.039577\n",
              "11  163.498740  0.035813  0.232803  0.031384\n",
              "12  191.220604  0.024976  0.251333  0.023691\n",
              "13  222.229161  0.016690  0.266381  0.016929\n",
              "14  240.000000  0.013247  0.272895  0.013858"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df_solvd = solved_rxnode.to_dataframe_list(time_column_name=\"min\")[0]\n",
        "df_solvd"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0c835b44",
      "metadata": {},
      "source": [
        "## 与えた速度定数で解と、実験値の残渣二乗和    \n",
        "実験の時間で再積分して残差二乗和（表示あり）  "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "3e0adbb6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Residual sum of squares: 0.00248538  R²: 0.973045\n"
          ]
        }
      ],
      "source": [
        "metrics = solved_rxnode.eval_fit_metrics(df1)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "venv312",
      "language": "python",
      "name": "python3"
    },
    "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.12.10"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}
