autowisp.browser_interface.diagnostics.series_table module

Class Inheritance Diagram

Inheritance diagram of ChannelColumn, MasterFile, ObservingSession, PhotometryColumn, SeriesKey

What the table above a diagnostics plot offers, and what it binds.

The half of the plot page that knows what a row means: which observing session and image type a row may be drawn for, which channel each of its columns may be bound to, how many images a binding would draw, and what a row is called while the user chooses. It never evaluates an expression and never draws anything – image_diagnostics_views does both – which is not merely a tidy division. The dropdowns a row is built from span every observing session and image type in the project, so evaluating anything to fill them would be work proportional to the whole image collection; every question asked here is answered by a SQL aggregate instead.

class autowisp.browser_interface.diagnostics.series_table.ChannelColumn(needed: frozenset, quoted: str | None = None)[source]

Bases: NamedTuple

Inheritance diagram of autowisp.browser_interface.diagnostics.series_table.ChannelColumn

One channel column of the series table: what it reads, and where.

Most bind one parameter of an axis quantity. The rest, with quoted set, choose the photometric reference of a channel the text quotes a diagnostic fit_magnitudes produces in: the channel is written in the text rather than bound, but its reference still has to be chosen, as for every channel such a diagnostic is read in.

Hashable, being what a table’s options are keyed by.

property by_reference

Whether an option binds a photometric reference with a channel.

count_options(db_session)[source]

Yield each option the column has, with how many images it draws.

Each (channel, photref) the images recording needed are bound to, where the column reads a diagnostic fit_magnitudes produces, and each channel alone otherwise; of a quoted column, only those of its channel.

Yields:

tuple –

One per option of each session and image type,

(session_label, session_id, image_type, option, count), the option (channel, photref), the photref None for a column binding channels alone.

needed: frozenset

The diagnostics read in the column’s channel.

quoted: str | None

The channel whose reference a quoted column chooses; None for a column binding a parameter.

class autowisp.browser_interface.diagnostics.series_table.PhotometryColumn(needed: frozenset)[source]

Bases: NamedTuple

Inheritance diagram of autowisp.browser_interface.diagnostics.series_table.PhotometryColumn

One photometry column of the series table: what it reads.

One per photometry parameter of the two axes. Apart from the channel columns rather than folded into their options: a photometry belongs to no channel, every image having every photometry in every channel, so two reads in one channel may be bound to two photometries.

Hashable, being what a table’s options are keyed by.

count_options(db_session)[source]

Yield each option the column has, with how many images it draws.

Each photometry the images record every one of needed in.

Yields:

tuple –

One per option of each session and image type,

(session_label, session_id, image_type, option, count), the option a photometry id.

needed: frozenset

The diagnostics read in the column’s photometry, in whichever channels.

class autowisp.browser_interface.diagnostics.series_table._PhotometryParameter(column: int)[source]

Bases: NamedTuple

A photometry column, standing in for the photometry it binds.

What an axis is walked with where it takes photometries, as it is walked with a column index where it takes channels. A type of its own rather than the index, because the walk resolves a quoted photometry to its id, an int: walked with indices, magfit_residual[0][0] - magfit_residual[0]['ap0'] would come back as two reads in photometry 0, one bound by column 0 and one quoted, and nothing would tell them apart. Channels need no such thing, a quoted channel staying a string.

column: int

The column’s position among the photometry columns.

autowisp.browser_interface.diagnostics.series_table._chosen_option(offered, *candidate_list)[source]

Return the option of one column the row chooses, or None.

A column with one option has it chosen, whatever the row says. Otherwise the first of candidate_list the column offers: what the row binds now, and for a channel column also the channel alone, since the row’s key gives a column binding channels alone the reference of another slot on its channel, which names no option of this column.

autowisp.browser_interface.diagnostics.series_table._common_length(sequences)[source]

Return how many leading elements all sequences share.

autowisp.browser_interface.diagnostics.series_table._label_options(offered, paths)[source]

Return what each (channel, photref) option of one column is called.

The channel, followed by what tells its reference apart from the others offered in the same channel – R: 1234 – or the channel alone where there is nothing to tell apart: a column binding channels alone, or a channel offering one reference.

