% -*- mode: noweb; noweb-default-code-mode: R-mode; -*-
%\VignetteIndexEntry{5. Automatic downloading of CDF packages}
%\VignetteKeywords{Affymetrix}
%\VignetteDepends{affy}
%\VignettePackage{affy}
\documentclass[12pt]{article}

\usepackage{amsmath,pstricks}
\usepackage[authoryear,round]{natbib}
\usepackage{hyperref}


\textwidth=6.2in
\textheight=8.5in
%\parskip=.3cm
\oddsidemargin=.1in
\evensidemargin=.1in
\headheight=-.3in

\newcommand{\scscst}{\scriptscriptstyle}
\newcommand{\scst}{\scriptstyle}

\newcommand{\Rfunction}[1]{{\texttt{#1}}}
\newcommand{\Robject}[1]{{\texttt{#1}}}
\newcommand{\Rpackage}[1]{{\textit{#1}}}
\newcommand{\Rmethod}[1]{{\texttt{#1}}}
\newcommand{\Rfunarg}[1]{{\texttt{#1}}}
\newcommand{\Rclass}[1]{{\textit{#1}}}

\bibliographystyle{plainnat}

\author{Laurent Gautier}
\begin{document}
\title{cdfenvs and oligonucleotide arrays}

\maketitle
\tableofcontents
\section*{Introduction}
This document describes briefly how the package gets (or tries to get)
the needed cdfenvs. Various issues like security and configuring the
options for the package \Rpackage{affy} are outlined. To some extend,
what is developped here could\footnote{Currently this would require
a bit of effort, but it should become very easy very soon}
 be applied to the package \Rpackage{oligochips}.

As usual, loading the package in your \verb+R+ session is required. 
\begin{Sinput}
R> library(affy) ##load the affy package
\end{Sinput}
<<echo=F,results=hide>>=
library(affy)
@

\section*{Why and how}

The {\it cdfenvs} are associative data structures to map efficiently a
{\it probeset id} with indices for the corresponding probes. These
indices are used to subset a matrix storing probe level
intensities. Technically, a {\it cdfenv} is a {\bf R} \Robject{environment}.
The functions \Rfunction{get} and \Rfunction{multiget} (in \Rpackage{Biobase})
are a convenient way to access what is in an environment.
Expert users only will consider modifying what is those environment.

In the case of {\it Affymetrix} data, the {\it cdfenvs} are built from
the {\it .CDF} files. The package \Rpackage{makecdfenvs} is dedicated
to the building of packages with {\it cdfenvs}. The simplest way
to proceed is to have the package needed for the analysis installed.
A number of {\it cdfenv} packages for {\it Affymetrix} chips are
available for download on the {\it Bioconductor} data packages repository. 
This release (1.2.x) of the \Rpackage{affy} package has an option to
allow automatic downloading and install of a {\it cdfenv} that would
be found missing during an analysis. However, if you are using an {\it
  unconventional} chip, it is possible that {\it  
  Bioconductor} has not created the appropriate package for your {\it
  .CDF} file. We recommend that you use the package
\Rpackage{makecdfenvs} to create the appropriate source code for the
{\it cdfenv} package you need. For Microsoft Windows binaries you need
to do more, see \url{http://www.stats.ox.ac.uk/pub/R/rw-FAQ.html}. If
you contribute the package to {\it Bioconductor} a windows binary
will be made for you (and everybody else). The last section outlines
briefly how to change the associated {\it cdfenv}.


The complete structure of the options for the package is not
completely described, but one can refer the source code for the function
\Rfunction{.setAffyOptions()}. The entry {\it probesloc} in the
options details the path used to look for the corresponding {\it cdfenv}.
We introduce a simple function to display the content of the options
for the obtention of the information about probe locations:
<<>>=
print.probesloc.opt <- function(affy.opt, fields) {
  all.fields <- c("what", "where", "autoload", "repository", "installdir")
  
  if (sum (! (fields %in% all.fields)) > 0)
    stop(paste("'fields' can only contain elements of:",
         paste(all.fields, collapse=" ")))

  l <- lapply(affy.opt$probesloc, 
              function(x) x[fields])
  l <- lapply(l, function(x) {
                   unk <- is.na(names(x))
                   x[unk] <- rep(list(unk=NA), sum(unk))
                   x <- lapply(x, function(y) if (is.null(y)) "NULL"
                   else y )
                   return(x)
                 }
              )
  ul <-  as.character(unlist(l))
  m <- t(matrix(ul, nr=length(fields)))  
  colnames(m) <- fields
  print(m)
}
@ 

The default search path for {\it cdfenvs} will be:
<<>>=
affy.opt <- getOption("BioC")$affy

print.probesloc.opt(affy.opt, c("what", "where", "autoload"))
@

The option \Rfunarg{autoload} is only relevant where \Rfunarg{what}
is equal to {\it package}. Having it set to \verb+TRUE+ means
that an attempt will be made to download the package if it is not found
in \Rfunction{.libPaths()} or in the search path shown above.

The following function returns a set of options with any existing automatic download
deactivated :
<<>>=
deactivate.autoload <- function(affy.opt) {
  l <- lapply(affy.opt$probesloc, 
              function(x) {
                i <- names(x) == "autoload"
                x[i] <- list(FALSE)
                return(x)
              })
    affy.opt$probesloc <- l
    return(affy.opt)
  }           
@ 
It can be used to deactivate any automatic download:
<<results=hide>>=
affy.opt <- getOption("BioC")$affy

affy.opt.noauto <- deactivate.autoload(affy.opt)

# commit the changes
.setAffyOptions(affy.opt.noauto)
@



\section*{Security}

The autoload mecanism can be perceived as a security breach. It is the
case, but not more than any {\bf R} package you might install (unless you
inspect carefully the source of every single package you install).

By default the {\it cdfenv} packages are downloaded from the bioconductor
repository. 
This can be changed through the options for the package.
One might want to check what it is like on his/her local installation:
<<>>=
print.probesloc.opt(affy.opt, c("what", "autoload", "repository"))
@

If you do not have install permissions, you might consider installing
the {\it cdfenvs} packages to a particular place. For that you need to
change the {\it installdir} (passed to the function
\Rfunction{install.packages}).
<<results=hide>>=
my.installdir <- "mydir/is/here"
has.installdir <- unlist(lapply(affy.opt$probesloc, function(x) 
                                if("installdir"%in%names(x)) 
                                grep("installdir",names(x))
                                else numeric(0)
                                ))
l <- lapply(affy.opt$probesloc,
            function(x)  {
              if("installdir" %in% names(x)) {
                 x$installdir <- my.installdir
              } 
              return(x)
            })

affy.opt$probesloc <- l

.setAffyOptions(affy.opt)
@

Note that a given {\it cdfenv} package is searched as specified in the
argument {\it where}. Depending on your settings, you might prefer updating
the \Rfunction{.libPaths()} of your {\bf R} session, or the field {\it
where} for the probelocs).

\section*{Changing the associated {\it cdfenv}}

If you do not care about mapping {\it probeset id}s with indices 
and only want to deal with probe intensities, or if you would like
to make a custom {\it cdfenv} from scratch, you will have to modify
the association between your \Robject{AffyBatch} object(s) and {\it cdfenvs}.

If you want to experiment with this feature of the package, we would
recommend to create a dummy {\it cdfenv} and associate your \Robject{AffyBatch}
to it:

<<>>=
data(affybatch.example)
dummymap.name <- "dummymap"
assign(dummymap.name, new.env())
affybatch.example@cdfName <- paste(dummymap.name, "cdf", sep="")
@ 

As explained in the first part, the \Rpackage{affy} package will then find a matching
environment in the current environment (\Robject{.GlobaEnv})and will not try to find a
package. Note: the environment should still be in the section {\it
probelocs} of the package options.

\end{document}
