Reporting
Output generation: charts, PDFs, PowerPoint, hex cartograms, 3D maps, branded multi-client reports.
Reporting utilities — lazy-loaded.
Comprehensive PDF and PowerPoint report generation with client branding. All submodules load on first attribute access via PEP 562 __getattr__.
- class siege_utilities.reporting.TitlePageTemplate[source]
Bases:
objectProfessional title page generator for siege utilities reports
- __init__(canvas_obj, page_size=None)[source]
- Parameters:
canvas_obj (canvas.Canvas)
page_size (tuple)
- siege_utilities.reporting.create_title_page(canvas_obj, title, subtitle='', report_period='', prepared_by='', client_name='', additional_info=None, page_size=None)[source]
Convenience function to create a title page.
- Parameters:
canvas_obj (canvas.Canvas) – ReportLab canvas object
title (str) – Main report title
subtitle (str) – Report subtitle
report_period (str) – Date range or period
prepared_by (str) – Who prepared the report
client_name (str) – Client name
additional_info (Dict[str, str]) – Additional information to display
page_size (tuple) – Page size tuple (default: letter)
- Return type:
None
- class siege_utilities.reporting.TableOfContentsTemplate[source]
Bases:
objectProfessional table of contents generator for siege utilities reports
- __init__(canvas_obj, page_size=None)[source]
- Parameters:
canvas_obj (canvas.Canvas)
page_size (tuple)
- create_table_of_contents(sections, title='Table of Contents', page_number=2)[source]
Create a professional table of contents page.
- Parameters:
- Return type:
None
- Section format:
- {
‘title’: ‘Executive Summary’, ‘page’: 3, ‘subsections’: [ # Optional
{‘title’: ‘Key Findings’, ‘page’: 3}, {‘title’: ‘Recommendations’, ‘page’: 4}
]
}
- siege_utilities.reporting.create_table_of_contents(canvas_obj, sections, title='Table of Contents', page_number=2, page_size=None)[source]
Convenience function to create a table of contents page.
- siege_utilities.reporting.generate_sections_from_report_structure(report_structure)[source]
Generate TOC sections from a report structure dictionary.
- class siege_utilities.reporting.ContentPageTemplate[source]
Bases:
objectProfessional content page generator for siege utilities reports
- __init__(canvas_obj, page_size=None)[source]
- Parameters:
canvas_obj (canvas.Canvas)
page_size (tuple)
- start_page(page_title, page_number, section_name='')[source]
Start a new content page with header and setup.
- add_paragraph(text, font_size=11, text_color=None, line_spacing=1.2)[source]
Add a paragraph of text to the page
- add_table(data, headers=None, table_title='', sort_by=None, sort_order='asc')[source]
Add a table to the page.
- siege_utilities.reporting.create_content_page(canvas_obj, page_title, page_number, content_sections, section_name='', page_size=None)[source]
Convenience function to create a complete content page.
- Parameters:
- Return type:
None
- Content sections format:
- [
{‘type’: ‘title’, ‘text’: ‘Section Title’}, {‘type’: ‘paragraph’, ‘text’: ‘Paragraph text…’}, {‘type’: ‘table’, ‘data’: [[…]], ‘headers’: […], ‘title’: ‘Table Title’}, {‘type’: ‘bullets’, ‘items’: [‘Item 1’, ‘Item 2’]}, {‘type’: ‘spacing’, ‘points’: 20}
]
- class siege_utilities.reporting.ChartGenerator[source]
Bases:
BaseChartEngine,BarChartMixin,MapChartMixin,StatsChartMixin,CompositeChartMixinGenerates charts and visualizations for reports using matplotlib, seaborn, plotly, and folium. Supports pandas DataFrames, Spark DataFrames, and various data sources.
All chart methods are provided by engine mixins:
BaseChartEngine —
__init__, scaling, placeholder, save/convert helpersBarChartMixin — bar, line, pie, proportional text bar charts
MapChartMixin — choropleth, marker, 3D, heatmap-map, cluster, flow, bivariate maps
StatsChartMixin — statistical heatmap, scatter plot, text heatmap
CompositeChartMixin — convergence diagram, dashboard, summary charts, subplots
- class siege_utilities.reporting.ChartTypeRegistry[source]
Bases:
objectRegistry for chart types and their implementations. Provides easy extension and customization of chart types.
- register_chart_type(chart_type)[source]
Register a new chart type.
- Parameters:
chart_type (ChartType) – ChartType object to register
- create_chart(chart_type_name, **kwargs)[source]
Create a chart using the specified chart type.
- Parameters:
chart_type_name (str) – Name of the chart type (must exist in the registry).
**kwargs – Parameters for the chart; must include every entry in the chart type’s
required_parameters.
- Return type:
matplotlib.figure.Figure
- Raises:
UnknownChartTypeError – If
chart_type_nameisn’t registered.ChartParameterError – If required parameters are missing.
ChartCreationError – If the chart type has no create function, or the create function raised.
- add_chart_creator(chart_type_name, create_function)[source]
Add or update the create function for a chart type.
- validate_chart_parameters(chart_type_name, **kwargs)[source]
Validate parameters for a chart type without creating the chart.
- Parameters:
chart_type_name (str)
**kwargs – Chart parameters to validate against the chart type’s
required_parameters. If the chart type defines a customvalidate_function, all kwargs are forwarded to it.
- Returns:
True iff required params present AND any custom
validate_functionreturns truthy.- Return type:
- Raises:
UnknownChartTypeError – If
chart_type_nameisn’t registered. (Legitimately-missing validation returns False; unknown chart type is a caller error.)ChartParameterError – If the custom validate function raised.
- siege_utilities.reporting.create_bar_chart(data, x_column=None, y_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a bar chart.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
x_column (str | None) – Column name for x-axis
y_column (str | None) – Column name for y-axis
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.create_line_chart(data, x_column=None, y_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a line chart.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
x_column (str | None) – Column name for x-axis
y_column (str | None) – Column name for y-axis
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.create_scatter_plot(data, x_column=None, y_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a scatter plot.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
x_column (str | None) – Column name for x-axis
y_column (str | None) – Column name for y-axis
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.create_pie_chart(data, label_column=None, value_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a pie chart.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
label_column (str | None) – Column name for labels
value_column (str | None) – Column name for values
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.create_heatmap(data, x_column=None, y_column=None, value_column=None, title='', width=8.0, height=6.0, **kwargs)[source]
Standalone function to create a heatmap.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_column (str) – Column name for Y-axis
value_column (str) – Column name for values
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
**kwargs – Additional arguments to pass to create_heatmap
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.create_choropleth_map(data, location_column=None, value_column=None, title='', width=8.0, height=6.0, map_type='world', **kwargs)[source]
Standalone function to create a choropleth map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
location_column (str) – Column name for locations (country codes, state names, etc.)
value_column (str) – Column name for values to color by
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
map_type (str) – Type of map (“world”, “usa”, “europe”, etc.)
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.create_bivariate_choropleth(data, x_column=None, y_column=None, geoid_column='geoid', title='Bivariate Choropleth Map', width=12.0, height=8.0, **kwargs)[source]
Standalone function to create a bivariate choropleth map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis variable
y_column (str) – Column name for Y-axis variable
geoid_column (str) – Column name for geographic identifiers
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.create_marker_map(data, latitude_column=None, longitude_column=None, value_column=None, label_column=None, title='', width=10.0, height=8.0, map_style='open-street-map', zoom_level=10, **kwargs)[source]
Standalone function to create a marker map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
value_column (str) – Column name for values (optional)
label_column (str) – Column name for labels (optional)
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
map_style (str) – Map style
zoom_level (int) – Initial zoom level
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.create_flow_map(data, origin_lat_column=None, origin_lon_column=None, dest_lat_column=None, dest_lon_column=None, flow_value_column=None, title='', width=12.0, height=10.0, **kwargs)[source]
Standalone function to create a flow map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
origin_lat_column (str) – Column name for origin latitude
origin_lon_column (str) – Column name for origin longitude
dest_lat_column (str) – Column name for destination latitude
dest_lon_column (str) – Column name for destination longitude
flow_value_column (str) – Column name for flow values (optional)
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.create_convergence_diagram(sources, hub_label='Unified Hub', outputs=None, title='Convergence Diagram', width=10.0, height=6.0, **kwargs)[source]
Standalone function to create a convergence diagram.
- Parameters:
sources (List[Dict[str, Any]]) – Source node dicts with keys
label(required),color(optional), and an optional magnitude key.hub_label (str) – Center node label.
outputs (List[Dict[str, Any]] | None) – Optional output node dicts (same schema as sources).
title (str) – Diagram title.
width (float) – Figure width in inches.
height (float) – Figure height in inches.
**kwargs – Forwarded to
CompositeChartMixin.create_convergence_diagram(). Acceptsarrow_style('curved','radial', or'orthogonal'),arrow_count,arrow_color,show_magnitudes, andmagnitude_key.
- Returns:
ReportLab Image object or None if error.
- Return type:
None
- siege_utilities.reporting.create_dashboard(charts, layout='2x2', width=12.0, height=8.0, **kwargs)[source]
Standalone function to create a dashboard with multiple charts.
- siege_utilities.reporting.create_dataframe_summary_charts(df, title='', width=8.0, height=6.0, **kwargs)[source]
Standalone function to create summary charts from a DataFrame.
- siege_utilities.reporting.generate_chart_from_dataframe(df, chart_type='bar', x_column=None, y_columns=None, title='', width=6.0, height=4.0, **kwargs)[source]
Standalone function to generate a chart from a DataFrame.
- Parameters:
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- class siege_utilities.reporting.ClientBrandingManager[source]
Bases:
objectManages client branding configurations for reports. Handles logos, colors, fonts, and styling preferences.
- __init__(config_dir=None)[source]
Initialize the branding manager.
- Parameters:
config_dir (Path | None) – Directory containing branding configuration files
- create_client_branding(client_name, branding_config)[source]
Create a new client branding configuration.
- get_client_branding(client_name)[source]
Get branding configuration for a specific client.
- Parameters:
client_name (str) – Name of the client
- Returns:
Branding configuration dictionary.
- Raises:
ClientBrandingNotFoundError – If no branding configuration exists.
ClientBrandingError – If loading fails for another reason.
- Return type:
- update_client_branding(client_name, updates)[source]
Update an existing client branding configuration.
- Parameters:
- Raises:
ClientBrandingNotFoundError – If no existing branding exists.
ClientBrandingError – If the update fails.
- Return type:
None
- delete_client_branding(client_name)[source]
Delete a client branding configuration.
- Parameters:
client_name (str) – Name of the client to delete
- Raises:
ClientBrandingError – If attempting to delete a predefined template.
ClientBrandingNotFoundError – If no configuration exists for the client.
- Return type:
None
- create_branding_from_template(client_name, template_name, customizations=None)[source]
Create client branding from a predefined template.
- export_branding_config(client_name, export_path)[source]
Export a client branding configuration to a file.
- Parameters:
- Raises:
ClientBrandingNotFoundError – If no branding configuration exists.
ClientBrandingError – If the export fails.
- Return type:
None
- import_branding_config(import_path, client_name=None)[source]
Import a branding configuration from a file.
- Parameters:
- Raises:
ValueError – If the file format is unsupported or validation fails.
ClientBrandingError – If the import fails.
- Return type:
None
- siege_utilities.reporting.decode_rl_image(rl_img)[source]
Decode a ReportLab Image’s base64 data URI to raw PNG bytes.
- Parameters:
rl_img – A ReportLab Image object (or any object with a
filenameattribute).- Returns:
Raw PNG bytes, or
Noneif the object is not a base64 data URI image.- Return type:
bytes | None
- siege_utilities.reporting.show_rl_image(rl_img)[source]
Display a ReportLab Image in a Jupyter notebook.
Decodes the base64 data URI embedded in the ReportLab Image and returns an IPython
Imageobject suitable for inline display.- Parameters:
rl_img – A ReportLab Image object returned by ChartGenerator.
- Returns:
An
IPython.display.Imagefor notebook rendering, or the original object if it is not a base64 data URI image.
- siege_utilities.reporting.save_rl_image(rl_img, path)[source]
Save a ReportLab Image (base64 data URI) to a PNG file.
- class siege_utilities.reporting.Argument[source]
Bases:
objectAtomic report unit: headline → narrative → table → visualization(s).
- layout is auto-resolved in __post_init__:
map_figure present → “full_width” (stacked: title / table / figure)
map_figure absent → “side_by_side” (title top, table left, figure right)
- __init__(headline, narrative, table, table_type, chart=None, map_figure=None, layout='auto', base_note=None, source_note=None, tags=<factory>)
- class siege_utilities.reporting.TableType[source]
Bases:
Enum- SINGLE_RESPONSE = 'single_response'
- MULTIPLE_RESPONSE = 'multiple_response'
- CROSS_TAB = 'cross_tab'
- LONGITUDINAL = 'longitudinal'
- RANKING = 'ranking'
- MEAN_SCALE = 'mean_scale'
- BANNER = 'banner'
- class siege_utilities.reporting.Algorithm[source]
-
Placement-algorithm choices for
hex_tile_layout().- GREEDY = 'greedy'
Sort by area, place in nearest unoccupied hex. < 100 ms typical.
- HUNGARIAN = 'hungarian'
Optimal centroid-distance assignment (no topology term).
- ANNEALING = 'annealing'
Centroid + topology weighted; SA refinement of an initial layout.
- FORCE_DIRECTED = 'force_directed'
Reserved — not implemented in v1.
- ILP = 'ilp'
Reserved — not implemented in v1.
- __new__(value)
- class siege_utilities.reporting.Sizing[source]
-
Sizing-mode choices for
hex_tile_map().- EQUAL = 'equal'
Every hex same size; values map to colour only.
- VALUE_PROPORTIONAL = 'value_proportional'
Hex area proportional to value.
- VALUE_SQRT = 'value_sqrt'
Hex side proportional to
√value(perception-correct).
- __new__(value)
- siege_utilities.reporting.hex_tile_layout(source, *, code_col='code', algorithm=Algorithm.ANNEALING, components='auto', component_gap=1, hex_size=1.0, seed=None)[source]
Build a hex tile layout.
- Parameters:
source (Union[str, 'gpd.GeoDataFrame']) – Either a registered/builtin layout name, or a GeoDataFrame of polygons to place algorithmically.
code_col (str) – Column name on the GeoDataFrame containing the polygon identifier (e.g. state abbreviation, FIPS code). Ignored when source is a string layout name.
algorithm (Union[Algorithm, str]) – One of
Algorithm(or its string value). Ignored when source is a registered layout name.components (Optional[Union[str, list[list[str]]]]) –
"auto"(default) splits the input into connected components by polygon adjacency and lays each out independently withcomponent_gapempty cells between them."single"forces everything into one component. A pre-computedlist[list[code]]lets the caller specify groups explicitly.component_gap (int) – Number of empty hex cells between neighbouring components in the final output.
hex_size (float) – Cell circumradius in CRS units used for the output geometry.
1.0is fine for visualization; choose a smaller value if you plan to overlay the cartogram on a real map.seed (Optional[int]) – Random seed for the annealing algorithm; ignored otherwise.
- Returns:
GeoDataFrame[geometry, code, q, r]— one hexagon per polygon, with axial coords on each row for downstream tooling.- Return type:
gpd.GeoDataFrame
- siege_utilities.reporting.hex_tile_map(values, layout, *, sizing=Sizing.EQUAL, cmap='viridis', code_col='code', label_col='code', title=None, figsize=(10.0, 7.0), edge_color='#888', missing_color='#eeeeee')[source]
Render a hex cartogram.
- Parameters:
values (pd.Series) – Values to encode, indexed by polygon code (matching the
code_colof layout). Codes present in the layout but absent from values render in missing_color.layout (gpd.GeoDataFrame) – GeoDataFrame from
hex_tile_layout()— needs at minimumcode,q,rcolumns.sizing (Union[Sizing, str]) – One of
Sizing(or its string value).EQUALuses the layout’s geometry as-is; the proportional modes scale per-hex around the cell center.cmap (str) – matplotlib colour map name.
code_col (str) – Name of the code column on layout.
label_col (Optional[str]) – Column to write inside each hex (typically the code). Pass
Noneto omit labels.missing_color (str) – Standard mpl knobs.
title (Optional[str])
edge_color (str)
missing_color
- Return type:
matplotlib.figure.Figure
- siege_utilities.reporting.register_layout(name, mapping)[source]
Register a hand-positioned layout under name.
The mapping must be
{code: (q, r)}with no duplicate(q, r)pairs. Use any reproducible code convention ("AL","01","al-cd-7");hex_tile_layout()will join your data on whichever column you provide viacode_col.
- class siege_utilities.reporting.IDMLExporter[source]
Bases:
objectBuild an IDML file programmatically.
- Parameters:
template_path (str or Path, optional) – Path to an existing
.idmltemplate. If provided andsimpleidmlis installed the template is loaded for modification. Otherwise the exporter builds the IDML structure from scratch.page_width (float) – Page width in points (default 612 = US Letter).
page_height (float) – Page height in points (default 792 = US Letter).
- add_text_frame(text, style_name='NormalParagraphStyle', x=72.0, y=72.0, width=468.0, height=36.0)[source]
Add a text frame to the document.
- add_image_frame(image_path, x=72.0, y=72.0, width=200.0, height=200.0)[source]
Add an image placeholder frame.
- add_table(headers, rows, x=72.0, y=72.0, width=468.0, height=200.0)[source]
Add a table as a text frame with tab-separated content.
- siege_utilities.reporting.export_report_idml(ga_data, output_path, template_path=None, title='Google Analytics Report')[source]
Export a GA-data report as an IDML file.
Accepts the same
ga_datadict produced bygenerate_sample_ga_data()/fetch_real_ga4_data()and writes an IDML file that Adobe InDesign can open.- Parameters:
- Returns:
The resolved output file path.
- Return type:
- class siege_utilities.reporting.ThreeDMapRenderer[source]
Bases:
objectHigh-level helper for creating pydeck 3D map visualisations.
- Parameters:
- create_hexagon_layer(df, lat_col='latitude', lon_col='longitude', value_col=None, radius=1000, elevation_scale=100, color_range=None, auto_highlight=True, extruded=True, coverage=0.8, zoom=10.0, pitch=45.0)[source]
Create a 3D hexagonal-bin aggregation layer.
- Parameters:
df (pandas.DataFrame) – Must contain lat_col and lon_col columns.
value_col (str | None) – Column whose values are summed per hex. When None the layer counts the number of points (default pydeck behaviour).
radius (int) – Hexagon radius in metres.
elevation_scale (int) – Multiplier applied to the aggregated elevation value.
lat_col (str)
lon_col (str)
auto_highlight (bool)
extruded (bool)
coverage (float)
zoom (float)
pitch (float)
- Return type:
pdk.Deck
- create_column_layer(df, lat_col='latitude', lon_col='longitude', value_col='value', radius=500, elevation_scale=1, color=None, auto_highlight=True, zoom=10.0, pitch=45.0)[source]
Create a 3D column layer at point locations.
Each row produces a column whose height is proportional to value_col multiplied by elevation_scale.
- create_choropleth_3d(gdf, value_col='value', elevation_scale=100, fill_color=None, line_color=None, opacity=0.8, zoom=10.0, pitch=45.0)[source]
Create an extruded polygon (choropleth) layer from a GeoDataFrame.
The polygons are extruded by value_col multiplied by elevation_scale, giving a 3D bar-on-map effect.
- Parameters:
- Return type:
pdk.Deck
- siege_utilities.reporting.create_3d_hexbin(df, lat_col='latitude', lon_col='longitude', **kwargs)[source]
Convenience wrapper — create a hexagonal-bin 3D map.
Accepts all keyword arguments supported by
ThreeDMapRenderer.create_hexagon_layer().
- siege_utilities.reporting.create_3d_columns(df, lat_col='latitude', lon_col='longitude', value_col='value', **kwargs)[source]
Convenience wrapper — create a column 3D map.
Accepts all keyword arguments supported by
ThreeDMapRenderer.create_column_layer().
- siege_utilities.reporting.sort_table_data(table_data, sort_by=None, sort_order='asc', has_header=True)[source]
Sort table rows by a column.
- Parameters:
- Returns:
A new list with rows sorted. The header row (if present) stays first.
- Raises:
ValueError – If sort_order is not
'asc'or'desc', or sort_by names a column not found in the header.IndexError – If sort_by is an int outside the column range.
- Return type:
- siege_utilities.reporting.get_report_output_directory(client_code=None)[source]
Get the appropriate output directory for reports based on profile system.
- siege_utilities.reporting.create_report_generator(client_name, client_code=None)[source]
Create a ReportGenerator with profile-based output directory.
- siege_utilities.reporting.create_powerpoint_generator(client_name, client_code=None)[source]
Create a PowerPointGenerator with profile-based output directory.
- siege_utilities.reporting.export_branding_config(client_name, export_path)[source]
Export client branding configuration to a file.
- Parameters:
- Raises:
ReportingConfigError – On any failure — OS error writing the file, missing client, etc.
- Return type:
None
- siege_utilities.reporting.import_branding_config(import_path, client_name=None)[source]
Import client branding configuration from a file.
- Parameters:
- Raises:
ReportingConfigError – On any failure — file missing, parse error, client collision.
- Return type:
None
- siege_utilities.reporting.export_chart_type_config(chart_type_name, output_path)[source]
Export chart type configuration to a file.
- Parameters:
- Returns:
True on success.
- Return type:
- Raises:
ReportingConfigError – On any failure — unknown chart type, OS error writing.
- exception siege_utilities.reporting.ReportingConfigError[source]
Bases:
RuntimeErrorRaised when a reporting configuration export / import cannot complete.
Charts and Visualization
Chart generation utilities for siege_utilities reporting system. Supports multiple chart types, maps, and data sources including pandas and Spark DataFrames.
- class siege_utilities.reporting.chart_generator.ChartGenerator[source]
Bases:
BaseChartEngine,BarChartMixin,MapChartMixin,StatsChartMixin,CompositeChartMixinGenerates charts and visualizations for reports using matplotlib, seaborn, plotly, and folium. Supports pandas DataFrames, Spark DataFrames, and various data sources.
All chart methods are provided by engine mixins:
BaseChartEngine —
__init__, scaling, placeholder, save/convert helpersBarChartMixin — bar, line, pie, proportional text bar charts
MapChartMixin — choropleth, marker, 3D, heatmap-map, cluster, flow, bivariate maps
StatsChartMixin — statistical heatmap, scatter plot, text heatmap
CompositeChartMixin — convergence diagram, dashboard, summary charts, subplots
- siege_utilities.reporting.chart_generator.create_bar_chart(data, x_column=None, y_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a bar chart.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
x_column (str | None) – Column name for x-axis
y_column (str | None) – Column name for y-axis
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.chart_generator.create_bivariate_choropleth(data, x_column=None, y_column=None, geoid_column='geoid', title='Bivariate Choropleth Map', width=12.0, height=8.0, **kwargs)[source]
Standalone function to create a bivariate choropleth map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis variable
y_column (str) – Column name for Y-axis variable
geoid_column (str) – Column name for geographic identifiers
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.chart_generator.create_choropleth_map(data, location_column=None, value_column=None, title='', width=8.0, height=6.0, map_type='world', **kwargs)[source]
Standalone function to create a choropleth map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
location_column (str) – Column name for locations (country codes, state names, etc.)
value_column (str) – Column name for values to color by
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
map_type (str) – Type of map (“world”, “usa”, “europe”, etc.)
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.chart_generator.create_convergence_diagram(sources, hub_label='Unified Hub', outputs=None, title='Convergence Diagram', width=10.0, height=6.0, **kwargs)[source]
Standalone function to create a convergence diagram.
- Parameters:
sources (List[Dict[str, Any]]) – Source node dicts with keys
label(required),color(optional), and an optional magnitude key.hub_label (str) – Center node label.
outputs (List[Dict[str, Any]] | None) – Optional output node dicts (same schema as sources).
title (str) – Diagram title.
width (float) – Figure width in inches.
height (float) – Figure height in inches.
**kwargs – Forwarded to
CompositeChartMixin.create_convergence_diagram(). Acceptsarrow_style('curved','radial', or'orthogonal'),arrow_count,arrow_color,show_magnitudes, andmagnitude_key.
- Returns:
ReportLab Image object or None if error.
- Return type:
None
- siege_utilities.reporting.chart_generator.create_dashboard(charts, layout='2x2', width=12.0, height=8.0, **kwargs)[source]
Standalone function to create a dashboard with multiple charts.
- siege_utilities.reporting.chart_generator.create_dataframe_summary_charts(df, title='', width=8.0, height=6.0, **kwargs)[source]
Standalone function to create summary charts from a DataFrame.
- siege_utilities.reporting.chart_generator.create_flow_map(data, origin_lat_column=None, origin_lon_column=None, dest_lat_column=None, dest_lon_column=None, flow_value_column=None, title='', width=12.0, height=10.0, **kwargs)[source]
Standalone function to create a flow map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
origin_lat_column (str) – Column name for origin latitude
origin_lon_column (str) – Column name for origin longitude
dest_lat_column (str) – Column name for destination latitude
dest_lon_column (str) – Column name for destination longitude
flow_value_column (str) – Column name for flow values (optional)
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.chart_generator.create_heatmap(data, x_column=None, y_column=None, value_column=None, title='', width=8.0, height=6.0, **kwargs)[source]
Standalone function to create a heatmap.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_column (str) – Column name for Y-axis
value_column (str) – Column name for values
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
**kwargs – Additional arguments to pass to create_heatmap
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.chart_generator.create_line_chart(data, x_column=None, y_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a line chart.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
x_column (str | None) – Column name for x-axis
y_column (str | None) – Column name for y-axis
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.chart_generator.create_marker_map(data, latitude_column=None, longitude_column=None, value_column=None, label_column=None, title='', width=10.0, height=8.0, map_style='open-street-map', zoom_level=10, **kwargs)[source]
Standalone function to create a marker map.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
value_column (str) – Column name for values (optional)
label_column (str) – Column name for labels (optional)
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
map_style (str) – Map style
zoom_level (int) – Initial zoom level
**kwargs – Additional arguments
- Returns:
PIL Image object or None if error
- Return type:
Image | None
- siege_utilities.reporting.chart_generator.create_pie_chart(data, label_column=None, value_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a pie chart.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
label_column (str | None) – Column name for labels
value_column (str | None) – Column name for values
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.chart_generator.create_scatter_plot(data, x_column=None, y_column=None, title='', width=800, height=600, **kwargs)[source]
Standalone function to create a scatter plot.
- Parameters:
data (pd.DataFrame | Dict[str, Any]) – DataFrame or data dictionary
x_column (str | None) – Column name for x-axis
y_column (str | None) – Column name for y-axis
title (str) – Chart title
width (int) – Chart width in pixels
height (int) – Chart height in pixels
**kwargs – Additional chart parameters
- Returns:
Chart configuration dictionary or None if error
- Return type:
- siege_utilities.reporting.chart_generator.generate_chart_from_dataframe(df, chart_type='bar', x_column=None, y_columns=None, title='', width=6.0, height=4.0, **kwargs)[source]
Standalone function to generate a chart from a DataFrame.
- Parameters:
- Returns:
PIL Image object or None if error
- Return type:
Image | None
Extensible chart type system for siege_utilities. Provides base chart types and easy extension capabilities.
- exception siege_utilities.reporting.chart_types.ChartCreationError[source]
Bases:
RuntimeErrorRaised when the underlying create function fails to produce a Figure.
- exception siege_utilities.reporting.chart_types.ChartParameterError[source]
Bases:
ValueErrorRaised when required parameters are missing or invalid.
- class siege_utilities.reporting.chart_types.ChartType[source]
Bases:
objectBase chart type configuration.
- __init__(name, category, description='', required_parameters=<factory>, optional_parameters=<factory>, supports_interactive=False, supports_3d=False, supports_animation=False, default_width=10.0, default_height=8.0, default_dpi=300, custom_options=<factory>, create_function=None, validate_function=None, customize_function=None)
- Parameters:
- Return type:
None
- class siege_utilities.reporting.chart_types.ChartTypeRegistry[source]
Bases:
objectRegistry for chart types and their implementations. Provides easy extension and customization of chart types.
- register_chart_type(chart_type)[source]
Register a new chart type.
- Parameters:
chart_type (ChartType) – ChartType object to register
- create_chart(chart_type_name, **kwargs)[source]
Create a chart using the specified chart type.
- Parameters:
chart_type_name (str) – Name of the chart type (must exist in the registry).
**kwargs – Parameters for the chart; must include every entry in the chart type’s
required_parameters.
- Return type:
matplotlib.figure.Figure
- Raises:
UnknownChartTypeError – If
chart_type_nameisn’t registered.ChartParameterError – If required parameters are missing.
ChartCreationError – If the chart type has no create function, or the create function raised.
- add_chart_creator(chart_type_name, create_function)[source]
Add or update the create function for a chart type.
- validate_chart_parameters(chart_type_name, **kwargs)[source]
Validate parameters for a chart type without creating the chart.
- Parameters:
chart_type_name (str)
**kwargs – Chart parameters to validate against the chart type’s
required_parameters. If the chart type defines a customvalidate_function, all kwargs are forwarded to it.
- Returns:
True iff required params present AND any custom
validate_functionreturns truthy.- Return type:
- Raises:
UnknownChartTypeError – If
chart_type_nameisn’t registered. (Legitimately-missing validation returns False; unknown chart type is a caller error.)ChartParameterError – If the custom validate function raised.
- exception siege_utilities.reporting.chart_types.UnknownChartTypeError[source]
Bases:
LookupErrorRaised when a chart type name is not in the registry.
- siege_utilities.reporting.chart_types.create_chart(chart_type_name, **kwargs)[source]
Create a chart using the specified chart type.
- Parameters:
chart_type_name (str) – Name of a registered chart type.
**kwargs – Forwarded to the chart type’s create function. Must include all of the chart type’s required_parameters. Optional parameters are filled from the chart type’s defaults. See ChartTypeRegistry.create_chart() for details.
- Return type:
Optional[Figure]
- siege_utilities.reporting.chart_types.get_chart_registry()[source]
Get or create the global chart type registry.
- Return type:
- siege_utilities.reporting.chart_types.register_chart_type(chart_type)[source]
Register a new chart type.
- Parameters:
chart_type (ChartType)
Rendering helpers for WaveSet longitudinal output.
Takes a LONGITUDINAL Chain (typically
from compare_chain()) and
produces matplotlib figures:
trend_chart()— line chart of each category across wavesheatmap()— category × wave heatmap of percents or counts
- exception siege_utilities.reporting.wave_charts.WaveChartError[source]
Bases:
ValueErrorRaised when a WaveSet chart cannot be rendered from the given Chain.
- siege_utilities.reporting.wave_charts.heatmap(chain, *, title=None, figsize=(10, 6), cmap='RdYlBu_r', annotate=True)[source]
Category × wave heatmap.
- siege_utilities.reporting.wave_charts.trend_chart(chain, *, title=None, ylabel='%', figsize=(10, 6), marker='o')[source]
Line chart of each row category across waves.
- Parameters:
chain (Chain) – A LONGITUDINAL Chain. Each wave is a column; each row_var value becomes one line.
title (Optional[str]) – Optional plot title; defaults to
f"{chain.row_var} over time".ylabel (str) – Y-axis label; default “%”.
figsize (tuple) – Matplotlib
figuresize tuple.marker (str) – Matplotlib marker style for data points.
Legend management utilities for siege_utilities reporting system. Provides comprehensive legend generation and management for charts, tables, and visualizations.
- class siege_utilities.reporting.legend_manager.ColorScheme[source]
Bases:
EnumEnumeration of color schemes for legends
- BLUE = 'blue'
- GREEN = 'green'
- RED = 'red'
- PURPLE = 'purple'
- ORANGE = 'orange'
- GRAY = 'gray'
- class siege_utilities.reporting.legend_manager.LegendManager[source]
Bases:
objectComprehensive legend management system for charts, tables, and visualizations. Provides consistent legend generation across all siege_utilities components.
- get_color_for_intensity(intensity, color_scheme=ColorScheme.BLUE)[source]
Get color for a given intensity (0-1) using specified color scheme.
- Parameters:
intensity (float) – Intensity value between 0 and 1
color_scheme (ColorScheme) – Color scheme to use
- Returns:
Hex color string
- Return type:
- create_heatmap_legend_table(min_value, max_value, value_name='Value', color_scheme=ColorScheme.BLUE, levels=5)[source]
Create a heatmap legend table for ReportLab.
- Parameters:
min_value (float) – Minimum value in the data
max_value (float) – Maximum value in the data
value_name (str) – Name of the value being visualized
color_scheme (ColorScheme) – Color scheme to use
levels (int) – Number of intensity levels (default 5)
- Returns:
ReportLab Table object
- Return type:
reportlab.platypus.Table | None
- create_matplotlib_legend(ax, labels, title='Legend', position=LegendPosition.BEST, **kwargs)[source]
Create a matplotlib legend with enhanced styling.
- Parameters:
ax – Matplotlib axes object
title (str) – Legend title
position (LegendPosition) – Legend position
**kwargs – Additional legend parameters
- Return type:
None
- create_legend_for_series(ax, series_data, title='Legend', position=LegendPosition.BEST)[source]
Create a legend for multiple data series.
- Parameters:
ax – Matplotlib axes object
series_data (Dict[str, Any]) – Dictionary mapping series names to their data/colors
title (str) – Legend title
position (LegendPosition) – Legend position
- Return type:
None
- create_heatmap_legend_elements(min_value, max_value, color_scheme=ColorScheme.BLUE, levels=5)[source]
Create matplotlib legend elements for heatmap visualization.
- Parameters:
min_value (float) – Minimum value in the data
max_value (float) – Maximum value in the data
color_scheme (ColorScheme) – Color scheme to use
levels (int) – Number of intensity levels
- Returns:
List of matplotlib Patch objects for legend
- Return type:
List[matplotlib.patches.Patch]
- add_heatmap_legend_to_plot(ax, min_value, max_value, color_scheme=ColorScheme.BLUE, position=LegendPosition.RIGHT, title='Intensity')[source]
Add a heatmap legend directly to a matplotlib plot.
- Parameters:
ax – Matplotlib axes object
min_value (float) – Minimum value in the data
max_value (float) – Maximum value in the data
color_scheme (ColorScheme) – Color scheme to use
position (LegendPosition) – Legend position
title (str) – Legend title
- Return type:
None
- get_legend_position_for_chart_type(chart_type, data_size)[source]
Get optimal legend position based on chart type and data size.
- Parameters:
- Returns:
Recommended LegendPosition
- Return type:
- class siege_utilities.reporting.legend_manager.LegendPosition[source]
Bases:
EnumEnumeration of legend positions
- BEST = 'best'
- OUTSIDE = 'outside'
- BOTTOM = 'bottom'
- TOP = 'top'
- LEFT = 'left'
- RIGHT = 'right'
- CENTER = 'center'
- siege_utilities.reporting.legend_manager.create_heatmap_legend_table(min_value, max_value, value_name='Value', color_scheme='blue')[source]
Convenience function to create a heatmap legend table.
- Parameters:
- Returns:
ReportLab Table object or None
- Return type:
reportlab.platypus.Table | None
- siege_utilities.reporting.legend_manager.get_optimal_legend_position(chart_type, data_size)[source]
Convenience function to get optimal legend position.
Utilities for working with ReportLab Image objects containing base64 data URIs.
ChartGenerator methods return ReportLab Image objects whose filename
attribute is a base64 data URI (e.g. data:image/png;base64,...).
These helpers decode, display, and persist those images.
- siege_utilities.reporting.image_utils.decode_rl_image(rl_img)[source]
Decode a ReportLab Image’s base64 data URI to raw PNG bytes.
- Parameters:
rl_img – A ReportLab Image object (or any object with a
filenameattribute).- Returns:
Raw PNG bytes, or
Noneif the object is not a base64 data URI image.- Return type:
bytes | None
- siege_utilities.reporting.image_utils.show_rl_image(rl_img)[source]
Display a ReportLab Image in a Jupyter notebook.
Decodes the base64 data URI embedded in the ReportLab Image and returns an IPython
Imageobject suitable for inline display.- Parameters:
rl_img – A ReportLab Image object returned by ChartGenerator.
- Returns:
An
IPython.display.Imagefor notebook rendering, or the original object if it is not a base64 data URI image.
Chart Engines
Engine mixins for the ChartGenerator class.
Each mixin defines a subset of chart-generation methods. At runtime they
are combined via multiple inheritance into the unified ChartGenerator
class defined in chart_generator.py.
- class siege_utilities.reporting.engines.BaseChartEngine[source]
Bases:
objectCore infrastructure: init, colors, styling, scaling, save helpers.
- __init__(branding_config=None, output_dir=None, max_chart_width=None, max_chart_height=None)[source]
Initialize the chart generator.
- Parameters:
branding_config (Dict[str, Any] | None) – Branding configuration for chart colors and styling
output_dir (Path | None) – Directory for saving Folium HTML map files. Defaults to
~/.siege_utilitiesfor backward compatibility.max_chart_width (float | None) – Maximum chart width in inches for ReportLab output. When set, charts wider than this are uniformly scaled down to fit.
Nonedisables width clamping.max_chart_height (float | None) – Maximum chart height in inches for ReportLab output. When set, charts taller than this are uniformly scaled down to fit.
Nonedisables height clamping.
- save_figure_as_vector(fig, output_path, fmt='svg')[source]
Save a matplotlib figure as a vector file (SVG, EPS, or PDF).
- Parameters:
- Returns:
Path to the saved file.
- Raises:
ValueError – If fmt is not a supported vector format.
OSError – If the file cannot be written.
- Return type:
- create_chart_with_caption(chart, caption, caption_style=None)[source]
Create a chart with a caption below it.
- create_chart_section(title, charts, description='', width=6.0)[source]
Create a complete chart section with title, description, and charts.
- generate_chart_from_dataframe(df, chart_type='bar', x_column=None, y_columns=None, title='', width=6.0, height=4.0)[source]
Generate a chart from a pandas DataFrame.
- Parameters:
- Returns:
ReportLab Image object
- Return type:
None
- class siege_utilities.reporting.engines.BarChartMixin[source]
Bases:
objectBar chart, line chart, pie chart, and proportional text bar chart methods.
- create_bar_chart(data, x_column=None, y_column=None, title='', width=6.0, height=4.0, chart_type='bar', group_by=None, show_legend=True, legend_position='best')[source]
Create a bar chart from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis (or ‘index’ for DataFrame index)
y_column (str) – Column name for Y-axis
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
chart_type (str) – Type of chart (‘bar’, ‘horizontal’)
group_by (str) – Column to group by for grouped bars
show_legend (bool)
legend_position (str)
- Returns:
ReportLab Image object
- Return type:
Image
- create_line_chart(data, x_column=None, y_columns=None, title='', width=6.0, height=4.0, show_legend=True, legend_position='best')[source]
Create a line chart from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_columns (List[str]) – List of column names for Y-axis (multiple lines)
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
show_legend (bool)
legend_position (str)
- Returns:
ReportLab Image object
- Return type:
Image
- create_pie_chart(data, labels_column=None, values_column=None, title='', width=6.0, height=4.0, show_legend=True, legend_position='right')[source]
Create a pie chart from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
labels_column (str) – Column name for labels
values_column (str) – Column name for values
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
show_legend (bool)
legend_position (str)
- Returns:
ReportLab Image object
- Return type:
Image
- create_proportional_text_bar_chart(data, labels_column, values_column, title='Proportional Text Bar Chart', max_width=50, bar_char='█', show_values=True, sort_descending=True)[source]
Create a proportional text-based bar chart
- Parameters:
data (pd.DataFrame) – DataFrame containing the data
labels_column (str) – Column name for labels
values_column (str) – Column name for values
title (str) – Chart title
max_width (int) – Maximum width of bars in characters
bar_char (str) – Character to use for bars
show_values (bool) – Whether to show actual values
sort_descending (bool) – Whether to sort by values descending
- Returns:
Formatted text chart string
- Return type:
- class siege_utilities.reporting.engines.MapChartMixin[source]
Bases:
objectGeographic map chart methods (choropleth, marker, 3D, heatmap, cluster, flow).
- create_choropleth_map(data, geo_data=None, location_column=None, value_column=None, title='', width=8.0, height=6.0, map_type='us', key_on='feature.properties.geoid', fill_color='YlOrRd')[source]
Create a choropleth map from data using Folium.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
geo_data (Union['gpd.GeoDataFrame', str, Path, Dict, None]) – GeoDataFrame, path to GeoJSON, GeoJSON dict, or None. If a GeoDataFrame is passed it is converted to GeoJSON automatically.
location_column (str) – Column name for locations (must match geo_data features via key_on)
value_column (str) – Column name for values to color by
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
map_type (str) – Type of map (‘world’, ‘us’, ‘europe’)
key_on (str) – GeoJSON feature property to join on (e.g. ‘feature.properties.geoid’)
fill_color (str) – Brewer color scheme name (e.g. ‘YlOrRd’, ‘BuGn’, ‘Blues’)
- Returns:
ReportLab Image object (placeholder — HTML saved to output_dir)
- Return type:
Image
- create_bivariate_choropleth_matplotlib(data, geodata, location_column, value_column1, value_column2, title='', width=10.0, height=8.0, color_scheme='default')[source]
Create a bivariate choropleth map using matplotlib and geopandas. This method follows the approach from the bivariate-choropleth repository.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
geodata (Union['gpd.GeoDataFrame', str, Path]) – GeoDataFrame or path to GeoJSON file
location_column (str) – Column name for locations (must match geodata)
value_column1 (str) – Column name for the first value (X-axis in bivariate scheme)
value_column2 (str) – Column name for the second value (Y-axis in bivariate scheme)
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
color_scheme (str) – Color scheme (‘default’, ‘custom’, ‘diverging’)
- Returns:
ReportLab Image object
- Return type:
Image
- create_advanced_choropleth(data, geodata, location_column, value_column, title='', width=10.0, height=8.0, classification='quantiles', bins=5, color_scheme='YlOrRd')[source]
Create an advanced choropleth map with multiple classification options.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
geodata (Union['gpd.GeoDataFrame', str, Path]) – GeoDataFrame or path to GeoJSON file
location_column (str) – Column name for locations
value_column (str) – Column name for values to color by
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
classification (str) – Classification method (‘quantiles’, ‘equal_interval’, ‘natural_breaks’)
bins (int) – Number of bins for classification
color_scheme (str) – Color scheme for the map
- Returns:
ReportLab Image object
- Return type:
Image
- create_marker_map(data, latitude_column, longitude_column, value_column=None, label_column=None, title='', width=10.0, height=8.0, map_style='open-street-map', zoom_level=10)[source]
Create a map with markers showing point locations.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
value_column (str) – Column name for marker size/color values
label_column (str) – Column name for marker labels
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
map_style (str) – Map tile style (‘open-street-map’, ‘cartodb-positron’, ‘stamen-terrain’)
zoom_level (int) – Initial zoom level for the map
- Returns:
ReportLab Image object
- Return type:
Image
- create_3d_map(data, latitude_column, longitude_column, elevation_column, title='', width=12.0, height=10.0, view_angle=45, elevation_scale=1.0)[source]
Create a 3D map visualization showing elevation or height data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
elevation_column (str) – Column name for elevation/height values
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
view_angle (int) – 3D viewing angle in degrees
elevation_scale (float) – Scale factor for elevation values
- Returns:
ReportLab Image object
- Return type:
Image
- create_heatmap_map(data, latitude_column, longitude_column, value_column, title='', width=10.0, height=8.0, grid_size=50, blur_radius=0.5)[source]
Create a heatmap overlay on a geographic map.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
value_column (str) – Column name for intensity values
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
grid_size (int) – Number of grid cells for heatmap
blur_radius (float) – Blur radius for smoothing
- Returns:
ReportLab Image object
- Return type:
Image
- create_cluster_map(data, latitude_column, longitude_column, cluster_column=None, label_column=None, title='', width=10.0, height=8.0, max_cluster_radius=80)[source]
Create a map with clustered markers for better visualization of dense data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
cluster_column (str) – Column name for clustering values
label_column (str) – Column name for marker labels
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
max_cluster_radius (int) – Maximum radius for clustering
- Returns:
ReportLab Image object
- Return type:
Image
- create_flow_map(data, origin_lat_column, origin_lon_column, dest_lat_column, dest_lon_column, flow_value_column=None, title='', width=12.0, height=10.0)[source]
Create a flow map showing movement or connections between locations.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
origin_lat_column (str) – Column name for origin latitude
origin_lon_column (str) – Column name for origin longitude
dest_lat_column (str) – Column name for destination latitude
dest_lon_column (str) – Column name for destination longitude
flow_value_column (str) – Column name for flow intensity values
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
- Returns:
ReportLab Image object
- Return type:
Image
- create_bivariate_choropleth(data, geo_data=None, location_column=None, value_column1=None, value_column2=None, title='', width=8.0, height=6.0, color_scheme='default')[source]
Create a bivariate choropleth map from data using Folium.
Uses the same 3x3 bivariate color classification as
create_bivariate_choropleth_matplotlibbut renders the result as an interactive Folium map.- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data (must include geometry if GeoDataFrame, or be joinable to geo_data via location_column)
geo_data (Union['gpd.GeoDataFrame', str, Path, Dict, None]) – GeoDataFrame, path to GeoJSON, GeoJSON dict, or None. If data is already a GeoDataFrame this can be omitted.
location_column (str) – Column to join data ↔ geo_data on
value_column1 (str) – First variable (X-axis in bivariate scheme)
value_column2 (str) – Second variable (Y-axis in bivariate scheme)
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
color_scheme (str) – Bivariate color scheme (‘default’, ‘blue_red’, ‘green_orange’)
- Returns:
ReportLab Image object (placeholder — HTML saved to output_dir)
- Return type:
Image
- class siege_utilities.reporting.engines.StatsChartMixin[source]
Bases:
objectStatistical chart methods (heatmap, scatter plot, text heatmap).
- create_heatmap(data, x_column=None, y_column=None, value_column=None, title='', width=8.0, height=6.0)[source]
Create a heatmap from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_column (str) – Column name for Y-axis
value_column (str) – Column name for values
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
- Returns:
ReportLab Image object
- Return type:
Image
- create_scatter_plot(data, x_column, y_column, color_column=None, title='', width=6.0, height=4.0)[source]
Create a scatter plot from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_column (str) – Column name for Y-axis
color_column (str) – Column name for color coding
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
- Returns:
ReportLab Image object
- Return type:
Image
- create_heatmap_text_chart(data, x_column, y_column, value_column, title='Text Heatmap', max_width=20, max_height=10, heat_chars=' ░▒▓█')[source]
Create a text-based heatmap visualization
- Parameters:
data (pd.DataFrame) – DataFrame containing the data
x_column (str) – Column name for x-axis labels
y_column (str) – Column name for y-axis labels
value_column (str) – Column name for values
title (str) – Chart title
max_width (int) – Maximum width in characters
max_height (int) – Maximum height in characters
heat_chars (str) – Characters for heat intensity (light to dark)
- Returns:
Formatted text heatmap string
- Return type:
- class siege_utilities.reporting.engines.CompositeChartMixin[source]
Bases:
objectComposite chart methods (convergence diagram, dashboard, summary charts, subplots).
- create_convergence_diagram(sources, hub_label='Unified Hub', outputs=None, title='Convergence Diagram', width=10.0, height=6.0, arrow_style='curved', arrow_count=None, arrow_color=None, show_magnitudes=False, magnitude_key='magnitude')[source]
Create a stylized convergence diagram with arrows into a labeled origin.
- Parameters:
sources (List[Dict[str, Any]]) – Source node dictionaries; supports keys:
label(required),color(optional), and optional magnitude key.hub_label (str) – Center node label.
outputs (List[Dict[str, Any]] | None) – Optional output node dictionaries (same schema as sources).
title (str) – Diagram title.
width (float) – Figure width in inches.
height (float) – Figure height in inches.
arrow_style (str) – One of
curved,radial,orthogonal.arrow_count (int | None) – Optional max number of source arrows to render.
arrow_color (str | None) – Optional color override for arrows.
show_magnitudes (bool) – If True, append magnitudes to source labels when present.
magnitude_key (str) – Dict key to read magnitude from.
- Returns:
ReportLab Image object.
- Return type:
None
- create_dashboard(charts, layout='2x2', width=12.0, height=8.0)[source]
Create a dashboard with multiple charts.
Base engine mixin — __init__, scaling, placeholder, and conversion helpers.
- class siege_utilities.reporting.engines.base_engine.BaseChartEngine[source]
Bases:
objectCore infrastructure: init, colors, styling, scaling, save helpers.
- __init__(branding_config=None, output_dir=None, max_chart_width=None, max_chart_height=None)[source]
Initialize the chart generator.
- Parameters:
branding_config (Dict[str, Any] | None) – Branding configuration for chart colors and styling
output_dir (Path | None) – Directory for saving Folium HTML map files. Defaults to
~/.siege_utilitiesfor backward compatibility.max_chart_width (float | None) – Maximum chart width in inches for ReportLab output. When set, charts wider than this are uniformly scaled down to fit.
Nonedisables width clamping.max_chart_height (float | None) – Maximum chart height in inches for ReportLab output. When set, charts taller than this are uniformly scaled down to fit.
Nonedisables height clamping.
- save_figure_as_vector(fig, output_path, fmt='svg')[source]
Save a matplotlib figure as a vector file (SVG, EPS, or PDF).
- Parameters:
- Returns:
Path to the saved file.
- Raises:
ValueError – If fmt is not a supported vector format.
OSError – If the file cannot be written.
- Return type:
- create_chart_with_caption(chart, caption, caption_style=None)[source]
Create a chart with a caption below it.
- create_chart_section(title, charts, description='', width=6.0)[source]
Create a complete chart section with title, description, and charts.
- generate_chart_from_dataframe(df, chart_type='bar', x_column=None, y_columns=None, title='', width=6.0, height=4.0)[source]
Generate a chart from a pandas DataFrame.
- Parameters:
- Returns:
ReportLab Image object
- Return type:
None
Bar, line, pie, and proportional text bar chart mixins.
- class siege_utilities.reporting.engines.bar_engine.BarChartMixin[source]
Bases:
objectBar chart, line chart, pie chart, and proportional text bar chart methods.
- create_bar_chart(data, x_column=None, y_column=None, title='', width=6.0, height=4.0, chart_type='bar', group_by=None, show_legend=True, legend_position='best')[source]
Create a bar chart from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis (or ‘index’ for DataFrame index)
y_column (str) – Column name for Y-axis
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
chart_type (str) – Type of chart (‘bar’, ‘horizontal’)
group_by (str) – Column to group by for grouped bars
show_legend (bool)
legend_position (str)
- Returns:
ReportLab Image object
- Return type:
Image
- create_line_chart(data, x_column=None, y_columns=None, title='', width=6.0, height=4.0, show_legend=True, legend_position='best')[source]
Create a line chart from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_columns (List[str]) – List of column names for Y-axis (multiple lines)
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
show_legend (bool)
legend_position (str)
- Returns:
ReportLab Image object
- Return type:
Image
- create_pie_chart(data, labels_column=None, values_column=None, title='', width=6.0, height=4.0, show_legend=True, legend_position='right')[source]
Create a pie chart from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
labels_column (str) – Column name for labels
values_column (str) – Column name for values
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
show_legend (bool)
legend_position (str)
- Returns:
ReportLab Image object
- Return type:
Image
- create_proportional_text_bar_chart(data, labels_column, values_column, title='Proportional Text Bar Chart', max_width=50, bar_char='█', show_values=True, sort_descending=True)[source]
Create a proportional text-based bar chart
- Parameters:
data (pd.DataFrame) – DataFrame containing the data
labels_column (str) – Column name for labels
values_column (str) – Column name for values
title (str) – Chart title
max_width (int) – Maximum width of bars in characters
bar_char (str) – Character to use for bars
show_values (bool) – Whether to show actual values
sort_descending (bool) – Whether to sort by values descending
- Returns:
Formatted text chart string
- Return type:
Composite chart mixins — convergence diagrams, dashboards, and subplot helpers.
- class siege_utilities.reporting.engines.composite_engine.CompositeChartMixin[source]
Bases:
objectComposite chart methods (convergence diagram, dashboard, summary charts, subplots).
- create_convergence_diagram(sources, hub_label='Unified Hub', outputs=None, title='Convergence Diagram', width=10.0, height=6.0, arrow_style='curved', arrow_count=None, arrow_color=None, show_magnitudes=False, magnitude_key='magnitude')[source]
Create a stylized convergence diagram with arrows into a labeled origin.
- Parameters:
sources (List[Dict[str, Any]]) – Source node dictionaries; supports keys:
label(required),color(optional), and optional magnitude key.hub_label (str) – Center node label.
outputs (List[Dict[str, Any]] | None) – Optional output node dictionaries (same schema as sources).
title (str) – Diagram title.
width (float) – Figure width in inches.
height (float) – Figure height in inches.
arrow_style (str) – One of
curved,radial,orthogonal.arrow_count (int | None) – Optional max number of source arrows to render.
arrow_color (str | None) – Optional color override for arrows.
show_magnitudes (bool) – If True, append magnitudes to source labels when present.
magnitude_key (str) – Dict key to read magnitude from.
- Returns:
ReportLab Image object.
- Return type:
None
- create_dashboard(charts, layout='2x2', width=12.0, height=8.0)[source]
Create a dashboard with multiple charts.
Map chart mixins — choropleth, marker, 3D, heatmap, cluster, flow, and bivariate maps.
- class siege_utilities.reporting.engines.map_engine.MapChartMixin[source]
Bases:
objectGeographic map chart methods (choropleth, marker, 3D, heatmap, cluster, flow).
- create_choropleth_map(data, geo_data=None, location_column=None, value_column=None, title='', width=8.0, height=6.0, map_type='us', key_on='feature.properties.geoid', fill_color='YlOrRd')[source]
Create a choropleth map from data using Folium.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
geo_data (Union['gpd.GeoDataFrame', str, Path, Dict, None]) – GeoDataFrame, path to GeoJSON, GeoJSON dict, or None. If a GeoDataFrame is passed it is converted to GeoJSON automatically.
location_column (str) – Column name for locations (must match geo_data features via key_on)
value_column (str) – Column name for values to color by
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
map_type (str) – Type of map (‘world’, ‘us’, ‘europe’)
key_on (str) – GeoJSON feature property to join on (e.g. ‘feature.properties.geoid’)
fill_color (str) – Brewer color scheme name (e.g. ‘YlOrRd’, ‘BuGn’, ‘Blues’)
- Returns:
ReportLab Image object (placeholder — HTML saved to output_dir)
- Return type:
Image
- create_bivariate_choropleth_matplotlib(data, geodata, location_column, value_column1, value_column2, title='', width=10.0, height=8.0, color_scheme='default')[source]
Create a bivariate choropleth map using matplotlib and geopandas. This method follows the approach from the bivariate-choropleth repository.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
geodata (Union['gpd.GeoDataFrame', str, Path]) – GeoDataFrame or path to GeoJSON file
location_column (str) – Column name for locations (must match geodata)
value_column1 (str) – Column name for the first value (X-axis in bivariate scheme)
value_column2 (str) – Column name for the second value (Y-axis in bivariate scheme)
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
color_scheme (str) – Color scheme (‘default’, ‘custom’, ‘diverging’)
- Returns:
ReportLab Image object
- Return type:
Image
- create_advanced_choropleth(data, geodata, location_column, value_column, title='', width=10.0, height=8.0, classification='quantiles', bins=5, color_scheme='YlOrRd')[source]
Create an advanced choropleth map with multiple classification options.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
geodata (Union['gpd.GeoDataFrame', str, Path]) – GeoDataFrame or path to GeoJSON file
location_column (str) – Column name for locations
value_column (str) – Column name for values to color by
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
classification (str) – Classification method (‘quantiles’, ‘equal_interval’, ‘natural_breaks’)
bins (int) – Number of bins for classification
color_scheme (str) – Color scheme for the map
- Returns:
ReportLab Image object
- Return type:
Image
- create_marker_map(data, latitude_column, longitude_column, value_column=None, label_column=None, title='', width=10.0, height=8.0, map_style='open-street-map', zoom_level=10)[source]
Create a map with markers showing point locations.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
value_column (str) – Column name for marker size/color values
label_column (str) – Column name for marker labels
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
map_style (str) – Map tile style (‘open-street-map’, ‘cartodb-positron’, ‘stamen-terrain’)
zoom_level (int) – Initial zoom level for the map
- Returns:
ReportLab Image object
- Return type:
Image
- create_3d_map(data, latitude_column, longitude_column, elevation_column, title='', width=12.0, height=10.0, view_angle=45, elevation_scale=1.0)[source]
Create a 3D map visualization showing elevation or height data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
elevation_column (str) – Column name for elevation/height values
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
view_angle (int) – 3D viewing angle in degrees
elevation_scale (float) – Scale factor for elevation values
- Returns:
ReportLab Image object
- Return type:
Image
- create_heatmap_map(data, latitude_column, longitude_column, value_column, title='', width=10.0, height=8.0, grid_size=50, blur_radius=0.5)[source]
Create a heatmap overlay on a geographic map.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
value_column (str) – Column name for intensity values
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
grid_size (int) – Number of grid cells for heatmap
blur_radius (float) – Blur radius for smoothing
- Returns:
ReportLab Image object
- Return type:
Image
- create_cluster_map(data, latitude_column, longitude_column, cluster_column=None, label_column=None, title='', width=10.0, height=8.0, max_cluster_radius=80)[source]
Create a map with clustered markers for better visualization of dense data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
latitude_column (str) – Column name for latitude values
longitude_column (str) – Column name for longitude values
cluster_column (str) – Column name for clustering values
label_column (str) – Column name for marker labels
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
max_cluster_radius (int) – Maximum radius for clustering
- Returns:
ReportLab Image object
- Return type:
Image
- create_flow_map(data, origin_lat_column, origin_lon_column, dest_lat_column, dest_lon_column, flow_value_column=None, title='', width=12.0, height=10.0)[source]
Create a flow map showing movement or connections between locations.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
origin_lat_column (str) – Column name for origin latitude
origin_lon_column (str) – Column name for origin longitude
dest_lat_column (str) – Column name for destination latitude
dest_lon_column (str) – Column name for destination longitude
flow_value_column (str) – Column name for flow intensity values
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
- Returns:
ReportLab Image object
- Return type:
Image
- create_bivariate_choropleth(data, geo_data=None, location_column=None, value_column1=None, value_column2=None, title='', width=8.0, height=6.0, color_scheme='default')[source]
Create a bivariate choropleth map from data using Folium.
Uses the same 3x3 bivariate color classification as
create_bivariate_choropleth_matplotlibbut renders the result as an interactive Folium map.- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data (must include geometry if GeoDataFrame, or be joinable to geo_data via location_column)
geo_data (Union['gpd.GeoDataFrame', str, Path, Dict, None]) – GeoDataFrame, path to GeoJSON, GeoJSON dict, or None. If data is already a GeoDataFrame this can be omitted.
location_column (str) – Column to join data ↔ geo_data on
value_column1 (str) – First variable (X-axis in bivariate scheme)
value_column2 (str) – Second variable (Y-axis in bivariate scheme)
title (str) – Map title
width (float) – Map width in inches
height (float) – Map height in inches
color_scheme (str) – Bivariate color scheme (‘default’, ‘blue_red’, ‘green_orange’)
- Returns:
ReportLab Image object (placeholder — HTML saved to output_dir)
- Return type:
Image
Statistical chart mixins — heatmap, scatter plot, and text heatmap.
- class siege_utilities.reporting.engines.stats_engine.StatsChartMixin[source]
Bases:
objectStatistical chart methods (heatmap, scatter plot, text heatmap).
- create_heatmap(data, x_column=None, y_column=None, value_column=None, title='', width=8.0, height=6.0)[source]
Create a heatmap from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_column (str) – Column name for Y-axis
value_column (str) – Column name for values
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
- Returns:
ReportLab Image object
- Return type:
Image
- create_scatter_plot(data, x_column, y_column, color_column=None, title='', width=6.0, height=4.0)[source]
Create a scatter plot from data.
- Parameters:
data (Union[pd.DataFrame, Dict[str, Any]]) – DataFrame or dictionary with data
x_column (str) – Column name for X-axis
y_column (str) – Column name for Y-axis
color_column (str) – Column name for color coding
title (str) – Chart title
width (float) – Chart width in inches
height (float) – Chart height in inches
- Returns:
ReportLab Image object
- Return type:
Image
- create_heatmap_text_chart(data, x_column, y_column, value_column, title='Text Heatmap', max_width=20, max_height=10, heat_chars=' ░▒▓█')[source]
Create a text-based heatmap visualization
- Parameters:
data (pd.DataFrame) – DataFrame containing the data
x_column (str) – Column name for x-axis labels
y_column (str) – Column name for y-axis labels
value_column (str) – Column name for values
title (str) – Chart title
max_width (int) – Maximum width in characters
max_height (int) – Maximum height in characters
heat_chars (str) – Characters for heat intensity (light to dark)
- Returns:
Formatted text heatmap string
- Return type:
Reports and Documents
Main report generator for siege_utilities reporting system. Orchestrates the creation of comprehensive reports with charts, tables, and branding.
- class siege_utilities.reporting.report_generator.ReportGenerator[source]
Bases:
objectMain report generator that creates comprehensive reports. Integrates templates, charts, and data sources.
- create_analytics_report(title, charts, data_summary='', insights=None, recommendations=None, executive_summary=None, methodology=None)[source]
Create a comprehensive analytics report with multiple sections.
- Parameters:
- Returns:
Dictionary containing report content structure
- Return type:
- create_comprehensive_report(title, author=None, client=None, report_type='analysis', sections=None, appendices=None, table_of_contents=True, page_numbers=True, header_footer=True)[source]
Create a comprehensive report with full document structure.
- Parameters:
- Returns:
Dictionary containing complete report structure
- Return type:
- add_section(report_content, section_type, title, content, level=1, page_break_before=False, page_break_after=False)[source]
Add a new section to an existing report.
- Parameters:
- Returns:
Updated report content
- Return type:
- add_table_section(report_content, title, table_data, headers=None, level=1, table_style='default', sort_by=None, sort_order='asc')[source]
Add a table section to the report.
- Parameters:
title (str) – Section title
table_data (List[List] | pandas.DataFrame) – Table data (list of lists or DataFrame)
level (int) – Section level
table_style (str) – Table styling
sort_by (int | str | None) – Column index or header name to sort by. None preserves existing order.
sort_order (str) –
'asc'or'desc'.
- Returns:
Updated report content
- Return type:
- add_text_section(report_content, title, text_content, level=1, text_style='body')[source]
Add a text section to the report.
- add_chart_section(report_content, title, charts, description='', level=1, layout='vertical')[source]
Add a chart section to the report.
- Parameters:
- Returns:
Updated report content
- Return type:
- add_map_section(report_content, title, maps, map_type='choropleth', description='', level=1)[source]
Add a map section to the report.
- Parameters:
- Returns:
Updated report content
- Return type:
- add_appendix(report_content, title, content, appendix_type='data', level=1)[source]
Add an appendix to the report.
Analytics reports module for siege_utilities reporting system. Integrates with Google Analytics, databases, and other data sources.
- class siege_utilities.reporting.analytics_reports.AnalyticsReportGenerator[source]
Bases:
objectGenerates analytics reports from various data sources. Integrates with Google Analytics, databases, and Spark dataframes.
- create_google_analytics_report(ga_data, date_range='', report_title='')[source]
Create a Google Analytics report.
- create_website_performance_report(performance_data, metrics, report_title='')[source]
Create a website performance report.
- create_custom_analytics_report(data_source, data, report_config)[source]
Create a custom analytics report from various data sources.
- create_monthly_analytics_report(monthly_data, year, month)[source]
Create a monthly analytics report.
- create_quarterly_analytics_report(quarterly_data, year, quarter)[source]
Create a quarterly analytics report.
PowerPoint generation utilities for siege_utilities reporting system. Creates presentations from analytics data and report configurations.
- class siege_utilities.reporting.powerpoint_generator.PowerPointGenerator[source]
Bases:
objectGenerates PowerPoint presentations from analytics data and report configurations. Requires python-pptx package for PowerPoint generation.
Internal-helper convention (writing-code:11): private
_add_*_slidemethods return the python-pptxSlideobject they added. Publiccreate_*_presentationmethods log at INFO when the presentation is saved (floor (b) for the whole flow). The combination satisfies writing-code:11 floor for both the per-slide and the per-presentation observation level: a caller can confirm a specific slide was added by inspecting the return value, and an auditor can confirm a presentation was emitted by greping logs.- create_analytics_presentation(report_data, presentation_title='', include_charts=True, include_tables=True)[source]
Create a PowerPoint presentation from analytics data.
- create_performance_presentation(performance_data, metrics, presentation_title='')[source]
Create a performance metrics presentation.
- create_custom_presentation(presentation_config)[source]
Create a custom PowerPoint presentation based on configuration.
- create_comprehensive_presentation(title, author=None, client=None, presentation_type='analysis', sections=None, slide_layouts=None, include_toc=True, include_agenda=True)[source]
Create a comprehensive PowerPoint presentation with full slide structure.
- Parameters:
title (str) – Presentation title
author (str) – Presentation author
client (str) – Client name
presentation_type (str) – Type of presentation
slide_layouts (Dict[str, str]) – Custom slide layouts for different section types
include_toc (bool) – Include table of contents slide
include_agenda (bool) – Include agenda slide
- Returns:
Dictionary containing complete presentation structure
- Return type:
- add_slide_section(presentation_content, section_type, title, content, level=1, slide_layout='default', notes=None)[source]
Add a new slide section to an existing presentation.
- Parameters:
presentation_content (Dict[str, Any]) – Existing presentation content
section_type (str) – Type of slide section
title (str) – Slide title
content (Any) – Slide content
level (int) – Section level (0=main, 1=section, 2=subsection)
slide_layout (str) – Custom slide layout
notes (str) – Speaker notes for the slide
- Returns:
Updated presentation content
- Return type:
- add_text_slide(presentation_content, title, text_content, level=1, text_style='body', bullet_points=True)[source]
Add a text slide to the presentation.
- Parameters:
- Returns:
Updated presentation content
- Return type:
- add_chart_slide(presentation_content, title, charts, description='', level=1, layout='single_chart')[source]
Add a chart slide to the presentation.
- Parameters:
- Returns:
Updated presentation content
- Return type:
- add_map_slide(presentation_content, title, maps, map_type='choropleth', description='', level=1)[source]
Add a map slide to the presentation.
- Parameters:
- Returns:
Updated presentation content
- Return type:
- add_table_slide(presentation_content, title, table_data, headers=None, level=1, table_style='default', sort_by=None, sort_order='asc')[source]
Add a table slide to the presentation.
- Parameters:
presentation_content (Dict[str, Any]) – Existing presentation content
title (str) – Slide title
table_data (List[List] | pandas.DataFrame) – Table data (list of lists or DataFrame)
level (int) – Section level
table_style (str) – Table styling
sort_by (int | str | None) – Column index or header name to sort by. None preserves existing order.
sort_order (str) –
'asc'or'desc'.
- Returns:
Updated presentation content
- Return type:
- add_comparison_slide(presentation_content, title, comparison_data, level=1)[source]
Add a comparison slide to the presentation.
- add_summary_slide(presentation_content, title, key_points, level=1)[source]
Add a summary slide to the presentation.
- generate_powerpoint_presentation(presentation_content, output_path)[source]
Generate a comprehensive PowerPoint presentation from a structure dict.
Consistent with sibling
create_*_presentationmethods (per writing-code:13): returnsPathon success and raises on failure. The previous bool-return contract conflicted with the sibling family’s raise-on-failure contract and forced callers of the PowerPointGenerator class to handle two failure-indication mechanisms across methods that looked similar.- Parameters:
- Returns:
Path to the saved .pptx file.
- Raises:
Exception – any python-pptx or filesystem error during slide construction or save. Caller pattern-matches on the exception type, not on a boolean.
- Return type:
- create_presentation_from_dataframe(df, presentation_title='', max_slides=10)[source]
Create a PowerPoint presentation from a pandas DataFrame.
- Parameters:
df (pandas.DataFrame) – Pandas DataFrame
presentation_title (str) – Title of the presentation
max_slides (int) – Maximum number of slides to create
- Returns:
Path to the generated PowerPoint file
- Return type:
IDML (InDesign Markup Language) report export.
Provides IDMLExporter for programmatic creation of IDML files that
Adobe InDesign can open, plus a convenience export_report_idml()
function that accepts the same ga_data dict used by the PDF/PPTX
generators.
IDML is a ZIP archive containing a set of XML files (designmap.xml,
Spreads/, Stories/, Resources/, etc.). When the simpleidml library
is installed we delegate to it; otherwise we build the ZIP structure
manually so that no external dependency is required at runtime.
- class siege_utilities.reporting.idml_export.IDMLExporter[source]
Bases:
objectBuild an IDML file programmatically.
- Parameters:
template_path (str or Path, optional) – Path to an existing
.idmltemplate. If provided andsimpleidmlis installed the template is loaded for modification. Otherwise the exporter builds the IDML structure from scratch.page_width (float) – Page width in points (default 612 = US Letter).
page_height (float) – Page height in points (default 792 = US Letter).
- add_text_frame(text, style_name='NormalParagraphStyle', x=72.0, y=72.0, width=468.0, height=36.0)[source]
Add a text frame to the document.
- add_image_frame(image_path, x=72.0, y=72.0, width=200.0, height=200.0)[source]
Add an image placeholder frame.
- add_table(headers, rows, x=72.0, y=72.0, width=468.0, height=200.0)[source]
Add a table as a text frame with tab-separated content.
- siege_utilities.reporting.idml_export.export_report_idml(ga_data, output_path, template_path=None, title='Google Analytics Report')[source]
Export a GA-data report as an IDML file.
Accepts the same
ga_datadict produced bygenerate_sample_ga_data()/fetch_real_ga4_data()and writes an IDML file that Adobe InDesign can open.- Parameters:
- Returns:
The resolved output file path.
- Return type:
Client branding management for siege_utilities reporting system. Handles client-specific configurations, logos, colors, and styling.
- exception siege_utilities.reporting.client_branding.ClientBrandingError[source]
Bases:
RuntimeErrorRaised when a client-branding operation fails unexpectedly.
Use the __cause__ attribute (set via raise … from e) to inspect the underlying error (YAMLError, OSError, ValidationError, etc.).
- class siege_utilities.reporting.client_branding.ClientBrandingManager[source]
Bases:
objectManages client branding configurations for reports. Handles logos, colors, fonts, and styling preferences.
- __init__(config_dir=None)[source]
Initialize the branding manager.
- Parameters:
config_dir (Path | None) – Directory containing branding configuration files
- create_client_branding(client_name, branding_config)[source]
Create a new client branding configuration.
- get_client_branding(client_name)[source]
Get branding configuration for a specific client.
- Parameters:
client_name (str) – Name of the client
- Returns:
Branding configuration dictionary.
- Raises:
ClientBrandingNotFoundError – If no branding configuration exists.
ClientBrandingError – If loading fails for another reason.
- Return type:
- update_client_branding(client_name, updates)[source]
Update an existing client branding configuration.
- Parameters:
- Raises:
ClientBrandingNotFoundError – If no existing branding exists.
ClientBrandingError – If the update fails.
- Return type:
None
- delete_client_branding(client_name)[source]
Delete a client branding configuration.
- Parameters:
client_name (str) – Name of the client to delete
- Raises:
ClientBrandingError – If attempting to delete a predefined template.
ClientBrandingNotFoundError – If no configuration exists for the client.
- Return type:
None
- create_branding_from_template(client_name, template_name, customizations=None)[source]
Create client branding from a predefined template.
- export_branding_config(client_name, export_path)[source]
Export a client branding configuration to a file.
- Parameters:
- Raises:
ClientBrandingNotFoundError – If no branding configuration exists.
ClientBrandingError – If the export fails.
- Return type:
None
- import_branding_config(import_path, client_name=None)[source]
Import a branding configuration from a file.
- Parameters:
- Raises:
ValueError – If the file format is unsupported or validation fails.
ClientBrandingError – If the import fails.
- Return type:
None
- exception siege_utilities.reporting.client_branding.ClientBrandingNotFoundError[source]
Bases:
LookupErrorRaised when a named client’s branding configuration does not exist.
Analytics Reports
Analytics submodule - Analytics-specific report components
Deprecation shim — re-exports from siege_utilities.reporting.analytics_reports.
Moved up one level during ELE-2439 so the reporting/analytics/ subdirectory
can be removed once PollingAnalyzer is deleted in v4.0.0.
See docs/adr/0006-polling-analyzer-location.md.
- class siege_utilities.reporting.analytics.analytics_reports.AnalyticsReportGenerator[source]
Bases:
objectGenerates analytics reports from various data sources. Integrates with Google Analytics, databases, and Spark dataframes.
- create_google_analytics_report(ga_data, date_range='', report_title='')[source]
Create a Google Analytics report.
- create_website_performance_report(performance_data, metrics, report_title='')[source]
Create a website performance report.
- create_custom_analytics_report(data_source, data, report_config)[source]
Create a custom analytics report from various data sources.
- create_monthly_analytics_report(monthly_data, year, month)[source]
Create a monthly analytics report.
- create_quarterly_analytics_report(quarterly_data, year, quarter)[source]
Create a quarterly analytics report.
Polling analysis — cross-tabulation, longitudinal analysis, change detection.
Operates on long-form DataFrames with at least one dimension column and one
numeric metric column (default metric='value'). Callers supply their own
column names via keyword arguments.
- exception siege_utilities.reporting.analytics.polling_analyzer.PollingAnalysisError[source]
Bases:
RuntimeErrorRaised when polling analysis cannot complete due to bad input or config.
- class siege_utilities.reporting.analytics.polling_analyzer.PollingAnalyzer[source]
Bases:
objectCross-dimensional analytics for polling and survey data.
Deprecated since version PollingAnalyzer: predates the
siege_utilities.surveymodule and bundles three unrelated concerns (cross-tabulation, longitudinal analysis, and chart rendering). Use the purpose-built replacements:Survey pipeline:
siege_utilities.survey.crosstab.build_chain()followed bysiege_utilities.survey.render.chain_to_argument()Stats primitives:
siege_utilities.data.statistics.cross_tabulationandsiege_utilities.data.statistics.longitudinal(coming with the survey waves subsystem, ELE-2440)Longitudinal / wave comparisons:
siege_utilities.survey.WaveSet(coming in ELE-2440)
See
docs/adr/0006-polling-analyzer-location.mdfor the rationale. This class will be removed in the v4.0.0.- create_cross_tabulation_matrix(data, dimensions, *, metric='value', top_n=10)[source]
Build pairwise cross-tabulations for all dimension combinations.
- Parameters:
- Returns:
Keys
"{dim1}_x_{dim2}"; values are filtered cross-tab DataFrames.- Return type:
- Raises:
PollingAnalysisError – If a required column is missing or aggregation fails.
- create_longitudinal_analysis(data, time_column, dimensions, *, metric='value', periods=('daily', 'weekly', 'monthly', 'quarterly'))[source]
Aggregate
databy time period and dimension.- Parameters:
data (pd.DataFrame) – Input with a parseable time column.
time_column (str) – Column to convert to datetime and group by period.
dimensions (list of str) – Dimension columns to group within each period.
metric (str, keyword-only) – Numeric column to sum.
periods (tuple of str, keyword-only) – Subset of
{"daily", "weekly", "monthly", "quarterly"}.
- Returns:
{period: {dimension: DataFrame}}.- Return type:
- Raises:
PollingAnalysisError – If the time column cannot be parsed or a period name is unknown.
- create_performance_rankings(data, dimensions, *, metric='value', top_n=10)[source]
Rank the top-N values per dimension by total
metric.- Parameters:
- Returns:
For each dimension, a list of
(value, sum_metric, percentage).percentageis the share of the dimension’s total, in [0, 100].- Return type:
- Raises:
PollingAnalysisError – If a required column is missing.
- create_change_detection_data(current_data, historical_data, *, geographic_column='geography', metric='value')[source]
Compare current vs historical aggregates and compute growth/decline.
- Parameters:
current_data (pd.DataFrame) – Long-form data sharing
geographic_columnandmetriccolumns.historical_data (pd.DataFrame) – Long-form data sharing
geographic_columnandmetriccolumns.geographic_column (str, keyword-only) – Column to aggregate on.
metric (str, keyword-only) – Numeric column to sum.
- Returns:
Columns:
geographic_column,{metric}_current,{metric}_historical,change_pct,change_direction.- Return type:
pd.DataFrame
- Raises:
PollingAnalysisError – If either frame is missing the required columns.
- create_polling_summary(data, *, metric='value', name_column=None)[source]
Build an executive-summary string from a dict of data-type frames.
- Parameters:
- Returns:
Multi-sentence summary.
- Return type:
- Raises:
PollingAnalysisError – If no frame in
datacontains the requestedmetriccolumn, or a frame has no non-metric column to use as a label.
- create_heatmap_visualization(crosstab_data, *, title='Cross-Tabulation Heatmap', metric='value', figsize=(10, 8))[source]
Render a cross-tab as a Seaborn heatmap.
metricis keyword-only; it is used only for the colorbar label. The annotation format is chosen automatically from the data dtype (integer data gets'd', float data gets'.2f').- Parameters:
crosstab_data (pd.DataFrame) – Output of
create_cross_tabulation_matrix().title (str, keyword-only)
metric (str, keyword-only)
- Return type:
matplotlib.figure.Figure
- Raises:
PollingAnalysisError – If matplotlib or seaborn cannot render the input.
Hex Cartograms
Hex cartogram (tile-map) construction and rendering.
A hex cartogram replaces each administrative unit (state, congressional district, county, country) with a single hexagon, positioned to roughly preserve geography. The whole point: small jurisdictions get the same visual weight as large ones, so Wyoming and DC don’t get drowned out by California.
Public API (re-exported from this package):
hex_tile_layout()— build a layout (GeoDataFrame[geometry, code, q, r]) from either a built-in name, an algorithmic placement of a GeoDataFrame, or a hand-drawn mapping registered viaregister_layout().hex_tile_map()— matplotlib renderer that takes a values series + a layout and returns a Figure. Three sizing modes (equal, value_proportional, value_sqrt) per the design discussion.register_layout()— extension hook for user-supplied hand-positioned layouts.BUILTIN_LAYOUTS— set of layout names shipped with the package. Empty in v1; populated as we add canonical layouts in follow-up work.Algorithmenum — placement-algorithm choices:greedy,hungarian,annealing. (force_directedandilpare future work; see ELE-2482.)Sizingenum — sizing modes:equal,value_proportional,value_sqrt.
See docs/source/hex_cartograms.md for the algorithm comparison and
worked examples.
- class siege_utilities.reporting.hex_cartogram.Algorithm[source]
-
Placement-algorithm choices for
hex_tile_layout().- GREEDY = 'greedy'
Sort by area, place in nearest unoccupied hex. < 100 ms typical.
- HUNGARIAN = 'hungarian'
Optimal centroid-distance assignment (no topology term).
- ANNEALING = 'annealing'
Centroid + topology weighted; SA refinement of an initial layout.
- FORCE_DIRECTED = 'force_directed'
Reserved — not implemented in v1.
- ILP = 'ilp'
Reserved — not implemented in v1.
- __new__(value)
- class siege_utilities.reporting.hex_cartogram.Sizing[source]
-
Sizing-mode choices for
hex_tile_map().- EQUAL = 'equal'
Every hex same size; values map to colour only.
- VALUE_PROPORTIONAL = 'value_proportional'
Hex area proportional to value.
- VALUE_SQRT = 'value_sqrt'
Hex side proportional to
√value(perception-correct).
- __new__(value)
- siege_utilities.reporting.hex_cartogram.hex_tile_layout(source, *, code_col='code', algorithm=Algorithm.ANNEALING, components='auto', component_gap=1, hex_size=1.0, seed=None)[source]
Build a hex tile layout.
- Parameters:
source (Union[str, 'gpd.GeoDataFrame']) – Either a registered/builtin layout name, or a GeoDataFrame of polygons to place algorithmically.
code_col (str) – Column name on the GeoDataFrame containing the polygon identifier (e.g. state abbreviation, FIPS code). Ignored when source is a string layout name.
algorithm (Union[Algorithm, str]) – One of
Algorithm(or its string value). Ignored when source is a registered layout name.components (Optional[Union[str, list[list[str]]]]) –
"auto"(default) splits the input into connected components by polygon adjacency and lays each out independently withcomponent_gapempty cells between them."single"forces everything into one component. A pre-computedlist[list[code]]lets the caller specify groups explicitly.component_gap (int) – Number of empty hex cells between neighbouring components in the final output.
hex_size (float) – Cell circumradius in CRS units used for the output geometry.
1.0is fine for visualization; choose a smaller value if you plan to overlay the cartogram on a real map.seed (Optional[int]) – Random seed for the annealing algorithm; ignored otherwise.
- Returns:
GeoDataFrame[geometry, code, q, r]— one hexagon per polygon, with axial coords on each row for downstream tooling.- Return type:
gpd.GeoDataFrame
- siege_utilities.reporting.hex_cartogram.hex_tile_map(values, layout, *, sizing=Sizing.EQUAL, cmap='viridis', code_col='code', label_col='code', title=None, figsize=(10.0, 7.0), edge_color='#888', missing_color='#eeeeee')[source]
Render a hex cartogram.
- Parameters:
values (pd.Series) – Values to encode, indexed by polygon code (matching the
code_colof layout). Codes present in the layout but absent from values render in missing_color.layout (gpd.GeoDataFrame) – GeoDataFrame from
hex_tile_layout()— needs at minimumcode,q,rcolumns.sizing (Union[Sizing, str]) – One of
Sizing(or its string value).EQUALuses the layout’s geometry as-is; the proportional modes scale per-hex around the cell center.cmap (str) – matplotlib colour map name.
code_col (str) – Name of the code column on layout.
label_col (Optional[str]) – Column to write inside each hex (typically the code). Pass
Noneto omit labels.missing_color (str) – Standard mpl knobs.
title (Optional[str])
edge_color (str)
missing_color
- Return type:
matplotlib.figure.Figure
- siege_utilities.reporting.hex_cartogram.register_layout(name, mapping)[source]
Register a hand-positioned layout under name.
The mapping must be
{code: (q, r)}with no duplicate(q, r)pairs. Use any reproducible code convention ("AL","01","al-cd-7");hex_tile_layout()will join your data on whichever column you provide viacode_col.
Placement algorithms for hex cartograms.
Three algorithms shipped in v1:
Greedy — sort polygons by area (largest first), assign each to the nearest unoccupied hex by centroid distance. Fast, baseline quality.
Hungarian — bipartite matching via
scipy.optimize.linear_sum_assignment(). Provably optimal for the centroid-distance objective. Doesn’t model topology, but sets a strong baseline.Simulated annealing — start from greedy or Hungarian, repeatedly swap pairs whose swap improves a weighted
α·centroid_error + β·topology_violationcost. The default for ≤ 200 polygons.
force_directed and ilp are documented as future work in the
ticket; the API allows callers to pass the enum but raises
NotImplementedError so the surface is forward-compatible.
Each algorithm returns a dict[code, AxialCoord] — a mapping from
input polygon ID to its assigned hex cell.
- class siege_utilities.reporting.hex_cartogram.algorithms.Algorithm[source]
-
Placement-algorithm choices for
hex_tile_layout().- GREEDY = 'greedy'
Sort by area, place in nearest unoccupied hex. < 100 ms typical.
- HUNGARIAN = 'hungarian'
Optimal centroid-distance assignment (no topology term).
- ANNEALING = 'annealing'
Centroid + topology weighted; SA refinement of an initial layout.
- FORCE_DIRECTED = 'force_directed'
Reserved — not implemented in v1.
- ILP = 'ilp'
Reserved — not implemented in v1.
- __new__(value)
- siege_utilities.reporting.hex_cartogram.algorithms.place_polygons(gdf, code_col, *, algorithm=Algorithm.ANNEALING, candidate_cells=None, iterations=5000, initial_temperature=1.0, cooling_rate=0.9995, centroid_weight=1.0, topology_weight=0.5, seed=None)[source]
Assign each polygon in gdf to a hex cell.
- Parameters:
gdf (gpd.GeoDataFrame) – GeoDataFrame of input polygons. Must have a geometry column and a string-valued code_col identifying each polygon.
code_col (str) – Column name holding the polygon identifier (used as the key in the returned mapping).
candidate_cells (Optional[list[AxialCoord]]) – Pre-computed pool of axial coords to assign into. If None, uses
bounding_grid()sized to the polygon count.centroid_weight (float)
seed (Optional[int]) – Annealing-specific knobs. Ignored by greedy / hungarian.
iterations (int)
initial_temperature (float)
cooling_rate (float)
centroid_weight
topology_weight (float)
seed
- Returns:
dict[code, (q, r)]mapping each polygon’s code to its hex coordinate.- Raises:
ValueError – Empty GeoDataFrame.
NotImplementedError –
force_directed/ilp(reserved).
- Return type:
Connected-component splitting for non-contiguous admin sets.
CONUS + Alaska + Hawaii is the canonical case: three disconnected groups that each deserve their own sub-grid, with empty hexes between groups so the result reads as separated.
The wrapper:
Build a graph where nodes are polygons and edges are “share a border” (or “centroids within a tunable distance”).
Find connected components.
Lay each component out independently using one of the placement algorithms.
Position the per-component layouts in the output grid by their group centroid, with
component_gapempty hexes between groups.
- siege_utilities.reporting.hex_cartogram.components.find_components(gdf, code_col)[source]
Split gdf into connected components by polygon adjacency.
Two polygons are considered adjacent if their geometries share a border (shapely
touches). Returns a list of lists of polygon codes — each inner list is one component.The result is sorted with the largest component first, then by representative-centroid x-coordinate for stable output across runs.
- siege_utilities.reporting.hex_cartogram.components.offset_layout(layout, *, dq, dr)[source]
Shift every cell in layout by
(dq, dr).Used by the multi-component pipeline after each per-component placement, to position the sub-grid in the final output.
- siege_utilities.reporting.hex_cartogram.components.stitch_components(component_layouts, *, component_gap=1)[source]
Combine per-component layouts into one, separated by
component_gapcells.Components are laid out left-to-right in the order received (which
find_components()already biases by size). Each subsequent component’s q-axis startscomponent_gapcells past the previous component’s max q.
Axial hex-grid coordinate math.
Uses axial (q, r) coordinates with pointy-top hexagons (the
visual convention for cartograms — wider than tall, easier to read state
abbreviations inside). All distance / Cartesian math derives from here;
having one canonical conversion module keeps algorithms / rendering
internally consistent.
Conventions
(q, r)are integers; the third cube coords = -q - ris implicit.Cartesian conversion uses unit-side-length hexes — caller can rescale.
Neighbor offsets: 6 directions, returned in the standard order (E, NE, NW, W, SW, SE).
- siege_utilities.reporting.hex_cartogram.coords.axial_distance(a, b)[source]
Hex-grid Manhattan distance between two axial coordinates.
Equivalent to half the cube-coordinate L1 distance.
- siege_utilities.reporting.hex_cartogram.coords.axial_neighbors(qr)[source]
Return the six neighbors of
qrin standard order.
- siege_utilities.reporting.hex_cartogram.coords.axial_to_cartesian(qr, *, size=1.0)[source]
Convert an axial coord to a Cartesian
(x, y)for a pointy-top hex.sizeis the hex circumradius (corner distance). For unit side-length hexes the natural choice issize = 1.
- siege_utilities.reporting.hex_cartogram.coords.bounding_grid(n_cells, *, aspect_ratio=1.3)[source]
Generate enough hex cells to plausibly hold
n_cellspolygons.Picks a roughly oval grid sized to
aspect_ratio(slightly wider than tall by default — matches the way countries are usually drawn on a page). The grid is generated as offset axial coords centered at(0, 0). Used by greedy and annealing algorithms as the candidate cell pool.
- siege_utilities.reporting.hex_cartogram.coords.hexagon_polygon(qr, *, size=1.0, scale=1.0)[source]
Return the 6 vertices of a pointy-top hexagon at
qr.- Parameters:
- Returns:
A list of 6
(x, y)tuples in counter-clockwise order. The polygon is open (no duplicate-first-point); callers that need a closed ring (matplotlibPolygon, shapely) typically don’t — matplotlib closes automatically; shapely’sPolygonconstructor accepts the open form.- Return type:
Layout dispatcher for hex cartograms.
Resolves three input shapes into a uniform GeoDataFrame[geometry,
code, q, r]:
Built-in name (
"us_states","us_cd_117", etc.) — looks up a registered canonical layout. v1 ships with no built-ins; theBUILTIN_LAYOUTSset is empty until ELE-2482 follow-up work bakes hand-positioned canonical layouts.Algorithmic placement — pass a GeoDataFrame of polygons; the module runs one of the algorithms in
algorithmsto position them on a hex grid.Hand-drawn mapping — register a
dict[code, (q, r)]viaregister_layout()and pass the registered name.
- siege_utilities.reporting.hex_cartogram.layouts.BUILTIN_LAYOUTS: set[str] = {}
Set of layout names shipped with the package. Empty in v1; will grow as canonical layouts (NPR-style US states, US CDs) are added in the ELE-2482 follow-up.
- siege_utilities.reporting.hex_cartogram.layouts.REGISTERED_LAYOUTS: dict[str, dict[str, tuple[int, int]]] = {}
User-registered layouts, populated by
register_layout().
- siege_utilities.reporting.hex_cartogram.layouts.hex_tile_layout(source, *, code_col='code', algorithm=Algorithm.ANNEALING, components='auto', component_gap=1, hex_size=1.0, seed=None)[source]
Build a hex tile layout.
- Parameters:
source (Union[str, 'gpd.GeoDataFrame']) – Either a registered/builtin layout name, or a GeoDataFrame of polygons to place algorithmically.
code_col (str) – Column name on the GeoDataFrame containing the polygon identifier (e.g. state abbreviation, FIPS code). Ignored when source is a string layout name.
algorithm (Union[Algorithm, str]) – One of
Algorithm(or its string value). Ignored when source is a registered layout name.components (Optional[Union[str, list[list[str]]]]) –
"auto"(default) splits the input into connected components by polygon adjacency and lays each out independently withcomponent_gapempty cells between them."single"forces everything into one component. A pre-computedlist[list[code]]lets the caller specify groups explicitly.component_gap (int) – Number of empty hex cells between neighbouring components in the final output.
hex_size (float) – Cell circumradius in CRS units used for the output geometry.
1.0is fine for visualization; choose a smaller value if you plan to overlay the cartogram on a real map.seed (Optional[int]) – Random seed for the annealing algorithm; ignored otherwise.
- Returns:
GeoDataFrame[geometry, code, q, r]— one hexagon per polygon, with axial coords on each row for downstream tooling.- Return type:
gpd.GeoDataFrame
- siege_utilities.reporting.hex_cartogram.layouts.register_layout(name, mapping)[source]
Register a hand-positioned layout under name.
The mapping must be
{code: (q, r)}with no duplicate(q, r)pairs. Use any reproducible code convention ("AL","01","al-cd-7");hex_tile_layout()will join your data on whichever column you provide viacode_col.
Matplotlib renderer for hex cartograms.
Three sizing modes per the design discussion:
Sizing.EQUAL— every hex same size. Most charming, perceptually honest for “states are equal political units” (NPR’s pick). Default.Sizing.VALUE_PROPORTIONAL— hex area ∝ value. Tilegram-style.Sizing.VALUE_SQRT— hex side ∝ √value, perception-corrected for size-encoding.
The renderer takes a layout GeoDataFrame (from
hex_tile_layout()) plus a values series indexed by code, and
returns a matplotlib.figure.Figure.
- class siege_utilities.reporting.hex_cartogram.renderer.Sizing[source]
-
Sizing-mode choices for
hex_tile_map().- EQUAL = 'equal'
Every hex same size; values map to colour only.
- VALUE_PROPORTIONAL = 'value_proportional'
Hex area proportional to value.
- VALUE_SQRT = 'value_sqrt'
Hex side proportional to
√value(perception-correct).
- __new__(value)
- siege_utilities.reporting.hex_cartogram.renderer.hex_tile_map(values, layout, *, sizing=Sizing.EQUAL, cmap='viridis', code_col='code', label_col='code', title=None, figsize=(10.0, 7.0), edge_color='#888', missing_color='#eeeeee')[source]
Render a hex cartogram.
- Parameters:
values (pd.Series) – Values to encode, indexed by polygon code (matching the
code_colof layout). Codes present in the layout but absent from values render in missing_color.layout (gpd.GeoDataFrame) – GeoDataFrame from
hex_tile_layout()— needs at minimumcode,q,rcolumns.sizing (Union[Sizing, str]) – One of
Sizing(or its string value).EQUALuses the layout’s geometry as-is; the proportional modes scale per-hex around the cell center.cmap (str) – matplotlib colour map name.
code_col (str) – Name of the code column on layout.
label_col (Optional[str]) – Column to write inside each hex (typically the code). Pass
Noneto omit labels.missing_color (str) – Standard mpl knobs.
title (Optional[str])
edge_color (str)
missing_color
- Return type:
matplotlib.figure.Figure
3D Maps
3D map rendering utilities using pydeck (deck.gl).
Provides hexagonal binning, column layers, and extruded choropleth maps for Jupyter notebooks, Databricks, and standalone HTML export.
Requires the pydeck package (available via the [3d] or [streamlit]
optional-dependency groups).
- class siege_utilities.reporting.map_3d.ThreeDMapRenderer[source]
Bases:
objectHigh-level helper for creating pydeck 3D map visualisations.
- Parameters:
- create_hexagon_layer(df, lat_col='latitude', lon_col='longitude', value_col=None, radius=1000, elevation_scale=100, color_range=None, auto_highlight=True, extruded=True, coverage=0.8, zoom=10.0, pitch=45.0)[source]
Create a 3D hexagonal-bin aggregation layer.
- Parameters:
df (pandas.DataFrame) – Must contain lat_col and lon_col columns.
value_col (str | None) – Column whose values are summed per hex. When None the layer counts the number of points (default pydeck behaviour).
radius (int) – Hexagon radius in metres.
elevation_scale (int) – Multiplier applied to the aggregated elevation value.
lat_col (str)
lon_col (str)
auto_highlight (bool)
extruded (bool)
coverage (float)
zoom (float)
pitch (float)
- Return type:
pdk.Deck
- create_column_layer(df, lat_col='latitude', lon_col='longitude', value_col='value', radius=500, elevation_scale=1, color=None, auto_highlight=True, zoom=10.0, pitch=45.0)[source]
Create a 3D column layer at point locations.
Each row produces a column whose height is proportional to value_col multiplied by elevation_scale.
- create_choropleth_3d(gdf, value_col='value', elevation_scale=100, fill_color=None, line_color=None, opacity=0.8, zoom=10.0, pitch=45.0)[source]
Create an extruded polygon (choropleth) layer from a GeoDataFrame.
The polygons are extruded by value_col multiplied by elevation_scale, giving a 3D bar-on-map effect.
- Parameters:
- Return type:
pdk.Deck
- siege_utilities.reporting.map_3d.create_3d_columns(df, lat_col='latitude', lon_col='longitude', value_col='value', **kwargs)[source]
Convenience wrapper — create a column 3D map.
Accepts all keyword arguments supported by
ThreeDMapRenderer.create_column_layer().
- siege_utilities.reporting.map_3d.create_3d_hexbin(df, lat_col='latitude', lon_col='longitude', **kwargs)[source]
Convenience wrapper — create a hexagonal-bin 3D map.
Accepts all keyword arguments supported by
ThreeDMapRenderer.create_hexagon_layer().
Pages
Pages submodule - OOP page hierarchy for reports
- class siege_utilities.reporting.pages.Page[source]
Bases:
ABCAbstract base class for all report pages
- class siege_utilities.reporting.pages.TitlePage[source]
Bases:
PageTitle page implementation
- class siege_utilities.reporting.pages.TableOfContentsPage[source]
Bases:
PageTable of contents page implementation
- class siege_utilities.reporting.pages.ContentPage[source]
Bases:
PageBase class for content pages (sections, charts, tables)
Page Models - OOP hierarchy for report pages
- class siege_utilities.reporting.pages.page_models.TableType[source]
Bases:
Enum- SINGLE_RESPONSE = 'single_response'
- MULTIPLE_RESPONSE = 'multiple_response'
- CROSS_TAB = 'cross_tab'
- LONGITUDINAL = 'longitudinal'
- RANKING = 'ranking'
- MEAN_SCALE = 'mean_scale'
- BANNER = 'banner'
- class siege_utilities.reporting.pages.page_models.Argument[source]
Bases:
objectAtomic report unit: headline → narrative → table → visualization(s).
- layout is auto-resolved in __post_init__:
map_figure present → “full_width” (stacked: title / table / figure)
map_figure absent → “side_by_side” (title top, table left, figure right)
- __init__(headline, narrative, table, table_type, chart=None, map_figure=None, layout='auto', base_note=None, source_note=None, tags=<factory>)
- class siege_utilities.reporting.pages.page_models.Page[source]
Bases:
ABCAbstract base class for all report pages
- class siege_utilities.reporting.pages.page_models.TitlePage[source]
Bases:
PageTitle page implementation
- class siege_utilities.reporting.pages.page_models.TableOfContentsPage[source]
Bases:
PageTable of contents page implementation