{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "f29e7db4-4e34-4a76-8a11-e7d0356ff99d",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import scipy.io as sio\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d4e9d384-f758-443c-ac3f-c83dff69827b",
   "metadata": {},
   "outputs": [],
   "source": [
    "rootdir = '/raid1/xdchen/collaborations/Pei/NN_type/'\n",
    "datadir = rootdir + 'data/'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d85467d-c641-4dc0-9c4e-560a397af2fd",
   "metadata": {},
   "source": [
    "## 1. test individual codes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "76f24c12-bdfb-4b75-8cfa-1b56f57b5bb4",
   "metadata": {},
   "outputs": [],
   "source": [
    "figsize = (6, 6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a53f7d0e-7333-4da0-b4b7-35aa1c16522f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- 1. Linear Case ---\n",
    "num_fig = 110\n",
    "figname = f'plots/{num_fig}_linear.png'\n",
    "\n",
    "range_x = 1\n",
    "delta_x = 0.01\n",
    "x = np.arange(-range_x, range_x + delta_x, delta_x)\n",
    "y = x\n",
    "\n",
    "fig1 = plt.figure(figsize=figsize)\n",
    "\n",
    "plt.plot(x, y)\n",
    "\n",
    "fig1.savefig(figname, dpi=600)\n",
    "\n",
    "plt.show()\n",
    "plt.close()\n",
    "del(fig1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2adedf7b-b5c3-4151-aa9c-09ed70e19201",
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- 2. Deadspace ---\n",
    "# Using \"Set 4\" parameters as per the active code in the MATLAB snippet\n",
    "range_x = 1\n",
    "delta_x = 0.01\n",
    "ratio = 0.1\n",
    "num_fig = 124\n",
    "figname = f'plots/{num_fig}_deadspace.png'\n",
    "\n",
    "range_y = range_x\n",
    "\n",
    "y_right = np.arange(0, range_y + delta_x, delta_x)\n",
    "x_right = np.linspace(range_x * ratio, range_x, len(y_right))\n",
    "\n",
    "y_left = np.arange(-range_y, 0 + delta_x, delta_x)\n",
    "x_left = np.linspace(-range_x, -range_x * ratio, len(y_left))\n",
    "\n",
    "# Middle section (zeros)\n",
    "x_middle = np.arange(-range_x * ratio + delta_x, range_x * ratio, delta_x)\n",
    "y_middle = np.zeros_like(x_middle)\n",
    "\n",
    "x_total = np.concatenate([x_left, x_middle, x_right])\n",
    "y_total = np.concatenate([y_left, y_middle, y_right])\n",
    "\n",
    "fig2 = plt.figure(figsize=figsize)\n",
    "plt.plot(x_total, y_total)\n",
    "fig2.savefig(figname, dpi=600)\n",
    "\n",
    "plt.show()\n",
    "plt.close()\n",
    "del(fig2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e84af15-650e-4f80-a9c1-097810bb9130",
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- 3. Multi-slope ---\n",
    "num_fig = 130\n",
    "figname = f'plots/{num_fig}_multislope.png'\n",
    "\n",
    "range_x = 1\n",
    "delta_x = 0.01\n",
    "ratio_x = 0.5\n",
    "ratio_y = 0.25\n",
    "range_y = range_x * 2\n",
    "\n",
    "y_right = np.arange(range_y * ratio_y, range_y + delta_x, delta_x)\n",
    "x_right = np.linspace(range_x * ratio_x, range_x, len(y_right))\n",
    "\n",
    "y_left = np.arange(-range_y, -range_y * ratio_y + delta_x, delta_x)\n",
    "x_left = np.linspace(-range_x, -range_x * ratio_x, len(y_left))\n",
    "\n",
    "x_middle = np.arange(-range_x * ratio_x + delta_x, range_x * ratio_x, delta_x)\n",
    "y_middle = np.linspace(-range_y * ratio_y + delta_x, range_y * ratio_y - delta_x, len(x_middle))\n",
    "\n",
    "x_total = np.concatenate([x_left, x_middle, x_right])\n",
    "y_total = np.concatenate([y_left, y_middle, y_right])\n",
    "\n",
    "fig3 = plt.figure(figsize=figsize)\n",
    "plt.plot(x_total, y_total)\n",
    "\n",
    "#fig3.savefig(figname, dpi=600)\n",
    "\n",
    "plt.show()\n",
    "plt.close()\n",
    "del(fig3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "32381e5d-e29e-4069-9038-45c2fd4583b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "def sigmoid_matlab(a, sigma, rho):\n",
    "    \"\"\"\n",
    "    Equivalent to the provided MATLAB sigmoid function.\n",
    "    y = 1 / (1 + exp(-(a + sigma) / rho))\n",
    "    \"\"\"\n",
    "    # NumPy handles scalar addition to arrays automatically\n",
    "    return 1.0 / (1.0 + np.exp(-(a + sigma) / rho))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "f19d51fb-dd85-4671-b36f-9a9e0a10692d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_hardsoft_cases():\n",
    "    # input2: column 1 is 2 to 21, column 2 is zeros\n",
    "    input2 = np.zeros((200, 2))\n",
    "    input2[:, 0] = np.arange(2, 22, 0.1)\n",
    "    \n",
    "    # input1: column 1 is same as input2, column 2 is -1s\n",
    "    input1 = np.zeros((200, 2))\n",
    "    input1[:, 0] = input2[:, 0].copy()\n",
    "    input1[:, 1] = -1.0\n",
    "    \n",
    "    input3 = np.arange(1, 21, 0.1).reshape(-1, 1)\n",
    "    input4 = input3.copy()\n",
    "    \n",
    "    # Apply the specific starting adjustments\n",
    "    input2[0, 0] = 0.02\n",
    "    input1[0, 0] = 0.02\n",
    "    \n",
    "    x = np.linspace(0, 1, 101)\n",
    "    IW1 = input1[:, 0]\n",
    "    b1  = input1[:, 1]\n",
    "    IW2 = input2[:, 0]\n",
    "    b2  = input2[:, 1]\n",
    "\n",
    "\n",
    "    sample_data = np.zeros((4, 101, 200))\n",
    "\n",
    "    # --- mID = 0 (MATLAB 1) ---\n",
    "    for ii in range(len(input1)):\n",
    "        numer = sigmoid_matlab(IW1[ii] * x, IW1[ii] * b1[ii], 1) - \\\n",
    "                sigmoid_matlab(IW1[ii] * 0, IW1[ii] * b1[ii], 1)\n",
    "        denom = sigmoid_matlab(IW1[ii] * 1, IW1[ii] * b1[ii], 1) - \\\n",
    "                sigmoid_matlab(IW1[ii] * 0, IW1[ii] * b1[ii], 1)\n",
    "        sample_data[0, :, ii] = numer / denom\n",
    "    \n",
    "    # --- mID = 1 (MATLAB 2) ---\n",
    "    for ii in range(len(input1)):\n",
    "        # MATLAB: 1-flip(x.^(1/input3(ii)))\n",
    "        # Note: np.flip reverses the array\n",
    "        val = x ** (1.0 / input3[ii])\n",
    "        sample_data[1, :, ii] = 1.0 - np.flip(val)\n",
    "    \n",
    "    # --- mID = 2 (MATLAB 3) ---\n",
    "    for ii in range(len(input2)):\n",
    "        numer = sigmoid_matlab(IW2[ii] * x, b2[ii], 1) - 0.5\n",
    "        denom = sigmoid_matlab(IW2[ii] * 1, b2[ii], 1) - 0.5\n",
    "        sample_data[2, :, ii] = numer / denom\n",
    "    \n",
    "    # --- mID = 3 (MATLAB 4) ---\n",
    "    for ii in range(len(input2)):\n",
    "        sample_data[3, :, ii] = x ** (1.0 / input4[ii])\n",
    "\n",
    "    outX = np.zeros((760, 201))\n",
    "    outy = np.zeros(760)\n",
    "    for x in np.arange(4):\n",
    "        for y in np.arange(190):\n",
    "            outX[(x*190+y), 100:201] = sample_data[x,:,y+10]\n",
    "            outX[(x*190+y), 0:101] = sample_data[x,:,y+10][::-1]*(-1)\n",
    "            outy[x*190+y] = x+4\n",
    "    \n",
    "    return outX, outy"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd52c2fe-e5db-4b75-902b-7d3312faa571",
   "metadata": {},
   "source": [
    "## 2. construct functions for each type\n",
    "\n",
    "Also, interpolate them to 201 [-1,1] sample"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "cbbf276f-f4e6-4259-bdc2-09c74958f40e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def interploate_to_Npt(in_x, in_y, in_N=201):\n",
    "    out_x = np.linspace(-1, 1, in_N)\n",
    "    #print(out_x)\n",
    "    outdata = np.interp(out_x, in_x, in_y)\n",
    "    return outdata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "6b5f1cdc-9de1-4809-9e20-4d6cd47ff42b",
   "metadata": {},
   "outputs": [],
   "source": [
    "def crt_linear_data(my_range_x=1, my_delta_x=0.01):\n",
    "\n",
    "    x = np.arange(-my_range_x, my_range_x + my_delta_x, my_delta_x)\n",
    "    y = x\n",
    "    outdata = interploate_to_Npt(x, y)\n",
    "\n",
    "    return outdata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "18841c46-d42f-4c65-84b4-39aca72abed7",
   "metadata": {},
   "outputs": [],
   "source": [
    "def crt_deadspace_data(my_range_x=1, my_delta_x=0.01, my_ratio=0.5):\n",
    "\n",
    "    my_range_y = my_range_x\n",
    "\n",
    "    my_y_right = np.arange(0, my_range_y + my_delta_x, my_delta_x)\n",
    "    my_x_right = np.linspace(my_range_x * my_ratio, my_range_x, len(my_y_right))\n",
    "    \n",
    "    my_y_left = np.arange(-my_range_y, 0 + my_delta_x, my_delta_x)\n",
    "    my_x_left = np.linspace(-my_range_x, -my_range_x * my_ratio, len(my_y_left))\n",
    "    \n",
    "    # Middle section (zeros)\n",
    "    my_x_middle = np.arange(-my_range_x * my_ratio + my_delta_x, my_range_x * my_ratio, my_delta_x)\n",
    "    my_y_middle = np.zeros_like(my_x_middle)\n",
    "    \n",
    "    my_x_total = np.concatenate([my_x_left, my_x_middle, my_x_right])\n",
    "    my_y_total = np.concatenate([my_y_left, my_y_middle, my_y_right])\n",
    "\n",
    "    outdata = interploate_to_Npt(my_x_total, my_y_total)\n",
    "    \n",
    "    return outdata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "780b19fa-e64c-475b-b39f-9ddb03341c44",
   "metadata": {},
   "outputs": [],
   "source": [
    "def crt_multislope_data(my_range_x=1, my_delta_x=0.01, my_ratio_x=0.5, my_ratio_y=0.25):\n",
    "\n",
    "    my_range_y = my_range_x * 2\n",
    "    \n",
    "    my_y_right = np.arange(my_range_y * my_ratio_y, my_range_y + my_delta_x, my_delta_x)\n",
    "    my_x_right = np.linspace(my_range_x * my_ratio_x, my_range_x, len(my_y_right))\n",
    "    \n",
    "    my_y_left = np.arange(-my_range_y, -my_range_y * my_ratio_y + my_delta_x, my_delta_x)\n",
    "    my_x_left = np.linspace(-my_range_x, -my_range_x * my_ratio_x, len(my_y_left))\n",
    "    \n",
    "    my_x_middle = np.arange(-my_range_x * my_ratio_x + my_delta_x, my_range_x * my_ratio_x, my_delta_x)\n",
    "    my_y_middle = np.linspace(-my_range_y * my_ratio_y + my_delta_x, my_range_y * my_ratio_y - my_delta_x, len(my_x_middle))\n",
    "    \n",
    "    my_x_total = np.concatenate([my_x_left, my_x_middle, my_x_right])\n",
    "    my_y_total = np.concatenate([my_y_left, my_y_middle, my_y_right])\n",
    "\n",
    "    outdata = interploate_to_Npt(my_x_total, my_y_total)\n",
    "    \n",
    "    return outdata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "3c61bac2-294c-43f7-b308-5fb4043611c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "def crt_saturation_data(my_ratio_x=0.5):\n",
    "    my_xdata = np.arange(-100, 100.1)/100\n",
    "    my_ydata = np.ones(201)-9999\n",
    "    my_sindex = np.argwhere(my_xdata==-1*my_ratio_x)[0][0]\n",
    "    my_eindex = np.argwhere(my_xdata==my_ratio_x)[0][0]\n",
    "    my_ydata[0:my_sindex] = -1\n",
    "    my_ydata[my_eindex:201] = 1\n",
    "    my_npts = my_eindex-my_sindex\n",
    "    my_ydata[my_sindex:my_eindex] = np.linspace(-1, 1, my_npts)\n",
    "    return my_ydata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "1f456d2e-dfe0-498c-aab1-5fa906d01974",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7fe168892a70>]"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#plt.plot(np.linspace(-1, 1, 201), crt_linear_data())\n",
    "#plt.plot(np.linspace(-1, 1, 201), crt_deadspace_data(my_ratio=0.6))\n",
    "#plt.plot(np.linspace(-1, 1, 201), crt_multislope_data(my_ratio_x=0.25, my_ratio_y=0.9))\n",
    "plt.plot(np.linspace(-1, 1, 201), crt_saturation_data(0.95))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be7c370e-6d52-4d0a-b677-74806ef8cd16",
   "metadata": {},
   "source": [
    "## 3. construct full dataset for DL"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "850f0c4f-211a-4a34-8f0e-15a6d865490e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Linear sample: 100\n"
     ]
    }
   ],
   "source": [
    "# linear, type 1\n",
    "n1 = 100\n",
    "\n",
    "Xdata1 = np.zeros((n1, 201))\n",
    "ydata1 = np.zeros((n1))\n",
    "\n",
    "# fill the data\n",
    "for i in np.arange(n1):\n",
    "    Xdata1[i] = crt_linear_data(1, 0.01)\n",
    "\n",
    "ydata1[:] = 1\n",
    "\n",
    "print('Linear sample: %d' % (Xdata1.shape[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "a02268bf-4c19-49b4-bf54-6a8e84ec5fd0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Deadspace sample: 170\n"
     ]
    }
   ],
   "source": [
    "n2 = 100\n",
    "\n",
    "Xdata2 = np.zeros((1000, 201))\n",
    "ydata2 = np.zeros((1000))\n",
    "\n",
    "count = 0\n",
    "for my_ratio in np.arange(0.1, 0.95, 0.005):\n",
    "    Xdata2[count] = crt_deadspace_data(my_ratio=my_ratio)\n",
    "    count = count+1\n",
    "\n",
    "ydata2[:] = 2\n",
    "\n",
    "Xdata2 = Xdata2[0:count]\n",
    "ydata2 = ydata2[0:count]\n",
    "\n",
    "print('Deadspace sample: %d' % (Xdata2.shape[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "a000a333-a2c3-472e-ae1e-39aae7d304bd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Multislope sample: 264\n"
     ]
    }
   ],
   "source": [
    "n3 = 100\n",
    "\n",
    "Xdata3 = np.zeros((10000, 201))\n",
    "ydata3 = np.zeros((10000))\n",
    "\n",
    "count = 0\n",
    "for my_ratio_x in np.arange(0.1, 0.901, 0.05):\n",
    "    for my_ratio_y in np.arange(0.1, 0.901, 0.05):\n",
    "        if np.abs(my_ratio_x - my_ratio_y)>0.05:\n",
    "            Xdata3[count] = crt_multislope_data(my_ratio_x=my_ratio_x, my_ratio_y=my_ratio_y)\n",
    "            count = count + 1\n",
    "\n",
    "ydata3[:] = 3\n",
    "\n",
    "Xdata3 = Xdata3[0:count]\n",
    "ydata3 = ydata3[0:count]\n",
    "\n",
    "print('Multislope sample: %d' % (Xdata3.shape[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "7fe9ded1-1abc-4911-85ba-1cdd7a9e4184",
   "metadata": {},
   "outputs": [],
   "source": [
    "db_X, db_y = generate_hardsoft_cases()\n",
    "\n",
    "Xdata4, ydata4 = db_X[0:190], db_y[0:190]\n",
    "Xdata5, ydata5 = db_X[190:380], db_y[190:380]\n",
    "Xdata6, ydata6 = db_X[380:570], db_y[380:570]\n",
    "Xdata7, ydata7 = db_X[570:760], db_y[570:760]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "301e8ce3-3215-4233-b030-9057309df81f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Saturation sample: 91\n"
     ]
    }
   ],
   "source": [
    "n3 = 100\n",
    "\n",
    "Xdata8 = np.zeros((10000, 201))\n",
    "ydata8 = np.zeros((10000))\n",
    "\n",
    "count = 0\n",
    "for my_ratio_x in np.arange(5, 95.001, 1)/100:\n",
    "    #print(my_ratio_x)\n",
    "    Xdata8[count] = crt_saturation_data(my_ratio_x=my_ratio_x)\n",
    "    count = count + 1\n",
    "\n",
    "ydata8[:] = 8\n",
    "\n",
    "Xdata8 = Xdata8[0:count]\n",
    "ydata8 = ydata8[0:count]\n",
    "\n",
    "print('Saturation sample: %d' % (Xdata8.shape[0]))"
   ]
  },
  {
   "cell_type": "raw",
   "id": "8e9034c4-0a21-44c0-ae47-7c9ed57d45d9",
   "metadata": {},
   "source": [
    "n4 = 100\n",
    "Xdata9 = np.zeros((n4, 201))\n",
    "Xdata9[:,0:101] = -1\n",
    "Xdata9[:,101:201] = 1\n",
    "ydata9 = np.zeros(n4)+9"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91deaa45-e7d8-452d-8211-53785944ebb4",
   "metadata": {},
   "source": [
    "### 3.1 3 types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "67d24ffe-89fe-4b3a-81ed-d66536996923",
   "metadata": {},
   "outputs": [],
   "source": [
    "X_full = np.concatenate([Xdata1, Xdata2, Xdata3], axis=0)\n",
    "y_full = np.concatenate([ydata1, ydata2, ydata3], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "e69d01ae-2043-4984-8e81-66edbb15a84b",
   "metadata": {},
   "outputs": [],
   "source": [
    "outfile = datadir + '/fulldata_3type.mat'\n",
    "sio.savemat(outfile, {'X_full':X_full, 'y_full':y_full})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d9ca17b2-d3db-47ed-867a-5795e64e779c",
   "metadata": {},
   "source": [
    "### 3.2 7 types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "5422da7b-19aa-4426-8b79-a32e720398a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "X_full = np.concatenate([Xdata1, Xdata2, Xdata3, Xdata4, Xdata5, Xdata6, Xdata7, Xdata8], axis=0)\n",
    "y_full = np.concatenate([ydata1, ydata2, ydata3, ydata4, ydata5, ydata6, ydata7, ydata8], axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "d4bbcd10-88f1-4c8c-8029-aec1b12f5185",
   "metadata": {},
   "outputs": [],
   "source": [
    "outfile = datadir + 'fulldata_8type.mat'\n",
    "sio.savemat(outfile, {'X_full':X_full, 'y_full':y_full})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dda52e38-9b44-42ad-983b-442a38d8c5f2",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.10.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
