Skip to content
Commits on Source (6)
......@@ -45,7 +45,7 @@ tiles.
<h2>Failure</h2>
<p>
This module will issue a warning if any tile shows a mean Phred
This module will raise and error if any tile shows a mean Phred
score more than 5 less than the mean for that base across all
tiles.
</p>
......
Installing FastQC
-------------------
FastQC is a java application. In order to run it needs your system to have a suitable
Java Runtime Environment (JRE) installed. Before you try to run FastQC you should therefore
ensure that you have a suitable JRE. There are a number of different JREs available
however the ones we have tested are the v1.6-v1.8 JREs from Oracle. These are available
for a number of different platforms.
Windows/Linux: Go to java.com - click on Free Java Download - DON'T click the large red button
but choose the smaller link to "See all java downloads". Find your operating system and select
the appropriate offline installer. If you are using a 64bit operating system (and nearly
everyone is these days), then make sure you select the 64bit version of the the installer.
OSX: On newer versions of OSX you need to install the Java Development Kit. The normal Java
runtime environment IS NOT enough. To get this go to java.com, click "Free java download",
then IGNORE the big red button, and select "See all java downloads", on the next screen select
"Looking for the JDK?" from the left hand menu and select the link to "JDK downloads" in the
first paragraph. You can then click the "Download" button underneath JDK in the page you are
taken to. Sorry this is such a pain!
OSX
---
FastQC is distributed as a DMG image file. Download the image from the project page
and double click it to open it. You should see the FastQC application appear in a
Finder window. Drag the application from there to wherever you want to install it
on your machine. Once you've copied the application double click it to open it.
FastQC is not a signed application therefore it may initially be blocked by the
Gatekeeper application. To avoid this open FastQC by right clicking on the app
and selecting open. This may prompt you to allow it to open. If it is still
blocked go to System Preferences > Security and Privacy and you should see an option
to allow the application to open. You only need to do this once and the preference
should be remembered by OSX.
Windows and Linux
-----------------
FastQC is a java application. In order to run it needs your system to have a suitable
Java Runtime Environment (JRE) installed. Before you try to run FastQC you should
therefore ensure that you have a suitable JRE. There are a number of different JREs
available however the ones we have tested are the latest Oracle runtime environments
and those from the adoptOpenJDK project (https://adoptopenjdk.net/). You need to
download and install a suitable 64-bit JRE and make sure that the java application
is in your path (most installers will take care of this for you).
On linux most distributions will have java installed already so you might not need to
do anything. If java isn't installed then you can add it by doing:
If you're not sure whether you have java installed then you can test this from a command
prompt. To get a command prompt try:
Ubuntu / Mint: sudo apt install default-jre
Windows: Select Start > Run, and type 'cmd' (no quotes) in the box which appears, press OK
CentOS / Redhat: sudo yum install java-1.8.0-openjdk
MaxOSX: Run Applications > Utilities > Terminal
You can check whether java is installed by opening the 'cmd' program on windows, or
any shell on linux and typing:
Linux: From your applications menu look for an application called 'Terminal' or 'Konsole'.
Either of these will give you a usable shell.
java -version
At the command prompt type 'java -version' and press enter. You should see something like:
You should see something like:
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)
>java -version
openjdk version "11.0.2" 2019-01-15
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.2+9)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.2+9, mixed mode)
If you get an error then you don't have java installed. If the version listed on the first
line is less than 1.6 then you might have problems running FastQC.
Actually installing FastQC is as simple as unzipping the zip file it comes in into a
suitable location. That's it. Once unzipped it's ready to go.
......@@ -59,9 +66,7 @@ Windows: Simply double click on the run_fastqc bat file. If you want to make a
shortcut then we've included an icon file in the top level directory so you don't have
to use the generic bat file icon.
MacOSX: There is an application bundle for MacOSX which you can use to install and run
FastQC. Just drag the application from the disk image to your Applications folder (or
wherever you want to install the program).
MacOSX: Double click on the FastQC application icon.
Linux: We have included a wrapper script, called 'fastqc' which is the easiest way to
start the program. The wrapper is in the top level of the FastQC installation. You
......
RELEASE NOTES FOR FastQC v0.11.9
--------------------------------
This is a bugfix release which resolves some issues with the program;
- We removed the native look and feel from the linux application since
it's horribly broken
- Fixed a hang if a run terminated from an out-of-memory error
- Fixed a corner case where adapters could occasionally be double-counted
- Updated the fast5 parser to account for the newer format multi-read
oxford nanopore fast5 files
- Fixed problems if analysing a completely blank file
RELEASE NOTES FOR FastQC v0.11.8
--------------------------------
......
fastqc (0.11.9+dfsg-1) unstable; urgency=medium
* New upstream version
* debhelper-compat 12 (routine-update)
* Standards-Version: 4.4.1 (routine-update)
* Updated patches.
-- Steffen Moeller <moeller@debian.org> Sun, 12 Jan 2020 22:40:39 +0100
fastqc (0.11.8+dfsg-2) unstable; urgency=medium
* Team upload.
......
......@@ -5,14 +5,14 @@ Uploaders: Steffen Moeller <moeller@debian.org>,
Olivier Sallou <osallou@debian.org>
Section: science
Priority: optional
Build-Depends: debhelper (>= 11~),
Build-Depends: debhelper-compat (= 12),
javahelper,
default-jdk,
ant,
libhtsjdk-java,
libjbzip2-java,
libcommons-math3-java
Standards-Version: 4.2.1
Standards-Version: 4.4.1
Vcs-Browser: https://salsa.debian.org/med-team/fastqc
Vcs-Git: https://salsa.debian.org/med-team/fastqc.git
Homepage: http://www.bioinformatics.babraham.ac.uk/projects/fastqc/
......
......@@ -17,7 +17,7 @@ Index: fastqc/fastqc
===================================================================
--- fastqc.orig/fastqc
+++ fastqc/fastqc
@@ -74,7 +74,6 @@ my $quiet;
@@ -97,7 +97,6 @@ my $quiet;
my $nogroup;
my $expgroup;
my $casava;
......@@ -25,7 +25,7 @@ Index: fastqc/fastqc
my $nofilter;
my $kmer_size;
my $temp_directory;
@@ -92,7 +91,6 @@ my $result = GetOptions('version' => \$v
@@ -114,7 +113,6 @@ my $result = GetOptions('version' => \$v
'threads=i' => \$threads,
'kmers=i' => \$kmer_size,
'casava' => \$casava,
......@@ -33,7 +33,7 @@ Index: fastqc/fastqc
'nofilter' => \$nofilter,
'contaminants=s' => \$contaminant,
'adapters=s' => \$adapter,
@@ -189,10 +187,6 @@ if ($casava) {
@@ -211,10 +209,6 @@ if ($casava) {
push @java_args ,"-Dfastqc.casava=true";
}
......@@ -44,7 +44,7 @@ Index: fastqc/fastqc
if ($nofilter) {
push @java_args ,"-Dfastqc.nofilter=true";
@@ -326,11 +320,6 @@ DESCRIPTION
@@ -350,11 +344,6 @@ DESCRIPTION
(including being gzipped and ending with .gz) otherwise they
won't be grouped together correctly.
......@@ -60,7 +60,7 @@ Index: fastqc/uk/ac/babraham/FastQC/Sequence/Fast5File.java
===================================================================
--- fastqc.orig/uk/ac/babraham/FastQC/Sequence/Fast5File.java
+++ /dev/null
@@ -1,107 +0,0 @@
@@ -1,142 +0,0 @@
-/**
- * Copyright Copyright 2010-17 Simon Andrews
- *
......@@ -84,6 +84,8 @@ Index: fastqc/uk/ac/babraham/FastQC/Sequence/Fast5File.java
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import ch.systemsx.cisd.hdf5.HDF5Factory;
-import ch.systemsx.cisd.hdf5.IHDF5SimpleReader;
......@@ -92,45 +94,58 @@ Index: fastqc/uk/ac/babraham/FastQC/Sequence/Fast5File.java
-
- private Sequence nextSequence = null;
- private File file;
-
- private String name;
- private IHDF5SimpleReader reader;
- private String [] readPaths = new String[] {""};
-
- protected Fast5File(File file) throws SequenceFormatException, IOException {
- this.file = file;
- name = file.getName();
-
- IHDF5SimpleReader reader = HDF5Factory.openForReading(file);
- private int readPathsIndexPosition = 0;
-
- String [] rdfPaths = new String [] {
- private String [] rdfPaths = new String [] {
- "Analyses/Basecall_2D_000/BaseCalled_template/Fastq",
- "Analyses/Basecall_2D_000/BaseCalled_2D/Fastq",
- "Analyses/Basecall_1D_000/BaseCalled_template/Fastq",
- "Analyses/Basecall_1D_000/BaseCalled_1D/Fastq"
- };
-
- boolean foundPath = false;
- for (int r=0;r<rdfPaths.length;r++) {
-
- if (reader.exists(rdfPaths[r])) {
-
- foundPath = true;
- String fastq = reader.readString(rdfPaths[r]);
- protected Fast5File(File file) throws SequenceFormatException, IOException {
- this.file = file;
- name = file.getName();
-
- String [] sections = fastq.split("\\n");
- reader = HDF5Factory.openForReading(file);
-
- if (sections.length != 4) {
- throw new SequenceFormatException("Didn't get 4 sections from "+fastq);
- }
- // These files have changed structure over time. Originally they contained
- // a single read per file where the base of the heirarchy was the read
- // itself.
- //
- // Later the files moved to having multiple reads per file. Now there is
- // an additional top level folder per read with the sub-structure being the
- // same as it used to be for the individual reads.
- //
- // We need to account for both of these structures.
-
-
- // See if we can see a bunch of paths starting with "read_" at the top of the
- // heirarchy. If we can then we substitute the read paths for these.
-
- nextSequence = new Sequence(this, sections[1].toUpperCase(),sections[3], sections[0]);
- break;
- List<String> topLevelFolders = reader.getGroupMembers("/");
-
- List<String> readFolders = new ArrayList<String>();
-
- for (String folder : topLevelFolders) {
- System.err.println("Looking at "+folder);
-
- if (folder.startsWith("read_")) {
- readFolders.add(folder+"/");
- }
- }
-
- reader.close();
- if (readFolders.size() > 0) {
- // We have read folders so we'll replace the default readPaths with
- // the list we made
-
- if (!foundPath) {
- throw new SequenceFormatException("No valid fastq paths found in "+file);
- readPaths = readFolders.toArray(new String[0]);
- }
-
- }
......@@ -140,9 +155,7 @@ Index: fastqc/uk/ac/babraham/FastQC/Sequence/Fast5File.java
- }
-
- public int getPercentComplete() {
- if (! hasNext()) return 100;
-
- return 0;
- return (readPathsIndexPosition*100) / readPaths.length;
- }
-
- public boolean isColorspace() {
......@@ -150,13 +163,35 @@ Index: fastqc/uk/ac/babraham/FastQC/Sequence/Fast5File.java
- }
-
- public boolean hasNext() {
- return nextSequence != null;
- return readPathsIndexPosition < readPaths.length;
- }
-
- public Sequence next() throws SequenceFormatException {
- Sequence seq = nextSequence;
- nextSequence = null;
- return seq;
-
- for (int r=0;r<rdfPaths.length;r++) {
-
- if (reader.exists(readPaths[readPathsIndexPosition]+rdfPaths[r])) {
-
- String fastq = reader.readString(readPaths[readPathsIndexPosition]+rdfPaths[r]);
-
- String [] sections = fastq.split("\\n");
-
- if (sections.length != 4) {
- throw new SequenceFormatException("Didn't get 4 sections from "+fastq);
- }
-
- Sequence seq = new Sequence(this, sections[1].toUpperCase(),sections[3], sections[0]);
- ++readPathsIndexPosition;
-
- if(readPathsIndexPosition >= readPaths.length) {
- reader.close();
- }
-
- return(seq);
- }
- }
-
- throw new SequenceFormatException("No valid fastq paths found in "+file);
- }
-
- public void remove() {
......
......@@ -24,8 +24,8 @@ Index: fastqc/fastqc
+ $ENV{CLASSPATH} .= "$JavaClasspathExtraDir/commons-math3.jar$delimiter$JavaClasspathExtraDir/htsjdk.jar$delimiter$JavaClasspathExtraDir/jbzip2.jar:$RealBin/fastqc.jar";
}
my @java_args;
@@ -277,10 +276,10 @@ if (@files or $version or $help) {
@@ -301,10 +300,10 @@ if (@files or $version or $help) {
if ($java_bin ne 'java') {
......
......@@ -45,6 +45,29 @@ else {
$ENV{CLASSPATH} = "$RealBin$delimiter$RealBin/sam-1.103.jar$delimiter$RealBin/jbzip2-0.9.jar$delimiter$RealBin/cisd-jhdf5.jar";
}
# We need to find the java interpreter. We'll start from the assumption that this
# is included in the path.
my $java_bin = "java";
# We might have bundled a jre with the installation. If that's the case then we'll
# use the interpreter which is bundled in preference to the system one.
# Windows first
if (-e "$RealBin/jre/bin/java.exe") {
$java_bin = "$RealBin/jre/bin/java.exe";
}
# Linux
elsif (-e "$RealBin/jre/bin/java") {
$java_bin = "$RealBin/jre/bin/java";
}
# OSX
elsif (-e "$RealBin/jre/Contents/Home/bin/java") {
$java_bin = "$RealBin/jre/Contents/Home/bin/java";
}
my @java_args;
my @files;
......@@ -79,7 +102,6 @@ my $nano;
my $nofilter;
my $kmer_size;
my $temp_directory;
my $java_bin = 'java';
my $min_length;
my $result = GetOptions('version' => \$version,
......@@ -234,6 +256,8 @@ if ($format) {
}
if ($java_bin ne 'java') {
warn "Java is $java_bin\n";
# $java_bin =~ s/\\/\//g;
unless (-e $java_bin) {
......
......@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import uk.ac.babraham.FastQC.Modules.BasicStats;
import uk.ac.babraham.FastQC.Modules.QCModule;
import uk.ac.babraham.FastQC.Sequence.Sequence;
import uk.ac.babraham.FastQC.Sequence.SequenceFile;
......@@ -105,6 +106,18 @@ public class AnalysisRunner implements Runnable {
}
}
// We need to account for their potentially being no sequences
// in the file. In this case the BasicStats module never gets
// the file name so we need to explicitly pass it.
if (seqCount == 0) {
for (int m=0; m<modules.length; m++) {
if (modules[m] instanceof BasicStats) {
((BasicStats)modules[m]).setFileName(file.name());
}
}
}
i = listeners.iterator();
while (i.hasNext()) {
i.next().analysisComplete(file,modules);
......
......@@ -120,12 +120,19 @@ public class OfflineRunner implements AnalysisListener {
try {
processFile(fileGroups[i]);
}
catch (OutOfMemoryError e) {
System.err.println("Ran out of memory for "+fileGroups[i][0]);
e.printStackTrace();
System.exit(2);
}
catch (Exception e) {
System.err.println("Failed to process "+fileGroups[i][0]);
e.printStackTrace();
filesRemaining.decrementAndGet();
somethingFailed = true;
}
}
// We need to hold this class open as otherwise the main method
......
......@@ -54,7 +54,7 @@ import uk.ac.babraham.FastQC.Utilities.NanoporeBasename;
public class FastQCApplication extends JFrame {
public static final String VERSION = "0.11.8";
public static final String VERSION = "0.11.9";
private JTabbedPane fileTabs;
private WelcomePanel welcomePanel;
......@@ -318,8 +318,14 @@ public class FastQCApplication extends JFrame {
}
else {
// Recent java themes for linux are just horribly broken with missing
// bits of UI. We're therefore not going to set a native look if
// we're on linux. See seqmonk bug #95 for details.
try {
if (! System.getProperty("os.name").toLowerCase().contains("linux")) {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
} catch (Exception e) {}
......
......@@ -139,7 +139,7 @@ public class LineGraph extends JPanel {
// Now draw the data points
int baseWidth = (getWidth()-(xOffset+10))/data[0].length;
int baseWidth = (getWidth()-(xOffset+10))/Math.max(data[0].length,1); // Math.max is there in case we have no data (no sequences)
if (baseWidth<1) baseWidth=1;
// System.out.println("Base Width is "+baseWidth);
......@@ -184,6 +184,7 @@ public class LineGraph extends JPanel {
for (int d=0;d<data.length;d++) {
g.setColor(COLOURS[d % COLOURS.length]);
if (data[d].length > 0)
lastY = getY(data[d][0]);
for (int i=1;i<data[d].length;i++) {
int thisY = getY(data[d][i]);
......
......@@ -146,10 +146,13 @@ public class AdapterContent extends AbstractQCModule {
// than we've seen before, but also that the last position we could find a hit
// is a positive position.
// If the sequence is longer than it was then we need to expand the storage in
// all of the adapter objects to account for this.
if (sequence.getSequence().length() > longestSequence && sequence.getSequence().length() - longestAdapter > 0) {
longestSequence = sequence.getSequence().length();
for (int a=0;a<adapters.length;a++) {
adapters[a].expandLengthTo(longestSequence-longestAdapter);
adapters[a].expandLengthTo((longestSequence-longestAdapter)+1);
}
}
......@@ -311,9 +314,10 @@ public class AdapterContent extends AbstractQCModule {
public void incrementCount (int position) {
if (position >= positions.length) {
expandLengthTo(position+1);
}
// Don't ever check or expand the storage within this
// function as it ends up double counting previously
// incremented positions. Rely on the upstream code
// having done the expansion correctly already.
++positions[position];
......
......@@ -84,11 +84,15 @@ public class BasicStats extends AbstractQCModule {
return "Basic Statistics";
}
public void processSequence(Sequence sequence) {
public void setFileName (String name) {
this.name = name;
this.name = this.name.replaceFirst("stdin:", "");
}
if (name == null) name = sequence.file().name();
public void processSequence(Sequence sequence) {
name = name.replaceFirst("stdin:", "");
if (name == null) setFileName(sequence.file().name());
// If this is a filtered sequence we simply count it and move on.
if (sequence.isFiltered()) {
......
......@@ -151,6 +151,7 @@ public class DuplicationLevel extends AbstractQCModule {
percentDifferentSeqs = (dedupTotal/rawTotal)*100;
if (rawTotal == 0) percentDifferentSeqs = 100;
}
......
......@@ -322,7 +322,7 @@ public class PerTileQualityScores extends AbstractQCModule {
public void makeReport(HTMLReportArchive report) throws IOException,XMLStreamException {
if (!calculated) getPercentages();
writeDefaultImage(report, "per_tile_quality.png", "Per base quality graph", Math.max(800, xLabels.length*15), 600);
writeDefaultImage(report, "per_tile_quality.png", "Per tile quality graph", Math.max(800, xLabels.length*15), 600);
StringBuffer sb = report.dataDocument();
sb.append("#Tile\tBase\tMean\n");
......
......@@ -70,6 +70,11 @@ public class SequenceLengthDistribution extends AbstractQCModule {
}
}
// We can get a -1 value for min if there aren't any valid sequences
// at all.
if (minLen < 0) minLen = 0;
// We put one extra category either side of the actual size
if (minLen>0) minLen--;
maxLen++;
......@@ -194,10 +199,13 @@ public class SequenceLengthDistribution extends AbstractQCModule {
return false;
}
// We might not have any sequences so only check if we do
if (lengthCounts.length > 0) {
// Empty sequences get us an error
if (lengthCounts[0] > 0) {
return true;
}
}
return false;
}
......
......@@ -124,7 +124,7 @@ public class ResultsPanel extends JPanel implements ListSelectionListener, Analy
panels = new JPanel[modules.length];
for (int m=0;m<modules.length;m++) {
System.err.println("Getting panel for "+modules[m].name()+" with "+modules[m].description());
// System.err.println("Getting panel for "+modules[m].name()+" with "+modules[m].description());
panels[m] = modules[m].getResultsPanel();
}
......
......@@ -21,6 +21,8 @@ package uk.ac.babraham.FastQC.Sequence;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import ch.systemsx.cisd.hdf5.HDF5Factory;
import ch.systemsx.cisd.hdf5.IHDF5SimpleReader;
......@@ -29,45 +31,58 @@ public class Fast5File implements SequenceFile {
private Sequence nextSequence = null;
private File file;
private String name;
private IHDF5SimpleReader reader;
private String [] readPaths = new String[] {""};
protected Fast5File(File file) throws SequenceFormatException, IOException {
this.file = file;
name = file.getName();
IHDF5SimpleReader reader = HDF5Factory.openForReading(file);
private int readPathsIndexPosition = 0;
String [] rdfPaths = new String [] {
private String [] rdfPaths = new String [] {
"Analyses/Basecall_2D_000/BaseCalled_template/Fastq",
"Analyses/Basecall_2D_000/BaseCalled_2D/Fastq",
"Analyses/Basecall_1D_000/BaseCalled_template/Fastq",
"Analyses/Basecall_1D_000/BaseCalled_1D/Fastq"
};
boolean foundPath = false;
for (int r=0;r<rdfPaths.length;r++) {
if (reader.exists(rdfPaths[r])) {
foundPath = true;
String fastq = reader.readString(rdfPaths[r]);
protected Fast5File(File file) throws SequenceFormatException, IOException {
this.file = file;
name = file.getName();
String [] sections = fastq.split("\\n");
reader = HDF5Factory.openForReading(file);
if (sections.length != 4) {
throw new SequenceFormatException("Didn't get 4 sections from "+fastq);
}
// These files have changed structure over time. Originally they contained
// a single read per file where the base of the heirarchy was the read
// itself.
//
// Later the files moved to having multiple reads per file. Now there is
// an additional top level folder per read with the sub-structure being the
// same as it used to be for the individual reads.
//
// We need to account for both of these structures.
// See if we can see a bunch of paths starting with "read_" at the top of the
// heirarchy. If we can then we substitute the read paths for these.
nextSequence = new Sequence(this, sections[1].toUpperCase(),sections[3], sections[0]);
break;
List<String> topLevelFolders = reader.getGroupMembers("/");
List<String> readFolders = new ArrayList<String>();
for (String folder : topLevelFolders) {
System.err.println("Looking at "+folder);
if (folder.startsWith("read_")) {
readFolders.add(folder+"/");
}
}
reader.close();
if (readFolders.size() > 0) {
// We have read folders so we'll replace the default readPaths with
// the list we made
if (!foundPath) {
throw new SequenceFormatException("No valid fastq paths found in "+file);
readPaths = readFolders.toArray(new String[0]);
}
}
......@@ -77,9 +92,7 @@ public class Fast5File implements SequenceFile {
}
public int getPercentComplete() {
if (! hasNext()) return 100;
return 0;
return (readPathsIndexPosition*100) / readPaths.length;
}
public boolean isColorspace() {
......@@ -87,13 +100,35 @@ public class Fast5File implements SequenceFile {
}
public boolean hasNext() {
return nextSequence != null;
return readPathsIndexPosition < readPaths.length;
}
public Sequence next() throws SequenceFormatException {
Sequence seq = nextSequence;
nextSequence = null;
return seq;
for (int r=0;r<rdfPaths.length;r++) {
if (reader.exists(readPaths[readPathsIndexPosition]+rdfPaths[r])) {
String fastq = reader.readString(readPaths[readPathsIndexPosition]+rdfPaths[r]);
String [] sections = fastq.split("\\n");
if (sections.length != 4) {
throw new SequenceFormatException("Didn't get 4 sections from "+fastq);
}
Sequence seq = new Sequence(this, sections[1].toUpperCase(),sections[3], sections[0]);
++readPathsIndexPosition;
if(readPathsIndexPosition >= readPaths.length) {
reader.close();
}
return(seq);
}
}
throw new SequenceFormatException("No valid fastq paths found in "+file);
}
public void remove() {
......