diff --git a/notebooks/REMI/REMI_Digitize_and_Transform.ipynb b/notebooks/REMI/REMI_Digitize_and_Transform.ipynb index 5784ef2255166113517322b5372f56fcfd42ba46..363ee1ae37c49c207185cfb210284b5f5623262c 100644 --- a/notebooks/REMI/REMI_Digitize_and_Transform.ipynb +++ b/notebooks/REMI/REMI_Digitize_and_Transform.ipynb @@ -37,6 +37,9 @@ "dataset_compression = 'gzip' # HDF compression method.\n", "dataset_compression_opts = 3 # HDF GZIP compression level.\n", "\n", + "# Trigger parameters.\n", + "ppl_offset = 0 # In units of the FEL pulses.\n", + "\n", "# Parallelization parameters.\n", "mp_pulse_info = 8 # Parallelization for pulse statistics.\n", "mp_find_triggers = 0.5 # Parallelization for finding triggers.\n", @@ -145,7 +148,7 @@ "# * `num_pulses = pulse_counts.sum(axis=0)`\n", "\n", "with timing('pulse_info'):\n", - " pulse_counts, pulse_offsets, num_pulses = remi.get_pulse_info(dc, mp_pulse_info)" + " pulse_counts, pulse_offsets, num_pulses = remi.get_pulse_info(dc, ppl_offset, mp_pulse_info)" ] }, { @@ -184,25 +187,27 @@ "source": [ "# A trigger defines the boundary of a pulse on the digitizer trace stored per train. This cell creates a\n", "# global variable:\n", - "# * `triggers [(start: int32, stop: int32, offset: float64): num_pulses]` containing the triggers for each\n", - "# pulse.\n", + "# * `triggers [(start: int32, stop: int32, offset: float64, fel: bool, ppl: bool): num_pulses]`\n", + "# containing the triggers for each pulse.\n", "# \n", "# Triggers may be obtained through two different methods:\n", "# \n", "# * `ppt` uses the pulse puttern table to locate the pulse positions on the trace. Only number of pulses and\n", "# their distance can be drawn this way, leaving the absolute offset for the very first pulse to be\n", - "# configured via `trigger/ppt/first_pulse_offset`.\n", + "# configured via `trigger/ppt/first_pulse_offset`. If a PPL laser is used, it will be included in the\n", + "# trigger pattern. The ppt_offset parameter allows taking into account an offset betwen PPL and FEL assuming\n", + "# the same rep rate.\n", "# \n", "# * `edge` uses the digitizer channel `trigger/edge/channel` and builds triggers around the edges found on it.\n", "# The boundaries relative to this edge may be configured with the `group_start`, `group_end` and `dead_time`\n", - "# parameters.\n", + "# parameters. There is no support for PPL with this method.\n", "\n", "psh.set_default_context('processes', num_workers=remi.get_num_workers(mp_find_triggers))\n", "\n", - "triggers = psh.alloc(shape=(num_pulses,), dtype=trigger_dt, fill=(-1, -1, np.nan))\n", + "triggers = psh.alloc(shape=(num_pulses,), dtype=trigger_dt, fill=(-1, -1, np.nan, 0, 0))\n", "\n", "if remi['trigger']['method'] == 'ppt':\n", - " from euxfel_bunch_pattern import indices_at_sase\n", + " from euxfel_bunch_pattern import indices_at_sase, indices_at_laser, PPL_BITS\n", " \n", " pptc = remi['trigger']['ppt']\n", " \n", @@ -227,6 +232,16 @@ " \n", " pulse_offset = pulse_offsets[index]\n", " pulse_count = pulse_counts[index]\n", + " \n", + " if ppl_offset != 0:\n", + " # Special support for asymmetric pump-probe patterns.\n", + " # For now only offsets as a integer multiple of the FEL pulse length are supported.\n", + " # The relative position array is extended by the number of required elements and\n", + " # the FEL/PPL flags set later on.\n", + " \n", + " abs_offset = abs(ppl_offset)\n", + " rel_pos = np.append(rel_pos, rel_pos[-1] + np.arange(abs_offset) * pulse_len)\n", + " \n", " train_triggers = triggers[pulse_offset:pulse_offset+pulse_count]\n", " \n", " start_frac = first_pulse_offset + rel_pos * 2 * clock_factor\n", @@ -239,6 +254,20 @@ " train_triggers['start'] = start\n", " train_triggers['stop'] = start + int(pulse_len * 2 * clock_factor) - 1\n", " train_triggers['offset'] = start_frac - start\n", + " \n", + " has_ppl = len(indices_at_laser(ppt, PPL_BITS.LP_SQS)) > 0\n", + " \n", + " if ppl_offset == 0:\n", + " train_triggers['fel'] = True\n", + " train_triggers['ppl'] = has_ppl\n", + " elif ppl_offset < 0:\n", + " ## There are PPL-only pulses before FEL pulses.\n", + " train_triggers[abs_offset:]['fel'] = True\n", + " train_triggers[:-abs_offset]['ppl'] = has_ppl\n", + " elif ppl_offset > 0:\n", + " # There are PPL-only pulses after FEL pulses.\n", + " train_triggers[:-abs_offset]['fel'] = True\n", + " train_triggers[-abs_offset:]['ppl'] = has_ppl\n", " \n", " with timing('find_triggers'):\n", " psh.map(trigger_by_ppt, keydata)\n", @@ -307,6 +336,7 @@ " pulse_trigger['start'] = start\n", " pulse_trigger['stop'] = stop\n", " pulse_trigger['offset'] = start - edge\n", + " pulse_trigger['fel'] = True\n", " \n", " with timing('find_triggers'):\n", " psh.map(trigger_by_edge, keydata)" @@ -880,9 +910,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ "seq_len = out_seq_len if out_seq_len > 0 else len(dc.files[0].train_ids)\n",