def plot_marker_filter_comparison(a, mrkr_chan=2, ret=False, **kw):
    pqf = a.pqf

    # get the PLU marked photons first
    is_ph_ch0, is_ph_ch1 = pq_tools.get_photons(pqf)
    is_ph = is_ph_ch0 | is_ph_ch1
    is_ph_with_PLU_mrkr = is_ph & pq_tools.filter_marker(pqf, mrkr_chan)

    # sp_lt = pqf['/PQ_special-1'].value # Special: marker channel
    # sn_lt = pqf['/PQ_sync_number-1'].value # Sync number: the number of the last sync signal

    # uniqueVals, uniqueCounts = np.unique(sn_lt[(sp_lt == 0)], return_counts  = True)
    # dupVals = uniqueVals[uniqueCounts>1]
    # uniqueSync = np.logical_not(np.in1d(sn_lt,dupVals))
    # is_ph_with_PLU_mrkr = is_ph_with_PLU_mrkr & uniqueSync

    # adwin_filter,adwin_syncs = a.filter_adwin_data_from_pq_syncs(sn_lt)
    # reps = (a.agrp['counted_awg_reps'].value)
    # LDE_attempts = (((reps - np.append([0],reps[:-1]))-1) % (a.g.attrs['LDE_attempts'])) + 1
    # LDE_attempts = LDE_attempts[adwin_filter]

    # is_ph_with_PLU_mrkr = is_ph_with_PLU_mrkr & (LDE_attempts < a.g.attrs['LDE_attempts'])

    if ret:
        return pq_plots.plot_photon_hist_filter_comparison(
            pqf, fltr=is_ph_with_PLU_mrkr, **kw)
    else:
        pq_plots.plot_photon_hist_filter_comparison(pqf,
                                                    fltr=is_ph_with_PLU_mrkr,
                                                    **kw)
Beispiel #2
0
def plot_marker_filter_comparison(pqf,mrkr_chan = 2,**kw):

    # get the PLU marked photons first
    is_ph_ch0, is_ph_ch1 = pq_tools.get_photons(pqf)
    is_ph = is_ph_ch0 | is_ph_ch1
    is_ph_with_PLU_mrkr = is_ph & pq_tools.filter_marker(pqf, mrkr_chan)
    plot_photon_hist_filter_comparison(pqf,fltr =is_ph_with_PLU_mrkr,**kw)
Beispiel #3
0
    def make_single_hist(self, a, channel, st_start, st_len, bin_size):

        is_ph = pq_tools.get_photons(a.pqf)[channel]
        bins = np.arange(st_start - .5, st_start + st_len, bin_size)
        y, x = np.histogram(a.pqf['/PQ_sync_time-1'].value[np.where(is_ph)],
                            bins=bins)
        x = x[:-1]

        return x, y
Beispiel #4
0
    def get_total_number_of_clicks_in_window(self, a, channel, st_start,
                                             st_len):

        is_ph = pq_tools.get_photons(a.pqf)[channel]
        bins = np.arange(st_start - .5, st_start + st_len, 1e3)
        y, x = np.histogram(a.pqf['/PQ_sync_time-1'].value[np.where(is_ph)],
                            bins=bins)
        x = x[:-1]
        # print 'Total clicks:', np.sum(y)

        return np.sum(y)
Beispiel #5
0
    def plot_histogram(self,
                       channel,
                       start=None,
                       length=None,
                       fltr=None,
                       hist_binsize=1,
                       save=True,
                       **kw):
        ret = kw.get('ret', None)
        ax = kw.get('ax', None)
        log_plot = kw.get('log_plot', True)
        if ax == None:
            fig = self.default_fig(figsize=(6, 4))
            ax = self.default_ax(fig)
        else:
            save = False

        if start == None:
            start = self.g.attrs['MIN_SYNC_BIN']
        if length == None:
            stop = self.g.attrs['MAX_SYNC_BIN']
        else:
            stop = start + length

        is_ph = pq_tools.get_photons(self.pqf)[channel]
        if fltr == None:
            fltr = is_ph
        else:
            fltr = fltr & is_ph

        bins = np.arange(start - .5, stop, hist_binsize)
        y, x = np.histogram(self.pqf[self.pq_device +
                                     '/PQ_sync_time-1'].value[np.where(fltr)],
                            bins=bins)
        x = x[:-1]
        print 'Total clicks:', np.sum(y)
        y = y / float(self.reps)

        if log_plot:
            ax.semilogy(x, y)
        else:
            ax.plot(x, y)
        #ax.colorbar()
        ax.set_xlabel('Time [bins]')
        ax.set_ylabel('Counts per rep per bin')
        if save:
            self.save_fig_incremental_filename(
                fig, 'histogram_chan_{}'.format(channel))

        if ret == 'ax':
            return ax
        if ret == 'fig':
            return fig
Beispiel #6
0
def plot_marker_filter_comparison(pqf, mrkr_chan=2, ret=False, **kw):

    # get the PLU marked photons first
    is_ph_ch0, is_ph_ch1 = pq_tools.get_photons(pqf)
    is_ph = is_ph_ch0 | is_ph_ch1
    is_ph_with_PLU_mrkr = is_ph & pq_tools.filter_marker(pqf, mrkr_chan)
    if ret:
        return plot_photon_hist_filter_comparison(pqf,
                                                  fltr=is_ph_with_PLU_mrkr,
                                                  **kw)
    else:
        plot_photon_hist_filter_comparison(pqf, fltr=is_ph_with_PLU_mrkr, **kw)
Beispiel #7
0
def plot_marker_filter_comparison(pqf_list,mrkr_chan = 2,ret=False,**kw):

    is_ph_with_PLU_mrkr = []
    for pqf in pqf_list:
        # get the PLU marked photons first
        is_ph_ch0, is_ph_ch1 = pq_tools.get_photons(pqf)
        is_ph = is_ph_ch0 | is_ph_ch1
        is_ph_with_PLU_mrkr.append(is_ph & pq_tools.filter_marker(pqf, mrkr_chan))

    if ret:
        return pq_plots.plot_photon_hist_filter_comparison(pqf_list,fltr =is_ph_with_PLU_mrkr,**kw)
    else:
        pq_plots.plot_photon_hist_filter_comparison(pqf_list,fltr =is_ph_with_PLU_mrkr,**kw)
