Source code for gustaf.create.edges
"""gustaf/create/edges.py
Routines to create edges.
"""
import numpy as np
from gustaf import utils
from gustaf.edges import Edges
[docs]
def from_data(gus_obj, data, scale=None, data_norm=None):
"""
Creates edges from gustaf object with vertices.
Data can be either multi-dim array-like data or a str describing a name
of vertex_data that belongs to given gustaf object.
len(gus_obj.vertices) number of edges will be created, where origin and
end of each edge is created using the following scheme:
[[vertices[0], vertices[0] + (array_data[0] * scale)], ...].
By default, scaling value will be
max([1, (aabb_diagonal_norm * 0.1 / max_data_norm)]).
If there's dimension mismatch between vertices and the data, will append
zero paddings!
Parameters
----------
gus_obj: Vertices
gus.Vertices or its derived classes
data: str or (n_vertices, d) array-like
If str, will be considered as data_name and search for saved vertex_data.
scale: float
Absolute value.
data_norm: float or array-like
If float, will be considered as max_norm of the data. Else, searches for
max value. Doesn't enforce len to match.
Returns
-------
data_arrow: Edges
"""
if not isinstance(gus_obj, Edges.__boundary_class__):
raise TypeError(
"Invalid input. Expecting gus.Vertices or its subclasses"
)
# get origin and increment (= array_data * scale)
origin = gus_obj.const_vertices
if isinstance(data, str):
# will raise if data doesn't exist
increment = gus_obj.vertex_data[data]
elif isinstance(data, (tuple, list, np.ndarray)):
increment = np.asanyarray(data)
if len(increment) != len(origin):
raise ValueError(
f"Data length mismatch: expected ({len(origin)}) / "
"given ({len(increment)})"
)
else:
raise TypeError(f"Couldn't process {type(data)}-data as input.")
# data dim check
inc_dim = increment.shape[1]
origin_dim = origin.shape[1]
if inc_dim == 1:
# if data is scalar, it should be addable to any vertices
utils.log.debug(
f"gus.create.edges.from_data() - requested data ({data}) is",
"scalar. Edge orientation will be [1,1,..,1].",
)
elif inc_dim != origin_dim:
# match data and vertex dim.
utils.log.debug(
"gus.create.edges.from_data() - dimension mismatch between",
f"vertices ({origin_dim}) and data ({inc_dim}). Matching",
"dimension by appending zeros.",
)
dim_diff = int(inc_dim - origin_dim)
zero_pad = np.zeros((len(origin), abs(dim_diff)))
if dim_diff > 0:
origin = np.hstack((origin, zero_pad))
else:
increment = np.hstack((increment, zero_pad))
# apply default scale
if scale is None:
if isinstance(data, str):
norm = gus_obj.vertex_data.as_scalar(data, None, True)
else:
# compute
if data_norm is None:
norm = np.linalg.norm(increment, axis=1)
else:
norm = np.asanyarray(data_norm)
max_data_norm = norm.max()
aabb_diagonal_norm = gus_obj.bounds_diagonal_norm()
scale = min((1.0, aabb_diagonal_norm * (0.1) / max_data_norm))
utils.log.debug(
f"creating edges from data with scaling factor ({scale})"
)
# by here, this should be good to go
vs = np.hstack((origin, origin + (increment * scale))).reshape(
-1, origin.shape[1]
)
return Edges(vs, utils.connec.range_to_edges(len(vs), continuous=False))