autowisp.browser_interface.diagnostics.series_table._make_cell(offered, chosen, *, labels, posted, titles)[source]

Return one slot cell of a row, as _slot_cell.html renders it.

What a channel column’s cell and a photometry column’s share: one offering a single option is settled and states it as text, any other is a dropdown starting with an unset entry, and either sorts by what it shows.

Parameters:
  • offered (dict) – {option: count}, what the column may bind under the row’s pair.

  • chosen – The option the cell binds, or None.

  • labels (dict) – {option: text}, what the cell says it binds.

  • posted (dict) – {option: text}, what the cell posts for it.

  • titles (dict) – {option: text}, what hovering over it shows, missing where nothing does.

Returns:

The cell, binding holding chosen and label what

the cell says it binds.

Return type:

dict

autowisp.browser_interface.diagnostics.series_table._path_separators = re.compile('([/_.-])')

at directory, word and extension boundaries, each kept as a part of its own so that what is left between them reads as written.

Type:

Where a reference’s path is split to tell it from the others

autowisp.browser_interface.diagnostics.series_table._walk_axis(quantity, expressions)[source]

Return what one axis reads, and in which columns.

Walked with a column index standing in for each channel, and a _PhotometryParameter for each photometry. A reference’s arguments are matched against the definition’s parameters positionally, so whatever is passed here is what comes back at the leaves: passing columns asks which column each diagnostic is read in, whatever numbers the expression happened to write. bg_center[3] / pixel_q99[7] reports column 0 and column 1.

A quoted channel comes back as itself rather than as a column, which is what tells the two apart: bg_center[3] / bg_center['G0'] reads bg_center in column 0 and, fixed, in G0. A quoted photometry comes back as its id.

Returns:

tuple: The quantity’s channel parameters, as the definition

numbers them; None each for a diagnostic, which has no numbering of its own.

tuple: Its photometry parameters, likewise.

set: (diagnostic, channel, photometry) reads: the

channel a column index or a quoted channel, and the photometry None for a diagnostic recorded per image, a _PhotometryParameter or a quoted photometry’s id.

Return type:

tuple

autowisp.browser_interface.diagnostics.series_table.count_bound_images(reads, channel_bindings, photometry_bindings, db_session)[source]

Count the images one binding draws on, for every group at once.

The exact question, where get_slot_options() answers the looser one that fills the dropdowns: an image counts when its rows cover every read between them, which is what a quantity comparing channels or photometries needs and what reading each column on its own cannot say – and, where the binding names references, when it was fit against each of them, as the series will be restricted to.

Every group is counted in one aggregate rather than one per row, since a binding is usually shared – by every row of a monochrome project at render, and by nothing much afterwards, when one row is rebound at a time.

Parameters:
  • reads (frozenset) – What get_table_reads() returned.

  • channel_bindings (list) – The (channel, photref) bound in each channel column, in order, the photref None where there is none.

  • photometry_bindings (list) – The photometry id bound in each photometry column, in order.

  • db_session – An active SQLAlchemy database session.

Returns:

{(session_id, image_type): count}, holding only the

groups with anything to draw.

Return type:

dict

autowisp.browser_interface.diagnostics.series_table.get_available_series(x_quantity, y_quantity, expressions, db_session, *, marker)[source]

Return what one section’s table offers, and the row it starts with.

A row is a series the user builds, so what this answers is what its dropdowns may offer: the (session, image type) pairs where every channel column has a channel to bind. The table then starts with one row on the first of them – the earliest session – so that the page has a series without the user having to build one.

The count is the number of images recording every diagnostic both axes need – for an expression, every diagnostic it reaches transitively. It is an upper bound on the number of drawn points, since arithmetic can still yield NaN, so the column is labelled for the inputs rather than for the points. Nothing is evaluated to produce it: the count is a question about rows, and stays a SQL aggregate.