Beispiel #8
0
 def get_fastssro_results(self,channel,pq_binsize_ns, hist_binsize_ns):
     if not hasattr(self,'reps'):
         self.get_readout_results('ssro')
     if not hasattr(self, 'sweep_pts'):
         print 'get_sweep_pts first'
         return
     if not hasattr(self, 'sweep_idxs'):
         print 'get_sweep_idxs first'
         return
     sync_nrs=self.pqf['/PQ_sync_number-1'].value
     if sync_nrs[-1] != self.reps:
         print 'WARNING last sync number ({}) != noof reps ({})! Sync error?'.format(sync_nrs[-1],self.reps)
     self.reps_per_sweep = float(self.reps)/len(self.sweep_pts)
     self.is_ph = pq_tools.get_photons(self.pqf)[channel]
     self.hist_binsize_ns = hist_binsize_ns
     self.sync_time_ns = self.pqf['/PQ_sync_time-1'].value * pq_binsize_ns
     self.extra_time_ns = (self.g.attrs['wait_length'])*1e9-100 #self.g.attrs['pq_sync_length']+
Beispiel #9
0
    def plot_histogram(self,channel,start=None,length=None,fltr=None,hist_binsize=1,save=True, **kw):
        ret = kw.get('ret', None)
        ax = kw.get('ax', None)
        log_plot=kw.get('log_plot',True)
        if ax == None:
            fig = self.default_fig(figsize=(6,4))
            ax = self.default_ax(fig)
        else:
            save = False

        if start==None:
            start=self.g.attrs['MIN_SYNC_BIN']
        if length == None:
            stop = self.g.attrs['MAX_SYNC_BIN']
        else:
            stop = start + length

        is_ph = pq_tools.get_photons(self.pqf)[channel]
        if fltr == None:
            fltr=is_ph
        else:
            fltr=fltr & is_ph

        bins = np.arange(start-.5,stop,hist_binsize)
        y,x=np.histogram(self.pqf['/PQ_sync_time-1'].value[np.where(fltr)], bins=bins)
        x=x[:-1]
        print 'Total clicks:', np.sum(y)
        y=y/float(self.reps)
        
        if log_plot:
            ax.semilogy(x,y)
        else:
            ax.plot(x,y)
        #ax.colorbar()
        ax.set_xlabel('Time [bins]')
        ax.set_ylabel('Counts per rep per bin')

        if save:
            self.save_fig_incremental_filename(fig,'histogram_chan_{}'.format(channel))
        
        if ret == 'ax':
            return ax
        if ret == 'fig':
            return fig
Beispiel #10
0
def plot_PLU_filter(pqf,chan = 2):

    # get the PLU marked photons first
    is_ph_ch0, is_ph_ch1 = pq_tools.get_photons(pqf)
    is_ph = is_ph_ch0 | is_ph_ch1
    is_ph_with_PLU_mrkr = is_ph & pq_tools.filter_marker(pqf, chan)

    # first window
    fig, (ax0, ax1) = plot_photon_hist_filter_comparison(
        pqf, save=False, fltr=is_ph_with_PLU_mrkr, log=True,
        binedges=settings.PHOTONHIST_BINEDGES)

    ax0.axvline(settings.CH0_START, color='k', linestyle='--')
    ax0.text(settings.CH0_START+1, 1, '{} ns'.format(settings.CH0_START), color='k')
    ax0.legend()
    ax0.set_title('PLU (hardware) filter first pi-pulse ch0')

    ax1.axvline(settings.CH1_START, color='k', linestyle='--')
    ax1.text(settings.CH1_START+1, 1, '{} ns'.format(settings.CH1_START), color='k')
    ax1.legend()
    ax1.set_title('PLU (hardware) filter first pi-pulse ch1')

    fig.savefig(os.path.join(folder, 'PLU_photons_window1.png'))

    # second window
    fig, (ax0, ax1) = plot_photon_hist_filter_comparison(
        pqf, save=False, fltr=is_ph_with_PLU_mrkr, log=True,
        binedges=settings.PHOTONHIST_BINEDGES + settings.PIPULSESEP)

    ax0.axvline(settings.CH0_START+settings.PIPULSESEP, color='k', linestyle='--')
    ax0.text(settings.CH0_START+settings.PIPULSESEP+1, 
        1, '{} ns'.format(settings.CH0_START+settings.PIPULSESEP), color='k')
    ax0.legend()
    ax0.set_title('PLU (hardware) filter second pi-pulse ch0')

    ax1.axvline(settings.CH1_START+settings.PIPULSESEP, color='k', linestyle='--')
    ax1.text(settings.CH1_START+settings.PIPULSESEP+1, 
        1, '{} ns'.format(settings.CH1_START+settings.PIPULSESEP), color='k')
    ax1.legend()
    ax1.set_title('PLU (hardware) filter second pi-pulse ch1')
     
    fig.savefig(os.path.join(folder, 'PLU_photons_window2.png'))
Beispiel #11
0
 def get_fastssro_results(self, channel, pq_binsize_ns, hist_binsize_ns):
     if not hasattr(self, 'reps'):
         self.get_readout_results('ssro')
     if not hasattr(self, 'sweep_pts'):
         print 'get_sweep_pts first'
         return
     if not hasattr(self, 'sweep_idxs'):
         print 'get_sweep_idxs first'
         return
     sync_nrs = self.pqf[self.pq_device + '/PQ_sync_number-1'].value
     if sync_nrs[-1] != self.reps:
         print 'WARNING last sync number ({}) != noof reps ({})! Sync error?'.format(
             sync_nrs[-1], self.reps)
     self.reps_per_sweep = float(self.reps) / len(self.sweep_pts)
     self.is_ph = pq_tools.get_photons(self.pqf)[channel]
     self.hist_binsize_ns = hist_binsize_ns
     self.sync_time_ns = self.pqf[self.pq_device +
                                  '/PQ_sync_time-1'].value * pq_binsize_ns
     self.extra_time_ns = (self.g.attrs['wait_length']
                           ) * 1e9 - 100  #self.g.attrs['pq_sync_length']+
