Skip to content

Statistics

Calculate statistics on grain volumes and aggregate and summarise the data.

Functions:

Name Description
area_pores

Extract area of objects in each layer.

calculate_pdf

Calculate the scaled probability density function for an array.

centroid_pores

Extract centroid of objects in each layer.

classify_pore_size

Classify pore sizes in a dataframe into colors.

concatenate_areas

Concatenate a list of dataframes appending the layer id.

count_pores

Count the number of region_properties, each of which represents a pore for all layers.

create_statistics_dictionary

Extract statistics of objects from each layer.

cumulative_area

Sort and calculate the cumulative sum of a single layer of areas.

cumulative_areas

Calculate cumulative area for objects across slices.

feret_diameter_maximum_pores

Extract the maximum feret diameter of objects in each layer.

find_nearest

Extract the area and proportion closes to the specified fraction.

full_width_half_max

Calculate the full-width half max.

hcfa

Half Cumulative Fraction for the total Area (HCFA) for all layers.

sum_area_by_layer

Sum the area of pores on each layer.

summarise_pores

Summarise pore types by image, layer and color.

volume_by_layer

Calculate the volume of objects in each layer.

area_pores

Extract area of objects in each layer.

Parameters:

Name Type Description Default

sliced_region_properties

list[Any]

A list (one for each layer) of lists which contain the region_props for each object within that layer.

required

Returns:

Type Description
list[list[float]]

A list with the same length as the number of layers, each item is a list of the area of objects within that layer.

calculate_pdf

calculate_pdf(array, xmin=None, xmax=None)

Calculate the scaled probability density function for an array.

Parameters:

Name Type Description Default

array

list[float]

Array of data points to be summarised.

required

xmin

int | float

Minimum value.

None

xmax

int | float

Maximum value.

None

Returns:

Type Description
dict[str, NDArray]

Dictionary of x and y values for the PDF.

centroid_pores

centroid_pores(sliced_region_properties)

Extract centroid of objects in each layer.

Parameters:

Name Type Description Default

sliced_region_properties

list[Any]

A list (one for each layer) of lists which contain the region_props for each object within that layer.

required

Returns:

Type Description
list[list[float]]

A list with the same length as the number of layers, each item is a list of the centroid of objects within that layer.

classify_pore_size

classify_pore_size(
    df, area_thresholds, pore_colors, area_val="area"
)

Classify pore sizes in a dataframe into colors.

Parameters:

Name Type Description Default

df

DataFrame

Dataframe with areas to be classified.

required

area_thresholds

dict[str, int]

Dictionary of thresholds, there should be three values for low, medium and high thresholds resulting in four categories.

required

pore_colors

list[str]

Colors to use for the four categories.

required

area_val

str

Column name containing the area data, default is area and is unlikely to need changing.

'area'

Returns:

Type Description
DataFrame

Dataframe with additional column with text categorisation of pore area.

concatenate_areas

concatenate_areas(areas)

Concatenate a list of dataframes appending the layer id.

Used for concatenating the cumulative area across layers.

Parameters:

Name Type Description Default

areas

list[DataFrame]

List of dataframes to be concatenated.

required

Returns:

Type Description
DataFrame

A single dataframe with the layer added to identify which layer data pertains to.

Examples:

>>> import pandas as pd
>>> from afmslicer import statistics
>>>
>>> cumulative_areas = [
            pd.DataFrame(
                {
                    "area_sorted": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                    "cumulative_sum": [1, 3, 6, 10, 15, 21, 28, 36, 45, 55],
                    "cumulative_fraction": [
                        0.018182,
                        0.054545,
                        0.109091,
                        0.181818,
                        0.272727,
                        0.381818,
                        0.509091,
                        0.654545,
                        0.818182,
                        1.000000,
                    ],
                }
            ),
            pd.DataFrame(
                {
                    "area_sorted": [
                        1.514573,
                        2.128789,
                        3.221781,
                        4.233843,
                        5.590145,
                        7.249351,
                        7.578406,
                        8.495520,
                        8.507319,
                        8.988321,
                    ],
                    "cumulative_sum": [
                        1.514573,
                        3.643361,
                        6.865142,
                        11.098985,
                        16.689130,
                        23.938481,
                        31.516887,
                        40.012407,
                        48.519726,
                        57.508047,
                    ],
                    "cumulative_fraction": [
                        0.026336708175331593,
                        0.06335394035771619,
                        0.11937707207826649,
                        0.19299881350935774,
                        0.29020512185250114,
                        0.4162631519515137,
                        0.5480430704702286,
                        0.6957705678538069,
                        0.8437032406962971,
                        1.0,
                    ],
                }
            ),
        ]
