Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 12x 12x 12x 12x 2x 2x 2x 2x | /**
* Two sequences against each other — a dot plot (SPECS §28), as a descriptor.
*
* One set of sequences along the x axis, another along the y, and a mark
* wherever the two share sequence: a reordering, an inversion or a
* translocation between two assemblies is the line that jumps, turns or
* leaves. It needs no contact map and no edit — two FASTA or `.2bit` files
* the session holds — and it is computed beside their residues, in the
* annotations worker (`dotplot/dotplot.ts` for how). A **dev feature** (§29)
* until it is validated.
*/
import type { AnalysisContext, AnalysisTask, CostEstimate, Params, ParamSpec } from '../types'
import { READY, waitingFor } from '../types'
/** Cells along the longer axis of the figure, unless the reader asks for others. */
export const DOTPLOT_CELLS = 400
const PARAMS: readonly ParamSpec[] = [
{
kind: 'sequence',
key: 'x',
label: 'along x',
hint: 'The sequences laid along the x axis, in their own order.',
},
{
kind: 'sequence',
key: 'y',
label: 'along y',
hint: 'The sequences laid along the y axis: another assembly, or the same one for its repeats.',
},
{
kind: 'choice',
key: 'streaks',
label: 'streaks',
default: 'one to one',
options: [
{
value: 'one to one',
label: 'one to one',
hint: 'Each stretch at its best place on the other axis, the others left out: the lines between two assemblies, without the grid a repeat family draws.',
},
{
value: 'every one',
label: 'every one',
hint: 'Every streak, a repeat’s other copies too. Always so for one set against itself, which one to one would leave a diagonal.',
},
],
},
{
kind: 'number',
key: 'cells',
label: 'cells',
hint: 'Along the longer axis of the figure; each cell is square in bases.',
default: DOTPLOT_CELLS,
min: 50,
max: 4000,
integer: true,
},
]
function estimate(context: AnalysisContext, params: Params): CostEstimate {
const free = { class: 'free' as const, requests: 0, bytes: 0, note: 'Nothing to read.' }
const x = params.x
const y = params.y
if (typeof x !== 'string' || x === '' || typeof y !== 'string' || y === '') {
return { ...free, refusal: 'Choose the two sequence sets: one along x, one along y.' }
}
void context
return {
class: 'free',
requests: 0,
bytes: 0,
note: 'No file reads: the minimizers of both sets and their merge-join, in the worker that holds the residues — several seconds for two yeast genomes.',
}
}
export const DOTPLOT_TASK: AnalysisTask = {
id: 'dotplot',
title: 'Two sequences against each other',
blurb: 'A dot plot of two assemblies: where they share sequence, as lines that jump, turn or leave.',
keywords: ['dot plot', 'synteny', 'alignment', 'assembly'],
group: '1d',
venue: 'annotations',
version: 1,
dev: 'dotplot',
mapless: true,
availability: (context) => {
const sequences = context.entries.filter((entry) => entry.kind === 'sequence').length
if (sequences >= 2) return READY
return waitingFor(sequences === 1 ? 'Load a second FASTA to set against the first.' : 'Load two FASTA or .2bit files.')
},
params: PARAMS,
outputs: ['matrix', 'table', 'intervals'],
estimate,
}
|