pycsamt.api.style#
pycsamt.api.style#
Central visual-style system for the entire pyCSAMT package.
All plot functions that respect the style system read from the
module-level singleton PYCSAMT_STYLE. Users configure it once
and every subsequent figure inherits those choices.
Quick start#
Apply a named preset:
from pycsamt.api.style import use_style
use_style("publication") # grayscale publication look
use_style("dark") # dark-background figures
Override specific attributes:
from pycsamt.api.style import configure_style
configure_style(
rose__compass_labels = "degrees", # dotted path: section__attr
multiline__mode = "gradient",
multiline__base_color = "red",
mt__xy__color = "#003f88",
)
Temporary changes with a context manager:
from pycsamt.api.style import PYCSAMT_STYLE
with PYCSAMT_STYLE.context("publication"):
fig = plot_phase_tensor_rose(sites)
# reverts to previous state automatically
Build a fully custom style and share it:
from pycsamt.api.style import PyCSAMTStyle, MultilineStyle
s = PyCSAMTStyle()
s.multiline = MultilineStyle(mode="gradient", base_color="teal")
s.mt.xy.color = "#004e89"
# pass to functions that accept style=
plot_phase_tensor_rose(sites, style=s.rose)
Style sections#
RoseStyle— rose diagram visuals (bars, rings, compass, mean line)MultilineStyle— gradient or cycle coloring for multi-line plotsMTComponentStyle— consistent per-component colors (XY/YX/XX/YY/TE/TM)CorrectionStyle— before/after pair for any 1-D correction workflowRawDataStyle— black diagnostic traces for unprocessed observations
Module Attributes
Package-level singleton. |
Functions
|
Configure |
Reset |
|
|
Apply a named full-package style preset to |
Classes
|
Consistent before/after visual pair for any 1-D correction workflow. |
|
Consistent colours and markers for MT impedance components and modes. |
|
Gradient-first coloring for multi-line (multi-station / multi-profile) plots. |
|
Visual style for phase-tensor ellipse plots (psection, map, summary). |
|
Global visual-style container for pyCSAMT. |
|
Visual style for raw, unprocessed EM observations. |
- class pycsamt.api.style.PyCSAMTStyle(preset=None)[source]#
Bases:
objectGlobal visual-style container for pyCSAMT.
Holds five style sub-objects:
rose—RoseStylemultiline—MultilineStylemt—MTComponentStylecorrection—CorrectionStyleraw—RawDataStylept_ellipse—PhaseTensorEllipseStyle
The module-level singleton
PYCSAMT_STYLEis the recommended entry point; import it and mutate it in your script or notebook before creating figures.- Parameters:
preset (str or None) – Named preset to initialise from.
None→"pycsamt".
Examples
Inspect the current style:
from pycsamt.api.style import PYCSAMT_STYLE print(PYCSAMT_STYLE)
Apply a named preset:
PYCSAMT_STYLE.use("publication")
Configure individual attributes with dotted paths:
PYCSAMT_STYLE.configure( rose__compass_labels="degrees", multiline__base_color="red", mt__xy__color="#003f88", )
Temporary style change (context manager):
with PYCSAMT_STYLE.context("dark"): fig = plot_phase_tensor_rose(sites)
- use(preset)[source]#
Apply a named full-package style preset.
- Parameters:
preset (str) –
"pycsamt"— default: gradient bars, NESW compass, blue/red MT, blue-dashed / red-solid correction pair."publication"— grayscale, degree compass, open markers."dark"— dark-background optimised colours.- Raises:
ValueError – If preset is not registered.
- Return type:
None
- configure(**kw)[source]#
Configure style attributes using double-underscore dotted paths.
- Parameters:
**kw (Any) – Each key uses
__as a section separator, e.g.rose__compass_labels="degrees",mt__xy__color="#003f88",multiline__base_color="red".- Return type:
None
Examples
>>> PYCSAMT_STYLE.configure( ... rose__compass_labels="degrees", ... rose__show_secondary=False, ... multiline__mode="gradient", ... multiline__base_color="red", ... mt__xy__color="#003f88", ... mt__yx__lw=2.0, ... )
- context(preset=None, **kw)[source]#
Temporarily apply a preset and/or overrides, then restore.
- Parameters:
preset (str or None) – Named preset to activate inside the context.
**kw – Additional dotted-path overrides (same syntax as
configure()).
- Yields:
PyCSAMTStyle – The (temporarily modified) style object.
- Return type:
Generator[PyCSAMTStyle, None, None]
Examples
>>> with PYCSAMT_STYLE.context("publication", mt__xy__lw=2.0): ... fig = plot_phase_tensor_rose(sites)
- class pycsamt.api.style.MultilineStyle(mode='gradient', base_color='blue', cmap=None, dark=0.85, light=0.25, reverse=False, lw=1.5, alpha=0.85, cycle_palette=<factory>)[source]#
Bases:
objectGradient-first coloring for multi-line (multi-station / multi-profile) plots.
When mode is
"gradient", the n lines returned bycolors()are shades of the same hue arranged from dark (line 0) to light (line n-1) — or reversed. This preserves visual coherence while still making individual lines distinguishable.- Parameters:
mode ({"gradient", "cycle", "matplotlib"}) –
"gradient"— sequential shades from base_color / cmap."cycle"— rotate through a fixed palette (default:tab10)."matplotlib"— fall back to matplotlib’s default"C0","C1", … colour cycle.base_color (str) – Base hue for
mode="gradient". If cmap isNone, a sequential colormap is auto-selected from this colour name (e.g."blue"→"Blues_r"). Any matplotlib colour spec works; unrecognised names fall back to cmap if set, else"Blues_r".cmap (str or None) – Explicit colormap override. Takes precedence over base_color for cmap selection.
dark (float) – Fraction (0–1) of the cmap for the darkest (first) line. Default
0.85avoids pure black.light (float) – Fraction for the lightest (last) line. Default
0.25avoids near-white.reverse (bool) – If
True, light lines come first and dark lines last.lw (float) – Default line width for multi-line plots.
alpha (float) – Default line alpha.
cycle_palette (list of str) – Colour list used when mode is
"cycle".
- colors(n)[source]#
Return n colours for a multi-line plot.
- Parameters:
n (int) – Number of lines / profiles.
- Returns:
RGBA tuples (for
"gradient") or colour strings (for"cycle"/"matplotlib").- Return type:
Examples
>>> ms = MultilineStyle(mode="gradient", base_color="red") >>> colors = ms.colors(5) # 5 shades of red, dark → light
- line_kwargs(idx, n, **overrides)[source]#
Return
ax.plotkeyword arguments for line idx of n.- Parameters:
- Return type:
Examples
>>> kw = ms.line_kwargs(0, 5) >>> ax.plot(x, y, **kw)
- class pycsamt.api.style.MTComponentStyle(xy=<factory>, yx=<factory>, xx=<factory>, yy=<factory>, te=<factory>, tm=<factory>, det=<factory>)[source]#
Bases:
objectConsistent colours and markers for MT impedance components and modes.
- Variables:
xy (_MTComp) – Off-diagonal XY component (TE-like). Default: solid blue circles.
yx (_MTComp) – Off-diagonal YX component (TM-like). Default: solid red squares.
xx (_MTComp) – Diagonal XX component. Default: dashed green upward triangles.
yy (_MTComp) – Diagonal YY component. Default: dashed purple downward triangles.
te (_MTComp) – TE mode (when TE/TM decomposition is used). Default: blue circles.
tm (_MTComp) – TM mode. Default: red squares.
det (_MTComp) – Determinant / rotationally invariant quantity. Default: grey circles.
- Parameters:
xy (_MTComp)
yx (_MTComp)
xx (_MTComp)
yy (_MTComp)
te (_MTComp)
tm (_MTComp)
det (_MTComp)
Examples
Spread kwargs into a matplotlib call:
ax.errorbar(per, rho, drho, **style.mt.xy.errorbar_kwargs())
Override for one call only:
kw = style.mt.yx.plot_kwargs(lw=2.5, alpha=1.0)
Change the XY colour package-wide:
PYCSAMT_STYLE.mt.xy.color = "#003f88"
- xy: _MTComp#
- yx: _MTComp#
- xx: _MTComp#
- yy: _MTComp#
- te: _MTComp#
- tm: _MTComp#
- det: _MTComp#
- class pycsamt.api.style.RoseStyle(bar_style='gradient', bar_color='#e53935', bar_alpha=0.88, bar_edgecolor='none', bar_edgelw=0.4, cmap='YlOrRd', outer_ring_lw=2.5, outer_ring_color='0.12', n_rings=3, ring_color='0.75', ring_ls=':', ring_lw=0.7, ring_labels=None, ring_label_angle=22.5, ring_label_fontsize=7.0, ring_label_color='0.30', ring_label_fmt='{:.0f}', spoke_every=45.0, spoke_color='0.72', spoke_ls=':', spoke_lw=0.7, compass_labels='NESW', compass_fontsize=8.5, compass_color='0.15', compass_fontweight='bold', show_mean=True, mean_color='crimson', mean_lw=2.2, mean_ls='-', show_secondary=True, secondary_color=None, secondary_ls='--', secondary_lw=None, show_annotation=True, annotation_pos=(0.05, 0.93), annotation_fontsize=8.0, annotation_bg='white', annotation_ec='0.25', show_n=True)#
Bases:
objectVisual style bundle shared by all pycsamt rose diagram functions.
Every attribute maps 1-to-1 to a keyword argument accepted by
plot_strike_rose()andplot_phase_tensor_rose(). Pass an instance via thestyle=parameter of either function; individual kwargs still override the style.- Variables:
bar_style ({"gradient", "solid", "bands"}) –
"gradient"— bar height mapped to cmap;"solid"— uniform bar_color;"bands"— one colour per period sub-band (stacked).bar_color (str) – Bar fill colour for
bar_style="solid".bar_alpha (float) – Bar opacity (0–1).
bar_edgecolor (str) – Bar edge colour.
"none"disables edges.bar_edgelw (float) – Bar edge line-width.
cmap (str) – Matplotlib colormap name for
bar_style="gradient".outer_ring_lw (float) – Line-width of the bold outer bounding circle.
outer_ring_color (str) – Colour of the outer bounding circle.
n_rings (int) – Number of concentric reference rings inside the plot.
ring_color (str) – Colour of concentric rings.
ring_ls (str) – Line-style of concentric rings (
":"dotted,"--"dashed, …).ring_lw (float) – Line-width of concentric rings.
ring_labels (list[float] or None) – Explicit count values to annotate on the rings (e.g.
[25, 50, 75, 100]).None→ evenly auto-spaced.ring_label_angle (float) – Clockwise degrees from North where count labels appear.
ring_label_fontsize (float) – Font size for ring count annotations.
ring_label_color (str) – Colour for ring count annotations.
ring_label_fmt (str) – Python format string for ring labels (e.g.
"{:.0f}").spoke_every (float) – Angular spacing (degrees) between radial spokes / tick marks.
spoke_color (str) – Colour of radial spokes.
spoke_ls (str) – Line-style of radial spokes.
spoke_lw (float) – Line-width of radial spokes.
compass_labels ({"NESW", "degrees", "none"}) – Perimeter labels.
"NESW"→ N/E/S/W;"degrees"→ 0°/45°/…;"none"→ hidden.compass_fontsize (float) – Font size for compass / degree perimeter labels.
compass_color (str) – Colour for perimeter labels.
compass_fontweight (str) – Font weight for perimeter labels (
"bold","normal", …).show_mean (bool) – Draw the mean direction as a diameter line through the centre.
mean_color (str) – Colour of the mean direction line.
mean_lw (float) – Line-width of the mean direction line.
mean_ls (str) – Line-style of the mean direction line.
show_secondary (bool) – Draw the 180°-conjugate (axial-symmetry) mean line.
secondary_color (str or None) – Colour of the conjugate line.
None→ same as mean_color.secondary_ls (str) – Line-style of the conjugate line.
secondary_lw (float or None) – Line-width of the conjugate line.
None→ same as mean_lw.show_annotation (bool) – Show the text box with mean angle and count.
annotation_pos ((float, float)) – Axes-fraction
(x, y)position of the annotation box.annotation_fontsize (float) – Font size of the annotation text.
annotation_bg (str) – Background colour of the annotation box.
annotation_ec (str) – Edge colour of the annotation box.
show_n (bool) – Append
n = N(data-point count) to the annotation text.
- Parameters:
bar_style (str)
bar_color (str)
bar_alpha (float)
bar_edgecolor (str)
bar_edgelw (float)
cmap (str)
outer_ring_lw (float)
outer_ring_color (str)
n_rings (int)
ring_color (str)
ring_ls (str)
ring_lw (float)
ring_label_angle (float)
ring_label_fontsize (float)
ring_label_color (str)
ring_label_fmt (str)
spoke_every (float)
spoke_color (str)
spoke_ls (str)
spoke_lw (float)
compass_labels (str)
compass_fontsize (float)
compass_color (str)
compass_fontweight (str)
show_mean (bool)
mean_color (str)
mean_lw (float)
mean_ls (str)
show_secondary (bool)
secondary_color (str | None)
secondary_ls (str)
secondary_lw (float | None)
show_annotation (bool)
annotation_pos (tuple)
annotation_fontsize (float)
annotation_bg (str)
annotation_ec (str)
show_n (bool)
- copy(**overrides)#
Return a shallow copy with overrides applied.
- Parameters:
**overrides (Any) – Any
RoseStyleattribute name and its new value.- Returns:
A new
RoseStyleinstance.- Return type:
- Raises:
ValueError – If an unknown attribute name is passed.
Examples
>>> rs = RoseStyle() >>> rs2 = rs.copy(compass_labels="degrees", show_secondary=False)
- class pycsamt.api.style.CorrectionStyle(before=<factory>, after=<factory>)[source]#
Bases:
objectConsistent before/after visual pair for any 1-D correction workflow.
Every correction plot in pyCSAMT (static-shift, near-field, noise removal, …) uses the same two-curve convention so that users can read results at a glance across all figures:
before — blue dashed line with hollow markers
after — red solid line with hollow markers
The two colours deliberately mirror
MTComponentStyle.xy(blue) andMTComponentStyle.yx(red) so the whole package stays visually coherent.- Variables:
before (_MTComp) – Style for the uncorrected / original curve.
after (_MTComp) – Style for the corrected curve.
- Parameters:
before (_MTComp)
after (_MTComp)
Examples
Use directly in a plot function:
cs = PYCSAMT_STYLE.correction ax.plot(period, rho_before, **cs.before.plot_kwargs()) ax.plot(period, rho_after, **cs.after.plot_kwargs())
Override just the line-width for one call:
kw_before = cs.before.plot_kwargs(lw=2.0)
Change the before colour package-wide:
PYCSAMT_STYLE.correction.before.color = "#005a9e"
Use dotted-path configure:
configure_style( correction__before__color = "#005a9e", correction__after__color = "#9b0000", )
- before: _MTComp#
- after: _MTComp#
- class pycsamt.api.style.PhaseTensorEllipseStyle(normalise_by='cell', scale=0.85, s1_ref=None, min_aspect=0.18, c_by='skew', cmap='RdBu_r', clim=None, clim_pct=(5.0, 95.0), symmetric_clim=True, alpha=0.92, edgecolor='k', linewidth=0.2, skew_threshold=3.0, mark_3d=True, lw_3d_factor=3.0, show_ref=True, ref_edgecolor='k', ref_lw=0.8, ref_fontsize=6.5)[source]#
Bases:
objectVisual style for phase-tensor ellipse plots (psection, map, summary).
Each plotted ellipse simultaneously encodes five physical quantities:
Width ∝ φ_max (s1 eigenvalue — mean phase level)
Height ∝ φ_min (s2 eigenvalue — minimum phase, ≤ φ_max)
Aspect ratio = φ_min/φ_max — ellipticity (1 = isotropic / 1-D)
Rotation angle = θ (CCW from E) — geoelectric-strike indicator
Fill colour — any scalar mapped through cmap (default: skewness β)
The style groups these into five sections:
Sizing (scale, normalise_by, s1_ref) — how big each ellipse is
Colour/fill (c_by, cmap, clim, …) — what drives the fill
Edge/border (edgecolor, linewidth, alpha) — ellipse outline
3-D cell marker (skew_threshold, mark_3d, lw_3d_factor) — highlight 3-D cells
Reference circle (show_ref, ref_edgecolor, ref_lw, ref_fontsize)
- Parameters:
normalise_by (
"cell"|"unity"|"abs") –Size normalisation strategy:
"cell"The 90th-percentile s1 fills scale of its grid cell. Relative sizes are preserved across stations/periods.
"unity"s1_ref = tan 45° = 1.0 (1-D half-space reference). A perfectly 1-D tensor plots as a circle of radius scale.
"abs"Raw data units: width = scale × s1 (legacy behaviour).
scale (float, default
0.85) – Fraction of each grid cell occupied by the normalised ellipse. Values above 1 produce overlap between adjacent cells.s1_ref (float or None) – Manual reference s1. Overrides the automatic reference computed from the data under
"cell"and"unity"modes.min_aspect (float, default
0.18) – Minimum height/width ratio enforced on every drawn ellipse. Real (noisy) EDI data frequently has φ_min ≈ 0 at some stations/periods, which collapses the ellipse to a near-invisible sliver. Flooring the height atmin_aspect × widthkeeps every cell visible as a proper oval while leaving φ_max, θ and fill colour untouched. Set to0to recover the raw (possibly degenerate) ellipticity.c_by (str, default
"skew") – Quantity mapped to fill colour. Supported values:"skew","beta","|skew|","|beta|","theta","|theta|","ellipt","phi_mean","phi_max","phi_min","s1","s2","alpha".cmap (str, default
"RdBu_r") – Matplotlib colormap. WhenNone, a sensible default is chosen automatically from c_by (e.g."RdBu_r"for skewness,"viridis"for ellipticity,"hsv"for strike angle).clim ((vmin, vmax) or None) – Explicit colour axis limits.
Nonederives limits from clim_pct / skew_threshold.clim_pct ((lo, hi), default
(5.0, 95.0)) – Percentile limits used for automatic colour scaling.symmetric_clim (bool, default
True) – Force vmin = −vmax for diverging quantities (skewness, etc.). Automatically disabled whenNoneis the appropriate default.alpha (float, default
0.92) – Ellipse fill opacity.edgecolor (str, default
"k") – Ellipse border colour. Set to"none"to suppress borders.linewidth (float, default
0.2) – Normal (non-3-D) ellipse border width in points.skew_threshold (float, default
3.0) – |β| threshold (degrees) above which a cell is flagged as 3-D. 3-D cells receive a thicker border when mark_3d isTrue. Set toNoneto disable 3-D flagging.mark_3d (bool, default
True) – Draw a thicker border on ellipses where |β| > skew_threshold.lw_3d_factor (float, default
3.0) – Multiplier applied to linewidth for 3-D flagged cells.show_ref (bool, default
True) – Draw a reference circle (s1 = s1_ref) in the corner of the pseudo-section as a scale indicator.ref_edgecolor (str, default
"k") – Border colour of the reference circle.ref_lw (float, default
0.8) – Border line width of the reference circle.ref_fontsize (float, default
6.5) – Font size of the reference-circle label.
Examples
Use the style in a plot call:
from pycsamt.api.style import PYCSAMT_STYLE es = PYCSAMT_STYLE.pt_ellipse plot_phase_tensor_psection(sites, **es.to_kwargs())
Switch colour quantity and cmap in one call:
plot_phase_tensor_psection( sites, **es.copy(c_by="theta", cmap=None).to_kwargs(), )
Configure package-wide:
configure_style( pt_ellipse__c_by = "ellipt", pt_ellipse__cmap = "viridis", pt_ellipse__edgecolor = "none", pt_ellipse__scale = 0.80, )
- resolve_cmap()[source]#
Return the effective colormap name, auto-selecting from c_by when cmap is
None.Examples
>>> es = PhaseTensorEllipseStyle(c_by="theta", cmap=None) >>> es.resolve_cmap() 'hsv'
- Return type:
- resolve_symmetric_clim()[source]#
Return effective symmetric_clim flag, honouring c_by natural symmetry.
- Return type:
- to_kwargs()[source]#
Return a dict of kwargs ready to spread into any phase-tensor plot function.
The dict covers every parameter currently accepted by
plot_phase_tensor_psection()andplot_phase_tensor_summary().Parameters that are style-only (e.g. lw_3d_factor, ref_edgecolor, ref_lw, ref_fontsize) are not included here because the plot functions do not yet accept them; they are preserved in the style for forward compatibility and will be added to the returned dict once the plot functions are updated.
Examples
>>> ax = plot_phase_tensor_psection(sites, **PYCSAMT_STYLE.pt_ellipse.to_kwargs())
- class pycsamt.api.style.RawDataStyle(color='black', ls=':', lw=0.8, marker='.', ms=3.0, mfc='black', mew=0.5, alpha=0.85, capsize=1.5, elinewidth=0.6, label='raw')[source]#
Bases:
objectVisual style for raw, unprocessed EM observations.
Raw data should be visually distinct from processed or modelled data. The package convention is therefore a restrained black trace with small markers and thin connecting lines. Plot functions may use this style automatically when called with
raw=Trueunless users explicitly pass colors or force a processed-data style.- Parameters:
- pycsamt.api.style.PYCSAMT_STYLE: PyCSAMTStyle = PyCSAMTStyle rose.bar_style = 'gradient' rose.cmap = 'YlOrRd' rose.compass_labels = 'NESW' rose.show_mean = True rose.show_secondary = True multiline.mode = 'gradient' multiline.base_color = 'blue' multiline.dark/light = 0.85/0.25 mt.xy color='#1f77b4' marker='o' mt.yx color='#d62728' marker='s' mt.te color='#1f77b4' ls='-' mt.tm color='#d62728' ls='-' correction.before color='#1f77b4' ls='--' label='before' correction.after color='#d62728' ls='-' label='after' raw color='black' marker='.' ls=':' lw=0.8 pt_ellipse normalise_by='cell' scale=0.85 c_by='skew' cmap='RdBu_r' pt_ellipse edgecolor='k' lw=0.2 alpha=0.92 mark_3d=True skew_thresh=3.0#
Package-level singleton. Import and mutate this object to configure all pycsamt figures globally.
- pycsamt.api.style.use_style(preset)[source]#
Apply a named full-package style preset to
PYCSAMT_STYLE.- Parameters:
preset (str) – One of
"pycsamt","publication","dark".- Return type:
None
Examples
>>> from pycsamt.api.style import use_style >>> use_style("publication")
- pycsamt.api.style.reset_style()[source]#
Reset
PYCSAMT_STYLEto package defaults.Examples
>>> from pycsamt.api.style import reset_style >>> reset_style()
- Return type:
None
- pycsamt.api.style.configure_style(**kw)[source]#
Configure
PYCSAMT_STYLEwith dotted-path keyword arguments.- Parameters:
**kw (Any) – Dotted-path attributes using
__as separator, e.g.rose__compass_labels="degrees",multiline__base_color="red",mt__xy__color="#003f88".- Return type:
None
Examples
>>> from pycsamt.api.style import configure_style >>> configure_style( ... rose__compass_labels="degrees", ... multiline__mode="gradient", ... multiline__base_color="teal", ... mt__xy__color="#003f88", ... mt__yx__color="#9b0000", ... )
- pycsamt.api.style.resolve_rose_style(style, **overrides)#
Resolve style to a
RoseStyle, then apply overrides.- Parameters:
- Return type:
- Raises:
ValueError – If style is a string that does not match a known preset.
TypeError – If style is not a str, RoseStyle, or None.
Examples
>>> rs = resolve_rose_style("pycsamt", compass_labels="degrees") >>> rs.compass_labels 'degrees'