# Tutorial for the R MMD package

The MMD package was developed in [1]. This tutorial illustrates the functioning of the MMD package using Campylobacter isolates from human and five animal sources (Cattle, Chicken, Pig, Sheep, and WB). For illustration purposes, the example uses genotypes of reduced size consisting 10 isolates per host reservoir described with genotypes of 10 SNPs. The data used in this tutorial comes with the MMD package. Other datasets studied in Ref. [1] are available from this link . To use these examples, simply download the data from the link.

### Setting the parameters for source attribution

Set the file names of the file csv containing genotype data and file pop containing population names used in this example:

datafile <- system.file("extdata", "Campylobacter_10SNP_HlW.csv", package = "MMD")
popfile <- system.file("extdata", "Campylobacter_10SNP_HlW.pop", package = "MMD")

Note that the full path to the files should be specified. For example:

datafile
## [1] "C:/Users/s05fp2/AppData/Local/Temp/Rtmp0w5QXw/Rinstf2c33403434/MMD/extdata/Campylobacter_10SNP_HlW.csv"
popfile
## [1] "C:/Users/s05fp2/AppData/Local/Temp/Rtmp0w5QXw/Rinstf2c33403434/MMD/extdata/Campylobacter_10SNP_HlW.pop"

This example searches for the data from the MMD package which is found using system.file. In general, however, in this step you should specify the path to the directory where you have stored the data you want to analyse.

Set the name of the population to be attributed. In this case, we want to attribute Campylobacter isolates from “Human”:

ToAttribute <- "Human"

Introduce the population names of the genotypes to be used as sources (these are available from the file *.pop):

sourcenames <- c("Cattle","Chicken","Pig","Sheep","WB")

Set the maximum number of loci to be used in the analysis:

NL <- 100

NL was set to 100 loci as an example but the program will use 10 loci since the genotypes in the file Campylobacter_10SNP_HlW.csv consist of 10 SNPs.

### Running the function MMD_attr for source attribution (verbose=FALSE by default even if verbose is not specified; set verbose=TRUE to see a progress bar for computations if you wish):

attribution <- MMD_attr(datafile,popfile,NL,sourcenames,ToAttribute,verbose=FALSE)

In this example, the source attribution results were stored in attribution:

attribution

The list contains 7 items:

• Number of individuals of unknown origin (Campylobacter isolates from humans):
[[1]]
[1] 500

• Number of sources:
[[2]]
[1] 5

• Statistics of the attribution probability to sources, ps:
[[3]]
Sources mean standard.deviation X2.5.percentile X97.5.percentile
1 Cattle 0.28475914 0.003788603 0.27715866 0.29197614
2 Chicken 0.32152237 0.004583734 0.31249737 0.33048377
3 Pig 0.05004946 0.007727446 0.03526279 0.06562583
4 Sheep 0.24744750 0.001905219 0.24357132 0.25093940
5 WB 0.09623947 0.006093308 0.08474618 0.10863976

• Runtime of the calculation:
[[4]]
Time difference of 1.759793 mins

• Probability pu,s that each individual of unknown origin is attributed to sources:
[[5]]
individual Cattle Chicken Pig Sheep WB
1 301 0.317562288 0.36062158 0.0000000 0.2610470 0.06076916
2 302 0.317562288 0.36062158 0.0000000 0.2610470 0.06076916
3 303 0.317562288 0.36062158 0.0000000 0.2610470 0.06076916
4 304 0.317562288 0.36062158 0.0000000 0.2610470 0.06076916
5 305 0.192435285 0.01012817 0.3155315 0.2532043 0.22870068
6 306 0.317562288 0.36062158 0.0000000 0.2610470 0.06076916
7 307 0.317562288 0.36062158 0.0000000 0.2610470 0.06076916
…..

• Number of loci:
[[6]]
[1] 10

• Parameter q used to calculate the q-quantile of the Hamming distance in the MMD method. Since a value was not specified for the MMD_attr function, the default value was used:
[[7]]
[1] 0.01

For example, a bar chart for the mean of the probability of attribution of Campylobacter human isolates to food sources can be easily obtained from attribution as follows:

barplot(height = attribution[[3]]$mean,names.arg = attribution[[3]]$Sources,las=2,cex.names = 0.8,main=NULL, ylab = expression("Attribution probability, p"[s]))

