Here’s an update on what’s happening when I go quiet, although the last week was also spent getting a replacement car for one that literally went bang, and restoring my OS which decided that was a good time to fail in the middle of an upgrade.
This is something I put together to help me understand what I’m thinking about. I don’t expect it will make much sense to others but if you have questions I’ll be happy to respond.
Data Pipeline Summary
The diagram shows stages from data loading to visualisation, from SourceResult, to ViewModel, and finally a VisualSchema:
- The SourceResults on the left hold arbitrary serialisations along with metadata about their origin (creation date, file path, SPARQL query etc.) and may be cached locally.
- In the middle are ViewModels suitable for visualisation when loaded with an appropriate VisualSchema.
- The VisualSchemas on the right are reactive components which can provide an interactive visual presentation of suitable ViewModel
- F - Filter is a means of identifying a subset of the contained data, which may have interactivity through the UI.
- T - Transform changes the serialisation and/or structure of a SourceResult or ViewModel and may have interactivity through the UI.
See below the diagram for an explanation of what happens in different parts of the pipeline, and the application features this is designed to support.
Interaction
User interaction is not shown in the diagram, but may be supported in any of the processing (circles) between stages (boxes). So the UI will present a unified set of controls that allow selection, querying of the source, choice of a transform to produce a visual model, and choice of a visualisation component to present the data.
Actions
For clarity the flow in the diagram only shows data from source to visualisation, whereas the design is intended to cater for actions to be invoked which flow in the other direction all the way from a VisualComponent to an external data source. Actions will be optional, declared on the ViewModel, and can support interactive features such as those just mentioned, and in addition the ability to make changes to data held locally or the data source itself (local or remote storage, such as a file, database). To provide the UI for invoking actions, a VisualComponent will check which actions are available according to the ViewModel.
Data Pipeline Explained
ViewUI Components and Views
The boxes with graphics on the right of the diagram are examples of ViewUI Components which provide the presentation and UI for a view of data held in a ViewModel. Each ViewUI Component is implemented as a Svelte component, using a View such as a ViewForceGraph to provide the underlying functionality. These present information about data for a set of data held in a ViewModel to which they are connected. Some Views may be capable of combining data from more than one ViewModel in a single presentation.
Note: for every kind of ViewModel there must be at least one VisualComponent capabale of presenting it, even if this is just a text summary or metadata related to the data and its source. So not all View are graphical or particularly complex. Some can be very simple. For example, a visual component might provide a textual summary of SourceResults via a simple metadata ViewModel of the form { records: Number, nodes: Number, source: Object, created: String }
.
A VisualComponent embodies a VisualSchema, which is the combination of what data it can present, and how it will be presented.
The component may have interactive capabilities where the Actions available on a ViewModel permit, for example:
- to reveal information on clicks or hover
- to highlight information through selection
- to explore a data source by issuing query instructions to a stage in the pipeling including the original data source, the SourceResults, or the ViewModel to which a datum is connected
- to issue a new query to add to or replace the data in the pipleline
- to mutate a data source (e.g. remote database, or local store) to add to, modify or delete data in the source
- selection, copy and paste between VisualCoponents and/or ViewModels
- cloning to create multiple coordinated views of the same ViewModel
The VisualSchema identifies what kind of ViewModels a VisualComponent can present and how these will be represented. Also, whether or not the component supports more than one model of each supported type in the same presentation. For example, a graph component may expect a visual model in the form of { nodes: [], links: [] }
with particular characteristics, but this might also be suitable for other components such as a tree or table. So a tabular component could be designed to handle models such as { rows: [], columns: [] }
which as well as the one which the graph component handles.
Coordinating Views
Where different components can present the data from the same type of visual model, they can be combined in the user interface to show different presenetations of the same data alongside each other, and for selection in one component to be reflected in any component presenting the same data from the same ViewModel.
This also allows multiple instances of the same component to be included alongside each other to provide multiple presentations in the same style (e.g. at different scales, or as subsets of the data through panning and zoom).
ViewModels
A set of ViewModels need to be defined so that suitable transforms can be made to generate them from SourceResults. The approach here is to define them based on the common conventions found in existing visualisations including Vega and Vega Lite, D3 examples and so on, with slight adaptations to keep transforms simple and representations concise and intuitive.
A ViewModel acts as a bridge between data loaded from a source, and the VisualComponent which provides a view of data to the user. On the one hand it knows quite a lot about the raw data (held in a SourceResult) from which its model is derived. On the other it makes this and other capabilities available in a standardised form which can be understood by View. The latter includes optional capabilities (Actions) which can be invoked through the UI of the VisualComponent, such as expand (e.g. issue a new query to the source), editing of properties, addition or deletion of data elements (entities, links) etc.
I envisage the ViewModel will comprise a number of aspects, some of which will be optional such as below.
- Schema: identification of its visual model (schema), used to determine the set of compatible View
- Transforms: either take the data of SourceResult and use it to create a new model, or can take data from another ViewModel and create its model from that.
- Filters: apply a ‘selected’ flag to the elements of the model according to values provided for the filter’s criteria. Criteria can be matching of properties (e.g. nodes with age > 20), including lists of type and identity (e.g. nodes with ids in a given list). This allows selection by search and match on the one hand, or selection of arbitrary sets through user interaction. Some Actions and Transforms would have the option to only operate on items with a selection.
- Model: the core of the model available to a VisualComponent. This is an object with properties according to the implemented schema, and methods for supported Actions.
- Actions: functions on both the model as a whole, and on the elements (nodes, links, rows, columns) of the model. For example, we define a set of ViewModel functions which are undefined if not implemented on a particular ViewModel or model elements. Actions on the whole model might include delete all, **re-load/discard changes, add new model element. **Actions on a model element can include expand, reload, modify, delete. In addition, actions may be a way to invoke Transforms which operate on the model itself, or which produce a new ViewModel derived from this model. Alternatively derived models could be implemented by creating them with a ViewModel as their source rather than a SourceResult. This raises the possibility that a SourceResult has a base implementation in common with a ViewModel, although my gut says that this will confuse rather than clarify the design. ← Needs thinking about.
- Sets: are subsets of the elements in a model, and may overlap with each other. A Set can be created from a selection (i.e. using Filters). Membership of a set would be useful input to both Filters and Transforms to allow sets, selections and new data models to be built from combinations of sets in the current model.
Filters
This is in effect a way of identifying a “selection” within a set of data, and so can be applied though either query style matching interface and/or interactively though a visualisation (e.g. using mouse clicks, or drawing a boundary etc.). In combination with a Transform, changing the filter applied to a SourceResult can change a downstream ViewModel and be reflected immediately in the presentation (of any View connected to the particular ViewModel).
Transforms
Two kinds of transform are needed:
- transforms which map SourceResults (JSON or non-JSON serialisations such as RDF, csv etc.) to a particular ViewModel for which a VisualComponent.
- transforms which create one kind of ViewModel from another.
Notes:
- perhaps a SourceResult can contain more than one serialisation, or would transformation create a new SourceResult?
Division of Responsibilities
SourceInterface and SourceResults
SourceInterface and SourceResults should remain limited to the details of loading data from different sources, and providing that in a small number of easy to generate forms. They should not be involved in creating the mappings to a visual model. This is intended to make it easy to retain the links between a set of SourceResults and the source, so this can easily be reference and if necessary re-generated. Also, to make it possible to maintain the relationship between each result in a SourceResults and the corresponding element in the source, and so to enable fine grained interaction with the source including modification of properties of a result, deletion etc (e.g. using CRUD, or file editing).
VisualModel and its VM Subclasses
The VisualModel and its VM subclasses consume SourceResults in a small number of standard forms (typically RDF/JS Dataset or JSON objects) and use a Transform to generate their internal visual model as a JSON object which can be accessed by a View class to present the data in a visual UI.
Where the data needs to be mapped, this can be achieve through a VM whose Transform consumes one JSON ViewModel in order to create a new ViewModel, and so on.
A Transform is implemented as a VM class which consumes one model (e.g. SourceResult or ViewModel) in order to generate its own view model.
A pipeline can have a single VM, or a chain of VM objects between a SourceResult and a final ViewModel intended for use by a particular View. Each model in a pipeline will for now include a reference to the source (ie the SourceResult at the end of the pipeline) as well as the preceding VM (if it doesn’t consume the SourceResult directly).
Each model element (e.g. entity type, column ref etc) along a pipeline will have a sourceResultId
to maintain it’s correspondence with its origin in the source (e.g. a record id, RDF URI etc.)
Want to play?
The latest version is deployed fairly regularly at vlab.happybeing.com