Table of Contents
This part guides the feature analysis and visualization of mosaics. Codes here follow the 1st part of the tutorial, you should run previous codes first.
For customizable visualization, it is necessary to import
the matplotlib library, as
import matplotlib.pyplot as pltIn this section, we introduce how to analyze and visualize spatial features in a single mosaic. We use the natural mosaic to present usages and results.
Due to boundary effects, the first step in feature analysis is to label boundary points in the mosaic, and later statistics will skip these points. The Mosaic class provides two methods to access indices of boundary or effective points separately, as,
# a numpy.darray(dtype=int) contains indices of boundary points
boundary_indices = natural_mosaic.get_boundary_indices()
# a numpy.darray(dtype=int) contains indices of effective points
effective_indices = natural_mosaic.get_effective_indices()Besides, you can randomly select points with a given number by the get_random_indices method, as
# a numpy.darray(dtype=int) contains indices of random points
random_indices = natural_mosaic.get_random_indices(n=30)
# If n >= the number of points, it will return all indices with a random order We draw the above points in the natural_mosaic as the example to introduce visualization methods in Mosiac. Next is how to draw effective points by using the draw_points method.
natural_mosaic.draw_points(highlights=effective_indices, nonhighlight_alpha=0.5, ax_grid=5, draw_plane_grid=True, ax_scaled=True, point_args={"color": "k", "s": 20}, ax=None) The draw_points method has several arguments for setting highlight points, the properties of the axes and points, as
highlights: Indices of solid points, default isNone, and the method will highlight effective points.nonhighlight_alpha: Alpha of parent points, default is0.3.ax_grid: The number of ax-ticks in a side, default is1.draw_plane_grid: Whether draw grids with ax-ticks, default isFalse.ax_scaled: If it is True, the unit of x and y sides are same. Otherwise, two sides have the same length without other commands with the axes. Please visit the manual of matplotlib.axes.Axes for more information.point_args: Arguments that are delivered into the matplotlib.axes.Axes.scatter method to control properties of points. In the above sentence, we set the color of points ask(black) and the size of points as20. NOTE: If it hasalpha, the alpha of un-highlight points is the multiple of givenalphaandnonhighlight_alphato ensure highlight points are more solid than others.ax: Drawing with the specified matplotlib.axes.Axes. If not provided, the method will create new axes and show drawing results at the end.
The next example draws red points and highlights boundary points, as
natural_mosaic.draw_points(highlights=boundary_indices, nonhighlight_alpha=0.2, ax_grid=5, draw_plane_grid=False, ax_scaled=True, point_args={"color": "r", "s": 40}) With specific axes, you can draw with several subplots. For example,
# The 1st subplot highlights effective points
ax1 = plt.subplot(131)
natural_mosaic.draw_points(highlights=effective_indices, nonhighlight_alpha=0.2, ax_grid=5, draw_plane_grid=True, ax_scaled=True, point_args={"color": "r", "s": 20}, ax=ax1)
ax1.set_title("Solid points are effective")
# The 2nd subplot hightlights boundary points
ax2 = plt.subplot(132)
natural_mosaic.draw_points(highlights=boundary_indices, nonhighlight_alpha=0.2, ax_grid=5, draw_plane_grid=True, ax_scaled=True, point_args={"color": "r", "s": 20}, ax=ax2)
ax2.set_title("Solid points are boundary")
# The 3rd subplot hightlights randomly selected points
ax3 = plt.subplot(133)
natural_mosaic.draw_points(highlights=random_indices, nonhighlight_alpha=0.2, ax_grid=5, draw_plane_grid=True, ax_scaled=True, point_args={"color": "r", "s": 20}, ax=ax3)
ax3.set_title("Random (N=30) Selection")
# Show drawing results
plt.show() Other visualization methods in Mosaic and Pattern support the ax-specific approach. Furthermore, similar to the point_args, several arguments in these methods are delivered into visualization methods in maplotlib. We recommend to check the manual of matplotlib for more information.
The 2nd step of feature analysis is the triangulation, whose edges that link neighbors split the plane into triangle areas. With a Mosaic, it is easy to view the results of Delaunay triangulation, as
natural_mosaic.draw_neighbors(highlights=None, nonhighlight_alpha=0.3, ax_grid=1, draw_plane_grid=False, ax_scaled=True, point_args={"s": 5, "color": "r"}, edge_args={"lw": 0.5, "color": "gray"}, ax=None)The draw_neighbors method shares several arguments with draw_points. Besides, it has an edge_args argument which decides the properties of edges in drawing and is delivered into matplotlib.axes.Axes.plot method.
Furthermore, there is a find_neighbors method to get neighbors of a given index, as
guy = 16 # We try to find the neighbors of this guy.
# get a list of indices of neighbors.
neighbors = natural_mosaic.find_neighbors(p_index=guy, effective_only=False)where p_index is the index of the point and the method will discard boundary points in return if effective_only=True. By specific the highlights argument, we can show the index=16 cell and its neighbors, as
# draw the index=16 cell
ax1 = plt.subplot(121)
natural_mosaic.draw_neighbors(highlights=[guy], nonhighlight_alpha=0.2, ax_grid=5, draw_plane_grid=False, ax_scaled=True, point_args={"color": "red", "s": 30}, edge_args={"lw": 0.5, "color": "gray"}, ax=ax1)
ax1.set_title("The lucky guy")
# draw its neighbors
ax2 = plt.subplot(122)
natural_mosaic.draw_neighbors(highlights=neighbors, nonhighlight_alpha=0.2, ax_grid=5, draw_plane_grid=False, ax_scaled=True, point_args={"color": "red", "s": 30}, edge_args={"lw": 0.5, "color": "gray"}, ax=ax2)
ax2.set_title("Neighbors of the guy")
plt.show() The nearest neighbor (NN) and its distance to a point is an important feature. You can use find_nearest_neighbor to get the NN and its neighbor, as
# NN distance and the NN neighbor of a point
nn_neighbor, nn_distance = natural_mosaic.find_nearest_neighbor(guy)
# nn_neighbor is the index of the NN neighbor.
# nn_distance is the distance from the point to its NN.You can use get_nns to get NN distances from multiple points, as
# NN distances of effective points
effective_nns = natural_mosaic.get_nns(indices=effective_indices, effective_filter=True)
# NN distances of all points
all_nns = natural_mosaic.get_nns(indices=None, effective_filter=False)Arguments in get_nns methods are
indicesspecific indices of query, default isNoneand return NN of all points,effective_filterReturn only NNs of effective points.
The Mosaic has a draw_nn_graph method to show NN relationships as arcs from points to their NN neighbors.
natural_mosaic.draw_nn_graph(highlights=None, nonhighlight_alpha=0.3, ax_grid=5, draw_plane_grid=False, ax_scaled=True, point_args={"s": 20, "color": "r"}, network_args={"edge_color": "k", "with_labels": False}, ax=None)The draw_nn_graph method share most common arguments with draw_points, except
highlights: Only draw NN graphs with given indices, default isNone(= effective points).network_args: Arguments are delivered into networkx.draw_networkx method to control the properties of the NN graph. NOTE: Arguments with points here have no effect.
Similarly, there are methods to access areas of Voronoi domains of points.
# VD areas of effective points
effective_vds = natural_mosaic.get_vorareas(indices=None, effective_filter=True)
# VD areas of all points
all_vds = natural_mosaic.get_vorareas(indices=None, effective_filter=False)You can use the draw_vds method to show Vornoi domains of a mosaic, as
natural_mosaic.draw_vds(highlights=None, nonhighlight_alpha=0.3, ax_grid=5, ax_scaled=True, plane_args={"facecolor": "gray", "alpha": 0.2}, voronoi_args={"show_points": False, "line_width": 0.5}, point_args={"s": 20, "color": "r"}, ax=None)The draw_vds method share most common arguments with draw_points, except
plane_args: Arguments are delivered into matplotlib.collections.PatchCollection method to control properties of the plane.voronoi_args: Arguments are delivered into scipy.spatial.voronoi_plot_2d method to control properties of VDs.
Based on the values of NN distances and VD areas, you can get regularity indices of the mosaic, as
# Nearest Neighbor Regularity Index
natural_mosaic.NNRI() # 4.966138094971688
# Voronoi Domain Regularity Index
natural_mosaic.VDRI() # 5.790713936276296NOTE: NNRI and VDRI only use values of effective points to calculate RI.
In this section, we use methods in Pattern to analyze features of multiple mosaics and get probability distribution. We use a Feature class to define the feature and interact with Pattern. Please import it as
from OPIPP import FeatureA Feature object requires an argument to decide how to calculate the feature and several arguments for the numpy.histogram.
# NN distance Feature
nn_feature = Feature(method="get_nns", min_value=0, max_value=50, n_bin=20)
# Or a callable method in the definition
# VD area feature
vd_feature = Feature(method=lambda mosaic: mosaic.get_vorareas(), min_value=0, max_value=4000, n_bin=20)The above shows two features containing information on NN distances and VD areas respectively. Arguments here are
method: Define how to calculate the features of a mosaic.- If it is a string, the
Featurewill use the corresponding attribute of the mosaic. For example,nn_featurehere will callmosaic.get_nns()and get values. - If it is a callable function, the
Featurewill callmethod(mosaic)and get values.
- If it is a string, the
max_value: The maximum value for the histogram.min_value: The minimum value for the histogram, default is0.n_bin: The number of bins in the histogram, default is1.
You can use extract_mosaic and extract_mosaics to get feature values through Feature, as
# Same as `natural_mosaic.get_nns()`
features = nn_feature.extract_mosaic(natural_mosaic)
# Or extract features from a list of mosaics
features = nn_feature.extract_mosaics([natural_mosaic, simulated_mosaic])The next step is to let the pattern know the name of the feature, as
pattern.set_feature("NN", nn_feature)
pattern.set_feature("VD", vd_feature)There are several approaches to getting the histogram of probabilities of a feature.
You can estimate the probabilities of values by several methods in Feature. For example, calculate values from a list of mosaics and estimate probabilities:
# get values from mosaics
mosaics = [natural_mosaic]
values = nn_feature.extract_mosaics(mosaics)
# get the probabilities
hist = nn_feature.get_hist(values)
# set the probabilities for optimization
nn_feature.set_target(hist)The pattern has a set_feature_target method that applies the above calculation to its natural mosaics, as
# Give the name of the feature, it will estimate
# probabilities and put into the corresponding feature object
probs = pattern.set_feature_target(feature_label="NN")Besides, the Feature has a view method to draw the histogram of probabilities.
nn_feature.view(bar_args={}, ax=None)where ax decides the specific axes, bar_args(default={}) controls properties of bars and is delivered into the matplotlib.axes.Axes.bar method to draw the above picture.
Alternatively, you can define a numpy.array or a list of probabilities and deliver it into the Feature directly. For example,
# data from (Keeley et al., 2020)
target = np.array([0. , 0. , 0. , 0.0016756 , 0.00670241,
0.02010724, 0.04356568, 0.08713137, 0.11394102, 0.17258713,
0.16253351, 0.16253351, 0.1152815 , 0.06635389, 0.0325067 ,
0.01005362, 0.00268097, 0.00134048, 0.00067024, 0.00033512,
0]) # n_bin=20 but len(target)=21
# The last item represents the probability of values
# larger than the `max_value`.
nn_feature.set_target(target)The above probabilities are calculation results from a population of 28 mosaics. It is more significant and stable in statistics. We use this histogram as the optimization target in later simulations. Here is an example that draws two probabilities with subplots.
ax1 = plt.subplot(121)
probs = pattern.set_feature_target(feature_label="NN")
nn_feature.view(ax=ax1, alpha=0.4, color='gray')
ax1.set_title("Distribution from a mosaic")
ax2 = plt.subplot(122)
nn_feature.set_target(target)
nn_feature.view(ax=ax2, alpha=0.7, color='k')
ax2.set_title("Distribution from a dataset")
plt.show()The Pattern class also has several visualization methods. Before diving into these useful tools, we need complete features in the pattern.
# Set probabilities of VD areas
# Also from (Keeley et al., 2020)
nn_feature.set_target(np.array([0. , 0. , 0.00608906, 0.0617784 , 0.17183275,
0.27966751, 0.27633813, 0.13262011, 0.05992875, 0.0117453 ,
0. , 0. , 0. , 0. , 0. ,
0. , 0. , 0. , 0. , 0. ,
0. ]))
print(pattern)The outputs are
Spatial pattern of Mouse Horizontal Cell,
- Density: Unknown,
- Natural mosaics: 1 case(s),
- Simulated mosaics: total 30 case(s)
0 case(s) in tag 'default',
10 case(s) in tag 'O-PIPP',
20 case(s) in tag 'PIPP',
- Features: 2
Label | Has target probabilities
NN | True
VD | True .
Now, the pattern object has 1 natural mosaic, 30 simulated mosaics with 2 tags, and 2 features with probabilities in both.
The draw feature hist method is for drawing several histograms in the pattern, as
pattern.draw_feature_hist(feature_label="NN", natural_color="skyblue", target_color="gray", simulated_color="red", simulated_tag="O-PIPP", bar_args={}, ax=None)Arguments decide users draw specific histograms and their colors.
feature_label: The name of the feature.natural_color: The color of the histogram from natural mosaics, default="skyblue". If it isNone, the method will not draw the histogram.target_color: The color of the histogram from probabilities, default="gray". If it isNone, the method will not draw the histogram.simulated_color: The color of the histogram from simulated mosaics, default="red". If it isNone, the method will not draw the histogram.simulated_tag: The tag that distinguishes draw which list of simulated mosaics, defalut=default.bar_argsandaxare the same as arguments in Mosiac.view.
With the draw feature hist method and subplots in maplotlib, you can draw histograms to compare features from two tags of simulated mosaics. For example, we plot histograms with NN feature from two groups of simulated mosaics.
# NN features in simulated mosaics with the `O-PIPP` tag
ax1 = plt.subplot(121)
pattern.draw_feature_hist("NN", natural_color=None, target_color="gray", simulated_color="red", simulated_tag="O-PIPP", ax=ax1)
# NN features in simulated mosaics with the `PIPP` tag
ax2 = plt.subplot(122)
pattern.draw_feature_hist("NN", natural_color=None, target_color="gray", simulated_color="red", simulated_tag="PIPP", ax=ax2)
plt.show()The draw_feature_boxes method uses matplotlib.axes.Axes.boxplot to compare values of features among different mosaics.
pattern.draw_feature_boxes(feature_label="NN", draw_natural=True, simulated_tags=["O-PIPP", "PIPP"], box_args={}, ax=None)Arguments in draw_feature_boxes are the same as draw_feature_hist, except the simulated_tags which is a list of tags for drawing. If no specific tags, the method will draw all simulated mosaics.
Compare to methods drawing with raw values, the draw_value_bars method uses another method to compass values into a single index and use matplotlib.axes.Axes.bar to compare values in different groups of mosaics. For example, we define NNRI and VDRI features and compare mean values from two groups of simulated mosaics, as
# The NNRI feature
nnri_feature = Feature("NNRI", 10)
pattern.set_feature("NNRI", nnri_feature)
# The VDRI feature
vdri_feature = Feature("VDRI", 10)
pattern.set_feature("VDRI", vdri_feature)
# Do not require target probabilities
# Sum mean values of two RIs
pattern.draw_value_bars(value_method=np.mean, feature_colors={"NNRI": "r", "VDRI": "b"}, draw_loss=False, draw_natural=False, simulated_tags=["O-PIPP", "PIPP"], bar_args={"width": 0.3}, ax=None)Arguments in the draw_value_bars method are
value_method: A callable function that calculates features into a single float value.feature_colors: A dictionary that features’ label are its keys and corresponding colors are its values.draw_loss: Calculate the Entropy or not, default=True. We introduce related usages in Part 3.draw_natural: Is draw natural mosaics, default=False.simulated_tags: A list of tags for drawing, default=None. If it isNone, the method will draw all simulated mosaics.bar_args: Arguments (default={}) control properties of bars and is delivered into the matplotlib.bar method to draw the above picture.