Beispiel #12
0
    def get_tail_vs_sweep(self, channel, start_ns, tail_length_ns, pq_binsize_ns=1e-3, hist_binsize_ns=1.0, verbose= False):
        """
        Integrate & make a time histogram of all photon clicks on given channel,
        that arrive between start_ns and start_ns+tail_length_ns.
        Normalizes the integrated result to 1/(self.reps*syncs_per_sweep/self.sweep_length)
        """
        if not hasattr(self,'reps'):
            self.get_readout_results('ssro')
        if not hasattr(self, 'sweep_pts'):
            print 'get_sweep_pts first'
            return
        if not hasattr(self, 'sweep_idxs'):
            print 'get_sweep_idxs first'
            return

        self.start_ns = start_ns

        is_ph = pq_tools.get_photons(self.pqf)[channel]
        sync_time_ns = self.pqf['/PQ_sync_time-1'].value * pq_binsize_ns

        hist_bins = np.arange(self.start_ns-hist_binsize_ns*.5,self.start_ns+1*tail_length_ns+hist_binsize_ns,hist_binsize_ns)
        
        self.tail_hist_h=np.zeros((self.sweep_length,len(hist_bins)-1))
        
        st_fltr = (self.start_ns  <= sync_time_ns) &  (sync_time_ns< (self.start_ns + tail_length_ns))
        if verbose:
            print 'total_photons in channel', channel, ':', len(sync_time_ns[np.where(is_ph)])  
            print 'total_photons in window:', len(sync_time_ns[np.where(is_ph & st_fltr)]) 
        valid_tail_idxs = self.sweep_idxs[np.where(is_ph & st_fltr)]
        if verbose:

            print 'total_sweeps in window:', len(valid_tail_idxs) 
            print 'total ph in window with sweep element 0:', len(np.where(valid_tail_idxs==0)[0])
            print 'div factor:', (self.reps*self.syncs_per_sweep/self.sweep_length)
        self.tail_cts_per_sweep_idx=np.zeros(self.sweep_length)
        
        for sweep_idx in range(self.sweep_length):
            self.tail_cts_per_sweep_idx[sweep_idx]= \
                                float(len(np.where(valid_tail_idxs==sweep_idx)[0])) / (self.reps*self.syncs_per_sweep/self.sweep_length)
            self.tail_hist_h[sweep_idx], self.tail_hist_b = \
                                np.histogram(sync_time_ns[np.where(is_ph & (self.sweep_idxs == sweep_idx))], bins=hist_bins)
Beispiel #13
0
def get_clicks(pqf, index = 1, pq_device = ''):


    sync_time_name = pq_device + '/PQ_sync_time-' + str(index)
    tot_time_name =  pq_device + '/PQ_time-' + str(index)
    sync_num_name = pq_device + '/PQ_sync_number-' + str(index)

    sync_time = pqf[sync_time_name].value
    total_time = pqf[tot_time_name].value
    sync_number = pqf[sync_num_name].value

    is_ph0, is_ph1 = pq_tools.get_photons(pqf)
    # thin down a bit with loose filtering

    st0 = sync_time[is_ph0]
    sn0 = sync_number[is_ph0]
    
    st1 = sync_time[is_ph1]
    sn1 = sync_number[is_ph1]

    return np.array([st0,sn0]).T,np.array([st1,sn1]).T
Beispiel #14
0
def ZPL_tail_analysis_per_run(BS_fp_len, fp, fp_LT1, ch0_start, ch1_start, ch0_stop, ch1_stop, dif_win1_win2,Verbose = True):

    # Initalizes file in which data is saved
    Tail_analysis = np.empty([5,BS_fp_len])

    for i in np.arange(BS_fp_len):
    
        # Opens file to retrieve BS sync times, numbers and filters for photons in channel 0 or 1
        f = h5py.File(fp[i], 'r')
        sync_numbers = f['/PQ_sync_number-1'].value
        sync_times = f['/PQ_sync_time-1'].value
        is_ph0, is_ph1 = pq_tools.get_photons(f)
        f.close()

        # Opens file to retrieve number of repetitions
        g = h5py.File(fp_LT1[i],'r')
        for k in g.keys():
            if type(g[k])==h5py.Group and not 'analysis' in k:
                Completed_reps = g[('/'+ str(k) + '/ssro/completed_reps')].value
        g.close()

        # Calculates the total repetitions
        Total_reps =  Completed_reps * 250
    
        # Makes a filter for events that are photons
        is_photon = is_ph0 | is_ph1
    
        # Makes a list of sync times for photons in channel 0 and 1
        sync_times_ph0 = sync_times[is_ph0]
        sync_times_ph1 = sync_times[is_ph1]
    
        """
        Note that all filters below can only be applied on sync_times_ph0 or sync_times_ph1 arrays with the same length
        """
    
        # Filters events in channel 0 on being in the first window or the second window, windows are set above
        is_event_first_window_ph0 = (sync_times_ph0 > ch0_start * 1e3) & \
                         (sync_times_ph0 <= ch0_stop * 1e3)
        is_event_second_window_ph0 = (sync_times_ph0 > ch0_start * 1e3 + dif_win1_win2 * 1e3) & \
                          (sync_times_ph0 <= ch0_stop * 1e3 + dif_win1_win2 * 1e3)
        # Filters events in channel 1 on being in the first window or the second window, windows are set above
        is_event_first_window_ph1 = (sync_times_ph1 > ch1_start * 1e3) & \
                         (sync_times_ph1 <= ch1_stop * 1e3)
        is_event_second_window_ph1 = (sync_times_ph1 > ch1_start *1e3 + dif_win1_win2 * 1e3) & \
                          (sync_times_ph1 <= ch1_stop * 1e3 + dif_win1_win2 * 1e3)
        
        # Calculates the amount of photons in the first or second window for both channel
        photons_first_window_ph0 = sum(is_event_first_window_ph0)
        photons_second_window_ph0 = sum(is_event_second_window_ph0)
        photons_first_window_ph1 = sum(is_event_first_window_ph1)
        photons_second_window_ph1 = sum(is_event_second_window_ph1)

        # Combines the photons from both channels
        photons_first_window = photons_first_window_ph0 + photons_first_window_ph1
        photons_second_window = photons_second_window_ph0 + photons_second_window_ph1
        Total_number_of_photons = sum(is_photon)

        # Normalize the amount of photons with respect to the total amount of repetitions
        photons_first_window_per_rep = photons_first_window / float(Total_reps)
        photons_second_window_per_rep = photons_second_window / float(Total_reps)
    
        # Saves calculated data
        Tail_analysis[:,i] = [Total_number_of_photons, photons_first_window, photons_second_window,\
                          photons_first_window_per_rep, photons_second_window_per_rep]

        if Verbose:
            print "Run: ", i+1
            print "Total number of photons: ", Total_number_of_photons
            print "Number of photons in first window", photons_first_window
            print "Number of photons in second window", photons_second_window
            print "Number of photons in first window per repetetion", photons_first_window_per_rep
            print "Number of photons in second window per repetetion", photons_second_window_per_rep
            print
    
    return Tail_analysis 
