# Quick Start

`tidysq` package is meant to store and conduct operations on biological sequences. This vignette provides a guide to basic usage of `tidysq`, i.e. reading, manipulating and writing sequences to file.

The most recent version of `tidysq` can be installed with `install_github()` function from `devtools`.

    # devtools::install_github("BioGenies/tidysq")
    library(tidysq)

## Sequence creation

Biological sequences can be and often are represented as strings – sequences of letters. For example, a DNA sequence can take the form of `"TAGGCCCTAGACCTG"`, where `A` means adenine, `C` – cytosine, `G` – guanine and `T` – thymine. Exact IUPAC recommendations for one-letter codes can be found in Cornish-Bowden A. Nomenclature for incompletely specified bases in nucleic acid sequences: recommendations 1984. Nucleic Acids Res. 1985 May 10;13(9):3021-30. doi: 10.1093/nar/13.9.3021. PMID: 2582368; PMCID: PMC341218.

Within `tidysq` package sequence data is stored in `sq` objects, that is, vectors of biological sequences. They can be created from string vectors as above:

    sq_dna <- sq(c("TAGGCCCTAGACCTG", "TAGGCCCTGGGCATG"))
    sq_dna
    #> basic DNA sequences list:
    #> [1] TAGGCCCTAGACCTG                                                         <15>
    #> [2] TAGGCCCTGGGCATG                                                         <15>

There are several thing to note. First, each sequence is an element of `sq` object. Many operations are vectorized — they are applied to all sequences of a vector — and `sq` objects are no different in this regard. Second, the first line of output says: `basic DNA sequences list`. This means that all sequences of this object are of DNA type and do not use ambiguous letters (more about that in “Advanced alphabet techniques” vignette).

## Subsetting sequences

Manipulating sequence objects is an integral part of `tidysq`. `sq` objects can be easily subsetted using usual R syntax:

    sq_dna[1]
    #> basic DNA sequences list:
    #> [1] TAGGCCCTAGACCTG                                                         <15>

Extracting subsequences is a bit more complicated than that — because it uses designated function `bite()`. Its syntax, however, closely resembles that of base R — indexing starts with one and negative indices are interpreted as “anything except that”. It returns an `sq` object with all sequences subsetted:

    bite(sq_dna, 5:10)
    #> basic DNA sequences list:
    #> [1] CCCTAG                                                                   <6>
    #> [2] CCCTGG                                                                   <6>
    bite(sq_dna, c(-9, -11, -13))
    #> basic DNA sequences list:
    #> [1] TAGGCCCTGCTG                                                            <12>
    #> [2] TAGGCCCTGCTG                                                            <12>

It’s possible to reverse sequences using this function:

    # Don't do it like that!
    bite(sq_dna, 15:1)
    #> basic DNA sequences list:
    #> [1] GTCCAGATCCCGGAT                                                         <15>
    #> [2] GTACGGGTCCCGGAT                                                         <15>

However, this usage is strongly discouraged, because it’s both ineffective and works badly with sequences of different lengths. Instead, there is a designated function `reverse()`:

    reverse(sq_dna)
    #> basic DNA sequences list:
    #> [1] GTCCAGATCCCGGAT                                                         <15>
    #> [2] GTACGGGTCCCGGAT                                                         <15>

Note that it is very different to base `rev()`, which reverses only the order of sequences, not letters:

    rev(sq_dna)
    #> basic DNA sequences list:
    #> [1] TAGGCCCTGGGCATG                                                         <15>
    #> [2] TAGGCCCTAGACCTG                                                         <15>

We can combine two or more `sq` objects using base `c()` function:

    sq_dna <- c(sq_dna, reverse(sq_dna))
    sq_dna
    #> basic DNA sequences list:
    #> [1] TAGGCCCTAGACCTG                                                         <15>
    #> [2] TAGGCCCTGGGCATG                                                         <15>
    #> [3] GTCCAGATCCCGGAT                                                         <15>
    #> [4] GTACGGGTCCCGGAT                                                         <15>

## Biological interpretation

`tidysq` offers two functions specific to DNA/RNA sequences, namely `complement()` and `translate()`. The former creates sequences with complementary bases, that is, replaces `A` with `T`, `C` with `G` and vice versa. The latter translates input to amino acid sequences using the translation table with three-letter codons.

These functions can be called as shown below:

    complement(sq_dna)
    #> basic DNA sequences list:
    #> [1] ATCCGGGATCTGGAC                                                         <15>
    #> [2] ATCCGGGACCCGTAC                                                         <15>
    #> [3] CAGGTCTAGGGCCTA                                                         <15>
    #> [4] CATGCCCAGGGCCTA                                                         <15>
    translate(sq_dna)
    #> basic amino acid sequences list:
    #> [1] *ALDL                                                                    <5>
    #> [2] *ALGM                                                                    <5>
    #> [3] VQIPD                                                                    <5>
    #> [4] VRVPD                                                                    <5>

