canopyhydro package

Submodules

canopyhydro.Cylinder module

Defines the component parts of the ingested QSM

class canopyhydro.Cylinder.Cylinder(cyl_id: int, x: ~numpy.ndarray[~numpy.float32], y: ~numpy.ndarray[~numpy.float32], z: ~numpy.ndarray[~numpy.float32], radius: ~numpy.float32, length: ~numpy.float32, branch_order: int, branch_id: int, volume: ~numpy.float32, parent_id: int, reverse_branch_order: int, segment_id: int, projected_data: dict[str, ~canopyhydro.DataClasses.Projection] = <factory>, flow_id: int | None = None, flow_type: str | None = None, drip_node: int | None = None, begins_at_drip_point: bool | None = None, begins_at_divide_point: bool | None = None, dx: ~numpy.float32 = 0, dy: ~numpy.float32 = 0, dz: ~numpy.float32 = 0, surface_area: ~numpy.float32 = 0.0, sa_to_vol: ~numpy.float32 = 0.0, slope: ~numpy.float32 = 0.0, is_stem: bool = False)

Bases: object

The Cylinder class is used to represent the 3-D cylinders that make up a QSM. Contains several wrappers for functions in ‘geometry’.

cyl_id

The ID of the cylinder.

Type:

int

x

The x-coordinates of the cylinder vertices. Length 2, ordered (start, end)

Type:

np.ndarray[np.float32]

y

The y-coordinates of the cylinder vertices. Length 2, ordered (start, end)

Type:

np.ndarray[np.float32]

z

The z-coordinates of the cylinder vertices. Length 2, ordered (start, end)

Type:

np.ndarray[np.float32]

radius

The radius of the cylinder.

Type:

np.float32

length

The length of the cylinder.

Type:

np.float32

branch_order

The branch order of the cylinder. See QSM documentation for more information.

Type:

int

branch_id

The ID of the branch the cylinder belongs to. See QSM documentation for more information.

Type:

int

volume

The volume of the cylinder.

Type:

np.float32

parent_id

The ID of the parent cylinder. -1 if cylinder is a root cylinder

Type:

int

reverse_branch_order

The reverse branch order of the cylinder. See QSM documentation for more information.

Type:

int

segment_id

The ID of the segment the cylinder belongs to. See QSM documentation for more information.

Type:

int

projected_data

A dictionary containing projected data of the cylinder on the ‘XY’, ‘XZ’ and ‘YZ’ planes. Defaults to an empty dictionary.

Type:

dict(Projection)

flow_id

The ID of the flow to which the cylinder contributes intercepted precipitation. Defaults to None.

Type:

int

flow_type

The type of flow associated with the cylinder (drip or stem). Defaults to None.

Type:

str

drip_node

The ID of the drip node associated with the cylinder. Defined by an ID correlating to the node_id of the node in the containing CylinderCollection’s graph . Defaults to None.

Type:

int

begins_at_drip_point

Indicates if (x[0],y[0],z[0]) at a drip point. Defaults to None.

Type:

bool

begins_at_divide_point

Indicates if (x[0],y[0],z[0]) at a dividepoint. Defaults to None.

Type:

bool

dx

The change in x-coordinate: x[1] - x[0]. Defaults to 0.

Type:

np.float32

dy

The change in y-coordinate: y[1] - y[0]. Defaults to 0.

Type:

np.float32

dz

The change in z-coordinate: z[1] - z[0]. Defaults to 0.

Type:

np.float32

surface_area

The surface area of the cylinder. Defaults to 0.0.

Type:

np.float32

sa_to_vol

The ratio of surface area to volume of the cylinder. Defaults to 0.0.

Type:

np.float32

slope

The slope of the cylinder, the rise over run in 3 dimensions. Defaults to 0.0.

Type:

np.float32

is_stem

Indicates if the cylinder contributes to stem flow. Defaults to False.

Type:

bool

begins_at_divide_point: bool = None
begins_at_drip_point: bool = None
branch_id: int
branch_order: int
cyl_id: int
draw(plane: str = 'XY', **kwargs)

A wrapper around the draw_cyl function allowing more readable code for drawing a single cylinder. e.g. For some Cylinder ‘cyl’ cyl.draw() replaces geometry.draw_cyls([cyl])

Parameters:

plane – The projection of the cylinder to draw. ‘XY, ‘XZ’, or ‘YZ’. Defaults to “XY”.

draw_3D(**kwargs)

Draws the cylinder in 3D space

drip_node: int = None
dx: float32 = 0
dy: float32 = 0
dz: float32 = 0
flow_id: int = None
flow_type: str = None
get_projection(plane='XY')

Calculates the projection of the cylinder on the requested plane

Parameters:
  • self (Cylinder) – Cylinder to be projected

  • plane (str, optional) – Plane on which to project the cylinder. Defaults to “XY”.

References

projected_data.polygon (shapely.Polygon):

represents the shape formed by projecting the cylinder (self) onto the given plane

projected_data.base_vector (list[float]):

cylinder vector *after projection (oriented away from cylinder base)

projected_data.anti_vector (list[float]):

cylinder vector *after projection (oriented towards cylinder base)

projected_data.angle (float):

angle (in radians) of cylinder vector with given axis. Between -pi/2 and pi/2.

projected_data.area (float) - area of polygon (see above) projected_data.xy_area: float

  • polygon formed by projecting the cylinder

    onto the XY plane

Returns:

projected_data[polygon]

Return type:

(shapely.Polygon)

Examples

>>> import numpy as np
>>> from canopyhydro.Cylinder import Cylinder
>>> cyl = Cylinder(1, np.array([0, 1]), np.array([0, 1]), np.array([0, 1]), 1, 1, 0, 0, 1, 0, 0, 0)
>>> cyl.get_projection("XY")
>>> print(cyl.projected_data['XY']['polygon'])
POLYGON ((0.7055547485197222 -0.,....)
>>> print(cyl.projected_data['XY']['base_vector'])
[0.57735027 0.57735027 0.57735027]
>>> print(cyl.projected_data['XY']['anti_vector'])
[-0.57735027 -0.57735027 -0.57735027]
>>> print(cyl.projected_data['XY']['angle'])
0.6154797086703873
>>> print(cyl.projected_data['XY']['area'])
4.642087600836025
initialize()

Initializes remaining attributes based off of the attributes provided at object creation

References

  • self.x, self.y, self.z

  • self.dx, self.dy, self.dz

  • self.radius, self.length

  • self.volume

  • self.surface_area

  • self.sa_to_vol

  • self.angle

  • self.xy_area

is_stem: bool = False
length: float32
parent_id: int
projected_data: dict[str, Projection]
radius: float32
reverse_branch_order: int
sa_to_vol: float32 = 0.0
segment_id: int
slope: float32 = 0.0
surface_area: float32 = 0.0
volume: float32
x: ndarray[float32]
y: ndarray[float32]
z: ndarray[float32]
canopyhydro.Cylinder.create_cyl(arr: array)
Creates a cylinder based off of an input array.

Enables user defined file structure via configuration yml file

Parameters:

arr (np.array) – Array containing attribute data for a single cylinder. Attributes must be ordered as per qsm_cols in canopyhydro_config.yml

Examples

>>> import numpy as np
>>> from canopyhydro.configuration import qsm_cols
>>> print(qsm_cols)
{'cyl_id': 1, 'parent_id': 2, 'x': [3, 6], 'y': [4, 7], 'z': [5, 8],
'radius': 9, 'volume': 10, 'length': 12, 'segment_id': 15, 'branch_order': 20,
'reverse_branch_order': 21, 'branch_id': 24}
>>> myCyl = create_cyl(
>>>    np.array([np.nan, 1, 0, -2.372914, 2.875943, -0.55, -2.382034, 2.887813,
>>>    -0.452896, 0.277545, 0.023777, 4.755711, 0.098251, 3880.839667,
>>>    np.nan, 0, -1, 0.240459, 4.604282, 3880.04742, 0, 41, 84.320816,
>>>    7110, 0, 0, np.nan, 0, 0, 0, 0.01, 0.401606, 0, 0.01, 0.401606])
>>> )
>>> print(myCyl)
Cylinder( cyl_id=1.0, x=[-2.372914 -2.382034], y=[2.875943 2.887813], z=[-0.55     -0.452896], radius=0.277545, length=0.098251, branch_order=0.0, branch_id=0.0, volume=0.023777, parent_id=0.0, reverse_branch_order=41.0, segment_id=0.0

canopyhydro.CylinderCollection module

class canopyhydro.CylinderCollection.CylinderCollection

Bases: object

CylinderCollections represent QSM’s or sections thereof, but with additional structure. A CylinderCollection is initialized from a .csv file and can:

  • Project cylinders onto the XY, XZ, and YZ planes

  • Determine which precipitation partition water intercepted by each of its cylinders will flow into.

  • Find common tree characteristics: DBH, trunk lean, etc.

  • Calculate occlusion for given cross sections of the canopy

  • Draw detailed figures representing the canopy watershed, with: Cylinders in 3D or projected on to the XY, XZ, or YZ planes, Drip points (areas of dense throughfall) and or Alpha shapes (concave hulls) around arbitrary parts of the canopy

file

The path to the .csv file used to initialize the CylinderCollection. Defaults to “”.

Type:

str

surface_area

The total surface area of all cylinders in the collection. Defaults to np.nan.

Type:

float

file_name

The name of the .csv file used to initialize the CylinderCollection. Defaults to “”.

Type:

string

volume

The total volume of all cylinders in the collection. Defaults to np.nan.

Type:

float

avg_sa_to_vol

The average ratio of surface area to volume for the cylinders in the collection. Defaults to np.nan.

Type:

float

max_branch_order

The maximum branch order in the collection. Defaults to np.nan.

Type:

float

max_reverse_branch_order

The maximum reverse branch order in the collection. Defaults to np.nan.

Type:

float

extent

The minimum and maximum coordinates of the cylinders in the collection. Defaults to {

“min”: [np.nan, np.nan, np.nan], “max”: [np.nan, np.nan, np.nan],

}.

Type:

dict

treeQualities
Various characteristics of the tree represented by the collection. Defaults to {

“total_psa”: None, “tot_hull_area”: None, “stem_flow_hull_area”: None, “stem_psa”: None, “flowStats”: None, “dbh”: None, “tot_surface_area”: None, “stem_surface_area”: None,

Type:

dict

}.
projections

Whether the cylinders have been projected onto the XY, XZ, and YZ planes. Defaults to {

“XY”: False, “XZ”: False, “YZ”: False }.

Type:

dict

hulls

Whether hulls have been calculated for the projections onto the XY, XZ, and YZ planes. Defaults to {

“XY”:False, “XZ”: False, “YZ”: False

}.

Type:

dict

stem_hull

The hull of the stem of the tree. Defaults to None.

Type:

shapely.Polygon

stem_paths

The paths along the stem of the tree. Defaults to [[]].

Type:

list

trunk

The cylinders that make up the trunk of the tree. Defaults to [].

Type:

list

graph

The graph representation of the tree. Defaults to None.

Type:

nx.Graph

digraph

The directed graph representation of the tree. Defaults to None.

Type:

nx.Digraph

end_nodes

The nodes at the ends of the branches of the tree. Defaults to [].

Type:

list

flows

The flows of water intercepted by the cylinders. Defaults to None.

Type:

list[Flow]

divide_nodes

The nodes at which the flows divide. Defaults to None.

Type:

list[int]

drip_nodes

The nodes at which water drips from the tree. Defaults to None.

Type:

list[int]

cyl_to_drip

A mapping from cylinders to drip points. Defaults to None.

Type:

dict[int,int]

drip_points

The coordinates and flow ids of the drip points. Defaults to {

“x”: np.nan, “y”: np.nan, “z”: np.nan, “flow_id”: np.nan }.

Type:

dict[str,list]

trunk_nodes

The nodes that make up the trunk of the tree. Defaults to [].

Type:

list

drip_point_loc

The locations of the drip points. Defaults to None.

Type:

list

stem_flow_component

The component of the graph representing stem flow. Defaults to None.

Type:

nx.Graph

drip_graph

The graph representing the flow of drips. Defaults to None.

Type:

nx.Graph

drip_flow_components

The components of the drip graph. Defaults to None.

Type:

list[nx.Graph]

flow_chars
Characteristics of the flows: num_cylinders, projected_area,

surface_area, angle_sum, volume, sa_to_vol, drip_node_id, drip_node_loc.

Defaults to {}.

Type:

dict

trunk_lean

The angle of lean of the trunk. Defaults to None.

Type:

float

calculate_flows(plane: str = 'XY')
Based on the findings of ‘find_flows’, sums the qualities of

all of the cylinders in each flow and stores the results in flow objects.

Parameters:

plane – The projection for which to source the angle and projected area data sumed. Valid values are “XY”, “XZ”, “YZ”, and “3D”.

contracted_nodes(node_list, next_node, G) tuple

Returns a graph made from removing nodes from G, and connecting the removed nodes’ neighbors via an edge

Parameters:
  • node_list – Nodes to be removed from the graph and connected to the next node.

  • next_node – The node to which the removed nodes should be connected.

  • G – The graph on which to carry out the operation

Returns:

A graph with the listed nodes removed and their neighbors connected to the next node. list: A list of the neighbors of the removed nodes

Return type:

nx.Graph

cylinders

alias of dict

direction_from_trunk(cyl: Cylinder)

Returns an array representing the direction of the cylinder from the trunk.

Parameters:

cyl – the cylinder for which to determine the direction from the trunk.

Returns:

A length 3 tuple corresponding the the x, y and z location of the cylinder. For each, a value of -1 indicates the cylinders location on the given axis

is less than the trunk’s location on the same axis.

Return type:

tuple

draw(plane: str = 'XY', highlight_lambda: ~typing.Callable = <function CylinderCollection.<lambda>>, filter_lambda: ~typing.Callable = <function CylinderCollection.<lambda>>, include_drips: bool = False, include_alpha_shape: bool = False, overlay_transparency: float = 0.5, file_name_ext: str = '', **kwargs)

Draws cylinders meeting given characteristics onto the specified plane.

Parameters:
  • plane – The plane to draw the cylinders on. Valid values are “XY”, “XZ”, “YZ”, and “3D”.

  • highlight_lambda – A lambda function that determines which cylinders to highlight. Takes no inputs but may reference any attribute of a cylinder object.

  • filter_lambda – A lambda function that determines which cylinders to include in the drawing. Takes no inputs but may reference any attribute of a cylinder object.

  • include_drips – If True, includes the most recently set drip points in the drawing. Default is False.

  • include_alpha_shape – If True, includes the most recently created alpha shape in the drawing. Default is False.

  • overlay_transparency – Determines the transparency of the drip points and alpha shape drawn. Default is 0.5,

  • file_name_ext – A suffix and/or the file extension to use for the output file. Default is an empty string.

  • **kwargs

  • function. (Additional keyword arguments to pass to the drawing)

find_flow_components(save_components: bool | None = False)
Determines to which partition perciplitation intercepted by

each cylinder in the collection is likely to contribute to.

That is, viewing each cylinder as a source, and allowing travel on the

digraph as defined by the edge’s direction, the function determines: - the set of nodes that can be reached from each source node. - for each set of nodes (each, ‘flow’) the eventual sink (or drip nodes)

to which the theoretical flow is directed

Parameters:

save_components – If true, the stemflow and drip components of the collection’s graph are saved. This is rather memory intensive so this input defaults to False.

Raises:

TypeError – Raised if the function is called on an undirected graph.

find_furthest(nodes)

Finds the furthest node in the given list from the provided n

find_overlap_by_percentile(plane: str = 'XY', percentiles: list[int] = [25, 50, 75])
Groups the projected polygons of the collection’s cylinders

by percentiles given - with respect to their z values.

Passes the list of grouped polygons to the get_projected_overlap function

to get the overlap percentages between the groups.

See get_projected_overlap for more information.

Parameters:
  • plane – Plane of projection from which to source the polygons. Defaults to “XY”.

  • percentiles – Percentiles defining the groups passed to get_projected_overlap. Expected to be strictly increasing. Defaults to [25, 50, 75].

Returns:

Each dicitonary corresponding to a percentile, with metrics describing the overlap between the polygons in that percentile {

”sum_area”: sum of areas of the polygons in the percentile, “effective_area”: the area of the union of the polygons in the percentile, “internal_overlap”: sum_area - effective_area, “overlap_with_previous”: the area of the overlap between the polygons in the percentile,

with the polygons in the previous percentile,

}

Return type:

list[dict]

find_trunk_distances() dict

Finds the distance in the graph (in number of nodes) between each node and the closest trunk node

find_trunk_lean()
Defines a straight line from base to tip of the trunk then

finds the angle of that line from the XZ plane

from_csv(file: TextIOWrapper | str) None
Initializes a new Cylinder Collection based on the QSM data.

the csv file is read in with the columns mapped to the configured column locations.

Parameters:

file – The file object or file name to read the data from.

generate_flow_file(file_name_ext)

Creates a csv and dictionary containing data describing the flows calculated in find_flow_components and calculate_flows

Parameters:

file_name_ext – the naming suffix to used for the saved file name

Returns:

A dictionary containing the flow data

Return type:

dict

get_collection_data() list[str]

Returns a list of string representations of the cylinders in the collection.

Returns:

A list of string representations of the cylinders.

Return type:

list[str]

get_dbh() float

Calculate and return the diameter at breast height (DBH) of the tree.

Returns:

The diameter at breast height (DBH) of the tree.

Return type:

float

get_end_nodes() list[int]

Returns a list of end nodes in the graph.

If the end nodes have already been computed, it returns the saved result. Otherwise, it computes the end nodes by finding nodes with a degree of 1 in the graph.

Returns:

A list of end nodes in the graph.

get_trunk_nodes() list[int]

Returns a list of trunk nodes in the digraph.

If the trunk nodes have already been computed, it returns the saved result. Otherwise, it computes the trunk nodes based on the branch order of the cylinders.

Returns:

A list of node ids for trunk nodes in the digraph.

identify_stem_paths()

Identifies the paths in the collection’s graph by which the root node can be reached.

initialize_digraph_from(in_flow_grade_lim=-0.16666)

This function creates a directed graph and its undirected counterpart. Initializes edge attributes as cylinder objects

Parameters:
  • in_flow_grade_lim – The drip edge cut off angle.

  • file. (Defaults to the in_flow_grade_lim from the configuration)

project_cylinders(plane: str = 'XY') None

Projects cylinders onto the specified plane.

Parameters:

plane (str) – The plane to project the cylinders onto. Valid values are “XY”, “XZ”, and “YZ”.

set_drip_points(percentile: int = 90)

Returns the locations of the drip points. **Drip points are identified as the subset of drip nodes

with a value for the provided metric in the percentile given

statistics(plane: str = 'XY', file_name_ext: str = '')
Generates a csv and dictionary containing a variety of descriptive

statistics about the collection of cylinders.

Parameters:
  • plane – The plane used for projection dependent statistics. Defaults to “XY”.

  • file_name_ext – the naming suffix to used for the saved file name

Returns:

_description_

watershed_boundary(plane: str = 'XY', filter_lambda: Callable | None = None, curvature_alpha: float64 = 1.8, draw: bool = False, save: bool = False, file_name_ext: str = '') None

Generates tightly fit concave_hull (alpha shape) around the passed component.

Parameters:
  • component – The component for which to generate the watershed boundary. If None, the entire digraph is used.

  • plane – The plane in which to generate the watershed boundary. Defaults to “XY”.

  • filter_lambda – A lambda function that determines which cylinders to include in the drawing. Takes no inputs but may reference any attribute of a cylinder object.

  • curvature_alpha – The alpha value that determines the tightness of the fit of the shape. Too low an alpha results in multiple shapes. Defaults to 2.

  • draw – If True, the hull polygon is drawn via matplotlib. Defaults to False.

  • save – If True, the hull is drawn and saved. Defaults to False.

  • file_name_ext – The file extension to add to the end of the file name when when saving the drawn hull. Defaults to an empty string.

Returns:

None

canopyhydro.CylinderCollection.pickle_collection(collection: CylinderCollection, file_name_ext: str = '')

Pickles a collection to a file so that it may be read into a CylinderCollection object at a later time.

Parameters:
  • collection – The collection to pickle.

  • file_name_ext – the naming convention to used for the saved file name i.e. For a collection w/ file name ‘myQSM.csv’ and file_name_ext ‘test_run’ the file created will be ‘myQSM_test_run.pickle’

Example

For a collection w/ file name ‘myQSM.csv’ and file_name_ext

‘test_run’ the file created will be ‘myQSM_test_run.pickle’

Returns:

The path and file name for the the pickled file.

Return type:

file_path (str)

Raises:
  • FileNotFoundError – If the file does not exist.

  • pickle.UnpicklingError – If there is an error while unpickling the file.

canopyhydro.CylinderCollection.unpickle_collection(file_name: str) CylinderCollection

Unpickles a collection from a file.File assumed to be generated by ‘pickle_collection’ method

Parameters:

file_name (str) – The name of the file to unpickle. Optionally, the full path to the file.

Returns:

The unpickled collection.

Return type:

db

Raises:
  • FileNotFoundError – If the file does not exist.

  • pickle.UnpicklingError – If there is an error while unpickling the file.

canopyhydro.DataClasses module

class canopyhydro.DataClasses.Flow(num_cylinders: 'int', projected_area: 'np.float64', surface_area: 'np.float64', angle_sum: 'np.float64', volume: 'np.float64', sa_to_vol: 'np.float64', drip_node_id: 'int', drip_node_loc: 'tuple')

Bases: object

angle_sum: float64
drip_node_id: int
drip_node_loc: tuple
num_cylinders: int
projected_area: float64
sa_to_vol: float64
surface_area: float64
volume: float64
class canopyhydro.DataClasses.Projection(plane: 'str', polygon: 'Polygon', base_vector: 'list[int]', anti_vector: 'list[int]', angle: 'int')

Bases: object

angle: int
anti_vector: list[int]
base_vector: list[int]
plane: str
polygon: Polygon

canopyhydro.Forester module

class canopyhydro.Forester.Forester(directory='./')

Bases: object

get_file_names()
qsm_to_collection(file_name: str = 'All', directory: Path = '')
Creates a Cylinder collection from the given file

and adds the collection to the Forester object

Parameters:
  • file_name (str) – Name of the csv file containing QSM data for the desired cylinder collection

  • directory (str, optional) – File directory in which the specified file is located. Defaults to input_dir.

canopyhydro.configuration module

canopyhydro.geometry module

Spacially centeric code

canopyhydro.geometry.circumcenter_lapack(points: list[tuple[float64]] | ndarray) ndarray

Calculate the circumcenter of a set of points relative to simplex https://en.wikipedia.org/wiki/Polarization_identity

canopyhydro.geometry.circumcenter_lu_factor(points: list[tuple[float64]] | ndarray) ndarray

Calculate the circumcenter of a set of points relative to simplex Theoretically less efficient than LAPACK (O(n^3) + O(n^2) v. O(n^2)) when a given set of equations (e.g. set of points, A ) only needs to be solved for a single vector (e.g b)

canopyhydro.geometry.circumradius(points: list[tuple[float64]] | ndarray, center: ndarray = []) float32

Calculte the radius of the circle in which the given polygon may be inscribed

canopyhydro.geometry.closest_points(point: tuple, points: array, num_returned: int = 3)

Finds the closest point in the list ‘points’ from the input ‘point’

canopyhydro.geometry.concave_hull(boundary_points, alpha: int = 0)

alpha shape / concave hull Creates a delaunay triangulation on the set of points. Using this triangulation, returns a minimal concave polygon with a concavity factor alpha see: trunk_lean

canopyhydro.geometry.draw_cylinders_3D(radii: int, vector_start_ends: list, save: bool = False, show: bool = False, draw_vectors=False, draw_projections=False, file_name_ext: str = '3Ddraw')

Draws a single Cylinder in 3 dimensions

canopyhydro.geometry.draw_cyls(collection: list, colors: list[bool] = [True], save: bool = False, file_name_ext: str = '', overlay: list | None = None, overlay_transparency: float | None = None, show: bool = False)

Draws a collection of cylinders in 2 dimensions

canopyhydro.geometry.furthest_point(point: tuple, points: array)

Finds the furthest point in the list ‘points’ from the input ‘point’

canopyhydro.geometry.get_cylinder_surface(radius, vector_start_end)

Returns points on the surface of the cylinder defined by the givent start and end points having the given radius

canopyhydro.geometry.get_projected_overlap(shading_poly_list: list[list[Polygon]], labels: list) dict
Takes in a list of lists of polygons, w/

each list representing a diff percentile grouping of polygons (e.g. grp1:(0%-25%), grp2:(25%, 50%)…)

Consider the case in which our percentiles are defined by height, with the first grouping being cylinders in the xth %ile y height, thus being under than cylinders in all of the other groupings In this case, this function calculates the area of shade cast by each grouping on the below sections. As such, in each loop ‘shading_poly_list’ is partitioned into 2 categories: The sections of canopy on which shade is being cast and the sections of canopy that are casting that shade. After each loop, a new section of canopy is moved from the ‘shading’ group to the ‘shaded’ group and a new calculation of shaded area is made. The result is a cumulative sum of shaded area at various heights in the canopy.

Note

shapely’s intersection function could be used, and would be slightly more accurate. However, it is also rather slow for the intersection of this many shapes

Returns:

Each dicitonary corresponding to a percentile, with metrics describing the overlap between the polygons in that percentile

Return type:

list[dict]

Example

Result = {

“sum_area”: sum of areas of the polygons in the percentile, “effective_area”: the area of the union of the polygons in the percentile, “internal_overlap”: sum_area - effective_area, “overlap_with_previous”: the area of the overlap between the polygons in the percentile,

with the polygons in the previous percentile,

}

canopyhydro.geometry.get_projection(vector: list, magnitude: list, radius: float())

Takes in the vector (starting point), magnitude and radius that fully define a cylinder. Finds the projection of the cylinder on a plane

Some linear algebra/diff eq could help us find this for an arbitrary plane.

canopyhydro.geometry.get_rotation_matrix(b: array)
canopyhydro.geometry.get_unoriented_cylinder(r, h, noCirPoints=20, nv=20)
Given the radius (r) and height (h), returns the parameterization of a cylinder

centered on the z axis, with a base at the origin and oriented vertically

canopyhydro.geometry.maximal_alpha(boundary_points: list[tuple[float64]] | ndarray, union_poly: Polygon) float32

Finds the minimal alpha shape for the given coord list that still contains the given polygon

canopyhydro.geometry.polygon_plot(ax, polys: list | Polygon, **kwargs)
canopyhydro.geometry.simplices(points: list[tuple[float64]] | ndarray) list[tuple[float64]] | ndarray

Yields simpicies and radius

canopyhydro.handlers module

class canopyhydro.handlers.ConsoleHandler(stream=None, highlighter: Highlighter | None = None, styles: dict[str, str] | None = None, level: int | str = 0)

Bases: StreamHandler

HIGHLIGHTER_CLASS

alias of ReprHighlighter

emit(record: LogRecord)

Emit a record.

If a formatter is specified, it is used to format the record. The record is then written to the stream with a trailing newline. If exception information is present, it is formatted using traceback.print_exception and appended to the stream. If the stream has an ‘encoding’ attribute, it is used to determine how to do the output to the stream.

canopyhydro.import_options module

canopyhydro.utils module

canopyhydro.utils.create_dir_and_file(filename) None
canopyhydro.utils.del_dir(filename) None
canopyhydro.utils.intermitent_log(prog: int, whole: int, msg: str, freq: int = 0.0001)
canopyhydro.utils.lam_filter(objects, a_lambda: Callable, return_all: bool = False)

Takes in a lambda that filters on cylinder attrs returns a list of cylinders for which that lambda func returns true

Parameters:

return_all (bool) – if true, returns all cylinders along with a boolean array of the same length w/ the results of the lambda function passed

Example

lam_filter(cylinders, lambda: diameter > 0.5) returns: all cylinders with diameter > 0.5

canopyhydro.utils.non_njit_stack(to_stack: list[array], col: bool = True)
canopyhydro.utils.on_rm_error(path)
canopyhydro.utils.read_file_names(file_path='./')

Reads in filenames to list

canopyhydro.utils.save_file(file: str, out_file: dict | list[dict], overwrite: bool = False, fileFormat: str = '.csv', method: str = '')

A somewhat overly complex file saving function. If file exists and overwrite = false, it will append to the file

Parameters:
  • file – str The name of the file to write to

  • out_file – Union[dict, list[dict]] The data to write to the file

  • overwrite – bool Whether or not to overwrite the file if it exists

  • fileFormat – str The file format to save the file as ()

  • method – str

Note

‘agg*’ variables intended to support future

updates - adding additional write to an append only file for better history tracking

canopyhydro.utils.stack(to_stack: list[array], col: bool = True)

A wrapper for njit stack that handles errors and allows for less strict typing

Module contents