Beispiel #15
0
    def get_tail_vs_sweep(self,
                          channel,
                          start_ns,
                          tail_length_ns,
                          pq_binsize_ns=1e-3,
                          hist_binsize_ns=1.0,
                          verbose=False):
        """
        Integrate & make a time histogram of all photon clicks on given channel,
        that arrive between start_ns and start_ns+tail_length_ns.
        Normalizes the integrated result to 1/(self.reps*syncs_per_sweep/self.sweep_length)
        """
        if not hasattr(self, 'reps'):
            self.get_readout_results('ssro')
        if not hasattr(self, 'sweep_pts'):
            print 'get_sweep_pts first'
            return
        if not hasattr(self, 'sweep_idxs'):
            print 'get_sweep_idxs first'
            return

        self.start_ns = start_ns

        is_ph = pq_tools.get_photons(self.pqf,
                                     pq_device=self.pq_device)[channel]
        sync_time_ns = self.pqf[self.pq_device +
                                '/PQ_sync_time-1'].value * pq_binsize_ns

        if str(self.f.keys()).count('sync_time') > 1:
            for i in np.arange(str(self.f.keys()).count('sync_time') - 1):
                ds_name = self.pq_device + '/PQ_sync_time-' + str(i + 2)
                sync_time_ns_add = self.pqf[ds_name].value * pq_binsize_ns
                sync_time_ns = np.append(sync_time_ns, sync_time_ns_add)
                is_ph = np.append(
                    is_ph,
                    pq_tools.get_photons(self.pqf,
                                         index=i + 2,
                                         pq_device=self.pq_device)[channel])

        self.sync_time_ns = sync_time_ns

        hist_bins = np.arange(
            self.start_ns - hist_binsize_ns * .5,
            self.start_ns + 1 * tail_length_ns + hist_binsize_ns,
            hist_binsize_ns)

        self.tail_hist_h = np.zeros((self.sweep_length, len(hist_bins) - 1))
        st_fltr = (self.start_ns <=
                   sync_time_ns) & (sync_time_ns <
                                    (self.start_ns + tail_length_ns))
        if verbose:
            print 'total_photons in channel', channel, ':', len(
                sync_time_ns[np.where(is_ph)])
            print 'total_photons in window:', len(
                sync_time_ns[np.where(is_ph & st_fltr)])
        valid_tail_idxs = self.sweep_idxs[np.where(is_ph & st_fltr)]

        if verbose:

            print 'total_sweeps in window:', len(valid_tail_idxs)
            print 'total ph in window with sweep element 5:', len(
                np.where(valid_tail_idxs == 5)[0])
            print 'div factor:', (self.reps * self.syncs_per_sweep /
                                  self.sweep_length)
        self.tail_cts_per_sweep_idx = np.zeros(self.sweep_length)

        for sweep_idx in range(self.sweep_length):
            self.tail_cts_per_sweep_idx[sweep_idx]= \
                                float(len(np.where(valid_tail_idxs==sweep_idx)[0])) / (self.reps*self.syncs_per_sweep/self.sweep_length)
            self.tail_hist_h[sweep_idx], self.tail_hist_b = \
                                np.histogram(sync_time_ns[np.where(is_ph & (self.sweep_idxs == sweep_idx))], bins=hist_bins)
