python_shape_stats package

python_shape_stats.helpers

python_shape_stats.helpers.get_camera_properties(cam)[source]
python_shape_stats.helpers.get_user_input_for_cam_view(mesh, link_views=True)[source]
python_shape_stats.helpers.set_camera_view(cam, view: dict | Callable)[source]
python_shape_stats.helpers.broken_stick_expectation(N)[source]
python_shape_stats.helpers.broken_stick_empirical(N, n_reps=100, seed=None)[source]

Empirically estimate the broken stick distribution when random splitting a stick of length 1 into N segments :param n_reps: number of repetitions :param N: number of segments to break the stick into :return:

python_shape_stats.helpers.get_dummy(x: DataFrame, dtype_obj: CategoricalDtype) DataFrame[source]

turns x into dummy variables, listening to the categories listed in dtype_obj

python_shape_stats.helpers.squeeze_categorical_dtypes(x)[source]
python_shape_stats.helpers.weighted_column_mean(x, w)[source]
python_shape_stats.helpers.weighted_rms(x, w)[source]
python_shape_stats.helpers.randomize_matrix(x, seed=None)[source]
python_shape_stats.helpers.animate_vectors(base_polydata, point_vectors, frame_scalars, mode='write_gif', file_name='animation.gif', fps=10, cam_view=None, off_screen=False, link_views=True, title=None, same_coordinate_system=False)[source]

Animates shape transformations and optionally saves the results as a .gif.

Parameters:
  • base_polydata – the polydata, or a list of n polydatas to animate

  • point_vectors – a point vector (an n points x 3 dimensions) array,or a list of n point vectors, specifying the direction of the transformation at each point

  • frame_scalars – a vector of scalars, or a list of n vectors, determining how much the polydata is transformed for each frame. For example the points of the polydata on the ith frame are equal to base_polydata.points+point_vector*frame_scalars[i]

  • mode – if ‘write_gif’ animation will be saved as a gif

  • file_name – the file_name of the saved gif

  • fps – the frame rate of the saved gif

  • cam_view – this functionality is to be implemented more fully in future

  • off_screen – this functionality is to be implemented mor fully in future

  • link_views – if True, if multiple vectors are visualised this links there views so they are always viewed from the same angle

  • title – a single title, or a list of n titles for each animated vectors

  • same_coordinate_system – if True mutliple (n) polydata and (n) vectors are viewed in the same viewer.

python_shape_stats.helpers.plot_colormaps(base_polydata, point_scalars, title=None, file_name='colormap.pdf', clim=None, cmap=None, link_cmaps=False, cam_view=None, off_screen=False, link_views=True, plot_color_bar=True, same_coordinate_system=False)[source]

Plot colormaps on polydatas either in a single window, or if multiple colormaps are plotted, in a grid of windows

Parameters:
  • base_polydata – a single polydata, or list of n polydatas, onto which to plot the colormaps

  • point_scalars – a single vector, or list of n vectors, of scalars for the colormaps

  • title – a title, or list of n titles, for the plots

  • file_name – the file name of the location where the colormap(s) should be saved

  • clim – a single clim (vector or list of min and max values of the colour scale), or a list of n clims, specifying the limits of the plotted colormaps.

  • cmap – a single colormap or a list of n colormaps top use

  • link_cmaps – if True the same colormap and scale will be applied to all plots. If more than clim or cmap are given as arguments, an error is raised

  • cam_view – this functionality is to be implemented more fully in future

  • off_screen – this functionality is to be implemented more fully in future

  • link_views – if multiple color maps are plotted, link the camera view across the plotting windows (so all colormaps are imaged from the same direction)

  • plot_color_bar – if True (default) a color bar is plotted for each colormap

  • same_coordinate_system – if True multiple colormaps will be plotted in a single window, otherwise they will be plotted in a grid of separate windows.

python_shape_stats.helpers.make_plotter(background_color=[255, 255, 255], **kwargs)[source]
python_shape_stats.helpers.add_vectors(mesh, vectors: ndarray | str = None, vectors_name=None, plotter=None, color_by_length=True, clim=None, cmap=None, **kwargs)[source]
python_shape_stats.helpers.add_shape(mesh, plotter=None, **kwargs)[source]
python_shape_stats.helpers.add_scalar_bar(plotter, **kwargs)[source]
python_shape_stats.helpers.get_path_to_pinnochio_demo_face()[source]

Get full path to the location of the Pinnochio demo face

Returns:

the full path to the face

python_shape_stats.helpers.get_path_to_demo_face()[source]

Get full path to the location of the non-Pinnochio demo face