This example illustrates self-attribution of Campylobacter isolates from the pig reservoir of the dataset used above. The genotypes from pig are split into training and test datasets. The test dataset is defined by randomly drawing 50% of the isolates from pig reservoir; the remaining isolates define the training dataset.

### Setting the parameters

To run self-attribution, the function MMD_attr can be executed as follows:

SelfAttribution <- MMD_attr(datafile,popfile,NL,sourcenames,ToAttribute = "Pig",SelfA = "yes",optq = "yes", pqmin = 0, pqmax = 0.5, np=1000, fSelfA = 0.5)

Here,
* ToAttribute is set to the “Pig” reservoir which will be analysed for self-attribution.
* SelfA is set to “yes” to do self-attribution (SelfA is set to “no” by default in the function MMD_attr, i.e. it is set by default to do source attribution instead of self-attribution).
* fSelfA is the fraction of genotypes in the “Pig” reservoir used to define the test dataset. Here, this is set to 0.5 which, in fact, is the default value.
* optq is set to “yes” to optimise the q-quantile for self-attribution accuracy (optq is set to “no” by default in the function MMD_attr).
* Optimisation of the q-quantile is done by considering a partition of np values in the interval [pqmin,pqmax] of the q-quantile. * The value of verbose was not explicitly indicated and the function will use the default value, verbose=FALSE, so that a progress bar will not be displayed.

The results are stored in the list SelfAttribution:

SelfAttribution

The list contains 8 items:

• Number of individuals of unknown origin (pig Campylobacter isolates from the test dataset):
[[1]]
[1] 65

• Number of sources:
[[2]]
[1] 5

• Statistics of the attribution probability to sources, ps:
[[3]]
Sources mean standard.deviation X2.5.percentile X97.5.percentile
1 Cattle 0.03104321 0.0042615251 0.02321769 0.03993305
2 Chicken 0.04086488 0.0008201976 0.03933067 0.04237244
3 Pig 0.70524955 0.0105881858 0.68546798 0.72476244
4 Sheep 0.16327327 0.0023348811 0.15896031 0.16814020
5 WB 0.05963771 0.0049012502 0.05068933 0.06987849

• Probability pu,s that each individual of unknown origin is attributed to sources:
[[4]]
individual Cattle Chicken Pig Sheep WB
1 805 0.006715212 0.04700648 0.7593355 0.1544499 0.03249296
2 806 0.006715212 0.04700648 0.7593355 0.1544499 0.03249296
3 807 0.006715212 0.04700648 0.7593355 0.1544499 0.03249296
4 808 0.006715212 0.04700648 0.7593355 0.1544499 0.03249296
5 810 0.006715212 0.04700648 0.7593355 0.1544499 0.03249296
6 812 0.006715212 0.04700648 0.7593355 0.1544499 0.03249296
7 813 0.078421452 0.03136858 0.5881609 0.1882115 0.11383759
…..

• Runtime of the calculation:
[[5]]
Time difference of 1.941194 mins

• Number of loci:
[[6]]
[1] 10

• Value of the q-quantile of the Hamming distance for which the self-attribution accuracy is maximised. Accuracy is the fraction of genotypes in the test dataset that are correctly attributed to the chosen reservoir (pig in this example):
[[7]]
[1] 0.219

• Self-attribution accuracy as a function of the q-quantile parameter:
[[8]]
1 0.0000 0.6337530
2 0.0005 0.6337530
…..

In this case, the bar chart for the probability that isolates of unknown origin are attributed to each of the sources can be obtained as follows:

barplot(height = SelfAttribution[[3]]$mean,names.arg = SelfAttribution[[3]]$Sources,las=2,cex.names = 0.8,main=NULL, ylab = expression("Attribution probability, p"[s]))

Despite the small number of SNPs used in the example dataset, it is interesting that the program predicts a relatively high probability of attribution to the correct source of pig Campylobacter isolates.

## Selection of informative loci

The package allows informative loci to be selected in terms of entropy and redundancy measures.

### Entropy measures

MMD_Entropy provides entropy measures for individual loci. It can be called as follows:

EntropyLoci <- MMD_Entropy(datafile,popfile,NL,sourcenames)

