INTRODUCTION {#s0}
============

Clustered regularly interspaced short palindromic repeat (CRISPR)-Cas systems provide adaptive immunity in most of the archaea and many bacteria ([@B1]). Short genomic segments of invading genetic elements (protospacers) are inserted as spacers between direct repeats in the CRISPR array(s) of the host genome during CRISPR adaptation ([@B2][@B3][@B4]). The primary transcript of the CRISPR array is processed into small-RNA guides that consist of a spacer with portions of the flanking CRISPR repeats, which are used by CRISPR-associated (Cas) nucleases to identify and degrade cognate nucleic acids ([@B5], [@B6]). The information content of CRISPR spacers is integrated directly into the prokaryotic genome and is inherited upon cell division, creating a durable genomic record of a host-pathogen interaction.

CRISPR-Cas systems have been classified into six types and more than 20 subtypes on the basis of gene content and locus architecture ([@B7][@B8][@B9]). CRISPR repeat sequences of the various types and subtypes show conservation in related bacteria, while the spacer content of the CRISPR arrays is extremely variable ([@B10]). Genomes of different strains of the same bacterial species often contain similar configurations of CRISPR-Cas systems with closely similar repeat sequences but substantially different and, in many cases, non-overlapping spacer repertoires ([@B11]).

Several type III CRISPR-Cas systems contain genes encoding fusions of reverse transcriptases (RTs) with the major CRISPR adaptation enzyme, the Cas1 integrase ([@B12][@B13][@B15]). Here, we explore the possible origins of RT-associated CRISPR loci, the routes of their evolution, and their spacer content. In particular, we address several open questions. When and how did putative functional associations between RTs and *cas1* genes arise? What constraints exist for the association of RT-Cas1 fusions with CRISPR-Cas systems? Do RT-Cas1-containing CRISPR loci acquire spacers from a distinct source, i.e., from genomic RNA, plasmid RNA, DNA phage transcripts, or RNA phage sequences, or from some other, uncharacterized RNA pool?

We have previously shown that RT-Cas1 fusions enable CRISPR spacer acquisition directly from RNA ([@B16]). The ability of the RT-Cas1 adaptation modules to acquire spacers from RNA, coupled with the ability of type III CRISPR-Cas effector modules to target RNA ([@B17][@B18][@B24]), implies the potential to provide adaptive immunity against parasites with both RNA and DNA genomes. We wondered whether such a capability might lend itself to an expanded immune function for RT-associated CRISPR-Cas systems in the environment.

The population of spacers contained within CRISPR arrays in a natural community of RT-Cas1-carrying organisms is a potential "memory bank" of the pools of nucleic acids, particularly RNAs, that are perceived as "threats" by these microbes ([@B25]). To gain insight into this form of microbial immune memory, we interrogated the spacer repertoire of a natural population of RT-Cas1-bearing cyanobacteria *Arthrospira platensis* grown in vast enriched cultures for commercial sale as a food supplement known as *Spirulina*. The *A. platensis* genome contains both an RT-linked type III-B CRISPR-Cas locus and an RT-lacking type III-D locus. We identified diverse spacer repertoires from each CRISPR-Cas system. Protospacers were identified in the *Spirulina* metagenome for a few type III-D spacers, but virtually none of the RT-linked type III-B spacers could be traced to any source. These findings suggest that the vast majority of RT-linked CRISPR spacers come from a distinct sequence pool, the nature of which remains enigmatic.

RESULTS {#s1}
=======

Phylogeny of reverse transcriptases associated with CRISPR-Cas systems. {#s1.1}
-----------------------------------------------------------------------

Previous phylogenetic analysis of the RT superfamily has suggested that the CRISPR-associated RTs could be derived from a single acquisition event, and that they are most similar to the RTs encoded by group II introns ([@B15]). To study the origin and extent of the RT association with CRISPR loci in greater detail, we retrieved 266 islands from a large dataset of both complete and draft bacterial and archaeal genomes that contained at least one *cas* gene and at least one RT gene (see Table S1 at <https://figshare.com/s/3a8dab8ed7138922f693>). From this collection of genomic loci, we selected a nonredundant set of proteins that could be expected to contain a full-sized RT domain (\~300 amino acids \[aa\]). As reported previously, the CRISPR-associated RTs do not show specific phylogenetic affinity to any subgroup of the group II intron-encoded RTs ([@B15]). To build a phylogenetic tree, we included several group II intron-encoded RTs as an outgroup ([Fig. 1](#fig1){ref-type="fig"}; also see [Fig. S1](#figS1){ref-type="supplementary-material"} in the supplemental material for details). The resulting tree topology is largely consistent with the phylogenetic analysis in the previous work ([@B15]), with the seven distinct groups described in the previous analysis reproduced in our tree ([Fig. 1](#fig1){ref-type="fig"}). Because our dataset included almost an order of magnitude more RTs than were used in the previous set, we were able to identify additional, well-supported branches that had not been described previously. These new groupings include branch 1, which consists of proteins containing fused Cas6, RT, and Cas1 domains; the Cyanobacteria-specific branch 5, which consists of RT-Cas1 fusion proteins; minor branches 8, 9, and 10 ([Fig. 1](#fig1){ref-type="fig"}); and the Methanomicrobia-specific branch 11 in the outgroup ([Fig. S1](#figS1){ref-type="supplementary-material"}). The RT from *Marinomonas mediterranea*, for which activity in spacer adaptation has been studied ([@B16]), belongs to branch 1, and the RT from *A. platensis* belongs to branch 5 ([Fig. 1](#fig1){ref-type="fig"}).

10.1128/mBio.00897-17.2

Phylogeny of selected representatives of reverse transcriptases encoded in genomic regions shared with Cas genes: the outgroup branch (see [Fig. 1](#fig1){ref-type="fig"}). Designations are the same as those used in [Fig. 1](#fig1){ref-type="fig"}. In addition, group II intron-associated RTs are shown in brown and other CRISPR-Cas systems in purple. Comments pertaining to type III systems and RT-containing loci are provided in parentheses. Similarly to the RT-associated adaptation module, the RT-*cas6* gene pair is promiscuous and was identified within three distinct type III subtypes. The *cas1* genes associated with these systems are confidently placed within the subtree that includes the other RT-associated *cas1* genes. Thus, in this case, the RT from a group II intron most likely displaced the ancestral RT in a CRISPR-*cas* locus. This substitution was then followed by gene rearrangement and dissociation from the adaptation module. Download FIG S1, EPS file, 1.6 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

![Phylogeny of a representative set of reverse transcriptases encoded within CRISPR-*cas* loci. A maximum likelihood phylogenetic tree was reconstructed for 134 RT sequences using the FastTree program. SH (Shimodaira-Hasegawa)-like node support values calculated by the same program are shown if they are greater than 70%; node support values for key nodes are highlighted. Major well-supported distinct branches are shown by blue rectangles. Each sequence in the tree is shown with a local numeric identifier (ID) and species name; these are also provided in Table S1 (<https://figshare.com/s/3a8dab8ed7138922f693>) for comparison. RT protein domain architecture is coded in each sequence description as follows: Cas6_RT_Cas1 and RT_Cas1 for the respective fusions, RT for the systems with known subtypes, and NA_RT for all other cases. A typical domain or gene organization for each branch and for selected sequences is shown to the right of the tree. Independent genes are shown with distinct arrows, while fused genes are displayed as single arrows with multiple colors. The text is color-coded to denote CRISPR-Cas system subtypes as follows: III-A, dark blue; III-B, magenta; III-D, sky blue; I-E, orange. The outgroup is collapsed and is indicated by a triangle. The details for the outgroup branch are provided in [Fig. S1](#figS1){ref-type="supplementary-material"}. For the sequences that were classified previously ([@B15]), the respective groups are indicated in green.](mbo0031733780001){#fig1}

To investigate the origin of the fusions between RT and *cas* genes, we examined the domain organizations of all Cas proteins fused to RT domains (or encoded by adjacent genes) in the context of the RT tree ([Fig. 1](#fig1){ref-type="fig"}). The tree suggests the original establishment of a functional connection between RT and *cas1* within the adaptation module, first as adjacent genes. The tree topology is further consistent with the parsimonious evolutionary scenario of single points of origin, first of the RT-Cas1 fusion and then of the Cas6-RT-Cas1 fusion (clades 1 and clade 2, respectively) ([Fig. 1](#fig1){ref-type="fig"}). However, there are many variations in protein architecture in different branches of the tree. Some of this variation in clades 1 and 2 can be explained by secondary fissions (i.e., split of the fusion protein into separate Cas1 and RT proteins), although the possibility of there being several additional, independent cases of RT-Cas1 fusion within or outside these clades (e.g., *Roseburia* in branch 8) cannot be ruled out. The Cas1 phylogeny largely follows the RT phylogeny ([Fig. S2](#figS2){ref-type="supplementary-material"}), which suggests that the two proteins (or domains in fusion proteins) generally coevolve. Recombination between RT and Cas1 domains could have occurred on several occasions and might account for the inconsistencies between the topologies of the RT and Cas1 trees (for example, see *Pirellula staleyi* DSM 6068 in [Fig. 1](#fig1){ref-type="fig"} and [Fig. S2](#figS2){ref-type="supplementary-material"}).

10.1128/mBio.00897-17.3

Phylogeny of RT-linked Cas1 proteins. Designations are the same as those used in [Fig. 1](#fig1){ref-type="fig"}. Download FIG S2, EPS file, 2.8 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

We also mapped the known CRISPR-Cas system subtypes onto the RT tree to determine whether the RTs coevolved with the respective CRISPR effector complexes. The RT-Cas1 fusions were associated with diverse subtypes and variants of type III CRISPR-Cas systems ([Fig. 1](#fig1){ref-type="fig"}). On the whole, we observed virtually no link between the RT phylogeny and the phylogeny of the effector modules. Furthermore, even within the RT-encoding loci classified as being of the same CRISPR-Cas subtype, gene content was often notably different ([Fig. 2](#fig2){ref-type="fig"}). About half of the RT-*cas* loci lack genes for effector complex subunits but often include a CRISPR array ([Fig. 2](#fig2){ref-type="fig"}). Taken together, these observations indicate that the RT-containing adaptation module represents an autonomous functional unit that spreads by horizontal transfer and can promiscuously combine or function in *trans* with any type III system (with the possible exception of type III-C). It should be noted, however, that given the absence of the hallmarks of group II introns, including both the typical elements of RNA secondary structure and additional domains of the intron-encoded proteins ([@B26]), these RT-encoding modules are not predicted to spread as retroelements. With a single exception described below, RTs were not found associated with other CRISPR-Cas types.

![Architectures of selected RT-associated CRISPR-Cas loci. For each locus, the species name, genome accession number, and respective nucleotide coordinates are indicated. Genes are shown roughly to scale; CRISPR arrays are indicated in brackets and are not shown to scale. Homologous genes are color-coded, with the exception of numerous ancillary genes, which are all shown in light green with a green outline, and unknown proteins are shown in gray. The gene names largely follow the nomenclature in reference [@B7], but the RAMP proteins of groups 5 and 7 are denoted gr5 and gr7, respectively. The CRISPR-Cas system subtype is indicated for the loci encoding the respective effector genes.](mbo0031733780002){#fig2}

In the course of this analysis, we detected two unusual RT-associated CRISPR-Cas architectures. One of these belongs to branch 11 in the outgroup (i.e., among group II intron-encoded RTs) and is present mostly in *Methanosarcina* species. In this case, the RT gene is located next to a *cas6* gene but there is no *cas1* gene in the locus ([Fig. 2](#fig2){ref-type="fig"}). This RT is confidently placed within the outgroup containing mostly RTs of group II introns ([Fig. 1](#fig1){ref-type="fig"}). Thus, this is most likely a case of independent recruitment of an RT into a CRISPR-Cas system. The second unusual architecture occurs in association with a small number of type I-E systems. The RT genes in this case are located next to the effector module genes ([Fig. 2](#fig2){ref-type="fig"}). This arrangement was detected in several *Streptomyces* species and in *Streptococcus oralis* ([Fig. 1](#fig1){ref-type="fig"}). The RT in this system seems to have been acquired from the main, type III-associated group described above ([Fig. 1](#fig1){ref-type="fig"}). The fixation of this gene arrangement in bacterial evolution implies that this RT functions as part of the type I-E CRISPR-Cas system, which is unexpected given the lack of RNA targeting by the type I systems that have been studied so far, and could be an interesting direction for experimental study.

A diverse repertoire of CRISPR spacers in commercially grown *Arthrospira platensis.* {#s1.2}
-------------------------------------------------------------------------------------

To compare the nucleic acid sequence repertoires sampled by RT-Cas1-associated and RT-lacking CRISPR-Cas systems in a physiological setting, we obtained a series of independent samples from the cyanobacterial species *Arthrospira platensis*, grown commercially in open-air "raceway" ponds and marketed as *Spirulina*. We chose this species because it represented an easily accessible, natural population of RT-Cas1-encoding bacteria, grown in a large culture exposed to the open environment.

The various *A. platensis* strains with sequenced genomes (8005, C1, NIES-39) contain type III-A, type III-D, and type III-B CRISPR-Cas systems, and two classes of CRISPR arrays with conserved CRISPR repeat sequences that are associated with either the III-D or III-B systems. None of the strains harbor any type I or type II CRISPR-Cas systems. One type III-B locus (denoted III-B--RT) in each strain carries an RT-Cas1 fusion in addition to a separate Cas1 gene without an RT domain. Additionally, InsQ and COG2452 transposases, as well as apparent pseudogenes of IS*1*, IS*607*, and IS*630* family transposases and group II intron-type RTs, can be found in the immediate neighborhoods of the type III-B loci. The arrangement of various CRISPR-Cas systems in the type strain *A. platensis* NIES-39 is shown ([Fig. 3A](#fig3){ref-type="fig"} to [C](#fig3){ref-type="fig"}).

![CRISPR-Cas systems in *Arthrospira platensis*. (A) Distribution of CRISPR-Cas systems by phylogenetic type in three sequenced reference strains of *A. platensis* (\"Others\": types I, II, IV, V, and VI). The tree at the right side of the panel shows the evolutionary relationship between type III subtypes. (B) List of CRISPR-Cas systems and arrays in type strain *A. platensis* NIES-39 (left panel). The approximate location in megabases (Mb) on the circular chromosome in the direction of the arrow is indicated (right panel). The *cas10 cmr2* and *cmr6* family genes in the III-B--RT system (but not the III-B system) show signs of mutational atrophy. (C) Alignments of CRISPR direct repeats from the various CRISPR arrays. (D) Gel image showing PCR products amplified from CRISPR arrays. The first lane shows a 25-bp DNA ladder. (E) List of *Spirulina* brands used in this study.](mbo0031733780003){#fig3}

We designed primers specific to the distinct III-D (RT-lacking) and III-B (RT-Cas1-associated) CRISPR repeat sequences in the *A. platensis* NIES-39 genome to amplify spacers selectively from each CRISPR array ([Fig. S3](#figS3){ref-type="supplementary-material"}). Spacers are typically integrated into CRISPR arrays in a directional manner: new spacers are inserted close to the "leader" sequence (which also contains the CRISPR promoter) and are pushed down the array when more spacers are acquired ([@B4]). Older spacers would therefore be seen more frequently in a bacterial population as they are propagated through cell division. Our sequencing method retains strand information but should lead to the amplification of all spacers with similar efficiencies irrespective of the ordering of the spacers in a CRISPR array.

10.1128/mBio.00897-17.4

Spacer amplification PCR strategy. First, primers that bind to the CRISPR repeat sequences are used to amplify spacers from the array. A forward primer in any repeat may amplify a product in concert with a reverse primer with any subsequent repeat; however, the shortest (\~125-bp) amplicons consisting of one CRISPR spacer are most efficiently amplified, while larger amplicons containing two, three, or more spacers produce the characteristic "ladder" pattern of PCR products shown in [Fig. 3D](#fig3){ref-type="fig"}. DNA adapters to make the amplicons compatible with Illumina high-throughput sequencing technology are attached in a subsequent round of PCR, and a final product corresponding to the \~125-bp amplicon from step 1 is size selected and sequenced. Download FIG S3, EPS file, 1.6 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

We purchased *Spirulina* from various *Spirulina* vendors at local grocery stores and extracted genomic DNA from the cyanobacteria. This DNA served as the template for amplification of CRISPR spacers, and the amplicons formed the characteristic "ladder" expected of primers that bind only in the repeat sequences of CRISPR arrays ([Fig. 3D](#fig3){ref-type="fig"} and [E](#fig3){ref-type="fig"}). We also used as an amplification control a similarly marketed raw probiotic blend that does not contain *Arthrospira platensis* and did not observe any amplicons (data not shown).

By high-throughput sequencing of the smallest amplicon from each reaction (corresponding to one repeat-spacer-repeat unit), we recovered a diverse repertoire of spacer sequences. To group highly similar spacers, we first trimmed CRISPR repeats from the reads and allowed up to 2 mismatches to account for sequencing error. This procedure yielded a total of about 2 × 10^6^ unique spacers. Variation in spacer sequences caused by mutations arising during cyanobacterial cell division could result in multiple "unique" spacers being identified that were likely derived from the same acquisition event. To obtain a more conservative estimate of the complexity of the spacer pools, we utilized a less stringent threshold for spacer equivalence. Spacers were ranked by the frequency with which they were encountered in the dataset and were then compared pairwise with every less prevalent sequence. If the two sequences were different at 4 or fewer sites (allowing for arbitrarily long deletions on either end to account for potential trimming artifacts), the less prevalent sequence was discarded. For every spacer observed 100 times or more, we also discarded any less frequent sequences that shared any 12-mer with their presumed "parents." This procedure yielded a dataset of \~2 × 10^5^ spacer clusters ([Fig. 4A](#fig4){ref-type="fig"}). The clustered spacers were typically observed only once in the dataset ([Fig. 4B](#fig4){ref-type="fig"}).

![Sequencing of spacers from *Spirulina* purchased from grocery stores. (A) Numbers of unique spacers recovered from type III-D and type III-B CRISPR arrays before and after clustering. The last two columns show Chao-1 estimates of species richness/diversity ([@B57]). The Chao-1 estimate corresponds to an approximate lower bound for the total number of unique spacers in the sample. The 95% confidence lower bound for the Chao-1 estimate has also been calculated. (B) Histogram of spacer frequency before and after clustering. The last bin contains all sequences observed 100 times or more. (C) Histogram of spacer lengths for III-D and III-B spacers. (D) Saturation curves calculated for III-D and III-B spacer pools using the clustering algorithm described for panel A showing the number of sequence clusters obtained as progressively larger subsets of the spacer datasets were considered.](mbo0031733780004){#fig4}

The spacers from the III-B system were shorter than those from the III-D system, as expected from their sizes in the sequenced CRISPR arrays in the reference genome ([Fig. 4C](#fig4){ref-type="fig"}). Coincidence analysis ([@B27], [@B28]) revealed that spacers amplified from the III-D and III-B loci indeed came from distinct sequence pools ([Fig. S4](#figS4){ref-type="supplementary-material"}). We found the spacers from CRISPRs B1/B2, CRISPR B3, and CRISPRs D1/D2/D3 to be mutually disjoint. Further validating the specificity of our PCR method, spacers in the CRISPR arrays in the reference genomes of various *A. platensis* strains were efficiently recovered, and there were no instances of crossovers between the III-D and III-B spacer pools at the genomic CRISPR loci. To assess whether we have approached a point of diminishing returns in our sequencing efforts, we randomly sampled spacers from our dataset in 10% increments and quantified whether the total number of unique spacers (counted according to the clustering method described above) kept increasing. We found that the spacer pools appeared to be approaching diminishing returns for the type III-D loci but not for the type III-B loci ([Fig. 4D](#fig4){ref-type="fig"}).

10.1128/mBio.00897-17.5

Coincidence analysis of spacer sequencing datasets. To measure the pairwise similarity of the sequenced spacer replicates, we computed the pairwise coincidence probability (or co-clonality score) from the replicates. The coincidence probability (or co-clonality score) between two replicates is the probability that a random spacer from one replicate would happen to be the same as a random spacer from a second replicate. The logarithms of these probabilities are shown in a heat map. The heat map shows that the replicates organize themselves by CRISPR loci into clear clusters. Download FIG S4, EPS file, 2.3 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

Sampling the extracellular environments of *A. platensis.* {#s1.3}
----------------------------------------------------------

We reasoned that the appropriate environment in which to find the sequence pool from which *A. platensis* captures spacers would be open-air "raceway ponds". We collected samples of the cyanobacteria and their extracellular environment from a commercial *Spirulina* farm (Earthrise Nutritionals LLC, Calipatria, CA). Several samples of enriched culture were collected directly from the *Spirulina* raceway ponds and separated into cellular and extracellular fractions by centrifugation (see Materials and Methods). A summary of the sequencing data thus obtained is shown in [Fig. S5A](#figS5){ref-type="supplementary-material"}. Mapping of the DNA sequences from the cellular fraction to the *A. platensis* reference genomes (strains NIES-39, C1, and 8005) revealed a highly polymorphic population ([Fig. S5B](#figS5){ref-type="supplementary-material"}). Because we were most interested in potentially rare and/or structured RNA species, the isolated RNA was sequenced using several different methods to mitigate inherent biases among the RNA sequencing protocols (see Materials and Methods). Virus-like contigs were detected in both extracellular RNA and DNA fractions ([Fig. S5C and D](#figS5){ref-type="supplementary-material"}; also see [Text S1](#textS1){ref-type="supplementary-material"} in the supplemental material). In addition to the data from *Spirulina* raceway ponds, small amounts of metagenomic data were collected from the nearby saline rift lake, the Salton Sea. We also obtained a metagenomic DNA dataset from a separate study of Lake Bogoria in Kenya (unpublished); this lake is a natural habitat of cyanobacteria, including *A. platensis*, which serve as the food source for one of the world's largest populations of flamingos.

10.1128/mBio.00897-17.6

Metagenomic database obtained from *Spirulina* raceway ponds. (A) Metagenomic data obtained from the various fractions of the *Spirulina* samples are summarized. "ER" denotes a *Spirulina* metagenomic sample obtained from raceway ponds operated by Earthrise LLC. "S.S." denotes a metagenomic sample collected from the nearby Salton Sea. Metagenomic assemblies obtained by Velvet and SPAdes programs are also summarized. The ultracentrifuged pellet from the Salton Sea extracellular fraction yielded no detectable RNA. (B) Snapshot of DNA sequencing reads from the ER cellular pellet mapped to the highly conserved bacterial *dnaK* gene in *A. platensis* NIES-39. The coverage plot shows \~100× coverage and is representative of the entire genome. Colored bars indicate mismatches between the sequencing reads and the reference sequence. (C) Conserved-domain search results for ER extracellular RNA contigs containing RNA replicase domain hits identified by HMMer 3.1. (D) Example of a DNA phage-like contig found in the ER extracellular DNA metagenome. Annotations shown were generated by the PHASTER online interface. Download FIG S5, EPS file, 2.6 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

10.1128/mBio.00897-17.1

Supplemental results. Download TEXT S1, DOCX file, 0.1 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

Additionally, we sequenced CRISPR spacers from the cellular DNA using the amplification scheme from [Fig. S3](#figS3){ref-type="supplementary-material"}. The resulting "native" spacer repertoire exhibited characteristics similar to those of the previous dataset from store-bought *Spirulina*, and both store-bought and native spacers were included in subsequent searches ([Fig. S6](#figS6){ref-type="supplementary-material"}).

10.1128/mBio.00897-17.8

Sequencing of spacers from the cellular fraction of metagenomic samples from *Spirulina* raceway ponds. (A) Numbers of unique spacers recovered from type III-D and type III-B CRISPR arrays before and after clustering. The last two columns show Chao-1 estimates of species richness/diversity ([@B57]). The Chao-1 estimate corresponds to an approximate lower bound for the total number of unique spacers in the sample. The 95% confidence lower bound for the Chao-1 estimate has also been calculated. (B) Histogram of spacer frequencies before and after clustering. The last bin contains all sequences observed 100 times or more. (C) Histogram of spacer lengths for III-D and III-B spacers. (D) Saturation curves calculated for III-D and III-B spacer pools using the clustering algorithm described for panel A showing the number of sequence clusters obtained as progressively larger subsets of the spacer datasets are considered. Download FIG S6, EPS file, 2.1 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

An enigmatic source of the RT-associated CRISPR spacers from *Spirulina.* {#s1.4}
-------------------------------------------------------------------------

We attempted to identify a source for *Spirulina* spacers from the combined pool of \~2.5 × 10^6^ sequences representing \>2 × 10^5^ clusters. Since searches through the *A. platensis* reference genomes and public (NCBI NR/NT) databases yielded very few matches (see [Text S1](#textS1){ref-type="supplementary-material"}), we shifted our focus to datasets that specifically aimed to collect bacteriophage sequences that were not present in NR/NT collections. Several such datasets were screened: a cyanobacterial virome sequenced from hot-spring microbial mats in Octopus Spring in Yellowstone National Park ([@B29]); all viral contigs from the Tara Ocean Viromes project, which contained many DNA bacteriophages of abundant marine cyanobacteria such as *Synechococcus* sp. ([@B30]); and a source-agnostic virome curated from a comprehensive analysis of thousands of metagenomic DNA samples ([@B31], [@B32]). None of the datasets yielded any conclusive identification of the *Spirulina* spacers ([Fig. 5A](#fig5){ref-type="fig"}). Next, to leverage the possibility that the type III-B CRISPR arrays were acquiring spacers exclusively from RNA, we also searched through an RNA virome constructed through a meta-analysis of metatranscriptomic contigs (unpublished) from the IMG/M system ([@B33]) containing RNA viral hallmark genes, including RNA-dependent RNA polymerase (RdRp) genes and other genes specific to RNA viruses. Again, we did not find any confident matches ([Fig. 5A](#fig5){ref-type="fig"}).

![Summary of *Spirulina* spacer search attempts. (A and B) BLAST results matching \~2 million CRISPR spacers to reads and contigs from (A) various virome datasets and (B) *Spirulina* metagenomic data. The "unfiltered hits" columns show the number of matches returned at e-value stringency cutoffs based on the size of the database. The "Unfiltered alignments" column in panel B denotes the subsets of reads and contigs from the unfiltered hits that could in turn be identified in public protein sequence databases (NR) at the protein level. The "Satisfactory alignments" columns list the manually curated hits remaining after low-complexity and low-confidence matches were eliminated.](mbo0031733780005){#fig5}

Next, leveraging the *Spirulina* metagenomes and viromes, we set out to find spacers that might have been derived from a sequence in the local environment which we could then potentially identify in external databases (also see [Fig. S7](#figS7){ref-type="supplementary-material"}, [S8](#figS8){ref-type="supplementary-material"}, and [S9](#figS9){ref-type="supplementary-material"} and [Text S1](#textS1){ref-type="supplementary-material"}). While a few more hits for type III-D spacers were observed in the *Spirulina* metagenomic data relative to public sequence databases ([Fig. 5B](#fig5){ref-type="fig"}), the overwhelming majority still could not be matched. Notably, only matches to a single site in thymidylate synthase were observed among the type III-B spacers ([Fig. S9B](#figS9){ref-type="supplementary-material"}). Alignments of spacers to metagenomic reads that could be identified as homologues of known open reading frames (ORFs) are presented in Table S2 (<https://figshare.com/s/16f85dbabc34e314a828>). Finally, we also screened metagenomic sequencing data from Lake Bogoria but found only \~540 hits in a total search space of over 37 million reads. Almost all of these hits contained stretches of low-complexity sequence and were unlikely to represent genuine matches.

10.1128/mBio.00897-17.7

Spacer homology searches through public sequence databases. (A) Only 2 clustered spacers in a combined-sequence pool of \>200,000 mapped to the reference genomes outside the native CRISPR arrays. The type III-B spacer mapping to the alcohol dehydrogenase gene is also contained in the CRISPR-B1 array in the *A. platensis* NIES-39 genome. (B) A Kmer-based mapping approach returns the expected number of random matches to the reference genome. (C) Only 2 of \>200,000 clustered spacers can be identified by BLAST in the NCBI nucleotide collection (NT). (D) Example of two type III-B spacers combined by the greedy assembly algorithm. Download FIG S7, EPS file, 1.9 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

10.1128/mBio.00897-17.9

Group I and group II self-splicing introns in *A. platensis*. (A) Reads from RNA and DNA sequencing of *Spirulina* cellular pellet mapping to predicted exon junction sequences from manually annotated group 1 and group 2 self-splicing introns in the *A. platensis* NIES-39 genome. An example of each is shown, with an RNA-Seq read spanning the predicted exon junction, and no support for the exon junction sequence being present as DNA in the sample. (B) Reads per kilobase per million (RPKM) values of the 30 most highly expressed genes in *A. platensis* NIES-39 as determined by sequencing of RNA from the *Spirulina* cellular pellet. Protein products of genes that were not annotated in the reference genome were identified by the presence of conserved domains using the NCBI CD-Search program (<https://www.ncbi.nlm.nih.gov/Structure/bwrpsb/bwrpsb.cgi>). Download FIG S8, EPS file, 1.7 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

10.1128/mBio.00897-17.10

Spacer homology searches through a metagenomic database obtained from *Spirulina* raceway ponds. (A) Example of a type III-D spacer (\~40 bp) that could be identified as a putative segment of a DNA methyltransferase-like gene in the *A. platensis* NIES-39 reference genome once it was mapped to a longer metagenomic read (\~150 bp) derived from the ER extracellular DNA fraction that could be identified based on its coding potential. (B) The only type III-B spacer (\~40 bp) that could be identified as a putative segment of a thymidylate synthase-like gene in the *A. platensis* NIES-39 reference genome once it was mapped to a longer metagenomic read (\~150 bp) derived from the ER extracellular RNA fraction that could be identified based on its coding potential. (C) Example of a type III-D spacer (\~40 bp) that could be identified as a putative segment of a DNA methyltransferase-like gene in the *Pseudomonas* sp. PH1b genome once it was mapped to a longer metagenomic read (\~150 bp) derived from the ER extracellular RNA fraction that could be identified based on its coding potential. (D) Prophage-like region in the *Pseudomonas* sp. PH1b reference genome containing the spacer-matching sequence described in panel C. Download FIG S9, EPS file, 1.6 MB.

Copyright © 2017 Silas et al.

2017

Silas et al.

This content is distributed under the terms of the

Creative Commons Attribution 4.0 International license

.

In summary, screening of the various databases detailed here led to the identification of only a small proportion of spacers with protospacers detectable in the *Spirulina* spacer pool. Several protospacers were identified for the RT-lacking type III-D system, but only a single potential target was detected for the RT-associated III-B system. The low prevalence of detectable protospacers in the *Spirulina* metagenome points to an unknown origin of the great majority of the type III-D and (especially) type III-B protospacers in *A. platensis*.

Several RT-linked CRISPR spacers appear to target DNA viruses. {#s1.5}
--------------------------------------------------------------

We then broadened our search to all CRISPR spacers in published genomic datasets. To assess whether any CRISPR spacers were specific to any RNA phages, we aligned all unique sequences from known RNA phage species (see Table S3 at <https://figshare.com/s/f373935a1da886040791>) ([@B34]) to CRISPR spacers from published genomes ([@B35]). No RNA phage sequences showed significant similarity to any CRISPR spacer. Given the lack of detected protospacers at this stage, we expanded the search to include all spacers from CRISPR arrays associated with the RT-encoding loci (see Table S1 at <https://figshare.com/s/3a8dab8ed7138922f693>) to look for possible matches to the viral subset of the NR/NT database (NCBI taxid 10239) and against the prokaryotic database. Only a few matches were found among the 2,054 spacers (see Table S4 at <https://figshare.com/s/72fccf4e2ad9503b5a0e>), and most of these originated from DNA phages or predicted prophages. The CRISPR arrays containing the spacers with matches are scattered among different branches of the RT tree (Table S4, <https://figshare.com/s/72fccf4e2ad9503b5a0e>).

DISCUSSION {#s2}
==========

The dynamic evolution of the CRISPR loci, both in their "hardware" (adaptation and effector enzymatic machinery) and "software" (spacer repertoires), provides a valuable opportunity to track virus-host coevolution ([@B36]). In this work, we analyzed the prevalent variants of type III CRISPR-Cas systems that contain reverse transcriptase domains and appear to acquire spacers from RNA molecules. To gain insight into the evolution and functions of these CRISPR-Cas systems, we examined the broad phylogeny of the RT-associated adaptation machineries and interrogated the resultant spacer repertoire in detail in a readily accessible bacterial species carrying such a locus (*Arthrospira platensis*).

Phylogenetic analysis of CRISPR-linked RTs revealed monophyly of the RT-Cas1 fusion, with some subsequent, lineage-specific fission events. The CRISPR-linked RTs are most closely related to group II intron-encoded RTs ([@B26]), suggesting that the initial recruitment of RT by the CRISPR-Cas system followed integration of a group II intron next to a type III *cas1* gene. This scenario is compatible with the detection of several cases of independent RT recruitment by narrow groups of archaea and bacteria, including bacterial type I-E. The apparent fixation of the association between the RT and CRISPR-Cas systems in each of these groups suggests that the group II intron RT is relatively easily adopted for spacer acquisition from RNA, and that fusion with Cas1 is not required. Nevertheless, the phylogenetic trees of the RT and Cas1 moieties of the RT-Cas1 fusion proteins are largely congruent, indicating that the two domains are involved in a functional interaction and tightly coevolve (although several isolated recombination events were detected). In contrast, there was little concordance between the phylogeny of CRISPR-linked RTs and the CRISPR type classification (largely based on the sequence and arrangements of CRISPR effector modules \[[@B7]\]), suggesting that the RT-Cas1 adaptation module is functionally autonomous, is disseminated via horizontal gene transfer, and can combine and function (perhaps even in *trans*) with diverse type III effector modules.

The various sources of commercial *Spirulina* provided a rich sampling of environmentally derived CRISPR spacers for both RT-linked (type III-B) and non-RT-linked (type III-D) CRISPR arrays in the same host genome. Both repertoires were remarkably diverse, rivaling the host genome in sequence content. Furthermore, while the spacer repertoire of the RT-lacking III-D system seemed to show signs that it was approaching saturation, the repertoire of the RT-containing III-B systems did not. Consistent with our relative ignorance of the natural populations of genome parasites for *A. platensis* (or for most microbes), we were able to identify protospacers for only a small fraction of spacers. Almost all of the identified spacers were from the type III-D arrays, making the origin of the spacers in the RT-linked type III-B loci particularly enigmatic. These findings indicate that the type III-B system might acquire spacers from a nucleic acid sequence pool distinct from the source of type III-D spacers. Such a distinct pool could potentially include viruses that are encountered only transiently by *A. platensis* in its natural environment. As a few intriguing (and unsupported) possibilities, the type III-B spacers could be generated from a pool of autonomously replicating RNA ([@B37]), by a random process ([@B38]), or from an as-yet-unknown pool of environmental nucleic acids.

Type III CRISPR-Cas systems can target RNA ([@B17][@B18][@B24]), and, given the demonstrated ability of the RT-containing type III-B system to also integrate spacers from RNA via reverse transcription ([@B16]), it appeared an interesting possibility that these variants of CRISPR-Cas could provide adaptive immunity against RNA-based parasites, such as RNA bacteriophages. However, no natural examples of CRISPR immunity against RNA phage have been described so far, nor have CRISPR spacers mapping to an RNA virus been identified in any prokaryote. In this work, we were unable to identify any spacers derived from RNA viruses despite extensive metagenomic sampling of the extracellular environment. Such efforts could be stymied by the relatively small number of currently characterized RNA phage ([@B34], [@B39]).

Type III CRISPR-Cas systems can also mediate defense against transcriptionally active DNA phages ([@B40], [@B41]). The ability to acquire spacers from RNA could help direct CRISPR immunity toward phage transcripts that are expressed early in the infection cycle, and toward highly expressed phage genes. Spacer acquisition from RNA could also enable sampling of phage genomes that could be protected from DNA-targeting CRISPR-Cas nucleases through DNA modification ([@B42]). Furthermore, a transcription-dependent targeting mechanism could allow microbes to tolerate lysogenic viruses integrated stably in the host genome and yet have a ready response upon prophage induction ([@B20]). A broad search of the CRISPR spacers linked to RTs in all available prokaryotic genomes against all nonredundant protein records indeed yielded several matches to DNA phage-like sequences. These results suggest that the RT-mediated mechanism of spacer acquisition by CRISPR-Cas systems may be used at least in part to provide defense against transcriptionally active DNA-based parasites.

The origin of the CRISPR spacers is a general, unresolved problem. A substantial majority of the spacers in most CRISPR arrays (over 90% on average, according to the latest comprehensive survey \[[@B43]\]) have no detectable matches in known sequences. However, to our knowledge, very few spacer repertoires and associated metagenomes have been sequenced to the depth reported here for *A. platensis*. The extreme diversity of spacers, especially in the RT-linked arrays, combined with the effective lack of detectable protospacers, indicates that a key element is missing from our picture of CRISPR-Cas biology: the sources of the spacers remain enigmatic. Part of the problem could stem from the high rate of spacer loss and mutation and, likely, an even higher rate of mutational escape of viruses, which result in accumulation of mismatches between a spacer and its cognate protospacer, rendering the latter unrecognizable. Nevertheless, another cause of the lack of detectable protospacers is likely to be the existence of a virtually untapped pool of mobile genetic elements that, at any given time, are not represented in a given environment ([@B10]). This paucity of spacer matches is conceivably explained by the vastness and diversity of viromes combined with the rapid evolution of the (proto)spacers ([@B43]). Longitudinal studies on metagenomes could help characterize that vast and currently enigmatic sequence pool ([@B25], [@B36]).

MATERIALS AND METHODS {#s3}
=====================

Prokaryotic genome database and open reading frame annotation. {#s3.1}
--------------------------------------------------------------

Archaeal and bacterial complete and draft genome sequences were downloaded from the NCBI FTP site (<ftp://ftp.ncbi.nlm.nih.gov/genomes/all/>) in March 2016. For incompletely annotated genomes (coding density of less than 0.6 coding DNA sequences \[CDS\] per kbp), the existing annotation was discarded and replaced with a Meta-GeneMark 1 ([@B44]) annotation with the standard model MetaGeneMark_v1.mod (heuristic model for genetic code 11 and GC 30). Altogether, the database includes 4,961 completely sequenced and assembled genomes and 43,599 partially sequenced genomes. Profiles for RT families (cd01651, pfam00078, and COG3344) that are included in the NCBI CDD database ([@B45]) were used as queries for a PSI-BLAST search (e-value = 1e−4) to identify RT homologs. The RT genes were used as a seed to identify defense islands as described previously ([@B46]). All ORFs within loci were annotated using RPS-BLAST searches with 30,953 profiles (COG, pfam, cd) from the NCBI CDD database and 217 custom Cas protein profiles ([@B7]). The CRISPR-Cas system (sub)type identification for all loci was performed using previously described procedures ([@B7]).

Sequence clustering, alignment, and phylogenetic analyses. {#s3.2}
----------------------------------------------------------

To construct a nonredundant, representative RT sequence set, sequences were clustered using the NCBI BLASTCLUST program (<ftp://ftp.ncbi.nih.gov/blast/documents/blastclust.html>) with a sequence identity threshold of 90% and length coverage threshold of 0.9. Short fragments or disrupted sequences were discarded. Multiple alignments of protein sequences were constructed using MUSCLE ([@B47]). Sites with gap character fraction values of \>0.5 and homogeneity values of \<0.1 were removed from the alignment. Phylogenetic analysis was performed using the FastTree program ([@B48]), with the WAG evolutionary model and the discrete gamma model with 20 rate categories. The same program was used to compute SH (Shimodaira-Hasegawa)-like node support values.

High-throughput sequencing of CRISPR spacers. {#s3.3}
---------------------------------------------

This method is a slight modification of a previously published protocol for CRISPR spacer sequencing ([@B16]); we have provided the protocol in its entirety for completeness, retaining relevant text from the original protocol. CRISPR spacers were amplified by PCR from 1 to 2 ng genomic DNA per μl PCR mix using primers anchored in the various CRISPR repeat sequences. The primers used for type III-D CRISPR arrays were as follows: SS-4F, CGACGCTCTTCCGATCTNNNNN[CTTGCGGGGAATTGGTAGGG]{.ul}; SS-4R, ACTGACGCTAGTGCATCA[AATTCCCCGCAAGGGGACGG]{.ul}; SS-5F, CGACGCTCTTCCGATCTNNNNN[CCAATTCCCCGCAAGGGGAC]{.ul}; SS-5R, ACTGACGCTAGTGCATCA[TGCGGGGAATTGGTAGGGTC]{.ul}; SS-8F, CGACGCTCTTCCGATCTNNNNN[CCAATTCCCCGTCAGGGGAC]{.ul}; and SS-8R, ACTGACGCTAGTGCATCA[GACGGGGAATTGGTAGGGTT]{.ul}. The primers used for type III-B CRISPR arrays were as follows: SS-19F, CGACGCTCTTCCGATCTNNNNN[TAACTTTCARAGAAGTYTAA]{.ul}; SS-19R, ACTGACGCTAGTGCATCA[TGAAAGTTAAACGTATGGAA]{.ul}; SS-20F, CGACGCTCTTCCGATCTNNNNN[CGACTTTCAAAGAAGTCTCA]{.ul}; SS-20R, ACTGACGCTAGTGCATCA[TGAAAGTCGAACGTATGGCA]{.ul}; SS-51F, CGACGCTCTTCCGATCTNNNNN[TTCTYTGAAAGTTAAACGTA]{.ul}; and SS-51R, ACTGACGCTAGTGCATCA[TTTAACTTTCARAGAAGTTT]{.ul}. F and R denote forward and reverse primers. Primers with the same numeric code were used together. Letters correspond to IUPAC nucleic acid notation. CRISPR repeat matching regions are underlined.

Sequencing adaptors were then attached in a second round of PCR with 0.01 volumes of the previous reaction mixture as the template, using AF-SS-44:55 (CAAGCAGAAGACGGCATACGAGATNNNNNNNNGTGACTGGAGTTCAGACGTGTGCTCTTCCGATC[ACTGACGCTAGTGCATCA]{.ul}) and AF-KLA-67:74 (AATGATACGGCGACCACCGAGATCTACACNNNNNNNNACACTCTTTCCCTACA[CGACGCTCTTCCGATCT]{.ul}), where the (N)~8~ barcodes correspond to Illumina TruSeq HT indexes D701 to D712 (reverse complemented) and D501 to D508, respectively. Template-matching regions in primers are underlined. Phusion High-Fidelity PCR master mix with HF buffer (Fisher Scientific) was used for all reactions. Cycling conditions were as follows: 98°C for 1 min; 2 cycles of 98°C for 10 s (60°C for 20 s for primer pairs AF-SS-4, AF-SS-5, and AF-SS-8; 44°C for 20 s for primer pair AF-SS-19; 50°C for 20 s for primer pair AF-SS-20) and 72°C for 30 s; 18 cycles of 98°C for 15 s (70°C for 15 s for primer pairs AF-SS-4, AF-SS-5, and AF-SS-8; 63°C for 15 s for primer pair AF-SS-19; 66°C for 15 s for primer pair AF-SS-20) and 72°C for 30 s; and 72°C for 9 min for round 1, and 98°C for 1 min; 2 cycles of 98°C for 10 s, 54°C for 20 s, and 72°C for 30 s; 4 cycles of 98°C for 15 s, 70°C for 15 s, and 72°C for 30 s; and 72°C for 9 min for round 2. The dominant amplicons (250 to 275 bp) containing a mixture of spacer sequences were excised following agarose electrophoresis (3%, 4.2 V/cm, 2 h) of round 2 PCR products. Libraries were quantified by Qubit and sequenced with Illumina MiSeq v3 kits (150 cycles for read 1; 8 cycles for index 1; 8 cycles for index 2).

Spacers were trimmed from reads using a custom python script and were considered identical if they differed by only 1 nucleotide. Protospacers were mapped using Bowtie 2.0 (--very-sensitive-local alignments). These methods preserve strand information.

Preparation of cellular and extracellular fractions from *Spirulina* samples. {#s3.4}
-----------------------------------------------------------------------------

Prepackaged *Spirulina* samples were purchased from various vendors as described for [Fig. 1](#fig1){ref-type="fig"}. A similar probiotic blend containing a variety of plant matter but lacking *A. platensis* was also tested as a negative control for CRISPR spacer amplification.

*Spirulina* metagenomic samples were collected in 50-ml polypropylene centrifugal tubes (Corning) from open-air raceway ponds operated by Earthrise LLC, Calipatria, CA, and were transported on ice to our laboratory for processing the same day (without freezing). *Spirulina* at these farms is grown in an interconnected network of open-air ponds, containing approximately 1 million liters of water seeded with inorganic nutrients and injected with carbon dioxide to support the high growth rate of the enriched cyanobacterial culture. The culture is kept in continuous circulation between ponds using paddle wheels and is maintained continuously from April through October. Growth of unwanted "weed algae" is prevented by raising the pH of the culture to leverage the rare ability of *A. platensis* to grow in alkaline environments.

Cyanobacteria were pelleted from \~120 ml of pond water by centrifugation at 4,000 × *g* for 1 h (Beckman Allegra X-15R) (4°C). The supernatant was then divided into four 30-ml polypropylene high-speed centrifugal tubes (Nalgene Oak Ridge) and subjected to a preclearing spin at 12,000 × *g* for 1 h (Avanti J-25I centrifuge with JA-17 rotor; Beckman Coulter, Inc.) (4°C). The cleared sample was further subdivided into 15-ml open-top Polyallomer tubes (Seton), and extracellular material was collected by ultracentrifugation at 200,000 × *g* for 16 h (Optima XE-90 Ultracentrifuge with SW41 Ti rotor; Beckman Coulter, Inc.) (4°C) with and without prior filtration through a 0.45-µm-pore-size Polysulfone membrane (Pall Corp.).

Nucleic acid extraction from *Spirulina.* {#s3.5}
-----------------------------------------

The cyanobacteria marketed as *Spirulina* are typically subjected to cold compression into pellets sold as food supplements, or flash-dried and sold as a powder intended to be mixed into kitchen recipes. Genomic DNA would be expected to remain intact through the packaging process, which eschews heat and mechanical granulation. Genomic DNA was extracted from *Spirulina* grocery store samples and metagenomic cellular fractions as previously described ([@B49]). RNA was extracted from *Spirulina* grocery store samples and metagenomic cellular fractions using a combined TRIzol/RNeasy method ([@B16]).

DNA extractions from metagenomic extracellular fractions were performed using a modified SDS/protease K method. Briefly, pellets were resuspended in 100 μl of lysis buffer (10 mM Tris, 20 mM EDTA, 50 μg/ml protease K, 0.5% SDS) and incubated at 56°C for 1 h. DNA was precipitated with the addition of isopropanol at up to 50% of the total volume. DNA pellets were washed with 70% ethanol and resuspended in 10 mM Tris (Qiagen) (pH 8.5). Metagenomic extracellular DNA samples were prepared by two methods: with and without RQ1 RNase-Free DNase (Promega) pretreatment of the ultracentrifuged pellet (per the manufacturer's instructions). The data obtained through the two methods were similar.

RNA samples from metagenomic extracellular fractions were prepared by two methods: with and without RQ1 DNase pretreatment of the ultracentrifuged pellet. RNA was extracted from the pellets using TRIzol (Life Technologies, Inc.) per the manufacturer's instructions. Purified RNA was treated with RQ1 RNase-Free DNase, which was subsequently removed by extraction performed with a 1:1 mixture of acidified phenol (Ambion) and chloroform (Fisher Scientific), followed by an extraction performed with chloroform and precipitation of RNA from the aqueous phase through the addition of ethanol at up to 70% of the total volume. RNA pellets were washed with 70% ethanol and resuspended in RNase-free water (Qiagen).

DNA sequencing of *Spirulina* samples. {#s3.6}
--------------------------------------

Genomic DNA extracted from *Spirulina* grocery store samples and metagenomic cellular fractions was prepared for high-throughput sequencing using a Nextera DNA Library Prep kit (Illumina) according to the manufacturer's instructions.

RNA sequencing of *Spirulina* samples. {#s3.7}
--------------------------------------

Three different methods were employed for RNA sequencing. The first was described previously ([@B16]); this method provides unbiased sequencing, especially of shorter RNA fragments that may be missed by other protocols. The second was carried out according to the instructions provided with a SMARTer Stranded RNA-Seq kit (Clontech); this method was especially useful in generating libraries from low-concentration RNA samples (e.g., *Spirulina* metagenome extracellular RNA fractions). The third method was developed previously in our laboratory for detecting low-abundance RNA species. Up to 100 ng of RNA was diluted to 6 μl in RNase-free water and incubated at 90°C for 1 min and then at 70°C for 4 min and was transferred to ice for 2 min. A 13.5-μl volume of reverse transcription master mix (4 μl 5x First Strand buffer, 2 μl 0.1 M dithiothreitol, 2 μl 10 mM deoxynucleoside triphosphate \[dNTP\] mix, 1 μl RNase-Out, 1.5 μl Superscript II reverse transcriptase, 3 μl RNase-free water \[all components from Life Technologies, Inc.\]) was added to each sample, and the mixture was incubated at 42°C for 30 min. A 0.5-μl volume of 100 ng/μl exonuclease-resistant random hexamers (Fisher Scientific) was then added, and the reaction mixtures were incubated at 25°C for 2 min and at 42°C for an additional 60 min. The reaction was terminated by heating to 95°C for 5 min. Subsequently, 127.5 μl of multiple-displacement amplification (MDA) master mix (6 μl of 25 mM dNTP mix \[Roche\], 15 μl of 10x Phi29 DNA polymerase reaction buffer \[NEB\], 7.5 μl of 1 μg/μl exonuclease-resistant random hexamers, 7.5 μl of 0.1 M dithiothreitol, 93 μl of RNase-free water) was added to each reaction, and the mixture was split into 3 tubes at 47.5 μl each and incubated at 95°C for 5 min and then at 4°C during the addition of 2.5 μl of Phi29 DNA polymerase (NEB) to each tube. The reaction mixtures were incubated at 30°C for 6 to 8 h. The MDA product was purified using Zymo DNA clean-and-concentrator columns and prepared for sequencing using a Nextera DNA Library Prep kit.

RNA from cellular fractions of the *Spirulina* metagenome was sequenced using all three methods. RNA samples from extracellular fractions (with and without filtration using 0.45-µm-pore-size filters and with and without DNase treatment) were sequenced using only the SMARTer Stranded and MDA methods as there was not enough input material for the small-RNA sequencing method described in reference [@B16]. The samples processed via the SMARTer Stranded protocol were prepared with and without the built-in RNA fragmentation step in an effort to capture shorter RNA fragments.

Computational analyses of *Spirulina* datasets. {#s3.8}
-----------------------------------------------

CRISPR spacers were trimmed from high-throughput sequencing reads and clustered to account for sequencing errors, with 1 allowed mismatch on the Illumina MiSeq platform and 2 allowed mismatches on the Illumina HiSeq platform. All searches for sources of spacer sequences were carried out using NCBI blast package 2.2.25, with a culling limit of 1 and an empirically determined e-value cutoff for each dataset to minimize false negatives as reported in the text. Blast databases were formatted using formatdb. Preformatted nucleic acid datasets (NT; nucleotide collection; posted 9 February 2013) and protein datasets (NR; ll nonredundant GenBank CDS translations plus PDB plus SwissProt plus PIR plus PRF, excluding environmental samples from whole-genome sequencing \[WGS\] projects; posted 13 March 2015) were obtained from NCBI. HMM searches for RdRP-related ORFs were carried out using HMMER 3.1 ([@B50]), and phage-like contigs were identified using the PHASTER online interface ([@B51]). Contigs were assembled using both Velvet 1.1.07 (velveth run with a maximum Kmer length of 31 and velvetg with a minimum contig size of 200) ([@B52]) and SPAdes 3.7.1 ([@B53]) in metagenomic mode. Alignments of metagenomic sequencing reads and CRISPR spacers to the reference genome(s) were carried out using bowtie 2.2.6 using the --very-sensitive-local option. The bedtools 2.25.0 merge program was used to collapse redundant alignments on the basis of the location. Custom python scripts were written for "greedy" spacer assembly, clustering of spacer sequences, translation of putative ORFs in metagenomic contigs, and curation of BLAST result files.

Metagenomic protospacer analysis. {#s3.9}
---------------------------------

For broader metagenomic searches, the CRISPRfinder ([@B54]) and PILER-CR ([@B55]) programs were used with default parameters to identify CRISPR arrays found in Cas7f and TnsA/TnsD loci. The MEGABLAST program ([@B56]) (word size, 18; otherwise, default parameters) was used to search for protospacers in the virus subset of NR database and the prokaryotic genome database. We considered only those matches with 95% identity and 95% length coverage or better with respect to the NR database.

Accession number(s). {#s3.10}
--------------------

Sequencing data have been deposited at SRA ([SRP107814](http://www.ncbi.nlm.nih.gov/sra/SRP107814)).

**Citation** Silas S, Makarova KS, Shmakov S, Páez-Espino D, Mohr G, Liu Y, Davison M, Roux S, Krishnamurthy SR, Fu BXH, Hansen LL, Wang D, Sullivan MB, Millard A, Clokie MR, Bhaya D, Lambowitz AM, Kyrpides NC, Koonin EV, Fire AZ. 2017. On the origin of reverse transcriptase-using CRISPR-Cas systems and their hyperdiverse, enigmatic spacer repertoires. mBio 8:e00897-17. <https://doi.org/10.1128/mBio.00897-17>.

We thank Earthrise Nutritionals LLC, A. Belay, and laboratory colleagues for help and advice.

S. Silas was supported by a Stanford Graduate Fellowship and an HHMI International Student Research Fellowship. K. S. Makarova, S. Shmakov, and E. V. Koonin are supported by the Intramural Program of the U.S. Department of Health and Human Services (via funds provided to the National Library of Medicine). D. Paez-Espino and N. C. Kyrpides were supported by the U.S. Department of Energy Joint Genome Institute, a DOE Office of Science User Facility, under contract number DE-AC02-05CH11231.

This research was supported by grant NIH R01-GM37706 to A. Z. Fire and grant NIH R01-GM37949 to A. M. Lambowitz. The funders had no role in study design, data collection and interpretation, or the decision to submit the work for publication.


Q:

Android - change Launcher Icon Language

I want add a settings for language to my app which is independent from system language.
I could manage to change language of anything but the launcher icon is still in system language.
Is it possible anyhow to change that icon language?
Metin

A:

Let's say that you are supporting N languages with this dubious feature.
You will need N entries in your manifest for the launcher activity. Each of those N entries will need an android:label pointing to a string that represents what you want displayed when your app is configured for -such-and-so language. You would then use PackageManager and setComponentEnabledSetting() to disable the old activity and enable the new one.
It is conceivable that you could use one <activity> element and N <activity-alias> elements to achieve your objective, but I am uncertain as to whether you can enable and disable activity aliases.


Long-term survival of patients with stage IV hypopharyngeal cancer: impact of fundus rotation gastroplasty.
Stage IV circular hypopharyngeal cancer is a disease with poor long-term survival, and the only means of cure-surgery-is associated with high morbidity. All patients admitted with circular hypopharyngeal cancer and extension to the esophagus were enrolled in a multidisciplinary treatment protocol, including circular laryngopharyngoesophagectomy with tracheostomy, neck dissection, and pull-up of a fundus rotation gastric tube that was anastomosed to the oropharynx. Five weeks postoperatively high-dose radiotherapy (60 Gy) was given to the cervical region. Altogether, 18 qualifying patients were explored cervically, were found to have resectable lesions (i.e., without carotid artery infiltration), and were included in the protocol. After laryngopharyngoesophagectomy, an elongated gastric tube was pulled up to the oropharynx. The average distance bridged with the tube was 32 +/- 4 cm. No anastomotic leaks were found on postoperative Gastrografin swallow, and oral feeding was started between days 5 and 8. Patients were discharged with normal oral feeding on day 21 (+/- 17 days). Diarrhea, postprandial fullness, and reflux resolved within 6 months postoperatively. Five patients died during the follow-up period of 42 months (range 3-63 months): three due to cardiac events 18 and 38 months postoperatively and two within 12 months with residual disease and tumor recurrence, respectively. The estimated 5-year survival was 60%. We concluded that an aggressive multidisciplinary approach including circular laryngopharyngoesophagectomy, neck dissection, and high-dose radiotherapy ascertains good long-term survival and good functional results in patients with advanced hypopharyngeal cancer when the intestinal continuity is reconstructed with a fundus rotation gastroplasty.


Edna’s Coffee – Decaf

$7.25–$13.25

Edna’s Coffee is a gourmet coffee with a unique flavor. The way Edna’s Coffee is prepared is as unique as its flavor. The coffee is prepared with the use of an espresso machine Steamer also known as a “Jazve.” “Demitasse” coffee cups, similar to espresso cups, are used to serve the coffee.


I’ve been thinking about the effect of transience in a longer work of fiction (or music, or whatever) — when a particular and particularly subtle moment is called into significance precisely through its briefness — and how hard it is to do well.

The problem is that it takes a lot of work, and a lot of content, to buttress a single moment to the point where it’s effectively transient. If you have one transient moment in a work that’s composed of similarly passing moments, then its transience is lost — it’s more a pulse in a rhythm, say. But when the world of a work is strong enough that something specific sticks out, the effect can be very poignant.

Let me give a few examples that will, hopefully, show why a transient moment can be such an interesting structural specimen.

Joyce’s “The Dead”

In the ending section of Joyce’s famous short story, Gretta, the wife of protagonist Gabriel, admits that a song they heard earlier in the night recalls to her a lost love — a boy who died for her. He coaxes a few aloof details from his wife (“He was in the gasworks,” she admits), and finally indulging her coldly, asks for the story:

“I think he died for me,” she answered.

A vague terror seized Gabriel at this answer, as if, at that hour when he had hoped to triumph, some impalpable and vindictive being was coming against him, gathering forces against him in its vague world.

The idea is that a whole world — his wife’s past, and her past passions — have come vividly and inaccessibly to life. At once in the same fleeting confession, Gabriel gets a glimpse into his wife’s secret past, and senses his distance from it.

This is what I really mean when I refer to transience. “The Dead” is a long story — some 15,000 words — that details an entire Christmas party with all its characters and exchanges. But the core of the story’s sense of loss and absence is disclosed in a brief and reluctant confession.

Mozart’s 40th Symphony, Finale

This is the example that inspired this blog entry. In an interview with pianist Glenn Gould about Mozart (which I can’t find online anymore! Frustrating!), Gould describes a passage from the last movement of Mozart’s 40th Symphony as an “oasis in a desert of cliches” (I think). It’s a very short, sharp transitional passage (from the exposition to the development) where every one of the twelve notes is played except the G of the piece’s G Minor key.

Here’s the passage, at 3:57, but rewind a little for some ambience:

This is kind of a weird example because the phrase doesn’t recur through the piece, so it sticks out like a sore thumb. It serves a transitional role through sheer contrast.

Proust’s In Search of Lost Time

This might be the most famous example of transience in art. Proust’s long fictional recollection is kicked off when the narrator, Marcel, enjoys a madeleine soaked in tea. One passing sensation — the taste, the scent of lime blossom — kicks off the whole enormous exploration of the past.

The structural trick here is interesting because it’s a reversal of what you might expect. The transient moment unfolds into the entire story. It’s a passing occurrence, but it’s not set against anything that came before — it’s the foundation of what follows.

The Simpsons, “The Way We Was”

In the first Simpsons flashback episode, there’s a moment where even in retrospect, Marge and Homer’s whole future together threatens not to be. Homer tricks Marge into a date to prom, she finds out she was deceived (Homer didn’t really need French lessons), and she dumps him to go with Artie Ziff instead. Marge finds Homer weeping in the hall at prom:

Homer: I’m sure we were meant to be together. Usually when I have a thought, there’s a lot of other thoughts in there — some things say yes, some things say no. But this time, there’s only yes! How can the one thing I’ve never been more sure about in my life be wrong?

Marge Simpson: Hm. I don’t know. But it is.

Homer and Marge not together at prom

What makes this scene so affecting is that (if you’re like me) you’ve seen Homer and Marge’s years together so many times that a moment like this — one that threatens to replace the couple’s many experiences with an abyss — is deeply unsettling.

Here, the keen sadness of Homer and Marge’s estrangement is made possible by all the time spent in episodes where their life together is taken for granted. With all that narrative work put into everything else in their lives — work, kids, hijinks — this foundational wobble is scary. It’s like watching Marty disappear from that photo of himself in Back to the Future.

Counterintuitively, it takes a lot of work to pull off a fleeting feeling in a work of fiction. The problem is that fleeting moments run against the grain of selective moments in storytelling. It’s impossible to convey the whole sturdy breadth of experience in writing, so the necessary shortcuts — of selective detail and precision — would seem to shutter creative possibilities that depend on life’s bulk. So when Gabriel’s life is successfully turned upside-down in “The Dead”, for example, that’s an impressive achievement. He never had a life to begin with! And yet Joyce created one so he could undermine it.


Q:

How can I keep guacamole from turning brown?

Even though a I put plastic wrap over a bowl of guacamole, it seems it's never tight enough, and the top layer of the guacamole turns brown, which sometimes changes the taste.
Is there any way I can keep my guacamole from oxidising in the fridge?

A:

As has been mentioned here (including a few times by me), this question has been discussed on Cooking.SE here.
Since I wrote that answer, I have done further experimentation and have found that adding Vitamin C in the concentration of 100mg to 50 grams of avocado will keep the avocado green for days, even exposed to air in a normal sealed tupperware and even in the face of lemon, lime, or vinegar; all of which speed the browning of avocados. The efficacy data of Vitamin C and propanethiol S-oxide gas, caused by diced onions, will be added to that answer.
EDIT I actually ended up writing a new answer after quite of back and forth about how best to handle it. So, it's a bit later than I had hoped, but it's here

A:

I'm sorry, but I have to contradict Cathie's answer:

Which acid works best to keep avocados from browning?
Answer: None (of the acids tested)
It's not that acid doesn't do much to help.
ALL OF THE ACIDS TESTED CAUSED AVOCADOS TO BECOME MORE BROWN AND TO
  BECOME BROWN FASTER THAN NO TREATMENT AT ALL

Source: An answer by  Jolenealaska at cooking.SE.
The pit acts as a oxygen-barrier, not as a preservative. You could use wrapping film instead.


CYBERFIRST BURSARY SCHEME Various

Find out more and apply


Q:

Download a file from ftp subdirectories using cmd script

I was trying to download multiple files from our ftp server using the script:
mget cd\dir_here\subdir_here\sample*.txt

but it didn't work so I tried to change to back slash:
mget cd/dir_here/subdir_here/sample*.txt

a message

Type set to A

appeared. What does that mean?

A:

Type set to A

This means that you've told the FTP server you will be transferring by ASCII.
You almost never actually want to do ASCII, it is better to make a habit of using Binary for all transfers.  (ASCII breaks the chain of custody, ASCII transfers can modify file contents such as changing New line characters and not sending correct Unicode characters and are completely unsuited to binary file contents, while the speed benefits are trivial.)
You want to make sure your FTP script uses commands separately it looks like you put a CD along with an MGet here...?
Example FTP Script:
user USERNAME PASSWORD
binary
lcd C:\Local\File\System\Folder
cd /root/dir_here/subdir_here
mget sample*.txt
quit

This would be in a script file which would be specified in the FTP command when you call it from the command line or from a script.
eg:
ftp -n -i -v "-s:C:\Local\Path\To\FTP\Script.txt" SERVER_IP


This is what Taco Cabana's new restaurants will look like, inspired by San Antonio

The new prototype for Taco Cabana's restaurants draws inspiration from the interior of Mexico and Alamo City artists have helped design and fill the walls with authentic-style architecture and photography. The new prototype for Taco Cabana's restaurants draws inspiration from the interior of Mexico and Alamo City artists have helped design and fill the walls with authentic-style architecture and photography. Photo: San Antonio Express-News Photo: San Antonio Express-News Image 1 of / 42 Caption Close This is what Taco Cabana's new restaurants will look like, inspired by San Antonio 1 / 42 Back to Gallery

SAN ANTONIO — The new prototype for Taco Cabana's restaurants draws inspiration from the interior of Mexico and Alamo City artists have helped design and fill the walls with authentic-style architecture and photography.

The first San Antonio restaurant in the new design opened this week on the Northwest Side near Loop 1604 and UTSA campus. Each of the restaurants' nearly 200 locations will undergo remodeling in the next year to resemble the prototype, which will be the model for all new locations, said Todd Coerver, Taco Cabana's chief operating officer.

"We wanted to echo that modern Mexico feel throughout the restaurant," he said. "There's not anything like it out there."

Coerver and a exploratory committee from the restaurant traveled to Mexico to draw inspiration for architecture, furniture, music and new recipes, Coerver said.

New features include a Mexican modernist building design, slit windows, photographs shot by the late San Antonio photographer Rick Hunter on the streets of Mexico, music from Mexican artists and furniture and lighting imported from the United States' southern neighbor.

Coerver said the restaurant wanted to convey the patio feel to the inside of the restaurant with stone columns, string lighting and metal trimmed in the style of papel picado throughout the restaurant.

There are about 45 Taco Cabana restaurants in the San Antonio area and the first Taco Cabana, which is still in operation, opened on San Pedro and Hildebrand in 1978.

The design for the outside of the building was developed by Davis Sprinkle, a San Antonio architect who worked with the revered Mexican architect Ricardo Legorreta on the enchilada red Central Public Library.

The Dallas-Fort Worth area has eight locations in the new style and Houston has one.

kparker@express-news.net

Twitter: @KoltenParker


//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the AliasSetTracker and AliasSet classes.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Type.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

static cl::opt<unsigned>
    SaturationThreshold("alias-set-saturation-threshold", cl::Hidden,
                        cl::init(250),
                        cl::desc("The maximum number of pointers may-alias "
                                 "sets may contain before degradation"));

/// mergeSetIn - Merge the specified alias set into this alias set.
///
void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) {
  assert(!AS.Forward && "Alias set is already forwarding!");
  assert(!Forward && "This set is a forwarding set!!");

  bool WasMustAlias = (Alias == SetMustAlias);
  // Update the alias and access types of this set...
  Access |= AS.Access;
  Alias  |= AS.Alias;
  Volatile |= AS.Volatile;

  if (Alias == SetMustAlias) {
    // Check that these two merged sets really are must aliases.  Since both
    // used to be must-alias sets, we can just check any pointer from each set
    // for aliasing.
    AliasAnalysis &AA = AST.getAliasAnalysis();
    PointerRec *L = getSomePointer();
    PointerRec *R = AS.getSomePointer();

    // If the pointers are not a must-alias pair, this set becomes a may alias.
    if (AA.alias(MemoryLocation(L->getValue(), L->getSize(), L->getAAInfo()),
                 MemoryLocation(R->getValue(), R->getSize(), R->getAAInfo())) !=
        MustAlias)
      Alias = SetMayAlias;
  }

  if (Alias == SetMayAlias) {
    if (WasMustAlias)
      AST.TotalMayAliasSetSize += size();
    if (AS.Alias == SetMustAlias)
      AST.TotalMayAliasSetSize += AS.size();
  }

  bool ASHadUnknownInsts = !AS.UnknownInsts.empty();
  if (UnknownInsts.empty()) {            // Merge call sites...
    if (ASHadUnknownInsts) {
      std::swap(UnknownInsts, AS.UnknownInsts);
      addRef();
    }
  } else if (ASHadUnknownInsts) {
    UnknownInsts.insert(UnknownInsts.end(), AS.UnknownInsts.begin(), AS.UnknownInsts.end());
    AS.UnknownInsts.clear();
  }

  AS.Forward = this; // Forward across AS now...
  addRef();          // AS is now pointing to us...

  // Merge the list of constituent pointers...
  if (AS.PtrList) {
    SetSize += AS.size();
    AS.SetSize = 0;
    *PtrListEnd = AS.PtrList;
    AS.PtrList->setPrevInList(PtrListEnd);
    PtrListEnd = AS.PtrListEnd;

    AS.PtrList = nullptr;
    AS.PtrListEnd = &AS.PtrList;
    assert(*AS.PtrListEnd == nullptr && "End of list is not null?");
  }
  if (ASHadUnknownInsts)
    AS.dropRef(AST);
}

void AliasSetTracker::removeAliasSet(AliasSet *AS) {
  if (AliasSet *Fwd = AS->Forward) {
    Fwd->dropRef(*this);
    AS->Forward = nullptr;
  }

  if (AS->Alias == AliasSet::SetMayAlias)
    TotalMayAliasSetSize -= AS->size();

  AliasSets.erase(AS);

}

void AliasSet::removeFromTracker(AliasSetTracker &AST) {
  assert(RefCount == 0 && "Cannot remove non-dead alias set from tracker!");
  AST.removeAliasSet(this);
}

void AliasSet::addPointer(AliasSetTracker &AST, PointerRec &Entry,
                          uint64_t Size, const AAMDNodes &AAInfo,
                          bool KnownMustAlias) {
  assert(!Entry.hasAliasSet() && "Entry already in set!");

  // Check to see if we have to downgrade to _may_ alias.
  if (isMustAlias() && !KnownMustAlias)
    if (PointerRec *P = getSomePointer()) {
      AliasAnalysis &AA = AST.getAliasAnalysis();
      AliasResult Result =
          AA.alias(MemoryLocation(P->getValue(), P->getSize(), P->getAAInfo()),
                   MemoryLocation(Entry.getValue(), Size, AAInfo));
      if (Result != MustAlias) {
        Alias = SetMayAlias;
        AST.TotalMayAliasSetSize += size();
      } else {
        // First entry of must alias must have maximum size!
        P->updateSizeAndAAInfo(Size, AAInfo);
      }
      assert(Result != NoAlias && "Cannot be part of must set!");
    }

  Entry.setAliasSet(this);
  Entry.updateSizeAndAAInfo(Size, AAInfo);

  // Add it to the end of the list...
  ++SetSize;
  assert(*PtrListEnd == nullptr && "End of list is not null?");
  *PtrListEnd = &Entry;
  PtrListEnd = Entry.setPrevInList(PtrListEnd);
  assert(*PtrListEnd == nullptr && "End of list is not null?");
  // Entry points to alias set.
  addRef();

  if (Alias == SetMayAlias)
    AST.TotalMayAliasSetSize++;
}

void AliasSet::addUnknownInst(Instruction *I, AliasAnalysis &AA) {
  if (UnknownInsts.empty())
    addRef();
  UnknownInsts.emplace_back(I);

  if (!I->mayWriteToMemory()) {
    Alias = SetMayAlias;
    Access |= RefAccess;
    return;
  }

  // FIXME: This should use mod/ref information to make this not suck so bad
  Alias = SetMayAlias;
  Access = ModRefAccess;
}

/// aliasesPointer - Return true if the specified pointer "may" (or must)
/// alias one of the members in the set.
///
bool AliasSet::aliasesPointer(const Value *Ptr, uint64_t Size,
                              const AAMDNodes &AAInfo,
                              AliasAnalysis &AA) const {
  if (AliasAny)
    return true;

  if (Alias == SetMustAlias) {
    assert(UnknownInsts.empty() && "Illegal must alias set!");

    // If this is a set of MustAliases, only check to see if the pointer aliases
    // SOME value in the set.
    PointerRec *SomePtr = getSomePointer();
    assert(SomePtr && "Empty must-alias set??");
    return AA.alias(MemoryLocation(SomePtr->getValue(), SomePtr->getSize(),
                                   SomePtr->getAAInfo()),
                    MemoryLocation(Ptr, Size, AAInfo));
  }

  // If this is a may-alias set, we have to check all of the pointers in the set
  // to be sure it doesn't alias the set...
  for (iterator I = begin(), E = end(); I != E; ++I)
    if (AA.alias(MemoryLocation(Ptr, Size, AAInfo),
                 MemoryLocation(I.getPointer(), I.getSize(), I.getAAInfo())))
      return true;

  // Check the unknown instructions...
  if (!UnknownInsts.empty()) {
    for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i)
      if (AA.getModRefInfo(UnknownInsts[i],
                           MemoryLocation(Ptr, Size, AAInfo)) != MRI_NoModRef)
        return true;
  }

  return false;
}

bool AliasSet::aliasesUnknownInst(const Instruction *Inst,
                                  AliasAnalysis &AA) const {

  if (AliasAny)
    return true;

  if (!Inst->mayReadOrWriteMemory())
    return false;

  for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) {
    ImmutableCallSite C1(getUnknownInst(i)), C2(Inst);
    if (!C1 || !C2 || AA.getModRefInfo(C1, C2) != MRI_NoModRef ||
        AA.getModRefInfo(C2, C1) != MRI_NoModRef)
      return true;
  }

  for (iterator I = begin(), E = end(); I != E; ++I)
    if (AA.getModRefInfo(Inst, MemoryLocation(I.getPointer(), I.getSize(),
                                              I.getAAInfo())) != MRI_NoModRef)
      return true;

  return false;
}

void AliasSetTracker::clear() {
  // Delete all the PointerRec entries.
  for (PointerMapType::iterator I = PointerMap.begin(), E = PointerMap.end();
       I != E; ++I)
    I->second->eraseFromList();

  PointerMap.clear();

  // The alias sets should all be clear now.
  AliasSets.clear();
}

/// mergeAliasSetsForPointer - Given a pointer, merge all alias sets that may
/// alias the pointer. Return the unified set, or nullptr if no set that aliases
/// the pointer was found.
AliasSet *AliasSetTracker::mergeAliasSetsForPointer(const Value *Ptr,
                                                    uint64_t Size,
                                                    const AAMDNodes &AAInfo) {
  AliasSet *FoundSet = nullptr;
  for (iterator I = begin(), E = end(); I != E;) {
    iterator Cur = I++;
    if (Cur->Forward || !Cur->aliasesPointer(Ptr, Size, AAInfo, AA)) continue;

    if (!FoundSet) {      // If this is the first alias set ptr can go into.
      FoundSet = &*Cur;   // Remember it.
    } else {              // Otherwise, we must merge the sets.
      FoundSet->mergeSetIn(*Cur, *this);     // Merge in contents.
    }
  }

  return FoundSet;
}

bool AliasSetTracker::containsUnknown(const Instruction *Inst) const {
  for (const AliasSet &AS : *this)
    if (!AS.Forward && AS.aliasesUnknownInst(Inst, AA))
      return true;
  return false;
}

AliasSet *AliasSetTracker::findAliasSetForUnknownInst(Instruction *Inst) {
  AliasSet *FoundSet = nullptr;
  for (iterator I = begin(), E = end(); I != E;) {
    iterator Cur = I++;
    if (Cur->Forward || !Cur->aliasesUnknownInst(Inst, AA))
      continue;
    if (!FoundSet)            // If this is the first alias set ptr can go into.
      FoundSet = &*Cur;       // Remember it.
    else if (!Cur->Forward)   // Otherwise, we must merge the sets.
      FoundSet->mergeSetIn(*Cur, *this);     // Merge in contents.
  }
  return FoundSet;
}

/// getAliasSetForPointer - Return the alias set that the specified pointer
/// lives in.
AliasSet &AliasSetTracker::getAliasSetForPointer(Value *Pointer, uint64_t Size,
                                                 const AAMDNodes &AAInfo) {
  AliasSet::PointerRec &Entry = getEntryFor(Pointer);

  if (AliasAnyAS) {
    // At this point, the AST is saturated, so we only have one active alias
    // set. That means we already know which alias set we want to return, and
    // just need to add the pointer to that set to keep the data structure
    // consistent.
    // This, of course, means that we will never need a merge here.
    if (Entry.hasAliasSet()) {
      Entry.updateSizeAndAAInfo(Size, AAInfo);
      assert(Entry.getAliasSet(*this) == AliasAnyAS &&
             "Entry in saturated AST must belong to only alias set");
    } else {
      AliasAnyAS->addPointer(*this, Entry, Size, AAInfo);
    }
    return *AliasAnyAS;
  }

  // Check to see if the pointer is already known.
  if (Entry.hasAliasSet()) {
    // If the size changed, we may need to merge several alias sets.
    // Note that we can *not* return the result of mergeAliasSetsForPointer
    // due to a quirk of alias analysis behavior. Since alias(undef, undef)
    // is NoAlias, mergeAliasSetsForPointer(undef, ...) will not find the
    // the right set for undef, even if it exists.
    if (Entry.updateSizeAndAAInfo(Size, AAInfo))
      mergeAliasSetsForPointer(Pointer, Size, AAInfo);
    // Return the set!
    return *Entry.getAliasSet(*this)->getForwardedTarget(*this);
  }

  if (AliasSet *AS = mergeAliasSetsForPointer(Pointer, Size, AAInfo)) {
    // Add it to the alias set it aliases.
    AS->addPointer(*this, Entry, Size, AAInfo);
    return *AS;
  }

  // Otherwise create a new alias set to hold the loaded pointer.
  AliasSets.push_back(new AliasSet());
  AliasSets.back().addPointer(*this, Entry, Size, AAInfo);
  return AliasSets.back();
}

void AliasSetTracker::add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo) {
  addPointer(Ptr, Size, AAInfo, AliasSet::NoAccess);
}

void AliasSetTracker::add(LoadInst *LI) {
  if (isStrongerThanMonotonic(LI->getOrdering())) return addUnknown(LI);

  AAMDNodes AAInfo;
  LI->getAAMetadata(AAInfo);

  AliasSet::AccessLattice Access = AliasSet::RefAccess;
  const DataLayout &DL = LI->getModule()->getDataLayout();
  AliasSet &AS = addPointer(LI->getOperand(0),
                            DL.getTypeStoreSize(LI->getType()), AAInfo, Access);
  if (LI->isVolatile()) AS.setVolatile();
}

void AliasSetTracker::add(StoreInst *SI) {
  if (isStrongerThanMonotonic(SI->getOrdering())) return addUnknown(SI);

  AAMDNodes AAInfo;
  SI->getAAMetadata(AAInfo);

  AliasSet::AccessLattice Access = AliasSet::ModAccess;
  const DataLayout &DL = SI->getModule()->getDataLayout();
  Value *Val = SI->getOperand(0);
  AliasSet &AS = addPointer(
      SI->getOperand(1), DL.getTypeStoreSize(Val->getType()), AAInfo, Access);
  if (SI->isVolatile()) AS.setVolatile();
}

void AliasSetTracker::add(VAArgInst *VAAI) {
  AAMDNodes AAInfo;
  VAAI->getAAMetadata(AAInfo);

  addPointer(VAAI->getOperand(0), MemoryLocation::UnknownSize, AAInfo,
             AliasSet::ModRefAccess);
}

void AliasSetTracker::add(MemSetInst *MSI) {
  AAMDNodes AAInfo;
  MSI->getAAMetadata(AAInfo);

  uint64_t Len;

  if (ConstantInt *C = dyn_cast<ConstantInt>(MSI->getLength()))
    Len = C->getZExtValue();
  else
    Len = MemoryLocation::UnknownSize;

  AliasSet &AS =
      addPointer(MSI->getRawDest(), Len, AAInfo, AliasSet::ModAccess);
  if (MSI->isVolatile())
    AS.setVolatile();
}

void AliasSetTracker::add(MemTransferInst *MTI) {
  AAMDNodes AAInfo;
  MTI->getAAMetadata(AAInfo);

  uint64_t Len;
  if (ConstantInt *C = dyn_cast<ConstantInt>(MTI->getLength()))
    Len = C->getZExtValue();
  else
    Len = MemoryLocation::UnknownSize;

  AliasSet &ASSrc =
      addPointer(MTI->getRawSource(), Len, AAInfo, AliasSet::RefAccess);
  if (MTI->isVolatile())
    ASSrc.setVolatile();

  AliasSet &ASDst =
      addPointer(MTI->getRawDest(), Len, AAInfo, AliasSet::ModAccess);
  if (MTI->isVolatile())
    ASDst.setVolatile();
}

void AliasSetTracker::addUnknown(Instruction *Inst) {
  if (isa<DbgInfoIntrinsic>(Inst))
    return; // Ignore DbgInfo Intrinsics.

  if (auto *II = dyn_cast<IntrinsicInst>(Inst)) {
    // These intrinsics will show up as affecting memory, but they are just
    // markers.
    switch (II->getIntrinsicID()) {
    default:
      break;
      // FIXME: Add lifetime/invariant intrinsics (See: PR30807).
    case Intrinsic::assume:
      return;
    }
  }
  if (!Inst->mayReadOrWriteMemory())
    return; // doesn't alias anything

  AliasSet *AS = findAliasSetForUnknownInst(Inst);
  if (AS) {
    AS->addUnknownInst(Inst, AA);
    return;
  }
  AliasSets.push_back(new AliasSet());
  AS = &AliasSets.back();
  AS->addUnknownInst(Inst, AA);
}

void AliasSetTracker::add(Instruction *I) {
  // Dispatch to one of the other add methods.
  if (LoadInst *LI = dyn_cast<LoadInst>(I))
    return add(LI);
  if (StoreInst *SI = dyn_cast<StoreInst>(I))
    return add(SI);
  if (VAArgInst *VAAI = dyn_cast<VAArgInst>(I))
    return add(VAAI);
  if (MemSetInst *MSI = dyn_cast<MemSetInst>(I))
    return add(MSI);
  if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(I))
    return add(MTI);
  return addUnknown(I);
}

void AliasSetTracker::add(BasicBlock &BB) {
  for (auto &I : BB)
    add(&I);
}

void AliasSetTracker::add(const AliasSetTracker &AST) {
  assert(&AA == &AST.AA &&
         "Merging AliasSetTracker objects with different Alias Analyses!");

  // Loop over all of the alias sets in AST, adding the pointers contained
  // therein into the current alias sets.  This can cause alias sets to be
  // merged together in the current AST.
  for (const AliasSet &AS : AST) {
    if (AS.Forward)
      continue; // Ignore forwarding alias sets

    // If there are any call sites in the alias set, add them to this AST.
    for (unsigned i = 0, e = AS.UnknownInsts.size(); i != e; ++i)
      add(AS.UnknownInsts[i]);

    // Loop over all of the pointers in this alias set.
    for (AliasSet::iterator ASI = AS.begin(), E = AS.end(); ASI != E; ++ASI) {
      AliasSet &NewAS =
          addPointer(ASI.getPointer(), ASI.getSize(), ASI.getAAInfo(),
                     (AliasSet::AccessLattice)AS.Access);
      if (AS.isVolatile()) NewAS.setVolatile();
    }
  }
}

// deleteValue method - This method is used to remove a pointer value from the
// AliasSetTracker entirely.  It should be used when an instruction is deleted
// from the program to update the AST.  If you don't use this, you would have
// dangling pointers to deleted instructions.
//
void AliasSetTracker::deleteValue(Value *PtrVal) {
  // If this is a call instruction, remove the callsite from the appropriate
  // AliasSet (if present).
  if (Instruction *Inst = dyn_cast<Instruction>(PtrVal)) {
    if (Inst->mayReadOrWriteMemory()) {
      // Scan all the alias sets to see if this call site is contained.
      for (iterator I = begin(), E = end(); I != E;) {
        iterator Cur = I++;
        if (!Cur->Forward)
          Cur->removeUnknownInst(*this, Inst);
      }
    }
  }

  // First, look up the PointerRec for this pointer.
  PointerMapType::iterator I = PointerMap.find_as(PtrVal);
  if (I == PointerMap.end()) return;  // Noop

  // If we found one, remove the pointer from the alias set it is in.
  AliasSet::PointerRec *PtrValEnt = I->second;
  AliasSet *AS = PtrValEnt->getAliasSet(*this);

  // Unlink and delete from the list of values.
  PtrValEnt->eraseFromList();

  if (AS->Alias == AliasSet::SetMayAlias) {
    AS->SetSize--;
    TotalMayAliasSetSize--;
  }

  // Stop using the alias set.
  AS->dropRef(*this);

  PointerMap.erase(I);
}

// copyValue - This method should be used whenever a preexisting value in the
// program is copied or cloned, introducing a new value.  Note that it is ok for
// clients that use this method to introduce the same value multiple times: if
// the tracker already knows about a value, it will ignore the request.
//
void AliasSetTracker::copyValue(Value *From, Value *To) {
  // First, look up the PointerRec for this pointer.
  PointerMapType::iterator I = PointerMap.find_as(From);
  if (I == PointerMap.end())
    return;  // Noop
  assert(I->second->hasAliasSet() && "Dead entry?");

  AliasSet::PointerRec &Entry = getEntryFor(To);
  if (Entry.hasAliasSet()) return;    // Already in the tracker!

  // getEntryFor above may invalidate iterator \c I, so reinitialize it.
  I = PointerMap.find_as(From);
  // Add it to the alias set it aliases...
  AliasSet *AS = I->second->getAliasSet(*this);
  AS->addPointer(*this, Entry, I->second->getSize(),
                 I->second->getAAInfo(),
                 true);
}

AliasSet &AliasSetTracker::mergeAllAliasSets() {
  assert(!AliasAnyAS && (TotalMayAliasSetSize > SaturationThreshold) &&
         "Full merge should happen once, when the saturation threshold is "
         "reached");

  // Collect all alias sets, so that we can drop references with impunity
  // without worrying about iterator invalidation.
  std::vector<AliasSet *> ASVector;
  ASVector.reserve(SaturationThreshold);
  for (iterator I = begin(), E = end(); I != E; I++)
    ASVector.push_back(&*I);

  // Copy all instructions and pointers into a new set, and forward all other
  // sets to it.
  AliasSets.push_back(new AliasSet());
  AliasAnyAS = &AliasSets.back();
  AliasAnyAS->Alias = AliasSet::SetMayAlias;
  AliasAnyAS->Access = AliasSet::ModRefAccess;
  AliasAnyAS->AliasAny = true;

  for (auto Cur : ASVector) {

    // If Cur was already forwarding, just forward to the new AS instead.
    AliasSet *FwdTo = Cur->Forward;
    if (FwdTo) {
      Cur->Forward = AliasAnyAS;
      AliasAnyAS->addRef();
      FwdTo->dropRef(*this);
      continue;
    }

    // Otherwise, perform the actual merge.
    AliasAnyAS->mergeSetIn(*Cur, *this);
  }

  return *AliasAnyAS;
}

AliasSet &AliasSetTracker::addPointer(Value *P, uint64_t Size,
                                      const AAMDNodes &AAInfo,
                                      AliasSet::AccessLattice E) {

  AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo);
  AS.Access |= E;

  if (!AliasAnyAS && (TotalMayAliasSetSize > SaturationThreshold)) {
    // The AST is now saturated. From here on, we conservatively consider all
    // pointers to alias each-other.
    return mergeAllAliasSets();
  }

  return AS;
}

//===----------------------------------------------------------------------===//
//               AliasSet/AliasSetTracker Printing Support
//===----------------------------------------------------------------------===//

void AliasSet::print(raw_ostream &OS) const {
  OS << "  AliasSet[" << (const void*)this << ", " << RefCount << "] ";
  OS << (Alias == SetMustAlias ? "must" : "may") << " alias, ";
  switch (Access) {
  case NoAccess:     OS << "No access "; break;
  case RefAccess:    OS << "Ref       "; break;
  case ModAccess:    OS << "Mod       "; break;
  case ModRefAccess: OS << "Mod/Ref   "; break;
  default: llvm_unreachable("Bad value for Access!");
  }
  if (isVolatile()) OS << "[volatile] ";
  if (Forward)
    OS << " forwarding to " << (void*)Forward;

  if (!empty()) {
    OS << "Pointers: ";
    for (iterator I = begin(), E = end(); I != E; ++I) {
      if (I != begin()) OS << ", ";
      I.getPointer()->printAsOperand(OS << "(");
      OS << ", " << I.getSize() << ")";
    }
  }
  if (!UnknownInsts.empty()) {
    OS << "\n    " << UnknownInsts.size() << " Unknown instructions: ";
    for (unsigned i = 0, e = UnknownInsts.size(); i != e; ++i) {
      if (i) OS << ", ";
      UnknownInsts[i]->printAsOperand(OS);
    }
  }
  OS << "\n";
}

void AliasSetTracker::print(raw_ostream &OS) const {
  OS << "Alias Set Tracker: " << AliasSets.size() << " alias sets for "
     << PointerMap.size() << " pointer values.\n";
  for (const AliasSet &AS : *this)
    AS.print(OS);
  OS << "\n";
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void AliasSet::dump() const { print(dbgs()); }
LLVM_DUMP_METHOD void AliasSetTracker::dump() const { print(dbgs()); }
#endif

//===----------------------------------------------------------------------===//
//                     ASTCallbackVH Class Implementation
//===----------------------------------------------------------------------===//

void AliasSetTracker::ASTCallbackVH::deleted() {
  assert(AST && "ASTCallbackVH called with a null AliasSetTracker!");
  AST->deleteValue(getValPtr());
  // this now dangles!
}

void AliasSetTracker::ASTCallbackVH::allUsesReplacedWith(Value *V) {
  AST->copyValue(getValPtr(), V);
}

AliasSetTracker::ASTCallbackVH::ASTCallbackVH(Value *V, AliasSetTracker *ast)
  : CallbackVH(V), AST(ast) {}

AliasSetTracker::ASTCallbackVH &
AliasSetTracker::ASTCallbackVH::operator=(Value *V) {
  return *this = ASTCallbackVH(V, AST);
}

//===----------------------------------------------------------------------===//
//                            AliasSetPrinter Pass
//===----------------------------------------------------------------------===//

namespace {
  class AliasSetPrinter : public FunctionPass {
    AliasSetTracker *Tracker;
  public:
    static char ID; // Pass identification, replacement for typeid
    AliasSetPrinter() : FunctionPass(ID) {
      initializeAliasSetPrinterPass(*PassRegistry::getPassRegistry());
    }

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesAll();
      AU.addRequired<AAResultsWrapperPass>();
    }

    bool runOnFunction(Function &F) override {
      auto &AAWP = getAnalysis<AAResultsWrapperPass>();
      Tracker = new AliasSetTracker(AAWP.getAAResults());
      errs() << "Alias sets for function '" << F.getName() << "':\n";
      for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I)
        Tracker->add(&*I);
      Tracker->print(errs());
      delete Tracker;
      return false;
    }
  };
}

char AliasSetPrinter::ID = 0;
INITIALIZE_PASS_BEGIN(AliasSetPrinter, "print-alias-sets",
                "Alias Set Printer", false, true)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(AliasSetPrinter, "print-alias-sets",
                "Alias Set Printer", false, true)