Returns:

the full path to the face

python_shape_stats.helpers.get_path_to_simulated_faces()[source]
python_shape_stats.helpers.get_path_to_simulated_noses()[source]
python_shape_stats.helpers.get_path_to_simulated_foreheads()[source]
python_shape_stats.helpers.get_path_to_simulated_metadata()[source]
python_shape_stats.helpers.get_path_to_pickled_shape_pca()[source]
python_shape_stats.helpers.get_path_to_pickled_shape_hypthesis_test()[source]
python_shape_stats.helpers.load_shape_hypothesis_test()[source]
python_shape_stats.helpers.load_shape_pca()[source]
python_shape_stats.helpers.landmark_3d_to_2d(a: ndarray) ndarray[source]

Converts the array of shapes (landmark coordinates) in ‘a’ from n (vertices) x 3 dimensions x k observations) into k x 3n

Parameters:

a – the array of landmark coordinates in the shape n (vertices) x 3 (dimensions) x k (observations)

if the shape is n x 3 it will be converted to n x 3 x 1 :return: a 2d array of size k x 3n (each row contains the landmarks of observation)

python_shape_stats.helpers.landmark_2d_to_3d(a: ndarray) ndarray[source]

Converts landmark configurations from representation as a 2d array (k (observations) x 3n (n = number of vertices) to a three-dimensional array n x 3 x k. If k==1 the result will be n x 3.

Parameters:

a – a k x 3n matrix, if array is one dimensional it will be treated as 1 x 3n

Returns:

an n x 3 x k matrix (if k==1) the result will be n x 3

python_shape_stats.helpers.load_shape(path: str = None, **kwargs) tuple[source]

Loads a file containing shape data

Parameters:
  • path – path to the shape to be loaded if str. If None a file dialog will be opened to select the files

  • kwargs – keyword arguments to be passed to helpers.TriPolyData.__init__

Returns:

a tuple containing an instance of helpers.TriPolyData,

python_shape_stats.helpers.load_shapes_to_array(paths: iter, n_jobs: int = 1) tuple[source]

Loads the meshes specified in ‘paths’ and returns their vertices in an n (vertices) x 3 x k observations array, as well as a list of corresponding helpers.TriPolyData objects All meshes must have the same number of vertices :param paths: an iterable containing the paths to the mehses to load :param n_jobs: the number of jobs to run concurrently. This uses joblib.Parallel rules. i.e. a positive integer specifies the number of jobs and negative integers indicates to run j + 1 + n_jobs where j is the maximum possible (e.g. -1 indictaes to use all available cores) :return: a tuple containing 1. the vertices in n (vertices) x 3 x k observations array, 2. a list of helpers.TriPolyData objects

python_shape_stats.helpers.ismember(A, B)[source]
class python_shape_stats.helpers.TriPolyData(*args, **kwargs)[source]

Bases: PolyData

This class adds some extra functionality and convenience to the pyvista.PolyData class

property faces_array

The faces of the polydata in shape n(faces) x 3

save(filename, **kwargs)[source]

Overrides the save method of pyvista.PolyData, to handle some additional formats. When the requested filetype is supported by the super class (‘.ply’, ‘.vtp’, ‘.stl’, ‘.vtk’]) the super class ‘save’ method is used, otherwise a custom writer is searched for (for now the only additional format supported is obj)

Parameters:
  • filename – the filename of the output file

  • kwargs – keyword arguments to be passed to pyvista.PolyData.save is it is used.

write_obj(filename)[source]
python_shape_stats.helpers.my_is_iterable(obj)[source]

Custom check for iterability of objects, but ignoriung some types

python_shape_stats.helpers.validate_landmark_configuration_and_weights(p, q=None, w=None)[source]

Implements some reusable checks of the inputs

python_shape_stats.helpers.validate_vector(x, var_name, output_type='flat')[source]
python_shape_stats.helpers.reshape_vector(x, output_type)[source]

python_shape_stats.inlier_processes

python_shape_stats.inlier_processes.update_inlier_weights_gaussian(p: ndarray, q: ndarray, w: ndarray = None, kappa: float = 3) ndarray[source]

Updates inlier weights (e.g. as part of an EM algorithm) between two landmark configurations to flag regions that are unusually diferent between them

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates

  • q – an n (landmarks) by 3 array of landmark coordinates

  • w – previously calculated inlier weights (e.g. on the previous iteration of the EM algorithm)

  • kappa – a threshold for determining inliers/outliers in units of standrad deviation

Returns:

inlier weights for each vertex in p and q

python_shape_stats.procrustes

