Example #1
0
def ffp_dax(filename,xmlname):	
	print "ffpdax started at " + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + " on file: " + filename
	#read in the settings in the .xml file using hazen's Parameter Class
	par = params.Parameters(xmlname+'.xml') #par is an object of type Parameters, defined in sa_library
	#to access parameters, use par.parameter name. eg par.start_frame
	#note these values can be manually changed: par.frameset = 200 replaces whatever was there.


	par = fixpar.fix_par(par,filename,'ffpdax') #function to 'fix' par by reading in needed stuff from setup file, 
	#and making other changes which might be needed based on the settings - 
	#eg round frame numbers to mutiple of 4 if alternating laser on STORM2

	print "x pixels: %d. y pixels: %d" %(par.dimx,par.dimy)

	if par.emchs == 2:	#read in mapping files
		Pr2l, Qr2l = mapcoords.readmapping(par,'r2l')
		Pl2r, Ql2r = mapcoords.readmapping(par,'l2r')
		#generate mapx and mapy for l-->r map (transforms right ch onto left)
		mapxl2r,mapyl2r = mapcoords.genmapxy(par,Pl2r,Ql2r) #does not include the dimx/2 offset
	
	fileptr = open(filename+'.dax','rb')
	#open the dax file
	#print "Filename: ", fileptr.name
	if par.d3peaks == 1:
		no_sets = long(math.floor(float(par.max_frame - par.start_frame + 1) / float(par.frameset)))
		#arrays for the pks data
		active = np.zeros((3,50000))
		complete = np.zeros((4,50000))
		#keep track of how many active, complete
		no_a = 0 #number active 
		no_com = 0#number complete
		
		#start reading in frame sets
		currset_st = long(par.start_frame) #start frame of the current set of interest
		frames = np.zeros((par.dimy,par.dimx,par.frameset)) #note: x value is column, y value is row.
		print "number sets: %i" %no_sets
		for i in range(0,no_sets): #goes from 0 to no_sets -1
			if i % 1000 == 0: print "working on %i"  %i #keep track of progress
			for k in range(0,par.frameset):
				frame = loadframe.load_frame(fileptr,currset_st+k,par)	
				#im =Image.fromarray(frame)
				#im.show()
				frame.astype(float) #change to float
				frames[:,:,k] = frame
				
			#if ALEX4 =1, pick out subset of frames to be used, based on pickcol. otherwise, use all frames
			if par.ALEX4 ==1:
				if par.pickcol == 0:
					rframes = np.zeros((par.dimy,par.dimx,(par.frameset)/4))
					for k in range(0,par.frameset,4):
						rframes[:,:,k/4] = (frames[:,:,k] + frames[:,:,k+1])/2
				elif par.pickcol ==1:
					rframes = np.zeros((par.dimy,par.dimx,par.frameset/4))
					for k in range(2,par.frameset,4):
						rframes[:,:,(k-2)/4] = (frames[:,:,k] + frames[:,:,k+1])/2
				elif par.pickcol ==2:
					rframes = np.zeros((par.dimy,par.dimx,par.frameset/2))
					for k in range(0,par.frameset,2):
						rframes[:,:,k/2] = (frames[:,:,k]+frames[:,:,k+1])/2
				else:
					print "That's not a pickcol option!"
					break	
			else:
				rframes = frames
				
					
				
			#next, median filter the frames in the frameset
			medimg = np.median(rframes, axis = 2)	
			
			#background for medimg
			fr_bk = smbkgr.sm_bkgr(medimg,par.bksize) #seems okay; check once showing images added
			medimg = medimg-fr_bk

			#deal with multiple emission channels -- either use one, or combine after mapping.
			if par.emchs ==1: 
				pass #one channel - no subset is picked out.
			elif par.emchs ==2:
				if par.pickchan ==0: #'left' channel
					medimg = medimg[:,0:par.dimx/2]
				elif par.pickchan ==1: #'right' channel; still find peaks in left coords so we get both.
					src = np.zeros((par.dimy,par.dimx/2,3))
					src[:,:,0] = medimg[:,par.dimx/2:par.dimx]
					mapyl2rCV = mapyl2r.astype(np.float32)
					mapxl2rCV = mapxl2r.astype(np.float32)
					rightmapped = cv2.remap(src,mapxl2rCV,mapyl2rCV,interpolation = cv2.INTER_CUBIC)
					medimg = rightmapped[:,:,0]
				elif par.pickchan ==2: #combine channels after warping. Using the 'left' channel coordinates
					print 'warping is lightly tested. Appears to work.'
					#medimg = medimg[:,0:par.dimx/2] + transform.warp(medimg[:,par.dimx/2:par.dimx],tformr2l)
					#medimg = medimg[:,0:par.dimx/2] + medimg[:,par.dimx/2:par.dimx] #FOR TESTING ONLY. NOT WARPED
					#templeft = medimg[:,0:par.dimx/2]
					#tempright = medimg[:,par.dimx/2:par.dimx]
					src = np.zeros((par.dimy,par.dimx/2,3))
					src[:,:,0] = medimg[:,par.dimx/2:par.dimx]
					mapyl2rCV = mapyl2r.astype(np.float32)
					mapxl2rCV = mapxl2r.astype(np.float32)
					rightmapped = cv2.remap(src,mapxl2rCV,mapyl2rCV,interpolation = cv2.INTER_CUBIC)
					rightmapped = cv2.remap(src,mapxl2rCV,mapyl2rCV,interpolation = cv2.INTER_CUBIC)
					#medimg = medimg[:,0:par.dimx/2] + cv2.remap(rightch,mapyl2r,mapxl2r,interpolation = cv2.INTER_CUBIC)
					medimg = medimg[:,0:par.dimx/2] + rightmapped[:,:,0]
					#medimg = rightmapped[:,:,0]
			else:
				print "Not set up for more than two emission channel"		
			
			
			#scale the med_img for display. for convenience, also find peaks in the scaled image
			medimg=255.0*(medimg+par.disp_off)/par.disp_fact 
			#requires scaling factors to be known ahead of time. tricky to pick out of the data -often nothing present at the begining
			
			
			#ready to go find peaks!
			sliceresult = ffpslice.ffp_slice(medimg,currset_st,par) #these are all 'raw' results in medimg frame. Wait until the very end to map, if needed
			current = sliceresult[0]
			
			#fixme: if number ch > 1, somewhere, output all channels with picked peaks circled
			#add current peaks to active unless they are already present
			no_cu = current.shape[1]
			#print "number current %d" %no_cu
			for c in range(0,no_cu):
				xc = current[0,c]
				yc = current[1,c]
				ID = 0 #has it been found?
				if xc > 0.1:	#real peaks aren't at zero
					for a in range(0,no_a):
						distance = ((xc - active[0,a])**2 + (yc - active[1,a])**2)**0.5
						#print distance
						if distance < par.dist_thr:
							ID = 1 #this peak is already in active.
							break #can stop looking for it
					if ID == 0:
						active[:,no_a] = [xc,yc,float(currset_st)]
						no_a +=1
			
			#move peaks from active to complete if they aren't found in keep
			n_t = 0 #number moved
			temp_active = np.zeros((3,50000))
			if par.keeptype == 0: 
				for a in range(0,no_a): #for each active peak, look through keep to decide whether to keep it active
					keep = sliceresult[1]
					xa = active[0,a]
					ya = active[1,a]
					ID = 0
					for c in range(0,no_cu): 
						distance = ((xa - keep[0,c])**2 + (ya - keep[1,c])**2)**0.5
						if distance < dist_thr :
							ID = 1
							break
					if ID ==1:
						temp_active[:,n_t] = active[:,a]
						n_t = n_t + 1
					else: #event over. move to complete, but only if long enough but not too long
						if((currset_st - active[2,a]) > par.length_thr) and ((currset_st - active[2,a]) < par.max_len):
							complete[0:3,no_com] = active[:,a]
							complete[3,no_com] = float(currset_st-1)
							no_com +=1
			else: #keeptype = 1
				keep = ffpslice.ffp_keep(medimg,currset_st,par,active[:,0:no_a])
				for a in range(0,no_a):
					if keep[a] == 0: #event a is done
						if((currset_st - active[2,a]) > par.length_thr) and ((currset_st - active[2,a]) < par.max_len):
							complete[0:3,no_com] = active[:,a]
							complete[3,no_com] = float(currset_st-1)
							no_com +=1
					else: #keep on active list
						temp_active[:,n_t] = active[:,a]
						n_t +=1
						
			active = temp_active
			no_a = n_t
			
			currset_st += par.frameset
			#end of analysis for this frameset
		#once we're done flipping through sets, move everything from active to complete, assuming long enough
		#print 'num active: %d' %no_a
		for a in range(0,no_a):
			if (((par.max_frame - active[2,a]) > par.length_thr) and ((par.max_frame - active[2,a]) < par.max_len)) :
				complete[0:3,no_com] = active[:,a]
				complete[3,no_com] = float(par.max_frame)
				no_com += 1
		
		
		if no_com > 0:
			print "there were %d events" %no_com
			times = complete[3,0:no_com] - complete[2,0:no_com] + 1
			print 'average event length: %f' %float(np.mean(times))
			print 'median event length: %f' %float(np.median(times))
		else:
			times = np.zeros((1,1))
		#now, if appropriate, map the values
		if par.emchs ==1:
			pass
		elif par.emchs == 2:
			#mapping - have 'left' coordinates; need 'right' channel coordinates too (**this is true even if picking on the right side, since it is mapped)
			#first, expand complete to have space for more coordinates.
			bigcomplete = np.zeros((6,no_com))
			bigcomplete[0:2,:] = complete[0:2,0:no_com]
			bigcomplete[4:6,:] = complete[2:4,0:no_com]
			for a in range(0,no_com):
				bigcomplete[2:4,a]=mapcoords.map_coords(bigcomplete[0,a],bigcomplete[1,a],Pl2r,Ql2r)
				#bigcomplete[2:4,a] = complete[0:2,a] #testing only. for null mapping
				bigcomplete[2,a] += par.dimx/2
				bigcomplete[2,a] = 0.5*round(bigcomplete[2,a]*2,0)
				bigcomplete[3,a] =0.5*round(bigcomplete[3,a]*2,0)
			complete = bigcomplete
			
			#then, need to make sure all the mapped positions are also acceptable . if not, remove that peak!
			#compare to par.frameborder
			filtcomplete = np.zeros((6,no_com))
			no_filt = 0
			for a in range(0,no_com):
				okay =1 
				if(complete[0,a]-par.frameborder < 0 or complete[0,a]+par.frameborder >par.dimx/2):
					okay = 0
				if(complete[1,a] -par.frameborder<0 or complete[1,a] +par.frameborder>par.dimy):
					okay = 0
				if(complete[2,a]-par.frameborder<par.dimx/2 or complete[2,a]+par.frameborder>par.dimx):
					okay = 0
				if(complete[3,a]-par.frameborder<0 or complete[3,a]+par.frameborder>par.dimy):
					okay = 0
				if(okay==1):
					filtcomplete[:,no_filt] = complete[:,a]
					no_filt += 1
			complete = filtcomplete
			no_com = no_filt
		
			
		#save output as text file
		c_tosave = np.zeros((complete.shape[0]+1,no_com))
		c_tosave[1:complete.shape[0]+1,:] = complete[:,0:no_com]
		for i in range(0,no_com):
			c_tosave[0,i] =i 
		c_tosave = np.transpose(c_tosave)
		format = ['%- i','%-.1f','%-.1f','%-.1f','%-.1f']
		if par.emchs ==2:
			format = ['%- i','%-.1f','%-.1f','%-.1f','%-.1f','%-.1f','%-.1f']
		np.savetxt(filename+'.pks3d',c_tosave,fmt=format,delimiter='\t')
		
		#make and save a histogram of the times
		#hbinnum = np.round((times.max()-times.min())/par.frameset)
		p95 = np.percentile(times,95)#make histogram look reasonable - don't display the very long tail
		hbinnum = np.round((p95 - times.min())/par.frameset)
		if hbinnum == 0: hbinnum =1
		hist,binedges = np.histogram(times,bins=hbinnum,range = (times.min(),p95))
		plt.plot(binedges[0:-1],hist)
		plt.xlabel('duration,frames')
		#plt.show()
		plt.savefig(filename+'durationhist.jpeg')

		
	else:
		print "not set up for this yet. use IDL code or add here"

	#save par object as an xml file. mostly the same as the input file, but some things are changed by fixpar.
	outxml = filename + "ffpdaxOUT.xml"
	writexml.write_xml(par,outxml,'ffpdax',filename,[no_com,np.mean(times),np.median(times)])

	#close the dax file
	fileptr.close()

	print "done at " + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')

	if par.autocont==1:
		print 'automatically calling apdax'
		#print 'apdax.py'
		from apdax import ap_dax
		ap_dax(filename,xmlname)