Parameters:
  • x_quantity (str) – Quantity on the X axis.

  • y_quantity (str) – Quantity on the Y axis, which is what the rows draw and therefore what their ids name.

  • expressions (dict) – The library, {name: expression}, passed in rather than fetched so that nothing below the view has to know where it is stored.

  • db_session – An active SQLAlchemy database session.

  • marker (str) – What this section’s rows are drawn with to begin with, chosen for the section rather than for the row so that the quantities on a plot are told apart by shape.

Returns:

diagnostics_fields, pair_options and

diagnostics_list, in the format _series_section.html expects.

Return type:

dict

Raises:

PipelineError – If an axis names nothing that resolves.

autowisp.browser_interface.diagnostics.series_table.get_axis_slots(quantity, expressions)[source]

Return the diagnostics read in each channel and photometry one axis binds.

An axis binds one channel per channel parameter of the quantity it draws, and one photometry per photometry parameter, and two axes never share one: their numbers are formal parameters, so the first slot of the x quantity and the first of the y quantity are unrelated, and tying them together would silently couple the axes.

Parameters:
  • quantity (str) – The concrete quantity the axis draws, the quantile family already resolved to a member.

  • expressions (dict) – The library, {name: expression}.

Returns:

list: One (parameter, needed) pair per channel to bind,

in column order: the slot number the definition writes, which names the column, and the diagnostics read in it. The parameter is None for a diagnostic, which has no numbering of its own. Empty for an axis binding no channel: one over the time, or over quoted channels alone.

list: The same per photometry to bind, the diagnostics read

in it in whichever channels. Empty for an axis reading nothing per photometry, or only in quoted photometries.

Return type:

tuple

autowisp.browser_interface.diagnostics.series_table.get_channel_columns(x_quantity, y_quantity, expressions)[source]

Return the channel columns of the table, in order.

The x quantity’s slots followed by the y quantity’s, concatenated rather than merged: an expression’s numbers are formal parameters, so the two axes’ slots are unrelated even when written alike.

Then a quoted column per channel a diagnostic fit_magnitudes produces is read in by quoting it, to choose that channel’s reference in: in the order the text first quotes them, x’s and then y’s, so that references are chosen in the order the expressions mention them. A channel quoted on both axes has one, an image having one reference per channel.

Parameters:
  • x_quantity (str) – Quantity on the X axis.

  • y_quantity (str) – Quantity on the Y axis.

  • expressions (dict) – The library, {name: expression}.

Returns:

One ChannelColumn per channel column.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.get_fixed_reads(reads)[source]

Return what the two axes read where no column binds anything.

A quoted channel is already bound, so it offers no choice and gets no column; but what is read in it still has to be recorded for an image to be drawn. So it narrows the (session, image type) pairs a row may name, exactly as a column’s reads do – and is what gives a table any rows at all when neither axis binds a column.

A read in a quoted channel and a photometry a column binds is not among them: until the column is bound, there is no photometry to look for it in. The column’s options narrow the pairs instead.

Parameters:

reads (frozenset) – What get_table_reads() returned.

Returns:

(diagnostic, channel, photometry) reads, as

count_images_with_channels() takes them.

Return type:

frozenset

autowisp.browser_interface.diagnostics.series_table.get_pair_options(columns, options, labels, fixed_groups, db_session)[source]

Return the (session, image type) pairs a row may be drawn for.

A pair is offered where every column has at least one channel or photometry to bind, and where some image records everything read where no column binds anything: otherwise a row on it could name no data at all. What a column takes is chosen in the row afterwards, so a pair is offered once rather than once per binding it could carry.

Parameters:
  • columns (list) – The table’s columns, channel and photometry columns alike.

  • options (dict) – What get_slot_options() returned.

  • labels (dict) – The session labels from the same call.

  • fixed_groups (dict) – The fixed reads’ counts from the same call, or None where nothing is read in a quoted channel.

  • db_session – An active SQLAlchemy database session.

Returns:

{"value", "text", "start", "end"} per pair, by session

start time and then image type – which is the order the dropdown lists them in, and why the first of them is the earliest session. Empty where the axes read no diagnostic at all – the time against the time – there being nothing to constrain the pairs, and nothing worth drawing.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.get_photometry_columns(x_quantity, y_quantity, expressions)[source]

