visualdynamics.core.author¶
author
¶
Writing and editing a specification, at any coordinates.
A specification is a sheet: breakpoints, a level per channel at each, bands in decibels either side, and a cross term per pair of channels. None of that depends on where the channels are, so one draft serves every door in (Brandon, 2026-09-04: a generic editor, not a modal one) — new at a shape set's modal coordinates, new at chosen physical DOFs, or opened from a specification that already exists — and every way out: a new object, or the one it was opened from, replaced.
The virtual point arc's third tool is one of those doors. Written at
M1 … Mn and expanded through the set, a specification becomes an
exact control-channel CPSD, phase and coherence included, with no
assumption in it: every number came from something the author
stated.
What an author states, per SpecificationDraft:
- Channels, each with the quantity its density is of.
- Breakpoints: frequencies and a level per channel at each, the
power law between breakpoints being how a written specification
reads (
Specification.interpolation = 'log_log'). - Every pair's cross term, as a coherence and a phase, from which
S_ij = √(γ² S_ii S_jj) e^{iφ}. A pair left unstated is a refusal to make the specification, not a zero: independent channels are a statement too, and the author makes it (Brandon, 2026-09-04: no assumptions about cross terms, ever).with_all_pairsstates one answer for every pair in one gesture. - Bands: warning and abort, as decibels either side of the target, the same on every channel — which is what lets them carry exactly through a transform.
The operations on a draft (scaled_db, with_bands,
with_breakpoint, without_breakpoint, with_all_pairs) each give
a new draft and leave this one alone, so a script reads as a sequence
of statements and a session journals as one.
Classes:
| Name | Description |
|---|---|
SpecificationDraft |
A specification being written, at any channels. |
Functions:
| Name | Description |
|---|---|
default_bands |
A channel's starting bands: ±3 dB warning, ±6 dB abort on every |
band_notes |
What a sheet opened on |
uniform_spacing |
The spacing of evenly spaced lines, or None when they are not |
Classes¶
SpecificationDraft
dataclass
¶
SpecificationDraft(
channels: list[str],
dims: list[str],
frequencies: list[float],
levels: list[list[float]],
pairs: dict[
tuple[int, int], tuple[float, float] | None
] = dict(),
bands: list[dict[str, Any]] = list(),
notes: list[str] = list(),
sources: list[str] = list(),
form: str = "breakpoints",
spacing: float | None = None,
)
A specification being written, at any channels.
Attributes:
channels: The DOF strings, one per channel — modal coordinates
(M1), physical DOFs (101Z+), whatever the door opened
on.
dims: The quantity each channel's density is of
('acceleration', 'angular_acceleration', …), one per
channel; the density's dimension is its square per hertz.
frequencies: The breakpoints, in Hz, increasing.
levels: One list per channel, a density at each breakpoint,
in the channel's SI density unit.
pairs: {(i, j): (coherence, phase_degrees)} for every pair
i < j of channels, or None where the pair has not been
stated yet.
bands: One entry per channel: {'warning': [(below, above)
per segment], 'abort': [...], 'symmetric': bool, 'uniform':
bool}, the bands in decibels either side of the target,
a segment being the span between two neighbouring
breakpoints. A channel's own constraints: symmetric
holds above at minus below, uniform holds every segment
at one band (Brandon, 2026-09-06: each channel its own
settings, the bands dragged on the plot per section, not
typed in a pane). A breakpoint belongs to the segment on
its right, the last one to the segment on its left.
notes: What a door could not carry over — cross terms that
varied with frequency, bands that differed — said rather
than silently dropped.
sources: Which specification each channel was opened from, one
per channel, when the sheet spans several (across);
empty when it is one object's. Channels of different
sources have no cross term between them — the pair is not
offered rather than unstated.
form: 'breakpoints' — the few points a specification is
written from — or 'lines', the same requirement read onto
evenly spaced frequency lines, as a controller writes its
target. to_breakpoints and to_lines convert; the
levels are edited on the breakpoints (Brandon,
2026-09-06).
spacing: The frequency spacing, in Hz, the lines form has or
the sheet remembers from the specification it opened —
what to_lines reads onto when not told otherwise.
Methods:
| Name | Description |
|---|---|
at_modal_coordinates |
A starter at a shape set's modal coordinates |
at_dofs |
A starter at chosen DOFs: a flat line across 20–2000 Hz at |
at_control_channels |
A starter at a channel table's control channels — every |
from_specification |
The sheet a specification already is: its autospectra's lines |
across |
One sheet spanning several specifications' sheets, so an |
for_source |
The sheet of one of the specifications a combined sheet |
validate |
Refuse what no specification could hold: unordered or |
pairable |
Every pair |
unset_pairs |
The pairs no cross term has been stated for. |
with_all_pairs |
The same draft with one answer stated for every pair. |
scaled_db |
The same draft with the target raised or lowered by |
segment_of |
Which segment each frequency lies in: a breakpoint belongs to |
band_db |
(below, above) in decibels at each frequency for one |
with_band |
The same draft with a band stated outright. |
shifted_band |
The same draft with one edge of a band moved — the drag on |
with_band_edge |
The same draft with one edge of a band set to |
constrained |
The same draft with channels' constraints set. Turning |
sections |
One channel's segments grouped into the linear sections of |
band_runs |
The segments of one channel grouped as the plot draws its |
with_breakpoint |
The same draft with a breakpoint at |
without_breakpoint |
The same draft without the breakpoint at |
to_breakpoints |
The same requirement as the few points it was written from: |
to_lines |
The same requirement read onto evenly spaced frequency |
bands_differ |
Whether any channel's band changes from one segment to the |
with_band_corners |
The same draft with a helper breakpoint a hair before each |
make |
The specification, with every cross term. |
constraints |
Each channel's constraints, by channel — what the object |
written_into |
The specification with this sheet's channels rewritten in |
preview |
The autospectra and their bands alone — what the plot shows |
as_dict |
A JSON-friendly form, for the provenance record. |
from_dict |
The draft a provenance record holds. |
Attributes:
| Name | Type | Description |
|---|---|---|
num_channels |
int
|
How many channels the draft covers. |
Attributes¶
Methods:¶
at_modal_coordinates
classmethod
¶
at_modal_coordinates(
shapes: ShapeSet,
quantity: str = "acceleration",
modes: Sequence[int] | None = None,
) -> SpecificationDraft
A starter at a shape set's modal coordinates M1 … Mn, each
channel's quantity by the transform's unit rule — a unit rigid
set's rotations per radian, a mass-normalised set's modal
quantity. A set with no mass unit gives its coordinates no
unit, and a specification in nothing is refused.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shapes
|
ShapeSet
|
The set the specification is written at. |
required |
quantity
|
str
|
The physical quantity the target is a density of. |
'acceleration'
|
modes
|
sequence of int
|
Which shapes get a channel, by index from 0 — the ones picked in the tree. All of them when omitted. A virtual point's target is usually its three translations alone (Brandon, 2026-09-06): expanded through the set, a shape with no channel contributes nothing, which is what a zero would say, and a sheet holds positive levels. |
None
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
Every pair unstated. |
Source code in src/visualdynamics/core/author.py
at_dofs
classmethod
¶
at_dofs(
dofs: list[str],
quantity: str | list[str] = "acceleration",
) -> SpecificationDraft
A starter at chosen DOFs: a flat line across 20–2000 Hz at one SI unit of density on every channel, every pair unstated.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dofs
|
list of str
|
The channels. |
required |
quantity
|
str or list of str
|
The quantity each channel's density is of, one for all or one per channel. |
'acceleration'
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
The sheet to fill. |
Source code in src/visualdynamics/core/author.py
at_control_channels
classmethod
¶
at_control_channels(
table: ChannelTable,
) -> SpecificationDraft
A starter at a channel table's control channels — every motion channel when none is flagged — each in the quantity its channel type declares.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
table
|
ChannelTable
|
The table. |
required |
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
The sheet to fill. |
Source code in src/visualdynamics/core/author.py
from_specification
classmethod
¶
from_specification(
spec: Specification,
channels: list[str] | None = None,
source: str = "",
) -> SpecificationDraft
The sheet a specification already is: its autospectra's lines as breakpoints, its cross terms as a coherence and phase where they hold one over frequency, its bands as decibels where they do — and a note for whatever did not fit the sheet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Specification
|
The specification to open. |
required |
channels
|
list of str
|
Only these of its channels — the ones picked in the tree. All of them when omitted. |
None
|
source
|
str
|
The specification's name, for a sheet that will span
several ( |
''
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
Ready to edit; |
Source code in src/visualdynamics/core/author.py
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | |
across
classmethod
¶
across(
drafts: dict[str, SpecificationDraft],
) -> SpecificationDraft
One sheet spanning several specifications' sheets, so an edit — a scale, a band — lands on all of them at once.
The sheets meet on one breakpoint list: the union of theirs
over the range they share, each read off its own power law
there (exact at its own breakpoints). Pairs are offered within
a specification only. for_source gives each its own sheet
back, and written_into writes it at its own lines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
drafts
|
dict of str to SpecificationDraft
|
Each specification's sheet by its name. |
required |
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
The combined sheet, |
Source code in src/visualdynamics/core/author.py
for_source
¶
for_source(source: str) -> SpecificationDraft
The sheet of one of the specifications a combined sheet spans — its channels and pairs alone, unnamed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
The specification's name, as |
required |
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
That specification's own sheet. |
Source code in src/visualdynamics/core/author.py
validate
¶
Refuse what no specification could hold: unordered or repeated breakpoints, a level that is not positive, a coherence outside [0, 1], a band the wrong way round.
Source code in src/visualdynamics/core/author.py
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | |
pairable
¶
Every pair (i, j), i < j, that has a cross term: two
channels of the same specification.
Source code in src/visualdynamics/core/author.py
unset_pairs
¶
with_all_pairs
¶
with_all_pairs(
coherence: float, phase_degrees: float = 0.0
) -> SpecificationDraft
The same draft with one answer stated for every pair.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
coherence
|
float
|
The coherence between every two channels, 0 for independent, 1 for fully coherent. |
required |
phase_degrees
|
float
|
The phase of the later channel against the earlier. |
0.0
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
scaled_db
¶
scaled_db(
decibels: float, channels: list[str] | None = None
) -> SpecificationDraft
The same draft with the target raised or lowered by
decibels — on every channel, or the named ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
decibels
|
float
|
The change, positive to raise. |
required |
channels
|
list of str
|
Which channels; all of them when omitted. |
None
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
segment_of
¶
Which segment each frequency lies in: a breakpoint belongs to the segment on its right, the last breakpoint (and anything past the end) to the last segment.
Source code in src/visualdynamics/core/author.py
band_db
¶
(below, above) in decibels at each frequency for one channel: the band of the segment each lies in.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
('warning', 'abort')
|
Which band. |
'warning'
|
channel
|
int
|
Which channel, by index. |
required |
frequencies
|
array - like
|
Where to answer; the breakpoints themselves when omitted. |
None
|
Returns:
| Type | Description |
|---|---|
(ndarray, ndarray)
|
The band below and above the target, per frequency. |
Source code in src/visualdynamics/core/author.py
with_band
¶
with_band(
kind: str,
below: float,
above: float,
channels: Any = None,
segments: Any = None,
) -> SpecificationDraft
The same draft with a band stated outright.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
('warning', 'abort')
|
Which band. |
'warning'
|
below
|
float
|
Decibels below (negative) and above (positive) the target. |
required |
above
|
float
|
Decibels below (negative) and above (positive) the target. |
required |
channels
|
list of str
|
Which channels; all of them when omitted. |
None
|
segments
|
list of int
|
Which segments, by index; all of them when omitted, and all of them regardless on a uniform channel. |
None
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. Refused where the band breaks a channel's own constraint. |
Source code in src/visualdynamics/core/author.py
shifted_band
¶
shifted_band(
kind: str,
side: str,
segments: Any,
decibels: float,
channels: Any = None,
step: float = 1.0,
) -> SpecificationDraft
The same draft with one edge of a band moved — the drag on
the plot, landed. A symmetric channel moves the other edge to
match; a uniform channel moves every segment. The edge lands
on a multiple of step (Brandon, 2026-09-06: whole decibels,
never 1.5), and never nearer the target than one step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
('warning', 'abort')
|
Which band. |
'warning'
|
side
|
('lower', 'upper')
|
Which edge was dragged. |
'lower'
|
segments
|
list of int
|
The segments under the drag. |
required |
decibels
|
float
|
How far, positive up. |
required |
channels
|
list of str
|
Which channels; all of them when omitted — the channels selected are the channels edited. |
None
|
step
|
float
|
The decibel grid the edge lands on. |
1.0
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
with_band_edge
¶
with_band_edge(
kind: str,
side: str,
segments: Any,
decibels: float,
channels: Any = None,
step: float = 1.0,
) -> SpecificationDraft
The same draft with one edge of a band set to decibels on
every channel — the drag on the plot, landed (Brandon,
2026-09-06: a drag from 3 to 4 dB puts every selected channel
at 4 dB, not each one decibel further from where it was, so a
channel at 3 and one at 4 both come out at 4). A symmetric
channel sets the other edge to match; a uniform channel sets
every segment. Lands on a multiple of step, never nearer the
target than one step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
('warning', 'abort')
|
Which band. |
'warning'
|
side
|
('lower', 'upper')
|
Which edge. |
'lower'
|
segments
|
list of int
|
The segments under the drag. |
required |
decibels
|
float
|
The edge's level, positive above the target. |
required |
channels
|
list of str
|
Which channels; all of them when omitted. |
None
|
step
|
float
|
The decibel grid the edge lands on. |
1.0
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
constrained
¶
constrained(
channels: Any = None,
symmetric: bool | None = None,
uniform: bool | None = None,
) -> SpecificationDraft
The same draft with channels' constraints set. Turning symmetric on mirrors the band above to the one below; turning uniform on gives every segment the first one's band.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
channels
|
list of str
|
Which channels; all of them when omitted. |
None
|
symmetric
|
bool
|
The constraint to set; kept when omitted. |
None
|
uniform
|
bool
|
The constraint to set; kept when omitted. |
None
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
sections
¶
One channel's segments grouped into the linear sections of
its requirement: every segment on its own in the breakpoints
form, and in the interpolated form the runs of one power law
— the lines between bends, as to_breakpoints finds them.
Source code in src/visualdynamics/core/author.py
band_runs
¶
The segments of one channel grouped as the plot draws its handles: one run over the whole range while the channel is uniform, else one per linear section of the requirement (Brandon, 2026-09-06: Uniform off should show a level per section, each moved on its own), split again wherever the band already differs within a section.
Source code in src/visualdynamics/core/author.py
with_breakpoint
¶
with_breakpoint(frequency: float) -> SpecificationDraft
The same draft with a breakpoint at frequency, its levels
read off the power law between its neighbours — or the end
breakpoint's, past the ends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequency
|
float
|
Where, in Hz. |
required |
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
without_breakpoint
¶
without_breakpoint(frequency: float) -> SpecificationDraft
The same draft without the breakpoint at frequency.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frequency
|
float
|
Which, in Hz; it has to be one of the breakpoints, and not one of the last two. |
required |
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; this one is unchanged. |
Source code in src/visualdynamics/core/author.py
to_breakpoints
¶
to_breakpoints(
tolerance: float = 1e-06,
) -> SpecificationDraft
The same requirement as the few points it was written from: the first and last line, and every line where the log-log slope of any channel changes. Exact for a specification that was read onto lines from breakpoints (a controller's target); a specification with no such structure keeps every line, and the notes say so rather than the sheet inventing a simplification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tolerance
|
float
|
How much the slope may wander between adjacent segments and still be one power law. |
1e-6
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft, |
Source code in src/visualdynamics/core/author.py
to_lines
¶
to_lines(
spacing: float | None = None,
) -> SpecificationDraft
The same requirement read onto evenly spaced frequency
lines — multiples of spacing from 0 Hz, as a controller lays
its lines — over the band the breakpoints cover, each channel
on its own power law between them.
Only the lines inside the band: a sheet holds positive levels, and the zeros a controller writes outside the band are its own convention, filled in by its loader for any line the file does not name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spacing
|
float
|
The line spacing in Hz. Defaults to the spacing the sheet remembers; with neither, refused — nothing is guessed. |
None
|
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft, |
Source code in src/visualdynamics/core/author.py
bands_differ
¶
Whether any channel's band changes from one segment to the next — where the object needs a helper line to carry the step.
Source code in src/visualdynamics/core/author.py
with_band_corners
¶
with_band_corners(
part: float = 1e-06,
) -> SpecificationDraft
The same draft with a helper breakpoint a hair before each breakpoint whose two segments carry different bands, so the object made of it can carry the step.
A limit array holds one value per line and a breakpoint
belongs to the segment on its right, so the segment on its
left needs a line of its own at the corner to show its band up
to it. The helper sits part of the breakpoint's frequency
before it, on the same power law, and folds away again —
to_breakpoints keeps only lines that bend.
Returns:
| Type | Description |
|---|---|
SpecificationDraft
|
A new draft; the same one when no helper is needed. |
Source code in src/visualdynamics/core/author.py
make
¶
make(comment: str = '') -> Specification
The specification, with every cross term.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
comment
|
str
|
A comment for the records — where the sheet came from. |
''
|
Returns:
| Type | Description |
|---|---|
Specification
|
Autospectra and cross terms at the breakpoints, a power law between them, the bands on every autospectrum. |
Source code in src/visualdynamics/core/author.py
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 | |
constraints
¶
Each channel's constraints, by channel — what the object carries beside its limits so a sheet reopens as it was set.
Source code in src/visualdynamics/core/author.py
written_into
¶
written_into(
spec: Specification, comment: str = ""
) -> Specification
The specification with this sheet's channels rewritten in it, at its own lines.
The sheet's channels take the sheet's levels, cross terms and bands over the sheet's range, read off its power law at each line; a breakpoint that is not a line becomes one. Lines the sheet left out — 0 Hz, a zero level — keep what they had, and a cross term the sheet states but the specification never held is made there from its own autospectra. Channels the sheet does not hold are untouched, read off their own curve at any new line.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Specification
|
The specification the sheet was opened from. |
required |
comment
|
str
|
Appended to the record's comment. |
''
|
Returns:
| Type | Description |
|---|---|
Specification
|
A new object; |
Source code in src/visualdynamics/core/author.py
1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 | |
preview
¶
preview() -> Specification
The autospectra and their bands alone — what the plot shows beside the sheet.
Source code in src/visualdynamics/core/author.py
as_dict
¶
A JSON-friendly form, for the provenance record.
Source code in src/visualdynamics/core/author.py
from_dict
classmethod
¶
from_dict(data: dict[str, Any]) -> SpecificationDraft
The draft a provenance record holds.
Source code in src/visualdynamics/core/author.py
Functions:¶
default_bands
¶
A channel's starting bands: ±3 dB warning, ±6 dB abort on every segment, symmetric and uniform.
Source code in src/visualdynamics/core/author.py
band_notes
¶
band_notes(spec: Specification) -> list[str]
What a sheet opened on spec should say about bands it does
not have: a specification with no warning or abort limits opens
wearing the defaults, there on the plot to drag, and the first
edit writes them (Brandon, 2026-09-06: where there are none, the
sheet is where they are added). Said from the object rather than
kept on the draft, so the saying stops when the limits exist.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spec
|
Specification
|
The specification the sheet is open on. |
required |
Returns:
| Type | Description |
|---|---|
list of str
|
One note per band kind missing; empty when both are there. |
Source code in src/visualdynamics/core/author.py
uniform_spacing
¶
The spacing of evenly spaced lines, or None when they are not — a controller writes its target at multiples of one spacing, a breakpoint specification at whatever frequencies it was written.
A helper line — one a hair before a breakpoint, carrying a band
step (with_band_corners) — is not a line of the grid and is
left out of the reckoning: read as one, two helpers made a
controller's target open as four thousand breakpoints, each its
own section (2026-09-06).