Example #2
0
def ap_dax(filename, xmlname):
    print "apdax started at " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " on file: " + filename

    # read in the settings in the .xml file using hazen's Parameter Class
    par = params.Parameters(xmlname + ".xml")
    par = fixpar.fix_par(par, filename, "apdax")  # function to 'fix' par by reading in needed stuff from setup file,
    # and making other changes which might be needed based on the settings -
    # eg round frame numbers to mutiple of 4 if alternating laser on STORM2

    if par.emchs == 2:  # read in mapping files
        Pr2l, Qr2l = mapcoords.readmapping(par, "r2l")
        Pl2r, Ql2r = mapcoords.readmapping(par, "l2r")

        # for now, not using CMOS calibration. FIXME
    if par.hcam_cal == 1:
        print "Not set up for CMOS calibration"
        # for now, only set up for .trdir output and .pks3d input
    if par.pks_type == 0:
        print "Not set up for .pks file. Only .pks3d"
    if par.outtype == 0:
        print "Not set up for .traces file. only trdir"

    if par.mt == 1:  # gaussian mask
        g_peaks = gengauss.gen_gauss()

        # read in peaks info
    if par.pks_type == 0:
        print "not set up for pks file"
    elif par.pks_type == 1:
        pkfile = filename + ".pks3d"
        peaks = loadpeaks.load_peaks(pkfile, par)  # loads and processes (adds buffer) peaks file
    else:
        print "format not recognized"
    no_peaks = peaks.shape[0]
    peaks_dim = peaks.shape[1]  # useful since since of peaks depends on analysis type

    # make list of arrays to hold data. allows unequal lengths for different traces
    time_tr = []  # for intensities. always need.
    crds_tr = []  # for fitting. sometimes need.
    for p in range(0, no_peaks):
        curlen = int(peaks[p, peaks_dim - 1] - peaks[p, peaks_dim - 2]) + 1
        if par.ALEX4 == 1:
            curlen = curlen / 2  # note this rounds down
            # note colors are interleaved. emchs is based on emission path

        time_tr.append(np.zeros((par.emchs, curlen)))
        crds_tr.append(np.zeros((par.emchs, curlen, 8)))
        # for holding coordinates (x,y, x_stdev, y_stdev, fitting flag, quality metric, tilt angle, fit height)
        # keep track of which position in the array next frame's info will be added to.
    addfr = np.zeros(no_peaks)
    # fixme: use peak position to decide where to center gaussian mask. see idl code.

    # start going through the frames.
    incr = 1
    if par.ALEX4 == 1:
        incr = 2  # go through frames 2 at a time
    fileptr = open(filename + ".dax", "rb")

    # if using constant background subtraction, determine that now:
    if par.bst == 0:
        # load first 10 frames to determine background
        frs = loadframe.load_frame(fileptr, 0, par)
        for i in range(1, 10):
            frs += loadframe.load_frame(fileptr, i, par)
        frs = frs / 10
        fr_bkgd = smbkgr.sm_bkgr(frs, par.bksize)

        # fitting stuff. fixme: choose fit type in xml file? for now, don't allow tilt
    fitfunc = lambda p, x, y: p[0] + p[1] * np.exp(-((x - p[2]) / p[4]) ** 2 - ((y - p[3]) / p[5]) ** 2)
    errfunc = lambda p, x, y, data: np.ravel(fitfunc(p, x, y) - data)
    fitxval = np.zeros((par.fit_box * 2 + 1, par.fit_box * 2 + 1))  # independent variables for fit
    fityval = np.zeros((par.fit_box * 2 + 1, par.fit_box * 2 + 1))
    for i in range(0, par.fit_box * 2 + 1):  # fill arrays with row or column number
        fitxval[:, i] = i
        fityval[i, :] = i
    fitxval1D = np.ravel(fitxval)
    fityval1D = np.ravel(fityval)
    # fixme: adjust error function to allow weighting

    for i in range(par.apst_fr, par.apmax_fr + 1, incr):  # i is always a real camera frame number
        if i % 1000 == 0:
            print "working on : " + str(i) + " " + str(par.apmax_fr) + "at " + datetime.datetime.now().strftime(
                "%Y-%m-%d %H:%M:%S"
            )

        if par.ALEX4 == 0:
            frame = loadframe.load_frame(fileptr, i, par)
        if par.ALEX4 == 1:
            frame1 = loadframe.load_frame(fileptr, i, par)
            frame2 = loadframe.load_frame(fileptr, i + 1, par)
            frame = frame1 + frame2
            # either way, now work with frame array

            # if set to determine background on each frame, do that
        if par.bst == 1:
            fr_bkgd = smbkgr.sm_bkgr(frame, par.bksize)

            # analyze each trace
        for j in range(0, no_peaks):
            if peaks[j, peaks_dim - 1] >= i and peaks[j, peaks_dim - 2] <= i:  # this event is happening now!
                for ch in range(0, par.emchs):
                    # determine intensity
                    curx = math.floor(peaks[j, 1 + 2 * ch])
                    cury = math.floor(peaks[j, 2 + 2 * ch])
                    if par.mt == 0:  # simple integration
                        local = (
                            frame[cury - par.sibs : cury + par.sibs + 1, curx - par.sibs : curx + par.sibs + 1]
                            - fr_bkgd[cury - par.sibs : cury + par.sibs + 1, curx - par.sibs : curx + par.sibs + 1]
                        )
                        time_tr[j][ch, addfr[j]] = np.sum(local)
                    elif par.mt == 1:  # gaussian masking
                        print "not set up for gaussian masking yet"

                        # if appropriate, fit
                    if time_tr[j][ch, addfr[j]] > par.fit_thr:
                        # use least squares optimization
                        # loc = np.ravel(frame[cury-par.fit_box:cury+par.fit_box+1,curx-par.fit_box:curx+par.fit_box+1])
                        loc = frame[
                            cury - par.fit_box : cury + par.fit_box + 1, curx - par.fit_box : curx + par.fit_box + 1
                        ]
                        [yguess, xguess] = np.unravel_index(loc.argmax(), loc.shape)
                        p0 = np.array(
                            [float(fr_bkgd[cury, curx]), float(loc[yguess, xguess]), xguess, yguess, 1.1, 1.1]
                        )  # a smarter initial guess
                        loc = np.ravel(loc)
                        # p0 = np.array([float(fr_bkgd[cury,curx]), float(frame[cury,curx]), par.fit_box,par.fit_box,1.0,1.0]) #initial guess

                        [p1, cov_x, infodict, mesg, success] = optimize.leastsq(
                            errfunc, p0, args=(fitxval1D, fityval1D, loc), full_output=1, xtol=par.fitxtol
                        )

                        # if fit successful and center is within box, store result
                        if (
                            success > 0
                            and success < 5
                            and p1[2] > 0
                            and p1[2] < (2 * par.fit_box + 1)
                            and p1[3] > 0
                            and p1[3] < (2 * par.fit_box + 1)
                        ):
                            xfitpos = p1[2] + curx - par.fit_box
                            yfitpos = p1[3] + cury - par.fit_box
                            if ch == 1:  # map right channel onto the left.
                                xfitpos -= par.dimx / 2  # mapping takes relative coordinate - within own channel.
                                [xfitpos, yfitpos] = mapcoords.map_coords(xfitpos, yfitpos, Pr2l, Qr2l)
                            crds_tr[j][ch, addfr[j], :] = [
                                xfitpos,
                                yfitpos,
                                abs(p1[4]),
                                abs(p1[5]),
                                1.0,
                                0.0,
                                0.0,
                                p1[1],
                            ]
                            # for coordinates (x,y, x_stdev, y_stdev, fitting flag, quality metric, tilt angle, fit height)
                            # fixme: not using any metric of quality.
                addfr[j] = addfr[j] + 1
        if i % par.outputpartial == 0 and i != 0:
            savetrdir.save_trdir(filename, par, peaks, time_tr, crds_tr, 0)
    fileptr.close()

    # print "saving data at" + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    if par.outtype == 0:
        print "not set up to save .traces file"
    elif par.outtype == 1:
        savetrdir.save_trdir(filename, par, peaks, time_tr, crds_tr, 1)

        # output xml file with actual settings in par.
    outxml = filename + "apdaxOUT.xml"
    writexml.write_xml(par, outxml, "apdax", filename, [])

    print "apdax done at " + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " on file: " + filename