python_shape_stats.procrustes.compute_procrustes_transform(p: ndarray, q: ndarray, scale: bool = True, w: ndarray = None) ndarray[source]

Computes the optimal rotation, translation and (optionally) scaling to align two corresponding landmark configurations (aligns p to q).

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates

  • q – an n (landmarks) by 3 array of landmark coordinates

  • scale – if True the scaling of p to q will be calculated. Otherwise, only rotation and translation will be calculated

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, those landmarks with higher weights have more impact on the solution

Returns:

a 4x4 transformation matrix

python_shape_stats.procrustes.compute_rotation(p: ndarray, q: ndarray, w: ndarray = None) ndarray[source]

Calculates the optimal rotation from p to q

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates

  • q – an n (landmarks) by 3 array of landmark coordinates

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, those landmarks with higher weights have more impact on the solution

Returns:

a 4x4 transformation matrix, modelling only rotation

python_shape_stats.procrustes.make_translation_matrix(origin=array([0, 0, 0]), destination=array([0, 0, 0])) ndarray[source]

Constructs a translation matrix for translating from the origin to the destination

Parameters:
  • origin – a vector of length 3 specifying the origin of the translation, defaults to [0,0,0]

  • destination – a vector of length 3 specifying the destination of the translation; defaults to [0,0,0]

Returns:

a 4x4 transformation matrix modelling only the translation from origin to destination

python_shape_stats.procrustes.compute_centroid_size(p: ndarray, w: ndarray = None) float[source]

Computes the (weighted) centroid size of the landmark configuration p

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, those landmarks with higher weights have more impact on the solution

Returns:

the centroid size of the landmark configuration p

python_shape_stats.procrustes.compute_rms_size(p: ndarray, w: ndarray = None) float[source]

Computes the (weighted) root mean squared distance of the landmarks in configuration p from the centroid

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, those landmarks with higher weights have more impact on the solution

Returns:

the rms size of the landmark configuration p

python_shape_stats.procrustes.compute_centroid(p: ndarray, w: ndarray = None) ndarray[source]

Computes the (weighted) centroid of the landmark configuration p

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates.

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, those landmarks with higher weights have more impact on the solution.

Returns:

the centroid of the landmark configuration p.

python_shape_stats.procrustes.scale_shape(p: ndarray, target_size: float = 1.0, size_type='centroid', w: ndarray = None) ndarray[source]

Scales the landmark configuration to the target centroid size.

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates.

  • target_size – the target centroid size to scale p to

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, thoselandmarks with higher weights have more impact on the solution.

  • target_size – the size to scale p to

  • size_type – which definition of size to use, can be ‘centroid’ or ‘rms’

  • w – the landmark configuration p scaled to the target size

python_shape_stats.procrustes.apply_procrustes_transform(p: ndarray, t: ndarray, invert: bool = False) ndarray[source]

Applies a procrustes transformation to the landmark configuration p

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates.

  • t – a 4x4 transformation matrix

  • invert – if True the function will apply the inverse of the transformation in t

Returns:

the landmark configuration p after applying the transformation

python_shape_stats.procrustes.conform_p_to_q(p: ndarray, q: ndarray, w=None, scale=True) tuple[source]

Computes the optimal rotation, translation and (optionally) scaling to align two corresponding landmark configurations (aligns p to q) and applies the transformation to p.

Parameters:
  • p – an n (landmarks) by 3 array of landmark coordinates

  • q – an n (landmarks) by 3 array of landmark coordinates

Keyword Arguments:
  • scale – if True the scaling of p to q will be calculated. Otherwise, only rotation and translation will be calculated

  • w – if not None this should be a vector of length n (landmarks). This is a vector of weights, those landmarks with higher weights have more impact on the solution

Returns:

a tuple containing a copy of p and the 4x4 transformation matrix

python_shape_stats.procrustes.do_generalized_procrustes_analysis(landmarks: ndarray, scale: bool = True, max_iter: int = inf, init_landmarks: ndarray = None, n_jobs=1) dict[source]

Aligns a sample of landmark configurations to their mean by generalized Procrustes analysis

Parameters:
  • landmarks – an n (vertices) x 3 (dimensions) x k (observations) matrix of landmark coordinates

  • scale – if True all landmark configurations will be scaled to unit centroid size

  • max_iter – the maximum number of iterations if not specified the algorithm will continue until convergence, however long it takes

  • init_landmarks – an n (vertices) x 3 (dimensions) array of landmark coordinates to initialise the algorithm. if unspecified

  • n_jobs – the number of jobs to run in parallel - see joblib.Parallel documentation

