photonscore.LINTag
LINTag.LINTagRemote
Python remote control interface for the LINTag time tagger.
LINTag is a multi-channel time-to-digital converter (TDC). This module provides a gRPC client to control the LINTag Capture desktop application, which must be running and reachable on the network.
The communication protocol uses a settings diff pattern: stage changes with the setup_* methods, then call LINTagRemote.sync to push them to the device and refresh the read-only status fields (such as the per-channel count rates) in a single round trip.
Configure two channels, watch the correlation, record for a minute:
from photonscore import LINTagRemote
tag = LINTagRemote("192.168.1.10:50052")
tag.setup_channel(0, threshold=-0.5, rising_edge=True)
tag.setup_channel(1, threshold=-0.5, rising_edge=True)
tag.setup_correlator(start_channel=0, stop_channel=1, window_ps=50000)
tag.sync() # apply config, read back device state
print(tag.cps) # live count rate per channel (8 values)
time_ns, counts = tag.get_histogram()
time_s, cps = tag.get_counts() # the CPS plot, last 60 s at 25 Hz
tag.start_recording("run.photons", seconds=60, chunks=True)
# ... acquisition runs on the device ...
tag.stop_recording()Dependencies: grpc, numpy, photonscore.proto.lintag_v1_remote_pb2 (generated from photonscore/proto/lintag_v1_remote.proto)
LINTagRemote
class LINTagRemote(target = None)Remote control handle for a LINTag time tagger.
Wraps the gRPC LINTagRemote service exposed by the LINTag Capture application. Configuration changes are staged locally in new_settings; call sync to commit them and read the current device state back into read_settings.
The channel grid is fixed at 8 channels (indices 0-7).
Unlike photonscore.LINCam.LINCamRemote.LINCamRemote, the constructor does not sync automatically, so read-only fields such as cps are empty until the first sync.
Attributes
grpc_target(str): Resolvedhost:portof the gRPC server.grpc_channel(grpc.Channel): Underlying insecure gRPC channel. Send and receive message limits are raised to 1 GiB to accommodate large settings/state payloads.grpc_client(LINTagRemoteStub): Generated gRPC stub.new_settings(LINTagRemoteSettings): Buffer of changes staged but not yet sent to the device.read_settings(LINTagRemoteSettings): Device state returned by the most recentsync.
sync
def sync()Push pending settings to the device and refresh all status fields.
Sends the accumulated new_settings diff via the Sync RPC. The reply — the full device state as it was before this call's changes — lands in read_settings; call sync again to read the applied values back. After the call new_settings is reset so the next sync only sends newly staged changes.
Calling this with nothing staged is a harmless way to poll the current device state (e.g. to refresh cps).
cps
property
cpsnumpy.ndarray: Per-channel count rate in Hz, one entry per channel (8).
Reflects the device state from the most recent sync; call sync first to refresh it.
setup_channel
def setup_channel(
channel,
threshold = None,
offset_ns = None,
dead_time_ps = None,
prolonged_dead_time = None,
divider = None,
temrinate_50_ohm = None,
rising_edge = None,
falling_edge = None,
static_calibration = None,
gate_reference = None,
)Stage configuration changes for a single input channel.
Only the parameters passed as non-None are written; the rest are left untouched on the device. Changes are buffered and take effect on the next sync.
Arguments
channel(int): Channel index to configure (0-7).threshold(float): Discriminator threshold, in volts (-2 to 2.5).offset_ns(float): Per-channel timing offset applied to timestamps, in nanoseconds (-100 to 100).dead_time_ps(int): Dead time after a detected edge during which further edges are ignored, in picoseconds (0 to 100000).prolonged_dead_time(bool): IfTrue, the dead time is extended for events detected during the dead time (suppresses afterpulsing).divider(int): Hardware prescaler; only every n-th event is recorded (1 to 32).temrinate_50_ohm(bool): Terminate the channel input with 50 Ω (Falseleaves it high impedance). The parameter name matches the proto field spelling.rising_edge(bool): Track and record the rising edge.falling_edge(bool): Track and record the falling edge.static_calibration(bool): IfTrue, fix the channel calibration. Needed for signals correlated with the LINTag clock.gate_reference(bool): Make this input a reference of the reference gate, with both its edges. Needsgate_available; seesetup_gate.
setup_gate
def setup_gate(enable = None, epochs_before = None, epochs_after = None)Stage reference gate changes; applied on the next sync.
The gate drops tags on the reference channels in the FPGA unless a hit on some other channel falls into a window around them, which is how a laser sync is kept out of the recording except where it is wanted. Mark the references with gate_reference of setup_channel; this method switches the gate on and sets the window.
Only the parameters passed as non-None are written. Requires firmware with the gate — check gate_available first, or the next sync raises FAILED_PRECONDITION.
Arguments
enable(bool): Run the gate.Falsekeeps the references and the window as set but the hardware sees no references.epochs_before(int): Window before a hit, in epochs of 32 ns (0 to 16).epochs_after(int): Window after a hit, in epochs of 32 ns (0 to 16). With both windows 0 every reference tag is dropped.
gate_available
property
gate_availablebool: Whether the firmware has the reference gate, from the most recent sync. Writing any gate field without it is refused.
setup_clock
def setup_clock(source)Stage a TDC clock source change; applied on the next sync.
Arguments
source(str):"internal","external_10mhz"or"external_50mhz".
clock_source
property
clock_sourcestr: Clock source from the most recent sync (see setup_clock for values), or "unknown" before the first one.
clock_frequency_mhz
property
clock_frequency_mhzfloat: Measured TDC clock frequency in MHz from the most recent sync.
setup_correlator
def setup_correlator(
is_correlating = None,
start_channel = None,
start_falling = None,
stop_channel = None,
stop_falling = None,
stop_offset_ps = None,
window_ps = None,
bin_size_ps = None,
correlator_type = None,
rolling_window_ms = None,
)Stage configuration changes for the online correlator.
Only the parameters passed as non-None are changed. Changes are buffered and take effect on the next sync.
Arguments
is_correlating(bool): Run the online correlator.start_channel(int): Start channel index (0-7).start_falling(bool): Correlate the start channel's falling edge instead of the rising one.stop_channel(int): Stop channel index (0-7).stop_falling(bool): Correlate the stop channel's falling edge instead of the rising one.stop_offset_ps(int): Offset added to stop timestamps, in picoseconds.window_ps(int): Histogram half-width in picoseconds (3000 to 1000000); the histogram spans-window..+window.bin_size_ps(int): Histogram bin size, one ofBIN_SIZES_PS.correlator_type(str):"start_stop"or"multi_start_stop".rolling_window_ms(int): Temporal accumulation window, one ofROLLING_WINDOWS_MS; 0 accumulates forever.
correlator_type
property
correlator_typestr: Correlator type from the most recent sync (see setup_correlator for values).
get_histogram
def get_histogram(clear_after = False) -> tupleFetch the online correlator histogram.
Arguments
clear_after(bool): Clear the correlator right after the histogram is taken, starting a fresh accumulation.
Returns: tuple A (time_ns, counts) tuple: bin centers in nanoseconds as
Returns: tuple numpy.float64 and bin counts as numpy.uint32, spanning
Returns: tuple -window..+window.
get_counts
def get_counts(clear_after = False) -> tupleFetch the count-rate history behind the GUI's CPS plot.
Independent of sync: the device keeps a rolling buffer per channel, the last 60 s at 25 Hz, and this reads it whole. Use it where cps — a single instantaneous value per channel — is too coarse.
Arguments
clear_after(bool): Clear the buffers right after the read, as the GUI's Clear Countrates does.
Returns: tuple (time_s, cps) - sample times in seconds relative to the read as numpy.float64, negative into the past, and an 8 by len(time_s) array of count rates in Hz as numpy.uint32, one row per channel, oldest sample first.
queues
property
queuesdict: Backpressure from the most recent sync — the GUI's "Enqueued for" numbers, as decoder, correlator and recorder.
A queue that climbs and does not come back is the acquisition falling behind; correlator_overflow and recorder_overflow are these crossing their limits.
clear_correlator
def clear_correlator()Clear the correlation histogram, like the GUI's Clear Correlator.
Any other staged changes are committed in the same call.
clear_cps
def clear_cps()Clear the count-rate history, like the GUI's Clear Countrates.
Any other staged changes are committed in the same call.
start_recording
def start_recording(
filename = None,
seconds = None,
chunks = False,
chunk_seconds = None,
)Start recording tagged events to a file on the device.
Calls sync immediately; any changes staged beforehand are committed in the same call. The GUI mirrors the running recording.
Arguments
filename(str): Destination.photonspath on the machine running LINTag Capture. Omit to reuse the already-set path (the file number keeps incrementing); an empty string stops recording (deprecated, usestop_recording).seconds(int): Record for this long. Withoutchunksthe recording stops by itself; withchunksit rotates to a new numbered file instead. Omit for one endless recording.chunks(bool): Rotate to a new file everysecondsseconds untilstop_recording. Requiresseconds.chunk_seconds(int): Deprecated alias forseconds=..., chunks=True.
stop_recording
def stop_recording()Stop the current recording; the file path and numbering are kept.
is_recording
property
is_recordingbool: Whether a recording ran at the most recent sync.
file_number
property
file_numberint: Number of the recording file being written (or next to write).
file_photon_count
property
file_photon_countint: Events written to the current recording file so far.
acquisition_seconds
property
acquisition_secondsfloat: Time the current recording file has been open, 0 when idle.
recorder_overflow
property
recorder_overflowbool: The recorder queue is nearly full and may drop events.
correlator_overflow
property
correlator_overflowbool: The correlator queues overflow and drop events.