.. toctree:: 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 `_. Installation ------------ The package is installed via pip for python3 :: $ pip3 install bowhead Getting Started --------------- First import ``bowhead`` and `Pillow `_ >>> import bowhead, PIL To detect the wound on an image file called 'wound_t08.jpg' call :func:`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')) >> y, x = my_wound['edge'] >>> plot(x, y, color='#127ba6') [>> savefig('round_wound') >>> close() .. image:: round_wound.png Time Series ------------------ In order to analyze a time series experiment with multiple images a list of wound detection dictionaries is needed. Call :func:`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 `_) .. image:: wound.gif The returned list ``my_series`` can be used to fit a velocity model (:obj:`bowhead.Model`) with the function :func:`bowhead.Model.fit` >>> model = bowhead.Model() >>> model.fit(my_series) >> 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') >> xlabel('hours') Text(0.5, 0, 'hours') >>> ylabel('pixels / hours') Text(0, 0.5, 'pixels / hours') >>> savefig('velocity') >>> close() .. image:: velocity.png Different ways to detect images ------------------------------- There are three different ways to give images to :func:`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 :func:`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() .. image:: transformed.png Or, for convenience, an argument can be given directly to :func:`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) >> y, x = my_wound['edge'] >>> plot(x, y, color='#127ba6') [>> savefig('bright_field_wound') >>> close() .. image:: bright_field_wound.png 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 :ref:`genindex` gives an alternative alphabetical listing of the package content. .. automodule:: bowhead :members: