コード例 #1
0
def sync_pixel_clock(mwk_path, oe_path, oe_channels=[0, 1]):

    # 1. read in ephys binary data and timestamps

    #for open ephys format data, use:
    #oe_events = open_ephys.loadEvents(oe_path)

    # unpack the channels
    #channels = oe_events['channel']
    #directions = oe_events['eventId'] # 0: 1 -> 0, 1: 0 -> 1
    #times = oe_events['timestamps']
    #event_types = oe_events['eventType']

    # for KWIK format, use:
   
    # 2. send those files to extract relevant info and concatenate:
    #all_times,all_channels,all_directions = concatenate(raw_files)
    
            #[relevant,channels,directions,times],experiment_length = concatenateKWIKfiles.concatenate(oe_path)
   
    # make path to the Ch_0 and Ch_1 files:
    if oe_path[-1] == '/':
        ttls_path = oe_path + 'Ch_'
    else:
        ttls_path = oe_path + '/Ch_'

    [times,channels,directions] = titanspikes_ttl_extract.get_TTL_info(ttls_path)
    # times are in seconds.microseconds
    ephys_fs = 1

    experiment_length=[]


    print 'Experiment length = ', experiment_length    


    # duplicate every element of times and directions

    rel_times_0 = times[channels==0]
    rel_times_1 = times[channels==1]
    rel_directions_0 = directions[channels==0]
    rel_directions_1 = directions[channels==1]

    plot_times_0 = np.array(list(itertools.chain(*zip(rel_times_0,rel_times_0[1:]))))
    plot_times_1 = np.array(list(itertools.chain(*zip(rel_times_1,rel_times_1[1:]))))
    plot_directions_0 = np.array(list(itertools.chain(*zip(rel_directions_0,rel_directions_0[:-1]))))
    plot_directions_1 = np.array(list(itertools.chain(*zip(rel_directions_1,rel_directions_1[:-1]))))

    # plot the up/down transitions as recorded on OE:
    # fig1 = plt.figure()
    # ax1 = plt.subplot(2, 1, 1)
    # plt.plot(plot_times_0,plot_directions_0)
    # plt.ylabel('OE Ch 0')

    # ax2 = plt.subplot(2, 1, 2,sharex=ax1)
    # plt.plot(plot_times_1,plot_directions_1)
    # plt.ylabel('OE Ch 1')

    #plt.show()
    #print 'some oe ttl times: ', times(0)

    oe_codes, latencies = pixelclock.events_to_codes(np.vstack((times, channels, directions)).T, len(oe_channels), 0.01,swap_12_codes = 1,swap_03_codes=0)
    # the pixel clock should change once per frame, or at ~16ms max. This is 16ms * 30samples/ms = 480 samples. If a code is shorter than that, it's probably a fluke.
    # if oe_code times are in 636... format, use 10e4 as min code length
    #if in seconds.microseconds, min code time = 0.01

    print 'Number of ephys codes = ', len(oe_codes)


    # !! assuming there's just one mworks file, take the first element in the list mwk_path:
    mwk_path = os.path.abspath(mwk_path[0])

    mwk = mw.MWKFile(mwk_path)
    mwk.open()



    # Start by getting the pixel clock / bit code data
    stimulus_announces = mwk.get_events(codes=['#announceStimulus'])

    # bit_codes is a list of (time, code) tuples
    mw_codes = [(e.time, e.value['bit_code']) for e in stimulus_announces if isiterable(e.value) and 'bit_code' in e.value]

    print 'Number of mworks codes = ', len(mw_codes)
    ## for mw_codes and oe_codes - if one code persists for too long a time (>thresh), get rid of it (keep only the fast-changing codes that come from the grating stimulus):

    #oe_codes = lowpass_codetimes(oe_codes,fs=ephys_fs,thresh_samples = 0.02) #0.2
    #mw_codes = lowpass_codetimes(mw_codes,fs=1e6,thresh_samples = 0.02)



    print 'Number of oe codes after lowpass = '******'Number of mworks codes after lowpass = '******'win max is ',int(len(oe_codes)/win_size)
    for win in range(0,int(len(oe_codes)/win_size),25): #range(int(round(len(oe_codes)/win_size)))
        print 'win = ', win
        if win*win_size+win_size < len(oe_codes):
            tmp_match = pixelclock.match_codes(
                [evt[0] for evt in oe_codes[win*win_size:(win+1)*win_size]], # oe times
                [evt[1] for evt in oe_codes[win*win_size:(win+1)*win_size]], # oe codes
                [evt[0] for evt in mw_codes], # mw times
                [evt[1] for evt in mw_codes], # mw codes
                minMatch = 20,
                maxErr = 0) 
            print 'temp matches = ', tmp_match
            matches.extend(tmp_match)
        else:
            print '!!win = ', win
            tmp_match = pixelclock.match_codes(
                    [evt[0] for evt in oe_codes[win*win_size:-1]], # oe times
                    [evt[1] for evt in oe_codes[win*win_size:-1]], # oe codes
                    [evt[0] for evt in mw_codes], # mw times
                    [evt[1] for evt in mw_codes], # mw codes
                    minMatch = 9,
                    maxErr = 0)
                    
            matches.extend(tmp_match)
    
    
    print 'matches = ', matches
    print 'type = ', type(matches)
    #matches = pixelclock.match_codes(
    #    [evt[0] for evt in oe_codes], # oe times
    #    [evt[1] for evt in oe_codes], # oe codes
    #    [evt[0] for evt in mw_codes], # mw times
    #    [evt[1] for evt in mw_codes], # mw codes
    #    minMatch = 5,
    #    maxErr = 0) # from 0 to 1 == from 23 to 27 matches, but in the wrong places. 


    #print "OE Code sequence:"
    #print [evt[1] for evt in oe_codes]

    #print "MW Code sequence:"
    #print [evt[1] for evt in mw_codes]

    #print "MATCHES:"
    #print matches

    mw_times = [item[0] for item in mw_codes] #[e.time for e in stimulus_announces if isiterable(e.value)]
    oe_times = [item[0] for item in oe_codes]

       

    # condition the data to plot square pulses:
    tmp_mw_codes = [evt[1] for evt in mw_codes]
    tmp_mw_codetimes = [evt[0] for evt in mw_codes]
    plot_mw_codes = np.array(list(itertools.chain(*zip(tmp_mw_codes,tmp_mw_codes[:-1])))) 
    plot_mw_codetimes = np.array(list(itertools.chain(*zip(tmp_mw_codetimes,tmp_mw_codetimes[1:])))) 

    tmp_oe_codes = [evt[1] for evt in oe_codes]
    tmp_oe_codetimes = [evt[0] for evt in oe_codes]
    plot_oe_codes = np.array(list(itertools.chain(*zip(tmp_oe_codes,tmp_oe_codes[:-1])))) 
    plot_oe_codetimes = np.array(list(itertools.chain(*zip(tmp_oe_codetimes,tmp_oe_codetimes[1:])))) 



    # Bokeh:
    save_folder = './pixel_clock/'
    if not os.path.exists(save_folder):
        os.makedirs(save_folder)
    ####### FIGURE 1 ###########

    colors = []
    #col = np.matlib.repmat(rgb,10,1)

    for i in range(len(matches)):
        r = np.random.randint(255)
        g = np.random.randint(255)
        b = np.random.randint(255)
        
        colors.append(RGB(r,g,b)) 
    match_idx = [idx for idx,match in enumerate(matches)]    
    #TOOLS = [HoverTool(),'box_zoom','reset','box_select']
    TOOLS="pan,wheel_zoom,box_zoom,reset,hover,previewsave"
    s1 = figure(width=1000, plot_height=500, title='MWorks and OpenEhys Pixel Clock Codes') # ,tools = TOOLS
    s1.line(plot_mw_codetimes/1e6,plot_mw_codes)
    mw_match_circles = [mat[1]/1e6 for mat in matches]
    mw_match_circles_samples = [mat[1] for mat in matches]

    s1.circle(mw_match_circles,match_idx,color=colors,size=20)
    
    #s1.circle(mw_match_circles,np.ones(len(matches)),color=colors,size=20)
    s1.yaxis.axis_label = 'MW Codes'

    #tap = s1.select(dict(type=TapTool))
    

    s2 = figure(width=1000, plot_height=500, title=None) #,tools = TOOLS
    s2.line(plot_oe_codetimes/ephys_fs,plot_oe_codes)
    oe_match_circles = [mat[0]/ephys_fs for mat in matches]
    oe_match_circles_samples = [mat[0] for mat in matches]
    
    
    s2.circle(oe_match_circles,match_idx,color=colors,size=20) # ,tags = match_idx
    #s2.circle(oe_match_circles,np.ones(len(matches)),color=colors,size=20) # ,tags = match_idx
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes'

    


    p = gridplot([[s1], [s2]])
    output_file(save_folder + "pc_codes_match.html")
    # show the results
    show(p)
    
    #plt.savefig('pc_code_matches.pdf')
    #plt.show()


    
    #m,c = fit_line(oe_match_circles_samples,mw_match_circles_samples)
    m,c = fit_ridge(oe_match_circles_samples,mw_match_circles_samples)
    
    # tb object lets you go back and forth between oe and mw timezones
    tb = timebase.TimeBase(matches,tmp_oe_codetimes,tmp_mw_codetimes)
    

    ## to test quality of match, plot OE codes in MW time

    print 'len plot_oe_codetimes = ', len(plot_oe_codetimes)



    


    #### want: take MW time (e.g. stim time) and get oe time:
    mw2oe_time = []
    for mw_time in plot_mw_codetimes:
        oe_tmp = mw_to_oe_time(mw_time,m,c) ### take MW time and convert to OE time 
        #oe_tmp = tb.mw_to_oe_time(mw_time)
        mw2oe_time.append(oe_tmp)

    mw2oe_time = np.squeeze(np.array(mw2oe_time))

    oe2mw_time = []
    for oe_time in plot_oe_codetimes:
        mw_tmp = oe_to_mw_time(oe_time,m,c)  ### take OE and convert to MW time!
        #mw_tmp = tb.oe_to_mw_time(oe_time)
        oe2mw_time.append(mw_tmp)

    oe2mw_time = np.squeeze(np.array(oe2mw_time))

    print 'oe2mw_time.shape ==== ', oe2mw_time.shape
    print 'plot_oe_codes.shape === ', plot_oe_codes.shape
    ####### FIGURE 2 ###########


    ####### PLOT the codes on the same time axis: e.g. everything on MW.
    
    

    tmp_oeMWconv_codetimes = [tb.audio_to_mworks(evt[0]/ephys_fs)* 1e6 for evt in oe_codes]
    plot_oeMWconv_codetimes = np.array(list(itertools.chain(*zip(tmp_oeMWconv_codetimes,tmp_oeMWconv_codetimes[1:])))) 

    

    s1 = figure(width=1000, plot_height=500, title='OE Codes Plotted in MW Time')
    s1.line(plot_mw_codetimes/1e6,plot_mw_codes)
    
    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in MW Time'

    s2 = figure(width=1000, plot_height=500, title=None,x_range=s1.x_range,y_range=s1.y_range)
    s2.line(oe2mw_time/1e6,plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in MW Time'
    
    p = gridplot([[s1], [s2]])
    output_file(save_folder + "oe_codes_in_MWtime.html")
    # show the results
    show(p)
    
    ####### FIGURE 3 ###########

    s1 = figure(width=1000, plot_height=500, title='MW Codes Plotted in OE Time')
    s1.line(mw2oe_time/ephys_fs,plot_mw_codes)
    
    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in OE Time'

    s2 = figure(width=1000, plot_height=500, title=None,x_range=s1.x_range,y_range=s1.y_range)
    s2.line(plot_oe_codetimes/ephys_fs,plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in OE Time'
    
    p = gridplot([[s1], [s2]])
    output_file(save_folder + "mw_codes_in_OEtime.html")
    # show the results
    show(p)
    

    ####### FIGURE 4 ###########
    ####### PLOT the LINE fit:
    
    pp = figure(width=1000, plot_height=500, title='Line Fit for MW and OE Time')
    
    #pp.line(oe2mw_time/1e6,plot_oe_codes)
    pp.line(plot_oe_codetimes,m*plot_oe_codetimes+c,color='red')
    #pp.circle(plot_oe_codetimes[0:len(matches)],plot_mw_codetimes[0:len(matches)])
    pp.circle(oe_match_circles_samples,mw_match_circles_samples)
    pp.xaxis.axis_label = 'oe codetimes'
    pp.yaxis.axis_label = 'mw codetimes'
    output_file(save_folder + "pc_line_fit.html")
    show(pp)


    print "number of MW events:"
    print len(mw_times)

    print "number of OE events:"
    print len(oe_times)

    print "number of matches: " + str(len(matches))
    

    


    return matches,mwk,m,c,experiment_length
コード例 #2
0
def sync_pixel_clock(vid_path, oe_path, head_data, oe_channels=[0, 1]):

    # make path to the Ch_0 and Ch_1 files:
    if oe_path[-1] == '/':
        ttls_path = oe_path + 'Ch_'
    else:
        ttls_path = oe_path + '/Ch_'

    [times, channels, directions
     ] = titanspikes_ttl_extract.get_TTL_info(ttls_path, oe_channels[0],
                                              oe_channels[1])

    # times are in seconds.microseconds
    ephys_fs = 1

    experiment_length = []

    print 'Experiment length = ', experiment_length

    # duplicate every element of times and directions

    # rel_times_0 = times[channels==0]
    # rel_times_1 = times[channels==1]
    # rel_directions_0 = directions[channels==0]
    # rel_directions_1 = directions[channels==1]

    # plot_times_0 = np.array(list(itertools.chain(*zip(rel_times_0,rel_times_0[1:]))))
    # plot_times_1 = np.array(list(itertools.chain(*zip(rel_times_1,rel_times_1[1:]))))
    # plot_directions_0 = np.array(list(itertools.chain(*zip(rel_directions_0,rel_directions_0[:-1]))))
    # plot_directions_1 = np.array(list(itertools.chain(*zip(rel_directions_1,rel_directions_1[:-1]))))

    #oe_codes, latencies = pixelclock.events_to_codes(np.vstack((times, channels, directions)).T, len(oe_channels), 0.01,swap_12_codes =1,swap_03_codes=0)

    # the pixel clock should change once per frame, or at ~16ms max. This is 16ms * 30samples/ms = 480 samples. If a code is shorter than that, it's probably a fluke.
    # if oe_code times are in 636... format, use 10e4 as min code length
    #if in seconds.microseconds, min code time = 0.01

    #oe_codes = titanspikes_ttl_extract.read_raw_ttl(os.getcwd() + '/TTLIns')

    #print 'Number of ephys codes = ', len(oe_codes)

    ############################ get Video's LED data (pre-extracted):

    video_data = np.load(vid_path)

    vid_channels = video_data['channels']

    vid_directions = video_data['directions']

    vid_times = video_data['times']

    #head_data.time  = head_data.time / 1e3 ## convert from ms to sec

    ch1_diffs = np.diff(head_data.bit1)
    ch2_diffs = np.diff(head_data.bit2)

    ch1_nonzero_diffs = np.nonzero(ch1_diffs)[
        0]  ## [0] b/c where returns a stupid tuple
    ch2_nonzero_diffs = np.nonzero(ch2_diffs)[0]

    ch1_directions = ch1_diffs[ch1_nonzero_diffs]

    ch1_times = head_data.iloc[ch1_nonzero_diffs].converted_times.values

    ch1_channels = np.zeros(ch1_directions.shape[0])

    ch2_directions = ch2_diffs[ch2_nonzero_diffs]

    ch2_times = head_data.iloc[ch2_nonzero_diffs].converted_times.values

    ch2_channels = np.ones(ch2_directions.shape[0])

    ard_channels = np.hstack([ch1_channels, ch2_channels])
    ard_directions = np.hstack([ch1_directions, ch2_directions])
    ard_times = np.hstack([ch1_times, ch2_times])

    print 'ch1_times = ', ch1_times[0:10]
    print 'ch2_times = ', ch2_times[0:10]

    ard_codes, ard_latencies = pixelclock.events_to_codes(np.vstack(
        (ard_times, ard_channels, ard_directions)).T,
                                                          2,
                                                          0.01,
                                                          swap_12_codes=1,
                                                          swap_03_codes=1)

    vid_codes, vid_latencies = pixelclock.events_to_codes(np.vstack(
        (vid_times, vid_channels, vid_directions)).T,
                                                          2,
                                                          0.01,
                                                          swap_12_codes=0,
                                                          swap_03_codes=0)

    ### hack: instead of changing downstream variable names, just rename ard codes "oe_codes":
    #oe_codes = None
    #oe_codes = ard_codes

    ##### alternative method:
    # codes = []
    # times = []
    # for idx in range(head_data.shape[0]):
    #     tmp_sum = head_data.bit1.values[idx] +  head_data.bit2.values[idx]
    #     #print tmp_sum
    #     if tmp_sum == 1:
    #         if head_data.bit1.values[idx] == 1:
    #             tmp_code = 2
    #         elif head_data.bit2.values[idx] == 1:
    #             tmp_code = 1
    #     elif tmp_sum == 0:
    #         tmp_code = 0
    #     else:
    #         tmp_code = 3
    #     codes.append(tmp_code)
    #     times.append(head_data.time[idx])
    # # (0,0) = 0. code = 0
    # # (0,1) = 1 code = 1
    # # (1,0) = 1 code = 2
    # # (1,1) = 2 code = 3
    # codes = np.array(codes)
    # times = np.array(times)
    # uni_codes = codes[np.where(np.diff(codes))[0]]
    # uni_times = times[np.where(np.diff(codes))[0]]

    # ard_codes = zip(uni_times,uni_codes)

    print 'Number of Arduino codes = ', len(ard_codes)
    print 'Number of Video codes = ', len(vid_codes)

    #### special skipping first few codes (which are bad,mkay) to get better matches- 8/3/16 for grat17:
    #vid_codes = vid_codes[3:] #10096
    #oe_codes = oe_codes[2:]
    ard_codes = ard_codes[1:]

    vid_codes = lowpass_codetimes(vid_codes, 30, 1)

    print 'some arduino codes = ', ard_codes[0:10]

    # 3. get pixel clock matches
    def run_match(codes1, codes2):
        print '############################### PREPARING TO MATCH CODES #######################################'
        matches = []
        win_size = 400
        print 'win max is ', int(len(codes1) / win_size)
        for win in range(0, int(len(codes1) / win_size),
                         5):  #range(int(round(len(oe_codes)/win_size)))
            #for idx,win in enumerate(range(int(len(oe_codes)/win_size))):
            print 'win = ', win
            if win * win_size + win_size < len(codes1):
                ## don't go thru all arduino codes, but start at the previous time. (i.e. move forward!)
                if len(matches) > 1:
                    ard_idx = np.where(
                        [thing[0] == matches[-1][1] for thing in codes2])[0][0]
                    print 'ard idx and last match time = ', ard_idx, matches[
                        -1][1]
                else:
                    ard_idx = 0

                tmp_match = pixelclock.match_codes(
                    [
                        evt[0]
                        for evt in codes1[win * win_size:(win + 1) * win_size]
                    ],  # oe times
                    [
                        evt[1]
                        for evt in codes1[win * win_size:(win + 1) * win_size]
                    ],  # oe codes
                    [evt[0] for evt in codes2[ard_idx:]],  # mw times
                    [evt[1] for evt in codes2[ard_idx:]],  # mw codes
                    minMatch=15,
                    maxErr=0)
                print 'temp matches = ', tmp_match
                matches.extend(tmp_match)
            else:
                print '!!win = ', win
                tmp_match = pixelclock.match_codes(
                    [evt[0] for evt in codes1[win * win_size:-1]],  # oe times
                    [evt[1] for evt in codes1[win * win_size:-1]],  # oe codes
                    [evt[0] for evt in codes2],  # mw times
                    [evt[1] for evt in codes2],  # mw codes
                    minMatch=9,
                    maxErr=0)

                matches.extend(tmp_match)

            return matches

    print 'len(vid_codes), len(ard_codes) = ', len(vid_codes), len(ard_codes)
    matches = run_match(vid_codes, ard_codes)

    print 'matches = ', matches
    print 'type = ', type(matches)

    #ard_times = [item[0] for item in ard_codes] #[e.time for e in stimulus_announces if isiterable(e.value)]
    #oe_times = [item[0] for item in oe_codes]

    # condition the data to plot square pulses:
    tmp_ard_codes = [evt[1] for evt in ard_codes]
    tmp_mw_codetimes = [evt[0] for evt in ard_codes]
    plot_ard_codes = np.array(
        list(itertools.chain(*zip(tmp_ard_codes, tmp_ard_codes[:-1]))))
    plot_mw_codetimes = np.array(
        list(itertools.chain(*zip(tmp_mw_codetimes, tmp_mw_codetimes[1:]))))

    tmp_oe_codes = [evt[1] for evt in vid_codes]
    tmp_oe_codetimes = [evt[0] for evt in vid_codes]
    plot_oe_codes = np.array(
        list(itertools.chain(*zip(tmp_oe_codes, tmp_oe_codes[:-1]))))
    plot_oe_codetimes = np.array(
        list(itertools.chain(*zip(tmp_oe_codetimes, tmp_oe_codetimes[1:]))))

    # Bokeh:

    ############################################################### FIGURE 1 #####################################################

    colors = []
    #col = np.matlib.repmat(rgb,10,1)

    for i in range(len(matches)):
        r = np.random.randint(255)
        g = np.random.randint(255)
        b = np.random.randint(255)

        colors.append(RGB(r, g, b))
    match_idx = [idx for idx, match in enumerate(matches)]
    #TOOLS = [HoverTool(),'box_zoom','reset','box_select']
    TOOLS = "pan,wheel_zoom,box_zoom,reset,hover,previewsave"
    s1 = figure(
        width=1000,
        plot_height=500,
        title='MWorks and OpenEhys Pixel Clock Codes')  # ,tools = TOOLS
    s1.line(plot_mw_codetimes, plot_ard_codes)
    mw_match_circles = [mat[1] for mat in matches]
    mw_match_circles_samples = [mat[1] for mat in matches]

    s1.circle(mw_match_circles, match_idx, color=colors, size=20)

    #s1.circle(mw_match_circles,np.ones(len(matches)),color=colors,size=20)
    s1.yaxis.axis_label = 'Arduino Codes'

    #tap = s1.select(dict(type=TapTool))

    s2 = figure(width=1000, plot_height=500, title=None)  #,tools = TOOLS
    s2.line(plot_oe_codetimes / ephys_fs, plot_oe_codes)
    oe_match_circles = [mat[0] / ephys_fs for mat in matches]
    oe_match_circles_samples = [mat[0] for mat in matches]

    s2.circle(oe_match_circles, match_idx, color=colors,
              size=20)  # ,tags = match_idx
    #s2.circle(oe_match_circles,np.ones(len(matches)),color=colors,size=20) # ,tags = match_idx
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'Video Codes'

    p = gridplot([[s1], [s2]])
    output_file("pc_codes_match.html")
    # show the results
    show(p)

    #plt.savefig('pc_code_matches.pdf')
    #plt.show()

    #m,c = fit_line(tmp_oe_codetimes,tmp_mw_codetimes) #oe,mw
    m, c = fit_line(oe_match_circles_samples, mw_match_circles_samples)
    # tb object lets you go back and forth between oe and mw timezones
    tb = timebase.TimeBase(matches, tmp_oe_codetimes, tmp_mw_codetimes)

    ## to test quality of match, plot OE codes in MW time

    print 'len plot_oe_codetimes = ', len(plot_oe_codetimes)

    #### want: take MW time (e.g. stim time) and get oe time:
    mw2oe_time = []
    for mw_time in plot_mw_codetimes:
        oe_tmp = mw_to_oe_time(mw_time, m,
                               c)  ### take MW time and convert to OE time
        #oe_tmp = tb.mw_to_oe_time(mw_time)
        mw2oe_time.append(oe_tmp)

    mw2oe_time = np.array(mw2oe_time)

    oe2mw_time = []
    for oe_time in plot_oe_codetimes:
        mw_tmp = oe_to_mw_time(oe_time, m,
                               c)  ### take OE and convert to MW time!
        #mw_tmp = tb.oe_to_mw_time(oe_time)
        oe2mw_time.append(mw_tmp)

    oe2mw_time = np.array(oe2mw_time)

    ####### FIGURE 2 ###########

    ####### PLOT the codes on the same time axis: e.g. everything on MW.

    tmp_oeMWconv_codetimes = [
        tb.audio_to_mworks(evt[0] / ephys_fs) for evt in vid_codes
    ]
    plot_oeMWconv_codetimes = np.array(
        list(
            itertools.chain(
                *zip(tmp_oeMWconv_codetimes, tmp_oeMWconv_codetimes[1:]))))

    s1 = figure(width=1000,
                plot_height=500,
                title='Video Codes Plotted in Arduino Time')
    s1.line(plot_mw_codetimes, plot_ard_codes)

    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'Arduino Codes in Arduino Time'

    s2 = figure(width=1000,
                plot_height=500,
                title=None,
                x_range=s1.x_range,
                y_range=s1.y_range)
    s2.line(oe2mw_time, plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'Video Codes in Arduino Time'

    p = gridplot([[s1], [s2]])
    output_file("vid_codes_in_Arduino_time.html")
    # show the results
    show(p)

    ####### FIGURE 3 ###########

    s1 = figure(width=1000,
                plot_height=500,
                title='Arduino Codes Plotted in Video Time')
    s1.line(mw2oe_time / ephys_fs, plot_ard_codes)

    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'Arduino Codes in Video Time'

    s2 = figure(width=1000,
                plot_height=500,
                title=None,
                x_range=s1.x_range,
                y_range=s1.y_range)
    s2.line(plot_oe_codetimes / ephys_fs, plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'Video Codes in Video Time'

    p = gridplot([[s1], [s2]])
    output_file("ard_codes_in_Video_time.html")
    # show the results
    show(p)

    ####### FIGURE 4 ###########
    ####### PLOT the LINE fit:

    pp = figure(width=1000,
                plot_height=500,
                title='Line Fit for MW and OE Time')

    #pp.line(oe2mw_time/1e6,plot_oe_codes)
    pp.line(plot_oe_codetimes, m * plot_oe_codetimes + c, color='red')
    #pp.circle(plot_oe_codetimes[0:len(matches)],plot_mw_codetimes[0:len(matches)])
    pp.circle(oe_match_circles_samples, mw_match_circles_samples)
    pp.xaxis.axis_label = 'video codetimes'
    pp.yaxis.axis_label = 'arduino codetimes'
    output_file("pc_line_fit.html")
    show(pp)

    #print "number of Arduino events:"
    #print len(ard_times)

    #print "number of OE events:"
    #print len(oe_times)

    print "number of matches: " + str(len(matches))

    return matches, m, c, experiment_length
コード例 #3
0
def sync_pixel_clock(ard_path,
                     oe_path,
                     oe_channels=[0, 1],
                     skip_head=0,
                     skip_ephys=0,
                     win_size=20,
                     minMatch=15,
                     max_codes=-1):

    # make path to the Ch_0 and Ch_1 files:
    if oe_path[-1] == '/':
        ttls_path = oe_path + 'Ch_'
    else:
        ttls_path = oe_path + '/Ch_'

    [times, channels, directions
     ] = titanspikes_ttl_extract.get_TTL_info(ttls_path, oe_channels[0],
                                              oe_channels[1])

    # times are in seconds.microseconds
    ephys_fs = 1

    experiment_length = []

    print('Experiment length = ', experiment_length)

    oe_codes, latencies = pixelclock.events_to_codes(np.vstack(
        (times, channels, directions)).T,
                                                     len(oe_channels),
                                                     0.01,
                                                     swap_12_codes=1,
                                                     swap_03_codes=0)

    # the pixel clock should change once per frame, or at ~16ms max. This is 16ms * 30samples/ms = 480 samples. If a code is shorter than that, it's probably a fluke.
    # if oe_code times are in 636... format, use 10e4 as min code length
    #if in seconds.microseconds, min code time = 0.01

    #oe_codes = titanspikes_ttl_extract.read_raw_ttl(os.getcwd() + '/636598533041104644/TTLIns',swap_12_codes =1,limit=1e7)

    print('Number of ephys codes = ', len(oe_codes))

    ############################ get Arduino data:
    names = ['time', 'bit1', 'bit2', 'ox', 'oy', 'oz', 'ax', 'ay', 'az']
    head_data = pd.read_csv(ard_path, names=names)

    print(head_data[0:15])

    head_data.time = head_data.time / 1e3  ## convert from ms to sec

    ch1_diffs = np.diff(head_data.bit1)
    ch2_diffs = np.diff(head_data.bit2)

    ch1_nonzero_diffs = np.nonzero(ch1_diffs)[
        0]  ## [0] b/c where returns a stupid tuple
    ch2_nonzero_diffs = np.nonzero(ch2_diffs)[0]

    ch1_directions = ch1_diffs[ch1_nonzero_diffs]

    ch1_times = head_data.iloc[ch1_nonzero_diffs].time.values

    ch1_channels = np.zeros(ch1_directions.shape[0])

    ch2_directions = ch2_diffs[ch2_nonzero_diffs]

    ch2_times = head_data.iloc[ch2_nonzero_diffs].time.values

    ch2_channels = np.ones(ch2_directions.shape[0])

    ard_channels = np.hstack([ch1_channels, ch2_channels])
    ard_directions = np.hstack([ch1_directions, ch2_directions])
    ard_times = np.hstack([ch1_times, ch2_times])

    #print '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
    #print np.where(np.isnan(ard_channels)), np.where(np.isnan(ard_directions)), np.where(np.isnan(ard_times))

    ard_codes, ard_latencies = pixelclock.events_to_codes(np.vstack(
        (ard_times, ard_channels, ard_directions)).T,
                                                          2,
                                                          0.01,
                                                          swap_12_codes=1,
                                                          swap_03_codes=1)
    # !! assuming there's just one mworks file, take the first element in the list mwk_path:

    ##### alternative method:
    # codes = []
    # times = []
    # for idx in range(head_data.shape[0]):
    #     tmp_sum = head_data.bit1.values[idx] +  head_data.bit2.values[idx]
    #     #print tmp_sum
    #     if tmp_sum == 1:
    #         if head_data.bit1.values[idx] == 1:
    #             tmp_code = 2
    #         elif head_data.bit2.values[idx] == 1:
    #             tmp_code = 1
    #     elif tmp_sum == 0:
    #         tmp_code = 0
    #     else:
    #         tmp_code = 3
    #     codes.append(tmp_code)
    #     times.append(head_data.time[idx])
    # # (0,0) = 0. code = 0
    # # (0,1) = 1 code = 1
    # # (1,0) = 1 code = 2
    # # (1,1) = 2 code = 3
    # codes = np.array(codes)
    # times = np.array(times)
    # uni_codes = codes[np.where(np.diff(codes))[0]]
    # uni_times = times[np.where(np.diff(codes))[0]]

    # ard_codes = zip(uni_times,uni_codes)

    print('Number of Arduino codes = ', len(ard_codes))

    #### special skipping first few codes (which are bad,mkay) to get better matches- 8/3/16 for grat17:

    ard_codes = ard_codes[skip_head:
                          max_codes]  #10096 ,skip_head=2,skip_ephys=0
    oe_codes = oe_codes[skip_ephys:max_codes]

    # 3. get pixel clock matches
    print(
        '############################### PREPARING TO MATCH CODES #######################################'
    )
    matches = []
    #win_size = 20 ### WIN SIZE is now a kwarg
    print('win max is ', int(len(oe_codes) / win_size))
    for win in range(0, int(len(oe_codes) / win_size),
                     10):  #range(int(round(len(oe_codes)/win_size)))
        #for idx,win in enumerate(range(int(len(oe_codes)/win_size))):
        print('win = ', win)
        if win * win_size + win_size < len(oe_codes):
            ## don't go thru all arduino codes, but start at the previous time. (i.e. move forward!)
            if len(matches) > 1:
                ard_idx = np.where(
                    [thing[0] == matches[-1][1] for thing in ard_codes])[0][0]
                print('ard idx and last match time = ', ard_idx,
                      matches[-1][1])
            else:
                ard_idx = 0

            tmp_match = pixelclock.match_codes(
                [
                    evt[0]
                    for evt in oe_codes[win * win_size:(win + 1) * win_size]
                ],  # oe times
                [
                    evt[1]
                    for evt in oe_codes[win * win_size:(win + 1) * win_size]
                ],  # oe codes
                #[evt[0] for evt in oe_codes[win_size*idx: win_size*(idx+1)]], # oe times
                #[evt[1] for evt in oe_codes[win_size*idx: win_size*(idx+1)]], # oe codes
                [evt[0] for evt in ard_codes[ard_idx:]],  # mw times
                [evt[1] for evt in ard_codes[ard_idx:]],  # mw codes
                minMatch=minMatch,  ###15
                maxErr=0)
            print('temp matches = ', tmp_match)
            matches.extend(tmp_match)
        else:
            #print '!!win = ', win
            tmp_match = pixelclock.match_codes(
                [evt[0] for evt in oe_codes[win * win_size:-1]],  # oe times
                [evt[1] for evt in oe_codes[win * win_size:-1]],  # oe codes
                [evt[0] for evt in ard_codes],  # mw times
                [evt[1] for evt in ard_codes],  # mw codes
                minMatch=9,
                maxErr=0)

            matches.extend(tmp_match)

    print('matches = ', matches)
    #print 'type = ', type(matches)

    ard_times = [
        item[0] for item in ard_codes
    ]  #[e.time for e in stimulus_announces if isiterable(e.value)]
    oe_times = [item[0] for item in oe_codes]

    # condition the data to plot square pulses:
    tmp_ard_codes = [evt[1] for evt in ard_codes]
    tmp_mw_codetimes = [evt[0] for evt in ard_codes]
    plot_ard_codes = np.array(
        list(itertools.chain(*zip(tmp_ard_codes, tmp_ard_codes[:-1]))))
    plot_mw_codetimes = np.array(
        list(itertools.chain(*zip(tmp_mw_codetimes, tmp_mw_codetimes[1:]))))

    tmp_oe_codes = [evt[1] for evt in oe_codes]
    tmp_oe_codetimes = [evt[0] for evt in oe_codes]
    plot_oe_codes = np.array(
        list(itertools.chain(*zip(tmp_oe_codes, tmp_oe_codes[:-1]))))
    plot_oe_codetimes = np.array(
        list(itertools.chain(*zip(tmp_oe_codetimes, tmp_oe_codetimes[1:]))))

    # Bokeh:
    save_folder = './pixel_clock_arduino/'  # os.path.dirname(ard_path) +
    if not os.path.exists(save_folder):
        os.makedirs(save_folder)
    ####### FIGURE 1 ###########

    colors = []
    #col = np.matlib.repmat(rgb,10,1)

    for i in range(len(matches)):
        r = np.random.randint(255)
        g = np.random.randint(255)
        b = np.random.randint(255)

        colors.append(RGB(r, g, b))
    match_idx = [idx for idx, match in enumerate(matches)]
    #TOOLS = [HoverTool(),'box_zoom','reset','box_select']
    TOOLS = "pan,wheel_zoom,box_zoom,reset,hover,previewsave"
    s1 = figure(
        width=1000,
        plot_height=500,
        title='MWorks and OpenEhys Pixel Clock Codes')  # ,tools = TOOLS
    s1.line(plot_mw_codetimes, plot_ard_codes)
    mw_match_circles = [mat[1] for mat in matches]
    mw_match_circles_samples = [mat[1] for mat in matches]

    s1.circle(mw_match_circles, match_idx, color=colors, size=20)

    #s1.circle(mw_match_circles,np.ones(len(matches)),color=colors,size=20)
    s1.yaxis.axis_label = 'MW Codes'

    #tap = s1.select(dict(type=TapTool))

    s2 = figure(width=1000, plot_height=500, title=None)  #,tools = TOOLS
    s2.line(plot_oe_codetimes / ephys_fs, plot_oe_codes)
    oe_match_circles = [mat[0] / ephys_fs for mat in matches]
    oe_match_circles_samples = [mat[0] for mat in matches]

    s2.circle(oe_match_circles, match_idx, color=colors,
              size=20)  # ,tags = match_idx
    #s2.circle(oe_match_circles,np.ones(len(matches)),color=colors,size=20) # ,tags = match_idx
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes'

    p = gridplot([[s1], [s2]])
    output_file(save_folder + "pc_codes_match.html")
    # show the results
    show(p)

    #plt.savefig('pc_code_matches.pdf')
    #plt.show()

    #m,c = fit_line(tmp_oe_codetimes,tmp_mw_codetimes) #oe,mw
    m, c = fit_line(oe_match_circles_samples, mw_match_circles_samples)
    # tb object lets you go back and forth between oe and mw timezones
    tb = timebase.TimeBase(matches, tmp_oe_codetimes, tmp_mw_codetimes)

    ## to test quality of match, plot OE codes in MW time

    print('len plot_oe_codetimes = ', len(plot_oe_codetimes))

    #### want: take MW time (e.g. stim time) and get oe time:
    mw2oe_time = []
    for mw_time in plot_mw_codetimes:
        oe_tmp = mw_to_oe_time(mw_time, m,
                               c)  ### take MW time and convert to OE time
        #oe_tmp = tb.mw_to_oe_time(mw_time)
        mw2oe_time.append(oe_tmp)

    mw2oe_time = np.array(mw2oe_time)

    oe2mw_time = []
    for oe_time in plot_oe_codetimes:
        mw_tmp = oe_to_mw_time(oe_time, m,
                               c)  ### take OE and convert to MW time!
        #mw_tmp = tb.oe_to_mw_time(oe_time)
        oe2mw_time.append(mw_tmp)

    oe2mw_time = np.array(oe2mw_time)

    ####### FIGURE 2 ###########

    ####### PLOT the codes on the same time axis: e.g. everything on MW.

    tmp_oeMWconv_codetimes = [
        tb.audio_to_mworks(evt[0] / ephys_fs) for evt in oe_codes
    ]
    plot_oeMWconv_codetimes = np.array(
        list(
            itertools.chain(
                *zip(tmp_oeMWconv_codetimes, tmp_oeMWconv_codetimes[1:]))))

    s1 = figure(width=1000,
                plot_height=500,
                title='OE Codes Plotted in MW Time')
    s1.line(plot_mw_codetimes, plot_ard_codes)

    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in MW Time'

    s2 = figure(width=1000,
                plot_height=500,
                title=None,
                x_range=s1.x_range,
                y_range=s1.y_range)
    s2.line(oe2mw_time, plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in MW Time'

    p = gridplot([[s1], [s2]])
    output_file(save_folder + "oe_codes_in_MWtime.html")
    # show the results
    show(p)

    ####### FIGURE 3 ###########

    s1 = figure(width=1000,
                plot_height=500,
                title='MW Codes Plotted in OE Time')
    s1.line(mw2oe_time / ephys_fs, plot_ard_codes)

    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in OE Time'

    s2 = figure(width=1000,
                plot_height=500,
                title=None,
                x_range=s1.x_range,
                y_range=s1.y_range)
    s2.line(plot_oe_codetimes / ephys_fs, plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in OE Time'

    p = gridplot([[s1], [s2]])
    output_file(save_folder + "ard_codes_in_OEtime.html")
    # show the results
    show(p)

    ####### FIGURE 4 ###########
    ####### PLOT the LINE fit:

    pp = figure(width=1000,
                plot_height=500,
                title='Line Fit for MW and OE Time')

    #pp.line(oe2mw_time/1e6,plot_oe_codes)
    pp.line(plot_oe_codetimes, m * plot_oe_codetimes + c, color='red')
    #pp.circle(plot_oe_codetimes[0:len(matches)],plot_mw_codetimes[0:len(matches)])
    pp.circle(oe_match_circles_samples, mw_match_circles_samples)
    pp.xaxis.axis_label = 'oe codetimes'
    pp.yaxis.axis_label = 'ard codetimes'
    output_file(save_folder + "pc_line_fit.html")
    show(pp)

    print("number of Arduino events:")
    print(len(ard_times))

    print("number of OE events:")
    print(len(oe_times))

    print("number of matches: " + str(len(matches)))

    return matches, m, c, experiment_length, head_data
コード例 #4
0
	ax1 = plt.subplot(2, 1, 1)
	plt.plot(plot_mw_codetimes,plot_mw_codes)
	plt.scatter([mat[1] for mat in matches],np.ones(len(matches)),s=200, c=range(len(matches)))
	#plt.plot([mat[1] for mat in matches],numpy.matlib.repmat(1.5,len(matches),1), '-ro')
	plt.ylabel('MW Codes')

	ax2 = plt.subplot(2, 1, 2)
	plt.plot(plot_oe_codetimes,plot_oe_codes)
	plt.scatter([mat[0] for mat in matches],np.ones(len(matches)),s=200, c=range(len(matches)))
	#plt.plot([mat[0] for mat in matches],numpy.matlib.repmat(1.5,len(matches),1), '-ro')
	plt.ylabel('OE Codes')

	plt.show()


	tb = timebase.TimeBase(matches)

	oe_code_conv2mw_time = []
	for oe in plot_oe_codetimes:
		oe_code_conv2mw_time.append(tb.audio_to_mworks(oe))

	# plot the 4 code values over time:
	f,(ax1,ax2) = plt.subplots(2,1,sharex=True)
	#ax1 = plt.subplot(2, 1, 1)
	ax1.set_title('Plotting OE codes in MW time')
	ax1.plot(plot_mw_codetimes,plot_mw_codes)
	#ax1.scatter([mat[1] for mat in matches],np.ones(len(matches)),s=200, c=range(len(matches)))
	#plt.plot([mat[1] for mat in matches],numpy.matlib.repmat(1.5,len(matches),1), '-ro')
	plt.ylabel('MW Codes')

	#ax2 = plt.subplot(2, 1, 2)
コード例 #5
0
def sync_pixel_clock(mwk_path, oe_path, oe_channels=[0, 1]):

    # 1. read in ephys binary data and timestamps

    #for open ephys format data, use:
    #oe_events = open_ephys.loadEvents(oe_path)

    # unpack the channels
    #channels = oe_events['channel']
    #directions = oe_events['eventId'] # 0: 1 -> 0, 1: 0 -> 1
    #times = oe_events['timestamps']
    #event_types = oe_events['eventType']

    # for KWIK format, use:
   
    # 2. send those files to extract relevant info and concatenate:
    #all_times,all_channels,all_directions = concatenate(raw_files)
    
    [relevant,channels,directions,times],experiment_length = concatenateKWIKfiles.concatenate(oe_path)
   
    print 'Experiment length = ', experiment_length    


    # duplicate every element of times and directions

    rel_times_0 = times[channels==0]
    rel_times_1 = times[channels==1]
    rel_directions_0 = directions[channels==0]
    rel_directions_1 = directions[channels==1]

    plot_times_0 = np.array(list(itertools.chain(*zip(rel_times_0,rel_times_0[1:]))))
    plot_times_1 = np.array(list(itertools.chain(*zip(rel_times_1,rel_times_1[1:]))))
    plot_directions_0 = np.array(list(itertools.chain(*zip(rel_directions_0,rel_directions_0[:-1]))))
    plot_directions_1 = np.array(list(itertools.chain(*zip(rel_directions_1,rel_directions_1[:-1]))))

    # plot the up/down transitions as recorded on OE:
    # fig1 = plt.figure()
    # ax1 = plt.subplot(2, 1, 1)
    # plt.plot(plot_times_0,plot_directions_0)
    # plt.ylabel('OE Ch 0')

    # ax2 = plt.subplot(2, 1, 2,sharex=ax1)
    # plt.plot(plot_times_1,plot_directions_1)
    # plt.ylabel('OE Ch 1')

    #plt.show()

    oe_codes, latencies = pixelclock.events_to_codes(np.vstack((times, channels, directions)).T, len(oe_channels), 200)

   
    
    #oe_justthecodes = [evt[1] for evt in oe_codes]

    #print "oe_justthecodes:"
    #print oe_justthecodes
    
    #ind1 = [i for i,x in enumerate(oe_justthecodes) if x==1];
    #ind2 = [i for i,x in enumerate(oe_justthecodes) if x==2];
    #for i in ind1: oe_justthecodes[i]=2;
    #for j in ind2: oe_justthecodes[j]=1;

    #for x in oe_codes[x][1]:
        #print "x = " + x
    
    #for x in oe_codes:
    #    print oe_codes[x][1]
    #print "OpenEphys Codes (timestamp, code, which_channel_triggered)"
  
    # 2, Read in mworks events

    #mwk_path = '/Volumes/GG Data Raid/Ephys/grat10/2016-02-02_16-22-34/session_1622/grat10_ephys_160202_1622.mwk'
    #mwk_path = '/Volumes/GG Data Raid/Ephys/grat10/2016-02-02_16-22-34/session_1811/grat10_ephys_160202_1811.mwk'
    #mwk_path = '/Users/Guitchounts/Dropbox (coxlab)/Scripts/Repositories/continuous-ephys/sample_data/digintest_160112_3/digintest_160112_3.mwk'
    
    # !! assuming there's just one mworks file, take the first element in the list mwk_path:
    mwk_path = os.path.abspath(mwk_path[0])

    mwk = mw.MWKFile(mwk_path)
    mwk.open()



    # Start by getting the pixel clock / bit code data
    stimulus_announces = mwk.get_events(codes=['#announceStimulus'])

    # bit_codes is a list of (time, code) tuples
    mw_codes = [(e.time, e.value['bit_code']) for e in stimulus_announces if isiterable(e.value) and 'bit_code' in e.value]


    ## for mw_codes and oe_codes - if one code persists for too long a time (>thresh), get rid of it (keep only the fast-changing codes that come from the grating stimulus):

    oe_codes = lowpass_codetimes(oe_codes,fs=30e3,thresh_samples = 0.2) #0.2
    mw_codes = lowpass_codetimes(mw_codes,fs=1e6,thresh_samples = 1)

    #oe_codes = del_duplicate_codes(oe_codes)
    #mw_codes = del_duplicate_codes(mw_codes)


    #### special skipping first few codes (which are bad,mkay) to get better matches- 8/3/16 for grat17:
    #mw_codes = mw_codes[1:]
    #oe_codes = oe_codes[1:]

    # 3. get pixel clock matches
    matches = []
    win_size = 40
    print 'win max is ',int(len(oe_codes)/win_size)
    for win in range(0,int(len(oe_codes)/win_size),50): #range(int(round(len(oe_codes)/win_size)))
        print 'win = ', win
        if win*win_size+win_size < len(oe_codes):
            tmp_match = pixelclock.match_codes(
                [evt[0] for evt in oe_codes[win*win_size:(win+1)*win_size]], # oe times
                [evt[1] for evt in oe_codes[win*win_size:(win+1)*win_size]], # oe codes
                [evt[0] for evt in mw_codes], # mw times
                [evt[1] for evt in mw_codes], # mw codes
                minMatch = 20,
                maxErr = 0) 
            print 'temp matches = ', tmp_match
            matches.extend(tmp_match)
        else:
            print '!!win = ', win
            tmp_match = pixelclock.match_codes(
                    [evt[0] for evt in oe_codes[win*win_size:-1]], # oe times
                    [evt[1] for evt in oe_codes[win*win_size:-1]], # oe codes
                    [evt[0] for evt in mw_codes], # mw times
                    [evt[1] for evt in mw_codes], # mw codes
                    minMatch = 9,
                    maxErr = 0)
                    
            matches.extend(tmp_match)
    
    
    print 'matches = ', matches
    print 'type = ', type(matches)
    #matches = pixelclock.match_codes(
    #    [evt[0] for evt in oe_codes], # oe times
    #    [evt[1] for evt in oe_codes], # oe codes
    #    [evt[0] for evt in mw_codes], # mw times
    #    [evt[1] for evt in mw_codes], # mw codes
    #    minMatch = 5,
    #    maxErr = 0) # from 0 to 1 == from 23 to 27 matches, but in the wrong places. 


    #print "OE Code sequence:"
    #print [evt[1] for evt in oe_codes]

    #print "MW Code sequence:"
    #print [evt[1] for evt in mw_codes]

    #print "MATCHES:"
    #print matches

    mw_times = [item[0] for item in mw_codes] #[e.time for e in stimulus_announces if isiterable(e.value)]
    oe_times = [item[0] for item in oe_codes]

       

    # condition the data to plot square pulses:
    tmp_mw_codes = [evt[1] for evt in mw_codes]
    tmp_mw_codetimes = [evt[0] for evt in mw_codes]
    plot_mw_codes = np.array(list(itertools.chain(*zip(tmp_mw_codes,tmp_mw_codes[:-1])))) 
    plot_mw_codetimes = np.array(list(itertools.chain(*zip(tmp_mw_codetimes,tmp_mw_codetimes[1:])))) 

    tmp_oe_codes = [evt[1] for evt in oe_codes]
    tmp_oe_codetimes = [evt[0] for evt in oe_codes]
    plot_oe_codes = np.array(list(itertools.chain(*zip(tmp_oe_codes,tmp_oe_codes[:-1])))) 
    plot_oe_codetimes = np.array(list(itertools.chain(*zip(tmp_oe_codetimes,tmp_oe_codetimes[1:])))) 



    # Bokeh:

    ####### FIGURE 1 ###########

    colors = []
    #col = np.matlib.repmat(rgb,10,1)

    for i in range(len(matches)):
        r = np.random.randint(255)
        g = np.random.randint(255)
        b = np.random.randint(255)
        
        colors.append(RGB(r,g,b)) 
    match_idx = [idx for idx,match in enumerate(matches)]    
    #TOOLS = [HoverTool(),'box_zoom','reset','box_select']
    TOOLS="pan,wheel_zoom,box_zoom,reset,hover,previewsave"
    s1 = figure(width=1000, plot_height=500, title='MWorks and OpenEhys Pixel Clock Codes') # ,tools = TOOLS
    s1.line(plot_mw_codetimes/1e6,plot_mw_codes)
    mw_match_circles = [mat[1]/1e6 for mat in matches]
    mw_match_circles_samples = [mat[1] for mat in matches]

    s1.circle(mw_match_circles,match_idx,color=colors,size=20)
    
    #s1.circle(mw_match_circles,np.ones(len(matches)),color=colors,size=20)
    s1.yaxis.axis_label = 'MW Codes'

    #tap = s1.select(dict(type=TapTool))
    

    s2 = figure(width=1000, plot_height=500, title=None) #,tools = TOOLS
    s2.line(plot_oe_codetimes/30e3,plot_oe_codes)
    oe_match_circles = [mat[0]/30e3 for mat in matches]
    oe_match_circles_samples = [mat[0] for mat in matches]
    
    
    s2.circle(oe_match_circles,match_idx,color=colors,size=20) # ,tags = match_idx
    #s2.circle(oe_match_circles,np.ones(len(matches)),color=colors,size=20) # ,tags = match_idx
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes'

    


    p = gridplot([[s1], [s2]])
    output_file("pc_codes_match.html")
    # show the results
    show(p)
    
    #plt.savefig('pc_code_matches.pdf')
    #plt.show()


    #m,c = fit_line(tmp_oe_codetimes,tmp_mw_codetimes) #oe,mw 
    m,c = fit_line(oe_match_circles_samples,mw_match_circles_samples)
    # tb object lets you go back and forth between oe and mw timezones
    tb = timebase.TimeBase(matches,tmp_oe_codetimes,tmp_mw_codetimes)
    

    ## to test quality of match, plot OE codes in MW time

    print 'len plot_oe_codetimes = ', len(plot_oe_codetimes)



    


    #### want: take MW time (e.g. stim time) and get oe time:
    mw2oe_time = []
    for mw_time in plot_mw_codetimes:
        oe_tmp = mw_to_oe_time(mw_time,m,c) ### take MW time and convert to OE time 
        #oe_tmp = tb.mw_to_oe_time(mw_time)
        mw2oe_time.append(oe_tmp)

    mw2oe_time = np.array(mw2oe_time)

    oe2mw_time = []
    for oe_time in plot_oe_codetimes:
        mw_tmp = oe_to_mw_time(oe_time,m,c)  ### take OE and convert to MW time!
        #mw_tmp = tb.oe_to_mw_time(oe_time)
        oe2mw_time.append(mw_tmp)

    oe2mw_time = np.array(oe2mw_time)


    ####### FIGURE 2 ###########


    ####### PLOT the codes on the same time axis: e.g. everything on MW.
    
    

    tmp_oeMWconv_codetimes = [tb.audio_to_mworks(evt[0]/30e3)* 1e6 for evt in oe_codes]
    plot_oeMWconv_codetimes = np.array(list(itertools.chain(*zip(tmp_oeMWconv_codetimes,tmp_oeMWconv_codetimes[1:])))) 

    

    s1 = figure(width=1000, plot_height=500, title='OE Codes Plotted in MW Time')
    s1.line(plot_mw_codetimes/1e6,plot_mw_codes)
    
    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in MW Time'

    s2 = figure(width=1000, plot_height=500, title=None,x_range=s1.x_range,y_range=s1.y_range)
    s2.line(oe2mw_time/1e6,plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in MW Time'
    
    p = gridplot([[s1], [s2]])
    output_file("oe_codes_in_MWtime.html")
    # show the results
    show(p)
    
    ####### FIGURE 3 ###########

    s1 = figure(width=1000, plot_height=500, title='MW Codes Plotted in OE Time')
    s1.line(mw2oe_time/30e3,plot_mw_codes)
    
    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in OE Time'

    s2 = figure(width=1000, plot_height=500, title=None,x_range=s1.x_range,y_range=s1.y_range)
    s2.line(plot_oe_codetimes/30e3,plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in OE Time'
    
    p = gridplot([[s1], [s2]])
    output_file("mw_codes_in_OEtime.html")
    # show the results
    show(p)
    

    ####### FIGURE 4 ###########
    ####### PLOT the LINE fit:
    
    pp = figure(width=1000, plot_height=500, title='Line Fit for MW and OE Time')
    
    #pp.line(oe2mw_time/1e6,plot_oe_codes)
    pp.line(plot_oe_codetimes,m*plot_oe_codetimes+c,color='red')
    #pp.circle(plot_oe_codetimes[0:len(matches)],plot_mw_codetimes[0:len(matches)])
    pp.circle(oe_match_circles_samples,mw_match_circles_samples)
    pp.xaxis.axis_label = 'oe codetimes'
    pp.yaxis.axis_label = 'mw codetimes'
    output_file("pc_line_fit.html")
    show(pp)


    print "number of MW events:"
    print len(mw_times)

    print "number of OE events:"
    print len(oe_times)

    print "number of matches: " + str(len(matches))
    

    


    return matches,mwk,m,c,experiment_length
コード例 #6
0
def sync_pixel_clock(mwk_path, oe_path, oe_channels=[0, 1]):

    # 1. read in ephys binary data and timestamps

    
    ###[times,channels,directions] = titanspikes_ttl_extract.get_TTL_info('./636152664381217973/TTLChanges/Ch_')
    
    # times are in seconds.microseconds
    ephys_fs = 1

    experiment_length=[]


    print('Experiment length = ', experiment_length)

    
    #oe_codes, latencies = pixelclock.events_to_codes(np.vstack((times, channels, directions)).T, len(oe_channels), 0.01)
    # the pixel clock should change once per frame, or at ~16ms max. This is 16ms * 30samples/ms = 480 samples. If a code is shorter than that, it's probably a fluke.
    # if oe_code times are in 636... format, use 10e4 as min code length
    #if in seconds.microseconds, min code time = 0.01

    oe_codes = titanspikes_ttl_extract.read_raw_ttl(oe_path)  # './636151800793559606/TTLIns'
    # oe_codes[0,:] = times
    # oe_codes[1,:] = codes

    print('Number of ephys codes = ', len(oe_codes))

   
    # !! assuming there's just one mworks file, take the first element in the list mwk_path:
    mwk_path = os.path.abspath(mwk_path[0])

    mwk = mw.MWKFile(mwk_path)
    mwk.open()



    # Start by getting the pixel clock / bit code data
    stimulus_announces = mwk.get_events(codes=['#announceStimulus'])

    # bit_codes is a list of (time, code) tuples
    mw_codes = [(e.time, e.value['bit_code']) for e in stimulus_announces if isiterable(e.value) and 'bit_code' in e.value]

    print('Number of mworks codes = ', len(mw_codes))
    ## for mw_codes and oe_codes - if one code persists for too long a time (>thresh), get rid of it (keep only the fast-changing codes that come from the grating stimulus):

    oe_codes = lowpass_codetimes(oe_codes,fs=1,thresh_samples = 0.01) #0.2
    mw_codes = highpass_codetimes(mw_codes,fs=1e6,thresh_samples = 1)



    print('Number of oe codes after lowpass = '******'Number of mworks codes after lowpass = '******'win max is ',int(len(oe_codes)/win_size))
    for win in range(0,int(len(oe_codes)/win_size),50): #range(int(round(len(oe_codes)/win_size)))
        print('win = ', win)
        if win*win_size+win_size < len(oe_codes):
            tmp_match = pixelclock.match_codes(
                [evt[0] for evt in oe_codes[win*win_size:(win+1)*win_size]], # oe times
                [evt[1] for evt in oe_codes[win*win_size:(win+1)*win_size]], # oe codes
                [evt[0] for evt in mw_codes], # mw times
                [evt[1] for evt in mw_codes], # mw codes
                minMatch = 20,
                maxErr = 0) 
            print('temp matches = ', tmp_match)
            matches.extend(tmp_match)
        else:
            #print '!!win = ', win
            tmp_match = pixelclock.match_codes(
                    [evt[0] for evt in oe_codes[win*win_size:-1]], # oe times
                    [evt[1] for evt in oe_codes[win*win_size:-1]], # oe codes
                    [evt[0] for evt in mw_codes], # mw times
                    [evt[1] for evt in mw_codes], # mw codes
                    minMatch = 9,
                    maxErr = 0)
                    
            matches.extend(tmp_match)
    
    
    print('matches = ', matches)
    #print 'type = ', type(matches)
  

    mw_times = [item[0] for item in mw_codes] #[e.time for e in stimulus_announces if isiterable(e.value)]
    oe_times = [item[0] for item in oe_codes]

       

    # condition the data to plot square pulses:
    tmp_mw_codes = [evt[1] for evt in mw_codes]
    tmp_mw_codetimes = [evt[0] for evt in mw_codes]
    plot_mw_codes = np.array(list(itertools.chain(*zip(tmp_mw_codes,tmp_mw_codes[:-1])))) 
    plot_mw_codetimes = np.array(list(itertools.chain(*zip(tmp_mw_codetimes,tmp_mw_codetimes[1:])))) 

    tmp_oe_codes = [evt[1] for evt in oe_codes]
    tmp_oe_codetimes = [evt[0] for evt in oe_codes]
    plot_oe_codes = np.array(list(itertools.chain(*zip(tmp_oe_codes,tmp_oe_codes[:-1])))) 
    plot_oe_codetimes = np.array(list(itertools.chain(*zip(tmp_oe_codetimes,tmp_oe_codetimes[1:])))) 



    # Bokeh:

    ## make save directory:
    save_folder = './pixelclock/' 
    if not os.path.exists(save_folder):
        os.makedirs(save_folder)



    ####### FIGURE 1 ###########

    colors = []
    #col = np.matlib.repmat(rgb,10,1)

    for i in range(len(matches)):
        r = np.random.randint(255)
        g = np.random.randint(255)
        b = np.random.randint(255)
        
        colors.append(RGB(r,g,b)) 
    match_idx = [idx for idx,match in enumerate(matches)]    
    #TOOLS = [HoverTool(),'box_zoom','reset','box_select']
    TOOLS="pan,wheel_zoom,box_zoom,reset,hover,previewsave"
    s1 = figure(width=1000, plot_height=500, title='MWorks and OpenEhys Pixel Clock Codes') # ,tools = TOOLS
    s1.line(plot_mw_codetimes/1e6,plot_mw_codes)
    mw_match_circles = [mat[1]/1e6 for mat in matches]
    mw_match_circles_samples = [mat[1] for mat in matches]

    s1.circle(mw_match_circles,match_idx,color=colors,size=20)
    
    #s1.circle(mw_match_circles,np.ones(len(matches)),color=colors,size=20)
    s1.yaxis.axis_label = 'MW Codes'

    #tap = s1.select(dict(type=TapTool))
    

    s2 = figure(width=1000, plot_height=500, title=None) #,tools = TOOLS
    s2.line(plot_oe_codetimes/ephys_fs,plot_oe_codes)
    oe_match_circles = [mat[0]/ephys_fs for mat in matches]
    oe_match_circles_samples = [mat[0] for mat in matches]
    
    
    s2.circle(oe_match_circles,match_idx,color=colors,size=20) # ,tags = match_idx
    #s2.circle(oe_match_circles,np.ones(len(matches)),color=colors,size=20) # ,tags = match_idx
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes'


    p = gridplot([[s1], [s2]])
    output_file(save_folder + "pc_codes_match.html")
    # show the results
    show(p)
    
    #plt.savefig('pc_code_matches.pdf')
    #plt.show()


    #m,c = fit_line(tmp_oe_codetimes,tmp_mw_codetimes) #oe,mw 
    m,c = fit_line(oe_match_circles_samples,mw_match_circles_samples)
    # tb object lets you go back and forth between oe and mw timezones
    tb = timebase.TimeBase(matches,tmp_oe_codetimes,tmp_mw_codetimes)
    

    ## to test quality of match, plot OE codes in MW time

    print('len plot_oe_codetimes = ', len(plot_oe_codetimes))



    


    #### want: take MW time (e.g. stim time) and get oe time:
    mw2oe_time = []
    for mw_time in plot_mw_codetimes:
        oe_tmp = mw_to_oe_time(mw_time,m,c) ### take MW time and convert to OE time 
        #oe_tmp = tb.mw_to_oe_time(mw_time)
        mw2oe_time.append(oe_tmp)

    mw2oe_time = np.array(mw2oe_time)

    oe2mw_time = []
    for oe_time in plot_oe_codetimes:
        mw_tmp = oe_to_mw_time(oe_time,m,c)  ### take OE and convert to MW time!
        #mw_tmp = tb.oe_to_mw_time(oe_time)
        oe2mw_time.append(mw_tmp)

    oe2mw_time = np.array(oe2mw_time)


    ####### FIGURE 2 ###########


    ####### PLOT the codes on the same time axis: e.g. everything on MW.
    
    

    tmp_oeMWconv_codetimes = [tb.audio_to_mworks(evt[0]/ephys_fs)* 1e6 for evt in oe_codes]
    plot_oeMWconv_codetimes = np.array(list(itertools.chain(*zip(tmp_oeMWconv_codetimes,tmp_oeMWconv_codetimes[1:])))) 

    

    s1 = figure(width=1000, plot_height=500, title='OE Codes Plotted in MW Time')
    s1.line(plot_mw_codetimes/1e6,plot_mw_codes)
    
    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in MW Time'

    s2 = figure(width=1000, plot_height=500, title=None,x_range=s1.x_range,y_range=s1.y_range)
    s2.line(oe2mw_time/1e6,plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in MW Time'
    
    p = gridplot([[s1], [s2]])
    output_file(save_folder + "oe_codes_in_MWtime.html")
    # show the results
    show(p)
    
    ####### FIGURE 3 ###########

    s1 = figure(width=1000, plot_height=500, title='MW Codes Plotted in OE Time')
    s1.line(mw2oe_time/ephys_fs,plot_mw_codes)
    
    #match_circles = [mat[1] for mat in matches]
    #s1.circle(match_circles,np.ones(len(matches)),color=colors,size=20)

    s1.yaxis.axis_label = 'MW Codes in OE Time'

    s2 = figure(width=1000, plot_height=500, title=None,x_range=s1.x_range,y_range=s1.y_range)
    s2.line(plot_oe_codetimes/ephys_fs,plot_oe_codes)
    s2.xaxis.axis_label = 'Time (sec)'
    s2.yaxis.axis_label = 'OE Codes in OE Time'
    
    p = gridplot([[s1], [s2]])
    output_file(save_folder + "mw_codes_in_OEtime.html")
    # show the results
    show(p)
    

    ####### FIGURE 4 ###########
    ####### PLOT the LINE fit:
    
    pp = figure(width=1000, plot_height=500, title='Line Fit for MW and OE Time')
    
    #pp.line(oe2mw_time/1e6,plot_oe_codes)
    pp.line(plot_oe_codetimes,m*plot_oe_codetimes+c,color='red')
    #pp.circle(plot_oe_codetimes[0:len(matches)],plot_mw_codetimes[0:len(matches)])
    pp.circle(oe_match_circles_samples,mw_match_circles_samples)
    pp.xaxis.axis_label = 'oe codetimes'
    pp.yaxis.axis_label = 'mw codetimes'
    output_file(save_folder + "pc_line_fit.html")
    show(pp)


    print("number of MW events:")
    print(len(mw_times))

    print("number of OE events:")
    print(len(oe_times))

    print("number of matches: " + str(len(matches)))
    
    linefit = dict(m=[m],c=[c])
    linefit_pd = pd.DataFrame.from_dict(linefit)
    linefit_pd.to_csv('linefit.csv')
   

    


    return matches,mwk,m,c,experiment_length