Browse Source

Documentation update

master
Carlos Reding 1 year ago
parent
commit
32375a308f
2 changed files with 200 additions and 32 deletions
  1. 154
    18
      puppeteer/_dataparser/plate_reader.py
  2. 46
    14
      puppeteer/_treeparser.py

+ 154
- 18
puppeteer/_dataparser/plate_reader.py View File

@@ -8,9 +8,30 @@ import numpy as np
def classify_plate(wells):
"""
This function generates an array of reference, where the wells'
labels are arranged accordingly to the image ---well 1 being A1
top-left corner of a microtitre plate and increasing towards the
right per row.
labels are arranged accordingly to the image.
.. note::
Well *A1* is located in the top-left corner of the image, increasing
towards the right.
.. note::
If photographic data is processed externally (i.e. user's laptop),
the graphical user interface flips this arrangement: well *A1* is
shown in the bottom-left corner of the image, and increases towards
the right.
Parameters
----------
wells : int
Number of wells in the microtitre plate.
Returns
-------
reference_plate : ndarray
*MxN* matrix where *M* is the number of rows expected for the
microtitre plate, and *N* the expected number of columns. Values
in the matrix range from *0* to *wells*, *0* corresponding to well
*A1*.
"""
if len(wells) == 6:
reference_plate = np.reshape(np.arange(0, 6), [2, 3])
@@ -29,21 +50,103 @@ def classify_plate(wells):


def crop_img(original_img, img_limits):
""" Crops image `original_img' to reduce file size and optimise
overall performance. """
"""
Crops image `original_img' to reduce file size and optimise
overall performance.
Parameters
----------
original_img : ndarray
Photographic data arranged as a *MxNxI* matrix where *M* is the
number of pixels in the *x* axis, *N* the number of pixels in the
*y* axis, and *I* the number of channels.
.. note::
Typically photographic data stored as JPEG will contain *3*
channels corresponding to red (R), green (G), and blue (B)
data.
img_limits : tuple
Image size in pixels. The tuple contains *(x_min, x_max, y_min,
y_max)* coordinates. Used to batch-crop photographic data and
improve data processing performance in case the analysis is
performed locally in the light modulator.
Returns
-------
cropped_img : ndarray
Photographic data arranged as a *MxNxI* matrix where *M* is the
number of pixels in the *x* axis, *N* the number of pixels in the
*y* axis, and *I* the number of channels. _This array has been
reduced in size to include well photographic data only_.
"""
x_min, x_max, y_min, y_max = img_limits
return original_img[y_min:y_max, x_min:x_max, :]


class PlateParser:
""" Docstring. """
"""
Collect biological data from photographic data.
Parameters
----------
dir_info : structure
Structure object that contains directory information: root
directory, protocol directory, data directory, etc.
wells : int
Number of wells in the microtitre plate.
flt : string
Filter used. Options are *Filter_1*, *Filter_2*, *Filter_3*,
and *No_Filter*.
col_labels : tuple
Column labels. A microtitre plate con tains _m_ columns by _n_
rows. Each label from this tuple is an *int* that notes the
_column_ of the microtitre plate that well data belongs to.
row_labels : tuple
Row labels. A microtitre plate con tains _m_ columns by _n_
rows. Each label from this tuple is an *int* that notes the
_row_ of the microtitre plate that well data belongs to.
img_limits : tuple
Image size in pixels. The tuple contains *(x_min, x_max, y_min,
y_max)* coordinates. Used to batch-crop photographic data and
improve data processing performance in case the analysis is
performed locally in the light modulator.
time : float
Time since the initiation of the protocol, in seconds.
debug : bool, optional
If *True*, the light modulator will save the images at every
transformation step to inspect the correct detection of wells'
location. Defaults to *False*.
"""
def _sort_wells(self, row_label, column_label):
""" Sort wells from 1-n based on kmeans labels. """
""" Private method. Sort wells from 1-n based on kmeans labels. """
return self._reference_plate[row_label][column_label]

