shyft.dashboard.time_series.sources.source

Classes

DataSource(*, ts_adapter, unit[, min_dt, ...])

This (not entirely enforced) immutable hashable object contains all data defining a source for requesting data.

Source(bokeh_document, data_source, views, ...)

This object plays the role of binding a DataSource (ref DataSource) to a set of Views, based on controls from the .parent (bindable) that need to provide TsViewer capabilities.

TsAdapterRequestParameter(*, ...)

This immutable hashable object contains all information to request data from TimeAxisHandle and we use it as message-transport between the front thread and the background worker-thread that performs the real work in an async context(strongly recommended)

Exceptions

SourceError

class shyft.dashboard.time_series.sources.source.DataSource(*, ts_adapter: TsAdapter, unit: str, min_dt: shyft.time_series.time | None = 0, time_range: UtcPeriod | None = None, request_time_axis_type: DsViewTimeAxisType | None = None, tag: str | None = None)[source]

Bases: Hashable, Bindable

This (not entirely enforced) immutable hashable object contains all data defining a source for requesting data.

It is typically used related to the view, ref to the class Source below, as means of keeping parameters that help getting ts-data in an optimal manner for renderers.

ts_adapter

from the underlying system.

It’s a callable object of type:

>>>   def fx( time_axis: TimeAxis, unit: Unit) -> Quantity[TsVector]:

and as indicated, given a time-axis and a unit, provide a Quantity[TsVector]. The TsVector having 1 or more members, depending on the wanted ts-renderer (percentile/fill-between or line/scatter-plots)

It is invoked by the view-controller each time it needs (new) data for rendering.

Type:

TsAdapter is the most important feature, its role is to provide the time-series data

min_dt: time >=0 the smallest time-step to propagate through requests to the ts_adapter

the purpose is to let the user instrument this data-source so that it will never ask for time-axis of less resolution than this. Typically, it’s reasonable to set 3600 for ts-expressions where you know that the underlying data is sampled at hourly resolution. Note that is only for optimizing memory/time usage.

time_range: UtcPeriod clipping period, default min..max, that is, -> no clip/crop

the purpose is to let you clip the request, and maybe also the returned resulting ts-vector from the ts_adapter.

request_time_axis_type: DsViewTimeAxisType (padded/not padded)

the purpose is to let user control which of the time-axis provided by the view-controller should be used for fetching data through .ts_adapter(….) call. The padded time-axis contains surplus ranges at each end of the time-axis to allow for smooth pan-operations.

tag :str the short-name of the data-source

the purpose..? have named data-sources.

__init__(*, ts_adapter: TsAdapter, unit: str, min_dt: shyft.time_series.time | None = 0, time_range: UtcPeriod | None = None, request_time_axis_type: DsViewTimeAxisType | None = None, tag: str | None = None) None[source]
Parameters:
  • ts_adapter – the TsAdapter which has the data

  • unit – the unit of the data

  • min_dt – the smallest time step to use when constructing time-axis used for the .ts_adapter(time_axis..) request.

  • time_range – the maximum time range for the data, used to clip request, in or outgoing to the ts_adapter(…. ) request.

  • request_time_axis_type – time axis type (padded/not padded), controls which of the time-axis to use for the .ts_adapter(…) request.

  • tag – tag(short-name) of data source

class shyft.dashboard.time_series.sources.source.TsAdapterRequestParameter(*, request_time_axis_type: ~shyft.dashboard.time_series.axes_handler.DsViewTimeAxisType, unit: str | ~pint.unit.build_unit_class.<locals>.Unit, view_time_axis: ~shyft.time_series._time_series.TimeAxis, padded_view_time_axis: ~shyft.time_series._time_series.TimeAxis)[source]

Bases: Hashable

This immutable hashable object contains all information to request data from TimeAxisHandle and we use it as message-transport between the front thread and the background worker-thread that performs the real work in an async context(strongly recommended)

Ref. to DataSource for the semantics of the data-members

__init__(*, request_time_axis_type: ~shyft.dashboard.time_series.axes_handler.DsViewTimeAxisType, unit: str | ~pint.unit.build_unit_class.<locals>.Unit, view_time_axis: ~shyft.time_series._time_series.TimeAxis, padded_view_time_axis: ~shyft.time_series._time_series.TimeAxis) None[source]

This object bundles all parameter needed to get data from ts_adapter