Return the photometry columns of the table, in order.

The x quantity’s photometry slots followed by the y quantity’s, as get_channel_columns() lays out the channel slots. A quoted photometry gets none: it is already bound.

Parameters:
  • x_quantity (str) – Quantity on the X axis.

  • y_quantity (str) – Quantity on the Y axis.

  • expressions (dict) – The library, {name: expression}.

Returns:

One PhotometryColumn per photometry column.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.get_quoted_channel(x_quantity, y_quantity, expressions)[source]

Return the channel a row is shown in when it binds none of its own.

The first the x quantity quotes, and failing that the y’s – the axes in the order their columns would be, had they any.

Parameters:
  • x_quantity (str) – Quantity on the X axis.

  • y_quantity (str) – Quantity on the Y axis.

  • expressions (dict) – The library, {name: expression}.

Returns:

The channel, or "" where neither quotes one.

Return type:

str

autowisp.browser_interface.diagnostics.series_table.get_reference_paths(options, db_session)[source]

Return the path of every photometric reference options offers.

What a reference is labelled from, and what hovering over it shows.

Parameters:
  • options (dict) – What get_slot_options() returned first, for the channel columns alone: a photometry column’s options name no reference.

  • db_session – An active SQLAlchemy database session.

Returns:

{photref: path}, read in one query however many

references there are.

Return type:

dict

autowisp.browser_interface.diagnostics.series_table.get_row_options(y_quantity, *, x_quantity, expressions, db_session)[source]

Return what a row drawing one quantity against the page’s x is built from.

The things that have to be worked out before any row can be built: what each channel and photometry column reads, what the axes read altogether, what each column may be bound to, and the (session, image type) pairs the row may name.

Parameters:
  • y_quantity (str) – The quantity the row draws, from its id.

  • x_quantity (str) – Quantity on the X axis.

  • expressions (dict) – The library, {name: expression}.

  • db_session – An active SQLAlchemy database session.

Returns:

columns, photometry_columns, reads,

quoted_channel, options, paths and pair_options, as get_channel_columns(), get_photometry_columns(), get_table_reads(), get_quoted_channel(), get_slot_options(), get_reference_paths() and get_pair_options() return them – keyed as make_row_for_pair() takes them.

Return type:

dict

autowisp.browser_interface.diagnostics.series_table.get_series_key(series)[source]

Return the population one posted row draws from, and what it binds.

All of it comes from the client and none from the row id: the session, the image type and the channels are chosen in the row, so reading any of them from anywhere but the dropdown the user just changed would be reading a stale value. What the id carries instead is the quantity, which the row cannot change.

Each channel column posts what make_channel_value() built: its channel, and its photometric reference where it has one. They are split here into the key’s channels and references. Each photometry column posts a photometry id.

Parameters:

series (dict) – One row as the client posted it back.

Returns:

What the row identifies, with empty channels where

its dropdowns are still unset, and no photometries where any photometry column is: a key holds ids, and there is no id meaning unset.

Return type:

SeriesKey

autowisp.browser_interface.diagnostics.series_table.get_session_times(session_ids, db_session)[source]

Return when each observing session began and ended, as text.

Formatted here rather than in the template because the table sorts a column by the text in it: YYYY-MM-DD HH:MM UTC sorts into chronological order, which is the whole reason these two columns exist. Session labels are free-form, so nothing else on the row can be sorted on to the same effect.

Parameters:
  • session_ids (iterable) – The sessions to look up, read in one query however many of them there are.

  • db_session – An active SQLAlchemy database session.

Returns:

{session_id: (start, end)}, with an empty string

wherever a session records no such time.

Return type:

dict

autowisp.browser_interface.diagnostics.series_table.get_slot_headings(axis, kind, slots)[source]

Return the column heading for each channel or photometry one axis binds.

Named for the axis, since the two axes’ slots are unrelated however alike they are written, and for what the column binds. Not for the quantity: the section header and the x selector name those already, and the column is only as wide as its heading needs. Where an axis binds several the heading is the slot as the definition writes it, so a column can be matched to the text it fills in.

