diff --git a/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb b/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb index 0679cfd1ceac81be21316da1223f4eebdfb35016..cc42a657d9d74c10268eba936bbae70fae794146 100644 --- a/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb +++ b/notebooks/AGIPD/Characterize_AGIPD_Gain_Darks_NBC.ipynb @@ -255,35 +255,6 @@ "print(f\"Operation mode is {'fixed' if fixed_gain_mode else 'adaptive'} gain mode\")" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following lines will create a queue of files which will the be executed module-parallel. Distiguishing between different gains." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# set everything up filewise\n", - "os.makedirs(out_folder, exist_ok=True)\n", - "gmf = map_gain_stages(in_folder, offset_runs, path_template, karabo_da, sequences)\n", - "gain_mapped_files, total_sequences, total_file_size = gmf\n", - "print(f\"Will process a total of {total_sequences} files.\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Calculate Offsets, Noise and Thresholds ##\n", - "\n", - "The calculation is performed per-pixel and per-memory-cell. Offsets are simply the median value for a set of dark data taken at a given gain, noise the standard deviation, and gain-bit values the medians of the gain array." - ] - }, { "cell_type": "code", "execution_count": null, @@ -319,13 +290,59 @@ " ]" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following lines will create a queue of files which will the be executed module-parallel. Distiguishing between different gains." + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "def characterize_module(fast_data_filename: str, channel: int, gg: int) -> Tuple[np.array, np.array, np.array, np.array, int, np.array, int, float]:\n", + "# set everything up filewise\n", + "os.makedirs(out_folder, exist_ok=True)\n", + "gain_mapped_files, total_sequences, total_file_size = map_gain_stages(\n", + " in_folder, offset_runs, path_template, karabo_da, sequences\n", + ")\n", + "print(f\"Will process a total of {total_sequences} files ({total_file_size:.02f} GB).\")\n", + "\n", + "inp = []\n", + "inp_modules = []\n", + "for gain_index, (gain, qm_file_map) in enumerate(gain_mapped_files.items()):\n", + " for module_index in modules:\n", + " qm = module_index_to_qm(module_index)\n", + " if qm not in qm_file_map:\n", + " print(f\"Did not find files for {qm}\")\n", + " continue\n", + " file_queue = qm_file_map[qm]\n", + " while not file_queue.empty():\n", + " filename = file_queue.get()\n", + " print(f\"Process {filename} for {qm}\")\n", + " inp.append((filename, module_index, gain_index))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculate Offsets, Noise and Thresholds ##\n", + "\n", + "The calculation is performed per-pixel and per-memory-cell. Offsets are simply the median value for a set of dark data taken at a given gain, noise the standard deviation, and gain-bit values the medians of the gain array." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def characterize_module(\n", + " fast_data_filename: str, channel: int, gain_index: int\n", + ") -> Tuple[np.array, np.array, np.array, np.array, int, np.array, int, float]:\n", " if max_cells == 0:\n", " num_cells = get_num_cells(fast_data_filename, karabo_id, channel)\n", " else:\n", @@ -334,14 +351,14 @@ " print(f\"Using {num_cells} memory cells\")\n", "\n", " if acq_rate == 0.:\n", - " slow_paths = control_names[gg], karabo_id_control\n", + " slow_paths = control_names[gain_index], karabo_id_control\n", " fast_paths = fast_data_filename, karabo_id, channel\n", " local_acq_rate = get_acq_rate(fast_paths, slow_paths)\n", " else:\n", " local_acq_rate = acq_rate\n", "\n", - " local_thresholds_offset_hard = thresholds_offset_hard[gg]\n", - " local_thresholds_noise_hard = thresholds_noise_hard[gg]\n", + " local_thresholds_offset_hard = thresholds_offset_hard[gain_index]\n", + " local_thresholds_noise_hard = thresholds_noise_hard[gain_index]\n", "\n", " h5path_f = h5path.format(channel)\n", " h5path_idx_f = h5path_idx.format(channel)\n", @@ -421,7 +438,7 @@ " bp[(noise < local_thresholds_noise_hard[0]) | (noise > local_thresholds_noise_hard[1])] |= BadPixels.NOISE_OUT_OF_THRESHOLD.value\n", " bp[~np.isfinite(noise)] |= BadPixels.OFFSET_NOISE_EVAL_ERROR.value\n", "\n", - " return offset, noise, gains, gains_std, gg, bp, num_cells, local_acq_rate" + " return offset, noise, gains, gains_std, bp, num_cells, local_acq_rate" ] }, { @@ -435,6 +452,16 @@ "psh.set_default_context(\"threads\", num_workers=parallel_num_threads)" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with multiprocessing.Pool(processes=parallel_num_procs) as pool:\n", + " results = pool.starmap(characterize_module, inp)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -451,39 +478,25 @@ "all_cells = []\n", "all_acq_rate = []\n", "\n", - "inp = []\n", - "for gg, (gain, mapped_files) in enumerate(gain_mapped_files.items()):\n", - " for i in modules:\n", - " qm = module_index_to_qm(i)\n", - " if qm in mapped_files and not mapped_files[qm].empty():\n", - " fname_in = mapped_files[qm].get()\n", - " print(f\"Process file: {fname_in} for {qm}\")\n", - " else:\n", - " continue\n", - " inp.append((fname_in, i, gg))\n", - "\n", - "with multiprocessing.Pool(processes=parallel_num_procs) as pool:\n", - " results = pool.starmap(characterize_module, inp)\n", - "\n", - "for offset, noise, gains, gains_std, gg, bp, thiscell, thisacq in results:\n", + "for (_, module_index, gain_index), (offset, noise, gains, gains_std, bp,\n", + " thiscell, thisacq) in zip(inp, results):\n", " all_cells.append(thiscell)\n", " all_acq_rate.append(thisacq)\n", - " for i in modules:\n", - " qm = module_index_to_qm(i)\n", - " if qm not in offset_g:\n", - " offset_g[qm] = np.zeros((offset.shape[0], offset.shape[1], offset.shape[2], 3))\n", - " noise_g[qm] = np.zeros_like(offset_g[qm])\n", - " badpix_g[qm] = np.zeros_like(offset_g[qm], np.uint32)\n", - " if not fixed_gain_mode:\n", - " gain_g[qm] = np.zeros_like(offset_g[qm])\n", - " gainstd_g[qm] = np.zeros_like(offset_g[qm])\n", - "\n", - " offset_g[qm][...,gg] = offset\n", - " noise_g[qm][...,gg] = noise\n", - " badpix_g[qm][...,gg] = bp\n", + " qm = module_index_to_qm(module_index)\n", + " if qm not in offset_g:\n", + " offset_g[qm] = np.zeros((offset.shape[0], offset.shape[1], offset.shape[2], 3))\n", + " noise_g[qm] = np.zeros_like(offset_g[qm])\n", + " badpix_g[qm] = np.zeros_like(offset_g[qm], np.uint32)\n", " if not fixed_gain_mode:\n", - " gain_g[qm][...,gg] = gains\n", - " gainstd_g[qm][..., gg] = gains_std\n", + " gain_g[qm] = np.zeros_like(offset_g[qm])\n", + " gainstd_g[qm] = np.zeros_like(offset_g[qm])\n", + "\n", + " offset_g[qm][..., gain_index] = offset\n", + " noise_g[qm][..., gain_index] = noise\n", + " badpix_g[qm][..., gain_index] = bp\n", + " if not fixed_gain_mode:\n", + " gain_g[qm][..., gain_index] = gains\n", + " gainstd_g[qm][..., gain_index] = gains_std\n", "\n", "\n", "max_cells = np.max(all_cells)\n", @@ -604,11 +617,52 @@ "source": [ "# set the operating condition\n", "# note: iCalibrationDB only adds gain_mode if it is truthy, so we don't need to handle None\n", - "condition = Conditions.Dark.AGIPD(memory_cells=max_cells,\n", - " bias_voltage=bias_voltage,\n", - " acquisition_rate=acq_rate,\n", - " gain_setting=gain_setting,\n", - " gain_mode=fixed_gain_mode)" + "condition = iCalibrationDB.Conditions.Dark.AGIPD(\n", + " memory_cells=max_cells,\n", + " bias_voltage=bias_voltage,\n", + " acquisition_rate=acq_rate,\n", + " gain_setting=gain_setting,\n", + " gain_mode=fixed_gain_mode\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "md = None\n", + "\n", + "for qm in res:\n", + " db_module = qm_dict[qm][\"db_module\"]\n", + " for const in res[qm]:\n", + " dconst = getattr(iCalibrationDB.Constants.AGIPD, const)()\n", + " dconst.data = res[qm][const]\n", + "\n", + " if db_output:\n", + " md = send_to_db(db_module, karabo_id, dconst, condition, file_loc,\n", + " report, cal_db_interface, creation_time=creation_time,\n", + " timeout=cal_db_timeout)\n", + "\n", + " if local_output:\n", + " md = save_const_to_h5(db_module, karabo_id, dconst, condition, dconst.data,\n", + " file_loc, report, creation_time, out_folder)\n", + " print(f\"Calibration constant {const} for {qm} is stored locally in {file_loc}.\\n\")\n", + "\n", + " print(\"Constants parameter conditions are:\\n\")\n", + " print(f\"• memory_cells: {max_cells}\\n• bias_voltage: {bias_voltage}\\n\"\n", + " f\"• acquisition_rate: {acq_rate}\\n• gain_setting: {gain_setting}\\n\"\n", + " f\"• gain_mode: {fixed_gain_mode}\\n\"\n", + " f\"• creation_time: {md.calibration_constant_version.begin_at if md is not None else creation_time}\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ ] }, { @@ -668,29 +722,6 @@ "metadata": {}, "outputs": [], "source": [ - "md = None\n", - "\n", - "for qm in res:\n", - " db_module = qm_dict[qm][\"db_module\"]\n", - " for const in res[qm]:\n", - " dconst = getattr(iCalibrationDB.Constants.AGIPD, const)()\n", - " dconst.data = res[qm][const]\n", - "\n", - " if db_output:\n", - " md = send_to_db(db_module, karabo_id, dconst, condition, file_loc,\n", - " report, cal_db_interface, creation_time=creation_time,\n", - " timeout=cal_db_timeout)\n", - "\n", - " if local_output:\n", - " md = save_const_to_h5(db_module, karabo_id, dconst, condition, dconst.data,\n", - " file_loc, report, creation_time, out_folder)\n", - " print(f\"Calibration constant {const} for {qm} is stored locally in {file_loc}.\\n\")\n", - "\n", - " print(\"Constants parameter conditions are:\\n\")\n", - " print(f\"• memory_cells: {max_cells}\\n• bias_voltage: {bias_voltage}\\n\"\n", - " f\"• acquisition_rate: {acq_rate}\\n• gain_setting: {gain_setting}\\n\"\n", - " f\"• gain_mode: {fixed_gain_mode}\\n\"\n", - " f\"• creation_time: {md.calibration_constant_version.begin_at if md is not None else creation_time}\\n\")" ] }, { @@ -886,7 +917,11 @@ "# now we need the old constants\n", "old_const = {}\n", "old_mdata = {}\n", - "old_retrieval_res.wait()" + "old_retrieval_res.wait()\n", + "\n", + "for (qm, const), (data, timestamp) in zip(qm_x_const, old_retrieval_res.get()):\n", + " old_const.setdefault(qm, {})[const] = data\n", + " old_mdata.setdefault(qm, {})[const] = timestamp" ] }, { @@ -895,9 +930,6 @@ "metadata": {}, "outputs": [], "source": [ - "for (qm, const), (data, timestamp) in zip(qm_x_const, old_retrieval_res.get()):\n", - " old_const.setdefault(qm, {})[const] = data\n", - " old_mdata.setdefault(qm, {})[const] = timestamp" ] }, { @@ -934,12 +966,12 @@ " for bit in bits:\n", " l_data.append(np.count_nonzero(badpix_g[qm][:,:,:,gain] & bit.value))\n", "\n", - " if old_const['BadPixelsDark'] is not None:\n", - " dataold = np.copy(old_const['BadPixelsDark'][:, :, :, gain])\n", + " if old_const[qm]['BadPixelsDark'] is not None:\n", + " dataold = np.copy(old_const[qm]['BadPixelsDark'][:, :, :, gain])\n", " datau32old = dataold.astype(np.uint32)\n", " l_data_old.append(len(datau32old[datau32old>0].flatten()))\n", " for bit in bits:\n", - " l_data_old.append(np.count_nonzero(old_const['BadPixelsDark'][:, :, :, gain] & bit.value))\n", + " l_data_old.append(np.count_nonzero(old_const[qm]['BadPixelsDark'][:, :, :, gain] & bit.value))\n", "\n", " l_data_name = ['All bad pixels', 'NOISE_OUT_OF_THRESHOLD',\n", " 'OFFSET_OUT_OF_THRESHOLD', 'OFFSET_NOISE_EVAL_ERROR', 'GAIN_THRESHOLDING_ERROR']\n", @@ -951,7 +983,7 @@ " for i in range(len(l_data)):\n", " line = [f'{l_data_name[i]}, {gain_names[gain]} gain', l_threshold[i], l_data[i]]\n", "\n", - " if old_const['BadPixelsDark'] is not None:\n", + " if old_const[qm]['BadPixelsDark'] is not None:\n", " line += [l_data_old[i]]\n", " else:\n", " line += ['-']\n",