HAEMOPHILUS Example of sequence statistics and gene finding with MATLAB
This demonstration looks at some statistics about the DNA content of the Haemophilus Influenzae. It shows also some algorithms for finding ORFs and for assessing their significance.
Contents
Introduction
Haemophilus influenzae is a non-motile Gram-negative coccobacillus first described in 1892 by Dr. Robert Pfeiffer during an influenza pandemic. It is generally aerobic, but can grow as a facultative anaerobe. It is responsible for a wide range of clinical diseases. The Haemophilus influenzae genome was the first to be sequenced and assembled in a free-living organism. It contains about 1.8 million base pairs and is estimated to have 1,740 genes.
Accessing NCBI data from the MATLAB workspace
The dna sequence can be obtained from the GenBank database with the accession number NC_000907. Using the getgenbank function with the ‘SequenceOnly’ flag just the nucleotide sequence is loaded into the MATLAB workspace.
Hflu = getgenbank('NC_000907','SequenceOnly',true);
If you don’t have a live web connection, you can load the data from a MAT-file using the command
% load Hflu % <== Uncomment this if no internet connection
The MATLAB whos command gives information about the size of the sequence.
whos Hflu
Name Size Bytes Class Hflu 1x1830138 3660276 char array Grand total is 1830138 elements using 3660276 bytes
The total length of the Haemophilus Influenzae genome is 1830138 bp.
Statistical sequence analysis
You will examine some statistics properties of the sequence. You can look at the composition of the nucleotides with the basecount function.
bases=basecount(Hflu)
Warning: Ambiguous symbols 'NKRNNRNSSNYKMMRSYNNNNYKNNNNSYWNMMMNKWNWYNNNSMRNNWNNWMKKNMYKNNKNYWRNKKSWNNNSSNNNNWYWSNNNYKNNRNRSSRMKRKMSKMNNWNWNYRYN' appear in the sequence. These will be in Others. bases = A: 567623 C: 350723 G: 347436 T: 564241 Others: 115
The four nucleotides are not used at equal frequency across the genome: A and T are much common than G and C.
Others symbols occur in the sequence. They correspond to positions in the sequence that are are not clearly one base or another and they are due, for example, to sequencing uncertainties. In this case for example: N: aNy base –
K: G or T –
R: A or G (puRine) –
Y: C or T (pYrimidine) –
M: A or C (aMino) –
S: C or G –
W: A or T.
Instead of grouping other simbols together, you can count them individually.
bases=basecount(Hflu,'Others','Full')
bases = A: 567623 C: 350723 G: 347436 T: 564241 R: 10 Y: 11 K: 14 M: 11 S: 12 W: 11 B: 0 D: 0 H: 0 V: 0 N: 46 Gap: 0
You can also calculate the frequency of each nucleotide.
[bases frequency]=basecountfrequency(Hflu,'Others','Full')
bases = A: 567623 C: 350723 G: 347436 T: 564241 R: 10 Y: 11 K: 14 M: 11 S: 12 W: 11 B: 0 D: 0 H: 0 V: 0 N: 46 Gap: 0 frequency = A: 0.3102 C: 0.1916 G: 0.1898 T: 0.3083 R: 5.4641e-06 Y: 6.0105e-06 K: 7.6497e-06 M: 6.0105e-06 S: 6.5569e-06 W: 6.0105e-06 B: 0 D: 0 H: 0 V: 0 N: 2.5135e-05 Gap: 0
It should be pointed out that these are on the 5′-3′ strand of DNA, but we know exactly the frequency of all the the bases on the other strand because of the complementarity of the double helix. Anyway we could verify it using again the basecountfrequency function.
[bases frequency]=basecountfrequency(seqrcomplement(Hflu),'Others','Full')
bases = A: 564241 C: 347436 G: 350723 T: 567623 R: 11 Y: 10 K: 11 M: 14 S: 12 W: 11 B: 0 D: 0 H: 0 V: 0 N: 46 Gap: 0 frequency = A: 0.3083 C: 0.1898 G: 0.1916 T: 0.3102 R: 6.0105e-06 Y: 5.4641e-06 K: 6.0105e-06 M: 7.6497e-06 S: 6.5569e-06 W: 6.0105e-06 B: 0 D: 0 H: 0 V: 0 N: 2.5135e-05 Gap: 0
CG content
The local fluctuations in the frequencies of nucleotides provide different interesting information. The local base composition by a sliding window of variable size can be measured. In the following the window size is assumed 90000 bp and 20000 bp respectively.
ntdensity1(Hflu,'window',90000)
ntdensity1(Hflu,'window',20000)
The phenomenon called horizontal gene transfer can be observed in the second plot: the H. influenzae genome contains a 30Kb region of unusual GC content from 1.56Mb to 1.59Mb.
k-mer frequency and motif bias
Now look at the dimers in the sequence and display the 2-mer frequencies in the table matrix. The simbols others than A, C, G, T are not considered.
[dimers,matrix] = dimercount(Hflu)
Warning: Ambiguous symbols 'NKRNNRNSSNYKMMRSYNNNNYKNNNNSYWNMMMNKWNWYNNNSMRNNWNNWMKKNMYKNNKNYWRNKKSWNNNSSNNNNWYWSNNNYKNNRNRSSRMKRKMSKMNNWNWNYRYN' appear in the sequence. These will be in Others. dimers = AA: 219880 AC: 92410 AG: 88457 AT: 166837 CA: 121618 CC: 68014 CG: 72523 CT: 88551 GA: 94125 GC: 95529 GG: 66448 GT: 91314 TA: 131955 TC: 94745 TG: 119996 TT: 217512 Others: 223 matrix = 0.1202 0.0505 0.0483 0.0912 0.0665 0.0372 0.0396 0.0484 0.0514 0.0522 0.0363 0.0499 0.0721 0.0518 0.0656 0.1189
You can also plot the frequency of certain di-nucleotides of interest: for example considering the local fluctuations in the frequencies of dimers AT and CG.
density = dndensity(Hflu)
As a further analysis you can also compare the observed frequency of each dimer with the one expected under the multinomial model. This is called genome signature.
gs=gensign(Hflu)
Warning: Ambiguous symbols 'NKRNNRNSSNYKMMRSYNNNNYKNNNNSYWNMMMNKWNWYNNNSMRNNWNNWMKKNMYKNNKNYWRNKKSWNNNSSNNNNWYWSNNNYKNNRNRSSRMKRKMSKMNNWNWNYRYN' appear in the sequence. These will be in Others. Warning: Ambiguous symbols 'NKRNNRNSSNYKMMRSYNNNNYKNNNNSYWNMMMNKWNWYNNNSMRNNWNNWMKKNMYKNNKNYWRNKKSWNNNSSNNNNWYWSNNNYKNNRNRSSRMKRKMSKMNNWNWNYRYN' appear in the sequence. These will be in Others. gs = 1.2491 0.8496 0.8210 0.9535 1.1182 1.0121 1.0894 0.8190 0.8736 1.4349 1.0076 0.8526 0.7541 0.8763 1.1204 1.2505
You can look at codons using codoncount. That function counts the codons on a particular reading frame. With no options, the function shows the codon counts on the first reading frame.
codoncount(Hflu)
Warning: Ambiguous symbols 'NKRNNRNSSNYKMMRSYNNNNYKNNNNSYWNMMMNKWNWYNNNSMRNNWNNWMKKNMYKNNKNYWRNKKSWNNNSSNNNNWYWSNNNYKNNRNRSSRMKRKMSKMNNWNWNYRYN' appear in the sequence. These will be in Others. AAA - 27760 AAC - 11523 AAG - 11701 AAT - 22178 ACA - 9121 ACC - 7249 ACG - 6917 ACT - 7801 AGA - 8763 AGC - 8142 AGG - 5340 AGT - 7569 ATA - 12768 ATC - 11041 ATG - 10029 ATT - 22007 CAA - 15527 CAC - 7692 CAG - 6634 CAT - 10049 CCA - 9185 CCC - 3866 CCG - 4213 CCT - 5502 CGA - 6311 CGC - 6771 CGG - 4112 CGT - 7255 CTA - 6110 CTC - 4112 CTG - 6625 CTT - 11985 GAA - 12946 GAC - 3624 GAG - 4202 GAT - 10719 GCA - 10832 GCC - 6310 GCG - 6537 GCT - 8153 GGA - 5296 GGC - 6218 GGG - 3590 GGT - 7147 GTA - 7714 GTC - 3651 GTG - 7741 GTT - 11118 TAA - 16924 TAC - 7723 TAG - 6372 TAT - 12561 TCA - 11592 TCC - 5542 TCG - 6240 TCT - 8663 TGA - 11513 TGC - 10991 TGG - 9045 TGT - 9079 TTA - 17139 TTC - 12550 TTG - 15162 TTT - 27184 Others - 110
Exploring the Open Reading Frames (ORFs)
In a nucleotide sequence an obvious thing to look for is if there are any open reading frames. The function seqorfs can be used to determine the ORFs in a sequence.
orf=seqorfs(Hflu);
The variable orf is a structure with information about the start/stop positions of each ORFs, its length and which reading frame it is in. Here the minimun number of codons for an ORF to be considered valid is 10 (default value).
The minimun number of codons for an ORF to be considered valid can be also set. Here a threshold of 70 and 80 amino acids are considered leading to about 2175 and 1966 ORFs respectively.
[orf n_70]=seqorfs(Hflu,'MINIMUMLENGTH',70);
n_70
n_70 = 2175
[orf n_80]=seqorfs(Hflu,'MINIMUMLENGTH',80);
n_80
n_80 = 1966
You can also look for the total number of ORFs
[orf n]=seqorfs(Hflu,'MINIMUMLENGTH',1);
n
n = 37500
Detecting significant ORFs
The classic approach to decide whether an ORF is a good candidate as a gene is to calculate the probability of seeing an ORF of a certain length L in a random sequence. To test the significance of ORFs a single-nucleotide permutation test can be used.
[orf1 n1]=seqorfs(Hflu(randperm(length(Hflu))),'MINIMUMLENGTH',1);
n1
n1 = 52174
The ORF Length of the original and of the randomized sequences can be compared.
ORFLength=[]; for i=1:6 ORFLength=[ORFLength; orf(i).Length']; end ORFLength1=[]; for i=1:6 ORFLength1=[ORFLength1; orf1(i).Length']; end
A threshold must be chosen in order to keep as candidate genes those ORFs in the H. Influenzae genome that are longer than most (or all) the ORFs in the random sequence.
max_threshold=max(ORFLength1) n_max=length(find(ORFLength>=max_threshold))
max_threshold = 573 n_max = 1182
You can also use a more tolerant threshold in order to keep all ORFs of length equal to or greater than the top 1% of random ORFs.
empirical_threshold=prctile(ORFLength1,99) n_emp=length(find(ORFLength>=empirical_threshold))
empirical_threshold = 207 n_emp = 2209