Measuring Coincidences

Quantum interference lies at the heart of photon-based technologies, such as photonic quantum computing, quantum metrology, and quantum networks. One of the key requirements for high-fidelity operations in these technologies is the indistinguishability of photons, a key property of quantum states. The level of indistinguishability between two photons is typically determined by measuring the Hong–Ou–Mandel (HOM) interference visibility: if the photons are identical and enter separately a balanced beam splitter, they will always exit the beam splitter together in the same output mode. If a detector is set up on each of the outputs, then the photons cannot be separately detected by the two detectors simultaneously. Thus, coincidence measurements enable the detection and analysis of correlated events, notably the simultaneous detection of entangled photons. When more than two photons are involved in a multiphoton quantum interference experiment, the interference capability extends beyond the pairwise distinguishability, and generalizations of the HOM effect to the many-particle case have been recently proposed. One method to quantify the n-photon indistinguishability relies on a cyclic multiport interferometer with N = 2n optical modes, composed of 2n beam splitters placed along two cascaded layers. The quantum interference pattern, resulting from the injection of n indistinguishable photons into the 2n ports-interferometer and obtained through a multiphoton coincidence detection, is a direct measurement of the n-photon indistinguishability.


This tutorial shows how to set up a measurement to count coincidence events between groups of input channels. In our example, we count fourth-order coincidences between four photons injected into an integrated eight-mode cyclic interferometer.

Time Tagger configuration

To perform our coincidence-counting experiment, we first connect the Time Tagger and select the channels used.

tagger = createTimeTagger()
input_channels = tagger.getChannelList(ChannelEdge.Rising)[:8]

The Time Tagger hardware allows you to specify a trigger level voltage for each input channel. The default trigger level is 0.5 V. In our example, we set the trigger level to 0.3 V for all the channels.

for ch in input_channels:
     tagger.setTriggerLevel(ch, 0.3)


Our protocol for counting coincidence events is schematically illustrated in the figure below. For clear visualization, the diagram considers coincidences for two groups of three channels among four input channels used. First, we define a time window as the largest time difference between events on the input channels to be considered as a coincidence (size of rectangular shaded colored areas). Next, we generate new streams of tags, which correspond to coincidence events occurring for each group of input channels (Coincidence [1, 2, 3] and Coincidence [2, 3, 4]). Finally, we count the events on each channel (bottom panel).


Our method can be implemented by creating the virtual channel Coincidences, which detects coincidence clicks on multiple channel groups within the given coincidenceWindow. In this regard, it is good to remember that this is a software-defined channel; therefore, it receives time-tags from the physical input channels and generates a new data stream in the PC. The Time Tagger does not detect coincidences onboard the hardware.

In our example, we consider fourth-order coincidence events from eight input channels.