Parameters:
  • axis (str) – Which axis these columns belong to.

  • kind (str) – What the columns bind: channel or photometry.

  • slots (list) – What get_axis_slots() returned for the axis, for that kind.

Returns:

One heading per slot to bind.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.get_slot_options(columns, fixed, db_session)[source]

Return what each column of the table may be bound to, and the labels.

One aggregate per distinct column – usually one for the whole table, since the commonest axis pairs read the same diagnostics in every slot – and one more for the fixed reads, if any. Nothing is evaluated: which channels and photometries a column may offer is a question about rows.

What a column offers, and how it is counted, is the column’s own: see ChannelColumn.count_options() and PhotometryColumn.count_options().

Parameters:
Returns:

dict: One entry per distinct column, holding

{(session_id, image_type): {option: count}}, the options as the column’s count_options gives them.

dict: {session_id: label}, the same whatever is read.

dict: {(session_id, image_type): count} of the images

recording every fixed read, or None where there are none, which constrains nothing.

Return type:

tuple

autowisp.browser_interface.diagnostics.series_table.get_table_reads(x_quantity, y_quantity, expressions)[source]

Return everything the two axes read, in the table’s columns.

The axes’ reads laid end to end, as their columns are: a column of the y axis comes after all of the x axis’s, among the channel columns and among the photometry columns alike. What a row’s binding is resolved against, to count what it draws.

Parameters:
  • x_quantity (str) – Quantity on the X axis.

  • y_quantity (str) – Quantity on the Y axis.

  • expressions (dict) – The library, {name: expression}.

Returns:

(diagnostic, channel, photometry) reads, as

_walk_axis() returns them, numbering the table’s columns rather than an axis’s.

Return type:

frozenset

autowisp.browser_interface.diagnostics.series_table.get_table_response(post_data, *, x_quantity, expressions, db_session)[source]

Return the rows to draw, and what the edit behind this redraw earns.

Three kinds of redraw arrive here. A row was rebound (bind) – its last channel chosen, or another (session, image type) pair, which is a rebinding as much as the first since which channels a column may offer depends on the pair, and so is answered even while the channels are unset. Or + was pressed in a row (add), which earns a copy of it. Or nothing structural happened at all – a colour, a marker, a row switched off – which earns the figure and nothing else.

Every one of them rides on the redraw the edit causes anyway, so each costs one round trip rather than two, and the table and the figure are answered together. Nothing here re-renders the table: the client replaces a row’s channel cells, or inserts one row, which is what lets every other row keep its node, and with it what was typed into it and its place under whatever sort is in force.

Parameters:
  • post_data (dict) – The whole POST, holding every row’s state and, where an edit is being answered, bind or add: the id of the row it happened in.

  • x_quantity (str) – Quantity on the X axis. The y comes from the row id, each row naming the quantity it draws.

  • expressions (dict) – The library, {name: expression}.

  • db_session – An active SQLAlchemy database session.

Returns:

list: The rows the figure is drawn from: those posted, plus

an added row, and with a rebound row’s colour and label replaced by the defaults of its new binding wherever the client reports them still automatic. Drawing from these is what stops a rebound row appearing in the colour and legend of the binding it has just left while the table beside it shows the new ones.

dict: For a rebinding, bind echoed back with the row’s

count, its channel cells rendered for the pair it now names, that session’s start and end, and the colour and label its binding makes default. For an addition, added_row, the markup to insert, and after, the row to insert it below. Empty when nothing was edited, which is every other redraw.

Return type:

tuple

autowisp.browser_interface.diagnostics.series_table.label_references(paths)[source]

Return what tells each of paths apart from the others.

What they all share at the start and at the end is dropped – the directories, the extension, a naming scheme – leaving the part that differs: …/DR/IMG_1234_R.h5 and …/DR/IMG_1289_R.h5 become 1234 and 1289. Split at separators rather than characters, so that a number is never cut: character by character, those two would become 34 and 89.

Pure, so that the rule can be tested without a database.

Parameters:

paths (list) – The paths of the references offered in one channel.

Returns:

One label per path, in the same order. Empty where nothing