Returns:

a tuple with two elements: 1. the landmarks after alignment to the sample mean and 2. the sample mean to which they are aligned

python_shape_stats.statistical_shape_models

class python_shape_stats.statistical_shape_models.PCA[source]

Bases: object

Implements a principal components analysis of a data matrix with several methods for determining the number of principal components.

property eig_vec

The right singular vectors (the PCs) of the data matrix . The first dimension corresponds to PCs, the second to features.

Type:

np.ndarray

property eig_val

The total variance explained by each PC. This is computed from the singular values of the training data matrix

\(\frac{s^2}{k}\) where \(s\) is the singular values and \(k\) is the number of observations (rows in the training data matrix). If x is column-mean centered in the call to ‘fit’ This is equal to the sample variance in each dimension of the transformed data.

Type:

np.ndarray

property eig_std

The square root of ‘self.eig_val’. If x was column mean centered during the call to ‘self.fit’ these are the sample standard deviations of the transformed training data

Type:

np.ndarray

property cumulative_perc_var

The cumulative percentage of the total initial variance explained. The \(i_{th}\) entry is the percentage of variace explained by the pcs 1-i

Type:

np.ndarray

property n_dim

The number of dimensions (PCs) currently in the model.

Type:

int

property transformed_training_data

Coordinates of the training data in the space spanned by the PCs. Rows correspond to observations, columns to PCs These are alternatively called ‘PC scores’

Type:

np.ndarray

property center_vec

The vector used to center the columns of x. Using default keyword arguments to ‘fit’ this is the column mean of the training data matrix

Type:

np.ndarray

property standardize_cols_vec

The vector used to standardize the columns of x. If standardize_cols == True during the call to fit this will be the column root mean square deviation from ‘center_vec’

Type:

np.ndarray

property params

Parameters used during the last call to self.fit

Type:

dict

fit_transform(x: ndarray, center: bool = True, center_vec: ndarray = None, standardize_cols: ndarray = False) None[source]

Fits the PCA model to training data x and applies the dimensionality reduction to x

Parameters:
  • x – a k (observations) by n (features) matrix of training data

  • center – if True the columns of x will be centered on center_vec prior to the SVD

  • center_vec – if None the ‘center_vec’ defaults to the column means of x and thus performs column mean centering of x

  • standardize_cols – if True the columns of x will be standardized to have unit variance prior to the svd

fit(x: ndarray, center: bool = True, center_vec: ndarray = None, standardize_cols: bool = False)[source]

Fits the PCA model to training data x - uses the singular value decomposition of (column centered and standardized) x.

Parameters:
  • x – a k (observations) by n (features) matrix

  • center – if True the columns of x will be centered on center_vec prior to the SVD

  • center_vec – if None the ‘center_vec’ defaults to the column means of x and thus performs column mean centering of x

  • standardize_cols – if True the columns of x will be standardized to have unit variance prior to the svd

transform(x: ndarray) ndarray[source]

Perform the dimensionality reduction on x

Parameters:

x – an l (observations) by n (features) matrix

Returns:

an l (observations) by self.n_dim array of co-ordinates in the lower dimensional space

predict(x: ndarray) ndarray[source]

Reverses the dimensionality reduction to get back the original feature values from the transformed values

Parameters:

x – an l (observations) x self.n_dim matrix (or a vector of length self.n_dim)

Returns:

an array with l rows and n (features) columns

parallel_analysis(n_reps: int = 50, n_jobs: int = 1, seed: int | Generator = None)[source]

Computes a ‘null’ distribution of eigenvalue spectra derived from random matrices. Run this method then PCA.parallel_analysis_plot to visualise and interpret the results and determine the optimum number of principal components

Parameters:
  • n_reps – number of repetitions to use in the parallel analysis

  • n_jobs – number of jobs to run in parallel

  • seed – random seed

scree_plot(ax: Axes = None) tuple[source]

Makes a scree plot of the eigenvalue spectrum

Parameters:

ax – optionally an axis handle

Returns:

a tuple containing 1. the axis handle on which the plot is plotted and 2. a NoneType object

cumulative_variance_plot(ax: Axes = None) tuple[source]

Plots the cumulative percentage of variance explained by each PC.

Parameters:

ax – an axis on which to plot.

Returns:

a tuple containing 1. the axis handle on which the plot is plotted and 2. a NoneType object

parallel_analysis_plot(ax: Axes = None, ci_level: float = 95, threshold_level: float = 95, n_reps: int = 50, n_jobs: int = 1, recompute_parallel_analysis: bool = False, seed: int | Generator = None) tuple[source]

