## Primer constraints

The physicochemical properties of the primers is facilitated by `check_cvg_constraints()`. Since we've already analyzed the primer coverage, we will compute all remaining constraints now by passing the corresponding `active.constraints` character vector to `check_cvg_constraints()`:

```{r my_constraint_setup}
xml.file <- system.file("extdata", "settings", "B_Taq_PCR_evaluate.xml",
              package = "openPrimeR")
settings <- read_settings(xml.file)
constraints(settings) <- constraints(settings)[names(constraints(settings)) != "gc_clamp"]
constraints(settings)$primer_coverage <- c("min" = 5)
conOptions(settings)$allowed_mismatches <- 7
conOptions(settings)$allowed_other_binding_ratio <- 0
conOptions(settings)$allowed_region_definition <- "any"

fasta.file <- system.file("extdata", "IMGT_data", "templates", 
        "Homo_sapiens_IGH_functional_exon.fasta", package = "openPrimeR")
hdr.structure <- c("ACCESSION", "GROUP", "SPECIES", "FUNCTION")
delim <- "|"
template.df <- read_templates(fasta.file, hdr.structure = hdr.structure, 
                                delim = "|")
leader.fasta <- system.file("extdata", "IMGT_data", "templates", 
        "Homo_sapiens_IGH_functional_leader.fasta", package = "openPrimeR")
template.df <- assign_binding_regions(template.df, fw = leader.fasta, rev = NULL)
template.df <- openPrimeR:::adjust_binding_regions(template.df, 
        c(-max(template.df$Allowed_End_fw), 0), NULL)

fasta.file <- system.file("extdata", "IMGT_data", "primers", 
        "IGHV", "Tiller2008_1st.fasta", package = "openPrimeR")
primer.df <- read_primers(fasta.file)
constraint.df <- check_constraints(primer.df, template.df, settings, active.constraints = "primer_coverage")
```

```{r check_constraints, exercise = TRUE, exercise.setup = "my_constraint_setup"}
# Check all constraints except for 'primer_coverage'
```

```{r check_constraints-solution}
constraint.df <- check_constraints(constraint.df, template.df, settings,
                 active.constraints = setdiff(names(constraints(settings)), "primer_coverage"))
asS3(constraint.df)

```

You can access the values of the computed properties in `constraint.df`. Fields containing the keyword `EVAL` indicate whether a primer passed or failed the constraints defined in `settings`. Let's try to access the computed melting temperatures and verify that the temperatures are in the desired range:

```{r constraint_setup}
xml.file <- system.file("extdata", "settings", "B_Taq_PCR_evaluate.xml",
              package = "openPrimeR")
settings <- read_settings(xml.file)
constraints(settings) <- constraints(settings)[names(constraints(settings)) != "gc_clamp"]
constraints(settings)$primer_coverage <- c("min" = 5)
conOptions(settings)$allowed_mismatches <- 7
conOptions(settings)$allowed_other_binding_ratio <- 0
conOptions(settings)$allowed_region_definition <- "any"

fasta.file <- system.file("extdata", "IMGT_data", "templates", 
        "Homo_sapiens_IGH_functional_exon.fasta", package = "openPrimeR")
hdr.structure <- c("ACCESSION", "GROUP", "SPECIES", "FUNCTION")
delim <- "|"
template.df <- read_templates(fasta.file, hdr.structure = hdr.structure, 
                                delim = "|")
leader.fasta <- system.file("extdata", "IMGT_data", "templates", 
        "Homo_sapiens_IGH_functional_leader.fasta", package = "openPrimeR")
template.df <- assign_binding_regions(template.df, fw = leader.fasta, rev = NULL)
template.df <- openPrimeR:::adjust_binding_regions(template.df, 
        c(-max(template.df$Allowed_End_fw), 0), NULL)

fasta.file <- system.file("extdata", "IMGT_data", "primers", 
        "IGHV", "Tiller2008_1st.fasta", package = "openPrimeR")
primer.df <- read_primers(fasta.file)
constraint.df <- check_constraints(primer.df, template.df, settings)
```

```{r constraint_manual, exercise = TRUE, exercise.setup = "constraint_setup"}
# Verify whether the melting temperatures are in the desired range
```

