Skip to content
chromosomix

chromosomix 0.16.0

What changed in chromosomix 0.16.0, released on 20 October 2026.

  • Licences, in About (§22.4). Under the tutorial and the source link: chromosomix’s own licence, the GPL, then one line per project it is built with or ported from — three.js, Apache ECharts, h5wasm, @gmod/bbi, cooltools, chromosight, yapc with IDR, SciPy, NumPy, scikit-learn, Boost-HiC, fdlibm, matplotlib, Lucide and Simple Icons — each with what it does here and its licence, a link to the build’s THIRD-PARTY-NOTICES.txt, and a line on the store and service marks. The dialog is wider and taller to hold it, so the build stamp is still on screen on a laptop. The README’s Licence section names the same projects, and a test holds the two to the source.

  • A set of pairs is arcs along a track, or rings on the map (§8.1, §18.7). A loaded BEDPE, longrange or interact file now offers the display a called set has: arcs (1D track) draws every pair as an arc from one anchor to the other along any edge of the map — the 1D browser’s own picture of a BEDPE, flipped with the lane — and map overlay puts the rings back; a reload keeps the choice. A loop set a task called is its arcs as a track too, where it was its anchors: two boxes per loop with nothing to say which went with which.

  • A set of pairs leaves as its anchors (§8.1, §18.7). Beside a called loop set’s BEDPE and TSV, and on a loaded BEDPE’s settings, anchors writes both ends of every pair as a BED, each exact place once however many pairs share it.

  • A sequence’s letters are copied (§8.8). Copy sequence on a sequence lane’s right-click menu puts the bases in view on the clipboard as plain text, at any zoom and beside a map as in the 1D browser, greyed where the view spans several sequences or more than 10 Mb. Where the letters are drawn, a drag across them — or across one reading frame’s codons — selects, with the caret over them, a wash and the drag-to-zoom’s chips: both ends to the base and the length, in bases or amino acids. ⌘C (Ctrl+C) copies the selection, as does the copy button at its end; a frame copies as its protein. A click elsewhere or Escape puts it away.

  • A track’s centre, and a flip by typing (§8.8). The limits are three boxes — foot, centre, head. The centre, empty by default, is IGV’s: the value bars and areas grow from, above it one way and below the other, so a ratio of two tracks centred on 1 reads at a glance. A head typed under the foot flips the track rather than being refused, and a flipped track shows its ceiling first — in the settings, in the batch box and in the range typed under a lane’s name.

  • Duplicate, on every lane’s right-click menu (§8.8), under Hide and Remove: a second row named … (copy) with every setting of the first, drawn wherever the first is, ready to be restyled.

  • A window says how to leave it (§8.9). Under the two lines on how to zoom, a map on a window of one sequence says click to see the whole of IV — which a click on a cell there already did.

  • Loop calling, a 2D task of its own, just before Pattern detection (§18.8, §18.9). It answers the one question where are the loops, where Pattern detection matches a template of which a loop is one of five. Every pixel is tested against four neighbourhoods of its own — a donut about it, a bar through it each way and the square below and left of it — each giving the pixel a local expected, in raw counts; pixels of a like expected are corrected together, in 40 log-spaced λ-chunks at an FDR of 0.1, kernel by kernel; a pixel that passes all four is enriched, enriched pixels within 20 kb are one loop, called at its brightest, and a filter keeps the loops that stand 1.5–2× over their neighbourhoods. The calls land on the map as rings and leave as BEDPE; beside them, a table of every call with its four expecteds and q-values, the loop spectrum, and the count each λ-chunk asked of a pixel. The kernel’s two half-widths are filled in for bins of 4 to 28 kb (w 7, p 4 at 5 kb, 5, 2 at 10 kb, 3, 1 at 25 kb); on a map outside that range the boxes are empty and the run is refused, saying why, until they are filled. A balanced map only. On the command line it is chromosomix loops. It reproduces HiCCUPS as cooltools.dots 0.7.1 computes it, with its Python API’s defaults: held to that package’s own output stage by stage over the demo cooler (test/golden/analysis/hiccups.json), and genome-wide on a mouse Hi-C map at 10 kb in the validation notebook’s new § 19, where the same 236 loops are called with the same counts, clusters, expecteds and q-values, in 48 s of CPU on one thread where cooltools takes 11 minutes over four.

  • Every number the validation’s figures draw, in one table (§18.10). notebooks/validation.qmd writes validation.txt beside its page — https://chromosomix.app/validation/validation.txt, and validation-<tag>.txt among each release’s assets — a tidy table with a row for every mark its twenty figures draw: each point, each vertex of a line, each hexagon of a density with its count, each cell of a picture, each bar, band and line across a panel, each tick that names something and each text, with the figure’s label, the panel’s letter and axes, and what the mark stands for. It is read off each figure as the page shows it, so any figure can be drawn again from it alone. A density is written as its hexagons rather than the millions of values behind it, a symmetric map’s cells once; and the metaplot’s heatmaps, 35,034 transcripts in a picture a few hundred pixels high, now draw each line as the mean of 100 transcripts, which is what the table holds. The P(s) figure’s four panels are lettered, as every other figure’s are.

  • A 3D model leaves as a PDB, for PyMOL, and a PDB this app wrote reads back (§25.2, §25.7). A PDB button beside bed3d on every row of the Structures card and on the drawer’s result for Model from the map, and a .pdb beside the .bed3d that chromosomix reconstruct3d --out writes. One HETATM per bead, one chain per sequence and haplotype with its residues numbered along it, and CONECT between neighbouring beads and nowhere else — none across a gap the model left, none between chains — which is what stops PyMOL joining beads by distance; coordinates centred and scaled so neighbouring beads are 3.8 apart, drawn in further where a model would overflow its columns, with the centre and the factor written down. Its REMARK 250 block gives the PyMOL lines that draw the model as the cell does — a cartoon trace at the cell’s tube radius, or beads — and a table of where each atom is on the genome, which is what lets the Structures card, the deck and --features/--structure read the file back bead for bead. A PDB from anywhere else says nothing about the genome — pastis’ lists its beads in bin order on one chain — and is refused with that reason and the way out, a bed3d of the coordinates beside their bins; so is one of these saved again by PyMOL, which drops every REMARK. A model past a PDB’s columns (99,999 beads, 9,999 in a chain) has its button disabled with the reason, and the shell says it on stderr. Checked against PyMOL 3.2 on the demo yeast, E. coli and mouse models; scripts/check_pdb_pymol.py repeats it.

  • A + before back, for one more file in this tab (§5.5). It opens the landing page’s first section, Load files, in a dialog: the drop area that is also the file chooser, and the URL box under it. A map comes up beside the one open and a track is drawn on it, as a dropped file is; on an empty tab the file opens there, and the tooltip and the dialog’s title say which. A tab opened by dropping a file has no Files column, nothing being connected, and no landing page any more, so a second file held at an address had no door but the palette’s Add a file to this tab.

  • A store’s rows are dragged as the Files column’s are (§20.5, §24.2). Every row that is a file — in a portal’s list, under the lab’s figures and under IGV’s genomes — can be let go on a map’s edge or its middle, on a cell of the deck, on the Tracks card, on an analysis form’s file box or on the landing page, and opens there with the name the store gives it and the tracks it brings. The two verbs on a row say add here and open in a tab of its own, and neither could say under the third map. A saved workspace’s row does not drag, being tabs rather than a file. The drag carries a token for the row, never its address, so a drag from another page opens nothing.

  • The page says when a picture is finished, and at what resolution (§12, §21.4). Once a view has been routed, opened, read and painted — its map’s block, the windows its lanes asked for, any track on it still opening, a smoothing or a finer block being read — and a frame has passed with nothing new begun, the window reports it once: a performance mark named chromosomix:rendered at the moment the last of it ended, a chromosomix:rendered event on window, and, in an embed, a chromosomix:rendered message to the host. The report gives each map on screen with the rung its block was read from, the bins pooled into a cell and the resolution that makes, the lanes drawn, the view state, and drawn, gated (the whole-genome read waiting for its button) or error with the refusal. A repaint alone reports nothing, and the census and circularity reads that follow a view hold nothing back. What a script screenshots on, or times — the viewer timings (notebooks/timing.qmd) wait on it.

  • The timings page opens on the time to a picture (§18.10). notebooks/timing.qmd now first times chromosomix against juicebox.js (on a .hic) and HiGlass (on an .mcool, served by higlass-python’s own tile server): one map and one track, of yeast, chicken and mouse, each seen whole, one chromosome, a region and a locus, from disk and from the bucket it is published in, in a fresh browser context — each viewer’s page loaded empty and left two seconds, as a reader’s is while they find their file — from handing each viewer the files to the viewer saying its picture is finished. Every view is at one resolution the plan names — never the viewer’s choice — and a view a viewer cannot draw at it, a rung the file lacks or juicebox.js’s whole genome, is reported rather than drawn some other way; a picture drawn in part, as juicebox.js draws a whole chromosome with a track beside it, says how much. Every run is a line of viewers.tsv, published beside timings.tsv and attached to each release.

  • chromosomix is now under the GNU General Public License, version 3 or later, in place of MIT (§22.4, §18.9). Peak calling is ported from yapc (GPL-3.0) and the IDR test it thresholds by from IDR (GPL-2.0 or later), and a translation of GPL code can only be distributed under the GPL. Version 3 is the one that admits both of them and echarts’ Apache-2.0 together. Both ports shipped in 0.15.0, which was labelled MIT. LICENSE is the GPL’s text, package.json says GPL-3.0-or-later, and the README, About, llms.txt and every build’s notices say so. Everything else the builds carry was already under a licence compatible with it.

  • A gene found from the map’s box opens with its neighbourhood (§5.4). The block read is the gene’s window and a hundred bins either side, opened framed on the gene as a bookmark is, so the wheel and a drag back out find what is around it; it was the gene alone, with paper past its edges. Coordinates typed are still read as typed.

  • Every row one run returns wears one colour (§18.5) — insulation’s four windows, its boundaries and its domains — where each took the next free colour and read as files of their own.

  • The guided tutorial is on 4DNESC23ZYOF (§30). K562 in situ Hi-C from 4DN, 187 million contacts in 1.9 GB, on chr15 down to chr15:38,100,001-50,025,000 at 5 kb. Insulation runs at four scales, and the tutorial says what they are: the TAD hierarchy, a border every window finds being high in it and one only the narrow windows see a subTAD’s. New steps mark the loop at chr15:45,662,501 × chr15:48,312,501 with an arrowhead and the weak border at chr15:47,215,001 between the two subTADs inside it with a line, save an insulation track as a bigWig, and save the figure as a PDF; the correlation ticks every track. Fifty-eight steps in twelve parts.

  • The contacts box shows e.g. 10M (§5.5, §6.5), paler than a number and gone once the box is clicked; the map’s own total, which was its placeholder and read as a total already typed, is in its tooltip.

  • One tickbox, the app’s own (§26.3): the fields’ corner and border, a resting shadow, the accent and a white tick when ticked, a halo under the hand — in place of the engine’s grey square.

  • The caption switch is on the Export card’s save row (§7.2), after the download and the clipboard it qualifies.

  • Pattern detection’s own words name no package (§18.8). Its row reads Find loops, borders, hairpins, centromeres or stripes by template matching, its thresholds are the template’s own numbers, tuned for it and published with it, and the note on a file with no weights speaks of the published method. Its keywords no longer take loop calling or call loops, which find Loop calling first; its command is still chromosomix chromosight.

  • The package is published without a token (§22.3). The release workflow publishes to npm by trusted publishing: npm takes the upload only from this repository’s release.yml, by the short-lived identity GitHub gives the run, and publishes it with provenance, so each version on npm says which commit and which run built it. The NPM_TOKEN secret is no longer read — 0.15.0 needed it, because npm trusts a workflow only with a package that already exists — and docs/deploy.md says how to configure the package on npmjs.com and retire the token. A fork’s release skips the registry rather than failing on it, where a missing token used to be the test.

  • The whole genome of a .hic is read in fewer requests, more of them at once, and a dropped one without a megabyte of the disk round each read (§3.6, §6.5). A walk across chromosome pairs — a whole-genome picture, the census — read pair by pair, a record’s head and then its blocks, four pairs at a time: the 4DN chicken map’s 630 pairs at 2.5 Mb were 1,258 requests, a minute and a half from its bucket. A walk is now planned before it reads, every place it reads being known: the records’ heads together, each with the 4 KiB past its record’s end, where Juicer puts the coarse blocks, as the stretches of the file they make within 64 KiB of one another, and the blocks left over together after them. The same picture is 427 requests, read six at a time; the yeast map of the demo store, whose records lie end to end, 72 where it was 130; the 4DN mouse map, whose records are megabytes apart, 453 read six at a time where 460 were read four. Pixels are handed over as they were, in the same order, and a plan holds no more than 24 MiB of them. A dropped .hic is walked the same way, in exact reads, where each read paid a 1 MiB slice of the disk: 11 MB for that chicken genome, where it was 222 MiB.

  • The dev features switch in About (§29.1, §26.3). It sat under the version, and it was the one control in a dialog of facts and the one trace anywhere on screen of what is still being built. About now carries none: nothing a reader sees names the switch or what it hides. The slider it was drawn as, the one toggle in the application with a track and a knob, goes with it.
  • Every build’s notices name the code ported into it (§22.4). Analyses that follow a reference implementation function for function — cooltools’ HiCCUPS and peak prominence, cooler’s region parsing, chromosight’s detection functions, yapc’s peak calling and IDR’s fit, SciPy’s cephes and fminbound, NumPy’s pairwise sum and samplers, scikit-learn’s BIRCH, Boost-HiC and fdlibm’s erf — owed their upstreams’ licences as any copy does, and THIRD-PARTY-NOTICES.txt named none of them. Each is now listed, its licence committed verbatim under licenses/. The notices also reproduce chromosomix’s own licence first, which the desktop app and the standalone page carried nowhere, and the MIT licence generic-filehandle2 declares but does not ship, where they said only that it had none.

  • A loop set, a mark or a rectangle lands on a map that spells its sequences another way (§5.9). Lit on a deck’s second map writing XIV where the set says chrXIV, a loop set drew nothing there while the tracks beside it resolved the name; everything drawn at a place now resolves it through the map’s own axis.

  • A computed row waiting to be recomputed is laid out as the others (§18.5). After a reload its name ran past the card and pushed the eye, the arrow and the × off the edge: the row’s status class was also the class of the note under it, and laid the row out on the baseline.

  • Tab from one box of a track’s settings to the next keeps the caret (§8.8). The commit a Tab makes fires with the focus on nobody, and the row was rebuilt under the box being tabbed to: typing a floor, Tab, Tab and a ceiling put the ceiling nowhere. A move between two fields now holds the rebuild until the focus has landed, as a caret in a field always did.

  • An eye has no border, wherever it is (§26.3). The lit look drew one round a pressed eye everywhere but on a loaded track’s row — on a row waiting to be recomputed, on the manual marks, over a figure’s series.

  • A number the map decides still follows the map after a run (§18.2). A run is handed every such number answered, so that its record says what it read, and that answer was what the form remembered: after a run, Base composition’s and Signal by group’s bin size stayed at the rung the run was on instead of following the next. The form now remembers a run as it was asked, the number left to the map unless the reader typed one.

  • A log axis draws its first and last ticks (§18.13). Where the figure gives an axis its own ticks, at 1, 2 and 5 or every digit of a decade, the library hid the first and the last of them whenever the axis’s fitted end went unlabelled, grid lines and all: a loop spectrum from 10.9 kb had no tick below 30 kb. An end goes unlabelled now only where a tick sits on it.

  • A 1D task is one Run, deck or not (§18.1, §18.4). The 1D tasks read the loaded tracks and sequences and never a map, yet a deck offered them run on ★ and run on all N maps: the batch read the same tracks once per map and filed as many identical lanes, each named after a map it never read, and a plain Run filed its lane on whichever map was starred, so moving the star and pressing Run again made a second copy of it. A 1D task’s button now reads plain run, with no batch beside it, and the star is nothing to it: it is priced, framed and laid out on the first map’s sequences and grid, where its form followed the star’s — a deck of two assemblies offered sixteen sequences or seventeen by which map was starred — and what it makes is filed with the session’s tracks, on the first map, so a second press after the star moved is the run already going, or the next run of the same one. Its heading says it reads the loaded tracks, not the map, and a pan no longer marks its result stale and offers to recompute here the same answer. A deck with no map starred greys only the tasks that read a map, and says only the 1D tasks can run, where it greyed the 1D card too under a sentence about a map.

  • A connected folder offers every file the app opens, and says why of the rest (§20.5, §24.9). The Files column drew 3D structures (.g3d, .3dg, .bed3d, .pdb), saved workspaces (.json), text tables (.txt, .tsv, .tab, compressed or not) and anything bgzipped as .bgz dimmed — not a format this viewer opens — though a drop opened every one of them, because the table that routes a name had never been taught them. They are offered now: a structure opens its 3D cell, a workspace’s one mark appends its tabs without leaving an empty tab beside them (its row does not drag, as a store’s workspace row does not), a text table is read by its bytes as a dropped one is, and a .bgz is read as a .gz everywhere, its .tbi included — which, for a gnomAD .vcf.bgz opened by URL, was never looked for. Every name each reader takes is in test/unit/browse-route.test.ts. What stays dimmed says what to do: a track hub’s hub.txt opens from the stores drawer, and its genomes.txt and trackDb.txt are read from it; a CSV is not a table any reader here takes; a .bz2, .xz or .zst wants gzip; a .gzi is not used, a compressed FASTA being read whole; a .crai goes with its CRAM. A workspace or a model in a Drive folder or a Dropbox, whose address is an id or a temporary link, now goes by the name the folder lists it under — fetched as a workspace, or opening a cell — instead of being taken for a track or a map; and a store row of a structure is marked a genome file, no longer a contact map.

  • A row pressed in the Files column opens on an empty tab, whatever it is (§20.5). From a folder on this machine, only a map did: a bigWig, a BED, a model or a loop table pressed on an empty tab went to the road a drop on an open map takes, found no tracks to join and did nothing, under a + that said it would open there. So did a file dropped on an empty window outside the landing page’s zone. Both now take the landing page’s road. And a text file the column offers whose rows no reader takes is refused as text, but not a table this viewer reads, with what a table is read as, rather than as a contact map that is not an HDF5 file.

  • A model dropped beside a map opens one cell, not two (§25.3). A structure dropped on a map, named by a URL or picked from a folder was given a cell for its name and another for its row’s arrival, so every model was drawn twice, and a second model’s spare cell fell back to the first. The watch on the store, which every road ends in, is now the only one that opens a cell.

  • A file let go on a cell of the deck goes into that cell (§16.9). A companion’s map took a file only on its five rectangles, and a tracks cell on none, so a track dropped on the lanes under the second map, on its heading or anywhere on a tracks cell — off the disk or out of the Files column — was drawn under the first map. The whole cell is the target now: on a map it means on this map, a track on its usual edge and an overlay on its face; on a tracks cell, a track drawn in it. The cell is outlined while the file is over it, and the map’s own rectangles keep their finer aim.

  • A row let go on the landing page opens with what it carries (§20.5, §24.2). A row of the Files column dropped on Load files was opened by its address alone, so a .bam came without the .bai its folder had found beside it and was refused for want of one. It opens as a dropped file does now, index and all — and a store’s row, which can be dragged there too, under the store’s name for it.

  • A page asking for a map’s file starts the reader while the file is found (§6.1). The picker starts the reader’s worker and h5wasm once the page is idle, so the first file dropped on it does not wait for them — but the picker a workspace or a restored tab puts up to ask for a map on this machine did not, and the file dropped there waited for a reader to be made. From disk, a chromosome or a locus of the three maps the timings draw took 1.18 s from that page and takes 0.96 s, medians of eleven pictures. A genome, which reads through no reader, starts none.

  • A file dropped on the page waiting for it opens the map the link or workspace named inside it (§5.6). A tab naming map.mcool::/resolutions/25000 or a .hic at 4 kb that has to be given the file asks for it to be dropped, and promises its view back; dropped, the file was opened by its path alone, so an .mcool landed on a rung of its own choosing and on its Chromosomes table, and a map dropped with a track beside it opened as a stranger to the view that asked for it. Both now open at the resolution named, on the view named, the track joining it.

Documentation of chromosomix v0.20.0 · built from 40ec1ec · source