Again, here you can specify verbose=TRUE to see a progress bar for computations if you wish.

#### Outputs of MMD_Entropy

The results give a list of 7 items:

EntropyLoci
• Number of loci used for the calculation:
[[1]]
[1] 10

• Number of individuals in sources:
[[2]]
[1] 673

• Proportional weight of each population, qs:
[[3]]
Sources qs
[1,] “Cattle” “0.222882615156018”
[2,] “Chicken” “0.222882615156018”
[3,] “Pig” “0.193164933135215”
[4,] “Sheep” “0.222882615156018”
[5,] “WB” “0.138187221396731”

• Number of alleles in the dataset:
[[4]]
[1] 4

• Value of the alleles in the dataset:
[[5]]
[1] 1 2 3 4

• Data frame with three columns for entropies: Total (HlT), within-sources (HlW) and between-sources (HlB):
[[6]]
HlT HlW HlB
1 0.01610117 0.01184854 0.004252624
2 1.24988869 0.63488510 0.615003590
3 0.91779974 0.49274008 0.425059661
4 0.91779974 0.49274008 0.425059661
….

• Runtime:
[[7]]
Time difference of 0.06805801 secs

Using the list EntropyLoci one can easily plot histograms for the different entropies,

histHlT <- hist(EntropyLoci[[6]]$HlT,col="#1C86EE",main=NULL,xlab=expression(paste("H"^"T")),ylab="Frequency") histHlB <- hist(EntropyLoci[[6]]$HlB,col="#1C86EE",main=NULL,xlab=expression(paste("H"^"B")),ylab="Frequency")

histHlW <- hist(EntropyLoci[[6]]$HlW,col="#1C86EE",main=NULL,xlab=expression(paste("H"^"W")),ylab="Frequency") or a scatterplot of the entropy between sources vs. entropy within sources for each locus: plot(cbind(EntropyLoci[[6]]$HlW,EntropyLoci[[6]]\$HlB),col="#1C86EE",main=NULL, xlab=expression(paste("H"^"W")),ylab=expression(paste("H"^"B")))

### Redundancy of loci

In a sequential selection of loci, the redundancy of the n-th locus can be calculated using the funtion MMD_Rn as follows:

RedundancyLoci <- MMD_Rn(datafile,popfile,NL,sourcenames)

#### Outputs of MMD_Rn

The results give a list of 9 items:

RedundancyLoci
• Number of loci used for the calculation:
[[1]]
[1] 10

• Number of individuals in sources:
[[2]]
[1] 673

• Proportional weight of each population, qs:
[[3]]
Sources qs
[1,] “Cattle” “0.222882615156018”
[2,] “Chicken” “0.222882615156018”
[3,] “Pig” “0.193164933135215”
[4,] “Sheep” “0.222882615156018”
[5,] “WB” “0.138187221396731”

• Number of alleles in the dataset:
[[4]]
[1] 4

• Value of the alleles in the dataset:
[[5]]
[1] 1 2 3 4

• Data frame with redundancy Rn of each locus:
[[6]]
locus Rn_original
1 2 0.001799635
2 3 0.889203483
3 4 1.000000000
….

• Index of loci with increasing Rn:
[[7]]
[1] 1 5 9 8 6 3 2 4 7

• Data frame with redundancy Rn of loci after sorting in increasing order:
[[8]]
locus Rn_sorted
1 2 0.001793803
2 3 0.002553717
3 4 0.160958703
4 5 0.271356486
….

• Runtime:
[[9]]
Time difference of 0.13464 secs

For example, one can plot the redundancy Rn of loci as a function of n and the redundacy of loci sorted in increasing order:

plot(RedundancyLoci[[6]],col="#EE4000",main=NULL,log="x",type="l",xlab="n-th selected locus",ylab=expression("R"[n]))

plot(RedundancyLoci[[8]],col="#EE4000",main=NULL,log="x",type="l",xlab="n-th selected locus",ylab=expression("R"[n]))

## References

[1] Perez-Reche, F.J., Rotariu, O., Lopes, B.S., Forbes, K.J., Strachan, N.J.C. Mining whole genome sequence data to efficiently attribute individuals to source populations, Scientific Reports 10, 12124 (2020). https://www.nature.com/articles/s41598-020-68740-6