Skip to content

bulanik.plot

Needs the plot extra (pip install "bulanik[plot]"). The package re-exports the plotting functions of its submodules (numbers, sets, inference, mcdm) and the house style (PALETTE, theme, current_theme).

plot

Publication-quality plots of fuzzy numbers, linguistic variables, inference and MCDM results.

Needs the plot extra (pip install "bulanik[plot]", which installs matplotlib); the rest of bulanik stays dependency-free.

Every function takes keyword-only options and an optional ax; without one it creates a new figure. It returns the matplotlib Axes and never calls plt.show(), so you can add annotations, save or show the figure yourself. Inputs are validated with the library's usual errors (TypeError for a wrong type, ValueError for a bad value).

House style: one validated categorical palette (PALETTE) in fixed slot order, 2 px lines with soft translucent fills, hairline axes and grid, direct labels instead of legends. Wrap plotting and saving in theme to get the light or dark variant; outside a theme the light variant's colours are used.

Examples:

>>> from bulanik import TFN, plot
>>> with plot.theme("light"):
...     ax = plot.membership([TFN(1, 2, 4), TFN(2, 4, 5)], labels=["A", "B"])
>>> ax.get_xlabel()
'$x$'

PALETTE module-attribute

PALETTE: Mapping[str, tuple[str, ...]] = MappingProxyType({'light': ('#2a78d6', '#eb6834', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#6250d6', '#e34948'), 'dark': ('#3987e5', '#d95926', '#199e70', '#c98500', '#d55181', '#2ea32e', '#9085e9', '#e66767')})

The categorical palette: eight hues in a fixed order, one tuple per theme.

Slots are assigned in order and never cycled; a ninth series is an error, not a generated colour. The order passes the dataviz palette validator (lightness band, chroma floor, colour-vision-deficiency separation, normal-vision floor) on a white surface ("light") and on the Material for MkDocs slate surface #1e2129 ("dark"). Three light slots (aqua, yellow, magenta) are below 3:1 contrast on white, so every plot that uses them also labels its series directly.

Examples:

>>> from bulanik.plot import PALETTE
>>> PALETTE["light"][:2]
('#2a78d6', '#eb6834')
>>> len(PALETTE["dark"])
8

current_theme

current_theme() -> Mapping[str, Any]

The tokens of the active theme, as a read-only mapping.

Keys: name ("light" or "dark"), surface (background), text, text_secondary, muted (ink for labels and annotations), grid, axis (hairlines), series (the categorical palette), ramp (five ordinal blue steps, nearest the surface first), sequential (the blue magnitude ramp) and fill_alpha (opacity of the soft fills under curves). Use them to annotate a figure in the house style.

Returns:

Type Description
Mapping[str, Any]

The tokens of the innermost active theme, or of

Mapping[str, Any]

"light" outside any theme.

Examples:

>>> from bulanik import plot
>>> plot.current_theme()["name"]
'light'
>>> with plot.theme("dark"):
...     plot.current_theme()["surface"]
'#1e2129'

theme

theme(name: str = 'light') -> Iterator[Mapping[str, Any]]

Context manager that applies the house style in a light or dark variant.

Inside the block, matplotlib's rc parameters (fonts, sizes, surface and ink colours, hairline axes, 2 px lines, tight saving at 200 dpi) follow the theme, and every bulanik.plot function picks the matching palette. Save figures inside the block so the background matches. Themes nest; the previous settings come back on exit.

Parameters:

Name Type Description Default
name str

"light" (white surface) or "dark" (the Material for MkDocs slate surface #1e2129).

'light'

Yields:

Type Description
Mapping[str, Any]

The theme tokens, as returned by current_theme.

Raises:

Type Description
ValueError

If name is not "light" or "dark".

Examples:

>>> from bulanik import TFN, plot
>>> with plot.theme("dark") as tokens:
...     ax = plot.membership(TFN(1, 2, 4))
>>> tokens["name"], type(ax).__name__
('dark', 'Axes')

mamdani_output

mamdani_output(fis: MamdaniFIS, inputs: Mapping[str, float], output: str | None = None, *, ax: Axes | None = None) -> Axes

How a Mamdani system reaches its crisp output for one set of inputs.

The output variable's terms are drawn as thin outlines. Every rule that fires contributes its consequent set, clipped (implication="min") or scaled ("prod") by its firing strength, as a filled area in its term's colour. The aggregated set (the system's aggregation of the implied sets, on the system's own sampling grid) is the dark outline, and the crisp output from MamdaniFIS.evaluate is the vertical marker. When no rule fires and the system has a default, only the default value is marked.

Parameters:

Name Type Description Default
fis MamdaniFIS required
inputs Mapping[str, float]

Crisp value of every input variable, by name.

required
output str | None

Output variable name; None takes the first output.

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If fis is not a MamdaniFIS.

ValueError

If output is unknown, or an input is missing or outside its universe (as in MamdaniFIS.explain).

NoRuleFiredError

If no rule fires for the output and the system has no default.

Examples:

>>> from bulanik import plot
>>> from bulanik.sets import LinguisticVariable, triangular
>>> from bulanik.inference import MamdaniFIS
>>> service = LinguisticVariable("service", (0, 10), {
...     "poor": triangular(0, 0, 5), "good": triangular(5, 10, 10)})
>>> tip = LinguisticVariable("tip", (0, 20), {
...     "low": triangular(0, 0, 10), "high": triangular(10, 20, 20)})
>>> fis = MamdaniFIS([service], [tip], [
...     "IF service IS poor THEN tip IS low", "IF service IS good THEN tip IS high"])
>>> ax = plot.mamdani_output(fis, {"service": 7.5})
>>> type(ax).__name__
'Axes'

surface

surface(fis: Any, output: str | None = None, *, resolution: int = 41, ax: Axes | None = None) -> Axes

Input-output map of a fuzzy system: a 3-D surface (2 inputs) or a curve (1 input).

Works with every system that has inputs, outputs and evaluate (MamdaniFIS, SugenoFIS, TsukamotoFIS and the interval type-2 systems). Each input universe is sampled at resolution evenly spaced points; where no rule fires (and there is no default) the output is left as a gap. A surface is coloured by height with a one-hue sequential ramp.

Parameters:

Name Type Description Default
fis Any

The fuzzy inference system.

required
output str | None

Output variable name; None takes the first output.

None
resolution int

Samples per input, an integer of at least 2.

41
ax Axes | None

Axes to draw into (3-D for two inputs); None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes (3-D for two inputs).

Raises:

Type Description
TypeError

If fis has no inputs, outputs and evaluate.

ValueError

If the system has more than 2 inputs, output is unknown, resolution is not an integer of at least 2, or ax has the wrong projection.

Examples:

>>> from bulanik import plot
>>> from bulanik.sets import LinguisticVariable, triangular
>>> from bulanik.inference import SugenoFIS, SugenoOutput
>>> x = LinguisticVariable("x", (0, 10), {"lo": triangular(0, 0, 10), "hi": triangular(0, 10, 10)})
>>> y = SugenoOutput("y", {"a": 1.0, "b": 5.0})
>>> fis = SugenoFIS([x], [y], ["IF x IS lo THEN y IS a", "IF x IS hi THEN y IS b"])
>>> ax = plot.surface(fis, resolution=21)
>>> type(ax).__name__
'Axes'

dematel

dematel(result: DEMATELResult, *, arrows: bool = True, ax: Axes | None = None) -> Axes

DEMATEL cause-effect diagram: prominence against relation, with the strong influences.

Each factor is a point at \((D + R,\, D - R)\): right means more involved in the system (prominence), up means a net giver of influence (relation). A hairline at \(D - R = 0\) splits the cause group above from the effect group below; causes take the first palette slot and effects the second. With arrows, every influence \(t_{ij}\) above the threshold (result.relations) is a thin muted arrow from factor \(i\) to factor \(j\), stopping at the edge of its marker; two factors that influence each other get two arrows bent to opposite sides. A stronger influence is a heavier, darker arrow, and the arrow ends that meet on one marker are spread around its edge so the heads stay apart. Factor names are placed clear of the points, the arrows and each other.

The number of arrows is set by the analysis, not by the plot: raise dematel(..., threshold=...) to keep only the strongest influences (the default threshold, the mean of \(T\), often keeps half of them), or pass arrows=False.

The group key ("cause group", "effect group") sits in the right margin, just past the end of the zero line. On a figure of your own with tight subplots, leave some room on the right (constrained layout does this) or the key can be clipped.

Parameters:

Name Type Description Default
result DEMATELResult required
arrows bool

Draw the relations above the threshold.

True
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If result is not a DEMATELResult.

Examples:

>>> from bulanik import plot
>>> from bulanik.mcdm import dematel
>>> r = dematel([[0, 3, 2], [1, 0, 3], [2, 1, 0]], ["a", "b", "c"])
>>> ax = plot.dematel(r)
>>> ax.get_xlabel()
'prominence $D + R$'
References

Gabus and Fontela (1973), Perceptions of the World Problematique: Communication Procedure, Communicating With Those Bearing Collective Responsibility, DEMATEL Report No. 1, Battelle Geneva Research Centre (the cause-effect diagram).

ranking

ranking(result: RankingResult, *, ax: Axes | None = None) -> Axes

Alternatives sorted best first, as a dot plot of their scores.

Rows follow result.ranking (best at the top, numbered), so methods where a lower score is better (VIKOR) read the same way as the others; the x label says which direction is better (VIKOR is known to be lower-is-better; for other methods the direction is read off the ranking). The best alternative is emphasised in the accent colour; every dot carries its score, the others in small muted ink.

Parameters:

Name Type Description Default
result RankingResult required
ax Axes | None

Axes to draw into; None creates a new figure sized to the number of alternatives.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If result is not a RankingResult.

Examples:

>>> from bulanik import plot
>>> from bulanik.mcdm import topsis
>>> r = topsis([[250, 16], [200, 16], [300, 32]], [0.5, 0.5], ["cost", "benefit"])
>>> ax = plot.ranking(r)
>>> type(ax).__name__
'Axes'

weights

weights(result: WeightingResult | BWMResult, *, ax: Axes | None = None) -> Axes

Criteria weights as horizontal bars, largest first, value at each tip.

Bars follow result.ranking. If the method reports a consistency ratio (AHP, fuzzy AHP, BWM), it is shown in the corner.

Parameters:

Name Type Description Default
result WeightingResult | BWMResult required
ax Axes | None

Axes to draw into; None creates a new figure sized to the number of criteria.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If result is neither a WeightingResult nor a BWMResult.

Examples:

>>> from bulanik import plot
>>> from bulanik.mcdm import ahp
>>> r = ahp([[1, 3, 5], [1 / 3, 1, 3], [1 / 5, 1 / 3, 1]], criteria=["cost", "quality", "risk"])
>>> ax = plot.weights(r)
>>> type(ax).__name__
'Axes'

alpha_cuts

alpha_cuts(number: TFN | TrFN, *, levels: int | Sequence[float] = 11, ax: Axes | None = None) -> Axes

The \(\alpha\)-cuts of a number as stacked horizontal intervals.

Every level \(\alpha\) is drawn as the interval alpha_cut(α) at height \(\alpha\), coloured from light (support, \(\alpha = 0\)) to strong (core, \(\alpha = 1\)), inside the outline of the membership function. This is the picture behind interval arithmetic on fuzzy numbers: an operation acts on each cut separately.

Parameters:

Name Type Description Default
number TFN | TrFN

A TFN or TrFN.

required
levels int | Sequence[float]

Number of evenly spaced levels from 0 to 1 (at least 2), or the levels themselves.

11
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If number is not a TFN or TrFN, or levels is a bool.

ValueError

If levels is below 2, empty, or holds a level outside \([0, 1]\).

Examples:

>>> from bulanik import TFN, plot
>>> ax = plot.alpha_cuts(TFN(1, 2, 4), levels=6)
>>> type(ax).__name__
'Axes'

defuzzification

defuzzification(number: TFN | TrFN, *, scores: Sequence[str] | None = None, ax: Axes | None = None) -> Axes

A number with markers at the crisp values of its score functions.

Each score (score: "centroid", "graded_mean", "mean") is a stem from the axis up to the membership curve, labelled with its name and value. Scores that coincide (the centroid and the mean of a triangle) share one stem.

Parameters:

Name Type Description Default
number TFN | TrFN

A TFN or TrFN.

required
scores Sequence[str] | None

Score names to show; None shows all of them.

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If number is not a TFN or TrFN.

ValueError

If scores is empty or names an unknown score.

Examples:

>>> from bulanik import TrFN, plot
>>> ax = plot.defuzzification(TrFN(1, 2, 3, 6))
>>> type(ax).__name__
'Axes'

it2_number

it2_number(numbers: IT2TrFN | Sequence[IT2TrFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes

Interval type-2 trapezoidal numbers: upper and lower trapezoids and the footprint between them.

Each IT2TrFN is drawn as its upper trapezoid \((a^U_1, 0), (a^U_2, h^U_1), (a^U_3, h^U_2), (a^U_4, 0)\) in a full line, its lower trapezoid (same form, heights \(h^L_1, h^L_2\), which may be below 1) in a thinner line, and the footprint of uncertainty, the area between them, as a soft wash of the same colour (lighter on the dark theme and when many footprints overlap). Numbers take the palette slots in order. Heights below 1 get their own ticks on the membership axis.

Parameters:

Name Type Description Default
numbers IT2TrFN | Sequence[IT2TrFN]

An IT2TrFN or a sequence of at most 8.

required
labels Sequence[str] | None

One label per number, written above the peak of its upper trapezoid.

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If a number is not an IT2TrFN.

ValueError

If there are no numbers or more than 8, or the label count differs from the number count.

Examples:

>>> from bulanik import IT2TrFN, plot
>>> low = IT2TrFN((0, 0.1, 0.1, 0.3, 1, 1), (0.05, 0.1, 0.1, 0.2, 0.9, 0.9))
>>> ax = plot.it2_number(low, labels=["low"])
>>> [line.get_gid() for line in ax.lines]
['upper', 'lower']
References

Mendel, John and Liu (2006), IEEE Transactions on Fuzzy Systems 14(6), 808-821, doi:10.1109/TFUZZ.2006.879986 (footprint of uncertainty). Chen and Lee (2010), Expert Systems with Applications 37(1), 824-833, doi:10.1016/j.eswa.2009.06.094 (the trapezoidal form).

iv_orthopair

iv_orthopair(numbers: IVQROFN | Sequence[IVQROFN], *, q: int | None = None, regions: Sequence[int] | None = None, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes

Interval-valued orthopair numbers as rectangles in the \(\mu\)–\(\nu\) plane.

An IVQROFN \(([\mu_L, \mu_U], [\nu_L, \nu_U])\) is the rectangle \([\mu_L, \mu_U] \times [\nu_L, \nu_U]\): every orthopair \((\mu, \nu)\) it admits. Since \(\mu_U^q + \nu_U^q \le 1\), its upper-right corner, and so the whole rectangle, lies in the feasible region of rung \(q\), drawn as in orthopair. Each number takes the next palette slot from the second on (the first, blue, is the region ramp), as a solid outline over a translucent fill. The fill sits on a knockout of the surface, so its hue stays clean over the region washes (on the dark theme the knockout stays bare: a warm tint over the slate surface turns brown); the region boundaries are drawn over it. A degenerate interval still shows: a zero-width side is a line and a crisp pair is a dot.

Parameters:

Name Type Description Default
numbers IVQROFN | Sequence[IVQROFN]

An IVQROFN (IVIFN, IVPFN, IVFFN) or a sequence of at most 7; may be empty to draw regions only.

required
q int | None

Rung of the one region to draw when regions is None.

None
regions Sequence[int] | None

Rungs whose regions are drawn, e.g. (1, 2, 3). Default: the rungs of the numbers, or (q,), or (1,).

None
labels Sequence[str] | None

One label per number, written by the upper-right corner of its rectangle.

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If a number is not an interval-valued orthopair number.

ValueError

If q or a region is not an integer of at least 1, regions is empty, both q and regions are given, there are more than 7 numbers, or the label count differs from the number count.

Examples:

>>> from bulanik import IVIFN, IVPFN, plot
>>> ax = plot.iv_orthopair([IVIFN(0.5, 0.6, 0.2, 0.3), IVPFN(0.6, 0.8, 0.3, 0.5)], labels=["a", "b"])
>>> type(ax).__name__
'Axes'
References

Atanassov and Gargov (1989), Fuzzy Sets and Systems 31(3), 343-349, doi:10.1016/0165-0114(89)90205-4 (interval-valued intuitionistic sets).

membership

membership(numbers: TFN | TrFN | Sequence[TFN | TrFN], *, labels: Sequence[str] | None = None, alpha_cut: float | None = None, fill: bool = True, ax: Axes | None = None) -> Axes

Membership functions of triangular and trapezoidal numbers on one axis.

Each number is drawn as its exact piecewise-linear membership function with a soft translucent fill, one palette slot per number, and is labelled above its peak. A single number gets its defining points as x ticks. With alpha_cut, every number's \(\alpha\)-cut (alpha_cut) is drawn as a band at height \(\alpha\) with guides down to the axis.

Parameters:

Name Type Description Default
numbers TFN | TrFN | Sequence[TFN | TrFN]

A TFN / TrFN or a sequence of up to 8 of them.

required
labels Sequence[str] | None

One label per number; None labels several numbers with their points and leaves a single number unlabelled.

None
alpha_cut float | None

Level in \([0, 1]\) of an \(\alpha\)-cut band to draw, or None.

None
fill bool

Shade the area under each curve.

True
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If a number is not a TFN or TrFN.

ValueError

If there are no numbers or more than 8, the label count differs from the number count, or alpha_cut is outside \([0, 1]\).

Examples:

>>> from bulanik import TFN, TrFN, plot
>>> ax = plot.membership([TFN(1, 2, 4), TrFN(3, 4, 5, 7)], labels=["A", "B"], alpha_cut=0.5)
>>> type(ax).__name__
'Axes'

neutrosophic

neutrosophic(numbers: NeutrosophicFN | Sequence[NeutrosophicFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes

Neutrosophic numbers as \(T\)/\(I\)/\(F\) radar triangles.

A NeutrosophicFN \((t, i, f)\) has three independent parts in \([0, 1]\); each number is a filled triangle on three spokes (truth at the top, indeterminacy lower left, falsity lower right) over a triangular grid at 0.25 steps. Up to 8 numbers, one palette slot each; several numbers (or given labels) are named in a legend.

Parameters:

Name Type Description Default
numbers NeutrosophicFN | Sequence[NeutrosophicFN]

A NeutrosophicFN or a sequence of up to 8 of them.

required
labels Sequence[str] | None

One label per number; None uses the parts.

None
ax Axes | None

A 2-D axes to draw into (its frame is hidden); None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If a number is not a NeutrosophicFN.

ValueError

If there are no numbers or more than 8, ax is not a 2-D axes, or the label count differs from the number count.

Examples:

>>> from bulanik import NeutrosophicFN, plot
>>> ax = plot.neutrosophic([NeutrosophicFN(0.7, 0.2, 0.1), NeutrosophicFN(0.3, 0.6, 0.5)])
>>> type(ax).__name__
'Axes'

orthopair

orthopair(numbers: QROFN | Sequence[QROFN], *, q: int | None = None, regions: Sequence[int] | None = None, labels: Sequence[str] | None = None, hesitancy: bool = False, ax: Axes | None = None) -> Axes

Orthopair numbers as points in the \(\mu\)–\(\nu\) plane with their feasible regions.

The region of rung \(q\) is \(\mu^q + \nu^q \le 1\); each requested rung is drawn as its boundary curve with a light wash, so nested regions (IFN \(\subset\) PFN \(\subset\) FFN) read as steps of one blue ramp. Numbers are points; with hesitancy=True each point gets a segment along the diagonal to the boundary of its own rung, whose length grows with the hesitancy π (a number on its boundary has none).

Parameters:

Name Type Description Default
numbers QROFN | Sequence[QROFN]

A QROFN (IFN, PFN, FFN) or a sequence of them; may be empty to draw regions only.

required
q int | None

Rung of the one region to draw when regions is None.

None
regions Sequence[int] | None

Rungs whose regions are drawn, e.g. (1, 2, 3). Default: the rungs of the numbers, or (q,), or (1,).

None
labels Sequence[str] | None

One label per number, written next to its point.

None
hesitancy bool

Draw the hesitancy segments.

False
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If a number is not an orthopair number.

ValueError

If q or a region is not an integer of at least 1, regions is empty, both q and regions are given, or the label count differs from the number count.

Examples:

>>> from bulanik import IFN, PFN, plot
>>> ax = plot.orthopair([IFN(0.6, 0.3), PFN(0.7, 0.6)], regions=(1, 2, 3), hesitancy=True)
>>> type(ax).__name__
'Axes'

picture

picture(numbers: PictureFN | Sequence[PictureFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes

Picture fuzzy numbers on the \(\mu\)–\(\eta\)–\(\nu\) ternary simplex.

A PictureFN \((\mu, \eta, \nu)\) has \(\mu + \eta + \nu \le 1\); the rest \(\rho = 1 - \mu - \eta - \nu\) is the refusal degree. The point sits at the barycentric position of \((\mu, \eta, \nu)\) normalised to sum 1 (its balance between positive, neutral and negative membership), and a translucent halo whose radius grows with \(\rho\) shows how much is refused.

Parameters:

Name Type Description Default
numbers PictureFN | Sequence[PictureFN]

A PictureFN or a sequence of them (at least one).

required
labels Sequence[str] | None

One label per number, written next to its point.

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes (its frame is hidden).

Raises:

Type Description
TypeError

If a number is not a PictureFN.

ValueError

If there are no numbers, a number has all three parts 0, or the label count differs from the number count.

Examples:

>>> from bulanik import PictureFN, plot
>>> ax = plot.picture([PictureFN(0.5, 0.2, 0.1), PictureFN(0.2, 0.3, 0.4)], labels=["p", "r"])
>>> type(ax).__name__
'Axes'

spherical

spherical(numbers: SphericalFN | Sequence[SphericalFN], *, labels: Sequence[str] | None = None, ax: Axes | None = None) -> Axes

Spherical fuzzy numbers inside the positive octant of the unit sphere.

A SphericalFN \((\mu, \nu, \pi)\) satisfies \(\mu^2 + \nu^2 + \pi^2 \le 1\): it is a point of the unit ball's positive octant. The sphere patch is drawn translucent with a few parallels and meridians; each point has a drop line to the \(\mu\)–\(\nu\) floor to make its depth readable.

Parameters:

Name Type Description Default
numbers SphericalFN | Sequence[SphericalFN]

A SphericalFN or a sequence of them (at least one).

required
labels Sequence[str] | None

One label per number.

None
ax Axes | None

A 3-D axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib 3-D Axes.

Raises:

Type Description
TypeError

If a number is not a SphericalFN.

ValueError

If there are no numbers, ax is not a 3-D axes, or the label count differs from the number count.

Examples:

>>> from bulanik import SphericalFN, plot
>>> ax = plot.spherical([SphericalFN(0.5, 0.4, 0.3)], labels=["a"])
>>> ax.name
'3d'

it2_set

it2_set(mf_or_term: IT2MF | IT2LinguisticVariable, *, universe: tuple[float, float] | None = None, label: str | None = None, ax: Axes | None = None) -> Axes

Footprint of uncertainty of interval type-2 sets.

The region between the lower \(\underline{\mu}\) and upper \(\overline{\mu}\) membership functions (the footprint of uncertainty, FOU) is shaded; the upper bound is a full line, the lower bound a thinner one. Given an IT2LinguisticVariable, every term is drawn and named above its peak.

Parameters:

Name Type Description Default
mf_or_term IT2MF | IT2LinguisticVariable

An IT2MF or an IT2LinguisticVariable.

required
universe tuple[float, float] | None

The (lo, hi) x range; default: the variable's universe, or for a single IT2MF a range that covers it (e.g. 3.5 sigma around a Gaussian).

None
label str | None

Name written above a single set's peak.

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If mf_or_term is neither an IT2MF nor an IT2LinguisticVariable.

ValueError

If universe is not a pair with lo < hi, or the variable has more than 8 terms.

Examples:

>>> from bulanik import plot
>>> from bulanik.type2 import gaussian_uncertain_mean
>>> ax = plot.it2_set(gaussian_uncertain_mean(4, 6, 1), label="medium")
>>> type(ax).__name__
'Axes'

variable

variable(var_or_scale: LinguisticVariable | LinguisticScale | IT2LinguisticVariable, *, x: float | None = None, ax: Axes | None = None) -> Axes

Every term of a linguistic variable or scale, direct-labelled.

  • A LinguisticVariable, or a LinguisticScale of TFN / TrFN terms: all membership functions on one axis with soft fills, each named above its peak. Up to 8 terms take the categorical palette in order; longer scales (Saaty's 1-9) take an ordered blue ramp. With x, a crisp input is marked and its membership degree in every term it touches is shown.
  • A scale of orthopair, picture, spherical or neutrosophic terms is drawn by orthopair, picture, spherical or neutrosophic, labelled with the term names.
  • An IT2LinguisticVariable is drawn by it2_set.

Parameters:

Name Type Description Default
var_or_scale LinguisticVariable | LinguisticScale | IT2LinguisticVariable

The variable or scale.

required
x float | None

A crisp input to mark (type-1 variables and TFN/TrFN scales only).

None
ax Axes | None

Axes to draw into; None creates a new figure.

None

Returns:

Type Description
Axes

The matplotlib Axes.

Raises:

Type Description
TypeError

If var_or_scale is none of the supported types.

ValueError

If x is outside the universe, or given for a scale or variable that has no crisp axis.

Examples:

>>> from bulanik import plot
>>> from bulanik.scales import EXAMPLE_TFN_7
>>> ax = plot.variable(EXAMPLE_TFN_7, x=4)
>>> type(ax).__name__
'Axes'