Skip to content
LinearScale

LinearScale

Mojo struct 🡭

LinearScale

@memory_only
struct LinearScale

A linear map from the domain endpoints to the range endpoints. range_min/range_max are the pixel positions domain_min/ domain_max land on, not necessarily increasing: a y-axis scale passes range_min=plot_bottom_pixel and range_max=plot_top_pixel, and the map comes out with a negative slope.

Fields

  • domain_min (Float64): The low end of the data domain this scale maps from.
  • domain_max (Float64): The high end of the data domain this scale maps from.
  • range_min (Float64): The pixel position domain_min maps to.
  • range_max (Float64): The pixel position domain_max maps to; not necessarily greater than range_min (a y-axis scale passes a smaller pixel value here).
  • is_log (Bool): False (the default) for a plain linear scale. True for a log10-scaled axis (Plot.scale_y_log()/scale_x_log()): domain_min/domain_max are then in log10-space (see _log_data_extent(), core/extent.mojo) and to_pixel() takes log10() of the real-unit value it’s given before applying the affine map, so every caller keeps passing real-unit values.
  • is_symlog (Bool): Whether domain_min/domain_max are in symlog space and to_pixel() should transform through _symlog_forward (#368). Mutually exclusive with is_log: a value cannot be both linear near zero and logarithmic there.
  • symlog_linthresh (Float64): Half-width of the linear region, in real units. Meaningless unless is_symlog; kept positive by the builders.
  • is_time (Bool): Whether the domain is POSIX seconds and the axis should be labeled as dates and times. Set by Plot.encode_time(); sends ticks() to _time_ticks the way is_log sends it to _log_ticks, and changes nothing about to_pixel() – a time axis is linear in seconds, which is exactly what makes this a labeling problem rather than a projection one.
  • tz_offset (Int): The data’s offset from UTC in seconds, so ticks land on local midnights and month starts and labels read in the zone the caller supplied. Meaningless unless is_time.

Implemented traits

AnyType, Copyable, Deinitable, ImplicitlyCopyable, Movable

Methods

__init__

fn def __init__(out self, domain_min: Float64, domain_max: Float64, range_min: Float64, range_max: Float64, is_log: Bool = False, is_symlog: Bool = False, symlog_linthresh: Float64 = 1, is_time: Bool = False, tz_offset: Int = Int(0))

Construct a LinearScale from an already-known domain and pixel range.

Args:

  • domain_min (Float64): The low end of the data domain.
  • domain_max (Float64): The high end of the data domain.
  • range_min (Float64): The pixel position domain_min maps to.
  • range_max (Float64): The pixel position domain_max maps to.
  • is_log (Bool): Whether domain_min/domain_max are in log10- space and to_pixel() should log-transform its input first; see this field’s own docstring.
  • is_symlog (Bool): Whether the domain is in symlog space.
  • symlog_linthresh (Float64): Half-width of the linear region, real units, when is_symlog.
  • is_time (Bool): Whether the domain is POSIX seconds and the ticks should be dates and times; see the field’s docstring.
  • tz_offset (Int): The data’s offset from UTC in seconds, for placing and labeling those ticks.
  • self (Self)

Returns:

Self

scale

fn def scale(self) -> Float64

The slope for a Transform2D built from this axis: (range_max - range_min) / (domain_max - domain_min). A zero domain span returns 0.0 rather than dividing by zero; every input then maps to range_min.

Args:

  • self (Self)

Returns:

Float64

translate

fn def translate(self) -> Float64

The intercept for a Transform2D built from this axis, derived from scale() so to_pixel(domain_min) == range_min exactly.

Args:

  • self (Self)

Returns:

Float64

to_pixel

fn def to_pixel(self, value: Float64) -> Float64

Map a data value onto its pixel position: scale() times value plus translate(). Takes log10(value) first when is_log is set, or _symlog_forward(value) when is_symlog is; value is always the real, untransformed data value.

Args:

  • self (Self)
  • value (Float64): The data value to map, in real units (never pre-logged, even when is_log is set).

Returns:

Float64: The pixel position value lands on.

ticks

fn def ticks(self, target_count: Int = Int(5)) -> Ticks

Return “nice” tick positions within the domain (see _nice_step), from ceil(domain_min/step)*step to floor(domain_max/step)*step, so ticks never extend past the domain; a tick landing exactly on a boundary is included (domain 0 to 100 includes both 0 and 100).

A zero-span domain returns a single tick at domain_min with 0 decimals, since the nice-step math would need log10(0).

Args:

  • self (Self)
  • target_count (Int): Roughly how many ticks to aim for; the actual count depends on which “nice” step size the domain rounds to. Defaults to 5.

Returns:

Ticks: The computed tick positions and their shared decimal count.

Raises:

Error: Only on a time axis, and only from morrow’s formatting signature – the numeric paths cannot fail.