topostats.grainstats#

Contains class for calculating the statistics of grains - 2d raster images.

Attributes#

Classes#

GrainStats

Class for calculating grain stats.

Module Contents#

topostats.grainstats.LOGGER#
topostats.grainstats.GRAIN_STATS_COLUMNS = ['molecule_number', 'centre_x', 'centre_y', 'radius_min', 'radius_max', 'radius_mean',...#
class topostats.grainstats.GrainStats(data: numpy.ndarray, labelled_data: numpy.ndarray, pixel_to_nanometre_scaling: float, direction: str, base_output_dir: str | pathlib.Path, image_name: str = None, edge_detection_method: str = 'binary_erosion', cropped_size: float = -1, plot_opts: dict = None, metre_scaling_factor: float = 1e-09)[source]#

Class for calculating grain stats.

data#
labelled_data#
pixel_to_nanometre_scaling#
direction#
base_output_dir#
start_point = None#
image_name#
edge_detection_method#
cropped_size#
plot_opts#
metre_scaling_factor#
static get_angle(point_1: tuple, point_2: tuple) float[source]#

Calculate the angle in radians between two points.

Parameters:
  • point1 (tuple) – Coordinate vectors for the first point to find the angle between.

  • point2 (tuple) – Coordinate vectors for the second point to find the angle between.

Returns:

angle – The angle in radians between the two input vectors.

Return type:

float

static is_clockwise(p_1: tuple, p_2: tuple, p_3: tuple) bool[source]#

Determine if three points make a clockwise or counter-clockwise turn.

Parameters:
  • p_1 (tuple) – First point to be used to calculate turn.

  • p_2 (tuple) – Second point to be used to calculate turn.

  • p_3 (tuple) – Third point to be used to calculate turn.

Returns:

Indicator of whether turn is clockwise.

Return type:

boolean

calculate_stats() dict[source]#

Calculate the stats of grains in the labelled image.

Returns:

  • grainstats (pd.DataFrame) – A DataFrame containing all the grain stats that have been calculated for the labelled image.

  • grains_plot_data – A list of dictionaries containing grain data to be plotted.

static calculate_points(grain_mask: numpy.ndarray)[source]#

Convert a 2D boolean array to a list of co-ordinates.

Parameters:

grain_mask (np.ndarray) – A 2D numpy array image of a grain. Data in the array must be boolean.

Returns:

  • points (list)

  • A python list containing the coordinates of the pixels in the grain.

static calculate_edges(grain_mask: numpy.ndarray, edge_detection_method: str)[source]#

Convert 2D boolean array to list of the coordinates of the edges of the grain.

Parameters:
  • grain_mask (np.ndarray) – A 2D numpy array image of a grain. Data in the array must be boolean.

  • edge_detection_method (str) – Method used for detecting the edges of grain masks before calculating statistics on them. Do not change unless you know exactly what this is doing. Options: “binary_erosion”, “canny”.

Returns:

edges – List containing the coordinates of the edges of the grain.

Return type:

list

calculate_radius_stats(edges: list, points: list) tuple[source]#

Calculate the radius of grains.

The radius in this context is the distance from the centroid to points on the edge of the grain.

Parameters:
  • edges (list) – A 2D python list containing the coordinates of the edges of a grain.

  • points (list) – A 2D python list containing the coordinates of the points in a grain.

Returns:

A tuple of the minimum, maximum, mean and median radius of the grain

Return type:

Tuple[float]

static _calculate_centroid(points: numpy.array) tuple[source]#

Calculate the centroid of a bounding box.

Parameters:

points (list) – A 2D python list containing the co-ordinates of the points in a grain.

Returns:

The co-ordinates of the centroid.

Return type:

tuple

static _calculate_displacement(edges: numpy.array, centroid: tuple) numpy.array[source]#

Calculate the displacement between the centroid and edges.

static _calculate_radius(displacements) numpy.array[source]#

Calculate the radius of each point from the centroid.

Parameters:
  • displacements (List[list])

  • Retrurns

  • --------

  • np.array

convex_hull(edges: list, base_output_dir: pathlib.Path, debug: bool = False)[source]#

Calculate a grain’s convex hull.

Based off of the Graham Scan algorithm and should ideally scale in time with O(nlog(n)).

Parameters:
  • edges (list) – A python list contianing the coordinates of the edges of the grain.

  • base_output_dir (Union[str, Path]) – Directory to save output to.

  • debug (bool) – Default false. If true, debug information will be displayed to the terminal and plots for the convex hulls and edges will be saved.

Returns:

  • hull (list) – Coordinates of the points in the hull.

  • hull_indices (list) – The hull points indices inside the edges list. In other words, this provides a way to find the points from the hull inside the edges list that was passed.

  • simplices (list) – List of tuples, each tuple representing a simplex of the convex hull. These simplices are sorted such that they follow each other in counterclockwise order.

calculate_squared_distance(point_2: tuple, point_1: tuple = None) float[source]#

Calculate the squared distance between two points.

Used for distance sorting purposes and therefore does not perform a square root in the interests of efficiency.

Parameters:
  • point_2 (tuple) – The point to find the squared distance to.

  • point_1 (tuple) – Optional - defaults to the starting point defined in the graham_scan() function. The point to find the

  • from. (squared distance)

Returns:

distance_squared – The squared distance between the two points.

Return type:

float

sort_points(points: list) list[source]#

Sort points in counter-clockwise order of angle made with the starting point.

Parameters:

points (list) – A python list of the coordinates to sort.

Returns:

sorted_points – A python list of sorted points.

Return type:

list

get_start_point(edges) None[source]#

Determine the index of the bottom most point of the hull when sorted by x-position.

Parameters:

edges (np.array)

graham_scan(edges: list)[source]#

Construct the convex hull using the Graham Scan algorithm.

Ideally this algorithm will take O( n * log(n) ) time.

Parameters:

edges (list) – A python list of coordinates that make up the edges of the grain.

Returns:

  • hull (list) – A list containing coordinates of the points in the hull.

  • hull_indices (list) – A list containing the hull points indices inside the edges list. In other words, this provides a way to find the points from the hull inside the edges list that was passed.

  • simplices (list) – A list of tuples, each tuple representing a simplex of the convex hull. These simplices are sorted such that they follow each other in counterclockwise order.

static plot(edges: list, convex_hull: list = None, file_path: pathlib.Path = None) None[source]#

Plot and save the coordinates of the edges in the grain and optionally the hull.

Parameters:
  • coordinates (list) – A list of points to be plotted.

  • convex_hull (list) – Optional argument. A list of points that form the convex hull. Will be plotted with the coordinates if provided.

  • file_path (Path) – Path of the file to save the plot as.

calculate_aspect_ratio(edges: list, hull_simplices: numpy.ndarray, path: pathlib.Path, debug: bool = False) tuple[source]#

Calculate the width, length and aspect ratio of the smallest bounding rectangle of a grain.

Parameters:
  • edges (list) – A python list of coordinates of the edge of the grain.

  • hull_simplices (np.ndarray) – A 2D numpy array of simplices that the hull is comprised of.

  • path (Path) – Path to the save folder for the grain.

  • debug (bool) – If true, various plots will be saved for diagnostic purposes.

Returns:

  • smallest_bounding_width (float) – The width in pixels (not nanometres), of the smallest bounding rectangle for the grain.

  • smallest_bounding_length (float) – The length in pixels (not nanometres), of the smallest bounding rectangle for the grain.

  • aspect_ratio (float) – The width divided by the length of the smallest bounding rectangle for the grain. It will always be greater or equal to 1.

static find_cartesian_extremes(rotated_points: numpy.ndarray) dict[source]#

Find the limits of x and y of rotated points.

Parameters:

rotated_points (np.ndarray) – 2-D array of rotated points.

Returns:

Dictionary of the x and y min and max.__annotations__

Return type:

Dict

static get_shift(coords: numpy.ndarray, shape: numpy.ndarray) int[source]#

Obtain the coordinate shift to reflect the cropped image box for molecules near the edges of the image.

Parameters:
  • coords (np.ndarray) – Value representing integer coordinates which may be outside of the image.

  • shape (np.ndarray) – Array of the shape of an image.

Returns:

Max value of the shift to reflect the croped region so it stays within the image.

Return type:

np.int64

get_cropped_region(image: numpy.ndarray, length: int, centre: numpy.ndarray) numpy.ndarray[source]#

Crops the image with respect to a given pixel length around the centre coordinates.

Parameters:
  • image (np.ndarray) – The image array.

  • length (int) – The length (in pixels) of the resultant cropped image.

  • centre (np.ndarray) – The centre of the object to crop.

Returns:

Cropped array of the image.

Return type:

np.ndarray

static get_triangle_height(base_point_1: numpy.array, base_point_2: numpy.array, top_point: numpy.array) float[source]#

Return the height of a triangle defined by the input point vectors.

Parameters:
  • base_point_1 (np.ndarray) – a base point of the triangle, eg: [5, 3].

  • base_point_2 (np.ndarray) – a base point of the triangle, eg: [8, 3].

  • top_point (np.ndarray) – the top point of the triangle, defining the height from the line between the two base points, eg: [6,10].

Returns:

  • Float – The height of the triangle - ie the shortest distance between the top point and the line between the two

  • base points.

static get_max_min_ferets(edge_points: list)[source]#

Return the minimum and maximum feret diameters for a grain.

These are defined as the smallest and greatest distances between a pair of callipers that are rotating around a 2d object, maintaining contact at all times.

Parameters:

edge_points (list) – a list of the vector positions of the pixels comprising the edge of the grain. Eg: [[0, 0], [1, 0], [2, 1]]

Returns:

  • min_feret (float) – the minimum feret diameter of the grain

  • max_feret (float) – the maximum feret diameter of the grain

Notes

The method starts out by calculating the upper and lower convex hulls using an algorithm based on the Graham Scan Algorithm [1]. Using these upper and lower hulls, the callipers are simulated as rotating clockwise around the grain. We determine the order in which vertices are encountered by comparing the gradients of the slopes between vertices. An array of pairs of points that are in contact with either calliper at a given time is created in order to be able to calculate the maximum feret diameter. The minimum diameter is a little tricky, since it won’t simply be the shortest distance between two contact points, but it will occur somewhere during the rotation around a pair of contact points. It turns out that the point will always be such that two points are in contact with one calliper while the other calliper is in contact with another point. We can use this fact to be sure of finding the smallest feret diameter, simply by testing each triangle of 3 contact points as we iterate, finding the height of the triangle that is formed between the three aforementioned points, as this will be the perpendicular distance between the callipers.

References

[1] Graham, R.L. (1972).

“An Efficient Algorithm for Determining the Convex Hull of a Finite Planar Set”. Information Processing Letters. 1 (4): 132-133. doi:10.1016/0020-0190(72)90045-2.