One noteworthy feature here is that translation can be done with any genetic code table of those listed on this Wikipedia page:

    translate(sq_dna, table = 6)
    #> basic amino acid sequences list:
    #> [1] QALDL                                                                    <5>
    #> [2] QALGM                                                                    <5>
    #> [3] VQIPD                                                                    <5>
    #> [4] VRVPD                                                                    <5>

## Finding motifs

Motifs are short subsequences. These are often searched for in biological sequences. `tidysq` has two distinct functions that allow the user to perform such search.

One of them is a `%has%` operator that takes `sq` object and character vector as parameters respectively. It returns a logical vector of the same length as `sq` object, where each element says whether all motifs passed as strings were found in given sequence:

    sq_dna %has% "ATC"
    #> [1] FALSE FALSE  TRUE FALSE
    # It can be used to subset sq
    sq_dna[sq_dna %has% c("AG", "CC")]
    #> basic DNA sequences list:
    #> [1] TAGGCCCTAGACCTG                                                         <15>
    #> [2] TAGGCCCTGGGCATG                                                         <15>
    #> [3] GTCCAGATCCCGGAT                                                         <15>

It says nothing about motif placement within sequence nor it exact form, however. In this case, there is `find_motifs()` function that returns a whole `tibble` (from `tibble` package; basically improved version of `data.frame`) with various info about found motifs. Important thing to note here is that the second argument is a character vector of sequence names to avoid embedding potentially long sequences in resulting `tibble` potentially many times:

    find_motifs(sq_dna, c("seq1", "seq2", "rev1", "rev2"), c("ATC", "TAG"))
    #> # A tibble: 4 × 5
    #>   names found     sought start   end
    #>   <chr> <dna_bsc> <chr>  <int> <int>
    #> 1 rev1  ATC <3>   ATC        7     9
    #> 2 seq1  TAG <3>   TAG        1     3
    #> 3 seq1  TAG <3>   TAG        8    10
    #> 4 seq2  TAG <3>   TAG        1     3

You can also provide this function with a `data.frame` (or, what we recommend, `tibble`) containing one column called `sq`, containing the sequences and the other column `name` containing the names.

    sqibble <- tibble::tibble(sq = sq_dna,
                              name = c("seq1", "seq2", "rev1", "rev2"))

    # does the same as the call from previous chunk of code
    find_motifs(sqibble, c("ATC", "TAG"))
    #> # A tibble: 4 × 5
    #>   names found     sought start   end
    #>   <chr> <dna_bsc> <chr>  <int> <int>
    #> 1 rev1  ATC <3>   ATC        7     9
    #> 2 seq1  TAG <3>   TAG        1     3
    #> 3 seq1  TAG <3>   TAG        8    10
    #> 4 seq2  TAG <3>   TAG        1     3

There are ambiguous DNA bases in IUPAC codes and these can be used in motifs. One of them is `"N"` — its meaning is “any of `A`, `C`, `G` or `T`:

    find_motifs(sqibble, "GNCC")
    #> # A tibble: 7 × 5
    #>   names found     sought start   end
    #>   <chr> <dna_bsc> <chr>  <int> <int>
    #> 1 seq1  GGCC <4>  GNCC       3     6
    #> 2 seq1  GCCC <4>  GNCC       4     7
    #> 3 seq1  GACC <4>  GNCC      10    13
    #> 4 seq2  GGCC <4>  GNCC       3     6
    #> 5 seq2  GCCC <4>  GNCC       4     7
    #> 6 rev1  GTCC <4>  GNCC       1     4
    #> 7 rev2  GTCC <4>  GNCC       7    10

This example displays the difference between `"sought"` and `"found"` columns. The former contains the string representation of motif that the user was looking for, while the latter contains a `tidysq`-encoded sequence with an “instance” of motif.

Two additional characters are reserved because of their special meaning in motifs. `"^"` means that this motif must be found at the start of a sequence, while `"$"` means the same, but with the end instead. They can be mixed with ambiguous letters, of course:

    find_motifs(sqibble, c("^TAG", "ATN$"))
    #> # A tibble: 3 × 5
    #>   names found     sought start   end
    #>   <chr> <dna_bsc> <chr>  <int> <int>
    #> 1 seq1  TAG <3>   ^TAG       1     3
    #> 2 seq2  TAG <3>   ^TAG       1     3
    #> 3 seq2  ATG <3>   ATN$      13    15

## Exporting sq objects

After doing computations the user might wish to save their sequences for future use. One of the most popular formats for storing biological sequences is FASTA. `tidysq` allows the user to write sequences to FASTA file with `write_fasta()` function. Important thing to remember here that the arguments for the function are analogous to those used in `find_motifs()` – either `sq` object and a vector of names or a `tibble` with columns of sequences and names:

    write_fasta(sq_dna,
                c("seq1", "seq2", "rev1", "rev2"),
                "just_your_ordinary_fasta_file.fasta")
    # or
    write_fasta(sqibble,
                "just_your_ordinary_fasta_file.fasta")