```{r constraint_manual-solution}
tm <- constraint.df$melting_temp
print(paste0("Melting temperatures: ", paste0(tm, collapse = ",")))
print(constraints(settings)$melting_temp_range)
idx <- which(constraint.df$EVAL_melting_temp_range)
print(tm[idx])
print(constraint.df[idx, "melting_temp"] <= constraints(settings)$melting_temp_range["max"] & 
      constraint.df[idx, "melting_temp"] >= constraints(settings)$melting_temp_range["min"])
```

Since analyzing the properties in this way is cumbersome, we'll create a visualization showing which primers fulfill the constraints using `plot_constraint_fulfillment()`:

```{r constraint_setup2}
xml.file <- system.file("extdata", "settings", "B_Taq_PCR_evaluate.xml",
              package = "openPrimeR")
settings <- read_settings(xml.file)
constraints(settings) <- constraints(settings)[names(constraints(settings)) != "gc_clamp"]
constraints(settings)$primer_coverage <- c("min" = 5)
conOptions(settings)$allowed_mismatches <- 7
conOptions(settings)$allowed_other_binding_ratio <- 0
conOptions(settings)$allowed_region_definition <- "any"

fasta.file <- system.file("extdata", "IMGT_data", "templates", 
        "Homo_sapiens_IGH_functional_exon.fasta", package = "openPrimeR")
hdr.structure <- c("ACCESSION", "GROUP", "SPECIES", "FUNCTION")
delim <- "|"
template.df <- read_templates(fasta.file, hdr.structure = hdr.structure, 
                                delim = "|")
leader.fasta <- system.file("extdata", "IMGT_data", "templates", 
        "Homo_sapiens_IGH_functional_leader.fasta", package = "openPrimeR")
template.df <- assign_binding_regions(template.df, fw = leader.fasta, rev = NULL)
template.df <- openPrimeR:::adjust_binding_regions(template.df, 
        c(-max(template.df$Allowed_End_fw), 0), NULL)

fasta.file <- system.file("extdata", "IMGT_data", "primers", 
        "IGHV", "Tiller2008_1st.fasta", package = "openPrimeR")
primer.df <- read_primers(fasta.file)
constraint.df <- check_constraints(primer.df, template.df, settings)
```


```{r constraint_plot, exercise = TRUE, exercise.setup = "constraint_setup"}
# Plot the constraint fulfillment
```


```{r constraint_plot-solution} 
plot_constraint_fulfillment(constraint.df, settings)
```

The plot quickly reveals that the main flaw of the primer set is associated with a high spread of primer melting temperatures. To quantify the deviations of the primer properties from the target constraints , we can use `plot_constraint_deviation`:


```{r constraint_deviation, exercise = TRUE, exercise.setup = "constraint_setup2"}
# Plot the constraint deviation
```

```{r constraint_deviation-solution}
plot_constraint_deviation(constraint.df, settings)
```

The plot shows that the constraint on the melting temperature deviations was violated most strongly, while some other constraints were violated only marginally. From these results we can conclude that, overall, the properties of the primers are reasonable. However, the high deviations in melting temperatures may require a relative low PCR annealing temperature and therefore lead to unspecific binding of the primers exhibiting high melting temperatures. 

Note that we haven't determined whether the GC clamp criterion is fulfilled since we've removed it at the beginning of the tutorial. Let's determine the values for the GC clamp and redraw the plots for the constraints:

```{r constraint_gc_clamp, exercise = TRUE, exercise.setup = "constraint_setup2"}
# Require 1 to 3 terminal GCs. Then determine the 'gc_clamp' property and plot the constraint fulfillment and deviation once again.
```

```{r constraint_gc_clamp-solution}
# require 1 to 3 terminal GCs
constraints(settings)$gc_clamp <- c("min" = 1, "max" = 3)
# update the evaluated primers
constraint.df <- check_constraints(constraint.df, template.df, settings, active.constraints = "gc_clamp")
# visualize the constraints
plot_constraint_fulfillment(constraint.df, settings)
plot_constraint_deviation(constraint.df, settings)
```

Great! Finally, we've really evaluated all constraints and there were no bad surprises when including the GC clamp condition. 

Having finished our analysis of the constraints, we may want to store the results in some way. For this purpose, there are two options: storing evaluated data as a CSV file or creating a PDF report. Storing the results as a CSV file can be time-saving if you want to re-analyze the same data at a later point in time, while the PDF report can be used for filing the results. You can store primers as a CSV with `write_primers()` and create a report with `create_report()`.