is left, which is always so for a single path: there is nothing to tell it apart from.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.make_channel_cells(available, bindings, paths)[source]

Return what each channel column of one row offers, and what it says.

A column offering a single option is settled rather than asked about: that is the whole of a monochrome camera, and of a colour one whose other channels are not processed yet, and demanding a click with one possible outcome before anything can be drawn is ceremony. Such a cell shows its option as text, which is what lets a row be drawn the moment it appears. Should another be recorded later, the column has a choice to offer and asks for one.

What a column may offer depends on the (session, image type) pair the row names, so choosing another pair asks this again for all of them. An option the new pair still offers is kept – the user chose it, and it remains an answer – and one it does not is cleared rather than quietly bound to something else.

An option is a channel, and a photometric reference where the column reads a diagnostic fit_magnitudes produces. The cell text names a reference only as far as it has to be told apart from the others in its channel; its full path is the option’s title, and the cell’s for the chosen one, so hovering shows it.

Pure, so that these rules can be tested without a database or a browser.

Parameters:
  • available (list) – What each column may be bound to under this row’s pair, {(channel, photref): count} in column order, the photref None for a column binding channels alone.

  • bindings (tuple) – What the row binds now, (channel, photref) per column in the same order. Empty, or short, for a row whose columns are not all set.

  • paths (dict) – {photref: path} for every reference offered.

Returns:

One cell per column, as _make_cell() builds it,

binding holding the (channel, photref) chosen, or None, and label what the cell says it binds.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.make_channel_value(channel, photref)[source]

Return what one option of a channel column posts.

The channel alone where the column binds a channel, and the channel with the photometric reference, R|12, where it reads a diagnostic fit_magnitudes produces and so binds a (channel, photref) pair. Built as make_id() builds the other ids, and so refused a channel containing its separator.

Parameters:
  • channel (str) – The channel.

  • photref (int) – The MasterFile id of the reference, or None for a column binding the channel alone.

autowisp.browser_interface.diagnostics.series_table.make_id(*parts)[source]

Return one of the ids the client round-trips, built from parts.

One function for both of them – a row’s quantity|ordinal and a pair’s session id|image type – because the encoding is the same and all either needs of it is that it can be taken apart again. Where the two differ is in the reading: split_row_id() and split_pair_id().

Returns:

The opaque id, which has to survive a round trip through

the client unchanged.

Return type:

str

Raises:

ValueError – If a part contains the separator, which would make the id ambiguous. Worth failing on rather than trusting, since the alternative is a plot that silently draws the wrong rows.

autowisp.browser_interface.diagnostics.series_table.make_photometry_cells(available, bindings)[source]

Return what each photometry column of one row offers, and what it says.

By the rules of make_channel_cells(): settled where there is a single option, and keeping what the row binds where the row’s pair still offers it. An option is a photometry id, called what an expression quotes it as, shapefit or ap2.

Pure, so that these rules can be tested without a database or a browser.

Parameters:
  • available (list) – What each photometry column may be bound to under this row’s pair, {photometry: count} in column order.

  • bindings (tuple) – The photometry id the row binds now per column, None where it binds none. Empty, or short, for a row whose columns are not all set.

Returns:

One cell per column, as make_channel_cells() returns

them, binding holding the photometry id chosen.

Return type:

list

autowisp.browser_interface.diagnostics.series_table.make_row_for_pair(row_id, series_key, *, columns, photometry_columns, reads, quoted_channel, options, paths, pair_options, marker, db_session)[source]

Return one row of the series table, bound as far as its pair allows.

Shared by the first row of a table and by a row whose pair has just changed, both asking the same question: what a row on this pair offers, which of the channels, references and photometries it names survive there, and how many images the result draws.

Parameters:
Returns:

A series entry, as make_series() builds it, counted

where the pair leaves it fully bound and uncounted where it does not.

Return type:

dict

autowisp.browser_interface.diagnostics.series_table.make_series(row_id, series_key, options, channel_slots, count, *, photometry_slots, marker, quoted_channel)[source]

Build the entry describing one row of the series table.

