pcaMethods/0000755000175000017500000000000014147456736012514 5ustar nileshnileshpcaMethods/DESCRIPTION0000644000175000017500000000356614136077111014214 0ustar nileshnileshPackage: pcaMethods Maintainer: Henning Redestig License: GPL (>= 3) Title: A collection of PCA methods LinkingTo: Rcpp LazyLoad: Yes Author: Wolfram Stacklies, Henning Redestig, Kevin Wright SystemRequirements: Rcpp Description: Provides Bayesian PCA, Probabilistic PCA, Nipals PCA, Inverse Non-Linear PCA and the conventional SVD PCA. A cluster based method for missing value estimation is included for comparison. BPCA, PPCA and NipalsPCA may be used to perform PCA on incomplete data as well as for accurate missing value estimation. A set of methods for printing and plotting the results is also provided. All PCA methods make use of the same data structure (pcaRes) to provide a common interface to the PCA results. Initiated at the Max-Planck Institute for Molecular Plant Physiology, Golm, Germany. Version: 1.86.0 URL: https://github.com/hredestig/pcamethods BugReports: https://github.com/hredestig/pcamethods/issues Encoding: UTF-8 Depends: Biobase, methods Imports: BiocGenerics, Rcpp (>= 0.11.3), MASS Suggests: matrixStats, lattice, ggplot2 Collate: 'derrorHierarchic.R' 'errorHierarchic.R' 'AllClasses.R' 'AllGenerics.R' 'BPCA_dostep.R' 'BPCA_initmodel.R' 'bpca.R' 'checkData.R' 'forkNlpcaNet.R' 'kEstimate.R' 'kEstimateFast.R' 'lineSearch.R' 'llsImpute.R' 'methods-ExpressionSet.R' 'methods-nniRes.R' 'methods-pcaRes.R' 'nipalsPca.R' 'nlpca.R' 'optiAlgCgd.R' 'orth.R' 'pca.R' 'pcaMethods-package.R' 'ppca.R' 'prep.R' 'repmat.R' 'robustPca.R' 'sortFeatures.R' 'svdImpute.R' 'vector2matrices.R' 'xval.R' Packaged: 2021-10-26 22:16:41 UTC; biocbuild biocViews: Bayesian RoxygenNote: 6.1.1 git_url: https://git.bioconductor.org/packages/pcaMethods git_branch: RELEASE_3_14 git_last_commit: 9419cfa git_last_commit_date: 2021-10-26 Date/Publication: 2021-10-26 NeedsCompilation: yes pcaMethods/README.md0000644000175000017500000000277314136047224013766 0ustar nileshnilesh# pcaMethods R package for performing [principal component analysis PCA](https://en.wikipedia.org/wiki/Principal_component_analysis) with applications to missing value imputation. Provides a single interface to performing PCA using - **SVD:** a fast method which is also the standard method in R but which is not applicable for data with missing values. - **NIPALS:** an iterative fast method which is applicable also to data with missing values. - **PPCA:** Probabilistic PCA which is applicable also on data with missing values. Missing value estimation is typically better than NIPALS but also slower to compute and uses more memory. A port to R of the [implementation by Jakob Verbeek](http://lear.inrialpes.fr/~verbeek/software.php). - **BPCA:** Bayesian PCA which performs very well in the presence of missing values but is slower than PPCA. A port of the [matlab implementation by Shigeyuki Oba](http://ishiilab.jp/member/oba/tools/BPCAFill.html). - **NLPCA:** Non-linear PCA which can find curves in data and in presence of such can perform accurate missing value estimation. [Matlab port of the implementation by Mathias Scholz](http://www.nlpca.org/). [pcaMethods is a Bioconductor package](http://www.bioconductor.org/packages/release/bioc/html/pcaMethods.html) and you can install it by ```R if (!requireNamespace("BiocManager", quietly=TRUE)) install.packages("BiocManager") BiocManager::install("pcaMethods") ``` ## Documentation ```R browseVignettes("pcaMethods") ? ``` pcaMethods/COPYING0000644000175000017500000004311014136047224013530 0ustar nileshnilesh GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pcaMethods/man/0000755000175000017500000000000014136047224013251 5ustar nileshnileshpcaMethods/man/pcaNet.Rd0000644000175000017500000000657214136047224014764 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/AllClasses.R \docType{class} \name{pcaNet} \alias{pcaNet} \alias{nlpcaNet} \alias{nlpcaNet-class} \title{Class representation of the NLPCA neural net} \description{ This is a class representation of a non-linear PCA neural network. The \code{nlpcaNet} class is not meant for user-level usage. } \details{ Creating Objects \code{new("nlpcaNet", net=[the network structure], hierarchic=[hierarchic design], fct=[the functions at each layer], fkt=[the functions used for forward propagation], weightDecay=[incremental decrease of weight changes over iterations (between 0 and 1)], featureSorting=[sort features or not], dataDist=[represents the present values], inverse=[net is inverse mode or not], fCount=[amount of times features were sorted], componentLayer=[which layer is the 'bottleneck' (principal components)], erro=[the used error function], gradient=[the used gradient method], weights=[the present weights], maxIter=[the amount of iterations that was done], scalingFactor=[the scale of the original matrix])} Slots \describe{ \item{net}{"matrix", matrix showing the representation of the neural network, e.g. (2,4,6) for a network with two features, a hidden layer and six output neurons (original variables).} \item{hierarchic}{"list", the hierarchic design of the network, holds 'idx' (), 'var' () and layer (which layer is the principal component layer).} \item{fct}{"character", a vector naming the functions that will be applied on each layer. "linr" is linear (i.e.) standard matrix products and "tanh" means that the arcus tangens is applied on the result of the matrix product (for non-linearity).} \item{fkt}{"character", same as fct but the functions used during back propagation.} \item{weightDecay}{"numeric", the value that is used to incrementally decrease the weight changes to ensure convergence.} \item{featureSorting}{"logical", indicates if features will be sorted or not. This is used to make the NLPCA assume properties closer to those of standard PCA were the first component is more important for reconstructing the data than the second component.} \item{dataDist}{"matrix", a matrix of ones and zeroes indicating which values will add to the errror.} \item{inverse}{"logical", network is inverse mode (currently only inverse is supported) or not. Eg. the case when we have truly missing values and wish to impute them.} \item{fCount}{"integer", Counter for the amount of times features were really sorted.} \item{componentLayer}{"numeric", the index of 'net' that is the component layer.} \item{error}{"function", the used error function. Currently only one is provided \code{errorHierarchic}.} \item{gradient}{"function", the used gradient function. Currently only one is provided \code{derrorHierarchic}} \item{weights}{"list", A list holding managements of the weights. The list has two functions, weights$current() and weights$set() which access a matrix in the local environment of this object.} \item{maxIter}{"integer", the amount of iterations used to train this network.} \item{scalingFactor}{"numeric", training the network is best made with 'small' values so the original data is scaled down to a suitable range by division with this number.}} Methods \describe{ \item{vector2matrices}{Returns the weights in a matrix representation.} } } \seealso{ \code{\link{nlpca}} } \author{ Henning Redestig } \keyword{classes} pcaMethods/man/repmat.Rd0000644000175000017500000000077314136047224015037 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repmat.R \name{repmat} \alias{repmat} \title{Replicate and tile an array.} \usage{ repmat(mat, M, N) } \arguments{ \item{mat}{numeric matrix} \item{M}{number of copies in vertical direction} \item{N}{number of copies in horizontal direction} } \value{ Matrix consiting of M-by-N tiling copies of input matrix } \description{ Creates a large matrix B consisting of an M-by-N tiling of copies of A } \author{ Wolfram Stacklies } pcaMethods/man/nP-pcaRes-method.Rd0000644000175000017500000000057014136047224016610 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{nP,pcaRes-method} \alias{nP,pcaRes-method} \alias{nP} \title{Get number of PCs} \usage{ nP(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{not used} } \value{ Number of PCs } \description{ Get number of PCs } \author{ Henning Redestig } pcaMethods/man/RnipalsPca.Rd0000644000175000017500000000423114136047224015574 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/nipalsPca.R \name{RnipalsPca} \alias{RnipalsPca} \title{NIPALS PCA implemented in R} \usage{ RnipalsPca(Matrix, nPcs = 2, varLimit = 1, maxSteps = 5000, threshold = 1e-06, verbose = interactive(), ...) } \arguments{ \item{Matrix}{Pre-processed (centered, scaled) numerical matrix samples in rows and variables as columns.} \item{nPcs}{Number of components that should be extracted.} \item{varLimit}{Optionally the ratio of variance that should be explained. \code{nPcs} is ignored if varLimit < 1} \item{maxSteps}{Defines how many iterations can be done before algorithm should abort (happens almost exclusively when there were some wrong in the input data).} \item{threshold}{The limit condition for judging if the algorithm has converged or not, specifically if a new iteration is done if \eqn{(T_{old} - T)^T(T_{old} - T) > \code{limit}}.} \item{verbose}{Show simple progress information.} \item{...}{Only used for passing through arguments.} } \value{ A \code{pcaRes} object. } \description{ PCA by non-linear iterative partial least squares } \details{ Can be used for computing PCA on a numeric matrix using either the NIPALS algorithm which is an iterative approach for estimating the principal components extracting them one at a time. NIPALS can handle a small amount of missing values. It is not recommended to use this function directely but rather to use the pca() wrapper function. There is a C++ implementation given as \code{nipalsPca} which is faster. } \examples{ data(metaboliteData) mat <- prep(t(metaboliteData)) ## c++ version is faster system.time(pc <- RnipalsPca(mat, method="rnipals", nPcs=2)) system.time(pc <- nipalsPca(mat, nPcs=2)) ## better use pca() pc <- pca(t(metaboliteData), method="rnipals", nPcs=2) \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteData))^2, na.rm=TRUE) < 200)} } \references{ Wold, H. (1966) Estimation of principal components and related models by iterative least squares. In Multivariate Analysis (Ed., P.R. Krishnaiah), Academic Press, NY, 391-420. } \seealso{ \code{prcomp}, \code{princomp}, \code{pca} } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/checkData.Rd0000644000175000017500000000242514136047224015412 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/checkData.R \name{checkData} \alias{checkData} \title{Do some basic checks on a given data matrix} \usage{ checkData(data, verbose = FALSE) } \arguments{ \item{data}{\code{matrix} -- Data to check.} \item{verbose}{\code{boolean} -- If TRUE, the function prints messages whenever an error in the data set is found.} } \value{ \item{isValid}{\code{boolean} -- TRUE if no errors were found, FALSE otherwise. isValid contains a set of attributes, these are: \itemize{ \item isNumeric - TRUE if data is numeric, false otherwise \item isInfinite - TRUE if data contains 'Inf' values, false otherwise \item isNaN - TRUE if data contains 'NaN' values, false otherwise \item isMatrix - TRUE if the data is in matrix format, FALSE otherwise \item naRows - TRUE if data contains rows in which all elements are 'NA', FALSE otherwise \item naCols - TRUE if data contains columns in which all elements are 'NA', FALSE otherwise }} } \description{ Check a given data matrix for consistency with the format required for further analysis. The data must be a numeric matrix and not contain: \itemize{ \item Inf values \item NaN values \item Rows or columns that consist of NA only } } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/center-pcaRes-method.Rd0000644000175000017500000000070214136047224017510 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{center,pcaRes-method} \alias{center,pcaRes-method} \alias{center} \title{Get the centers of the original variables} \usage{ center(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ Vector with the centers } \description{ Get the centers of the original variables } \author{ Henning Redestig } pcaMethods/man/scl-pcaRes-method.Rd0000644000175000017500000000101014136047224017002 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{scl,pcaRes-method} \alias{scl,pcaRes-method} \alias{scl} \title{Get the scales (e.g. standard deviations) of the original variables} \usage{ scl(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ Vector with the scales } \description{ Get the scales (e.g. standard deviations) of the original variables } \seealso{ \code{\link{prep}} } \author{ Henning Redestig } pcaMethods/man/orth.Rd0000644000175000017500000000121214136047224014510 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/orth.R \name{orth} \alias{orth} \title{Calculate an orthonormal basis} \usage{ orth(mat, skipInac = FALSE) } \arguments{ \item{mat}{matrix to calculate orthonormal base} \item{skipInac}{do not include components with precision below .Machine$double.eps if TRUE} } \value{ orthonormal basis for the range of matrix } \description{ ONB = orth(mat) is an orthonormal basis for the range of matrix mat. That is, ONB' * ONB = I, the columns of ONB span the same space as the columns of mat, and the number of columns of ONB is the rank of mat. } \author{ Wolfram Stacklies } pcaMethods/man/scores.pcaRes.Rd0000644000175000017500000000062114136047224016251 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \name{scores.pcaRes} \alias{scores.pcaRes} \title{Get scores from a pcaRes object} \usage{ \method{scores}{pcaRes}(object, ...) } \arguments{ \item{object}{a pcaRes object} \item{...}{not used} } \value{ The scores as a matrix } \description{ Get scores from a pcaRes object } \author{ Henning Redestig } pcaMethods/man/loadings-pcaRes-method.Rd0000644000175000017500000000075114136047224020034 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{loadings,pcaRes-method} \alias{loadings,pcaRes-method} \title{Get loadings from a pcaRes object} \usage{ \S4method{loadings}{pcaRes}(object, ...) } \arguments{ \item{object}{a pcaRes object} \item{...}{not used} } \value{ The loadings as a matrix } \description{ Get loadings from a pcaRes object } \seealso{ \code{\link{loadings.pcaRes}} } \author{ Henning Redestig } pcaMethods/man/svdImpute.Rd0000644000175000017500000000602414136047224015522 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/svdImpute.R \name{svdImpute} \alias{svdImpute} \title{SVDimpute algorithm} \usage{ svdImpute(Matrix, nPcs = 2, threshold = 0.01, maxSteps = 100, verbose = interactive(), ...) } \arguments{ \item{Matrix}{\code{matrix} -- Pre-processed (centered, scaled) data with variables in columns and observations in rows. The data may contain missing values, denoted as \code{NA}.} \item{nPcs}{\code{numeric} -- Number of components to estimate. The preciseness of the missing value estimation depends on the number of components, which should resemble the internal structure of the data.} \item{threshold}{The iteration stops if the change in the matrix falls below this threshold.} \item{maxSteps}{Maximum number of iteration steps.} \item{verbose}{Print some output if TRUE.} \item{...}{Reserved for parameters used in future version of the algorithm} } \value{ Standard PCA result object used by all PCA-based methods of this package. Contains scores, loadings, data mean and more. See \code{\link{pcaRes}} for details. } \description{ This implements the SVDimpute algorithm as proposed by Troyanskaya et al, 2001. The idea behind the algorithm is to estimate the missing values as a linear combination of the \code{k} most significant eigengenes. } \details{ Missing values are denoted as \code{NA}. It is not recommended to use this function directely but rather to use the pca() wrapper function. As SVD can only be performed on complete matrices, all missing values are initially replaced by 0 (what is in fact the mean on centred data). The algorithm works iteratively until the change in the estimated solution falls below a certain threshold. Each step the eigengenes of the current estimate are calculated and used to determine a new estimate. Eigengenes denote the loadings if pca is performed considering variable (for Microarray data genes) as observations. An optimal linear combination is found by regressing the incomplete variable against the \code{k} most significant eigengenes. If the value at position \code{j} is missing, the \eqn{j^th}{j^th} value of the eigengenes is not used when determining the regression coefficients. } \note{ Each iteration, standard PCA (\code{prcomp}) needs to be done for each incomplete variable to get the eigengenes. This is usually fast for small data sets, but complexity may rise if the data sets become very large. } \examples{ ## Load a sample metabolite dataset with 5\\\% missing values data(metaboliteData) ## Perform svdImpute using the 3 largest components result <- pca(metaboliteData, method="svdImpute", nPcs=3, center = TRUE) ## Get the estimated complete observations cObs <- completeObs(result) ## Now plot the scores plotPcs(result, type = "scores") } \references{ Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and Hastie T. and Tibshirani R. and Botstein D. and Altman RB. - Missing value estimation methods for DNA microarrays. \emph{Bioinformatics. 2001 Jun;17(6):520-5.} } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/asExprSet.Rd0000644000175000017500000000174114136047224015461 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-ExpressionSet.R \name{asExprSet} \alias{asExprSet} \title{Convert pcaRes object to an expression set} \usage{ asExprSet(object, exprSet) } \arguments{ \item{object}{\code{pcaRes} -- The object containing the completed data.} \item{exprSet}{\code{ExpressionSet} -- The object passed on to \code{pca} for missing value estimation.} } \value{ An object without missing values of class \code{ExpressionSet}. } \description{ This function can be used to conveniently replace the expression matrix in an \code{ExpressionSet} with the completed data from a \code{pcaRes} object. } \details{ This is not a standard \code{as} function as \code{pcaRes} object alone not can be converted to an \code{ExpressionSet} (the \code{pcaRes} object does not hold any \code{phenoData} for example). } \author{ Wolfram Stacklies \cr CAS-MPG Partner Institute for Computational Biology, Shanghai, China } \keyword{multivariate} pcaMethods/man/pcaMethods.Rd0000644000175000017500000000221714136047224015631 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pcaMethods-package.R \docType{package} \name{pcaMethods} \alias{pcaMethods} \alias{pcaMethods-package} \title{pcaMethods} \description{ Principal Component Analysis in R } \details{ \tabular{ll}{ Package: \tab pcaMethods \cr Type: \tab Package \cr Developed since: \tab 2006 \cr License: \tab GPL (>=3) \cr LazyLoad: \tab yes \cr } Provides Bayesian PCA, Probabilistic PCA, Nipals PCA, Inverse Non-Linear PCA and the conventional SVD PCA. A cluster based method for missing value estimation is included for comparison. BPCA, PPCA and NipalsPCA may be used to perform PCA on incomplete data as well as for accurate missing value estimation. A set of methods for printing and plotting the results is also provided. All PCA methods make use of the same data structure (pcaRes) to provide a unique interface to the PCA results. Developed at the Max-Planck Institute for Molecular Plant Physiology, Golm, Germany, RIKEN Plant Science Center Yokohama, Japan, and CAS-MPG Partner Institute for Computational Biology (PICB) Shanghai, P.R. China } \author{ Wolfram Stacklies, Henning Redestig } pcaMethods/man/wasna-pcaRes-method.Rd0000644000175000017500000000144014136047224017341 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{wasna,pcaRes-method} \alias{wasna,pcaRes-method} \alias{wasna} \title{Get a matrix with indicating the elements that were missing in the input data. Convenient for estimating imputation performance.} \usage{ wasna(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ A matrix with logicals } \description{ Get a matrix with indicating the elements that were missing in the input data. Convenient for estimating imputation performance. } \examples{ data(metaboliteData) data(metaboliteDataComplete) result <- pca(metaboliteData, nPcs=2) plot(completeObs(result)[wasna(result)], metaboliteDataComplete[wasna(result)]) } \author{ Henning Redestig } pcaMethods/man/method-pcaRes-method.Rd0000644000175000017500000000063214136047224017512 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{method,pcaRes-method} \alias{method,pcaRes-method} \alias{method} \title{Get the used PCA method} \usage{ method(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ The used pca method } \description{ Get the used PCA method } \author{ Henning Redestig } pcaMethods/man/ppca.Rd0000644000175000017500000000727414136047224014475 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ppca.R \name{ppca} \alias{ppca} \title{Probabilistic PCA} \usage{ ppca(Matrix, nPcs = 2, seed = NA, threshold = 1e-05, maxIterations = 1000, ...) } \arguments{ \item{Matrix}{\code{matrix} -- Data containing the variables in columns and observations in rows. The data may contain missing values, denoted as \code{NA}.} \item{nPcs}{\code{numeric} -- Number of components to estimate. The preciseness of the missing value estimation depends on the number of components, which should resemble the internal structure of the data.} \item{seed}{\code{numeric} Set the seed for the random number generator. PPCA creates fills the initial loading matrix with random numbers chosen from a normal distribution. Thus results may vary slightly. Set the seed for exact reproduction of your results.} \item{threshold}{Convergence threshold.} \item{maxIterations}{the maximum number of allowed iterations} \item{...}{Reserved for future use. Currently no further parameters are used.} } \value{ Standard PCA result object used by all PCA-based methods of this package. Contains scores, loadings, data mean and more. See \code{\link{pcaRes}} for details. } \description{ Implementation of probabilistic PCA (PPCA). PPCA allows to perform PCA on incomplete data and may be used for missing value estimation. This script was implemented after the Matlab version provided by Jakob Verbeek ( see \url{http://lear.inrialpes.fr/~verbeek/}) and the draft \emph{``EM Algorithms for PCA and Sensible PCA''} written by Sam Roweis. } \details{ Probabilistic PCA combines an EM approach for PCA with a probabilistic model. The EM approach is based on the assumption that the latent variables as well as the noise are normal distributed. In standard PCA data which is far from the training set but close to the principal subspace may have the same reconstruction error. PPCA defines a likelihood function such that the likelihood for data far from the training set is much lower, even if they are close to the principal subspace. This allows to improve the estimation accuracy. A method called \code{kEstimate} is provided to estimate the optimal number of components via cross validation. In general few components are sufficient for reasonable estimation accuracy. See also the package documentation for further discussion on what kind of data PCA-based missing value estimation is advisable. \bold{Complexity:}\cr Runtime is linear in the number of data, number of data dimensions and number of principal components. \bold{Convergence:} The threshold indicating convergence was changed from 1e-3 in 1.2.x to 1e-5 in the current version leading to more stable results. For reproducability you can set the seed (parameter seed) of the random number generator. If used for missing value estimation, results may be checked by simply running the algorithm several times with changing seed, if the estimated values show little variance the algorithm converged well. } \note{ Requires \code{MASS}. It is not recommended to use this function directely but rather to use the pca() wrapper function. } \examples{ ## Load a sample metabolite dataset with 5\\\% missing values (metaboliteData) data(metaboliteData) ## Perform probabilistic PCA using the 3 largest components result <- pca(t(metaboliteData), method="ppca", nPcs=3, seed=123) ## Get the estimated complete observations cObs <- completeObs(result) ## Plot the scores plotPcs(result, type = "scores") \dontshow{ stopifnot(sum((fitted(result) - t(metaboliteData))^2, na.rm=TRUE) < 200) } } \seealso{ \code{\link{bpca}, \link{svdImpute}, \link{prcomp}, \link{nipalsPca}, \link{pca}, \link{pcaRes}}. } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/slplot-pcaRes-method.Rd0000644000175000017500000000340614136047224017551 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{slplot,pcaRes-method} \alias{slplot,pcaRes-method} \alias{slplot} \title{Side by side scores and loadings plot} \usage{ slplot(object, pcs=c(1,2), scoresLoadings=c(TRUE, TRUE), sl="def", ll="def", hotelling=0.95, rug=TRUE, sub=NULL,...) } \arguments{ \item{object}{a pcaRes object} \item{pcs}{which two pcs to plot} \item{scoresLoadings}{Which should be shown scores and or loadings} \item{sl}{labels to plot in the scores plot} \item{ll}{labels to plot in the loadings plot} \item{hotelling}{confidence interval for ellipse in the score plot} \item{rug}{logical, rug x axis in score plot or not} \item{sub}{Subtitle, defaults to annotate with amount of explained variance.} \item{...}{Further arguments to plot functions. Prefix arguments to \code{par()} with 's' for the scores plot and 'l' for the loadings plot. I.e. cex become scex for setting character expansion in the score plot and lcex for the loadings plot.} } \value{ None, used for side effect. } \description{ A common way of visualizing two principal components } \details{ This method is meant to be used as a quick way to visualize results, if you want a more specific plot you probably want to get the scores, loadings with \code{scores(object)}, \code{loadings(object)} and then design your own plotting method. } \note{ Uses layout instead of par to provide side-by-side so it works with Sweave (but can not be combined with \code{par(mfrow=..))} } \examples{ data(iris) pcIr <- pca(iris[,1:4], scale="uv") slplot(pcIr, sl=NULL, spch=5) slplot(pcIr, sl=NULL, lcex=1.3, scol=as.integer(iris[,5])) } \seealso{ \code{\link{pca}}, \code{\link{biplot}} } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/nVar-pcaRes-method.Rd0000644000175000017500000000072414136047224017142 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{nVar,pcaRes-method} \alias{nVar,pcaRes-method} \alias{nVar} \title{Get the number of variables used to build the PCA model.} \usage{ nVar(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ Number of variables } \description{ Get the number of variables used to build the PCA model. } \author{ Henning Redestig } pcaMethods/man/nmissing-pcaRes-method.Rd0000644000175000017500000000067414136047224020067 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{nmissing,pcaRes-method} \alias{nmissing,pcaRes-method} \alias{nmissing} \alias{nmissing,nniRes-method} \title{Missing values} \usage{ nmissing(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ Get the number of missing values } \description{ Missing values } \author{ Henning Redestig } pcaMethods/man/dim.pcaRes.Rd0000644000175000017500000000054514136047224015531 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \name{dim.pcaRes} \alias{dim.pcaRes} \title{Dimensions of a PCA model} \usage{ \method{dim}{pcaRes}(x) } \arguments{ \item{x}{a pcaRes object} } \value{ Get the dimensions of this PCA model } \description{ Dimensions of a PCA model } \author{ Henning Redestig } pcaMethods/man/metaboliteDataComplete.Rd0000644000175000017500000000162514136047224020154 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pcaMethods-package.R \docType{data} \name{metaboliteDataComplete} \alias{metaboliteDataComplete} \title{A complete metabolite data set from an Arabidopsis coldstress experiment} \description{ A complete subset from a larger metabolite data set. This is the original, complete data set and can be used to compare estimation results created with the also provided incomplete data (called metaboliteData). The data was created during an in house Arabidopsis coldstress experiment. } \details{ A matrix containing 154 observations (rows) and 52 metabolites (columns). } \references{ Matthias Scholz, Fatma Kaplan, Charles L. Guy, Joachim Kopka and Joachim Selbig. - Non-linear PCA: a missing data approach.\emph{Bioinformatics 2005 21(20):3887-3895} } \seealso{ \code{\link{metaboliteData}} } \author{ Wolfram Stacklies } \keyword{datasets} pcaMethods/man/robustPca.Rd0000644000175000017500000000632014136047224015503 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/robustPca.R \name{robustPca} \alias{robustPca} \title{PCA implementation based on robustSvd} \usage{ robustPca(Matrix, nPcs = 2, verbose = interactive(), ...) } \arguments{ \item{Matrix}{\code{matrix} -- Data containing the variables in columns and observations in rows. The data may contain missing values, denoted as \code{NA}.} \item{nPcs}{\code{numeric} -- Number of components to estimate. The preciseness of the missing value estimation depends on the number of components, which should resemble the internal structure of the data.} \item{verbose}{\code{boolean} Print some output to the command line if TRUE} \item{...}{Reserved for future use. Currently no further parameters are used} } \value{ Standard PCA result object used by all PCA-based methods of this package. Contains scores, loadings, data mean and more. See \code{\link{pcaRes}} for details. are used. } \description{ This is a PCA implementation robust to outliers in a data set. It can also handle missing values, it is however NOT intended to be used for missing value estimation. As it is based on robustSVD we will get an accurate estimation for the loadings also for incomplete data or for data with outliers. The returned scores are, however, affected by the outliers as they are calculated inputData X loadings. This also implies that you should look at the returned R2/R2cum values with caution. If the data show missing values, scores are caluclated by just setting all NA - values to zero. This is not expected to produce accurate results. Please have also a look at the manual page for \code{robustSvd}. Thus this method should mainly be seen as an attempt to integrate \code{robustSvd()} into the framework of this package. Use one of the other methods coming with this package (like PPCA or BPCA) if you want to do missing value estimation. It is not recommended to use this function directely but rather to use the pca() wrapper function. } \details{ The method is very similar to the standard \code{prcomp()} function. The main difference is that \code{robustSvd()} is used instead of the conventional \code{svd()} method. } \examples{ ## Load a complete sample metabolite data set and mean center the data data(metaboliteDataComplete) mdc <- scale(metaboliteDataComplete, center=TRUE, scale=FALSE) ## Now create 5\\\% of outliers. cond <- runif(length(mdc)) < 0.05; mdcOut <- mdc mdcOut[cond] <- 10 ## Now we do a conventional PCA and robustPca on the original and the data ## with outliers. ## We use center=FALSE here because the large artificial outliers would ## affect the means and not allow to objectively compare the results. resSvd <- pca(mdc, method="svd", nPcs=10, center=FALSE) resSvdOut <- pca(mdcOut, method="svd", nPcs=10, center=FALSE) resRobPca <- pca(mdcOut, method="robustPca", nPcs=10, center=FALSE) ## Now we plot the results for the original data against those with outliers ## We can see that robustPca is hardly effected by the outliers. plot(loadings(resSvd)[,1], loadings(resSvdOut)[,1]) plot(loadings(resSvd)[,1], loadings(resRobPca)[,1]) } \seealso{ \code{\link{robustSvd}, \link{svd}, \link{prcomp}, \link{pcaRes}}. } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/pcaRes.Rd0000644000175000017500000000577214136047224014770 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/AllClasses.R \docType{class} \name{pcaRes} \alias{pcaRes} \alias{pcaRes-class} \title{Class for representing a PCA result} \description{ This is a class representation of a PCA result } \details{ \bold{Creating Objects}\cr \code{new("pcaRes", scores=[the scores], loadings=[the loadings], nPcs=[amount of PCs], R2cum=[cumulative R2], nObs=[amount of observations], nVar=[amount of variables], R2=[R2 for each individual PC], sDev=[stdev for each individual PC], centered=[was data centered], center=[original means], varLimit=[what variance limit was exceeded], method=[method used to calculate PCA], missing=[amount of NAs], completeObs=[estimated complete observations])} \bold{Slots}\cr \describe{ \item{scores}{"matrix", the calculated scores} \item{loadings}{"matrix", the calculated loadings} \item{R2cum}{"numeric", the cumulative R2 values} \item{sDev}{"numeric", the individual standard deviations of the score vectors} \item{R2}{"numeric", the individual R2 values} \item{cvstat}{"numeric", cross-validation statistics} \item{nObs}{"numeric", number of observations} \item{nVar}{"numeric", number of variables} \item{centered}{"logical", data was centered or not} \item{center}{"numeric", the original variable centers} \item{scaled}{"logical", data was scaled or not} \item{scl}{"numeric", the original variable scales} \item{varLimit}{"numeric", the exceeded variance limit} \item{nPcs,nP}{"numeric", the number of calculated PCs} \item{method}{"character", the method used to perform PCA} \item{missing}{"numeric", the total amount of missing values in original data} \item{completeObs}{"matrix", the estimated complete observations} \item{network}{"nlpcaNet", the network used by non-linear PCA} } \bold{Methods (not necessarily exhaustive)}\cr \describe{ \item{print}{Print function} \item{summary}{Extract information about PC relevance} \item{screeplot}{Plot a barplot of standard deviations for PCs} \item{slplot}{Make a side by side score and loadings plot} \item{nPcs}{Get the number of PCs} \item{nObs}{Get the number of observations} \item{cvstat}{Cross-validation statistics} \item{nVar}{Get the number of variables} \item{loadings}{Get the loadings} \item{scores}{Get the scores} \item{dim}{Get the dimensions (number of observations, number of features)} \item{centered}{Get a logical indicating if centering was done as part of the model} \item{center}{Get the averages of the original variables.} \item{completeObs}{Get the imputed data set} \item{method}{Get a string naming the used PCA method} \item{sDev}{Get the standard deviations of the PCs} \item{scaled}{Get a logical indicating if scaling was done as part of the model} \item{scl}{Get the scales of the original variablesb} \item{R2cum}{Get the cumulative R2} } } \author{ Henning Redestig } \keyword{classes} pcaMethods/man/predict-methods.Rd0000644000175000017500000000335314136047224016637 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{predict-methods} \alias{predict-methods} \alias{predict.pcaRes} \alias{predict,pcaRes-method} \title{Predict values from PCA.} \usage{ \method{predict}{pcaRes}(object, newdata, pcs = nP(object), pre = TRUE, post = TRUE, ...) \S4method{predict}{pcaRes}(object, newdata, pcs = nP(object), pre = TRUE, post = TRUE, ...) } \arguments{ \item{object}{\code{pcaRes} the \code{pcaRes} object of interest.} \item{newdata}{\code{matrix} new data with same number of columns as the used to compute \code{object}.} \item{pcs}{\code{numeric} The number of PC's to consider} \item{pre}{pre-process \code{newdata} based on the pre-processing chosen for the PCA model} \item{post}{unpre-process the final data (add the center back etc)} \item{...}{Not passed on anywhere, included for S3 consistency.} } \value{ A list with the following components: \item{scores}{The predicted scores} \item{x}{The predicted data} } \description{ Predict data using PCA model } \details{ This function extracts the predict values from a pcaRes object for the PCA methods SVD, Nipals, PPCA and BPCA. Newdata is first centered if the PCA model was and then scores (\eqn{T}) and data (\eqn{X}) is 'predicted' according to : \eqn{\hat{T}=X_{new}P}{That=XnewP} \eqn{\hat{X}_{new}=\hat{T}P'}{Xhat=ThatP'}. Missing values are set to zero before matrix multiplication to achieve NIPALS like treatment of missing values. } \examples{ data(iris) hidden <- sample(nrow(iris), 50) pcIr <- pca(iris[-hidden,1:4]) pcFull <- pca(iris[,1:4]) irisHat <- predict(pcIr, iris[hidden,1:4]) cor(irisHat$scores[,1], scores(pcFull)[hidden,1]) } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/kEstimateFast.Rd0000644000175000017500000000553514136047224016314 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/kEstimateFast.R \name{kEstimateFast} \alias{kEstimateFast} \title{Estimate best number of Components for missing value estimation} \usage{ kEstimateFast(Matrix, method = "ppca", evalPcs = 1:3, em = "nrmsep", allVariables = FALSE, verbose = interactive(), ...) } \arguments{ \item{Matrix}{\code{matrix} -- numeric matrix containing observations in rows and variables in columns} \item{method}{\code{character} -- a valid pca method (see \code{\link{pca}}).} \item{evalPcs}{\code{numeric} -- The principal components to use for cross validation or cluster sizes if used with llsImpute. Should be an array containing integer values, eg. evalPcs = 1:10 or evalPcs = C(2,5,8).The NRMSEP is calculated for each component.} \item{em}{\code{character} -- The error measure. This can be nrmsep or q2} \item{allVariables}{\code{boolean} -- If TRUE, the NRMSEP is calculated for all variables, If FALSE, only the incomplete ones are included. You maybe want to do this to compare several methods on a complete data set.} \item{verbose}{\code{boolean} -- If TRUE, the NRMSEP and the variance are printed to the console each iteration.} \item{...}{Further arguments to \code{pca}} } \value{ \item{list}{Returns a list with the elements: \itemize{ \item minNPcs - number of PCs for which the minimal average NRMSEP was obtained \item eError - an array of of size length(evalPcs). Contains the estimation error for each number of components. \item evalPcs - The evaluated numbers of components or cluster sizes (the same as the evalPcs input parameter). }} } \description{ This is a simple estimator for the optimal number of componets when applying PCA or LLSimpute for missing value estimation. No cross validation is performed, instead the estimation quality is defined as Matrix[!missing] - Estimate[!missing]. This will give a relatively rough estimate, but the number of iterations equals the length of the parameter evalPcs.\cr Does not work with LLSimpute!! As error measure the NRMSEP (see Feten et. al, 2005) or the Q2 distance is used. The NRMSEP basically normalises the RMSD between original data and estimate by the variable-wise variance. The reason for this is that a higher variance will generally lead to a higher estimation error. If the number of samples is small, the gene - wise variance may become an unstable criterion and the Q2 distance should be used instead. Also if variance normalisation was applied previously. } \examples{ data(metaboliteData) # Estimate best number of PCs with ppca for component 2:4 esti <- kEstimateFast(t(metaboliteData), method = "ppca", evalPcs = 2:4, em="nrmsep") barplot(drop(esti$eError), xlab = "Components",ylab = "NRMSEP (1 iterations)") # The best k value is: print(esti$minNPcs) } \seealso{ \code{\link{kEstimate}}. } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/DModX-pcaRes-method.Rd0000644000175000017500000000344414136047224017211 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{DModX,pcaRes-method} \alias{DModX,pcaRes-method} \alias{DModX} \title{DModX} \usage{ DModX(object, dat, newdata=FALSE, type=c("normalized","absolute"), ...) } \arguments{ \item{object}{a pcaRes object} \item{dat}{the original data, taken from \code{completeObs} if left missing.} \item{newdata}{logical indicating if this data was part of the training data or not. If it was, it is adjusted by a near one factor \eqn{v=(N/ (N-A-A0))^-1}} \item{type}{if absolute or normalized values should be given. Normalized values are adjusted to the the total RSD of the model.} \item{...}{Not used} } \value{ A vector with distances from observations to the PCA model } \description{ Distance to the model of X-space. } \details{ Measures how well described the observations are, i.e. how well they fit in the mode. High DModX indicate a poor fit. Defined as: \eqn{\frac{\sqrt{\frac{SSE_i}{K-A}}}{\sqrt{\frac{SSE}{(N-A-A_0)(K-A)}}}} For observation \eqn{i}, in a model with \eqn{A} components, \eqn{K} variables and \eqn{N} obserations. SSE is the squared sum of the residuals. \eqn{A_0} is 1 if model was centered and 0 otherwise. DModX is claimed to be approximately F-distributed and can therefore be used to check if an observation is significantly far away from the PCA model assuming normally distributed data. Pass original data as an argument if the model was calculated with \code{completeObs=FALSE}. } \examples{ data(iris) pcIr <- pca(iris[,1:4]) with(iris, plot(DModX(pcIr)~Species)) } \references{ Introduction to Multi- and Megavariate Data Analysis using Projection Methods (PCA and PLS), L. Eriksson, E. Johansson, N. Kettaneh-Wold and S. Wold, Umetrics 1999, p. 468 } \author{ Henning Redestig } pcaMethods/man/scores-pcaRes-method.Rd0000644000175000017500000000075214136047224017533 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{scores,pcaRes-method} \alias{scores,pcaRes-method} \alias{scores} \title{Get scores from a pcaRes object} \usage{ \S4method{scores}{pcaRes}(object, ...) } \arguments{ \item{object}{a pcaRes object} \item{...}{not used} } \value{ The scores as a matrix } \description{ Get scores from a pcaRes object } \seealso{ \code{\link{scores.pcaRes}} } \author{ Henning Redestig } pcaMethods/man/show-methods.Rd0000644000175000017500000000122114136047224016155 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{show-methods} \alias{show-methods} \alias{showPcaRes} \alias{print,pcaRes-method} \alias{print,nniRes-method} \alias{show,pcaRes-method} \alias{show,nniRes-method} \title{Print/Show for pcaRes} \usage{ showPcaRes(x, ...) \S4method{print}{pcaRes}(x, ...) \S4method{show}{pcaRes}(object) } \arguments{ \item{x}{a pcaRes object} \item{...}{not used} \item{object}{the object to print information about} } \value{ nothing, used for its side effect } \description{ Print basic information about pcaRes object } \author{ Henning Redestig } pcaMethods/man/vector2matrices-matrix-method.Rd0000644000175000017500000000100214136047224021425 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/vector2matrices.R \docType{methods} \name{vector2matrices,matrix-method} \alias{vector2matrices,matrix-method} \title{Tranform the vectors of weights to matrix structure} \usage{ \S4method{vector2matrices}{matrix}(object, net) } \arguments{ \item{object}{an nlpcaNet} \item{net}{the neural network} } \value{ weights in matrix structure } \description{ Tranform the vectors of weights to matrix structure } \author{ Henning Redestig } pcaMethods/man/fitted-methods.Rd0000644000175000017500000000324214136047224016461 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{fitted-methods} \alias{fitted-methods} \alias{fitted.pcaRes} \alias{fitted,pcaRes-method} \title{Extract fitted values from PCA.} \usage{ \method{fitted}{pcaRes}(object, data = NULL, nPcs = nP(object), pre = TRUE, post = TRUE, ...) \S4method{fitted}{pcaRes}(object, data = NULL, nPcs = nP(object), pre = TRUE, post = TRUE, ...) } \arguments{ \item{object}{the \code{pcaRes} object of interest.} \item{data}{For standard PCA methods this can safely be left null to get scores x loadings but if set, then the scores are obtained by projecting provided data onto the loadings. If data contains missing values the result will be all NA. Non-linear PCA is an exception, here if data is NULL then data is set to the completeObs and propaged through the network.} \item{nPcs}{The number of PC's to consider} \item{pre}{pre-process \code{data} based on the pre-processing chosen for the PCA model} \item{post}{unpre-process the final data (add the center back etc to get the final estimate)} \item{...}{Not used} } \value{ A matrix representing the fitted data } \description{ Fitted values of a PCA model } \details{ This function extracts the fitted values from a pcaResobject. For PCA methods like SVD, Nipals, PPCA etc this is basically just the scores multipled by the loadings and adjusted for pre-processing. for non-linear PCA the original data is propagated through the network to obtain the approximated data. } \examples{ pc <- pca(iris[,1:4], nPcs=4, center=TRUE, scale="uv") sum( (fitted(pc) - iris[,1:4])^2 ) } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/rediduals-methods.Rd0000644000175000017500000000216514136047224017161 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{rediduals-methods} \alias{rediduals-methods} \alias{residuals.pcaRes} \alias{residuals,pcaRes-method} \alias{resid,pcaRes-method} \title{Residuals values from a PCA model.} \usage{ \method{residuals}{pcaRes}(object, data = completeObs(object), ...) \S4method{residuals}{pcaRes}(object, data = completeObs(object), ...) \S4method{resid}{pcaRes}(object, data = completeObs(object), ...) } \arguments{ \item{object}{\code{pcaRes} the \code{pcaRes} object of interest.} \item{data}{\code{matrix} The data that was used to calculate the PCA model (or a different dataset to e.g. adress its proximity to the model).} \item{...}{Passed on to \code{\link{predict.pcaRes}}. E.g. setting the number of used components.} } \value{ A \code{matrix} with the residuals } \description{ This function extracts the residuals values from a pcaRes object for the PCA methods SVD, Nipals, PPCA and BPCA } \examples{ data(iris) pcIr <- pca(iris[,1:4]) head(residuals(pcIr, iris[,1:4])) } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/R2VX-pcaRes-method.Rd0000644000175000017500000000144214136047224016773 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{R2VX,pcaRes-method} \alias{R2VX,pcaRes-method} \alias{R2VX} \title{R2 goodness of fit} \usage{ \S4method{R2VX}{pcaRes}(object, direction = c("variables", "observations", "complete"), data = completeObs(object), pcs = nP(object)) } \arguments{ \item{object}{a PCA model object} \item{direction}{choose between calculating R2 per variable, per observation or for the entire data with 'variables', 'observations' or 'complete'.} \item{data}{the data used to fit the model} \item{pcs}{the number of PCs to use to calculate R2} } \value{ A vector with R2 values } \description{ Flexible calculation of R2 goodness of fit. } \examples{ R2VX(pca(iris)) } \author{ Henning Redestig } pcaMethods/man/nni.Rd0000644000175000017500000000237314136047224014331 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pca.R \name{nni} \alias{nni} \title{Nearest neighbour imputation} \usage{ nni(object, method = c("llsImpute"), subset = numeric(), ...) } \arguments{ \item{object}{Numerical matrix with (or an object coercible to such) with samples in rows and variables as columns. Also takes \code{ExpressionSet} in which case the transposed expression matrix is used.} \item{method}{For convenience one can pass a large matrix but only use the variable specified as subset. Can be colnames or indices.} \item{subset}{Currently "llsImpute" only.} \item{...}{Further arguments to the chosen method.} } \value{ A \code{clusterRes} object. Or a list containing a clusterRes object as first and an ExpressionSet object as second entry if the input was of type ExpressionSet. } \description{ Wrapper function for imputation methods based on nearest neighbour clustering. Currently llsImpute only. } \details{ This method is wrapper function to llsImpute, See documentation for \code{link{llsImpute}}. } \examples{ data(metaboliteData) llsRes <- nni(metaboliteData, k=6, method="llsImpute", allGenes=TRUE) } \seealso{ \code{\link{llsImpute}}, \code{\link{pca}} } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/deletediagonals.Rd0000644000175000017500000000134414136047224016666 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xval.R \name{deletediagonals} \alias{deletediagonals} \title{Delete diagonals} \usage{ deletediagonals(x, diagonals = 1) } \arguments{ \item{x}{The matrix} \item{diagonals}{The diagonal to be replaced, i.e. the first, second and so on when looking at the fat version of the matrix (transposed or not) counting from the bottom. Can be a vector to delete more than one diagonal.} } \value{ The original matrix with some values missing } \description{ Replace a diagonal of elements of a matrix with NA } \details{ Used for creating artifical missing values in matrices without causing any full row or column to be completely missing } \author{ Henning Redestig } pcaMethods/man/cvseg.Rd0000644000175000017500000000170014136047224014645 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xval.R \name{cvseg} \alias{cvseg} \title{Get CV segments} \usage{ cvseg(x, fold = 7, seed = NULL) } \arguments{ \item{x}{a factor, character or numeric vector that describes class membership of a set of items, or, a numeric vector indicating unique indices of items, or, a numeric of length 1 that describes the number of items to segment (without any classes)} \item{fold}{the desired number of segments} \item{seed}{randomization seed for reproducibility} } \value{ a list where each element is a set of indices that defines the CV segment. } \description{ Get cross-validation segments that have (as far as possible) the same ratio of all classes (if classes are present) } \examples{ seg <- cvseg(iris$Species, 10) sapply(seg, function(s) table(iris$Species[s])) cvseg(20, 10) } \seealso{ the \code{cvsegments} function in the \code{pls} package } \author{ Henning Redestig } pcaMethods/man/BPCA_dostep.Rd0000644000175000017500000000132414136047224015623 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/BPCA_dostep.R \name{BPCA_dostep} \alias{BPCA_dostep} \title{Do BPCA estimation step} \usage{ BPCA_dostep(M, y) } \arguments{ \item{M}{Data structure containing all needed information. See the source documentation of BPCA_initmodel for details} \item{y}{Numeric original data matrix} } \value{ Updated version of the data structure } \description{ The function contains the actual implementation of the BPCA component estimation. It performs one step of the BPCA EM algorithm. It is called 'maxStep' times from within the main loop in BPCAestimate. } \details{ This function is NOT intended to be run standalone. } \author{ Wolfram Stacklies } pcaMethods/man/bpca.Rd0000644000175000017500000001332014136047224014444 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/bpca.R \name{bpca} \alias{bpca} \title{Bayesian PCA missing value estimation} \usage{ bpca(Matrix, nPcs = 2, maxSteps = 100, verbose = interactive(), threshold = 1e-04, ...) } \arguments{ \item{Matrix}{\code{matrix} -- Pre-processed matrix (centered, scaled) with variables in columns and observations in rows. The data may contain missing values, denoted as \code{NA}.} \item{nPcs}{\code{numeric} -- Number of components used for re-estimation. Choosing few components may decrease the estimation precision.} \item{maxSteps}{\code{numeric} -- Maximum number of estimation steps.} \item{verbose}{\code{boolean} -- BPCA prints the number of steps and the increase in precision if set to TRUE. Default is interactive().} \item{threshold}{convergence threshold} \item{...}{Reserved for future use. Currently no further parameters are used} } \value{ Standard PCA result object used by all PCA-based methods of this package. Contains scores, loadings, data mean and more. See \code{\link{pcaRes}} for details. } \description{ Implements a Bayesian PCA missing value estimator. The script is a port of the Matlab version provided by Shigeyuki OBA. See also \url{http://ishiilab.jp/member/oba/tools/BPCAFill.html}. BPCA combines an EM approach for PCA with a Bayesian model. In standard PCA data far from the training set but close to the principal subspace may have the same reconstruction error. BPCA defines a likelihood function such that the likelihood for data far from the training set is much lower, even if they are close to the principal subspace. } \details{ Scores and loadings obtained with Bayesian PCA slightly differ from those obtained with conventional PCA. This is because BPCA was developed especially for missing value estimation. The algorithm does not force orthogonality between factor loadings, as a result factor loadings are not necessarily orthogonal. However, the BPCA authors found that including an orthogonality criterion made the predictions worse. The authors also state that the difference between real and predicted Eigenvalues becomes larger when the number of observation is smaller, because it reflects the lack of information to accurately determine true factor loadings from the limited and noisy data. As a result, weights of factors to predict missing values are not the same as with conventional PCA, but the missing value estimation is improved. BPCA works iteratively, the complexity is growing with \eqn{O(n^3)}{O(n^3)} because several matrix inversions are required. The size of the matrices to invert depends on the number of components used for re-estimation. Finding the optimal number of components for estimation is not a trivial task; the best choice depends on the internal structure of the data. A method called \code{kEstimate} is provided to estimate the optimal number of components via cross validation. In general few components are sufficient for reasonable estimation accuracy. See also the package documentation for further discussion about on what data PCA-based missing value estimation makes sense. It is not recommended to use this function directely but rather to use the pca() wrapper function. There is a difference with respect the interpretation of rows (observations) and columns (variables) compared to matlab implementation. For estimation of missing values for microarray data, the suggestion in the original bpca is to intepret genes as observations and the samples as variables. In pcaMethods however, genes are interpreted as variables and samples as observations which arguably also is the more natural interpretation. For bpca behavior like in the matlab implementation, simply transpose your input matrix. Details about the probabilistic model underlying BPCA are found in Oba et. al 2003. The algorithm uses an expectation maximation approach together with a Bayesian model to approximate the principal axes (eigenvectors of the covariance matrix in PCA). The estimation is done iteratively, the algorithm terminates if either the maximum number of iterations was reached or if the estimated increase in precision falls below \eqn{1e^{-4}}{1e^-4}. \bold{Complexity:} The relatively high complexity of the method is a result of several matrix inversions required in each step. Considering the case that the maximum number of iteration steps is needed, the approximate complexity is given by the term \deqn{maxSteps \cdot row_{miss} \cdot O(n^3)}{maxSteps * row_miss * O(n^3)} Where \eqn{row_{miss}}{row_miss} is the number of rows containing missing values and \eqn{O(n^3)}{O(n^3)} is the complexity for inverting a matrix of size \eqn{components}{components}. Components is the number of components used for re-estimation. } \note{ Requires \code{MASS}. } \examples{ ## Load a sample metabolite dataset with 5\\\% missig values (metaboliteData)e data(metaboliteData) ## Perform Bayesian PCA with 2 components pc <- pca(t(metaboliteData), method="bpca", nPcs=2) ## Get the estimated principal axes (loadings) loadings <- loadings(pc) ## Get the estimated scores scores <- scores(pc) ## Get the estimated complete observations cObs <- completeObs(pc) ## Now make a scores and loadings plot slplot(pc) \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteData))^2, na.rm=TRUE) < 200)} } \references{ Shigeyuki Oba, Masa-aki Sato, Ichiro Takemasa, Morito Monden, Ken-ichi Matsubara and Shin Ishii. A Bayesian missing value estimation method for gene expression profile data. \emph{Bioinformatics, 19(16):2088-2096, Nov 2003}. } \seealso{ \code{\link{ppca}}, \code{\link{svdImpute}}, \code{\link{prcomp}}, \code{\link{nipalsPca}}, \code{\link{pca}}, \code{\link{pcaRes}}. \code{\link{kEstimate}}. } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/nipalsPca.Rd0000644000175000017500000000361414136047224015456 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/nipalsPca.R \name{nipalsPca} \alias{nipalsPca} \title{NIPALS PCA} \usage{ nipalsPca(Matrix, nPcs = 2, varLimit = 1, maxSteps = 5000, threshold = 1e-06, ...) } \arguments{ \item{Matrix}{Pre-processed (centered, scaled) numerical matrix samples in rows and variables as columns.} \item{nPcs}{Number of components that should be extracted.} \item{varLimit}{Optionally the ratio of variance that should be explained. \code{nPcs} is ignored if varLimit < 1} \item{maxSteps}{Defines how many iterations can be done before algorithm should abort (happens almost exclusively when there were some wrong in the input data).} \item{threshold}{The limit condition for judging if the algorithm has converged or not, specifically if a new iteration is done if \eqn{(T_{old} - T)^T(T_{old} - T) > \code{limit}}.} \item{...}{Only used for passing through arguments.} } \value{ A \code{pcaRes} object. } \description{ PCA by non-linear iterative partial least squares } \details{ Can be used for computing PCA on a numeric matrix using either the NIPALS algorithm which is an iterative approach for estimating the principal components extracting them one at a time. NIPALS can handle a small amount of missing values. It is not recommended to use this function directely but rather to use the pca() wrapper function. } \examples{ data(metaboliteData) mat <- prep(t(metaboliteData)) pc <- nipalsPca(mat, nPcs=2) ## better use pca() pc <- pca(t(metaboliteData), method="nipals", nPcs=2) \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteData))^2, na.rm=TRUE) < 200)} } \references{ Wold, H. (1966) Estimation of principal components and related models by iterative least squares. In Multivariate Analysis (Ed., P.R. Krishnaiah), Academic Press, NY, 391-420. } \seealso{ \code{prcomp}, \code{princomp}, \code{pca} } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/plot.pcaRes.Rd0000644000175000017500000000237414136047224015740 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \name{plot.pcaRes} \alias{plot.pcaRes} \alias{plot,pcaRes-method} \title{Plot diagnostics (screeplot)} \usage{ \method{plot}{pcaRes}(x, y = NULL, main = deparse(substitute(object)), col = gray(c(0.9, 0.5)), ...) } \arguments{ \item{x}{\code{pcaRes} The pcaRes object.} \item{y}{not used} \item{main}{title of the plot} \item{col}{Colors of the bars} \item{...}{further arguments to barplot} } \value{ None, used for side effect. } \description{ Plot the computed diagnostics of PCA model to get an idea of their importance. Note though that the standard screeplot shows the standard deviations for the PCs this method shows the R2 values which empirically shows the importance of the P's and is thus applicable for any PCA method rather than just SVD based PCA. } \details{ If cross-validation was done for the PCA the plot will also show the CV based statistics. A common rule-of-thumb for determining the optimal number of PCs is the PC where the CV diagnostic is at its maximum but not very far from \eqn{R^2}. } \examples{ data(metaboliteData) pc <- pca(t(metaboliteData), nPcs=5, cv="q2", scale="uv") plot(pc) } \seealso{ \link{screeplot} } \author{ Henning Redestig } pcaMethods/man/robustSvd.Rd0000644000175000017500000000620414136047224015535 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/robustPca.R \name{robustSvd} \alias{robustSvd} \title{Alternating L1 Singular Value Decomposition} \usage{ robustSvd(x) } \arguments{ \item{x}{A matrix whose SVD decomposition is to be computed. Missing values are allowed.} } \value{ The robust SVD of the matrix is x=u d v'. \item{d}{A vector containing the singular values of \code{x}.} \item{u}{A matrix whose columns are the left singular vectors of \code{x}.} \item{v}{A matrix whose columns are the right singular vectors of \code{x}.} } \description{ A robust approximation to the singular value decomposition of a rectangular matrix is computed using an alternating L1 norm (instead of the more usual least squares L2 norm). As the SVD is a least-squares procedure, it is highly susceptible to outliers and in the extreme case, an individual cell (if sufficiently outlying) can draw even the leading principal component toward itself. } \details{ See Hawkins et al (2001) for details on the robust SVD algorithm. Briefly, the idea is to sequentially estimate the left and right eigenvectors using an L1 (absolute value) norm minimization. Note that the robust SVD is able to accomodate missing values in the matrix \code{x}, unlike the usual \code{svd} function. Also note that the eigenvectors returned by the robust SVD algorithm are NOT (in general) orthogonal and the eigenvalues need not be descending in order. } \note{ Two differences from the usual SVD may be noted. One relates to orthogonality. In the conventional SVD, all the eigenvectors are orthogonal even if not explicitly imposed. Those returned by the AL1 algorithm (used here) are (in general) not orthogonal. Another difference is that, in the L2 analysis of the conventional SVD, the successive eigen triples (eigenvalue, left eigenvector, right eigenvector) are found in descending order of eigenvalue. This is not necessarily the case with the AL1 algorithm. Hawkins et al (2001) note that a larger eigen value may follow a smaller one. } \examples{ ## Load a complete sample metabolite data set and mean center the data data(metaboliteDataComplete) mdc <- prep(metaboliteDataComplete, center=TRUE, scale="none") ## Now create 5\% of outliers. cond <- runif(length(mdc)) < 0.05; mdcOut <- mdc mdcOut[cond] <- 10 ## Now we do a conventional SVD and a robustSvd on both, the original and the ## data with outliers. resSvd <- svd(mdc) resSvdOut <- svd(mdcOut) resRobSvd <- robustSvd(mdc) resRobSvdOut <- robustSvd(mdcOut) ## Now we plot the results for the original data against those with outliers ## We can see that robustSvd is hardly affected by the outliers. plot(resSvd$v[,1], resSvdOut$v[,1]) plot(resRobSvd$v[,1], resRobSvdOut$v[,1]) } \references{ Hawkins, Douglas M, Li Liu, and S Stanley Young (2001) Robust Singular Value Decomposition, National Institute of Statistical Sciences, Technical Report Number 122. \url{http://www.niss.org/technicalreports/tr122.pdf} } \seealso{ \code{\link{svd}}, \code{\link[ade4:nipals]{nipals}} for an alternating L2 norm method that also accommodates missing data. } \author{ Kevin Wright, modifications by Wolfram Stacklies } \keyword{algebra} pcaMethods/man/weightsAccount.Rd0000644000175000017500000000106014136047224016524 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/AllClasses.R \name{weightsAccount} \alias{weightsAccount} \title{Create an object that holds the weights for nlpcaNet. Holds and sets weights in using an environment object.} \usage{ weightsAccount(w) } \arguments{ \item{w}{\code{matrix} -- New weights} } \value{ A weightsAccound with \code{set} and \code{current} functions. } \description{ Create an object that holds the weights for nlpcaNet. Holds and sets weights in using an environment object. } \author{ Henning Redestig } pcaMethods/man/helix.Rd0000644000175000017500000000110214136047224014643 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pcaMethods-package.R \docType{data} \name{helix} \alias{helix} \title{A helix structured toy data set} \usage{ data(helix) } \description{ Simulated data set looking like a helix } \details{ A matrix containing 1000 observations (rows) and three variables (columns). } \references{ Matthias Scholz, Fatma Kaplan, Charles L. Guy, Joachim Kopka and Joachim Selbig. - Non-linear PCA: a missing data approach. \emph{Bioinformatics 2005 21(20):3887-3895} } \author{ Henning Redestig } \keyword{datasets} pcaMethods/man/nniRes.Rd0000644000175000017500000000252714136047224015004 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/AllClasses.R \docType{class} \name{nniRes} \alias{nniRes} \alias{nniRes-class} \title{Class for representing a nearest neighbour imputation result} \description{ This is a class representation of nearest neighbour imputation (nni) result } \details{ \bold{Creating Objects}\cr \code{new("nniRes", completeObs=[the estimated complete observations], k=[cluster size], nObs=[amount of observations], nVar=[amount of variables], centered=[was the data centered befor running LLSimpute], center=[original means], method=[method used to perform clustering], missing=[amount of NAs])} \bold{Slots}\cr \describe{ \item{completeObs}{"matrix", the estimated complete observations} \item{nObs}{"numeric", amount of observations} \item{nVar}{"numeric", amount of variables} \item{correlation}{"character", the correlation method used (pearson, kendall or spearman)} \item{centered}{"logical", data was centered or not} \item{center}{"numeric", the original variable centers} \item{k}{"numeric", cluster size} \item{method}{"character", the method used to perform the clustering} \item{missing}{"numeric", the total amount of missing values in original data} } \bold{Methods}\cr \describe{ \item{print}{Print function} } } \author{ Wolfram Stacklies } \keyword{classes} pcaMethods/man/biplot-methods.Rd0000644000175000017500000000356614136047224016504 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{biplot-methods} \alias{biplot-methods} \alias{biplot.pcaRes} \alias{biplot,pcaRes-method} \title{Plot a overlaid scores and loadings plot} \usage{ \method{biplot}{pcaRes}(x, choices = 1:2, scale = 1, pc.biplot = FALSE, ...) \S4method{biplot}{pcaRes}(x, choices = 1:2, scale = 1, pc.biplot = FALSE, ...) } \arguments{ \item{x}{a pcaRes object} \item{choices}{which two pcs to plot} \item{scale}{The variables are scaled by \eqn{\lambda^{scale}}{lambda^scale} and the observations are scaled by \eqn{\lambda^{scale}}{lambda ^ (1-scale)} where \code{lambda} are the singular values as computed by \code{princomp}. Normally \eqn{0\le{}scale\le{}1}{0 <= scale <= 1}, and a warning will be issued if the specified 'scale' is outside this range.} \item{pc.biplot}{If true, use what Gabriel (1971) refers to as a "principal component biplot", with \eqn{\lambda=1}{lambda = 1} and observations scaled up by sqrt(n) and variables scaled down by sqrt(n). Then the inner products between variables approximate covariances and distances between observations approximate Mahalanobis distance.} \item{...}{optional arguments to be passed to \code{biplot.default}.} } \value{ a plot is produced on the current graphics device. } \description{ Visualize two-components simultaneously } \details{ This is a method for the generic function 'biplot'. There is considerable confusion over the precise definitions: those of the original paper, Gabriel (1971), are followed here. Gabriel and Odoroff (1990) use the same definitions, but their plots actually correspond to \code{pc.biplot = TRUE}. } \examples{ data(iris) pcIr <- pca(iris[,1:4]) biplot(pcIr) } \seealso{ \code{prcomp}, \code{pca}, \code{princomp} } \author{ Kevin Wright, Adapted from \code{biplot.prcomp} } \keyword{multivariate} pcaMethods/man/svdPca.Rd0000644000175000017500000000260514136047224014763 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pca.R \name{svdPca} \alias{svdPca} \title{Perform principal component analysis using singular value decomposition} \usage{ svdPca(Matrix, nPcs = 2, varLimit = 1, verbose = interactive(), ...) } \arguments{ \item{Matrix}{Pre-processed (centered and possibly scaled) numerical matrix samples in rows and variables as columns. No missing values allowed.} \item{nPcs}{Number of components that should be extracted.} \item{varLimit}{Optionally the ratio of variance that should be explained. \code{nPcs} is ignored if varLimit < 1} \item{verbose}{Verbose complaints to matrix structure} \item{...}{Only used for passing through arguments.} } \value{ A \code{pcaRes} object. } \description{ A wrapper function for \code{prcomp} to deliver the result as a \code{pcaRes} method. Supplied for compatibility with the rest of the pcaMethods package. It is not recommended to use this function directely but rather to use the \code{pca()} wrapper function. } \examples{ data(metaboliteDataComplete) mat <- prep(t(metaboliteDataComplete)) pc <- svdPca(mat, nPcs=2) ## better use pca() pc <- pca(t(metaboliteDataComplete), method="svd", nPcs=2) \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteDataComplete))^2, na.rm=TRUE) < 200)} } \seealso{ \code{prcomp}, \code{princomp}, \code{pca} } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/plotPcs.Rd0000644000175000017500000000246214136047224015170 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pca.R \name{plotPcs} \alias{plotPcs} \title{Plot many side by side scores XOR loadings plots} \usage{ plotPcs(object, pcs = 1:nP(object), type = c("scores", "loadings"), sl = NULL, hotelling = 0.95, ...) } \arguments{ \item{object}{\code{pcaRes} a pcaRes object} \item{pcs}{\code{numeric} which pcs to plot} \item{type}{\code{character} Either "scores" or "loadings" for scores or loadings plot respectively} \item{sl}{\code{character} Text labels to plot instead of a point, if NULL points are plotted instead of text} \item{hotelling}{\code{numeric} Significance level for the confidence ellipse. NULL means that no ellipse is drawn.} \item{...}{Further arguments to \code{\link{pairs}} on which this function is based.} } \value{ None, used for side effect. } \description{ A function that can be used to visualise many PCs plotted against each other } \details{ Uses \code{\link{pairs}} to provide side-by-side plots. Note that this function only plots scores or loadings but not both in the same plot. } \examples{ data(iris) pcIr <- pca(iris[,1:4], nPcs=3, method="svd") plotPcs(pcIr, col=as.integer(iris[,4]) + 1) } \seealso{ \code{prcomp}, \code{pca}, \code{princomp}, \code{slplot} } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/leverage-pcaRes-method.Rd0000644000175000017500000000213414136047224020023 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{leverage,pcaRes-method} \alias{leverage,pcaRes-method} \alias{leverage} \title{Extract leverages of a PCA model} \usage{ \S4method{leverage}{pcaRes}(object) } \arguments{ \item{object}{a \code{pcaRes} object} } \value{ The observation leverages as a numeric vector } \description{ The leverages of PCA model indicate how much influence each observation has on the PCA model. Observations with high leverage has caused the principal components to rotate towards them. It can be used to extract both "unimportant" observations as well as picking potential outliers. } \details{ Defined as \eqn{Tr(T(T'T)^{-1}T')}{Tr(T(T'T)^(-1)T')} } \examples{ data(iris) pcIr <- pca(iris[,1:4]) ## versicolor has the lowest leverage with(iris, plot(leverage(pcIr)~Species)) } \references{ Introduction to Multi- and Megavariate Data Analysis using Projection Methods (PCA and PLS), L. Eriksson, E. Johansson, N. Kettaneh-Wold and S. Wold, Umetrics 1999, p. 466 } \author{ Henning Redestig } \keyword{multivariate} pcaMethods/man/kEstimate.Rd0000644000175000017500000001435514136047224015476 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/kEstimate.R \name{kEstimate} \alias{kEstimate} \title{Estimate best number of Components for missing value estimation} \usage{ kEstimate(Matrix, method = "ppca", evalPcs = 1:3, segs = 3, nruncv = 5, em = "q2", allVariables = FALSE, verbose = interactive(), ...) } \arguments{ \item{Matrix}{\code{matrix} -- numeric matrix containing observations in rows and variables in columns} \item{method}{\code{character} -- of the methods found with pcaMethods() The option llsImputeAll calls llsImpute with the allVariables = TRUE parameter.} \item{evalPcs}{\code{numeric} -- The principal components to use for cross validation or the number of neighbour variables if used with llsImpute. Should be an array containing integer values, eg. \code{evalPcs = 1:10} or \code{evalPcs = c(2,5,8)}. The NRMSEP or Q2 is calculated for each component.} \item{segs}{\code{numeric} -- number of segments for cross validation} \item{nruncv}{\code{numeric} -- Times the whole cross validation is repeated} \item{em}{\code{character} -- The error measure. This can be nrmsep or q2} \item{allVariables}{\code{boolean} -- If TRUE, the NRMSEP is calculated for all variables, If FALSE, only the incomplete ones are included. You maybe want to do this to compare several methods on a complete data set.} \item{verbose}{\code{boolean} -- If TRUE, some output like the variable indexes are printed to the console each iteration.} \item{...}{Further arguments to \code{pca} or \code{nni}} } \value{ A list with: \item{bestNPcs}{number of PCs or k for which the minimal average NRMSEP or the maximal Q2 was obtained.} \item{eError}{an array of of size length(evalPcs). Contains the average error of the cross validation runs for each number of components.} \item{variableWiseError}{Matrix of size \code{incomplete_variables} x length(evalPcs). Contains the NRMSEP or Q2 distance for each variable and each number of PCs. This allows to easily see for wich variables imputation makes sense and for which one it should not be done or mean imputation should be used.} \item{evalPcs}{The evaluated numbers of components or number of neighbours (the same as the evalPcs input parameter).} \item{variableIx}{Index of the incomplete variables. This can be used to map the variable wise error to the original data.} } \description{ Perform cross validation to estimate the optimal number of components for missing value estimation. Cross validation is done for the complete subset of a variable. } \details{ The assumption hereby is that variables that are highly correlated in a distinct region (here the non-missing observations) are also correlated in another (here the missing observations). This also implies that the complete subset must be large enough to be representative. For each incomplete variable, the available values are divided into a user defined number of cv-segments. The segments have equal size, but are chosen from a random equal distribution. The non-missing values of the variable are covered completely. PPCA, BPCA, SVDimpute, Nipals PCA, llsImpute an NLPCA may be used for imputation. The whole cross validation is repeated several times so, depending on the parameters, the calculations can take very long time. As error measure the NRMSEP (see Feten et. al, 2005) or the Q2 distance is used. The NRMSEP basically normalises the RMSD between original data and estimate by the variable-wise variance. The reason for this is that a higher variance will generally lead to a higher estimation error. If the number of samples is small, the variable - wise variance may become an unstable criterion and the Q2 distance should be used instead. Also if variance normalisation was applied previously. The method proceeds variable - wise, the NRMSEP / Q2 distance is calculated for each incomplete variable and averaged afterwards. This allows to easily see for wich set of variables missing value imputation makes senes and for wich set no imputation or something like mean-imputation should be used. Use \code{kEstimateFast} or \code{Q2} if you are not interested in variable wise CV performance estimates. Run time may be very high on large data sets. Especially when used with complex methods like BPCA or Nipals PCA. For PPCA, BPCA, Nipals PCA and NLPCA the estimation method is called \eqn{(v_{miss} \cdot segs \cdot nruncv \cdot)}{(v\_miss * segs * nruncv)} times as the error for all numbers of principal components can be calculated at once. For LLSimpute and SVDimpute this is not possible, and the method is called \eqn{(v_{miss} \cdot segs \cdot nruncv \cdot length(evalPcs))}{(v\_miss * segs * nruncv * length(evalPcs))} times. This should still be fast for LLSimpute because the method allows to choose to only do the estimation for one particular variable. This saves a lot of iterations. Here, \eqn{v_{miss}}{v\_miss} is the number of variables showing missing values. As cross validation is done variable-wise, in this function Q2 is defined on single variables, not on the entire data set. This is Q2 is calculated as as \eqn{\frac{\sum(x - xe)^2}{\sum(x^2)}}{sum(x - xe)^2 \ sum(x^2)}, where x is the currently used variable and xe it's estimate. The values are then averaged over all variables. The NRMSEP is already defined variable-wise. For a single variable it is then \eqn{\sqrt(\frac{\sum(x - xe)^2}{(n \cdot var(x))})}{sqrt(sum(x - xe)^2 \ (n * var(x)))}, where x is the variable and xe it's estimate, n is the length of x. The variable wise estimation errors are returned in parameter variableWiseError. } \examples{ ## Load a sample metabolite dataset with 5\\\% missing values (metaboliteData) data(metaboliteData) # Do cross validation with ppca for component 2:4 esti <- kEstimate(metaboliteData, method = "ppca", evalPcs = 2:4, nruncv=1, em="nrmsep") # Plot the average NRMSEP barplot(drop(esti$eError), xlab = "Components",ylab = "NRMSEP (1 iterations)") # The best result was obtained for this number of PCs: print(esti$bestNPcs) # Now have a look at the variable wise estimation error barplot(drop(esti$variableWiseError[, which(esti$evalPcs == esti$bestNPcs)]), xlab = "Incomplete variable Index", ylab = "NRMSEP") } \seealso{ \code{\link{kEstimateFast}, \link{Q2}, \link{pca}, \link{nni}}. } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/scaled-pcaRes-method.Rd0000644000175000017500000000072614136047224017471 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{scaled,pcaRes-method} \alias{scaled,pcaRes-method} \alias{scaled} \title{Check if scaling was part of the PCA model} \usage{ scaled(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ TRUE if scaling was part of the PCA model } \description{ Check if scaling was part of the PCA model } \author{ Henning Redestig } pcaMethods/man/BPCA_initmodel.Rd0000644000175000017500000000267614136047224016324 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/BPCA_initmodel.R \name{BPCA_initmodel} \alias{BPCA_initmodel} \title{Initialize BPCA model} \usage{ BPCA_initmodel(y, components) } \arguments{ \item{y}{numeric matrix containing missing values. Missing values are denoted as 'NA'} \item{components}{Number of components used for estimation} } \value{ List containing \item{rows}{Row number of input matrix} \item{cols}{Column number of input matrix} \item{comps}{Number of components to use} \item{yest}{(working variable) current estimate of complete data} \item{row_miss}{(Array) Indizes of rows containing missing values} \item{row_nomiss}{(Array) Indices of complete rows (such with no missing values)} \item{nans}{Matrix of same size as input data. TRUE if \code{input == NA}, false otherwise} \item{mean}{Column wise data mean} \item{PA}{ (d x k) Estimated principal axes (eigenvectors, loadings) The matrix ROWS are the vectors} \item{tau}{Estimated precision of the residual error} \item{scores}{ Estimated scores} Further elements are: galpha0, balpha0, alpha, gmu0, btau0, gtau0, SigW. These are working variables or constants. } \description{ Model initialization for Bayesian PCA. This function is NOT inteded to be run separately! } \details{ The function calculates the initial Eigenvectors by use of SVD from the complete rows. The data structure M is created and initial values are assigned. } \author{ Wolfram Stacklies } pcaMethods/man/listPcaMethods.Rd0000644000175000017500000000105714136047224016466 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pca.R \name{listPcaMethods} \alias{listPcaMethods} \title{List PCA methods} \usage{ listPcaMethods(which = c("all", "linear", "nonlinear")) } \arguments{ \item{which}{the type of methods to get. E.g. only get the PCA methods based on the classical model where the fitted data is a direct multiplication of scores and loadings.} } \value{ A character vector with the current methods for doing PCA } \description{ Vector with current valid PCA methods } \author{ Henning Redestig } pcaMethods/man/metaboliteData.Rd0000644000175000017500000000174514136047224016466 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pcaMethods-package.R \docType{data} \name{metaboliteData} \alias{metaboliteData} \title{A incomplete metabolite data set from an Arabidopsis coldstress experiment} \description{ A incomplete subset from a larger metabolite data set. This is the original, complete data set and can be used to compare estimation results created with the also provided incomplete data (called metaboliteData). } \details{ A matrix containing 154 observations (rows) and 52 metabolites (columns). The data contains 5\% of artificially created uniformly distributed misssing values. The data was created during an in house Arabidopsis coldstress experiment. } \references{ Matthias Scholz, Fatma Kaplan, Charles L. Guy, Joachim Kopka and Joachim Selbig. - Non-linear PCA: a missing data approach.\emph{Bioinformatics 2005 21(20):3887-3895} } \seealso{ \code{\link{metaboliteDataComplete}} } \author{ Wolfram Stacklies } \keyword{datasets} pcaMethods/man/cvstat-pcaRes-method.Rd0000644000175000017500000000071714136047224017542 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{cvstat,pcaRes-method} \alias{cvstat,pcaRes-method} \alias{cvstat} \title{Get cross-validation statistics (e.g. \eqn{Q^2}).} \usage{ cvstat(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{not used} } \value{ vector CV statistics } \description{ Get cross-validation statistics (e.g. \eqn{Q^2}). } \author{ Henning Redestig } pcaMethods/man/nlpca.Rd0000644000175000017500000000674114136047224014645 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/nlpca.R \name{nlpca} \alias{nlpca} \title{Non-linear PCA} \usage{ nlpca(Matrix, nPcs = 2, maxSteps = 2 * prod(dim(Matrix)), unitsPerLayer = NULL, functionsPerLayer = NULL, weightDecay = 0.001, weights = NULL, verbose = interactive(), ...) } \arguments{ \item{Matrix}{\code{matrix} --- Preprocessed data with the variables in columns and observations in rows. The data may contain missing values, denoted as \code{NA}} \item{nPcs}{\code{numeric} -- Number of components to estimate. The preciseness of the missing value estimation depends on thenumber of components, which should resemble the internal structure of the data.} \item{maxSteps}{\code{numeric} -- Number of estimation steps. Default is based on a generous rule of thumb.} \item{unitsPerLayer}{The network units, example: c(2,4,6) for two input units 2feature units (principal components), one hidden layer fornon-linearity and three output units (original amount ofvariables).} \item{functionsPerLayer}{The function to apply at each layer eg. c("linr", "tanh", "linr")} \item{weightDecay}{Value between 0 and 1.} \item{weights}{Starting weights for the network. Defaults to uniform random values but can be set specifically to make algorithm deterministic.} \item{verbose}{\code{boolean} -- nlpca prints the number of steps and warning messages if set to TRUE. Default is interactive().} \item{...}{Reserved for future use. Not passed on anywhere.} } \value{ Standard PCA result object used by all PCA-basedmethods of this package. Contains scores, loadings, data meanand more. See \code{\link{pcaRes}} for details. } \description{ Neural network based non-linear PCA } \details{ Artificial Neural Network (MLP) for performing non-linear PCA. Non-linear PCA is conceptually similar to classical PCA but theoretically quite different. Instead of simply decomposing our matrix (X) to scores (T) loadings (P) and an error (E) we train a neural network (our loadings) to find a curve through the multidimensional space of X that describes a much variance as possible. Classical ways of interpreting PCA results are thus not applicable to NLPCA since the loadings are hidden in the network. However, the scores of components that lead to low cross-validation errors can still be interpreted via the score plot. Unfortunately this method depend on slow iterations which currently are implemented in R only making this method extremely slow. Furthermore, the algorithm does not by itself decide when it has converged but simply does 'maxSteps' iterations. } \examples{ ## Data set with three variables where data points constitute a helix data(helix) helixNA <- helix ## not a single complete observation helixNA <- t(apply(helix, 1, function(x) { x[sample(1:3, 1)] <- NA; x})) ## 50 steps is not enough, for good estimation use 1000 helixNlPca <- pca(helixNA, nPcs=1, method="nlpca", maxSteps=50) fittedData <- fitted(helixNlPca, helixNA) plot(fittedData[which(is.na(helixNA))], helix[which(is.na(helixNA))]) ## compared to solution by Nipals PCA which cannot extract non-linear patterns helixNipPca <- pca(helixNA, nPcs=2) fittedData <- fitted(helixNipPca) plot(fittedData[which(is.na(helixNA))], helix[which(is.na(helixNA))]) } \references{ Matthias Scholz, Fatma Kaplan, Charles L Guy, Joachim Kopkaand Joachim Selbig. Non-linear PCA: a missing data approach. \emph{Bioinformatics, 21(20):3887-3895, Oct 2005} } \author{ Based on a matlab script by Matthias Scholz and ported to R by Henning Redestig } pcaMethods/man/summary.Rd0000644000175000017500000000070214136047224015234 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \name{summary} \alias{summary} \alias{summary.pcaRes} \alias{summary,pcaRes-method} \title{Summary of PCA model} \usage{ \method{summary}{pcaRes}(object, ...) } \arguments{ \item{object}{a pcaRes object} \item{...}{Not used} } \value{ Nothing, used for side-effect } \description{ Print a brief description of the PCA model } \author{ Henning Redestig } pcaMethods/man/showNniRes.Rd0000644000175000017500000000060214136047224015635 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-nniRes.R \name{showNniRes} \alias{showNniRes} \title{Print a nniRes model} \usage{ showNniRes(x, ...) } \arguments{ \item{x}{An \code{nniRes} object} \item{...}{Not used} } \value{ Nothing, used for side-effect } \description{ Print a brief description of nniRes model } \author{ Henning Redestig } pcaMethods/man/simpleEllipse.Rd0000644000175000017500000000156314136047224016354 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pca.R \name{simpleEllipse} \alias{simpleEllipse} \title{Hotelling's T^2 Ellipse} \usage{ simpleEllipse(x, y, alfa = 0.95, len = 200) } \arguments{ \item{x}{first variable} \item{y}{second variable} \item{alfa}{confidence level of the circle} \item{len}{Number of points in the circle} } \value{ A matrix with X and Y coordinates for the circle } \description{ Get a confidence ellipse for uncorrelated bivariate data } \details{ As described in 'Introduction to multi and megavariate data analysis using PCA and PLS' by Eriksson et al. This produces very similar ellipse as compared to the ellipse function the ellipse package except that this function assumes that and y are uncorrelated (which they of are if they are scores or loadings from a PCA). } \seealso{ ellipse } \author{ Henning Redestig } pcaMethods/man/sortFeatures.Rd0000644000175000017500000000070514136047224016230 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sortFeatures.R \name{sortFeatures} \alias{sortFeatures} \title{Sort the features of NLPCA object} \usage{ sortFeatures(nlnet, trainIn, trainOut) } \arguments{ \item{nlnet}{The nlnet} \item{trainIn}{Training data in} \item{trainOut}{Training data after it passed through the net} } \value{ ... } \description{ Sort the features of NLPCA object } \author{ Henning Redestig } pcaMethods/man/R2cum-pcaRes-method.Rd0000644000175000017500000000104714136047224017223 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{R2cum,pcaRes-method} \alias{R2cum,pcaRes-method} \alias{R2cum} \title{Cumulative R2 is the total ratio of variance that is being explained by the model} \usage{ \S4method{R2cum}{pcaRes}(object, ...) } \arguments{ \item{object}{a \code{pcaRes} model} \item{...}{Not used} } \value{ Get the cumulative R2 } \description{ Cumulative R2 is the total ratio of variance that is being explained by the model } \author{ Henning Redestig } pcaMethods/man/prep.Rd0000644000175000017500000000445614136047224014517 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/prep.R \name{prep} \alias{prep} \title{Pre-process a matrix for PCA} \usage{ prep(object, scale = c("none", "pareto", "vector", "uv"), center = TRUE, eps = 1e-12, simple = TRUE, reverse = FALSE, ...) } \arguments{ \item{object}{Numerical matrix (or an object coercible to such) with samples in rows and variables as columns. Also takes \code{ExpressionSet} in which case the transposed expression matrix is used.} \item{scale}{One of "UV" (unit variance \eqn{a=a/\sigma_{a}}) "vector" (vector normalisation \eqn{b=b/||b||}), "pareto" (sqrt UV) or "none" to indicate which scaling should be used to scale the matrix with \eqn{a} variables and \eqn{b} samples. Can also be a vector of scales which should be used to scale the matrix. \code{NULL} value is interpreted as \code{"none"}.} \item{center}{Either a logical which indicates if the matrix should be mean centred or not, or a vector with averages which should be suntracted from the matrix. \code{NULL} value is interpreted as \code{FALSE}} \item{eps}{Minimum variance, variable with lower variance are not scaled and warning is issued instead.} \item{simple}{Logical indicating if only the data should be returned or a list with the pre-processing statistics as well.} \item{reverse}{Logical indicating if matrix should be 'post-processed' instead by multiplying each column with its scale and adding the center. In this case, center and scale should be vectors with the statistics (no warning is issued if not, instead output becomes the same as input).} \item{...}{Only used for passing through arguments.} } \value{ A pre-processed matrix or a list with \item{center}{a vector with the estimated centers} \item{scale}{a vector with the estimated scales} \item{data}{the pre (or post) processed data} } \description{ Scaling and centering a matrix. } \details{ Does basically the same as \code{\link{scale}} but adds some alternative scaling options and functionality for treating pre-processing as part of a model. } \examples{ object <- matrix(rnorm(50), nrow=10) res <- prep(object, scale="uv", center=TRUE, simple=FALSE) obj <- prep(object, scale=res$scale, center=res$center) ## same as original sum((object - prep(obj, scale=res$scale, center=res$center, rev=TRUE))^2) } \author{ Henning Redestig } pcaMethods/man/getHierarchicIdx.Rd0000644000175000017500000000052514136047224016750 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/nlpca.R \name{getHierarchicIdx} \alias{getHierarchicIdx} \title{Index in hiearchy} \usage{ getHierarchicIdx(hierarchicNum) } \arguments{ \item{hierarchicNum}{A number} } \value{ ... } \description{ Index in hiearchy } \author{ Henning Redestig, Matthias Scholz } pcaMethods/man/centered-pcaRes-method.Rd0000644000175000017500000000070514136047224020024 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{centered,pcaRes-method} \alias{centered,pcaRes-method} \alias{centered} \title{Check centering was part of the model} \usage{ centered(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ TRUE if model was centered } \description{ Check centering was part of the model } \author{ Henning Redestig } pcaMethods/man/forkNlpcaNet.Rd0000644000175000017500000000054414136047224016131 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/forkNlpcaNet.R \name{forkNlpcaNet} \alias{forkNlpcaNet} \title{Complete copy of nlpca net object} \usage{ forkNlpcaNet(nlnet) } \arguments{ \item{nlnet}{a nlnet} } \value{ A copy of the input nlnet } \description{ Complete copy of nlpca net object } \author{ Henning Redestig } pcaMethods/man/completeObs-nniRes-method.Rd0000644000175000017500000000111514136047224020524 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{completeObs,nniRes-method} \alias{completeObs,nniRes-method} \alias{completeObs} \alias{completeObs,pcaRes-method} \title{Get the original data with missing values replaced with predicted values.} \usage{ completeObs(object, ...) } \arguments{ \item{object}{object to fetch complete data from} \item{...}{Not used} } \value{ Completed data (matrix) } \description{ Get the original data with missing values replaced with predicted values. } \author{ Henning Redestig } pcaMethods/man/optiAlgCgd.Rd0000644000175000017500000000073714136047224015564 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/optiAlgCgd.R \name{optiAlgCgd} \alias{optiAlgCgd} \title{Conjugate gradient optimization} \usage{ optiAlgCgd(nlnet, trainIn, trainOut, verbose = FALSE) } \arguments{ \item{nlnet}{The nlnet} \item{trainIn}{Training data} \item{trainOut}{fitted data} \item{verbose}{logical, print messages} } \value{ ... } \description{ Conjugate gradient optimization } \author{ Henning Redestig, Matthias Scholz } pcaMethods/man/tempFixNas.Rd0000644000175000017500000000063414136047224015621 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xval.R \name{tempFixNas} \alias{tempFixNas} \title{Temporary fix for missing values} \usage{ tempFixNas(mat) } \arguments{ \item{mat}{a matrix} } \value{ The original matrix with completely missing rows/cols filled with zeroes. } \description{ Simply replace completely missing rows or cols with zeroes. } \author{ Henning Redestig } pcaMethods/man/linr.Rd0000644000175000017500000000043314136047224014504 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lineSearch.R \name{linr} \alias{linr} \title{Linear kernel} \usage{ linr(x) } \arguments{ \item{x}{datum} } \value{ Input value } \description{ Linear kernel } \author{ Henning Redestig, Matthias Scholz } pcaMethods/man/nObs-pcaRes-method.Rd0000644000175000017500000000073514136047224017137 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{nObs,pcaRes-method} \alias{nObs,pcaRes-method} \alias{nObs} \title{Get the number of observations used to build the PCA model.} \usage{ nObs(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ Number of observations } \description{ Get the number of observations used to build the PCA model. } \author{ Henning Redestig } pcaMethods/man/llsImpute.Rd0000644000175000017500000000776614136047224015536 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/llsImpute.R \name{llsImpute} \alias{llsImpute} \title{LLSimpute algorithm} \usage{ llsImpute(Matrix, k = 10, center = FALSE, completeObs = TRUE, correlation = "pearson", allVariables = FALSE, maxSteps = 100, xval = NULL, verbose = FALSE, ...) } \arguments{ \item{Matrix}{\code{matrix} -- Data containing the variables (genes) in columns and observations (samples) in rows. The data may contain missing values, denoted as \code{NA}.} \item{k}{\code{numeric} -- Cluster size, this is the number of similar genes used for regression.} \item{center}{\code{boolean} -- Mean center the data if TRUE} \item{completeObs}{\code{boolean} -- Return the estimated complete observations if TRUE. This is the input data with NA values replaced by the estimated values.} \item{correlation}{\code{character} -- How to calculate the distance between genes. One out of pearson | kendall | spearman , see also help("cor").} \item{allVariables}{\code{boolean} -- Use only complete genes to do the regression if TRUE, all genes if FALSE.} \item{maxSteps}{\code{numeric} -- Maximum number of iteration steps if allGenes = TRUE.} \item{xval}{\code{numeric} Use LLSimpute for cross validation. xval is the index of the gene to estimate, all other incomplete genes will be ignored if this parameter is set. We do not consider them in the cross-validation.} \item{verbose}{\code{boolean} -- Print step number and relative change if TRUE and allVariables = TRUE} \item{...}{Reserved for parameters used in future version of the algorithm} } \value{ \item{nniRes}{Standard nni (nearest neighbour imputation) result object of this package. See \code{\link{nniRes}} for details.} } \description{ Missing value estimation using local least squares (LLS). First, k variables (for Microarrya data usually the genes) are selected by pearson, spearman or kendall correlation coefficients. Then missing values are imputed by a linear combination of the k selected variables. The optimal combination is found by LLS regression. The method was first described by Kim et al, Bioinformatics, 21(2),2005. } \details{ Missing values are denoted as \code{NA}\cr It is not recommended to use this function directely but rather to use the nni() wrapper function. The methods provides two ways for missing value estimation, selected by the \code{allVariables} option. The first one is to use only complete variables for the regression. This is preferable when the number of incomplete variables is relatively small. The second way is to consider all variables as candidates for the regression. Hereby missing values are initially replaced by the columns wise mean. The method then iterates, using the current estimate as input for the regression until the change between new and old estimate falls below a threshold (0.001). } \note{ Each step the generalized inverse of a \code{miss} x k matrix is calculated. Where \code{miss} is the number of missing values in variable j and \code{k} the number of neighbours. This may be slow for large values of k and / or many missing values. See also help("ginv"). } \examples{ ## Load a sample metabolite dataset (metaboliteData) with already 5\\\% of ## data missing data(metaboliteData) ## Perform llsImpute using k = 10 ## Set allVariables TRUE because there are very few complete variables result <- llsImpute(metaboliteData, k = 10, correlation="pearson", allVariables=TRUE) ## Get the estimated complete observations cObs <- completeObs(result) } \references{ Kim, H. and Golub, G.H. and Park, H. - Missing value estimation for DNA microarray gene expression data: local least squares imputation. \emph{Bioinformatics, 2005; 21(2):187-198.} Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and Hastie T. and Tibshirani R. and Botstein D. and Altman RB. - Missing value estimation methods for DNA microarrays. \emph{Bioinformatics. 2001 Jun;17(6):520-525.} } \seealso{ \code{\link{pca}, \link{nniRes}, \link{nni}}. } \author{ Wolfram Stacklies } \keyword{multivariate} pcaMethods/man/pca.Rd0000644000175000017500000000752314136047224014312 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pca.R \name{pca} \alias{pca} \title{Perform principal component analysis} \usage{ pca(object, method, nPcs = 2, scale = c("none", "pareto", "vector", "uv"), center = TRUE, completeObs = TRUE, subset = NULL, cv = c("none", "q2"), ...) } \arguments{ \item{object}{Numerical matrix with (or an object coercible to such) with samples in rows and variables as columns. Also takes \code{ExpressionSet} in which case the transposed expression matrix is used. Can also be a data frame in which case all numberic variables are used to fit the PCA.} \item{method}{One of the methods reported by \code{listPcaMethods()}. Can be left missing in which case the \code{svd} PCA is chosen for data wihout missing values and \code{nipalsPca} for data with missing values} \item{nPcs}{Number of principal components to calculate.} \item{scale}{Scaling, see \code{\link{prep}}.} \item{center}{Centering, see \code{\link{prep}}.} \item{completeObs}{Sets the \code{completeObs} slot on the resulting \code{pcaRes} object containing the original data with but with all NAs replaced with the estimates.} \item{subset}{A subset of variables to use for calculating the model. Can be column names or indices.} \item{cv}{character naming a the type of cross-validation to be performed.} \item{...}{Arguments to \code{\link{prep}}, the chosen pca method and \code{\link{Q2}}.} } \value{ A \code{pcaRes} object. } \description{ Perform PCA on a numeric matrix for visualisation, information extraction and missing value imputation. } \details{ This method is wrapper function for the following set of pca methods: \describe{\item{svd:}{Uses classical \code{prcomp}. See documentation for \code{\link{svdPca}}.} \item{nipals:}{An iterative method capable of handling small amounts of missing values. See documentation for \code{\link{nipalsPca}}.} \item{rnipals:}{Same as nipals but implemented in R.} \item{bpca:}{An iterative method using a Bayesian model to handle missing values. See documentation for \code{\link{bpca}}.} \item{ppca:}{An iterative method using a probabilistic model to handle missing values. See documentation for \code{\link{ppca}}.} \item{svdImpute:}{Uses expectation maximation to perform SVD PCA on incomplete data. See documentation for \code{\link{svdImpute}}.}} Scaling and centering is part of the PCA model and handled by \code{\link{prep}}. } \examples{ data(iris) ## Usually some kind of scaling is appropriate pcIr <- pca(iris, method="svd", nPcs=2) pcIr <- pca(iris, method="nipals", nPcs=3, cv="q2") ## Get a short summary on the calculated model summary(pcIr) plot(pcIr) ## Scores and loadings plot slplot(pcIr, sl=as.character(iris[,5])) ## use an expressionset and ggplot data(sample.ExpressionSet) pc <- pca(sample.ExpressionSet) df <- merge(scores(pc), pData(sample.ExpressionSet), by=0) library(ggplot2) ggplot(df, aes(PC1, PC2, shape=sex, color=type)) + geom_point() + xlab(paste("PC1", pc@R2[1] * 100, "\% of the variance")) + ylab(paste("PC2", pc@R2[2] * 100, "\% of the variance")) } \references{ Wold, H. (1966) Estimation of principal components and related models by iterative least squares. In Multivariate Analysis (Ed., P.R. Krishnaiah), Academic Press, NY, 391-420. Shigeyuki Oba, Masa-aki Sato, Ichiro Takemasa, Morito Monden, Ken-ichi Matsubara and Shin Ishii. A Bayesian missing value estimation method for gene expression profile data. \emph{Bioinformatics, 19(16):2088-2096, Nov 2003}. Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and Hastie T. and Tibshirani R. and Botstein D. and Altman RB. - Missing value estimation methods for DNA microarrays. \emph{Bioinformatics. 2001 Jun;17(6):520-5}. } \seealso{ \code{\link{prcomp}}, \code{\link{princomp}}, \code{\link{nipalsPca}}, \code{\link{svdPca}} } \author{ Wolfram Stacklies, Henning Redestig } \keyword{multivariate} pcaMethods/man/derrorHierarchic.Rd0000644000175000017500000000061414136047224017020 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/derrorHierarchic.R \name{derrorHierarchic} \alias{derrorHierarchic} \title{Later} \usage{ derrorHierarchic(nlnet, trainIn, trainOut) } \arguments{ \item{nlnet}{the nlnet} \item{trainIn}{training data} \item{trainOut}{fitted data} } \value{ derror } \description{ Later } \author{ Henning Redestig, Matthias Scholz } pcaMethods/man/vector2matrices-nlpcaNet-method.Rd0000644000175000017500000000074314136047224021700 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/vector2matrices.R \docType{methods} \name{vector2matrices,nlpcaNet-method} \alias{vector2matrices,nlpcaNet-method} \title{Tranform the vectors of weights to matrix structure} \usage{ \S4method{vector2matrices}{nlpcaNet}(object) } \arguments{ \item{object}{an nlpcaNet} } \value{ weights in matrix structure } \description{ Tranform the vectors of weights to matrix structure } \author{ Henning Redestig } pcaMethods/man/Q2.Rd0000644000175000017500000000654714136047224014036 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/xval.R \name{Q2} \alias{Q2} \title{Cross-validation for PCA} \usage{ Q2(object, originalData = completeObs(object), fold = 5, nruncv = 1, type = c("krzanowski", "impute"), verbose = interactive(), variables = 1:nVar(object), ...) } \arguments{ \item{object}{A \code{pcaRes} object (result from previous PCA analysis.)} \item{originalData}{The matrix (or ExpressionSet) that used to obtain the pcaRes object.} \item{fold}{The number of groups to divide the data in.} \item{nruncv}{The number of times to repeat the whole cross-validation} \item{type}{krzanowski or imputation type cross-validation} \item{verbose}{\code{boolean} If TRUE Q2 outputs a primitive progress bar.} \item{variables}{indices of the variables to use during cross-validation calculation. Other variables are kept as they are and do not contribute to the total sum-of-squares.} \item{...}{Further arguments passed to the \code{\link{pca}} function called within Q2.} } \value{ A matrix or vector with \eqn{Q^2} estimates. } \description{ Internal cross-validation can be used for estimating the level of structure in a data set and to optimise the choice of number of principal components. } \details{ This method calculates \eqn{Q^2} for a PCA model. This is the cross-validated version of \eqn{R^2} and can be interpreted as the ratio of variance that can be predicted independently by the PCA model. Poor (low) \eqn{Q^2} indicates that the PCA model only describes noise and that the model is unrelated to the true data structure. The definition of \eqn{Q^2} is: \deqn{Q^2=1 - \frac{\sum_{i}^{k}\sum_{j}^{n}(x - \hat{x})^2}{\sum_{i}^{k}\sum_{j}^{n}x^2}}{Q^2=1 - sum_i^k sum_j^n (x - \hat{x})^2 / \sum_i^k \sum_j^n(x^2)} for the matrix \eqn{x} which has \eqn{n} rows and \eqn{k} columns. For a given number of PC's x is estimated as \eqn{\hat{x}=TP'} (T are scores and P are loadings). Although this defines the leave-one-out cross-validation this is not what is performed if fold is less than the number of rows and/or columns. In 'impute' type CV, diagonal rows of elements in the matrix are deleted and the re-estimated. In 'krzanowski' type CV, rows are sequentially left out to build fold PCA models which give the loadings. Then, columns are sequentially left out to build fold models for scores. By combining scores and loadings from different models, we can estimate completely left out values. The two types may seem similar but can give very different results, krzanowski typically yields more stable and reliable result for estimating data structure whereas impute is better for evaluating missing value imputation performance. Note that since Krzanowski CV operates on a reduced matrix, it is not possible estimate Q2 for all components and the result vector may therefore be shorter than \code{nPcs(object)}. } \examples{ data(iris) x <- iris[,1:4] pcIr <- pca(x, nPcs=3) q2 <- Q2(pcIr, x) barplot(q2, main="Krzanowski CV", xlab="Number of PCs", ylab=expression(Q^2)) ## q2 for a single variable Q2(pcIr, x, variables=2) pcIr <- pca(x, nPcs=3, method="nipals") q2 <- Q2(pcIr, x, type="impute") barplot(q2, main="Imputation CV", xlab="Number of PCs", ylab=expression(Q^2)) } \references{ Krzanowski, WJ. Cross-validation in principal component analysis. Biometrics. 1987(43):3,575-584 } \author{ Henning Redestig, Ondrej Mikula } \keyword{multivariate} pcaMethods/man/pcaMethods-deprecated.Rd0000644000175000017500000000105414136047224017725 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pcaMethods-package.R \name{pcaMethods-deprecated} \alias{pcaMethods-deprecated} \title{Deprecated methods for pcaMethods} \description{ \describe{ \item{plotR2}{Lack of relevance for this plot and the fact that it can not show cross-validation based diagnostics in the same plot makes it redundant with the introduction of a dedicated \code{plot} function for \code{pcaRes}. The new plot only shows R2cum but the result is pretty much the same.}} } \author{ Henning Redestig } pcaMethods/man/nPcs-pcaRes-method.Rd0000644000175000017500000000074314136047224017140 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{nPcs,pcaRes-method} \alias{nPcs,pcaRes-method} \alias{nPcs} \title{Get number of PCs.} \usage{ nPcs(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{not used} } \value{ Number of PCs } \description{ Get number of PCs. } \note{ Try to use \code{link{nP}} instead since \code{nPcs} tend to clash with argument names. } \author{ Henning Redestig } pcaMethods/man/errorHierarchic.Rd0000644000175000017500000000060714136047224016656 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/errorHierarchic.R \name{errorHierarchic} \alias{errorHierarchic} \title{Later} \usage{ errorHierarchic(nlnet, trainIn, trainOut) } \arguments{ \item{nlnet}{The nlnet} \item{trainIn}{training data} \item{trainOut}{fitted data} } \value{ error } \description{ Later } \author{ Henning Redestig, Matthias Scholz } pcaMethods/man/loadings-ANY-method.Rd0000644000175000017500000000077614136047224017255 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{loadings,ANY-method} \alias{loadings,ANY-method} \alias{loadings} \title{Crude way to unmask the function with the same name from \code{stats}} \usage{ \S4method{loadings}{ANY}(object, ...) } \arguments{ \item{object}{any object} \item{...}{not used} } \value{ The loadings } \description{ Crude way to unmask the function with the same name from \code{stats} } \author{ Henning Redestig } pcaMethods/man/lineSearch.Rd0000644000175000017500000000104014136047224015610 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lineSearch.R \name{lineSearch} \alias{lineSearch} \title{Line search for conjugate gradient} \usage{ lineSearch(nlnet, dw, e0, ttGuess, trainIn, trainOut, verbose) } \arguments{ \item{nlnet}{The nlnet} \item{dw}{..} \item{e0}{..} \item{ttGuess}{..} \item{trainIn}{Training data} \item{trainOut}{Fitted data} \item{verbose}{logical, print messages} } \value{ ... } \description{ Line search for conjugate gradient } \author{ Henning Redestig, Matthias Scholz } pcaMethods/man/sDev-pcaRes-method.Rd0000644000175000017500000000077314136047224017141 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \docType{methods} \name{sDev,pcaRes-method} \alias{sDev,pcaRes-method} \alias{sDev} \title{Get the standard deviations of the scores (indicates their relevance)} \usage{ sDev(object, ...) } \arguments{ \item{object}{pcaRes object} \item{...}{Not used} } \value{ Standard devations of the scores } \description{ Get the standard deviations of the scores (indicates their relevance) } \author{ Henning Redestig } pcaMethods/man/loadings.pcaRes.Rd0000644000175000017500000000063514136047224016560 0ustar nileshnilesh% Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods-pcaRes.R \name{loadings.pcaRes} \alias{loadings.pcaRes} \title{Get loadings from a pcaRes object} \usage{ \method{loadings}{pcaRes}(object, ...) } \arguments{ \item{object}{a pcaRes object} \item{...}{not used} } \value{ The loadings as a matrix } \description{ Get loadings from a pcaRes object } \author{ Henning Redestig } pcaMethods/src/0000755000175000017500000000000014136077111013263 5ustar nileshnileshpcaMethods/src/nipals.cpp0000644000175000017500000000731114136047224015261 0ustar nileshnilesh#include #include #include using namespace std; using namespace Rcpp; double difference(vector& vec1, vector& vec2) { double diff = 0; double a; int len = vec1.size(); for(int i = 0; i < len; i++) { a = vec1[i] - vec2[i]; diff += a * a; } return(diff); } void norm(vector& vec) { double siz = 0; int len = vec.size(); for(int i = 0; i < len; i++) { siz += vec[i] * vec[i]; } siz = sqrt(siz); for(int i = 0; i < len; i++) { vec[i] = vec[i] / siz; } } // [[Rcpp::export]] List Nipals(SEXP Mat, SEXP params) { try{ bool cnt; int count = 0; double tsize; Rcpp::List rl = R_NilValue; Rcpp::List rparams(params); int maxSteps = Rcpp::as(rparams["maxSteps"]); double eps = Rcpp::as(rparams["threshold"]); int nPcs = Rcpp::as(rparams["nPcs"]); double varLimit = Rcpp::as(rparams["varLimit"]); Rcpp::NumericMatrix mat(Mat); Rcpp::NumericMatrix omat = Rcpp::clone( Mat ); int nr = mat.nrow(); int nc = mat.ncol(); Rcpp::NumericMatrix est_mat(nr, nc); Rcpp::NumericMatrix tt(nr, nPcs); Rcpp::NumericMatrix pp(nc, nPcs); vector r2cum; vector thold(nr); vector th(nr); vector phold(nc); vector ph(nc); double tss = 0; double sse = 0; int np = 0; double anotherPc = true; for (int r = 0; r < nr; r++) { for (int c = 0; c < nc; c++) { if(!ISNAN(mat(r,c))) { tss += mat(r,c) * mat(r,c); } } } while(anotherPc) { for(int r = 0; r < nr; r++) { th[r] = 0; if(!ISNAN(mat(r,0))) { th[r] = mat(r,0); } } cnt = true; count = 0; while(cnt) { count++; for(int c = 0; c < nc; c++) { ph[c] = 0; } tsize = 0; for(int r = 0; r < nr; r++) { tsize += th[r] * th[r]; } for(int r = 0; r < nr; r++) { double ti = th[r] / tsize; for(int c = 0; c < nc; c++) { if(!ISNAN(mat(r,c))) { ph[c] += mat(r,c) * ti; } } } norm(ph); thold = th; for(int r = 0; r < nr; r++) { th[r] = 0; for(int c = 0; c < nc; c++) { if(!ISNAN(mat(r,c))) { th[r] += mat(r,c) * ph[c]; } } } if(count > maxSteps) { throw 1; } if(difference(thold, th) <= eps) { cnt = false; } } //deflate mat sse = 0; double mathat = 0; double err = 0; for(int r = 0; r < nr; r++) { for(int c = 0; c < nc; c++) { if(!ISNAN(mat(r,c))) { mathat = th[r] * ph[c]; est_mat(r, c) += mathat; err = omat(r,c) - est_mat(r, c); sse += err * err; mat(r,c) -= mathat; } } } r2cum.push_back(1 - (sse / tss)); for(int r = 0; r < nr; r++) { tt(r,np) = th[r]; } for(int c = 0; c < nc; c++) { pp(c,np) = ph[c]; } if(fabs(varLimit - 1) > 1e-4) { if(r2cum[np] >= varLimit) { anotherPc = false; } } if (np + 1 >= nPcs){ anotherPc = false; } np++; } if(np != nPcs) { Rcpp::NumericMatrix ttt(nr, np); Rcpp::NumericMatrix ppp(nc, np); for(int r = 0; r < nr; r++) { for(int p = 0; p < np; p++) { ttt(r,p) = tt(r,p); } } for(int c = 0; c < nc; c++) { for(int p = 0; p < np; p++) { ppp(c,p) = pp(c,p); } } rl["scores"] = ttt; rl["loadings"] = ppp; } else { rl["scores"] = tt; rl["loadings"] = pp; } rl["R2cum"] = r2cum; return rl; }catch(int e) { if(e == 1) { ::Rf_error("Too many iterations, quitting"); }else { ::Rf_error("unknown error"); } } catch(std::exception& ex) { forward_exception_to_r(ex); } catch(...) { ::Rf_error("unknown error"); } return R_NilValue; } pcaMethods/src/RcppExports.cpp0000644000175000017500000000102414136047224016257 0ustar nileshnilesh#include using namespace Rcpp; // Nipals List Nipals(SEXP Mat, SEXP params); RcppExport SEXP pcaMethods_Nipals(SEXP MatSEXP, SEXP paramsSEXP) { BEGIN_RCPP SEXP __sexp_result; { Rcpp::RNGScope __rngScope; Rcpp::traits::input_parameter< SEXP >::type Mat(MatSEXP ); Rcpp::traits::input_parameter< SEXP >::type params(paramsSEXP ); List __result = Nipals(Mat, params); PROTECT(__sexp_result = Rcpp::wrap(__result)); } UNPROTECT(1); return __sexp_result; END_RCPP } pcaMethods/vignettes/0000755000175000017500000000000014136077111014504 5ustar nileshnileshpcaMethods/vignettes/outliers.Rnw0000644000175000017500000001203114136047224017041 0ustar nileshnilesh\documentclass[a4paper]{article} %\VignetteIndexEntry{Data with outliers} \usepackage{hyperref} \title{Handling of data containing outliers} \author{Wolfram Stacklies and Henning Redestig\\ CAS-MPG Partner Institute for Computational Biology (PICB)\\ Shanghai, P.R. China \\ and\\ Max Planck Institute for Molecular Plant Physiology\\ Potsdam, Germany\\ \url{http://bioinformatics.mpimp-golm.mpg.de/} } \date{\today} \begin{document} \setkeys{Gin}{width=1.0\textwidth} @ \maketitle \section{PCA robust to outliers} Away from often showing missing values, Microarray or Metabolite data are often corrupted with extreme values (outliers). Standard SVD is highly susceptible to outliers. In the extreme case, an individual data point, if sufficiently outlying, can draw even the leading principal component toward itself. This problem can be addressed by using a robust analysis method. Hereto we provide \texttt{robustSvd}, a singular value decomposition robust to outliers. \texttt{robustPca} is a PCA implementation that resembles the original \texttt{R} \texttt{prcomp} method, with the difference that it uses \texttt{robustSvd} instead of the standard \texttt{svd} function.\\ Robust SVD and its application to microarray data were proposed in \cite{hawkins01} and \cite{liu03}. The algorithm is based on the idea to use a sequential estimation of the eigenvalues and left and right eigenvectors that ignores missing values and is resistant to outliers. \\ The \texttt{robustSvd} script included here was contributed by Kevin Wright. Thanks a lot to him! \section{Outliers and missing value imputation} The problem of outliers is similar to the missing data problem in the sense that extreme values provide no or wrong information. They are generally artifacts of the experiment and provide no information about the underlying biological processes. \\ Most of the PCA methods coming with the package were not designed to be robust to outliers in the sense that they will converge to the standard PCA solution on a complete data set. Yet, an applicable solution is to remove obvious outliers from the data first (by setting them NA) and to then estimate the PCA solution on the incomplete data. This is likely to produce accurate results if the number of missing data does not exceed a certain amount, less than 10\% should be a good number. The following example illustrates the effect of outliers and the use of robust methods. First, we attach the complete metabolite data set and create 5\% outliers. We mean center the data before we create outliers because these large artificial outliers will strongly shift the original means. This would not allow for objective comparison between the differnt results obtained, e.g. when doing scatterplots. <>= library(pcaMethods) @ <<>>= data(metaboliteDataComplete) mdc <- scale(metaboliteDataComplete, center=TRUE, scale=FALSE) cond <- runif(length(mdc)) < 0.05 mdcOut <- mdc mdcOut[cond] <- 10 @ Then we calculate a PCA solution using standard SVD and robust SVD. <>= resSvd <- pca(mdc, method="svd", nPcs=5, center=FALSE) resSvdOut <- pca(mdcOut, method="svd", nPcs=5, center=FALSE) resRobSvd <- pca(mdcOut, method="robustPca", nPcs=5, center=FALSE) @ Now we use \texttt{PPCA} to estimate the PCA solution, but set the outliers NA before. <>= mdcNa <- mdc mdcNa[cond] <- NA resPPCA <- pca(mdcNa, method="ppca", nPcs=5, center=FALSE) @ To check the robustness to outliers we can just do a scatterplot comparing the results to the optimal PCA solution for the complete data set (which is \texttt{resSvd}). In Figure \ref{fig:svdPlot} we plot the estimated and original loadings against each other. \begin{figure}[!ht] \centering <>= par(mfrow=c(2,2)) plot(loadings(resSvd)[,1], loadings(resSvdOut)[,1], xlab="Loading 1 SVD", ylab="Loading 1 SVD with outliers") plot(loadings(resSvd)[,1], loadings(resRobSvd)[,1], xlab="Loading 1 SVD", ylab="Loading 1 robustSVD with outliers") plot(loadings(resSvd)[,1], loadings(resPPCA)[,1], xlab="Loading 1 SVD", ylab="Loading 1 PPCA with outliers=NA") plot(loadings(resRobSvd)[,1], loadings(resPPCA)[,1], xlab="Loading 1 robust SVD with outliers", ylab="Loading 1 svdImpute with outliers=NA") @ \caption{Figures show (from left to right): \newline Original PCA solution vs. solution on data with outliers; \newline Original PCA solution vs. robust PCA solution on data with outliers; \newline Original PCA solution vs. PPCA solution on data where outliers=NA; \newline Robust PCA solution vs. PPCA solution on data with outliers / outliers=NA. \label{fig:svdPlot} } \end{figure} \begin{thebibliography}{2006} \bibitem{hawkins01} Hawkins, D.M., Liu, L. and Young, S.S. {\sl Robust Singular Value Decomposition.} National Institute of Statistical Sciences, 2001, Tech Report 122. \bibitem{liu03} Liu, L., Hawkins, D.M., Ghosh, S. and Young, S.S. {\sl Robust singular value decomposition analysis of microarray data.} PNAS, 2003;100:13167--13172. \end{thebibliography} \end{document} pcaMethods/vignettes/missingValues.Rnw0000644000175000017500000000565414136047224020041 0ustar nileshnilesh\documentclass[a4paper]{article} %\VignetteIndexEntry{Missing value imputation} \usepackage{hyperref} \title{Imputing missing values using the pcaMethods package} \author{Wolfram Stacklies and Henning Redestig\\ CAS-MPG Partner Institute for Computational Biology (PICB)\\ Shanghai, P.R. China \\ and\\ Max Planck Institute for Molecular Plant Physiology\\ Potsdam, Germany\\ \url{http://bioinformatics.mpimp-golm.mpg.de/} } \date{\today} \begin{document} \setkeys{Gin}{width=1.0\textwidth} @ \maketitle \section{Missing value imputation} One application for missing value robust principal component analysis is that it effectively can be used to impute the missing values and thus obtain an estimated complete data set. The pcaMethods package was partly written with this application in mind. PCA is a way of creating a model of a matrix, $X$, by defining two parameter matrices, the scores, $T$, and the loadings, $P$, which together have less values than the original matrix but when multiplied with each other well reconstruct the original matrix. I.e.: $$X=1\times{}\bar{x} + TP' + E$$ where $E$ is the error matrix and $1\times{}\bar{x}$ denotes the original variable averages. Now if $X$ contains missing values but we still are able to get complete estimates of $P$ and $T$ than we can use: $$\hat{X}=1\times{}\bar{x} + TP'$$ as an estimate for $x_{i,j}$ if $x_{i,j}$ is missing. This is can be done as the following example illustrates. First we attach the metabolite data set with missing values. <>= library(pcaMethods) @ <<>>= data(metaboliteData) mD <- metaboliteData sum(is.na(mD)) @ Now we get the estimated data set by using PPCA and three principal components. <<>>= pc <- pca(mD, nPcs=3, method="ppca") imputed <- completeObs(pc) @ If we compare with the original values we see that the error is rather low. <<>>= data(metaboliteDataComplete) mdComp <- metaboliteDataComplete sum((mdComp[is.na(mD)] - imputed[is.na(mD)])^2) / sum(mdComp[is.na(mD)]^2) @ When using a different PCA algorithm, we get different performance. <<>>= imputedNipals <- completeObs(pca(mD, nPcs=3, method="nipals")) sum((mdComp[is.na(mD)] - imputedNipals[is.na(mD)])^2) / sum(mdComp[is.na(mD)]^2) @ If the data we are interested in was gene expression set of class 'ExpressionSet' we could simply do <<>>= library(Biobase) data(sample.ExpressionSet) exSet <- sample.ExpressionSet exSetNa <- exSet exprs(exSetNa)[sample(13000, 200)] <- NA lost <- is.na(exprs(exSetNa)) pc <- pca(exSetNa, nPcs=2, method="ppca") impExSet <- asExprSet(pc, exSetNa) sum((exprs(exSet)[lost] - exprs(impExSet)[lost])^2) / sum(exprs(exSet)[lost]^2) @ Different results will be obtained with different PCA algorithms. Which one to use depends on the general structure of the data set and the imputation performance can be estimated by cross-validation. Please see the 'introduction' vignette on further details on how to use the cross-validation capabilities of this package. \end{document} pcaMethods/vignettes/pcaMethods.Rnw0000644000175000017500000005554214136047224017300 0ustar nileshnilesh\documentclass[a4paper]{article} %\VignetteIndexEntry{Introduction} \usepackage{hyperref} \title{The pcaMethods Package} \author{Wolfram Stacklies and Henning Redestig\\ CAS-MPG Partner Institute for Computational Biology (PICB)\\ Shanghai, P.R. China \\ and\\ Max Planck Institute for Molecular Plant Physiology\\ Potsdam, Germany\\ \url{http://bioinformatics.mpimp-golm.mpg.de/} } \date{\today} \begin{document} \setkeys{Gin}{width=1.0\textwidth} @ \maketitle \section*{Overview} The \texttt{pcaMethods} package \cite{stacklies07} provides a set of different PCA implementations, together with tools for cross validation and visualisation of the results. The methods basically allow to perform PCA on incomplete data and thus may also be used for missing value estimation. When doing PCA one assumes that the data is restricted to a subspace of lower dimensionality, e.g. correlation patterns between jointly regulated genes. PCA aims to extract these structures thereby filtering noise out. If only the most significant loadings (eigenvectors, also referred to as principal components) are used for projection this can be written as: \begin{equation} X = 1\times{}\bar{x}^T + TP^T + V \end{equation} Where the term $1\times{}\bar{x}^T$ represents the original variable averages, $X$ denotes the observations, $T={t_1, t_2,\ldots,t_k}$ the latent variables or scores, $P={p_1, p_2,\ldots,p_k}$ the transformation matrix (consisting of the most significant eigenvectors of the covariance matrix) and $V$ are the residuals. Missing values may be estimated by projecting the scores back into the original space using $\hat{X} = 1\times{}\bar{x}^T + TP^T$. Optimally, this produces an estimate of the missing data based on the underlying correlation structure, thereby ignoring noise. This will only produce reasonable results if the residuals $V$ are sufficiently small, implying that most of the important information is captured by the first $k$ components. In order to calculate the transformation matrix $P$ one needs to determine the covariance matrix between variables or alternatively calculate $P$ directly via SVD. In both cases, this can only be done on complete matrices. However, an approximation may be obtained by use of different regression methods. The PCA methods provided in this package implement algorithms to accurately estimate the PCA solution on incomplete data. Although the focus of this package is clearly to provide a collection of PCA methods we also provide a cluster based method for missing value imputation. This allows to better rate and compare the results. \section{Algorithms} All methods return a common class called \texttt{pcaRes} as a container for the results. This guarantees maximum flexibility for the user. A wrapper function called \texttt{pca()} is provided that receives the desired type of pca as a string. \subsection*{svdPca} This is a wrapper function for $R's$ standard \texttt{prcomp} function. It delivers the results as a \texttt{pcaRes} object for compatibility with the rest of the package. \subsection*{svdImpute} This implements the SVDimpute algorithm as proposed by Troyanskaya et~al \cite{troyanskaya01}. The idea behind the algorithm is to estimate the missing values as a linear combination of the $k$ most significant eigengenes\footnote{The term ``eigengenes'' denotes the loadings when PCA was applied considering variables (here the genes) as observations.}. The algorithm works iteratively until the change in the estimated solution falls below a certain threshold. Each step the eigengenes of the current estimate are calculated and used to determine a new estimate. An optimal linear combination is found by regressing an incomplete variable against the $k$ most significant eigengenes. If the value at position $j$ is missing, the $j^{th}$ value of the eigengenes is not used when determining the regression coefficients.\\ SVDimpute seems to be tolerant to relatively high amount of missing data (> 10\%). \subsection*{Probabilistic PCA (ppca)} Probabilistic PCA combines an EM approach for PCA with a probabilistic model. The EM approach is based on the assumption that the latent variables as well as the noise are normal distributed. In standard PCA data which is far from the training set but close to the principal subspace may have the same reconstruction error, see Figure \ref{fig:pcaSubspace} for explanation. <>= library(pcaMethods) x <- c(-4,7); y <- c(-3,4) distX <- rnorm(100, sd=0.3)*3 distY <- rnorm(100, sd=0.3) + distX * 0.3 mat <- cbind(distX, distY) res <- pca(mat, nPcs=2, method="svd", center=F) loading <- loadings(res)[1,] grad <- loading[2] / loading[1] if (grad < 0) grad <- grad * -1 lx <- c(-4,7) ly <- c(grad * -4, grad * 7) @ \begin{figure} \centering <>= par(mar=c(2, 3, 2, 2)) plot(x,y, type="n", xlab="", ylab="") abline(v=0, col="dark gray", lwd = 2); abline(h=0, col = "dark gray", lwd = 2) points(distX, distY, type = 'p', col = "blue") lines(lx,ly, lwd = 2) points(-1, -1 * grad + 0.5, pch = 19, col = "red", lwd=4) points(6, 6 * grad + 0.5, pch = 19, col = "red", lwd=4) @ \caption{Normal distributed data with the first loading plotted in black. The two red points have the same reconstruction error because PCA does not define a density model. Thus the only measure of how well new data fits the model is the distance from the principal subspace. Data points far from the bulk of data but still close to the principal subspace will have a low reconstruction error. \label{fig:pcaSubspace}} \end{figure} PPCA defines a likelihood function such that the likelihood for data far from the training set is much lower, even if they are close to the principal subspace. This allows to improve the estimation accuracy.\\ PPCA is tolerant to amounts of missing values between 10\% to 15\%. If more data is missing the algorithm is likely not to converge to a reasonable solution. The method was implemented after the draft ``\texttt{EM Algorithms for PCA and Sensible PCA}'' written by Sam Roweis and after the Matlab \texttt{ppca} script implemented by \emph{Jakob Verbeek}\footnote{\url{http://lear.inrialpes.fr/~verbeek/}}. Please check also the PPCA help file. \subsection*{Bayesian PCA (bpca)} Similar to probabilistic PCA, Bayesian PCA uses an EM approach together with a Bayesian model to calculate the likelihood for a reconstructed value.\\ The algorithm seems to be tolerant to relatively high amounts of missing data (> 10\%). Scores and loadings obtained with Bayesian PCA slightly differ from those obtained with conventional PCA. This is because BPCA was developed especially for missing value estimation and is based on a variational Bayesian framework (VBF), with automatic relevance determination (ARD). In BPCA, ARD leads to a different scaling of the scores, loadings and eigenvalues when compared to standard PCA or PPCA. The algorithm does not force orthogonality between loadings. However, the authors of the BPCA paper found that including an orthogonality criterion made the predictions worse. They also state that the difference between ``real'' and predicted Eigenvalues becomes larger when the number of observation is smaller, because it reflects the lack of information to accurately determine true loadings from the limited and noisy data. As a result, weights of factors to predict missing values are not the same as with conventional PCA, but the missing value estimation is improved. BPCA was proposed by Oba et~al \cite{oba03}. The method available in this package is a port of the \texttt{bpca} Matlab script also provided by the authors\footnote{ \url{http://hawaii.aist-nara.ac.jp/\%7Eshige-o/tools/}}. \subsection*{Inverse non-linear PCA (NLPCA)} NLPCA \cite{scholz05} is especially suitable for data from experiments where the studied response is non-linear. Examples of such experiments are ubiquitous in biology -- enzyme kinetics are inherently non-linear as are gene expression responses influenced by the cell cycle or diurnal oscillations. NLPCA is based on training an auto-associative neural network composed of a component layer which serves as the ``bottle-neck'', a hidden non-linear layer and an output layer corresponding to the reconstructed data. The loadings can be seen as hidden in the network. Missing values in the training data are simply ignored when calculating the error during back-propagation. Thus NLPCA can be used to impute missing values in the same way as for conventional PCA. The only difference is that the loadings $P$ are now represented by a neural network.\\ A shortcoming of the current implementation is that there is no reasonable stop criterion. The quality of the estimated solution depends on the number of iterations. This should in most cases be somewhat between 500 and 1500. We recommend to use \texttt{kEstimate} or \texttt{kEstimateFast} to determine this parameter. \subsection*{Nipals PCA} Nipals (Nonlinear Estimation by Iterative Partial Least Squares) \cite{wold66} is an algorithm at the root of PLS regression which can execute PCA with missing values by simply leaving those out from the appropriate inner products. It is tolerant to small amounts (generally not more than 5\%) of missing data. \subsection{Local least squares (LLS) imputation} The package provides an algorithm called \texttt{llsImpute} for missing value estimation based on a linear combination of the $k$ nearest neighbours of an incomplete variable (in Microarray experiments normally a gene). The distance between variables is defined as the absolute value of the Pearson, Spearman or Kendall correlation coefficient. The optimal linear combination is found by solving a local least squares problem as described in \cite{kim05}. In tests performed in the cited paper the llsImpute algorithm is able to outperform knnImpute\cite{troyanskaya01} and competes well with BPCA. In the current implementation two slightly different ways for missing value estimation are provided. The first one is to restrict the neighbour searching to the subset of complete variables. This is preferable when the number of incomplete variables is relatively small. The second way is to consider all variables as candidates. Here, missing values are initially replaced by the columns wise mean. The method then iterates, using the current estimate as input for the LLS regression until the change between new and old estimate falls below a certain threshold (0.001). \section{Getting started} \paragraph{Installing the package.} To install the package first download the appropriate file for your platform from the Bioconductor website (\url{http://www.bioconductor.org/}). For Windows, start \texttt{R} and select the \texttt{Packages} menu, then \texttt{Install package from local zip file}. Find and highlight the location of the zip file and click on \texttt{open}. For Linux/Unix, use the usual command \texttt{R CMD INSTALL} or set the option \texttt{CRAN} to your nearest mirror site and use the command \texttt{install.packages} from within an \texttt{R} session. \paragraph{Loading the package:} To load the \texttt{pcaMethods} package in your \texttt{R} session, type \texttt{library(pcaMethods)}. \paragraph{Help files:} Detailed information on \texttt{pcaMethods} package functions can be obtained from the help files. For example, to get a description of \texttt{bpca} type \texttt{help("bpca")}. \paragraph{Sample data:} Two sample data sets are coming with the package. \texttt{metaboliteDataComplete} contains a complete subset from a larger metabolite data set. \texttt{metaboliteData} is the same data set but with 10 \% values removed from an equal distribution. \section{Some examples} <>= library(lattice) library(pcaMethods) @ To load the package and the two sample data sets type: <>= library(pcaMethods) data(metaboliteData) data(metaboliteDataComplete) @ Now centre the data <<>>= md <- prep(metaboliteData, scale="none", center=TRUE) mdC <- prep(metaboliteDataComplete, scale="none", center=TRUE) @ Run SVD pca, PPCA, BPCA, SVDimpute and nipalsPCA on the data, using the \texttt{pca()} wrapper function. The result is always a \texttt{pcaRes} object. <>= resPCA <- pca(mdC, method="svd", center=FALSE, nPcs=5) resPPCA <- pca(md, method="ppca", center=FALSE, nPcs=5) resBPCA <- pca(md, method="bpca", center=FALSE, nPcs=5) resSVDI <- pca(md, method="svdImpute", center=FALSE, nPcs=5) resNipals <- pca(md, method="nipals", center=FALSE, nPcs=5) resNLPCA <- pca(md, method="nlpca", center=FALSE, nPcs=5, maxSteps=300) @ Figure \ref{fig:eigenvalues} shows a plot of the eigenvalue structure (\texttt{sDev(pcaRes)}). If most of the variance is captured with few loadings PCA is likely to produce good missing value estimation results. For the sample data all methods show similar eigenvalues. One can also see that most of the variance is already captured by the first loading, thus estimation is likely to work fine on this data. For BPCA, the eigenvalues are scaled differently for reasons discussed above, see Figure \ref{fig:loadingBPCA}. The order of the loadings remains the same. \begin{figure} \centering <>= sDevs <- cbind(sDev(resPCA), sDev(resPPCA), sDev(resBPCA), sDev(resSVDI), sDev(resNipals), sDev(resNLPCA)) matplot(sDevs, type = 'l', xlab="Eigenvalues", ylab="Standard deviation of PC", lwd=3) legend(x="topright", legend=c("PCA", "PPCA", "BPCA", "SVDimpute","Nipals PCA","NLPCA"), lty=1:6, col=1:6, lwd=3) @ \caption{Eigenvalue structure as obtained with different methods\label{fig:eigenvalues}} \end{figure} To get an impression of the correctness of the estimation it is a good idea to plot the scores / loadings obtained with classical PCA and one of the probabilistic methods against each other. This of course requires a complete data set from which data is randomly removed. Figure \ref{fig:loadingBPCA} shows this for BPCA on the sample data. \begin{figure} \centering <>= par(mfrow=c(1,2)) plot(loadings(resBPCA)[,1], loadings(resPCA)[,1], xlab="BPCA", ylab="classic PCA", main = "Loading 1") plot(loadings(resBPCA)[,2], loadings(resPCA)[,2], xlab="BPCA", ylab="classic PCA", main = "Loading 2") @ \caption{Loading 1 and 2 calculated with BPCA plotted against those calculated with standard PCA. \label{fig:loadingBPCA}} \end{figure} \section{Cross validation} \texttt{Q2} is the goodness measure used for internal cross validation. This allows to estimate the level of structure in a data set and to optimise the choice of number of loadings. Cross validation is performed by removing random elements of the data matrix, then estimating these using the PCA algorithm of choice and then calculating $Q^2$ accordingly. At the moment, cross-validation can only be performed with algorithms that allow missing values (i.e. not SVD). Missing value independent cross-validation is scheduled for implementation in later versions. $Q^2$ is defined as following for the mean centered data (and possibly scaled) matrix $X$. $$\mathrm{SSX}=\sum (x_{ij})^2$$ $$\mathrm{PRESS}=\sum (x_{ij} - \hat{x}_{ij})^2$$ $$Q^2=1 - \mathrm{PRESS}/\mathrm{SSX}$$ The maximum value for $Q^2$ is thus 1 which means that all variance in $X$ is represented in the predictions; $X=\hat{X}$. <>= q2SVDI <- Q2(resSVDI, mdC, fold=10) q2PPCA <- Q2(resPPCA, mdC, fold=10) @ <>= # PPCA does not converge / misestimate a value in very rare cases. # This is a workaround to avoid that such a case will break the # diagram displayed in the vignette. # From the 2.0 release of bioconductor on, the convergence threshold # for PPCA was lowert to 1e-5, this should make the method much more # stable. So this workaround might be obsolete now... # [nope it is not, ppca is unstable] while( sum((abs(q2PPCA)) > 1) >= 1 ) { q2PPCA <- Q2(resPPCA, mdC, fold=10) } @ \begin{figure}[!ht] \centering <>= q2 <- data.frame(Q2=c(drop(q2PPCA), drop(q2SVDI)), method=c("PPCA", "SVD-Impute")[gl(2, 5)], PC=rep(1:5, 2)) print(xyplot(Q2~PC|method, q2, ylab=expression(Q^2), type="h", lwd=4)) @ \caption{Boxplot of the \texttt{Q2} results for BPCA, Nipals PCA, SVDimpute and PPCA. PPCA and SVDimpute both deliver better results than BPCA and Nipals in this example.\label{fig:Q2}} \end{figure} The second method called \texttt{kEstimate} uses cross validation to estimate the optimal number of loadings for missing value estimation. The \texttt{NRMSEP} (normalised root mean square error of prediction) \cite{feten05} or Q2 can be used to define the average error of prediction. The NRMSEP normalises the square difference between real and estimated values for a certain variable by the variance within this variable. The idea behind this normalisation is that the error of prediction will automatically be higher if the variance is higher. The \texttt{NRMSEP} for mean imputation is $\sqrt{\frac{nObs}{nObs - 1}}$ when cross validation is used, where $nObs$ is the number of observations. The exact definition is: \begin{equation} NRMSEP_k = \sqrt{\frac{1}{g} \sum_{j \in G} \frac{\sum_{i \in O_j} (x_{ij} - \hat{x}_{ijk})^2}{o_j s_{x_j}^2}} \end{equation} where $s^2_{x_j} = \sum_{i=1}^n (x_{ij} - \overline{x}_j)^2 / (n - 1)$, this is the variance within a certain variable. Further, $G$ denotes the set of incomplete variables, $g$ is the number of incomplete varialbes. $O_j$ is the set of missing observations in variable $j$ and $o_j$ is the number of missing observations in variable $j$. $\hat{x}_{ijk}$ stands for the estimate of value $i$ of variable $j$ using $k$ loadings. See Figure \ref{fig:kEstimate} for an example. The NRMSEP should be the error measure of choice. But if the number of observations is small, the variance within a certain variable may become and unstable criterion. If so or if variance scaling was applied we recommend to use Q2 instead. <>= errEsti <- kEstimate(md, method = "ppca", evalPcs=1:5, nruncv=1, em="nrmsep") @ \begin{figure}[!ht] \centering \begin{minipage}[c]{0.6\textwidth} \centering <>= barplot(drop(errEsti$eError), xlab="Loadings", ylab="NRMSEP (Single iteration)") @ \end{minipage} \begin{minipage}[c]{0.3\textwidth} \caption{Boxplot showing the \texttt{NRMSEP} versus the number of loadings. In this example only 1 iteration of the whole cross validation were performed. It is normally advisable to do more than just one iteration. \label{fig:kEstimate}} \end{minipage} \end{figure} \texttt{kEstimate} also provides information about the estimation error for individual variables. The $Q^2$ distance or the NRMSEP are calculated separately for each variable. See the manpage for \texttt{kEstimate} and \texttt{kEstimateFast} for details. Plotting the variable - wise results gives information about for which variables missing value estimation makes sense, and for which no imputation or mean imputation is preferable, see Figure \ref{fig:variableWiseError}. If you are not interested in variable - wise information we recommend to use the faster \texttt{kEstimateFast} instead. \begin{figure}[!ht] \centering \begin{minipage}[c]{0.6\textwidth} \centering <>= barplot(drop(errEsti$variableWiseError[, which(errEsti$evalPcs == errEsti$bestNPcs)]), xlab="Incomplete variable Index", ylab="NRMSEP") @ \end{minipage} \begin{minipage}[c]{0.3\textwidth} \caption{Boxplot showing the \texttt{NRMSEP} for all incomplete variables in the data set. For the first 7 variables missing value imputation does not seem to make too much sense. \label{fig:variableWiseError}} \end{minipage} \end{figure} \newpage \section{Visualisation of the results} \subsection{Quick scores and loadings plot} Some methods for display of scores and loadings are also provided. The function \texttt{slplot()} aims to be a simple way to quickly visualise scores and loadings in an intuitive way, see Figure \ref{fig:slplot}. Barplots are provided when plotting only one PC and colours can be specified differently for the scores and loadings plots. For a more specific scatter plot it is however recommended to access scores and loadings slots and define own plot functions. \begin{figure}[!h] \centering <>= slplot(resPCA) @ \caption{\texttt{slplot} for scores and loadings obtained with classical SVD based PCA. \label{fig:slplot}} \end{figure} \noindent Another method called \texttt{plotPcs()} allows to visualise many PCs plotted against each other, see Figure \ref{fig:plotPcs}. \begin{figure}[!ht] \centering <>= plotPcs(resPPCA, pc=1:3, type="score") @ \caption{A plot of score 1:3 for PPCA created with \texttt{plotPcs()} \label{fig:plotPcs}} \end{figure} \subsection{Using ggplot2} For using ggplot, the scores and loadings should best be added to a data frame that add other relevant descriptive factors. For example, after doing PCA on the Iris dataset, we may add the scores back to the original data frame and use ggplot to visualise, see Figure \ref{fig:ggplot}. \begin{figure}[!ht] \centering <>= pc <- pca(iris) irdf <- merge(iris, scores(pc), by=0) library(ggplot2) ggplot(irdf, aes(PC1, PC2, colour=Species)) + geom_point() + stat_ellipse() @ \caption{Score plot using ggplot2} \label{fig:ggplot} \end{figure} \cleardoublepage \begin{thebibliography}{2006} \bibitem{stacklies07} Stacklies W., Redestig H., Scholz M., and Walther D., and Selbig J. {\sl pcaMethods -- a Bioconductor package providing PCA methods for incomplete data} Bioinformatics. 2007, 23, 1164-1167. {\sl Non-linear PCA: a missing data approach.} Bioinformatics. 2005, 21, 3887-3895. \bibitem{scholz05} Scholz, M. , Kaplan, F., Guy, C.L., Kopka, J. and Selbig, J. {\sl Non-linear pca: a missing data approach.} Bioinformatics. 2005, 21, 3887-3895. \bibitem{troyanskaya01} Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and Hastie T. and Tibshirani R. and Botstein D. and Altman RB. {\sl Missing value estimation methods for DNA microarrays.} Bioinformatics. 2001 Jun;17(6):520-525. \bibitem{feten05} Feten G. and Almoy T. and Aastveit A.H. {\sl Prediction of Missing Values in Microarray and Use of Mixed Models to Evaluate the Predictors.}, Stat. Appl. Genet. Mol. Biol. 2005;4(1):Article 10 \bibitem{oba03} Oba S. and Sato MA. and Takemasa I. and Monden M. and Matsubara K. and Ishii S. {\sl A Bayesian missing value estimation method for gene expression profile data.} Bioinformatics. 2003 Nov 1;19(16):2088-96. \bibitem{wold66} Wold H. {Estimation of principal components and related models by iterative least squares.} In Multivariate Analysis (Ed. P.R. Krishnaiah), Academic Press, NY, 391-420. \bibitem{kim05} Kim H. and Golub G.H. and Park H. {\sl Missing value estimation for DNA microarray gene expression data: local least squares imputation} Bioinformatics. 2005 21(2) :187-198 \end{thebibliography} \end{document} pcaMethods/build/0000755000175000017500000000000014136077111013573 5ustar nileshnileshpcaMethods/build/vignette.rds0000644000175000017500000000042214136077111016130 0ustar nileshnileshRn0t1_*TUUիb)#!ƏxK=x홵ggmDGc HH&0 a4I^eSU\pˌ*ֱCźwV, %])ƵֳZ*;jd 'oeRg:::u>Ϗ"c'<}#iK.EqÛ xIn须qK.^k M,v~ie95Ɉc% }KLpcaMethods/R/0000755000175000017500000000000014136047224012677 5ustar nileshnileshpcaMethods/R/derrorHierarchic.R0000644000175000017500000001251114136047224016301 0ustar nileshnilesh##' Later ##' @param nlnet the nlnet ##' @param trainIn training data ##' @param trainOut fitted data ##' @return derror ##' @author Henning Redestig, Matthias Scholz derrorHierarchic <- function(nlnet, trainIn, trainOut) { weights <- nlnet@weights$current() netDim <- dim(nlnet@net) if(nlnet@inverse) { numElements <- nlnet@net[1] * dim(trainOut)[2] trainIn <- matrix(weights[1:numElements], nrow=nlnet@net[1], ncol=dim(trainOut)[2]) wTrainIn <- weights[1:numElements,drop=FALSE] weights <- weights[(numElements + 1):length(weights), ,drop=FALSE] } weightMats <- vector2matrices(weights, nlnet@net) trainDim <- dim(trainIn) subnetNum <- length(nlnet@hierarchic$var) ## ****************************** Epattern <- array(0, dim=c(dim(trainOut), subnetNum)) nOut <- array(0, dim=c(sum(nlnet@net), trainDim[2], subnetNum)) for(subnet in 1:subnetNum) nOut[1:trainDim[1],,subnet] <- eval(parse(text=paste(nlnet@fct[1], "(trainIn)"))) if(nlnet@inverse) for(subnet in 1:subnetNum) nOut[nlnet@hierarchic$idx[,subnet]==0,,subnet] <- 0 ## forward propagation for(subnet in 1:subnetNum) { if(nlnet@hierarchic$var[subnet] != 0) { sBias <- array(1, dim=c(1, trainDim[2])) for(i in 1:(netDim[2] - 1)) { if(i == 1) nBegin <- 1 else nBegin <- sum(nlnet@net[1:(i-1)])+1 sIn <- rbind(sBias, nOut[nBegin:sum(nlnet@net[1:i]),,subnet]) sOut <- eval(parse(text=paste(nlnet@fct[i+1], "(weightMats[[i]] %*% sIn)"))) if(i == (nlnet@hierarchic$layer - 1)) sOut[nlnet@hierarchic$idx[,subnet]==0,] <- 0 nOut[(sum(nlnet@net[1:i])+1):sum(nlnet@net[1:(i+1)]),,subnet] <- sOut } output <- nOut[(sum(nlnet@net[1:(length(nlnet@net)-1)])+1):dim(nOut)[1],,subnet] Epattern[,,subnet] <- output - trainOut } } ## error function Epattern <- Epattern^2 Epattern[is.na(Epattern)] <- 0 #set the missing values to zero if(!is.null(nlnet@dataDist)) for(subnet in 1:subnetNum) Epattern[,,subnet] <- Epattern[,,subnet] * nlnet@dataDist Eitemize <- apply(Epattern, 3, sum) * 0.5 Etotal <- sum(nlnet@hierarchic$var * Eitemize) if(!is.null(nlnet@weightDecay)) Etotal <- Etotal + nlnet@weightDecay * 0.5 * sum(weights^2) if(nlnet@inverse) Etotal <- Etotal + 0.01 * nlnet@weightDecay * 0.5 * sum(wTrainIn^2) ## back propagation nError <- array(0, dim=c(sum(nlnet@net), trainDim[2], subnet)) dWeight <- vector(length=netDim[2] - 1, mode="list") wBp <- vector(length=netDim[2] - 1, mode="list") ## wBp is weights for back propagation for(u in 1:(netDim[2] - 1)) wBp[[u]] <- weightMats[[u]][,2:(nlnet@net[u] + 1)] # cats the weights which belong to bias dw <- array(0, dim=c(length(weights), subnet)) for(subnet in 1:subnetNum) { if(nlnet@hierarchic$var[subnet] != 0) { ## last layer sTmp <- nOut[(dim(nOut)[1]-nlnet@net[length(nlnet@net)]+1):dim(nOut)[1],,subnet] if(nlnet@fct[length(nlnet@fct)] == "tanh") eTmp <- (1 - sTmp^2) * (sTmp - trainOut) #prev trainOut - sTmp (fixed to get rid of sign change) else if(nlnet@fct[length(nlnet@fct)] == "linr") eTmp <- sTmp - trainOut #prev trainOut - sTmp (fixed to get rid of sign change) eTmp[is.na(eTmp)] <- 0 if(!is.null(nlnet@dataDist)) eTmp <- eTmp * nlnet@dataDist nError[(dim(nError)[1]-nlnet@net[length(nlnet@net)]+1):dim(nError)[1],,subnet] <- eTmp ## all other layers for(n in 1:(netDim[2] - 1)){ i <- netDim[2]-n ## the if clause is to avoid 1:0 difference in R ## Matlab (1:0 => Empty matrix), R (1:0 => [1,0]) if(i > 1) sTmp <- nOut[(sum(nlnet@net[1:(i-1)])+1):sum(nlnet@net[1:i]),,subnet] else sTmp <- nOut[1:sum(nlnet@net[1:i]),,subnet] if(i==(nlnet@hierarchic$layer-1)) eTmp[nlnet@hierarchic$idx[,subnet]==0,] <- 0 dWeight[[i]] <- tcrossprod(eTmp, rbind(sBias, sTmp)) #gradient if (nlnet@fct[i] == "tanh") eTmp <- (1 - sTmp^2) * crossprod(wBp[[i]],eTmp) else if (nlnet@fct[i] == "linr") eTmp <- crossprod(wBp[[i]], eTmp) ## the if clause is to avoid 1:0 difference in R if(i > 1) nError[(sum(nlnet@net[1:(i - 1)]) + 1):sum(nlnet@net[1:i]), ,subnet] <- eTmp else nError[1:sum(nlnet@net[1:i]), ,subnet] <- eTmp } dw[,subnet] <- unlist(dWeight) #fixed sign change } } if(nlnet@inverse) { dw <- rbind(array(0, dim=c(numElements, subnetNum)), dw) for(subnet in 1:subnetNum) { eTmp <- array(nError[1:nlnet@net[1],,subnet], dim=c(nlnet@net[1], dim(nError)[2])) eTmp[nlnet@hierarchic$idx[,subnet] == 0,] <- 0 dim(eTmp) <- NULL #a bit unsure if this is correct but seems to work dw[1:numElements,subnet] <- unlist(eTmp) #fixed sign change } ## weights <- rbind(cbind(rep(0, numElements)), cbind(weights)) #old: only weight decay for real weights weights <- rbind(cbind(0.01 * wTrainIn), cbind(weights)) #new } dwTotal <- array(0, dim=dim(weights)) for (subnet in 1:subnetNum) { dwTotal <- dwTotal + nlnet@hierarchic$var[subnet] * dw[, subnet] } if(!is.null(nlnet@weightDecay)) dwTotal <- dwTotal + nlnet@weightDecay * weights return(list(dwTotal=dwTotal, Etotal=Etotal, nError=nError, nOut=nOut)) } pcaMethods/R/methods-ExpressionSet.R0000644000175000017500000000272614136047224017305 0ustar nileshnilesh##' This function can be used to conveniently replace the expression ##' matrix in an \code{ExpressionSet} with the completed data from a ##' \code{pcaRes} object. ##' ##' This is not a standard \code{as} function as \code{pcaRes} ##' object alone not can be converted to an \code{ExpressionSet} (the ##' \code{pcaRes} object does not hold any \code{phenoData} for ##' example). ##' @title Convert pcaRes object to an expression set ##' @param object \code{pcaRes} -- The object containing the completed ##' data. ##' @param exprSet \code{ExpressionSet} -- The object passed on to ##' \code{pca} for missing value estimation. ##' @return An object without missing values of class \code{ExpressionSet}. ##' @export ##' @author Wolfram Stacklies \cr CAS-MPG Partner Institute for ##' Computational Biology, Shanghai, China ##' @keywords multivariate asExprSet <- function(object, exprSet) { if(!inherits(exprSet, "ExpressionSet")) stop("Parameter exprSet must be of type ExpressionSet") if(!inherits(object, "pcaRes") & !inherits(object, "nniRes")) stop("Parameter object must be either of type pcaRes or nniRes") if (is.null(completeObs(object))) stop("completeObs(object) is NULL, exiting") if(!all(dim(exprs(exprSet)) == dim(t(completeObs(object))))) stop("Dimensions of exprs(exprSet) and completeObs(object) do not match. Did you really do missing value estimation using this ExpressionSet object?") exprs(exprSet) <- t(completeObs(object)) return(exprSet) } pcaMethods/R/AllGenerics.R0000644000175000017500000000456514136047224015224 0ustar nileshnileshsetGeneric("vector2matrices", function(object, ...) standardGeneric("vector2matrices")) ##' @exportMethod leverage setGeneric("leverage", function(object, ...) standardGeneric("leverage")) ##' @exportMethod DModX setGeneric("DModX", function(object, dat, newdata=FALSE, type=c("normalized","absolute"), ...) standardGeneric("DModX")) ##' @exportMethod nP setGeneric("nP", function(object, ...) standardGeneric("nP")) ##' @exportMethod cvstat setGeneric("cvstat", function(object, ...) standardGeneric("cvstat")) ##' @exportMethod nPcs setGeneric("nPcs", function(object, ...) standardGeneric("nPcs")) ##' @exportMethod nObs setGeneric("nObs", function(object, ...) standardGeneric("nObs")) ##' @exportMethod nVar setGeneric("nVar", function(object, ...) standardGeneric("nVar")) ##' @exportMethod centered setGeneric("centered", function(object, ...) standardGeneric("centered")) ##' @exportMethod center setGeneric("center", function(object, ...) standardGeneric("center")) ##' @exportMethod completeObs setGeneric("completeObs", function(object, ...) standardGeneric("completeObs")) ##' @exportMethod method setGeneric("method", function(object, ...) standardGeneric("method")) ##' @exportMethod nmissing setGeneric("nmissing", function(object, ...) standardGeneric("nmissing")) ##' @exportMethod wasna setGeneric("wasna", function(object, ...) standardGeneric("wasna")) ##' @exportMethod sDev setGeneric("sDev", function(object, ...) standardGeneric("sDev")) ##' @exportMethod scaled setGeneric("scaled", function(object, ...) standardGeneric("scaled")) ##' @exportMethod scl setGeneric("scl", function(object, ...) standardGeneric("scl")) ##' @exportMethod R2cum setGeneric("R2cum", function(object, ...) standardGeneric("R2cum")) ##' @exportMethod slplot setGeneric("slplot", function(object, pcs=c(1,2), scoresLoadings=c(TRUE, TRUE), sl="def", ll="def", hotelling=0.95, rug=TRUE, sub=NULL,...) standardGeneric("slplot")) ##' @exportMethod scores setGeneric("scores", function(object, ...) standardGeneric("scores")) ##' @exportMethod loadings setGeneric("loadings", function(object, ...) standardGeneric("loadings")) ##' @exportMethod R2VX setGeneric("R2VX", function(object, ...) standardGeneric("R2VX")) ## @exportMethod prep #setGeneric("prep", function(object, ...) standardGeneric("prep")) pcaMethods/R/sortFeatures.R0000644000175000017500000000502114136047224015506 0ustar nileshnilesh##' Sort the features of NLPCA object ##' @param nlnet The nlnet ##' @param trainIn Training data in ##' @param trainOut Training data after it passed through the net ##' @return ... ##' @author Henning Redestig sortFeatures <- function(nlnet, trainIn, trainOut) { weightsAll <- nlnet@weights$current() weights <- weightsAll if(nlnet@inverse) { numElements <- nlnet@net[1] * dim(trainOut)[2] trainIn <- array(unlist(weightsAll), dim=c(nlnet@net[1], dim(trainOut)[2])) weights <- weightsAll[(numElements + 1):length(weightsAll),,drop=FALSE] } netDim <- dim(nlnet@net) trainDim <- dim(trainIn) bneckNum <- nlnet@net[nlnet@componentLayer] weightMats <- vector2matrices(weights, nlnet@net) bneckNum <- nlnet@net[nlnet@componentLayer] ## ****************************** nOut <- array(0, dim=c(sum(nlnet@net), trainDim[2], 2)) for(subnet in 1:2) nOut[1:trainDim[1],,subnet] <- trainIn ## forward propagation for(n in 0:(bneckNum - 2)) { E <- c(0,0) for(choice in 1:2) { sBias <- rep(1, trainDim[2]) for(i in 1:(netDim[2] - 1)) { if(i == 1) nBegin <- 1 else nBegin <- sum(nlnet@net[1:(i - 1)]) + 1 sIn <- rbind(sBias, nOut[nBegin:sum(nlnet@net[1:i]),, choice]) sOut <- eval(parse(text=paste(nlnet@fkt[i], "(weightMats[[i]] %*% sIn)"))) if(i == nlnet@componentLayer - 1) { idx <- rep(0, bneckNum) idx[1:(n + choice)] <- 1 if(choice == 2) idx[n+choice-1] <- 0 sOut[idx == 0,] <- 0 } nOut[(sum(nlnet@net[1:i]) + 1):sum(nlnet@net[1:(i+1)]),,choice] <- sOut } output <- nOut[(sum(nlnet@net[1:(dim(nlnet@net)[2]-1)])+1):dim(nOut)[1], ,choice] Epattern <- (output - trainOut)^2 Epattern[is.na(Epattern)] <- 0 if(!is.null(nlnet@dataDist)) Epattern <- Epattern * nlnet@dataDist E <- mean(Epattern) E[choice] <- E } if(E[1]>E[2]) { #change features changeIdx <- 1:bneckNum changeIdx[(n+1):(n+2)] <- c(n+2, n+1) weightMats[[nlnet@componentLayer - 1]] <- weightMats[[nlnet@componentLayer - 1]][changeIdx,] weightMats[[nlnet@componentLayer]] <- weightMats[[nlnet@componentLayer]][,c(1,changeIdx+1)] switching <- c(n+1, n+2) nlnet@fCount <- as.integer(nlnet@fCount + 1) } } weights <- cbind(unlist(weightMats)) if(nlnet@inverse) nlnet@weights$set(rbind(matrix(trainIn, nrow=numElements, ncol=1), weights)) } pcaMethods/R/optiAlgCgd.R0000644000175000017500000000414314136047224015041 0ustar nileshnilesh##' Conjugate gradient optimization ##' @param nlnet The nlnet ##' @param trainIn Training data ##' @param trainOut fitted data ##' @param verbose logical, print messages ##' @return ... ##' @author Henning Redestig, Matthias Scholz optiAlgCgd <- function(nlnet, trainIn, trainOut, verbose=FALSE) { tmpnet <- forkNlpcaNet(nlnet) derr <- tmpnet@gradient(tmpnet, trainIn, trainOut) dw <- derr$dwTotal e <- derr$Etotal dv <- -dw if(tmpnet@featureSorting) eSortLast <- e eHist <- rep(0, tmpnet@maxIter) ttLast <- rep(0.0001, 6) for(i in 1:tmpnet@maxIter) { if(verbose) { if(i %% 10 == 0) cat("*") if(i %% 100 == 0) cat(" [", i, "]\n") } eHist[i] <- e eLast <- e # line search in direction dv (downhill) ttGuess <- max(min(ttLast), 0.00001) linSe <- lineSearch(tmpnet, dv, e, ttGuess, trainIn, trainOut, verbose) tmpnet@weights$set(cbind(linSe$wBest)) e <- linSe$eBest tt <- linSe$ttBest ttLast <- c(ttLast[2:length(ttLast)], tt) #shift and add new tt gradRes <- tmpnet@gradient(tmpnet, trainIn, trainOut) dwNew <- gradRes$dwTotal e <- gradRes$Etotal ## define new search direction dv (conjugate direction) ## b1=dw_new'*dw_new; # Fletcher-Reeves b1 <- crossprod(dwNew, (dwNew - dw))#Polak-Ribiere b2 <- crossprod(dw) beta <- b1 / b2 dv <- -dwNew + dv %*% beta dw <- dwNew if(e > eLast) { dv <- -dwNew if(verbose) cat("!", sep="") } if(is.na(e)) stop("Square error is NA (critical) - accuracy in line-search might be too small") if(tmpnet@featureSorting) if(e / eSortLast < 0.90 || i == tmpnet@maxIter || i == tmpnet@maxIter - 1 || i == tmpnet@maxIter - 2) { eSortLast <- e if(verbose) cat("<", i, ">", sep="") ## somewhat secret method, sortFeatures calls ## nlnet@weights$set(x) so the weights are updated here ## 'behind the scenes' sortFeatures(tmpnet, trainIn, trainOut) } } tmpnet } pcaMethods/R/pcaMethods-package.R0000644000175000017500000000772014136047224016510 0ustar nileshnilesh##' Simulated data set looking like a helix ##' ##' ##' A matrix containing 1000 observations (rows) and three variables ##' (columns). ##' @title A helix structured toy data set ##' @name helix ##' @aliases helix ##' @usage data(helix) ##' @docType data ##' @references Matthias Scholz, Fatma Kaplan, Charles L. Guy, Joachim ##' Kopka and Joachim Selbig. - Non-linear PCA: a missing data ##' approach. \emph{Bioinformatics 2005 21(20):3887-3895} ##' @keywords datasets ##' @author Henning Redestig NULL ##' A complete subset from a larger metabolite data set. This is the ##' original, complete data set and can be used to compare estimation ##' results created with the also provided incomplete data (called ##' metaboliteData). The data was created during an in house ##' Arabidopsis coldstress experiment. ##' ##' A matrix containing 154 observations (rows) and 52 metabolites ##' (columns). ##' @name metaboliteDataComplete ##' @docType data ##' @aliases metaboliteDataComplete ##' @title A complete metabolite data set from an Arabidopsis ##' coldstress experiment ##' @keywords datasets ##' @seealso \code{\link{metaboliteData}} ##' @references Matthias Scholz, Fatma Kaplan, Charles L. Guy, Joachim ##' Kopka and Joachim Selbig. - Non-linear PCA: a missing data ##' approach.\emph{Bioinformatics 2005 21(20):3887-3895} ##' @author Wolfram Stacklies NULL ##' A incomplete subset from a larger metabolite data set. This is the ##' original, complete data set and can be used to compare estimation ##' results created with the also provided incomplete data (called ##' metaboliteData). ##' ##' A matrix containing 154 observations (rows) and 52 metabolites ##' (columns). The data contains 5\% of artificially created uniformly ##' distributed misssing values. The data was created during an in ##' house Arabidopsis coldstress experiment. ##' @name metaboliteData ##' @docType data ##' @aliases metaboliteData ##' @title A incomplete metabolite data set from an Arabidopsis ##' coldstress experiment ##' @keywords datasets ##' @seealso \code{\link{metaboliteDataComplete}} ##' @references Matthias Scholz, Fatma Kaplan, Charles L. Guy, Joachim ##' Kopka and Joachim Selbig. - Non-linear PCA: a missing data ##' approach.\emph{Bioinformatics 2005 21(20):3887-3895} ##' @author Wolfram Stacklies NULL ##' Principal Component Analysis in R ##' ##' \tabular{ll}{ ##' Package: \tab pcaMethods \cr ##' Type: \tab Package \cr ##' Developed since: \tab 2006 \cr ##' License: \tab GPL (>=3) \cr ##' LazyLoad: \tab yes \cr ##' } ##' ##' Provides Bayesian PCA, Probabilistic PCA, Nipals PCA, Inverse ##' Non-Linear PCA and the conventional SVD PCA. A cluster based ##' method for missing value estimation is included for comparison. ##' BPCA, PPCA and NipalsPCA may be used to perform PCA on incomplete ##' data as well as for accurate missing value estimation. A set of ##' methods for printing and plotting the results is also provided. ##' All PCA methods make use of the same data structure (pcaRes) to ##' provide a unique interface to the PCA results. Developed at the ##' Max-Planck Institute for Molecular Plant Physiology, Golm, ##' Germany, RIKEN Plant Science Center Yokohama, Japan, and CAS-MPG ##' Partner Institute for Computational Biology (PICB) Shanghai, ##' P.R. China ##' ##' @name pcaMethods ##' @aliases pcaMethods ##' @docType package ##' @importFrom Rcpp evalCpp ##' @import Biobase ##' @import BiocGenerics ##' @import methods ##' @title pcaMethods ##' @useDynLib pcaMethods ##' @author Wolfram Stacklies, Henning Redestig NULL ##' \describe{ ##' \item{plotR2}{Lack of relevance for this plot and the fact that it ##' can not show cross-validation based diagnostics in the same plot ##' makes it redundant with the introduction of a dedicated ##' \code{plot} function for \code{pcaRes}. The new plot only shows ##' R2cum but the result is pretty much the same.}} ##' @name pcaMethods-deprecated ##' @aliases pcaMethods-deprecated ##' @title Deprecated methods for pcaMethods ##' @author Henning Redestig NULL pcaMethods/R/methods-pcaRes.R0000644000175000017500000007727514136047224015722 0ustar nileshnilesh##' The leverages of PCA model indicate how much influence each ##' observation has on the PCA model. Observations with high leverage ##' has caused the principal components to rotate towards them. It can ##' be used to extract both "unimportant" observations as well as ##' picking potential outliers. ##' ##' Defined as \eqn{Tr(T(T'T)^{-1}T')}{Tr(T(T'T)^(-1)T')} ##' @title Extract leverages of a PCA model ##' @param object a \code{pcaRes} object ##' @return The observation leverages as a numeric vector ##' @references Introduction to Multi- and Megavariate Data Analysis ##' using Projection Methods (PCA and PLS), L. Eriksson, E. Johansson, ##' N. Kettaneh-Wold and S. Wold, Umetrics 1999, p. 466 ##' @examples ##' data(iris) ##' pcIr <- pca(iris[,1:4]) ##' ## versicolor has the lowest leverage ##' with(iris, plot(leverage(pcIr)~Species)) ##' @keywords multivariate ##' @aliases leverage leverage,pcaRes-method ##' @author Henning Redestig setMethod("leverage", "pcaRes", function(object) { diag(scores(object) %*% solve(crossprod(scores(object))) %*% t(scores(object))) }) ##' Distance to the model of X-space. ##' ##' Measures how well described the observations are, i.e. how well ##' they fit in the mode. High DModX indicate a poor fit. Defined as: ##' ##' \eqn{\frac{\sqrt{\frac{SSE_i}{K-A}}}{\sqrt{\frac{SSE}{(N-A-A_0)(K-A)}}}} ##' ##' For observation \eqn{i}, in a model with \eqn{A} components, ##' \eqn{K} variables and \eqn{N} obserations. SSE is the squared sum ##' of the residuals. \eqn{A_0} is 1 if model was centered and 0 ##' otherwise. DModX is claimed to be approximately F-distributed and ##' can therefore be used to check if an observation is significantly ##' far away from the PCA model assuming normally distributed data. ##' ##' Pass original data as an argument if the model was calculated with ##' \code{completeObs=FALSE}. ##' @title DModX ##' @usage DModX(object, dat, newdata=FALSE, type=c("normalized","absolute"), ...) ##' @param object a pcaRes object ##' @param dat the original data, taken from \code{completeObs} if ##' left missing. ##' @param newdata logical indicating if this data was part of the ##' training data or not. If it was, it is adjusted by a near one factor ##' \eqn{v=(N/ (N-A-A0))^-1} ##' @param type if absolute or normalized values should be ##' given. Normalized values are adjusted to the the total RSD of the ##' model. ##' @param ... Not used ##' @return A vector with distances from observations to the PCA model ##' @aliases DModX DModX,pcaRes-method ##' @examples ##' data(iris) ##' pcIr <- pca(iris[,1:4]) ##' with(iris, plot(DModX(pcIr)~Species)) ##' @references Introduction to Multi- and Megavariate Data Analysis ##' using Projection Methods (PCA and PLS), L. Eriksson, E. Johansson, ##' N. Kettaneh-Wold and S. Wold, Umetrics 1999, p. 468 ##' @author Henning Redestig setMethod("DModX", "pcaRes", function(object, dat, newdata=FALSE, type=c("normalized","absolute"), ...) { type <- match.arg(type) if(missing(dat)) { if(!is.null(completeObs(object))) dat <- completeObs(object) else stop("missing data when calculating DModX") } A0 <- as.integer(centered(object)) ny <- ifelse(newdata, 1, sqrt(nObs(object) / (nObs(object) - nP(object) - A0))) E2 <- resid(object, dat)^2 s <- sqrt(rowSums(E2) / (nVar(object) - nP(object))) * ny if(type == "absolute") return(s) s0 <- sqrt(sum(E2) / ((nObs(object) - nP(object) - A0) * (nVar(object) - nP(object)))) s / s0 }) ##' Get number of PCs ##' @param object pcaRes object ##' @param ... not used ##' @return Number of PCs ##' @aliases nP nP,pcaRes-method ##' @usage nP(object, ...) ##' @author Henning Redestig setMethod("nP", "pcaRes", function(object, ...) { if(is.null(object@nPcs) & !is.null(scores(object))) return(ncol(scores(object))) object@nPcs }) ##' Get cross-validation statistics (e.g. \eqn{Q^2}). ##' @param object pcaRes object ##' @param ... not used ##' @return vector CV statistics ##' @aliases cvstat cvstat,pcaRes-method ##' @usage cvstat(object, ...) ##' @author Henning Redestig setMethod("cvstat", "pcaRes", function(object, ...) { object@cvstat }) ##' Get number of PCs. ##' @param object pcaRes object ##' @param ... not used ##' @note Try to use \code{link{nP}} instead since \code{nPcs} tend to ##' clash with argument names. ##' @return Number of PCs ##' @usage nPcs(object, ...) ##' @aliases nPcs nPcs,pcaRes-method ##' @author Henning Redestig setMethod("nPcs", "pcaRes", function(object, ...) { nP(object) }) ##' Get the number of observations used to build the PCA model. ##' @param object pcaRes object ##' @param ... Not used ##' @usage nObs(object, ...) ##' @aliases nObs nObs,pcaRes-method ##' @return Number of observations ##' @author Henning Redestig setMethod("nObs", "pcaRes", function(object, ...) { object@nObs }) ##' Get the number of variables used to build the PCA model. ##' @param object pcaRes object ##' @param ... Not used ##' @usage nVar(object, ...) ##' @aliases nVar nVar,pcaRes-method ##' @return Number of variables ##' @author Henning Redestig setMethod("nVar", "pcaRes", function(object, ...) { object@nVar }) ##' Check centering was part of the model ##' @param object pcaRes object ##' @param ... Not used ##' @usage centered(object, ...) ##' @aliases centered centered,pcaRes-method ##' @return TRUE if model was centered ##' @author Henning Redestig setMethod("centered", "pcaRes", function(object, ...) { if(is.null(object@centered)) return(FALSE) object@centered }) ##' Get the centers of the original variables ##' @param object pcaRes object ##' @param ... Not used ##' @usage center(object, ...) ##' @aliases center center,pcaRes-method ##' @return Vector with the centers ##' @author Henning Redestig setMethod("center", "pcaRes", function(object, ...) { object@center }) setMethod("completeObs", "pcaRes", function(object, ...) { object@completeObs }) ##' Get the original data with missing values replaced with predicted ##' values. ##' @param object object to fetch complete data from ##' @param ... Not used ##' @usage completeObs(object, ...) ##' @aliases completeObs completeObs,nniRes-method ##' completeObs,pcaRes-method ##' @return Completed data (matrix) ##' @author Henning Redestig setMethod("completeObs", "nniRes", function(object, ...) { object@completeObs }) ##' Get the used PCA method ##' @param object pcaRes object ##' @param ... Not used ##' @usage method(object, ...) ##' @aliases method method,pcaRes-method ##' @return The used pca method ##' @author Henning Redestig setMethod("method", "pcaRes", function(object, ...) { object@method }) setMethod("nmissing", "nniRes", function(object, ...) { sum(object@missing) }) ##' Missing values ##' @param object pcaRes object ##' @param ... Not used ##' @usage nmissing(object, ...) ##' @aliases nmissing nmissing,pcaRes-method nmissing,nniRes-method ##' @return Get the number of missing values ##' @author Henning Redestig setMethod("nmissing", "pcaRes", function(object, ...) { sum(object@missing) }) ##' Get a matrix with indicating the elements that were missing in the ##' input data. Convenient for estimating imputation performance. ##' @param object pcaRes object ##' @param ... Not used ##' @usage wasna(object, ...) ##' @aliases wasna wasna,pcaRes-method ##' @return A matrix with logicals ##' @examples ##' data(metaboliteData) ##' data(metaboliteDataComplete) ##' result <- pca(metaboliteData, nPcs=2) ##' plot(completeObs(result)[wasna(result)], metaboliteDataComplete[wasna(result)]) ##' @author Henning Redestig setMethod("wasna", "pcaRes", function(object, ...) { object@missing }) ##' Get the standard deviations of the scores (indicates their ##' relevance) ##' @param object pcaRes object ##' @param ... Not used ##' @usage sDev(object, ...) ##' @aliases sDev sDev,pcaRes-method ##' @return Standard devations of the scores ##' @author Henning Redestig setMethod("sDev", "pcaRes", function(object, ...) { object@sDev }) ##' Check if scaling was part of the PCA model ##' @param object pcaRes object ##' @param ... Not used ##' @usage scaled(object, ...) ##' @aliases scaled scaled,pcaRes-method ##' @return TRUE if scaling was part of the PCA model ##' @author Henning Redestig setMethod("scaled", "pcaRes", function(object, ...) { if(is.null(object@scaled)) return(FALSE) object@scaled != "none" }) ##' Get the scales (e.g. standard deviations) of the original ##' variables ##' @param object pcaRes object ##' @param ... Not used ##' @usage scl(object, ...) ##' @aliases scl scl,pcaRes-method ##' @return Vector with the scales ##' @seealso \code{\link{prep}} ##' @author Henning Redestig setMethod("scl", "pcaRes", function(object, ...) { object@scale }) ##' Cumulative R2 is the total ratio of variance that is being ##' explained by the model ##' @param object a \code{pcaRes} model ##' @param ... Not used ##' @return Get the cumulative R2 ##' @aliases R2cum R2cum,pcaRes-method ##' @author Henning Redestig setMethod("R2cum", "pcaRes", function(object, ...) { object@R2cum }) ##' Get scores from a pcaRes object ##' @param object a pcaRes object ##' @param ... not used ##' @return The scores as a matrix ##' @export ##' @author Henning Redestig ##' @method scores pcaRes scores.pcaRes <- function(object, ...) object@scores ##' Get scores from a pcaRes object ##' @param object a pcaRes object ##' @param ... not used ##' @return The scores as a matrix ##' @seealso \code{\link{scores.pcaRes}} ##' @aliases scores scores,pcaRes-method ##' @author Henning Redestig setMethod("scores", "pcaRes", scores.pcaRes) ##' Get loadings from a pcaRes object ##' @param object a pcaRes object ##' @param ... not used ##' @return The loadings as a matrix ##' @export ##' @author Henning Redestig ##' @method loadings pcaRes loadings.pcaRes <- function(object, ...) object@loadings ##' Get loadings from a pcaRes object ##' @param object a pcaRes object ##' @param ... not used ##' @return The loadings as a matrix ##' @seealso \code{\link{loadings.pcaRes}} ##' @author Henning Redestig ##' @aliases loadings,pcaRes-method setMethod("loadings", "pcaRes", loadings.pcaRes) ##' Crude way to unmask the function with the same name from ##' \code{stats} ##' @param object any object ##' @param ... not used ##' @return The loadings ##' @author Henning Redestig ##' @aliases loadings loadings,ANY-method setMethod("loadings", "ANY", function(object,...) { stats::loadings(object) }) ##' Dimensions of a PCA model ##' @param x a pcaRes object ##' @return Get the dimensions of this PCA model ##' @method dim pcaRes ##' @export ##' @author Henning Redestig dim.pcaRes <- function(x) { res <- c(nObs(x), nVar(x), nP(x)) names(res) <- c("nObs", "nVar", "nPcs") res } ##' Print basic information about pcaRes object ##' @title Print/Show for pcaRes ##' @param x a pcaRes object ##' @param ... not used ##' @return nothing, used for its side effect ##' @name show-methods ##' @export ##' @author Henning Redestig showPcaRes <- function(x, ...) { summary(x) cat(nVar(x), "\tVariables\n") cat(nObs(x),"\tSamples\n") cat(nmissing(x), "\tNAs (", round(100 * nmissing(x) / (nObs(x) * nVar(x)), getOption("str")$digits.d), "%)\n") cat(nP(x), "\tCalculated component(s)\n") if(centered(x)) cat("Data was mean centered before running PCA \n") else cat("Data was NOT mean centered before running PCA \n") if(scaled(x)) cat("Data was scaled before running PCA \n") else cat("Data was NOT scaled before running PCA \n") cat("Scores structure:\n") print(dim(scores(x))) cat("Loadings structure:\n") if(method(x) == "nlpca") { cat("Inverse hierarchical neural network architecture\n") cat(drop(x@network@net), "\n") cat("Functions in layers\n") cat(x@network@fct, "\n") cat("hierarchic layer:", x@network@hierarchic$layer, "\n") cat("hierarchic coefficients:", x@network@hierarchic$var, "\n") cat("scaling factor:", x@network@scalingFactor, "\n") } else{ print(dim(loadings(x))) } } ##' @aliases print,pcaRes-method print,nniRes-method ##' @name show-methods setMethod("print", "pcaRes", showPcaRes) ## @importFrom methods show ##' @aliases show,pcaRes-method show,nniRes-method ##' @param object the object to print information about ##' @name show-methods setMethod("show", "pcaRes", function(object) showPcaRes(object)) ##' Visualize two-components simultaneously ##' ##' This is a method for the generic function 'biplot'. There is ##' considerable confusion over the precise definitions: those of the ##' original paper, Gabriel (1971), are followed here. Gabriel and ##' Odoroff (1990) use the same definitions, but their plots actually ##' correspond to \code{pc.biplot = TRUE}. ##' @title Plot a overlaid scores and loadings plot ##' @param x a pcaRes object ##' @param choices which two pcs to plot ##' @param scale The variables are scaled by ##' \eqn{\lambda^{scale}}{lambda^scale} and the observations are ##' scaled by \eqn{\lambda^{scale}}{lambda ^ (1-scale)} where ##' \code{lambda} are the singular values as computed by ##' \code{princomp}. Normally \eqn{0\le{}scale\le{}1}{0 <= scale <= ##' 1}, and a warning will be issued if the specified 'scale' is ##' outside this range. ##' @param pc.biplot If true, use what Gabriel (1971) refers to as a ##' "principal component biplot", with \eqn{\lambda=1}{lambda = 1} and ##' observations scaled up by sqrt(n) and variables scaled down by ##' sqrt(n). Then the inner products between variables approximate ##' covariances and distances between observations approximate ##' Mahalanobis distance. ##' @param ... optional arguments to be passed to ##' \code{biplot.default}. ##' @return a plot is produced on the current graphics device. ##' @method biplot pcaRes ##' @export ##' @examples ##' data(iris) ##' pcIr <- pca(iris[,1:4]) ##' biplot(pcIr) ##' @seealso \code{prcomp}, \code{pca}, \code{princomp} ##' @author Kevin Wright, Adapted from \code{biplot.prcomp} ##' @keywords multivariate ##' @name biplot-methods biplot.pcaRes <- function(x, choices=1:2, scale=1, pc.biplot=FALSE, ...) { if(length(choices)!=2) stop("length of choices must be 2") scores <- scores(x) n <- nrow(scores) lam <- sDev(x)[choices] * sqrt(n) if(scale < 0 || scale > 1) warning("'scale' is outside [0,1]") if(scale != 0) lam <- lam^scale else lam <- 1 if(pc.biplot) lam <- lam/sqrt(n) biplot(t(t(scores[,choices])/lam), t(t(loadings(x)[, choices]) * lam), , ...) invisible() } ##' @aliases biplot,pcaRes-method ## @importFrom stats biplot ##' @name biplot-methods setMethod("biplot", "pcaRes", biplot.pcaRes) ##' Flexible calculation of R2 goodness of fit. ##' @title R2 goodness of fit ##' @param object a PCA model object ##' @param direction choose between calculating R2 per variable, per ##' observation or for the entire data with 'variables', ##' 'observations' or 'complete'. ##' @param data the data used to fit the model ##' @param pcs the number of PCs to use to calculate R2 ##' @aliases R2VX R2VX,pcaRes-method ##' @examples ##' R2VX(pca(iris)) ##' @return A vector with R2 values ##' @author Henning Redestig setMethod('R2VX', 'pcaRes', function(object, direction=c('variables', 'observations', 'complete'), data=completeObs(object), pcs=nP(object)) { direction <- match.arg(direction) if(is.null(data)) stop('missing input when calculating R2') if(any(is.na(data))) stop('missing values not allowed for calculating R2') dat <- prep(data, scale=scl(object), center=center(object)) xhat <- resid(object, pcs=pcs, data=dat, pre=FALSE, post=FALSE) switch(direction, variables={ 1 - colSums(xhat^2) / colSums(dat^2) }, observations={ 1 - rowSums(xhat^2) / rowSums(dat^2) }, complete={ 1 - sum(xhat^2) / sum(dat^2) }) }) setAs('pcaRes', 'data.frame', function(from) { tt <- scores(from) pp <- loadings(from) if(is.null(rownames(tt))) rownames(tt) <- 1:nrow(tt) if(is.null(rownames(pp))) rownames(pp) <- 1:nrow(pp) dfs <- as.data.frame(tt) dfs$names <- rownames(tt) dfs$type <- 'scores' dfl <- as.data.frame(pp) dfl$names <- rownames(pp) dfl$type <- 'loadings' rownames(dfl) <- rownames(dfs) <- NULL rbind(dfl, dfs) }) ##' Print a brief description of the PCA model ##' @title Summary of PCA model ##' @param object a pcaRes object ##' @param ... Not used ##' @return Nothing, used for side-effect ##' @aliases summary summary.pcaRes summary,pcaRes-method ##' @author Henning Redestig ##' @export ##' @name summary ##' @method summary pcaRes summary.pcaRes <- function(object, ...){ cat(method(object), "calculated PCA\n") cat("Importance of component(s):\n") prop <- vector(length=length(R2cum(object)), mode="numeric") prop[1] <- R2cum(object)[1] if (length(R2cum(object)) > 1) { for (i in 2:length(prop)) { prop[i] <- R2cum(object)[i] - R2cum(object)[i-1] } } r <- rbind(prop, R2cum(object)) rownames(r) <- c("R2", "Cumulative R2") colnames(r) <- paste("PC", 1:nP(object), sep="") print(r, digits=4) invisible(r) } setMethod("summary", "pcaRes", summary.pcaRes) ##' Predict data using PCA model ##' ##' This function extracts the predict values from a pcaRes object for ##' the PCA methods SVD, Nipals, PPCA and BPCA. Newdata is first ##' centered if the PCA model was and then scores (\eqn{T}) and data ##' (\eqn{X}) is 'predicted' according to : ##' \eqn{\hat{T}=X_{new}P}{That=XnewP} ##' \eqn{\hat{X}_{new}=\hat{T}P'}{Xhat=ThatP'}. Missing values are ##' set to zero before matrix multiplication to achieve NIPALS like ##' treatment of missing values. ##' @title Predict values from PCA. ##' @param object \code{pcaRes} the \code{pcaRes} object of interest. ##' @param newdata \code{matrix} new data with same number of columns ##' as the used to compute \code{object}. ##' @param pcs \code{numeric} The number of PC's to consider ##' @param pre pre-process \code{newdata} based on the pre-processing ##' chosen for the PCA model ##' @param post unpre-process the final data (add the center back etc) ##' @param ... Not passed on anywhere, included for S3 consistency. ##' @return A list with the following components: \item{scores}{The ##' predicted scores} \item{x}{The predicted data} ##' @method predict pcaRes ##' @keywords multivariate ##' @examples ##' data(iris) ##' hidden <- sample(nrow(iris), 50) ##' pcIr <- pca(iris[-hidden,1:4]) ##' pcFull <- pca(iris[,1:4]) ##' irisHat <- predict(pcIr, iris[hidden,1:4]) ##' cor(irisHat$scores[,1], scores(pcFull)[hidden,1]) ##' @export ##' @name predict-methods ##' @author Henning Redestig predict.pcaRes <- function(object, newdata, pcs=nP(object), pre=TRUE, post=TRUE, ...) { if(!method(object) %in% listPcaMethods("linear")) stop("predict method not implemented for that type of PCA") if(pre) newdata <- prep(newdata, scl(object), center(object)) ## set na's to zero to achieve NIPALS like prediction newdata[is.na(newdata)] <- 0 tnew <- newdata %*% loadings(object)[,1:pcs,drop=FALSE] xhat <- tcrossprod(tnew, loadings(object)[,1:pcs,drop=FALSE]) if(post) xhat <- prep(xhat, scl(object), center(object), reverse=TRUE) list(scores=tnew, x=xhat) } ## @importFrom stats predict ##' @name predict-methods ##' @aliases predict,pcaRes-method setMethod("predict", "pcaRes", predict.pcaRes) ##' This function extracts the residuals values from a pcaRes object ##' for the PCA methods SVD, Nipals, PPCA and BPCA ##' @title Residuals values from a PCA model. ##' @param object \code{pcaRes} the \code{pcaRes} object of interest. ##' @param data \code{matrix} The data that was used to calculate the ##' PCA model (or a different dataset to e.g. adress its proximity to ##' the model). ##' @param ... Passed on to \code{\link{predict.pcaRes}}. E.g. setting ##' the number of used components. ##' @return A \code{matrix} with the residuals ##' @method residuals pcaRes ##' @keywords multivariate ##' @export ##' @name rediduals-methods ##' @examples ##' data(iris) ##' pcIr <- pca(iris[,1:4]) ##' head(residuals(pcIr, iris[,1:4])) ##' @author Henning Redestig residuals.pcaRes <- function(object, data=completeObs(object), ...) { if(is.null(data)) stop("data missing when calculating residuals") data - predict(object, data, ...)$x } ##' @aliases residuals,pcaRes-method ##' @name rediduals-methods setMethod("residuals", "pcaRes", residuals.pcaRes) ##' @name rediduals-methods ##' @aliases resid,pcaRes-method setMethod("resid", "pcaRes", residuals.pcaRes) ##' Fitted values of a PCA model ##' ##' This function extracts the fitted values from a pcaResobject. For ##' PCA methods like SVD, Nipals, PPCA etc this is basically just the ##' scores multipled by the loadings and adjusted for pre-processing. ##' for non-linear PCA the original data is propagated through the ##' network to obtain the approximated data. ##' @title Extract fitted values from PCA. ##' @param object the \code{pcaRes} object of interest. ##' @param data For standard PCA methods this can safely be left null ##' to get scores x loadings but if set, then the scores are obtained ##' by projecting provided data onto the loadings. If data contains ##' missing values the result will be all NA. Non-linear PCA is an ##' exception, here if data is NULL then data is set to the ##' completeObs and propaged through the network. ##' @param nPcs The number of PC's to consider ##' @param pre pre-process \code{data} based on the pre-processing ##' chosen for the PCA model ##' @param post unpre-process the final data (add the center back etc ##' to get the final estimate) ##' @param ... Not used ##' @return A matrix representing the fitted data ##' @keywords multivariate ##' @method fitted pcaRes ##' @examples ##' pc <- pca(iris[,1:4], nPcs=4, center=TRUE, scale="uv") ##' sum( (fitted(pc) - iris[,1:4])^2 ) ##' @export ##' @name fitted-methods ##' @author Henning Redestig fitted.pcaRes <- function(object, data=NULL, nPcs=nP(object), pre=TRUE, post=TRUE, ...) { if(method(object) %in% listPcaMethods("nonlinear")) { if(is.null(data) & is.null(completeObs(object))) stop("completeObs slot is empty -- provide the training data") if(is.null(data) & !is.null(completeObs(object))) data <- completeObs(object) if(is.null(data)) stop("nlpca requires original data to be provide") if(pre) data <- prep(data, scl(object), center(object)) recData <- errorHierarchic(object@network, t(scores(object)), t(data))$out[,,nPcs] recData <- t(recData / object@network@scalingFactor) } else { if(!is.null(data)) { if(pre) data <- prep(data, scl(object), center(object)) tt <- data %*% loadings(object)[,1:nPcs, drop=FALSE] } if(is.null(data)) tt <- scores(object)[,1:nPcs, drop=FALSE] recData <- tcrossprod(tt, loadings(object)[,1:nPcs, drop=FALSE]) } if(post) recData <- prep(recData, scl(object), center(object), reverse=TRUE) return(recData) } ## @importFrom stats fitted ##' @name fitted-methods ##' @aliases fitted,pcaRes-method setMethod("fitted", "pcaRes", fitted.pcaRes) ##' Plot the computed diagnostics of PCA model to get an idea of their ##' importance. Note though that the standard screeplot shows the ##' standard deviations for the PCs this method shows the R2 values ##' which empirically shows the importance of the P's and is thus ##' applicable for any PCA method rather than just SVD based PCA. ##' ##' If cross-validation was done for the PCA the plot will also show ##' the CV based statistics. A common rule-of-thumb for determining ##' the optimal number of PCs is the PC where the CV diagnostic is at ##' its maximum but not very far from \eqn{R^2}. ##' @title Plot diagnostics (screeplot) ##' @param x \code{pcaRes} The pcaRes object. ##' @param y not used ##' @param main title of the plot ##' @param col Colors of the bars ##' @param ... further arguments to barplot ##' @return None, used for side effect. ##' @seealso \link{screeplot} ##' @examples ##' data(metaboliteData) ##' pc <- pca(t(metaboliteData), nPcs=5, cv="q2", scale="uv") ##' plot(pc) ##' @method plot pcaRes ##' @aliases plot.pcaRes plot,pcaRes-method ##' @export ##' @author Henning Redestig plot.pcaRes <- function(x, y=NULL, main=deparse(substitute(object)), col=gray(c(0.9, 0.5)), ...) { y <- NULL ## the deparse(subsitute(object)) later fails otherwise main <- main if(!is.null(cvstat(x))) { cvs <- cvstat(x) if(length(cvs) != nP(x)) cvs <- c(cvs, rep(NA, nP(x) - length(cvs))) xx <- rbind(R2cum(x), cvs) barplot(xx, beside=TRUE, ylim=c(0,1.1), col=col, main=main, names.arg=paste("PC", 1:nP(x), sep=""), ...) legend(x="topleft", fill=col, legend=c(expression(R^2), expression(Q^2))) } else barplot(R2cum(x), ylim=c(0,1.1), ylab=expression(R^2), main=main, names.arg=paste("PC", 1:nP(x), sep=""), col=col[1], ...) } setMethod("plot", "pcaRes", plot.pcaRes) ##' A common way of visualizing two principal components ##' ##' This method is meant to be used as a quick way to visualize ##' results, if you want a more specific plot you probably want to ##' get the scores, loadings with \code{scores(object)}, ##' \code{loadings(object)} and then design your own plotting method. ##' @title Side by side scores and loadings plot ##' @usage slplot(object, pcs=c(1,2), scoresLoadings=c(TRUE, TRUE), ##' sl="def", ll="def", hotelling=0.95, rug=TRUE, sub=NULL,...) ##' @param object a pcaRes object ##' @param pcs which two pcs to plot ##' @param scoresLoadings Which should be shown scores and or loadings ##' @param sl labels to plot in the scores plot ##' @param ll labels to plot in the loadings plot ##' @param hotelling confidence interval for ellipse in the score plot ##' @param rug logical, rug x axis in score plot or not ##' @param sub Subtitle, defaults to annotate with amount of explained ##' variance. ##' @param ... Further arguments to plot functions. Prefix arguments ##' to \code{par()} with 's' for the scores plot and 'l' for the ##' loadings plot. I.e. cex become scex for setting character ##' expansion in the score plot and lcex for the loadings plot. ##' @return None, used for side effect. ##' @note Uses layout instead of par to provide side-by-side so it ##' works with Sweave (but can not be combined with ##' \code{par(mfrow=..))} ##' @author Henning Redestig ##' @seealso \code{\link{pca}}, \code{\link{biplot}} ##' @aliases slplot slplot,pcaRes-method ##' @examples ##' data(iris) ##' pcIr <- pca(iris[,1:4], scale="uv") ##' slplot(pcIr, sl=NULL, spch=5) ##' slplot(pcIr, sl=NULL, lcex=1.3, scol=as.integer(iris[,5])) ##' @keywords multivariate setMethod("slplot", "pcaRes", function(object, pcs=c(1,2), scoresLoadings=c(TRUE, TRUE), sl=rownames(scores(object)), ll=rownames(loadings(object)), hotelling=0.95, rug=FALSE, sub=NULL,...) { opar <- par(no.readonly=TRUE) cl <- match.call() mainArgs <- c(1,match(c("ll", "sl", "scoresLoadings", "sub"), names(cl), 0)) scoreArgs <- grep("^s", names(cl)[-mainArgs]) loadingArgs <- grep("^l", names(cl)[-mainArgs]) if(!is.null(ll) & length(ll) != nVar(object)) stop("Loading labels do not match the object dimensions") if(!is.null(sl) & length(sl) != nObs(object)) stop("Score labels do not match the object dimensions") if(is.null(sl)) sl <- NA if(is.null(ll)) ll <- NA ## no loadings for non-linear pca if(method(object) %in% listPcaMethods("nonlinear") && scoresLoadings[2]) scoresLoadings[2] <- FALSE if(length(pcs) > 2) plotPcs(object, pcs, scoresLoadings=scoresLoadings,...) else { if(is.null(sub)) sub <- paste(sprintf("%.2f", R2cum(object)[max(pcs)] * 100), "% of the variance explained", sep="") if(sum(scoresLoadings) == 2) layout(matrix(c(1,2), 1, 2, TRUE), respect=matrix(c(1,1), 1, 2)) ## exception plot if one dimensional if (length(pcs) == 1 | nP(object) == 1) { pcs <- 1 ## score plot if(scoresLoadings[1]) { newCall <- call("barplot", height=scores(object)[,pcs], main="Scores", las=3, ylab=paste("PC", pcs), sub=sub, names.arg=sl) tmp <- cl[-mainArgs][scoreArgs] names(tmp) <- gsub("^s", "", names(tmp)) for(i in 1:length(tmp)) { newCall[[length(newCall) + 1]] <- tmp[[i]] names(newCall)[length(newCall)] <- names(tmp)[i] } eval(newCall) } ## loadingplot if(scoresLoadings[2]) { newCall <- call("barplot", height=loadings(object)[,pcs], main="Loadings", las=3, ylab=paste("PC", pcs), names.arg=ll) if(length(loadingArgs) > 0) { tmp <- cl[-mainArgs][loadingArgs] names(tmp) <- gsub("^l", "", names(tmp)) for(i in 1:length(tmp)) { newCall[[length(newCall) + 1]] <- tmp[[i]] names(newCall)[length(newCall)] <- names(tmp)[i] } } eval(newCall) } return(invisible(TRUE)) } ## the score plot if(scoresLoadings[1]) { ## setup plot plotCall <- call("plot", x=scores(object)[,pcs], main="Scores", ylab=paste("PC", pcs[2]), sub=sub, xlab=paste("PC", pcs[1])) if(length(scoreArgs) > 0) { tmp <- cl[-mainArgs][scoreArgs] names(tmp) <- gsub("^s", "", names(tmp)) for(i in 1:length(tmp)) { plotCall[[length(plotCall) + 1]] <- tmp[[i]] names(plotCall)[length(plotCall)] <- names(tmp)[i] } } ## add text if (!is.null(sl) & !all(is.na(sl))) { plotCall[[length(plotCall) + 1]] <- "n" names(plotCall)[length(plotCall)] <- "type" textCall <- call("text", x=scores(object)[,pcs], labels=sl) if(length(scoreArgs) > 0) { tmp <- cl[-mainArgs][scoreArgs] names(tmp) <- gsub("^s", "", names(tmp)) for(i in 1:length(tmp)) { textCall[[length(textCall) + 1]] <- tmp[[i]] names(textCall)[length(textCall)] <- names(tmp)[i] } } } eval(plotCall) if (!is.null(sl) & !all(is.na(sl))) eval(textCall) if(rug) rug(scores(object)[,1]) abline(h=0, v=0) if(!is.null(hotelling)) { A <- length(pcs) el <- simpleEllipse(scores(object)[,pcs[1]], scores(object)[,pcs[2]], alfa=hotelling) lines(el) } } ## the loading plot if(scoresLoadings[2]) { ## setup plot plotCall <- call("plot", x=loadings(object)[,pcs], main="Loadings", ylab=paste("PC", pcs[2]), xlab=paste("PC", pcs[1])) if(length(loadingArgs) > 0) { tmp <- cl[-mainArgs][loadingArgs] names(tmp) <- gsub("^l", "", names(tmp)) for(i in 1:length(tmp)) { plotCall[[length(plotCall) + 1]] <- tmp[[i]] names(plotCall)[length(plotCall)] <- names(tmp)[i] } } ## add text if (!is.null(ll) & !all(is.na(ll))) { plotCall[[length(plotCall) + 1]] <- "n" names(plotCall)[length(plotCall)] <- "type" textCall <- call("text", x=loadings(object)[,pcs], labels=ll) if(length(loadingArgs) > 0) { tmp <- cl[-mainArgs][loadingArgs] names(tmp) <- gsub("^l", "", names(tmp)) for(i in 1:length(tmp)) { textCall[[length(textCall) + 1]] <- tmp[[i]] names(textCall)[length(textCall)] <- names(tmp)[i] } } } eval(plotCall) if (!is.null(ll) & !all(is.na(ll))) eval(textCall) abline(h=0, v=0) } } par(opar) }) pcaMethods/R/nlpca.R0000644000175000017500000001664414136047224014132 0ustar nileshnilesh##' Neural network based non-linear PCA ##' ##' Artificial Neural Network (MLP) for performing non-linear ##' PCA. Non-linear PCA is conceptually similar to classical PCA but ##' theoretically quite different. Instead of simply decomposing our ##' matrix (X) to scores (T) loadings (P) and an error (E) we train a ##' neural network (our loadings) to find a curve through the ##' multidimensional space of X that describes a much variance as ##' possible. Classical ways of interpreting PCA results are thus not ##' applicable to NLPCA since the loadings are hidden in the network. ##' However, the scores of components that lead to low ##' cross-validation errors can still be interpreted via the score ##' plot. Unfortunately this method depend on slow iterations which ##' currently are implemented in R only making this method extremely ##' slow. Furthermore, the algorithm does not by itself decide when it ##' has converged but simply does 'maxSteps' iterations. ##' @title Non-linear PCA ##' @param Matrix \code{matrix} --- Preprocessed data with the ##' variables in columns and observations in rows. The data may ##' contain missing values, denoted as \code{NA} ##' @param nPcs \code{numeric} -- Number of components to ##' estimate. The preciseness of the missing value estimation depends ##' on thenumber of components, which should resemble the internal ##' structure of the data. ##' @param maxSteps \code{numeric} -- Number of estimation ##' steps. Default is based on a generous rule of thumb. ##' @param unitsPerLayer The network units, example: c(2,4,6) for two ##' input units 2feature units (principal components), one hidden ##' layer fornon-linearity and three output units (original amount ##' ofvariables). ##' @param functionsPerLayer The function to apply at each layer ##' eg. c("linr", "tanh", "linr") ##' @param weightDecay Value between 0 and 1. ##' @param weights Starting weights for the network. Defaults to ##' uniform random values but can be set specifically to make ##' algorithm deterministic. ##' @param verbose \code{boolean} -- nlpca prints the number of steps ##' and warning messages if set to TRUE. Default is interactive(). ##' @param ... Reserved for future use. Not passed on anywhere. ##' @return Standard PCA result object used by all PCA-basedmethods of ##' this package. Contains scores, loadings, data meanand more. See ##' \code{\link{pcaRes}} for details. ##' @author Based on a matlab script by Matthias Scholz and ported to ##' R by Henning Redestig ##' @references Matthias Scholz, Fatma Kaplan, Charles L Guy, Joachim ##' Kopkaand Joachim Selbig. Non-linear PCA: a missing ##' data approach. \emph{Bioinformatics, 21(20):3887-3895, Oct 2005} ##' @examples ##' ## Data set with three variables where data points constitute a helix ##' data(helix) ##' helixNA <- helix ##' ## not a single complete observation ##' helixNA <- t(apply(helix, 1, function(x) { x[sample(1:3, 1)] <- NA; x})) ##' ## 50 steps is not enough, for good estimation use 1000 ##' helixNlPca <- pca(helixNA, nPcs=1, method="nlpca", maxSteps=50) ##' fittedData <- fitted(helixNlPca, helixNA) ##' plot(fittedData[which(is.na(helixNA))], helix[which(is.na(helixNA))]) ##' ## compared to solution by Nipals PCA which cannot extract non-linear patterns ##' helixNipPca <- pca(helixNA, nPcs=2) ##' fittedData <- fitted(helixNipPca) ##' plot(fittedData[which(is.na(helixNA))], helix[which(is.na(helixNA))]) ##' @export nlpca <- function(Matrix, nPcs=2, maxSteps=2 * prod(dim(Matrix)), unitsPerLayer=NULL, functionsPerLayer=NULL, weightDecay=0.001, weights=NULL, verbose=interactive(),...) { ## do some basic checks object <- Matrix trainIn <- NULL trainOut <- t(object) stds <- apply(trainOut, 2, sd, na.rm=TRUE) scalingFactor <- 0.1 / max(stds) trainOut <- trainOut * scalingFactor ## now setup the initial nlpcaNet object numNaN <- sum(is.na(object)) ## always inverse in this version, bottleneck is not fully implemented inverse <- TRUE ## DATADIST (nlnet@dataDist) is given by weightOut dataDist <- apply(!is.na(trainOut), 2, as.integer) #0 for NA, 1 for everything else if(!inverse) dataDist <- NULL ## setup the network architecture if(is.null(unitsPerLayer)) { ld <- dim(trainOut)[1] lh <- nPcs if(nPcs < 10) lh <- 2 + 2 * nPcs unitsPerLayer <- c(ld, lh, nPcs, lh, ld) if(inverse) unitsPerLayer <- c(nPcs, lh, ld) } featureLayer <- ceiling(length(unitsPerLayer) / 2) if(inverse) featureLayer <- 1 if(is.null(functionsPerLayer)) { functionsPerLayer <- rep("tanh", length(unitsPerLayer)) functionsPerLayer[1] <- "linr" functionsPerLayer[featureLayer] <- "linr" functionsPerLayer[length(unitsPerLayer)] <- "linr" } hierarchic <- list(layer=featureLayer, var=rbind(c(rep(1, nPcs), 0.01)), idx=getHierarchicIdx(unitsPerLayer[featureLayer])) ## set up the weights wNum <- sum(sapply(2:length(unitsPerLayer), function(i) (1 + unitsPerLayer[i - 1]) * unitsPerLayer[i])) if(!is.null(weights) && length(weights) != wNum) { warning("Weight vector not expected length (", wNum, "), using random weights", sep="") weights <- NULL } if(is.null(weights)) weights <- cbind(0.2 * (runif(wNum, 0, 1) - 0.1)) if(inverse) { numPattern <- dim(trainOut)[2] tmpTrainIn <- cbind(rnorm(unitsPerLayer[1] * numPattern,0,1) * 0.1) weights <- rbind(tmpTrainIn, weights) } if(nPcs == 1) featureSorting <- FALSE if(nPcs > 1) featureSorting <- TRUE nlnet <- new("nlpcaNet") nlnet@net <- rbind(unitsPerLayer) nlnet@hierarchic <- hierarchic nlnet@fct <- functionsPerLayer nlnet@fkt <- functionsPerLayer[2:length(functionsPerLayer)] nlnet@weightDecay <- weightDecay nlnet@featureSorting <- featureSorting nlnet@dataDist <- dataDist nlnet@inverse <- inverse nlnet@fCount <- as.integer(0) nlnet@componentLayer <- as.integer(featureLayer) nlnet@error <- errorHierarchic nlnet@gradient <- derrorHierarchic nlnet@maxIter <- as.integer(maxSteps) nlnet@weights <- weightsAccount(weights) nlnet@scalingFactor <- scalingFactor ## ****************************** if(verbose) cat("Training network with", nlnet@maxIter, "iterations...\n!:\tSquare error is NA -- accuracy in line-search might be too small\n:\tComponents were sorted at iteration n\n^:\tToo many iterations while expanding\n") newnet <- optiAlgCgd(nlnet, trainIn, trainOut, verbose) if(verbose) cat("\nDone\n") if(inverse) { nObs <- unitsPerLayer[1] * dim(trainOut)[2] we <- newnet@weights$current() scores <- t(matrix(we[1:nObs], nrow=unitsPerLayer[1], dim(trainOut)[2])) newnet@weights$set(we[(nObs + 1):length(we),,drop=FALSE]) } ## for further applications newnet must not be inverse anymore newnet@inverse <- FALSE res <- new("pcaRes") res@scores <- scores res@loadings <- matrix() res@network <- newnet res@method <- "nlpca" R2cum <- rep(NA, nPcs) TSS <- sum(Matrix^2, na.rm=TRUE) for(i in 1:nPcs) R2cum[i] <- 1 - sum((Matrix - fitted(res, Matrix, nPcs=i))^2, na.rm=TRUE) / TSS res@R2cum <- R2cum res } ##' Index in hiearchy ##' @param hierarchicNum A number ##' @return ... ##' @author Henning Redestig, Matthias Scholz getHierarchicIdx <- function(hierarchicNum) { res <- matrix(1, ncol=hierarchicNum, nrow=hierarchicNum) res[lower.tri(res)] <- 0 cbind(res, c(0, rep(1, hierarchicNum - 1))) } pcaMethods/R/AllClasses.R0000644000175000017500000003074414136047224015060 0ustar nileshnilesh##' @include errorHierarchic.R ##' @include derrorHierarchic.R NULL ##' This is a class representation of a non-linear PCA neural ##' network. The \code{nlpcaNet} class is not meant for user-level ##' usage. ##' ##' Creating Objects ##' ##' \code{new("nlpcaNet", net=[the network structure], ##' hierarchic=[hierarchic design], ##' fct=[the functions at each layer], fkt=[the functions used for ##' forward propagation], weightDecay=[incremental decrease of weight ##' changes over iterations (between 0 and 1)], featureSorting=[sort ##' features or not], dataDist=[represents the present values], ##' inverse=[net is inverse mode or not], fCount=[amount of times ##' features were sorted], componentLayer=[which layer is the ##' 'bottleneck' (principal components)], ##' erro=[the used error function], gradient=[the used gradient method], ##' weights=[the present weights], ##' maxIter=[the amount of iterations that was done], scalingFactor=[the ##' scale of the original matrix])} ##' ##' Slots ##' ##' \describe{ ##' \item{net}{"matrix", matrix showing the representation of the ##' neural network, e.g. (2,4,6) for a network with two features, a ##' hidden layer and six output neurons (original variables).} ##' \item{hierarchic}{"list", the hierarchic design of the network, ##' holds 'idx' (), 'var' () and layer (which layer is the principal ##' component layer).} ##' \item{fct}{"character", a vector naming the functions that will be ##' applied on each layer. "linr" is linear (i.e.) standard matrix ##' products and "tanh" means that the arcus tangens is applied on the ##' result of the matrix product (for non-linearity).} ##' \item{fkt}{"character", same as fct but the functions used during ##' back propagation.} ##' \item{weightDecay}{"numeric", the value that is used to ##' incrementally decrease the weight changes to ensure convergence.} ##' \item{featureSorting}{"logical", indicates if features will be ##' sorted or not. This is used to make the NLPCA assume properties ##' closer to those of standard PCA were the first component is more ##' important for reconstructing the data than the second component.} ##' \item{dataDist}{"matrix", a matrix of ones and zeroes indicating ##' which values will add to the errror.} ##' \item{inverse}{"logical", network is inverse mode (currently only ##' inverse is supported) or not. Eg. the case when we have truly ##' missing values and wish to impute them.} ##' \item{fCount}{"integer", Counter for the amount of times features ##' were really sorted.} ##' \item{componentLayer}{"numeric", the index of 'net' that is the ##' component layer.} ##' \item{error}{"function", the used error function. Currently only one ##' is provided \code{errorHierarchic}.} ##' \item{gradient}{"function", the used gradient function. Currently ##' only one is provided \code{derrorHierarchic}} ##' \item{weights}{"list", A list holding managements of the ##' weights. The list has two functions, weights$current() and ##' weights$set() which access a matrix in the local environment of ##' this object.} ##' \item{maxIter}{"integer", the amount of iterations used to train ##' this network.} ##' \item{scalingFactor}{"numeric", training the network is best made ##' with 'small' values so the original data is scaled down to a ##' suitable range by division with this number.}} ##' ##' Methods ##' ##' \describe{ \item{vector2matrices}{Returns the ##' weights in a matrix representation.} } ##' @title Class representation of the NLPCA neural net ##' @docType class ##' @aliases nlpcaNet nlpcaNet-class ##' @seealso \code{\link{nlpca}} ##' @aliases nFit nFit-class ##' @exportClass nlpcaNet ##' @keywords classes ##' @name pcaNet ##' @author Henning Redestig setClass("nlpcaNet", representation(net="matrix", hierarchic="list", fct="character", fkt="character", weightDecay="numeric", featureSorting="logical", dataDist="matrix", inverse="logical", fCount="integer", componentLayer="integer", error="function", gradient="function", weights="list", maxIter="integer", scalingFactor="numeric"), prototype(net=rbind(c(4,6,2,6,4)), hierarchic=list(var=rbind(c(1,1,0.01)), layer=3, idx=rbind(c(1,1,0),c(0,1,1))), fct=c("linr", "tanh", "linr", "tanh", "linr"), fkt=c("tanh", "linr", "tanh", "linr"), weightDecay=0.001, featureSorting=TRUE, inverse=FALSE, dataDist=NULL, fCount=as.integer(0), componentLayer=as.integer(3), error=errorHierarchic, gradient=derrorHierarchic, weights=NULL, maxIter=as.integer(1200), scalingFactor=NULL)) setAs("NULL", "nlpcaNet", function(from, to){ new(to) }) ##' This is a class representation of a PCA result ##' ##' \bold{Creating Objects}\cr ##' \code{new("pcaRes", scores=[the scores], loadings=[the loadings], ##' nPcs=[amount of PCs], R2cum=[cumulative R2], nObs=[amount of ##' observations], nVar=[amount of variables], R2=[R2 for each ##' individual PC], sDev=[stdev for each individual PC], ##' centered=[was data centered], center=[original means], ##' varLimit=[what variance limit was exceeded], method=[method used to ##' calculate PCA], missing=[amount of NAs], ##' completeObs=[estimated complete observations])} ##' ##' \bold{Slots}\cr ##' \describe{ ##' \item{scores}{"matrix", the calculated scores} ##' \item{loadings}{"matrix", the calculated loadings} ##' \item{R2cum}{"numeric", the cumulative R2 values} ##' \item{sDev}{"numeric", the individual standard ##' deviations of the score vectors} ##' \item{R2}{"numeric", the individual R2 values} ##' \item{cvstat}{"numeric", cross-validation statistics} ##' \item{nObs}{"numeric", number of observations} ##' \item{nVar}{"numeric", number of variables} ##' \item{centered}{"logical", data was centered or not} ##' \item{center}{"numeric", the original variable centers} ##' \item{scaled}{"logical", data was scaled or not} ##' \item{scl}{"numeric", the original variable scales} ##' \item{varLimit}{"numeric", the exceeded variance limit} ##' \item{nPcs,nP}{"numeric", the number of calculated PCs} ##' \item{method}{"character", the method used to perform PCA} ##' \item{missing}{"numeric", the total amount of missing values in ##' original data} ##' \item{completeObs}{"matrix", the estimated complete observations} ##' \item{network}{"nlpcaNet", the network used by non-linear PCA} ##' } ##' ##' \bold{Methods (not necessarily exhaustive)}\cr ##' \describe{ ##' \item{print}{Print function} ##' \item{summary}{Extract information about PC relevance} ##' \item{screeplot}{Plot a barplot of standard deviations for PCs} ##' \item{slplot}{Make a side by side score and loadings plot} ##' \item{nPcs}{Get the number of PCs} ##' \item{nObs}{Get the number of observations} ##' \item{cvstat}{Cross-validation statistics} ##' \item{nVar}{Get the number of variables} ##' \item{loadings}{Get the loadings} ##' \item{scores}{Get the scores} ##' \item{dim}{Get the dimensions (number of observations, number of ##' features)} ##' \item{centered}{Get a logical indicating if centering was done as ##' part of the model} ##' \item{center}{Get the averages of the original variables.} ##' \item{completeObs}{Get the imputed data set} ##' \item{method}{Get a string naming the used PCA method} ##' \item{sDev}{Get the standard deviations of the PCs} ##' \item{scaled}{Get a logical indicating if scaling was done as ##' part of the model} ##' \item{scl}{Get the scales of the original variablesb} ##' \item{R2cum}{Get the cumulative R2} ##' } ##' @title Class for representing a PCA result ##' @keywords classes ##' @exportClass pcaRes ##' @docType class ##' @name pcaRes ##' @aliases pcaRes pcaRes-class ##' @author Henning Redestig setClass("pcaRes", representation(completeObs="matrix", scores="matrix", loadings="matrix", R2cum="numeric", R2="numeric", # ditch, get from R2cum cvstat="numeric", # ditch, get from R2cum sDev="numeric", # ditch, get from scores nObs="numeric", # ditch, get from scores nVar="numeric", centered="logical", center="numeric", subset="numeric", scaled="character", scale="numeric", varLimit="numeric", # ditch, useless nPcs="numeric", # ditch, get from scores method="character", missing="matrix", network="nlpcaNet"), prototype(completeObs=NULL, scores=NULL, loadings=NULL, R2cum=NULL, R2=NULL, subset=NULL, cvstat=NULL, sDev=NULL, nObs=NULL, nVar=NULL, centered=NULL, center=NULL, scaled=NULL, scale=NULL, varLimit=NULL, nPcs=NULL, method=NULL, missing=NULL, network=NULL)) setAs("NULL", "pcaRes", function(from, to){ new(to) }) ##' This is a class representation of nearest neighbour imputation ##' (nni) result ##' ##' \bold{Creating Objects}\cr ##' \code{new("nniRes", completeObs=[the estimated complete ##' observations], k=[cluster size], nObs=[amount of observations], ##' nVar=[amount of variables], centered=[was the data centered befor ##' running LLSimpute], center=[original means], method=[method used ##' to perform clustering], missing=[amount of NAs])} ##' ##' \bold{Slots}\cr ##' \describe{ ##' \item{completeObs}{"matrix", the estimated complete observations} ##' \item{nObs}{"numeric", amount of observations} ##' \item{nVar}{"numeric", amount of variables} ##' \item{correlation}{"character", the correlation method used ##' (pearson, kendall or spearman)} ##' \item{centered}{"logical", data was centered or not} ##' \item{center}{"numeric", the original variable centers} ##' \item{k}{"numeric", cluster size} ##' \item{method}{"character", the method used to perform the clustering} ##' \item{missing}{"numeric", the total amount of missing values in ##' original data} ##' } ##' ##' \bold{Methods}\cr ##' \describe{ \item{print}{Print function} } ##' @title Class for representing a nearest neighbour imputation result ##' @docType class ##' @exportClass nniRes ##' @name nniRes ##' @keywords classes ##' @aliases nniRes nniRes-class ##' @author Wolfram Stacklies setClass("nniRes", representation(completeObs="matrix", nObs="numeric", nVar="numeric", centered="logical", center="numeric", k="numeric", method="character", correlation="character", missing="numeric"), prototype(completeObs=NULL, nObs=NULL, nVar=NULL, centered=NULL, center=NULL, k=NULL, method=NULL, correlation=NULL, missing=NULL)) setAs("NULL", "nniRes", function(from, to) { new(to) }) ##' Create an object that holds the weights for nlpcaNet. Holds and ##' sets weights in using an environment object. ##' @param w \code{matrix} -- New weights ##' @return A weightsAccound with \code{set} and \code{current} ##' functions. ##' @author Henning Redestig weightsAccount <- function(w) { list( set = function(newWeights) { if(!inherits(newWeights, "matrix")) stop("The weights must inherit from matrix") w <<- newWeights }, current = function() { w } ) } pcaMethods/R/lineSearch.R0000644000175000017500000000615214136047224015103 0ustar nileshnilesh##' Line search for conjugate gradient ##' @param nlnet The nlnet ##' @param dw .. ##' @param e0 .. ##' @param ttGuess .. ##' @param trainIn Training data ##' @param trainOut Fitted data ##' @param verbose logical, print messages ##' @return ... ##' @author Henning Redestig, Matthias Scholz lineSearch <- function(nlnet, dw, e0, ttGuess, trainIn, trainOut, verbose) { iterGoldenSectionSearch <- 6 alpha <- 0.618034 tt <- rep(0, 4) e <- rep(0, 4) tmpnlnet <- forkNlpcaNet(nlnet) tt[1] <- 0 e[1] <- e0 tt[4] <- ttGuess tmpnlnet@weights$set(nlnet@weights$current() + tt[4] * dw) e[4] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error if(e[4] > e[1]) { #got final interval calculate tt[2] and tt[3] tt[2] <- tt[1] + (1 - alpha) * (tt[4] - tt[1]) tmpnlnet@weights$set(nlnet@weights$current() + tt[2] * dw) e[2] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error tt[3] <- tt[1] + alpha * (tt[4] - tt[1]) tmpnlnet@weights$set(nlnet@weights$current() + tt[3] * dw) e[3] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error } else { #expand, add new tt[4] tt[3] <- tt[4] e[3] <- e[4] tt[4] <- (1 + alpha) * tt[4] tmpnlnet@weights$set(nlnet@weights$current() + tt[4] * dw) e[4] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error if(e[4] > e[3]) { #got final interval, calculate tt[2] tt[2] <- tt[1] + (1 - alpha) * (tt[4] - tt[1]) tmpnlnet@weights$set(nlnet@weights$current() + tt[2] * dw) e[2] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error } else { #expand: add new tt[4] i <- 1 while(e[4] < e[3] && i < 50) { tt[2] <- tt[3] e[2] <- e[3] tt[3] <- tt[4] e[3] <- e[4] tt[4] <- (1 + alpha) * tt[4] tmpnlnet@weights$set(nlnet@weights$current() + tt[4] * dw) e[4] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error i <- i + 1 if(verbose && i == 50) cat("^") } } } ## golden section search for(i in 1:iterGoldenSectionSearch) { if(e[3] > e[2]) { tt[4] <- tt[3] #remove right value tt[4] e[4] <- e[3] tt[3] <- tt[2] e[3] <- e[2] tt[2] <- tt[1] + (1 - alpha) * (tt[4] - tt[1]) #split left interval tmpnlnet@weights$set(nlnet@weights$current() + tt[2] * dw) e[2] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error } else { tt[1] <- tt[2] #remove left t value tt[1] e[1] <- e[2] tt[2] <- tt[3] e[2] <- e[3] tt[3] <- tt[1] + alpha * (tt[4] - tt[1]) #split right interval tmpnlnet@weights$set(nlnet@weights$current() + tt[3] * dw) e[3] <- nlnet@error(tmpnlnet, trainIn, trainOut)$error } } if(e[2] < e[3]) { eBest <- e[2] ttBest <- tt[2] } else { eBest <- e[3] ttBest <- tt[3] } wBest <- nlnet@weights$current() + ttBest * dw return(list(wBest=wBest, eBest=eBest, ttBest=ttBest)) } ##' Linear kernel ##' @param x datum ##' @return Input value ##' @author Henning Redestig, Matthias Scholz linr <- function(x) x pcaMethods/R/robustPca.R0000644000175000017500000002237014136047224014770 0ustar nileshnilesh##' This is a PCA implementation robust to outliers in a data set. It ##' can also handle missing values, it is however NOT intended to be ##' used for missing value estimation. As it is based on robustSVD we ##' will get an accurate estimation for the loadings also for ##' incomplete data or for data with outliers. The returned scores ##' are, however, affected by the outliers as they are calculated ##' inputData X loadings. This also implies that you should look at ##' the returned R2/R2cum values with caution. If the data show ##' missing values, scores are caluclated by just setting all NA - ##' values to zero. This is not expected to produce accurate results. ##' Please have also a look at the manual page for \code{robustSvd}. ##' Thus this method should mainly be seen as an attempt to integrate ##' \code{robustSvd()} into the framework of this package. Use one of ##' the other methods coming with this package (like PPCA or BPCA) if ##' you want to do missing value estimation. It is not recommended to ##' use this function directely but rather to use the pca() wrapper ##' function. ##' ##' The method is very similar to the standard \code{prcomp()} ##' function. The main difference is that \code{robustSvd()} is used ##' instead of the conventional \code{svd()} method. ##' @title PCA implementation based on robustSvd ##' @param Matrix \code{matrix} -- Data containing the variables in ##' columns and observations in rows. The data may contain missing ##' values, denoted as \code{NA}. ##' @param nPcs \code{numeric} -- Number of components to ##' estimate. The preciseness of the missing value estimation depends ##' on the number of components, which should resemble the internal ##' structure of the data. ##' @param verbose \code{boolean} Print some output to the command ##' line if TRUE ##' @param ... Reserved for future use. Currently no further ##' parameters are used ##' @return Standard PCA result object used by all PCA-based methods ##' of this package. Contains scores, loadings, data mean and ##' more. See \code{\link{pcaRes}} for details. are used. ##' @seealso \code{\link{robustSvd}, \link{svd}, \link{prcomp}, ##' \link{pcaRes}}. ##' @examples ##' ## Load a complete sample metabolite data set and mean center the data ##' data(metaboliteDataComplete) ##' mdc <- scale(metaboliteDataComplete, center=TRUE, scale=FALSE) ##' ## Now create 5\% of outliers. ##' cond <- runif(length(mdc)) < 0.05; ##' mdcOut <- mdc ##' mdcOut[cond] <- 10 ##' ## Now we do a conventional PCA and robustPca on the original and the data ##' ## with outliers. ##' ## We use center=FALSE here because the large artificial outliers would ##' ## affect the means and not allow to objectively compare the results. ##' resSvd <- pca(mdc, method="svd", nPcs=10, center=FALSE) ##' resSvdOut <- pca(mdcOut, method="svd", nPcs=10, center=FALSE) ##' resRobPca <- pca(mdcOut, method="robustPca", nPcs=10, center=FALSE) ##' ## Now we plot the results for the original data against those with outliers ##' ## We can see that robustPca is hardly effected by the outliers. ##' plot(loadings(resSvd)[,1], loadings(resSvdOut)[,1]) ##' plot(loadings(resSvd)[,1], loadings(resRobPca)[,1]) ##' @keywords multivariate ##' @export ##' @author Wolfram Stacklies robustPca <- function(Matrix, nPcs=2, verbose=interactive(), ... ) { nas <- is.na(Matrix) if (sum(nas) != 0) warning("Data is incomplete, it is not recommended to use robustPca for missing value estimation") svdSol <- robustSvd(Matrix) ## Sort the eigenvalues and eigenvectors loadings <- svdSol$v[, 1:nPcs, drop=FALSE] sDev <- svdSol$d[1:nPcs] / sqrt(max(1, nrow(Matrix) - 1)) ## We estimate the scores by just setting all NA values to 0 This is ## a bad approximation, I know... Use ppca / bpca or other missing ## value estimation methods included in this package compMat <- Matrix compMat[is.na(compMat)] <- 0 scores <- compMat %*% loadings ## Calculate R2cum (on the complete observations only) R2cum <- rep(NA, nPcs) TSS <- sum(Matrix^2, na.rm=TRUE) for (i in 1:nPcs) { difference <- Matrix - (scores[,1:i, drop=FALSE] %*% t(loadings[,1:i, drop=FALSE])) R2cum[i] <- 1 - (sum(difference^2) / TSS) } result <- new("pcaRes") result@loadings <- loadings result@scores <- scores result@R2cum <- R2cum result@method <- "robustPca" return(result) } ##' A robust approximation to the singular value decomposition of a ##' rectangular matrix is computed using an alternating L1 norm ##' (instead of the more usual least squares L2 norm). As the SVD is ##' a least-squares procedure, it is highly susceptible to outliers ##' and in the extreme case, an individual cell (if sufficiently ##' outlying) can draw even the leading principal component toward ##' itself. ##' ##' See Hawkins et al (2001) for details on the robust SVD algorithm. ##' Briefly, the idea is to sequentially estimate the left and right ##' eigenvectors using an L1 (absolute value) norm minimization. ##' ##' Note that the robust SVD is able to accomodate missing values in ##' the matrix \code{x}, unlike the usual \code{svd} function. ##' ##' Also note that the eigenvectors returned by the robust SVD ##' algorithm are NOT (in general) orthogonal and the eigenvalues need ##' not be descending in order. ##' @title Alternating L1 Singular Value Decomposition ##' @param x A matrix whose SVD decomposition is to be ##' computed. Missing values are allowed. ##' @return The robust SVD of the matrix is x=u d v'. \item{d}{A ##' vector containing the singular values of \code{x}.} \item{u}{A ##' matrix whose columns are the left singular vectors of \code{x}.} ##' \item{v}{A matrix whose columns are the right singular vectors of ##' \code{x}.} ##' @note Two differences from the usual SVD may be noted. One relates ##' to orthogonality. In the conventional SVD, all the eigenvectors ##' are orthogonal even if not explicitly imposed. Those returned by ##' the AL1 algorithm (used here) are (in general) not orthogonal. ##' Another difference is that, in the L2 analysis of the conventional ##' SVD, the successive eigen triples (eigenvalue, left eigenvector, ##' right eigenvector) are found in descending order of ##' eigenvalue. This is not necessarily the case with the AL1 ##' algorithm. Hawkins et al (2001) note that a larger eigen value ##' may follow a smaller one. ##' @references Hawkins, Douglas M, Li Liu, and S Stanley Young (2001) ##' Robust Singular Value Decomposition, National Institute of ##' Statistical Sciences, Technical Report Number ##' 122. \url{http://www.niss.org/technicalreports/tr122.pdf} ##' @author Kevin Wright, modifications by Wolfram Stacklies ##' @seealso \code{\link{svd}}, \code{\link[ade4:nipals]{nipals}} for ##' an alternating L2 norm method that also accommodates missing data. ##' @examples ##' ## Load a complete sample metabolite data set and mean center the data ##' data(metaboliteDataComplete) ##' mdc <- prep(metaboliteDataComplete, center=TRUE, scale="none") ##' ## Now create 5% of outliers. ##' cond <- runif(length(mdc)) < 0.05; ##' mdcOut <- mdc ##' mdcOut[cond] <- 10 ##' ## Now we do a conventional SVD and a robustSvd on both, the original and the ##' ## data with outliers. ##' resSvd <- svd(mdc) ##' resSvdOut <- svd(mdcOut) ##' resRobSvd <- robustSvd(mdc) ##' resRobSvdOut <- robustSvd(mdcOut) ##' ## Now we plot the results for the original data against those with outliers ##' ## We can see that robustSvd is hardly affected by the outliers. ##' plot(resSvd$v[,1], resSvdOut$v[,1]) ##' plot(resRobSvd$v[,1], resRobSvdOut$v[,1]) ##' @keywords algebra ##' @export robustSvd <- function(x) { ## We need the weightedMedian function provided by the aroma.light ## package. However we do not want to make the whole package dependant ## on aroma.light if (!requireNamespace("matrixStats", quietly=TRUE)) stop("package matrixStats required but not available") L1RegCoef <- function(x, a){ keep <- (abs(a) > .Machine$double.eps) & (!is.na(x)) if(!any(keep)) { warning("No non-missing data for l1 regression, unstable results") return(0.) } a <- a[keep] return(matrixStats::weightedMedian(x[keep] / a, abs(a), na.rm=TRUE, interpolate=FALSE)) } L1Eigen <- function(x, a, b){ x <- as.vector(x) # Convert from matrix to vector ab <- as.vector(outer(a, b)) keep <- (abs(ab) > .Machine$double.eps) & (!is.na(x)) ab <- ab[keep] return(matrixStats::weightedMedian(x[keep] / ab, abs(ab), na.rm=TRUE, interpolate=FALSE)) } ## Initialize outputs svdu <- matrix(NA, nrow=nrow(x), ncol=ncol(x)) svdv <- matrix(NA, nrow=ncol(x), ncol=ncol(x)) svdd <- rep(NA, ncol(x)) for(k in 1:ncol(x)) { ak <- apply(abs(x), 1, median, na.rm=TRUE) converged <- FALSE while(!converged) { akprev <- ak c <- apply(x, 2, L1RegCoef, ak) bk <- c / sqrt(sum(c^2)) d <- apply(x, 1, L1RegCoef, bk) ak <- d / sqrt(sum(d^2)) if(sum((ak - akprev)^2) < 1e-10) { converged <- TRUE } } eigenk <- L1Eigen(x,ak,bk) ## Deflate the x matrix x <- x - eigenk * ak %*% t(bk) ## Store eigen triple for output svdu[,k] <- ak svdv[,k] <- bk svdd[k] <- eigenk } ## Create the result object ret <- list() ret$d <- svdd ret$u <- svdu ret$v <- svdv return(ret) } pcaMethods/R/forkNlpcaNet.R0000644000175000017500000000131414136047224015407 0ustar nileshnilesh##' Complete copy of nlpca net object ##' @param nlnet a nlnet ##' @return A copy of the input nlnet ##' @author Henning Redestig forkNlpcaNet <- function(nlnet) { res <- new("nlpcaNet") res@net <- nlnet@net res@hierarchic <- nlnet@hierarchic res@fct <- nlnet@fct res@fkt <- nlnet@fkt res@weightDecay <- nlnet@weightDecay res@featureSorting <- nlnet@featureSorting res@dataDist <- nlnet@dataDist res@inverse <- nlnet@inverse res@fCount <- nlnet@fCount res@componentLayer <- nlnet@componentLayer res@error <- nlnet@error res@gradient <- nlnet@gradient res@weights <- weightsAccount(nlnet@weights$current()) res@maxIter <- nlnet@maxIter res@scalingFactor <- nlnet@scalingFactor res } pcaMethods/R/xval.R0000644000175000017500000002764114136047224014006 0ustar nileshnilesh##' Internal cross-validation can be used for estimating the level of ##' structure in a data set and to optimise the choice of number of ##' principal components. ##' ##' This method calculates \eqn{Q^2} for a PCA model. This is the ##' cross-validated version of \eqn{R^2} and can be interpreted as the ##' ratio of variance that can be predicted independently by the PCA ##' model. Poor (low) \eqn{Q^2} indicates that the PCA model only ##' describes noise and that the model is unrelated to the true data ##' structure. The definition of \eqn{Q^2} is: \deqn{Q^2=1 - ##' \frac{\sum_{i}^{k}\sum_{j}^{n}(x - ##' \hat{x})^2}{\sum_{i}^{k}\sum_{j}^{n}x^2}}{Q^2=1 - sum_i^k sum_j^n ##' (x - \hat{x})^2 / \sum_i^k \sum_j^n(x^2)} for the matrix \eqn{x} ##' which has \eqn{n} rows and \eqn{k} columns. For a given number of ##' PC's x is estimated as \eqn{\hat{x}=TP'} (T are scores and P are ##' loadings). Although this defines the leave-one-out ##' cross-validation this is not what is performed if fold is less ##' than the number of rows and/or columns. In 'impute' type CV, ##' diagonal rows of elements in the matrix are deleted and the ##' re-estimated. In 'krzanowski' type CV, rows are sequentially left ##' out to build fold PCA models which give the loadings. Then, ##' columns are sequentially left out to build fold models for ##' scores. By combining scores and loadings from different models, we ##' can estimate completely left out values. The two types may seem ##' similar but can give very different results, krzanowski typically ##' yields more stable and reliable result for estimating data ##' structure whereas impute is better for evaluating missing value ##' imputation performance. Note that since Krzanowski CV operates on ##' a reduced matrix, it is not possible estimate Q2 for all ##' components and the result vector may therefore be shorter than ##' \code{nPcs(object)}. ##' @title Cross-validation for PCA ##' @param object A \code{pcaRes} object (result from previous PCA ##' analysis.) ##' @param originalData The matrix (or ExpressionSet) that used to ##' obtain the pcaRes object. ##' @param fold The number of groups to divide the data in. ##' @param nruncv The number of times to repeat the whole ##' cross-validation. The deletion of diagnols in 'impute' is ##' deterministic so result will alsways be the same but in ##' krzanowski where cv-split is obtained by sampling it can be ##' informative to examine the spread of the Q2 values over several ##' CV runs. ##' @param type krzanowski or imputation type cross-validation ##' @param verbose \code{boolean} If TRUE Q2 outputs a primitive ##' progress bar. ##' @param variables indices of the variables to use during ##' cross-validation calculation. Other variables are kept as they ##' are and do not contribute to the total sum-of-squares. ##' @param ... Further arguments passed to the \code{\link{pca}} ##' function called within Q2. ##' @return A matrix or vector with \eqn{Q^2} estimates. ##' @export ##' @references Krzanowski, WJ. Cross-validation in principal ##' component analysis. Biometrics. 1987(43):3,575-584 ##' @examples ##' data(iris) ##' x <- iris[,1:4] ##' pcIr <- pca(x, nPcs=3) ##' q2 <- Q2(pcIr, x) ##' barplot(q2, main="Krzanowski CV", xlab="Number of PCs", ylab=expression(Q^2)) ##' ## q2 for a single variable ##' Q2(pcIr, x, variables=2) ##' pcIr <- pca(x, nPcs=3, method="nipals") ##' q2 <- Q2(pcIr, x, type="impute") ##' barplot(q2, main="Imputation CV", xlab="Number of PCs", ylab=expression(Q^2)) ##' @author Henning Redestig, Ondrej Mikula ##' @keywords multivariate Q2 <- function (object, originalData=completeObs(object), fold=5, nruncv=1, type=c("krzanowski", "impute"), verbose=interactive(), variables=1:nVar(object), ...) { type <- match.arg(type) if (inherits(originalData, "ExpressionSet")) { set <- originalData originalData <- t(exprs(originalData)) } if (is.null(originalData)) stop("missing data when estimating Q2") originalData <- as.matrix(originalData) originalData <- prep(originalData, scale=scl(object), center=center(object)) nR <- nObs(object) nC <- nVar(object) if (nR != nrow(originalData) | nC != ncol(originalData)) stop("data and model dimensions do not match") if (fold > max(nR, nC)) stop("fold must be equal or less to max dimension of original data") if (method(object) %in% c("svd") & type != "krzanowski") stop("Chosen PCA method must use krzanowski type cv") if (method(object) %in% c("llsImpute") & type != "impute") stop("Chosen PCA method must use impute type cv") if (is.logical(variables)) variables <- which(variables) ssx <- sum(originalData[, variables]^2, na.rm=TRUE) if(type == "impute") nP <- nPcs(object) if(type == "krzanowski") { rseg <- split(sample(1:nR), rep(1:fold, ceiling(nR/fold))[1:nR]) cseg <- split(sample(1:nC), rep(1:fold, ceiling(nC/fold))[1:nC]) foldC <- length(cseg) foldR <- length(rseg) nP <- min(nR - max(sapply(rseg, length)), nC - max(sapply(cseg, length)), nPcs(object)) } q2 <- matrix(NA, nP, ncol=nruncv) for (nr in 1:nruncv) { press <- rep(0, nP) if (type == "impute") { seg <- list() nDiag <- max(nR, nC) diagPerFold <- floor(nDiag / fold) suppressWarnings(diags <- matrix(1:nDiag, nrow=diagPerFold, ncol=fold, byrow=TRUE)) if (diagPerFold == 0 || diagPerFold > (nDiag/2)) stop("Matrix could not be safely divided into ", fold, " segments. Choose a different fold or provide the desired segments") if (nDiag%%fold > 0) warning("Validation incomplete: ", (nDiag %% fold) * min(dim(originalData)), " values were left out of from cross validation, Q2 estimate will be biased.") for (i in 1:ncol(diags)) seg[[i]] <- which(is.na(deletediagonals(originalData, diags[, i]))) if (verbose) { pb <- txtProgressBar(0, length(seg), style=3, width=20) } j <- 0 for (i in seg) { j <- j + 1 if (verbose) setTxtProgressBar(pb, j) test <- originalData test[i] <- NA test <- tempFixNas(test) if (method(object) != "llsImpute") { pc <- pca(test, nPcs=nP, method=method(object), verbose=FALSE, center=centered(object), scale=object@scaled, ...) } for (np in 1:nP) { if (method(object) == "llsImpute") { fittedData <- completeObs(llsImpute(test, k=np, allVariables=TRUE, center=FALSE)) } else { if (method(object) == "nlpca") fittedData <- fitted(pc, data=test, nPcs=np) else fittedData <- fitted(pc, data=NULL, nPcs=np) } ii <- i[ceiling(i / nR) %in% variables] press[np] <- press[np] + sum((originalData[ii] - fittedData[ii])^2, na.rm=TRUE) } } } if (type == "krzanowski") { rseg <- split(sample(1:nR), rep(1:fold, ceiling(nR/fold))[1:nR]) cseg <- split(sample(1:nC), rep(1:fold, ceiling(nC/fold))[1:nC]) tcv <- array(0, dim=c(foldC, nR, nP)) pcv <- array(0, dim=c(foldR, nC, nP)) for (f in 1:foldC) { test <- tempFixNas(originalData[, -cseg[[f]]]) tcv[f, , ] <- scores(pca(test, nPcs=nP, method=method(object), verbose=FALSE, center=centered(object), scale=object@scaled, ...)) for (p in 1:nP) { if (cor(tcv[f, , p], scores(object)[, p]) < 0) tcv[f, , p] <- tcv[f, , p] * -1 } } for (f in 1:foldR) { test <- tempFixNas(originalData[-rseg[[f]], ]) pcv[f, , ] <- loadings(pca(test, nPcs=nP, method=method(object), verbose=FALSE, center=centered(object), scale=object@scaled, ...)) for (p in 1:nP) { if (cor(pcv[f, , p], loadings(object)[, p]) < 0) pcv[f, , p] <- pcv[f, , p] * -1 } } press <- rep(0, nP) for (p in 1:nP) for (fr in 1:foldR) for (fc in 1:foldC) press[p] <- press[p] + sum(( originalData[rseg[[fr]], cseg[[fc]]] - (tcv[fc, , ][, 1:p, drop=FALSE] %*% t(pcv[fr, , ][,1:p, drop=FALSE])) [rseg[[fr]], intersect(cseg[[fc]], variables)])^2, na.rm=TRUE) } q2[, nr] <- 1 - press/ssx } if (verbose) message("\n") rownames(q2) <- paste("PC", 1:nrow(q2)) drop(q2) } ##' Simply replace completely missing rows or cols with zeroes. ##' @title Temporary fix for missing values ##' @param mat a matrix ##' @return The original matrix with completely missing rows/cols ##' filled with zeroes. ##' @author Henning Redestig tempFixNas <- function(mat) { badRows <- apply(mat, 1, function(x) all(is.na(x))) badCols <- apply(mat, 2, function(x) all(is.na(x))) mat[ badRows,] <- 0 mat[,badCols ] <- 0 mat } ##' Replace a diagonal of elements of a matrix with NA ##' ##' Used for creating artifical missing values in matrices without ##' causing any full row or column to be completely missing ##' @title Delete diagonals ##' @param x The matrix ##' @param diagonals The diagonal to be replaced, i.e. the first, ##' second and so on when looking at the fat version of the matrix ##' (transposed or not) counting from the bottom. ##' Can be a vector to delete more than one diagonal. ##' @return The original matrix with some values missing ##' @author Henning Redestig deletediagonals <- function(x, diagonals=1) { wastransposed <- FALSE if (dim(x)[1] > dim(x)[2]) { # matrix must be lying down x <- t(x) wastransposed <- TRUE } nr <- nrow(x) nc <- ncol(x) if (!all(diagonals <= nc)) { stop(paste("Order of diagonal number", max(diagonals), "is out of bound")) } indexmatrix <- matrix(1 : (nr * nc), ncol=nc, nrow=nr) finalmatrix <- matrix(ncol=(nr - 1 + nc), nrow=nr) finalmatrix[,1 : (nr - 1)] <- indexmatrix[,rev((nc : 1)[1 : (nr - 1)])] finalmatrix[,nr : (nr - 1 + nc)] <- indexmatrix dia <- 1 + 0:(nr - 1) * (nr + 1) finalIndices <- NULL for (i in 1:length(diagonals)) { indicestodelete <- finalmatrix[dia + (diagonals[i] - 1) * nr] x[indicestodelete] <- NA finalIndices <- c(finalIndices, indicestodelete) } if (wastransposed) x <- t(x) return(x) } ##' Get cross-validation segments that have (as far as possible) the ##' same ratio of all classes (if classes are present) ##' @title Get CV segments ##' @param x a factor, character or numeric vector that describes ##' class membership of a set of items, or, a numeric vector ##' indicating unique indices of items, or, a numeric of length 1 that ##' describes the number of items to segment (without any classes) ##' @param fold the desired number of segments ##' @param seed randomization seed for reproducibility ##' @return a list where each element is a set of indices that defines ##' the CV segment. ##' @examples ##' seg <- cvseg(iris$Species, 10) ##' sapply(seg, function(s) table(iris$Species[s])) ##' cvseg(20, 10) ##' @seealso the \code{cvsegments} function in the \code{pls} package ##' @export ##' @author Henning Redestig cvseg <- function(x, fold=7, seed=NULL) { if(any(table(x) > 1)) { if(any(table(x) < fold)) { fold <- min(table(x)) } if(fold < 2) stop("too few observations in the smallest class") res <- sapply(unique(x), function(z) { if(!is.null(seed)) set.seed(seed) tmp <- sample(which(x == z)) seg <- matrix(c(tmp, rep(NA, ifelse(length(tmp) %% fold ==0, 0, fold - (length(tmp) %% fold)))), nrow=fold) },simplify=FALSE) res <- do.call("cbind", res) } else { if(length(x) == 1) x <- 1:x res <- matrix(sample(c(x, rep(NA, ifelse(length(x) %% fold ==0, 0, fold - (length(x) %% fold))))), nrow=fold) } res <- res[!apply(is.na(res), 1, all),,drop=FALSE] res lapply(as.data.frame(t(res)), function(x) c(na.omit(x))) } pcaMethods/R/methods-nniRes.R0000644000175000017500000000161114136047224015720 0ustar nileshnilesh##' Print a brief description of nniRes model ##' @title Print a nniRes model ##' @param x An \code{nniRes} object ##' @param ... Not used ##' @return Nothing, used for side-effect ##' @export ##' @author Henning Redestig showNniRes <- function(x, ...) { summary(x) cat(dim(x)["nVar"], "\tVariables\n") cat(dim(x)["nObs"],"\tSamples\n") cat(nmissing(x), "\tNAs (", round(100 * nmissing(x) / (nObs(x) * nVar(x)), getOption("str")$digits.d), "%)\n") cat("k was set to", x@k, "\n") if(centered(x)) cat("Data was mean centered before running LLSimpute \n") else cat("Data was NOT mean centered before running LLSimpute \n") if(scaled(x)) cat("Data was scaled before running LLSimpute \n") else cat("Data was NOT scaled before running LLSimpute \n") } setMethod("print", "nniRes", showNniRes) setMethod("show", "nniRes", function(object) showNniRes(object)) pcaMethods/R/kEstimateFast.R0000644000175000017500000001215414136047224015571 0ustar nileshnilesh##' This is a simple estimator for the optimal number of componets ##' when applying PCA or LLSimpute for missing value estimation. No ##' cross validation is performed, instead the estimation quality is ##' defined as Matrix[!missing] - Estimate[!missing]. This will give a ##' relatively rough estimate, but the number of iterations equals the ##' length of the parameter evalPcs.\cr Does not work with LLSimpute!! ##' As error measure the NRMSEP (see Feten et. al, 2005) or the Q2 ##' distance is used. The NRMSEP basically normalises the RMSD ##' between original data and estimate by the variable-wise ##' variance. The reason for this is that a higher variance will ##' generally lead to a higher estimation error. If the number of ##' samples is small, the gene - wise variance may become an unstable ##' criterion and the Q2 distance should be used instead. Also if ##' variance normalisation was applied previously. ##' @title Estimate best number of Components for missing value estimation ##' @param Matrix \code{matrix} -- numeric matrix containing ##' observations in rows and variables in columns ##' @param method \code{character} -- a valid pca method (see ##' \code{\link{pca}}). ##' @param evalPcs \code{numeric} -- The principal components to use ##' for cross validation or cluster sizes if used with ##' llsImpute. Should be an array containing integer values, ##' eg. evalPcs = 1:10 or evalPcs = C(2,5,8).The NRMSEP is calculated ##' for each component. ##' @param em \code{character} -- The error measure. This can be ##' nrmsep or q2 ##' @param allVariables \code{boolean} -- If TRUE, the NRMSEP is ##' calculated for all variables, If FALSE, only the incomplete ones ##' are included. You maybe want to do this to compare several methods ##' on a complete data set. ##' @param verbose \code{boolean} -- If TRUE, the NRMSEP and the ##' variance are printed to the console each iteration. ##' @param ... Further arguments to \code{pca} ##' @return \item{list}{Returns a list with the elements: ##' \itemize{ ##' \item minNPcs - number of PCs for which the minimal average NRMSEP ##' was obtained ##' \item eError - an array of of size length(evalPcs). Contains the ##' estimation error for each number of ##' components. ##' \item evalPcs - The evaluated numbers of components or ##' cluster sizes (the same as the evalPcs input parameter). }} ##' @seealso \code{\link{kEstimate}}. ##' @export ##' @examples ##' data(metaboliteData) ##' # Estimate best number of PCs with ppca for component 2:4 ##' esti <- kEstimateFast(t(metaboliteData), method = "ppca", evalPcs = 2:4, em="nrmsep") ##' barplot(drop(esti$eError), xlab = "Components",ylab = "NRMSEP (1 iterations)") ##' # The best k value is: ##' print(esti$minNPcs) ##' @keywords multivariate ##' @author Wolfram Stacklies kEstimateFast <- function(Matrix, method = "ppca", evalPcs = 1:3, em = "nrmsep", allVariables = FALSE, verbose = interactive(), ...) { method <- match.arg(method, c("ppca", "bpca", "svdImpute", "nipals", "nlpca")) em <- match.arg(em, c("nrmsep", "q2")) maxPcs <- max(evalPcs) lengthPcs <- length(evalPcs) missing <- is.na(Matrix) error <- array(0, lengthPcs) ## If the data is a data frame, convert it into a matrix Matrix <- as.matrix(Matrix, rownames.force=TRUE) if(maxPcs > (ncol(Matrix) - 1)) stop("maxPcs exceeds matrix size, choose a lower value!") ## And now check if everything is right... if( !checkData(Matrix, verbose=interactive()) ) stop("Invalid data format! Use checkData(Matrix, verbose = TRUE) for details.\n") if( (sum(is.na(Matrix)) == 0) && (allVariables == FALSE) ) stop("No missing values. Maybe you want to set allVariables = TRUE. Exiting\n") iteration = 0 for(nPcs in evalPcs) { iteration = iteration + 1 if (method == "nlpca") { estimate <- fitted(pca(Matrix, nPcs = nPcs, verbose = FALSE, method = method, center = TRUE,...), Matrix, nPcs = nPcs) } else { estimate <- fitted(pca(Matrix, nPcs = nPcs, verbose = FALSE, method = method, center = TRUE,...), nPcs = nPcs) } if (em == "q2") { # The Q2 distance q2 <- 1 - sum((Matrix[!missing] - estimate[!missing])^2) / sum(Matrix[!missing]^2) error[iteration] <- q2 } else { nrmsep <- 0 for(i in 1:ncol(Matrix)) { nrmsep <- nrmsep + ( sum((Matrix[!missing[,i], i] - estimate[!missing[,i], i])^2) / (sum(!missing[,i]) * var(Matrix[,i], na.rm = TRUE)) ) } nrmsep <- nrmsep / sum(apply(missing, 2, sum) > 0) error[iteration] <- nrmsep } if(verbose) cat("The", em, "for", evalPcs[iteration], "components is:", error[iteration], "\n") } ret <- list() if (em == "nrmsep") ret$bestNPcs <- evalPcs[which(error == min(error))] else ret$bestNPcs <- evalPcs[which(error == max(error))] ret$eError <- error ret$evalPcs <- evalPcs return(ret) } pcaMethods/R/pca.R0000644000175000017500000003477014136047224013600 0ustar nileshnilesh##' Vector with current valid PCA methods ##' @title List PCA methods ##' @param which the type of methods to get. E.g. only get the PCA ##' methods based on the classical model where the fitted data is a ##' direct multiplication of scores and loadings. ##' @return A character vector with the current methods for doing PCA ##' @export ##' @author Henning Redestig listPcaMethods <- function(which=c("all", "linear", "nonlinear")) { switch(match.arg(which), all={ return(c("svd", "nipals", "rnipals", "bpca", "ppca", "svdImpute", "robustPca", "nlpca", "llsImpute", "llsImputeAll")) }, linear={ return(c("svd", "nipals", "rnipals", "bpca", "ppca", "svdImpute", "robustPca")) }, nonlinear={ return("nlpca") }) } ##' Perform PCA on a numeric matrix for visualisation, information ##' extraction and missing value imputation. ##' ##' This method is wrapper function for the following set of pca ##' methods: ##' ##' \describe{\item{svd:}{Uses classical \code{prcomp}. See ##' documentation for \code{\link{svdPca}}.} ##' ##' \item{nipals:}{An iterative method capable of handling small ##' amounts of missing values. See documentation for ##' \code{\link{nipalsPca}}.} ##' ##' \item{rnipals:}{Same as nipals but implemented in R.} ##' ##' \item{bpca:}{An iterative method using a Bayesian model to handle ##' missing values. See documentation for \code{\link{bpca}}.} ##' ##' \item{ppca:}{An iterative method using a probabilistic model to ##' handle missing values. See documentation for \code{\link{ppca}}.} ##' ##' \item{svdImpute:}{Uses expectation maximation to perform SVD PCA ##' on incomplete data. See documentation for ##' \code{\link{svdImpute}}.}} ##' ##' Scaling and centering is part of the PCA model and handled by ##' \code{\link{prep}}. ##' @title Perform principal component analysis ##' @param object Numerical matrix with (or an object coercible to ##' such) with samples in rows and variables as columns. Also takes ##' \code{ExpressionSet} in which case the transposed expression ##' matrix is used. Can also be a data frame in which case all ##' numberic variables are used to fit the PCA. ##' @param method One of the methods reported by ##' \code{listPcaMethods()}. Can be left missing in which case the ##' \code{svd} PCA is chosen for data wihout missing values and ##' \code{nipalsPca} for data with missing values ##' @param nPcs Number of principal components to calculate. ##' @param scale Scaling, see \code{\link{prep}}. ##' @param center Centering, see \code{\link{prep}}. ##' @param completeObs Sets the \code{completeObs} slot on the ##' resulting \code{pcaRes} object containing the original data with ##' but with all NAs replaced with the estimates. ##' @param subset A subset of variables to use for calculating the ##' model. Can be column names or indices. ##' @param cv character naming a the type of cross-validation ##' to be performed. ##' @param ... Arguments to \code{\link{prep}}, the chosen pca ##' method and \code{\link{Q2}}. ##' @return A \code{pcaRes} object. ##' @references ##' Wold, H. (1966) Estimation of principal components and ##' related models by iterative least squares. In Multivariate ##' Analysis (Ed., P.R. Krishnaiah), Academic Press, NY, 391-420. ##' ##' Shigeyuki Oba, Masa-aki Sato, Ichiro Takemasa, Morito Monden, ##' Ken-ichi Matsubara and Shin Ishii. A Bayesian missing value ##' estimation method for gene expression profile ##' data. \emph{Bioinformatics, 19(16):2088-2096, Nov 2003}. ##' ##' Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and ##' Hastie T. and Tibshirani R. and Botstein D. and Altman RB. - ##' Missing value estimation methods for DNA microarrays. ##' \emph{Bioinformatics. 2001 Jun;17(6):520-5}. ##' @seealso \code{\link{prcomp}}, \code{\link{princomp}}, ##' \code{\link{nipalsPca}}, \code{\link{svdPca}} ##' @examples ##' data(iris) ##' ## Usually some kind of scaling is appropriate ##' pcIr <- pca(iris, method="svd", nPcs=2) ##' pcIr <- pca(iris, method="nipals", nPcs=3, cv="q2") ##' ## Get a short summary on the calculated model ##' summary(pcIr) ##' plot(pcIr) ##' ## Scores and loadings plot ##' slplot(pcIr, sl=as.character(iris[,5])) ##' ##' ## use an expressionset and ggplot ##' data(sample.ExpressionSet) ##' pc <- pca(sample.ExpressionSet) ##' df <- merge(scores(pc), pData(sample.ExpressionSet), by=0) ##' library(ggplot2) ##' ggplot(df, aes(PC1, PC2, shape=sex, color=type)) + ##' geom_point() + ##' xlab(paste("PC1", pc@R2[1] * 100, "% of the variance")) + ##' ylab(paste("PC2", pc@R2[2] * 100, "% of the variance")) ##' @export ##' @keywords multivariate ##' @author Wolfram Stacklies, Henning Redestig pca <- function(object, method, nPcs=2, scale=c("none", "pareto", "vector", "uv"), center=TRUE, completeObs=TRUE, subset=NULL, cv=c("none","q2"), ...) { if(inherits(object, 'data.frame')) { num <- vapply(object, is.numeric, logical(1)) if(sum(num) < 2) stop('no numeric data in supplied data.frame') Matrix <- as.matrix(object[,num]) } else if(inherits(object, "ExpressionSet")) { Matrix <- t(exprs(object)) } else Matrix <- as.matrix(object, rownames.force=TRUE) if(!is.null(subset)) Matrix <- Matrix[,subset] cv <- match.arg(cv) scale <- match.arg(scale) if (nPcs > ncol(Matrix)) { warning("more components than matrix columns requested") nPcs <- min(dim(Matrix)) } if (nPcs > nrow(Matrix)) { warning("more components than matrix rows requested") nPcs <- min(dim(Matrix)) } if (!checkData(Matrix, verbose=interactive())) stop("Invalid data format.", "Run checkData(data, verbose=TRUE) for details") missing <- is.na(Matrix) if(missing(method)) { if(any(missing)) method <- 'nipals' else method <- 'svd' } if(any(missing) & method == 'svd') { warning('data has missing values using nipals instead of user requested svd') method <- 'nipals' } method <- match.arg(method, choices=listPcaMethods()) prepres <- prep(Matrix, scale=scale, center=center, simple=FALSE, ...) switch(method, svd={ res <- svdPca(prepres$data, nPcs=nPcs,...) }, nipals={ res <- nipalsPca(prepres$data, nPcs=nPcs, ...) }, rnipals={ res <- RnipalsPca(prepres$data, nPcs=nPcs, ...) }, bpca={ res <- bpca(prepres$data, nPcs=nPcs, ...) }, ppca={ res <- ppca(prepres$data, nPcs=nPcs, ...) }, svdImpute={ res <- svdImpute(prepres$data, nPcs=nPcs, ...) }, robustPca={ res <- robustPca(prepres$data, nPcs=nPcs, ...) }, nlpca={ res <- nlpca(prepres$data, nPcs=nPcs, ...) }) nPcs <- ncol(res@scores) if(is.null(scores(res)) | is.null(loadings(res)) | is.null(R2cum(res)) | is.null(method(res))) stop(paste("bad result from pca method", method)) colnames(res@scores) <- paste("PC", 1:nPcs, sep="") rownames(res@scores) <- rownames(Matrix) if(all(dim(loadings(res)) == c(ncol(Matrix), nPcs))) { colnames(res@loadings) <- paste("PC", 1:nPcs, sep="") rownames(res@loadings) <- colnames(Matrix) } if(!is.null(subset)) res@subset <- subset res@missing <- missing res@nPcs <- nPcs res@nObs <- nrow(Matrix) res@nVar <- ncol(Matrix) res@sDev <- apply(scores(res), 2, sd) res@center <- prepres$center res@centered <- center res@scale <- prepres$scale res@scaled <- scale res@R2 <- res@R2cum[1] if(length(res@R2cum) > 1) res@R2 <- c(res@R2, diff(res@R2cum)) if (completeObs) { cObs <- Matrix if(method %in% listPcaMethods("nonlinear")) cObs[missing] <- fitted(res, Matrix, pre=TRUE, post=TRUE)[missing] else cObs[missing] <- fitted(res, post=TRUE)[missing] res@completeObs <- cObs } if(cv == "q2") res@cvstat <- Q2(res, Matrix, nruncv=1, ...) return(res) } ##' Wrapper function for imputation methods based on nearest neighbour ##' clustering. Currently llsImpute only. ##' ##' This method is wrapper function to llsImpute, See documentation ##' for \code{link{llsImpute}}. ##' @title Nearest neighbour imputation ##' @param object Numerical matrix with (or an object coercible to ##' such) with samples in rows and variables as columns. Also takes ##' \code{ExpressionSet} in which case the transposed expression ##' matrix is used. ##' @param method For convenience one can pass a large matrix but only ##' use the variable specified as subset. Can be colnames or indices. ##' @param subset Currently "llsImpute" only. ##' @param ... Further arguments to the chosen method. ##' @return A \code{clusterRes} object. Or a list containing a ##' clusterRes object as first and an ExpressionSet object as second ##' entry if the input was of type ExpressionSet. ##' @export ##' @seealso \code{\link{llsImpute}}, \code{\link{pca}} ##' @keywords multivariate ##' @examples ##' data(metaboliteData) ##' llsRes <- nni(metaboliteData, k=6, method="llsImpute", allGenes=TRUE) ##' @author Wolfram Stacklies nni <- function(object, method=c("llsImpute"), subset=numeric(), ...) { isExprSet <- FALSE if(inherits(object, "ExpressionSet")) { set <- object isExprSet <- TRUE object <- t(exprs(object)) } method <- match.arg(method) if ( !checkData(as.matrix(object), verbose=interactive()) ) stop("Invalid data format, exiting...\n", "Run checkData(data, verbose=TRUE) for details\n") missing <- sum(is.na(object)) if(length(subset) > 0) object <- object[,subset] res <- llsImpute(object, ...) return(res) } ##' A function that can be used to visualise many PCs plotted against ##' each other ##' ##' Uses \code{\link{pairs}} to provide side-by-side plots. Note that ##' this function only plots scores or loadings but not both in the ##' same plot. ##' @title Plot many side by side scores XOR loadings plots ##' @param object \code{pcaRes} a pcaRes object ##' @param pcs \code{numeric} which pcs to plot ##' @param type \code{character} Either "scores" or "loadings" for ##' scores or loadings plot respectively ##' @param sl \code{character} Text labels to plot instead of a point, ##' if NULL points are plotted instead of text ##' @param hotelling \code{numeric} Significance level for the ##' confidence ellipse. NULL means that no ellipse is drawn. ##' @param ... Further arguments to \code{\link{pairs}} on which this ##' function is based. ##' @return None, used for side effect. ##' @seealso \code{prcomp}, \code{pca}, \code{princomp}, \code{slplot} ##' @export ##' @examples ##' data(iris) ##' pcIr <- pca(iris[,1:4], nPcs=3, method="svd") ##' plotPcs(pcIr, col=as.integer(iris[,4]) + 1) ##' @keywords multivariate ##' @author Henning Redestig plotPcs <- function(object, pcs=1:nP(object), type=c("scores", "loadings"), sl=NULL, hotelling=0.95, ...) { type <- match.arg(type) panel <- function(x,y, ...) { abline(h=0, v=0, col="black") if(!is.null(hotelling)) { A <- length(pcs) el <- simpleEllipse(x, y, alfa=hotelling) lines(el) } if(is.null(sl)) points(x, y, ...) else text(x, y, labels=sl,...) } switch(type, scores={ labels <- paste("PC", pcs, "\n", "R^2 =", round(object@R2[pcs], 2)) pairs(scores(object)[,pcs], labels=labels, panel=panel, upper.panel=NULL,...) }, loadings={ if(method(object) == "nlpca") stop("Loadings plot not applicable for non-linear PCA") labels <- paste("PC", pcs, "\n", "R^2 =", round(object@R2[pcs], 2)) pairs(loadings(object)[,pcs], labels=labels, panel=panel, upper.panel=NULL, ...) }) } ##' A wrapper function for \code{prcomp} to deliver the result as a ##' \code{pcaRes} method. Supplied for compatibility with the rest ##' of the pcaMethods package. It is not recommended to use this ##' function directely but rather to use the \code{pca()} wrapper ##' function. ##' @title Perform principal component analysis using singular value ##' decomposition ##' @param Matrix Pre-processed (centered and possibly scaled) ##' numerical matrix samples in rows and variables as columns. No ##' missing values allowed. ##' @param nPcs Number of components that should be extracted. ##' @param varLimit Optionally the ratio of variance that should be ##' explained. \code{nPcs} is ignored if varLimit < 1 ##' @param verbose Verbose complaints to matrix structure ##' @param ... Only used for passing through arguments. ##' @return A \code{pcaRes} object. ##' @seealso \code{prcomp}, \code{princomp}, \code{pca} ##' @examples ##' data(metaboliteDataComplete) ##' mat <- prep(t(metaboliteDataComplete)) ##' pc <- svdPca(mat, nPcs=2) ##' ## better use pca() ##' pc <- pca(t(metaboliteDataComplete), method="svd", nPcs=2) ##' \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteDataComplete))^2, na.rm=TRUE) < 200)} ##' @export ##' @keywords multivariate ##' @author Henning Redestig svdPca <- function(Matrix, nPcs=2, varLimit=1, verbose=interactive(), ...) { pcs <- prcomp(Matrix, center=FALSE, scale.=FALSE) imp <- summary(pcs)$importance if(varLimit < 1) nPcs <- sum(imp[3,] < varLimit) + 1 res <- new("pcaRes") res@scores <- cbind(pcs$x[,1:nPcs]) res@loadings <- cbind(pcs$rotation[,1:nPcs]) res@R2cum <- imp[3,1:nPcs] res@varLimit <- varLimit res@method <- "svd" return(res) } ##' Get a confidence ellipse for uncorrelated bivariate data ##' ##' As described in 'Introduction to multi and megavariate data analysis ##' using PCA and ##' PLS' by Eriksson et al. This produces very similar ellipse as ##' compared to the ellipse function the ellipse package except that ##' this function assumes that and y are uncorrelated (which they of ##' are if they are scores or loadings from a PCA). ##' @title Hotelling's T^2 Ellipse ##' @param x first variable ##' @param y second variable ##' @param alfa confidence level of the circle ##' @param len Number of points in the circle ##' @seealso ellipse ##' @author Henning Redestig ##' @return A matrix with X and Y coordinates for the circle simpleEllipse <- function(x, y, alfa=0.95, len=200) { N <- length(x) A <- 2 mypi <- seq(0, 2 * pi, length=len) r1 <- sqrt(var(x) * qf(alfa, 2, N - 2) * (2*(N^2 - 1)/(N * (N - 2)))) r2 <- sqrt(var(y) * qf(alfa, 2, N - 2) * (2*(N^2 - 1)/(N * (N - 2)))) cbind(r1 * cos(mypi) + mean(x), r2 * sin(mypi) + mean(y)) } # .onLoad <- function(libname, pkgname) { # require("methods") # } pcaMethods/R/errorHierarchic.R0000644000175000017500000000440014136047224016133 0ustar nileshnilesh##' Later ##' @param nlnet The nlnet ##' @param trainIn training data ##' @param trainOut fitted data ##' @return error ##' @author Henning Redestig, Matthias Scholz errorHierarchic <- function(nlnet, trainIn, trainOut) { weights <- nlnet@weights$current() if(nlnet@inverse) { numElements <- nlnet@net[1] * dim(trainOut)[2] trainIn <- array(weights[1:numElements], dim=c(nlnet@net[1], dim(trainOut)[2])) wTrainIn <- weights[1:numElements, drop=FALSE] weights <- weights[(numElements + 1):length(weights),,drop=FALSE] } netDim <- dim(nlnet@net) trainDim <- dim(trainOut) weightMats <- vector2matrices(weights, nlnet@net) hierarchicIdx <- nlnet@hierarchic$idx[,nlnet@hierarchic$var != 0, drop=FALSE] hierarchicVar <- nlnet@hierarchic$var[,colSums(nlnet@hierarchic$var) != 0, drop=FALSE] subnetNum <- length(hierarchicVar) out <- array(0, dim=c(trainDim[1], trainDim[2], subnetNum)) sBias <- array(1, dim=c(1, trainDim[2])) sExtract <- eval(parse(text=paste(nlnet@fct[1], "(trainIn)"))) Eitemize <- NULL if(nlnet@hierarchic$layer > 1) { #this should not be executed at all if sequence is 1:0 for(layer in 1:(nlnet@hierarchic$layer - 1)) { sExtract <- rbind(sBias, sExtract) sExtract <- eval(parse(text=paste(nlnet@fct[layer + 1], "(weightMats[[layer]] %*% sExtract)"))) } } for(subnet in 1:subnetNum) { sRecon <- sExtract sRecon[hierarchicIdx[,subnet]==0,] <- 0 for(layer in nlnet@hierarchic$layer:(netDim[2] - 1)) { sRecon <- rbind(sBias, sRecon) sRecon <- eval(parse(text=paste(nlnet@fct[layer+1], "(weightMats[[layer]] %*% sRecon)"))) } out[,,subnet] <- sRecon ## error function eTmp <- (sRecon - trainOut)^2 eTmp[is.na(eTmp)] <- 0 Eitemize[subnet] <- sum(eTmp) * 0.5 if(!is.null(nlnet@dataDist)) Eitemize[subnet] <- 0.5 * sum(nlnet@dataDist * eTmp) else Eitemize[subnet] <- 0.5 * sum(eTmp) } error <- tcrossprod(hierarchicVar, rbind(Eitemize)) if(!is.null(nlnet@weightDecay)) error <- error + nlnet@weightDecay * 0.5 * sum(weights^2) ## smooth (0.01) weight decay also for input values if(nlnet@inverse) error <- error + 0.01 * nlnet@weightDecay * 0.5 * sum(wTrainIn^2) return(list(error=error, out=out)) } pcaMethods/R/bpca.R0000644000175000017500000001606314136047224013735 0ustar nileshnilesh##' Implements a Bayesian PCA missing value estimator. The script ##' is a port of the Matlab version provided by Shigeyuki OBA. See ##' also \url{http://ishiilab.jp/member/oba/tools/BPCAFill.html}. ##' BPCA combines an EM approach for PCA with a Bayesian model. In ##' standard PCA data far from the training set but close to the ##' principal subspace may have the same reconstruction error. BPCA ##' defines a likelihood function such that the likelihood for data ##' far from the training set is much lower, even if they are close to ##' the principal subspace. ##' ##' Scores and loadings obtained with Bayesian PCA slightly differ ##' from those obtained with conventional PCA. This is because BPCA ##' was developed especially for missing value estimation. The ##' algorithm does not force orthogonality between factor loadings, as ##' a result factor loadings are not necessarily orthogonal. However, ##' the BPCA authors found that including an orthogonality criterion ##' made the predictions worse. ##' ##' The authors also state that the difference between real and ##' predicted Eigenvalues becomes larger when the number of ##' observation is smaller, because it reflects the lack of ##' information to accurately determine true factor loadings from the ##' limited and noisy data. As a result, weights of factors to ##' predict missing values are not the same as with conventional PCA, ##' but the missing value estimation is improved. ##' ##' BPCA works iteratively, the complexity is growing with ##' \eqn{O(n^3)}{O(n^3)} because several matrix inversions are ##' required. The size of the matrices to invert depends on the ##' number of components used for re-estimation. ##' ##' Finding the optimal number of components for estimation is not a ##' trivial task; the best choice depends on the internal structure of ##' the data. A method called \code{kEstimate} is provided to ##' estimate the optimal number of components via cross validation. ##' In general few components are sufficient for reasonable estimation ##' accuracy. See also the package documentation for further ##' discussion about on what data PCA-based missing value estimation ##' makes sense. ##' ##' It is not recommended to use this function directely but rather to ##' use the pca() wrapper function. ##' ##' There is a difference with respect the interpretation of rows ##' (observations) and columns (variables) compared to matlab ##' implementation. For estimation of missing values for microarray ##' data, the suggestion in the original bpca is to intepret genes as ##' observations and the samples as variables. In pcaMethods however, ##' genes are interpreted as variables and samples as observations ##' which arguably also is the more natural interpretation. For bpca ##' behavior like in the matlab implementation, simply transpose your ##' input matrix. ##' ##' Details about the probabilistic model underlying BPCA are found in ##' Oba et. al 2003. The algorithm uses an expectation maximation ##' approach together with a Bayesian model to approximate the ##' principal axes (eigenvectors of the covariance matrix in PCA). ##' The estimation is done iteratively, the algorithm terminates if ##' either the maximum number of iterations was reached or if the ##' estimated increase in precision falls below \eqn{1e^{-4}}{1e^-4}. ##' ##' \bold{Complexity:} The relatively high complexity of the method is ##' a result of several matrix inversions required in each step. ##' Considering the case that the maximum number of iteration steps is ##' needed, the approximate complexity is given by the term ##' \deqn{maxSteps \cdot row_{miss} \cdot O(n^3)}{maxSteps * row_miss ##' * O(n^3)} Where \eqn{row_{miss}}{row_miss} is the number of rows ##' containing missing values and \eqn{O(n^3)}{O(n^3)} is the ##' complexity for inverting a matrix of size ##' \eqn{components}{components}. Components is the number of ##' components used for re-estimation. ##' @title Bayesian PCA missing value estimation ##' @param Matrix \code{matrix} -- Pre-processed matrix (centered, ##' scaled) with variables in columns and observations in rows. The ##' data may contain missing values, denoted as \code{NA}. ##' @param nPcs \code{numeric} -- Number of components used for ##' re-estimation. Choosing few components may decrease the ##' estimation precision. ##' @param maxSteps \code{numeric} -- Maximum number of estimation ##' steps. ##' @param verbose \code{boolean} -- BPCA prints the number of steps ##' and the increase in precision if set to TRUE. Default is ##' interactive(). ##' @param threshold convergence threshold ##' @param ... Reserved for future use. Currently no further ##' parameters are used ##' @return Standard PCA result object used by all PCA-based methods ##' of this package. Contains scores, loadings, data mean and ##' more. See \code{\link{pcaRes}} for details. ##' @references Shigeyuki Oba, Masa-aki Sato, Ichiro Takemasa, Morito ##' Monden, Ken-ichi Matsubara and Shin Ishii. A Bayesian missing ##' value estimation method for gene expression profile ##' data. \emph{Bioinformatics, 19(16):2088-2096, Nov 2003}. ##' @seealso \code{\link{ppca}}, \code{\link{svdImpute}}, ##' \code{\link{prcomp}}, \code{\link{nipalsPca}}, ##' \code{\link{pca}}, ##' \code{\link{pcaRes}}. \code{\link{kEstimate}}. ##' @note Requires \code{MASS}. ##' @examples ##' ## Load a sample metabolite dataset with 5\% missig values (metaboliteData)e ##' data(metaboliteData) ##' ## Perform Bayesian PCA with 2 components ##' pc <- pca(t(metaboliteData), method="bpca", nPcs=2) ##' ## Get the estimated principal axes (loadings) ##' loadings <- loadings(pc) ##' ## Get the estimated scores ##' scores <- scores(pc) ##' ## Get the estimated complete observations ##' cObs <- completeObs(pc) ##' ## Now make a scores and loadings plot ##' slplot(pc) ##' \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteData))^2, na.rm=TRUE) < 200)} ##' @keywords multivariate ##' @export ##' @author Wolfram Stacklies bpca <- function(Matrix, nPcs=2, maxSteps=100, verbose=interactive(), threshold=1e-4, ... ) { ## R implementation of a Bayesion PCA missing value estimator. ## After the Matlab script of Shigeyuki OBA (2002 May. 5th) ## See also: http://hawaii.aist-nara.ac.jp/%7Eshige-o/tools/ ## Great thanks to them! M <- BPCA_initmodel(Matrix, nPcs) tauold <- 1000 for( step in 1:maxSteps ) { M <- BPCA_dostep(M, Matrix) if( step %% 10 == 0 ) { tau <- M$tau dtau <- abs(log10(tau) - log10(tauold)) if ( verbose ) { cat("Step Number : ", step, '\n') cat("Increase in precision : ", dtau, '\n') cat("----------", '\n') } if (dtau < threshold) { break } tauold <- tau } } R2cum <- rep(NA, nPcs) TSS <- sum(Matrix^2, na.rm=TRUE) for (i in 1:nPcs) { difference <- Matrix - (M$scores[,1:i, drop=FALSE] %*% t(M$PA[,1:i, drop=FALSE]) ) R2cum[i] <- 1 - (sum(difference^2, na.rm=TRUE) / TSS) } result <- new("pcaRes") result@scores <- M$scores result@loadings <- M$PA result@R2cum <- R2cum result@method <- "bpca" return(result) } pcaMethods/R/llsImpute.R0000644000175000017500000002204114136047224014777 0ustar nileshnilesh##' Missing value estimation using local least squares (LLS). First, ##' k variables (for Microarrya data usually the genes) are selected ##' by pearson, spearman or kendall correlation coefficients. Then ##' missing values are imputed by a linear combination of the k ##' selected variables. The optimal combination is found by LLS ##' regression. The method was first described by Kim et al, ##' Bioinformatics, 21(2),2005. ##' ##' Missing values are denoted as \code{NA}\cr It is not recommended ##' to use this function directely but rather to use the nni() wrapper ##' function. The methods provides two ways for missing value ##' estimation, selected by the \code{allVariables} option. The first ##' one is to use only complete variables for the regression. This is ##' preferable when the number of incomplete variables is relatively ##' small. ##' ##' The second way is to consider all variables as candidates for the ##' regression. Hereby missing values are initially replaced by the ##' columns wise mean. The method then iterates, using the current ##' estimate as input for the regression until the change between new ##' and old estimate falls below a threshold (0.001). ##' ##' @title LLSimpute algorithm ##' @param Matrix \code{matrix} -- Data containing the variables ##' (genes) in columns and observations (samples) in rows. The data ##' may contain missing values, denoted as \code{NA}. ##' @param k \code{numeric} -- Cluster size, this is the number of ##' similar genes used for regression. ##' @param center \code{boolean} -- Mean center the data if TRUE ##' @param completeObs \code{boolean} -- Return the estimated complete ##' observations if TRUE. This is the input data with NA values ##' replaced by the estimated values. ##' @param correlation \code{character} -- How to calculate the ##' distance between genes. One out of pearson | kendall | spearman , ##' see also help("cor"). ##' @param allVariables \code{boolean} -- Use only complete genes to ##' do the regression if TRUE, all genes if FALSE. ##' @param maxSteps \code{numeric} -- Maximum number of iteration ##' steps if allGenes = TRUE. ##' @param xval \code{numeric} Use LLSimpute for cross ##' validation. xval is the index of the gene to estimate, all other ##' incomplete genes will be ignored if this parameter is set. We do ##' not consider them in the cross-validation. ##' @param verbose \code{boolean} -- Print step number and relative ##' change if TRUE and allVariables = TRUE ##' @param ... Reserved for parameters used in future version of the ##' algorithm ##' @note Each step the generalized inverse of a \code{miss} x k ##' matrix is calculated. Where \code{miss} is the number of missing ##' values in variable j and \code{k} the number of neighbours. This ##' may be slow for large values of k and / or many missing ##' values. See also help("ginv"). ##' @return \item{nniRes}{Standard nni (nearest neighbour ##' imputation) result object of this package. See ##' \code{\link{nniRes}} for details.} ##' @seealso \code{\link{pca}, \link{nniRes}, \link{nni}}. ##' @examples ##' ## Load a sample metabolite dataset (metaboliteData) with already 5\% of ##' ## data missing ##' data(metaboliteData) ##' ## Perform llsImpute using k = 10 ##' ## Set allVariables TRUE because there are very few complete variables ##' result <- llsImpute(metaboliteData, k = 10, correlation="pearson", allVariables=TRUE) ##' ## Get the estimated complete observations ##' cObs <- completeObs(result) ##' @keywords multivariate ##' @export ##' @references Kim, H. and Golub, G.H. and Park, H. - Missing value ##' estimation for DNA microarray gene expression data: local least ##' squares imputation. \emph{Bioinformatics, 2005; 21(2):187-198.} ##' ##' Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and ##' Hastie T. and Tibshirani R. and Botstein D. and Altman RB. - ##' Missing value estimation methods for DNA microarrays. ##' \emph{Bioinformatics. 2001 Jun;17(6):520-525.} ##' @author Wolfram Stacklies llsImpute <- function(Matrix, k=10, center=FALSE, completeObs=TRUE, correlation="pearson", allVariables=FALSE, maxSteps=100, xval=NULL, verbose=FALSE, ...) { threshold <- 0.001 correlation <- match.arg(correlation, c("pearson", "kendall", "spearman")) ## If the data is a data frame, convert it into a matrix Matrix <- as.matrix(Matrix, rownames.force=TRUE) ## And now check if everything is right... if ( !checkData(Matrix, verbose = interactive()) ) { stop("Invalid data format! Use checkData(Matrix, verbose = TRUE) for details.\n") } ## Exit if number of neighbours exceeds number of columns if (k > ncol(Matrix)) stop("Cluster size larger than the number of columns, choose a k < ncol(Matrix)!") ## Set allVariables TRUE if k exceeds number of complete genes ## Print warning messages in the first case and when less than 50% of all genes are complete ## and allVariables == FALSE cg <- sum( apply(is.na(Matrix), 2, sum) == 0) if ( (k > cg) && (!allVariables) ) { warning("Cluster size larger than number of complete genes, using allVariables = TRUE") allVariables <- TRUE } else if ( (cg < (ncol(Matrix) / 2)) && (!allVariables) ) { warning("Less than 50% of the genes are complete, consider using allVariables = TRUE") } else if (sum(is.na(Matrix)) == 0) stop("No missing values, no need for missing value imputation :))") ## Find all genes with missing values missing <- apply(is.na(Matrix), 2, sum) > 0 missIx <- which(missing == TRUE) # For cross validation we want to only estimate one variable, the others # are not considered in the cross validation anyway if (!is.null(xval)) missIx = xval obs <- Matrix ## working copy of the data Ye <- Matrix ## Estimated complete observations ## Center the data column wise if (center) { obs <- scale(Matrix, center = TRUE, scale = FALSE) Ye <- obs means <- attr(Ye, "scaled:center") } if (allVariables) { compIx <- 1:ncol(obs) ## Impute the row average rowMeans <- apply(obs, 1, mean, na.rm = TRUE) for (i in 1:nrow(obs)) { obs[i, is.na(Matrix[i,])] <- rowMeans[i] } ## distances between all genes, ignore the diagonal (correlation to itself) distance = abs(cor(obs, obs, method = correlation)) } else { compIx <- which(missing == FALSE) ## missing genes are the rows, complete genes the columns distance = abs(cor(obs[,missIx, drop=FALSE], obs[,compIx, drop=FALSE], use="pairwise.complete.obs", method = correlation)) } change <- Inf step <- 0 while ( (change > threshold) && (step < maxSteps) ) { step <- step + 1 iteration <- 0 ## Do the regression and imputation for (index in missIx) { iteration <- iteration + 1 if (allVariables) { similar <- sort(distance[iteration,], index.return = TRUE, decreasing = TRUE) simIx <- compIx[ similar$ix[similar$ix != iteration][1:k] ] } else { similar <- sort(distance[iteration,], index.return = TRUE, decreasing = TRUE) simIx <- compIx[ similar$ix[1:k] ] } ## ## Do a regression against the k most similar genes ## See Kim et. al 2005 for details ## target <- obs[, index, drop = FALSE] tMiss <- is.na(Matrix[, index, drop = FALSE]) Apart <- obs[!tMiss, simIx, drop = FALSE] Bpart <- obs[tMiss, simIx, drop = FALSE] targetComplete <- target[!tMiss, , drop = FALSE] X <- MASS::ginv(Apart) %*% targetComplete estimate <- Bpart %*% X ## Impute the estimate Ye[tMiss, index] <- estimate } ## We do not want to iterate if allVariables == FALSE if (!allVariables || !is.null(xval)) { break } else { ## relative change in estimation change <- sqrt(sum( (obs - Ye)^2 ) / sum(obs^2)) obs <- Ye if (verbose) { cat("Step number : ", step, '\n') cat("Relative change : ", change, '\n') cat("---------------", '\n') } } } ## Add the original mean if (center) { for(i in 1:ncol(Ye)) { Ye[,i] <- Ye[,i] + means[i] } } ## Build the nniRes object ## result <- new("nniRes") if(completeObs) { Ye[!is.na(Matrix)] <- Matrix[!is.na(Matrix)] result@completeObs <- Ye } result@centered <- center result@center <- attr(scale(Matrix, center = TRUE, scale = FALSE), "scaled:center") result@nObs <- nrow(Matrix) result@nVar <- ncol(Matrix) result@method <- "llsImpute" result@correlation <- correlation result@k <- k result@missing <- sum(is.na(Matrix)) return(result) } pcaMethods/R/svdImpute.R0000644000175000017500000001132714136047224015006 0ustar nileshnilesh##' This implements the SVDimpute algorithm as proposed by Troyanskaya ##' et al, 2001. The idea behind the algorithm is to estimate the ##' missing values as a linear combination of the \code{k} most ##' significant eigengenes. ##' ##' Missing values are denoted as \code{NA}. It is not recommended ##' to use this function directely but rather to use the pca() wrapper ##' function. ##' ##' As SVD can only be performed on complete matrices, all missing ##' values are initially replaced by 0 (what is in fact the mean on ##' centred data). The algorithm works iteratively until the change ##' in the estimated solution falls below a certain threshold. Each ##' step the eigengenes of the current estimate are calculated and ##' used to determine a new estimate. Eigengenes denote the loadings ##' if pca is performed considering variable (for Microarray data ##' genes) as observations. ##' ##' An optimal linear combination is found by regressing the ##' incomplete variable against the \code{k} most significant ##' eigengenes. If the value at position \code{j} is missing, the ##' \eqn{j^th}{j^th} value of the eigengenes is not used when ##' determining the regression coefficients. ##' @title SVDimpute algorithm ##' @param Matrix \code{matrix} -- Pre-processed (centered, scaled) ##' data with variables in columns and observations in rows. The data ##' may contain missing values, denoted as \code{NA}. ##' @param nPcs \code{numeric} -- Number of components to ##' estimate. The preciseness of the missing value estimation depends ##' on the number of components, which should resemble the internal ##' structure of the data. ##' @param threshold The iteration stops if the change in the matrix ##' falls below this threshold. ##' @param maxSteps Maximum number of iteration steps. ##' @param verbose Print some output if TRUE. ##' @param ... Reserved for parameters used in future version of the ##' algorithm ##' @note Each iteration, standard PCA (\code{prcomp}) needs to be ##' done for each incomplete variable to get the eigengenes. This is ##' usually fast for small data sets, but complexity may rise if the ##' data sets become very large. ##' @return Standard PCA result object used by all PCA-based methods ##' of this package. Contains scores, loadings, data mean and ##' more. See \code{\link{pcaRes}} for details. ##' @examples ##' ## Load a sample metabolite dataset with 5\% missing values ##' data(metaboliteData) ##' ## Perform svdImpute using the 3 largest components ##' result <- pca(metaboliteData, method="svdImpute", nPcs=3, center = TRUE) ##' ## Get the estimated complete observations ##' cObs <- completeObs(result) ##' ## Now plot the scores ##' plotPcs(result, type = "scores") ##' @keywords multivariate ##' @references Troyanskaya O. and Cantor M. and Sherlock G. and Brown ##' P. and Hastie T. and Tibshirani R. and Botstein D. and Altman ##' RB. - Missing value estimation methods for DNA ##' microarrays. \emph{Bioinformatics. 2001 Jun;17(6):520-5.} ##' @author Wolfram Stacklies ##' @export svdImpute <- function(Matrix, nPcs=2, threshold=0.01, maxSteps=100, verbose=interactive(), ...) { missing <- is.na(Matrix) temp <- apply(missing, 2, sum) missIx <- which(temp != 0) ## Initially set estimates to 0 Matrix[missing] <- 0 ## Now do the regression count <- 0 error <- Inf while ( (error > threshold) && (count < maxSteps) ) { res <- prcomp(t(Matrix), center = FALSE, scale = FALSE, retx = TRUE) loadings <- res$rotation[,1:nPcs, drop = FALSE] sDev <- res$sdev ## Estimate missing values as a linear combination of the eigenvectors ## The optimal solution is found by regression against the k eigengenes for (index in missIx) { target <- Matrix[!missing[,index],index, drop = FALSE] Apart <- loadings[!missing[,index], , drop = FALSE] Bpart <- loadings[missing[,index], , drop = FALSE] X <- MASS::ginv(Apart) %*% target estimate <- Bpart %*% X Matrix[missing[,index], index] <- estimate } count <- count + 1 if (count > 5) { error <- sqrt(sum( (MatrixOld - Matrix)^2 ) / sum(MatrixOld^2)) if (verbose) { cat("change in estimate: ", error, "\n") } } MatrixOld <- Matrix } tmp <- prcomp(Matrix, center = FALSE, scale = FALSE, retx = TRUE) loadings <- cbind(tmp$rotation[,1:nPcs]) scores <- cbind(tmp$x[,1:nPcs]) ## Calculate R2cum R2cum <- rep(NA, nPcs) TSS <- sum(Matrix^2, na.rm=TRUE) for (i in 1:nPcs) { difference <- Matrix - (scores[,1:i, drop=FALSE] %*% t(loadings[,1:i, drop=FALSE])) R2cum[i] <- 1 - (sum(difference^2) / TSS) } result <- new("pcaRes") result@scores <- scores result@loadings <- loadings result@R2cum <- R2cum result@method <- "svdImpute" return(result) } pcaMethods/R/BPCA_initmodel.R0000644000175000017500000000510314136047224015572 0ustar nileshnilesh##' Model initialization for Bayesian PCA. This function is NOT ##' inteded to be run separately! ##' ##' The function calculates the initial Eigenvectors by use of SVD ##' from the complete rows. The data structure M is created and ##' initial values are assigned. ##' @title Initialize BPCA model ##' @param y numeric matrix containing missing values. Missing values ##' are denoted as 'NA' ##' @param components Number of components used for estimation ##' @return List containing ##' \item{rows}{Row number of input matrix} ##' \item{cols}{Column number of input matrix} ##' \item{comps}{Number of components to use} ##' \item{yest}{(working variable) current estimate of complete data} ##' \item{row_miss}{(Array) Indizes of rows containing missing values} ##' \item{row_nomiss}{(Array) Indices of complete rows (such with no ##' missing values)} ##' \item{nans}{Matrix of same size as input data. TRUE if \code{input == NA}, ##' false otherwise} ##' \item{mean}{Column wise data mean} ##' \item{PA}{ (d x k) Estimated principal axes (eigenvectors, ##' loadings) The matrix ROWS are the vectors} ##' \item{tau}{Estimated precision of the residual error} ##' \item{scores}{ Estimated scores} ##' Further elements are: galpha0, balpha0, alpha, gmu0, btau0, gtau0, ##' SigW. These are working variables or constants. ##' @author Wolfram Stacklies BPCA_initmodel <- function(y, components) { ## Initialization, write static parameters to the central M <- NULL M$rows <- nrow(y) M$cols <- ncol(y) M$comps <- components ## Column number M$yest <- y ## Original data, NAs are set to 0 later on ## Find rows with missing values, etc... M$nans <- is.na(y) temp <- apply(M$nans, 1, sum) M$row_nomiss <- which(temp == 0) M$row_miss <- which(temp != 0) M$yest[M$nans] <- 0 M$scores <- NULL ## Get the SVD of the complete rows covy <- cov(M$yest) values <- svd(covy, components, components) U <- values[[2]] S <- diag( values[[1]][1:components], nrow = components, ncol = components) V <- values[[3]] ## M$mean: column wise mean of the original data M$mean <- matrix(0, 1, M$cols) for(j in 1:M$cols) { idx <- which(!is.na(y[,j])) M$mean[j] <- mean(y[idx,j]) } M$PA <- U %*% sqrt(S) M$tau <- 1 / ( sum(diag(covy)) - sum(diag(S)) ) ## Constants etc taumax <- 1e10 taumin <- 1e-10 M$tau <- max( min(M$tau, taumax), taumin ) M$galpha0 <- 1e-10 M$balpha0 <- 1 M$alpha <- (2 * M$galpha0 + M$cols) / (M$tau * diag(t(M$PA) %*% M$PA) + 2 * M$galpha0 / M$balpha0) M$gmu0 <- 0.001 M$btau0 <- 1 M$gtau0 <- 1e-10 M$SigW <- diag(components) return(M) } pcaMethods/R/orth.R0000644000175000017500000000354014136047224014000 0ustar nileshnilesh##' ONB = orth(mat) is an orthonormal basis for the range of matrix ##' mat. That is, ONB' * ONB = I, the columns of ONB span the same ##' space as the columns of mat, and the number of columns of ONB is ##' the rank of mat. ##' @title Calculate an orthonormal basis ##' @param mat matrix to calculate orthonormal base ##' @param skipInac do not include components with precision below ##' .Machine$double.eps if TRUE ##' @return orthonormal basis for the range of matrix ##' @author Wolfram Stacklies orth <- function(mat, skipInac = FALSE) { if(nrow(mat) > ncol(mat)) { leftSVs <- ncol(mat) } else { leftSVs <- nrow(mat) } result <- svd(mat, nu = leftSVs, nv = ncol(mat)) U <- result[[2]] S <- result[[1]] V <- result[[3]] m <- nrow(mat) n <- ncol(mat) if(m > 1) { s <- diag(S, nrow = length(S)) } else if(m == 1) { s <- S[1] } else { s <- 0 } tol <- max(m,n) * max(s) * .Machine$double.eps r <- sum(s > tol) if ( r < ncol(U) ) { if (skipInac) { warning("Precision for components ", r + 1 , " - ", ncol(U), " is below .Machine$double.eps. \n", "Results for those components are likely to be inaccurate!!\n", "These component(s) are not included in the returned solution!!\n") } else { warning("Precision for components ", r + 1 , " - ", ncol(U), " is below .Machine$double.eps. \n", "Results for those components are likely to be inaccurate!!\n") } } if (skipInac) { ONB <- U[, 1:r, drop=FALSE] ## Assing correct row and colnames rownames(ONB) <- labels(mat[, 1:r, drop=FALSE])[[1]]; colnames(ONB) <- labels(mat[, 1:r, drop=FALSE])[[2]]; } else { ONB<-U ## Assing correct row and colnames rownames(ONB) <- labels(mat)[[1]]; colnames(ONB) <- labels(mat)[[2]]; } return(ONB) } pcaMethods/R/vector2matrices.R0000644000175000017500000000252314136047224016140 0ustar nileshnilesh##' Tranform the vectors of weights to matrix structure ##' @param object an nlpcaNet ##' @return weights in matrix structure ##' @author Henning Redestig ##' @aliases vector2matrices,nlpcaNet-method setMethod("vector2matrices", "nlpcaNet", function(object) { netDim <- dim(object@net) posBegin <- 1 posEnd <- 0 result <- list() for(i in 1:(netDim[2] - 1)) { wSize <- c(object@net[i + 1], object@net[i] + 1) posEnd <- posEnd + prod(wSize) result[[i]] <- matrix(object@weights$current()[posBegin:posEnd], wSize[1], wSize[2]) posBegin <- posEnd + 1 } if(posEnd < length(object@weights$current())) stop("weight vector has too many elements\n") result }) ##' Tranform the vectors of weights to matrix structure ##' @param object an nlpcaNet ##' @param net the neural network ##' @return weights in matrix structure ##' @author Henning Redestig ##' @aliases vector2matrices,matrix-method setMethod("vector2matrices", "matrix", function(object, net) { netDim <- dim(net) posBegin <- 1 posEnd <- 0 result <- list() for(i in 1:(netDim[2] - 1)) { wSize <- c(net[i + 1], net[i] + 1) posEnd <- posEnd + prod(wSize) result[[i]] <- matrix(object[posBegin:posEnd], wSize[1], wSize[2]) posBegin <- posEnd + 1 } if(posEnd < length(object)) stop("weight vector has too many elements\n") result }) pcaMethods/R/repmat.R0000644000175000017500000000166714136047224014324 0ustar nileshnilesh##' Creates a large matrix B consisting of an M-by-N tiling of copies ##' of A ##' @title Replicate and tile an array. ##' @param mat numeric matrix ##' @param M number of copies in vertical direction ##' @param N number of copies in horizontal direction ##' @return Matrix consiting of M-by-N tiling copies of input matrix ##' @author Wolfram Stacklies repmat <- function(mat, M, N) { ## Check if all input parameters are correct if( !all(M > 0, N > 0) ) { stop("M and N must be > 0") } ## Convert array to matrix ma <- mat if(!is.matrix(mat)) { ma <- matrix(mat, nrow=1) } rows <- nrow(ma) cols <- ncol(ma) replicate <- matrix(0, rows * M, cols * N) for (i in 1:M) { for(j in 1:N) { start_row <- (i - 1) * rows + 1 end_row <- i * rows start_col <- (j - 1) * cols + 1 end_col <- j * cols replicate[start_row:end_row, start_col:end_col] <- ma } } return(replicate) } pcaMethods/R/prep.R0000644000175000017500000000732214136047224013774 0ustar nileshnilesh##' Scaling and centering a matrix. ##' ##' Does basically the same as \code{\link{scale}} but adds some ##' alternative scaling options and functionality for treating ##' pre-processing as part of a model. ##' @title Pre-process a matrix for PCA ##' @param object Numerical matrix (or an object coercible to such) ##' with samples in rows and variables as columns. Also takes ##' \code{ExpressionSet} in which case the transposed expression ##' matrix is used. ##' @param scale One of "UV" (unit variance \eqn{a=a/\sigma_{a}}) ##' "vector" (vector normalisation \eqn{b=b/||b||}), "pareto" (sqrt ##' UV) or "none" to indicate which scaling should be used to scale ##' the matrix with \eqn{a} variables and \eqn{b} samples. Can also be ##' a vector of scales which should be used to scale the ##' matrix. \code{NULL} value is interpreted as \code{"none"}. ##' @param center Either a logical which indicates if the matrix ##' should be mean centred or not, or a vector with averages which ##' should be suntracted from the matrix. \code{NULL} value is ##' interpreted as \code{FALSE} ##' @param eps Minimum variance, variable with lower variance are not ##' scaled and warning is issued instead. ##' @param simple Logical indicating if only the data should be ##' returned or a list with the pre-processing statistics as well. ##' @param reverse Logical indicating if matrix should be ##' 'post-processed' instead by multiplying each column with its scale ##' and adding the center. In this case, center and scale should be ##' vectors with the statistics (no warning is issued if not, instead ##' output becomes the same as input). ##' @param ... Only used for passing through arguments. ##' @return A pre-processed matrix or a list with ##' \item{center}{a vector with the estimated centers} ##' \item{scale}{a vector with the estimated scales} ##' \item{data}{the pre (or post) processed data} ##' @examples ##' object <- matrix(rnorm(50), nrow=10) ##' res <- prep(object, scale="uv", center=TRUE, simple=FALSE) ##' obj <- prep(object, scale=res$scale, center=res$center) ##' ## same as original ##' sum((object - prep(obj, scale=res$scale, center=res$center, rev=TRUE))^2) ##' @export ##' @author Henning Redestig prep <- function(object, scale=c("none", "pareto", "vector", "uv"), center=TRUE, eps=1e-12, simple=TRUE, reverse=FALSE, ...) { if(inherits(object, "ExpressionSet")) obj <- t(exprs(object)) else obj <- as.matrix(object) if(is.null(center)) center <- FALSE if(is.null(scale)) scale <- "none" if(is.logical(center[1])) { if(center[1]) center <- colMeans(obj, na.rm=TRUE) else center <- rep(0, ncol(obj)) } if(length(center) != ncol(obj)) stop("center do not match matrix dimensions") if(!reverse) obj <- sweep(obj, 2, center, "-") if(is.character(scale[1])) { scale <- match.arg(scale) if(scale == "uv") scale <- apply(obj, 2, sd, na.rm=TRUE) else if(scale == "none") scale <- rep(1, ncol(obj)) else if(scale == "pareto") scale <- sqrt(apply(obj, 2, sd, na.rm=TRUE)) else if(scale == "vector") scale <- apply(obj, 2, function(x) sqrt(sum(x^2, na.rm=TRUE))) } if(length(scale) != ncol(obj)) stop("scale vector do not match matrix dimensions") if (any(scale < eps)) warning(paste("Variance is below eps for", sum(scale < eps), "variables. Not scaling them.")) scale[scale < eps] <- 1 if(!reverse) obj <- sweep(obj, 2, scale, "/") if(reverse) { obj <- sweep(obj, 2, scale, "*") obj <- sweep(obj, 2, center, "+") } if(inherits(object, "ExpressionSet")) exprs(object) <- t(obj) else object <- obj if (simple) object else list(data=object, center=center, scale=scale) } pcaMethods/R/ppca.R0000644000175000017500000001463414136047224013755 0ustar nileshnilesh##' Implementation of probabilistic PCA (PPCA). PPCA allows to perform ##' PCA on incomplete data and may be used for missing value ##' estimation. This script was implemented after the Matlab version ##' provided by Jakob Verbeek ( see ##' \url{http://lear.inrialpes.fr/~verbeek/}) and the draft \emph{``EM ##' Algorithms for PCA and Sensible PCA''} written by Sam Roweis. ##' ##' Probabilistic PCA combines an EM approach for PCA with a ##' probabilistic model. The EM approach is based on the assumption ##' that the latent variables as well as the noise are normal ##' distributed. ##' ##' In standard PCA data which is far from the training set but close ##' to the principal subspace may have the same reconstruction error. ##' PPCA defines a likelihood function such that the likelihood for ##' data far from the training set is much lower, even if they are ##' close to the principal subspace. This allows to improve the ##' estimation accuracy. ##' ##' A method called \code{kEstimate} is provided to estimate the ##' optimal number of components via cross validation. In general few ##' components are sufficient for reasonable estimation accuracy. See ##' also the package documentation for further discussion on what kind ##' of data PCA-based missing value estimation is advisable. ##' ##' \bold{Complexity:}\cr Runtime is linear in the number of data, ##' number of data dimensions and number of principal components. ##' ##' \bold{Convergence:} The threshold indicating convergence was ##' changed from 1e-3 in 1.2.x to 1e-5 in the current version leading ##' to more stable results. For reproducability you can set the seed ##' (parameter seed) of the random number generator. If used for ##' missing value estimation, results may be checked by simply running ##' the algorithm several times with changing seed, if the estimated ##' values show little variance the algorithm converged well. ##' @title Probabilistic PCA ##' @param Matrix \code{matrix} -- Data containing the variables in ##' columns and observations in rows. The data may contain missing ##' values, denoted as \code{NA}. ##' @param nPcs \code{numeric} -- Number of components to ##' estimate. The preciseness of the missing value estimation depends ##' on the number of components, which should resemble the internal ##' structure of the data. ##' @param seed \code{numeric} Set the seed for the random number ##' generator. PPCA creates fills the initial loading matrix with ##' random numbers chosen from a normal distribution. Thus results may ##' vary slightly. Set the seed for exact reproduction of your ##' results. ##' @param threshold Convergence threshold. ##' @param maxIterations the maximum number of allowed iterations ##' @param ... Reserved for future use. Currently no further ##' parameters are used. ##' @note Requires \code{MASS}. It is not recommended to use this ##' function directely but rather to use the pca() wrapper function. ##' @return Standard PCA result object used by all PCA-based methods ##' of this package. Contains scores, loadings, data mean and ##' more. See \code{\link{pcaRes}} for details. ##' @seealso \code{\link{bpca}, \link{svdImpute}, \link{prcomp}, ##' \link{nipalsPca}, \link{pca}, \link{pcaRes}}. ##' @examples ##' ## Load a sample metabolite dataset with 5\% missing values (metaboliteData) ##' data(metaboliteData) ##' ## Perform probabilistic PCA using the 3 largest components ##' result <- pca(t(metaboliteData), method="ppca", nPcs=3, seed=123) ##' ## Get the estimated complete observations ##' cObs <- completeObs(result) ##' ## Plot the scores ##' plotPcs(result, type = "scores") ##' \dontshow{ ##' stopifnot(sum((fitted(result) - t(metaboliteData))^2, na.rm=TRUE) < 200) ##' } ##' @keywords multivariate ##' @author Wolfram Stacklies ##' @export ppca <- function(Matrix, nPcs=2, seed=NA, threshold=1e-5, maxIterations=1000, ...) { ## Set the seed to the user defined value. This affects the generation ## of random values for the initial setup of the loading matrix if (!is.na(seed)) set.seed(seed) N <- nrow(Matrix) D <- ncol(Matrix) Obs <- !is.na(Matrix) hidden <- which(is.na(Matrix)) missing <- length(hidden) if(missing) { Matrix[hidden] <- 0 } ## ------- Initialization r <- sample(N) C <- t(Matrix[r[1:nPcs], ,drop = FALSE]) ## Random matrix with the same dimnames as Matrix C <- matrix(rnorm(C), nrow(C), ncol(C), dimnames = labels(C) ) CtC <- t(C) %*% C ## inv(C'C) C' X is the solution to the EM problem X <- Matrix %*% C %*% solve(CtC) recon <- X %*% t(C) recon[hidden] <- 0 ss <- sum(sum((recon - Matrix)^2)) / (N * D - missing) count <- 1 old <- Inf ## ------ EM iterations while (count > 0) { ## E-step, (co)variances Sx <- solve(diag(nPcs) + CtC/ss) ss_old <- ss if(missing) { proj <- X %*% t(C) Matrix[hidden] <- proj[hidden] } ## E step: expected values X <- Matrix %*% C %*% Sx / ss ## M-step SumXtX <- t(X) %*% X ## Replace the right matrix division from matlab C <- (t(Matrix) %*% X) %*% solve( (SumXtX + N * Sx) ) CtC <- t(C) %*% C ss <- ( sum(sum( (C %*% t(X) - t(Matrix))^2 )) + N * sum(sum(CtC %*% Sx)) + missing * ss_old ) / (N * D) objective <- N * (D * log(ss) + sum(diag(Sx)) - log(det(Sx)) ) + sum(diag(SumXtX)) - missing * log(ss_old) rel_ch <- abs( 1 - objective / old ) old <- objective count <- count + 1 if( rel_ch < threshold & count > 5 ) { count <- 0 } else if (count > maxIterations) { count <- 0 warning("stopped after max iterations, but rel_ch was > threshold") } } ## End EM iteration C <- orth(C) evs <- eigen( cov(Matrix %*% C) ) vals <- evs[[1]] vecs <- evs[[2]] C <- C %*% vecs X <- Matrix %*% C ## Paramters in original Matlab implementation were: ## C (D by d) - C has the approximate loadings (eigenvectors of ## the covariance matrix) ## as columns. ## X - The approximate scores ## Matrix (N by D) - Expected complete observations. ## M (D by 1) - Column wise data mean ## ss (scalar) - isotropic variance outside subspace R2cum <- rep(NA, nPcs) TSS <- sum(Matrix^2, na.rm=TRUE) for (i in 1:ncol(C)) { difference <- Matrix - (X[,1:i, drop=FALSE] %*% t(C[,1:i, drop=FALSE])) R2cum[i] <- 1 - (sum(difference^2, na.rm=TRUE) / TSS) } res <- new("pcaRes") res@scores <- X res@loadings <- C res@R2cum <- R2cum res@method <- "ppca" return(res) } pcaMethods/R/kEstimate.R0000644000175000017500000003072014136047224014752 0ustar nileshnilesh##' Perform cross validation to estimate the optimal number of ##' components for missing value estimation. Cross validation is ##' done for the complete subset of a variable. ##' ##' The assumption hereby is that variables that are highly correlated ##' in a distinct region (here the non-missing observations) are also ##' correlated in another (here the missing observations). This also ##' implies that the complete subset must be large enough to be ##' representative. For each incomplete variable, the available ##' values are divided into a user defined number of cv-segments. The ##' segments have equal size, but are chosen from a random equal ##' distribution. The non-missing values of the variable are covered ##' completely. PPCA, BPCA, SVDimpute, Nipals PCA, llsImpute an NLPCA ##' may be used for imputation. ##' ##' The whole cross validation is repeated several times so, depending ##' on the parameters, the calculations can take very long time. As ##' error measure the NRMSEP (see Feten et. al, 2005) or the Q2 ##' distance is used. The NRMSEP basically normalises the RMSD ##' between original data and estimate by the variable-wise ##' variance. The reason for this is that a higher variance will ##' generally lead to a higher estimation error. If the number of ##' samples is small, the variable - wise variance may become an ##' unstable criterion and the Q2 distance should be used ##' instead. Also if variance normalisation was applied previously. ##' ##' The method proceeds variable - wise, the NRMSEP / Q2 distance is ##' calculated for each incomplete variable and averaged ##' afterwards. This allows to easily see for wich set of variables ##' missing value imputation makes senes and for wich set no ##' imputation or something like mean-imputation should be used. Use ##' \code{kEstimateFast} or \code{Q2} if you are not interested in ##' variable wise CV performance estimates. ##' ##' Run time may be very high on large data sets. Especially when used ##' with complex methods like BPCA or Nipals PCA. For PPCA, BPCA, ##' Nipals PCA and NLPCA the estimation method is called ##' \eqn{(v_{miss} \cdot segs \cdot nruncv \cdot)}{(v\_miss * segs * ##' nruncv)} times as the error for all numbers of principal ##' components can be calculated at once. For LLSimpute and SVDimpute ##' this is not possible, and the method is called \eqn{(v_{miss} ##' \cdot segs \cdot nruncv \cdot length(evalPcs))}{(v\_miss * segs * ##' nruncv * length(evalPcs))} times. This should still be fast for ##' LLSimpute because the method allows to choose to only do the ##' estimation for one particular variable. This saves a lot of ##' iterations. Here, \eqn{v_{miss}}{v\_miss} is the number of ##' variables showing missing values. ##' ##' As cross validation is done variable-wise, in this function Q2 is ##' defined on single variables, not on the entire data set. This is ##' Q2 is calculated as as \eqn{\frac{\sum(x - ##' xe)^2}{\sum(x^2)}}{sum(x - xe)^2 \ sum(x^2)}, where x is the ##' currently used variable and xe it's estimate. The values are then ##' averaged over all variables. The NRMSEP is already defined ##' variable-wise. For a single variable it is then ##' \eqn{\sqrt(\frac{\sum(x - xe)^2}{(n \cdot var(x))})}{sqrt(sum(x - ##' xe)^2 \ (n * var(x)))}, where x is the variable and xe it's ##' estimate, n is the length of x. The variable wise estimation ##' errors are returned in parameter variableWiseError. ##' @title Estimate best number of Components for missing value ##' estimation ##' @param Matrix \code{matrix} -- numeric matrix containing ##' observations in rows and variables in columns ##' @param method \code{character} -- of the methods found with ##' pcaMethods() The option llsImputeAll calls llsImpute with the ##' allVariables = TRUE parameter. ##' @param evalPcs \code{numeric} -- The principal components to use ##' for cross validation or the number of neighbour variables if used ##' with llsImpute. Should be an array containing integer values, ##' eg. \code{evalPcs = 1:10} or \code{evalPcs = c(2,5,8)}. The NRMSEP ##' or Q2 is calculated for each component. ##' @param segs \code{numeric} -- number of segments for cross validation ##' @param nruncv \code{numeric} -- Times the whole cross validation ##' is repeated ##' @param em \code{character} -- The error measure. This can be nrmsep or q2 ##' @param allVariables \code{boolean} -- If TRUE, the NRMSEP is ##' calculated for all variables, If FALSE, only the incomplete ones ##' are included. You maybe want to do this to compare several methods ##' on a complete data set. ##' @param verbose \code{boolean} -- If TRUE, some output like the ##' variable indexes are printed to the console each iteration. ##' @param ... Further arguments to \code{pca} or \code{nni} ##' @return A list with: ##' \item{bestNPcs}{number of PCs or k for which the minimal average ##' NRMSEP or the maximal Q2 was obtained.} ##' \item{eError}{an array of of size length(evalPcs). Contains the ##' average error of the cross validation runs for each number of ##' components.} ##' \item{variableWiseError}{Matrix of size ##' \code{incomplete_variables} x length(evalPcs). Contains the ##' NRMSEP or Q2 distance for each variable and each number of PCs. ##' This allows to easily see for wich variables imputation makes ##' sense and for which one it should not be done or mean imputation ##' should be used.} ##' \item{evalPcs}{The evaluated numbers of components or number of ##' neighbours (the same as the evalPcs input parameter).} ##' \item{variableIx}{Index of the incomplete variables. This can be ##' used to map the variable wise error to the original data.} ##' @seealso \code{\link{kEstimateFast}, \link{Q2}, \link{pca}, \link{nni}}. ##' @examples ##' ## Load a sample metabolite dataset with 5\% missing values (metaboliteData) ##' data(metaboliteData) ##' # Do cross validation with ppca for component 2:4 ##' esti <- kEstimate(metaboliteData, method = "ppca", evalPcs = 2:4, nruncv=1, em="nrmsep") ##' # Plot the average NRMSEP ##' barplot(drop(esti$eError), xlab = "Components",ylab = "NRMSEP (1 iterations)") ##' # The best result was obtained for this number of PCs: ##' print(esti$bestNPcs) ##' # Now have a look at the variable wise estimation error ##' barplot(drop(esti$variableWiseError[, which(esti$evalPcs == esti$bestNPcs)]), ##' xlab = "Incomplete variable Index", ylab = "NRMSEP") ##' @keywords multivariate ##' @export ##' @author Wolfram Stacklies kEstimate <- function(Matrix, method="ppca", evalPcs=1:3, segs=3, nruncv=5, em="q2", allVariables=FALSE, verbose=interactive(), ...) { fastKE <- FALSE if (method == "ppca" | method == "bpca" | method == "nipals" | method == "nlpca") fastKE <- TRUE method <- match.arg(method, listPcaMethods()) em <- match.arg(em, c("nrmsep", "q2")) maxPcs <- max(evalPcs) lengthPcs <- length(evalPcs) ## If the data is a data frame, convert it into a matrix Matrix <- as.matrix(Matrix, rownames.force=TRUE) if(maxPcs > (ncol(Matrix) - 1)) stop("maxPcs exceeds matrix size, choose a lower value!") ## And now check if everything is right... if( !checkData(Matrix, verbose=interactive()) ) stop("Invalid data format! Use checkData(Matrix, verbose = TRUE) for details.\n") if( (sum(is.na(Matrix)) == 0) && (allVariables == FALSE) ) stop("No missing values. Maybe you want to set allVariables = TRUE. Exiting\n") missing <- apply(is.na(Matrix), 2, sum) > 0 missIx <- which(missing == TRUE) if (allVariables) missIx <- 1:ncol(Matrix) complete <- !missing compIx <- which(complete == TRUE) error <- matrix(0, length(missIx), length(evalPcs)) iteration <- 0 for(nPcs in evalPcs) { ## If the estimated observations are just scores %*% t(loadings) ## we can calculate all we need at once, this saves many ## iterations... if (fastKE) nPcs = maxPcs iteration = iteration + 1 if (verbose && !fastKE) { cat("Doing CV for ", nPcs, " component(s) \n") } else if (verbose && fastKE) {cat("Doing CV ... \n")} for(cviter in 1:nruncv) { pos <- 0 if (verbose) cat("Incomplete variable index: ") for (index in missIx) { pos <- pos + 1 cat(pos, ":", sep="") target <- Matrix[, index, drop = FALSE] compObs <- !is.na(target) missObs <- is.na(target) nObs <- sum(compObs) ## Remove all observations that are missing in the target genes, ## as additional missing values may tamper the results set <- Matrix[compObs,] if (nObs >= (2 * segs)) { segments <- segs } else segments <- ceiling(nObs / 2) ## We assume uniformly distributed missing values when ## choosing the segments tt <- gl(segments, ceiling(nObs / segments))[1:nObs] cvsegs <- split(sample(nObs), tt) set <- Matrix[compObs,] if (fastKE) { nrmsep <- array(0, length(evalPcs)) q2 <- array(0, length(evalPcs)) } else { nrmsep <- 0; q2 <- 0 } for (i in 1:length(cvsegs)) { n <- length(cvsegs[[i]]) # n is the number of created # missing values ## Impute values using the given regression method testSet <- set testSet[cvsegs[[i]], index] <- NA if (method == "llsImpute") { estimate <- llsImpute(testSet, k = nPcs, verbose = FALSE, allVariables = FALSE, center = FALSE, xval = index) } else if (method == "llsImputeAll") { estimate <- llsImpute(testSet, k = nPcs, verbose = FALSE, allVariables = TRUE, center = FALSE, xval = index) } else { estimate <- pca(testSet, nPcs = nPcs, verbose = FALSE, method = method, center = TRUE,...) } if (fastKE) { for (np in evalPcs) { estiFitted <- fitted(estimate, data = NULL, nPcs = np) estimateVec <- estiFitted[, index] original <- target[compObs, ] estimateVec[-cvsegs[[i]]] <- testSet[-cvsegs[[i]], index] ## Error of prediction, error is calculated for removed ## elements only nIx <- which(evalPcs == np) if (em == "nrmsep") { nrmsep[nIx] <- nrmsep[nIx] + sum( (original - estimateVec)^2) } else { q2[nIx] <- q2[nIx] + sum( (original - estimateVec)^2 ) } } } else { estimate <- estimate@completeObs[, index] original <- target[compObs, ] ## Error of prediction, error is calculated for removed ## elements only if (em == "nrmsep") { nrmsep <- nrmsep + sum( (original - estimate)^2) } else { q2 <- q2 + sum( (original - estimate)^2 ) } } } ## iteration over cv segments if (fastKE) { if (em == "nrmsep") { error[pos, ] <- error[pos, ] + nrmsep / (nrow(set) * var(set[,index])) } else error[pos, ] <- error[pos, ] + (1 - (q2 / sum(set[, index]^2))) } else { if (em == "nrmsep") { error[pos, iteration] <- error[pos, iteration] + nrmsep / (nrow(set) * var(set[,index])) } else error[pos, iteration] <- error[pos, iteration] + (1 - (q2 / sum(set[, index]^2))) } } # iteration over variables if (verbose) cat("\n") } #iteration over nruncv ## The error is the sum over the independent cross validation runs error <- error / nruncv if (verbose && !fastKE) cat("The average", em, "for k =", iteration, "is", sum(error[,iteration]) / nrow(error), "\n") ## if nlpca, ppca, bpca, nipals we do not need to iterate over the ## number of components... if (fastKE) break } # iteration over number components if (em == "nrmsep") avgError <- sqrt(apply(error, 2, sum) / nrow(error)) else avgError <- apply(error, 2, sum) / nrow(error) ret <- list() if (em == "nrmsep") ret$bestNPcs <- evalPcs[which(avgError == min(avgError))] else ret$bestNPcs <- evalPcs[which(avgError == max(avgError))] ret$eError <- avgError if(em == "nrmsep") ret$variableWiseError <- sqrt(error) else ret$variableWiseError <- error ret$evalPcs <- evalPcs ret$variableIx <- missIx return(ret) } pcaMethods/R/nipalsPca.R0000644000175000017500000001513614136047224014742 0ustar nileshnilesh##' PCA by non-linear iterative partial least squares ##' ##' Can be used for computing PCA on a numeric matrix using either the ##' NIPALS algorithm which is an iterative approach for estimating the ##' principal components extracting them one at a time. NIPALS can ##' handle a small amount of missing values. It is not recommended to ##' use this function directely but rather to use the pca() wrapper ##' function. There is a C++ implementation given as \code{nipalsPca} ##' which is faster. ##' @title NIPALS PCA implemented in R ##' @param Matrix Pre-processed (centered, scaled) numerical matrix ##' samples in rows and variables as columns. ##' @param nPcs Number of components that should be extracted. ##' @param varLimit Optionally the ratio of variance that should be ##' explained. \code{nPcs} is ignored if varLimit < 1 ##' @param maxSteps Defines how many iterations can be done before ##' algorithm should abort (happens almost exclusively when there were ##' some wrong in the input data). ##' @param threshold The limit condition for judging if the algorithm ##' has converged or not, specifically if a new iteration is done if ##' \eqn{(T_{old} - T)^T(T_{old} - T) > \code{limit}}. ##' @param verbose Show simple progress information. ##' @param ... Only used for passing through arguments. ##' @return A \code{pcaRes} object. ##' @references Wold, H. (1966) Estimation of principal components and ##' related models by iterative least squares. In Multivariate ##' Analysis (Ed., P.R. Krishnaiah), Academic Press, NY, 391-420. ##' @author Henning Redestig ##' @seealso \code{prcomp}, \code{princomp}, \code{pca} ##' @examples ##' data(metaboliteData) ##' mat <- prep(t(metaboliteData)) ##' ## c++ version is faster ##' system.time(pc <- RnipalsPca(mat, method="rnipals", nPcs=2)) ##' system.time(pc <- nipalsPca(mat, nPcs=2)) ##' ## better use pca() ##' pc <- pca(t(metaboliteData), method="rnipals", nPcs=2) ##' \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteData))^2, na.rm=TRUE) < 200)} ##' @keywords multivariate ##' @export RnipalsPca <- function(Matrix, nPcs=2, varLimit=1, maxSteps=5000, threshold=1e-6, verbose=interactive(), ...) { nVar <- ncol(Matrix) ##Find a good? starting column -- better way? startingColumn <- 1 ## sum(c(NA, NA), na.rm=TRUE) is 0, but we want NA sum.na <- function(x){ ifelse(all(is.na(x)), NA, sum(x, na.rm=TRUE))} TotalSS <- sum(Matrix*Matrix, na.rm=TRUE) ph <- rep(0, nVar) R2cum <- rep(NA, nPcs) scores <- NULL loadings <- NULL anotherPc <- TRUE l <- 1 while(anotherPc) { count <- 0 #number of iterations done th <- Matrix[,startingColumn] #first column is starting vector for th continue <- TRUE if(verbose) cat(paste("Calculating PC", l, ": ", sep="")) while(continue) { count <- count+1 ph <- rep(0, nVar) ##Calculate loadings through LS regression ##Note: Matrix*th is column-wise multiplication tsize <- sum(th * th, na.rm=TRUE) ph <- apply(Matrix * (th / tsize), 2, sum.na) ##normalize ph based on the available values. psize <- sum(ph*ph, na.rm=TRUE) ph <- ph / sqrt(psize) ##Calculate scores through LS regression ##Trick: To get row-wise multiplication, use t(Matrix)*ph, then ##be sure to use apply(,2,) and NOT apply(,1,)! th.old <- th th <- apply(t(Matrix) * ph, 2, sum.na) ##Round up by calculating if convergence condition is met and ##checking if it seems to be an neverending loop. if (count > maxSteps) { stop("Too many iterations, quitting") } if (t(na.omit(th.old - th)) %*% (na.omit(th.old - th)) <= threshold) { continue = FALSE } if (verbose)cat("*") } if (verbose) cat(" Done\n") Matrix <- Matrix - (th %*% t(ph)) scores <- cbind(scores, th) loadings <- cbind(loadings, ph) ##cumulative proportion of variance R2cum[l] <- 1 - (sum(Matrix*Matrix,na.rm=TRUE) / TotalSS) l <- l + 1 if((!abs(varLimit - 1) < 1e-4 & R2cum[l - 1] >= varLimit) | l > nPcs) { anotherPc <- FALSE nPcs <- l - 1 } } r <- new("pcaRes") r@scores <- scores r@loadings <- loadings r@R2cum <- R2cum r@varLimit <- varLimit r@method <- "rnipals" return(r) } ##' PCA by non-linear iterative partial least squares ##' ##' Can be used for computing PCA on a numeric matrix using either the ##' NIPALS algorithm which is an iterative approach for estimating the ##' principal components extracting them one at a time. NIPALS can ##' handle a small amount of missing values. It is not recommended to ##' use this function directely but rather to use the pca() wrapper ##' function. ##' @title NIPALS PCA ##' @param Matrix Pre-processed (centered, scaled) numerical matrix ##' samples in rows and variables as columns. ##' @param nPcs Number of components that should be extracted. ##' @param varLimit Optionally the ratio of variance that should be ##' explained. \code{nPcs} is ignored if varLimit < 1 ##' @param maxSteps Defines how many iterations can be done before ##' algorithm should abort (happens almost exclusively when there were ##' some wrong in the input data). ##' @param threshold The limit condition for judging if the algorithm ##' has converged or not, specifically if a new iteration is done if ##' \eqn{(T_{old} - T)^T(T_{old} - T) > \code{limit}}. ##' @param ... Only used for passing through arguments. ##' @return A \code{pcaRes} object. ##' @references Wold, H. (1966) Estimation of principal components and ##' related models by iterative least squares. In Multivariate ##' Analysis (Ed., P.R. Krishnaiah), Academic Press, NY, 391-420. ##' @author Henning Redestig ##' @seealso \code{prcomp}, \code{princomp}, \code{pca} ##' @examples ##' data(metaboliteData) ##' mat <- prep(t(metaboliteData)) ##' pc <- nipalsPca(mat, nPcs=2) ##' ## better use pca() ##' pc <- pca(t(metaboliteData), method="nipals", nPcs=2) ##' \dontshow{stopifnot(sum((fitted(pc) - t(metaboliteData))^2, na.rm=TRUE) < 200)} ##' @keywords multivariate ##' @export nipalsPca <- function(Matrix, nPcs=2, varLimit=1, maxSteps=5000, threshold=1e-6, ...) { nipRes <- .Call("pcaMethods_Nipals", Matrix, params=list(nPcs=nPcs, varLimit=varLimit, threshold=threshold, maxSteps=maxSteps), PACKAGE="pcaMethods") r <- new("pcaRes") r@scores <- nipRes$scores r@loadings <- nipRes$loadings r@R2cum <- nipRes$R2cum r@varLimit <- varLimit r@method <- "nipals" return(r) } pcaMethods/R/checkData.R0000644000175000017500000000537314136047224014701 0ustar nileshnilesh##' Check a given data matrix for consistency with the format ##' required for further analysis. ##' The data must be a numeric matrix and not contain: ##' \itemize{ ##' \item Inf values ##' \item NaN values ##' \item Rows or columns that consist of NA only ##' } ##' @title Do some basic checks on a given data matrix ##' @param data \code{matrix} -- Data to check. ##' @param verbose \code{boolean} -- If TRUE, the function prints ##' messages whenever an error in the data set is found. ##' @return \item{isValid}{\code{boolean} -- TRUE if no errors were ##' found, FALSE otherwise. isValid contains a set of attributes, ##' these are: \itemize{ \item isNumeric - TRUE if data is numeric, ##' false otherwise \item isInfinite - TRUE if data contains 'Inf' ##' values, false otherwise \item isNaN - TRUE if data contains 'NaN' ##' values, false otherwise \item isMatrix - TRUE if the data is in ##' matrix format, FALSE otherwise \item naRows - TRUE if data ##' contains rows in which all elements are 'NA', FALSE otherwise ##' \item naCols - TRUE if data contains columns in which all elements ##' are 'NA', FALSE otherwise }} ##' @keywords multivariate ##' @export ##' @author Wolfram Stacklies checkData <- function(data, verbose = FALSE) { isValid <- TRUE isNumeric <- TRUE isInfinite <- FALSE isNaN <- FALSE isMatrix <- TRUE naRows <- FALSE naCols <- FALSE if (!is.numeric(data)) { isNumeric <- FALSE isValid <- FALSE if (verbose) message("Error: Data is not numeric") } if ( sum(is.infinite(data) >= 1) ) { isInfinite <- TRUE isValid <- FALSE if (verbose) message("Error: Data contains 'Inf' values") } if (sum(is.nan(data) >= 1)) { isNaN <- TRUE isValid <- FALSE if (verbose) message("Error: Data contains 'NaN' values. Missing values must be denoted by 'NA'") } if (!is.matrix(data)) { isMatrix <- FALSE isValid <- FALSE if (verbose) message("Error: data is not a matrix. Try to use as.matrix(data)") } ## Check for entire rows that are NA only if (sum(apply(is.na(data), 1, sum) == ncol(data)) >= 1 ) { naRows <- TRUE isValid <- FALSE if (verbose) message("Error: Data contains rows in which all elements are 'NA'. Remove them first") } ## Check for entire columns that are NA only if (sum(apply(is.na(data), 2, sum) == nrow(data)) >= 1 ) { naCols <- TRUE isValid <- FALSE if (verbose) message("Error: Data contains columns in which all elements are 'NA'. Remove them first") } attr(isValid, "isNumeric") <- isNumeric attr(isValid, "isInfinite") <- isInfinite attr(isValid, "isNaN") <- isNaN attr(isValid, "isMatrix") <- isMatrix attr(isValid, "naRows") <- naRows attr(isValid, "naCols") <- naCols return(isValid) } pcaMethods/R/BPCA_dostep.R0000644000175000017500000000543714136047224015116 0ustar nileshnilesh##' The function contains the actual implementation of the BPCA ##' component estimation. It performs one step of the BPCA EM ##' algorithm. It is called 'maxStep' times from within the main loop ##' in BPCAestimate. ##' ##' This function is NOT intended to be run standalone. ##' @title Do BPCA estimation step ##' @param M Data structure containing all needed information. See the ##' source documentation of BPCA_initmodel for details ##' @param y Numeric original data matrix ##' @return Updated version of the data structure ##' @author Wolfram Stacklies BPCA_dostep <- function(M,y) { ## Empty matrix in which the scores are copied M$scores <- matrix(NA, M$rows, M$comps) ## Expectation step for data without missing values Rx <- diag(M$comps) + M$tau * t(M$PA) %*% M$PA + M$SigW Rxinv <- solve(Rx) idx <- M$row_nomiss if (length(idx) == 0) { trS <- 0 T <- 0 } else { dy <- y[idx,, drop=FALSE] - repmat(M$mean, length(idx), 1) x <- M$tau * Rxinv %*% t(M$PA) %*% t(dy) T <- t(dy) %*% t(x) trS <- sum(sum(dy * dy)) ## Assign the scores for complete rows xTranspose <- t(x) for (i in 1:length(idx)) { M$scores[idx[i],] <- xTranspose[i,] } } ## Expectation step for incomplete data if( length(M$row_miss) > 0) { for(n in 1:length(M$row_miss)) { i <- M$row_miss[n] dyo <- y[ i, !M$nans[i,], drop=FALSE] - M$mean[ !M$nans[i,], drop=FALSE] Wm <- M$PA[ M$nans[i,],, drop=FALSE] Wo <- M$PA[ !M$nans[i,],, drop=FALSE] Rxinv <- solve( (Rx - M$tau * t(Wm) %*% Wm)) ex <- M$tau * t(Wo) %*% t(dyo) x <- Rxinv %*% ex dym <- Wm %*% x dy <- y[i,, drop=FALSE] dy[ !M$nans[i,] ] <- t(dyo) dy[ M$nans[i,] ] <- t(dym) M$yest[i,] <- dy + M$mean T <- T + t(dy) %*% t(x) T[ M$nans[i,], ] <- T[ M$nans[i,],, drop=FALSE] + Wm %*% Rxinv trS <- trS + dy %*% t(dy) + sum(M$nans[i,]) / M$tau + sum( diag(Wm %*% Rxinv %*% t(Wm)) ) trS <- trS[1,1] ## Assign the scores for rows containing missing values M$scores[M$row_miss[n],] <- t(x) } } T <- T / M$rows trS <- trS / M$rows ## Maximation step Rxinv <- solve(Rx) Dw <- Rxinv + M$tau * t(T) %*% M$PA %*% Rxinv + diag(M$alpha, nrow = length(M$alpha)) / M$rows Dwinv <- solve(Dw) M$PA <- T %*% Dwinv ## The new estimate of the principal axes (loadings) M$tau <- (M$cols + 2 * M$gtau0 / M$rows) / (trS - sum(diag(t(T) %*% M$PA)) + (M$mean %*% t(M$mean) * M$gmu0 + 2 * M$gtau0 / M$btau0) / M$rows) M$tau <- M$tau[1,1] ## convert to scalar M$SigW <- Dwinv * (M$cols / M$rows) M$alpha <- (2 * M$galpha0 + M$cols) / (M$tau * diag(t(M$PA) %*% M$PA) + diag(M$SigW) + 2 * M$galpha0 / M$balpha0) return(M) } pcaMethods/inst/0000755000175000017500000000000014136077111013451 5ustar nileshnileshpcaMethods/inst/CITATION0000644000175000017500000000164614136047224014617 0ustar nileshnileshcitHeader("The pcaMethods package implement algorithms found in several different publication. Refer to function documentation for reference to the original articles.") citEntry(entry="article", title = "pcaMethods -- a Bioconductor package providing PCA methods for incomplete data", author = "Wolfram Stacklies and Henning Redestig and Matthias Scholz and Dirk Walther and Joachim Selbig", journal = "Bioinformatics", year = 2007, pages ="1164--1167", volume = "23", textVersion = paste("Stacklies, W., Redestig, H., Scholz, M., Walther, D. and Selbig, J. ", "pcaMethods -- a Bioconductor package providing PCA methods for incomplete", "data. Bioinformatics, 2007, 23, 1164-1167") ) citFooter("This free open-source software implements academic research by the authors and co-workers. If you use it, please support the project by citing the appropriate journal articles.") pcaMethods/inst/doc/0000755000175000017500000000000014136077111014216 5ustar nileshnileshpcaMethods/inst/doc/outliers.R0000644000175000017500000000340414136076734016222 0ustar nileshnilesh### R code from vignette source 'outliers.Rnw' ################################################### ### code chunk number 1: outliers.Rnw:59-60 ################################################### library(pcaMethods) ################################################### ### code chunk number 2: outliers.Rnw:62-67 ################################################### data(metaboliteDataComplete) mdc <- scale(metaboliteDataComplete, center=TRUE, scale=FALSE) cond <- runif(length(mdc)) < 0.05 mdcOut <- mdc mdcOut[cond] <- 10 ################################################### ### code chunk number 3: outliers.Rnw:70-73 ################################################### resSvd <- pca(mdc, method="svd", nPcs=5, center=FALSE) resSvdOut <- pca(mdcOut, method="svd", nPcs=5, center=FALSE) resRobSvd <- pca(mdcOut, method="robustPca", nPcs=5, center=FALSE) ################################################### ### code chunk number 4: outliers.Rnw:77-80 ################################################### mdcNa <- mdc mdcNa[cond] <- NA resPPCA <- pca(mdcNa, method="ppca", nPcs=5, center=FALSE) ################################################### ### code chunk number 5: outliers.Rnw:88-97 ################################################### par(mfrow=c(2,2)) plot(loadings(resSvd)[,1], loadings(resSvdOut)[,1], xlab="Loading 1 SVD", ylab="Loading 1 SVD with outliers") plot(loadings(resSvd)[,1], loadings(resRobSvd)[,1], xlab="Loading 1 SVD", ylab="Loading 1 robustSVD with outliers") plot(loadings(resSvd)[,1], loadings(resPPCA)[,1], xlab="Loading 1 SVD", ylab="Loading 1 PPCA with outliers=NA") plot(loadings(resRobSvd)[,1], loadings(resPPCA)[,1], xlab="Loading 1 robust SVD with outliers", ylab="Loading 1 svdImpute with outliers=NA") pcaMethods/inst/doc/missingValues.pdf0000644000175000017500000034773714136076711017574 0ustar nileshnilesh%PDF-1.5 % 10 0 obj << /Length 2110 /Filter /FlateDecode >> stream xڽYo})t59xvln@ dSiI$ 5ТE jo|fPFgnv0֩gyzSr=G6{ n_/&̷xAx>p0|adGoZZ w2z0Zy]2YM0,3((T^fT7oI{8"p3 R4(DB,*lA']T+o)mw3u /P1۹)(8\–Ai9( *o/@U2y:f*Aof7]( cB~ 3,\,ٿb[Д.~ŶR_mU"\5U3!T2疰WoCV&QR$j:%TV-N0 l nd(NZr/ Nw\tme7p|$]0P->6 X݇ϥsf;VR)0+4]Cv.fܡS*k7 z/xe⍪UkCv$[^# *-vJP}?ڨ} siRҌr}5.Qqt, jM؅\'^ȩӈL WsBF蕘 ŝATpJngwᵆ^akz'u¤SqӇo%paB`?UQ t|1TJ8(6KcJ] NP-A{LߴW,l^čK9E7uv ď%t > stream xXKoFWB\RCj rpSW2Q4H*i}%'Q=ٙog|sqnOYhr*-<5}:yp~s8OSY ]{whzs-h/P~t#@{VBK'iF O?>&4m'5_@C[`Rp R No2U"slJY"1ec$Ot9 BiHĝ(Z0iIV(Y=%ͣb4"=1G*Wۉr\`v:b`}6C9QbN? ]B҆|b1)v/hLIuT[m 6\Qm!kA~Dg҄Yg|k wiF0} ~KSp+޾j4M[ -S!F̚ XXoҤ:1y/rI ?-[dH8_ZI?8wj?aJK_G{H@mܽ $ ɥmuGTXQGf ?K'Tpy cbLt* I4i6w.G ].2,ҸW IÊɩK*36*!),szF>j#ZN4P?XeECee h\H8l${)Os5>.#"\| $+k1àG냗s$|O]DIh^=Ƨ>2&xyʤ uZ7a>N}C)m{RzK=נ2xRpH1GZ ܛּ ?]hl@sZA;fצffVuD2Mid%M K[9(s$&+7 hzN(g*j endstream endobj 40 0 obj << /Length1 1571 /Length2 8342 /Length3 0 /Length 9368 /Filter /FlateDecode >> stream xڍT6,݈tP1 ]00CtHHtҠttH H|ss[saa喵AXCpwn @^Ceaу qY nP\L~o<`($*PyBm<5"pvٻߧ#  sq:A\`r8g`] qlbH$ƃpb b0@3\=/. r0(w@\_p w8`3 l0๒:;m!A ( d}or@IVoPgw77(wOYn#prpקu:H ݄3>QU^ ',@\/=zΐ??}& P[pwS@kb_]^S{|?~2 UT2|W!Bn~A>>A.p[@j=&X{Bl!  L?. F-HfANPp_ !`6Suݯ,!Bݔ^-;/%c0(pT@>/p'~o;"`B+ x6?.W), -D(^?P EN|GF>:grx__{|??M#!5!-U4HIM4vn9V+BdA+g]Dl2{MuXn,u7qg{F dk?rlݺ:5xj\ ?){~~06^ h)S—gT/(]Cʸ%3I;r WxT7T62N7ņq~;'K%1OL:%mEnPXŇrH+8X4c-k*` T8#* Yl>5 ҡoZQt2])z89FE<&=zV1o%y߰GWoB( p*1ul'z^3-^n  f1ۗ5Q>pZ;; {BxJSmbG^cd˒%hB W\5NՐZH:$GXku58Ց ^#0xYⴳt3U $UbuKCjnsf> zjr3wpˏbt-ˮF"jIS$VJqf /J8\өXU̺) 7\t[!%= cYw7(\P0Xw$}&+Kǐk/<ZN+ip}XC胏?l.NmP(놭f&]0ﰧt/F0L8^(ܚG䝧,Ab2MQ.esυiaur!!^U׸z̲ǚ"ZV*pb}vl' ANj.'Fc=Ow\g?5yHִ|丮([7;ˁJB,!L!|"b>E%܉7F B'ï(E' m}#@B k~nȘYIT}Mdos7c3s&ԋB1_繂}dYTOL?V3-c;8cI8&U|u* 칸&j{rekqV7Yy9Pt.thHkfh;T|R/BsPPܟZ$_{-Lږ9Hyt~4o=@Aޒ25(z^9k@#΋rRhX!=!})Ro@L۝Xr!~JWh5pceqǁ͎24 ;=8cRFHޏ%yt zTW Mۘ_GBjp0R\w+{~Q8:s1hGs4ί{gfb ,5bLx䢏`%:omj pL^2MDz/`a8~Y KWd`}PV H%g8x`.2կ p¾YՋ[f+MN:sb>ҥ=|. yHnr'A]R%]62s{;EO>cSy@ۀ߅vE'$: ZF!;[ă+ 8~Rvs#A$+zWMNm`߀(fb:Q連<~K%cZ&!{ @EA+EDž@UbyC:8Cj ɛ+wI d~mJ)Ɔ0*'ھt-e+V[Sη6YUw} *gmpEO}%A̻?CGSRQ̥,NʔN,_^6oKcO.htMl<-;~=;BE+Ť萚فF𓽻L ]i;L{Hiu 6lU8X4W'M,?HZ6)9:`-m"F_g1[M6v'֣>Ĵc 1̦vR4OK|d:Nm/ulś( Eqt/*MI?fZ翇\0H5,iB3Bǚqf6ām[i ǝLc3O }ImOѩLԝ  iDTPGL+6/zҸ6i4).7&ExE Gr"I# #דr/bޝLJ0`X6GA `7]=c b:=xuZ!I[ACWe^Ct-þ ?si/!)f_I/ qmoTe q|5wGG+=T5**yÏ\'xԥse$?w3\}|ܨ3'ӯ*C F8+P|(5s<'Ԧnݧԉ繑 ٕ1~<}ad!c?W֥ TlK09I*P{M$tJI-H,rGIm :SG"hq83)9ZK[ ?tFJUe>tVja75YGdKܒ{sOG<VeL$ v&wz;+1į $ F[8? << ?t-.V*GL%R -HVgyrj:zOʈB5vJACj>gQs*iٓ@!J~BypԥFFY|.hFѝȖ( m'/8G ;ƀ}󲞣!qqU&]v[3RP91h9hJ[UQT3{A<܊SJqXB YXyE)-}R%3I(grURY#\qۤ>01r Ďz $kg\RE=۝ $%XL2_Z]MJjj "qNV*L<]F_1D( 'Б932f6+t׾8)yBmp!6;4E{\_lN mza7^ڒ-w'V(j+]V3'zsgiAl&}r  &N |+:F.3{Qӵ{+1T$ ]ݑvøk7vy<ó%;[ӷA4HL/Z\7~sϩ";V^0+FZ/* SOʢR53|"d5z cooYۛ\Sp% Nұ$HrN!;$f.gu02:Ve$ʈվ,U4%X7[A8oz"Ԗ!S(1G@Aɛ+0rMm ><kҔ"nrcBx;&-> > 468U7bB䫂 |9Gw!}:-\6T9YQ}7BZEyW;X-Ug_.1qa' ?+ XѬmG7vB~opbWzۊ!KZ§ i8co{cqME%A_:UwGvHe5:1)xo+p2/N^bLQlCĜߍi4  T)? ;h iWr- '=zH?%%JVeRu!{3߲> ѸD^a1ޏ8{Bzn%B= *JoBREZSھ΋ǭOEI:JƩ31|ki5pP}}գDšq騛:mߢqOIt u*ln5u/ #vq i|0dϯLN><\|k3`V4T15Nk1:C{]QYy9-Y~jn9s07{`w$&У6ͣ-89:j>s. &'IPu>)'J*q(QJ!yADo9$̗ٗ|DgʏOL^وgթ[e2|x ¾:uOW&yR!G `ŏv+*Gѷ'"7\39~۳g#En-w"a;o˚dnz2 ±d2گAff o)` x;mhhBLYo< AVf#E +}$kd9,6ʣ5d/hHy}<="& iC~i\dE(b8YlosfۯFjQ{_Om\fzo?aV"Wjc2falS>{P L?g,sT-CEOE!n7sZd֮P~*a3$320N~bevnl)y}A endstream endobj 42 0 obj << /Length1 1450 /Length2 7213 /Length3 0 /Length 8198 /Filter /FlateDecode >> stream xڍwT[. Ui"tBޤ $$;JMt J*HQ@zG;]w3g<:\p55Uy gf6! H_y$)7@M8 |@@8R r4jp,Gx"}^Xl^QQaY  fG0C!h`p@b<< 7i/ pz*r)`EeЇۡAHF C`0[p;@_Uk9/7 . A!m% nQ NPn*S "(nW<"VQS"!s\'d*)u} QUQ@a~A;mGnʀB 7/|o @#B|>// Fl P?o#3 x_V7 Ü=n1ǟc{\|@/P@ |wOWf +ߛ;g?$`3!lӂP`@A ]o4H驳o;_r:{AP)f 47o1ՄBU Y x(%V;E Q_W̍_);\#nenFdP;Enk $I{3pM;;8WDZ;UFyw/rݶImdlؒOjV,&v;X'E~:#A̒˥"s"mg{QFiP_B=;G/ rjK^|g~f:dE"m.(9k5dܘL$ա@hV4߄ Zix[B#o/69iת(X ibOz˳^u^.KG>UK.B VIG ٯ6#c(["+f1cm1Jr(>[1J϶.0Z:/RFByRS?ZR\dz }my-+$K!ЧÚ+2|fXmĿn]Y~cH 3_Rݤ%t>iM,e_lTղcz$%CEٞeȅ?_@xim5Ќ "Y$&=:&uq} _?pY!oY̌@c^_9 & =xYdd6Qsx6a@^A)A137G`쳓^DWz9-wK\{lVycTϚԉYB!&$7$v/19593[0Y.su>pi <=M5@FMˍx>4mcv' -~,ų):/}m=%10 H>^D:;J Mw}sk&yA-{E3ҵDPzc&IH%2Qu|IږKA-/ ZBcxr˫^ɻVC/3ly;PHEFޱtW(ڕAmMG,eqP~qښfY:9}!!c:xc @Å|Dg#S-ȿ?KP eV#M75HK x+ CAKGג;tioy[=~dS⫊iLum7ҷd+J\L6Y뽜tl⵽w7 V*pNjge3GtK_}%2dGج?l(F]ƞIQ 1"XT!5\S8w_R%xHa~ ^k S'6LO)ǝjktwhĶ53L>Xh9F<3 ==۳~! @EWsV%Ku!L}(7(xa%D6/{"#75ĭ&25$w~ps]';W3$L.,@f>'4 \IOge[7 X;:\dF)c Ecg1 'E߫V@Q3{\'Vt4 2xdq9*i?3݀S(gb$Y5?a0׺fVV5o}{! 5K3rR7+j&~bK y띻ؤEb`nQYe=I+G_ w zh(|lMlxv٭UDI#ӮcO59p[3=9)y"j zƍǭƢW4{ŅU~zPIJ{Lr<Ě(YiGx -PI>- )rY7vj.HZ4g$;.Qt*}IX).'e\ "#7[Ac2 {)"5u-m8J%H|Ib(~r]O9ϻ|w;d{Wx0`<}}eX~&DceAnm)a:NsU' XѳމဖC+ Jdz/o vQ-Y!y*wvOxVo񼡐e4rU4m×>ﹽSa'qS9?6N=iB0X~1)+ĸ`-<^Yi7!?tfc#DN^Pl.1딅 g{xG#I?yJXz *FPy1]#/b:#Q!oí>&\9E6*+:K -VX'e-ˈF=Lh$ R,yW=fwl(ʥ8Bc`u]p-_bTwuWVbO>#ƟÁkq2U-;|BV:r\x/}]37~k.yQ6S&rT+fJRx{=xe)Q6@"L{}dUu;،enQMW$1ҩ9gtck%(6^qʐ5u5`rҕ+ デM.4/<,n&E~ y෢7HD˽}mjI{ݼ9^wc,Z~7U"xB򯄕7~w*')txg%S{PY <H]Qn[c+bF JCa:Ҩԕ0n,x;@떻¤y,eJ:KzّA@ qhGZy;ċ8mN[]T%{ --_m|sT n]mvUOă^z68-b|GД} h i55zͺ5?y=gg:C! u<8i|+#kS[t'dG -,YP̬!F>T.D$_uCɧ)[ ⵎ]g S|(rs:P儏ZHRйe rKQs=Lg V>4-Mz"t(7'eL]$:~ sҊk4,Hs&><&<6/]1sWDz "=XvH٩F˱?( ˎjE QRtvBQͽ?+{BLJY)zQk!фMcg>~#Op{ڡn f\Bp9i'P6EO\ݕuΧ NqdeCՎlfko~s90#%n0&l8qs\A~mr_Q7Ci 6˂7_7?KhL7`ZWZtQf(5 >yMW4BFk`Jf6=ۂUb$4^vfGMaK7v4ї"nKQmPYAʗK8%=ߕbyѱRH7QnzYD:D:۪8Z Sw\D}HTUtBA P-ZOVeSc<88!pjCA va]J^7s [YANUWOQ^%Lզ^a.6(OrecWC<ﵳ**ZlPLˢo*_gsTÁ'~_=-"./_Qh&#puoEma8խ\Zq1SvRw>\` uIrHH03i4ΨC +9t E^lߔleg 0.{(ut9MjEriXcmV)$}4 i7йq#J¨w4%; %ΙSg^pٲZr,bg ,_pz Ni4sK& 1]!6q~m`mJ;+&{uerm`ÀIWqTǸcvzmkŤmoPamB=1cȮִ8}iATtD "s m}-1oo-Jϳ0OãSץ"zR^ ~aXqJ+aP1PΫ)4-&˦j9 F 6VoqJፖ| wh]iQ|ZW'x2]ކ ֋; IA Up:\AevkzJ%DW7v 0+6{q?ԻH4=\::eS m<4Z=SУڼ#tyj),j3c*l;J2ڼvmvȶtfYx9'X`Q_$C(f6; M˾^F+3igba> a-JVvZnt٨I9e \ұWTTn'w'1 OV(L] 8]1~SЂ!w*r+NNXY:/\+O>=*uN4?4*%J%&0_Ț$*MI/*}Rpk#լm46SA7N|ί%MM }ZJi&˫ݔo}I1{>s K ;T[`0p˵Չx|E}pcȓ.E;Jil9XKsu*շEF?_ϬWif-l36$RI5\<'G ÆM:(5=m^El+<Oe[o! LjroVG$}#yɩiȫsbեK램[t|]bY`OC)¶]K*#` ASH̦zI޻ ofp,`]t1gq~%QHV\Tkv(Ґb 0GP%CKI-Ii|rRdб2UaXc\A3OwP~^L`IH9p0'~N}Hn#uρ-}V4aq:W˜td8?V;]O,g[w3nKN-*3ȀѼ}l]hۧ#Дnd"&lŢNw>:q$r1JO)~WN$-ֺf1AJi*_+q2wH&rϨ7\{B5.G]{'ZiDۚW;Ɔ;.ҙ4/j ]mJ endstream endobj 44 0 obj << /Length1 1418 /Length2 6406 /Length3 0 /Length 7380 /Filter /FlateDecode >> stream xڍtT6)")!C 3tItR03 4H*!%]R!C(R"7{{k}ߚytyl0e$ I45UE $@QN`"DHG `&Ny8XT@ DI!p&@ .>np;{8(t3  =s"GB0?JpH٣P.^^^|gw>4' an0Zg؟{\i !1s8@_UC n`>;"] 8` w5P(a+C/#ycS-e?'/ , b^YE ߩ[$ -ձ_KBbX pMr30yTc*!e'n q;! #M$F5&^U#9̼`!> QP?A}[0Y 0:b^qA1bC^/?PB@6t' ,A|0X?0F60!(L 3sFk~x!$ )wm`|t/a0ohf q i9]M=1ɷ D([.&gf̪*t-ڵ]OLe:eTfh?u}=y+8YD[C7elz5]$/6beQUTFKz&>U#%g1f)ZեN*|'fR ^c C)I+ T\dyng\^8gRqjz^`x5<Χ[rCjDH]2t>~[}4vx=@t%BpO6vJ ҩ`D@ 8zusP @%PC/v6.ێ ͋ǥO>WDm=2 ࢉpT~Qa:!na_\\?SӾm^5y07 J=tݖ~f:sIQ~@:U3c7W*J"6J߻O~9ؙosk.*k  *n$χ| nKҨaçY qxOɷQF| O۔R IIekcAF6P殦'^puؐoCmޔ=[Slt`޼C˶U+#?8oPp ؗѡxeh3N|٥?J'lv7p=B$tPfM,ܧZj2!= y~}W?ʇӧEA;w)C(^_nu lg?\N}9+QB,ÿYRjAvK J0g~SC鐚3۲d«U)2Z-ZYBDFG&⺞86W K2͙sQP(K~ ,siMl-q5NpkM3j(-,sܠ̳,.Na$-+,]T[G=F\TO/#4lF٪lVNέtiOZeQHpS3~AeSԋn XVzaHcFV[TgnC.+mn̝ ), h`ݧ$#Utd5oTm;b3[p<,tlVoұRs-fkқI&S{:G..͞W,Mˢ(J?mJ p8Mg r/G;ՌWUnD1gnLJpAAHgE|4 NOСera!9dHSeK=֍L{T.:Ia)2HKrl%5ZEPW-+4Yfs 6JX5x-ŋJ63pRLx"YiZo+ tV (ZuڅdU6g,u}{"(6I!ɲ;TS]돂AW6Vj1K&*P| gæ6@^/ޥUcNΒDRf~4v&cH5.-G͇c])dIժ>T7uj{X|*]!Wԫ)8BP)h;Iߓy0PphBH,RPQ!9yjOYnOkj-G4‚59#Xƕ\8.sv_(] 24m kJ򟓳hFPb #& v@L?y6FC{Ա䃖 U%+- vf $&$H%gbQS?[EPr?Y}mp䒱з~ЈHTݕ#X]Ok,iI>Iͮf>=8ҫ$=q_aɷWkMB΂xX)W볰~®گϬ+SGi2?% Z|Ep_Ŕ5H8gOIKQsx:V sHg>C8Q }VhRwy?X] vh[2N.îL8ߎs TsE:/p$h5N0&~_v_&f6ah]A7;%jkD *6sdHuFxqS@cKj%8SzF Gx{7Kx_\░>$a'XkES9'm^yXI^A<-9+ֶl y!}9~WΖɜ=FzU4T> q-3T]UKl5AtdOv`ߞX^:knvS${:ߊ~+vM&M3OG L gVV#}ٚmJ`ZZ%tb=aku(xױq0.c|ҹ; uQcAi T$) g3}1mMلwt+>d ~垲!gQAONd|Ifm/Yq );T!Sbx9eN+\t>)tߤ]0cn7>A8S Z;cʒR݋;۱դپ2Gߤч:w PX1hY0~bC=aMȩsLw"Gm7^A[ϩ n[ڿ_x2PޯPW8 9ZwSRoVyF Ђo)*&bnÁ"`.%jdܼpǐ s67xݍk6ƣ?\m 2-)N~Lo /z[Ƭ+,M+wN؊ciwWxfU Vzu(XG[~ b\5z<'+@޲ 2/S:=C x7&49Pb6u͟5fNqqʃQ,+[w^)8u f& {FKiBW-zw<~pRn޸6wL>#HwPm|miNErԿ;H&Mpޛ4o)hK~l 6Nݧfx;IIya>G1vZ 4x4,meGS$-9 H=g+ڼp6pT+f*&MOD~׳ǣ+> ٳ%ќޮ +Aݗ[Q呯QI-wQ!AISw8%3r3>a!2!3q=#2k5qakQ(a7,Sx-nxN0Mӌ}cux挸J)8ZfOV=z'žkJgp/LgMՒ/I/ƾI);O;w L][BVwb;k)l'-C;&=╬ %o:iϤJ=jgvm3?|l&Imqo텂oⓏK7h&N v6?9/NN Գ=u9jPs}/Ww2,r׾*/7:<\z~lY x*$XǨQ%1=LSe){ٓ0D\'RKuzcvS5}7;Ρ!f|stK&,4SN*&dpíҺuAiTl[TB-U(cN+n RjD?Uv-IuƧrcErgz{VMۗ*bu%(nM}oP^ZR!~pq 1yZpkfv*L}5;evO{@w^3J22'ub~q\CLk2 )R^тy:J"j>o(hy*$8'9 i{ ߸m$Soa5ߠ]$W*} bsީ/ڣivj0Gqn&&yS@kC K-Yf|I٘Z@$z-;*9ZC+:ƈ ~LH  QF%"mC|cnCN+]}Nůnry0hٟ\ER|)Еv=#+Ak]c}h|Н!c,^ 滗`|y|aG^*.I}̚)S*9$IKp?ÓBD+|&EP%M[=Sa0Ԣ9wFIo`\,G?u\ʭyU,ckۮ(Ă#xXV DXxI+8fvo4!~KYF@ܗ_dXX-)IzL/xUv'j8օ>* י3H&pU俹.=^+#4բc*pt)3ȱϒ@qy]$?ErOFP=w;<%#j2_觰shSCkl)çeN x9Jwj;]fB1MTuqx˫bTWќ&뉬W/ 3);^3c +\SR=hݘœy*Mhtm[^H:~rz`mDΝ$"ͶvȁM{++=F{{bSSE_aQ5Ms<],}}Ԉg z 3k.wx+Lj,@ [;7Jy0-_S,$v4ME{ *Wnٯt>"gӱCx>N睩bBXJ/+JJ&plwx b4b镬2{&-~b%865gʐeed ua~&rqGve-=W,cMk)Q5rtB<PR{Ϊ 8ףn56&utʴ&M') 9׹UƮd8E&L.),<3; m0OwU#Ĕ`Ѷ%itLn+`R!| PSVB&Mjiq_]B߳<5oŶ;ҧULk8?Q XL|i(j~iֿ_JL|>0\>5B FyT\CU߉5 i],{/+3xh͋67tk_J:qe[4ˑՑ]vv!M)|@TIr ڨa+}>+Vy~rb,aܱ3"G~-t gGV@DdžԂO5T&J󃂊p/Hޏ6̛qԏZc{k) д|GcAX>D]ZD}e[l&W= ȹgn2ӮW> stream xڌP] Cpw qwwwww6|\ -Hpwys%~_^QkgZ)Pޅ `ffcdffPv O 9[;#@ 4qy)8d]m,lN^.^ff+33@q7ks#@ O! ry/G tdmfbP0qڽW439Y]<őݝΙd)HCpv 79/E;࿔1SԭeWspq7[k3{9x/P(9,z{`ad/ݿ";`am (I3xL 4uvx7q351}&Iɻs6Y;83:[%/.K؛9]:5hvOݬ_"]4쭝\2y7Y]\ގw@k xog7  < ` nZ _>>{,~d>^_&5Em 1)OT ```5d\>Klbc#WӾ?'vP{9h˥>@!g`6{yN7 =n?n;k[(8 ki֮v+b"m\_/_[fkmTvp`x{_-3WHo7s0kX98& '%#7.=b{ ]׍rrD2 q n`/b0IAl&?EzgQYYw?sj#?轂^zg1Yؾw?f3W_d`i_}`,~k^ao hw?[`.Gyo!{m;3?䲼" O{'w?nw.w 'WM{a0 r|g>L.pv|^ |W72s޿!޷?4_s0 Tz_)ѝawL`bW+{ "=pt+}ue[FxKsJgo- "5}p {_>k@4wRd;r#+bܻJy,Up!i5Z}COb;Nw@0~L#VEW *6 Ajfŧ$%7 ձcSp?]hRPv>!KwZ +e4$Z@LT%P&!ށEYuzG8?)PlߘAuG7z T|3Hdzb0NI YR0]la3{mq, /`ٝ/xYˑBsa.`P4(`붴TA=Lt(zS+8']?Y)EJ»8SSuQ7-ugwq E>C/  z*oY۔QW)!Ȍچ4~TS%뙟&5Mm[ad~?j]:2"qM]v*m~28)Jƌ)8v" /J_/|!H(P_yR*ߩN..q7=kC*G~cjގu\B&$<+N^f*v IEv WXmY*ߪl9$ UhTh"Ȳ(Pbc`.%`=\бUd=dzsҳ㯾2#K[Jr$ĸV #\??0i[ϟA\6卿a!}mb-;x2MhX+h$J{2?;,ᕀ4 gJSHΕ)UC :Vڥzrh׌B_y]ݍD/N9+>:a饂Bϑ7ou܄9PP*)DBM=԰ITf<25rUhfR929Fx N|Xv"7*pâ9(* \uxJץ@~0q7O[19徹jPҳ(7zz#jw& [ǂ h[į3YdضQ(KiШ3`q`ee{D&k^І# իCcuTOt+6$7N*ö;LbXa% 0 lDd)f( R}/zv?ߚ#%mKJIeˁ 1Z>4+jx9k?Uѱ Z$ Jڔ3!'=! qƴ5pU+ԕn܂qKA ?xW߱tw@X#a N6|ueI/Ւ26MMѰid$r%F kVn9,} aRɍG9{ӧoѶԶ]KSeQ$%7_LUXp*G|<[N?F qΆ6i^ߺ`ay3 .J@%An_xe_)E,?nrzT䗃=VWv [ͥܯٝZZ ea2YY/N™fwszHf{2^e{4md :3-'Й\V#ի})$D;|t\x:[R+XYF+MRuwD" g,+ܮWtgۋW|~^C-΁hsxZ,g3IWoQu7uKhd^I?.2C.1DyɱuX{]J̅&l|Ϟ< |FXT(,0t WN_}#¹N*IL8D0jmK%~LAwk-ȏ$tNgD7ʙ 8v hIW1dyf X"1ݐPk5 a|U}5D-oT0 cxTV`س$R .l(A_{GIڒkuQ[s<P5 f9 X:Ք=PAMƩЧj݂k1Ip ܓȋiYH:Ap]1 N"^l1 *CezT &{#9ԉٿ&R $֗/ mL׺|O+ `M5rݶWrY0@v"og1.u!hSZo.0My!1eӭ?9'cƱG0u tVN6'gԿIwDoD@V}8ԛXOg16YDiT-U>%+UmUmp<n|;/$0\p:žjC>=:#Np#a~8hLD\]<+X7 W`|\˷,E4A&zͱxw)O:]}ϒ8rjơxS(%"rUqQoI}]쁥B"W=/KJcIhYNc]6tV|!mDZGQNo5 e2~EOLC6sH|֌Ύ)KvTȡ죌䗵 2.^*%]دt"+=o(B1#'~M2Z64 YČ2&8-v Z!/p`ۡ-4o3>㡮)F ѰwRGiM50X3ֲӇuLTLX ;.b,ڽQ$xoNSB;_'X: Yz|CXGJeR#%j29*rqk#>,/DH'm6MWFit\Acj&I~%|?9{ -“80+hrc"̉ՔWHrI->0E nDl]oWه= 8BYXX>+</N5IqB@ȀE,DuЬ]w\MLP onyc̉`T V".h %4[&%CV[x|4 )C CGLYg+No^[ݱ-:Qtm/?uy{Y:.l]?yB5vPo)s"p)Bb,x}D"3 Ą#bמI0ϧ!᧼]>?sz(]/B^W_l>%vd{83Qt'枭v 95j7Ú{Q,R4[nm_ t Z5yeyd9jZ+=߃Xs#mA7v!mVX"ܴTî 'yCuz/]A\ MU}l2.CoPU~&VB'8I':BmG$=j\ȝK:DP矖)EdJ:Z`їnsv9ݪuɖq~ Sݞwwq).;9Yg(b_}PdCr^\Tt47dɻG};ÙxB|Gq@$i7d AS>hb+bޒOh.`s AkxMЭ4[Y]uz9|ETU*]23ĝB꼧 8o0j]U?iZ6-$bj?AM2ػ#*6J`M_W! DB뼺gn/Z\N__u69cp$}< 42?Ҏ,%1)Or+;iaHpV{N{ Mcɫdb~ȍz0Dl7JFA;M%F/, OdM+XaV0NH MqrR\1ۤeU&|+y^z9 땟UÈ((k-v3w+mNƼa!Y6]d 3/O,i"WYnz9p!5bcᓟTkV5y n)6N[VD8xBjJ2I{zk,[Ww M`i?h""C 1I@e=:^8$>sLa> ^l/QF^"iGW vHQbLfh}Défp%l}^hUQwT)PTqYh޿Y/L?t b_/P"G22FרՅ׈@:F%3f'z@.!LTLl1w_kfSڅߡADz5D %hnG.s)cC 4] u6K%An1۹d͜c,3r;++VTm  jtbyv4:FLy[7GO90UfA9û5eoHxZhr5Jl=őPVn5)Oo8*l!L:]XYgH0;zz$'"a5@a{lCiP-8q@23MS!Yp=z;ì"T{fFΈ]VNl+7]YUw6)-C_dD-)vj.KhtНa 簅U!.guZJfy}T2 F c~ɷ ~@0n,ZiOoۣ(ns6E eRvX>ږXX!*P#%P丫XE1j-i!'hq#H^#hPq", Ye-jS_clT$DXN b/4Z/lDF[(LFhL1qf+aHڳH(-4Q[M-iG%c$Z~%=hWB.Q`@T\ "! ;E~'RF'}:Svmά`yaN { |TRdE=wRZ/ ] v\`Vu;>v4Ob~Õ2 H4/$ڜeq'(,݋ai,,_ ~ȗ%KL-s#ZN/uKX o6zxN+ ￞_d@MU[fٽI")rgR~K=|Gƃ:h'b˟?fq6"[2^X ˱Un_j,3bUl}|'/^eϛŲ@yU/Yvgo-'Zpp.lX-5?P(<bɗ9{NzGԒR izL_Ql.3= Q|3.[0;W)5AyyT(U,0FFGk#%;s7a;@}ia I7~ES<}CYשܴpma\,\B ءbe0;L৫.z46X,k }&i_A[8hjTddJY ]'KY[Z1ߪBk"ׅ˶@Or_`cSA)+GNMR0ey^ e!);"0+54Oot]Bur]k)M\P!{.Pb0DMKl1~F(sKm4Yd"dGtЍnR~58Bu b,@n/LB_qH䰘\h6Ae9hPBB^ݓT%9ͤ,uK0߉飍17)|lj hr (7Nm^(n羚V۱}naA5|pYu}@mZWy'K_Ύ~5ITyt#LoY -jp pBHt3v[ :'I[w/: EZ0rSA|^A%D?x2 v4R<E35x0#CB{<$bs\WBdzkHVֈfiD0utL0N=QGGy 51*1gKɴɀŁLT9ЦjFYA&09,6N<_6X#M֖!iiXsR$壂_R!$Ψjwsttx\_;iD['ǩνEnd2VlQs%Ϫ7qyk[b%BDٞ+>&93>N >qym.lgHy=$LWQٵ|B%]Hy&|gP8Uо @95szR)౿ Nm=]4PI(/k H7%U$20H6.YHN/,J`fʤ&e-B6`fu)ikҢ T+J@`Xr2I6Uњ^/gB*פ]LqѵKV6h ZٷPD'N&v򟷆+ TMFrrVg6ÍQoqT5Ւl7~VX52L;w' Ue6EC0!kx$1oB1ARI/_jk#%?7ؑ]; #gYe&x@DnD9rֻD$TRO(n~k;.+.js#5xʇT3GÜEmxk=f ETJq+չiMIumLGOx@d~(D#u98k8V j PZ"rsb{i=L,xu_}rKP?q,ϪL${ϞSc*$ΚzuZVʔ?s%1t ך:Ϋ?U@>Ť61R=םϏ#`&p`wc7=@HJΕ&YH$@l{rJ00! ~ݷ¿[qVݐ9)^HdJg!: ͛F4}x#/AO5.T䤡.AsR Z5G-cZS`uѼ2þJ bwMvBl/ex|Nɏ=e# $ x,W%VZLd'Z݇ͭLp|/EzG>DăF_)4.%8gQ?YŪ@*{-]s:ʝ゙ M[S=ũѱI`HuE~D$>`Koj[ĝw^bLsfyYo[` l~ޣ% %@bsӢ9 X4hX/"o9{*wq AO 6:#w>D2E4lk1bPwu?'d%٢_6ؑk?a7>HO883dl |Gez[-CXuc{kǶ|bIux:X]M]tv1lS:.c/ߒ*lՄijyD:7S]N0!zeuRUvEq>Uե;F8=VQPH%[0B,f|~4dr5cI Dx~+H̝1!ZOrUgngRM[( P@TOXJ B<ei׭ɂQcq]:d+Myvfm dꦌZ̻ЗkvkeY9CϜEnպ +6rާL~B$ڤ܃i F1)Fv3੥6di_x!N8! Lc%z*,4qi',|=Er%!lzhBn]'( ygdxK}d=bMbB^)1Z||l[?"G/0;y ^1օYu݃m$j93#n$6tis^,#pY`S B$b[ xԃRl25k[hS2Me&Y]˱Tg['b渜JG69ic! 2?A~bVI֑ǟc_BFIqy DhGA q%]͸QoOyo&5AϽQ_biadW-%bPo_&gQiEة#A c}wXAw6Y¹o,ULxTeǩS: G'Γax/y`[,gגF*#wR]>`vp783+sprI7%ΘO d*M_Q;ߊuFQ_xrABFw_!)L>(/+ ŋy±qRWmƭ޺i,{ E0HZ #\Bc-v7$9"vF^=psS4=҃M+>tẗ`6֥wPOi?~UFҴ>M8_.E.wAH~װ(6-eЕJv|6g!h(dS|麞t%4eL I VTxo+AJ>YUo_t˂;A܆=JCdX[]S\Re)K,^NA Q`Y0# ^f]惫IvqJThe3oC$h*"m7jy#="? "u*֤Eڳ@M0QxE5GE!|c?(z*I3 YXP:LΑЪw B=54vUFAvTJ+z݇a'-\Pѓ@heFZ}/&HUă:|I(Q8qiXB'"(G4ѯ[zL w!$`/{*0*"n9Jm~S):'QhCV'q>; Oe*.XhqJt)YSA澗)2sai{0b T]Q M%TWپU  ވsQϧZ$lńǨxe/ RV:O([`v#뽵/-fkbsmt1&LI䦫t*=Z榀mnshDaJ`"`,3 3F>)zs,, }C83$UmmiDzFKּl !.2m8H+:gi_:ʝ=ke`m:(c E-Fr<^S'NTߗ(F[cpB7oLЙ)cUJǁw$z/gEdj`ʶ1b32_xIM}eEY FIUTT+A3=|:BKGi)rg;x \.yVA7,uWNz=:NFR3ṫ<])~a?%.|3>kC[-xT܂R4#+3=hUˍ{'͢rAIDʼ5X4ݗw狁pG=lg$Zߋ_XdF-=4Xvx91C_M46 +JSTi"- wMx@] c)يAft8HU`]fʸMې .8<c]}ㄨҕuOH8XKUa{u Njri#ԇvFy+4 sRLT%SBMl=m GcűR;2KߝYi,K3kQѲ7@C|tmM`_ xEU;laewd6kج2 zk Wfm[3 ﰚ{wRj(@CeKhNu N35GaMHr=͝=hA2vINN\>ӊ'm;v© Z+>c\bE:':/ʼn>C[eD'8g8qkO)%i1%ED"RZŏFh\= đJBNusB- 0'K+̒״|L# 8#Ϲ5C.˭9H6'\ `^7e|jv=HpG1&ReHi>|Dž|Y0jNԛú!)̕ز*Tj},3E&k-A7䜓2LVwކ߰ Yn[! 4~Qyfxk̮] 64dFգc .B'&,n*ܝHXW&`f!JIyylvo|hg -[Y/лwBi/R R=O?9U.cI5Ay$W.H6fla[ [e%o~T|!h;HI -0 hsm01?#ٔRyZ7XS>f(f @D,wYŕ#\`@4~@^khZ2Yhpm֮=@'H}լKۿm̗֧5h۔%5'>doN+`#F<[GVm7gǪ_B%{#L8~}Pg\#]S+Ƀ=UΈӟ:~ OG"![5UO]q'[>y_ָ'Ն#ģii fBFG{d g_*r 5 sLBTl^s;G('^=@' ?+ߣn5[)_|3@js7RS_f{A)ۮZk+m-܊nRcm s Dt_`vn@:1Fv wFhDj,*Rav3wC6v3I.la;rMCNb uC>Mt %ux.D´ \*> stream xڍP[ w!Cpgp2 85X܃;\{kfiyVw~gU5,̀Ҏ &6fV~:;J1" / 0M&ifȻ8ll<vVV1t$Ml,JyGJlcev|Кxv96 5DsS{ Q Z8񳰸3:83;6.u30@Of̈TMk.` M`oc9y,` 9E?_xEdiX*Ҋ..S_Ύon6foGn S%6N.6[@@3_Iڀoedf@ K_IX:hl>$c&B#XYYy85_Nl2vrtX%} z;.`W!,l]f@+71v`>[Xz[{Y8=},ҊJz d_p|7`*t['`?f𿹔ߚ\ool;o [߀]VQ:{g]]_m @T*-l\Vm@V-BfGאۀ6m+ѽMp~ȿUGJ-0v.n)lH\\oQzf˛ -=_#%qX EbA?OXT7?Ezc/{C/z; ?Օ_-[oQX Y!+Jc&|_-TX@EXf-R?7_ ZGWvNo:|M#oio9E'xxv6wy?=@9✣@m}H];Oi] :&Ep*|*]Mv:F,u}e[Zt[|xkZۣϓqnnxѱ>b&M=>AvS}tEU-sW<6WíT>cX2Coy= ;zh37Әd 'zq^?( I1G'K鳸c)l^w #jq~Z|hlV$$8ϿW=.x93$ټ|RGzuOSCn N5pj)o`|uxD[GUv{&ЊǠ̹T6=+,ν1g #T \I$hܯI\oRfg}hTE06=F˪9hsG;.*(Bo sŕ\ ߔ{ +Ԯ~yfX*\n!lx6EdЃ_Js* X (b\'y'ajqVBs04݆yHSoHڥf Wnai-PC-ok妗ֽpFspB db] rhL⣄ZtV@@)~" tas4Rt+lAfm{蝝%zMg=2ֈNV" [j9u{VdP1u^-jrkav%A΃a;r-v >DbܠMNCfTԜ˰r'tn j,N^"H^,>9S]ld:- GiS("IV%Mgb_'vMp3mRcz w[ Lk=x҄EE-|fo&i d;Eaې1@vY~^_KQ}*7=k91_rr~fT"UbghE=zs]8nQպm`mo-JIc*Jt{-$_"SƗ Ѐ PKk#DKb$23vf/O2Cx?7bwyḭyrʮ*Q_,R蓕4CUj>V^p:Tj?㿙=e 8@Jue߮CEaw|gLL!vSJ+cOq>Aܽ 9QJQdsluUڝA;6rYft%Y6UpsZ8>c+1!XQdNUX Ļ}>TPšvJfן&T"hj$W2V$/Hp-+Îc؟6/]poeHESj^Ө_ NA:α(|_ ~'4܊ON@ q5T##GRV %[ʩ\ ?↟Yu#9$WEUKKs:i_!VTI].-0 !a>ʘ&xcĎ^0K}IVDLÙH/VpR8 R>(ܠ<`>Q~̼|/1}-N(mzx(3"N6bs0HGx '+[{<0 QO~bEOj"O7PնI3+Mzm d̒Ezt2ȧo`qSQd=&"ybQ8ݎBlk5wR +0ywgr>8FyoWu^Gnԇ]t޲nt5;ŬZ r7na]`̯F%|n D4r.-gA)D{y=OH)Yyp;|{yx}Xv =Ifʍ\8}k^*bFfxnbq daY!a*GK*9>2676}YG(%7_gn (A 1,e ^=hTRB / B?QJTZuț{6?n/xҵX Ϲs0((SzP5 c%ָ$R4G[QMKӫ̸,&UP4V:ڈ gF)$2IFi[fۗT?D'8KmfTrU&Eg"!`L D6M?bDЍs.|Uͯah62_ݏ*8E@Wis }a|!zIuuI=BI )宗OZ@?Lt˅q (6Ez6^ǒ{7]?, 7fOZ뽋,D/ ;$Ѽ]0aYO;cgj Vv& k+1)w!|9o!qc`C HTS|oZze'VJ,2cC3B##15C"̐__e{,E4״uz}'(w(;Eqi9 X%B2)ܲT.U:a.Cߞ`H1I#ZJ *7PuYb9}O="%LM:Pjޘ:V pdw@mb\#mqI#;j[9TDJiR\bU>=TmoFP Ts8W\`yc&o'lR13xspٷDmB6T sF6PPbIX٦/m#QZXץ)ڮ%^= .`YD FMG!j iVˀP/e`3}f3 FE\59YwWH@]`,KgIwb0U?M4 taP똧ܕ7%v=*\e)iyQǕyYHY, 9Hc5eANuvDLsqGcآw'YO{pHJ!UuA&gN3&^1/4Yȑg8 I#x.I|ʙ]r$yΟ{Μh[0x7El?ck;?5:ӛ[].9YJ`i:aC85W7)V|/rҌk!Onj-$BqQ'"yܖ, qx}qbug:m,wc3.E`㼘 w w_FkbI2PX^ u}+@p\L*>Z!UKm|{v1;|L᡹F2&WزKmlR:X1s xC {6Ɵ?{J3Nƴ47V*~k͟7|s'[thXX~ W8grF[S!Ÿq&K*DI~cS;i2X˛)t2H<Fq)SʨH ͟=G,>SJL&1D5e{J>}=V~r: ZW@+ORh'-]s! 1NWK_u%u\ɰ rd+APv#w6:ҥ@8pyRӛhYПlǟ4TK5MW>64j/ADSvYY/3wdbsҟX Vo00/?CJ]>9X 7e&ƖRV  !6hۧ*N@} jbuW5ud%zLP C*{k}[׍a'C?S!Bacr'`/ؒtD&{+~Y?6U1W%>#?b4P}K:USUcyaC .1ێ],Kx8ب~@kR#0Vl5#L\Bfh*q'mvaI<^EjJHiWDYcAA947u3Zi=e I"}2k|B2 \S\ 8 a m8k&gOuZS*IL0bR#SɋK|ʮ?(,(1lco+ܫUhMo.P\~$#G4ăvh e нJ-b{+yO g*e?ֲcpͺ*fȄcFJ44L{=@yiǴ52>~6(% ?$؝9QC*܁H<HM ,ЬBY:Joö?GZlpOBG8p縳 ;}YU}L91~$SB/xHnDqxZ{`H-^=LԎ$ uj tSH5$Qa˗o1[-pIK3B͓BjMJyz`~8h ^}L(z$W{{5,:W΋M-;?Wd2.畕#R-IsIӁ2;Oըoz.<-fFOF?,Ikx:B,~];.u8'Nȷܱ*f_uϹЕ" {QuS/ d>؂g3pOYZ߈'^\8 /7mg a6{/Ei.JazLrD}e;oTW/v;h^qhгL9c""2 oiE2rR-ʛ3ZNCCi. ȠXqՇP;FyD@nvf *\ tFM^Pfs#a5C~BB:ʄ2ȆfP짔^k B'a?=ZOyJc!*\":@ha3_Ǘ״i1Ww>[ߒԔgmc `D+48Hn gfmɼI%Eh5S`iEeH, KY- oЇp:@dIN2S4}5Hńx -#hCDFbQR}V`LFOýty47gt2ean(X\)L'9I4ymД#g9CGDKy2>C!.9c/'iugmNxXwݛ^EgۆT3Xǜ FfrwK QmR(սE#GCC Z^f|ȟ(2)^ZJ,Bvh`;̟,ɯcBX"w6g) x+bZs%Ƴb^N].lu8x\Jk:wr]3Ph2e!?qd.V|G^ލ2I:>W4@~K=n&^œ_ zaoz|>-D_ Zin\rQLj7mßdj,Tم[B$o}C)%ED!_uJGT@Ec19 ZY6/Kͧ!Z'C,WL ں*UKb+3?Sχ2.;45MPLD <:!'Y$ *hfd Ys 2i"Q7N/65`I~ȚCDZen刕rIDNW-x_qw)o3d.p,L8~Ko`q%_L\ 矠rS5-PZ@\ mX~sPCZ;>*2ўo} b Ȉ ^pC'S"*u_'Jl?dhX $ 6J½`{Κ\h>T/{`H](9nUgDm޷5/2'j BL$׆}S(25~Y|&ŐO$^"6({>I'o콘é˓pOP`c$3y$Eئ[T`ٖ+un*GvT)/QtWbEGo"2(w 9 Mc~cΛl􏖤F֩Hb`ʏ<-*~AX{z"ѴufG*+ݒC[VJ'}oO%Z گ0}H!vHNw{b%e(L&7UmH 䛒7ΗƙwmGX /'+|Rr}ymdhIW1tŗ )Y9_pQDv>\Iš9Rhl#&3YZxHJ}PJ++x{iJ-y uM}/2Urv94Q3MuO7 R*ԲNǛQOs#w+S)D'2aMx#t!'lT+AaJM4ZԂo4["]mӑwDNit™<8mBJݘxɣ*:Qpp'ɦS){&!;&ZͽhTVu{͒n3Oho<}>"Wi#|Ѫ7^xvf/I썾> ߫!"V$0 Dͽ]DCXFC>.<ʹnɊ̪ЌKt\ûV=t3 _iBG^ȚnQp4mޕ'/tm>uݠL)SaրTQх#W/]:rT#N4 ySOgfϻ3ԡ"禀yiv6Dy}ަY#a;S֎f]ati3vׄn _Z?aRh.!;$˔fUbÂe&qnR8F /3sAU"fԬ;{w1ie/wxٝ1j'`&p]x@! n,o~lǯ[;'=z,n2Tf)[jŽs+a3>nU|(%<%(sO{MSD}X8uqpkB!7tA^HVZ1FV}w՚"]\}mϞƦUWW V:iY_MuY*wϙ1W}梡=Q9:}c&qRa,Ӫ >2t4wKW̭BG\VSY]TDTW_&7j { A q~Ds\ cB & GzsI4i7E÷wI<~x9XHʎ[cKoӬϹF g١3Gz}0%^Tyš䋂Mتm 瑪(]#sJoi7U7J8GuQIi: ~;&<_.AteA2{KU-[bi9:`1 )Bl&8֧$ {j8DoVU ȐXekh [F2'T0Ww¼CR-1fCǧ᱈K5 kN^ƈ씱}9-"|.>9uMOE#.|[Am\ZL0QO=rkc@?6|(dg=yxYW@V mym'cI6qɛn)êلMMGgsܐ 5ye*؏SߵĘ<"MF $8WעlXuGJ(ٹlǥR})mLſ7&O>jjb.7%n)\_?ruql`; )<-߇4ONpg;L(y^S'C b%DgU11MՁ8֔|pQ~;Z'YMX gzu8 bj$d8e|ppGGx@i~9d+4ׇYzHK cS jnI9Qȑv^dSF:XYS_n 呂0-i[.EK1t^],GPj<} 3AkJkёVmAra1byjˆP 5W(3dv ͋"W!12CoQT!f]QeQ GW_dr 2mC]Tp"- 蛉1١UU@* /H> %[]&戃Zu 9\zP3>qgΨ4P2y!+GFk{h>ƤMw/0mjo˴edFBvƏ`e! a}itbѿ%z72s7.ˢe 1 7r&~, O(7e bO߼BkS $NaOgT55gXW uT3~5V HuyH`ž }R* z)NMO|F"}s"b!l<598"$wAtGp$ojh)ɥRL"Syڰn˴ BSQ-ψ|g. ^p'=P2?I2j nwW#aB sA3`#RZNwql`=EjK8?I@R(6"-`tq亁ou|ڪHQQ>T |( yL|/+ wh̿IX*\ž((j-'G`};0M[G]4rƇ?x v;}W߃LٝʝqbS Cy@u|}f65 :o3٠1SFwMCAD=DhvÆ+YYؕ/PgaSυ!$3:c9D|YsHt8X rEOz^jWo] K38Nm]ބh 52.`Jݣo"8AV)!:4j|KەMPTP8ەy ʹrER|B0grg ~x<#ߗxm 87vU O' k^(G~wIͧ5$fj!3Kќ"8yNxKiL^PW]v! nO@M>lNGMyT}Csp<6|Yl $G1-f1H6 j)9xLSpD*F1?|j>J54ћE>j M#\lǽw `/h3}bյ. 9kjM<1}fϐq'EbA/!A4Z޳E\MFZ,GA.{XTd"cDN>UK.el]=VY <*IO|3LkP9AmWRA*r!d,Q݊ WK#(46YelsU(?,'*XG7~ V *e.qxyY]_DVs[犌*]ʭEcjÂ~JʤCwbEp_ˎ`+O:Os!+^LSxMڏeW7=,e_Ddeθ^1~T"}30 wz4wB;p]sB%*s 26Ij7 >p,7A'%u3I `Ӄ ^+XZJ ,I{>ZNlW;J%_uUOdb阱(~˕ E^ !̝_դߡ']+krxz}n7٩řbb+3ֹ>+qكg^MdTU'+ؐ?H}4>G09yՏcM9?^Wy:|n~2tm޷{x$ٱʗMACuP}u!67*eu×lb Z"XpK 1ll2SX]CLL)W!RޟԓW{ DUM P6)C 9U}Of*uD szkM= r/GEM2}]V,> stream xڍP\[. ]Kc www]ww NG3zNU-_kkWP3Z@̀R 3+@\QʎLCr#F:9 `? ĝ./2 S;E j`cce0uYr0FvyIO9/w= dn (X_2! vqqcaqwwg6wf8Y 1A.53 h0@wg4 kru"/` %9@]Vm#ؘ߁@࿜M!`O ` ]<\`߆vΐS7Sً_DU/ ӞřdEa^, .ȿ9_ڂ!`%la WM0(+ɋ?2+ t=̭Y~td-~|i M݀'WFll h#'h7~9|'@{lϿ _eyeUg o&;+ (*`,ؗ)`Οݠw,% ip܀w )W;Դ?jS{?/uuy"e k {g Wʺ(c9K<* s\ف@3`bcef۾/K|YN) 6X0vwS''SOd"sq^V,`ˋ =_% rsXdF#d `17]+ rX\%b|k| X/,.n_ #//@ClBokDݙv'giv蘼:\#Ug}sM\ݖY!!5I8Amz yi oph) wGG@[]r4y<*8e_vUWGy(aՌ1,7˞'wa"E>Ν|&K`@=(`7VMHMG@ s=6[lwhQGlH%9 Z݀>o 덨77^R ߵCu=z[UI X0|n]K2@fhc럣޿vJE)etP_*<*tiE?2+"R U%c-{I1y{!v,?}m̂Vq̫MiO=d _+[GllC4+GQ[0У;o8=gڿq7ʺp@IȑY8w2](KZЬ3Tkb|vU3&Q~ :%<_XHdxD CHcnrL'VԎ)NIf71*zEp<%A̒V3 {#*{0VY+qɗݾV"K[ u{!5P4F=Բ[CyU,o[u8OFG z}2$YH0Dy,NJt[fF'҂mn8n(G`}G 'rْ;tL*O'J$<: {^bs(E7y۞<=^]c?هh{Ȓe8j0ٚwX2#3jpb6,K> }-"V@O\WQu; ۰yRMi&+k9DM % b#l k^C㾬zyP ,uowƛbWyh<q #!r1ĵp0P8FD$ (eқ).&B,,rְxJ#bOt¼h1:FBap[J{F`v Ź܄=/'W9M1u: lxjkDJ|j Yb8?RąO3kIbŃ@{pvxE#^\L gȗ ѤFИR^)[~5R}#eߗ]`,VQ0rыU[xž9O0Oʖbt0▒D:PYctm R^єZO/?X>Q̩q";x3ɢ3AC-DV=O{D+ltc-:8ofkuov㨲îi]΁6O Gv`bx4A_Aq8H* |<{̔/#A8N&!gT/=灯&(tx@wp[pkaQUH~5R8<ׯ[ 1]k":mk;lGjGꢙJMyXCZ饀6w\bq" *8LȰQ5C/,0rM]īr@5"ҝs@fRi܇Ka靈:}\M0.}*tәǮ (Ez yDHU3\;h? œy%V<|[ 2L`P2&YvC78rҤlUbۍ0\k]ONŲ\B7jY` 1L`spj]>e8?u~)| !mL16r WSغFE]eD8ll>x 05E&ћi-ǮųOb-}&z'?+U X9.`-wٙ;WǂXCڲ ~H 񫘘ֵX%TIn@rCKsĥf I剖gkI7*EM}Z}T>2\I ]f\' dE/G~y jm?Mlk$ JleoMg@\SvZ~{E " ϫ?=iѡ.p_ԓ* zz>BRh\W'^e+ jEf(nNꈎCrGMH M8^O߰K“a*/aES^g vą)v׶^񆬠M I+krXT[ Klz9RURSo^[ Tq9~ j%ᅧ9 [| $zBji)-t X8M'i&G^Ec#>ᙦOXe0摺d p6oY=v$bmL Iu<4nz`@x#JYP1lu?*R}z8>x ~˟pKToڄ%aBg}őɶaHLk^K/jV.`bU-R)t^\j $itbO; 눥viv@`TרC4䑹5i~r+ TV=D k4WBMI 8lE) }Hu9$&y$C_fǷ-rX{w 7֍~!C[f'Tq`Q^ڥU[PT^sEFܮ3߫{ PJƖEnIC -HO۲KҪ֟*Sydž0moc3ӁUlļ1-09 (ؾM=~}Qo4@ N?C2q.?!QPVuG$TEN nl%.p%W4PKV*ۢ1QPا>=F_.QLV!'Qdd$QgsMg^tGq[釟lP!ۯ]Z'=w٪dzffdTd]^9In*@?E^`D6ԁ?rgW+^sFgVO{F SO7#~Lj֝* 'gղ{ghIEڄ."~M!}K$J=_ Hߚ'FswGh"z|-E|\8*"jULipkq1oNA1y'b!NٜꡜDFFl#jp]-۱9.Yz6r<'{fd4#_ W_U;PKԾ}N"(LD匋Gt]/V#w?}zݯIkKkޛk=@8֛O|1a%! ?ӷE뿧rQF?:I-FP%Y>ijM K)q8!ӶВph>/ڑB#OJ[ʕܚAu1p&ȴlV4*RCv|>GSguka1Zs;#1Nqn=pY&ݠDv2`8.0sѻX ; f"*z`df+DT)˜2ɔ>_V[iuhށmɛ&CM "T!Y%]e4< xidG0r85iY"TK Oz^*eaM ^3:wc&<I {EX#05K #gɮq.NXOIwsWdK +ÞOŽ&QFCz@\h c._gXt3{jr"x2[B[gQ,'e ,ﯩys %V| 9Y;^Pyje1GwܞDv<ܾ{!J56Eg72u}l8j)@8G$!>?M&pd<=;j;*-\Ilvg'kwNv[~J6PFkԋ΍HϧH$|%6;9m^|SIr{],5,2OfP\=+=* TwOIDO3 +j~#HXdڸe ENQ[>E{oTb9) Fm~/g֗4VLjC:fla}}]O|W~XDcy v%T`U0lYgX+4));>]$/X5|j=ؐ01@?wm@S~J*y} Vlr" cjvzo$u#{k;wl~POKһ ׇ}h}ruh@|a豂H8 $9NM^͘'ٳWyʏ9aax9TG5ﱟ"v dޫcLiJwΧ:*_+ #t#ʐ_lPh\7Ć)k aκ@N#f9)v"wCC ,giJncl2214:js4s)+8@ոph .,u'++`&o:z(d௯NivkY[}JlQ %:e0$|mPpEro:'c߉ ϖR0F>NhyʝIQ=Yp/oG!TCC|0Ke< oHcq*?]uX}}7HuA!^X}I Ϲ6.Krsz%Q?P .V:?˛啌 {m iXR'%c>bk>!+fU j/$%vثSaW{ E؄ :&Xjd_ j$biuSR.WSÞR*-Zk'M;0A?5>?S bdyr]<pRSm:op))aN?l?t,)u|N{#t X3@\O~\ Aԫ- 1Y_c]vWc)ؗ{QT RTx( @qy" NA @' F p0 =B؊ nZB[0~3E #7` 4U 9tW4SaoU4-a7$gqZ;1ԡ %e̲T'p(|Ske}IO-%-P%-{9[ˏ݁X†_YƨR aIdX%v+##7(^c@S9O=VsjobZ3zd_ 8i#7=uޫt-ƚnv5񹺰Cܕ4X#O |#'x')QadJm>äFSJK9Е%1bpZ?ZlM;2WaLN P>Bn\b>k+e8/rn&^JdnFlDc)n/y4h\!>}_M I#䊍J0B2ۺlƜ∇(f`k !q3?SV&7+63"Ayݮ\8E^ޝYX=BkJU>{U*[*b)fG'XU|{A>f}/.oi㼖B`,QRJ̺&^7 G Mh=FQh!j[rBc?-A/ApmClX%T6tE9Ki.FTM$CT0Pdu$9H5>LNm>*z#8@8^b)Rx/{g3Z"1m:eAҍF"pnhſG:~+7o\,|6OoX[ƍy)RN:#D S~(GIH5şlbWj;KGuA0NU ޤ7s%Lr*+:w= kUY/-w2F_<"9I%9ךBK'=OSֲj;w{3XW)cUNs<&˧Q41dv|T3Ev2K'P`FP:SmMTt񳭐6@=Rr*%^ʯ:ƩW[k&av%Q_q׈y=mމˉs^1g^|@z44U"ӂ] `fxb}cڹ]Qg'VZFͥE>9+v$[me; .R@xzoP}1NupAM6W!b \vhfxwHQ>o0t<~\{mJ,xl%4rfe;#[hψ>P#\/Nm!ӎzyn3X β(3Q@bZIQ f z]HJ)g@f5VAzͰZTfZ}|޲2Л HێI¡>Ԭ1w OkHBr5ڂg]aL 5H:ŀ_){ATh1Ig-=f`ZR|P޺gDJ2 x(DnTi5a2<{`I*1G?l* S d t yYGiy, q4{r] Q?y }uYE{p:F"8JPb'bw$-g;֮>yJ8 Fޤo+w FUQf9%::s͏ o߱3s)QӭiT 2>ULƿcD$QH']X1들2ɶXUJ1x֞lr#S#嫣>( )j ]\T5|YE v_eѕa1l^}CJ`N#*; endstream endobj 52 0 obj << /Length1 2117 /Length2 12185 /Length3 0 /Length 13473 /Filter /FlateDecode >> stream xڍvuXk/%- )ݍ0t3tww!HHH74yƽo?55Vu :)X++hh@  ȎJCaѠh]e# 6@e&=@`g@ :8$Lܬ,9{ *%76>>v`g+=@b f@V`@YYYL\X-0ܭ 5 l6@Os,4 K+Uwg0*]Nf`g4?@]VXo&`ca'rs4[قR ,췡jW&)QU trrXw%IX9A{s6V\Y5\P,, YNK[ `mkezgWPfV lae':T 6CYlBId噙UZERGBQ9xفfv7߁TLSȿ\e| "gO;` 7rw\mm?6P B] m {fVv[+ 1|,\#e[?U~N uPx:ܗƉ[:9=ƃkl^\aҨSb2Α/w"]L%QtΙJ:E\JH^*: M3ϢgXXypOǞb5ݘj R ~X,uvԘŮLhKճmw;τ(3) rZLh/%MH}鳆wfq$4yZLoaavc` Fcqq.IQAړ➉㳄$\+ ۲uSb|CQvߚ:_h]`V9Mui^NMMۺ|S>PU , cZq:n$rHL"v ]՝oW#~"@n:xaKӣӸS5WdFI/APq*H(wFo@i%"{Ȃax]nzţ0~ZImGT_Co\Ok+Jb3#*$/Cc? ' kۋE4x&QY-ll6A[)aX ֪*(*lu#[$d$e֫sCPfQB\3$b2^[g ULFeJ-$9O\ȥ1.ToY ` ;[Fc8L-?s^WYpJN,bx6}΅F |79`J5l ȡ) /55<$n=6C݋ͺJRX)*wd^X-f iqwfV}Kb"K-)6Uw#™^ HZM]BD+6=W˜cd?;uVn?e(/e~ ̡f.Z|<<{%@4 W7ىUҌc!s>.]U)<]/U ^|l)'yPY }?]+WI?{ރlaˋOQ Ȱx'W>a׊W@G>$IJA?R;$0AR uKRAt;NٰiLKG$j)DT/<J2d)H HjX2[+ 5wA0f󠸀p^,y"&:>B8k;]փ_U%s~:vSMWKtJ\6CP n_Ԏa9-H:gt6 %l}we!2T ͙զ#yOvG9ϛjAY@(nw06qv"p15mmžZLdˑp9QTy1S>*GCc 0 ) w1 p|;'XħxeHјILh*UbX# FuXRRM;)s5;p}f+o;?6 !Lf Kn ٔnrC+yryc=HMfISbx!'1y7h<}ɤ߬, yDdi7{$eC[y1'WfK-qKT;= $#ΑouL& L+H\,'lq&`!IS\t.۬P4-Sc ϭneD$[(Yb c%PX~79R 'Zpjs$e-~}8xysi6VҨ"S32ej;P Lk x8U'&H}b:S !6P6K !e@O~2Wb&3wZD[ Yx>Q4nSG_7֕%/X7JtzG]w`ЂOmvUzFKgү~TpBƃL?",Kf^;} 7}gɅ)_Vh.tS>zW%0!}R˹^@4HTI%1sCX.~xsx0f{YY+@s 1yX(YcSEKqO 8hL,BVCOn-䁀ҀD4<{CK+4S?@'IORRA(4bV#lRC{oֹn2m!A'/^ˮn矺}9KVizy_J!aJkKzhh%y3zTyJ~ X$ͧ?{oD-_盒K ֪kat˰v -N?_O>H=JIMrRI1w\~Z>ձ{9*[ ,|Ό3@qonkxUT 3&r 7Nc4]ccj'%!3)qyOk|=|TtNzj8SӄÑQ1{&yFVDj_2ν3eTaNtrQlnv:=c '*kb0S#ly/u0" sҊRQ@QI 8)"^mrHP)gۧQ. C'ʭj`/ۥ[v>cb^M^{px%  jGs˕T]nIܠꖟZ\ZlϜyYI+_ha17 tNUDH r=Gjf) X^0[L%y ypa>:?;(ƓL0xɭҙt0mt2=,άWǻqHx&{c'|.jYTAVD 3 |ǏC g`SiP`Elt幆df.8Yb~beJYLM*QCl3xcZ˨/1uOf!S9R)JEWX aTi|L?aE6&j-誚) que{6D[FIgFw)}TxR 09O\GdibDrkoNcX,ڜs% y FƤLIw*d bGThj9s-ڥ@3='| _ܛʬʯ;^O60N\{oByXDY^̒ɌbWD\EHwG{Į_31 =LBETm))3=kv7? ,y*2{ƤdjG1%q.h܎|i*N>O Sigo[Zd\:YBSE%7j_GsP;[ws>ODUqSQ֐} KғQD^b2-&c2.rj3x 3O5e \F!a͖2F~-Bs17h-n}}b1$\}ۏU?"~D%АGw`ksSIj8t#RMF_['9#m؝9H5^BrvxJU\dVbG|yO41 SSq#zӫ,=Ԩ3۟r[Ynɬ+"i W0 Vzg8FuJ_>S<wX7Nb8|g8$d д;R?rïb7Ct [9cFL0]b|";hqdc6ڋV0;KŁ~6+žhp\eAkeop#H,ppPHVWe҉\Hbѣrͱxr:˯-b>F0\ .KԘ]&Ӄ?uI!]{JÝp$fAhJ6scz.Aj'vm(g GD.^vhʼn\#g&i3Q79N'i)_T_G=vk:.eN\W]>cebo'@n!k,)G&_ oq:Y&x񮄩šG.:Z|?p뜿?dPtOwmc4JɗoDxa13*%Vn zHHF o.C! H7֗E?5R;+P +ex.:(dӥTp]c!ulT~{sAx<()_;-P ͋7I/mncm=!r4ʊ'{NXnF c7ǟP]ޡ-.6_`F&H@|eK'-Ewzp G(6R;:qW0eO޺n χ ѽNM1LWee%Yy#w[=ZGCɨ bI@$6Q5i[J NMOixZʺh&[;['oV6IwUtAe~wߊ3,p ʗqoðՊN&5W"6Sꚩ|i.FF1sOh8b`uq5/[w_?k?%&5g]%{ķk?URոt -h9u:lXOR>*UoB'ݩG#-tt)lm? ooGߛn%w<o5ͅJ-O4)z /D)](&d6΁ŧlDV8But$'%[+Rs*+w% |d'%}AtKEyE"0Z$ -rFdY6k $ irNM_MkP^ EyIwYq :[1 Ȋ8l(1bvz:ӜkfSBO9ߧۀZo997sە 23Ze Fi#"MLK9üQەܸ~%Z%P),*DD4I :ʰi>aCSUryGyRಶW=g0٥M >XC,hppvۀr%V3}-dH_Iۙ)|"Ad N/3gGa Et)==+WRC1yQR2,s6`6ooTPS0W0Ҥ{e;~2χ+:* pŶÄ6N8aK0")k>C IuIJt8k84 Rܨ*#3[kO%War;&mu@)NO\CW xaLU8lF{sjKcS=jtyH-?ah,f2 NC1Ly6L?JTY<<-qȶ(:rZ~J @MPԝg{5:|Ńiv^|>*G[b"bkYkgdEG6z"Lx`Jm\{:P1puq4'd$k퀣Goiy<9KAsZ!$zQuCs+ҽU,c Rӌω3j=3C?,H9 ]-qGX^Sp,)R)gg>%0Hs.E6|sRNTw" !q29D5mg|T׿'%22NzcT ]#/z T$J{w"tOaV`򮭦w:{EM0$.N"_? V|}5"p g}%ZB1~:wI:}T!LCEʊ+AiE2 .lHs3cjB`[F6|ѽWd엙ik͙ŷbe;" jl^/H_hT~X%g iG񵱐+ol (nN!Jw^"tTD-JWקmZ%#/&Tծ^2Lbm8Ѵ7?ʖ܈">ɏsر)w=܅`K#i AtwHFH|ϋn[[Wp!]sBc_.?tBL!5E롔3׾P}7PpI齳㶎RUyX@J 1,ň/FD$FRM$h^fA"c3TiRn)D"St1 BnjAI"`c \r 73"2<yEEeD\޲)sZ'Ţ*D!kKԜl4m.sR ~<7ʕ"<7} l~r}l5]UcL֑~jgY{ !m_~ J`<|͒Ʈt&ɗ½n_z0 \oIC'Aǹ",򚾶RӾVh5O"8ⳇE>Z5'"εDUU&W6Zkb> #+FM'.L| }mY+DY**ߣ:\yi>gHZ&i'N\!%#&oj@Xq-nh *- 7O'X4]~ۆB]b+oX+u\3N\WQ!-$pwV/6 DLTdH9vIO]i96{%h*2R$;:eaq8cP=Qev[h`WBXŃ&v3MrM\\W m"H'ǃI>Ǯ9U.V C!bjG ~{E%y`{~*=_e>j/x¢ pwQ|O>"tHL' mm`^~e}GOH>Ciǡ^nN*bP:K|o+֋,-P6,Yޭp,9{;'HT #Ѥn+QF׷gNv A"ҡ ڳƉJg8sF"HTo7>2W !X N[-@Kr$kj[n YÃmCx*~أxZG5,*Hn-W j/iVևZ77.P‹B+J.,ÿ&/}]֝:=׺LG{QDW'dge;%ӣ @$z`Iy5GfId"jq 7Q0Vۧ1pݠHë!(NIikDŎ.OȞd̠0d)&5Px{)~y.5F(. ݰY]mĶ_ aҭSۨ()ge='rBW" T+``elա64B=޴# $Iqޱ'[zHgdzsP?@5bSou~/N>v69&f{9k2H3Y8CnPoܫ"OF, z@7 YL'_s)ydiI؋3>հ:nΉ#Vg9z |bic9l矂x .8߅ ~WyS?5bkȂhC2rhsB.\djfӛD bXV['%fG\l4U\sWunҫ\_(H540RnHu4/[}ZE/ߧ/#TeuϳRY;!NBV6Ni铔h?)^⳿N>|d`M,ٛ[h$t8RǍi_bi51HL}0x C"He4b\K|"~B2qiO{4X_>pkQyBYi`l7`Ɍ-.ȱ>@1H(¾k&rMOklH|J'X!5OݥZ`' \Vge/d , iw_ğ?luPc2!-^~DT.?X"\Ѷ2Px4C!ydRR+OߍSg OfXcn?b^7+^u̘hK#Np`d>p \+)Ty *SAPoF Zjn ',B 3.^Lp찐Cs!WuzN5=e<))l v{f&s]ͩYQQЖ_nr"4"E }|4tFhyY|dcͣ_7{N\SJ^nPJj19IгsI뮟н%MT8T¢}% ¡ ԀzdCh'^TE|#Q8۬n dW]/l&.6%? 5mEc^qeەK\Fi Ce4|`^ᐍtda`fO@F̋Pk/Q8YY ǏѰ{?4%WLq h;-gUnUӴ<@MiMa*/-xvIVHH 7HKqcGn]]VP_e6^ 2rݔJg\4oΎ4Z{x{BfE ub&[@g/su QA:=FrS`>֯?=&w̯/OP5cs͒Q!^=SkqhD,_?`_` ̶7I+S/q'ʟtw2/I1A{_Pw#X0(}2ljuZ.KOgVZ%8P" mEjW5]=}qK&/ ^W[T-xqtZ 7l S1 ] TG7_-3B[_-EI˩Kbi1k_J$p`Rq:j 3P]>$ؼSL'ZFXgzf5ccݫ4~؟4*Ky[ؒ-;qDZQ;+R66ԯ_NAbNLf/h80baib80kxgp5X>PSWcKjm| c s['"ѬjƦgتM(gYI+ysNژOf$k H=唽`zc0 LI[>)ic)bl۠^/:Pq0}ZwޚmRF΃H$oOEz ΗLska.w.pYsQ.^ endstream endobj 54 0 obj << /Length1 1382 /Length2 6009 /Length3 0 /Length 6959 /Filter /FlateDecode >> stream xڍxTT6Rn[A$aaARJA:$QR@ZZAB) }}9oZ{s]s]{fmN6cA%=T@ d]cK @D&04 ꁂ!2P*"]O8 "HȈHʀ@($7!`p8U0'g4߷(A=`0n00FB`P?RqFen(!< C;FP A&D 8P9ho0„x":`Cu6W?ѿ!G } xc[J3P;%(+ f*H77("՟* 컯uE a_c8x "`H\Dtc,+#uO8/z1*Ebo9/B`nB1jPB8a-(r[t/; :X0z`@aDqP,"S C; H s,FjG{Y '߹R37ҡ6ryƪof~}[lV/<*|oʨo>X0,Qu,[̈́_ڢé_Bygـ;ӑ Fvg2]]wpI/9:%TYb^͡XZ)Ƕװ42U7$9iaqEScm  Uw'w6֔Fvf/^,DU}lM?SJ#%p1|uyU_nG)\.x+,>RI8Vlx.^oMGqx|dM!OKxj %fÛf/LrZ0ѰJi^(vieM$~%,GTX2Y'J`4yVAe-7*590X09FzsG -7N$ѫ:pD}>ZViC7>V-n u+OfхLgrQ^=exFo=6C3WLggdKoulxͳJR6i&2ͭ). {"2Fs4T9CKٶG%FJ 8>hw3^Vwun&fעXLȅnwtn#j]2J $w~m\>TLނ'2Qߙy=;[ʁ ۮ K+F{<36 l˫nXcd0 ?ԄQ$,zݤ<X\ڗ|'Yw`wN攅v=R`Ҹɮ!H\d ߺIP.el*fF̗jd#9߲Gw v#@)O7}oZ}){ѪXn }[703h9V\&jx0ߢ Ӽ*2 A<2k|V$:vay.FҳkJ'&zB9@,?Bz`ݔ~ǛR%?]|MBz?e2<({2̐tt0-&Q*A}mIː,|{ұ3Z .{ڧT>.mBx"uϿjUu ህ5"'Gw&,;W𠂟EIc $Cboe8D~)FƧ[TsQ'sb{lÚVP{hh H*_}{. ilLTXn=YÓ?/H1kNBv _7_dz㣒},pF~\dRUz ]PZU&}PUGWe smNi[-zZBӷRnR{^WU~9Ca !QL1(WBkצ`G #hMt28EşI;[ͷb݃dp"/!btFÌIG*EoV ݃mUXU N޻/˦9X𾉛:N<0 < ?#`ЋʖR1])XN\K8Pdڦyf mar&PQ:(w-[JMj1~7٨XWpGi*Hl͐f[!ǡZQmckj+z-Ytw<嬭JU\yY`X͢1[tfDrrXޭ=8^Ԓ+;p 7}b)+~FZf]R?f(Toisޙ q;ZIm}E5L0BoȸIk^Zѹ-Z;EJ&2C\ajŧqSzʁzrI_9)s9js ;b^rkJtҝ,N>@M^Ƭ|Yׇ<;D] )ɻ P,= 5m5x?rmofS^4m#jj'y0\;|QLY?6^wn_0qFWsv).$'Ĕ(/RK01n뾬 ' MgOV-5YER5[l,'HpMT]82cTp?h6XTkP;]8-О7pnxhՂ5lBphB"ϼn&{=\f2atUBIq t3ΩƳdI7_{}j#CUpڐt< i 1`pIdا~N'Xe_xo7^3NK9AnXp:PH~t8}xjRn7 j{y/yzu{ݑ q"j5//Y$cLQf+|7?Ī_jx8Ḧ Kh!x^rc^*?cO ,l} 2^c=foƜ|cPCB#.L[~pnuP͓ IvnPdGfPp(b^mV(H܊➊M2*\T`|9`gjDnJ4i1WUlY=2?H_xH4 .}bj ?p:!RߔQA'AH]DUܬJ>TKʇ_UtbXr=g)%cZ|NoIJ಄##'κ%}m@#ͯ&YG+o}֚'pc y~\2鵣WN)1yc '6 )bߺo5y"q8^h ,ǃ{Kt3]h4p_Ghpk䟝7pcJ wlwDLF3TYG1-QX̩M.m *l>{kN3 9Q\Z1=@>q|"lVRQ^d?q`pȊfZ'ƹ;ޒw).J#gf},jT-gD36F=$&a ,O: ߣL KlX|㝷Ǽ0R&\_|`#ܻv"Z æ,=1nqӃҠzGYwvÎ9W ތnz /veə-+Zt*W*8uynUr<3:sRtBMzru.j)Ͳvd^9o.֚XAfB1.q+Ux1h/O$Z{MS*oҏ|>ZxBޭͪ*1Iڱ,kj'nmV2%1j5Zfk^D~MZ/F@ o\OT/Έg8)}(w\0jC"vWSV ߯z5e!w|%+l\> m+":.uznĞt?@&$GfY*=L : QrF2[7 N&:s*9~Z3殿ىv(w%~zD,-;6>ǻ%n4x𲒝^ɓ(S ,~߷P*wH@]Z5æ}sƓ:c8eK)ŀESJuaL:LtBNIK-r2hXftAtE~H$ju ;Yyۓ0I AZ] U\+ǩ>JRZg5>PG kǤ *\Z%65҉?GLX?oNמxTy9Am8 .Pؖly~aZʹ^0W@:W=cnz]kJQ~a+|; ©yA|nLy޷A8EWz:ʣi1ʏ=.8W{Fo|Rٳ*b"+6 'J2DDcD& ^|2^/9kΤ\ Hd:2PJx_]k^lv&\{2N< flέ/RssOS'd=/xHp#,UhN4.jk걀h &hk+9Va|rG_Cy TP G8u Aq "--SY&n{CSOیVw5* h,1Ehnp endstream endobj 56 0 obj << /Length1 1372 /Length2 5926 /Length3 0 /Length 6871 /Filter /FlateDecode >> stream xڍtT.(1( ! CtH0 0 Cw7%R*t7H)!sw]5k}{?{y8شdP%k88a(0C%@ 10 @j$* <(`V ~u!G8y"a6(6zpA.:B0l!`<тKr.4}; e Ѕ@nP+/M#3~"-O\ar#t]p+(r wտ࿋ m0(@KI偺í~.t= s['du`4\ Hʅ"W)+­P8ʅ| 0$>vO#0/VN'p+TU/"O<@P-W{}O'$W F¬?"oBB}w+"`P?a50Z{ ߿ߞe;x~zjZ;''xD|D@ !&.gm0U[#L>MW\ g/MZPDn& "A?@R]S./@J\Gs @6mC L:wVFAn3H_@OZiP?j08TmAW W/=m ~LPDF"Dh9 AhCZA=~+#P/$uh04}t!H$b_~B=Ia]eHE,;!xKo[u 1ggVet_ބN0_ {e.0V.Ol,VULqL%Nkx^eP-+Ӽmƾ76#@> ;k\5KJ:~hY%=[@b=uBZ 77w 8+'@LLqb&YXf"RHuC g$/ORCZ`,p Yܟм|\uq*m8`l̞sH7%`|rKS*ji-=ީA 6U睈¨Ɍެz%<4ɺqe'KH?,H$뚳]- 5;NșɧaSvaFm|CS.MXς54E}"vAffZςd)y2n"3;fC* v˛Y~Yg8^$ms/B<|5*zrvfS naGw.!8n:73BWMg>©KgM$7oCpŦ?Eld[{yD=g$b0QCZ^Ĭ󟀬Z?f'Qɑ(WOk"e\2vUV_ch,}0{V""9#K .Nu O.J3tCӵrI{|tčsK1mCCr>0q! LQII`Hgz1k&JZJ.nX׃l\Q>w"(ø=n7"bKv+c/}Va2֣[/@k hXe&VnՈ|PGt ~ 忆Qkd-YRarB@dQً b?Igbx \rs/bc,g~p;o/.f-,AVg.ۤQ{[,qjdCz4lBջ{CJrqGBR R:{Rf2oI1=aLzЪ|G)߯gfm}z˕*/?H|"=0~Xv7u%oòYq#’8;gb{ |_jϞKQǕ¿'b;lNFel *"[r ~&D$&UcFe#qTý=Ufڪy!)s͗Aiq4e.8lLI+T0dZl"s]I6y wJ)=4Ox#ob@fjx}jz(va4LR9'*8;tes :$Dĭ$F*aA]"%zh_b7S O MgVO 'H0$;ޅ+hQfa7~-7Q Eqr2\3" Vb8~=}t17U?#hM9I$ɒQ<*Z`},d-;peCC7oK83u=o;x<7k,UFˤd=˟$'vِ8&lKm.xi;5ʈ;yo#J0Fm<,-mLjtA7|\ROҒvO %N'aRN"s-n鿁GT8 7s& ~c2*bPL_.w=oL~pB^IkOa.K _UǤ{ֳ;"8]JR{z$`Dׇ<s%ML_f=plc;}OڲJV4,Vo$Fpp$oӹ"}tf2\I)M?ՠWftH;̲yןҔ7B8{7)"vj"9>~D |G. dP3N`<įYQ}dcz}FWAJ#*mmP] mb!o HXS`=*CAoO YE!f `Mk`|[Th9hds4B. |cjMpq"dp) hnwxp}I@gAy&<;00] :[r+ULF$X$8atWzn1$)I\%Og)Ua"&TaZm&X՘MOb2+)jSDp%KˋmWJktzaЗv4(%? joWާg_<8ƄV|ZYOeamvu:]WQ75Cb$5Q6;c"1N~QTǂZ%BtF>h-.~KP*, {]E=Tió)&HDe5v,~zIS϶}9-2̧a2j&`bgƗF?*UG+ 2 EZIv8\ lNi [T%=N18غ'1kԬԶS3g;BT^ambCJu>]YGl-5{n8OI~dnBdiux" a+;@srE-y5͒IcU]g,1?gcy$|3*]z9yƽg[^Ho;eEsCb\6c4|y..+L:GH#"1Ӟ +`Ư@gC5L !ovx{T=¯&%F6pi,cɆ oglf~T~.aVqGuĎj)cF)^݌s m ^M:ԵcbRII1sjP-!SbQ?opcxYd}o~T%3Q U0ts|h2xưjq$5Qӫ'eZHͯ|Q|PD9n灆غ2b:_ō&Ը *hf 0i[It;>n Aolq7x;]r{T>Kɚ"w(HzԉUèy/VI7R";(@$y3衛 ;HJq,Ch~ #V6l7͓-]&ckٮ. Y, {eCAۯ_^k[<'U.96l ,}M5R5Sk"iuOH 3ڡR,f%L:hߛrYpm=+.@]'ԥ/J÷[z\D1Zd6C]m[ՄL$,rYmin]%쉰Pe":Mf%=“)m7xVUiۭ7{=c&nQ?u=; AUYoaw=!~Aw5h/$phMcٽ zDzT#ɧ KwA_.z+[wp*THkHvUΡ}{\ :l?`]壸 ,U LIb?0)U<$SG!QjZ<KV%(5ދW}QL$$)"̄QSԪ U_&OՉf˝*JG|*lkɖ.pF| ə)ԡL]-zApN")RG/$lr ׸S>UjbF.ƼTq\2I66{roV[A6~Gǫy/ 4e`RPH[Kdu cb6pf$ /S6"@U%k+"app4iˮFv$A:+ZUE#Xv.^R endstream endobj 58 0 obj << /Length1 1558 /Length2 8829 /Length3 0 /Length 9870 /Filter /FlateDecode >> stream xڍT]6L !)5 CwKwI03P ҒJJtt 4H >}k֚ϵ\̠-@.Hn>8@Ax@~ff 7 p]S wy8||"@ GbQEilvk =<zr˃ԧѝ~Z.-Q,5x騜u}Z;LƠ@sU""r:</bU8a5o$j.ސn9)yӿ/os h-/Z@~S+!NFUɘaveU͐^-gȈn^嘧Ec fg&b =.eYo8yWkKyYiC!hU+U-4z>H'>L.|1;d԰/ʄ[c ݚxȧ|Y >Z%K=WܯS_taYf3\Ǣqyow 4 ˖ݛeij48F;Ąu|O(J ( ,t'/bdG &G"2;ӧVW|ټŽͽ[v׼kI16_iL0W>4U$zXVݹReL |*5%Fhg7ӢL;ԄTmIݠ,q BggsCKCIY`rHJkKOmtU$Ze)U%L>b?lRx1z$ʭ|r7"i /"uA&d(p\1mdHxҚ-r9WP}} U:8[qUGK\s/Z_@_@Vx1፼w 2R&dPȍ"֗Ֆl}SX˺ejoمg`Z1h\kA?%tQ+lR&|-[?_OVh_=0af9 cTQ8{r?\Wڌϝo$j3lJ'@;ݎh˹i,7QY?:w!h,ݼiİ?E OFrܮR6CGo_^w"h\6Қ3m 7?(ԗz6Q5 6MbAػ%FqsݾUKoib įi# !-}o?bӸ=u-i+. _YΗ){G)S؋yϚcq/LF^>Yp]&>dmqhQ 4 ^x (dzx׆44S,˙VZH[^S} )\{K*^??V~Bc@VFH:<ՁMV^QK Ӯ9{O i/h=,6JwGQXH#]'2b3oJ-╦ky`r- (MvݮwuD3VR+4[MArK/WeAPW62 ҌcdwX&G߲g)^;a<3V-Hbjх`u>sgXGRq!hLoG+dq:<;㔰3 ϑ6bJL1Y5=6Ta3nCAIkV͆_l踕4=M 2`eĐ$}Qǵ(ڋA;ge!ن|@ j$jҔA7~[af"k 6\s؄ob(XE}W_.3݁/H6(m y۫_-BcBbJXP|l8n!CmMImUEJazsF>g|lfN#sV<5L0J7&i.*q˫M"rUrThvoft%<0bϞv݁*aXρv癯GaM(vL/6̻ܷdB‚ئ'P=$_h&~ϧyrӄ[5{aWdhoz$JU߳lި$CtgN1&ZL[ օUM -gyHdE_sTm ` K&R&(?Oʶtq|C@rUvg)j2C~j~NCiHP7,l}Y7AFre҂8ЊsbZg͓/jLurUi UV1PɾbԥNrs"K7;`=+xPoYF(9vtx)܁%JYR[aC8 `<ϴGU- lIIal=vccD_5FXiT֊?#e.1k'֖> \iW*a|c$1S*--~=?OWx%L#VD M(ƟU.u\@xpN׼DhKZQɎEbUQΔRF4})dIO_eމ2}x:ȳ?'oQo ӗJѾ?Ѵ|WD[=J4W8>J:+xŤv+cxăM3Ӟ'$НCxfӖ E|L4R5UogRTEBd}cPGR{h'F,$[T2rDhxd7Tzfne4L=%ү4%9uls#ПS*wIO|n!ʭH߰s@S}$kYL=C/BcnK(X3gaF\hbQP=xab]mf%_Jg_>_ !bCy-=F>>&Ic.g昍gVK% L VUD(d{e2RzǓxpZxY iJzcҢ>o[ɳG $vʌ=I;UbVU1D&jd-YY_["a+,1F#"uv?#NGy:~q".BS}9+TśZ ۋ\}% A4Mn1&I% ѓ:#/I]D[-Ƶ~Mz3ڦ|gΫk? j{sFlQwELp΃tU8nx;W 4#!R1f'uANaUEg[sI2ܔߌ_(jsp]yÚ! *s-)5b6 _#}6@ oX.-_Q?K9R Ě,&4Oڒ|ZN=(}֔B<.d;[nMmDzM8#ةV ~jӆw&5r mps-PUn!h"KeX Ì*E9R' [Wێ{QfiX5Qbh{-$*1nk?w/,vNZ7Z|e^f]'gϑZ tK֨b,➌C^eI˿JJ?5) Q< c %k}r[#:rrFM0b`9{ Qp9!})<062Ӕ%"j8m\}ZoS9UޝI/gR0}6zjaL/Q>hPieByf#Su1[R'-y%{YogXY]*OI j +~Wc,rd^I(!8Pϟh}3cQ$}XsZ>.Di5ok7,/CḠ.0N\+㕚H,oNqș8b$RY)to9€{ʢj"^MQՠ4*Y<ތ& Qw (W(…X,-)CJâ3r0~EP;WA Hu\f3<ǎvtŢpH?FU,S|ftE7/:j!y_b*My]'5#~fO3TSIIOK?|)YC~5qKXJ} پp(!]pf?C̯*TۨlֽuI^Fʶ*=|,+\@/B4ڂnE< NqG~1 EelҾQ#3S~ݹ kďucۖT6`4ٮˆY4n?c.<2Σ7"%)}ҍimMI*kC4uUSOʒtIt`5< G?rZNTJxX#fľjҞW ȋy~>P1UVk<(Q=u [<%RFx+!Grܐ!Vq5yʞk> stream xڍw 4mH٪GKe%{$ɘyL̘,!R$ER$K!57J}7}g1ߵsT0@S2RDjF6NN(%TVD"`pNa F 470 ٌthC&D 4Q5H@ M$S5ct (dHȔ *O `dAခ/H%`$MǃPE 812x:@0 E/ML֕:pi 5#оap Ot8qt H$O‚T8ZXl :'ݯDҏ`4CIA7#AZH$:Mxt@D{AS{ Mk>Ji4q}FzMHX#/H` : į!G aqc`)g0ŁL?6o"Huee@ ^)p 2Ac}iS# ` :zH?!3HH~(1HaX2FG ~А+%e@UIPPBMO G4~6 ~)@zu d@Pgi|=*vdO$$?~/֟ .ŵz-hh H@3%X;f=#HFXY\AwE]_2%U5M`HHIJ@0 F,CBDC!4](#SaWq@M?:4 0d"oz p2U ܘ6@>qQP+bC7@ʟbjG; jBiC4:0T*&~ ؛^2F+DqTB1CIuaeD$`>H{eA93Ϡg㓃Iu1D<]Yp/祟,=>w[n~I+uLzטso5&4ݖo<۽ NgƆ5hma ӟWP<XjYu\bIHVy(Z.Ĉprm蚓E0*ڤT[S-䌁Z~זV-3w0LeؾRms+͔-LSDդUiZf5V&=j @\9D !"%kӚj=ȤDvhQ7Ymp7ttRPKbR[j Ci$>O|Uj^} 3W\6uaSqv}Zielq0#)-^rqo2c➊Lhȇ.g';<5<[VCNr. ':i|asHT;bJ >0)C0Rzp9 VyTV5Ѳ$*Weԍߛs75o<3{b"҉f&JCV҈)V=A(yWRcpgۢb=]Y[n0-iQ:1`Ú2sD;t&XQuN"n_lL.-񗳪_L \ X?k=]{3Mu>Hd\OynlRͶju{H ;|j`'{pRu_EGCF,\1Ek^{Gf<75#Z6\:FʭOX"l=J-m!Z zS$ hpYO6,|ǮX~ke"]kOLk~1,J } Y}s< ޲(jX뚓;+4_,ص&hu]]x WLn4Uu}QW8O');tJ~Ԅls3T<2h,rtٜ 6\iQQYyZ[f<'=2Ң7 q.K#3(!j eIl}V;no/H"ݨʗ[ؒS:((Ʀ ;t͗]婪;Q1~_d\mC WZdץvGf=o^8*яStX4HwF,b婿77W W[[~Q^P\ȗ)216-/NwpUa >3﮳>FbV$TfWM ^hYG٘k?i{LS-H>V'p^)<f\0snSnU66;XF?ui#ԻYI~^#嬓5uH[Q6>o,La& oyyCޡT0>sK{$ϖEHQ߻S[Y:6=ekOr8[BL/\Ar]l+lsb)>7˶ş_y|<䱔Szjg|/Qʋ⽮u݆ōJ<[M}Z"O?Wfýu?QbJ>1rT..SRmhhOY'"Q.왋t-3%9]ᱥObnJM^m_U\*vmU2 ?T~oJofx E3l!.ն"yl9*jX.G2b%-9çٍiPScQ[C;Tx2L !{HYeJ j4Mp$tT .Pթy y'dRx*{qv}`ɨΔi8oGTCƓ^s%x2"lY*IIro[}*I7 a;ftNtW4Xԇ;‹(*U6\if|~xZkBeڻ.Ô4J(+Ɵ)WEݒf_ZkWz䏸 (',|[g_ w0#zG=Us(fƞq7oۻfLS{k~ s[܊|Aa W%%C/v॔{"v)59g= 'EŦ{b2ܧ?wU]Vg5 |1q#{BzQBvd){KT #Jq_k wb<3k98}rxԏ}Tm-坢y;Juge cgp|!Ōy!+W3k)G);%ljjϐG='㗿4]GZ(n^=9{(KkeW.aǐ箑y-*-ՋrLg:uհesTv+MJVM8t$Lgb W`W91AI=nBy:Xu/DǺߧ oó"Dc#C[MDs  BJ'DezxkrHS51T-{oiLxp[m0j.W̓\\@c%5.!_9|{.y4]],I~ endstream endobj 66 0 obj << /Producer (pdfTeX-1.40.20) /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Keywords() /CreationDate (D:20211026181432-04'00') /ModDate (D:20211026181432-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) kpathsea version 6.3.1) >> endobj 2 0 obj << /Type /ObjStm /N 51 /First 382 /Length 2643 /Filter /FlateDecode >> stream xZ[sJ~G-<ur!N ʃqDŶ|,ٖ嘃*GsQd2fʘe1ǼgL3!r ɴL1m dIˬ3=sIü|DS S INCo(1o!ΘrX%SSaJ*(EL[4D0cfFzmUft \ NfI`&ǜ63g޽Ӣ <sVz@ ;GE}E+>˯ӜM'uW|6+4v` L_ UbfXOɤ{[G{|](O\'qE5{/GI݇g>'u7.jH'{0{#~_8ϽۺEYL>18V=)Gc4o9+CWyA.6BhtmNSg[x|m<ȋGZS%a ݴE(bSS&lڊig܍l[&E b̿]vBIn(INu\w{d]Ps# V*죜xi[%wZGYPz }7}ZTǀj Q)F TY܂䡐E-YGhX^Jh_P$I (Xa 胦eξW <0 Cf9DyB `MdC""aZd8OBo0`LKOFY4'dȲ,]p!\XcQqPQ$ڒ'K*t2i>rpAA.f5SJXRG:=l=IlsZ3X9YqȽb-3QNn^q0bZt6cgOup/27i~|~{`%{ c=ij&4!=!Eap0}7qy{ hf3+:f22dfxv /|+^9|?YvT@닧yz Zo} -J>_0]0(brwC "/BVDr<sYCwAtq$xqR~2m hC8#03N{ |X̆QGa5G~)x0a*§(t4_-L%?_赻{trz2+M 5o~ Fn_%K*?E_7W(XVb!ȫ/KAo>+0[R)@F4[4`f8ad8jsg4;>֋mQ~Tx`[pXKKRN ߵڍ>E""l01 v lvp(O?R-,Ͽpf v 賔镆3+k:|TZ2;%DHʖ"7"@=b)~y~poQ?Gdm 83j9IBySvoěl+jw͝2Qlڷ4rwݒѽl;n&uv3`kmp/WyNo{ZPO;/*Yhd͏Hᢝ庢56/3Ar[O4hLw_qd6?)EךA^a#"M/Ѵ%ƂV/u_Vg|~EUT endstream endobj 67 0 obj << /Type /XRef /Index [0 68] /Size 68 /W [1 3 1] /Root 65 0 R /Info 66 0 R /ID [<803A75B2429EB750EEE094A7B8026D4C> <803A75B2429EB750EEE094A7B8026D4C>] /Length 187 /Filter /FlateDecode >> stream x%=NBDDAT@Qe؄ pl^Jh]ϵr)$m)= }0$,Jq;An7ЁGxY4FE8*pPU\5\Gխ(aMOUTFVԹuaD^ԥ=D]3wˮU endstream endobj startxref 118313 %%EOF pcaMethods/inst/doc/outliers.Rnw0000644000175000017500000001203114136047224016553 0ustar nileshnilesh\documentclass[a4paper]{article} %\VignetteIndexEntry{Data with outliers} \usepackage{hyperref} \title{Handling of data containing outliers} \author{Wolfram Stacklies and Henning Redestig\\ CAS-MPG Partner Institute for Computational Biology (PICB)\\ Shanghai, P.R. China \\ and\\ Max Planck Institute for Molecular Plant Physiology\\ Potsdam, Germany\\ \url{http://bioinformatics.mpimp-golm.mpg.de/} } \date{\today} \begin{document} \setkeys{Gin}{width=1.0\textwidth} @ \maketitle \section{PCA robust to outliers} Away from often showing missing values, Microarray or Metabolite data are often corrupted with extreme values (outliers). Standard SVD is highly susceptible to outliers. In the extreme case, an individual data point, if sufficiently outlying, can draw even the leading principal component toward itself. This problem can be addressed by using a robust analysis method. Hereto we provide \texttt{robustSvd}, a singular value decomposition robust to outliers. \texttt{robustPca} is a PCA implementation that resembles the original \texttt{R} \texttt{prcomp} method, with the difference that it uses \texttt{robustSvd} instead of the standard \texttt{svd} function.\\ Robust SVD and its application to microarray data were proposed in \cite{hawkins01} and \cite{liu03}. The algorithm is based on the idea to use a sequential estimation of the eigenvalues and left and right eigenvectors that ignores missing values and is resistant to outliers. \\ The \texttt{robustSvd} script included here was contributed by Kevin Wright. Thanks a lot to him! \section{Outliers and missing value imputation} The problem of outliers is similar to the missing data problem in the sense that extreme values provide no or wrong information. They are generally artifacts of the experiment and provide no information about the underlying biological processes. \\ Most of the PCA methods coming with the package were not designed to be robust to outliers in the sense that they will converge to the standard PCA solution on a complete data set. Yet, an applicable solution is to remove obvious outliers from the data first (by setting them NA) and to then estimate the PCA solution on the incomplete data. This is likely to produce accurate results if the number of missing data does not exceed a certain amount, less than 10\% should be a good number. The following example illustrates the effect of outliers and the use of robust methods. First, we attach the complete metabolite data set and create 5\% outliers. We mean center the data before we create outliers because these large artificial outliers will strongly shift the original means. This would not allow for objective comparison between the differnt results obtained, e.g. when doing scatterplots. <>= library(pcaMethods) @ <<>>= data(metaboliteDataComplete) mdc <- scale(metaboliteDataComplete, center=TRUE, scale=FALSE) cond <- runif(length(mdc)) < 0.05 mdcOut <- mdc mdcOut[cond] <- 10 @ Then we calculate a PCA solution using standard SVD and robust SVD. <>= resSvd <- pca(mdc, method="svd", nPcs=5, center=FALSE) resSvdOut <- pca(mdcOut, method="svd", nPcs=5, center=FALSE) resRobSvd <- pca(mdcOut, method="robustPca", nPcs=5, center=FALSE) @ Now we use \texttt{PPCA} to estimate the PCA solution, but set the outliers NA before. <>= mdcNa <- mdc mdcNa[cond] <- NA resPPCA <- pca(mdcNa, method="ppca", nPcs=5, center=FALSE) @ To check the robustness to outliers we can just do a scatterplot comparing the results to the optimal PCA solution for the complete data set (which is \texttt{resSvd}). In Figure \ref{fig:svdPlot} we plot the estimated and original loadings against each other. \begin{figure}[!ht] \centering <>= par(mfrow=c(2,2)) plot(loadings(resSvd)[,1], loadings(resSvdOut)[,1], xlab="Loading 1 SVD", ylab="Loading 1 SVD with outliers") plot(loadings(resSvd)[,1], loadings(resRobSvd)[,1], xlab="Loading 1 SVD", ylab="Loading 1 robustSVD with outliers") plot(loadings(resSvd)[,1], loadings(resPPCA)[,1], xlab="Loading 1 SVD", ylab="Loading 1 PPCA with outliers=NA") plot(loadings(resRobSvd)[,1], loadings(resPPCA)[,1], xlab="Loading 1 robust SVD with outliers", ylab="Loading 1 svdImpute with outliers=NA") @ \caption{Figures show (from left to right): \newline Original PCA solution vs. solution on data with outliers; \newline Original PCA solution vs. robust PCA solution on data with outliers; \newline Original PCA solution vs. PPCA solution on data where outliers=NA; \newline Robust PCA solution vs. PPCA solution on data with outliers / outliers=NA. \label{fig:svdPlot} } \end{figure} \begin{thebibliography}{2006} \bibitem{hawkins01} Hawkins, D.M., Liu, L. and Young, S.S. {\sl Robust Singular Value Decomposition.} National Institute of Statistical Sciences, 2001, Tech Report 122. \bibitem{liu03} Liu, L., Hawkins, D.M., Ghosh, S. and Young, S.S. {\sl Robust singular value decomposition analysis of microarray data.} PNAS, 2003;100:13167--13172. \end{thebibliography} \end{document} pcaMethods/inst/doc/pcaMethods.R0000644000175000017500000001310614136077111016431 0ustar nileshnilesh### R code from vignette source 'pcaMethods.Rnw' ################################################### ### code chunk number 1: pcaMethods.Rnw:102-114 ################################################### library(pcaMethods) x <- c(-4,7); y <- c(-3,4) distX <- rnorm(100, sd=0.3)*3 distY <- rnorm(100, sd=0.3) + distX * 0.3 mat <- cbind(distX, distY) res <- pca(mat, nPcs=2, method="svd", center=F) loading <- loadings(res)[1,] grad <- loading[2] / loading[1] if (grad < 0) grad <- grad * -1 lx <- c(-4,7) ly <- c(grad * -4, grad * 7) ################################################### ### code chunk number 2: pcaMethods.Rnw:118-125 ################################################### par(mar=c(2, 3, 2, 2)) plot(x,y, type="n", xlab="", ylab="") abline(v=0, col="dark gray", lwd = 2); abline(h=0, col = "dark gray", lwd = 2) points(distX, distY, type = 'p', col = "blue") lines(lx,ly, lwd = 2) points(-1, -1 * grad + 0.5, pch = 19, col = "red", lwd=4) points(6, 6 * grad + 0.5, pch = 19, col = "red", lwd=4) ################################################### ### code chunk number 3: pcaMethods.Rnw:253-255 ################################################### library(lattice) library(pcaMethods) ################################################### ### code chunk number 4: pcaMethods.Rnw:258-261 ################################################### library(pcaMethods) data(metaboliteData) data(metaboliteDataComplete) ################################################### ### code chunk number 5: pcaMethods.Rnw:264-266 ################################################### md <- prep(metaboliteData, scale="none", center=TRUE) mdC <- prep(metaboliteDataComplete, scale="none", center=TRUE) ################################################### ### code chunk number 6: pcaMethods.Rnw:271-277 ################################################### resPCA <- pca(mdC, method="svd", center=FALSE, nPcs=5) resPPCA <- pca(md, method="ppca", center=FALSE, nPcs=5) resBPCA <- pca(md, method="bpca", center=FALSE, nPcs=5) resSVDI <- pca(md, method="svdImpute", center=FALSE, nPcs=5) resNipals <- pca(md, method="nipals", center=FALSE, nPcs=5) resNLPCA <- pca(md, method="nlpca", center=FALSE, nPcs=5, maxSteps=300) ################################################### ### code chunk number 7: pcaMethods.Rnw:293-296 ################################################### sDevs <- cbind(sDev(resPCA), sDev(resPPCA), sDev(resBPCA), sDev(resSVDI), sDev(resNipals), sDev(resNLPCA)) matplot(sDevs, type = 'l', xlab="Eigenvalues", ylab="Standard deviation of PC", lwd=3) legend(x="topright", legend=c("PCA", "PPCA", "BPCA", "SVDimpute","Nipals PCA","NLPCA"), lty=1:6, col=1:6, lwd=3) ################################################### ### code chunk number 8: pcaMethods.Rnw:308-311 ################################################### par(mfrow=c(1,2)) plot(loadings(resBPCA)[,1], loadings(resPCA)[,1], xlab="BPCA", ylab="classic PCA", main = "Loading 1") plot(loadings(resBPCA)[,2], loadings(resPCA)[,2], xlab="BPCA", ylab="classic PCA", main = "Loading 2") ################################################### ### code chunk number 9: pcaMethods.Rnw:335-337 ################################################### q2SVDI <- Q2(resSVDI, mdC, fold=10) q2PPCA <- Q2(resPPCA, mdC, fold=10) ################################################### ### code chunk number 10: pcaMethods.Rnw:339-349 ################################################### # PPCA does not converge / misestimate a value in very rare cases. # This is a workaround to avoid that such a case will break the # diagram displayed in the vignette. # From the 2.0 release of bioconductor on, the convergence threshold # for PPCA was lowert to 1e-5, this should make the method much more # stable. So this workaround might be obsolete now... # [nope it is not, ppca is unstable] while( sum((abs(q2PPCA)) > 1) >= 1 ) { q2PPCA <- Q2(resPPCA, mdC, fold=10) } ################################################### ### code chunk number 11: pcaMethods.Rnw:353-356 ################################################### q2 <- data.frame(Q2=c(drop(q2PPCA), drop(q2SVDI)), method=c("PPCA", "SVD-Impute")[gl(2, 5)], PC=rep(1:5, 2)) print(xyplot(Q2~PC|method, q2, ylab=expression(Q^2), type="h", lwd=4)) ################################################### ### code chunk number 12: pcaMethods.Rnw:389-390 ################################################### errEsti <- kEstimate(md, method = "ppca", evalPcs=1:5, nruncv=1, em="nrmsep") ################################################### ### code chunk number 13: pcaMethods.Rnw:396-397 ################################################### barplot(drop(errEsti$eError), xlab="Loadings", ylab="NRMSEP (Single iteration)") ################################################### ### code chunk number 14: pcaMethods.Rnw:420-421 ################################################### barplot(drop(errEsti$variableWiseError[, which(errEsti$evalPcs == errEsti$bestNPcs)]), xlab="Incomplete variable Index", ylab="NRMSEP") ################################################### ### code chunk number 15: pcaMethods.Rnw:445-446 ################################################### slplot(resPCA) ################################################### ### code chunk number 16: pcaMethods.Rnw:456-457 ################################################### plotPcs(resPPCA, pc=1:3, type="score") ################################################### ### code chunk number 17: pcaMethods.Rnw:469-475 ################################################### pc <- pca(iris) irdf <- merge(iris, scores(pc), by=0) library(ggplot2) ggplot(irdf, aes(PC1, PC2, colour=Species)) + geom_point() + stat_ellipse() pcaMethods/inst/doc/missingValues.R0000644000175000017500000000327414136076711017205 0ustar nileshnilesh### R code from vignette source 'missingValues.Rnw' ################################################### ### code chunk number 1: missingValues.Rnw:43-44 ################################################### library(pcaMethods) ################################################### ### code chunk number 2: missingValues.Rnw:46-49 ################################################### data(metaboliteData) mD <- metaboliteData sum(is.na(mD)) ################################################### ### code chunk number 3: missingValues.Rnw:52-54 ################################################### pc <- pca(mD, nPcs=3, method="ppca") imputed <- completeObs(pc) ################################################### ### code chunk number 4: missingValues.Rnw:58-61 ################################################### data(metaboliteDataComplete) mdComp <- metaboliteDataComplete sum((mdComp[is.na(mD)] - imputed[is.na(mD)])^2) / sum(mdComp[is.na(mD)]^2) ################################################### ### code chunk number 5: missingValues.Rnw:64-66 ################################################### imputedNipals <- completeObs(pca(mD, nPcs=3, method="nipals")) sum((mdComp[is.na(mD)] - imputedNipals[is.na(mD)])^2) / sum(mdComp[is.na(mD)]^2) ################################################### ### code chunk number 6: missingValues.Rnw:71-80 ################################################### library(Biobase) data(sample.ExpressionSet) exSet <- sample.ExpressionSet exSetNa <- exSet exprs(exSetNa)[sample(13000, 200)] <- NA lost <- is.na(exprs(exSetNa)) pc <- pca(exSetNa, nPcs=2, method="ppca") impExSet <- asExprSet(pc, exSetNa) sum((exprs(exSet)[lost] - exprs(impExSet)[lost])^2) / sum(exprs(exSet)[lost]^2) pcaMethods/inst/doc/missingValues.Rnw0000644000175000017500000000565414136047224017553 0ustar nileshnilesh\documentclass[a4paper]{article} %\VignetteIndexEntry{Missing value imputation} \usepackage{hyperref} \title{Imputing missing values using the pcaMethods package} \author{Wolfram Stacklies and Henning Redestig\\ CAS-MPG Partner Institute for Computational Biology (PICB)\\ Shanghai, P.R. China \\ and\\ Max Planck Institute for Molecular Plant Physiology\\ Potsdam, Germany\\ \url{http://bioinformatics.mpimp-golm.mpg.de/} } \date{\today} \begin{document} \setkeys{Gin}{width=1.0\textwidth} @ \maketitle \section{Missing value imputation} One application for missing value robust principal component analysis is that it effectively can be used to impute the missing values and thus obtain an estimated complete data set. The pcaMethods package was partly written with this application in mind. PCA is a way of creating a model of a matrix, $X$, by defining two parameter matrices, the scores, $T$, and the loadings, $P$, which together have less values than the original matrix but when multiplied with each other well reconstruct the original matrix. I.e.: $$X=1\times{}\bar{x} + TP' + E$$ where $E$ is the error matrix and $1\times{}\bar{x}$ denotes the original variable averages. Now if $X$ contains missing values but we still are able to get complete estimates of $P$ and $T$ than we can use: $$\hat{X}=1\times{}\bar{x} + TP'$$ as an estimate for $x_{i,j}$ if $x_{i,j}$ is missing. This is can be done as the following example illustrates. First we attach the metabolite data set with missing values. <>= library(pcaMethods) @ <<>>= data(metaboliteData) mD <- metaboliteData sum(is.na(mD)) @ Now we get the estimated data set by using PPCA and three principal components. <<>>= pc <- pca(mD, nPcs=3, method="ppca") imputed <- completeObs(pc) @ If we compare with the original values we see that the error is rather low. <<>>= data(metaboliteDataComplete) mdComp <- metaboliteDataComplete sum((mdComp[is.na(mD)] - imputed[is.na(mD)])^2) / sum(mdComp[is.na(mD)]^2) @ When using a different PCA algorithm, we get different performance. <<>>= imputedNipals <- completeObs(pca(mD, nPcs=3, method="nipals")) sum((mdComp[is.na(mD)] - imputedNipals[is.na(mD)])^2) / sum(mdComp[is.na(mD)]^2) @ If the data we are interested in was gene expression set of class 'ExpressionSet' we could simply do <<>>= library(Biobase) data(sample.ExpressionSet) exSet <- sample.ExpressionSet exSetNa <- exSet exprs(exSetNa)[sample(13000, 200)] <- NA lost <- is.na(exprs(exSetNa)) pc <- pca(exSetNa, nPcs=2, method="ppca") impExSet <- asExprSet(pc, exSetNa) sum((exprs(exSet)[lost] - exprs(impExSet)[lost])^2) / sum(exprs(exSet)[lost]^2) @ Different results will be obtained with different PCA algorithms. Which one to use depends on the general structure of the data set and the imputation performance can be estimated by cross-validation. Please see the 'introduction' vignette on further details on how to use the cross-validation capabilities of this package. \end{document} pcaMethods/inst/doc/pcaMethods.Rnw0000644000175000017500000005554214136047224017012 0ustar nileshnilesh\documentclass[a4paper]{article} %\VignetteIndexEntry{Introduction} \usepackage{hyperref} \title{The pcaMethods Package} \author{Wolfram Stacklies and Henning Redestig\\ CAS-MPG Partner Institute for Computational Biology (PICB)\\ Shanghai, P.R. China \\ and\\ Max Planck Institute for Molecular Plant Physiology\\ Potsdam, Germany\\ \url{http://bioinformatics.mpimp-golm.mpg.de/} } \date{\today} \begin{document} \setkeys{Gin}{width=1.0\textwidth} @ \maketitle \section*{Overview} The \texttt{pcaMethods} package \cite{stacklies07} provides a set of different PCA implementations, together with tools for cross validation and visualisation of the results. The methods basically allow to perform PCA on incomplete data and thus may also be used for missing value estimation. When doing PCA one assumes that the data is restricted to a subspace of lower dimensionality, e.g. correlation patterns between jointly regulated genes. PCA aims to extract these structures thereby filtering noise out. If only the most significant loadings (eigenvectors, also referred to as principal components) are used for projection this can be written as: \begin{equation} X = 1\times{}\bar{x}^T + TP^T + V \end{equation} Where the term $1\times{}\bar{x}^T$ represents the original variable averages, $X$ denotes the observations, $T={t_1, t_2,\ldots,t_k}$ the latent variables or scores, $P={p_1, p_2,\ldots,p_k}$ the transformation matrix (consisting of the most significant eigenvectors of the covariance matrix) and $V$ are the residuals. Missing values may be estimated by projecting the scores back into the original space using $\hat{X} = 1\times{}\bar{x}^T + TP^T$. Optimally, this produces an estimate of the missing data based on the underlying correlation structure, thereby ignoring noise. This will only produce reasonable results if the residuals $V$ are sufficiently small, implying that most of the important information is captured by the first $k$ components. In order to calculate the transformation matrix $P$ one needs to determine the covariance matrix between variables or alternatively calculate $P$ directly via SVD. In both cases, this can only be done on complete matrices. However, an approximation may be obtained by use of different regression methods. The PCA methods provided in this package implement algorithms to accurately estimate the PCA solution on incomplete data. Although the focus of this package is clearly to provide a collection of PCA methods we also provide a cluster based method for missing value imputation. This allows to better rate and compare the results. \section{Algorithms} All methods return a common class called \texttt{pcaRes} as a container for the results. This guarantees maximum flexibility for the user. A wrapper function called \texttt{pca()} is provided that receives the desired type of pca as a string. \subsection*{svdPca} This is a wrapper function for $R's$ standard \texttt{prcomp} function. It delivers the results as a \texttt{pcaRes} object for compatibility with the rest of the package. \subsection*{svdImpute} This implements the SVDimpute algorithm as proposed by Troyanskaya et~al \cite{troyanskaya01}. The idea behind the algorithm is to estimate the missing values as a linear combination of the $k$ most significant eigengenes\footnote{The term ``eigengenes'' denotes the loadings when PCA was applied considering variables (here the genes) as observations.}. The algorithm works iteratively until the change in the estimated solution falls below a certain threshold. Each step the eigengenes of the current estimate are calculated and used to determine a new estimate. An optimal linear combination is found by regressing an incomplete variable against the $k$ most significant eigengenes. If the value at position $j$ is missing, the $j^{th}$ value of the eigengenes is not used when determining the regression coefficients.\\ SVDimpute seems to be tolerant to relatively high amount of missing data (> 10\%). \subsection*{Probabilistic PCA (ppca)} Probabilistic PCA combines an EM approach for PCA with a probabilistic model. The EM approach is based on the assumption that the latent variables as well as the noise are normal distributed. In standard PCA data which is far from the training set but close to the principal subspace may have the same reconstruction error, see Figure \ref{fig:pcaSubspace} for explanation. <>= library(pcaMethods) x <- c(-4,7); y <- c(-3,4) distX <- rnorm(100, sd=0.3)*3 distY <- rnorm(100, sd=0.3) + distX * 0.3 mat <- cbind(distX, distY) res <- pca(mat, nPcs=2, method="svd", center=F) loading <- loadings(res)[1,] grad <- loading[2] / loading[1] if (grad < 0) grad <- grad * -1 lx <- c(-4,7) ly <- c(grad * -4, grad * 7) @ \begin{figure} \centering <>= par(mar=c(2, 3, 2, 2)) plot(x,y, type="n", xlab="", ylab="") abline(v=0, col="dark gray", lwd = 2); abline(h=0, col = "dark gray", lwd = 2) points(distX, distY, type = 'p', col = "blue") lines(lx,ly, lwd = 2) points(-1, -1 * grad + 0.5, pch = 19, col = "red", lwd=4) points(6, 6 * grad + 0.5, pch = 19, col = "red", lwd=4) @ \caption{Normal distributed data with the first loading plotted in black. The two red points have the same reconstruction error because PCA does not define a density model. Thus the only measure of how well new data fits the model is the distance from the principal subspace. Data points far from the bulk of data but still close to the principal subspace will have a low reconstruction error. \label{fig:pcaSubspace}} \end{figure} PPCA defines a likelihood function such that the likelihood for data far from the training set is much lower, even if they are close to the principal subspace. This allows to improve the estimation accuracy.\\ PPCA is tolerant to amounts of missing values between 10\% to 15\%. If more data is missing the algorithm is likely not to converge to a reasonable solution. The method was implemented after the draft ``\texttt{EM Algorithms for PCA and Sensible PCA}'' written by Sam Roweis and after the Matlab \texttt{ppca} script implemented by \emph{Jakob Verbeek}\footnote{\url{http://lear.inrialpes.fr/~verbeek/}}. Please check also the PPCA help file. \subsection*{Bayesian PCA (bpca)} Similar to probabilistic PCA, Bayesian PCA uses an EM approach together with a Bayesian model to calculate the likelihood for a reconstructed value.\\ The algorithm seems to be tolerant to relatively high amounts of missing data (> 10\%). Scores and loadings obtained with Bayesian PCA slightly differ from those obtained with conventional PCA. This is because BPCA was developed especially for missing value estimation and is based on a variational Bayesian framework (VBF), with automatic relevance determination (ARD). In BPCA, ARD leads to a different scaling of the scores, loadings and eigenvalues when compared to standard PCA or PPCA. The algorithm does not force orthogonality between loadings. However, the authors of the BPCA paper found that including an orthogonality criterion made the predictions worse. They also state that the difference between ``real'' and predicted Eigenvalues becomes larger when the number of observation is smaller, because it reflects the lack of information to accurately determine true loadings from the limited and noisy data. As a result, weights of factors to predict missing values are not the same as with conventional PCA, but the missing value estimation is improved. BPCA was proposed by Oba et~al \cite{oba03}. The method available in this package is a port of the \texttt{bpca} Matlab script also provided by the authors\footnote{ \url{http://hawaii.aist-nara.ac.jp/\%7Eshige-o/tools/}}. \subsection*{Inverse non-linear PCA (NLPCA)} NLPCA \cite{scholz05} is especially suitable for data from experiments where the studied response is non-linear. Examples of such experiments are ubiquitous in biology -- enzyme kinetics are inherently non-linear as are gene expression responses influenced by the cell cycle or diurnal oscillations. NLPCA is based on training an auto-associative neural network composed of a component layer which serves as the ``bottle-neck'', a hidden non-linear layer and an output layer corresponding to the reconstructed data. The loadings can be seen as hidden in the network. Missing values in the training data are simply ignored when calculating the error during back-propagation. Thus NLPCA can be used to impute missing values in the same way as for conventional PCA. The only difference is that the loadings $P$ are now represented by a neural network.\\ A shortcoming of the current implementation is that there is no reasonable stop criterion. The quality of the estimated solution depends on the number of iterations. This should in most cases be somewhat between 500 and 1500. We recommend to use \texttt{kEstimate} or \texttt{kEstimateFast} to determine this parameter. \subsection*{Nipals PCA} Nipals (Nonlinear Estimation by Iterative Partial Least Squares) \cite{wold66} is an algorithm at the root of PLS regression which can execute PCA with missing values by simply leaving those out from the appropriate inner products. It is tolerant to small amounts (generally not more than 5\%) of missing data. \subsection{Local least squares (LLS) imputation} The package provides an algorithm called \texttt{llsImpute} for missing value estimation based on a linear combination of the $k$ nearest neighbours of an incomplete variable (in Microarray experiments normally a gene). The distance between variables is defined as the absolute value of the Pearson, Spearman or Kendall correlation coefficient. The optimal linear combination is found by solving a local least squares problem as described in \cite{kim05}. In tests performed in the cited paper the llsImpute algorithm is able to outperform knnImpute\cite{troyanskaya01} and competes well with BPCA. In the current implementation two slightly different ways for missing value estimation are provided. The first one is to restrict the neighbour searching to the subset of complete variables. This is preferable when the number of incomplete variables is relatively small. The second way is to consider all variables as candidates. Here, missing values are initially replaced by the columns wise mean. The method then iterates, using the current estimate as input for the LLS regression until the change between new and old estimate falls below a certain threshold (0.001). \section{Getting started} \paragraph{Installing the package.} To install the package first download the appropriate file for your platform from the Bioconductor website (\url{http://www.bioconductor.org/}). For Windows, start \texttt{R} and select the \texttt{Packages} menu, then \texttt{Install package from local zip file}. Find and highlight the location of the zip file and click on \texttt{open}. For Linux/Unix, use the usual command \texttt{R CMD INSTALL} or set the option \texttt{CRAN} to your nearest mirror site and use the command \texttt{install.packages} from within an \texttt{R} session. \paragraph{Loading the package:} To load the \texttt{pcaMethods} package in your \texttt{R} session, type \texttt{library(pcaMethods)}. \paragraph{Help files:} Detailed information on \texttt{pcaMethods} package functions can be obtained from the help files. For example, to get a description of \texttt{bpca} type \texttt{help("bpca")}. \paragraph{Sample data:} Two sample data sets are coming with the package. \texttt{metaboliteDataComplete} contains a complete subset from a larger metabolite data set. \texttt{metaboliteData} is the same data set but with 10 \% values removed from an equal distribution. \section{Some examples} <>= library(lattice) library(pcaMethods) @ To load the package and the two sample data sets type: <>= library(pcaMethods) data(metaboliteData) data(metaboliteDataComplete) @ Now centre the data <<>>= md <- prep(metaboliteData, scale="none", center=TRUE) mdC <- prep(metaboliteDataComplete, scale="none", center=TRUE) @ Run SVD pca, PPCA, BPCA, SVDimpute and nipalsPCA on the data, using the \texttt{pca()} wrapper function. The result is always a \texttt{pcaRes} object. <>= resPCA <- pca(mdC, method="svd", center=FALSE, nPcs=5) resPPCA <- pca(md, method="ppca", center=FALSE, nPcs=5) resBPCA <- pca(md, method="bpca", center=FALSE, nPcs=5) resSVDI <- pca(md, method="svdImpute", center=FALSE, nPcs=5) resNipals <- pca(md, method="nipals", center=FALSE, nPcs=5) resNLPCA <- pca(md, method="nlpca", center=FALSE, nPcs=5, maxSteps=300) @ Figure \ref{fig:eigenvalues} shows a plot of the eigenvalue structure (\texttt{sDev(pcaRes)}). If most of the variance is captured with few loadings PCA is likely to produce good missing value estimation results. For the sample data all methods show similar eigenvalues. One can also see that most of the variance is already captured by the first loading, thus estimation is likely to work fine on this data. For BPCA, the eigenvalues are scaled differently for reasons discussed above, see Figure \ref{fig:loadingBPCA}. The order of the loadings remains the same. \begin{figure} \centering <>= sDevs <- cbind(sDev(resPCA), sDev(resPPCA), sDev(resBPCA), sDev(resSVDI), sDev(resNipals), sDev(resNLPCA)) matplot(sDevs, type = 'l', xlab="Eigenvalues", ylab="Standard deviation of PC", lwd=3) legend(x="topright", legend=c("PCA", "PPCA", "BPCA", "SVDimpute","Nipals PCA","NLPCA"), lty=1:6, col=1:6, lwd=3) @ \caption{Eigenvalue structure as obtained with different methods\label{fig:eigenvalues}} \end{figure} To get an impression of the correctness of the estimation it is a good idea to plot the scores / loadings obtained with classical PCA and one of the probabilistic methods against each other. This of course requires a complete data set from which data is randomly removed. Figure \ref{fig:loadingBPCA} shows this for BPCA on the sample data. \begin{figure} \centering <>= par(mfrow=c(1,2)) plot(loadings(resBPCA)[,1], loadings(resPCA)[,1], xlab="BPCA", ylab="classic PCA", main = "Loading 1") plot(loadings(resBPCA)[,2], loadings(resPCA)[,2], xlab="BPCA", ylab="classic PCA", main = "Loading 2") @ \caption{Loading 1 and 2 calculated with BPCA plotted against those calculated with standard PCA. \label{fig:loadingBPCA}} \end{figure} \section{Cross validation} \texttt{Q2} is the goodness measure used for internal cross validation. This allows to estimate the level of structure in a data set and to optimise the choice of number of loadings. Cross validation is performed by removing random elements of the data matrix, then estimating these using the PCA algorithm of choice and then calculating $Q^2$ accordingly. At the moment, cross-validation can only be performed with algorithms that allow missing values (i.e. not SVD). Missing value independent cross-validation is scheduled for implementation in later versions. $Q^2$ is defined as following for the mean centered data (and possibly scaled) matrix $X$. $$\mathrm{SSX}=\sum (x_{ij})^2$$ $$\mathrm{PRESS}=\sum (x_{ij} - \hat{x}_{ij})^2$$ $$Q^2=1 - \mathrm{PRESS}/\mathrm{SSX}$$ The maximum value for $Q^2$ is thus 1 which means that all variance in $X$ is represented in the predictions; $X=\hat{X}$. <>= q2SVDI <- Q2(resSVDI, mdC, fold=10) q2PPCA <- Q2(resPPCA, mdC, fold=10) @ <>= # PPCA does not converge / misestimate a value in very rare cases. # This is a workaround to avoid that such a case will break the # diagram displayed in the vignette. # From the 2.0 release of bioconductor on, the convergence threshold # for PPCA was lowert to 1e-5, this should make the method much more # stable. So this workaround might be obsolete now... # [nope it is not, ppca is unstable] while( sum((abs(q2PPCA)) > 1) >= 1 ) { q2PPCA <- Q2(resPPCA, mdC, fold=10) } @ \begin{figure}[!ht] \centering <>= q2 <- data.frame(Q2=c(drop(q2PPCA), drop(q2SVDI)), method=c("PPCA", "SVD-Impute")[gl(2, 5)], PC=rep(1:5, 2)) print(xyplot(Q2~PC|method, q2, ylab=expression(Q^2), type="h", lwd=4)) @ \caption{Boxplot of the \texttt{Q2} results for BPCA, Nipals PCA, SVDimpute and PPCA. PPCA and SVDimpute both deliver better results than BPCA and Nipals in this example.\label{fig:Q2}} \end{figure} The second method called \texttt{kEstimate} uses cross validation to estimate the optimal number of loadings for missing value estimation. The \texttt{NRMSEP} (normalised root mean square error of prediction) \cite{feten05} or Q2 can be used to define the average error of prediction. The NRMSEP normalises the square difference between real and estimated values for a certain variable by the variance within this variable. The idea behind this normalisation is that the error of prediction will automatically be higher if the variance is higher. The \texttt{NRMSEP} for mean imputation is $\sqrt{\frac{nObs}{nObs - 1}}$ when cross validation is used, where $nObs$ is the number of observations. The exact definition is: \begin{equation} NRMSEP_k = \sqrt{\frac{1}{g} \sum_{j \in G} \frac{\sum_{i \in O_j} (x_{ij} - \hat{x}_{ijk})^2}{o_j s_{x_j}^2}} \end{equation} where $s^2_{x_j} = \sum_{i=1}^n (x_{ij} - \overline{x}_j)^2 / (n - 1)$, this is the variance within a certain variable. Further, $G$ denotes the set of incomplete variables, $g$ is the number of incomplete varialbes. $O_j$ is the set of missing observations in variable $j$ and $o_j$ is the number of missing observations in variable $j$. $\hat{x}_{ijk}$ stands for the estimate of value $i$ of variable $j$ using $k$ loadings. See Figure \ref{fig:kEstimate} for an example. The NRMSEP should be the error measure of choice. But if the number of observations is small, the variance within a certain variable may become and unstable criterion. If so or if variance scaling was applied we recommend to use Q2 instead. <>= errEsti <- kEstimate(md, method = "ppca", evalPcs=1:5, nruncv=1, em="nrmsep") @ \begin{figure}[!ht] \centering \begin{minipage}[c]{0.6\textwidth} \centering <>= barplot(drop(errEsti$eError), xlab="Loadings", ylab="NRMSEP (Single iteration)") @ \end{minipage} \begin{minipage}[c]{0.3\textwidth} \caption{Boxplot showing the \texttt{NRMSEP} versus the number of loadings. In this example only 1 iteration of the whole cross validation were performed. It is normally advisable to do more than just one iteration. \label{fig:kEstimate}} \end{minipage} \end{figure} \texttt{kEstimate} also provides information about the estimation error for individual variables. The $Q^2$ distance or the NRMSEP are calculated separately for each variable. See the manpage for \texttt{kEstimate} and \texttt{kEstimateFast} for details. Plotting the variable - wise results gives information about for which variables missing value estimation makes sense, and for which no imputation or mean imputation is preferable, see Figure \ref{fig:variableWiseError}. If you are not interested in variable - wise information we recommend to use the faster \texttt{kEstimateFast} instead. \begin{figure}[!ht] \centering \begin{minipage}[c]{0.6\textwidth} \centering <>= barplot(drop(errEsti$variableWiseError[, which(errEsti$evalPcs == errEsti$bestNPcs)]), xlab="Incomplete variable Index", ylab="NRMSEP") @ \end{minipage} \begin{minipage}[c]{0.3\textwidth} \caption{Boxplot showing the \texttt{NRMSEP} for all incomplete variables in the data set. For the first 7 variables missing value imputation does not seem to make too much sense. \label{fig:variableWiseError}} \end{minipage} \end{figure} \newpage \section{Visualisation of the results} \subsection{Quick scores and loadings plot} Some methods for display of scores and loadings are also provided. The function \texttt{slplot()} aims to be a simple way to quickly visualise scores and loadings in an intuitive way, see Figure \ref{fig:slplot}. Barplots are provided when plotting only one PC and colours can be specified differently for the scores and loadings plots. For a more specific scatter plot it is however recommended to access scores and loadings slots and define own plot functions. \begin{figure}[!h] \centering <>= slplot(resPCA) @ \caption{\texttt{slplot} for scores and loadings obtained with classical SVD based PCA. \label{fig:slplot}} \end{figure} \noindent Another method called \texttt{plotPcs()} allows to visualise many PCs plotted against each other, see Figure \ref{fig:plotPcs}. \begin{figure}[!ht] \centering <>= plotPcs(resPPCA, pc=1:3, type="score") @ \caption{A plot of score 1:3 for PPCA created with \texttt{plotPcs()} \label{fig:plotPcs}} \end{figure} \subsection{Using ggplot2} For using ggplot, the scores and loadings should best be added to a data frame that add other relevant descriptive factors. For example, after doing PCA on the Iris dataset, we may add the scores back to the original data frame and use ggplot to visualise, see Figure \ref{fig:ggplot}. \begin{figure}[!ht] \centering <>= pc <- pca(iris) irdf <- merge(iris, scores(pc), by=0) library(ggplot2) ggplot(irdf, aes(PC1, PC2, colour=Species)) + geom_point() + stat_ellipse() @ \caption{Score plot using ggplot2} \label{fig:ggplot} \end{figure} \cleardoublepage \begin{thebibliography}{2006} \bibitem{stacklies07} Stacklies W., Redestig H., Scholz M., and Walther D., and Selbig J. {\sl pcaMethods -- a Bioconductor package providing PCA methods for incomplete data} Bioinformatics. 2007, 23, 1164-1167. {\sl Non-linear PCA: a missing data approach.} Bioinformatics. 2005, 21, 3887-3895. \bibitem{scholz05} Scholz, M. , Kaplan, F., Guy, C.L., Kopka, J. and Selbig, J. {\sl Non-linear pca: a missing data approach.} Bioinformatics. 2005, 21, 3887-3895. \bibitem{troyanskaya01} Troyanskaya O. and Cantor M. and Sherlock G. and Brown P. and Hastie T. and Tibshirani R. and Botstein D. and Altman RB. {\sl Missing value estimation methods for DNA microarrays.} Bioinformatics. 2001 Jun;17(6):520-525. \bibitem{feten05} Feten G. and Almoy T. and Aastveit A.H. {\sl Prediction of Missing Values in Microarray and Use of Mixed Models to Evaluate the Predictors.}, Stat. Appl. Genet. Mol. Biol. 2005;4(1):Article 10 \bibitem{oba03} Oba S. and Sato MA. and Takemasa I. and Monden M. and Matsubara K. and Ishii S. {\sl A Bayesian missing value estimation method for gene expression profile data.} Bioinformatics. 2003 Nov 1;19(16):2088-96. \bibitem{wold66} Wold H. {Estimation of principal components and related models by iterative least squares.} In Multivariate Analysis (Ed. P.R. Krishnaiah), Academic Press, NY, 391-420. \bibitem{kim05} Kim H. and Golub G.H. and Park H. {\sl Missing value estimation for DNA microarray gene expression data: local least squares imputation} Bioinformatics. 2005 21(2) :187-198 \end{thebibliography} \end{document} pcaMethods/inst/doc/outliers.pdf0000644000175000017500000036513114136076734016602 0ustar nileshnilesh%PDF-1.5 % 16 0 obj << /Length 2475 /Filter /FlateDecode >> stream xڥYYo~_<ݼq;Ycb3:0ٴhl}g]]Uuӻ?5Y:yZAFiVN3XQ`uP%higrxKc5O(3 Ginkp U|%+YP-ڌhZ5ijden[ 9@4_:aĴ̣TC="HdFLRgE+qH7 UBҠx@B[;gZt,t$J Oٵ,na(߷}ĤQ欯7E96*ˊĀ(w@'I'fБiAE -RN js#7QYxd5@iIs⸣~":pnZ\~Ux[v]$iZMgNu`ȧ[gJB7Qгq`]3?AAS>9ִ]i j|9Ԓe}GkN{E1iZG<i"]kO;ɪ$|!4 `и#pd2ňN cً$$1slXӂ]v=2ԝhOkٷU"v.4>䶜pqKw!CQl:g(9 h8f3HX륒]4r~EC ?r00uM-Ĕ|>i>R-X( Yܩ:ZDHMm4cz&#ȄsDt-'b^f`UU„d.j hBL m͹SDr 812# p?'&5ۣ)V|9xiWEv |Ͼڣ_feʻ%F8D.w"ҲBz)l(egX-cؽhѥ\0ֹp |Z ?*$P_}1kF$17UQ(з(2F@;R ^IŅyV ʟRkI1xgD@qf!l4sykEn4 ^B} driQxūAu޸[ ڤQ_/s9 oioC'Rr >/@eB`RZ P(v% $M$'%ALM8ORv<ε1iX$ސ;W rpQEz8{'}ZNm4.N/'/F< 4 )AI,^K [> stream xXmFί*9xwJJK)Td;GQ|muGV C3~}tY|L'as^E'jy16RX.>?Zo?*0(KwYp 4* |)A`>#bSgz8.P`++dٷ2'4KX0:e3h<}E̻%R984<5dJx{\)R e6^ wb$D5BcmGLM -D9o.ʑ b6Aވ-`0D) _+{{cAQ$=g\Ј/(\C^3$C%#vzV""ɂn`(ޢ kkDUQ#rm[W >萖ظ1ÀXL=LZID i6' VU jr1u .Wdq(B wHp^/5xKss*{’ y%tƷ[~a˔Ho%[$(gafAElse}ñF$Al#Xg4nMyFqdwJyenXe{ 0KQb݇ǰ)0L1-}Gtx*7Cz"+l!{h`욁s 7L dTfA0!2w؆g})Z!Q"DOP.}_kR3GjQpRxG9U W֦0˪ɪ*lN{ANO5Cʒ =-)ӽZ3ڣԣ$zZ|{a. pZrpO!nHfVxY()Bs;Rt: >:s$ѕ<ho8`-xʥNuҧx[24oADд (n|:m k|/9 q2 &иv xW endstream endobj 40 0 obj << /Length 376 /Filter /FlateDecode >> stream xT=O0+<:CܜMC)T  Rۈ; j%dٹ{|/, d"dr E >cb_7z[`eF3:ʃd22e4Z+38ukFJ)0J4JnV󃣿:ƭΪ:ҦKrFrE`5cw&֮%p6Nr:9AC\꽗.wĘP̘S,ٲ$N"QryYTօo\uUF,cO72twz|1@^~Ȫ\r?:i6!m'GퟚW]U\Vtx5XCz Ka]B jH!3oV endstream endobj 29 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/outliers-005.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 42 0 R /BBox [0 0 576 576] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 43 0 R>> /ExtGState << >>/ColorSpace << /sRGB 44 0 R >>>> /Length 13180 /Filter /FlateDecode >> stream x}˲q~J^x [7%ز;/by]qbj8[k h%.$9=nOb%7fIXͣ䛒{WĖymIq.bX}heo8K,1iXI#[5p؆!ܾ[-v[rO_FRcxG>mÙRī[2) BRĶDűɼ}s {))1ox1=+=Nc>GS3#8bþ):Elۙk޺/`wsIM᳜%~7eHµ;[N{Jo-M(kz2oH#FC0ⵣҝ\nG?qm*rd)G|q3ۏUs6n[8 ur !nZGw mbbsqlڝ2ؿEfRB;UkiJJo-MHalHa[v%욷e\c\qjcIґ+ik߷w7%ض+#K}.u<hX ض;#^,*XO#5-^p[c\M5Gpǖ]y e (=+^řE]Zx:n)g%۴D{bһvN}4 1}Welڝ}.Ûl{Ɲoj2剕45lƲ?/-v;^~TQ3?~ϕW`CVl~x+ےy#%<օx\ooc}scUXxUh?;? |_u|3 ܟ{^ezc_Sq?xtH\'Hi8`r}%.O;Sv%lz}7˵w07Dޠt=A|{5Rdˣb"j7|߻{}?(ۆ58ܠ3qߑs__osl yA95Xeo;VmHX-,uxOtE"IMex7~}4kIwkm{WGb-m&Xi`}!7N3/ay\ȻX38P F?k,kXS'0;.y.M"Υ3lXܐl%B[7,=(n",7h'{Hǖ]y I} S2N+nkxm۱XJ+ !Ξ)hƶ] =Xg%<5ؕ;; Vq޸7v, k01<5AΎ M"/}oq4 YxGڣK|bs6cˮ]ֹpi1`~㢜k"^6FM7nlJ 1`54}7b2 gt_Cl+ |TZw]'h{hԌ)065)ϼu.'xc&7؛W_Iwb/?O'V|hi؊!!hŖ]y =6ۯ/;Gõ.MU\R'6$]ƂTteW^>vx~S?Nv#B*\%$fqmm}(Ss&)/y-y5T5o|H5(a*FZƴ_NXI_yg,jJǖ]y A>VvC)Ò(~PVn"ljFl $+黛eW^®yvT9VsTp7H 3(IhxM;ƉT<&X #flۙk> 2yAذUهx$N R/"[E-v[RI??V w+O6Q㚴Jޕ2`EOٻ2K5oKAXv oe6hb-yt d-ܱeW^>v535Nlv?< ~ HwNeidM'~}|9}s69]u_92ގA.M)1FwFV|+XoHyiW^®y\N|4]Jk쌏]/Jx'7AeGԴX*LlGԾG-vrL9*}+IZo-ƒcߐpc}s=lR֌-FmnK)1;|[v|\XJͣ'l'ߔ|>T5oK|tSyGH/KOZl?@5VR7A95bQ +޴|W:2K5o&^՘l[S.nteWVnYj~X|#-v >VM;9n$r1+)p{bA)hƶ]ymI|1hI!{$%ċ Ҟؒ4W:7%>_vE#oۈR|I v4H9Yc8-hk*t=q%cˮ] , _?;,ܸp$8ʨ\۴JJqju|73ʫ?$JOÂRo8OU베$>P&'HJj$djwXƖ]y F2χUsQ ;M1u:9 ~i&:=F tc֔eW^®yuʚ?IGPv~'i>IMuekw1>cMv炝8MԀ^!RX]fo.ﹶ7)i,́/,Z97]5KGncKzt,>cb!vXwKK%өJ؊}|plُ,>R?[b=-8WO#>p,s@p`kxw(5[LN!ߒp4c}siT:%5; Dh-\TrvX9M rb%5NI k[(wG[vURSfbj区;zd^qH}ga%m&)JW@wģ 5oKo?VMe%6\R5a_ћm;GKɔ'jE7%]L}KY>& 冺D=݈qx c7ۖ}@l-G *3%lc8 >&i'1.D׹s}+z?|\V5Zm>EN2v|NpHﳢ mX8δ1c-m[wMve욷zǪ$5I!cKCDBii/XKūϩb%}c۞lgy{L>b$&c45v1E :ֶG4vFfC0U컻[Ɩ]yٷJkbE"^i1mO90OT.5(#3s.>L1+٦}$RNmb;[|g-v{(;:K v}`\q` wN^Cְ|,!h߳Ġcμ]2mZ;[ƢZj3?ZjsrxݒDZLf>Fcv:<^D@.sd]2G'V1@łe AeW^®y $x{x??"䟃SGOyy3%-ʣ~"|,$~"<~"|BopeK4 E\& }_##(/G( }\(NP]6 ÿ$ 2udX1bւP)'$|0GϹeV<,hc,5֢钏?KON܉{VG G2 x砿#mK6D̒Z= G\?`&ˆT(Xl_7T +`ۣ˻Z+P[quIIX>2ǚݰCf[9KGޏ:a)PP뒘:찟4N5eB{ulٕkޏqQ_S"J* U{k^vL;'VRqM ށb=}Sь-"Z:W/YFl(""Kۊ&N#6 @+ ' fIQ]mcմʩlz\pYuILnRjjJh'v6IƦyQAd{4^\6=Zm..v@XIIzN 6 ].E8t23D]ވ.7C<٘1KR,fMe&~vSr붳K${s鶌-vQ=׎bjJ«\z`$C{b%mQ)7OY=5G4/R%Kju9uIriG)J.5.H,K,iز+/a׼K=sD\z3vSx(XKY+5{>%ᝫM"T{(|dh#KKb@{b%Aj:!cQ<},Rش;/by?JV X5W,m\z˩Kb~j/Us- La4[O^K2-5;Ϝ^g~|"kUy?JG%gkrQzd9uIv,v|XIuƖ Q--*.%,o.MerKTVӎR쉕Tfysi6,M)bۮT&1M͎7K/N%1h im!M L:j6cˮ]~j4`\z$^%^~UkixjFc-}weW^>~j/;>X5QUlSx,v|tXI=gXi, G+K5Gv=>V d,˩KB<[O;Jkz5,coJ|0΋GޏR1_Zr1~j65\z\(r<vb7Rl15Uj^Z+ʫ>>UxgO1+\N]GQY/5{E/veT;>c-^Urx/f,n,%vp=y՚e}i9y?JG ׳25XTfYN]C{b%5?+SS5Ei]زo}YޏRu So+i 5? l:7%ز+/ay?JG.%i̮(WJF"miGJSFb7|o-vQ=Z=#;NKȧ0_6Qmcμ]~j#qdM˥&r,.niG)Rd [Z%5wve*T{~jmL|rцrj{b%cN`. 6IeW^®yI gv}Yv%.veOЗVhNf7?TyUgחQ]2FK_>3 G'/!n-^}5"X"\㜫;q߿{8?I2ww_gHhn}NRԱpͣVfA8 I7q@*d;F%Wxߞs+@!![s|:&BrϭܸN=)6 \]2)V{Wb\YqIVqn`s@7;F%G!G\ʸuJ듒Bn!(VKwr5i(9Ϲj 9݊_C z|ZV :&n\ ͍^2 Q=nd.i税5o$G[,fG _>.PuXJIYWL[qkNn0 ʣU}V_3B׭ݸuǔYnTT$[X5'ω4\BЍ%Eݾ'ݱeW^>vaMIaO h*,J)/v?bGmRKIaO TE=}'=cˮ]̏RSz\c7E='oIhC%G+)) XR{Rv%욷Inq'k1O=9>rH{؎OP K9j*@K|udvU 3ر:'X`l+=-^XKgO 8_=}'=cˮ]%{YRD>{R+i)- 6|-ve9֐ǵw8~${`U:+iS%cdߓض+Sa׼=Ğ$K!fzIt,Ir09=ANkS:*8&뇁r;Gi'XIInucI^InwlۙkJSBݰ%:~2|a0;GTG[{"/a׼kSz;Ύ+?~;ܞ zNr{Ɩ]y =XlMr{jvW:ΤlǴTb%[Ej@POls3nc{v%욷`Kr{j@Px{#軓?E,G?RSßuvǶ]y{>ܞ0P0y]?ؼQVr{qpܞ ƒnߓܞg."KJ,?uTqŧFQAv$VRSzb7J-*i!rvYA=jij;Vr;j|~>ej[5K}Orcۮۣ>#a/5uFQ $=]ݦ׉ԀXUiDA-v=ʅܞla D^*,h'hn +)A=JInز+/a׼N&=5VђZƃ܎sN;`ZJr{jgw;vE#o`,Ԁ?Q܎x{O]}tXIInO ƒnߓض+/a׼]r4"G9ή UWǴ`Rb?OJr{jVu^m3%,#ǻXKIucI^Inwlۙk.c^=҈iRu[Q Dz+i!uaE^ܮiW[Er{j/ь(InӲ+)A=;[v%SEJnO _I^WQDvvҁ V@-v{$Kr{j{bJnG:XIInO ƒnߓض+/a׼繜JnOͬ\L^[_>ܞ}wPٖu;K5oeSzez/u%GʶO;?1V6ԍ%yݾ'ݱmg^Ʈyϒ۶S\RzK: eAp."ωTג4A=KJ<ʴ+3y.SzۓΎu%GveL'4xBԍ%yݾ'ݱmg^ƮyDBn*~\h#u[S/&=52uvǶ] ;'=5; s$y=oJn Gy$Ƨ԰  zNr{Ɩ]y ɂܞ2Ix ,v@ `%廘5$K}Orc۞PY޳4~Vr{jEyuo+=Ǵc4ܞԍ%yݾ'ݱmW^®yrObb$ݭH;XKInO Vx-"Tn8~fef8堼L~i>7i8폄2^_IªOq|17|^) o#k ąD{']d뀅#s#t+3,5lw]._Nxoa?Ylݔwq=._(+aG}{}? _{r?w?j endstream endobj 46 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 55 0 obj << /Length1 1716 /Length2 10012 /Length3 0 /Length 11101 /Filter /FlateDecode >> stream xڍP;ݽ%w ݃wKf9U[T-_{ jre5fQs;S33  ,@ ;5:KD rt@d"0q~Sȹ@l6n~6~ Α a 6(lANHv`K+4Йxpڀf&g+KF3@ rtVnnn,&6N,vBL7@rt~7 P4 5@ \x@f [[s#%9@MVdXO&_g`ca;_޿mp6137Z,@IJݙ `bkdojQ @JT`_99흝X-rʒv66 [g'IAf/Zڹz`[sMسj؂\@Y\@ rͬXWCҁ= pvtx[߄09LA`[A;zce2^v_V5MMq?;['&fbf0slFW򕵵Y1b׿w,Er} 7ΰ߆ r@PMl ^e^M@.u&/k jk NR`w2YS{ `[`fGXf/@53`\GG+~!.&a+ 9#I<V񿉇7;Uo{3xKwB6+__`  _/j/|Id7rؾR$rX/VjX~9 Kݜf\wr!ؙ |-(ֈ$V*=לc|}UhR$ݥ<٣~C |HcJӽQV1т}nRDfumGoM?kV9^4<.i C3[*U>O0GiDOQfNP93"0`O]^Mbe>1"Dqz鮲GN{.;RB_b x&zEfvO$LX,+ߊMՖf4UВU#xQH[$TRe?>RkC3i;8hedES;GN4.Q(eqDt8Evfܙ?1YO;jc>ڡ.G(&FP;FsZR- cp7xfm1n K5돒ٸ+DBtm4B.~Ի]GˬpTW19QQ"?Dmhٹ.6PxSmnXf6lK g/3Bi$ ॖEKo9" tRXGܼ#f 5j>CNֱ\怋N; -}}у ȥ!:, eV֝u*RkFPIfOV@ Q)nphdϕzx>2p&oʕλu-Q3NI9V򂵀:eluJH}ɹ7NOy-đ<l'Ь)37$}ʕJyO2\x1НRK?a_{fouCC}$[ z*:JO EGNRYHn}dNVh oO` ?jK/`Gys73J :J4,WOCb]1W6LVFWd|4h!ۅi/,+'p]bz-KY L.Vh_ȅCZ_gZl:J=÷,bChVL݅\f"zq `7I}*`wѣ }\zϤDRSWO]ֽ*aŖR:ؼ!yu)J:}Að0n"Y乖>ضdA 3P7`ѽR Sv^i9tMDHE%-[«Qjs5[yS Kg=Xaoj j5xۨw{󛌟O4'|s(&~'‹$Ut[fa[C 60*3AV39LT)1N0HĦdOfD`+sЗH}嫏R'79q8>Xمd<ח"N!V6o9nS je:֬DLi @v }J:ŝ9=x{Sl%Y%1"m YYw/Խ:|NZ&R<}\s!?TRP; 9@/HTk~gmp*o,-.*_Z1yʾvAS-9 9pNJIy?6:=|.6,ӜՔ3e*9$RZ.D}jW j$n(,eNxЖOU 0`#*P 5ew )Z@#IgiD"=?{csx^D܆o`cr v&፟kq< jn☐ooc1_.)ȟ#>E8wR#ܵ-l0yJw"꣤^RO4\T>1}fF;#~xoYAx|bߴ58t?<)k ]Mʥ>Сz*he%@Aj&Z5Y &qI"2[6jws 'ȴq[c,I{ؒW`T|%&:jQqG4eaML ob6{x<ڸ0#eN*`Ɠu@ns 𕼇Dt }u};Zrn-X:I^}M|B J_5lhY@( {)%m_A< ,3G<6IAowf7a ~XǤ3uD7}w}e& nAzD붂 iTiGWk~U+(!-Sj_" 7_q}w B$qv*N탊FwS /KK_-`uM"k-LdtݍRYA>:;^|q.Z%ڂ߬m^g DJVtjL'xUǜ`'@,qPp@hu>5h3~,,$liNUجiDgX> ǨCޠ %cADސ *dS/A$aIΠ>?&; %8P'QaR|&)G(E?YSC^7CncM=oxtz.Kb~{vPg[Ok Ə𗸠lRJ-;bͶ&|%F쐵DB ׻!% TOr < }&I01\RVkv{N(cXԏkhEy%/ZةN0deJ>D N-DvJߎiH^h{:2xC.TاN :frx]J.̢EPEY4nE{814Қ,,fB*;Qs1aZ@ 5#WJذ \#279掇#n-u*ou?"/v!Xv:$H!wy w*e7А/[x#*TH1Q+UZh.R|p_񍇗+őJ7{_8/޴@gx_WohJv +K?b6p.BaKU2xޫ͛Z1 kZϡ} /%>0@i\51û ,ʂee/AK Dp8 p!j˃Q+cG<8FZAPjC-lN<,:Lɻ:Ř4AS71_R=&VoJ kGjW -n*݆QQrE)Y;8>5t?v7!JP1#ή&$;OmqCr#"%.# bk"!<=Mmo,48#Q{32\N(CIS¸nӜFKR{qƐ+(9%‹N%l)doQ'3?uTɔ$uQf8`ӎscWԃX@|3A*7kWT:W!|^BUnN!{{q`;? ڟRG\dgҒ0xBuo[kZGaT%L{xEԲ'r*;(jagy噯'(Mj|Vb{"βxP !Lo}bUA$'bs1z z3KEy>Wˑ"#u~!o] ?eQϦO3ɫ@"ҩ%5r>J,>3Se4gi8ܪi mȝ &#~sfqGxhF+ {?Q(!alM;KE,_k{Q^ˏY*hУ{z IZ4}lv& i|=z c"iPyDPw6LZyS#贰EbVyjfMғ9 BhOAyU|S £( wTN0OM{O&0jc2CCtSj&r:@zpbS.wqok˦C (Meuk-l ! ~yBxƥ*t-8qkj8ى:og`bkZ=ҺN;rs5)&벪BAk BZ[0d 4 ?vfOUYw2W$;ѽr@+(H)K%Qْp8]YsvxC.] w\LOد 8Aano =Ѭ#XVHL{"4j^دd˯S3 o#.«'l'kMQP{[r[6 ޹bvF5rd 4֠eD t<~jߕdm]y஁@6?~R bDM\kնuE@4~} ̇T3YAEdK?^}iyxia$.4|ű &pھ*HK]!Bb8po5*'5Wyz)wۥE I8kLh!8c JY"s!fY 随!S]C<"4mP{˽m@["mXH4ǧ7\Nً0TA6iQq7ijx7X$sXvYBYn5c]8ߚ,Aq>jk2?jWnGQp[}Y-T;$sZ$] WG9FoަEҀצ15aK@ "mڲA:]l]=S9m{7dJs՜+38sYZCAD$_].)sfvOl ]KB GA8KoJpĄ.U|SUY>smRE:"wk{}G͒}qe6w(+ !I2\{/MDǴ*9?Bv~+4]E ~n$.,4L'Dnbr^EU:jkle cބOTN{O庎ߕR G>7ܡ@lpi𹱦26.g ={63yg#`!a~8R{UIYLTc˼}tnZkˍ)MC=c2B'ӆ[>lոWZtN98r>3 ϩ!3Vt'}%0̖_,拄Ӈs\Gv+)NCWįH(43˞ l(Ø̫V@AݏsAd)xo%.Y9#CvkeuNLE;3?ɐy_V_:->^;(vIi M տ8XkJ5G>o_.+|f}m.{Q2N$9s%鬲Nꪴ)VkǡJW{hz:΍-1n"&:hh l H"| YR?aP@li8ԃrr!rv(T7ZUtZ;Z ?0[EIJ@Zi(F]>Delk'1D'Q* ǢIbWGK"C ^efBeHФAqQJXrWCΙu/T3>?9հšV+*rKFiť' YZ*W3HT|tn&N04cz)ɃPQa4Hå^Forf5%<xqo օw?4q`͜oX;@k 06M~-nS `O?5]AL+ Y`ђsYJn;`GF.Xk0LY~ȅ??|K83esT&@@d}[ ZwdSd}#,&Zr:rI>bWC e;J.fFb{]+K+^=Pl( jPDPØ;>M5/=:13L& .Apb 5*,v5-}׌AYL|]VO\@jˈ9܃s`5T.*`S=4i dA$k̯zp4*І(9ȇO =kVG_3mX9w^?OCR %_Mi J{n˿>|+wkQ"a_~u9¬$JFx,T_gb;CxHQܗ9; O.;FGת# Զ~[?+zYp!C+4>ݏj6.4y+$vGklpAF,澤t4zl ~|%4d#SY[̎)&nJXoUF2)u ;_ܘM*,-ĆΣkɤ q٭2˛ʯ* -5w %t) -9bE?X0QCVO#ߔD_Aw/|15\)8yXYB{\C0S:F*9⒜E%C@Sl wp^h:.qZ9 n͒]BaYȄv:h\ W6"(ϴ! xWaw/sl=O$c닸"tap$g#J;3*["z.j_gۨՉFSHܘ-OĊ ì ?yH134sj}!~Z%m9lk,gu KyaO{WUޯHӇ)Y8C'm|7|t>,''їyG{˲D+k%hA%":btna:._} H& |3DnK!Ɠ+y7Ƶ0U-}:&1^[{I7F}fX(SC0O fdڌa9xB& gnTGMq J7hboLM-i즾F]ߕ8Ro;Hڐbd/Xh'jo?*owמ2Os> Q ;D~9y\MŅ,jZF.NC Qk5=AR ,wTj  eړ#(87sӣPf&229\(W7Rx]ɷ=XNu~aZR*4tv"v;$lIxt5w ϨPXGX *7Moŵk/،)_E|@OMK6`ұ){yܗƇz܁լ7}uZw'!=h3e%';˞-QUXGd'ك3z&fq'ġWѶ';Y7˱eis7ǝ%0EReF-y.{n9'$S1o}2thh:(6 WlQ89\*.QTu@J_\&gnyx E}ͯuoʌ){ Yύs?zٷZC!n,NE;^gq3-1?zi?0; ~րN$58eKo|f) YvZWCc%=MLL9sTh02,f=nuSz[+(dah.>#(cB>$F즩htxJ#)!}a5"(4uP!rGHGc{ܮҟ* endstream endobj 57 0 obj << /Length1 2436 /Length2 20864 /Length3 0 /Length 22273 /Filter /FlateDecode >> stream xڌPm ZCp+N.Nqw(-Nn'gw}oLrוLEQ (WTce3!QQi&#Qi]\A| M4 S7@`ccaGх a(2HTN. +k7<hMn@{GsS;9?&hܜ===L]]_=oj=%+ o!/s;SKeu,!/7`rXw}p;lu W&C/˿Sq, dbSq:/:i뿩W=ǀ 㯂qOjwYY |2Y>*<Rp G`]?琹 n)s{#-/84uՋz2NRjc]vv@OpMvu[Z;Q{3|DGjߓqn'dh 1"Ȟ߳V-t;g9|gwTB;iʕ {u\O31esTf9xpng^hs7yr HDZ%zlq>klzxcԾbir%CK^%y(W2eՁԢZ<Ɩ{XwSa4C; X.uјn @K>Kt3M9]룠>f絑!w#}eƒDVQ+|Y鰕nP@Y{< =nC;i9SٜC_0 } Rz5~vVo.i KCz<*#e.lI›T!is+e tbHA=o/"Uha*1#CGHazԂz]3EJo(N4<[Ѵ5{K\ S],}eJU vyQ\nBέߗ."Xkh~Af02bUjʓ\3%\=ү5QU`b"y$@ +KBƫ@isRz~FaBKK}}%wX>~j%< w4~6ywCLMqXP&N[M7K9 iAG2~lGaiSОy4qՅܽb.KX/^ʂ]?%y$_:%GcFWiU];\Qy_Hq=1n$bZ(yl,Z\*vmɸxGs軯clTV)fu>rc|ݓ2#3;KQTM~((O16y*ϭZb;nrNȳ;y2B@-x¤H63L6Qs̰H KRn= #؞?:VojekaEEXJ@  B)SpT`<˕+'8LC;%dм໣@ a>o j)&W{Pdl)*.NI=CWvLH!bUW,ikk%atwJ~Va:V)3֟ъDzy_z} %:-J[,xd!gr #|)cDfjZscuy$:ɤQf`p($&k\C$ # ةgv2(ݒF2Z㔬_=H 3^mOnqvDK"Ʈs*;ӥ;ïeK!w>#THu^,]C1Y&o^c[[ORॗ9y\O̸Y,gr@Ц+^#0Vi!Bq[1e1-_?_s..Xy)F2GKȤO]QCۃaЮ-(&Z֛#TتR%*[衁 ]*z4&5$(.ߵRJ]gY6"^ fĨAޣc>l\ :V5{-%W.0\c.5Qm@I1PMB(E_ 9=0RX)WhR环C`PX8w)zֽ%! }VuJ|OPU8KS}Ks,?:>k7X^UM,ң+Pq_Sl5hr $8:,)& 8 ґgJw|XzTXH#PlUriGRhg[(H:#NJܐ(?u(M:XMσWpXioi?! etwgK$ڎIŖd Xo֨c+uwC]^M9*S$0D0Ӹ8"AIkӴHwىB9#26o]]CVӐ}Z+Mn7OVG!=@g9#eUp[BD]:M+ 38G*`[}ҴFۻk|+ל 6-lRefKo_ɥ+ki,]Hu5nZZtZblƿF+˼"Ǒ?hLܒk(@m 6\@\D[S{&۶1e]?{}g W"9lDǝSFzAfS;t]2k#sf&LJHG !'8=J+^kJAHCS{%vi~*bϯG0;.Χ얢! /k;ӧ3.o%oc[@E1V&â0,ޚ՟+sEPOCА0աIM5F6-BYly5I/eNXj=l-v^¯&w"P~0Ǥ ͙CF߹1zO?`DMD5-I{lJBgt`o3Z?"X?腶w >c!5#=/j^et(FP> 4p#IZ᯵#: >'a/<(W2 gXYu$G].D򙾴i5n,?!ЏVY=@5lu!f%\&s0k"ӨoYؘQ2mIR1PeCB.TGy(7{5f6gWA:WIE[Ϗ ˥:eio~ '[QFKR@t{jBL=,z j/s{'w 4]J.Fu ]+x e &inop-1bWKo1U87Ì@Z UTITabdf(. h[(vE .nhIwtOD i  [=C},JJQ燍"풿HoE}0'x5K&&F@0AqzU|H>lEG~I>Wic~B&,4Z+Ek= a};\i^_a]=4c[))i0AQ J}2sWS|'"KRJ:}k, t֛ pR+LKMPtFӌ$#$!nuc`->_nػf >-4Ǖ 0 Ij&-Kـ4#lFoDjDh^gŀw ]T%rqF(dB$ZȓfI']f7l9M UHkx%]("IH5~SP{ Wfų y/ gl MKOrM8$5D8ྐྵذNeDaN׾y|y'Ox>)K5Yu]@O&9 fR窘:'о&\&î# AFzJ@'\vTLvKMO@{j\t~Q YqB`$F$7 ly`yF5]ZJiܦ1S)>:F IEa[ylT{[{F?HǎR|kQ9F z$uDuIuϥnx)b}EХZ_uXUd1@l1@Ԉw_vUmul!vOME rvBFl4@Y?d8F)}F jzPbRU]aki,h>85 <P%US@|ڕ5bZVtVhμu:% .啼GWco$PbɞX!*1 iW[A|ʹ#HK9A~tGZ-d1#ւͨĢe0NPO01ZzVs:k<T'ܣv.cq{ِ xڷXY&5EJ>J\]oߧ,O ajBX=zR;S0\;7BJL;Oa% ].`Mu AsiLa>O)TUl&Jp ;[?#XUqmĴ1l0wwq$ԥCOA$4YrAeP6<=Q=Գ"Isns2q®.%ϣ~˷GL*5m>I#-u߬IP} ~I,E{&{(쪔c{\XH79>2ۺbN3]4wT痠YvE{_V"¨rO+'ss%ZҮD\z)p;'8A{i73n =G~Ffe1KAkZR400_ȋKYڪr˂s`VRI^?ݸ aрOb礨C)-3u#FsPaaG>oz#=H\?'%>-izS0\Us_rO\6%Bͥ\j:уIQ^D$4,D:Σs.<[*'$)pPp/;("UPL.(oB>;|tg"$U+%k Cw$ خF[su_AYLhGd_LfwYؖ!.9 AQ:@u H2S>}y j6=aI|rl%o#ߑ9L2l'M@`2Fy'HgtwʎH6Tx &RZ&o܃'Y:_gߕrD9A Fd.iUV A&lyրK+ؗi"LyQzM%'"ǼL[h /[<{{OŦLc2r`.\!/rnK+.$ɡZ7T.ǓŤNBԤRrٚ(҅,F$^Ѭ J@?mZ paUrEV\?U<`'d鸽fKѬEۙnNb[j*-9|Y,Q"=gO_BzcW' cR #?[x:Qę5Q )NvWX?hfuvcݳNQo}y=LFCsZ0Ml{\a'=)6k fNb5AۤIp{+X>leZ&0pIǸ~CWw_7;Z8> w&~ő D9tӫ$[ڦRo۸mViW%sRxw10pau *4#C'SLPư ׷r;y|>@~PCYGX|Ic϶~AF89sΧ3^(蔝ucy)i|jJ!*jIV;z[_$k uԅadF 抺jӉBGmZ* u+K!2H/ǣ#3V%mԻ#[ll?Z0}3˪&!T,rYvqciZ<]*ɲlnr[+\u Tr_` !4}{WO8x1o]~5$ujfXA!x&rAc{"ة= 82'~J>;GT#Q_+]?rғ1| `O~upOL[F:?K B܊i?wd|:T.(pTB(p`BYщ{$u1ibd[ES)w u?Wo2oCcΏs4V#u*XG& NHS5шvN)bg0c=͞E_C5WNH3nL d&cN:x9Tj2/8l(2vA\|` } W!> ls(FC0#9Y[ 'D .@쾑Ưp!~.L.a~&3c.v~v41Zvn0?D@]d"We&^r~/LƙC-*m;Y0j7GMZØCz[9*ڨSytxOޮS̷G8{>J-9Pg̙sI:`DAȚ/zg(/8T֓*qϖ M,AZUB}[v[ v0vkN F4<ƴB)?SoS]Z :"(K?yϵBk9JCX CF "ôSoES'py7&_0c?xW1J7%TVy┅B<"V$3gC9-QPgG+ɍF1n"߫u*;%@ќ~n+Kkph~zWwKeKˇe']Tms՘c{:矛63.!5W#fGL274̟ge( Dٕn;O\7MQ@@bl5GEԚDJr]9 ykmrvhu)pz=*>=F!}/a~o-O%J琷0Zn~6{L ݖ;AŸT~T.+J,FA8x`q[B1t/G`G>ɷQW|hNMH?b&vD>*aY{Va6]vd)1Î14*\'K2?M֝` oxӲzbsOK+ v>ₘ\CvDo^OHM(ksZ,%4괦)Ew-rf:)ZXDņ~ \MJˑpP#\ٝ4a]ຫvo N )j@2~/fqI4;JmN; IVoX}l[UT$s/u@B<֙2"~ƳM.*ǣ"U!"s韐%?Mª.BߍGނxw0Pm!+NBC6y cSC zl+3avTS4U ꢁϪࠁIը?~IO{*vwaz[*Q/HA2FzGz$_OHLYSb6 ]i,?gLrl!"rRvIe<WơXN>őhq%VB:|@,hR}9Ax^Չ'iaribR0f幀Jn6' 3HyYqd0?v&SC^gwz`04@%*YᆹIwÕ!)՛7yzd_\x0<ԈkOPuk)_Qī'1:tQo}_zmZMi j2$/ͩdθX*1{e*rxRg]ab: k@釜#kkh( J^O(OKAPP%MV(ɔ|8?5F5"‹}w }V50([?LzY1lKQBuAFdk|V_gK(:hAgaÐɑ-6ᇉ|5О +{;*Xߡ侨9.0u'1#_׼9|@jqF6:2XFƂ{SWΗ6HRz^U~XD@Z6A*2-\p'D9Pd0<6 5 IcJUlz.J$V.*E 4ޕ5R_;⢓0tum553)ne,堽 SEׇ({3c~62Hy!1QFnn!=Y S,`~C1dsibcV5aЕ:U(d"~SX«ߛXq;I6e* MMMk'[QPΫOgrN-3.8tSs 4j#0;6V$>)KI r⏙g^{>_23Yfn¤`\o oJ2c{3 ߿$4&-bB*+w U&+s=d6B$ lXa_X1Ǣ9ClEJi~Dp5V]4ߞ8\"zb:IS}Њzs霺Z[n[Fh8XtҧѠ#rHV$^5&n*1EWf)/B%R&B >񟗏Dlˡ ~5/FwYf_Ͽމtk p-cc4>a ")ˍA/q&xC7" FND&u.ᏕJ)yYVO5@W^Tz w;= `:5I $ W&> R2P}SOs<1*HÖHhEaGQh^0056PְxeT{ݑVYZ8f$/o~ުūf xJB'QeéxTo9_nx#EKyg\ם鳝2|r-&3iўBlh /+ cp|Rji kt4ɑ<@UcܐnW|+i?VJ\FOqٯӘ]I&wR;MVbK|@|'Ň*fC3XE(<r7u~@+eNMin;hUB~[}(<{)7;6ty4 8P`kFs]eO3-c% El~ĵdtr86|hkݳҐr;F8%b--Qŏ5+OOO}פQLg 0b?!a'uNc@[9 @f!X)Mjة[78'c=ݯiGϊ&<]՟\j']ТF!1B݉z~t_hiV cceJ)ѥu=Ug~dpD ^ʓeD V7z'+0ӆ2 HGz> \C" ;5]ǎQ0_/ m")})1* P@c~a(xV!*~Zǀ ƥrD<4cZZDNIc;~J3F2dln]F!hƵ,\lJKMb)לAJͻp$bwAӂzCڒט6 8jjdF͒&Ϸ^Caӛ{(frf̰ G>&܃l"{io nW[[UUn|d1/=Qy}Yש=G4r?NVx!6CJi f?RTȔs ,̾W&Uwh)$`j6b7 YWhKAWNQ4d[n=ʅ9=qp0hiaAf-)R(N98Q!]m각SAx<֏Q ,ehb'=CZ92-ʞ.C)7Υ}$}3{ -G *͵Jl'?x4EջS/ OѲ>uܪ8@Ho+Ce8١+^=9gjtƲ.FzLMpSKA>K5oj 7MyW=ھYC;qů)nr]OU?c74$R hP +C5y]Q*~KK+qCU=Z1e]hUGE28,ezr'*ɐ{[ Мt>JI뼂|*j2 |{tQ_:Nl^BŶ+??Xq4U㸰~Ӂ1be1< _Mɕ"D0L\S(xl8vV]"BXiAE1zSPBw6bcG߹zǡ%o 2DY k=\4u ѕƋi&% ëm%+hzY`nR SeヒGOҚ`Q14yg*9&bc=sĬޘeթː<*߫v}GϷ 6WHR({Lk%KaoYƽϼ^KҸ fgrsT7mG)zs5%ЗQj( Zs1& sW~bi&4iXdbC00 a,Do-pu[~c}'cjeJj2ah/f G(=C6V$KQxA^?VFa:K%`fFc k(=y&O{٘-LN\ê7=d3]Zfn?}X;BCPo)p"?˩z`DXf+!pM{,[S I[۷aC+'ʣeIWd.v%d9]g\o(V={rgXu M-|u\A{o~‡ӵ.2Pj/1fHJ>n8۩ϬׅMVH|$vM7+Ǣmԝe/ }J4>>&О`GoI+-5t%"qW*c В.b?Qۏ%Y8UI?v̓-Aux(#k$N/ii^dVM+R![ OTXr|rU1BM"DKWRE=.UB A b4oNa -k+uġ[\ vh:Qa) A`w9p̸|OuNsLo.u`$YW`rF"o4a7inðJr}b Hsc=L͜B\V;Hf4|d +~&0]cꊒެĽm:ʋ /~p$cjJH~,񆐖v^ f}b@04˜Z|5pvU8m-mHa?cIڑ4)ע%8tԠNgnG>jDD г!amC*lI o.(6NJ¤mЪ:1r:|abyg8K^gͬih|ZaҪ d[ DhdǶ}701,ߟg,SUkIX2b$ :N q| '.0oxzFNYR"^Ҿ!1TIl|5l Za|_* fD&ྠ&᱾7(AWK%pno,Dj"_4vt; B &}>8&=!@/K^HQ]y+c)_C=-}Z(}^SM~j?ӓ- ~/u/uD0)Tc?RSFJ}s3ɞ!"^]^AzWyAS=l^zt'<Άȅ}XqU%3LdYHŃRw5)$n|ҏaqR?0fY'ٰĔ)Q`Qu's숉w\A9e)`;$,0TAI NXf^3=v*t} >&EVepS>Xv]QMxi $?,s#qL "RB{0J) 569}2|nu!cA[Zicmţ+7po˄Yb"evu(m?K}6y5jDW[`s^(hDV/lvIG gj b-~3X' !+Adǫ%}P>^SϜZm'q $"0"3`c=$E0%"œ XrΡ #=9c~RK2IK/h; k/EGI 겋& 5M(=hD@G.V5}h{j z_&ee fLeaW[\X~ݙTg軮"Hp٭BRn9a<藼6d\geM/I6Lı7`c10wUCڌK,I";ywuZk rTtC0dM|E'7X3cz ˏw,Jş7?d!E#c-0FjG拃6y̔\oB]ݑO܍o thO`ʿI)Qu@]Zk!'HߓhMkl%_uLE Z) A-)Xl)X,𐢒}ZH,Q9.{jadnJ_v?m[ujZ!bn/7<ćʜєIxyk+8V(cN)xe[-+#D ,Sq%* /k}̌n$۽ -#z3 ) -W Yk.ә_DI? (3*f:tq/Gj}%̲H\r-QDk3_i_8/ґhKuc%ʎ-{eO u4T8qqm,:xlu0,`UƷonf/9 lW'TWM K\ zmк>?jV||&M'{Sf~[GE#'(byjR1JټTJi.VVgD qF}VLPE@ZuuCU~TNJ{`D89 aWj1$ 'ڻIѶR2`c(Mx7@J<c) by@%UQԻd6mۥvd#jjd8SmVE1l@W8KY򅸔V( {z3wh75L$|QHqТҎ cvrCO7;&ȥTyvS Gg` (%RZjl+-m¶P{.p;D(Xw4ؙapY[!;9<0Vg-,Gd~R!KY? pT.f-Sg $ŸP6dOi9d@X%ҟ8 $7~v~,×rϵhg0ŏG] ԱnyG[ qGǭ^!=!Xڈu œIK^Gv|Sa%{cڴGlzMZA1/W\<]u??g 8ڍ+n"C_S;BQ 'QW"a m+ EWDSg]TMy96+8r GW7I|׉H rm>aɖ:Nӯ줪 N݃)/S41e%$jnY \:w{+=j,R#YhGe~9mZ$9ӝ]07o䅧捃O;aCƿWW(Mh[PBޫkw7 a0Y[Aku⯢;}|6L \mx!C;ރYKRǏlD V]wnq8ql֡!%\R_SUh7N?Ȼ; 5&K6u ;p&O(C'Q%Fiag@-3@F1D= ci D4zSGqҖohnAeR`kRR4="^񚱘J,WԬ!=ƈ}No;͉gW֌Ŵ &@q=AһUΰ-pDT@P.li f%XH'ѯu{đ ]S}mbϕTvlAD~3 n_Cc;/NisrvOTV ե3c>dFGo4ZDzWB5tDVϏǃ[\ɹ(D#/Ug^h4F7Ց<+՚d# ױZF7! 7Pfݠqq،=LΒ|vEtVۣGyjnknfmequْZ sXt怙׭ m'=IW4B| OQ/RhjW2*UloC ['.f V"0@5<v G^tXoLt&u_aR\H߉Vfmִs޵|GfvQ%eel;Gxw<#zNs8*lIgZ8zƱCRds0ƸYJO >jr[N^K;m̝?7Ykv)rIs A" ֶ4SЈ0)v"H|m>t#'We\Ou#22 j){f?`~sRbLA3WKt$8H9%\+Q}Yҍn|3"V~'V;,{'cRYEpw S峁tJ(| NN /Xa${ endstream endobj 59 0 obj << /Length1 1994 /Length2 13568 /Length3 0 /Length 14798 /Filter /FlateDecode >> stream xڍP[ w!Cpgp2 85X܃;\{kfiyVw~gU5,̀Ҏ &6fV~:;J1" / 0M&ifȻ8ll<vVV1t$Ml,JyGJlcev|Кxv96 5DsS{ Q Z8񳰸3:83;6.u30@Of̈TMk.` M`oc9y,` 9E?_xEdiX*Ҋ..S_Ύon6foGn S%6N.6[@@3_Iڀoedf@ K_IX:hl>$c&B#XYYy85_Nl2vrtX%} z;.`W!,l]f@+71v`>[Xz[{Y8=},ҊJz d_p|7`*t['`?f𿹔ߚ\ool;o [߀]VQ:{g]]_m @T*-l\Vm@V-BfGאۀ6m+ѽMp~ȿUGJ-0v.n)lH\\oQzf˛ -=_#%qX EbA?OXT7?Ezc/{C/z; ?Օ_-[oQX Y!+Jc&|_-TX@EXf-R?7_ ZGWvNo:|M#oio9E'xxv6wy?=@9✣@m}H];Oi] :&Ep*|*]Mv:F,u}e[Zt[|xkZۣϓqnnxѱ>b&M=>AvS}tEU-sW<6WíT>cX2Coy= ;zh37Әd 'zq^?( I1G'K鳸c)l^w #jq~Z|hlV$$8ϿW=.x93$ټ|RGzuOSCn N5pj)o`|uxD[GUv{&ЊǠ̹T6=+,ν1g #T \I$hܯI\oRfg}hTE06=F˪9hsG;.*(Bo sŕ\ ߔ{ +Ԯ~yfX*\n!lx6EdЃ_Js* X (b\'y'ajqVBs04݆yHSoHڥf Wnai-PC-ok妗ֽpFspB db] rhL⣄ZtV@@)~" tas4Rt+lAfm{蝝%zMg=2ֈNV" [j9u{VdP1u^-jrkav%A΃a;r-v >DbܠMNCfTԜ˰r'tn j,N^"H^,>9S]ld:- GiS("IV%Mgb_'vMp3mRcz w[ Lk=x҄EE-|fo&i d;Eaې1@vY~^_KQ}*7=k91_rr~fT"UbghE=zs]8nQպm`mo-JIc*Jt{-$_"SƗ Ѐ PKk#DKb$23vf/O2Cx?7bwyḭyrʮ*Q_,R蓕4CUj>V^p:Tj?㿙=e 8@Jue߮CEaw|gLL!vSJ+cOq>Aܽ 9QJQdsluUڝA;6rYft%Y6UpsZ8>c+1!XQdNUX Ļ}>TPšvJfן&T"hj$W2V$/Hp-+Îc؟6/]poeHESj^Ө_ NA:α(|_ ~'4܊ON@ q5T##GRV %[ʩ\ ?↟Yu#9$WEUKKs:i_!VTI].-0 !a>ʘ&xcĎ^0K}IVDLÙH/VpR8 R>(ܠ<`>Q~̼|/1}-N(mzx(3"N6bs0HGx '+[{<0 QO~bEOj"O7PնI3+Mzm d̒Ezt2ȧo`qSQd=&"ybQ8ݎBlk5wR +0ywgr>8FyoWu^Gnԇ]t޲nt5;ŬZ r7na]`̯F%|n D4r.-gA)D{y=OH)Yyp;|{yx}Xv =Ifʍ\8}k^*bFfxnbq daY!a*GK*9>2676}YG(%7_gn (A 1,e ^=hTRB / B?QJTZuț{6?n/xҵX Ϲs0((SzP5 c%ָ$R4G[QMKӫ̸,&UP4V:ڈ gF)$2IFi[fۗT?D'8KmfTrU&Eg"!`L D6M?bDЍs.|Uͯah62_ݏ*8E@Wis }a|!zIuuI=BI )宗OZ@?Lt˅q (6Ez6^ǒ{7]?, 7fOZ뽋,D/ ;$Ѽ]0aYO;cgj Vv& k+1)w!|9o!qc`C HTS|oZze'VJ,2cC3B##15C"̐__e{,E4״uz}'(w(;Eqi9 X%B2)ܲT.U:a.Cߞ`H1I#ZJ *7PuYb9}O="%LM:Pjޘ:V pdw@mb\#mqI#;j[9TDJiR\bU>=TmoFP Ts8W\`yc&o'lR13xspٷDmB6T sF6PPbIX٦/m#QZXץ)ڮ%^= .`YD FMG!j iVˀP/e`3}f3 FE\59YwWH@]`,KgIwb0U?M4 taP똧ܕ7%v=*\e)iyQǕyYHY, 9Hc5eANuvDLsqGcآw'YO{pHJ!UuA&gN3&^1/4Yȑg8 I#x.I|ʙ]r$yΟ{Μh[0x7El?ck;?5:ӛ[].9YJ`i:aC85W7)V|/rҌk!Onj-$BqQ'"yܖ, qx}qbug:m,wc3.E`㼘 w w_FkbI2PX^ u}+@p\L*>Z!UKm|{v1;|L᡹F2&WزKmlR:X1s xC {6Ɵ?{J3Nƴ47V*~k͟7|s'[thXX~ W8grF[S!Ÿq&K*DI~cS;i2X˛)t2H<Fq)SʨH ͟=G,>SJL&1D5e{J>}=V~r: ZW@+ORh'-]s! 1NWK_u%u\ɰ rd+APv#w6:ҥ@8pyRӛhYПlǟ4TK5MW>64j/ADSvYY/3wdbsҟX Vo00/?CJ]>9X 7e&ƖRV  !6hۧ*N@} jbuW5ud%zLP C*{k}[׍a'C?S!Bacr'`/ؒtD&{+~Y?6U1W%>#?b4P}K:USUcyaC .1ێ],Kx8ب~@kR#0Vl5#L\Bfh*q'mvaI<^EjJHiWDYcAA947u3Zi=e I"}2k|B2 \S\ 8 a m8k&gOuZS*IL0bR#SɋK|ʮ?(,(1lco+ܫUhMo.P\~$#G4ăvh e нJ-b{+yO g*e?ֲcpͺ*fȄcFJ44L{=@yiǴ52>~6(% ?$؝9QC*܁H<HM ,ЬBY:Joö?GZlpOBG8p縳 ;}YU}L91~$SB/xHnDqxZ{`H-^=LԎ$ uj tSH5$Qa˗o1[-pIK3B͓BjMJyz`~8h ^}L(z$W{{5,:W΋M-;?Wd2.畕#R-IsIӁ2;Oըoz.<-fFOF?,Ikx:B,~];.u8'Nȷܱ*f_uϹЕ" {QuS/ d>؂g3pOYZ߈'^\8 /7mg a6{/Ei.JazLrD}e;oTW/v;h^qhгL9c""2 oiE2rR-ʛ3ZNCCi. ȠXqՇP;FyD@nvf *\ tFM^Pfs#a5C~BB:ʄ2ȆfP짔^k B'a?=ZOyJc!*\":@ha3_Ǘ״i1Ww>[ߒԔgmc `D+48Hn gfmɼI%Eh5S`iEeH, KY- oЇp:@dIN2S4}5Hńx -#hCDFbQR}V`LFOýty47gt2ean(X\)L'9I4ymД#g9CGDKy2>C!.9c/'iugmNxXwݛ^EgۆT3Xǜ FfrwK QmR(սE#GCC Z^f|ȟ(2)^ZJ,Bvh`;̟,ɯcBX"w6g) x+bZs%Ƴb^N].lu8x\Jk:wr]3Ph2e!?qd.V|G^ލ2I:>W4@~K=n&^œ_ zaoz|>-D_ Zin\rQLj7mßdj,Tم[B$o}C)%ED!_uJGT@Ec19 ZY6/Kͧ!Z'C,WL ں*UKb+3?Sχ2.;45MPLD <:!'Y$ *hfd Ys 2i"Q7N/65`I~ȚCDZen刕rIDNW-x_qw)o3d.p,L8~Ko`q%_L\ 矠rS5-PZ@\ mX~sPCZ;>*2ўo} b Ȉ ^pC'S"*u_'Jl?dhX $ 6J½`{Κ\h>T/{`H](9nUgDm޷5/2'j BL$׆}S(25~Y|&ŐO$^"6({>I'o콘é˓pOP`c$3y$Eئ[T`ٖ+un*GvT)/QtWbEGo"2(w 9 Mc~cΛl􏖤F֩Hb`ʏ<-*~AX{z"ѴufG*+ݒC[VJ'}oO%Z گ0}H!vHNw{b%e(L&7UmH 䛒7ΗƙwmGX /'+|Rr}ymdhIW1tŗ )Y9_pQDv>\Iš9Rhl#&3YZxHJ}PJ++x{iJ-y uM}/2Urv94Q3MuO7 R*ԲNǛQOs#w+S)D'2aMx#t!'lT+AaJM4ZԂo4["]mӑwDNit™<8mBJݘxɣ*:Qpp'ɦS){&!;&ZͽhTVu{͒n3Oho<}>"Wi#|Ѫ7^xvf/I썾> ߫!"V$0 Dͽ]DCXFC>.<ʹnɊ̪ЌKt\ûV=t3 _iBG^ȚnQp4mޕ'/tm>uݠL)SaրTQх#W/]:rT#N4 ySOgfϻ3ԡ"禀yiv6Dy}ަY#a;S֎f]ati3vׄn _Z?aRh.!;$˔fUbÂe&qnR8F /3sAU"fԬ;{w1ie/wxٝ1j'`&p]x@! n,o~lǯ[;'=z,n2Tf)[jŽs+a3>nU|(%<%(sO{MSD}X8uqpkB!7tA^HVZ1FV}w՚"]\}mϞƦUWW V:iY_MuY*wϙ1W}梡=Q9:}c&qRa,Ӫ >2t4wKW̭BG\VSY]TDTW_&7j { A q~Ds\ cB & GzsI4i7E÷wI<~x9XHʎ[cKoӬϹF g١3Gz}0%^Tyš䋂Mتm 瑪(]#sJoi7U7J8GuQIi: ~;&<_.AteA2{KU-[bi9:`1 )Bl&8֧$ {j8DoVU ȐXekh [F2'T0Ww¼CR-1fCǧ᱈K5 kN^ƈ씱}9-"|.>9uMOE#.|[Am\ZL0QO=rkc@?6|(dg=yxYW@V mym'cI6qɛn)êلMMGgsܐ 5ye*؏SߵĘ<"MF $8WעlXuGJ(ٹlǥR})mLſ7&O>jjb.7%n)\_?ruql`; )<-߇4ONpg;L(y^S'C b%DgU11MՁ8֔|pQ~;Z'YMX gzu8 bj$d8e|ppGGx@i~9d+4ׇYzHK cS jnI9Qȑv^dSF:XYS_n 呂0-i[.EK1t^],GPj<} 3AkJkёVmAra1byjˆP 5W(3dv ͋"W!12CoQT!f]QeQ GW_dr 2mC]Tp"- 蛉1١UU@* /H> %[]&戃Zu 9\zP3>qgΨ4P2y!+GFk{h>ƤMw/0mjo˴edFBvƏ`e! a}itbѿ%z72s7.ˢe 1 7r&~, O(7e bO߼BkS $NaOgT55gXW uT3~5V HuyH`ž }R* z)NMO|F"}s"b!l<598"$wAtGp$ojh)ɥRL"Syڰn˴ BSQ-ψ|g. ^p'=P2?I2j nwW#aB sA3`#RZNwql`=EjK8?I@R(6"-`tq亁ou|ڪHQQ>T |( yL|/+ wh̿IX*\ž((j-'G`};0M[G]4rƇ?x v;}W߃LٝʝqbS Cy@u|}f65 :o3٠1SFwMCAD=DhvÆ+YYؕ/PgaSυ!$3:c9D|YsHt8X rEOz^jWo] K38Nm]ބh 52.`Jݣo"8AV)!:4j|KەMPTP8ەy ʹrER|B0grg ~x<#ߗxm 87vU O' k^(G~wIͧ5$fj!3Kќ"8yNxKiL^PW]v! nO@M>lNGMyT}Csp<6|Yl $G1-f1H6 j)9xLSpD*F1?|j>J54ћE>j M#\lǽw `/h3}bյ. 9kjM<1}fϐq'EbA/!A4Z޳E\MFZ,GA.{XTd"cDN>UK.el]=VY <*IO|3LkP9AmWRA*r!d,Q݊ WK#(46YelsU(?,'*XG7~ V *e.qxyY]_DVs[犌*]ʭEcjÂ~JʤCwbEp_ˎ`+O:Os!+^LSxMڏeW7=,e_Ddeθ^1~T"}30 wz4wB;p]sB%*s 26Ij7 >p,7A'%u3I `Ӄ ^+XZJ ,I{>ZNlW;J%_uUOdb阱(~˕ E^ !̝_դߡ']+krxz}n7٩řbb+3ֹ>+qكg^MdTU'+ؐ?H}4>G09yՏcM9?^Wy:|n~2tm޷{x$ٱʗMACuP}u!67*eu×lb Z"XpK 1ll2SX]CLL)W!RޟԓW{ DUM P6)C 9U}Of*uD szkM= r/GEM2}]V,> stream xڍP[-C x]h$,8 %wGrܙz[[ַ>kj:* m6IP`bHjq89y99t@Nhtz@7w,i7dzM9N(y:x\89ܜ d,@6Uv tG@@vϯ#њ %(' tY[@7Z[:! (E=<\88-!nvbLo=@ t~7 Pt;@]bm<@@s'x~9@[QW+عMwo"O5  ' @]Nǃ` hyη9YZ= ' |nܭ@. -ry,F {O~;㯓uC[w6.`'PQglv@'''  Xsׁ8~;ull?h^@'Fh\\ h ?`=.ϿLe;A|9 %e4 X>))  EwIUB<3LR<`M88'OYo߂<?nKggzz<_ @z=,@l1@>@ _bˮ{ɜ@`VqqryogEq_) 0nWK77K(糐\ϫha;xn` qC}ߦ?Ha$7]? LdpN\gf? /?d|Q J@mnb-Pv]%IͶ9":A;y}ȲۥdnuY y߽:Ȗw~IZch?F$k{Qt$\a(z `i_{Jl-^7$x.*{%59 3ޱ^R ~<_77S+t;i^_ JS"->]m6DhaD Yfr%>u䏄rZM%vK?PާKY Xq&!*sc9 44F!=DVO٢chRXy8?52;,bQNZⅱCDtTF>*ľASOt VӮ]1 .|+8$}Ů#nuӯO^\2ُ-F֓+zsHɑ>6#6A>c1JTUkV)Jo(K:Hnqmna$Dʦ Y:^ձYkR9vf $X&6A, "7a?;pwpGV;!#ӿ.Q¶Y =}4) 4Fu)e%YIÇI1W17آ^slb1 H4!Zd*,|^'ʋw2 :P,&T늴=)p=%3 5Kl!HYw&æ Nǒ \jF#4[xq!\;o`6Hnk%(N$-A\iby/+ܱwox̂p^RqzWŘl߁MmkI@\i|8O2I0mၥ/͊`[|,F+̕x$Q, eߛD9ѭ=/ʇ'|[| yk-G(7=dh?тƽL#O։B8"8S.]~[UCQYJ'j6=i. R9u1t3qwZk3]IS헇XIxt/zPM 3= bCy>g.;LD6^,xF5w(Lg83P@TD!{ EWpg$w1Mdzfr ѢaHqřCGw29K^.JX>- m8Rw_MZ{ngkzJ5a/dNZ{ e.ˆ'BnnēK6hVC]հMou  W)MmE>aW(H},ll6ՂMZ#o/eһ"`A!.a[5 [`.bЯ,dP-_9Oge*cfH3.uc^900ISddpT,NTL!-W\4-$*qY$ 0$Ba8zGUӚ/M8@ghY)v.vMl'&HuN|x9P7XkQJ;5hKUXE^Z9DJNm9nh }lx{ӣ1TX{nHZz⩢JgBqG孽r^FÔ4\ j"~\4Ѩ@ןz>Rçհ Q -"7ZƋYdWM뼁=gFɕWMAZLį E/ͷxlfLmoEM4U4@qP1č;x3:04 ~Н{u,fh/Ie4 Ӝ&G?ApA~TP3/PmFb8䂬ӽlQP:ǃu?JB[9[ #$|]*G~ @x(%~S7RC/`(ʾ3iKW8EԴUR0GJf3E+IFW=pmcHwZ&JnA.JS˥!T<{dpC잀؋m}"8)2|pcxFS1u0mg`~ R>cثP˩5TyWY%pC!٦R*F; mRP0ӽG+u XR6{ $murUObFKw}g'7o0¼~0lc'< }ѸmA;VI5S"|p$RP1iD1W'0$w\ FT<`:lߊpcPUy;DZS! 4)Γ|e mΓfCk! |M"ݻTގ5/JR#S>U6 ãH։Li( lOnUn ADTR H#!Wul.Ci j,YJhHWO+/Ԫvr}GBsw&>593 _X{Dj^pGM \< u8!GǨi|V"A]s1PmPџOK Ǡ įNHX>: hCWN]OFbKF5QaX0q\ ?zj*vSUinxAEʪ#D[U| 6י'WǺ} )w5uDLS%Z6f1$i`FYz9>դ՝ 6t~[+⃟1M)Wz S5Y8U"Ѣ5)pqgo 9`1:C5UΆmfd9& >?tQBy uoTa0`'~z{g4S1*Z+#n]f%,k;{c8NCRzĠuF x\R aPIn^{MGp@A[or%/.X2S>o_smzƗb9]dSn'|j<+|Q u0k{e7ÅSl ĹķR,8ʗ *X~G>}yVPB8r 讣YO8V Y;oҩkz$k_!ex!ihES?>)*jD&y12Bj>rJCQҗ@/7tǚd%l9pA2F<K. 1ł}}G=׊0OZ,^7Y`xxW*l,}ԳIhޝBV+zULԖSs3:៛nHPt;ہ5 ռWh-Ms ԍ7NyDăw{F#TuKY87Xr{e^E/gXq* #cQm[]gM RnC) *ۧ`uG3l௜ pwD $/cws5KH:qZqO$X<ř:~2Yhx /IFTr ~Ν s._9X*4LHG奕 E %5fJ!i;nQ>zmF2۟tQ2hhh'WH啊:q/eI:3|v|q*y~`a/=Y~-ݛd h~j v ߞ`Ӻl ۷y9]Ng&8N.E)$6;TH#V^.yy#C\D]Ѭ+ARG>8awko~\lښ:g! yN"AZN>bRޚ B1g ]@av:}*S4cIF5$P"r7LbM mWqw,]'ߚC6<&Yl+gx3q-b[*w/=_(;x?||#;y8F1;=R9(`$=p0ć|2sCG!S7De `%oe*BU Mm[aB~WNf6}E {“tg:¥QX2Jvr2b* yj~N[-MhH3eߙxކܺ:];U.< vƊy2tѿ(jV39Xtp>OMƑܯݤVhcn6ݔblj*6 ~D'5 %#i.Ew|̘c}cx i9ZLܹŤzϽP1l0ې#3Uo]oXmsu'9z;6=_?ft3?DMoH99CFr}TĜ;KU#4l(3 }~ #AeKݯdN 0w?&kyvT-tۮ4jխ%3-xx\ۥ%HRpEC_=Ґ"M ED)=Adj姾{ J3_nTH GM9}E7I[3†*(Q֒Zt0_ wՠ5A\2z~!ͪ/"E]/%&׬6CIJLD6~|oGhߚ!cRA 9/?+7hkiɘl>u;3;;5"K)dž 4",c sYX]n1}QCl=vSԇn9߲H )Vf9$"v$ⲥ ɑ30JMU$,)5Iщ]p"Gk`#XVh6k4+[ײk|bQ)w9;-'iG8FCOYok`9}0îYX!m)3w}Y֥mi\ KQؐE%,m*H4G~_/*W{5<({^Z\]1Y)Ð5_# pJ귞S-0j%|;y՛)fbRn-uRH*P.}@іClD !=cJE;}uM v8GU}7+e2adISHWZQllЋLI2S)(E"Zl&ɜ зNqpQ!n=$ɽPokD ?*%ޝv;beaQ;xj^Kq(Q,QKf^?Pfp*pPH< O!!mo\)1b |Mֿia '$@~ *:=l3ZkPߙoʿ7,,(b.Oh2Bb=} #5_v{[SEb7Uz0\8.5؅Se1,?bnaZПaw[Z1'>v8w6%Բp2. \sxGqY9Sk f6X_6. 6X?VnmX6A;!b}P}A,};znP(^go)>05 nsi-K.#ŋUlI+^O '߫=j|:Ba\pB,SbH?/;hsY?eD~-?GjuٜF v_}2]Yʃ UHr3zirHI8txrH3/Z7Nv~hٽb.!) ~qqv1+и,zXnZ;_M8KwHɩ^=%}<ےgffxˊ@DE>{\;0]/)D'ICmN5Wai7f䊓^ 빨? 5VP81v*_dlR&T,^MERlj VUlSDPek}&Ӂ#P (^B;@J{/1T5s*C&UyV t)/1SKNs+]1:yߕYH=>ArEm+*t?T ̙mK8e 8l5l*eTU_e=&{י02P7 m33!&#Ȑ6BVj,w,N[Tiu(.Ѧ4- oRg;sT4~QJenIF]^K|`o@k,foFթN.bP- LpbߞM(^@3="DŽy^%> stream xڍP  N. 0Xpww2 3wwwwwC!8#szjf޽zW  )(;330DTdLL LL,H GkH@{/ Q{LPH;YY<̜ GG[FF#5hP:흁?ZnjrK1st1^  l fHl࿌e2}9f@ F&&[#l0Y  t#FW#g#$Fݟ=сdGyfq(vt@>1=2MhɖQ sJm*BGft311qrsv Tl*a _<G{'ǿ G1F'h~=J?f^f [c5%4hnJ+@`ffap7:+6*S{AK\ 23~1.XGWߊ$Se7Ym\'-jZ]9)j^Alhzn6  +Thbin 0P331뎙X>"S|]M+6k,#{{#7Q"vR]2 q|u0#1W.?+AFQhzb0 3/_5!;-U|Mm/}]@Fȿkn6hKȿef0 v|p|ʜ,3@'{E{/' 4AZYZvpߛbaC Fw>P廻b_8f)yia΃xsA։e_[ېljs֢2ٶ4%0T-nE5wq9zy$?=4{q\~$|SgDvixo좍t FoHi tJN<#/wv ʴ7`3P>#S^&rl8O Ue0 (|#3ͨnI&Ȃr0y\:L GьV#=ow4w({$ifyJ{Lq¤ I@Sby\ǒ o~[bp^CG;F|gk"^J2.Fbr®T3xNC&_Le/|M4%lc'(X(Cm+jW'zxwi+݇|V$Ө0 ank41w獟a~1TI;esYɰ7X9uiPh5>MԼ]]IlT+`9URA@*F9c~Za\Ki.aE5FnbЃnlf (Fc1Eqܿ6_X&A&NFD`+"W#>HfA7γIaέdyus-"|dURw4v|Gy{UJ@L:"##zT,V4Km<m_v)PXlƨE.pX~^KObD:Vfx'c01(VKN)`<"}o:* + ֳxyf; >#"F&[W+Cfn%snI`ehoRY@]Hcd+~ۋISWe0iwfOmV-Կ"X$/6k/q5 DZ-eNnO{Fx7 6w-ӃbRST1M\iK9Zu_*Q*9V{/LvLYZQ yr'|OBd߃%?F$6]Īo@1<ݒL~;2͍Rb1J̹sH M։B eG2ɒXSw(!0DڎK4MO~ r8Ag=#'-7K._})hv_EJb) {.Lݥv qJ߬x)zguЏc&M끸, ??+9_lzws (6]~ĕ)u;&:ŕ-q_ Ҳd\w?V/p>7ԠNԮ? UZYqeZAw |8A7SOЗe/ $RLUǿ*]qeYn ȚhHsA8L1!p6P_]&ܪ^*Up\lkڥϞlmi~bc3 <|JƝ&-cYU8_y|FR }xuZN@:FQn?o95 8Joܴ6d­֋Q% pDlsнq i/+S雸#vjOϕyX˴R#U?8:?V&:*uP'lNprQPeM3Vs̖ D'6Pf=7.c)"cuP"9x4[~pFFc"Mrz@#28GFEr~n;|Y޽DٌzBEddR$On] .pהQ{>^7+2~]~50[Łe 4ĹCUIpY^'̌R3']:Ͻ)(;eBBg0G&Q$EgLU% 2Լ29ƍ|3&a~qMVƠ`d^z6֟^,F[֤Cq8r:^n'`K*j s{x>r%nSXcC!lom]d⛛71H(XuVbɧ>3Rh!O-ndD|Ԩ.\4#ycⲄt?{497sFHJq2Y9dz7U840S>^r6_!fO)2p+v* 4ࢸ:K~%鱔b6OF)ə >ㄴ3yoˬC!^I6/ |drl M7wc%7`wRP_'b&V RϚYИӭbgboѺH l:BXrQHV1j'&:d< `Uz,h i8<7BPBoug㪮D Phc"Jl]Α.PÚKP] =j,AGA+fCtx^VlW5ܴm߻c5<˺)ί{.]rV/!<{tUrccfxGO}[1j/)5M=n(/(ӆlˁ$ۄ>Yۙqg?h 7fpW0fjRYclR+ ܯxTswʬBmѓw{n$qyKfWEo޾w#"@z‰< |OdxgAѕ bᘜ 2zvle=)\XqvcL1WG<_6h%5IU{ʭ$z%$LE6S*'x>U]^),S|DNMr\ω!9{|/#cSaCt&B|~[wr/OX14Wq06:hqO)I 1MX3^C?K 0dŸ"/Ǒ͹&9pm0#=鮄]/{3e>K6WLᄉYlŘbtRdeL*K=-=b94;Qߘ\-KN9)JP&Q_yO-a_l0x$ydV-j f#$Fcİ4CIkԗ.ͬF( t)7IP#0Bxc6?cc{6x3Z$=xBU=dq]uQfWHkYUpv#~CmoioIro x \%ivZH_mCsO;g8q,"qo`Ecч+Zz wȈGEz"P0Tlhy1nֽ=B _w?yo\<ft$[NOGtl5{"#m!2Q}OB49k8DR>lz>\Pgoi{KwZoh%sL}`|ӒEzlq#4zآILyw ]#!𱷊Q*&IhE[A **ycG%G]noNlm2҇d^8G(-2XuHMֹQ__*C.f0Y62V _Ӹ{7o f\7ʷs+[^L1¡ qLmk`_DJ]a_պ@$Ң-$ x1w_ٸ"i,_, CM 2<`Ҟ>ۏ8)+zum@@UhMMnuPdyqT9tJ~2Zw#P$wՋ1j /VF7Crŏ$[ܶe _-U.,RM.#~ WMxSJ\qJS'+xe'PGhE}8^pbH6M>v*w8}fj1sL?)^n_CR *yҠdOLKI5cyp%$퇿ڦCc]w3u@W=(.~+SغIU ^A\`e'E[k C^g~7"6{otiH[LSg|D*rB#lpYo­oߵk~yK8j̎jEĴ/bf_-л[0>gI赯$jwC <R/EGZ,d(DZa |P$xvN=WR`#węvl߲aq_4 juh-_˷bk58̈́&GO)ωHt{FØ |v"UEn>HA;6|K :oF. :'J2kjse>|zr? 8m$#ƫ]-$IjR ˹G{-]>>-:Xue gogF(=F\߾:_b쳧d"d–ͱ-,S Lf(SaETEQRs-͘o8r@??T8#{/$}LV&H""3 Wzh-XKrE}87=bYCBtAMV&H,B(W} k_[jۧ*j%~'G/Q[R+1]dFlGۈ}#VFmH&D?W$k/7^vF=o{žf6:.I]O^G̚;]A\solmaFblyU1Es>vpj˧=R,XZ|xnNneXĒ؉شCl6Rj`cphʻKYl"n(gm+k>ꂬܷP~ޗ*^v} wx(RDȸc+EZ9IA2~gm%nC4^4tϳ>1h~=m4{$7G&Fe^3 E'MD^YF AXv|m{1̖36_X*p. 2vIe:@#AJʱP\S z0%y5|+%q89XflbH Ճ  !l=RO^w>xtֵv~%Ndlpd78NГžI04.a &;Nˋ0O3,/و|ZR$3%k/:wX$D;~,1yxZ0q qS|P@2}*bf. O-{ЂЊ bTuX*tkN֢s?Oso忽\|~oO޵uUƳ=D;Zz7-55l jrYAדP0BQtYOA1wߝڪ\sS50 $I,-H4J`x4yZ#h5GT. +Xd2@DφpJd)2gKΞ1R'_GjX9e[ 1GB<K6 .⯼OgMOX t1 n.^B_a%Zʗ(rq <Èi ^u?֟"iJn<ؘS|kY0i$tKe5&+E3Tg[X~"K4% CS2d!f?_d ipPmO28&m=;Usxw5fHX"T ˲EDe}ڰ̆2nHa3H^.*| Pm)}ʽs0vs#6)K*dFwNy]A]Y P QMi2ߐ,o;adTͦxA[;Lg4,*K$S兤VR_,trԔL5]&Y fhp|JkҬM#g>σI߂qJLWE碙|O<1YhC2yfwR9?(DZM꾂?*H93w s|MjD}w2 "zK}x}%bai}hrV%'۩Hz=CcȺ(b2A>w9ߕ)$'q_tpT{dWLBgS"6N&vWQ,M-tz_|%LW&۷+,ry:*:Wg{4mBz퀸;sY'cֲ'$#ypS#tq螖\F' pPɍgyU`ߠ=C97LV5Q8 9qI$*hSe7㓤oć%IGP0~㑉a_ kI>>JsǬ:?ѩ\D1~-]ȯϤ2~rml;A]VS?3nT칭=i> #džX9gcSAAScW--sa:]7u"2HZ_C:ʽG΍KѓO(m=7QDw3rOcG1UI n0=lug (Pe vNۛ 0!шho zM`vPvm w'#Qܖ2tot6)pJY:^ Xbph3uC`r|{6@)(/cip!@/Q+ x ߿s߅H G+& $ &^ h=EN ,~\E^.}訕WԩW}w%Z>d'yy@=t|_h.5jP̋+RjyA8tй}otPo-4|wh}_ǝAE`t EQ}BtT;&mu(K8OyǒF@hR{% t7a&Rw ՠ1Ϳ#oT+>^&6Q|/l3}loA%uULS {0#Dd?R]U۷\@)^)};tct(?Cϖ\ endstream endobj 65 0 obj << /Length1 2144 /Length2 12844 /Length3 0 /Length 14132 /Filter /FlateDecode >> stream xڍweTk-^\ ,k)Zܡ.[-P pӽs;2F|gM5$! 9S prrsrr=A4hz 7w0Y_6n Lj q(y: _)?7!P8!.n`[;h `bYrH:VU ;4#@byWF;!ooov 'wv+aܼ@րm,@4ǎFб҆xx[P# utڊ*u*3Oxv b v؀Au9vVoC Gwha 5x &:trxw; tв'';dn +}99bglv݊ 3(+,D[ # ۀh^ '(ߊFh@ lقDA6c( >cN( ߯Byf qvcAs*?j)) HBl]/tPS=aw,5 prZA߀߬EQ?ktt˂L/ 'l􀮃*TN[a] Ig[(y> k _4[{ ;U`rr/t׬׉;@UגּV;psEㄒ.5/>8؝!P@ 8$F?H! BpA|?EFQQA(CphA<?Z?HPfa^6? hV hZ'C&o hW6@^h^_zOg LU ڼc3Sb$6B ^U?頶Gڿ].g. 77WO_CB޿Bx B_ڼ-OPk<ݠzuA_2d~cN̛mwgO*8Gmv~5b 2+\Q;cxUx؈D28~oA.vdxp Ѥ'"jB?P9?&gJ~Q8eH/&=!1?pUG",FU?X`${]]1HSin[udRO-z.uc m(DGIrĊ.7kla\L~2Ř=z$+c, lIfX*\ |ռIx|z10nArѷA* E|vzբ1 c!AX$Y2<%ocvZRZI*LfvbD余G:uU>&_ؘKWvqq5H>G{Fc_RFҟ <@b)N»wXذ<+(dmk4_ݩq{u QgmD4 ǪWtvnXz}P.;錟r), ow'7Y'-pn2ۧ_ 5HĨ5'0iBFF :wҪ\XH9r]GQ;$I)TٱLo _;_6MS&$i,^OWIEk,h:!i|^^i|~aI a(H"@f'V _ť7JX!Or֟ N_P"=Ԃ+eRofb5S Yڡg{-ϗj]9-OxQʢbi3D9 aMlbZ}u~zqؤF4LI,D4cΝހ0%曋_e=Zy~ }\YGSqß; 1MjةԸU֊@X[o#x% IvSt,1=nì9u E:q]i_H T,A+yOWE$HȿG&8D Jno'$O7_63W?fdб/0N^I2'~[28HӍd1;QtXaK%~kNI礡I58C 7WMU{iʧ]?kAU"Wxb"H~鏛,xxs}Nk+ GtǸMLz%=/7Ki^cv5 E5I뫖DF e㸙Lz4&UYٯLEjNfd-\M_*]u:ƇV08I:V6C")+%^M7t}|LS/N$]%rt~Z^DNp:_++&iMeH/40nOb$bu,Yn E+9K3Ba_'O|;=C !%(¡pJd^qR,> yU:Uṃo:"Ǟ7Ӎ0ŏ.yfZ} Qm*jDG%cٲ:Nfq;] ,K&-14zSg:3W~(JZQ80(R22-~6~hPU0\ ] yì-1Ywop70Qe8;2A>śo^[GZͺvxI O_l8!x/7|scPDIeA6sx1@])C!e!IDaY;G#/Ww OgYV~ $?yE'=ŠCr Mr#?x9R>y<HqPza[8M]s.nBĘү+v eW Eqg>=)DPL ?>Lscc>l /:{w҈돹d7i6z<2_p^q7N◒Y֓+)\U5a;yB[3_Q# ߣ%g9 T#Ү] ~je&&&8>.?&K8ug-֘ \h330a?f]+wi4TLB#NpțOA.yS<ގh*)Z:9D 3Io](YdB։\'/Dj#P .- "UyK.e#?0q kYgD-i$:R#71]W'@ lO&?ɲw 4E1g;?ٺ̒C~_k tU[[F/٣DyRsR,|{^6ٙaTP afqs݅Xɮc2 o(( ]jo6Ao ܅rhyTdWd<4!낕pLUU~QҀmW\gŊZeX$֘qx>U& l /Rc_'J@GMGRDB 7m44(GTS\ZM3a\t[oʬ~PW̓*:U,ro48/;ro̊=><],&2M.A..H2|NFE6dl\)/ Wx7O|j8K薊Xee޸h.MؐA>L/Ohy" )i*)h 6$Yk.sR:LS fȇkJCmv_ W5L.0/P K*䪩K,kѻf0ˣ|pqx >ssħLgF3v8PoÍw?XUu_p Zx'vתrx6>l=ݱƻo.b5MOL1c#Ew;gOUkQA+* 8ou9u0_]ijo ~DCA)EE.E}_üAH;cnL'K^8gDs2uq_!}]|1v"'4d;x-J\rWn\{P[mgDce!)a OΝ0Tq7PSC׳Ķ͔fK?&Oafi!Y[[[>ti5F_/?" ¡.gX_9h_a]Jee;Ҫ %f#fGJQTͷ *3wupDZYrk?1{a?l1tw*PT^ vsfCGxefkDcR#,f;V0:ef<[m1XcL;WWJ[fة0RLզ3Xk.Ixy ޔ}I<'mUcaxު]c1c_*$~ik,I !Kk(g>"=`;46Ol:?WR0m~*sE^-[m["|LC(/+t|}*~.15r)&t;hS._z?`B XQS jWϼf=i73OCՕ1uY|a1x_FaA&Kҝ*y%ubx>'}P mC(&~)F̶9j:kuɹ{_Bp|9.*o6mgk^rpa0Ѝ";} ޡ˗w )':f&'fz-uS/nRVNqmk)hoF1skO}F089hHT^}×J% (r+b )NioБQU\orBDl)ˁ'gCf? Ϻ??61)@֞LJ`"ArMU"681ɵw0f&Ƴ<.d6? SZ91K#3渊<ƌ-_\|#t$RVwJcqnbr'agEW^xBОɎ1RP!UfA= 1).մͮ"BmhLFޕHC.ʄ4)u.)Y&O؇bX_pNoCEDbuecO})XJ7až{ʙ+7rr2E2y,G0]VK_=hٯT[]l`yYw{Lx\X!W=]G12o0ReҴ~-#qzηl c&H+zƭ\mle ,CTSe7NR]Nh2+[uf$Do7r؁&cUБ/ ᯉj2s`/TUFufnUAOGo["K2pնV_bc?/*PLRGDbUlX(ip%h NZ%D0ٔJR =d]wf.H&?Ti'nͼd@nj Vx5U(~Ti+armWXSAs+u(TnQ2R3Xq ww/H,W(_n%bB7(ˢBq5ϴJ9kpBs:)y B纴cFbH-U @}ݽkF!I;b5}e0$/xF,bv|Ws WbbҐҮ#nPA;}=_-&֟FWd;͍=ho3j>ciB]"Cv+Ze fok|EX.DQ)mh%]݋#O&#Zj) a=ݺt$Ieʋ]e4އz1f:Xܖr3ŰwiXƒ=Ctl-U~_n62 ma/ <Ɯ:U}d'Pͭ-hQ=\3BnO2%>Ub&.Ivt?y&N(ņбBP*ʹW R \5*\քnk SFZ+<`u@aAȋ˛q%SrUdQ6DZ Ԧ dO,t** 9roQ[Vh0O%8;=u-X3$1zHBk>d"ωl%j7WOуP GHf׫`[f}w%oY-8ԩOLJ%"6psvJ5B&'Gz1R]Kx*͑),W{>]=~AP- v !Z̾vŤwJ޻ıs&̦x{W43?mLhF+cp!Ɗ<[*9)}Tb4#PVVO˂hvG˿[W V^n!}*RwIU; nt`=0VwAbqǹ_ch D zti}r Ab2`g/":8r_I&Pv].O0.C,`g.1JjŽy qn݃{UT-v!fYQE%$%8=*Awgq!|^ߨE;v뉁Q]/2?G}Qul(ϊT]aEct0vd2_/s,ZV+ ?7uyn?! h٭F\bwŹt+a_J͞t|n|Ti7pcvVCX;t-).?Dw4LҼH̘j tt\y,$9SV4;iy/)TGL~>552tf~6;3ebQM|:(ˀ3SCZʓR֋SXW01~M?skn2qZq-~/#;!h~`NKCP0_80h#X;>}1\a!c:˻c!ro6 l=x4o~+ln2<Y9:a15Tj E1v9*b-ekK/|r?ޫ9<:즮8mWU*~)<5 ?jt#@cf*U3#e*,wSvbY*H" ||CUm^pI8ReiE~hchӕLG`Odr i n6o86II<3* X76"Նqq +W߅+q!cLHXD4i]lcv1Sȝ$#I7rH!̦N`ev!G+R+U <`n*|jDP8>aAߏcQY(C@C--ȚgCT߈ohKA+?u3mps fR8 حuKʊY1LaB`ENDgNSRn&37;c{>;bu$G?L9NESWl(]M85=эD%p4Qn#tt5QA엏؍RyF ?YYخ 1-vƓ$Eğ1ޖ{t1Ɋ+."Yf ?(?ل䇐K^^pcwɤP=_k(Cfn*4~Au{8fash;aM`g=HPBz`]9\17/y)-C֨:!mdǃ \WZO|LVS>^[|JLhMSؼ2LAڝ<޸ӝM7udҷ2IjZ k/}Ƭ4Tg\i׀lS%. ,6OsNbvC%%6ƽsQ>Zŀ7--f:=8gz }NxgxfL yS8Pϗ\&l8MqyTYܽϺ)JdcWyjGv+}S bHÓAgfez}@>jZaqO9([DR}v}^1A Rb-lj߷ 9?X {8c+i;>=sQ}.Dc<m m@٬m_/["S, >{zK ,\ٽ~NWCU| !*WNiqd3k$?芲cB(aڢ)rx0tMqsg81n@dg|xUrEqU+O†7vZ6QGo(Ja%1-| {O;RQ`ȷ`&1dTcÙ*wE(0K/pu_f%`'P!SI4Fr ]71V`7 /RiΚl,;o$ kMK'V:δlFz!ٻ]J%M$McM܃4o[Mꑼ$eh^;Q]}K.G/+4C3|">4JÛ]o+ZBcR_cH;OND6]$k#K5pU]I]_}0-TҾyjR>XDSNAz ߗ ưPf|<.$;79l>*Ms~0yb L~mpgԋf'8}z#l tٙ¼3 H٩wَ/Qpڴfo7uJn;Exi{ eKkV v;ʹce+/%0Z,i#ήGO&ӗ[ |ؙywJy;r_0;hY rhm*NVNvc:CgHӕ^)}1y| mh;; ѣ:HxR%Z [3 1Agjb5s bw endstream endobj 67 0 obj << /Length1 1616 /Length2 10030 /Length3 0 /Length 11086 /Filter /FlateDecode >> stream xڍT-;wikC7и;$ܒ '8Ip{dfkzoWSuή56$"Hp@ 7;ȅFGpǎFqs:; !y Ks9?`G&@^,WoEr$ G_gzz<π$8/UBPO*zgAA} ` Ӭ{N gw yogI<(d =d\| $.^^?4!>x.`HxM"~Hq8As$ 8F{ r8 dp8 >/p|n_/\s^N+O7;?B[sxA̛m{\tn[?-r SmVۥdP,Ճa[#rd{f];ICɆ> Tr6{6N%2VQ%:- ʏv4p|@ֶpaw9Ě'f/Po-5Drcz#l,"\^(O m,H+L#HxZ)Ŝx\҈UӊNuwдj4c,aM2&6^U?P+Or7w?[m$u$x,Kez`ʖG^ҕJƴNٌ!9 Eˆb~ B~e;u hv+ ,>C yJ.?lGk]4?`2ffyN=0 ?}I}cpRalcVˬGE 8`4pE4-@##)q% C6ˢc(m4 w0I}=gHO!C`o+Q'\f91G-sM#}[ގ~Ǵ/_>I>8++9tɿQS22֏`yW>jhC2dF6&ƻv)䪃f˜!NaT~ĐP?% h#S0zBw%HQrf%Oo~oe01ӊ*؂L -W ÇwWZZf/IoH.0H$ 23G6C8e%a[LM&jF5z`a>qޅ苬qmC7vh?A`?46vUYu<5ۄVE)dGGƀIo9Ww1_VD0%4tFrҮϚL3(re);1>x?/M~"guD]ͩɊ+jև` ?Z\h`-u%uBqhN\Lx `x͖)Vގ6%H=ϳ(A5jL*ԧѪ.[.9&nv69 I`vF!͓,rI4"Ί_b|XǬL27kZ".W<t&)“!7-RQ*n]U @t71X`LiX5?wAczZs p%9.lCH_"CsMTR:I!VpЩor-[GJ> )Z6؉L-dFnq֦ή槻˷rII-5,QC`Ѐu=_Kȶ0u^hUNSqIm˦# t7d ܫz^e-,fCK" -ژ! ,qT1du-HOJDFʘ9zfGȲX6̶1+hAHƣOOAXT?tpYV-@߈&`RAuHb'rpg8U?&v(GȝًFUd2w~NPM17vvIRwJnZu'j"RٙapNB@VD+ ~.yt% MeWTMdoqLY[ΫaIF"'?_vwA@fdT4JJ(s/7=o( Hl82|:?MOrH hlzyJ2DKc Y*rT~h1a4Rǟ>FI7(Q/LNs!y:~T9mL6h\ZI!mBp>'J܀?Wu'z7gBzeXZD5pO P,›SHяNjn`)Ct%@B|PxThTn5AMnIA9G2g>Zɖy*45GӴ絶TjD xvCpޟjWq6t=KNs$Ť[fG9db~zܟ7tBJn"6f= A>Hfʛ3$D놷2#I4׭ɴ-iKq F;Erg1lC/r}>'! 'R=FOғ[(0hj8$ႡPJhVF҃Syk4W0wI$m\#/h+ +m3=eZw⨋9&\k-Ql`SK)Mtl 226Qd뮋R20<$7X`FoBjb\cg2vX3XEX y֔QU @,aq&e՟7ѩ?ub_ƀs lBSn TP|Vm@5r MfyKV3!l7)$j'ޢl`Rny.^P 9%a#DȇQݖU&={渶thWa;㙻3jN*ɫ88lbɊ?`8#/pg(ÇLټ]kbe)&XwGNhzfXjV{ߵ7Q5ru^N^u^|ڱ|BXk.v^U)^8|z(J>cøWb+@Xd Ʒ5kp Q:&FC] %suJ׳}< j!NNիLUe4rӔns+ 9wbl\;Ϯ8 /v`oLzBtlc׌̏"k yj_F! yŢEӄNWH ObhpĸĝXC]X{I)erB&GlJ>DinZrnks7*KBձhD^6H vDooUG:/Uv4.W>H (W|o{rRY8'V"l 𨿍vQ̑Q@<FauCy,Ů0ۄ3;h M]Züԟ-̙eؔ;wfj'28!Hd'd1 ;]ۇ foق3MqjC1Wuq'Y׌-Ή忨EM7Nă%>A!_?Ҷx*tCX{ȷ0Wz,JJRx!E'P9v+Ý0-BD1K妿%$;A]}5?CJQ6H爛%_wV!M|TCVp<6a-2a!8nĥ-n:8Y! ,݀jY\'c\~irS/ONRzk{kO$bAw7M)SsR+A[*OTY͔葶>y"M۹\srէ8!> >ձl֙tRRoTJwKH@7+fщbtlS^-\ tKDAvRɬ1NY3T0[B5\*޻`9.t#W;@.=[춍]#5FTl >QkhIV [c, gpGbr5`6@~uxP@15zzEQd+;jy!@Z~+St*YGQzcʩ>ʙ[v"^qTj4x^}ˇʑiiש |3"1 #7ra:o#JjuJ,Ytk:G%wh!ɭX\ Uf6 @xL vN9{b"MD-eF'Bo{0cÉ*qW$?DQ%%[4ߒqD93) q`R+]v1jU/M 6ca̴W!G/ $ t a ϾВND#- d )lNޜr3^A BEK`K:UJ9v9R fAFC׈lC7KzZ1~S4$Ĺ[{܋iw+RM/oau VQgcaS|Uzmo rT.g<IyO~b^X]D9Ȯ7 /XYٮd΢N}+a/&ܰJ_pn%"Ӛ!_[c/\}2j&OEͬ*) 9|7lߨ@[p>`]nq]}u)Gŝ2Ӧg\^WWQe܇؁f+FNyD%z^ovq=b[ө+؟ Thnlgh]C\H,`pvh+"^*bc\8oԢ̾ˎ ZG]0QB"%ZFb242bI3ޗУcn-A?))E|T`tM .+,=4K. <1Q=}HM2\$hYe3~QKDΤ`{&u/f]}$O (+~ZY<1"r_L!61 j,֮ȶ>DQ4ļ;zhz!qFXR<#88: ݨlUii=-&)FN4Q{a>7Ld޽4B zj)d`iLJK~CIB aTǾF.i U+$1 |zY2񬻖ZJ[#s \]](k/j }붊ۀFK9ܯ_cqXN/ 3?D>[;V\pOKPݚ5#I6o̐qn`͎&x8o2}4>ѲO}o&v x-6]@Y<:Xm<)^8J0rPUt}Fv( 9:{A!˪"C) E2SMJ9 O8y~}j^Vջ[QEUno]Gr0 ~,Wus)qScfb};bd^0%9,>&XUCe[AgZ;0HuL/>>yxf#D6ٿq/~WX^ݽ]Bʈu/Y$U`B٘ *L$(-seU>h0jDb` Kט*ҋQSϏM׭T#C>|64q 5جKHF?ߤ![V T't(nEz`9ĬKdai2zHDmt^>~T6i4%S4ڡ`%†7DOUL>fYF + Yx3F" 2WI˼D!ؕ Z8"'Kp̵EATv lN4^Q i\N:zfNSf7/\DӸQАZËѱh(c]uQ8FE28B&]`MRJ5OԂLx "4%hn47 k\b'dEWHE'ߎI3$FZf}; (]t,6ŒlZt$Rw[jG.6׽WeL W,/-"eU} endstream endobj 69 0 obj << /Length1 1680 /Length2 3950 /Length3 0 /Length 4992 /Filter /FlateDecode >> stream xڍw 4mH٪GKe%{$ɘyL̘,!R$ER$K!57J}7}g1ߵsT0@S2RDjF6NN(%TVD"`pNa F 470 ٌthC&D 4Q5H@ M$S5ct (dHȔ *O `dAခ/H%`$MǃPE 812x:@0 E/ML֕:pi 5#оap Ot8qt H$O‚T8ZXl :'ݯDҏ`4CIA7#AZH$:Mxt@D{AS{ Mk>Ji4q}FzMHX#/H` : į!G aqc`)g0ŁL?6o"Huee@ ^)p 2Ac}iS# ` :zH?!3HH~(1HaX2FG ~А+%e@UIPPBMO G4~6 ~)@zu d@Pgi|=*vdO$$?~/֟ .ŵz-hh H@3%X;f=#HFXY\AwE]_2%U5M`HHIJ@0 F,CBDC!4](#SaWq@M?:4 0d"oz p2U ܘ6@>qQP+bC7@ʟbjG; jBiC4:0T*&~ ؛^2F+DqTB1CIuaeD$`>H{eA93Ϡg㓃Iu1D<]Yp/祟,=>w[n~I+uLzטso5&4ݖo<۽ NgƆ5hma ӟWP<XjYu\bIHVy(Z.Ĉprm蚓E0*ڤT[S-䌁Z~זV-3w0LeؾRms+͔-LSDդUiZf5V&=j @\9D !"%kӚj=ȤDvhQ7Ymp7ttRPKbR[j Ci$>O|Uj^} 3W\6uaSqv}Zielq0#)-^rqo2c➊Lhȇ.g';<5<[VCNr. ':i|asHT;bJ >0)C0Rzp9 VyTV5Ѳ$*Weԍߛs75o<3{b"҉f&JCV҈)V=A(yWRcpgۢb=]Y[n0-iQ:1`Ú2sD;t&XQuN"n_lL.-񗳪_L \ X?k=]{3Mu>Hd\OynlRͶju{H ;|j`'{pRu_EGCF,\1Ek^{Gf<75#Z6\:FʭOX"l=J-m!Z zS$ hpYO6,|ǮX~ke"]kOLk~1,J } Y}s< ޲(jX뚓;+4_,ص&hu]]x WLn4Uu}QW8O');tJ~Ԅls3T<2h,rtٜ 6\iQQYyZ[f<'=2Ң7 q.K#3(!j eIl}V;no/H"ݨʗ[ؒS:((Ʀ ;t͗]婪;Q1~_d\mC WZdץvGf=o^8*яStX4HwF,b婿77W W[[~Q^P\ȗ)216-/NwpUa >3﮳>FbV$TfWM ^hYG٘k?i{LS-H>V'p^)<f\0snSnU66;XF?ui#ԻYI~^#嬓5uH[Q6>o,La& oyyCޡT0>sK{$ϖEHQ߻S[Y:6=ekOr8[BL/\Ar]l+lsb)>7˶ş_y|<䱔Szjg|/Qʋ⽮u݆ōJ<[M}Z"O?Wfýu?QbJ>1rT..SRmhhOY'"Q.왋t-3%9]ᱥObnJM^m_U\*vmU2 ?T~oJofx E3l!.ն"yl9*jX.G2b%-9çٍiPScQ[C;Tx2L !{HYeJ j4Mp$tT .Pթy y'dRx*{qv}`ɨΔi8oGTCƓ^s%x2"lY*IIro[}*I7 a;ftNtW4Xԇ;‹(*U6\if|~xZkBeڻ.Ô4J(+Ɵ)WEݒf_ZkWz䏸 (',|[g_ w0#zG=Us(fƞq7oۻfLS{k~ s[܊|Aa W%%C/v॔{"v)59g= 'EŦ{b2ܧ?wU]Vg5 |1q#{BzQBvd){KT #Jq_k wb<3k98}rxԏ}Tm-坢y;Juge cgp|!Ōy!+W3k)G);%ljjϐG='㗿4]GZ(n^=9{(KkeW.aǐ箑y-*-ՋrLg:uհesTv+MJVM8t$Lgb W`W91AI=nBy:Xu/DǺߧ oó"Dc#C[MDs  BJ'DezxkrHS51T-{oiLxp[m0j.W̓\\@c%5.!_9|{.y4]],I~ endstream endobj 77 0 obj << /Producer (pdfTeX-1.40.20) /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Keywords() /CreationDate (D:20211026181452-04'00') /ModDate (D:20211026181452-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) kpathsea version 6.3.1) >> endobj 2 0 obj << /Type /ObjStm /N 62 /First 469 /Length 2801 /Filter /FlateDecode >> stream xZ[s6~ׯc;!N3'i&-2ITI*MwJ"iNgD!̲8f)Kb& dPd*IX4f9mG2a.LDXbta)ht`P#fZsLV)E;4*K1L&V2 D210wݦO:OVЇDYt }bBYf!gdXoAdK4v**p\AhR K) d%i =҆%Л$F; I, @HHCu@*-l`Xxi#OZu>nr=㏣oYU^5%+Wͬȫzog7n YyQb>gUΊrdD|9P񣢹 >elAhESD8y]q^3W_ع wMHA(I/FSauI2\?\zc#&y ?x_x p*%ybQ"JyM@wl,G^9]fEY,ju4_Çr6GqMrq6V rv\lFnt96JS%YGGF8EGE-%c !uGZ(:BˬX Gdz>}5́uDXf;iM6m,d$BR)dܫvD9-mcRhQj+OJ儲I[3ITJG_bLai]1;=&L0Idu*#'qULWUɁsa.зQ6ػjN*I"fotl)Gvﻆ0?$ZU'ìكA2.l;-Z*[^#'2L8Vb8DneTאU9Sfu7'q9l:x%U^tMoX/b|X\]倊=w>/*|_5 S*VgUqQWY7 s<WL.4蒍ǰ`Zn_ ͲMj1ͪ|^NE3W/qGkHcMh7_)K}1qhqVjX =w#V=8c']SQ$H+N[8% Az[E a۶uo][iЮ.F|LObUtX@c"+kA-E֪-Chԁ'`=?e?v"L%OI';^=(j(7 izOXRR*8BI9ia4KnV06'!pl:[0*)<ƛku^[gS)!`jx}iI0i͓-zoa1\APxIߐc;}]#OC)|ϝ GjFl &g|6*f$ugIPi[i}OCг('"vּ n^4)/m߈1 aSRiu}_G9/Y"۾ж6 7ma0NFmGL93hHHPoRc=>S{vkbLEH:ƛ1NnMlM\Lաiz? ,}<=%k(֋N0UN2lP>ٻwyeSlc'~CgF))Kӧ6c;͖bzb7٬/I߁QP ?~3~|s~ŧ3> ^rlW o~/ =* %mӿ/xwioZ{~C{}'mQ^ˡ?_^ㄟw=?\VSОz]#3s|y$y*x́ `O5@Wi>xaD-o, ۤEA;^huk+ʞ}wSo>u`>$k~v6V{: W}5akϿ>G@PH I`Xw]~,!W]ޟAǓqRZM;cdCaٵzck}[.%;y_j;(HC^7((vdn~;mjW$6/y w0rr9~#昷?<q7Xwb[{g(^|,IS,itw:^]nIFY;SؑNo~w~mzxѹ?u8*2s)8z_L뚎-{N lel+n-zVD6ae'psCx_>ߴ%>avp6O0;K)k:@\AE17g8<,Z`M? άX{dZY;}95vNzd M'MV5{LPS1AP=mѻ쾫=KG,E3C P/1~ ĺ5Fj |Kox- üUNG6*XL^km8_;^'Z+A endstream endobj 78 0 obj << /Type /XRef /Index [0 79] /Size 79 /W [1 3 1] /Root 76 0 R /Info 77 0 R /ID [<7CC9213C799BE12D09E95FC6B624D9B7> <7CC9213C799BE12D09E95FC6B624D9B7>] /Length 210 /Filter /FlateDecode >> stream x%л2Caaّq 8DB\%ff܏+P5Vޥy_%IDJdtDMSQq-b$Ѕ}8`JPJXP+M!`*V:aaU+ 5Xu4nZwQgԖi=EطQ-kD0K_: endstream endobj startxref 125068 %%EOF pcaMethods/inst/doc/pcaMethods.pdf0000644000175000017500000122045514136077111017011 0ustar nileshnilesh%PDF-1.5 % 39 0 obj << /Length 3017 /Filter /FlateDecode >> stream xڽZ[6~ϯ𣍍()>$m A@4ֶ 3I+Iy4I(:$;ًo 7+c]lV"3 ck?^~_/eXrj]wƁzx9NXaEm-~Njom3sӔ57y1[ԍ%^H6w{?H*?BLΏ"VeF_s&wr0.adKTs+ʀ[o Ie)Rg/WTKg${| ^w+Bز" me\, Th9>,X뎖ɪ1p֥uUo=Jo}Pt ]yl\kgya\-]mdf L!z 6:N]Oy63u i֑NhE{ROݣ4Yi۔^6|of=8GVTSW,5wăYo^ADQHyVUT%j.U|9 p)PE?l[+V{`? (yKΚ V1RQ hd>iO7SHPIX o>NRvfb'^4]HG2Gϳ'H$Б6)WI ^qELT-'pMY9Gd萤W^>1HKFarj?18bY.H B.V0hg +|JfF{N^d_H4lE >V}3Jɷ*j.A9Mc !XxVSL( ŋ2w7E .X"G,6 mB7YBS4{1?> @SFiAN*{ݘӰ7b H |gST>l|`u̎ȳ[ePM"`.-S̄\Ej-`5 .$)Db򿬹 ȂJOv(hCtvrǍ00hYWR(Ä p@i?1)+/}3.MHSw٫ {ю ߎ58!qgmկlc#P1Rxe%;u|)>th͓Tk.|>fEĕuJn|qx!'0зXJZEXlr6^묻y샳B4<1 2pBNp|VNuN ϴ)9:i[*WMX%vEBJ k)]J^@'bq |$܆?PҒLkе|jP>=Z\Nj]C'd"KП&%]ғy˕!f4KEh|V#_֤x]ɟN\@,s;Eޘ`#%$·'JJK$PN1q{y$HWIM?Qɋ.H"|< E}GE> stream xڕZɎHW 4 I&9 `؀0 }}$j"E )ڗ5Ud/^]̌BK`gl}?0rW78yvw,8q L%[,,WZ.oZni .X8r}ΏucZj4mUN]Em4h['F=qzA꠼mRr"9$ m'.zGmpe[ΖxYO{8,nM2]p=$)=W_2K_}a/m\DtxqƗ޶x-Xp\Npy<e|%eׄsM]/o0d DZa i@AKCkG\{ ")Z'r7-ثau('Rw> 5C) i<( sy/Bj_Xy) S3QQjq36;HÕԪӺ.t!QK{A=,d1gh!o Q`4j߇nLZ,#;CJ m:™sJIUTA׃l{߳B v"M_Qil^jh%?n4_,|wݬ0e޶BaVG{U9&qVmIف{Y27Z4"$.Zqt ZfZΕ SUW|eU 6(ő؄Z6Z\L];O.Q |蛌Ѣ&kZ?}Np&!8R!zqBA @ rd}*&>gdȍ:n6ѯ\n]_GO?W 2Mdd5ArQ~amhszU:o 4j.m2TҏJBaP5bdXA* rnrc|hAPܐlAՄvCDGA丨( ! y#Qn]*KF>w> stream xڅ]oݿB(pD4߼v)k'%%іԑҢb,"g&N2Yd¸כ07%#p5OVJs_>*8_iQIV-ֻŗai Y*-MS>2x' 2\êP<uA_# - J#/&rZiH2.!PU+ieLXe9}Fe\rWe04K'A 62|_02:VF-r܍ڞEo}Ljxؠklp[_FG{"#Ek+ƸڈjKWwx8w } 8Z&MdP=JauvOx"Exa!#? yNAg481(R$;bq Gf; _( vkdaK4x jՖzBH \lPI|%B3GDxx %54iz]q#öpcó35In%=$Q9xp=19үsR}G+BF _ʞ ˾VepW)H{M+בVa rnwN262ux [dɗM-YOdnkE}0K IXΟa8LnѰP9uJ%z\P(>p&,TExA!n(FŐ_F†A;FPQ+U*zkXp sa- gl%e|'A4tp5700t<'Ka7gZų룧 T I'2sߪR"6m= -e+vJnSS8'ǨȔ$(]Y ;dg "a_1x䲋4Ꝅ[^Nׁy(-5r*qr>u| "+vp+lAi瞿5^y k0qVB1 ) 26@o)X@v#jJ xa `B>̖G` &Xɤ;`c ׸u0GOR'i%66plmSOdJX 7Q±rZ6g0Yz4QnCTT(l/F$ #&5eqtKDE`螽Pfる9Yw%(, ˸c9KZMķBNvCH " #lk]4!HĽN.ĥ0֦Ǿa?R>s_m+Yl]ȑ0ڲޫ]lQ l:Lۮ?I&>Z/ s勫'j\ͺi:4jWs>L^ 4H0K7i2kjѴw =mӗ"#5Hx1j\SZGAoJz41zo2̓X͒j644UW;joEťb].b_1B^}D}(yXIIa%D$̍()! Ӽ&!xm kJ,]y ͇G>ڭLz6!T? !RG_1\I)yQ_o8( M/K M#lt@WQ)+-?{[3 ka f8Zӆ3vk׃{.;HsԢ>=^H1JF3C;.W_etv9M4>?m[IyCLY0^&LkT:Nȇi1AB_#kUƥIcm:וI/HhӭGFݾh0,ڤzƭ{g4~6j/KuhQBjJa`d\Fo>PDS˷hEPPTP[@)´|\r3EA7$ ˲I$p3hFG{{K3~kKz\!U=n(q9AD:μeH\A¸E%:^* endstream endobj 59 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-002.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 89 0 R /BBox [0 0 576 360] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 90 0 R>> /ExtGState << >>/ColorSpace << /sRGB 91 0 R >>>> /Length 6608 /Filter /FlateDecode >> stream x\e;NS|Cp$$ĨV$O쵖S}W㝝Ď_w_7_W_J)}ٿۿWo}?|WY_mW$Ĥk@xb!/5Ȑ<^-\d[ʯr"6X_?|oeOˋ+կZ_U˯~o~rc-loTvZs}_j}) ^@9U?uC~!?S>~!'y?+?ZW>+?W?ի+c'y?;,8οk?=< /o.3m #}.RzȺb4G7Xn==5NZk`/O;_e'~M{m|~Yͯiqq`{6^OT7+{ *?=1>(^’rx*%nPxmKNs"zz榞W1_mhyڑ/m%49Wxa+|2u;6崋nnjûcKh;W[KmSCuQB;9XPO3_ks>tno;䴔nKZE[XQ#\%l5{Bw7Wې.`?ϯ*"N'oj v{(ݶgyXROSlvn4ۆ\va7es??ڊwgf[1?g5eQ y+ +uir`V?)]~w X}_%2mW]^i.K 49#`brnP4ۖa7eMo4x}>4QkW&aIn8;Z`wOe#]vk_cc}qWfd?Yzzǐ|b]%tir4ݠ4ږ{ۭw\CE[X ߭.J֍v5’]i6m[ߥwQ۔.bo}pX,:] ^V^D%^DzQB*Gc ,(Ẃ]ݠ4ږ{-_Y=:k8lIUv炒?Ie_`I͘tCm>W۔.bo.G]خ1 Q<ǴODU.lJbM9"bKTx3rClLbL#~’r]{yt v{ۭwо,|ߜ#=[-fcIBReko`Enrݚ/. *尭EOP|g+yŨV v mC.eGAzwq;fgoVc:#lXR=f8?֩]E۔.bo]z%rw<aUC]jL!_1]=CO3+ۑnP]{ۭ27~+';={9x֯4,#ymRDlof`__G7(M9"nc&c~qmlV?kV>9嶺(׭9Ŧy`HS߹íiݚ/Gi9ע<j_6eՂB~ZC!oT@ZDyth Ec>MIJCz|Bfeg aE/4O ۰_vl[rEzi/lev{q7%+u+圄ݿtVGN[}}s|Q:-+>2Ērݲ9_X_^CS6崋n ~q۳ݬf3VٔD)Clσ庿s=YGLY6=V'oɜ3#oy={oGم%底tNe`3rԝOmC.[\n}XA}7>XRЍi\XQ7(ݭmi)zP,<'-8={KXR+dq%ZnPZW:rEmc1YX`׳ Onț5“mP NK!]~-_=oS-A`W2l I>}طwݠ4ږv {ۭB^Nyߜq7;X d[]4q, 'Ѡn";WaIe`BlVcmKN햯Wo=ջ(LRA]zDT¢&PO͠ڦv{ۭ*Z_rc%TEƀURUJ%x:!'Z):irrݠU[ےG-N?حxsy1fW:9Ziܖخ9b(a,`"ä6 5_+;:/Xj>1<,e4Xtdy;FΙkf,!~حwa,)8̱Z:Hm"_;$IwYRM9"[1L|"iXΦpJ']~r$,%8(.R۔.bo0 xYM gݒugv>ڏ|_xmi`͵Н4mi'N8^u}6>FݞC)aE>qXG,c۔.bo]P!}qXjmOTQU^/ĒZQE?nP.hrY 앵ҪOǏ󁛵2V>?5Opa=O}2ۖv9Uc|X) CV:D!PtS@XQJCDX?ݧJCmC.)5,wAM6r9[XR)dr= OmagX6KW<lkM+=9 (4j1orEm/>O8ς\SK!<Vԩ{b){zK-9"{}sG>BXRdzsb{ʶ%]v+oy֙ς-hczzhF;J%2fEutu1y=N ۦ|ݧֺ⫫vFdz|:o=(d&uPTXRW5(9ۼ[Ai-9"l{ *TXn~>`RnG-ʹ1I*M٠tt<ϑ.bo_:NCW`+jjqWZD!ߟ<5X;'>AAЎ崋sfQc8ZYtVϜLG,Q[r+N[Ē:Gl/~|%ۖv {}Ph6oEE/yA=cQ&baJwU=W휰˱vq8~ mCV6HzcuQ9n KǨENʥڦvѻtcޞQ  ]vQqiF:iv=TV/<چ\va|%2һ'y0.E'ͫ>򺰤fz~D.ݠt~8Vev;u*guve-}%{]ɟ`EͨXuvjrEmbc}s<O{p+VHpf@pR6. Ϟva9{ͪ%ng~xYE)gXRzLU,G8ۖaKÞǽ$q YXR?>b((ַ?>%^8ղ-6崋[Z`y=#>Kʢ3 JV ZS=6~As'6崋ndt[7g F~ZG*[SuzfE׉ʅ>~"8Vp_GuE#Rmy'w(ߟ '<%l0Lk`?>~1/auPJ~#ﺍZTSqnۺtWmi. ,KyCԤ`CF#G",Q8FѶ䴋_jg[hŘ^3:[rFIJ{Bݠ,9n%/uު/(PG{=-.9Kŝ,bI7%~-_;ǝqt/0Nm6֗H+ʫE;#4Ϫ Bw;#jr/Ōꗁ79zmETY[sG`JQKNCMlnQ%]~}Ko@9^w}Sq-g(}ϡA@J,෣ңT|zMyv+2R, ɗ_#kKq;#,aIqpSTs|sM9"K^q/" '7Fp$Xd%UTuaG7(<%]vk+n7U-Q'wMzdN'Hpإ{E*NUB(]D۔.bo[%8H Ltr-Q8Y+aIw NHxEmKNw%A*lF[ [A[Ik#m̵6|&\h[%xgjhsgm u;88Zxyt6C^qWXQ'-[ Z?k;N-$_(i&Թ@ ;}nmi).Ȑ@ endstream endobj 93 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 102 0 obj << /Length 3296 /Filter /FlateDecode >> stream xڕˎ_1,g37Y'Nfz=}HXI%O=!q6AfwuWuox޴i[fMթۛͯIwX,sk|Zd\vFl }]6:Oݟ#]0yBq7>}5NCv1{:1w"ȳ[nS[>?n1i[Ur ` p+c)(%3d?-L^%j̧xxXI;u`CYyGۉG|?yBf$Ų(=KItm?DPB x2I.m{EϋHح9x^$ozaxKc8O3P`it5M|$T5SF*! '\fGw&G{$RAr?n";gZJpk:|ta}~Șm'\n(g!6q*;JSB/ [^HU.GT4c۬ByZZM4&-W]ei=] -w&y/ s1rWLWZ<`n߇p.Mjqbbw`dM k½n##(aC1bWwi?Hõkwxq1a'U>1~ر3 3tB j3._T2-I}lyEMhԌ(a <a"'e “ .;opp¸/S&g[>r"gYdFW!t좐xu OHBN;)s?=KHi $F!6ZtJ]#'n&f:$Pw{.4%Al(G3}?xVN՟EsaL `fS;r ZK8,~ k,KnhIt 'oAM 鉜))Hɣ[_^Tb`+R͗Fy祕?o˴-+ A|fҸHșfß 8e4szJNͽL 6wٹXB%4`_I]:s6 +a2u]94EASLC'4Q:Y:>5y'f2C\B֨KZB5DH:͈u9@އ$u %܇f$̆TVn=.tZE=ܳDOJPaP%wd9fw:̳* \nwɉRW8_'"vǽz@nt-#iۺ!6 0HPr]an}cRij$@|iUSҡ :!7*AC-̍xn1Was#盼O%0~;#)RB7iCVXk=nIEkqn< }H1FlS ҌS/ͅ&x4R}$hFARqE\a!iN[dpSʤFomD0лh׌w7iͳG»D [>7&LFYޚ?p6 (LQS8[poJ-qkej> endstream endobj 116 0 obj << /Length 2251 /Filter /FlateDecode >> stream xY[o~_a,P,.gKfctmyi@KF}mȡD_p Y*FZFk558S N%y\#&+ͣ5QJ܋cڭcٖՖ\Ѣ85vۚ!6/ԤW1~Zj2FTul^j]̊lꟑKTZl$o4;rىAc^O8CE\Xx5Qy{n$t^Yj67MMB}4d(> ELW8}X!RfP8nWF˶d[v h;r)cz4A4Ubv8TY14i'rmi%@ 31 !VI y@3%} Y 7udzZQqchʧm"L~S&W%@+}[jy۬w19+@6TAI0Hy*gMć(xe2e,<%YH]Oj-vq{IkAxh&{e(qU$-'S'`U} >soC@gI Bpأq$;+, MHgĄpZeea0-{In#Kaq^C}S\0veá4Fwz~%Ι @wكBj+eK:Yxjz_O974$.rmwwewF?^_[h|[ '6] r ?;VI@Z᾿ nQ|pcwH8h+3y7OIpT̎r@;<Q0td-OSJV9Kh@&pA<$dVD^ enx7qUõ~Z_qZgjMM:D`8)^"IF"+|GN ݂! ,+O7$< {!9E#|3お*^XfMTD,JENvq2U0qbMIכϩ$:ދfMKJaqc ̸rMֻCKTt~+I UCI!4 ?8uq& ]{Y[~ua9p~p" _$rf ?5UX4ph`{I4 w<-,ѓj5;664Nzkq. u#BnnjCS^,~ 7\{ruP쩤j7q-V Dj]EȹY ;W\x,?7 c#turYd}@׾ q\p5IqW\:Ec(vyj-RE=eK )KXx ]+W<wzkzjM׃El`y7r J8SXxaӧoMV3 V}QnR^ۦO\E%]DqG:^NWۍ> [؁!/I Q=`x4 (2sm?kUEـÖF0bI4i/`r{5=z`j#%َh#*_7P7=Y( O{Uͧw&O^.&jV7NRѢ)Bz jߣM&IGpNlP w(e' }}n$#٨}=C-Nq9,+f3Ч SvGa@v rN\u|?ۗU|B.> stream xuRMO0 WRn 6 ހCh˘vq>nBS{̸dZp@}EgW{I&;),!/Ԥ KɔHYNnqo=MʔRT^,]M`ӦП4ϩa0s4GܽUc{Jj#ͺzmGmD>CFWq|1.@|HVQI 0+|zX(Lx6/. |RSL֚*T8A;:öQ#e@*rYgJ|B&8_.#)8̍ݺ>| =s2  s=VsGZ%Ak. 4?5 endstream endobj 111 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-007.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 128 0 R /BBox [0 0 432 288] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 129 0 R>> /ExtGState << >>/ColorSpace << /sRGB 130 0 R >>>> /Length 872 /Filter /FlateDecode >> stream xVMs0W19 KG 3CLB:I>+Ke4uP/}zZ w`J%Ih0K#L )?ӂ]_EpsQ()A6$/uAJ -.`%} _40GHr/ a3GdhMks=-'fNî/w,~wɛfW,Hغ@Ha{gf+m}D6UUv9t97U2B'QV(՘JnfvKaf2nDgsa25d"il 0s] `o$T~@vG]Sh'EOoe89CKXß?q:9<~,cFr7+Wͯia]9}o,c>y5Xl &MqBQxj#27kfMٝ5tgM:Fj0RأSee쨌eWq}].θmd'1N //٣,} U]M\Q* *cy*! 靠NʞWB ,SzëA?zz9=KBW4,WSKE5)ɭ*QL=뀜ǀCj70.x xUcH#NWؠ}0 K+h =*ߦKq{Tln}&rr?ah W?~}|XbXtu;_ *__?MJT endstream endobj 132 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 113 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-008.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 133 0 R /BBox [0 0 504 288] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 134 0 R/F3 135 0 R>> /ExtGState << >>/ColorSpace << /sRGB 136 0 R >>>> /Length 6902 /Filter /FlateDecode >> stream x\KmQ_0Ȏ_5["  4j{jB *W.]z~]2G{{Q??7o{+Rcݷ0Gy>~5}Vzϫ>Ycaq=Z)<$s"gVgq$Eaq-X EY'[߾=wOî CoT5!iVGƳZA V*ϱ|3 3gߣ<7zn[D@+q;; i%ARXcb̯Y㸞|2'$ƳMLb{]m:|ZY qR+ E<[ >W(9h/>zIKg!IlED@+:9S+ >괔jg[0a2ktށ.hv8j?ٸ:qVYƸ֥hy޽;{ N."{47q$5{/fJ"{L)#nU3Ϝ'N5Jz1}aVvS'--?ĒnیݺI4\ ڭ֞-6gg?cEpc++nR,ͺ%]ľ2|.LQ{t̅5sLXR1[~&GݖRaWՖsb};vˏ&VԖm1amvEuK.]V[*L/X9 {ZriC}ã+ YD#ݤXuK.}nKGX9ݡS,f)wš9˚S ;+nRH-"nŦ:l7gc4"( 6OHԜkle%w$%]®vmіkl 8;S_a^+ۺ)% e=miP ̺/nej19 wl>tb++ye|.dƚWrs:}LXm+nej\c͙!Ҝ{B5Xf;VJEXQtLYƶ8KݠXZuK.]f[5ΉG)Nvj"ޒ n,aeF`\ W1:)5ĭJ(ߌ+g 'g5ڕR‰8ߛ= qai"P՝Vb^9/_WtZACTL.޵xFdyGG)j΁aoݤbdSsӸ832Pi f.Q%zqC|uz׌Y-®v담8/vp l)v΀*LB^o)=(*ƆYᆼ ZO\'V??|07Nc**NT{L@;GY,mq)\uVQuZsb# s݌OIlt 5):MZF kjܞ$N7[9@'nel\7*33hJg+ض1< ѢZ= NJe q4ǁTƽqZ8c!bt8ЊbJ[kvuak{UB bT̈h4~Ee+)ɘxKjEQ1p,"\DZI|)V1JӐ }[Vu:`>&C0zC+8y Gf]8X*EQƸVK(qED8gvuo`MSwĉ 33p]j% [܋rAr0aM{j%!iWJep/y*y) c' [1|[D@;0z7íZ:)5ĭ|<"[CF8X8T=Yѽ0f0b}L iU6b)m*B#*vF<^lĉWl8מ;"9 wę(>gq$$uJJk[m 4AI f;K]@PE1%=‰NJ0qE6AkqRTښ'Ƿ"ivlEkOIY8yfrZISRYCjǩYŖmy[tmу!!Ap&U{ {l;)5­fP.%0p6C ڑR%'B 2k_N0l p/Y(ca p荞y3'fCD4ϱf`3DMZ<ǺNJe qCg.<1W!˄gӌ[gZ=ȡqwJB#J9Gik[mg(,š6pL:g'"S@ևp#Jj%Fd^l %<2SeN\bRqEi4[,r#\6.)'2_/O?9|=ӿ?*}J!#l/~1||?AGx^ g |SD q~!uKrE."8x$o̱|nm_,0j;#mNķ7,nj֐>0h6TNlʔxn/)qm6mNMтw?ǣ~6Foۿ^](|Ǣ&:Dϗ/Ñ OnlcZvzqܾG 3r;~ {aMU'$R*Jnm/vsMn8>C_k]ܖZn95|b[-RwaM"n¹ݎDط_i=HѺ+I7\+ܜw!v;d&Ҭ[r%jKZ3@=LgýE}cw{*8QR/& +8ǜrsnR,ͺ-]Ʈv-ss0x1gFss!xq&+ nYXR ؊F&Ҭ `WՖ{AN($|%^$}LA[cQcEeOrcluLqݖ.aWI0k"#mx 8|zCJFbԻJR(b0_\!3ӨWGݜ)6x#)vƑ3pw"u\ZI(괔ǭգ"rMf$95.<;A|Uu7Q_H5VTm8q^ =fbKaqnHQW #,)U |ŝ~Ӳ-U@bAQ|a.I/㑖Q`{RE >ƈP"&Ç"ͷ-q["<%4ZuJJk[lR hq䗐#n֗cclR ho~ :-/wXb\א^>#`EMH3 8;Zϼ/TJY6dlrM4[.K}[m= AƬLԮ|ݑooJI>#iqX2Gnew[̶ЇHxWHÞx#9O5oAPb F \v D ~c:7pOQny7GA⢱?hݤGKnNYrN}yKb7ī;7>VS5ur[ʙrEwiw'٫9Xur[bIr1V~\(lW~g%!]®v-4Hv6?OY8?)ǫĊH(%dꮾȺ%]®vIc\r%; ;wd˥"qMr;-iEpr> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 143 0 obj << /Length 2091 /Filter /FlateDecode >> stream xڭi ~s2.`;1^Wwծȍ(ϻ̛7w^_}]nMcMJ](cdM~J*3Zae~Vs6ʋyW/*U]$V,P@E^z& DyG]l?@>ݷHpCS<0m"sC`lz<]5RB~t~x$~3cTu'{:Ei;k oXG^ 9m0`~i˧8m m{{sX q@#I3,[kyմ[͂lrbw7K#D z"1dҏ=ly{H{@T#E+c6U90BUx{sH|/LHXEY,f-ГiU8: :T M4\imSAdBX5mj .%Hq4ʋ-gA&zyū Ij|:WCr5'cG7w4링'SgU}..*w쮋yC6NM%IT}Kt.J)yMelU/yMTҏX5b⁃<xK HXcfC$)c.W.D=ֶsSC\rS]4Xky*5mM IuTmι{^`4(pR[ܱ'IC0MKK/N<+@ͫ|P< RakcA Ip q=dF2.&S.DOBAH)p P"|Bdxx+L'_/6v~Km`|oꃳOP[9͓JKw·Q " ?4hf. 5SnU.*xKj,PDthKYL-7v:Ӊ em;59SDZ)#OQ[$l!y3aGm !W>\**>ퟚТ=j&k1ow)"9PA,@_I&:OjjG0Ϋݥw˦`(כ;'0rd s !Q.. i5ɰvwWD/E6lf)#M!s 4t϶DZGspԷsygٲ4k݈W,f@ڱ94}y@ۗ؞mim}hH]S@dfkUU!'rF endstream endobj 139 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-011.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 148 0 R /BBox [0 0 864 504] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 149 0 R>> /ExtGState << >>/ColorSpace << /sRGB 150 0 R >>>> /Length 861 /Filter /FlateDecode >> stream xVKOAϯhGYDFQ)ea`R|_z92`͏~ׇs9g{ʣo ?)0OWO{Z@M'~5 u:aMiphgr%mu&h!М`~ReVYK2O3_:0G;`8W `b[\6|3pR!- -mb-uab-eb-E.;>).nLVňB`%ɜp揄^p2^uGsClɜ&n+/oHQJcZc] !ژ=u.ؽv/B#ć~{=n'y8f;a>U2̦s)8el N8?Zzsɏу=(qx#7̈yt';#W,i7m~CMᖢos;T*-PBINB ly-)= )*A 8v`=;iPAr tje}9o=-zzМqΉ؋ƗEޓ_5%XHĖQ!ZHFƇkj [ j [a-G͈/㦘͔YvQ73>R3 gvQ9+S9hҹ)D8dgSp l Nra 95U+$apVUbȼJ 52'VfL#+1df%Z!S+1zGTS@P^Q!P.آ (gДTL%޼ Mo;}/K}o-_`}"tf endstream endobj 152 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 2 0 obj << /Type /ObjStm /N 100 /First 805 /Length 2421 /Filter /FlateDecode >> stream xZ[oF~ׯ ~)\tۍmhYSKR)%lTb Ùs|ghL ,2LȤfbtID@I)Ŕïe*ҐigihJ%Ӛz`1 ilgދ,JŌdB `0%B`(DY(c1~9h9 EaRRxFZɜ5Z`ґkP 1^0 l&`=^y`3;Fs`6\ Ar`qiR7h\qS OhinB1^(B 89B3+$ ^!ZMX " ֈ4IdAN#j7|)7()l$?+%8LZTp2S0ZwP.Q5a%Q @Z ?\tH I9"51'D4pמi -i<R{C9#1ADJrDGA;%R2hgG,9c]ŒIgmQ͸D -J.Ye '(dp` dVg C%q@GُQ,11Xr9&_P"@?wv37v3v퍲Af8ckoRaXESbS[a{u)57TՄW:Z;ij;&d4G ֛{yuUU-V#aShkNz\yJ(m8\3CxCmUd~V*1Kϣs{'jx͋Y]m:UL8)tlTmdUa6D Q#A2FnH9Aڑd`[u_$  /A9>آ_B'y A.Ԋt^鰁u1i'ϿQB P`X0jٻ--{Y`y z9`<򚞚.֪Ѻ'(v+A7({:g :m.ɫ|YV-ދ njSbe|?緓ɬ)<~^\]p)ȘLټA'1UKB2`}ɤNI<Ɋ:Oc%4j`eCYh%K4EpDk_%5N2D,7IZϧe:ojR̀(YJ5i?RTQrjҕƕ0qJz2@cԁ\E**RQ=PRd4rQ3FdH|ARTB4]I[]iQhڧNyob?fN3RɺB 6O%nEP5Sv M2mȿ+Z'VQ}w -zY! Dy:9ck-גNL ]06%RLʱs?uݹ{`(1D t\țbcsIEXYˢʪj7*5uhz5N:)]9@w;" wȤA&@& ڄ" Mݯǹ/H% cX\aNE~ <9@ Z$Ƃ4J#9\ .%c3'WĎDPJyRZP~=6M+<0aWVS7P R7׽im.y=/}zFAL#ALkC|fؾggQ 6ӊ$Zsj*0Tx;ʑm%ǽAi]xa0RQ[5Js'z{W5nu<0: lE endstream endobj 160 0 obj << /Length 2973 /Filter /FlateDecode >> stream xڽYo8=BYYl iXIvƊwetY~uuNꦒ_*TWå\|g_./[5tN\.+ࡹ_.U8a^񁖇gHgޥ!vaO:{^w7V55 HA䔭p(*-@bD\=4"Npި=iwaU\s?ȣ,,ާ3"gG 4Y0t{ FT}I-R$,Vʸ>D`'*5Y/- OFZm̈B0bM#tx u.rORK]G04F3af'K5ɦQW\-%XYiU1`*{.5k|\rT#1Lbd Q0w>ɀWh^S)9 6a6]^WׁKv(\U77 swXZYʠkEf]R{m}kӚ,Y&qaR` 'N-&`C1-ӠkWC|aJ\< q:1X0i!#R!Sb!\Hp榈EHUzɯg|pKaęHq  x0eq:..7YǾ>>\6(H!=l ـ HW;(4Ŏo6ryh\N*}0\ tr<¾R.^P$4/,t,8deާhH]j) ]g dP{6 dڎ"f쩈:#р֫Xk '= ݳ^Za~K|\'j襼'2;Vk )mUkܨZ3? JhÄɱ/2d~Qp9_-UW~ȱ,G`~A0_sClPDG.Yz$:uC_p 3-*H\.wq~L T@="8wT-z%/2Q语uВ_odRha5JyVp++͠V8)F!v&N>r F!Z[2tN޴Z٧r\aLͩ5S1ah58eo еS~3 #]H'd$9tT->. endstream endobj 155 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-013.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 166 0 R /BBox [0 0 288 360] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 167 0 R>> /ExtGState << >>/ColorSpace << /sRGB 168 0 R >>>> /Length 397 /Filter /FlateDecode >> stream xMo0 >ü8_M 6 4ho@|h?LۤΓ׭:%>1 s"0yyW0B@s.z#/2L ` xl`XZ@f3 R]uv)tZ4*b'7,Q%9gspkO7 )Ĥ4 o =t^~N&'R4ttȟAdQjcMEfSְO)9fi:r׎B$(1ՔDU8 !lp{!Ҷ1lpmњC9x, ϋ-j;ȩ\Q.mrZ.Ғr^*r^?ADo endstream endobj 170 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 180 0 obj << /Length 1443 /Filter /FlateDecode >> stream xڅWKs6WH͘4 [3L;N@cb@*@RG}|RA*PY:LRƅM K!m)ѓۏ->ߊhfn/2.ji`3VuOxT>eu_QZ[<OyxG[a-]nDJťlMedL(NAޜT:@?;|>|XLEz zv*tr+L efnQ 94iiLX%%գqmY,Z1K aPᜓ<^F*19da>ͥ/`(IBG8^ "t9 p2n<'zP m>9W cR!{4GC%95 a;.աC- 4TfzI=Q8׊M}cLM;n9.VŚ|z,5߄W@OK R1T|nm갦D< *L `.{({gqL~"Rp6 #MnSsd: WIu3P߁dkPzD$ _z9@Z XDqWH&{1> #L_ua9PL 5ok\.OIpg} U1#b >Iâ< U$.J;DqF/&8>Gƞ F 2";Ut-’]>{9) ||y20zO"nR\;^2Rԃ8n39h[3:|/,H}%g-KqV6gRFŶ4LTD;FA^ zbuc&]ZȤlaG<56ħnFP)tr^nxgF|xXa`F35MY-{g< pjq͛bV+-'x^(-J:?K&iI|y+A$6sxlVA3?%pxa)ݼTx,VbQ~?洍?ʪJdх*c9+4#EEwީ-A}WUIU)K"uNfA4bS>߶r8o[y<@LliP1.[j endstream endobj 157 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-014.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 182 0 R /BBox [0 0 360 360] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 183 0 R>> /ExtGState << >>/ColorSpace << /sRGB 184 0 R >>>> /Length 795 /Filter /FlateDecode >> stream xMO1 +r=D+@@a+mjkOdD.&TW߇ {pn_ :>_n >0Z9:#~ WJ)'A>) (4.:;9F 2\;X`-$ Fбw! Q$ Bt4V"I HWr)H䗻z#%|Nc$X#6B/":pZߩ5`"b tԩ

&}TWۯv?vZ]<'FN> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 192 0 obj << /Length 269 /Filter /FlateDecode >> stream xMPKO +8ëum'm&Vن =fh (H-\%FԎvgMVDX Y6ʇsM#yƵ@|WMKQ/kJ g%m{ƚPp%olZp`}'"(x=nXļh },V3eܥ6BBE_|GD٠ Nzy.W }r'~BV$XZS.+̀*%;Lk endstream endobj 173 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-015.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 194 0 R /BBox [0 0 792 504] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 195 0 R/F3 196 0 R>> /ExtGState << >>/ColorSpace << /sRGB 197 0 R >>>> /Length 5164 /Filter /FlateDecode >> stream x\YsGr~ǯGaMoGҮd،!8K)á,7hȧjl}5c%832I ,5u\m.?ˊN0l Mhq Bg͵Ɣ!ѳܜ4:O/fx}uBlחgas2x3χz{ywϜI`HBKޟpΛy\ ?l+Lwz3\ln4D8w}AW_9Q1PLh8%^עȫw͂fyyz\^nφMxK]S[f?\oj>7CnsH$Lu8CR}<; 0&yWh +^B׻k$ys_Axۯ-s=X&zq{xxm YU~>I2a/ WWpSꟁ&r{s+{:}>C"8^g7w~ٷU+&sȓ۾/Hi M/ۛn#fc)>l7m7QǑZ?Y hX )b螯wϏI]%t𪟭dXnzUDΓ /a!(v8Vq: j)bMuHc_nf;rgOԛrH@)NӽW.i/7Mvlu%>[='2@!|DjC1cgggz( ۏ 4_T R%Em?C=p&YYm/-rQdno6S6hOotκg.͗mrWrY?2 r$ &}%)eeu0<)0y1M3~ݞ=c W jsžYL^-ٗl1q&I dzWKOjI&xDttd'V Rոd{*OUwFsb,?%\xF?{H>ε#djW x;=2vwPڏg7Xա6UTM(~tt@~{s~uO^1Ù(A>1J{5UmBBn9ܾگWo^lɤ97'!s9̞gn;D. uі\%m?]c}zF`8~3Pr ׯ#xkȇC&UHO _ڢCڅ6,Pl}Aر$Y*a.J)ZW並ޜ*!%$&=MщgtQC U'7] O]t/ *pu 9I;ՂCQcM-:17t{Q>p闡 >Ls헡S .vY'V2؊~ JLM wǡSkמ1- '$Kz\VI~k4E\t,XY0XWpEnF=E7\$,7>q?nm'|a0l"̥2+ jmAZi"dGg8Ȱi(ϥq/ps<`?FiO|,1a}|zQ"AQb$)T P-'$a8ܗ81=bl()"EBq.X7MN?Cd}W:qp+< ) FRՅ&8K'eʈGvMH)U{~NU-` ;&FM^2JJ>b4L[m/OHjD"L㘅{Vyҁgh?9#,!w,33雳 # {@_[" Nc=6Ñan0%Ɛ 7 8oYNж(6R<}8`wjA1-/xH%>yA䋏D :L_G8ArG*Rdy(O0Xnm4P: g$\%Ye.b0E#"ӔYQ~YA &Ԃ՞~$`#RF4ydςRލ\)Ʋ"KLwgd1&;a ?l]Eb.\r2U|q(7<h&2]oBȩ۶3 r;4R@44ӤMym H{} e`C |H865+S1"y.wpCo\0h8acߢͻF!ka(ӝnƠTPܾ}Ө$G}4$>hgtJgN 5khrF ŇZcP%YUQlB#@TD'T6K 7N}wx_l"%-4D^844#Iv%vz^[Ơe,+,AT8bX fg\Lɚ4Ҁ+ OwWIIĸB2y(g9yكJpi A# hLI+AUHr"5` vr Cb/)^$/^_M:+RAc-= endstream endobj 199 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 202 0 obj << /Length 236 /Filter /FlateDecode >> stream xMPMO0 WI&JpRou!1'PdO/Alh ڀAK(ǼQntw7x`@텳HF xg@"ՇqrhP|s|mZk umi?`_Υ_攍> /ExtGState << >>/ColorSpace << /sRGB 206 0 R >>>> /Length 31977 /Filter /FlateDecode >> stream xMfn<_CS& s$& ()]u}99 ݏU^kU\.ە}o?|G*?j1Wo_[R?<ٿo|O۷=ݷ|~kǜOGZ߿b7ý>0~ݷ~ais+ =W/ }WyaCs/z?G^~7z?=[1}ݷ{XgksYszyӟZ֏߬~Xg?kGxaVյ~|!fKoh#_̘|Gڥ|>5/]j 3$W'ПmiO?[Ǐ^1XG?=?rП`hs rGTs鑠}o}h|ﯟ z~2?~>]HJzHXHBRN$QVLQÿcqQ :HG |8S_O y9!ʣT&>V"N(gZg#SUZϛ37L*;Pdxؠd1H3M>m쳬<~,¢?$(U*oÍ|χ. x:kBY >#<+򖧣xG ,w|?%?p(Aԋtg.{y zƒLx>i蟦Gvv9Oy@3DzqtJ89 v>34=`;{)}9_ץ;NHHN &  3 k`RmTqTNN~H wulB~{xp<ڥt(3iu~|tl*`t # >ʳ=IjjG<`*kdMhQR4s _ \cď#M{uthb+dzgc&K>/%λܗS]/zY:D1oαl@s?{=`x@: Gi`i ,ӒQ!AxVy~E|P ,N44qִ:y98%;aw:jxR!El1QFdJ*Q+_*R_AHVC&Tr˒.ُΫVh@׊tVu`ZH\kK^"&)K+s׊,W+^hZAJbx(X-ZIEŒlɢyM Oz?`){ȢJ-v- ^3>d> 1lQ3~/7-`Zϰ*QVd>尹b~߇,R~.ǣ,5d)[w߾&`oXA$\D9c|W3Y秝;Z'BMQVS)![֟bK]|c=ax>^NG5%O@LFkU)$ҀCV L1 vUG΀bga݆~Ӷ ü6-L9?xMm@]r-7y;B}A!KQm*6LVm5W*}Ji?¬?&E-,yFY?Q,OgX-ֲ!32LK3fjފ tI*޷~kb`/5*Zwұ^Ahۿýov hE\}V1ԎkpbYgcq9T$'[GudeTICD\xR`6g?yږzlah^AhͣC}.[rvӦhX=M:PĹ=A^t qqFo%xrY6,” _:o'aeM2=/Eۄk-"ZEIgKBGx B`c,ŀؒ'߲$[ZzxT*J jӖ)kn[$ήg&mE>hUwZOî̭ZaUҐ-F҂d<rzp?gg?g#._l6-LH3/m@]r-Uޅ7 f<μaBM;'6 TB>x8vE\}gFYSd&}aN Y1/}YR<1la ݾJ)yr{p*VTEҝPR7CFxmZ8sI VߢK.-pWƘ1p{m/Õ̠A^EFt+h؊ +U}.[ϒ&ܘ 3{ZKbOW毅Xm@]r-X _/HǾv9P>CDŽ&D]q`:}Ѷm8`, YGM}ﲹ1loϻ- SA?eqXWЈbLǻ5ov-&rCnϗtsY1i3۠k$^Ahۿ^9vsQ}w.[ndDqM6 XqI}rq#/ ̱b j3"M$9}.I1-{`*x_G>Bd.K^Ct̑h;,I\ςohϏO#ttJWC~e5y %{ᱭyh-c7C_N Ry'g i E %1c`hoƞmgo-y?Oc.l}cpGZ73ћ=Ϩ1/hP%y?/il^Bئ *uO^R@5 _m$$SZFX(p~,7/|YVp CpOBJZQ0͇[ A4{z!gsLBJT!S%_ĩyXU[t%޷ܞy\7_o "ku+Ĕ'Q54 fvkݯ1I\[2󶼏 @;i;yc|4zv+RgL>Ld $%xre`%*s>^@+Gxmz>*xYm@&rCn& f1^|l*<{l cu|ЪxuU:O)F|oYS~nmXgwr?FJ^nKy>ӛ_#yxd_ ߇:N4+m}L2Wm+s @F|w}VHC*.XiXgbPb N"{޳6ŚWP-Xv}n!'4|c be;'^A&9$K1, z>_ ;-"ܚԋZa5G<sveA*g`y4gVP$#, >dէg z@9-ñ>M bxJ3"ѷKo Ѿޘv'Z׽1!DMxWl_ڗ7ôwۀ~Jm6A\})W;ymxUؘжEo[ϲ'zc``%tܯ'E87e60ElX=™E\}˭Ud{ xq+{ .q3/Ħ@,tNBe9)MC>n 9-̕N[Cρg+Ow+x L>/?x,e’vX,~-81u瀫ap|/ 3P`_A|Z% SdžȌK=F 8rB%Cۧ=y,>1| Yyj}*iЄY~7 p"mZKt}W 1:T[mB>&ҋ]}}]p% ؟aTPCjfh%tfNWڶj*b^^Ov1tEQ ΘJ7";y-t**7}D x]p^%޷ܱPP+v(b!trڞ̣{\xKjeSWV ؟45"Z5B |3%%wP7b('mm3Iv)*.Nc1Kq1\01[f^C3t6oqE?y" 8.c#bShmP)9`^A).a+x&_wNF[rheD;*8F=#P1m߲ɈrTV$UҐ-©zv ;0SZ=bn6C,[ ҀC{P>TXN4+CutY!QZPMaz e]˥S.ֳt6zc*Ayk) C|qIT|O&lvM]r-rNLm}oϮ(y0|5ٍ4_SlXdySVMꁍP  8a@2FPن q2՗r=KdNUo?!|bekp,I![V[^MxNT/x1At+2;0^dSF=tݷKo#EC}D>tw}HAe/m1R4ɪ+##&|Ǚ<*M/i>A ю26\?[X T |4rjw@X}alg Qڝi'0/qoL #wjg oaF.EGEn$ZTؗ_p`qP|?+YO@1#P]I|8Frl#,>dHHtANn";nTNڶ4&#ݼH_N\}^$O{>fPݟ 4WNʭ3V@X}j;4;&$y !i{xΈc.b6O ޓHmB}Tocq玕ZŹ(jSi+sT3bvLX}RdחaW`R@NL}y'nJRKĽ\ ^4C5v' P=45kv QJe/8Q3d5-6̭~}:SVlqs0AYmڟT_HtD$]ˈ&R&b4Qt5Zf [s!s)|ty*Pb7kCmt'OO5GY^\}5>e)_zk=Pu2`U9ʰ HX|ڻESw>r\YcˣtSg:/4 R &bERg_nJ@b{4{*KoF1،@c[5:x6PK̷A-@>D@/SԭfTIYCenY|m<3c;0_G ?Uw fߊb>ft>YI߇r,n #P$ctR)O>i.A,F> #pi>?$UҐ-\g%I1Jx_PjxL1TQMuX ,>delqd[!V״}tZvJ+w[g`F !`Zn`wJeA(ڇBYqٛet[P3g,׭H|sՖҀC"'Z 7Ni?eֈ`p,qnkns򭟲x"vDe 0 211'1B2 CXYv7E!+hà}lގZnE\}1ɫ1RI:aƂֶ6:l`ἕrQWPȭdOR%MU8I C/hNQ3[6g5_;]17=oIO <rGQoy%B fXu3Yhg.jY)>+>!&*竹v$UҐ-kD60QbN (bbȖ63Ѽn0*ռg5mBkH,~;Y;YGt-^W(VK䑨OQ|ʪөFE7XOTF3 @}H]4.'`YOTUCm^vU'jCf6V3:5|zؐՌݐOQOf5ž3mW w" ܂:h9Oz97X|vUf+ntP7-Fm[Zx|VTIC>KƃZt?wZOm 13Řn:m4 j8c DĻwJep P0>}Ntʋ]vx$xMmV5&S(aW꨿m7tH,NRxg:!lG\/F[V7}n!gV9;)D&eȃX!.d/ٛ1mW-70 BhT(Gť_/_:#|Xvs)'y1 MuU-k{UDŽިȱ`b@F\MF{U$j*{u8>OYoR$XrdmU@f0/7x3 ֎0I²]KY?ٛ]n3Y>v7`qGy%%VK8'gc|GJ:2&BB!wU@5u$Lt4mB?%te޷7/ç7/c#IWVczb^F_+KtZ/7/Tٗ6iݣ]r-o'" ɼ 8o:W&T *P%c־So%xr^s=f3(V{R,_F^W+7ڵ秬*,W]fpIrb /=2]3^1cGVZՒԧ˞>e Zuܭ_NǡuNAusiΰ>+RY+;PT#, >d] ڄT+c ̀>6 OZ5z}>lj'Æ ^Yp_RVH\?mNl =DMC#b`jh5 O VFe|' >S¤0tӅx^|j(nsț= TICw ͇Q[][n[jVTabn[hs_:)݀3G@s}SיPQ_?+˞iWrN3BI׭+*Z|UWH3e]YÏ*oJ^Q.qI`!zu>AM0l0_R-B'Qr.OYc6E ק47 d;G0^6@%m!}ۭpO#t%2XmJ8U# uJ&.0m,1iU2j0l`kDg2=}f`B33ɬQ~Sւ9FlėVsWJe[Uogrm~:ž.^Uo h f՛ htV! ޲FAa,;2DNQn>Nyʎ(nU?UkEx0m J@/%*|oY#bvwh` 5Ob8U` UHh;u5MHj5V5f\-/׀RVtㄺʼFՃUl@&ܸ HS֨Nx]˴9X Ų 1ڼ^ ==jr&󧬑q}hڱy ,\̏&s~l3P`~j >I]ra;q%[Hŀwe4l;V Pq$3꣮V !Ґ-M|*)䂙3ue;r_kz >UOǫ٧^uͣ^k}qlm@ wI2Gf&W4zS$8:9`E޷swKjS?{^? I=c2$(ч SCMv4~\Ow4{z;35Rm_j4(j jH>5.7Vh ![P>=7g7("jG\!*.Wڋ[mPKY5X>4b曊݇yB Δ02.̲y|2jSdhOY])3s1Uŧ*¤܍7 0uQwQm[wQ}˸.[&N\\٘x2]r>qiLGFhPhݗEyy ʋrKʫoѳÞSA;W~pGh='.5O@ '[d@OztTJ#aќ3\9[~Ax\N' 14ʅW|/xqmGz-zs$}#%үF@t1̀b\g [g :A]>dDEǦ^a :m;5* Jwܵ˭viuDA)kl{]pRەbUUq d׭k4T|܁UvRJeMWwŝqו@*ʠBױ7#P\4 ^Wo%y?v I 5$ɬ I@HV?32( Vޝ dEO?ڰv,1,AŇ._k7(x;(_#e܋Ï=‹yxfix<3,;.&G|/.}^l~ WgaO\c X\eɋyzf%lt<Ÿa{Z^~!)ߋO</^gr1J{ƽU\M۽\OUp2y m}ܽFr'VT7Z>pccx-n zߍEמecidTT%RpyxGqEY?8HpSױNF2WF>ț;ýNN_KH yM`|ߔ@۷=88y@~:oqt~|j`d<,s\M-b۷ؗ)A{u$Lj ?p xtJU9wDQ߾TGms78goīm jLTs\?2/Yz'j<j$ϔ˩`U#v*MSwC?DDjLjX6 ?N<6Up]M+<<#>M1?g"ވ<8yo]кU$pyW',ZEav*|c3^`ձBHtlC2ijԏie>~j/'UWP%^lJ|&[Sl#1_s!~ꍇ8U`lڙ/ËWx챼ɘ1jN1OV~Z\gCt{c~(eh궭.2lsW[ kA4{7O>#MC%&sǞ.xyab=.-q@X(p~.w)|e,=R*Z/?32ßż G*K !޲j:^Kx^%@?wP'&Ը_N2*b_$UҐ- 1ExQQc8w(o*+O@dbPėpVS\>E4{*Ť=9g9 ^jBA<Ќ9 Ƭ8YqqnI@{k}*˯7QX۩A%HAEՐtWKP-Um{Q\޷~9fDQQ ]j, ^A gZkMfߦK.厒GkʖA ߧω;g5!*GbM^E߻'D7u&OR% ޲:!譯7++bC3ZƼC'x JmBu]r-fഃ)bUdg]0zEùt/5̹{]r-*ކK 3y9{2qzLGF N}aR+iJ觹qF!cHTS%uYr0';̳[%x҂*i5 w s!sc% t$,A]2t]V!< KV H|Ji2f>}DY*޼>xc*t/svqdz-[n_  7Fpm5yE4WPn ⻃7!bo%xrY-.o3cmgk6dƼtn+m`(mYsߢK.*eG(tO&Zpߘs.uօ<#GjwRdEr_co6xظpi 藎4= 2umvؗ.QZ<` l{d8^PV%bZץ*Bb 1ㅼmB56]-U ځ eٳZVUZ'wok Ja^oF-[{Wcژ%qyvxA?eMk?+( 6OU}ĶS\^E\^`UTOo&+,mƣ///.as(:-zH/r[ g(1_w vV۰Kz.[{ncx}yy}N1_ܷKoKcҦA+Jyx aL6ηwo-y?,07fUY p>Q YZt\b^C31ÞT洓jՐ[az W 5Xerz7@q1{akAG*y E,ڼ(mGtE nTFGlLE4{z )sBU;KB +(1BVDWo)yrO1Bb1,͈Tې1{W:!+h^c~S=씋I96F?IzbϯZ32gRe AeнA5ZmQNH}6)޲޺pfuў8;\͋V #zD-v 2d\C2V#nDrVkLmj! oyꤩK#atkkw퓙ӱ4] jʤ*,nxzGߢK.((籁[xsCWqw:6~N]uߢK.i ީf %G}~jBq<$0z**'rmSK\}$nW `ƠV]zwsҮ!N`Fy/^A` /xdmko%xrKd\':š&mr(v*[\a:1/RO⾁X`:C{G1cE^J6+7%d&0˗d65Q`}c9!tTХ:A"W=3Eh0 EAmts[OX]"XsdTT+JOt#76*` _>Dc7r盄p3P\2~jOR% ޲G(*czrlB+%4MG%Ķf;ǭѢmB>%xr_G[Yk8ڴz+()l3l/CvNa]iL⍤zS[R姣o-y?v0FVҸ +~PMCori[c"_5oUߢW1rY a?gǿ4܋g?< .g{ێ%x[--rE.JdE+81.ـpYTsr|^*iw;yRrmsK ᖺe6w}2WWr_̪6uߢ)"g!_^TC855B*D} ӧZse٩] NgOY)-8Vxr"=슶 E S%y?ggR>֌i3 Yˤz!;H].#9z c)QD$V% *yr0BҐC{Ty@hW14iHV-w|4^CwcL¬f 1]˥1f0LIB28E\b07H?~J/]-㏆Hkl8- i9FP'mC%pҠ4ƊVkQV75*foW M; EI}QJv N@puU%TICz\+z!\Qqp㛐'e-*c]`8f8_[Q8=理|oYmu(ή]`zxePvQM72AyA^C=0FV[]-[-+ù%~g,yޖ=Ș};یVsܯ0",e4{qqzg"+yFˡ?VS!PmFJn$CV/iշf1TN6VH[30S[3m'5ѱEme4A}.!wV 7~@Qv(Ħ=tyͷ"#ϸZ%`SaisS$5lÁQCJ6dQޗfد -W9%jE\}AW|)J# sİ StV)Tl\ k6{$lQx)[P9Ѩ>g6[yye^Blִ" 1 2K\+w, bdBKwquSPHP`+1n8w-q<;w839kU88I(GFRYA-/['|i h,bčbSS\}p@i!UM>sT>2Rjk'|oYoV!l=„h-ץ=_P Sp7m/_u;OJi>)Q}R^s}1:f_R@:u8u̐RtJ5V&!yuk|! OP@a&+N!(Nl9ce@N)&+45;;`5W"06vb@YIAfsG* /1􃭦k䀒ւ-̼\+yPݒ?ԃ8[2xR!N2PIէ|[1k􌳡t% %Z=ع'i3|#H_Z1! >drޣ4 9ArJ u≯ZWYܛ0} yUҐ-< q%̊]?r jNߘL5yq̪nU?] %âV 蛦i߇qb}S2q9ۀ0Es)|CJܮ9*f9$uFhQYtu'KREE}UXXuqn3{#=1v.n566KYc@Y}AN_ upoN^hQ~[N=ICx[qр &{z+yB"Pi%#11`xG>(;1B M,P;jկQ|/#Qhʐ0k1&y}BIۘݹO@@7VTIeRi~';uCܵZ⊤{ӱm%;-mBhɘJJ#01)"ubNK,3$y#"X\*Ltm4{$H%F(D1Dv#ID$wxAfsMQ \3b9 g:N#*\&pUScw't[@ WK܃sn5N'7OYF ȲfoFqMC|ʌOW|Hs>IB)o;-mʰl#v`g%Q3k>-qC[-qTwÝBe&s)oBk?ct&Ǧc BEkƓO'U Fxpq5"2%_ѱy:K%/ګ7Jl^ڼdn^0WP%M"Uwjխ{Gͺ8u-cbz!+OT v}L(% XDRׂRRdQ4_Q5Q허R8(#U(":VFP%MDDQ yZ*Bl]6&oxٮ5Br *c'&,Sdrdا|oY_Oxt;'Itw.c/uoH{ >QqV*STJ#G6T+)m8juWr n 1QA-޻)^"~~SX euPXkG uEݵ+(٘Ӕ=4cJ+uPDUD v90hNya26' aVߤ[.IƏZ0x—Ж!6.`)2ưTx#q6!oZTa+lBh|{n4n6tD# !p,_dh dzJ@ɚv4{VjY3ba/1ŀ,4Ex0>'^֌h0ƷuigUނ-͈EF!((тa2)r7d4Y#A}h:z}ai!G9o{eWVwE-c}\PN9 8IEíwnu7>n64{z.K:ٟqwYwE0!*@ў4ۥF^C%cbYOIr#X/rD Ōڒ1!@JT nӟ%:- *6{q6jEn? 6b;/K ڮ+>_|×}:;!^~w9O/!7eX t[pF4YF:u?N&i!kfm97#^¹X hhcE.B! w&J@>ӧW)kArUjYl"T~xcES|K.e[q1RC{`q{@!Z=6HqeC =NV xuv>ey*}*ȝ]gTiQJa;2& |Ʃ^uY#pb96A+݈iTz#H.v#^}*idw<HVi\2_*dHV ES(`3F-Xd2*i5nR1#V*^1 H턡8 ,Z]+B$JF6JWpG9P.k"5GմOx~b[o'4@|1^&`y(>p6ږ68Q/|RTtOw,4^p)>OQk)k/%k_|OEDWW3 JPSK\UoWpyqEg.T?e [E#py L \@dH5UΝdTFEw`dWPL_4{=baH%5'`D1 !:NV#}*i5 >_FBTpw VI}|jhS! /DѳX&?O_! >d:hPr0Ay,إ1ڜ)/0Z"z hɫ9|oY#%#3=Bs:X=׎X݌9N_`Y|#P|VwJ}~7ӲG[҄rv(.. tjR1`*iH-9}zSW@tmn$ 9o͕+U P|EOeai!kDonGo< HYoD%n{) P {rncaԽN&HqH(ęXCl{Ź)a$ْiNȿ5pV2b%U9t*GOPgIE h((H\S)ը>I4{*gy#p@38 tg3$`K<H6/"eUajFB$⊗U"XIcgu_ȜNRj)5I[|LbU7U}*52oaYƌUtPt/Dtfռ %ph}.u_o )t]қAtzG"}vҺG5NּG9s\^ÊUUqEάV" +RO@Co!7 Jۀ*iym%L_ #Lƹ_eJeh:uU9/g o{h;Mo/r_h _C%>ͮY8VO1!BNj'|^WBAߪ(0 U؂};ܸ@ #h+!)V>tCePH=R]a~):y7Dx;kvAU.eG+㇅dbd!WSOpN7=囚VǍmeBeu<tcw2R{x:dkY޼RT[Aǘ΍&_g2=n @{8uLE_߹|\fx'fs%$)0[&cS!"1 D[وʒҵXvú r0ˎg#GV$UҐ-?~%N.~?}{ aau2xZ??ڷۿ׿v}}0OQՁ$o?W?GDϿa2pbP6{/ߣM 2Bz7|W7ͼ6ksP:yk߾qJAZ^V .QU g3/*~OE/8ƨZc`p돍?ڐb6+3^f݈?XYy_=1iAkq]aFuhxx Y`WuS'.u?0}b^OÕMpy`t ƒ=X׷@peti 꿹D^ʂuYW^x=|텗!<$ ?0<5~ ð?;ec>!|"7m890_âMP~C`:Cjn,ρyCh'Wx >;>!fj70p{ӕ9^*V;ΐ̚U}J"t< W*·txBɾx}|-8 y nHw80 F{}wA:j?ϹۊU?*ˆZJ:N/EG&偑-~a1Vfy܉oUp=߰U;_81]M0K?' g;Mzugp' 7˟" Wqa%ϰJ0VT|%'fq$V04\!l/t3k>dEMU'S9]V5fdR8>~P`觲ybge S_wR+o|y?y}vwJg+&o;TvuSIbP8]01LY&FIw5΁S^3h5M8NsJ4[1}1=Oxw.+I쳢R 1بX&b(CL܈jibZk)JfJUj֏Elkl^°Nc] z?ӭc&I磴>l)T]ù@Áuî8'1hU0Zm:lYVVi Sk^[P98%qbj oMPs#7*f3s{բJ][ ^fT2SQ##9E "^l*O[Gqi?~UF7ͯI 3qہwb:tCtfJ^ 邷E I\NH|Q@A#GaZ^*:' ya בu薔rY*}u[t%޷zƅc3m󟯮ʯ~jG|/P60r ^ h;o-y?Lb~r#}FtPK1U@kv5S ^.FGѷFEnmVtgm< +1;]z=ĶkaY̛jvh-%%w *Q1?3u_BU>J]|OM"wm)7+0 pڕ#575PZVTu2oA&1+A\` [zuUo4}$/ h{p7['ܞ/qLo(0I2,x)kY_@.\[70Smk䯨E\ѯ7[ڳ"NO=9/^ %^Ah邩QeM\}g^׷0vM$4 k:/1t2gcEɱѷKoT i/+k YҼ+tfz#/#6!?KΗ^=~gE;4K}elrZEB<v.N*> o8bEWm_vr+ԛz9Saq\?[㽯^8L+iJ}FMaO͔&ZW)4cP=Vyx uq"hބem.}n!+佾|HU=5hqc\;0'$/kK[},%IN~aιpe4 ގr֚}:l@ڑR/vq [t%޷cWϾjWŽ+v}`ZX_z^M;$_&#=~۶\l[.G.6-M]w٠bijt v$ّ޶k~Eߤ[.~}ח9 z!Ziu9>"FP'*wtd(sd>r2ܧU5}z}`A|1l$Ci ~tWtT``/*K}.۟b,Ĕzp|c,VJbPu5䵣fRX˧Е3"/U <GmjHH4k8608^G);-ra1|h&{0 ɈɐX_\.4I9M8v)ݷ͗-/Ss|117CK߾[kr]`RpF*:-zH/r[ ub GMs.ʆ^ ^C%1 Pr-o)]rCn%EyTPڴrz[x6oL1&C:"R3ڎѷ&οȭgi}cPxU$';iyz4c389/wߤ[.~}ɢj ZX!E3= yk Ҝ;趇+\DߢK.wyzTYa Orp> :>=[BPM8SԦ?ejXSjxNZ Du4] vPt5ū}N\oћSsE,fս i愞#m.c^^AՉa$yJs9o%xr->L1|B6-t0 C x Ԗ ^[kMD~[gpC |Z;IG`]Ky7]h6҈%deF醭к)#bȫȉ1׼/1na"gۄڐ˼oNEa vҽxƸtw}¤tydj; NDߢ)"u%WaբsykEm,Lt{g\_c̋h&CMby.tϻtT\ۆK߾_r(m ׷.һ7"E}/qAlŪg}.}(Q1󄐘78BůK\}˭gIq.a2* vYRu)n/ag-)yL*^B)J6dK}m˾$쳈%?lfUoafVط )xvTn{Ď}.z;k] e]#Yͻ]i(P{\o!^$0;b\ ko!Jn}n\40 ^ܪmǥѷKoZT-^tV7Uw5Ë= fy+/Cb]}}3U: *H3R=TixWxշ4 0/N|5]r-eZ"s8Q'鎗#H2b[7]h3qhE\}}VtŘ,e(G+q Pa:^ċvgqߢK.~m8i11%C+3{e(ƥWVo-OAy3N68J\_]UnЎnXq\k3l%vHǵrM!El;=U[WEnQNTNnSo3ϼжZ]K-M_ ae&i-1`@(Fk-$ol:U߮:EzڤS.fTt(\l.ЭAџ݂N|^BFb1$ _{x][tJO)䎄 &3OcSvNVBCW)9=Aӵa_ZƳίMP>N>?c|C-=wh;&R=3ڛȐ#Fxܡo6o 5bq7* ^%)h:07xE"#k.Ko1䎣`ۏzfl\OMQ k}xD@X[7!c{CRfS( +  :L*A?j>4=]B]ڤ7ΛqV.eB*̊otAzk؄ `cؚ#azrLK.ȝ_8n_<م=nAy,X/;w"67N`grlƝ E4a"-ASͦ׌x;7j v rݘ3eg[p0F6dk[ôXUڤS.fý7N**IL-`?[eR>PAt? Y&vr[ڀ3(#sߊ{0 0i -PtN$/!=: ׮UX&yܡUƻcvY+-ݣEQ5q&[\X"wΌy6s(IYɉ$=J^BdaПJ6מ'ڤS.fvqVpޡ7&"N0jN$3{uM@AzJȘvUF=ֱy  x am)۬ˇ̼o&w(EqRƄ9RiqZ5K۽O ˣPݔ̵SCWFԣC): t,Arr#X~I%3 YX Gq~Mӟ}yb;wE,w2^ b2^ 2 ]o7ǝ xS#4^8$/钫Rbm)0P^+0T*Y;K١d!ȳ 1C" Ds%^keeܯF%b ٨ W_ǖNsBҎ%3A)ALQ ȟt^^2Nd2!0a *f˰oL2p%y_ŒY ~PV)% tñI#%B܊J[4 WS힐kʵrR5,ǝ81B;ɗ#ԐzR{{Зڱ!& )5aѻXVy;" W gǎ' r Fuypi ^:k/M8kNț'̰<j\EhRM𢣵x r<#i3dITH$pjy}/fkE7\.%HIKhFV1Cu:5Uv֐kT3NNdfQp"( f{ SNÆ"\ kg'rAF)y Л5tJzT~r+b)#06Ɂp?qCU:/sa,iE'8܍:2,wj~Wxf3pS¹AnUMz+A/&e . &]rET;F2[T-٭#%X7]lgE,wlh-l rfKg xQiS&}kJorrb.=r#NpĹd جa ӡ_,. Bv0E,=y-) )`sx@q@%IH>[B,XP?92%YQpGz(([>5WPˏ>{> QPME9Nx͔6T&<ء27J/"/5T^V<l'Ϫ-&KuYS oELEk-4+#y ⠺vfkk>mQ!xܩʈpntV;G ɬCsr4~Z /JsB&iʛܩ@'Δ>^…i{ŞG= `03'SJ|[֌ww uݣu=%զ1@:"5 I*!_5uCnu eKf[/ja-6 6aBɘQ3ێrfl7K~ Gub)rU] ȕS%t^zL +hz[*µE\r5js=L YAs eU|U)jϪI&|5쪋>D{kCm }}}yyHKLb"Ci'ܑ KěN+Om'/:]U>y|yhFLAxUU ҝJH̲㐘Xa6c]p5S=A>1}:T9o=G&};Y|<뭇 2}kvHP*alxMWڀtxٷ[E,wԘݯ R/ :r=C zEi.Wdk밮n!/-\#G!x_䎏:Yn2݆sQŒ 9YNQ>9y;Z-A4B0 |.s5W"_XOav;Qp9ZfcC>K f̅k+s8s9F :a6K.9hmZ^tE,w wY8Ћ5ʡ *Yk."wr卷jӐ)Ԑ?v__1-DtP`Te-dkrO T+^* 8ƈa c{/y#-(Xu*k iȗdM L~ .hLAz1g >;A3­A{oW tx\rzǷ.àM4l/9 nWPq(1pc;zmD wMav36apSKwz/ ^A;6YچpmifAnso;ޱ UlLS!fЏ&LxlxXPrp3-:"o;bYjɌX@)UƲI1M4}[řx HnU1n o5ڢC.fSbn(F6<,ڑ[Ģ(vc)Mɝ)yBkI,iorǷ06|+sۧ(Hk:6,2A[3ETHC$kxW ~gwC;cHK5'Ae\i_3XU63N"()B \ hVD>]R+# +@v ݔOor ޔ3U (,<;A$K;%Z_v%ӲUW=ߝLA\};N򭋘t֜.c':[0ۏgA\rGS 6kB 6+N83D?M NmJ>';NĶuЉ{!fKv'^q/6锋YTVzx%t$zCc;Z(4SBS|m@9HLzky5=G爙Gx~{c@9M:N^A#rX-v}S>΀~!]#HX_AfkP Lf圮߉k߉&!&wРp6W9mzaX6[ J9/*"_7= 8Jŗ5Ҹ-HOc̠O*'CN\tpr5%wcm#@vf6:dKmR_U2%t7S*|(%n8=f S J@lRFR0oor-oS5c.qbWExѶ;҆P z.U )(kNț厐} bWjSbF_jQ_FK ЦN=ÙkN7ر≶^+@LC??G;vmAR zCxHL &>]+z{u)>Нrm#̵?hQ!&Pq;ʠ=ڀ;tռ(ыa&BcÎ[Pnq%4"sr#A\};%]@5X+ 7;ÓWЈtzɋ"iEԺ6锋YQ:5 |ٌeP{ ְWK(US.JMg)y_Vhxj:2-cvմ`َܴ+U`@DX[q)XuE4I*!_5*ϸ ,?q"l~ KX5B%Y?ID"4?Py3[ rjĒ[ ϊX˯<`b wQ>KK5j%-]1=t>V`?k&1"_?_˯?>̵T?>i׏Uˏu˔M;΂bcלնMoy~b53xk10w&:Hy_@2qۿbNN~?Żx'yb|?{&0<^9-|G; |__=f" endstream endobj 208 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 211 0 obj << /Length 393 /Filter /FlateDecode >> stream xڅSKO0 Wj$cILMݫ@=IS<>q'i4%2(PFȘr$&QD]%W7o^gTR{?pV͒Q#Fo_ZO\AD+QAE%\2\V(I[hqkA/׼9hdp[6Pނ_f?o?{N[WV:}h_O3s Qg\9Vg +s*@*UuDi,7E}%Q\621|PFp`Iu>;9NZ -N !bsH(;ͮ\Ůޤ: 2D-Q •񪌇? endstream endobj 177 0 obj << /Type /XObject /Subtype /Form /FormType 1 /PTEX.FileName (/tmp/RtmpUYDXpJ/Rbuild190a5a28d36f7f/pcaMethods/vignettes/pcaMethods-017.pdf) /PTEX.PageNumber 1 /PTEX.InfoDict 213 0 R /BBox [0 0 324 216] /Resources << /ProcSet [ /PDF /Text ] /Font << /F2 214 0 R>> /ExtGState << >>/ColorSpace << /sRGB 215 0 R >>>> /Length 10879 /Filter /FlateDecode >> stream x}ˮeqݼ {Oa CR7p4KZ݆ΈVdb*։"c32w>oˇL)=οooq|y[!??4aYhYnZy^ϑ61=R_3/ ={o>zn9C'ɟ>|GJ-9|I{す^ ()@9sTY!iH 9>u@9 yjx#,,~Q͊>ydתk>Xp&Ox/vv:_vIoW6cg~.uyP>ĒrxfU`3[SxiSN=Fuͫ_jn 5fU3b <1 UƂnXR38h"sk)]Ğv(V{FVl\x?9(S0$(8s&-’rz9*v`mTܺz%6U݁cODiQn86e֎`FJ|ժ~tA92/@X* ꍍ-؍ݿ .7ݭ_CZoi"f+;ogϑvb߮iA9rGXVƴ!ʴaVp jjwHO݈ZU5ѭA l֦aHiR k;ls#9dFZY-IahH)ti\Ctz%䴔nKjUK)9M`VEZl(lF wKiJwNUiSN=Vg}kQgA{Mjkd =||Z~SG4 rnPxiKN=U{MO7d~u+l% >jc˧MKu[u[~=aOrEiv}_]%~rV="K}_B=(K^ Kuir݋GLrj/z˼\^ȹ|L_5 z ((m$V떷*lw@R)]ؽ}i%Rܓ% &H=^s دVAw.qRkYӄwڪ8joKa*r/Zز{g'EbJWt’rxdStbӳT4h9W)-T/4_,N«?p \+uF~8np;3a"c6'ݻhu˧XR[cGOqՍ(j)]ĞvUsuO>Ꭹ"Psɞ m%T݁r|F`W)ڵ崋:D2pG?-R\0ɧ#’@//lž!1 Pڔ.bOև> QpMF5&y5I'VoH75=CҚS[wEܭ~?9;Y5tdUc ;R}aIn54 [ݳҦv{ڽ#lVwONE߰ޛՐ[J &2}nPa|*FGvkzyy`ԡI88E""N*Nu_G؂&u;Ɖ /wr&Wƴޒ}BO߲KY i)p"2b4ɹV'`{Ő5{ktOU3Obֲ+r,ͱ7P}9RFxZ;~r"m@ɷ%䶿 VTX8sG،{iSN}{!Q+_~Iٖ7=V70FȱOXPPryAW)l4Hջ55ȹl#E[#w5Q%Ǻ\7&gxDM廥)EGrEi}fDrb* cYdK+oy .zӼCvZUJ[N=+@+) s#+JVk:+RV+K ;Qs6 ^ݼ%g쫆xڗklJ+Mc)6g-lG`0mi/v\67S0[.l1'=LLwCd`Ac}#8Aɵui)ݻ/fsՓ~9 Sg.J[/pbEX1M#]qbR1|jհ/vV<0=jjpûpLD0.0 h)ӂ 6$f5qSIY(,~h5aIq|@F\v{ҭG"]nN5_>Uoib/eŚMIbl2o֯2-LAbU+ڗ ⮰m7t͏!4 (.gԐy芎<`Hk4!5UzIg[RYpeEi"'lB ~'9vZ!]~sen1}ݖ0kZz_n;0zHVg4 tiI҄wJ5w'[KX&v.J%@1Gmie90}":،C*K362m` )7m`ܾB#ЉoH}%H[Bi&+hϮ#vdo7o!i}w_IVe(l/Vנ^bj܀:Sc^OiQD btYfBZtq܋QU }*Uމ)pI*`U)TG:J#Rr,Q[&fl[Y_n/%dP# &t!>A"G"YGNOGp/|Y]]uPUŘH'FQl)\3;BJk;mjF@D )71lpNzZp>KV'h}8'01p7ц솹e/շ+Cz! .p]G(ñDNCÉ0ۮ_4w&bݍ9E04Dٞ&5FiZ1WN[a~^p/qh+fZm=HkVFiBJk;m 71n>rB: Gb+pͲYZ`_wHi pۣ*M  q0l!E8M0p֢F )5'Vj[|BYJ. ׺GZ|ϚUN[cM84"2%Erq7eŕ0[3p$R81`$_#֦׋4ws{}=\ U0spxQhGAHR>#Z546_ BZC8+;~u;h]}$FLaftDZ-p4!5{W?&1l7-toǼ݃SHI'ֆZ(|NFB}ZuN^iBJk;m O7;,rP"҂ lj(;m!/Hkq܋DiaN/#ٔ7b&By HŴ  */ATF_4m.BARx(]cJe[l% D!yF`L}(12{WX sђdw tayt|̾J 6s,&/]kM=8Wc-\:@ ؿyfHi^lݑTwؑTvvKo+#?(e~H0_\,}Hj 6s5Ak!Fg.6\:B"XõO#Ѵ}C}?qsZK\ 4 ˦ T*g ͽ PcVkF…"D\h:w)ٹۿ~ T#si֡mvlچU^C6_$]1( &E":ԚbOӤ4slj$ҷ8,NlemO;;'I=’ڛXAFXDe{obQڔǮnmK6㰎K`x$؈5V LN?A*CcdI)! m["}D@pb#W^{'KA N{ N5*}nU+tw`Vѱ``vrbZ`IA7܅Alun-9-%[ ,.=!.K-OԎ؉n̠7K*6Õ+bZEݠ4Җv {ڽ`W:Ξpi#Nȶk׍ASeNiS>tTޱ|aNy3zO\ry Kj)oq:E 7)mi*^zcްԺ)P;zyR$f%6Sn:햷̸|dyЕ<$=}}ϕsZ)Q }\k5z/m㸩9ZiQ9 ߠI=bFY66h`iCǖS,)7X-R77Zrҩ;jm7?mGGx,yΗ'jx f+j;o.toGiSN=WBJ3 :'d ?/l.MmcI}8-8Gݠ4Җv {-bϧ8o#{bڵC~raI]S}&A *<崋nM9YtE9շ;9# ) \q%,NIhvt']iS޴7` .{m El(p~#( g%]ȩzFڒ.aO$+pӾOZL{ 3"ph37|KjqiR k;l҈6LK0V8Yj(;єFKjqq:6 Qڔ.bOwsoF4^(so$}3レ^RځAaIIũh ָᣋRsOs˻6"GvZU8.: ͪ/ilKXR 8CT\[My /t~dWKfWnP b)tx+&[~kRF'K|tM&Mg6tHV",^j{ tH[r%i_nShQLSDi6Tgȇ#,)~c9t[ܤnPH)حn$ y؞848ԤhnɢmRΪ]1y *:Ѱ%!K?1 @D) g~fKR$z@؂]v)2w=6V+yʾDZѶ][’72W׷KwrQڔ6#5NEdu4TK\+Ty!'āl8RLDڔӮ*l8ÑG+ k myG4XRM5olC[˨7gڔ.bO^ +qε3 7p**Z@ra#T Ts 1yӬ4|WD͹z|z?9 V>r!?N>jq7mXyf[rm!]حr{o]NdEUחgř] ҆\vbW]LɆUmc;KU=6.+SwD,2 7Ik/0MHi p_8:~?9ne-kqW!pnKjƇ8 ۽ww(miݚb#ws0_nsvX3tR^U bES1VcվHDdP%vZ:.xRQqy/ƦbkOpGmTNDڔ7r >RSu*.8Li߲tZcٚ~K|Ήyû֝cƦ)]Ğv﫹}^t\.8Y3nO-@<@,8# AmƖ.aOս;@tTpj,\Zլ*bZ8OHDXOiSN=Ciqb==;96QZBr$,G䞂t8!]ؽ諒}O} 0zazBk5Rd4"^0zPU}N$53,zɿ/x{`WoocΚkoV{d*m%GqU* ;JB3@U@Vòc'e|짗zV[*{} 1>Ͷun~o Ώʙ_i|fٽZE/4.,ycaYE )jWE=TjQQ 9coTamXǿ}Okο]I?7./wWYUu5¦/޾Z_3Kl/z/O*z}U(ok,?>dO?Tbq?Vo|G)#)-+bcRXm0C^P_LTطljFGdBLJRSt]峛Lpņ~~c;D?;R|F+_K"hb|Roi~Ae|1{÷寽k^I9ZnQ~oeU:CN]}UO-Xv95U_Sg?u(> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~ endstream endobj 220 0 obj << /Length 1667 /Filter /FlateDecode >> stream xڭWKSHW(W!E4ʞ &Tnj+A\ؖ2MoFl537=WO=P626Ճ@iX8KiWo_7ȣ<)Qn ,9Tշah3QVnP:Zx΂[O3h: 4冇߂ܨPVdd3^u"v;3]:=$aP!qY0M' 97 ӊOĠڰZ"w$ m7ƿgrW^Xuqy, A,~״Zz!6wii`? 󴦜Mj .P*p4ۛF1Yv:0i+V X4!q{Dk,{4 8AHWKt&G[ "zEQ)K{hbσ.]"{0qm0S[U2DۼA8%z_(k (w[l[M+.|3ImJU|h0/e#=}"D{r{fEl+z ̉yab0jǵI8HN2Ý4|-7 7%wP9j+ŷeSTJ[W4,˃ bsXX;s}d*h@9~mp\{j[gM @H~},9=i<Ւ۴Y(DŶlGX.څWD6MlHzyMW#{b񽜰5%9VޘlAu-.&n(ڷOzD!> stream xڍP]۶pwwwww[ xp %wwwwx=_^Q{1')P Sea03123"PP[#F:X;xe 4q})8nv6 '/ /33 y&F@!lmif4."@gk3@ h`f t_!\]y<<<M]-i֮VU h0@3F ?r5 Wg ]`gm{́΀5y#?p+5og33{G5`am(I3zL@ع8Xۙ] @RD`N?\̜]]]W.K Wv݋韓9x|,A0wsdY;ec.B#88Y@'̊^8:8,I-|\L܁Wg7Ͽ!̭\@KkŸb?=z`Oec2ɫʋ)i:QQO'+Q6OY8xMS?A߱ާ3f?,GoW!I[6к/u3:W5Y.֞@sekW3f_;fg *;XuX}l/[|ߛRd`ׂrpLMޏq|X7A.wr~ gΓ$ `LbE\,&?$d(7I0)q3 *{?=^Oj?=쿈]g`uLKBswps ;꿐ˬߩ o/N|}${}#K^[dp#e{ƽߙ,\ ~C0Z9j\=> s){{ =2ss~'=d~k@393ڐjqtvGTYAkη"C=h[7‹/>G-?UZ|UvZ~ObO$'dP}q lsrFQǼY46S|!V#F?di/\RW"8ZsOٛ܉7bD:X"uָ_+.]xxD7S>eq}Jcs"C~i~Ru)c $0t4PPRRJY$W eZ?%iӵw:>cB}TBjDKU/Zɱx\~YrT1&ob[/~k1,yΒw;=Bd B21߳a.FEjsV(aŰL3 zUu,SƳ`pG;n0ʵDm ְZ&3;2s`Rԧm7-V#r+wz=얽zoU%Ax*JbQ[t:TZ/m=#}aغ|N Fj*40"ͫ+ƐT8ӰDi.wmeݹ$NieJiE2齷ZN;7$P5'8g'nܰB4Ic1˶H?e ~G FR\Q&l#&Y4M.{ V^+̸ܰ9'GZ0@ӄk}B8l%eNltHJ]nhsi[)b)+ꙩE(ׇAh8&E@ݙB@xa'瑇RJI˟kRĞDrl٢[E0/`X#YٷkB\ɹF۴Ι+YZ^/1\,Lis℃d1OU=JEl_ܸP]vЙ!A:8OG?lO%  ~+NKĎM!sp;>+;F7ph{T=a} $c2˩Eޢ㉨Zh;Ӫ|~ !Mm!3oo'7_g䠃 +u%qa;*b6ct/?%`]1oh?gם&Ctp "Wl&c!{c Ea *-!zXJPӿu .$eF.m+O&pHCіꌍ7-5C<( Q#^X}S)*3π#kP/x!O I_^n`౽B/&W4md#$8;,$A׼me<ԏ-=}'Th{1zyZ\plN/w%'=o!C% Y.Y=N.x—hkNkMX$n']rżCl{j2+d^ R{[ԓ^<~7X-LaeE j9!JNҩKqPg_:B5~jyu}+*i`H~LPBELVN}ff/T6e쵊-~2.קr7chf sl" ,P0*iO}S<.`7*PX %H<&ٰSHLu]6'9,$̷t&J,=TPj(b xޱY85<%%:Mfw6U%}2HEC^>:F9L1t\sI -,LuQwX_i1s'c:}4((rFO@9DqOt/<(>XbB둤Q9T[߿i' ϕR1 {zy9pWJqpxn̬ yvO̠=2t#VAV`I޷!qSiF7)IeeW`+Oc{?`g.Ֆ$R-D!XX] +v6'w:6YɠB2]~ڀ71XqGfJ5Zxhɬ{_۸Dz+;7ǣ#7, _Fǧ0a?(g%@4uI1! ӼB,ž &d3 C͐2)2,w.ܸSC+(hʹ{  ;L)F8̺e1)VcɎehL}Ry޴q̣p՘AUCʖNs#$FEζYqa!o͸X֢߯\;wN9uN[wn|/p&ڤFv9D_v*۝Hº`wss@ 54{ #| ~=-'L61^QTk}`7+R}aζж~$LK'$yGϗ5C ({ስœW}uPH,JճQѩ6>]w*(McwzNNǗ@$I籚c)*(,GbkE(UF3XGqCQR{7Bb(*Bx#ςF!VRt=Y3[R چVe=j{buuYD§)TzBn{{ihTXK[Yҵ>\P_v(pL| ,td B}طnIKx,3D4>)V1, +^?õT4h);ɏVc(;/&+RfBX%`./W?&.S|)r}`|[a- WQ:Yu_ZܨxH͗ss=O&DQylyB5/RQ#U{%f~4/M>ϚO֪ZY_sD.2x*IkDnrW97-ۣ9ze ^z}p-qúfPd϶ n,&R$U 5.So\a{rPUu".1+BghM*p/so͐ T~-EPfW7Õp~ G1 &@p>$C#/YWGg83]SV:uFi3f,C挭';DBZrz΅|'xv}[i*r 4@I-G6X ea<yTV1A ޳da#B1`JcR2}1bs҅w?Q4(D4ڮ;`Ғӯ<6W8!<ž^.?-hvk{ XT*H_Nlu_L?{O F8a!`>p]b7T$Go\YzK<̱[[W7I=_TjN2-&o;HgLeIh{C˭}&SL@X[Wm0sBFԄvOWeK;S?FnUdЃ (`秛k/?̖R5S* 䱀{|[ k%{ꠞ Dl}PMɾet4f]EGMM~(e4 ՄapB-0)aZ!_wmP\ C>J#㙟Ob"4XV V> qY4g &7_goYl0|vcSqw!%m4RܔG4geLD6ʯc 4 uR)4$1"U$7 +j$O<)ʹ "2OH?$+vJhyos^4zOz̐=YuP[s S/2\uTG 6HaY~9(_{3&wܠN,)I"/s/Š&m:տ6>l֓ , )rvq= J#b}6Ũ?TjtߺОl4-gM] ^Ȝ%rޓ(QB OkXIrmFl"o#a zC*ǐj-ȈNsDempKpf3fB35:#w , Mѵ'͐Ts 0Ƚl9P$M5>6"YPί{"q7k*SbރT̵'ԻXM_8z%5hrSk4jVdgՙ;bU?-s T~{2e)]!¨K90="fyi@t]^\s9cR$Mj9[^ 'wP ynKԸR EjY .Cw&YHq[2r9wYg=='^5Ʊ-NM"Gy{ARDE䍉K*k_7b &}3ӄ 6ltʝ-.N!GP^śF3.al01Rқȯ =z8Tq="u`7leE\&1tͿ}c<݌.[:vI"{ R@Gu׀[[僺8K)Om\ggf~+R̀ؑݟE Vjn2}_! .JT#w6<=a[Z8HLnme0S'%Ё1M’'"L8!X4.G](,d4:i 1!M󍆌>`:6pI43R$ϢpV`? /n:P6ikFB$g}xm䥧" NddMsXwda#3T5\doɁDD]K#|檲 /ހі?6 !)fC%h~bw_=N^mx,H2֔kV׹];C&; <Ɩ^P1SF:[wt걶'N TɊv*B)i' ߇ At=CN7CW13O- N,@%rK{\'XԥKVEfؽ κ\0' " b4jsu pN}sn脃7wbX\BaQYTZvî"G"wݞIA:!ݶ؛6/p⦿vc?JiR}aB:qȫlQܼ`?4H< L-e*϶2Nأ` :RԽ1P{\ 3u:Y(%{l)xG9jvcEgm%h^w4`k8 Ul 9/ '}?`cs,ʩE@Ď*e|4ya$w"7+t8OΓT8?,>%!AGşNZw(v[K[Q?C(•+$D6~R } <Mccpcvf-v]HGSd}:`|H<7+&omD\ ]4 QhP,H절>(\<͌caY5$ /~VXAn `Doy^,̈́=}ƅlȥ)eRh~X%s*yL׌kcAb¤:EoR- Woq &JrIdTT7p .> *x|KX~TO-J vCVhj{&}X4[W3U iUM:ub!+)iJ 1InvQʶN˨'5.+~nJ 9@N7Uͦj ɲ>jsj[q<S&<ϤgGRk6kO. ˻5=+PӨ_$ƍMȡ80XYǘpשk>SN3ƻF\ _5^#_&"ւߍE6%J# uR+[G. K' ,wN'nh$-&Q@C̦™bk3-O)6Kܽ5*U|$33r&odv0R^9ǵ*0M=4˰$Hy]ZK%BxW_M zrG}I쉉*-0 L ւ 2R\[վ"2[Pi=n=@`tAAe62PUBVoHyGescte'`+Ut P[R R鋋" Pj^Lq~ $_MLċb5 3Iϫ#SE^(_S+I/%wSfjٓUԏr ۼ{ If& ֜dr(@MF1d\­>t^IK:[~|ٶH#M݂76.CKkSQ*sIMǁ)6-P`ymSwа.+!4tjst4Q%1G{uSeٲ"?U${#g  פJ|mXGFH6}A/Jg|2J;;̀MlSmvQM}m?fo #piT{եBp8qK ${/h3hvxWVL6"R 1$/ȅ;C?ŴUңbl-<g==6dF^r݋8֔eK͘tܭkӕ6N',:MK5k 2j/咽Vы :fͅ;{}x)(#01 ɮm2ڒy_vSeW1s>\l(#zփ$6^1 uI 0"Ea*Fδm-$ ք ]ͥKC`GYGͰk9#i= wڤ~2 ãE*d1ix0 , $"He)X9mU4#GWօvy _nĹeŴ wiB<6HE/{=/]oa ʫ:ژlE0ئb˄#fx99U+W Uf.eqꉩQ)㡾ϫ :SƉ8g_PAutDOu>Rj' _AB쐈ļyb%0r7-Ra Uᗪ֕BkP "&DXj!) xŀokdd 5Qu5te%y5Jp$wq㎆f X$ @1䕡]_*𑫫Ƶnl^[)ZMIMڍFd,bujqENkBq BICt+;BǕ Q~|_zdx J".0(QF\)9sey2=P$ZfsR us,܇-/DRe/3cٜ6V`+Zcnu|FadTlc׶0asѣ,cS1Emb(lpF :1®s'HΒ1σ9Ic(}6ƌ=qySQ0"Ȧ+M|q5%v(UxvZYEB-7;LxMpV-Yvff+ !@<0%AWxi;3Uiw[I" b2& S˪Ր<܎48Gq+nK}K+,&,ܸf":y'kOkagR'߾u!b@Xa;yMcbrqgL*T"MlQZ#~7N@FFUXqbS쳽d/S.%TO.x)pgW-uQ` զ~IN#W"P93egKg2q)${FfePU?$ҏI(75N1(Nk{ q+Љ/x MÛ hc$k*g"7((P2Z.ħ[ b#[e&灸NׁՒ`.SB&6տL8! quS rBsz}hhkw7Jj?bB/>F Bu |*g;?#\ደCx[<HG@[EWXzKzK$"[H>+ YmBn/ǜwMj֖BP]hi.O14P&ӴҎv7O=m=m%VYs 1lHNU)4_J:ڛ?;R܉/60@ek`T:G8ܙ?? C&_UH ?<7aP;RLЊ_7-uD3\̴ sG]; c>dFd ]>raJ,(W"5h7Bf*'uPt <&s\wóN$> stream xڍt4l߾Y{ZAg B$D{kVmJm5ZJmRlQj5J)_:}?NIr_od30P# 8J((,PU EE99M(/ "2PEB@(4B upo( J%e""25 A!^$_#(--ABAp.qGgtG(r.( KtVBQ.#~ C&H 0qz&N(_@0#v!H:;X[6m3Pw??A῜Aw w8Aa ? A0/@h_ʆ?y9"(/A/(gB?àǬ"!pԠH#zB. urN?{{¡m?6h?3@<?G L= HOCPnu@> '!CQ3Nh$`- ?[8?濮XHRCʈO**?@@@DZBHJS?Nzуf?"!<C pG6Ž/Y\2UW ?< c7 2{wu!`(zΰ ҀAPoM  ?_PX89_/,Q;:h" 'D_3$7 %d BHŸw D?cBHU??߸00Z(tο() C D{NH!οH87pt}vV+6*s^3\KtY1!dhV6Y;E~%KyG6yr25|A;IVK"S U&"^ 虱O(ߎTȼC7X^X<ɖqh}jr~%NOl~QTQA5Chʆfh..٪/\Ժ4dh_.moB[U; +nnϱXw0I5pݬxTT>,}KX6}|{:rO\od.Al1-2Bd :9P/f)tw-m@t 㢳/s>}Sy`2ش}ջA~&N2f8F-/)vz[ǽ/K3,gCb#1 GZe4lǬg\4;(_,{kS(g9#v8Nk)<:5"/vmf߿Q1EZOh=l0} U:2:RY{}].uz"dm@Yz&cG`4zkUYFv7gun!q\GDsN>-+D(\o'7GW%Kb5^W:A͞Lu?:(|;e& jO)3-by4y1fD=-l:E^$YBdkF#o6dI%5eTTeQuvy=E j'>c] W[?bx/'hʠ8Zz0K'mR=k X9HVꗷKYc}Ąk.m}c( qhpaH^D`{]oCwpWEp0J&* =V|r>t^R#Oꄧ^6d/Mʭ_ow0,l!UEj:,? UTc;;W98sjԧ.1""-zwK`c6 xz:qFYg9pXpx/MM\2>y5xVJ sjY/\,n]V|oCJ0֧8$Ex6YwEO6WR,fY)@Bj\&hCs(~Dت\%p<~Cifͪ@=~*e왔TY.r7u;|b*GLb jq(sE,onψf/ZW L41{\Ÿe6HR+\ ϐ22ϯNV=og h$7QE]G闞=?` 2t5O=w'Gvůq$7?eڢwRhX;uȪ Ͷ&+E#wUR"_82Q[d1$.pEwh}}F &"-QsTܠ_jU͙D; )l, KvšYU~.5 |+ l+&5#]j߭\m[ j17z oMz`2VLEvI]9 ;`WpR/"&qj–-sñnZ;/9?>Q~(156^⹽캂v[zqs3ۓBUclO6il.F--d6=X(9vp-9U*-<\e֕HOmD)K艹hx`l[T3lPaz:8#H3c~Zς [W8'>򘄨v|ɜtc/~ Jxkd:ß<-*!-oЋQF}d ԍɊyle1$GU"/նPX,1r|Ḭ$bz;h%ሄtU|Pɫ؈,CiP>EH1f8iUl}zq>.%g Vk̙7G~сlrV'dAÀS༡:Ή*6*лz̤vrLH[ 'Դ?(q&l9F̷CiZͅpȆ]5(j%ѽ\]vaΚA7o]#>5rw7D~4d> ||:5Nli&1q.~lo2uZa$Z!{4P7nw2dhR[lـhna ^m&`/40D] Ң>[;T룃cB2Æb54_cshsa`9X5[N`y5Ê9kUtC7U7>~:+[=E-վ0;;/GC58g&wu7SnU?}<0οDT:c.uY:o2xh|͔d)hdJT h{Eun-{Dї4;6@ijz^kF1o 4?cz8S*%G1gWtUZϭm:ThX*]sd 4{T}XsЦ"Ybzvž-B[{zgVz<)Lc'sRi\GMu|MiNmåN,=^c<[F"˽ 5"8y L2q !۳_[0xxVNRRwm \*ǁTo=C{בT{t> %RnuY ΎzR io 0j&ޏڊ!I!m%)U5~x'&-gEv1Qݮǹ%p}bիIE􊐲עHr9NYPIҘZ>9!WPR6YA6Sd#WySR5O?=-y33&' T@.(vxz϶r&N} ۜmOTRA{arRa!iS{b<}./{G[\MoN,.^xp+N Ga*zd|:/H>-GLԖ8_?~w,<${-i=6{綱uʚs>1.LSқ/k׳%NT-Oo`%5Zg{)u-.֚aݜbIǯ9J2%(d8-t8;,hR֋7.jjb4L Jb-;eJ16{m.>'\(ZSRþ5=&K?NK'mg5nkN0,Q7oSS0.!hrC Hn$_U/sqk!/ɻYmsXcV ~yI~Mt@#)./c[*.|N.G {!I]{P.l|YŢ+@y~Cؗ (^MXh'9k`nYkӹZb*i6j[Lz YVUYƭU/$>3NʫzqSEA؏$׷!+k^,^%k r|yKlO1.$֓E?rU?*o]w\/m)K7(`~|J? ~Ba0a7S,!QH{{s7mOp~u2*jLCfs@쇌77%ZHic8[+g_PU c Cp1yZ.?3ľݰX{K4@Atxp)\{'qS:}9&.T x`μ{(vtKaT;$c7zB^`Ds|Mh<$dnJ'o/?&=rfh,~P-=[4ʶq o_$Wuª=m|i1`W}r ڽ~#y~8vRܷA6-N"̆fu-NqQrI"1;'лd7D8()3f8y1,3Ʉ"_yn~J H2 ZHwðRrcyvB>d󘼴bk=:Oמy ;B9{O[{buxMK-G@<.F7xov6n8ׁE&tGTwNj[EUx=[a>_' aE ˏUJ~[\ YVF9>&`ښ.I 4$)~,BB߲Hゔɉ{`ٜLՒ9T n:މW `dЕfݰA(sՙVJ(=;c󄚅3j"~M׈f7ko;Ut~ ]I>49M;9YGLE~f7;Hgz$o.]/n9֊ĹubuvTfڥ2Z x鞊q5H3%$:v#lb GCS&@وhDFAD endstream endobj 248 0 obj << /Length1 1786 /Length2 11545 /Length3 0 /Length 12689 /Filter /FlateDecode >> stream xڍPk.Lp4H >8 2w'8wn=!䜳{kfi{oɕUE& I= SPa@6& Z b Zl"7Y[ <"xƮVf&,L-vp#֔/s` ٽD45M@rAo 823193,ܬ 3d]2@OiL5K+`s"2;؛/2%d /ccSSPgC~m/ƮV&/R7HTO}ΦNVg&g+52vrfb`;;=w~VN ӗs`6`7{!s+{3e80[9dἈ,@rM-Ppd-~0)cezAr6v N. T7BfaYB& +{?_ Kc2af`{[?Z,"OV^lFV  zyo?V2`og}9!tv~]Ϥ9/_,ߘH/=߄@^@ K 3+@_AeYؙ˭%AfVS˿o)~_1/V@^q~ͿU/+1e; {Sc;9{ 4qX^ tK>sFs%~B\,f? q;#n Yzb0Alf?q5xZFAl\_U?h_[jʋTCI6lZxªojey~,pJ)r}b7p׍ l#\9| yPp7`}`8KY}'5xǙ9}6 aO'n kZ[5}w$2(2Lpi=m߫@ ZlPv +g.WE3,Cߗ! yN$`EO O#K+.Hh? *8*k\ Qs+vINp&>چ9 udqR@-㺼NV8eOPb֦ο\k[>PǚmB4GF?H}psJf8l[ Pȳ5`U&0IjNE1ohJgUQ7f9hsNwǍ\$:7&6տk=_N>שvy4ٿj D@z@6Ldc2nZq\~Uל@ZmgifcYU-\yil4F~j&>̂6G7򔞸8~Q&/S7ēWo}(V]UztmI0kp&lu'5f_^$y6ydxD|"Y>aoxv*{oeu|1axޥso1dϟu|>,%V}'+r1/2;aKa[U$s.̩zR7A4=COܲD+tR|OFw|tcixR D=ς^L k 8, @d iM9oOgKMkQ` *EnyYuOslFON eL?^k3BRk*X=~B"rBXmW>i9ě"1I5aJB M9m G~p`ˋIh{P,"<4t*Na>ni>sj%lr4o=:pi BB }/$#e7֩ `cP E9"o(`~m_({zŅlpޖH[Ǟ^L&ZȈe5{0Ŧpi]a :m3؈T@Hv0cgUg(Z+"v"W?2a:(v|J:ۯ?I'*~ͩ_!pbvtZ2@ҩ~R/$v$}3q)`W9ƺҿ{p߭`UfUU [6kС^80v漧ݖe쓇 ;@8#McF|EoT&<|ehZj{ -[CLe8BB@i\@%Q )mEf kaKv!Ka8W~JqE/ژ@A:V+$n[ag7RL!J7!:'ے8j+_Q,;'5|ӳ7a2|C #qjrN&QL~l*SrS5a썃lUu.|m|&ܵC |^İH.&&JA@ԜRrWOOck13hb'g0#8/O6R4{BUDFY<`=aDc*# Ϯ귄=7|!Sj&[];]:X:ˏ 7F !$q_4À%ⅫےNY 6 yshI+@{K|7߆>if3lTt6r6ˎZ|sn1Ltng- [$rROյ1)wAz3:j٫ 18g׮Ȗ+',hԜ1L%μCD|ҬUuB] u8;OPʅ7 FK7fBxĕG]u$pD/0GRX# ?yg{LU8ۀ[K)M;H3|~/aIr j,V< ۝|_sK'V3C~]qrIYĴލb܉ P]!:ħʠo挿t¸"D"U퍡Ok0H=%R7' քYv ݭj"4Q[˓*1~X(r_\qfu;yfV(tuu3;7X1tsplýGRB`(8P?A v"8u06`@#\ˣGJLIh8Q v-\}ϵ;/׎>E}tSL(qC>cF; uqqdiq+ڪZjڕ ei VTFSߚpK6rIikGevXqHD,B(Ej[pf Y1݌ܫXu2J9ɴue_JSe%IXRn~Db)> ȭ> I}#ȠgwңbE]bvw`:VTHm(ALT;8ߡI^ۿgSNg Zl!'MNC-p3*;Am4+{ O%1O@j?Xvl$INt-a?ciɲM\ g8 mӊ'[rP78l!$ǯ5oyy:,K5f"S~ j[K`Dqe1Ev9B?Uo)6m(Ws.UseQ/`q|%M d<$>KZۗ:Փ՜F'p ΍ά@]E#`I8 A{=m3Jjor y;?O-VjϓKɁ&*j6bcQjXo:CIi *D>{q4{rSn.d2)E):_m.r [DGJP6= 0 F}^ĩj--,cWs4TM2>)_sV)VaԐP_-,mk5Ƀ{dI~=(ތ5A jX9'XXЙD!\R :c9Q]-4j\ܾ~q]ɽdMdu-E=y&xސ(wӉ@miMg~67!餛OddK<Å+f0~4}8ɷ2 V綗TP>p9 M Q uk55M%3v&%w*X?cnZr+,p OK"1+!xvs؏r]`~:;UtZ~tZ:8OԎoOl[4ʛ FB!d ?靨*r{k_.F3bB=jODKERJ@./rL1mVB "b_-BiH$&*\)-w_1 O#M rYy0qWο@gCMn9 ׂ>(WH9荄H*m?͍[l8t/C-'ɾU^L}*DrqH,`j:hc ! CBĽfSV}.wڣ6v*evzb&XWl1z}!S&faAl&vI6Ӡ(/ .k8E0m"d# w}N" Kʧ|;oKHq: \epWRy'ceh":[SNw[#@G>s\X*mZoXJ,dz1{cnO Ig L SW2yrS& lo?U7-?L}e/i9hnIpB2RgW[ⷆDX>O 3LH}US6rK|`%aSX6)q 1 D%ҿ^h:T1A?UcEP%y7`5\}]O~Bi$2 _esջmhH*Tzjw}@^>=6?T{T p=`I$<5:;~v*\*"bղ(e/ӥBنOxcGw:6#3_='3SnN=RUkr0ީ~Jf}XKs uQ8K ej56H sn-Id((=MFk!y uP]~T cԁ~1j]$O@l!թI =s,_bBϷ@zhUr gE!~]_3&QU&)w*"<."F1*vm\͊u/}Z<]*PDI ޿Z- '|UMfx 4tG.ގ0Bw (#} Is_;tVλp)!ND?pƿRiɅMq_}kX?叁YgBDW!P 1Ly!Wbi-O|o !˪`A&,,G."7륜ت˹Dũ<l龺 P[ITazhu01PcM0C' AZ]P۞$EX2XltaVӒKn԰OP׽d-6OP BU'AUc]Q@M=2|đe0WF,<*Β )Q?X_|{~{@{F4ثWV9Sᑺݷt.2.U2{ւMBl ں8)(<&߰B/'߅6:;=1sRӳc ^@q2L%5agqB!4rB7p zӸIB.?W´Qs]ttW1Q;4d_Vˈ(9|#~*`SʶfR !q' 4N;=8JeͲIc4kn]PY )N k%Yrt!""zds!B(X'_zvsyIg%׏C&B21?{DѡCK MЩ2/C+ .+Wȯ"~Мq^߁,|ׄlwA`ԩ 5z8wFIRx>ww;&i߸+I{xN,ǐ5u9-ȅ$8c_%bɻkJ9eqG.*oϬ*Yt+Pku8Y?oj.hl>/x3_"1zp&TZ2J;>)N; -REy~o8ZG L%E5毪v0_2Vj!_4Eɯ-h|d}[rpGKJXйbޞ_hsΨX83z$1jbŕβ¤b*7ћSn<feDRB@lR^@XRb*Q_Tyzf-vH`A6*'XPeۥ>ޛwf)~=a7_ /&-4_5e{B>^Jhaæ~]#H9IOiFkT [#lj11̮PV{GDr7 .{ "95tqs-}nD.$$,RaD@CHxu7x&6/+ IoBZKRRJbdloWϷ(DE8;~ldM=1ӰILb}>oglv*K57ljrpK=9jyz:٥?v"Ucin@ق A(P\|_BTnČ~%IaZ'KB ^({h$y@E̅(UqdtdSot-VW="C-3_3q+X[0uH. "fXĬn6SQ;L.cOS>\R_<+_S瀭Ғ޲%̽r-=ٌqg@5g8s`Oأ($/=TϘXx-S ֿ+KIgn&&~ɧyN@>`D)'0/.Q*AiO9\eŞ;:N,zڈ>Fis "C ]= ǜ |)jYb1q8'k-FXRGWtUG2KEE를l3 '2$RA5j#3͑^wQ2!8"c "T,x- ;TJ}@+@Z{.ճ$sςj !$a)9,'AwIdH`*) 勦%61Ýk#~v|O[䏶ϣclßVU. =#Ig?E'|Wa#yK|(˺bO%-$'W2BYy{i}1M AޘZt}a8$S:Z嘿Cde֤Bx9S #RSy.x*#5O>5ӎӹhl͞0s*UcM"sKz[t_JgB*wppA-JK{kX Bƈ:8;{*V,֖I6"eB؏ZZnAor7˙V Tʏ7ş]~z+)d}Dl]_f_ZK VmVl#z)g}wL3*cWH@tg"GiGJvj.xIW|jxRC>|y+(xs+ږEHD@XV>Exmp0 E>YOv&na*ik+bE=usԠ)m>ڊ|a/l)`z'r : 6^329*I]<5} ̴lw .Wa0*h}GKR"r}qktRE1iVg>[Pc "| ];.![(3fX-hJzQEXRp,~rB"(RlBԛbsE7K(N!ױQRT!9Fk~p< F B boDp$eDLLmNW9gK)Ғ@QsUIt ԷА'^dd zdC@d8KR.S GNUڢDzXۆ1;@ dkQXrLA Zќ&`Tܰ0ۿ9 . T}PeCiHDgH5cZbB*u/gu֔#Wd)=`["^<-nC~)UHl7u/Ja$#J] kOԒcՆ)wpSb=p!f'~Ֆ4Z!? kG2 *:OA"@I, @RqH!H~zs}ޕlQ xnCl ۆÛ8VdvTx/JeO.X5}brug@Nî~=՗o[5Ȏk=:qW&"znu~ESjOr*ǓݢXrHD2bK߮^i&6˼b)\ ]M/ju%IkWNf?$[lT[}yc ꡝkRw,J o[-aO,P}[Ff"/;IǬ.3:W5B((ȣ)?uf>L.N6OuGLpͥWkY!:ǗAo<*-|]5r]BuT:*KkaHC΢W~N[_2ݲx˧h.%~AoݺΩ`賅(_(?:c!lub><8X:2#+<aKuȃc…BE1KO{DH Y|I!"I'r☙A:vjטfP_:V)Ե(p,D$j,h':$ /)ǞGBPlRΨ޾I{Q?<VP?XcvskNlxn~l",t]v!GJ˒hrX]2#w}ˋ:і5V~xИgM;2e;?՛{-iJ;YD8o<!]f)]$mr:MW_[!Ulb;)3;gN׋L&:m"yyu@U,w;TS @G:^ӽ0#y[ n?yrҊOg6[|Ӹঋ-W0`?7c΁wU n_ȹfEGpFòKMB&b8ka؂38YQj IOD`J|ݫ]޾>=( [ym*TзN{9v{Y$Ln|mF{w"gJװ9sLݹ:m^(~ ]ϋޫZNZFɐ:Js̖& A endstream endobj 250 0 obj << /Length1 1385 /Length2 6006 /Length3 0 /Length 6956 /Filter /FlateDecode >> stream xڍtT.)*%9t Hw CC ݩ " 4!] !8޵]70ȁ6e8 (hi @A^ PpuC=p(C@O@03_/"/*@E a|;:_v[(t j @ D[3n |Q]pxe8P@qh\ &g:@= vo;r8Cm!0T' qit\!?`?n߻_ [[+ &/ g8*:lPߝrzjyغC]P_#*e%X!<uآݗf`po_ gyBBP.!0PLTP  >|B~Q]v! P; =!;O "6{( ?Qn|w?7Kp˧ng>AQ0EW!q(%UtAп]E]ӿ:K6Z?$ mQoN1W!eOga# r:H@ @ 쿡&?Ղ.UCPB٣/ z(C} `](e~I =-, b(}:(^ hyև3x p]JOS _jUWr-|0W茇Ay˞&i }CGF$nha<%h6.tx6{V6ur x~|NtXXBC KD%OƤE`njEB7ϖ:H8vI X ?/F~)x/˒UB;wwN sPGsUQQ mcӾQ ݾlSjAi)?`c2 5=?e%(먂Qetu=URi] 胉ѴXGMaZz@9s .ܢN9X欤Cn]Ϧ?T0NzTbu& :I煙Q*~=_O5dBƫV9 &cp-f ;S5}),O=h:$qp|VB 1W}gqM!||Kg33?nH_B1o9?PTi2:WZ#1)[9>9JJKnX):DŋNV!/i}#x:o\ S`n1?8-ׂL JT+[xF6 6J/)ƱT:h((S) 3)!ɂ{|2aJ =Jl.r`WK}E]dGRX}1u|h 9T]JSNv6gV[WNgK03ױGssޏ b [ 9_ƨ2׭ ε~jF~E2>8I~ˀsܰ)aalWeAz0}2#czo5K6]?8tp[aJ;HѺJ<3 {Q2F AtmLx} nt2!YLd%bӘVv{hm8ku&/^?I{YTD;m0fQ0>):nF;'oAыL4t,=:?&ysY\Vjڂ)ccf@W#/g:2}lʭMRص(\ wCDD.[^}QFR{Жҩ[ a},T4?;9EY]ŝ=h _jSJγ:o8֫Jf 0 ʦwV#(_ut/ !jI#ќ _U"RpMNWJL,+p?9r\Φ\hg(+1Fܳ`sm,?j ֗ӣk7GY!K? NLm-tgladX{J>0|:8ٰfXlk&?xIPs#ÿRNZ[6_)nѠ]1he50\d"QN 7wWP!͢+jT sULPmkq^_Lgh"*.;o#wמU0 qM]כ=YJŵg^#B\s}ChsOŻׂ.*kiP+eNUN=] PJӈfCrZB`AzB~swia2JYs'~yx-5aT{`0s}dX$֢kpWfYe5nPPrA49*xDX(5 4Pi˜I[fK(-8wo., 2,.@* "w/uUMMNޜڈ(}{e{7ƶaA"SB᯾Vy 18+J `ǫ5(ܐl0GJ0]Euj! %L6oV'LDFf5mi R퇱fXo=kEzBkΠu2rgF2scLjALXHMSP`dkD‘0} UXNdtc|MXAP1t UԘh>b(o_XI%eڭC)hrHH &͐BstTF[a˷\Ӥ!1A!Tmfx)\ovMl[I1žL Č0lf H3}+̲%N⛨3? RNab9E 6?j4Nj~ζ FwT9Ϗ ޫ<*χ1 T0G̬U^(%4Z04F-|DӬFn L 'X&lHsɯaN4Y~hRBfC@TljYMY`2Hu <[PO*׿΋Ӣyq~:6#%2(#R.A6V3#^NF>k\ٚ]):mDD|qi3닛qʉ<T3i&7mI}7U)T0h\Nif~7VXL6g[Qt߇| 5qJjhXVϞYNks^oM7z7f@cSe o㫖ƾuWJZuxpo+<"c#͋@R^m^O=Ӆ|oNHu<̗.Gmv"k2\MuA؜njIqst4ɦVƧ8I&o2~n'pO~{:<ƕsXSMC d=Iky;"g݁?Re&1pe"1R =<@G+Qj"M'ku܆ ̀S3i;ު'HŔbyCГﲢ $1aӄ>fho*1 h^[wDx1 .U3v^&٬,N|TxmH0\;}hE=akgj&fcw8xTR~ĜbLm:sT_Θd"ER)+vc[ﰚgϫ9xTn0x 3{LEq̸+narRf<nKIMeܕ_I80AA u;ij塵/\涠 #iN'pJMAjH{ڑmWN|vA+v6~7c)5b]غ!nʶ:K '!_(ʹn{sԒɈ:P̸(y@/2dsޔC25AT@e~('6 }4Aq)>xIuYyS%D٬ԍa?JY|rȸ}N&jTQN nߍZ}.˷i709PJ2@t}Dӱ4|յ?vrdx~!*4dH^o:\74FnUoq,^'OWT=}VN(`*A!}6#ДE47bg NXߪC\9&]-d S@q.;FZC^h?gsv/|,6[uٕ B5c6F&9Y=ɽx  bi[xA|pNw3)*tPk+9xf>bClS_kn4= ^RL_@D7'S'Q'x`@yrIĤyzCc}A޼/"ӊ2Gl)E <k'(Em_$.bUU R5GXgkC\}TsITVߦCibr[+P~\sSw̬ cL[M}nI.qtjY{luπ/^]U<z-m>I\o<\OuڰN, i{>bKaʧ?pٰ/)8+ >$DFU(X"K gӲl=굮fo1nH8w|W wc Z"aA7vGb>?||*5f=(tnU:GfaTR ^8s ŠZ6ǽÎMp4ī>Yf:]06Fk!/PI}t}ғ}$'ꇅ/^5l煲s[Gqx7>5ʟҭ{=5>\!7_2mGN߻"(1)/ N _)O;\Y\eRZȢTmA."}=5%fILbDf J"ydb0~3MIS s897*)taV,Jן]|bDmsH=-b_euNn W]24YMh]H/aGt7|igl,ZS0Ƚ;n@' 4 m~"1A6+s'MOda_f1мf^JJ}8םIBYw2=-8U͠A%5&hD3,M0Ґ;Lz endstream endobj 252 0 obj << /Length1 1546 /Length2 8420 /Length3 0 /Length 9447 /Filter /FlateDecode >> stream xڍT[6L "!))Hwtw 1 ) JHHwׇzsZ߷fgu׾7%1Hedeb)(pXXؙXXP()Pk_bJM#/1$Bl!Y'k+;C[>8l P`B@(bvn`s 59hLh "6  PB-@6O7j&`BX@v|...L@G&[sAZ jP9A_6?1P-jfP$ ONSr<@c,ǀWoLW 03qCf`k@IR e! ֎O@g hd;s @RD|*MvPG&GyT:O2yjZAl] 30WNvHF/'?2s@&̿«ف~+Y*򰳵=P< o#VV) 0!(D;],Oc}-eVSVS:QQ[W#+ ~:xwe ,XqXYdԦdhZZS}b-@X8YL>T_Qo$߄$i~?j /':A@i k SjeE?( v*&(Gkլ#?2zz?xGt|Z61 u<$ & tp< q СF$Bj5s.T8Eܲퟫy5TMgԙk6Q?>&* _ĸT\X! u8zŔ @\A,tM0՝-HEٌt-KPG…af2ҷqP[}${F85H8^މt+ quO):@c ,,[$YP%HI?l&!վ6innoUaM_ yᇊYM P |6 a QPkyf˫@,TyrF/}W;X^_D }oLcQ' rJ!ł2yk_'PQv|x1^\J]o|Z\#e`RX/O^G7#ueu /8سg67jTrWhۄtIc2LT~[.Ё*+2K8hVpU*۲oӲdeFGwlnwfm9'4y~üțwZwNy+.U>R=l;_1Ʋy/k d6 Exԣ8^ ,a?GXӼvyhhе\I)QTjNyDef}JsB1.BtN.OBFs]!;4A~esǽC4[4d>-瑺%Dz ZˤI툻il2PSh8-Ҝ2tR;G^g8S-n1b -}Xְ4Ż0{fJƃ e[AڦTOiWu::0%VA9b&2 vAo[;)wf{+r4 I[G_߇(tSU׿5tMS?u%eJ q7j V[yAc9$) G\A"DuL\Hϵ 2],[J:o>?Pto]r0)y2vJ'R&s1Y^JJ] C=8Ŵhs>$ޜr%;{pMڗQ!P^:a4$b=m]:l6n{zNJƂؠĖ Il-:SH14k&!e |jۮb[Zuy2d X9MZrqE]%Z| \ŀC((R#+6q^IαJ"+~߃; W7WK/# #CKw0@kax4F@!o;Vi{CW̓}pE:D؀Dž'pg"KmP˽ eIؕ2Dmqv9]i; ,+1j %3Un&SyxOX ۯ"OiY)j?i%dH'>S~;T 52!3]]6+=%W 4}jn "xA~ {!+QX]';6|%p,)b<E !xڏ=ehWmq=*9a}UBz+?=6jH|Z|a|71xfnԢm\Ж);+:!5㷍p1x9k?1[hyrH&Q\  &7uއR`E/0.^-lasV\VM }uwz)0ܯ)^ÉKdSt{1*'G[7JMO?哜-sqvm~(F-h8B˜U8o |8>'i4uDZyʏc?~0l ؂%4uqY@v{4Q0k, q.˻9js׊}q:zb3h@g$>,=e#gT~Az{'+~L[e^;G @ۻ#vɜaxx.fՋ&F=YNG AA%Mc)kJIF4P_vzTų_T9L@R`D]:i`HV}=$J0T5>"U<)fsڿ?/ňHGF 7pó) :a h,Hi$&YchbOvLs >ܬ,fK*'*xnbQZx?к֨Bk|eԉ0%G}dAç?#k@o4ƭ(_\g-Y$}ߵ>j)rT䡀*Ug"~A/{{?G5 %ܜ-Dn$#H ar>^LW$C q?Y0vgxK ®+?)Sq%Yۋ' ψkPVnDy _tO 4}Hh,jN5KD}\rFYAPQj&)ag9}7l5Z-Yhi/)1=I&mcWQ ->/[TGX$w.}$<(V_m 8[YPuBlx/jq*8yFX$^%k[~\7}f6d8u~ٚd/f<3f=K40*+_{c D&֝HKzVh-dF ӆPf)3]eRqUuJ҇ Lՙ3ކ9*#VϦh5^q:mJ܀54n]7Ucļ@ބF)QrkǞ&[:0ױo ߊT$N[>0Vjז?d#|NdQ'dU',1u*@S]!;Xz&W-sL6c ]{F6}Uf[mQ2x+ha'6k.>|y;UT%gfv"f^s3tm]qfvY 8?5ojIM`'fF`09%!+} <^ 3 JPUS{3;mRv׹0%<ݓeJ)0/drmXy6-lWKhnf3vԮf 4̓=|\ԀO+浽K~f#?މ#D&"5-/Cg\瘨)M*|$8?YfĿ"ѿ9 о|VZWcQIn]PvWJGcqT$OK ]xD} FI/I$dcX:)QQ+;ho-c);!F?Com?dI‰)LhA PD ćB2*b8jS(~0?B*Zᘲ(64ot98߽v`Q6d8_+@۴-_CrffXB(1b䣗&h'ic;hX3"Є?s119Ҏr`ۺ(q99ˆ5W]Q(W|AK3UsB:idGt^B(W(Yz>z(!^̱?ċ^{ucL@+L&<@ ɛgHD`@pwe@C5`2ʊ(j.t_>b[7ۡ8;T>+7f5z2\r@w"U12ʉ}¯m^qM*{9*`Nb@Kw;֓D9ҧnN&yiGAa"V^TBБO4U=uvckUa{^\13vf>.XzvJ<K;Cu{$$W|xșmL>A!wj[RV 7cVԐL > _bQLgn2Wn߮3Rsre@kץDE\?0{8w鸜)r䰓($'B kI#Jom|3W|/N(}[A_Ƣ7vOL;z `47ZF&%q{"5FRYuC=UĆ;3,eݟʽ F<~v7].]:6t:.$"?䳚Zꚧ*\L~: ejh<6+5EN/^eg򅪁]Acn'х b寉 5&XNh/ؔTƀg&jIEu׶G^1vpXv;v=3- آƂ1:NӶ 2V=qS i0>Ƣ)QQN,KUꁇUd/ (d=2ˆS'e)05.DlDm[?2r?sU )%|Ŋ쒾imjzsDGT6}`p(SZU3[?YD4%s̅s: :wjqzw96;KFJ3V!9m2i:FR=cd,L!6򖺣 M縄dN!+"nCw-~zۉ I5Nwn*| ;HȰ'yS*.<1}^aLZ]9}3l\ s%z2Jjcr9Q4/&'OGot^uﮃq}z-Cg5p[JmGΟ`^6EӴ32fٖarӱdF.>Hr3HY4 ?ׄ I&G{|Zz`HIZ@1#rXX|%e+դTl"}Q\9wsY$󍾗6m> X*%n ,goDy8GkT.8zd{08A pS\anL+V)tw,>"ST8>ek*B6 J9Ydp ,zoa5g;T6ܼ>qDeNC-jڿ-P%lcX܆:pV Q_`vz>Q3];3(^@"Z/>' ƈ ErFF%܈l׷68_K!K5>L * /ծXg~Kr=֖^)ITed\ dl ꡻ɔ?4,kY!bATюQ)-Rw旅LzyWL^}ܝWK$Oii}rh[Dɠ~RR% )ll$DC$ " HFXPhsVÂ5 ^2 UkhDE <Rvx%,fm6ڦm1cg]0JB'>B.2_ pxXin) RET}2z6aճ~/kpQhs#CmLtpl+@}Yrʙ>Rb*67*O=1Pȹȡ4mGo5)ɲtBPX75oż]<'韓tɎ3N%W38_!r'|Vo&ZSt^ɕ/WU|inV`<˴WsFbԧ~.sX멠=@ 9@/Ux|<ӏ)^uS4 \[0'Sk rXY}ߐ51" .Ѩ֗dj& r+|gPgmD ex r-elFefo Q=)Ra^V Vm{M{(TKOT x1 6 KGNF hYM$BOж;e ?3*Ўx dA֡Mu۾S_r-o#,gt s>޺ڟ f\I/:jCZ02 ك [o'LfJˬrU|g`J[0G z9w2 ǫHTOVY)ަwcGJQH~atj>"[J1qּZg \JvL]C/hyuF|7NIa!~4z&-7F aśT"ؐ7EyYY>&0 K9BbZu5r9:媷'7VnHq!2H(jnwFYæ66OlR>& ^OZ[Hg:Q'5fxguj<nۼijt2#bu@խ "A^Su_žuj<`]X'po7oN#(&I=N /eq1`]+)|k݆܍oG'g!Y4p FG&|ZE11A"(T3N=zX7yxLwmu8ąuU 1J7j:sIh'QHYj5bpGa*Z6.f9o;44t> stream xڌP] l݂l\C ]k {{p9ޛ+`ݣm;u&1 G3 `e`feeGҰ#F8:a 4e @`ggeх incPb;:]$\lA0}Кx>ؘ:LA@{pDsS; / ? +0#d P]܁(Ɍ am\av6@W 7 .Pq:c#?1NæN^6VK; @EZ b:Xehj>onjcgj6)@ZL` N?鹚8\]mJ/7*K9XH8@qOg;8z8X8XXPN?&`obee@Oskkx9V%g'  7ϟ#D669`q@,Zw賂g e`ꪩh3t⎞&NV;+!?;S㬜#2?A/eG܀}߄m/!i7;մԦ6v^1J5pV hafr S"9X66@w6 s_[fg|j׵`e|uGo9)`h׊sqL]\LM#.x-1>ttA\D no`x,E"Xd~#vo`8,o(F`.ʿ/˻E7sQ\#0E7s\#0Eli-~#033S@{[???صoknbfoin\vq/CE_sb3l`J3u8pq-C/hO0 8Y%/sG7? `qgd t,#>+8M? S2`2. |\`oC.o~`R]:V9_ NH=XN@Se6 1fZ+,oſ#?Zo\]6Fl4 sqs ~],^ ?}ty1Ӟ@{? .޿Ɂ=y] ߯JzBlBk=vDŽvS|]Q| Zw<܃-E{#Ds\&%Qqn+x~b"& =gg_͐Tn1=d<-Us+ =M1hFPeÁ1.zVhvSC`LR$ ,x6 001gTۨE94ֺ,v~`$֖6b`WGaj9:,Wn-mSfPt}~;` Kin],/BdF/e̟A[a1.}5  )HUʪ 9Btƕ3֯Bcc}05[լ3ߚC$36/CcZ@a&bYԋT1ak eL|pA_Vf'U(у!>[rq#CGJM j9]*i2bQP_g{(N5jk=nv}y`,)ZTW8 ]4\,ů x^׮rO K Ma>ܨ@P]>{w~jt6]A1g_@+: .l~; j]6:2iMC~6cf~24#N񦝃KxDPXJXĀ:m%H$TjPu#Z.dХ I.)y09gS&Oa0=Ǧj.)l~QV?;zYeNz<Ķ, P]\O5wRyd!L4/boa$ AeԽ>L PUvNc{lm:Eu;?o`C_H/ ZZK):p_zP2OTgxߗ $Ў<=Y+?`PS٠gamtQ+6jφUVگQ.?K\OdͲkz'ŞO%F.Ȳ'XsƅY&-V~e'P eAA.> ""Gm1OvXL僂1t6 Q|;׎+w@ynQ)(^T8% B'i7/mJJ2zϫ-0{䅫0 ZqD~Zt`Vԇm׊0pp[ce1+Lx|3ъ@VͭFxzΘD:) 秐h;;'cQK\nw59Xzl$e;1qJ fNa>e#8ZZ ymӨ(U**6ms$'aV9BB yfR;ch̦*cVɚfgl>?r֌G FO]-b3PT)f{Ƣ_ E+KvD)Q)ڼP'-Xn:q{A#I4\ * -Tam.z^wwfq B{ib7+5Pb`8`M#;-&[4|ټ bs,Bvg,P_`7Hb0J ϔxD#uHid$; K/aī,Z!b8@s4}يϘ#eqIpa:Wjx}!ݛ~S]g_[rQ݂nk1iHMiٷ4u zco7@T;ə]%t<}OcYȵ43˦=4z|YOcq0v -O,Xc"AGAa}}ZÑ?Ωbu!ifdsSֹJ^>g5[*L{3X=WziBw]o.3D}$$H|pᙵ?};9'cu@0s r}jA4ip[=6A( ٷ?y/ؠW{0qwkv6x8^H2^B{p<+E7<^?Cs*+HX#WJM#,yrȆb~X!B$Zzڻߔ5 .ׇgKK;5R+sfojpe>fE{]ꉭʈ ֯Mqo 'U3Ƣxit>.RS7"V7Yi{g;ڟ $-a]{'e.Hg`/]šilr^t5[_g~u &`G#H9ݒ|"_B#rplwtk}0E2] u/S.;] >"CI\]PQIZxaaIY|mWl ϕd=᥉)UKv}K5Ot;&"rɂm g0@w^, "m2+J12/m XdAfJ/s7Y,8֓3|&)MFܧTr|3Ctؤc03Oe;:H&q" ?<Kj-J nC|{j] "⛲4"\i!xĭ?j&Ve!V0a}0 ;sԆWsh,X6p]6r'2i}QK[w3OR>TuИR{hƳmGJ^7Jիn~ν \^dϫY]'\=~оe*cJ!VNjpF > Y=8S. m#1^T[M8t7Dq9BmeEW>Z?oRc>θyv gƠUlYz"IGֽZo`ZƍX&}"ۗ_oA,3H/1#[k*"I 91YYYS?C+=,M5( pz ȹ8pX۸U^OLa躠K,YQ+^$Б>1bmXo«)$i(PxX '~S ߂"t .M~mER,.2o&颌Ѫ\?v7^؟y`aE8iv/ E SqB=qP>`Mxƒ5"J~X$TLjTvAA7) !rͥi.a_~)$P/saI} UIrjkH# sϪ7K,C:Bb5ڼ'FMwb?KN bzU]XaFv߰(j^~˔oM 8 N$=Ͽ8k}; L-jTdbWNl=1J+H{{3̪} ] a^5v:mPcht|2|WBcgV. @a%!ttgU\5Fو#gΑlԹytIM>BuMFHAb4xC#ovRAENʟҵp &[%ѩ kO%7 ԓ r#_a,`vMޡOrB~IR)WdG!S?MFV1b!J\:JF=S!a"#*ˁ6&CGҁ-UOnFE(NOҋ{{DDeA[|n:X*Fa˱=:[]fI,Na OXfޅ`?:w{+I->rQazd+xf)~C D< نI81=,J Qh }ԑ`@ƺ'Z2't$LD6 Z =WpBUDV075&rInM9Y|+GdҴ$cكeZ[Lc`wb |VV]\t% Llŵαy= PQSs_:Sr<`'xK3o25H8b'`@K=oA/ǒ#PꁨTwH6Ysmd_6P ?mΧ|EZ[e5Dї>bM\b˼\: Duf'kf4sіs5BJ߁u}@<7&/?{UN6Y2ާhvj'%V"%w _ra k|.*LS5=v& fE RP*S G$˕PtkWQHkf_ wr9Y$3]N%ԷzQT]J)df<_<+_9׶'#5l<¨RGtx ~Y񨠫gw8z  vLv%Eq/2R/?}=HnIRBQ|vz_Fnt1x:HPSL55}<6{ =‘pXLS^:ӺKF9ot[XwyG2'f\Z,6{UOtsQ. ]˼=CGɫF#,0Mf0nvA0իo47E:`Řv҃æ{1 /Es#iv dY!vEC?n~Ⅴ0H>=eիGOQ4W#X۫fix'κ0\zu]K@5e$76_3~x%ɇ~Q:ƦW\rA6LZZ+'PeѶvkLD/ >nU0-$7˗Tpš9JQ_`ض8r=?gNQVߟ1%v5yRKx8hdaDwĀgо2 -akHz~g֪*.%ѡ |ŏnQBm3/ f Wz;E벧o躷Cڭ=TOGs)/+=wJ&[-$x#dcoώCDļUlrҶѯ#Jw zwr8w_u". L9$.2717̢Dil6BY8O"NNr$?hTRoNX#E~'TK~F0R .Ej8/;4WzSkwy{H4ݾ{ꭌ=vkQҞv[aFYyĴ;ZT-T:-٠el c靔"Ծ}ْ~ ?',X `ߎvdvӮKVX&5 +#G|"6@'8mL |K׾u̢- #DˠKOx+lz̄n'CIDy"L1Dz4 ۈ*}N·S#28=sNwjx.'PM} SQLD;oZl"=jB&wë<B(y؊(:qmgoZv4x"1~GR]ܢbXFcla"&idtH0F&BN4{=<+\JQ&i͝^R.w֖9Baõ-~; m-ok `mh;Ν\P$RcN|駌@VyS(8T+Uٶ͝ש¢o OMO"LD ~R"}>irE&ѕ.f.iZ>B 6^8ڙS%$fn{}Ws˧,'Rus7$.+>d)-i{R#ZwFEg =N}5c# cs҉-I{3\a 9f .b3v^k8,C/lb04mJn{5ʕP5a`گ;oNy@R# ^}#v)FPQ&%{O,f R:]A?{cKca{xґaʙ0v֜z.Ld3JUNKoQCFI#!7ɗ|#r[1d>'Wn^zb8i,'= &)oۇY!MvZ{=OۛIHqXUVb.^UtDO3MYYg5xYIpEȄ9$6zVCD {G.`@ӂڦ|yRUb! >Ue[^ݽ!sOJ!NOkǷxpSĥݖF_Ip{璇j_^ V`k<o 7ۅ`<ŭL'9Ǎ[dk>rePkƐ2 E ,^GUcS!2!XwK -ޓd]P!Loj]!\i/a Wb۟C*D(K-ۧ H_9JSx&D uh2ӟCi0KӡyفjsOT@M=sB{*"j K&E(T&q\Eȴj0G1 5fV+T@&%P9W;zeί F>F)g7{ͨ~9ʧQl{] 񇤦ǩԽ$[tW!G \a6i #MهZÜJ l/2=2mFWoُ֔PDfH=Ӧho{H^Gfw!Co^$yRWzK L(Í$5#-|XkfnT3f;@BdRݫUt/=ב*0!۔̶槚v2eV$XH,NƫByTRxxN  HD,v$'8lWlqǮM& \hJ|{GD<ؤ?d,O? nxh[8j >NR 5_p.[gT­H-/Ca?0L}JӋn]֤mRΨK7%W8/M/&A؀|3M|+DD# "تbX7oɆG -BoKV?."iD׬;fI!FE( bKU|HҘ7r 9&UqjwY+:8 /簾z#9{fojyR $Qቨk^f.w"wvާ ^a?XBqx@Ǔk!fI>`\48"$_P<8Ը'*"AYGgnoe9T9/{vtK<~I;n |:} PPZԯy}&54 /Uîh#B>uZU]#<݌P_]+s!G!Ǎ 68S4j1P_)o5!Bvīc`N{yFtlg}@di[/꽏 -83{fm~]ûGCZ%kuzvE4`ۧ# HrjXznۭJ!y_XeۜOЂۆyi_{˷}9Żc1'N<fkZi(fK+pauY2., ?j%Ԉg.:xb-)1SZx=*ĭlϬTA-t) wwLAqX YjHn|4e10ߕpb5AJۤ[>fmK AP9$ E55%RS318&h؞?!); TO6N3Q3>z|xRm5dCg7!_SQP4;-8S|0Sd.h Z1iY*4Uy gNm"xɂ^Y벨j`LI)˜dC-A4z.]-I6EƢ*]KoҰ/GHC W~P0-#Ta#RvCGb2GSQ{Jx7'K' &ZUgLpᏋG0= Α8rVbƺNbGO(Cɋ?Ju˹'j˖6_}0;=,f[E2E,40SiJ:<' 0\95Ii)+Ќ`ÀE8rO[ܕ/73ͳB܆ĺ҇BQ!e y/w)#:$_lY'w"8"vuXT)7sLM1 C~(a-(!4"~>U+,Wu#GvJqi`\z:>՛|5)U:jVeSFGUQw|WЏPJXAveCclӕpil>zCS2͕lf/ Z%ǩUbU9*:昒u3Xq"J>>+2GH ;_RIEύx wPO5qwofxbK2~Z|^ПS#aBI2Ɋ4F<3 cKH,Im&RΊAB]ېft]jO |vF"9<3X: /]7T-+B{#oKI=|wÀ0ɖ4nfz-0/ϓ'WRI/uQ{)!Z'!) j.\"G FKJQI3݅A p>Ff 76S:2l599icJ) OL$fO4M5SY .Fv2ɬuc画I0ru}jIo/pHEJG #]oGi2ٹC} וRPՏŵD)awkfQQۖ4;%A]TYq&NFAi6 c|?zc [WR"ݸ=ATATQc϶5JF}"Was eg*UQݗ]WUʬRa..ڧ}" nHp.x<0%wm Mi?O= `d'}NR$ YG0yi+g^  EkCaD̔^I;^%c$jl+hkCG6jA8$ҖB'yߔNGNj T Q|:A:kO ,_s[?Aj0ۘ տY=@A )`qߟ4f=B!*䵛Q㍅hQ|Rw1{ꡀPu'FGpiv iD Wku?͗ka6Mů"x7,Kf';9xр]#v~#~w8 0ϥ%Vh r2w7+2 MK0ׇHD0or'[v٨y [߰݊)m?9^IhhBOm'tG(4}qi΄tvo"kmQE6|V8U!xc[CzaQdGOa.Z$t ]`q.{:ǚy=,Itq$(QO}!#ݍvhSӉowHUِ"N:/5QK2QmԻ/::!it*닜]F_uɍ[3?&zVlbi_Ƞk :)AE'AjpnxG3[Lϸ4<Dة2m 5m@&dnJB U7myɍc6;hU sɵ|"}yXB'L9) ސ6{d7Ǐ#5,j~·Ë\i>!ŗ]+lWPs?)(/cD/wk b4ڞҦDL~hkZi?9,ϡ\mJ]NS@DB^gMѥè2.e(Y}_pf%^}T:la-uF݆Cf~y)"!$1::?s/Ch 7N\m)Yu cw( QP%d~Q#ɋ+*YCi,`1k[\Ky7崽(AN4YKv@ |J|D^im>GN!diX-\`j1t^q|)H&O)p;opZةf~ma [r&߮_@MLҖϮn9%=H}| =ݳx"kp=[Yq?Z15md7~Q@PO)t ^> \iO5w+eŽIca9} ؈88NBd)G%V<ʘ8r-).\F8r\b`G#&P3WaGn8e>:N4{ȰKryPZBs=V핺ڔ`_ dPLawM=iEvq_tM`דNV6+c+Ƞ>jC^?%D$?&N'[:x0Bktn+k_ _! "ko"0ț]0͈Scleg" aN(iн1\,0\TM\GpF@ei:"t˭ z-MOC^!K஖SҰA'q<?K]YZ ᡐvXPrG]l$dE |ox4AsbJ0`; _8rIϼk3w?ȨRJV$265oN7.DQ7JT+qrZﲓue1hnzBބG&"硏?Y$H 2+G S$Z9QgAW]`RnoM]al)yęy@!Zu*1eWRg{pK  ŽpknaGtY+IS3JrD2GuaKuX9 p T/L_Lnx^c3$q6H$(wJoQ Οe Z(&10TBŴӇ:A^X+dn~^Oej}\[y, X _宀 \(2L3|+ULIΛ37T"v:yEi6I:5XqAܶ^xd* bqKTrS*ى5a;0U<~6۳+U+Sgc ~fs@cC&di tg*/nÒ$!.b_ 5ԒA{zl َ+] t;ImQz)Sh=a~~2VI n?O&[\%MmEh,m RUڑ;1fh ^ynROt $HFI)V)ת`VqriSPg ~~vJ7 LTЀAO#Y7 nG d?/W=>D0D+y)xa4̅D7 ?8⷟?7/:IOڱZ"<_9 XL SLnb[R+꿼6_-]O!~hXx:i, tc<.яVy(gɅZoS0Y&䳜AVHd˸ gu? /ԼCޒqVmEL[*ݛ (@үT6Kj$= žxO˨/.Nv0!`ykݯB;KDI?}jrZ~lso i߫qNa]p$|L'x?Noq<-?Ǵճ5qa`zܺ%ğ@cM[ Jmp9|5Yq#2*>Oush|5aHw (' 速qݿ=#Zޚ%`tl9r3ʹIc){*$\oN6@!,0[[g E|T;RH3.bD03X]~FnzR˧N 7&c"{kʼnV5J(`R# hΉqlGRFU*oB F!dX̢jhO?fϘ0}SY) \7 f`8=)Χۮ93@) FQ%"ݿv-'8^(b Bj lk%Y;lh͜,:DD%ig$HsX(Ñ 9D Kɉ~!5Ra\8!oFG_0@0kVi.vp욬E B-17&pX㮫Zdo|I *FJÅUSt8wS;X`b;TS>@4&uOgE樔w)CufM~u TnW$ dYtu3i4ǫ|ZT^fhy|nۃ1~RKP%;ڪ[.廮=٬:zIxj psYAoѯ*B^>^!uSUzOWvALU+!;'EJ2}t!VgX0F;N};:O6%W޹aLIP;Zwhcrij Tl~ tAKԶ@^t/B P+sO63y3 lN5U$LTPyfNrfv^y-1iM^iV?_ z̾D(P[8X7wDA}=KR,:+>UzR0̇rD_=!ܱޜr1sRILpRYQR+}@M?zI``A=9ƭC>aqc#em1 W\r@Ą2>Tfa.U1wmٜI\:LsNOMy_)9c1g:g peAu>M,vtgRdNmdJzGUr'QX]-ED ~|j_j=aӅi]vJHe:l:* Ql<Jп&pל~FhX| 1$m_,76Jwb8QkvJiί|g-zdUS-Tnc)R?s[FkVH0 }>;뤂Y첊,2\+2-Eh2t2=*7(Z`} E$ہ\6(D#|'RhiVu)6 h\r٭S13S\ܭ*}H²-XC1܋e+BBOE=;QupVi`0b ~-(?P.} eBU#*J:InǼA#֨" %õ] R(96[d8^=0Y|ҺkLbjn"c]l`gaȽ5"kg 4^(rpR| w}Ozœ@xVJaLFhRʝchaM9X 4FBi% .W%=dD&q[eLw'z_kp;׊@jvtSdk9߼cbEIlM7-y̑~u7ZLl(X歆o|Ly'![uIO>H \T.fT{Yn'U;XU,!O5vgp|Q.Uh\QD KԞ~EeEZk#ru^ĜZ n 8IdݾF^Mӳ.?"XËQx氂'NɅClfvThF+<>;;aף^fVrg!1&DU9o8 :ad+j`Cys4?qeJ&FdȹdfXaKA\dL$dHҦvLEIAl :+L:ZҽxR*C속>/.^sX=--D{rUע9?:2?G ͊@r ~&n1$:X8p^+x緶ee!=05 >LS F,}PFי{SsJmݩP|᜽y v1(b<{I-?l/TUXY|PKX%$o̥CULmoh X{?KBz3Żg2 /f!]ecP2 /8hT+I7~nZp>WUbj N"pY- }\rl>Vf~y$״a} xpԦ ³,QML 29PaSM :"ZfMkU?Mlб" 61ķ?VbHhuenmQE\+yBP5--G;OU@yU']'H%4إz/|8hџ(Q['Fyp Et>?Dg7U$9H ?^Va9Oo3t[ F"A~B(ǿ˹ޝY|rY *ZEtɷ/aeZ5SVv> stream xڍP[ w!Cpgp2 85X܃;\{kfiyVw~gU5,̀Ҏ &6fV~:;J1" / 0M&ifȻ8ll<vVV1t$Ml,JyGJlcev|Кxv96 5DsS{ Q Z8񳰸3:83;6.u30@Of̈TMk.` M`oc9y,` 9E?_xEdiX*Ҋ..S_Ύon6foGn S%6N.6[@@3_Iڀoedf@ K_IX:hl>$c&B#XYYy85_Nl2vrtX%} z;.`W!,l]f@+71v`>[Xz[{Y8=},ҊJz d_p|7`*t['`?f𿹔ߚ\ool;o [߀]VQ:{g]]_m @T*-l\Vm@V-BfGאۀ6m+ѽMp~ȿUGJ-0v.n)lH\\oQzf˛ -=_#%qX EbA?OXT7?Ezc/{C/z; ?Օ_-[oQX Y!+Jc&|_-TX@EXf-R?7_ ZGWvNo:|M#oio9E'xxv6wy?=@9✣@m}H];Oi] :&Ep*|*]Mv:F,u}e[Zt[|xkZۣϓqnnxѱ>b&M=>AvS}tEU-sW<6WíT>cX2Coy= ;zh37Әd 'zq^?( I1G'K鳸c)l^w #jq~Z|hlV$$8ϿW=.x93$ټ|RGzuOSCn N5pj)o`|uxD[GUv{&ЊǠ̹T6=+,ν1g #T \I$hܯI\oRfg}hTE06=F˪9hsG;.*(Bo sŕ\ ߔ{ +Ԯ~yfX*\n!lx6EdЃ_Js* X (b\'y'ajqVBs04݆yHSoHڥf Wnai-PC-ok妗ֽpFspB db] rhL⣄ZtV@@)~" tas4Rt+lAfm{蝝%zMg=2ֈNV" [j9u{VdP1u^-jrkav%A΃a;r-v >DbܠMNCfTԜ˰r'tn j,N^"H^,>9S]ld:- GiS("IV%Mgb_'vMp3mRcz w[ Lk=x҄EE-|fo&i d;Eaې1@vY~^_KQ}*7=k91_rr~fT"UbghE=zs]8nQպm`mo-JIc*Jt{-$_"SƗ Ѐ PKk#DKb$23vf/O2Cx?7bwyḭyrʮ*Q_,R蓕4CUj>V^p:Tj?㿙=e 8@Jue߮CEaw|gLL!vSJ+cOq>Aܽ 9QJQdsluUڝA;6rYft%Y6UpsZ8>c+1!XQdNUX Ļ}>TPšvJfן&T"hj$W2V$/Hp-+Îc؟6/]poeHESj^Ө_ NA:α(|_ ~'4܊ON@ q5T##GRV %[ʩ\ ?↟Yu#9$WEUKKs:i_!VTI].-0 !a>ʘ&xcĎ^0K}IVDLÙH/VpR8 R>(ܠ<`>Q~̼|/1}-N(mzx(3"N6bs0HGx '+[{<0 QO~bEOj"O7PնI3+Mzm d̒Ezt2ȧo`qSQd=&"ybQ8ݎBlk5wR +0ywgr>8FyoWu^Gnԇ]t޲nt5;ŬZ r7na]`̯F%|n D4r.-gA)D{y=OH)Yyp;|{yx}Xv =Ifʍ\8}k^*bFfxnbq daY!a*GK*9>2676}YG(%7_gn (A 1,e ^=hTRB / B?QJTZuț{6?n/xҵX Ϲs0((SzP5 c%ָ$R4G[QMKӫ̸,&UP4V:ڈ gF)$2IFi[fۗT?D'8KmfTrU&Eg"!`L D6M?bDЍs.|Uͯah62_ݏ*8E@Wis }a|!zIuuI=BI )宗OZ@?Lt˅q (6Ez6^ǒ{7]?, 7fOZ뽋,D/ ;$Ѽ]0aYO;cgj Vv& k+1)w!|9o!qc`C HTS|oZze'VJ,2cC3B##15C"̐__e{,E4״uz}'(w(;Eqi9 X%B2)ܲT.U:a.Cߞ`H1I#ZJ *7PuYb9}O="%LM:Pjޘ:V pdw@mb\#mqI#;j[9TDJiR\bU>=TmoFP Ts8W\`yc&o'lR13xspٷDmB6T sF6PPbIX٦/m#QZXץ)ڮ%^= .`YD FMG!j iVˀP/e`3}f3 FE\59YwWH@]`,KgIwb0U?M4 taP똧ܕ7%v=*\e)iyQǕyYHY, 9Hc5eANuvDLsqGcآw'YO{pHJ!UuA&gN3&^1/4Yȑg8 I#x.I|ʙ]r$yΟ{Μh[0x7El?ck;?5:ӛ[].9YJ`i:aC85W7)V|/rҌk!Onj-$BqQ'"yܖ, qx}qbug:m,wc3.E`㼘 w w_FkbI2PX^ u}+@p\L*>Z!UKm|{v1;|L᡹F2&WزKmlR:X1s xC {6Ɵ?{J3Nƴ47V*~k͟7|s'[thXX~ W8grF[S!Ÿq&K*DI~cS;i2X˛)t2H<Fq)SʨH ͟=G,>SJL&1D5e{J>}=V~r: ZW@+ORh'-]s! 1NWK_u%u\ɰ rd+APv#w6:ҥ@8pyRӛhYПlǟ4TK5MW>64j/ADSvYY/3wdbsҟX Vo00/?CJ]>9X 7e&ƖRV  !6hۧ*N@} jbuW5ud%zLP C*{k}[׍a'C?S!Bacr'`/ؒtD&{+~Y?6U1W%>#?b4P}K:USUcyaC .1ێ],Kx8ب~@kR#0Vl5#L\Bfh*q'mvaI<^EjJHiWDYcAA947u3Zi=e I"}2k|B2 \S\ 8 a m8k&gOuZS*IL0bR#SɋK|ʮ?(,(1lco+ܫUhMo.P\~$#G4ăvh e нJ-b{+yO g*e?ֲcpͺ*fȄcFJ44L{=@yiǴ52>~6(% ?$؝9QC*܁H<HM ,ЬBY:Joö?GZlpOBG8p縳 ;}YU}L91~$SB/xHnDqxZ{`H-^=LԎ$ uj tSH5$Qa˗o1[-pIK3B͓BjMJyz`~8h ^}L(z$W{{5,:W΋M-;?Wd2.畕#R-IsIӁ2;Oըoz.<-fFOF?,Ikx:B,~];.u8'Nȷܱ*f_uϹЕ" {QuS/ d>؂g3pOYZ߈'^\8 /7mg a6{/Ei.JazLrD}e;oTW/v;h^qhгL9c""2 oiE2rR-ʛ3ZNCCi. ȠXqՇP;FyD@nvf *\ tFM^Pfs#a5C~BB:ʄ2ȆfP짔^k B'a?=ZOyJc!*\":@ha3_Ǘ״i1Ww>[ߒԔgmc `D+48Hn gfmɼI%Eh5S`iEeH, KY- oЇp:@dIN2S4}5Hńx -#hCDFbQR}V`LFOýty47gt2ean(X\)L'9I4ymД#g9CGDKy2>C!.9c/'iugmNxXwݛ^EgۆT3Xǜ FfrwK QmR(սE#GCC Z^f|ȟ(2)^ZJ,Bvh`;̟,ɯcBX"w6g) x+bZs%Ƴb^N].lu8x\Jk:wr]3Ph2e!?qd.V|G^ލ2I:>W4@~K=n&^œ_ zaoz|>-D_ Zin\rQLj7mßdj,Tم[B$o}C)%ED!_uJGT@Ec19 ZY6/Kͧ!Z'C,WL ں*UKb+3?Sχ2.;45MPLD <:!'Y$ *hfd Ys 2i"Q7N/65`I~ȚCDZen刕rIDNW-x_qw)o3d.p,L8~Ko`q%_L\ 矠rS5-PZ@\ mX~sPCZ;>*2ўo} b Ȉ ^pC'S"*u_'Jl?dhX $ 6J½`{Κ\h>T/{`H](9nUgDm޷5/2'j BL$׆}S(25~Y|&ŐO$^"6({>I'o콘é˓pOP`c$3y$Eئ[T`ٖ+un*GvT)/QtWbEGo"2(w 9 Mc~cΛl􏖤F֩Hb`ʏ<-*~AX{z"ѴufG*+ݒC[VJ'}oO%Z گ0}H!vHNw{b%e(L&7UmH 䛒7ΗƙwmGX /'+|Rr}ymdhIW1tŗ )Y9_pQDv>\Iš9Rhl#&3YZxHJ}PJ++x{iJ-y uM}/2Urv94Q3MuO7 R*ԲNǛQOs#w+S)D'2aMx#t!'lT+AaJM4ZԂo4["]mӑwDNit™<8mBJݘxɣ*:Qpp'ɦS){&!;&ZͽhTVu{͒n3Oho<}>"Wi#|Ѫ7^xvf/I썾> ߫!"V$0 Dͽ]DCXFC>.<ʹnɊ̪ЌKt\ûV=t3 _iBG^ȚnQp4mޕ'/tm>uݠL)SaրTQх#W/]:rT#N4 ySOgfϻ3ԡ"禀yiv6Dy}ަY#a;S֎f]ati3vׄn _Z?aRh.!;$˔fUbÂe&qnR8F /3sAU"fԬ;{w1ie/wxٝ1j'`&p]x@! n,o~lǯ[;'=z,n2Tf)[jŽs+a3>nU|(%<%(sO{MSD}X8uqpkB!7tA^HVZ1FV}w՚"]\}mϞƦUWW V:iY_MuY*wϙ1W}梡=Q9:}c&qRa,Ӫ >2t4wKW̭BG\VSY]TDTW_&7j { A q~Ds\ cB & GzsI4i7E÷wI<~x9XHʎ[cKoӬϹF g١3Gz}0%^Tyš䋂Mتm 瑪(]#sJoi7U7J8GuQIi: ~;&<_.AteA2{KU-[bi9:`1 )Bl&8֧$ {j8DoVU ȐXekh [F2'T0Ww¼CR-1fCǧ᱈K5 kN^ƈ씱}9-"|.>9uMOE#.|[Am\ZL0QO=rkc@?6|(dg=yxYW@V mym'cI6qɛn)êلMMGgsܐ 5ye*؏SߵĘ<"MF $8WעlXuGJ(ٹlǥR})mLſ7&O>jjb.7%n)\_?ruql`; )<-߇4ONpg;L(y^S'C b%DgU11MՁ8֔|pQ~;Z'YMX gzu8 bj$d8e|ppGGx@i~9d+4ׇYzHK cS jnI9Qȑv^dSF:XYS_n 呂0-i[.EK1t^],GPj<} 3AkJkёVmAra1byjˆP 5W(3dv ͋"W!12CoQT!f]QeQ GW_dr 2mC]Tp"- 蛉1١UU@* /H> %[]&戃Zu 9\zP3>qgΨ4P2y!+GFk{h>ƤMw/0mjo˴edFBvƏ`e! a}itbѿ%z72s7.ˢe 1 7r&~, O(7e bO߼BkS $NaOgT55gXW uT3~5V HuyH`ž }R* z)NMO|F"}s"b!l<598"$wAtGp$ojh)ɥRL"Syڰn˴ BSQ-ψ|g. ^p'=P2?I2j nwW#aB sA3`#RZNwql`=EjK8?I@R(6"-`tq亁ou|ڪHQQ>T |( yL|/+ wh̿IX*\ž((j-'G`};0M[G]4rƇ?x v;}W߃LٝʝqbS Cy@u|}f65 :o3٠1SFwMCAD=DhvÆ+YYؕ/PgaSυ!$3:c9D|YsHt8X rEOz^jWo] K38Nm]ބh 52.`Jݣo"8AV)!:4j|KەMPTP8ەy ʹrER|B0grg ~x<#ߗxm 87vU O' k^(G~wIͧ5$fj!3Kќ"8yNxKiL^PW]v! nO@M>lNGMyT}Csp<6|Yl $G1-f1H6 j)9xLSpD*F1?|j>J54ћE>j M#\lǽw `/h3}bյ. 9kjM<1}fϐq'EbA/!A4Z޳E\MFZ,GA.{XTd"cDN>UK.el]=VY <*IO|3LkP9AmWRA*r!d,Q݊ WK#(46YelsU(?,'*XG7~ V *e.qxyY]_DVs[犌*]ʭEcjÂ~JʤCwbEp_ˎ`+O:Os!+^LSxMڏeW7=,e_Ddeθ^1~T"}30 wz4wB;p]sB%*s 26Ij7 >p,7A'%u3I `Ӄ ^+XZJ ,I{>ZNlW;J%_uUOdb阱(~˕ E^ !̝_դߡ']+krxz}n7٩řbb+3ֹ>+qكg^MdTU'+ؐ?H}4>G09yՏcM9?^Wy:|n~2tm޷{x$ٱʗMACuP}u!67*eu×lb Z"XpK 1ll2SX]CLL)W!RޟԓW{ DUM P6)C 9U}Of*uD szkM= r/GEM2}]V,> stream xڍP-{2`=8 3wO!Kpw܃' %9sWWS5u^kh4u8l`V yԝ( Q@ .یruà ȸ,ݟlO<5p_s  P_D0@lP(à 7 +5z0[@`kK(@FkK@f W fQ{wwga..///NK'7N8 ; n\=A6 -@uƉеeׁٺ{YOu{ڀ\O/(4AпȪtGN 99[B}P;-hȫr{,67S%biDS%@^J `Y8-rN4e9 uw],d4vN lPMx8sA. %ٿ)O&@~ ( @\88:u9lmAO?n F; db'd~:|W7=nOOA!>9_.eu ee:OZ pB|>!gѴ]?JP[@b=>w߹aO@~ w y䏛tC|&Ww@xž֗*e3zq/IhQ9(Xx]^L=R+'ao򼾝^CJOjLBx?>+L[!s'A90cIl/裯äJ/f 7(su? ڏW2 h_ {ڜ(`I#xW~7GD`gϭ1b0 ggY*a/7QQ`CsVJ~..f@zFqXsvRxlћy]SE%j[t> I֧q45[)v.BYćψ.}+|no"Ïn w .Xg:6")&f .0'LzP}Zҫ3U~q0fzʮ[?Om5fsT(K}/0wA l9v+ǴD8)eRnUK xWˁ)_r4t*dW[ݑ9x-&-?m:t ;c ݨ/V a;I_;WEq+U!#m*% ,FU)u%<< Cѻј[1egBC-ָid$c;0rO?_FZ^؞D仑d~F#1{FDCV[.pKs? ÏLl+s%% ɟ_6+DSTwF(L] ߾tJR$`RE&g-NL^'&-(:$Ź{PH? ,'1+oLd0W1_BD.41"wW'vQ33 R')vpN`g[ J<"ͼ~d3M {$ly_aOQ<:rO:}Q$&4 i/`m/&+Hu^c$/*60<tNs77i?̆>$ch_hPg~DY]{6r-U#eK壖{sC%"7%ς> δگצ=~B "#m:\9*Vq<|†2*ލSǕ(PW;`]kS/(V{{CE>8ǚ?j TM+Ǭ_ S4v;zx"q#ï_,z2rϔ >'7H^LKh:ٷatooD^v]\-|N+e8bX;ԕ]Ju|+VppT@v4!׍!Ou~l--^|p ʤ)1/ߑRR)">9Ī]qlu8+`l|1N葎eqsi6 AE2?y +Dv QS2g4sr)nMD *^6ZT&`l?F 0_:xBZ7wZ+8A+Nw:'XB'i(4k}.X7ְHwc'nMHK&քM8}8mޟLgQsV靾.ΕqBI&upјp6K+fʲIuAgvȫ#((e0bdrg"X*| qP?ZHk˜yD<*?ya>vF ";H+@j3k`J-FbjF5.p^K[Y=,l5n1|IiQ;4Tݡ/M]C7yM&uRZÈ?w;XiOOY䦔NK .aZ9!]sp@:*Y8:j8e~pƏlU㻬2tslqT$5!R!T;Rє3n߆E~/(N I75}ҠXHڧ#-7AH`/?EvEQhbsU/RS?h8^/-~<J&w1bpH2UAs/f^207eJɻ搾^,-r HەDfrZ=!'ΊYh19EBA+R`B5!#BWR|ܨ5S8Yv"z\6RHIm6ڄK&_C&FX݃k=RSK$3M'ߖg&v Gi` G%gp7:j~kCY%x!,Sz$ə#5RuŤ tgSz ylI{}&co9z M91SåkC#LM&ntE&^9LF5XC7CcPm?R+$Imƃe'{-ݻ|,`CNd?bF-]!udqk $k& D4 Bo"dtzj. `##++O)h9TvR6n h6 \#ؕ TjB\ڨ/N$|a3[TۿЄ[ל"їR?yT=q64 bGpΥ.@NL9fzv!.]{#"LY +hWc$"ϔ[ crߋh,"eVc㞽`!C\^-_-d7y4QڢGH};7ٮrjrlج;3xղJhYG˶Y2ob<"^gLH4n`3Q6ȋ%l_u` zZX?>lL^W'$ hCjњcTx̋wn4\X=Z6lkޫzhȍjpX)pYߙ~RHߕ.cT7>Gb8$p7-`:x㽱]3pT>kKin05#o6bL8J. k9c z,9vy7n}kpk E.,h 7&?-%`>6kb]~Jɼe nւRϯ|I]δ*̨P{`e:RI xPMxV2>΄y?S t@_uV~:4uֱfx~AUC-U*"pӃEv]C6ݷX4?B K?N71SI$\NvbBtJ7л a Πdfe$%삎9ƶ5<~9pLJuflu3c#Xr뫦B d/(2'=D}IlbڍN9u1 Y$h|%/GxUD; ѺFV!^ZD#$Z<O?,o-Λ| ݆3хV>&Q7jz,(y7D#{޲ .Z^%ɝe-etLĎh,OY l5`N:؞}}6,d>V7g@8f'fFRx$V"cG#a)lb>12V*rjષ3'l`=]et?Y(ֈ[#Ng Sۻ){ eWBWƀ9L]<ƨܔRḈbMi;R(:N_RLic\<)VO2u{ ʆMmBi)w|Q.ål>+!G.4ZO]C4{OT=z@Q&p!9sJ2I͔^JeJP )"goд 'qpF<}~aF"rdHo1?5p!mZlK(y<=!M݅WGޭܜǥ4sj_'GDca}`g3\Dӿ3\|OTCdSh!UT_Sx /lQN Q'a8] fNJ(*b:ö"eZA'nG]hHt"Adžq䋚KZs:8' ?zNcZsÜN=7_bz6|pw~u=(˧_Ybs֛)yMj`9jD/] LYGZ|dqUȞw:.|"YӱH~lR =H5%c8%KO_n|OnsTN]u_M\jNT˓Wu|9@m+|ȵѰjvY1n\j]=1Al-WjH`Fq*ڲ1)rH0.lC8/` x[kNz eΠe6D,+KͱVTEk9eoBaAf"S2oEA80bnzt"K`9)nWSU%v)kXӜ_C}%DcUb3%][ )H1&hr2@{C$<-s}Foա%F[U\/Tɥi:[I8FTp%lr4Mf ȾJur__͏Cy_eむyjV?e_Zc{!Ѷ蒯ہ,J|=12l䆆M<îCNeI/@Vg@)X&&/⟪ m_f}jB{ۼ'_'o\ػ=]$JpVfL3|x\-&hD"gņﱄq:nVmӜ\ϛ)avD'E/x[谏3۠8B UupIqsSSXEbAF!W+9e0ƖrwYtz⤎&?KѬ,7PF)lxYe˾32}_6{[ȴVI'1\޷H%5AT$s ,FSөomL{C4Go^7}N:z|_3=!f7 (k^m(cm [#m)1&]eů*eGT9=#m12x@@cq820ds6rX܆tBfyLcEn[*)/cJҾn?ۊGPгe|tH(M+Ýi^(=M zsvAn7Y~h;[HQ#mOQ|=aўgg'ؽWT|ǥ]T<7?5}*,@7)} f?4L14RpZR%D'Ŷ, O6FmO:y?~ђWp?5%b"%*/c*2[]O9El}Uйoקؙ z,~xbZ^p|ô#3.BmL'% C?g./@0&0bWGp4J7$j_RbUbXM<4xb+WSCNZYɭ+*ҫ8S"deSdvTGD^WHiD6Z[ .HNqOeqK`M,+"3_kQ+|)@A(DEi=V[FWٻWZI8I ocumg9ˆ/=L ہ`Ȼ-dA#imµ8{Sdo_!Rd"&Ӡ*")T@NGW B)|/~p8&c(/)(NQE3̜qয{c *ܮ,`h^JƆ-Di|`mYTs᛫Wj_DhdXs7@-"/)nj#Ku60ozJXޡZWDk"o.eő7,)^fhy^̨ Gtd:9n3oeJ>mVZ!MA.9e: .5B׆@V^8Q M|SD6 T* endstream endobj 260 0 obj << /Length1 1391 /Length2 6286 /Length3 0 /Length 7237 /Filter /FlateDecode >> stream xڍwTl?JH0atww0ƀ l8lt7HtAJKI4 H|S}s]q_slh¯waH~!4@EX$PJnAxB0Ы $S!1fzp@ $@Կ i*haOvuvAbnIIIv(CP0!]  7  %DzH =gyn>0xBGr wH.P? B@ <1^0G` 01п+=@04 pAH92y1 o 18da:O0PWL`*pww I+?U(t-{0 stU "s b@ PBR y.= B`L~pH !yCH$?HP0qH!NdP!-[po44125]Up_DC?eW HIӥ%Z n?c1& P | i_Qw>^nn\uC 6YW=#ZHf`nn"S8B`?TZ07( bzPB@0[v<>VA0K+``3b$¬#Aq` 8$)*H? q5 ,oj`{!L2?˄?l 8Wÿ6*7žf7:'#L ]A|WJ|EYDӥN[aT{˟vk/IiJvG|Tqy+nv6{#/I2bS7o+Eά׉^TN'ۄg/rțc!@#u"}V5v2/InHժpٴRg==ܓ[&873o=+]A˜&廦o|}LNZ+.~]3Ž9@4`Q{M zm&шW=UƼ@}wD(,M{Ph}}&z}^Q$+!tI`b>ްT` zz$%, { Z*lb5__i}}Y&_H$#aJ9ЪrgdVSe` (h Qz` CNk5%;>|:5idpy=&zD V>5fƤ(sJWj9~mcIyC,1z"F;Z(ИaăTvөݠ{Rl=VߨѶnHDE!\]Nΐ|<N0IP3c hP=wyfdfU@~ʗ9]N$ $Cj{PJ 6agྎŬ⼼-ӧyɍ ;iհ9[-$xHu@ M|Bs?|[pc/,`Cv(nšr2#[x}z'lI?7D:'oSYy L42 m~RzG% bd3]/ř s4b%oLtID w9ըA4B^ aEc82lw6>d9\/zoSݪ#wi-j,g)v$1)T+s k6OfZP) :ƽu1Arvl ]v$UG \]`X$ dԵpKZU7tqNve.l)g\^|]I7ϭcZ!ysuWNڑ[b|l>%Fo>SILLQk K[w:4qrIc=ppB;k`F x2͘O"e%$}cEͬ*&N|>äKCW#hшv*YK)T43Z{[$CWb}kb2.l(7 {vgpؾmk@ )\tsL}>eR]plf\aO'̛F1uP/;2ېƳ8rf\*^ s{<⤖"vn;΀}Ht`\;jǰTY5*8^ly1;|RؔcD:S_uRkSO&FoJaUk=B*k~!НG$,pW_zͱSoS/Jj댁msw .#L3,ʻ:ɵ5 ƙ/G|5Xbn'{9 n*2hw!dU~>JØ,yYT֖{|\pS#--Y^Wr>9e+լ] B IVC^[0iBv =hIu1IB 2}rFn3LflG3 a@RНQ0~wՊE/ޜ.~o tO^vj;1<~b[cMbkKtf;p _9_1Dtxx3~x7kjVkq9i:9Ycy+ϰ'NXʿفef>OZN`R[{_$*1rZY+1I1.vsaxLכ%+"%iKxzic>yYWRp%Ch}jLe; =}1P Ekex.&Ffګ>\Σl<,,9Dcs(XQV CLPءOw7?-j "YR>Ɉϕ5FF?,7Bj3U֮Nw,Cu jA  |*oS,cEӆ&e_o#mFԍU<*Mw  óɈ#4Rzk5kGk"I9{z K5k Qw^]s pMy֟ˬLߙgqfh1_;\sRc_b@Z~;_1cMd㋙R|ߞ(4^<+a^;aĬEyk٧֜6۲S٧R)gtb8f!dpќI^_Is 7\|9e!>[E0pRq;4o_n5oKf-H Z؜E{' Pࠃh^9rUx(}݇zR^`,V7%-Aɾ5fWkJykn02AHh^(u~ىfB~ɘҀMW^WcY"#d [cpU\I e fPsB?(#yo8G0ګnUBŬ5wsͬjG&^_0f$x}*j~l39S8󚑎oȀ(J>&J[MWqx7/{"sT+ssd<ǏqS=~pQpzɡr3!Nsxʹ[rAs#޵^poA{dӊ&jCЫhs r%KL~\xz;8]J\[9ʹೳ]'.bvoeS{2rY3jf?<^Hoh:Js/W6M^gN 5U:"'iez >$۽ SkA@;=̲=C7' 4eIEx7z<%W#ՇQIΥ]VBя#ס\)n\Ղzȿ-sJp,ۊ2B7t@a+uɰcRX h|" +S I^b/>:;753IbvMÔ^*U)]͹&}fPyp=7B^uA~]sBh./q5 2CL#P(5&t([*WHe\U^:ϕ-oVy7LH*B盔t dž+ۃGÓ[cOkxq9Ǿ/vu N&k>g]y!7* QTpW|@#d->`&şZ(F5Ju_-9K4I߇ VHۮ ?VRߺ,e44?$r+mw}XGa-xU2O*(℀k흁WDT /[[U߮6%'u9.|_(޻{"_arDaΚ%-d?Fb1weUĞ!>`=9T7\,nql\mMr|xpׇ<K Sn?$V)x$4RH.P-U\&xx~Fsêܠ_<@+gs/=DӆoY:ivUO "p ٍTWj7=RUh)5ZDvLTOٴԲﴮF\S,lE*Z}Q&} +r@>e-c- ա (tSZ~<<ؓUdll؞BRms8lgX4Q贇K=KwL_db~tzuSa+S ($=R}w3먥k*,ӍG=븺`TM mpq8g*T}0rM##*qeXwNgt_0":uoijCn 4) 9>3Xˮ=C4 匈7y]~Jcג&-)v_j `~3],e,GL_XfFpi{.$z^F9e9_? OY7r> stream xڍvTl?%1F)nI 1 ctҊ( RJ|Sys]q_3s153\ŠA @ #3Y ,)K,X/ pEQ X ̌(" (@d`,/C4F Gāh  ܱ[u „yyY@5$AQ@#(z0X E1nBhc._H@ w b@Q8?  431 DwB~;Ca04 B܀/886+ \~B|8?uN V3BqU/ "~Ud-_i"0pAcDP!ή\A(\O/ 7`<a_-῕_0.o7W< B|p  O?%tA@gwt w#&Aoqă>qrAm{ -s[+5}RWGC$db` "!+ }Phdq]WM_31X8PKa/]![+KhHW_z_8qoS+u5 Bq;r_mD ׂy!Pp/׃mh[-?B.KBZ`A܈q40[CxoA(4ĕtEc)>~߈<{qa1@8$[G20? ɂ_g0v˻kֆ֬ `ZNH2F.b2h>j r_l5"iN3m9 =wL5L2yVI!fzz'a~@Iq@N`moܻ52-M:?d%Ɗq RO\r맊¶%KBl$N&ZHvڲpҽ!dxί4NcN b"UJ?!ϺvANll Ѫ4!St/yϟjzĸ"ætx-{s֟[y[5'DmJMe*b.DATt ")z\DG:7 }t'glhںJģw?ba\i(I4lÜdݙN;һAtC*uķa$׬zmlo_:w"m5ԈӻRBڅ'o#L(n3Mtx#KLjŌF6ozSun.˥]ԗq{26[8X/<߼]pPwr6L)-׻@d_ |Pu ƴehV߰M)I&(P ,޾O;ȽfVfV+tfI` C)}ჷFC%/JrϧD>7NվrWslX7 |ztR9pV}Kz(*`'ps tOɴ Xq$bRYvJfܧ3qbiXaA9i.D"aIꇑ6"cӋ^kJw8b4x}Q5S%Y- [wU~0=|UM$_vHPIllG:nti|aӚpLM/BA?jQ~iiShxm)΁2L>k}D#}VD .gu>0 ]= 9+8}w%ugYd8ιs9淪\cìƽ8VTE-uTWSb*SNPUʒfB=1W y8ď]4E2#i堎Wq=M ^; e4bm\\d iTϭ/iųbIz_ aw;'PǬ G[3wczY[w$nR=V!{~+·3ü^.vp|#kW!]gI&Ԭ fZ{.~X+zvתWOx:LN5pJR\<%PTSڹ~^ӇqeRg'# ҥ)v6y1Ǚ wn)phD(5ފ}dRên#Dj*o[.I~ =#(F>󶔴Ynhcu:o/C\m[f>&l]cq0=% $=/O}6oW(Xca v<>/*L h6-ǀf9n|{V>u{婫-ٝ Ǜ{Ayq[/=DVM ب̰mq\6MzY(y蹞Ӎ\p]m>ju}hr/lm9AL4#<ߊ&՛[DŽ>DYՎjaGԃh'%od*N`_NsXL|\cZ~_.}ZIך4ML.FKƫ(n5 םf5N7>Z@Huu;0x^OBH4Cۡh9[ReIQ-C%L3{*;we&YAQSj*B=Oȃ3 承&xou]}CfeSk9E7J3(*wdbG{UVy)ZFCܺݜ ^$?[邶hr.jlqBD3"T^9D)XD$ c' xUql}*jEz;L,ȩQoxVX^Y+-+ Jgev [{ BG~,]`4~ .!fvB-Hu!%KlE jo!AEVAf,`H63Yi}(Tkm /{+]cFPzʋ}@,Ҙf_D1wf{EKC0@jI6GE {FvY^kx(ݑQ"V '6l "/[_KH^fNtp7 ecєdd~sFmD/~,ѣLbV!w/3+z;G|{̖29c 5 󮊃BRe.) 3YvۜfK ףB2Yym!&~Xt=ݖ~S .kRC:;&lւ33#ں!NR[JMGF]Dw waZJx~ X=E5֊ߩ[ڹkqG[dsF7p֛+Q+ ͕L?Ȝ|Z4 8=^'].Bn{ nYð bAui_rI: vn,kGr0H2T? Ot\Hh} 'R1.ojQx jdKǸb#d9[1Tx[n]+R&|"WzX^NjPGMr?A Ut~9\%<.B2xH[*-es7ZI)ESo'O&9]'Rl:ֺR5"Fs؀hBIR=TITHyCjht=G {Y.`OEraybm9JerpqRFk8հ5[˾I[<|[5j2Mh<~=/4P>9vgR2ɷIJff+-rEr*]K gq#BP|Cǥh~7hxNUGeэvOxksHx{ow"RR>-u9^"ZF=ӔX#>{ VW49(EF; UNb߲rX=zG~nKfN~ZۖڣoPiM  /za=P0CU~%ҟ~ڴr~:p|}K x^K)Ⱦ kuުZ{mww2CWf% By]Zee=5AKxi}iuxNS(̦e"Q?Hy$Ÿ:O>Ԫ'=S;i3Wj,˂BV٨.Q-X2?w֎(NS 7sțqyS$= Z}I3X8P{|YyO@Mȥ~_Np7[+X徂DƘo>DCovѭ'nb6F`ET*d>)_mPtS @mՍDʏnRaOṱY[C'~Jr&o>zeFdj xw6#~XX})Px2(j @>vɶftó>]{x45m{߽LŹW 5ST /ܸ3nqnŜ H~9`q%һMU2|ȗb>NưYV:]:i#ZV*OM.J~X:}muvսon~e W8\ىQTEn=)ȭX.D[Z٣xO:ợϑc_$gtXLeqhuKB DtgEb%.37?sMfQn=~"gB/NWpM k׎K]&%O=4ytI%E~{My;@ Rx.=zD4Q eifԠ=Q厶̲od ޮ&WB6Ngl<\|=lAk"MA~eC}s-]vx{?$~ˎhB6U Ia`c{w9QÒ_JrNJg蹒LuһLtx/B1jJV-ŕd7M 7:dk0 Y7-Q'{y(dFX:$<3{sYsvk+ʙe~^GNXmzw8svQe(l@Xe7k,ck3,L|גfQ]YH܆ٞMqf\K7l:jJjq pPa9emC鷇 'hQ ٜ endstream endobj 264 0 obj << /Length1 1779 /Length2 10638 /Length3 0 /Length 11755 /Filter /FlateDecode >> stream xڍP-[иKkpoi!@pw!w;3{U_}Rdt08@]ـ윂IeWNNnvNN.4::-+Nv K/ 2s}I>);@ n rr89c,2s[ P 39F &P@w=la(ڀ3ZA``quu`7wawp~ 4@. gw%w3{l.5\=̜Agl<;A-A΀My%#ҟd/߁?,,͠^`5 Te]=]YfP߆fg3w302wKZJ:ۃ.h;,o݋㏱A<>PK-X9rhCNn y,EhȬA^NNN~ yZpC~?GGs ?puv[ X-\ k0b՟y`O3߿OFܲtB1c:,4JB`99f |V?}Z &Rqxf, 9y9-?gQ/zd ?=nWvx Kj]͞w@j .2`OO)`0؀{* G噏@K)`l%8ء.Vh -8$F8j H apX~wa/pYl > >'A9 r8<϶ϏrG K'g=Oќ\A ⿣*\UV=5~ 7j]Xgn҂@ 9 `ۚ_dl;c"t;o>1,8b!'3U[sOYޒf[|9lCkNRo7IИiA6A7(^KJΦ%hU.Z./Yҥй*>E)hYbj$W6 fSO˫i'J4u؛Yr-.Z}b KIz /} ֜G>nؿBwT4~9Ӎ 2sGE5%Q%"d.+yʟ7&T!5X&=֓\v>d|kscwWу<*3B:CY>~[ZOB=Cn"$*8虠ơ6xI)4F<*YK[dHj_T,T ++G./?KTmuS3i$Kb{} fJfpab[ڲb~!\zuJL+EY$$~uLcmEiE< t%gu#H "{[-B|1i| ֩6iG 8\ܯHh6#ywmV3#g\ y~Z}%bDkxlЂ |xהg="6]([XR| Yf8]/`CGi*ow:eM=fZ+:BCQbFH OĮSk|id5S=DO9"MppϚkٔOQ,ڧHWztO7OvT礽(XQI0 Ix{^f18c rqwO< %"kG^Wiaj̾5&l& Lt YTUL$XBe\]2N } T\l]B4;78qM>mL"p:48i٘9*&Xf;9ԶbЮMI`!$,]e6g 'Ku~XPxU27- ;hUl۽I䧗%?9LߗŦB_iX|j0L9Õ4|0ى"T7{~Hn'X3Dp%}(`ae3hx/c` {|=DX8:]Bx:>ߔKqbw"*4x>vp]љ6ރ}!#$<;\ tw48>u"RA4xM ) EDӇ[9~+tҷ^m焢uno+9Sf܃'hqvڣzHXwgug:U̕[/1.T1|Nlq '9qk>f/yz@Hg*6Wi,؂~!w^!bT2@iNZPvcF@g4wvs"q5+_!wNʭ.Nh z:;3/Dɵf+$:EwjmX"; ^uѸRdkz"܀a%[M#B!Ҡn*slvi>9jX%/(ZG"7uuIK/@ꓮ Hi/W\@ܢyDӐBHeڧ8|CsAJ=Vq㎂ݶf <3ƭH&V` _ ICLX !fHYh5t8`1h{I6SP)d#H9LYjG8.@ʯ!+yYDHG& eN) 9$jhXJKrGJfCJ;)?.wߘSV1ZAmqv\+R 㗣^ Ԉ<+`Kqj_n"cPXͼع^m? NBY.esY{Y w!.ܭ+d䟴CLaRۓKvDv`C"*%nTmnv^Լ抖xH`}1犛:5-[1x0 u$ Qn (4Fʲ>&4A#n|oUo@4Z'}6BƼ:Opxj hd C6ףDvZݸ[ItM9kszȤ-U^qW)o}U<&8IW]S!񧍀sh^FyG\ȏ|qr-颃F>rg@>[1:*yjWZI,t+L!Ƕd\%i) #h+<sh~ XX;"߫ G= OOZ#wN\#hWzҜH+Xqjpaئc@dgR -}Y4sfb Me7y T@$"NQ*|\_ۯȈsd.=q~:,wX(V6K~R |%:gY|(<}[#GOci,3a,NoP?VrEP1a "[KR X.|"|`/GK۽KA@;He#mϙ#N@Nul zoKTaִp;ѩt1#F_1$֠6`jFB͂[rOBs.Ƀ'C,Q9|s.u۴LVIiMʉBD)wc{p5U2חŵ¬ 1U/]a/t\3\!-p;&Tl3-vE\s\zIdh T~72`Cl104lvذc_ )8}+e<wGz7ި4m&üzur/R g IO[}j@h=vDL): ֱvm0B[2#+Vv?|L 7`яG ڷr}t!R{× J`2k޻ǰh>2Ty(86qH { Ɨn,sXQ3=FB٘Z/'ڣV[}/꩐Uy1 ;fzS<ᦗ\ rFFI.ĒoIeUu[Ȋ<>/Ed>/bi-)P2;uZ$\{ާߡ۠=%=p֖yYuC2M36>D^%jpS(ܒ<+l?5=uƑQn}hEUz"$Q˫TO0}qB~pO''!CӗՄ;!QԚ{W\1a37BS "ݤp b%Ԡ#)x AlHr+_͔ &#t<m{" >J>Gq R_ULPzfط/!_@]`aj{dy˓uU%&㹦Kclm)][^NBuFw؝XC$;rG+Mp5}/ %x|ގV1Hپ*\[jb(:t2ZD(TyLGս",6ؠ!K1COEi!H3۫t:R%QiSM^TBDE% 75˛TE9>pDqrش5P}݁$TTVoI 4[sK&NZn*- k*8qi珱x->PalD;!KQy$"^.:tq0pح#j,Ө(Pwaw[쥠ca>S(:J[z:W_"cq_XJ"e{]C{85oY3!]uƱe1O^w=h9au,y͇n\XGHo.HR]D~Q3:]eSkwi:=#F Y dߵyS&e}j敾/fxbTql3&ߣeރ{jK\b4N3e{ BQ++ /yX*Ћ"iy\1-T]P1-yQt7;>>ufaDN"78ߕEEoݾ7}*?7R`/~ށ ~2^Y.bbi;3cadЊwQ㭖R*V!ٔU|}<4-|I<k#ӏx[OU:A% 24b:m7 Uע!̯0>1Z# K$  \Q~.Dy /۰$FQ}Yg{$uօA̪_-?G#("b+_b;:LH$i+x B+w\v69% ?t{ oBAa"G߈~hVI ?"_JNQՙ˰3h D7I5CR-Xu"w\h1OG$3R3?v)$fUO것5%6Te #h4j4י~hInr!;S'BU!^1F@|1.a$jTQbňNNF\ a@ ~&:]$-Q#eeXu.wgX6U-3"YR(Kf {feGқZlf\svo:@3_+%nZa'r Xgz(C/njTׂtM Q5ur&ܬfXcirBu\,k˨VNTyC^)T!6oJbm# ;|~A K 7 pU΋w_X5tثoNP" ~ _&(xzq[bD5ZvQBYQ.@jcѷа+Oi+Su, +4MU@sza\V;f*a#V~ѹAi/|яB`qf)бGGlNzn-vCKʿBHR_5JAQ_q|-e?4_٪y͂ ypb!{8߈r8$f)ks@`@6dtcRzx?Q ˽YGjM)}^0Wy* #hX&TJ'iUD4@H;cB|8acd_;SfɝUabZ7tߧZ֢["Yd#R -~p,&cm#[N9g{a! q 5]Uڻw1Qds!uCj ^*wI _x0Uſw5HϘq#/+|W&ƙb31ZF ɸ4n݁s6~%  rqU%Z t7. J/L17j=Ј5$5ҥ /u"0TXdI5gGLj#H8[Ͼ6GͲsO!vTW8GlT CG@(Ү~SrU_D;o *!כʦQjp@q,{dmޟ5z$B#8PxZMqSRX=Αfi ekTY[F\/.6$[)[fqjy ojО6p諸*1R'MB@]B=nM&g._),Ў>.$\׻?U-uA-67cp6"v:MlkR:m盛Oo)f/nꏙlg)N/FA8wqB͋<ٱL?b!3!u)do'č܃瑼v-wys"ȹė6E7Q4Ԍ=$U~@b M Y'5C=CQ:yw8K=CH|NElbV7޻.1< ',B1(+Bs 6ftDNU륺n/D6 m::RowFvP, cXV)3Q:^gM7y.&^$ڌuIyc+$ 3M{ q0̓< 69]<@\U3r'BW9U3Y±WEpn3zB "|Xjy!aS\i짇s)! V0Ӗ3EaX=݄{{xTV+fd.{&_Tck$g>xX l iQp1(x-2J{WJk9F]u$|[!!xJՒe=}7UyGd7!Pc3yހ%{ IO'㤬n4V%K(y]5I(J$uGD[ZI{kXĭDCΈXo_2>H+N{R9CVɥXQ, @8\:>`/4DKS+.EXGr+'):̇ŤYjǼݦM'*yxz:nlxܵϰU<(fsyʲhnõJlFIQOmS=W`=6= }Vwrr>qOKjL] BbȔn5i[~ԑ0ѹoO GWS*yUq(wZ Q+ۺa~4),?863~~õ x"dnd}UF"ÿ0vp|Fy0Ar5t={WF/ =;܋ߧpbTTt}LtcJaX:͛Š%2#/΍`0lnB|( 4KM'+ܴ%tդ ŌĠU+M\_ ذ<(?P572apvϗб|cSvH첾e ?9φۗeyW+H7+AØ%tY: |hq[Ef{Dh+7ePKOy(%.!k6A\{w?˺9Z~"P.SPN.ճULp}t*4h_Psۚb{ ٩"rf& i v`zhf=> stream xڍP  2; Cp 'ww`% \ޚi}WLUI(PPdcr0#RQi#Ri 'GYHfno2I37C%'G= `ge i(1TN`[<h-l||<`#@dyOZA77g~OOOf3Wf'0#fP@K%ƌHдpr4o{eh)T+e96f@ ?,,A+="0s doff'u3¿s\]AG6K9ZJ898\' -9:y:Y-(ݙEMbee]@/ ?hz;T!~`Vd|Au5@+!,Ans5ob_ /Xm,1YTt$.Jqq'//7;y{8fyW ݷ>3@7 !+qߔu/#iw{?@[M(95J@KʹmD31sr%J 7 /fr:`LlGcvodrpcعf`7Q!./RZe ۛ Ds! qXA</E`/yTY*XTAoAoޢ2XqŴpk$t_ :[\me`Ka/ `Ǘ󍷍 do/_۞+/Fo]r~[U/F/_-ۿQ737f; w0~xk>@\Ytm |#d:dD}/q"!xQ,;=qk._V,?Js'4ЯSWEw ==8_ԇ=oEp]rei 5 ˁ %U+ 67-Gz-:yB,}50ε;Z "<9AqV=<&P0QI=%цvӚkPO_^6$F>*2!5;.v(`r+ $+^lsP7]yr'o{uf 1t/ZF2V:9;)T òB^ζ'X3Rax8T{ j$61"~j.BPJUܒEi'=xkE'Nu i\Xni2Af*FV4‘Gy`t΀Sݝ\YAk}O> u =[nπbEVrT~Vv**dsƪUrζ;p8Ysjv|^ɑ=$VB5fg"lFw= C15{'e%y'|tD0|)[s8@#B?qVJb[=3'lɽx$|6ؠcIDa8JxQ99PF{&xE&857V1 ixӜ{!ܾAɓ떄(iډ'M#$yx%$El{g^FՐFgϚC1d4-҆UKO>I;I~j&{ܹ;y7ITi_k|\gK2jH rߓ K*HzT8E 6CgMmY 0l(t?nȺ@ٸoK9ܝ әwX ik%. k¼\ ! QЀzyL&Жo~Wzc]OިIg #8g=&؏|mTj MOfqOOHJ2qb^Np홚M]PG5-Aˌ)=90(jWW/l 0z 7t8}+&S/L43)>|vO3O3zgUHd(B:/nN`5NcG\ԗgb3i眞+6WLKL3>:g&FXvc$낯 8PUf e1LNl 4?S=%t/|*gfD=Ȫc! %UЩt>>CĦp~[Jwu|?PFfZ'?VGR-$.! VqEX [G ts„V\OAUX %6T&$`JTVEN~zS=_2(Vlڨڈ(<zx%q~P fl\&[}Ix h!J <U-8Ҏ$n̿Ի~9<޼f}(`=7h_WѰ%D*Kc̴>K^n5"5IcPٳ^-Q00\v’J#ˆp&ՕQm*~U~`_¶1O^*?!0pF2 =4_Ƭ^ɻ#+`!xv\CxI+\YZ7 MP[?>@u#è(KPr`oBtW +6nȰ֠p@@!.X<&J{^t%y &g OnsC$mݵ6L Vhgw ;F8~LhNr†utwi|Q~A6'JK:$XF I24_s;Ku76GauYe݉=ɠp@j\+!{>LRM! T޲T0,z>(Ҷ&UA Yi`A=VicՍy@!Hwh;_yybf sc:dq򑯽m;aE/I x<~cNʑVKp̲!lʻE=hLbF6i4W5,CW,nLaK'\jiu~~+x-!:ϯ*uWο^ i x P*xV5SE['ڐV"H5FI0i'vpFp\r(ﶸ)aeQ ֗Ht\9 ly92&>/l{ٺA8B ad6e: V+&?qW~OJӨ߇'b}J6|WƂ롻 ڤEWiiRPdi_}ƭ̲oMbOxTv^h~|3ܕRo*";'/4(_Jf3v8%Ge ˺HQ*?^O3iEB/G{D2:٭/UR3\~41~scD"& JE<夬-W"T n^gdGo":e+.v3VKmn-aIab^.CRqO&f.;=O䲩}'; &fx”zD9iLNh6n]:nءpRCL Ī| >^Klӣ~Wɟw2AȰc 3ŰLN^3nS9BJ3Uv^auk]>JK{ScroP!^´3>xaՉZ~f\su"5bu0>Ҧ+k1. qte/B#]arØl.?H]9-+=QLۃbѱI<>Z >- g$<(y?M\ܚANR|5u4KY?RfHuanV eN-z,^odiSN*0b2]ݼy0Xk3*3Z F>Yɗx*7Y5X>7=x7z1օBƙاwI|=Ҋ$xpoEŷqk뉮ĞS5Z-0B!gڹϐ]}̍dħfڜ>pq% !-G7&ULDUvLeaN\s1X29'$, :9'ؗcH|$ܸM"7b^׃1%Vtmԍv;$`gQ#q1)S >Xe:W8ThI l#Td OMYe7\+&gEQpGNb,Vipu5ru y5(e#a>!3U!Z'e#Ŝ\VkSҕ 枏b4D#>}@XCPml$p|A%D(ikc:[%uQ D:<]_A~U:*|SzlνΈo+̈6l -+q9\Q7*rܦkR;HdIat<$20(-WDS+fC@Rho]4fl |׮QYbEz! YS%Ğ?G^BΐK 5xԼ^S$]iՄbm6w*?sE>Ac~(1L g/VwO/橴cϊBiH̿3d=A}sL+p9`">5emAᔭjbGޓ5 yB@iu\_b>øAUa-`F6'wFF\5KO:^BX3h3"6\5 I,ҥ~ i}eEޣG6"Hϡ~Y韇6ϧ7ן?ҏ;9,l*Wu\LdGxYO)#i%_pI*o3eڑ!πnv<|o+ J *RJ}ѭQ*~DQR9i1Ĩ,9XWGH)!Bz_fv $R4[;ovA(& 6 Pt+L4|~uS!dA]`ތm)v"ڑ;nyfLB\+ZSa{8pjW+f^໛]_UT~)>uҧ'Lzr#M}d)_K.2i\<840F$(&H058T h%PS;OMRў+J Rl²;au|cNBwArZ#f.*w-mL]C¢g%hUb4$ϯ^Ӕi[{\3Zu`ɲށWܿv٩!S 쪥/>]F+TmxB>~^)0N‚ n~JLcPca; ݔcR7/x@r度l:ğ rC& i4V[v60b]"SVP'ѿd|-($Y' tp~7~~=Z @O'y-Bq8Gh'8 "ELO=B !gjwIF&gX-h]וNpr4}UÆ}=vڡ]ڭ;zHo(Ui;M-:ƌ(M(^?vk*6۲k_eY9<ٱASv)p{AJ{CTI!K'J.ᎏqQo4\d[Q2z2~)95FP$IOChdU$UzZmPuM)Ah%/TZ1b/K%ruDJMw󪒑sB 2gnNhYѡIS(WYNTf}. ,xK%ΟP;+pQ =g2tebQm(+%<`$4AJ}/t<fhfǜH )V#OQ,H }w P16ʗ1t!9DЎ% Qg?ǫMGn9m,,> _yD*saٷM49FNa<0ОZf' -ܟ Yf^(ux:QGTwrEͩUŜkE9&i6w%4)BS]JГBƔϑfMLd FEd9Kr}i^{6ݤ剺 h|swb!>JVɧbtގ|׺z))a٦I'1 0@+۩mZ;tv$G|K.;n !}$A^nSHWFyé Ğq5MjԌ If* AA"gr1oo&-B3*Ne;\JI95WڨK #u:gFlUdsՙ 艒!Ul)ŋ|N%3("Pɤ`ߕl][^zTxoc-Cݐ!<;VARDA>=Sad226rXԣf@ d}˚DDz|-?l=I!.5yFy=N Eyǰԯ˫V@[Hq}KevC^B~|1 UT J9+(Zwb@% \Tws(3:\v-SG '4v5](g|Xq֫@p8 Sk`S:K ?O WIRXf/ do$sB .;c fNŦ,W,,2;_N*}4ҍa@.Aw$PO-9i<\OX”;gp}&4 fBS=͖nUJi0.vV`xQޢU8u *Gsy%iդ-=]Pƍ\I)%AC1e'#jeKϣp`j Pi!ܷZtkџ~36r#|vǯOx:I<p̺])uqPLf ->4fIBEA|uy@C;NRcRz^rv9ojÀhFAAFsUx~h6S _iip<ۈ!܆B#j^.>z2iI^aBZ&^`FR ^ʈ0YXְt^$'xk~eģ\3UR޼-s('I- '϶TJBG3GgGsA[#'!ـE>c%!)$}ŚЂcPp&JOrrI51|*) 2XNYq=~Ak~2ݩnӋ>#b_H}p!VV,}Zr[Iƨ CFRIϭD.Vʤqsn|PBY!|ZG.Vm80"+/5U}n:>VY4~(tE%&í _+8=_dB圥:˗v5"M|r?Q/sJcjGB)͹ ݏsgF":Ϋ*tc*ۈO:yUi#RkLi֌]ԖQSD1 ʂNB HAhW^S5Bޓr8HrL*#g 's2mf"ZގQN~k&eYe ʼ1GdR;qo/=ZK+v*]v-&gq`=,TybHdd+\o s5`^Rpų3u_69 z62 83K_31[fo!?cXJ.ܸ%2x mvVOm Bv[|De`-56փkǁu[|t5S'Q`w9pA)>. #gfHߌI˭NauMI7Jw2#G6A|-av޸҈*%9Hu#fc-y~+.\(BGr_~58u?X,_xdżY^J0>k0 )CbڗΞP^*N^ULqczđ (٢ 6 #)4t%s̨Jua8Чf(7>{I/5sh\hRĞ́v~)'ShS`MByP|/6f2i|m :"%1(d@ ibGqьW9Kp!_P6*~˒ɤ&[>/TTzV{r͙w˟d.F&0pK<\\7LXDXCg̯~` =4;)] ;۝L; HF屋BvtTP dHmFz %7fd`5WGMl5ўu/Q"[T砨o;I>sgZ#]]o⤀>6 z޽V{߷o] sщ͗WԚFosjl]&w^1Y,0rc,-h '8\aldgns(u>q2n`@MYdTYbw,j;MtM(hдQ8V0v6×߶!czP5(Wa$;ژXr4\:~p7Y%=UL'6[s9jͬjeLxu-~2nNG?\E,6e~<&Qh*6yF.]1CVobtܖ-WG}dxrv;p\ 2KSr)&: 4(1 v=%M^o/ƭwcE2ɇ8PF y.*#B8BX='X({9GpX+G7cL=156 # =;95/«9Dl [p+V6@^");='aZEi!}ܤj~)(}BVa.śG:?1_&tTs;QQ^yHBER[2G8&Ë$PͫdBtϳ?^sջ21m >YhSAګ\2"r0ѐ2ֲLE*@&(0麃_R "Rf O6)Mm-Zqķ[t BAۺ Of .) cf'1U6WHW2)ލ Jkc7v(]W\2d:A@`P./.\G˞OQЙ J6EroUIqO';l'X4j*@YljQ>}i`Vb |[Z!yv1 ٔ+&Zyz9-M^: /d^U171:uIǨ_%ŗ4WkD((YJC$!Ց  V `'6lV.gb|klݹ }.yN+Mù*uIH,H^`,ZLfLDG>[)Jr@ M%_WB^KMj5@^4[ZN9 7;ŕ9>,R_t!.Idj$z1f^Pc|;ǥHȘu΁Bb}Dʶ ek]wQm&$3Yψ1F!Ζ{L>|P"*0N&KTղF5T'´IGuO_U?be֧g MiM"ڃ i-oa~rum+9Ty rr,]f0*b+ѭY]6f{Gd=d4jߵZӷ:Q2ܝ }~IpL*;u9+#cu)'}ƫ_gpP@"@deu6:9;+xGs%RۇfڳDB#4Zꠌa+u5?,MWt1T™hY<9BSK1"+}tnƹYwn\ZoB>T%ic"ev(={YƏ7V.p~$ub"b楞>t/#! LSh15̩Qdy-2;&LVq(2VMAh7܇M3L@,_N*@@bttbb\{ endstream endobj 268 0 obj << /Length1 2255 /Length2 14081 /Length3 0 /Length 15425 /Filter /FlateDecode >> stream xڍeT;w) . RXpww;5Kp\%J{~̏YU>=ޢ"WRe67I۹02rjj@ !QQY؀h4@NVv|ueb.`Sy{; ؀@;Čݬ{;3 8hM܌mANVvycK-8 @ ?!h[8𱰸3:3;Y1ܭ\,* g 6@9f$**U{swc',29\@Np~@dOxdePcvpaۙ64q[ * ! 0sCgS'+gfg+,Y~7ZLd>1+'),;{w;?73Wu;+GW"?2 yZNK[ `0SZ@'WXYfV.ҟ`1o '+.<_",""o&6  o %c/Wi;s{ߚ3:R0@g@SkG1& W,hk0 x]] o^ k {AfVW+b ^ a; h32sp-r)YZ5&HU`bk׉3x:RYL~' *6NN7+x9@33;!>Z.No߈ "qXD  7"X pL?ST(A? 3A?HgA&?3%%ٿ bПFc&a'_zO<LUX d/ _Lÿ ןl~=  BaWl%b';K ~ml@.}C#SwqW%ǖj23WCY5Lg'bqtS,.r@8:;%n eC lr;, .ݱ/<@HBC:kܙv'ؿr߾q @n3C)(#ȿISօ 'v+  %Ix^v0#~Zyŭ68j=?ɽ"iEa</cOE)?e>ߺĀAi242:'wXUFs"$\M˸ƻ-;e {h-A'QwVm%I̟H(; L~GIF4w<.]v-kV,sjf̈r&W!=nXpͨICP/-'6 \ OsC.hHj2 FdX'hEY#YcBS)yl?q 5]/4s|3n:罕{՞a Ӭ eZ^'ӍnAU/oх >^Ёq" JA~x-F6MDb{1[6]#4[}bu@ ڣ<Z7\VZ1,nrQ64„th *՘w+mw|q.mPʀ䒆v5 ?,< ٬2&Rӭ $jxbҨ/,huv [QE¬_ĺ\+*1Ay+*9C5lJKq`Ky/'BIGgt'~|H=N1h4'YvOo"Հ1!dD2JgiKPTZpIǷ!ӷ%-A6Usz2XNEƵw$cT>^I=hm$EY8C@ݼ0j(^;tX'fKd4^SI9Vk R8[V#7xA]k]'KZ/+Yo 8F 簡L05c'It{c6 .i c,?oZHp7j8)`d+}˃tWӮHop^ϛ <45}k`(W}?}l#=Sz30R:^FM%YFV2$tuh iY1LJ RD)܄1o2= KnWiFɁF|{M*ʞR),xjf j̓bIs+r a ?4rIv9u-y`Z$w:W%-*aU aX 307r=Ɉq0I jA-P.C9Lf_#]ɔ"0K.r|yϛjQ2w8b;h,-d%TA4vֶha /uxV4m5ݫ+bUV\·cX,xAP\>cUUܠsZC G85k[[{&eJ'M-r|||3ş)gL͢v8PԚMipxVy`GaĆ1TGoٱG=ډ]{N;lxJsR0/y9诘.B/ax+bqEȱ]E~a|;S2<)cn={.w&&a im3Mul=zeyqQkUNZʼF[H& Hf jh@ު(҂H`RSӅV״WV>~:}xWVvE5[ :x fbʅ1A"VKp%sd.p!%̙.rH|M>Q҂$Cʅ\g >`&BcU)ѻ&i6ߜ |90ZylD""0avɢ{=y^wM#Ѷl$MZ)㦙01-ؐQnnKj=򎾪 YB۶h'a7 u mCw_h[}g+DvpB{LRy\0BJmJ- x#p07p5}&aA^ʖNQA{@>9bʾA n9BcH2g\'7}ֵ40s1(N"|Jm#C^uɩlB)äL&qvEok6"Yb~ܪ.k ]­Ǚe-Sy5sR/Q(ơk |G'+ĉ;ցBJEdp5M'ghxBA:ʲn^]Z'>RA#ޏA!d~k" O:&Nf yee} gC>;g颷Y{"Q󕵤}G,cp3f*3xƝ#>F` Ip2 {nč{"ė5'ş/d$/ Y7f۞g1 MQ`}9*Fq}NrS$POxN?8HEA) li?(=I)KQ&\L# ߋK²˓aFG.r2Op@I@*U{ wNݑHh`ʎz ,ò9a64O⋄ gLd7g(d|X=rVoZ[@s#8 |d`c3ۼ*uOߠ@sMX fz"U1|iϹmKc_/n)q]!Y0<%"NmfKF Ѳ }ҭj`'ݣ_̿@>ڠidKF4xli=Fgsj,SAű\7vTbS[ (\sXwǣM\\*AGux0~D(D/ksǶ~B?WE&@iE/+V鵡!qNqG<^֓K۹+dcq[D(N[E-l̽kFzbi]S#r!`?feb8=tgČ0F0C_Ng[^UPY84mm{HEg35[!A wCi2,s7s gxW)j"#Q7'w.8XYg+N]e౮k=X-ϷϿ+>>e yPyLcθaH@@Ua,*.k)%ѯ2szwa]]QS;)rƒ} d[~/Xrڟw 켙ǷSt"y5)HA2)߲1f}.0)%E9RK$jN2_|~Jzyd5ufzo|W+q"~8L^ⳝz6c'~~⸋g!Iu:)Mi0)Srj/Wߪv`COƇC3뭭-):f?aiC!,&]Z+0@.Gf$ojKi6GdO-h̍JA`_AmKj8ՠnAQi(yO%C~|u}./X-Wh);y15ώf~l2\2'`8&^f|(Zf a[y(#5*x<Ss0.#W[8apP>RIƅO/!^jv NE积R n#n> C[HZ0O?+u61 "Cg΅ʊ)T@Ay1諠D]Y.W@`eXEhc ;l,B&9ߐSzyؑ8D^c-&4yirvq8ItW{,uXv|\נvr+Ɔz_# G 2dQپĨM֐95Hl 8훇.$g% sl`IHsK6`t8.p(X(|OW]}gRϙ,6kb{t,hWu nxjC&Z ݲi\N f'i}?slSiQo[s$ I"Z~j J"v|y˗zT5cB70'BNVװgD0t}CW8/.Wep1l˩>U䐨,mwnqԀ*QĻP |lK\Em7)Mdb),PiƯ"0=NZۋЮ9 77TzVl$8ǿH G⶟-rC:Fb_lmo'1nJA>3됾Bk;{jC,o} 瘒輲]Bt0iP89 2K%N|R3>i5.aKrhPqx(yX“ 1ζkdPr-gC[§`ŒP"`Ԁ͵BYnNλ"H9RuRS],FɈW\}67]檫YɯFݢeԥGcaR1,F`>VOq1kzLIԛԇϴٸ*'H(]jj)A;kBU o?0)+ϣr;Ѯ'v(K)S B{r6r]q-eAz4ā."clxhraIy|h?uCFHbJfZ W҅Dž:83--0Lkǩ)Do* t]evOh84GzM r5q/} ^M ȊTE3}Bd\w؍pb bkRȄO a߬,GZttp*S!mr7O%]p0EJPL tdpxS6yxF/܍P^#S$8M,yŽWHG ~Zv3y㲷!Vb^dSثϕmN Q[s 2~X5W.J}37SpD槪G`i}k/Sl AoxhpX`q%39—MSСdSmKT-@ڇqn/|D9`+z4ă#B%zes1 &lo>t~>^:"~ 8f.CNٷYBoptPړ/aP 'e;' ,aHnτTQJE. RU1EEmQmy[| TM.=3O֝.ȭ&/0F{h{VP;NHע9r=a%cjZio pHWwEM AwOQD(?溽;K׷^^3})۔QFIR6Iz j! 3Zʇ "K@26`"̉.V7Ef}K-HsX<;W4P"Umb"jDȪy{ u?a:)4GZIvjA TXњ@vPu"ض5dpJ\SFDlSI6*%ڟ؄ofIq( T]}b{ƫц @tR6rkux'nBCpR<ȁ)j7Ia5hfx'烶 [&W1/᥺TZ=Mؒr䕯ds~<$Crdc]t%FKe rB? UILCdl@kpaI?nY XPJi0{N6pV_6zZ'^chN̫B4 9V:j [E)V9Tw/"W<'g[mWْp;GqHZ]@OS~rf^ } Gj<Ifd;['$K&tOZyݯPʒÖ%pp\B:a*Uo+dl"+wWGE5(Ue3xZU~R_q} {۬CG@; +)S~=Q`1'JrN->iw݌WYI*.<{`L&Āot0C*_3b3mM#Vvur9j)#R_>_~==+A{wƦlZ/ҽtBTݠ~r48>JȊaȪą}yfJLR#(ߩmj]'Ӧo?/EgOTX.iFd/ѿϸuqC3Nl~ywC3."+gӖya}fAjX;%g?J1#[ pBX"> ,O5L:f!A'\18Sߠk,tau*&;G);@f/m◒/X'd;"9{p*} N´@'Efª͎70wN:JqӔq+\#XB N%rW!Ok>j-3~7] ;T ˔18fMjsl a=9u6*}ݶ#"zJ3AEլF*<,c<,(!>VǕE3+,NT~#竆o1`ǑYktr,W\%tFڛJ( /h;zɝZ9@ ic;YBIŮDz9\+m;Ѯ8={8UrXwa8l Lb) $ YGw0*T<mH0PM79wWŝe'EiU[r[qhmEJJͬ&L#-+9/{sķz. 1HnG/ܧUKπW GE.'Өns*?l ̋8Xb`-cLWfkaیZ ^S %2iwQ#ѝoy%GLyk-+zp7d'FzƔJ:2T1zAK2 9xۧkވGͥ|D gb>fRW&&RRqztAs#NaȶK& HC1p-̼L7~vU+wO~LF˘`1P V!9[S =(?!']#ڰdq`᝷CWU-[=>'Ҽ}Ű݅nH$3*5_"x1tNEg{^G۸]։96"Љ\8b27m.1tcqF1(\<ZègpO0Τc?d*+YP~"iK^;J(SNoz$j~oq$IDyٍΤrb'#i܇7K+ؘPʄ|4 XdrﮓDCûK$Kk͹T%;L:dtE7S]9pgXolH 1Pyş;S a(Ig5 X,ΜXN*|B]F+5ξ9-jϢ.%zGtvUvg`;nHyH W:h,/znzZg.+@eB8mU2+-BC썮ET|7R㨽e>8HLa ֖ʋ<3O"v}f》uTS4޲\dTAȵW}\%;~Z{O9Þ%Cf{v#ռD͛[ފ0dK]YdQyR:exfIblQFYZ%fE6(jV][c2;Z_4l.6*&}(dfh%Q HsHBtx?djNQe6G2W'G,R j% ++/]Q!TmNJ_S~1>ƽg‹n =&Vl:NV럜C(?; L'V8KcRo *~=؜Or]YRLWG@@AOԖ&_ǥ :tˈa2Vq7iCU`iaQ~'3tfKQ Fg!p FLuWqFjP.=  q52nP-Mõ  ntLC̕S-%;R17R[/  l@+GW\%D n䒸a-d Kfie1lI*?§oIV{4q')a F |qLnF/3 C5T0ǩ}{=J#2D,_G 7>B)AsLvUqtmiVȏM.7q %sJ۽=nǩsN|ܸpn&xlPdd`w~-)2%Ы\uimIRw11w_plیͱD{I6OTvÕKU܅зku3$ tvogWnbǔdwI8KTkwcx>C_ĵ5_l;Wff<̹;\w熗_L֙ѩo`sR Z1c-|#TQ-J\tc!J/kͩ_^f܁49ߑT˶RU[ihآn#Fj4u#L0dҷ[ۙ׵%s; 6 @{-'oN>5|WұQvJ(e{n' LSPCb ̌.c2Fu80{k_[8)K{p2v\=N}$Ny ‡E}c|`SG W!/)p_$KPy'F->Cچ Y8wBw0G±u{l'2΁K"wCa"},[461 ɦN-hH+Ԯ y^̟e*t{̍Dycew,IՑKH ᭰#YJ:I`v|[6ytIYyx6w'TF> stream xڍxXm>"R@:7nc`lFwtI tHH(HIM}?;v}Wu{;DA@I@!Bvvc'd7z`H0<`4S1D$  QI$%&"=$`/@GD@QJHw_3KPpz `@va2Bp}KvN|o`EA=_-tn? a FHG7 p@a\<P&;HCEE9_x CvC H7w0p8P#~p`{ w`O(@z*%FO`W"W06<MP ? Do %DEE@C,+;7!pĴ 9B1(+BP'105=`>+ F~ _W9 p)eTTD$@G Sj %{ן3.\(BB0oT+*Hmn0Fh 1oՁ:<۪cAQ4?_8 :Tnk0T`a ⊹0mbfyUïa=<ƬD T:@}~ (@1.LGᯃ`O/7 ]4О2(䤫z[/mgRdV&gv= 1mKj3_c6EZZaxA/53k4B}s<^P u \|3EQ}8+ =;M]ϑ{|_ê!NZt D!B;svvR^j#7QEk!m򓦃 qۻԤ,%'XLI 猵7t ,$#BH(\*}T&E&C<8qtC`/~AϷ[6GB6Z]veɰ-E#٥&A '~{i9Șjb3cG ~XMr5^՜$Ҧq*jqڂֱ\zVʇʀ;k5:!8D1_'„fXΎ̈́p9EVlZ.܏z?R3 jAoI\O hw!rN+n岓"E*GBkBkZ+ ):ʡOv$٥]&֤ikY?kc:3)䍆+]XJK{#gἎy:wrփ`֕nQd`eZzCS,_LIՐ-zL*헬AOy{heӷM}jP-:f+B)ԬJ57]A6LnlxՖ*Ӑ~W*=^f,_ZYU֪o94 2Kp HmGH;]P';74.m+r(J4\ >ߓBM5*FQD{^ƭ [3hfGݑ^L|627lR#wڰ+3!E2G#B릊 go4;E} J[#bӟI" "Ԉ/S Q8nGOؐ+;8^/^Uٙ |5rT:]Z|>\,V{NV}W=U&pHGK4]e?iwd{KckrqxFKT+GDkU㍾0 JD uhkTVƕ Q,q bb1x &;~5rZw?8?fr`H`:cu<Z\k4_I[u̎V}j[-[ߨ6}>6 ȱ>ݒ#?GӲDS~xؖnmH6g1p?'xp!zZ2s{`kY•ȗ"7 !k;~<SkӼ QP1zs* pȾsW]&W[ ۮ xˆ\gmɀ W{nXcptmT5O(Ғ{ݽs\\ܗI|bf`.z>:4'jA_qK`UM4t ߺ T@*>7`ktrZy5\,Lˑoɣv_?g(s@)W7moF}!)^ˈXIUݛ-.[NWcެͷ(Dûԯ C}Pc:ELtP[JVԭ2$cGHZ}3 6> ^{P/DpeC˛¡iq'E2.$xA_ ϣ"rCbdbR,ۏ~N,1<ϐmXӷ\~-A'ky8}LpP <٭'6 :}#f`-Kn}nL?y-+`tqj9όEƅXg "תq.@?JL+wƾLWlELjh7//Fk LߋJW|O]X{*OU,Ci1v1MGpZ=sɯ]9(.JQGS`s5 %;cߦ,0ޥ:I yBs.Hg7n_x£?bHK|.dY޸e@ ˏI~N*o]<J3rK"OדSR/P:pm,鋁 kqUаѹ n6*"sD4Qc4y"]x9 <_y~ϝJtIMHta/J:d;TŶ ̠uR\Õ[Y$壯\ Ne5 Cdt/"ot#[pɲ.l=u-@]`}Ī'){^Xu2$S:́!GQO. xRv3T&%?]Pg5xXLБ>eS-plJ/~;R]U=gp@1lPMk^߹!HѪGcv'&D Șoiʑ`@z:3=*}SY4q.А4 }U]!W" SSLI0NNi֢\RBα7I3:)JrɑdYWnE(M%-3H_ѐ+`1.~޻yfb<VS4NEVqO&)||qu:`|>`gڱrT^Z,I GulY="7XWhH4.qjު/;p:%PݔA'AH\ܬJ>UɆ]Utbr8`*#6){1(tpYD͑Eec94pU?]v>wk}"Mw{ Y~\"U# (\̳w,*}OT吴}.5ď/$J)$U Q-hrYcdg.;»Yl% J6t!rvn09ߴ+?&nߩ!C3TYiГ/fI[&F6{GFG7Wl+t* `-k|z-:Ii&Uڲ{85b]%Mv4*Y;VY\0(vcz*߸#όA - cִg>8ED_(u+k1ѽvrv,5 ڍ~f!U&\elEDwaܲt9\Hi,Ux T:#Paώ?R?Y斯lQ̺eJ&+RUgI*ڋUY8|ڎnWD;w(Y\y35+`8EvQ;1tZl~zIuzBd=>ovz+:Mv\]UsZ4|gz=QCRWpFw8mt)t{KpbiU%+P'a 4U䂷oUfyIOYZ5Ӧ} ӣ:#3@2Rj]¸ͫsj<5 ?T2hXrdAhEv3&iɔ7Xɂ K-Um.b4%gB{y![< hcB? G34\ endstream endobj 272 0 obj << /Length1 1409 /Length2 6124 /Length3 0 /Length 7090 /Filter /FlateDecode >> stream xڍtT.(ࠀ0CtH0 0 Cw#% )R"HJwKw#]"({׺wZ|ﳟ߽y>vVm=^Y+%T G$zƢH bgׇa"v(K/< F10 @j~AED % `7@C]NH- Ϳ^.YG(`-#C@`P?JpJڢPN@;хzplP( j50@3;@CXH( 8 P :nEЛTZNP߳_``{6k·@=V`:9-фߝJ:0z@0' ׈_eЧG8:B(_)P=np{]XVֿru>Ü] )h? w FYCD.`7(tz?WD+DG< _=E wMLd199_+.@?D, m\U5 [1ck.?ki"Ъ8#r30~KwMῪD ):8sa#/-ZW M51 QUmY Z̼B| ?8E ҆ $j08TmAg@C b~u;E*!_>H'-'aa7?ڐVPJ:`@Vt] K14@脄!H$:LkPB4=< i^.λ><θ#B1V3° Ff3UQroz.N>@Y 6C)Wuo?31pghfFU˦5#մeʶ56#@>ŠŞ5D_xƦwgtv}V&RFIOƚ՗EOV!'M0).}cc8?[l;=Pd' L@jVod]jVR?I pB= z6+W/N& 쀍2#Z9Unij]F.m~Ns >S*0b27^I#2b{a&ONÑ+壝M 9y">ӎa:n} Me K㈾6BS֢e0y&A9bNhz{5Irh8w2|V={($!ʷ'g٤Uὰ>@XZǟw1ByD^vt,MhΫyi*^R^M_L2kBLT*/(h_P d1~NaUO$=58Fs'Ǔ2ci74ӥc9qGOzs\Τ3/rIa 6JO3gpcL vI;qv*ߖ=O#o酔aɉ^eU4HpKܤ&3Qܩv򣮕e뷶KBӆ<;o[s_>l 'E 笯9;ӒPÛO o ̜ 4hroE160w_|,E o;^ҍu|!,e6$zSX>n.e՚@yN\\EWL2t<(.5 m^MW`r6Ƴ F>D!䅜1G=Y+zk/cǽTl5j`qo?YsAN> Q5*91B?\*8IBM RWޯ*KB}L?C.+Z#:+ GIRjxOL8y~|io;%~ /?L&~7 -Q1q9y%0E$%!iw.%*iqvgJ({au- r#=$D9u{ ¢Kv+,G_dGYK־/?TȥO/3rFB/s8 Ǎ NG(|fI9h΀2րRl:1soW|Ut>F[}A %;^P'&7`7۔={6qQ7k]wf BۛwY'EKn$}mu$ڏUk"sb+^TU5?TbPU-yApyt/: SVBrbʓ\t+U<_^?H|,9^?~Xr/N?Kf϶edz`GE=YpwM,"Ԟ-+_>qL{4DJYUN 9 <\8?%0TD芓h[T ƩW> |0Vnvxji}SػѭA[c4%.8g̗{+?T0.$Zlv"s=n Vy" Ŕz}V9Ay"&n%~b!5 fluma bT~B\z=]_x"LV #yxaF],%rhO?cug+XuHgEIŞa`%VإKor2.mz NhCeWF(^_-Zu/cF9؍cBCH Ө?ãqLA+6p-"BR/F \l[_RVx& ~스?d(a rf%& ZeO8\n[M~*Tc1Sg`7>߆gscRe[^"%k,}eP.g:{HeS+ڦ"OF p:S"*sS-].76"4\ƃ"ì;FkO} zZ{ Hݎ*.ju f(zt:A!RldpGx]Us#2BxD 3P:GonA? B}jc2`3!oyJ y!>^Y,Qv,UmқZt!MCVz &t>Tvw E,-5+HeRe:9&n'2bfʧg:έORn}lnwMQ.(MI WRlgRHqϰr5Y0R.덧4f?PrV-f0ocH%Q2}[ j)p\l<ž8*"F]$xU҈H[TBEnHL}%ETA~Y=-Msͬ.(3[*rl( n 9X՚=+"cMIHSz'=Bܖ-`')xW20T'vtDNճE*XP}>=s`_ hg?[}8Ʈ#fqyS3 JRi=*L5>Ay,U$HxLeM`DxE\wU ڳ/T0-frxViroDUV^0VٰmrjNeB1-ޙW>dpj&`{/8, ,*UG*^ # a#W꩙+Y8偏-Gig; ]SVTKΰ< Kt?] Q";-_2ȿlI!p@#rjehNE6X0#5!Mw99#Fg!9Vn~RG36(hd5x?a.^2!OQZ1JI1shP!'D#c~g HY]cOurWy'50 wGאׯm V)'H\5D ɼ-( "[WFT["a]*.nƅHPn4˸F(]pո9j0JezgkָǓdJv6gS,&i ߥ<#S'|8V 枾xN$XvJlF8=аG3ߞ͟?̎uŨP8"oav#:"4LaR;7.p~Ynbz |e//.Z2\?ԋ2ٙeu8=Y:tnoAG9fCUe98g {$ k"Ukms$I{|rAERVվ>!d=!r>G~t`%$m;/K~U۬ܡ r3y1z7S%*+YvSyF`ݖvYh.z>[p *øI|ᩥYlF]M/F°hzш:c鮦>@8vfMs% ?2#$M+q1vs"2g9Tl>{/~]TFO߿h(~u3ޔw9weу6yW6<\hxPQoLP&.D^\LsR2>͗IYĺ|"CJІzԕ:䝪}ң@g1V3b&ɭ;-^M \L %Ƥ낤Hndz?sͺHr >ORpG΀vJ2L3YLw{d3.H1OGH4+߶v6s%NRCCtXCbDooc`?'{1zJ5?}we@ԱfuZ8Gsj٤t|&fb$ f3(,d@seLpOE,*)֞d2+Y]]D!tm;|жJn{C0q-G` T! vj'Op 9 Ѹ,G=i$Z >RYЗ8 &Ԛ8]:pr\:h;`]᥸ ,VIBN| kjڮ S|C.QbZ0)hJP0p{ XLĿT\Eb 'UI&NՉ_}E.wBp* 94;[]b^ii'SF`157TԡD͍+ jkA5^傑G^G }ŇgH֣ Dquu'r tz9rB 8OQl6E!j[Jh4Z㫊@!U@*~uDyl0]&/H@ ^s ǀdB= DXoVKB$N u8p)bQG,D*A5pqo[G+nMU;ӂG"o-7un 53וb\N oyVJU3͟h0¥a,e!Wj?*&#U]:.7> 9$!|rc{@R0q2%Ӵ=V69ėϥ(y|"CYFzPzJ<<}֒L[1Vs\:xl/bk:Jf˅$RɬG;3هٴg酆Zz,\Rsk)l:u>ͰПt4z\Ey_"0dpwsNg~ jM/% sqe c%HX&$d/Ԗ'%JO{囝uO~~ Ứj^Mr.) ("ν:YV6Npe1 ;jA,Ƿ]h$ ([|4]*Fb%$I/ƠK}wrGl S ۰i v1k?=5hc>.ԧ"Y+#˚ ?,M&JJ6Jt3S&+\ Hvvͳҁr:$0_?Ibպ qɇF)ruZzЯ?" endstream endobj 274 0 obj << /Length1 1478 /Length2 7916 /Length3 0 /Length 8908 /Filter /FlateDecode >> stream xڍT6LwĀ4)! 03 H#ҒRHHJwHHI#t}Zfߜgg9>L:emP%O iᱲNxFP7w. y7(yoS 8@ /D!" O-@CX.>n0{>,6~QQa?YghBPm N} H qvEKq`H nq/+CaA' ~wj]x_ A8@>0=h+i"<7䎸xB`N{Ÿ!%Y]ÿsq yaN{Ns̊p[y3t] js>/`p[mz 0Wߜ{޿mP$'@]Po |\= \vm@`v???H |<:uG*sdϿ5p;^Pǿn泹?Og +RprCaN>3끼M,j kt50"! Wc~A^>0w%7VqK5 ϛ A~0Q||2W^\}6  nnG`TB#!v7+,6A"Bѿ07E :Kx_xOwl@PixJه^7F@=/qi<7u%.gd'G_,킊M9Z.F=mƴ^#u}Wok{b%ߠu,3Ikc*c[Ya/HL46ZhlFK\d*zAxgpgE8cGV`uC Gqs k!}G♪c*1z *)oqey[Zs)}z9dP+f/(-U&TUZT_<=)s"g0NG+ `t[,G~-P/%+W߂GU͝*L/]1> 6ʧRP ]ف}d]=Nl4QO`SȮi* ]2qQ!uf]DiEƏ-xt$*J/>םtf7qӸF7aqZ#I{]vy`rFoX5d4`45҆'LC_d͠P%jm%]5',5ǰf_گrI|~*G- xW݌P,zҶYhXSێךpt6Pa~IfuƼdsJRTs֭\]ʂX$d4|O8XFLWZڝ|k$iA`HD%|hd}%0x.?z(lfM-|YRk)A3n^HN %G>%37qTR_mIMs|;h-9KT_+R#tt׮6Fow{tUo>_15™\`Mm\U^.OpdGBAG XfM(WېuuYQ欅&,Y'üǗJ#3NS,!unOq%t+ЧNh*ZLAI|kT^{dSU#^M9%bLݔ[}USn6[%Kѷ,2"m)2vBnP"Ti1,X =`\3LPẈWW17\~g4U,! f4Ǧ1koT>xv<9$|@KAܺT{sTo:6 .P#+7g!B]qu3'O)(;h!XROVt~$vWI3Rk$ h4e[RVns˜-D~KI!Wc1sSJRC"cд2F =KSBݙ:c_Q} *9;CgΟ Qu[q++dMg֚>.ie7e]ۂ!xn(u"wuc@:&$u¯[U7-n=yle/IK]n ZQ9<* HVzh?N.Z)xLԭ3e:;`ݑz{9EH3zn† ]#ϊb'R8`B8{*HBw~6Q5yd%=,*{O46P%RK!*xKtŗ N3~*,zd Bv =_msWoL\V}c}ηb^Cق{¾}gK9x-Q`Au1iC]1sd7x[nRu#vHǙ$! ~fVf-:аxWڄʧN˻Z 7U%OQ| Vf֞t~ᮙOǖꆤEf.V7*@4 &OTF=''LRvO0#-<[ ]s;@[3.UE4>=Q# $."Cu]Φ~Qv9]/tvJEcA)/CٕAUEEhzJKG$f/5M59K:yZ/桢Wuo);ySomAJOʾFϨ%D|;t; dŽxBQeJS4\N4gZp& = կG,`j>VtFѻws :8O`aBnoT!&УKo`Pq;h:+;+/pGX+u>I}SxZ0;]}ÖjяߌGm*1qLT.2m3㟵r x/o؝(څzT.0J`1{yz7xj G먊~J"d4ݨmA-5$񘯅ˇƾDd^鎡Iӂ7M Z(篍Ϯ="ܪ`/S OqC޷!˯h?/`5~u"$k7ɛs@[SgG@{ep{jR^3$|L%Csk=fgH1Y qcrl'n5=I&c;zgY F'Sڿ}MkAEH6;j3Tbe1 (4}}pG4q95WEre=+THebGզkNKR`q Ƹ0~ZD]6ZLDV(1Qdg3eӵMT@S6rLV[RVwtiCJgu s~c%\^O=;S#l,i]^0.D~|EpbeBe/zTWRǷDavD~VM (QpBQna-Ǐ`|3 ze:fЮB~%vw-ldQ:,ëoW}(ݡz>NXϹ ۞rD6xYXuZum :JC+#M55 #4p~Alb8%W$eEz W̬0gcDyr0՞^U6zxncح~c-!GT,6VuUY<ygDʉa1xAyUHμуgEo Gߌ޸:r|Z~3 Id:.. S^@^iɃ ]K+dxV~Uڊlz,ei&= \Î_<:,tPёnm9KΏ''=;ڈYknMN`k Fs]1faklwnB nk3./gUȠ b.>&ʐzΰXE({= 3N˪r ]\(`X0z@ږw4{vT=\ToN@-쯆egiF\Ȉ ګ<~כ%~iuS|p:ZomlyGAת`'Wgu>*P^Ok>NRzo֐}"Nz]9 `]|}ziKg%IIQTf-#]gp3b<3cHfyn_E t`T @ lW71YɱN6Uռ 0=1bi븛ȔjYreר9akdmyWCr\fO}Isc"s 9]t(=d>vԗCYbW=]VY6KO%0ȧ*n$*6$'KZ3rM|Ҭ+@ifB#Z r&=C'q-_nXS$P70/Byn\|^KwN+omv,UWhȓJ[vT\ä8XuڹF۔8KK]<#4mz]/‡|eUrNH k뾈9.OSV4 ʎ+sn*bCg(?^4zE.]P=\*)'oN't?Ur {g8 8Q zCNn-IG岝>RN}izvUQJ̈́)%_f[=s5\rE$f<:l{_=.RJ^+Ek `VD ? tg83jEetz<.jfXp< ;QDqD;Nr3=pKuT:eK2z+@4&@g wV{ׅdË9TpoU1KE3/7_,[uQBc%0+vI]s(7_g~<.+dGWri'q2r E8O/"._ZQSo!42,AʀL⣘ S{lDDdbld"fJ*V94ݦ{˔WᘷG2yi)Vm-ab ;˶'2cFZIRJ*YV?XRf8 Nc%YVw1ݽw]%("QVYatV!rJjJj 5` xZxj.lXUyڿhrKhu{Z endstream endobj 276 0 obj << /Length1 2048 /Length2 13919 /Length3 0 /Length 15157 /Filter /FlateDecode >> stream xڍPҀb%xwBpw;'.[I^ս5U|VTIA(ivd`adɫ0Y)(TAV)ԁ 0b@CW㫡  d`app23Xychc 7t26`"=5~i,<<\D cC0@h bc :Oj~sGG[^&&FCkF{3Az  t;M P0#"@BxX`W' "-P1ǀXY_;X@`3) PcttuM24ry7t6Y]!@R#s0::0:0,6Od4~=w7/l&adˤ9y!ljlWU7[Jį=xyL_zL_@O" d0ۃ\:̯`_fbrm3I(}Q*EEm\ V66Q AV4O׃l^=柘9_]_Q_V$de5_׹ur|yM_S ?+49Y_.ͬ{ I+D hll#VkϬ@`诗telz8*oF _K 07tCd~$V6]b#ڝ+0%Lb$x^' `Ml& `M1kLk`XLʿ5ob0x^3 Fjǫ#̙LkkfkEף4w5U_+_˱_k;GW|wW[קl4u-eWWz?goNl&F*_q+C? ^N:L.vvY_kw_ug_szݍp@W1✍1_EuJ1idEV{TDtuk+WK$OGMp![<c'wZ&pDjzTw=<, e(휸Qr1o]z\kzGv>Vp"=O1DE~6Cc1 ֑mz#kD&8kݬj*C9;"+IJ/24#$?yu1pyFȽZj4wT limPљHJ*6 ܄ә;)yn.\i]q1B@^i] ’%̷H+"?vuUi+儊3?b0 BO§NA%IeFg9#ܲ..unV F $Ʊ?KPS㹲exo , OHCʇt<7?h< 1ilH W Ŵͯ]ݗC 1Ugx2;J}%w涖 :e8C]Bf)E5aU;^bJ \ov/VNў^prӠ׉>HĨi#!l Rj]o4`^@R ލ;soun*O<^Aa,lk,)\u{Tf9>xMYfmRv:ZoRc7b߃!Z(6`i6e4NW.aU.E%pFϑ@U|^qXZWN%$8[l?J/ W<es~lbg623~s%5s'Зt!˔FgE"(r_D 䠴0^dgE4Ej'}EGw%uogLe s^|#eIq~I@ Ve W[<Ē(1?հ+2˂םW-,!#1㼫'N/!f# ;]dS%$ MXF_U@!Gآuuvk r>QnHzx[c5oӹÈóBScvۜ~"15GQl0Kɳʮ 0[lx`u|c׋FWtf:9'L@g/,Xea݆i~|J"3tCCyqi8$! TQ)++;KcuoӊžUp<I'/zDOs(WZj:YW>nD5'8qG (Jo]GgD,eQkD}Rπ:l :I MvkJ0 =]bCIW~#\MUUSֆf$yr-+BEr5oee[e&{jHah bCi~6WV*`! lp(:yFr3C_4- a'B iuJ ;P-0\Q{<"бBZz3d;fЙ=Wx;>&,T{K,W~uB1xC‹k4c]+g*:F<'L ɩàJ4=jM €J X_U2SH2!Mҳ78#$BV9N3!snl&Q÷_IqCN6F@k2Csc7x=iX쀶8ث5"zU6Mg^DuÅ*Cã̌,k4H&8/aGZ|tq1ZΚp!۟2D=W3VO>5@FmWhbe n`o7}y{Gi&,0\㞚 $݋#C[0+r:_;6 @E/cPwJb,5 xE+Ȁ&j^ӑQicK%#x>?D未ۂQwm2@ՀbiL[~ɰܝ5).j7I K=-&Z]ݥ|l>mCw3AJ3ڮ؄ppV^0AnSF烗Q6lw*>[zn/lZv"ꉺMTT"`hNv&O mÉr»!c\&yCvx+epĴd#n[< ҟ$qDϮ1|!Gl4I_a|(.+'ŗ #zblP]j Krƌ|U}$HpHÎ5d᣺*xSW`?N}rs!Ձ~pLD$ΪD̃Yl ^ySkKNϾi5Vs3_XJ"ziIҷM߈$(+)Yo4T!w?l:))Z\z~bVE%]VFzÜdY6A eiNb=ԫjmMy '*])0Wg;)/d%*/UPЬq(SS}:V9TۓmؒBw%ڏEI*;&${V ?qb0-C\Z{A#d^Uݺ[ieV.4Ln˖ EY PQt5]f}F$ф}VK'凉19k7\Rw!2k%fRz]=5Jz[k3xZZAd XB \IK^Mq?lCөT\WY]:xFy|q9t܈9E*cAqy{>tpxeӜQ{`zKeK2>s U^ }m) I~%E2"o%uX;$DcfK צ,)Pk 28NݬS3lC(61syL ͹~PC,wF/)jTs3Z2bʀc*胢Ҫ 3Kg+r21i+GWI{CkRzNg1#"fu CSlb.Q1ܰ+)2T1]()!=~RJ5yttig_,!&1dx~QH@EӶCaHjMƕR˜S-9mzlV~fLfC{y\; z]mf9 % ``d` mol뀕]x8@ͤ#'VkhϹ=yH],"B:qAខhLndRA~vڞv94yY$C#4]ZM#ˬ9[\lgri }.e]М@DvE0aysG~E! |(s$bY ttIfa+߸rA5MX0䤈ad'H߃ ".LcNP2[y( ?Vkxɪ{^)SE%klQVoʊW&&O3@@La{kJ/]SFϻY:#tAF%Y;'+<~9߬4㌸]#B}[]{WGnX2Lv0Q<~ knjF0ou:ʇD)_4AH[l/-\1Pሹw0lvG%c,+~g3QZ<ƃe)X$8s{L.hc]IᦚE rڂ,BùM~9)~6\ypR:A?{)㋔:\k)1ޥǀцyus09{VnJ&:.?&!|8DV>ȈE*avh:"KsL} Y8-OSVcv<;[OV"v W~ڟ:-_G ̯l#UA,$ynIBUmG%G5lq^]ovuD&]I &R2| >dkt팄zX1jWim/ "hf|+YސP8Д(PqVy7ϥPSwTY,۾ɲz%6![O?Z"V\LRx ()lPeyaRgڿUatb$ʓk_D!4݂Wх hNc5㨻N\vˌcTLW^HZJHqɤ]tsVpj<)XV]#vwt7F8pIϹmoԿ]X1w*h6tZZs/$_8JR>zoBň {Pa>7j{Cdˆp\6`04aiULlշz*1S7lRYq1ϸ% (J {Nj=$"6|n_I| Y9/Uœ"jG-o$bJ)R*r5̓2 ZA5Vƕ3hnb5U=d QSdwQɇ<.4lFTyX_(7o8'L~?m{`4A7xs1_mNzZ _VfNqq Ad4^ꊡŊwnWt6V[K7<^b%V'T?w̡U0$,hSЕ<~TBWrrɯ8_^%BZYG6^m?:mˠ UF`!:t*kM®FǺ nj^PϋM/ULIp:_T 2x*X>d^l$PM4Yd> sCjB̾> ,MSNNNhb 2O6+Fǻo5D ; #ȫX.)0?"6'[?Ō;L4~42/7"Oۀeb-R|PNS8fsEMmըs\~ }lª wK5SV{mh!5Tɋxʐwy!([<辋iyuk !̤R0e),e6mDŽ zn`Wl&Ӗ Q_2#pQZ=G{w4$\Ìֈu&i[Spȷ&|wB{dP$V?sWqVa+6|r|nRa%NO8MrORqboc|j7=+:p]2 Yi=eҀnlE5iw&Kx7l/ r6Mb6<r;oAd?z1.*ǞHJaL;fΫ )S;Cw BہL a»۬bH1(,f=Q.^=LpFa´8d8yLW^@ylN'HT5ѼeE3wdșۀ{#(*~X /\r/opGȗQ>1wY~?&%?og,|t8%g'QN:FHd?7C_2G[rʙKl6jfRmaQ/ MZ i Ȏ^T+eIݿ#yvͻ0R[[g ζ^W-U5ɏFn̦<_m. EM;k?RzVjL ~dE,QÝ ڌ4ͬ$Tא@}V}”Gg0UzOګtlTN5 ۻ왖CV2v'DuN*E k}LcU$VhqQ<`By\{ߑtƫ P=Nu"?k%AQsEF28GC{+or]8f55|٠H[RXꬉ> iqx GL0PA DQh UHH=rYHu=܋^~bv> [טjC ɒEv\bDIw%b!?01cFR_2(.N ྂ`Z+5ڜssb^S{"MD =vc lRjAm(aªG2<#\fǞ+'ml(xJ1%H偣A:Ctr@ձY6`@̱{mHͪ۰MCi$vZi"S,ZO߿ E]j{[c} Hr0Hǻ@T xMΞN.tvhɃ1  >F6$~s=Tf N Ds"UK5nu7_18CS;lDrˋN8 Pدue˅J0h =4,93W.J9Za<VmL`[9 ;|A7~C&^44C>d*Kn )p7w~:nz%@MVam syU*^O%PjJj-B?6Fp->eLw28V͑_#C DUb~ Ӣ/eC+=aIj}ƋWA?]vF8U+ZEuzGbF<\ڒU:^j#gv5;I◔(9I X6I{}"DF-nF66wLfމS*\(+QoL\ 3Kœߟ{%fa|.,ȺbvUFQ 7ڧƞ 'ߗm1-.olDZ a)wUݫ_,rW"Cv#'Վ?m_G{%1\-3~dn\BUMX3}G3U{>Ƭ ssK剭8}Q4mhʁ+%[gfM{zv('1qhO2siEط5?lUA茫ڔ?}f5`PeYd;zQAR>D|D)Δ3һD|lt{)I#/$5ШdHn!}N[iJ,urMo1Wx/0 :y榶/fUq GҘZ,p5Z:SSh_ng16#j|~s{6D4Zm"ꯑ4Ӆjf"1HPN}QN5%DR|$y.y=\rA#jDm1S*$B){mb\=j|+O'E<{r+O_!7XZDҽ}Zt"D݆XȾkY}$rP Y#x,SlȢIӨ+kی8 ^}:wN_/Zvlr8 rh (Q6S-& Jh{9v7 >Z~b#"P_\w!+F>5"Y}z|jG팻B{8"jTŎy-AJlT?H#яK0J9ZD+w1+S5ʭ.v/p-{6 &͟-l=`sgq]FC_?T'y&.8U\iG0'TrnXy;^;[_BX {0r2g[D1|SKuD+a˔Y油2xUPףk5'.ƩY[RM"K%nT\^B`ɬ/؆UpHͬX+a:S3\V ȷ깵~ O(ٙT.+uqGj#[/Dy& B9vj3,zcC VkCd?F` W̛NR-幏 8CTa7ſ7U2g^K.)j;}݀Ç[8-'ӣU߻Xm G@Ws];Q}v8KmrQ+y@ ߊXL93 :"<{q:XJ)!"{\+CW; (D&іREqcO;+ݷ?ŵܧw. t#*8?ocm۲SlG>_`%5 RV ?9|Oi~~ WYt y^g Z ͣSlz*UyzQ2NHSI U')$5e>go/HVZ#9=tX>ƒ>.nꝥĝGk }y~Uy>G;bHQ9B@9]˅L,khS7 kp(1|,Q:C5;z,yU! bCYhg7ID:CLcw ͥIj** >@r "Qɻ[CM=[E-֞úeX9i#yωAxV͔U`=OSMopbwOvzV3^˙QK6y?aLUb'DO@Q/7#hQcU.-G&cAGqU#55OU=T"--u}夏pgQ@pEO)L&Hp_j4&AVUIpR܈j:Nhә) Go1O8JM):Q,zjc 4ΎŻ!LafPl"dEާc "$|o9ten-zg!1Y #YQiծZu+Q ny\,U4}Ba[[R߁m 0~pvHf !e3ޣ©m NCz@F6MyD,)-7FɂNzW>KqFҾD8JOU;-UHDZXHQ#cQKp;3G   |^&u dn@c+65I}L*M 9oW0jn|Bl2.>rMp4QYf4‚e3hɥpxIyXy<33Oēu9!*SIecFW^T[ Ϣ)9էbT5g~ Srd*:aJePx|JSHZF|p.x^$Ia" RAߠ`1=zgQQ%ypUiՠEMZj=eRڡFXQRmv]cwDZj Z_@Dk]#Vħ5}'Βi"=DC<^ȹv5#UX3m ;-|Ì,t4D)DD>W~7f`%AD6WRE.oM{sa8 60וhWwϲ·ʰ_KLҋP̱ɤ$)8kw8 A1Z?,e~RĞ} BKz5z aqoFm ?S(wJLkݹ~ zCR|@yȏh2㣒oم✠ `RHlPr= v#:k!)',%rD:n5H.5|,_V G;hu)mlK֢\x .ݲ"82됱p&P䨝IK?ӋXEwG u*i9| oôtnx{dTgN2b:) ,Չ_^'+e|3јtqj DYY^q$h.?jxX.pbC& g8H֌S}&}t/'^=,7ZcԔͫKq?]byb w*-Yh`U]2mۜH $#phYsԴٱ`ń'0$;dd⻒ߑy=rǃ endstream endobj 278 0 obj << /Length1 1680 /Length2 3950 /Length3 0 /Length 4992 /Filter /FlateDecode >> stream xڍw 4mH٪GKe%{$ɘyL̘,!R$ER$K!57J}7}g1ߵsT0@S2RDjF6NN(%TVD"`pNa F 470 ٌthC&D 4Q5H@ M$S5ct (dHȔ *O `dAခ/H%`$MǃPE 812x:@0 E/ML֕:pi 5#оap Ot8qt H$O‚T8ZXl :'ݯDҏ`4CIA7#AZH$:Mxt@D{AS{ Mk>Ji4q}FzMHX#/H` : į!G aqc`)g0ŁL?6o"Huee@ ^)p 2Ac}iS# ` :zH?!3HH~(1HaX2FG ~А+%e@UIPPBMO G4~6 ~)@zu d@Pgi|=*vdO$$?~/֟ .ŵz-hh H@3%X;f=#HFXY\AwE]_2%U5M`HHIJ@0 F,CBDC!4](#SaWq@M?:4 0d"oz p2U ܘ6@>qQP+bC7@ʟbjG; jBiC4:0T*&~ ؛^2F+DqTB1CIuaeD$`>H{eA93Ϡg㓃Iu1D<]Yp/祟,=>w[n~I+uLzטso5&4ݖo<۽ NgƆ5hma ӟWP<XjYu\bIHVy(Z.Ĉprm蚓E0*ڤT[S-䌁Z~זV-3w0LeؾRms+͔-LSDդUiZf5V&=j @\9D !"%kӚj=ȤDvhQ7Ymp7ttRPKbR[j Ci$>O|Uj^} 3W\6uaSqv}Zielq0#)-^rqo2c➊Lhȇ.g';<5<[VCNr. ':i|asHT;bJ >0)C0Rzp9 VyTV5Ѳ$*Weԍߛs75o<3{b"҉f&JCV҈)V=A(yWRcpgۢb=]Y[n0-iQ:1`Ú2sD;t&XQuN"n_lL.-񗳪_L \ X?k=]{3Mu>Hd\OynlRͶju{H ;|j`'{pRu_EGCF,\1Ek^{Gf<75#Z6\:FʭOX"l=J-m!Z zS$ hpYO6,|ǮX~ke"]kOLk~1,J } Y}s< ޲(jX뚓;+4_,ص&hu]]x WLn4Uu}QW8O');tJ~Ԅls3T<2h,rtٜ 6\iQQYyZ[f<'=2Ң7 q.K#3(!j eIl}V;no/H"ݨʗ[ؒS:((Ʀ ;t͗]婪;Q1~_d\mC WZdץvGf=o^8*яStX4HwF,b婿77W W[[~Q^P\ȗ)216-/NwpUa >3﮳>FbV$TfWM ^hYG٘k?i{LS-H>V'p^)<f\0snSnU66;XF?ui#ԻYI~^#嬓5uH[Q6>o,La& oyyCޡT0>sK{$ϖEHQ߻S[Y:6=ekOr8[BL/\Ar]l+lsb)>7˶ş_y|<䱔Szjg|/Qʋ⽮u݆ōJ<[M}Z"O?Wfýu?QbJ>1rT..SRmhhOY'"Q.왋t-3%9]ᱥObnJM^m_U\*vmU2 ?T~oJofx E3l!.ն"yl9*jX.G2b%-9çٍiPScQ[C;Tx2L !{HYeJ j4Mp$tT .Pթy y'dRx*{qv}`ɨΔi8oGTCƓ^s%x2"lY*IIro[}*I7 a;ftNtW4Xԇ;‹(*U6\if|~xZkBeڻ.Ô4J(+Ɵ)WEݒf_ZkWz䏸 (',|[g_ w0#zG=Us(fƞq7oۻfLS{k~ s[܊|Aa W%%C/v॔{"v)59g= 'EŦ{b2ܧ?wU]Vg5 |1q#{BzQBvd){KT #Jq_k wb<3k98}rxԏ}Tm-坢y;Juge cgp|!Ōy!+W3k)G);%ljjϐG='㗿4]GZ(n^=9{(KkeW.aǐ箑y-*-ՋrLg:uհesTv+MJVM8t$Lgb W`W91AI=nBy:Xu/DǺߧ oó"Dc#C[MDs  BJ'DezxkrHS51T-{oiLxp[m0j.W̓\\@c%5.!_9|{.y4]],I~ endstream endobj 280 0 obj << /Length1 1778 /Length2 4836 /Length3 0 /Length 5935 /Filter /FlateDecode >> stream xڍu 8{~ȒPG"[dd/035;#kٳ%keϚZoS.3~`嗳B["(?X$(@HXC” FI(P `8BL#A(@ ` @1"i@54 P@;y`68c py(q; 0l'a.D tXa h?'l؟q]5 A@a .(+ <U? _g~u!Q08Cy Q65h)kq| euTs 0WfI(8Vn0€1H'Vt8QpJ(+#RSDbp±{Y{ X#QVGCX8 ꣐.U_%埘 @@ 0@8w8 > &rB;ք!>Hk sE8 d߈ p`A(럘p;` "x >eF9x)?_Au%Fz?'G^_HX܀"ϿIa_"@:UQh@V!sZ \hg 8lX7Wq8aH_˺ Ko!BVHfUq0ȡl~#tGXi#qpcc FcG 'G+=ὁ%8 ͿK"0%`#! ~`@PZt>5Cyt"†Q,$BX8 J  Bq~<+8AP9o!Nt$h; ؟9 "l $(s LN ᝆG8D["(Ɯy?q' b`X-V Hz. Af\>~"8.dW\ٍ_MV J\?P,#2ߛ_*ވdo6㝌`n _j-77ߵFY0?r";sysa4mYEYn:9W'jxrF11ajFR &k-+{=B;!璙?~qRåV&uA`}A w{ܖ^8|6ī7в豁;- %FU' y 51qoo4R8o2ʶYUʌjSYz,AȄxOߟVE-jq}Ta>t4j:5^%.ܤ̛&̒T|7l1R kY '>SFrƃ_)ϔiH BҀ(P)¡!\ImAhzxћtW'zQO􏛟: T]^lDGn& &XJ)K2t]ryeB0+CBQs+ ZGIb]H-Q{ݝӬv.os}:d]~?|F8AeVm"YA:7KO'YU\eL4ŪWpM;MsDm8Jq󆡸2M*<ߖ]+ۜ|4*Tf*%x&1"d*L #+8|eǪn|}E6Fkl:h~ͶĜO{F5lܼsn> ]뎶ܕGRG>3^l`=k*u psï;ӪaS~^bi>n:@䟷wr`p s_T)5'.PɺJ'<"$f"Фdua٢gAoEHIw<7K³ڦX+,@ע}׺:qƏvYFϫc33nK:HTVQxtˊ0yx㑒k#hj꙾hzP@ܯg{ WV:~yԐpQC'_Y)~=8>Gɯq]t^QFN(5YgPE*Dgb%VuHqL|.j?뗱kPv|MhUqԩ2135 czOi}}9,T=Қ%݋4 dl7O ;14 tiW3Ig~E^5&h%\9LX]y .ͭjbg!`7RKz{7%QZ ?=e95_c\3YӴcN,_'JxY ƃlx9 ms1oB{ ʿSqUs1AMQm(*Ge˓DŽcM1UgaScVPhV@aL~f{~_N|$%,߁-_o[3y3!K2LuJJrZW#F@lWWh+-Xtd{?b^v{jm`G:9MoGM?Y|(5`)6 =Y 6;3 _whՔs+7AŠ|+_'ubAfpcDڞ!L`.AN_*\EQ*T^0i>$SgR%D[&~ (+H2~A-9v0mp k/`п; J[9 ~xו^,P/m瀷#Z$sj=Ѱ?p6N(܅2aS!5/ޱfJ=^&^XsN$ ӏQy D:DtEAnrw 4<8(0hj`A.r "iiܜf}b/GY/ۉ+G_oPT㋇^RĐGͶ,uU@o0]a[֬qRgzĎ֏*5 L kwCKϱ$߹YRZ'aYVdu]n^( \[l/ j6H3ACgANx+uMJ!8W3Ky :[õ]xԅ*/s&x:'/m0IطVjey#1oOͨ#lVӀd&=1s sS^2@SeA]4>%jA>!R%DlϾǽ@tʇlPփʭi!:?`c O؏5d\lcg>^MZ }Շ R6Tʪ+QmJ >|۩hh.ax&qf[qjp=U(cث>i_ TF_ %jitVh;#vY |G1ԠZ<_q z)ݕBJZg 5=/\wZN!%NU9~{qV<-fOSqՈL05Yv)6q7k|$ɶgZ.lNI3mGqT&HkfzT(X%>d[}O#h/ i atz O(T,2 OѭR\6&o}繁*s%[b(D*y*"Y_G^qJ0$U3׊OK#/V_ߊ#feK,.T`)΃r\)%y8-GHJWKuTMQ4d xNSklzeCȭ+i~Ce_TXQEZ[8) 'ìXV%kù3$/#F $Ni7N;69I،3/7.iNlwu03e /U?ϨTcW}\?oET m4lVΫaDqXԔ`xQU.i'Y"{-e"OR)~%bt2YCS~MhUo6*7_xv_5+[ʰ2)zI-P] H. 0 w$T#rD׶3,0_p=;inPY?:1=| oA4 rOU#uMUt-Yڸxtwb6ʪ7֧-E,> stream x\ks8_xqL*QdAΰS4JB#c(!h^}1zYd3Ic:Kx)3p; <4f&%(sKLbUlu łN6*~9'x6:eqӧb6.s e*wsmQQ)rmpY<>H3=cy{Rpљۛj [ǘ4f> YZbPtMlM~ښlB$ ^s(ocTn_(Ogx6p.H^P FoC\H‘:B[9@|Ά\#1/I6ۺ+]cCNank)nJ:;qeT\ÕE<CS-DE>|4o'~1Jc/sgl N isУ}]_8b>$vhzГGҵ y- B-ǟ$zz 7ǥ+VUK)jԂU#Ki&R> 8wU%H7m3ZE-%q%ЫTIfIM%sd˔I-q!%Ϗ?BXKt=]xGب!Udf@۪N6Z@+ii,[4x.rzinĵ؀I[ԁʭ( tD(Jt ZuZ2KARX6ǣr*(W % m*W+͂kfm5+mjS+hSJ$qfH 36kY!8ABiMFqՆc>,:C*ӒԒINIJuA}LpRYb\˻T,kR5;+kȣ4Drr)oMmR)uXt۵VK{Ms՚eu$-4z'\ #I)&A@dX/vhv L E3<֤tF>2X*aLaGfj#Obvc`w ]-Hgc]c% hDqaİ_qlhv>88z۾'r8_ЛpnzGaiƵZ#@.w x.zX[.q9 ߱,r!K;6U 4(yZ(j8 K]4Ļ{=-շyGb:(Qwh|jo!%)4NS׆O/hyy3hMG>in-[枊 |%'yg-"M4}]ōijnyGb wȩȡڢ{pD 뾋Vnn8KMyN@4TrNߍAmBsʛMe)7KdSt0+OOm꾩T6erzB\9q9鍫h^/_G@{1Lju=t*{xSX>ٚ{D^RV #h{(;z{ËAAɴzCgxWwCewLW~{C7q(+q,NkFtG`4}QOS_B\˿/ˡg1Wb(Fb4,ŵs44.ը/c1S193E)$,VЀ~ pA7Cǀɻ6l~b!/5Eۢ,vdoeq_G>| s-dŚvUDOk|!~m;4Q[8q2D$d" r'/uľZf[WJ̮ (?pM@=)4I#OyѪ/DO_<}ʾZ,p?` dsnOdA܀p/:-h,ڸ5BM)1Pg&{pƪ;ɫRѵs wއ%dZXQON޿cMͷ,Խ(Y0-'yBtsnYS~leX߈jo')Q*R;߯R'/ytN0nݐ<.ԻZhzH@1DrO޽z tzz BJvR -Æu,4Y`^ pRSV_aOzq,׸daLJ:mۥ/:56+fiu=Xu05ku[(~gNb}(v !+ ߒ\n'B;m?2͘{:UЪދzWUۉA~wDI`haD;'l>wi-6JcET% N4v^S>iǥ`lci NN,3[B';UU% 0qGu|e=d Ŷ?[c JqGy5LIewqYorz o endstream endobj 300 0 obj << /Producer (pdfTeX-1.40.20) /Author()/Title()/Subject()/Creator(LaTeX with hyperref)/Keywords() /CreationDate (D:20211026181641-04'00') /ModDate (D:20211026181641-04'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) kpathsea version 6.3.1) >> endobj 282 0 obj << /Type /ObjStm /N 46 /First 379 /Length 1487 /Filter /FlateDecode >> stream xڝXr9}+ޭ kTJ!v 8Ğ8Tf~a\ ^L%J̀ HZ %H J$Ѡ%pQRv@@p"SsM"5$@0n9W#`JDd 9"a$q!5p sAYQ 9AN s(Lh-!j8a~@1tI8t;KK*u BӸ>Fcs̥iD=%u;Axw$woUF#}}~6?8e1_,q_rKݳxn^2bw gS.Zu*u'/pxrۜo޻{8?O'nQuE:ZsMf=jw#NZ'UtOOG>O4*경Ϟ~:mද?.y]%Źr5m9whB?(Bb]Nۃ Ye7ZYCYܖ3?ePea.g̤BʢZKK*KCu~lMSNn+6rw~V=ZU7k@jjs-)8 {j%[-)O)M$#n @mim\jNT/v)AmL+c,׸<_ups[\ꢓۿ86^p=| 7 endstream endobj 301 0 obj << /Type /XRef /Index [0 302] /Size 302 /W [1 3 1] /Root 299 0 R /Info 300 0 R /ID [<2225D34FB64571D0B4D8E91175E125D3> <2225D34FB64571D0B4D8E91175E125D3>] /Length 752 /Filter /FlateDecode >> stream x%IlNaϹRڢRohUS qglf]6`pXt#F  `80M`vExRQ'I>OK{rY<(5๴SnKS"usƥxnԠٔԐפ= 5GR>,5;R)uֳ*תs .jj(y^6Qjր&ֳY]r endstream endobj startxref 335165 %%EOF pcaMethods/data/0000755000175000017500000000000014136047224013407 5ustar nileshnileshpcaMethods/data/helix.RData0000644000175000017500000004656614136047224015456 0ustar nileshnilesh]xTU" l_T*JGAD@J)қ;@:ilOH@{fy?dgs~g?]{;AA!A (SB3t&k^: \WwS Zw Z={h]]{o7c˹_~ "j}Wxjgs lˣϦ x',,Pk\_kJ{3^ >ݳxww"؈wԹF5Ǔ}w5^?5 {L4ŭ~y }$x-n<=^>|?TOj}y'oxl7?wPms;:S htkί6רiw^s9whEg0Az]%S< bࣻ79|7<6+ul9i~qZ>iCؽ ӫ̏r0f oGFZ [!Kc20d||^1f+fm}p_]~Z#vﮄ1AڞoħG漙QUCI']Ӟ| \Zb7ƍ<0?t臘~өy]U앝ݒ1ݮߕ7^Mvӄڑ_N|T&,g'ڧYt2&vI.?Rn&&>D`şO>a2o+ח?|rn 1)ONkV[LVi>qBLݵ쇥pg#fໍ+I1ׅ:y8f.OA˷1y|W-A.Œ_~ pj?^m f^L}qZM̨lp럢JYLnjǎ1 23J C_ mQB;qVpDLd7/ Q{ !V6W>߾v9Mz/|Vdo`^ .|s.Z{2ڲZQQm3Ц/Zi:hѱJ0/ƠMK%nlYmѳ7fN{Ӷ{Nw:ۄ-&8ujJy9ɤS2ycX茊s>U5˅7YuG?^7uB06%Љ~vzx 9m1tv2O8S>kfIY”DG7w6۝ ;zme7~|u`yt?)v:o-b;ݕG̒֕mTzL 9f@Cf1#a1Kݽ|7sz7=ȲГ?2LY;{|: zg ͨ{}|[@ψ6CƱzF̮o #}Oۜ}EN 9{w/{]MO/#9ӎ#5mB->#Mo;nr蛲dhcTBthʆ _{h赕_WZk[={o6J꘿ѧQDj 7l'f/A1{VbR&^ԫy׳;nSRu=]V?(9edz-}=bF6_5OB<|L?Su'砧pμ(}%elCi 9bvN=²Z\D/X7UbM9WjfC&l<Ȇ^qWOmVꑅ['KkpUqD%/ -`m`ҟbW΅=uhFըrc}y7gWlAkC_D301ZJ64~y{6/l_pvrFEv(~X}_տ ꄞǢڣ'-DظIϼvOm}':z#E1zǿ3ꘊ+ߍz>758Ŷt^}M̊ccV팮/~t0yHz!t:~KAߎi o__CW~S܎{n5 3ٷ-Ƭ ;F6,)ӄ[?48j|*.h>d r8XzڵnB+}:[Q NŢcɰ&#ŌKBG[#i?ThFT̘ ctma\Ƕ-#]1#3iWj}hs疈Zv χ1C-NcyL]Ph\Y旨ģƏo3{Z||Gcl~\сxjbrxG2O;]`43;։ܐ*J~w_}áUxmo,kZթx15X_ ؐxrr5ox6tΟ޸;Vī!"cS[v6}1Q y5};Wn;nSVf82tbj۰? NXwCJ }ؾFZ˞8=EKӞ/Om6]>:ON}yEG%?<܀1~u &2U3κw:7fp]vbBRC4^A%Z~ {YA ٩V1Zu7HV沿$@RՍDgC Qv|&$܀-k]|>$l`JYqlې]roBW i,r!jE({e(ZyDI~RH9:ZۡU 󃱺s؃}#d|RRtd!-V쁴v H:|@!=⯠ u[A:X ܶ!f?t 6=,uJ=շ!uo ]K.w6C@fW=hILjJԏftǂm?Ʋ|ׂL| dXhL27Ѩj_Z7dO3xώ'_ zy]gy}?q'y_ ~VU9|  #?=zM~V͗^M& ;` +/-}~&̯wY ٬]^VU^m4}y 7kss!gKOgk;vT&W琢_ni >6^y=2v[[,d8 \,}ex|lU*4hI2[}h>MwR(:#dy pkO߂;;4 /w_%mTpӆGcolVbcjxpx" 0|9ZUq`7842OJNDFDZD{D=)fp~w3Tnw2jȝ=?{wh[kK.j/W/ؙ:'u\Ah8l`_^duV>خe?k?s`ƙή!E7(2[e\ҵ]`Y tlr_;e}XY':4Xb>A:o_44Nl2Iy{kz :H]Po eUc̐^ Ir[HVe<{ o~*{0,:.Wx3C N.RX`'+7pZoW˒*oՇZpa?՛;׬nneh-#/d8X0cd䂓-v7UJV z-_Rrnpu¹*ª_< =#hQBXYoЗ_~ Ge k-~3~X9 lkvg׳G`uђڷy wer\&/~>|2܆[v}dkdS:zcj_}t}Eџٴm'oEjm.}Dԯ<=~]n zdzeark{7r; Uп[k'gfY$ ~Vqn>֍izx]}Lv=?г ͖MLE۬q6=}/GW-3W^/{\@'Li\G'q^K+[džW cryJp[詿lؑlţrݩ3*ۍe`gtbʎc3[~'k߇/zJ_壗Uѽ7[ AwylGި@7k_9yk[Б;eaexԊc1&vAʮS LE'_Fu0KX͸5貲F]MSڷv"yz]: xΥ`,?)Y̅0ǯ}}٘ŏn}=OBfZfZ m/z8eխO&i+(k'.tto@*A;/`Vm] u?CX.}!}\D0&5@wv.p`S#C^ڮLaGD<mZw#f>9w}ƱD=xf/jHE AeGcmr37 L1C$LexHsa80%J`0UCh7h51}Lck0?`Ĵt*oY e?1 &<[iM/idXi/m=a{L6/0sղR[0M%ԩ9`1'Dvܝ`jC@1e30 g` e*&S>ceݔU/$Ď= lUo39Uw1NY7a%=->:O(A8^_#^amXS2eqj: co"pѲ+*aei[˨1V?+{>ڮ~S Vu0G`D4M?`ɮr\>YWw2F?z.4kwzw^G)Gڃ_YVgRo't,d5Б*5Ǜw5.#uk/~fvEN-?3TûZ6OWoܧf2^.^.L[ܙg}g\8Wl< VZ xX{λ^r[l쭕=<{/f;swYlU%o.Ta#?k KyRY=~c`wڪgqɴ8>}!λiWǺbopbDu5vꃳK"N=N)Թl6~0!HְcO0"ϧ~eS{M(UO WpIO0dh#Í*VU4;4_95 dKVJ 7e}Xw#@$?ዙ/̅k7Toj] f?<( =fmk z{;VHC?<͍RU15 O})</jT pJ{n@ ot;͙%<(h' 12_5}`Ť eV,h#u B+;-'"_'e` 1-a3'up:gSkvi8=;@Ӟ-g8HHvi,ۤo%C)TV{1[cuvʪM!)VA@8w!ۚóOVC9As& '7'֘2ǘviRwI0Kd/A$? [)|w!SCP\ L]'A`鲎I`zHZWRz / ]cV)->OW鏵̪-d<3%Ú@v\^n| +`a}"Xw1pz-ot]խ˹}22U)|V`gn5`?3`c\L;o~ v1y|p:~+p0whY`Ĕ\蛎v'8 N.? s FpO&.9+spn }cWE쎃+˂KΐK;Knf ^`ꀋ57Yq땧YZ1d9?!#p[H+^޷Aޕff~7/#KKr5Oa'NKx7 D&XRBQ,X^#6pr%ر} -L?Owǀaq"q˙Yt'c!?}I^ϧc^yYzp)#W4y;g텃'כOFh~Թ:.x|Ÿ^Ow)X?d粆}u)xNgS?XӻLxi&dsGF3F-v_w/)F}ywUF9+U׷!Gqt'gy~3|L&;|G>KpvU3]7C3Y|~z}N~_^vG],z|]|mGu֩_<ٵx>:fyy%x|"<}F^xj?w>H~+I _nVZ3)?p! '=\L.87xx["e#nKj/vd8k\<}|nd#|a%&nV.?&\@?|͘*k|$jZ;-CO|Ss%S3'G f]6R%|m6,|&)>Hpq :8MY;3MupC|.~m)|dF`gJTpH_FB&;V-L^/L𡂃AfMy!7G;C)ڢ-BtZ u&w{6 $!uAK@j2+pc؅n6~H#yp +ػB82z =ҤNi~HdoHm(Ht[` -x iL4nC\3Cb[(tُM_@:;RB\ILѝT֮~2}9b;A:&gFl1BJ[nsm?_)$s[HHb"x#ılK$1B^,ij %h+f_xHmW$a!rɬ3>GLb♽7!{#8=Q]Ev3moUჅGzܐ֝Nw: < \FpF׷e鞘?Mۿfr%ȍ;B>I?U17 _* x][Y;kIVNڻl  x\G^.(SЂMUU=Cv>.:? Q3vv%|ӈ=xf$sbn`)c780^g0b}2)F,bx~lGx y7L2H'Lf] 17n`1G8M >zyaѦqx2N>e^>Ә.DRڥ`{aMBvi]XC`K9G[6`F}.@L^ۇ0UQ0#wS&tLxi 3E_.dfT9wbc*rSsx;f:f^ $L_\ygh]31]9N9᯵ ?f,:rkQk:mrfhYr#&9em{PJ]%fC- s.-6K;>o,:E>Yr>dk1z&k^"k6]3],];ޠgD'Oak0dEݳD~yi:jV[K0uF`u>t *p9ĹY[.@7KFD7fS}r :ME*~ K?rytzkC[~Oz>9?u::=E_g0o_Ǫ"S5sy&k|>^CfJC 6`yk!ȩOgz `)^ٗ~%48;L%=yl~^@].iׅ6MGWm+BY D}ҟ^.ާ C//o("lדu8J8e>~ކ~Gv d?/]eaZg?V#nF]M(u!t5sU#xۻ!fjDG>F|ZX%5P#:R#W#rԈW7p_!t75BDŽj௦!t |W5BjGyy5B z}vjsb\X5\ /5L𺼐VÆBvv'jѩab>Q 5Ə݁jT:gP1WMaroj fsJ :*eڻkUqBE>υUaС*b5Dk5T^P'TCDݪ ;T j׺;=O!̶*xj(=PC܊*65PqNnWCY{V5d!K/B :,5[^!"SC>dwUCJ/bjګU0ΥJjDfkGsC:!O j] 'Cp*[?x?D :ϡ ΩAD|nS .#L j$WSfhi\/A؂U DrN i50/D5hy<1T@I5H rkSy_jܷA 5PƴY <D5p1[lc87ؘj=5ṔAM[ sjժL&2O HF5++'~/80j3SdMݥU 5@ը|`M~`SZhvļ tX|+yV9H%,tКmp|"9Y$ͷBo7_$6Eb9]$ }7ooF7BBim  |~#HL!ӶBџBwB ,Xjy pa E x 򺼖y|ck|*cP~97] Z?X O]۠/E^ 8:qXlS9J X.o[|ɏ: +Kyb+| |?KƗCXp_ٷd3̗W[q _RP̗Ϩf>/żs/:|$_pM_F̍/]w3Oا<1O\;{!+_'9+w\Olw~>xD~^`w}9q7>-n# f{ }\^1[֣'e05-k%lcWbsc%c6O>lAc?O{K%/~_>"[SѧUU @s_a@^sFG_rVi+[}W-{^.sG s+y/Ƞ̼y͍pz9)tB3az!zfSϋq_2DNWD= 侻R,_GE,f<3M?dqKQ>,8y!f1 2іMc&8hgnK!6Nִ ̐>L1oLv3ٸ{6ڄүoq"ڤ3C>O(O0Cr"PS:d.<1U1]Ǔyӛ gTx$Ls)]\TdMRj+>piߞ61 <l`y sHXnp#r$DDO|tg`|V`JGkr>Q1qY9; b0LU17֡za?botMa6<݇ xW +^>/L<= Z𜘃?<sAx]ws|,d .vR?f<ڍ8#tbsyB<>`Hxvϋr '`Ѱ^ō}'G85x\\WrVX[]_WNGa߲3kmǭ߼-[nkh8jⱹUNLprlRMTѣħaOgUnNc fOl˫B'þ0zpۉ3%u9Oq(.l(}IαYuK 9yQyKF9z\e\=`f*<ɭ;nIܽ2W2!Ok)@bv|lή<p_g>8ϛ!FQܸwBЗ!F<VbΛ ;b!^<b )qyH4VXd'3^@nɿz &<e?fpC͐si?!,Ȕܐ}{)Gt9'Qa+\leqyyʹ!ShO`kxĜ];.cAfV.8a2yZ`}LyLS!YB,7s\ҷH|ka>9&vGԗacn[r>,\p˹}/,Jxq/ |·*|P|yLoTvk ^kIrҳ#[v9.@x~r}LNmZs9׸~A8![οf~dȖnd*H?Oϑ!kBy#2Ϸ\wr^9)/\>9\5 \Jl.Oo\rĠ3<%Jnȕ9/;!OG JWJ?]|^F^0/!?nk}ȓsy j/q4L/t1!O_H_jSzK_T __r:[?x!kx!ȓ|w|)}x!1_K@xҧ/Hx%tVxՎK Oᥘ .ҏJ \+|Wr ?i+1WD^ ~rN@P PuA +9o^kY#O|@  ZBQ?@!_#5s+U~ozr>7BlەL_E^\'( 4;x#BWC\oKs]ކq}6aP$9FWy.x ]$E5WZ<+׻H"}g@J0B ׭HۋD3S }JЇO%gnWܛ zq]\SX srJ@>Ts( %XEJ@$?)J{% k%Wy)%@ S9<%Τ(i%PMJu(B_V P  %PpJ ?%-׋@ )A }K z>% P$>%踞)A—?] M N\`NQ|nI 簕?SW|D }%%8sK ,%x{S!%!cgsO "?TnXhTc_%XYJx"J*!lvJ0ouWBr]T -/%-""eI%""_~(6g~-,}ZX YJ7*龍D/T P17)!`JпPq)ߠdE]%TER\VBfK>W}{>?2'|䶗ׯ 1tvԍﵶk .ݲG޷?׎=cW~}=oz]P_'밼]=ƔgD?w~lӾ%d-Sλ|}/9Yl _~se:ݙ_ZsS?~- όS}ԜO/[U>s~=|[{Y>{ GM5cU_7>['?7r?nm}ۿκ_>[n_puYwW5{~ˇ96rׯU'to_~m?ߗʞ_K**y+ w·񇎿ӫlB;,5} Xsm7U~_~n57|y,W4֭y^2z] m[[}_>WrZ>zew./{|/ ,nwrw7Yz'~Eٺ7 R/kβWڊhwgR3yR,~g 7*ݞٳ:Ψm~jOUx]v_}l}KXsg6ߟ}WǼ^b]"3~/ٝŬ˾􊫯Xu޶'څʲ-l =Z"]x>k9}__i.|ՑMKYoܺw{?_?ru3=_Xom ZsJWzoKn4xe|u{I?/9'~.QYc[m׽s{wWMֶZaMφ ۓ B%˲pVhgX|o=] ϵ^xٽġ_}j+m*{ُѷo]z|ҮcF3l1 7a[>,zswh]ryz'mk-{9ʮ݇VݭWsN[shnO[O! |˖z{0ߖG_;Ӧh=\nJ+l]ljѪ` ~ֽ"Swf#lT8ozţG~zu|#M?7 +^U%N<o8i/%,'V:ˉseoڿm*ٗUwm9i9V˿m;ɖE7YE٭'؆7yu|cnkNzo꘿CEyAt>kEw-b.c_U?9_7/>ϖ`}%/^|Z~* ?97 ^gKB~x^x ɾ_t{sK>}[Slz+q{s>α!͜KV9 q\hŜKS: / »v؊p>ɦdHSlͻdK++?{~ [y_=~2_uo+N>ڔRٓѵ_^'P3^F7?JG[p>O9|}6rTwCh1Ü{s'`+^ͳ]~ׇon!o:ҕ y>/Pqk.Cm{,zlK%F>}c?/ ;yu`6y.q[)F^X'x0Nl+>J$ y_[oZ[z;^W%CCo!9i$覐(UxnκS>{z/qy].;GC5-Z0%/_9sy_yXfFY^I=6K}7Z_KC+ K{ߒ<6ç^QZ_籾sw yՋx/K꽵ߋUz;!/xu}9ϫ zo\KtK>:oo6]X%'><|Da$E/t =ƬU^ĕ{QŝyC||mǣ o'Ba>]Vms-Q|8_J]Airn/K|xuTNn`㏹ֵ>%nBcE)ǦiI\os8w<'ިI>p7ߣ. >d}ou=ȹ0x.+_OFw!ﱍ{(_`RlȞnx/GO<7HΙ- 'm}ϋ˄+MQA[) ͫ9矠S|qwvdC:s븎uQ}[ZmѦWyޑx0#ϏBdp];=uD/(<ѵ^ުC]fc'vf+{΂+Ћ9e7]u77:؇!pWC˕{AFp0_q|޶Dw{}|ŗs/͹@ޢ|4+=z -K/z3syP|^gyΉ2Q6썶&Ի<'K&臟&qpwȯx1ye1#~8_0?9G? }o{k|+>PWqY!'G7{꼱m+G%1q1".-MX8 !a//Wj E`I<}s߉[B+#8qN#8j߇|Rb/h;t'~h\iǍ_mŢ/lf?w;;]#}$+ۣpqx>K7ǶGQ_XcBdW/팏B~_+q@\[*ƓO8AaP' 5"~Y"/=^^4S2} S틏x^Eu_ E FyyMw!  }Nxj׏ω/M4y"Wwy&k9j3q5zɀ~0Mzo[ }yymm||.!$׿qƈ.nq8<'7-^{). S_zߓo<{,]P曨7F|} lKuRW!u_ 瘫IwmuC2šqtA8/{xvIgY :3{i;+Y7. ^EkoK}\myr(筗).p|"Q/>IWQ_fqx?.`{lVYKT%_8-!gpO o͚$H1u̟/[}S_veMWxK{Om'&k[jG?Y(_>>d{Ό R[CQ^S@~Փ;Zާ8:FvZdB}nȾ5K]U<\a)0E?z3sټ0IaW@{S>+J֙p6p{&W:붖BmZ/(>z֏@̜!o_Qwzfөˇ.v78ɳ~ >|Ha5-|d}ПHɪkLuwGWlm y}GO4&$O\v v*[S>.Kn1tWI}'LZ_^JO_|c%u.ԫ_R*.d:w6_`#E;7>E{y8M/~Ѷ~Cz]9>+ 6<﬍y[5g]d }}㔷TR&n^^0wz}A_Fl/.9wЯH@ӜG{ GҬ_Ӫ7~: g)9xjv;Za|azxz۾7D亶$_:-aQoYHoK7lo\_'>aqzD VK_D8x bB>cZcs%|U-Γ~ז_R(:l{{wem9xp^^k\}0xLm<| TVJr&|/@|菀xsbW^/W &5K}:(+!oLyuUmUlSg-pa.8Ѕ|Zm`>V@D8x-7[E/2sx-7?>3>PGaXx_i0,Z9gUϩ%@8m~5~ :Lets9~Wx-L㷟m-z/۟Guwimgu>OKT~hs k'ux[h)οm˓Nisf IYm)b8X9dG$| 䑾Reg3nS4OWd]6xdqKRo4%8Vn|{4i _w_{qxvZmyт.~+=8/!#xoَx1}Fձ*OUNyDui} lb ;_ׅ+ɓR6i*O5q1G}e+ |hS>/,e.#Rnyy|ÅϲOKgBAcdq8%_#sz\+՟C/fXWob+7?~KMܸ]^ OD>7;A}D%#-޽'ʱFe!owKxWGI &^:x9gk?#djittZNaSMxoK$[G.}z/&__xpʳ}K‹g\3 KOPsf=˭oo3 <m?:lep7oe 2/^S <<:[uZKwg*λ>~^$P|;k%UQ+MM?"7ۃ8|_B:\S9h+#Ʒ?}ύ7eBUQjkNi$/f:ۭփK]u@%}Jp CG5o7J<&G~PN-VCOf6_,o,V? ՉWm ƞxCZpJp) kOs!羟}[OaDrTqhaJ7G&>ǰWm'뭗󶂸v7<:@f)xxITHgk_)iM^p>#+s֫x5C ckm?E>mGWX:XK= ]|#:;~O],~vx/u CXW_q|]a|9Ψ[qʷ?Sޔ 钭,^g/J=F8)}!k +ҋOJipcro%}&O]G:G3S_=x*WIެ:.=atcM1?':p}?7'@\\,gΧQ*Ƽ~5MuBzG'UpY 8.plҧh?o2 *Wqg]ق["Gۆ?M^yN^DC=_*^eg-^Cu'-ׅG7zSK&:_WUʼn)y*wttmYN^eǬ>yVN\[x^ԺWVݦs~ף _ / @W?q=7,\8(V N{-G*TsBxpj*b#QxCrt~^ +-f:WnH/W/o|"୾.#j%x*^Պ2/Ieڧ > ğ 8k_?Fxxv>CR?8~ywqv'O-?}{x^vzK'G = Q_ G/U}Z?ߡ^!&|'t]C"يpixV>2p ȾEW\zmU)Ë;cKRuЗ/ݩq7Sg(OrVnpۋI<=*PKJdC{Ktv৊謫~LI rWѹ% ƍ@C *5gV [wucQmjxuQߴqlo: LV9n @[;J<V5Eunv;q4*~⫺y2H8 ?6ppW#EwgpYrRVþm.8~9Zo( x艬|*àIx,^+cΛ?ۖI8Xۗ|8G+ /!^Z9QkSWW uWީJ} *$@ڈUW kCk+jWjwuUs`3Hzt.vrK~s_(TL_U9f>Vkdu?\X|gOkd=fBCKB>|r;r5G:Cxѵ~x_}o6MI[ N&޹%{ׂ=hq_8w 57g/~C ]Rykh9'KcГ5 WN=wg%g%F{vPWNwksLFF׫ ކ.\W_I Bo\9L «/Հn@n 7UnDS(؛_fZ|<ϡtCNVm%ʯZxw JpBx޳}tDүN~Eԉ:s_X:_"wmEwTD_ԟH0} 7ѷga^}UUďt: W5ȿH_I+z凬k5'9*G{Y3q>*&f>u|Y!} T+x6B<W½SQGG<oj3g'~g}THL[I82S_NxH|,_8vп1Bˇo@'@ֿoI]'|gI$ .E~#Աڟ)b*߽83[{CO -o@9"x TuDё'5MBoy;~O"NEĉ -LjuiG0ᑊzU|n%Omaǵnt<ң D%]R1y|3O~vxmuwzgU/y!~@'^%Txt#--9otP^1ύuoz9G{3GЯxXQ /~$}v⯮3M~]Ĺ9)uZ菪N w+iʏе@=M=Q=nē'>X#*eū~P╇/N_9wHo g&1ywP>χeetX {}EQ9'Ot9j01^ޏ7t7/-f^ũ؏oAe3}>~; r -\0;KQrBMO|pp®PZ1|Dp;?mWKەwZy8Oi#T :"1I]4pQ{T#?/=]eE܏/B1VeL1wI\8qUO 9E;E\G\wB΍}N޷FOypcaSȓm}7qLz"t#bqI_D<CG[>/S>94 q'[u\yD;p>$~GWU?n+"ϑ/Uu5p>m6WKt!ȟ[~jҡ+/H.+$7:ؿ'8De ~^ Ӷo*~V]-a߉e?f=QEBy|.$El> 'C|`^urζ"$kaG ~;k!f_gLzq2|(<.ΉI)GXQЅ 7qᥜۭܗ">}D~R)|Z zB2EߤPq}eO+pg!G}J⥡%]8*x9Z)0# G> o?M5mGcC9+DY|!ư}tH9<˞C&>=E=+tzc2A=*w|{qx9߅x\zF\,gU}ǩ/E:' tqI>x<+%5u5G?7x5rȇc.>@s4֓>lv|~Za=jvF5CV3p;FTz}Cxm&N$8~V__|m;w?F?m3~_JYsl?8r+\]#?{js}/>(Fo&ﳭʇ_IO ᧓[ky2:ߵRK(I^VN]|q)Mě5|zZ)颊/"=uq^g+c'uUK!n~NF& ?sKT ~|[nMjEiK%D>q3&YѿmƯ-|/W7Eˣnϳ>_ )?I++|~2DԣW?i; |9FoY /h/8u$>m'LDZJ߉{u|Y/܋//h#q;_w6 <WG0ޥv{̯K KjJ~[gZʺƇAk)p h|W:9yAI_gL|Z!G]'Mt39?%6 Ucxy9Qk^zi9%䚗<)Sq5¯8Q"QtC /Eyu_Ix'~Tw Jo u\pR4qC.%_y~휳^#t.3 fpf|HS1i:~ ~#; .7@?a4<W/UsdFO\<(u y L<:K7.\. o+{A'b? Ǘ1%_WG?o.-j .O'Ws3vU~kiZ]B^=-#yA8} =\7%t һuRfWQSO%s $ɏ^sK s ޢ%18k8xy,U~N#&&8 Эj‡>tTZ~|{8O{ QODT)_"9#"!>;sFuG׆g]q{W>y4H/cMDz >&~ fRoMϭnOzu4 ~î) cZ{ oh!\.Ϙ#g?!|M&f˘P-sd1sx~ 9J{>k~|PJ&_|$VFtlp;}GW)|UG|Ggh8wю$2g]E Z:TrM7-p'E);PO>o/Q~rOȗ\zq%שf7:IV?jD2[#9<:O]ț=>ZE|ל%]9/%Y|"Gjǿ!E](G&p zȗ9y泗O[)#>D^u1"s~>g/ܷ)֑t%5d`pbX'~LQV>]>S_i#xv'B4֬9/mhnQI~+V6t.ZMz$p>kҎ8me'WR(q75W=ySrGgޜf}I"KEi )`M-x }e+{_)˿Q4~1%`|lOׁ7T<^[X= Y'<&9\IN-T >MT8t%{M-̢I8e#}=vO'N7fB#qYw:F S?xK]Ãܖϋte1c;M+_vJ#_>tds1:^mskC}qY|NGButm3KUKtipBk~K9L987`K8}a|yZ!|ƣL38< I ~esЃ Ofwh$VmX5 ϝLzz/i3*<}"㟦~p`[LgNik8t 6/*3 _3)} BpiUR=ye/`Gz>LM_+(b7_=4yՁo yW◩|u=\ Me=O u2ລɻwA<܋w{^Q'z  |x|( ['ujG~RGoFp* Zkn3 /Ϫ;؆n y=g>Q |)j}qijtĿplj_ZT'cS}8z 'З1cʧ[9wI[yyc9ׅOt HSg)x̍S?'H#w;j1kBǡw'xރM+jgFpxUN&Χ"ç;Dtu |g%lQO{'S_0먋mp|\T/|d3HOS6A~^#vwĿTC_cFA'rv|L#j^89Z7-ɠsr3y?t GϏ^ܤe4 k3hwԓ[Lwsj`?qR:,p./E&x?yt}WO|>O|t^A*7炯k]8\>/ҧK0Fy9aKW /Lkf!Ӝ ͩ~o`_ޕj_ma }Iqg`? l>?Fa浦#>9n?D<@v}Z wSk))sN:kG8MtY/4If{k]sRG&Cq?j.:zJs95UX+裨N' FaNm๚#%~N~̏'Dd*x럔~~a5:axk7G'=H?A5׵K2}*AIF{nYqZϧYh q8?{zWPooe oB$^r4WK.sx^κ:z\1/ pd(L:#׷:A||׼sc8D/o|XG`od^ K,S:wj2>>EQހhQw`EE~Rzxεflê_}tdȧѫ5?#Nt!CryPV ;z>z|\NṈm|N6p\pif(7sod? \t&G:ǙwaUlg5O5gQ)'qB(8u~Y6/W'֣N1Gj}t?(^4r[x~oʟb"^|syT\#s'x4?X/?nt?Y YƯ\sm#w|o/F>k+/-s^5oC<4;; [iIL} -C<!6 x vyUԜCRU[>$*7^k^]D}ͳhCg[<WbΠ(uˈ3s΄7&Q'6?8iNzuy)znpƃ-: _~=ˮsxC.̷rsz.E6p^zg }R5<{9_:C}>/|f/l%J|~[tV@M11 Ch=䗓ߟ$gOې^]ߊ?o#uHͽ4Dgy=emԡ]jݤBb=&XW\;$V+ùid^p=|_RJ/q8 O5װ E~ZʩY^ow.^wYzn!_W9A n{HW$8X~}Ze_$_'O?-$y 4O%/G'ԍ kt, H?k]X>d%x56H>| y]MZ_ė}x'..p;W7n.es} 7o2HG_BKɜ[>5=cHnn*? \ #S\Q[ p7sO0\͓o?oAyaU|/~B#xs4GD֐et{Daסbs RuT&UV _خ9њw1[qpX8|kEҏO Z3|=\)g?ξhqUwS nӇI]0@:?OL7Jpzp$՗5w wѹ)9o)oFNxOsw¿JSPt꣟4V|=ϯ9#;N= tҽi9|q|/'9s'i#n Q{?s! F ~>%`}c1ipRm&a\Ā|Sk7}Hl=uCkvi:`=$/ߒQ>@VqN'M[#^p\s3N)=x_h[1Q%KO*')g`p!g#&Q'\䵇qtkwRgd?jG|l$"['up/[3@# x})ώb6N}0y'sⅇOH|~F3ٵC 7{3D^X9\^d|ɗMR|:I)փ3.+_w&.g{}c k0l$~j~t4OS? =I?ApqKSҟLA7q 5'u,_,}äUD{>jlW|u8WҷO= ezy~U H#<ԝԛ[AG`1H|.ʳ7hݹmut6WQ7%@,Q̓qk.78T<6$d|ބoͅo3Gx2wsgޔ3w|(+8|{/0^:9~|Rxh;Hfx2Gn"Dc$| R}y8⼾Y>=C9*mD%@78>AoD{~ZyY'<.%s+>D85~|])Pg#|< ]g Cts^Cc՜;{+!~1FbW ˈ_x:̑qtSߪO/~knV 'z~+\6gAۗk.tw[kg x~7S~)*p׫yLO胥OXu֝7G5&erx|/<Ҝg*鯡Ogw搿IGù|x(FqGaG$\tܷ~t\i#&|;>/nx'u5W}vMلt~&9g `݊}Cώq~Ni <8Mxįofv:{?Ox3G+聗a/#հ4e{M{caﶅ}>̹9SUjDwPŜX/nW_?f<4}{<]A }1U^ӕ0Ƕy0*d]Ԑߣqp5vSwnfXCa++~ VO*}/ʈ?08G%9V#]d?9gN=v9,޼1!x;z) Qr}u{Ljˊ?)!zt/j|h%SKlܰ }8#&_?<6p^p)0 s]>!+ƉS̭7N_x'зo?E. '+VC⃔7)?9.Ddg3N~Z_Yğ_.y%vT:͋j苩ޔ O/? /'~Jp{c~ԥo#wl|L? t =d]rV迀̥p#% ZyaNx2G9g8/u;!_Hmүkg{Sl ?k6yyMʩG*Q+uMq^V$^ՁA r9~D:/dKNYK|&^BK#&/0 Hq^|(~,ė=J1}$q(|6pBm 9gC' _':7<a:k; ?ux؄gԻ-ԯ?"/m:x~ #EQ~Q~r5ɾAj2q!ʇ8{GCǼZk]|~ n^8/\by/;p^IϧCn<>nQzܐn+sG8=?4 8}%_< |?dL?}1m;/S}Gk?|z+{c}[G_ī~]bk<5zi Ao^'9Ź,s8NR7Fm}c4/~?R3Yҹ7SvP7>QxΣԝ8;U 8g9@Q~psY sb,^&Ü3%Np=OÛ& ϧ'?E?:<ߏQ_s^d+w8LNj QNm3u՜)UZ\II:\no+8ա=F߬HZxxBK u@7`༥yʨ&ɇw# /j!IF7_o1R2ԋ‹B q!J k&O8A͙>33W\j|ssj4sn;W?pxq0x5yS 'h>1C9"7a˟}r>QN򼁀91@}}zj4s$O9FU,]o8眱I3Mх7Wz>I=P:6I$ < 8}A|F¾uKɼa|*eoZ6{WcÓ>ƟXm'?9z~K~ŭ#s277ߋ46u}^Ö`:G*$9oo9b9RCoȡR?؈f:mmA}CXWϺwEhϷd85~UQףU?ς.MNIϠ~}81㕁_q (>м4oΙIZSj-&vSE#}1U3>#ܸ6?3F@sΤO|0붏He_+{Q9-͟yH7$xxux_}ńMoW=^ _;;H\?X s!lAFCs>}-yqԡ[W=M_j' gNߡ睂'LUk }X'~}>Ljki5@:Tq}7bnCI\ o!e <>J4'}8ry.ֹ֩t&~eSt3GS#=M:a}&^anwFBܜsNYp-n?O|Dw;oa1yp /-⳱O ?oߎ9@cF紓/?| Y#VǨsGd3 qRo>^x5^xΜF^۪񩒎x8#z^_!I6 NCͫ7j~+Y>.L; Hi"%߬+g. c(O|);'p}9/bd;^U=weRwpB.!^ u}b |w~ O/'O?MM5!pbxɍi4itnn&hIy:Qx:A9V_a|_wxIv|)/>j>3aA=q(y|rp)lj/Z+(u@_0 *߷ ]s7 ?qWxO {Qkv:Ypnrx _Jպċ<\c/n<|6^5miDtf\gʺriz+&C''D|1NC}IuzNy!֩ 0|{/7s]j/E>{"%~(ךࢮm_}|Nh?Q|&?Jǧ:R`O7'/{.\G Q>41N%?*GO;w'OA<GG[xI>"c?WGdYK᫠yG._c,\ )4W]y㞥 ?7|Vs;GΙE0AT/z8s^pʦw%zSJ*a֍2:8>၀?As͵OT#}p|x:2"-\ou33C |sz5S:4&H-:ʦgq+Yο!_/_ϏfoC%7νaMj^ ^_7;y[p˭sosϛ+zxn]?_t?i¹7tUo7οܹ̿.<%}ẅw__?E _sÛs~Us\W>眫7<߽檹ϿW/޺py^ٛ-w5u nu &vg8u<~?Cq򯧽nn~Esw$zi .87.iן.ʾէ.9ﯜw{ʹ//ys+bW8?W4s #d?Wgsռ_8u.\_7[{ⷯ+xU w5'iW_pC6e‚'^?g57/sD$OwF//9m_L;Mok?67NWο1>~k?z s>8›YoU[]W߆Hp/.ȼnvႹ7]`Q3oawe鿉b>Ap}>zd/,ͫ-u5Wwm%2^pه7ςKfy_\}[g<;y(% A=_O_ vOMi.O݅hx/|/=ųM?N O O O O O_ӯWud[]6M˦_eӯ|klM˒k ?_0 g|ьg?_2Kg?ϸ f\3?Kf|%3>wϻtttw%3~p33~xϗ?3opppt]:.q}θKg\ߥ333??} g/,wܸN ~\vkYb0<ЖBX:]Bݺtx*I C_;d0A7X:N 1P

N-_c?0ǒYzhiPbUEZ 4UٌDd}Jq,""9E^Qt?zNP# pcaMethods/data/metaboliteData.RData0000644000175000017500000006337114136047224017255 0ustar nileshnileshe)ڱ+*f5!$ 랠ˊ CP^ )IH'gz/2%̤ΤN{w?_ ןR+o{Ss|׍{u/?.8 // wk^n2s ӧM9壓gN~UOu3V^\^z*Sm_^Y{ #c~.۰ԒYG톫E7}ok_2(k99|C=+3˚w3{~ה6O~ X/w q&9}ןٹ uv_yӗ7/Z7go}q֧Һ_Zhm}o ڟN?Cߨڼ?7^l/Wy[]r˖So{O?~?+>mϬU?.%'uO_O;6{V?zׇ:~|[=|8//^7{'~\߯+gv 1=-׆i+8?˼_٢ ғ~l?ѝ~mm=Y+{ W7YMnۖ^k/mϴ&O JVONsc^Ƚ9n]W[SXٓZ[op|a}[oȬ(8pusm^DJo:~3e 6]v6=a/&]lӫO\s3e;o~>߳]sÊnsdض.Y]E#[q[aS?#{,k<7^lϼ950G?a~OO*>?~ʗEo{/OMw||Es5n:BU~ڇRcVsuz=cڽryuɶxm۱ݚ5!~֔^~MbLwٛJAeu?>mc?*[]_ ~Yn`M=w^ϷUyѽ>O=y[S/p15čq-.M dff`}U=/<ׇӀ g2cs }룦/k& d?/o޲bq_ko7u8 kC7C =_`lWtGBm-_y•)[y>~.Pt7i SyH7g2]v_ .up6x.q'., *N3[42gúS<3b_on2\ק yXxoZ򖮊O5JWG@}ے(4d,t{Ȓ/Ybh} *#ٝۖH"N+ing^ѽu㱾ߝM\=uwy1b$[da^cWWק Y?' 5gѸ|}2ⅸ%_kFHt_X^cOa}Mrc/fY+݊߼9}WkA,}2 Ob_K|v^)Ëtrr[&x %Ol&C[=.׻]*~xNj*V5q!Ne1!0~QxN+_FF ^Csb?%)˳/9|ocF_pg֎KxOOlUbps=y ~E;eޔ5}41yᙐGƸ"م]is&qۓ'㵉uKk?Mپ*ku#m0!SsxUp?my~+C~rKH~?Î7I?$J/(NH>i'NՉy.kpݶ(Ľ.k5䓛PtzIqm6~Õ'mF8}h07Wn𫞙&i\/)y`E#qy[Dcԝ9xEv7|•<W<N\;'^-8a=>7ن%ߌ8Ԝ|6W&g=q]<(8_).ךӹ)5Oޛnis}溵nے:9?t_oOI铅{qk*/[/g_/`7nbӀ–՗(.q!~>Xp*__=k߱[B [o~h+p_"YE\ڄFqqQ_k(^ËK[,\z}=Oojo ǕWƮ6^MxxF\_.>B\/Ŷ$u3}u'QvۅJ Gs΋B{td>Y|d߿! L?[[WOH= /[_sVx&Y ;I}7mypG2١l&)Ѯ6>xoʳݙԱ_ g}!NSnC> Be+=M ^y!e]mHu Lv[{+ϣ"[/}[6+ݛpW8uՃcWOQ1Լ۟ $Z֞G OwZu^겵i&%mK_l RzWoo$^{:oßdWK zQU|.jS~ܘ&8؝~NUKj[}^$ns55A*i{ȫA49 Ċ]􃿳̍Gp6/ }z3k& ˨+O7P\g© +;uT⫰_ !^%>xKoa/(>2֏gU@,M+B Bnl۳AөLӇ/ZIm˦#a~ >xHꬳyxdU N/UK kE<MxbCK@_oIx~uS\7އڙo!4-Vp-^G# +yΞ43^"\Pv-4ѵx+B엲~N>Yͯ};T?mHxGX_^>|D>ߥ#ܗ7 ؐ :Q8qWҶS VԡfQSRmήMv#_0;}05o맅:[K[q΄ B\?m -"Ok`jV}}oj`6V?-` DX_r>5SG̐SO<Oo7|yO.qlukpzFe!ܾ;o4Ÿ${ĠLٵU֔lr@x b C vJW?;C#O+^7]龽?{7L&?/K;Yo9|$^n$8x.>'嫰5YAț:*3sa)~EyCIvsC]!޴Og;=Iܮ7ZWQ^gl!yp [[nksIPWݼ)Ŷ5cBi&]W[d^<W#/QuSB{hyI 6MOgWOnYmb98XdSD> H_ r˅k]p?]YR*",xer8֚oӶ u/K Ѿ$3w%n7B?/|K|}( ~7_|u>ԇm%ɂ(~ˎ=ǗqSNeB%csTG]oEO:8w8)iS4iEoY{PTW6`N6?bG>nJ]ŞzK-q)ڗt娞IgmgT@kA?>³W] hVP?+'X׶'ӨNrZ q٭Xˏcg~>+tO0.G.VU7jL]MFuVحꈷ&2%GZnN /I~+ziƺ,85W_ ^vȰ޺4zUIOÛ)67<6TW_plk+{ p_ŃS'Rs9W'( I<:x-ׁ7 ę;oH¶wطyERyO-ڝ$gsgvsλ|~7\IJC 5ţR'#_Bf9u{/೉Wdޓ>IֱZ8r{G8zo~bXGq]/O?7RW2/+ڒҶ?[?Oo&,"/R=R8_u[p~ {Zo :DvvwE2i:+fsO}3.^\˹/v oϨxK YS0\c--ꇪVJ} >zvѕTQWG!/$<~݊ϨZ8 ѷ y滓,kmW*_OLqSSG/?R=,yS$qV.(Ia8K[CdS~3 [?si\M=iC?]>ux>s%֋o>'t_ljz\Y:.\@][yx#7Yo;7xwt8[ *OWI~3[7)ڏԛ~"&J}5UYW}΄X[Cw7χW2o/V.NhxsyTMǾ-"ިMs%^?kN[WUoU_Ḋx>]|0mG>;qQ"yuȫZ(;vmaRx|cu/6uH_ X|QtӷG]6_oG~WX UFo.Q 9{sNj;͋A<@7?ϭO]0px\IU(N,4Xת'xԧބ8|_uyme. /S/lKKGx7 jnc?@-:' 3aGV9cb>CR=8H=E iOzjzzs)䳾-Ƹ3"qAGk(>xҾ7S Gj)lϫ<Ɍ~k?3u`ZM'um=SڈB#GG~ Užu+_"VI1[ة$ bKS>8m-t)g"knT] \g_ ݭ}N}]}R3n sG ^#DV A:=a׉]| C[Po$^jȧOJl|/N"o_m#9y3WEܗ=^8ׯNw[ZĮKg>5+'S[O@}( _UQ`.nT_n|+w q'N2ukSr+{_࡙oT=?Ϩ:؇؜>Oy9S6u^R WX?F2邗ɬ'}|BzJ8'OQ_`#Jp5fNÏ'ԇ C!:VJ?dž "|y⦵)Lhg*f4~ ax#>1ЍW[zg~[.^5-<'׈_X|:ኊ3Q}}?IJt>"{gD>"@K{^ǫJ~%?>yeїˠ._7-~k'9y<~b o+ux?pW+Qoϛ_|1o4 yv^;Y|^QSݸ;>^̍ ໮>se~sܜ(?WL]UI\X\Πsa ycS|t!>pK L5x,z ~ag ?> 7fn>ԯ-[Fs=x^sx0e|&xAKD8FUP*~VDZbFE݀a;.~|[upc]G:cwGa }*+%^UG=*EJoOϕT߳^ٗ^DBMa{ I˻kPsU/vФ }JɿVD]Vwnbt:?hGe}6#ݕ>8p;["b<&t׷!xk7gkC{Izm%ꓥ W NJK{3Z~VJ|݁s}@yy doo| W":[f-\9}|Bn#/R]imo!>p3\Ih ۣuoƈWsPoȩ׊-}?:=}V ] / ܨtDYKjMv+"O_R/+[GQ1k'~Q}HhE苩o N߻<\l 8L^ҟkAi:񺼖R >4H/՟M]:*Xh4*>d]D|kIN^ qֆv~+uG> ~}o\5W+-ToܞG"ѽW)b3'sR;ыkw!}AK`+y_/`)^Vb7mbO*ʠ!DS½3%U-JlurgGr峾z$-$XSh{գ󰈇:2gDZZ|0tb|&}A~t7v,oNQ_qP]ЇՋ6jfЋ$oGf/J>x=.tny3z 'W߁"!y*Q7x^sD>^eV>J['(N7TDg0#io#y㶱{5ǭ>S+пΠkX8w?>-%K':ct]wuwV&og/Lz)z@7^Tx~;O8'n7}K9๱|Tϵ}s|ݪK?@tTj ~BGo܈y6Ǵ_WU \4|_ |iY[3&x> CԽx#/^qmV+@8g=%xgF w\8Goa tX;{{I ''}x:~L~s?,%y;M|87xyyhx\7")*Vx˵ޯ ~T_>3/'~!+"]$/Wٕn 'VS}>meBwZEGڂq;}Dc..j/>BNp|Wsvw)(}j&>FJ}6B U-8STO 9B;B\]Dw'av;=~#\,c6ZkmVl`Eb<)/3a]i4ĩ;5ck. VRA.} "Ļětө:X1.Rt޲v?tŏ냽qOH()o {B_un]Sw.pz0ԧm'޴UZz&Uk؄;YաvN]C:?": ϶cZ&"<܏ZvT\GR7;IR:c7.su[у8E]hQIggV^ pO*r4Fz8\TKB`2B?RO6«"i)b 1pׅjp⇓g鲈"cItĻ|F Y)8<N"~Z%=Ϻxr:]+ a9I*/'wVMe1OTn wgK޶?;Xɫڃ,Nae.ܢߗS <}V`u"״%=N̻}Vk_}6y,[mp:D|/]96v~>{G*w.eyVRGTݾܾR L"~'' J*t:c bF\qZɿs]_ ſ?Eŋ?go'Y໑8y)t0O:'O-#Gďr]B=X/#P'j-ǷVmH n7ǹq]kWF_X VsVz<25:y-ϙ߷SWA˘[cۉ73ffyJ5k]k>hy)X H}*??cթ= ԱB}6h3jF_bpλ^Wv70ǣU'/53o ,]rKctW}˳ik(1uItKt/~κIx'zT*=+%kS>N}C>5_;W~tYM~r4:p0Ψbu+C5/ 6{Ղᵵ2S󈱯g JpQu=Rޓˤ%BtDϰ7lo_M[TOYE[)H>C/QzrOH\K\I]%)֠ù;ؿx]ڟg J uk 7S_͂WbwDgD\8y[Q蜝|Nq֑K ki?h~F<>\a1U *y?8J+;5-=!6ĿhJ;?׼ ͍B?*0jޜя}+ ^n!V+80}E#p:kҦ4l+NHQV?kG{x+I#R@Zxa S^B]Jm+Rg7i.FK_)g!ףϫϹuG_a/=h(#5D}«ŗE|V_t8. ^֓p lֈn˜q;u鳊ԃ=<>ؑr鼨oBFաCWP: ًVzwH$= A:j(/q}5SMaѻ Կ\9OQG>m+хmR}&Oːe[o9#eXoLvsB/*}| [G 2ؚts`%<}h/Eޡg<.H9 gщ_z\x2븃C qlxׅkI9C>73AQgr-sx4<] O4CmMsN_TKW{QIY/]O_7^14դy5oqWTVL\ݦr>Ovs/IxE> ν~Ap߷Зr [7yGG>Gjn]Mkg~A?rsR'y#oGXG9u7~~j(ul_3MW>m],}\E\O\!9>';~~xҏ|Ia̭C|\p g5ug9A2?>7};VD?uSO`gѻJ7?xFuKdg 5Y;5/8#t],~0x:/0MzgV>>Cy:a?H':q|pn^!~k z!|yP+sz'+ @gp~; UPg\ƞOw|$8lʷK#!)]q#< Zcщp-Sh'm ?XFwؿK\CcFAǾ;T}嚫$y1' GԼqst`oѓ*X<1~ҋ^|o![ŷ, :29>-GuA?FMsﰓaWkGO31:7c #hb6`ߥt<$}#3c<Nҟ w#k9|c gܟ}PO߿9d&x?5IgB.6E(gtӧ(}Pu SsP=s;J|}Oܧ qj9Bw6~1Hl?[M'M[<p."so 0zL-3F? v8cn..}zWo/ zs oIx4W]zeܕଛZŏ*ZpzZD՟隣WzdƐ'e !e-]ˣՔO!_|%pWO1H)fU!V>T?WTflaU1^~B-}dM!>9`9}u2pҨ<(g=d ?hn ٙcm+nNp5Wڨ˃O:A/{U_(q.q]X?bulg!9ğ#̣vyfzYv ]nG!ncՅh>_̣scws/~C }8mEK_!qD'+9w`ީs^tVJ]Z8A}+k/ކxQ硹30#oހ }qQ^F"^M3)u9 ஠y1ӜCRP@CHWUn:t#r,_϶yWbΠ(eؙI(_kNz5yya_A/ԟzJM}ayXѣܪ:x,<{ _vaAx;^̶#;9<>>[\Z 78@n/G{ <()jdg!} k\߁>oLs/mcc#.]6/ rtO /ZNzNj^"хgޠ/D_8.g~V#}|#׷$^ s{M+}biT?oj_Kr pz[hќ*t)2Gc6@~ޕWAC>5熘D>C9BÇ= {{+p &.+>:敜wGgiԡ:s89oҊ=.6}h?}{6G :o$#;LيDZe*m#_m5Pp $WNTp\ %P}>,NzEưQ+C[Wh.q, םċQG(xr+q89V~^A#ᷙoA&27ڼdoҼn:C0"j";qs!}? _\4Py Y?OO&ء۱s !8iKz,QϣY:wLAbg4\Yn S}y8k` 4Y vYq׳4oPNa_ҿmg7;io y5Uynq\ LހWz/>qzhL_{?: -;?_*Kx}#e~6mb>R߅;X{q7EUVç78@}Po+C^ >Ŝ0ל/~Lzz1[m*=O98IE3®Jy73τ9}Iܢ.ۼ /<Ie-A.9\{S]#ޒp7@{~Գ¾Uuk Ng@_4}{CV ΀s猄x2g|^{?s 0OuW/n%-|9>;{ze!_ava_gD^'|_ )J픾7uHlu[Bқkэvi yJvSoh?@/@}\s3Nߛ~~+ mp 5/Y  ^3Fp8naǥs:<`/k#¯wga?jG؁l :Rt-g<uk+ր|<k;wv~!}xQ~>Xڡǿׅ<9;j\ 7$N?gp8tß9<~ǟ.栢^YR?t%_NTou-B}.Tt4 ]19_z]eZ\bT.8Pt֬Z: 2ovgBsX{IOq#']6Wkk?O=C7zpŸ8`Nv~yp}vckRӂd/􅞁"\@8>9ޜǧCs3Nt~nnIl>a0O_T"]˽xUG*G7>Fx_N.[O>~~A^Z!ɋ量\\?g؇ǾgYT#}(G>ɷ>N pS[Nnx=KV~}:[!vjr/P\K!q{m(:#4* q/9qtu7D/ƈCJ{ė5z9 osd-w$Y? B_ 5)x޿'s5[}w୞[kg\|f^T*g^|=uXu֝7SGC5ve}#^$y9^KsF?t$~SE~ xuףCЫoj O<^A}+np>Ha/3kz?]؛ԳP< 7_~8ue}Cώ7G#>_qI0ꚹ3Ԉ73H?qC,0x\'k4e{_|9@m-|?~9$yY }[-T3':9Kg63JyC(s}1bg߅R<_ťqZO||h?8 .jwj۝pvAOz7zk^!]ѭFPg=Rp&"'ԈZ)uva?yw`Wyd+=I珄 ss<@]y Ć1.Fd7G*E)}\Vi{W~xV#};/j¿Oh%#m?a='!3GN4zO|jNH7qcGә[o;EzO NP?>C]$6nԇկ)I%^K=ǃ}o<n扗^G!Sh^|3գ): gYkۛt~ `{ܯ>>a }#a'?#m'` qi{[<_n?YK]|tpl>0zQ]~:žպ/CSvv7xN.Ƽ:k=n^8O`D?^wyTIW\r |#W#T{hN~xL'ٟ+p|=t|}CqN~_2USwpM4|-~_uC]Rg xKTїp}"Nmb}=4A Bg3G`t9y)vO5y$^jC >wkvnN'Of~>pPtޅsb)|.& ay}GVLxi<Gx>违M>4<yy0>AA"x;>a􁇨;u4}U Z\Sԓyxo<ߎj=}B,׏ < <DzWPדo7`eyɛNy/v]xQ;qHb.~By)VLV?}yE$jzIp% kI&N5Ug )}zՠjcwG!nW}Ou>@Z+`_z7Ռ>t( х4r#{C?xh f^WN3.Eߤ-68~Cs~Y&ֿ`_':JMIc7b_&_uqJ7G ٞ'7}IsMѥO+^1)z$<:8E<888^u [)ُ@UЯ!VWx^uns<`Jx2x'5^]C觕<HXoyUqȜL/-)hHE };u9u=Ի-=fP;缊9~ 0?N2CzoXI8xc }6sѫBV1gQuCП|]s>_ N҄_Ԝ'ҏ&o?Vuc:K^_kxmgPp|z~5ǫi^c=O;~4ÉoNSF[;UIe )=uүh0̺jW7};D}fć;nƒ;c{4DSZ:/ෘ?cἫ?hGgxx44;  ^I[ȯ".{~)t v`c}M aso$ou\M߉__N_qs;a++/]'yӿ'F4W^7/ցãK'VL=Nm[WuI#C# ^Y^úARo?Z K>Tt'{{_4ou=}JvNt^Dsw#::W柩&prx1CO98/{'gWXg@.u $z] O97CF<$Ojc}bT+qF/Y/=D_nw td#=G9nw< <<'䟓{σ 3rtD(nna^:A=YK vا~'~~^|; QExo/!OPbuP?LUBp6Myv27Ov/eu#w4E*qO1aNwRO>pr#!߼|cBoe>Rǥ?ӎ~>Rsע7ʙKk1ڈǏ l M[S6[N^CCd\rP \/};2UXyk~*Ey+ twY¾\%v_U޷AwiaoG_j>58k^)qu?1@}Cqߛ9VsnM"=y1߯D'a6CkAqpQ\e6/L|Ӊ_l}ďbY/|}p?:%Ǖ'/6RV!>E_8Us8:S H^s~#6/Po8N\_@sPJgrx18μu{c??+t9 ȹ8G=>}=݅^J =Nmᶗ:NKs*"/ox\=ҫ 1+;Om YnI?y-Qx7jxI'NOJu'Տ*jp | q0v-}#Ƞ_ݦ!Ն87 uISO7>:> >ƀF/׈p2WFC`i0B.gZ[oQKܲ|(䳾~s+} GCG_M_[/}R};s/hkk_47R:;HO~ OEA7;,5?06P'qg;[5OXx ^I?'7gћoa7V'5]$aZ zVO9 t{g;r!sɓqn| wJ9x ҉jZKZ[| 8#}fs̺yU} 9.~4`-:7\=;5/›ޒ+Kx>7ُ:)g|5|6y5mS.e̛y[:K_{5ҳ3&zk:N7NKƝKyƔzo3m3'?~}賸;n9ENys^yU30ύύ:8sMSn|xԱg[>擷N}ܖٟxև^.d߿zʴ7L=]~zG^{i/z[^1_ʾׇ>15=5aį\y񨿝;L1ٟ{g|~sOٿ<ֻM6s}g\}+rǍ/O>}'ߒ^?YgƏ>鏏^S9HkW~3_k}7j>K8V5/-7N}ʛ\ucyÔsj[rejƏ*71't/G123/ ϾΗ^٫6gtԫ^]W~o藗~9~F0//rqǏ?×}`˱_F_e/їpKlY]6.}VFՄg5aO]1+F|sb9_w|E2죌%׍{i«q^]:Q.j¨Wƍm6nG7죍ƍ?hɫ _ɫq^]:Q.j¨WbBh>hɫq^]:Q.j¨WўO>[o pcaMethods/NAMESPACE0000644000175000017500000000236214136047224013720 0ustar nileshnilesh# Generated by roxygen2: do not edit by hand S3method(biplot,pcaRes) S3method(dim,pcaRes) S3method(fitted,pcaRes) S3method(loadings,pcaRes) S3method(plot,pcaRes) S3method(predict,pcaRes) S3method(residuals,pcaRes) S3method(scores,pcaRes) S3method(summary,pcaRes) export(Q2) export(RnipalsPca) export(asExprSet) export(bpca) export(checkData) export(cvseg) export(kEstimate) export(kEstimateFast) export(listPcaMethods) export(llsImpute) export(nipalsPca) export(nlpca) export(nni) export(pca) export(plotPcs) export(ppca) export(prep) export(robustPca) export(robustSvd) export(showNniRes) export(showPcaRes) export(svdImpute) export(svdPca) exportClasses(nlpcaNet) exportClasses(nniRes) exportClasses(pcaRes) exportMethods(DModX) exportMethods(R2VX) exportMethods(R2cum) exportMethods(center) exportMethods(centered) exportMethods(completeObs) exportMethods(cvstat) exportMethods(leverage) exportMethods(loadings) exportMethods(method) exportMethods(nObs) exportMethods(nP) exportMethods(nPcs) exportMethods(nVar) exportMethods(nmissing) exportMethods(sDev) exportMethods(scaled) exportMethods(scl) exportMethods(scores) exportMethods(slplot) exportMethods(wasna) import(Biobase) import(BiocGenerics) import(methods) importFrom(Rcpp,evalCpp) useDynLib(pcaMethods)