def _ppw(self, mock_img, wells, channels, radius):
""" Partially process first image (any, really) to calculate
the pixel density per well. """
"""
Private method. Partially process first image to calculate the
number of pixel per well.
Parameters
----------
mock_img : ndarray
Zero matrix used to calculate the location of each pixel within
a given well.
wells : callable
*cv2* object resulting from the maximally stable extremal
regions (MSER) extractor.
channels : int
Number of channels in photographic data. **NOTE:** while JPEG
images do contain 3 channels for red, green, and blue, other
formats may include a 4th channel, alpha, to encode
transparency.
radius : int
Radius set for each well, in pixels.
Returns
-------
ppw : int
Number of pixels detected within a well.
"""
x, y = wells[0].pt
cv2.circle(mock_img, (int(x), int(y)), np.uint8(radius*0.55),
(255, 255, 255), cv2.FILLED)
@@ -54,9 +157,40 @@ class PlateParser:
def _create_tensor(self, img_list, img_data_path, img_filename, wells,
radius, img_limits):
"""
Partially process first image (any, really) to create a container
for ALL the data (all images). This container is later used to store
ALL the data of EACH well in one single file.
Private method. Partially process first image to create a container
(_tensor_) to store ALL numeric data within all wells.
Parameters
----------
img_list : list
List of files generated during the run. **NOTE: filenames
only.** Used to estimate the number of light intensities used.
img_data_path : string
Absolute path where photographic data is stored.
img_filename : string
File to be used to generate the tensor. It will typically be one
of those listed in *img_list*.
wells : callable
*cv2* object resulting from the maximally stable extremal
regions (MSER) extractor.
radius : int
Radius set for each well, in pixels.
img_limits : tuple
Image size in pixels. The tuple contains *(x_min, x_max, y_min,
y_max)* coordinates. Used to batch-crop photographic data and
improve data processing performance in case the analysis is
performed locally in the light modulator.
Returns
-------
ppw : int
Number of pixels detected within a well.
raw_data : ndarray
Fifth-dimmensional array with structure *MxNxIxJxK*, where *M*
is the number of light intensities used, *N* the number of
wells, *I* the number of channels in the photographic data, *J* the
number of pixels per well, and *K* a matrix containing the raw
(numeric) data.
"""
img = cv2.imread(img_data_path + img_filename, cv2.IMREAD_COLOR)
img_c = crop_img(img, img_limits) # Optimise perf.
@@ -73,9 +207,10 @@ class PlateParser:
blanks_list, radius, pixels_per_well, row_labels,
col_labels, debug):
"""
This routine exploits the presence of multiple cores to accelerate
image processing. Each file in `img_list' gets blank corrected and
image data is stored using `wells' cached coordinates.
Private method. This routine exploits the presence of multiple cores
to accelerate image processing. Each file in `img_list' gets blank
corrected and numeric data is extracted using wells' cached
coordinates.
"""
img_filename = img_list[i]
ref_image = blanks_list[i]
@@ -126,8 +261,9 @@ class PlateParser:
def _read_wells(self, dir_info, wells, flt, row_labels,
col_labels, img_limits, time, debug):
"""
Retrieve data from images using precalculated `wells' coordinates,
and cropped using precalculated `img_limits'.
Private method. Extract numerical data from images using
precalculated `wells' coordinates, and cropped using precalculated
`img_limits'.
"""
img_data_path = dir_info.root_path + dir_info.protocol_path +\
dir_info.img_data_path + flt + "/"
@@ -168,7 +304,7 @@ class PlateParser:

def __init__(self, dir_info, wells, flt, row_labels,
col_labels, img_limits, time, debug=False):
""" Use well location to retrieve data distribution in each well. """
""" Initialise the class _PlateParser_. """
# Get the data!
self._reference_plate = classify_plate(wells)
self._read_wells(dir_info, wells, flt, row_labels,

+ 46
- 14
puppeteer/_treeparser.py View File

@@ -5,7 +5,10 @@ import shutil as sh


def ask_user():
""" Asks user how to proceed. """
"""
Asks user how to proceed. Only useful if the light modulator is run
from a command-line interface (CLI) interactively.
"""
ans = input("Calibration data seems to exist, calibrate again? (Y/n): ")
return ans.lower()

@@ -15,20 +18,45 @@ class GenerateTree:
Create folder structure for reference images or experimental data. The
root directory contains a file with the temperature record and the
subdirectories `img/' and `src/', which store image data per filter
and raw numeric data respectively. Defaults to false (directory
structure for experimental data).
and raw numeric data respectively. The root directory will be named
after the current date by default.
Parameters
----------
calibrate : bool
Flat to create folder structore _also_ for calibration data.
Defaults to *False*.
filters : list
List of filters used for the protocol. Options are *Filter_1*,
*Filter_2*, *Filter_3*, and *No_Filter*.
label : string, optional
Name of the directory.
annotations : string
Further comments to be includede as part of the directory's name.
"""
def _calibration_tree(self, filters):
""" Check whether folder tree exists. If not, create it. """
"""
Private method. Check whether folder tree exists. If not, create it.
"""
for flt in filters:
if not os.path.exists(self.root_path + self.ref_path + flt + "/"):
os.makedirs(self.root_path + self.ref_path + flt + "/")

def create_tree(self, label, notes, filter_set):
"""
Create the directory structure to store experimental data based on
a series of parameters such as date of experiment, `label', `notes'
(optional), and `filter_set'.
Create the directory structure where photographic data will be
stored.
Parameters
----------
label : string
Name of the directory.
notes : string
Further comments to be includede as part of the directory's
name.
filter_set : list
List of filters used for the protocol. Options are *Filter_1*,
*Filter_2*, *Filter_3*, and *No_Filter*.
"""
# Date of experiment running...
date = t.localtime()
@@ -56,9 +84,17 @@ class GenerateTree:

def create_references_subfolders(self, filter_set):
"""
.. note:: To use this routine, ensure there is no microtitre plate
in the light modulator.
Create folder where reference images for blank correction are
stored. These images **do not include a microplate** and are taken
at all light intensities.
stored.
Parameters
----------
filter_set : list
List of filters used for the protocol. Options are *Filter_1*,
*Filter_2*, *Filter_3*, and *No_Filter*.
"""
self.ref_path = '.refs/' # This folder will be hidden in *NIX systems.
# Create folders if need be...
@@ -94,11 +130,7 @@ class GenerateTree:
return 0

def __init__(self, calibrate=False, **kwargs):
"""
Create basic directory structure and export it to help generate
the metadata file. If calibrate is False, the parameter `label'
is required.
"""
""" Initialise class _GenerateTree_. """
# Set directory structure
self._data_path = '/data/'
# root Set folder where all data is stored

Loading…
Cancel
Save