Lesson 6 - De novo plasmid assembly
Learning objectives
- Explain the limitations of tools like
flyefor reconstructing plasmid sequences - Use specialised tools like
plassemblerto perform de novo assembly of plasmids from long reads
6.1 Introduction to plasmid detection
In Lesson 5, we briefly introduced the tool plassembler and its goal to specifically assemble bacterial plasmids. The detection of plasmids in the bacterial genome is of particular importance, especially within the context of identifying antimicrobial resistance genes present in a bacterial isolate. Plasmids are small, circular sequences of DNA that are supplementary to the main chromosome. While they aren't vital to the functioning and maintenance of the cell, they typically contain genes required for antimicrobial resistance. Additionally, plasmids are mobile, meaning they can be passed from cell to cell, and even between different species. This means that AMR genes present on a plasmid can spread between species. As such, being able to accurately detect, assemble, and analyse plasmids in bacterial sequencing data is vital when studying antimicrobial resistance.
Sequencing plasmids suffers from the same problems as sequencing the main bacterial chromosome; frequent repetitive sequences make assembly from short-read sequencing difficult to near impossible. Long read sequencing is essential for generating an accurate assembly of plasmids. However, at the same time, long read sequencing can often result in under-representation of smaller plasmids, particularly those less than 20kb in size. This can be due to these plasmids resisting fragmentation during the library preparation process, meaning fewer sequencing reads ultimately derive from these plasmids, and generic assemblers can end up discarding these reads due to low coverage.
6.2 plassembler
plassembler (Bouras et al., 2023) is a tool built specifically for recovering bacterial plasmids that general-purpose assemblers like flye can miss or mis-assemble. It works alongside either flye or raven, working on the assumption that the chromosome has already been successfully assembled by that tool, and focusing on re-assembling the reads that don't align to it, which should, in theory, contain all the plasmid DNA.
At a high level, plassembler runs through the following steps:
- Start from a long-read-only assembly.
plassemblerneeds aflyeorravenassembly of the full read set as a starting point. It can generate this itself, or you can hand it one you've already produced. - Classify contigs as chromosome or putative plasmids. Any contig longer than a user-specified length threshold (1mb by default) is treated as chromosomal; everything shorter is treated as a candidate plasmid contig.
- Extract the reads that don't belong to the chromosome. All reads are mapped back against the assembly with
minimap2. Reads that map to the chromosome are discarded, while those mapping to the small, candidate plasmid contigs, along with any reads that didn't map anywhere at all, are kept. - Reassemble just those reads. The remaining reads are reassembled from scratch with
unicycler(another bacterial-specific assembly tool). Because the chromosomal reads have been removed, small or low-abundance plasmids that would otherwise be swamped by chromosomal coverage, or discarded outright by a whole-genome assembler's coverage filters, get a much better chance of assembling cleanly and circularising. - Estimate copy number. Reads are mapped back to both the chromosome and the newly assembled plasmid contigs, and the relative sequencing depth is used to estimate each plasmid's copy number per cell.
- Check against a plasmid database. Each recovered contig is compared against PLSDB, a curated database of published plasmid sequences. This tells you whether you've recovered a novel plasmid or one that closely matches something that has already been characterised.
6.2.1 Tool inputs
plassembler needs two things to run on long-read-only data: your reads, and a database used for the PLSDB comparison step. You download the database once with:
This downloads a compact (~437MB), pre-built sketch of PLSDB.
The other key input is the flye assembly. You have two options here:
- Let
plassemblerrunflyeitself, by simply not providing an existing assembly. - Supply the
flyeassembly you've already generated, using--flye_assembly(pointing atassembly.fasta) and--flye_info(pointing atassembly_info.txt).
Since we already generated a flye assembly of our sample in Lesson 5, we should reuse it rather than have plassembler redo that work.
A typical command, reusing an existing flye assembly, looks like this:
plassembler long \
-l /path/to/sample.fastq \
-d /path/to/plassembler_db \
--flye_assembly /path/to/flye/assembly.fasta \
--flye_info /path/to/flye/assembly_info.txt \
-t <int> \
-o /path/to/output/plassembler
6.2.2 Tool outputs and statistics
Running plassembler populates the output directory with several files, including:
plassembler_plasmids.fasta: the final, assembled plasmid contigs, with each header annotated with its estimated copy number. An empty file will be created if no plasmids are detected.plassembler_plasmids.gfa: the corresponding assembly graph, viewable in Bandage just like aflyeassembly graph.plassembler_summary.tsv: a per-contig summary table giving each plasmid's length, estimated copy number, circularity, and (where one exists) its closest match in PLSDB.flye_output/: the underlyingflyeassembly, ifplassemblerranflyeitself rather than being given one.
6.2.3 Comparing plassembler and flye plasmid calls
Because plassembler starts from the small, non-chromosomal contigs and unmapped reads left over from a flye (or raven) assembly, its output and that of the main assembler will potentially overlap and will need to be manually reconciled. There are three broad outcomes to expect:
- Agreement.
plassemblerrecovers a plasmid whose length is close to oneflyealready reported as a small, circular, high-coverage contig. This is the reassuring case: two independent assembly approaches converged on the same sequence, which is good evidence it's a genuine plasmid. plassemblerfinds somethingflyedidn't (or improves on it). This isplassembler's main selling point. A plasmid may be entirely absent fromflye's output (e.g. discarded as low-coverage), present but fragmented into pieces, or present but linear rather than circular.plassembler's targeted reassembly can often close and circularise contigs thatflyewasn't able to.plassemblerfinds fewer plasmids thanflye's small contigs would suggest, or none at all. This can mean that the additional contigsflyepicked up were mis-assembled fragments of the chromosome, unresolved repeats, or contaminating DNA, andplassembler's more careful read classification and reassembly step corrected this error. An emptyplassembler_plasmids.fastais a valid result if the underlying reads genuinely can't support a circularised plasmid, or if the sample simply doesn't carry one. However,plassemblercan be sensitive to read coverage, so it is also possible that it simply didn't have enough reads left over after discarding the chromosomal reads to correctly assemble the plasmids.
In short, agreement between both tools is good evidence for the existence of a plasmid, while disagreement should be manually inspected.
When a plasmid candidate appears in only one tool's output, or the two tools disagree on the genome structure, a few checks can help you judge whether it's likely to be real:
- Coverage relative to the chromosome. Genuine plasmids are usually maintained at a similar or higher copy number than the chromosome, so their per-base coverage (
flye'scov.column, orplassembler's estimated copy number) should be comparable to or greater than the chromosome's. A small contig with chromosome-level or lower coverage is more likely to be a mis-assembled chromosomal fragment. - Circularity. A contig that closes into a circle (in either tool's output, or visually in Bandage) is much stronger evidence of a real plasmid than a linear contig of similar size, since plasmids are naturally circular molecules.
- PLSDB hits. A confident match in
plassembler's PLSDB comparison is strong independent evidence that a contig is a genuine, previously characterised plasmid, since it's very unlikely for a mis-assembled chromosomal fragment to closely match a known plasmid sequence. - Sequence content. Looking at what genes are encoded on a candidate contig can also help: plasmid backbones typically carry genes for replication, mobilisation/conjugation, and (often) antimicrobial resistance, whereas a mis-assembled chromosomal fragment will tend to carry genes typical of core chromosomal function. This is a preview of the annotation work in later lessons, but it's a useful sanity check to keep in mind even now.
- Length and repeat content. A
flyecontig flagged as arepeat(see theassembly_info.txtcolumns in Lesson 5), or one whose length looks suspiciously similar to a known repetitive element (e.g. an rRNA operon), is more likely to be a unresolved repeat than a standalone plasmid. However, true plasmids can sometimes be flagges asrepeat; if it is also circular and matches an entry in PLSDB, it may be a real result that was flagged due to low coverage or read length.
No single one of these checks is definitive on its own, but taken together they let you build a reasonably confident picture of which candidate contigs are real plasmids.
6.3 Exercise
In this exercise, you will run plassembler on your assigned sample, reusing the flye assembly from Lesson 5, then inspect its output to see whether it recovered any plasmids that flye alone missed.
6.3.1 Run plassembler
Run plassembler using your assigned FASTQ file and the flye assembly you generated in Lesson 5. Place the output in a directory called plassembler and use 4 CPU threads. Note that plassembler will create the directory for you; it will error if it already exists, so don't create it beforehand. Use the pre-downloaded plassembler database located at ~/data/ref/plasmid_db_plassembler. Also be sure to pass the full path to your trimmed and filtered FASTQ file.
Solution
plassembler long \
-l ~/filtered/sampleXX.filtered.fastq.gz \
-d ~/data/ref/plasmid_db_plassembler \
--flye_assembly ~/flye/assembly.fasta \
--flye_info ~/flye/assembly_info.txt \
-t 4 \
-o plassembler
Remember to substitute your sample name for sampleXX. This assumes your flye outputs are in the ~/flye directory, as per the instructions in the Lesson 5 exercise.
Once finished, you should have a plassembler directory that looks like:
plassembler/
├── flye_output/
├── logs/
├── plassembler_1789366321.7878132.log
├── plassembler_plasmids.fasta
├── plassembler_plasmids.gfa
├── plassembler_summary.tsv
└── unicycler_output/
The flye_output and unicycler_output folders contain the intermediate results from those two tools. The plassembler_plasmids.fasta and plassembler_plasmids.gfa files contain the sequences and sequence graph, respectively (if any plasmids were found). plassembler_summary.tsv is the summary table describing each plasmid identified.
6.3.2 Inspect the outputs
Once plassembler has finished, inspect the summary table. Note that the table has a lot of columns, so open it in the VS Code editor. You can either navigate to it using the Explorer side-bar, or use the code command:
Displaying large TSV files
The plassembler_summary.tsv file has a lot of columns and can be quite difficult to read within a code editor. There are two ways you can more easily view this file:
- Copy and paste the contents into a spreadsheet program, e.g. Google Sheets or Microsoft Excel.
- Use the VS Code extension Rainbow CSV.
The Rainbow CSV extension was installed on your VMs in the setup instructions. If it was installed successfully, you should see an Align button in the bottom bar of your VS Code window:

