py4sci

Source code for sloth.image_processing

# -*- coding: utf-8 -*-
"""
Created on Wed Dec 14 09:47:23 2011
  This file is part of SLOTH - stick/like object tracking in high-resolution.
    Copyright (C) 2012 Monika Kauer

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
@author: monika
"""

import numpy as np
import vectorial
from scipy import optimize
import matplotlib.pylab as pylab
import array

#==============================================================================
# Class to abstract from file formats
#==============================================================================
[docs]class MyImageFile: "Abstracts from file format like nd2 or tiff" def __init__(self, filename, dual_color, shift=1): if filename.endswith(".nd2"): import read_nd2 self.raw_image = read_nd2.Nd2File(open(filename)) self.dual_color = dual_color self.number_frames=self.raw_image.attr["uiSequenceCount"] self.shape=(self.raw_image.attr['uiHeight'],self.raw_image.attr['uiWidth']) self.fmt="nd2" self.shift=shift elif filename.lower().endswith(".tif"): import tifffile self.raw_image = tifffile.TIFFfile(filename) self.number_frames = len(self.raw_image)-1 self.shape = self.raw_image[0].asarray().shape self.fmt = "tif" self.shift=0 else: raise Exception("unkown filetype %s"%filename)
[docs] def get_frame(self, number): if self.fmt=="nd2": frame = self.raw_image.get_image(number) red=np.ndarray(self.shape,dtype="H", buffer=frame[1]) if not self.dual_color: return red green=np.ndarray(self.shape, dtype='H', buffer=frame[2]) return red + green*int(self.shift) if self.fmt=="tif": return self.raw_image[number].asarray() #============================================================================== # Major functions of tracking program #==============================================================================
[docs]def vec_intensity(image, pos, direction): intensity=0.0 l = abs(direction) for j in range(int(l)): newp = pos + (direction/l)*j intensity += image[int(round(newp.y))][int(round(newp.x))] return intensity
[docs]def vec_intensity2(linear_image, width, pos, direction): """faster intensity calculation""" l=abs(direction) return sum(end_profile2(linear_image,width, pos, direction/l, l)) #============================================================================== # Fitting routines for Fermi-Tip # XXX get better initial values #============================================================================== # Fits Fermi Function to Tip profile and returns Fit params and Coord at Half Maximum #==============================================================================
[docs]def error_fit(profile,p0): coords=np.array(range(len(profile))) profile=np.array(profile) #Fit to Fermifunction fitfunc = lambda p, a: p[0]*(1./(np.exp(a*p[1]-p[2])+1))+p[3] # Target function errfunc = lambda p, a, b: (fitfunc(p, a)-b)# Distance to the target p1,cov,infodict,mesg,ier = optimize.leastsq(errfunc, p0[:], args=(coords, profile),full_output=True)#least square fit ss_err=(infodict['fvec']**2).sum() ss_tot=((profile-profile.mean())**2).sum() rsquared=1-(ss_err/ss_tot) fit = fitfunc(p1, np.array(coords)) #pylab.figure(8) #pylab.hold(True) #pylab.plot(profile,'k.',fit,'-', color='#0B2A51') #Find Half Maximum y=max(fit)-(max(fit)-min(fit))/2. if p1[0]/(y-p1[3])-1.>0: x_fwhm=(np.log(p1[0]/(y-p1[3])-1.)+p1[2])/p1[1] else: x_fwhm=0 slope=-p1[1]/p1[0]*(p1[0]-y+p1[3])*(y-p1[3]) #pylab.plot(x_fwhm,y,"kx", markersize=10) #pylab.hold(False) if np.isinf(x_fwhm) or np.iscomplex(x_fwhm) or np.isnan(x_fwhm): return p1,rsquared,fit,0,y,slope else: return p1,rsquared,fit, x_fwhm,y,slope #============================================================================== # Display Functions #==============================================================================
[docs]def ShowCoordinates(image, directions): "Plot coordinates ontop of image with matplotlib." fig=pylab.imshow(image, cmap="gray") for i in range(len(directions)): k = directions[i] end = k[0] + k[1] mp = k[0] + k[1]*0.5 pylab.hold(True) pylab.plot(k[0].x,k[0].y,'r+') pylab.plot(end.x,end.y,'r*') pylab.text(mp.x,mp.y, '%d' %i, color="w") pylab.hold(False)
[docs]def RotatingIntensity(image, linear_image, axis,direction,alpha_min, alpha_max, step, center=True): '''Rotate microtubule to maximum intensity. If center is False, the rotation axis is the start point.''' maxv = 0 maxstart=None maxdir=None l=abs(direction) for alpha in np.arange(alpha_min,alpha_max,step): direction2=direction.rotate(alpha) if center: start = axis + direction2 * -0.5 else: start = axis try: v = vec_intensity2(linear_image, image.shape[1], start, direction2)/l if v > maxv: maxv = v maxdir = direction2 maxstart = start except IndexError: pass return maxstart,maxdir,maxv
[docs]def end_profile(image, start, direction): "Go through image from one endpoint, and record intensity profile." pos = start + direction try: i = image[int(round(pos.y))][int(round(pos.x))] except IndexError: i = 0 return i, pos
[docs]def end_profile2(linear_image,width, start, direction, len_scan): "Go through image from one endpoint, and record intensity profile." intensity=[] for j in range(int(np.ceil(len_scan))): newp = start + (direction)*j try: intensity.append(linear_image[int(round(newp.y))*width + int(round(newp.x))]) except IndexError: intensity.append(0) return intensity
[docs]def tracker_data(filename): """reads position data (x,y) in file. Data needs to be separated by tab""" pos=list() length=list() if filename==None or len(filename)==0: return None with open(filename, 'r') as f: dialect = csv.Sniffer().sniff(f.read(1024)) f.seek(0) data=csv.reader(f,dialect) for k in data: pos.append([float(k[0]),float(k[1])]) return pos