Plots the result of a parallel analysis to determine the number of principal components to retain. In a parallel analysis the observed eigenvalue spectrum is compared to a (‘null’) distribution of eigenvalue spectra obtained from random matrices. If the observed eigenvalue for the ith principal component is greater than the specified threshold it is considered ‘significant’. The estimated number of components is the (k-1)th component where k is the index of the first non-significant component. The plot plots the threshold as a solid line. The null distribution is plotted as a shaded region that spans the 0-ci_level percentiles of this distribution.

Parameters:
  • ax – an axis handle on which to plot

  • ci_level – the upper limit of the null distribution (as a percentile) to plot as a shaded region

  • threshold_level – the percentile of the null distribution, if the eigenvalue exceeds this it is considered significant

  • n_reps – the number of repetitions to compute the null distribution (will be ignored if the null distribution has already been calculated by calling PCA.parallel_analysis and recompute_parallel_analysis==False)

  • n_jobs – the number of jobs to run in parallel while computing the null distribution (will be ignored if the null distribution has already been calculated by calling PCA.parallel_analysis and recompute_parallel_analysis==False)

  • recompute_parallel_analysis – if True will recompute the null distribution, even if ot has already been calculated

  • seed – seed for the random number generator

Returns:

a tuple containing 1. the axis on which the plot is plotted and 2. the estimated number of principal components

broken_stick_plot(ax: Axes = None, ci_level: float = 95, threshold_level: float = 95, n_reps: int = 1000) tuple[source]

Plots the result of a broken stick analysis to determine the number of principal components to retain. In a broken stick analysis the observed eigenvalue spectrum is compared to a (‘null’) distribution of eigenvalue spectra produced by randomly uniformly splitting the total variance ito the maximum number of principal components possible. If the observed eigenvalue for the ith principal component is greater than the specified threshold it is considered ‘significant’. The estimated number of components is the (k-1)th component where k is the index of the first non-significant component. The plot plots the threshold as a solid line. The null distribution is plotted as a shaded region that spans the 0-ci_level percentiles of this distribution.

Parameters:
  • ax – an axis handle on which to plot

  • ci_level – the upper limit of the null distribution (as a percentile) to plot as a shaded region

  • threshold_level – the percentile of the null distribution, if the eigenvalue exceeds this it is considered significant

  • n_reps – the number of repetitions to perform to estimate the broken stick distribution

Returns:

a tuple containing 1. the axis on which the plot is plotted and 2. the estimated number of principal components

trim_no_pcs(no_pcs: int)[source]

Modifies the object in situ, removing the specified number of pcs

Parameters:

no_pcs – the number of pcs to retain

trim_perc_var(pct_var: float)[source]

Modifies the object in situ, removing the number of pcs explaining up to the specified amount of variance

Parameters:

pct_var – the percentage of variance s to retain

weighted_transform_to_model(x: ndarray, weights: ndarray, max_m_dist: float = None) ndarray[source]

Performs the dimensionality reduction on a single observation with weights that increase/decrease the infleunce of a given feature on the solution. The solution can also be constrained to lie within a specified Mahalanobis distance of the origin.

Parameters:
  • x – a single observation in the original feature space

  • weights – a weight for each feature

  • max_m_dist – the maximum Mahalanobis distance the transformed values can be from the origin

Returns:

the transformed values of x

scale_vec(x: ndarray, target_dist: float | ndarray, origin: ndarray = None, metric: str = 'euclidean') ndarray[source]

Scales vectors in the transformed space to be the target distance from the origin

