From 309f4ab7976432713d779c3b7249183c2e02c8fd Mon Sep 17 00:00:00 2001 From: Ben Williams Date: Thu, 24 Nov 2022 21:48:32 +0000 Subject: [PATCH 01/30] Add gated image binning for SSX Add a command line tool for binning each gated batch of images to a single image. --- src/tristan/command_line/__init__.py | 19 +++++ src/tristan/command_line/images.py | 121 +++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) diff --git a/src/tristan/command_line/__init__.py b/src/tristan/command_line/__init__.py index 1d67b9d9..5bf90b17 100644 --- a/src/tristan/command_line/__init__.py +++ b/src/tristan/command_line/__init__.py @@ -421,3 +421,22 @@ def positive_int(value: SupportsInt) -> int: group.add_argument( "-x", "--num-sequences", help="Number of image sequences.", type=positive_int ) + +# A parser for specifying a pair of trigger signals with which to gate event processing. +gate_parser = argparse.ArgumentParser(add_help=False) +gate_parser.add_argument( + "-g", + "--gate-open", + help="Trigger signal denoting the start of each gate period.", + choices=triggers.keys(), + required=True, +) +gate_parser.add_argument( + "-c", + "--gate-close", + help="Trigger signal denoting the end of each gate period (optional). If not " + "provided, this will default to the complementary signal to the '--gate-open' " + "value. For example, if the '--gate-open' signal is 'TTL-rising', " + "the --gate-close signal will default to 'TTL-falling', and vice versa.", + choices=triggers.keys(), +) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 449a1f75..047f814e 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -47,6 +47,7 @@ check_output_file, data_files, exposure_parser, + gate_parser, image_output_parser, input_parser, interval_parser, @@ -529,6 +530,116 @@ def multiple_sequences_cli(args): print(f"Images written to\n\t{output_nexus_pattern or out_file_pattern}") +def gated_images_cli(args): + """Utility to bin events into a sequence of images according to a gating signal.""" + write_mode = "w" if args.force else "x" + output_file = check_output_file(args.output_file, args.stem, "images", args.force) + + input_nexus = args.data_dir / f"{args.stem}.nxs" + if not input_nexus.exists(): + print( + "Could not find a NeXus file containing experiment metadata.\n" + "Resorting to writing raw image data without accompanying metadata." + ) + + image_size = args.image_size or determine_image_size(input_nexus) + + raw_files, _ = data_files(args.data_dir, args.stem) + + # If gate_close isn't specified, default to the complementary signal to gate_open. + gate_open = triggers.get(args.gate_open) + gate_close = triggers.get(args.gate_close) or gate_open ^ (1 << 5) + + with latrd_data(raw_files, keys=cue_keys) as cues_data: + print("Finding detector shutter open and close times.") + with ProgressBar(): + start, end = find_start_end(cues_data) + + print("Finding gate signal times.") + open_times = cue_times(cues_data, gate_open, after=start) + close_times = cue_times(cues_data, gate_close, after=start) + with ProgressBar(): + open_times, close_times = dask.compute(open_times, close_times) + + if not open_times.size: + sys.exit(f"Could not find a '{cues[gate_open]}' signal.") + if not close_times.size: + sys.exit(f"Could not find a '{cues[gate_close]}' signal.") + if not open_times.size == close_times.size: + sys.exit( + "Found a non-matching number of gate open and close signals:\n\t" + f"Number of '{cues[gate_open]}' signals: {open_times.size}\n\t" + f"Number of '{cues[gate_close]}' signals: {close_times.size}\n" + f"Note that signals before the shutter open time are ignored." + ) + + open_times.sort_values(inplace=True) + close_times.sort_values(inplace=True) + + num_images = open_times.size + + if input_nexus.exists(): + try: + # Write output NeXus file if we have an input NeXus file. + output_nexus = CopyTristanNexus.multiple_images_nexus( + output_file, + input_nexus, + nbins=num_images, + write_mode=write_mode, + ) + except FileExistsError: + sys.exit( + f"This output file already exists:\n\t" + f"{output_file.with_suffix('.nxs')}\n" + "Use '-f' to override, " + "or specify a different output file path with '-o'." + ) + else: + output_nexus = None + + print(f"Binning events into {num_images} images.") + + # Make a cache for the images. + images = create_cache(output_file, num_images, image_size) + + with latrd_data(raw_files, keys=(event_location_key, event_time_key)) as data: + # Consider only those events that occur between the start and end times. + data = valid_events(data, start, end) + + # Gate the events. + event_times = data[event_time_key].values + open_index = da.digitize(event_times, open_times) - 1 + close_index = da.digitize(event_times, close_times) - 1 + data["time_bin"] = open_index + open_times = da.take(open_times, open_index) + close_times = da.take(close_times, close_index) + data = valid_events(data, open_times, close_times) + data.drop(columns=event_time_key, inplace=True) + + # Convert the event IDs to a form that is suitable for a NumPy bincount. + data[event_location_key] = pixel_index(data[event_location_key], image_size) + + # Bin to images, partition by partition. + meta = pd.DataFrame(columns=data.columns).astype(dtype=data.dtypes) + data = dd.map_partitions( + make_images, data, image_size, images, meta=meta, enforce_metadata=False + ) + + print("Computing the binned images.") + # Use multi-threading, rather than multi-processing. + with Client(processes=False): + compute_with_progress(data) + + print("Transferring the images to the output file.") + with h5py.File(output_file, write_mode) as f: + zarr.copy_all(zarr.open(images.store), f, **Bitshuffle()) + + # Delete the Zarr store. + images.store.clear() + + print(f"Images written to\n\t{output_nexus or output_file}") + + parser = argparse.ArgumentParser(description=__doc__, parents=[version_parser]) subparsers = parser.add_subparsers( help="Choose the manner in which to create images.", @@ -603,6 +714,16 @@ def multiple_sequences_cli(args): ) parser_multiple_sequences.set_defaults(func=multiple_sequences_cli) +parser_serial = subparsers.add_parser( + "serial", + description="Bin events into images, gated with trigger signals.\n\n" + "Events will be binned into as many images as there are gate signals, one image " + "per gate. Each 'gate-open' signal is taken as the start of an exposure and the " + "next 'gate-close' signal is taken as the end of the exposure.", + parents=[version_parser, input_parser, image_output_parser, gate_parser], +) +parser_serial.set_defaults(func=gated_images_cli) + def main(args=None): """Perform the image binning with a user-specified sub-command.""" From 8ce2091f596eb47aae4af3cc7c98bfc6bc008d92 Mon Sep 17 00:00:00 2001 From: Ben Williams Date: Thu, 24 Nov 2022 21:49:29 +0000 Subject: [PATCH 02/30] Rationalise checks for parsers that give no help --- tests/test_command_line.py | 52 ++++++++++++++------------------------ 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/tests/test_command_line.py b/tests/test_command_line.py index 2c47bba9..36984b49 100644 --- a/tests/test_command_line.py +++ b/tests/test_command_line.py @@ -13,6 +13,7 @@ check_output_file, data_files, exposure_parser, + gate_parser, image_output_parser, image_size, input_parser, @@ -74,6 +75,24 @@ def test_data_files(dummy_data_transient): data_files(dummy_data_transient, stem) +no_help_parameters = [ + (version_parser, []), + (input_parser, ["some/dummy/path/to/file_name_meta.h5"]), + (image_output_parser, []), + (exposure_parser, ["-e", ".1"]), + (gate_parser, ["-g", "TTL-rising"]), +] + + +@pytest.mark.parametrize(("parser", "req_arguments"), no_help_parameters) +def test_no_help(capsys, parser: argparse.ArgumentParser, req_arguments: list[str]): + """Check that this parser does not introduce a help flag.""" + for flag in "-h", "--help": + with pytest.raises(SystemExit, match="2"): + parser.parse_args([*req_arguments, flag]) + assert f"error: unrecognized arguments: {flag}" in capsys.readouterr().err + + def test_version_parser(capsys): """Test that the version parser gives the correct behaviour.""" for flag in "--version", "-V": @@ -87,13 +106,6 @@ def test_version_parser_optional(): assert version_parser.parse_args([]) == argparse.Namespace() -def test_version_parser_no_help(capsys): - """Check that the version parser does not introduce a help flag.""" - with pytest.raises(SystemExit, match="2"): - version_parser.parse_args(["-h"]) - assert "error: unrecognized arguments: -h" in capsys.readouterr().err - - @pytest.mark.parametrize( "filename", ("dummy_meta.h5", "dummy_1.h5", "dummy_0001.h5", "dummy.nxs") ) @@ -243,16 +255,6 @@ def test_input_parser_cwd(run_in_tmp_path, filename): assert args.stem == "dummy" -def test_input_parser_no_help(capsys): - """Check that the input parser does not introduce a help flag.""" - directory = "some/dummy/path/to" - stem = "file_name" - for flag in "-h", "--help": - with pytest.raises(SystemExit, match="2"): - input_parser.parse_args([f"{directory}/{stem}_meta.h5", flag]) - assert f"error: unrecognized arguments: {flag}" in capsys.readouterr().err - - def test_image_size(): """Test unpacking an image size tuple from a comma-separated string of integers.""" for size in "1,2", "1, 2", "1 ,2", "1 , 2", "(1,2)", "'1,2'", '"1,2"', "'\"(1,2'\"": @@ -331,14 +333,6 @@ def test_image_output_parser_malformed_image_size(capsys): ) -def test_image_output_parser_no_help(capsys): - """Check that the output/image size parser does not introduce a help flag.""" - for flag in "-h", "--help": - with pytest.raises(SystemExit, match="2"): - image_output_parser.parse_args([flag]) - assert f"error: unrecognized arguments: {flag}" in capsys.readouterr().err - - def test_units_of_time(): """Test the utility for applying a default unit to a quantity.""" # Check that a dimensionless input quantity defaults to seconds. @@ -452,11 +446,3 @@ def test_exposure_time_mutually_exclusive(capsys): "error: argument -e/--exposure-time: not allowed with argument -n/--num-images" in capsys.readouterr().err ) - - -def test_exposure_time_no_help(capsys): - """Check that this parser does not introduce a help flag.""" - for flag in "-h", "--help": - with pytest.raises(SystemExit, match="2"): - exposure_parser.parse_args(["-e", ".1", flag]) - assert f"error: unrecognized arguments: {flag}" in capsys.readouterr().err From 79d1e8c0a3571d88b678fa8bad394b5e3a10fe70 Mon Sep 17 00:00:00 2001 From: Ben Williams Date: Fri, 25 Nov 2022 18:18:42 +0000 Subject: [PATCH 03/30] Fix some misuse of Dask objects --- src/tristan/command_line/images.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 047f814e..46901188 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -573,8 +573,8 @@ def gated_images_cli(args): f"Note that signals before the shutter open time are ignored." ) - open_times.sort_values(inplace=True) - close_times.sort_values(inplace=True) + open_times = np.sort(open_times) + close_times = np.sort(close_times) num_images = open_times.size @@ -614,7 +614,7 @@ def gated_images_cli(args): open_times = da.take(open_times, open_index) close_times = da.take(close_times, close_index) data = valid_events(data, open_times, close_times) - data.drop(columns=event_time_key, inplace=True) + data = data.drop(columns=event_time_key) # Convert the event IDs to a form that is suitable for a NumPy bincount. data[event_location_key] = pixel_index(data[event_location_key], image_size) From 62e82b2c00a64440b062c47ab68e7645a9f8d448 Mon Sep 17 00:00:00 2001 From: Noemi Frisina <54588199+noemifrisina@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:11:23 +0000 Subject: [PATCH 04/30] Use new copy tool for serial crystallography data --- src/tristan/command_line/images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 2c27fc03..dca76661 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -586,7 +586,7 @@ def gated_images_cli(args): if input_nexus.exists(): try: # Write output NeXus file if we have an input NeXus file. - output_nexus = CopyTristanNexus.multiple_images_nexus( + output_nexus = CopyTristanNexus.serial_images_nexus( output_file, input_nexus, nbins=num_images, From 7705aa340c1d99d890d07f20925e5d1cb40ec046 Mon Sep 17 00:00:00 2001 From: Noemi Frisina <54588199+noemifrisina@users.noreply.github.com> Date: Fri, 10 Feb 2023 23:13:22 +0000 Subject: [PATCH 05/30] Pin nexgen to latest version to get the serial tools working --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 312dd1c9..fbeeae8f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,7 +32,7 @@ install_requires = dask[array,diagnostics,distributed] != 2021.3.* h5py hdf5plugin - nexgen >= 0.6.8 + nexgen >= 0.6.20 numpy pandas pint From 08d0c9d14fbca7c63eacfee3e0c629930630797a Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Fri, 17 Feb 2023 15:56:26 +0000 Subject: [PATCH 06/30] Add first and last trigger timestamp and warn if they happen before/after shutter --- .../diagnostics/find_trigger_intervals.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/tristan/diagnostics/find_trigger_intervals.py b/src/tristan/diagnostics/find_trigger_intervals.py index e0bf912c..c21fd0d0 100644 --- a/src/tristan/diagnostics/find_trigger_intervals.py +++ b/src/tristan/diagnostics/find_trigger_intervals.py @@ -273,6 +273,8 @@ def main(args): logger.info("TTL") logger.info(f"Found {len(v['TTL re'])} rising edges.\n") if len(v["TTL re"]) > 0: + logger.info(f"First TTL rising edge timestamp: {v['TTL re'][0]:.4f} .") + logger.info(f"Last TTL rising edge timestamp: {v['TTL re'][-1]:.4f} .") d = [i - v["TTL re"][n - 1] for n, i in enumerate(v["TTL re"])][1:] d_avg = np.average(d) if len(d) else np.nan logger.info( @@ -321,6 +323,22 @@ def main(args): logger.info( f"Found {len(v['SYNC re'])} rising edges and {len(v['SYNC fe'])} falling edges." ) + logger.info( + f"First SYNC rising edge timestamp: {v['SYNC re'][0]:.4f} ." + ) + # logger.info(f"First SYNC falling edge timestamp: {v['SYNC fe'][0]:.4f} .") + # logger.info(f"Last SYNC rising edge timestamp: {v['SYNC re'][-1]:.4f} .") + logger.info( + f"Last SYNC falling edge timestamp: {v['SYNC fe'][-1]:.4f} ." + ) + if v["SYNC re"][0] < shutters[0][0]: + logger.warning( + "First SYNC rising edge was recorded before the shutter open signal!" + ) + if v["SYNC fe"][-1] < shutters[1][0]: + logger.warning( + "Last SYNC falling edge was recorded after the shutter close signal!" + ) diff4 = [b - a for a, b in zip(v["SYNC re"], v["SYNC fe"])] avg4 = np.average(diff4) if len(diff4) else np.nan logger.info( From 1fd29dec984626fd074629c16af3e26b841127d8 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Fri, 17 Feb 2023 16:20:21 +0000 Subject: [PATCH 07/30] Fix typo --- src/tristan/diagnostics/find_trigger_intervals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tristan/diagnostics/find_trigger_intervals.py b/src/tristan/diagnostics/find_trigger_intervals.py index c21fd0d0..dfee47bf 100644 --- a/src/tristan/diagnostics/find_trigger_intervals.py +++ b/src/tristan/diagnostics/find_trigger_intervals.py @@ -335,7 +335,7 @@ def main(args): logger.warning( "First SYNC rising edge was recorded before the shutter open signal!" ) - if v["SYNC fe"][-1] < shutters[1][0]: + if v["SYNC fe"][-1] > shutters[1][0]: logger.warning( "Last SYNC falling edge was recorded after the shutter close signal!" ) From ef8317162315f0f9f4f4fc3262b7d47a2cd5c767 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Tue, 21 Feb 2023 09:59:53 +0000 Subject: [PATCH 08/30] Print also timestamp difference between shutters and signal to see just how small the interval is --- CHANGELOG.md | 1 + src/tristan/diagnostics/find_trigger_intervals.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dac728d8..71606604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## - Fixed the axis dimensions for `images pp`. +- Added timestamp check and warning on triggers if they happen before/after shutters in `find-tristan-triggers`. ## 0.2.1 - Added dagnostic tool `valid-events` for checking that there are events recorded after the shutter open signal in case the binned image is blank(asynchronicity issue). Also, a couple of small improvements on the other diagnostic tools. diff --git a/src/tristan/diagnostics/find_trigger_intervals.py b/src/tristan/diagnostics/find_trigger_intervals.py index dfee47bf..8b7ce894 100644 --- a/src/tristan/diagnostics/find_trigger_intervals.py +++ b/src/tristan/diagnostics/find_trigger_intervals.py @@ -333,11 +333,13 @@ def main(args): ) if v["SYNC re"][0] < shutters[0][0]: logger.warning( - "First SYNC rising edge was recorded before the shutter open signal!" + "First SYNC rising edge was recorded before the shutter open signal! \n" + f"Timestamp difference: {shutters[0][0] - v['SYNC re'][0]} s." ) if v["SYNC fe"][-1] > shutters[1][0]: logger.warning( - "Last SYNC falling edge was recorded after the shutter close signal!" + "Last SYNC falling edge was recorded after the shutter close signal! \n" + f"Timestamp difference: {v['SYNC fe'][-1] - shutters[1][0]} s." ) diff4 = [b - a for a, b in zip(v["SYNC re"], v["SYNC fe"])] avg4 = np.average(diff4) if len(diff4) else np.nan From 291b9e939405297db35f294567beb307a3af1bf1 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Tue, 21 Feb 2023 10:51:49 +0000 Subject: [PATCH 09/30] Tidy up printed messages --- .../diagnostics/find_trigger_intervals.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/tristan/diagnostics/find_trigger_intervals.py b/src/tristan/diagnostics/find_trigger_intervals.py index 8b7ce894..27cf8b54 100644 --- a/src/tristan/diagnostics/find_trigger_intervals.py +++ b/src/tristan/diagnostics/find_trigger_intervals.py @@ -237,8 +237,8 @@ def main(args): logger.info(f"--- {k} ---") logger.info("SHUTTERS") if len(shutters[0]) > 0 and len(shutters[1]) > 0: - logger.info(f"Shutter open timestamp: {shutters[0][0]:.4f}") - logger.info(f"Shutter close timestamp: {shutters[1][0]:.4f}") + logger.info(f"Shutter open timestamp: {shutters[0][0]:.4f}.") + logger.info(f"Shutter close timestamp: {shutters[1][0]:.4f}.") diff0 = shutters[1][0] - shutters[0][0] logger.info( f"Total time between shutter opening and closing: {diff0:.4f} s." @@ -246,10 +246,10 @@ def main(args): elif len(shutters[0]) == 0 or len(shutters[1]) == 0: logger.warning("Missing shutter information!") logger.warning( - f"Number of shutter open timestamps found: {len(shutters[0])}" + f"Number of shutter open timestamps found: {len(shutters[0])}." ) logger.warning( - f"Number of shutter close timestamps found: {len(shutters[1])}" + f"Number of shutter close timestamps found: {len(shutters[1])}." ) logger.info("LVDS") if len(v["LVDS re"]) > 0 and len(v["LVDS fe"]) > 0: @@ -324,12 +324,12 @@ def main(args): f"Found {len(v['SYNC re'])} rising edges and {len(v['SYNC fe'])} falling edges." ) logger.info( - f"First SYNC rising edge timestamp: {v['SYNC re'][0]:.4f} ." + f"First SYNC rising edge timestamp: {v['SYNC re'][0]:.4f}." ) # logger.info(f"First SYNC falling edge timestamp: {v['SYNC fe'][0]:.4f} .") # logger.info(f"Last SYNC rising edge timestamp: {v['SYNC re'][-1]:.4f} .") logger.info( - f"Last SYNC falling edge timestamp: {v['SYNC fe'][-1]:.4f} ." + f"Last SYNC falling edge timestamp: {v['SYNC fe'][-1]:.4f}." ) if v["SYNC re"][0] < shutters[0][0]: logger.warning( @@ -344,13 +344,13 @@ def main(args): diff4 = [b - a for a, b in zip(v["SYNC re"], v["SYNC fe"])] avg4 = np.average(diff4) if len(diff4) else np.nan logger.info( - f"Average time interval between SYNC re and fe: {avg4:.4f} s" + f"Average time interval between SYNC re and fe: {avg4:.4f} s." ) if len(v["TTL re"]) == len(v["SYNC re"]): diff5 = [b - a for a, b in zip(v["TTL re"], v["SYNC re"])] avg5 = np.average(diff5) if len(diff5) else np.nan logger.info( - f"Average time interval between TTL re and SYNC re: {avg5:.4f} s" + f"Average time interval between TTL re and SYNC re: {avg5:.4f} s." ) else: logger.error( From da7043df077ff0199bf603b079b7da2db75e4d14 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Tue, 21 Feb 2023 11:15:37 +0000 Subject: [PATCH 10/30] Add some docs for new tool --- docs/usage.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/usage.rst b/docs/usage.rst index 70dfd5e2..85273dba 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -99,6 +99,29 @@ by duration, with `-i`, or by number, with `-x`. For example, this could be used to deconstruct a rotation data collection into several rotation datasets, each corresponding to a different pump-probe delay window. +Serial crystallography tool (gated access) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To bin events into images gated by trigger signals, use `images serial`, which will write one image per gate signal. Each 'gate-open' signal is taken as the start of an exposure and +the next 'gate-close' signal is taken as the end of the exposure. + +This tool requires at least the rising edge of the trigger signal, specified with `-g`, to be passed as *gate open* and will then look for the corresponding falling edge +to be used as *gate close*. + +.. code-block:: console + + images serial -g SYNC-rising /path/to/file + + +In some cases, it might be more useful to look at the events collected between different kinds of trigger signals, by specifying the *gate open* signal with `-g` +and the *gate close* using the `-c` flag as in the example below. + +.. code-block:: console + + images serial -g TTL-rising -c SYNC-falling /path/to/file + + + Apply the flatfield correction ============================== From 0d3c39517852e6ab58c4bb514e616654b03688f8 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Tue, 21 Feb 2023 13:50:35 +0000 Subject: [PATCH 11/30] Hack to use the shutter open/close if first/last trigger signal is missing --- src/tristan/command_line/images.py | 46 ++++++++++++++++++++++++------ src/tristan/data.py | 9 +++++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index dca76661..0c271133 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -561,8 +561,10 @@ def gated_images_cli(args): start, end = find_start_end(cues_data) print("Finding gate signal times.") + # Here we assume no synchronization issues: + # falling edges always recorded after rising edges. open_times = cue_times(cues_data, gate_open, after=start) - close_times = cue_times(cues_data, gate_close, after=start) + close_times = cue_times(cues_data, gate_close, before=end) with ProgressBar(): open_times, close_times = dask.compute(open_times, close_times) @@ -570,17 +572,45 @@ def gated_images_cli(args): sys.exit(f"Could not find a '{cues[gate_open]}' signal.") if not close_times.size: sys.exit(f"Could not find a '{cues[gate_close]}' signal.") - if not open_times.size == close_times.size: - sys.exit( - "Found a non-matching number of gate open and close signals:\n\t" - f"Number of '{cues[gate_open]}' signals: {open_times.size}\n\t" - f"Number of '{cues[gate_close]}' signals: {close_times.size}\n" - f"Note that signals before the shutter open time are ignored." - ) open_times = np.sort(open_times) close_times = np.sort(close_times) + if not open_times.size == close_times.size: + # If size difference is just one, look for missing one right before/after + # sutter and use shutter timestamp as first/last gate + if abs(open_times.size - close_times.size) > 1: + sys.exit( + "Found a non-matching number of gate open and close signals:\n\t" + f"Number of '{cues[gate_open]}' signals: {open_times.size}\n\t" + f"Number of '{cues[gate_close]}' signals: {close_times.size}\n" + f"Note that signals before the shutter open time are ignored." + ) + else: + if open_times[-1] > close_times[-1]: + print( + "WARNING! \n\t" + f"Missing last '{cues[gate_close]}' signal.\n\t" + f"Shutter close timestamp will be used instead for last image." + ) + # Append shutter close to close_times + close_times = np.append(close_times, end) + elif open_times[0] > close_times[0]: + print( + "WARNING! \n\t" + f"Missing first '{cues[gate_open]}' signal.\n\t" + f"Shutter open timestamp will be used instead for last image." + ) + # Insert shutter open to open times + open_times = np.insert(open_times, 0, start) + else: + sys.exit( + "Found a non-matching number of gate open and close signals:\n\t" + f"Number of '{cues[gate_open]}' signals: {open_times.size}\n\t" + f"Number of '{cues[gate_close]}' signals: {close_times.size}\n" + # f"Note that signals before the shutter open time are ignored." + ) + num_images = open_times.size if input_nexus.exists(): diff --git a/src/tristan/data.py b/src/tristan/data.py index 3e7dacd8..f6330a99 100644 --- a/src/tristan/data.py +++ b/src/tristan/data.py @@ -146,7 +146,12 @@ def first_cue_time( return data[cue_time_key].loc[first_index] -def cue_times(data: dd.DataFrame, message: int, after: int | None = None) -> da.Array: +def cue_times( + data: dd.DataFrame, + message: int, + after: int | None = None, + before: int | None = None, +) -> da.Array: """ Find the timestamps of all instances of a cue message in a Tristan data set. @@ -165,6 +170,8 @@ def cue_times(data: dd.DataFrame, message: int, after: int | None = None) -> da. index = data[cue_id_key] == message if after: index &= data[cue_time_key] >= after + if before: + index &= data[cue_time_key] <= before return da.unique(data[cue_time_key][index].values) From e957cb7285952402fb51662b1590edb641eef175 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Tue, 21 Feb 2023 14:00:26 +0000 Subject: [PATCH 12/30] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71606604..1a370b67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## - Fixed the axis dimensions for `images pp`. - Added timestamp check and warning on triggers if they happen before/after shutters in `find-tristan-triggers`. +- Added `images serial` for gated access binning of events. ## 0.2.1 - Added dagnostic tool `valid-events` for checking that there are events recorded after the shutter open signal in case the binned image is blank(asynchronicity issue). Also, a couple of small improvements on the other diagnostic tools. From e1682e8ef11fa13743cc1bd4bdd6205f0f067788 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 10:46:48 +0100 Subject: [PATCH 13/30] Try to make the gated_access work --- src/tristan/command_line/images.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 0c271133..04782fe8 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -612,6 +612,7 @@ def gated_images_cli(args): ) num_images = open_times.size + bins = np.linspace(0, num_images, num_images + 1, dtype=np.uint64) if input_nexus.exists(): try: @@ -642,20 +643,31 @@ def gated_images_cli(args): data = valid_events(data, start, end) # Gate the events. - event_times = data[event_time_key].values + event_times = data[event_time_key].astype(np.int64).values open_index = da.digitize(event_times, open_times) - 1 close_index = da.digitize(event_times, close_times) - 1 - data["time_bin"] = open_index - open_times = da.take(open_times, open_index) - close_times = da.take(close_times, close_index) - data = valid_events(data, open_times, close_times) - data = data.drop(columns=event_time_key) + # Look for events that happen after gate open and before gate close + after_open = event_times - da.take(open_times, open_index) + before_close = da.take(close_times, close_index) - event_times + # Eliminate invalid events. + # Valid only if both before and after are positive + valid = (after_open > 0) & (before_close > 0) + valid = dd.from_dask_array(valid, index=data.index) # Convert the event IDs to a form that is suitable for a NumPy bincount. data[event_location_key] = pixel_index(data[event_location_key], image_size) + columns = event_location_key, "time_bin" + dtypes = data.dtypes + dtypes["time_bin"] = dtypes.pop(event_time_key) + + meta = pd.DataFrame(columns=columns).astype(dtype=dtypes) + # Enumerate the image in the stack to which each event belongs + data = data.map_partitions(find_time_bins, bins=bins, meta=meta) + data["time_bin"] = open_index + data = data[valid] + # Bin to images, partition by partition. - meta = pd.DataFrame(columns=data.columns).astype(dtype=data.dtypes) data = dd.map_partitions( make_images, data, image_size, images, meta=meta, enforce_metadata=False ) From 7183e3c48a64f1ed901a3bbb201415eb16192faa Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:07:08 +0100 Subject: [PATCH 14/30] Update versions for docs --- .readthedocs.yaml | 2 +- requirements.txt | 2 +- requirements_dev.txt | 2 +- requirements_doc.txt | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 093a84c1..8746836f 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,7 +11,7 @@ sphinx: # Set the version of Python and optionally declare the requirements required to build your docs python: - version: '3.8' + version: '3.10' install: - method: pip path: . diff --git a/requirements.txt b/requirements.txt index 48376605..1fbf961e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 hdf5plugin==3.3.1 -nexgen==0.6.14 +nexgen==0.6.23 numpy==1.23.5 pandas==1.5.2 Pint==0.20.1 diff --git a/requirements_dev.txt b/requirements_dev.txt index 4c9170d5..1f894323 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -2,7 +2,7 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 hdf5plugin==3.3.1 -nexgen==0.6.14 +nexgen==0.6.23 numpy==1.23.5 pandas==1.5.2 Pint==0.20.1 diff --git a/requirements_doc.txt b/requirements_doc.txt index 45d2f55e..e9f78686 100644 --- a/requirements_doc.txt +++ b/requirements_doc.txt @@ -2,10 +2,10 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 hdf5plugin==3.3.1 -nexgen==0.6.14 +nexgen==0.6.25 numpy==1.23.5 pandas==1.5.2 Pint==0.20.1 -Sphinx==4.5.0 +Sphinx==7.0.0 sphinx-rtd-theme==1.0.0 zarr==2.13.3 From 25c2b085c7cd5faf767259886f798319af2aa9dc Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:10:42 +0100 Subject: [PATCH 15/30] Update versions for docs - try again --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 8746836f..093a84c1 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,7 +11,7 @@ sphinx: # Set the version of Python and optionally declare the requirements required to build your docs python: - version: '3.10' + version: '3.8' install: - method: pip path: . From 36ff926e5ece192d30de831788549a8267fc751b Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:13:48 +0100 Subject: [PATCH 16/30] Update versions for docs - try again part 2 --- requirements.txt | 2 +- requirements_dev.txt | 2 +- requirements_doc.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 1fbf961e..ba618e54 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 -hdf5plugin==3.3.1 +hdf5plugin==4.0.1 nexgen==0.6.23 numpy==1.23.5 pandas==1.5.2 diff --git a/requirements_dev.txt b/requirements_dev.txt index 1f894323..39173e44 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,7 +1,7 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 -hdf5plugin==3.3.1 +hdf5plugin==4.0.1 nexgen==0.6.23 numpy==1.23.5 pandas==1.5.2 diff --git a/requirements_doc.txt b/requirements_doc.txt index e9f78686..de419b60 100644 --- a/requirements_doc.txt +++ b/requirements_doc.txt @@ -1,7 +1,7 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 -hdf5plugin==3.3.1 +hdf5plugin==4.0.1 nexgen==0.6.25 numpy==1.23.5 pandas==1.5.2 From f1deeab9eb8c7e8d6e89446794193ba1d7fa065d Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:15:55 +0100 Subject: [PATCH 17/30] Fix typo --- requirements_doc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_doc.txt b/requirements_doc.txt index de419b60..6b0c7b5f 100644 --- a/requirements_doc.txt +++ b/requirements_doc.txt @@ -2,7 +2,7 @@ dask==2022.11.1 distributed==2022.11.1 h5py==3.7.0 hdf5plugin==4.0.1 -nexgen==0.6.25 +nexgen==0.6.23 numpy==1.23.5 pandas==1.5.2 Pint==0.20.1 From 1aafa36fc3bc0a0e1ae83dee5def52f4f3bcab99 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:20:25 +0100 Subject: [PATCH 18/30] Update versions for docs - try again part 3 --- requirements_doc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_doc.txt b/requirements_doc.txt index 6b0c7b5f..d3b33ef9 100644 --- a/requirements_doc.txt +++ b/requirements_doc.txt @@ -7,5 +7,5 @@ numpy==1.23.5 pandas==1.5.2 Pint==0.20.1 Sphinx==7.0.0 -sphinx-rtd-theme==1.0.0 +sphinx-rtd-theme==1.2.0 zarr==2.13.3 From a7558632d0b8849d7bde41897947f0be5d11c9cb Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:22:46 +0100 Subject: [PATCH 19/30] Update versions for docs - try again part 4 --- requirements_doc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements_doc.txt b/requirements_doc.txt index d3b33ef9..cbd90bae 100644 --- a/requirements_doc.txt +++ b/requirements_doc.txt @@ -6,6 +6,6 @@ nexgen==0.6.23 numpy==1.23.5 pandas==1.5.2 Pint==0.20.1 -Sphinx==7.0.0 +Sphinx==6.2.0 sphinx-rtd-theme==1.2.0 zarr==2.13.3 From 766a955639e6dcc6a5bd99bcb7ce177b166f31ca Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:40:36 +0100 Subject: [PATCH 20/30] Update versions for docs - try again part 5 --- .azure-pipelines/azure-pipelines.yml | 2 +- .readthedocs.yaml | 2 +- src/tristan/command_line/images.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines/azure-pipelines.yml b/.azure-pipelines/azure-pipelines.yml index cd233c27..5d47006c 100644 --- a/.azure-pipelines/azure-pipelines.yml +++ b/.azure-pipelines/azure-pipelines.yml @@ -106,7 +106,7 @@ stages: - task: UsePythonVersion@0 displayName: Set up python inputs: - versionSpec: 3.8 + versionSpec: 3.10 - task: DownloadBuildArtifacts@0 displayName: Get pre-built package diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 093a84c1..8746836f 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,7 +11,7 @@ sphinx: # Set the version of Python and optionally declare the requirements required to build your docs python: - version: '3.8' + version: '3.10' install: - method: pip path: . diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 04782fe8..7ebfa214 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -651,7 +651,7 @@ def gated_images_cli(args): before_close = da.take(close_times, close_index) - event_times # Eliminate invalid events. # Valid only if both before and after are positive - valid = (after_open > 0) & (before_close > 0) + valid = (after_open >= 0) & (before_close > 0) valid = dd.from_dask_array(valid, index=data.index) # Convert the event IDs to a form that is suitable for a NumPy bincount. From 66244e4e1ee35d153aa8bb47fc26da7a376d5417 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 11:42:08 +0100 Subject: [PATCH 21/30] Try removing deprecated version from docs config file --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 8746836f..f53ef02b 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,7 +11,7 @@ sphinx: # Set the version of Python and optionally declare the requirements required to build your docs python: - version: '3.10' + #version: '3.10' install: - method: pip path: . From c80c22ebd0de9624ba73de37bb26d96bc8a820b0 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 12:01:25 +0100 Subject: [PATCH 22/30] Update readthedocs config file --- .readthedocs.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index f53ef02b..c077f19d 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,13 +5,19 @@ # Required version: 2 +# Set the version of python and other tools +build: + os: ubuntu-22.04 + tools: + python: '3.10' + # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py # Set the version of Python and optionally declare the requirements required to build your docs python: - #version: '3.10' + #version: '3.8' install: - method: pip path: . From d8848836ab2468f53003ad57632705ca0ad16a59 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 13:59:26 +0100 Subject: [PATCH 23/30] Fix typo --- src/tristan/command_line/images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 7ebfa214..96f1edb5 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -645,7 +645,7 @@ def gated_images_cli(args): # Gate the events. event_times = data[event_time_key].astype(np.int64).values open_index = da.digitize(event_times, open_times) - 1 - close_index = da.digitize(event_times, close_times) - 1 + close_index = da.digitize(event_times, close_times) # Look for events that happen after gate open and before gate close after_open = event_times - da.take(open_times, open_index) before_close = da.take(close_times, close_index) - event_times From 2b230df108cb3813cfca2bd1ba3a3b28cf0dba98 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 14:03:18 +0100 Subject: [PATCH 24/30] Fix number of bins --- src/tristan/command_line/images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 96f1edb5..f9c611ed 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -612,7 +612,7 @@ def gated_images_cli(args): ) num_images = open_times.size - bins = np.linspace(0, num_images, num_images + 1, dtype=np.uint64) + bins = np.linspace(0, num_images - 1, num_images, dtype=np.uint64) if input_nexus.exists(): try: From 1178a60c9f768bfa4ea76904fa8fcb8d90ac7639 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 14:50:52 +0100 Subject: [PATCH 25/30] Small changes --- src/tristan/command_line/images.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index f9c611ed..b3b3ea21 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -599,7 +599,7 @@ def gated_images_cli(args): print( "WARNING! \n\t" f"Missing first '{cues[gate_open]}' signal.\n\t" - f"Shutter open timestamp will be used instead for last image." + f"Shutter open timestamp will be used instead for first image." ) # Insert shutter open to open times open_times = np.insert(open_times, 0, start) @@ -612,7 +612,7 @@ def gated_images_cli(args): ) num_images = open_times.size - bins = np.linspace(0, num_images - 1, num_images, dtype=np.uint64) + bins = np.linspace(0, num_images, num_images + 1, dtype=np.uint64) if input_nexus.exists(): try: @@ -647,11 +647,12 @@ def gated_images_cli(args): open_index = da.digitize(event_times, open_times) - 1 close_index = da.digitize(event_times, close_times) # Look for events that happen after gate open and before gate close - after_open = event_times - da.take(open_times, open_index) - before_close = da.take(close_times, close_index) - event_times + # after_open = event_times - da.take(open_times, open_index) + # before_close = da.take(close_times, close_index) - event_times # Eliminate invalid events. # Valid only if both before and after are positive - valid = (after_open >= 0) & (before_close > 0) + # valid = (after_open >= 0) & (before_close > 0) + valid = open_index == close_index valid = dd.from_dask_array(valid, index=data.index) # Convert the event IDs to a form that is suitable for a NumPy bincount. From ba947f57043fa297c0bccf40ac92f7c8f3218f1a Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 15:14:53 +0100 Subject: [PATCH 26/30] Small changes --- docs/api.rst | 6 ++++++ docs/usage.rst | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index c5dddd8d..a84e8bae 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -2,6 +2,9 @@ API === +General +======= + .. automodule:: tristan :members: :show-inheritance: @@ -25,6 +28,9 @@ Data Diagnostics API =============== +General +======= + .. automodule:: tristan.diagnostics :members: diff --git a/docs/usage.rst b/docs/usage.rst index 85273dba..76380860 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -106,7 +106,7 @@ To bin events into images gated by trigger signals, use `images serial`, which w the next 'gate-close' signal is taken as the end of the exposure. This tool requires at least the rising edge of the trigger signal, specified with `-g`, to be passed as *gate open* and will then look for the corresponding falling edge -to be used as *gate close*. +to be used as *gate close*. .. code-block:: console @@ -114,7 +114,7 @@ to be used as *gate close*. In some cases, it might be more useful to look at the events collected between different kinds of trigger signals, by specifying the *gate open* signal with `-g` -and the *gate close* using the `-c` flag as in the example below. +and the *gate close* using the `-c` flag as in the example below. .. code-block:: console @@ -122,6 +122,7 @@ and the *gate close* using the `-c` flag as in the example below. +============================== Apply the flatfield correction ============================== From c827abd43b6704654bccece6c65ce8995609270f Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 10 May 2023 15:53:39 +0100 Subject: [PATCH 27/30] Tidy up a bit --- .readthedocs.yaml | 1 - src/tristan/command_line/images.py | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index c077f19d..416a0faf 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -17,7 +17,6 @@ sphinx: # Set the version of Python and optionally declare the requirements required to build your docs python: - #version: '3.8' install: - method: pip path: . diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index b3b3ea21..2b65778d 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -578,7 +578,7 @@ def gated_images_cli(args): if not open_times.size == close_times.size: # If size difference is just one, look for missing one right before/after - # sutter and use shutter timestamp as first/last gate + # shutters and use shutter open/close timestamp as first/last gate if abs(open_times.size - close_times.size) > 1: sys.exit( "Found a non-matching number of gate open and close signals:\n\t" @@ -608,7 +608,6 @@ def gated_images_cli(args): "Found a non-matching number of gate open and close signals:\n\t" f"Number of '{cues[gate_open]}' signals: {open_times.size}\n\t" f"Number of '{cues[gate_close]}' signals: {close_times.size}\n" - # f"Note that signals before the shutter open time are ignored." ) num_images = open_times.size @@ -647,11 +646,7 @@ def gated_images_cli(args): open_index = da.digitize(event_times, open_times) - 1 close_index = da.digitize(event_times, close_times) # Look for events that happen after gate open and before gate close - # after_open = event_times - da.take(open_times, open_index) - # before_close = da.take(close_times, close_index) - event_times - # Eliminate invalid events. - # Valid only if both before and after are positive - # valid = (after_open >= 0) & (before_close > 0) + # Eliminate invalid events by looking at the open and close index valid = open_index == close_index valid = dd.from_dask_array(valid, index=data.index) From 6c8a3a66a3dd354cd9a9f0ebe529b88b19c1ca52 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Thu, 11 May 2023 17:06:20 +0100 Subject: [PATCH 28/30] Tidy up triggers code --- src/tristan/diagnostics/find_trigger_intervals.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tristan/diagnostics/find_trigger_intervals.py b/src/tristan/diagnostics/find_trigger_intervals.py index 27cf8b54..86dbf5a3 100644 --- a/src/tristan/diagnostics/find_trigger_intervals.py +++ b/src/tristan/diagnostics/find_trigger_intervals.py @@ -326,8 +326,6 @@ def main(args): logger.info( f"First SYNC rising edge timestamp: {v['SYNC re'][0]:.4f}." ) - # logger.info(f"First SYNC falling edge timestamp: {v['SYNC fe'][0]:.4f} .") - # logger.info(f"Last SYNC rising edge timestamp: {v['SYNC re'][-1]:.4f} .") logger.info( f"Last SYNC falling edge timestamp: {v['SYNC fe'][-1]:.4f}." ) From 7f34e7c9e342bd870749a95d9884abbaf7235968 Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Thu, 11 May 2023 17:08:47 +0100 Subject: [PATCH 29/30] Clean up import pattern --- src/tristan/command_line/images.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tristan/command_line/images.py b/src/tristan/command_line/images.py index 2b65778d..9172ed0a 100644 --- a/src/tristan/command_line/images.py +++ b/src/tristan/command_line/images.py @@ -29,7 +29,6 @@ find_start_end, find_time_bins, make_images, - valid_events, ) from ..data import ( cue_keys, @@ -41,6 +40,7 @@ latrd_data, pixel_index, seconds, + valid_events, ) from . import ( check_multiple_output_files, From 660efe0103abb957c3578514a4ce2d9f20b4748d Mon Sep 17 00:00:00 2001 From: Noemi Frisina Date: Wed, 21 Jun 2023 11:40:25 +0100 Subject: [PATCH 30/30] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a370b67..45298140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGES -## +## 0.2.2 - Fixed the axis dimensions for `images pp`. - Added timestamp check and warning on triggers if they happen before/after shutters in `find-tristan-triggers`. - Added `images serial` for gated access binning of events.