diff --git a/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb b/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb
index 4605853286fa12bc057e845c56437b1997de1761..27cdbc0e6ef9aa2b43f6ef1a9de011ce1af706f9 100644
--- a/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb
+++ b/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb
@@ -96,6 +96,7 @@
     "\n",
     "%matplotlib inline\n",
     "\n",
+    "import itertools\n",
     "import multiprocessing\n",
     "\n",
     "from cal_tools.agipdlib import (\n",
@@ -945,49 +946,65 @@
     "else:\n",
     "    constants = ['Offset', 'Noise', 'ThresholdsDark']\n",
     "\n",
-    "for const in constants:\n",
+    "constants_x_qms = list(itertools.product(constants, res.keys()))\n",
     "\n",
+    "def compute_table(const, qm):\n",
     "    if const == 'ThresholdsDark':\n",
     "        table = [['','HG-MG threshold', 'HG-MG threshold', 'MG-LG threshold', 'MG-LG threshold']]\n",
     "    else:\n",
     "        table = [['','High gain', 'High gain', 'Medium gain', 'Medium gain', 'Low gain', 'Low gain']]\n",
     "\n",
-    "    for qm in res.keys():\n",
-    "        data = np.copy(res[qm][const])\n",
+    "    compare_with_old_constant = old_const[const] is not None and old_const['BadPixelsDark'] is not None\n",
     "\n",
+    "    data = np.copy(res[qm][const])\n",
+    "\n",
+    "    if const == 'ThresholdsDark':\n",
+    "        data[...,0][res[qm]['BadPixelsDark'][...,0]>0] = np.nan\n",
+    "        data[...,1][res[qm]['BadPixelsDark'][...,1]>0] = np.nan\n",
+    "    else:\n",
+    "        data[res[qm]['BadPixelsDark']>0] = np.nan\n",
+    "\n",
+    "    if compare_with_old_constant:\n",
+    "        data_old = np.copy(old_const[const])\n",
     "        if const == 'ThresholdsDark':\n",
-    "            data[...,0][res[qm]['BadPixelsDark'][...,0]>0] = np.nan\n",
-    "            data[...,1][res[qm]['BadPixelsDark'][...,1]>0] = np.nan\n",
+    "            data_old[...,0][old_const['BadPixelsDark'][...,0]>0] = np.nan\n",
+    "            data_old[...,1][old_const['BadPixelsDark'][...,1]>0] = np.nan\n",
     "        else:\n",
-    "            data[res[qm]['BadPixelsDark']>0] = np.nan\n",
-    "\n",
-    "        if old_const[const] is not None and old_const['BadPixelsDark'] is not None:\n",
-    "            dataold = np.copy(old_const[const])\n",
-    "            if const == 'ThresholdsDark':\n",
-    "                dataold[...,0][old_const['BadPixelsDark'][...,0]>0] = np.nan\n",
-    "                dataold[...,1][old_const['BadPixelsDark'][...,1]>0] = np.nan\n",
+    "            data_old[old_const['BadPixelsDark']>0] = np.nan\n",
+    "\n",
+    "    f_list = [np.nanmedian, np.nanmean, np.nanstd, np.nanmin, np.nanmax]\n",
+    "    n_list = ['Median', 'Mean', 'Std', 'Min', 'Max']\n",
+    "\n",
+    "    def compute_row(i):\n",
+    "        line = [n_list[i]]\n",
+    "        for gain in range(3):\n",
+    "            # Compare only 3 threshold gain-maps\n",
+    "            if gain == 2 and const == 'ThresholdsDark':\n",
+    "                continue\n",
+    "            stat_measure = f_list[i](data[...,gain])\n",
+    "            line.append(f\"{stat_measure:6.1f}\")\n",
+    "            if compare_with_old_constant:\n",
+    "                old_stat_measure = f_list[i](data_old[...,gain])\n",
+    "                line.append(f\"{old_stat_measure:6.1f}\")\n",
     "            else:\n",
-    "                dataold[old_const['BadPixelsDark']>0] = np.nan\n",
-    "\n",
-    "        f_list = [np.nanmedian, np.nanmean, np.nanstd, np.nanmin, np.nanmax]\n",
-    "        n_list = ['Median', 'Mean', 'Std', 'Min', 'Max']\n",
-    "\n",
-    "        for i, f in enumerate(f_list):\n",
-    "            line = [n_list[i]]\n",
-    "            for gain in range(3):\n",
-    "                # Compare only 3 threshold gain-maps\n",
-    "                if gain == 2 and const == 'ThresholdsDark':\n",
-    "                    continue\n",
-    "                line.append('{:6.1f}'.format(f(data[...,gain])))\n",
-    "                if old_const[const] is not None and old_const['BadPixelsDark'] is not None:\n",
-    "                    line.append('{:6.1f}'.format(f(dataold[...,gain])))\n",
-    "                else:\n",
-    "                    line.append('-')\n",
+    "                line.append(\"-\")\n",
+    "        return line\n",
+    "    \n",
     "\n",
-    "            table.append(line)\n",
+    "    with multiprocessing.pool.ThreadPool(processes=multiprocessing.cpu_count() // len(constants_x_qms)) as pool:\n",
+    "        rows = pool.map(compute_row, range(len(f_list)))\n",
+    "\n",
+    "    table.extend(rows)\n",
+    "            \n",
+    "    return table\n",
+    "\n",
+    "\n",
+    "with multiprocessing.Pool(processes=len(constants_x_qms)) as pool:\n",
+    "    tables = pool.starmap(compute_table, constants_x_qms)\n",
     "\n",
-    "    display(Markdown('### {} [ADU], good pixels only ###'.format(const)))\n",
-    "    md = display(Latex(tabulate.tabulate(table, tablefmt='latex', headers=header)))"
+    "for (const, qm), table in zip(constants_x_qms, tables):\n",
+    "    display(Markdown(f\"### {qm}: {const} [ADU], good pixels only\"))\n",
+    "    display(Latex(tabulate.tabulate(table, tablefmt='latex', headers=header)))"
    ]
   }
  ],