Beispiel #16
0
def analyse_rnd_ro_bell(folder, save=True, RO_start=10730, **kw):
    a = pqsequence.PQSequenceAnalysis(folder)
    a.reps = kw.pop(
        'reps', a.g.attrs['repetitions'] *
        a.g['joint_params'].attrs['LDE_attempts_before_CR'])

    pq_binsize_ns = 1

    RO_length = a.g['joint_params'].attrs['LDE_RO_duration'] * 1e9
    a.plot_histogram(0,
                     start=0,
                     length=3000,
                     hist_binsize=1,
                     save=False,
                     log_plot=False)

    fig, ax = plt.subplots(1, 1, figsize=(4.5, 4))

    sync_nrs = a.pqf['/PQ_sync_number-1'].value
    is_photon_0, is_rnd_clk = pq_tools.get_photons(a.pqf)
    sync_time_ns = a.pqf['/PQ_sync_time-1'].value * pq_binsize_ns

    is_marker_1_event = pq_tools.get_markers(a.pqf, 1)
    is_marker_2_event = pq_tools.get_markers(a.pqf, 2)
    noof_rnd_0_events = np.sum(is_marker_1_event)
    noof_rnd_1_events = np.sum(is_marker_2_event)
    print 'noof_rnd 0/1 events:', noof_rnd_0_events, '/', noof_rnd_1_events
    print 'bias toward 0 : {:.2f} % '.format(
        50 - float(noof_rnd_0_events) /
        (noof_rnd_0_events + noof_rnd_1_events) *
        100), ', error : {:.2f} %'.format(1 / np.sqrt(
            len(np.where(is_marker_1_event)[0]) +
            len(np.where(is_marker_2_event)[0])) * 100)
    print 'noof syncs:', sync_nrs[-1]
    print 'Detected marker events {} / {}:'.format(
        noof_rnd_0_events + noof_rnd_1_events, a.reps)
    noof_reps_wo_rnd_clk = len(np.unique(sync_nrs[is_rnd_clk]))
    print 'number of reps with a random clk', noof_reps_wo_rnd_clk
    print 'syncs without a random click: {} / {} = {:.2f} %'.format(
        a.reps - noof_reps_wo_rnd_clk, a.reps,
        float(a.reps - noof_reps_wo_rnd_clk) / a.reps * 100.)

    is_last_random_click = np.append(
        np.diff(np.asarray(is_rnd_clk, dtype='int')) == -1, is_rnd_clk[-1])
    start_rnd = np.min(sync_time_ns[is_rnd_clk]) - 20
    length_rnd = np.max(sync_time_ns[is_rnd_clk]) - start_rnd + 20
    pq_plots.plot_photon_hist_filter_comparison(a.pqf,
                                                is_last_random_click,
                                                start=start_rnd,
                                                length=length_rnd,
                                                hist_binsize=1,
                                                save=False)

    marker_1_sync_numbers = sync_nrs[is_marker_1_event]
    marker_2_sync_numbers = sync_nrs[is_marker_2_event]

    ssro_calib_folder = kw.pop('ssro_calib_folder',
                               toolbox.latest_data('FastSSRO'))
    roc = error.SingleQubitROC()
    roc.F0, roc.u_F0, roc.F1, roc.u_F1 = pqsequence.get_analysed_fast_ssro_calibration(
        ssro_calib_folder, RO_length)
    #(0.9398,0.0034,0.9942,0.0013)
    print pqsequence.get_analysed_fast_ssro_calibration(
        ssro_calib_folder, RO_length)
    ##ssro.get_SSRO_calibration(ssro_calib_folder, ro_duration)

    st_fltr = (RO_start <= sync_time_ns) & (sync_time_ns <
                                            (RO_start + RO_length))
    is_photon_0_in_ro_window = st_fltr & is_photon_0
    photon_in_0_ro_window_sync_numbers = sync_nrs[is_photon_0_in_ro_window]
    no_photon_in_0_ro_window_sync_numbers = np.setdiff1d(
        sync_nrs, photon_in_0_ro_window_sync_numbers)
    av_p0 = float(len(np.unique(photon_in_0_ro_window_sync_numbers))) / a.reps
    u_av_p0 = np.sqrt(av_p0 * (1 - av_p0) / a.reps)
    av_F0, u_av_F0 = roc.num_eval(np.array([av_p0]), np.array([u_av_p0]))
    print 'averaged RO results: F0 {:.2f} $\pm$ {:.2f} % '.format(
        av_F0[0] * 100, u_av_F0[0] * 100)

    marker_1_ro_ms0_events = pq_tools.filter_on_same_sync_number(
        photon_in_0_ro_window_sync_numbers, marker_1_sync_numbers)
    marker_2_ro_ms0_events = pq_tools.filter_on_same_sync_number(
        photon_in_0_ro_window_sync_numbers, marker_2_sync_numbers)
    marker_1_ro_ms1_events = pq_tools.filter_on_same_sync_number(
        no_photon_in_0_ro_window_sync_numbers, marker_1_sync_numbers
    )  #np.invert(marker_1_ro_ms0_events) #this also works.
    marker_2_ro_ms1_events = pq_tools.filter_on_same_sync_number(
        no_photon_in_0_ro_window_sync_numbers,
        marker_2_sync_numbers)  #np.invert(marker_2_ro_ms0_events)
    noof_marker_1_ro_ms0_events = np.sum(marker_1_ro_ms0_events)
    noof_marker_2_ro_ms0_events = np.sum(marker_2_ro_ms0_events)
    noof_marker_1_ro_ms1_events = np.sum(marker_1_ro_ms1_events)
    noof_marker_2_ro_ms1_events = np.sum(marker_2_ro_ms1_events)

    print 'MA1 & RO0: {}, MA1 & RO1: {}, MA2 & RO0: {}, MA2 & RO1: {}'.format(
        noof_marker_1_ro_ms0_events, noof_marker_1_ro_ms1_events,
        noof_marker_2_ro_ms0_events, noof_marker_2_ro_ms1_events)

    ma_1_p0 = (float(noof_marker_1_ro_ms0_events) /
               (noof_marker_1_ro_ms1_events + noof_marker_1_ro_ms0_events))
    ma_1_u_p0 = np.sqrt(
        ma_1_p0 * (1 - ma_1_p0) /
        (noof_marker_1_ro_ms1_events + noof_marker_1_ro_ms0_events))
    ma_2_p0 = (float(noof_marker_2_ro_ms0_events) /
               (noof_marker_2_ro_ms1_events + noof_marker_2_ro_ms0_events))
    ma_2_u_p0 = np.sqrt(
        ma_2_p0 * (1 - ma_2_p0) /
        (noof_marker_2_ro_ms1_events + noof_marker_2_ro_ms0_events))

    print 'Uncorrected: RND 0: F0 {:.2f}%, RND 1: F0 {:.2f}%'.format(
        ma_1_p0 * 100, ma_2_p0 * 100)

    p0, u_p0 = roc.num_eval(np.array([ma_1_p0, ma_2_p0]),
                            np.array([ma_1_u_p0, ma_2_u_p0]))

    ax.bar(
        range(2),
        p0,
        #color=[settings.COLORS[0], settings.COLORS[1]],
        align='center',
        yerr=u_p0,
        ecolor='k',
        width=0.8)
    ax.set_title(a.timestamp + '\n Corrected RO')
    ax.text(0, -.15, 'Rnd_no = 0', ha='center', va='bottom')
    ax.text(1, -.15, 'Rnd_no = 1', ha='center', va='bottom')
    ax.set_xticks([0, 1])
    #ax.text(1, 1.05, '{:.0f}+/-{:.0f} %'.format(p0*100., u_p0*100.),
    #    ha='center', va='bottom', color=settings.COLORS[1])

    ax.text(0,
            1.02,
            'F0: {:.2f} $\pm$ {:.2f} %'.format(p0[0] * 100, u_p0[0] * 100),
            ha='center',
            va='bottom')
    ax.text(1,
            1.02,
            'F0: {:.2f} $\pm$ {:.2f} %'.format(p0[1] * 100, u_p0[1] * 100),
            ha='center',
            va='bottom')
    ax.set_ylabel('Fidelity ms0')
    ax.set_ylim(0, 1.1)
    if save:
        a.save_fig_incremental_filename(fig, 'random_mw_correlation_corrected')