Click this, and the columns of your TSV file will become aligned:

Note that this modifies the file in the editor, although it doesn't save the changes. Make sure you don't save the changes. When closing the file, if VS Code asks you to save changes, say no.
You can also cross-check the contig lengths against the ones flye reported in flye/assembly_info.txt, to see whether plassembler has genuinely found something new, or simply reassembled a plasmid flye had already recovered.
6.3.2.1 Questions
- Did
plassemblerdetect any contigs in your sample? If so, how many? - Were the recovered contigs circular, or were some linear?
- Did any of the contigs get a hit against PLSDB? If so, what does that tell you about the plasmid?
- How do the estimated copy numbers compare to what you'd expect? Recall from Lesson 5 that plasmids are often maintained at a higher copy number per cell than the chromosome.
Discussion points
- Finding zero additional contigs is a perfectly valid result: it simply means
flyehad already recovered everythingplassemblercould find from these reads (or that your sample carries no plasmids at all). - A contig that remains linear (rather than circularising) may indicate that reads are still too sparse or too short to bridge the whole plasmid, even after the extra targeted reassembly.
- A high-confidence PLSDB hit is a strong piece of independent evidence that a contig genuinely is a plasmid (and possibly which incompatibility group or host range it belongs to), rather than a mis-assembled fragment of chromosome.
6.3.3 Compare the plassembler and flye plasmid calls
Now that you have your plassembler results, you need to determine which contigs should be kept for downstream analysis. Remember, as disucssed above in Section 6.2.3, good signs of a true plasmid are:
- Higher coverage, copy number, or multiplicity compared to the main chromosome
- Circularity
- PLSDB hits with high identity and similar length
- (For
flye): The contig is not flagged as an unresolved repeat
For the plassembler results, you can find all of this information in the plassembler_summary.tsv file. For flye however, you will need to run an additional tool to check the contigs against PLSDB.
To help you with this, we have created a custom script that takes your flye assembly and searches the same PLSDB database that comes with plassembler for hits from each of your contigs. The script can be found at ~/scripts/utilities/search_plsdb.sh. You can run this as follows:
~/scripts/utilities/search_plsdb.sh \
--fasta flye/assembly.fasta \
--db ~/data/ref/plasmid_db_plassembler \
--output flye/assembly.plsdb.tsv
More on PLSDB
You can find more information about the PLSDB database at their website here: https://ccb-microbe.cs.uni-saarland.de/plsdb2025.
Note that you can also search the database directly on the website, although it isn't as fast or scalable as working on the commandline with a pre-downloaded database.
The script as run above will output a TSV file at flye/assembly.plsdb.tsv that looks like:
Contig Identity Shared Hashes Median Multiplicity P-value NUCCORE_ACC Description NUCCORE_CreateDate NUCCORE_Topology NUCCORE_Completeness NUCCORE_TaxonID NUCCORE_Genome NUCCORE_Length
assembly.part_contig_1.fasta 0.99899 979/1000 3 0 NZ_CP079682.1 Klebsiella pneumoniae subsp. pneumoniae strain WRC29_CMC309MPCH plasmid pCMC309MPCH_P9, complete sequence 2021-07-27 circular complete 72407 plasmid 1137
assembly.part_contig_1.fasta 0.998893 977/1000 3 0 NZ_CP079163.1 Klebsiella pneumoniae subsp. pneumoniae strain WRC08_CMC432MC plasmid pCMC432M_P8, complete sequence 2021-07-22 circular complete 72407 plasmid 1044
assembly.part_contig_1.fasta 0.995101 902/1000 8 0 CP060657.1 Citrobacter freundii strain MGH283 plasmid unnamed3, complete sequence 2020-08-31 circular complete 546 plasmid 3076
assembly.part_contig_1.fasta 1 650/650 2 0 NZ_CP084906.1 Escherichia coli strain EC20 plasmid pEC22-6 2021-10-21 not-set 562 plasmid 670
assembly.part_contig_1.fasta 0.99899 979/1000 3 0 NZ_CP122388.1 Klebsiella pneumoniae subsp. pneumoniae strain KPN-68 plasmid pU7 2023-07-07 linear 72407 plasmid 1138
assembly.part_contig_1.fasta 1 358/358 2 0 NZ_CP118573.1 Enterobacter hormaechei strain 2020CK-00199 plasmid unnamed6 2023-03-03 linear 158836 plasmid 378
assembly.part_contig_1.fasta 1 389/389 3 0 NZ_CP118572.1 Enterobacter hormaechei strain 2020CK-00199 plasmid unnamed5 2023-03-03 linear 158836 plasmid 409
assembly.part_contig_2.fasta 0.996855 936/1000 1 0 NZ_CP079682.1 Klebsiella pneumoniae subsp. pneumoniae strain WRC29_CMC309MPCH plasmid pCMC309MPCH_P9, complete sequence 2021-07-27 circular complete 72407 plasmid 1137
assembly.part_contig_2.fasta 0.99736 946/1000 1 0 NZ_CP079163.1 Klebsiella pneumoniae subsp. pneumoniae strain WRC08_CMC432MC plasmid pCMC432M_P8, complete sequence 2021-07-22 circular complete 72407 plasmid 1044
assembly.part_contig_2.fasta 1 650/650 2 0 NZ_CP084906.1 Escherichia coli strain EC20 plasmid pEC22-6 2021-10-21 not-set 562 plasmid 670
assembly.part_contig_2.fasta 0.997108 941/1000 1 0 NZ_CP087628.1 Klebsiella pneumoniae subsp. pneumoniae strain DD02280 plasmid pDD02280-5 2022-04-23 not-set 72407 plasmid 1856
assembly.part_contig_2.fasta 0.996855 936/1000 1 0 NZ_CP122388.1 Klebsiella pneumoniae subsp. pneumoniae strain KPN-68 plasmid pU7 2023-07-07 linear 72407 plasmid 1138
assembly.part_contig_2.fasta 1 358/358 2 0 NZ_CP118573.1 Enterobacter hormaechei strain 2020CK-00199 plasmid unnamed6 2023-03-03 linear 158836 plasmid 378
assembly.part_contig_2.fasta 0.997361 368/389 2 0 NZ_CP118572.1 Enterobacter hormaechei strain 2020CK-00199 plasmid unnamed5 2023-03-03 linear 158836 plasmid 409
assembly.part_contig_3.fasta 0.999425 988/1000 1 0 NZ_CP043516.1 Enterobacter kobei strain EB_P8_L5_01.19 plasmid pIMPIncN3_57kb, complete sequence 2019-09-14 circular complete 208224 plasmid 56515
assembly.part_contig_3.fasta 0.997058 940/1000 1 0 NZ_CP084054.1 Klebsiella pneumoniae subsp. pneumoniae strain WRC12_S471M plasmid pWRC12_P10, complete sequence 2021-10-04 circular complete 72407 plasmid 1355
assembly.part_contig_3.fasta 0.990016 810/1000 1 0 NZ_CP090795.1 Enterobacter hormaechei strain FY-1 plasmid pFY-1.p3, complete sequence 2022-01-18 circular complete 158836 plasmid 42568
assembly.part_contig_3.fasta 0.992012 845/1000 1 0 NZ_CP090797.1 Enterobacter hormaechei strain Y-2 plasmid pY-2.p1, complete sequence 2022-01-18 circular complete 158836 plasmid 41269
assembly.part_contig_3.fasta 0.993499 872/1000 1 0 NZ_CP010378.1 Enterobacter hormaechei subsp. hormaechei strain 34983 plasmid p34983-59.134kb, complete sequence 2015-01-21 circular complete 301105 plasmid 59134
assembly.part_contig_3.fasta 1 650/650 1 0 NZ_CP084906.1 Escherichia coli strain EC20 plasmid pEC22-6 2021-10-21 not-set 562 plasmid 670
assembly.part_contig_3.fasta 0.996855 936/1000 1 0 NZ_CP086012.1 Pseudomonas aeruginosa isolate KB-PA_F19 plasmid pKB-PA_F19-2 2021-11-08 linear 287 plasmid 2519
assembly.part_contig_3.fasta 0.991732 840/1000 1 0 NZ_CP106962.1 Leclercia adecarboxylata strain 17YN198 plasmid pIMP-1, complete sequence 2023-07-07 circular complete 83655 plasmid 42504
assembly.part_contig_3.fasta 0.999087 981/1000 1 0 NZ_CP110890.1 Citrobacter freundii strain CF1807 plasmid pCF1807-4, complete sequence 2022-11-23 circular complete 546 plasmid 33719
assembly.part_contig_3.fasta 0.999087 981/1000 1 0 CP110903.1 Citrobacter freundii strain CF2206 plasmid pCF2206-3, complete sequence 2022-11-20 circular complete 546 plasmid 33742
assembly.part_contig_3.fasta 1 358/358 1 0 NZ_CP118573.1 Enterobacter hormaechei strain 2020CK-00199 plasmid unnamed6 2023-03-03 linear 158836 plasmid 378
assembly.part_contig_3.fasta 1 389/389 1 0 NZ_CP118572.1 Enterobacter hormaechei strain 2020CK-00199 plasmid unnamed5 2023-03-03 linear 158836 plasmid 409
assembly.part_contig_3.fasta 0.999232 984/1000 1 0 NZ_CP043856.1 Enterobacter hormaechei strain EB_P6_L3_02.19 plasmid pIMPIncN3_52kb, complete sequence 2019-09-20 circular complete 158836 plasmid 51628
This file will show you all of the hits that each contig had against the PLSDB database and:
- The identity match of the contig against the plasmid in the database (
identity); ideally this is very close to or exactly1 - The number of hashes the contig shares with the database hit (
Shared Hashes); this should be as high as possible - The p-value of the match (
P-value); this should be as low as possible or0 - The plasmid ID (
NUCCORE_ACC) - The length of the plasmid in the database (
NUCCORE_Length); this should be as close to the length of the contig as possible - The circularity of the plasmid in the database (
NUCCORE_Topology); ideally this will becircular
If you find that a flye contig gets the same PLSDB hit as one of your plassembler contigs, that's a good sign that it is a real contig. In this case, you might choose to keep the contig that has the closest match in length and/or sequence identity.
PLSDB hits from other species
Note that the Description column may show a different species than that of your sample. The PLSDB hit simply states the species that plasmid was characterised in, but since plasmids can pass between species, finding a very close hit in another species is not unsurprising.
Run this script on your flye assembly. Then, inspect the output file and answer the questions below.
6.3.3.2 Questions
- Which contigs appear in both tools' output, which appear only in
flye's, and which appear only inplassembler's? - For any contig unique to
flye, does its coverage and circularity support it being a genuine plasmid, or does it look more like a mis-assembled chromosomal fragment? Does it closely match any plasmids in PLSDB? - For any contig unique to
plassembler, is there evidence (a PLSDB hit, high copy number, circularity) supporting it as a real, novel recovery, rather than an artefact of the targeted reassembly? - Based on all of this, which contigs would you carry forward into your final assembly, and which would you discard?
6.3.4 Create your complete assembly
Based on the results from both flye and plassembler, you should now create a final, complete assembly from both tools' outputs. We have written another custom script to help you accomplish this, which can be found at ~/scripts/utilities/merge_contigs.sh. The tool will take the flye and plassembler assemblies, the name of your chromosome contig from the flye output, and a comma-separated list of all of the contig names you want to keep. It will then merge the contigs into a single FASTA file and rename them as either chromosome or plasmid_#. For example:
~/scripts/utilities/merge_contigs.sh \
--flye flye/assembly.fasta \
--plassembler plassembler/plassembler_plasmids.fasta \
--chromosome contig_1 \
--keep contig_1,contig_2,2,3 \
--output draft_assembly.fasta
A few notes for using the script:
- You must always provide the chromosome contig name from
flyewith--chromosome.- This is usually but not always
contig_1; double check yourassembly_info.txtfile before you run the command.
- This is usually but not always
- If you want to keep all contigs, simply leave out the
--keepparameter. - If you only have a few contigs you want to remove, you can replace
--keepwith--excludeand list the contigs you want to remove instead. - Remember that
flyecontigs are named likecontig_1,contig_2, whileplassemblercontig names are purley numerical, e.g.1or2.
Finally, the tool will also generate a merged assembly graph (.gfa) file and a map of the old IDs (contig_1, contig_2, etc.) to new IDs (chromosome, plasmid_1, etc.). You will need these later.
Run the merge_contigs.sh script to create your complete assembly and name it draft_assembly.fasta
Discussion points
- Neither tool is automatically "correct" when they disagree; treat each candidate contig on its own merits using the evidence above, rather than trusting whichever tool happened to produce it.
- It's entirely possible to conclude that none of the small contigs from either tool represent real plasmids, or conversely that your sample carries several. Both are valid outcomes, and this exercise is about building a defensible argument either way, not reaching a predetermined answer.
- Keep in mind that these checks are all circumstantial evidence, not proof. Gene annotation and consensus assemblies will give you further tools to build confidence in your plasmid calls.
Wrap-up
You've now used a plasmid-specific tool to recover small or low-coverage plasmids that a general-purpose assembler like flye can struggle with, and refined your draft assembly. Next, we'll look at how quality control of your assembly, and, optionally, how to combine multiple assemblies into one consensus genome.