order = 4
groups = list(itertools.combinations(input_channels, order)

coincidences_vchannels = Coincidences(tagger, groups, coincidenceWindow=100)

Finally, the physical input channels and the Coincidences virtual channel are fed into the Counter measurement class.

#Generate a list including input and virtual channels
channels = [*input_channels, *coincidences_vchannels.getChannels()]

counting = Counter(tagger, channels, 1e10, 300)

measurementDuration = 10e12 # 10 s

index = counting.getIndex()
counts = counting.getData()

Delay adjustment for coincidence detection

When detecting coincidence events, it is essential to have signals aligned in time. Delays between channels inevitably arise from experimental conditions, such as different optical paths or cable lengths, and inherent delays in the detectors. Such delays can be compensated in the Time Tagger by providing a proper input delay.


If the signals are sufficiently correlated, the best way to quantify the time misalignment between the channels is to perform multiple Correlation measurements. The peak of the Correlation curve between two channels is centered at the relative delay. This value is employed a posteriori to compensate the time misalignment between the two channels. In our example, we keep the first channel as a reference and alternatively measure the Correlation between it and all the others. Finally, we align all the signals in time, using setInputDelay() method.

# Set input delays to 0, otherwise the compensation result will be incorrect.
for ch in input_channels:
    tagger.setInputDelay(ch, 0)

# Create SynchronizedMeasurements to operate on the same time tags.
sm = SynchronizedMeasurements(tagger)

#Create Correlation measurements
corr_list = list()
for ch in input_channels[1:]:
        Correlation(sm.getTagger(), input_channels[0], ch, binwidth=1, n_bins=5000)

# Start measurements and accumulate data for 1 second
sm.startFor(int(1e12), clear=True)

# Determine delays
delays = list()
for corr in corr_list:
    hist_t = corr.getIndex()
    hist_c = corr.getData()
    #Identify the delay as the center of the histogram through a weighted average
    dt = np.sum(hist_t * hist_c) / np.sum(hist_c)

print("Delays:", delays)

# Compensate the delays to align the signals
for ch, dt in zip(input_channels[1:], delays):
    tagger.setInputDelay(ch, dt)

You can check that the delays are properly compensated by repeating the Correlation measurements and verifying that the histograms are centered at zero.

Exclusive coincidences using Combinations virtual channel

The indistinguishability of the input photons in a quantum interferometry experiment results in a large number of forbidden output configurations, among the possible many-particle states. This can be viewed as the generalization of the original two-photon HOM effect extended to the case of multiple ports and photons. In this regard, it turns out to be beneficial to consider coincidence measurements with specific restrictions. For instance, excluding certain coincidences based on the occurrence of events happening right before or after them can be important e.g., to eliminate the effect of background noise, hence for refining quantum state tomography or interference studies.

The best approach to achieve this goal is to employ the virtual channel Combinations. It detects coincidence clicks on all possible (2^N{-}1) channel subgroups from a given number (N) of channels, when no additional events occur within two guard windows, one preceding the first event starting the coincidence, the other following the last event concluding the coincidence. We report below a representative sketch of Combinations virtual channel given three input channels.


It should be noted that the combination of events on channels 1, 2, 3 results in the generation of a timestamp exclusively on the virtual channel VCH{1,2,3} and not on VCH{1,3} or VCH{2}. This distinction, however, does not apply to the virtual channel Coincidences, as the coincidences between channels 1, 2, and 3 constitute a subset of coincidences between 1 and 3. Contextualizing this to the quantum interferometry experiment with four input photons and eight output ports, coincidences of order higher than four, made possible only by dark counts, are discarded on the fourth-order combinations. This is true if all eight channels are input to the Combinations virtual channel.

In the following minimal example, we demonstrate how to obtain the virtual channel numbers for fourth-order combinations, that can be input to the Counter measurement class. The goal of the example is to ensure that each combination includes at least one number from each of the sets {1, 2}, {3, 6}, {4, 5}, and {7, 8}.

# Create the Combinations virtual channel
combinations_vchannels = Combinations(tagger, input_channels, window_size=100)

#Define sets of inclusion
set1 = {1, 2}
set2 = {3, 6}
set3 = {4, 5}
set4 = {7, 8}

# Filter combinations of four channels groups based on conditions
filtered_combinations = [list(comb) for comb in groups
                      if any(num in set1 for num in comb)
                      and any(num in set2 for num in comb)
                      and any(num in set3 for num in comb)
                      and any(num in set4 for num in comb)]

# Create a list with the virtual channels monitoring the combinations
virtualchannelsnumber = []
for group in filtered_combinations:

Coincidence-counting vs Correlation Measurement

Let us now assume in the following discussion to have only two channels. In this scenario, a coincidence-counting experiment could be also performed using other measurement classes, such as Correlation. The latter is a multi start, multi stop measurement, which means that every start click is correlated with every stop click as far they are within the Correlation time span. This implies that Correlation takes into account both positive and negative time differences. On the other hand, the “Coincidence + Counter” approach does not discriminate the order of the clicks, as the virtual channel detects an event whenever the time tags on the two channels are separated within the coincidenceWindow, regardless of whether this time difference is negative or positive.

Coincidence counts can be retrieved by summing up a few bins of the Correlation histogram around zero time difference, depending on the size of the defined coincidence window. However, there is one point to consider for getting the correct number of coincidinces using Correlation measurement class. Please see the figure below.


When summing the bins of the Correlation together to get coincidence counts, the bin alignment must be taken into account, to get consistent results from the two analyses. It is indeed important to properly choose the binsize in Correlation such that the edges of the two outer bins align with the coincidenceWindow.