def get_coincidences(pqf, index = 1, fltr0=None, fltr1=None, pulse_offset = 0, force_coincidence_evaluation = False, save = True):

    sync_time_name = '/PQ_sync_time-' + str(index)
    tot_time_name =  '/PQ_time-' + str(index)
    sync_num_name = '/PQ_sync_number-' + str(index)

    if pulse_offset == 0:
        if pq_tools.has_analysis_data(pqf, 'coincidences') and not force_coincidence_evaluation:
            c, c_attrs = pq_tools.get_analysis_data(pqf, 'coincidences')
            return c    
    else:
        if pq_tools.has_analysis_data(pqf, 'coincidences_offset_'+str(pulse_offset)) and not force_coincidence_evaluation:
            c, c_attrs = pq_tools.get_analysis_data(pqf,'coincidences_offset_'+str(pulse_offset))
            return c   

    sync_time = pqf[sync_time_name].value
    total_time = pqf[tot_time_name].value
    sync_number = pqf[sync_num_name].value

    is_ph0, is_ph1 = pq_tools.get_photons(pqf)

    # thin down a bit with loose filtering
    if fltr0 != None:
        fltr0 = is_ph0 & fltr0
    else:
        fltr0 = is_ph0

    if fltr1 != None:
        fltr1 = is_ph1 & fltr1
    else:
        fltr1 = is_ph1

    st0 = sync_time[fltr0]
    t0  = total_time[fltr0]
    sn0 = sync_number[fltr0]
    
    st1 = sync_time[fltr1]
    t1  = total_time[fltr1]
    sn1 = sync_number[fltr1] + pulse_offset
   
    samesync0 = np.in1d(sn0, sn1)
    samesync1 = np.in1d(sn1, sn0)

    c_st0 = st0[samesync0]
    c_st1 = st1[samesync1]
    c_t0 = t0[samesync0]
    c_sn0 = sn0[samesync0]
    c_t1 = t1[samesync1]
    c_sn1 = sn1[samesync1]

    ### Code for afterpulsing (PH 16) - also need to uncomment one line in for loop
    # unique_vals, uniq_counts = np.unique(sn1, return_counts = True)
    # repeated = np.in1d(sn1,unique_vals[uniq_counts > 1])
    # c_st0 = st1[repeated]
    # c_st1 = st1[repeated]
    # c_t0 = t1[repeated]
    # c_sn0 = sn1[repeated]
    # c_t1 = t1[repeated]
    # c_sn1 = sn1[repeated]

    coincidences = np.empty((0,4))
    for i, (_sn0, _t0, _st0) in enumerate(zip(c_sn0, c_t0, c_st0)):

        _c = c_sn1==_sn0
        # _c[i] = 0 # Not the same entry (for afterpulsing)
        
        for _t1, _st1 in zip(c_t1[_c], c_st1[_c]):
            dt = int(_st0) - int(_st1)
            coincidences = np.vstack((coincidences, np.array([dt, _st0, _st1, _sn0])))

    # coincidences = np.empty((0,4))
    # for _sn0, _t0, _st0 in zip(c_sn0, c_t0, c_st0):
    #     _c = c_sn1==_sn0
        
    #     for _t1, _st1 in zip(c_t1[_c], c_st1[_c]):
    #         dt = int(_t0) - int(_t1)
    #         coincidences = np.vstack((coincidences, np.array([dt, _st0, _st1, _sn0])))
    
    if save:
        
        if pulse_offset == 0:
            pq_tools.set_analysis_data(pqf, 'coincidences', coincidences,
                          columns=('dt = ch0-ch1 (bins)', 'sync_time ch0 (bins)', 'sync_time ch1 (bins)', 'sync number'))
        else:
            pq_tools.set_analysis_data(pqf, 'coincidences_offset_'+str(pulse_offset), coincidences,
                          columns=('dt = ch0-ch1 (bins)', 'sync_time ch0 (bins)', 'sync_time ch1 (bins)', 'sync number'))    

    return coincidences
Beispiel #18
0
def analyse_rnd_ro_bell(folder, save = True,RO_start=10730, **kw):
    a = pqsequence.PQSequenceAnalysis(folder)
    a.reps=kw.pop('reps',a.g.attrs['repetitions']*a.g['joint_params'].attrs['LDE_attempts_before_CR'])
    
    pq_binsize_ns=1
    
    RO_length = a.g['joint_params'].attrs['LDE_RO_duration']*1e9
    a.plot_histogram(0,start=0, length=3000, hist_binsize=1, save=False, log_plot=False)

    fig, ax = plt.subplots(1,1, figsize=(4.5,4))
    
    sync_nrs=a.pqf['/PQ_sync_number-1'].value 
    is_photon_0, is_rnd_clk=pq_tools.get_photons(a.pqf)
    sync_time_ns = a.pqf['/PQ_sync_time-1'].value * pq_binsize_ns

    is_marker_1_event=pq_tools.get_markers(a.pqf,1)
    is_marker_2_event=pq_tools.get_markers(a.pqf,2)
    noof_rnd_0_events=np.sum(is_marker_1_event)
    noof_rnd_1_events=np.sum(is_marker_2_event)
    print 'noof_rnd 0/1 events:',noof_rnd_0_events, '/' , noof_rnd_1_events
    print 'bias toward 0 : {:.2f} % '.format(50-float(noof_rnd_0_events)/(noof_rnd_0_events+noof_rnd_1_events)*100),', error : {:.2f} %'.format(1/np.sqrt(len(np.where(is_marker_1_event)[0])+len(np.where(is_marker_2_event)[0]))*100)
    print 'noof syncs:', sync_nrs[-1]
    print 'Detected marker events {} / {}:'.format(noof_rnd_0_events+noof_rnd_1_events, a.reps)
    noof_reps_wo_rnd_clk=len(np.unique(sync_nrs[is_rnd_clk]))
    print 'number of reps with a random clk', noof_reps_wo_rnd_clk
    print 'syncs without a random click: {} / {} = {:.2f} %'.format(a.reps-noof_reps_wo_rnd_clk, a.reps, float(a.reps-noof_reps_wo_rnd_clk)/a.reps*100.)
    
    is_last_random_click=np.append(np.diff(np.asarray(is_rnd_clk, dtype='int'))==-1,is_rnd_clk[-1])
    start_rnd=np.min(sync_time_ns[is_rnd_clk])-20
    length_rnd=np.max(sync_time_ns[is_rnd_clk])-start_rnd+20
    pq_plots.plot_photon_hist_filter_comparison(a.pqf,is_last_random_click,start = start_rnd, length = length_rnd, hist_binsize = 1, save = False)

    marker_1_sync_numbers= sync_nrs[is_marker_1_event]
    marker_2_sync_numbers= sync_nrs[is_marker_2_event]
    
    
    ssro_calib_folder = kw.pop('ssro_calib_folder', toolbox.latest_data('FastSSRO'))  
    roc = error.SingleQubitROC()
    roc.F0, roc.u_F0, roc.F1, roc.u_F1 =pqsequence.get_analysed_fast_ssro_calibration(ssro_calib_folder, RO_length)
    #(0.9398,0.0034,0.9942,0.0013)
    print pqsequence.get_analysed_fast_ssro_calibration(ssro_calib_folder, RO_length)
    ##ssro.get_SSRO_calibration(ssro_calib_folder, ro_duration)
        
    st_fltr = (RO_start  <= sync_time_ns) &  (sync_time_ns< (RO_start + RO_length))
    is_photon_0_in_ro_window = st_fltr & is_photon_0
    photon_in_0_ro_window_sync_numbers = sync_nrs[is_photon_0_in_ro_window]
    no_photon_in_0_ro_window_sync_numbers = np.setdiff1d(sync_nrs,photon_in_0_ro_window_sync_numbers)
    av_p0=float(len(np.unique(photon_in_0_ro_window_sync_numbers)))/a.reps
    u_av_p0 = np.sqrt(av_p0*(1-av_p0)/a.reps)
    av_F0, u_av_F0 = roc.num_eval(np.array([av_p0]),np.array([u_av_p0]))
    print 'averaged RO results: F0 {:.2f} $\pm$ {:.2f} % '.format(av_F0[0]*100,u_av_F0[0]*100 )
        
    
    marker_1_ro_ms0_events=pq_tools.filter_on_same_sync_number(photon_in_0_ro_window_sync_numbers,marker_1_sync_numbers)
    marker_2_ro_ms0_events=pq_tools.filter_on_same_sync_number(photon_in_0_ro_window_sync_numbers,marker_2_sync_numbers)
    marker_1_ro_ms1_events=pq_tools.filter_on_same_sync_number(no_photon_in_0_ro_window_sync_numbers,marker_1_sync_numbers)#np.invert(marker_1_ro_ms0_events) #this also works.
    marker_2_ro_ms1_events=pq_tools.filter_on_same_sync_number(no_photon_in_0_ro_window_sync_numbers,marker_2_sync_numbers)#np.invert(marker_2_ro_ms0_events)
    noof_marker_1_ro_ms0_events=np.sum(marker_1_ro_ms0_events)
    noof_marker_2_ro_ms0_events=np.sum(marker_2_ro_ms0_events)
    noof_marker_1_ro_ms1_events=np.sum(marker_1_ro_ms1_events)
    noof_marker_2_ro_ms1_events=np.sum(marker_2_ro_ms1_events)
    
    print 'MA1 & RO0: {}, MA1 & RO1: {}, MA2 & RO0: {}, MA2 & RO1: {}'.format(noof_marker_1_ro_ms0_events, noof_marker_1_ro_ms1_events,noof_marker_2_ro_ms0_events, noof_marker_2_ro_ms1_events)
    
    
    
    ma_1_p0=(float(noof_marker_1_ro_ms0_events)/(noof_marker_1_ro_ms1_events+noof_marker_1_ro_ms0_events))
    ma_1_u_p0 = np.sqrt(ma_1_p0*(1-ma_1_p0)/(noof_marker_1_ro_ms1_events+noof_marker_1_ro_ms0_events))
    ma_2_p0=(float(noof_marker_2_ro_ms0_events)/(noof_marker_2_ro_ms1_events+noof_marker_2_ro_ms0_events))
    ma_2_u_p0 = np.sqrt(ma_2_p0*(1-ma_2_p0)/(noof_marker_2_ro_ms1_events+noof_marker_2_ro_ms0_events))        
    
    print 'Uncorrected: RND 0: F0 {:.2f}%, RND 1: F0 {:.2f}%'.format(ma_1_p0*100, ma_2_p0*100)

    p0, u_p0 = roc.num_eval(np.array([ma_1_p0,ma_2_p0]),np.array([ma_1_u_p0,ma_2_u_p0]))
    
    ax.bar( range(2),p0, 
        #color=[settings.COLORS[0], settings.COLORS[1]],
        align='center', yerr=u_p0, 
        ecolor='k', width=0.8)
    ax.set_title(a.timestamp+'\n Corrected RO')
    ax.text(0, -.15, 'Rnd_no = 0',ha='center', va='bottom')
    ax.text(1, -.15, 'Rnd_no = 1',ha='center', va='bottom')
    ax.set_xticks([0,1])
    #ax.text(1, 1.05, '{:.0f}+/-{:.0f} %'.format(p0*100., u_p0*100.),
    #    ha='center', va='bottom', color=settings.COLORS[1])  
    
    ax.text(0, 1.02,'F0: {:.2f} $\pm$ {:.2f} %'.format(p0[0]*100,u_p0[0]*100 ),ha='center', va='bottom')
    ax.text(1, 1.02,'F0: {:.2f} $\pm$ {:.2f} %'.format(p0[1]*100,u_p0[1]*100 ),ha='center', va='bottom')
    ax.set_ylabel('Fidelity ms0')
    ax.set_ylim(0,1.1)
    if save:
        a.save_fig_incremental_filename(fig,'random_mw_correlation_corrected')
