Optional layers¶
mobilome.run: true is the whole switch for the module itself
(Turning it on). It is not the switch for the four layers
described here. Each of them stays off until you give it a source of its own, and
turning the module on changes none of them.
Terms used on this page
| AMR | antimicrobial resistance |
| IS | insertion sequence — the smallest mobile element, carrying only the genes it needs to move itself |
| ICE | integrative and conjugative element — carries its own conjugation machinery, so it can move itself into another cell |
| IME | integrative mobilisable element — carries a relaxase but no apparatus of its own, so it needs a helper element |
| AICE | actinomycete integrative and conjugative element |
| att site | the short direct repeat left at each end of an element where it integrated |
| HMM | hidden Markov model — a statistical profile of a gene or protein family |
The four layers¶
| Layer | What it adds | Switched on by | Modes | Rules |
|---|---|---|---|---|
| ICEscan models | a second MacSyFinder model set run beside CONJscan: the AICE class, roughly twice as many IMEs, and integrase profiles CONJscan does not carry | mobilome.icescan.run: true |
all | 2 |
| TnCentral | curated transposon and integron names — the only thing that makes ladder tier 4 reachable | mobilome.tncentral.url or .dir |
all | 3 |
| ICEberg 3.0 | curated names for the elements the ICE/IME caller already found. Changes no gene's tier | mobilome.iceberg.urls or .dir |
all | 3 |
| ISOSDB copy number | how many IS copies the assembler collapsed, from read depth. Changes no gene's tier | mobilome.isosdb.fasta_url + family_map_url, or .dir |
illumina, hybrid |
4 |
Twelve rules in total, against the ten the module runs on its own. Every layer is independent: any combination is valid, and a layer you leave alone is skipped in full — its rules are never defined, nothing is downloaded, and none of its outputs appear.
Where the data comes from
All four fetch third-party data at run time. BacFlux ships none of it: the
workflow distributes a URL and you download under your own agreement with the
licensor, the same arrangement bakta_db, gtdbtk_db and the CARD link have
always had. Licence types are listed once, on
Licensing.
Half-configured is an error, not a silent skip¶
The gating is deliberately blunt: a layer is on when it has a source and off when it does not. Two configurations are ambiguous rather than off, and both stop the run at parse time — before any job starts — rather than three hours in:
[BacFlux] mobilome.icescan.run is true but neither mobilome.icescan.url nor
mobilome.icescan.dir is set, so there is no model package to use.
[BacFlux] mobilome.isosdb.fasta_url is set but mobilome.isosdb.family_map_url is
empty, so the IS family map cannot be downloaded and every element would be
reported as 'unassigned'.
Each message goes on to name the ways out: set the missing key, point dir: at a
copy you already hold, or switch the layer off. The reasoning is the same in both
cases — asking for a layer and getting today's results back, with nothing to say
the layer never existed, is worse than a stop.
ICEscan models¶
A second set of machinery models, run over the same Bakta proteins as CONJscan. The two hit tables are merged before the ICE/IME caller sees them.
It is not a second opinion. ICEscan is a fork of CONJScan by the same
Institut Pasteur authors — its own metadata.yml still calls itself CONJScan —
and it is one minor version behind the release BacFlux installs (2.0.1 against
2.1.0). It is therefore added alongside CONJscan and never instead of it: the
fork drops the MOB relaxase models, the decayed-machinery models and the whole
plasmid set, so a swap would lose elements BacFlux currently detects.
What it adds. Two system models CONJscan 2.1.0 does not carry — IME and
AICE — and 21 profile HMMs: eight integrase families, the Gram-positive and
IME relaxases, and the AICE machinery. The integrases are the substantive part,
because CONJscan carries none at all: conjugation is its subject and integration
is not. Four of the eight are used as element anchors; the other four are
integron or chromosomal housekeeping recombinases, deliberately ignored because
they would anchor an element onto the wrong gene.
The measured effect is on IMEs: over the 28-genome benchmark, 10 ime rows
without the layer and 21 with it. Turning it off roughly halves the IME rows; it
does not remove them, because BacFlux's own rules call an IME whenever the anchors
are an integrase plus a relaxase with no mating apparatus, and CONJscan's MOB
models supply plenty of those. aice calls are ICEscan-only. The rest of the
numbers, including what the layer does not improve, are in
Validation.
What it does not add: boundaries. MacSyFinder reports gene ordinals — "the 41st protein in the file" — never base pairs, so every coordinate BacFlux prints still comes from its own Bakta GFF3 join, its own clustering and its own att search. ICEscan's own spans are never used as element edges.
mobilome:
icescan:
run: true # the only key you must change — a URL ships filled in
sha256: "" # optional, recommended: pins which release you analysed with
dir: "" # optional: a MacSyFinder models directory holding ICEscan/
This is the one layer whose url is already populated in the shipped config (the
ICEfinder2 database bundle, ~61 MB, of which only macsydata/ICEscan is kept and
the rest discarded). So run: true is all it takes.
Both machinery searches run at the same stringency, and must
CONJscan and ICEscan are both given mobilome.coverage_profile (default
0.5, MacSyFinder's own default). Their hit tables are merged, so different
stringencies would make an element's class depend on which model set happened
to be more permissive. What lowering it buys and costs, measured, is on
Tuning.
Outputs. 08.mobilome/icescan_models/ once per run, and
08.mobilome/{sample}/icescan/ per sample. No new column appears in the mobility
table: the layer works by changing what the ICE/IME caller can see.
TnCentral¶
Curated transposons and integrons, matched by blastn against the whole
assembly, then merged into element copies and named.
Tier 3 is an inference: two IS copies of one family, the right distance apart, a gene between them, so we call it a composite transposon. The pattern only stays right because of hand-written exceptions to it — IS26 flanks its cargo in direct orientation, so it is exempted from the same-orientation test every other family has to pass, and without that exemption BacFlux would miss the most important architecture in clinical AMR. A TnCentral hit needs no such exception. It matches an element somebody characterised, named and deposited, whose architecture is already known. Where both fire on one gene the curated hit wins, and the composite call it displaced is written to the audit. This is the only route to tier 4.
mobilome:
tncentral:
url: "https://tncentral.ncc.unesp.br/api/download_blast/nc/tn"
sha256: "" # optional, recommended — the endpoint is unversioned
dir: "" # optional: a directory already holding tncentral.fa
min_identity: 90.0 # percent identity before a hit may confer a name
min_reference_coverage: 0.8 # fraction of the CURATED element that must be present
min_reference_coverage is measured against the reference, not against your
contig: a 7 kb transposon inside a 300 kb contig covers 2% of the contig and 100%
of itself. The question is whether the whole of a known element is here — a
fragment of a transposon is not that transposon. On a draft assembly a low value
usually means the element is split across contigs. Both
thresholds are naming conventions rather than biological boundaries, and every
hit refused a name reaches the discard audit with the measured identity and
coverage that refused it.
The nc/tn endpoint above is the transposon set on its own. The variants that
also serve ISfinder content bring ISfinder's terms with them — written
authorisation to download, no redistribution — so they are deliberately not wired
in.
This layer names elements; it does not guarantee a tier 4 row
Reaching tier 4 needs a TnCentral source and at least
min_reference_coverage of a curated element present and no higher tier
claiming the gene first. On the ATCC BAA-2146 positive control the layer named
seven elements and exactly one produced a tier 4 row — blaCTX-M-15 in
TnEcp1.1 at 87% coverage; the other six sat on plasmids and scored 5 or 6.
On fragmented clinical assemblies the same TnEcp1.1 was refused outright at
12% and 49% coverage of its 3,417 bp reference. Expect names on any genome,
and tier 4 mainly on closed ones. See Worked example.
Outputs. 08.mobilome/tncentral_db/ once per run;
{sample}_tncentral_blast.tsv, {sample}_named_elements.tsv and
{sample}_named_elements_discarded.tsv per sample. The named elements are handed
to the co-localisation step as a third element table, alongside the IS calls and
the ICE candidates.
ICEberg 3.0¶
Curated names for the candidates the ICE/IME caller already found — ICEs, IMEs, AICEs and genomic islands. A conjugative region never takes a name, because it has no integrase and calling it an ICE is exactly what the classifier refused to do.
This layer labels; it never decides. The caller has already said what is an
ICE and what class it is, and turning this on cannot change any gene's tier. What
it changes is "predicted self-transmissible element" into a name like
ICEKpnATCCBAA-2146-1, which is what lets you look the element up.
mobilome:
iceberg:
urls:
- https://tool2-mml.sjtu.edu.cn/ICEberg3/data/download/ICE_seq_all.fas
- https://tool2-mml.sjtu.edu.cn/ICEberg3/data/download/IME_seq_all.fas
dir: "" # optional: a directory of .fas files you already hold
min_identity: 80.0 # identity floor for a name
min_overlap_fraction: 0.5 # how much of OUR candidate the curated element must cover
Note the host: the older bioinfo-mml.sjtu.edu.cn path 404s for ICEberg 3.0,
because it still serves ICEberg 2.0 — which is exactly why a stale URL kept
looking plausible. ICE_seq_all.fas is around 100 MB and the server is slow, so
the download rule is allowed to resume a part-finished transfer.
min_overlap_fraction is lenient next to the transposon cascade on purpose. ICEs
are mosaic and their cargo varies between strains, so demanding near-completeness
would refuse to name exactly the divergent elements a name helps with most. A
separate rule handles the other direction: when less than 80% of the
reference is present, the name is suffixed -like, because we have part of a
known element rather than the whole of it. That 80% is not a config key — it is
EXACT_NAME_REFERENCE_COVERAGE in
workflow/scripts/80_mobilome/name_ice_elements.py, named here so there is
something to grep for.
The real reason to switch this layer on
It measures how far the module's boundaries fall short. On the
K. pneumoniae ATCC BAA-2146 positive control the ICE call spans 54,943 bp
against ICEberg's 58,048 bp for the same element: 0.946 of it recovered,
stopping 3,138 bp inside its far end, and the naming audit records it. Any AMR
gene in that last 3 kb is scored as though it were outside the ICE. That is
the good case — a closed genome where the att search found a
tRNA-anchored repeat. With boundary_method = none the interval is only the
machinery span and the shortfall is far larger
(Draft assemblies).
A second caution that comes with any name from this layer: ICEs of one species are near-identical across strains, so one real element matches dozens of curated entries. The name is a group label, not a unique identification.
Outputs. 08.mobilome/iceberg_db/ once per run;
{sample}_iceberg_blast.tsv, {sample}_ice_candidates_named.tsv and
{sample}_ice_naming.tsv per sample. Whenever this layer is on, the
co-localisation step reads the named candidate table instead of the unnamed one:
the same rows, mge_name filled in, and six columns added carrying the evidence
behind each name — identity, how much of our interval the curated element covers,
how much of the curated element is present, and how many other entries fit about
as well.
ISOSDB copy number¶
On a fragmented assembly the located IS count is a floor, and an unquantified one: you cannot tell whether it is 2 short or 40 short. This layer puts a number on it.
Reads are immune to assembly collapse — every copy of an IS contributes its own reads whether or not the assembler kept them apart — so an IS present in five copies attracts about five times the read depth of the single-copy chromosome:
Both depths are measured with BBMap at identical settings, one against ISOSDB and one against the sample's own assembly, so their ratio is comparable.
mobilome:
isosdb:
fasta_url: "https://raw.githubusercontent.com/joshuakirsch/pseudoR/main/ISOSDB.V3.fna.zip"
family_map_url: "https://raw.githubusercontent.com/joshuakirsch/pseudoR/main/IS_fam_annot.txt"
dir: "" # optional: a directory already holding both files
min_covered_percent: 90.0 # a database entry must be covered end to end to be believed
min_copy_number: 0.5 # below this multiple of the genome baseline, treated as absent
Set both URLs or neither. A partly covered database entry is usually a conserved
domain shared with another family, and averaging it in would inflate every
estimate, which is what min_covered_percent refuses. min_copy_number sits
below 1.0 on purpose: a real single-copy IS lands near 1×, and sampling noise
plus mapping loss routinely drag it to 0.6–0.8×.
illumina and hybrid only. In nanopore and contigs mode there are no short
reads to map and the layer is absent, whatever the config says.
Outputs. 08.mobilome/isosdb_db/ once per run;
{sample}_isosdb_covstats.tsv, {sample}_assembly_covstats.tsv,
{sample}_is_copy_number.tsv and {sample}_is_copy_number_audit.tsv per sample.
The deliverable is one row per IS family:
| Column | What it is |
|---|---|
located_copies |
copies ISEScan found on the contigs |
estimated_copies |
copies the read depth implies |
collapse_delta |
estimated − located — the assembler's collapse, measured |
db_informative |
TRUE only when ISOSDB detected the family and the estimate reached the located count |
n_db_entries_detected, max_entry_copy_number, genome_baseline_depth |
the working behind the estimate |
Reported per family rather than per entry because ISOSDB is dereplicated at 95% identity and families remain similar: the family sum is robust to which near-identical entry an ambiguous read happened to land on, and the per-entry split is not.
This table changes no AMR gene's tier, and must not
It says how many copies exist, never where they are, so it cannot place a gene inside anything. Nothing downstream reads it — it is a quality metric on the IS inventory, read by a person.
PROVENANCE.txt¶
Three of these four addresses carry no version at all, and the fourth is a
GitHub main branch that can move under you. Fetch nc/tn today and again in six
months and you may get different data from the same URL, with nothing in the file
to say which is which.
So each download rule writes a PROVENANCE.txt beside the data it fetched,
recording what actually arrived:
source: https://tncentral.ncc.unesp.br/api/download_blast/nc/tn (sha256 8f3c…)
fetched: 2026-08-16T09:41:07Z
fasta_sha256: 5b90…
sequences: 533
| File | Written by | Records |
|---|---|---|
08.mobilome/icescan_models/PROVENANCE.txt |
icescan_models |
source, fetch date, the package's own version line, number of profiles |
08.mobilome/tncentral_db/PROVENANCE.txt |
tncentral_db |
source, fetch date, checksum of the repaired FASTA, sequence count |
08.mobilome/iceberg_db/PROVENANCE.txt |
iceberg_db |
source, fetch date, checksum of the concatenated FASTA, sequence count |
08.mobilome/isosdb_db/PROVENANCE.txt |
isosdb_db |
source, fetch date, checksum of ISOSDB.V3.fna, sequence count |
Under those fields each file carries a few lines on why it exists and on the terms the data came under.
Two practical uses. Keep the file with the results — it is the line a methods section needs, and it is the only record that exists. And check it when two runs disagree: a different checksum on the same URL is the first thing to rule out.
conjscan_models, the module's always-on model fetch, writes none. It installs a
versioned package through msf_data install, so the version is already
recoverable.
Only two of the four can be pinned in advance
mobilome.icescan.sha256 and mobilome.tncentral.sha256 are checked against
the download and fail the rule on a mismatch, with a message saying the
upstream file changed. Set both once you have decided which release you are
working with.
ICEberg and ISOSDB have no sha256 key. ICEberg serves two files rather
than one archive and the large one has to be resumable over a slow link, so a
single pinned digest is the wrong instrument; ISOSDB comes from GitHub raw
paths, where the source repository's own history is the version record. For
both, the observed checksum is recorded after the fact — you can say later
what you used, but you cannot demand it up front.
What the download rules do besides downloading¶
- They refuse an error page. A bot block or a redirect arrives with a 200 and would otherwise be indexed as an empty database that silently names nothing. Each rule tests the archive or the FASTA and fails loudly instead, printing the first bytes it received. TnCentral's server rejects curl's default user-agent, so the rule identifies as a browser; if that stops working the rule fails rather than producing an empty database.
- They repair the FASTA before indexing it. Both curated nucleotide sets ship
with deflines glued onto the end of a sequence line instead of starting their
own — 21 of 533 records in the TnCentral release checked, 1 of 1,774 in
ICEberg's. The damage runs both ways: those records are invisible to
makeblastdb(for TnCentral that included Tn7 itself and eleven integrons, the very class tier 4 exists to name), and the records they were glued to become chimeric.In_Tn6162measured 41,492 bp instead of 8,911 — 4.7× its real length — and since the naming cascade tests coverage asalignment / reference length, an inflated reference makes an element almost impossible to name, silently. After repair, each rule asserts that every>begins a line and stops if it does not. - They rebuild the BLAST index as v5. TnCentral ships a v4 index built from the unrepaired FASTA, so it is missing the same 21 records. It is deleted rather than reused.
Practical notes¶
The databases live in the output directory, under 08.mobilome/, and are
fetched once and shared by every sample in that run. A second project therefore
downloads them again. That is what the dir: key on every layer is for: point it
at a copy you already hold and nothing is fetched. dir: always takes precedence
over the URLs, exactly as directories: beats links: elsewhere in the config.
Network and environments. icescan_models uses wget and tar from the
environment you launched Snakemake in, with no conda environment of its own — the
same arrangement as the CARD download (Installation).
The other three download rules, and the BLAST searches that follow them, share one
small conda environment carrying BLAST, curl and unzip, built on first use.
The ISOSDB read mapping uses the same BBMap environment the CARD leg already
builds.
Do not mix runs. Switching a layer on or off mid-project changes what the
mobility table can report, and nothing in the table says which layers were on when
it was written — only the PROVENANCE.txt of each layer that ran. Re-run
everything rather than comparing a half-and-half result set; a mixed one is very
hard to unpick later.
Related pages¶
| Page | Read it for |
|---|---|
| Turning it on | the master switch, and what the module does on the default configuration |
| Reading the output | what these layers change in {sample}_amr_mobility.tsv, column by column |
| Tuning | the naming and coverage thresholds, with the measurements behind them |
| Validation | what each layer was measured to add, and what it did not |
| Licensing | the terms attached to each of the four data sources |
| Configuration | every key in the mobilome block, in the file's own order |