@physiomelinks/protocol-kit
v0.6.0
Published
Experiment protocols for PhLynx and CUFLynx: read, check, edit and preview the protocol_info, data items, prediction items and prediction plots of a circulatory_autogen obs_data.json, as CUFLynx edits them, and compute their features as circulatory_autoge
Readme
protocol-kit
Experiment protocols for PhLynx and
CUFLynx: read, check, edit and preview the protocol_info, data_items,
prediction_items and prediction_plots of a circulatory_autogen
obs_data.json, as CUFLynx's "Edit obs_data" dialog edits them, and compute a run's features as circulatory_autogen
does, the same way in both apps.
What it holds
- Core (
@physiomelinks/protocol-kit): plain JavaScript, no framework.- Reading and writing
obs_data.json; loading and saving an unedited file reproduces it, unknown keys included. - Validating
protocol_infoas circulatory_autogen does, with its own error messages. - Expanding protocol shapes (steps, pulses, pacing trains, ramps) and traces.
- Editing: adding, removing and moving experiments and sub-experiments, and setting values and inputs. Data and prediction items keep pointing at the right experiment and sub-experiment.
- Previewing an input over time.
- Prediction items: adding, changing and removing the items a run records, one at a time as CUFLynx's rows, and checking them as circulatory_autogen #536 does.
- Features: a run's feature values, of its prediction items and its data items, computed from its recorded samples as circulatory_autogen computes them, to the bit.
- Prediction plots: adding, changing, removing and checking
prediction_plots, which plot a feature across experiments (an I–V curve, say), and pairing computed features into their points. - Data items: adding, changing and removing the measured data a calibration fits, every field CUFLynx edits, and checking them as circulatory_autogen #536 does, with its messages.
- Reading and writing
- Editor (
@physiomelinks/protocol-kit/editor): Vue 3 + PrimeVue 4 components that edit an obs_data document as CUFLynx's "Edit obs_data" dialog does. The host app supplies its model's variables, its preset, a confirm dialog and a colour palette.
circulatory_autogen is the reference. Golden vectors generated by its own code (tests/resources/*-vectors.json)
check that the shape expansion, validation and features here match it.
It does not run simulations. Each app runs protocols with its own engine: CUFLynx through circulatory_autogen and Myokit, PhLynx through libOpenCOR.
How it reads obs_data
It follows circulatory_autogen's semantics for obs_data.json, so a file means the same in PhLynx, CUFLynx and CA:
protocol_infoconfigures the simulations and their perturbations: experiments (pre_times,sim_times, one row of sub-experiments each), the values parameters take in each sub-experiment (params_to_change), and the shapes and traces inputs follow over time (protocol_shapes,protocol_traces).data_itemsandprediction_itemsrefer to an experiment by its place (experiment_idx, 0 when left out) and to a sub-experiment by its place in it (subexperiment_idx). A data item without one is in the first sub-experiment; a prediction item without one records over its experiment's last, as circulatory_autogen #536 reads it.- Edits renumber both kinds of item when experiments or sub-experiments move or go, so none points at the wrong one.
- A prediction item records the trace of the variable in
operands, or with anoperation(andoperation_kwargs) a feature of it, one number over its sub-experiment, in one experiment. Items shareitem_name_for_plottingto be plotted as one group. An item with held-out data (value,std,data_type,obs_dt) is validated against it: edits keep those keys as they are, and never write them. - A data item is measured data: a
valueandstd(one number, or aseriesof them everyobs_dt) or a distribution (prob_dist_params), of the variables inoperandsor a feature of them (operation), scored by a cost (cost_type, by defaultgaussian_MLE) with aweight. Edits keep its keys as written, but write the legacyvariableandname_for_plottingasdata_item_nameandtrace_name_for_plotting. - A prediction plot (
prediction_plots, a top-level list circulatory_autogen draws) pairs two groups of features experiment by experiment, byexperiment_idx, or a group with an input's value in a sub-experiment of each; or draws a model output with an input, over time or against it, in each experiment. Edits keep it pointing at the same groups, sub-experiments and experiments. - Keys it doesn't know are kept, wherever they are.
Getting started (contributors)
You need Node.js 22 or later, and Yarn 4 through Corepack.
- Fork
physiomelinks/protocol-kiton GitHub, then clone your fork:git clone https://github.com/<your-username>/protocol-kit.git cd protocol-kit git remote add upstream https://github.com/physiomelinks/protocol-kit.git - Install:
corepack enable yarn install - Test and build:
yarn test # vitest yarn build # the library, into dist/ - Keep your fork up to date:
git fetch upstream git rebase upstream/main
Open pull requests against physiomelinks/protocol-kit main.
Using it in an app
Once published:
yarn add @physiomelinks/protocol-kitTo develop against a local checkout, point the app's package.json at it:
"@physiomelinks/protocol-kit": "portal:../protocol-kit"A checkout has its own node_modules, so the app must keep one copy of the editor's peers. With Vite:
resolve: { dedupe: ['vue', 'primevue', 'papaparse'] }.
import { parseObsData, validateProtocolInfo, readProtocolInfo } from '@physiomelinks/protocol-kit'
const { protocolInfo } = parseObsData(text)
const { errors, warnings, protocolInfo: valid } = validateProtocolInfo(protocolInfo)
const view = valid && readProtocolInfo(valid) // experiments, sub-experiments and inputsCore API
Every function takes and gives plain JSON-like values; edits never change the document given.
| Module | What it does | Main exports |
| --- | --- | --- |
| obsDataDocument | Reads and writes obs_data, and finds it among an archive's files as CUFLynx does. | parseObsData, readObsDataParts, serialiseObsData, findObsDataExtra, buildObsDataLocation |
| protocolValidation | Checks protocol_info as CA does, with its messages, then for what running it needs. | validateProtocolInfo, readAsCircAutogen, checkParamsToChange, PROTOCOL_INFO_KEYS |
| protocolModel | Reads a valid protocol_info as experiments of sub-experiments, and each parameter's input in each. | readProtocolInfo, readShapeForm, buildShapeFromForm, nameExperiment, changesDuringWarmUp, readFromSubExperimentStart, findParametersAtModelValues |
| protocolShapes | Expands pacing and ramp shapes into traces, as CA's protocol_shapes.py. | normaliseShape, expandShape, materialiseShapes, validateTraceReferences, ProtocolShapeError |
| protocolEditing | Edits a document's protocol, renumbering its data and prediction items. | addExperiment, addEmptyExperiment, removeExperiment, moveExperiment, addSubExperiment, removeSubExperiment, setTiming, addParameter, removeParameter, setValue, setInput, setInputFromSubExperimentStart, alignWithWarmUp, findObservationsAt, ensureProtocol |
| protocolPreview | Samples an input over time for drawing. | interpolateTrace, sampleInput, findValueRange, writePolylinePoints |
| predictionItems | Edits a document's prediction items one at a time, each read as a row and written back as CUFLynx's editor does. | listPredictionItems, readPredictionItemRow, buildPredictionItem, createPredictionItem, addPredictionItem, updatePredictionItem, removePredictionItem, findFreeItemName, isValidationData |
| operations | Computes the operations a feature can take as CA's funcs do, to the bit, and the samples a range takes. | applyOperation, sumPairwise, computeMean, sliceRange, sliceRangeBounds, COMPUTED_OPERATIONS, OperationError |
| features | Computes a run's features from each sub-experiment's samples: its prediction items' as CA's features_from_segments does, its data items' as its cost loop does. | computeFeatures, computeDataItemFeatures |
| predictionPlots | Edits and checks a document's prediction plots, and pairs features into their points. | addPredictionPlot, updatePredictionPlot, removePredictionPlot, validatePredictionPlots, listFeatureGroups, computePlotSeries, listPlotExperiments, findPlotsLosingInput, PREDICTION_PLOT_KINDS, PREDICTION_PLOT_KIND_KEYS, INPUT_REDUCTIONS |
| predictionValidation | Checks prediction items as CA #536 does, with its messages, then each range for the run's dt. | readPredictionItemsAsCircAutogen, validatePredictionItems, checkOperationRange, findPredictionItemLimits, readPredictionItem, nameItemForPlotting, PREDICTION_ITEM_KEYS |
| dataItems | Edits a document's data items, each read as a form's row and written back as CUFLynx's editor did. | listDataItems, isRowDataItem, addDataItem, updateDataItem, removeDataItem, readDataItem, buildDataItem, createDataItem, DATA_ITEM_FIELDS |
| dataItemValidation | Checks data items as CA #536 reads them, with its messages, then each for an editor: kwargs, references, experiments. | readDataItemsAsCircAutogen, validateDataItems, checkOperationKwargs, checkCostKwargs, checkDataItemReferences, DATA_ITEM_KEYS |
| dataItemVocabulary | CA #536's data types, plot types, default cost, operations and cost funcs, for an editor to offer. | DATA_ITEM_VOCABULARY, readObsDataOptions, DATA_TYPES, PLOT_TYPES, DEFAULT_COST_TYPE, DATA_ITEM_OPERATIONS, DATA_ITEM_COST_TYPES |
| protocolCompatibility | Lists what CA, and so CUFLynx, can't run of a protocol. | findCircAutogenLimits |
| protocolNames | Finds the variable a parameter names, as CA's name resolver does. | findNameCandidates, resolveParameterName |
| experimentColours | Colours experiments as experiment_colors names them, or from a palette by place. | resolveExperimentColour, EXPERIMENT_PALETTE, MATPLOTLIB_COLOURS |
| pythonFormat | Formats values as Python does, for CA's messages. | formatPythonG, formatPythonRepr, ... |
import { parseObsData, removeSubExperiment, serialiseObsData } from '@physiomelinks/protocol-kit'
const { document } = parseObsData(text)
const edited = removeSubExperiment(document, 0, 1) // items in it go; later ones move down
const bytes = serialiseObsData(edited) // an ArrayBuffer, indented with 2 spacesPrediction items
import { addPredictionItem, createPredictionItem, listPredictionItems, updatePredictionItem, validatePredictionItems } from '@physiomelinks/protocol-kit'
let edited = addPredictionItem(document, {
...createPredictionItem(), // a trace, in the first experiment, over its last sub-experiment
operands: ['i_Na/i_Na'], // left unnamed, it is named after its variable: i_Na/i_Na, else i_Na/i_Na_2...
unit: 'uA_per_cm2',
experiment: 1,
subexperiment: 1, // from 0; null for the experiment's last
operation: 'min_in_range', // '' for a trace
operationKwargs: { start_frac: 0, end_frac: 0.2 },
itemName: 'I_peak', // item_name_for_plotting: the group it is plotted in
traceName: 'Sodium current', // trace_name_for_plotting
})
const rows = listPredictionItems(edited) // [{ index, name, operands, unit, experiment, subexperiment, operation, ... }]
edited = updatePredictionItem(edited, rows.at(-1).index, { name: 'I_peak_e1' })
const { errors, warnings, itemErrors } = validatePredictionItems(edited, { dt: 0.01 })A row holds an item's fields under the names of readPredictionItemRow; buildPredictionItem writes only those that
changed, so an item read and written back is the same, held-out data and keys it doesn't know of included. An item left
unnamed is named after its variable, apart from every data and prediction item (findFreeItemName), as CA requires
names unique. updatePredictionItem renames an item where other prediction items' operation_kwargs name it, and the
prediction plots follow a group (item_name_for_plotting) renamed in its last item. A document the Outputs of 0.2 to
0.4 wrote (one item per experiment, sharing item_name_for_plotting) reads as a row per item.
validatePredictionItems gives CA's error for each item, and those of the whole list (names repeated across data and
prediction items), where CA stops at the first (readPredictionItemsAsCircAutogen does too). It also checks that each
*_in_range window takes a sample: CA reduces the samples from int(start_frac * (n - 1)) up to, not including,
int(end_frac * (n - 1)) of the n = int(duration / dt) + 1 a sub-experiment records. Its warnings say which items need
circulatory_autogen #536 (an operation, operation_kwargs or subexperiment_idx): released libcuflynx 0.7.3 and
current CUFLynx reject them.
Data items
import { addDataItem, createDataItem, listDataItems, updateDataItem, validateDataItems } from '@physiomelinks/protocol-kit'
let edited = addDataItem(document, {
...createDataItem(), // a constant, the max of its variable, scored by CA's default cost
name: 'V_peak', // data_item_name
operands: ['membrane/V'],
unit: 'mV',
operation: 'max_in_range',
operationKwargs: { start_frac: 0, end_frac: 0.5 },
value: 20, // or a list for a series, with obsDt
std: 1.5,
experiment: 1,
subexperiment: 0,
})
const [row] = listDataItems(edited) // { index, name, dataType, operands, value, std, costType, plotType, ... }
edited = updateDataItem(edited, row.index, { name: 'V_max', costType: 'gaussian_MLE_robust', costKwargs: { p_outlier: 0.1 } })
const { errors, warnings, itemErrors, itemWarnings, sharedErrors } = validateDataItems(edited)A row holds an item's fields under the names CUFLynx's editor gave them (readDataItem): '' is no operation and the
default cost, a plotType of null the data type's default and '' no marker ('None'), and labels left '' CA's
defaults. buildDataItem writes only the fields that changed, so an item read and written back is the same, keys it
doesn't know of included; updateDataItem renames an item where other data items' operation_kwargs name it.
isRowDataItem(row, vocabulary) says whether the editor lists an item as a row, for a host counting them. Every
edit gives each item an experiment_idx and subexperiment_idx once one has them, as CA refuses a column some lack.
readDataItemsAsCircAutogen reads data items as #536's parser does, stopping at its first error, pandas' quirks
included. validateDataItems gives each item's errors, and goes on: CA's own for it, its experiment and sub-experiment
in the protocol, its operation_kwargs and cost_kwargs against the funcs (checkOperationKwargs,
checkCostKwargs, with difflib's suggestions), and references to items not computed before it; then what CA refuses
of them together (names repeated across data and prediction items). It warns of an operation or cost func CA has not.
It checks against DATA_ITEM_VOCABULARY, or a host's own: readObsDataOptions reads CUFLynx's
/api/obs_data/options, user funcs included.
Features and prediction plots
import { addPredictionPlot, computeDataItemFeatures, computeFeatures, computePlotSeries, sliceRangeBounds, validatePredictionPlots } from '@physiomelinks/protocol-kit'
// Each sub-experiment's own samples, by operand: [experiment][sub] = { time, values: { 'i_Na/i_Na': Float64Array } }
const features = computeFeatures(document, segments) // [{ name, group, experiment, subexperiment, kwargs, value, unit, error }]
const measured = computeDataItemFeatures(document, segments) // the same, for each constant data item with an operation
const { start, end } = sliceRangeBounds(samples.length, measured[0].kwargs) // the samples it reduced, end excluded
const edited = addPredictionPlot(document, {
name: 'Peak I_Na vs step potential',
kind: 'feature_vs_input', // or 'feature_vs_feature' (x a group)
x: { params_to_change: 'clamp/V_cmd', subexperiment_idx: 1, reduce: 'max' }, // reduce: for an input that is a trace
y: 'I_peak', // a group: the items' item_name_for_plotting
series: null, // or an input like x: a line per value
})
const traced = addPredictionPlot(edited, {
name: 'V with the command',
kind: 'input_and_output', // or 'output_vs_input': the output against the input
input: { params_to_change: 'clamp/V_cmd' },
output: 'membrane/V',
experiments: [0, 2], // left out for all
})
const { errors, plotErrors, plotWarnings } = validatePredictionPlots(traced)
const [plot] = computePlotSeries(edited, features) // { x, y, series, points: [{ experiment, x, y, series, measured }], skipped, errors }A sub-experiment's samples are those CA records for it: from the one taken once its values are set, to its end. A run that joins sub-experiments into one trace, and so starts each with the last sample of the one before, must split them so, or a feature over a window that starts the sub-experiment comes out differently. A constant may be given as a number or one sample, as libcuflynx's Myokit helper records it. A feature CA can't compute (a maximum over a range with no samples, say) is NaN with the error; a mean over none is NaN, as numpy's.
A data item's feature is over its own sub-experiment, the first when it names none. CA visits the sub-experiments in
order, each experiment's in turn, and in each its data items in the order of data_items, so an operation_kwargs value
may name an item computed before it there or in an earlier sub-experiment. Each feature's kwargs hold the values such
names stand for, so sliceRangeBounds gives a host the samples an *_in_range operation took, to draw it over them.
The operations computed (COMPUTED_OPERATIONS) are max, min, mean and max_minus_min, each over all of its
sub-experiment or, as *_in_range, over its start_frac to end_frac, and first_peak_time of the operands
[t, V]: the time of V's first peak as scipy's find_peaks finds it (at least spike_min_thresh high, when given),
in the sub-experiment's own time, or its last time when there is none. A host draws it as a vertical line.
A plot pairs, for each experiment its y group has an item in, that item's feature with the x group's in the same
experiment (feature_vs_feature), or the value params_to_change[key][experiment][subexperiment_idx]
(feature_vs_input). Where that is a trace, reduce makes it one number, as CA #591 does: 'final', 'mean',
'max', 'min' or {at: <seconds from the start of the sub-experiment>}; a number ignores it, and CA leaves out the
point of a trace without one. input_and_output and output_vs_input draw a model output (output) with an input
(input: {params_to_change}), over time on twin y axes or against it, in each experiment of experiments, all when
it is left out; computePlotSeries gives them no points, as they draw a run's traces, but their input, output and
experiments. validatePredictionPlots checks what CA does: each kind's keys and no others, a name of its own, the
kind, and for the feature kinds the x it takes, groups that exist, are features (an operation, not a series) and
have one item per experiment, x and y over the same experiments, and inputs set to a number or a trace in that
sub-experiment of each experiment, with a reduce CA knows (its at no later than the end of a sub-experiment
where the input is a trace); for the others, an input params_to_change sets, an output
and experiments the protocol has. plotWarnings names a trace read without a reduce. Removing or moving an experiment
renumbers the experiments a plot names; one left with none goes. Removing a sub-experiment moves an
input reference down with it where every point is in that experiment; where one index can no longer name the same
sub-experiment in each, or names the one removed, the plot goes, and findObservationsAt names it first.
Mounting the editor
The editor is a v-model on an obs_data document (document prop, update:document event): each edit passes on a
new document, never changing the one given, so the host keeps it, saves it and undoes edits as it likes. It needs
Vue 3.5, PrimeVue 4 (styled, with a theme such as Aura), papaparse and PrimeIcons.
<template>
<ObsDataEditor v-model:document="obsData" :variables="variables" :get-value="getValue" preset="phlynx" />
</template>
<script setup>
import { ref } from 'vue'
import { ObsDataEditor } from '@physiomelinks/protocol-kit/editor'
import '@physiomelinks/protocol-kit/editor.css'
import 'primeicons/primeicons.css'
const obsData = ref(null) // e.g. parseObsData(text).document; null or a bare list offers to add protocol_info
const variables = [
{ name: 'membrane/g_Na', label: 'Sodium conductance', unit: 'mS_per_cm2', kind: 'constant', value: 0.12 },
{ name: 'membrane/V', unit: 'mV', kind: 'variable' },
]
const getValue = (name) => variables.find((variable) => variable.name === name)?.value
</script>ObsDataEditor has a section for each key of the document, headed by the key as CUFLynx's dialog heads them:
protocol_info, on a timeline (ProtocolInfoEditor), or for a data-only document (a bare list of data items, or noprotocol_info) the button "Add protocol_info".data_items(DataItemsSection), then, with a protocol,prediction_items(PredictionItemsSection) andprediction_plots(PredictionPlotsSection): a row per item, its details under a chevron.
Clicking a row selects it: the timeline shows its experiment and tints its sub-experiment (a prediction item's last when it names none), as CUFLynx's dialog does.
| Prop | | |
| --- | --- | --- |
| document | Object \| Array \| null | The obs_data document (v-model:document). |
| variables | Array<{name, label?, unit?, kind?, value?}> | The model's variables. name is as the protocol names it (component/variable, as params_to_change keys). Those of kind 'constant' or 'global_constant' can be added for the protocol to set; unit labels its lane, and a prediction item's when picked. The pickers search name and label. |
| preset | 'cuflynx' \| 'phlynx' | Optional. The host's app: 'cuflynx' (the default) edits every column; 'phlynx' shows the data items read-only, without weight, cost and differentiability. Prediction items and plots are edited in both. |
| getValue | (name) => number \| string \| undefined | Optional. A variable's value in the model, which a parameter starts from when added, and which tells the parameters left at it (below). By default, its value in variables. |
| confirm | (options) => Promise<boolean> | Optional. Asks before removing something from the protocol; options has header, message, severity, acceptLabel and rejectLabel. By default, PrimeVue's ConfirmDialog (the editor shows its own, in the group protocol-kit-confirm) when the app has ConfirmationService, else the browser's confirm. Rows are removed without asking, as CUFLynx's are; the host's undo brings one back. |
| palette | string[] | Optional. Colours of experiments the file doesn't colour (experiment_colors), by place. By default EXPERIMENT_PALETTE. |
| warn | (protocolInfo) => string[] | Optional. The app's own warnings about the protocol, shown after the editor's: what it ignores, say. |
| dt | number | Optional. The time between the samples a run records, to check that each prediction item's range takes some. |
| showDataItems | boolean | Optional. Whether to show the data items; by default true. PhLynx passes its "Show data items" setting. |
| dataItemColumns | string[] | Optional. The data items' columns, when not the preset's (below). |
| dataItemsReadOnly | boolean | Optional. Whether the data items are only listed; by default as the preset says. |
| vocabulary | Object | Optional. The operations, cost funcs, data and plot types offered; by default DATA_ITEM_VOCABULARY. CUFLynx passes its own: :vocabulary="readObsDataOptions(await getObsDataOptions())". |
The slot data-items-actions puts the host's buttons beside the data_items heading (CUFLynx's "Custom funcs").
Parameters at their model values. A parameter the protocol sets to its value in the model, as a plain number, in
every experiment and sub-experiment (within rounding, a relative 1e-9) has no lane until asked for: a line below the
others counts them, with a button to show and hide them. The document keeps them. The model's values come from
getValue, else variables; a parameter whose value is unknown there, one added or edited while the editor is open, and
one an error or warning names (whole, not as the start of a longer name) are always shown.
Times in the first sub-experiment. An input's times are from the start of its sub-experiment, the first one's
too. CA starts an experiment's first sub-experiment, and its inputs' clock, with the warm-up, so an input written there
is moved to start with the sub-experiment and holds its first value through the warm-up
(setInputFromSubExperimentStart), and is shown again with the times it was given (readFromSubExperimentStart). An
input a file has that changes during the warm-up is marked, and editing it writes the times shown from the start of the
sub-experiment.
Data items. DataItemsSection has CUFLynx's rows, name | value | std | operation | exp | sub, and under the
chevron the operands (each labelled x1, x2... as CA's func names them, time among the variables), trace label,
unit, weight, cost_type (the default named) and its kwargs, plot_type, the operation's kwargs (another item's name
for an operation of no operands), source and comment. A row CA would refuse is tinted red and says why, read-only
too; one whose operation CA can't differentiate is tinted orange, with CUFLynx's warning. An item a row can't hold (a
series, a frequency, a distribution, an operation the vocabulary hasn't) is kept as it is, and counted: "N
non-editable item(s) (series / frequency / custom operation) will be preserved unchanged." Its columns are keys of
DATA_ITEM_COLUMNS (name, value, std, operation, experiment, subexperiment, operands, traceName,
unit, weight, cost, plot, operationKwargs, source, comment, and differentiable for the tint), and the
presets (DATA_ITEM_COLUMN_PRESETS) name them:
'cuflynx', for an app that calibrates: every column, editable.'phlynx', for an app that only runs the protocol: the data as measured, read-only, withoutweight,costanddifferentiable. PhLynx hides the section with its "Show data items" setting.
Prediction items. PredictionItemsSection has a row per item, variable | unit | trace label | exp | sub |
operation: the sub-experiment "(last)" or an index, the operation "(none)" or one of CA's. Under the chevron, its
name, item label (item_name_for_plotting, CA's default as its placeholder) and the operation's kwargs, start_frac and
end_frac for a range. A variable picked names an item left unnamed, and gives its unit. An item with held-out data is
marked obs, its data kept. Each row shows CA's errors for it; the section warns what needs #536.
Prediction plots. PredictionPlotsSection has a row per plot, name | kind | settings: the kind a dropdown of the
four, and only that kind's settings. feature_vs_feature: y and x groups of features, and series none or an input in a
sub-experiment. feature_vs_input: y, x an input with its sub-experiment and reduce (and a time for "at a time"), and
series. input_and_output and output_vs_input: the input, the output (picked from variables when the host gives
them, else typed) and a box per experiment, every one ticked leaving experiments out. Choosing a kind writes its keys
alone, keeping the name and carrying an input over. Each row shows the plot's errors, and its warnings.
Each section takes document, readOnly and, but for the plots, columns (a preset or a list of keys); it emits
update:document, and the item sections select with the place of the row selected (selected). The entry also
exports ProtocolCellEditor, InlineNumber, NumberInput, VariablePicker, INPUT_KINDS, findInputKind,
DATA_ITEM_COLUMNS, DATA_ITEM_COLUMN_PRESETS, resolveDataItemColumns, isReadOnlyPreset,
PREDICTION_ITEM_COLUMNS, PREDICTION_ITEM_COLUMN_PRESETS, resolvePredictionItemColumns, searchVariables,
splitVariableName and isSettable. The editor registers PrimeVue's tooltip directive itself.
CSS variables. The components use the PrimeVue theme's tokens, so they follow the host's theme, light or dark. Each has a fallback (Aura's light value) for a host without them:
| Variable | Fallback | Used for |
| --- | --- | --- |
| --p-text-color | currentColor | Headings |
| --p-text-muted-color | #64748b | Secondary text, units, captions |
| --p-primary-color | #10b981 | Focus rings, the current experiment, links |
| --p-content-background | #ffffff | Chips over lanes |
| --p-content-hover-background | #f1f5f9 | Column heads, lanes, hovered experiments |
| --p-content-border-color | #e2e8f0 | The experiment list's border, chips |
| --p-inputtext-border-color | #cbd5e1 | The experiment name's border, on hover |
| --p-orange-400, --p-orange-500 | #fb923c, #f97316 | Warnings: inputs CUFLynx can't run, inputs starting with the warm-up |
| --p-red-500 | #ef4444 | Errors: inputs circulatory_autogen refuses, numbers that aren't |
Fixtures and golden vectors
tests/resources/ holds obs_data files from circulatory_autogen and CUFLynx (br-1977 with shapes and engine/pace,
SN_simple with traces, NKE_pump, and others), and prediction_items_536_obs_data.json, prediction items as CA #536
reads them (operation, operation_kwargs, subexperiment_idx, held-out values). The round-trip tests check that
loading and saving each without edits gives the same document, byte for byte when it is written as serialiseObsData
writes it (JSON indented with 2 spaces), and that every edit leaves what it doesn't own untouched. Numbers are
written as JavaScript writes them, so a file written by Python (1.0, -0.0, 1e-05) comes back with the same
values but not the same bytes.
scripts/generate_ca_vectors.py runs circulatory_autogen's own shape expansion and validation and rewrites
tests/resources/ca-vectors.json, for the shape cases in it and every *_obs_data.json fixture. It needs no packages.
Run it when circulatory_autogen changes its protocol semantics, or a fixture is added, then fix whatever the tests show:
python scripts/generate_ca_vectors.py /path/to/circulatory_autogenscripts/generate_prediction_vectors.py does the same for prediction items, with #536's own parser: it rewrites
tests/resources/prediction-vectors.json, for its good and bad cases and every fixture with prediction items. It
needs a Python with that circulatory_autogen's libcuflynx installed. The vectors record the commit they come from:
#536's head (refs/pull/536/head).
/path/to/venv/bin/python scripts/generate_prediction_vectors.py /path/to/circulatory_autogenscripts/generate_data_item_vectors.py does the same for data items, with the same Python: #536's parser on good and
bad items and every fixture's, its operation_kwargs and cost_kwargs checks, and its vocabulary (data and plot
types, the default cost, its operations and cost funcs, their kwargs), into tests/resources/data-item-vectors.json.
/path/to/venv/bin/python scripts/generate_data_item_vectors.py /path/to/circulatory_autogenLicence
scripts/generate_operation_vectors.py runs circulatory_autogen's own operation funcs, its features_from_segments
over a run of random samples, and its get_obs_output_dict over the same run's data items, sub-experiment by
sub-experiment as its cost loop does, and rewrites tests/resources/operation-vectors.json: thousands of cases over
series of many lengths (around numpy's blocks of 8 and 128), NaNs, infinities and signed zeros, with windows inside and
outside 0 to 1, and the samples each window takes. The tests check each value to the bit. It needs a Python with that circulatory_autogen's libcuflynx installed:
python scripts/generate_operation_vectors.py /path/to/circulatory_autogen