Beispiel #19
0
def HH_event_PLU_Marker_Check(BS_fp_len, fp_BS, fp_LT1, fp_LT3, first_win_min, first_win_max, second_win_min, second_win_max):
    """
    This function checks the number of entanglement events which is obtained from the 
    Hydraharp data and compares it to the entanglement events found by markers.
    """


    for i in np.arange(BS_fp_len):
    
        # Checks if there is enough data for the analysis
        if tb.has_data(fp_LT1[i], 'PQ_sync_time-1') and tb.has_data(fp_LT3[i], 'PQ_sync_time-1'):
            print "Run: ", str(i+1)
            
            # Opens LT1 data  
            g = h5py.File(fp_LT1[i],'r')
            for k in g.keys():
                if type(g[k])==h5py.Group:
                    ad1_reps = g[('/'+ str(k) + '/ssro/entanglement_events')].value
            g.close()
    
            # Opens LT3 data    
            h = h5py.File(fp_LT3[i],'r')
            for k in h.keys():
                if type(h[k])==h5py.Group:
                    ad3_reps = h[('/'+ str(k) + '/ssro/entanglement_events')].value
            h.close()  
            
            # Open BS data
            pqf = h5py.File(fp_BS[i], 'r')
            sync_numbers = pqf['/PQ_sync_number-1'].value

            # Defines two filters for photons arriving in channel 0 and 1
            is_ph0, is_ph1 = pq_tools.get_photons(pqf)
            
            test = second_win_max - first_win_max

            # Defines filters for if photons in channel 0 and 1 are arriving in the first or scond window  
            print first_win_min
            print first_win_max
            print second_win_min
            print second_win_max       
            is_valid_ph0_w1 = is_ph0 & pq_tools.filter_synctimes(pqf,first_win_min ,first_win_max)
            is_valid_ph0_w2 = is_ph0 & pq_tools.filter_synctimes(pqf,second_win_min ,second_win_max)
            is_valid_ph1_w1 = is_ph1 & pq_tools.filter_synctimes(pqf,first_win_min ,first_win_max)
            is_valid_ph1_w2 = is_ph1 & pq_tools.filter_synctimes(pqf,second_win_min ,second_win_max)
            pqf.close()
    
    
            # Applies filters above to get a list of sync numbers
            valid_ph0_w1_sn = sync_numbers[is_valid_ph0_w1]
            print len(valid_ph0_w1_sn)
            print len(np.unique(valid_ph0_w1_sn))
            valid_ph0_w2_sn = sync_numbers[is_valid_ph0_w2]
            valid_ph1_w1_sn = sync_numbers[is_valid_ph1_w1]
            valid_ph1_w2_sn = sync_numbers[is_valid_ph1_w2]
            

            # Defines type of events by checking if sync numbers are in two lists
            is_00_sn = np.in1d(valid_ph0_w1_sn,valid_ph0_w2_sn)
            w0w0_sn = valid_ph0_w1_sn[is_00_sn]
            is_01_sn = np.in1d(valid_ph0_w1_sn,valid_ph1_w2_sn)
            w0w1_sn = valid_ph0_w1_sn[is_01_sn]
            is_10_sn = np.in1d(valid_ph1_w1_sn,valid_ph0_w2_sn)
            w1w0_sn = valid_ph1_w1_sn[is_10_sn]
            is_11_sn = np.in1d(valid_ph1_w1_sn,valid_ph1_w2_sn)
            w1w1_sn = valid_ph1_w1_sn[is_11_sn]
    
            # Defines a list with psiplus and psiminus events
            psi_plus_sn = np.unique(np.append(w0w0_sn,w1w1_sn))
            psi_minus_sn = np.unique(np.append(w0w1_sn,w1w0_sn))
    
            if Settings.VERBOSE == True:
                print "Number of Hydraharp psi_plus events: ", len(psi_plus_sn)
                print "Number of Hydraharp psi_minus events: ", len(psi_minus_sn)
                print "Number of PLU Markers LT1: ", ad1_reps
                print "Number of PLU Markers LT3: ", ad3_reps
                print
        else:
            print "There is no analysis data for run", i+1