Parameters:
  • x – a k (observations) x self.n_dim matrix of locations in the transformed space. This can also be a vector of length self.n_dim

  • target_dist – the target distance from the origin - this can be a single float or a vector entries corresponding to the rows of x

  • origin – the origin with respect to which to scale the vectors

  • metric – the distance metric (can be ‘mahalanobis’ or ‘euclidean’

Returns:

the scaled vectors in a matrix the same size as x

maha_dist_to_p_value(md: float | ndarray) float | ndarray[source]

Returns the probability an observation as or more extreme than the given Mahalanobis distance from the origin

Parameters:

md – the mahalanobis distance, can be a float or an array of floats

Returns:

the p-values corresponding to the elements in md

p_value_maha_dist(p)[source]

Returns the Mahalanobis distance for which the probability of an observation as or more extrem is equal to p

Parameters:

p – the p value, can be a float or an array of floats

Returns:

the Mahalanobis distance, corresponding to the elements in md

get_distance(x: ndarray, origin: ndarray = None, metric: str = 'euclidean') ndarray[source]

Gets the distance of x from the origin, in the space of the transformed variables

Parameters:
  • x – a vector of length l or an array k (observations) x l. l == self.n_dim

  • origin – a vector of length l or an array k (observations) x l. l == self.n_dim. If origin is a matrix each row of x is comapred to the corresponding row of origin

  • metric – the distance metric to use, must either be ‘euclidean’ or ‘mahalanobis’

Returns:

an array containing the distances of each row of x from

class python_shape_stats.statistical_shape_models.ShapePCA[source]

Bases: PCA

Implements some additional properties and methods for doing principal components analysis on a sample of shapes

property average_polydata

A polydata object of the average shape

Type:

helpers.TriPolyData

property reference_polydata

This should be an example shape from your dataset.The reference polydata determines how the average_polydata in visualisation of the PCA model can be rendered. Specifically if the topology of the surface is known this should be kept in reference_polydata.faces The average and other shape visualisations can then be visualised as surfaces, not just points.

Type:

helpers.TriPolyData

fit(x: ndarray, center: bool = True, center_config: ndarray = None)[source]

Fits the PCA model to training data x - uses the singular value decomposition of (centered) x.

Parameters:
  • x – an l (vertices/landmarks) x 3 dimensions x k (observations) array of homologous shapes

  • center – if True x will be centered along the third dimension by center_config x prior to the SVD

  • center_config – if None the ‘center_config’ defaults to np.mean(x,axis=2) and thus centers the landm,rks on their mean shapes

transform(x: ndarray, apply_procrustes_transform: bool = True, procrustes_scale: bool = True, n_jobs: int = 1)[source]

Transforms the landmark configurations in x into the lower dimenisonal space of the PCA model.

Parameters:
  • x – an l (vertices/landmarks) x 3 dimensions x k (observations) array of homologous shapes

  • apply_procrustes_transform – if True each observation in x will be aligned first to the mean shape using the Procrustes transform. If false then the shapes must already be aligned to the mean shape before calling this function

  • procrustes_scale – if apply_procrustes_transform is True then this will determine if the configuratioons are allowed to scale towards the mean shape

  • n_jobs – the number of jobs to run in parallel (see joblib.Parallel documentation)

Returns:

a tuple containing 1. a k observations x self.ndims array of coordinates in the lower dimensional space, 2. a list of the procrustes transformations applied to each configuration

fit_transform(x: ndarray, center: bool = True, center_config: ndarray = None)[source]

Fits the PCA model to training data in x and transforms it into the lower dimensional space

Parameters:
  • x – an l (vertices/landmarks) x 3 dimensions x k (observations) array of homologous shapes

  • center – if True x will be centered along the third dimension by center_config x prior to the SVD

  • center_config – if None the ‘center_config’ defaults to np.mean(x,axis=2) and thus centers the landmarks on their mean shapes

animate_pc(pc_num: int, max_sd: float = 3, n_frames=20, mode='write_gif', **kwargs)[source]

Makes an animation illustrating the shape change associated a specified PC

Parameters:
  • pc_num – the PC to visualise

  • max_sd – The shape will be morphed between -max_sd - max_sd standard deviations

  • n_frames – the number of frames to render in the animation

  • mode – if ‘write_gif’ animation will be written to file, if NoneType it will not

  • kwargs – see helpers.animate_vectors

colormap_pc(pc_num, **kwargs)[source]

Make colormaps of the pcs in pc_num

Parameters:
  • pc_num – a single, or list of n pcs to plot

  • kwargs – see helpers.plot_colormaps

class python_shape_stats.statistical_shape_models.PLS[source]

Bases: ABC

An abstract base class implementing properties and methods common to all classes implementing partial least-squares analyses

property y

The complete block of y variables, before exclusion mask or dummy variables are created as a pandas DataFrame. The y.setter, depending on the subclass, may take or expect an instance of PCA or ShapePCA in which case the getter will return the attribute PCA.transformed_training_data :type: pd.DataFrame

property x

The complete block of x variables, before exclusion mask or dummy variables are created as a pandas DataFrame. The x.setter, depending on the subclass, may take or expect an instance of PCA or ShapePCA in which case the getter will return the attribute PCA.transformed_training_data

Type:

pd.DataFrame

property center_x

Indicates whether or not the x-block is to be column centered. Is intended to be set only via a call to the ‘fit’ method of the class

Type:

bool

property center_y

Indicates whether or not the y-block is to be column-centered. Is intended to be set only via a call to the ‘fit’ method of the class

Type:

bool

property standardize_x

Indicates whether or not the x-block is to be column standardized to have unit variance. Is intended to be set only via a call to the ‘fit’ method of the class

Type:

bool

property standardize_y

Indicates whether or not the x-block is to be column standardized to have unit variance. Is intended to be set only via a call to the ‘fit’ method of the class

Type:

bool

property n_obs

Number of observations after exclusion mask have been applied

Type:

int

property x_treated

The block of x variables after categorical variables are expanded to dummy variables and exclusion mask has been applied. If no categorical variables are in self.x and no observation mask has been applied then this is the same as self.x cast into a DataFrame

Type:

pd.DataFrame

property y_treated

The block of y variables after categorical variables are expanded to dummy variables and exclusion mask has been applied. If no categorical variables are in self.y and no observation mask has been applied then this is the same as self.y

Type:

pd.DataFrame

property observation_weights

A vector of weights (one for each observation) that control the influence of each observation on the fitted model

Type:

np.ndarray

property observation_mask

A boolean vector that can be used to control the observations that are included in fitting the model. Each element corresponds to an observation (row of x and y). If the value is true then that observation will be included otherwise it won’t be.

Type:

np.ndarray

property no_y_features

The number of features/variables (columns) of the y-block before categorical variables are expanded to dummy variables

Type:

int

property no_x_features

The number of features/variables (columns) of the x-block before categorical variables are expanded to dummy variables

Type:

int

property x_mu

The (weighted) column means of x after categorical variables are expanded to dummy variables and after the observation mask has been applied

Type:

np.ndarray

property x_std

The (weighted) column standard deviations of x after categorical variables are expanded to dummy variables and after the observation mask has been applied

Type:

np.ndarray

property y_mu

The (weighted) column means of y after categorical variables are expanded to dummy variables and after the observation mask has been applied

Type:

np.ndarray

property y_std

The (weighted) column standard deviations of x after categorical variables are expanded to dummy variables and after the observation mask has been applied

Type:

np.ndarray

abstract fit()[source]
class python_shape_stats.statistical_shape_models.PLS_2B[source]

Bases: PLS

Performs a symmetrical 2-block PLS via singular value decomposition of the cross-covariance matrix C

property x_projection_matrix

An orthogonal projection matrix onto the lower-dimensional space of the x-scares. Rows correspond to the features (columns) in the x-block, columns correspond to the PLS dimensions.

Type:

np.ndarray

property y_projection_matrix

An orthogonal projection matrix onto the lower-dimensional space of the y-scares. Rows correspond to the features (columns) in the y-block, columns correspond to the PLS dimensions.

Type:

np.ndarray

property cov_explained

The amount of covariance explained by each latent dimension

Type:

np.ndarray

property x_scores

The observations in the x-block represented in the lower-dimensional space. Rows correspond to observations, columns to dimensions.

Type:

np.ndarray

property y_scores

The observations in the y-block represented in the lower-dimensional space. Rows correspond to observations, columns to dimensions.

Type:

np.ndarray

property n_dim

The number of latent dimensions in the model

Type:

int

property inner_relation_coefs

Coefficients modelling the relationship between the x-scores and the y scores. Each coefficient corresponds to a pair of dimensions. The ith coefficient is the coefficient of a major axis regression of self.y_scores[:,i] onto self.x_scores[:,i]

Type:

np.ndarray

property perm_test_p_values

P values corresponding to each latent dimension. PLS_2B.compute_null_distribution() before accessing this property

Type:

np.ndarray

transform_x(x: ndarray | DataFrame, expand_categories: bool = True) ndarray[source]

Performs the dimension reduction on x. If expand_categories == True the function will search for categorical variables in x and expand them into dummy variables.

Parameters:
  • x – an n (observations) by k (number of x features) np.ndarrdy or pd.DataFrame. If expand_categories==True, this must be a DataFrame

  • categories (expand) – whether to search for categoricakl variables in x and expand them into dummy variables.

Returns:

np.ndarray

transform_y(y: ndarray | DataFrame, expand_categories: bool = True) ndarray[source]

Performs the dimension reduction on y. If expand_categories == True the function will search for categorical variables in x and expand them into dummy variables.

Parameters:
  • x – an n (observations) by k (number of x features) np.ndarrdy or pd.DataFrame. If expand_categories==True, this must be a DataFrame

  • categories (expand) – whether to search for categoricakl variables in x and expand them into dummy variables.

Returns:

np.ndarray

fit(x: ndarray | DataFrame | ShapePCA, y: ndarray | DataFrame | ShapePCA, center_x: bool = True, center_y: bool = True, standardize_x: bool = False, standardize_y: bool = False, observation_weights: ndarray = None, observation_mask: ndarray = None)[source]

Fits the two block PLS model to the data x and y

Parameters:
  • x – the x-block of variables. This can be an n (observations) by k features np.ndarray or pd.DataFrame. It can also be an instance of PCA or one of its subclasses. If it is an np.ndarray this simply becomes the x block. If it is a DataFrame, each column’s dtype is checked if dtype==’category’ these will be expanded to l-1 dummy variables, where l is the number of unique values in the column. If it is a PCA (or a subclass thereof) the x block will be the PC scores PCA.transformed_training_data

  • y – the y-block of variables. The same details apply as for ‘x’

  • center_x – boolean indicating whether to column mean center x

  • center_y – boolean indicating whether to column mean center y

  • standardize_x – boolean indicating whether to standardize the columns of x to have unit variance

:param standardize_y:boolean indicating whether to standardize the columns of y to have unit variance :param observation_weights: a vector of length n (observations) :param observation_mask: a boolean array of length n (observations) :return:

reconstruct_y_from_scores(y_scores)[source]
reconstruct_x_from_scores(x_scores)[source]
predict_y_scores_from_x(x_scores)[source]
predict_x_scores_from_y(y_scores)[source]
compute_null_distribution(n_reps=1000, n_jobs=1, seed=None)[source]
permutation_test_plot(p_crit=0.05, ax=None, recompute_null_distribution=False, n_reps=1000, seed=None, n_jobs=1)[source]
class python_shape_stats.statistical_shape_models.ShapePLS_2B[source]

Bases: PLS_2B

animate_latent_dim(dim, max_sd=3, n_frames=20, **kwargs)[source]

Animates the shape transformations of a single latent dimension.

Parameters:
  • dim – the latent dimension to visualise

  • max_sd – the animation will go between +/- max_sd of the scores of the latent dimension

  • n_frames – the number of frames for the animation

  • kwargs – see helpers.animate_vectors

Returns:

colormap_latent_dim(dim, direction='normal', **kwargs)[source]
Parameters:
  • dim – the latent dimension to visualise

  • direction – plots the shape transformtion along the surface normals (if set to ‘normal’) otherwise plots the total magnitude of the shape transformation per point (if set to ‘total’)

  • kwargs – see helpers.plot_colormaps

Returns:

class python_shape_stats.statistical_shape_models.PLSHypothesisTest[source]

Bases: PLS

property coefs
property method
property model_stats
fit(x, y, method='simpls', n_comp=None, center_x=True, center_y=True, standardize_x=False, standardize_y=False, observation_mask=None, observation_weights=None)[source]
run_permutation_test(vars_to_test=None, test_full_model=True, seed=None, n_reps=1000, n_jobs=True)[source]
class python_shape_stats.statistical_shape_models.ShapePLSHypothesisTest[source]

Bases: PLSHypothesisTest

property y

The complete block of y variables, before exclusion mask or dummy variables are created as a pandas DataFrame. The y.setter, depending on the subclass, may take or expect an instance of PCA or ShapePCA in which case the getter will return the attribute PCA.transformed_training_data :type: pd.DataFrame

plot_coefficients(x_vars=None, direction='normal', **kwargs)[source]

Plot the regression coefficients as colormaps

Parameters:
  • x_vars – the names of the x variables plot

  • direction – either ‘normal’ or ‘total’ plotting the magnitude of the coefficients along the surface normals or their total magnitude

  • kwargs – see helpers.plot_colormaps

plot_r_squared(x_vars=None, **kwargs)[source]

Plots the partial r-sqaured for the specified variables for each point

Parameters:
  • x_vars – the names of the x variables plot

  • kwargs – see helpers.plot_colormaps

plot_p_values(x_vars=None, p_crit=0.05, **kwargs)[source]

Plots the significance of of the effect at each point as a binary colormap

Parameters:
  • x_vars – the names of the x variables plot

  • p_crit – the significance threshold

  • kwargs – see helpers.plot_colormaps

animate_coefficients(vars, max_sd: float = 3, n_frames: int = 20, **kwargs)[source]

Visualise the regression coefficients as animations and save as a gif.

Parameters:
  • vars – the names of the x variables plot

  • max_sd – animate between the predicted shapes at +/- max_sd of standrad deviation of the predictor

  • n_frames – the number of frames for the animation

  • kwargs – see helpers.animate_vectors

Returns:

python_shape_stats.statistical_shape_models.simpls(x0, y0, n_comp)[source]
python_shape_stats.statistical_shape_models.pls_svd(cross_cov)[source]