Parameters:
  • request_time_axis_type – defines which time axis to use view_time_axis or padded_view_time_axis

  • unit – unit of the requested data

  • view_time_axis – view time axis provided from time_axis_handle

  • padded_view_time_axis – padded view time axis provided from time_axis_handle

classmethod create_empty() TsAdapterRequestParameter[source]
property is_empty
is_equiv(other)[source]
property request_time_axis: TimeAxis
property request_parameter: TimeAxis]
exception shyft.dashboard.time_series.sources.source.SourceError[source]

Bases: RuntimeError

class shyft.dashboard.time_series.sources.source.Source(bokeh_document: Document, data_source: DataSource, views: List[BaseView], unit_registry: UnitRegistry, thread_pool_executor: ThreadPoolExecutor | None = None, logger: Logger | None = None)[source]

Bases: Bindable

This object plays the role of binding a DataSource (ref DataSource) to a set of Views, based on controls from the .parent (bindable) that need to provide TsViewer capabilities.

It utilizes a thread-pool to ensure that time-consuming data-fetching/computations can run in the background thread, and that when ready, these are properly dispatched into the bokeh foreground async io-loop.

Notice that this class plays together (closely) with the TsViewer class that have several Sources that is renders.

The TsViewer is reached through the .parent (from Bindable) member.

Control flow for an update goes like this:

>>> #From the TsViewer           This class        The background worker(thread-pool)          TsAdapter
>>> #.update_data(vw_parms) ->     |                        |                                    |
>>> #                           compute
>>> #                      time-axis suitable for the current view,
>>> #                     given  source.min_dt,source.time_range(alias clip)
>>> #                              |                        |
>>> #                               post the TsReq  -->     |                                    |
>>> #                              |                  request_data_from_ts_adapter_sync ()      fx(time_axis,unit)->TsVector
>>> #                              |                        |
>>> #                           update_view_data(tsv..) <--- TsVector
>>> #.trigger_view_update(views:tsv)
logger

provides logging functionality

Type:

Logger

data_source

provide means of getting time-series data from the data-layer, with time-axis/delta-t limitations, does not have any logic.

Type:

DataSource

views

keeps the list of view that presents this source

Type:

List[BaseView]

unit_reqistry

keeps the measurement-units and methods for conversions so that we can do simple conversions at the visual/presentation layer

Type:

UnitRegistry

visible

True if this datasource should be visible

Type:

bool

_state

represent the port/visual state of this object

Type:

States

bokeh_document

the document we renter into (we use async, so we need to keep track of it)

Type:

Document

async_on

True if thread-pool executer is supplied (can be turned off)

Type:

bool

queue

Keeps the list of pending request (async) fetching data

Type:

List[TsAdapterRequestParameter]

current_request_parameter

Keeps the ongoing request (so that other similar request can be skipped)

Type:

TsAdapterRequestParameter

loading_data_async

True while the async-thread worker is executing in background

Type:

bool

async_observer_ts_viewer

the TsViewer that registers itself as the observer of this Source. This is needed if trigger_view_update() should wait for results from all async data updates in its sources.

Type:

TsViewer

__init__(bokeh_document: Document, data_source: DataSource, views: List[BaseView], unit_registry: UnitRegistry, thread_pool_executor: ThreadPoolExecutor | None = None, logger: Logger | None = None)[source]
Parameters:
  • bokeh_document – bokeh document

  • data_source – data source

  • views – views to updated after data was loaded

  • unit_registry – unit registry use to check units

  • thread_pool_executor – thread pool executor needed for async data loading, if provided source will use it

update_data(view_axis: ViewTimeAxisProperties) None[source]

This function triggers the updating of the data using the ts adapter provided in data_source container. It is called by the controller(TsViewer):

It goes through these steps:
  • Create suitable time-axis/parameters to forward to the ts-adapter for getting data

    (try to figure out minimum amount of work to be done)

  • In thread-pool thread, execute the ts-adapter to get the data

  • when done, invoke the update_view_data(..) to update the TsViewer with the results.

:parameter view_axis Contains the properties of the visual-time-axis, so that this class can

adapt and optimize it’s request to the TsAdapter class.

request_data_from_ts_adapter_sync(*, request_param: TsAdapterRequestParameter)[source]
update_view_data(ts_vector: Quantity[TsVector]) None[source]

This function triggers the view data update for the ts_vector, for each of the views (as a dict), same ts_vector. Before return, async_observer_ts_viewer must be notified about completed_async_data_update

update_view_data_async(ts_vector: TsVector) None[source]

Trigger the view data update, from async function