Its default colour is that of the channel it is shown in: the first it binds, wherever it has a column to bind one in, and otherwise – every channel it reads being quoted – the first its quantities quote.

Parameters:
  • row_id (str) – What make_id() returned for this row.

  • series_key (SeriesKey) – What the row draws once bound. Its channels are empty for a row still to be bound.

  • options (list) – Every (session, image type) pair to allow the user to select, as get_pair_options() returns them. Carried by the row rather than read from the page’s context, so that a row can be rendered on its own.

  • channel_slots (list) – One cell per channel the axes bind, as make_channel_cells() builds them.

  • count (int) – The number of images contributing, or None where nothing is bound yet and there is nothing to count.

  • photometry_slots (list) – One cell per photometry the axes bind, as make_photometry_cells() builds them.

  • marker (str) – What the row is drawn with to begin with, which its section decides: the default tells quantities apart by shape, as the colour tells channels apart. Editable afterwards, like the colour.

  • quoted_channel (str) – What get_quoted_channel() returned for the row’s axes, which it is shown in if channel_slots is empty.

Returns:

A series entry with the keys expected by

diagnostics/_series_row.html and plot_image_diagnostic_series().

Return type:

dict

autowisp.browser_interface.diagnostics.series_table.next_row_id(row, row_ids)[source]

Return the id for a row added beside row, drawing the same quantity.

One past the highest ordinal among that quantity’s rows rather than one past row’s own, so that the id stays unique after a removal has left a gap: reusing a freed ordinal would collide with nothing on the page, but the id is also the suffix of five element ids, and a second row answering to them while the first is still being edited is the kind of bug that shows up as one row’s colour landing on another’s.

Parameters:
  • row (dict) – The row the new one is built beside, as the client posted it. Only the quantity in its id is read here.

  • row_ids (iterable) – Every row id on the page, the new one having to be unique among all of them.

Returns:

The id, as make_id() builds it.

Return type:

str

autowisp.browser_interface.diagnostics.series_table.parse_photometry_value(value)[source]

Return the photometry id a photometry column posted, or None.

An option posts its id as text, and an unset column "", which is None here: every id, the shape fit’s -1 and aperture 0 included, is a valid binding, so nothing but None can mean unset.

autowisp.browser_interface.diagnostics.series_table.posted_rows(post_data)[source]

Return the rows of a posted table as a list, each carrying its id.

The client posts them keyed by id, since that is what it has to look them up by; everything on the server wants a row to be one object that knows its own id. The single place that turns one shape into the other.

autowisp.browser_interface.diagnostics.series_table.row_id_separator = '|'

a row’s, quantity|ordinal, and the value of one option of the session and type dropdown, session id|image type. Not the underscore an earlier encoding used: pixel_q* names contain those, so unpacking had to guess which underscores separated fields. Neither a session id, an image type nor a diagnostic name can contain this one.

Type:

Separates the fields of the two ids the client round-trips

autowisp.browser_interface.diagnostics.series_table.split_channel_value(value)[source]

Return (channel, photref) from what a channel column posted.

The photref is None where the value names none: a column binding a channel alone, or one still unset, whose channel is "".

autowisp.browser_interface.diagnostics.series_table.split_pair_id(pair_id)[source]

Return (session_id, image_type) from what a row’s dropdown says.

The pair is the unit everything on this page is counted by, so it travels as one value and is taken apart only here.

autowisp.browser_interface.diagnostics.series_table.split_row_id(row_id)[source]

Return (quantity, ordinal) from the id of one row.

A row outlives everything chosen in it – its session, its image type and its channels are all edits made in the row – so its id names only what cannot be edited there: the quantity the row draws, and its place among the rows drawing it. That is what lets the five element ids derived from it (plot-color:, marker-button:, marker:, scale:, label:) and the key the client posts it under stay put while the user chooses.

The quantity is part of it because two rows drawing different quantities may otherwise agree on everything: a row is told apart by what it draws, not by where it draws it.

autowisp.browser_interface.diagnostics.series_table.unset_option_text = '—'

What a channel dropdown shows while it is unset. Named here rather than written into the template because a cell sorts by the text of its selected option, so one place has to decide what that text is.