Beispiel #20
0
def PSB_tail_analysis_per_run(fp, first_window_start, first_window_stop, second_window_start, second_window_stop, Verbose = True):
    
    Tail_analysis = np.empty([5,len(fp)])
    
    for i in np.arange(len(fp)):
   
        if tb.has_data(fp[i], 'PQ_sync_time-1'):

            # Opens file to retrieve number of repetitions
            g = h5py.File(fp[i],'r')
            sync_numbers = g['/PQ_sync_number-1'].value
            sync_times = g['/PQ_sync_time-1'].value
            is_ph0, is_ph1 = pq_tools.get_photons(g) #Note that there are only photons in channel 0
            for k in g.keys():
                if type(g[k])==h5py.Group:
                    Completed_reps = g[('/'+ str(k) + '/ssro/completed_reps')].value
            g.close()

            # Calculates the total repetitions
            Total_reps =  Completed_reps * 250
    
            # Makes a list of sync times for photons 
            sync_times_ph0 = sync_times[is_ph0]

            """
            Note that all filters below can only be applied on sync_times_ph0 or sync_times_ph1 arrays with the same length
            """
    
            # Filters events in channel 0 on being in the first window or the second window, windows are set above
            is_event_first_window_ph0 = (sync_times_ph0 > first_window_start) & \
                             (sync_times_ph0 <= first_window_stop)
            is_event_second_window_ph0 = (sync_times_ph0 > second_window_start) & \
                              (sync_times_ph0 <= second_window_stop)


            # Calculates the amount of photons in the first or second window for both channel
            photons_first_window = sum(is_event_first_window_ph0)
            photons_second_window = sum(is_event_second_window_ph0)
            Total_number_of_photons = sum(is_ph0)

            # Normalize the amount of photons with respect to the total amount of repetitions
            photons_first_window_per_rep = photons_first_window / float(Total_reps)
            photons_second_window_per_rep = photons_second_window / float(Total_reps)
    
            # Saves calculated data
            Tail_analysis[:,i] = [Total_number_of_photons, photons_first_window, photons_second_window,\
                          photons_first_window_per_rep, photons_second_window_per_rep]

            if Settings.VERBOSE:
                print "Run: ", i+1
                print "Total number of photons: ", Total_number_of_photons
                print "Number of photons in first window", photons_first_window
                print "Number of photons in second window", photons_second_window
                print "Number of photons in first window per repetition", photons_first_window_per_rep
                print "Number of photons in second window per repetition", photons_second_window_per_rep
                print
            
        else:
            #Tail_analysis_LT1[:,i] = [0,0,0,0,0]
            if Settings.VERBOSE:
                print "Run: ", i+1
                print "There is no data for this run in LT1"
                Tail_analysis[:,i] = np.array([0,0,0,0,0])
                print
                
    return Tail_analysis
Beispiel #21
0
def plot_PLU_filter(pqf, chan=2):

    # get the PLU marked photons first
    is_ph_ch0, is_ph_ch1 = pq_tools.get_photons(pqf)
    is_ph = is_ph_ch0 | is_ph_ch1
    is_ph_with_PLU_mrkr = is_ph & pq_tools.filter_marker(pqf, chan)

    # first window
    fig, (ax0, ax1) = plot_photon_hist_filter_comparison(
        pqf,
        save=False,
        fltr=is_ph_with_PLU_mrkr,
        log=True,
        binedges=settings.PHOTONHIST_BINEDGES)

    ax0.axvline(settings.CH0_START, color='k', linestyle='--')
    ax0.text(settings.CH0_START + 1,
             1,
             '{} ns'.format(settings.CH0_START),
             color='k')
    ax0.legend()
    ax0.set_title('PLU (hardware) filter first pi-pulse ch0')

    ax1.axvline(settings.CH1_START, color='k', linestyle='--')
    ax1.text(settings.CH1_START + 1,
             1,
             '{} ns'.format(settings.CH1_START),
             color='k')
    ax1.legend()
    ax1.set_title('PLU (hardware) filter first pi-pulse ch1')

    fig.savefig(os.path.join(folder, 'PLU_photons_window1.png'))

    # second window
    fig, (ax0, ax1) = plot_photon_hist_filter_comparison(
        pqf,
        save=False,
        fltr=is_ph_with_PLU_mrkr,
        log=True,
        binedges=settings.PHOTONHIST_BINEDGES + settings.PIPULSESEP)

    ax0.axvline(settings.CH0_START + settings.PIPULSESEP,
                color='k',
                linestyle='--')
    ax0.text(settings.CH0_START + settings.PIPULSESEP + 1,
             1,
             '{} ns'.format(settings.CH0_START + settings.PIPULSESEP),
             color='k')
    ax0.legend()
    ax0.set_title('PLU (hardware) filter second pi-pulse ch0')

    ax1.axvline(settings.CH1_START + settings.PIPULSESEP,
                color='k',
                linestyle='--')
    ax1.text(settings.CH1_START + settings.PIPULSESEP + 1,
             1,
             '{} ns'.format(settings.CH1_START + settings.PIPULSESEP),
             color='k')
    ax1.legend()
    ax1.set_title('PLU (hardware) filter second pi-pulse ch1')

    fig.savefig(os.path.join(folder, 'PLU_photons_window2.png'))