>>> statistics.concatenate_areas(cumulative_areas)

count_pores

Count the number of region_properties, each of which represents a pore for all layers.

Parameters:

Name Type Description Default

sliced_region_properties

list[Any]

A list of region properties found on each layer.

required

Returns:

Type Description
NDArray[int32]

A list of the number of region properties detected in each layer.

create_statistics_dictionary

create_statistics_dictionary(
    sliced_region_properties,
    feret_maximum=False,
    centroid=False,
)

Extract statistics of objects from each layer.

Parameters:

Name Type Description Default

sliced_region_properties

list[list[Any]]

List of lists of region properties, the top level is layer, the nesting within it is each of the objects within the layer.

required

feret_maximum

bool

Whether to extract the maximum feret distance.

False

centroid

bool

Whether to extract the centroid coordinates of the region.

False

Returns:

Type Description
dict[int, dict[int, Any]]

Dictionary of statistics, top-level is the layer/slice through the image, and nested within are statistics for each pore.

cumulative_area

cumulative_area(areas)

Sort and calculate the cumulative sum of a single layer of areas.

Parameters:

Name Type Description Default

areas

NDArray[float64]

An array of areas for a single slice.

required

Returns:

Type Description
DataFrame

Pandas dataframe of sorted area, cumulative sum of the area and the cumulative fraction.

Examples:

>>> import numpy as np
>>> from afmslicer import statistics
>>>
>>> areas = np.asarray([10, 1, 9, 2, 8, 3, 7, 4, 6, 5]),
>>> statistics.cumulative_area(areas)

cumulative_areas

cumulative_areas(areas)

Calculate cumulative area for objects across slices.

Parameters:

Name Type Description Default

areas

list[NDArray[float64]]

List of numpy arrays of the area of objects in layers.

required

Returns:

Type Description
list[DataFrame]

A list of dataframes with the areas sorted by size, the cumulative area and the cumulative area fraction.

Examples:

>>> import numpy as np
>>> from afmslicer import statistics
>>>
>>> areas = [
            np.asarray([10, 1, 9, 2, 8, 3, 7, 4, 6, 5]),
            np.asarray(
                [
                    4.23384259,
                    8.50731915,
                    5.59014498,
                    7.24935116,
                    7.57840579,
                    8.98832143,
                    1.51457266,
                    8.49551991,
                    2.12878874,
                    3.22178091,
                ]
            ),
        ]
>>> statistics.cumulative_areas(areas)

feret_diameter_maximum_pores

feret_diameter_maximum_pores(sliced_region_properties)

Extract the maximum feret diameter of objects in each layer.

Parameters:

Name Type Description Default

sliced_region_properties

list[Any]

A list (one for each layer) of lists which contain the region_props for each object within that layer.

required

Returns:

Type Description
list[list[float]]

A list with the same length as the number of layers, each item is a list of the maximum feret diameter of objects within that layer.

find_nearest

find_nearest(
    areas,
    fraction=0.5,
    cum_fraction_col="cumulative_fraction",
    cum_area_col="cumulative_sum",
)

Extract the area and proportion closes to the specified fraction.

Parameters:

Name Type Description Default

areas

DataFrame

Pandas dataframe of the sorted area, cumulative area and cumulative fraction of the cumulative area.

required

fraction

float

Proportion of interest, default is 0.5 and typically won't need changing.

0.5

cum_fraction_col

str

Column name for the cumulative fraction. Default is cumulative_fraction and typically won't need changing.

'cumulative_fraction'

cum_area_col

str

Column name for the cumulative area. Default is cumulative_area and typically won't need changing.

'cumulative_sum'

Returns:

Type Description
dict[str, float]

A dictionary of the cumulative area and fraction.

Examples:

>>> import pandas as pd
>>> from afmslicer import statistics
>>>
>>> cumulative_areas = pd.DataFrame(
            {
                "area_sorted": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                "cumulative_sum": [1, 3, 6, 10, 15, 21, 28, 36, 45, 55],
                "cumulative_fraction": [
                    0.018182,
                    0.054545,
                    0.109091,
                    0.181818,
                    0.272727,
                    0.381818,
                    0.509091,
                    0.654545,
                    0.818182,
                    1.000000,
                ],
            }
        )
>>> statistics.find_nearest(cumulative_areas, fraction=0.5)
>>> statistics.find_nearest(cumulative_areas, fraction=0.2)

full_width_half_max

full_width_half_max(pdf)

Calculate the full-width half max.

We are interested in the layers that cover the full-width half-max of the number of pores in an image. And therefore extract the indices the calculated PDF (y_pdf)

Parameters:

Name Type Description Default

pdf

NDArray

Array probability density function for which peak and full-width half-max are to be calculated.

required

Returns:

Type Description
tuple[int, int]

Dictionary of the lower and upper layers for the full-width half-max range.

hcfa

hcfa(areas, fraction=0.5)

Half Cumulative Fraction for the total Area (HCFA) for all layers.

Parameters:

Name Type Description Default

areas

list[DataFrame]

List of pandas dictionaries with the fraction, area and cumulative_fraction for the given fraction.

required

fraction

float

The fraction at which to extract areas.

0.5

Returns:

Type Description
DataFrame

Pandas dataframe of the layer, fraction, area and cumulative_fraction.

Examples:

>>> import pandas as pd
>>> from afmslicer import statistics
>>>
>>> areas = [
            pd.DataFrame(
                {
                    "area_sorted": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
                    "cumulative_sum": [1, 3, 6, 10, 15, 21, 28, 36, 45, 55],
                    "cumulative_fraction": [
                        0.018182,
                        0.054545,
                        0.109091,
                        0.181818,
                        0.272727,
                        0.381818,
                        0.509091,
                        0.654545,
                        0.818182,
                        1.000000,
                    ],
                }
            ),
            pd.DataFrame(
                {
                    "area_sorted": [
                        1.514573,
                        2.128789,
                        3.221781,
                        4.233843,
                        5.590145,
                        7.249351,
                        7.578406,
                        8.495520,
                        8.507319,
                        8.988321,
                    ],
                    "cumulative_sum": [
                        1.514573,
                        3.643361,
                        6.865142,
                        11.098985,
                        16.689130,
                        23.938481,
                        31.516887,
                        40.012407,
                        48.519726,
                        57.508047,
                    ],
                    "cumulative_fraction": [
                        0.026336708175331593,
                        0.06335394035771619,
                        0.11937707207826649,
                        0.19299881350935774,
                        0.29020512185250114,
                        0.4162631519515137,
                        0.5480430704702286,
                        0.6957705678538069,
                        0.8437032406962971,
                        1.0,
                    ],
                }
            ),
        ]
>>> statistics.hcfa(areas=areas, fraction=0.5)

sum_area_by_layer

sum_area_by_layer(areas, min_size=None)

Sum the area of pores on each layer.

Parameters:

Name Type Description Default

areas

list[list[float]]

A list of areas of pores on each layer.

required

min_size

float

Minimum size to include in calculation.

None

Returns:

Type Description
list[float]

A list with the total area per slice.

summarise_pores

summarise_pores(df, pore_colors)

Summarise pore types by image, layer and color.

Parameters:

Name Type Description Default

df

DataFrame

Pandas dataframe to aggregate, typically will be AFMSlicer.statistics. Must have columns image, layer, pore_color and counter.

required

pore_colors

list[str]

List of pore color columns that should be present in the resulting dataframe.

required

Returns:

Type Description
DataFrame

Aggregated data frame of counts of pore_color by image/layer with counts of each pore_color.

volume_by_layer

volume_by_layer(areas, scale=None)

Calculate the volume of objects in each layer.

Parameters:

Name Type Description Default

areas

list[list[int | float] | int | float]

List of areas of pores on each layer.

required

scale

float

Scaling for calculating volume. This may be the pixel to nanometer scaling if slicing has been performed relative to this factor, or if an arbitrary number of slices have been taken it should be the range of heights divided by the number of slices.

None

Returns:

Type Description
NDArray[float64]

A numpy array of volumes for each object in each slice.