Bowhead¶
Welcome to the homepage of Bowhead, a cell velocity Python package. This package provides tools to analyze cell velocity from time series of wound healing experiments.
The accompanying paper is found at PLOS.
Image data presented in that paper you can download here.
The source code is available at GitLab.
Getting Started¶
First import bowhead
and Pillow
>>> import bowhead, PIL
To detect the wound on an image file called ‘wound_t08.jpg’
call bowhead.detect()
>>> threshold = .25 # 25% of cell confluency
>>> my_wound = bowhead.detect('img/wound_t08.jpg', thresh=threshold)
The result is a dictionary with values from the detection such as area and perimeter and their variances.
>>> my_wound['area']
55551.0
>>> my_wound['area_variance']
20267858.0
>>> my_wound['center_of_mass']
(294.0, 286.0)
To visualize the detected wound on the original image use Matplotlib. The perimeter coordinates are saved in the wound dictionary with the keyword ‘edge’
>>> from matplotlib.pyplot import *
>>> gray() # keep image plots gray scale
>>> imshow(PIL.Image.open('img/wound_t08.jpg'))
<matplotlib.image.AxesImage object at ...
>>> y, x = my_wound['edge']
>>> plot(x, y, color='#127ba6')
[<matplotlib.lines.Line2D object at ...
>>> savefig('round_wound')
>>> close()

Time Series¶
In order to analyze a time series experiment with multiple images a
list of wound detection dictionaries is needed. Call
bowhead.detect()
with paths and corresponding time points
>>> from glob import glob
>>> paths = sorted(glob('img/*.png')) # time sorted images
>>> time = range(len(paths))
>>> my_series = bowhead.detect(paths, time, sigma=40)
This call detects wounds on all images and assign an experimental time point to each of them. By plotting static frames per time point allows for creating a movie of the detection (e.g. with imageio)

The returned list my_series
can be used to fit
a velocity model (bowhead.Model
) with the function
bowhead.Model.fit()
>>> model = bowhead.Model()
>>> model.fit(my_series)
<bowhead.velocity.Model object at ...
When a model is fitted it can be used to predict cell velocity t
desired time points with bowhead.Model.predict()
. Note that
these do not have to be the original data time points
>>> velocity, std = model.predict(time, return_std=True)
When return_std=True
is passed to predict
, the
standard deviation of the velocity is also returned. Velocity
with errors can be plotted like so
>>> errorbar(time, velocity, std, c='#127ba6')
<ErrorbarContainer object of ...
>>> xlabel('hours')
Text(0.5, 0, 'hours')
>>> ylabel('pixels / hours')
Text(0, 0.5, 'pixels / hours')
>>> savefig('velocity')
>>> close()

Different ways to detect images¶
There are three different ways to give images
to bowhead.detect()
. Parse a file path to the image
>>> path = 'img/wound_t08.jpg'
>>> my_wound = bowhead.detect(path)
or a PIL
image
>>> import PIL.Image
>>> pil_image = PIL.Image.open(path)
>>> my_wound = bowhead.detect(pil_image)
or even a numpy.ndarray
>>> import numpy
>>> array_image = numpy.asarray(pil_image)
>>> my_wound = bowhead.detect(array_image)
For all of the cases above a single image or a list
of images can be used as input to bowhead.detect()
.
Bright-field and similar image types¶
Some imaging techniques, such a bright-field or phase contrast, violates Bowhead’s assumption that cells are light and wounds are dark respectively. To overcome this the image gradient can be used instead of pixel intensity directly. Bowhead deploys a Scharr edge filter for this purpose. Users can use the utility function before analysis
>>> # sample image from 'TScratch' by CSElab
>>> # www.cse-lab.ethz.ch/images/software/tscratch_sampledata.zip
>>> bright_path = 'tscratch_example_image.jpg'
>>> bright = PIL.Image.open(bright_path)
>>> grad = bowhead.image_gradient(bright) # (or use file path)
>>> fig, axes = subplots(ncols=2, figsize=(12,8))
>>> original = axes[0].imshow(bright) # bright field image
>>> gradient = axes[1].imshow(grad) # gradient map
>>> savefig('transformed', bbox_inches='tight')
>>> close()

Or, for convenience, an argument can be given directly to
bowhead.detect()
to achieve the gradient transform indirectly
>>> my_wound = bowhead.detect(bright_path, use_gradient=True)
- To see how the detection performs on the bright field image
>>> imshow(bright) <matplotlib.image.AxesImage object at ... >>> y, x = my_wound['edge'] >>> plot(x, y, color='#127ba6') [<matplotlib.lines.Line2D object at ... >>> savefig('bright_field_wound') >>> close()

Contour tracing method¶
By default Bowhead uses the Marching Squares algorithm with linear interpolation to establish the perimeter coordinate chain. This gives a perimeter with round corners on the pixel level. As an alternative a chain code implementation is available. Chain code saves the discrete pixel values and gives a rugged perimeter. Chain code runs slightly faster than Marching Squares. The perimeter length varies slightly between the two methods.
>>> # use keyword argument to set the method
>>> path = 'img/wound_t08.jpg'
>>> marching_wound = bowhead.detect(path, method='marching')
>>> chain_wound = bowhead.detect(path, method='chain')
Package Reference¶
Here is a list of the available classes and functions in the package. The Index gives an alternative alphabetical listing of the package content.
-
class
bowhead.
Model
(area_kwargs=None, perimeter_kwargs=None)[source]¶ Wound velocity model.
The model is based on Gaussian Process Regression (GPR) and numerical differentiation. The GPR uses scikit-learn GPR class
sklearn.gaussian_process.GaussianProcessRegressor
.Parameters: - area_kwargs (dictionary) – The keyword arguments to the area GPR model.
- perimeter_kwargs (dictionary) – The keyword arguments to the perimeter GPR model.
Variables: - area (area model) – Instances of GaussianProcessRegressor from scikit-learn.
- perimeter (perimeter model) – Instances of GaussianProcessRegressor from scikit-learn.
- time (sequence) – Sequence of the input time points. Defined when fitted.
Notes
The keyword argument
kernel
is specifying the covariance function of the GPR models handling the area and perimeter. The default kernel is a sum of a linear and squared dotproduct kernel. See scikit-learn for the different kernels that can be used. Note that the kernel hyperparameters are optimized during fitting.-
fit
(wounds)[source]¶ Fitting the velocity model to wound data.
Parameters: wounds (sequence of dictionaries) – A sequence of wound dictionaries representing an experimental time series of the wound healing assay, as returned by detect()
. The area, perimeter and time point of each wound is used to fit the overall velocity model. All these attributes should be positive scalars.Returns: self – The velocity model in a fitted state. Return type: Model
-
predict
(time, dt=0.1, return_std=False)[source]¶ Predicting a velocity curve of a wound healing experiment.
In addition to the mean of the predictive distribution, also its standard deviation (return_std=True) can be requested.
Parameters: - time (sequence) – Desired time points of the velocity prediction. Should be positive.
- dt (scalar) – The time interval for calculating velocity.
- return_std (bool) – Whether to include the standard deviation of the prediction or not.
Returns: velocity, [vel_std] – Velocity and (optionally) it’s standard deviation. Returned either one array or (if return_std=True) as a tuple (velocity, vel_std).
Return type: 1d arrays
-
bowhead.
detect
(images, time=None, sigma=25, thresh=0.4, err=0.05, radius=None, use_gradient=False, method='marching')[source]¶ Detect wound on a image with uncertainty.
Parameters: - images (sequence of [file paths | numpy.ndarray | PIL.Image]) – Images to detect wound(s) from. A single image path, array, or PIL image can be passed outside a sequence.
- time (sequence) – The time points of the images (same order as images).
- sigma (scalar) – The standard deviation of the image smoothing. This should be roughly the same as the distance (in pixels) between cells at confluency.
- thresh (scalar) – Threshold factor to calculate wound boundary. Between zero and one.
- err (scalar) – Standard error of the threshold value to calculate uncertainty of the detection.
- radius (scalar, default is None) – If radius is not None and more than 2 images parsed
the algorithm uses the mean center of mass of the two first wounds
to define a circular zone of exclusion with radius
radius
in pixels. Subsequent wound candidates have to been inside this zone to be considered valid wounds. - use_gradient (boolean, default is False) – Whether to preprocess the images with a Scharr edge filter. This is useful to better detect wounds on bright-field images and other types where cells appear as a both light and dark in the microscope image.
- method (string, default is 'marching') – Which method to use for contour tracing. Choose between ‘marching’ for the marching square algorithm or ‘chain’ for chain code tracing. Chain code is fastest. The perimeter found differs slightly because Marching square finds interpolated round edges at pixel corners where chain code result in a standard pixel chain.
Returns: wound(s) – Returns one dictionary (or a list of several) with the detected wound values
- area
- perimeter (without parts that touch image border)
- area and perimeter variances
- center of mass
- time
- edge (tuple of wound edge x and y coordinates)
- filename, (image file path if loaded from disk)
- image area
Returns
None
, for wounds that can not be detected.Return type: dictionary or a list of dictionaries
Notes
All image types and bit depth supported by Pillow can be used as input. If the images contain more than one color channel the sum of all channels will be used.
-
bowhead.
sort_and_cutoff
(wounds, min_area=0.05, abs_area=False)[source]¶ Sort by time and cutoff based on minimum area.
Utillity function to sort wounds by time and filter out wounds by minimum area (pixel^2).
Parameters: - wounds (sequence of dictionaries) – A sequence of wound dictionaries representing an experimental
time series of the wound healing assay, as returned
by
detect()
. - min_area (float) – Percentage (or absolute) image size to consider a closed wound area. After this limit is hit the following time points will be excluded from the wound list.
- abs_area (bool) – Wether to use absolute area.
Returns: wounds – A wound list sorted by time point of the wounds. The following will remove wounds from the returned list:
- wound area smaller than
min_area*image area
orabs_area
- wounds with later time point than the first removed
- None valued wounds
Return type: list of dictionaries
- wounds (sequence of dictionaries) – A sequence of wound dictionaries representing an experimental
time series of the wound healing assay, as returned
by
-
bowhead.
image_gradient
(image)[source]¶ Preprocess bright-field or similar type images.
Applys a Scharr filter and normalizes the output gradient image.
Parameters: image ([file path | numpy.ndarray | PIL.Image]) – A color or grayscale image as file path numpy array or PIL image. Returns: image – A normalized image representing the gradient (edge magnitude) of the input image. Return type: PIL.Image (8 bit image mode ‘L’)