vcd/0000755000175300001440000000000011720430152010670 5ustar meyerusersvcd/MD50000644000175300001440000002050411720430152011201 0ustar meyerusers1e0bc98308ee3945b893ba957383bfac *DESCRIPTION ef563359850db139cac3c8e87731398c *NAMESPACE a4c0795384ae94f7d0349cb21cff181c *R/Kappa.R 244cf8918c239a9b0483c13b4656db1c *R/Ord_plot.R fb41df0cdd3821439a7c782166300749 *R/agreementplot.R de1dd373ec451b231e8bed60665ca911 *R/assoc.R c69cc2cbab432d4713b8ce4c41aff4d8 *R/assocstats.R 630074b55ebc6fe379451eabd286d8e0 *R/cd_plot.R 3ea43d07743875dfce874f4cc067196c *R/co_table.R 1cfff0fdbfa0b20fe4e691b997a5a328 *R/coindep_test.R 5e817ef2b14973a5537f5edb0c6315ad *R/cotabplot.R fb4b5c897bb4c37dcf263635ff33eb18 *R/distplot.R 404c2d7be10c796079fc3e68a0186e3e *R/doubledeckerplot.R c120768abc1c61e5f2eecc168376dcdc *R/fourfold.R 551270d63bd1de2418ccf32ce5430462 *R/goodfit.R 28c740a578ded3b5263f283da35c6f95 *R/grid_legend.R 2c061c5f3b6c7480155aca387cbae2bf *R/hls.R c0fd8b5aeb29007f2df6c344f73c8b93 *R/labeling.R fadba320d61531d41c8dc41913f7a731 *R/legends.R e3ef35004813f8b56b2dbb0d9159ba79 *R/mosaic.R e4f2691bc8e47cb87b1a9407af0dbaa6 *R/oddsratioplot.R 3e28e9a4039cb29fa398c55f73ec89fd *R/pairsplot.R 7c06bc6117e8dbcca31dcc2f76ff2307 *R/plot.loglm.R 57c2a8e1d679141b9538e7128459633a *R/rootogram.R 817a0411b6221ddfd7fbfdf4bc7b7921 *R/shadings.R ba1d9eba99cd9e48a00ea50ccfe2620a *R/sieve.R fd79ebf9c8a9b483b500bad1f0b228e9 *R/spacings.R 8c1e69e46e0d3127ca572abc3b813924 *R/spine.R 109ec21c6576caed57263dd32cef29f1 *R/strucplot.R 6ae7ba9dbb0a2e264593dc03eb355d00 *R/structable.R f9cb38c8cc2490f84245ddae3bb5700d *R/tabletools.R e828a3fdbfa5e0871f13ad2ebe8531b3 *R/ternaryplot.R a8395e661cfd7f767e167cbef6f82714 *R/tile.R f1f0d3194326666f81dc1ef97623a911 *R/utils.R a54ac332c792d35e0846d4bf45d45bd8 *R/woolf_test.R 1fcacdd810545176c5dfc8ad4be480d3 *data/Arthritis.rda af42b0e82f7602ef3a21ac54ba67071c *data/Baseball.rda 4956f3321e6fb5582e3f2ba8901012cd *data/BrokenMarriage.rda 4db232a9f37c6afe361051f4f3d425a5 *data/Bundesliga.rda 93e7f6208ec8c8db86401c1afc3320f6 *data/Bundestag2005.rda adab94166082d5cab1b6290e63340bee *data/Butterfly.rda eff0e0ad4d9423fafeb704652f85ce83 *data/CoalMiners.rda aa7e80a1cd039d8fc05298dac9a2d0bf *data/DanishWelfare.rda 334547aefc59c1583fe5e986521ca940 *data/Employment.rda acba7fcb07a1ea519867f08d5166a1da *data/Federalist.rda 59c4403257e7fdd114f70aedb279b9eb *data/Hitters.rda dd8f043ff4cd82d9d74972539be0ef1d *data/HorseKicks.rda ee6552c4ac7b091e00c27862006b5e63 *data/Hospital.rda 30aa94bd0a31ce461608ba6934ebe5ba *data/JobSatisfaction.rda c8f5e67eab217718fa29e5400dd45bf5 *data/JointSports.rda 280cd2c5c9cd5ea5cbf82f0eead25aef *data/Lifeboats.rda d72362ebcc0ee03de0a660bccb5a1a12 *data/MSPatients.rda ba9681b79f4ebe1322cacaa081b968d8 *data/NonResponse.rda 134589af7ec903a3c3e00d4206dd1360 *data/OvaryCancer.rda 367544d269ca5e57fe7a79089cdf5bc3 *data/PreSex.rda f0935833b88518d4cec4cbd4cad1c93c *data/Punishment.rda 85bacd321edc3ca7251548fe69056f09 *data/RepVict.rda 6847170fba2f90971713d24df3894ad9 *data/Rochdale.rda 99873a84976e8f73a6e091764c30b73b *data/Saxony.rda d9056090e3ef45162e3e61a33e9b1bc1 *data/SexualFun.rda a9971961ea92c34cfa6df11a2702ab57 *data/SpaceShuttle.rda 0eb87cf6d2220269883447c796eb51b0 *data/Suicide.rda 645187968a5775ec0f32c58b00fa416b *data/Trucks.rda 8bcf43be5a80e53804694b015f9311ff *data/UKSoccer.rda 203346753d583e64ebaae114e009466f *data/VisualAcuity.rda 7f1432aa827fde459adce4e66fcac287 *data/VonBort.rda 2b834e0ff62003b1f9f8d98e42d0c7f5 *data/WeldonDice.rda 8e92d494d9fefe1e0d2ddf8a680821e4 *data/WomenQueue.rda fea43b041738222b9ca05543c2103248 *demo/00Index 6446ca2edeae8ffaab647cbaf9badc92 *demo/discrete.R 7eb8e56560704b20fe6ca89df6a37843 *demo/hcl.R b96320b9a646b8fc6c63661f49b6aa6f *demo/hls.R 002ca3d1e79c9d84416d3b4e0bf8024e *demo/hsv.R 1da0bb6bdd21c0b13a1599b2121253be *demo/hullternary.R 32aefed96167152c94cf9f5c1a3708cf *demo/mondrian.R a61a25a7b48e3d172cc6353b956c9392 *demo/mosaic.R 7b08161f2cdc60d9e594f3aa76479272 *demo/strucplot.R fb58c51aea5669bb1aa5f7bc93119881 *demo/twoway.R 1868ee22006e7378323f6581a91690eb *inst/CITATION c2f353708e22037a0bf750728ef6b118 *inst/NEWS.Rd 602c680f1ef5d2af17cc38d59a8426a9 *inst/doc/residual-shadings.Rnw e2ae9e23c2ba8efc9d2551706e558b3c *inst/doc/residual-shadings.pdf 607cd06d4ce9e4ede162f870a26fb27b *inst/doc/strucplot.Rnw a7d692739fff1fd837abc4aab4982016 *inst/doc/strucplot.pdf 52757bd94ba340a720830f6075f8b0fb *man/Arthritis.Rd 912a44043a40235b1800aae01d50042e *man/Baseball.Rd 1059d318cb78e6586c3b772ad941cc36 *man/BrokenMarriage.Rd 946f82b735010df751088fb117cc84e8 *man/Bundesliga.Rd 23f1d7e5d9a6d33812db961e11313c98 *man/Bundestag2005.Rd d5d5c262a89021e918ad8ec488568ed5 *man/Butterfly.Rd 5b05c0c3e6383c22357387af6846f9ac *man/CoalMiners.Rd 9a605318f578054afcff4fbe130450c2 *man/DanishWelfare.Rd a8fbbdb872f26bc25aa776061febbd36 *man/Employment.Rd 5e26cab32f3905b6b243f5688dd11cb3 *man/Federalist.Rd ceabf42729a57cb25fa2c707572ccbf1 *man/Hitters.Rd e559ebed2dae1632aa67296563f05b2b *man/HorseKicks.Rd 8e75757feb4d17a3c40a34a0dcc3ca81 *man/Hospital.Rd c533f38a41280541958fdec1520d2341 *man/JobSatisfaction.Rd 4f60b35a1bfffbba60802d60d19d2d35 *man/JointSports.Rd 4c1ae42d7e402ef8b416133bdc8cf856 *man/Kappa.Rd 0ab6cfcde586f29bb80ba421f7de5350 *man/Lifeboats.Rd 09bb004fea4d21926babdd57628908bc *man/MSPatients.Rd aa707134c91334b4c6e9ad33af97a6b8 *man/NonResponse.Rd 4c3b401a928c18aa938b932412b29d88 *man/Ord_plot.Rd 946497fa005b8f2ec4c6d43e667d7fc8 *man/OvaryCancer.Rd 3ffa16283546c87e5c81190cddd976f8 *man/PreSex.Rd c5cdc599551ae8d2f0a8dbf3a18363df *man/Punishment.Rd 35dd143e4e35bc2b72804ca99e6f746e *man/RepVict.Rd 7c9a39dcc04d539a98407436c5254c20 *man/Rochdale.Rd 250e3176df959f30b160b10b381ac598 *man/Saxony.Rd 57dbc598ae5f4a0b07023d97b9eac55c *man/SexualFun.Rd 57c0d552618bf1b43de02a34883d10a9 *man/SpaceShuttle.Rd 0135b1039084161d9304ac1e9f983467 *man/Suicide.Rd 88b3d9056e47f6f3a7120c6bec9191e9 *man/Trucks.Rd c4221305498c64d7cce56fd05d38c10b *man/UKSoccer.Rd 48b1d95e9d4b09c3b142cbccca21f574 *man/VisualAcuity.Rd 36eba659eb6ae3203f9103a86d41bf5b *man/VonBort.Rd ca83003c80bb9d41eeff4805c4f4df1c *man/WeldonDice.Rd 72e0e324020dbb52d40709c115b30ee4 *man/WomenQueue.Rd cae4c6d78cd852a00615696387b59e15 *man/agreementplot.Rd 38c2b48f456a2c8b982cefbb2a4cdaed *man/assoc.Rd aa9b2eda917003bc2ad6c6ecfd5dac25 *man/assocstats.Rd 1ac905b88d759b08c37f895d5d7c81fb *man/cd_plot.Rd 09171e763dcdae39764a92d5359965e2 *man/co_table.Rd 83c9d27f830219c9a71f6f3d9a8168d3 *man/coindep_test.Rd 21d8a4f5194bb3721632a0085d245b94 *man/cotab_panel.Rd ff865e92033951fd7d93ab981531bcd6 *man/cotabplot.Rd 4dbf3ca6269f2e43b1dc2d0c814741b3 *man/distplot.Rd feb661d6f2e2c1314caf80e32fbf6a6b *man/doubledecker.Rd 492f0f2c44abc43fff6d8bfd5de74870 *man/fourfold.Rd f2082e60016ee1b96a1c602fd611579a *man/goodfit.Rd 2254d6c0ff6f6e3282460c22600d68fa *man/grid_barplot.Rd e1ef9d594744b45f444b0f601eacfb3d *man/grid_legend.Rd f3084a15ca398a9835c9ba3eae26f773 *man/hls.Rd f9b406c3111ee9cacaa55124de6c9df8 *man/independence_table.Rd 6ef4c333cbbb2490cee751eb360de9e3 *man/labeling_border.Rd 926f10258bde9d18e8d5e9c869529958 *man/labeling_cells_list.Rd fa4bf5cf0eb4a35d77af44fd58fd360f *man/legends.Rd 6166d08f94e23cb571c4d655eeaa66cd *man/mar_table.Rd 2d7d88c91d6eca43c824f96849c105e1 *man/mosaic.Rd 56140ffeab23c02a6a6b543bbcf28564 *man/oddsratio.Rd 868ff420f4eed095c6b98f6f332c2eb9 *man/pairs.table.Rd df992e85a8fc390f22e15e626b6ce549 *man/panel_pairs_diagonal.Rd 75ae7e1aa5813e8583fa4b1b5b2f4ed9 *man/panel_pairs_off-diagonal.Rd ef922554ed4055dd2effd2a72642d901 *man/plot.loglm.Rd 1a62c7f339347df3153f69b28c9a9dc5 *man/rootogram.Rd 11aebd503b7929260bfe48731fa01d2d *man/shadings.Rd 3c7941811a6c46ddfe81b2539c74bce4 *man/sieve.Rd 6e12036047f9ee2619bad64902d7b562 *man/spacings.Rd 9475ef38895fac17d95f0f4b736c6d66 *man/spine.Rd 11eb3bc61ee26cb74aca0e383f0c0833 *man/struc_assoc.Rd 755c50179c0b66b9b188661d6c38d470 *man/struc_mosaic.Rd fb4ea0ef8c1539fdcb9b0434d2b655dd *man/struc_sieve.Rd 5199198b2bea136c045829882ca2c187 *man/strucplot.Rd 540cd565f07378f320e96801aa29bbcb *man/structable.Rd cb980b5da00d2ca687b1cfb9f6750256 *man/table2d_summary.Rd 4a23aa9782ff1aa067b15d76e6f6287e *man/ternaryplot.Rd fa04dfdca119943015fa09db83e183b7 *man/tile.Rd bec04ba65f65e48db59acafdd14e3caf *man/woolf_test.Rd 60b5a25113c95aef01c2793f797d69aa *tests/demos.R 1bd85dce9589862a54d02cf5687befcd *vignettes/Z.cls 602c680f1ef5d2af17cc38d59a8426a9 *vignettes/residual-shadings.Rnw 0f08ab21c366ba4d4204fae211e89104 *vignettes/struc.pdf fe22f0d95f4098096281d58c459928f9 *vignettes/struc.sxi 607cd06d4ce9e4ede162f870a26fb27b *vignettes/strucplot.Rnw ace1d42555f8fbfb6345c83898c59e01 *vignettes/vcd.bib vcd/inst/0000755000175300001440000000000011720426624011656 5ustar meyerusersvcd/inst/NEWS.Rd0000644000175300001440000001152211720300221012702 0ustar meyerusers\name{NEWS} \title{News for Package \pkg{vcd}} \newcommand{\cpkg}{\href{http://CRAN.R-project.org/package=#1}{\pkg{#1}}} \section{Changes in version 1.2-13}{ \itemize{ \item \code{agreementplot()} now allows to add marginals to the plot \item \code{abbreviate} argument of \code{labeling_border()} renamed to \code{abbreviate_labs} to prevent name clash with \code{abbreviate_foo} args in \code{labeling_cells()} \item Several partial matches fixed in code } } \section{Changes in version 1.2-12}{ \itemize{ \item Bug fix: \code{assoc()} would not plot tables with 0 residuals \item Bug fix: \code{structable()} adds dimnames and dimname names if none are specified \item Bug fix: print error message when subsetting/selecting of structable objects using more than 2 indices \item \file{NEWS} file changed to .Rd format } } \section{Changes in version 1.2-11}{ \itemize{ \item Bug fix: \code{gamma} argument removed from \code{hcl2hex()} } } \section{Changes in version 1.2-10}{ \itemize{ \item Add aperm method for structable objects \item For use with \code{shading_Friendly()}, \code{shading_hsv()} now sets the line type of borders corresponding to \code{abs(residual) < eps} to \code{lty[1]} in addition to setting \code{color} to \code{line_color}. \item In \code{fourfold()}, modified default \code{colors[3:4]} for non-significant log odds ratios to be more visually distinct from the fully saturated \code{colors[5:6]} for significant ones. \item In \code{fourfold()}, allow the function to work with tables with more than 3 dimensions, by restructuring all strata dimensions into a single combined 3rd dimension. \item In \code{fourfold()}, modified defaults for \code{mfrow}/\code{mfcol} to give landscape display, \eqn{nr <= nc}, rather than \eqn{nr >= nc}. If \code{length(dim(x)) > 3}, set \code{nr=dim(x)[3]}. } } \section{Changes in version 1.2-9}{ \itemize{ \item Fixed \code{Ord_plot()} for devices where the default filling is \code{"white"} and not \code{"transparent"} by explicitly setting it to the latter. \item Bug fix in \code{as.table.structable()}, returning the table in a different order than defined in the structable object, confusing in particular \code{plot.structable()}. \item add parameter to \code{ternaryplot()} to control the positioning of the plot labels. } } \section{Changes in version 1.2-8}{ \itemize{ \item Small bug fixes in handling of some graphical parameters. } } \section{Changes in version 1.2-7}{ \itemize{ \item Corrected df handling in \code{goodfit()} with ML estimation: only non-zero cells are used. This is backward compatible with versions \eqn{<=} 1.2-4. \item Fixed bug in \code{goodfit()} for binomial distribution with specified \code{"size"} parameter (introduced in 1.2-5). } } \section{Changes in version 1.2-6}{ \itemize{ \item Small typo in doc of \code{co_table()}. } } \section{Changes in version 1.2-5}{ \itemize{ \item Bundesliga data set has been augmented with the results of the seasons 2006/7, 2007/8, 2008/9 (thanks to Torsten Hothorn). \item \code{goodfit()} was modified to treat zero cells better: \sQuote{Internal} zero cells (i.e., counts below the maximal observed count that did not occur in the sample) are retained (and not dropped as before). \sQuote{Trailing} zero cells (i.e., counts above the maximal observed count) are still not considered. The documentation now points out the problems with the minimum-chi-squared method in the latter situation. \item \code{sieve()} now accepts a \code{gp_tile} argument to control the appearance of the cells (apart from the sieve color) } } \section{Changes in version 1.2-4}{ \itemize{ \item Bug fix: labeling arguments were incorrectly handled when the options were not provided as named vector \item \code{ternaryplot()} now makes use of the \code{cex} argument also for the rendering of optional labels, if any } } \section{Changes in version 1.2-3}{ \itemize{ \item \file{hcl-colors.pdf} removed from source ball (vignette now in \cpkg{colorspace}) } } \section{Changes in version 1.2-2}{ \itemize{ \item \code{strucplot()} now accepts a \code{df} argument that is passed to the shading functions. Also, expected values are no longer computed if residuals are given. } } \section{Changes in version 1.2-1}{ \itemize{ \item Fixed a bug in labeling (incorrect handling of some parameters) } } \section{Changes in version 1.2-0}{ \itemize{ \item Moved color palettes from \cpkg{vcd} to \cpkg{colorspace}, including \code{vignette("hcl-colors")}. Package \cpkg{colorspace} is (as before) loaded automatically with \cpkg{vcd}. } } vcd/inst/CITATION0000644000175300001440000000473711633646522013032 0ustar meyeruserscitHeader("To cite package vcd in publications use:") ## R >= 2.8.0 passes package metadata to citation(). if(!exists("meta") || is.null(meta)) meta <- packageDescription("vcd") year <- sub(".*(2[[:digit:]]{3})-.*", "\\1", meta$Date) vers <- paste("R package version", meta$Version) citEntry(entry="Manual", title = "vcd: Visualizing Categorical Data", author = personList(as.person("David Meyer"), as.person("Achim Zeileis"), as.person("Kurt Hornik")), year = year, note = vers, textVersion = paste("David Meyer, Achim Zeileis, and Kurt Hornik (", year, "). vcd: Visualizing Categorical Data. ", vers, ".", sep="")) citEntry(entry="Article", header="To cite the strucplot framework (e.g., functions mosaic(), sieve(), assoc(), strucplot(), structable(), pairs.table(), cotabplot(), doubledecker()), additionally use:", title = "The Strucplot Framework: Visualizing Multi-Way Contingency Tables with vcd", author = personList(as.person("David Meyer"), as.person("Achim Zeileis"), as.person("Kurt Hornik")), journal = "Journal of Statistical Software", year = "2006", volume = "17", number = "3", pages = "1--48", url = "http://www.jstatsoft.org/v17/i03/", textVersion = paste("David Meyer, Achim Zeileis, and Kurt Hornik (2006).", "The Strucplot Framework: Visualizing Multi-Way Contingency Tables with vcd.", "Journal of Statistical Software, 17(3), 1-48.", "URL http://www.jstatsoft.org/v17/i03/") ) citEntry(entry="Article", header="If you use the residual-based shadings (in mosaic() or assoc()), please cite:", title = "Residual-based Shadings for Visualizing (Conditional) Independence", author = personList(as.person("Achim Zeileis"), as.person("David Meyer"), as.person("Kurt Hornik")), journal = "Journal of Computational and Graphical Statistics", year = "2007", volume = "16", number = "3", pages = "507--525", textVersion = paste("Achim Zeileis, David Meyer, and Kurt Hornik (2007).", "Residual-based Shadings for Visualizing (Conditional) Independence.", "Journal of Computational and Graphical Statistics, 16(3), 507-525.") ) vcd/inst/doc/0000755000175300001440000000000011720426623012422 5ustar meyerusersvcd/inst/doc/strucplot.pdf0000644000175300001440000246467411720426623015203 0ustar meyerusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 4255 /Filter /FlateDecode /N 91 /First 739 >> stream x\[w6~_uNb9={NMέy%b#K*Iu~6ԡH|sUIƭcIfYaL 33.>>:C; hd<h7LdF`k䘐L(ƌ #Љ3afB0L % :i&D'ävˤaL'Spre2|J&"L_́wKZHǴ4gb1^dhT!(Ɍt43/+͌sxPDhr ˘U6: "0 #ehJ} f6g`l4!1,@i9@:(oRNj :,W % -ᖘ--֒@&B>.4ud=dǀ_qCQlG`a 9PrdW!(ƒ2 9ݐJXd6 l=coatCW_sҝ-gx=oqU<zӹN%Eƛ d۲/QِBdyr{-JzdG@wo_t?|&mxoM[Mq$Xt^:"<⡇,}AF-Z Ͳ$'' DBkNƉcثf_VxHQՖZVӲj>׳ceXXe(Xy|X:f7O0cVb$l❢IC <->/:.f_쬬ܩ01G>$V .Ov_`J)CMB~ ʝl1QN FɟJwK60;lBd a{Ff\OR&l9Fh]KzhVuLz<+Q]-yM1S+>kPwո4N ceG}bspĢ k n?bc#_ѵvW,svʹ3[O~1o 93_;ʠMP9AWP]jMLG'lFCd9RpȐM8&R:BKTW4̻AfH@|Gx B <%iSQU9O?!aWe ,8L+0L+ _ Rk]3.Qw3cHUV&D!js ܻ"hkXU'9A T )~A*HגTA@kzFDAVV*ʉ(>C<&~[ 3X께D@)e&OZiH݃gV%CѽVϋ/ՌfOրj@y[blLڂm+mW'T =p=aѩZ &wLdË'&X5b'>Ay vT>!c{}s_#up|('TҴm[xo{s\dd De-֞ kZë@X+lXWJ^`siZn։ؾKFa4<A[TJPwYz֨hw !g`Cx.ͱ3k\+UVPzT|[of`,35IWf-f;h3s7)eaLҞh*~ Q E_V@p_VI[gC XEyAtc,_ꥷA206 F&xY9 9Mb*c*6.@8jG!ҩp)$p8U # B,\hq("rKP6^zq$i1*$Gv5T TE"+ꜗֵBZK{"pNAGBoh$ge5 i<RE(技D"p"@@Lb2 dxAb&|@S2 T 1x(PQQP T 1@Lb:@R|C< 09$ z'bYŊm^6^ְZ.;߱& 7I n%.';n ǟv} Ӧ]bgYhe>j/E= \Ra]Cb-?jscckJsXuc_m[8KHq,3$RLWi()AD\t_yӚYhH ohHQn\_]! L/MgK$FvB'^)nZT]o_(T+@X$| ;ĤN&ߎsI.[!~sM&4hC(QV^ ݉'s[\ŬE Bp1'.]_/r*RUF WcHWIJ/EJa7` 4H6P R F[ N՝%g^aTC 0t. ]Esjȳu?}y1fpA0rPGf -Vyf([Z2,5C?g0~C|syR0~AF=5ϽYZ #EI^cZmlj뿣Or@W_.l!i+Bޖz:/8]LM{l(ͼ-LJSZOHД'U)PS6SbMI]i{:O4#=KL,Fed%F[.5 e3fva#d )id=M ' 7Lox܄wiX+p]wr ¹_\y{ oAZ' ,mIEanǧȡ%C9FyFmhƯ;6c.hrw4ܑ\}]nfNHՄTLHw^E~v̷q{[lюaC"tV!{@G-'MB@SIMBs,&W1uO=.F(#}+qB ]C6~>m^ba*}lVXM,\W14)W_1?^Me; l=+Vc ؓѤ:a^\- U N]Yіx‚]aaeNv0ʺ. Сt^C[#Xe5;.g3eOMQb:oT4|Tѻ¼Ft> stream xڕYK6ϯ`%TՈ&oNSNy(zhDf2_~ırY$FC7w6Ziiճ_L87k'3NM|t]W?\W_@?w𿖎"ں~NC'xwV߂+WWenA<1vY䡋E,BC^ko9 vxX{ߑp~?_v  ?p6E%}qu 873/I1$ȢEe%0π1@)pQ%Q?]8E@0ՏZlmC$}.& &n^hB~C=v)@1^ ^Y.@[t{Ŵ,r>ڑ@3a:a} @[pVz ,z9_SA;Ly<ԝE(w͐EB2 ͽB ʌ/V>ɻcxvi2Xј H=G 0 {YVþPDW(\WELKp@[Qq;.zU/%%tbx8 $Ɋ#vFӀ OpJc0QdsHsR9 BSZ4aHf v)P@RR=;N_3%%sfHp-Dз (wMmaDz~jff$|<\2 ܪKnċbkspCD1@QsIt#Ç='JXXP69AcW*ˆJ*$L1 s/쫇kY5fRZlg췖Sl [ &XwzژAɡ.յ ..b$ v/0!KlEyap]A D r1f6XSl$r mjMK&PVSBa%r:KvR:gЋBq6SP8 sLS>m6葕yȤ<`)KeHGR81Z;ٷÉBgZ$?~kw!VBny;~مse:zzH? -Nj^(+8w m"'Z}%Ւr4Ɔ: M'1<3PZ6tQMK;ߘ/x 7Ky"G] B/F)(]`)vʓAZSͶ_r):||Ԛ= {$W/ 8ȑa5R( MRZe3|No&wh]nj2)#vl$4nKl V;eDI=)BSρH$ )Z2U&b.JS/M=('! ȗ/6 EKqӶmMH5?qM IHePTbu%% eܥ',\p;N!4v~RR?JYvM 8)/5h&Z#r<;9G+@nɞ(쒿+U ޅ;sD_ЃM,$jՈk&Iy\l)41dendstream endobj 94 0 obj << /Type /ObjStm /Length 3053 /Filter /FlateDecode /N 91 /First 790 >> stream xZ[sH~_o }RSxg㲓Mf#lAd; ±&ran_>>Fa>,P(dBJELẌ́3:Y2❯RgTp6L ƒ8L)?d1J&ϬNf-pB! 4F$19CH +IF0!1$J: &$CѤ|eIDF@a"$9zDT *)%^, \P!.H.J2FCfP"ZAׂDeM5(F' eKLA{c@9prlhHʡ؀rDzFddlr 0,K1!SCYR?dSALED&UL+2FkKRڒ>:pMO:\A 3lHfT@ndLЅa&" gR4*`V'!(“g!' Cbe&pY8 ?05I,+}ZP'G-y~c^mp`] lGî@=`a]cr;Ƥ_m\Gϥ4C }J#`Lax(hRף=>NZ{P )%CNˢahjrwCAt}5v\no( W7.WwYuڀ=)ާ_\y;MZBq:W>pdIZ=\My{S$4+\hiYɪe$I-rš.Diƻ^4hOּٴ.b,ջ˃W۳;[Noֵox,9&#@n؂_Vr }1XS!Q!h#-C}&5Th>}XN@QgA*G eh2D(}n cAju( !hQ< ƴ;BN/'hrxzژ_ڐ1Q9D{.P-PuX;E5)O/s9NzRE/E %Q/]q\VӴ|CmqnD{syWTkLtZCT*EqM~/:Eܢ[A<;JZp}oeb?$mxZ\ qw&B\;p|H,G/q7"*3]+U1hբ_j$S\>Κfr[7 7 '!Qdھ@kMkjۆ7P-Wn]!rvҖԆ[^Ww~4{OwVȳ5DQA.p;Oo>|A=6Q$nv(_e.jϋ>J 'P#}ޘ$0i3=%`Zλ/ -Prk20AWS\uvr~!]*QX՛os!RÐa9].Ӟ?D7aDA#$D^gmvioe)#9&#tBC{1m{ۛ m2"P U̫__[+[ӄ}dȋB=wݵ8 Ga 8NJilE׺={͵~Ogc0W:!OHI8Kn^^-k)tИCANfqt%|@HX!0tGO<%7~$bfTw9t/d+m1SǺ;mboIvH%B7%X8H[}qĠ-qۍ8?z)R֙*2Vb*R娘P#_Q|” Zlptфx#.z/{>0]񁝸K MFSWp:nbVM׋8A].ټyTt>BML9Rm)Veفm,,k/4إ{S>|<}U,qNeuyMO˴-9YV˴r\wѧr$_֝FXa-8K.,)kpAL3JQj2\gdq8YhF#R}~N^Iv@3LP;8YyfӬ^b+GYаj׌iz>ԇ",릜g%(2oP*ÂUᐢ`}ZhVY;. YV0԰-CFC,(ܸ ׎  Jf([t ˈ"{~G =>X;V{RoC~aCD +  B[xB!g<<͊"rk9OEYUgi>]3oR&7U\MkCmVY}pVVETf>z-(J9]]l+j=O;l =ҠŇǷCN4%#MPeVC 8sVJn7##'$_~Gb[Uh`iG3Jf6Wu^ ^eMZ5G4 Wʬ!mMo~F$-~Qޤ"2^'''2:-M1C @3 )+H7gYE`%J6arYm<#HAS6u}uΪ;dy~OĺUʅ1Rendstream endobj 186 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3101 >> stream x\Ml^r`EVH$`Di i= $0'#ȭLЛ| ` "pb b#T`i4-qN7Rw V;o޼yl# aaaa~74}M;<}-YEBH.rG@Q .jwFY-'< Zo~E^VG^x?~~s2g˕wg{ >=pgmn-rl߲my$f A9gi988H)oܸ'NsM7Ξ=\DL41YLb}Xmqi9_7_ ˟>|dd_Iwߵ_l~WfsffƕIY O~gou Mrźr-GBYRӴms$@)-JbRz8F&I'=gA~z|bqnf8]0!$ZBdHpfd8R N=z㗿enA]=ϺyjFc3&QچIw.GG?jqqq74c1?cnPpwEQEI7o裏cbs^V/_|3g p8D~\*c_{4%.'ܵTӴR|:!ę7r9! UUunjGPx(MF |pN Zcݻtҕ+W>D"u˗rĵkVVVRo$L&9{n,H$"I]BH*RE4|޿?(Bhrj:IZ{6{t^nqثOӛ@ Je2l6{ܹ :Btiiidd&ăw㏧ ̌1ꫯzoir\0@ @YXX}6tma?KRA?UU1Fa`R $I{HKYVǟ^0mCZ Zx<뺘Ơv֗0OPZmB:݂x|؆qd@Z/!mT8!*e("2m[uoFe*o[`H7YZZb>22"~{EQr TZUULT(j5YAS[ lSNu\Ql lV:k9RHa^J7<00B&''< 20ED?ڠ8 JH& )HKf_^+6sG4+˲PT Ì|>FKR>e˲!J1R444}$ɲ,˲l6Ml!pb N$I$p1 mXث 9׹x|DKٜ(!$b1 ('CM%ɤR)2!81 #MVUՙ?NPzy'\8ںGNpo8OHpU}AQJ{w^z wHp[ i=xy"G #Ji("QJ_~eҊp8>/Z DQ=@9== mgaqq}áj !(gۈq|nk]AjBUf@ ,:.y2^'IMN:eF9TP(b14Q>Di3"B!4u]WفYQAtj10Em/$-ueݼyIV>(J(B\em{Loj4P((J>'IEDIwvvֶm+laxiB jx닋0εZ -;mX8EQF{CKH-=8iBH&S}Jj}GփUL{"'O$\"<3+5Kc֌EA&c)#d2Y*UӋ>V=㻐HїMZ*a~ ;l^$Ipٺ#0MI$Ip3NoXLmCOք }-=ݏݏݏݏP([endstream endobj 187 0 obj << /Type /ObjStm /Length 3534 /Filter /FlateDecode /N 91 /First 822 >> stream x[[s۶~?oM'c~aخ7qc;iNhx"K(I$eb9X$o !0dHTT0e pWjf΢MjwRAw,BTZiƢ Y 2EA40 )1%m@3< zZUԁ'E=N.0-L< ieC,դL[H`tWD4@$#=f2c_qj<3>PLJܩYqYJiͬ%Xa9jc)q̦^y$@ɜ$ K5"Їqƌg* {IS(R*+Q@CM`C`kYȱCYWA[IYHa K(;D Kli Kp4`v N& _匟*[՗_lXF'+^mE^C*y@܍|hbJ2`n˨T`xy!3t]&}٦ m:Dk򌿚Nz?u`Nߜe`:0z zr n nVc:t6>zɿAlYtu&ilwW$?y]ݘhCwtīZ_dOݦ6!) V:PxMуɺI^N^^.V ("_P٬Y ]uǓ C˩%S4DY1Ts8ͮEd/糫ue?GYiܛE\u#dz;Qqƅnh>ЬfŸ0qY\WA-V~e1 ;|2G`FXe4Yoy旃QY12M'cϧ95DϬ#Sʢd<Of|42҃1FY~8_d(b2?]G.^N6VllolȷbfE[i&oVm[iOV÷!MLf''ʸw$|V]F~y] y=]G dzaӳ߼=u=iX)㇓ItǻiTLAA6'9l, m< M-A%r^ OOǐdYv>?JDRC2˷F%Թ?_ e[@P:$6`^ -TsI@8+ 4O';"yZ3|LUUkSy1e-<,m%˪K#3J-nZ!ɫKrx:+݆دԪSll6>8~h56ߘPkH_mz.蟾k t@l.}M,(fgaw9ϋ~LUotmB5-6|X%R~(PYzh4Z_9A;:r~^b\l cx]w fBb{ _V#fZasZ/ߑ.~7^ (.VbkOkϬU}[MD\)ZG13(Z:9B B\h O靷MjQ!FM"@5Eo 5*F:'8fTq#*&=@k=RWK({*H~+Hhvim͐D6bW]m+H}A2jJ,!%g*vDnQs=PêWQŚxP8wT֦ɦ K{T c5)lL7=ƓƫTs^~iwUKS[TJ6j+kC g{)$lLUߌM6h)VusZFXn˵Y蹒է)Xˉ:e5JAܐi0`ax#V 0C_FuxLR2#ۥCbuuZWDF["khPSK mRSZ+ߢmXØXnUU &iweWbGDQ?gxc>(>|_|±W|K^"P ygNO'lwACd((Yp ?wc;DzP`CTST+׏f٨=_5}oQV$[ r0g?/1_~F7MƸ^^f |0(xqȇ_Ы|ZL-\ &%@*+``:E8>.~8DϧYC>)O%d^S'2iٛLs /؈ 8ءO[an64;dr8h%ml[FW̼|f ZճM?[y?"nW8c܎5DxA4*[lrqwn5|wG'!?K˓$yV"dPA4N|19jj8g=R`!]PJ%kQOK^V,Uju5*?xr4qk׶8w'1BIVվveɦӭ&ֺgy ڬ<Nj$ %FUJvLW5/K}(JmVY,A4,A9sgS4b>mTkrUޥ&F9r迬Qendstream endobj 279 0 obj << /Filter /FlateDecode /Length 4016 >> stream xڽ\Y~_Ti*#.qJ77q~HͯOh(Y)(@7n ŷ^|". W,ɢ$/C}ۇ_LXH626̇5ތ1pzyÿ?lZ'"vL9 IO:SCGU8z :Ž&.~\VD2OHgo5`"J/t^]brFq-&%<|UcGdEx & s:gXt J1u*:_*G9>`/ 4*2*npWS,\Q :DM=oVP-=e!QDJ΅rR @g1\s7 p?ř'7|}FnNki(CIFD\ D*̥Ө6B[~B鸍 F&ˣXU+<2oFs?![4S6u(2u|7myze2Fzb/߷@Ç.4*T~A\| l6zMkE&-^*Nr&cr$D)%=n@iPػ&0^}෱5S[_ejcz"MO 1yrRV*?q0c`0SȤ6L\vc4R}shrvz85J }3lv 6(6VnKqq7mco)OYhQ o*3"Ά$.7wwz^._gKZ04ADo<1uiPi=t#Dg#OЭ2mR*R1[{L%*o<..Dy:hT lj#G,XlqKZ1a p3EѾfG@`_2*!#p)Gju>g/}p37=\+ b"S\]QU ,~CR%9e[7!P% "|;z1qLs_7..6]ڄ Eo,sID%7/gkכdH3PQ2&~`F3qߒb6}0'υ`(A#}:KfiGO$&7h/mc8\jכtեuҼOe:葔,GlWw^B/Ń G0vc}"AWE+犤]+}%zz ]Hm+y ]}k,mEWxކwt=Ð0l?xAfFIe]hEޑ!}R/=@{`zQk./CK 3~֥ qi]ttPgS/t ]q*Е<]3t}B׍>Z`DE6}Dq\::N˵a\T(L*t1ѥ }~»{]ZAf@< VEEn{.jӆ2<ދib6] vhÃ: ơz^ @샮b ^J0>O׃ xL$ɿr:뾘viC@ۥ m6+ɸSmT^MztXm6Ld~HҮגӛ@mbm~=˻d?N`! _f+> T6pVxW5ntɲ?nn[3n|k;phk鐲(y݌r܅gE<$~V{͂{~#߆wN? sA{tmNpe1SHbGCELr2:ط-'` [R%Ӧ#hd]p0|QΚ>9ݎ֏m2'endstream endobj 280 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3313 >> stream x\o8׹ڷmi\MZ%%Uk < +TBʩAOg[]mD685oV:s~zwvv'3;;ӞM:'ppS?rx>jꪪj[@Dlsd97 cff zk3s_D:a@sΝ;Dif @Ds hÁ iPc` Н>f0@""XX~:FGGQ999i&Ef###D؜|vBaLtjs( mD3 ,~Җ. YP9<2mrp/IUUEQ4M$ZnnnZED:믿nll!IRT$ɲ,!Q(0m^YY!j*2h4ǁV& *IRljɶˆ3xb2Ɉ\.b1+bF2䜣iaaǼf ۶jmcOz,6|ҕ+g/_#OuJ5MFjj&4ʶm($IL&p8 JiڳgL x<>77766f&Tz;77OD$iU}FԓU~##aIꛙoNX:&cvҼ1mn0Msuu5UX ضr" rLD1e<BA^e\m6QL^OΝ{O>yݍazi(TƹCD i;?b*;!(N_?i4MNqO-=ڈ0 Ƙ{u߲,0^EDe]766qR8-..qD$IuqYhnn… iqD8oD:M~T,EaKK˯v1oښ=55%m@ ةJ9p~7q!"˲DtP >8$AZ,tr46PB8ǶmfEmgcmۓa,--]v '=Νry<8w8BD@O8<@= IcYk IKKĿrن$5ͺsI11ܲ,UUs|\.711S6Ls5Ǒea-ضJc7ouXJ*-J?mDҥK-V=+v]:zo(x?tջwRtj*wV ïX45 \.G"RyݫmAY'&&`$2T766,"IcgjWF|U۶pz*=4!NY?~DLݰj`16ضY*D",訪jX__ "QUT*E{:vc RLӔeY௘f!vh4JDB" jÇ$#wG!/_ӿA>7|@˝jvGǃqi lz7B;Z{. 1Vh]$Kǃ>tpp c,NR/O?˗`vv͛tfgg9VULR&I|޽;==]Tͦ<_6^]o^YYd2h}۷Qu֭[;_:񘧏 B72twA9E((_xqhh1lۂ7nH&DdvժxUTMDӢ^;LJUU;aK^/Gti'[SG=rt:[o7ܝж-{v]QO%Iq'#prݥoF؃N;#vPH7kK;2Huj=Ap+=m Ռ1.wکң|9ΐvާwG=uӤiEQp%bDz(ۥhw/:v]QO0JB'Eaexރ8.Tڶe#!C"鞈lۦx,?-Dž:'}?즵SG=fN}r(#Iul6]ډiTQO}(7C:~ ,4dVaNᾪNNDfgg8|ϟ:33dЋXAھ[ Fchhv4w};NVFAy*&pea,v doawzz:N>HD"aigΜQE,*xBϑhȂAsN`/'_'-V666r9KQUxqp BՂa\qu5LDjUu-|ιqwO Vc1 gEPzŸ|9뺢(id13dYfPH<᜷Z-ã@ @D⡌@"uݶm9q:e$]pXQD1L2t?beL"bD0`oA )alvrr?dK7J\ko 4xyM.{AHtM+d$/&22 ruĥ*ҥO-HM [>]wȊ "WDD.IMA960r/\]We߲}av*zV7|8)N>}Hendstream endobj 281 0 obj << /Filter /FlateDecode /Length 4286 >> stream xڍ[Ks6Wr ]eq\fSq6$U--qde%!8~ %O"4_?,6dͿnݗvaNjxH:Xy6_<D?ߚ;4>ᯍ>@ ҡ8tM6-χݛgѾ@ \V6݁chv V[} ;|ǎvY$zx Lsx"@O2y9'>$ز46γ h7eGY)#c'y}}A+^:󾩋>$OHQnLÚSwʣ }Fi(OG„ [q!X?@1Krd5x#X`ZOUs|*5l;MyL UHwt:DhepEK̬Vԣh>> >&i^.:u~`ʣ/+Wqg:+%'+dp#Q ~6GT85 {ͽјXbIճVp4&D<@1#o(=qO7&`Z+Yb3 /r( iio9.Pu&$xj\VX-ձ+Z[0;Z&4Xظ΅&d֗b3`%E'uwx[ yQ|xE#cO3HTo=2N@>qGoO{Ma7=<qz k]OxF~0fF mM̼9A{`9t|eɁ<S3:sO3;1~DO+^Cp,ęGͣf*}v^P/L>iZǑ'ڇ͜"T&^Y#Y8Egg蕤hRWU*d>^EfX+2lʕjMZ}t]pD=2Gҕs rJO"Iv"j5:݃M+Wl0gӫ |G%|QRxп:9~ `1="V_ 8z4RPHL JLO$KyTN{,֠ͺ7+~5#S*h_5_jGt(a^- \ܘLBD6* *3&έ!,jOb!u O:l)Dr@#cH4>. ñ0Yl:78+7sU%*e&Y\V7{fI0 B,DZH}U+Ȫ4Ix{h[ 7~D 5;P8RaOeM貪.R*ǝ^зck8b7јgq01z$ DM]ƕSuWGG[8i3=T 3CVAv6F[F@,|G~UjΨ A zQv_#jtz 680"V Q:T&V .4\StiddP}xPW O 1Kg jApx1˄Ue_XtP7WiHe3V=ݭD:>_u SMPŏo>zh ιJ#sLMc{#[+ ~AWC9\zWPu7S8eYeCs J21jỤ)8LiR/NCXIY],m0c3)#N.&GDCdB>\) p˜_Hl,t`\P7rd.jAۗK*.HCTiاoLqt9S SF@D*‘L\M/^1q*.I+''% 'aNK>ث!̵5B4\ŰeWՒ>!n|/@< ʅ<5wFd͊pu7m5e|;M0\r$wXJ"җ[3xzKmY0FQf.|C.LVR4L03qV|Mй94}mμMwY~?G`h\e ȝk{ҴᲝ$/eMaj&V~QB, D;P%sAoe4v^ZQHgERB(uuelSmÙ Mt/IUɫw,+{-pHQU75x'{V5`to4F>>8G JdQ X{O 0^UZJCxX#j|8_u R2\UQ u jWF7 ϥ՘47ܬ#ȳ#3:x-A\/ "uL^MO=2$0nd]ڤ0oR m z0P9|t#^^q\;ewLu]_A/nv貋fc?cendstream endobj 282 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3583 >> stream x\]kG>Y'qmU 6 nH*@/tk ;zP#D!^5JJj"dؕHTZU[uT{TkۯHٝ3}v;ngx o5CqJJ)D2>rRʣ~sڮ}3ofJ \5 Qv[u0 :RtѩyN& eYRJ)2s1WWWq?B)xXЭ!"BpCFDt^zDЄ8ۃ B"q]'VUv]i,=.nx1 0jRRah4lvww0^_! =yq`jZ"ð``̈Vdŋ} ˲R}i޾};5=\ H躾iǏǏћ7o>vѣ0 }Dt:_~eii Ŷ.J) #1P#|>\`SAR...AD:""!Daz1eA\" JĬ!ag\Vt٥H`Biָ8\R0}?JA)_¶<Ў-=-W7bu8*?˂^Jx`0 9`AlcSB À`$JH$`6x"0t:. W+D,k8\.L&qSy8wooOVOsvu-[pR(QJyV8t")z ·OӜfS8fP(۶-Y& j]H:54MUrl0gØha6l j"pߙLu]h0-rfiYLn<Ad `!,G 8ۮ9Kg%4%/hfiaT,-J݋>+堳N(0&,BE׼׉ϐF,QB!m6kX~jNF6gHy1jZasiRJ3Lل\[[\$;w?S>'l6 v,HBmn ,,,`z\apQp jy׼/c 3P!r(hd_|>Њ*4hB-f"\ yȴ5 N1 \s\ -RMנ Vy0u-appa Y?6 f|?N_|ỹcٳg@\V+W^}W "@&hR_¹хUL6N3= bQGSR93M V\ tgp! ('o0:eY~/t:hyy'OA(4DPz쯿:huuG?|i~\ +ex'jǭe8-(RTQ#ZJH)߼y֊g*fp3,J]'"h`9G3"Rqt!~lWgcCJ4} oX3ĉQ`&+ Vu ?ť|>(QQ|Vs&_qu(-1p jÆNSR,& @/gM_kvJ3ay;6xF r9޽?H)777.\~ؼ: |Ȣ4MHYph4677բip]G2飦pykxR={Ԡy1Rcihj,xr\ Yyy+++i6+++?D )e&A(<4Q2~mJ1G(\d2TCJ9LP^B y*9IHx>9.y{gYYT(q&9<)(o=(„Q`Y- W]ӭۉ:yUEN^~8׿Bs8߹+J:85!N!si\a,94WǶFi!ہ4kJZZF uj|TVB W٘@seQT׿^v;ngx͟Ǥendstream endobj 283 0 obj << /Filter /FlateDecode /Length1 1704 /Length2 9709 /Length3 0 /Length 10789 >> stream xڍP.;0kBpw.!xpw $Xp 8Gv_^M|}ݧBEEjBY8XRJvv.VvvN -/3  +@dl6u~SB..  ;;]?PGA+ PB@N(4RP{Gs,@v G0P2u=gԡ@0(腭XMX 7@ rt~ 3avӮpv3u ` br<'+(ۃ 38X9ko"0ͦ@ X, [Vgwgf)wy)9d%Tt;;:mKdM|2s)|`G=  X!EسiB. BM(,Avvv>^rZjx[PL]AgG׿P88`3 d lYv?s{C!Q_6e72L*') uxrX8y>MGVS_ SG_mA0;;s/;;yYouM6z.c}jeIMCbi%d s3O m py܀6ωspS@Pc 0ut4@y.3xq<ϧ9B[|PGI6l2#>>?o`Sq4A63?7_|Ni/_Y_9?yH AN33ӿ:D cn(PPumPMͶv*׼; $U+.MKGÖz qjۭ({%zȐIY4wm`[`ir\1Trqnܾɹ.nTA}(d֌2/d9CHB;ԫ'r8&h/5Θr N"j"=B2W^{Ɋs^ŅQ"sY|ϼ"|BT"# h{#C )H(6$>R3}|qtĆy++1~H4)]$eqL|8C'4 7,,mmBĉVRb"^8}C7\;$fd 6z AIj3|sfled^hWzv?6bٴ !c9p=G)/Nrц.[SNnXg74 ~zgXђJ#ʮ`ċK:,1l\K馴ayqG~5f>CA޵R怇I7 +}ы Deū9 J|v?(S\7[+ɕDG &h~lmtZ(! f| BQ㐠I~ mM7v_/fD)zPܤ6p{ıwQ+t{0FB !VBPz}rKgcG.#ATh؞Jwf$0h.z|\N%qݷKK\ʾ/X۩ ˆ4RT|ɖO2>h>u_|hPc(>@C4l)7ҤTQ*]ʹܿ >~ptJ)fй ? ls"%1 W'=QT)j O,I#":8xa DoT7wTp¦^_E㝑c ~9*Bm' ~aǼ2ae}uA.B8SER$K>e[>sl+{ a^o!CŰC/MeR/3-Ǥ[&S, 9:mTSlů!vAPAVObk>+1,>ӘsYU6.^rpM D˩]޵HMDUOٜs&boN!?Zbgb"WVjck.($-p+ESMK<*BګXuXYXJň#k_;.7hvP7x NY'^KZOwYxqМ.yk=f,%LnпO.5V-`V%+Wl#d<= w.}1{Sۜ2 2ؔowL_^fͅz}) A䴉lex|cm~;hrH;ӱ~5rJ][(cIK%"}j"Tkݾg|൞^,€@O81L%l%͇e;5ά;\ؾcQJ5^Q<|wE׬HqIfO6$^~HX<?w-|BRj\Q(,%zJU|6`5 ;.ٷJhr޻u(_ADUMC,D_hDPZKIjei;+*S5bjk"F kwõI.A@qa 5lN[|{IJxgA2?luH 6603@>u; ~ [# gugd2ט+уc.<'|7uI:Ov=%>p> ivC+~pD?.4fۣa֧GKլ~*JSVjˣ|WT+t.P{H=ĺU8ˣ^NLH:=5!XV3?9hw+ 9lNI6y6ǻ=|. j1ZV~Оח!g);'mQZ.~l_PbN.91[QP# /V | W 7t .RVtzssz^KF>|rz6rIp_@Ha:]M q= H8m ?2 Yi}Q~"45;b'x[MDeMWҍnt!eat?<1!5h^[W}S@+䐂a`>.,~2% %c?.8_0X{}oB{B pYP-% xA.}2O)ޝpɘwD:L;%v+ܖ#W'|"'f{P-s9!6$p{:n}>a_:PC73PBQw(T4cݡVF9Q̉ WydWU!n U\}ELR%^ ;$,Ä#'ز1mv z* wNSaXRCS*H- T`_m|:L]eÄmrI 8 OzZ_Ͷ,5-CDAW!AiǠ'BfD4?BvݎN7j(R.tE$(`ePnVMzMD?䍷&v۾vb=ivLhcFݾ,>}oJ#;:%;z+ 2@'Cww畊 D;?$]/|Q9j~b En(IhCu!S냿NKIL5<4`z}[f?;Q3d er")NѧLuw>ȷ\n&6@,P6-<1;f, ""*ӏ&NOt<9<Ҟ,&iJ&7Y͵*V'8 fRWz_Ywɕıe?M]GEf9k4Vhv;>}i[зcXN(ˮgQD(/Vtä`H-yRZ7 oCÍM(v.O"_ڈ%p );}y"0Q4A0G&6eF3Ǚd馝| =f gyw:p&H7뉄M:wW [ j ⪋26@=2/4?ؐrGlA^Z-BLKvH~^a0~dRTǤi@|>?ul9<6:)dNNm[毙~nE Uu.B}j[J$ή2e5wWGPu9 da.vp"Gyh}ـ1K[ڨc!ݽiOҸ>i-Kr̺hU̲/r&  ge\:ST e>W@t#p(Ojgyf 8f ť[H{> W+Qѽ&P!x#cÏsS$o?[ݒL8nDY[,q$7Z>͆UwfZ&)ѰY‚8T&i.#XH?ٵkZ0!Rcl3:渷`_l8鋖7Դ%MW?a< bxlL1unS(%&_M'kW̆AZ:U+6گ 2ȂԶ %K6/MXH^ M69<:qlɚs̔cr8 w]-.DF2,]upl6LfTH-䔫ԑ)\c)y0ݬ@?<`- ͊LpDq  z\"9D;wxWZ2>f^ d/2o'o (pLNsc㓼Q8dB%ѽXBș]wM96ch1"nQaMx|?3*mԅ  /3I.c苲DK]|IF^V'{NnA3K6pL2V΢7K'&6~}kp tN-1bWCǽ#يĽ䠁Q{)KXY X7zyVޫr&D;W,b2K4t5=DӃ=툪+L]1 s4Ӣ?gt`mdQZt9#ARt3Sa]i/E.FE&-%),B˿ƹcqo֮؆l\6/e|iYV}2=1CR t A_un#^fUљh"zF׿ .5%U}\jSkUqcr+Rg[3Ͷ[~1П]͕&I jv,sMjq4 (XAWNYuWv \Gb}oTgֈ^& ~Cf_*Xm|+A/#tQ!Eg#2*| -?xesQYrFz){?@R&i#ViɁUSm^MUr5O !," iFJ)_m saLCI7f8I0o$Բx1T[wJ{5~:$xWO_6Os=֍ރC\?i߸$ h kۀG>\sHɈp|E!L9l UJYkbMh-9r2e_z"`qf%>x[qES&u 1@A֘Q-1_7"ðk UMm`bF2MPҍݜS—N~CYSd\ŀhRɺ-OrkI( ;U}*IFo_s ǂ/y𚯸XjuBM0#TMb΄ɧdۉ{i w-}^;Tes(Uv5yI1 4IKDBԉ2u{-RXA|uv/x<ŞyW밭aUUrU\ЩejW.e*1D:F=yu#e(?2,xKkEW|KaĔTxpsq\6'Ab0Oʝ_86|?Jl葴BItMX lP@0Qa X5/|0r[>&K-11fvN5{w\ӼR[sm?&EO1 #_X!jj~u6.IM1YPFj??+f-~&?Y;2,}`  헥]GL8D{NrzQoԝ,-'Ƚ8vZkJިW$jXRX2rOBHz U -tktd^P)?rBٹovE$BH҂NG $]1gDZ+>kb}C='c'8eq7C^'p33S YبU߈5:`oHFt?(|3nYK}^X($+Ik!Cp(3D pǑ<{E8 "eWǬF(՞VvI,D%j˘}0KdxF\1/^ceguc=l A `FXYJ %r2܏LvD;&i.Wޓm"n$S?-3cǷ:pHnS06|)/N$)+L;2cB;a:LJj{U' V9+SNlkl!epA3 kqqo4-3Yd~:1'jn8fQ ׬gX`NHE^cOptN+rcOpl \6 eR13W"$Aru2BES468AEDK/ĻyGzEL$ȴ{`9{rbun8Q󴱞Vӯ:bc8'g;{0 7s.s^v1(mQ`s 3{"_]PXE LDrZj˭$dY (un`9gy$ v W&K6R?Р(~b!Y%ꖫġNЛpg/+ 2̴`g"fx^spNPNУ`endstream endobj 284 0 obj << /Filter /FlateDecode /Length1 2803 /Length2 24028 /Length3 0 /Length 25586 >> stream xڌP\ qw AC X݂|^սE.kP*2ٛ%\YXb*,v&6JJ5+?bJ bN@cLd'ooqXXXXl,,3wY2v@gJ1{O'+ KP}ИXyyrL.@[PFSc?!h,]\ݙm,iV.3 h0@wgL5K+.N@H`ce syڙUi9oc o`ne(J1x0~8ۃ݌lM@Un Q=gS'+g&g+_-2 ;;31{[[3¯ĭ{2vvs+;3_M:0Y91~,.Nn^v0d^ԁl8}T!̬L]&@ +;Ab|'+. {_?~_eVV֔uoF#' ɸA|JVGDi;s{=>?'C o{cd1b|(oIK6DeWYۃj>eyJC1Z9KXy͔\L- oceTw0t3}z8v |ggjo8NNƞՃ'tf@ `fw@~m,K70Ff߈,Y+Y7b0KFf߈,j@FZ#P- ]7eW@~#Pv]7e@ٵ~#Pv/(o3m@ HjfgdlzG+Uқ8ALm@lwh;?+H3+m*;.heeښ;[!U 2_q]A;4h'! ZCN_wes2wu#:-=,vXdgnM4?[m@j?rԌo5(nbp#/-A@L0Kfe{8ظ_t__ʱڻLlS ;oa)?#1/AVB~W rrZ朿lnfUDmCWVPUӂ^N.N?X@ .  wqH^@SoZ_`i5 ",ڛX׆!pg};EF:+hV`;Eg毰ߒ[~<&L ̏}>%'dTyv| ]2ѕE)޽Gңli8lvGyKl1V=F/x2${  #ƹƧWzXBou 56< <7D7Tޢ)2s%}$Rј2Tk܆Ys?B 0jJ [ 1]jEWZo5:ͭS y'^ږGM?: 1ޅ~l,"pg{gėI ]2ѡ BcXtm*t!ϺE|3"η\}}}C?5K{gu8+KDCmtÛ6ƣj}(zrg(.\=YП/ yVۦxOGIn6بq/JvO=79EcbۦR i@E:q&& t.cq@$\FΎSҝhKu} ᛷԉ4ϭO _g1(irn3VETdLJ=3ao>W.P,A=e%%1tg۴Q*c#Uc(9,)X˶сHCm^ N& ., ,[e>G fPD_^sv*U}0 s[~+<Ơ%NX(9L$ݓ<}U^~n\WyEҶX? {.L&(+qg3-]#0ΆƢ3{d2vil&e12+a?@9念FaSp! IY\WB'legYB/<82'Ĩ`7hyIn^ i9$y ;.Opx KY#ϊq""o’W'mwR/i.Su^3&]Mrx{D g>#x2]z4oVe#91rγ'ӛ\J?*X׮ ms;}vޔD0X|W5Ap9En XɦshǕʕtkJk%}KZKs&~6!C~}"LMje'r6QXB|o (o$]XcK0] {h/SI6401 WQEf/]?O+ўZ>nb`A:w K#3 8ȷ\oVN(Wjٜ@(F6z;{NmUI|촨\x<b0YOc]ٲE쾁̰@(s*Z7Yj8zc]̧^mGok",p_ EޑT^`c/:{POF%xZnX7"^Ƀ#@*4V+$,6&5T.=kh)=o LU33iTu2n&HsoS  >UģgU=^u׭fI\#:9lZNj%(X̸Jz֟C{H}WOĩ4 ʶg)`֊P]?W0-h^a;^-v!+>m(@3!ۥD A.Y`%?) _=4t.T'4!&|WvH/k~/dUţF2hv>( ~G"9? {I"?uyGm@91$~*c\dav*}ak1pBm\&E~q( T=7,730ʇ{i~8J*r]y5V{o^u :`GCipii흒Ox瀞f]'Pa_M}CDU,f Suz4+iKΌBCNjD s$M#g%"fw7KYm9c;ay, 2u .VW獽OZJ&[r @k>-i(%m &*E" ݚx t ̖"Ҩ)c2!l⻘1%-8N 2`6e_KI(ٍ:ߖ zDuKex wN>ͬX]eAAC+d&}kOTiėsuJß₾0eD%gF͒0ZDJEִѭ\+V/&Ύ'1onc͈aU !WI".HGeh7}f9ƫ;] W6/GMXbb0A1Xw#?J&SLôǒ"K|S}{v,}s^,6 ~p#{a|c}\9?0tGЌ&ۇtwB yZ]bZ}Y{ cbGRm#Suq#ZiāQnj'䙬 k eQJA2on?Z "g6JLCZWCrc[&,-F>~ȝHz\i*xk}bQ"19wa9(JS?C+LL<|.e![I7فx3˳|oNQZ׉Yc?1 0nvw,rt,jWCY/!QM. їF|onXx{CVIJ.ctO(l_LCRn~BsSn[p˘^Ԋ Ra$; FF}yaAkZMKm׹W ̌OoZbNQ}j"o! |ȦZeoGrQ$ !;|Uz=AR\ʽi&Mq$W$|e&'KM.2 ̂CyYDN]x_aZi7>ud?@rڷK1(PPcZF((wJ_JM\tK)"ªjuTжXkq7K7Z/1שABO0ڹ>3 F(4CFU{uMߞN!4̻hopJfztCDSk%H ϢqI#ꑤ- > j)⥓fř#dž;cW_tݖ2^zV2DCjГza֣;mչfliu3keKX~¬Vg{dfDYHI-JpݲΥOhoAWŲB.sUDx ufIO2Yzu8ĕ8NjoP}`~[Ne9DaWuLT ˸u1Ȓ_~ CBSrWUN->B%!S[eQUNް:زٞ:}֕mR^8%Z: @;L>-vTLVSeW@aS*sD/5K%sT,>H,#܊fRHH$upN#n3q)%NjmAZAw s(0/(w7v!- 6/{9OY=Z:%{yRտzduYhUVsP.TP-SUdַQ/L7/b_'X,O<< Jߤىۄ@>Bz?*%Jn2ł@'?x J!uRzW|\Q]nsa8`aRG '+WHrh ͲYX,@} B)[ԩnh-aόF61J<߉`Db tRbViy& uZ^)4icZPdo<ۅe8gR-{Md}B}-^u8wGǏ%Icj /ô!*l>aMM7ŚKF&ĪC 8-q ^F飭.PYY03X}=mVx 'ȵ:Ǭ+j9_9B1Z7b5n%l-lU9( lMy$ևe?%cXw#% V;D=\w#m])Y0.Fi`glrzcVE{SCP\_s9 ;܀N̆Osjk.̑j߸KkɝYe+R ,PzDw)Rꗝ:1ﮟ|OKIЮ7B^kDX(SseQru#$"SZ4W v[ %yMirw*ot4EYqZdIC ujhs~:Lߗ/R@I\d5?̟$d)& 2+@^3a,)xG24$i, eH,D$")U{""$rJnT?rC:i%Waic_x_DJD4uͨJшc5& t?@c@g{Q|3/ԟXT Е0}iÔƼl*Z" TP?gZ1#1WXxea}繤'{BSv@%ex ivgg Zg{7Yt))>wP: //: +r!xcr sl0gƛ'Yo=aNa36 ċ\u5Ge5oC '"3כ釢 Qtg4UB Q0(rL|kcvB:ո5E8 ֒ևCd=I[ C}. Pсo.Jgkiz_5Y%c9zԊoȡ_yߺ͜6~/#6"ٝvCݢHyzٌ]Y^/Ty\c|r(tm-t>{V30JJ%(Q[OG2?L@k$9KEo4V.{\WI)^&25Q7w0 NQYIL2yi_:鋺 <>_IШ0g^U ivbLBlslމO=xz)&QMz|,g~4 BlcQ{;lni90̅I@>u-,H!k׌ ̠ljq=;X.NlRqpMd-ɘ7{ow{qP"urj67nɩF創n^}"e0ɐJ=myS&r^-0߀aDMCv'%I- .!w~'(z7힨Ѭʬh7Y F%۰ tlo[h4[E'ZLU:_a[ꊹ'!i{e$rd^uPϢz&&Л?;(Կڞ nߗ7Bt&w5:̳ƬX#][֜o7Ht/YdW;”X'55OJL.-H@vx bX ϓ֡Jbsi \۬Sq 6 M CtKѰ8_I#J:R_emyZV< ^"px5#eI(Ja КC JڹB+#6M7i wmOӛt6})>L|㣼5vܫHSz({*3E!th&S$@PxĂj|715N+5a :FHnJĂ<6-*|mp+*6cJԮV!V_Ͻ2%Z,;b%r\֋t Q匥 3~|dI:Z [#4]D+@}'%#2_+Q4QKJ'бVC-j$b^!B6tJPvY?_;ۿq7( Er38,1s]}v;zo66Yd1 9Mq.JU*6p_d}ݴ;rvu s\<0K".V\y}swV S`٠R)3aGsI}}iD$`vL-r[;J+m=ʽrE|DM+5|D4g__i`El*Ȇ33-&/]9ImϡI<^t}}0R${+l|| G(iJW] Z#"ΔhR^Gd:-S\h9hp&3Q1eI38z\`K$[)"͊OM1KJ6J{~(:R4;h#NC^ftfpVwR cc*Z2%K0#ZЦ G 1e(?l}gv€! M]Kd$4HFNX&@%?]h%\tpY)R$VW&FhF#Ix°|jxzG X !xrXB'W-UP…sQqkt{IL v5HWGtz|?WwT; 9U}a~Z-8c$od41PZd]2nu2u w08rY{Kkz3KT:"J.7vrT|mIpk>?dkp?M+eԅ\v;q37QY$qǛ[Ŗig<"r?qLll;E5qf"}/ BcZd;@vHLmqk@iYQxMkԄW 3֍u`'6ɡ/EeU!u_tv]Tv{!p&t-s1\6$ihK7^h` g¹Q2)_?8e+ED={Zad EO>h*9o&Ԡ8::W"4 2ӡ:k42>G5cAN{x;!z"$$iѨ\ٲA[#RGu~eɤwaMo=ILBBdĊsyk9)]^a;f(uLƁ_;5xCDݣ5pr~ 9{#uq "M|YJ8bjMm0h%1Lүc1iF i=k`ؙNVt[[Iqx蝇#&m"6qvgCޟ}X{#ިԻj3vS u#3S#4Ώx"? rd}NDeH+B|xXu!|WH HjG ib,uJ/Cx8Wk%^Nrg0{BE"ӍO}_s'*^"D9 Z9hCDmHf0,b2E31gʱ 8;vwG$R'8XjNqms^_卹Z ٛLT}SNj8-6?%yjsĒϜ{:!_;h䏺xU'm?2rZ- T[ ެ 9r罱x $*"V[j ڦ`0ϩ] iON g~^+Z18BAvFu#@vO}ȷ6g{e!D[mok{ rg`L}v^pQdɠ DD3".(].VBic#CCs,P"$Mǘ:z1|lgpL,mF${`eNl |jOBmh\b+r<ʚWnkTj 7clЧX "Hu,]ґsCă~hَLDg˰u#{VE(́@EFvsDAx+'5Лhnu:fBNx}%;W Q>xӨ//mQm}.-z+r~EG <fK#;_)wF4t{.xNI =8EJ#?wg.n5(k"Rc Ԍ8Eʙx!W.uBK (B3]#JED+lhl_֌b9GY86f U9+ŁiQ?b 5`tkitV.7Y)!u>T*\hJVږC*2T0;AcdM4(0wl-OrȫO:^;d0w|Ra>^~`#-b1 e[Hsx"|r*e@ʥnԚo~STVT%Ț9&?6[3!wM%*ԖT}wڪXWEtunI/&N ܌0㧑PÒW.7ִO ,\¢|y_FpyMBֈe+X%Y($!)nڛ0tTiK敢 v8DM֔Z~s:@NE[@vKs 6r޸OKxTau~($J1 fW#(`;i`Y)3yfϵ;ed ƩvvZZ 2g+28Ĥјr'l2N ,^ZkLBiaDZ= yw_7xI)re)0" [}}]3v23y򆷖4fs&ex 5#,jQM ߍIqRQa -Ū88R)G7<؁K.:3K}mL0Up5Q'iXL&} 73tFÉ) SGh{b:קYh[b $G,\s }wÙ\K ~6&e.g!/==ǬAxov!~\_r 82&-jyۣ ~l%m4M`@4g$+CzwmNx\|F!Vh3)Ig{r;ڍhHr` Ҳ8CnX_7~˻x&Up5$ٌrKA-\]j׻O"(ɜ;Z;܂ 3Rd}-FAO3spUX/׬|5vg`&Z<o\ ZoL81ƙ4ʞ ǘLhS,6{xK\;{hq4.q^QD=}FWj{>+B"ݩYI6[}lU,l:F0Mz9bU=GhrCYҜ@Ao0v3I9Jv* (p&vK>*}W[ԺTSy[NEE/ZtGNA-L"?I g֝JL`:ɩv4+TT+n6qa0|¼Ut 0hKMo&ٙo}*_W`2 ʹ,n\P_3[+G#J.2ҹWF$䞎d *:(ns5Q^ $7IAi^pKT9Qle*ӰG 2:/ʼn^Ku)z7f>< <-*5h)fWZ.hŧS.k>9aЗ2 s&29/s|.0%2ۧW},T(˻1zYk2̕z7Q3hJg#Ms8ȑLEք0F:9\ U*z.s^O&ĮJѥ* # o:3;cNUWsdsLiGj/yV56]0f!_J&$e RaGGws4T_ `BeB|:#zxҿdGcA(=fH='Ǯy_cE0yr}1egs_+ye-qcdMЅYO.r 91 j+ӄ_#yf|*O'8g+^+hL'u<\:PF|7qpبtqhx(d WoêS?G/)va)'՝k퉹vW`Go,mv%7s$p='Lqx(_wH*Mn6Pz6E"*OjDcmgc4"ZLP6zS^M&;ാR]}}ҹ—?KF׸,fB\!Z_ ky,ccP'{fXJ\E67I`ڭP ίbu2~hi_+Ouϟ;*`}g1ܔj.evGI>d:xpعbK/I۬~:j rhOquھ8=T :XDgW.c8bO⥞xBrbCɗޤJYLҼHg<>ӥyNu}D.(ì"]",JicB:>q{X{}&Ρ]#zXPt`Skj,>FJ" 4_mX>MS\VfﯠQ[Δ.ODVWmqBEs_Nm5|K/F~0{xp6L?]Ʃ.;NF2~n="`떒jmlU\s_6/k1%Ah, K,,}%a$x s+)$YW 2.YXl1WuB<ͧ/s@<}Ey_$SƆe7-*Z]~owBH 򼸂Ozr̟ҪY.}?טf\_q Rkh,)Z0ELW![:s d|f@+@ʠdRqh[_3XJae krrn &IV-b0Y%L# IQ>[В27ơ9Y<QogD1y:n3X'ZE#`tA.i Yܸ w8=IUQل;{ǞAjT+?⦀ 4a U}ʪ$ѮÑ* mf֯Hعc&UkfW(WV< OnKaUH^ˊBedtvNw? ~+I2}X2H$8.Ycd#SY)b鱴%z}PEE3*>\3鳧Rǭ@8-5Q.9~V̂CIH '"iݸ͏8)!_(߃Щ&*nh58`̱j6XN2B\Y&a̢/‚+[b;ȅmXt)^u hQjՅ2rK'.ӰC`LRXGp5%6tMsɒZ|uo4K 4ܬ:-Gҽp|0O9j~wv$8h xމyl.0:vv s@1$dvNOѪ26wkT~![5t-1@pBU\0OG9[eڭփX E2ڌbv+UH ze"61%o.H3U1@9mP>FOGCZ*ԽXh2i8Cjkqq+WP/B9`錁QEwTSq%2?7/=f>Vb1=/`Y?v*!mi4 6¾9ekf'*Ҍ!Z ;fgYL;_=^M <mgZtUJ>ܓG;kx%@^"QJЬP$. B{蕻C~=xG)bgd<֗Esi)DHGcUQފ;;eiClC L. @6HAJ[zW9n^I*C`_(RNHh_4ʪ ݙ~ͣ&  , ̳VbʼnG;@hT98(-]֞e WL,C 8=-i0e=zk(_@9`S'cw4AN!ڱLfn27E}4ȧOnLb7w^jZ4b}~ZZ`rD۫FWxy1}Us֤r+Gi&Sye'I ) {;Q4sI/ DSHǻ?$tq0 "&4"mr3K` ݧ<Hc@I ?#"\I{" oC⑇}&hK[ܫy1K}%ОMn0\Vt8 b?@\B%@*n{ⲮNӂCr>qxUY2C\"9:64 |F礴 9O?%@{34A6JBMX/>Y oG}R$H"$>2ΉSM<]dfy=f\W.S"`ﱌW**j3&5i`2ԢڕJap<|] 9aqPۦA\N2J7ќW~rJs(Y8qOB +#| R+ &㌼PSZ ^l(.^F8U~E1K qqu>/dgKkDž3F::;#2RA,{?L"$xcQ%y!Fg+A0 ddlLyBmEQ84~MI4r-uRDd`6_#۹gr]~?B|]x~c:{dr s"oZ|1㜒K6 Toc|/%a/xT PHU93v(je^2"\BVoFRؙdzO4hzľ9;lW!?ې5cXx;ڌ{F`Xmnk `ue (čC̚jy;Jiz)nɢhO+#>Ȓߝl1)3b<0P#;?W- KwEǨqVfߗ ^fmlC1O@'7gZ03oJe$vqEh*ȩt&!0/[cIXolxwoZR6J[AUgBru7>Mm=Ys6{{Ft)R*3ґL/LyCxw=0~ڂ쫤?7?mxŗ(a$hkYI^_\VfWr#FbLʑNX,w*wc$KĕVbN$iҨ[7-7iDE . >68Np, rCV6yR>j-8+mS%UV6̵OA o%$`eja& ۥD'1HٿDVҼuJa7˰&iwEL5AO鋹w zPʾh7hQI峵O_كo~nMQ'*EKd2CHοBgLbBc6sKI6rzc}-P-vDɰ]z_PLn2 ?ΗBtS8pie8Y MÃxpp/'uQr[47~w"ו%B60ZOkҊPU>"Agu͑5.ǯwN;5!y7 0{q%5N}¤?k}o̝^m#tnmٴ' =2i#t‘e,pfOZ|IG{2VzkZ~$|AN  #Rٽ0।(>k+[/Y}b9-Ȳ&9tE›Zmkt| iYdeeyo9:gO:Q)h.U7M_+~R޹Wrh0ʳH"&MTS{oRjDLI/-&޸[0ӧ0k"H,orzgEϚ5Hh>s']VL;xSPA7`eB8gH^=;C'扇3=܀Q{ȱ#߀$:4,:[@wRMlLԥ O(#=Gx[쀂 ,Gh# ; HFuΆVwJy@lD|oC"o!7T4ս3}xzop!|^!bÖm8rm+R$#fn+zϙX/~z\8d*S/a %B)Yyt~GCwu-{*dƏ®FO/Q@wJ;Z 2=̵]ϴ+,]S[I@)b,:m=@(R#EZN*]]Ve \!J.'_rȏzM='쪜:vݛPWLt9N^Ԋ">@#e=8U:u nQ!*F1h96߉G6DT?'dM/)qo,yLI9 |Y6RL)crgaVmp^Y܅|Y(jxnG4V IFɠa4Z1tbRik>]04C4P?\1숌@(qD )4 )4x:3u״8at!׎s7XqђXX')2^SMoR]Dt') ~EcAnQ&˺&: D[8:%9,g0#_5:{bׯу klOuu2$&Z@Q-W|Js\`$۾wK: #GFo cB3Au~VC%)*Xq~WJb|4=:rOuӁ7j%\?M\|yF|LiZ@!׏)]mNIbU!eHyIC&r-[_*ܩz{4`^v$WMvb!DGHc+R:{)^c˛Wi:aXQ/n0V7'c(hXLeնo> stream xڍPm.\Xqm Sܭ $@ )Z(Pxqw)vdw9g2׭-3yԵX%A03 gdHh)sr88880!p[t`G' * iG0$Ÿ U`P-'/!Q t*lEA' wwXZ`g iv lh ЂCp b `b,W v;A?JƆAж8ЂY]`b:=8CA`GSv2@ X/pq;@tPw`np h{!@'?IjO]#F?~2z0 j?G̮,-)wVJI|\V.^''7O:QjUSUߛ7mA`ߐQ'sSGغm'n_S=_V vU8" |sVA6'9[JS [sqX998Gug$aq8ݜL}+ q8" T@ 1I2D\r|YLb0MrZ\! d5EڞXN;`n]61#Ӡ8pșQȠe\Щ}5%V h+y:;MIj:%wF5H^}$:z~cՇdž%UAC٧ɑ?sΤ)+0ܯJ.M'M^?ن=T}ZǍHk.}a(mQ=xrǽҨu9/ Yk8Mkf6ﮈRɘw58['\wbG`d4kڊj= GH lYeOu掓Wra|4am{3]ǻ2t^*ֵDyKs/~D~j=>eޙGj};DCwxE\^*vY/<ܦfN_LR ]FF=)v8`N)i`4Kqao2^y﭅㧦#9 + NK4(cV1}xc@:&7ShRo?m`ݭ%OeFket0\Dm Ͷ>Ir qGڗ@wS1V% AdvzzogSsF>YO{VQXQQ2wهET#؊Hz/N0tGPyFc+7'HcBG#EP˥㬇s#>~'gsnVNo~u7}*r2~):]8:flւ>9Gh_)N )F7_YwIIɟs/嚚VUX-"pkJ$)QYb"sUu$w} `dNAT Cc&Ĩñ2 U2r2Ue@K@rF^(ɔ]iƇN4a/ [2Qv FqC]2Edi_OSm7l2~N! oFjpۧĄ-0 -3ts2Յ+ҔƧk7*z9ۿN歺ncaK4HhtC]6`7 vS9KR-hž)gU)& WK$c[<ǿY +{8!1^+uEBLgwM`a#$"r6Zc4NƑ.KFq{9;ar\ێ醬xcO Zϴ2SZNSk57P A@: /`% V~ Y? G|ld]'ϖDAY:W4.-2ćj|֍3T2 Cק*$GW_}~鏢ẹ|Sؘquw<NJz~!-GˆH/ l ʵUE cvb83)<ݰEPaݔVe~9-&;/?U]&+"kT^Qu=ߍ)p hNsv)=dvp ,o.J10oΆRtR"rp' pl|v`8{V&C~hcd[3Da?1*\VEYO(MD'9$fzǫ_5;A\xt2Yџ{v'y"Io g+u 5q6jҼWL8%~>5<_4XdP`F >63+RJۅ_b kD͆!cG/wf$ h<'ao'moP^?`nTsv f&>/eᢉ%AIS?rv|˖W N=npΛc=o"6lqv~¿nzr&q`競TYИoصՃJl֏ٿ{h#-ZKzUEnT9rfWO/pq  O1v#_}N6Oܠ*{z僜$r^SqzbIb>t SH3FFڻٓE_rj*+^cmzθ 7 > mzYQ0ҝݷFuU6|L: .Nouz1+ ~Meߵ'c-%I5\#bB36 uD ȯs3j%G6u-!DC&`s󇃆6 ;,8^ 0BWL/dLR9>I _!{a#o$DyDqPmVu 9z1ԥFf#0*q[NKuCl!wwB9AҭS} ŅSGOqsI7f~Waϴ9.m΋z(H-;t鏃 G)[<6MT羃g:\ǥa>@<8M*IOVYynEi'n(kJv|k bcUB5ܾ,"?8r;L8jia G_6J{SeW\IlJNS^෭.ut֊_Auy*l a{~;k#)Ш?ڦT9}J7PnhxKB*:.r4 tI yn$DAbvhepڞ7 uψzbU8K3:LcnsXOAX2 T4/=mEsI{*Pn5\ɞZ{HM|\rDW9fBE@/ɋKvC/U!$Ư͗˞e2r㤾 yQn\cȆi 793M"Gz2=yZɏ`/{VZM=qA f4ke;Ҳ(gQLwc]R瀂邝rPԀc[.5ggɮ*@,M\o'O47ȕn9ɝHA }bv~$oh̽&oo%Dv4z&Pά[l*P?|8^+|pӈo]:IlwhՈm𖲨ŨU A/hvpfú ꓽ-$hy9םc'xO) %4 Eu$;YXoε;}Ehi)ޠV"nqF ù<{~_"Wy3$RJ_tm%S3od(!v[!6-Ь -OFchGR* s~1\<*uF!n<}=Ѻ&Ɯ L\ ~ Qѳq}H6 w!Q$Vc&5cy Nkc̐LvuzjFK13(0h5|jPJY_1uHHx~с2F BT7kb#&;YԭbĆl xCy=I3cyTP[˘=WJNR5;;K[u_[_/'QlQo/B Sj ~[9wsWOskBPg/Wn|U_ b-ظvI^^iә -Jz&_J/7OP-FDipF ^Vfߵ]ҥ͕ug`H <$m2uAYؼq.j(gxB ~ e2-7ǹqQc9+4j U&e( X ^2|QG seF^i;Taf WtsNn "o#8bnDR*{3#ԬKPH3L|NoNbڃgA]M]u7[I˅oXC-U$Ӯi`ܛqE3H~nLOC{Yq{'q[(x+T3^;تl+ 5]; ZgϝN&'* 32PXkMFd. $}e؞H`"bVX>j@6h!~Dsط}q%dMõۍ -|Jo!B rM^tBQ7F;ìiT^86;Jtji!IM*g$wWƃrρt[EF1<y1i+%2= 3l?t?|pV_G4УP5hj=>h}46,H)wZne{f}B媂q inavOWnÍ4ivk}LW?ut.~XIT\ 9„]S;I -);\2IO"\"7!\KK={8&k'*&|8L8S̕ -9[)~ԣVȬL1l4iL[g\3%ZEQT`CV<ѷ8}fwmlNi"EnYȳ2/N"-d!vk|*D }r z,Y\$SiMH\(w|&o.PTo}K@S͜ðpy8Y痱s?xGlÂjv^t;w }_< ~nh'ӍL2c&"]a瞅gfKo{c\~?޸ hYk+n%D%fkūWo8%PY[A$n \UUo4UX{KHG/ |=_ ļ)8RvWlrn3TV;BixH}avu|Ž[@kZչSh29ig3ޭ}4tŀ{HЖ &_S'{gAT!9AbK7]/5 03Y k#o T~}4ϸ/%uilٶll>\\BN{a DLFe BgJ$UPJܱa#Ȕ~I$"/(?4FEh09N˼^na~C&ڎy&J-<`,d%L^@m5qtdr)Ә{uĻ< -{Eu93Wv~ M&s# }/QS 7 _i?tYyDLϪ44؅ߤ ]zEwySƳul2DN6j_5C:" `ɄgHb%\n⏥Q0& Ԟk)>F/yp(N\eϊDx>LjaCMJȭo򼋼ȃ Nf a׶W=(R3#gjJdsjYɏG|KsƔ:Y+ X; {Ocmxq᧯51]֢QK-4TS=K^)i195!l±X 20m9~idjً*sR:t!Y(eRb(ȋ=je5/˧ͷ;.حyш!!$qɘ/:S|-Ţm(mW?1n[@(;RW{/,/;; mщ{U8;4!9ogiBc'{䒁;<[]dl3>i36əD;f.y /~G&Ӛ-oBkU^[*CEJepa1T#@oƹtMA^spR*,oY~LNG!uՔЖΚCMӯiMzS^Y:P5G! ?\G"MUO8ĩ.\)Jąԋ|'Ish[@|aǠYoR e[^]j,C ݵ& im1P5u:oIJE3k.d55A gyY&(,Ƞ"Va((5>'`A=R y0T!Ia< lG:0Fendstream endobj 286 0 obj << /Filter /FlateDecode /Length1 1747 /Length2 8595 /Length3 0 /Length 9693 >> stream xڍP6t.ݰt ] ,%ҝJ4H#! !govfιs=*b34H(s@ ȉFKځj]1$APM #*Brv.  &Bn` "@rA8z:<?|,كES51 l : ڻADY`5@ rvY~I(ڃƆF аPXBMAlrpqu9` eGßd? ,`'_;qbh vX@ei6``hj7u3ۙ)@ZL` S>sg#ԅlK#02K9XH@AP_' vWsm #K/`'W_ @~ y[J qXd| uvz_Cf +03O 3ϓ!l, v][Y[\N/8!oV^+' 7?[VS_/`[_0A gy/}#iW;? ?~S{_ 8Ba-RA"j^Y)lE)$EPCͭ ov@\n+?>ҙnXp`;ߔR_ 0uv6D&R  `gs@aG0yK3گ~D|v7]7+v߈q#X߈3`>Hn-;_ ah ~3`6 ,o[9`wsuV AX{a T 29sWggصv7<@hs`֫*12wն8p(\okN&C)*3>dLWK29P8ucּN+j/%bQ*9>>}]_׏6z{{@e24F,m>Jf:k묟!9vo&\׏M\\M/][G%G= A|\ 8υDiT7\ >jjVB's= MѨiFflĒؚgB3m%f>S}KHz@˅Lt^8|6x ?PI% %F; (hS+fHXjP"$ixsA x 0徴DywZśJ^Hv;niT{Qyɼ+4(FfM4gaU^+W^OBg Nt,fOZ*+M[{/o;wJjh/Vt-x>O湕G >cͤ.ՏU3=ЬelXE4[rlޝZ٠U/{trh Gu<Kd5a qc6۳Lb@9 pdLVj~jsN9&7Po<ø5bȜꔷI U%:ehgfL:D,qXk騶z.|:+sܶk-A>JuB~@\Q=\KЇpmۃL-m]&}u<%scY9zIfXȇ0~7il%"w K$##R~S{$:!^%ً#?ókБS"_5x*z#X='͍/(dJqF |eWsK%(2}_2.(ݚ7ß0hpIB.vezA</sħmn d@ҟKedIyz$殷q]pn!BS)yV C#uy}.=@(Y9?S~oG}Ys]^9{񸨫ϗշgR;\J[0xv%t#&<΅LORfݤXMo`L4fR#?%SkGc/+6RqJiEk \5:+܃fM,I\kʜ+S&8Ř3h;ꌛ(nz\3WItiAtBIc9m;un%jyϼ,>yv󄉅W*NtRiX06 1G$=FpӢbNO@!btŻ.Ū Q )DΒpRlhT:Ce8qFl~ i8/d"njymOs%u'XV29,y" fD=iue?|H/]x/9lRd)ݶ. h}Wʴ `)fi9 eI)s?62,Y eͨTIe8d $4: 'Ea__rޓ|_[ĶbWU@ ~EyH'jR\IMaJN׳R*xB7wۇ*4 9]'` (ȍRN_Ufp}fN4??ĥ7c\ 稫[CY-0ՕutD3tq9FTu e 1F_鈏 V}x'gPɬ Y)JaCeM:tBϩ'HCԱ_,tW^Yt_,[iUgm8r ieOU6?}CE=f&qD_E:Bcd^@|2eӋ qWH*Q&43p_wC3 ṵH]XE1{sU`s"SK%i` .^ &.ANJg=Pi;xY&՗56m_CFO{P nctݞ0axe%F~G.SwY{\VG:>avk0zRJy3헪k[K (KUs_gqO2)x ǂpTDjӗ~9ml'y;㱆.i)H!LCв-w ftGtOhqDkR9/ ^҈/ߞd꼰Dס bШvx1#b:yz}Cz dF-tr8Qd׬owKm?\wp. =RHmoH-JC"ZB¤9y} Dn|B"qn_8e"(\tpzN7iFJF/a$4g-#Ŕh_qBYkrRRMS01g2nkkҨ<ȩ^F &޷dc}V8Oe ( 6_&R ̭E>m*іP՗E=?}Ūv~eyôd>YDҹ#~ ^.LXp3.˺NW~Go2 rBhYTy}4m2pU?G).iUQw ާG-gaC,jb χ*M"//IgIEV]al7řFJjn=C<>{J|vXBʅx[ 2khLGv)d1NAijW.c{7ӣpDߧ^tS4Ӗg`Ms m;A5ґp| gg|ՇȏJF@)Z5Qmp`r P^v cVJ\^VXqfKSo漀/Vm!1 R⫁ hrDYrۼF5Bl"k@dHkTqQc2M}WHLŖvG>oW`FMES 3@K6.UL6j,Қ HsUI+uUp r-WլS~W G{R\1v(ٺbBH_8!X()ďIYϖFíeCdwLrVybhIġL5g_U*4*F9\K˗,qк{`F%Иo >m T-.JXpqw #Dg&BmwyoX]D캹gkA* )yΌGx4"k‡a6[`e >P Gm{'JunBb&sٯ0l9{;~Q8Onʕx0ɶ_Y9-&mR3|B3.ZݓYy*BbF ,|aޮJ9FVA&+͏ WQ_']w{z*q;gsb Fq947t f$8[qQUuOŶ 1Wuo.TT,S)TK#:M=Eg3g(.WhʰٗL\+=hھqPX%\kme|4fHa)ÕԧZ]wN+m R#54.S/{XqzjJU0)*˾c MlsGr-K.eKWQ} l'K;F(39 tp;3ȶXGvOr2\O/ Qp00LJ,`^d硦콬 ryQDano?cJ$hj@i0;Jďi5&u3<۟'f>ubuNfRH\Pb—^-;a) Ia}rA>]ը)v1jXl-U7Sdэ@u:\Fo:1 ,oRcb.M5f0|un~H! iѿl7?W%GfDq}<-9 у7y8VomJcGЌ&{\ & QYm JjfGCe9ul Q {A &լKhƃӃf2͑ߙ4_+ױndR.w?MəҾP;r8|ǕOx+*m֬ W#6]B^qQX􊏭>xo^8OZ9I=)Ai>4p3JeswyP)h 'k\c8v겵hFV1|Ҟz`%M 5Q΁{DsK[a-FHܙ%ʏG c"}CԊĺȻn嶿a*p8s9qyj6=86L]vbg#?%G}P"#9]۟Q" $%T 4F7%D\-cLd[+ JEφF1ht粽D1ц1 }'+^ޛ oj`q!\pc[t[62޻׸ZV(ZE<0o'%>IzkQG> ;XVI i 8uVRj;!] xʐ~?Zd"%}CTa|BYa%zIh'@<06bq̗MUo{Lgv(.+nx MD}yy8)IZ4ODi _W!>Pmc194OcR/kygmևwcqJ>{"rmuXu<,>~ kҡ#luԀ_&vuQ}^ȱS77% Q-xQY=#},Šy]jrچ:\@>2j@y.P/dUsu?6i}7VͨEizaJvv@񻕑UH ><{!~O8,QNd>T?{+,HٛC&*(Ely3%P)^ }.ةz&qUғ&@8S9^䲚 %&@e ^Ӈ8 CszQmavk6/'1R_Ih1~0,\=ĜD=1<-(_Ώ-跤&E~٦+_>5RŇېXQ N LD-5ˤ^fz KJGGHK=Ñ@F@L3=WQ o.b]rvI1,M$6mcRy+J}]^*endstream endobj 287 0 obj << /Filter /FlateDecode /Length1 1447 /Length2 6139 /Length3 0 /Length 7118 >> stream xڍxT}? t@-%  hN.AVR@ZZAB)ATwz{?s?9{v~θ M!H' z&V Q@TT\XTTCƉ̡^(!^PG4SsDc7 IY( &**"KPsA=aEs"=`.hL^0m({@``Gvz`"  +)+"+Fz( 0+` EA|WɀOi\+ uC(70m]KY/AOs0_XrC6vp0-8" ($wt(NP61yQ(W"`ڬ"=<4W~j0/(w?uG }a2 ޞ"f=o Do$De$%%@ ` - cjDzΘ20g(8^D  8A]`{PΘ{Q @׿l1 p%TQABb2($)) ~Ձ:dH@"0?6|?##1|]Q Q0 ^&?3yR0 јCb6ߪпZ y{Te B[¢a( bC]ĀPC$ X z`w݂Œ٬UG_+(&! 8zy9c9I ̮B~)#h 1pFz( Cx~1 G<1@'fbH_// rnO#/|MoƥX JiSqяg.UE,1]N}^URR9*r A2LIemQ~L5b!wIXy{/jZ)سЉʅ97cVw)lrMͦc?%]t'0|߲I{EPI@d]45Í;i# 4wPX*U) ek8RkJRGĽ[\Uî݄X/_;a7"BJߞ*ؐͩU:X//ezW!+*/tWZG۽tHKfåG>V4z;[\ q6o ~<dKG9Fr̆X iK4WD7," B q z5嬕d9ɋM)MuwrdC(ȨݏXJ|$.)*zuчdƭF_REtz]*yoZRvUfÎ֊T~SW޿[-Y"KXkx\FlȖ,=I9Ϧ? di|==vӔ,״&Kt3v>k'zds!wk;nE{*j9RV^(L .Iygi*Rp0s+6\QgA{)C "3-.ĸmG6+XENlsO6a{)g[f5euGA[?;ӨdJ2΢Ӵ,+6Wצv݈0G6et~HSo`(h 9UQ{Kkf݌!jRn+1ٜ`xy;m3|GY)w9= ?dP9PgjEr4aU]|(yMqǷ%v].b\tk]9r!J̙Gm~%[0tz#QOk:W (-io ޻c'"cŽk]dW"gw»[Jixfv;2H_PGSڣ ڰb+o;,8be\Iyja]nrT7GEPHp`R\<ٵU`IOVjRp\/{DžV~)mZɑ>Ǫ<۳]yA't1<=ǕB2AO}&y EEs&ݾm%Vw$4O9F- ݍT0-{li[&)@SU+<̗}1kB2qp}[ϞW|=I7v <:ZI^a0 \c^ӑxG[_1IO=;[NL!o,cjy}vZȗ^*?sh(1˄BJMTߙx ϫ&74ԼVQ-V5n7e7Oى-qQb+_}م0I@νPu]'M]dC6SJX3[I. ,ԝpyˆ{>G;$H m[@t)2vx;?kV¥u,ny䩾5md6FdyԺ0;`vu QCxFk#1M/6ڕ3:ὍZߋmLPz%,Qq͏Ъr^,_zK-ae2#qzc8(ҏsEXU\PP_䧛i^b@ {/]TROS?.=̻&4Vu-Dd}3u('-055VovsNV)L$?q)jXxd@;G=mճ$K( KW TL UVA>ى5JH[DDD:yHMg?Ȏ,\x!>dA#y?.=Ho'Imn|(wH骲bca|v>:F@JÖHax=si!V9ST^S2MHM !B4Z ۽* =9;O;,KKqn ٤,eP*<ӳ^sZG/9$B qrY&郥٩*۔ˢn?|.ƚYנ|_$#g_\L02E|`M ~O"* \>ȭFLRu4\*:KV?-ܕvI,#|QYrwށk%ۈ@Dq漣R#P;G̊scίOo0 _,P܇((lū籸s T!7rF<{@7ܾiP2RłP,CMMջY|u|? (Ky;旵\$ni$7Z?vN\UkjJj4,| AvgKC.hY^h o9! Ĕ,N J[(%<{iB-'6X@-]Z##vV3y dď85*_ei-3*zdw0\Ґ V?_>/Y2tmlӎ=fJxlJ6LCt{.+#*-̷:hO7D+!w+C)7ܝKOwP7lZͭ+.&'V~`AÖEg)–FWaI,l-XnZ _oC~97~&?c4g^zhh0'Uv=!&eb8OPy鵻gKE̺aņRh49f˭әDV6o>&M2}zƏ>oR%!i& }&Zh.RclfF jo0yvc &ZʲںgW,RMf' U; LT%4\6)$^r&d'p5$|Y$]OZ\n׍]~*A|:̷2~iAeA&8ئn:{<;ݠ:%grlQwBxeɍQ[ֹXub]bpvKvȩ Lk3ysa #%/Nբ ȂOCJ_qbQ (Jre,; .gD;茥|3I0M)0we%U=<OXi ioU<]_EBVQd1 $7?e͠y,3!42R!ۓ"1 ׇ?Qv-&єA}XaG[e`EzR>PDO lq?wIW09lxt&bglP._xS7 m]{lg>+bgB24F"eKGFgZR|pƱ/w:#׵_c/v{r"kXf1N*R.T=Rty˒~D]=s 1Q,d3qtLkb gG) E#64sEIVT4M|KH )w7Bb MQ~eZ5t(c&]+wXKNGay͸YXS%Lޡik~a#Z6@bp;w~:N]4]gM8PVxWjKҩf|Wmxq+'FXgTuJNSir|DiqVOWjs%"uɶRojs^Ŏ6ctK\?FzCRio<5pW?vynm{#{%iTOMՀys>syx~Ɨ=V;reqZM|zVk>$_ߙ}]~sy5yN\(v}^"bw(J)0EB8v[kjf_ 0%7:$UgKS&`F&D),[]u#}?6>7r-К'̭܅X/jj8S6^!}"%^qJriB`e/uo3QjW|ܩ=Le^tdljgr7gÛ5reLWNePW up漇iZi`jdJ+OZ!ׄ_%[Rp72Mp19+[gpzO}zE-ٙ;̇"a?V.Gz(`> stream xڌP\ !иwwwwo{p 4܂>J*zs9WoT?Z8XX,v&6** ?r*-  qg+D&a 1TtV.>Vn>   "@ tAwprYYB@kN`f jt@{HFsS;9?!h]]=<98Ylnȃ/o)#,& O׆ NsK+ߊGojd\!5k 7u5( 2X9X8%H<* Ws8w ^,,GY=s[9U@fo^I_+0uv6BLq|X!j{L`W ң寃0%0Af?,%Y;Y0A|$ɧA2(U 6ɧAiA Z$ɠ_ љAn 'Dg`9H88,-! DTide.AX [ rpsc Ǜ¾5 )Š? u@/ Nb ?qv5?jH0Goh'K>HՎK\" ם߻!;_BȒ/A"+? Қ +?!3Ginf!zc !Ly tWݜ!T}C?_k hc?Ħ.FLJlCWQ7HڻA D{o9f+ymg5Moi;FEmO[τlaޢ6q#2KGts>PZ f2&-;LHhVgX\,˕i{clCeРwGG7YGBi}\D&ӀY>ɷA7!f.ٲW2W1jV-2Ûa7/6ExlwKEH(f)+/BFXB9 c-P;:hᒒ=^8Ӥ~:c< b| hhg4ZYя)JEuHrLUH5u6. c\}7Իo)o@䔗uʟP3HhPM>Z;@b*`*s+.4{Sjr g-ń` %ّٛ"vtiYғ9ry҂woLe .TsWNaq9pRNkr9V{By'*b4% Q1{_f[c 3kp #yʪ~X3;]*Mj'J^^ŭqK(UOrsOI+XM%*n2:]./4d)BAyYԀ(i91|bM<y]:Q! .6P%=DN,c:͍Ny݂90z 0mWH$6m0.,uYBKrϿ ỎHoa̮Ks0`g?(ߖV5P'<ZoHPc& M|&>kxm~SeMB.Qcj** NA*{MM=OϤ*590]ڀzlYK "Kew}E֖aUSin}DL1k>wVJ#EeYo %PX>^٪7̗3_AD 2 8b)ؚoCc OW}8^}4D 8> X'o#pM_VLd$4suJN(DutƆ)w { ]<> "#rRǵ2Rr0U$ĈsONEZEi~*+c4/j֫mð$`2dz?P{';'D([neQ)r@u!E~ R|4dG ׫C]~`u2+0 k/ҝd)^y~khF+ﲪ ©4JC/jM7*7 PKކRXxKy+{ 5~b{YEU,UԎ|ni7 `ݿ\r>3{ 9T뽘H`1փܑUMA-aWPp>2wSB4׌clPז_HԨ) BL$?ltBT N>*<*XyhP$N0`!D2{ۮZ0¬5oQU" W[:Xe~u [I'%#&ؗ?c}'N`LW ѓY`?nOu;fDlʱ5}2dbEDòePrFӕ8.Ъgch@>9}UGi.qXIѠOq{HK~﷖Jj!HT,DL;'f<>Q*xnpT(]Co&ڰo5eW[KصU粏MS.ffVD(!y;-3y >7t*#9-rWC.MQ־x^ oV{HV?rc6|5Sяcu*[8~5>:!|^9~u]>2sɩjqR]^w4iOQt+LuLz||.b"8i"VtWѯ!OjB5[ԙG$Uby1s<^f&z%jPlV <9 Wsс9*#fˆ^'?ٴ(+"ҡ1j=FJ2!]5/a! 35䨋Ϊ=Ʋ_ةޣ=u1K>_o~&Qn[7;wtw ݘVbwdщ(;|OIQKc\Ilӿ%ٖZ0_DXol Eԛ}DqHU:Ëm3qxsk5d~LiGwi[_[g>ȾjmaP qE(0i9xxEyx0Y 1jF"#Կ) GNhiMвus7[*74^R/DMM,u[թ9*`XMKD븕}: Z*bN6$M~55ʺ'}w}`-QҞ'r9_t{OHZ5vnh-oE#QD#8ߣtYMHl&ԑ7p v6\{tɼ %A/L72?i\_g=Osқ "}Ri[nȦGZEY~g}h/a !|vdFCQ@D}&($VǒUH2tS-@qk[]h} QK J}RtCd<@ѥ9cUU>bMѧXx co kU([Z!드ޮ/0積NťZc}AXqޯ-3B2bbZ# (BU *)$$C7h[ ߰i 7\*Tޣ_}-.p!YϦ1d 5_ 1e(OUFsx糋3@ɦb+fa7|S'g#}ܻ%(,IčReq}|J g8]u//JuxWXG2h$ߎ~6wr(X wL,7[CF]l$G)D}|^'Q]Fݻ؎S2ݡm[~Y|Y)͏ƽj4#&W0n2C2 CSD`Cٕ áC[(i?vo Iu%׷F#VBΈXAbРϡ^z3 gv*ՁM+e"`F/>b bo|J:l(HnMOKtAm 0{Fu𵗡f"<9k 9SX@iT'otJTtڝnޤWcu֫δ]9SF5) x$7Y+ى6]t잫Tg;TrC,#O#д n LvbshC=-Sd(ZF TѾUC%27/WioCNJ֑dT&ę9UU}5}\7j= nC< 28ui7¿i Z_C>s`PX|P׻c;0nHU uIۛfw߯6~{y={N[j(ic`i~hmcůJq Ӷ$:kUPغi}֛םQXQZx%WDGܣ E)3aM#LR7MuFZ/ G IڦXN$ǟ#QŸlZ=? V$*r8l+˕\ُq<7+6Cb&V#A>laH!\s2e!NR#_?-wY(  ucGg[-^ԩP~du،YK\ p1Lj;aCt(kKgUB dcQ'Do0^wѻV"\pJV~~Gg .hU %Zqq12LZYOIEr3}y Is :桵F镂暇G?[%Wӛ4?#fE\])KJ,c~?'RWr rU6D.3@dx223x;Cɵ\XkA1U&TZq h [$LRO6T-3}ωW1y̺"]LW=UPa}_҃Р4K+ )ez+e %+'bL>I ,5=2XVX_$\4{#ʕ,h.^NQ'g.N1;Ѯ{fWcnԎ*ϹBY]o3^,<ޙ >gJK5I,ezOw8Ϳ$q07"rIkF l+ܐMT%^ܣ͋d.Y%ƨI{%@Z;МH`13ayEO$+.amWO-)3#1 ?4TMLSnpzqų~ &%#}2Ml/sXylq k4GV' (YI;KaΧD;}f{?IxMp}&s8͕;$mPĞ5CyU(r0OۃSC,굫4O#*4kq\TϜv*L-Fr=`-n@^7F]gBoޔT l\o"?ȼB17奣$B@]zX`6I=='Hv9p=?e s88Ee q#.׹yD`o ;Px9䱽"ud J a55t_ij5y<ϟ-hgjҌQ"0O2Xi/#tQpPhGsڡs3~kqbԎQt* ZKfJ3 >۩sۄ^rJ)44]fҕ2͸oܕ$6<^d^NF+pw!qE7aeݩ֨· c?a+Knv1Ԕbg|m&!EjL\ļ%$tBlZM魥Bඛ;kjT.",*.dzȅ_4T:'$gG%ʍSa;`r ֞ur9Hb{5_r%}wum񮃫 o0qLy)iduO0J#>p&%V dr+|3}8W$X}*x{J*oW UHUn3Wcxg#:ūG-E}d ` eMUh׫핽 %2>H-uۘ{kۉ^h /i$%Ӣ$3ChxKү!+.My/riS ~uW2S"#QT.>bH!t Ld`D"tهdsZq^#~сԫ ;(*y2q­w13 H>,{ JWoғņ^w3vkQKhbƓ I*cV285Irdn'hew'anؾ I1k{$#wH/vć.4Æm_dI|1@Bw87#C ~%*S1i \E'!̣ hSFZ)r(vtO$% J cӤ]z}p{HFK=j|m5A? Fdj owZK^F4&6oz&8^00n Udm-ǭqc`#[ry)!ioh6}QپA<+T)]ҵj ȭ7дjzQ:oN7۪Y[{1=ƾeypp3|Q<7b'(S@} P7)fi90-sҸkFmBi8'Ͼ%Y-b3ԏTٔA>fC?]Dqn [V8͌B72vIG[Hab}]5oNH~n&гQNq[vypO~]rm[/'y7h|idʹt*U\<^?6MěJ?'J|c띱(|H~~K ;:AH ߔKT;_%mn [/ i4*k, 8إ~M"SL# 1I4pd^}S{-ey T> e5{_Ppxڣ}*Y(kXN3ɋ:a'zMgiQBt^FnU^2I{Ou˺TYiNz+}P])&ylp^!"7M(-'t?~ʒ |Kk]1AkhS<(p;Rv&|"6Ϯ_g)೔oXBkr$[,~!nEK i-O/;s.D_tvl QhM *aoآ浭g13 :)YӲv ͅS⬠ΜF;m.?Lìd6ȚDfvuX*7$6AHtoTh]JbV.9W7\LzEX+\g Mӆ#Wβ>R.sl҂zFpx%d mEw\D|A(5#^I;MK)y̅m]ˆ2Wx-I}~b&Vg)-Dd\b1ĥ̪ϬY֌/Jx^~О;NVF[R/g}\UH9%YW}7*\kyF7W!S&d!knf>D8UP'j W_+"+@4ڽ2L,-O_DFR_taKbr$f`Їw- o1 UBV2G(l5̊}S hD3^CNQϴ%Ά\Kj ,jo9KFyǒ>"|51|=ܑb!*ᏼŻ:~O*"!66dXο!"0jx5WPʲn9y0>yV'貸k$hAqt@ggW(2G8+ p v:(b_ g2 K4r.ZK#loXY&(ǑpJ$CN*|DR#>Y oa߫vRL~[ T=FL 2x ޓ&ywc0&Gԁ0:m!*^㳙BDzt[Fѧ"5/H'"߄^!o 4\:$3G9_Mi 8= c@я` 2SVaYJ^ B%ZWW XRL#1YHρv1.C `݂^1ѳ7 q0Ԝ譴M;wp;T8\+ skd7< d HKc3'S%T[=S"|R\~xRԭ?Qn"gf}"uiuV,C*ZP;_R~CL 2W>5w`|#D?R:0mx#U2XQjꚜ~F%uAC\quVZmwEwz}=`15E ɂXa8Y#U Nq,V؍EwYG㠻R Wq0\jv)N蓶e{퓢gsJr&I7a.4.y7ϭ_ԡ̄Ii /tG&) lmJɷBZs-#(|Nǩֻަ` ގv3 NBK?Nnbgmy#`46 R;]P8PnEn`/Wxp1=P}bC:(y%3yYfK#З$cu Krg3^Fl&7-va$l"nNUL'g*MW?y#26 l7N}xB|$~ Tጥza>$`k-5VBy:AaL5|R?EI䏊ߦz x=7SA[- 5#yR.15plH>sUPVW#UEeqC1M-] B͞rU;ܔt9 4Ȱ)%u)Jd#*/9hÉ;W2KOQ!>Bp-)ZIlir?O4 )9lN~X-f<)9fEPkIƉv{^޾y~w'˛XW.aSdóUmw{P*Z#6>^nc0G MՑF{n[oj$4λpݑ*wm&~(f<;zrj=?_caz& u8"ׄZ YǷ5v*XθapRCxn!N#J7rb(ɳw;[pZDwȺ.1rBH^-nzsΞT5Yb{U_t\h%xzPKN=0nd.Q~޼6FDuW)sfJYoH&}3NR^J5~uA0/?u}*?ӣ4lԡTC'F^"I&yR4+#}ߌ]/H3 :X+c79L8Qm9=]% e@YU^$ݩU.(nmrv*$C%UNh{=JA|aIj:=)w߀g>H/۰[KP]t!_9sIl7!*XÁDfcS̈ߍ/IozoghWCA ̦0'lʻu^tqAQgC 4غ2RIݮ lƫnge ƋCHlƺ&+n"6h[h'/)cE2(Z?gMJw =A0\ٮV&>쾔ܾ$ITF tQ#pد[Xf]>6J.JH>DK>,m/W~ǂU}w{T串9NJtYbHw"2Mp }ypIg`ڐUVXpi;{LEokW' -_{ rqY-)i wUL<&&J\B#Q{l1|)Dt9Y Dq)N҉$NK?o/҉<6E z. & qFY{Afw>|i >IMG n݁wKuZ1hm;:Cw5 MZxhg/x3#KEmSAp84uJ'Kk'%'Y뭟]Og1=uj׃=yQ89HB\FVQ,:/m"/#%XeA7i3JEQg2֜^U7+?ٍ_2ƽ$KV fsNr-~ z]z҅ ^>RLRN_KdMn6 XDc#lf}]._Bh+G-̘q6;] dGד@noWVtO" {sP} 2)]/f`t^"( 9eo; If˜sL?+a*)Mk_Y+E~8xY6T'v`z3蔟T)ol$Łuʢ9 p%ɀʆba &0 >\ppC_c,/,.9"hXT49=jZ@4Z6r3ssRTUzo(A҅Yr\ W_>3,-Z j\Weecv&tj U [鬚iґe}dOF/+qPf|:58:9{ّK蹛ܮKrb@[ѭ8vf: \9ÛZT1jŀyJ-30$KE3H{NB*h.)(QY~hηpwRڼ#xr4zΧǃYUa2x$zz#E4T,Z:ǔ{s,]i>n}!65:֛8(c [Ϸ$Pݩ9)5 vʚvΠ.Lp*4M ͊Ĥy. s>v{&):ܽg41g+I:b50׏XK*乺!f;ߖݖ!407e_\tu)vXqJ#/++܎ ZWםѤAM MfTwa{s;#6TI~Ke * :+9p4)N&1H>igyNyč=~.ư;2q[gߖͶkL}:1ݭ^wqPWgwtjl)zo⊓O?kxg>'TB U+3O )8y6TʡWί{ft3 ኁgC!<>ԟĨ9M xgh}vgH,n"!=p={3Tt%9E!n_UxoUrA:Dzc()z]W5|] *4Ц$6i+&I:ByVmɧ -149ǓzA %~6co! oҨQFs+!1`ZZb4-m%O ACqq$"vC0B(~R$y]kѳ *6fzc:K*%Acr HT)3-x=C`v5KW+ݥNo܇Nv@lJb6@1v&A)Ԧ/D&PPeiWb\iH0X=id8H!r(=; sw+rd YzFӞRrn3Ù}rn(T]|8@EA9.9)nJs׫;J͏8?o+p!"1*"qN,X$ܸ`yg;PJaƤFru/@( XkfoyR}&dV\GNG֞X}+1s(䆫R% srQ`6#xlƆ2>R/c Q4|.(UQȽN,&7XܜlqAqwLfQ٠ڕ&WK0[Tq㴍Ҝi&ҜB&Ljzx3{=G_UE1>-xFu\ً6jI\ bɰ,H'8e. 5cwe{3%V;N}X;Ko/u NT)MxkOdUxE\JSŘxg}X*?u'.?N0ʥ5n-t~cCWyAO"s{ >HF̉vKVރ6}=Ҝ5UFH'`Oe>"jژR]v^Lf%=w"z_2;_w&o}in[FdLԫ%_jsѾ\%k뼛+nT w2՛['D K6J߯.f X{ GRB!K/E4$i]J~^X\xsh1R2 sH;K}?䴮p$"M̨vH DKCL5l~In[F%k(j7vNΣMҺL- uۚ#:O;7beU/hV(MFg&3z&6)9GA z^eg"BzSuXIwd P#:w@WMѓmQ* '6Q([w@?DS:XW.$ cfsQmXMksl\fXR&ayzF5x_D?ȣз-Z4|jn,! ZdF`ku'Vn@`&{>u߽!Ծi棐cv9 g,p<<};c_dO؂l' )Lኜ@VLޣ:R͜īvPa_gbc*MTH<$wY$L&PRG[=1VzDfo zgoP[ݿ yw2 tYcFd"Q+\, ƿk;jQրV֫xSj Xpʱ 1,E,Dd4@s{%E74f>*8lRyJ(U֚ta?*EHOKq{Z̘eL43ߡT1Tk&~"9jjĄ"]}uȭ+QіAGH=6, OxȫSttzMGa pii8&?XSeG_j賓|{2|3N450}9! T[kLugD-躐uBLmlp2vbI,tH$],;H 1.,Tr'D'\5PQBa+6E)S?[^0c" t@9gOk0Q% %xT&,+SdT!=3;4)OXjxxĀ;35ql¡Gs bա [8TV^qv& J_|;vc <1(qӀGA^}R‡! fyu|"o|8mm-=vj߇Ag;mJ@؊GlZ^Oteܔfem*3?S)=vB(Ӱ,~Q'zgI#kq?IJ I>RȄ}ٽ3)b$*z);;9灇r{=Od?Va"S{GX*}mK'o)gAIp1ZV#ss!sAK KHT4ҀpNF ?9bd(nqveb*HЦ6/_O1WXD$0jiuI;QEgb%^Ysp-yLd7;~z0/;s]0*:H? %;`Ք@}80#XQ9r fly={ܧrwcG2 irąZw{+J|8{,ro Ӡîl4^Z8T[ t{g59ZNւJENM-SƟ$yMCLWj|0Wur d"xZH EnPY ]n!*,14Q(vjF,$pvL-~EZd3AF"`.r-1c+Oa/LwPZS#N>[7e 3z.tpQ: \^gJ FӺS~C TGCZv6N>py, )v,Gv搐1I==?ڿIUmJ  uϣk gNmՙ|grKt__0O "g;MEZt 79/ (JmSIG̭KoEnWH:ETJudfL3'qB#6f:W`+s~AIuR kircgեK!"\u"0`ͪ%L%6Hl:&CC! >5ɕ?F@6F{zs-E@y?Vj) >pVn|;{¾ Qjc9;/C.ꢝ˛(4ڮJzu7:^يNaW+endstream endobj 289 0 obj << /Type /ObjStm /Length 1609 /Filter /FlateDecode /N 91 /First 792 >> stream xX\7 n^ș |@`$]};"G7Nf ҂ NZt0+EŢ24 ƆՆ̀JqI9.UΛ˂5![(1c,$Wl1Z`}2b 'FlѰg,иE•Q3h`dKX.@6d\T Y Wb.\ d,~MU WRUQ BH@AZ /:6FL o="< }E(8PCmQc٨d 9)mlM@pNd[ `+WRSTad"E >B0f@IG50 fe:Х\h+cQh} qFX"b2H)$lApJq)2KuIRO]7^ߺ_:~t/J ){ƽ~}1"Rb(Z! ,o9\o53A=z7Fp s(tŠg}k$auB b'6|B̑cT"!pU VeـrYUF. 2*84_ԣCrwrаԏS'9ƈ(ߘ.<'" $ bHx!a< CX?ѠťMՆLk Cn>"\4rZ-m2 k-e,RPr'-Cuʞ[>gr6 }#6ޝ-|8K8k8M&3,Ӳ,ٲp LUwCw懸uYc}̷ ]eTFj,(JUA+NA}ˆTRqqE!㇦~'X??z\7w_Š?z T4P0.^8`de6L0?!Lsyo\34WZ0͵[r?ƌB e%Pg LKyr􅫮RB@ %+0Ͳ %L3n-ꘪ/Tת҂O4%L3-/%s(%3m9*E^+ iOm#l8E=ì1 T3,DNe1:u"GtWm1+̎cʂ[/H2ȶlwmK܎9&r02ފFdCKsL/ꂛ55Qqe֯ȡʯ6_2u^*rݭ7Jt[}:endstream endobj 381 0 obj << /Type /ObjStm /Length 1673 /Filter /FlateDecode /N 88 /First 773 >> stream xXˎ6+F|SE Hh,@[X$O~}ϥd[)->.=>( 2$S8WxjEaѸe;l}gj_'? OCޔհvb{ȫ9`v L.2{bQ)CuogO13Aj}r0|T=u^pfn$_[&ȕ`$gIIj3''siB)OQkBIp$\Rː>c:v$nGA_ 71IqN =I5- w.%i i @m:҉H ¨èCD3Y@Pje=ҥH$:Bz8~Ik%VpNX E46KL4909q g'w`]w8aZXD%փyx"Y Ӏ]kӀ[@O~`d.h9 эD>-P.Wj-S+yr` _x+.mql?endstream endobj 470 0 obj << /Type /ObjStm /Length 2301 /Filter /FlateDecode /N 91 /First 817 >> stream xZYo7~_Gټ#c{o [khZc8>_F6bCx Y,"x3^1iJ͔( ңLkj;fE陷4.J3*Q"nH*PѨ1LZ@I:PqLzug2X,1POdJx )i1ԕ ԣ2 \Dpk)/ie*8BPN,[SdɬL[`dkb:`V`K/+0A vKӭFR2䭠 @lVƢBHБDLپIX`]a b . FH*ɜYPqԣ9T9Cte UXⴽH`Z-qD#h|H6Gړ XB;d?ƳhQk o7`#P% @[,FCH$ư(huH-J[ԊxEK;E#:,zb@ 9ըX1Ľ I5C4тA PBQ~4Ą#Xv){rYgMɕeoXS}^dq݌ʆi{!s` xCv]U,Gtܛ`Y3DL4{I>='GG6~rBG,O~-_hVvVeSNȠ#u5PoVw夼aem[lx^:EIe]5:/zʲEI[UXZqHyT^)Q5wfq̮' q=-qFESno#vCIƽ\ @@`R?_ :ձW9 lN `73 |ś.{uzʏqۯ!m$V^\-BPäjn}:7(5؇Z O xcR}@WƔWyCv~벭g +jv}&5{ɽIS]UOOsgJH%[ S {h@c4+JKtWP oeκYݲe;h+o ݱ.uDuݚSҺ(~F٥cHJ -}Հ iײa =7  /~y"/#iQ 3%5Js ߺVg@Ľ< 72pDWwrXpia8ATKy <"6IgF| ZzCda=~8%z1HU!BN*~⮥*E}&ѡv^+ݝB\ tZv bxPj*osmT7ݔI ` uWmͅw#Q JH'k*GdРm5+߰p4&e1p3ppGjS!FZÿw;Hqf:8 YF++؝َ# TG=ZAy5sj<[`a^LHLJ~Gz اWaߡb~B5+cm/nѭxX7_pFM׭,O)ʺ"V[WݺĄ_ZkZW?.c]nd]Q|`k@o+RyBVpy'CYjQs%LjޚۨPShoRDJ+#4㤾Z[nlɑqG)WvٍCJ=_g2zѳs L9l5އ[3̦0fA2 mܠ\q GiCy)z1>P:Cۦ-%#Q!K%>u2]Da2B,mQ/nqu2r:o!tGHeg`-dk=@fPb2sGt7 ʾz,@[ɵ KͶP;q48~_j;OSSy.t2,_@ (|ɢLb1~ ܃^xmr{ldl>Ͱ9e}]9w Fjx_;貖o}ӲyYUސ{|EVde6ΪlMr^ZCs6O[M}7QOqď:}1G9<'Y.Tt`ޕow3{[ڝK_Hm5~R.A89RK endstream endobj 562 0 obj << /Type /ObjStm /Length 2240 /Filter /FlateDecode /N 91 /First 817 >> stream xZYoG~_я6:X8BY#r$MC WsHTH 5SWW]i&ueK<3I3ba c0+&Ѱc4,JA= etf4$zoPE'b^ K: $~''4Тٳ|g+sIAQ|-KN"̦%Kf?2,y3FB`Yc:X2P,*%_wm"yt2{O!O>=CY~}ͳ0+'1K&tQ,}1+qv]Ȇ%Y9Ί"g<lcχ8’25Iٔ%Wt8HQnE^Og(fɼd8]]Lob2Npv3fa\ZQ.a>+h}{u,7a+|?a294?9ŋl_޲%a^m5O%WC$Syi~ȧ2OI+P5%U0p'm&5m3ux7z!/ᇌK.`})I?]J "GV!h)O7;Dz2X+`$G0'Q}Vs Z/ $cZ"ZQNYZY zuR Eu3`6glq 1Z 3Kt^U~Â('ඌ4ݿD0&(j{zCgЂ";hy@R%mJ? ~[dC!# CwGddȰ݌ 2("#UdȘ-@|TbVRY`WOYKCI¶ _8B-h1(@W@.hAʹj8m 9Ul&JnC덕]Y'Mé5ņ1Z݌7Yac*cExwt1:Mv\wTsڄ0[!Jgn>!ss!u]\ Jqnef51׹)kNTmO,N,9P3}}9_Bpu]JV,͵@Z8ך\eh0ooCQ+o<8ǃ?O߽;,m:[qϲb8~{ҟᥣnՊwɛKQe!a/;a/g/+ʫus(|޹'Á56T=%g&*)逓(lt5o* ONӻY~s[2zq JrwϤXL&M%#W8) xRcIN@bkչ ДjL:/q><`4XM~f\-MsQ 1mWZFͲÒ$O~]H5R lWU.s$Mޝ5"ޛ5"}J vDK}hZboVi?endstream endobj 654 0 obj << /Type /ObjStm /Length 2691 /Filter /FlateDecode /N 91 /First 823 >> stream x[mo8~(JX,&wJcd}FۉS;olĤ(|f43RZ&3%dȌ9lD7'7T*k&6&rX&us1i[yjӑ)!S:cN-USVzT4S.b@o xTtˡ-*itL+`i ɴ'(FЩ#q0Ť2#-uv(/xЭh aF?c `QHf3Ǭt0+3Vjq0zf-q#f# &^U*j yDT-?P aTK4{8Z @3/K\4?K-y4,HeE2Q,XK H<^fDIZ&UEExJY DcųH<`M Ы ͮk D ƐBA`&3A'=JA@jnS  "j$YJ QsHOJ~{9 F­ >dٳ|Z Ɍe/bVs<Vrr`oY`@x~2zwm;4O?mɳjP z88_X6+#4]ú.#̇ÂHmZNY'lTn Q9KY^/Vgդ~y32cLJA~أdZ ge5G=UTAh0!.dwLe[~QՓS%v+א4r +2bEڀnP+]:%KR*P j{%@x"R! )8ƻ ]2Ka=_^` kd\*}*C*iLfir4v_7u:r=:;ߪƦCUGoqmÂz2iw%|;jy^p~.nqZU֝~ՊD +'|xq(p D= î ׄ"4n1jtfeqU&RW~3tvx wУb:KRy䩓D|@Fi X~k{>6r~</nk=t$ tH-AIiPkbzi,g}iDwjG5GzWse,G-&CSJ)ԩ4;״4ts:b2}*c.rk}hcw [C'^zG.E9v{˴ \A?wQA=Tkս# EM)hBK)ʝ ︁(B *ڼWa{޵1&&iemݯ.y]67C@0i2o,v)(\zvk& Nll=te{ۓظ>bcmb/{6{c9fJkx 8"nYsmv7tctTTp21>dt(E-Th!U9!?C*#zh|@*e4BSWVB@2e4^W+u wIk=@uejp=Կ6:K^S^)O-7M ӷ ~(idSM{7=ҨY~Gz4qEhʮnlյѵghmL=!hm}鰕> stream x[ko6~.n&m`'MEgd+iʞq:c- %<$3 L22V0Jɬ(s.,(EOIcRE O HZ62I =nde$9Ŕ^N3%=2L)"Rcj D"0P5pi +\x 5FQô Z%zt̽LG)NdF)00b& Ga&ˬH5&@'xfuz4D1(0J#Ybe})0 1g#yBqAt0kK[qЊ!@ǩ1pDLigАHbQ#4jAVӅedA7 !5CXX])X&`RaRI)U .'MF2Qa ,h65hh]*)P<@I*O HVr|+^0cONe[q-6o׬xٴӪe/ōnc+IOp qqyGCqbūz+ަEceU͢jIOYbL)8?g辯E9Nt2vkNRȥ!A܀m7 D#ApC"JN@lѺYp5 H,3^sj##wM&q5.A ܍s%"&PX2NZ S%J)@"?ZZ^#)o9VdGO+ \g<0w7fnKg$%, cCXd1Vo%`r`kO7_Ò8F~hXB7.\Ҋ\\\\\T`԰+,i]l~ϫh6|˛EF8u8fN.hlyv y{SV_"?x+m!u?8Ożɯìgeon[ʾbO+@ѯ2? =9fzkC}TԒA@|[jmY=؏|?^^fm_6zKXMb.ŋEW_U''vf̲^,ˎ]6}5Nnku5+N/'Ku1d^ΊOQuVNf㶢YN& Ŵh]ݱC +dn˵rqZ˳yDYT2QIELZ ݦwRɥAZm.p棿&WͺOh0^5 $qSY%^m'2HI-tׅnbΐ@$||C2 u7ƌQ:Wps%d8>R)U+Vvgoh[C 4a[e\zR<€}PSN\D YJ D -Ц5[y4vKRɬϟ/ϺyӞ9uů]U| ]Lw|Z^t͂?.f nX@Wn"7YǦm'eq{T -m"Ҋx .qK8 8?3:2%qPe(9 9@ 9 CZWv M>BVGJGpF:~@pxԂ+eU:ђN[X~GL%ȶ%+_/qJS$!m9S|?Yv¥?]6O>::bn~wVIS9SʢH_ϙ ؕi?R"jy** y2k [;pu<*8.sO`ڦ[N˄~3x2(-sX[ ][澍B _,whΫŻWlVjUB'xy/Dh( No^W%Mn r8W].s^ 3*Ǩ|2]LOez*oULOgz:+z2˜[#P\~ X!f8 ūyRҰ A*9͡Q`/6_Xj9}|Eʿ铟?j+zj/QSx)DYoR PHVps4}:~=]΋.D1ey]UΆYaExSG]1x>E7/DĎNcfurŅ;ѳe/S/J_V-弞Xwb}u bp9O Z^,endstream endobj 838 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter /DCTDecode /Height 392 /Subtype /Image /Type /XObject /Width 538 /Length 22731 >> stream JFIFI CREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ٜddǃr9Nͤ$7~IY֘A)_kn lKөd@y`/ g4m0IjC)\hTc $㊜B} 8CR+N8}*o$SgQ΂̇bh@O*L_?r^F΂f;{R~Ɏ6iܑoz\v3O< FB0qZȞ6CYd&E,d'NX6og r: L96;VF *G V'KmMjw4ĝYIt;}iJ֯AGaGظ\,d4/ڴŨ=Tﲌs #ǥ8!h}0{R@( Oj<&8R ?nbvb Qg# ja$p)LDvϽ.p3y\U!86" qUyaX7j >'ҟ5}ӥ7`'^:S,@sK,T =)DY?JqO^sW=U+$ {bBOsG2)@"UH˜`6(qH@z-~@kp2zOAwJkE1siQ΅fP;s@<-pH&[s΂]"e(C)qX7?;.d+3J- N#c TY(Ͻ]/ٟyQ`mE;nG2 2QL!V2B>͜{exczu,5Uw0)6^*xBk`T|Ckpd==j敥Bt;Bp "s\'c(e;jXJJk'I0T:Aqi(4Q2ۧMH!N?*p*=(W10A#ҟfCM(;@␨9 W <V6sc"h;gZ~3dOڢp)|8lJ#qUr23D*] yKԂ"(zdz D&@ \pE]@Wq6D8PǧLA>m={{TW+G F6=id̋b҃*p?JaPq)1LJG&;:t!F_zrJX9W#£@K"j e&?Z irqRYHoҌ`}iT {f'I1N=pGRU#1׏jO(qM9^])1V|9?ؕ69g7qOSU#cCޞӔG=)Ò)q{!xC 494'ؐҙ=Lq4~CixFFH nG;\)UEr*y5.4⟵f6x@5ch)6uڋ sI5.iHڱ"d\*IzgJ={4VךQv8J?\=֏hy k+mI*1Mg'=+qv>[{K^!EܪNk~)BsZUHAPW{Q Ԃ0sVm~5s*RH^ sR6!~*N4 (XhxPG8<FIb=@viFA@9o[#=y+dIjyv XwE >ʇ2FU?(k[% z뭭@Pª\Z+vQNN:NWW5٭gzP&WcXd⁂rhx+\VA$P8i9 Ts)69g֙OCO 88#ANHAӃ~8*4>fN:f 9LH;fܐ~ȥ@fWO/83Qf44,dxSb\sx#t'ޙ"43?H1gG˸sզx 1y6}29ҋXGO+qp#8N(j(FwE_1F>')FffΐA\ =C%ŸHl,60q#Q^;%<,P*m76-Pɛ)95{-0ZW #'oʚ;7$VWEHH9WGggnv0F?IHo@M/q]I6O/G /j%`VgPd ΋VӦP{Y,t-GCY67=sHq돭puF95%IKK,H }JvN#ҚT=SԚP<A\IoaSj5lqVN#1k'A:fjAl!qYfM6S^j)Gz">׆̜5='D:VW(>3!,B`p_A 21d,lT/^m[nMI$؁OQ}q/X:IיQYÒ'50Jv븻#NM/<`(R)v8Nj78OCҤlUKD63<8VXOګp5$beتyR}F~gˏҝ&:RX*QɦV DhXE<(==ד*1Gp}M[{>o_v!GR}خc>J@)UQ{OO?Z]秥'sSF;Y7!fV;^'X}Ccnq"y3a챜T 7"aTz[<ҕnwFhoKTNTg?\ԋG[ĤP Vuvmn9Edk{ yvcdqwJXFJ[ء*ݜ#f~fDdmB"RZ}\[q䎞]n.1[I4 ȏR; 33HT{ſ{Ҙu2M;qZwOzZ秕b3ǥRR{fP`1W*TK0R%Qio+uNgTpMVF{}S5Ԑ9295OMċo0Cno[Լf9~듊ҷZyQVRdxʼ^J*I+Grާ~\qc#=;{W/v×U$HA:`zQH 9=sn\ѧ(BaNgyp@>o7o9dI6ʊ2KJP̐k]CI嘨'+2}vp#}953yxU_(2<>YfcJ•?͎})opeps\I#`(IsKDIw.HA8ԥ>J:_\BqXkF.N>+fWG@8Hxx mZ6xH9׽V2i7\#ʰ umNJ/洚'8ir1gz6mfo$b#\kևLw&as9o=H]!{㚈Z)VczWz t}f CAAէomo "B=+D")YxvT?:4OyxBCaFU8u~/5~qqP2}M;+-62{.k-uwO 9^ٰ.۸3wXkw)֟kKo3IQCI=lS[*dcs*"hbKnO&HѼ hVS]IQ<488\}ڍ<=i\gnqڐʂ{E{P'(&\Da1As1F~4d{@O*#q֗+zMr|w'viZB3L .wv[{0"%wjJ C`OQzݼWPdΰ<%kr'>j^f@8lܱ8lұ-IDA½~-ٹ=8yw%KkK@0^>!lW^v;{8}swͫ."6NI.ՠ?8&5>mPm *FWӚ؀JlszfD+֭X7[6?sgmtVfrI> L[v PDڍ5qѹ^ҳtc ALlhJDb2g`{We*.#Md,nߒ0lizp:Li7juXrr@ּi9P*?L&8ARR=h0z]RV9^S [_Hi/CPF' W cqk1ʻ;):rsҟ'n{\T^!cڐ6?cA֫=v;Ÿ ?\8|_h}ZHsiY%'x%q AVIQh+w1x)gB?i.?ַmJO?zӮ 9mnf#:L1BlhN͌=+/쑏ƒ C]uߌ:kc&rMrgZ)}Q}iɩA-Y杀yDjͳ!~&j5 foiy;u~o-y DnlVP-{0UCOZ^=i~q=}M?R䞼Iwl֏do8ce4li3jS|ًۣ0(M5%,ertlb> 1>mpb t"rB@z{aҭf)< ñLsMD٥5s 6O}:`6PqH- 5Z=:g'l D`QW-;5G9"0pҌL^* q9}@$BOzLP 1ϥ8 1@ J cq.pNޔz;f*J R⓽) Q/E;)F1ҜGғH :&pi tȠFx"D*1Q8iL`'Fm zʶ.Pmco\<` 7pFs(ȰܑX=8QoIP:6r1NyPXEMrbgiI4Xd֐S4@& m(> v}sMisA"q3sLNϯ5 -)hhqIjLsPG&A>SN"ݎi @8)@xa\x)2i^{f!=N=M >☮I3PN?:V 'kLMEnjffxuGQz3sLcObv3ғk=:֖.Jq޺=5ERsDDsuKU.v@c|}Nk'qcS c5Z"ʓ?JhHxP8? L84K9)OjLњfiT9P\⛚;'$sڋRQRQfPZq҂zEHH|dffsfWk^Oֲ/.MԌOc4I?pGnk@5W"'t@ Ba mZtCFi:qY;E+cȤ6h8vC~ݘQ&n*Q&:vEo>>P9QWRP,UÕ͋I.zZdB$(f؊p'oή8J>H?'Rb3wS1WEu=ZSڜδyi= ?})2}(#h# 1Ҏ p;1gC< aO4ex)N=+X#;)9ڏzSxQL'z 3Fx{џZhfCڏJ=i₄4v(#84dR{M.i2h& h$q'Jk1 R"DFjյц}Ozfݢ7h Ш:Rw<[(bOvkoc'9 gOHK2qG^^udObZobs:{ya L`XvtJ*52V˲-`W)d?Zմh ._b,掇;SvBYF~ЧKӥ4tg@0Kւ($/sIގ3߷-QIގ PSB:PH٦SM3[v$ 8|(-*Hmf'Vvrc"مmw6; )+qb]J6htҬ\+-G^Tg%2Iβ+$<{ֆo#$γ[$wl*t֤r{J&@cpOZȆ͹6j~ӵu훨.InکH[}BȻp*綞BѰBCϵ6XUUƏW^x{NIo[1>T>\Vg8}+o *3>T$}i\+dwUCs9w~^]2?+.4ɭ?EY&NVJ: fS⊔L"FihL4P1Fj&g *zCd \tץUx2?Ԗ1 R6sVY#Ԗ]$uԓh%f@!_z/R<2˶F2 2ӜR[qqMKc""7ʹ:u0J791e$T#?ZӖc+`nURk{2$tRGJNs]:1̷ŶzVƓ#J#UҒ?0]Dg[q\Bj#{$* y $t?S8| w?֗ϷqM''OJѳ!3ל֫K ("N}W4:`8ϭbټVdk2fXǗU46BAdGל_2rU\0/퍞4G Sb Ҷg]/IQ^p~QwfՕqIJfxATgb ozSzPږ 8+[c3MDhmϠiރچEsAE$"e@*xD{p1TLwVݕ8vZķ .n7@4 ū "P % gִ%ɲ!VeJܚ됴˰~ح[D =['S;mP8`GxX005}KuU9=4lʇqD2KCJWaH\0HwHNs!~v#iM;[l3P^OYF8ǥ>sJ1<jYq6,i#Pq@ΧH<m׭rZ\G]8o3³hL0㷥)'P5"RpVXiv!m3njI'Lt@'wlޝh4A u@ÆȬ N_0KabJX0N+"]@Ҫ6Č~4cj[p#'U\?h-EFnuz<ҪI)aqLwiT5H͊NqΣbs*3!="Cӯ5j=٠4HL'M4QڃE08.}hHE7g7!hK6ifwb3Fp9^ږI93lb~>} f扪DxIT(`p6/n~Zc=ʻU9դSfVO['Zji''Ou2l;?ZIܬx5wٜ.:81%I1<46:qj0E (RJs;Qծ1GiW5 V%銎H<ji < +g pȭ#Z6:L7SIF͚:k#^ek-.O`kyŁdYŤQD_ϐGj, /׽cSD]vW񓗻'kG~CNYCSڦ|L=iN'ӊoZJ1E2E3ތRgZLQ@ zcg]^C#ֺO1 7s*3Ici HHx4Kc[ګ ܳ-C}R}b RvcD$k*Ïod$wܙ06GZ&R3j<|6Z8r[Tdzvd8=zW/c:J'5[(Y~ʁ.z.I0rTQY^6Q\=vM(_{{5b%1\DˑA^>ZQaqU`m/F!+qUv p:Ґ 9?$s $Cw‹6@8葷6Gp ?)3$ 8;t$栐4d29c9'ڳ-"k,qzxb[:Nh˩IUelȬu$kj?'-hѩ._a=?N*-ԏZܰ[kˌTi'W7cSQH~+Ynppw1b[/X fcPBX.Y2L-CҖ-HNzQA!EPKBߎ)(>Qڀ8}飭4+iW9ZQRcӵ'sISr"1Gz+ 2 {l3Tgm}j-[EV*T:UY=pʐڥPIs4G8Sz|EkCIW Ū^%\|CZԕ)+|{N#Mv3^.@pa\,PNᾆ? 'N>~?z9SK֓Z,:l_zNVt_Vm HVqis8ݥ[ġn)bb2z$Lezywph8k:B]NNf׮XCcݸ\ [k,X5MF#sb]ƽg7ZJRrئ:Rc4`=TQkt4LwtDQ\r xvzH҂+hDH018O6rqPWЬx#?coc[|=:>gk8Ց?9zwȥi$~XsرbÃֲ5=.%>B'Ԛ$eh\qe=9dV r=h)bId#9Z)&Kgh RHu7w*Df49oǭbm4lAlX^Jn%]"@*v4-g9~0Pvb$aR4 t5fѭG1=*5wF2V`Tҝ:g*HohaΦzVEfkZA!1x㯽[I m"ʠ|DZ5:T[R:rE\.֥n&j w||Pz`GSKa3jQ#۽hŨ[ +ddf*q&9?Rx'\3 SGjNţp.aHAHcQ`O_N{jv.ROq}j̗*x'z9՛5f#V0s$yQF% +YRq=z@uYZK̽ =1y5]xh0-IY9ϽcjƢ6sP3 qޚiYZo@(vP7Wv ejV4 D]OdTg歸{VM\iwcyL8?l T?:(R rC,~YI9$ cܮ,VvV$I'cWSlTE 1o0?ٮ2tkK@@\c &yN+ozVv12r@Wf{-qhY7v~5XA 9%'2u!MuRW.Ad=Y8\ s_J֌9#N|9>$oT9Z-3T3tOAN bg߭e( S֟2IFԐ3~C%bK+EׇC֋uy-Yӓ`i^{Ul!y!w'rzo p1V3vgCsiVl"D֢]4#ƀI"砍.|+Ϩ:bѴfc4q((J:KL=)}tC/ =,X(\Or ޣ&*>k҆5QE?4*Σ>ڎp e(&a`t0"C z=ICjjڙL4^~DMpEZWiisu2b5JNFGjE_7( d~YD;Ci4) /횔vquX?p~{Eewt[2`Tb^F(&ܙKW$Nc\,`L}qh)E fI׻1%b)K/4]}P#n(^,FjKOh(dz]($f a[U?(G 44{"1.E3s˶ěsu[L:V k"C!=*AMSalWC֙-'_DRAcEq[^*!,x<+8R؝7֧&=yMq\Z6,ɝcZsBOQ*;NMeO'_f< }s!bTQ%Kۻ&Y ©㊔i5Ж'|zwnh#)ozZBpE;%'~w4Np9wR8@1IA=1ڀqրv((SH=h); >/)(=)-<9vt5IL\tNp 5qcLs\hTE )v'zgƨ ?\z2#089㊱i0܌w1YaʼOJeͥ B? T #\MٺdP{{<%1MssHe Fjo޲}ZQԻxm77 .S+sO~]JR9˅D0'EVLn<|9=y s-u:|eM͙j9TЫr0kZlʢ%oebd' ۺ׷\JC ?x3xg`ƵJG%exN*Wn ۓ]8KIGX/Vh E;I OF%̰)R`Q ?ȧIJNN}+sIKږF҂!PQjDcHdR ie|CB o5lGĂL|X1yաcP˃ygS.T#k4[Ayb8qY_23U+"^۳W91m+_'Rh_p^0i+Xj0ېUEۉ7 5 V^t?gmf~sOq%%MR\ng-\I@g:j5cxT"`@zpjn9sM<53g#11V0kT"3FNr(=(iҎԜbG\PZZSMt('PojJP9h籠9 ^hƀv@(@Ju&h4y5Wq⒔P;bn((?JS֛4,k`;T:Uv;R qlUs&X*~PvUdV=ܛ>5vMGdAEWA(KME.xwAe`S\ Z3IԧgtDU#$ҲGKIj>y'1PޏjSHV)pc+KK//Nj/ QԚ#Aon(9싦DZ us֗Uֹ rIғi2~4rA/s֠nɩs5 lfՈ 2_֞ҚZ7.eHaMH=I@ČR+ypga=I=JlF;gMY\ƫEUQE?Z3J1sG| (PsNځJX7ڝJCFMS(4Qޜ Ef;IzR8hqqM4Qڎ ()(E%zuǵ0j(G\Rg(H(4g#ϭi;W4߼tSH'=)z(fczQE#d>ڊ(Bbr~E0FMltUj(-Ţ)fQEZ1EQ֊(ssESRQE&8EqAE3NP:`P:hR@ <њ(hڝ( 0OQ@ QE-%Pڗ袀Q@hy"(endstream endobj 839 0 obj << /Filter /FlateDecode /Length 696 >> stream xڝTKo0 Wh"Y=E{Xaqe+˶}P߶{wg5*Eug~ثmȬ 3 u߱! O[5oMAitsCC1wga(pRlG+*2I<8)Jَ%\b|Q\p #`T Wpe|A KqF㩷t..QE0O dendstream endobj 840 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 805 >> stream x?O@/NUcJY,!EB,Y;1z`' pr!*dSZN <~~oy.i* 6҇ Æ1DD)4ApxxhRJEQ$ @b_JtΙwٷ R~h4PJy,wEQTV2ȩ(~sV6E"#W9̟ٲ,uͦm0ef1zFcU)l~C(#})(EDD4iyם!0D,Y(˟ֆȳs2F\7CGiOlH6҇ ÆaC!}ؐ>lH6҇ ÆaC!}ؐ>lH6҇ ÆaC!}ؐ>lH6҇ ÆɯVO?v7666vwwV^ZJ"X^^<4~_ק)eR)YR*0p0XЈ=i& 2 e{{{Yo4Q)54t:8q+Z^g۶VƳ3۶ݮ8v{<'Iiv]7Z-ͯw"M|X]u4oO#:D.tan5ʮ14ߕl|3(z;;; 9nmm@E$Ǟ穿3s*䬥%=|[QpB8$I ƆaC!}ؐ>lH?H:lNendstream endobj 841 0 obj << /Filter /FlateDecode /Length1 1488 /Length2 6811 /Length3 0 /Length 7796 >> stream xڍwuT6]tI*!Q m !) HR"]JKHwK ;}x>}_w=u}?!Pe X8Pjf) 0XEP0.pR_5 nC8]Kee`,Q܆mwA-BB{bX\6BqyyY0 ܅b`qm!zVswwAPBw8pølB^D0r2Daݡ@m`H\+ 5uzhQ]_Pc4 G@z`EP/ Cݠp=<Q1@q; ƺ\_[*;hucBkp wb_Ƕ#m~b3F]aD\aX4 0_M<Ѱnh`[ ~(]n0 w8nXH0?l 0p%GBq'+lQH?-fnf/UUQo<(! KJdo>|CXw~'?tQ8^>Xl~UqE ~#_c8O ٮXJpZA/UQib8 q|KR.VqO]\@,0b8 82.K߾H/)JH ԓ% i1ťpP_W+4bLP2%b\21o?#ڸb085fn߯fC1eXTZ\$!EytYm PMdVĄJjy-*'3&Ӄ9 LvK>t7ζ\t\%V,I"m홾Vv?Rbu_Kݸt+@6ST)$%APJjCjh&ˁ8}ҋSlTh͛2״ F[Yc]S&λ<&^j0+gM/ѬDAX1P9[S(cwP\1qAc0Oo'fY-){`v!cFH!Y<0rİgoْzLǂI܂C|% f^[}3ǒixnakd% fAV1_D*DT+*kSp1HD+|ͯT ?Jٟ7-BmM?dݹ*>*}_Q5,Y_FAUqǫ3〘nx ϑo?oRV$, x>w׭Ae]\;X| 44Tw|camtS"p+d$ Z,{M pv0/,g0PIoeC),ijZ4>FUz5/J-M71Ҿ0}XeKDN&ݖWqQ[qbPT`OBҡ5VF f%u/{S1o'f)Q[WϗfԁM #bbr CN5)ry?NHKr[N/ж5qrzATb|?:QIlC&1"4rƵ8n2aL48G G v7hmTY¬h{-EdIg2QI*Ua@= ;Cw |~*,8|n1?حnwO.l4G1)}fY՜,xi%] ,w]T-޽n!Q7v}SC|9A}zҼm7A- kX55`S#W|sx1XT&߈ wɎ#Ӂ:It,=Sgxºg xDk!ܔbv. 䙩I xPu|=Qiko2z2KI,Jfho%;6zhB%ΡE[ظ&qzO6:3UũNKZO3bz)`?9:vv;/TD->>dzq $(#bV[nmAaUS4,'$X\Ӭ:3Ї/;<{'Dlhrd*C$|dd_NAu% 9/ i ͧٮi'$$ss[7v-xDf9_5ʲUX b"*4)v鈞o0ϔM1WSTiA|hlGj'1M?D}\^inuJ-ova YqaC-@4? 90 q qf3}d![iݗ2%: afb5W#/7ЩM<Ւ۵CK/#2&瞫7c^Nyr9tSܒani[/imL/s@u`'' oy7 q-[T/ݫ7C-fn%`ykS2v-dW  n!z{5@Ei{VyR:`j3PN:;JP}KPBR0 DCDž׺LIZJPP^@3~Zpmrq+P'THS'L=}+sO퀻XVq 'Sc2u f i/LӹeSWa߲/]j(Dy *Y/#Je><Ƈ-su_(߽,u0pbd*zT@ɹPMn;C  h ,)k'է$u݌}{^Cލ; . KFZ=dAK78kX^^l6cbv+ֵ%na)iYyWFRdRIc{=bK;w)3 s^LƆ]oR*g.억lǫv)ۦ΋p"N!jcxl|m`'%k25wSrwdJksMr-\ H*nF4ruPޗ&X<vlcV {%PBbmj=c b٘8cmM܏b"vl;G̎ԯa,>G4W,2LOMiYkY0\4?bngiu.~g)v wLtR \ug+wʶk{B h ?{ %]5ugY/8O08suf !>I PΰUdL ԧ&{tu=ם,Ek \Lù؄=!cT-٤POeTP3% \{@-<kP~WPgS8A>b,@= Z#Wg.>q̼qg-E>ܚN9CThϷvtyF217{z10 9==.򩦳`K-VbK6ݽI~!$P~=+]i>5u;pktw;hF=<*c1좣Vc\4 ^t=^-1q0k$&(a5kkKZ~5*}h5rUՎYGn%~gk< ~Tb ӏ|D?'J䓔lIcRUNFѹ;.^tO{?zO8i@Q=qȎ!Eg [ƵEo[gJQ#nJ ODüel%4tFg:,;Xp]244Z&L(H@ iW@oiywh4%-v5mL˸W(AiRM(N,ה֔Wo Mnlh1\}Ƌ-a{Ⴥr4K1gKmNGbX#X&:LJ)uku^T3+W[Hdfhc׾it݆fzLbH(f2Y?n3 65C)OR;V7V]n!0YߛFd$gv;+ dl<@E>U^o/ظT+cv_ᦝ]^E\GVS̡|>A"J"g1ig?ٜ)~`UۖP!Ueߙ$fU+Hz'ɸY}! ‡3E{ۚ,j]d {BZӼKGgQK֊} &gNP */ܙ{-JՓ 씚&UrqLͣ)$]%GC:mvMVidNTK\Ӹ • 85)OB/m.t$$DfjsǔQ $9&o17]lUk:2~/_TGc%+~4,-DfKШеMM e#S Z{DsI.eٻ|{)Y ѹה _,8 W#޻+Lge߽Wës^dzviqU|ѱ9vw}ۉc' <3K.AHޭKfՏ[>`Ghl~8J>LzI^Pm7nճv#\u))Yu)D]Oy '^v}hgܻk-՚ov/ *Մ1in#AgШDj4{zuUr-COޙXB}(כG-_赎TfԸYy/eyz}q^\\'%s()Wh2EyH~>9 n:B|32Zt^gm'|-C%Mf&-/r!7"_*̙<l<%H)[Ȁ+a8tT7%`׽Bm U|N 9zXtbwQ5cEc:SCSiz5cqY{I |vq"=׈u}^sk+5^L?B̛zM/;z.aǮygNK 7&ىo$}фu?FmGe'Nc J2KZ'ʕAq1@[mexycn1YiԖ1o.b{ö&O=s8ۖ5n\N DZfƻ[ǀ,> MG(pTӶpxn5`Y.3UGV~DX3P{YܾG2 f5IO1~;8x1fFih ##GNxNs7| BArLRW5 ?ȳs!񯮉;L%%y~ҤT;lÍgY*%z^7J:`j}˔9DhSGE<.'a >^*6"ZQi"7{Kr\(in(}DҊP;9lb.YĺhGtz(ؿow:䳏b]*th{+oWZg}&{cO 9:͉ ^roo > T|DdsVj(Ej0àzs(0I-<@W[ &< F5cZwԆSX>&uW]Y,,9nQ+U 3xN4ڔïZJH y1*Z2wZn"*mZ4X^v,\͙4@9:ߨJ{- ~yM! rN(_7+XotGTy&qU{ݪ6fS! U2m`&j@~5|n!{Sm17GE)59R10hI?g-@ "5*M_9i?bϺ)FkOBTI+g]q\&(`@9Gm<*J|^iE<{u ;zX=.!U咮}VcDd].% Kendstream endobj 842 0 obj << /Filter /FlateDecode /Length1 1414 /Length2 6355 /Length3 0 /Length 7308 >> stream xڍtT .! !9H! 9A 3 30P)tJ)!TD:D1wݻֽkzݽqCQ0+*!Th$$@(Ig"`d|V0T_{c/PH' !US@ߎ("@ ($̃O]e~B r7~a8.0ˊ0`aXTrbъb`w1YEu`0 ` vF&Fp{֛` p@!0e' . &ho?HI'ݟ蟉_`#}Hgaq0@]ƃpW`| <zy?!Ls9em$TCb=~ cY7$Gp#N?A@=H}OK?:g "3(S} B.AN?2? x `0g8jor8px= ?o􂢐W@Odb*l(OTJ *)#Pc5'> P rv ?#wc%a(\>$+FY_t<_f_ v#|8\2{yF@5%pOcסtFgp85c!.).#H)[vyo~`H $ed` C O@0/fŐ(e^ !Q98q?ĥ%(<_o`8lv ZqR-Zyo:CHoyFI*T9RO}CnU[PmߧȶoIv7ş9HE-6 v#l2˿)OiZHwݧﯘZ7ۨE~^1.g{/t1-ub(Uaگ8ã ڼ .$qR%~w%O.˫$d0s!{e"9)֝ B^-7(P:hsvwήZ~7?k;嵵*zB tmx@YSC7kRE2px)fgJ5֭"ʪl&;J_aYq^,_>T$! reēQ͊"mAT}g=#wlDJbTƈGtwrM w& ez(j&Cv ҾĒ~J+.)άMvVxtM;/M-WV U.jgޡ?pJ[$ *>yXއ]܉Jzo祝E0; < I#; egS q }0?)$e>|-UI`Ћ7dy_a[DG𾝱WQSl.un_9wgKq2D7)F\BJ/cx}7p Q1_X(n9v]ft\vG\$|v-ݴR'p/)vrf:=&_aT9zݘ>.gUf8n<†?yu1VܻU ~,i;}B?EXdWf Zc׹lEZ2OE>Bl5ǯ&;}vԟԍ٭5W8'*0fʈmSEBc)6ލ}u\WxPf Cs!kmCA 8^jJè`#AkɏFacy x /[* (4(Vc UO t2=bWZI_i[dRwvM w&"VeeZ_ ́W |Dz |.ii)"g˵{Y}4Oo9 [P4 VRʀfDv j?n-HV/hΏ!mXț]1SȞlHVA\V_deWTfY}kQ$h#gWĝ| -ᵪd vvwևM1}v1 J?򕛙@crWm"t%*~AS"YC\k,R#7+i"'|kstQQ /'1=; Q"pS=O;Վy wȎfw2,|z'Vmp˨RZDa6}wlD"Ԙg'=?rweFe6 w)l3WkAfzYykάv#*i.2E=(L3&$%,+4z,cs<80+ܫVw,vqVNSk *?eَMH2lo=RZ-ΉPBqP œ3f0]j th{WT%/`VrA&k5ݣ WHUmt| >Ma̽ӏBKr<uZ:bYz(;@ Ծ31E)06'yא!1[Fvquk#2PiˇkAξ߮Pa8)(tYVF4\~_60r̿඗tLA1u~%P)j{"3MI1TH+[@g˪[7mqcxnMFM(-Z~?zw[8LL@=kpZ[rw R6%U']/csu H^5 ^a̸*RPW9drg\RjnWZ}@kecVN&u霄'j!X\0r|d}MQ%k̃FMY F AgQ(RϏPJ Q׺8#qF]vdB,>ޙ>uk^I}Vv4'h M\jn̔tJPH9'nǘg[3YMU_\\+mOl ! .2#$_&N6ElնZ]z0[ڻC-lţJaʶ$J| սGWuح\ѷΈQ]x4p'$&.#:jV$r #Gd, 06]C|7%$ +e:WY%/;v5G*O>#"b2}eQ$}bnQ;xsCZZ>>7yuA|U T%,f+k\mI(1y"4|x,= dAG Gz/3Տ>U6 ;g/np!=򭛰Z]dNSx[i7.\{77 ARBR3g΃T4ۖl#-CT;TW 86薚ZF'c꾵PŚ@n(36"]"p[ȡBothyWtݭQr9^+bL5k}*,zl S8ɝonXfHqą{!ZmO>k`Рlu)Ux1u%zp:ddLՒ3<XņLAa8W;MUVW3_T̲uIB.g'9G"&쩆'FTj(ϲnX7Zv^* a |SJɌxzW Q$DIX>Gh8|=! 4H 9? .:?1s^D0syE6QzvdTo(EHf2_LJ_ ƙK}=^U+LG+ʅk >n8\\)ٔbfXY/WW~qAd}:w=Wq{C[{Oc =*_+bmd'a6'>#9ۂ ۝kQ}ǞDLj<tD+f3 _znve5$7{rhͧE%#,Ѓ" ٛHL V2Q9%`ZWNn$ hU^N兯4r4Eُ6׭^[("9}=T;MeqFוv[ͭA[fPXl[Xpƪu#6`kGqĨ}6+%w;fa;ͯEŶ7 )OЬH[y-8DcB4yLFC3 W^KmN|75:IJ-WSߔ0:u~t|Yq'꘽ vf}Ц=&> l< su[9%`ϮG æOy|f6Ҝ68']{b*8qO(蹅iJ)i¿ow(rMb > 5t-4G_Ud܍͸'\ES:93n W77^4.kN~vVҔ+7|gZ2RQjciН;żMձeQ72^#QmK\٭Y__,PAۂ&|5k #T}Ļ6D-xIܒ$ճTC6Y@cN4[iB'ή )HG SRjx n3IJUuC=F 6wAR+g"ơO{Ȓj&*x=q8Dc 3Cl?[TdZ9cP!nyVưHF헻Z:>u8M~;]R*_~2ȒByi\+`ymĎa_90Fn5$ %]TH߱y(g9yFhRCc6ٻSx y|aU4٭T|Q{{Ӂo Cł3E:cپq^*.4^,A2{: 2m84ɦ&Fqff}5M9֍l~I37Ͱ?VsVYqlMh&5p6: ~+\INܠ1EVvX<{VpU7J*d8ogl 16} Tzr VOzi Si]r5CLpehw:>WN t˟,XsB$ 8fR-Y$ߠVQ : e6 w n$/0dR+jlN@edHrAuv}oר5GJǩ-Nac?$8M<9vcK5 F~=Mg?Ks%u Mgd`;@UyM!mʟA#}"Gv,ڧP.7RA_́NU>Sfx絺3<=E d^|cwO]r+(Lr_l',U5F-};û M-?|վ| Y0uv_ fԣJKl>,Lwm7Uw6Y0T $Df?_2Vcn¸ ) f!cg W&>[MRȼ :鮏Q^kcP73B@U# q ,OiBԧWSYYe %󡫱e W$"tU|HZG+t(Dojm=k6AhLY@ǧmƛ_rRnK/ *[endstream endobj 843 0 obj << /Filter /FlateDecode /Length1 1635 /Length2 7040 /Length3 0 /Length 7867 >> stream xڭTu\ZUJCeeXJ %Q.׽wyf}}Yxdm`E8 #`k$gΞ<` <@",,r` '# @  $$$YrpGOg=/?L 09Q  [ 6QT+i0ڮPa.`-0\xd]@#yH{!n# 윁0  u!GgC@ wA!CUmyſDk@`!r=E!0] 8B!pu7lt]\hο過P??QpCmyj 0l۸:s;9 ;zl|pCIMe#Gw%S+B@$?:C@@+ zGj/t qQxm!=}8?~  sI!Wa6oA?>7OXU@{:]HnO7pGP$|M?D5g_߿,(@pˣlퟎ0A?Ol>aLHCP˛t 8W;RW%YV֏>kuʹ1EeL0qt-qmYEyMn Zߢӎ 9c]p32t%k#G")cMܾ@_ Z:5Wv,S o.[Yڍ?SfSmٮG{\d3WDR-n^cquH0Jg8ǩ8v~DILݱќ/!~v(`11I<6 sQtI8QNvkvνf^ 0lYF3Fեqi={ףW8^$-0QS'LU\iu)99=ªpItyoaP;kT68s8Ǡe˦ǦqWOƖx;=.Ɨ*ODgb?i&rZk)"(Kvٲ5aXcg4 i=uIu0qP%M#Xf,xADw4ezO^'60d'. zA3EUAqF+׶n"*)R"9 R.0 ͣĭf-/=?Kx-/t^䚻^={MBӷlA ?} ?ϋʏt5޺_v 2R\;ݫq̩Glzg48,lQn f"6P禼yqBhBn)_p͐L'9%C)ea$"̞dx޴ VoUxRqAKDh> A݊7ҟbq1vtryNRaбpfr]Ⳟ +!j'R gw)N1BXo">n{dnF_cSk%jxS)OoʨQ_̎{S)%(p:ݺ >}acOB_xkmh)ս W ?~'[1tCAu !C"D|5咕rlY_Sx7I | #X#:ĸ[i+33Nt'B[mI}S-{fl o!Cj:RxP[J׮ETf{n_0Q+P?0J/QOhi oȊ  qY1v8 MOaT۾V㓻?o'OcKզAILC=?pN=j_KQ ؞$7g|`b:VhqχdӌrrOj㪃av*.{V8ԽHqR/D^L"Ҭᥗ;3E^16/n`QwaYuD}y'GʋK&rbZ&>gҜMSs`뷚O(^$^i,/oMuFdw莝EK,zOXycJfuhJei=3`_f6LHDhVsqgғBkڇ|+7&\5af4l<2^nJ0i"ٲ^8*fasx2z-Y-T,_,uZXØc%a3x  !1L߮ʩPz:S-|{^\X:4xqY=Ԑ&OzAԱΝYdx3# w]H^o Q}1+RN1<`D^amB4#:7;ەCpH]ڞaVON–;"Ƭt92b&:$#%:KXWBOY6yPX׈x> ޮg<5\A@$76.ɝl1Kq;w֙Gv>8OC }'8%8 н݅"=\:H9 N=yt?6FDpի)Vq^h4zAjZ<fOe 4cSgVh2k}rcfc.V퐘Fnb^e(y2:9vp~8#Ţa:!m=d)5H;obl-x| +g>"jv7$Rn~ivO#ZdanMpl2_k^<h#-Wh_ ]EBH==?0d#$>IL$%U6bADzs=sIHiIBmAhf>ǔp'\ Nf?r IPm|j@묱n\沈;`(I;Ŧv-lbg;kh yYU~2ٰ NVNjyey~G .ep`V,4h 3c[wgf. z#;h7{W!f1|z;->W9D<8~@m 501gJvp[^vWillELZPvPa&;(EnL\?09oB-'mHWlN,1l;%eWby}Dbӑa*Uj^AO[ƿ2PK&/3fK /&890P_c,Z%f!FK|v]Y~ѠԂ@znl"G`;]PK>;U{OzJGW#>quز "n ߐѱlMø@nSf7H@-ͶG>eQ {EjR _XnWV.; >&탹hwKoϐkG|\(?[Y2:JY&+ctw7mh{Y bs$H_ T_=j܉̴8GZ]#K-ϰG tK s8F\fR1΃O /U:(AܣRE&QYN|Y됛G fof%Tc|3c7ݽZPsSy32Kqt偱*KݵbW\q%$[(MvIe pXa\vBY/0+ZT.'?)SȜJ }{![fV;x#Ny;_ǥ|YDm{nIԻ+EGѫ>5 a@~F)"e3>VEJa=T=7#\tdb{0T?l蘼`m}t#Mzǝ~H1 H=O|#tKl(["s̸wM#b9֩>rgKOy2u#!Hx֮TDdt`7v\OTC4[rMދK &"$PTh (c.7^ay#"ў S6x52.!qK6G+J*$ǭ}U#'eĴRT[LfE] l W}%O3njCk mم9z(~r{s#9b1AO9r(Ocu?䮡N=-;gOdD`;6_)P;ߣsU}Yjdb23'c2^Y6k:.}De<Tlwy֡E!CW<$teRFv.47igO:-7*^a΋AHa $Ga2|؁2 #J ]lPHG4X] VSfHJn?K$* I#ކ6+oGmx]1@xtoUEFۣs[E᝽.Pݣڏr}Lpg.IB7Q Z: }(2Tx|8(xuLr[c%tBH|ڰ+ADez$I:m,4c׍f"'e'B@k 読MmŐɈm-U}M=[4YP2X>1'µ siW,qr*ƂR>ڕe]:>] 'SϣJm25`t s FTg2‡@b?RNM3 ER_?|]Q]:y0猠݋r)e `rn#S =f5JoPOa3>`&֊&ޯhNvle>\|(N'aoiG%(9|<N?{e|,7#뙣x{e\ɛ"{ohMީ W)+{\7sCBk9j[«dྦྷN6 jq ~o9U_/``H0!O_~޴c&2mzɍ3VH15a!g#D3qG ںeaOE7&jjRGbuZZ;&R8 !n?t"9A@wl4'Ue:W_|"7wkm fFm/l-yf 9VH8v'f"^RtI J:endstream endobj 844 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-Arthritis.pdf) /PTEX.InfoDict 196 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 199 0 R >> /ExtGState << >> /Font << /F2 197 0 R /F3 198 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 729 >> stream xVKO@W19dٙ}R/*6!)4}86`1izgy|kc@ŷw>_rSHɁèrYhw (0'!= a]uP*5F˪]%,Yv-tǮvBd*)mB-|1YS>$OB>G!XewOlB6Bv4em)v;NN38 W1?7E@pқNBiqX>0c\ FCuS|[R3 `ue 82%a>(.'#옇@(P5o4X&>OA#HDjV";_yݕHJuG"wV"d%i$DŽ43xKN)9┞`$zZ/:~ky2WIXuyu?o>RP:yt;ywh6e.=x]JAP9 e`gD{>YUh^=g'z?{T|%B)@c Tc_Nr[sDq J&fC"i9Ǒ֭e ݢ^=n݌Atn`_k&[顾"C0*K\Hgecե̼-#xNe dƑM9W mxdD0?fZ"*q &NWˡ&^)H[xĐ{GOxendstream endobj 845 0 obj << /BBox [ 0 0 720 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-UCBAdmissions.pdf) /PTEX.InfoDict 201 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 204 0 R >> /ExtGState << >> /Font << /F2 202 0 R /F3 203 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1304 >> stream x͙Mo8<sI=4iS @h["qQؿ3Iֲ HyXZ\ -Ŀ݇tݹy蔌ʈ[z|qMRbz~(>}JvZ\ui wJUJ8;f^rEh#Z9"Ml b݋7ş+ޮk˽0P:w ot$G^10 $ܾﮧk;^gdytDXy64łn~QzMdjڡ4%(/sҒ;\f DִJyq;'nOww]%F29_'s {l!O1L &j0cw4ڰ^" l|mn7-,գ|3?Iz^pTǜ~ MƧW8lX_ek3+scf#>o!{FQ!d6dZjoe/tH퓒= 7` DGscb"\9Z\ǵ %>l)>V>lYź< 8vz&Az"TI^ҴT;Mh/Qҵ8br*ծfGʻ WmB~&WsݶIq a7ȥg.{ ? Y>/]k?΂ı`2ZV?*5QL)p$BS:H ZGu>ϵF=CGxKv(sMS?q|ګpyK#y"MNqZėjq!'p\rZ|]#bU״jqhų ,ZXw|u]敫M=N PY(W q6@! "q7֋WϾsLH&9&S f.? ~k_hlljBECF) ~NsC26W K.`$oSzZ\ #?кsBp-^jGK-p=!ǭ03T e&C138V N|u:D؂ o?$}_5%3F?<~?~H%endstream endobj 846 0 obj << /Filter /FlateDecode /Length 394 >> stream xڝO0=?xۦM<d> /Filter /FlateDecode /Height 106 /Width 75 /Length 2187 >> stream x\]L[?b-Ź`u 5JDW fzD7MEj1&\bYf7# >/ux+׏&P5q-;Wɮ=--md'v:l@?9?@N8 9 3YGVa#BSn٨`iD&!===ȚbYΫ61 [[ndf>6B:aJ^^ɓ'Z:`Mf t:~?Bh6w-ɚE@$DS_~pdP-VEߞfM&>Oӑ$JDk?{UfSCye<|q|hhzk|#ͷ\OnooߺufKz4_Zm#S~Cu @o*\]YB!0EWҞ Ν{<;B&7GN~,GS#} _Ԅ qb)ۿ<&lM&jQ Tɜo͛7񬓓Df&LeY#={D9rEQ)DPȳ*/~ϊe2X-_~ёhBrsCbQh4 A<RVgՆ(~sj3 K4=^6ɤ['GM/EQA@S)BWKU`CS . v 5B+Ȉ(,,Lѕ8 f)< ]^[LLLLNN>|8y?{*|df> 3ŇEI$J$ !ims4j!A4-AoF(RĜ d40H1==_ϗl E]v#CbrҥKQ_,,,٬w?{^payަ(koo/w4Ν۵kWLBAAALӳgώ9ӧǎK }&ԩS1M&S8.--miia[% :xUee%X߿|gϞeh$<8㷵22?~͛nYI4 i0HX,;wt:D]ÉKgL_0]]],6P Z6 Xϟ?B},jAD]/º:7-[~tvlWYEfgg].Ǐ#@7551 Q6ɓ'r|``18@"/ERiڄC3_v n u$*,Ba[zXkqZKV5$IR5>>id ÊLz)`[L 5%|j4>LLL\HZ7TQa&QG9qH;\7xŇQ(eqq1???&kff&&rؔQ'VxxSNNN8YT*UEOLh*jX޾}{QpgB˗/sgX(Bb) '1ByTXz,58jƴdwޕGm{ѣGDO@CCT*]]]z/^@xҾW&xe jKKKǏRc +|>|0YX ~b2 O>EYjm߿_WWŲZQ<O3g:t(0hAPqgYQQ|GRaI&&T*i|SDl ` +| z$6~&)?9~R\k 0=9~C`|y{i ,˖-[4 a555(D")//G& AAWml6[UUUYY`nn"VgGVa#0U*|df> 31Lendstream endobj 848 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 849 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 850 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-PreSex.pdf) /PTEX.InfoDict 208 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 211 0 R >> /ExtGState << >> /Font << /F2 209 0 R /F3 210 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 916 >> stream xWKO1ﯘR/PjHU8Ddh7wf%H։|g>\}?98yƙ83Z蓮֖i1gAp=Hfo֖xΔKK|`R5iT؀HÈ,Ș5aӤ4y޴Hӵ2)ieR5zsZή3/L%>pȊWl~Urm߃, @j m=8Ŵ.?d}2'E֭aU9 f:D r/ J+xkMK1|V[O)ZV3R6#jFg Rf>͠!6gH3LY"&!/|6B'[*0_q0zE3ѣݿ{D%rκ5a$F43Np9@5KBYԦuv K&yŝ̈v( 6۠Ae2AoHY\6HH,)2ۡ@UɐQ^1DC~(TNՆ"ڑ$_BlE%vU$$tT @BSax`FB߰E@5+xӡYxMH`8@mITFxt|~yKťvV$"h[ DE1 +> /ExtGState << >> /Font << /F1 214 0 R /F2 215 0 R /F3 216 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1559 >> stream xZMo9 W[cl hXAEmYm"eϸN2^6H>(kq#xL~?zKqu;QR)%۫iP~ & M]'2(.[^k Hfc%44)z~sbŅ=Yk0tIϏGy|5;tʈx:فw>X+ݚpRY='#8D!Ie$,$!7k{ΟDd=9Q=IW kE70I9'\Bk2`֟~9tH=`Y21H`MJ ‚S#>~&TVo@{.Hc`eȸ/*%( :Kp)/L:zioM'LFT"쀬tMy6F)(=fSN'lS.kY ZFGܵqP\M< ii7gZџq]V+cPvKxS0‡#yP3d:F <x|#ob4rl2sp^Hu=O~[5$henGՕAC7{yMCC50,>j"I%UAFxcJ6%RytRHiDڌˤhw<#̣ L  f\%Uz*Kҩ05DqYb;-lE{QV^&͈/ͥu#M<Ϻ+Bӏh"IL sgu ݧӘDpqtZ'tb0IjSu2gRmuR:}04gy6^$e镃wO]]9J6ɮƳC! n؞X;%7kgFrb72+RV^d櫍>_mTf_eOM@4&IY~јWi&Qh}M;^n;U5;af3 ۣXfPGd5 {u=\"8GQwӫTi^Rh k(iAlvͪ܄8,Yw(U+wҍUŤf$uY5jYn2 לpp^e G ZfݕINAj*nt2*sC#]AO$hS.!FUeYh~_ޏo?&?Xendstream endobj 852 0 obj << /Filter /FlateDecode /Length 383 >> stream xڝKO0 >fqM!&! q(::||,CjBUbuO9́mr]%YnLbFfj 8ôӴYT/\J2}NcILu)mD~e¤F/$> /Filter /FlateDecode /Height 106 /Width 75 /Length 1835 >> stream xOLYBRxEĨK(ɖh=ImOpM&hb}oFW\aǏjvhQ| 8H1442pX~wwիW=H/_,C >} +++feKwl̙3kdz(Wa,;w  mz@0??XVVVl6K"p_N6Pe)t *&ϓぁhjj"~?dsSxXQQ!znÇJ=d)b$)XtuNJv, 馦T;K_|IQHx%]]]`iieYEnl4M4-yiT 8fK*SA)ؚ,YzؐE'G^/˲Ż]aoLMMݺu+uQZ!l.9coܸPVVD4=~x/5b0r\Jczx~KKK 89KKX[p?i(eF[,rJ4˲c0Y\",:1(r0$Y>T?B)T?{_Evf)//?xj__ZǑ}0`)y!DQT(***䢤b]]v{晭hP^x1<< ͛7z>-.. -|>ׯO>M ONNfݻwiQjXx7rI۷wUMB2VQ"EQʶI [$B)T?ly/_HJr XRR,ˊ]uԄ %,P(][[t,W}h2l|̃b<#+OI~ϗIm>ݑl=K8~&KdKN|' t~)Ç?6L, o#].h$q[њɤ Dd2YVn$6ڡ2[D>0L0>(l6cIm d2s7== Hs}~~~vv d29>>Q B`PZo=z433qlFފ/,,qh6w(wn8v86رc|j}}!cfx]nRL<|NB!a+++Uꩩ*ia dB(=zT ]G݇GS~4GS~4GS~4GS~,Wendstream endobj 854 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 855 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 856 0 obj << /Filter /FlateDecode /Length 3289 >> stream xZ[~_1KmtH$%JA[ yKBcc7ەf+EL6H"ؘCR|B77͗>}離)ɛv{S7Yc˛jۿxRQzkМݲXt˕v4_[ÿwzQxݢopSqW5hlU{pgp!ׁ?moн 큿reEh zC\}x+JGDB6?lrڧ|lSެL ]L?h־V#xz;iE'B(R Һ}Wd)~ bl'!B7{YVH4=@k.(=|?> y'$[Ѹ3%+<  j5y?TUڵ=xDȬ;NEgIDI;PK p],E]Y/)?5UB~_~5QND&B<rU5@Vi}'̂Gq/_|O+ ?s~ݻ P`[)$}n5J>SDfLt" [¹AWp-{UjP#4qeY NO>&cy`?Yr%(1o=s/EK@4-M[e A؀I/)={i͋L#aj (Ƣ+l;XDO>k0Qޢ^6 x0$+Of.~HgE0tRf҆mM֊'y27a2gemb7X\m[dcIL ʊEyRyV5fTcݽ'1G9tA&BA e5:Gwj%{g{":X0fMW?&J&9HmrQ'* BHM O&y 1RsMl|r\ åF(+Ӹ6eOm_5#"926'qK?e>'2aqQlH{=>s~Tjg*? ̓TN41 ptU(/&hX3PDM5/[;u/QZ)W>E9t])w9-ho8uYOhedCMA8q ٠CqЄj< Il(OmA8GmFr *v,h)`:7Kzn)s ]QKWylz^ #YIZ  ΨͣOs2ӄpY-,/ܙ̔eIX^rC%_&6C\v-lq&>F'$w\#?|1AQ-TPPs?&y ^i:== AzJm b ,o&:27os2#BP}dY2ҾI / ̚1Nn0xD'CJdܕoe|%Y=4Ęc#1WwȑrPKj-^kA[_#ͬ1EH_W+Z!? ~N" W(z;*Q~F&|z_(bLZh^Z-OB3V:W_n::"auVb}7,O oIq3hCr7![jA5mVGا^X):tI׍2I$ zБWTt ˧4IdEtv]ois%+AQmkloЄYTiU#Ҳ\IH4 0@9B^NE4m?_QKvk!2CºBnSH g-),ï^2ya -B_*IpOc#Dr4e`j'AP5Lbpk46ɢGOeijN3\PG[}S 7`w)18MkyrMAYUґR!=3j\ l3jb<#,]+Vk&_D{T tAhHAqBtNIgȰSڵ{% gbvKH*?ִJrћ+a 0Ѫ3!z8wF&q\-~w#!%$)4tHlmgk&`(k2{.!KU^fzʚpsr饉4wMwePN^7ٸp.I<2_y%Cojr+/Od0HmM7<Nj3IP\f[$ytJ.pG_ ޕq[M$bɛrrR2. T![)F K 9VL&pVEpj)+ ۣcendstream endobj 857 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2838 >> stream x\oy(2:+6/P "z"U\ $N[* KNUWvB^(RT}Rw3-)m9T^淛v\O`2peXї/1.//e'D, RRϟR$uƨM)%87g/m)% %(JBAc&nyf=rLLLNϞNDu:4alNei o}@rRJ)-na2їē'ObٶdRV èjNOO;۷o^P/۶<"  !R}%EQ !Htht8\nhJ}'ǶCK{/ex c6Y!SK>6z.>%")e>/Jo߆i듓Ab J RqÃ;G]-tL4\* h40 ZfYD?0hwwlrBR)0H pwp?x/gʮiau3..yxq$~A`7|MӌD;uU31"M' *F0r|#GraIbq&TZEsss}t> cpHIQ[+&j(BڠbfBF#X]h6f-x?Ac۶;GM\&":y6@"mDJSSS7n۶ilֲ,0W:OMԞl~&#i~(m<.=i_cboqApEѴ]+nCB?5:;F7_FX:$EfC0o޼Y\\^je\Jω^`pB9K'z+3K)۶AJ)m[ 6g HD\fT*DWLLLl6 @ 4MB9թvw9FqhX,.,,0}_y 5ៜߔRW\A<`CgggaQŋi2 H4(@h|R NۍRﻮN#T*X\ rU)Uն@677d2$"]׻.t¥?QJ麞Ja888wv4vj޽kY֝;wv2<֭[B˲A[}^.޽ poooff {A]N&Z۷oTϸ˗/5Mt3UP RpN.b4݄Or8I:ƚDa?χFfP(Q}(=%6qWTPaqLZ)P> dó)$?[T bRgϞ=x@)u…GEB?r-!=rZ^x|>™(4myD1 9WIBZ=ްC n3LTv횮Riff_1m IqRaH;k`n޼.7RD""Z!XW1 :k\T˧{xy?tVV^P;@1ih)x[qR)!D> Ϟ}9OZ -^zB:K_=O޽{WqnVU,U4 P_DUi4== 6$7p7Ccp)6aBmb1_֊zÇGDęcNǂ$70ruށTӧOc,}*CPx+rF86J]bh۶G˝C!?|vx ll9zFz2Xї/c G_5}/ff?endstream endobj 858 0 obj << /Filter /FlateDecode /Length 2482 >> stream xڵ\r+fAf{'I+$%Vi'E4 64 Pz`͏7}B4A}q`4U%Z_ {Bx'yYWoVCSxuŢۏ}@lt^S O_Y67$ U58u իnhg\Un~9;P@Y;_$ƞ=ǩ\^UQt_Fa"r"yI+ xt6UwԔ^)1+t[#zq9LGs6b0R}1 LܸBΊe<;MOfiFTJR۾AEt 9PWGKtW`+~{< ngUeR .l vófXJp|! cw5wiWifo[lts ?9L9jnt7֠G#>9} =Ft@좤|}gtT]ey ish=5`q*0bIPktXWnUXX{E>wpFhZ}ʃ\*UCv'\h2@8 eA)FX٭N vն[&6yXjqJd:8bc̿=?VWujowRvV5CE4T !&ۊB pl&ۈD RN =z^rSdDu6S3GB KܬdL!q<|Ǽ1:zua. P\b5^eXBQG{lmw3{#97̾k y{3t/KLlk""b)_6@Q| l8ҒmH E/=qz̮N^;^%Y'LU+T$St!k,؊ϩvf`uJ^Oczh_ыRzVٍKNA0ScqS&dag ]I|Z76ov FH JP!FDDitl}?Oy:8.s5E:cMD(g ` ˧Ϧ= tsb},M$,h"i԰򵡔%)mjT&dmQ ip8 ,dўU@mp,krVu=+5 ~sYӯ^}FĮ@RGhhmDt PѣϮe" hf<KsM?hr;g.:ߛ;oI?-2ͳCG/#W-&!#{:pT5|@/>Լ0o>C_W>1Q>$Kqo|xi]}ZWRׯC9{Į*'Eʍbe|c;/--s]@ёÙ~~[ e{>+L8wk`4^$HvXݨdb `iق7 6y@>t]jZٷzM=wa#L V:PQZb1l#㌈Qlz89jr7& /ξ]K ?x~s(MM+T3yA6ުrlc:_,~0niߴy~6H&{ް+rFgk[/į:<~8v'dOMendstream endobj 859 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2762 >> stream x[k]>oRjm môHm QA+R\7;w kvb)ba R(&`K-zgdLH"̜qs9ϽOR: 4>%l}jKԖY*D(io5MȏFv=\4=Y[S[֧Om [>%l}%ׯ'''Md2ieڒVX,FIEQ=z(ʅ fff3h&I1$IbdM) r5MG$4o )ŋӂ |ŋ?$ippPu}""X(NJLD+:ն$I,Jh6vvv p 4d2PHQ "bUJit ò,!'rK$###DtV m]ÇN_&qD)P&E! {+uȴ^8&"n3?! mtxrrR(iH[4Mqm eYc&i6h߉W/#X},hzҥ>tuu_*VWW2EX~?"hfKDY}508\.sFT""[[iX152C(sss >6;;ۙI0Ohu]$Hd( ¶,˒$ `0 g[}ڵ[L[rDzҭ-nmm y\.wygY"*Jkkk:Xi$bJD"Q.1VW۴k Y04UjDzlUREQ4M S^z||'HEyRFn.V3 P$"k ejuxx yDuTev8RS}&8M `iJ5(Ja 1%tF"Ѓhvqq65p4U @14$/9܊u/BJ&'uO<Εω~___QGO>ŵݻŐ$)Nf2I޼ys [FCP>?88K$tZݧR1kotyLL'Nhmeƺ{?[GuB&5|X,peeeddwRUz6 X1⥥%\K@iHxVmaE"rOOJ032c_uQ8 |1tڵG[C+5jj0`!4s`DѕHp(Ê/__/Ձb8-Ԫ:l@ma]i^zǪ9vΣ45\Y+ ߸DR͐ޞzNEQ KKK,NޏQkppu:!癊qU䭰*6c "bDQ\YYRT*\* bJe(DzUUUU{}}}pp=HR@@@ '"0 Imѐ*^P[oZ* B<MR=hwH޽pvE0V$Ie|;t!h4:11 "80`א=A]J^m1w~hr^WO6 8CcIq@u1(<y{VFqִ]C4F+]YYY__zq~N^!>jFmQVҜ1E<4IP"r@1PdBZC+ :l̙(Q$_d28^"ICD!KHRsVHEQ󪪆ae |1( (;wQ"Nve\cpKղ tZg8AM-ɤӾd2)+63?~I2̓?kCz&btaiW\!"Ύ] 3009sssܹs===dX,m.T*x^d2L&oݺrl潖.MbԪd]cٟ%K'ǣiZ"%X,˓X X 2t:9oY~4kvZS $^.7^V&߿߼ypRIi]mS.//[7I:6' DD'omQ(ׯJp&WWW^o6MRֆ5MÁX,zc8C(Rh^oV֖-aS[֧Om [>%l}jKԖ-a ]^endstream endobj 860 0 obj << /BBox [ 0 0 794 595 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./struc.pdf) /PTEX.InfoDict 236 0 R /PTEX.PageNumber 1 /Resources << /Font << /F1 237 0 R /F2 238 0 R >> /ProcSet [ /PDF ] >> /Subtype /Form /Type /XObject /Length 1891 >> stream xZn7 ?l99Hrv$ ?;A /=CɥZIP "ݬ.6əˋ Ya!jU_ȿvy!"LN//Y,6Hh ƶNيȽŝpX470/kj4~r-.eQCx4 |6RIᢾaBZ[F$'%8+[~U[uR[K@L]tcҡú7Ӵ6VgwBu(HqkWiK1uґF[K@o$T'j2kHA6ĢĐNWd#@c6ZJl`)cVٸF0@еXh>NuA?Q`~E[JJ) -b-[yy ƕҀ~L~iiuuPiIn00-ݨJ.jS~#S(^" YQm"PSvg[*C3*Ne ~*=zKek08-RzY cAm3yAF3s),>7l^Z")h&n ٣LIkkFr^Z3%E%vmk(;,*XK憣Ξn?ⅅ3LӷҜ9E#:{h5lg!䰩\j鷣mN1,#QFvhMBp[cl嚢((.)oW좵ۀٷXw";!B%x5*Z-tM^?푉׫[wHδe!]=Wix09Es{kp5 R.l'DodP"!YFh-UdYrB;qڣaJSvR(AT^ -,na&Qr!t  \\UӸDtPt-3ݘslHAVsF@{Tf!.Sڳ 埝'n5n']y<,i|-xѰ&ؒl9ǩs5K( gsņaqRR$+ܕ< zֺ'-]{=`_Cby3?a:H}22Ԉ+cMBܘ0>5 Q 1DN!S=A”Duibj/VZT_f~5@Mx#CkƸF+sG/h<,p @4^SL2:QI'4#w}Ǘ v35 O kڻq:2H/k:o^a{ͣQ'}nLQ˟+?YgX< ݨy:,Ҩ1);mG@cEI7%.`4ڨUҏyB3|SWS܉1mZ@X#d~TƔJ_&endstream endobj 861 0 obj << /Filter /FlateDecode /Length 1490 >> stream xڭWKoFWH%wInJ\jH+E$*>w^bh9ܝ4Dinf1+4UbU**MDU!-~I:K 2gyb7yy_{Kw9nϧzӬ/x${^/& 4RLZJ m~u&Z\ːMRnEk3|2g#H 袌6Kbl9=&to48?L꘳Y3N1;?s;OTq2ռ*̌MPpgeق[[ūdtL<exU ~hIQX.syR.i*})n.:v_p7)7 9&?ܔMcQ{ҝ,-ErZczʗ4/EBzʤI,(LD'$;dwH>Nڿ.xؠ΃w"wiFo:T`Kަ#JjNej59>b H$l6*ppNl+A15)<~oyIa*b"oScL fRo溓{O&tIxy%'zz O3Å:v)vi(H7Lk Q#0wWKTщ %.ˤ2wfꈍJt^yqN70)zH+ƑDzRs#ⲛd\.YfsѠElߙ'ڊ(wL¸_y _rJv؉;oͩ לHvT {8'D}7>q\cJh»Y;8vn-,a3U/j@t41Ikk a۲j&Kg8f(xv<;zl tZF4}g uvqfwbv6;hlpfL^r鮤f:;b,(Ĩw_vߑy;"څ[y52~ôS&z#, ;vt9&cRNj ֧'/ά SӔ5z*%B8WD[|zu[d^@Ou;Lg"}ku!XE0D9]eS#>t205I~_na''Ws_h۰Ho<0|V@)Њ[ Ffy>d 31RPZ?`׆Z%Y|%#܊k_ox5H_lK ,oGj/9Cy#X:N6ﱀ}+εhF `ή㾃zfMV5.sp%i^AKLy=|>2endstream endobj 862 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2638 >> stream x\[LcŁb& Nk u"JFlD} TUmVQ+U6yX) 647M*̮Ng aqL~8S3g?3X^^} ^o`Ǒ0000BAY @ @)8D)%\t G)k=娍Rqnq)}>,tOh&P"{;5v(|`d2UUU}\vWZ?ބ{>Ef Bt: !^8\BB i)oѣGZd 8p&#d~N|=23 9Nlk%J?.18T >hVYBP95㙂,%G|p 1$6 y=$8N0Q1l/b}lw>%{/_^XXv=b1X,EJ266}}}%cvĩS'Ji豏]烛=_;??lǏ7 ɲD0uVCCCooo{{۷ggg+++_mXz{{ \.66ɐG}qzfß`~.\j tvvfBz]]]xץMddj*g |>V3gΔt'WuGEs3osA<44<Jc t#5%C7*8m3PH$yzznhɿgVo*{^R! m)K(s ^d}u|ϱ|3LV2YbW pBEKcv<Vi1)STT4ٵL,)@Kxo|O%+a@Mm#A@JJJJj Pk`e/sf)؆Ѧ^[?p&i mxx JbnIzE2J(dRm'O4P__ڵ  ]_}H_o>900vCL&̊h4A eLG1KÀ&gK 6,6zqzj YbAphhpX,&ᖷ'~sh4B(HB!0E8N(H)>lB"W:ef޴=󇪚ЯV4>? 0)..nooz͒$9NJK5T] Uc}~1M"oiry s['mqJ C;tBo=l"%mbSHVҋ/ @)AŴNAv <[4 bZ=Tɂ n[4aBurԯ|e EQuZŔg[BOa`,c^$<n[EIXjG-0Ǚ:h44H`0PJb.l{I \n@6å%pWPPv wqjyjjq&Rv !uuuO~`065}]+ɲ,2!tb'W/wZYM4x3L=~55qqelbjC%X=.a_,:S@<=㡚K;W2P j='1<51zÇ\.ɤNCݹsp,bzDmLWTL|#!؅<E H$B)(*f4qrI!Cy|GQJҒy^$u:>H$A$#,;-Zq^7eYF (p l( >f U@2h2<> /ExtGState << >> /Font << /F2 249 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 436 >> stream xMO@+j= &Jo> Bhƿ~UD-m3;Ka n!f`Blf|lx-> stream xڭYsܶ_KyS  @f&q+Ex;J}(;CwO<٩5I`XLg?}y"hUd7YQ2ږ!d=5dȷ){#62z:D|r ^72Dש_mns떆VV u-R*S hWt6$WS/._a/.F'xyZ9_ E S~Vħƪ,}A ߳gRUU0.P˂? ` /3f86F=3%E+$Άӎ.~ 4: mF#VO緺P2/2Aj $uUNk0 YNo_[#^VxٛQȖ픃ٖ)s.8qgLPvpM7r/n,JNYk jḘrEafU<F&Ɣb g/H_ O6L9Q K {q#OW)bwZLラu}n3VlZ`Je.9 9ΠmxkICkdby@"0)=b&c_@D;YÄӐX%ǻUQmo'1,(dl 1Bc_%eft{:o"07mq f8augT.l ? `ږ/ݕ5߲K }ȥ;qtA~%Lqvs:C̥AU'!HȠ.tR&(m+7t__֘wA&\'O3}|>X\; t,`uSB5'B:>rм!87e܊'H%ZϹ/3L/ ^nqw⺍W*1zypt$?y|*](oz'sq ;O7pzvbb42qap.-DhvW:\Lۇteb$ֈ٬EiiG+hc`b"#EIUPШ}sudu,# LVw=dFr:qқx:R݈GVW~IaC;xEO1` ˋp P7`8bfa]kW4@BX0* J!rg S;6 B/lQF} #~&R+qϭkH<.5: di`=K(CyǼ ۖ_1OP@peȓ@m+!)+cھ@XJҬkūEUz !#ol >5|!O}mN %<&IIeFQ˾: md&ĺY!sw&I8|mL?.e|Lm\rJoQ6+թ5z$fXU6h&}'`ׯbwonXc'_.xʆXK[ܲR*9mUa0Se=4_rZ7}> /Filter /FlateDecode /Height 106 /Width 75 /Length 2241 >> stream x[Ah[>/8 CJv;ApVwр0+EHd,"I(TzH )xmqeHIL$/ߢ̽s{朜{wj5k8N{@@@@G4eyqqE&{D<[ ǿ,O$333mϵǷ/ [G<D" >Ν;'Pfnnܹsx~ҥ6dى d2P7www>|kְįB_nlEأ-]w" ;nd1h877w9RY9Y:;;H$bB^zeKݻwo(b S8>YirU[f"nlCc̙3wAxSGD+tr[={G4DO˗'DcV*/ C<0-VR( jJz@)MRjUd2(BRJ)aU߯jV+ AQ)۔RAeB \RBVVV`mm;6D~u~wHA MLLh !Hd~~ƍGFS4M󣣣HD塡!U.SdY6Sʣ !&\$~E'@Wjel)+++'&cNKE5l[`|+WpJ% ܝtfB&hRtB.Gu@Qn{jjR}\.CP B+Px/j5s_Hӆo7Ra^/a8E) 0dLkkkhL&Fo>9#(J8^\\oPJf)WXaPUT*E"*h+ޏCLOO+ÇѪ -JnRʲ>HMI}\9/6l4R4A8 :9~%~!I98biنY-6m/HFj5d0eߵ1tT . 0Jdvcqg׌"MO4@@@@Gku[hhendstream endobj 866 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 867 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-Observedfig.pdf) /PTEX.InfoDict 254 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 257 0 R >> /ExtGState << >> /Font << /F2 255 0 R /F3 256 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 737 >> stream xŘKOA )|LǼA<^LqxXM^ڴk'6G=<5MCpfmCpި ;0 2GLs1aԞ3jȡ&^%#:d H3*yrD>ȗ͏$cERB =^R@\)B@/d-R/W@z(Ɣ8 f훫{Hz"Px+?RAHIK&p"l{^=߼&^EKj"^=x6R1͐TEݿgN5bD=>Y2TUZuuo("hIT*1"]^%үľJ=Tb j5 𬕵+n}5Mks,@0ĸvnSjO<{<:5r0`zM[Log߃MhܙbFs9Ebgt:[*Cv.'vc"~vZߔ}~M7bT¸@'UL]|qe.^}$[[:ilmƞ}Dѽ_B/o EQʥrڕ`By}j/1Pw'h~cA*^1tCE3Iendstream endobj 868 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-Expectedfig.pdf) /PTEX.InfoDict 259 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 260 0 R >> /ExtGState << >> /Font << /F2 563 0 R /F3 564 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 680 >> stream xMo@sCm(BJnQ(q*m}w=Aj<`>}fh'V}zaw{5]Q Æo/mx;/? |@08 }$ @|@_ < p*}0(+y K@x^r1^.P,%`>K g P/$ @|@_ < pU@7kϻ9 ܋$g}x̖Ç9usPX~moYw iiuFX>4{XΫe) {63Zk0ʣ34̢Mxa\(_{8՗Oy-SG?oE1pM7/exڂѤ+]vNRhfu3ΔO> stream xڵSN0+hzGa8 rQjI[g4"E-'7{)H8IdP"9B9Pp,^y"#Tkͮ(]Q4kz z=RWXaM5 7>ܬj8,D'"L YHKc18y8't$+e`t.2gZ! =t|(xjfAeuƢ/̈́IP4*ﳭF eSpզih9xsNX|pDnBJȒ/i`M5=]3>ݘv7@J)]UxԮیU:Ԗ4i?kendstream endobj 870 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 1747 >> stream x[MoL^%MbQD+j!AzA8pjψk$\V^pQR(*"0ii|5R(a_;u̮~Nzf\iD"4GGG0qQ,EQD"dى`0xjEq/0l3;X,ٳv>qX,}ETXibׯҎRya0XVm .>G\FbXTpԍ޽{Ⱥkkk2LFEullJ y&{KsÇZ__?zP(͛i46!['N GNGGG|:>~nCkJw@Fi7}p:?~jqn}Y:22P+o%oܸI$W^o,vO:fu>UkRm(yh͉4f^Utq\Lfz.2=`ibb d"h*h4TۆUQ7Uރ8ƁSyc}gϞu8Tʠ|\n*U|~ss@$ڪ۷o-T E}9d]s\:@[$|t-//_pA~A777gE}@S_| <_jYzyd]sv;Д ^Puid a3> 0 sxq(>T*Q/ qpXIQMӰۦZ{<91~_i]2ag fh6,OhwMFř;wh hȑ#cccp6dY/5"M'ML9!|ɓr#NӴ\Y])SՔ+dpgWe\.WЗ* $I냿\"h s|߯/=]B>oxko~ԃ1.Ö,<}YE9fwX*Zh-b|D4E 7$Yeп:z%IA_&|oBelZ4޽Cv=jH?cF Uyݺu OwDXm9K1+oe=zܵÇGfi0D^%Ca^x/sjgrpONN"?lևZ6Cfh}\endstream endobj 871 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 872 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 873 0 obj << /Filter /FlateDecode /Length1 1765 /Length2 12045 /Length3 0 /Length 13165 >> stream xڍP\ ]4 .!`ww;w\wN=ޫ٫{w*2e5FS1Hb Sfe3!SQA#Si[1@@W8镨:[X\,,6!q ؂ v`s 8yКXyx4؀&@[dh PANゖɎՕ hq0c, G GE Ҙ`ǿj3'W*l_MmMA5y/_2o?m4@l쀶`[sPgrrsbmM !@ hJ3u @RD|MvNL`?jdk%lM 66 ['G?;L^pl!Af`[S?0ucְ;d漊+39>pqr@@*Yi^=. 3ߊEȬSdEW1/:@uX,|y0SY]^KTC%<?r>XY99\?@ˣWO!.ogC}hz,YL^X?&v/3tSOG[xggP^j:hQ8_/D6%n Se_K):ۂ!?^8FV{9חT^OCJؚ@L=׹ȯEGj rsLWkq3`C0XR .3i_`6/3_=G`6*8;+_5M353nKԯ9 @ XNU󚝓+_ :7y0M^_t|@n 9 _eMj"WƝ1iT:FE6{t$5kn̕- +%'ϣ:ЖG8ɝV䅉}G"$HČ»^O^Vo;dr읹ѕpn]H~] Q٭Cy:_A~8ٮ&֚&jZD`)JLbZ6釶'^1Q{c6p63}8ˀRpIfP?)NzK:Fx20Z *rō؃r~鯧ŽXAj+ Lv 'gA 2lDerȦ8khMܛjO O?e*r} !?)pbX($rۨA\ kf<^HA}$CM%Uceoe,mK$]7{U򧉪`XI'IcYd:l^>I&ER?j{DyuNϟ\H@zΈig*2"sw<?i%y(4[ ]>:51I{yu*ɑ2s!NbJ,q egs:Nt壟 ҁ")&}~fԈ(W;Z)H&RH׵ psZgϨ`4g54H(m>Ԅ)ό(p 3 xI7zGl^hr=Puˣ;K,a2ןl^/ؿ'<˴^9z\qʷoDW\/:%PPˋ,M(b?ptx]a:*Ӯ @>s'g<N Z\%dYyGt ~9݉uϭ1DZ,4[j=pi 5\uXXN:kz$^>зWat/WG%GG2_Y~H;jo>$wc龱xS+佱H>PHhi0+ы9XG\ FypA[t_yi鲍-k=cN^.f< t^='K.D^UM] !F{U\eQQK䬞7HjC%:f7,)_S*iLNJ-\(aa @ڌLũ爨,xڸ歡)k+hdT$- K[Whg2lWٵuimJaczBZN|Q仪6ݕtץzZ]ӓ (E:ёgzKB6 {ĠKnɡMIb#VASg`q:vYÒb i=t@:~6b\'TXy1h)d^[cY{1{ ~Y+W[?:ԗ<4~6G_S=_H-c~>+"3AWww/i\ #g$pP~X' < JEH:hE_ɉGeߧ>%.Tx\( pQ8(-h&?8 vseHA;+T7@dIaq\* M!Ï!N00rȣBj]V]j7(1q& O; -#o{7xEzu\>|nMPB L|&6ؗMСQ佨'C@9t?N֜5swwY\t@~NŔ|L1J[ՈyǨ{#&bǒ$8|3`yN p]m'KjĊ͖<щU7DF^*Z(d/mPSg,2Mhl9L%8X ).zx&0]iSADЮBe>#:o8''n|?}2Ls>9h`@})wDb?=_Gl8.Vt n < &Q|4W2Eay#X=\f6lX8]nRO{V nHKYrs;<RmLFV@"<`۠ od:ΒDh D3?EMQଥ_!QunX %Y~.W"~ˑ/|MԳ WdYvab)ەސoټÖ@å8vFkFFG^q=  'xgYeơz4zRy ѕ=Έ3ƺ' bKx-}OoK|7 qb\JN> LjDϜY}F[#쏲rq2Y9q)C۾lm3iϦ'⻞ٲ5q\@& dȵ/UK ;U3'WA/v74er|3*DM{׻Z) bwÙf z sz?*8!'=R?rlH+ZN/f&>̈~g V09vy<^%!;aSvC:=s3: \Q LI;(*:HFHoՔ]oݖ)nJ90ŠDS*=gQtx5v'Oz1sY~R(Qԗ#CW'GƮ{̵ J^f+i DtmҧLjX,-EŮ1Z *(戇c-ǚNoΜxdP յH4"WD0\᦭G# @^@)5#o,^%?pԧNZϰխV'~v8Uut p>^l74\6;]jrK^s>tfRL؞>E*jGCXY6n`9 G爉xӈE|oBF4}LW?bN[MޢZ5oG5JTodxFT }+YgD P{AKӼ O(saԌ,7ut9 p ,r/E<V1>0Gz(R T'jIZ(Gb";P=a @Mf,"bwYbFQX$)o=!>uR{ 93sCDCϕRCڳs %׀6H /).5uKeX󦛧|RBB@Mugw劗F|/F5:la^p"&)*?13!F_eb`W.C=T+$ʏ5OCn}b­ϑ vc1Q,B%O~>˘yVQ/xp_ ϝU- o=<;/mԄSU@\6>JUKWp^Y%k ]]DQ_l.þ$W*'lEecB]b( ?Ob8Ԡt`Yx':3q;·^ڸ>Y(YOgAl].plj=: ml0M K ݬn3#0کoW1tP/781jRG;hK̲ :[+VP9>)gRDWMh)rOO3P9ށtb6#<@o냉/t]G6Zd0lKR{idH50 Z{0* ;oób_f)[2oiE*33lc_)" olKP`$JVQ!-w/%QvsrMA?URܠmdq"ԦI$7%Gcߴ瓨P J3s+Tn]&zq.V])ȝ2nǯ'n%9! 4&Vݤoڰ?u:Vҍ hq4j}0}Nv(dqg tvA'DʑwwDp~9W(g۔sK%'I5 RϚI 6n Fw PxK5PJak}V"/ګUJ,ݻďVqӔ0w5nmqe͗+A0 YοL2Xx HW`3eÕ.ጤa. Ȥf#/VmSdx8 0;s_3,8J#:I&>pcűAt :w}  %>uJ>F~5J.yHЌ~1M GJ#qiV.qQiEW2Ɨʞ2_e%[5Iw %HHtw1}w vCC~r=೪R . f=}R'rȝiSyoQwt4<5D^jKW) r'u=5rwևd)I_C I9!%#B@UCmN;N^cMe B!(Qj/,S e? )~[oG2]] 'd-RLpJXrMNK_Oc$-vuT%^B66A1T~;Tf!؜k{xSo=h:RعAm&f,a #VLsNGCP|>ȝ'q"䟱ܬ;\%&8PGe_Ym^We 96Gll$R`^.KX5Ӝ bPf@Qϭ́!xօVpv4Ұ+7Csс2^pOoA7Vi>;MЏ; A4tVdF{,~mߘC#*GfCcʳ'DoU׷IvUZxjJ?|xknjh[R2-)o{Jx0kd Q7&b>C pĻ`wS U}]Ύ r O*<ɫ{ R+o Wmn-RV3/֒}ev㛜_ɷFھS<' 5Y3Ins/yT嫤\d<|k[VFxrUFhSxϐgKIZXǡOph)M <-_o+(^k󒌔]*:ޙcԜ|SPz@8wE`Z^)Gndsy7/,DHGYMrcH(ӕ}`)|CH=z|ϾSg& -Gt5vҙqg8 Eg3>~! T;CIACJ#o}:ۃ̞2n$7Z8ix b[frVؑJUa,0b,MDG/ qѰiqI"?56RS]i)wiJ?,ߑ)֖6N%AsӂtZN<0Z.WlYcѪ]M$o74jX2Lbe4} &dpCl[H/0ÄH3V[?}uD®y8^{%S*(-8.4+'E-a,dcX{g$}bL~_̓Ū[VO9(5T&Izz&20=t{(`Hsg a!FM|K+l#'D.NM#N =žЛd/Ahh>d(:*:I%a:<,v0ң+5#{2C2G ^rDk~TZѲx eٞuMAG1$ŖDځ- ~{e&  cp݊ 9CqKz ok+bfGXYU4!uz 8pޣ \z,!'zwSȷ黶7;G$o:x!z7"ANd8$#O&;}`SYm?(Hy (II_ |ƢDt5(;_2aHa1󋏎9!5&bs"cs2+le ȆMD4#FnP\[o)'J ~vppYEq |1piv#@V>3$\SH(|\( 4 `J!N0v<ԧW+Rkh B$TU;{gvc?,S)vrx懦)k)pBqyb2&On`ݦ[:j"7Z67p6t$C5 ܡ"Inh*A,B ]nWl2|H}#ae>B|灷cs6qWjHZ,V1ܨ/nB]ʏUZJxB1[a 2ߡqy!\E-׬Bݳ ʳxJXvO(4@jliu<V$Q@u)n ԷFXte#LV! (xiTPf @ﳒLc>6 \xMG^~Ckv^l-"Z%3iAo~ZLrNePR`+,4ʷʦSAdz(KvJ=TWۮWC j JGU5(p4v&dmSH}tSs%cJ\iE hlm|hra1y ?(JT+VU=&b;6Fg1fآ 6 2I*h H7%6zHŪo7FKOX,R<\%5&0$hDt>qGQݮ`Enu!=x#aHjEa֞7Ȟ;;tKupYy:cA]hmQ)r\n[АM4!7 QtL>^|!.'adT@㸢] 6IFc\ H5լt@ N_X_p݉3ĺݥ8nqXBI'ap,tY%*?D@œuہ3pص](oMz2W j6]--ce9RK=9A$BLl޹m&3o 5Z Ćjƫ:, )M_;3G MjŎ%p5F#(\1P%ݯ` )fzu0scB-B;y$`cikv/H5P/z0y'8jґa-v_,#r%&B>ؕN%{LNV9r[zX Ń^"~;.%@zә][uu$/M5n6#i{Bv*rg#l`W1I;<\^99p'sxHҵRendstream endobj 874 0 obj << /Filter /FlateDecode /Length1 2195 /Length2 15430 /Length3 0 /Length 16732 >> stream xڍP Cpw @pwwwCnsޫվvwMI(jjg ufdeb+鰲XXؙXX))5֠)@N`;[X;o2 󛡢-@`ccaΑ trv 'DJq;{G[ИXyyvڀ&@["dh P3='=3Ɖ\v@ S_J@п1!R4,NRۙ9A75dbk re*A2V߇`ebo{l3h5Ae)&gwg/Cݛ?]: % 17?'G/y;fI[Sq;_IA&oZڹzmMabϬi vpJMGfrpps@_ 43#1<; f֏WxzDh/ 9ϵr 6n ]|bḵ)*/$9XυfĆMBh@Ү%KѶBcMT(ņYgucfqM?!:v?z~Mw r>Qa Kb!F ik w;4uW?E6g/;I;s?m34>iLB GX-Ha?dj TbZ A/z'o9VSO)$HxP`^ƂƮKih*&ՒOzT1M=Z 1cLrE@Zb 0?)"9Vo~d:i)!2nhe?@e yLc]rL\ d B4J8I[AiBM=7 ɚ/nUۈOq;}[JL4ZJ{{D0FN=%*MH1fś]}x]cnT⪕\i],Jb$&rZ{Tf?75tw"0Oxjҍ|`/ٖ)p U{77 F:9u Ľ7[)!Mj @$b*lj tG $mH*a\H\1nYglז45t~]4bo<చ@Y}P%P_۔'7,f iЋЉk'1ihP4#{$zjP LI$>@< N`B/Mw>Q؟a%N^Eu/|JW cʼn/' QqsDZ J?Z%gz`;ű uξ-|O`nC`ӍR lYN^ x)$g>YQmcB%_N]FEƋI6',R3^#!*x !Ždd]xvbO;Mxz9{+ d!Jò!HM*_ u_Zh^$,Fl`alR{5%W߅t~ Rх9%I\Msz[*h!mC3t GKXg9/Q ƉE{#[-A& ]q@'5C}eӒ5]{D BD7 u员m)|sRAĎUT 38^v-/@gjteC 7)?;HͽsiD?#X=[Kfɹ ]btZjyze{pg_g^.E[r#(W7 .?{vOp`Zͱmd6VH/TFb,^CEB)삺_!)c^ŅH3twAt b@h%?Y$"O]2hQ 1D^XޥiYEXR\~!wuX'Œi% ˬ諙 ne939z} "9G.^+y^2X%d'3(zO xOiHo'хofWE ߷}ɣ0B 3g8rd9|#;܃N&,lۤ u@U}o0ϢtzCB=좠>!h7hMYE kG(}VġkEVV04e.Fʃj>1f'^E;t6 K)_ƜȑtpP; 7t ⤎1V`?XX%< FPHfz F[vi H}Xn!CwٌiRwnqUNrɣ[z:4;*+~N<^uR-[D]P-0l^ e^L& u-\6!^9M-WCxF<6uQaª"yd: i9,EiURӘmF]F)e`Ќl7&;BpԎq_?ro6HNHvKWE7ou}k\s=ѹ9sHENĜ"F">7[7 IE, GVq{/[tB-xY 5RM YёpP8cN >RS4";davmws.]@Hm!gaƹ ?V2*%7(n;iDž oyc4+9Kd)u@2|-Rm*bw V󽢣rdD(F.k{htUieUUd:mڃ4]i(:O4}(}݌M2"5_x ku+${w[:k>^o Ǻp`SuZ+ҬJ=g`LRSFG>ȷv V.ԧniU< >`$ҭ㉉NU6iķXc,e8uvoD&o'bj$l=&xZ76+B7ηnkZ4&L5 Ʃzuǜ|0jpJP8 f:{!kΧ_Z(/ ?S*,gIX Y|rt1y n}o;Nh*Z)m9Zĕ/;'(\S^/Oe[RךH]ֿ)agOB,| 0őfqVɾ|1=@k]$z!mԞJWfVDOƞu8)Y&Pfjѹ~7x,O"gAB:s%iAFh@/+?&W^ӚC_Z/(idUkp23~ׄg>QqHy˷=VibzrC"%m趭pT? ɣ,4!'ڔّOH7c/*(笩(3<.zCjd\F+^çScu>/'raHSNs;xui ^j<<, 3~!n @;1;) %+K#˻EWڳeJIù^Ji:X[B 5 ˺j*U s{Dr٠tcA\܁i #uqW{}Nuu馪G)%סeStƖ᧥, R4q&tEG*; yHbp"ODnTz R0nSnڶBm_bcD*id6"P+Rz_ӿγ4!!AƙÝUrUj]+I.<O] J dM鑅`C`l?#\zyF]0#R7")MQ|⌷gˎ4=C/ or?(e0&Aſt+6MBa虭Ų|ܬcAΛ><%%QW9Ⱥ }`)[Sd"+ܠ1o?n#UvYwKy-2ܤ"bQ3Y:8T\`BVmylwʨ(m3iW%˷CҩIXіġ]^r'XO٦*#yt4᳑yNs,pWZ9CH\͞VDT3ꥺl iJp$Rk~ aT -CoܩF.#l)nYO0Efx:0QǩZF)sx!BM*pEˇY e8HTO骓'X){zìHlI >БX⇧!Sq 1-:>5'!!{ m6,kk,gX]qp)8Bٔ']-%JuUXC }^iTQ|V_SĊkd |ӪKVߞ=6 :_+D<m6#'ݢR&h\F 1@w Nj(J0آӠEmI Sa]\v'U-<szXfE":z!~bjSsɉ?J_1"QǐodlC+!6dt`UJ}VMhRPÝ[vmyNA/s~=k/OrA KUyHvu;rOUԠBo =pFS52[jchx+϶cIW`u=yD~j3i{OgT[ףhrڙnV7ƷF>JepʟFe;(mr@TEZKA~~#!u־ӈ4We+q6tA-yo}9FG\tx2[ $%$8LsvynGAO6#]In:b V;7]qk^OvCA/# t:Ցc3f36}/#,zeb6⫨+ڣ4'ϜАh z8_B;$y>{+:xpndb>0H4_]/jڔw)+O Z BOPy lO ?fqkRgG؇I[nΜQyAyO;`VP*M{8JQ^-j3X\CBM,T9K]Z_Yk,E_ǓXL|FZ&a!EldGwv`/ʳc#Pt9h=btĆvh5V>Yb$_y;R|qMN<1㛵rCExš۔A%(Qސ; c//ls",|QI].v%_*~O' Rf:UƔ*a{ɡy]ϳ9֯`Vu=mڳ1"Z[ŮܤDӦ4/L*#Zhb,ԏHNRaU~l.摡M~Shbu|lއ[]m [ݒ`&EaWAJK p9 )f# 9[-082].OQbn.,45/؂G"`wƋ+bT|*P =An{"b[atb-8#+Wdt^D`vW‡B|ʎaӥx5ϱ8 F N:zSj>G2)sL~/YTkwxw1Ou{DkC0s<˄H:p`pRuj @J!q9)_&XBa_Ryݷ8z*36jBיȇzvɰ,8zMC>_ gr!x*s: X+f_'{8R{Qq!Ԍ]vk$Wᅓ _6x>fig*8UIȩxڄ#Nq{^YDTVwHX߾ԝ0dCitQ1ӢzBUw*'8w샀4/=?MW"'hB8Ƴ>g;DyѧUų`<*[і=|y :0'p>`qcDM.vJ[dd >It-U8!MkHȴ&'ЋN5ىy4ivjuj%EH#PxmHxk#_ g 5a Seح'bД?ؗ+M,N@v Fk@jdZ6/Gu5(eR-LN:尺D]>ȇqcv lFCU3 +:gfX.9O KRtoaKD*&R( sP=#TS6{G*AJYf͂CHO&U l}[{HŎ6&hFqqkm"bFκhN>Dl9c}Bz=薴ܦIc.X9u OoQLЀKtNGy`Ԁ^G߮U9WFgÜsmz$,\'nc/zl/穕r;2jl/ut<}]ӂf&Rλ6$S2RWUv5P@@ݯHۈd>ls`&S%6+ #90is5^5g5}AU8 hSVsDٶ 1 |KFAu(93ddZ*Cm{qfxds~h$LIlKF Tw} R`06De2zl LeIz 6⩳1|ۈᚨ }>p&I_s3J%a:1-je˟~B"-h)JGBT:F'x {O*OE.E]|ܶ.,WY@?/αQȭE0c{S`viF*'{^;MvaF϶b$:6Sj߫w!1>{ WBhQ=#Lo>.-Ir%t>&aiŮ(dgGXP=k:,>R0'RCg7bA{@e{ +[S2tZ|c:^Ep*My Gjd =%RaY 75j{W9}K{~+ȅ2V>ůiO =4a`ѩB6*HZ|ΌEK(k-x=~ 5t`p9^uL.!]n"TʪJՎh&?>&9 T!w2r Y/튐Iݼ'יÑ i:@ GZF߻l z䝺iJn2(t%qXF1/ҟ5%$a202U/)E^j_lFw >𔨠W\pgPn׭ ZCE?wP]BH/5@ޯP4l1<_5LoV\|Yi@F3Ч'B5m((XOYK;UInW "7JDJ̩r# g$E0OÀP++uw3xN? ;_ݨ^O9Xc<ٵ~ =x3~({۽)Pu[; \nun)p§siZ\.Gr(rɽ .?v*G@,(ӎ&yo+~'`?Pb_/|!%&ڠs ;)mk\*j wybNl2 j! ۀ YòFEɗe~&&9sѴWg_B_<'`P2h<2ΐP7m>'XҥS!x'].`qYoܴ|iRZ( ZD~2}6ݼq7A۔[)BZqVPrFBI#'ו@Xl\&Df>[ J**3S.b?"2mvzZ1KpPâ{7><>IPIz*\D5/1D+6>=, 7}n 69#4xZsd;yIu{ЎKoMrͫWnY &gB1?qŢ(3֣j71}?`B$i ST2JuT/ce-c.鴯bు\}).6*NxX|P*:Ŕ*,wڭ(2'(,Q[ ?v\X;[ILWňg.@+:I6$熱0-@ ptvE^Kw8v+FuU, ndm!'RR;?c1QEsEJ(^4m&_B\d79c} h B*%]gM:]|H,ظ2(m=4ǯ#;h=h}Wqzzp)?8JbuYd7 :u 0}+DoyUt'/17AdV3gn9? >h\IŐk@ep}%Ec6JM/QA˜蟖%<0<;a՛Cx_>fiqhf2]|}ѳUBi)i U/Ҽ(%U-MCE\9G|2Km~IET'c)Pwk 㑢wtx|Pf{mM{EFKvH:؜hYp5Y-S.uOAKA؍^լ^!;tכfp9Ѭw.3-0ER QhWqѿlguVt| cާ끫J"-2!~c,j7W[eM gS5%" J> MuxM !Wgd}]b7:!>tq|/s=^[T,VM|Y8֪*'L*(`K=擏8~)DE'W]i|D/\!0V0lN7#-> $*BϸQeTH\rS7K,%FSx:8#tz~#w.ն: AKd ]G #I\@q S B'Bx'tBF)%VsF[ay3J3faG5fi!+t-OʫP^1`-U@Cp\^ԐJDmӗ2ʸAx|9[~6.u -m]|P;kV@KT!R5ex|yO)5񞚦$Ac~Z+ܟcV?V;T5 Ac^Z8W$ Q%m=@ӝ+.]Up86&`WNjcKuݰǍ} @]c \lNynJ8\-c\d8f|U],J Sc3__T,5LmHo*BL~4낸BVj@kMP1iMlB (smTTϝlg?Z!(uBFi}yS]VruZq{y0rela!ҍQhgcܵ!ҷp}TB<\FR_0#}:C~Ub5M!fD`h&3qnZȖEt;$粌|N7щ߭($C>U4~ŐL{E< `-!ʧ$$W5#.>V:9<ݼ;}[ƶZ"^!smILܭkQ$r7>i2~T[yM'U8'8mR}%XDYHey: fHW!*w-V̫+z:DFO0ۻ%j W)^bAd'])TC]i]jjEz#i˯?aQ56UJƪ8^u(b pWRG4'icHs=7X\P`zXш<&d*`jɹBu)>x{EIȌ~Ŀ4}X+`Hؗ}dxļw>Ӕ("҈aY @,*=n\WdVh}QZ@ G&_FVԞX-߰lۇ_O  u+oʈ+KpWp"}Q#3Mf˩wYOzR~~c%**bW'UmpbСF  :k1T#MHwGUhI(zT/v4bf+Z!dLa LA)mReX1E5Yb.&h.#nYַۜ X` I G|QDNjEܹ$ʭRjMvj" Κ8̈́ n^Pòg-KZ-`$-LZ?},Bd]ЄI|ѫQlkZxCyEAYrA}" xbQd+7vnB d%6BAK.n15 9W֯x IQ;d/J#2FĄJߝ-2;^̽#ۡEft*;m*>3!aPAx޳v(gD$xĽ{0tY|NN{;҉^{b8py mVfk2S2lH;oob\LNN0|!+OR[^~ G\wN*-v8T߹ LlG-JͩySܢryF>Zg؟e~f٫x~\^\pynrBu,vV> 9Lj2( 3d<;ı}JހVOȨjo4Z$ȷ矚-gY]?: 5" NB>/Zkp|TRSOHa)Wg r㜙)Y9B4pה@e|IG BMt.ضyw8?i eψw[s#V!^h[]rz,81NVSX8'ʹZb. `g 1pwV5ȍlλUghxMk'@^xSfHVG&_$ز q/FVoCIJ G&d+Wq^\~4dgO׺Ͱm5ܸxfcp< 쒊G^jKɣFrv]Q6ebv> stream xڍtT}Կ*4? .ADdlc PD@@@$APBAiQwglWDBEjD IDP6544E1 ZA3$a2Q#aDL F$Y㰀+$%!@ 25IT9{({")ѯY ʋwx4aD{)#Lpp4gΊ`;D";h\Fx7$F09!q h Ύ##+􀉶`0a  @hwgsra=X` C =у(o0 G-{0@C($HD|# gu,B SCpR=szvh,3 ViDD@C ۃ0tF~WJ~Xz;;/I&ܐ[oD+) p"`DH4xp B@IuҐ!pX VExJHIKrrP@*;"]jC,xX;Լ_<~ٟ#;4HB/|wM($ W ٟ iBiW"i=q%*R#hWj0Қ(cQQAd~ a&Oί H# Hw$;wZu,Rr yBHs&%+KҶ"G8" Qpxo/+/~ (6H:*a$I;"I֎G.[c~)$IF_ `_ "~C#ҁKM *IMqI=pÎTsJ Jx|z9+O:ow[Dz ᴣpsAA {ʜz|+C!9rd*$u_,FOAé%Uiebf" XU7Pp FytZ_h3 yM_LJ݄z|.('5S$泔zF(FLa!UwBץՇZPhgx=.[>f mP୺: u8 E=,|-%sqϲےh֫1ZTq47*LDm #'A|Pa,DPĬz(ثVS 5(R E~$j%}yL|̀i4Uh: 6;,XubB?'pݘ~{wR @YIJ|;ь-ǭ^,+\ zVk)JXm&/-DC&;  >Ϟ`[7M>׽ 9֘j~IDCyeGZR{ʲ M OgP1qʱ0ģO&&o*wdÚ.Ex)(L|e?zN!0M1XI,i~q]7{̽$rѯH/A+{v|=8V ?(7)M]B|j%w n.I$V8y2#R/TWLmVt~#3C`; qCM2;^ywK@ G gO~YRTs/'woѲM #V7Uk[=BA\MMs:9bwm3 q\ %Y;3Zp_ݓOg4 2_Z:jp2he.BSZdKh9Ra//PY8Qc*~l ~Y|BedTs]bQ.9l#v\c򆃹FҎƶDEf0#Q OJ\W{G[,_ ZhPj|CYܝs2=1z̴uli +ǍִnAuV2Uyz]iGC}W"/Ud$|ny]-%њ/'._Ʊޤ iźq ssY٫A/IGSe63ama1buܓKTVsb~uATe)X]q [oNXaVvJK8tWZt\a&jӬzAN!938o>\-WT>],njs7?&ln1z2[L޺֎+^b)oWFV)=nW.ț4.¤f3Ao:+y(5W~j:aj%RvŎQ*J,-}LPt0v{P\ P[yoid0^0=_R| &%BvII̠;N > m g! [URz@C %S-YaK%~~Trw/k_X {_ov`?bes uz9 Cq*0!zzL|t#SRjnvD2`zJ=Uu;]C=,}z1ȑBN 7B#aE(>-,m 6J2tԲ^C܀|;Zu6ǬitbJqk b9vB"բfO:{@w`L}TNJv|Ptϔ|&:ud:v<VJ?P7VS~B]/rVѴ#ݾ,:7I*Pڍyl="Y=N↍p +UߑoNg7O9{oz)2TJjntU d-liSQݷa0JE"oyT/Yp9)}Ja~8ɏF)gTojKnΰn;o ʼȸsL\G&0*hR6 䜜`O]]RBM[6k&CX݄ O!o*vT%xֳ'__٠iqa|%߰~ "fAiQ:W=?O_~P2K6W1fUU'b-ZSF%wO>eBWL+Wox郙\vT#-3t,lfWf2rU2qlr/+ SRi%0/lO )HXIjmEӕoR~`ۙ{A9?_W݌c7eD9&-%¬F|̓#C#uWڡϿTc>vn,j\_7 !>lO=ouJHsيk ."DVvMMW2YkڤDCw!>y}Q:xn ;^ibu]V#wiM\w|ruEymq.A1#=Fv7R) ȥoH"Hlշse|\ܢv0y>GGj'Z}nT ŒS"[6V]Շ,e"u2?+L2DB+EyWm#IZλ&Ã] *q]ScA纣x->-'zP<'L?i{iX_/c~ʄr4{pn;Y9ZhzՓЂ !HQUwQ:PZjKQqziiB44evL5Ṑ/Q׃ѣM|+/=K}^=)naGAȠ?u^!ܕ|)FCEv^.ИHN 8K䤅݃eUv&Ttl4 iѾVyGJO:ΗPxY5q卪1qrY!zm|6lHδg foě9XO3.h > stream xڍT6Ԁ%)9C0 ҥtt7R4"! _֬5쾯}gh5٥`yS b`Ё pI?NAA>. a~ 0k @]io `D,6'?C<Fpd0+R^UO/ovn;7'W yj ?2*:YCKFоE %Ԡ1'GYɻ:8agc9B%Nr@p8aypp"B}P8A :UJh@r f G󠱴#=?\zF(Gnox3P[m-[Z=Xs3PK`) wh^ xy2O\vjΗ˳'4 4[643珦/(fHTQ]V6 x>/z&3 (utՔdP hwJ"۠ht:eю+xjEOT^?Eȉ P>[|WNn:K"]:cۍ]Z.[Dh^WTEbTxnfBv ~ 4Br7*{e_)Fc}Llbw?}cܬC[_$lȱd2ZwZ6\hx{Cq޹:)0k~' 26ZqܧcDZ[ȷ:K&* . !h\X~F]kT[~}H2mCr+ ENa4MtFc?oMQPuiia!`}GҺA(Dq>.gN5@v6Ӗ(Z=@ <6N2Şu[C͞JS\ztOGGєѽ :ކwQcN,`8>nqVP9 ~&{vkmUUMN.L2ymL?GwàK#FN:$K,T[r!} aw;3͌V/ɖj'Y X'9.I^hMZtosL-Z0@C!f;Dh7}\~7q 7(ֳ F4&:rҵ"7$;T% /xXiNFbUmS|B9>ak7oYgDXƞ>6&µhN,s(^*3HL_ĉX4)z3Iop`vHo&)(;=HeUΘ@gNo-tڇ۬CVzGL2wua d ^_7Ko4~kO cQg[ǘ[THƧ_ #܉4~t(+*"ɡ5<nƢr*qՐ~~0 ,<sw_6`SӇFN!NAaALe/emW){Cr*t~N%f"LP`&.M bkDRGI(oWUU(Y )r/*1:+Υ{`|c5牒鯘+*z,~d sۑMvv4]ԜgTu(&<3>uH.fFBCxhF}Lh&i^-KjUI_NrI6rE{%u~*#8Z{8Razbչ־VPֳ0\/X$'T2z|iOȯnOE1ldv"hzDN}J3@a 5"ZN LVdY2&CV%$dfh;*Op.jRgB4fEMNԃL KO|kX9>T4SԋO.:܋2琽v$m!m1;=Mi$>eӠ@>jyRֺPm*XR%bY ]PvgCt,-umTΝ!^SÙp2c;ϸ,C8gئ\duk"*P8JA51T?%R}6/Q?sQuMj76;zǥY, ./]lk9Z ==.Qsz ][gTRDjM>~ : Ά:Kb;$‹SZ0F;W3`hhR x"4c4(HB Ѷϻ}U'n-v)h[9"K&7mbN>;n?qA1ݩ9|$q;X$$ OT!:s/S*MKg a+i1!Gd,ήlxgA4 '%V~/8RF1 %6 c< 5ze8q剕36j=MVf3]$9*7]x~[` ~wժGE[9Bx8@'u_^ys0Դ^#̚xK[]@U؇7`6\^mGo7=jtK|$ٴgf"e^*&44r˥gPsB]>[20-FeRa~5ܘh61@fWȂl ^HaW& BcY`.8WrN'"ZqNܞc$sM*=/|p'$NS<ێ(V7?hqoc޶9FNeBBagT[O奆;yQ/!z|߯`N᝷E4R,vn6*N9A~.?d5dx7%i9M\$?_9νQf?U0F@'eKpӕeJ>0)ȸ-Op_my~ hHuU<IxT>5;爙?CCFC RCmZ\%e Q9M|_d<" tLhW|@}.JY:0:)IMO=o!]P[3l줓3a1KMS2.7 G |)V. ojaߝ=&Dk:u|LxV(U=c e 1-֛bX1ܟ*c](+217awfLt^USHhzb٭|.XK^c|ڠJ7@@yOr,T`%뫮ڕf @rA?}I݂4Ohzۛmn}̥|dsoDMf9IaETk"",n3c.l?B2 ҲygimB'߳$ҍ^M| VV))11l=C#vL%ZۊZ8lDg+/ JCՍ*eBMf(e^,{Iq0odTP;$-LcmktZ]Ð'$0#|7p_px= ?'f@RMu,Sn6w bzmsl3!.*fBhi592}>q\eL$[ݒӥ=͛VeO*<wl.p2V&F&9eKh.ߙgoW=>ٮFC7-`]OksڕnIY8\~bBp$W|.%GuYǔr70}RRĤ@()̒m*7 MZ XA}$n$>XSql?CZoaFD㉌_umy$<^ roD)^ !m$}Ν 둸LK9kڽbKE. _H{LN${7cBv' x+O'ٮϻgTs`:Hg<5)D-Qu*=~w")/-0H=ZbRƍ5ʂZC~sIh7IR@˸PV#cXe)r_v] u$/*gԢȖSDeP9xN/_}˹9ۼ I0(5ݧ=PvfXWkݜMЁWOtHYjfhR?ʠ@8?7uŚԲ},Մ.?vU̾Σ](:gDHyIMng al5T9{Uå/H#&Q}س.:xob3$ Cl|g`/9Hc'^ts`Mj bv_PvD{Y+gqX&Pp_,9!ȰH nk߂hNz*cz6~m*@0p-fhx{{5W}1#6uԽ,ckYc.-)q%٫pNQpu@ 6k; Ӟb/# jZg~V^_qS^Q<aцŵ:\M,NYn7US`g֢/i5vxP?eoKHpJo ǁK|µ`g\}>}sh#–|^ZHdy÷Wa#=)ϩ^1W2)g VIq[M<iTPi h>t3I W_t+a81,2>nm,I: <Ӱ~EAId,LhAc$U)P;Fa_3cYm؈|}PSʉ]#Mx;K,BP*F,|09c3?~*:5tǑ{^ije{2"HF]31 VVj [N/-?Z? X3Iw/ v[%Tpzb- ݒӅKg^v$5.-`^0χT-ȫx5Y4" Z 0>_DD]߄ 5N,NJJ VjBL| Pc!̖/멌~{Hi}hQHoU&cQ1)qI#Kj D5⮇=hXi6݆XMWq]:c 8q/xvoNsii~^T/ᴵ /};>)/#o`iWS#B=GSw+&.."(g14^b(Pk;?<&'pſ~QYtd4\jtA33iÚՅ/@Fi [_=gRqs1"4JS0ɍn6{0ZXl)GLLY/QQ 1[K殠.U܌vhmB9G`[8z^,Fx5_:]tܑ&`EPiJ܉jAݓ#QU#sɳMù2ާݪ E l>':Lϯ6wbrXL d{JN|XUVv3޷Y\:']endstream endobj 877 0 obj << /Filter /FlateDecode /Length1 1413 /Length2 6189 /Length3 0 /Length 7146 >> stream xڍTT헦K鐔:D;D$%f`hI $$SZ;Dj9g{>}ʤk+g )à^ $@AK_ ' HjF@@h X@np0 * n +Jh@iuw(J$9$V`[@ X`.^n`{_G '(!!; rXAZV3`^Jprq<>r~h[9~#`: `vO+7m@P8*j rj 4:. Κ8w?%C[]^`= t5H j <+kƭrz+?m.8 W%+Am` (N?Eu^yB}8ہv غ?]AjzTAr6z~Q\v( ?Gn ?nDl65 %';J CFM  }2Gqx{ZU54T$/C|xD"@ uwV godT@@_0<ǟ wm ?7A}o8+AGmeV+g0O;FhP{O'?X d vwO rP{ߗ+ []05Tz ҅/P@?l]qB=%pԤ~@UwI% ܬPGI" j9mA߼AaT`s#5OQ ꎺuFXzQJ۸75P}%} !Hp|t^.Gɻ1$=κ5'ό[%n2gY%SO$kJ'7>_q|-G7 Pu*WŀOk({kYުΚ.NK~٩*,ոs]48,`5:sˀEv$89'{3|˨M#dY0b{PFBcB̀yB60#J޴O%I@6 6aIj~L DDy%zk8N"V"VIdyd?Z.*I7%03AiSP|Q c*VDJ_r˯wV3G`;z1o? W%JFC`I|QZ3CB)15W2O)Jj=Ga1RGx*81&mI=˄=ҺÆx0 %V"K=X:ǚ6纫 ޗ$ϋI_|ouRǭhZ\i&ZuO5>*m ]{ἄS(5*>Ohnb0DuY7nP|ᵟVDn~߶H%h3|2Fm1ׅ0GOMCSRJzӢG"dƑd&-,{@obԸ&Yhg>Qlu{o&%~܈d[.@%K%F + ٴea2NyGK۞=r&3 #$E>/Tb|&ޅbB~1hd`Ω'0tf1jjxqAn6STuS&`;CxN\9c$vudbMΦX{* @ݡ]7@xyI0%o85D!|_&~+Xbq.r:m<)[A~bᕕ7JO>(6(v72Hұ.fl\=S$G'*<]<ɔOjq!N<2ZߐfB(Ғ25;yy0T)zLӱ - %d*lmmЧrboQξ+8PRA,똾CT=P&HScmHF=h} څY'ғ/i"_6J\GIjd[q3; 2ĸ.<Vgm~y 3L֓Qen*+ӔQu`({盡+|c* nI݈e[,m" P&)f"tPˏ{sË]s@ժ{8A ͢Wr]6k1*Y,ۮ짦-F p4z%ֺ vkW'WUaB^4Q<%# 591,1οs;aV=J)xi%+xG޲w'ϊ?bώ0O3/=1YM@GwVnѣCfSs6xc;PJ8hu))#>B^r0ۨ#=Q^hԹ&!6 G˖fE֦ԇb\lLhCC%d1l,}T.dAItqGKzjQ7udf)in;GbdEKO_}/JIHX7g=DoAoi>`f:YM͑5qU h# B_ZYf<5-&k"PT ve<)IZu<%;[h=_۩o\#pBW*Mrj%nÊ| XKixZﮓv;TZ7u,It!p=;Ofe*]oܘA-sZTgvǸgDV~E2,ͦGA*Y9?(ի/hk+@.]8`Ttb2N45 l4$Y&4 _0Դ{u WǢOdP*Mt{S?!:ՙ){1>9>f*M0c5wx31=/xJ&a#Kŏ}Yx~3\H!U}n"ceI >Y?3tzdnm #?vҌ?ꝋL_&c pW_S_'|bwInGTZ~ _/FRiVM|dI@NḊŝ$\hƼévHnq`gą،t͋Z Jt~̞՘a62~^] >׹v/jy `a2v K wE?EB 5E܀~ۙ2Rê=eK :\J¬XAz^| n`3zgŠ!3 %ْϬp1O/)(mH ۬g *p|6yBr~ीT\+~SΨG\a:py9okl@|xהT!tDc/)WڈwZ}upAZICk "Z*: t|8H/Bf!#,{wku.Yc];xy .aFHGg<*s7{H{.=(.R _pa͓V}"n1ḘU'[]ANXw.yWwKLD{8oiS.zMzm;@d@>Ю/Ty9q04Bޱ)Ά>R& 9xd thK8RӤ huo'roWHF-T->:RMe; =.P͛&}<Ľ晑oX(hHsPMif(c۲}a0|*ɖtOK-a1+GSBMX޵$O&DQHvS, tcb(Z:"jVCQ.$l=@T;PA#hI҇'dk*tKbOcS~pxxE( ͹(Hl\48@rՊ`s b^~9P;Kc}c1~DRT{*.ESQnlP od*c"? Xd~XUnX&Is Q%srZf]. to[n=9G웍{SPG{~QKTs=ѿR=,_ݸYa[v]b }!vl9YEwڈ S੬] ;U˒s˾,o[ 78xyTNu.@!Ǡ>v ,N(#B?b3Q09b,@nCEBd nڨa%w=KYOyoqy3ߕlOxdgvtd8yĥKABSw޶0r)#ÊSbku([endstream endobj 878 0 obj << /Filter /FlateDecode /Length1 2627 /Length2 16784 /Length3 0 /Length 18290 >> stream xڌeT\ wi!C7$hp`Aw ,A^s=c4=jU,Y{7%$`SPWWge3!RR[ڂ~k)5A.V|؈9L\2qW=@`cca nn(0dA.b^VH 1r3} br23(ZLljfV WqAՑÃ΅Baj PA@_&v1!R-\Q9z8`|rdJ 1`<V&_>lbf`hbeeo0$\=]& Ml]MMlML'oQ9 _,r.=PdW~V 3p彘molne4 ͑Y $#+ daa7yY2D/1#LgeCq1q\@~>*!VfS=o`1 g+O xY,l,F6vv+7 --U6Oz87w\2qxg{hA< -gd1ޅ_^lIo ,Llcl7W(8Wjmje\M"boxF^&V.V v#Zك\mʿ:ـ/pV Q%m"' ~"8߯.f ? ة.Ad?ע3Ү?wo+ ' qe?Ժ!NqKՍ1r Oצ'-W\yRFZ2<@"ÆW :F:tS{E4W,Ib^Cw:bjXDGNJpĕEJG?+I͏tXGd V&NCpj.om5Gix<ӑ@9i|qc}|Ř2bZSa"gxwI\IFMx:O _]Pe5+A HJsr&zE4cGrۋz<&+E |fU5^S 3Ig3MS"x/ɨ"ːx?diA=(XVG;꬧o!u{!^+Di:ak2gaߨ̖0QǨ!<ƓS,, hwqY+NLؾI K$k/ Qpab {Uyg 5t0ҕ6S~mGEEAQCğrab#@3ӚJ^3R" T_A=)hXETkڽ6 #GFA -0%p]]j*b l(}r2J`>p;Z$V|Fi'U`B1xmT1A7H5(v/'i xk膐TJ蚁~lpO;f YH.CEiv7ᅃČ̔@wE%d*^$pO obݡ*_S>!e]X*Qj$jy/u!t`.7Aq֛/?ĸihlRg e;#!U6qX-Džrf3?N OבaĈ=W^S-<+E=C@e׳x_]إGZ?!35uay|x&9PmɣlX=`]o膙¸|re=b37rӱ'-EȶVdE? ԓqlvu1CE39BNGJ:)! FwgGvZLX# ={zȅ'7{ ^3[2d^tŎkrЫh Jv(Ƒ!k,&bj ,#kӠ;ǫN o8Ada\l 9Ȃ)ƕkӈ5/ T?i (YBt] oI؂FK$q36[QS-oPUKjvwN4n& ]DwNn Yꦴ@ [ϑ)òDJ8+CB޵dҀkRR}X6ә]VN$[jG5BD/ jq}`3,+8W1O0ઑ%WM 27QClmm@3o1o^3P(E{O8{H~~rF2&SyuhZڊj̪_XcvmoG[?s`zm@͕ؽ+l]bǦ_֮l1Q1c>͛@`r\Ve¡=%:͗X꬗v3gf_]N =c+g![&,MY\酞4UG1ڸ3i[D{'(F]_,q <%L_c, M+{%S$Lq$ɾ"E^u.߫T2-We ?ͭm˥G [)^XCc gƵTG_svYEL)#P7;7{T&3(Qe(GT$W ™@"mFazx փIp1&t7szn"]ҙ:ƭH* ӻODHoBL6*%O!xcǘfp5oϤiyAA:˱n_d&c$tfƳuPHkY~_;*#RNc0vB\2oy}sv'CX@bcAwboG #hGC{bmLKd;|]DSfS S{F)V 6`t(N:>ٚDfHTA- S8cǮzƱWehu g>ưeAs9څ`ljVP·iJ/`xf,l<޳MoG&}s}2GJI, LBRù Ȃt۫? H%'r%q.4O򋤤+g\T T4CNDh'{tJGh%qα.Xߙ>xװ:EA[6gṠɉXM+Aϵ0CHnH%Zy gOJ ۮ7D,qt@˭)\!ß5:mhǸؖSWo @*~j\]NZ8\RK#< IWJ"Ȝxֽ Y.Evf\ kvm}WZS p7+$$z1C z7F:| jLQ-Hr|&9 80Zpk.>$67kяDB]} ? }b(Qm+&7ͮh- B؁pd-K ,~6I+(XlO[pnI!OxzF/-Xy7 zn~XFpe<7㙴N:/SA)^"͐IQgG߫|ęo}+? B w;|(XI`YoT2[u{~'v AvKfB&f$~mk_5>M]܁{TܢMftwG}:+^eA,r'%"e ,WE2^MfQXzgANo:9F AxZ:\…LF9%q, rIst o[c~caW<cB]a3$908{ʎ.yӤDf1ͪâ WΎ-|?׬oӾQIJZ=%axP!]Y=j]Ȇ-;w BYt[8-7ix%]gX#sUT?pX7eY,.w/Y5De)?v@}?T]s\Zm3h\fW#C)4˖ʎLx ]t9A;N޲/, Xg/MWTz՚33ijT“0G;G!jkTg+We%rnί+dƃ8Q7 :77I+EG(˚jb JBR:AjPr^ 3LVqyo_73{)u uJ IOjKOXsI_6Vԙ ڡ|mr`/ B#y'ؾu~%A&[ E[]wz)۵p"sεZ.œ|ۚ1=#HI(Bo-J*sY1.hxt{-zуij&bvIFB9Ŧ ض{v5擮o]5?% $Y?iH7̄ı8qNV=Mc>Wa{c'5=**8BF4ͤX5~ƅA|'.h>e#a+Yp@^{ MK s50apDl"͵UF _ݬ.(a@a-E^#uo&=2$cؽ޿,chCy%#UDh0?M'Akz U‘k'k3uFVGH~9M5p$}(hGIc<vYr0!KqYx؃՘ߓꌜ %M,NfTID恵%e\+ScUsf荤EƃT(CBiã$T@5qdk;k6@2 DP!Ju}G-R,§HO4A!%e6n;g:̈^uzGJmh.G, 6݇ba]]/ UDzf,*ú ^;4\Ԕ* ]%ϣhl0yاܑ1N!̡y3R[ޑݢ$JTW/!_fy^Haܱ1&Ypmąa*lߞ'"hɰC6_z~JyɈmNh(x`ht_+{x-I'u=_N7M^5.gק  Smp5}<6DE 3ksbLNNį"#%_ .#ߨ!$GA]г7$sLY@%T-^1 MDx\jzZ߰{5B՚';?/ G v~H8J]峛槈w y[00y͊_*l)ŬVuf:%.mbf\AWݡ"3h%f5u H.w@!fo{S۬UF!EeTdhDμ ^Y4YAsJntYVzևuP^8Yo+bn.$s@Ż` <_͓PRobh\Z8G~M; FMV4?y]2&[mz?WRq`ŘU}P'{$`…[W68>|-趾:\vᮈ F Ec2}t#DO_{|6QԏԜl<,Q<jRtG9sXNQ#ٗDɑ<+9+O6'^Mʰl.Mo{eOPƟۇE2꾿gq7D)>J0_zU_qfuB y6qu>N߰Ɩ1c g*rN~LmIShBh-L"'Ln7c𝍢jFP2ݏG3W~t5-]9a (]#|u:5Dܮ {hhnc_"4k~>O6K׸dQo?W3F%@^J 3e^vG.ކ=ի~o/CiщrCIg9 {ˍzqfWKjVֶqG 'ni}>)A,kYRDXO4r\oBNPR7 a)͒ʢcTl$14YR@^w@~_u-Ɖ Lʈ4OhĘ j*Z0U$ Ϛ%)?3_NINί{ꤊ{gWd{-yh1_tH~HSn2{S$rDsxH\W48ZUC,*{ϲR\,a+C{h g| "v&ze̻+g'NBw6k&$= o{y7F B4xGZ6௯leȨѠaUM˨ZNM]b -ּfESC<(f Fӆyo&ؙZ[chF6~] ȜkL$zL}Ocj=N. VUs%5.YvK$Y&Zb(Cw{GET6鵢hrl+~3xlWL ξn f4Om|WRӏqn?"]U/t:2*W\M|iΒC/oK%|D*N8A^+vZm4KMVzvѺ<\,=NQE(EA c 'JYP/"4Fރ9hP_]|xUz''woHtg]r*QuWfIÈoJk LO%N];  [Z2Q&tyuZKQgKqrw}ED͵)ade|>ǀsZkDswJnC\:7g~IDi#פE~&RvmcTTkԓT8#!sΑŞؒ~L$ n,f >EA%&8BF&Y3FL1ouY'(T.({|e sg}T%ə(;11iUqeٶI\,>IJ9"0* )ԑ SKZr$WԷR=E*R7e7 5X~5}H@UBljMs[0bcG]*.fKqV6 [}K~g-flw%D$y5 !n%3o{kh-nS.<n IAT|ۆ-[Ua'{!H$l"~VѵgdLUEn`S$[[xKg%t vxq!rZWVc>-8cs\q?C+/׮?t8adZrNs*[`L%b =8TNLHcxpHYOt?rjۏ=Pk[a/zI5-Fcn2rk MmXW-=%7en M _rƦiPGL{*O  ˎMtԉR%/kh+c+۷V??kX pJdU2F/&{۰9t_! ƚ9P' # WuL P3@ڭRURLpv9}tO<-_#Sg6'2<̄ô[єK.Y h,()t#([}YpZE/> tCF{_@WGTLmAB2;wMQCTX0tDWu;#l:=y=nY}\n`t$Ư.)2?IvWݢƽF͉fޘ!kaYxÄ́kKzOYlgquZz\J Xجdy4X P|T!`N7M SIC>ge~O.KytYHm{+6>n,~+gPNz^4_}F߫J VH!&ҌCF[dIm`ZS`#J'tYzۭzt"Idg&9|S4t1& h*칯lddهʼnyØsWk0_e[|Jq.3KTvvل@hsބ,=:!Hm Z}'}'FEI[[e飚9 y rl%aʘ{GH!UG36C!rg,hR(P2^IK 69!Ƅ2oMo:86P#\!10Ԥ#d9'*ާh\4*n"`ySG%|{^MR^d9&~QUT'$>L3gnХ>2>(׻G#d{N= g$8C[^ĀⅥP6ԅr0?)!f7;w?=7wBEϽ\fQ`V@^v9 Utn{4D &9 nylJi7[b ц3bêl]5^pL#!#*? ItzbzpDМHHvQ_1q½WJت%X^zfԮMF[O\, ]ٞ}ϙz}U6ږ%I?m9|H0+i:]‰fO߃-cip#Tn:;b+|t2+W*z7Uz|-H)*-q7LЕPހiE_z#}0?2Or 7:V9baE#>oppa g TQ,,"n}xW_Ou1o/xz(ۛBЊf . ˳L=ν:?G5ؒ~Mƌ`Z[nm:MY4Nx5 gD3ڪ//{G)1NXzbY.o;m{K@Ms&bΛR< y/$gt&?wK{yIY-z8F"Gp崁,5g|:^] #`N'OTptBz&#|HoTp/:c~*oJ e"/^KX%'ԅ=r/jCd4C.2t |hIdEU,` "Ֆ_. -js`7ڥ % nٲ)O]ϥ^W::Ezk$EK q W$?Gh^#svev; kRaۼnA* wWctGIc۶`km,IU>d3zoº;X ʎ6tK@8Y Abf)*8TدmXƜ U:[p;C8aU6TJHPZQB/q (q`o ![;QUBv9B}@3?Mm֡G6Y37Oc Y#wQˋjpSPq*W oɟ2+Ğ;7dYYܲ,ֵZ7#*C7ǥȋC-AMr Zp,zvaX|F:p0;eܹi ?8` [cMK  <Zg~rQqB6F`m憣9-+h#U{+^lyԹjo QEj6u{r\.ñ2Fr:ZCn|9>ORr>i p_i17RӳoQݡe%6Oh<=O>rlb1p'`V8fکr$O%2J`a+{IN`soxn&lևYtl:Yz}Hw-C(l|eiG*ih6᭢G9=gDYx?z>qpgrUmFHl?\!KZP+m=6u,)It9 gMzn5a3|ຎԽz֩'p-;g>>N\1iM3Ƅ#ձQ:VϜfF !"4&Sg?Qh F)+)csQ/,_g쾽#139┣-,k`hI nÈAlMo-?)Lc MS]}lOCM'e ISm_%[On4qFJ_Glz ٟC\#IVGs%To 1 >Hƛ&VjPKdNi~@å q>ނn(#=̇ZQXEx1(3{Kxސ x~|-`6NݻT@EkɲQOUZ}݁I?R(rayySofCd=]"}˙,4Pg0>D͘jףVg}0JmnrAƋvDNkM G UmZTNWhǾqӍ"(thL5I!+ vѕ'j/o:mjL5bBK mVCuRoճ0-b:k)t R1 k4~-0GJ+]sq'ěrvWWMa,u9YR+17Qz+h&}~g(nO2鉩]e!2x٧rxBPHEqSs{na=? edHf-|+d>bwf4Ǔ.`)B-)ݿ`5/?Ec)xZW@K`J]o2 [tvi q6]Qlr],H+[޾>Q0$eE`*!E4Uc|tBU.4 0nu6@)Cfb[GڠUn嬑FҢ6 SIQ@GNiܪtozU.Yn D(a-.1.)\J߉P~nUݦ˫o6҅^8Du썾 4+W,I@Epj<(V 9I3g.:˓9'g]MU]Ϝ-.:,c]܋W`yĞ!vlRP%aOR'n9J oXrVdN;vƹ= 㡊ƞsnoE],[*I䖳L~YdTlt},,z؝Egg]՘s+Ka눮]#c7ki8bNS\K\¹ qkyhq[q-ꛢ4O~ǚZPşuυQ#SMKqb8&%(Faf|nи4ѩ7XZ?ڍ~B !f.nN$%0"PGgg@C M5enk,{l\腤wλMa{ء 2ru>'kL}ݳՏ=8/'+(PնE36eD 8|ac MM'DMV(a/o׺Jz104I2t?BwW9?BM~_Wv%8vA_5y|M|<17W.Lv} κVQQ[M𠊝Hk4;:}ި7lhjmD7)C4Z$?H4W xB?PB5EәT&cJ̄).J. 7p7*y2K2Tnz &Н|:\.|b.=&`B%:kGS/+|>m9ۍ>ކ2ԷrsUrp 2eT BRJ#P+cCҎ屉a|,sp,-͛ݺ f^Yb)B\5subpD9D>(«wy,ϲΡԄ+)T^*׺bMW1:iJ V Cr"eRgJgoZ("vc/Whl' 餡&NRIhӡ3F0j=£=5dzMA 1:r}?ڠ9-$o$30(O;aF;6>BjS;\ 8s /z]L)JQ :\|WnV)]0 r[( pI>f0jH~0p0v7X$1D3dP9Z!It$uXSI|nb)5lF<`"hC=x!`[.FsvE6a`ci4$鰡*?;zd^vLI_'G{uH9x5,ю1v:~>/aEكc)9]펤Afg4)vd-,\i!lpT'g]j1AlA\.p0ׁ, O ;ꏎϫ V*ۮf`H䯗kTmd|>w$MT'G nJ2twNC^<Ů\yw\Qr]8aBˊԛ"#eNv{uhG}"L;;f} iJW-?z2ʚK2π5a{9]qM ׾N32cTEG*OE uRkDg'Jxendstream endobj 879 0 obj << /Filter /FlateDecode /Length1 2469 /Length2 17229 /Length3 0 /Length 18661 >> stream xڌP c {g!;w oιszYw( ubbcf)XY9YYّANȑ4 -?,NPl uqظxYY쬬|1;č]@ff,L%swYX:A#֔;@25(;Ym Mj`SB Z:9񳰸282,>1\ANU#h2@ojTuKj`s'Wc "m!.ζf@$;@MFd nW Ʀ`;c[wd (I3;91m24vC]A&K7H! d#_a m5mO4ݝ߇jd53-(#obee`@7SKV%p!4 s   2 d0ZlDwX!`翟!fvcꪪ0`7''xoƠx2`߿(@z. / 3(! O\_lWoWI:[[do 4;;A6C k:+@6W+d [ 6( r)L-$5 vuXYr!w#V!%lMf;72_\\O6Ȏm - :Rn._!n`x,E⿈"X v?OS  H>"^H>?AdP8,$FKc?JHz?B3|ÊMzM L֐C/͟>? $%OH/3de@aR91R1eDH,,@! a -!˟\W[CS ?j?jH0;g?o 'j;G!; N@3bHQ6H ]A.#o-ގƎ)O;cpurAr;0iBCBBfH$ÿ*m U h46 ~W-Bʴ7ajO+sɡ!*#`F$qsuGZx!5^0Vuj yqX ׳gNY{g^t<;^)ҕ=*n9iHOET&sNL0fof'^dcO"9ynGy; $%|{=:E)3I`0bB+3hH') 6(w[v*Rƞ}1!TRsa`mK4ܵi턞ǰ66js7<>}72_8iu -Kj0_p=z4['Lp`7Yƞà1d߽]1j<S92,}4zoPp0Ycd-0k0i.A!}cFƩs"eP9ޠE'aZ}6o UԫȠ}PM+:#6#ۇmQ%>)3]nU!5Zz3P {s|$mA=SV̆9#d kGwC3 M3n6s:ɸOVјpc=Yxq df TuXzML2UdXRk x6?H];+{YI<:#)#G_GdUQI=Y j-&Bz]%]woէ}-\F=kn%FT{Vn$N=Z:uvYU')-k/pr~D}UjXI ;J?doFa Ԡ9%tQ%^Sg%e8 NwfE93~e n,eEu ~MĢ# Qg}:)yXs–$10ݴ'6GFԓ_+i*Ĕy]h`ACfz{#0'SlS5NJ!&n:4G\l:طMqƸF>ݍ3ɖroE3-Y= ;(|,68}])xDՎix_/F'{JVg"[cOq t%-̆G9^zIFVLc5x7!Ql#2;Ȑ06nOBhaLzRT"&Q9|F(LjL2 t狶%͇XSFP346Ph0gh>fceHl*+2+ SbWE)t>gIW2ͭquqibXQEv_ !Ŵ+v2w^a &CZ\׶xן%p4{Fݨ2e_ֻyXcqQ=9Fk7;)~7 kbR tpe:l-7e_s4:ʋYNި#SQx3:ݤp\%f9 HCsZz̶hLFLoJ?ymou{. ;6 +$t\uY<Κ0#O}{ۓZ;0;vw# lj~rP'Ig"o'v PF0/3 h:]Eb5~᨟:]'D;xċ03E*\# Wyh$e[AGًG@O3oHC8h(>׋o1}فJ  }K()=+l/xH}dћ<~|JNz^\[_y6RHڿGy&{-Iɾz4eХ 0^Yݯ9](ȳY%osIG*ǗTup7&Wj6. W>Y-XN叛F`"1-Cth s>r΃nR&O̮ZA`HD?kD3Gxb>*N7M0hL?Ky]Ə'<'c=eP4M0!͊liZe/K%) |-zHMd}hFE߂7eݨr#a#jIwzOڳ/D2uh HAy7,OPa{O]= bM !M׌V~˜cGE/~BGcS;R3{sEC+ȈzpMD,};UlIIJnV&Yf̴]ge$0TvW}?z1.{č;os+Zs˝WŞ'JM`y4??)iw}_ѱJŠ=LҊ||#wfe$a;&4{Z"9 a 7>Ȓ_>TKAl56LNx>0c|{@rzV~:Ip+uK]Q%Yb&9lJLPtEui6 XQ%|29Gsy-Jݛ% Zs% stw)I6Je/t4/FyO~u=ÛgQ¡K7)UB'9h17mvoBYdyb797|7 udž}UF Qg;9qn(6]̏z̒D-& fL?+ C-"tyTiW-aFP|’Sd۟Z".uIU63yq1cTcB\aR-oi%*/6)L-:ahRZiHx?dL'8^+<8j ߑ BAp4paۊOQӛ~H˹5 Oa&x]UJ4xCOo%fi޽Bv3}i~Hgox)rMԧ(T\ƭ,nh'cNО}417@!&3D2Kf.S$qW8h*#Bǘ'dZ~ٰ`Iuk˭V:`_[GAN//cV$LUy A3HVKz/ m(i\)4N?z4Fݓ:)ՠ^bjքd;{cE9焉:J\p`Z3x MA0e+ڱ^f'mlV$*z3*⻫kB;:FTh(>@%O _q߇ ~uus@![`/xfMZd;k28%Ӊ̣{nߝ~YΉ-+PW)IV[P3';V<%X6 )qmw6+%$a fi熯Uv "\^۶UE*pqL-CVcԻInj1y7^=<ؿC.e^i, {|ܔ g6utG)(q̛xH6ZGv?C82hԃ^<>nw|qD\gѳ%2ѻ 6gخ+WcJA)RP 4-cfG[/X--E5٭C:W\"N,%>lUא |!,=/?J_0 04~_9zGyй=rBތq8GbssŚx? ?!2N}M^{Vƈlb>"BZ1uT[0`X4n老W-9r^(k!UT5~Üs \S` Y` 4AP3cf9zǦTK+Ǣz ROrFT5G!QYK%φ\2$ն.֔^V{vd7)Jh]Azߗs`gQ(6UL~k i '\aOL*ke54CcX>̇iaGYArB6j.u,,/s 2Bg`N z_賈h4ołf([Բ5 VPqN5Qm pI;02P̥ g}6 !88p<ʘScyHFI6%{8T`|[4Dˢ+% Vo3}],< J W#YCѪMRˢYC^Tr!ˉNNy򁳃t΄B9dcO\̾F u%G\\Wj;!2}hy̼^}м`xnU0IeKWAU1"+B(Kr0E lLYVqjQ mx?0쬄qdt(Ec!w솗7U4۲VȊq bb1J.u"B|:gCf=qFom3 } qdkn20S:ݔŰ17ztN=Uy ܮ6oz_>A]$ NA:6Sd85PNjg?fa])5iѿOS:RC:f;3&h  X5x5q+YF2ړm%X$,eCnA)V m 6<>׆ m-)|7#vE!K¸KzK= 5\4Be̩RzAx%?ܚe R_ Ah1Fs~zy(>MXT+_-=E8azL LYB~K:FU=̌E)rNCCHaC.52#OWQgq;v,9Ws@(D362F5M?Iյ[XRBN\7^bA=2__smc R[ <{$pH`FyDwi9 qywcO(A}/yaQ/ob|o{%jLQ4?^*e]p5^ؼ Iv"=n-haqXۉ,Ccx/n"u}"hn=%szvp%֖ojѩn_NNi(K~P؂}LY)n~MRd꺼HTW]OEmvDdzC&@Qh#Y1R߾jڙx; hqTs99)}ga,ͶFFQP#ot$ :v;S A#lGӐ~"֗ Ҧf#Ϝ[NyNrfo/5'vvm_os=۲an-Ndqr|>a{zk`ޅ*SL_(s{#fףbB׿}x¤n3'%!#$Yr'm75*ș) jkG0,OܟO JU;5)88?kTf)iS}~Ag!}]Y zr{r .}!dVe%YԹ #;調+CH߰LX &`z~T-F* uX| l',n[|=G }DprOAt5ɉi<,Ā;q.f926:I ?7MhcQ`|X01I9q+ӆSAstXEuhA;܈8ke.(hM1a MF6˽eevoHRI}jF1277m,ٺ3~oS`wNEI]p}'fVnP^ ndy% !0ɔ*h՜1zh(DܠhdKƑp C4e"ͪa* c!(Dʀ øXp ; VnsP.9 }YZzH>t D]y Նϥ_Nʘ}%rѯ5ƌ. 0 5`KA@gWYXz|:V,¢a#Ж&$4w7Zm8=1?'H˙ğc1OKߋuɪnR|S+sM܌w2nN@gi*nPQ5 bYzc"=!= 1J:`N8LLun }ݬI2]/)xRKzWx0h:YP[x7[ʶ|/~d PZp:%-WA]MOENpꍀ /Rm.Քͻaq\T8@x ,O0ìRIp4$As%D2kŪT_qok iV7ev6imrƑ~*v}Q"Nû>xvg9Ҷ`.)~yV4#ht4eGɴE/.g~A _iž:iyT58ɔGUh# OZGOQZ6&R^8(O{ZT-eԗ" dfA8Ha'Vor>>MvD7&Wֿ BwvE-{T R3ڈlp8c͒[IYڛ[ِv;%6Z/֞uh;wj=2xg)\s~_~hjfWӀ*& *,#G +Pw{޷H~?#QI_Z$woaI^#xg7hfu=֪^%|"Lqw >e}Y0UbJDQILzhxyyYe B);k5~#Rr3gD,YݱNi>"-\meQ+TOZM#`}EF吞V 3R[~ ayM vn=k-w&=="zKe?͙`; [2G 1w{&"R]7?hKe[?}n!w'/8yS*0 OAvN;0mWQ{֏Em$<ݺ4x82w x`|+&QDyyu$CCK:އYWoVlh=;U$uI`zb [Qb_4zp9ΙAAp[&Ju?K[V\>bSg4qIl\KB/{>2ožll,:[!.:= S-hiSUbxWݝ.`nx^bo`~^:w€arǽqwtmLm}[ ~†FuZ^yZ0Vږŏ_d# vQm f Vmy"π @+31 xKY77 4~$PJ΂`0Z= SmQP-oD&wDAU Bb.׺>J s'~_Qvޕ ?)΄u\]͎#4Pι?^(] 7G״J_E8^'ܦ߃7@E̬ϻ4Ā!][ujs`m>߾hX+1!ʁ$ө Ю'{B#լIMl+B)+ˑ Mˀ^,:4͒@gO>@hk9 gW}fY>%TsG_X"U3/y9Jhbu4T:b#zÏƗOk ӣGSbL+B2D9ttT6@nQ mTGž6lA+N7 9뾒ŝ !nBRlJ~ev'"dj?UbhQr{PƩ^^iVGoۢsgc [~>d9>S| a$AEKQhrҹD#(UzKt=y u:0U:9@=L}%$jܷ E3 5˺"čgN]4=hN- cQ2#፱(Mo<UMA-Rv;a\ ӟ[%R-Ǘd&sHd]pܟ+fu ;95p , LZ7XrY*; R:zO;+իh3TޏO )N!E?XZ|ur%Hc_L{ܿOLWYL'A]+@mOlxmsp`*eY$rťt֤Md_:GxZ\$Q'4HͲښ2|Ő1^=EҦ``5xN5LQKا/7]nlK5 SWxr\"/egp⩍)Fu%m6 ~Z.6ׇ3U PVM빁4/mThk6-}z-\rdhЫbqfǪz';l*WP8K 1Uf{A;okzb' %2k37FI;߽ˉ7u<[UF~g,ԇ)n9Vu⼈;QftGM1fVWM6Q %ȿ& t5fv=ϭ7>fZ1=p$gX ڭݿCJǘpLxLΪ ZL1mrFU 8 y-Q?:/.Azw1F[n $"E<2$?_7h8̻@W%2թ%<њ<3 %T2_CLf4ں'9#ق'ya>SSje͘Y +)wڢtyaI%;턿q=628۫v ZgȮ>_Y<}-mké远`,ybxu$5J+H+Y:NR7{#cVVN]M Vڏ,hFV脤M)MxN맱XOy_Iw1P?a>k:9$YAbz lwR[EY%%1LQUn~`gש^< ~9a( {Ay }IᗩG`NQ~ߒ)cGKY/[ j$)MQJ6(ɚFz_ݚ0_<]x-#4S^I½]a"fA+ #dz6S7v3p#d(2Q$~)-[%we̓zX£PMU4g^ 3BG!Cx0+]zJ6ۓV&pz Y O}ѝu2j[W|2󆯵^ń"?rG I7-DJJ!sd}ՄÏDDRbV# ES?a1q+-ߚ#uKY?c{C1M?e9[S^PuRp(ODNl'Zk!8IC/e&x_Mfq_9%(?0Wv#8\3rpe^Npkܚ( 1k )ܾn+C5ɴ ooX9B\Pml7 Tdvp?![^e}t<`U7ռ-@K ;OrV2;G+Ѐ*nĒ5):? c~ꜰeJO$ X' Ϙsn(K2R Ͷ 10Q}`ۗkΝb-ȁxl3Jh)NdF$7$oCkss|OrQԑؒroDo(Yd#~7;\jO{ڶ̗X{}s襓͙- .W gۮR2tQ5V 'Y n?Uey7{c4zxy ݯw#!-t0Ik8/tjs?bq1,Z^5qc -z+o=kۙeUa0Y#;4Y_3MI~Aͤolrc G(۠x^yUJavaAЦ e\0FOoo1N}F#[ӎm*cPKrdnו뵏gpScSR"q\J5Ta*O/!D! @I;R/Bo2"F9pjhU;"6wv-%<gOŮcτ +9vtv(}*YTNĉw}>*oѓ 9ݘ#Xbb'\ j)gB//d˹ e/Zɶ\!y)p{GYصmrwG1w"T:e'n0g eɰrLyaC[x([5Epj]FvT!]\(Դo)Hr>nTbŽS^zE OM}@hHO=@Kݓ\V63wOI_O5ψY!؂3xFk2j1l4*2=P\6US_5P?{=s/!ړa4cs, n-"l$kdܚ.u^4# AJ_Ӈ;> > qf2bьғI,-ݟyx2VB"_*jkhBch;mi |~u9f,Gd.wT{͝$mSpϾ?k+~Gq@f`lT\ v%cZG{V_־~ t5 LX:,Y in@Xyj(IyOѕ 7>9%8/W{[P5!wg"a-1fjV rhkws-!Nun( 7߬T=_y8q5xP{q+]wɵ"P[j^Y; Tj̪yܙchBCȴ?LkT 1@<~5}Uqx\}X{ C>ڬbNlůri.iQfALژ.</Py_Y7BBƇ;PQۘ5ܣ϶w'p@սI)!5`4A'TF&lnqU "%8*Mea%g<Kkۓ|}] AxPH ZeRvieTyHV{pi2F4UV8&~@T%ۓ6Dօ<P*`}npƥ?CRsf) o!Z }7*@Hʈ8ɤwl֎Q֯(H~js侀{Ş%DcXXW !Ys2^r?3U&e-t)w awV@>Ҍ*\С>CO=sn%AX\kB2|` P,?;xmT#̸ z_gEK@gwMa|hNID]&o%dH\eQYbn= FA2 {? P/uZ-+vуrb%[EJ7=j[Y\gAgs{\B?$"(`c[d3ޖ(^0_|dmP2H)'TfEn7&*Z'KLPd7@P@B=]m\{Ҍ㏅%m,$Úmw On-0cmmÚDԳ@Ǡ\~dBWیp? ?(Ee.tyl3Bz_&;}4`Y`M L{BiecjnZ1> stream xmwuTk5R5t 30 2tJ ]t4 HJIy}}׻ַ~>g?g=k8X5'TD@DPX`a/",##PCAAh,  " !!=Q0W4ۉo`A`0 G>9>}G( ]g P3Zih5 P>`8 s"<g$ '8!_x EsF!=*u5!S5iiGeN("U? sBPH/ߴH?0Ax@}pACQ}$B Ŀ, C s@0o X oϽC!0s$?G􍍁f|-euCL  ? >lZ῾#e"Dbqq hBA 3˿ߋAfNrn!E|㣎f|"s#G6^WS|_0I(Jy85nᲘ%jڨ6Ϝ(ݭ*Us,k'_y5?u̴M{G>tFrAZX5TIfuYx*h6h'gg~ʧd(MK~ 2@4KZ*,bfIvjA:7"I쮿eW3}ݔ0`o~ϔiRm.*2ua-ɗ!FYicD'jz>+dDBKx|'V6_x_w'ȽiB&Jw'M* {b#"߼p7)T)M¹hkXw6=Y,* ׷]ٌq or>+'~\"&3P"><_{3z `<,G/oM >+f4h,h3Ʈ V=6dEMo1dnhe>/ȍrf SN`f]ȃ)%IFڪڕEi,n]t!T>sffVx]ͭ](pxu8^\Efa }0iOO nMl: 9]%iL #ǥdOxԓ4Vu|K* eOtn>ʿ1ډ6fWqiڄ︯OBٛn0?tZUc7$GdXP*=kDɠyBe/r-r8wlt9*[ /{#NI53~rݡ0&xͮ >،}*6qDg%ҿG@j3KC 'eԩ 6짹3 '0wτ-}0|KH)'QAɸ nGCK=vrȐ޷?6j `#i9Iݝ“0u ^iV)g=qAp-`j*ǔAoS5ѝۆ>F:!jkTOTwq7OS7KD]a =Hh"xS#%o~+#+R:иa T<.l3_|V{{4.9jV Q^C)}RWG͖ P$a6]mM_42TUjj͆m~KNT]16RR q->hlsFcs~ ~OAɳ<z*}oLsGKa[@h;U1o9Uxqeb~gf/^$@:W=CZ J";K 8 EAgzE.M/1!ݑmН=<2+gեrPɛQh4c|& Ͼ'|aׇeޤ/ZEԌYk>!wn?Zʡ9l e/2@g;?z2$铵ЦO4~C.iJؔrIkRDP4*PWw+TO8!CՓ$S&O,o]ULUh2v͐N9Ռs&вĭMhc&WwڌRlu'~p晻 1g2p˒>(+4v$ pie`"!\3okWɥUT|NS?j K&?Rf ߠIeS[b[}{\w_SG'!Q31~XWΪwqjV cOtg[}i*`Aw9nd!.b :pr3oX!S1Qyez1H1;ۗ3>NN+ᭆld 6Ufi YB3VMZⷀga%ڵwL^O88 xP̷w-7;kKj},cv&ub:qD{qӦ95"  \YH${#)s`AXKn6Kݝ;c804rdYA74MAѡQ]$AJ'ݸ!􄕝M[KXeI͉tE"Tr}~is :u<1x=CmVyn25:A7|%55@x=dǍH>`ϱvBA}csoTur>KmY0s0G\ K-o9evVb*>䢻pKrZAf,LF ݄IՖ4;S)!Q޼񣮍@X=ah>c`"](umX^A"1Y2%L@ z߯wMK'ԎP&+b QLK /pb1Kk^1aaO145gZS瞍Q:Lc7slT6 Ҁ,1k3;KY6PvŷJY,L] D^\}K*̍bWQp [GCYgm9U2sd% FO;P/w wo"6{^Bgʨ$e%XP<֦mx4;5 ɱJռHg?:S0k.O=Œ7&I} +1{]o}yHwwK: wlyzMtg؏jx6[݆)Qƾ5-JzVansf8Gfϥaos/Q=e}ւc1T1˨ ߏ1`hWg@FLuyn %T]|,J9? -fZY0$atӫMG7<MNX2 +t0jАUU@5%)r`%6.tY29=E/wlaE ӤY&(Zuj>Y"l_я 1b}Tϓ)Ks,И nUoDnJTl~H 7z2UaӬm'a^kn~Yz?#4n.E/zMGR^Od,JJZΊ؉C-ا H5wk?\sutVrlm ;gפj 8߅}@9 (]jG2Ucًq|*1YݾfdE5läkFZ{1mDɝWjs3Ud4f5rv_JJi ď/<7ewt$|x >n{Ł#٥ 2?Z_iy\q^(P'6Х{+a8sY|:0Lx@ p}l^4)dh>`6A<3]oVŊ}%+ӟ=y[0 ." 3M-IY)^߫G{|+q"IbYLpp @Z-^: %4d L߉mcדm*}r<KwZ*_{f=uF\e&G'WfE ;R(nkK=$J0}]BuU~ ἅuֵiU;r .COvIM=*GE+ xOW-n"~_{z ?7 :Oԍ>~ZMMف9H~+yo* ƒ0n;)o.B춬u^# 8P˶8':wDO*3~6U'gs)>hN.{4|~Nc0FVhՎh&NB MٻȚl.cg+U1C,44#'`Lk)u*T/MFeIu:i8HQV$ 'ށOI@eBEwK2G?Z}N!V5W{ٟrf(Cm%ɧ Q v o%5akeO(kR![{Ma`s4s~L鲲>YQmyq3F6˒>v?eoJ]kfdU5  `7&b]rBYOm_Kv_Y}~7fŖ'‘Y S69v2~hu"^nRSm]7ٔ|޵ *Օ?ڱyg&mb|u_&> ӣfDt6rW\{t9Iܐt̺u_Uo nbVsnG թ9 C0]_ !<=ۼ a:q1aa7 T{Ү(kF3 2J,B*Kn> 3䑆Z-ZSGFJSendstream endobj 881 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 882 0 obj << /BBox [ 0 0 864 360 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-bundesligafig.pdf) /PTEX.InfoDict 478 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 482 0 R >> /ExtGState << >> /Font << /F1 479 0 R /F2 480 0 R /F3 481 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 2369 >> stream x\Ko6> #2&$9dlld[ŗVwDb*I#;&G+x۷^)&gϿqs%3<&eO7'7SZ\ͨZ^¯T6ߛnҁ oʃ=-Zqh}3׃dQniJ nۻTo7&/ Mt*#yQwM=Bs9G٠"XڃCql#xڳص:QNQGY(8)V6-pUiN[fyzZ,USZ(ꕂm|YU#ćG+yJ _Q2G\|~y=N=dJؗwT^pmoemޱ jcJ,+ ʮGeXv/%L*lEgsO%} 4t ի>HLL;% {WQ͞czL.꡾jOV}zbO5fWo5SJdz=u OI e!WHNI ~M4ύ'*B @N|A țJȐR_]or=y(1^J޿iqZQPS\u!Rxͅz@ұv'[}zhb13@X+U@NAAxy3A-Yإ>)-N MƥcXN]]F!%Obׂ̈$~v{=}%C{3`#KyQ>@`x-W Hxgܝ W김./eU|z䉆dYYOxc%Ǟ+ײ)"ul{tr ݞ8,Z=ETxO [K'ʏ{\_\|8ύհ͂,+͂^ZPh3q') ١%8\ő8zQ (d@P ŝ#+2'L2NWSf$xd䎕ïbԞ?GdbFa3=/_g|| TkDO)dTO)tdS}Ҵ| H>.jZI+%/endstream endobj 883 0 obj << /Filter /FlateDecode /Length 1447 >> stream xڍW[oF~@G:.VԨMsU۪ \^;3; cUD~sf'ETBz'/^dQo}%_o3rɴ8!ĴүP)eqi{mkX%3=/c!եߟ ID"̫"J1Q5!޸ǩc,-#e8-s #k_?Va$d7$NFoQǁ7j@j{|hU>S`RIϣbaiRRHd[XITQ3$Lo H9$eQF?ӒLMLc\% *o|=D`Wh4ݱ3+R-^6Nomۇ"ǎa9cop wIzv5%IG=3`l92&.7׷n"RyP EЙX -Ʉ5WqMj<[Kʱ %H8ނ1z;'t2rbUφƝkD·w09CJW|g 7>w vEH`}Xx>5 _G1endstream endobj 884 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2686 >> stream xZKlHH%'2mK F5y RC>@NEzK- 80"(s FHmFD+A"ZTR%Z=҄-z:T?̌T*@;3}> ku 5Mey' Ȳ<00( I4-(BbUUpyEQc;ih#kco=ƝTVevv@&innyIcǎJ,mdr󜩩)Oت{˜JK{J#Zp]DіqU߷Zasd8. P?4իDٳ]]]Կ  I* ^(VW>7xWEF}>ߎ2ƜNٳg͓B')͍D1&Ib_}c݇l,MM8zm ߶fw8TSzm&'%I" Z?x]l^hvb<<oll<}F2Oo/LU YX_ 5_$Ju=@ץ ~cF~qQ_^;t?/fX,sqvtt曏h^.r /,Kgە`m ?~u]oFӴeaPuw~?l^÷zk'9tЮ˴l^ լ ;;;wқ=$IQEMN,L#(WXR&ӝBŋrRieeSSS" ϖȷI.i>%vd0$l}2dѬpU`h9+s,÷nݢ$7d/w4ϫeY yR?90+nN+jՖ;2WK{cdf2dYQý(CU>M&.f9ӝ<'H\.;99i|]9?/)ϒcLjF$ 8D)2eoWW[477->[ɡޡ!0rI{EbsH;V>{\Gz 9V5LK@ Ţv:EpH\-, '3Gd7S7As32,,@p&nfvt:U^W5flaϷimmZDéTl6ITx{RSsWgg ?i*ēey9˵ M^wg0uAJPp$bCC2bqbY+NLFϜ9% zrz=77n<@1?h;dώsU*X֢>85FÛogEQO4W:2ZZZ~^5 Cd2)ĵkz!AqTĄ ~?lkk(. s8d0APUfMLLB@MREMzsgoMW؇d)'F;::$tz1hIDoEQKu0CCC?97M$IFvoQOAUUj $=|,zzz.]d2zzz4McLhi1m|ȶj|+˻>*0w`l19|V))$SirH13%Z4GQ:#-@x-Bn0/:9 }ffiHШsՂy^C9<>MaΰQgX3}> ku:GaΰQgX3}> ku:Gadzendstream endobj 885 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 886 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-arthritisfig.pdf) /PTEX.InfoDict 487 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 490 0 R >> /ExtGState << >> /Font << /F2 488 0 R /F3 489 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 714 >> stream xVMo0 W]Zl ߂KlGMM$E6MROA8{]|;p9u!'RF EK@i K.ٲgJo|1Ϲ2©əyMBL͚IފI L09|[轙gSLAmp㾈(.zI9>.Ngzw$0@zAI sP8By_|*#[ M-w!p=tBj=<ťF/% j,@(P޵49akZX}nZ}cEE-Rko,>hhuf" DF#jNqJ'! jZ/k(Zs%u]Uy4? {ta<>;쩂{,+hR|hDOq'G˩ʝ|Ot*%s|ס>J[1\ZGAM-HJ?@MVI^[ (qoaC"r$ݯ]֓eZۗ緁`FqE5!xe8;|6)ێ!b?&q_j6~,s:\Q+a%rA\)49x9?2/!dŔkă_Jbkendstream endobj 887 0 obj << /Filter /FlateDecode /Length 337 >> stream xڍR;O0+ntw~ Fi#JP}F#dj +)+kz|NwN,޳\)ߊ8^|%eB}H ,1/ΰdJ%EQj7^1_jFNA mRXҰ'CQ4!L  NZٳRYVR(Ua\>`'MkxE,΋Y#LQ$@n= m Tc*QG7FnO}8]; =aB]fL)ϷwwA1sendstream endobj 888 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 881 >> stream xOAB0Fm/Pum!C!~?d2 C!C!~?dohkOMMr9l333WpQ-BPZ $ϫD~‚(ttd.0_ӨW|6#[8?{g...zYH~Wl`vkfTxW$IeH)1XLH{?Fc.(2fB ,3x(@ 04e* Ѩ"!pppxj5g"[-xޞh4TUewBɎ>ytxUO=cȬ~Ohyx^miZsss<>97C2C/I+-]ڵ K61\YYR  `eywK_:99)NaRQ9iӗ[V(J$>aTNҮ>dg'wy$vg?}7ӿC!C!~.3dYgf<UUEio$ITpd>zj> 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 890 0 obj << /Filter /FlateDecode /Length 3636 >> stream xZY~_!%`E/`x'y8Œ(_P3:@fD꯾ro^՗ohVfծ.Zfs}/&htP;5ƘwxoK]cn|8O8ƫRgV+ W¸*Bnr;[+=lX|n Ք-lMam]@x]8G`7ğwÿ=| oS*V8ן\56=t*.mk=ZOBqj@];TcܴҦ*j}=UCY( ;k&+CJQSԪpRSkX* ^)e5)7MEu65T*4tZnGۆi|ׁJV Q4h7>` ʽGcX$ JepOQ=m>w8"xc5Y*zޜB5 1[ؖJ]a_DVҬf?5wnK{Vja8n/|-A>lF;ϴYͺyBM>I +ڽ"Ft5b(0/m|*@؅PYB x|;h t hm)" "kb 4Pl'½ X [D( BQ >=[ʌf͉wҌ{@Wˋt=\OZL*Z(Ӳ!"* 0KR-| aOHz!J-ړkQUAЪ[s3Y@ EB,jnTVmM0]d3x>wlWT{ }~8KG4ǴSV9X-rV ϲbA\!=Lp Sd=/8ZF{Mby1KUhk>^jp$OՁd({6cфRΉe@#?=3Q} _0BV$b<"Ԑ KB먵. i(j3A#3%0MHrX6k33C0K,9W‰~Pi>"`>OoKS[-lk;6HYKr n Ԏzddcn|8c]uD3x 0Bjƅ&@3VWo&VX5וV4 ׿$ZW)r:};[:$ Cˉ3z҃82Fd578IA" dybBjU̴!} & W~$RYb',Ҵ/FB0:=ܠ)9*l."<_Dg1\{9ox=cH{tt$},p?(, >7mH8۱ ;K|d,cg΁*#6Hb%ȯM[J%Sm.{>@R] TٚOG][ %nOFSOCUamgOcvoJ̘K FpMicGO'0tfnj) \() n(LoXS^)123R2>vį٩R4%OYWNeY&6 N/%:7~/'RR~%(B<А;tEXI7C#r_xzۜ5zQۈ^Wཟ@z'ILh $#ī3ZI,!޽ 9QB>᳹"XtIf.{"RMDO\Y3tQ6cr'x4D4ǽ?|×_fTb ~ykpv+ztG϶,aL1]]A+&{: :@=}!b@Ki:>p~Z$f%CNck~{ueEL&9F^HBғ J?27B"Ŵgu};K*?@u/txbsؒzi&)4%^_2KB^XS_׉| |şIR2ʒ Qm\D>9J yBP7CFt֜1d*˥ӕ.r vM{!!NR O'/?jL?!EL?$ aH$}Jg^]᥊ۑ zGj*W ?0L9ԗWoI|endstream endobj 891 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3126 >> stream x[k?uf/jhQOq1JfvV Y.JM6uy.PT8wdҌ-~5XY[WWwι/ CkJ\\8]pzO;}ӍK)Rryj׻}v\RQ"J4R'曖e !^4z6E4^2]*_\׽u/cJ)۶}mmM)߯_W,RJ˲.tÅ?pa/4- CHv0fL&{ޞ8iJy>裏>u떔2 C̳im|eYN#\.Ilnnh4>?|I^W^9::VeYVVB  !ǕRQ }^#I\ǽB[*-! 8::xM硔Rj޽yQP*6 ױ[qr`0(JyH F'lZ|~0 69<ۋri&_bB4ma(jiBT677N'Lc]04MJyp8$NfR=Z\\uظy&øKJ믿"ab0=|C+m!>f-˂ixAP*B?=+4o' !.3r:`WWW1 ssє1)FJaa9::Bafz\XXT*eA&!=*RV{V:pss d2LDQu]ӴӶ0{oi`?Vwn&!"\m#2h61h~- j|L`R*p1a0]{KÖJ)8p0""L)%}=®it]#N$pAt])18tZaY'Vd4=)=I6><jݿm`,>n>b%|G|s,Q\bYVRY^^]]]U#sooo`XmNbubxHDf𔈢q`^rD΀X!D^OR@"^^^Ye7"0rg`a z,lE?BRJ4pnimDyTZdg-.."un?~XAZ^oggJlJ70Q #)/( W艫:aL0 'O]ZZj4---ep믇a8 [VXl4bNٳpxΝNS(RT2$hΟ٬aZ- !8C1^o8ah&F^M)Z¤N|  !X<{9cq񹿿 LPv.B'!!>뇧%w"o]pad*bC`u*JX\tYB Np%g~:GoqӘRb3PB)%(^\DBayyѪA0_f0$"4B׍~/](q;u]2" Ð{43 @KǢ}6(BcdSTT,/ ,r (3J@ Ȯ4bv֐2y5݄b #R+++A0>D_(L9`(nBh+R>xsF͕c4rLL%{6յ9L"n'H$>} RO*ҭ{Hj?UaL."݊*O4ƞ{Qt4i,uFhb nmmhO&A  J3ά#jx "< Zи4>M/4CD}(G dqأûT  p1炿lf24JtΓ!m!h/JX"g 0UhS`HDBj{뭷0F'-08S Q3 b@d;PvԔG۶x<RoGgoUj,4.OJ3zK0 sDc#+2Q ȘȸZ޼y CB*C8?>VgF.v*r g`amC(p#u;96ObKp2~ͤgf[h$IXD*v=uGlꫯao nmmYr9zm۾ sxCiH.EQ98£fTi)!f2l&.'bi%p4|FRrRw?jt-G;}gw84;>˧endstream endobj 892 0 obj << /Filter /FlateDecode /Length 2386 >> stream xZY#~_!I­: 6aza1iŔRK.4;z+W-Cct=Żo;p5alId= t? tޯû'/u G3D0 aФQeσaM"+ȗ4۳|I* y4"NυJV'{.[ak'tM(`ztE\—/a+L {3<"z2xL&%KLLjM@+y^ e\J\]e.]G X y#_>ÚiE;~V HpFgc2wWVc&ؐ {|37_nv*33<4SDLv9/{'-?Cui M@"x Kmkʂ@ōJj>/!|%p!^mըo$8YZęwlXsIRx80'kNX`+dw@'8X8ߊOjlaڅLH_!2`->d`TˍhU4asS'74Z*iKǞeи 3]BQ+ETgX7vcNLF4ba!j 8DSK@"!M3k ~7NB&s#cu|=t8?`w2hzkLAIxG`]x^RW بbbL{8Sgy*_"tB WdLyV͠HJ < D;PQejIJ5۞`LHY7I'aPVe`CٝKҵ3qTd{=%I۫5!a䉆LݓΌ1ΠHN(j!EfpY)|mi[W n^RX6xƝʆE`+`oo b]:h$Pm(7__LtʤTLJ(hX+&+4Yc75%ۓryZv"˒7˗8!|fmʣ#ԜR-JZAdBI OtVtdr&ԜKr(J!kL /]PS.oGq8"T(,y%"f?x*)қytmYODwvK#(Wŷi .磾b*t\1bU"r5Byx m?rkoHWyYGV={:[ ?W3K)0t9NN25o_ =bbn4aAIKu\ZˉD^K$נ*4BrJ[OO>!Ha-'HRlQnIe@s:$e}l`(3`r-9]ܜfFǭ ;u6)ǧAE@Q"*ہθQ8+R;`6ϕq8vkB?{Pendstream endobj 893 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2514 >> stream x\OK]?OI2I-lY<, ү|~JwE[n,NH0Cjɻ5FͿ&ĜL{{=zN# ^a1c "LRJ)D=Je2^1چFÉOx-RJq* ~uu]׵m;R HP(dDdfRݽsQ6jDd6ZfY)mmmݿ?Ja=naeBKq2T*Zοˇmh驔2GQ0/^s]?4QE)hJ%4C Ӑ`"C*Ed2DSU]4 䓔RQ&b,̷l6@L0d'=Z`0t]q}i(douRtttluql4Rfr( Z ߣ?)7-uv7KaLNNR#msss KqDhapopȅp"75r||,1:Sg ~?EB34Bض =ݨ(ʫWjR]zrr255.JEYvQ"kd*Sm[imv4M:*LӄHDpE`0XA^1-""_V#X,i֭[pxuu/B,MvH( ܗ4Kx<#"|r@=Y1:F1#|v֥`!0Zc.BUU8`TUU-کaO< 1lPJ4h4j&/,|a[hn=Q0ښwc¥T_?f*0p ; 7:k+Co/4d+>>BCunwY]޲s鍿MpDs/pd 1 ݻw>|X^^NhW + Nb~Wp ðmz8ۇ>k6UU߿\.o9T;~Ëb8n Q8#KAAse,iFD.i.ynHi@7"i]%v;:;ztMRk44mVXL!\\\ _vwwݻND" 84WVV5 " b hAM  eE๶S Ɇb+,s˲jZ8R !="riC#>{<`k i6\J?G!D y#kMQ0O,m fƲtj[_|4ms~C!`Oۇ#V̊\.CD8r BpS7֎zIv4Dhww`5B$,S:mFOӴj{Z(!}>_.0blqHnЗXmܣn?cǒfa"> /ExtGState << >> /Font << /F1 510 0 R /F2 511 0 R /F3 512 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 3188 >> stream x][o~ׯG/Q vJMҟrn,9KCp~+9};]zzJBݛ᪷WJNϧ+ ﮴ϠtWE31^k.HD7o%Xq s?Yi$rqo_L7ۛ4:RǗ~|uFZ뤰s4VL9L'/g'ѹ=K){RlV!Q$-6P¤)+ڬ[#,C(I$`YqT\SXz?(] 0l<:Yפポm~Yn-NJl-)uRAcF9̙YIU&1Ƅ臫RLVO)9ETP=YɅYKsd%og.b,I qY\3b[K1*+HUۈAQp:EA Xxd0*8¨TadshcnNة8*YgLbp> KflАig^іmD ,V-0ts +_$rQ,م3d~D +;Na{ʤNMdеw?A|E b@" a`DpAw.jLzj/|ABr0}|1Zx?N7ߢӨt>,K)/ޭRɅCa =;IX{ׅՕMkqrPA*U*PǹۿlJl)WѠ!4_`oG;t6ּ6Hww|C][Hgd@{ѐQ?ZC6 {KG/;ʹ٤>w, lpdzښʇ~x |~ʺwu$_~.ah9z+-W2t0{FM.2o3&Q3V",VF`j$n-&Eg9\qg#1\5 W[Zd n%Ml(&V|ƅ0pAop*hW(4p8[ŊpjULp8UL@^ .; 36MBn$@lHGV$B q4!x8ŬAq(@qk)j Zlp 882 3Xq 0wm70:i0n-c& DF0` qguÂ4.4~@#£uU>p䩥GcvvW9*d*ѭGu x?m9_U3_39uM_J,)G)}" %wE]׃uJѴ *y0tAn%-rJh楅m$z$)3H܎LxGy#a3\_@AAG3((K3TS"E<LfPѣmdb9F ey0U:3h!E6k^0C5PHd<9-ll[$+r9 ܔMͼ 3 !3(_f"fZnk4+okyhp.D^4U11sy e03ha,p2J`q8iKHHGSCq^q }X *Z<&Ń3h,衙J ڥg{HJ8C!"3g-m>kgʄGݠ qpZwtqj>1."rTk] UNi| Cg1Πe! P,xRwOZt%qe]O_xXB 1$ML#89CENJ(CST4>u(^bҟ~C'T/CH%R,9aIǂb_Qݶ,%.}N>kO)NUٳv8p}N ?-{ߟwfR0endstream endobj 895 0 obj << /Filter /FlateDecode /Length 604 >> stream xڝTn0+xIqrkиhXZKe;i3\"0(ooތɆp!Rh"8+y)H& V[VJM|R߫O(aJV$qj ڦރy5᱇5q7˴Pt;?<#յ]08@E2--3&.p0Knv128;~H/e1mvw^#!+ %`mNAqIs}f|`]=xf\f0mx>D룋>gBv qu{TmfFKZP0zin %Ǵ*:MDԧeRAAC}/T#߸4/otBGĵS!*k_"A> /Filter /FlateDecode /Height 106 /Width 75 /Length 2849 >> stream x\KL]~m(ʔk(I#DD#WbLܹ1qA@ c-Rh41Q*@G.:32iIv:C~bxVù<}999eU0ڀ%NJ+.xGp6AaL&xii`  ifm߾ݻ8P$$㌿;C4J߿pY~5Mܰhjjڷo_UUUX6)7 R@QEQNg>[,mDh ٜڵիW@JJ EQV՜UUUVffggC}>[7??d2p|>˗:k1fKp޽m۶r(Ǐ@S8l:.4bl޼U:pbMsLooMج9[ZZڏ?"5722hpg{{{=:44$l i&MLL,..h4lVqq1MNCPC@ ׯ_555"͖-OMM@AAfl833 B$fffRSSlقWZ}H*}hZ ae~BBBbbb z~_VOLL>}\.WX䁁@ h^Miii^&\[[,fseeeOOܹ$iGEE5Meee$*6r$[^^իÇ+qɨfE׋,=ĔۇJEqvJDl86aH^y|R 7//riZ(JPf4o޼yʕƒn4Yr8zx%iGv67==Cp}>_E9;vpZt8%%%(JNZn˥P(v8^WW'I\*s^~ uk/!ߛ7ohg:رcwXSS}SOOO[[[QQFA"UhaRʹ hFc0L^dC0Wxx9PPP0<<PQ*["d2}%77W$A8WTT MT.,,^l&[>}`0\av'(H#@/"vd[A:Ah6P?\|C111vʦ455k 9 >i ܙEccc$]"#4\VV}=y7niX|q׮]ypp/wnݒ0v={b:=N޻aoA${P,btI(t6 e+ q#GZ\_GDRlW1ٓ$FVUT"!񶶶})9ALOOa0^x{nvѿA+it4M4Q";'(733sjj 58#3\P^tI a9J 1 h4}}}yiatq*htmmmh,1 v0-~?`hnmmA$8A8<> 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 898 0 obj << /BBox [ 0 0 864 864 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-label2fig.pdf) /PTEX.InfoDict 517 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 521 0 R >> /ExtGState << >> /Font << /F1 518 0 R /F2 519 0 R /F3 520 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 2972 >> stream x\Ko7ϯ|p6 H] XBAƐXi*fҰtYlY,#YW v0|މQ1??~O8Nu'ờѣCqfx(E% u@ߡp{I7J%1`]CaׇpzMvh>| U;衩paWjA0SoH=ڏBOMXӼ)me7FJ1 8j7"()F,/.JcG Ն`>480a#,)MZV,9onZͺuۀZ;%\ 1%=`2GSQ}cϺ8) H8#KPuɅt(N/4Z3|麴ڸfЈ4粰 pZf 0=¬6S.Xӂ^}/8:d2yyy\[áϘ/F6 4q*@a(O 0+/_HZXY3.݀fPihRT߈7 ^Q0 f(}D3xN~-4CX\<3Pp Yy~&!5*^`5hSipN2 0/7[}#$>jpEN!;5x0gxjb` 0/#HF9\Cd195`ڭ~ ûJK5'j=raoxn5DQϮ!Q?5EJء_e.h,nlJ7$!v3D:|,Θ`'0Wty'd'~w]Kb4LFAI SR>hdT\>IQ֡aueVy:\ցXuM&YG|+*eZVArQ֡`uk:3F'@rSQFIQ̿YrSAdGVYu((e4\b_!q2:ΛLA?앧H@e iNYfVuW!au3~cB܈:7ұv9I"Ь!"}ʂ0{:,9K\ %ϲB=v?KW("Zh%-گ{(5^IyGqM#<^l.I`8S(Fs\sf.£fh 3UwP+aMq;mU\l#Ε|{ȏ8(&'~*^'e vBqqḂDdV'+OF?9ڻ`YqD,tϞjoT3V%M_>{5ߝKg.oR3 zQ g2KH(g#Y)=?̧!.mG͢r6&HJ;F#J\h ~vL-@Ekh㢥Z*g#Dy.vG3H 0AZG:B\0'j!8$n-j*oz 3Gk=!Ar kdW qھZִӀ.LoILjfK'۪SXױJtc\mD5̿Z{Gkc0'WsZZ 94P(RR.90J?e@5=iHN,(wAQqA|<(F<<BXę -竧C0Crܓtyy-Pg\P$?P4H~Ι;-! Q$J"9gBWB_EBM (Er,2/7[}IH~ΗEs>gΉ"2ONWʉ"YOodr E|ΓUD%Jz|e}{ 'X;PGvB9^Gjv<3`0LL,3޹L\bJFFAcߐpdslEw. ,XFaG>pE>P֛c|i]C.SqvK/E萾 Wב+[+'E†#\yᙹPnz/Q;.}+> W3#38YY b\i\@W:QchSA6.#Em bH Iz?s7fx4h3{)](#g BstաdR,eM{M"s|5Yz3"]0[VAda q;BN'Թ?nendstream endobj 899 0 obj << /Filter /FlateDecode /Length 701 >> stream x}UMs0+t31@dt[3ƤɆx,jբD/CYJUZ;UVh'J[fUaE݊ost9g!z\🣰h2Ni4/e3Kԟo]ůy(ra(Q[uAPB Entf!jer]ʴ!1K"m cj8F_8Mݻtct%:  )衛yoN,RCvy˂OtbX# ߲ :/a]8/td ;q:9,%PEfMT1rlta+yloزpNۼ@D"[|".e$2H0Ăwe]lm1``CLC zj5CukY^8gXnP]P+X!K砼PmWcHwɠ@m,_ޖaB~{n7X:!y{dR[3"v^蔕t&䪡ձ{/%e,~ rpg:C9ȷv }0nr1nxţ4^Cn0Ϥew|:A#ݻte8(ƿJ)EypN,_"endstream endobj 900 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2933 >> stream x[o_1>p\%qBcGnʕը)R[RVs_7TQ/UFBMSP6rt 9c~9 c>:#t;;s3;7h4 JB<B(`Ic 5w+.tj    _txH&*o1fY!c6Cp:o^]EQd$uj]]]`ݮѣG׮]Ժh4G'Msx||Z%!õZ x/aFVt:=33|> MOOeg) ^]@ PՖZ$IBnxںr [L&[+'''ERΝNl#~zKq\0lmE!M(,+b[JЅ rhK/Iw:LΜ9 ҸJt<rm[I}.[XXxA[}jxV.X8.d7n܈b]!qFqbbNBj:77GӴlnjf.]װ,k2.^6H|>OHŮ$,Jw}Whzz:M[=t\~?|\N6({&Mc_X,t:-B*[d4BMMK _U`0s\.Bhww<7Re{YΝ( >S<L&{1˪dP!rDQZ !attTN<˲F>E`07||\A<}צE e0$ UԢ^?ע1 TΝ;6(}mg 0LOX|>&GzJK#ʋ~iOتByÇd|!dX - BZ|w@`0L&]*`nZn‚di"IIRrl2A6}[;F"9Y MӤh4`M9@lՕ)cccC~VnXnB~> }ooOb 4қ [E¾)롊y)8*s8??՞hx^qOi-J^xE"p:Pχ`22!p\ 9f۹L&t:׵tX^+,l߿L{D:~jRIqzViI VBl{_~% A޽{BA޺t:as wwwϞ= d20 ,*Nm hT*4Mw24M婩a TZY֦b@*\bo$Vb5 K3\u:]O?d2nݺ^Ȉ@WbHr"G}0iH֖B܅8y`||eZ|>tj09³jM&N+++<{<Fu`Z:#V+N4PMȡ._æ!… dπ1]D8QfKQjjM qrwMƯZlccczz:OLLLMM5޻wd2A~cܾ}[ x\.S& Ъ4dRtjtd_rp Qj$Jk  ###!%S}iV jM&EK$5A (\xhlN$W\A/M!n7˲ p8 )R`{||АlV<666~:Ƙy O qX\^^/ yTN"R1DQ$$d'}>n'`O>C@ !,K>7p_>)?~, YxN#L^[Fۢe}2tR,r XTP(4JRT GQx{{RPd, 8%CRaFbP%gjaP IRP&kWgt8>>P8$ ^d\a0$c9L2t/IEQ0@:R KT T*hOWPhPt +A ~,%06@:":Ig7Fp3{@@@@@@@@@r_endstream endobj 901 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 902 0 obj << /Filter /FlateDecode /Length 2288 >> stream xko6{~O2k%QԣE}jBX2${wSw^H?.Z G9͍&h7c=xrs7)ITzr3lͿ^]ʅ2,bt ~¯l\O4&yi\Dիk j3"˘7әNT: D)x  ڈ @bw@qltDYR:JYW|/I= G\?4s&E[J,yl5k.܉X[G{yG\, r_oE~2'qZ'JCQa@ ( Z )`iZ^ 4< jhQun#$ԣIF"$ ;l/ Yyf*+yO8hx4a3PQժiUk:PZGpPY`t96 P<+i>=!8]|aM'5 #VNKؿEp#zU芽C':q %Vi+,YBӲ LIikҢ$zM#x|?7 := ;d4Ta*$;Th!y<?qoxV8/Fp~tsgqZŖڙkE"goQ͢-Ė2xp],g}KÓVHwf2.A(vcn{6|4m]74Xy F9y7:վ)%u?Eb ƍskD͘\py̎9v+-)z ʼzž86R}ٙs~m/r:.ߚvЈY}4oɁzAGP 05i1$\9L e5jo77vD3C.d*tvfRaK{6T?ەEp`*N6bo=/Ma|owD hQlҤT*>QuDÒ2 ,Δ8ꔉ]%9I]#W3%;UaSEQ]ݺ(M>k[Ԃ˘X(HBe勻6!ӱ{ {zu2,b=0aS=_55@LL20I0x aY'٠,R#v I0Dy[ȓ`> /Filter /FlateDecode /Height 106 /Width 75 /Length 2428 >> stream x\K]>o&CJFӁl]l\d㻐n/.B\( "iZq4Al.CZLZ|;+1hҜ$7w3s3QTw7phѰaKG֗*2ƒy&H&a4XP4 ND/_4s~N?8,7mKаٳgiZ(۶iYV*q1M3@ 9kkk9if.e͛7$GeƆ$IF"* @@}ahL&b1֡rn,jK՞5^rltaNYӴX,V(\ׅ#j}ݻcF__~REe9Nᮮa"m;p9ryxxs=::ڸQ69GVRUU}L&?~70EI$*x=,52VWW'''chl4i SD&:*oU0 cH*:d#I|4圣gPκxN6=ft]nj#bxzְ)UFu4 (nB~uZ%H(y}UOjFXҰRO TU$ɶm˲ rD4MX(ZZZXXXÎ㬬ι8 IΚMZêwIՒJR!|#ޜ<1H奥)}}}h( H`{1YeYmu퉉 Lm6H0ycQVzuPA5s!^l6;<_${!yapTְ PԄ 5Y8$q777{zzLd2݆aXA4ͭ-@<[[EDݼyS!|U:cYֿO$Ҿtw4=jm,KRCCChLa!rq"2 :s΃b1>Y:Nq9 춽=44T?jRQPfp82 T*"tdVq:53ëN;N, "/y:vmllB!b02QRLL&`\̍ w\ev =5M+^PŬb!խqɏ?<@C H$$i$~IRF!`ogNRװtU0x@-)8󑇹܏#B" 8PX, |#PP̶m,&r&C8s (J'JD:FR9t]KR7n n((5i33*cŋDjgo9J#8i_ZŐ$0 q,b !Nc38ԓ I"MԊ`@T8Em[TDY5`=`Qy.<ޯ| !\ec|4M03ϟQb+x{ ʈP"I&H;aouqٝbU4LѰaKG֗/:Lendstream endobj 904 0 obj << /BBox [ 0 0 576 576 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-label3fig.pdf) /PTEX.InfoDict 536 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 540 0 R >> /ExtGState << >> /Font << /F1 537 0 R /F2 538 0 R /F3 539 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 2207 >> stream x[Moϯqt0*~vv0`#, KIlHZDzS=ݒFROF3RlR/??~~>mNƨݧ㷧)O~ѫ?7).6ˆ~fM:ZE4e6Q^7)ziY{m8k&EO#  &?ǟ7ɪ9YYB/fl,\"O,yO?P{wCƶNl4uvη?ޞW׏W_?~o'﷟./N~Sg6?@2Ǥ\dC ֨kˉ?__@utXrI 5i p̿+#NRzZtʦ~Z1j4x_EIC<<jޱfM rj7Þ)Q0-NVa/nƯM:+/^I2 ^_OٗgD?e0Թm:BP `L j9"9E^¨ Qf ^QkJ@[,h?T{?.d![t57J60z?.D8CsKj\C w2CoIH)jmH`Kdi߈A -"HhT`eɩ/a%9|[@=VE@G~"f6),Y@edrX2Ig`TT<A2XMF brA&VxImi9-iVu)Vr1OŬ&#JME}*d/TKb!ObY{I~?BP A}*hF]< vt`TEHi'bV7’Jus=NF]mNw|~CB[EtWB>>adhװ;pƄfӈX3Nsm90_EC0Wzv er&e;(iiƜ԰;P-&cae-cV8g&qƏ<)[}c߄&{~C_@,GMI>7Q phs~K)ENLJg }$ٲ#_it9ɧR;y?Pi֕P[KTeZm2Di#2|dĽH'ї6DHwn@0Eo5  ƈ|ȩ$mhw?fMဍЀ~<7y^N L[Ϳ_PLJy!H09@iû'솿]7<%ƣo<[8'#Q+R}@Qh+-|f-sA9N!A=xt^A'P䯋<ɼ@p?N ̯-z[5*Ϸ' [ b0o0=y>4?|R,EIݤxx/Y>R :y~W/qw:iƌ>P(Ks񆽙AQYm'wٕjn7 *$jxHcj19#f(g$`EJN.ۋ*[D0:D47J~CF8c-mٲ鞛XcvkP&^@ 0@ y4B*sq=J ON\T!AVXL]h{.z<6FpPxendstream endobj 905 0 obj << /Filter /FlateDecode /Length 731 >> stream x}UKs0W(f Icڦ:[xƶ i]I2Nc$Vow}Ȗ0}u]n$e%+96D2\LVJEۄS=}J)*靓 i*͘Mu]򧺽ja.rZV,8ZqaL4ӊeF+-tx)~$#_ų!3H$m4&3^߄>NII~NR$ut(7 5"9h-6 ڏ`5&L<28%˄01! wa}H6G=%CXvGY`}Nh+$ mHeCk]&~;j%Chz`Y9 䴻 f)tOg4 *if? mc{iL\zspbЅ2hgB ]r:4Lnuݮ.$ `' f 673PU#okzP!Qcosb1H3#.+Xՙ}@|w##7c{k" x`tcqGǂuq@Z܇4!Af:y_nǧPendstream endobj 906 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2861 >> stream x[ML> v6?6;m81J[ qD(JTʪVQ6U.Ru *JU؄Vۂ׺n(`mM=Loqż)c-н瞹|sϙsMM.c Qp2|TV> +UbH~ ljUD*w\|nܸQU< +U*GaʰqP_:::H$Կ~̲^/98kD ===:^$ɒj"H\__O<rPh7!`xDp:jCL/2ˑH'ɴ{ )RP(TJOo4Ls8e*a$0,;IGaPy9/F rp/qg LLL }NLLp_o?\嗹Wo%D"TٙbM7nP2J>~:I>`0$`2^r8~Oy||˟}پRa(7ͷo߶ZcT*NW(a(^o vO@``  fio.ilƻDƙL&Á>u:]WWyh4tH$d{9W_}p8Pz-g2$VyH$H p 9qmmd2Zsss"ܴZW\Y[[CU[[[Ce) I2?$B4e*D}>@YWv\Eݽ{7H333gϞEEQwww#y2a8;;E9yvK濳 A8N &)םNZ~'daaAן?HL&z{{IlhhX,ۏ?x&)vs^-3kvv)MNyymq:+oKK~$^ /^cX, AK3|FFF nC%VxX _|ET`Y6 b#46O|{Tgu[oX,Vu:655%UZ=<Hh4WlbYðl6KD*BehF8$ɤNCFsD敕ãNhA׺FAep86@ hBjZ( H$%Ahoo@ >l@_hZXXX\\ +U*g?endstream endobj 907 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 908 0 obj << /Filter /FlateDecode /Length 2593 >> stream xn_!F#5h EN $hHBJv݇|{纻(_rp Crgvv3LfY27W_3$qfvs7̬˸f9xWp)J+@BnM^ϭ{b66]WY7[xQW<*NIisUQzQ5d[QJTE /2:"w;}LjuF<]pEv0\hÀ"dJǷlz'En7%3@j9 $9x976γ"нf[jwOO4)AUqZ_ %6E$6$O`1e83<۫3#}ĀT  tuطC!M8͖^dj=[JmTܔ&#, 2sg¾05fѲwްr: qzz9Nj~K%Iiꆆ){gB+$ъ;xc߫UCvJg~2zP5B b*G|}C.!U!B9S˺VNH5Ky9^穂;O('m\e@[h~ >[C׻3[ű}t_qZ,)  "vf7N/`, -/{FY &q qU?|k  ܶø[ZptI k̘7 <\{u2ay-Zg}Y- 4T0ȣ["o+m؈!i[(x̘9f$ ^/U,Oq`|cdb[QmևIx=2Eҫ# $?f@3 ${Tm1Yx$9oG8+fLn:k1wr4N;Rvڷ.3KAF\HC+hm-t=ˉ(J΁0 ,|Ptjm$}yD]VƷ!Zl9[>RZKPk(%7ddL쥒E>'"YMeKF&;O<E+,*^Z%KGI2N=} zIR4 0ID6yĉk׵ ҡh9vG1dJ߆HHǪI+"iޥ lgr[ƅ()89OwyWBy%WVKT2Br>(/tG1S6TP6 @AjA>YKyspr&Ӝ(r f(TLYPV{+eSʝPM7O– d _ ?(ڊzzJ}|M^*/d_2@r@:4,y8+?pC'tZL#ĭޝ$J~9;a?n[^JSϗ-㤮ƇS8̫WkJ" Qݍ<{JpBd܋=ɾ #JyBF:Q&pngM^0ιv!]q8@ zO]U7O;Ϳ~+3cg'Cw!Ŀ]seS[@ ďÛm:JbžӴk KZIk !܍ݚ2,x4!`{OXp"d@qvJlHe&(:ha}'ˆFz/o5æ~6]}llbY0ZiI+T\'J쨽Lz<^((-dij7/(Yar2N|/g$=%A*T1X:ub­ )pሎ*͆&bG@Vdm{X݋Jݣ='p8VSd*CCoܧT=ikeǫ]+n}YlT׹l[sͮUpܷu@^8)+> /Filter /FlateDecode /Height 106 /Width 75 /Length 2566 >> stream x[K?o-a@L.>|~5a -0 WoNxNtQpWpe,ZB_7"I*Yx;1Hj\DCS$1F= w9s=s=VEcMU-O>r8t:?R*L{t:}pp0??o4M;<TJ)*J4%4 !$쬮J)+J<@0RlܜiaXa"NaF8==%"!RJӴP(DURv6i`P-҆aH)!U0Ȳ,!b,^Kd3id2#H;3'J) FJf 1 #,//a[!RC,P(FrnQJܽ{`x}Ozþu7aBAcsߖx4- p^rY/^`B6(iiz GaR* a":<<$")% i:+%j\[G  "|{lavaiBh\K4BR*^HJ%BTȣL|>Htð4^E-HJ,$"|lDTّx3NMMA2߻ɹ5ͅqb+Fiay>!^\.' qf3!DRx-eY"C du`nBlxiJbzZVnXt]sTTk0 ;j|,R6VU*뺥Riff&b1uݶmu:\K$ ?|ǹX-^W&Dz,8 " ڠ1k&19[/>MD&)QJ!2T*Ɛlf/wm_Vq\}Qku=A)h4vwwa,QHD\.ǡ06#:88DL&#&>]ч tЇ&C_yĄ/_V4x&+H)v.!\Uԣ6cQE}+v`ae_筬SZP4"mPȐmN9RȾ BDl*jpx D? T,ǩm( d#w>uΣ\$sq "="4 ׃zԗ>hinnn...ROzBJBDT*Z4Mvq-PyJmvG.WKVpсn@Oj&RRLLLDSSSP*.FEi"P?_(lAf MumRb@"Vr7ju]6ʭ6eZ333/̦z\Fj|>3BŰ\5|>ž4 q|rD rTΝ;|2"ŭCǸW?x˲/19Dw{eph-eS?u DU6jRh"hkkɓ'TQTfgg.h5Ԇ`_K}l)۷ov1bm8%aW#o,H(Jݿ9K۶Qz&#3Y}QEy!\0ippn(sQJ%@  >"']t]gT8z3@xċRAȮ벐᜹8\gz] -OfpxMu> /ExtGState << >> /Font << /F1 549 0 R /F2 550 0 R /F3 551 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 931 >> stream xXKo7ﯘ|7}hKDjCJQ)ߏ܇V6V:,w73C ݐ׳]Qx;_ͫפhk$/M*w+Cam܎;=z_բyv-dWY !v G gŶyvEcQ|?~E,['>q6ڮj'Ҡu5Xd*<%VCcB#LO@ъ+* lp)pIȢz8Ncm둩YM<2x%,zyDjw,nvLJl%9:U 8TKU:\ʛy,R`hSN7iXXhE;?&/!ug5"½]|E2=C&#=r[L-^I8Vrv^kdy .3RRDup`_ { hֱN%UHn7W@k9 ht-xؖ |݌ E"!5kOu6i]|/3aA>TV9T hIR νBSĢеل4Nh5_N f^&D9c^3Vٗ_V6p>@,tgVS6v G 8sNkҪsf5hL|w,Z_>$]| ξ(V4a|_Vٷ zfv`#Zv-{ Z-/'(f3~4Hyendstream endobj 911 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-artspinefig.pdf) /PTEX.InfoDict 554 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 556 0 R >> /ExtGState << >> /Font << /F2 555 0 R /F3 748 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 369 >> stream xMO@+X;_+D$z@ D/`0d&gy%?jxہZHA\OU;Qv! |$A/\D)/G@Ơc R(cXй{Զlwexynѷҵ*v~nl<ڰ|`5HHz42%2\(^Ă_yPw%6!N(7*|t3cUvq f:M!`%-%DtŦ5'Vwkth7:.,)eo%Ѳ||JHk$ 4} d~f6 $(k襔vH"Bυ2KϡTsbگ_bRendstream endobj 912 0 obj << /Filter /FlateDecode /Length 403 >> stream xڝQO +xe|茋/ƾn̹f_vɜ48NJ&RpI(HȜT yݰ{sCN3)Β>:8ytES!%wNѦl2|#XKϟ, :%<$|S%N*@T! 2$ g{Dobr@m>d1x6!_fRaJe섾H3$_L]#,#][dzly,j؟0 M;`f~JiLlm[5l:;{%1>Y/C/ k9/M CBbA7.ExH,ev# endstream endobj 913 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 1343 >> stream xK*]GIQB*CB)I~[Tj-"jBh:#2*4%"PK"5ac.}GF:y9gyΙ3?>>>PK#h8B#(?B#(?R n7BiaJ?=^z8"? O\.[?H}(ʊXJ2Nşt QA*4)ܦ(*Nk4\EQZ?@އ|>ގtZղ,˲gZHTW)EQOOO\,Hlkkh0:: BBjX^__x<>00AHzL,[(*L`0p$!dX*b0T <0DG&###fA $ZT(tuBQ,n#8>T*q{pp**H2l||%EQ!FQD"~z ~r(W%bXNl6(W$IB "fB$!ѨH$h4t:ns0JWD"FbXc4ξcMjgn^stt UGPrֳRo]5Elꪾ///Dp4gPȚ! )"beevgd2)fe8N&V5r9ѸBP.l.X133CdGWWW g&JL&xX,5߮ӢBf`0(.0ߥ ϧju&)lVcajŅng &|֏iO+i)2S4>CmmmU1b'''Pb,--*l%A\,5F;.L-|u8/A!A!7  6 5.9DR(4+)|P[{T*UpB!đu~q?X,5>uvvr1STP@!~/X3aQUprrO#QUSy[VcL& 2(G`:p8\rAU(mz9Z>>>/ZPA!_q*o|!fs\ZM$6i^ViVTb$Il_Xvy1siv4n#?B#(?B#(?B#(?!?endstream endobj 914 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 915 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 916 0 obj << /Filter /FlateDecode /Length1 1606 /Length2 3174 /Length3 0 /Length 4176 >> stream xڍT 8m.-4^m*[/b6md_C(3La6lҦYJ-K(BE!KB=ccfk>[DRZOv1dMG*VV(4DH4LDĊHsa" J$ЦXdҠ@c2 0(%RPF"4#LQt "0dHh=})DW_@'MBaI1 z@qXw#4?Jh7A).R7 XTenPD+W"ÒLyc) ܉8DR$ǽٷcxoLkʧQ:[Q}=`f1CЭ@w%lS}G-𬜙9Sx5\dps yMU\9,7rDub5bgQ3x/T'WD(*7])~.Mu߷Ї$F]b5 93U t[ yerE;^y7P'f+ cKxR QuFv݂s"W] W5j7+'bxi@Q 3jsQAtOrZ, kF3_ oYlM'.ObNI_z5hV.8:H1j Kغ| o*kXyOkl,#?qwkr<q lţMESg:t@D .hz4)}<#~H޿`8ksDP&sV/`.EMzZnWF.=e(Y-I̮cq(墪9ēg<@d` ̬Z'^|K 2tֳhη1FצoM?D4E~vjfb QdvՈ6Z)TlqdE|u$# e9y.UnQƹs/e:[U*bX88?gm aodKFxH.Uo1O'>)d,V)=^w᛫޵L"i&&8ބ0fctՐ{mk~bƅ[\WiϰKڞBwVN9m|r6kF骒!ߍ(:[]pxwNKSɏAaONe*̬P/_z;>ȡ_RӮZ2VS)Cި;MYN;-9.(c-ʻSb )b+@GoL~? -Q>nCL ;Sw}tF,fϙMD>|rWaxӫf&2Â9bԁ#Yi^w₾$K4hH7濠1aE Ֆf-_k-̼x4nlr[C 8gWc~\{LjQg]ND2NeKW0sl'k`is>] BӸF~)'mP)jc_mئv:)edFw_nGs2b+[H0lxB_RW2y+`\A <}%U.6(,] L<,I¬8U2 G \_kw/E=j |qݺ3`a<'w?CKendstream endobj 917 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-sievefig.pdf) /PTEX.InfoDict 569 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 572 0 R >> /ExtGState << >> /Font << /F2 570 0 R /F3 571 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 2905 >> stream xKWrplr+pX3 E TuY {|:v7]Ejq˻寷?Ο/?׷mݶm߯랖_o?l7w7dž[ ߖݚaQ,e-~y}Ky+뚪銦+^Z銦 vp(#5C{28HPǞVepП!Cw*zaw3?0Op.~_}\>=|ф1؄j {t]J̦ F3(5p:8p#50:s0:4Uym0 u0`p `}8%`Z3n 8~lA'etE݈tEݶٛ18\paepVxHe8 y 2q%rOWtZݵ(l6ԖLW4zv34G ̡|cpPFU28nh“66GpsBw4GO4wx1N/a2,zds4  ރCy+:XjepB8a9_\Ѝ+9O:ěSC -4A~(=̡ Z,naw`eݓF<$i!%7|jj.Mc:[pt2:~\!? 6so+-PyMatclatxZp#P:qFepTF5qpZ+=+!ǵV18/9Q#lHx܅aF;ӨCd{vZ;א޼2,7K0D+ Iξ_vZa}f| 鉫c !A( @)V514VY*7|K C:+|蠠aӠ<N|Z󼶰Fa_ ]Aۈ"FdKcCl8X7GCTk<9t̠Ҟl"5.-> ,xU)apCyngwh;bU:ё=' sw:j V#u'HJ |dL邠3]t>etxχFGH630:bᢰ9AkFatP2pY ݟ(ӶaB zV8v_Y"mA oԩen~,fDuA )J7ޑj%it]FPw0|r@ڵ2EG3і2(8RoBWBZY9;u. ]2uOQM2: 궝KMVF!حA@ m]A碐3]rc.x?,&at;8_9 = |&+N=U-ﲴ\ZcVOxz}r}2: J{E|k(>51޵ED[f<9k߅ngɜO +!Ҋҙ"r"p7Gt@(ZFTDA:"J?IvYm$C$etв@ U\:uSʌ2“Յ+N; oW}0(^#fEӃ;VMWf+Nu`#<8p|;޽0!$5Ӛ|ruA)68K٠날S)Uw]tNZA=GҮ ^hAa-)K+"' Ӛ邠տ NV]We~YU=WWMRRjzm%.+Rq&)DZrxN.c,=IېÏ!ؒ+.Zв.o!<_C&!͜-P'AZDCq<A 1n!0yַs7!hkA_9|9A/(#qёS!|ܰs _4.85<(ڈp'z.EoGOzۏ/u'zOV//A={?^,{xzqvpMoer\]&-o.i9<|ϟ^,iGBQyA{k57d9n/AzXCg/?"2'_X>{/1 [QN=vx%p;žR/zia܌:o7(;ؠSEX g\xW^OOKX [ ;?_BQzendstream endobj 918 0 obj << /Filter /FlateDecode /Length 1882 >> stream xڵɎ6>_!$Bdh&Mh&sKzmyIƖ#3})j$E E>>}~xzyEa"R:DiZ&FQIir_tܜQ]Ƥq\ÿsEfE|3Kjay /$_X N.|兆tmLG6_$6-Jrf i퓉/ZE?7ϭy7&~Z ?a{f~vQټrɾ5EOW(?iy܉yxYbL+A#3 +yS/ hKMZk3|}A:8rű&d%"[/53[HY4Ou$b OyJ>Y1]xx%#crީLMIK yBԙI-CI?'NHQ!#F]1dK U8ȮoUj\&=L2V<6O-- j}xNrZZHW"bgܵe9@Qh%8Ov2w8 -ۺIڀ)knj! 6YoEDށe&=d.ĘATj !(ZSCƖB-- e7e$iB|pJ9u[Ȃ7&HrJ4wYuu zmL.sbQ<M%i^Ak<:udT5KY 4>SP1%(=Nl, u.j‰'$> (SN۞Q, >5]l"R^߉̢*[4p*TiM;YdInGBӼs2n mB椎4z8YTx"b*i(/E;aޛǷtTŗ.h)ZhT.$2U6Z .[v&e],mR BQ/29[8k5P^aM}iAntoVּ)'!ņj(,pq$ ΍ ga/y #_,IF260ůgF|DYWF tx$endstream endobj 919 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2954 >> stream x[_h[?޶wݤ6z:!*Td"M e}I/`f B;M 6MHsz6]a֤Rys99'er!    {šicccP(Ej>lG5G݆|?ŋӧO߷c쫯attt#UUnݺ522:J?Vcw8===1^ !DUWU4[_,,,[GQ`ܹshW0^~}pp?2w흝=01{+=(䠪*!7bt1w)JW*pB4r(njjss=NywA#N'G}"W$]ϝ;Za2x7Px<ŋo /7|'4MzfXXr|>6޼y`8f=4 ka}p徵4ϟ_ZZZ\\$9rѣ+++G}6!r-..=,,,c^Eqjj2>Z]] dvBfb]]] 矮.Ir,kN@HikJl8$[bqdd kaWW;UU|O=#a}wЬX,KxSʡ$I<,‘+?ٳ9N!b/*UP5y޽t9/}kkךlEo3 */fy5qO߼yjbȗ-rvٳg-Oֽ>d2X, ^L&^o&A4?p$q݄>rf[ZZAcxرc&˵uY$IЄQNgX.Db}}T*3w͡nWAK|6 "Et:yoy:|(woK@|>sNYWmyr((Flm,ϑ|>赱 'a'|RᱦiLfmm \.߿ M)\@ 3T*E)E1Ji( clbbbyyYEQ)BP(4bH$R(8p8bX.f2&/r*kkk'J }^ REQ,˨ Zа7 :EQ4mrrrdd,W*N:ECCC)a J#A؆R$B,:p8ߏ6xv뺎95Y;i_CncMMM s* `!4b23)K$<1%@{ E{ZTc!Ą$I(9NQ޾}nAv;4 R *꺾N) .K4Qgff\.c젙]Z6h.~dG2|Vac_$ pc$ ?sL(BcnZ7l?L3NS`)---~rFrffFH$CpB!DqUӉxgg'Qё? VVVxe;\[^_a6GwBn>g2lmmzKcAd__h0[+I>!DQ@ f;?+PTCJ)> +9￯Bl6[:,ܡ#clrrT*AϨF8 qE%[rW!c(nƒ"ýDT:!d``qP(Gչvq掁,eQ}>_kk+w2zqjϝМqS4vGGGGx,oendstream endobj 920 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 921 0 obj << /BBox [ 0 0 432 720 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-Residualsfig.pdf) /PTEX.InfoDict 576 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 579 0 R >> /ExtGState << >> /Font << /F2 577 0 R /F3 578 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1081 >> stream xMo6<1~ 0`8[Ami;CQE{ i=3CVկÏyzJ6ƨ~~6|J2ꚯ%Fy: aqcLc3{] 6A=՞[ӀVnpFbn'[@mGfusRwr2wMDڮVGΌ[wsVJlvbxP;i`gbypvQxiFrln"M+,VnBWSKp⦌xʝE6QS,op4^vZeM%H:D8{x+7b|j)r29.6G<_a=VSһUyA\jl7,Fp"v9zM/o6*]8ym+󕎲gkY@(: pgrwZ+pj+BJ.Ja1gh ukZVYPLrԱ#S-<%8[WA^*_4bY בS.._ɑRSe \ו-*Fnܦ>Dٵky~>mh(II;KDWqs0r,zg񴒣U""2r;w=[Zs(G'xя5Ϗ+lGP6b56n5|^ڨѢ&IV{7a5qC{Ơ'=:>q-TuI}~IL:<ԧ7\K]/?,~*۱=7VM-7%͑8u9n,%~??]ý8CA4ݣKE2:}Ye ]}cH5dK>!H{3Pv{K8q+1>HM)|gSGLg_z~Jpȴۀ^:VTӗUz<"z@zD2endstream endobj 922 0 obj << /Filter /FlateDecode /Length 298 >> stream xڍQMO +RRq3캫ѵkw%V!yO\5JVBh6\dUЬaQ&]1GמH"yDVt菴PtCj^ ox]hǻSSW!% 8%IV;Ɣth籘^N.:vK+}0YfhK[ZHQy/QP̘ЉF_X;LuTh?kC$FtCLn\ډ5oIGs9-:u 2@endstream endobj 923 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 1435 >> stream xMK@(M ***zPI"x ^#xE.貈C(R(ƀXݭ]@(5t;Nd&%T!PC8Eu# յ!Ȳzfffl6q;Y韵ɲ?wHUH>T![Z:{4NLL6qO,+++>/;;MYjhhpݑH\<77w{{kC4CBá+gvvd2c288ZcPx@JTrvv9N`Y6wY,Y$IJ$vjah`0v4h1 ui&''+**quuuGGG~?;;S@R 3ji-nw,CrssKKK~?*GPVVV[[t:I$0::>U.))8LKxt,},qV'i>FȸgrId60 322.qZ}}} àI$-f1˲hmp8>~:<;$|PAT[{^崪76X^^F[999XÇpwwPa<b-dJމE[SKxOAN]kk뫫"؞H$,UjW7ݰUm ۪Kf3?tj>- 3%{ZZcsP(TXXJ0w{{[SSSPP?ܠ¼(W333nIP4}{X,߾}h4UHGGG{{{8PH^coqq hU3 ѪtvwwF4X_EͦyDQEQH{)--xbYQ= r$L&0ܓb0׵!wꗗwuusUxrr<A^ 3"t~~~zzNsrr~{F$z-H<B<gYf)n~yy\$rOsaa/_uj0| ~HH|BѪȲt:ѾOP$Iʲ,ˢ($-T!PCUH>T!PCoHendstream endobj 924 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 925 0 obj << /BBox [ 0 0 504 504 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-splitfig.pdf) /PTEX.InfoDict 584 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 587 0 R >> /ExtGState << >> /Font << /F2 585 0 R /F3 586 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 731 >> stream xŘKO@stLwf BR! T@ h;MJhlEx ΀~4_xq2cc0}|x)˦,&V:jR]3ں3 )J.@^׊@c}D=T k{'!x >kEt~IxTtsRڤ0?;fhr}!J`0&qFT{?:|Ad69Bi$ֱ/OQ=z;% *߹ҁt|q^+ieHQ}jM{Mhc@w,3ߊdHXJPz|0+2몯 l_ƓlneWե[r_=`r%zm}'w0m/#@h`rM rl.Ӊ9-b Y{`ML=DXBi?8iD(vƿ}߱+į=ՔqN^snX3`/Wendstream endobj 926 0 obj << /Filter /FlateDecode /Length 328 >> stream xڍRMO!+2Qm&{36m[?^&Lf ኝ7l2sP /=BӁR^h^hK8MQjxѭ} 9}6J UB9cU<6 I}^@L uOhT-AŖ1),*Gf wcrE= +Ϙ2'/GO@T {FiYQVоk07]K_mOJke,LeaƷ/(y._"[fۯv3yҧȚ>@!#cendstream endobj 927 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 1253 >> stream xKK2_f3d7!-@n\kKD*m۔MD.dYh8^/ Qy9193g;j~C ɇ5$jH>2t:{{{rDQT6EQDnGqmnnkzF<Ԑ|!PCC ɇ5$jH>Ԑ|aZ=Vem}}}rrfyy+Zgggsss_?0xx(|>YGFF<\^^vtt@[[' >>>vww+ݝd/B\C*M,+IkjjFGG?ipPJ0ijAwAl,h4333^XX@fFlL&S0ĩynnNټ`YxDU nZ677&Qxy> e2^Z6668l()IJӓVU6Z.ΠMz a8F(xxdyyA  X,R8cccԐ|!PCC ɇ5$jH>Ԑ|!PC =Kendstream endobj 928 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 929 0 obj << /Filter /FlateDecode /Length 1926 >> stream xYrF+X>,RI'R\ěDRc PKHVؕYz_/3Jf7dw˳&$.̖׳4KΖ/O/r72YMhy;7fpEï}?{_Y] ҿ9mE/Bh ^Bj0fVjTJ td@! S(A8wRT~SãW/=~7;4@GэU2_OlHZ >}͟e=S _F?}uBr#=wmuо @g2a6WcAdhZ yeP~i=_]/] $>a#[@Gqt/|nRܞ60:=!}V}js!ߍR8s* Cm)u@'mǪu"N9LD\5TcSEYS8Nxi Hoq|wS9+s*'4êџHZq8l}IeON9#DIe+_qyM[* '4n2Go;x]bDߞG"xT>u l`18M= TA[**؇XA) E_CsM|7 r U89L;׳GwQ^OQl7o80KW? _0b <{ !@ 7:[}ۏ2.dL42k je)MMfIAc2~,,%]Mx@*X+ W&ǛƁ#Wq%Od_ڨjP_ bp@Ώ_L1z[;RnE( 2tML$:?\؜8mՍD{OQ$jy/> /Filter /FlateDecode /Height 106 /Width 75 /Length 1976 >> stream x[OkO~MR$B5&,zVC@D/'^=S@J^acҁMvSBL~ij1i69,}̼{T#p9f3 LBCB B!rΉH!,s^(4M"Z[[peY16]c B&QWLd7O}z\D$"Ǐ")Xx4麮:DB2|-N,C7۶SiTsNRJ]mj4ƘhO&xNfIDDBJiv<=td0-IJ m'bC0Ba"uݲ, `0uR0޿k6@@Y cڵk!mfnB!4}D K0t]RnllܹsqT*mcccyyomׯ_]`]P888XZZhB!xJu4x|D"Z\׭jfsooO4)8>>6Mn38Q\nZ輸(t]W4˲:[[[PrB Օh4jF"ooo_zj:AtRj>vCeևB a|~yy!Q1Ztlx'7MLgt!`#¨Xz13 /R(A4iFQq) pU4 ׯhX,*ZB-zݲV Fb{{HYA4U3 SZH)۷o>|K"B+UQ}s?!Tk f:N<{҉Eӿ1lVJY,lD+L\?D$2ճMPJkiX0<ݻX,VZ @ij|NZ1*aRJvMDPH.s#e8w.kh/^ܿ?ϣOtZQz=0mۭVKizmnnQӁVъ ێ[#U]p8 #:S.~7&mb?lٳgbetJJYTT1uULmŠܪK>U I)<:ԕ4MӲ,JeAs^,SԪG xLlZ3탡t8!> stream xY[~_!K)tE{HlCMl$XAsʔjK̹͙E,}{͋"QXEU<{xSIϊ$=g/qО_w~HN@߀oO+Sanin~}L)G;Ne^i<[$YX9/䃞Ef M(ʚ _K %ihr0EYSr3/(-[$4aaLLU_y)-<!(IcE(KQ`YeAsj֤Va 6QK_0=<(79:2B[Snv5=;;~{U70v5 +8鹧fV:$0%dZ~?rjɍ,,3'8۫j" $h9 `<>&'$i0•+9+rxWK_4'TN%)׷<»"RNoaԍ1t hPFvOw0tzHpKT L)Zٓؠ|lIyYp`>|Rs8m:->] ڎ*5F!"V)yB\-B2$ofoOyL̅&HC*NDH%laA?fɨI孭l"Sa\+h{pf8)Ec<*Y9|-&Sg\uRG~}9pb2'o-$xc؃Ϗ>Q$<@hNjJ/z3nR]uRȬ;;h; kJOf*; Deİtz@"y9TuQ,ߓ֪.wA"DYuہ?$b[餗3q\I{͐3LjWWj!UQ1K|\odO;RB#9"\j}TrU;Jd52V`]}wsܻ.rTʫZvqL%΂`5Og-% A> /Filter /FlateDecode /Height 106 /Width 75 /Length 2327 >> stream x[Ok]?>MRKHJbZEI\uQ⺋|~~~ .ԅ"m00 eA4י0]h;oDc4y,D=sSՔ9????͊C4"YJ)<>/J>r{{{5gmsOieYRJ"-)R*HJ m{t:~za:& r\X]]E]gKҕT)%nfA?搳9[9т:Ǐ9H)o`T8n c_:4 !t]G%J)]-""0$}_4)e>mr9q2`0 "T2rz}kkBA:'BT*U,gPJy8 b뺈XڶmF!z`^)5 鴔2inu]u/ }qVWWa>!gyyΆ6+v/VO>u4<|L8dEs=4ӢP ˲6 xjuggDz,D"1 wf۶ nm!OEDƒuv]\~-+!:WޮK>|Hlco߾ B| 0q[@08&">I8U*EOvwwܡRQtN}!g<ӜRqP AeT/итCsu3b)Dta ߃>LFRt]O$Y׉Zba! KtrI !D׻!C@m.BnR>pWkf} _8z}mmwRdUDT@UNT䘙gHxssNΣIdxmd* !gipAòD> ^1RJ(џ"t]AΊHjWdGҨ&l6+hu㍪'Gyi+++H#hj: PZW0Bg2R.QT fRlω+q/H$< h> AӘۏbT*jax||VBW4M 0J>Q +L`7hJ71_~L&STX@(a N(8-+x6vavݣ0 V!PJJ$~e2Kqp$%iƪ_z@QV[XX "=R:a'''Dy"Eʹ.(,m4_XXx'.umEΣۯq}';> /ExtGState << >> /Font << /F1 602 0 R /F2 603 0 R /F3 604 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 668 >> stream xMo0 <&"ŷۊ d;q`!b=M/ ~U_.|%ܯ+<9&,yq sɄu~;l}>Oujq *k+ qK. ѹNf-|"ZNx]]f-}}3r'at> ME O2 mzErRr SA#_ "ٽ]V>~R@?OrE@,J2aQ GfX&f>J%U5ۘiz݋U[a`5vBCiTa`8zY}?XB`GJCY݃fT*$m)s0¥nD~(~=tҹRs dub!b1FhMv*TY}7ƿ\MAIxI01zEϡpMDZw\&j mЅ:Q)AO&b mZER!dCjD5GEH:~W-X.5YdPiۀZ[ӝ&yڀ:Y/x 6J,8Rp64cu- #ٱZosZD;P`Fendstream endobj 934 0 obj << /BBox [ 0 0 792 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-cotabplotfig.pdf) /PTEX.InfoDict 607 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 611 0 R >> /ExtGState << >> /Font << /F1 608 0 R /F2 609 0 R /F3 610 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 767 >> stream xWMOA 19`= *D7A&ϯ3JaWv3g{s ey7߾R}(˳9/+;g_kpX]]d\Td*J `"W@NS3V߁48jC-[\M) .n5o LrB/avu< hD76uA#E 5;KUlO:Tj)FF>gtΗ8`6B4H7Ffh[$&q'ջ).e5]7v A/EG e&)Z$"'|05!Ily5::fٙ0̸'?)ڗyeӽ iǢL2*=+ yGilOŪ+Ƭ H}Q"ɚ$W 3o kpgLX piFRuCF @ϥq&kGKb@A~$ Fz_XٴBH[7 X*ͽ$\`_JJI+XfX$oH R n3\% Ҡz(2^ \\c륢L_endstream endobj 935 0 obj << /Filter /FlateDecode /Length 657 >> stream xڝTK0+TL}draM $wƏv=37IKbr/Œ',sN5ќdIr&bɩOs$Ʃx 9mHJIypð]AVt(w+0 vn}?#&QG}^| 1=mL..7´MdutIY~m+g9:%Z(PK4%ND-:!:hc0LDHX9;Dկeh1N] ΫqS& y4g9&V^gU9NR^#W(Lab3/#q\m/sdp2ςNgBgeR0(t|~QhCi'mKХfoZGOP*8nʙQHҋV#L;L~;&ZhpoohlǍrSi9> /Filter /FlateDecode /Height 106 /Width 75 /Length 1856 >> stream x[OhK&?M 4GzPx(x)x͛z ފd &Km ٤iIjk; oٗ?vn;7N;3;P_݀E(?PK: FFFv  r95<< !Tϟ?#FFFѨ盘E]'CjC % 34-a$wDnF199/\ZZj\*x<ax<ɓ޽߆a6Fd>p]G^[[s\M1drppPt͛naݦR)։*Nk۷o g$Uh<b7loo6!/nwkmHb\KE(?H$"aJoW8===|iiI*6+tϟ*ץb#a 9N H4P8 I zzzfgg;jZK!RpZŋ WZ]+ěQBիWMU;;;ݲ5SNq{$ ijP^o "!a&`0jSfmll;v) BX%XK.]d2˗[yށ\.LNF,NLL7^ᙙ'U`Bәھ r=?~>iZV l6s(!dX`PTzl6W*IQT"drhhangd2uB-@  j)ppNJPzYDT߹sGBXJ`yyh4f2L !df``wi&T*F_Lp8{͛7"Vf9j4\ʲ,E*C~[$ e,?Pz0BHHEhX߿/ fݸqC LbkF,=w@իW=z$qaa`0Xֹ9)L899)&>?~\8`̙3F*t:C>B_~dnݺ%VEc"X!={cǏsNx|xwl4gbt\mԕ T!Mb>7bH=ʙX لApkkkaa! Y־?~Ƽ}oβ, (wxŋg51TUN&E"X__vIIm/ ՗v-6(򇈟|>_VQdzz̰,h4,BZp8p8BLB3ؑ/,˲,qXrDBѬk4q8$;ƞ59h4 ؉oEApb69)P0J X,vi.#V0盝 4M[,i?-$QhhJ% X*( E(?PP_$endstream endobj 937 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 938 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 939 0 obj << /BBox [ 0 0 864 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-Conditioningfig.pdf) /PTEX.InfoDict 617 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 621 0 R >> /ExtGState << >> /Font << /F1 618 0 R /F2 619 0 R /F3 620 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 647 >> stream xM0s JH[%7B?PXw'].$~f޼`[Y|v|8腀a<=wó%v/g3R@ Xp_B+w&԰4Ⱦ6CM`=0(O?\F Z d ͤ@'zD$Pڠb:4 [ .5z^@7nciUΉkI5v{(D> zՖG}VHerؼČWA1ROKT&_>9> stream xڝYYF~ׯr@&G%*4SgwI`xHvWWWW}un-]q},MVQeeWabeadtWӟO>$->G89A_J$C\u/߽}oUe Φ@E${~0-Ͳ4aq" 314d#H[ 8<@U{9\%iU&^[w=Zn3S&Hn bipZd4 ȶnT>Gp39]CHQ`;$a&Q(gT&p+cVs@i!7Ƀ:XsA8{6RFw.? 0 ˫jҭI|!}gи:>XG;2I]s;m/OWA΁b=;6KӰQXFAsd\3 4ɇiT'JS5(ظ AE%XOx=?d9GZ11{'aaNuDĐ4HǏzKoF>ɻ'^/o$&yaNCBrƍE0`!s|[~2eЀBc⃤O|Nt$2^0?GY3MQjfPl n_[dEB[y\D"2&˄)r ɡ檾VtsLdxNwe^681d(i=1z d 2<`rMm kzؾ`} n< T\]\ErW^$m>2Tn*pM.Hٞ Xjb BfGh߂Nȕf63 "h6}mx^QNe;gp|*lvy!qYc@{e3"'=唜^HuLZ'e$ĭ4f/ǟ4 c#ًT*v=/"}n$3g<4uX2!RnYdZj[e.g4_&Iħb@g_TR\28)u  rzdu ^X{am%Ἄ4Lk˒ \|I(RL|`(<9׺ FO4/z-?J$.IM@̂|  ֐Nr#~b], L7sAJ<8n7w׸ "FlƦњ0BQQ+-띍SH{&Gl( r*)6h#&Ċ<@[[2d7غllޕ^E7ւ$c vN)JJO-irڑ$48 4yߴ7lF=,?D+5?Ї9MΚٌTfH,2ꅏ^)Pv)9p& -F: HP8*J,'k8[Om2I*HxQ6j- *qaE-7bXLEv= _[0{wgdݚ*G&:YS ?3/<^P;'v5[m|Ν%л%֛H敆ybm!M\]8l9,FSw  cf|Dtj{O k^#FzClyeH4wGEܯ<.endstream endobj 941 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2619 >> stream x\MO] uNJm&I4Фѝ;+]vƕn$ 1'Nbd'CBOgBwq'i EkA̜{LVѕ7q(~(~(~(~tBUU3 i㗌1_XX@^|yڣzQ[ףGy+šIJ_l޽+J-j躾iDH$~z㱊M|۷o+ ֭[G+ ϟ??ͬ8ڥRpY*Bt"lnD`JGkR{ѣѣѣH G@aG1GGG]v1(| -,,\f:~(~\} ʀ/7Po߾ 4~}wwAs~]TvwwݻwqÇ͌ |>?~ ~uX^^nf~{)FDi$I""umn<|{{{nnG|}Q6%"A hmی1Yhȋ;J/_49[TrM._Ǐ蓙퉉t:}1+ΞgϞ5xnRNMLL躮ax(Z8NV<϶m0pX ÖeeY1q"H.VDL&mۘC|2uq,(Ic̶H$r* ؃>=āN-Ld,ˎTU4$I}h4Z.c1X777gffp)2k(œdYF[VuEVVt]*\cO˖rGAt.˲,˚E" Мͩ)1\s8Qa3o"9 Mw,˸CD0 "Ot:ꎿNQȆ+FQ^Ñ,Acj.'8A0b$I±Bɲ,I D$IK"4ƍ1|;DC1KRk---|f˲QGET١![C{"Ӡq`wyRmaa%p8gd2> 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 943 0 obj << /BBox [ 0 0 576 576 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-pairsfig.pdf) /PTEX.InfoDict 626 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 630 0 R >> /ExtGState << >> /Font << /F1 627 0 R /F2 628 0 R /F3 629 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1009 >> stream xݙn7sr8"O(=fy! S0:K6htƱ,),E!pA.m>3#g̍Vij@"m+Bb>1oF\oDQ LL,'#&(Hn_롊L' ƀ.C:πm|HJ!HE $"rF3`:Qc`1"\e?G/ 9jsI?F0Ew #R` x0EMNpVή?+g083UPUF5Ii41}Vj:Ѻ$5KMf.J&d%I( n_]Kϟqrr=uu+2KNh6E ov'W7}䍶e,*L]@tMm`B}q1>D!9HN+ :]Qyv䈘8T0~O~ȏ_,o)kb|*4?5%& F wݦόޞIm^kښ?~Bz~ i9TFfeyA^u?4f- p*>7FW.chBIkĘj-k'߶ #endstream endobj 944 0 obj << /Filter /FlateDecode /Length 1991 >> stream xڝko6MjV)Qڷ k^СVwcR,~"E9Ejx<%$KξE3UgNoJ'p6ErJ>y+gb,]֪+ BHws1& ռilqtoc W_}s=Ӱh.tbsr;g!xM^2a? <“_D'tJi,SYW nЉ./5JzV!-;>:drt4%sm*GWxΩI#$UsPUVc+%w@D3(wgE?v/2-1D W.O>>8MWG {d.Ts>GJ$+[=^;Zh +^0oa\+QGd\EwȞ(Dt!wE pD42E޺q?fE?z=2i QMUm#V ZANFlv0؊Ԩ#܄*lHNhnȟ:b<15^cKQ[m\C`?&IeGA {[PZfX5eYn.}$>ۈ֑H+9eDגKDk z>䉑ےdyl!YZ݆<[03NN+T]֬{I˽*aByC?!f"j "=gҥ%E "= h F' 'eNV2?5%~ڳ~ y zIVgœ;4Ȼq ە Z^'7RV($v/227/ڒ#"kh- n1v-;"GCP6JRm +%*t)eLaԷpɨC(RQ%U`.$48 K!+:2k,#q?XDAlƶ# vC MĶ@NMVl̡&QChP8rS a/ Y> $+q=bZDZIءO3PHtʎ dzm3{jo9mCi|Lc$eE`a.D}ՄA7*:&8U;,KcQ#V1H{R9x,Q^GO"mR @NaXo@3=1>H)j˨ > zaV,Quei*w׽4]xqp3S1 .؆ 7xgiF2a7ѫ $פxHcx ߘH?)~p/wM=X/{΅M]Tʕ}+xuTr23f%/-%^zT]%jy |DvS5 2<&b'qq֒X2\^ D0 '32+r*]Fɤdӝa; \[?VzHcTiKSI5w"q/oEj@nzR?ZYH%> 7 &RY + p1{D;'7#ezp4AZ]BJ>QD;pD{!t?<<4Wz-g+vw `1m> /Filter /FlateDecode /Height 106 /Width 75 /Length 2711 >> stream x\olF^$M,maWKHJ9TKRŅo[{P 'C)"$CZTխlMIG!J=YU7=|ȍI&;D7=֤^:u>u>u>u>oX,3 cbǏ7 sND !H:FW\ywu]gmCўڄ/z6O?dfl 5MKt u8yd2ID=8drff}:Hӧ(ɠ5H$~?;݇;wr{~[x@r\,d2|… q?_=zTT.zGџG}DDxgT*XE800 }(|嗵߻wɓ'+++M| O>?3"!]ܞ/WKzfff2đ#G*yBX,^tɓD$@4[O{o3͛}ᇵKQ_Ç߻wollDt] 4M3ԏH$FGGwaTZ^^IZZZOOOwuumqrDCz{{k9jqÇ=T*~fRѣG_Jtyee3o߾n-q~EYZZ !>?_{V䅨gϞ=5-PgOЯ˿{-333}}}J0W^y9>8q~\.g4jz뭦Į!Yݸ9nA4M?t2|f7ڵk\R߿7DSNQZ/(ݻw/~ᆱT՞ZN2^}U7n8~x8FدZ?Ԕϋ4jk"> l}jivuu"B8iBas(NWUƘ븎0ͺd[ͷ6Co |޶}%IYts~>'"u\EqT*U(TU󕕕U2ꪪslll޽u]u'''eY(փЪp& L ,|``@>߿l6䓓1t\D)A94MUUι 4Ab&Il wh C90C,?JIYAD٬iL&5MRU 1bٶODRn*<϶rX,.3MSU H e9be23,B4c kfQB(D"m#jaD"qyooi`E4M/瀟DSNm,4E_XKu];vӵFE*'CCH7CDhEOxhcrX%u]o-.,`3ɜ;w+JD]eٶ=88X*auY ǰ~60vj4ϥQѓSa=~"bvvVk688B!qӞ1( |hh( )b6^,1V*1DcpαFsyOQud2Ɩ7 -*lzJ4M?ub4M]9N!`rr94үºAسr O G $d2a2ܲf2,vG `&'&FFg"GDP\.o>1XP 4!4 r A-M <>LUh4 (={t:8666<< xY4*u#qTl"g\0-sy9/ kV*(z³mgϞ, Zḅp߶mLqx 2Bbj1߇Rz4MӡPL`iY:GD6!|٪˗?RKUǀCCC‡werzA%Í}K WիWu]5Fq4 G8z'"UU_(ҕaPB N6- _"n`iiQZD&"JD 9HsdN B8!R .b###ׯ_p·~gbO;vTz,CY.q7޸>qddd;0:Z 1M8Wif 4|$OHp,,,J뺜sԳQB"rBbdUUkυZܢ)ZAAAAA/[ endstream endobj 946 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 947 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-viewportnamesfig.pdf) /PTEX.InfoDict 637 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 640 0 R >> /ExtGState << >> /Font << /F2 638 0 R /F3 639 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 594 >> stream xKo0 <&r(5E"ɭ!H=`Yb b$+15 ?(L`o>m/'6 R0lu?}>i&[PpL[5 H h 8æ:h S5l=z_XTě]cT=ȨJ B5)|j [~ƯɆH 8R@Yd.|1٪xw;6ijӛ:o8e{?)7u,TV#wH*әn>|АCR2䳜!6h"?H|\Ȟ tZ-SD5ŏ(^S$Z)[:1Qma,> stream xnF rPpH$E6B.N4EIFEQ%8;oP\,͛M?^-g7 Dq!:HLgQt\ỹۓͿr7_(%v *``Gÿ{CeQ]22 G ybC΢Y$B(OShj` 8&7Y ŪLöA ҰjA_I-*'z.ֆ, &=xFp(4Ύ>/c,wrf`k$"!}BE:).YVC.l }.+`%\+Ў˾'ͫ{5~d)/1 \@| ЂRoF‘rFL}midd]j Q2cwȾ&xN![mH,+Sʻ 8i]0uH)@p=![CvcEt,/Hv(BsF'0) t d #)GtpyKrA*pŘ\x(R1$EA$OٜȹѬ2Mxc}q = RO"룎$5%P.ëD,Ifp|"Smpl?+c@\+yǜ)ZEJb2ӞW&œoJ"YS^[˩(Nz"Bei'g2@e)O$J`Τ@"Wzj )Sp^󃟽͵QgM ȷ([F,lllųā!D XVdC`4\)l עnHV>zKC>:&{;F7lC&_0-xfc&T. =4v(߄wzaDzE#Hz@>0| !>%PlʉHBOh+{-'qP;.fLca++ 6^٠v3j,FXG vޱV j+v 1İ)ozW^!gb$~ެ|鮊+Yg9/6}{GΞjW<#v|Vt a]XM8Mȳ*w֠vP'vDYloSCs䨈+l' 54Ҧ!A <ݛ7tej2I9Lo;ܤ-N^o[E"̩(sms^'EKO մ hv[.z7L9Xd9c汈- Lf=)hʒM؀p[f|>Cq {lh#%anl39a*z{N.Ruf2,dO5lrDak: K 3)8n8lMg$9DRr nePnY, /v^Ln)16'7@|c4MM*gɱsqϡ#O%hK 7Q~RdO[endstream endobj 949 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2255 >> stream x[KܴE4EҴ1ۥ}(>XR<҇\K[,9B)=Cą¢'cbVT'&3koo4݀ða0lt?4Y,120:nnǮG=Xmm\ǔR u]q1cBfgg(bqww7 % qFGGML&e뺞JTUϋ(cJk$B ܹsRJaa&(Hy\Gxcy^&4ͲrL1MSh4J)u;  ˲*[[[A0Me,WWW2cX,UtZ4X:23LRb1Ƙ,GQ8&CxHp]wdde2dIJ$I(B È㌱d2I)eJI|ǶmHB.Q!($U*rX_:Mu… fc2֍ƺ$:cLUUJ)0BRus-.&loo뺮(JX6XO( gOqgߦ9 ²\.400T*UTիW}}}N,tZQ\)kkkQJϟ?O)rhBtww{ca|~iiT*bc0,{Mξ3K_|y-˲(1ov)ږeEQ<ϣʲf'-˲m[[[h@;;;;00\| - AA BEcXcB6iaZ&0;upuˇR8==*X V:%{Mcf,{)9(Fљ>>JE_<>c XXX(hy Eam-*-0Ľ#tUu]GX,&  $ MIEyx 8Gwqm0WgLPJSc̶m/Z?o*CZOrh$n`ΆaBN02u@UU]בDpJD4 Ia4um۸mξM0M|(Iub1 ezF^.JcccC$_~UUU`DʡK & "g)Æaxwp8˗ϟիWwvv6I0/^͛7 ,M14 dž0Sa Or]z {2MӲCm.uDu]\ʕ+]]]{{{;w>x@TDZmRot|>?>>^pmL+R.3uzo>fȥK([[[/^&i\.ǟkb޿{ww`J,][[?xdxƍO! "gi2L=j5kJTBސKccrܢa8.SQ43M#hhl<w"MĈ[E) ځ\]w(k㤚5Q')Kga}M#1B#1_F7UP‡,S^`~CXfu 1'&&xQ3L&b7=֊$ѯ$ 5iD"jP(@.bG\N~U!T#cCCCS{u?C%x#Kq`V$a;@Kwg=l4tg0 Aߜ8-p8܂yސRAuQD"\WKfiQjCdDGӴ?: Gað?8e[endstream endobj 950 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 951 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-changeplotfig.pdf) /PTEX.InfoDict 647 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 657 0 R >> /ExtGState << >> /Font << /F2 655 0 R /F3 656 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 679 >> stream xMO@ >.x>( {CR)*zǪP4sf;o&^ xϗgk8*`:_|]o᥺near=mEޠ֏Us,0vCλh]o- Kbrn+V|n@^TCȳY3؛Bm8a_r,zߛsL2Fu}@v1gkZ.)%,N:%<.M:7n0!PFendstream endobj 952 0 obj << /Filter /FlateDecode /Length 1645 >> stream xڽXIs6Wpr!L̸3Iɩ$9-VR'}HС]M;H6|{hK"*t4JPU2ztaB)W4%(!L,ɲ,0|,𱁱?⪉/gz3S?T:,X%SewO0K'O0x C5yNqk)'YO+ aԢ /`~+E={ Mt1I}xm|L痀N>VbM/F}OzxΰvZlohB6iW3 i4tUEVy؞~*g\"3-2qfGL' Y GYYSWv`2]<%fwHo5O^_l}zGmZ4_L|n̔d1mdyd&~~iHkU9g9Xk#QOfO{-0kPxIM+bQi`PS Kf n6uMBַfPİ׆ S:V u*k4>Kњ|_ZgbaA BwD[Њ0NSȍ.&rje'mnA{dLJ] غ"(`\QFq=YP(qƒqQ:VÖdo++N#=y%Qھ_T'Nu;l`I$QQ1<TʬW &zتbR[;*d\n_K#H1D4,1ixW5Sj/l/ٮLhD݊~Fp6 KIdSдvICП$#rH5r+|lmDcY7r~wAr ˈf#P{&$԰A6gpZj}?cHV@aYU;F|N;2P1W9.;9A \G\nqM}َ;l"kGq 3f٢z?IF ~Z 7܏J`L"QFQGlF OeIv*/ă{ OJaúT@Ox3M~}ituKt{Loe:nDB;2&sfh fi D2 )_Zpg{$1MD2 g>q8XqU:Rz{iu3^ Y1B̨^p-C* *-h6GET<v v1 wᝍ]2)=ewyH}3y`OXUd&v*_y1yyUZSOS;vZFNʹ0ݼ캿򑸳S uA˳Pʫ2(*YzR)R~ЕV%tѐ$G)4.KsPЛPϯ ٫2M@.{vʻSʓ̣ZPxM1 OB? mtendstream endobj 953 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2111 >> stream x\OLMnU\5EPh4k>i&(^L'x g/̓ z0.D$x0c7~.H0N尠cSW^4]J[;7fޟ7X[[rT8,}T8,}T8,}T8,}L:0<OBZZZn7AHVUUu'Oʲ,IRŽ{m$ס͛i^|>0Z[[)===aBx< UUU=abbB44MVUuI_^|lmm4-2en,C͆kznҐJ/CEQ +2DQ$L(D˰X8:dn7c ˵󵵵$iaa) 8pAp8655(`rQJA . (h]Е Bv]h4p8^/^tvvaV2m +ğ,Y٣gi{m=bF/,--%JLcc#Vt$yn0۷ov,B7nH<7dE]]?%LXhӊ&Ȱccc+++X'BΝ;WWWwAݻѣXliiinn+O8?~}n۝ dCLNN^t … ӧO^rŔM^Essssssb͞={4M1 d>oߒ՝:u*}vC \ZZzjI b q޽ݻw'5 CAJu?b`:>[n960eoݝAoo/7!g7=KBӼ{.'wtt$M n ӠupC &F빡r2SpXZ l˲|Νׯ|>F8h) ߿dznܶ$ax} l&2?9ge&"GM{9vs7*QAB<z===/_?<~ϝ;G)z@ÇVUdg)}dkV$EQ4b\.XD`clttt-cކ1vUU4F,˘(=Ѯbix{>>;;zy"HRC*IуCW.9meYVeH$Iw||b! <K!c W$I(. 6Ey4MnȐ ȲL)s8iVUU%X`aGj}}=c0 ]ףh$F>(XV0DQvbf͗_ Hf6s:]/^qgʑKeFCXa4 u(؀1eJ)$*J)B!N 皦1`A4,Aqp+&8MKt|QP%s8gqp+C\ 0w&~(ocwB[VٳgstK @ ,B^/>A4 c2@f;n ;55(kmmEwRjٸ 60 #^Ûyyرc'O`WŁ]v T/UfoW2hnM;(ۋ-S0{(F<8PÇohB&Bd?53022m$ۧO~edd NӠč/S6g%C$Qk ŨKEGGGGs?|endstream endobj 954 0 obj << /Filter /FlateDecode /Length1 1436 /Length2 6124 /Length3 0 /Length 7094 >> stream xڍuT6 J Cwt0 0 Н"4"J H}{y}YkqD@pj ( @UO( !0ܡˉ8̡Ho.U$P7@=p%d2aa鿁 @ Az{8ԛC鏄9n ҒP$ @(MD0`à(sAp 0xBu_` 0 ';`+C@p/ qcB` A e#~`$- sQ藛2!(M+?5 ПON08 V[ EąE$%$P/"+'K|!8 p 9Ao^D 4B@S(#'1M0?¿}Lw7w5T MPREHKbbII@?-5.N_,n77<FG 4[7is @nCq"Z@h=(ZmfI*$[P`>ܸwoد; /ځnnVAo!`K@H$ȟ7'q@ fO!P #P7&z'WOBH=AB>oT#y&Ͽ/( &Fe\*Xn#8ISVr҈ȨRdT?|_k5z3nQ#C|Q>!dh|1o %DKywkek{wDKEϦ*ME2X3aS T̼G7XVt5ZS4%Nk@b~VRUA3Ghʆ?[sRUψikeȎ$㩋Kj,EF?Lϣ/SY# .BrS~ÒMa fͣ-Q@c^RKפb~8sN'T]SUY(//M601 N>CQ(,c_'PigT/8'#5{N;*K/i۾OЕ'chM;Ww10HO)3v z]ÚjڸWw?O#;\m&i'̣\JG BgCP*OlVJrÛl 5Kxz~}MZ0fqUV >zpnV]$.I9A:?)rO+  7:nI>~C?]05}Ԧ\X쓣ߌ YpGj5莼q˗%`٤(|yB7h%tk]xD͡Vl:ۀw;# .T]^b! 7X&m3e㋇6{g'/ y5LϓTEJ$?k$ ) ~F q|'S!m!9ёx~gty@ CWMlko+໽N-z:]NrmZ; ΍_hYYe>.= {_ɹ-­),M &:sޏ!qK/"T bX7xJJس %aqѰ{1~re0N/dci`0\Umݲ!O{GCW3eQwWf*ʹS~=Qӌ5{mtw"NTT!lj[]S@eZ$yۖ|ǶkN&;t8UXREpS>A%<;hrưY7We96G[H#w#^q|{ы&15.^AvCA{as3kn ls/46LN#-d2;X(9r=Z~T=2ƕX_.@BP<0.]6 *;[3Vv0aE}uT-Vw(s~t|gAݠU9{<]_2'؞>e^E+'OKĭa#pHS8xQF}bԋ`͊~be18GUmDB::n=.2Ɓy"5m }Y;;cby<-&mQ}! keƜs/$&++ۧCrLjdA㠊SZJ [>AYE\Rq q8D,ɯZc;a a ZIt/6] hgͳn7<#{ZkD1,1A}{D .2ӠD 2VGQ400ZXcm^7ZQD~i)zU mˏ٫A?c貥X Keؚm5f|lJҠDHVO  ?98+F`igmt?H?Hg1rJmRͩ.aֲ_eYjctha]z s۝1lK5YhqYև|lzۭX)V%(b;Po@~5;띡nࣳ* U ͷH=OBpnS>[~:ROk;]}-U`w{ۻݯF4L~mܮz"og%Iɛ<4ZB8c.C?o;rD*TZpnAIN.?i lOGTdydîrhSӇZ3[f!Ԟ[#om=t ~T sj[zfcۅB\-lŠ0r߷7kP,,BBϦؿMd`_G@/eȌi5z䛝)!]HA=e":`ȷ;dUv}%& `%Ьb_C?Ħ%y[ו$<8$ShÝȠݑ[JjDRݞX`?)ԄޮL>Q)P2 I鐓B"D@D—~*jJI,(;:Q$qiD-Fh&d"n#i `3y[SK!?uXp}Pi&#5M3EwzVfơ:Ƥny|/+V)\VZ$mZx^R)9Mm-? @NVya kپO4=|=򖍴ЫiqޠZza}劝ʦc(Js{2BdTB՗tKB6e.?g KbA"yǧ`[Y?3[XiS.<ͭ(.:犎 8r`ڒz^uGrXs=!Ar ?˴K3hջ]l4{90Œ6 b:JeJ) PȰYrtY=TT,]TVWjn9GuuȔ0 c3l]8\(Z3fR ȟמ&,wOv4Zkg?0*QhSSg4S G-Wɜ]DnUY-V9vکu%%WA~#R+g4ȾRyrk9tģ{TN}Yâ+D=TM~0B& t'5+F%zaUOb-`ѪCNvdpֱ 堃7YG"^28u϶Pz:R5ϔsIw9.l^e殸FX[x]cz.>Duv>" ssBeC#KlPɔa/EE\Լ]g&?ϋ,,i RȪz\S뜲2xo[ r+t"$j' y;+ q!x5]ag 85+RL1=ja'D$s7N(fM`R8J}d1"x.[[,jdRάMץdWkI䐳&q ;4b=xM#]b[Ns{%A:*kKMQޝ͹pl3Dc!d9S΄+X|4b~Uj2C^%EK19PŻ[p w~"7P+o_$}jyy3k̓B^f0=} ѦPC攣'IG'sAfjßMB+rHVB^ʸ=ȋmOmCFЂAIB| -[]UdHAx]2}xG.].u/G`FmstMB;J! ʘsZ,rwDZ q(=Щ[b KblPq{{1GWgEkcm抂&F,Te'r1>W#Oع~\YB-y"_ޒx()^AEcv8vQR]Jk2W7\MIEF^sBW׽kKEA2x_nyKO0%6+6D?qQ^3.vPVPBe_ps9AtHzpިڂRչAHv9Vy 7XB0-\L=2l1C1|;B$V܂Z[Ư?sAu%Ň0SWZg*> KNՏ],'u?9"`,o4b3rZnW_(0yTfșU(6 v:)g.(<@qS=NZ̯RW-R3YHƯmR,q %Ayw|6<ۯRr ǘ5(B^L,.f&r퉉>LRa\l<;ga䔨w&Gҥ9α>0m@z uĽ<2ݙ"hXFKW ͠*fz2b-{p^8M@n.konj2n*|t8gx~4%S xr`S m\G1-s<ܼ*ZcloKendstream endobj 955 0 obj << /Filter /FlateDecode /Length1 1438 /Length2 6536 /Length3 0 /Length 7510 >> stream xڍtT6HIC ]!ݝ 003tH# ]  R" -! Z߷fgoFm=Y; T @yAy Q$ p_jBC; D; hP8XD@b;" O@D@Q,HWw#S#ݖul!uTzH[쒎h8/ŋtwxЎ](  Є@ %d;PzH{ (0[(@A=u+Y7௻yJWD0`-!08΋Fs _8 xB`p w<;E JeE<@sb݇dH/_= ag +UQ"DEDP7֑Wz}Wo# ǀ졘?B? @{@O l A5;`p d)(*)qA//`0 93Ϳ.o_́Qa`x vH s$| #,!%81C\`p0\@cBAV4 y ?zJ ӆm0Y`ja6`@a0c0;=_2eCaB;ćC$c>^ `0>_D!?DaoUm=1m& / %<sztV-KųQw7̘c%>Kqj1IyZNSYԡJ̓ZJlN^O;c$m7Jc/uҦ%k%sc!}c:ًNjxfskuY=:1Kw6BGlK. q隙LjI^Ud =m!{hrE^:A*[~6ʔ4u { RR;eG;&nQ~(V J?jMgt񳓜S j~7?FuwN:Ȟ | 0`@V/)֔(:IIe ":} N*:h7p>ԹVO?f+@CF.8.7tyTN=L#Ϊ86)^):SWu{(rld,Sb ݡ Ɋ g9}^XN)JH,vqs_ڬ3ȸߪ#Ҍ4<tdz(:gR `;O ]բg޷CRF'ڴ'gߒyt`- ldp$5%dR4a+DTi Z@caRToL9rN!ܒS!tRJM?[I˫7~(0|gt%)>iCTh([(td6xArT52>)vn[{ ܸO y'qHJzM&mrN.«JB2ט3uPIv8X)^̞ӈ>4/SyλĢo@5Tg4(\ɖfy xa8 <Ȗq}?źpܧ G>yuޏDb'ZMC ̥T#lNunL|)|)C8Ѓ}-LLlqT[ &nåb2&i W븛\qqz KAxy}8`]3}upAzRWj]юhrຬq(o*d/ZRScSI@A! 3ŧL4/k bM^/L`QZ)j?,y ^b馱K$jV^zU*.q5 Wh)um{~Zv#>0bQI;7 ͓ q*cEN;ZO_Ɗ{huֱ32^/,#G*4ӌ=?dZ'{ |w)rs2oD}2Wm2*UΏx-M'xFԊ2!ߩ2hഞƯ.")Z(=`{ѥƪI-G_}OzӸa5g>X2 iXUnE;iTgt.VGd<{b]_Q酈"/RYj!_>L.b;<<Q *|2NMc@@7>rh)5wcXdC?02AX9Q-14;?B)獡7a&&sxsle{hJW3u7H+YzmAk3$< Y[&U.l?uyqM=zK!᫇g@3U ilX|@şB8Nُ bxX. j/k$rZK6#&oŵK!7>fq0_tSmz+ɽW'QNhB ΄ids2&OXķWeQOX$ZۈFT-/^ |qa+eO2t7Iд',|mj[/J/6ڷMsOa1, 2upƕ!M(*{DWu@$*;r)IO}կ#cU,҃#RK3(ӏY_3z0&yr>ىgg-[x7庩[Ӆovy/?H#&̄kvW~eqߣJgwo]a $Wwi"z&1r"Jty4\] Nj (BblvRarPAZ=)N6>׀ɸ"3ٕhf.`+W(P[Z,6p V# (tP1QLfh&M6e;.6(C8(TAS"x]\[=3TkE+!GT|\`&Y;UTJНˡJ/ֹM%=ן?NQSuh8+ 0'ᤐƖy|10|v88ؼwgAcr+WV]h=IK@ǕzT5)'I 8r(S/JEvH^kM(*V?:70 -=09sDdsHgVV;4x [-8 ?pIN9mט7urQ9VRZN8t86|jfd%D,>5DmH!0+/ ;}-!a%`=ʄ t/<\eXa.%~p5l6)kv>cL8(d9NrXn1V~+}";'M T|·ATs4o2O*&{sdQ1Ow͕.*(9 ,]RgK-tX \* ƛX˾rѓvjx6-Υw[^܂Q~՝X A/)*coHgԵx=N+ Ÿ=ns޶Ma ̺!y o wc9ҬnmL"΅v^.Uvo7]zsX(ܝ^җ0cD8i w!|B;KK(˓lF\voE+ ;ǕZ%) ޱ&2[H?Ov] ^K=O RqLHh$&:lW%{Q4ϛV_>ƫ45ϰбF~僪XgjO 5mFe==TC Ϣ.d0r;ãI3Wn^,6{9fRDE ʏ+KGg[➃uE"j+$AHj뛈-GR<0[%lo{ je+M */5+y}S~-PVe\,Yx)v|8?8T߮YX8L5aqQϗǞ}i{;wRPnexEY*O{20C.!kj(pG73a%zg4H> [eLy;5:݃wq)WaeN$Un.mn{7FH:S,!ys3n7^ 44cynqouX$+73)@ 0B`U\㽓{\l> stream xڍuT6-Ni=FZBzm 4 Ht4(!!Jw<=;g~\}]qTlwQHHXwB(,,pr#NS8@!eW*lj,.Nj;EĀ""R@QaaQhYꁀ($TEzX\`:ZcV `O4, gRM,z vFA;hȈg_D&r%jqɐ)r2/.DOy(5!y" Rl50x>E,p##7ARU߃4MރN{)8SG3E*bd6? R}`$uT:04c? e%3~f\ i20N䀾%ArV zHqcƒ_.}I{77 >6lp'q@ٍ jAO^R fBWL5Br?SV{ e0D`7ovZ[c0y9'ϴPL=c-\q-^ +"0pSFtM% y<#I5˙G=}?|O;Y#U&sj ͙ 8,Y =je%]D΅q,4I $Sm[YX)n`J8s)ulԼjj0V; ZJu2AĮ[ ė]mVkm('iG dR't>v_#2L6Z|Qѩ$bOѴZ?3G Ў|4&Ξ`o[9O)ˏ%oGQvݙypq/72k:im~t }Q{hUIRr?}~7Nͅi>EAľfReѱÌn?m3rŗR}?v${驉J:[g@ddS[Qes5譼1\-5cgN֗#RY˶ߺlsſym#,4f4oWuIO&τ_MTZ<.US2: ˦&ݹf)=e{.9 ֳо18Z\ TH%mܪA›8?sybSkG$*{D~!Y-4 i,# Io\{g͊h:[<%q$5J+PuZֵFK=-:td`27K ̀4vIwY ܇7n:X{M<>K|p ~kb^d#5i^_~^,UbtbO][ lt/GL" _ TY0D ,)x0s:zJ'Ew["G{S#1a:I+yy&~|YguӛĖ^b>ͳ!U+jA#%\D݇k`.Rw Dk ohl'UbA"' '!͆)yc.)rc`LR'P@}RF߷C~W~3 ]7&U~dNRue_&k wBErT:MuMY3IKۗC;-j_"`=9 9{n_z4id#һ?y*ebט&<;醨~BuEk}J/ ナC%J'\↗jJ垌TNp_g>p7D/5j.OQNab9*20('*r'_Ἧv0L%1# !y@hVC4]Q+U6V9Qa%бjOi9iЧE0T'1"o~tD&wч+%8IŶV?Lq 8ׂrQ"9/L=ذ.ru>t.A9:_K wܢ^fKG).L,L ͝d\wG xKKdIDIzm+c.3wԿ/Hf2 7pRT C|P2[7 >1;*ϑ6AIJ<黹,wŰ=^CWo˚ Qo=g2UOg: Fa$(GtO87lV?w5 dW{cR|1G,)1eSm5)R9k%>e/|&ZIBz1ʒ/d:?ʬzL6Sե6K"a'`r0.4.,DŽ )J_~UmH=qzar\n|cGlt_>td M/F}6 +5DGkG.k@ G -T?]?dI|P+=AH[{z&]}.y.yo.Eed c%C[9Չ!s)9 b a('v!(umSsg-[eE4@uVҪ3ɟiŭlgRbȏIٟ$58{&66Cd>s(u 䑳^DݠBoaZho I;bBgO \MbҠ4B.ˠA` %G/;5l9A~2:vuG'Q<5<{hΟ +uG1Zk}y( c&njAvz Mr QDGEʏle {kPg!`>yjߌDgu!#^+ pEr6N}SňUR2O bbZ=fJW [4q=[I7GEHdhw⧐Kh v9wrT cwopIhOeJ$ܩkr?K?$"mWlokT,2& _.Q T{ywWI9y"[~8A!rNeƺ|.K^_fixodlN Xph7זO[ԋBW'Q e2+:aK&l|ö?m!VJĞ5ֺ%Hbo1ZDp_:x/H `.0lӗrgIeanO)/ 4Pt>8 5A&yf@]> <'ݖLa{"Kn07L.բ#% mqvO'JS/IZk_M$T!/?Q1M{93S2) sI?J4=W3L&*=&ԘDute΁t~T 1z$4rBaWY׺QP`]u4@/Xtmִ]w-NwuDoP?`fOfKGIdA[kWlj Hү)7|+ߴu70<1ulW߿VEQn8xxګ4Du;7r/$à7&S]7鼂1M,hS祸3 Z6-ec(s*}Q3='YZX́= |"R)qH +gMH&R } MZ}WɌIkMHU K7vɛz#'Qk9ufaWU\c^U< R7^\^v;#ȯ0̥媸IL n1F:gӝNn:>h1  1xJ|vwDSJ½x;T^*|[0܇V3ZAZA9I C;&x8tW?]AX@=׶e%ښ3kqz8wel˷~W۱T=͐ ]Rc-e+2[6+:zIԚUV_, 2${N \wf_i9eּK$loPQ?oIg nn-khc yFeJzϯuFL0X:+ClFI`~3.tzI75 ZeBervesx<":_unQZR">Ξe*>&jkU'un^rk$$`)bd`zbkFl>kǪɳh'ˤ~f`oQۤKz%3Iѫ>< f:aPD,qhL:}pn"/ ؙ^OX,-(NW33 ݸm 2NC5N0IeUx1edm{_> 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 958 0 obj << /Filter /FlateDecode /Length 2905 >> stream xڥY[~_1KGjBrE] FP-64ĒFH^o}ϕsY{E|#?_UD)mp +fAQ2 l\vyYw@-|Zm,TEy~:AG={W6_(+Pvv(̓8,c7Bl،7;ckDsnD7$`%7$FY^sebNTFzB8q6wYؠZN܆D] OhzcoNPN|)k4٬5 ǹ )'Iʳ(jzZSLUa"g 0]IɃ mzŅR6) ({Rhz`8WZ\4h%tVNߪ45F[EyO01J@ARxFLk효VxgR3eHȘ|dʡ8eeVhUvYD١g*{Tx{cHgoE$y6H r,\ ke ;'kRkCTZyxhʊN:Re#%qL=Q׵xO䪶S(p_4LWђd3 ׭,Z.{&tw>{Qg-)э<ҟ.i|nЛNa;snݭơbH",ì9zy-(@jpr8,zn$W@݅D=iqɣٶ6Cv%hEUEc͒6cӪ=aE x}<%%ݱS}zT=#9:|Ӧ j\K;`#n:=|ؐ):12u ՞mL-?6\@4:|i(t"b֗$ʐ{F[/}h{*H/h}/ e AqF-+r&]ύ^ Ωٸ40=/‰IVi\z+#YB %づ+5& Ym>wj߲g z>t\b5e m PjcavSmiT=<U q c qcsH\s ЃUH5U'<->},$U@aZ 8E0S)q<-pmX~{"2'rف <mqmuBT7ֽ#M\f6<I{1L˗ܫf.xrDk->>9Q00G\v أ9 w;G)FIlV&Vq;ɣs36p<5W~R?Z3ʟ`SԹ>qǾ:ț.v6 ֌e1N *IGh*d dQ+#Mkq ɬh=tj5':W:USlLcS.:Xȵsn ?QnY TߞDwpG>]җ1ydxxEڝT~dCIM&D^j 0$b)S@ɧ]k&f<4=L\tz?lwK(D-WEʢk~'&x ,f\*w+,ܱmTu/4¿bQ08?ugĭ+pCs߉v8=> /Filter /FlateDecode /Height 106 /Width 75 /Length 2523 >> stream x\K_]&&݋JX(P{ꥇ R 9yn.}CI(B*$nE5~Wc5 ٙy1|fkt9>>>>z%DdB^ !P/}޼ysҭkìmK(,X,sB"*B6 H9ǥP(5TK'?ʜsEB:p]"Bk(,K#O>=aF1fF$) x0"Vxh4T*5H$:m~9+-1ƄFy9WEF*hAuE9eW_nY'OH]+x^\GlX?!qE=0/i$E::}>˗/˷o߮g R#MPd20`:zkZ&A`@… JennNUU9cLd2Bv[1y^OӺ3wi6NeX)^J{9 C?|\r,iDϟ3?~4d2)X\\i9窪i: <7FAd8ememZ\N4!X EQbGQIgfyjy.  Ch4z3NpSa@mXݎb 8dlDӴv g㜗e4cL40cmQ"4MfJqXVSUav44M!)"޹|KzܜLTU[Gs,Y^ t>TBD"~r0TUնP($88m' I"HsɆ9TuIizqpp((񵵵H$R,ᢠ^wvv`S=Cp߿wVEDjׯ22 & drqyRyAXLӲhohdh9i]-zs|&L9`dH@#u]<m(ǯLZ.,ABS`EtKskF9/-JH5O;ak&vؑm")Ey5OQ|>2[X%қ7oʃh pՂǹP^*l@s QJdXUU+ʍ7HU 34- ,[cD*V[[[s]Wض-~˲+/= :H9\4Ws!?0r{Rirrrsssqq1ݽ{‚Y'&&%ӧ{qο}C|~rrrzzTUǙV%vǏ5W?ti)#1e-//ONNnlllj9 iM.m65"L~Tb1KA3G@;;Dр1mSSS獎*^ׯ_w֭[׮]D"hdFd2z;55UgggQ-lF( %3hgǙ6:`lLOO:Xb,0ư8t$d/XsUexP($nΉ1EU/V%H  |N뺦iBA_+\ޞf|ѣG@:9dr9NDBV!Tb臃}u9왿DUUe$f}S_aDD9fl 6t]ⅿ0!--- P;TJe_a՗3OFHF)H!D>WhZp@` {LXJn$!ׯ_߹sGI ޮ0vg8y> /ExtGState << >> /Font << /F2 674 0 R /F3 675 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 286 >> stream xj0 @ CU[Z(a4.,,5f'u(zD $=1fz9M B@1]VZ$ T%dx0QvC$.WpV, N1" 9"]fȑ6[pn ]/Z J@'uMG8 HC\&(, k_WА5:{7K0c?uhhx`o*>E(ωendstream endobj 961 0 obj << /Filter /FlateDecode /Length 2256 >> stream xڭY[~_!Kdt)R)m/IB#kl'H:F;I,<(ܹi/w_=ܽWyҤJ+=}R@=l*n,ax_?םz? T|p`F&ZQ.Mr$GS&޼߫*sw/5KG~ПJi)uRl>#(r4&X 5.hcADA%K;kV֡X'}[o/R qY йI$Q 5O ڮ7Y:Uy"y?iu'dVR26610UmZQ<!&Æܟ WYtP 5>h܆hb;cN` G4j${ 5끙}fs煗.oz`Y,MPԤM'A|/~ZҲcAi'kf3=i#lA!SI\|t“r`x齛R:c~%-ؾI{o:2PO衅'~I-WH~uTLaHA/;)HUgƋAG@)=Td~3<޽̐7&OL9" `+Ndeh/5i0ZfI&s1v8eQf1D>2h__Qx<yE\/+3$ _$hP[~~p$ 6p-]yEV#pZ4Q-abNHO']UIf"Qe|߃48L'Zq2p$(l2P S Pz6Qys$or%w*3$awjtft Sy^LbnWœ2a*ML z s8c+%pjR],~`:l'^"3YfI*J\Y"ƅ/2[s|93ULb!F'"KQ&Y%UD   z l*KkT:=b?V5Utuۏ\gu6J|k8׮F 5ط\V -% B249GpnkP S4C84^by?y?]y=W+9vQaXm4>z[mvUni?\ӌcvEk)H䛔`ӽzwyL3kuYNZLabL3JK_VB94c0\B' $Q%Q_ULA qp똪p=]@-# bxQ^UK+̿K^gjҜw>?H*̓VjA5*+I1 ䷫WazK{:Dcs#=$|zSDJaKD5D\0 ‰"OS8SH'WI`kCMz^kvXaS\nVБelGkrӮϬ$Px j`ipeqٺC]̤Fv(O ZQ{.]: jW|OB=6ߛkB[%;B9EH's ) *eWxO#NhUKDI Y1 VRI:U UzZ! v6]O܅^z>Y( a+qbۂ KXQx%r--P1Ş/1x dm[. SU|I\+ 6`]$`mp?#"k2{PmE尿M4bѨ{iAft%PUQ?*w1W径]ll5i0)Ph̢BI21zH-}3Qsirͻk96aUN:XߴaI䷐u~%~f~ 4 HhY9|Vf_sϬtW^V˸|ƍvxs'[YyrA^VIYSG5tpNendstream endobj 962 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2309 >> stream x[oI~n2rZrh*0Aqz!dio^r?!5 ,m. )9@,IK ,˝mr'+`(0.;wWY^G7~+njnjnjnjǭ T*5|ѣGTʲ,"Rlr3idrsss}}]u 8Wy ^3~z(\V񍍍Y:v)sNDqeYz}yyyȘ!y_31H.;J9lZͷ429|Dj ÇJ& 29sqjdo?YFsӏ [0@0$"˲pƠzPbn8TP(///mС<@bb !& 2s.vc uI!x2NNatKBn TŶ3r L\?tOx8tz0ZO *p⋸ 'Тk>Kx3(^gD666,j۝N֏`HcADx `u 4[cߖ9zj4Ɵra/1>n~\:˞ #nmmAO<;88s^>R l#mooᣣP(DDsdOD亮8/_\XX "UU,4"*nV \oVჿ>9B'&"^<9$ιȋCQ}Ync"Vp^">>>6MqT"sp,#F7MStr777;˲x*a8&<÷oߞ9887?~|G{|uQﺮeYjS:wvvNNNf4-HsEW,˚!WUMTUE!qV*0=aŨ twЎ ÃƠFl2eYryiiioo^C> jǦiF"˲EApG6Ƌ a`FшD"9/o޼Ji'UU/M'0gD׻G fb1f>}3 yح[޽{O UC.Q#8D^y^,C[d"EB󼕕MPr~(q2 ʠ,2E"4 dQZYYO5MCKrQ20X " FC"* }`aYV}0p]u  B^UUq( ii'Ϙbo1G!)iZRY[[#Jr" PꟜ}qI$8 Ea_ԝ]2 ʬz.K$/ e>~dVVRߠA}> Ve4M#"3=v1 Y7Nv*#m' Qy0Άc ~k/1pk> 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 964 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-recyclingfig.pdf) /PTEX.InfoDict 683 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 687 0 R >> /ExtGState << >> /Font << /F1 684 0 R /F2 685 0 R /F3 686 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 971 >> stream xYMoG Q:x2pP0u)XMjH)*I~jmI;]hfy#B^| k- w2=|6}p+CxS3dh&,쪻sQa~Y5z]Aq; 916X$an y>T?/9\{+6+LMp=E2B *5 s9h# cIL1jz`*z07d"Q5%287ƟT;Nؑq~X]U̥?mfRLȐ/])*\0! B٤4DFq 'E3V3j?ϥig1+T~iѹzN6zҍdݚpҕIq214  ȱď$KiCЖ)H4dEJB^hĄ M*ԾMZ[x>V d92J*b$٥Y]oT ^B (B޷`>~ؠg] #ݸ%$>L&SM ф$IApY rD%'gQ~@g)K嘗''FYyQDǿpd޼m'"\'f)ї*WY I>y#"Uendstream endobj 965 0 obj << /Filter /FlateDecode /Length 1713 >> stream xڝX[F~@}R` DUF)M-!*fm'68`o=lMTe8swsU:PϋͭVq ,c,p U>|=asK[å#kM݆_^Eᗹqa@5kVg&̣E\4<@:+b]Aؘ4Xgg*NMXdLLmoTk3ȫFz ss$l >.#g]Bz2.U _g(ixpdŒqZs<Nj% x@qwzm-`h34Ƙ(@iR0$ 1(xL!q8φgY"D.J`j/ ^"rtb&< Ctx5a'(Ľ_5aܖ{'7'|Pbm^99b92weG ޱ6]xt[ ~wgJu$MےK/ ~i͑sdaML4v\}()-3Pkl myxKI+8>xA bTpbbq\'YVlv 0A(;bԴ:;6΃ceM<6wI@X%Ik:Sc;Ezp;*aM/Zv^!?!n!3^q{QNKU<|nZ4,ɷdCXFE[O,:]f{0Чiū|bB7:N\jӴoI՘N04=2qyaBZfAᠠ!L^~ G8>ʧR~ՔF)pȅIOgtZڍ2B{˴GJR'7,~"cF2€@zR8e]8.8R4NM@vTt FM9!+;9T2a#Nrc䍄bYMMNbª\6F SbU㬖qkՈw8 7}ᖏTGCd+rw^ ]^_Fb'˹{*%(jǯ z%9u\ț_acB> 5% />X^Y/Ѧv"[qD!'1CI_]-G AD}چY `xX ?N:x.xTI!ǟj ~6cF2kd?!J|9q(6TCj(@$FIl""Gt<ێ:qyU?8OB|MsnH=ҫwNU=㞶zmUhʄ˓3Z:ڟwTvnbZs }Nt8k?Aa,(9Ό֊E~c=L ?k> /Filter /FlateDecode /Height 106 /Width 75 /Length 2245 >> stream x[OLfYS%LeWB`jd[#7$Pq*rS.H*,EjKaiY/%c^0=|%c3cԿ3L\hg-a-a-a-aYF@4J)I)+cyUtG[Bi\=4(Rf TB,ZxD.]vA1]?beBBM"GFFy#yU?ݏYml1/=D"T}&ΜR0 իW- ^ 1d2y.N,R8@O\^:")BaW;vp{{?~^C໿|sş^Ұ099isy}&Uq1Tep̹iw}vn毙>!bggGz(?N|ew9יn {޽oƾ0$rJzbjW߫;_$IgRL0gRdrvvRjtzz>TUYu`훻1KN9R@ry_۫H`;h4j;&2?_!@W嫗ccc昄^[F~Sy}{^9& LF~8 ,D'#aL?ևcޢg}}dcYI 68 RjWɲ8ޓ/^xmOOL>,,.]x<( OcH$2I($>>>oݺE)MӲ,_ȇ1 \~_KakkKeLn8+ Gh\z)6>T|ra;k񚇶i}%l}\w^>4MSrPJ766@D"Q. !T*D>7M""'Ɓ /if*r\+++HLӴ7oE[T nnn 0 B w,Mmn-!: !*q6.+b&I^ qxC)2`\ F<$ ÄxAN5TjyC\q߉$sN"! )px6dqW Au>44Tx((ay87EQTUi@B2|R7}Z<;-,6J%+Vbqyy9kr666^(8\Ӵ@ FoܸH`mmrØiinnn|BCH\ño(_0n4~yS@;5˯~1Nlaaapp8_B)%LLL9qapeg`4NRIk00 /@bB bqL& fSQ%.yHQIZvm=l}\| Qy#-3Cl6vImU62 RZ,( 'X=TB0$/Q0chl<4MQL&(->`ʋ'I\%lmmFGG҆d2 PFcS;t0qa/dbnT܃-ZOi6z,v+t:<Ʈ`0SM ]f)W:|\|=b)2TE^}Y__t]6x?7a ǽ^/6ccQz R,Cμ$g"h 1QbSSS-..NMMm1G(i>US_S!<}ZM"ois Xt||8GI ԵhsPJQ n,躾( rۻ/ISռO+ֹg*x1춡}\= !߯AcUUiŗҹx> 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 968 0 obj << /BBox [ 0 0 504 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-shading1fig.pdf) /PTEX.InfoDict 691 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 694 0 R >> /ExtGState << >> /Font << /F2 692 0 R /F3 693 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 318 >> stream xMk1QN3MU XM<T*7Y]J03 N&E%~9r2'ms~kâ+H'cJK#ΣX7 *l(jqW4Eؠ} RjoVyPeC}Qޥ1 AG; }.VSƲ7CK:V(-탉w^4endstream endobj 969 0 obj << /Filter /FlateDecode /Length 1106 >> stream xWIoFW9Q@Hb$2Z5EAQJ+v_߷HL !0F{o**OnfZŅ*t0_2Ņu|dǛYfT:- S6-C?`4-p6͓Pij9O1Qb,O".4eڊΖH$ 029 \+ ;aS7 #&Mii`Vm쒂u"z>ȷ:ZL <7uis =D,:N`8ӆ W00#S؈?0!0qiS^3;sD#+LH$wA_Occ;kDd%mƋP΁8EDU-Vsyr̴@XbßSgm?;C>cC|_Ȩh^] p[Erc 䁧o;y"nGc{S~?h@SEX4Kj?kbgb=l7: ^h "&MwonQU"PS[#ZkN+1DnbmEKh%ڊWq='KGd$@*}@wW%lYR4{w<<02 <<6\`a,'?kkJ5 ?PKkI!fў׌4{);F b9+eHr7A'iWë́XQo!޲߹4#BB$cTkiFZ)ϞIl g4hyV+OkB` /.Jw o?H>1דp3b D%i3 BO,z{ӊ 9߮jPJ)O9`ٳ]y y $_e-W2~;TQ`A}.9i'Gendstream endobj 970 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 1594 >> stream x\kG~^96 V@.K.BM|\rSι.*!D-kaD6jP$,Or-5RH<~ay;?4vPκcGzC#`} `H)土l6E)c\.SJ,X?>}C69!db͝ ~8=c,nll9clJC0БE)Ja4MUU'9 GP6Lw 4D,k4aFVkuu5HyL)]XXd2xZ9??n8WUd29VUu{{hB`Y֥Kcfv bqvvX,ӧO:Cy왦iZ󙙙|>L&Gc8d줿 xC͇G#pY[['lCÇ{kt]B>Ey*rc,c,J1s,sk\}+JqMDcp&aMҪ  NW R)˲c=Br9.L P,!' 30SJ HӷnEQF,t:BcLu6Msee˗7o ϯceCDŽPtQdv)"|[LX,.--mnnNI JH$Ȍ [n8wHWnMV$W]!3ȑ7i]ɓ'ɂLW^Md2|Dm {$j xY2uZ ? 8[G~$vIC4Cmo|_45,׿#W92z.K\Hc'K\Hcx}YBf,k 2~I6Yɰ:d2qDm vG-]&.+?~b\إ`gzGJi(D"ueccy*lێF+l6 *u],K4۶5M{xD"-mTfc%{+ǷR#`}!V*UU5Msss4)tP^uq ob0 ˲prGN`%0 ?!$' q:mw岪sh9e4BPǤ `6MPS*g?9*Q%LF$œ󃃃"!dgg'mK^Cg8<˲6TQh4uj*|V-BP>}E<jhPmvsL&)/.΢<l8ۂxuZkqP{BHr8iH} Kŀ`0 4 zlX, ض kkkbm&qs^T4MC !\nqqW 9Q:Պ:0 Jy8#ڰ"9GKic]|]Զ -ӑGg&zC#`} Kendstream endobj 971 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 972 0 obj << /Filter /FlateDecode /Length 3602 >> stream x]ݿ' .)A[ yH>A;Œv]RH0~lvx}otw&K6w;kԙ]Yi튻ݏɷ t?~t&]ߠkSyayaˤ顣]t_bmUz-pҫLj^湹["V+^pDHрeE?fnۼN3[뮸x pn{8Tf lfr[ Y)AhJ'GP\RSV | u{QSDAo.z2 H Qs8-virCmc-MUµ"m@sZ`0oBIhtge=$Y=-B +flğe;8d6'a{? ?V82`Nl'LwW*U5{H_f1|S)G"rU?+a,$̲Nuӑ8+#s%S0eM ̌Y^h?6i"] /JN Ln:zqWUlAʇ^옘Sp5Ljd7}rⁿ\,WHBc\D;YsY*5s׺+EplxN%]$4<^V@՞sQ~q;sSk;q;FLM:#"pYpbʰDbs.J^H"TԈ-f.Sl+;ɍٟ'2V7< "ekRH_' BQ2- /5B } %;}3EmҬt4i^"Hh L]o 13,/]7Νt݋@,7U#HrUW6 @PdȶENC97Gm2B1T, =[a@HlCpYgc,)>9xhG$4g F^ kސʊa'! 6h,<Q[ޜ}$8H^/ݓ 1:l-GRIþ2&@b28z:6\bO{5QѦ,[5I<+.[.V?={K^V8*~Mb\k-΁ќY721j~*Xգ9MU<O<xґ{#y#L*ZHkP׭ubeR|Cxv`0\fJ4:'[֔nmB_$|2&Q(LnP+(NZcmbVOaksh{5mlcmA c'CƓ v65cP;2&ıjP\ T>@҇ωbx;_{LP(`$16#I]%F$lZp^-e^-zU=:4}D;d\> %E" 6KSgoF4WKP5 ׋*{Oqn14yƴ12x[D -[˒(GD^CHq9(2~|Dt d哘Y5k+Ė(26vjO(U99ä)_4沴$, /ENǑ'-cґǩk1䇀gNX:AD^?cWs*S/l=#؈'XDQpm>2v(VFiTSGCjt{p|/{wއ! Ac렆ѡ V._$3@C9` hFFE鴎E1걍q_b)o;($ݎevIzN{c"yދ,+4hqt;Wh!V B=t/LNblWpy6'Ef[UɡrQ[hFtwo&Z qEڢMRCNl4`C*ťP] L^JA`fyI~aVT<=*UM%P d1E4sYZ2󗙥.<'asuȾUV_]*)"m k-5}\ z=b)au5c]M,uFrrcgͼ+Nܝ)(R'GUo5xڥL(C{^Qpqs-Z[A,?iqWw?ϰ[f=ڝy(YM(rO7y/iJqHQn) VV|E\§VAʂ1V &42C',ɣj5YqzoGCJ+)~ubc"eZS, 4!BYsDm`PUsQS 52zy8Hb^4"}>cn[T (LV97$yqPGqX 4G:㭄m,k=p)>BL^R98> !dbhTe\ќri:\}<fGN„ 벃9a*o<wDj礵dlܼ688˟$Zc&x엾'pgx^-L,~210'|Ig/yT'WBo%>l}I;=3Gt!Bjurqpoi=,9[Ojl|EQ׶bZZ7ܓj0䓵/ ҹhPC3'bͧc?At%J s&󸶋%T/f6J]vfđ ,|&6<*}Ǒ{Nj~~PM@22otM~UH\hyq6M-!MWOüڋ>Nlfɹ&˩A\>Ύ^9 guvIH Wb[endstream endobj 973 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3087 >> stream x\Kk\WiDSˢ G !tl"g;J)]Rڅw%^Xd񒀨,L!,&JI{-4/i\\fAE9g?4Ҥ] 9tէk>]sxiX[T<)%RzZj=]y}oٳ RiAXEDRJ4צiJ)m7ͭ-"m ///=#"̅ S|>15Mz<iXPK  !(T*mۮB}*ˎXlfa۷b(}T*aJ2??~6ŌS`@zXb^BYi7*Rk!d6l !pq1,ey^piӧ}}Vu4{{{omme2)e `jj󼉉NS t:D>}vثkkk{{{i71麎AYVzH1`t:苋>Z-C]1n&6 #qMMM---JL&_~N5Mޞr677/0N;<!D]YYaLDϣ 8=9u:jl6˲.`aL51(LxuԦFeMB0NtVãdLiw* tղ,kww9RRlWֈ ."Хf59UKퟲ=){|} էaVK9,,-mP>> 8T} e0<0p793ydIyǪFMM0cRlB|KXXX@T*(v>(.G$X "B<]H)٬Z3=: b*V+fyX7MF\4R~>wXW{ogZ [ iPɸ\j^~cޥo߾}!]960.l (~R򲪽R24-(̸<4Ma DAkyC^3N(NR) ڨײ,8a&jsmca22|Ƹ A {pqiAyf #3Vn^5HWbhk2T4"Vt<5^emRYXضgq]0  >\1Z&L ncVU׋ŢmfggbUiutCDH'Šbeb}X=<]!Qr7;8gvab4ֺ|j^\emT0 R>7.} Uj N-9aC?ʧ `II),| }N2 o@ :S*!@lK J\R D:+ a`iPX'9G!8j.S(Ni=GL4rݻwlϟ8o.ȅ5MszP%F`$8Wrr9=VB bHq#T( JPi'slSq̀8P79T;PfO!pvRUڟF?xէk>]sxëO*Cendstream endobj 974 0 obj << /Filter /FlateDecode /Length 3400 >> stream xڽZ[~XZtp8mf[yh\ ֭[\g+p( z\9jy_}Oo^|uk+GU\7\YU6z3z;I_†L^EeR$õ4SkG(9t3[uN?^'dw;\E,T}u Mu͢2yoYb'- kx³sϯ,騍S.WYvRs򊓵U<<?@y- Ws+eZX^2 NL_B;56ҊihY\L8uy6`bS+bq n'SD<V6GVMVEPn|gGZzHvTr'Q➠B%RAi!c'rZIkTnv%ILƒ|s"͡`gn8clO n!Al}+,7Ac/O)l&;i8_jTvZjQGJKm>qOqcɵ *M'@1$T 먒Pib[ Yh3dDzZd9Uګȿ8碼6R\_%yl kw+s0^GЈ)q9.TXfˤ=[LCSNAwIF%:݆=uiymҁ,&!ա.!+ρ`/"\&YYgw $M27l^i}~I+GH}#K X3Z=w`⒭*[:S@.BV>}+-prX piq6牗G:CbM-zmhA8͒~ l=g6ォ/Ԛ/=˯_̐an茅W_zy« O*vgQsi9[nPO&;k+zi\eQEMqsmRLZO')tƝfy9$I?* )t]BYw~tB4zGsܯ8r\jvOiWA g))_*> ATԂu W`YynrqzCIq1V:Az8NY,62IBj\NQs0Vo~fī4 2u.0'2&Џ.ւQ ;Vt W &V\`Jyjaz,;/]U8t=S64K*Ҭ:i@ (W% {=R5l56*cۗ ()бp\,.\k^y=G)!"*eNupEحVH OA{ εc5,p</<= I¥$*̈O'yPh*̦TiRWP^F70k^Y_AN7wŏ4aǕw%c) DY_6w&qDA^DI=#&~ m7-_PM\w>yeKv*No!; 8dwz&p.Ђ7L4aPY4ɗ/S!.9(ѼQ*&FܮL&C9A Hq+<Φ);ZnsRʭ*K#c3i%o_щ-ʩҐIneWE̲"ud,䖪 LE ue Seuܹ˗C4o5bLտfQ癿"; i)W!-'^m0-[^t >;Q.jp+B! %me7҉Tsv,,)G86B'U C$vX2p~fFJWb xBp#)1$IDqZ!aAr˗k~Ko]q7AxX%yARI[n T!tf>-Ab<;gy-]c[j]+{32 "Uws^zT]9kTٷi-/r T6fש/,.@ߒ-a}Yon85(B|ݕ 5y7^7*n py*9~ہ |7 n]mu}g%ӄq89 {7VUcHL%{T < 8& ?. Ղ#5">Ӹ>&m'?8쳇; FД7/\Lendstream endobj 975 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3174 >> stream x\k> (.%>ZZa .ZvM麐U,ܕhh YE ELFˆDPjƮϼŇZ#ɲ;> {νιgVtI 9] /?] /?=Yu)ePR~|4M"R˗0\.k&E'[ڤgVxt0w iuۆa}]EIRKKKi:J*J&ef3{z2TUOaLN#T*nӱm{~~HNCDh=:>`LS݆yꫯp_(J2V؏r(p}u4ٶ=33#RիO?>|g9L&u]y I)ïNki5lH)rC)%X}l0t:k5MSRJ>gL8D( Rm&VNy%RJ0 uVK4wZ R͗z}aaa*;2hYV&zvu]'ѸˣM~gZt1M4eODlu/^mBض*ʊiPQB4qÕKGzHDBM=H)~na(gv:>[4aL"tZ][[CO ! \B78ʐ%DK)QV٬i.lTXpMZ^^Q/wU @?8\MҌnKD6Rxhp3(#"8d2)dql,e0TTXy/_dWVWWyVyҋuvFD7/lgϞeY)sfQnh@!d2xj=H-J' Ɛ3p 9$8xL6-a7jf^zGv'l0d !z믿 !gyymۉD}ER B{(b2e'j\i j-cx8u6Sl\.;I姫‘ߟx.4M۶/JDG aSeJ)kZ2<r ?' $lz=FɫHEqFfk)Aտt0y3d ffft]/ aO]0FFK0xHIX,vxxhFE'gu1͑Ñ@1$3a !׿[pu]fWré97ޖ/x޽{by睻w'RʹBn޼w _~?o9^LT)w'eω(N Rv3wRŶmr3]d78Nf@6MM j7ng"}>LT82SՈ؂BEC !8nݲ,0 Iycc#HpN3d&Eglc#"be`E gp&*GD,bEQ777ܹ )\HDv{eeesssmmAՉ 8 >}:>LY}iR|xHdB9/>X0xoRI$܊@IJ)6# af㏜eD0MsyyZJ)l^'D"Ắah!5ng@d2#1{{{,r _xR:D<sh ,{煝VXb~ đ։FAmpu/3 0 188\,">54?R%;RF(@|$̇LiAp4MjуT ˶, Oj\H)۶}$.?Nc[Q|q0*A#4gϞ4MN+DE[h&@nz8(T*t 48#BpJ%lswv- P?䄳#t\.cB8c6!&mJ&"/0&mg2lJJd6R).9% t\a#<@n 0ϟrn Zg;\ <r&FPx<ξ'-"-ĦeW ͦ#tnXNx#\J x z EqA}0ӫdHYAgf,uv8ƨVKKKq`Bx14p sE8p?^#F4RM~D"g v޿8wgir^`l,R;`x<4i?|"DNm,* Th$޿%OHX?P i{v?u׶ /?] /?]_iendstream endobj 976 0 obj << /Filter /FlateDecode /Length 3460 >> stream xk>P./)q h~p(`IDɏ ?\.y+E#wwv1,ٟxUf3&uZffmdyY>_^Ͽ3 GYf'`?ח"HjΖ ?kʶDglxpYTEa @7.軻ָU bnϱi-ìqw\t8-y!3~z@Lv؊]U1:eQ%t){\6|X1y <凉_YyIm"+ `5[,] +\ki N| 4$U^.ԋ9=OsWGY!f%O ܋oAw{ nBC-Xa+Cp{|@{lT2fWYũY;#,xqVhtRG1 hEm4Yԕ^ҵS懝t;/ymX3L H L,EnAv'\ 09x9c@^>Wx"FHxLSo2 vo/rE{W# Fp4}0b|w-+@'-+ll/⊴+y="X;>-~ !K =uDm(NB1w02C+:˹9Nq5h1}mU&-D*1u`$x={hYf.1v^E@h 8)p(Ā87*Cӓܚ1–.Dg9Z$!5w_c{f?ooM$Mޫb-;ܭp|Vf8ng x/ aD@GK4sc7ywodP]#wjϳEi'rZ5z\<\[lɯK!?pk%R'%oo'{ɒn zM<{*QekFd @HPI.d2SʇiRXStǭ)p;y#5GatnGkNl ٢u* 4tB,I3ZҜTUT}Vܡ`Fj]׽Z,naoWWw-0 ,kVJ”t` zYo:UI^!.3ot[LJ/|T0ortK®Ue#+xיCrAM 5~,c\z`KGׇC=Obq;0i8݁HhbIi /G]2m_" $Z^}~dbK v6iVމLuf.VA% zO Xg%ǍMlj9ylQ8oE#oy'IJȖeRרs`xRB@DQWj]@7IX\W(T{5d^T݌tvȧNݜiep+POلC5(FhyrXF"\O؂ߨ Kc(,瑡>rkERk+|&P,{kZFq}md7c7h.|o+;9Fis%GHh">:JABTVOM~ .vNZT';nL1f! x}Qw0?A|)#9=,4)vAM|4iTR+ɚ7N-v$Yn10s{5yFz~ODzj-}.tc<Qj|5&=7n`$}9IC (/ Xp(N$XhIcQVPLa>, ”Т"%!*j6y9'ꈈ"wlٮH]ɻWJղ4~ N|q"u"n+ \IDLF )ytmE$ I.*ZL$KݮŅf(S3f ڐa͂9;a+eH,W*y> /Filter /FlateDecode /Height 106 /Width 75 /Length 3002 >> stream x\Mo~q.Ll Tk/_e4ʖ,ҩ`Z8VU) p[9* .'8-JoEs}׹Rr/p4dO?Mf8tZ3mZ8RJ>RJzVoݺ2ƞ. 5mۖeXa{n~~^Jd:aeI)DEE_(+(j4BVmۆaaXJiY|h4%ޙP۷oOYK4BH)KVtssB˲VWW*%G/"RE4;eYaT*'O!"Z%P(a(vy| c OƖ&no TU8 BrZfׯ5MSUk1z88[JݻDTV|>/TU79'ilxxlx .JϞ={)d faaxql6+Md~9N@J[iO)¶|>ٳl6+ ۷SSSq7̓"@+ض(RʸOhc8766TU뚦x"\.\vnn\.>^y]vݳÁf#]F .x "R !2 r˲>ﯿ)Ry'„h3J$"w3K-y [8h#C><@f mHe]t[}1-=m`ޣa˿78Npd0!GO\/ǥDu]4@nmmq# 4Ҷ8hgghpUUz8I1A뚦!u1[UU!'y@gZ .u4 ٯX__R&tLB<8  6b ,b j@$u\.~ MJqB \ņEI8kY? Y TkJ@A߽{` ,..(ͶZ-)%p4u eYa.,,uEQE aSm4ȕ ð,kaao9Q H閆M <" C]m ' ƶmԇ` HJB,a:?T!;`.9{q sSUZ̀ \}T1qFy{ pY-~EW^e_/2d )dF+` cC8_ *I.--ex`T2sRG˟T}20 x3?矅7o_%>DOq L$#>|ff&A4c"RUqm]Hy?Kzq` γVHIozy܃{=BNn\Bק_~7ǨDD\ׅ^.t2z89/[E6Ga~ /p";6%/_DQ \JG)<Fb(t=){2 M,SzL"ŮV6:B wOψY0~\Ȁ\*)4ܳ;*&c_$5` hen8Ei$h(R@9H)mȰrc.:c&9qLD؍D0$mTėxp41}߂\ɚO\1M3"EQ"y]^^vRJ_ϋ`ii b_(ߩL4)%ʫPL"u}.pJҵ~ \IBaGy߂+`u= pKŅ_"xpJ]~x^^F 8>@D enƍa8 "y3<oQ{{|pm<y7& }t]p{Fp}zx-v}$ { xwڊw'dO?Mf84 endstream endobj 978 0 obj << /BBox [ 0 0 576 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-haireyefig1.pdf) /PTEX.InfoDict 717 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 720 0 R >> /ExtGState << >> /Font << /F2 718 0 R /F3 719 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 849 >> stream xWKO1ﯘcrY BjBnC MDQ;^nPB{AG]0<@! ZQX@A&%ܷ:F+q(ߙ2 Jv` [ 2˔f.*y#R ՜vz_|kq} ~"`4B}UKPM[0Tހ^N e`taX"5HAOj[pX!T2#(buBx ʣ C@8 Q||}_f9Pi2ۯ׹DJDZguV:H)0HL^$u%ƫ.ȎI E1ם]0:p2}wo`pX Ǥ>ܽ Gӏۜp dѯޟ.pu>&WI*U6&%kD6(K)K9Dפ1_wZmXOsF&VDo^sɶm1z6 BJX2@Ve2ZagctX?%.vȽKZ(|C !(P9.˃0ϥp'o_gc^m]wKi_ #"=z) 9t>*G{vHsٜs6)qQHKendstream endobj 979 0 obj << /BBox [ 0 0 576 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-haireyefig2.pdf) /PTEX.InfoDict 722 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 725 0 R >> /ExtGState << >> /Font << /F2 723 0 R /F3 724 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 874 >> stream xWKoH Wh,v/.-tV`$*ЬH/d%Q8v|ѐGrW}j.6d#Nߎl.+O o &cL5|QD'}DduR{CCn;;Hт1-'d?dQWeS1w[hbQ*zs.ƨ}O=>} vfͻ|YLfzP'dYNgT< 42#X]Ax 6r,{ǡA` Di\^oY.Y\ hKe9ohC([HYKDIDY$G%ڵJhixm˳.6c8&AiI\onaqԣiBDWǺ|]69!bѿSě,W5 ۘ\YkΤ{5zdT8/ˁ (!&rq(Qñ~sF/FpR@OJd>;ܣ4O.}蚞-fiB`ɕV &v,ČdOGO\u#]΃sh4cGoNh'YmŰ}l<y6v?aJ?J(2$0ii8BQzGN=G|zЅ]wS&)9iX'3mb4s۟S6N,-@w6$jU˯ᬲLMgT%($Q0XK?cQ&mc?C^@81ˡGȘ f? n:9c;_*ի#;$ln]Cȸendstream endobj 980 0 obj << /BBox [ 0 0 576 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-haireyefig3.pdf) /PTEX.InfoDict 727 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 730 0 R >> /ExtGState << >> /Font << /F2 728 0 R /F3 729 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 874 >> stream xWKO@W19dϪQRrC"046EvpP;Zb_dI j&J0*B{ L`02›!LI м) A@E BfwElN٠< q(Ȑ0ǴB0///KV-g|9~Z6,uS"%J"eV)R`% 2Np:J㵪.{]ld$"! |X>·W09hJ,Nc/n]Nтt8SI)Ua'J#I/jt[:&RR<@5iEh+~b86ӷu* ^5l[GC/=>E|(ԩ% z5*(.Tke? 8!.m@k` hqB^nfJط+T4+ 1 ou cȉ?r/}CEOf3M> stream xڝSMs WpDaM;SM/mYN2T]@89d4ewyoI![b^z`9`Xac/p!Hps]^h7w=nn[\ÎrWO,FG&ST P x0AXg3)4=`/&clT}xUwXX" kD\ n?&I\Eר`x|J>ś:Q&u|W•ܠ["!k\U9IӴ,vnMp&A6#uk:D="֖GИ6vi| 7AE2X$@>+Qz”SGiRh 42NL_Rta%%()(a }BnAgcTħ:e{adoendstream endobj 982 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 1843 >> stream x\mlSU~{;nmQ}\1jc5$AML&41&`™~$?6TNfc~Lڱrge^ tt-{sWL&!A,:d҇PJ2Cnw܁y~ժUveY(j||!t:^f;x`SS04MqGA6b0w#C!3>!qT -8\YKXVLBEEE-C3m޳Ǚ-͟W`KwCjjj6UUUU: |ёD"A* 1>r>aH$J׮-lmmdTۨﯨ(^WVV5$v:v 57 ÃDFErIiG.f|D01!RfgyeIVP+V!B!RxG\>t:fDt.Cx<9 l^^'Br)Ҿxzz[ZܹTf4ZLy^,8X,5&Ԩ CU xP#b1>*>\! %%x|W"H>ӧOC3BwWw1E:)ޖ&\ .\ (c;?/ij޶m *sθf+R\0 3͒i% Ap?y6k`*NHJh4֭#5$Wgkڌzj]/ѣGEyDR XFwJ#X XG/2RQY%*>V6Z]{Dt %7[fH*Qh&(O\?w0]'fkxj3\V\ze?/*?~9~2^xɲauXSyfR!+Q]YPjlc$HE-Y=w'o{Mz7*Q氪 zɄ'IҕUvdtJTUqDQq3OnʨD9",s%d&-ϥѱE)ĕ<iHx,Fwrn`LgA Q˪t%ʤ%P_cs%jǮ}9Dѡ_t4 duQ9+@iib?oP*ZB5,4-*!011jBv!ۻaJfx<4MP8EQ:!tʕJll6eq_!0 ~Uv4}zU/ ޝneAD"pwrAe`0(Ad҇PJ2CCf(}?vendstream endobj 983 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 984 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 985 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 986 0 obj << /BBox [ 0 0 936 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-interpolatefig.pdf) /PTEX.InfoDict 741 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 474 0 R >> /ExtGState << >> /Font << /F2 472 0 R /F3 473 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 3239 >> stream x[ˎWRZ#H62$ /"K|}f7ś{HQ<,]SŦ~n߯O߿^Qs2qRq0}z);5E3+5i549=[3=Oo7![;2Ș-(;wq[s(+ݣEIlA>9Rfl8-N!vLcܜS>'>q.j' ӀBa0d`J^^s^&߯+-y_&5ӏGQ_$ 1)0*?L۷&$~8ˤ琧ߦg/w8hgy,hFvG0!9}З@&ly##LY⥄͇<%|Z|M=!]P e NH?ݲ{/}9Kٓ\CgZfCd,e fLg)@Bݯ[r,s"< ٳD1uGo HYe^鏁&@Ya 3ȂF nyA^jy?lWt)Rα rFrFnx$3js#3LtIrHF3k;l(@Ac\+vF`CdVq)5ZF?12`;jLLnJ!Y_N`4l 3Zak&?hXe΂m Hy XDn1rv" HL\ U59!C)b|7 _8\50@0Lb1끃qoz֓,SQ ݊ Xbx?{}G u}[\-ah(x΍C&95X͒0h4{ڽҖ4V߰^*ʡG]o6J޽bh(ً6F37H=hsq4v0w吵E[`LIpwl6XkHNjߩR|n IJP4(cLT;7$C1l;|E{-0NBmJb|w 1R\մIW+&Jѱb2Z}\9@eZ}ÚhsJ9#{_+];.D݊!RN[r ywVI!6cΏGb{ Ѩ|:vΏF-킡7;?KiA((BhQ`F!;? $_Kِ귝/!;?Q1\'hr.@q`saboWIz \$~tאq0(iyCQ㣐h7FQp]0Tt($>rf 1Qȇ3#KqCl$u|'9n ^GRuc@(9Pt; zZk +v1+aA̞3ca %)1Dv<۬i;zgFG{ dQ$LpRPqXyd 1mAIX0x6]!K0q{@%N+qD r^$=0IMgIm 8pr܎ { b܎%nKgВBy}C Tͅrq0*%7 d )qnG9>U0Yۅ? 0J=mx9n̕w(@#xqnoK6W' r@%\9ܳ vvC-قN`c>2/mLs&q{ɚŹ%Vd!YZ9OV;h9n{;' a}øMx9n;mxI 1o@-ق Kjjjxk%#uqۑKc(J9G핤qے?pY[Z?n0b-$%arܶa0VۖƉr(ق%vPK6gIYQM\d9nS+gT^ bk"tmzxf 7_kk"ii ~L"ꥈW[װ5JQf)^-Z8vό]-d.B^+58zw^-dBTXZ:qj[^[kk8qkݏ`-x./[[͉SXHK>8[< Xe՜8u.C@3DuʏY/!x2u7'fC( !r!1/Cx1Dw@{z(e:^ov\ӡ7ˏ|!RJ^|"}ݔJuU.c##>A|r >F/i&4]O99,Q3Hy\`+>1u* }G&_׽Ⳅt\pGՊl0G~gٗ|TTbbO|'\q*Oz+y^)2Oe.aO{CMh~7}b oendstream endobj 987 0 obj << /Filter /FlateDecode /Length 2559 >> stream xڵYo6bq_* Iz@ڋC!]7߼HQkqZÙ<~Cf/ξ<{zQ U+\/TjE Unq,~I?7Iwջeڤ[3M^C--X8[ߞ2ywn=O/_YG; 'ia3 0,ȐUb?L0mw{~l IRڔiS;U7Gs.Ery= _1"WUd:JH9>R| N. \Qzr?ZN~@Bkdy[< n+{?Vs%FoΗ6O:nV+ȵ=K"&#ۀR-&,4RxV,)jb(oeʙg߯skUQ%Do幛k &slys Q'`JH$-5h ntDr{ա` oqv'5.aZs">miJDŤ'TA[(ǾGYsw'fk9љg6U33R9pDt[:ZM F}zKMht^g[ 2| {dL|F ~ |Sk @[*Y0y&q@/fnX&(sb` a/+~-Id73k\~7iK$dhEDl+.N-݁mkR9 osջmDهf#tl4$_n$"bEt9U~+Gq;*t]o"00-0U3Ȟ녢gḺ:j66e1i󖺡eZ,n9mIҁja>5ͪq^([\;oDosV ,l raL{3Uj2+])4[1gVѴ[/&S&Mh =W$+r|qJB2Lb{8vnޟZ@ ~rR Tf]ڂ}х4bO}#|`J=cP|ږOzDtno 2/Mx2R"[ K2:RMS 3j~WE3ȏg`dl2oHVw 4t˶xQTd%?u{E{h@jy۵dQb.~w>uғ;d 2}OW(8}75؝`..iO+.U7׮D Ƶv15~jJM:5Ԇ8΢~OU9)}zrczj^,++eDÄpk w1lv 6^);%2E} ?7 f,}&sgJ} f7eyU7t4դR]WTe|kb߃wW+.7+BDx#ʄ0s zF|f6w0ʟ6(Z_Nyw*we_beB.SU}g8$5ҹq:GӚx#t*#gtM̬m9|//Bsر֘´o\l$L`q'ck_;_hpgxendstream endobj 988 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3493 >> stream xmL[?qblfHh 6uLѪI4UӴ?ItU~ͦ*]wE&^1N!tt6fvp…l6;<ɯ/WxU 6>ӟWe]*IRQ84BQA Pt=(teYg+ "oj8Ьa,EE,盟j8ciTg$IB)ǎjv2BpI̋z![n|)L&-M}vіVŒa`akZM+OLVO^u#w&7oq,YЩsyϪ9Dnύ /b&cըr _$9:>fO.FXCjJhnn/]| G, `jGhh$SxOPWӲGk;i,T呡$Im::G0rXM@2ݢ$Y,Cy47]nv9tnlc:Pvr<6cL[8#3q{pof6;;w&鹌";ݫ*T%Ta"oh=mGrZྴ T/oģ/wݼ>oI9Dh6B~-{Nh=|k~P2[lȻ+EP􏞏D"w~b `pE(aYoݗ b)yTknJML5_3o}577/ǹye m]m4k=S=444<đܮW>l} 'O,p[X,Nѫ9svc($IXjz<BH(ylyqTUyjUUh$RN(<#L&f,X$xΝ;-+Bq=,oBn^F)DB4^񇹮yUUC+ȲN%Il@ N˲*Ȋ} bB"bzNfUU-K `B)yQUUPꭄY1r T^eL&Kd2AMطسg+=PJv;bbis4- ""mll,l0 zU@ q駞z ҙ۝G`{{;Fէ؃kb$Iݡf3,zBNu<LPDL !$vAɤ$Ihv(< "dGGrb'3|^eiB^oSS=w3>w[J V/NfEre2ɤ( !\.I>cAQr)244tAFJQAxxfbeYfRNqؘdRUMDlmmE9o(t(ٳU`w Ƃ d2tbOQD8*(>Vؙ q,M$X,zi$[( B!$ |j,T),wːI}il3??  v%sUU`mDѻw]tZ Jnp{2\6nX/^N) fN8ت-|>Qq$݄JMe1lI`Zʰ4Ot!H b܃.XD={nt>o׮]sK.a5@ pu<8CR<|>t4J~q:22ڭW[:`/|$a,z{zzAf|4 2;e-.$%J555B0AD"Nn,B E, 4y5555aMLLh|&q8h0hii!x> stream xڍt8׾J՘ث$*% VѢVEU*5Zw͢UV7wu=y9sG𲹥&b%@hPxOZA$(DI>4b@Ii@bqJ@ 4b1HZAmWuOj+J**ʋNj8H4# QH|JTx/%0@ H>X 5a1 wZ }8?$4FMVh#bu`8$DR/I큖@3/$1ܟٿ 0ap807n(O$LX0_@P Tbr0LFAH " g!N*{$]_OПC<O $Cm@;jAZv壋G"Qx]x0HsקW$>C!$I[n _"p8X-gR@$I%0X<)H"thݫ< mIB$`0e`o_3}q8P i_$ •#oVGگԼD_rn3cNJC35:x}>a݉vI]ͦZ93c52⼺+7x]GOw |udyxqdL-4TO%~eRYmPY_׻vY-p\yN{4H6i#s;wk|_7(<3T #Cc>ѣb DW=m6K<3GchJ^,EY;t*3AN-((#kl,E^7+K~;ϣ_0UD&O$J4^q4Y.ט *Gtݫ6Tc,ֆR=ƖG?UOxDJ)74" >SjS&>qIx1jEFL "䜎as)b=?+1Oz0SF \QOb;$Z* IZ-s|M/w^w5}D/M_/֠Wp޿u2.a [|;!դQf5~76&9 &Q87rWl+[k1U.ȁb5f>tޱ-9ԍqj|.;,}:ou1501YV ߹gV?0闓Y_l] O9 v-QH< Cvxlldm̩ YUIDWW/ _kv; h(&'fWU/>푫l9s ɥ{R;47P}jp}SŐ笏T۴R]I $1]$񖏧ޤ1~}糰}oĵ)t%Ջ*DMriBܔVY8&mj~u&1. =GK8 [ʥ0;\f9zсwOo@OO%J}R*͈2_,5NOWʼn{Xf2~P`7:3̠0ʀvwvO")4zZH(W1T"o]G8f SrY2K`8"bG)Q}sHbL''C)OԬ)Ya#`|ƴL;$BFhh6pu(Wf  ؗOb6uEO&CFC*/P%$bH/΍f oJ)pOauRպr)vzV7K+F<_mQLE,T.9 \{ς"R%>鶰xQ6ʀ-.5'-TU%l4zÖ"]ތpާƈww3JMb4t6=FJJM϶-nL{EbγhN<$t"a.F,(IѦ1֟n/BsVʇ<ֽO%r2w_^;S_vu`3MU/fzY,407|r4@2' 4?B%`AuB,67#]_7LmM9TAq*Ĺ'[fB"5bdCN9TcAh^_uvAZLђĻstjplW@)| N__>(}sN-_1;,+%"Gԡq 3LdȨ#U?T0OlrfÆ ;}aݫF9"4?qk7]/Yz&d;k%<PwKmg ît)U5?(&G.*Xqk$(on(CKH!kuۚyJ9sO( #lJ̀?l* .iB=oO-;oCu(Rۥ֊-˳%vw$em[V&*;}ꖲJGT4²*PF'zoslusmLY_%󅢷5 Fq'w!}atFdɋ _,Eodegy/wI1ksog)?\5I*!Zgو! ̦" $Ч{7nAKd˭orrK#uE%pؘ\Fۇ~vrdMŇ?h<ߵ1׳7VC_pǙ}wf TDڗe8S3=qxq''8h"GべQ ;JiADIx0iҩם~GiKvc]˖%Ku}"D^2N;@9Q鐼G̗N/ ^o{Zm+8WiO x{;Lz{ 0]`¦kk1pQ3NC S6CZ'*Bߥ}P N}tUT H|*c+8#oD`|FS4%o=S= kL 76 SlzGvgsP &>v[6:8"A=n'OW i+emUC/*xGkʙd-z:ߺhV5O|SQ-@)4 Q!cxF@Hx,ԆΘ}!;5k8Vռ0ȁ p/y[#:ì11UGϠ'W(VM 2{r6SS+ʥc?e't̜ЙLl|Ί}|NUG2vZT[w,d5Ȑ=m6n;-B<8?n qO=ʕuNzu2ςBPGēQOl)q㾆(1gX韻ŲjE<1csj0r*|<`)1DxmFY=U6#E9W|GTn~  +Y#.Ս@,i)nL>+ 7.1br[rۯPgn zTW5T@Q==\:6a)+B.TMFZzI ݙdijeoD(um2O: Wڰtݯ搓{Xmy 0݉I\dr.*e3:.^߾E<ʌhuXZ6ԪPx0ֆ0x|JQ۶'er9(Ler)w_/4 mXoEPXTw>M=2lۣ, Fra,Џe#\D,o}_c r/M6}9 Kg?˝,Y}k ά\=s׻7t\;?M|ۚYn$ZD#ꫀ56R܌A6=o{P(ڛukhg6gj ^l(^6V=(`{tXny}  ;/ cN;4G>%ܲpM|,s✑es=г5’ٳdKكA-jEU4ߟ[WNcwo*VM?xg 4zBȨ,("`27aks6Ğƴ?03;,'!9ukL[tb,"32&1}sΧHgۏ*(($;J ߟ;=NxcCLyRi_wgt3<_ a9[\ay=鋗*l==_# cxw>5STI/!3 ؞޹ <卟:Gi4Ek&+j![լ=g >PL ps JG7&HM1n] G(xN~cQدQAw_=TYRhĦ7jeaV}ֆnNMݛK-$t^PI5.C :K#tJ;qJkw;^ xW+)=eWፓ gasmxr+e8T !iW/Vc^ 2W8Z|(SM5E&=<3s*6J]LJ`&s(j!0 őE7';{l{M .lcΡFOXlb$j_8 _VLŞQ꟣Y}r-4z@lT8'5sT:\4g ୸jCc(G `[=,hx-xHE5]g R*)|kJ=3{5[E`..ed/u=#[&jyTl9aaѶƒ}[]O2k$ջQ_v?as~vZŊGT,Vlj睵u oHqK5HӯX8ETM*c|wl4tǭߵ=) pѭs* ַW+Dedp{f+|FʵpaD)(ne\+e[>}l],=I&|x(aYKZS,\CDeكDo᧵VrNd CF^{NbЛ=%͆dvV/uOaZgsHM,KX 'v+fxo?-ygjKs}7KZJ`0J\rfW.K}2q7I*:+M{5QMO^ҹ5VΏAy{`S&۔dJWD: P{fuWWrXdz܇2{ϗ+z|~OWbo(*O'F|XŅ G;1!VdJ:zr9Oo;5ho >GCwe uXr734 XT yqBdi)+ea2Ul᱙6·`xе}*=4'-Mk1}F{o8mexG\U hv~!k}ɾXa=~nFeg~uPȾwօ5=)3Kb 2 #j{ǧ޹PM,a*T=YkBW\ek An5N× SHDN3&RK>et­--ъPuG@%U?\wߐQt;6Kz\N - 1]ŭKO<.J =fR\ZdeD{{Ύ[q0/c>te R}E%GC>ڊ!S ~q.!Lu1Pc%IѐvY2zuX|KQvHDQ+dn _,FfMyJ(pڙX2F㇤d鮝N w2 .iӌ:mt:ŭiJߟĈ2TV=7Lp%6̸ kM@!oexbeIl`G6.I?FG*@=fE8m/3Op[k/76n;-AOvK5*^]a6rGd},@H8bDLN\e*;S SDϗp\cqE֑ɕQ:)c*$VGgno'}i?1TL.ubǽ5+|v~m:d/|$c> stream xڍP\-k݃CpFi%@<k֜s5-P !RVpppqppjQh]! 'п,\n/2isC'0@ pqpm*6YTN` VdcO%#SPw#di_2Z;,A@7 b,fasrcdxl@hMj -@Sdi @@0ltdh)(Ԝ?4`u8N6w gsKK'Ggs7l9jln^n,soCsӋ9X loü JvO |9wokvA`+4ܝu w_6/"d6@7/ zYڲN C[`BP|!@;ߊF(+hE 0x?N?_/fvk)*J0E?JII'//+7 w㟈 `k'$^No"M_k N/ 03F/?KH=ß#/yvw{  .υVZWf#`9gaSȂV 7K?gfpN{ŋt/gir@^Z YWld{x殮(/s |U+#`g;^8\Q~7.[ p ?Hntrx73v<A. 7_Dп _%ÿK%@Η*e/ٝy^l_n_p $vK(7[W?/-bwtˉ TZ\rK{ܨ@eaR8̮6Zēu{,IwKcG#DJ0v^sgWsɪ_FB}&Dٝׯf`+/EXn7;V̫ !ma -/l)V[ oCvNo C̥6:x/D8nqSj T(ϳlN>+V"dd7l@XYe]6m:QT}q9m3z_ke/->F*YS9a@S%ҙA;B3K,yۘ.Ek[1R ZSϩowm ,~w|MqP1f_@)#-s.ɔ@**j!{DKrR!`)Y&?$O^Ĕq^  Zar~ DHӉǣe=rֺ@!˜7?>z$(|\;Zf 'n6]oZOЫg 8B_M ^ +6'Gu&*5,]]i"۞ӎ-c-ĖJ5.tp B־ZA2BÂɧu^kΥDh)[p*vtT̕KpE~bt*oy$Rv:c2ؿd넢) a*+$ncV6؊'7]@z 35qV.Z P~6kI[XVH;iF0HI#i;kgP.HTX?, `LV5%}@ jwp1&4N&JÝhRG0*$XXJlٹ'&Ce&!|f*aSʐ4u/^h-' 'E^nÆ5-l*yYF@UFzڄし ɥttH| ̸"^80+h姂#Z/´!X{ˉ|,uzV6dpW!&E?b6[ %ɶGa"Q-ȰiI '1UhxCX -1owiMKT(i7y"V׈Q.4JsUf+E'!dz} -\ΐJ5oa|%M&x4îV\8^0OB톾W%%]3VФW*i.G+%&n[H'T8=lN^h=蠵Zl?cJi}D%R*t@h7WElB|0"M7'.5Q7]a!D(qOkF%ƹ-E)FTY'-(Ty3ppeab mCr.5$^ 7iZaz!%`v!I~gdᤗhrqwS19'RX5-v0^ï@,y]EDhE~aT߅6u#B~ޜX!r=ϧݭqtV?q&7ǡ퉭߀"*5b;7T0~NG-) h@j czlM"Ҋc8{WoFU2wCj?ح~p~+C(cZKD[ԹFtqcyS1좵l[-bz >C.3HlPY.ǔ ֡'m4O<AΥmz<(W|A5I8+tot.kDK2b}.43<UlKӸF b?35B j`ݣͿ@_DP) %{4\ޙa2x ýžsƷ < KoC`k <0=ֹGڑ;7FwVru\>S~Y/ޜZɽ;\*q:-~:)J`ě gA9 Z=JE W2~ܣ{}WzKO⭀P2q$R::yɗϹSwEPt #g^dLCKQ1FgIw'"RRUH8Fg:|Z 5?/VF .3ʘ_@x]l z[h<ӗf?VڋXXhsSfvQ zb|w/ktR:bل3ĄF`dU1u #Q/龟eDꆠIF=;&/w[$:/hl Hl*cC%{x7:G8{Nש#Ut`}sX5GNeDH9H0cl(?L?uy`Չ5ۣكFkaT CԚF0RY.wV'L S괓s2!1ԚH0uYtː>OՍ<ĉ9F_.M'r\"a6t6٥+h*0yq}&lYPaրmFjE f{f`f- *rZRXabm1+{C -v|фutݤ)n%x[Tه4cߚw)ig; $ԯ)[J HgI>żdb>X # &U@7@: +▕-Q}rbd=|SRbHyU@#M'ލ xGʋA uh=Sk~V}R]l>*ۮIpӥU`neXgƌ\m*pr`a"7SJ]ԇvA՝F2T{ZaܹǓPq 2UIƕJ?*ƌNz~1<$aWTq^?qʍ}4uU%헭$=,Mbhӟ( :cB]$ *ꋺdHCP.~ݿKyf9dWPJo*PA!V-F zj gdaq\ ObtXc魢{U$SpE&db#!kl8B(0mY8YD#8njizG%ǿ7sBz{tG0Qt$R<)߆"^blyҙybJ,{1{uvyp:@ z58l>:s Q?l7= 4Lԃ˒YLF$ӇLAfMX;??O=VlJ9Ȧ~hu Ż׬t8G"iL,Cx?7W=F۷ߪ`o!ݱF /WP|4cC xѺ"ȭ_4g.TScXYiN3oGd!7_,=W:3"_U| l 5u%BL2֣r#6<T&d.O3\ ނOu Pm3n2+oAjz9Uܱf  F #2u4_%;I2ZA wr_R%NڈTHMD,J1%g&Uѫ5}%P婞(yzǝRVc˒:F`,%VQO_Nh:e53n'pIb=i`QjH:`2 l ^pVO)[S"Wx4dXʨj U-O|ŏ7"tmt$ C ^/_:A:pM"jRb.PA  ,-L(ZQ­'- p;}PoWB]-u "ZuPWSxm ';ri1~1Vj&ƕۋa)!)Ѕ׸Lm kSY:Nzd6gBϱ'S>D6`ܵ[.[X+"yleiUZ~C|7*Q @[:5\~$l͇I,(b;ƢfVio"_>Vݍ Yj#``Qq'DޕpJfEGWjt0уT3EWH Q<նtsH xp~'DA16+Жџ#RM=lS:b4+gx|id5҈.FRox|5wXXdOQz'Os^ j`Z$ Dæ%L&m< 4!qm1lrb9Y Pqv57ldʹqiwjk>'&)+}oHh.;mOZN"_,g  ,eÄjzv F9Ha ߜ}:n#Xf AHt`g!tߗ4o>+, ?CAc ;zv';/S4 7pȏ"8ZL_Preݰ"D9AGgBWwVU#*9輱_L"T7lb3Qo Ae:~Zxʓ^EsH;̙MىPw`ǀ}Wi"^KL dO~ͽ7X|[F3? /ʻ-%wԵ筡HvL sZ\p ϫ:?* ؄~|'0+ל'(\O"z2)hF[3pYRAJZ!1ӍVb ,&&f>K5]֛ՊgD._Z6V QS3čd\1 w ᗛptDܬ^ؤ{w5 t8/ 1Ck 1$nB9apdVRCԭ{66oiaqQ8Wmo AyMћkSiΌyxAK <ڛ}~m: r>MjVz+HlH7E0I4DV[ͣJ3G) =ʡ0P/ޘ& ?Ppu+a!6 )qgzP؂=ILtSk`W ,!/NHH|v1{r.܀SDC Am:N7v}}e{f2;`w\M㼿I!nsoJ%j4L-f%J8 Bh]Z;jw _rUA(7q(䰸|Lnd0!j #^mG kҟK'%CptN҈3reUVnl"D0+{7B8n̫g oʨ1l`]Ar%Mm8(zi`/"M}L`=#D7\CKݏ>  CmNVIWe3p 2T B2\7cwF^2kQ`nGs+& `]"43b̗ƣѵأVi.W\{xf굧<' FƾUw!Mkq*6e0;>Ϸ',QaAzzY7d'XWsl~ u1tLp^~ڏ~F_5t_d/_s~G'S<@ƌq{(R04,[wj ?r$BޚV0&&n>$'`iS#<͓Qf%gC4f<:)rVbf睳#K5аi FG}ca&kF!c;-8<,n]{~m/|nh;E3cf=HHQ(La6;*,4'}'r=$[`=MKiS\cP]YXWQWo˥r%J¸t6<YY7ϗ<:g|!9Nc'#R>7%2˭+[X\Z@2)6@2]}fbEKh\Fa1_'U2@7´ 줈uF $Րodgŋ]ToT>uy2ѝE霭?<͞/mۦv2c kicɭ{ 9CkI~ R>7~,Cc+XKMʼ(Nw|DkeA43cNJ`(O&+xGQ!"~Hoq̚8 V0$Q w/TaGyzYZTL~d7GV]Os_fW+9Hӭ]aK 56YJZ3lFҲ̫$ ZB(ygx R7,s7eeC4(5&I4{o!g+ȳ3\I~pu\n;٭Q{pkW%n{C+))&J›N]5D2e-nNvX &`BS'afW c L.LQOKf ;evSxvϺ 1o)D#D(ɭu\~[{4Uuj$c^rf9!U,3`8B"ZcxO7xNYI2 Mi܈F]T{(OE1rF|'*ճ0 dy;r^>ApRzq|qe6\ݾs͖ބ!S6 d[xqa qj|X'Yo1[C+uU|X#<ytNj}Uw}DKSN!\d> stream xZ[o~ϯ$Ù5h E.vP`((,)q{!Ernѐ˹:7~ʤ3Ge\ͬ0<ͣҥy/v܅LVF-`t}0zt \E?.l>߷0x UథtiTd2n;pӌ-X~*;vH#MMꎟl "Bb3QVjA/[עZv23iwR;&y<:<˸;+,4.JRx ֬eb0Q6S14^{8)}j8niyMa%u }zHyՈQՎly­*WDP67ZD95'f!^ G:Y.>D!Ńx["%CN}0<B.N9`J_`df+L~ 61l)jlz6@O@:R2 3` >Ё0*h#q>%{O%#MoHw)5bWDХV0ZR(eɹPF)KdTe%m8HS)~3f:ӼtWL iгAVS;5¬cb,PROPMy> ՞=c=b~ yuGIwhlZoi{ʊZi._rf&OMKGy.%lJPPؐr׃)$C{"c2GB&2:wS*(ã:eFY. ]d5 "<2Ts-( =lN>;QNS6 οVHSMpk8roAKcցo0E,.Ϧ-%&cw%XNT>v%4@EF@Z/-6uqoC 4,DF*# ar(?L&YA; *wU+>Y(= ,*V'l &~ЭR_T 0RcpXa/3'er/ˡU +M83;i`6?+DP+}>{ ,͙@04?v‘m4ʓt uĥkLM|LK- $d1l8\;P 1T\)+CuDG$j TB%Ǵ9ѐl;/n\b>[(ҎÚ i/g%a4%xEIPy|ij jlo1pk9BB6STB9x~n}{g|z}Ɓ^*_ܫh+>niZy+FbE[d+xT0i Z a*}@9 kr 5>5#C 9lupoSLMJ5nO@bk+y*){W˂9pqÐ9 AoO;hʃgtQ]ժr)Sjw`0)b$ RwE9%>4f q ^+'7NAslY+#>x]kERm&`㡘KbI&ߧgՊs @I\' ChcJa(Z݆Kj̚Hʮ,#3uo+~@Țu/.mԕQݕM:8Nu6״<`^Je^=x"J7LW b^ x"~9ƹGOM?Uc\ƻ;kvZnfpqOf]@xoI[m Un[".ukp{LV`Nop"%TVQIoOD۳)dQw׏;тAa-J}54Aȉ"#) d=遦x)`Np? >J,Os3J)tz\Zwg;&RMC/0D^~[zS,->>$j^)kW}UPʳٷɇI^N졋o M-ȭvO QҸTmS^x3 -I!Cq?uЂ7_̡')3t<]G9~We]b'I=r/c' 138KSϲq^S'nTV> /Filter /FlateDecode /Height 106 /Width 75 /Length 2623 >> stream x\k>շ"P7EuE 4YsPJQ"4C I C^z_i,ܹ3wιsιzt0sGx1|~2Or|>e !enM$u0h]&d]~w߿?aHdcc#H); 5 )m jFDB)%z=M"vcoF9n4† @ 8N*`(X&t:e%IƘmR)!K$i`0뺲ʊeY0 n`1eL۶4!C0~? |s3`D+Y6 k{a鍍W^k6s*B}(~?J)FA`ԧ"^^^F1D̄/ 9zZ1͠98s/5 "JӐ&%^C@@z~2HDJeyy>в,]׽JDz=LJ)WVVrЉjrȞ8x(iRJ˲Ns^,cL& !qsދg۵mas1xLHy,#"ߏ:>>hyvvb\mxLc y'R*'bBH$0 X@7J?/4#fs.{J$0fWWW @1r5۶.ܒs ߚ꿊nȏ8:zJ]3B!u~{(7K:~vvvp8F"/_ppQрZ>~s\VkJjlv]j x;̪6c 86w x>1T\.1wx/FYr>_ZZZYYfH/2 ʐXo")۷BlY]]q cHY1ozϥ@^ú,hET_ˢiT 4r{H-¨ڏJQF?qA9YBCnl6!"pԈ?Dww{D kXT*tZWJaRxIΤxsb]Q !e2;ns|QUm|bUǏ߿y,j66k˲6 LǏQa!YEy˪T9rfD-VFÛw:VÇ/_ yuxgЅvUUMCA9zP( CI`ƘOӶmQ\bB{N%L&+ QAK9o6D3ƒ$(YL&SשO{jH!JmҫX^꺮*"I)Ux!6|ɶp8H!U&D~S{]=5M, EϠ!&D5oeUG0MŻ|#bF}>mXV#jG4sj.̮Th4&FC w߆w1^}Tcp$Tۏ=2MR 2B`w=~DИ1V5dk~0 ԚTdifSEPm)rԧY#b}Be(˲(ғeY˲p :}ナxaÙf7b3X;gψHέΫmnnx 883ߎӏiQS'⏷!7" Q8"ь0 QD2Fnߐ)!.&L}6ׯ_ҙ&/x\ӧOEJ:0s^APm\#l-uMJR)appb3`*#͟MGbnËp5Pg62iz~Nwb>ۏo?#c>ۏMIQendstream endobj 993 0 obj << /BBox [ 0 0 864 864 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-spacingfig.pdf) /PTEX.InfoDict 761 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 764 0 R >> /ExtGState << >> /Font << /F2 762 0 R /F3 763 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 714 >> stream xWMO1ﯘc8z\AmU$P[8АhڿچTk&~3{{'p߇wVAk|We\4>?>pq ynL548r=#2D:3r[o=a;|؄)*+[V9>[Pb6o=k 2>Z97cy 6F~ g@Rew}V"K4nWƓ86V8X(Ӆ{v{l4z9M!#Rz5_|fgr3F!J]r>vz%"Km^dL2;_/-:*c'jWg Dr}lh:cH=ٵ}=Md'I+O*QzEƯ]j+~sꍕ)ّ) ~eߑ) [Oa#SX9VhSM)YlED *}WJ@qOUd_te _؊\SO{PE'0JBW/Nק> =) =E?O!r=L > stream x}SM0+|4CoTjQ/m(dd!i~& RZE1{X[(eX2KaT\DirV5'Hﯴ /ԧ43F']Lq vS+Z5jwڪ|1ԢX['[DFz~Ed l%V> /Filter /FlateDecode /Height 106 /Width 75 /Length 1533 >> stream xkMu% Z={كR({ H=(mRFV )tib4 .=,o<ݨw>d~ff9uttDz#HG:?rH)M&49筷s ptϟ?tJ|tC#ba1dYk|ǏL&] >?ܹsGӓ';FQL-g k'jF)hhv4A>di4 BHXb.\Ю`>˱@k yzߡ<>.,,1LFu[PJgYիWkiyyyaߣ ]…+ɴ*;QpBԉ|> X599Vg*f*ipX_JY[8$ӟ-/Yc؋/VVVR?~;L&`RdҥKFa"NOO{ x\=Džj/^~BD"߿k(@ B[=xhJ%۶9皦={lrrRj^/rfmۮT*r͛7Hs^(cPs*_UUM&O44M]c|>idYEQ BKSUU4m󊢤RaGqq![_ㄚ>d z|ӊ<Ͳ٬+o߾9J"H.+˕J%)R B{/R)Bȹs'tNg8ℐb;yooOuF7tsX<jFi=344&!Z 9pymyr~#eW7mHG:?ҡtC#H SXendstream endobj 996 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 997 0 obj << /BBox [ 0 0 576 576 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-ocpairs.pdf) /PTEX.InfoDict 769 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 771 0 R >> /ExtGState << >> /Font << /F2 770 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1542 >> stream xZr[7 +f cL̴ۙ3mdqԎ3~q6>tǮd  !/7G}w돯Y?oή[1j2ߋwʨ RoaA"~ZDSFQ1姏k Ro9d+;8s/.Ƌ[|A y64į䌟vvWr3%no_'ju͊I7EV7:.o5'hjuH>,_#X#d`eaiCe4݇3y*Xev]VAƔCLƒ~\~Rxl~0Aix{` Yͧ}OS<}>zw;l5:ec`w|enmN Oڟ{)je4a?Y_˾OyE8"$ݦ#wy!q_$A:8"Ԓ{F:|d4aBFArlTWߓQD}#ds ƒ̠{n4geͲgƀf4K;]}@SO:?X䐔;pE6I4 rCgT- E,%P<$*=^7ITz.xK fK$/z\nh} .K0qw`Dv(qX^[بGYs/8|2ÝBC89wKoQ bxf9Ξ8<X6CLGe@ 0Xu-uHG@CY9H.]ͬCS[9zwC%jgu&e a6^ΉFGR.s-JH 8rv\mle/ j: 2dW_˪~L#ax1W{RT`$ML$4 o_E=&$ܜ aU}@U s5Xi(`=sEiVm,h@ζтpDjKTz&ah:7I4z.X$QD$f`#Hy+(-NH+k!!>샴x{\C9&x]'MO_0r}NfG؈F:9ˋG8-e`7,E}tO帲8<7wCB'dA=YS߿hx %%彆b91[S~cG'a+rntj(ۯ8,-Ե4Y@b)J9?Xnt!k/9Ӣ9/ *qMdr0!jfW1\zoq'| 7e''y f[ H7[I/?_?eA~%gq#g]PG`e;ﲀNK{`6  0-튎{@iz(Nq_򎞀a_endstream endobj 998 0 obj << /Filter /FlateDecode /Length 1978 >> stream xڥX[o6~0 J)RbmͰ6ڡP$fKd'~΍h!PL xꫫťkGE\:WfQU~,TZD΁ ]nTl$I0<ӟ_utG\&7A_aa'EsBwZ(OS>%6VOX:Cxw$ xSULz ]%ҶH_ Ywsl"}^/eԓ'Evݣ< qM(pRL&(6Mhu@N0 yqqHyOlw<7 b#sP se0x"'OwF$i(2<Yzƺ(*)fFw0IZ(qz+2:';r[+_{xk_].1$so]$\\,"0%Y3d>J3i8V舒 bXr-[ Lů)UGvfԆ1`t(#iʢ0:$Brlavp\~vP78pǁvlI1r<%aɣTy7d% L{#/ ڰX&7Q#⨍PaR/)vNb dǹs|4e1KȮD ) H+J;Z -+'9[Fvn(ۡts;Uq {GOc<T]N3 $BYM m5$ڶ<#Ixikf!Ky1'#x"ϖ"BÃ&5JH}olI\ecwpECmL9ȍڡiJ4GlИ"xv8ҏX $Ă9p(U2Į֜Z"kf3,QG#T)Zn6XFWRKJiOh~Rrp?axDjV ep[@.X6VJn%"Rvgim&3}֌.> /Filter /FlateDecode /Height 106 /Width 75 /Length 3150 >> stream x\ob^imc6EVc*H@^QU\+B/;RL+VBB6Uڊ&ک$^Yl]9Mz9X;γ3EQr1M@ӴL&k:EQ@&E1FyUU}>,.1H$*J"p\ rRiL8T/52T{8C % ۷eTUM$V-'1QP&Uyy݆;OmGIbзeYfuJF,W_}`~7ϟT*qܷ~ |ŋ1wiii$8掍]|h1B8k׮Y,w}ǟ| f?7ޠhtb̙3@@Q}bf`6)ߨRill1fJbPɓ''&&è}ԔlޛJ(]]L'I62Hk:Kz 7o|R'Op'Ǐ;R-8qu}9 B4ȧ$JUZjjuuutRR ͆7FGGnoDEٶbؤuA>|n`pnnY:K/駟@8.JgrriVVVΞ=wב /cɤ@ c \.`P(`tT*oKKK_~A"=Ntwwo2(׈". ݽW]ԐZxE EC8lϝ;w\R*޹s'ɐݫ8ub\|GFE1P+QA߿{n#pyy\. F?==p8;44dܿgRbŋCk鹹`0:_((}Ms]rn߾;+Np8; H&}8}4YZZrD\BX˵5z*y&faԖzo K׮]Y/2ΛgffH8Jn44M(XɲV甗4]CiLL ![|>r(cccmyY{ aK.eHUl o ?1ܽ{VU*͆|/h&YZZz@XtnfLr٭_Em#-$6w4&g?,~ѣ&L0aV^dK|STkk[TO:8}GSTff SIebXG1 W_}Uѯ *X4zi*Ic9N 쩿x-͋a [JtɮHfvc|ZeݎϪt:@*ЈgYB( /BcH'Ivd/8lW_UU<*xy*t\[[y燆qx%l-6)(`3h4ZJM&x̬M /EnА8uꔦit'uv=K[VE &ԩSPLgkkK:c,Gq`ddv[D"1<6|&`lBIC,L|>Ob0x~1G" 4Ch4zjy8H!OE N}."d2tFv$XTCEٌ eYEnT.z)g?xFt@^BǙ"-//oll \rp<@hX3DQtI8>NHQrz5/ſb%L!NX8+_[ U$nrȓH~?jo&m)8pDQA[nnn"iM1r4Mif.> o-/~aaaaa; endstream endobj 1000 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 1001 0 obj << /BBox [ 0 0 576 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-ocdoubledecker.pdf) /PTEX.InfoDict 778 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 781 0 R >> /ExtGState << >> /Font << /F2 779 0 R /F3 780 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 908 >> stream xXMOA 190+J-z@VI 36ae ~7|X~| e#Er<'gZJ +58ۜ_I?W_e`lB9A)D)BtuٓOI;!(D2g!Fd_1ph1G0I@cp> nb5JhLEAY0@,]ʮNJ% x<5`† |mȮJ\ (}&CRg6MdA7XNxJdቅ B|,2᭘k'^{'K'S-Ij?g F7p>X޵CP?pN=E,nv;}FA^ɩ t 8xX9tjJ`(i?`Đ*tJ.epӔ2 (/&e.r6 _1aA#x|Xivaa#x=VR:,Hd6n7`K4`X8&z$Ja0},n4WR> stream xڭY~>REs|Mױ&*P) ;)9(rп\.u<Nyfv-7Z߼P:b}N)e^c$:<,W٤÷K3=<66J$yiqiˤ9AGL>ٿiQy`vn2ax,V.O`˕6ʖgƵzq$=2uq?2k%W]rûL6up-SL3[w}~2 jf<ܷS 'e:/XR#Y;6HxU .ueC֖"y7،}WHwujj2.}c4{ x"VMa߉̐yHBLkfuԆdA HB? >?ȁ/L/'n~ FvsvjJq%s߰(@(橯*> "ՠxF p:|R5dl*{~hFV7)zx&lC]_K7eD^CR25Yx?7 |N43_5_7?[鲫h]BVq c,*,J& #m~DcҌ&GGqBSi"^H';dx,g.U@e#ߏ?rtܠt͈{IP:azZ$.p?WlgӲrhi}v,h U&}Oaq"8}+d[}cxl O ATЎb'CBA:@Wy5,P *y:YЮÞO۳r8Qcچ$X´6WEtoR ɟU'fD Gقl XEMjl|ʂ#x0j1S󜋦.-œ)%.rl:>on@293w*+{Mzc [!+!m˩ j~ت%_B;,X-|YvM& 9Xe ط)73bUreʎv;|'D!܌x%Xv6@q+ D&s. a$%ĭTFG@I@틾d͏Q `U68u2 6x O:~ mRT7gs y_%&FWKʣ XX¶HQҗ9Kǽ&xTJCc Q5I1gO{J7t8"x??y r3&6,WpܥI!cmM!F`NOS|+dMI%:P Fj e亘Bu%wɲ+&+&|//EfÆee~Cy%]VNBfC!ҽc.=v6[;1dવQ{f#o$kNd&5vPp!GSSH\21+ݰ=Gfv+5;„-'g0r<:]I5I ?*8cF+MlCBIpb!i?g yT@7x2Ae `3# Aq'#`@-5AB.ʢ-a<ſVi69\\xfaNX.{)Vh02Ub,uQJ݅> /Filter /FlateDecode /Height 106 /Width 75 /Length 2700 >> stream x\OwY .WbФF <7cl]oWx`4M^@iҰI(㮄P:R=|^'iaQ|94ٝy:_<_\\8s"m۶o0>>^.SSS]]]DCa0\K?wվ$)뺮ׯ^jF6ݳgI8窪r'''߯* csDt]4-Jpr@'*91t]ٳg9r]]]d2Y.a?`oHQ"bRp8c\ "âLMMɲ(ʃ8 CgiҝxǏ%ϚRXx<`p޽_~=sL"O̘gYZT$Iڽ{w4]ZZz~Q[[J%5c>}bkkkkk(fN:::|bݻݻfoݺ~6O>MӲ,֮iY2#-rX,JkEVVV hoo'l6{ԩH$⢟%us1dž:vw 6hÇu]O^sJ9dž69.ȿ `O[lh#ƙ1cYV&AZG:b?>>EI$,#ƶd2D?8u7W"FH$b2$IfR ]g2889_\\PUUeiiP(dirYX2h<-]m{j[D%\B: l sAAKA}Dr AMD0dY ^šml Zv"V(`"O9JE"܊&'GwEgU 50JG֯21mp | o⤚Xd !VD,HX g8[wmQg qZh-u,˂EDBq.!( dY"hفP(KMӢh>58XU \ÇeRA tE aRp؏‹4hEX#EQPͲJ ֍ߢB8n/aģѨEdC,؇рׁ3+6@OʍJ础kh ]S$C~ 0@\ao1y.Œ/zΰ1!5vXpԑcxg$I|^n~W]&Ţ~8>8/ƙLӬ XKGɢQw&v6T}2s[s.(4U"HQ>trJhr*$vԡBKPNMDawm; }JxsKg?jCQ X۶0N!2555;; v j-׵D=cÝ^|K36>6>6>6>vendstream endobj 1004 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 1005 0 obj << /Filter /FlateDecode /Length 3349 >> stream xڕZ[o~_aKv3HqNWeu-Qx-{áD) ̙s΅Jgهon^~oܙI*Yi WUngFNyER˴Enbf2Ͳ,|{7{;|F' &i[{HC4sq';f9iIu@^g)ך-m[q2Ms:Mi>mIzGZO2£Z8cUįYBFIU״yMеĚ!t%Gr&%^!hS5}A#YZr~ HeJx2y[HxE\`I,Ndcn >-1W အ XN;[NhioT[P3v*[yYM>)^L F,<@d4ѷS$Jo飬,[Ƚhx!~K/YyNZCnoQYlNU)Vsdm9,dݮP|{20RMl @(H9r?ڪE{y!PSDSN$N. _-,P,j/vg[?W6Hb& R9>K3q(Cb^g)=l|;*֊34^@yLh*i݁A6xUoӊYG,E}r@0Z^gf$ qRf$))UITD.I p=c(hu ҧ߬1*T4;a4blAiYE4LBCi}O$@q6dۉqFRDGxEXaSv}mȆ\./D 9t]!ZJ1jdY+@ڔp3a oѐBɨ4kD{gWFףǥ sb?PNܢfѷ2,1p;; @(J;IPRIP"B|BąlHEbgRėZdELJSb{^uV˚}N _LB{ DѠp❞zK9 yQLcQ`- 'uG,+|Rg+A@N{oгv+9cRx:ttl0wXAKnQ )nq9tw $ hٻcM5~ !֊FE=D*'jMT2 ݓx(֍O3iƧ^xs4FeE#2Z*J6UY2>STQݩ[lwZz,bΰZ8'B؟@bCĤۍYZ3OEmF`SxץO(/EgZL%>wjCTpFjrEk$<& :5x$AG0 _Jy߳9x/mWGkg}dlބPFFH!^͂`9[AQкd}-_9z V'EH$ PSq'ZwDb|8~4H-pקYoghIfG/7:@#[GRaXS׎G,߫u)3U)J,qrj,u@91:NGli,m D,]u 9HAnR~8'ǛW>d?v "~^8 S <n4ɺZS!LcPA+, 2<$Wͭr֬)t2tүeI{`&S<UJgSUFJ{=pZjS6&[# _&. \t} Hx$l8kA/Eoiz#tuS K H+'sMeޑkS(#-(bG(7dJNYxr(ҩgIB\:\ii&|0P(>b YȪMM$K뢽SL9M4! ~Wõ2n9BגM4t;~/ڕ뾯0V7ed`):5Mxp|*{a,c0mf[qxլp9@>MqkNo;qC(p263f'vJE4cioZU6y=oo;;Lu@ה=̓7-^#f El̠U!%ɬ*M2wOTnƓJDLj.{ PR<$GcE|AZwԀ3ehbHZd}DV;8AH,ymoLD"U$U|<9G}'O֖ |Un}ͫ*Fxb4 rɰ܅K}l/!op v$ ꐑ@raOGuas*گH{'cA$ZȎ렀.Q|&Q'oNBcSbX<7ձB kPOw7nr1C^%et=(<"Ϥ偔U mZ{m#ծwHBt4Fd4P(db2 $Zn ; =Zm\> /Filter /FlateDecode /Height 106 /Width 75 /Length 2946 >> stream x\k?'U.!~zCBClAv%^t]]u @馳iLKQ0 F5Ɨ ף1c-~&m9> s?tOLӡMQo`tz?pOg?Rc dZvƍL&# "Moq]7N?~Ν;m3I)GqNx!ygY1hljhFN9mcY,ggg#MӶ4W{E">cBGă<Bat "hqq0 ]]M&R JR&"]( j#u=|>ܹd2yDQRM$",G+lcyy9"Lg G[[[}.IVWW\`AT逦imP!"yGRJ۶0TL<"P0 -OLL@eYaDi&ЬɷsnӧO2 Օ!4P(:==ޝ("Is`fX,H)r,̺Ϸm'ad2ID60 QP(X5,|H 6~<^9}R OR-"e fBe!HDNP((9nBal1y"p]7A`xՖ.9xNb'RҨWC8!ɓ'B=z;#? ?55K۶!xj0t:^ ? mN/\2LOMM  QeY}tȅ+Wb9d0 D& j*M`[ h40u%0nRizzڲ,VQр]xRNNN"[VNMMuZRmXHRjBD"AD{{{Y*p0 }gٶMDJ_}ff.3:ңņRZT bћ{/ˈbѲ,8i\ZZwb x@3Ɩn߾ أ.2^?^C?99Y,;}?L]dR]KPOI j+Jz]ׅ4 ˤFA]3'X[[$$lΖe9C]B`ƒmW*\VUaTHG@ YR.//뺾uX,zVt:J .A7^|2_10 D5<|q'zxQD U(E #fRJaԫ?~) },uٳk׮8iQKR*sm8-vE=d7u]8z>phd()n?t4q<GmBIT(HpA8Λ7ot]GSraa1ŋk׮eC)Rk?ضz B9Eu P@|/sahpe TBl6k\wٶaL'w@Ǐ5M+ 7n4U'O*9Gΰl6D!XT5@#!ip*;K-TMl6m'2ԗH$/]:C.Af$e$AGgc?e<={8XIy~J!t4 ǹ"4F! s6R7sL [ 6T *# &ASf&~fOK0Þe:dk@3W0Ça ;w~oCNj>z4H`brrjy!d),Klnn"'~9e<xFc=r7oޘBύ7*Qi*&"d^Ç|iiܹs= @u]ue]8lW7=S HLql68zڋGRJterєB;o7co-CПt wǹu6glFv6.߾l{uc8;͗>{',c i<`WVV V %Qeeg0,BHVPoa0n*j*3sazo28pGJ4CR~E''iNO8tz?pO:~2endstream endobj 1007 0 obj << /BBox [ 0 0 720 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./strucplot-ocmosaicnull.pdf) /PTEX.InfoDict 791 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 794 0 R >> /ExtGState << >> /Font << /F2 792 0 R /F3 793 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1031 >> stream xXKo"Gϯ#h%HvV{@f6l50pgꫮw]~ΖyNWJI-VyZ^Vka% '%FC2OvWO¥ ^DOţ*f*r".^4dꐄ]L:I>q̄-&cHnub̔R2f O/$iZ)b)>vS/ldٗC*t_IiQ^ШY-# FV;užSVW]AĐ%]%o[K ʾEQeMQmoQXS}!`l"K kS] ls"R_Crd~{]SdEM&/x8qI856zv4jmlR7*պuȼdаV({4]Ufp8a6>2 B$7@&(#s:znr[a5\Oc͐эB1EQ(iQxSX%tHuz yvMݖ; |DgBwXYQD){A'Źi Ikެ }C'\5 |'Vh_TV{(6H(+{G.HaВt>gy?B43鞛<>V/&3ri1ZQ wâ8{jMkE 2ܨX o7bw1t`[E3Iq]{`ˌ .\B>SvS(o">vmAW@'h g7z=/}x A:| YygY:gW]xt<5W> /ExtGState << >> /Font << /F2 797 0 R /F3 798 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 862 >> stream xWKO@W9d؝}WVBjՖ+1UP4Z}gʛ;Zfo4;}7=l*PEДPXp&1 h]XR 6Gkp8>B!?gQ!l mGgbrF)v0lV~5GP5*7Yi$bDОyc&%hZs!_.glzѾ:Э7NgD|t7q&84^ 9.)(j\'0:|)),o0ږEL'լn٬f䠬f5||N6V%~#JK}^Bk8,fq A{L$)z~gp VBߵ4h @)s.Z)qnXľ`W~h3 hC_$U#A)l:"D:=BBNaU^ dbϔ<];ᚬ-D.&r6=^ՓDI!]G Bʅjݖ8Royj䆮v*9\/r>Jqt;2I:󔭞/vendstream endobj 1009 0 obj << /Filter /FlateDecode /Length 691 >> stream xڭn0z ) 걋(>h{P"y ɵd~pI4!( p8sɊp1{fRY+AK"eŔ4%!׹}C $7haϐ&]KGrYz6ͅ9_Ify>6(E&`‰ BLAg3δt.ӹ_L;a^YϾ')l1w. ]ŴA> /Filter /FlateDecode /Height 106 /Width 75 /Length 1712 >> stream x[OV8sHHjD93Ce!큪hb CK[ITڭjQmHN&e $Mv9|ߏPgؠ;w a3>lGFG8Y!4۟>}ҚK&ՐkQCI:)hl!i g]+go#¿eΏtA9(S)~lVŋ!/'R Gryl$E .]Fsss;G'l"lΪH&7BzlVk yO#;Q@%lCo߾ zsfCk_ǻl>@W ́]zV|RYmM\z] O>]Rٽ?{3 NRpiQ^d'-;Jk.k&3$I~tARy>Ljh@ϿҚ8f YOqs!EQtQzχj8l)|0԰Tɐ$;wT*u 9 B^1q#'Q:;pxP./χB!a @Z,FļQުާ_vO3bX.oݺfٶ###GO`z;L$i$Mti3y~v8>,Re0P(Nq\yLJZbxi448\(QO#J(!=Rr˗-Ɗi`W7ZU,ˮ6[J#6 iVχ?>N{ }"b8::ʲ09 e rOZmey||e٩)d(J561ڤ_8롱8at/4 HT풚p8å%$A/y^UҨi4S GQߏ*飯#\E,AЙ1TÅNP(΢$I"IO P0 ESswQXlvvVH!hoWST$I1D5b140x=ٌvK=:Rfh} a3>lևZ6C3cSendstream endobj 1011 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 1012 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 1013 0 obj << /Filter /FlateDecode /Length 3283 >> stream xڭZIsWrH*FoڗJd29@$Di, AZ萿5 L@7Ѝ^Hvf;gϞRnG%O9=Ns:Gd?O=v/89 BN/F**GccLt5\ &K]Xc^rk3YXA;,UmKy+rVGctȣ{,R+pP 8E8By%D4Mbmj4.pT\aUt ^bu1AAʵv]&Yh.6]Q,\q#馈V>qfAIC$?-3 *%xH.I7\hSPhr Hd0Xb&A~"rh.JwFehucXP^ޮluh"iBݮH|9 0OcjZ<ܐ:!hkͨOQ# ;.j^:ڛ@TM \`s`!518ĽAՇu۸68f]=(fnb0׫'k63|iim [bc8v> EA~-b£oY,JJ\lzhGpח~d}u\̜ٮO*|)25H[t@0'kDׂL¶d72R63"$,UKX"upJp)mY\=]ul}mk"ҷ! 9b%q.|y3Ւ/kxE< *b,Zk1 ;]ߧ l TBcCeEZNRwLHb<%;+ #m'k6\7+n.\632֛.Zϱ8f!Zk "뒺"t.m*J'pKlVڢ}ma4AGs)y]u/VA  [$5W-ilkR%&j$I͙Oݚ| qlJ.r< ФԲr*A,b?}5̈́@> ȵZaДY2q}}8o wI-&΢'$ #jzC~1*,O.?A IQ .g]Bb2"͒Il}C"2қ\4д%߯Zm&x;'Fr@3 HuRձ@72x3̇٫F#I2 K0բKZe" [,P"hw"O@>>1Ze}&ǏUKCzC VQ@G&ZnS!pk ns kڱD*BtX,qhMqޜm&Ks&~]ՇbCVX) $a^ȫH&J }jlA&iBU.ψ'S?!@vqCѐ݈F.d!}~<$Un)Lȴ]x/#dEk2~Qƚv=d֌횳]/A+jǦ :i :/sXVxѺ4 V/d RbҀ8  c0JAv01Vt~C0 094Ԋ9G+loͯ( 4ؤN{OOYVHNrz bmm'f$>p{R/r /I}~Guܫ$Q#)Ǒo$} 1ou23L'StO$CB_5J~+Fx4-X@S~GOpatvX>R5I8bvWۦ~?ت<?f,(rv8bE\GUCCa穳>u&6P3 ˑ ֓`]'>zx<,,¯C\y]!X6/88UBȐkŦ}n>Ig.-y?^>/ 0endstream endobj 1014 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 2892 >> stream x\k>C[Bڨ>о@)}?Ԑ@Rh"7(%( j'FɍƫykA7m,lYy|;90 i-r/w;ɷ|;ɷ|CT6=RJuhX,ҒB)u=F)8Gc>+RbF q 88y1ƲO?4==cL1VVkzTJ)|.fsפR)۶_zx<.`1\ ͚j5 ңY}f"s[J)0ɏҺGֆvRJ"CR$_R7T*D"!1Ad2/^q[J$\Ns0 Q-B(ٞc+++1zhիW9u8BpT"}ǖeI)'''AHݿʕ+@)=!FFGH$2aDk(;J77[.wfq^]_^ǓaG wR*)w>M-, :c)/"Bܽ{0 HnJomYV]d JY<MRJ 1m6`lǰ9z$"!%$ *a @I <:͂?v: 7ߜ9sf}}0|>OD ӗ_~4/bggG)vyuAxî!BJ.!"p#T5ەJ4c@\D"aIDo7[[W^!ݻ]w077cӇf/; ֆ 4͕B;;;sPjf鴔T*=~>4M;N ߺM jhn4PBd2H] wyR͕e !.fq@%Bķ~{rr… ejj*aײ,~c7._oem;L:88;|՗AS;CW=N$'8WR2ΡMpqeiȭ߿9vQgHsx듽Xj6C3U%8h6ba-j!jJ5ZB/Cy9*U~>aJTo+vڵ?L:Rj~~D,˪dRJ<.p?:O}"jO G]z^1rΝ{ 2 6ilC0i@e2L?j-uݵ5L㍍ ȟ5 ?0$D.,:it,+Dԩ+=b7n?LDtT_1 @ ULbƇѓfGы;yeu5-{zv`P/:/ Ȝh*R {EU+[tnNMok@D<|pkk zOovú\\]a<\ZФ*55ϤA@ԞDcT12ZY\^^>{͛7`llll_JH$Vb!~Wy]YW銵)hpR_nhM xZR1!zy#DcJRRJ.6Ryٳv_r fi_=3%*@OKj.`c cvZT*k9竫h?Q "FIvc u=> stream xZ[o8~0eeVDԥbv:mg:"I[,8Fbɰ춙yؿFJǙ>ئC:w.r4ѫ'/#yHn1uj% ZG>kn[5ܐ,G78&g=6$V6N |9|g1 %{ñ{8*JC%p~>_^Qf6s!}bUa;ix1E  ::(VׄCj9L%E*<*zbFy,>e$Ck$N8Ђa86;=? AT\}KBoyjF ؈~;v3=QceMPZ 0PJ5™ F7?;D 8Αx`G=+I KFqB$Ҩ+^Yѱ"GތmƎnꊻC41YºĢN_gA]%CH|N  ֌xj\|DP<20wEab>Ð*M?w k$.y?BO6rEmDqb~y?&*8MUL4ᢤcdxkJtsɦ`h۲$Σ//yDm~^8&_Wb! b;!6e):Zr< ?^7W&)%I!xK]GRp-moG&8EUDp 3iuM1> -ZAN#BYȌ@HKl5'1`}z b[Bw}:_!De0:5SkR -Tno BZ޴ʁm! IhHk9)[KU0shD  6m2F"rYtd`W\kb6C [1G?ilhiK@mWa*$#c$vg5BOZfJ=֭mfGRP9/r= B$+(\{#XDͪ3|>`k8},/d_p+>|R>:ud;IGʀ2Ą6Ր;Ƀr26mk 9@섮sс[ y1l>ZTM'1IJfb]v릕r!ʒI ٴ&6j޵N7# mBN$Ov1"l3';yQFoʳX h(7 w7.k1r{ c( 4=KtUr[Bf]:;t5L}S,:},<hy/0_{J2vm}z|űvR@rNd)~Y㘄=bq%ޮ}&: <=ub h mɃTw})(uYJ(Gʡae;SpA½$:r=Kq=N^w}nn݂=Dpy@l(nLd2lm $=$ICm~d\܇F)|,cNVv4+FJMcxo2+y"#%.[ \MNGКaAHI#N'QPHu) xHIg v^yA(S'`'=ue3/qwdO2{وbZR3l'5Tc GX} ^J{!׭)ljBx;Am?5bK@B" 몂(?շqTȨmܓoHIl]&U[#g."`iGܓ sW0K] 7Y.ۧo"}68\fX!\x?ۃ.MfA%pkzXSv/#Yf`L0X4a%ImՃaD;O 冷[i %+]mee%ɸȣn8Q,:4;@VPNz),C) {dW`1A,q4ɽN0ڭu^g.k" KҊ v{'4vfTtӝD/쨣"D$,\AZX`+P|x;Yv/9쁠.q:bnXVsuh# mqBL,޻S9߯!ƃyI+Zt.Z4ݲg^ɳ.VW^#}QZױ|GRT qa 9A6Qrv>X(j!%͟Fv"Ѐk᱊u|$5$i^di\Qr,Eԛ{?psS2yNG4-bW!ڟ.]G&Et,ɿHhK=FlU-0IrY9_ZƗ(^J컱d^Hlw cZ%vLknޕKy;3ېp{FHoaz'3^}&x|hoiLIc`$W=6me Ԓ(2LGTnX-\`M/T$0$ /Wko*p+,xX"1N,2Lֶ9_YsQ(\qM9JBBwdr YJ1hPa˥'eIw N͟.k)#|NaǼK3_+qNV <̝$Yödfe"$ωyҝ;l3W Gk d^b}Pkõ9i(wv(tA.egEMlVZ>&NeD#S8˃ Vi.ۧUcىQ&x7*V.c-G(Ge{e:CPOPl~r܆Wq}^dC4jq58luq.܉C06od*IUendstream endobj 1016 0 obj << /BitsPerComponent 8 /ColorSpace /DeviceRGB /DecodeParms << /BitsPerComponent 8 /Colors 3 /Columns 75 /Predictor 10 >> /Filter /FlateDecode /Height 106 /Width 75 /Length 3104 >> stream x\OhռXH&(Aq!P-7A{C%֘=Hc,3KvgVV&-Çؖk%G0|*Cv.4)z=O? 8emۜssW:O_~M^[po=6\~pز,!l nd,"vMܭ\.L&9JEUU8!,N/+==ּe:)e+?9gY9/ iok,Ky'Wc!I\@>Wx? ߕLge2˲{0˲8iO)E&٠Z8ΣGnݺE) m` \]]u\׭v[6`rr2&I|ys"|0773 1vʜ"[ևɤoY06DBRahyhO|)5 J 5NO^;! a1ƄLu,٬itJ}!DR.u}ssnW*H$h48uDqeq岦ips8X8)EEGԒ\4󼃃0l۞o_~%`jшFs!@\0Hzt9<i0,7od-J699Iye8jw!(W\<ڵkccckyx<f&Hs \ 6MSQu#=TU6s^,8r9B@]v߲.oY#l~y+K/&Bl /,[7nl>w/ӹ={DzB޽[-BRPݻuSC!B)2ڨnŋ`mm<hr'ɮ:*vd#ŷoh^R_f?3@Kt:ܯw a1TБPuVe]IP]9_ZZz eft4 |ep9VTjfffzz󼩩)u@QVNX8R D"9y\yP]8wE9zt9<=,+LJFT,߿Gd2)HQzFQs0=EQ+¡ٔ5 u|>JukkkDhm<z(1UEHeaYBFƳ,9,Qcu!دTG"c寬liڨo r)YT!!dET*1 2R<},lS RŎXaO mUѶl6۳%1u!~iMx.)=i`T*4M}X,aZ RX sjFlV=bÓ'OFFFD` ۮds,Ze2EQ ` 93] qg%M>]X gv5m݌6j0zPhZXQâ"Zүj'5MCg^|q :k˲ -,,%p8[Ғi` Ѯb vvvt]}X7pF?sBy d5 N0&!!P;9^^O!eғ'Osz6؛PLLӘ}Y^^}e)x0 JR:~^iNio^{M?q_:99){0eU@tqq1H"JVp8O>}?_f\%`EM 6: "9fXi8Q;+.A3==0??c^cRX&y)W^ee̾xgFZ5 ciis D"t˲nܸL&hTUL1._m*7Mƹ(LJ񈢏+1s:!#͹@U/r4jv]?2G #SU}ssu]#hwDd`UTE>R.Ye=&ۖᩏ'v`ƥ<`:f;J"xܶmL%+WݑHXz=͛7@U'7-JY'|`2I40%8NV2"P];nQ'1e& 0'gG="b1z *4t{{5i*sh#{T4cZlZI;{fffw^6cX!J}&㻾 %I4Ą:h~,yd  c"otp.jvѡI)=ZxKQe)Nq庫rw#{Y:aSi8Z޹s?+/m{tTU~Pwꡐ A97qaqvH]ûi&uS!Xad@(px ctmoll`Ʋ|yse<bRfѭ)x\ M>Xzyl6{܁~ -? 8p4iaamendstream endobj 1017 0 obj << /Filter /FlateDecode /Length1 1524 /Length2 6869 /Length3 0 /Length 7880 >> stream xڍwT]6!5H7 0ttIw0 CwHHH7JHw(]]SZ߷f{}uξ̰0hm!Jp$SA A^H¢E8CX !P8L? ҧ`@"503_/"/*@ pw  T y;l#uC60 qP_%إW >>ooo^^Cn7ԅx@ܽ v_6.XP?"zp{;t8C2fq"T\!?p ?/U l]\m`P j)=E 60_@g82lc^ PIVh'A;uEW>+..k} Pw|i"bgyBT!]|P! n@ؑW }_W /7E+h$ C/ -?? Fm!PH79P9@ЯO!Ü}>e>M##CU#8yE< ?HT(*, w/6?Uap,?OpAi A`YS.^o`ujOR pL` 5!k 忣Pdaa P@촡Y 8CamՃL+ z@7UvD( ,qw i jq / @pwsrDE|@@>, ? OKȧi%}].Q oϿ=ݑ=wHٿoLON#ΫeyV02΍x,݊#Vߓrg˕,Z5s&W> +m8&Lܝ%0NԡIwh>hÑsc!`{9JR$I,1]Dm1[1YR-$K_zhcCռV#=4 BXUsJmmuR~q]r+?:x0޷D.p{^bg<=8D 2?ʐa zw8F{](=R[{8 Q}Vȭ l{-I0186i Sϟ|%Ę,KurSnluKv,M FkT $a\g ^I揆 B<6K5Z gj0zn@0q{S .~SJU=xY(kWm1gY OM}ʝr# m,lf÷zFQfYXCKPsWMq<{S.yk#k1=RAjTu3XvB;C\.+--vl~FoGd 9V_duk3#%8O D3vqIty XyIͿ 6:=jW9[`Uu“ Q8}~wOs8\ĵZcz 8}Xܝ-9(;[ɁȬSYѾOZf^0Wc>\; wa#n|Y %6&+J_$' GZ>tugM}UaTyR衭zJd_F-5U ޭԵҔtOŒF΢+ >\EtSMcXDѲQ/]{&U^X"4{KvëMʠ^^#eB>GW$Xhuz $GZ)e⧋$7ڪf$k-CqîۈAC 0Dx"NfLF Fj觹^y;4#CkCtcJɯ(G"իyCJ٭S0Y Q.TtAucөT/K?ƝrYGTBJ o|-N_EaO _dWs+(^$.=Q}@8DFKmU 0~3!WO9$k|6ب5-[|Ы7FvdON+N**rx5]5ZQ u+L[p#W 71"**4Djn>#*)JGwcPoSɒ# jljF$!HAv؛qԞ R}Ec|8حe${&guE*ֹ s Ɍ1~PRKF*ru&oD W&j ""kdRRԆ2kE|[@oKjDǸe u|Vĸqg{~Au rQ{1&x͔d$B-;s&:(Zϛ 䱖KnLzo rـ@it(9➶}uuZn2u?sugR_*t@*OWq=& ;֌sOR Pz1Skh,ۄRC>,.χ.p!j Q6` ,U꺜/(\jn.ץ_Mis,$64Xg86,]gR[d?k&L ; _1|Lun@[^g93(~BX7b NS*BtkiXW{ jm%0c *|I__Sl;y&/5P҇K oύl ]5DO{r d[Ff= n7`O(*In}2120e߽ !.4{sOpZ%;˟\W"n4-ˍYyR>yPVn6[P/ WǚgyQ.>pPGni>.T}>g)RlBf N nT!/4P?ՙtu޿g(x0r> ӷ,ŬoC>RNUd?Cΰ9Ϧ+ :ۃ{7 I.,}OLtBKm(^d'wsFd:,uѸ){`#*o/?~JƷmRNqR4|¨[!ؑŪƲT885uuuc6LҋJӋS=?H3 8Jk%o.N2y5򨆝fg^%zir0K#R |Sy*pRX-shL+Ugg`4?ޫF桀J r?Q/h֪A66:z~׶S 7J Yx>E\ "7b̭&.6=`|^,5>ull@T;o*_J:"%ѝKIanyz&dxb]ېOp\ 0{[ȭ_AP^e)XKe9;P*8銠z@ZR)wQtQ9#7xq͢nh·FYM{i\E牰_}d&HlX"j{g=UZc 9YMwb܊OMŅ+{ il)\,}3-{Y3q.3Nvޔe$gq3{BC*/ѓI}z%t}k.A6iQLmIkѼU l",A]4h43E^)(S7$1e=שY |u+W=鷣/:蕅p^_R* uKY#4Emӂ|p_F I&K0yr־m5) B3lD.ܱ[ZZz{cllyD}k1=#|?jsh6LʁVwϳkđ1_H_H孭/YN~|vJgl>hu];vAۙ -OxB}:YzNY\ /,,$7Vo%a~{IDt#Pg"es~d}%Mo.?gvi ]WSB.`>V·D%CXyK!'q5)Kq-&^-joO^f'IqnKi.ɝQX)R!<O&YRVXj|rXPzͺ]\0'78/e䰯HQ3"ASPOep|msr2JpXOGܐu&GycZj偲2B̳@2s;˃.Ch=v1:1sdCҘ.nxqWL?3dBF>Җܕ708`*a$($A_'iƶ d~36`FI5_% sOKß QF*1 K}v빟D]%܃FcoLJ/Q`;> myP Uy(Wx;M}69*4L3 g2+!YK#+kk!!51F:$ގ2=L7CY:]˅Lfgh4D3n2xf3yLԓeCK^F?g u9Nb>Ž13Fޟ^J]l$Βn3jɟx': 3|wyObtv1:Յu)׷V|yfn_M~ _2>R)zf܊|7Y+7cU8[0ܺ']L8+ٗ"[wS؇7`Uos.kǬT|S[|=Y \X)hg,ѭg\Ǧ(6=‪9##3n8hN x!/sΓd4WxzgNPvĊj˚?M8t5\*҇˔xL[`.7S+[qB 7!َܸ}]Y\e6#CՂ6s-{CRkc7*D氰jG\kFT+;ewsr"r£l"XzNӊ# )kZNsrX̛/#YV +Ee?*zvklRml% "K_=EsԳ|+CiJ3,j{TM'v#9W{̖5vUZL{jn+zL1tvYw*񭄵.y7,5p#iko$%ϡk +> /W [ 1 3 1 ] /Info 92 0 R /Root 91 0 R /Size 1019 /ID [<67f8aa2bf646b2293f27dc097f61ce24><22f349574fc9faffcccd282880aaa1b8>] >> stream xϋMa9s{35ͽh4kJSX $De",$Id a&! )w!+jD"FH4hsw9}y{u,8e7mhXY:z'jyۨ0M-S]QaZVD-iI υա ; +h~qz4IщVde,VE2 4|\(on4|%:)2:1L4F|k0M'R&C-t|`˺K-G΄0C6A0<ϸLU=U0 WaO>.9؅v LW>u \)m-KdxޤcTtjmS2}GRE,~Xz 9x$rc/.D_ޮ#箑mj<+O_%:@ok9z0(&z^ Xxo݂d y6N}{%簈vԥRL8fzMQh&$)=An;{ 輷ާ qT-;r endstream endobj startxref 681482 %%EOF vcd/inst/doc/strucplot.Rnw0000644000175300001440000031127011720426623015155 0ustar meyerusers\documentclass[noJSS]{jss} %% need no \usepackage{Sweave} \usepackage{thumbpdf} %% almost as usual \author{David Meyer, Achim Zeileis, \textnormal{and} Kurt Hornik\\Wirtschaftsuniversit\"at Wien, Austria} \title{The Strucplot Framework:\\ Visualizing Multi-way Contingency Tables with \pkg{vcd}} %% for pretty printing and a nice hypersummary also set: \Plainauthor{David Meyer, Achim Zeileis, Kurt Hornik} %% comma-separated \Shorttitle{The Strucplot Framework} %% a short title (if necessary) \Plaintitle{The Strucplot Framework: Visualizing Multi-way Contingency Tables with vcd} %% an abstract and keywords \Abstract{ This paper has been published in the Journal of Statistical Software \citep{vcd:Meyer+Zeileis+Hornik:2006b} and describes the ``strucplot'' framework for the visualization of multi-way contingency tables. Strucplot displays include hierarchical conditional plots such as mosaic, association, and sieve plots, and can be combined into more complex, specialized plots for visualizing conditional independence, GLMs, and the results of independence tests. The framework's modular design allows flexible customization of the plots' graphical appearance, including shading, labeling, spacing, and legend, by means of ``graphical appearance control'' functions. The framework is provided by the \proglang{R} package \pkg{vcd}. } \Keywords{contingency tables, mosaic plots, association plots, sieve plots, categorical data, independence, conditional independence, HSV, HCL, residual-based shading, \pkg{grid}, \proglang{R}} \Plainkeywords{contingency tables, mosaic plots, association plots, sieve plots, categorical data, independence, conditional independence, HSV, HCL, residual-based shading, grid, R} \SweaveOpts{engine=R,eps=TRUE,height=6,width=7,results=hide,fig=FALSE,echo=TRUE} \setkeys{Gin}{width=0.7\textwidth} %\VignetteIndexEntry{The Strucplot Framework: Visualizing Multi-way Contingency Tables with vcd} %\VignetteDepends{vcd} %\VignetteKeywords{contingency tables, mosaic plots, association plots, sieve plots, categorical data, independence, conditional independence, HSV, HCL, residual-based shading, grid, R} %\VignettePackage{vcd} <>= set.seed(1071) library(vcd) data(Titanic) data(HairEyeColor) data(PreSex) data(Arthritis) art <- xtabs(~Treatment + Improved, data = Arthritis) @ \newcommand{\var}[1]{\textit{\texttt{#1}}} \newcommand{\data}[1]{\texttt{#1}} \newcommand{\class}[1]{\textsf{#1}} %% \code without `-' ligatures \def\nohyphenation{\hyphenchar\font=-1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font=`-} {\catcode`\-=\active% \global\def\code{\bgroup% \catcode`\-=\active \let-\codedash% \Rd@code}} \def\codedash{-\discretionary{}{}{}} \def\Rd@code#1{\texttt{\nohyphenation#1}\egroup} \newcommand{\codefun}[1]{\code{#1()}} %% end of declarations %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} %% include your article here, just as usual %% Note that you should use the \pkg{}, \proglang{} and \code{} commands. \section[Introduction]{Introduction} %% Note: If there is markup in \(sub)section, then it has to be escape as above. In order to explain multi-dimensional categorical data, statisticians typically look for (conditional) independence structures. Whether the task is purely exploratory or model-based, techniques such as mosaic and association plots offer good support for visualization. Both visualize aspects of (possibly higher-dimensional) contingency tables, with several extensions introduced over the last two decades, and implementations available in many statistical environments. A \emph{mosaic plot} \citep{vcd:Hartigan+Kleiner:1984} is basically an area-proportional visualization of (typically, observed) frequencies, composed of tiles (corresponding to the cells) created by recursive vertical and horizontal splits of a rectangle. Thus, the area of each tile is proportional to the corresponding cell entry \emph{given} the dimensions of previous splits. An \emph{association plot} \citep{vcd:Cohen:1980} visualizes the standardized deviations of observed frequencies from those expected under a certain independence hypothesis. Each cell is represented by a rectangle that has (signed) height proportional to the residual and width proportional to the square root of the expected counts, so that the area of the box is proportional to the difference in observed and expected frequencies. Extensions to these techniques have mainly focused on the following aspects. \begin{enumerate} \item Varying the shape of bar plots and mosaic displays to yield, e.g., double-decker plots \citep{vcd:hofmann:2001}, spine plots, or spinograms \citep{vcd:hofmann+theus}. \item Using residual-based shadings to visualize log-linear models \citep{vcd:Friendly:1994,vcd:Friendly:2000} and significance of statistical tests \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Zeileis+Meyer+Hornik:2005}. \item Using pairs plots and trellis-like layouts for marginal, conditional and partial views \citep{vcd:Friendly:1999}. \item Adding direct user interaction, allowing quick exploration and modification of the visualized models \citep{vcd:Unwin+Hawkins+Hofmann:1996,vcd:Theus:2003}. \item Providing a modular and flexible implementation to easily allow user extensions \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Meyer+Zeileis+Hornik:2006b}. \end{enumerate} \noindent Current implementations of mosaic displays can be found, e.g., for \proglang{SAS} \citep{vcd:SAS:2005}, \pkg{ViSta} \citep{vcd:young:1996}, \pkg{MANET} \citep{vcd:Unwin+Hawkins+Hofmann:1996}, \pkg{Mondrian} \citep{vcd:Theus:2003}, \proglang{R} \citep{vcd:R:2006}, and \proglang{S-PLUS} \citep{vcd:SPLUS:2005}. For \proglang{R}, currently three implementations do exist in the packages \pkg{graphics} (in base \proglang{R}), \pkg{vcd} \citep{vcd:Meyer+Zeileis+Hornik:2006b}, and \pkg{iplots} \citep{vcd:urbanek+wichtrey:2006}, respectively. Table \ref{tab:compare} gives an overview of the available functionality in these systems. Most environments are available on Windows, MacOS, and Linux/Unix variants, except \pkg{MANET} which is only available for the Macinthosh platforms. \begin{table}[h] \centering \begin{tabular}{|l|c|c|c|c|c|c|c|c|c|} \hline & & &\multicolumn{3}{c|}{} & & &\\ & \proglang{SAS} & \proglang{S-PLUS} &\multicolumn{3}{c|}{\proglang{R}} & \pkg{ViSta} & \pkg{MANET} & \pkg{Mondrian}\\ & & &\pkg{base}&\pkg{vcd} &\pkg{iplots}& & &\\\hline Basic functionality & $\times$ & $\times$ & $\times$ &$\times$ &$\times$ & $\times$ & $\times$& $\times$\\ Shape & & & &$\times$ && $\times$ & $\times$&\\ Res.-based shadings & $\times$ & & $\times$ & $\times$ & ($\times$) & &($\times$)& ($\times$)\\ Highlighting & & & &$\times$ &$\times$ & $\times$ & $\times$& $\times$\\ Conditional views & $\times$ & & &$\times$ & & $\times$ & $\times$&\\ Interaction & & & & &$\times$ & $\times$ & $\times$& $\times$\\ Linking & & & & &$\times$ & $\times$ & $\times$& $\times$\\ Extensible design & & & &$\times$ & & & &\\ Language & \proglang{SAS} & \proglang{S} & \proglang{R} & \proglang{R} & \proglang{R}/\proglang{Java} & \proglang{XLisp} & \proglang{C++} & \proglang{Java}\\ \hline \end{tabular} \caption{Comparison of current software environments.} \label{tab:compare} \end{table} Figures \ref{fig:arthritis} to \ref{fig:titanic} illustrate some of these extensions. Figure~\ref{fig:arthritis} shows the results from a double-blind clinical trial investigating a new treatment for rheumatoid arthritis, using an extended mosaic plot with residual-based shading based on the maximum statistic: clearly, the new treatment is effective. The dark blue cell indicates that the rate of treated patients showing marked improvement is significant at the 1\% level. Figure \ref{fig:ucbadmissions} visualizes the well-known UCB admissions data by means of a conditional association plot. The panels show the residuals from a conditional independence model (independence of gender and admission, given department), stratified by department. Clearly, the situation in department A (more women/less men accepted than would be expected under the null hypothesis) causes the rejection of the hypothesis of conditional independence. Figure~\ref{fig:presex} illustrates the conditional independence of premarital and extramarital sex, given gender and marital status. The $\chi^2$ test of independence, based on the permutation distribution, rejects the null hypothesis: possibly, because the tendency of people to have extramarital sex when they had premarital sex is particularly marked among married people? The rate of such women and men ist significant at the 0.01 and 0.1 level, respectively. Finally, Figure~\ref{fig:titanic} visualizes the ``Survival on the Titanic'' data using a double-decker plot. Here, a binary response (survival of the disaster) is to be explained by other factors (class, gender, and age). The gray boxes represent the proportion of survived passengers in a particular stratum. The proportions of saved women and children are indeed higher than those of men, but they clearly decrease from the 1st to the 3rd class. In addition, the proportion of saved men in the 1st class is higher than in the others. \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[p] \begin{center} <>= mosaic(art, gp = shading_max, split_vertical = TRUE) @ \caption{Mosaic plot for the \data{Arthritis} data.} \label{fig:arthritis} \end{center} \end{figure} \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= cotabplot(UCBAdmissions, panel = cotab_coindep, shade = TRUE, legend = FALSE, type = "assoc") @ \caption{Conditional association plot for the \data{UCBAdmissions} data.} \label{fig:ucbadmissions} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[p] \begin{center} <>= presextest <- coindep_test(PreSex, margin = c(1,4), indepfun = function(x) sum(x^2), n = 5000) mosaic(PreSex, condvars = c(1, 4), shade = TRUE, gp_args = list(p.value = presextest$p.value)) @ \caption{Mosaic plot for the \data{PreSex} data.} \label{fig:presex} \end{center} \end{figure} \setkeys{Gin}{width=0.8\textwidth} \begin{figure}[p] \begin{center} <>= doubledecker(Survived ~ ., data = Titanic, labeling_args = list(set_varnames = c(Sex = "Gender"))) @ \caption{Double-decker plot for the \data{Titanic} data.} \label{fig:titanic} \end{center} \end{figure} This paper describes the strucplot framework provided by the \pkg{vcd} package for the \proglang{R} environment for statistical computing and graphics, available from the Comprehensive \proglang{R} Archive Network (\url{http://CRAN.R-project.org/}). The framework integrates displays such as mosaic, association, and sieve plots by their unifying property of being flat representations of contingency tables. These basic plots, as well as specialized displays for conditional independence, can be used both for exploratory visualization and model-based analysis. Exploratory techniques include specialized displays for the bivariate case, as well as pairs and trellis-type displays for higher-dimensional tables. Model-based tools include methods suitable for the visualization of conditional independence tests (including permutation tests), as well as for the visualization of particular GLMs (logistic regression, log-linear models). Additionally, two of the framework's further strengths are its flexibility and extensibility: graphical appearance aspects such as shading, labeling, and spacing are modularized by means of ``\underline{\vphantom{g}gr}aphical \underline{\vphantom{g}ap}pearance \underline{\vphantom{g}con}trol'' (\emph{grapcon}) functions, allowing fine-granular customization and user-level extensions. The remainder of the paper is organized as follows. In Section \ref{sec:strucplot}, we give an overview of the strucplot framework, describing the hierarchy of the main components and the basic functionality. In Section \ref{sec:shading}, we demonstrate how (residual-based) shadings support the visualization of log-linear models and the results of independence tests. Also, we explain step-by-step how the concepts of generating and grapcon functions can be combined to provide a flexible customization of complex graphical displays as created by the strucplot framework. Sections \ref{sec:labeling} and \ref{sec:spacing} discuss in detail the labeling and spacing features, respectively. Section \ref{sec:example} exemplifies the framework in the analysis of a four-way data set. Section \ref{sec:conclusion} concludes the work. \section[The strucplot framework]{The strucplot framework} \label{sec:strucplot} The strucplot framework in the \proglang{R} package \pkg{vcd}, used for visualizing multi-way contingency tables, integrates techniques such as mosaic displays, association plots, and sieve plots. The main idea is to visualize the tables' cells arranged in rectangular form. For multi-way tables, the variables are nested into rows and columns using recursive conditional splits, given the margins. The result is a ``flat'' representation that can be visualized in ways similar to a two-dimensional table. This principle defines a class of conditional displays which allows for granular control of graphical appearance aspects, including: \begin{itemize} \item the content of the tiles \item the split direction for each dimension \item the graphical parameters of the tiles' content \item the spacing between the tiles \item the labeling of the tiles \end{itemize} The strucplot framework is highly modularized: Figure~\ref{fig:struc} shows the hierarchical relationship between the various components. On the lowest level, there are several groups of workhorse and parameter functions that directly or indirectly influence the final appearance of the plot (see Table \ref{tab:grapcons} for an overview). These are examples of grapcon functions. They are created by generating functions (\emph{grapcon generators}), allowing flexible parameterization and extensibility (Figure~\ref{fig:struc} only shows the generators). The generator names follow the naming convention \code{\textit{group\_foo}()}, where \code{\textit{group}} reflects the group the generators belong to (strucplot core, labeling, legend, shading, or spacing). The workhorse functions (created by \code{struc\_\textit{foo}()}, \code{labeling\_\textit{foo}()}, and \code{legend\_\textit{foo}()}) directly produce graphical output (i.e., ``add ink to the canvas''), whereas the parameter functions (created by \code{spacing\_\textit{foo}()} and \code{shading\_\textit{foo}()}) compute graphical parameters used by the others. The grapcon functions returned by \code{struc\_\textit{foo}()} implement the core functionality, creating the tiles and their content. On the second level of the framework, a suitable combination of the low-level grapcon functions (or, alternatively, corresponding generating functions) is passed as ``hyperparameters'' to \codefun{strucplot}. This central function sets up the graphical layout using grid viewports (see Figure~\ref{fig:layout}), and coordinates the specified core, labeling, shading, and spacing functions to produce the plot. On the third level, we provide several convenience functions such as \codefun{mosaic}, \codefun{sieve}, \codefun{assoc}, and \codefun{doubledecker} which interface \codefun{strucplot} through sensible parameter defaults and support for model formulae. Finally, on the fourth level, there are ``related'' \pkg{vcd} functions (such as \codefun{cotabplot} and the \codefun{pairs} methods for table objects) arranging collections of plots of the strucplot framework into more complex displays (e.g., by means of panel functions). \begin{table} \begin{tabular}{|l|l|l|} \hline \textbf{Group} & \textbf{Grapcon generator} & \textbf{Description}\\\hline strucplot & \codefun{struc\_assoc} & core function for association plots\\ core & \codefun{struc\_mosaic} & core function for mosaic plots\\ & \codefun{struc\_sieve} & core function for sieve plots\\\hline\hline labeling & \codefun{labeling\_border} & border labels\\ & \codefun{labeling\_cboxed} & centered labels with boxes, all labels clipped,\\ && and on top and left border\\ & \codefun{labeling\_cells} & cell labels\\ & \codefun{labeling\_conditional} & border labels for conditioning variables\\ && and cell labels for conditioned variables\\ & \codefun{labeling\_doubledecker} & draws labels for doubledecker plot\\ & \codefun{labeling\_lboxed} & left-aligned labels with boxes\\ & \codefun{labeling\_left} & left-aligned border labels\\ & \codefun{labeling\_left2} & left-aligned border labels, all labels on top and left border\\ & \codefun{labeling\_list} & draws a list of labels under the plot\\\hline\hline shading & \codefun{shading\_binary} & visualizes the sign of the residuals\\ & \codefun{shading\_Friendly} & implements Friendly shading (based on HSV colors)\\ & \codefun{shading\_hcl} & shading based on HCL colors\\ & \codefun{shading\_hsv} & shading based on HSV colors\\ & \codefun{shading\_max} & shading visualizing the maximum test statistic\\ && (based on HCL colors)\\ & \codefun{shading\_sieve} & implements Friendly shading customized for sieve plots\\ && (based on HCL colors)\\\hline\hline spacing & \codefun{spacing\_conditional} & increasing spacing for conditioning variables,\\&& equal spacing for conditioned variables\\ & \codefun{spacing\_dimequal} & equal spacing for each dimension\\ & \codefun{spacing\_equal} & equal spacing for all dimensions\\ & \codefun{spacing\_highlighting} & increasing spacing, last dimension set to zero\\ & \codefun{spacing\_increase} & increasing spacing\\\hline\hline legend & \codefun{legend\_fixed} & creates a fixed number of bins (similar to \codefun{mosaicplot})\\ & \codefun{legend\_resbased} & suitable for an arbitrary number of bins\\&& (also for continuous shadings)\\\hline \end{tabular} \caption{Available grapcon generators in the strucplot framework} \label{tab:grapcons} \end{table} \begin{figure}[h] \begin{center} \includegraphics[width=0.8\textwidth]{struc} \caption{Components of the strucplot framework.} \label{fig:struc} \end{center} \end{figure} \setkeys{Gin}{width=0.6\textwidth} \begin{figure}[h] \begin{center} <>= pushViewport(vcd:::vcdViewport(legend = T, mar =4)) seekViewport("main") grid.rect(gp = gpar(lwd = 3)) grid.text("main", gp = gpar(fontsize = 20)) seekViewport("sub") grid.rect(gp = gpar(lwd = 3)) grid.text("sub", gp = gpar(fontsize = 20)) seekViewport("plot") grid.rect(gp = gpar(lwd = 3)) grid.text("plot", gp = gpar(fontsize = 20)) seekViewport("legend") grid.text("legend", rot = 90, gp = gpar(fontsize = 20)) grid.rect(gp = gpar(lwd = 3)) seekViewport("legend_sub") grid.rect(gp = gpar(lwd = 3)) grid.text("[F]", gp = gpar(fontsize = 20)) seekViewport("legend_top") grid.rect(gp = gpar(lwd = 3)) grid.text("[E]", gp = gpar(fontsize = 20)) seekViewport("margin_top") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_top", gp = gpar(fontsize = 20)) seekViewport("margin_bottom") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_bottom", gp = gpar(fontsize = 20)) seekViewport("margin_right") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_right", rot = 90, gp = gpar(fontsize = 20)) seekViewport("margin_left") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_left", rot = 90, gp = gpar(fontsize = 20)) seekViewport("corner_top_left") grid.rect(gp = gpar(lwd = 3)) grid.text("[A]", gp = gpar(fontsize = 20)) seekViewport("corner_top_right") grid.rect(gp = gpar(lwd = 3)) grid.text("[B]", gp = gpar(fontsize = 20)) seekViewport("corner_bottom_left") grid.rect(gp = gpar(lwd = 3)) grid.text("[C]", gp = gpar(fontsize = 20)) seekViewport("corner_bottom_right") grid.rect(gp = gpar(lwd = 3)) grid.text("[D]", gp = gpar(fontsize = 20)) @ \caption{Viewport layout for strucplot displays with their names. [A] = ``corner\_top\_left'', [B] = ``corner\_top\_right'', [C] = ``corner\_bottom\_left'', [D] = ``corner\_bottom\_right'', [E] = ``legend\_top'', [F] = ``legend\_sub''.} \label{fig:layout} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \subsection{Mosaic, association, and sieve plots} As an example, consider the \data{HairEyeColor} data containing two polytomous variables (hair and eye color), as well as one (artificial) dichotomous gender variable (\code{Sex}). The ``flattened'' contingency table can be obtained using the \codefun{structable} function (quite similar to \codefun{ftable} in base \proglang{R}, but allowing the specification of split directions): <>= (HEC <- structable(Eye ~ Sex + Hair, data = HairEyeColor)) @ Let us first visualize the contingency table by means of a mosaic plot. % \citep{vcd:Hartigan+Kleiner:1984} which is basically % an area-proportional visualization of (typically, observed) frequencies, composed % of tiles (corresponding to the cells) created by recursive % vertical and horizontal splits of a square. Thus, the area of each tile % is proportional to the corresponding cell entry \emph{given} the % dimensions of previous splits. The effect of <>= mosaic(HEC) @ \noindent equivalent to <>= mosaic(~ Sex + Eye + Hair, data = HairEyeColor) @ %\setkeys{Gin}{width=0.75\textwidth} \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{HairEyeColor} data.} \label{fig:observed} \end{center} \end{figure} \noindent depicts the observed frequencies of the \code{HairEyeColor} data. If there are zero entries, tiles have zero area and are, additionally, marked by small bullets (see, e.g, Figure~\ref{fig:titanic}). By default, these cells are not split further. The bullets help distinguishing very small cells from zero entries, and are particularly useful when color shadings come into play (see the example using the \data{Bundesliga} data in Section \ref{sec:overview}). Note that in contrast to, e.g., \codefun{mosaicplot} in base \proglang{R}, the default split direction and level ordering in all strucplot displays correspond to the textual representation produced by the print methods. It is also possible to visualize the expected values instead of the observed values (see Figure~\ref{fig:expected}): <>= mosaic(HEC, type = "expected") @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{HairEyeColor} data (expected values).} \label{fig:expected} \end{center} \end{figure} %\setkeys{Gin}{width=0.7\textwidth} \noindent In order to compare observed and expected values, a sieve plot \citep{vcd:riedwyl+schuepbach:1994} could be used (see Figure~\ref{fig:sieve}): <>= sieve(~ Sex + Eye + Hair, data = HEC, spacing = spacing_dimequal(c(2,0,0))) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Sieve plot for the \data{HairEyeColor} data visualizing simultaneously observed and expected values.} \label{fig:sieve} \end{center} \end{figure} \noindent where \code{spacing\_dimequal} is used to set the spacing of the second and third dimension to zero. Alternatively, we can directly inspect the residuals. The Pearson residuals (standardized deviations of observed from expected values) are conveniently visualized using association plots \citep{vcd:Cohen:1980}. In contrast to \codefun{assocplot} in base \proglang{R}, \pkg{vcd}'s \codefun{assoc} function scales to more than two variables (see Figure~\ref{fig:residuals}): <>= assoc(HEC, compress = FALSE) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Association plot for the \data{HairEyeColor} data.} \label{fig:residuals} \end{center} \end{figure} \noindent where the \code{compress} argument keeps distances between tiles equal. For both mosaic plots and association plots, the splitting of the tiles can be controlled using the \code{split\_vertical} argument. The default is to alternate splits starting with a horizontal one (see Figure~\ref{fig:split}): <>= options(width=60) @ <>= mosaic(HEC, split_vertical = c(TRUE, FALSE, TRUE), labeling_args = list(abbreviate_labs = c(Eye = 3))) @ <>= options(width=70) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{HairEyeColor} data---alternative splitting.} \label{fig:split} \end{center} \end{figure} \noindent (Note that \code{HEC}, a \class{structable} object, already includes a splitting information which simply gets overloaded in this example.) For compatibility with \codefun{mosaicplot} in base \proglang{R}, the \codefun{mosaic} function also allows the use of a \code{direction} argument taking a vector of \code{"h"} and \code{"v"} characters: <>= mosaic(HEC, direction = c("v","h","v")) @ By a suitable combination of splitting, spacing, and labeling settings, the functions provided by the strucplot framework can be customized in a quite flexible way. For example, the default method for \codefun{doubledecker} is simply a wrapper for \codefun{strucplot}, setting the right defaults. Most default settings such as colors, spacing, and labeling are specified via the parameters and passed through to \codefun{strucplot}. The additional code just handles the dependent variable information, and in particular permutes the table to have the dependent variable as the last dimension as required for the doubledecker plot. Figure~\ref{fig:titanic} shows a doubledecker plot of the \data{Titanic} data, explaining the probability of survival (``survived'') by age, given sex, given class. It is created by: <>= doubledecker(Titanic) @ \noindent equivalent to: <>= doubledecker(Survived ~ Class + Sex + Age, data = Titanic) @ \subsection{Conditional and partial views} So far, we have visualized either full or collapsed tables, as suggested by the analysis task at hand. Subtables can be selected in a similar way as for objects of class \class{table} using indexing. Note, however, that subsetting of \class{structable} objects is more restrictive because of their inherent conditional structure. Since the variables on both the row and the columns side are nested, subsetting is only possible ``outside-in'', that is, indexing operates on blocks defined by the variable levels. In the following, we use the Titanic data again, this time collapsed over \code{Survived} to investigate the structure of crew and passengers (and having the \code{Child} and \code{Age} labels of the \code{Age} variable swapped for optical clarity): <>= options(width=75) @ <>= (STD <- structable(~ Sex + Class + Age, data = Titanic[,,2:1,])) STD["Male",] STD["Male", c("1st","2nd","3rd")] @ <>= options(width=70) @ \noindent \emph{Conditioning} on levels (i.e., choosing a table subset for fixed levels of the conditioning variable(s)) is done using the \code{[[} operator. %]] Here again, the sequence of conditioning levels is restricted by the hierarchical structure of the \class{structable} object. In the following examples, note that compared to subsetting, the first dimension(s) are dropped: <>= STD[["Male",]] STD[[c("Male", "Adult"),]] STD[["Male","1st"]] @ \noindent Now, there are several ways for visualizing conditional independence structures. The ``brute force'' method is to draw separate plots for the strata. The following example compares the association between hair and eye color, given gender, by using subsetting on the flat table and \pkg{grid}'s viewport framework to visualize the two groups besides each other: <>= pushViewport(viewport(layout = grid.layout(ncol = 2))) @ <>= pushViewport(viewport(layout.pos.col = 1)) mosaic(STD[["Male"]], margins = c(left = 2.5, top = 2.5, 0), sub = "Male", newpage = FALSE) popViewport() @ <>= pushViewport(viewport(layout.pos.col = 2)) mosaic(STD[["Female"]], margins = c(top = 2.5, 0), sub = "Female", newpage = FALSE) popViewport(2) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= <> <> <> @ \caption{Two mosaic displays put side-by-side, visualizing the distribution of class and age, given gender. The marginal distribution of gender cannot be seen.} \label{fig:parttable} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent Note the use of the \code{margins} argument: it takes a vector with up to four values whose unnamed components are recycled, but ``overruled'' by the named arguments. Thus, in the second example, only the top margin is set to 2.5 lines, and all other to 0. This idea applies to almost all vectorized arguments in the strucplot framework (with \code{split\_vertical} as a prominent exception). The \codefun{cotabplot} function does a much better job on this task: it arranges stratified strucplot displays in a lattice-like layout, conditioning on variable \emph{levels}. The plot in Figure~\ref{fig:cotabplot} shows class and age group, given sex: <>= cotabplot(~ Class + Age | Sex, data = STD, split_vertical = TRUE) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= <> @ \caption{Conditional table plot for the \data{Titanic} data, again visualizing the distribution of age and class, given gender, using separate mosaic displays like the ``manual'' plot in Figure~\ref{fig:parttable}.} \label{fig:cotabplot} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} %\noindent The \code{labeling\_args} argument modifies the labels' %appearance: here, to be left-aligned and unclipped %(see Section \ref{sec:labeling}). \noindent Visualizing the strata separately ``hides'' the distribution of the conditioning variable(s) which may or may not be appropriate or sensible in a particular analysis step. If we wish to keep the information on the marginal distribution(s), we can use one single mosaic for the stratified plot since mosaic displays are ``conditional plots'' by definition. We just need to make sure that conditioning variables are used first for splitting. Both the default and the formula interface of \codefun{mosaic} allow the specification of conditioning variables (see Figure~\ref{fig:conditioning}): <>= mosaic(STD, condvars = "Sex", split_vertical = c(TRUE, TRUE, FALSE)) @ <>= mosaic(~ Class + Age | Sex, data = STD, split_vertical = c(TRUE, TRUE, FALSE)) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[h] \begin{center} <>= <> @ \caption{Mosaic plot again visualizing the distribution of class and age, given gender, this time using a single mosaic plot. In contrast to Figures~\ref{fig:parttable} and \ref{fig:cotabplot}, this plot also visualizes the marginal distribution of gender.} \label{fig:conditioning} \end{center} \end{figure} \setkeys{Gin}{width=0.7} \noindent The effect of using this is that conditioning variables are permuted ahead of the the conditioned variables in the table, and that \codefun{spacing\_conditional} is used as default to better distinguish conditioning from conditioned dimensions. This spacing uses equal space between tiles of conditioned variables, and increasing space between tiles of conditioning variables (See Section~\ref{sec:spacing}). Another set of high-level functions for visualizing conditional independence models are the \codefun{pairs} methods for \class{table} and \class{structable} objects. In contrast to \codefun{cotabplot} which conditions on variables, the \codefun{pairs} methods create pairwise views of the table. They produce, by default, a plot matrix having strucplot displays in the off-diagonal panels, and the variable names (optionally, with univariate displays) in the diagonal cells. Figure~\ref{fig:pairs} shows a pairs display for the \data{Titanic} data with univariate mosaics in the diagonal, and mosaic plots visualizing the corresponding bivariate mosaics in the upper and lower triangles. Due to the inherent asymmetry of mosaic displays, the corresponding plots in the upper and lower triangle differ depending on which variable is used first for splitting---inspecting both views might help detecting patterns in a data set. Additionally, we are using a special spacing and shading normally used to `highlight' %' the second variable in the first (as will be discussed in Section \ref{sec:spacing}): here, the intention of the spacing is to emphasize the conditional distributions of the second variable, given the first one, and the shading helps identifying the factor levels in the second variable. <>= pairs(STD, highlighting = 2, diag_panel = pairs_diagonal_mosaic, diag_panel_args = list(fill = grey.colors)) @ %\setkeys{Gin}{width=\textwidth} \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[h] \begin{center} <>= <> @ \caption{Pairs plot for the \data{Titanic} data.} \label{fig:pairs} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent The labels of the variables are to be read from left to right and from top to bottom. In addition, the levels can be matched by position within the columns and by shading within the rows. In plots produced by \codefun{pairs}, each panel's row and column define two variables $X$ and $Y$ used for the specification of four different types of independence: pairwise, total, conditional, and joint. The pairwise mosaic matrix shows bivariate marginal relations between $X$ and $Y$, collapsed over all other variables. The total independence mosaic matrix shows mosaic plots for mutual independence, i.e., for marginal and conditional independence among all pairs of variables. The conditional independence mosaic matrix shows mosaic plots for marginal independence of $X$ and $Y$, given all other variables. The joint independence mosaic matrix shows mosaic plots for joint independence of all pairs ($X$, $Y$) of variables from the others. Upper and lower parts can independently be used to display different types of independence models, or different strucplot displays (mosaic, association, or sieve plots). The available panel functions (\codefun{pairs\_assoc}, \codefun{pairs\_mosaic}, and \codefun{pairs\_sieve}) are simple wrappers to \codefun{assoc}, \codefun{mosaic}, and \codefun{sieve}, respectively. Obviously, seeing patterns in strucplot matrices becomes increasingly difficult with higher dimensionality. Therefore, this plot is typically used with a suitable residual-based shading (see Section \ref{sec:shading}). \subsection{Interactive plot modifications} All strucplot core functions are supposed to produce conditional hierarchical plots by the means of nested viewports, corresponding to the provided splitting information. Thus, at the end of the plotting, each tile is associated with a particular viewport. Each of those viewports has to be conventionally named, enabling other strucplot modules, in particular the labeling functions, to access specific tiles after they have been plotted. The naming convention for the viewports is: \begin{center} \code{\emph{[Optional prefix]}cell:\emph{Variable1}=\emph{Level1},\emph{Variable2}=\emph{Level2}} \dots \end{center} \noindent Clearly, these names depend on the splitting. The following example shows how to access parts of the plot after it has been drawn (see Figure~\ref{fig:afterplot}): <>= mosaic(~ Hair + Eye, data = HEC, pop = FALSE) seekViewport("cell:Hair=Blond") grid.rect(gp = gpar(col = "red", lwd = 4)) seekViewport("cell:Hair=Blond,Eye=Blue") grid.circle(r = 0.2, gp = gpar(fill = "cyan")) @ \noindent Note that the viewport tree is removed by default. Therefore, the \texttt{pop} argument has to be set to \texttt{FALSE} when viewports shall be accessed. \setkeys{Gin}{width=0.6\textwidth} \begin{figure}[h] \begin{center} <>= <> @ \caption{Adding elements to a mosaic plot after drawing.} \label{fig:afterplot} \end{center} \end{figure} In addition to the viewports, the main graphical elements get names following a similar construction method. This allows to change graphical parameters of plot elements \emph{after} the plotting (see Figure~\ref{fig:changeplot}): <>= assoc(Eye ~ Hair, data = HEC, pop = FALSE) getNames()[1:6] grid.edit("rect:Hair=Blond,Eye=Blue", gp = gpar(fill = "red")) @ %% code-chunk reuse does not work with parameter changing \begin{figure}[h] \begin{center} <>= x <- tab <- margin.table(HairEyeColor, 1:2) x[] <- "light gray" x["Blond","Blue"] <- "Red" assoc(tab, gp = gpar(fill = x)) @ \caption{Changing graphical parameters of elements after drawing.} \label{fig:changeplot} \end{center} \end{figure} \subsection{Performance issues} \label{sec:performance} As stated above, the implementation of strucplot displays is based on creating and nesting \pkg{grid} viewports. The main time-consuming steps performed by the core functions are the following: \begin{enumerate} \item recursively, split the table until the individual cells are reached \item during the splits, add viewports to the plot \item for the individual cells, add plot-specific content (rectangles for mosaics, bars for association plots, etc.) \end{enumerate} \noindent All these operations scale linearly with the amount of created viewports. For a $d$-dimensional table with $k_i$ levels, $i=1 \dots d$, the total number of needed viewports $T_d$ can roughly be estimated as \begin{equation} \label{eq:numbervp} T_d \quad = \quad k_1 + k_1k_2 + \cdots + k_1 \cdots k_d \quad =\quad \sum_{i=1}^d \prod_{j \le i} k_j \end{equation} \noindent since we first push the $k_1$ viewports for the levels of the first dimension, then, for \emph{each} of these, the $k_2$ levels of the second dimension, etc. If the number of levels is equal ($k$) for all dimensions, $T_d$ simplifies to \begin{equation} \label{eq:equalvp} T_d \quad = \quad \sum_{i=1}^d k^i = \frac{k(k^d-1)}{k-1} \end{equation} \noindent and so the time complexity for drawing a strucplot display is of order $k^d$. \section{Shadings} \label{sec:shading} Unlike other graphics functions in base \proglang{R}, the strucplot framework allows almost full control over the graphical parameters of all plot elements. In particular, in association plots, mosaic plots, and sieve plots, the user can modify the graphical appearance of each tile individually. Built on top of this functionality, the framework supplies a set of shading functions choosing colors appropriate for the visualization of log-linear models. The tiles' graphical parameters are set using the \code{gp} argument of the functions of the strucplot framework. This argument basically expects an object of class \class{gpar} whose components are arrays of the same shape (length and dimensionality) as the data table (see Section \ref{sec:gp}). For convenience, however, the user can also supply a grapcon function that computes such an object given a vector of residuals, or, alternatively, a generating function that takes certain arguments and returns such a grapcon function (see Section \ref{sec:shadingcustom}). We provide several shading functions, including support for both HSV and HCL colors, and the visualization of significance tests (see Section \ref{sec:overview}). \subsection{Specifying graphical parameters of strucplot displays} \label{sec:gp} As an example, consider the \data{UCBAdmissions} data. In the table aggregated over departments, we would like to highlight the (incidentally wrong) impression that there were too many male students accepted compared to the presumably discriminated female students (see Figure~\ref{fig:ucb}): <>= (ucb <- margin.table(UCBAdmissions, 1:2)) (fill_colors <- matrix(c("dark cyan","gray","gray","dark magenta"), ncol = 2)) mosaic(ucb, gp = gpar(fill = fill_colors, col = 0)) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{UCBAdmissions} data with highlighted cells.} \label{fig:ucb} \end{center} \end{figure} \noindent As the example shows, we create a fourfold table with appropriate colors (dark cyan for admitted male students and dark magenta for rejected female students) and supply them to the \code{fill} component of the \class{gpar} object passed to the \code{gp} argument of \codefun{mosaic}. For visual clarity, we additionally hide the tiles' borders by setting the \code{col} component to 0 (transparent). If the parameters specified in the \class{gpar} object are ``incomplete'', they will be recycled along the last splitting dimension. In the following example based on the \data{Titanic} data, we will highlight all cells corresponding to survived passengers (see Figure~\ref{fig:recycling}): <>= mosaic(Titanic, gp = gpar(fill = c("gray","dark magenta")), spacing = spacing_highlighting, labeling_args = list(abbreviate_labs = c(Age = 3), rep = c(Survived = FALSE)) ) @ \noindent Note that \codefun{spacing\_highlighting} sets the spaces between tiles in the last dimension to 0. The \code{labeling\_args} argument ensures that labels do not overlap (see Section \ref{sec:labeling}). \begin{figure}[h] \begin{center} <>= <> @ \caption{Recycling of parameters, used for highlighting the survived passengers in the \data{Titanic} data.} \label{fig:recycling} \end{center} \end{figure} \subsection{Customizing residual-based shadings} \label{sec:shadingcustom} This flexible way of specifying graphical parameters is the basis for a suite of shading functions that modify the tiles' appearance with respect to a vector of residuals, resulting from deviations of observed from expected frequencies under a given log-linear model. The idea is to visualize at least sign and absolute size of the residuals, but some shadings, additionally, indicate overall significance. One particular shading, the maximum shading \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Zeileis+Meyer+Hornik:2005}, even allows to identify the cells that cause the rejection of the null hypothesis. Conceptually, the strucplot framework offers three alternatives to add residual-based shading to plots: \begin{enumerate} \item Precomputing the graphical parameters (e.g., fill colors), encapsulating them into an object of class \class{gpar} as demonstrated in the previous section, and passing this object to the \code{gp} argument. \item Providing a grapcon function to the \code{gp} argument that takes residuals as input and returns an object as described in alternative 1. \item Providing a grapcon generator taking parameters and returning a function as described in alternative~2. \end{enumerate} \noindent For each of these approaches, we will demonstrate the necessary steps to obtain a binary shading that visualizes the sign of the residuals by a corresponding fill color (for simplicity, we will treat 0 as positive). \subsubsection*{Alternative 1: Precomputed \class{gpar} object} The first method is precomputing the graphical parameters ``by hand''. We will use \code{royalblue4} color for positive and \code{mediumorchid4} color for negative residuals (see Figure~\ref{fig:binary}): <>= expected <- independence_table(ucb) (x <- (ucb - expected) / sqrt(expected)) (shading1_obj <- ifelse(x > 0, "royalblue4", "mediumorchid4")) mosaic(ucb, gp = gpar(fill = shading1_obj)) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Binary shading visualizing the sign of the residuals.} \label{fig:binary} \end{center} \end{figure} \subsubsection*{Alternative 2: Grapcon function} For implementing alternative 2, we need to create a ``shading function'' that computes \class{gpar} objects from residuals. For that, we can just reuse the code from the previous step: <>= shading2_fun <- function(x) gpar(fill = ifelse(x > 0, "royalblue4", "mediumorchid4")) @ \noindent To create a mosaic display with binary shading, it now suffices to specify the data table along with \codefun{shading2\_fun}: <>= mosaic(ucb, gp = shading2_fun) @ \noindent \codefun{mosaic} internally calls \codefun{strucplot} which computes the residuals from the specified independence model (total independence by default), passes them to \codefun{shading2\_fun}, and uses the \class{gpar} object returned to finally create the plot. Our \codefun{shading2\_fun} function might be useful, but can still be improved: the hard-wired colors should be customizable. We cannot simply extend the argument list to include, e.g., a \code{fill = c("royalblue4", "mediumorchid4")} argument because \codefun{strucplot} will neither know how to handle it, nor let us change the defaults. In fact, the interface of shading functions is fixed, they are expected to take exactly one argument: a table of residuals. This is where generating functions (alternative 3) come into play. \subsubsection*{Alternative 3: Grapcon generator} We simply wrap our grapcon shading function in another function that takes all additional arguments it needs to use, possibly preprocesses them, and returns the actual shading function. This returned function will have access to the parameters since in \proglang{R}, nested functions are lexically scoped. Thus, the grapcon generator returns (``creates'') a ``parameterized'' shading function with the minimal standard interface \codefun{strucplot} requires. The following example shows the necessary extensions for our running example: <>= shading3a_fun <- function(col = c("royalblue4", "mediumorchid4")) { col <- rep(col, length.out = 2) function(x) gpar(fill = ifelse(x > 0, col[1], col[2])) } @ \noindent The first statement just makes sure that exactly two colors are specified. In the call to \codefun{mosaic}, using the new \codefun{shading3a\_fun} function, we can now simply change the colors: <>= mosaic(ucb, gp = shading3a_fun(c("royalblue4","mediumorchid4"))) @ \noindent (figure not shown). The procedure described so far is a rather general concept, applicable to a wide family of user-level \pkg{grid} graphics. Indeed, the customization of other components of the strucplot framework (labeling, spacing, legend, and core functions) follows the same idea. Now for the shading functions, more customization is needed. Note that \codefun{shading3a\_fun} needs to be evaluated by the user, even if the defaults are to be used. It is a better idea to let \codefun{strucplot} call the generating function, which, in particular, allows the passing of arguments that are computed by \codefun{strucplot}. Since shading functions can be used for visualizing significance (see Section \ref{sec:overview}), it makes sense for generating functions to have access to the model, i.e., observed and expected values, residuals, and degrees of freedom. For example, the \codefun{shading\_max} generating function computes a permutation distribution of the maximum statistic and $p$ values for specified significance levels based on the observed table to create data-driven cut-off points. If this was done in the shading function itself, the permutation statistic would be recomputed every time the shading function is called, resulting in possibly severe performance loss and numerical inconsistencies. Therefore, generating functions for shadings are required to take at least the parameters \code{observed}, \code{expected}, \code{residuals}, and \code{df} (these are provided by the strucplot framework), followed by other parameters controlling the shading appearance (to be specified by the user): <>= shading3b_fun <- function(observed = NULL, residuals = NULL, expected = NULL, df = NULL, col = c("royalblue4", "mediumorchid4")) { col <- rep(col, length.out = 2) function(x) gpar(fill = ifelse(x > 0, col[1], col[2])) } class(shading3b_fun) <- "grapcon_generator" @ Note that in this simple binary shading example, the first four parameters are not used. In some sense, generating functions for shadings are parameterized both by the user and the strucplot framework. For shading functions that require model information, the user-specified parameters are to be passed to the \code{gp\_args} argument instead, and for this to work, the generating function needs a class attribute to be distinguishable from the ``normal'' shading functions. For others (like our simple \codefun{shading3b\_fun}) this is optional, but recommended for consistency: <>= mosaic(ucb, gp = shading3b_fun, gp_args = list(col = c("red","blue"))) @ \noindent The final \codefun{shading3b\_fun} pretty much resembles \codefun{shading\_binary}, one of the standard shading functions provided by the \pkg{vcd} package. \subsection[An overview of the shading functions in vcd]{An overview of the shading functions in \pkg{vcd}} \label{sec:overview} \cite{vcd:Friendly:1994} suggested a residual-based shading for the mosaic tiles that can also be applied to the rectangles in association plots \citep{vcd:Meyer+Zeileis+Hornik:2003}. Apart from \codefun{shading\_binary}, there are currently two basic shadings available in \pkg{vcd}: \codefun{shading\_hcl} and \codefun{shading\_hsv}, as well as two derived functions: \codefun{shading\_Friendly} building upon \codefun{shading\_hsv}, and \codefun{shading\_max} building upon \codefun{shading\_hcl}. \codefun{shading\_hsv} and \codefun{shading\_hcl} provide the same conceptual tools, but use different color spaces: the Hue-Saturation-Value (HSV) and the Hue-Chroma-Luminance (HCL) scheme, respectively. We will first expose the basic concept of these shading functions using HSV space, and then briefly explain the differences to HCL space \citep[a detailed discussion can be found in][]{vcd:Zeileis+Meyer+Hornik:2005}. Color palettes in HCL space are preferable to palettes derived from HSV space from a perceptual point of view. Functions for creating palettes (see, e.g., \codefun{diverge\_hcl}) are provided with the \pkg{vcd} package. In HSV space, colors are specified in three dimensions: Hue, Saturation (``colorfulness''), and Value (``lightness'', amount of gray). These three dimensions are used by \codefun{shading\_hsv} to visualize information about the residuals and the underlying independence model. The hue indicates the residuals' sign: by default, blue for positive, and red for negative residuals. The saturation of a residual is set according to its size: high saturation for large, and low saturation for small residuals. Finally, the overall lightness is used to indicate the significance of a test statistic: light colors for significant, and dark colors for non-significant results. As an example, we will visualize the association of hair and eye color in the \data{HairEyeColor} data set (see Figure~\ref{fig:haireye}, top): <>= haireye <- margin.table(HairEyeColor, 1:2) mosaic(haireye, gp = shading_hsv) @ \noindent As introduced before, the default shading scheme is not \codefun{shading\_hsv} but \codefun{shading\_hcl} due to the better perceptual characteristics of HCL color space. The following example again illustrates the \data{HairEyeColor} data, this time with HCL colors: <>= mosaic(haireye, gp = shading_hcl) @ <>= mosaic(haireye, gp = shading_hcl, gp_args = list(h = c(130, 43), c = 100, l = c(90, 70))) @ \noindent In Figure~\ref{fig:haireye}, the plot in the middle depicts the default palette, and the bottom plot an alternative setting for Hue (\code{h}), Chroma (\code{c}), and Luminance (\code{l}). \setkeys{Gin}{width=0.5\textwidth} \begin{figure}[htbp] \begin{center} <>= mosaic(haireye, gp = shading_hsv, margin = c(bottom = 1), keep_aspect_ratio = FALSE) @ <>= mosaic(haireye, gp = shading_hcl, margin = c(bottom = 1), keep_aspect_ratio = FALSE) @ <>= mosaic(haireye, gp = shading_hcl, margin = c(bottom = 1), gp_args = list(h = c(130, 43), c = 100, l = c(90, 70)), keep_aspect_ratio = FALSE) @ \caption{Three mosaic plots for the \data{HairEyeColor} data using different color palettes. Top: default HSV color palette. Middle: default HCL color palette. Bottom: a custom HCL color palette.} \label{fig:haireye} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent Large positive residuals (greater than $4$) can be found for brown eyes/black hair and blue eyes/blond hair, and are colored in deep blue. On the other hand, there is a large negative residual (less than $-4$) for brown eyes/blond hair, colored deep red. There are also three medium-sized positive (negative) residuals between 2 and 4 ($-2$ and $-4$): the colors for them are less saturated. Residuals between $-2$ and $2$ are shaded in white (gray for HCL-shading). The heuristic for choosing the cut-off points $2$ and $4$ is that the Pearson residuals are approximately standard normal which implies that the highlighted cells are those with residuals \emph{individually} significant at approximately the $\alpha = 0.05$ and $\alpha = 0.0001$ levels, respectively. These default cut-off points can be changed to alternative values using the \code{interpolate} argument (see Figure~\ref{fig:interpolatecontinuous}): <>= mosaic(haireye, shade = TRUE, gp_args = list(interpolate = 1:4)) @ \noindent The elements of the numeric vector passed to \code{interpolate} define the knots of an interpolating step function used to map the absolute residuals to saturation levels. The \code{interpolate} argument also accepts a user-defined function, which then is called with the absolute residuals to get a vector of cut-off points. Thus, it is possible to automatically choose the cut-off points in a data-driven way. For example, one might think that the extension from four cut-off points to a continuous shading---visualizing the whole range of residuals---could be useful. We simply need a one-to-one mapping from the residuals to the saturation values: <>= ipol <- function(x) pmin(x/4, 1) @ \noindent Note that this \codefun{ipol} function maps residuals greater than 4 to a saturation level of 1. However, the resulting plot (Figure~\ref{fig:interpolatecontinuous}, right) is deceiving: <>= mosaic(haireye, shade = TRUE, gp_args = list(interpolate = ipol), labeling_args = list(abbreviate_labs = c(Sex = TRUE))) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[htbp] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) mosaic(haireye, gp_args = list(interpolate = 1:4), margin = c(right = 1), keep_aspect_ratio= FALSE,newpage = FALSE,legend_width=5.5,shade = TRUE) popViewport(1) pushViewport(viewport(layout.pos.col = 2)) mosaic(haireye, gp_args = list(interpolate = ipol), margin = c(left=3,right = 1), keep_aspect_ratio = FALSE, newpage = FALSE, shade = TRUE) popViewport(2) @ \caption{\label{fig:interpolatecontinuous}The \data{HairEyeColor} data. Left: shading with 4 cut-off points. Right: continuous shading.} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent Too much color makes it difficult to interpret the image, and the subtle color differences are hard to catch. Therefore, we only included shadings with discrete cut-off points. The third remaining dimension, the value, is used for visualizing the significance of a test statistic. The user can either directly specify the $p$ value, or, alternatively, a function that computes it, to the \code{p.value} argument. Such a function must take observed and expected values, residuals, and degrees of freedom (used by the independence model) as arguments. If nothing is specified, the $p$ value is computed from a $\chi^2$ distribution with \code{df} degrees of freedom. The \code{level} argument is used to specify the confidence level: if \code{p.value} is smaller than \code{1 - level}, light colors are used, otherwise dark colors are employed. The following example using the \data{Bundesliga} data shows the relationship of home goals and away goals of Germany's premier soccer league in 1995: although there are two ``larger'' residuals (one greater than 2, one less then $-2$), the $\chi^2$ test does not reject the null hypothesis of independence. Consequently, the colors appear dark (see Figure~\ref{fig:bundesliga}, left): <>= BL <- xtabs(~ HomeGoals + AwayGoals, data = Bundesliga, subset = Year == 1995) mosaic(BL, shade = TRUE) @ \noindent Note that in extended mosaic plots, bullets drawn for zero cells are shaded, too, bringing out non-zero residuals, if any. A shading function building upon \codefun{shading\_hsv} is \codefun{shading\_Friendly}, implementing the shading introduced by \cite{vcd:Friendly:1994}. In addition to the defaults of the HSV shading, it uses the border color and line type to redundantly code the residuals' sign. The following example again uses the \data{Bundesliga} data from above, this time using the Friendly scheme and, in addition, an alternative legend (see Figure~\ref{fig:bundesliga}, right): <>= mosaic(BL, gp = shading_Friendly, legend = legend_fixed, zero_size = 0) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[htbp] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) mosaic(BL, margin = c(right = 1), keep_aspect_ratio= FALSE, newpage = FALSE, legend_width=5.5, shade = TRUE) popViewport(1) pushViewport(viewport(layout.pos.col = 2)) mosaic(BL, gp = shading_Friendly, legend = legend_fixed, zero_size = 0, margin = c(right = 1), keep_aspect_ratio= FALSE, newpage = FALSE, legend_width=5.5) popViewport(2) @ \caption{The \data{Bundesliga} data for 1995. Left: Non-significant $\chi^2$ test. Right: using the Friendly shading and a legend with fixed bins.} \label{fig:bundesliga} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent (The \code{zero\_size = 0} argument removes the bullets indicating zero observed values. This feature is not provided in the original \proglang{SAS} implementation of the Friendly mosaic plots.) % Figure~\ref{fig:shadingHSVHCL} depicts % HSV space in the upper panel and HCL space in the lower panel. % On the left (right) side, we see the color scales for red (blue) % hue, respectively. The $x$-axis represents the colorfulness, and the % $y$-axis the brightness. % The boxes represent the diverging color palettes used for the shadings. % For HSV space, we can see that the effect of changing the % level of brightness (`value') is not the same for different levels of % saturation, and again not the same for the two different hues. % In fact, in HSV space all dimensions are confounded, which % obviously is problematic for coding information. In contrast, HCL color % space offers perceptually uniform colors: as can be seen from the lower panel, % the chroma is homogeneous for different levels of luminance. % Unfortunately, this comes at the % price of the space being irregularly shaped, making it difficult to automatically select % diverging color palettes. % <>= % hue.slice <- function(hue, grid.n = 101, type = c("HCL", "HSV"), plot = TRUE, fixup = FALSE) % { % type <- match.arg(type) % if(type == "HCL") { % chroma = seq(0, 100, length = grid.n) % luminance = seq(0, 100, length = grid.n) % nc <- length(chroma) % nl <- length(luminance) % color.slice <- outer(chroma, luminance, function(y, x) hcl(hue, x, y, fixup = fixup)) % xlab <- "chroma" % ylab <- "luminance" % main <- paste("hue =", round(hue, digits = 0)) % } else { % chroma = seq(0, 1, length = grid.n) % luminance = seq(0, 1, length = grid.n) % nc <- length(chroma) % nl <- length(luminance) % color.slice <- outer(chroma, luminance, function(y, x) hsv(hue, x, y)) % xlab <- "saturation" % ylab <- "value" % main <- paste("hue =", round(hue, digits = 3)) % } % if(plot) { % plot(0.5, 0.5, xlim = range(chroma), ylim = range(luminance), type = "n", axes = FALSE, % xlab = xlab, ylab = ylab, yaxs = "i", xaxs = "i", main = main) % for(i in 1:(nc-1)) { % rect(chroma[i], luminance[-nl], chroma[i] + 100/(nc-1), luminance[-1], border = color.slice[,i+1], col = color.slice[,i+1]) % } % axis(1) % axis(2) % box() % } % colnames(color.slice) <- chroma % rownames(color.slice) <- luminance % attr(color.slice, "type") <- type % class(color.slice) <- "slice" % invisible(color.slice) % } % @ % \setkeys{Gin}{width=.8\textwidth} % \begin{figure}[p] % \begin{center} % <>= % ## generate colors % hue23 <- hue.slice(2/3, grid.n = 101, plot = FALSE, type = "HSV") % hue0 <- hue.slice(0, grid.n = 101, plot = FALSE, type = "HSV") % saturation <- as.numeric(colnames(hue23)) % value <- as.numeric(rownames(hue23)) % ## select those with value >= 0.5 % hue23 <- hue23[value >= .5, ] % hue0 <- hue0[value >= .5, ] % value <- value[value >= .5] % nl <- nrow(hue23) % nc <- ncol(hue23) % ## plot 2 slides from HSV space % plot(0.5, 0.5, xlim = c(-1, 1), ylim = c(0, 1), type = "n", axes = FALSE, % xlab = "", ylab = "", yaxs = "i", xaxs = "i", main = "") % for(i in 1:(nc-1)) { % rect(saturation[i], value[-nl], saturation[i] + 1/(nc-1), value[-1], border = hue23[,i+1], col = hue23[,i+1]) % } % for(i in 1:(nc-1)) { % rect(-saturation[i], value[-nl], -(saturation[i] + 1/(nc-1)), value[-1], border = hue0[,i+1], col = hue0[,i+1]) % } % axis(2, at = c(50, 75, 100)/100, labels = c(0.5, 0.75, 1)) % axis(4, at = c(50, 75, 100)/100, labels = c(0.5, 0.75, 1)) % axis(3, at = -4:4*.25, labels=c(4:0*.25, 1:4*.25)) % mtext(c("hue = 0", "hue = 2/3"), side = 3, at = c(-.5, .5), line = 3, cex = 1.2) % mtext("saturation", side = 3, at = 0, line = 2) % mtext("value", side = 2, at = .75, line = 2) % mtext("value", side = 4, at = .75, line = 2) % lines(c(-1, 1), c(.5, .5)) % ## significant colors % rect(-1, 0.95, -.90, 1, col = hsv(0, 1, 1)) % rect(-0.45, 0.95, -.55, 1, col = hsv(0, 0.5, 1)) % rect(-.05, .95, .05, 1, col = hsv(2/3, 0, 1)) % rect(0.45, 0.95, .55, 1, col = hsv(2/3, 0.5, 1)) % rect(.90, .95, 1, 1, col = hsv(2/3, 1, 1)) % text(-1, .33, "significant", pos = 4, cex = 1.2) % rect(-1, .20, -.80, .30, col = hsv(0, 1, 1)) % rect(-.40, .20, -0.6, .30, col = hsv(0, 0.5, 1)) % rect(-.20, .20, 0, .30, col = hsv(0, 0, 1)) % rect(0, .20, .20, .30, col = hsv(2/3, 0, 1)) % rect(0.4, .20, .60, .30, col = hsv(2/3, .5, 1)) % rect(.80, .20, 1, .30, col = hsv(2/3, 1, 1)) % lines(c(-.9, -.55), c(0.975, .975), lty = 2) % lines(c(-.45, -.05), c(0.975, .975), lty = 2) % lines(c(.45, .05), c(0.975, .975), lty = 2) % lines(c(.9, .55), c(0.975, .975), lty = 2) % ## non-significant colors % rect(-1, 0.5, -.90, 0.55, col = hsv(0, 1, 0.5)) % rect(-0.45, 0.5, -.55, 0.55, col = hsv(0, 0.5, 0.5)) % rect(-.05, .5, .05, 0.55, col = hsv(2/3, 0, 0.5)) % rect(0.45, 0.5, .55, 0.55, col = hsv(2/3, 0.5, 0.5)) % rect(.90, .5, 1, 0.55, col = hsv(2/3, 1, 0.5)) % text(-1, .13, "non-significant", pos = 4, cex = 1.2) % rect(-1, 0, -.80, .10, col = hsv(0, 1, 0.5)) % rect(-.60, 0, -.4, .10, col = hsv(0, 0.5, 0.5)) % rect(-.20, 0, 0, .10, col = hsv(0, 0, 0.5)) % rect(0, 0, .20, .10, col = hsv(2/3, 0, 0.5)) % rect(0.4, 0, .60, .1, col = hsv(2/3, .5, 0.5)) % rect(.80, 0, 1, .10, col = hsv(2/3, 1, 0.5)) % lines(c(-.9, -.55), c(0.525, .525), lty = 2) % lines(c(-.45, -.05), c(0.525, .525), lty = 2) % lines(c(.45, .05), c(0.525, .525), lty = 2) % lines(c(.9, .55), c(0.525, .525), lty = 2) % @ % <>= % ## generate colors % hue260 <- hue.slice(260, grid.n = 101, plot = FALSE) % hue360 <- hue.slice(360, grid.n = 101, plot = FALSE) % mychroma <- as.numeric(colnames(hue260)) % luminance <- as.numeric(rownames(hue260)) % ## select those with lumincance >= 50 % hue260 <- hue260[luminance >= 50, ] % hue360 <- hue360[luminance >= 50, ] % luminance <- luminance[luminance >= 50] % nc <- ncol(hue260) % nl <- nrow(hue260) % ## plot 2 slides from HCL space % plot(0.5, 0.5, xlim = c(-100, 100), ylim = c(0, 100), type = "n", axes = FALSE, % xlab = "", ylab = "", yaxs = "i", xaxs = "i", main = "") % for(i in 1:(nc-1)) { % rect(mychroma[i], luminance[-nl], mychroma[i] + 100/(nc-1), luminance[-1], border = hue260[,i+1], col = hue260[,i+1]) % } % for(i in 1:(nc-1)) { % rect(-mychroma[i], luminance[-nl], -(mychroma[i] + 100/(nc-1)), luminance[-1], border = hue360[,i+1], col = hue360[,i+1]) % } % axis(2, at = c(50, 70, 90, 100), labels = c(50, 70, 90, 100)) % axis(4, at = c(50, 70, 90, 100), labels = c(50, 70, 90, 100)) % axis(3, at = -4:4*25, labels=c(4:0*25, 1:4*25)) % mtext(c("hue = 0", "hue = 260"), side = 3, at = c(-50, 50), line = 3, cex = 1.2) % mtext("chroma", side = 3, at = 0, line = 2) % mtext("luminance", side = 2, at = 75, line = 2) % mtext("luminance", side = 4, at = 75, line = 2) % lines(c(-100, 100), c(50, 50)) % ## significant colors % rect(-100, 47.5, -90, 52.5, col = hcl(0, 100, 50)) % rect(-55, 67.5, -45, 72.5, col = hcl(0, 50, 70)) % rect(-5, 95, 5, 100, col = hcl(260, 0, 100)) ## grey vs. white % rect(-5, 87.5, 5, 92.5, col = hcl(260, 0, 90)) ## grey vs. white % rect(45, 67.5, 55, 72.5, col = hcl(260, 50, 70)) % rect(90, 47.5, 100, 52.5, col = hcl(260, 100, 50)) % text(-100, 33, "significant", pos = 4, cex = 1.2) % rect(-100, 20, -80, 30, col = hcl(0, 100, 50)) % rect(-60, 20, -40, 30, col = hcl(0, 50, 70)) % rect(-20, 20, 0, 30, col = hcl(0, 0, 90)) % rect(0, 20, 20, 30, col = hcl(260, 0, 90)) % #white# rect(-20, 20, 0, 30, col = hcl(0, 0, 100)) % #white# rect(0, 20, 20, 30, col = hcl(260, 0, 100)) % rect(40, 20, 60, 30, col = hcl(260, 50, 70)) % rect(80, 20, 100, 30, col = hcl(260, 100, 50)) % lines(c(-45, -5), c(72.5, 87.5), lty = 2) % lines(c(45, 5), c(72.5, 87.5), lty = 2) % lines(c(-95, -55), c(52.5, 67.5), lty = 2) % lines(c(95, 55), c(52.5, 67.5), lty = 2) % ## non-significant colors % rect(-25, 47.5, -15, 52.5, col = hcl(0, 20, 50)) % rect(-15, 67.5, -5, 72.5, col = hcl(0, 10, 70)) % rect(5, 67.5, 15, 72.5, col = hcl(260, 10, 70)) % rect(25, 47.5, 15, 52.5, col = hcl(260, 20, 50)) % text(-100, 13, "non-significant", pos = 4, cex = 1.2) % rect(-60, 0, -40, 10, col = hcl(0, 20, 50)) % rect(-40, 0, -20, 10, col = hcl(0, 10, 70)) % rect(-20, 0, 0, 10, col = hcl(0, 0, 90)) % rect(0, 0, 20, 10, col = hcl(260, 0, 90)) % rect(20, 0, 40, 10, col = hcl(260, 10, 70)) % rect(40, 0, 60, 10, col = hcl(260, 20, 50)) % lines(c(-18.75, -11.25), c(52.5, 67.5), lty = 2) % lines(c(-8.75, -1.25), c(72.5, 87.5), lty = 2) % lines(c(18.75, 11.75), c(52.5, 67.5), lty = 2) % lines(c(8.75, 1.25), c(72.5, 87.5), lty = 2) % @ % \caption{Residual-based shadings in HSV (upper) and HCL space (lower).} % \label{fig:shadingHSVHCL} % \end{center} % \end{figure} A more ``advanced'' function building upon \codefun{shading\_hcl} is \codefun{shading\_max}, using the maximum statistic both to conduct the independence test and to visualize significant \emph{cells} causing the rejection of the independence hypothesis \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Zeileis+Meyer+Hornik:2005}. The \code{level} argument of \codefun{shading\_max} then can be used to specify several confidence levels from which the corresponding cut-off points are computed. By default, two cut-off points are computed corresponding to confidence levels of $90\%$ and $99\%$, respectively. In the following example, we investigate the effect of a new treatment for rheumatoid arthritis on a group of female patients using the maximum shading (see Figure~\ref{fig:maximum}): <>= set.seed(4711) mosaic(~ Treatment + Improved, data = Arthritis, subset = Sex == "Female", gp = shading_max) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{The \data{Arthritis} data (female patients) with significant maximum test.} \label{fig:maximum} \end{center} \end{figure} \noindent The maximum test is significant although the residuals are all in the $\left[-2,2\right]$ interval. The \codefun{shading\_hcl} function with default cut-off points would not have shown any color. In addition, since the test statistic is the maximum of the absolute Pearson residuals, \emph{each} colored residual violates the null hypotheses of independence, and thus, the ``culprits'' can immediately be identified. \clearpage \section[Labeling]{Labeling} \label{sec:labeling} One of the major enhancements in package \pkg{vcd} compared to \codefun{mosaicplot} and \codefun{assocplot} in base \proglang{R} is the labeling in the strucplot framework which offers more features and greater flexibility. Like shading, spacing, and drawing of legend and core plot, labeling is now carried out by grapcon functions, rendering labeling completely modular. The user supplies either a labeling function, or, alternatively, a generating function that parameterizes a labeling function, to \codefun{strucplot} which then draws the labels. Labeling is well-separated from the actual plotting that occurs in the low-level core functions. It only relies on the viewport tree produced by them, and the \code{dimnames} attribute of the visualized table. Labeling functions are grapcons that ``add ink to the canvas'': the drawing of the labels happens after the actual plot has been drawn by the core function. Thus, it is possible to supply one's own labeling function, or to combine some of the basic functions to produce a more complex labeling. In the following, we describe the three basic modules (\codefun{labeling\_text}, \codefun{labeling\_list}, and \codefun{labeling\_cells}) and derived functions that build upon them. \subsection[Labels in the borders]{Labels in the borders: \texttt{labeling\_text()}} \codefun{labeling\_text} is the default for all strucplot displays. It plots labels in the borders similar to the \codefun{mosaicplot} function in base \proglang{R}, but is much more flexible: it is not limited to 4 dimensions, and the positioning and graphical parameters of levels and variable names are customizable. In addition, the problem of overlapping labels can be handled in several ways. As an example, again consider the \data{Titanic} data: by default, the variable names and levels are plotted ``around'' the plot in a counter-clockwise way (see Figure~\ref{fig:labels1}, top left): <>= mosaic(Titanic) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Mosaic plot for the \data{Titanic} data with default settings % for labeling.} % \label{fig:defaults} % \end{center} % \end{figure} \noindent Note that the last two levels of the \code{survived} variable do overlap, as well as some adult and child labels of the \code{age} Variable. This issue can be addressed in several ways. The ``brute force'' method is to enable clipping for these dimensions (see Figure~\ref{fig:labels1}, top right): <>= mosaic(Titanic, labeling_args = list(clip = c(Survived = TRUE, Age = TRUE))) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{The effect of clipping.} % \label{fig:clipping} % \end{center} % \end{figure} \noindent The \code{clip} parameter is passed to the labeling function via the \code{labeling\_args} argument which takes a list of parameters. \code{clip} itself takes a vector of logicals (one for each dimension). % as mentioned before Almost all vectorized arguments in the strucplot framework can be abbreviated in the following way: unnamed components (or the defaults, if there are none) are recycled as needed, but overridden by the named components. Here, the default is \code{FALSE}, and therefore clipping is enabled only for the \code{survived} and \code{age} variables. A more sensible solution to the overlap problem is to abbreviate the levels (see Figure~\ref{fig:labels1}, middle left): <>= mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = TRUE, Age = 3))) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Abbreviating.} % \label{fig:abbreviating} % \end{center} % \end{figure} \noindent The \code{abbreviate} argument takes a vector of integers indicating the number of significant characters the levels should be abbreviated to (\code{TRUE} is interpreted as 1, obviously). Abbreviation is performed using the \codefun{abbreviate} function in base \proglang{R}. Another possibility is to rotate the levels (see Figure~\ref{fig:labels1}, bottom): <>= mosaic(Titanic, labeling_args = list(rot_labels = c(bottom = 90, right = 0), offset_varnames = c(right = 1), offset_labels = c(right = 0.3)), margins = c(right = 4, bottom = 3)) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Rotating labels.} % \label{fig:rotating} % \end{center} % \end{figure} \noindent Finally, we could also inhibit the output of repeated levels (see Figure~\ref{fig:labels1}, middle right): <>= mosaic(Titanic, labeling_args = list(rep = c(Survived = FALSE, Age = FALSE))) @ \setkeys{Gin}{width=0.9\textwidth} \begin{figure}[p] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2,nrow=3))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(Titanic, newpage = FALSE, keep = TRUE, margin = c(right = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(Titanic, labeling_args = list(clip = c(Survived = TRUE, Age = TRUE)), newpage = FALSE, keep = TRUE, margin = c(left = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = TRUE, Age = 2)), newpage = FALSE, keep = TRUE, margin = c(right = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(rep = c(Survived = FALSE, Age = FALSE)), newpage = FALSE, keep = TRUE, margin = c(left = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 1:2, layout.pos.row = 3)) pushViewport(viewport(width = 0.55)) mosaic(Titanic, labeling_args = list(rot_labels = c(bottom = 90, right = 0), offset_varnames = c(right = 1), offset_labels = c(right = 0.3)), margins = c(right = 4, bottom = 3), newpage = FALSE, keep = FALSE, gp_labels = gpar(fontsize = 10)) popViewport(3) @ \caption{Examples for possible labeling strategies for the Titanic data mosaic. Top left: default labeling (many labels overlap). Top right: with clipping turned on. Middle left: \texttt{Age} and \texttt{Survived} labels abbreviated. Middle right: \texttt{Age} labels not repeated. Bottom: \texttt{Age} and \texttt{Survived} labels rotated.} \label{fig:labels1} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} We now proceed with a few more ``cosmetic'' features (which do not all produce satisfactory results for our sample data). A first simple, but effectful modification is to position all labels and variables left-aligned (see Figure~\ref{fig:labels2}, top left): <>= mosaic(Titanic, labeling_args = list(pos_varnames = "left", pos_labels = "left", just_labels = "left", rep = FALSE)) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Left-aligning.} % \label{fig:left} % \end{center} % \end{figure} \noindent Note that obviously we need to change the justification to \code{"left"} as well. We can achieve the same effect by using the convenience function \codefun{labeling\_left}: <>= mosaic(Titanic, labeling = labeling_left) @ \noindent Next, we show how to put all levels to the bottom and right margins, and all variable names to the top and left margins (see Figure~\ref{fig:labels2}, top right): <>= mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, abbreviate_labs = c(Survived = 1, Age = 3))) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Changes in the margins.} % \label{fig:margins} % \end{center} % \end{figure} \noindent The tl\_\var{foo} (``top left'') arguments are \code{TRUE} by default. Now, we will add boxes to the labels and additionally enable clipping (see Figure~\ref{fig:labels2}, bottom left): <>= mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, boxes = TRUE, clip = TRUE)) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Boxes and Clipping.} % \label{fig:boxes} % \end{center} % \end{figure} \noindent The values to \code{boxes} and \code{clip} are recycled for all dimensions. The result is pretty close to what calling \codefun{mosaic} with the \codefun{labeling\_cboxed} wrapper does, except that variables and levels, by default, are put to the top and to the left of the plot: <>= mosaic(Titanic, labeling = labeling_cboxed) @ \noindent Another variant is to put the variable names into the same line as the levels (see Figure~\ref{fig:labels2}, bottom right---clipping for \code{Survived} and \code{Age} is, additionally, disabled, and \code{Age} abbreviated): <>= mosaic(Titanic, labeling_args = list(tl_labels = TRUE, boxes = TRUE, clip = c(Survived = FALSE, Age = FALSE, TRUE), abbreviate_labs = c(Age = 4), labbl_varnames = TRUE), margins = c(left = 4, right = 1, 3)) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Variable names beneath levels, and clipping disabled for the % survival variable.} % \label{fig:labbl} % \end{center} % \end{figure} \noindent \code{labbl\_varnames} (``variable names to the bottom/left of the labels'') is a vector of logicals indicating the side for the variable names. The resulting layout is close to what \codefun{labeling\_lboxed} produces, except that variables and levels, by default, are left-aligned and put to the bottom and to the right of the plot: <>= mosaic(Titanic, labeling = labeling_lboxed, margins = c(right = 4, left = 1, 3)) @ \noindent A similar design is used by the \codefun{doubledecker} function. \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2, nrow = 2))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(Titanic, labeling_args = list(pos_varnames = "left", pos_labels = "left", just_labels = "left", rep = FALSE), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 12)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, abbreviate_labs = c(Survived = 1, Age = 3)), newpage = FALSE, keep = TRUE, margins = c(left = 4, right = 1, 3), gp_labels = gpar(fontsize = 12)) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, boxes = TRUE, clip = TRUE), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 12)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(tl_labels = TRUE, boxes = TRUE, clip = c(Survived = FALSE, Age = FALSE, TRUE), labbl_varnames = TRUE, abbreviate_labs = c(Age = 4)), margins = c(left = 4, right = 1, 3), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 12)) popViewport(2) @ \caption{Advanced strategies for labeling of the Titanic data. Top left: left aligning of both variable names and labels. Top right: changes in the margins (all variable names are in the top and left margins, and all labels in the bottom and right margins). Bottom left: clipping turned on, and boxes used. Bottom right: variable names beneath levels, clipping disabled for the survival and age variables, and \texttt{Age} abbreviated.} \label{fig:labels2} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \subsection[Labels in the cells]{Labels in the cells: \texttt{labeling\_cells()}} This labeling draws both variable names and levels in the cells. As an example, we use the \data{PreSex} data on pre- and extramarital sex and divorce (see Figure~\ref{fig:labels3}, top left): <>= mosaic(~ MaritalStatus + Gender, data = PreSex, labeling = labeling_cells) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Cell labeling for the \data{PreSex} data.} % \label{fig:cell} % \end{center} % \end{figure} \noindent In the case of narrow cells, it might be useful to abbreviate labels and/or variable names and turn off clipping (see Figure~\ref{fig:labels3}, top right): <>= mosaic(~ PremaritalSex + ExtramaritalSex, data = PreSex, labeling = labeling_cells(abbreviate_labels = TRUE, abbreviate_varnames = TRUE, clip = FALSE)) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Cell labeling for the \data{PreSex} data, labels abbreviated.} % \label{fig:cell2} % \end{center} % \end{figure} \noindent For some data, it might be convenient to combine cell labeling with border labeling as done by \codefun{labels\_conditional} (see Figure~\ref{fig:labels3}, bottom left): <>= mosaic(~ PremaritalSex + ExtramaritalSex | MaritalStatus + Gender, data = PreSex, labeling = labeling_conditional(abbreviate_varnames = TRUE, abbreviate_labels = TRUE, clip = FALSE, gp_text = gpar(col = "red"))) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Conditional labeling for the \data{PreSex} data, labels (in % red for clarity) abbreviated.} % \label{fig:conditional} % \end{center} % \end{figure} \noindent Additionally, the cell labeling allows the user to add arbitrary text to the cells by supplying a character array in the same shape as the data array to the \code{text} argument (cells with missing values are ignored). In the following example using the \code{Titanic} data, this is used to add all observed values greater than 5 to the cells after the mosaic has been plotted (see Figure~\ref{fig:labels3}, bottom right): <>= mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = 1, Age = 4)), pop = FALSE) tab <- ifelse(Titanic < 6, NA, Titanic) labeling_cells(text = tab, clip = FALSE)(Titanic) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{User-supplied text (observed frequencies exceeding 5) % added to a mosaic display of the \data{Titanic} data.} % \label{fig:text} % \end{center} % \end{figure} \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= grid.newpage() pushViewport(viewport(layout = grid.layout(ncol = 2, nrow = 2))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(~ MaritalStatus + Gender, data = PreSex, labeling = labeling_cells, newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(~ PremaritalSex + ExtramaritalSex, data = PreSex, labeling = labeling_cells(abbreviate_labels = TRUE, abbreviate_varnames = TRUE, clip = FALSE), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(~ PremaritalSex + ExtramaritalSex | MaritalStatus + Gender, data = PreSex, labeling = labeling_conditional(abbreviate_varnames = TRUE, abbreviate_labels = TRUE, clip = FALSE, gp_text = gpar(col = "red")), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = 1, Age = 3)), pop = FALSE, newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) tab <- ifelse(Titanic < 6, NA, Titanic) labeling_cells(text = tab, clip = FALSE)(Titanic) @ \caption{Cell labeling. Top left: default labeling using the \data{PreSex} data. Top right: abbreviated labels. Bottom left: conditional labeling (labels abbreviated and in red for clarity). Bottom right: user-supplied text (observed frequencies exceeding 5) added to a mosaic display of the \data{Titanic} data. Note that clipping is on by default (top left), and has explicitly been turned off for the three other plots.} \label{fig:labels3} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \subsection[A simple list of labels]{A simple list of labels: \texttt{labeling\_list()}} If problems with overlapping labels cannot satisfactorily resolved, the last remedy could be to simply list the levels below the plot (see Figure~\ref{fig:list}): <>= mosaic(Titanic, labeling = labeling_list, margins = c(bottom = 5)) @ \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[p] \begin{center} <>= mosaic(Titanic, labeling = labeling_list, margins = c(bottom = 5), keep = TRUE) @ \caption{Labels indicated below the plot.} \label{fig:list} \end{center} \end{figure} \noindent The number of columns can be specified. \section{Spacing} \label{sec:spacing} Spacing of strucplot displays is customizable in a similar way than shading. The \code{spacing} argument of the \codefun{strucplot} function takes a list of \class{unit} vectors, one for each dimension, specifying the space between the tiles corresponding to the levels. Consider again the introductory example of the \data{Arthritis} data (Figure~\ref{fig:arthritis}). Since we are interested in the effect of the medicament in the placebo and treatment groups, a mosaic plot is certainly appropriate to visualize the three levels of \code{Improved} in the two \code{Treatment} strata. Another conceptual approach is to use spine plots with highlighting \citep{vcd:hummel:1996}. A spine plot is a variation of a bar plot where the heights of the bars are held constant, whereas the widths are used to represent the number of cases in each category. This is equivalent to a mosaic plot for a one-way table. If a second (indicator) variable is highlighted in a spine plot, we obtain a display equivalent to a simple mosaic display for a two-way table, except that no space between the levels of the highlighted variable is used. In the \data{Arthritis} example, we will highlight patients with \code{Marked} improvement in both groups. To obtain such a display within the strucplot framework, it suffices to set the space between the \code{Improved} tiles to 0 (see Figure~\ref{fig:artspine}): <>= (art <- structable(~Treatment + Improved, data = Arthritis, split_vertical = TRUE)) (my_spacing <- list(unit(0.5, "lines"), unit(c(0, 0), "lines"))) my_colors <- c("lightgray", "lightgray", "black") mosaic(art, spacing = my_spacing, gp = gpar(fill = my_colors, col = my_colors)) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Spine plot for the \data{Arthritis} data using the strucplot framework.} \label{fig:artspine} \end{center} \end{figure} \noindent Note that the default and formula methods for \codefun{mosaic} provide a convenience interface for highlighting. A similar plot (with slightly different shading) than the previous one can be obtained using: <>= mosaic(Improved ~ Treatment, data = Arthritis, split_vertical = TRUE) @ \noindent The strucplot framework also provides a set of spacing grapcon generators which compute suitable spacing objects for typical applications. The simplest spacing is \codefun{spacing\_equal} that uses the same space between all tiles (see Figure~\ref{fig:spacing}, top left): <>= mosaic(art, spacing = spacing_equal(unit(2, "lines"))) @ \noindent \codefun{spacing\_equal} is the default grapcon generator for two-dimensional tables. Slightly more flexible is \codefun{spacing\_dimequal} that allows an individual setting for each dimension (see Figure~\ref{fig:spacing}, top right): <>= mosaic(art, spacing = spacing_dimequal(unit(1:2, "lines"))) @ \noindent The default for multi-way contingency tables is \codefun{spacing\_increase} which uses increasing spaces for the dimensions. The user can specify a start value and the increase factor (see Figure~\ref{fig:spacing}, bottom left): <>= mosaic(art, spacing = spacing_increase(start = unit(0.5, "lines"), rate = 1.5)) @ \noindent For the arthritis example above, we could as well have used \codefun{spacing\_highlighting} which is similar to \codefun{spacing\_increase} but sets the spacing in the last splitting dimension to 0 (see Figure~\ref{fig:spacing}, bottom right): <>= mosaic(art, spacing = spacing_highlighting, gp = my_colors) @ \noindent Finally, \codefun{spacing\_conditional} can be used for visualizing conditional independence: it combines \codefun{spacing\_equal} (for the conditioned dimensions) and \codefun{spacing\_increase} (for the conditioning dimensions). As an example, consider Figure~\ref{fig:presex}: the spacing clearly allows to better distinguish the conditioning variables (\code{Gender} and \code{MaritalStatus}) from the conditioned variables (\code{PremaritalSex} and \code{ExtramaritalSex}). This spacing is the default when conditional variables are specified for a strucplot display (see Section \ref{sec:strucplot}). \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2, nrow = 2))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(art, spacing = spacing_equal(unit(2, "lines")), keep = TRUE, newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(art, spacing = spacing_dimequal(unit(c(0.5, 2), "lines")), keep = TRUE, newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(art, spacing = spacing_increase(start = unit(0.3, "lines"), rate = 2.5), keep = TRUE, newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(art, spacing = spacing_highlighting, keep = TRUE, newpage = FALSE) popViewport(2) @ \caption{Varying spacing for the Arthritis data. Top left: equal spacing for all dimensions. Top right: different spacings for individial dimensions. Bottom left: increasing spacing. Bottom right: spacing used for highlighting.} \label{fig:spacing} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \section{Example: Ovarian cancer survival} \label{sec:example} In the following, we demonstrate some of the described techniques in analyzing a data set originating from \citep{vcd:obel:1975} \cite[taken from][]{vcd:andersen:1991} about a retrospective study of ovary cancer carried out in 1973. Information was obtained from 299 women, who were operated for ovary cancer 10 years before. The data consists of four binary variables: the \code{stage} of the cancer at the time of operation (levels: \code{early}, \code{advanced}), the type of \code{operation} performed (\code{radical}, \code{limited}), the \code{survival} status after 10 years (\code{yes}, \code{no}), and \code{xray} indicating whether X-ray treatment was received (\code{yes}, \code{no}). The dataset in \pkg{vcd} comes pretabulated in a data frame, so we first create the four-way table: <>= tab <- xtabs(Freq ~ stage + operation + xray + survival, data = OvaryCancer) @ \noindent A ``flattened'' textual representation can be obtained using \codefun{structable}: <>= structable(survival ~ ., data = tab) @ \noindent A first overview can be obtained using a pairs plot (Figure~\ref{fig:ocpairs}): <>= dpa <- list(var_offset = 1.2, rot = -30, just_leveltext= "left") pairs(tab, diag_panel_args = dpa) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Pairs plot for the \data{OvaryCancer} data showing mosaic displays for all pairwise distributions and bar plots for all marginal distributions.} \label{fig:ocpairs} \end{center} \end{figure} \noindent The pairs plot, by default, creates mosaic displays for all pairwise variable combinations, and bar plots in the diagonal to visualize the absolute frequencies of the variables. The \texttt{var\_offset} argument modifies the offset of the (centered) variable names to avoid overlap with the bars. Additionally, we use the \texttt{rot} and the \texttt{just\_leveltext} arguments to rotate the level names, again to avoid their overlap. First, we consider the marginal distributions. The study design involved (nearly) the same number of survived (150) and deceased (149) patients. Similarly balanced, 158 cases were in an advanced and 141 in an early stage. Most patients (251, 84\%) were treated with a radical operation, and 186 (62\%) were submitted to X-ray treatment. Next, we inspect the two-way interaction of the influencing factors (\code{stage}, \code{operation}, and \code{xray}): the corresponding mosaics exhibit symmetric, regular shapes with aligned tiles, which indicate no marginal interaction between these variables. The same is true for the interactions of \code{survival} with \code{operation} and \code{xray}, respectively. Only the stage seems to influence survival: here, the tiles are ``shifted''. A different view on the data, focused on the influence of the explanatory variables on \code{Survival}, can be obtained using a doubledecker plot (Figure~\ref{fig:ocdoubledecker}): <>= doubledecker(survival ~ stage + operation + xray, data = tab) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Doubledecker plot for the \data{OvaryCancer} data showing the conditional distribution of X-ray, given operation, given stage, and with survival highlighted.} \label{fig:ocdoubledecker} \end{center} \end{figure} \noindent From a technical point of view, the display is constructed as a mosaic plot showing the conditional distribution of \code{survival}, given \code{xray}, given \code{operation}, given \code{stage}, with vertical splits for the conditioning variables and horizontal ones for \code{survival}. Additionally, there is zero space between the tiles of the last dimension and a binary shading is used for survived and deceased patients. Conceptually, this plot is interpreted as a mosaic plot of just the influencing variables, with \code{survival} highlighted in the tiles. Thus, the plot really shows the influence of the explanatory variables on \code{survival}. Clearly, the survival rate is higher among patients in an early stage, but neither radical operation nor X-ray treatment seem to improve the situation. From this exploratory phase, the survival rate seems to be slightly higher for patients who received a limited operation only, whereas the effect for X-ray treatment is less marked. To visualize inference results, we can make use of residual-based shadings, investigating log-linear models for the four-way table. Figure~\ref{fig:ocmosaicnull} visualizes the null model, where survival is independent from the combined effect of operation, X-ray treatment, and stage: <>= split <- c(TRUE, TRUE, TRUE, FALSE) mosaic(tab, expected = ~ survival + operation * xray * stage, split_vertical = split) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{OvaryCancer} data, with residual-based shading for the (clearly rejected) null model (survival)(operation, X-ray, stage).} \label{fig:ocmosaicnull} \end{center} \end{figure} \noindent The model is clearly rejected ($p$-value: 0.000). From the exploratory phase of our analysis, we (only) suspect \code{stage} to be influential on the survival rate. A corresponding hypothesis is that \code{survival} be independent of \code{xray} and \code{operation}, given \code{stage}. The model is specified using the \texttt{expected} argument, either using the \codefun{loglin} interface or the \codefun{loglm} formula interface (the resulting mosaic plot is shown in Figure \ref{fig:ocmosaicstage}): <>= mosaic(tab, expected = ~ (survival + operation * xray) * stage, split_vertical = split) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{OvaryCancer} data, with residual-based shading for the hypothesis of survival being independent of X-ray and operation, given stage. The hypothesis is not rejected.} \label{fig:ocmosaicstage} \end{center} \end{figure} \noindent Thus, based on this data, only pre-diagnosis seems to matter in ovarian cancer therapy. \section{Conclusion} \label{sec:conclusion} In this paper, we describe the ``strucplot'' framework for the visualization of multi-way contingency tables. Strucplot displays include popular basic plots such as mosaic, association, and sieve plots, integrated in a unified framework: all can be seen as visualizations of hierarchical conditional flat tables. Additionally, these core strucplot displays can be combined into more complex, specialized plots, such as pairs and trellis-like displays for visualizing conditional independence. Residual-based shadings permit the visualization of log-linear models and the results of independence tests. The framework's modular design allows flexible customization of the plots' graphical appearance, including shading, labeling, spacing, and legend, by means of graphical appearance control (``grapcon'') functions. These ``graphical hyperparameters'' are customized and created by generating functions. Our work includes a set of predefined grapcon generators for typical analysis tasks, and user-level extensions can easily be added. \bibliography{vcd} \begin{appendix} \section{Data sets} \label{sex:data} The data set names in the paper are those from the \proglang{R} system. In the following, we give a short description of each data set. \begin{description} \item[\texttt{Arthritis}] Data from a double-blind clinical trial investigating a new treatment for rheumatoid arthritis. Source: \cite{vcd:Koch+Edwards:1988}. Taken from: \cite{vcd:Friendly:2000}. Package: \pkg{vcd}. \item[\texttt{Bundesliga}] Results from the first German soccer league in the years 1995/6 \citep{vcd:Knorr-Held:1999} and 2001/2 (Collected by: Achim Zeileis). Package: \pkg{vcd}. \item[\texttt{HairEyeColor}] Distribution of hair and eye color and gender in 592 statistics students. The gender information is artificial. Source: \cite{vcd:Snee:1974}. Taken from: \cite{vcd:Friendly:2000}. Package: \pkg{datasets} (included in base \proglang{R}). \item[\texttt{OvaryCancer}] Data about a retrospective study of ovary cancer carried out in 1973. Information was obtained from 299 women, who were operated for ovary cancer 10 years before. Source: \cite{vcd:obel:1975}. Taken fromn: \cite{vcd:andersen:1991}. Package: \pkg{vcd}. \item[\texttt{PreSex}] Data on pre- and extra-marital sex and divorce. Source: \cite{vcd:thornes+collard:1979}. Taken from \cite{vcd:gilbert:1981}. Package: \pkg{vcd}. \item[\texttt{Titanic}] Information on the fate of passengers on the fatal maiden voyage of the ocean liner ``Titanic'', summarized according to economic status (class), gender (\code{Sex}), age and survival. Data originally collected by the British Board of Trade in their investigation of the sinking. Taken from: \cite{vcd:dawson:1995}. Package: \pkg{datasets} (included in base \proglang{R}). \item[\texttt{UCBAdmissions}] Aggregate data on applicants to graduate school at Berkeley for the six largest departments in 1973 classified by admission and gender. Source: \cite{vcd:Bickel+Hammel+O'Connell:1975}. Taken from: \cite{vcd:Friendly:2000}. Package: \pkg{datasets} (included in base \proglang{R}). \end{description} \end{appendix} \end{document} vcd/inst/doc/residual-shadings.Rnw0000644000175300001440000003655511720426623016536 0ustar meyerusers\documentclass{Z} %% need no \usepackage{Sweave} \usepackage{rotating} \newcommand{\given}{\, | \,} \title{Residual-based Shadings in \pkg{vcd}} \Plaintitle{Residual-based Shadings in vcd} \author{Achim Zeileis, David Meyer, \textnormal{and} Kurt Hornik\\Wirtschaftsuniversit\"at Wien, Austria} \Plainauthor{Achim Zeileis, David Meyer, Kurt Hornik} \Abstract{ This vignette is a companion paper to \cite{vcd:Zeileis+Meyer+Hornik:2005} which introduces several extensions to residual-based shadings for enhancing mosaic and association plots. The paper introduces (a)~perceptually uniform Hue-Chroma-Luminance (HCL) palettes and (b)~incorporates the result of an associated significance test into the shading. Here, we show how the examples can be easily reproduced using the \pkg{vcd} package. } \Keywords{association plots, conditional inference, contingency tables, HCL colors, HSV colors, mosaic plots} \begin{document} %\VignetteIndexEntry{Residual-based Shadings in vcd} %\VignetteDepends{vcd,colorspace,MASS,grid,HSAUR} %\VignetteKeywords{association plots, conditional inference, contingency tables, HCL colors, HSV colors, mosaic plots} %\VignettePackage{vcd} \SweaveOpts{engine=R,eps=FALSE} \section{Introduction} \label{sec:intro} In this vignette, we show how all empirical examples from \cite{vcd:Zeileis+Meyer+Hornik:2005} can be reproduced in \proglang{R}\citep[\mbox{\url{http://www.R-project.org/}}]{vcd:R:2006}, in particular using the package \pkg{vcd} \citep{vcd:Meyer+Zeileis+Hornik:2006}. Additionally, the pakcages \pkg{MASS} \citep[see][]{vcd:Venables+Ripley:2002}, \pkg{grid} \citep[see][]{vcd:Murrell:2002} and \pkg{colorspace} \citep{vcd:Ihaka:2004} are employed. All are automatically loaded together with \pkg{vcd}: <>= library("vcd") rseed <- 1071 @ Furthermore, we define a \code{rseed} which will be used as the random seed for making the results of the permutation tests (conditional inference) below exactly reproducible. In the following, we focus on the \proglang{R} code and output---for background information on the methods and the data sets, please consult \cite{vcd:Zeileis+Meyer+Hornik:2005}. \section{Arthritis data} \label{sec:arthritis} First, we take a look at the association of treatment type and improvement in the \code{Arthritis} data. The data set can be loaded and brought into tabular form via: <>= data("Arthritis", package = "vcd") (art <- xtabs(~ Treatment + Improved, data = Arthritis, subset = Sex == "Female")) @ Two basic explorative views of such a 2-way table are mosaic plots and association plots. They can be generated via \code{mosaic()} and \code{assoc()} from \pkg{vcd}, respectively. For technical documentation of these functions, please see \cite{vcd:Meyer+Zeileis+Hornik:2006b}. When no further arguments are supplied as in <>= mosaic(art) assoc(art) @ this yields the plain plots without any color shading, see Figure~\ref{fig:classic}. Both indicate that there are more patients in the treatment group with marked improvement and less without improvement than would be expected under independence---and vice versa in the placebo group. \setkeys{Gin}{width=\textwidth} \begin{figure}[b!] \begin{center} <>= grid.newpage() pushViewport(viewport(layout = grid.layout(1, 2))) pushViewport(viewport(layout.pos.col=1, layout.pos.row=1)) mosaic(art, newpage = FALSE, margins = c(2.5, 4, 2.5, 3)) popViewport() pushViewport(viewport(layout.pos.col=2, layout.pos.row=1)) assoc(art, newpage = FALSE, margins = c(5, 2, 5, 4)) popViewport(2) @ \caption{Classic mosaic and association plot for the arthritis data.} \label{fig:classic} \end{center} \end{figure} For 2-way tables, \cite{vcd:Zeileis+Meyer+Hornik:2005} suggest to extend the shading of \cite{vcd:Friendly:1994} to also visualize the outcome of an independence test---either using the sum of squares of the Pearson residuals as the test statistic or their absolute maximum. Both statistics and their corresponding (approximate) permutation distribution can easily be computed using the function \code{coindep_test()}. Its arguments are a contingency table, a specification of margins used for conditioning (only for conditional independence models), a functional for aggregating the Pearson residuals (or alternatively the raw counts) and the number of permutations that should be drawn. The conditional table needs to be a 2-way table and the default is to compute the maximum statistic (absolute maximum of Pearson residuals). For the Arthritis data, both, the maximum test <>= set.seed(rseed) (art_max <- coindep_test(art, n = 5000)) @ and the sum-of-squares test, indicate a significant departure from independence. <>= ss <- function(x) sum(x^2) set.seed(rseed) coindep_test(art, n = 5000, indepfun = ss) @ Thus, it can be concluded that the treatment is effective and leads to significantly more improvement than the placebo. The classic views from Figure~\ref{fig:classic} and the inference above can also be combined, e.g., using the maximum shading that highlights the cells in an association or mosaic plot when the associated residuals exceed critical values of the maximum test (by default at levels 90\% and 99\%). To compare this shading (using either HSV or HCL colors) with the Friendly shading (using HSV colors), we generate all three versions of the mosaic plot: <>= mosaic(art, gp = shading_Friendly(lty = 1, eps = NULL)) mosaic(art, gp = shading_hsv, gp_args = list( interpolate = art_max$qdist(c(0.9, 0.99)), p.value = art_max$p.value)) set.seed(rseed) mosaic(art, gp = shading_max, gp_args = list(n = 5000)) @ the results are shown in the upper row of Figure~\ref{fig:shadings}. The last plot could hae also been generated analogously to the second plot using \code{shading_hcl()} instead of \code{shading_hsv()}---\code{shading_max()} is simply a wrapper function which performs the inference and then visualizes it based on HCL colors. \section{Piston rings data} \label{sec:arthritis} Instead of bringing out the result of the maximum test in the shading, we could also use a sum-of-squares shading that visualizes the result of the sum-of-squares test. As an illustration, we use the \code{pistonrings} data from the \code{HSAUR} \citep{vcd:Everitt+Hothorn:2006} package giving the number of piston ring failurs in different legs of different compressors at an industry plant: <>= data("pistonrings", package = "HSAUR") pistonrings @ \begin{sidewaysfigure}[p] \begin{center} <>= mymar <- c(1.5, 0.5, 0.5, 2.5) grid.newpage() pushViewport(viewport(layout = grid.layout(2, 3))) pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1)) mosaic(art, margins = mymar, newpage = FALSE, gp = shading_Friendly(lty = 1, eps = NULL)) popViewport() pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2)) mosaic(art, gp = shading_hsv, margins = mymar, newpage = FALSE, gp_args = list(interpolate = art_max$qdist(c(0.9, 0.99)), p.value = art_max$p.value)) popViewport() pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 3)) set.seed(rseed) mosaic(art, gp = shading_max, margins = mymar, newpage = FALSE, gp_args = list(n = 5000)) popViewport() pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 1)) mosaic(pistonrings, margins = mymar, newpage = FALSE, gp = shading_Friendly(lty = 1, eps = NULL, interpolate = c(1, 1.5))) popViewport() pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 2)) mosaic(pistonrings, gp = shading_hsv, margins = mymar, newpage = FALSE, gp_args = list(p.value = 0.069, interpolate = c(1, 1.5))) popViewport() pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 3)) mosaic(pistonrings, gp = shading_hcl, margins = mymar, newpage = FALSE, gp_args = list(p.value = 0.069, interpolate = c(1, 1.5))) popViewport(2) @ \includegraphics[width=.9\textwidth,keepaspectratio]{residual-shadings-shadings} \caption{Upper row: Mosaic plot for the arthritis data with Friendly shading (left), HSV maximum shading (middle), HCL maximum shading (right). Lower row: Mosaic plot for the piston rings data with fixed user-defined cut offs 1 and 1.5 and Friendly shading (left), HSV sum-of-squares shading (middle), HCL sum-of-squares shading (right).} \label{fig:shadings} \end{center} \end{sidewaysfigure} Although there seems to be some slight association between the leg (especially center and South) and the compressor (especially numbers 1 and 4), there is no significant deviation from independence: <>= set.seed(rseed) coindep_test(pistonrings, n = 5000) set.seed(rseed) (pring_ss <- coindep_test(pistonrings, n = 5000, indepfun = ss)) @ This can also be brought out graphically in a shaded mosaicplot by enhancing the Friendly shading (based on the user-defined cut-offs 1 and 1.5, here) to use a less colorful palette, either based on HSV or HCL colors: <>= mosaic(pistonrings, gp = shading_Friendly(lty = 1, eps = NULL, interpolate = c(1, 1.5))) mosaic(pistonrings, gp = shading_hsv, gp_args = list(p.value = pring_ss$p.value, interpolate = c(1, 1.5))) mosaic(pistonrings, gp = shading_hcl, gp_args = list(p.value = pring_ss$p.value, interpolate = c(1, 1.5))) @ The resulting plots can be found in the lower row of Figure~\ref{fig:shadings}. The default in \code{shading_hcl()} and \code{shading_hsv()} is to use the asymptotical $p$~value, hence we set it explicitely to the permtuation-based $p$~value computed above. \section{Alzheimer and smoking} \label{sec:alzheimer} For illustrating that the same ideas can be employed for visualizing (conditional) independence in multi-way tables, \cite{vcd:Zeileis+Meyer+Hornik:2005} use a 3-way and a 4-way table. The former is taken from a case-control study of smoking and {A}lzheimer's disease (stratified by gender). The data set is available in \proglang{R} in the package \pkg{coin} \cite{vcd:Hothorn+Hornik+VanDeWiel:2006}. <>= data("alzheimer", package = "coin") alz <- xtabs(~ smoking + disease + gender, data = alzheimer) alz @ \begin{figure}[b!] \begin{center} <>= set.seed(rseed) cotabplot(~ smoking + disease | gender, data = alz, panel = cotab_coindep, n = 5000) @ \caption{Conditional mosaic plot with double maximum shading for conditional independence of smoking and disease given gender.} \label{fig:alz} \end{center} \end{figure} To assess whether smoking behaviour and disease status are conditionally independent given gender, \cite{vcd:Zeileis+Meyer+Hornik:2005} use three different types of test statistics: double maximum (maximum of maximum statistics in the two strata), maximum sum of squares (maximum of sum-of-squares statistics), and sum of squares (sum of sum-of-squares statistics). All three can be computed and assessed via permutation methods using the function \code{coindep_test()}: <>= set.seed(rseed) coindep_test(alz, 3, n = 5000) set.seed(rseed) coindep_test(alz, 3, n = 5000, indepfun = ss) set.seed(rseed) coindep_test(alz, 3, n = 5000, indepfun = ss, aggfun = sum) @ The conditional mosaic plot in Figure~\ref{fig:alz} shows clearly that the association of smoking and disease is present only in the group of male patients. The double maximum shading employed allows for identification of the male heavy smokers as the cells `responsible' for the dependence: other dementias are more frequent and Alzheimer's disease less frequent in this group than expected under independence. Interestingly, there seems to be another large residual for the light smoker group ($<$10 cigarettes) and Alzheimer's disease---however, this is only significant at 10\% and not at the 1\% level as the other two cells. <>= <> @ \section{Corporal punishment of children} As a 4-way example, data from a study of the Gallup Institute in Denmark in 1979 about the attitude of a random sample of 1,456 persons towards corporal punishment of children is used. The contingency table comprises four margins: memory of punishments as a child (yes/no), attitude as a binary variable (approval of ``moderate'' punishment or ``no'' approval), highest level of education (elementary/secondary/high), and age group (15--24, 25--39, $\ge$40 years). <>= data("Punishment", package = "vcd") pun <- xtabs(Freq ~ memory + attitude + age + education, data = Punishment) ftable(pun, row.vars = c("age", "education", "memory")) @ It is of interest whether there is an association between memories of corporal punishments as a child and attitude towards punishment of children as an adult, controlling for age and education. All three test statistics already used above confirm that memories and attitude are conditionally associated: \setkeys{Gin}{width=\textwidth} \begin{figure}[t!] \begin{center} <>= set.seed(rseed) cotabplot(~ memory + attitude | age + education, data = pun, panel = cotab_coindep, n = 5000, type = "assoc", test = "maxchisq", interpolate = 1:2) @ \caption{Conditional association plot with maximum sum-of-squares shading for conditional independence of memory and attitude given age and education.} \label{fig:pun} \end{center} \end{figure} \setkeys{Gin}{width=\textwidth} \begin{figure}[t!] \begin{center} <>= set.seed(rseed) cotabplot(~ memory + attitude | age + education, data = pun, panel = cotab_coindep, n = 5000, type = "mosaic", test = "maxchisq", interpolate = 1:2) @ \caption{Conditional mosaic plot with maximum sum-of-squares shading for conditional independence of memory and attitude given age and education.} \label{fig:pun2} \end{center} \end{figure} <>= set.seed(rseed) coindep_test(pun, 3:4, n = 5000) set.seed(rseed) coindep_test(pun, 3:4, n = 5000, indepfun = ss) set.seed(rseed) coindep_test(pun, 3:4, n = 5000, indepfun = ss, aggfun = sum) @ Graphically, this dependence can be brought out using conditional association or mosaic plots as shown in Figure~\ref{fig:pun} and \ref{fig:pun2}, respectively. Both reveal an association between memories and attitude for the lowest education group (first column) and highest age group (last row): experienced violence seems to engender violence again as there are less adults that disapprove punishment in the group with memories of punishments than expected under independence. For the remaining four age-education groups, there seems to be no association: all residuals of the conditional independence model are very close to zero in these cells. The figures employ the maximum sum-of-squares shading with user-defined cut offs 1 and 2, chosen to be within the range of the residuals. The full-color palette is used only for those strata associated with a sum-of-squares statistic significant at (overall) 5\% level, the reduced-color palette is used otherwise. This highlights that the dependence pattern is significant only for the middle and high age group in the low education column. The other panels in the first column and last row also show a similar dependence pattern, however, it is not significant at 5\% level and hence graphically down-weighted by using reduced color. <>= <> @ <>= <> @ \bibliography{vcd} \end{document} vcd/inst/doc/residual-shadings.pdf0000644000175300001440000071011411720426623016527 0ustar meyerusers%PDF-1.5 % 1 0 obj << /Type /ObjStm /Length 3732 /Filter /FlateDecode /N 71 /First 565 >> stream x[msӸ~mm@KK LeYv&nc)t}$NB~Hѣ&1L1s֜fgʼn`1R,a'eƥ0k42x4(0nВ~*T"&bK0$ LrH&KZ5*a̤5`3H%L)0 L), :KF]1D h1wô21iR8L2Y &LJifÌAL11e&)劘3 9 CDChY,0mXL8kZ _,1NX@>#+$(I`dL(dX/4A4xBy, cHHL$}, Y8?IYVmDCO={'`u?s?#p?j~,ܩ6+^a6ӧA j }֠$}qGYSMA~ry~Osm 6 .ﳼav_Tu|,H?`1 W':iU"r ,'-EZ Zxh#ȏ /?uxbR L'p$ LC HIRŁBRZzDruNrp*7d݃% f oGsAWoq~98ڞ<7KWFnچ@ziB06)Rix 4wDג'Qee0݉ MԷYY(%I)(<$'%2a$-hkBJeEr&i]+0/-ȫtL=w~U1~Xaa";;4Ü|XhClEn~vAyIYt8/ 44ڬ(*+ 49 HLgEm^ 4N5<g:ܚaa5fg, WQѴBNi> 0 00 pa^`C46#{wۀl[8w¹^^dt⏨/z۴Oszf㷌][N5wL`-ͦ/%&&  GWT`Iݡ q/l`uz_idN"Wa;6=])N!,tPWXзW. -Au3kJ+#;spWi=ybB*l+_-o[\ =%tf 4kn ~~k ݽA>n5>nӺ}3vTuZɴ̛јfS:NJuoNƒ'5wk0mSOD&oڪdt=קKd{fHX3> tuJ@twoBwKAof^0G5IoN Eq%7a&[8R\q<ڦchp~L "iq&KE_o > stream xڥY[o~ DC΅hf7mHH]jQtI)=!8-r.g|g ~/o$HH% 1YUF:)*^, 7Tnwu5̆7kpn 7R(0@T.*Y $Qa•s0*& Wpbpi5GY ^˙VW?O8Tw5?4Td±Rhio홧-|u;RMcmY9UY]߉: 'ǃfw֚ pG3j;i8$M 6UPƔ4Urqgj4G.c}(ڤT"> stream xZkSF?+-K CEm3 #"i _Ja ̀uUl4V į|dksα aXP,`d,:<3,_*-Y4F&oƳJ(JýbHХ +KL@h-ėŴȴi ΤLMʹ`D2==r̈H< H@#2c@YX`8tKԣ PěV4c,aUFJϬ&e`J m:+@47'Ќ֑9MeUg.Xzz"R!57=c:b}dRÄB# GTPQ#1aRɨh8jȑx61. ̩즩A/}ǒb\ADaWѵS73õpko-j: v mx!kpBg۲f56KeW5;ƣߍxxyͳhʪA_Eh! :|\d l:$j42֣f6oݤnE:,0O}1{qNʌ%?FsE9J(N4Y9a.K(#Y5ś< M8g9y{)qQOv L~qBoL=|:/[i[@d**mn7p@0 2zQezq*󤾘/oz'}|ƃbOJj{6p Zw77i!¬uٴpʯ;򓓬ƃ"o,9Ǔ2zǤQvR79#TU,9- &t2d]GCtS@I~%+_8."R#*5!h3X.L-xPs0qХᐲozOK"(tZ>cѡ.HDZ1 }$t=:ƾMKʹ II>v{fK֯{G?6Nld_~Q>Q@#U@V <'@hG4wX]/ioY.f1?Æp+)v.Z55X&JKj)qpG]ə?=;7{|bv% Bx0z~̽v5KJn>>{3iJ'-Lllϕs39CS`s9)+\4YU/E5;qO+3W ٶ6-Yژ=&mx辴MFï6z6%,pHm׋x$+>,r^\!Zw$e0Z|`,ooHţB Ӫٙf+$UuZWIY$:ysKg6smx:а6~?񃵋p>,8{pkrtD2J T3#Q " Ү.CAhm:k2cKvc}== zLAQ qu=zs7iUòFr^D6/x:ߓɧd< '6N 5a=rZ)]٘xOde_4}{Tӵ.!|DX!|"@{*E?G?RJOeЈO*ݑw㷤^?Y x ETQV:&=v& >( UW-5ŏYk qݲB̵(4}(H ^Z5rh0 A`.`'BbAh)PRFϼmIm00 4h'(6sSJAŠF15fF%0q$ ĩAXL on}B䷂d&7 mHFwxfW #d33m'^$Mg2Y UIk~ԗE,xDSIs{V̴ l 5ؚ/DSq|;DzGM]iحQ>Xb4nCS*\L: fشH. شIpH/Rd^5ʫeB_v&r6Ha{Ҹ4Ol4ɒ.' Jgmq|_>i5%te5{)m`)$-'ZtJ=B_3Kvw;`nW͏wsKendstream endobj 146 0 obj << /BBox [ 0 0 792 432 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./residual-shadings-Arthritis-classic1.pdf) /PTEX.InfoDict 38 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 41 0 R >> /ExtGState << >> /Font << /F2 39 0 R /F3 40 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 600 >> stream xWMs0Wj+SfioLC w?bBAbd}owvm9lW ևDa-ꆟ:-K<6 ?uJR $d:fKrh]MJa\|[FSgz<+H)$'Dn\x6'~=fYS#>ȾI6 ==Yɧ~ɮMo!'#bme&m'){ڗ)xWE}h*^"5 ŽO8ɺ:M>߯7UR^Ha8 @m~1$tc+ƶ0+:QIoUVyzq  bdjpzݵ ^TljlX鬾_iX#c189ʃ,^g8[䎼T}8S~ӕ\rź!66`e8v:6ÀҠ# O^I ׃uѾ1T6F06ܩFendstream endobj 147 0 obj << /Filter /FlateDecode /Length 1774 >> stream xڍXmoD_}#@!JH6{٤C'~;:M{Uxw;3;/&ɋ|ZguTyVմubzM_/J/癩 BK^J~in'‘wYjNl,mW4ahՅ fz,pUH3cijl6x߷&A |+/rx|໓WkodO/ΘӭpXWu~;Y S{pHEQ!hHG_b?^q){]tVہx)ooeW':;C>rHo7h#>PUl yۊ272:"–Y=E[4lL&CTR;~|n$[噵j,9D[vTJ,y]$$&)GV>~͛Ky,UMK6kiP26凙P%[ΓY݋ݮ !BipMM@@ABدC$L8E8Y%~7F^ ٲEhOO%c̅ž:0fiY(2J5[_IA͎xh`DȬl%ؼx#1#X1IP[dUգ(~H"R0ckO֧Z٬66,;5 .]-0#I |MU3KY" V,91$0T[pX 0:p)t`&Lr;v:ỲSj0 'OwXy-Cq9gO #l|rw*b=)eT:&# Ў-Y>z!A=Zuܸ`&Ϛ:~?G 0Yn!xń4&j!!>\ Ըt?j01;y!oVvϓ1"QQEID\IV`?ORkp u{z1V>bLUd! T_A4?m㗕d pr8Tw*WYNnԵ`0a_jC7>Xi?z"S(2eF/k+n烋|hZ^]Ǘ[h*irMM?7,C(7ٓ^?endstream endobj 148 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 149 0 obj << /Filter /FlateDecode /Length 2152 >> stream xَD}"䈉W|i9V0rc;p`'s >:ٙežQ]uMoO{lڭ׫]sAaVO!kFHuFIfF|8RH,zEߙl)I/XbGܯOIr8C$!+SP~fWBP{}zע|4)i-Z b.5 Eض'i9ͪשּׂ]n·$Z##Ǯ6jN6m/x8i:XUf?>hv kv Cj4G#a%qb&] (A J Rlc7Y{tWUPJD!bRK]zHpX7 ͔(1^*8 %3jSMWT[~b*Iz^TR@Eg (꛵:WSn]h>E.E5Kʻ禓[\~k#5(W L5t"S^W!ZB)ރ6FJyMeS7/~ev9HgP}{-dMrU}eCUs#K$0q Au-î1}Mz@ԋ=oG7QxH7/z^jtbP!f:J7}=^u/KiO[$s^sKGp7Cbg(5wl\ͼclJT3v\MwB0@arsp#'*-'U.w-T~:/3~|att呤ǵ[kdL09+PoUNyܕ |=FZu~ZD[JVY{ k05 n)|q#E'`W]Kt TtBd}TYsRFZt`Gr$:{r1j~V <B6OV9kU;{{.KbҔVgY/YdP~xyGx_p1[b޼Z;hw &VZiEj о;s K6z pJkVZ7Z5E 'zĮ^p^wɸ@ye҈HR08yom,n[J-ggYnlpă B ~jzL+D%O㮒/XGRT.lOEngCM~#_qq|=;8z;endstream endobj 150 0 obj << /Filter /FlateDecode /Length 1704 >> stream xXYoF~ >PpR#SA}IDUܸsr9 ?=fggf7"ogO.^μ멧(̲ ('?u,v q)p!wH&;+ nՓQy9$[:ogZE#= E"=PJ84. E Nq c4wۖ6 <74yOJFY$W7TD^EJ3W+<9.p.2;o63nˤn^ R(ޮ!!\%y/Q+eOR0y9pmIt'd%$UFlH۠@)ȴ] I#Y1h(aNp S,;2Y޿uևAҜ![P9߲3%$/яwovPr+r+ssz9y]a M Qӊ |dXFdI¡]r4Yf*6< 9<pS]}HB~`$s3_ܲ#*-=h"cx^DW-n X8-Q YPL3]V(QfہaphHBCظzL7fm\764?-o6A8*эMF#A~;Uj$Icoj16κHKK!H0vd;Y9JNOrc@\FgݚY')'#ϙZ8U|͇ӿ z93"'9 #RaPCeE(n;WRb1 u1]bgW ,L |tTV~ί 6{^DODqY8c1_±3VZ8D,4j]#=ov(戧i OPRIZlf.4 f- egrNNpR$1'n182i)ZbYJ 2+|ؕ"ՄG։i'p>֗;҅p DZU S/DzY0O"}6$#6"|3X胊٪פr`6 R^oYjMel  R'ٱv@Qv ^ p:y{z,dZ?e9iFg[ixr`3o꽱$# sOGp_IBFbj]䄐y=LXcv)6&Jq}E}(3>(??WS)c7~<3S Kۃq)M'5HW ґ ⮯;`}ƌnkø$`Xo+ R}!eUƵ0dymJz \N\ک9'|EĽAPiDET~嬬Lh-ޱIS'.=p͙B.:jB8f*Eܺgqj nV6râsW|AW-ZWXV(.^l}{$8xθ\ÿK.CVSĹlkky{@ZN85G5g=j|ڟ }&<]~6{9B_ESӣYC?Z^+:-?$ւendstream endobj 151 0 obj << /Filter /FlateDecode /Length 628 >> stream xڅTr@+(U,ZAev ,9Mߧ,P.K=wl{iYLel`(,2KY;U$;Xk~kpM# x HU~>RE׏;qu׷̯dZSLuV @Y,$& IYrj6_ М! ,)D甬tI.D게dcN1yV nM*}$f8u'Lmf,w|3Q ~ِn*Òɤn;`|C7T1ֆ,:%P8wMl{5pyIc\VPB;6HYtB?zO$wd=W6;kkU*ã8K"C1~E~\6<Ś7PvKnC7{ c2Mmy۳I;rsudԖ/.j-IN>P;q,zUEXPƸ"c, fp.Ϲ/p Q'K aSB0?}^ Id[endstream endobj 152 0 obj << /Filter /FlateDecode /Length1 1604 /Length2 8571 /Length3 0 /Length 9608 >> stream xڍT.Lw CIǀ4-] ] R (HK) " %p;|ZYk}vxaP/1_['#r x@އBwQf Ccʰ;:a)/ \7mB P5Gmzm0nkXZe8unV! WFkՃr(քB~?5. / >t MR^;>Aa$> `xapCr[8w?<ҿEd xtDtVA"п<"@a?ay`T@>?3L?_ϻ{A8spX֋wԞ\#'7 2ٸ|mWilosWgi]DkRt;Mu)Z-~7I-8cd=;`?ҕwڄܮ]@ׇ/o§7~|{f+N/4l:+ ;//©ӳI{:$8_o|_}t\;(()hPOƟlƮ<J>%KM Dh@v|OP6U%]OַwM"^S,C7!9;DU|~9xVțf&~ 0KhCB3G"K@Aݚwq<%PNz}'=(BN M^:ڒ+Dgx7A / K{-+̢E 5'rSȧ!rū Ri;1et38s_ ]QsFf3toOϰڵ\BJ2F?pW0 +FP^ȗls54,BWlut o̯oo)c  >PyNy+3aaC1 , 10̆ #B|N6f2zɎFSIavꅞ_=iv|ZiXgv$@˨[]bJI]ѻSB^Fm?՚a%-o-Gx`nZ١fe]NߣLKsoШ@nyDϔC/4O3Sc }1igGS6+T*+?-;8XH"K dRO?)fw>y]~b#=!:V;h'xBIcfMF᳻9D?* /_DDF6;˷",Mg=\wJeN2lp 4Fw "'(EUWhg4q<\複t?_f΢ٗ6 Q!9q.[dӉ?%@d91`X3A `h{޺dz>kÙnrMnHOL%rP)k { +au:jugnAaN踡Cp,JK6&!a$<^ATfA/Gハ"5h clQ2K] @X ޔ4-X0x\כ,;~HQ-g a=Uw?'zKd(UScHr^c9z(*HPη [a}]m*<]*=-RKB2 eIT`/~VFJ= CL.[_Us tZУPo> 69&Pʘ@d, zT]tD|7w0>XsE jc8:BCy:kU]!?ԍ4~D g/7B ru+1: @Y^W)=Obϡ]-c\A eӛر2'L3߇͈ p]cFC! Nh}IٙL}ctLLż& WU5;3iG3zXV* 5 jj$ Mj4|#4K9՜^Tݫ{5SlGwȍVqf@ E<s07Y(C ,{?f%bzPcx҅}IDU W$ ]I"kﱦ]֍aXq\{zku_ptk8mI\嚗.V&=.kp׻k]&ՠ#y -$/v'ծwE,/nQDC@xTk>1<iճkc" I?=(yɥj凜}n!L0}^#WXoNgc+PN0 }8BdjT=odHUnm7EwW(hiD.;߷92c_NAs]tņ́~_ Cj{6Ss5h@A9O/\uuxuD2݋V(wuP>W礸O?u(N(EƎ_Ճ=&a)\&R@CCAӫqLkW`koc~ ɲ&Sao&ʟ^47LL {q=~wۯ$ž01yFUK:R3wEm,jU*~a!GX:.} $!UhG% 5ز^6Odrҙ BBC2B\W,&mT`K /)oֿywzX$T:|@깉䬲%z#3EܷgUFntW[`QK `կMv]}Xj3َ$xdYCqZ/C?XXJ-k)顥8w|k߈Hi8;J$bOvtȏ܅˝uwwiB1gSݝktmB"Q%=qXz$FOg1OU%tOSG}iDz,uӘ1vrTKNp-u9:<a1ESVFr?*5~,δ^K4,CM99(̳ 6y[jq'8W{C_3%eh&'jDVPE"Om4-zP#_5/7}NǎGy=u4T18T_OnF\ڧ<ßyʠrz֊ql)ۏ j*.P{+6ea`?t? oIPEƣ+ɇh[}O^Q/^ӏTMk_r<-.}XfnhxLG禮c/|;εJ ΈM\:]v s7õ5h9~WtHu4mnOB9bSPBk'˓3"g_ YQn(q"k ;{IC3陯 [$ knףmml q7מm v- W"j9xJnZ]Z*nj-6? ?ۙ$\e4e53=qڰJIjtQ`Q-WfСlHڮW(n9 4dn/. Ir '+)V{bτAN1Df_2;s6 &`4FϢ(@֖r,Ljd$=B#k'+Gix`&|8sO:{ԑ?3&I@6-g{h ){ ܤh9?_+CrS4 Sh+{t_:H3iL:u I Y^G`K%B.)"=[ח_>@iX"Ϳ4''?(MƒӈGUT av_5v~1dht/~g`Qld)lUpC"J-S+{cgk#VPh+kռ:'H=oҌEߣxq@i.l7Nd)xذUhlksҪhh}]'37nг n%Q'xx1.iA@IEKǔG : ~Na^~WtC`$ 36c4DMxEp4jS ~qճY$Nf/s>3GhܡeUQj^͊p8Trt||qjG-fˉDcOQsg\/* x R`ܖcJޓL鵸[gU2= uij.B ږG4-w\cﻐ%|ilώ,:0LDeIE\DBά 7FE᥊f)^+&PѯS .n֙g 3GvzGTgV|B: z+*Fcaڇ2ZDHEeA5V!]wdRg#&bT`é弚O)&"c6ɋpѧFcLbS[VӖ=llad7_@ƌH|]m48?=Ȉ6WGG~He7jZMH3h EyB7$9d I?FvD9iacaC ^haEWJ,Z(Sx̘f,E\xE{:'ΚWEߠq.PfcQ^k~Mp…D J#V'/I^  FV $fJRfP>k*+iI{KM˺R߷/0VPB6KBCD1-b!WOǢacJU//g(C,mܡ)$ZL[D D闣[JȄBlPsgԁRc+ìcoުBlRWa W /l,͕\,d)AIjO+ϱYwӪ[ J= 2-TO)s5)LyW WoSg-I07@_ȡyPzwO $3Nyd@C*`yYi^-ɂ26[+vY ̾MjzE1B:2]i5}: !x3]Pbsg]`ɢˤIO_b5^DK(8r=a1pHFfΛ,!=XqzT#B"kX`UA|Dld.vr<"߅g6Y"l%Cj;;4b+fS*:BڣAA?*׈1}C4;=zhx !#v+'i3ͼ2D+_4s2D5LBPM+ >ވxT}zfͶV[Z&y4ð5ˆMSuRv~ʢI&9tNK^+!g go1+kqaIdh[`X$Czy{ߓI \k_WLi~& :Ѷ/:-WL7t=F{C͋% ]~G*AQiQQ/Sj/*xq~\UpvC]GcWO}?f&FO| kbbmLjO =wNa?T*yD<f27/G8x9>.^ kgXVJh'*{=%^tdփXODhމKSMq09WmfƝmDVI4IݚQp5ZkwSBm4;lF[&C2s}䈘&K`ig߅7v1c@u7fsEsڛAg)QBȷɺ6YZ0YA #q3_*=<#nt_zG4\Ҥ檓f٨:(ƲӭQ!c TKȴ_=~OShg(C}-{1?Isy!&7`,( K?DuٌlBzrۄzCD$;IJ'A'Ưn`*%SD Iw2BdfSYH 3؄-{2mGKT(􆶝㐸Y$6V>U5u+bъ%ƽj|b[൜"-RE(GԬ{wPw/:a +`f`3GkM;CԊ SˍZk֏[G$M$PǥQ8 *@T|d1ߵP}37EE*GSZ6P8J6#;y֜=F{\T ;tkq~RR6sn33v*~k_lOd~ ?g7i||)"*7<ͷ}-ė+Rxv@ƙ߅%Zz%^ڄb0f;ML ga{^ v9鎪XZql#,Y̝Bx24endstream endobj 153 0 obj << /Filter /FlateDecode /Length1 1998 /Length2 13022 /Length3 0 /Length 14240 >> stream xڍPk %8wwwE/^KR({~?sd&ɵZZRkHX:d!,)I}N;;+;;' -6bVvr+yI!*NEw{WO.C'WA4l Pa(:9Ph]6< ``p1p- hr Aqdcd::Z22<& E t+ -@/   GWwGK+5;@KA r nW @ 'g7`dY!^f/Cӫ?]: +27?7 W3č lG¼YRqC>i+l>\;G'OG +_4,ݝt. ۼPȬA;;;yYذ@/+_g'g+ ?  *pp,9'd/z`/!qzY:9{1ٔ5UMJII'// %aov?ODG+'Hv?D<= ^FfPuzg^]_Q_V$no_?zy  qz-)@"hm6d^ Ku0_CSx nv;p,GsvYqpk8yx@WW7 q|9^lX .Wr+'WN&_&ؤ8lMzFQ/gAQ4(ZEkZ$`/~Ew:f`a_/lV`?zNpx5|Mh'+yog ū ?+?zD؜${}}CZ5+z*x\8^Ks| b G3^x:ᕋ?+?5?ku>Z wW{u~|@^ ' 0ۺ RO Ym4FeN)՟C~Han0\P<6 F%k?=&jNo,M N~9 G&c{r mVuqPǽ*U?P},ba[cW lNQpmy<-Ι,N b"B_ θy mNbb"rki:_ɽTEEߒxň"+rfNL w-epQ}`2̭x MZɑ}{."z'7'ʹϮbvcu$7a b]{{K3 I/Ky^_q ݹ䤜#RcQ)(j7!l*;Qh0Jc?}0^U-BVLw`6]Ö, AqpJԜZ5$q*TCK/Q$-Wŷ ӥ3Q-%-ʦNM<߫`VOO9ʹ zXǦ.Y xȅӴUFE\+TCS6C3E l{olGt=_ηPh~OmSe*dН1:U!kƀ7r-UPo-C.m=o&N7x9P,nS723,=֫>cROB3dG7\7[򅞄>0# ?Y?N[xx}*#a6]Q>Q=-י"9Zpo"@4OAw> ~a;W5SWxLr? Bڄ#Uh7FOVhpK p)j__VƏ2+{0aѯP굪 Ed+*6D\ fIXn>G3d)*KXMcCP8.a7dF?z6h?JTV(:7V4h-s'VP3t 21Zp pՌ #طJ8"%fl74ߨ u ӌX N-mT8V)_ 2{k<`"gQ d# JTTIKM(NnJS6wr9FIMXY>ʤ|ZG:g=N0U.4ir.]GCx~"ʵ6j@Ԡdl]l2nSa/$~5Q򞷍4@L>àwB]"I.%ςp>w|;.eT&Bśf,9c<<7 Uo[Hߑ59ݤ(=4 -dI__WD[s|d dB\1t( J`p(WشE)Ds}F!%Py֖uj~s:#w{H'0^ӀF&Wj3[]yw=X?,6E|P&7&> r{p T~1& duAk\Ě NK~IWYbٓfPtKuH\LLT5tE9DAdeYMdjB]LWQ/ux7آV9eB˜YW%Y$=P+BgLF(dDqTf3g=^O_ L a*1Lu(H3o$?Y) 2]UrPW~(Nr2@!m1yv^qh"@`ՙ=4MXN Mơ.C@Dy~]@%[we G5E'1aBxTm4cweT.*lYTؓ_kjߋ/~foX#ȸwRhR ;\u3knY҄/QɅ}MAcGF* ZKg:\Mxx"S= M60(*4!kplMT!`+Z<ZKA5/yOvv%*FnPe\ דmw"d:/X@I/~7TJ0)GcDX3*/)YqbUonTtY@/9hޱvmudzh!,kQzܙ,q7Z(E&i+" WxL<ĊEŨmCQ([]Zα@}tš3S殢oJ@}B: 3+?jr9;$P]J0(8| ⡏3l0Q< TZ-6 PNg%@.Y/Ԇ&ޥXɋw6]el ZZTQNvSL mkꋈܩ|YKXc&3V2t&; "KќHK}O+TYsr Iq>zZvJ usж#9% ('>#UzA*LJaCVTl\_nRz+EFXv5iw6S%w_x%lz4ejr|h~' ^tܾ\ǫ"-&ꆽhA38T9k5`n dC掮 5tTy5w7s!w75iJgގj*,/5>6g 4MݓTQzF=lE8=>|쓊+ҁLuQּ#[+"LJho0hb\8=[^|Ԥ/@h[øO#)#1-l?WFFf?in\E؊Hn3p%uXsyJ$4@*"]J-:r/l 4ԈXGGć5yӪ_@6-~7e Li۷FYc giU-l$:<n.h+E쎼ծ1ha֓8kc!C9-7@?۟NhMvXO՟d֝8&Wx@()5)-f: Qp3\f7W8iFޜ9*RI<HvD2n-g2Va?.nRl^2'Iïyuc™=h薙=UGG xkϧ\[i.d s cU sH ۘ}0quq.t n 5:Gq5NV͜p4?ș== 1:)cfUǵΑ9jw uq-o@!*URTݩ7f*-3c޼g56(<t݀K B~x0MQԨv[вㇲT+ p44 3Uja;*Xw*qE!98꺃 ܊rA3khU7JnIֆ_%{ gO@pkuU5hR.yEm{ѨrTКIiMq6_C sro=HË7K[հO9 VNA*L&i'l|mGNGآ3lwg#}P"~E\%D.YTu0ҜaQRT^&5q(:a TouvEuMuM*P.H}]RXՙ*R])Uk nz`DCFի^M5nN./!y;tLъI.-(L?QOت8X)9hʑWU6è˸S ',)xRŠ$5ElPU,H?t~QƮWX}6 yfCpOJ[yxxYMht'oA_TMØ^KPQ, *xt<ըdɧ.Ed)r1 ½񠰷Pӯ |}C>_S7 7i-̷ur}".ocfE0+@'`]{Ѧʟ[=Llx>,;]q,]pãct-h* dښ=x*G-S9n|QB}FB4XrǕdR靓рonVM 9,10=ed0V F*hw8+=aͅ$Spnm&Vu.1|)@g ?$+0pq1#"“9a%^!ޫ3*k2'~nUt J}Ɗ,K8i m}Ϩ~#wy-gDF:xk \ d 3<*͙ 3Bc oNp%S&lM5*hV('d֥I-KB+8Zzy=hm>WkBjH]MթF4^N[#A] ٌMXRڽ17YkBt#W}L?=y[ujP->ZݐH< Jy?IhĻk՗|i7˱(}B;' 'pͥ?>mk xNfT ۉ0I3$Kj SPrW2Jv^^,c;-vCԕG2V8^c|a&|1@_<~jo?"}1ŧS,#.y>W-쵒CbbX5{a@#[+J<]+HQ6lo(գJ4w'&:Uj h$7h!Lx>eˉVNxMn?)wT$cqDu* {0~DWܨJTU^.@ 8 cЀ mU̦erx|sU)@xu+mJ}aA?xOjhZWcثb{|ѕn8)F=Ag&7qDoAβZҺF"sƖs/=i&?ozrUuxJru_OwY\ '$R/qHR~R @K+C:M x{]vR>9}$$9%"0FQ?c2]l TPn)" bX6WZؼU'OUfO|i۾گύXS\9. Lj䜨%WaWxQn1OA!ca탥A:ݒF7s͚^P7,?x D I89:sĔRl)g9Td)b7TD괺I]37;nXUSvt<(*;U-tjX=d qfhu[!=e 5-UwxOdpٸ=?]>Gm9Pͤᙜgs\{H\c{=oȷb .>')N*2<]I`Hx^jn#?TqeJDNH e/SrӪuűE" v9PRn#7\&@#XӲ'UXp@s ^OxnJnqj}Gdo.xl%)G`tme4+*AUMIz$oq/IGzl8rbG+ j׉ɑcPd(ܪ<\[_HdX)$/GCOim# viX34j.McKoh4QF IPEli#G{[e:_3F5}"$7?`0eJҝw{6> |R09Z7!axHU:X]7Vi邸95Y*k&jHO5)#5Ãe^G/.[;$Q:,hn&׏UtVgiI} ;tvRM>IL(tڼقV[ B 0BAbPLyiҨ%s_#GIn)e0VaɚsFxAvbpmHZL|= #E;"1?UP@tU"r\͉Ї}F} 9%T_oZosdS#wHޔXT3$>Uψ$C<&>ˇTwNlYm1[ן^EZ fKKs?SŷPձTL-YZKn gN]+*%ؑ.,\"a*Rq֠m(4siRݸ1. ] .|ߔw] #l9x7wħ'ު4;%,^Q] Mky(׫P):"̅r]!ú5NUX?(#YE|Dƚ(\#]S8:j1gWƑ&иE trJ_Fܭ{Y-BTl1޷6ψژߴL ipVvcn(>2~46ï.9҂l6cG֙)U"2ThUbaKw!as7w2SWd^"q1W9xa}CqJRY{HW7|bgtu_>@6PNGz\{nCN&R;=?=. mjfUeM>QCπ$vC:87۶Arbt~U&Rԛ /}ӾN/ s"e^YF.F plw?K*>WMg1o,5 ?-8"MʝbojkU%ULݨ$2%lཱི v+0>7fHdS豯NFRt]yE%+Õ@X$\G]/ߍEP4>C)˗Zjޝ)y|(Ҕ{+Pj7f!`UÔ21cCfa?؄PfUvwfCGXp0QKbo".d|8sOU5MШ:gJǐw_+ۡ~Dd:H8Rtȥ$8ba &b9gg3thJi1XV$G{<)x*FObc4f`r]4Ǵ{(>$)wk̀Qu),e/ZRg??M_1qC1A7wvb]aJɂTrckZ,m>BZ2 rNfUJwO݆\gʆ?cQ_I4dŻUG X ]fG˶a<8|.=@rЭܫfȕ'A'N8F[W4)D5/Ϋ>b=m8{vkc=ίNtX%ߌ(W ^&VPSMn<6l&jO$yG"U*8^H2 jl;w vÜhg8\lR !LߣJ8XNѕ\3}Z\R|U5z iFEywxX=݉hЁL'g3{˯|8܍xK@Ꞵz]LU 3AO<]0ujA:<[ +KXBoi'մDvR%⨚KԼqWפ¯rh-5h#2P@Yx09ΆߋW9oӆeF@F 4T ':Y|gpOj(aSA@J}:99o=2>N)CPi "1/bZi BK2ĥžBm&_qxi4*=QN4Jܳ0ZQQE6\l!Ida9b:!vWi9(I=qJޒpհ'7FG OnYUpI)^f:|bjQw'W5l^BQonޯ[D @9M=`ȑ|IG-hOkm gaU(-sϡ`ȥBuDv+c(;؋QBwSRfC_myS+ ABCW 7gP-ոhdj<~PbkFw*ScBmGɯcmݪd,DTV6׹Q Vq){QuO=Z+ԙ@Ll,{-VQe6Cw3ʜYuaN''Ao2@QV4P'K0:hk=KBuBE @S4AzJb ňA{SNIQ}izRvH6a:ZđNSFT0*uJmInEkeQ䷳ۜj݀N|rcoc^ %/~MNv\Š5e;UpK71Oh?lDhu[ }4c }!5w鮢uJlOfTd[_蛹#r \+# %muϙR(u}=z֦qD{$oKdw4?+j*s j1OZJ J)*w )Htjє5h;ft$;10 ">L< vNBEi L1 *`>:Gi]y#ds-OވQLoio[141EgLTZGaf)j? ,eKOQ2e/CO|Swh5UHud]VIg V D] LΏǣzN" \k9w&R qdXpBZc9큛%$Hxx3QG1ӵc}MʲdL@--Z^USrJ8Jx*i;+u`G(nʸGljZY Ag+u$Fl4HKq8s30 BGS]<5H4mQas:{Up~nc3rshTz9rbBwoUn? ZnqkOxZBIfk1#8L|P#?-5 Wԟ6FxG׃z5.!y7JrglUaaza)c-ʃb{Οn/cx`'zD:_>3BQaA#)[7;\#p`mf`xП@&'i#t h fѤeZqĒGn=G` ꉀw~`&TC M"mTMSԙ({y 9\^"M}!EL0[7Ӝ\5{>1X;K,޸RL;{LPSqiCI zCR/5?W>\\_u/98=MFز:Bh2 O;& g }6g<1N8 sImT?هQ KK3>xA-[8TIe҈pAI)v X>]?LbVEroM?bRDJDNW +R"+ >˷ƾ]7ߎִe j4䋥Ww`"va CjLnz-wQ8TDGl/v@\vkC˚(44ˡRm;&B +c{N ]*IVx*N%H .꾠)~Ē:zJ݀ 0G2 ~:m l[HچKc8! 'WybU',I6wj4yiڬ/7,By\60 =/~Đmv۽8&c;4g c*e)LD4f7ͯW<CG.`'KBk_'wޕ2k$ePD3hn=MCt 6t{%8ڳ(=Ar L$@31g}@rr̹DM4x B0y㾠vs/ąwf^~h Nᧁ^\d}Ug`rD&qzEFV2ie}CUaj8[PВ`>*$f5wJ`[\fkLjKk?&נ&L Xx|%b_ 7 /vzSTE8P>EbNØ[/ ]J1$rMEmIgE\VHMuV ×G/ P,)|'-io .T}Z kZvwGH yٸ_T1dU[vngNֽCb8_kxLEA66iYs`gC:0-:q,S^O):lBsp!tHloK  z4;?ʸj8klTN ~~ЁvPWYSLa<:6$yQ&<\Z5PP 1Ұk@r h\f 7`X!#uvt3zxx˒g0cynyoɇ %ri]nN0hNj[W瘇'ju̗%{,}w21X~LL?^Tmы._Z:DihyRPtdO~Yo *FHƱ;єO˺`R wңfzܡ$njQ c_D哳/T4?t˕2$t郴LZMLJnnV?J*Q .ݷ v?ZpOl]KmC?dADkZG~e [1/ ՌVߠYFZ "\9M&5M [?uQG?TomETo[/;Pm767&Yxc:03F2AL^(H8lˎtD)=TQ@slcnO > stream xڌP]Ywwwww.=HpwពWuoQucX$j "掦@IG7Ff^* 3BBj/1H&nSptȺX,,\Vff:M< YG+<j3 {@ hb439Yݼ͉ӓޕRifP]?ħ,MAl;V7E3qtfvOw?fw8V5 N* _ honj/@9TB_o?ǿx;+_td&Xy;YeY _TMTߡ8@ovԠ;V9ޓv@udg[򲁸@e_}909?,l%[_{5faW3X@=3 ǿ2wƃt3Y5y:_@A=5^ oAPxAP|~nB3wP|W h8hjS~Eߓaw\`bW+wѥ Mmu[OC(+7K/G- 0*mO~FSm X'D0 8iBuR9s#){Ky}X U٫Cxfӈ.7͙!vc E;BAV53$coudžb`qFRRXDɎfл;(T'eErfі "VNt ʥ`Lm[~v*ߎ~rV?Hk'3Wk*_R.b">v&7w< ad!* \wxBœԣ@~0y7D_55鹹jXѷ1zAv??mdA]H5-y{i @(X#vIYp46W羌їvg+džy%4R: ٜ=&ucI7R_MZs8E+̋PƙG0L7}9vD"4jL{Xb"w9v|5#d PI1߅r.8&cSi9* Ϥi$v z(qUvܙ +3弓 NMDmsRj@eU¾g"V2ͮ⡒WV)%J࿯IrEDz5.}YZ*V3VqGd DErAu /%*9ch1/Pn6'ǔїcu+Yh+vjM|W+FႫUذ45"gjr7۹+B,? lJn'vjQY,NWǭ4T̥΍o<` Tl9k7\ mO \|{`a x s}p Q+\ *B<;cxe_)E,78"d$/vNJEDp=“צ (uv6P-Z .`bf2YY/NÙsH}ffjZucqy$2^jBgp+/:UX֯" fTq9yzlIrHԌ$c|6ZiIjubxNwHx%wN30EV9\4-Iكu}b\MTONZebaxb@(O9CXc[0]I[ň/`y3|ݿf%bK66_zNQiۣ@Ep.oJ@0<,TI,vTߚB $A:~X7Ε'xeIW1`J0ElCB0JVvOr;=YV3zհJKVXc]*n͍ C(Կ*q%ҩfg=й@?q-/[ЉP~Ӑ(8z= CoUGYp(yK+|γwy_{C5lMJ%pv=|>,u0|~d&|u"dmZïcBe"|H43ֽkt@t{SO߯.t!h3]o0L}`IĈc|`u1c; l:Y*3L֎fQ;uA5#ۡk j>xdOFg1>]BiT/S39UcUψ>m0Bnܹ"{KEx{]I8ao5vUpĩ9$Mђ)ޯ?KE~Wb,E4N&zͱxw)O:S}ϒ:qbơxS$%&rq͒ SMPf{,Yu9Xǀ2޻ƺ7cЦV,F_UԐPUĮQOzZehjF'&|5#qJ-;*-ȣn2Ep?u.0+]RQV{a;DRcְ҄ –-1r'}<)X;Y!MlL9RqJ ǫ,X|Kްw RFW jfaVeg[u\\ ;nvb,14xğB;1>,bjt,}D!p51JTOv3D!]&{'E9.0`MšItjnL-{@~u4`d$Uw$`2:e3q(̊%jDGe ԠYdW3VHz*V: \^M8 :Rs|D,ƋmcSNc!BO Aγ%7ءxbo1|㗁[H+d0TbVBj8/m'#_z.qr2M02D͢/]5-tY6f 1n{ ܨ#mxοQ>M)M?w290D^:R0i:v|_Brz̹;e`.I-fϚW2S)|H(< %X~ y%OqqggcD4Λ"HQ}NцP=l= [Oiᕏ!/ͪGY7/TAhTcj۽mv8\XunžV6~r0ʂo\d)yBvcEx݈:`cv4zw۳"'|,3>Sx0^0n㨄.)cj^Իw1uvtG抪IGvoBڬˤ3 ~^fL:5N'%Mr |/ʐv ZV-Ez+00x[d#}dQX=6DX-q\&Id)RQ-,ԙ2"!ȁ{ʽȮ6X%4T]rNz5nhYmhw#~ l7N4eZ[J\`W!<0)Eٟ*t]vl/xb+bQ Sԓef7D&|lB͵^\//-4[g{ r 8;Q'%P)˨ЭˣUzd.gǮ'yO$ϰ`Դ{Vhڬ6桃;-Z$śAM19x#D*6K`N]! ĩB}zgoڧ-lr'`Keyą@hPi'5FJ #ḳp g >i= Ε0c4.`ži,|rߑ̶], Q^/ɍY8ѓ=zyw܆v3 y8E8 ^B+aOe2|q{_~A =7ȢbξW,a\ _7q^yBlW,jK,%d?NY".ј5S5r~`p a4>~̆OR m[Y%,dFwKQwض"~,"o?aꎡi,2u=-9 3:6y;CĥOǧ8%O\F ߘ)2?bw<-ǎG;,ǀsUXmW9fFB*¤2Wv-щΎCBOQ[\RmAXnm ,$[5/q %|gh%yLgğSJ@h+8QЮRW}XYh}Odgځ!^ B͊X|XԞ]V^3z>( 3^J?R?ͻ|pb?6Gb7䷧ z ,ds7hT[JZEoYgf2bepL_s0?HoI>J?Ak抺وά 6;n7y5xs:Gi; (Գɉz+@[f`7Ɖ^b^4_wePxաN(шc Rp߽. N`13mL+R#/m&\6r,F6N9bRE#y+Y5T.֑e &Y,gZVGƊ:b+TRH$vK[M -)nA6|{9*cb[@nMS.Td13xl܃_ܳl L+L{A -Tq Oܝ:t٠n oðAh"4ÅTi O=ݐ1/*^3 buw/5c7O-QnPh->1,GNG[D?3hZ/CGb4Qg{IDv hzǕD>oZ#H$7U G9VFW<|3[X 1!pˋ}PL/ .yBv> 4e2&~mԥj8pBEEņX?2ƨ:hXvXikTy? s tn%d {)'-:#ﮨ3%@"%VE/@>4_X䵋nFdCհVrC3x#Ƞ!(wh#:bBJ"iEOU&&Tj4 ~SBS <;RHcɕF0 pCٍ$u4_28o4~8; ܱ)(=/,>D-lJN &k~t.YFDh߀Be<*I&urxX ^uO0Bt+BZP>:!CKK-SX.yUᠽn7P-*_lEX[J+ʨ2lEl)(3ܤ߽ &ƪ͙cW>L$sԨul_u:Fjy)ϣAe\Cҽ6,\?I)fӾ숗#xUE2>Hn=e }~)R=OEI-NRi^nsrbч׎KeҶM9Sp#b,iE\x@ב5 K ^On#DMuNa zٰi-:}сfτ464άq/W?U2%wUs[@V+M…A8U ߳^`k$~5-؞9M񻄝C;[U'WHF174)LA&eJvnd܉q5Gg>hL7BqL!$Dr,_EkC=(Ĺ^ &elu3WM\83vLl;XQfڔKF ()'uH }yL,wcY'?jqKczW)TMT!#"webF%ޗQEce[9PI뻛 {*c"hPdn,~Jg@u٭EX˽Y΂,fț,YOApc,z741Rܡe8ФR>$՞~ |}s$Oc8%e8-ڼW z^6655Z;KKlB^v=8`Ӻ՞|@\ĀD-~<|y>k8>%4t3%/'-v"1_ 1 yw0DMtEhnwb0j>F^$(~m-XCjTk`9 SSxb qKO`vJ  ҚkSHfB2#hFsad+W(r"\' HÒ_J%l~֍V`DDT+o5?I>`Z]`ڋPrԦU iI/Pu~8x8~7tO /1wkb;?C,E ,pVKH463QBw,u/u}18f5/%?o -+"P_ڦy3GdX"9]бu=/ Ig%ouZac hQ SZn^y`|h7ּTtdsP|*I .HS~j{n_G30emV64'h}%ΎNfC_ޅ\ǕbIK;%j 3 &Xڊ{@34I7B';e֥bWkJ_CQtpRԢ$yo[|(T1-X~"V( dp.tӚ1P!<1;=a|yO؄ ODn ֫xi,rnWz2/ȃ G牡G[UH"iZsR3sfN1:F_$LsEi^밒t- C皸b BvCP&gnGDI9+ӪVXI+*B1Bicx Rt毫3=O]|].r&qlL!4%4܉+GE(\Ⱥ I={C}OUE;[*c *4_iw' R8\0B`LP{V A*֝ޚL8ңWF)2(~z!7 |%%8 &}\c2Mʟ龞&%Q`@k5{8H=NtSumsE gb<Fh->r~ hI?d=1kP7;g6:eN WAФ*bT\]KsY@_;6ףrCmbitҔoWw;@h8{omC < 6kBm<}2UIZS:,~GP\;h91$+џD₩_ "='έH|\QM*Hqpa_fpYYmIO{N38"-N-map_-B*_Mٖ,LKOd10xNCӬXtĘ$|6EBN%L$V_=%,yzTeWWY>2 Dѧ0K6"L #r3w`Î4|2n9׮hxpFEP>t 4-:9<;ꇺP;^DûAhKY6Nfvj/};vCҍIt+RXF!(i QwEyxb(5m Q#o¨nlagw}7<}㩹]G\un *)u;Ēm7"1Fʶ#OUa#93E-_~ټ+pEڲIɶzzXŔO䯂<TO6D`|DqH{O oA?L`!ևrGlɥ&,FB\di- RANm!STOz):ޠe$~? m0C] ymA5|o~}!j(>8eĆr>R? YrٺϋM༗){L8P`;;љY0"=Gcv8/^T<=$$(4{'Lr?:Al*Ign?\m83wؖe(= W+y7I#$^|7OVqĴArĄ/upYDR~" yATznyH1YfF#U' _J-pm\sǂ]}$ ,0QK1_M 5nIIE&;%*ɵX]>A8{2g?͸.)r4ɪO-1<-+{JNR և8͇܄Mh3'=Ycdsi~.tqe,|DPۭ̪Kg%Zu^']LƘO^B1a$:~ YD'ǹB,33_l}K?% +$BK9ѵ,q Fmx#WM1yg#_U:84bGk?Yޗ*- IE ]2B֧j@nMN==h rkRPy+ݭ'$4\ )r@6ff5`W\It9Jeyϣ]Oכ#`Κ`.8{_KM `Q~HZJf#SH܉3/O\A㴏y LK:}]ă/]-= w֊.&ob3['ՉyΐRYAԲZfNٰf% .KfQeOZJ9%F~ m+ Yx{P|b<G)ccr­ U͂U FzXbSH-SeX3p@ 6%J.idzC쎒6rʪvIVO(H]r)~^7l$OW׫)ԋ-D6D{A!UO+xlYf+?Gd]c ytTR*E êF`-c!\oRs@% \\SnQAr9_ @H} GZN=ϻXX*wx`^8/h)M*{ p|G)h26عɞ8 ֧BK ;J*i3Y[Hheoզᴺ޸8m%ΒB/9+CpMK!fk{ђ(Gξm]֍3f,Fͽx)gO:$iCg,溓&ʞ1\D=`C [,O\É+=RA6j{b"ʊq0DȆB{XfkөkU3HR5 &t,!?=lj,1;hfM±LǭeX'4rI+JF%eR&txY9ׁ6) H2!K>dC6$[thp庠,YG?=_lkz< a`2b0S+YJJ\fM~?衲* g6&z2AB.\)əS`,CS',{ %Ebp33hʒcOǻuH`v ߤ̾$1x-x,kZ!)x}JH~/IǃH^퇦e*j&x9L؟A8^&OUj9v%*Wyq0.ԃv`Q:HBR/lKVPC_<()B D Νն.04(C.v"ʩtIzzٳρ(.S U#iZןe+;J XQZ"m̘oh%\T,RCOg™mQ+hpxSTd>za=%AuXBʧ`"pW*L;Y|vk(}]9zAz%\+@)js8>nDg)Al[_a-~E'ؽOr(3;y|j7ƊSxthm8*ju}NVR秬SǤbI~$˛a@wi1=j@T#:'^ty,fխ͐Oї"Kt!N1n?O&^ؓjݬL+rNSQc?>Y`Fau)3|ܙ#I8$4d}_bŽw[`e V'eTE5w8g )xfSsB)bEdVd 6GH!2 ;:Px˱=cO'J>Rb=-%܉ u ?lgύ$ [{}2nT0x7}p[qs V5z{iUFm9|3E`AtND2fn&H=gŌ;6 :|YرƊޱ Ӎ+D"RENk0.| Ҽׅ=} ݚPtpX^$-/a/!vR>&w%5& 4.~J6hR-5r/И?/ 2A kBSjMl#o(i2ݲ{Ta~n=ԧS~{>KH.9qp4HoZ,@ǻR9A'Ux.`"£eP`,u\j0($:u.L_:}zH8NUeNy3WgvXo_=rKb5 Ӹ*2%OJ%v+`UThiiϴ\Q$6)IXpsO+{R TWe Q0ypwLEG3m49P[rom v+' q#q FrGk4¢P[L! ~˛%#╪/VUgl-xM޷f K}x P|GYV$P`дG񩵮ECJ  nz$+Jy6ͬ{ $x7&8JPnz;51~Ӎ'/0Uo-v;:w!MW赗33NsٛOk:He&H8ZA Ɋx?&:E߰1g c߲A!3&{Y6DՍWTZ~f37]y~~6g#{l6x1Ae W:%D=΋*D⽷x@Ϟfcc[E^HPzK|a^88!1 yl#Թ!aW5Q )5nIO{d+_Op/ <=4˹-ʓ-E&>t#`yWEsHh^ӧOYjP+?L!=bŁ82[C+з0$Xhh퀨ZM+wlƐnu9CRFbo b[UvWNnbMsO4;ݑSSAYvlO򖩻}&kWdvhh#W/#[x:>@>9O%0_nZ{+ջeW2PĮ&1GwV>AYnœ>T e.>6%TYuȳV a+!dqSl]ɤ[GZ$lJ@T/ceqaތ\>!qs\D1 _yfU׆Y^Ke )c ?,bXq~JO5Ar;2>3ͦ}6w3pP̩s CmtDgAQtK6Kik׈W0p%*mJ@^TW>hꦲ|7u/-&6.aR;Ek 8 f]QźSƈ^i >jj啣Z"WXٌvx5_Sw-# 㪳S׋G~oU,rz_Q{VB?O/ccZdӁ]S&.U_׻`~Ne +-d/eըjr[āI)D:BDUwJ~y_q?Q"YKNJdۨkX@R˜ ?ߟZuYo#=C3ٔlW{Llkx>ך@ZcEbOWTacJxgg77&߃C%9ËnRYk!|Ҝޞz ɹ巈kPS"v 7}"4%i$mV ?ܼeGG WU#~e{G+z`'`1Lyx' s s|ꐽ'2ȒN\QKLn\/yMn$bHynYx \EÿVg5ݖܩd Z.,\of|}>r3J- RJgÍ]HnY-Ώ]h. 1NZmEź&݌&GGmw`4wK= Ͻ"uה0(ٗ0\L:m1RA8.e?'t-UbfET{,nn$Qb]%FײgY^Fng"ٜ閎'1&:$/Vp2dXEHB]5"- \߯ ~@E$.HaϖlZ]ؐrp=GǷآX}l}0Ǯ-1q! zVzrvՠ~bc2WӢ>Wpϫʢ.|Sk)|c={rE5&hNtvT Vcuxz6%ʖ~zAT\i2%c߅}{n:/?Fa> ޚ RӇ&[P~譹kUx7I>m$=g[k8B8U䙙Lҭmy# o/%5 'ͳ/-n-EHtqC6p[XojY%v,E~b8*iBi?G߳F괽K r# XSwu-n>JT[٠ԮQgϏltz:$;)c_={%N£[PtV xPoZi\,d[6C\ڄZD+o9۬L_U^1䛺g2Gǿ6Gv ̟!̩",kP7OKY0bDYv\̳:-99\ L|Z[+9aUK u dX8Շ;͔s׭";TL_a54?)|iY mɽ:.Y]j(Cpy mMi}@e.͆glyGuq"*9Yx?8/RF4mN$=Ì[@q>@XNxRP=TS히;8!ՌѮ|)hO0T9!T[PƂTC%“)ړ^qeb;fx5s࿧>VJ# EN-Lk,e@hg!JV4`ՂlيOnOYрW#!>A2jDo,0H . zJp|o劑o/T9߮S!Xӷ#<M0DFbiGc4"B":J!gP[8")0I'L{@"rğda;䐫{e: R骙&#@!Z&_b= 6`RCŽj噦-$m$O"~6aصْ}+ zlj]ބ╽e*F $1n5_ <֐1z0l:>f.z3]_ ή1Jg]WcV#^\m.ՌE_ETRe:R2Wy xdTJ ξ w|NV2qendstream endobj 155 0 obj << /Filter /FlateDecode /Length1 1814 /Length2 12167 /Length3 0 /Length 13306 >> stream xڍP \CpI;!8 0  8 w ,'\ޚ~VwzR]Eba,)-ev;;+;;':-6fVuAbHAfg왨]\^A>Avv'; @d Pa(B@gtZ)dm{GC@Os 0T`6@f-60 3+j- pl@g h dXi6 Z+x؃,`g% xRP9"0>+m#Oc3 X5YeV;`hf y7s5ٛ?L +0{- G33p|2`K) sF#?ih|l7 q{YVaȦ9~ ta##O%>x9BVe??^f@ o"t%0ZxٟǏOFf {Cl*L_$ `apppr>Sn;yT[A|z)ɠ{mA<@?ony 47xz?z3ߌyv= yCkU U=yYXyeA@KuQO/C؃@u3ktϛga|8?wOy7 br̠P3xF</U96V0lx. E<6?D!~'MTT .;lgzgYqs?Y r؀am]Y|N_97/W| |/ ` >u||'[@7<^@;}nb!h[zS%ڍek%ަ 뎆WnķU΢F;}Bv;pA¹V$+ fQ\gemS.5IfۥTƞۦrCVLpb~~.L6 jvsx2ٽԞANXJ)J NzCZbB ǙuƢCn_a )TU ?&nv4BDUy!$hz3jDq-FdPA0P>2>"R^J6FT1NGA3Sqh?%31"{nj #J-TmH Ⴇb>~h5dYl 8fX\BLꎅߤq :qg՘W`ԉ_ c2s{yEhrs0X1x;i}ȱ Q.iWQNŞ \ܗ[|#cGAn-;zPRrW}_)D1YFX}%UK:5xsM*aD#\:*"!x0g̹_b _bdMHgHލzԴi/VЇ'DEVIꛛvKA[D:}Z mYz-p]FORŠK#?"+n~|r!w{2K3n-V$ Q%`Y |6&n{k+j͟10Z;t=H1M%`4"+Չ3᧫>nh7G^FR͈SOAJ)8wڊVځۓrJTz% tS*tJ;sr*/U6X! HvܐEl$7LC~u}s7 ~h*EgcdD@%w>p> 5BqXv,Fvn `?Gةj&Jb<4coRq>¹ҍB.lI0׵^|=A,+g^y?ݕ?AZ^etn#)ϡ]uTtbo4JߘCQo>+/>AD4QNDv'вi8c|ԝmi:SjBiFD:fE.G.i6U9n8 lz_me!DeY#m!mxȴؕيNWrVРcܯo&j,*?Hy5C񔪱3Oˎ!h{+յM׻l"nу̫V|l!Mrvq"!NA>AoIѮn,oӝeHGtbi=:pD!25`%܎mdN3#zrKAD#y%䱼jLukC$zZhIbTs\0qm.欂4ceSȤ(yO5!|i$YTH~OneT-,et׷ 3nR1Wg=^3%cV@ioo2:0˘r5qJTD}IE~xa `C"?Zmm YejZ)UkSp(u2#>0OJjhq VҀX٠_ | ׳-ju?ct"7 og~/'qy+kqG[4J.%1d r=HGBV؎~@1;Y`n^!F2*}VRPibgW̛*Xs%b;W0"*&2պ$MՎ,݉O\V[)r܃_@.JdK'ķUdwID<0Y$y -3nU@=((աѦaGZ%Q~.v>a?-߾kkv"IOUWs+iF,N:56{-Yfun[ŽrVRBiѡ߰{*$>i-Vw݌?;inG0+l&iPVwJ^e2ٶRH<& ߜHzPnm:-x?YDn%_x-)~o%.U޵&%В_n3!\@0blU8 X9~Ti|!p1unG ݇Z9׋$$bΨUuAO;"d."4&«3bTacy!p4(\;oEL%|L'Mw(6swY>S;kgjLaZ2{qg2|[1solIƹG_Ϟ__=H%pD ,SrDN ߎ՛,G-ͫ,scZnw0:>_hjƣh ?l ~):QF ljGkOZ$jR}xi3k&In!VJG?XN&$E:"K{5U}m7tqwN2|M!tO"%ͺՉb5tK&q:+l/KT& &S2nX`%6VxLo'IЊsVl\ SIYk_tzٿta*p\)ʀu-(Wi=?)pF]PJ: ݽSKs,Ede/iIũi=& ZtWx0=Y"20S%|1W.fHhYd2bQU.zxxl`ʸT0~*P70Rba2Άњyۀ#>E&;+-}6r~grV Lʊ9^ܑaΡ֝)(|#D-f6ylLx`!Xv!N o*.$!D czx;@J>@,d'cDtR:۴}fC=hzN]8Ik^3jktxQVlOXכyBtał~(/<x^+` O>e^ qCtalP: "ce^8EjfNAH&o"7d`9Iqx|Jv1 QX_VϮrE؏Cm!Uѯ+v?ʞ;X>{}p]M!=db0qt(a=WT?ms7-\|"F~NHw¥rYR$W,'%7g9zvrkK$(ujWz bXW)%ݧjd=T%Yˏm!~J9 ƪiHu1jM[m3EFسN曵Y7xhİ %rp%|!|*l.ѓГq`ѥ}bǸc]c6+iHBTs Ux*aхtyĦ|1qrLCmE&}mj79y^ѾU4gq, .076fWrcUuc :6Pۣ8_Z=z2+T>O<};r .A[@S|WHsI }pۛ}]u48(i8'%6N'ҳe]xNAKaIk,w* H`?Ȉerg R7.=q!rN;:lIJ7SJp-^9>S˱0 J$c^Td㧋-h(> yxCd[a6ÎZ4p% Y/ߪo;j! aS[1wYec%Fգ>}1+?ԗ숪}N V3B.tc(_8KVwokS/h6Vux\/2$n"U]vfx!~No(2xm k0܀v Z3:JUWE8ctsozFEmxl܏Hdi9}EO q t~K10~n!F3EHP!AJkF!zzuL&.yOiRB&=0DJ;|#oCe7_V9;  jBl̽δ>R!a_[C>610ٹx1ˆ /8UIpGs9{P]7'ɲ.z[U&,N%| 6,ZQ 5,3m`\@TRxi7]Z#Fo<,VZ?Ybێy2=qO2J985.P'_};k;+sz˼,mmrhekI)Àqaj<ğ̲DɆ䯼Ċj^faG)ٶ#dce8l/jk^"qk׈:k8)]?췃OPt_7xUL@iv,$ Plw5Zij Oh|r]`a=C ]+cn.ZԘX}o:as>1 "c,H_d՜L :r#[aWi~zBjrC21ؖ 3l!:Q-. PUj84sʪH+6'}[č&*ی7^w_-dX~֜@:{N&3FPgrxM]Q\X>nణK0e'`$+aݸggHgY sHjJZd+@& S^i%VQ[X>}@vbIػ4n[g-P[Dk(T )56GB۸F~@|cXvAajWA^_%׾mBC:{]b-xCEÔ_"y1/Gbxb^A9MƴH Kh_a."F-_چU[IM[_SOP=Y{>sd3ͣ+`Aծ{.d_37Xv^7~ )skĚ|f);UOe<JG@wtZu˅7'%)菫p`&,*7jk%1*c~Bcoiybt43e2՟{j탑KpHBt */3v40 pfQl46],gw@]?DxLՁc!YF$'-oO:wK>[)kLNf ͲZD&e0+K>hB=}JlU}LlS4W.S2ܟW d~s`]Ayr?p=\ҔsuKW;bE噜 %x֪r|󙙨̃>9{AS 1TQ=m%IKGjjc0VaZ׼>吖\QRyr>𰚫j4L3Muc˷O0A2jYrJ)ա++e]e4>)7|λjDl'Qo2]>Rxm]Fr,/ЫqL+XBqӹFE4UBxd_Ͼgq2myn,&e K,иHPyDj~ RlIeޢaH,>8+[btd}6w5W3f]Q!syUJœ_wBxXUgRTS4$5Y+@|gtWG^H_{}ו4[QC6untZᢲ^%?"aBB6f3YN5'5CYјpp?F@viQ< Y:E8aTv.c| _ևNr,$ 1ss*u+B{!T&/E(_%o";JCYABQ==ӏw6響c^$Ǎv-af˷b`ISdR28mտ KIF ]6T:\c6࢛CqaI'FrpF j&YQXL?jG:\ |r=JncNC]\t*ʺnl dȫ=HQ5rM+!M 7#.3r#`AyAPF %on]*8gGm;41~>ݑZ #S #)+,Bԑ!c"ozۛRڷ)e_JE3ݼi:O Yؙv!5z>#p՘ k.ZԸZ b %63yOw=ns;/m{c1vD C~1]mfC4%5*|^K59,ٜd)#ˡ:._mlEV r=lojx0`$a+Q4~q Hł=*ݔZ7~WtCM:x&:ME-RaA%V{Ndw|mbrdkjn>mڞZYjVz>TڍyU(CJHnfRYcD9Lm` 4/7%K6&U0^I/Lbh{?Sk3>Rʧ~X#c٥ȹn /59oO~qT8}0'E$#INϯ3US *s~_2ۀh&^xI&;̄O>R7 {Ŝ⣀xl,k׏GV|sCҗ$@t_DVI%<J""d~nd?L$CS,A;]1nyݣlz$+_|1uB& w=.32{Mg3ߵa:/%Wk0}iQO&ths)wVhO|1ыMY~ЕKuQ1N71cQx+q~"d&{;CS*n;-p18C]2 TMtk3ԇD&¯*/M:O!VB܄*x$ܯq56vVlS5(Z琾fiWq+UNd2a>ȭ{NW5z@ a'.]~-@Sɱ}PHI%cX>gyn5ܭu"%У8WCd $o:xZj[SYߟ=lO?ískF==Yo72A>wScL3}7b,U)JGsrnB|F9vP|N*. -`vso?eAm9ɠg],)5¢M筀q}]AAӋ@bѩwE,rBJ$dnyBTM~qd[*ڼTЩ\5TGF.o3L:?3q|[z.yF]h V=2wg]&*%)BR;e)?K3#M*ǬROEpeLJ*x ҆G |b5C9a] Kh4߸;^.dGM?tBQfŢ0E{ɠA 6j1= nDs%'/.ͱ}48|;NU$B_`Å2e &ILozh[f"&>Gww,x׵*7*@(rNO>/8/'xD0W7iz>{*G\XJ㺦dc V:8=J+ ˓E"Ns9:r3̐&wdʸo~{:/in03%(P8~[zbRp}h brUՂ5h|BàQJ d [0c:YͧϫKϗe8[ŲELӬ8bЗ)Imza>K!\VPl;sm7a}9wrD+f,jR SovD]+qt`WkbbUnc1yt ;Y𖲖O%zob-^ؿuD@O i膌!Ϸ0yiR@$Tc.eK46`Ѕy;4KР9kG(q'cSWat(-4ZH̄|9Y)I?Vn9endstream endobj 156 0 obj << /Filter /FlateDecode /Length1 2378 /Length2 14578 /Length3 0 /Length 15988 >> stream xڍeT\-Ӹ\6]C !@pu=}?1{V*UP"adurp T(kiqٹX9hhlA?$l\f L 6Uqr(8|Nvv: 濎$f3 6 '(3d]=eTNJDвuꍓ m-nC@W8>2@c0񏻿Ovda3 'g3Go[Gk=& 1-ٻ9ϛyڛ J +0wn 7V7[Uv&ZRrC+̼7?-~[:ZZ.ݙM XGf x^6lhy;RruvrXKZ?Hnf@o"$`uD,Z `B?sfhFʪ2S?jII'// '; (oIlN_L+{<FPu5@g y-_ϻבa do`K^TVZں;ZxY$"Rda@u'7MG@wK ܴT@oTG 'ߛ 0su5Fb'@+X9"n-/M/`8lM)A6?؋lZ8[YZغZ;#[gd/+qs3?j?lld%ܿ%6 8|rO;xLǟ?jp `g৔= G?w?b0O8ۻ+[sOܸ;X/9=84wy:?דTS;G'2#诋|uH sNBavua5Ğ,;c\=ڷH[PU ޕsJۈ~1VH"|' %MtZ/*r@?qC> ご3[}QQ7N{.jpdEUjs x!jp3v!Ȋ]MtMwUXs<3rHssb2>.G%No1t{WŃw T"|xm1%Ҳs'7 jΞ3as(vVG6 >y|eGAglFLv`> E(PGJƌ[ȇK|m>&}#I!lj?h i HKQbȌ &=mdfXDr4A=1 #e+unhVТw༻rwD$2=Ɇ@2q.*—6jd y=™BNjiE`U~TfJߴtIð}f<=3JHCrޭ_:3匏b!$kg۝笝ҚY(Y;ص'*p' \/4'64A:G c)N|_b9|ζInhpZ$TXь5Nڭy}3N5*u#a(V}+(7S(('7*:^e-d|.AG)aPB Sq[PT>b_ѿYEֲW ȱT+%5WߙjX&lJk;IXKy7BITU[UÈM,O'(쫺-0fƓprbEu3 B(7=f8[[".֋wDy>ݜY'u1 lO W  q֞& _%Du:SeKŴE"ѻ`. R,9t)rPa;W;/^4ld-ezfP-r3 OH0@@&xO|PNg%2{V^xF_nM.ysFQA(C3WUY_^dd/w|T$ ]b ­H?o0rzҝTX Sr޹$*[5d)=;3CeNma9 A0(xmS=ytzMIr&ݐ.m#&Tg%~AD;{-8H>y 0o':M>k:8۟6C_+RYOJN->ItS L~|~Ea@+8cQs;40P&˨I8aTg cF,ݞ.wO.5GG]֥_A(p2^bjv/O'RF gײ\}tH6}BZ&kR,A@F%/*l.kF,S3w'(-kG+YaF%*']wjQ-ͨʃ2~F2ejc̚86ٝ(jw14nBY DyQ=0jQ"{yݫ[xѻ[y¼"67iTm2;L뛙!f6_XҠO]>&h鋎ݭ:qBfbl?nXПf!<}) PԎ*:l (C)vZV,lDxh¤czﮊA[XZx#\ivBxWg'r^m 1o3'7J2uM^Z g׾6L07 8͋$ %nr~kOLln" 2Mz SVrbty?pM_p d-q '@c6&xCI\7.@uE ~& tmHɔYRt:zL+(N#ۺlMZ衛=c=jO>rShv >f؉pi ٲs>icK*倇ͺb'7\=MFAɑӕF۸a3{4^~dr x^e{߸Y x MmYq`|sg4φ&XroB[јMG+:m d^c mޚЙW|J*zB=8Ν/GZ]e^y"t[ݒ˄MP3bF`wWT85gBȇ{oMŇ*zgh2rZDƤ"K;:uz7ؠJot2S',D{fgU^/El20knȃf׺UW:< 3_]OęS $XE2 (0\~9[bZÃGăqо+ڤ7_\l SFO0DS ~y+:jf|& LkTEM3Հ2"zz2PANO* z*3 }Pl(<8Vaky[a-fi ?EVy *)Hv×^vs=&G|J[X9i"&ܖPxKۮe{=f<Ҫ70FFOt_/D[Q`D ~#c p Gir:S `7,!ip^轗7sŔ7PB귔aٌ_0@V,&~q>EagJA4J]tJgKyq"{4ίVÅe:jo]w,K_p"Yg` ~a me=۽?)4%qa98T|m%C[;A&?ΒlM]6 (kt媹(٩vq|ZG,oiN2#"dưxwe5uLyJ!ňrbz3s b(K\Uݞa_y@8ٹA@/i5V#T`>KT*ԐK>L˘TپT7vNG QNo<}"J3T 0zg+kB6kiÄ́qȯ'N|?ڗܜ׺i}~Cbl1]\E3zRH$5ʙu~e4.8ae0*IS"@4X̪a$zu&/ ό%Jz]0By(;]Iػg%W6ƻЫhtB Ea6AS?#YT?#%g 2١Z1ZH@234Ez~rmZMnD$K f~ &R>QTdܥw@X—P1𡙫$|\2&K}$6Ɠ7AA} k, )\8>@1J+kxD|B`a2@W y,˨m_b<[oLK""*B9QrpLW]gs=E9zmϷgTŞ8%zUUK:4.6:RB!mI(9deGwF"~y z?H^`* Rc.$XNhPۜ3;̿y9?sv;ӪbsSrqKU,c6 "ÅB*4,k$!vaug ̰j9ݡb.rF,kXtsd G#/!DRIIVc?Ҿ:s=m2t@fj(eȱfr\fgNX(xђ얌P-oq? s@op* xB#ǻz%޸qz%M&PP]`q'J P…4+6_VMbh9fԉF#y&%L $-O7c wB@/07-W픔ޜ 3ALt#kO^q9'`ڱɬ Hs:ZiR3Nxu;5>}yPdU/=0F|fMoA nN'3죇c@'a#0l'WnlUľSx$l"̈́ٵEl?䭬|kZ8^nݺd79` 9Xhn'ˏm"w.^ᗻy|=(7J0$vqJ~ DH1Jc N][N\Ay;#xSE{$vY;*Kye dL{LËoG&Ҥw]ôZzQg$4)uƽ\$SՎ-bI\`1;@22 N5&JBU S[5rli&f7] /'MA(O:RBdfuw$h_3mGVޜsdxG(f+髡IѬ( &}Ȕ /F@GkqP&' ;O5/S'1#Ii"NIN|Y*akbE!Gu=4Ye(zK[NęBKvAw0;;(ZסMvØ>V>O)/,xVT n,qIvFEo."eEv=>*) $W#I0b9jr|k\ PBBL.X7G˃(/> "K C|B]Azğ uU=Jhm^ XfYģ"ʯ2 hhՇ%]3;e/O·_R?j?FT}H>N]tNplE4Q7vɁ'YSܶ]M۽{؄F틅i9UKBR9CPZu˭Wp\mBPˋ7)!-vsCLKY hMQ! :&r8W)qV딕&ʺXYZk5dWq8f 8 j.f(ih7 `{mcFp6uMRnh?P&YDl#\ hV& U{E22?b^vNCѾ~|K0=?DTdP 'c5g C{I1|4ᓡ fLrF%|$=Yn`i(V0QV TQMJ7<"{p+m_(:)( ;do#bx2)ӽ} 4wZ G .< o4:)li|1 ^ͷ֤v6 wElړ4sVq: 6'^'%\ӗvq/1Z틉b?Ce +&v~"L\Ɖiv?uJzs]Jwrj>dd~1ir=w$"2[>;rV>338\k;#/OR[cR1 i/򡔟mD6xcdjxgA%\}צxv~DX[)ve E lgQ!GZ>SUFLFj0p'>U~1ŀTMOra~uƧ%"㞓E: /'\gYW1$b:m#%g){zvMgNKV)~>U8~y=6^i>~4*Uvr774i0 3ach[sѕ#ç=^d_)63Ksjp:}![q2pkh@+%_Xϳrh[vzس!k Lu@7Oo5P#ZTjcʫmm|=+Nxt۷3d.̾\8lج<6'C&Gko5_DS/uRDd κC'񯃐Gw"-h#句blK:t`ը`,,FH;Z-hw-" {^Hh. Ii3jQNJ -4YL"nlaՊ$IJ6=R'ahfv ldWH] !m*[Dϓ(y\|\FV~z PkBkJY\MvyU3| 7h|sjƐ:U=4\?Ġ\א{qW!I_Oe?B@lX޵7=PU=+pog=rZF5\[G0y^V"! 29yVO1xr<;1w5q.nm#_l%j0[ݘ0DŽIYY:Ss Mуrˏ',[jEoYp) 0zN=Xt:EҞUKI#odrS;`SBJw4FH= 6oKO77|]XjwpASR8 &U#ypcrXRƠzlC>DCM/#f/Hv=Y|A+5+l,V>3 }e@~BǻNɿbE+j&̇D츙H@;,Bjވ<jLt.4<3;kl13dDx ߀ќRNS B.&Hۢ&vȳzg: sO7'| E{18k5½Qhվ9x<$ Wl 觰m?4 ߅Œ{G)4LxM0n_ J~$~c=%OH,tf0+ih9 4sD͎1͉+jpHu‡<Cg{y`amyTKxfeB+ǹ6kl Ժoޅj Z/0ңze숫]m]c#ӎI[)2 ֶb4E. !ЗM,:5@Z^g c> ZI  h[!P[KS/-1oX)I XTd2(!xQƚē2^t )oʡ VeƑ1c̓7IRJ D;PҎJW"Q7A͒V矾{z鋘a4ީ>i}7ۤ vqN>d~Ҟ{]~ UTl7n?}cw6rϹ)aҮ*֐̽.A7òcKI-$Se7-44ck{BD?nCU{lS7*j`Yg͗_*U|詁ǥxC_?bBJafteRZf>6I >j#trgP bPׇyc"sWFo/E`&U B/>TȖB=cxE5ӑHTEE89]4Zǐ_+"Y#c2Tܞ5.iuI?+Q W+N 6-/&MДVV =.\GFрGWh7BZKNye~HIţntuw_/D1Z`?!]|0å-`+IWۮy-O•ֽKRUFG%_"/~$=Rמ~BT-GbR:S~Ig567I^~.éH <̌&1REvUlڭ_ [ȍ/b:%]0 zoT_$o#(c2|;[1~Eg[Dw}Y56({EYo=}Y Q\UьJ3Jw虈q>ҎQX_bE>߳WGZ:Џ]W2:^o6(jBs#MH^]-]k/zބ9~弌+a?*S,KH +{rF\BXd.y^h7BSM wm.7/x˸k"{;@7'w<,;7xg&9  c %*&rG6gǭg%n31"Ԥk%02ꆒ^0|(,r4'S^W$+6pK(v72W"(,WROE$uyHwE'gϢ*LEe h nuxH R_FKZڣSue\ki@9J1K$E즷] 1`J(*|MR.L6oBUR-[fKNiĬGIA>Eaޓ\[Ma_֌`-õZlC~iR K֌mo0GJԊPB 4_ A $Y$C NJ5PqUn[ `ɆZŤ3o͹)*d؝,s Pm5&^8=[K?&҇y0SK^ ip%Z,yퟲT4gܳ;V> ۭ[sk?!7mf8a0F/!څO6biW+at^!`[!PpkU9s8ee4:#=]%"`KD *]9r$'8rk?,ap}̙+_1<"nv6!SY9qޭH#<_͂wՆcd:&`,uM^t9eP-JfŜk)kFmHz|0uЈڴZm]2*BgOA^b =#U9l PD<8nӐT»ː j)nZD=-R,RYBxk]kFhuAI̴R;ȕv^%s]~|;Motr7Gge8jE$5)OEqtRxWflVb+ Qβz1Gz؋ț =h`vBK+MB uN"J +S԰~^q-|/^(mĢ`v1\PkC[_i l1||*(efS~Yc0mq,5)j rlbw+d(8WMiA9B(2 i7$Y&yƨle|M?1GCjSEsfx*vY)#2R!z~ne`l˨&9NI#췗i@dUu% "Z9#)v>!XOqhX 45(RUnUFլy!#,)/fU7-щ}s,Od O"״g\+Zn(j |ϲ ys2 2z6z>Q UyίVg;txj 9Q4C;r7xgIw:N1P9 /PICRGKߪ;lhfZLcHBj:TUfRk]ЀϠ6y UWRXi'JGZ~koW+|lEsd*?sHvŠCi!尷cQ:D͝ᆫ";W,[/)[(ݳF 07 T;XEpODPnPvא4QV(YgHC94뤄ֈ3̥[*55 CHBaa8 "PÊ=%HtyRtqiΣf9?R[[Ad3J7fj ;݋ )GK>ևŷQU̺x6b->Qҿ. (DvBsspv oҎaΰXy#?y#@)ƛqgް"Vs+Ds?fmS{ IqDqڇ}*k߷d\ P=Xm:?\!|< 2:$-7ȸQ.74}tLvŜp)3gл5oԡᇣ\~H7#,Uo`AI2[%*ghTVOz>\(`UQqYVc %}ClrL*QnK/syLi-lCGkEͻWɋ3"Yj$0̉ѯ7}Q?8RHb}(\a UK(; DFzA^u7r刟ـPߑK'#Nl>GP?ЎQ$˧zkHupW.R'gz0JWNQ=64.|=a̙]d kO+B L/ץ[RdБ]gMT}\FP1Z8ݰBXMưQc}eA2h جJƐ&_0~8ﱌo=/,}-4&9Q`%k\;L4> N~ϙɅ/;?,HTs(Dl k~RQVY!SD$}gҵ[)Mwmf;"*tŞ?ʼnHQ f}aUh{?_v.:Kgىs۞#Oḅ@}OՙhB9 G7␒U#~5޵q%Wg2f}+ ѱ<~%o^ X0"&ByI&fK4,#\2Yu!Z\CVJOmOirTmz$HhR9 =7od@?NT՗;2J#֢=qF~(׏|$!W-c2S{5.H$yFe󌎝%:wctG&[:Kn.#N@x\zi{c`Zx3 ՛]]̊ nQȁ1d-I@V7L&7t%>pćXĉZ: kBht˪-/@IymN>E1T*1}2Z&U+Ǧ>bV7hI"^"u6.V5\ A8f|nӤh!N˜~ƪz3Pu21@-ÃSbXK_Ⱕ>'IW['N4z;iTڍ :-!F(_/9q꾾ڊ'׌CU`b'(l:uثJ_TpHwK{҉;+G_5%M)ոC(׹_-*׷Yi+CYH>ƕHlEqp? m1APqė o_"B R.ڸSN1}bN˄Xs(p΂Gw]sD6g e5ј<ʇ臗[z-z$;hm> stream xڌP҆ ,={kpwww_ޢ LDYA(` SPaa03123QP[c:X9Cha7vpTpȺX,,\Vff8:8čݭ Y{ G|PXxx:[]-vMmjV@W Aohll!HCr]@3%GPrkA0Z]>ٛj2%G_9> #@Vn665us4[J򌮞c{?m]>[|8) )0\L]]]l0,ao&`gwuC3ܽ\{{e92i[9e0c8Y@'Ԓ^?Y00(geb:|02u-al eh??af^yLʒZtEQQOq{OQWB dž>9M?~??U$fk:_?vV^{|l(8|Lu5 @3+7*j1#"}EhljjW/2>rZ\xw>v133x[\>%do^ {S?F`laU3-`bwp` rrD0E\&$$K\&$}Ĕ8LG##?`R>2C4 % Gǚ 0 YL@BD"DK/GK࿣جJmrlZygW_1b*CC˿c?? ? ?zҼҼWdS7g'~@SESPj|IVv= \C`1k"NXKޛlm 6}?bԷCN <Ȼuu}2b7:oVw_:lucBѲj]euIu7Vu䗵J_2k la*YVZ26iV_CTs۵WC6 Pmhv57\І(E4tR{/(wT8m{Y:X&]OׅJ)-8_; .'jɣmw އ҃]ɷEBτPp E2X~(] Czdۋߊ^@_b(*_W7-+)ύV#+"b.W.rJ@ZA<>U[j~N? #X@eLR?5Z-Z&PqlqXjH| 㝐/&)Bq"&'vxz֌)\uP0Psfu &O|svrG}c6V[0oH` 3jJ (^,]DHv)'RIg,b5*-rӡէs] @,[UU_LzR ^ҥJ,g=x@#uݙNknW6^I`4W(84vUJ!m!+$*kB(Hx~Va)_LmiR Dq&cm E?u^edMS@A |ro;vA qGxg+FM+рf&q4u59xt53=n\^ q<Rb2R'rpPJv"h9'¼b´Ckc2ToCDm$g~Vm]_l XnR`jWElCYUdOPmc.y WG{r~+(N`2r57@ (c uLSFx@ֻY:9-{3fZi 4 h^u%w$g/O͂s%iz Mܩ4rH}nU%no/,A':%Q0es~OIT{d tU2WQ:^ ɥytًw-:| M5G &փ>\LMUacu: ؏ AS_" vEx*rD¢ ^ӏ2 c\%Q5^. N ;lpPa#FpIkj,ʆ=d&H6{ӦR 5̤`V] K&zYK"syN s-r[nIR ׂug\PaSź(EjSDgO^jnQ, qc#tnP?RC#ffa{@6hعR%yY3sFDAP>g { uWnuxܐ F Dcyzq+oGdb1 FxЕ4pꉵRL7 !I| 9z$i)`kDKkB+,}SnƇ3Ӫ^d_[_Tx: >tjVe}~m8[~-/YT s.^a1$b DD-j*RaQAC?sG=qki{`- űl|yO%c&rKxKf DMÕ .Ȣ{sp$]s"Vm)-*D츲JvevK„g磢jsh n{o~t1hzeLSx RLV`9 T5+{۵.X ]TVR&qȷғ]sWکW8ۤlW#N-_6[LX.Z줭X^ Y|7G*o߱;<F&GŌN/tϜA.\~m1C:9B ؍n?6Ǡ4!bIE/vU0ߛ6穮tE:{Y {s8̜ށ7V*ٲ/'yXMߺTxǻκ'=ژ݅&߷ 哅 <gB$ʹ`ZG<>OR+0\aff:,77GU E1 !NsÀV =/ɸ0+2ʡ9z)9 B\vi zIRkQHe'T应%ir, fG';qtW $AQ IrPNcu] Xՙds]X, ѵq]Հ(+ڹBh3f֦R%8]ޗD.X>)w"Drex ] :E뻯 D9=ĉ䚥3<gk6nQ9v:7]CT+OWglL'| a}U[^AQacX"D>v8Ff{(@.UUFqٶi"`ns*{ķvOÐbNқ@3IICJC$\3nd.|X/VW6P\y@wJ9@让h]=m<UΥ-W;r񘝮(3jWP>IiqR=v~p#wM=^X=$ϣtYup\Ա7p|&T{xQh;厽 nA+ֻ84ϋxL=|jY6-:"SaSX6kVV7Ho|*u~aИensA_a}u@9..=DMy5ED^I4Q$dKܠ@ߑyd(CEfu^ܒbȬ5= XH3~aC mP>ޮo` v) VoK5'Vv=NJsMfrle*.U5: LS0Qha۠_x$gXǛ/bZt+fA,"/X ; b0º/v{9Xq 3x_:?4`Z+"8C ZG\itbC< ޼I #5clQB|6"y&Tw<$5˟[b C!h >O9YEp 9rBHo+~.{P]M͇xNK /&~U{d`Zos wjxyÑLIKxqV j̋yh9I{GpS^<(Yt7q T\w, # U-0V>WK¿&x!Ub]|AAMߋCe ~[Mk Ħަ'"P4% L'WCay.LU1$;4z:EF"-Bcc^.w@z>- _&/_x 28n[߀Yj9qqiȿp;t.#8D_a " @$! 5@clzf0S`0F;<0;i@ }:$U2f)sk(DzI%YrE!> " V]G{(CO"Oѝ9HUΟ%[G9VD݌sƨ3 S9õDo'2z iB4KX}zd =cMzL2"0G"fV$dNrdxfOڅ8-}޼vMͲl&XC gIH8ŷG}yH +G:[ʍ.H wXG\ iK8w r'[]m;—OfʧR:P"6=;ǨH7shϥZ{ǎ %{t*׶<9kxVF `c׷,r谠Αȧ`?WDf5aN+fC}h@y`0.s;nVy:]03pqG̋eg eJw孡op6\nsKIh>ƧP(,o#ce>67ʞH.Sbt?rzLGdpgVKs:Dž6Ke"l1amt \ClюEX|Y,36">_*7@pE5kΜVuj=sJl8D!$s!-^H,_6r3)e сEr@槉0W^km^⭇zw9%C"G_2b'iMdN!7vS }H/tJymƃ#4N_ihvs(u=7-_n_ I~(W V|sŰz-gV1)]~]R׺ƙFՂ6W{UՒ4N:JkK)O|xjyVΗ^INO'j4v蒰}r1y{7G{}*fsdz*17 W6^iѦ( wS^pu)X)6þs@m^ɞ87- 1q\ 1CΘѷs dm?>{)fЃiXI-X"9Ѳ ~Tƹ_2ƝQg^pI ]߂*3,g߄ռ6֍ӉDXHͧN<~G6,㖢{v gy?;5 3ꄢ04@O27W,\px%Cҹ&F7B4-6ȧ:ݜ)ܡz&tS̒ЭnO!D7^BkF 8FLHӠǽi.ܤ ,|TLp pP"8gh-jUvF8Ec6-X 3+ӄ=c^`8lAEKT Up$MK I:Aзmt YFۜ-FOQp NEڏ씭 iF^a\oi띪/g'(yK'z0aw O͈}p6?ybS|H@/sIG%,:QX0!zy GO@ȿ4۲`&mpB12ś=/T[Z]cAVj0oh5DXHOg,oiP/HXςh@~Gsr[ͭ.iW3o+~7E Ta]W G=yKŜ&XNM$"C.>蹤=9G. 쐺21.$v?-朏  ΍CX`K}иJh~ѵ9I qrTa'cy61:AoP ϫqYy`~^ܳKY3K^4b_:oy,:]i$Եehs*C)n24!u};SkP>AO >sKV8zsY'~`$t@"?ѽ!]v6p o()KQJcLd;0tOsQtOq_^`cFZ KRUDǾ>1GMQDIqg%Nvc9*wË@=1J۳ިQ%-i[NR}֡ЛHt佬$hWJO$WYlhZUf p(ӫL& \٢2uCv*0۞9<-Sj,%{P !MxMQ9O_(hUE]: v[ULZgx/ނM uxחvv(U"ѯgbR+UbBȃ6Kǫɕs6l5,u`=0$yr&g=}jlw,]K w46aC{2Muce10 ^ߢy KঁmcnkLidAR /qLJ 0,cG-;D1g/{`(cO<YG@ёtǔU97o>5j<< jq!'_#fNؖEFjj`c=LܛM~>%V h=u1`7Mɍrb^qْzZ1Rs~:=R&÷maxٵ0|5Ui= nٳXN@7&?g/,YCOڟ"n#F7;UBV\upu=i(9Gi(SlS!xHqwI 4tb: $cKU<Ӎ|OJkF4ߥ~[ACpZ;5K?jZ9w`v>}$oo&R*Ju~6\!Pw:a fȋ3o&`FsiU"TS0["' W۔='LjxB64Vw]N.ZB Zp/{)1幔Z?< uF7$8;F6nxY<)DڽSb&03ҳR@Ng"Dw:zu- ╽\kޘ+Y1}֩lelџcQIy;va%k_)lK, 8w·`-שԛN!$8_wfS)IhdF_oCHCǼRaift՛gЮDؽTS+aGb ١hōzHs񉟍Z y+~MMWz7 ˞UdRW1cKzORRb#ެweߒMM> h0e|A5 ޿Z !rA':16@c]JV5Tb-@\OZEˆ0*IcoLk{ZbDgT}.>}Y}7^d[я(EJ30XWB=CtvM /f ~UA>Q_kA9] K[/ ~ټ4A'r1B4wE5Ϣ:ʠhVMT %\j[&w)ؚq!O( tք7yYlt7 $fC8MHq6*ՕLָ#RҁqpW[rvshn Wː#2,Y_`3A(ɉ&TE8].nzA$ug;R(e7 %׉̶8\.mYUoo (J޼/ATB ")-{} syH-?A]c׋sUțCzg=t%ñJ"TNbͅd \\},R;cK+LW*:vR^YH$*ejai=,4+.‘W-{I3NpU]XoyӘ'sea,Įp"gO{ S(UiC{Pv{-qmԗrmK-b +&3Թo0\4衽& DzjaJP3 G"q`"G+(w/»22Z x>YihT;-Nܽ56 nF*}< byTýfVvgG8(Y bԔT9C fmf&4u[Kll262zmZUs9NRh~ ;Eڍy4@ov"\)z.uB{j1ȓB\xHS[d8U)~f >CtSȀXD1d GOSĺGWRrf'Hf"OPRu\;|6YA܈j y78 ,_V]-nU)$ʃ[, < `"}`.dl`ڇwt@MBw+OG43F]yLfq'GEW8jBdK,0h6a_1m>iKz}Ŵj,➨ R왑wR ^U|Cd\4okMh^!sc8oWhFKeG+ Ƅ۶KUP][F㧯Z0*a 4Y?' pJ !Q$_rnO%}Mfi%;Tk5oམ !G~ YUVc *ؤ"c+6(P"$*v{8Kh5%N&8pChߊrj$!ޝ21:[Uɾ9%k-4חr.2<Ǝ08XCe,9Ka1Hk7r |y1*}߾"$Ix\:tA'+G_G>MXڢ&AShӼ4 lX+s8vP Dc;~UnnsK#I_5}VLH#{5a\Ml@İ-=&vpj[wTk2vM /JD%UX`&x?b]k pdӋ>G7QB5Ri`[0MB݅E\iߪH%od%1> )v Wu^1G0!^g*: (zF.?E,ө3 Ne+>Uvj$)kH[ţRom FV0+tr&5Wl+!ҶD@ ^Tӷ8HA'"ķ$b=%9Zj>Cܗ4Ȋ 5U#KG{T |2BTB(px$_t+Q!KI/V,y9L"UtX\Iv}rsDreiDD_?C+r1eu*|~ HUuBK%Oi2I!\LubI$1&9E GY:5Ix3@0Gb` ]Rs[-BmpNcawe\?}07 x:Ӥ4anhLCO$DN[>;)2ZfCi-u 4X>$jo8#CQȷHkfM?ZgF$p6;CP\ؓ8Nu&o$ VkgainO?n{@X0(#UDendstream endobj 158 0 obj << /Filter /FlateDecode /Length1 2364 /Length2 16365 /Length3 0 /Length 17757 >> stream xڌPN !w.8l!www;K߫1\#'QT2A6 L<9f&+ 9?vr59Ȇ"@w{ d`f0s0s01X8 PQ9NY͍ lrf@FVe9JP9:020X;0M.f%h 2@oj 3s9A&.@hdc w(Kl6 W[2;dmk`fnc 01e]6X9 ̭  .`m̭WwlE@@G5õxEɖQ (%w)Ff5Pqdd 0y27Ap0p흀^t/B`f9 6&oo fz_?f_?O}ÌA6Vn>bF%%))iSSX gгY9_U߳ / ߗA PYLLF￘?_Sm_U_N$de_?~ks+Go͐u;Y_ 1@cEsG#7?^r03313|SoFoG1#_W``oo_,;j t{ 6 ;;/ #`0 e0q2  `8{? (q;(AQzZz_zAݍ}F wcacbm'3a4d0Tx}O;-?)L̝Q/7 !*M>ٟ0s5#f>?HJ㝲_K0i^}Ygdq}6XMoN9w4ПC/w5a !{3> QAޟ2FG3{?񝇣  5{ϿF .?X. {QnB;_#ad t!,/x-jj\'?ϑ﫧R{,w8=&QWgoJE[\!qRҚE/Nif 4TPGxBzvj~-]vN\(.ue_9d_fT#ϓf-8tE53F,GuZ衵^ЍOc|Cg4GIQl&jbϱ.3mY) \&+enq2:F?>$}e}[Z%`e!m5V\[ 'SGShMYA%7z=6Rr5 0zP}eN/<>L;~#e7yyb\gbaήS=0w9ȁk%Q d|7MP>m$x87KէҀjP1 Q.n5 2ܷo5a<* p'j/c6g%=M\IꩄvkgX .KoM?%);Ö~MpElE jFqnzTnݫQcbl]c RK0z%t.8l"^|4tM'0='N8\ ;R)2\V-~,]-@mӋ=j;i'w;*Xwj!=pS6X "H&)O|\#1Gnq$Ѣ86 IfԌ&>\o*HJQ9rEO&q*&PWbx~DY~0(+3j.qlFa4_ $L hMr|L̛ddM^~|;:پktΓy*N_~Zx֯?_y}l+U`bH誎fޠF4~Ɖt3*3櫨1pՂ3U .tX #+׮pڪTWVI$m#jWbI\f-m}4OD}[8-3I]@mX`tӌ:I ҂).T!ݩ V0>bܵhp]~¾E#?fEYX o_cTr7Q(&{j ;mH$ GlXAF  @x*{r4vw7jlK/~gۜ D|7.'1tpٟ2P/KgãE QYH2A2Ds Ǧsz;j\۬ic?v~k]6WQ}7mP[֞И ޯ 6 ǯSis+-+j렯;,R:>Tmê?,L;-DP=&lI_i]ep՟v31$-ˌ#)W?,I:aX<Ĩiz.Ǿ;"%]Zf곟Ή1`h,Ö1NkĸӁO(s4/J6}.=N)FX](w7zc V)1U>Q;ƣh<>};R‚ qgYJOs5;Vqk&;_D賢9ěCFikU^j~LIJޚ!MOw]]ŗckQˬQj v%ׁ(8.Vp_8aMST(^8*y*9S&9EmEzy,B(%FK5q%4_JSipbZbAt8 C2muY}dv'R ^*mG`΢*a4$}61Och}N[)t=g}-ƍ#9Oȵk#Uno}w<>nϖfXCs"I'QJzKg!K&JГ;[3~f40~h g-1>ۿabOH˳ LdX{<| x8Kz\9S(]|[:eBT#j7,bC.t^%͖!Jo URQ_<:xD{|v }m agI}w͉o(䗓PVc^Bxj>4R N.m\NK(wT(~ z&9s[Kx# |a tG4Ӱ ,0WZN7$x̧jlAj'AⳖhqr3e/'%b>*:Z jDRv@Ri\wXl#Wjt"4?e@ 6cڕ|Z~u1p ]b/ާ QV^b!lO偷yG틈U%1͒ڧ8dL*T@|uEz֞#/b&aMܐCGYH:c1!}N&;`j4zшM{M\8XkJI)Pɿ9H@TΒ] Z#,ɩ 5 <p2J[kj9!ƅ$C TQpr爅q Q_pדWhLcwA9P]$" LWؗ0MC}i=-"y#L.$!..Y î"9CLԁ͌j e5k|BgRGrʧRpEԢ~UE(mMS`ªo%\.r䰴b<Αᣤse> E8SHuH'Q[vtlF?dFǩ =a>*=64U@R:ȊCYҬfvh$pLrIHiM!>eyW3o_MD\#)Chw M,7j /N;He$ EP]X-X|r\u49>n&Bqu]GO'u^h~:SBg\IL/_gj\z }OCO~t}Y܍W靖(ˁ-"B%pBa胨1ŀOp=Ug&7-aaǀMЪm̝^k,ęwKT=:Z@8lA1`$,߬R*5j@wV}-gn:XV'{Ei|fKrf@қ3w=_E˷ LB Rrl6&R ŤpFUy? c \^Vy_yv6^? zإO-|a34~D-+r-;bǁLP%#E5EDjɼOse4R2N9n:ê :6Վ j<fB0 <SN`VPT-lh2wOK Hrb q4˓²U;Hx m#?<.4Q"_a> b+@ 52'\aFHY-U $V8hA`h6'-|䯤DXb-gP+]4d'LCm"LY ZR?^ԉÏ/t37KЇ2hn5JRL$]]ܪ fQ֟}$bs}mH|~nkS: ̯YNR#|?iuj&+{xP&_ *\唂Q0zB9LG]AO9ˢ%Nt9!qK*l3k#话8_#d&H7rE/Ͷ5pH$w4l͚EC9PSUWbJhqP:0oq@Wj MT䇬&H.C=0H"pp\7y=Ql$>ΪEZz29HoU jIޫͭqon[U'T/(d8@BD*#|IrzoyE ovb8(+NY!O_d!I ?4XtsMh]U^=<1/? )P+cDնpD!DE#9ڰ:,gǿX})ZU)+ ڕᾗ8NUYE|pl!".dUTb㆛{c LI1zG Kp[fX 5_:¡i!€Ef4p$"AO`Z?Z[ibge)(̄0u3[X^fJ׮QGWst_ O])j5Z7[ïLev9 wjFYTC]Ph xٖ|ȝU\{_O5>n(zFv'.f$`Ku2'q9H{hW®P`t7bP]` 1\Y&p6ig~1@qNb KC !(|Y:&fcjUlFْI2$~cw #1CF|UG5mqy%"acq7m emN fn^Ij RFKDskmB*[r23KiJ|Xyl=*J#GZ+G{` XcQ_Ku\prP9nct Vd#,ㆍX 0[4lݤ5w#)LH'@mʲwM`@T[hNJdu Hepq9RàLMZGOFUpv|kXFvhWĮK0f6{+?S9 Cf{L|;_cu8DOmZQܚ~߳N0 ̴c=} Uu. $&`(ĥU0W_\b*Htb!0 _|j])4m@]ǿhnj7+|dHch[RH \hJeu=+dv|(À4e  B|ܠ tIa ^aܷ#TˌT k45Uk$ ()4J7ݢOӛ|DmZ0r֒Uܲ<9PmqҒq  { 9c[Gy])acKRjNj|ZskGx]K#9F d u γyů,LJ!s$.kUtyX1&햵"3`JŢM,{o=BJHPevpd:/,nIߗ.s7 4F6W1:Uv؄\ةԇgј=f_ތj1c,3~[ԑ 8H4`]cDiio%O+]{{f*[Fp@s1JY~n2h8+[VT* Te1Zڌk 3ȐhBA3Co-ve_2866%lPbdU6f;'BQTegq\Vkl͖b6r [$ hPY/QUvW,jˆ(<@?ܦt/Z*S馎'{ER?g(약"ە!ةMSxn40ևa k3*:iZݭBܢxS'o_uQ0r2rMX\j";.0I61tF  ={cgs10lRdѨ (wiBQel;n,l7F.mQq-AҾn/Mwbo28 G`,tnbFK@vd?m~u Wi*n9Ef4ၡ,UO?ƦɊrO#m'2k!w ;UY--Hbͨk J#&mNkJ-R.p5ۜI!D,#2:ҕF0\_]:`J4A=lGJs)GشǫHwlh_~ Cq w hہZz9?Z"DjuZ=˅D_!ґOltRa e"xtN憪U@5 '3 gffv5/y-oo_^ *H ]-[B`4:ؤ{iV 01JPymaHm/}5"+i7@OQ[Mg|QR FA- bh(BtyDyQe^<1Ohv(VMe3/EflUt4Έ/W!{#-Qm5E*8FJ͹GpJ!6aAZ tJd%4Dcx}fMi\&n'PݨOj7С j7;W@qESWs.ְ wrĚUM~Kޱ R^u54fjEFLCsӳet!=NgΌEzfO׆^Z91UZUI`oqT']!Jnϋ,ey[<&+G ["x*In3p n"ۢV*&Ts1&B|@Ǎ heIPw MOg1#tK~3kyޥW%W)v"}0\ٕH Fnwbn4ټKY[şmInIo$j3:s%YKX^ݺQ;T7G2T}Pd#O/$m9W9 #@P$w"Ҳ%~v 'Rvbgߥ`#{^>A'1v]@oTyNhsrq9A=ZkSw[$Ȉr$70%<`i5͟M(ߺ( jm`P 5>)!vxWkwE2`S}A-)K-+ݛ-3ݼb?J U!O9@]s17;҇1j\p?lnl'[Y" HXkh]B}GjNs\'-u3nw[?o̥Dܳc9nߒwv$Ѩnv]6LYƍ=IM V(̠CZ~|J:D DZ{|cZ xF\d5VЮ/8q5G U^L jCpv=ӗ[ =(BD<8&KJ3~ryJ7d,S +.e c$ teAJzO *>aTF_SC^w'Njj|2mGh`&u@g iO\fSJDUcde"b)Hpڠ|&HF#qGyK[,U 37 ,rbƎbW.)»olN &Y0Hɓ-|4ܵv>0QZħ֞ѫR Z>T諰 X讀.8%Voț)ZVzR]X!wPw[kYBg4bGxQfteaEl'5)e(F$e@ulcSK/fŏnڲ*Z_Yt*C"}Ę;3@:>l fCXhtt*jRHS5hW e񀭓evvR 'z,?y^&'dF c2@1D(bDuoU !:Gã,KBO;2MWX+}#w8+ ^;r{|βMS@Bx&3O k"z]Xrz)g0~^guDW'*$бu8o`\{Bc<uF| yq$P_vjal,.9 Á qd۝цK[ʡ9oSeHҽ''Vw &0A~7sRP(l7{2~CF4C fIFYǬlC_#r41\!|Ӈ~2Aۜ[`M{*# K'=_Mlq;G='LmVsxJ~ش?LbXZvadNu%8*^{Pb@ym -+CK^+2cZPu@dB=$s)-:5O)ą椢Ez nƒ6!]]gi~0*gG@CmH@%6l Z.BMڰyf\]{Q% V睵[9j"s'abJM11WR;{2NYf6;lwc LT"F:;P}i#Dٗg)q጑9ůQu6.[=/B;!~eX0v{\B-Вh=:O:r&tM'uf+{)/!74 6ďDf!|DW*Xǁ<k//?J 5pljZ)O#y${OF FQPط>'wR0[+6v=p:w/!`;Ui&E{.NbMr겴{j@{D[|SB#jDt(d XmC+1D L9\D{c櫳6R2tRP$ TJm$˦kT"hjck=`W/2D䞽,+Ja7K;bRҙ|RV#l%PZx-f4E,Z[*s>'Ƽ^>! i, P m=i<1#Wwu`fHjeVlig&ꉮ!S9z~+͗<2K_+5^7,\[x\I\T5f:n9޳TYH!Del!…O҃Dz-K`յ8&0>S lvyHC-$!J7I16@C3CwIsnMϚWCFMo﷢3xIq԰$5eGpRqaV]nc !dOQWR/ A_1J$k#yW 2Ny~$Q' #3?$nQ Μ>k 3qyN +||tΝ+* vp+{A|DŚ:Lٕ4&Pxl%,l\ J(⃹&9$xjئu?1o*B>6HCo+%ޅ.D:ÜZsvich(#P;ܮɗeKwPVHCC8 k-X Hx^),;E0>}%X>X7W<)3eGQ97&,|c Γا`'y>4 r :\ x5EwL u6c:J:f ;oPλ&(=*dwXaK.d{raÁf>WxH!P5iy:K78=\=ItQ/A.y71^174ѥrÖ mȺPrDz4 =(H1$ƞ6^:Ƌ."ijUiA/jβ)Ijl(FڸmzWx!sgncIEFQK!_[nGG8xR&UsB~OLLtF B`@7i޶ܭ7QQTC[X!YxT|O-箜)"'K &wq=#U`h,AZ"tл¿I9h\Rnbi[ja/QIW܄rAnrV.a$o&wVǘ/_CuyrVճ%P9"ah%R^Qg7j6cd4l̈́iO#mqX.^2kMuH9̝YGz3ފ(!endstream endobj 159 0 obj << /Type /ObjStm /Length 2001 /Filter /FlateDecode /N 69 /First 597 >> stream xX[o۸~_AE&b4mn nBː_!Xl훡!E\0mӛbx<50)92e1=O1d3F)T,yЕwl˙u$g 93,ddH8pe".JI%#&' ( !#6O=$"xD!*1C''3Id%qϤO8L hE2Hh&F! ZR# $lA)@ECi IK54 p#q$JdJ9KCH[pic5JJb& 43RaȲ"̈́Z˯2|(.ZYǢm| X~k$9_)SG Od]tGa.~6aZI],",yR2lz+ңeStL/fRJYWٸguqCgM2=+WM`u~z(,iF((-"m&MQbV7wṗlr=Y1mqU/z2gEݐ]B(2 Cjij;>z£)lѓ )xb)x5Y'?߾9vxk4׫x6V5Ne].[P:iO[s,(rVa$-o_}}a-q~W>0a\fƑgZDV}veR"8ds>.J}W42#V)MtyɌZ!T69T(3$^ByݞgFz˩R OS=TDߡvaTR%n?q<@s3k|-Tڃ׌Fo<;Qd{md)PXFEܨSY}& &w%;Z*6K-NlXc;bch)^Z"I%G屍,hT۶mGa0hھo4m#%B'<2 H K -Y$<$rQslcL j|ETHyPv$+^8Ѕ=㴴iL/ݥa$^`9,HB50m6 Ҥ_c=gz쉎*H80Lphm{؅_#8N%60)DbO}1[ Uj|Ǫre" ${G;ʪ)O+ ΓvqTmݓarǥhXQޝc6_]R{d(gxudP4 /yWqIի'X_H[ E?)QKD{rSl4yyy3UMq lZUKб)_Hi68XFP5ρsS_ی]V77W|gY%/xŗ|Iyq^M&jSϛwE]<Ά 5vfȸ[gj&wTbɞ7e˲)һ7wIYU/^,˓ۺ.s˄}TХ;b1߿$\ZPT/&粘?h>Z kZrOoI_<.vWm]jG WӁ !|H 6d)%ceAfLESm!j;)endstream endobj 229 0 obj << /BBox [ 0 0 1296 864 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./residual-shadings-shadings.pdf) /PTEX.InfoDict 80 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 83 0 R >> /ExtGState << >> /Font << /F2 81 0 R /F3 82 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 2251 >> stream xZMs6W(`gz43ɤo\Gi#wA`AH"胘|=rYaͧoy7PJ#bP0]9#B6#BQߛdzx5o}Cּߧ3C׃ιDv/7/̺Q\}p9E[bLsul1hc3߂т`kЂؾ0 hCTmpƊAp:5< mDK(o`vqpz5uZ-cݴ<z}fB]Ct`-'i euCL8X-*B9W{50.XI0ja Y׿Šf'ߔ,u LB_>?56F&3yƈbp-^50Dc3Ј?H%iexp;r9\z{{}!Q1Aik]Bpn<s|+CnYzﶯ!Ιj:ZR]zc"c,Ɔ rc^  @q #2};#wFD k=·Dp׀"|NQZʊ_nF 7Hoo J>VTV1r\F~D9 7KUb+IS//(_+~,%0U9UZY:+FTgf尧R`3*FθOrㆼfUCNüzY^zs?5sjSs޺B^-=UirθZK8|3['B;E}#|;A" &Ni5JhFJFVp+|@JkO i+eo)'WZ,&h8JVq\UxvhCfu`RP;S^KFCDn?,VZB[7)'Ɓefly ,xw /"FыݟlbJs{y*G^53i@0|BŘ(߸U>0~kB ̶Dm/v_Kע(hg%qR O# L#2plin:)&pbs=TEf26X.c  2d,ZX.c Fdl(B*zGEXD26 D"e,"zQD"c2el*"cS2v- ֔)|w+3WՅ+ɪz+(rduʨɲ{> 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 231 0 obj << /Filter /FlateDecode /Length 2033 >> stream xkoD{Et_pD}(BnQ;'wW>ۙԗQ{;;dqHߜ}uyXL^,QY/(z{-EfCPL ,uԯQQ#QZ_U Okoz&`ѪL'vihU#Y"OYMu"N9o PhG<"{iqë[pUEW5B! 柆9G>ct f*;?s6"@P<[(p/;O%XRIH[:SVu&Ҍ84KU7cu"`ϡ0o?Z[dd c޻"Y-Ct>PEZf(49P,K& DWN71dؼG+&{JDJRy[ppgJӱ{JȂ2}#j7LI9UC^uGp|iM]L-NNs>vZN "\#!,`7!胐#Ek6ɧ1PJ_YKM {+⣑py"lY*^_/|j'9Bc}D7Cpv-:*b-׏ ԍ&z8f(slʡqSL]&0;W{6SʨR kVS ^=Q4{;潘>[2oO^ ^::QljP?d^rF%-dƩ 's6"tKr%MrJ y8dlh~ֳZ(Û58zzҽl``^mz{u{!uL<[. %PsBxgmDԓWođ.cdT^s'"靊^ى`|7%<4P98LBlM R{p`gvΪ,/Z&h=re?i=PB!Tz-mj=#<ռGp?̙.*[Iهr?\gxQbr!MD}7Њ)":*6![M#v F46IԷuirP玝y^lVp.cAoiWD5l.F0.j>˫^ aleaDLqo@#Ƌ 8_Q`ǎsr|,t_L2 lChNޮ/w;LI۳2oG NcMl{U`n&ؘ"rBo.vh*y?ibSJR"7)98%wKz.2l42㰝d?jh~UbO)[6f4~CBԵ@r\}__O/ endstream endobj 232 0 obj << /BBox [ 0 0 648 360 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./residual-shadings-alzheimer-plot1.pdf) /PTEX.InfoDict 98 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 101 0 R >> /ExtGState << >> /Font << /F2 99 0 R /F3 100 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 834 >> stream x͗MO1+cRATmrC"PTT34ڒ5=؊w?c{ oŧZ~p`2rѾ>kc љ< ߋ 00-N ހ%$ (up_aq8ްj =b }2sC 9]Uiuox_HW'OUC2Fjӄf>\Rv1کޢ'($'/.ʷc?2&i lDP?Ą;m|1']{I/KC2޹J/ :=9a,H!Gon>!SNu6mwM2]ϐ)mOy>":Mgja|)NsIcuH[O-[)b8BB55C'W +aaJ8[T͑Incrhu5W吓A>>\Vj0,wfn6Z-f),9JF: F/hp5Zw(&[>Us? $U4.DG  <<ćhxxuچ_3!]o@L6!g6> stream xW[D~ϯ[ xwHR=3]/|s[ /]:':q'GeIr vGթ{*za?8=}+}d;"'G[e7~7ߴ]#m{fDaV@l٥ OBRq$4~TD%D)X_8j:t?W><<\҃筜g-/-`;< #3@7Tg,H2wKjau|V<܊&'"vNX,a!=´vI[ |cʣH&DhGBYpTbN-q2Wd@q9D{> 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 235 0 obj << /Filter /FlateDecode /Length 1855 >> stream xڭXYoF~ PrwyiH>ꢠ%Z"*)Qw%4I]173Mhǫ˗$$N&WDa$CbgMeQZ{9UA nהL8Vqn0}0 bV9w8 \x}gBmL0Ky[՛i(a <$X8zud#@)^*׎s^3Ldn^EH, ߲@pN\+v_ PVؒz_$4VrhI.3!^;BiP!SdvBE&ԄQBdN,t)ڀ*U7ѝ20HRvA$'JpC%l5XtM(L(]-" j?Lg6֌'~W~ َN)0C'QJ(ݸPe+o@3wܸS)>Mf);%.:"E+ }M!"eNlz~n|=bY(9FC$L#pWcCƌ%l?!ߚʹt nXr7Պf[n8Z#Q/8 (3zMLmX')ߢ [%`wR<ȇ`(H`v\E|7GD4֡ό 77Wycf:m)e |׾2IjMg1ë^] .#Vծ$qAD25w>1D|2a-хfEqy<Αۍ(X34낯NԟX\qTB'{Os|GY .m$9P=-]>6/l2-%Nt+e˳#&;I ew\`@X*>6+u~!o0V˵؎c[b"rD+$Bl/s.*g&>: ˾^<'x$طsvpS7/]Ђ?ZKNyIäw^H?X|0rYx*xDd L{TDnɒ3=8O!22n&a*z \<^nGL"U# t$J3sM6su,M Ks6 ?\6,ݠ.&jGY&hhLdW}x44]lyї c՗HzP -Hܠ txǘ'3whurf>bO/5ӌgD\Y'jE<%]y1#'x"'7znϰVla)+N%B[[oKLہTbI̕ ]?#zMg=,kfR3i^.S͂{ "Qt.vh.lVr1Z"HJ6HUPՃr>Z1#krvoo }O\<+b@ZMFDR)lU:˹Df$qY6^@ID9b \Z*DW/F1o/ vUA#c(;ǘ ^FÃJ^9Z:R[܇FTգ'D%]}endstream endobj 236 0 obj << /BBox [ 0 0 792 792 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./residual-shadings-Punishment-assoc1.pdf) /PTEX.InfoDict 108 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 111 0 R >> /ExtGState << >> /Font << /F2 109 0 R /F3 110 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1997 >> stream x͛IoFsξzI}+r0l5 "}|mQJѡ53|}όdod?w^Q(Vn77oez]I>W Wp#7KÔ4aWv:\WQ^ͤ[Rxyg j^]ذke./WsC<7;hme=^`k-ث[lז)/2pk_ϫs'9xWMѡ8g8oyTl0f^:^qa۵yJrZiԸf tR<:҆|` zyڕIFJue=du L d-9: u|MdRXٵDH,LW #V83x~V6K;)6Sgh䮜5w*Vɻ\ԁfI7v\TB/-CGk+e-ն<íis4~Uk@IّgL毶 WkCҏFh]` zᖳ\aiRr?Y=/aE o_#WR2;UA}*0}\܄t~8}.֒G1O:L݁K`+~1ODlaR7\ Uyw |kLjLC,8J?RZ/ޠ؏vsoݠRZ( KsWּ])gZ7m;MϫynUs)QsKrzpuTu8OY ֚a] 8l&Tt{7 z/%HH.|1Oq1wpP7l}{Va g D]3]a qzg 4՚#H|&Sϑ8+hJA9t;;YIhB:  O6끅:ҌȮT]# \(:2U ;X;pgqw9UVaP|&/ E4]a Ͱ먢phWN[y:/54}69g:F(:R|4!!{]|Lq}},v.d7H3i1q; e!g(h$Nv2"r{p 3Ԩ>+;lTO 礉KIibd?+MXBKky?/m!y/Mdb32IH-ln Ӈ++ݪRV=g-iShg7m]^Ehhܮ6U?; [g.= botSg&*] t1WJw~𶁖QzwDZ#Sm?NE[3ۅTtGMWXBE,ުvp)Tt+7OU4hM-*9fLs+sJ>QJ|& d`l+\L6W px(05nqp3S.쇗49p;H?=;{sޥ3{+,q[=;U'pϭ<{wGg"oqϑ7ffe[\JF)qV [qm mS4S`ϋ/xSd=ViMޖ2"yEj4r1jg6;|lGٱ{l&.% d3]` lE_Q6@$9V30endstream endobj 237 0 obj << /Filter /FlateDecode /Length 648 >> stream xUn0 }WjE[ l.ai FMҮ(]EC:Qb)%3NB׵Ե1RR:3}3L^f:rkm zLzf70_1!3uo_n?~>OuD8#mSu`DgC -rvʢ|$J6 69M>|ZbL'G$lL}ZiY: r ɘڥyJߍDwE8:iW>ݢcsQE\QٺLK\~-7<[qsAK8mbZ˦t8>n̉U'Z턂qiOyQEq#zv8 ɰ yz{Z꒽}摢h&Ӫ J:_C%z!a}ϵR?GG$g?( 3 ;d!Vq8P @)PhYBXc> 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 239 0 obj << /BBox [ 0 0 792 792 ] /Filter /FlateDecode /FormType 1 /PTEX.FileName (./residual-shadings-Punishment-mosaic1.pdf) /PTEX.InfoDict 117 0 R /PTEX.PageNumber 1 /Resources << /ColorSpace << /sRGB 120 0 R >> /ExtGState << >> /Font << /F2 118 0 R /F3 119 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 1666 >> stream x͛Mo6+xf9~zI} r0mb#k"3"-aehy9k}roFɨ^.noOg^OEz+|(܀xG p4JxжC:u+lޜ=Rk'V#@8 P(3qG矶WDcqvk?T2Djp5.non{sXGߏ?w\uѯЎӾS@^:5)=3Ry2|u~z# ^XJB=^g+ %}oAjmFW>^mwؖ7xA״\1mobJ&dRUۚLD^`M_y2N)O  nkWB 5bfM4]ڗ_ :I@#k+!p!>ЯL΄򱬑3uDs&5v&--LVD3尷3i2#LT Tɨg0~KWv^Yct?) ?ߗǝFw1EWʙܾ|c]n9݁`#[I=:zuS0R539_Γh'щ"ɗ = ^ҒJUѓi@RDO#Tvlg9WĈJv7FԑW܅!e Qwو!e|Vž|8fݓUo4v~>ԯgOHFsiĿ<$KyX"+gE- pV |zX蕠h=Kfz٥z\jzy'PxC +gg,Q- "nRY>^ť2Y3"sfh f}d_ݥ摽R^AE].p^v5^s|8ez ǀDo,1rn_"r:iyjzhӕr Bys{y.J:Iua[)|uE}@@。ϟ`n5WBI_9R{WXOʮz(7{%K|yc,aN[T]p U/$핬N#zgFq{ Vz}G~=Sr:H?]=`X#g=Qii+O1g9S^.HhW{%/ZϕӽJ^vre+ %&> stream xڝUێ0}WёK4H` "mݤؓ4YZrbg7 odZVYi6'P\ CDH-VVO=:&ܸ.GGy:WLkE?վpNѕ䅑T-D`ޯ "G6ZiKDL.y"Ѱx[I>߰T6*+#reiLa KnS\ ڣourAijl8P{?2$ӡB ӘiA{ϟI(|6HK]ʔ.`oZk ޵e . <cCwnsá~Zr1)j ײT!&E; b]t,8Jg%QD$~(? ΟDg_<s3 dZʹU˘ P!173d. ~xC:hFq&gK'oG)@y``?BMtxDPtI[t>l.Q0mѣ<߀ֹ{d;CmHCB}0w4x_Bl__@endstream endobj 241 0 obj << /Alternate /DeviceRGB /Filter /FlateDecode /N 3 /Length 2596 >> 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 242 0 obj << /Filter /FlateDecode /Length 2977 >> stream xZB0ЂB<Η8NlYiEx:Œώry~qٙVՁZAl#k x;0^g/a$WRg=Y׾ Ӑ:8bIKKdSZL"M| ?Ȝ^&E6%Rއ\Ή48sTHֻɤJV[~*kwj8|0ϼ{WCbnξf!W mך` U᜼25ݍPY4)by cH2uܷ#)ևGSzze CCYxR֥> !-(~ $8ʼnn)ʎ%HIprte1ў ڙk+䡥HjE=/`A.7IīgOk^]EYy=Hwu z}ՆUTk Ǯ 7lFbՔZB 3d^F b$?D %UUΩb[QF:I(,zB^;vXjRuBFOp1N ,a j/+ɺ9,hnF·T|-pnSlLD. AU{_C4L:go'x吉f"_{4=atÄs)wmٴd "HbHINp?>e$#;;s k2*#yF658'~Ԟ't=\^Y?dgLk3?vG⭜`=X0& f,\Na > O <>:F'7Yv 7ҳ9/$潄o&`;VZ31izpFTFqfYJW͍n|a6t{*ÙWaijgoXxF RC`n8D8WN38D X ̂2;k >H~Ngt~x*֜V{捸CDk5}b!)iL.r6М;/ 4Ҝh#0!+Q84{dfiWV.Ve5 4K]f YcN^N(^T}?x_X_8w܉ >ߝC9.B}E/7YK罸B+}? "K(T/K;T$+>|3 f`3ϸr㒱#&SIF{Kć^̃&R|!AQ|׈޺ ]\ ?;dT=@S]&yi,!+)c(Ew&p|z/Yb.bֹ;->gW'ߨsendstream endobj 243 0 obj << /Filter /FlateDecode /Length 1201 >> stream xڝWKs6WpzfLotl'n>J2}MhKEiH^׳ ,(RV&X~.ųg?N.3oFY2%dI{.'Vu%bYPdz ~')l]OR2մX۳&jW] H d'(x'; SeҬtdegt 0b ?Ho` pQApx'900et#:5sl#teG2-[lO(C6< @ƀD Qe^ <ȁ+(pMAQad0o` &1ZH!Z%[xByђ3[ b6WO^m\x@18Q~hUgۤeE`%sX]`Ux΁q^Wi94"]61т0%p0Nh cZh$xD1ianD ƹYFB %8* ׃REd+,Ou ^!!o`z{CxDF~/:&"-s dϤ&733 n Wj$7p։h-7C uG .{fÌ@W(r7Mux&cF>ѐgU,/B@yցr>EB9{ 61 QZ:6ਤ_G\ E| s)N,HkFlEcT)%i }(/Q_p3O嶰gygw˟bw~]*6 oÐ]ٗQۡ$TgߺUbR(ɲEԳӡ`r“(U/! l!SbaPimvĊIg `ɟV6W1D @T+" s-wN{3uTm8býVa6`<Yf=Fc}ZoC)>#hq3|4cxۂK-o΀?]?QvȆO7:z$p*LSG> stream xڍTm5 %CwwHtC3- HHtRHHOZ߷f{O]:ZRV < cȨJssx9x`q4z]+WaO0@ pq q%E8{ž `dp rYU ЂXځ`^*$f 9przxxpWqf6 \AVߔj@'_8ڶv?Zkx,A`S xRTv V3 9)WBv?'g ls^˫pY;Wӽ{q5\0emM͙SlR+ Bf Җwm/gN?g30W7;mqs,a ?՟`]<F\Opf0+?SUI^WE/8!v~;?[ :@Ձv**!?I;f|>E/x7?KBNR2-P =2QrT HUJ_`PA_dAnp}OKoP7wK 眥q$k%9ׄZ9~rИ|O|?D=Gn-v~Wᘵ xxOBy~f),sM;Au4nǻ%&3ZHk8 Ҍzn2ɑ`66L.!t)i!u˗M04rJ5O.lL%;OnT>ym^tخj~&lwg=2Vh܏UŁ) _wOSʭ(J2Ρ_;Y傢j6b?Y{0pWͥ 2vCIU9pӍW%ݻ -126 +6\K;D>sȑzڥfUcV!9F)~%5':-!NSA;!2ȏކ./)qEIЍR@9Y~ܗ_:ȟCs$/:9;nOK%٫(0Vtfr,_I(`&I\%(W#a##bXs%=b8m 1 oLKo#-$? awNi~\R )pm<ı^w SDҶj'/B.Cb*0:W/Ln&SqT}'>R26(*U nbYV{Nه8`W!zt,u9@w4e tYFq@C7L q}T⪯u/~Cs]Ibu=*X>9#h[@uzHqC3Jq; i[HmzD.ds틝 J#i%6N:-;xuҠ**0sWsyKjk}b#JSIܾ4&}s0*e&5=)~{mDAq NLVm[upn!`n%kb3cX=ؠX_(hS F=͖&ybgEVsE1~\k7Fx<$` k}:bYz(ظUr&h7zTI 2r&g:=>6.@X>S_Ԑ̜uqQ 4 /?"s`*26h"` %/].H{]Mi*ao V~ŁkVG z`(Éz>GEsL(kɬ=|_'sl>P `Bg~`tݎLˏDu%Gkcg="TdgZ>CO| 0>8(( ) 5! cKG9._7oa# f+Sv'HP .{{b|]MVcwv՗o/Er*1fw> Wgѽf#%UmPڝdyFskż;^Q2=Y otf7I]2nl02WEe%ILiHq;8>Pkbs|-A6Z!~5'BA͐GYv;poEk3YTP~Aٺ !!Us>8&f0|O}0#7M \R6w>]lxz_F2N:yboq Lg6B>q^Ϯ?B#P(_H gXSt ?<ݒ3h)+enaG,'rJѶQ-/{FE*8Ӈ8dPs#k_:n̲ڌb\%܌&5ntzɉxrWe_Jfbibàtd"+D>+9]{"_Lcd¶0Y- b*rf4a^%Aw0 grIh!vM&:}B?'}30^÷3niq(o\ylWûsID1+ZK„O&vÿPH Z0ZaQnOm+)k;=M `\9ot=}Q 2z2˓g흰"B"[}yt>"M <)QPО%&7/S{d@rraE%It]c#ƉB8A:Bb>,zDoD_[ uFJRɢKSʇmZ?wF/# qSICb?I9اTj 6')=5c#iyT!I;+W5yƩVt,K|#h~oYҮ ЉYM G^M9# {*Seyd9{+)o kCS#"eFn@. כ ӂn{~Df{ן. )>4tAo99e>MLc襃Dȳ{2u_r Js,!1< 7-ܒQiͧySr;4AKmMb8첺:G]:XNV'X|,2yЅ@?ܹa"5d=?m%k#RWi,|딲,YeӦX>qo1Gث&LWpJ; ^'RdlZJ ϔLp'lj5O_NA+C$W%cJGM&݊nĸZNG cŷ+_i%]hj;JTW7YDq!PJ~M zB"}dU*?k bk>G+bƜ]uo fKwN jL4oNd_nZ33Ev) 9"a"PǀD83PEZW)`nhCPOJLz* J]8h:L9A\jPY*Tn6f7h*[=uԼ'#__éh\nH9.,{Q R:xU|kAgP֗f[E妍H37%I-VdU>">u -燩5)+ l _ p\Ef ؊i {>+WDv\DI0oMY$]}L"^ĀgOdCtѻQ{P(;bM\+˜G|qD RhM iqUl*]ÁoH#.ZoW@JWX?`*-8Jh-j2.@T\r @x/4$AL't:wjHDh1E S"Hm4>+A[ -}{@pgȔL^:bżُ6?.Ȫ^@ ƢtP07Ԭɘg`pՐcrMArq,hD] ͻNWօ-jۈWl 6͉7ZYCt0[F DVڍk9c*_w@zKC6\b,uc\F=_l~#B(a|М|!tC*j{LfY@뼓Fjs{SqNV՛<P5}:q}yhQ,s%~C c7ӱiEIirջ>v(CG7x>,ϵx{-!o,=Pj=Cu>{0B՘EFc+f) {gA14p͘)qhvZ|ͫtgǥ7X_7ܶ#٥&W|J3iuDĭ/fF{%d;5S4Hot!m›#6OgmZҋ°';HZ0k{ur”('O\+Q'9G\ixz.}4K,''}['# >fX 0%A+Ά%Hjuʹ21dRMd4VSxqZ9* ^ Yy4\XI!֡q)r_*.kpr ^) f%=tQ㽒M::Umj t|X RH~~Ws$аmXh)TfY.5XrJ1g[)'RahL_[f@Ȣb>hig –DIj)2Y #JN o>$V12 Uʃ D2);p]'Cjbp;[dkׯ V{I74#3)#loQ۞.>:٬#bT:O7pxMPL6劾d &VHtڒz[;T^;u2ȣa@&Jhi^ Qʏ%un,$#` 86@#b$3sc$TkS;tq;eHҒ"~y37k{/krh031dܯ?Q<} YVs|RaÙu/eM-U1ǫ9Z5Vu:h'Lj3diV[i_; 1ؿ& 1u3aTyӋĖ0˪4w"JUQ啸tj46O6)wn=e.*y$>Թ.SG(KIR>z]w'3a>"ח}'Ra7.mW_Ej)~'ads[>Woybڏ=?SC %R}oҷݏʩRگ'$J?U`a~=,vv{6A& +7!5u9.P|l _ y*\{|/R' P>yLbkx ~#{,&0( 2ߊ]&tR$~ FKhG<*Gh4W.Lw ޭbvלB/wrj yY |[8QzULE2 7F _czO?1stTdg۪* ,eFmWN^{:-F~+( FE|Z:,Y&Q S7aw*.u0Qv .Вć۲P~e^cPZ}tu[XQO0$14B(~ú9lDJ&'+9щAږ6ve882H֣F6^kwNH2>y}C1PA J4 "Q,YJ$-Qq?2jL~*M6u4}I hKY{C|<BM~'ջ,tV> [ L2u9u E%ULO/CIe$HLu=eD߸ زKN<<3oD3UvS! Cq_.:roUU)/K}^7%4| \R`D8ɑTjb2%C.ߤ'RC*񫡣<ۮ'ݤK:vuJ1n eF]^C t8^k]tj!LDwC6pa8s/.Bp/yˣmʚ/#2<g$p1 wSlx`\J>S߆gOrKCWB2x@ތ3^l mtKDO~cX g1BԽk׵3 a->ܲk* ]^=o| -HUۼ"Q3gB248j% k:ؕ,Zz>khŕ =,.Jvm wh N1ɐk*y #ɏuR.WEk^NjuG_yLΎ3*RDuJrwbªt_1 H,&=A_ԔKp$uOE(0nu)#;{q3PPGdYqYmo{1;9 2<>Ƞ/tNk/7y'XG9s#dž_L5}P`6T#w$5)M?ǡP 8qt/Ɔ쁔P-b%YoASn;,3|V_! .TGe|/}5i며m XxԎGjU e*#\؍bN ucHʒӶKh}΢i<ZͶMoj[ Wh}3 zD,ԣ>uvgA_4$a ;ǫ z9MSIץLb$'kendstream endobj 245 0 obj << /Filter /FlateDecode /Length1 1433 /Length2 6197 /Length3 0 /Length 7166 >> stream xڍwP6 EtI*@ DJ(;JM*һ(U@"*)R޹>3NfoY|~LX B!q @P"@%CSX0X8 )Gi@pGCw@Rr i9  4 ^p'@a)yQh_ G#J z0p( 0\aP`a8Spr" /\0, s 0x@]ؿ f(g78B!`:L`!r6Ap п BQht80' ~9BX!# ߭CZ&|X(aEp/Y餎!qX_i10(}E F-9ÑNο`8C#`|*\`8$PFZ\F| }ѰF/5C8`00`~iD PGR;;A sK&X >z%0 DE5 /',.@@ 4!yu ?2"Q_%~ HPYE 4 o%PCwumC<?BEXZhC[uq’"]DI%ñZpm8Fa.B_6A 0L,aqKV}h"(_;)&)`0_J%$DX^'oDE(!@pFa( Z E*HV@bQo0B'BoMQP0փ*U6o!͌;bCEvn$ܜ Z@ZvnFjy3k|%V\.%i"zd)W&KAmCS7/c^xQ[GUYŷ/f>/ClӍn+R&yWMuq YӔcאTi1I~z6ʺSY-ŭu|)Ү)qoC:Zp9i2/W)ykљ y= ^dX=t]w=a|BIgy^{9GܪJ[d_ p}Íȝ pm+LɆݡgT_{j/qxMw³2O*zt }SͬS{{Wz[=$}{p=Yk gi|r+j8̨N0T+8WYp:t8 `DÓ>}UbEq7gJ-AzSSf>6L-t{K SUh\&P0&=kUiΏf~L1\Dלq6+\m\(?-fzB.5lYBؐz5NK)tj3z|TGiW#`dnbUu .eWAm9zO!m_y[nByn)?jIP2d5?%@>Ys@)x\;} _Nᯊhf:z'BN-خu>Cܖ9?xт'%Oy#5~LJ115J~LvtANVvs*pqy`fU1ge;J'oNa"v7GEAoȸ3͇!%A5A&bws@P ]*)>{ፃh\SPPS1[(2'}wNjOV B]1^"OeKUߐ]Yf$H= n[T1 49(Z*8 rWK9Cl(y'YSc_sNj%C@Т0wlG|xw SG|mU\wE#=d;Sn.#&Ok(JWPsWުtVyb)&(1cbgT_q6&yOP_v8.T[){HaO³Vw:~g=7Ƥ9^TsNwAB[Da$އ9`U/NĠŹmli T QYba k)%mADI|< 8(|)kCttDkx&Sݓ+O}Q>*6} k^f#)Y5p rC SAuY GyZ>M|Z`Gn#|z g޺^'?;d/Dr> @TiHҝ󾢉c3i&ɓlr3VNf^lfzB) ]ϻK?>ݴXYʻި3?tƺ:a,o$MO%Ӫ3 ~5sR8-P3/AGÖ́HACɩUǺg}|! ^pl'o|[`y2"tfMl&.4vHGS^f!An/:}M+:2fA  S- NG$}-A# ?'pԜV-+':z5mgN HLeC ˧{"_q+Uk~&ER*I@iY1D-DLw3aWpPooUbCPݒ>oU3bvp7%~qYK DLL§⟾~H3C^E¹iDв`˴ RbTĢ1 _Ԙv3yF@X`ʤTdj&Rj5t/z܋w_sVxNZqe\F1aM<#8G4ٝdSUݯ9ڌo,f2 'g[ү6k\ J6z_k_iCCuvaMNڇAg%<GRl6Ԗ'זnqIܞuzwe3"cy'c?+V-n)m^t.mrfRj/^Sa] 3IU;-DF2MW'xnRJSǭ4IK'ރL8i9nt _?Uϔ ]j?$"=`Xڊ]v\?Wf7)dGTv|E#i֙#nU.h1ZS qC6CYM')uEl< T}ًA4"7c+<;y#N0fe\ļlx˱) 4߂qVn2U'͖{舱mwǡC}\|m Y>P2M%?`Z~W}/̂> ~ŠTAZRr {|<:ƻ|54P0W搚"{=eb ۚ⨾+o 7f] OF;~n\ll?y)Ҧ웾xg{\)ՄÖy˚*-)"bvsb|>r1OxX 7Wc yqO;M*VQ0$36 2EY|3[}v Yuc 7{6+gM r6.Kal{u*_(#jgDw 'ׄqDYE{"RNݏEfVSPC a,|+桋FYi4)7z<} 5 Zg4)eB%zZCMm՝oc/rۭU)xX<|I>6H\-;^R"9 ͡,RG}\r+A#"eNg@͌! bCq*g)i_].xΎLa<=6ΔD>7%Bh#:_?,5z9F;G>4JUS746'uPlfI]y1lۚ*CީoiI፤?0; ,^vg<^>4 ̂idV&Qfs$8xJKH73Y.La@jW}\7uҘԹ!K! v\xOsd5%o]CA֭hҡqjKv[#hIG Hvj+UӘa-s>1L#[J r.>c U:ہf\ʚlټхn1 nq>h6/V=CI 0'TϓezzQ heCj={ Dp{P41-.)sCOЛdXRњrmyLPzNER^oRl$&tPHL$oaY #jf+Ѵ\,yWLK^<}I`ֳY1:(rSqxQ΃ دՍ$m5o4EXw9bVpGcs1@(e\YC?h mӶ(h#ŏ/3{^%5fWt }cd$D 9o+:H&d9WSs/P.3G r+Rg_Ԟ/C+mAFpG.UY /ɈENxX32 Rfnt͘V*"8Pѧ4vSry2`z刱Rj #y_;!EWI_<}$eL6 uIECB؇'+wX \d7׃Q;p^2V'_`=#m!R-d^9KDӢz'HbK*l6̌d2rZ2Kn<ÿ8f3|b#o}bQ+-"^9.w$ĤaҾD$sj]iLXl%*\R[Aa\gهAkYb$QdƩ9~:o'EZGw-~sC GWzt7u#φ|?Gn$_ICÛ-yGZrͯiVoŐ_א+## 'a^6I>ao~ډ^H.r)f+EMUq[U]䢗$GvQaAIpSA{GF%Õ3u iz=6,W:Qiř.gk+_5 |AA`ޒnȎOő׺{)>ܧx df:\kpo"cBgd3!l'!L/Ra,sUi~ J#㌄(ǾTsC) bemE;gOMXZJ gd찬X/HR1SU|nUhx/ѳa!I+e>6*gA%|^(]'vc<6E^RE܅mh8^~C|8MvhNoj Erb̞ӕt@X6B}P}ŹO-.V_x,^ Y/Kg_vwN9_ݡyCc_XnGXm}NoJ3k<'ArO~*Y|7˂Ux~knVuir|~v"GefgLә0RV~ oM* 2:)J,}W~\7In27<{[AnbDV"@);II?PqUWr5CʾR.[&N*¶}t> stream xڍwT6R HC7 tK 1%  ݒJI H R"ݝ7sk}ߚf{k}_{YkXxdm%8 5A$  ౰Cΐx,w;DHPT=~A_D_T@ pw @ 4xU8 cC:?6(p@ 0₪hv6P)إHW >>///^ n/ xA.q(`jx,CnCj!P!0[;詨Z_`J'W"(w0 @ah)"f vFQ`O0l:P(!lܡH/#߯46+l..~ Pw >|{>Aavhz=A< * 0(޿m$ @ x8* eFqsv({B$?<P$` euF P~}d0[8#S5R5C_N997#qqq@TXg5o`GByT&o٠[_Y)y8;`j=(ihQ75 P (H(B Ն"mڢJ A7%:'[oTmO@X}@ Q*x^nGBkb/?x4{ MOm$kZϫeixV>b/,E'F #Y9x4&ge[A9=U12Où{>m֙˦~M<,P "Ue|,1K*'|*_$7ލ7{tNNNv'F46F[ ɻM8bp%ּ7Ҿ{CBStlmzOc汔L_#09W+ ȯưSX}DI7|XYáƖ/L񒎹8,$2t=뺸{PyQ`!!-~,:p( ݾwQ,(F[} beAH -<ۮ6 OO,. D[{Wl|h0>|>d| }g\nc{viQZ]rFF i}|`*+ZHdU=.͍8э\]V{GʂN! 'QX,V\I~/B#5-w-6s ;Z486;6W}Z3yZ?{8V?:vnuVJZ-MƤ'p4 !)νNwz 6[w??]j6=QKkk8HJNoD+Gk }ZZ6XBHɹ1$[qK 9BaVu`X1K&(`+hI2|Ò!*#k&z*BZkG5#uZY%c7LG22"mPQeܮޠEiN8M:^M<QGi/̴OAsxG#?^adE#Ь>G xޯ19ݧ~5Ժ0G@ofqID@x_~['z|GYKr p3ruTOzKMX]sEkmh#H¥M|lvHa2C1@vY@LL2_A%B눂4 )덆e_ ឯHRԐejaPH@F9q1)nDzpίjzIEwCNĴ^Hsn="H7h %h5';I%?_sQ,%P"=!{;!{МT6m(F^- &U+lYBIB@þh𲍆 \5TQXE*穑l2'WDĒ\<57cqݟ•82=c)!H 7weaR/qͽxU) ls PwIRs#Yh>=lmZzQlv8eZm{(:AU/? MeIa;'3>Ʒ~mJ1V'؎ޭHSբOjT)#7Cy$2]kIڻ}na9׉f ZjO_E|<p.HQPgx冷=mYz\B%)ܛ+eså/QӘ Da1{8TIu/I(0#1p: l>O|TL*dD#l\!FwbZ(Tj ^txOӧáP&HW$mh3ģ3 >BXK =9z8`g(38mv>X.O0BOV_P zhݭo;]2FqX{kqQ Wwd7{k>NLopv/DH\߿樘nG^lV-)@p[3+tvʣܽ0ûK3Ǣ!>hzJ]hEǧ肫\D{HAx'; ۩Ө"M6B׻$gDhnxà/ت×aLznqr'ȌiIg7AX}N=[m(7a-~ΩʞxMFv+UÊ woZ, `Xo3kkX^OA4DhǒӪ`CI,_ ءUU+ ;9CQtZ)R_w( n}^r (ptnd~R(JL]6"xE.xqX"@ϪWN>ONZu„%[ OI"N7m-ʰSd1~w[ ы:/ Tf( sk}}F'm*_?r ]8e˕JtK@@B_jU]t~kwӾ|2p-.Ȯ J8@d(ui<Ůbe9/^9ǨH8<Թjnyqv~]ꡒ k{?OJ\4eBk>Dfz=> M$?=soPgeICk44P)ew+i) oe}mݘrq{̏ڂ꧿)mfƩr.ιqK_*[װ&GXY011c Va^!H}>O5B6;еتXx<Uf,]ږE8k7?x_te}4YzbGA 䩺F,7}ZRWM?7Hʨt͓UG'kX#44qLuܐ1> Vk ^OW\ 4Z|ƂB> N?p DŽQran cC硧BL@FC%XP< ]8׍͔@﹛=e;dk!w 9{ b`)$Pѽ!s^/W,&<ڡTy}u<< +iNxn+'Kol7"IwޙU,wUɟRt|ʚ?OmIzIE'#"DyɸfG-%v`S7ITSAдںlr^W7y+{QdA*Z9_'0yS/6ux9K$ҏҰ o8tGf龉Jڀ„xf}me<1%1*i8]c@)ĈmM ~ݰzI{ !CK=\_9}`]+Md R r Jv>a4@xk =KNto2{rBӭ7&_oIO9NGiMUbRZMwe"m?BT\y\}R%ILl:UjTtmqxF<.d^|lh/N`/zIG,R*S78)@GS.s'lU6ۻ=[9+|y ҉} Vy{3y=`T9,_li0Y8V! cƜ>C竄90`fJ; Le;>7be*3zJB#"er,zynU|ӈ ȮwD1^4<π69BC6^ٙ9M>bO}mrzީNve^ 3 3-_+DI=_K$] M_ :PvW͎ Y$"!c 4ho̚TQSmAG3å= P`jAA nrY];P*z8M"h"h>^hTo:Fʓf+;wZ8L N,F<^d)-havʣ1q50U.},^ʟJtz~9˳NUw6q'݄21y@6{U`vA?W`Ͱ(7F5-+ީ5n3qbVe7q'@-g#uG0Hd3B6 VšO?~Jy|X^NA9D~Cȣ IHe>kεOς̖X?<9d纎^UѢS|wEt3 4Td>{A1zc3hv?IrogXab#5-Yҿ) @%JA*wL\TM0:.?v=V :yI/d͒ &/ Aw5ghЦF'|*zHmixɂGLI^cʝU-Î)%m/̚vۦRk;@6f.,¬6&ꚩD$UV)J}htʋwLG&D~XXml0: b8 VOK^?YxG]lǕp^v.1y mҴollʹu}٦q04m&>3[[ecM$ۛ}Ev| 2˸}BȻKGD=3,u?MnxԂP9%'g'%(&؞pЍhm6 b}(W$KW9ItSFw֝%a3?+}vp2-Hq:0,7w2`79ޗx,CE\.-r%}s3kwoA-S?Wu.CG U)Ptycد>  {#n/YY^ugUtv _Zoѻ1o9>~i1JhV #ڈrrj:zlD Rq2&\3ABLa؏h'~/Eo{AM-Ķh@:bˆ}Ws8mLXx80Y:tvN/6Ԝt"^pTږ6?v,dg,C_#)"%}*&sė)OQ'.){NLn%$QۺUP[suäOM*~ͻ!R];f CPʕFhL%—I9u[mN0C~GGz۩ircK\}x|7y3& K36H B"6^-Q[>o7V FŹ|dH L鷝NsvvX%+*pM޶Oqr TY [[bendstream endobj 247 0 obj << /Filter /FlateDecode /Length1 1417 /Length2 6088 /Length3 0 /Length 7047 >> stream xڍw4\m׶mDoA0ނ轎.fw%^"D!'Zt hQ޿I>}k:s{_gpv0U$/$*B $" 88h G"A2A @MOPH\ZHB @R(i2 nj"0wtBcu r$~\a(8@N0WLG(FB0JpsBݤ H7v<`(/=i.7 Gt@{CP0 O= Ĵ5zn0`?|?w($ w?#~'CP G8.0 !.HL> wa*!nh/`Yatu!_S`P uHoߦa1 Pq9@1$ɂa>P'_-|`BnH7,|= ^0  -E`p73(@! ;+̐#.&_**"}R@~a1P$![^}GE ( S:wEbfG@b ("K࿗'@\.B0CD ⿡?d{wT Ev~!?pU^:1K Gz=z0) 0><^<0';hMUP/ !(%¨{ā$ : Q_*) 4 [jD0J= e= &FPpO' K}3N̄^YUm~$_dMjN Z;7*dό/~`=gQ]qdK>N?6JVg,]jg!o&wlspV'{ߥ.R|I(KƼ!ήhIgμk麙lZOIes=]SmL-1^aK;w"*2]E L^^zgR۩Q_o/W{zQ|M:K/`rη\ "pԽ9G(3dWf FMЃ=(<3>bgOeǟD߻t?A5Ǹk)ⓍM40Ch9eK_$MB˅${x}8@ՒbȓO.hrP9ő-ڐzOUmscU2MVLLjM,v,עoo'}f|E(ĦM6e!O*Y`z`䙬]] ;pr^&fP`МzQWá޺lR>_KG׳+qj,d穞uUDt~xOa~Ŧ-]Oas۬7'^U*.@/3 0U$/eY(~%*siKk_^}5LmhIcCmtqvœWqz]=O'2ШB2\&ūA4 N/OpR'IIޅ1Y^تø [dd]ZޕWzTN46a%4]<=N## Z9mpc\Gd AYƬ6eOf|<ċԨV7OXv42ՙ ^ 1='\\nV~[,Ǵ N)ITE(y<ވ%|fǻV+j4||ATUL˜MHZ‰r5$Qy+?N%S(c_P }E.".<|JNoRNp6۔y=ÍwTX<xaQVwn8ssSb_V1vxITYs[bK-ˣ\pDBT#¢jZЕ^P$%ktM! 6swwx߮O&0_Ы+Z9=g+%rAq&/+SZp{i~:iØ烖5pB,=cj|E ZTʋH\*ҧFE[Sa{]@l_c8Q7[Enӯ?f?K/i4J= M$\3xQd%}m:ܴB\`U>=Wk$^Tx~# ~h,SBH#:H۸]AVz5MN?N"< M@+@Y# 'yaOo]NLQL9d7t+Y)!jZ% TcGAUn0eL WFRSc>&#B*뭶 ^7z\ȬcݑM;q\yb*!BuTWIWxݔ*Zj QP `ՔMF^lC}v ِ4B2c%7w\-jȣMFӆ2`Ȑ{S+\^g.v+;w2^#ϰң݊2-pl;V7vT9Hǻ?S&*r9'P j cE67A ddļQ0MeHRH"uLː =|l@!R""G%HUdp(!?éac"#Fk6 ɧA'bIֱ).L'֎ ymq֓[?-wުUj5~$J@Y9(PWaKT❚j IE:tzK-cͷ?}i\\ZwuUuX 6`@5B"%j*u:в5$h(5IM7}6RVy/$tǣpt7`Q ~B}-CCxꠜOpZ){^ }q*w߈2{ 3OsU0^$/~3O;̬($}ӵCIN4GzsD4aa.&׽=>.'tnY=(XuI ʭ5oLz2|pyt@EͷLo>w9zoNOԕϵw\&8zZ.̙ .Bn=Jnf]6X#B Th=R\b}"*) 9[lfmeLϚlrMDeSi]x 85+GLaRksOCK-N,nfUyV+(ݖbpLbYk*1&e/Je5EKOUe3j`FuVa2o=&9=&YAIG4i=7C)lXȳqpw֝q( sAO2 wLz9afO+b*]imKw%`dwFp#CCأ)pkyuqs!-<5qůE-˕=;E\]&Q vk6;~n1f> yUSKC> i1|SEQܼN'fQ2|8QPp7+C>GCxu3zVUjmӯ>C_?ƙG4wϮ|׳5-`o) Tq gNBF-jN3^41:9օQsXulZNYy8Xn Wi(痃cd5]juSD d(NSM<2)Ru!>m|,g(s1z5j o\Ƃ'?=F|vK:M(w\ n9< NyE+ujuU]F#^KT?` `$?~7!e&N摞Doh *B%Q/l >N}S#, lReM0aSk k{x"-_]T?fޟh=4–;ɧB }mS9Vq% IH( 2[6|ORE"8Y/i/K}p"ӵA{; Uf7 h*lClvnƉ("v4&CO_IÆw}M[sVwsϞ Ȱ^.|q򉴐thmݸ/lS2-8ߝ=t9Tzo :5t~,5h=] ޜ$c]٣7ƐppWX8: w(#v&!**qXp2Y jI7q{'YWPf@߷~wIXk84X;ȮUЅZwswl>O4p+6_H:)T|T(g^ >ku忹hFxe6KL}vn]܁GrOTl=v_vHl=ݰ}O:9BaN,J\yj SI[0'v_uJ!bj\>.<{GQ1J#&6-cc;բuG{}W7HkܹdH˙gL50'IFic)H("5èT~^3#ll2# 3bۭ, q8 Ir_M:Jv^}Ь[i$||-!f#?^ y=%`nA\yWcEwŖұE&J ۲<+2SsǷlUОfc#,srvǸ+4PJ.QY[DN RJrE=B+ю`"=4ēdFGMImmE`? *oQN].K6QJ&כ3qm; Q8n;yxw0&-+3ԊV2 {~&{Qq*1{tH2Ҕ$qsZ!utΐ\_~S>-ZEao fyY nNR2$ʙߑFs+F;=(R]{ҝz؍ciyu[n_ -Jp~ ŭvȧwY$Ej ^fgf~!-@rPXQUtD_ƕ@CsSl܉$O >Y¢B,ے :?p?4+4V%l7nP5̼7Zm4Ӄ**b2c^\W82Q`(k~rڊ%tEP]M-WezR(i[\6+}CG0L=V6HoT[p[7w uaukdJGlf?,h,+ w-p\٪n,;fDZ.W y[㋙5NMD? )nQ4~É9~V߸Iph8H5Tؔ*qnex v[Uqendstream endobj 248 0 obj << /Filter /FlateDecode /Length1 1409 /Length2 6135 /Length3 0 /Length 7094 >> stream xڍxT>R= !-  3 )%! J HK#Hw{}Ykw~9gf 3>="y|>>A>>ff0ێlraP@ȻlH- ԄAj _X_D '7.P4yj0(,sq;:!u~bb"\ w0 дE8\> !|&c 灹;Js'r~QhٺPa89a/[wi (m7/_.+ݟ_@ :@[IBm!p2 C~o$ E2t!1aa!~) tU یs8 i @{?? D@`(ο# |H~dT= 7wyu 4 U8PSN p ""B UgwQEyz ?cg-R ۿo'DwO)y@ l+Գ90@j k5A`"l3" uDꜛ1`dF@ր AF9z@G UaFP@H`n냃Tr%GΪ=kӧg5Ĕ$j y#ɃIjp9KDFb4ӅIZ}h JXo|ţhIv`cG<0껖~jNJˮL5Pb1 ZmOP\e' XIBD?ցй8/OjVHdġ(Su['%Lw)KɈO0& hdjaMӾ^R2E2M4=º=[%ڹ `Yw9ٔj!'ovLOEfW ˞Y;sxo"[eN ܰ~l &ao'kڎJKSbaeAưbHeSPhC[,Mpͯ$oY6jx*xH:.&Q"懎eU!Dc,ɡ g"HVx`%e/':^A_ZqOϼ&}dauv,R+hbD>^-=h!*4MPhxq+a-O=EI2AûnEOzVr՚0z%u#B"PUω5RݗH%x +a0NypD_prD1W[Um[VFl~WhM3>}3W=;kĴDV/2l*JU7VpK u.^EY4HV1-^gX4ZÓo& 5g,y&KԧKI,Kq lVvY0V~kJ&;'6_C?-c͕7H6K,#zcZQ嵐M\b: H3|?lZ>V> =5(8=|0n^cEY@ K%4"xW#KI3\L Nk)na"sK: e"d!ShzQnIdh6{X^3~8v2nd=W{~VD NO6 FgXȃ 8ʟZ~-c MRyUNlɋ1590$?&h;Zh*7R˴*#Pgb{֪ޭnj&(/ Ա丮#5f7T}o/#0Ԫ mMy_1q-M}Gۋs[k~ᖩ{hqKz;^7qY/*"TgBNjwehHiɮ\@}KR/̸<3!kX;J561ViuX bEO'R,%kV_Ғ nT@ : {Z;%xǘyocS9wj6[f(UADBI|W$(3V<0uSEP.7-NiF+ܣxMmOȭ)L{˹ZdVT5wHWݘm9A7|L6\'%TPP҅IAw.Uf= a⣝ n5w?|{#:],e ;.up;ciGaʤm|oDɯ!%gF/reϨ>/9_{;`sa^sξ۫Q85C j.::YLvbycEc9eG~)ŧYWH1ݡ)a:2LDqLwȭ#hxv&Я)-ߊ?g6&XAQ?o]H cx$<%6֯u4Tno/11ɨB><& h4Sٿl\TV~qXYE %P~MF49Xw7lBMIUa BՇ~GE ?$(qT}[6jl* K:tryXޭ;rU3OWO4q3$2+o/#d'JߟAa P+Γyݭ6_; E)^[W_bZgͰ~)n|نXtfJ~uKP I ^eDh{yFWkvʎ).4_%[%؞:[ASC6SUX63;۲X* _4 xYNfSsdR*pfD%v3J¬$38 qpY>TL]uz?*HԀwe{tzjM=oeEY5֎۵OL6z!eADZ.05 gkK~+s qgč)%H< 3KOƎ.5!NYSg0(^;[})B7}B"3bYkc}R؜+Zes&GnBXY~0מOr}_}gE> zh5dxD=if ,<(N2Q1;*O9 gb74PI D¤UGjx#.݃HO7; Ȼ v1R\Xމ:bR昶,a9%Q |_0R 75՗II=Hݩ&V}_Yk H_I<)F`_{܈/t^(I(uϪs9ż_9M.O!@>ڎԼ:3Ztg>MH.o_f=((OzTm=:CM4˘n۽J}'ף脇Zܺ(Jrm"f$Ր=jCzy ]#@Ld *1 x X%:f#f(\+Nf(Xk%6^B*ģVu6üz'bW'F&9>sP`pcv(ÏfG7b}9y8UꖜײZ*L.~+U•ryX#ktI-dޙ^؟JhÕZVr=c TLoA'|MXc`~Ű< 0*gR9ǭVbĜ"OQ.LH GͽOa$5n{}u216`˹30Ҕfuy~~8p_@a)EV}.Y!RLo͇5|V%\Y;Dk'O- k/o˽sZ)JP TjniǬǹvCoYէl܀ K?q/U2kcZ>D$-ܩt!`WE+VuR˹fEt/bRf@&NtjXrT/GI?lܭQcǔ q$is]#b8JqN+1UQwGŝܞͿ]#o2ԅ9R9{W7-n`^N+'xR }N~"QoWI }22ټI=3oeӻIqhKυeHv˼K˕pS]6/hze=/1|0eY9LJ*hwTtbt#@JT jm\k1E|З؏(5ۅK=نb*lw}ӟ~nɁ1Y}_ֶAT1X\ fNG]2tU'6' Qz~Oj0wn~my_endstream endobj 249 0 obj << /Filter /FlateDecode /Length1 1470 /Length2 6897 /Length3 0 /Length 7877 >> stream xڍw4\]6тDFeFE] 3 w;E'z zD I>}5g_w^gؘx H+2 (h@ ^M )&`{E0P@Ah"mD>882D`w PC".l H'/_K5'OLL;@YM5CZà^ !i$zxx]x([iNn uܡ/-#fl};r=p5pC@(zs܀?s;ܟ޿HG'0 Pce ^WOWne `w0 B>9, IsruuQ βtt"\]~OZO`C@l~9 0g7&h?2[+@Wx}/'o%/1 `&@/;r߈Y0?b]|` B{en/w}J54`N^  ||bBaN_K?'* :yp-8NwB{ @B ky~W@npo5o;^[=Hp (#֩!D2 цZAC@._W /zܬ׉ RUP4{K%5k` E.< | znltE6Hz rDV 1o'] BnBS 1PO5 Z"M۳j9:/Rl_ S9y|PmnDx/92-N^&YXS8g/%Q /cT jye7|:> rjPcqv%#?U+Q%NxU:kcT<Ŗk9MsוC}OI7Lj/vb }LO{/tҲҚ0` MVSR]d`1(F va,}a=ͷA kaq:lirjE'~='piI]'$]U(Cj^t@"NT_+N/z&"UҽqK03g`ey錙ZWo:-$?aΖg.'e4c#f݀AmC9aV'lՃdK Utuv璱B9>|+E110F2OjH$+ƒqaI=;PB2 !fjS=*NiB8zMĢ_J>fa30'q<>w[ChTRWHv{7U1:/Nxy;waBca"sG("Uj RSE^:R,OHMz$RyE/o ]z"'aeE VRT^I'i`}} -vep>P#ElDX ~I %n"S(]u:FfDr=P"աUm˙#ҍi:wo RR&r4"YgM&DnIf :hYW+9)5>ɪ L )S[qU=E bw"eH( (=/';ɏ2@Y=0\d[P+zN#BvBS#7l?[$]V(8LeT>O%HN j0yAA>Ƙ-j}aK1' KuOB"~eV`Yt㰨q>.II=!K,wbgt4rWX810& E*%,IL>q2%nL|dBhHءzgGB4Ҳ~ȘiVUVfHLSud:}lNM($J5mC8@1]mGĽhШc6@i_SR~̆}8܂caN^_DsAS_8uI| TmR_r$HTj8= Crqd |SFhTh80dyeHħHJ@i\9-.dqizOHFS`Ӗ:'S1'f-7r{gͲ::_vܰBDnE9y` súz~\#]F4=* O)(z{iGal#ܹp 惡إ"(Gl2AoMz8CdWx ҂շ8v&q"7p,G--wF!c6b, Iݺeΐ0(Y702t_E [Q}7NQ?,,'UC W2I9I=/LcOCukTLT{!P>[y-~D9|u"-njb&Ż58!_ں6hjȱӞ*|aAqL<7C9ֿCܢ1JDs.YW2%V;IbuԹvDh6n1W6#۞4Y4|}]USJ{Ev& ݚ(SMn|֡伆8 d?&BHʶaT~Ɠ\)ұpq02])kMۛ, 3 (B+eR3R'~}н~i;g;UՎP>7`ر l5* fR\SGO;{BklFӖ=@h(@qՄؽC_M] ̲Yh Q/]O@~ʙ%So6b LBqⲧግyB2#Wx a@;lȚJR Kϰר 귳$5"H Y)8fGA936 ۫ƃ\E !Tx4Ni(?^yVk2t`#MF;%'շli>oϞW'R+Ut\MjTxy˷6vKסoP%&sA7]}2:ZI$ -es ^Fɼv?WVs2W:HGHfu^d.@f[=*_R.Q#S[`=\B$y|SȕYde4pz}PPaUb !Vw"y+J B*TְXз+ś*;,ᾤvNV q߬oJ\ ק\I2#}zT{QOh{F|նɠ/t5^L z$*{\+1(Lkzڴq\2ə3-k0g|hﱴMG| 8:ޛZv({Y/((ĸaeR5\{|;Lm:>(]ץ֖A?ͷJ&v$,;GzOɄ//B{=&؏ K"_XH>,JrV8_BrixF&%Ȟ_c04D_.!io6eYvRYiN^Z ZA] dĻL.ϒ;q| 7omg0!=$ڂ{΋Z8S{C_ӻM%TieϾϽ,= &Ukir[wfgUR#w,CI@f2VCU,2UppN.$?o8<#8'h{^p"90zISZ :إsja?4rUk4.笺vnmt1W/LSdز֧aã` z[QE~ - oi3}vA&t*7 g-\K7JKxphN^ymZR[wZ(M߇l(w&שLx@̀Iյ\䢄&Saњ۬e]enP`bR= ZݼJoFʆYzW)Z4d(z*ѐ"xb!M̩ 8Z$ՓWܪo\JS"}87˪`vO^ܣ$RAv% !"y}뜖=(zzbReR{V5[xdoV-)X9+. 6Zh AwŜRǒ!=fRb[r /t ǺT`S{ߚjt7c&rR7:Q9ԋ&`|?V'cWy^m`jHާEP_㋴Qֿ/V[x!, &uf ]lTm"=c>edHohT?/r(.{y(?S:lWrOe j>n"ۣt~N:Zf\ΆB3:!nx˘N^瘮FNQv+6伐EӞmjA7e3]9$q{3٢&VB ]&TH!vf.iW$X|Ft eNݬ&֟Tiud%P x~ݸug.y n%^i/YF˾LNĢ+|D; 0|C'jR$VNy .rx.; éQEY%j._(T[* G+^60B&Q uT s0efT:l W1ܾ~U_YK'xdq<h g2[S=)3^Sdc0wn ¹7m#ҁnRQ${)YEYb,`yn76$te *(F"'^ت> stream xڍtT .! !9H! 9A 3 30P)tJ)!TD:D1wݻֽkzݽqCQ0+*!Th$$@(Ig"`d|V0T_{c/PH' !US@ߎ("@ ($̃O]e~B r7~a8.0ˊ0`aXTrbъb`w1YEu`0 ` vF&Fp{֛` p@!0e' . &ho?HI'ݟ蟉_`#}Hgaq0@]ƃpW`| <zy?!Ls9em$TCb=~ cY7$Gp#N?A@=H}OK?:g "3(S} B.AN?2? x `0g8jor8px= ?o􂢐W@Odb*l(OTJ *)#Pc5'> P rv ?#wc%a(\>$+FY_t<_f_ v#|8\2{yF@5%pOcסtFgp85c!.).#H)[vyo~`H $ed` C O@0/fŐ(e^ !Q98q?ĥ%(<_o`8lv ZqR-Zyo:CHoyFI*T9RO}CnU[PmߧȶoIv7ş9HE-6 v#l2˿)OiZHwݧﯘZ7ۨE~^1.g{/t1-ub(Uaگ8ã ڼ .$qR%~w%O.˫$d0s!{e"9)֝ B^-7(P:hsvwήZ~7?k;嵵*zB tmx@YSC7kRE2px)fgJ5֭"ʪl&;J_aYq^,_>T$! reēQ͊"mAT}g=#wlDJbTƈGtwrM w& ez(j&Cv ҾĒ~J+.)άMvVxtM;/M-WV U.jgޡ?pJ[$ *>yXއ]܉Jzo祝E0; < I#; egS q }0?)$e>|-UI`Ћ7dy_a[DG𾝱WQSl.un_9wgKq2D7)F\BJ/cx}7p Q1_X(n9v]ft\vG\$|v-ݴR'p/)vrf:=&_aT9zݘ>.gUf8n<†?yu1VܻU ~,i;}B?EXdWf Zc׹lEZ2OE>Bl5ǯ&;}vԟԍ٭5W8'*0fʈmSEBc)6ލ}u\WxPf Cs!kmCA 8^jJè`#AkɏFacy x /[* (4(Vc UO t2=bWZI_i[dRwvM w&"VeeZ_ ́W |Dz |.ii)"g˵{Y}4Oo9 [P4 VRʀfDv j?n-HV/hΏ!mXț]1SȞlHVA\V_deWTfY}kQ$h#gWĝ| -ᵪd vvwևM1}v1 J?򕛙@crWm"t%*~AS"YC\k,R#7+i"'|kstQQ /'1=; Q"pS=O;Վy wȎfw2,|z'Vmp˨RZDa6}wlD"Ԙg'=?rweFe6 w)l3WkAfzYykάv#*i.2E=(L3&$%,+4z,cs<80+ܫVw,vqVNSk *?eَMH2lo=RZ-ΉPBqP œ3f0]j th{WT%/`VrA&k5ݣ WHUmt| >Ma̽ӏBKr<uZ:bYz(;@ Ծ31E)06'yא!1[Fvquk#2PiˇkAξ߮Pa8)(tYVF4\~_60r̿඗tLA1u~%P)j{"3MI1TH+[@g˪[7mqcxnMFM(-Z~?zw[8LL@=kpZ[rw R6%U']/csu H^5 ^a̸*RPW9drg\RjnWZ}@kecVN&u霄'j!X\0r|d}MQ%k̃FMY F AgQ(RϏPJ Q׺8#qF]vdB,>ޙ>uk^I}Vv4'h M\jn̔tJPH9'nǘg[3YMU_\\+mOl ! .2#$_&N6ElնZ]z0[ڻC-lţJaʶ$J| սGWuح\ѷΈQ]x4p'$&.#:jV$r #Gd, 06]C|7%$ +e:WY%/;v5G*O>#"b2}eQ$}bnQ;xsCZZ>>7yuA|U T%,f+k\mI(1y"4|x,= dAG Gz/3Տ>U6 ;g/np!=򭛰Z]dNSx[i7.\{77 ARBR3g΃T4ۖl#-CT;TW 86薚ZF'c꾵PŚ@n(36"]"p[ȡBothyWtݭQr9^+bL5k}*,zl S8ɝonXfHqą{!ZmO>k`Рlu)Ux1u%zp:ddLՒ3<XņLAa8W;MUVW3_T̲uIB.g'9G"&쩆'FTj(ϲnX7Zv^* a |SJɌxzW Q$DIX>Gh8|=! 4H 9? .:?1s^D0syE6QzvdTo(EHf2_LJ_ ƙK}=^U+LG+ʅk >n8\\)ٔbfXY/WW~qAd}:w=Wq{C[{Oc =*_+bmd'a6'>#9ۂ ۝kQ}ǞDLj<tD+f3 _znve5$7{rhͧE%#,Ѓ" ٛHL V2Q9%`ZWNn$ hU^N兯4r4Eُ6׭^[("9}=T;MeqFוv[ͭA[fPXl[Xpƪu#6`kGqĨ}6+%w;fa;ͯEŶ7 )OЬH[y-8DcB4yLFC3 W^KmN|75:IJ-WSߔ0:u~t|Yq'꘽ vf}Ц=&> l< su[9%`ϮG æOy|f6Ҝ68']{b*8qO(蹅iJ)i¿ow(rMb > 5t-4G_Ud܍͸'\ES:93n W77^4.kN~vVҔ+7|gZ2RQjciН;żMձeQ72^#QmK\٭Y__,PAۂ&|5k #T}Ļ6D-xIܒ$ճTC6Y@cN4[iB'ή )HG SRjx n3IJUuC=F 6wAR+g"ơO{Ȓj&*x=q8Dc 3Cl?[TdZ9cP!nyVưHF헻Z:>u8M~;]R*_~2ȒByi\+`ymĎa_90Fn5$ %]TH߱y(g9yFhRCc6ٻSx y|aU4٭T|Q{{Ӂo Cł3E:cپq^*.4^,A2{: 2m84ɦ&Fqff}5M9֍l~I37Ͱ?VsVYqlMh&5p6: ~+\INܠ1EVvX<{VpU7J*d8ogl 16} Tzr VOzi Si]r5CLpehw:>WN t˟,XsB$ 8fR-Y$ߠVQ : e6 w n$/0dR+jlN@edHrAuv}oר5GJǩ-Nac?$8M<9vcK5 F~=Mg?Ks%u Mgd`;@UyM!mʟA#}"Gv,ڧP.7RA_́NU>Sfx絺3<=E d^|cwO]r+(Lr_l',U5F-};û M-?|վ| Y0uv_ fԣJKl>,Lwm7Uw6Y0T $Df?_2Vcn¸ ) f!cg W&>[MRȼ :鮏Q^kcP73B@U# q ,OiBԧWSYYe %󡫱e W$"tU|HZG+t(Dojm=k6AhLY@ǧmƛ_rRnK/ *[endstream endobj 251 0 obj << /Filter /FlateDecode /Length1 1955 /Length2 13874 /Length3 0 /Length 15073 >> stream xڍP CpBNݽ%kp ]K{g~_^u}uާ 2"eZA[#-#@XVLOFr%'S:8lmv:D dmmRVFf##;󿆶\C @ ekt'sw;g@aL `d h td ́ ʶ 1wr㢧wuu3vu0㣤J@G ]5Obtds_be[S'WC ]`28;8ۘʒ2y;_2s5F:ƿ@ ? m mA6fS /&CD01dehng1AE;s4v999`HGK189Qh~) &v6 {g,ÈNVvN&t36#O%=l S  <##d0l.;rh3#'2rҫ+hQIo@`d`f7O!?1Q/ օlguX0?]Q_#led;;o^_Su_K, 49[_fژY} G1Ddl@6@[G w)q|ԟ**oJQc[?v ``w d|_N۟s uzw:O6v?;^[8X*#N?7qF,Qޟ zAF=_@7de]b/]|gb/N_?z_|zZnkXM2G-~^ߩ8 /;wZ\i߽ktwW_g0މ8pO @~y֘;Ȣ.FוvowlO+%C#"L2eufí`pOQϓO^J{KS'px*^/^j-Rd }nc! {lghUtK汈haP.ܐnngQr&OѤ"2eT"m{k]Ɩ;wsA_pPwk˚ѫ[#Qj-Bmjݦx+3oyvO\]y9Rg_%1,L՟1_$qN,]GYkKVյnRo}t݆z§O抢WN0 / M0u&)WB{`dAѷXn w(T[\'a9mykj#9G8҄9[F%nyrkWy٧~Qh \pȝtXyi9Do3 lrap䎢2# Z iѼIfRt}lwb& {#[x#^\k}G2P[W[10ژf*vsTCUpHUVT$D1-G#9g.w8W.=wA0\_FgKP-t~t|9 o{@Ѭ5'9_4тs69{'%ݡ&fIcLf9+xrg λ?Ys8cA9Tu!w9#~ƒ9Q@Mn3~T%zZO[\kn:HdT0lˇX$iHdE]Y3SqyonARuJw_83MAWM`Vkr w}΃ )> l \gv#zio5ѮB?əoD4b N_ FKX? ܡV* k] Zx0^du`VXjrٗe=ng3{^B6:cl<+ӧʹn-L%W)I%ۚ= s%ǼhUc#@sMvB^ݖ2JpAcWo2Mg^bXWu铬ٱiR);&pџ 4G!Q=MK7}W=neRvQ,!`)Åw᷈ M6Q cfXw}*8z(?hG*|#6Ŗ zMnWq!#d["$VpSB)>>Y^p | {h枍$G!Xձ!bP>f?޳F^v JÒёx؈F9C쓽{U(R I7a1u6F,D5Lo!$NPffw?a֥c?zi i }[}죜2u _K5DxJw.՘[ߣ<%N+K>,hӒ Tєiu .P ynr|XϬw2+byq~0֞3ɢ0[18 nصfW.3݇9n~4r'^(=u t* t߱a)WEnoz(!ˮOQz̙9rzHOez+n7LASm\0F#U/V!{;] B#vc_J?'Bj")o/~8*?UH5EeRo㕛śg Xz PO$#r¸Ⱖٵy)W6>WYΔ2wa(if"Is=,3իS{%R뇊pCz/4gl1K~>~G|-TRqdÖe@4p?@u73lv EQjGĻb8ƒeVyBA{?nտgI >~58Qub?[sMMCBXOn-ck|+!o+єШMh\swJsb}ڮ_($w3|q0ɢl,M<1"H券sZޔB=;cH)mcGW%uuQmB%|LW9BG1Mng2a0*11wDVlvqJR,3%{"w@d # 9γBIh&al0) ;z6Xl̢ #G O7=؛u3e*3 ; yDgȢ+s-}ҽB5Ec) apfd{%i EӲ1QYRǯGH MBb=$LM[)ҏeiޕ@AIg5 yW<9x"]ePJ7@Xl3nhƏ8|B x:QPF"Vߑ[3-/)bJRC{e~erLm6-;Q\utC+ZySZõ6h51:l$| T> U?qJyzUU&=c}HS;՝ֽzf舰fL PS|繄{A(R& OE88,&ވ QTSFp>`l4=ؖ&la$Qu5ތԵ]DԥpC3|WFo8'| K-`؈ (#q*(i5D3%5;F4CFZ|RR@#Rx`&q&}X)&[wUPRW&17J&:GX@HCQ-!"-b/J8ie>N9p{V(*QRl:9F#1U?RPuOdKwkgo2VSKñ#c6~WT,W8TI=xY9ԣ㮧戮vr髦ЊILYoPkrn\{.NN71Ҭp-D~w t[*$RT TU\i 4`ˋQ~+ڡ PjQIնj%LE? wse:ss:#L Q$|W]Dc9 ~^ZKae)KTaއ2Ice7vE|%MZ+#p,x+< IMDWFpm0dD=F1rʄ,^4e՞Bw"Tp..;VdJ.TӲT֞a2HRCsߧ.O%$M;TE|@E-7 ftۥYjԾm:aR/P\z;?E7 5bh!XGϔ'ظ(_\TC1,XU3?6}a֗*aYY8IܹLwa9>2И>Ӊ^ĝ᭺3J?nHħ"jNF+~cxh+4  '>c7̗Ϯ4ykdrw G_u6;?>u^94ÞEqM+j.3Po~a 9}yc h6;Ng.eqG``"o;K@1C`V.CMxY?ZWO$qacЈj%c,:6uդҤ69)s纝< |Kaog,}l_f"T˵GEa"Er VDysdKVʻ93_f\+\"c]"]`cR̃B>`D=|[pPIuaq+l[(B"&5oobH:8g94-ۓ@3,U6Y6@t ic6o  ٮȫ.3A=ǭ/]iu.DPOU^DݍKce^X`V-"{GKQvr|]'VWt:PfG&{3/=,dm:c=Tt)K +bpb =vP2i-_o &smwli#"uz)"\Է|{+?jXZ.4ꘌz+9 k2V4k%D[URkN@G @յ2)WVz֕r0AnRsx'Yhr$; <Pa.qx]m^I|pU -R<*aޔBݸ|&I@̽0LӖK"9ȭV0Sb%ij4tԊ]5$=pUDszyXkXUPf'''b=E+K65ܠf-axֳG1~lzߚ kf8W)2$洔d?/5"8_0>I\QI$Ss ߇B,:XD~PJ7%L 2l@Nݗ$`(7D6PGg\*],vI{%.p]tQT6IYjp߉("ZnזcQ)e¨y3uyP,rzhg?J@#C}a8{byӥ3^kp i#~"yҴ^糚\j&ڍuoCU$Kj LuBJ{ڀX f3VJ)f\4DoR߂efn3P;֎ !˹M->3%hro^!>oM9=*^ʔd'gcC {CBRҧˤ6= N"@`P-~C qmc}~j9l? %c|D/lꢍi1i[(6wKЧ*Pyr75 ŵř@[?3iS:|*,Yu^au41(BH}3y7_JgBb= Ag^`y3DF&$oKevw6ɹȺTGim>e"ωxò/đ>\svPU.ȗ86A phOIlBK|F=J6]r)vb`!i /xNW`kY3 .z8y N pW]CKyְ%oRC \:9&B ~#/ t HDgA~μg?^mB8e=1fϼH㱩 MyRWsBxH$h́kSZ- &`eF6:X/ )tkjQ !׏24_%'.@/iu OKyeJ*BZ{q]3^o?3iP9EU:̫+BC "1Re+\ +Wpm98&ȸe%T-|-;@y@Qy3 OZiCTNAb!'ifS@Byc=Q#"HHINt1[ fvJT,3{)"J_:n#Ժ'X[믷aZD*712BBzHE qRi!,[7q%󟄖Au! X/`8fw@~0CW7"_R\ lH6JV:@&ז>K'չK[CES=SKo>%\]8wRRQlW8*r\׏8J|;gnͤ=/?NxI\S~wDob^O$, e1j_Fu9=弗5sBH[ ބ<{/w*U J3<. :#d7 =\ggH+"?u$Pi #I>+IK@B9Mz{4*z$y\lڃv7ADTƗ.! gႲl[mC=*<^L_R`WԔ2#C"wxVPn0@ptWʪ.M`ɛP)zp!ʹܢٶB[bY+*y -)wOeD0^h/An3K1Z{zscfU90Hx ؏ie6X/RY[zxkJ)O|kx3šmo[y**RKGB@{O &XG,WqՎUȣ=dH4oe,|$rU>"[fuZ͹nM ~^o{m28(ʹ-ǮQ (Y e}ԑ mrW%U YA-ĥ= HuZCO/ӒGSh  tؤ hɶXv00i|y_p޶^_g#^6ss)8D!Q#M F6Ј6kFCIOؽPTE`xkWBF~l{I P?{W"U ב׎vI闸aN~q$@gZl_5:nJ?B ~?]nwpWQĎP9+laL&MQso}ɉ!^UNWN''aP6YDGk-fVqL(>'|dS 'OkӒ=6(ic`3j-Nq-X,Cua ׸G]BhV:grKӓ>ic$Y' ~9Z>֥|<\S]CǓhz /U\uO,QDdN-mCtYn0 &+>M)]T&IldU* 7 Lw5kd8MB~V1+;>*#<R(U`nוRʷf#^vF235 ~Ok_$- , 9[ tv&'"n {-$n| 1J`X[)RMz1Y xWʒ~n~p^ }iڳ@2x& k_(N@u =`^?&mcd\VJKNRb+O6`9$QN~\8X'Y![/wdGt.%͖4dE7LH1mɐRh3J1cg(Kv"rϯfdKVI~1qgkΈK lLr[3zD䴺W䁹j$q\KܐO墹%fOSO#)hǴYK|KKr!v%q2r<%:v5 !D7Y s"P>k/CxpcOpK:\Q~ kⲵEW<|&SqC2-^T~Ec0y2ρ[v#q6M[̋YIˤm&uý+>)GɍnJ(J'zkUd,/ U+@3^oQVjO~Sg'D~{DR±T? Z۠dRurܩ3|^ M `Y';^m6~ȡ}Xk͗WW͞J;U=ё3 yb{荇CILk@^sBۚ웟R08W OmÈF]3$\!gL`fV0}2=<.0 a m `Ãμ 񠨭t|G!1o E-kjSH ND= ī}!6bVmq r &pn֙Yji]-?J;] H ppIlȯduL'5@e}C ngM$Mdr7HEc~>=~ꞙYЌٛPX.5a Q >dnVlwZhZMG>Twσ&>gr 0þgӪXM."A|ٵ 2 )7 15/pf[;y؋|niU"l9~4YE'yT9RwA_Kr~!]dz(U$s>ketDnA=vAL i4X]m=H @*?Vdr;:k>S! kH!YJeK/4iϹۑ+ݮJ}#X\=eQeāVendstream endobj 252 0 obj << /Type /XRef /Length 186 /Filter /FlateDecode /DecodeParms << /Columns 5 /Predictor 12 >> /W [ 1 3 1 ] /Info 72 0 R /Root 71 0 R /Size 253 /ID [<29acfab2aebb096acb5de21510195e77><22f349574fc9faffcccd282880aaa1b8>] >> stream xcb&F~0 $8Jj??. kP 3([b (-@$w'> R'1@l\iD.c?&.=@6R\[HU` 䂈IN+p$,rak RDH40(mȨ f R/a & endstream endobj startxref 233085 %%EOF vcd/man/0000755000175300001440000000000011720426624011454 5ustar meyerusersvcd/man/coindep_test.Rd0000644000175300001440000000751711150520606014425 0ustar meyerusers\name{coindep_test} \alias{coindep_test} \alias{fitted.coindep_test} \title{Test for (Conditional) Independence} \description{ Performs a test of (conditional) independence of 2 margins in a contingency table by simulation from the marginal distribution of the input table under (conditional) independence. } \usage{ coindep_test(x, margin = NULL, n = 1000, indepfun = function(x) max(abs(x)), aggfun = max, alternative = c("greater", "less"), pearson = TRUE) } \arguments{ \item{x}{a contingency table.} \item{margin}{margin index(es) or corresponding name(s) of the conditioning variables. Each resulting conditional table has to be a 2-way table.} \item{n}{number of (conditional) independence tables to be drawn.} \item{indepfun}{aggregation function capturing independence in (each conditional) 2-way table.} \item{aggfun}{aggregation function aggregating the test statistics computed by \code{indepfun}.} \item{alternative}{a character string specifying the alternative hypothesis; must be either \code{"greater"} (default) or \code{"less"} (and may be abbreviated.)} \item{pearson}{logical. Should the table of Pearson residuals under independence be computed and passed to \code{indepfun} (default) or the raw table of observed frequencies?} } \details{ If \code{margin} is \code{NULL} this computes a simple independence statistic in a 2-way table. Alternatively, \code{margin} can give several conditioning variables and then conditional independence in the resulting conditional table is tested. By default, this uses a (double) maximum statistic of Pearson residuals. By changing \code{indepfun} or \code{aggfun} a (maximum of) Pearson Chi-squared statistic(s) can be computed or just the usual Pearson Chi-squared statistics and so on. Other statistics can be computed by changing \code{pearson} to \code{FALSE}. The function uses \code{\link{r2dtable}} to simulate the distribution of the test statistic under the null. } \value{ A list of class \code{"coindep_test"} inheriting from \code{"htest"} with following components: \item{statistic}{the value of the test statistic.} \item{p.value}{the \eqn{p} value for the test.} \item{method}{a character string indicating the type of the test.} \item{data.name}{a character string giving the name(s) of the data.} \item{observed}{observed table of frequencies} \item{expctd}{expected table of frequencies} \item{residuals}{corresponding Pearson residuals} \item{margin}{the \code{margin} used} \item{dist}{a vector of size \code{n} with simulated values of the distribution of the statistic under the null.} \item{qdist}{the corresponding quantile function (for computing critical values).} \item{pdist}{the corresponding distribution function (for computing \eqn{p} values).} } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \seealso{ \code{\link{chisq.test}}, \code{\link{fisher.test}}, \code{\link{r2dtable}} } \examples{ TeaTasting <- matrix(c(3, 1, 1, 3), nr = 2, dimnames = list(Guess = c("Milk", "Tea"), Truth = c("Milk", "Tea")) ) ## compute maximum statistic coindep_test(TeaTasting) ## compute Chi-squared statistic coindep_test(TeaTasting, indepfun = function(x) sum(x^2)) ## use unconditional asymptotic distribution chisq.test(TeaTasting, correct = FALSE) chisq.test(TeaTasting) data("UCBAdmissions") ## double maximum statistic coindep_test(UCBAdmissions, margin = "Dept") ## maximum of Chi-squared statistics coindep_test(UCBAdmissions, margin = "Dept", indepfun = function(x) sum(x^2)) ## Pearson Chi-squared statistic coindep_test(UCBAdmissions, margin = "Dept", indepfun = function(x) sum(x^2), aggfun = sum) ## use unconditional asymptotic distribution loglm(~ Dept * (Gender + Admit), data = UCBAdmissions) } \keyword{htest} vcd/man/PreSex.Rd0000644000175300001440000000347011150520606013145 0ustar meyerusers\name{PreSex} \alias{PreSex} \docType{data} \title{Pre-marital Sex and Divorce} \description{ Data from Thornes \& Collard (1979), reported in Gilbert (1981), on pre- and extra-marital sex and divorce. } \usage{ data("PreSex") } \format{ A 4-dimensional array resulting from cross-tabulating 1036 observations on 4 variables. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab MaritalStatus \tab Divorced, Married \cr 2 \tab ExtramaritalSex \tab Yes, No \cr 3 \tab PremaritalSex \tab Yes, No \cr 4 \tab Gender \tab Women, Men } } \references{ G. N. Gilbert (1981), \emph{Modelling Society: An Introduction to Loglinear Analysis for Social Researchers}. Allen and Unwin, London. B. Thornes \& J. Collard (1979), \emph{Who Divorces?}. Routledge \& Kegan, London. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/marital.sas} } \examples{ data("PreSex") ## Mosaic display for Gender and Premarital Sexual Experience ## (Gender Pre) mosaic(margin.table(PreSex, c(3,4)), main = "Gender and Premarital Sex") ## (Gender Pre)(Extra) mosaic(margin.table(PreSex, c(2,3,4)), expected = ~Gender * PremaritalSex + ExtramaritalSex , main = "PreMaritalSex*Gender +Sex") ## (Gender Pre Extra)(Marital) mosaic(PreSex, expected = ~Gender*PremaritalSex*ExtramaritalSex + MaritalStatus, main = "PreMarital*ExtraMarital + MaritalStatus") ## (GPE)(PEM) mosaic(PreSex, expected = ~ Gender * PremaritalSex * ExtramaritalSex + MaritalStatus * PremaritalSex * ExtramaritalSex, main = "G*P*E + P*E*M") } \keyword{datasets} vcd/man/labeling_border.Rd0000644000175300001440000002526311720272464015066 0ustar meyerusers\name{labeling_border} \alias{labeling_border} \alias{labeling_conditional} \alias{labeling_left} \alias{labeling_left2} \alias{labeling_cboxed} \alias{labeling_lboxed} \alias{labeling_doubledecker} \alias{labeling_values} \alias{labeling_residuals} \alias{labelings} \title{Labeling Functions for Strucplots} \description{ These functions generate labeling functions used for strucplots. } \usage{ labeling_border(labels = TRUE, varnames = labels, set_labels = NULL, set_varnames = NULL, tl_labels = NULL, alternate_labels = FALSE, tl_varnames = NULL, gp_labels = gpar(fontsize = 12), gp_varnames = gpar(fontsize = 12, fontface = 2), rot_labels = c(0, 90, 0, 90), rot_varnames = c(0, 90, 0, 90), pos_labels = "center", pos_varnames = "center", just_labels = "center", just_varnames = pos_varnames, boxes = FALSE, fill_boxes = FALSE, offset_labels = c(0, 0, 0, 0), offset_varnames = offset_labels, labbl_varnames = NULL, labels_varnames = FALSE, sep = ": ", abbreviate_labs = FALSE, rep = TRUE, clip = FALSE, \dots) labeling_values(value_type = c("observed", "expected", "residuals"), suppress = NULL, digits = 1, clip_cells = FALSE, \dots) labeling_residuals(suppress = NULL, digits = 1, clip_cells = FALSE, \dots) labeling_conditional(\dots) labeling_left(rep = FALSE, pos_varnames = "left", pos_labels = "left", just_labels = "left", \dots) labeling_left2(tl_labels = TRUE, clip = TRUE, pos_varnames = "left", pos_labels = "left", just_labels = "left", \dots) labeling_cboxed(tl_labels = TRUE, boxes = TRUE, clip = TRUE, pos_labels = "center", \dots) labeling_lboxed(tl_labels = FALSE, boxes = TRUE, clip = TRUE, pos_labels = "left", just_labels = "left", labbl_varnames = FALSE, \dots) labeling_doubledecker(lab_pos = c("bottom", "top"), dep_varname = TRUE, boxes = NULL, clip = NULL, labbl_varnames = FALSE, rot_labels = rep.int(0, 4), pos_labels = c("left", "center", "left", "center"), just_labels = c("left", "left", "left", "center"), varnames = NULL, gp_varnames = gpar(fontsize = 12, fontface = 2), offset_varnames = c(0, -0.6, 0, 0), tl_labels = NULL, \dots) } \arguments{ \item{labels}{vector of logicals indicating whether labels should be drawn for a particular dimension.} \item{varnames}{vector of logicals indicating whether variable names should be drawn for a particular dimension.} \item{set_labels}{An optional character vector with named components replacing the so-specified variable names. The component names must exactly match the variable names to be replaced.} \item{set_varnames}{An optional list with named components of character vectors replacing the labels of the so-specified variables. The component names must exactly match the variable names whose labels should be replaced.} \item{tl_labels}{vector of logicals indicating whether labels should be positioned on top (column labels) / left (row labels) for a particular dimension.} \item{alternate_labels}{vector of logicals indicating whether labels should be alternated on the top/bottom (left/right) side of the plot for a particular dimension.} \item{tl_varnames}{vector of logicals indicating whether variable names should be positioned on top (column labels) / on left (row labels) for a particular dimension.} \item{gp_labels}{list of objects of class \code{"gpar"} used for drawing the labels.} \item{gp_varnames}{list of objects of class \code{"gpar"} used for drawing the variable names.} \item{rot_labels}{vector of rotation angles for the labels for each of the four sides of the plot.} \item{rot_varnames}{vector of rotation angles for the variable names for each of the four sides of the plot.} \item{pos_labels}{character string of label positions (\code{"left"}, \code{"center"}, \code{"right"}) for each of the variables.} \item{pos_varnames}{character string of variable names positions (\code{"left"}, \code{"center"}, \code{"right"}) for each of the four sides of the plot.} \item{just_labels}{character string of label justifications (\code{"left"}, \code{"center"}, \code{"right"}) for each of the variables.} \item{just_varnames}{character string of variable names justifications (\code{"left"}, \code{"center"}, \code{"right"}) for each of the four sides of the plot.} \item{boxes}{vector of logicals indicating whether boxes should be drawn around the labels for a particular dimension.} \item{fill_boxes}{Either a vector of logicals, or a vector of characters, or a list of such vectors, specifying the fill colors for the boxes. \code{"TRUE"} and \code{"FALSE"} values are transformed into \code{"grey"} and \code{"white"}, respectively. If \code{fill_boxes} is atomic, each component specifies a basic color for the corresponding dimension. This color is transformed into its HSV representation, and the value is varied from 50\% to 100\% to give a sequential color palette for the levels. For \code{NA} components, no palette is produced (no fill color). If \code{fill_boxes} is a list of vectors, each vector specifies the level colors of the corresponding dimension.} \item{offset_labels, offset_varnames}{numeric vector of length 4 indicating the offset of the labels (variable names) for each of the four sides of the plot.} \item{labbl_varnames}{vector of logicals indicating whether variable names should be drawn on the left (column variables) / on top (row variables) of the corresponding labels.} \item{labels_varnames}{vector of logicals indicating, for each dimension, whether the variable name should be added to the corresponding labels or not.} \item{sep}{separator used if any component of \code{"labels_varnames"} is \code{TRUE}.} \item{abbreviate_labs}{vector of integers or logicals indicating, for each dimension, the number of characters the labels should be abbreviated to. \code{TRUE} means 1 character, \code{FALSE} causes no abbreviation. Values are recycled as needed.} \item{rep}{vector of logicals indicating, for each dimension, whether labels should be repeated for all conditioning strata, or appear only once.} \item{clip}{vector of integers indicating, for each dimension, whether labels should be clipped to not overlap.} \item{lab_pos}{character string switching between \code{"top"} or \code{"bottom"} position of the labels (only used for \code{labeling_doubledecker}).} \item{dep_varname}{logical or character string. If logical, this is indicating whether the name of the dependent variable should be printed or not. A character string will be printed instead of the variable name taken from the dimnames.} \item{value_type}{character string specifying which values should be displayed in the cells.} \item{suppress}{numeric vector of length 2 specifying an interval of values that are not displayed. 0 values are never displayed. A single number, \var{k}, is treated as \code{c(-\var{k}, \var{k})}. The default for labeling residuals is \code{c(-2,2)}. Use \code{suppress = 0} to show all non-zero values.} \item{digits}{integer specifying the number of digits used for rounding.} \item{clip_cells}{logical indicating whether the values should be clipped at the cell borders.} \item{\dots}{only used for \code{labeling_conditional} and \code{labeling_doubledecker}: parameters passed to \code{labeling_cells} and \code{labeling_border}.} } \details{ These functions generate labeling functions called by \code{\link{strucplot}} for their side-effect of adding labels to the plot. They suppose that a strucplot has been drawn and the corresponding viewport structure is pushed, since the positions of the viewports are used for the label positioning. Note that the functions can also be used \sQuote{stand-alone} as shown in the examples. All values supplied to vectorized arguments can be \sQuote{abbreviated} by using named components which override the default component values. In addition, these defaults can be overloaded by the sequence of non-named components which are recycled as needed (see examples). This help page only documents \code{labeling_border} and derived functions, more functions are described on the help page for \code{\link{labeling_cells}} and \code{\link{labeling_list}}. \code{labeling_left}, \code{labeling_left2}, \code{labeling_cboxed}, and \code{labeling_lboxed} are really just wrappers to \code{labeling_border}, and good examples for the parameter usage. \code{labeling_residuals} is a trivial wrapper for \code{labeling_values}, which in turn calls \code{labeling_border} by additionally adding the observed or expected frequencies or residuals to the cells. } \value{ A function with arguments: \item{d}{\code{"dimnames"} attribute from the visualized contingency table, or the visualized table itself from which the \code{"dimnames"} attributes will then be extracted.} \item{split_vertical}{vector of logicals indicating the split directions.} \item{condvars}{integer vector of conditioning dimensions.} } \author{ David Meyer \email{David.Meyer@R-project.org} } \references{ Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \seealso{ \code{\link{labeling_cells}}, \code{\link{labeling_list}}, \code{\link{structable}}, \code{\link[grid]{grid.text}} } \examples{ data("Titanic") mosaic(Titanic) mosaic(Titanic, labeling = labeling_left) labeling_left mosaic(Titanic, labeling = labeling_cboxed) labeling_cboxed mosaic(Titanic, labeling = labeling_lboxed) labeling_lboxed data("PreSex") mosaic(~ PremaritalSex + ExtramaritalSex | Gender + MaritalStatus, data = PreSex, labeling = labeling_conditional) ## specification of vectorized arguments mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = TRUE))) mosaic(Titanic, labeling_args = list(clip = TRUE, boxes = TRUE, fill_boxes = c(Survived = "green", "red"))) mosaic(Titanic, labeling_args = list(clip = TRUE, boxes = TRUE, fill_boxes = list(Sex = "red", "green"))) mosaic(Titanic, labeling_args = list(clip = TRUE, boxes = TRUE, fill_boxes = list(Sex = c(Male = "red", "blue"), "green"))) ## change variable names mosaic(Titanic, labeling_args = list(set_varnames = c(Sex = "Gender"))) ## change labels mosaic(Titanic, labeling_args = list(set_varnames = c(Survived = "Status"), set_labels = list(Survived = c("Survived", "Not Survived")), rep = FALSE)) ## show frequencies mosaic(Titanic, labeling = labeling_values) } \keyword{hplot} vcd/man/CoalMiners.Rd0000644000175300001440000000274711150520606014001 0ustar meyerusers\name{CoalMiners} \alias{CoalMiners} \docType{data} \title{Breathlessness and Wheeze in Coal Miners} \description{ Data from Ashford & Snowden (1970) given by Agresti (1990) on the association between two pulmonary conditions, breathlessness and wheeze, in a large sample of coal miners. } \usage{ data("CoalMiners") } \format{ A 3-dimensional array resulting from cross-tabulating variables for 16,330 coal miners. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab Wheeze \tab W, NoW \cr 2 \tab Breathlessness \tab B, NoB \cr 3 \tab Age \tab 25-29, 30-34, \dots, 60-64 } } \references{ A. Agresti (1990), \emph{Categorical Data Analysis}. Wiley-Interscience, New York. J. R. Ashford \& R. D. Snowdon (1970), Multivariate probit analysis, \emph{Biometrics}, \bold{26}, 535--546. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data, pages 82--83, 319--322. } \examples{ data("CoalMiners") ## Fourfold display, both margins equated fourfold(CoalMiners, mfcol = c(2,4)) ## Log Odds Ratio Plot summary(l <- oddsratio(CoalMiners)) g <- seq(25, 60, by = 5) plot(l, xlab = "Age Group", main = "Breathlessness and Wheeze in Coal Miners") m <- lm(l ~ g + I(g^2)) lines(fitted(m), col = "red") ## Fourfold display, strata equated fourfold(CoalMiners, std = "ind.max", mfcol = c(2,4)) } \keyword{datasets} vcd/man/independence_table.Rd0000644000175300001440000000126111150520606015523 0ustar meyerusers\name{independence_table} \alias{independence_table} \title{Independence Table} \description{ Computes table of expected frequencies (under the null hypotheses of independence) from an \eqn{n}-way table. } \usage{ independence_table(x, frequency = c("absolute", "relative")) } \arguments{ \item{x}{a table.} \item{frequency}{indicates whether absolute or relative frequencies should be computed.} } \value{ A table with either absolute or relative frequencies. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("MSPatients") independence_table(MSPatients) independence_table(MSPatients, frequency = "relative") } \keyword{category} \keyword{array} vcd/man/spacings.Rd0000644000175300001440000000631311150520606013545 0ustar meyerusers\name{spacings} \alias{spacings} \alias{spacing_highlighting} \alias{spacing_equal} \alias{spacing_dimequal} \alias{spacing_increase} \alias{spacing_conditional} \title{Spacing-generating Functions} \description{ These functions generate spacing functions to be used with \code{\link{strucplot}} to obtain customized spaces between the elements of a strucplot. } \usage{ spacing_equal(sp = unit(0.3, "lines")) spacing_dimequal(sp) spacing_increase(start = unit(0.3, "lines"), rate = 1.5) spacing_conditional(sp = unit(0.3, "lines"), start = unit(2, "lines"), rate = 1.8) spacing_highlighting(start = unit(0.2, "lines"), rate = 1.5) } \arguments{ \item{start}{object of class \code{"unit"} indicating the start value for increasing spacings.} \item{rate}{increase rate for spacings.} \item{sp}{object of class \code{"unit"} specifying a fixed spacing.} } \details{ These generating functions return a function used by \code{\link{strucplot}} to generate appropriate spaces between tiles of a strucplot, using the \code{dimnames} information of the visualized table. \code{spacing_equal} allows to specify one fixed space for \emph{all} dimensions. \code{spacing_dimequal} allows to specify a fixed space for \emph{each} dimension. \code{spacing_increase} creates increasing spaces for all dimensions, based on a starting value and an increase rate. \code{spacing_conditional} combines \code{spacing_equal} and \code{spacing_increase} to create fixed spaces for conditioned dimensions, and increasing spaces for conditioning dimensions. \code{spacing_highlighting} is essentially \code{spacing_conditional} but with the space of the last dimension set to 0. With a corresponding color scheme, this gives the impression of the last class being \sQuote{highlighted} in the penultimate class (as, e.g., in \code{\link{doubledecker}} plots). } \value{ A spacing function with arguments: \item{d}{\code{"dim"} attribute of a contingency table.} \item{condvars}{index vector of conditioning dimensions (currently only used by \code{spacing_conditional}).} This function computes a list of objects of class \code{"unit"}. Each list element contains the spacing information for the corresponding dimension of the table. The length of the \code{"unit"} objects is \eqn{k-1}, \eqn{k} number of levels of the corresponding factor. } \author{ David Meyer \email{David.Meyer@R-project.org} } \references{ Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \seealso{ \code{\link{strucplot}}, \code{\link{doubledecker}} } \examples{ data("Titanic") strucplot(Titanic, spacing = spacing_increase(start = 0.5, rate = 1.5)) strucplot(Titanic, spacing = spacing_equal(1)) strucplot(Titanic, spacing = spacing_dimequal(1:4 / 4)) strucplot(Titanic, spacing = spacing_highlighting, gp = gpar(fill = c("light gray","dark gray"))) data("PreSex") strucplot(aperm(PreSex, c(1,4,2,3)), spacing = spacing_conditional, condvars = 2) } \keyword{hplot} vcd/man/mosaic.Rd0000644000175300001440000002401611474031017013213 0ustar meyerusers\name{mosaic} \alias{mosaic} \alias{mosaic.default} \alias{mosaic.formula} \title{Extended Mosaic Plots} \description{ Plots (extended) mosaic displays. } \usage{ \method{mosaic}{default}(x, condvars = NULL, split_vertical = NULL, direction = NULL, spacing = NULL, spacing_args = list(), gp = NULL, expected = NULL, shade = NULL, highlighting = NULL, highlighting_fill = grey.colors, highlighting_direction = NULL, zero_size = 0.5, zero_split = FALSE, zero_shade = NULL, zero_gp = gpar(col = 0), panel = NULL, main = NULL, sub = NULL, \dots) \method{mosaic}{formula}(formula, data, highlighting = NULL, \dots, main = NULL, sub = NULL, subset = NULL, na.action = NULL) } \arguments{ \item{x}{a contingency table in array form, with optional category labels specified in the \code{dimnames(x)} attribute, or an object of class \code{"structable"}.} \item{condvars}{vector of integers or character strings indicating conditioning variables, if any. The table will be permuted to order them first.} \item{formula}{a formula specifying the variables used to create a contingency table from \code{data}. For convenience, conditioning formulas can be specified; the conditioning variables will then be used first for splitting. If any, a specified response variable will be highlighted in the cells.} \item{data}{either a data frame, or an object of class \code{"table"} or \code{"ftable"}.} \item{subset}{an optional vector specifying a subset of observations to be used.} \item{na.action}{a function which indicates what should happen when the data contain \code{NA}s. Ignored if \code{data} is a contingency table.} \item{zero_size}{size of the bullets used for zero entries (if 0, no bullets are drawn).} \item{zero_split}{logical controlling whether zero cells should be further split. If \code{FALSE} and \code{zero_shade} is \code{FALSE}, only one bullet is drawn (centered) for unsplit zero cells. If \code{FALSE} and \code{zero_shade} is \code{TRUE}, a bullet for each zero cell is drawn to allow, e.g., residual-based shadings to be effective also for zero cells.} \item{zero_shade}{logical controlling whether zero bullets should be shaded. The default is \code{TRUE} if \code{shade} is \code{TRUE} or \code{expected} is not null or \code{gp} is not null, and \code{FALSE} otherwise.} \item{zero_gp}{object of class \code{"gpar"} used for zero bullets in case they are \emph{not} shaded.} \item{split_vertical}{vector of logicals of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (default: \code{FALSE}). Values are recycled as needed. A \code{TRUE} component indicates that the tile(s) of the corresponding dimension should be split vertically, \code{FALSE} means horizontal splits. Ignored if \code{direction} is not \code{NULL}.} \item{direction}{character vector of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (values are recycled as needed). For each component, a value of \code{"h"} indicates that the tile(s) of the corresponding dimension should be split horizontally, whereas \code{"v"} indicates vertical split(s).} \item{spacing}{spacing object, spacing function, or corresponding generating function (see \code{\link{strucplot}} for more information). The default is \code{spacing_equal} if \code{x} has two dimensions, \code{spacing_increase} for more dimensions, and \code{spacing_conditional} if conditioning variables are specified using \code{condvars} or the formula interface.} \item{spacing_args}{list of arguments for the generating function, if specified (see \code{\link{strucplot}} for more information).} \item{gp}{object of class \code{"gpar"}, shading function or a corresponding generating function (see details and \code{\link{shadings}}). Components of \code{"gpar"} objects are recycled as needed along the last splitting dimension. Ignored if \code{shade = FALSE}.} \item{shade}{logical specifying whether \code{gp} should be used or not (see \code{gp}). If \code{TRUE} and \code{expected} is unspecified, a default model is fitted: if \code{condvars} (see \code{\link{strucplot}}) is specified, a corresponding conditional independence model, and else the total independence model.} \item{expected}{optionally, an array of expected values of the same dimension as \code{x}, or alternatively the corresponding independence model specification as used by \code{\link[stats]{loglin}} or \code{\link[MASS]{loglm}} (see \code{\link{strucplot}}).} \item{highlighting}{character vector or integer specifying a variable to be highlighted in the cells.} \item{highlighting_fill}{color vector or palette function used for a highlighted variable, if any.} \item{highlighting_direction}{Either \code{"left"}, \code{"right"}, \code{"top"}, or \code{"bottom"} specifying the direction of highlighting in the cells.} \item{panel}{Optional function with arguments: \code{residuals}, \code{observed}, \code{expected}, \code{index}, \code{gp}, and \code{name} called by the \code{struc_mosaic} workhorse for each tile that is drawn in the mosaic. \code{index} is an integer vector with the tile's coordinates in the contingency table, \code{gp} a \code{gpar} object for the tile, and \code{name} a label to be assigned to the drawn grid object.} \item{main, sub}{either a logical, or a character string used for plotting the main (sub) title. If logical and \code{TRUE}, the name of the \code{data} object is used.} \item{\dots}{Other arguments passed to \code{\link{strucplot}}} } \details{ Mosaic displays have been suggested in the statistical literature by Hartigan and Kleiner (1984) and have been extended by Friendly (1994). \code{\link[graphics]{mosaicplot}} is a base graphics implementation and \code{mosaic} is a much more flexible and extensible grid implementation. \code{mosaic} is a generic function which currently has a default method and a formula interface. Both are high-level interfaces to the \code{\link{strucplot}} function, and produce (extended) mosaic displays. Most of the functionality is described there, such as specification of the independence model, labeling, legend, spacing, shading, and other graphical parameters. A mosaic plot is an area proportional visualization of a (possibly higher-dimensional) table of expected frequencies. It is composed of tiles (corresponding to the cells) created by recursive vertical and horizontal splits of a square. The area of each tile is proportional to the corresponding cell entry, \emph{given} the dimensions of previous splits. An \emph{extended} mosaic plot, in addition, visualizes the fit of a particular log-linear model. Typically, this is done by residual-based shadings where color and/or outline of the tiles visualize sign, size and possibly significance of the corresponding residual. The layout is very flexible: the specification of shading, labeling, spacing, and legend is modularized (see \code{\link{strucplot}} for details). In contrast to the \code{\link[graphics]{mosaicplot}} function in \pkg{graphics}, the splits start with the \emph{horizontal} direction by default to match the printed output of \code{\link{structable}}. } \value{ The \code{"structable"} visualized is returned invisibly. } \references{ Hartigan, J.A., and Kleiner, B. (1984), A mosaic of television ratings. \emph{The American Statistician}, \bold{38}, 32--35. Emerson, J. W. (1998), Mosaic displays in S-PLUS: A general implementation and a case study. \emph{Statistical Computing and Graphics Newsletter (ASA)}, \bold{9}, 1, 17--23. Friendly, M. (1994), Mosaic displays for multi-way contingency tables. \emph{Journal of the American Statistical Association}, \bold{89}, 190--200. Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL \url{http://www.jstatsoft.org/v17/i03/} and available as \code{vignette("strucplot", package = "vcd")}. The home page of Michael Friendly (\url{http://datavis.ca}) provides information on various aspects of graphical methods for analyzing categorical data, including mosaic plots. In particular, there are many materials for his course \dQuote{Visualizing Categorical Data with SAS and R} at \url{http://datavis.ca/courses/VCD/}. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{assoc}}, \code{\link{strucplot}}, \code{\link{mosaicplot}}, \code{\link{structable}}, \code{\link{doubledecker}} } \examples{ data("Titanic") mosaic(Titanic) ## Formula interface for tabulated data plus shading and legend: mosaic(~ Sex + Age + Survived, data = Titanic, main = "Survival on the Titanic", shade = TRUE, legend = TRUE) data("HairEyeColor") mosaic(HairEyeColor, shade = TRUE) ## Independence model of hair and eye color and sex. Indicates that ## there are significantly more blue eyed blond females than expected ## in the case of independence (and too few brown eyed blond females). mosaic(HairEyeColor, shade = TRUE, expected = list(c(1,2), 3)) ## Model of joint independence of sex from hair and eye color. Males ## are underrepresented among people with brown hair and eyes, and are ## overrepresented among people with brown hair and blue eyes, but not ## "significantly". ## Formula interface for raw data: visualize crosstabulation of numbers ## of gears and carburettors in Motor Trend car data. data("mtcars") mosaic(~ gear + carb, data = mtcars, shade = TRUE) data("PreSex") mosaic(PreSex, condvars = c(1,4)) mosaic(~ ExtramaritalSex + PremaritalSex | MaritalStatus + Gender, data = PreSex) ## Highlighting: mosaic(Survived ~ ., data = Titanic) data("Arthritis") mosaic(Improved ~ Treatment | Sex, data = Arthritis, zero_size = 0) mosaic(Improved ~ Treatment | Sex, data = Arthritis, zero_size = 0, highlighting_direction = "right") } \keyword{hplot} vcd/man/VonBort.Rd0000644000175300001440000000256611150520606013335 0ustar meyerusers\name{VonBort} \alias{VonBort} \docType{data} \title{Von Bortkiewicz Horse Kicks Data} \description{ Data from von Bortkiewicz (1898), given by Andrews \& Herzberg (1985), on number of deaths by horse or mule kicks in 14 corps of the Prussian army. } \usage{ data("VonBort") } \format{ A data frame with 280 observations and 4 variables. \describe{ \item{deaths}{number of deaths.} \item{year}{year of the deaths.} \item{corps}{factor indicating the corps.} \item{fisher}{factor indicating whether the corresponding corps was considered by Fisher (1925) or not.} } } \references{ D. F. Andrews \& A. M. Herzberg (1985), \emph{Data: A Collection of Problems from Many Fields for the Student and Research Worker}. Springer-Verlag, New York, NY. R. A. Fisher (1925), \emph{Statistical Methods for Research Workers}. Oliver & Boyd, London. L. von Bortkiewicz (1898), \emph{Das Gesetz der kleinen Zahlen}. Teubner, Leipzig. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/vonbort.sas} } \seealso{ \code{\link{HorseKicks}} for a popular subsample. } \examples{ data("VonBort") ## HorseKicks data xtabs(~ deaths, data = VonBort, subset = fisher == "yes") } \keyword{datasets} vcd/man/table2d_summary.Rd0000644000175300001440000000215011150520606015023 0ustar meyerusers\name{table2d_summary} \alias{table2d_summary} \alias{print.table2d_summary} \title{Summary of a 2-way Table} \description{ Prints a 2-way contingency table along with percentages, marginal, and conditional distributions. } \usage{ table2d_summary(object, margins = TRUE, percentages = FALSE, conditionals = c("none", "row", "column"), \dots) } \arguments{ \item{object}{a \eqn{r \times c}{r x c}-contingency table} \item{margins}{if \code{TRUE}, marginal distributions are computed.} \item{percentages}{if \code{TRUE}, relative frequencies are computed.} \item{conditionals}{if not \code{"none"}, the conditional distributions, given the row/column factor, are computed.} \item{\dots}{currently not used.} } \value{ Returns invisibly a \eqn{r \times c \times k}{r x c x k} table, \eqn{k} depending on the amount of choices (at most 3). } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{mar_table}}, \code{\link{prop.table}}, \code{\link{independence_table}} } \examples{ data("UCBAdmissions") table2d_summary(margin.table(UCBAdmissions, 1:2)) } \keyword{category} vcd/man/legends.Rd0000644000175300001440000000714711150520606013365 0ustar meyerusers\name{legends} \alias{legends} \alias{legend_resbased} \alias{legend_fixed} \title{Legend Functions for Strucplots} \description{ These functions generate legend functions for residual-based shadings. } \usage{ legend_resbased(fontsize = 12, x = unit(1, "lines"), y = unit(0.1,"npc"), height = unit(0.8, "npc"), width = unit(0.7, "lines"), digits = 3, check_overlap = TRUE, text = NULL, steps = 200, ticks = 10, pvalue = TRUE, range = NULL) legend_fixed(fontsize = 12, x = unit(1, "lines"), y = NULL, height = NULL, width = unit(1.5, "lines"), steps = 200, digits = 1, space = 0.05, text = NULL, range = NULL) } \arguments{ \item{fontsize}{fontsize of title and p-value text.} \item{x, y}{objects of class \code{"unit"} indicating the coordinates of the title. For \code{legend_fixed}, the default for \code{y} is computed as to leave enough space for the specified \code{text}.} \item{height, width}{object of class \code{"unit"} indicating the height/width of the legend. For \code{legend_fixed}, the default for \code{y} is computed as to align upper margins of legend and actual plot.} \item{digits}{number of digits for the scale labels.} \item{check_overlap}{logical indicating whether overlap of scale labels should be inhibited or not.} \item{space}{For \code{legend_fixed} only: proportion of space between the tiles.} \item{text}{character string indicating the title of the legend.} \item{steps}{granularity of the color gradient.} \item{ticks}{number of scale ticks.} \item{pvalue}{logical indicating whether the \eqn{p}-value should be visualized under the scale or not.} \item{range}{Numeric vector of length 2 for setting the legend range. Computed from the residuals if omitted. \code{NA} values are replaced by the corresponding minimum / maximum of the residuals.} } \value{ A function with arguments: \item{residuals}{residuals from the fitted independence model to be visualized.} \item{shading}{shading function computing colors from residuals (see details).} \item{autotext}{character vector indicating the title to be used when no \code{text} argument is specified. Allows strucplot to generate sensible defaults depending on the residuals type.} } \details{ These functions generate legend functions for residual-based shadings, visualizing deviations from expected values of an hypothesized independence model. Therefore, the legend uses a supplied shading function to visualize the color gradient for the residuals range. \code{legend_fixed} is inspired by the legend used in \code{\link[graphics]{mosaicplot}}. For more details on the shading functions and their return values, see \code{\link{shadings}}. } \references{ Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. Meyer, D., Zeileis, A., Hornik, K. (2003), Visualizing independence using extended association plots. \emph{Proceedings of the 3rd International Workshop on Distributed Statistical Computing}, K. Hornik, F. Leisch, A. Zeileis (eds.), ISSN 1609-395X. \url{http://www.ci.tuwien.ac.at/Conferences/DSC-2003/Proceedings/} } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{structable}}, \code{\link{shadings}} } \examples{ data("Titanic") mosaic(Titanic, shade = TRUE, legend = legend_resbased) mosaic(Titanic, shade = TRUE, legend = legend_fixed, gp = shading_Friendly) } \keyword{hplot} vcd/man/assocstats.Rd0000644000175300001440000000164311150520606014126 0ustar meyerusers\name{assocstats} \alias{assocstats} \alias{summary.assocstats} \alias{print.assocstats} \alias{print.summary.assocstats} \title{Association Statistics} \description{ Computes the Pearson chi-Squared test, the Likelihood Ratio chi-Squared test, the phi coefficient, the contingency coefficient and Cramer's V. } \usage{ assocstats(x) } \arguments{ \item{x}{an \eqn{r \times c}{r x c} table.} } \value{ A list with components: \item{chisq_tests}{a \eqn{2 \times 3}{2 x 3} table with the chi-squared statistics.} \item{phi}{The phi coefficient.} \item{cont}{The contingency coefficient.} \item{cramer}{Cramer's V.} } \references{ Michael Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("Arthritis") tab <- xtabs(~Improved + Treatment, data = Arthritis) summary(assocstats(tab)) } \keyword{category} vcd/man/WeldonDice.Rd0000644000175300001440000000223611150520606013753 0ustar meyerusers\name{WeldonDice} \alias{WeldonDice} \docType{data} \title{Weldon's Dice Data} \description{ Data from Pearson (1900) about the frequency of 5s and 6s in throws of 12 dice. Weldon tossed the dice 26,306 times and reported his results in a letter to Francis Galton on 1894-02-02. } \usage{ data("WeldonDice") } \format{ A 1-way table giving the frequency of a 5 or a 6 in 26,306 throws of 12 dice where 10 indicates \sQuote{10 or more} 5s or 6s. The variable and its levels are \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab n56 \tab 0, 1, \dots, 10 \cr } } \references{ K. Pearson (1900), On the criterion that a given system of deviations from the probable in the case of a correlated system of variables is such that it can be reasonably supposed to have arisen by random sampling, \emph{Philosophical Magazine}, \bold{50} (5th series), 157--175. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data, pages 20--21. } \examples{ data("WeldonDice") gf <- goodfit(WeldonDice, type = "binomial") summary(gf) plot(gf) } \keyword{datasets} vcd/man/rootogram.Rd0000644000175300001440000000556711150520606013761 0ustar meyerusers\name{rootogram} \alias{rootogram} \alias{rootogram.default} \alias{rootogram.goodfit} \title{Rootograms} \description{ Rootograms of observed and fitted values. } \usage{ \method{rootogram}{default}(x, fitted, names = NULL, scale = c("sqrt", "raw"), type = c("hanging", "standing", "deviation"), rect_gp = gpar(fill = "lightgray"), lines_gp = gpar(col = "red"), points_gp = gpar(col = "red"), pch = 19, xlab = NULL, ylab = NULL, ylim = NULL, name = "rootogram", newpage = TRUE, pop = TRUE, \dots) } \arguments{ \item{x}{either a vector or a 1-way table of frequencies.} \item{fitted}{a vector of fitted frequencies.} \item{names}{a vector of names passed to \code{\link{grid_barplot}}, if set to \code{NULL} the names of \code{x} are used.} \item{scale}{a character string indicating whether the values should be plotted on the raw or square root scale.} \item{type}{a character string indicating if the bars for the observed frequencies should be hanging or standing or indicate the deviation between observed and fitted frequencies.} \item{rect_gp}{a \code{"gpar"} object controlling the grid graphical parameters of the rectangles.} \item{lines_gp}{a \code{"gpar"} object controlling the grid graphical parameters of the lines.} \item{points_gp}{a \code{"gpar"} object controlling the grid graphical parameters of the points.} \item{pch}{plotting character for the points.} \item{xlab}{a label for the x axis.} \item{ylab}{a label for the y axis.} \item{ylim}{limits for the y axis.} \item{name}{name of the plotting viewport.} \item{newpage}{logical. Should \code{\link{grid.newpage}} be called before plotting?} \item{pop}{logical. Should the viewport created be popped?} \item{\dots}{further arguments passed to \code{\link{grid_barplot}}.} } \details{ The observed frequencies are displayed as bars and the fitted frequencies as a line. By default a sqrt scale is used to make the smaller frequencies more visible. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \references{ J. W. Tukey (1977), \emph{Exploratory Data Analysis}. Addison Wesley, Reading, MA. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \seealso{\code{\link{grid_barplot}}} \examples{ ## Simulated data examples: dummy <- rnbinom(200, size = 1.5, prob = 0.8) observed <- table(dummy) fitted1 <- dnbinom(as.numeric(names(observed)), size = 1.5, prob = 0.8) * sum(observed) fitted2 <- dnbinom(as.numeric(names(observed)), size = 2, prob = 0.6) * sum(observed) rootogram(observed, fitted1) rootogram(observed, fitted2) ## Real data examples: data("HorseKicks") HK.fit <- goodfit(HorseKicks) summary(HK.fit) plot(HK.fit) ## or equivalently rootogram(HK.fit) data("Federalist") F.fit <- goodfit(Federalist, type = "nbinomial") summary(F.fit) plot(F.fit) } \keyword{hplot} vcd/man/spine.Rd0000644000175300001440000001073711235655675013104 0ustar meyerusers\name{spine} \alias{spine} \alias{spine.default} \alias{spine.formula} \title{Spine Plots and Spinograms} \description{ Spine plots are a special cases of mosaic plots, and can be seen as a generalization of stacked (or highlighted) bar plots. Analogously, spinograms are an extension of histograms. } \usage{ spine(x, \dots) \method{spine}{default}(x, y = NULL, breaks = NULL, ylab_tol = 0.05, off = NULL, main = "", xlab = NULL, ylab = NULL, ylim = c(0, 1), margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "spineplot", newpage = TRUE, pop = TRUE, \dots) \method{spine}{formula}(formula, data = list(), breaks = NULL, ylab_tol = 0.05, off = NULL, main = "", xlab = NULL, ylab = NULL, ylim = c(0, 1), margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "spineplot", newpage = TRUE, pop = TRUE, \dots) } \arguments{ \item{x}{an object, the default method expects either a single variable (interpreted to be the explanatory variable) or a 2-way table. See details.} \item{y}{a \code{"factor"} interpreted to be the dependent variable} \item{formula}{a \code{"formula"} of type \code{y ~ x} with a single dependent \code{"factor"} and a single explanatory variable.} \item{data}{an optional data frame.} \item{breaks}{if the explanatory variable is numeric, this controls how it is discretized. \code{breaks} is passed to \code{\link{hist}} and can be a list of arguments.} \item{ylab_tol}{convenience tolerance parameter for y-axis annotation. If the distance between two labels drops under this threshold, they are plotted equidistantly.} \item{off}{vertical offset between the bars (in per cent). It is fixed to \code{0} for spinograms and defaults to \code{2} for spine plots.} \item{main, xlab, ylab}{character strings for annotation} \item{ylim}{limits for the y axis} \item{margins}{margins when calling \code{\link{plotViewport}}} \item{gp}{a \code{"gpar"} object controlling the grid graphical parameters of the rectangles. It should specify in particular a vector of \code{fill} colors of the same length as \code{levels(y)}. The default is to call \code{\link{gray.colors}}.} \item{name}{name of the plotting viewport.} \item{newpage}{logical. Should \code{\link{grid.newpage}} be called before plotting?} \item{pop}{logical. Should the viewport created be popped?} \item{\dots}{additional arguments passed to \code{\link{plotViewport}}.} } \details{ \code{spine} creates either a spinogram or a spine plot. It can be called via \code{spine(x, y)} or \code{spine(y ~ x)} where \code{y} is interpreted to be the dependent variable (and has to be categorical) and \code{x} the explanatory variable. \code{x} can be either categorical (then a spine plot is created) or numerical (then a spinogram is plotted). Additionally, \code{spine} can also be called with only a single argument which then has to be a 2-way table, interpreted to correspond to \code{table(x, y)}. Spine plots are a generalization of stacked bar plots where not the heights but the widths of the bars corresponds to the relative frequencies of \code{x}. The heights of the bars then correspond to the conditional relative frequencies of \code{y} in every \code{x} group. This is a special case of a mosaic plot with specific spacing and shading. Analogously, spinograms extend stacked histograms. As for the histogram, \code{x} is first discretized (using \code{\link{hist}}) and then for the discretized data a spine plot is created. } \value{ The table visualized is returned invisibly. } \seealso{ \code{\link{cd_plot}}, \code{\link{mosaic}}, \code{\link{hist}} } \references{ Hummel, J. (1996), Linked bar charts: Analysing categorical data graphically. \emph{Computational Statistics}, \bold{11}, 23--33. Hofmann, H., Theus, M. (2005), \emph{Interactive graphics for visualizing conditional distributions}, Unpublished Manuscript. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \examples{ ## Arthritis data (dependence on a categorical variable) data("Arthritis") (spine(Improved ~ Treatment, data = Arthritis)) ## Arthritis data (dependence on a numerical variable) (spine(Improved ~ Age, data = Arthritis, breaks = 5)) (spine(Improved ~ Age, data = Arthritis, breaks = quantile(Arthritis$Age))) (spine(Improved ~ Age, data = Arthritis, breaks = "Scott")) ## Space shuttle data (dependence on a numerical variable) data("SpaceShuttle") (spine(Fail ~ Temperature, data = SpaceShuttle, breaks = 3)) } \keyword{hplot} vcd/man/structable.Rd0000644000175300001440000001223311563233643014116 0ustar meyerusers\name{structable} \alias{structable.default} \alias{structable.formula} \alias{structable} \alias{Extract.structable} \alias{aperm.structable} \alias{t.structable} \alias{is.structable} \alias{cbind.structable} \alias{rbind.structable} \alias{length.structable} \alias{is.na.structable} \alias{as.matrix.structable} \alias{as.vector.structable} \alias{dim.structable} \alias{dimnames.structable} \alias{as.table.structable} \title{Structured Contingency Tables} \description{ This function produces a \sQuote{flat} representation of a high-dimensional contingency table constructed by recursive splits (similar to the construction of mosaic displays). } \usage{ \method{structable}{formula}(formula, data, direction = NULL, split_vertical = NULL, \dots, subset, na.action) \method{structable}{default}(\dots, direction = NULL, split_vertical = FALSE) } \arguments{ \item{formula}{a formula object with possibly both left and right hand sides specifying the column and row variables of the flat table.} \item{data}{a data frame, list or environment containing the variables to be cross-tabulated, or an object inheriting from class \code{table}.} \item{subset}{an optional vector specifying a subset of observations to be used. Ignored if \code{data} is a contingency table.} \item{na.action}{a function which indicates what should happen when the data contain \code{NA}s. Ignored if \code{data} is a contingency table} \item{\dots}{\R objects which can be interpreted as factors (including character strings), or a list (or data frame) whose components can be so interpreted, or a contingency table object of class \code{"table"} or \code{"ftable"}.} \item{split_vertical}{logical vector indicating, for each dimension, whether it should be split vertically or not (default: \code{FALSE}). Values are recycled as needed. If the argument is of length 1, the value is alternated for all dimensions. Ignored if \code{direction} is provided.} \item{direction}{character vector alternatively specifying the splitting direction (\code{"h"} for horizontal and \code{"v"} for vertical splits). Values are recycled as needed. If the argument is of length 1, the value is alternated for all dimensions.} } \details{ This function produces textual representations of mosaic displays, and thus \sQuote{flat} contingency tables. The formula interface is quite similar to the one of \code{\link{ftable}}, but also accepts the \code{\link{mosaic}}-like formula interface (empty left-hand side). Note that even if the \code{\link{ftable}} interface is used, the \code{split_vertical} or \code{direction} argument is needed to specify the \emph{order} of the horizontal and vertical splits. If pretabulated data with a \code{Freq} column is used, than the left-hand side should be left empty---the \code{Freq} column will be handled correctly. \code{"structable"} objects can be subset using the \code{[} and \code{[[} operators, using either level indices or names (see examples). The corresponding replacement functions are available as well. In addition, appropriate \code{\link{aperm}}, \code{\link{cbind}}, \code{\link{rbind}}, \code{\link{length}}, \code{\link{dim}}, and \code{\link{is.na}} methods do exist. } \value{ An object of class \code{"structable"}, inheriting from class \code{"ftable"}, with the splitting information (\code{"split_vertical"}) as additional attribute. } \author{ David Meyer \email{David.Meyer@R-project.org} } \references{ Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \seealso{ \code{\link{strucplot}}, \code{\link{mosaic}}, \code{\link[stats]{ftable}} } \examples{ structable(Titanic) structable(Titanic, split_vertical = c(TRUE, TRUE, FALSE, FALSE)) structable(Titanic, direction = c("h","h","v","v")) structable(Sex + Class ~ Survived + Age, data = Titanic) ## subsetting of structable objects (hec <- structable(aperm(HairEyeColor))) ## The "[" operator treats structables as a block-matrix and selects parts of the matrix: hec[1] hec[2] hec[1,c(2,4)] hec["Male",c("Blue","Green")] ## replacement funcion: tmp <- hec (tmp[1,2:3] <- tmp[2,c(1,4)]) ## In contrast, the "[[" operator treats structables as two-dimensional ## lists. Indexing conditions on specified levels and thus reduces the dimensionality: ## seek subtables conditioning on levels of the first dimension: hec[[1]] hec[[2]] ## Seek subtable from the first two dimensions, given the level "Male" ## of the first variable, and "Brown" from the second ## (the following two commands are equivalent): hec[["Male"]][["Brown"]] hec[[c("Male","Brown")]] ## Seeking subtables by conditioning on row and/or column variables: hec[["Male","Hazel"]] hec[[c("Male","Brown"),]] hec[[c("Male","Brown"),"Hazel"]] ## a few other operations t(hec) dim(hec) dimnames(hec) as.matrix(hec) length(hec) cbind(hec[,1],hec[,3]) as.vector(hec) ## computed on the _multiway_ table as.vector(unclass(hec)) } \keyword{hplot} vcd/man/NonResponse.Rd0000644000175300001440000000164511150520606014212 0ustar meyerusers\name{NonResponse} \alias{NonResponse} \docType{data} \title{Non-Response Survey Data} \description{ Data about non-response for a Danish survey in 1965. } \usage{ data("NonResponse") } \format{ A data frame with 12 observations and 4 variables. \describe{ \item{Freq}{frequency.} \item{residence}{factor indicating whether residence was in Copenhagen, in a city outside Copenhagen or at the countryside (Copenhagen, City, Country).} \item{response}{factor indicating whether a response was given (yes, no).} \item{gender}{factor indicating gender (male, female).} } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, Table 5.17. } \examples{ data("NonResponse") structable(~ ., data = NonResponse) } \keyword{datasets} vcd/man/SexualFun.Rd0000644000175300001440000000276611150520606013660 0ustar meyerusers\name{SexualFun} \alias{SexualFun} \docType{data} \title{Sex is Fun} \description{ Data from Hout et al. (1987) given by Agresti (1990) summarizing the responses of married couples to the questionnaire item: Sex is fun for me and my partner: (a) never or occasionally, (b) fairly often, (c) very often, (d) almost always. } \usage{ data("SexualFun") } \format{ A 2-dimensional array resulting from cross-tabulating the ratings of 91 married couples. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab Husband \tab Never Fun, Fairly Often, Very Often, Always Fun \cr 2 \tab Wife \tab Never Fun, Fairly Often, Very Often, Always Fun } } \references{ A. Agresti (1990), \emph{Categorical Data Analysis}. Wiley-Interscience, New York. M. Hout, O. D. Duncan, M. E. Sobel (1987), Association and heterogeneity: Structural models of similarities and differences, \emph{Sociological Methodology}, \bold{17}, 145-184. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data, page 91. } \examples{ data("SexualFun") ## Kappa statistics Kappa(SexualFun) ## Agreement Chart agreementplot(t(SexualFun), weights = 1) ## Partial Agreement Chart and B-Statistics agreementplot(t(SexualFun), xlab = "Husband's Rating", ylab = "Wife's Rating", main = "Husband's and Wife's Sexual Fun") } \keyword{datasets} vcd/man/sieve.Rd0000644000175300001440000001513411236051237013056 0ustar meyerusers\name{sieve} \alias{sieve} \alias{sieve.default} \alias{sieve.formula} \title{Extended Sieve Plots} \encoding{UTF-8} \description{ (Extended) sieve displays for n-way contingency tables: plots rectangles with areas proportional to the expected cell frequencies and filled with a number of squares equal to the observed frequencies. Thus, the densities visualize the deviations of the observed from the expected values. } \usage{ \method{sieve}{default}(x, condvars = NULL, gp = NULL, shade = NULL, legend = FALSE, split_vertical = NULL, direction = NULL, spacing = NULL, spacing_args = list(), sievetype = c("observed","expected"), gp_tile = gpar(), main = NULL, sub = NULL, \dots) \method{sieve}{formula}(formula, data, \dots, main = NULL, sub = NULL, subset = NULL) } \arguments{ \item{x}{a contingency table in array form, with optional category labels specified in the \code{dimnames(x)} attribute.} \item{condvars}{vector of integers or character strings indicating conditioning variables, if any. The table will be permuted to order them first.} \item{formula}{a formula specifying the variables used to create a contingency table from \code{data}. For convenience, conditioning formulas can be specified; the conditioning variables will then be used first for splitting. Formulas for sieve displays (unlike those for doubledecker plots) have no response variable.} \item{data}{either a data frame, or an object of class \code{"table"} or \code{"ftable"}.} \item{subset}{an optional vector specifying a subset of observations to be used.} \item{shade}{logical specifying whether \code{gp} should be used or not (see \code{gp}). If \code{TRUE} and \code{expected} is unspecified, a default model is fitted: if \code{condvars} is specified, a corresponding conditional independence model, and else the total independence model. If \code{shade} is \code{NULL} (default), \code{gp} is used if specified.} \item{sievetype}{logical indicating whether rectangles should be filled according to \code{observed} or \code{expected} frequencies.} \item{gp}{object of class \code{"gpar"}, shading function or a corresponding generating function (see details of \code{\link{strucplot}} and \code{\link{shadings}}). Components of \code{"gpar"} objects are recycled as needed along the last splitting dimension. The default is a modified version of \code{\link{shading_Friendly}}: if \code{sievetype} is \code{"observed"}, cells with positive residuals are painted with a red sieve, and cells with negative residuals with a blue one. If \code{sievetype} is \code{"expected"}, the sieves' color is gray. Ignored if \code{shade = FALSE}.} \item{gp_tile}{object of class \code{"gpar"}, controlling the appearance of all \emph{static} elements of the cells (e.g., border and fill color).} \item{legend}{either a legend-generating function, a legend function (see details of \code{\link{strucplot}} and \code{\link{legends}}), or a logical value. If \code{legend} is \code{NULL} or \code{TRUE} and \code{gp} is a function, legend defaults to \code{\link{legend_resbased}}.} \item{split_vertical}{vector of logicals of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (default: \code{FALSE}). Values are recycled as needed. A \code{TRUE} component indicates that the tile(s) of the corresponding dimension should be split vertically, \code{FALSE} means horizontal splits. Ignored if \code{direction} is not \code{NULL}.} \item{direction}{character vector of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (values are recycled as needed). For each component, a value of \code{"h"} indicates that the tile(s) of the corresponding dimension should be split horizontally, whereas \code{"v"} indicates vertical split(s).} \item{spacing}{spacing object, spacing function, or corresponding generating function (see \code{\link{strucplot}} for more information). The default is no spacing at all if \code{x} has two dimensions, and \code{spacing_increase} for more dimensions.} \item{spacing_args}{list of arguments for the generating function, if specified (see \code{\link{strucplot}} for more information).} \item{main, sub}{either a logical, or a character string used for plotting the main (sub) title. If logical and \code{TRUE}, the name of the \code{data} object is used.} \item{\dots}{Other arguments passed to \code{\link{strucplot}}} } \details{ \code{sieve} is a generic function which currently has a default method and a formula interface. Both are high-level interfaces to the \code{\link{strucplot}} function, and produce (extended) sieve displays. Most of the functionality is described there, such as specification of the independence model, labeling, legend, spacing, shading, and other graphical parameters. The layout is very flexible: the specification of shading, labeling, spacing, and legend is modularized (see \code{\link{strucplot}} for details). } \value{ The \code{"structable"} visualized is returned invisibly. } \note{To be faithful to the original definition by Riedwyl & Schüpbach, the default is to have no spacing between the tiles for two-way tables.} \references{ H. Riedwyl & M. Schüpbach (1994), Parquet diagram to plot contingency tables. In F. Faulbaum (ed.), \emph{Softstat '93: Advances in Statistical Software}, 293--299. Gustav Fischer, New York. M. Friendly (2000), Visualizing Categorical Data, SAS Institute, Cary, NC. David Meyer, Achim Zeileis, and Kurt Hornik (2006). The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{assoc}}, \code{\link{strucplot}}, \code{\link{mosaic}}, \code{\link{structable}}, \code{\link{doubledecker}} } \examples{ data("HairEyeColor") ## aggregate over 'sex': (tab <- margin.table(HairEyeColor, c(2,1))) ## plot expected values: sieve(tab, sievetype = "expected", shade = TRUE) ## plot observed table: sieve(tab, shade = TRUE) ## plot complete diagram: sieve(HairEyeColor, shade = TRUE) ## an example for the formula interface: data("VisualAcuity") sieve(Freq ~ right + left, data = VisualAcuity) ## example with observed values in the cells: sieve(Titanic, pop = FALSE, shade = TRUE) labeling_cells(text = Titanic, gp_text = gpar(fontface = 2))(Titanic) } \keyword{hplot} vcd/man/co_table.Rd0000644000175300001440000000162011264574713013520 0ustar meyerusers\name{co_table} \alias{co_table} \title{Compute Conditional Tables} \description{ For a contingency table in array form, compute a list of conditional tables given some margins. } \usage{ co_table(x, margin, collapse = ".") } \arguments{ \item{x}{a contingency table in array form.} \item{margin}{margin index(es) or corresponding name(s) of the conditioning variables.} \item{collapse}{character used when collapsing level names (if more than 1 \code{margin} is specified).} } \details{ This is essentially an interface to \code{\link[base]{[}} which is more convenient for arrays of arbitrary dimension. } \value{ A list of the resulting conditional tables. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \examples{ data("HairEyeColor") co_table(HairEyeColor, 1) co_table(HairEyeColor, c("Hair", "Eye")) co_table(HairEyeColor, 1:2, collapse = "") } \keyword{array} vcd/man/Rochdale.Rd0000644000175300001440000000233011150520606013452 0ustar meyerusers\name{Rochdale} \alias{Rochdale} \docType{data} \title{Rochdale Data} \description{ Information on 665 households of Rochdale, Lancashire, UK. The study was conducted to identify influence factors on economical activity of wives. } \usage{ data("Rochdale") } \format{ A 8-dimensional array resulting from cross-tabulating 665 observations on 8 variables. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab EconActive \tab yes, no \cr 2 \tab Age \tab <38, >38 \cr 3 \tab HusbandEmployed \tab yes, no \cr 4 \tab Child \tab yes, no \cr 5 \tab Education \tab yes, no \cr 6 \tab HusbandEducation \tab yes, no \cr 7 \tab Asian \tab yes, no \cr 8 \tab HouseholdWorking \tab yes, no \cr } } \note{ Many observations are missing: only 91 out of all 256 combinations contain information. } \source{ Whittaker (1990). } \references{ H. Hofmann (2003). Constructing and reading mosaicplots. \emph{Computational Statistics & Data Analysis}, \bold{43}, 4, 565--580. J. Whittaker (1990), \emph{Graphical Models on Applied Multivariate Statistics}, Wiley, New York. } \examples{ data("Rochdale") mosaic(Rochdale) } \keyword{datasets} vcd/man/Lifeboats.Rd0000644000175300001440000000275011150520606013647 0ustar meyerusers\name{Lifeboats} \alias{Lifeboats} \docType{data} \title{Lifeboats on the Titanic} \description{ Data from Mersey (1912) about the 18 (out of 20) lifeboats launched before the sinking of the S. S. Titanic. } \usage{data("Lifeboats")} \format{ A data frame with 18 observations and 8 variables. \describe{ \item{launch}{launch time in \code{"\link{POSIXt}"} format.} \item{side}{factor. Side of the boat.} \item{boat}{factor indicating the boat.} \item{crew}{number of male crew members on board.} \item{men}{number of men on board.} \item{women}{number of women (including female crew) on board.} \item{total}{total number of passengers.} \item{cap}{capacity of the boat.} } } \references{ L. Mersey (1912), Report on the loss of the \dQuote{Titanic} (S. S.). Parliamentary command paper 6452. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/lifeboat.sas} } \examples{ data("Lifeboats") attach(Lifeboats) ternaryplot( Lifeboats[,4:6], pch = ifelse(side == "Port", 1, 19), col = ifelse(side == "Port", "red", "blue"), id = ifelse(men / total > 0.1, as.character(boat), NA), prop_size = 2, dimnames_position = "edge", main = "Lifeboats on the Titanic" ) grid_legend(0.8, 0.9, c(1, 19), c("red", "blue"), c("Port", "Starboard"), title = "SIDE") detach(Lifeboats) } \keyword{datasets} vcd/man/panel_pairs_diagonal.Rd0000644000175300001440000001251011235655426016102 0ustar meyerusers\name{Pairs plot panel functions for diagonal cells} \alias{pairs_barplot} \alias{pairs_text} \alias{pairs_diagonal_text} \alias{pairs_diagonal_mosaic} \title{Diagonal Panel Functions for Table Pairs Plot} \description{ Diagonal panel functions for \code{\link{pairs.table}}. } \usage{ pairs_barplot(gp_bars = NULL, gp_vartext = gpar(fontsize = 17), gp_leveltext = gpar(), just_leveltext = c("center", "bottom"), just_vartext = c("center", "top"), rot = 0, abbreviate = FALSE, check_overlap = TRUE, fill = "grey", var_offset = unit(1, "npc"), \dots) pairs_text(dimnames = TRUE, gp_vartext = gpar(fontsize = 17), gp_leveltext = gpar(), gp_border = gpar(), \dots) pairs_diagonal_text(varnames = TRUE, gp_vartext = gpar(fontsize = 17, fontface = "bold"), gp_leveltext = gpar(), gp_border = gpar(), pos = c("right","top"), distribute = c("equal","margin"), rot = 0, \dots) pairs_diagonal_mosaic(split_vertical = TRUE, margins = unit(0, "lines"), offset_labels = -0.4, offset_varnames = 0, gp = NULL, fill = "grey", ...) } \arguments{ \item{dimnames}{vector of logicals indicating whether the factor levels should be displayed (only used for \code{pairs_text}).} \item{varnames}{vector of logicals indicating whether the variable names should be displayed (only used for \code{pairs_text_diagonal}).} \item{gp_bars}{object of class \code{"gpar"} used for bars (only used for \code{pairs_barplot}). If unspecified, the default is to set the \code{fill} component of this object to the \code{fill} argument.} \item{gp_vartext}{object of class \code{"gpar"} used for the factor names.} \item{gp_leveltext}{object of class \code{"gpar"} used for the factor levels.} \item{gp_border}{object of class \code{"gpar"} used for the border (only used for \code{pairs_text}).} \item{gp}{object of class \code{"gpar"} used for the tiles (only used for \code{pairs_diagonal_mosaic}). If unspecified, the default is to set the \code{fill} component of this object to the \code{fill} argument.} \item{fill}{color vector or palette function used for the fill colors of bars (for \code{pairs_barplot}) or tiles (for \code{pairs_diagonal_mosaic}).} \item{just_leveltext, just_vartext}{character string indicating the justification for variable names and levels.} \item{pos}{character string of length 2 controlling the horizontal and vertical position of the variable names (only used for \code{pairs_text_diagonal}).} \item{rot}{rotation angle for the variable levels.} \item{distribute}{character string indicating whether levels should be distributed equally or according to the margins (only used for \code{pairs_text_diagonal}).} \item{abbreviate}{integer or logical indicating the number of characters the labels should be abbreviated to. \code{TRUE} means 1 character, \code{FALSE} causes no abbreviation.} \item{check_overlap}{If \code{TRUE}, some levels will suppressed to avoid overlapping, if any.} \item{split_vertical}{vector of logicals of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (values are recycled as needed). A \code{TRUE} component indicates that the tile(s) of the corresponding dimension should be split vertically, \code{FALSE} means horizontal splits. Default is \code{FALSE.}} \item{margins}{either an object of class \code{"unit"} of length 4, or a numeric vector of length 4. The elements are recycled as needed. The four components specify the top, right, bottom, and left margin of the plot, respectively. When a numeric vector is supplied, the numbers are interpreted as \code{"lines"} units. In addition, the unit or numeric vector may have named arguments (\samp{top}, \samp{right}, \samp{bottom}, and \samp{left}), in which case the non-named arguments specify the default values (recycled as needed), overloaded by the named arguments.} \item{offset_labels, offset_varnames}{numeric vector of length 4 indicating the offset of the labels (variable names) for each of the four sides of the plot.} \item{var_offset}{object of class \code{"unit"} specifying the offset of variable names from the bottom of the bar plots created by \code{pairs_barplot}. If numeric, the unit defaults to "npc".} \item{\dots}{other parameters passed to the underlying graphics functions.} } \details{ In the diagonal cells, the pairsplot visualizes statistics or information for each dimension (that is: the single factors) alone. \code{\link{pairs_text}} displays the factor's name, and optionally also the factor levels. \code{\link{pairs_barplot}} produces a bar plot of the corresponding factor, along with the factor's name. } \value{ A function with one argument: the marginal table for the corresponding dimension. } \seealso{ \code{\link{pairs.table}}, \code{\link{pairs_assoc}}, \code{\link{pairs_mosaic}} } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("UCBAdmissions") pairs(UCBAdmissions) # pairs_barplot is default pairs(UCBAdmissions, diag_panel = pairs_text) pairs(UCBAdmissions, diag_panel = pairs_diagonal_text) pairs(Titanic, diag_panel = pairs_diagonal_text) pairs(Titanic, diag_panel = pairs_diagonal_text(distribute = "margin")) pairs(Titanic, diag_panel = pairs_diagonal_text(distribute = "margin", rot = 45)) } \keyword{hplot} vcd/man/Punishment.Rd0000644000175300001440000000274311150520606014073 0ustar meyerusers\name{Punishment} \alias{Punishment} \docType{data} \title{Corporal Punishment Data} \description{ Data from a study of the Gallup Institute in Denmark in 1979 about the attitude of a random sample of 1,456 persons towards corporal punishment of children. } \usage{ data("Punishment") } \format{ A data frame with 36 observations and 5 variables. \describe{ \item{Freq}{frequency.} \item{attitude}{factor indicating attitude: (no, moderate) punishment of children.} \item{memory}{factor indicating whether the person had memories of corporal punishment as a child (yes, no).} \item{education}{factor indicating highest level of education (elementary, secondary, high).} \item{age}{factor indicating age group in years (15-24, 25-39, 40-).} } } \note{Anderson (1991) erroneously indicates the total sum of respondents to be 783.} \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, pages 207--208. } \examples{ data("Punishment", package = "vcd") pun <- xtabs(Freq ~ memory + attitude + age + education, data = Punishment) ## model: ~ (memory + attitude) * age * education ## use maximum sum-of-squares test/shading cotabplot(~ memory + attitude | age + education, data = pun, panel = cotab_coindep, n = 5000, type = "assoc", test = "maxchisq", interpolate = 1:2) } \keyword{datasets} vcd/man/cd_plot.Rd0000644000175300001440000000737511150520606013373 0ustar meyerusers\name{cd_plot} \alias{cd_plot} \alias{cd_plot.default} \alias{cd_plot.formula} \title{Conditional Density Plots} \description{ Computes and plots conditional densities describing how the distribution of a categorical variable \code{y} changes over a numerical variable \code{x}. } \usage{ cd_plot(x, \dots) \method{cd_plot}{default}(x, y, plot = TRUE, ylab_tol = 0.05, bw = "nrd0", n = 512, from = NULL, to = NULL, main = "", xlab = NULL, ylab = NULL, margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "cd_plot", newpage = TRUE, pop = TRUE, \dots) \method{cd_plot}{formula}(formula, data = list(), plot = TRUE, ylab_tol = 0.05, bw = "nrd0", n = 512, from = NULL, to = NULL, main = "", xlab = NULL, ylab = NULL, margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "cd_plot", newpage = TRUE, pop = TRUE, \dots) } \arguments{ \item{x}{an object, the default method expects either a single numerical variable.} \item{y}{a \code{"factor"} interpreted to be the dependent variable} \item{formula}{a \code{"formula"} of type \code{y ~ x} with a single dependent \code{"factor"} and a single numerical explanatory variable.} \item{data}{an optional data frame.} \item{plot}{logical. Should the computed conditional densities be plotted?} \item{ylab_tol}{convenience tolerance parameter for y-axis annotation. If the distance between two labels drops under this threshold, they are plotted equidistantly.} \item{bw, n, from, to, \dots}{arguments passed to \code{\link{density}}} \item{main, xlab, ylab}{character strings for annotation} \item{margins}{margins when calling \code{\link{plotViewport}}} \item{gp}{a \code{"gpar"} object controlling the grid graphical parameters of the rectangles. It should specify in particular a vector of \code{fill} colors of the same length as \code{levels(y)}. The default is to call \code{\link{gray.colors}}.} \item{name}{name of the plotting viewport.} \item{newpage}{logical. Should \code{\link{grid.newpage}} be called before plotting?} \item{pop}{logical. Should the viewport created be popped?} } \details{ \code{cd_plot} computes the conditional densities of \code{x} given the levels of \code{y} weighted by the marginal distribution of \code{y}. The densities are derived cumulatively over the levels of \code{y}. This visualization technique is similar to spinograms (see \code{\link{spine}}) but they do not discretize the explanatory variable, but rather use a smoothing approach. Furthermore, the original x axis and not a distorted x axis (as for spinograms) is used. This typically results in conditional densities that are based on very few observations in the margins: hence, the estimates are less reliable there. } \value{ The conditional density functions (cumulative over the levels of \code{y}) are returned invisibly. } \seealso{ \code{\link{spine}}, \code{\link{density}} } \references{ Hofmann, H., Theus, M. (2005), \emph{Interactive graphics for visualizing conditional distributions}, Unpublished Manuscript. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \examples{ ## Arthritis data data("Arthritis") cd_plot(Improved ~ Age, data = Arthritis) cd_plot(Improved ~ Age, data = Arthritis, bw = 3) cd_plot(Improved ~ Age, data = Arthritis, bw = "SJ") ## compare with spinogram spine(Improved ~ Age, data = Arthritis, breaks = 3) ## Space shuttle data data("SpaceShuttle") cd_plot(Fail ~ Temperature, data = SpaceShuttle, bw = 2) ## scatter plot with conditional density cdens <- cd_plot(Fail ~ Temperature, data = SpaceShuttle, bw = 2, plot = FALSE) plot(I(-1 * (as.numeric(Fail) - 2)) ~ jitter(Temperature, factor = 2), data = SpaceShuttle, xlab = "Temperature", ylab = "Failure") lines(53:81, cdens[[1]](53:81), col = 2) } \keyword{hplot} vcd/man/RepVict.Rd0000644000175300001440000000264411150520606013315 0ustar meyerusers\name{RepVict} \alias{RepVict} \docType{data} \title{Repeat Victimization Data} \description{ Data from Reiss (1980) given by Fienberg (1980) about instances of repeat victimization for households in the U.S. National Crime Survey. } \usage{ data("RepVict") } \format{ A 2-dimensional array resulting from cross-tabulating victimization. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab First Victimization \tab Rape, Assault, Robbery, Pickpocket, Personal Larceny, \cr \tab \tab Burglary, Household Larceny, Auto Theft \cr 2 \tab Second Victimization \tab Rape, Assault, Robbery, Pickpocket, Personal Larceny,\cr \tab \tab Burglary, Household Larceny, Auto Theft } } \references{ S. E. Fienberg (1980), \emph{The Analysis of Cross-Classified Categorical Data}, MIT Press, Cambridge, 2nd edition. A. J. J. Reiss (1980), Victim proneness by type of crime in repeat victimization. In S. E. Fienberg & A. J. J. Reiss (eds.), \emph{Indicators of Crime and Criminal Justice}. U.S. Government Printing Office, Washington, DC. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data, page 113. } \examples{ data("RepVict") mosaic(RepVict[-c(4,7),-c(4,7)], gp = shading_max, main = "Repeat Victimization Data") } \keyword{datasets} vcd/man/strucplot.Rd0000644000175300001440000002626011150520606014000 0ustar meyerusers\name{strucplot} \alias{strucplot} \title{Structured Displays of Contingency Tables} \description{ This modular function visualizes certain aspects of high-dimensional contingency tables in a hierarchical way. } \usage{ strucplot(x, residuals = NULL, expected = NULL, condvars = NULL, shade = NULL, type = c("observed", "expected"), residuals_type = NULL, df = NULL, split_vertical = NULL, spacing = spacing_equal, spacing_args = list(), gp = NULL, gp_args = list(), labeling = labeling_border, labeling_args = list(), core = struc_mosaic, core_args = list(), legend = NULL, legend_args = list(), main = NULL, sub = NULL, margins = unit(3, "lines"), title_margins = NULL, legend_width = NULL, main_gp = gpar(fontsize = 20), sub_gp = gpar(fontsize = 15), newpage = TRUE, pop = TRUE, keep_aspect_ratio = NULL, prefix = "", \dots) } \arguments{ \item{x}{a contingency table in array form, with optional category labels specified in the \code{dimnames} attribute.} \item{residuals}{optionally, an array of residuals of the same dimension as \code{x} (see details).} \item{expected}{optionally, an array of expected values of the same dimension as \code{x}, or alternatively the corresponding independence model specification as used by \code{\link[stats]{loglin}} or \code{\link[MASS]{loglm}} (see details).} \item{df}{degrees of freedom passed to the shading functions used for inference. Will be calculated (and overwritten if specified) if both \code{expected} and \code{residuals} are \code{NULL}, or if \code{expected} is given a formula.} \item{condvars}{number of conditioning variables, if any; those are expected to be ordered first in the table. This information is used for computing the expected values, and is also passed to the spacing functions (see \code{\link{spacings}}).} \item{shade}{logical specifying whether \code{gp} should be used or not (see \code{gp}). If \code{TRUE} and \code{expected} is unspecified, a default model is fitted: if \code{condvars} is specified, a corresponding conditional independence model, and else the total independence model.} \item{residuals_type}{a character string indicating the type of residuals to be computed when none are supplied. If \code{residuals} is \code{NULL}, \code{residuals_type} must be one of \code{"pearson"} (default; giving components of Pearson's chi-squared), \code{"deviance"} (giving components of the likelihood ratio chi-squared), or \code{"FT"} for the Freeman-Tukey residuals. The value of this argument can be abbreviated. If \code{residuals} are specified, the value of \code{residuals_type} is just passed \dQuote{as is} to the legend function.} \item{type}{a character string indicating whether the observed or the expected values of the table should be visualized.} \item{split_vertical}{vector of logicals of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (values are recycled as needed). A \code{TRUE} component indicates that the tile(s) of the corresponding dimension should be split vertically, \code{FALSE} means horizontal splits. Default is \code{FALSE.}} \item{spacing}{spacing object, spacing function, or a corresponding generating function (see details and \code{\link{spacings}}).} \item{spacing_args}{list of arguments for the spacing-generating function, if specified.} \item{gp}{object of class \code{"gpar"}, shading function or a corresponding generating function (see details and \code{\link{shadings}}). Components of \code{"gpar"} objects are recycled as needed along the last splitting dimension. Ignored if \code{shade = FALSE}.} \item{gp_args}{list of arguments for the shading-generating function, if specified.} \item{labeling}{either a logical, or a labeling function, or a corresponding generating function (see details and \code{\link{labelings}}. If \code{FALSE} or \code{NULL}, no labeling is produced.} \item{labeling_args}{list of arguments for the labeling-generating function, if specified.} \item{core}{either a core function, or a corresponding generating function (see details). Currently, generating functions for mosaic plots (\code{\link{struc_mosaic}}), association plots (\code{\link{struc_assoc}}), and sieve plots (\code{\link{struc_sieve}}) are provided.} \item{core_args}{list of arguments for the core-generating function, if specified.} \item{legend}{either a legend-generating function, or a legend function (see details and \code{\link{legends}}), or a logical. If \code{legend} is \code{NULL} or \code{TRUE} and \code{gp} is a function, legend defaults to \code{\link{legend_resbased}}.} \item{legend_args}{list of arguments for the legend-generating function, if specified.} \item{main}{either a logical, or a character string used for plotting the main title. If \code{main} is a logical and \code{TRUE}, the name of the object supplied as \code{x} is used.} \item{sub}{a character string used for plotting the subtitle. If \code{sub} is a logical and \code{TRUE} and \code{main} is unspecified, the name of the object supplied as \code{x} is used.} \item{margins}{either an object of class \code{"unit"} of length 4, or a numeric vector of length 4. The elements are recycled as needed. The four components specify the top, right, bottom, and left margin of the plot, respectively. When a numeric vector is supplied, the numbers are interpreted as \code{"lines"} units. In addition, the unit or numeric vector may have named arguments (\samp{top}, \samp{right}, \samp{bottom}, and \samp{left}), in which case the non-named arguments specify the default values (recycled as needed), overloaded by the named arguments.} \item{title_margins}{either an object of class \code{"unit"} of length 2, or a numeric vector of length 2. The elements are recycled as needed. The two components specify the top and bottom \emph{title} margin of the plot, respectively. The default for each \emph{specified} title are 2 lines (and 0 else), except when a legend is plotted and \code{keep_aspect_ratio} is \code{TRUE}: in this case, the default values of both margins are set as to align the heights of legend and actual plot. When a numeric vector is supplied, the numbers are interpreted as \code{"lines"} units. In addition, the unit or numeric vector may have named arguments (\samp{top} and \samp{bottom}), in which case the non-named argument specify the default value (recycled as needed), overloaded by the named arguments.} \item{legend_width}{An object of class \code{"unit"} of length 1 specifying the width of the legend (if any). Default: 5 lines.} \item{pop}{logical indicating whether the generated viewport tree should be removed at the end of the drawing or not.} \item{main_gp, sub_gp}{object of class \code{"gpar"} containing the graphical parameters used for the main (sub) title, if specified.} \item{newpage}{logical indicating whether a new page should be created for the plot or not.} \item{keep_aspect_ratio}{logical indicating whether the aspect ratio should be fixed or not. If unspecified, the default is \code{TRUE} for two-dimensional tables and \code{FALSE} otherwise.} \item{prefix}{optional character string used as a prefix for the generated viewport and grob names.} \item{\dots}{For convenience, list of arguments passed to the labeling-generating function used.} } \details{ This function---usually called by higher-level functions such as \code{\link{assoc}} and \code{\link{mosaic}}---generates conditioning plots of contingency tables. First, it sets up a set of viewports for main- and subtitles, legend, and the actual plot region. Then, residuals are computed as needed from observed and expected frequencies, where the expected frequencies are optionally computed for a specified independence model. Finally, the specified functions for spacing, gp, main plot, legend, and labeling are called to produce the plot. The function invisibly returns the \code{"structable"} object visualized. Most elements of the plot, such as the core function, the spacing between the tiles, the shading of the tiles, the labeling, and the legend, are modularized in graphical appearance control (``grapcon'') functions and specified as parameters. For each element \emph{foo} (= \code{spacing}, \code{labeling}, \code{core}, or \code{legend}), \code{strucplot} takes two arguments: \var{foo} and \var{foo\_args}, which can be used to specify the parameters in the following alternative ways: \enumerate{ \item Passing a suitable function to \var{foo} which subsequently will be called from \code{strucplot} to compute shadings, labelings, etc. \item Passing a corresponding \emph{generating} function to \var{foo}, along with parameters passed to \var{foo\_args}, that generates such a function. Generating functions must inherit from classes \code{"grapcon_generator"} and \code{"}\var{foo}\code{"}. \item Except for the shading functions (\var{shading\_bar}), passing \var{foo(foo\_args)} to the \var{foo} argument. \item For shadings and spacings, passing the final parameter object itself; see the corresponding help pages for more details on the data structures. } If legends are drawn, a \sQuote{cinemascope}-like layout is used for the plot to preserve the 1:1 aspect ratio. If \code{type = "expected"}, the expected values are passed to the \code{observed} argument of the core function, and the observed values to the \code{expected} argument. Although the \code{gp} argument is typically used for shading, it can be used for arbitrary modifications of the tiles' graphics parameters (e.g., for highlighting particular cells, etc.). } \note{ The created viewports, as well as the tiles and bullets, are named and thus can conveniently modified after a plot has been drawn (and \code{pop = FALSE}). } \value{ Invisibly, an object of class \code{"structable"} corresponding to the plot. } \author{ David Meyer \email{David.Meyer@R-project.org} } \references{ Meyer D., Zeileis A., and Hornik K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \seealso{ \code{\link{assoc}}, \code{\link{mosaic}}, \code{\link{sieve}}, \code{\link{struc_assoc}}, \code{\link{struc_sieve}}, \code{\link{struc_mosaic}}, \code{\link{structable}}, \code{\link{doubledecker}}, \code{\link{labelings}}, \code{\link{shadings}}, \code{\link{legends}}, \code{\link{spacings}} } \examples{ data("Titanic") strucplot(Titanic) strucplot(Titanic, core = struc_assoc) strucplot(Titanic, spacing = spacing_increase, spacing_args = list(start = 0.5, rate = 1.5)) strucplot(Titanic, spacing = spacing_increase(start = 0.5, rate = 1.5)) ## modify a tile's color strucplot(Titanic, pop = FALSE) grid.edit("rect:Class=1st,Sex=Male,Age=Adult,Survived=Yes", gp = gpar(fill = "red")) } \keyword{hplot} vcd/man/Suicide.Rd0000644000175300001440000000211711150520606013321 0ustar meyerusers\name{Suicide} \alias{Suicide} \docType{data} \title{Suicide Rates in Germany} \description{ Data from Heuer (1979) on suicide rates in West Germany classified by age, sex, and method of suicide. } \usage{ data("Suicide") } \format{ A data frame with 306 observations and 6 variables. \describe{ \item{Freq}{frequency of suicides.} \item{sex}{factor indicating sex (male, female).} \item{method}{factor indicating method used.} \item{age}{age (rounded).} \item{age.group}{factor. Age classified into 5 groups.} \item{method2}{factor indicating method used (same as \code{method} but some levels are merged).} } } \references{ J. Heuer (1979), \emph{Selbstmord bei Kindern und Jugendlichen}. Ernst Klett Verlag, Stuttgart. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/suicide.sas} } \examples{ data("Suicide") structable(~ sex + method2 + age.group, data = Suicide) } \keyword{datasets} vcd/man/Hitters.Rd0000644000175300001440000000327611150520606013365 0ustar meyerusers\name{Hitters} \alias{Hitters} \docType{data} \title{Hitters Data} \description{ This data set is deduced from the \code{\link{Baseball}} fielding data set: fielding performance basically includes the numbers of Errors, Putouts and Assists made by each player. In order to reduce the number of observations, the was compressed by calculating the mean number of errors, putouts and assists for each team and for only 6 positions (1B, 2B, 3B, C, OF, SS and UT). In addition, each of these three variables was scaled to a common range by dividing each variable by the maximum of the variable. } \usage{data("Hitters")} \format{ A data frame with 154 observations and 4 variables. \describe{ \item{Positions}{factor indicating the field position (1B=first baseman, 2B=second baseman, 3B=third baseman, C=catcher, OF=outfielder, SS=Short Stop, UT=Utility Players).} \item{Putouts}{occur when a fielder causes an opposing player to be tagged or forced out.} \item{Assists}{are credited to other fielders involved in making that putout.} \item{Errors}{count the errors made by a player.} } } \references{ M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ SAS System for Statistical Graphics, First Edition, Page A2.3 } \examples{ data("Hitters") attach(Hitters) colors <- c("black","red","green","blue","red","black","blue") pch <- substr(levels(Positions), 1, 1) ternaryplot(Hitters[,2:4], pch = as.character(Positions), col = colors[as.numeric(Positions)], main = "Baseball Hitters Data") grid_legend(0.8, 0.9, pch, colors, levels(Positions), title = "POSITION(S)") detach(Hitters) } \keyword{datasets} vcd/man/Federalist.Rd0000644000175300001440000000204311150520606014014 0ustar meyerusers\name{Federalist} \alias{Federalist} \docType{data} \title{`May' in Federalist Papers} \description{ Data from Mosteller & Wallace (1984) investigating the use of certain keywords (\sQuote{may} in this data set) to identify the author of 12 disputed \sQuote{Federalist Papers} by Alexander Hamilton, John Jay and James Madison. } \usage{ data("Federalist") } \format{ A 1-way table giving the number of occurrences of \sQuote{may} in 262 blocks of text. The variable and its levels are \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab nMay \tab 0, 1, \dots, 6 \cr } } \references{ F. Mosteller & D. L. Wallace (1984), \emph{Applied Bayesian and Classical Inference: The Case of the Federalist Papers}. Springer-Verlag, New York, NY. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data, page 19. } \examples{ data("Federalist") gf <- goodfit(Federalist, type = "nbinomial") summary(gf) plot(gf) } \keyword{datasets} vcd/man/UKSoccer.Rd0000644000175300001440000000174411150520606013417 0ustar meyerusers\name{UKSoccer} \alias{UKSoccer} \docType{data} \title{UK Soccer Scores} \description{ Data from Lee (1997), on the goals scored by Home and Away teams in the Premier Football League, 1995/6 season. } \usage{ data("UKSoccer") } \format{ A 2-dimensional array resulting from cross-tabulating the number of goals scored in 380 games. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab Home \tab 0, 1, \dots, 4 \cr 2 \tab Away \tab 0, 1, \dots, 4 } } \references{ A. J. Lee (1997), Modelling scores in the Premier League: Is Manchester United really the best?, \emph{Chance}, \bold{10}(1), 15--19. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data, page 27. } \seealso{ \code{\link{Bundesliga}} } \examples{ data("UKSoccer") mosaic(UKSoccer, gp = shading_max, main = "UK Soccer Scores") } \keyword{datasets} vcd/man/woolf_test.Rd0000644000175300001440000000214611150520606014123 0ustar meyerusers\name{woolf_test} \alias{woolf_test} \title{Woolf Test} \description{ Test for homogeneity on \eqn{2 \times 2 \times k}{2 x 2 x k} tables over strata (i.e., whether the log odds ratios are the same in all strata). } \usage{ woolf_test(x) } \arguments{ \item{x}{A \eqn{2 \times 2 \times k}{2 x 2 x k} table.} } \value{ A list of class \code{"htest"} containing the following components: \item{statistic}{the chi-squared test statistic.} \item{parameter}{degrees of freedom of the approximate chi-squared distribution of the test statistic.} \item{p.value}{\eqn{p}-value for the test.} \item{method}{a character string indicating the type of test performed.} \item{data.name}{a character string giving the name(s) of the data.} \item{observed}{the observed counts.} \item{expected}{the expected counts under the null hypothesis.} } \seealso{ \code{\link{mantelhaen.test}} } \references{ Woolf, B. 1955. On estimating the relation between blood group and disease. \emph{Ann. Human Genet.} (London) \bold{19}, 251-253. } \examples{ data("CoalMiners") woolf_test(CoalMiners) } \keyword{htest} vcd/man/plot.loglm.Rd0000644000175300001440000000503411150520606014024 0ustar meyerusers\name{plot.loglm} \alias{plot.loglm} \alias{assoc.loglm} \alias{mosaic.loglm} \title{Visualize Fitted Log-linear Models} \description{ Visualize fitted \code{"loglm"} objects by mosaic or association plots. } \usage{ \method{plot}{loglm}(x, panel = mosaic, type = c("observed", "expected"), residuals_type = c("pearson", "deviance"), gp = shading_hcl, gp_args = list(), \dots) } \arguments{ \item{x}{a fitted \code{"loglm"} object, see \code{\link{loglm}}.} \item{panel}{a panel function for visualizing the observed values, residuals and expected values. Currently, \code{\link{mosaic}} and \code{\link{assoc}} in \pkg{vcd}.} \item{type}{a character string indicating whether the observed or the expected values of the table should be visualized.} \item{residuals_type}{a character string indicating the type of residuals to be computed.} \item{gp}{object of class \code{"gpar"}, shading function or a corresponding generating function (see details and \code{\link{shadings}}). Ignored if \code{shade = FALSE}.} \item{gp_args}{list of arguments for the shading-generating function, if specified.} \item{\dots}{Other arguments passed to the \code{panel} function.} } \details{ The \code{plot} method for \code{"loglm"} objects by default visualizes the model using a mosaic plot (can be changed to an association plot by setting \code{panel = assoc}) with a shading based on the residuals of this model. The legend also reports the corresponding p value of the associated goodness-of-fit test. The \code{mosaic} and \code{assoc} methods are simple convenience interfaces to this \code{plot} method, setting the \code{panel} argument accordingly. } \value{ The \code{"structable"} visualized is returned invisibly. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \seealso{ \code{\link{loglm}}, \code{\link{assoc}}, \code{\link{mosaic}}, \code{\link{strucplot}} } \examples{ ## mosaic display for PreSex model data("PreSex") fm <- loglm(~ PremaritalSex * ExtramaritalSex * (Gender + MaritalStatus), data = aperm(PreSex, c(3, 2, 4, 1))) fm ## visualize Pearson statistic plot(fm, split_vertical = TRUE) ## visualize LR statistic plot(fm, split_vertical = TRUE, residuals_type = "deviance") ## conditional independence in UCB admissions data data("UCBAdmissions") fm <- loglm(~ Dept * (Gender + Admit), data = aperm(UCBAdmissions)) ## use mosaic display plot(fm, labeling_args = list(abbreviate = c(Admit = 3))) ## and association plot plot(fm, panel = assoc) assoc(fm) } \keyword{hplot} vcd/man/cotabplot.Rd0000644000175300001440000001222411636647070013741 0ustar meyerusers\name{cotabplot} \alias{cotabplot} \alias{cotabplot.default} \alias{cotabplot.formula} \title{Coplot for Contingency Tables} \description{ \code{cotabplot} is a generic function for creating trellis-like coplots (conditional plots) for contingency tables. } \usage{ cotabplot(x, \dots) \method{cotabplot}{default}(x, cond = NULL, panel = cotab_mosaic, panel_args = list(), margins = rep(1, 4), layout = NULL, text_gp = gpar(fontsize = 12), rect_gp = gpar(fill = grey(0.9)), pop = TRUE, newpage = TRUE, \dots) \method{cotabplot}{formula}(formula, data = NULL, \dots) } \arguments{ \item{x}{an object. The default method can deal with contingency tables in array form.} \item{cond}{margin index(es) or corresponding name(s) of the conditioning variables.} \item{panel}{panel function applied for each conditioned plot, see details.} \item{panel_args}{list of arguments passed to \code{panel} if this is a panel-generating function inheriting from class \code{"grapcon_generator"}.} \item{margins}{either an object of class \code{"unit"} of length 4, or a numeric vector of length 4. The elements are recycled as needed. giving the margins around the whole plot.} \item{layout}{integer vector (of length two), giving the number of rows and columns for the panel.} \item{text_gp}{object of class \code{"gpar"} used for the text in the panel titles.} \item{rect_gp}{object of class \code{"gpar"} used for the rectangles with the panel titles.} \item{pop}{logical indicating whether the generated viewport tree should be removed at the end of the drawing or not.} \item{newpage}{logical controlling whether a new grid page should be created.} \item{\dots}{further arguments passed to the panel-generating function.} \item{formula}{a formula specifying the variables used to create a contingency table from \code{data}. It has to be of type \code{~ x + y | z} where \code{z} is/are the conditioning variable(s) used.} \item{data}{either a data frame, or an object of class \code{"table"} or \code{"ftable"}.} } \details{ \code{cotabplot} is a generic function designed to create coplots or conditional plots (see Cleveland, 1993, and Becker, Cleveland, Shyu, 1996) similar to \code{\link{coplot}} but for contingency tables. \code{cotabplot} takes on computing the conditioning information and setting up the trellis display, and then relies on a panel function to create plots from the full table and the conditioning information. A simple example would be a contingency table \code{tab} with margin names \code{"x"}, \code{"y"} and \code{"z"}. To produce this plot either the default interface can be used or the formula interface via \code{cotabplot(tab, "z")} \code{cotabplot(~ x + y | z, data = tab)} The panel function needs to be of the form \code{panel(x, condlevels)} where \code{x} is the \emph{full} table (\code{tab} in the example above) and \code{condlevels} is a named vector with the levels (e.g., \code{c(z = "z1")} in the example above). Alternatively, \code{panel} can also be a panel-generating function of class \code{"grapcon_generator"} which creates a function with the interface described above. The panel-generating function is called with the interface \code{panel(x, condvars, \dots)} where again \code{x} is the full table, \code{condvars} is now only a vector with the names of the conditioning variables (and not their levels, e.g., \code{"z"} in the example above). Further arguments can be passed to the panel-generating function via \code{\dots} which also includes the arguments set in \code{panel_args}. Suitable panel-generating functions for mosaic, association and sieve plots can be found at \code{\link{cotab_mosaic}}. A description of the underlying ideas is given in Zeileis, Meyer, Hornik (2005). } \seealso{ \code{\link{cotab_mosaic}}, \code{\link{cotab_coindep}}, \code{\link{co_table}}, \code{\link{coindep_test}} } \references{ Becker, R.A., Cleveland, W.S., Shyu, M.-J. (1996), The visual design and control of trellis display. \emph{Journal of Computational and Graphical Statistics}, \bold{5}, 123--155. Cleveland, W.S. (1993), \emph{Visualizing Data}, Summit, New Jersey: Hobart Press. Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. Zeileis, A., Meyer, D., Hornik K. (2007), \emph{Residual-based shadings for visualizing (conditional) independence}, \emph{Journal of Computational and Graphical Statistics}, \bold{16}, 507--525. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \examples{ data("UCBAdmissions") cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions) cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions, panel = cotab_assoc) ucb <- cotab_coindep(UCBAdmissions, condvars = "Dept", type = "assoc", n = 5000, margins = c(3, 1, 1, 3)) cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions, panel = ucb) } \keyword{hplot} vcd/man/Trucks.Rd0000644000175300001440000000311211150520606013203 0ustar meyerusers\name{Trucks} \alias{Trucks} \docType{data} \title{Truck Accidents Data} \description{ Data from a study in England in two periods from November 1969 to October 1971 and November 1971 to October 1973. A new compulsory safety measure for trucks was introduced in October 1971. Therefore, the question is whether the safety measure had an effect on the number of accidents and on the point of collision on the truck. } \usage{ data("Trucks") } \format{ A data frame with 24 observations on 5 variables. \describe{ \item{Freq}{frequency of accidents involving trucks.} \item{period}{factor indicating time period (before, after) 1971-11-01.} \item{collision}{factor indicating whether the collision was in the back or forward (including the front and the sides) of the truck (back, forward).} \item{parked}{factor indicating whether the truck was parked (yes, no).} \item{light}{factor indicating light conditions: day light (daylight), night on an illuminated road (night, illuminate), night on a dark road (night, dark).} } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, Table 6.8. } \examples{ data("Trucks") tab <- xtabs(Freq ~ period + collision + light + parked, data = Trucks) loglm(~ (collision + period) * parked * light, data = tab) doubledecker(collision ~ parked + light + period, data = tab) cotabplot(tab, panel = cotab_coindep) } \keyword{datasets} vcd/man/JointSports.Rd0000644000175300001440000000231611150520606014233 0ustar meyerusers\name{JointSports} \alias{JointSports} \docType{data} \title{Opinions About Joint Sports} \description{ Data from a Danish study in 1983 and 1985 about sports activities and the opinion about joint sports with the other gender among 16--19 year old high school students. } \usage{ data("JointSports") } \format{ A data frame with 40 observations and 5 variables. \describe{ \item{Freq}{frequency.} \item{opinion}{factor indicating opinion about sports joint with the other gender (very good, good, indifferent, bad, very bad).} \item{year}{factor indicating year of study (1983, 1985).} \item{grade}{factor indicating school grade (1st, 3rd).} \item{gender}{factor indicating gender (Boy, Girl).} } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, page 210. } \examples{ data("JointSports") tab <- xtabs(Freq ~ gender + opinion + grade + year, data = JointSports) doubledecker(opinion ~ gender + year + grade, data = tab) loglm(~ opinion* (gender + grade+ year) + gender*year*grade, data = tab) } \keyword{datasets} vcd/man/struc_mosaic.Rd0000644000175300001440000000612511474031017014434 0ustar meyerusers\name{struc_mosaic} \alias{struc_mosaic} \title{Core-generating Function for Mosaic Plots} \description{ Core-generating function for \code{strucplot} returning a function producing mosaic plots. } \usage{ struc_mosaic(zero_size = 0.5, zero_split = FALSE, zero_shade = TRUE, zero_gp = gpar(col = 0), panel = NULL) } \arguments{ \item{zero_size}{size of the bullets used for zero-entries in the contingency table (if 0, no bullets are drawn).} \item{zero_split}{logical controlling whether zero cells should be further split. If \code{FALSE} and \code{zero_shade} is \code{FALSE}, only one bullet is drawn (centered) for unsplit zero cells. If \code{FALSE} and \code{zero_shade} is \code{TRUE}, a bullet for each zero cell is drawn to allow, e.g., residual-based shadings to be effective also for zero cells.} \item{zero_shade}{logical controlling whether zero bullets should be shaded.} \item{zero_gp}{object of class \code{"gpar"} used for zero bullets in case they are \emph{not} shaded.} \item{panel}{Optional function with arguments: \code{residuals}, \code{observed}, \code{expected}, \code{index}, \code{gp}, and \code{name} called by the \code{struc_mosaic} workhorse for each tile that is drawn in the mosaic. \code{index} is an integer vector with the tile's coordinates in the contingency table, \code{gp} a \code{gpar} object for the tile, and \code{name} a label to be assigned to the drawn grid object.} } \details{ This function is usually called by \code{\link{strucplot}} (typically when called by \code{\link{mosaic}}) and returns a function used by \code{\link{strucplot}} to produce mosaic plots. } \value{ A function with arguments: \item{residuals}{table of residuals.} \item{observed}{table of observed values.} \item{expected}{not used by \code{struc_mosaic}.} \item{spacing}{object of class \code{"unit"} specifying the space between the tiles.} \item{gp}{list of \code{gpar} objects used for the drawing the tiles.} \item{split_vertical}{vector of logicals indicating, for each dimension of the table, the split direction.} } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{mosaic}}, \code{\link{strucplot}}, \code{\link{structable}} } \references{ Cohen, A. (1980), On the graphical display of the significant components in a two-way contingency table. \emph{Communications in Statistics---Theory and Methods}, \bold{A9}, 1025--1041. Friendly, M. (1992), Graphical methods for categorical data. \emph{SAS User Group International Conference Proceedings}, \bold{17}, 190--200. \url{http://datavis.ca/sugi/sugi17.pdf} Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \examples{ ## Titanic data data("Titanic") ## mosaic plot with large zeros strucplot(Titanic, core = struc_mosaic(zero_size = 1)) } \keyword{hplot} vcd/man/struc_assoc.Rd0000644000175300001440000000755311474031017014277 0ustar meyerusers\name{struc_assoc} \alias{struc_assoc} \title{Core-generating Function for Association Plots} \description{ Core-generating function for \code{strucplot} returning a function producing association plots. } \usage{ struc_assoc(compress = TRUE, xlim = NULL, ylim = NULL, yspace = unit(0.5, "lines"), xscale = 0.9, gp_axis = gpar(lty = 3)) } \arguments{ \item{compress}{logical; if \code{FALSE}, the space between the rows (columns) are chosen such that the \emph{total} heights (widths) of the rows (column) are all equal. If \code{TRUE}, the space between the rows and columns is fixed and hence the plot is more \dQuote{compressed}.} \item{xlim}{either a \eqn{2 \times k}{2 x k} matrix of doubles, \eqn{k} the number of total columns of the plot, or a recycled vector from which such a matrix will be constructed. The columns of \code{xlim} correspond to the columns of the association plot, the rows describe the column ranges (minimums in the first row, maximums in the second row). If \code{xlim} is \code{NULL}, the ranges are determined from the residuals according to \code{compress} (if \code{TRUE}: widest range from each column, if \code{FALSE}: from the whole association plot matrix).} \item{ylim}{either a \eqn{2 \times k}{2 x k} matrix of doubles, \eqn{k} the number of total rows of the plot, or a recycled vector from which such a matrix will be constructed. The columns of \code{ylim} correspond to the rows of the association plot, the rows describe the column ranges (minimums in the first row, maximums in the second row). If \code{ylim} is \code{NULL}, the ranges are determined from the residuals according to \code{compress} (if \code{TRUE}: widest range from each row, if \code{FALSE}: from the whole association plot matrix).} \item{xscale}{scale factor resizing the tile's width, thus adding additional space between the tiles. } \item{yspace}{object of class \code{"unit"} specifying additional space separating the rows.} \item{gp_axis}{object of class \code{"gpar"} specifying the visual aspects of the tiles' baseline.} } \details{ This function is usually called by \code{strucplot} (typically when called by \code{assoc}) and returns a function used by \code{strucplot} to produce association plots. } \value{ A function with arguments: \item{residuals}{table of residuals.} \item{observed}{not used by \code{struc_assoc}.} \item{expected}{table of expected frequencies.} \item{spacing}{object of class \code{"unit"} specifying the space between the tiles.} \item{gp}{list of \code{gpar} objects used for the drawing the tiles.} \item{split_vertical}{vector of logicals indicating, for each dimension of the table, the split direction.} } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{assoc}}, \code{\link{strucplot}}, \code{\link{structable}} } \references{ Cohen, A. (1980), On the graphical display of the significant components in a two-way contingency table. \emph{Communications in Statistics---Theory and Methods}, \bold{A9}, 1025--1041. Friendly, M. (1992), Graphical methods for categorical data. \emph{SAS User Group International Conference Proceedings}, \bold{17}, 190--200. \url{http://datavis.ca/sugi/sugi17.pdf} Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \examples{ ## UCB Admissions data("UCBAdmissions") ucb <- aperm(UCBAdmissions) ## association plot for conditional independence strucplot(ucb, expected = ~ Dept * (Admit + Gender), core = struc_assoc(ylim = c(-4, 4)), labeling_args = list(abbreviate = c(Admit = 3))) } \keyword{hplot} vcd/man/grid_legend.Rd0000644000175300001440000000324111150520606014176 0ustar meyerusers\name{grid_legend} \alias{grid_legend} \title{Legend Function for grid Graphics} \description{ This function can be used to add legends to \emph{grid-based} plots. } \usage{ grid_legend(x, y, pch, col, labels, frame = TRUE, hgap = unit(0.5, "lines"), vgap = unit(0.3, "lines"), default_units = "lines", gp = gpar(), draw = TRUE, title = "Legend:") } \arguments{ \item{x, y}{coordinates of the legend} \item{pch}{integer vector of plotting symbols} \item{col}{character vector of colors for the symbols} \item{labels}{character vector of labels corresponding to the symbols} \item{frame}{logical indicating whether the legend should have a border or not.} \item{hgap}{object of class \code{"unit"} specifying the space between symbols and labels} \item{vgap}{object of class \code{"unit"} specifying the space between the lines} \item{default_units}{character string indicating the default unit} \item{gp}{object of class \code{"gpar"} used for the legend} \item{draw}{logical indicating whether the legend be drawn or not.} \item{title}{character string indicating the plot's title} } \value{ Invisibly, the legend as a \code{"grob"} object. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link[graphics]{legend}} } \examples{ data("Lifeboats") attach(Lifeboats) ternaryplot(Lifeboats[,4:6], pch = ifelse(side == "Port", 1, 19), col = ifelse(side == "Port", "red", "blue"), id = ifelse(men / total > 0.1, as.character(boat), NA), prop_size = 2, dimnames_position = "edge", main = "Lifeboats on Titanic") grid_legend(0.8, 0.9, c(1, 19), c("red", "blue"), c("Port", "Starboard"), title = "SIDE") } \keyword{hplot} vcd/man/panel_pairs_off-diagonal.Rd0000644000175300001440000000463611474031017016651 0ustar meyerusers\name{Pairs plot panel functions for off-diagonal cells} \alias{pairs_strucplot} \alias{pairs_mosaic} \alias{pairs_assoc} \alias{pairs_sieve} \title{Off-diagonal Panel Functions for Table Pairs Plot} \description{ Off-diagonal panel functions for \code{\link{pairs.table}}. } \usage{ pairs_strucplot(panel = mosaic, type = c("pairwise", "total", "conditional", "joint"), legend = FALSE, margins = c(0, 0, 0, 0), labeling = NULL, \dots) pairs_assoc(\dots) pairs_mosaic(\dots) pairs_sieve(\dots) } \arguments{ \item{panel}{function to be used for the plots in each cell, such as \code{\link{pairs_assoc}}, \code{\link{pairs_mosaic}}, and \code{\link{pairs_sieve}}.} \item{type}{character string specifying the type of independence model visualized in the cells.} \item{legend}{logical specifying whether a legend should be displayed in the cells or not.} \item{margins}{margins inside each cell (see \code{\link{strucplot}}).} \item{labeling}{labeling function or labeling-generating function (see \code{\link{strucplot}}).} \item{\dots}{\code{pairs_mosaic}, \code{\link{pairs_assoc}}, and \code{pairs_sieve}: parameters passed to \code{pairs_strucplot}. \code{pairs_strucplot}: other parameters passed to panel function.} } \details{ These functions really just wrap \code{\link{assoc}}, \code{\link{sieve}}, and \code{\link{mosaic}} by basically inhibiting labeling and legend-drawing and setting the margins to 0. } \value{ A function with arguments: \item{x}{contingency table.} \item{i, j}{cell coordinates.} } \seealso{ \code{\link{pairs.table}}, \code{\link{pairs_text}}, \code{\link{pairs_barplot}}, \code{\link{assoc}}, \code{\link{mosaic}} } \references{ Cohen, A. (1980), On the graphical display of the significant components in a two-way contingency table. \emph{Communications in Statistics---Theory and Methods}, \bold{A9}, 1025--1041. Friendly, M. (1992), Graphical methods for categorical data. \emph{SAS User Group International Conference Proceedings}, \bold{17}, 190--200. \url{http://datavis.ca/sugi/sugi17.pdf} } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("UCBAdmissions") data("PreSex") pairs(PreSex) pairs(UCBAdmissions) pairs(UCBAdmissions, upper_panel_args = list(shade = FALSE)) pairs(UCBAdmissions, lower_panel = pairs_mosaic(type = "conditional")) pairs(UCBAdmissions, upper_panel = pairs_assoc) } \keyword{hplot} vcd/man/oddsratio.Rd0000644000175300001440000000577411150520606013740 0ustar meyerusers\name{oddsratio} \alias{oddsratio} \alias{print.oddsratio} \alias{summary.oddsratio} \alias{confint.oddsratio} \alias{print.summary.oddsratio} \alias{plot.oddsratio} \title{(Log) Odds Ratios} \description{ Computes (log) odds ratios and their asymptotic standard errors for (possibly) stratified data. } \usage{ oddsratio(x, stratum = NULL, log = TRUE) \method{plot}{oddsratio}(x, conf_level = 0.95, type = "o", xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, whiskers = 0.1, baseline = TRUE, transpose = FALSE, \dots) } \arguments{ \item{x}{a 2 by 2 by \dots table.} \item{stratum}{vector of strata dimensions.} \item{log}{if \code{FALSE}, ordinary odds ratios are computed.} \item{conf_level}{if not \code{NULL} or \code{FALSE}, \code{conf_level}-\% confidence intervals are plotted for each data point.} \item{type}{plot type.} \item{xlab}{label for the x-axis. Defaults to \code{"Strata"} if \code{transpose} is \code{FALSE}.} \item{ylab}{label for the y-axis. Defaults to \code{"Strata"} if \code{transpose} is \code{TRUE}.} \item{xlim}{x-axis limits. Ignored if \code{transpose} is \code{FALSE}.} \item{ylim}{y-axis limits. Ignored if \code{transpose} is \code{TRUE}.} \item{baseline}{if \code{TRUE}, a red dashed line is plotted at a value of 1 (in case of odds) or 0 (in case of log-odds).} \item{transpose}{if \code{TRUE}, the plot is transposed.} \item{whiskers}{width of the confidence interval whiskers.} \item{\dots}{other graphics parameters (see \code{\link{par}}).} } \value{ An object of class \code{"logoddsratio"}, which is simply a vector of (log) odds ratios with dimensionality depending on \code{stratum}, along with the following attributes: \item{ASE}{a numeric vector with the asymptotic standard errors.} \item{log}{logical indicating whether log odds ratios or common odds ratios are computed.} } \note{ In case of zero entries, 0.5 will be added to the table. The \code{summary} method prints the standard errors and---for log odds ratios---also computes and prints asymptotic \eqn{z} tests (standardized log odds ratios) and the corresponding \eqn{p} values. There is a \code{confint} method for computing confidence intervals for the (log) odds ratios. The \code{plot} method plots (log) odds ratios, computed by \code{oddsratio} for \eqn{2 \times 2 \times k}{2 x 2 x k} tables, along with confidence intervals. } \references{ M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{confint}} } \examples{ ## load Coal Miners data data("CoalMiners") ## compute log odds ratios lor <- oddsratio(CoalMiners) lor ## summary with z tests summary(lor) ## confidence intervals confint(lor) ## visualization plot(lor, xlab = "Age Group", main = "Breathelessness and Wheeze in Coal Miners") ## add quadratic model g <- seq(25, 60, by = 5) m <- lm(lor ~ g + I(g^2)) lines(fitted(m), col = "red") } \keyword{category} vcd/man/Bundestag2005.Rd0000644000175300001440000000561611150520606014166 0ustar meyerusers\name{Bundestag2005} \alias{Bundestag2005} \title{Votes in German Bundestag Election 2005} \description{ Number of votes by province in the German Bundestag election 2005 (for the parties that eventually entered the parliament). } \usage{ data("Bundestag2005") } \format{ A 2-way \code{"table"} giving the number of votes for each party (\code{Fraktion}) in each of the 16 German provinces (\code{Bundesland}): \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab Bundesland \tab Schleswig-Holstein, Mecklenburg-Vorpommern, \dots \cr 2 \tab Fraktion \tab SPD, CDU/CSU, Gruene, FDP, Linke } } \details{ In the election for the German parliament \dQuote{Bundestag}, five parties obtained enough votes to enter the parliament: the social democrats SPD, the conservative CDU/CSU, the liberal FDP, the green party \dQuote{Die Gruenen} and the leftist party \dQuote{Die Linke}. The table \code{Bundestag2005} gives the number of votes for each party (\code{Fraktion}) in each of the 16 German provinces (\code{Bundesland}). The provinces are ordered from North to South. The data have been obtained from the German statistical office (Statistisches Bundesamt) from the Web page given below. Note that the number of seats in the parliament cannot be computed from the number of votes alone. The examples below show the distribution of seats that resulted from the election. } \source{ Der Bundeswahlleiter, Statistisches Bundesamt. \url{http://www.bundeswahlleiter.de/bundestagswahl2005/} } \examples{ ## The outcome of the election in terms of seats in the ## parliament was: seats <- structure(c(226, 61, 54, 51, 222), .Names = c("CDU/CSU", "FDP", "Linke", "Gruene", "SPD")) ## Hues are chosen as metaphors for the political parties ## CDU/CSU: blue, FDP: yellow, Linke: purple, Gruene: green, SPD: red ## using the respective hues from a color wheel with ## chroma = 60 and luminance = 75 parties <- rainbow_hcl(6, c = 60, l = 75)[c(5, 2, 6, 3, 1)] names(parties) <- names(seats) parties ## The pie chart shows that neither the SPD+Gruene coalition nor ## the opposition of CDU/CSU+FDP could assemble a majority. ## No party would enter a coalition with the leftists, leading to a ## big coalition. pie(seats, clockwise = TRUE, col = parties) ## The regional distribution of the votes, stratified by province, ## is shown in a mosaic display: first for the 10 Western then the ## 6 Eastern provinces. data("Bundestag2005") votes <- Bundestag2005[c(1, 3:5, 9, 11, 13:16, 2, 6:8, 10, 12), c("CDU/CSU", "FDP", "SPD", "Gruene", "Linke")] mosaic(votes, gp = gpar(fill = parties[colnames(votes)]), spacing = spacing_highlighting, labeling = labeling_left, labeling_args = list(rot_labels = c(0, 90, 0, 0), pos_labels = "center", just_labels = c("center","center","center","right"), varnames = FALSE), margins = unit(c(2.5, 1, 1, 12), "lines"), keep_aspect_ratio = FALSE) } \keyword{datasets} vcd/man/fourfold.Rd0000644000175300001440000001417011510637073013565 0ustar meyerusers\name{fourfold} \alias{fourfold} \title{Fourfold Plots} \description{ Creates an (extended) fourfold display of a \eqn{2 \times 2 \times k}{2 x 2 x k} contingency table, allowing for the visual inspection of the association between two dichotomous variables in one or several populations (strata). } \usage{ fourfold(x, color = c("#99CCFF", "#6699CC", "#FFA0A0", "#A0A0FF", "#FF0000", "#000080"), conf_level = 0.95, std = c("margins", "ind.max", "all.max"), margin = c(1, 2), space = 0.2, main = NULL, sub = NULL, mfrow = NULL, mfcol = NULL, extended = TRUE, ticks = 0.15, p_adjust_method = p.adjust.methods, newpage = TRUE, fontsize = 12) } \arguments{ \item{x}{a \eqn{2 \times 2 \times k}{2 x 2 x k} contingency table in array form, or a \eqn{2 \times 2}{2 x 2} matrix if \eqn{k} is 1. If \code{length(dim(x)>3}, dimensions \code{3:length(dim(x)} are silently raveled into a combined strata dimension with \code{k=prod(dim(x)[-(1:2)]))}.} \item{color}{a vector of length 6 specifying the colors to use for the smaller and larger diagonals of each \eqn{2 \times 2}{2 x 2} table. The first pair is used for the standard (non-extended) plots, the other two for the extended version: the second/third pair is used for tables with non-significant/significant log-odds ratios, respectively, the latter being visualized in brighter colors.} \item{conf_level}{confidence level used for the confidence rings on the odds ratios. Must be a single non-negative number less than 1; if set to 0, confidence rings are suppressed.} \item{std}{a character string specifying how to standardize the table. Must be one of \code{"margins"}, \code{"ind.max"}, or \code{"all.max"}, and can be abbreviated by the initial letter. If set to \code{"margins"}, each \eqn{2 \times 2}{2 x 2} table is standardized to equate the margins specified by \code{margin} while preserving the odds ratio. If \code{"ind.max"} or \code{"all.max"}, the tables are either individually or simultaneously standardized to a maximal cell frequency of 1.} \item{margin}{a numeric vector with the margins to equate. Must be one of \code{1}, \code{2}, or \code{c(1, 2)} (the default), which corresponds to standardizing only the row, only column, or both row and column in each \eqn{2 \times 2}{2 x 2} table. Only used if \code{std} equals \code{"margins"}.} \item{space}{the amount of space (as a fraction of the maximal radius of the quarter circles) used for the row and column labels.} \item{main, sub}{character string for the fourfold plot title/subtitle.} \item{mfrow, mfcol}{a numeric vector with two components: \var{nr} and \var{nc}, indicating that the displays for the \eqn{2 \times 2}{2 x 2} tables should be arranged in an \var{nr} by \var{nc} layout, filled by rows/columns. The defaults are calculated to give a collection of plots in landscape orientation when \var{k} is not a perfect square.} \item{extended}{logical; if \code{TRUE}, extended plots are plotted, i.e., colors are brighter for significant log-odds ratios, and ticks are plotted showing the direction of association for positive log-odds.} \item{ticks}{the length of the ticks. If set to 0, no ticks are plotted.} \item{p_adjust_method}{method to be used for p-value adjustments for multi-stratum plots, as provided by \code{link[stats]{p.adjust}}. Use \code{p_adjust_method="none"} to disable this adjustment. The p-values are used for the \sQuote{visual} significance tests of the odds ratios.} \item{newpage}{logical; if \code{TRUE}, \code{grid.newpage()} is called before plotting.} \item{fontsize}{fontsize of main title. Other labels are scaled relative to this.} } \details{ The fourfold display is designed for the display of \eqn{2 \times 2 \times k}{2 x 2 x k} tables. Following suitable standardization, the cell frequencies \eqn{f_{ij}}{f[i,j]} of each \eqn{2 \times 2}{2 x 2} table are shown as a quarter circle whose radius is proportional to \eqn{\sqrt{f_{ij}}}{sqrt(f[i,j])} so that its area is proportional to the cell frequency. An association (odds ratio different from 1) between the binary row and column variables is indicated by the tendency of diagonally opposite cells in one direction to differ in size from those in the other direction; color is used to show this direction. Confidence rings for the odds ratio allow a visual test of the null of no association; the rings for adjacent quadrants overlap iff the observed counts are consistent with the null hypothesis. Typically, the number \eqn{k} corresponds to the number of levels of a stratifying variable, and it is of interest to see whether the association is homogeneous across strata. The fourfold display visualizes the pattern of association. Note that the confidence rings for the individual odds ratios are not adjusted for multiple testing. } \references{ Friendly, M. (1994), \emph{A fourfold display for 2 by 2 by \eqn{k} tables}. Technical Report 217, York University, Psychology Department, \url{http://datavis.ca/papers/4fold/4fold.pdf}. Friendly, M. (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \seealso{ \code{\link{mosaic}}, \code{\link{assoc}} \code{link[stats]{p.adjust}} for methods of p value adjustment } \examples{ data("UCBAdmissions") ## Use the Berkeley admission data as in Friendly (1995). x <- aperm(UCBAdmissions, c(2, 1, 3)) dimnames(x)[[2]] <- c("Yes", "No") names(dimnames(x)) <- c("Sex", "Admit?", "Department") ftable(x) ## Fourfold display of data aggregated over departments, with ## frequencies standardized to equate the margins for admission ## and sex. ## Figure 1 in Friendly (1994). fourfold(margin.table(x, c(1, 2))) ## Fourfold display of x, with frequencies in each table ## standardized to equate the margins for admission and sex. ## Figure 2 in Friendly (1994). fourfold(x) cotabplot(x, panel = cotab_fourfold) ## Fourfold display of x, with frequencies in each table ## standardized to equate the margins for admission. but not ## for sex. ## Figure 3 in Friendly (1994). fourfold(x, margin = 2) } \keyword{hplot} vcd/man/distplot.Rd0000644000175300001440000000631211150520606013577 0ustar meyerusers\name{distplot} \alias{distplot} \title{Diagnostic Distribution Plots} \description{ Diagnostic distribution plots: poissonness, binomialness and negative binomialness plots. } \usage{ distplot(x, type = c("poisson", "binomial", "nbinomial"), size = NULL, lambda = NULL, legend = TRUE, xlim = NULL, ylim = NULL, conf_int = TRUE, conf_level = 0.95, main = NULL, xlab = "Number of occurrences", ylab = "Distribution metameter", gp = gpar(cex = 0.5), name = "distplot", newpage = TRUE, pop = TRUE, \dots) } \arguments{ \item{x}{either a vector of counts, a 1-way table of frequencies of counts or a data frame or matrix with frequencies in the first column and the corresponding counts in the second column.} \item{type}{a character string indicating the distribution.} \item{size}{the size argument for the binomial and negative binomial distribution. If set to \code{NULL} and \code{type} is \code{"binomial"}, then \code{size} is taken to be the maximum count. If set to \code{NULL} and \code{type} is \code{"nbinomial"}, then \code{size} is estimated from the data.} \item{lambda}{parameter of the poisson distribution. If type is \code{"poisson"} and \code{lambda} is specified a leveled poissonness plot is produced.} \item{legend}{logical. Should a legend be plotted?} \item{xlim}{limits for the x axis.} \item{ylim}{limits for the y axis.} \item{conf_int}{logical. Should confidence intervals be plotted?} \item{conf_level}{confidence level for confidence intervals.} \item{main}{a title for the plot.} \item{xlab}{a label for the x axis.} \item{ylab}{a label for the y axis.} \item{gp}{a \code{"gpar"} object controlling the grid graphical parameters of the points.} \item{name}{name of the plotting viewport.} \item{newpage}{logical. Should \code{\link{grid.newpage}} be called before plotting?} \item{pop}{logical. Should the viewport created be popped?} \item{...}{further arguments passed to \code{\link{grid.points}}.} } \details{ \code{distplot} plots the number of occurrences (counts) against the distribution metameter of the specified distribution. If the distribution fits the data, the plot should show a straight line. See Friendly (2000) for details. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \references{ D. C. Hoaglin (1980), A poissonness plot, \emph{The American Statistican}, \bold{34}, 146--149. D. C. Hoaglin \& J. W. Tukey (1985), Checking the shape of discrete distributions. In D. C. Hoaglin, F. Mosteller, J. W. Tukey (eds.), \emph{Exploring Data Tables, Trends and Shapes}, chapter 9. John Wiley \& Sons, New York. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \examples{ ## Simulated data examples: dummy <- rnbinom(1000, size = 1.5, prob = 0.8) distplot(dummy, type = "nbinomial") ## Real data examples: data("HorseKicks") data("Federalist") data("Saxony") distplot(HorseKicks, type = "poisson") distplot(HorseKicks, type = "poisson", lambda = 0.61) distplot(Federalist, type = "poisson") distplot(Federalist, type = "nbinomial", size = 1) distplot(Federalist, type = "nbinomial") distplot(Saxony, type = "binomial", size = 12) } \keyword{category} vcd/man/Kappa.Rd0000644000175300001440000000420611235655470013005 0ustar meyerusers\name{Kappa} \alias{Kappa} \alias{print.Kappa} \alias{confint.Kappa} \alias{summary.Kappa} \alias{print.summary.Kappa} \title{Cohen's Kappa and Weighted Kappa} \description{ Computes two agreement rates: Cohen's kappa and weighted kappa, and confidence bands. } \usage{ Kappa(x, weights = c("Equal-Spacing", "Fleiss-Cohen")) } \arguments{ \item{x}{a confusion matrix.} \item{weights}{either one of the character strings given in the default value, or a user-specified matrix with same dimensions as \code{x}.} } \details{ Cohen's kappa is the diagonal sum of the (possibly weighted) relative frequencies, corrected for expected values and standardized by its maximum value. The equal-spacing weights are defined by \eqn{1 - |i - j| / (r - 1)}{1 - abs(i - j) / (r - 1)}, \eqn{r} number of columns/rows, and the Fleiss-Cohen weights by \eqn{1 - |i - j|^2 / (r - 1)^2}{1 - abs(i - j)^2 / (r - 1)^2}. The latter one attaches greater importance to near disagreements. } \value{ An object of class \code{"Kappa"} with three components: \item{Unweighted}{numeric vector of length 2 with the kappa statistic (\code{value} component), along with Approximate Standard Error (\code{ASE} component)} \item{Weighted}{idem for the weighted kappa.} \item{Weights}{numeric matrix with weights used.} } \note{ The \code{summary} method also prints the weights. There is a \code{confint} method for computing approximate confidence intervals. } \references{ Cohen, J. (1960), A coefficient of agreement for nominal scales. \emph{Educational and Psychological Measurement}, \bold{20}, 37--46. Everitt, B.S. (1968), Moments of statistics kappa and weighted kappa. \emph{The British Journal of Mathematical and Statistical Psychology}, \bold{21}, 97--103. Fleiss, J.L., Cohen, J., and Everitt, B.S. (1969), Large sample standard errors of kappa and weighted kappa. \emph{Psychological Bulletin}, \bold{72}, 332--327. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{agreementplot}}, \code{\link{confint}} } \examples{ data("SexualFun") Kappa(SexualFun) } \keyword{category} vcd/man/shadings.Rd0000644000175300001440000002274211566721116013554 0ustar meyerusers\name{shadings} \alias{shadings} \alias{shading_hsv} \alias{shading_hcl} \alias{shading_max} \alias{shading_Friendly} \alias{shading_sieve} \alias{shading_binary} \alias{hcl2hex} \encoding{UTF-8} \title{Shading-generating Functions for Residual-based Shadings} \description{ Shading-generating functions for computing residual-based shadings for mosaic and association plots. } \usage{ shading_hcl(observed, residuals = NULL, expected = NULL, df = NULL, h = NULL, c = NULL, l = NULL, interpolate = c(2, 4), lty = 1, eps = NULL, line_col = "black", p.value = NULL, level = 0.95, \dots) shading_hsv(observed, residuals = NULL, expected = NULL, df = NULL, h = c(2/3, 0), s = c(1, 0), v = c(1, 0.5), interpolate = c(2, 4), lty = 1, eps = NULL, line_col = "black", p.value = NULL, level = 0.95, \dots) shading_max(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = NULL, c = NULL, l = NULL, lty = 1, eps = NULL, line_col = "black", level = c(0.9, 0.99), n = 1000, \dots) shading_Friendly(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = c(2/3, 0), lty = 1:2, interpolate = c(2, 4), eps = 0.01, line_col = "black", \dots) shading_sieve(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = c(260, 0), lty = 1:2, interpolate = c(2, 4), eps = 0.01, line_col = "black", \dots) shading_binary(observed = NULL, residuals = NULL, expected = NULL, df = NULL, col = NULL) hcl2hex(h = 0, c = 35, l = 85, fixup = TRUE) } \arguments{ \item{observed}{contingency table of observed values} \item{residuals}{contingency table of residuals} \item{expected}{contingency table of expected values} \item{df}{degrees of freedom of the associated independence model.} \item{h}{hue value in the HCL or HSV color description, has to be in [0, 360] for HCL and in [0, 1] for HSV colors. The default is to use blue and red for positive and negative residuals respectively. In the HCL specification it is \code{c(260, 0)} by default and for HSV \code{c(2/3, 0)}.} \item{c}{chroma value in the HCL color description. This controls the maximum chroma for significant and non-significant results respectively and defaults to \code{c(100, 20)}.} \item{l}{luminance value in the HCL color description. Defaults to \code{c(90, 50)} for small and large residuals respectively.} \item{s}{saturation value in the HSV color description. Defaults to \code{c(1, 0)} for large and small residuals respectively.} \item{v}{saturation value in the HSV color description. Defaults to \code{c(1, 0.5)} for significant and non-significant results respectively.} \item{interpolate}{a specification for mapping the absolute size of the residuals to a value in [0, 1]. This can be either a function or a numeric vector. In the latter case, a step function with steps of equal size going from 0 to 1 is used.} \item{lty}{a vector of two line types for positive and negative residuals respectively. Recycled if necessary.} \item{eps}{numeric tolerance value below which absolute residuals are considered to be zero, which is used for coding the border color and line type. If set to \code{NULL} (default), all borders have the default color specified by \code{line\_col}. If set to a numeric value, all border colors corresponding to residuals with a larger absolute value are set to the full positive or negative color, respectively; borders corresponding to smaller residuals are are drawn with \code{line\_col} and \code{lty[1]}}. This is used principally in \code{shading\_Friendly}. \item{line_col}{default border color (for \code{shading_sieve}: default sieve color).} \item{p.value}{the \eqn{p} value associated with the independence model. By default, this is computed from a Chi-squared distribution with \code{df} degrees of freedom. \code{p.value} can be either a scalar or a \code{function(observed, residuals, expected, df)} that computes the \eqn{p} value from the data. If set to \code{NA} no inference is performed.} \item{level}{confidence level of the test used. If \code{p.value} is smaller than \code{1 - level}, bright colors are used, otherwise dark colors are employed. For \code{shading_max} a vector of levels can be supplied. The corresponding critical values are then used as \code{interpolate} cut-offs.} \item{n}{number of permutations used in the call to \code{coindep_test}.} \item{col}{a vector of two colors for positive and negative residuals respectively.} \item{fixup}{logical. Should the color be corrected to a valid RGB value before correction?} \item{\dots}{Other arguments passed to \code{\link{hcl2hex}} or \code{\link{hsv}}, respectively.} } \details{ These shading-generating functions can be passed to \code{strucplot} to generate residual-based shadings for contingency tables. \code{strucplot} calls these functions with the arguments \code{observed}, \code{residuals}, \code{expected}, \code{df} which give the observed values, residuals, expected values and associated degrees of freedom for a particular contingency table and associated independence model. The shadings \code{shading_hcl} and \code{shading_hsv} do the same thing conceptually, but use HCL or HSV colors respectively. The former is usually preferred because they are perceptually based. Both shadings visualize the \emph{sign} of the residuals of an independence model using two hues (by default: blue and red). The \emph{absolute size} of the residuals is visualized by the colorfulness and the amount of grey, by default in three categories: very colorful for large residuals (> 4), less colorful for medium sized residuals (< 4 and > 2), grey/white for small residuals (< 2). More categories or a continuous scale can be specified by setting \code{interpolate}. Furthermore, the result of a significance test can be visualized by the amount of grey in the colors. If significant, a colorful palette is used, if not, the amount of color is reduced. See Zeileis, Meyer, and Hornik (2007) and \code{\link[colorspace]{diverge_hcl}} for more details. The shading \code{shading_max} is applicable in 2-way contingency tables and uses a similar strategy as \code{shading_hcl}. But instead of using the cut-offs 2 and 4, it employs the critical values for the maximum statistic (by default at 90\% and 99\%). Consequently, color in the plot signals a significant result at 90\% or 99\% significance level, respectively. The test is carried out by calling \code{\link{coindep_test}}. The shading \code{shading_Friendly} is very similar to \code{shading_hsv}, but additionally codes the sign of the residuals by different line types. See Friendly (1994) for more details. \code{shading_sieve} is similar, but uses HCL colors. The shading \code{shading_binary} just visualizes the sign of the residuals by using two different colors (default: blue HCL(260, 50, 70) and red HCL(0, 50, 70)). The color implementations employed are \code{\link{hsv}} from base R and \code{\link[colorspace]{polarLUV}} from the \pkg{colorspace} package, respectively. To transform the HCL coordinates to a hexadecimal color string (as returned by \code{hsv}), the function \code{\link[colorspace]{hex}} is employed. A convenience wrapper \code{hcl2hex} is provided. } \references{ Friendly M. (1994), Mosaic Displays for Multi-Way Contingency Tables. \emph{Journal of the American Statistical Association}, \bold{89}, 190--200. Meyer D., Zeileis A., and Hornik K. (2006), The Strucplot Framework: Visualizing Multi-Way Contingency Tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17}(3), 1--48. URL http://www.jstatsoft.org/v17/i03/. See also \code{vignette("strucplot", package = "vcd")}. Zeileis A., Meyer D., Hornik K. (2007), Residual-Based Shadings for Visualizing (Conditional) Independence. \emph{Journal of Computational and Graphical Statistics}, \bold{16}, 507--525. Zeileis A., Hornik K. and Murrell P. (2008), Escaping RGBland: Selecting Colors for Statistical Graphics. \emph{Computational Statistics & Data Analysis}, Forthcoming. Preprint available from \url{http://statmath.wu-wien.ac.at/~zeileis/papers/Zeileis+Hornik+Murrell-2008.pdf}. } \value{A shading function which takes only a single argument, interpreted as a vector/table of residuals, and returns a \code{"gpar"} object with the corresponding vector(s)/table(s) of graphical parameter(s). } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \seealso{ \code{\link[colorspace]{hex}}, \code{\link[colorspace]{polarLUV}}, \code{\link{hsv}}, \code{\link{mosaic}}, \code{\link{assoc}}, \code{\link{strucplot}}, \code{\link[colorspace]{diverge_hcl}} } \examples{ ## load Arthritis data data("Arthritis") art <- xtabs(~Treatment + Improved, data = Arthritis) ## plain mosaic display without shading mosaic(art) ## with shading for independence model mosaic(art, shade = TRUE) ## which uses the HCL shading mosaic(art, gp = shading_hcl) ## the residuals are two small to have color, ## hence the cut-offs can be modified mosaic(art, gp = shading_hcl, gp_args = list(interpolate = c(1, 1.8))) ## the same with the Friendly palette ## (without significance testing) mosaic(art, gp = shading_Friendly, gp_args = list(interpolate = c(1, 1.8))) ## assess independence using the maximum statistic ## cut-offs are now critical values for the test statistic mosaic(art, gp = shading_max) ## association plot with shading as in base R assoc(art, gp = shading_binary(col = c(1, 2))) } \keyword{hplot} vcd/man/Arthritis.Rd0000644000175300001440000000235711150520606013713 0ustar meyerusers\name{Arthritis} \alias{Arthritis} \docType{data} \title{Arthritis Treatment Data} \description{ Data from Koch \& Edwards (1988) from a double-blind clinical trial investigating a new treatment for rheumatoid arthritis. } \usage{data("Arthritis")} \format{ A data frame with 84 observations and 5 variables. \describe{ \item{ID}{patient ID.} \item{Treatment}{factor indicating treatment (Placebo, Treated).} \item{Sex}{factor indicating sex (Female, Male).} \item{Age}{age of patient.} \item{Improved}{ordered factor indicating treatment outcome (None, Some, Marked).} } } \references{ G. Koch \& S. Edwards (1988), Clinical efficiency trials with categorical data. In K. E. Peace (ed.), \emph{Biopharmaceutical Statistics for Drug Development}, 403--451. Marcel Dekker, New York. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/arthrit.sas} } \examples{ data("Arthritis") art <- xtabs(~ Treatment + Improved, data = Arthritis, subset = Sex == "Female") art mosaic(art, gp = shading_Friendly) mosaic(art, gp = shading_max) } \keyword{datasets} vcd/man/agreementplot.Rd0000644000175300001440000000740711720277575014632 0ustar meyerusers\name{agreementplot} \alias{agreementplot} \alias{agreementplot.default} \alias{agreementplot.formula} \title{Bangdiwala's Observer Agreement Chart} \description{ Representation of a \eqn{k \times k}{k by k} confusion matrix, where the observed and expected diagonal elements are represented by superposed black and white rectangles, respectively. The function also computes a statistic measuring the strength of agreement (relation of respective area sums). } \usage{ \method{agreementplot}{default}(x, reverse_y = TRUE, main = NULL, weights = c(1, 1 - 1/(ncol(x) - 1)^2), margins = par("mar"), newpage = TRUE, pop = TRUE, xlab = names(dimnames(x))[2], ylab = names(dimnames(x))[1], xlab_rot = 0, xlab_just = "center", ylab_rot = 90, ylab_just = "center", fill_col = function(j) gray((1 - (weights[j]) ^ 2) ^ 0.5), line_col = "red", xscale = TRUE, yscale = TRUE, ...) \method{agreementplot}{formula}(formula, data = NULL, ..., subset) } \arguments{ \item{x}{a confusion matrix, i.e., a table with equal-sized dimensions.} \item{reverse_y}{if \code{TRUE}, the y axis is reversed (i.e., the rectangles' positions correspond to the contingency table).} \item{main}{user-specified main title.} \item{weights}{vector of weights for successive larger observed areas, used in the agreement strength statistic, and also for the shading. The first element should be 1.} \item{margins}{vector of margins (see \code{\link[graphics]{par}}).} \item{newpage}{logical; if \code{TRUE}, the plot is drawn on a new page.} \item{pop}{logical; if \code{TRUE}, all newly generated viewports are popped after plotting.} \item{xlab, ylab}{labels of x- and y-axis.} \item{xlab_rot, ylab_rot}{rotation angle for the category labels.} \item{xlab_just, ylab_just}{justification for the category labels.} \item{fill_col}{a function, giving the fill colors used for exact and partial agreement} \item{line_col}{color used for the diagonal reference line} \item{formula}{a formula, such as \code{y ~ x}. For details, see \code{\link{xtabs}}.} \item{data}{a data frame (or list), or a contingency table from which the variables in \code{formula} should be taken.} \item{subset}{an optional vector specifying a subset of the rows in the data frame to be used for plotting.} \item{xscale, yscale}{logicals indicating whether the marginals should be added on the x-axis/y-axis, respectively.} \item{\dots}{further graphics parameters (see \code{\link{par}}).} } \details{ Weights can be specified to allow for partial agreement, taking into account contributions from off-diagonal cells. A weight vector of length 1 means strict agreement only, each additional element increases the maximum number of disagreement steps. } \value{ Invisibly returned, a list with components \item{Bangdiwala}{the unweighted agreement strength statistic.} \item{Bangdiwala_Weighted}{the weighted statistic.} \item{weights}{the weight vector used.} } \references{ Michael Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("SexualFun") agreementplot(t(SexualFun)) data("MSPatients") ## best visualized using a resized device, e.g. using: ## get(getOption("device"))(width = 12) pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) agreementplot(t(MSPatients[,,1]), main = "Winnipeg Patients", newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 2)) agreementplot(t(MSPatients[,,2]), main = "New Orleans Patients", newpage = FALSE) popViewport(2) dev.off() } \keyword{category} \keyword{hplot} vcd/man/WomenQueue.Rd0000644000175300001440000000231511150520606014026 0ustar meyerusers\name{WomenQueue} \alias{WomenQueue} \docType{data} \title{Women in Queues} \description{ Data from Jinkinson \& Slater (1981) and Hoaglin \& Tukey (1985) reporting the frequency distribution of females in 100 queues of length 10 in a London Underground station. } \usage{ data("WomenQueue") } \format{ A 1-way table giving the number of women in 100 queues of length 10. The variable and its levels are \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab nWomen \tab 0, 1, \dots, 10 \cr } } \references{ D. C. Hoaglin \& J. W. Tukey (1985), Checking the shape of discrete distributions. In D. C. Hoaglin, F. Mosteller, J. W. Tukey (eds.), \emph{Exploring Data Tables, Trends and Shapes}, chapter 9. John Wiley \& Sons, New York. R. A. Jinkinson \& M. Slater (1981), Critical discussion of a graphical method for identifying discrete distributions, \emph{The Statistician}, \bold{30}, 239--248. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data, pages 19--20. } \examples{ data("WomenQueue") gf <- goodfit(WomenQueue, type = "binomial") summary(gf) plot(gf) } \keyword{datasets} vcd/man/HorseKicks.Rd0000644000175300001440000000250011150520606013775 0ustar meyerusers\name{HorseKicks} \alias{HorseKicks} \docType{data} \title{Death by Horse Kicks} \description{ Data from von Bortkiewicz (1898), given by Andrews \& Herzberg (1985), on number of deaths by horse or mule kicks in 10 (of 14 reported) corps of the Prussian army. 4 corps were not considered by Fisher (1925) as they had a different organization. This data set is a popular subset of the \code{\link{VonBort}} data. } \usage{ data("HorseKicks") } \format{ A 1-way table giving the number of deaths in 200 corps-years. The variable and its levels are \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab nDeaths \tab 0, 1, \dots, 4 \cr } } \references{ D. F. Andrews & A. M. Herzberg (1985), \emph{Data: A Collection of Problems from Many Fields for the Student and Research Worker}. Springer-Verlag, New York, NY. R. A. Fisher (1925), \emph{Statistical Methods for Research Workers}. Oliver \& Boyd, London. L. von Bortkiewicz (1898), \emph{Das Gesetz der kleinen Zahlen}. Teubner, Leipzig. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data, page 18. } \seealso{ \code{\link{VonBort}} } \examples{ data("HorseKicks") gf <- goodfit(HorseKicks) summary(gf) plot(gf) } \keyword{datasets} vcd/man/assoc.Rd0000644000175300001440000002255211474031017013053 0ustar meyerusers\name{assoc} \alias{assoc} \alias{assoc.default} \alias{assoc.formula} \title{Extended Association Plots} \description{ Produce an association plot indicating deviations from a specified independence model in a possibly high-dimensional contingency table. } \usage{ \method{assoc}{default}(x, row_vars = NULL, col_vars = NULL, compress = TRUE, xlim = NULL, ylim = NULL, spacing = spacing_conditional(sp = 0), spacing_args = list(), split_vertical = NULL, keep_aspect_ratio = FALSE, xscale = 0.9, yspace = unit(0.5, "lines"), main = NULL, sub = NULL, \dots, residuals_type = "Pearson", gp_axis = gpar(lty = 3)) \method{assoc}{formula}(formula, data = NULL, \dots, subset = NULL, na.action = NULL, main = NULL, sub = NULL) } \arguments{ \item{x}{a contingency table in array form with optional category labels specified in the \code{dimnames(x)} attribute, or an object inheriting from the \code{"ftable"} class (such as \code{"structable"} objects).} \item{row_vars}{a vector of integers giving the indices, or a character vector giving the names of the variables to be used for the rows of the association plot.} \item{col_vars}{a vector of integers giving the indices, or a character vector giving the names of the variables to be used for the columns of the association plot.} \item{compress}{logical; if \code{FALSE}, the space between the rows (columns) are chosen such that the \emph{total} heights (widths) of the rows (columns) are all equal. If \code{TRUE}, the space between rows and columns is fixed and hence the plot is more \dQuote{compressed}.} \item{xlim}{a \eqn{2 \times k}{2 x k} matrix of doubles, \eqn{k} number of total columns of the plot. The columns of \code{xlim} correspond to the columns of the association plot, the rows describe the column ranges (minimums in the first row, maximums in the second row). If \code{xlim} is \code{NULL}, the ranges are determined from the residuals according to \code{compress} (if \code{TRUE}: widest range from each column, if \code{FALSE}: from the whole association plot matrix).} \item{ylim}{a \eqn{2 \times k}{2 x k} matrix of doubles, \eqn{k} number of total rows of the plot. The columns of \code{ylim} correspond to the rows of the association plot, the rows describe the column ranges (minimums in the first row, maximums in the second row). If \code{ylim} is \code{NULL}, the ranges are determined from the residuals according to \code{compress} (if \code{TRUE}: widest range from each row, if \code{FALSE}: from the whole association plot matrix).} \item{spacing}{a spacing object, a spacing function, or a corresponding generating function (see \code{\link{strucplot}} for more information). The default is the spacing-generating function \code{\link{spacing_conditional}} that is (by default) called with the argument list \code{spacing_args} (see \code{spacings} for more details).} \item{spacing_args}{list of arguments for the spacing-generating function, if specified (see \code{\link{strucplot}} for more information).} \item{split_vertical}{vector of logicals of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (default: \code{FALSE}). Values are recycled as needed. A \code{TRUE} component indicates that the corresponding dimension is folded into the columns, \code{FALSE} folds the dimension into the rows.} \item{keep_aspect_ratio}{logical indicating whether the aspect ratio should be fixed or not.} \item{residuals_type}{a character string indicating the type of residuals to be computed. Currently, only Pearson residuals are supported.} \item{xscale}{scale factor resizing the tile's width, thus adding additional space between the tiles. } \item{yspace}{object of class \code{"unit"} specifying additional space separating the rows.} \item{gp_axis}{object of class \code{"gpar"} specifying the visual aspects of the tiles' baseline.} \item{formula}{a formula object with possibly both left and right hand sides specifying the column and row variables of the flat table.} \item{data}{a data frame, list or environment containing the variables to be cross-tabulated, or an object inheriting from class \code{table}.} \item{subset}{an optional vector specifying a subset of observations to be used. Ignored if \code{data} is a contingency table.} \item{na.action}{an optional function which indicates what should happen when the data contain \code{NA}s. Ignored if \code{data} is a contingency table.} \item{main, sub}{either a logical, or a character string used for plotting the main (sub) title. If logical and \code{TRUE}, the name of the \code{data} object is used.} \item{\dots}{other parameters passed to \code{\link{strucplot}}} } \details{ Association plots have been suggested by Cohen (1980) and extended by Friendly (1992) and provide a means for visualizing the residuals of an independence model for a contingency table. \code{assoc} is a generic function and currently has a default method and a formula interface. Both are high-level interfaces to the \code{\link{strucplot}} function, and produce (extended) association plots. Most of the functionality is described there, such as specification of the independence model, labeling, legend, spacing, shading, and other graphical parameters. For a contingency table, the signed contribution to Pearson's \eqn{\chi^2}{chi^2} for cell \eqn{\{ij\ldots k\}} is \deqn{d_{ij\ldots k} = \frac{(f_{ij\ldots k} - e_{ij\ldots k})}{ \sqrt{e_{ij\ldots k}}}}{d_\{ij\ldotsk\} = (f_\{ij\ldotsk\} - e_\{ij\ldotsk\}) / sqrt(e_\{ij\ldotsk\})} where \eqn{f_{ij\ldots k}}{f_\{ij\ldotsk\}} and \eqn{e_{ij\ldots k}}{e_\{ij\ldotsk\}} are the observed and expected counts corresponding to the cell. In the association plot, each cell is represented by a rectangle that has (signed) height proportional to \eqn{d_{ij\ldots k}}{d_\{ij\ldotsk\}} and width proportional to \eqn{\sqrt{e_{ij\ldots k}}}{sqrt(e_\{ij...k\})}, so that the area of the box is proportional to the difference in observed and expected frequencies. The rectangles in each row are positioned relative to a baseline indicating independence (\eqn{d_{ij\ldots k} = 0}{d_\{ij\ldotsk\} = 0}). If the observed frequency of a cell is greater than the expected one, the box rises above the baseline, and falls below otherwise. Additionally, the residuals can be colored depending on a specified shading scheme (see Meyer et al., 2003). Package \pkg{vcd} offers a range of \emph{residual-based} shadings (see the shadings help page). Some of them allow, e.g., the visualization of test statistics. Unlike the \code{\link[graphics]{assocplot}} function in the \pkg{graphics} package, this function allows the visualization of contingency tables with more than two dimensions. Similar to the construction of \sQuote{flat} tables (like objects of class \code{"ftable"} or \code{"structable"}), the dimensions are folded into rows and columns. The layout is very flexible: the specification of shading, labeling, spacing, and legend is modularized (see \code{\link{strucplot}} for details). } \value{ The \code{"structable"} visualized is returned invisibly. } \seealso{ \code{\link{mosaic}}, \code{\link{strucplot}}, \code{\link{structable}} } \references{ Cohen, A. (1980), On the graphical display of the significant components in a two-way contingency table. \emph{Communications in Statistics---Theory and Methods}, \bold{A9}, 1025--1041. Friendly, M. (1992), Graphical methods for categorical data. \emph{SAS User Group International Conference Proceedings}, \bold{17}, 190--200. \url{http://datavis.ca/papers/sugi/sugi17.pdf} Meyer, D., Zeileis, A., Hornik, K. (2003), Visualizing independence using extended association plots. \emph{Proceedings of the 3rd International Workshop on Distributed Statistical Computing}, K. Hornik, F. Leisch, A. Zeileis (eds.), ISSN 1609-395X. \url{http://www.ci.tuwien.ac.at/Conferences/DSC-2003/Proceedings/} Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("HairEyeColor") ## Aggregate over sex: (x <- margin.table(HairEyeColor, c(1, 2))) ## Ordinary assocplot: assoc(x) ## and with residual-based shading (of independence) assoc(x, main = "Relation between hair and eye color", shade = TRUE) ## Aggregate over Eye color: (x <- margin.table(HairEyeColor, c(1, 3))) chisq.test(x) assoc(x, main = "Relation between hair color and sex", shade = TRUE) # Visualize multi-way table assoc(aperm(HairEyeColor), expected = ~ (Hair + Eye) * Sex, labeling_args = list(just_labels = c(Eye = "left"), offset_labels = c(right = -0.5), offset_varnames = c(right = 1.2), rot_labels = c(right = 0), tl_varnames = c(Eye = TRUE)) ) assoc(aperm(UCBAdmissions), expected = ~ (Admit + Gender) * Dept, compress = FALSE, labeling_args = list(abbreviate = c(Gender = TRUE), rot_labels = 0) ) } \keyword{hplot} vcd/man/OvaryCancer.Rd0000644000175300001440000000373611150520606014160 0ustar meyerusers\name{OvaryCancer} \alias{OvaryCancer} \docType{data} \title{Ovary Cancer Data} \description{ Data from Obel (1975) about a retrospective study of ovary cancer carried out in 1973. Information was obtained from 299 women, who were operated for ovary cancer 10 years before. } \usage{ data("OvaryCancer") } \format{ A data frame with 16 observations and 5 variables. \describe{ \item{Freq}{frequency.} \item{stage}{factor indicating the stage of the cancer at the time of operation (early, advanced).} \item{operation}{factor indicating type of operation (radical, limited).} \item{survival}{factor indicating survival status after 10 years (yes, no).} \item{xray}{factor indicating whether X-ray treatment was received (yes, no).} } } \references{ E. B. Obel (1975), A Comparative Study of Patients with Cancer of the Ovary Who Have Survived More or Less Than 10 Years. \emph{Acta Obstetricia et Gynecologica Scandinavica}, \bold{55}, 429-439. E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, Table 6.4. } \examples{ data("OvaryCancer") tab <- xtabs(Freq ~ xray + survival + stage + operation, data = OvaryCancer) ftable(tab, col.vars = "survival", row.vars = c("stage", "operation", "xray")) ## model: ~ xray * operation * stage + survival * stage ## interpretation: treat xray, operation, stage as fixed margins, ## the survival depends on stage, but not xray and operation. doubledecker(survival ~ stage + operation + xray, data = tab) mosaic(~ stage + operation + xray + survival, split = c(FALSE, TRUE, TRUE, FALSE), data = tab, keep = FALSE, gp = gpar(fill = rev(grey.colors(2)))) mosaic(~ stage + operation + xray + survival, split = c(FALSE, TRUE, TRUE, FALSE), data = tab, keep = FALSE, expected = ~ xray * operation * stage + survival*stage) } \keyword{datasets} vcd/man/DanishWelfare.Rd0000644000175300001440000000230011150520606014442 0ustar meyerusers\name{DanishWelfare} \alias{DanishWelfare} \docType{data} \title{Danish Welfare Study Data} \description{ Data from the Danish Welfare Study. } \usage{data("DanishWelfare")} \format{ A data frame with 180 observations and 5 variables. \describe{ \item{Freq}{frequency.} \item{Alcohol}{factor indicating daily alcohol consumption: less than 1 unit (<1), 1-2 units (1-2) or more than 2 units (>2). 1 unit is approximately 1 bottle of beer or 4cl 40\% alcohol.} \item{Income}{factor indicating income group in 1000 DKK (0-50, 50-100, 100-150, >150).} \item{Status}{factor indicating marriage status (Widow, Married, Unmarried).} \item{Urban}{factor indicating urbanization: Copenhagen (Copenhagen), Suburbian Copenhagen (SubCopenhagen), three largest cities (LargeCity), other cities (City), countryside (Country).} } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, page 205. } \examples{ data("DanishWelfare") ftable(xtabs(Freq ~ ., data = DanishWelfare)) } \keyword{datasets} vcd/man/Bundesliga.Rd0000644000175300001440000000414211223326553014017 0ustar meyerusers\name{Bundesliga} \alias{Bundesliga} \title{Ergebnisse der Fussball-Bundesliga} \description{ Results from the first German soccer league (1963-2008). } \usage{ data("Bundesliga") } \format{A data frame with 14018 observations and 7 variables. \describe{ \item{HomeTeam}{factor. Name of the home team.} \item{AwayTeam}{factor. Name of the away team.} \item{HomeGoals}{number of goals scored by the home team.} \item{AwayGoals}{number of goals scored by the away team.} \item{Round}{round of the game.} \item{Year}{year in which the season started.} \item{Date}{starting time of the game (in \code{"POSIXct"} format).} } } \details{ The data comprises all games in the first German soccer league since its foundation in 1963. The data have been queried online from the official Web page of the DFB and prepared as a data frame in R by Daniel Dekic, Torsten Hothorn, and Achim Zeileis (replacing earlier versions of the data in the package containing only subsets of years). Each year/season comprises 34 rounds (except 1963, 1964, 1991) so that all 18 teams play twice against each other (switching home court advantage). In 1963/64, there were only 16 teams, hence only 30 rounds. In 1991, after the German unification, there was one season with 20 teams and 38 rounds. } \source{ Homepage of the Deutscher Fussball-Bund (DFB, German Football Association): \url{http://www.dfb.de/} } \references{ Leonhard Knorr-Held (1999), Dynamic rating of sports teams. SFB 386 \dQuote{Statistical Analysis of Discrete Structures}, Discussion paper \bold{98}. } \seealso{ \code{\link{UKSoccer}} } \examples{ data("Bundesliga") ## number of goals per game poisson distributed? ngoals1 <- xtabs(~ HomeGoals, data = Bundesliga, subset = Year == 1995) ngoals2 <- xtabs(~ AwayGoals, data = Bundesliga, subset = Year == 1995) ngoals3 <- table(apply(subset(Bundesliga, Year == 1995)[,3:4], 1, sum)) gf1 <- goodfit(ngoals1) gf2 <- goodfit(ngoals2) gf3 <- goodfit(ngoals3) summary(gf1) summary(gf2) summary(gf3) plot(gf1) plot(gf2) plot(gf3) Ord_plot(ngoals1) distplot(ngoals1) } \keyword{datasets} vcd/man/cotab_panel.Rd0000644000175300001440000000716711150520606014215 0ustar meyerusers\name{cotab_panel} \alias{cotab_mosaic} \alias{cotab_assoc} \alias{cotab_sieve} \alias{cotab_coindep} \alias{cotab_fourfold} \title{Panel-generating Functions for Contingency Table Coplots} \description{ Panel-generating functions visualizing contingency tables that can be passed to \code{cotabplot}. } \usage{ cotab_mosaic(x = NULL, condvars = NULL, \dots) cotab_assoc(x = NULL, condvars = NULL, ylim = NULL, \dots) cotab_sieve(x = NULL, condvars = NULL, \dots) cotab_fourfold(x = NULL, condvars = NULL, \dots) cotab_coindep(x, condvars, test = c("doublemax", "maxchisq", "sumchisq"), level = NULL, n = 1000, interpolate = c(2, 4), h = NULL, c = NULL, l = NULL, lty = 1, type = c("mosaic", "assoc"), legend = FALSE, ylim = NULL, \dots) } \arguments{ \item{x}{a contingency tables in array form.} \item{condvars}{margin name(s) of the conditioning variables.} \item{ylim}{y-axis limits for \code{assoc} plot. By default this is computed from \code{x}.} \item{test}{character indicating which type of statistic should be used for assessing conditional independence.} \item{level,n,h,c,l,lty,interpolate}{variables controlling the HCL shading of the residuals, see \code{\link{shadings}} for more details.} \item{type}{character indicating which type of plot should be produced.} \item{legend}{logical. Should a legend be produced in each panel?} \item{\dots}{further arguments passed to the plotting function (such as \code{\link{mosaic}} or \code{\link{assoc}} or \code{\link{sieve}} respectively).} } \details{ These functions of class \code{"panel_generator"} are panel-generating functions for use with \code{\link{cotabplot}}, i.e., they return functions with the interface \code{panel(x, condlevels)} required for \code{cotabplot}. The functions produced by \code{cotab_mosaic}, \code{cotab_assoc} and \code{cotab_sieve} essentially only call \code{co_table} to produce the conditioned table and then call \code{\link{mosaic}}, \code{\link{assoc}} or \code{\link{sieve}} respectively with the arguments specified. The function \code{cotab_coindep} is similar but additionally chooses an appropriate residual-based shading visualizing the associated conditional independence model. The conditional independence test is carried out via \code{\link{coindep_test}} and the shading is set up via \code{\link{shading_hcl}}. A description of the underlying ideas is given in Zeileis, Meyer, Hornik (2005). } \seealso{ \code{\link{cotabplot}}, \code{\link{mosaic}}, \code{\link{assoc}}, \code{\link{sieve}}, \code{\link{co_table}}, \code{\link{coindep_test}}, \code{\link{shading_hcl}} } \references{ Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. Zeileis, A., Meyer, D., Hornik K. (2007), \emph{Residual-based shadings for visualizing (conditional) independence}, \emph{Journal of Computational and Graphical Statistics}, \bold{16}, 507--525. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \examples{ data("UCBAdmissions") cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions) cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions, panel = cotab_assoc) cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions, panel = cotab_fourfold) ucb <- cotab_coindep(UCBAdmissions, condvars = "Dept", type = "assoc", n = 5000, margins = c(3, 1, 1, 3)) cotabplot(~ Admit + Gender | Dept, data = UCBAdmissions, panel = ucb) } \keyword{hplot} vcd/man/Employment.Rd0000644000175300001440000000342011150520606014063 0ustar meyerusers\name{Employment} \alias{Employment} \docType{data} \title{Employment Status} \description{ Data from a 1974 Danish study given by Andersen (1991) on the employees who had been laid off. The workers are classified by their employment status on 1975-01-01, the cause of their layoff and the length of employment before they were laid off. } \usage{ data("Employment") } \format{ A 3-dimensional array resulting from cross-tabulating variables for 1314 employees. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab EmploymentStatus \tab NewJob, Unemployed \cr 2 \tab EmploymentLength \tab <1Mo, 1-3Mo, 3-12Mo, 1-2Yr, 2-5Yr, >5Yr \cr 3 \tab LayoffCause \tab Closure, Replaced } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. Springer-Verlag, Berlin. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data, pages 126--129. } \examples{ data("Employment") ## Employment Status mosaic(Employment, expected = ~ LayoffCause * EmploymentLength + EmploymentStatus, main = "Layoff*EmployLength + EmployStatus") mosaic(Employment, expected = ~ LayoffCause * EmploymentLength + LayoffCause * EmploymentStatus, main = "Layoff*EmployLength + Layoff*EmployStatus") ## Stratified view grid.newpage() pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) ## Closure mosaic(Employment[,,1], main = "Layoff: Closure", newpage = FALSE) popViewport(1) pushViewport(viewport(layout.pos.col = 2)) ## Replaced mosaic(Employment[,,2], main = "Layoff: Replaced", newpage = FALSE) popViewport(2) } \keyword{datasets} vcd/man/Hospital.Rd0000644000175300001440000000241611235655727013542 0ustar meyerusers\name{Hospital} \alias{Hospital} \docType{data} \title{Hospital data} \description{ The table relates the length of stay (in years) of 132 long-term schizophrenic patients in two London mental hospitals with the frequency of visits. } \usage{ data("Hospital") } \format{ A 2-dimensional array resulting from cross-tabulating 132 patients. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab Visit Frequency \tab Regular, Less than monthly, Never \cr 2 \tab Length of Stay \tab 2--9 years, 10--19 years, 20+ years } } \references{ J.K. Wing (1962): Institutionalism in mental hospitals. British Journal of Social Clinical Psychology, 1:38--51. } \source{ S.J Haberman (1974): Log-linear models for frequency tables with ordered classifications. Biometrics, 30:689--700. } \details{ Wing (1962) who collected this data concludes that the longer the length of stay in hospital, the less frequent the visits. Haberman (1974) notes that this pattern does not increase from the "Less than monthly" to the "Never" group, which are homogeneous. } \examples{ data("Hospital") mosaic(t(Hospital), shade = TRUE) mosaic(Hospital, shade = TRUE) sieve(Hospital, shade = TRUE) assoc(Hospital, shade = TRUE) } \keyword{datasets} vcd/man/goodfit.Rd0000644000175300001440000001131011363154670013374 0ustar meyerusers\name{goodfit} \alias{goodfit} \alias{summary.goodfit} \alias{plot.goodfit} \alias{predict.goodfit} \alias{fitted.goodfit} \alias{print.goodfit} \title{Goodness-of-fit Tests for Discrete Data} \description{ Fits a discrete (count data) distribution for goodness-of-fit tests. } \usage{ goodfit(x, type = c("poisson", "binomial", "nbinomial"), method = c("ML", "MinChisq"), par = NULL) \method{predict}{goodfit}(object, newcount = NULL, type = c("response", "prob"), \dots) } \arguments{ \item{x}{either a vector of counts, a 1-way table of frequencies of counts or a data frame or matrix with frequencies in the first column and the corresponding counts in the second column.} \item{type}{a character string indicating which distribution should be fit (for \code{goodfit}) or indicating the type of prediction (fitted response or probabilities in \code{predict}) respectively.} \item{method}{a character string indicating whether the distribution should be fit via ML (Maximum Likelihood) or Minimum Chi-squared.} \item{par}{a named list giving the distribution parameters (named as in the corresponding density function), if set to \code{NULL}, the default, the parameters are estimated. If the parameter \code{size} is not specified if \code{type} is \code{"binomial"} it is taken to be the maximum count. If \code{type} is \code{"nbinomial"}, then parameter \code{size} can be specified to fix it so that only the parameter \code{prob} will be estimated (see the examples below).} \item{object}{an object of class \code{"goodfit"}.} \item{newcount}{a vector of counts. By default the counts stored in \code{object} are used, i.e., the fitted values are computed. These can also be extracted by \code{fitted(object)}.} \item{\dots}{\emph{currently not used}.} } \details{ \code{goodfit} essentially computes the fitted values of a discrete distribution (either Poisson, binomial or negative binomial) to the count data given in \code{x}. If the parameters are not specified they are estimated either by ML or Minimum Chi-squared. To fix parameters, \code{par} should be a named list specifying the parameters \code{lambda} for \code{"poisson"} and \code{prob} and \code{size} for \code{"binomial"} or \code{"nbinomial"}, respectively. If for \code{"binomial"}, \code{size} is not specified it is not estimated but taken as the maximum count. The corresponding Pearson Chi-squared or likelihood ratio statistic, respectively, is computed and given with their \eqn{p} values by the \code{summary} method. The \code{summary} method always prints this information and returns a matrix with the printed information invisibly. The \code{plot} method produces a \code{\link{rootogram}} of the observed and fitted values. In case of count distribtions (Poisson and negative binomial), the minimum Chi-squared approach is somewhat ad hoc. Strictly speaking, the Chi-squared asymptotics would only hold if the number of cells were fixed or did not increase too quickly with the sample size. However, in \code{goodfit} the number of cells is data-driven: Each count is a cell of its own. All counts larger than the maximal count are merged into the cell with the last count for computing the test statistic. } \value{ A list of class \code{"goodfit"} with elements: \item{observed}{observed frequencies.} \item{count}{corresponding counts.} \item{fitted}{expected frequencies (fitted by ML).} \item{type}{a character string indicating the distribution fitted.} \item{method}{a character string indicating the fitting method (can be either \code{"ML"}, \code{"MinChisq"} or \code{"fixed"} if the parameters were specified).} \item{df}{degrees of freedom.} \item{par}{a named list of the (estimated) distribution parameters.} } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \references{ M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \examples{ ## Simulated data examples: dummy <- rnbinom(200, size = 1.5, prob = 0.8) gf <- goodfit(dummy, type = "nbinomial", method = "MinChisq") summary(gf) plot(gf) dummy <- rbinom(100, size = 6, prob = 0.5) gf1 <- goodfit(dummy, type = "binomial", par = list(size = 6)) gf2 <- goodfit(dummy, type = "binomial", par = list(prob = 0.6, size = 6)) summary(gf1) plot(gf1) summary(gf2) plot(gf2) ## Real data examples: data("HorseKicks") HK.fit <- goodfit(HorseKicks) summary(HK.fit) plot(HK.fit) data("Federalist") ## try geometric and full negative binomial distribution F.fit <- goodfit(Federalist, type = "nbinomial", par = list(size = 1)) F.fit2 <- goodfit(Federalist, type = "nbinomial") summary(F.fit) summary(F.fit2) plot(F.fit) plot(F.fit2) } \keyword{category} vcd/man/Ord_plot.Rd0000644000175300001440000000763111150520606013524 0ustar meyerusers\name{Ord_plot} \alias{Ord_plot} \alias{Ord_estimate} \title{Ord Plots} \description{ Ord plots for diagnosing discrete distributions. } \usage{ Ord_plot(obj, legend = TRUE, estimate = TRUE, tol = 0.1, type = NULL, xlim = NULL, ylim = NULL, xlab = "Number of occurrences", ylab = "Frequency ratio", main = "Ord plot", gp = gpar(cex = 0.5), name = "Ord_plot", newpage = TRUE, pop = TRUE, \dots) Ord_estimate(x, type = NULL, tol = 0.1) } \arguments{ \item{obj}{either a vector of counts, a 1-way table of frequencies of counts or a data frame or matrix with frequencies in the first column and the corresponding counts in the second column.} \item{legend}{logical. Should a legend be plotted?.} \item{estimate}{logical. Should the distribution and its parameters be estimated from the data? See details.} \item{tol}{tolerance for estimating the distribution. See details.} \item{type}{a character string indicating the distribution, must be one of \code{"poisson"}, \code{"binomial"}, \code{"nbinomial"} or \code{"log-series"} or \code{NULL}. In the latter case the distribution is estimated from the data. See details.} \item{xlim}{limits for the x axis.} \item{ylim}{limits for the y axis.} \item{xlab}{a label for the x axis.} \item{ylab}{a label for the y axis.} \item{main}{a title for the plot.} \item{gp}{a \code{"gpar"} object controlling the grid graphical parameters of the points.} \item{name}{name of the plotting viewport.} \item{newpage}{logical. Should \code{\link{grid.newpage}} be called before plotting?} \item{pop}{logical. Should the viewport created be popped?} \item{\dots}{further arguments passed to \code{\link{grid.points}}.} \item{x}{a vector giving intercept and slope for the (fitted) line in the Ord plot.} } \details{ The Ord plot plots the number of occurrences against a certain frequency ratio (see Friendly (2000) for details) and should give a straight line if the data comes from a poisson, binomial, negative binomial or log-series distribution. The intercept and slope of this straight line conveys information about the underlying distribution. \code{Ord_plot} fits a usual OLS line (black) and a weighted OLS line (red). From the coefficients of the latter the distribution is estimated by \code{Ord_estimate} as described in Table 2.10 in Friendly (2000). To judge whether a coefficient is positive or negative a tolerance given by \code{tol} is used. If none of the distributions fits well, no parameters are estimated. Be careful with the conclusions from \code{Ord_estimate} as it implements just some simple heuristics! } \value{ A vector giving the intercept and slope of the weighted OLS line. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \references{ J. K. Ord (1967), Graphical methods for a class of discrete distributions, \emph{Journal of the Royal Statistical Society}, \bold{A 130}, 232--238. Michael Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \examples{ ## Simulated data examples: dummy <- rnbinom(1000, size = 1.5, prob = 0.8) Ord_plot(dummy) ## Real data examples: data("HorseKicks") data("Federalist") data("Butterfly") data("WomenQueue") grid.newpage() pushViewport(viewport(layout = grid.layout(2, 2))) pushViewport(viewport(layout.pos.col=1, layout.pos.row=1)) Ord_plot(HorseKicks, main = "Death by horse kicks", newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col=1, layout.pos.row=2)) Ord_plot(Federalist, main = "Instances of 'may' in Federalist papers", newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col=2, layout.pos.row=1)) Ord_plot(Butterfly, main = "Butterfly species collected in Malaya", newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col=2, layout.pos.row=2)) Ord_plot(WomenQueue, main = "Women in queues of length 10", newpage = FALSE) popViewport(2) } \keyword{category} vcd/man/pairs.table.Rd0000644000175300001440000001425211474031017014145 0ustar meyerusers\name{pairs.table} \alias{pairs.table} \alias{pairs.structable} \title{Pairs Plot for Contingency Tables} \description{ Produces a matrix of strucplot displays. } \usage{ \method{pairs}{table}(x, upper_panel = pairs_mosaic, upper_panel_args = list(), lower_panel = pairs_mosaic, lower_panel_args = list(), diag_panel = pairs_barplot, diag_panel_args = list(), main = NULL, sub = NULL, main_gp = gpar(fontsize = 20), sub_gp = gpar(fontsize = 15), space = 0.3, newpage = TRUE, pop = TRUE, margins = unit(1, "lines"), \dots) } \arguments{ \item{x}{a contingency table in array form, with optional category labels specified in the \code{dimnames(x)} attribute.} \item{upper_panel}{function for the upper triangle of the matrix, or corresponding generating function. If \code{NULL}, no panel is drawn.} \item{upper_panel_args}{list of arguments for the generating function, if specified.} \item{lower_panel}{function for the lower triangle of the matrix, or corresponding generating function. If \code{NULL}, no panel is drawn.} \item{lower_panel_args}{list of arguments for the panel-generating function, if specified.} \item{diag_panel}{function for the diagonal of the matrix, or corresponding generating function. If \code{NULL}, no panel is drawn.} \item{diag_panel_args}{list of arguments for the generating function, if specified.} \item{main}{either a logical, or a character string used for plotting the main title. If \code{main} is a logical and \code{TRUE}, the name of the object supplied as \code{x} is used.} \item{sub}{a character string used for plotting the subtitle. If \code{sub} is a logical and \code{TRUE} and \code{main} is unspecified, the name of the object supplied as \code{x} is used.} \item{main_gp, sub_gp}{object of class \code{"gpar"} containing the graphical parameters used for the main (sub) title, if specified.} \item{space}{double specifying the distance between the cells.} \item{newpage}{logical controlling whether a new grid page should be created.} \item{pop}{logical indicating whether all viewports should be popped after the plot has been drawn.} \item{margins}{either an object of class \code{"unit"} of length 4, or a numeric vector of length 4. The elements are recycled as needed. The four components specify the top, right, bottom, and left margin of the plot, respectively. When a numeric vector is supplied, the numbers are interpreted as \code{"lines"} units. In addition, the unit or numeric vector may have named arguments (\samp{top}, \samp{right}, \samp{bottom}, and \samp{left}), in which case the non-named arguments specify the default values (recycled as needed), overloaded by the named arguments.} \item{\dots}{For convenience, list of arguments for the panel-generating functions of upper and lower panels, if specified.} } \details{ This is a \code{\link[graphics]{pairs}} method for objects inheriting from class \code{"table"} or \code{"structable"}. It plots a matrix of pairwise mosaic plots. Four independence types are distinguished: \code{"pairwise"}, \code{"total"}, \code{"conditional"} and \code{"joint"}. The pairwise mosaic matrix shows bivariate marginal relations, collapsed over all other variables. The total independence mosaic matrix shows mosaic plots for mutual independence, i.e., for marginal and conditional independence among all pairs of variables. The conditional independence mosaic matrix shows mosaic plots for marginal independence given all other variables. The joint independence mosaic matrix shows mosaic plots for joint independence of all pairs of variables from the others. This method uses panel functions called for each cell of the matrix which can be different for upper matrix, lower matrix, and diagonal cells. Correspondingly, for each panel parameter \var{foo} (= \samp{upper}, \samp{lower}, or \samp{diag}), \code{pairs.table} takes two arguments: \var{foo\_panel} and \var{foo\_panel\_args}, which can be used to specify the parameters as follows: \enumerate{ \item Passing a suitable panel function to \var{foo\_panel} which subsequently is called for each cell with the corresponding coordinates. \item Passing a corresponding \emph{generating function} (of class \code{"panel_generator"}) to \var{foo\_panel}, along with parameters passed to \var{foo\_panel\_args}, that generates such a function. } Hence, the second approach is equivalent to the first if \var{foo\_panel(foo\_panel\_args)} is passed to \var{foo\_panel}. } \seealso{ \code{\link{pairs_mosaic}}, \code{\link{pairs_assoc}}, \code{\link{pairs_sieve}}, \code{\link{pairs_diagonal_text}}, \code{\link{pairs_text}}, \code{\link{pairs_barplot}}, \code{\link{assoc}}, \code{\link{sieve}}, \code{\link{mosaic}} } \references{ Cohen, A. (1980), On the graphical display of the significant components in a two-way contingency table. \emph{Communications in Statistics---Theory and Methods}, \bold{A9}, 1025--1041. Friendly, M. (1992), Graphical methods for categorical data. \emph{SAS User Group International Conference Proceedings}, \bold{17}, 190--200. \url{http://datavis.ca/sugi/sugi17.pdf} Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("UCBAdmissions") data("PreSex") data(HairEyeColor) hec = structable(Eye ~ Sex + Hair, data = HairEyeColor) pairs(PreSex) pairs(UCBAdmissions) pairs(UCBAdmissions, upper_panel_args = list(shade = TRUE)) pairs(UCBAdmissions, lower_panel = pairs_mosaic(type = "conditional")) pairs(UCBAdmissions, diag_panel = pairs_text) pairs(UCBAdmissions, upper_panel = pairs_assoc, shade = TRUE) pairs(hec, highlighting = 2, diag_panel_args = list(fill = grey.colors)) pairs(hec, highlighting = 2, diag_panel = pairs_diagonal_mosaic, diag_panel_args = list(fill = grey.colors, alternate_labels =TRUE)) } \keyword{hplot} vcd/man/ternaryplot.Rd0000644000175300001440000001010411437031640014315 0ustar meyerusers\name{ternaryplot} \alias{ternaryplot} \title{Ternary Diagram} \description{ Visualizes compositional, 3-dimensional data in an equilateral triangle. } \usage{ ternaryplot(x, scale = 1, dimnames = NULL, dimnames_position = c("corner","edge","none"), dimnames_color = "black", id = NULL, id_color = "black", id_just = c("center", "center"), coordinates = FALSE, grid = TRUE, grid_color = "gray", labels = c("inside", "outside", "none"), labels_color = "darkgray", border = "black", bg = "white", pch = 19, cex = 1, prop_size = FALSE, col = "red", main = "ternary plot", newpage = TRUE, pop = TRUE, \dots) } \arguments{ \item{x}{a matrix with three columns.} \item{scale}{row sums scale to be used.} \item{dimnames}{dimension labels (defaults to the column names of \code{x}).} \item{dimnames_position, dimnames_color}{position and color of dimension labels.} \item{id}{optional labels to be plotted below the plot symbols. \code{coordinates} and \code{id} are mutual exclusive.} \item{id_color}{color of these labels.} \item{id_just}{character vector of length 1 or 2 indicating the justification of these labels.} \item{coordinates}{if \code{TRUE}, the coordinates of the points are plotted below them. \code{coordinates} and \code{id} are mutual exclusive.} \item{grid}{if \code{TRUE}, a grid is plotted. May optionally be a string indicating the line type (default: \code{"dotted"}).} \item{grid_color}{grid color.} \item{labels, labels_color}{position and color of the grid labels.} \item{border}{color of the triangle border.} \item{bg}{triangle background.} \item{pch}{plotting character. Defaults to filled dots.} \item{cex}{a numerical value giving the amount by which plotting text and symbols should be scaled relative to the default. Ignored for the symbol size if \code{prop_size} is not \code{FALSE}.} \item{prop_size}{if \code{TRUE}, the symbol size is plotted proportional to the row sum of the three variables, i.e., represents the weight of the observation.} \item{col}{plotting color.} \item{main}{main title.} \item{newpage}{if \code{TRUE}, the plot will appear on a new graphics page.} \item{pop}{logical; if \code{TRUE}, all newly generated viewports are popped after plotting.} \item{\dots}{additional graphics parameters (see \code{par})} } \details{ A points' coordinates are found by computing the gravity center of mass points using the data entries as weights. Thus, the coordinates of a point \eqn{P(a,b,c)}, \eqn{a + b + c = 1}, are: \eqn{P(b + c/2, c \sqrt{3}/2)}{P(b + c/2, c * sqrt(3)/2)}. } \references{ M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("Arthritis") ## Build table by crossing Treatment and Sex tab <- as.table(xtabs(~ I(Sex:Treatment) + Improved, data = Arthritis)) ## Mark groups col <- c("red", "red", "blue", "blue") pch <- c(1, 19, 1, 19) ## plot ternaryplot( tab, col = col, pch = pch, prop_size = TRUE, bg = "lightgray", grid_color = "white", labels_color = "white", main = "Arthritis Treatment Data" ) ## legend grid_legend(0.8, 0.7, pch, col, rownames(tab), title = "GROUP") ## Titanic data("Lifeboats") attach(Lifeboats) ternaryplot( Lifeboats[,4:6], pch = ifelse(side == "Port", 1, 19), col = ifelse(side == "Port", "red", "blue"), id = ifelse(men / total > 0.1, as.character(boat), NA), prop_size = 2, dimnames_position = "edge", main = "Lifeboats on Titanic" ) grid_legend(0.8, 0.9, c(1, 19), c("red", "blue"), c("Port", "Starboard"), title = "SIDE") ## Hitters data("Hitters") attach(Hitters) colors <- c("black","red","green","blue","red","black","blue") pch <- substr(levels(Positions), 1, 1) ternaryplot( Hitters[,2:4], pch = as.character(Positions), col = colors[as.numeric(Positions)], main = "Baseball Hitters Data" ) grid_legend(0.8, 0.9, pch, colors, levels(Positions), title = "POSITION(S)") } \keyword{hplot} vcd/man/tile.Rd0000644000175300001440000001163511235655643012714 0ustar meyerusers\name{tile} \alias{tile} \alias{tile.default} \alias{tile.formula} \title{Tile Plot} \description{ Plots a tile display. } \usage{ \method{tile}{default}(x, tile_type = c("squaredarea", "area", "height", "width"), halign = c("left", "center", "right"), valign = c("bottom", "center", "top"), split_vertical = NULL, shade = FALSE, spacing = spacing_equal(unit(1, "lines")), set_labels = NULL, margins = unit(3, "lines"), keep_aspect_ratio = FALSE, legend_width = NULL, squared_tiles = TRUE, main = NULL, sub = NULL, ...) \method{tile}{formula}(formula, data, \dots, main = NULL, sub = NULL, subset = NULL, na.action = NULL) } \arguments{ \item{x}{a contingency table, or an object coercible to one.} \item{formula}{a formula specifying the variables used to create a contingency table from \code{data}}. \item{data}{either a data frame, or an object of class \code{"table"} or \code{"ftable"}.} \item{subset}{an optional vector specifying a subset of observations to be used.} \item{na.action}{a function which indicates what should happen when the data contain \code{NA}s. Ignored if \code{data} is a contingency table.} \item{tile_type}{character string indicating how the tiles should reflect the table frequencies (see details).} \item{halign, valign}{character string specifying the horizontal and vertical alignment of the tiles.} \item{split_vertical}{vector of logicals of length \eqn{k}, where \eqn{k} is the number of margins of \code{x} (values are recycled as needed). A \code{TRUE} component indicates that the tile(s) of the corresponding dimension should be split vertically, \code{FALSE} means horizontal splits. Default is \code{FALSE.}} \item{spacing}{spacing object, spacing function, or corresponding generating function (see \code{\link{strucplot}} for more information).} \item{set_labels}{An optional character vector with named components replacing the so-specified variable names. The component names must exactly match the variable names to be replaced.} \item{shade}{logical specifying whether shading should be enabled or not (see \code{\link{strucplot}}).} \item{margins}{either an object of class \code{"unit"} of length 4, or a numeric vector of length 4. The elements are recycled as needed. The four components specify the top, right, bottom, and left margin of the plot, respectively. When a numeric vector is supplied, the numbers are interpreted as \code{"lines"} units. In addition, the unit or numeric vector may have named arguments (\samp{top}, \samp{right}, \samp{bottom}, and \samp{left}), in which case the non-named arguments specify the default values (recycled as needed), overloaded by the named arguments.} \item{legend_width}{An object of class \code{"unit"} of length 1 specifying the width of the legend (if any). Default: 5 lines.} \item{keep_aspect_ratio}{logical indicating whether the aspect ratio should be fixed or not. The default is \code{FALSE} to enable the creation of squared tiles.} \item{squared_tiles}{logical indicating whether white space should be added as needed to rows or columns to obtain squared tiles in case of an unequal number of row and column labels.} \item{main, sub}{either a logical, or a character string used for plotting the main (sub) title. If logical and \code{TRUE}, the name of the \code{data} object is used.} \item{\dots}{Other arguments passed to \code{\link{strucplot}}} } \details{ A tile plot is a matrix of tiles. For each tile, either the \code{"width"}, \code{"height"}, \code{"area"}, or squared area is proportional to the corresponding entry. The first three options allow column-wise, row-wise and overall comparisons, respectively. The last variant allows to compare the tiles both column-wise and row-wise, considering either the width or the height, respectively. In contrast to other high-level strucplot functions, \code{tile} also accepts a table with duplicated levels (see examples). In this case, artificial dimnames will be created, and the actual ones are drawn using \code{set_labels}. Note that multiway-tables are first \dQuote{flattened} using \code{structable}. } \value{ The \code{"structable"} visualized is returned invisibly. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{assoc}}, \code{\link{strucplot}}, \code{\link{mosaic}}, \code{\link{structable}}, } \examples{ data("Titanic") ## default plot tile(Titanic) tile(Titanic, type = "expected") tile(Titanic, shade = TRUE) ## some variations tile(Titanic, tile_type = "width", squared_tiles = FALSE) tile(Titanic, tile_type = "height", squared_tiles = FALSE) tile(Titanic, tile_type = "area", halign = "center", valign = "center") ## repeat levels tile(Titanic[,,,c(1,2,1,2)]) } \keyword{hplot} vcd/man/BrokenMarriage.Rd0000644000175300001440000000165311150520606014630 0ustar meyerusers\name{BrokenMarriage} \alias{BrokenMarriage} \docType{data} \title{Broken Marriage Data} \description{ Data from the Danish Welfare Study about broken marriages or permanent relationships depending on gender and social rank. } \usage{ data("BrokenMarriage") } \format{ A data frame with 20 observations and 4 variables. \describe{ \item{Freq}{frequency.} \item{gender}{factor indicating gender (male, female).} \item{rank}{factor indicating social rank (I, II, III, IV, V).} \item{broken}{factor indicating whether the marriage or permanent relationship was broken (yes, no).} } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, page 177. } \examples{ data("BrokenMarriage") structable(~ ., data = BrokenMarriage) } \keyword{datasets} vcd/man/hls.Rd0000644000175300001440000000132111150520606012516 0ustar meyerusers\name{hls} \alias{hls} \title{HLS Color Specification} \description{ Create a HLS color from specifying hue, luminance and saturation. } \usage{ hls(h = 1, l = 0.5, s = 1) } \arguments{ \item{h}{hue value in [0, 1].} \item{l}{luminance value in [0, 1].} \item{s}{saturation value in [0, 1].} } \details{ HLS colors are a similar specification of colors as HSV colors, but using hue/luminance/saturation rather that hue/saturation/value. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \seealso{ \code{\link{hsv}}, \code{\link{hcl2hex}}, \code{\link[colorspace]{polarLUV}} } \examples{ ## an HLS color wheel pie(rep(1, 12), col = sapply(1:12/12, function(x) hls(x))) } \keyword{hplot} vcd/man/grid_barplot.Rd0000644000175300001440000000265011235655402014415 0ustar meyerusers\name{grid_barplot} \alias{grid_barplot} \title{Barplot} \description{ Bar plots of 1-way tables in grid. } \usage{ grid_barplot(height, width = 0.8, offset = 0, names = NULL, xlim = NULL, ylim = NULL, xlab = "", ylab = "", main = "", gp = gpar(fill = "lightgray"), name = "grid_barplot", newpage = TRUE, pop = FALSE) } \arguments{ \item{height}{either a vector or a 1-way table of frequencies.} \item{width}{width of the bars (recycled if needed to the number of bars).} \item{offset}{offset of the bars (recycled if needed to the number of bars).} \item{names}{a vector of names for the bars, if set to \code{NULL} the names of \code{height} are used.} \item{xlim}{limits for the x axis.} \item{ylim}{limits for the y axis.} \item{xlab}{a label for the x axis.} \item{ylab}{a label for the y axis.} \item{main}{a title for the plot.} \item{gp}{a \code{"gpar"} object controlling the grid graphical parameters of the rectangles.} \item{name}{name of the plotting viewport.} \item{newpage}{logical. Should \code{\link{grid.newpage}} be called before plotting?} \item{pop}{logical. Should the viewport created be popped?} } \details{ \code{grid_barplot} mimics (some of) the features of \code{\link{barplot}}, but currently it only supports 1-way tables. } \author{ Achim Zeileis \email{Achim.Zeileis@R-project.org} } \examples{ grid_barplot(sample(1:6), names = letters[1:6]) } \keyword{hplot} vcd/man/MSPatients.Rd0000644000175300001440000000330611150520606013764 0ustar meyerusers\name{MSPatients} \alias{MSPatients} \docType{data} \title{Diagnosis of Multiple Sclerosis} \description{ Data from Westlund \& Kurland (1953) on the diagnosis of multiple sclerosis (MS): two samples of patients, one from Winnipeg and one from New Orleans, were each rated by two neurologists (one from each city) in four diagnostic categories. } \usage{ data("MSPatients") } \format{ A 3-dimensional array resulting from cross-tabulating 218 observations on 3 variables. The variables and their levels are as follows: \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab New Orleans Neurologist \tab Certain, Probable, Possible, Doubtful \cr 2 \tab Winnipeg Neurologist \tab Certain, Probable, Possible, Doubtful \cr 3 \tab Patients \tab Winnipeg, New Orleans } } \references{ K. B. Westlund \& L. T. Kurland (1953), Studies on multiple sclerosis in Winnipeg, Manitoba and New Orleans, Louisiana, \emph{American Journal of Hygiene}, \bold{57}, 380--396. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{M. Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/msdiag.sas} } \examples{ data("MSPatients") ## best visualized using a resized device, e.g. using: ## get(getOption("device"))(width = 12) pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) agreementplot(t(MSPatients[,,1]), main = "Winnipeg Patients", newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 2)) agreementplot(t(MSPatients[,,2]), main = "New Orleans Patients", newpage = FALSE) popViewport(2) dev.off() } \keyword{datasets} vcd/man/Baseball.Rd0000644000175300001440000000455111235655776013472 0ustar meyerusers\name{Baseball} \alias{Baseball} \docType{data} \title{Baseball Data} \description{ Baseball data. } \usage{ data("Baseball") } \format{ A data frame with 322 observations and 25 variables. \describe{ \item{name1}{player's first name.} \item{name2}{player's last name.} \item{atbat86}{times at Bat: number of official plate appearances by a hitter. It counts as an official at-bat as long as the batter does not walk, sacrifice, get hit by a pitch or reach base due to catcher's interference.} \item{hits86}{hits.} \item{homer86}{home runs.} \item{runs86}{the number of runs scored by a player. A run is scored by an offensive player who advances from batter to runner and touches first, second, third and home base in that order without being put out.} \item{rbi86}{Runs Batted In: A hitter earns a run batted in when he drives in a run via a hit, walk, sacrifice (bunt or fly) fielder's choice, hit-batsman or on an error (when the official scorer rules that the run would have scored anyway).} \item{walks86}{A \dQuote{walk} (or \dQuote{base on balls}) is an award of first base granted to a batter who receives four pitches outside the strike zone.} \item{years}{Years in the Major Leagues. Seems to count all years a player has actually played in the Major Leagues, not necessarily consecutive.} \item{atbat}{career times at bat.} \item{hits}{career hits.} \item{homeruns}{career home runs.} \item{runs}{career runs.} \item{rbi}{career runs batted in.} \item{walks}{career walks.} \item{league86}{player's league.} \item{div86}{player's division.} \item{team86}{player's team.} \item{posit86}{player's position (see \code{\link{Hitters}}).} \item{outs86}{number of putouts (see \code{\link{Hitters}})} \item{assist86}{number of assists (see \code{\link{Hitters}})} \item{error86}{number of assists (see \code{\link{Hitters}})} \item{sal87}{annual salary on opening day (in USD 1000).} \item{league87}{league in 1987.} \item{team87}{team in 1987.} } } \references{ M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ SAS System for Statistical Graphics, First Edition, page A2.3 } \seealso{\code{\link{Hitters}}} \examples{ data("Baseball") } \keyword{datasets} vcd/man/VisualAcuity.Rd0000644000175300001440000000203711150520606014357 0ustar meyerusers\name{VisualAcuity} \alias{VisualAcuity} \docType{data} \title{Visual Acuity in Left and Right Eyes} \description{ Data from Kendall & Stuart (1961) on unaided vision among 3,242 men and 7,477 women, all aged 30-39 and employed in the U.K. Royal Ordnance factories 1943-1946. } \usage{ data("VisualAcuity") } \format{ A data frame with 32 observations and 4 variables. \describe{ \item{Freq}{frequency of visual acuity measurements.} \item{right}{visual acuity on right eye.} \item{left}{visual acuity on left eye.} \item{gender}{factor indicating gender of patient.} } } \references{ M. G. Kendall & A. Stuart (1961), \emph{The Advanced Theory of Statistics}, Vol. 2. Griffin, London. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/vision.sas} } \examples{ data("VisualAcuity") structable(~ gender + left + right, data = VisualAcuity) } \keyword{datasets} vcd/man/struc_sieve.Rd0000644000175300001440000000407111236052754014301 0ustar meyerusers\name{struc_sieve} \alias{struc_sieve} \title{Core-generating Function for Sieve Plots} \encoding{UTF-8} \description{ Core-generating function for \code{strucplot} returning a function producing sieve plots. } \usage{ struc_sieve(sievetype = c("observed","expected"), gp_tile = gpar()) } \arguments{ \item{sievetype}{logical indicating whether rectangles should be filled according to \code{observed} or \code{expected} frequencies.} \item{gp_tile}{object of class \code{"gpar"}, controlling the appearance of all \emph{static} elements of the cells (e.g., border and fill color).} } \details{ This function is usually called by \code{\link{strucplot}} (typically when called by \code{\link{sieve}}) and returns a function used by \code{\link{strucplot}} to produce sieve plots. } \value{ A function with arguments: \item{residuals}{table of residuals.} \item{observed}{table of observed values.} \item{expected}{not used by \code{struc_sieve}.} \item{spacing}{object of class \code{"unit"} specifying the space between the tiles.} \item{gp}{list of \code{gpar} objects used for the drawing the tiles.} \item{split_vertical}{vector of logicals indicating, for each dimension of the table, the split direction.} } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{sieve}}, \code{\link{strucplot}}, \code{\link{structable}} } \references{ Riedwyl, H., and Schüpbach, M. (1994), Parquet diagram to plot contingency tables. In F. Faulbaum (ed.), \emph{Softstat '93: Advances in Statistical Software}, 293--299. Gustav Fischer, New York. Friendly, M. (2000), Visualizing Categorical Data, SAS Institute, Cary, NC. Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \examples{ ## Titanic data data("Titanic") strucplot(Titanic, core = struc_sieve) } \keyword{hplot} vcd/man/labeling_cells_list.Rd0000644000175300001440000001205211150520606015725 0ustar meyerusers\name{labeling_cells_list} \alias{labeling_list} \alias{labeling_cells} \title{Labeling Functions for Strucplots} \description{ These functions generate labeling functions that produce labels for strucplots. } \usage{ labeling_cells(labels = TRUE, varnames = TRUE, abbreviate_labels = FALSE, abbreviate_varnames = FALSE, gp_text = gpar(), lsep = ": ", lcollapse = "\n", just = "center", pos = "center", rot = 0, margin = unit(0.5, "lines"), clip_cells = TRUE, text = NULL, \dots) labeling_list(gp_text = gpar(), just = "left", pos = "left", lsep = ": ", sep = " ", offset = unit(c(2, 2), "lines"), varnames = TRUE, cols = 2, \dots) } \arguments{ \item{labels}{vector of logicals indicating, for each dimension, whether labels for the factor levels should be drawn or not. Values are recycled as needed.} \item{varnames}{vector of logicals indicating, for each dimension, whether variable names should be drawn. Values are recycled as needed.} \item{abbreviate_labels}{vector of integers or logicals indicating, for each dimension, the number of characters the labels should be abbreviated to. \code{TRUE} means 1 character, \code{FALSE} causes no abbreviation. Values are recycled as needed.} \item{abbreviate_varnames}{vector of integers or logicals indicating, for each dimension, the number of characters the variable (i.e., dimension) names should be abbreviated to. \code{TRUE} means 1 character, \code{FALSE} causes no abbreviation. Values are recycled as needed.} \item{gp_text}{object of class \code{"gpar"} used for the text drawn.} \item{lsep}{character that separates variable names from the factor levels.} \item{sep}{character that separates the factor levels (only used for \code{labeling_list}).} \item{offset}{object of class \code{"unit"} of length 2 specifying the offset in x- and y-direction of the text block drawn under the strucplot (only used for \code{labeling_list}).} \item{cols}{number of text columns (only used for \code{labeling_list}).} \item{lcollapse}{character that separates several variable name/factor level-combinations. Typically a line break. (Only used for \code{labeling_cells}.)} \item{just, pos}{character string of length 1 (\code{labeling_list}) or at most 2 (\code{labeling_cells}) specifying the labels' horizontal position and justification (horizontal and vertical for \code{labeling_cells}).} \item{rot}{rotation angle in degrees, used for all labels (only used for \code{labeling_cells}).} \item{margin}{object of class \code{"unit"} (a numeric value is converted to \code{"lines"}) specifying an offset from the cell borders (only used for \code{labeling_cells}).} \item{clip_cells}{logical indicating whether text should be clipped at the cell borders (only used for \code{labeling_cells}).} \item{text}{Optionally, a character table of the same dimensions than the contingency table whose entries will then be used instead of the labels. \code{NA} entries are not drawn. This allows custom cell annotations (see examples). Only used for \code{labeling_cells}.} \item{\dots}{Currently not used.} } \details{ These functions generate labeling functions that can add different kinds of labels to an existing plot. Typically they are supplied to \code{\link{strucplot}} which then generates and calls the labeling function. They assume that a strucplot has been drawn and the corresponding viewport structure is pushed, so that by navigating through the viewport tree the labels can be positioned appropriately. This help page only documents \code{labeling_list} and \code{labeling_cells}; more functions are described on the help page for \code{\link{labeling_border}}. The functions can also be used \sQuote{stand-alone} as shown in the examples. Using \code{labeling_list} will typically necessitate a bottom margin adjustment. } \value{ A function with arguments: \item{d}{\code{"dimnames"} attribute from the visualized contingency table, or the visualized table itself from which the \code{"dimnames"} attributes will then be extracted.} \item{split_vertical}{vector of logicals indicating the split directions.} \item{condvars}{integer vector of conditioning dimensions} } \author{ David Meyer \email{David.Meyer@R-project.org} } \references{ Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \seealso{ \code{\link{labeling_border}}, \code{\link{structable}}, \code{\link[grid]{grid.text}} } \examples{ data("Titanic") mosaic(Titanic, labeling = labeling_cells) mosaic(Titanic, labeling = labeling_list) ## A more complex example, adding the observed frequencies ## to a mosaic plot: tab <- ifelse(Titanic < 6, NA, Titanic) mosaic(Titanic, pop = FALSE) labeling_cells(text = tab, margin = 0)(Titanic) } \keyword{hplot} vcd/man/doubledecker.Rd0000644000175300001440000000623011150520606014364 0ustar meyerusers\name{doubledecker} \alias{doubledecker.default} \alias{doubledecker.formula} \alias{doubledecker} \title{Doubledecker Plot} \description{ This function creates a doubledecker plot visualizing a classification rule. } \usage{ \method{doubledecker}{formula}(formula, data = NULL, \dots, main = NULL) \method{doubledecker}{default}(x, depvar = length(dim(x)), margins = c(1,4, length(dim(x)) + 1, 1), gp = gpar(fill = rev(gray.colors(tail(dim(x), 1)))), labeling = labeling_doubledecker, spacing = spacing_highlighting, main = NULL, keep_aspect_ratio = FALSE, \dots) } \arguments{ \item{formula}{a formula specifying the variables used to create a contingency table from \code{data}. The dependent variable is used last for splitting.} \item{data}{either a data frame, or an object of class \code{"table"} or \code{"ftable"}.} \item{x}{a contingency table in array form, with optional category labels specified in the \code{dimnames(x)} attribute.} \item{depvar}{dimension index or character string specifying the dependent variable. That will be sorted last in the table.} \item{margins}{margins of the plot. Note that by default, all factor names (except the last one) and their levels are visualized \emph{as a block} under the plot.} \item{gp}{object of class \code{"gpar"} used for the tiles of the last variable.} \item{labeling}{labeling function or corresponding generating generating function (see \code{\link{strucplot}} for details).} \item{spacing}{spacing object, spacing function or corresponding generating function (see \code{\link{strucplot}} for details).} \item{main}{either a logical, or a character string used for plotting the main title. If \code{main} is \code{TRUE}, the name of the \code{data} object is used.} \item{keep_aspect_ratio}{logical indicating whether the aspect ratio should be maintained or not.} \item{\dots}{Further parameters passed to \code{mosaic}.} } \details{ Doubledecker plots visualize the the dependence of one categorical (typically binary) variable on further categorical variables. Formally, they are mosaic plots with vertical splits for all dimensions (antecedents) except the last one, which represents the dependent variable (consequent). The last variable is visualized by horizontal splits, no space between the tiles, and separate colors for the levels. } \value{ The \code{"structable"} visualized is returned invisibly. } \references{ H. Hoffmann (2001), Generalized odds ratios for visual modeling. \emph{Journal of Computational and Graphical Statistics}, \bold{10}, 4, 628--640. Meyer, D., Zeileis, A., and Hornik, K. (2006), The strucplot framework: Visualizing multi-way contingency tables with \pkg{vcd}. \emph{Journal of Statistical Software}, \bold{17(3)}, 1-48. URL http://www.jstatsoft.org/v17/i03/ and available as \code{vignette("strucplot")}. } \author{ David Meyer \email{David.Meyer@R-project.org} } \seealso{ \code{\link{strucplot}}, \code{\link{mosaic}} } \examples{ data("Titanic") doubledecker(Titanic) doubledecker(Titanic, depvar = "Survived") doubledecker(Survived ~ ., data = Titanic) } \keyword{hplot} vcd/man/SpaceShuttle.Rd0000644000175300001440000000335611150520606014346 0ustar meyerusers\name{SpaceShuttle} \alias{SpaceShuttle} \docType{data} \title{Space Shuttle O-ring Failures} \description{ Data from Dalal et al. (1989) about O-ring failures in the NASA space shuttle program. The damage index comes from a discussion of the data by Tufte (1997). } \usage{ data("SpaceShuttle") } \format{ A data frame with 24 observations and 6 variables. \describe{ \item{FlightNumber}{Number of space shuttle flight.} \item{Temperature}{temperature during start (in degrees F).} \item{Pressure}{pressure.} \item{Fail}{did any O-ring failures occur? (no, yes).} \item{nFailures}{how many (of six) 0-rings failed?.} \item{Damage}{damage index.} } } \references{ S. Dalal, E. B. Fowlkes, B. Hoadly (1989), Risk analysis of the space shuttle: Pre-Challenger prediction of failure, \emph{Journal of the American Statistical Association}, \bold{84}, 945--957. E. R. Tufte (1997), \emph{Visual Explanations: Images and Quantities, Evidence and Narrative}. Graphics Press, Cheshire, CT. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data: \url{http://euclid.psych.yorku.ca/ftp/sas/vcd/catdata/orings.sas} } \examples{ data("SpaceShuttle") plot(nFailures/6 ~ Temperature, data = SpaceShuttle, xlim = c(30, 81), ylim = c(0,1), main = "NASA Space Shuttle O-Ring Failures", ylab = "Estimated failure probability", pch = 19, col = 4) fm <- glm(cbind(nFailures, 6 - nFailures) ~ Temperature, data = SpaceShuttle, family = binomial) lines(30 : 81, predict(fm, data.frame(Temperature = 30 : 81), type = "re"), lwd = 2) abline(v = 31, lty = 3) } \keyword{datasets} vcd/man/Saxony.Rd0000644000175300001440000000176511150520606013225 0ustar meyerusers\name{Saxony} \alias{Saxony} \docType{data} \title{Families in Saxony} \description{ Data from Geissler, cited in Sokal & Rohlf (1969) and Lindsey (1995) on gender distributions in families in Saxony in the 19th century. } \usage{ data("Saxony") } \format{ A 1-way table giving the number of male children in 6115 families of size 12. The variable and its levels are \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab nMales \tab 0, 1, \dots, 12 \cr } } \references{ J. K. Lindsey (1995), \emph{Analysis of Frequency and Count Data}. Oxford University Press, Oxford, UK. R. R. Sokal & F. J. Rohlf (1969), \emph{Biometry. The Principles and Practice of Statistics}. W. H. Freeman, San Francisco, CA. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ M. Friendly (2000), Visualizing Categorical Data, pages 40--42. } \examples{ data("Saxony") gf <- goodfit(Saxony, type = "binomial") summary(gf) plot(gf) } \keyword{datasets} vcd/man/mar_table.Rd0000644000175300001440000000057511150520606013670 0ustar meyerusers\name{mar_table} \alias{mar_table} \title{Table with Marginal Sums} \description{ Adds row and column sums to a two-way table. } \usage{ mar_table(x) } \arguments{ \item{x}{a two-way table.} } \value{ A table with row and column totals added. } \author{ David Meyer \email{David.Meyer@R-project.org} } \examples{ data("SexualFun") mar_table(SexualFun) } \keyword{category} vcd/man/JobSatisfaction.Rd0000644000175300001440000000224211150520606015015 0ustar meyerusers\name{JobSatisfaction} \alias{JobSatisfaction} \docType{data} \title{Job Satisfaction Data} \description{ Data from Petersen (1968) about the job satisfaction of 715 blue collar workers, selected from Danish Industry in 1968. } \usage{ data("JobSatisfaction") } \format{ A data frame with 8 observations and 4 variables. \describe{ \item{Freq}{frequency.} \item{management}{factor indicating quality of management (bad, good).} \item{supervisor}{factor indicating supervisor's job satisfaction (low, high).} \item{own}{factor indicating worker's own job satisfaction (low, high).} } } \references{ E. B. Andersen (1991), \emph{The Statistical Analysis of Categorical Data}. 2nd edition. Springer-Verlag, Berlin. E. Petersen (1968), \emph{Job Satisfaction in Denmark}. (In Danish). Mentalhygiejnisk Forlag, Copenhagen. } \source{ E. B. Andersen (1991), The Statistical Analysis of Categorical Data, Table 5.4. } \examples{ data("JobSatisfaction") structable(~ ., data = JobSatisfaction) mantelhaen.test(xtabs(Freq ~ own + supervisor + management, data = JobSatisfaction)) } \keyword{datasets} vcd/man/Butterfly.Rd0000644000175300001440000000163511150520606013720 0ustar meyerusers\name{Butterfly} \alias{Butterfly} \docType{data} \title{Butterfly Species in Malaya} \description{ Data from Fisher et al. (1943) giving the number of tokens found for each of 501 species of butterflies collected in Malaya. } \usage{ data("Butterfly") } \format{ A 1-way table giving the number of tokens for 501 species of butterflies. The variable and its levels are \tabular{rll}{ No \tab Name \tab Levels \cr 1 \tab nTokens \tab 0, 1, \dots, 24 \cr } } \references{ R. A. Fisher, A. S. Corbet, C. B. Williams (1943), The relation between the number of species and the number of individuals, \emph{Journal of Animal Ecology}, \bold{12}, 42--58. M. Friendly (2000), \emph{Visualizing Categorical Data}. SAS Institute, Cary, NC. } \source{ Michael Friendly (2000), Visualizing Categorical Data, pages 21--22. } \examples{ data("Butterfly") Ord_plot(Butterfly) } \keyword{datasets} vcd/tests/0000755000175300001440000000000011720426624012043 5ustar meyerusersvcd/tests/demos.R0000644000175300001440000000015011150520606013261 0ustar meyeruserslibrary(vcd) demo(discrete) demo(twoway) demo(mosaic) demo(mondrian) demo(strucplot) demo(hullternary) vcd/R/0000755000175300001440000000000011720426624011102 5ustar meyerusersvcd/R/assoc.R0000644000175300001440000002717111623301116012333 0ustar meyerusers#################################################################333 ## assocplot assoc <- function(x, ...) UseMethod("assoc") assoc.formula <- function(formula, data = NULL, ..., subset = NULL, na.action = NULL, main = NULL, sub = NULL) { if (is.logical(main) && main) main <- deparse(substitute(data)) else if (is.logical(sub) && sub) sub <- deparse(substitute(data)) assoc.default(structable(formula, data, subset = subset, na.action = na.action), main = main, sub = sub, ...) } assoc.default <- function(x, row_vars = NULL, col_vars = NULL, compress = TRUE, xlim = NULL, ylim = NULL, spacing = spacing_conditional(sp = 0), spacing_args = list(), split_vertical = NULL, keep_aspect_ratio = FALSE, xscale = 0.9, yspace = unit(0.5, "lines"), main = NULL, sub = NULL, ..., residuals_type = "Pearson", gp_axis = gpar(lty = 3) ) { if (is.logical(main) && main) main <- deparse(substitute(x)) else if (is.logical(sub) && sub) sub <- deparse(substitute(x)) if (!inherits(x, "ftable")) x <- structable(x) tab <- as.table(x) dl <- length(dim(tab)) ## spacing cond <- rep(TRUE, dl) cond[length(attr(x, "row.vars")) + c(0, length(attr(x, "col.vars")))] <- FALSE if (inherits(spacing, "grapcon_generator")) spacing <- do.call("spacing", spacing_args) spacing <- spacing(dim(tab), condvars = which(cond)) ## splitting arguments if (is.null(split_vertical)) split_vertical <- attr(x, "split_vertical") if(match.arg(tolower(residuals_type), "pearson") != "pearson") warning("Only Pearson residuals can be visualized with association plots.") strucplot(tab, spacing = spacing, split_vertical = split_vertical, core = struc_assoc(compress = compress, xlim = xlim, ylim = ylim, yspace = yspace, xscale = xscale, gp_axis = gp_axis), keep_aspect_ratio = keep_aspect_ratio, residuals_type = "Pearson", main = main, sub = sub, ...) } ## old code: more elegant conceptually, but less performant ## ## struc_assoc2 <- function(compress = TRUE, xlim = NULL, ylim = NULL, ## yspace = unit(0.5, "lines"), xscale = 0.9, ## gp_axis = gpar(lty = 3)) ## function(residuals, observed = NULL, expected, spacing, gp, split_vertical, prefix = "") { ## dn <- dimnames(expected) ## dnn <- names(dn) ## dx <- dim(expected) ## dl <- length(dx) ## ## axis limits ## resid <- structable(residuals, split_vertical = split_vertical) ## sexpected <- structable(sqrt(expected), split_vertical = split_vertical) ## rfunc <- function(x) c(min(x, 0), max(x, 0)) ## if (is.null(ylim)) ## ylim <- if (compress) ## matrix(apply(as.matrix(resid), 1, rfunc), nrow = 2) ## else ## rfunc(as.matrix(resid)) ## if (!is.matrix(ylim)) ## ylim <- matrix(as.matrix(ylim), nrow = 2, ncol = nrow(as.matrix(resid))) ## attr(ylim, "split_vertical") <- rep(TRUE, sum(!split_vertical)) ## attr(ylim, "dnames") <- dn[!split_vertical] ## class(ylim) <- "structable" ## if(is.null(xlim)) ## xlim <- if (compress) ## matrix(c(-0.5, 0.5) %o% apply(as.matrix(sexpected), 2, max), nrow = 2) ## else ## c(-0.5, 0.5) * max(sexpected) ## if (!is.matrix(xlim)) ## xlim <- matrix(as.matrix(xlim), nrow = 2, ncol = ncol(as.matrix(resid))) ## attr(xlim, "split_vertical") <- rep(TRUE, sum(split_vertical)) ## attr(xlim, "dnames") <- dn[split_vertical] ## class(xlim) <- "structable" ## ## split workhorse ## split <- function(res, sexp, i, name, row, col) { ## v <- split_vertical[i] ## splitbase <- if (v) sexp else res ## splittab <- lapply(seq(dx[i]), function(j) splitbase[[j]]) ## len <- sapply(splittab, function(x) sum(unclass(x)[1,] - unclass(x)[2,])) ## d <- dx[i] ## ## compute total cols/rows and build split layout ## dist <- unit.c(unit(len, "null"), spacing[[i]] + (1 * !v) * yspace) ## idx <- matrix(1:(2 * d), nrow = 2, byrow = TRUE)[-2 * d] ## layout <- if (v) ## grid.layout(ncol = 2 * d - 1, widths = dist[idx]) ## else ## grid.layout(nrow = 2 * d - 1, heights = dist[idx]) ## vproot <- viewport(layout.pos.col = col, layout.pos.row = row, ## layout = layout, name = remove_trailing_comma(name)) ## ## next level: either create further splits, or final viewports ## name <- paste(name, dnn[i], "=", dn[[i]], ",", sep = "") ## rows <- cols <- rep.int(1, d) ## if (v) cols <- 2 * 1:d - 1 else rows <- 2 * 1:d - 1 ## f <- if (i < dl) { ## if (v) ## function(m) split(res, splittab[[m]], i + 1, name[m], rows[m], cols[m]) ## else ## function(m) split(splittab[[m]], sexp, i + 1, name[m], rows[m], cols[m]) ## } else { ## if (v) ## function(m) viewport(layout.pos.col = cols[m], layout.pos.row = rows[m], ## name = remove_trailing_comma(name[m]), ## yscale = unclass(res)[,1], ## xscale = unclass(sexp)[,m], default.units = "null") ## else ## function(m) viewport(layout.pos.col = cols[m], layout.pos.row = rows[m], ## name = remove_trailing_comma(name[m]), ## yscale = unclass(res)[,m], ## xscale = unclass(sexp)[,1], default.units = "null") ## } ## vpleaves <- structure(lapply(1:d, f), class = c("vpList", "viewport")) ## vpTree(vproot, vpleaves) ## } ## ## start spltting on top, creates viewport-tree ## pushViewport(split(ylim, xlim, i = 1, name = paste(prefix, "cell:", sep = ""), ## row = 1, col = 1)) ## ## draw tiles ## mnames <- paste(apply(expand.grid(dn), 1, ## function(i) paste(dnn, i, collapse = ",", sep = "=") ## ) ## ) ## for (i in seq_along(mnames)) { ## seekViewport(paste(prefix, "cell:", mnames[i], sep = "")) ## grid.lines(y = unit(0, "native"), gp = gp_axis) ## grid.rect(y = 0, x = 0, ## height = residuals[i], ## width = xscale * unit(sqrt(expected[i]), "native"), ## default.units = "native", ## gp = structure(lapply(gp, function(x) x[i]), class = "gpar"), ## just = c("center", "bottom"), ## name = paste(prefix, "rect:", mnames[i], sep = "") ## ) ## } ## } ## class(struc_assoc2) <- "grapcon_generator" struc_assoc <- function(compress = TRUE, xlim = NULL, ylim = NULL, yspace = unit(0.5, "lines"), xscale = 0.9, gp_axis = gpar(lty = 3)) function(residuals, observed = NULL, expected, spacing, gp, split_vertical, prefix = "") { if(is.null(expected)) stop("Need expected values.") dn <- dimnames(expected) dnn <- names(dn) dx <- dim(expected) dl <- length(dx) ## axis limits resid <- structable(residuals, split_vertical = split_vertical) sexpected <- structable(sqrt(expected), split_vertical = split_vertical) rfunc <- function(x) c(min(x, 0), max(x, 0)) if (is.null(ylim)) ylim <- if (compress) matrix(apply(as.matrix(resid), 1, rfunc), nrow = 2) else rfunc(as.matrix(resid)) if (!is.matrix(ylim)) ylim <- matrix(as.matrix(ylim), nrow = 2, ncol = nrow(as.matrix(resid))) ylim[2,] <- ylim[2,] + .Machine$double.eps attr(ylim, "split_vertical") <- rep(TRUE, sum(!split_vertical)) attr(ylim, "dnames") <- dn[!split_vertical] class(ylim) <- "structable" if(is.null(xlim)) xlim <- if (compress) matrix(c(-0.5, 0.5) %o% apply(as.matrix(sexpected), 2, max), nrow = 2) else c(-0.5, 0.5) * max(sexpected) if (!is.matrix(xlim)) xlim <- matrix(as.matrix(xlim), nrow = 2, ncol = ncol(as.matrix(resid))) attr(xlim, "split_vertical") <- rep(TRUE, sum(split_vertical)) attr(xlim, "dnames") <- dn[split_vertical] class(xlim) <- "structable" ## split workhorse split <- function(res, sexp, i, name, row, col, index) { v <- split_vertical[i] d <- dx[i] splitbase <- if (v) sexp else res splittab <- lapply(seq(d), function(j) splitbase[[j]]) len <- sapply(splittab, function(x) sum(unclass(x)[1,] - unclass(x)[2,])) ## compute total cols/rows and build split layout dist <- if (d > 1) unit.c(unit(len, "null"), spacing[[i]] + (1 * !v) * yspace) else unit(len, "null") idx <- matrix(1:(2 * d), nrow = 2, byrow = TRUE)[-2 * d] layout <- if (v) grid.layout(ncol = 2 * d - 1, widths = dist[idx]) else grid.layout(nrow = 2 * d - 1, heights = dist[idx]) pushViewport(viewport(layout.pos.col = col, layout.pos.row = row, layout = layout, name = paste(prefix, "cell:", remove_trailing_comma(name), sep = ""))) ## next level: either create further splits, or final viewports rows <- cols <- rep.int(1, d) if (v) cols <- 2 * 1:d - 1 else rows <- 2 * 1:d - 1 for (m in 1:d) { nametmp <- paste(name, dnn[i], "=", dn[[i]][m], ",", sep = "") if (i < dl) { if (v) sexp <- splittab[[m]] else res <- splittab[[m]] split(res, sexp, i + 1, nametmp, rows[m], cols[m], cbind(index, m)) } else { pushViewport(viewport(layout.pos.col = cols[m], layout.pos.row = rows[m], name = paste(prefix, "cell:", remove_trailing_comma(nametmp), sep = ""), yscale = unclass(res)[,if (v) 1 else m], xscale = unclass(sexp)[,if (v) m else 1], default.units = "null") ) ## draw tiles grid.lines(y = unit(0, "native"), gp = gp_axis) grid.rect(y = 0, x = 0, height = residuals[cbind(index, m)], width = xscale * unit(sqrt(expected[cbind(index, m)]), "native"), default.units = "native", gp = structure(lapply(gp, function(x) x[cbind(index,m)]), class = "gpar"), just = c("center", "bottom"), name = paste(prefix, "rect:", remove_trailing_comma(nametmp), sep = "") ) } upViewport(1) } } split(ylim, xlim, i = 1, name = "", row = 1, col = 1, index = cbind()) } class(struc_assoc) <- "grapcon_generator" vcd/R/hls.R0000644000175300001440000000106511150520606012005 0ustar meyerusershls <- function(h = 1, l = 0.5, s = 1) { RGB <- function(q1, q2, hue) { if (hue > 360) hue <- hue - 360 if (hue < 0) hue <- hue + 360 if (hue < 60) q1 + (q2 - q1) * hue / 60 else if (hue < 180) q2 else if (hue < 240) q1 + (q2 - q1) * (240 - hue) / 60 else q1 } h <- h * 360 p2 <- if (l <= 0.5) l * (1 + s) else l + s - (l * s) p1 <- 2 * l - p2; if (s == 0) R <- G <- B <- l else { R <- RGB(p1, p2, h + 120) G <- RGB(p1, p2, h) B <- RGB(p1, p2, h - 120) } rgb(R, G, B) } vcd/R/woolf_test.R0000644000175300001440000000131411150520606013401 0ustar meyeruserswoolf_test <- function(x) { DNAME <- deparse(substitute(x)) if (any(x == 0)) x <- x + 1 / 2 k <- dim(x)[3] or <- apply(x, 3, function(x) (x[1,1] * x[2,2]) / (x[1,2] * x[2,1])) w <- apply(x, 3, function(x) 1 / sum(1 / x)) o <- log(or) e <- weighted.mean(log(or), w) STATISTIC <- sum(w * (o - e)^2) PARAMETER <- k - 1 PVAL <- 1 - pchisq(STATISTIC, PARAMETER) METHOD <- "Woolf-test on Homogeneity of Odds Ratios (no 3-Way assoc.)" names(STATISTIC) <- "X-squared" names(PARAMETER) <- "df" structure(list(statistic = STATISTIC, parameter = PARAMETER, p.value = PVAL, method = METHOD, data.name = DNAME, observed = o, expected = e), class = "htest") } vcd/R/sieve.R0000644000175300001440000003111511236051214012330 0ustar meyerusers########################################################### ## sieveplot sieve <- function(x, ...) UseMethod("sieve") sieve.formula <- function(formula, data = NULL, ..., main = NULL, sub = NULL, subset = NULL) { if (is.logical(main) && main) main <- deparse(substitute(data)) else if (is.logical(sub) && sub) sub <- deparse(substitute(data)) m <- match.call(expand.dots = FALSE) edata <- eval(m$data, parent.frame()) fstr <- strsplit(paste(deparse(formula), collapse = ""), "~") vars <- strsplit(strsplit(gsub(" ", "", fstr[[1]][2]), "\\|")[[1]], "\\+") varnames <- vars[[1]] condnames <- if (length(vars) > 1) vars[[2]] else NULL if (inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { condind <- NULL dat <- as.table(data) if(all(varnames != ".")) { ind <- match(varnames, names(dimnames(dat))) if (any(is.na(ind))) stop(paste("Can't find", paste(varnames[is.na(ind)], collapse=" / "), "in", deparse(substitute(data)))) if (!is.null(condnames)) { condind <- match(condnames, names(dimnames(dat))) if (any(is.na(condind))) stop(paste("Can't find", paste(condnames[is.na(condind)], collapse=" / "), "in", deparse(substitute(data)))) ind <- c(condind, ind) } dat <- margin.table(dat, ind) } sieve.default(dat, main = main, sub = sub, condvars = if (is.null(condind)) NULL else match(condnames, names(dimnames(dat))), ...) } else { tab <- if ("Freq" %in% colnames(data)) xtabs(formula(paste("Freq~", paste(c(condnames, varnames), collapse = "+"))), data = data, subset = subset) else xtabs(formula(paste("~", paste(c(condnames, varnames), collapse = "+"))), data = data, subset = subset) sieve.default(tab, main = main, sub = sub, ...) } } sieve.default <- function(x, condvars = NULL, gp = NULL, shade = NULL, legend = FALSE, split_vertical = NULL, direction = NULL, spacing = NULL, spacing_args = list(), sievetype = c("observed","expected"), gp_tile = gpar(), main = NULL, sub = NULL, ...) { if (is.logical(main) && main) main <- deparse(substitute(x)) else if (is.logical(sub) && sub) sub <- deparse(substitute(x)) sievetype = match.arg(sievetype) if (is.logical(shade) && shade && is.null(gp)) gp <- if (sievetype == "observed") shading_sieve(interpolate = 0, lty = c("longdash", "solid")) else shading_sieve(interpolate = 0, line_col = "darkgray", eps = Inf, lty = "dotted") if (is.structable(x)) { if (is.null(direction) && is.null(split_vertical)) split_vertical <- attr(x, "split_vertical") x <- as.table(x) } if (is.null(split_vertical)) split_vertical <- FALSE dl <- length(dim(x)) ## splitting argument if (!is.null(direction)) split_vertical <- direction == "v" if (length(split_vertical) == 1) split_vertical <- rep(c(split_vertical, !split_vertical), length.out = dl) if (length(split_vertical) < dl) split_vertical <- rep(split_vertical, length.out = dl) ## condvars if (!is.null(condvars)) { if (is.character(condvars)) condvars <- match(condvars, names(dimnames(x))) x <- aperm(x, c(condvars, seq(dl)[-condvars])) if (is.null(spacing)) spacing <- spacing_conditional } ## spacing argument if (is.null(spacing)) spacing <- if (dl < 3) spacing_equal(sp = 0) else spacing_increase strucplot(x, condvars = if (is.null(condvars)) NULL else length(condvars), core = struc_sieve(sievetype = sievetype, gp_tile = gp_tile), split_vertical = split_vertical, spacing = spacing, spacing_args = spacing_args, main = main, sub = sub, shade = shade, legend = legend, gp = gp, ...) } ## old version (not performant enough) ## ## struc_sieve <- function(sievetype = c("observed", "expected")) { ## sievetype = match.arg(sievetype) ## function(residuals, observed, expected, spacing, gp, split_vertical, prefix = "") { ## dn <- dimnames(expected) ## dnn <- names(dn) ## dx <- dim(expected) ## dl <- length(dx) ## n <- sum(expected) ## ## split workhorse ## split <- function(x, i, name, row, col, rowmargin, colmargin) { ## cotab <- co_table(x, 1) ## margin <- sapply(cotab, sum) ## v <- split_vertical[i] ## d <- dx[i] ## ## compute total cols/rows and build split layout ## dist <- unit.c(unit(margin, "null"), spacing[[i]]) ## idx <- matrix(1:(2 * d), nrow = 2, byrow = TRUE)[-2 * d] ## layout <- if (v) ## grid.layout(ncol = 2 * d - 1, widths = dist[idx]) ## else ## grid.layout(nrow = 2 * d - 1, heights = dist[idx]) ## vproot <- viewport(layout.pos.col = col, layout.pos.row = row, ## layout = layout, name = remove_trailing_comma(name)) ## ## next level: either create further splits, or final viewports ## name <- paste(name, dnn[i], "=", dn[[i]], ",", sep = "") ## row <- col <- rep.int(1, d) ## if (v) col <- 2 * 1:d - 1 else row <- 2 * 1:d - 1 ## proptab <- function(x) x / max(sum(x), 1) ## f <- if (i < dl) { ## if (v) ## function(m) split(cotab[[m]], i + 1, name[m], row[m], col[m], ## colmargin = colmargin * proptab(margin)[m], ## rowmargin = rowmargin) ## else ## function(m) split(cotab[[m]], i + 1, name[m], row[m], col[m], ## colmargin = colmargin, ## rowmargin = rowmargin * proptab(margin)[m]) ## } else { ## if (v) ## function(m) viewport(layout.pos.col = col[m], layout.pos.row = row[m], ## name = remove_trailing_comma(name[m]), ## yscale = c(0, rowmargin), ## xscale = c(0, colmargin * proptab(margin)[m])) ## else ## function(m) viewport(layout.pos.col = col[m], layout.pos.row = row[m], ## name = remove_trailing_comma(name[m]), ## yscale = c(0, rowmargin * proptab(margin)[m]), ## xscale = c(0, colmargin)) ## } ## vpleaves <- structure(lapply(1:d, f), class = c("vpList", "viewport")) ## vpTree(vproot, vpleaves) ## } ## ## start splitting on top, creates viewport-tree ## pushViewport(split(expected + .Machine$double.eps, ## i = 1, name = paste(prefix, "cell:", sep = ""), row = 1, col = 1, ## rowmargin = n, colmargin = n)) ## ## draw rectangles ## mnames <- apply(expand.grid(dn), 1, ## function(i) paste(dnn, i, collapse=",", sep = "=") ## ) ## for (i in seq_along(mnames)) { ## seekViewport(paste(prefix, "cell:", mnames[i], sep = "")) ## vp <- current.viewport() ## gpobj <- structure(lapply(gp, function(x) x[i]), class = "gpar") ## div <- if (sievetype == "observed") observed[i] else expected[i] ## if (div > 0) { ## square.side <- sqrt(vp$yscale[2] * vp$xscale[2] / div) ## ii <- seq(0, vp$xscale[2], by = square.side) ## jj <- seq(0, vp$yscale[2], by = square.side) ## grid.segments(x0 = ii, x1 = ii, y0 = 0, y1 = vp$yscale[2], ## default.units = "native", gp = gpobj) ## grid.segments(x0 = 0, x1 = vp$xscale[2], y0 = jj, y1 = jj, ## default.units = "native", gp = gpobj) ## } ## grid.rect(name = paste(prefix, "rect:", mnames[i], sep = ""), ## gp = gpar(fill = "transparent")) ## } ## } ## } ##class(struc_sieve) <- "grapcon_generator" struc_sieve <- function(sievetype = c("observed", "expected"), gp_tile = gpar()) { sievetype = match.arg(sievetype) function(residuals, observed, expected, spacing, gp, split_vertical, prefix = "") { if (is.null(expected)) stop("Need expected values.") dn <- dimnames(expected) dnn <- names(dn) dx <- dim(expected) dl <- length(dx) n <- sum(expected) ## split workhorse split <- function(x, i, name, row, col, rowmargin, colmargin, index) { cotab <- co_table(x, 1) margin <- sapply(cotab, sum) v <- split_vertical[i] d <- dx[i] ## compute total cols/rows and build split layout dist <- if (d > 1) unit.c(unit(margin, "null"), spacing[[i]]) else unit(margin, "null") idx <- matrix(1:(2 * d), nrow = 2, byrow = TRUE)[-2 * d] layout <- if (v) grid.layout(ncol = 2 * d - 1, widths = dist[idx]) else grid.layout(nrow = 2 * d - 1, heights = dist[idx]) pushViewport(viewport(layout.pos.col = col, layout.pos.row = row, layout = layout, name = paste(prefix, "cell:", remove_trailing_comma(name), sep = ""))) ## next level: either create further splits, or final viewports row <- col <- rep.int(1, d) if (v) col <- 2 * 1:d - 1 else row <- 2 * 1:d - 1 proptab <- function(x) x / max(sum(x), 1) for (m in 1:d) { nametmp <- paste(name, dnn[i], "=", dn[[i]][m], ",", sep = "") if (v) { colmargintmp <- colmargin * proptab(margin)[m] rowmargintmp <- rowmargin } else { rowmargintmp <- rowmargin * proptab(margin)[m] colmargintmp <- colmargin } if (i < dl) split(cotab[[m]], i + 1, nametmp, row[m], col[m], colmargin = colmargintmp, rowmargin = rowmargintmp, index = cbind(index, m)) else { pushViewport(viewport(layout.pos.col = col[m], layout.pos.row = row[m], name = paste(prefix, "cell:", remove_trailing_comma(nametmp), sep = ""), yscale = c(0, rowmargintmp), xscale = c(0, colmargintmp))) gpobj <- structure(lapply(gp, function(x) x[cbind(index, m)]), class = "gpar") ## draw sieve div <- if (sievetype == "observed") observed[cbind(index, m)] else expected[cbind(index, m)] gptmp <- gp_tile gptmp$col <- "transparent" grid.rect(name = paste(prefix, "rect:", nametmp, sep = ""), gp = gptmp) if (div > 0) { square.side <- sqrt(colmargintmp * rowmargintmp / div) ii <- seq(0, colmargintmp, by = square.side) jj <- seq(0, rowmargintmp, by = square.side) grid.segments(x0 = ii, x1 = ii, y0 = 0, y1 = rowmargintmp, default.units = "native", gp = gpobj) grid.segments(x0 = 0, x1 = colmargintmp, y0 = jj, y1 = jj, default.units = "native", gp = gpobj) } gptmp <- gp_tile gptmp$fill <- "transparent" grid.rect(name = paste(prefix, "border:", nametmp, sep = ""), gp = gptmp) } upViewport(1) } } ## start splitting on top, creates viewport-tree split(expected + .Machine$double.eps, i = 1, name = "", row = 1, col = 1, rowmargin = n, colmargin = n, index = cbind()) } } class(struc_sieve) <- "grapcon_generator" vcd/R/cotabplot.R0000644000175300001440000002536211636647070013232 0ustar meyeruserscotabplot <- function(x, ...) { UseMethod("cotabplot") } cotabplot.formula <- function(formula, data = NULL, ...) { m <- match.call() edata <- eval(m$data, parent.frame()) fstr <- deparse(formula) fstr <- gsub("*", "+", fstr, fixed = TRUE) fstr <- gsub("/", "+", fstr, fixed = TRUE) fstr <- gsub("(", "", fstr, fixed = TRUE) fstr <- gsub(")", "", fstr, fixed = TRUE) fstr <- strsplit(paste(fstr, collapse = ""), "~") vars <- strsplit(strsplit(gsub(" ", "", fstr[[1]][2]), "\\|")[[1]], "\\+") varnames <- vars[[1]] condnames <- if(length(vars) > 1) vars[[2]] else NULL if (inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { tab <- as.table(data) if(all(varnames != ".")) { ind <- match(varnames, names(dimnames(tab))) if (any(is.na(ind))) stop(paste("Can't find", paste(varnames[is.na(ind)], collapse=" / "), "in", deparse(substitute(data)))) if (!is.null(condnames)) { condind <- match(condnames, names(dimnames(tab))) if (any(is.na(condind))) stop(paste("Can't find", paste(condnames[is.na(condind)], collapse=" / "), "in", deparse(substitute(data)))) ind <- c(condind, ind) } tab <- margin.table(tab, ind) } } else { tab <- if ("Freq" %in% colnames(data)) xtabs(formula(paste("Freq~", paste(c(condnames, varnames), collapse = " + "))), data = data) else xtabs(formula(paste("~", paste(c(condnames, varnames), collapse = " + "))), data = data) } tab <- margin.table(tab, match(c(varnames, condnames), names(dimnames(tab)))) cotabplot(tab, cond = condnames, ...) } cotabplot.default <- function(x, cond = NULL, panel = cotab_mosaic, panel_args = list(), margins = rep(1, 4), layout = NULL, text_gp = gpar(fontsize = 12), rect_gp = gpar(fill = grey(0.9)), pop = TRUE, newpage = TRUE, ...) { ## coerce to table x <- as.table(x) ## initialize newpage if(newpage) grid.newpage() ## process default option ldx <- length(dim(x)) if(is.null(cond)) { indep <- if(ldx > 1) 1:2 else 1 if(ldx > 2) cond <- 3:ldx } else { if(is.character(cond)) cond <- match(cond, names(dimnames(x))) cond <- as.integer(cond) indep <- (1:ldx)[!(1:ldx %in% cond)] } ## sort margins x <- margin.table(x, c(indep, cond)) ## convenience variables that describe conditioning variables if(is.null(cond)) { cond.n <- 0 cond.num <- cond.dnam <- cond.char <- NULL } else { cond.n <- length(cond) ## number of variables cond.num <- (length(indep) + 1):ldx ## position in x cond.dnam <- dimnames(x)[cond.num] ## corresponding dimnames cond.char <- names(cond.dnam) ## names of variables } ## create panel function (if necessary) if(inherits(panel, "grapcon_generator")) panel <- do.call("panel", c(list(x, cond.char), as.list(panel_args), list(...))) if(cond.n < 1) panel(x, NULL) ## no conditioning variables else { cond.nlevels <- sapply(cond.dnam, length) nplots <- prod(cond.nlevels) condition <- as.matrix(expand.grid(cond.dnam)) ## compute layout #Z# needs fixing for more than two conditioning variables if(is.null(layout)) { layout <- c(1,1,1) ## rows, cols, pages if(cond.n == 1) { layout[2] <- ceiling(sqrt(floor(cond.nlevels))) layout[1] <- ceiling(cond.nlevels/layout[2]) } else { layout[1] <- cond.nlevels[1] layout[2] <- cond.nlevels[2] if(cond.n >= 3) layout[3] <- nplots/prod(cond.nlevels[1:2]) #Z# FIXME if(layout[3] > 1) stop("multiple pages not supported yet") } } else { layout <- c(rep(layout, length.out = 2), 1) if(layout[1] * layout[2] < nplots) stop("number of panels specified in 'layout' is too small") } layout <- expand.grid(lapply(layout, function(x) 1:x))[1:nplots,] ## push basic grid of nr x nc cells nr <- max(layout[,1]) nc <- max(layout[,2]) pushViewport(plotViewport(margins)) pushViewport(viewport(layout = grid.layout(nr, nc, widths = unit(1/nc, "npc")))) strUnit <- unit(2 * ncol(condition), "strheight", "A") cellport <- function(name) viewport(layout = grid.layout(2, 1, heights = unit.c(strUnit, unit(1, "npc") - strUnit)), name = name) ## go through each conditioning combination for(i in 1:nrow(condition)) { ## conditioning information in ith cycle condi <- as.vector(condition[i,]) names(condi) <- colnames(condition) condistr <- paste(condi, collapse = ".") condilab <- paste(cond.char, condi, sep = " = ") ## header pushViewport(viewport(layout.pos.row = layout[i,1], layout.pos.col = layout[i,2])) pushViewport(cellport(paste("cell", condistr, sep = "."))) pushViewport(viewport(layout.pos.row = 1, name = paste("lab", condistr, sep = "."))) grid.rect(gp = rect_gp) grid.text(condilab, y = cond.n:1/cond.n - 1/(2*cond.n), gp = text_gp) grid.segments(0, 0:cond.n/cond.n, 1, 0:cond.n/cond.n) upViewport() ## main plot pushViewport(viewport(layout.pos.row = 2, name = paste("plot", condistr, sep = "."))) panel(x, condi) upViewport(2) grid.rect(gp = gpar(fill = "transparent")) upViewport() } upViewport() if(pop) popViewport() else upViewport() } invisible(x) } cotab_mosaic <- function(x = NULL, condvars = NULL, ...) { function(x, condlevels) { if(is.null(condlevels)) mosaic(x, newpage = FALSE, pop = FALSE, ...) else mosaic(co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]], newpage = FALSE, pop = FALSE, prefix = paste("panel:", paste(names(condlevels), condlevels, sep = "=", collapse = ","), "|", sep = ""), ...) } } class(cotab_mosaic) <- "grapcon_generator" cotab_sieve <- function(x = NULL, condvars = NULL, ...) { function(x, condlevels) { if(is.null(condlevels)) sieve(x, newpage = FALSE, pop = FALSE, ...) else sieve(co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]], newpage = FALSE, pop = FALSE, prefix = paste("panel:", paste(names(condlevels), condlevels, sep = "=", collapse = ","), "|", sep = ""), ...) } } class(cotab_sieve) <- "grapcon_generator" cotab_assoc <- function(x = NULL, condvars = NULL, ylim = NULL, ...) { if(!is.null(x)) { fm <- coindep_test(x, condvars, n = 1) if(is.null(ylim)) ylim <- range(residuals(fm)) } function(x, condlevels) { if(is.null(condlevels)) assoc(x, newpage = FALSE, pop = FALSE, ylim = ylim, ...) else assoc(co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]], newpage = FALSE, pop = FALSE, ylim = ylim, prefix = paste("panel:", paste(names(condlevels), condlevels, sep = "=", collapse = ","), "|", sep = ""), ...) } } class(cotab_assoc) <- "grapcon_generator" cotab_fourfold <- function (x = NULL, condvars = NULL, ...) { function(x, condlevels) { if (is.null(condlevels)) fourfold(x, newpage = FALSE, ...) else fourfold(co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]], newpage = FALSE, ...) } } class(cotab_fourfold) <- "grapcon_generator" cotab_coindep <- function(x, condvars, test = c("doublemax", "maxchisq", "sumchisq"), level = NULL, n = 1000, interpolate = c(2, 4), h = NULL, c = NULL, l = NULL, lty = 1, type = c("mosaic", "assoc"), legend = FALSE, ylim = NULL, ...) { if(is.null(condvars)) stop("at least one conditioning variable is required") ## set color defaults if(is.null(h)) h <- c(260, 0) if(is.null(c)) c <- c(100, 20) if(is.null(l)) l <- c(90, 50) ## process conditional variables and get independent variables ## store some convenience information ldx <- length(dim(x)) if(is.character(condvars)) condvars <- match(condvars, names(dimnames(x))) condvars <- as.integer(condvars) indep <- (1:ldx)[!(1:ldx %in% condvars)] ## sort margins x <- margin.table(x, c(indep, condvars)) ind.n <- length(indep) ind.num <- 1:ind.n ind.dnam <- dimnames(x)[ind.num] ind.char <- names(ind.dnam) cond.n <- length(condvars) cond.num <- (ind.n + 1):length(dim(x)) cond.dnam <- dimnames(x)[cond.num] cond.char <- names(cond.dnam) test <- match.arg(test) switch(test, "doublemax" = { if(is.null(level)) level <- c(0.9, 0.99) fm <- coindep_test(x, cond.num, n = n) resids <- residuals(fm) col.bins <- fm$qdist(sort(level)) gpfun <- shading_hcl(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = h, c = c, l = l, interpolate = col.bins, lty = lty, p.value = fm$p.value) }, "maxchisq" = { if(is.null(level)) level <- 0.95 level <- level[1] fm <- coindep_test(x, cond.num, n = n, indepfun = function(x) sum(x^2)) resids <- residuals(fm) chisqs <- sapply(co_table(residuals(fm), fm$margin), function(x) sum(x^2)) pvals <- 1 - fm$pdist(chisqs) gpfun <- sapply(pvals, function(p) shading_hcl(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = h, c = c, l = l, interpolate = interpolate, lty = lty, level = level, p.value = p)) }, "sumchisq" = { if(is.null(level)) level <- 0.95 level <- level[1] fm <- coindep_test(x, cond.num, n = n, indepfun = function(x) sum(x^2), aggfun = sum) resids <- residuals(fm) gpfun <- shading_hcl(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = h, c = c, l = l, interpolate = interpolate, lty = lty, level = level, p.value = fm$p.value) }) type <- match.arg(type) if(type == "mosaic") { rval <- function(x, condlevels) { if(is.null(condlevels)) { tab <- x gp <- if(is.list(gpfun)) gpfun[[1]] else gpfun } else { tab <- co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]] gp <- if(is.list(gpfun)) gpfun[[paste(condlevels, collapse = ".")]] else gpfun } mosaic(tab, newpage = FALSE, pop = FALSE, gp = gp, legend = legend, prefix = paste("panel:", paste(names(condlevels), condlevels, sep = "=", collapse = ","), "|", sep = ""), ...) } } else { if(is.null(ylim)) ylim <- range(resids) rval <- function(x, condlevels) { if(is.null(condlevels)) { tab <- x gp <- if(is.list(gpfun)) gpfun[[1]] else gpfun } else { tab <- co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]] gp <- if(is.list(gpfun)) gpfun[[paste(condlevels, collapse = ".")]] else gpfun } assoc(tab, newpage = FALSE, pop = FALSE, gp = gp, legend = legend, ylim = ylim, prefix = paste("panel:", paste(names(condlevels), condlevels, sep = "=", collapse = ","), "|", sep = ""), ...) } } return(rval) } class(cotab_coindep) <- "grapcon_generator" vcd/R/structable.R0000644000175300001440000004232611623302245013376 0ustar meyerusers######################################### ## structable structable <- function(x, ...) UseMethod("structable") structable.formula <- function(formula, data = NULL, direction = NULL, split_vertical = NULL, ..., subset, na.action) { if (missing(formula) || !inherits(formula, "formula")) stop("formula is incorrect or missing") m <- match.call(expand.dots = FALSE) edata <- eval(m$data, parent.frame()) if (!is.null(direction)) split_vertical <- direction == "v" if (is.structable(data)) { split_vertical <- attr(data, "split_vertical") data <- as.table(data) } if (is.null(split_vertical)) split_vertical <- FALSE if (length(formula) == 3 && formula[[2]] == "Freq") formula[[2]] = NULL ## only rhs present without `.' in lhs => xtabs-interface if (length(formula) != 3) { if (formula[[1]] == "~") { if (inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { data <- as.table(data) varnames <- attr(terms(formula, allowDotAsName = TRUE), "term.labels") dnames <- names(dimnames(data)) di <- match(varnames, dnames) if (any(is.na(di))) stop("incorrect variable names in formula") if (all(varnames != ".")) data <- margin.table(data, di) return(structable(data, split_vertical = split_vertical, ...)) } else if (is.data.frame(data)) { if ("Freq" %in% colnames(data)) return(structable(xtabs(formula(paste("Freq", deparse(formula))), data = data), split_vertical = split_vertical, ...)) else return(structable(xtabs(formula, data), split_vertical = split_vertical, ...)) } else { if (is.matrix(edata)) m$data <- as.data.frame(data) m$... <- m$split_vertical <- m$direction <- NULL m[[1]] <- as.name("model.frame") mf <- eval(m, parent.frame()) return(structable(table(mf), split_vertical = split_vertical, ...)) } } else stop("formula must have both left and right hand sides") } ## `ftable' behavior if (any(attr(terms(formula, allowDotAsName = TRUE), "order") > 1)) stop("interactions are not allowed") rvars <- attr(terms(formula[-2], allowDotAsName = TRUE), "term.labels") cvars <- attr(terms(formula[-3], allowDotAsName = TRUE), "term.labels") rhs.has.dot <- any(rvars == ".") lhs.has.dot <- any(cvars == ".") if (lhs.has.dot && rhs.has.dot) stop(paste("formula has", sQuote("."), "in both left and right hand side")) if (inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { if (inherits(edata, "ftable")) data <- as.table(data) dnames <- names(dimnames(data)) rvars <- pmatch(rvars, dnames) cvars <- pmatch(cvars, dnames) if (rhs.has.dot) rvars <- seq_along(dnames)[-cvars] else if (any(is.na(rvars))) stop("incorrect variable names in rhs of formula") if (lhs.has.dot) cvars <- seq_along(dnames)[-rvars] else if (any(is.na(cvars))) stop("incorrect variable names in lhs of formula") split_vertical <- c(rep(FALSE, length(rvars)), rep(TRUE, length(cvars))) structable(margin.table(data, c(rvars, cvars)), split_vertical = split_vertical, ...) } else { if (is.matrix(edata)) m$data <- as.data.frame(data) m$... <- m$split_vertical <- m$direction <- NULL if (!is.null(data) && is.environment(data)) { dnames <- names(data) if (rhs.has.dot) rvars <- seq_along(dnames)[-cvars] if (lhs.has.dot) cvars <- seq_along(dnames)[-rvars] } else { if (lhs.has.dot || rhs.has.dot) stop("cannot use dots in formula with given data") } if ("Freq" %in% colnames(m$data)) m$formula <- formula(paste("Freq~", paste(c(rvars, cvars), collapse = "+"))) else m$formula <- formula(paste("~", paste(c(rvars, cvars), collapse = "+"))) m[[1]] <- as.name("xtabs") mf <- eval(m, parent.frame()) split_vertical <- c(rep(FALSE, length(rvars)), rep(TRUE, length(cvars))) structable(mf, split_vertical = split_vertical, ...) } } structable.default <- function(..., direction = NULL, split_vertical = FALSE) { ## several checks & transformations for arguments args <- list(...) if (length(args) == 0) stop("Nothing to tabulate") x <- args[[1]] x <- if (is.list(x)) table(x) else if (inherits(x, "ftable")) as.table(x) else if (!(is.array(x) && length(dim(x)) > 1 || inherits(x, "table"))) do.call("table", as.list(substitute(list(...)))[-1]) else x if (is.null(dimnames(x))) dimnames(x) <- lapply(dim(x), function(i) letters[seq_len(i)]) if (is.null(names(dimnames(x)))) names(dimnames(x)) <- LETTERS[seq_along(dim(x))] idx <- sapply(names(dimnames(x)), nchar) < 1 if(any(idx)) names(dimnames(x))[idx] <- LETTERS[seq_len(sum(idx))] ## splitting argument dl <- length(dim(x)) if (!is.null(direction)) split_vertical <- direction == "v" if (length(split_vertical) == 1) split_vertical <- rep(c(split_vertical, !split_vertical), length.out = dl) if (length(split_vertical) < dl) split_vertical <- rep(split_vertical, length.out = dl) ## permute & reshape ret <- base::aperm(x, c(rev(which(!split_vertical)), rev(which(split_vertical)))) dn <- dimnames(x) rv <- dn[split_vertical] cv <- dn[!split_vertical] rl <- if (length(rv)) sapply(rv, length) else 1 cl <- if (length(cv)) sapply(cv, length) else 1 dim(ret) <- c(prod(cl), prod(rl)) ## add dimnames attr(ret, "dnames") <- dn attr(ret, "split_vertical") <- split_vertical ## add dimension attributes in ftable-format attr(ret, "col.vars") <- rv attr(ret, "row.vars") <- cv class(ret) <- c("structable", "ftable") ret } "[[.structable" <- function(x, ...) { if(nargs() > 3) stop("Incorrect number of dimensions (max: 2).") args <- if (nargs() < 3) list(..1) else .massage_args(...) args <- lapply(args, function(x) if (is.logical(x)) which(x) else x) ## handle one-arg cases if (nargs() < 3) if (length(args[[1]]) > 1) ## resolve calls like x[[c(1,2)]] return(x[[ args[[1]][1] ]] [[ args[[1]][-1] ]]) else ## resolve x[[foo]] return(if (attr(x, "split_vertical")[1]) x[[,args[[1]] ]] else x[[args[[1]],]]) ## handle calls like x[[c(1,2), c(3,4)]] if (length(args[[1]]) > 1 && length(args[[2]]) > 1) return(x[[ args[[1]][1], args[[2]][1] ]] [[ args[[1]][-1], args[[2]][-1] ]]) ## handle calls like x[[c(1,2), 3]] if (length(args[[1]]) > 1) return(x[[ args[[1]][1], args[[2]] ]] [[ args[[1]][-1], ]]) ## handle calls like x[[1, c(1,3)]] if (length(args[[2]]) > 1) return(x[[ args[[1]], args[[2]][1] ]] [[ , args[[2]][-1] ]]) ## final cases like x[[1,2]] or x[[1,]] or x[[,1]] dnames <- attr(x, "dnames") split <- attr(x, "split_vertical") rv <- dnames[!split] cv <- dnames[split] lsym <- is.symbol(args[[1]]) rsym <- is.symbol(args[[2]]) if (!lsym) { rstep <- dim(unclass(x))[1] / length(rv[[1]]) if (is.character(args[[1]])) args[[1]] <- match(args[[1]], rv[[1]]) } if (!rsym) { cstep <- dim(unclass(x))[2] / length(cv[[1]]) if (is.character(args[[2]])) args[[2]] <- match(args[[2]], cv[[1]]) } lind <- if (!lsym) (1 + (args[[1]] - 1) * rstep) : (args[[1]] * rstep) else 1:nrow(unclass(x)) rind <- if (!rsym) (1 + (args[[2]] - 1) * cstep) : (args[[2]] * cstep) else 1:ncol(unclass(x)) ret <- unclass(x)[lind, rind, drop = FALSE] if (!lsym) { i <- which(!split)[1] split <- split[-i] dnames <- dnames[-i] } if (!rsym) { i <- which(split)[1] split <- split[-i] dnames <- dnames[-i] } attr(ret, "split_vertical") <- split attr(ret, "dnames") <- dnames ## add dimension attributes in ftable-format attr(ret, "col.vars") <- dnames[split] attr(ret, "row.vars") <- dnames[!split] class(ret) <- class(x) ret } "[[<-.structable" <- function(x, ..., value) { args <- if (nargs() < 4) list(..1) else .massage_args(...) ## handle one-arg cases if (nargs() < 4) return(if (length(args[[1]]) > 1) ## resolve calls like x[[c(1,2)]]<-value Recall(x, args[[1]][1], value = Recall(x[[ args[[1]][1] ]], args[[1]][-1], value = value)) else ## resolve x[[foo]]<-value if (attr(x, "split_vertical")[1]) Recall(x,,args[[1]], value = value) else Recall(x,args[[1]],, value = value) ) ## handle calls like x[[c(1,2), c(3,4)]]<-value if (length(args[[1]]) > 1 && length(args[[2]]) > 1) return(Recall(x, args[[1]][1], args[[2]][1], value = Recall(x[[ args[[1]][1], args[[2]][1] ]], args[[1]][-1], args[[2]][-1], value = value))) ## handle calls like x[[c(1,2), 3]]<-value if (length(args[[1]]) > 1) return(Recall(x, args[[1]][1], args[[2]], value = Recall(x[[ args[[1]][1], args[[2]] ]], args[[1]][-1], ,value = value))) ## handle calls like x[[1, c(1,3)]]<-value if (length(args[[2]]) > 1) return(Recall(x, args[[1]], args[[2]][1], value = Recall(x[[ args[[1]], args[[2]][1] ]],, args[[2]][-1], value = value))) ## final cases like x[[1,2]]<-value or x[[1,]]<-value or x[[,1]]<-value dnames <- attr(x, "dnames") split <- attr(x, "split_vertical") rv <- dnames[!split] cv <- dnames[split] lsym <- is.symbol(args[[1]]) rsym <- is.symbol(args[[2]]) if (!lsym) { rstep <- dim(unclass(x))[1] / length(rv[[1]]) if (is.character(args[[1]])) args[[1]] <- match(args[[1]], rv[[1]]) } if (!rsym) { cstep <- dim(unclass(x))[2] / length(cv[[1]]) if (is.character(args[[2]])) args[[2]] <- match(args[[2]], cv[[1]]) } lind <- if (!lsym) (1 + (args[[1]] - 1) * rstep) : (args[[1]] * rstep) else 1:nrow(unclass(x)) rind <- if (!rsym) (1 + (args[[2]] - 1) * cstep) : (args[[2]] * cstep) else 1:ncol(unclass(x)) ret <- unclass(x) ret[lind, rind] <- value class(ret) <- class(x) ret } "[.structable" <- function(x, ...) { if(nargs() > 3) stop("Incorrect number of dimensions (max: 2).") args <- if (nargs() < 3) list(..1) else .massage_args(...) args <- lapply(args, function(x) if (is.logical(x)) which(x) else x) ## handle one-arg cases if (nargs() < 3) return(if (attr(x, "split_vertical")[1]) x[,args[[1]] ] else x[args[[1]],]) ## handle calls like x[c(1,2), foo] if (length(args[[1]]) > 1) return(do.call(rbind, lapply(args[[1]], function(i) x[i, args[[2]]]))) ## handle calls like x[foo, c(1,3)] if (length(args[[2]]) > 1) return(do.call(cbind, lapply(args[[2]], function(i) x[args[[1]], i]))) ## final cases like x[1,2] or x[1,] or x[,1] dnames <- attr(x, "dnames") split <- attr(x, "split_vertical") rv <- dnames[!split] cv <- dnames[split] lsym <- is.symbol(args[[1]]) rsym <- is.symbol(args[[2]]) if (!lsym) { rstep <- dim(unclass(x))[1] / length(rv[[1]]) if (is.character(args[[1]])) args[[1]] <- match(args[[1]], rv[[1]]) } if (!rsym) { cstep <- dim(unclass(x))[2] / length(cv[[1]]) if (is.character(args[[2]])) args[[2]] <- match(args[[2]], cv[[1]]) } lind <- if (!lsym) (1 + (args[[1]] - 1) * rstep) : (args[[1]] * rstep) else 1:nrow(unclass(x)) rind <- if (!rsym) (1 + (args[[2]] - 1) * cstep) : (args[[2]] * cstep) else 1:ncol(unclass(x)) ret <- unclass(x)[lind, rind, drop = FALSE] if (!lsym) { i <- which(!split)[1] dnames[[i]] <- dnames[[i]][args[[1]]] } if (!rsym) { i <- which(split)[1] dnames[[i]] <- dnames[[i]][args[[2]]] } attr(ret, "split_vertical") <- split attr(ret, "dnames") <- dnames ## add dimension attributes in ftable-format attr(ret, "col.vars") <- dnames[split] attr(ret, "row.vars") <- dnames[!split] class(ret) <- class(x) ret } "[<-.structable" <- function(x, ..., value) { args <- if (nargs() < 4) list(..1) else .massage_args(...) ## handle one-arg cases if (nargs() < 4) return(## resolve x[foo] if (attr(x, "split_vertical")[1]) Recall(x,,args[[1]], value = value) else Recall(x,args[[1]],, value = value) ) ## handle calls like x[c(1,2), 3] if (length(args[[1]]) > 1) { for (i in seq_along(args[[1]])) x[ args[[1]][i], args[[2]] ] <- value[i,] return(x) } ## handle calls like x[1, c(2,3)] if (length(args[[2]]) > 1) { for (i in seq_along(args[[2]])) x[ args[[1]], args[[2]][i] ] <- value[,i] return(x) } ## final cases like x[1,2] or x[1,] or x[,1] dnames <- attr(x, "dnames") split <- attr(x, "split_vertical") rv <- dnames[!split] cv <- dnames[split] lsym <- is.symbol(args[[1]]) rsym <- is.symbol(args[[2]]) if (!lsym) { rstep <- dim(unclass(x))[1] / length(rv[[1]]) if (is.character(args[[1]])) args[[1]] <- match(args[[1]], rv[[1]]) } if (!rsym) { cstep <- dim(unclass(x))[2] / length(cv[[1]]) if (is.character(args[[2]])) args[[2]] <- match(args[[2]], cv[[1]]) } lind <- if (!lsym) (1 + (args[[1]] - 1) * rstep) : (args[[1]] * rstep) else 1:nrow(unclass(x)) rind <- if (!rsym) (1 + (args[[2]] - 1) * cstep) : (args[[2]] * cstep) else 1:ncol(unclass(x)) ret <- unclass(x) ret[lind, rind] <- value class(ret) <- class(x) ret } cbind.structable <- function(..., deparse.level = 1) { mergetables <- function(t1, t2) { ret <- cbind(unclass(t1),unclass(t2)) class(ret) <- class(t1) attr(ret, "split_vertical") <- attr(t1, "split_vertical") attr(ret, "dnames") <- attr(t1, "dnames") attr(ret, "row.vars") <- attr(t1, "row.vars") attr(ret, "col.vars") <- attr(t1, "col.vars") attr(ret, "col.vars")[[1]] <- c(attr(t1, "col.vars")[[1]],attr(t2, "col.vars")[[1]]) if (length(unique(attr(ret, "col.vars")[[1]])) != length(attr(ret, "col.vars")[[1]])) stop("Levels of factor(s) to be merged must be unique.") attr(ret, "dnames")[names(attr(ret, "col.vars"))] <- attr(ret, "col.vars") ret } args <- list(...) if (length(args) < 2) return(args[[1]]) ret <- mergetables(args[[1]], args[[2]]) if (length(args) > 2) do.call(cbind, c(list(ret), args[-(1:2)])) else ret } rbind.structable <- function(..., deparse.level = 1) { mergetables <- function(t1, t2) { ret <- rbind(unclass(t1),unclass(t2)) class(ret) <- class(t1) attr(ret, "split_vertical") <- attr(t1, "split_vertical") attr(ret, "dnames") <- attr(t1, "dnames") attr(ret, "row.vars") <- attr(t1, "row.vars") attr(ret, "col.vars") <- attr(t1, "col.vars") attr(ret, "row.vars")[[1]] <- c(attr(t1, "row.vars")[[1]],attr(t2, "row.vars")[[1]]) if (length(unique(attr(ret, "row.vars")[[1]])) != length(attr(ret, "row.vars")[[1]])) stop("Levels of factor(s) to be merged must be unique.") attr(ret, "dnames")[names(attr(ret, "row.vars"))] <- attr(ret, "row.vars") ret } args <- list(...) if (length(args) < 2) return(args[[1]]) ret <- mergetables(args[[1]], args[[2]]) if (length(args) > 2) do.call(rbind, c(list(ret), args[-(1:2)])) else ret } as.table.structable <- function(x, ...) { ret <- stats:::as.table.ftable(x) structure(base::aperm(ret, match(names(attr(x, "dnames")), names(dimnames(ret)))), class = "table") } plot.structable <- function(x, ...) mosaic(x, ...) t.structable <- function(x) { ret <- t.default(x) attr(ret, "split_vertical") <- !attr(ret, "split_vertical") hold <- attr(ret, "row.vars") attr(ret, "row.vars") = attr(ret, "col.vars") attr(ret, "col.vars") = hold ret } is.structable <- function(x) inherits(x, "structable") dim.structable <- function(x) as.integer(sapply(attr(x, "dnames"), length)) print.structable <- function(x, ...) { class(x) <- "ftable" NextMethod("print", object = x) } dimnames.structable <- function(x) attr(x,"dnames") as.vector.structable <- function(x, ...) as.vector(as.table(x), ...) as.matrix.structable <- function(x, ...) matrix(as.vector(unclass(x)), ncol = attr(x, "dim")[2]) length.structable <- function(x) dim(x)[1] is.na.structable <- function(x) sapply(seq_along(x), function(sub) any(is.na(sub))) str.structable <- function(object, ...) str(unclass(object), ...) find.perm <- function(vec1, vec2) { unlist(Map(function(x) which(x == vec2), vec1)) } aperm.structable <- function(a, perm, resize=TRUE, ...){ newtable <- aperm(as.table(a), perm = perm, resize = resize, ...) if (!is.numeric(perm)) perm <- find.perm(names(dimnames(newtable)), names(dimnames(a))) structable(newtable, split_vertical = attr(a, "split_vertical")[perm]) } ############# helper function .massage_args <- function(...) { args <- vector("list", 2) args[[1]] <- if(missing(..1)) as.symbol("grrr") else ..1 args[[2]] <- if(missing(..2)) as.symbol("grrr") else ..2 args } vcd/R/Ord_plot.R0000644000175300001440000000636011371553135013014 0ustar meyerusersOrd_plot <- function(obj, legend = TRUE, estimate = TRUE, tol = 0.1, type = NULL, xlim = NULL, ylim = NULL, xlab = "Number of occurrences", ylab = "Frequency ratio", main = "Ord plot", gp = gpar(cex = 0.5), name = "Ord_plot", newpage = TRUE, pop = TRUE, ...) { if(is.vector(obj)) { obj <- table(obj) } if(is.table(obj)) { if(length(dim(obj)) > 1) stop ("obj must be a 1-way table") x <- as.vector(obj) count <- as.numeric(names(obj)) } else { if(!(!is.null(ncol(obj)) && ncol(obj) == 2)) stop("obj must be a 2-column matrix or data.frame") x <- as.vector(obj[,1]) count <- as.vector(obj[,2]) } y <- count * x/c(NA, x[-length(x)]) fm <- lm(y ~ count) fmw <- lm(y ~ count, weights = sqrt(pmax(x, 1) - 1)) fit1 <- predict(fm, data.frame(count)) fit2 <- predict(fmw, data.frame(count)) if(is.null(xlim)) xlim <- range(count) if(is.null(ylim)) ylim <- range(c(y, fit1, fit2), na.rm = TRUE) xlim <- xlim + c(-1, 1) * diff(xlim) * 0.04 ylim <- ylim + c(-1, 1) * diff(ylim) * 0.04 if(newpage) grid.newpage() pushViewport(plotViewport(xscale = xlim, yscale = ylim, default.units = "native", name = name)) grid.points(x = count, y = y, default.units = "native", gp = gp, ...) grid.lines(x = count, y = fit1, default.units = "native") grid.lines(x = count, y = fit2, default.units = "native", gp = gpar(col = 2)) grid.rect(gp = gpar(fill = "transparent")) grid.xaxis() grid.yaxis() grid.text(xlab, y = unit(-3.5, "lines")) grid.text(ylab, x = unit(-3, "lines"), rot = 90) grid.text(main, y = unit(1, "npc") + unit(2, "lines"), gp = gpar(fontface = "bold")) RVAL <- coef(fmw) names(RVAL) <- c("Intercept", "Slope") if(legend) { legend.text <- c(paste("slope =", round(RVAL[2], digits = 3)), paste("intercept =", round(RVAL[1], digits = 3))) if(estimate) { ordfit <- Ord_estimate(RVAL, type = type, tol = tol) legend.text <- c(legend.text, "", paste("type:", ordfit$type), paste("estimate:", names(ordfit$estimate),"=", round(ordfit$estimate, digits = 3))) legend.text <- paste(legend.text, collapse = "\n") } grid.text(legend.text, min(count), ylim[2] * 0.95, default.units = "native", just = c("left", "top")) } if(pop) popViewport() else upViewport() invisible(RVAL) } Ord_estimate <- function(x, type = NULL, tol = 0.1) { a <- x[1] b <- x[2] if(!is.null(type)) type <- match.arg(type, c("poisson", "binomial", "nbinomial", "log-series")) else { if(abs(b) < tol) type <- "poisson" else if(b < (-1 * tol)) type <- "binomial" else if(a > (-1 * tol)) type <- "nbinomial" else if(abs(a + b) < 4*tol) type <- "log-series" else type <- "none" } switch(type, "poisson" = { par <- a names(par) <- "lambda" if(par < 0) warning("lambda not > 0") }, "binomial" = { par <- b/(b - 1) names(par) <- "prob" if(abs(par - 0.5) > 0.5) warning("prob not in (0,1)") }, "nbinomial" = { par <- 1 - b names(par) <- "prob" if(abs(par - 0.5) > 0.5) warning("prob not in (0,1)") }, "log-series" = { par <- b names(par) <- "theta" if(par < 0) warning("theta not > 0") }, "none" = { par <- NA }) list(estimate = par, type = type) } vcd/R/mosaic.R0000644000175300001440000003223111150520606012471 0ustar meyerusers########################################################### ## mosaicplot mosaic <- function(x, ...) UseMethod("mosaic") mosaic.formula <- function(formula, data = NULL, highlighting = NULL, ..., main = NULL, sub = NULL, subset = NULL, na.action = NULL) { if (is.logical(main) && main) main <- deparse(substitute(data)) else if (is.logical(sub) && sub) sub <- deparse(substitute(data)) m <- match.call(expand.dots = FALSE) edata <- eval(m$data, parent.frame()) fstr <- strsplit(paste(deparse(formula), collapse = ""), "~") vars <- strsplit(strsplit(gsub(" ", "", fstr[[1]][2]), "\\|")[[1]], "\\+") varnames <- vars[[1]] condnames <- if (length(vars) > 1) vars[[2]] else NULL dep <- gsub(" ", "", fstr[[1]][1]) if (is.null(highlighting) && (!dep %in% c("","Freq"))) { if (all(varnames == ".")) { varnames <- if (is.data.frame(data)) colnames(data) else names(dimnames(as.table(data))) varnames <- varnames[-which(varnames %in% dep)] } varnames <- c(varnames, dep) highlighting <- length(varnames) + length(condnames) } if (inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { condind <- NULL dat <- as.table(data) if(all(varnames != ".")) { ind <- match(varnames, names(dimnames(dat))) if (any(is.na(ind))) stop(paste("Can't find", paste(varnames[is.na(ind)], collapse=" / "), "in", deparse(substitute(data)))) if (!is.null(condnames)) { condind <- match(condnames, names(dimnames(dat))) if (any(is.na(condind))) stop(paste("Can't find", paste(condnames[is.na(condind)], collapse=" / "), "in", deparse(substitute(data)))) ind <- c(condind, ind) } dat <- margin.table(dat, ind) } mosaic.default(dat, main = main, sub = sub, highlighting = highlighting, condvars = if (is.null(condind)) NULL else match(condnames, names(dimnames(dat))), ...) } else { m <- m[c(1, match(c("formula", "data", "subset", "na.action"), names(m), 0))] m[[1]] <- as.name("xtabs") m$formula <- formula(paste(if("Freq" %in% colnames(data)) "Freq", "~", paste(c(condnames, varnames), collapse = "+"))) tab <- eval(m, parent.frame()) mosaic.default(tab, main = main, sub = sub, highlighting = highlighting, ...) } } mosaic.default <- function(x, condvars = NULL, split_vertical = NULL, direction = NULL, spacing = NULL, spacing_args = list(), gp = NULL, expected = NULL, shade = NULL, highlighting = NULL, highlighting_fill = grey.colors, highlighting_direction = NULL, zero_size = 0.5, zero_split = FALSE, zero_shade = NULL, zero_gp = gpar(col = 0), panel = NULL, main = NULL, sub = NULL, ...) { zero_shade <- !is.null(shade) && shade || !is.null(expected) || !is.null(gp) if (!is.null(shade) && !shade) zero_shade = FALSE if (is.logical(main) && main) main <- deparse(substitute(x)) else if (is.logical(sub) && sub) sub <- deparse(substitute(x)) if (is.structable(x)) { if (is.null(direction) && is.null(split_vertical)) split_vertical <- attr(x, "split_vertical") x <- as.table(x) } if (is.null(split_vertical)) split_vertical <- FALSE dl <- length(dim(x)) ## splitting argument if (!is.null(direction)) split_vertical <- direction == "v" if (length(split_vertical) == 1) split_vertical <- rep(c(split_vertical, !split_vertical), length.out = dl) if (length(split_vertical) < dl) split_vertical <- rep(split_vertical, length.out = dl) ## highlighting if (!is.null(highlighting)) { if (is.character(highlighting)) highlighting <- match(highlighting, names(dimnames(x))) if (length(highlighting) > 0) { if (is.character(condvars)) condvars <- match(condvars, names(dimnames(x))) x <- if (length(condvars) > 0) aperm(x, c(condvars, seq(dl)[-c(condvars,highlighting)], highlighting)) else aperm(x, c(seq(dl)[-highlighting], highlighting)) if (is.null(spacing)) spacing <- spacing_highlighting if (is.function(highlighting_fill)) highlighting_fill <- rev(highlighting_fill(dim(x)[dl])) if (is.null(gp)) gp <- gpar(fill = highlighting_fill) if (!is.null(highlighting_direction)) { split_vertical[dl] <- highlighting_direction %in% c("left", "right") if (highlighting_direction %in% c("left", "top")) { ## ugly: tmp <- as.data.frame.table(x) tmp[,dl] <- factor(tmp[,dl], rev(levels(tmp[,dl]))) x <- xtabs(Freq ~ ., data = tmp) gp <- gpar(fill = rev(highlighting_fill)) } } } } ## Conditioning only if (!is.null(condvars)) { if (is.character(condvars)) condvars <- match(condvars, names(dimnames(x))) if (length(condvars) > 0) x <- aperm(x, c(condvars, seq(dl)[-condvars])) if (is.null(spacing)) spacing <- spacing_conditional } ## spacing argument if (is.null(spacing)) spacing <- if (dl < 3) spacing_equal else spacing_increase strucplot(x, condvars = if (is.null(condvars)) NULL else length(condvars), core = struc_mosaic(zero_size = zero_size, zero_split = zero_split, zero_shade = zero_shade, zero_gp = zero_gp, panel = panel), split_vertical = split_vertical, spacing = spacing, spacing_args = spacing_args, gp = gp, expected = expected, shade = shade, main = main, sub = sub, ...) } ## old code: more elegant, but less performant ## ## struc_mosaic2 <- function(zero_size = 0.5, zero_split = FALSE, ## zero_shade = TRUE, zero_gp = gpar(col = 0)) ## function(residuals, observed, expected = NULL, spacing, gp, split_vertical, prefix = "") { ## dn <- dimnames(observed) ## dnn <- names(dn) ## dx <- dim(observed) ## dl <- length(dx) ## ## split workhorse ## zerostack <- character(0) ## split <- function(x, i, name, row, col, zero) { ## cotab <- co_table(x, 1) ## margin <- sapply(cotab, sum) ## v <- split_vertical[i] ## d <- dx[i] ## ## compute total cols/rows and build split layout ## dist <- unit.c(unit(margin, "null"), spacing[[i]]) ## idx <- matrix(1:(2 * d), nrow = 2, byrow = TRUE)[-2 * d] ## layout <- if (v) ## grid.layout(ncol = 2 * d - 1, widths = dist[idx]) ## else ## grid.layout(nrow = 2 * d - 1, heights = dist[idx]) ## vproot <- viewport(layout.pos.col = col, layout.pos.row = row, ## layout = layout, name = remove_trailing_comma(name)) ## ## next level: either create further splits, or final viewports ## name <- paste(name, dnn[i], "=", dn[[i]], ",", sep = "") ## row <- col <- rep.int(1, d) ## if (v) col <- 2 * 1:d - 1 else row <- 2 * 1:d - 1 ## f <- if (i < dl) ## function(m) { ## co <- cotab[[m]] ## z <- mean(co) <= .Machine$double.eps ## if (z && !zero && !zero_split) zerostack <<- c(zerostack, name[m]) ## split(co, i + 1, name[m], row[m], col[m], z && !zero_split) ## } ## else ## function(m) { ## if (cotab[[m]] <= .Machine$double.eps && !zero) ## zerostack <<- c(zerostack, name[m]) ## viewport(layout.pos.col = col[m], layout.pos.row = row[m], ## name = remove_trailing_comma(name[m])) ## } ## vpleaves <- structure(lapply(1:d, f), class = c("vpList", "viewport")) ## vpTree(vproot, vpleaves) ## } ## ## start spltting on top, creates viewport-tree ## pushViewport(split(observed + .Machine$double.eps, ## i = 1, name = paste(prefix, "cell:", sep = ""), ## row = 1, col = 1, zero = FALSE)) ## ## draw rectangles ## mnames <- apply(expand.grid(dn), 1, ## function(i) paste(dnn, i, collapse=",", sep = "=") ## ) ## zeros <- observed <= .Machine$double.eps ## ## draw zero cell lines ## for (i in remove_trailing_comma(zerostack)) { ## seekViewport(i) ## grid.lines(x = 0.5) ## grid.lines(y = 0.5) ## if (!zero_shade && zero_size > 0) { ## grid.points(0.5, 0.5, pch = 19, size = unit(zero_size, "char"), ## gp = zero_gp, ## name = paste(prefix, "disc:", mnames[i], sep = "")) ## grid.points(0.5, 0.5, pch = 1, size = unit(zero_size, "char"), ## name = paste(prefix, "circle:", mnames[i], sep = "")) ## } ## } ## # draw boxes ## for (i in seq_along(mnames)) { ## seekViewport(paste(prefix, "cell:", mnames[i], sep = "")) ## gpobj <- structure(lapply(gp, function(x) x[i]), class = "gpar") ## if (!zeros[i]) { ## grid.rect(gp = gpobj, name = paste(prefix, "rect:", mnames[i], sep = "")) ## } else { ## if (zero_shade && zero_size > 0) { ## grid.points(0.5, 0.5, pch = 19, size = unit(zero_size, "char"), ## gp = gpar(col = gp$fill[i]), ## name = paste(prefix, "disc:", mnames[i], sep = "")) ## grid.points(0.5, 0.5, pch = 1, size = unit(zero_size, "char"), ## name = paste(prefix, "circle:", mnames[i], sep = "")) ## } ## } ## } ## } ## class(struc_mosaic2) <- "grapcon_generator" struc_mosaic <- function(zero_size = 0.5, zero_split = FALSE, zero_shade = TRUE, zero_gp = gpar(col = 0), panel = NULL) function(residuals, observed, expected = NULL, spacing, gp, split_vertical, prefix = "") { dn <- dimnames(observed) dnn <- names(dn) dx <- dim(observed) dl <- length(dx) zeros <- function(gp, name) { grid.lines(x = 0.5) grid.lines(y = 0.5) if (zero_size > 0) { grid.points(0.5, 0.5, pch = 19, size = unit(zero_size, "char"), gp = gp, name = paste(prefix, "disc:", name, sep = "")) grid.points(0.5, 0.5, pch = 1, size = unit(zero_size, "char"), name = paste(prefix, "circle:", name, sep = "")) } } ## split workhorse zerostack <- character(0) split <- function(x, i, name, row, col, zero, index) { cotab <- co_table(x, 1) margin <- sapply(cotab, sum) margin[margin == 0] <- .Machine$double.eps # margin <- margin + .Machine$double.eps v <- split_vertical[i] d <- dx[i] ## compute total cols/rows and build split layout dist <- if (d > 1) unit.c(unit(margin, "null"), spacing[[i]]) else unit(margin, "null") idx <- matrix(1:(2 * d), nrow = 2, byrow = TRUE)[-2 * d] layout <- if (v) grid.layout(ncol = 2 * d - 1, widths = dist[idx]) else grid.layout(nrow = 2 * d - 1, heights = dist[idx]) pushViewport(viewport(layout.pos.col = col, layout.pos.row = row, layout = layout, name = paste(prefix, "cell:", remove_trailing_comma(name), sep = ""))) ## next level: either create further splits, or final viewports row <- col <- rep.int(1, d) if (v) col <- 2 * 1:d - 1 else row <- 2 * 1:d - 1 for (m in 1:d) { nametmp <- paste(name, dnn[i], "=", dn[[i]][m], ",", sep = "") if (i < dl) { co <- cotab[[m]] ## zeros z <- mean(co) <= .Machine$double.eps split(co, i + 1, nametmp, row[m], col[m], z && !zero_split, cbind(index, m)) if (z && !zero && !zero_split && !zero_shade && (zero_size > 0)) zeros(zero_gp, nametmp) } else { pushViewport(viewport(layout.pos.col = col[m], layout.pos.row = row[m], name = paste(prefix, "cell:", remove_trailing_comma(nametmp), sep = ""))) ## zeros if (cotab[[m]] <= .Machine$double.eps && !zero) { zeros(if (!zero_shade) zero_gp else gpar(col = gp$fill[cbind(index,m)]), nametmp) } else { ## rectangles gpobj <- structure(lapply(gp, function(x) x[cbind(index, m)]), class = "gpar") nam <- paste(prefix, "rect:", remove_trailing_comma(nametmp), sep = "") if (!is.null(panel)) panel(residuals, observed, expected, c(cbind(index, m)), gpobj, nam) else grid.rect(gp = gpobj, name = nam) } } upViewport(1) } } ## start splitting on top, creates viewport-tree split(observed, i = 1, name = "", row = 1, col = 1, zero = FALSE, index = cbind()) } class(struc_mosaic) <- "grapcon_generator" vcd/R/plot.loglm.R0000644000175300001440000000176711150520606013317 0ustar meyerusersplot.loglm <- function(x, panel = mosaic, type = c("observed", "expected"), residuals_type = c("pearson", "deviance"), gp = shading_hcl, gp_args = list(), ...) { residuals_type <- match.arg(tolower(residuals_type), c("pearson", "deviance")) if(is.null(x$fitted)) x <- update(x, fitted = TRUE) expected <- fitted(x) residuals <- residuals(x, type = "pearson") observed <- residuals * sqrt(expected) + expected if(residuals_type == "deviance") residuals <- residuals(x, type = "deviance") gp <- if(inherits(gp, "grapcon_generator")) do.call("gp", c(list(observed, residuals, expected, x$df), as.list(gp_args))) else gp panel(observed, residuals = residuals, expected = expected, type = type, residuals_type = residuals_type, gp = gp, ...) } mosaic.loglm <- function(x, ...) { plot(x, panel = mosaic, ...) } assoc.loglm <- function(x, ...) { plot(x, panel = assoc, ...) } vcd/R/pairsplot.R0000644000175300001440000001772011720271304013242 0ustar meyerusers################################################################# ### pairsplot pairs.table <- function(x, upper_panel = pairs_mosaic, upper_panel_args = list(), lower_panel = pairs_mosaic, lower_panel_args = list(), diag_panel = pairs_barplot, diag_panel_args = list(), main = NULL, sub = NULL, main_gp = gpar(fontsize = 20), sub_gp = gpar(fontsize = 15), space = 0.3, newpage = TRUE, pop = TRUE, margins = unit(1, "lines"), ...) { if (newpage) grid.newpage() if (inherits(upper_panel, "grapcon_generator")) upper_panel <- do.call("upper_panel", c(upper_panel_args, list(...))) if (inherits(lower_panel, "grapcon_generator")) lower_panel <- do.call("lower_panel", c(lower_panel_args, list(...))) if (inherits(diag_panel, "grapcon_generator")) diag_panel <- do.call("diag_panel", diag_panel_args) d <- length(dim(x)) l <- grid.layout(d, d) pushViewport(viewport(width = unit(1, "snpc"), height = unit(1, "snpc"))) pushViewport(vcdViewport(mar = margins, legend = FALSE, legend_width = NULL, main = !is.null(main), sub = !is.null(sub))) ## titles if (!is.null(main)) { seekViewport("main") if (is.logical(main) && main) main <- deparse(substitute(x)) grid.text(main, gp = main_gp) } if (!is.null(sub)) { seekViewport("sub") if (is.logical(sub) && sub && is.null(main)) sub <- deparse(substitute(x)) grid.text(sub, gp = sub_gp) } seekViewport("plot") pushViewport(viewport(layout = l, y = 0, just = "bottom")) for (i in 1:d) for(j in 1:d) { pushViewport(viewport(layout.pos.col = i, layout.pos.row = j)) pushViewport(viewport(width = 1 - space, height = 1 - space)) if (i > j) { if (!is.null(upper_panel)) upper_panel(x, j, i) } else if (i < j) { if (!is.null(lower_panel)) lower_panel(x, j, i) } else if (!is.null(diag_panel)) diag_panel(x, i) if (pop) popViewport(2) else upViewport(2) } if (pop) popViewport(3) else upViewport(3) invisible(x) } pairs.structable <- function(x, ...) pairs(as.table(x), ...) ## upper/lower panels pairs_assoc <- function(...) pairs_strucplot(panel = assoc, ...) class(pairs_assoc) <- "grapcon_generator" pairs_mosaic <- function(...) pairs_strucplot(panel = mosaic, ...) class(pairs_mosaic) <- "grapcon_generator" pairs_sieve <- function(...) pairs_strucplot(panel = sieve, ...) class(pairs_sieve) <- "grapcon_generator" pairs_strucplot <- function(panel = mosaic, type = c("pairwise", "total", "conditional", "joint"), legend = FALSE, margins = c(0, 0, 0, 0), labeling = NULL, ...) { type = match.arg(type) function(x, i, j) { index <- 1:length(dim(x)) rest <- index[!index %in% c(i, j)] rest2 <- index[!index %in% 1:2] panel(x = margin.table(x, if (type == "pairwise") c(j, i) else c(j, i, rest)), expected = if (type == "joint") list(1:2, rest2) else NULL, condvars = if (type == "conditional") rest2 else NULL, labeling = labeling, margins = margins, legend = legend, split_vertical = TRUE, newpage = FALSE, pop = FALSE, prefix = paste("panel:Y=",names(dimnames(x))[i],",X=", names(dimnames(x))[j],"|",sep = ""), ...) } } class(pairs_strucplot) <- "grapcon_generator" ## diagonal panels pairs_text <- function(dimnames = TRUE, gp_vartext = gpar(fontsize = 17), gp_leveltext = gpar(), gp_border = gpar(), ...) function(x, i) { x <- margin.table(x, i) grid.rect(gp = gp_border) grid.text(names(dimnames(x)), gp = gp_vartext, y = 0.5 + dimnames * 0.05, ...) if (dimnames) grid.text(paste("(",paste(names(x), collapse = ","), ")", sep = ""), y = 0.4, gp = gp_leveltext) } class(pairs_text) <- "grapcon_generator" pairs_diagonal_text <- function(varnames = TRUE, gp_vartext = gpar(fontsize = 17, fontface = "bold"), gp_leveltext = gpar(), gp_border = gpar(), pos = c("right","top"), distribute = c("equal","margin"), rot = 0, ...) { xc <- unit(switch(pos[1], left = 0.1, center = 0.5, 0.9), "npc") yc <- unit(switch(pos[2], top = 0.9, center = 0.5, 0.1), "npc") distribute <- match.arg(distribute) function(x, i) { x <- margin.table(x, i) grid.rect(gp = gp_border) if (varnames) grid.text(names(dimnames(x)), gp = gp_vartext, x = xc, y = yc, just = pos, ...) l <- length(dimnames(x)[[1]]) po <- if (distribute == "equal") unit(cumsum(rep(1 / (l + 1), l)), "npc") else { sizes = prop.table(x) unit(cumsum(c(0,sizes))[1:l] + sizes / 2, "npc") } grid.text(dimnames(x)[[1]], x = po, y = unit(1, "npc") - po, gp = gp_leveltext, rot = rot) } } class(pairs_diagonal_text) <- "grapcon_generator" pairs_barplot <- function(gp_bars = NULL, gp_vartext = gpar(fontsize = 17), gp_leveltext = gpar(), just_leveltext = c("center", "bottom"), just_vartext = c("center", "top"), rot = 0, abbreviate = FALSE, check_overlap = TRUE, fill = "grey", var_offset = unit(1, "npc"), ...) function(x, i) { if (!is.unit(var_offset)) var_offset <- unit(var_offset, "npc") dn <- names(dimnames(x)) x <- margin.table(x, i) if (is.function(fill)) fill <- rev(fill(dim(x))) if (is.null(gp_bars)) gp_bars <- gpar(fill = fill) pushViewport(viewport(x = 0.3, y = 0.1, width = 0.7, height = 0.7, yscale = c(0,max(x)), just = c("left", "bottom")) ) xpos <- seq(0, 1, length = length(x) + 1)[-1] halfstep <- (xpos[2] - xpos[1]) / 2 grid.rect(xpos - halfstep, rep.int(0, length(x)), height = x, just = c("center", "bottom"), width = halfstep, gp = gp_bars, default.units = "native", name = paste("panel:diag=", dn[i], "|bars", sep = ""), ...) grid.yaxis(at = pretty(c(0,max(x)))) txt <- names(x) if (abbreviate) txt <- abbreviate(txt, abbreviate) grid.text(txt, y = unit(-0.15, "npc"), rot = rot, x = xpos - halfstep, just = just_leveltext, gp = gp_leveltext, check.overlap = check_overlap) popViewport(1) grid.text(names(dimnames(x)), y = var_offset, just = just_vartext, gp = gp_vartext) } class(pairs_barplot) <- "grapcon_generator" pairs_diagonal_mosaic <- function(split_vertical = TRUE, margins = unit(0, "lines"), offset_labels = -0.4, offset_varnames = 0, gp = NULL, fill = "grey", ...) function(x, i) { if (is.function(fill)) fill <- rev(fill(dim(x)[i])) if (is.null(gp)) gp <- gpar(fill = fill) mosaic(margin.table(x, i), newpage = FALSE, split_vertical = split_vertical, margins = margins, offset_labels = offset_labels, offset_varnames = offset_varnames, prefix = "diag", gp = gp, ...) } class(pairs_diagonal_mosaic) <- "grapcon_generator" vcd/R/co_table.R0000644000175300001440000000161211623033204012763 0ustar meyerusersco_table <- function(x, margin, collapse = ".") { if (!is.array(x)) stop("x is not an array") if("xtabs" %in% class(x)) attr(x, "call") <- NULL dx <- dim(x) idx <- lapply(dx, function(i) 1:i) dn <- dimnames(x) if(is.character(margin)) { if(is.null(dn)) stop("margin must be an index when no dimnames are given") margin <- which(names(dn) %in% margin) } idxm <- expand.grid(idx[margin]) cotab1 <- function(i) { idx[margin] <- lapply(1:length(margin), function(j) idxm[i,j]) rval <- as.table(do.call("[", c(list(x), idx, list(drop = FALSE)))) if(length(dim(rval)) > 1) { dim(rval) <- dim(x)[-margin] dimnames(rval) <- dimnames(x)[-margin] } return(rval) } rval <- lapply(1:NROW(idxm), cotab1) if(!is.null(dn)) names(rval) <- apply(expand.grid(dn[margin]), 1, function(z) paste(z, collapse = collapse)) return(rval) } vcd/R/utils.R0000644000175300001440000000006611150520606012357 0ustar meyerusersremove_trailing_comma <- function(x) sub(",$", "", x) vcd/R/coindep_test.R0000644000175300001440000000576311150520606013710 0ustar meyeruserscoindep_test <- function(x, margin = NULL, n = 1000, indepfun = function(x) max(abs(x)), aggfun = max, alternative = c("greater", "less"), pearson = TRUE) { DNAME <- deparse(substitute(x)) alternative <- match.arg(alternative) if(is.null(margin)) { rs <- rowSums(x) cs <- colSums(x) expctd <- rs %o% cs / sum(rs) Pearson <- function(x) (x - expctd)/sqrt(expctd) resids <- Pearson(x) ff <- if(is.null(aggfun)) { if(pearson) function(x) aggfun(indepfun(Pearson(x))) else function(x) aggfun(indepfun(x)) } else { if(pearson) function(x) indepfun(Pearson(x)) else function(x) indepfun(x) } if(length(dim(x)) > 2) stop("currently only implemented for (conditional) 2d tables") dist <- sapply(r2dtable(n, rowSums(x), colSums(x)), ff) STATISTIC <- ff(x) } else { ff <- if(pearson) function(x) indepfun(Pearson(x)) else function(x) indepfun(x) cox <- co_table(x, margin) nc <- length(cox) if(length(dim(cox[[1]])) > 2) stop("currently only implemented for conditional 2d tables") dist <- matrix(rep(0, n * nc), ncol = nc) for(i in 1:nc) { coxi <- cox[[i]] cs <- colSums(coxi) rs <- rowSums(coxi) expctd <- rs %o% cs / sum(rs) Pearson <- function(x) (x - expctd)/sqrt(expctd) if(any(c(cs, rs) < 1)) warning("structural zeros") ## FIXME dist[, i] <- sapply(r2dtable(n, rs, cs), ff) } dist <- apply(dist, 1, aggfun) Pearson <- function(x) { expctd <- rowSums(x) %o% colSums(x) / sum(x) return((x - expctd)/sqrt(expctd)) } STATISTIC <- aggfun(sapply(cox, ff)) ## just for returning nicely formatted fitted values ## and residuals: fit once more with loglm() vars <- names(dimnames(x)) condvars <- if(is.numeric(margin)) vars[margin] else margin indvars <- vars[!(vars %in% condvars)] coind.form <- as.formula(paste("~ (", paste(indvars, collapse = " + "), ") * ", paste(condvars, collapse = " * "), sep = "")) fm <- loglm(coind.form, data = x, fitted = TRUE) expctd <- fitted(fm) resids <- residuals(fm, type = "pearson") } pdist <- function(x) sapply(x, function(y) mean(dist <= y)) qdist <- function(p) quantile(dist, p) PVAL <- switch(alternative, greater = mean(dist >= STATISTIC), less = mean(dist <= STATISTIC)) METHOD <- "Permutation test for conditional independence" names(STATISTIC) <- "f(x)" rval <- list(statistic = STATISTIC, p.value = PVAL, method = METHOD, data.name = DNAME, observed = x, expected = expctd, residuals = resids, margin = margin, dist = dist, qdist = qdist, pdist = pdist) class(rval) <- c("coindep_test", "htest") return(rval) } fitted.coindep_test <- function(object, ...) object$expected ## plot.coindep_test ## mosaic.coindep_test ## assoc.coindep_test ## difficult, depends on functionals... vcd/R/spine.R0000644000175300001440000001077211150520606012342 0ustar meyerusersspine <- function(x, ...) UseMethod("spine") spine.formula <- function(formula, data = list(), breaks = NULL, ylab_tol = 0.05, off = NULL, main = "", xlab = NULL, ylab = NULL, ylim = c(0, 1), margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "spineplot", newpage = TRUE, pop = TRUE, ...) { ## extract x, y from formula mf <- model.frame(formula, data = data) if(NCOL(mf) != 2) stop("`formula' should specify exactly two variables") y <- mf[,1] if(!is.factor(y)) stop("dependent variable should be a factor") x <- mf[,2] if(is.null(xlab)) xlab <- names(mf)[2] if(is.null(ylab)) ylab <- names(mf)[1] spine(x, y, breaks = breaks, ylab_tol = ylab_tol, off = off, main = main, xlab = xlab, ylab = ylab, ylim = ylim, margins = margins, gp = gp, name = name, newpage = newpage, pop = pop, ...) } spine.default <- function(x, y = NULL, breaks = NULL, ylab_tol = 0.05, off = NULL, main = "", xlab = NULL, ylab = NULL, ylim = c(0, 1), margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "spineplot", newpage = TRUE, pop = TRUE, ...) { ## either supply a 2-way table (i.e., both y and x are categorical) ## or two variables (y has to be categorical - x can be categorical or numerical) if(missing(y)) { if(length(dim(x)) != 2) stop("a 2-way table has to be specified") tab <- x x.categorical <- TRUE if(is.null(xlab)) xlab <- names(dimnames(tab))[1] if(is.null(ylab)) ylab <- names(dimnames(tab))[2] xnam <- dimnames(tab)[[1]] ynam <- dimnames(tab)[[2]] ny <- NCOL(tab) nx <- NROW(tab) } else { if(!is.factor(y)) stop("dependent variable should be a factor") x.categorical <- is.factor(x) if(!x.categorical) stopifnot(is.numeric(x), is.vector(x)) if(is.null(xlab)) xlab <- deparse(substitute(x)) if(is.null(ylab)) ylab <- deparse(substitute(y)) if(x.categorical) { tab <- table(x, y) xnam <- levels(x) nx <- NROW(tab) } ynam <- levels(y) ny <- length(ynam) } ## graphical parameters if(is.null(gp$fill)) gp$fill <- gray.colors(ny) gp$fill <- rep(gp$fill, length.out = ny) off <- if(!x.categorical) 0 else if(is.null(off)) 0.02 else off/100 if(x.categorical) { ## compute rectangle positions on x axis xat <- c(0, cumsum(prop.table(margin.table(tab, 1)) + off)) } else { ## compute breaks for x if(is.null(breaks)) breaks <- list() if(!is.list(breaks)) breaks <- list(breaks = breaks) breaks <- c(list(x = x), breaks) breaks$plot <- FALSE breaks <- do.call("hist", breaks)$breaks ## categorize x x1 <- cut(x, breaks = breaks, include.lowest = TRUE) ## compute rectangle positions on x axis xat <- c(0, cumsum(prop.table(table(x1)))) ## construct table tab <- table(x1, y) nx <- NROW(tab) } ## compute rectangle positions on y axis yat <- rbind(0, apply(prop.table(tab, 1), 1, cumsum)) ## setup plot if(newpage) grid.newpage() pushViewport(plotViewport(xscale = c(0, 1 + off * (nx-1)), yscale = ylim, default.units = "native", name = name, margins = margins, ...)) ## compute coordinates ybottom <- as.vector(yat[-(ny+1),]) ybottom[ybottom < ylim[1]] <- ylim[1] ybottom[ybottom > ylim[2]] <- ylim[2] ytop <- as.vector(yat[-1,]) ytop[ytop < ylim[1]] <- ylim[1] ytop[ytop > ylim[2]] <- ylim[2] xleft <- rep(xat[1:nx], rep(ny, nx)) xright <- rep(xat[2:(nx+1)] - off, rep(ny, nx)) gp$fill <- rep(gp$fill, nx) ## plot rectangles grid.rect(xleft, ybottom, width = (xright-xleft), height = (ytop-ybottom), just = c("left", "bottom"), default.units = "native", gp = gp) ## axes ## 1: either numeric or level names if(x.categorical) grid.text(x = unit((xat[1:nx] + xat[2:(nx+1)] - off)/2, "native"), y = unit(-1.5, "lines"), label = xnam, check.overlap = TRUE) else grid.xaxis(at = xat, label = breaks) ## 2: axis with level names of y yat <- yat[,1] equidist <- any(diff(yat) < ylab_tol) yat <- if(equidist) seq(1/(2*ny), 1-1/(2*ny), by = 1/ny) else (yat[-1] + yat[-length(yat)])/2 grid.text(x = unit(-1.5, "lines"), y = unit(yat, "native"), label = ynam, rot = 90, check.overlap = TRUE) ## 3: none ## 4: simple numeric grid.yaxis(main = FALSE) ## annotation grid.text(xlab, y = unit(-3.5, "lines")) grid.text(ylab, x = unit(-3, "lines"), rot = 90) grid.text(main, y = unit(1, "npc") + unit(2, "lines"), gp = gpar(fontface = "bold")) ## pop if(pop) popViewport() ## return table visualized names(dimnames(tab)) <- c(xlab, ylab) invisible(tab) } vcd/R/grid_legend.R0000644000175300001440000000345611334106150013466 0ustar meyerusersgrid_legend <- function (x, y, pch, col, labels, frame = TRUE, hgap = unit(0.5, "lines"), vgap = unit(0.3, "lines"), default_units = "lines", gp = gpar(), draw = TRUE, title = "Legend:") { labels <- as.character(labels) if (is.logical(title) && !title) title <- NULL if (!is.null(title)) { labels <- c(title, labels) pch <- c(NA, pch) col <- c(NA, col) } nkeys <- length(labels) if (length(pch) != nkeys) stop("pch and labels not the same length") if (!is.unit(hgap)) hgap <- unit(hgap, default_units) if (length(hgap) != 1) stop("hgap must be single unit") if (!is.unit(vgap)) vgap <- unit(vgap, default_units) if (length(vgap) != 1) stop("vgap must be single unit") legend.layout <- grid.layout(nkeys, 3, widths = unit.c(unit(2, "lines"), max(unit(rep(1, nkeys), "strwidth", as.list(labels))), hgap), heights = unit.pmax(unit(1, "lines"), vgap + unit(rep(1, nkeys), "strheight", as.list(labels)))) fg <- frameGrob(layout = legend.layout, gp = gp) for (i in 1:nkeys) { tit <- !is.null(title) && i == 1 if (!tit) fg <- placeGrob(fg, pointsGrob(0.5, 0.5, pch = pch[i], gp = gpar(col = col[i])), col = 1, row = i) fg <- placeGrob(fg, textGrob(labels[i], x = 0 + 0.3 * tit, y = 0.5, just = c("left", "center")), col = 2 - tit, row = i) } pushViewport(viewport(x, y, height = unit(nkeys, "lines"), width = grobWidth(fg))) if (frame) fg <- placeGrob(fg, rectGrob(gp = gpar(fill = "transparent"))) if (draw) grid.draw(fg) popViewport(1) invisible(fg) } vcd/R/fourfold.R0000644000175300001440000003616711720271155013057 0ustar meyerusers## Modifications - MF - 1 Dec 2010 # -- change default colors to more distinguishable values # -- allow to work with >3 dimensional arrays # -- modified defaults for mfrow/mfcol to give landscape display, nr <= nc, rather than nr >= nc # Take a 2+D array and return a 3D array, with dimensions 3+ as a single dimension # Include as a separate function, since it is useful in other contexts array3d <- function(x, sep=':') { if(length(dim(x)) == 2) { x <- if(is.null(dimnames(x))) array(x, c(dim(x), 1)) else array(x, c(dim(x), 1), c(dimnames(x), list(NULL))) return(x) } else if(length(dim(x))==3) return(x) else { x3d <- array(x, c(dim(x)[1:2], prod(dim(x)[-(1:2)]))) if (!is.null(dimnames(x))) { n3d <- paste(names(dimnames(x))[-(1:2)], collapse=sep) d3d <- apply(expand.grid(dimnames(x)[-(1:2)]), 1, paste, collapse=sep) dimnames(x3d) <- c(dimnames(x)[1:2], list(d3d)) names(dimnames(x3d))[3] <- n3d } return(x3d) } } "fourfold" <- function(x, # color = c("#99CCFF","#6699CC","#FF5050","#6060A0", "#FF0000", "#000080"), color = c("#99CCFF","#6699CC","#FFA0A0","#A0A0FF", "#FF0000", "#000080"), conf_level = 0.95, std = c("margins", "ind.max", "all.max"), margin = c(1, 2), space = 0.2, main = NULL, sub = NULL, mfrow = NULL, mfcol = NULL, extended = TRUE, ticks = 0.15, p_adjust_method = p.adjust.methods, newpage = TRUE, fontsize = 12) { ## Code for producing fourfold displays. ## Reference: ## Friendly, M. (1994). ## A fourfold display for 2 by 2 by \eqn{k} tables. ## Technical Report 217, York University, Psychology Department. ## http://datavis.ca/papers/4fold/4fold.pdf ## ## Implementation notes: ## ## We need plots with aspect ratio FIXED to 1 and glued together. ## Hence, even if k > 1 we prefer keeping everything in one plot ## region rather than using a multiple figure layout. ## Each 2 by 2 pie is is drawn into a square with x/y coordinates ## between -1 and 1, with row and column labels in [-1-space, -1] ## and [1, 1+space], respectively. If k > 1, strata labels are in ## an area with y coordinates in [1+space, 1+(1+gamma)*space], ## where currently gamma=1.25. The pies are arranged in an nr by ## nc layout, with horizontal and vertical distances between them ## set to space. ## ## The drawing code first computes the complete are of the form ## [0, totalWidth] x [0, totalHeight] ## needed and sets the world coordinates using plot.window(). ## Then, the strata are looped over, and the corresponding pies ## added by filling rows or columns of the layout as specified by ## the mfrow or mfcol arguments. The world coordinates are reset ## in each step by shifting the origin so that we can always plot ## as detailed above. if(!is.array(x)) stop("x must be an array") dimx <- dim(x) # save original dimensions for setting default mfrow/mfcol when length(dim(x))>3 x <- array3d(x) if(any(dim(x)[1:2] != 2)) stop("table for each stratum must be 2 by 2") dnx <- dimnames(x) if(is.null(dnx)) dnx <- vector("list", 3) for(i in which(sapply(dnx, is.null))) dnx[[i]] <- LETTERS[seq(length = dim(x)[i])] if(is.null(names(dnx))) i <- 1 : 3 else i <- which(is.null(names(dnx))) if(any(i > 0)) names(dnx)[i] <- c("Row", "Col", "Strata")[i] dimnames(x) <- dnx k <- dim(x)[3] if(!((length(conf_level) == 1) && is.finite(conf_level) && (conf_level >= 0) && (conf_level < 1))) stop("conf_level must be a single number between 0 and 1") if(conf_level == 0) conf_level <- FALSE std <- match.arg(std) findTableWithOAM <- function(or, tab) { ## Find a 2x2 table with given odds ratio `or' and the margins ## of a given 2x2 table `tab'. m <- rowSums(tab)[1] n <- rowSums(tab)[2] t <- colSums(tab)[1] if(or == 1) x <- t * n / (m + n) else if(or == Inf) x <- max(0, t - m) else { A <- or - 1 B <- or * (m - t) + (n + t) C <- - t * n x <- (- B + sqrt(B ^ 2 - 4 * A * C)) / (2 * A) } matrix(c(t - x, x, m - t + x, n - x), nrow = 2) } drawPie <- function(r, from, to, n = 500, color = "transparent") { p <- 2 * pi * seq(from, to, length = n) / 360 x <- c(cos(p), 0) * r y <- c(sin(p), 0) * r grid.polygon(x, y, gp = gpar(fill = color), default.units = "native") invisible(NULL) } stdize <- function(tab, std, x) { ## Standardize the 2 x 2 table `tab'. if(std == "margins") { if(all(sort(margin) == c(1, 2))) { ## standardize to equal row and col margins u <- sqrt(odds(tab)$or) u <- u / (1 + u) y <- matrix(c(u, 1 - u, 1 - u, u), nrow = 2) } else if(margin %in% c(1, 2)) y <- prop.table(tab, margin) else stop("incorrect margin specification") } else if(std == "ind.max") y <- tab / max(tab) else if(std == "all.max") y <- tab / max(x) y } odds <- function(x) { ## Given a 2 x 2 or 2 x 2 x k table `x', return a list with ## components `or' and `se' giving the odds ratios and standard ## deviations of the log odds ratios. if(length(dim(x)) == 2) { dim(x) <- c(dim(x), 1) k <- 1 } else k <- dim(x)[3] or <- double(k) se <- double(k) for(i in 1 : k) { f <- x[ , , i] if(any(f == 0)) f <- f + 0.5 or[i] <- (f[1, 1] * f[2, 2]) / (f[1, 2] * f[2, 1]) se[i] <- sqrt(sum(1 / f)) } list(or = or, se = se) } gamma <- 1.25 # Scale factor for strata labels angle.f <- c( 90, 180, 0, 270) # `f' for `from' angle.t <- c(180, 270, 90, 360) # `t' for `to' byrow <- FALSE if(!is.null(mfrow)) { nr <- mfrow[1] nc <- mfrow[2] } else if(!is.null(mfcol)) { nr <- mfcol[1] nc <- mfcol[2] byrow <- TRUE } else if(length(dimx)>3) { nr <- dimx[3] nc <- prod(dimx[-(1:3)]) } else { # nr <- ceiling(sqrt(k)) nr <- round(sqrt(k)) nc <- ceiling(k / nr) } if(nr * nc < k) stop("incorrect geometry specification") if(byrow) indexMatrix <- expand.grid(1 : nc, 1 : nr)[, c(2, 1)] else indexMatrix <- expand.grid(1 : nr, 1 : nc) totalWidth <- nc * 2 * (1 + space) + (nc - 1) * space totalHeight <- if(k == 1) 2 * (1 + space) else nr * (2 + (2 + gamma) * space) + (nr - 1) * space xlim <- c(0, totalWidth) ylim <- c(0, totalHeight) if (newpage) grid.newpage() if (!is.null(main) || !is.null(sub)) pushViewport(viewport(height = 1 - 0.1 * sum(!is.null(main), !is.null(sub)), width = 0.9, y = 0.5 - 0.05 * sum(!is.null(main), - !is.null(sub)) ) ) pushViewport(viewport(xscale = xlim, yscale = ylim, width = unit(min(totalWidth / totalHeight, 1), "snpc"), height = unit(min(totalHeight / totalWidth, 1), "snpc"))) o <- odds(x) ## perform logoddsratio-test for each stratum (H0: lor = 0) and adjust p-values if(is.numeric(conf_level) && extended) p.lor.test <- p.adjust(sapply(1 : k, function(i) { u <- abs(log(o$or[i])) / o$se[i] 2 * (1 - pnorm(u)) }), method = p_adjust_method ) scale <- space / (2 * convertY(unit(1, "strheight", "Ag"), "native", valueOnly = TRUE) ) v <- 0.95 - max(convertX(unit(1, "strwidth", as.character(c(x))), "native", valueOnly = TRUE) ) / 2 fontsize = fontsize * scale for(i in 1 : k) { tab <- x[ , , i] fit <- stdize(tab, std, x) xInd <- indexMatrix[i, 2] xOrig <- 2 * xInd - 1 + (3 * xInd - 2) * space yInd <- indexMatrix[i, 1] yOrig <- if(k == 1) (1 + space) else (totalHeight - (2 * yInd - 1 + ((3 + gamma) * yInd - 2) * space)) pushViewport(viewport(xscale = xlim - xOrig, yscale = ylim - yOrig)) ## drawLabels() u <- 1 + space / 2 adjCorr <- 0.2 grid.text( paste(names(dimnames(x))[1], dimnames(x)[[1]][1], sep = ": "), 0, u, gp = gpar(fontsize = fontsize), default.units = "native" ) grid.text( paste(names(dimnames(x))[2], dimnames(x)[[2]][1], sep = ": "), -u, 0, default.units = "native", gp = gpar(fontsize = fontsize), rot = 90) grid.text( paste(names(dimnames(x))[1], dimnames(x)[[1]][2], sep = ": "), 0, -u, gp = gpar(fontsize = fontsize), default.units = "native" ) grid.text( paste(names(dimnames(x))[2], dimnames(x)[[2]][2], sep = ": "), u, 0, default.units = "native", gp = gpar(fontsize = fontsize), rot = 90) if (k > 1) { grid.text( paste(names(dimnames(x))[3], dimnames(x)[[3]][i], sep = ": "), 0, 1 + (1 + gamma / 2) * space, gp = gpar(fontsize = fontsize * gamma), default.units = "native" ) } ## drawFrequencies() ### in extended plots, emphasize charts with significant logoddsratios emphasize <- if(extended && is.numeric(conf_level)) 2 * extended * (1 + (p.lor.test[i] < 1 - conf_level)) else 0 d <- odds(tab)$or drawPie(sqrt(fit[1,1]), 90, 180, col = color[1 + (d > 1) + emphasize]) drawPie(sqrt(fit[2,1]), 180, 270, col = color[2 - (d > 1) + emphasize]) drawPie(sqrt(fit[1,2]), 0, 90, col = color[2 - (d > 1) + emphasize]) drawPie(sqrt(fit[2,2]), 270, 360, col = color[1 + (d > 1) + emphasize]) u <- 1 - space / 2 grid.text(as.character(c(tab))[1], -v, u, just = c("left", "top"), gp = gpar(fontsize = fontsize), default.units = "native") grid.text(as.character(c(tab))[2], -v, -u, just = c("left", "bottom"), gp = gpar(fontsize = fontsize), default.units = "native") grid.text(as.character(c(tab))[3], v, u, just = c("right", "top"), gp = gpar(fontsize = fontsize), default.units = "native") grid.text(as.character(c(tab))[4], v, -u, just = c("right", "bottom"), gp = gpar(fontsize = fontsize), default.units = "native") ## draw ticks if(extended && ticks) if(d > 1) { grid.lines(c(sqrt(fit[1,1]) * cos(3*pi/4), (sqrt(fit[1,1]) + ticks) * cos(3*pi/4)), c(sqrt(fit[1,1]) * sin(3*pi/4), (sqrt(fit[1,1]) + ticks) * sin(3*pi/4)), gp = gpar(lwd = 1), default.units = "native" ) grid.lines(c(sqrt(fit[2,2]) * cos(-pi/4), (sqrt(fit[2,2]) + ticks) * cos(-pi/4)), c(sqrt(fit[2,2]) * sin(-pi/4), (sqrt(fit[2,2]) + ticks) * sin(-pi/4)), gp = gpar(lwd = 1), default.units = "native" ) } else { grid.lines(c(sqrt(fit[1,2]) * cos(pi/4), (sqrt(fit[1,2]) + ticks) * cos(pi/4)), c(sqrt(fit[1,2]) * sin(pi/4), (sqrt(fit[1,2]) + ticks) * sin(pi/4)), gp = gpar(lwd = 1), default.units = "native" ) grid.lines(c(sqrt(fit[2,1]) * cos(-3*pi/4), (sqrt(fit[2,1]) + ticks) * cos(-3*pi/4)), c(sqrt(fit[2,1]) * sin(-3*pi/4), (sqrt(fit[2,1]) + ticks) * sin(-3*pi/4)), gp = gpar(lwd = 1), default.units = "native" ) } ## drawConfBands() if(is.numeric(conf_level)) { or <- o$or[i] se <- o$se[i] ## lower theta <- or * exp(qnorm((1 - conf_level) / 2) * se) tau <- findTableWithOAM(theta, tab) r <- sqrt(c(stdize(tau, std, x))) for(j in 1 : 4) drawPie(r[j], angle.f[j], angle.t[j]) ## upper theta <- or * exp(qnorm((1 + conf_level) / 2) * se) tau <- findTableWithOAM(theta, tab) r <- sqrt(c(stdize(tau, std, x))) for(j in 1 : 4) drawPie(r[j], angle.f[j], angle.t[j]) } ## drawBoxes() grid.polygon(c(-1, 1, 1, -1), c(-1, -1, 1, 1), default.units = "native", gp = gpar(fill = "transparent") ) grid.lines(c(-1, 1), c(0, 0), default.units = "native") for(j in seq(from = -0.8, to = 0.8, by = 0.2)) grid.lines(c(j, j), c(-0.02, 0.02), default.units = "native") for(j in seq(from = -0.9, to = 0.9, by = 0.2)) grid.lines(c(j, j), c(-0.01, 0.01), default.units = "native") grid.lines(c(0, 0), c(-1, 1), default.units = "native") for(j in seq(from = -0.8, to = 0.8, by = 0.2)) grid.lines(c(-0.02, 0.02), c(j, j), default.units = "native") for(j in seq(from = -0.9, to = 0.9, by = 0.2)) grid.lines(c(-0.01, 0.01), c(j, j), default.units = "native") popViewport(1) } if(!is.null(main) || !is.null(sub)) { if (!is.null(main)) grid.text(main, y = unit(1, "npc") + unit(1, "lines"), gp = gpar(fontsize = 20, fontface = 2)) if (!is.null(sub)) grid.text(sub, y = unit(0, "npc") - unit(1, "lines"), gp = gpar(fontsize = 20, fontface = 2)) popViewport(1) } popViewport(1) return(invisible()) } vcd/R/ternaryplot.R0000644000175300001440000001074011437031441013604 0ustar meyerusers"ternaryplot" <- function (x, scale = 1, dimnames = NULL, dimnames_position = c("corner", "edge", "none"), dimnames_color = "black", id = NULL, id_color = "black", id_just = c("center", "center"), coordinates = FALSE, grid = TRUE, grid_color = "gray", labels = c("inside", "outside", "none"), labels_color = "darkgray", border = "black", bg = "white", pch = 19, cex = 1, prop_size = FALSE, col = "red", main = "ternary plot", newpage = TRUE, pop = TRUE, ...) { ## parameter handling labels <- match.arg(labels) if (grid == TRUE) grid <- "dotted" if (coordinates) id <- paste("(",round(x[,1] * scale, 1),",", round(x[,2] * scale, 1),",", round(x[,3] * scale, 1),")", sep="") dimnames_position <- match.arg(dimnames_position) if(is.null(dimnames) && dimnames_position != "none") dimnames <- colnames(x) if(is.logical(prop_size) && prop_size) prop_size <- 3 ## some error handling if(ncol(x) != 3) stop("Need a matrix with 3 columns") if(any(x < 0)) stop("X must be non-negative") s <- rowSums(x) if(any(s <= 0)) stop("each row of X must have a positive sum") ## rescaling x <- x / s ## prepare plot top <- sqrt(3) / 2 if (newpage) grid.newpage() xlim <- c(-0.03, 1.03) ylim <- c(-1, top) pushViewport(viewport(width = unit(1, "snpc"))) if (!is.null(main)) grid.text(main, y = 0.9, gp = gpar(fontsize = 18, fontstyle = 1)) pushViewport(viewport(width = 0.8, height = 0.8, xscale = xlim, yscale = ylim, name = "plot")) eps <- 0.01 ## coordinates of point P(a,b,c): xp = b + c/2, yp = c * sqrt(3)/2 ## triangle grid.polygon(c(0, 0.5, 1), c(0, top, 0), gp = gpar(fill = bg, col = border), ...) ## title, labeling if (dimnames_position == "corner") { grid.text(x = c(0, 1, 0.5), y = c(-0.02, -0.02, top + 0.02), label = dimnames, gp = gpar(fontsize = 12)) } if (dimnames_position == "edge") { shift <- eps * if (labels == "outside") 8 else 0 grid.text(x = 0.25 - 2 * eps - shift, y = 0.5 * top + shift, label = dimnames[2], rot = 60, gp = gpar(col = dimnames_color)) grid.text(x = 0.75 + 3 * eps + shift, y = 0.5 * top + shift, label = dimnames[1], rot = -60, gp = gpar(col = dimnames_color)) grid.text(x = 0.5, y = -0.02 - shift, label = dimnames[3], gp = gpar(col = dimnames_color)) } ## grid if (is.character(grid)) for (i in 1:4 * 0.2) { ## a - axis grid.lines(c(1 - i , (1 - i) / 2), c(0, 1 - i) * top, gp = gpar(lty = grid, col = grid_color)) ## b - axis grid.lines(c(1 - i , 1 - i + i / 2), c(0, i) * top, gp = gpar(lty = grid, col = grid_color)) ## c - axis grid.lines(c(i / 2, 1 - i + i/2), c(i, i) * top, gp = gpar(lty = grid, col = grid_color)) ## grid labels if (labels == "inside") { grid.text(x = (1 - i) * 3 / 4 - eps, y = (1 - i) / 2 * top, label = i * scale, gp = gpar(col = labels_color), rot = 120) grid.text(x = 1 - i + i / 4 + eps, y = i / 2 * top - eps, label = (1 - i) * scale, gp = gpar(col = labels_color), rot = -120) grid.text(x = 0.5, y = i * top + eps, label = i * scale, gp = gpar(col = labels_color)) } if (labels == "outside") { grid.text(x = (1 - i) / 2 - 6 * eps, y = (1 - i) * top, label = (1 - i) * scale, gp = gpar(col = labels_color)) grid.text(x = 1 - (1 - i) / 2 + 3 * eps, y = (1 - i) * top + 5 * eps, label = i * scale, rot = -120, gp = gpar(col = labels_color)) grid.text(x = i + eps, y = -0.05, label = (1 - i) * scale, vjust = 1, rot = 120, gp = gpar(col = labels_color)) } } ## plot points xp <- x[,2] + x[,3] / 2 yp <- x[,3] * top size = unit(if(prop_size) prop_size * (s / max(s)) else cex, "lines") grid.points(xp, yp, pch = pch, gp = gpar(col = col), default.units = "snpc", size = size, ...) ## plot if (!is.null(id)) grid.text(x = xp, y = unit(yp - 0.015, "snpc") - 0.5 * size, label = as.character(id), just = id_just, gp = gpar(col = id_color, cex = cex)) ## cleanup if(pop) popViewport(2) else upViewport(2) } vcd/R/assocstats.R0000644000175300001440000000240511566471033013417 0ustar meyerusersassocstats <- function(x) { if(!is.matrix(x)) stop("Function only defined for 2-way tables.") tab <- summary(loglm(~1+2, x))$tests phi <- sqrt(tab[2,1] / sum(x)) cont <- sqrt(phi^2 / (1 + phi^2)) cramer <- sqrt(phi^2 / min(dim(x) - 1)) structure( list(table = x, chisq_tests = tab, phi = phi, contingency = cont, cramer = cramer), class = "assocstats" ) } print.assocstats <- function(x, digits = 3, ...) { print(x$chisq_tests, digits = 5, ...) cat("\n") cat("Phi-Coefficient :", round(x$phi, digits = digits), "\n") cat("Contingency Coeff.:", round(x$cont, digits = digits), "\n") cat("Cramer's V :", round(x$cramer, digits = digits), "\n") invisible(x) } summary.assocstats <- function(object, percentage = FALSE, ...) { tab <- summary(object$table, percentage = percentage, ...) tab$chisq <- NULL structure(list(summary = tab, object = object), class = "summary.assocstats" ) } print.summary.assocstats <- function(x, ...) { cat("\n") print(x$summary, ...) print(x$object, ...) cat("\n") invisible(x) } vcd/R/cd_plot.R0000644000175300001440000000666011566471033012663 0ustar meyeruserscd_plot <- function(x, ...) { UseMethod("cd_plot") } cd_plot.formula <- function(formula, data = list(), plot = TRUE, ylab_tol = 0.05, bw = "nrd0", n = 512, from = NULL, to = NULL, main = "", xlab = NULL, ylab = NULL, margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "cd_plot", newpage = TRUE, pop = TRUE, ...) { ## extract x, y from formula mf <- model.frame(formula, data = data) if(NCOL(mf) != 2) stop("`formula' should specify exactly two variables") y <- mf[,1] if(!is.factor(y)) stop("dependent variable should be a factor") x <- mf[,2] if(!is.numeric(x)) stop("explanatory variable should be numeric") ## graphical parameters if(is.null(xlab)) xlab <- names(mf)[2] if(is.null(ylab)) ylab <- names(mf)[1] ## call default interface cd_plot(x, y, plot = plot, ylab_tol = ylab_tol, bw = bw, n = n, from = from, to = to, main = main, xlab = xlab, ylab = ylab, margins = margins, gp = gp, name = name, newpage = newpage, pop = pop, ...) } cd_plot.default <- function(x, y, plot = TRUE, ylab_tol = 0.05, bw = "nrd0", n = 512, from = NULL, to = NULL, main = "", xlab = NULL, ylab = NULL, margins = c(5.1, 4.1, 4.1, 3.1), gp = gpar(), name = "cd_plot", newpage = TRUE, pop = TRUE, ...) { ## check x and y if(!is.numeric(x)) stop("explanatory variable should be numeric") if(!is.factor(y)) stop("dependent variable should be a factor") ny <- length(levels(y)) ## graphical parameters if(is.null(xlab)) xlab <- deparse(substitute(x)) if(is.null(ylab)) ylab <- deparse(substitute(y)) if(is.null(gp$fill)) gp$fill <- gray.colors(ny) gp$fill <- rep(gp$fill, length.out = ny) ## unconditional density of x dx <- if(is.null(from) & is.null(to)) density(x, bw = bw, n = n, ...) else density(x, bw = bw, from = from, to = to, n = n, ...) x1 <- dx$x ## setup conditional values yprop <- cumsum(prop.table(table(y))) y1 <- matrix(rep(0, n*(ny-1)), nrow = (ny-1)) ## setup return value rval <- list() for(i in 1:(ny-1)) { dxi <- density(x[y %in% levels(y)[1:i]], bw = dx$bw, n = n, from = min(dx$x), to = max(dx$x), ...) y1[i,] <- dxi$y/dx$y * yprop[i] rval[[i]] <- approxfun(x1, y1[i,], rule = 2) } names(rval) <- levels(y)[1:(ny-1)] ## use known ranges y1 <- rbind(0, y1, 1) y1 <- y1[,which(x1 >= min(x) & x1 <= max(x))] x1 <- x1[x1 >= min(x) & x1 <= max(x)] ## plot polygons if(plot) { ## setup if(newpage) grid.newpage() pushViewport(plotViewport(xscale = range(x1), yscale = c(0, 1), default.units = "native", name = name, margins = margins, ...)) ## polygons for(i in 1:(NROW(y1)-1)) { gpi <- gp gpi$fill <- gp$fill[i] grid.polygon(x = c(x1, rev(x1)), y = c(y1[i+1,], rev(y1[i,])), default.units = "native", gp = gpi) } ## axes grid.rect(gp = gpar(fill = "transparent")) grid.xaxis() grid.yaxis(main = FALSE) equidist <- any(diff(y1[,1]) < ylab_tol) yat <- if(equidist) seq(1/(2*ny), 1-1/(2*ny), by = 1/ny) else (y1[-1,1] + y1[-NROW(y1), 1])/2 grid.text(x = unit(-1.5, "lines"), y = unit(yat, "native"), label = levels(y), rot = 90, check.overlap = TRUE) ## annotation grid.text(xlab, y = unit(-3.5, "lines")) grid.text(ylab, x = unit(-3, "lines"), rot = 90) grid.text(main, y = unit(1, "npc") + unit(2, "lines"), gp = gpar(fontface = "bold")) ## pop if(pop) popViewport() } ## return conditional density functions invisible(rval) } vcd/R/oddsratioplot.R0000644000175300001440000001015711566471033014122 0ustar meyerusers"oddsratio" <- function (x, stratum = NULL, log = TRUE) { l <- length(dim(x)) if (l > 2 && is.null(stratum)) stratum <- 3:l if (l - length(stratum) > 2) stop("All but 2 dimensions must be specified as strata.") if (l == 2 && dim(x) != c(2, 2)) stop("Not a 2x2 table.") if (!is.null(stratum) && dim(x)[-stratum] != c(2,2)) stop("Need strata of 2x2 tables.") lor <- function (y) { if (any(y == 0)) y <- y + 0.5 y <- log(y) or <- y[1,1] + y[2,2] - y[1,2] - y[2,1] if (log) or else exp(or) } ase <- function(y) sqrt(sum(1/(y + 0.5))) if(is.null(stratum)) { LOR <- lor(x) ASE <- ase(x) } else { LOR <- apply(x, stratum, lor) ASE <- apply(x, stratum, ase) } structure(LOR, ASE = ASE, log = log, class = "oddsratio" )} "print.oddsratio" <- function(x, ...) { if (length(dim(x)) > 1) print(cbind(unclass(x)), ...) else print(c(x), ...) invisible(x) } "summary.oddsratio" <- function(object, ...) { if(!is.null(dim(object))) ret <- object else { LOG <- attr(object, "log") ASE <- attr(object, "ASE") Z <- object / ASE ret <- cbind("Estimate" = object, "Std. Error" = if (LOG) ASE, "z value" = if (LOG) Z, "Pr(>|z|)" = if (LOG) 1 - pnorm(abs(Z)) ) colnames(ret)[1] <- if (LOG) "Log Odds Ratio" else "Odds Ratio" } class(ret) <- "summary.oddsratio" ret } "print.summary.oddsratio" <- function(x, ...) { if(!is.null(attr(x, "log"))) { cat("\n") cat(if(attr(x, "log")) "Log Odds Ratio(s):" else "Odds Ratio(s):", "\n\n") print(as.data.frame(unclass(x)), ...) cat("\nAsymptotic Standard Error(s):\n\n") print(attr(x, "ASE"), ...) cat("\n") } else printCoefmat(unclass(x), ...) invisible(x) } "plot.oddsratio" <- function(x, conf_level = 0.95, type = "o", xlab = NULL, ylab = NULL, xlim = NULL, ylim = NULL, whiskers = 0.1, baseline = TRUE, transpose = FALSE, ...) { if (length(dim(x)) > 1) stop ("Plot function works only on vectors.") LOG <- attr(x, "log") confidence <- !(is.null(conf_level) || conf_level == FALSE) oddsrange <- range(x) if(confidence) { CI <- confint(x, level = conf_level) lwr <- CI[,1] upr <- CI[,2] oddsrange[1] <- trunc(min(oddsrange[1], min(lwr))) oddsrange[2] <- ceiling(max(oddsrange[2], max(upr))) } if (transpose) { plot(x = unclass(x), y = 1:length(x), ylab = if (!is.null(ylab)) ylab else "Strata", xlab = if (!is.null(xlab)) xlab else if (LOG) "Log Odds Ratio" else "Odds Ratio", type = type, yaxt = "n", xlim = if(is.null(xlim)) oddsrange else xlim, ...) axis (2, at = 1:length(x), names(x)) if (baseline) lines(c(1,1) - LOG, c(0,length(x) + 1), lty = 2, col = "red") if (confidence) for (i in 1:length(x)) { lines(c(lwr[i], upr[i]), c(i, i)) lines(c(lwr[i], lwr[i]), c(i - whiskers/2, i + whiskers/2)) lines(c(upr[i], upr[i]), c(i - whiskers/2, i + whiskers/2)) } } else { plot(unclass(x), xlab = if (!is.null(xlab)) xlab else "Strata", ylab = if(!is.null(ylab)) ylab else if(LOG) "Log Odds Ratio" else "Odds Ratio", type = type, xaxt = "n", ylim = if(is.null(ylim)) oddsrange else ylim, ...) axis (1, at = 1:length(x), names(x)) if (baseline) lines(c(0,length(x) + 1), c(1,1) - LOG, lty = 2, col = "red") if (confidence) for (i in 1:length(x)) { lines(c(i, i), c(lwr[i], upr[i])) lines(c(i - whiskers/2, i + whiskers/2), c(lwr[i], lwr[i])) lines(c(i - whiskers/2, i + whiskers/2), c(upr[i], upr[i])) } } } "confint.oddsratio" <- function(object, parm, level = 0.95, ...) { ASE <- attr(object, "ASE") LOG <- attr(object, "log") I <- ASE * qnorm((1 + level) / 2) cbind( lwr = if (LOG) object - I else exp(log(object) - I), upr = if (LOG) object + I else exp(log(object) + I) ) } vcd/R/strucplot.R0000644000175300001440000002722711566471033013300 0ustar meyerusers################################################################ ### strucplot - generic plot framework for mosaic-like layouts ### 2 core functions are provided: struc_mosaic and struc_assoc ################################################################ strucplot <- function(## main parameters x, residuals = NULL, expected = NULL, condvars = NULL, shade = NULL, type = c("observed", "expected"), residuals_type = NULL, df = NULL, ## layout split_vertical = NULL, spacing = spacing_equal, spacing_args = list(), gp = NULL, gp_args = list(), labeling = labeling_border, labeling_args = list(), core = struc_mosaic, core_args = list(), legend = NULL, legend_args = list(), main = NULL, sub = NULL, margins = unit(3, "lines"), title_margins = NULL, legend_width = NULL, ## control parameters main_gp = gpar(fontsize = 20), sub_gp = gpar(fontsize = 15), newpage = TRUE, pop = TRUE, keep_aspect_ratio = NULL, prefix = "", ... ) { ## default behaviour of shade if (is.null(shade)) shade <- !is.null(gp) || !is.null(expected) type <- match.arg(type) if (is.null(residuals)) { residuals_type <- if (is.null(residuals_type)) "pearson" else match.arg(tolower(residuals_type), c("pearson", "deviance", "ft")) } else { if (is.null(residuals_type)) residuals_type <- "" } ## convert structable object if (is.structable(x)) { if (is.null(split_vertical)) split_vertical <- attr(x, "split_vertical") x <- as.table(x) } if (is.null(split_vertical)) split_vertical <- FALSE ## table characteristics d <- dim(x) dl <- length(d) dn <- dimnames(x) if (is.null(dn)) dn <- dimnames(x) <- lapply(d, seq) dnn <- names(dimnames(x)) if (is.null(dnn)) dnn <- names(dn) <- names(dimnames(x)) <- LETTERS[1:dl] ## replace NAs by 0 if (any(nas <- is.na(x))) x[nas] <- 0 ## model fitting: ## calculate df and expected if needed ## (used for inference in some shading (generating) functions). ## note: will *not* be calculated if residuals are given if ((is.null(expected) && is.null(residuals)) || !is.numeric(expected)) { if (!is.null(df)) warning("Using calculated degrees of freedom.") if (inherits(expected, "formula")) { fm <- loglm(expected, x, fitted = TRUE) expected <- fitted(fm) df <- fm$df } else { if (is.null(expected)) expected <- if (is.null(condvars)) as.list(1:dl) else lapply((condvars + 1):dl, c, seq(condvars)) fm <- loglin(x, expected, fit = TRUE, print = FALSE) expected <- fm$fit df <- fm$df } } ## compute residuals if (is.null(residuals)) residuals <- switch(residuals_type, pearson = (x - expected) / sqrt(ifelse(expected > 0, expected, 1)), deviance = { tmp <- 2 * (x * log(ifelse(x == 0, 1, x / ifelse(expected > 0, expected, 1))) - (x - expected)) tmp <- sqrt(pmax(tmp, 0)) ifelse(x > expected, tmp, -tmp) }, ft = sqrt(x) + sqrt(x + 1) - sqrt(4 * expected + 1) ) ## replace NAs by 0 if (any(nas <- is.na(residuals))) residuals[nas] <- 0 ## splitting if (length(split_vertical) == 1) split_vertical <- rep(c(split_vertical, !split_vertical), length.out = dl) if (is.null(keep_aspect_ratio)) keep_aspect_ratio <- dl < 3 ## spacing if (is.function(spacing)) { if (inherits(spacing, "grapcon_generator")) spacing <- do.call("spacing", spacing_args) spacing <- spacing(d, condvars) } ## gp (color, fill, lty, etc.) argument if (shade) { if (is.null(gp)) gp <- shading_hcl if (is.function(gp)) { if (is.null(legend) || (is.logical(legend) && legend)) legend <- legend_resbased gpfun <- if (inherits(gp, "grapcon_generator")) do.call("gp", c(list(x, residuals, expected, df), as.list(gp_args))) else gp gp <- gpfun(residuals) } else if (!is.null(legend) && !(is.logical(legend) && !legend)) stop("gp argument must be a shading function for drawing a legend") } else { if(!is.null(gp)) { warning("gp parameter ignored since shade = FALSE") gp <- NULL } } ## choose gray when no shading is used if (is.null(gp)) gp <- gpar(fill = grey(0.8)) ## recycle gpar values in the last dimension size <- prod(d) FUN <- function(par) { if (is.structable(par)) par <- as.table(par) if (length(par) < size) aperm(array(par, dim = rev(d))) else par } gp <- structure(lapply(gp, FUN), class = "gpar") ## set up page if (newpage) grid.newpage() if (keep_aspect_ratio) pushViewport(viewport(width = 1, height = 1, default.units = "snpc")) pushViewport(vcdViewport(mar = margins, oma = title_margins, legend = shade && !(is.null(legend) || is.logical(legend) && !legend), main = !is.null(main), sub = !is.null(sub), keep_aspect_ratio = keep_aspect_ratio, legend_width = legend_width, prefix = prefix)) ## legend if (inherits(legend, "grapcon_generator")) legend <- do.call("legend", legend_args) if (shade && !is.null(legend) && !(is.logical(legend) && !legend)) { seekViewport(paste(prefix, "legend", sep = "")) residuals_type <- switch(residuals_type, deviance = "deviance\nresiduals:", ft = "Freeman-Tukey\nresiduals:", pearson = "Pearson\nresiduals:", residuals_type) legend(residuals, gpfun, residuals_type) } ## titles if (!is.null(main)) { seekViewport(paste(prefix, "main", sep = "")) if (is.logical(main) && main) main <- deparse(substitute(x)) grid.text(main, gp = main_gp) } if (!is.null(sub)) { seekViewport(paste(prefix, "sub", sep = "")) if (is.logical(sub) && sub && is.null(main)) sub <- deparse(substitute(x)) grid.text(sub, gp = sub_gp) } ## make plot seekViewport(paste(prefix, "plot", sep = "")) if (inherits(core, "grapcon_generator")) core <- do.call("core", core_args) core(residuals = residuals, observed = if (type == "observed") x else expected, expected = if (type == "observed") expected else x, spacing = spacing, gp = gp, split_vertical = split_vertical, prefix = prefix) upViewport(1) ## labels if (is.logical(labeling)) labeling <- if (labeling) labeling_border else NULL if (!is.null(labeling)) { if (inherits(labeling, "grapcon_generator")) labeling <- do.call("labeling", c(labeling_args, list(...))) labeling(dn, split_vertical, condvars, prefix) } ## pop/move up viewport seekViewport(paste(prefix, "base", sep = "")) ## one more up if sandwich-mode if (pop) popViewport(1 + keep_aspect_ratio) else upViewport(1 + keep_aspect_ratio) ## return visualized table invisible(structable(if (type == "observed") x else expected, split_vertical = split_vertical)) } vcdViewport <- function(mar = rep.int(2.5, 4), legend_width = unit(5, "lines"), oma = NULL, legend = FALSE, main = FALSE, sub = FALSE, keep_aspect_ratio = TRUE, prefix = "") { ## process parameters if (is.null(legend_width)) legend_width <- unit(5 * legend, "lines") if (!is.unit(legend_width)) legend_width <- unit(legend_width, "lines") if (legend && !main && !sub && keep_aspect_ratio) main <- sub <- TRUE mar <- if (!is.unit(mar)) unit(pexpand(mar, 4, rep.int(2.5, 4), c("top","right","bottom","left")), "lines") else rep(mar, length.out = 4) if (is.null(oma)) { space <- if (legend && keep_aspect_ratio) legend_width + mar[2] + mar[4] - mar[1] - mar[3] else unit(0, "lines") oma <- if (main && sub) max(unit(2, "lines"), 0.5 * space) else if (main) unit.c(max(unit(2, "lines"), space), unit(0, "lines")) else if (sub) unit.c(unit(0, "lines"), max(unit(2, "lines"), space)) else 0.5 * space } oma <- if (!is.unit(oma)) unit(pexpand(oma, 2, rep.int(2, 2), c("top","bottom")), "lines") else rep(oma, length.out = 2) ## set up viewports vpPlot <- vpStack(viewport(layout.pos.col = 2, layout.pos.row = 3), viewport(width = 1, height = 1, name = paste(prefix, "plot", sep = ""), default.units = if (keep_aspect_ratio) "snpc" else "npc")) vpMarginBottom <- viewport(layout.pos.col = 2, layout.pos.row = 4, name = paste(prefix, "margin_bottom", sep = "")) vpMarginLeft <- viewport(layout.pos.col = 1, layout.pos.row = 3, name = paste(prefix, "margin_left", sep = "")) vpMarginTop <- viewport(layout.pos.col = 2, layout.pos.row = 2, name = paste(prefix, "margin_top", sep = "")) vpMarginRight <- viewport(layout.pos.col = 3, layout.pos.row = 3, name = paste(prefix, "margin_right", sep = "")) vpCornerTL <- viewport(layout.pos.col = 1, layout.pos.row = 2, name = paste(prefix, "corner_top_left", sep = "")) vpCornerTR <- viewport(layout.pos.col = 3, layout.pos.row = 2, name = paste(prefix, "corner_top_right", sep = "")) vpCornerBL <- viewport(layout.pos.col = 1, layout.pos.row = 4, name = paste(prefix, "corner_bottom_left", sep = "")) vpCornerBR <- viewport(layout.pos.col = 3, layout.pos.row = 4, name = paste(prefix, "corner_bottom_right", sep = "")) vpLegend <- viewport(layout.pos.col = 4, layout.pos.row = 3, name = paste(prefix, "legend", sep = "")) vpLegendTop <- viewport(layout.pos.col = 4, layout.pos.row = 2, name = paste(prefix, "legend_top", sep = "")) vpLegendSub <- viewport(layout.pos.col = 4, layout.pos.row = 4, name = paste(prefix, "legend_sub", sep = "")) vpBase <- viewport(layout = grid.layout(5, 4, widths = unit.c(mar[4], unit(1, "null"), mar[2], legend_width), heights = unit.c(oma[1], mar[1], unit(1, "null"), mar[3], oma[2])), name = paste(prefix, "base", sep = "")) vpMain <- viewport(layout.pos.col = 1:4, layout.pos.row = 1, name = paste(prefix, "main", sep = "")) vpSub <- viewport(layout.pos.col = 1:4, layout.pos.row = 5, name = paste(prefix, "sub", sep = "")) vpTree(vpBase, vpList(vpMain, vpMarginBottom, vpMarginLeft, vpMarginTop, vpMarginRight, vpLegendTop, vpLegend, vpLegendSub, vpCornerTL, vpCornerTR, vpCornerBL, vpCornerBR, vpPlot, vpSub)) } vcd/R/legends.R0000644000175300001440000001577111566471033012663 0ustar meyeruserslegend_resbased <- function(fontsize = 12, x = unit(1, "lines"), y = unit(0.1, "npc"), height = unit(0.8, "npc"), width = unit(0.7, "lines"), digits = 3, check_overlap = TRUE, text = NULL, steps = 200, ticks = 10, pvalue = TRUE, range = NULL) { if(!is.unit(x)) x <- unit(x, "native") if(!is.unit(y)) y <- unit(y, "npc") if(!is.unit(width)) width <- unit(width, "lines") if(!is.unit(height)) height <- unit(height, "npc") function(residuals, shading, autotext) { res <- as.vector(residuals) if(is.null(text)) text <- autotext p.value <- attr(shading, "p.value") legend <- attr(shading, "legend") if (all(residuals == 0)) { pushViewport(viewport(x = x, y = y, just = c("left", "bottom"), default.units = "native", height = height, width = width)) grid.lines(y = 0.5) grid.text(0, x = unit(1, "npc") + unit(0.8, "lines"), y = 0.5, gp = gpar(fontsize = fontsize)) warning("All residuals are zero.") } else { if (is.null(range)) range <- range(res) if (length(range) != 2) stop("Range must have length two!") if (is.na(range[1])) range[1] <- min(res) if (is.na(range[2])) range[2] <- max(res) pushViewport(viewport(x = x, y = y, just = c("left", "bottom"), yscale = range, default.units = "native", height = height, width = width)) if(is.null(legend$col.bins)) { col.bins <- seq(range[1], range[2], length = steps) at <- NULL } else { col.bins <- sort(unique(c(legend$col.bins, range))) col.bins <- col.bins[col.bins <= range[2] & col.bins >= range[1]] at <- col.bins } y.pos <- col.bins[-length(col.bins)] y.height <- diff(col.bins) grid.rect(x = unit(rep.int(0, length(y.pos)), "npc"), y = y.pos, height = y.height, default.units = "native", gp = gpar(fill = shading(y.pos + 0.5 * y.height)$fill, col = 0), just = c("left", "bottom")) grid.rect(gp = gpar(fill = "transparent")) if(is.null(at)) at <- seq(from = head(col.bins, 1), to = tail(col.bins, 1), length = ticks) tw <- paste(rep("4", digits), collapse = "") if (any(trunc(at) != at)) tw <- paste(tw, ".", sep = "") if (any(at < 0)) tw <- paste(tw, "-", sep = "") grid.text(format(signif(at, digits = digits)), x = unit(1, "npc") + unit(0.8, "lines") + unit(1, "strwidth", tw), y = at, default.units = "native", just = c("right", "center"), gp = gpar(fontsize = fontsize), check.overlap = check_overlap) grid.segments(x0 = unit(1, "npc"), x1 = unit(1,"npc") + unit(0.5, "lines"), y0 = at, y1 = at, default.units = "native") } popViewport(1) grid.text(text, x = x, y = unit(1, "npc") - y + unit(1, "lines"), gp = gpar(fontsize = fontsize, lineheight = 0.8), just = c("left", "bottom") ) if(!is.null(p.value) && pvalue) { grid.text(paste("p-value =\n", format.pval(p.value), sep = ""), x = x, y = y - unit(1, "lines"), gp = gpar(fontsize = fontsize, lineheight = 0.8), just = c("left", "top")) } } } class(legend_resbased) <- "grapcon_generator" legend_fixed <- function(fontsize = 12, x = unit(1, "lines"), y = NULL, height = NULL, width = unit(1.5, "lines"), steps = 200, digits = 1, space = 0.05, text = NULL, range = NULL) { if(!is.unit(x)) x <- unit(x, "native") if(!is.unit(y) && !is.null(y)) y <- unit(y, "npc") if(!is.unit(width)) width <- unit(width, "lines") if(!is.unit(height) && !is.null(height)) height <- unit(height, "npc") function(residuals, shading, autotext) { res <- as.vector(residuals) if(is.null(text)) text <- autotext if (is.null(y)) y <- unit(1, "strwidth", text) + unit(1, "lines") if (is.null(height)) height <- unit(1, "npc") - y pushViewport(viewport(x = x, y = y, just = c("left", "bottom"), yscale = c(0,1), default.units = "npc", height = height, width = width)) p.value <- attr(shading, "p.value") legend <- attr(shading, "legend") if (is.null(range)) range <- range(res) if (length(range) != 2) stop("Range must have length two!") if (is.na(range[1])) range[1] <- min(res) if (is.na(range[2])) range[2] <- max(res) if(is.null(legend$col.bins)) { col.bins <- seq(range[1], range[2], length = steps) } else { col.bins <- sort(unique(c(legend$col.bins, range))) col.bins <- col.bins[col.bins <= range[2] & col.bins >= range[1]] } l <- length(col.bins) y.height <- (1 - (l - 2) * space) / (l - 1) y.pos <- cumsum(c(0, rep(y.height + space, l - 2))) res <- col.bins[-l] + diff(col.bins) / 2 grid.rect(x = unit(rep.int(0, length(y.pos)), "npc"), y = y.pos, height = y.height, default.units = "npc", gp = shading(res), just = c("left", "bottom")) numbers <- format(col.bins, nsmall = digits, digits = digits) wid <- unit(1, "strwidth", format(max(abs(col.bins)), nsmall = digits, digits = digits)) grid.text(numbers[-l], x = unit(1, "npc") + unit(0.6, "lines") + wid, y = y.pos, gp = gpar(fontsize = fontsize), default.units = "npc", just = c("right", "bottom")) grid.text(numbers[-1], x = unit(1, "npc") + unit(0.6, "lines") + wid, y = y.pos + y.height, gp = gpar(fontsize = fontsize), default.units = "npc", just = c("right", "top")) wid2 <- unit(1, "strwidth", format(max(abs(trunc(col.bins))))) + unit(0.3, "strwidth", ".") grid.segments(x0 = unit(1, "npc") + wid2 + unit(0.6, "lines"), x1 = unit(1, "npc") + wid2 + unit(0.6, "lines"), y0 = unit(y.pos, "npc") + 1.5 * unit(1, "strheight", "-44.4"), y1 = unit(y.pos + y.height, "npc") - 1.5 * unit(1, "strheight", "-44.4") ) popViewport(1) grid.text(text, x = x + 0.5 * width, y = 0, gp = gpar(fontsize = fontsize, lineheight = 0.8), just = c("left", "top"), rot = 90 ) } } class(legend_fixed) <- "grapcon_generator" vcd/R/tabletools.R0000644000175300001440000000512211566471033013377 0ustar meyerusersindependence_table <- function(x, frequency = c("absolute", "relative")) { if (!is.array(x)) stop("Need array of absolute frequencies!") frequency <- match.arg(frequency) n <- sum(x) x <- x / n d <- dim(x) ## build margins margins <- lapply(1:length(d), function(i) apply(x, i, sum)) ## multiply all combinations & reshape tab <- array(apply(expand.grid(margins), 1, prod), d, dimnames = dimnames(x)) if (frequency == "relative") tab else tab * n } mar_table <- function(x) { if(!is.matrix(x)) stop("Function only defined for 2-way tables.") tab <- rbind(cbind(x, TOTAL = rowSums(x)), TOTAL = c(colSums(x), sum(x))) names(dimnames(tab)) <- names(dimnames(x)) tab } table2d_summary <- function(object, margins = TRUE, percentages = FALSE, conditionals = c("none", "row", "column"), ... ) { ret <- list() ret$chisq <- summary.table(object, ...) if(is.matrix(object)) { conditionals <- match.arg(conditionals) tab <- array(0, c(dim(object) + margins, 1 + percentages + (conditionals != "none"))) ## frequencies tab[,,1] <- if(margins) mar_table(object) else object ## percentages if(percentages) { tmp <- prop.table(object) tab[,,2] <- 100 * if(margins) mar_table(tmp) else tmp } ## conditional distributions if(conditionals != "none") { tmp <- prop.table(object, margin = 1 + (conditionals == "column")) tab[,,2 + percentages] <- 100 * if(margins) mar_table(tmp) else tmp } ## dimnames dimnames(tab) <- c(dimnames(if(margins) mar_table(object) else object), list(c("freq", if(percentages) "%", switch(conditionals, row = "row%", column = "col%") ) ) ) ## patch row% / col% margins if(conditionals == "row") tab[dim(tab)[1],,2 + percentages] <- NA if(conditionals == "column") tab[,dim(tab)[2],2 + percentages] <- NA ret$table <- tab } class(ret) <- "table2d_summary" ret } print.table2d_summary <- function (x, digits = max(1, getOption("digits") - 3), ...) { if (!is.null(x$table)) if(dim(x$table)[3] == 1) print(x$table[,,1], digits = digits, ...) else print(ftable(aperm(x$table, c(1,3,2))), 2, digits = digits, ...) cat("\n") if (!is.null(x$chisq)) print.summary.table(x$chisq, digits, ...) invisible(x) } vcd/R/Kappa.R0000644000175300001440000000362711720270752012270 0ustar meyerusersKappa <- function (x, weights = c("Equal-Spacing", "Fleiss-Cohen")) { if (is.character(weights)) weights <- match.arg(weights) d <- diag(x) n <- sum(x) nc <- ncol(x) colFreqs <- colSums(x)/n rowFreqs <- rowSums(x)/n ## Kappa kappa <- function (po, pc) (po - pc) / (1 - pc) std <- function (po, pc, W = 1) sqrt(sum(W * W * po * (1 - po)) / crossprod(1 - pc) / n) ## unweighted po <- sum(d) / n pc <- crossprod(colFreqs, rowFreqs) k <- kappa(po, pc) s <- std(po, pc) ## weighted W <- if (is.matrix(weights)) weights else if (weights == "Equal-Spacing") 1 - abs(outer(1:nc, 1:nc, "-")) / (nc - 1) else 1 - (abs(outer(1:nc, 1:nc, "-")) / (nc - 1))^2 pow <- sum(W * x) / n pcw <- sum(W * colFreqs %o% rowFreqs) kw <- kappa(pow, pcw) sw <- std(x / n, 1 - pcw, W) structure( list(Unweighted = c( value = k, ASE = s ), Weighted = c( value = kw, ASE = sw ), Weights = W ), class = "Kappa" ) } print.Kappa <- function (x, ...) { tab <- rbind(x$Unweighted, x$Weighted) rownames(tab) <- names(x)[1:2] print(tab, ...) invisible(x) } summary.Kappa <- function (object, ...) structure(object, class = "summary.Kappa") print.summary.Kappa <- function (x, ...) { print.Kappa(x, ...) cat("\nWeights:\n") print(x$Weights, ...) invisible(x) } confint.Kappa <- function(object, parm, level = 0.95, ...) { q <- qnorm((1 + level) / 2) matrix(c(object[[1]][1] - object[[1]][2] * q, object[[1]][1] + object[[1]][2] * q, object[[2]][1] - object[[2]][2] * q, object[[2]][1] + object[[2]][2] * q), ncol = 2, byrow = TRUE, dimnames = list(Kappa = c("Unweighted","Weighted"), c("lwr","upr")) ) } vcd/R/goodfit.R0000644000175300001440000001522511720271405012660 0ustar meyerusersgoodfit <- function(x, type = c("poisson", "binomial", "nbinomial"), method = c("ML", "MinChisq"), par = NULL) { if(is.vector(x)) { x <- table(x) } if(is.table(x)) { if(length(dim(x)) > 1) stop ("x must be a 1-way table") freq <- as.vector(x) count <- as.numeric(names(x)) } else { if(!(!is.null(ncol(x)) && ncol(x) == 2)) stop("x must be a 2-column matrix or data.frame") freq <- as.vector(x[,1]) count <- as.vector(x[,2]) } ## fill-in possibly missing cells nfreq <- rep(0, max(count) + 1) nfreq[count + 1] <- freq freq <- nfreq count <- 0:max(count) n <- length(count) ## starting value for degrees of freedom df <- -1 type <- match.arg(type) method <- match.arg(method) switch(type, "poisson" = { if(!is.null(par)) { if(!is.list(par)) stop("`par' must be a named list") if(!(names(par) == "lambda")) stop("`par' must specify `lambda'") par <- par$lambda method <- "fixed" } else if(method == "ML") { df <- df - 1 par <- weighted.mean(count,freq) } else if(method == "MinChisq") { df <- df - 1 chi2 <- function(x) { p.hat <- diff(c(0, ppois(count[-n], lambda = x), 1)) expected <- sum(freq) * p.hat sum((freq - expected)^2/expected) } par <- optimize(chi2, range(count))$minimum } par <- list(lambda = par) p.hat <- dpois(count, lambda = par$lambda) }, "binomial" = { size <- par$size if(is.null(size)) { size <- max(count) warning("size was not given, taken as maximum count") } if(size > max(count)) { nfreq <- rep(0, size + 1) nfreq[count + 1] <- freq freq <- nfreq count <- 0:size n <- length(count) } if(!is.null(par$prob)) { if(!is.list(par)) stop("`par' must be a named list and specify `prob'") par <- par$prob method <- "fixed" } else if(method == "ML") { df <- df - 1 par <- weighted.mean(count/size, freq) } else if(method == "MinChisq") { df <- df - 1 chi2 <- function(x) { p.hat <- diff(c(0, pbinom(count[-n], prob = x, size = size), 1)) expected <- sum(freq) * p.hat sum((freq - expected)^2/expected) } par <- optimize(chi2, c(0,1))$minimum } par <- list(prob = par, size = size) p.hat <- dbinom(count, prob = par$prob, size = par$size) }, "nbinomial" = { if(!is.null(par)) { if(!is.list(par)) stop("`par' must be a named list") if(!(isTRUE(all.equal(names(par), "size")) | isTRUE(all.equal(sort(names(par)), c("prob", "size"))))) stop("`par' must specify `size' and possibly `prob'") if(!is.null(par$prob)) method <- "fixed" } switch(method, "ML" = { if(is.null(par$size)) { df <- df - 2 par <- fitdistr(rep(count, freq), "negative binomial")$estimate par <- par[1]/c(1, sum(par)) } else { df <- df - 1 method <- c("ML", "with size fixed") size <- par$size xbar <- weighted.mean(count,freq) par <- c(size, size/(xbar+size)) } }, "MinChisq" = { if(is.null(par$size)) { df <- df - 2 ## MM xbar <- weighted.mean(count,freq) s2 <- var(rep(count,freq)) p <- xbar / s2 size <- xbar^2/(s2 - xbar) par1 <- c(size, p) ## minChisq chi2 <- function(x) { p.hat <- diff(c(0, pnbinom(count[-n], size = x[1], prob = x[2]), 1)) expected <- sum(freq) * p.hat sum((freq - expected)^2/expected) } par <- optim(par1, chi2)$par } else { df <- df - 1 method <- c("MinChisq", "with size fixed") chi2 <- function(x) { p.hat <- diff(c(0, pnbinom(count[-n], size = par$size, prob = x), 1)) expected <- sum(freq) * p.hat sum((freq - expected)^2/expected) } par <- c(par$size, optimize(chi2, c(0, 1))$minimum) } }, "fixed" = { par <- c(par$size, par$prob) }) par <- list(size = par[1], prob = par[2]) p.hat <- dnbinom(count, size = par$size, prob = par$prob) }) expected <- sum(freq) * p.hat df <- switch(method[1], "MinChisq" = { length(freq) + df }, "ML" = { sum(freq > 0) + df }, "fixed" = { c(length(freq), sum(freq > 0)) + df } ) RVAL <- list(observed = freq, count = count, fitted = expected, type = type, method = method, df = df, par = par) class(RVAL) <- "goodfit" RVAL } print.goodfit <- function(x, ...) { cat(paste("\nObserved and fitted values for", x$type, "distribution\n")) if(x$method[1] == "fixed") cat("with fixed parameters \n\n") else cat(paste("with parameters estimated by `", paste(x$method, collapse = " "), "' \n\n", sep = "")) RVAL <- cbind(x$count, x$observed, x$fitted) colnames(RVAL) <- c("count", "observed", "fitted") rownames(RVAL) <- rep("", nrow(RVAL)) print(RVAL) invisible(x) } summary.goodfit <- function(object, ...) { df <- object$df obsrvd <- object$observed count <- object$count expctd <- fitted(object) G2 <- sum(ifelse(obsrvd == 0, 0, obsrvd * log(obsrvd/expctd))) * 2 n <- length(obsrvd) switch(object$type, "poisson" = { pfun <- "ppois" }, "binomial" = { pfun <- "pbinom" }, "nbinomial" = { pfun <- "pnbinom" }) p.hat <- diff(c(0, do.call(pfun, c(list(q = count[-n]), object$par)), 1)) expctd <- p.hat * sum(obsrvd) X2 <- sum((obsrvd - expctd)^2/expctd) names(G2) <- "Likelihood Ratio" names(X2) <- "Pearson" if(any(expctd < 5) & object$method[1] != "ML") warning("Chi-squared approximation may be incorrect") RVAL <- switch(object$method[1], "ML" = { G2 }, "MinChisq" = { X2 }, "fixed" = { c(X2, G2) } ) RVAL <- cbind(RVAL, df, pchisq(RVAL, df = df, lower.tail = FALSE)) colnames(RVAL) <- c("X^2", "df", "P(> X^2)") cat(paste("\n\t Goodness-of-fit test for", object$type, "distribution\n\n")) print(RVAL) invisible(RVAL) } plot.goodfit <- function(x, ...) { rootogram(x, ...) } fitted.goodfit <- function(object, ...) { object$fitted } predict.goodfit <- function(object, newcount = NULL, type = c("response", "prob"), ...) { if(is.null(newcount)) newcount <- object$count type <- match.arg(type) switch(object$type, "poisson" = { densfun <- "dpois" }, "binomial" = { densfun <- "dbinom" }, "nbinomial" = { densfun <- "dnbinom" }) RVAL <- do.call(densfun, c(list(x = newcount), object$par)) if(type == "response") RVAL <- RVAL * sum(object$observed) return(RVAL) } vcd/R/tile.R0000644000175300001440000001437611566471033012177 0ustar meyeruserstile <- function(x, ...) UseMethod("tile") tile.formula <- function(formula, data = NULL, ..., main = NULL, sub = NULL, subset = NULL, na.action = NULL) { if (is.logical(main) && main) main <- deparse(substitute(data)) else if (is.logical(sub) && sub) sub <- deparse(substitute(data)) m <- match.call(expand.dots = FALSE) edata <- eval(m$data, parent.frame()) fstr <- strsplit(paste(deparse(formula), collapse = ""), "~") vars <- strsplit(strsplit(gsub(" ", "", fstr[[1]][2]), "\\|")[[1]], "\\+") varnames <- vars[[1]] dep <- gsub(" ", "", fstr[[1]][1]) if (!dep %in% c("","Freq")) { if (all(varnames == ".")) { varnames <- if (is.data.frame(data)) colnames(data) else names(dimnames(as.table(data))) varnames <- varnames[-which(varnames %in% dep)] } varnames <- c(varnames, dep) } if (inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { dat <- as.table(data) if(all(varnames != ".")) { ind <- match(varnames, names(dimnames(dat))) if (any(is.na(ind))) stop(paste("Can't find", paste(varnames[is.na(ind)], collapse=" / "), "in", deparse(substitute(data)))) dat <- margin.table(dat, ind) } tile.default(dat, main = main, sub = sub, ...) } else { m <- m[c(1, match(c("formula", "data", "subset", "na.action"), names(m), 0))] m[[1]] <- as.name("xtabs") m$formula <- formula(paste(if("Freq" %in% colnames(data)) "Freq", "~", paste(varnames, collapse = "+"))) tab <- eval(m, parent.frame()) tile.default(tab, main = main, sub = sub, ...) } } tile.default <- function(x, tile_type = c("squaredarea", "area", "height", "width"), halign = c("left", "center", "right"), valign = c("bottom", "center", "top"), split_vertical = NULL, shade = FALSE, spacing = spacing_equal(unit(1, "lines")), set_labels = NULL, margins = unit(3, "lines"), keep_aspect_ratio = FALSE, legend_width = NULL, squared_tiles = TRUE, main = NULL, sub = NULL, ...) { ## argument handling if (is.logical(main) && main) main <- deparse(substitute(x)) else if (is.logical(sub) && sub) sub <- deparse(substitute(x)) tile_type <- match.arg(tile_type) halign <- match.arg(halign) valign <- match.arg(valign) x <- as.table(x) dl <- length(d <- dim(x)) ## determine starting positions xpos <- 1 - (halign == "left") - 0.5 * (halign == "center") ypos <- 1 - (valign == "bottom") - 0.5 * (valign == "center") ## heuristic to adjust right/bottom margin to obtain squared tiles ## FIXME: better push another viewport? if (squared_tiles) { ## splitting argument if (is.structable(x) && is.null(split_vertical)) split_vertical <- attr(x, "split_vertical") if (is.null(split_vertical)) split_vertical <- FALSE if (length(split_vertical) == 1) split_vertical <- rep(c(split_vertical, !split_vertical), length.out = dl) if (length(split_vertical) < dl) split_vertical <- rep(split_vertical, length.out = dl) ## compute resulting dimnension dflat <- dim(unclass(structable(x, split_vertical = split_vertical))) ## adjust margins spacing <- spacing(d) delta <- abs(dflat[1] - dflat[2]) fac <- delta / max(dflat) un <- unit(fac, "npc") - unit(fac * 5 / spacing[[1]][[1]], "lines") leg <- if (shade) { if (is.null(legend_width)) unit(5, "lines") else legend_width } else unit(0, "npc") if (dflat[1] < dflat[2]) margins <- margins + unit.c(unit(0, "npc"), unit(0, "npc"), un + leg, unit(0, "npc")) if (dflat[1] > dflat[2]) margins <- margins + unit.c(unit(0, "npc"), un - leg, unit(0, "npc"), unit(0, "npc")) if (dflat[1] == dflat[2]) margins <- margins + unit.c(unit(0, "npc"), unit(0, "npc"), leg, unit(0, "npc")) } ## create dummy labels if some are duplicated ## and set the labels via set_labels dn <- dimnames(x) if (any(unlist(lapply(dn, duplicated)))) { dimnames(x) <- lapply(dn, seq_along) if (is.null(set_labels)) set_labels <- lapply(dn, function(i) structure(i, names = seq(i))) } ## workhorse function creating bars panelfun <- function(residuals, observed, expected, index, gp, name) { xprop <- expected / max(expected) if (tile_type == "height") grid.rect(x = xpos, y = ypos, height = xprop[t(index)], width = 1, gp = gp, just = c(halign, valign), name = name) else if (tile_type == "width") grid.rect(x = xpos, y = ypos, width = xprop[t(index)], height = 1, gp = gp, just = c(halign, valign), name = name) else if (tile_type == "area") grid.rect(x = xpos, y = ypos, width = sqrt(xprop[t(index)]), height = sqrt(xprop[t(index)]), gp = gp, just = c(halign, valign), name = name) else grid.rect(x = xpos, y = ypos, width = xprop[t(index)], height = xprop[t(index)], gp = gp, just = c(halign, valign), name = name) } mycore <- function(residuals, observed, expected = NULL, spacing, gp, split_vertical, prefix = "") { struc_mosaic(panel = panelfun)(residuals, array(1, dim = d, dimnames = dimnames(observed)), expected = observed, spacing, gp, split_vertical, prefix) } strucplot(x, core = mycore, spacing = spacing, keep_aspect_ratio = keep_aspect_ratio, margins = margins, shade = shade, legend_width = legend_width, main = main, sub = sub, set_labels = set_labels, ...) } vcd/R/rootogram.R0000644000175300001440000000736711566471033013255 0ustar meyerusersrootogram <- function(x, ...) { UseMethod("rootogram") } rootogram.goodfit <- function(x, ...) { rootogram.default(x$observed, x$fitted, names = x$count, ...) } rootogram.default <- function(x, fitted, names = NULL, scale = c("sqrt", "raw"), type = c("hanging", "standing", "deviation"), rect_gp = gpar(fill = "lightgray"), lines_gp = gpar(col = "red"), points_gp = gpar(col = "red"), pch = 19, xlab = NULL, ylab = NULL, ylim = NULL, name = "rootogram", newpage = TRUE, pop = TRUE, ...) { if(is.null(names)) names <- names(x) if(is.table(x)) { if(length(dim(x)) > 1) stop ("x must be a 1-way table") x <- as.vector(x) } obs <- x fit <- fitted if(is.null(xlab)) {xlab <- "Number of Occurrences"} if(match.arg(scale) == "sqrt") { obs <- sqrt(obs) fit <- sqrt(fit) if(is.null(ylab)) {ylab <- "sqrt(Frequency)"} } else { if(is.null(ylab)) {ylab <- "Frequency"} } switch(match.arg(type), "hanging" = { if(is.null(ylim)) {ylim <- range(-0.1 * c(fit-obs,fit), c(fit-obs,fit)) + c(0, 0.1)} dummy <- grid_barplot(obs, names = names, offset = fit - obs, gp = rect_gp, xlab = xlab, ylab = ylab, ylim = ylim, name = name, newpage = newpage, pop = FALSE, ...) downViewport(name) grid.lines(x = dummy, y = fit, default.units = "native", gp = lines_gp) grid.points(x = dummy, y = fit, default.units = "native", gp = points_gp, pch = pch) grid.lines(x = unit(c(0, 1), "npc"), y = unit(0, "native")) if(pop) popViewport() else upViewport() }, "standing" = { if(is.null(ylim)) {ylim <- range(-0.01 * c(obs,fit), c(obs,fit)) } dummy <- grid_barplot(obs, names = names, gp = rect_gp, xlab = xlab, ylab = ylab, ylim = ylim, name = name, newpage = newpage, pop = FALSE, ...) downViewport(name) grid.lines(x = dummy, y = fit, default.units = "native", gp = lines_gp) grid.points(x = dummy, y = fit, default.units = "native", gp = points_gp, pch = pch) if(pop) popViewport() else upViewport() }, "deviation" = { if(is.null(ylim)) {ylim <- range(-0.1 * c(fit-obs,fit), c(fit-obs,fit)) + c(0, 0.1)} dummy <- grid_barplot(fit - obs, names = names, gp = rect_gp, xlab = xlab, ylab = ylab, ylim = ylim, name = name, newpage = newpage, pop = FALSE, ...) downViewport(name) grid.lines(x = dummy, y = fit, default.units = "native", gp = lines_gp) grid.points(x = dummy, y = fit, default.units = "native", gp = points_gp, pch = pch) if(pop) popViewport() else upViewport() }) } grid_barplot <- function(height, width = 0.8, offset = 0, names = NULL, xlim = NULL, ylim = NULL, xlab = "", ylab = "", main = "", gp = gpar(fill = "lightgray"), name = "grid_barplot", newpage = TRUE, pop = FALSE) { if(is.null(names)) names <- names(height) height <- as.vector(height) n <- length(height) width <- rep(width, length.out = n) offset <- rep(offset, length.out = n) if(is.null(names)) names <- rep("", n) if(is.null(xlim)) xlim <- c(1 - mean(width[c(1, n)]), n + mean(width[c(1, n)])) if(is.null(ylim)) ylim <- c(min(offset), max(height + offset)) if(newpage) grid.newpage() pushViewport(plotViewport(xscale = xlim, yscale = ylim, default.units = "native", name = name)) grid.rect(x = 1:n, y = offset, width = width, height = height, just = c("centre", "bottom"), default.units = "native", gp = gp) grid.yaxis() grid.text(names, x = unit(1:n, "native"), y = unit(rep(-1.5, n), "lines")) grid.text(xlab, y = unit(-3.5, "lines")) grid.text(ylab, x = unit(-3, "lines"), rot = 90) grid.text(main, y = unit(1, "npc") + unit(2, "lines"), gp = gpar(fontface = "bold")) if(pop) popViewport() else upViewport() invisible(1:n) } vcd/R/labeling.R0000644000175300001440000007175211720272420013007 0ustar meyerusers################################################################ ## labeling pexpand <- function(par, len, default_value, default_names, choices = NULL) { if (is.null(par)) par <- default_value nam <- names(par) if (!is.null(choices)) par <- sapply(par, match.arg, choices) if (is.null(nam)) { default_value <- par par <- rep(par, length.out = len) nam <- names(par) <- default_names } else if (length(nam[nam == ""])) { default_value <- par[nam == ""] nam <- nam[nam != ""] } ret <- rep(default_value, length.out = len) if (!is.null(nam)) { names(ret) <- default_names ret[nam] <- par[nam] } ret } labeling_list <- function(gp_text = gpar(), just = "left", pos = "left", lsep = ": ", sep = " ", offset = unit(c(2, 2), "lines"), varnames = TRUE, cols = 2, ...) { function(d, split_vertical, condvars, prefix = "") { if (is.table(d)) d <- dimnames(d) ld <- length(d) labeling_border(labels = FALSE, varnames = varnames)(d, split_vertical, condvars, prefix) seekViewport(paste(prefix, "margin_bottom", sep = "")) pos <- unit(switch(pos, left = 0, center = 0.5, 1) / cols, "npc") ind <- split(seq(ld), rep.int(seq(cols), ceiling(ld / cols))[seq(ld)]) for (i in seq_along(ind)) grid.text(x = offset[1] + pos + unit((i - 1) / cols, "npc"), y = unit(1, "npc") - offset[2], paste(names(d[ind[[i]]]), sapply(d[ind[[i]]], paste, collapse = sep), sep = lsep, collapse = "\n" ), just = c(just, "top"), gp = gp_text ) } } class(labeling_list) <- "grapcon_generator" labeling_conditional <- function(...) { function (d, split_vertical, condvars, prefix = "") { if (is.table(d)) d <- dimnames(d) v <- rep.int(TRUE, length(d)) v[seq(condvars)] <- FALSE labeling_border(labels = !v, ...)(d, split_vertical, condvars, prefix) labeling_cells(labels = v, ...)(d, split_vertical, condvars, prefix) } } class(labeling_conditional) <- "grapcon_generator" labeling_cells <- function(labels = TRUE, varnames = TRUE, abbreviate_labels = FALSE, abbreviate_varnames = FALSE, gp_text = gpar(), lsep = ": ", lcollapse = "\n", just = "center", pos = "center", rot = 0, margin = unit(0.5, "lines"), clip_cells = TRUE, text = NULL, ...) { function(d, split_vertical, condvars, prefix = "") { if (is.table(d)) d <- dimnames(d) dn <- names(d) ld <- length(d) ## expand parameters if (length(pos) < 2) pos <- c(pos, pos) labels <- pexpand(labels, ld, TRUE, dn) varnames <- pexpand(varnames, ld, TRUE, dn) abbreviate_labels <- pexpand(abbreviate_labels, ld, FALSE, dn) abbreviate_varnames <- pexpand(abbreviate_varnames, ld, FALSE, dn) ## margin if (!is.unit(margin)) margin <- unit(margin, "lines") prvars <- ifelse(abbreviate_varnames, sapply(seq_along(dn), function(i) abbreviate(dn[i], abbreviate_varnames[i])), dn) prvars <- ifelse(varnames, paste(prvars, lsep, sep = ""), "") ## draw labels split <- function(vind = 1, labs = c()) { n <- d[[vind]] for (labind in seq_along(n)) { lab <- c(labs, n[labind]) names(lab) <- names(d)[1:vind] mlab <- paste(prefix, "cell:", paste(dn[1:vind], lab, sep = "=", collapse = ","), sep = "") if (vind < ld) split(vind + 1, lab) else { seekViewport(mlab) pushViewport(viewport(width = max(unit(0, "npc"), unit(1, "npc") - 2 * margin), height = unit(1, "npc") - 2 * margin, clip = clip_cells)) txt <- if (!is.null(text)) { lab <- lab[names(dimnames(text))] do.call("[", c(list(text), as.list(lab))) } else { prlab <- ifelse(abbreviate_labels, sapply(seq_along(lab), function(i) abbreviate(lab[i], abbreviate_labels[i])), lab) prlab <- prlab[labels[1:ld]] paste(prvars[labels[1:ld]], prlab, sep = "", collapse = lcollapse) } grid.text(if(!is.na(txt)) txt, x = switch(pos[1], left =, top = 0, center = 0.5, 1), y = switch(pos[2], left =, top = 1, center = 0.5, 0), gp = gp_text, just = just, rot = rot) popViewport() } } } split() seekViewport(paste(prefix, "base", sep = "")) upViewport(1) } } class(labeling_cells) <- "grapcon_generator" labeling_border <- function(labels = TRUE, varnames = labels, set_labels = NULL, set_varnames = NULL, tl_labels = NULL, alternate_labels = FALSE, tl_varnames = NULL, gp_labels = gpar(fontsize = 12), gp_varnames = gpar(fontsize = 12, fontface = 2), rot_labels = c(0, 90, 0, 90), rot_varnames = c(0, 90, 0, 90), pos_labels = "center", pos_varnames = "center", just_labels = "center", just_varnames = pos_varnames, boxes = FALSE, fill_boxes = FALSE, offset_labels = c(0, 0, 0, 0), offset_varnames = offset_labels, labbl_varnames = NULL, labels_varnames = FALSE, sep = ": ", abbreviate_labs = FALSE, rep = TRUE, clip = FALSE, ... ) { ## expand parameters that apply to the four table margins pos_labels <- pexpand(pos_labels, 4, "center", c("top", "right", "bottom", "left"), c("left", "center", "right")) just_labels <- pexpand(just_labels, 4, "center", c("top", "right", "bottom", "left"), c("left", "center", "right")) offset_varnames <- if (!is.unit(offset_varnames)) unit(pexpand(offset_varnames, 4, rep.int(0, 4), c("top","right","bottom","left")), "lines") else rep(offset_varnames, length.out = 4) offset_labels <- if (!is.unit(offset_labels)) unit(pexpand(offset_labels, 4, rep.int(0, 4), c("top","right","bottom","left")), "lines") else rep(offset_labels, length.out = 4) rot_labels <- pexpand(rot_labels, 4, c(0, 90, 0, 90), c("top", "right", "bottom", "left")) if (inherits(gp_varnames, "gpar")) gp_varnames <- list(gp_varnames) gp_varnames <- pexpand(gp_varnames, 4, list(gpar(fontsize = 12, fontface = 2)), c("top", "right", "bottom", "left")) rot_varnames <- pexpand(rot_varnames, 4, c(0, 90, 0, 90), c("top", "right", "bottom", "left")) pos_varnames <- pexpand(pos_varnames, 4, "center", c("top", "right", "bottom", "left"), c("left", "center", "right")) just_varnames <- pexpand(just_varnames, 4, pos_varnames, c("top", "right", "bottom", "left"), c("left", "center", "right")) function(d, split_vertical, condvars, prefix = "") { if (is.table(d)) d <- dimnames(d) dn <- names(d) ld <- length(d) ## expand table- (i.e., dimensionality)-dependent parameters clip <- pexpand(clip, ld, TRUE, dn) labels <- pexpand(labels, ld, TRUE, dn) labels_varnames <- pexpand(labels_varnames, ld, FALSE, dn) ## tl_labels def <- logical() def[split_vertical] <- rep(c(TRUE, FALSE), length.out = sum(split_vertical)) def[!split_vertical] <- rep(c(TRUE, FALSE), length.out = sum(!split_vertical)) tl_labels <- if (is.null(tl_labels)) def else pexpand(tl_labels, ld, def, dn) ## rep labels rep <- pexpand(rep, ld, TRUE, dn) printed <- lapply(d, function(i) rep.int(FALSE, length(i))) ## alternate labels alternate_labels <- pexpand(alternate_labels, ld, FALSE, dn) ## abbreviate abbreviate_labs <- pexpand(abbreviate_labs, ld, FALSE, dn) labs <- d for (i in seq_along(d)) if (abbreviate_labs[i]) labs[[i]] <- abbreviate(labs[[i]], abbreviate_labs[i]) ## gp_labels if (inherits(gp_labels, "gpar")) gp_labels <- list(gp_labels) gp_labels <- pexpand(gp_labels, ld, list(gpar(fontsize = 12)), dn) ## varnames varnames <- pexpand(varnames, ld, labels, dn) ## tl_varnames if (is.null(tl_varnames) && is.null(labbl_varnames)) tl_varnames <- tl_labels tl_varnames <- pexpand(tl_varnames, ld, tl_labels, dn) ## labbl_varnames if (!is.null(labbl_varnames)) labbl_varnames <- pexpand(labbl_varnames, ld, TRUE, dn) ## boxes boxes <- pexpand(boxes, ld, FALSE, dn) ## fill_boxes dnl <- sapply(d, length) fill_boxes <- if (is.atomic(fill_boxes)) { fill_boxes <- if (is.logical(fill_boxes)) ifelse(pexpand(fill_boxes, ld, FALSE, dn), "grey", NA) else pexpand(fill_boxes, ld, "grey", dn) col <- rgb2hsv(col2rgb(fill_boxes)) lapply(seq(along.with = dnl), function(i) if (is.na(fill_boxes[i])) "white" else hsv(h = col["h",i], s = col["s",i], v = seq(from = col["v",i], to = 0.5 * col["v",i], length = dnl[i]) ) ) } else { fill_boxes <- pexpand(fill_boxes, ld, "white", dn) lapply(seq(ld), function(i) pexpand(fill_boxes[[i]], dnl[i], "white", d[[i]]) ) } ## precompute spaces lsp <- tsp <- bsp <- rsp <- 0 labsp <- rep.int(0, ld) for (i in seq_along(dn)[tl_labels & labels]) labsp[i] <- if (split_vertical[i]) { if (alternate_labels[i]) bsp <- bsp - 1 tsp <- tsp + 1 } else { if (alternate_labels[i]) rsp <- rsp + 1 lsp <- lsp - 1 } for (i in rev(seq_along(dn)[!tl_labels & labels])) labsp[i] <- if (split_vertical[i]) { if (alternate_labels[i]) tsp <- tsp + 1 bsp <- bsp - 1 } else { if (alternate_labels[i]) lsp <- lsp - 1 rsp <- rsp + 1 } if(is.null(labbl_varnames)) { ## varnames in the outer margin ## compute axis names tt <- bt <- lt <- rt <- "" for (i in seq_along(dn)) { var <- if (!is.null(set_varnames) && !is.na(set_varnames[dn[i]])) set_varnames[dn[i]] else dn[i] if (varnames[i]) { if (split_vertical[i]) { if (tl_varnames[i]) tt <- paste(tt, var, sep = if (tt == "") "" else " / ") else bt <- paste(bt, var, sep = if (bt == "") "" else " / ") } else { if (tl_varnames[i]) lt <- paste(lt, var, sep = if (lt == "") "" else " / ") else rt <- paste(rt, var, sep = if (rt == "") "" else " / ") } } } ## draw axis names if (tt != "") grid.text(tt, y = unit(1, "npc") + unit(tsp + 1, "lines") + offset_varnames[1], x = switch(pos_varnames[1], left =, bottom = 0, center =, centre = 0.5, 1), rot = rot_varnames[1], just = just_varnames[1], gp = gp_varnames[[1]]) if (bt != "") grid.text(bt, y = unit(bsp - 1, "lines") + -1 * offset_varnames[3], x = switch(pos_varnames[3], left =, bottom = 0, center =, centre = 0.5, 1), rot = rot_varnames[3], just = just_varnames[3], gp = gp_varnames[[3]]) if (lt != "") grid.text(lt, x = unit(lsp - 1, "lines") + -1 * offset_varnames[4], y = switch(pos_varnames[4], left =, bottom = 0, center =, centre = 0.5, 1), rot = rot_varnames[4], just = just_varnames[4], gp = gp_varnames[[4]]) if (rt != "") grid.text(rt, x = unit(1, "npc") + unit(rsp + 1, "lines") + offset_varnames[2], y = switch(pos_varnames[2], left =, bottom = 0, center =, centre = 0.5, 1), rot = rot_varnames[2], just = just_varnames[2], gp = gp_varnames[[2]]) } else { ## varnames beneath labels for (i in seq_along(dn)) { var <- if (!is.null(set_varnames) && !is.na(set_varnames[dn[i]])) set_varnames[dn[i]] else dn[i] if (varnames[i]) { if (split_vertical[i]) { if (tl_labels[i]) { if (labbl_varnames[i]) { grid.text(var, y = unit(1, "npc") + unit(1 + tsp - labsp[i], "lines") + offset_varnames[1], x = unit(-0.5, "lines"), just = "right", gp = gp_varnames[[4]]) } else { grid.text(var, y = unit(1, "npc") + unit(1 + tsp - labsp[i], "lines") + offset_varnames[1], x = unit(1, "npc") + unit(0.5, "lines"), just = "left", gp = gp_varnames[[2]]) } } else { if (labbl_varnames[i]) { grid.text(var, y = unit(labsp[i], "lines") + -1 * offset_varnames[3], x = unit(-0.5, "lines"), just = "right", gp = gp_varnames[[4]]) } else { grid.text(var, y = unit(labsp[i], "lines") + -1 * offset_varnames[3], x = unit(1, "npc") + unit(0.5, "lines"), just = "left", gp = gp_varnames[[2]]) } } } else { if (tl_labels[i]) { if (labbl_varnames[i]) { grid.text(var, x = unit(lsp - 1 - labsp[i], "lines") + -1 * offset_varnames[4], y = unit(-0.5, "lines"), just = "right", rot = 90, gp = gp_varnames[[4]]) } else { grid.text(var, x = unit(lsp - 1 - labsp[i], "lines") + -1 * offset_varnames[4], y = unit(1, "npc") + unit(0.5, "lines"), just = "left", rot = 90, gp = gp_varnames[[2]]) } } else { if (labbl_varnames[i]) { grid.text(var, x = unit(1, "npc") + unit(labsp[i], "lines") + offset_varnames[2], y = unit(-0.5, "lines"), just = "right", rot = 90, gp = gp_varnames[[4]]) } else { grid.text(var, x = unit(1, "npc") + unit(labsp[i], "lines") + offset_varnames[2], y = unit(1, "npc") + unit(0.5, "lines"), just = "left", rot = 90, gp = gp_varnames[[2]]) } } } } } } ## draw labels split <- function(vind = 1, root = paste(prefix, "cell:", sep = ""), left = TRUE, right = TRUE, top = TRUE, bottom = TRUE) { n <- d[[vind]] vl <- length(n) sp <- split_vertical[vind] labseq <- seq_along(n) if (!sp) labseq <- rev(labseq) for (labind in labseq) { mlab <- paste(root, dn[vind], "=", n[labind], sep = "") if (labels[vind] && (rep[vind] || !printed[[vind]][labind])) { lab <- if (!is.null(set_labels) && !is.null(set_labels[[dn[vind]]])) set_labels[[dn[vind]]][labind] else labs[[vind]][labind] if (labels_varnames[vind]) lab <- if (!is.null(set_varnames) && !is.na(set_varnames[dn[vind]])) paste(set_varnames[dn[vind]], lab, sep = sep) else paste(dn[vind], lab, sep = sep) if (sp) { if (tl_labels[vind]) { if (top) { seekViewport(mlab) if (clip[vind]) pushViewport(viewport(height = unit(1, "npc") + 2 * offset_labels[1] + unit(2 * (2 + tsp - labsp[vind]), "lines"), clip = "on")) if (boxes[vind]) grid.rect(height = unit(0.8, "lines"), y = unit(1, "npc") + offset_labels[1] + unit(1 + tsp - labsp[vind] - (2 + as.numeric(offset_labels[1]) + tsp - labsp[vind]) * clip[vind], "lines"), gp = gpar(fill = fill_boxes[[vind]][labind])) grid.text(lab, y = unit(1, "npc") + offset_labels[1] + unit(1 + tsp - labsp[vind] - (2 + as.numeric(offset_labels[1]) + tsp - labsp[vind]) * clip[vind], "lines"), x = unit(0.15 * switch(pos_labels[1], left =, bottom = 1, center =, centre = 0, -1) * boxes[vind], "lines") + unit(switch(pos_labels[1], left =, bottom = 0, center =, centre = 0.5, 1), "npc"), rot = rot_labels[1], just = just_labels[1], gp = gp_labels[[vind]]) if (clip[vind]) popViewport() printed[[vind]][labind] <<- TRUE } } else { if (bottom) { seekViewport(mlab) if (clip[vind]) pushViewport(viewport(height = unit(1, "npc") + 2 * offset_labels[3] + unit(2 * (1 + abs(labsp[vind])), "lines"), clip = "on")) ### if (boxes[vind]) grid.rect(height = unit(0.8, "lines"), y = -1 * offset_labels[3] + unit(labsp[vind] + (1 + as.numeric(offset_labels[3]) + abs(labsp[vind])) * clip[vind], "lines"), gp = gpar(fill = fill_boxes[[vind]][labind])) grid.text(lab, y = -1 * offset_labels[3] + unit(labsp[vind] + (1 + as.numeric(offset_labels[3]) + abs(labsp[vind])) * clip[vind], "lines"), x = unit(0.15 * switch(pos_labels[3], left =, bottom = 1, center =, centre = 0, -1) * boxes[vind], "lines") + unit(switch(pos_labels[3], left =, bottom = 0, center =, centre = 0.5, 1), "npc"), rot = rot_labels[3], just = just_labels[3], gp = gp_labels[[vind]]) if (clip[vind]) popViewport() printed[[vind]][labind] <<- TRUE } } } else { if (tl_labels[vind]) { if (left) { seekViewport(mlab) if (clip[vind]) pushViewport(viewport(width = unit(1, "npc") + 2 * offset_labels[4] + unit(2 * (2 - lsp + labsp[vind]), "lines"), clip = "on")) if (boxes[vind]) grid.rect(width = unit(0.8, "lines"), x = -1 * offset_labels[4] + unit(lsp - 1 - labsp[vind] + (2 - lsp + as.numeric(offset_labels[4]) + labsp[vind]) * clip[vind], "lines"), gp = gpar(fill = fill_boxes[[vind]][labind])) grid.text(lab, x = -1 * offset_labels[4] + unit(lsp - 1 - labsp[vind] + (2 - lsp + as.numeric(offset_labels[4]) + labsp[vind]) * clip[vind], "lines"), y = unit(0.15 * switch(pos_labels[4], left =, bottom = 1, centre = 0, -1) * boxes[vind], "lines") + unit(switch(pos_labels[4], left =, bottom = 0, center =, centre = 0.5, 1), "npc"), rot = rot_labels[4], just = just_labels[4], gp = gp_labels[[vind]]) if (clip[vind]) popViewport() printed[[vind]][labind] <<- TRUE } } else { if (right) { seekViewport(mlab) if (clip[vind]) pushViewport(viewport(width = unit(1, "npc") + 2 * offset_labels[2] + unit(2 * (1 + abs(labsp[vind])), "lines"), clip = "on")) if (boxes[vind]) grid.rect(width = unit(0.8, "lines"), x = offset_labels[2] + unit(1, "npc") + unit(labsp[vind] - (1 + as.numeric(offset_labels[2]) + abs(labsp[vind])) * clip[vind], "lines"), gp = gpar(fill = fill_boxes[[vind]][labind])) grid.text(lab, x = offset_labels[2] + unit(1, "npc") + unit(0.1, "lines") + unit(labsp[vind] - (1 + as.numeric(offset_labels[2]) + abs(labsp[vind])) * clip[vind], "lines"), y = unit(0.15 * switch(pos_labels[2], left =, bottom = 1, center =, centre = 0, -1) * boxes[vind], "lines") + unit(switch(pos_labels[2], left =, bottom = 0, center =, centre = 0.5, 1), "npc"), rot = rot_labels[2], just = just_labels[2], gp = gp_labels[[vind]]) if (clip[vind]) popViewport() printed[[vind]][labind] <<- TRUE } } } } if (vind < ld) Recall(vind + 1, paste(mlab, ",", sep = ""), if (sp) left && labind == 1 else left, if (sp) right && labind == vl else right, if (!sp) top && labind == 1 else top, if (!sp) bottom && labind == vl else bottom) } } ## patch for alternating labels, part 1 if (any(alternate_labels)) { ## save set_labels set_labels_hold <- set_labels ## create vanilla set_labels-object set_labels <- d ## copy old set_labels if (!is.null(set_labels_hold)) set_labels[names(set_labels_hold)] <- set_labels_hold ## mask half of the labels for (i in which(alternate_labels)) if (length(d[[i]]) > 1) set_labels[[i]][seq(2, length(d[[i]]), 2)] <- "" } split() ## patch for alternating labels, part 2 if (any(alternate_labels)) { ## create again vanilla set_labels-object set_labels <- d ## copy again old set_labels if (!is.null(set_labels_hold)) set_labels[names(set_labels_hold)] <- set_labels_hold ## clear all non-alternated labels labels[!alternate_labels] <- FALSE ## mask other half of alternated labels for (i in which(alternate_labels)) set_labels[[i]][seq(1, length(d[[i]]), 2)] <- "" ## invert tl_labels and labsp tl_labels <- ! tl_labels labsp <- -labsp ## label again split() } seekViewport(paste(prefix, "base", sep = "")) upViewport(1) } } class(labeling_border) <- "grapcon_generator" labeling_doubledecker <- function(lab_pos = c("bottom", "top"), dep_varname = TRUE, boxes = NULL, clip = NULL, labbl_varnames = FALSE, rot_labels = rep.int(0, 4), pos_labels = c("left", "center", "left", "center"), just_labels = c("left", "left", "left", "center"), varnames = NULL, gp_varnames = gpar(fontsize = 12, fontface = 2), offset_varnames = c(0, -0.6, 0, 0), tl_labels = NULL, ...) { lab_pos <- match.arg(lab_pos) if (inherits(gp_varnames, "gpar")) gp_varnames <- list(gp_varnames) gp_varnames <- pexpand(gp_varnames, 4, list(gpar(fontsize = 12, fontface = 2)), c("top", "right", "bottom", "left")) function(d, split_vertical, condvars, prefix = "") { if (is.table(d)) d <- dimnames(d) ld <- length(d) dn <- names(d) ## expand dimension parameters boxes <- pexpand(boxes, ld, c(rep.int(TRUE, ld - 1), FALSE), dn) clip <- pexpand(clip, ld, c(rep.int(TRUE, ld - 1), FALSE), dn) varnames <- pexpand(varnames, ld, c(rep.int(TRUE, ld - 1), FALSE), dn) tl_labels <- pexpand(tl_labels, ld, c(rep.int(lab_pos == "top", ld - 1), FALSE), dn) if (!is.null(labbl_varnames)) labbl_varnames <- pexpand(labbl_varnames, ld, FALSE, dn) ## expand side parameters rot_labels <- pexpand(rot_labels, 4, c(0, 0, 0, 0), c("top", "right", "bottom", "left")) pos_labels <- pexpand(pos_labels, 4, c("left", "center", "left", "center"), c("top", "right", "bottom", "left"), c("left", "center", "right")) just_labels <- pexpand(just_labels, 4, c("left", "left", "left", "center"), c("top", "right", "bottom", "left"), c("left", "center", "right")) offset_varnames <- if (!is.unit(offset_varnames)) unit(pexpand(offset_varnames, 4, c(0, -0.6, 0, 0), c("top","right","bottom","left")), "lines") else rep(offset_varnames, length.out = 4) labeling_border(boxes = boxes, clip = clip, labbl_varnames = labbl_varnames, rot_labels = rot_labels, pos_labels = pos_labels, just_labels = just_labels, varnames = varnames, gp_varnames = gp_varnames, offset_varnames = offset_varnames, tl_labels = tl_labels, ... )(d, split_vertical, condvars, prefix) if (!(is.logical(dep_varname) && !dep_varname)) { if (is.null(dep_varname) || is.logical(dep_varname)) dep_varname <- names(d)[length(d)] seekViewport(paste(prefix, "margin_right", sep = "")) grid.text(dep_varname, x = unit(0.5, "lines"), y = unit(1, "npc"), just = c("left","top"), gp = gp_varnames[[2]]) } } } class(labeling_doubledecker) <- "grapcon_generator" labeling_left <- function(rep = FALSE, pos_varnames = "left", pos_labels = "left", just_labels = "left", ...) labeling_border(rep = rep, pos_varnames = pos_varnames, pos_labels = pos_labels, just_labels = just_labels, ...) class(labeling_left) <- "grapcon_generator" labeling_left2 <- function(tl_labels = TRUE, clip = TRUE, pos_varnames = "left", pos_labels = "left", just_labels = "left", ...) labeling_border(tl_labels = tl_labels, clip = clip, pos_varnames = pos_varnames, pos_labels = pos_labels, just_labels = just_labels, ...) class(labeling_left2) <- "grapcon_generator" labeling_cboxed <- function(tl_labels = TRUE, boxes = TRUE, clip = TRUE, pos_labels = "center", ...) labeling_border(tl_labels = tl_labels, boxes = boxes, clip = clip, pos_labels = pos_labels, ...) class(labeling_cboxed) <- "grapcon_generator" labeling_lboxed <- function(tl_labels = FALSE, boxes = TRUE, clip = TRUE, pos_labels = "left", just_labels = "left", labbl_varnames = FALSE, ...) labeling_border(tl_labels = tl_labels, boxes = boxes, clip = clip, pos_labels = pos_labels, labbl_varnames = labbl_varnames, just_labels = just_labels, ...) class(labeling_lboxed) <- "grapcon_generator" labeling_values <- function(value_type = c("observed", "expected", "residuals"), suppress = NULL, digits = 1, clip_cells = FALSE, ...) { value_type <- match.arg(value_type) if (value_type == "residuals" && is.null(suppress)) suppress <- 2 if (is.null(suppress)) suppress <- 0 if (length(suppress) == 1) suppress <- c(-suppress, suppress) function(d, split_vertical, condvars, prefix) { lookup <- if (value_type == "observed") "x" else value_type if (!exists(lookup, envir = parent.frame())) stop(paste("Could not find", dQuote(value_type), "object.")) values <- get(lookup, envir = parent.frame()) values <- ifelse((values > suppress[2]) | (values < suppress[1]), round(values, digits), NA) labeling_border(...)(d, split_vertical, condvars, prefix) labeling_cells(text = values, clip_cells = clip_cells, ...)(d, split_vertical, condvars, prefix) } } class(labeling_values) <- "grapcon_generator" labeling_residuals <- function(suppress = NULL, digits = 1, clip_cells = FALSE, ...) labeling_values(value_type = "residuals", suppress = suppress, digits = digits, clip_cells = clip_cells, ...) class(labeling_residuals) <- "grapcon_generator" vcd/R/shadings.R0000644000175300001440000002205311566721036013032 0ustar meyerusers## convenience function for interfacing ## HCL colors as implemented in colorspace hcl2hex <- function(h = 0, c = 35, l = 85, fixup = TRUE) { hex(polarLUV(l, c, h), fixup = fixup) } ## shading-generating functions should take at least the arguments ## observed, residuals, expected, df ## and return a function which takes a single argument (interpreted ## to be a vector of residuals). shading_hsv <- function(observed, residuals = NULL, expected = NULL, df = NULL, h = c(2/3, 0), s = c(1, 0), v = c(1, 0.5), interpolate = c(2, 4), lty = 1, eps = NULL, line_col = "black", p.value = NULL, level = 0.95, ...) { ## get h/s/v and lty my.h <- rep(h, length.out = 2) ## positive and negative hue my.s <- rep(s, length.out = 2) ## maximum and minimum saturation my.v <- rep(v, length.out = 2) ## significant and non-significant value lty <- rep(lty, length.out = 2) ## positive and negative lty ## model fitting (if necessary) if(is.null(expected) && !is.null(residuals)) stop("residuals without expected values specified") if(!is.null(expected) && is.null(df) && is.null(p.value)) { warning("no default inference available without degrees of freedom") p.value <- NA } if(is.null(expected) && !is.null(observed)) { expected <- loglin(observed, 1:length(dim(observed)), fit = TRUE, print = FALSE) df <- expected$df expected <- expected$fit } if(is.null(residuals) && !is.null(observed)) residuals <- (observed - expected)/sqrt(expected) ## conduct significance test (if specified) if(is.null(p.value)) p.value <- function(observed, residuals, expected, df) pchisq(sum(as.vector(residuals)^2), df, lower.tail = FALSE) if(!is.function(p.value) && is.na(p.value)) { v <- my.v[1] p.value <- NULL } else { if(is.function(p.value)) p.value <- p.value(observed, residuals, expected, df) v <- if(p.value < (1-level)) my.v[1] else my.v[2] } ## set up function for interpolation of saturation if(!is.function(interpolate)) { col.bins <- sort(interpolate) interpolate <- stepfun(col.bins, seq(my.s[2], my.s[1], length = length(col.bins) + 1)) col.bins <- sort(unique(c(col.bins, 0, -col.bins))) } else { col.bins <- NULL } ## store color and lty information for legend legend <- NULL if(!is.null(col.bins)) { res2 <- col.bins res2 <- c(head(res2, 1) - 1, res2[-1] - diff(res2)/2, tail(res2, 1) + 1) legend.col <- hsv(ifelse(res2 > 0, my.h[1], my.h[2]), pmax(pmin(interpolate(abs(res2)), 1), 0), v, ...) lty.bins <- 0 legend.lty <- lty[2:1] legend <- list(col = legend.col, col.bins = col.bins, lty = legend.lty, lty.bins = lty.bins) } ## set up function that computes color/lty from residuals rval <- function(x) { res <- as.vector(x) fill <- hsv(ifelse(res > 0, my.h[1], my.h[2]), pmax(pmin(interpolate(abs(res)), 1), 0), v, ...) dim(fill) <- dim(x) col <- rep(line_col, length.out = length(res)) if(!is.null(eps)) { eps <- abs(eps) col[res > eps] <- hsv(my.h[1], 1, v, ...) col[res < -eps] <- hsv(my.h[2], 1, v, ...) } dim(col) <- dim(x) # line type should be solid if abs(resid) < eps ltytmp <- ifelse(x > 0, lty[1], lty[2]) if(!is.null(eps)) ltytmp[abs(x) < abs(eps)] <- lty[1] dim(ltytmp) <- dim(x) return(structure(list(col = col, fill = fill, lty = ltytmp), class = "gpar")) } attr(rval, "legend") <- legend attr(rval, "p.value") <- p.value return(rval) } class(shading_hsv) <- "grapcon_generator" shading_hcl <- function(observed, residuals = NULL, expected = NULL, df = NULL, h = NULL, c = NULL, l = NULL, interpolate = c(2, 4), lty = 1, eps = NULL, line_col = "black", p.value = NULL, level = 0.95, ...) { ## set defaults if(is.null(h)) h <- c(260, 0) if(is.null(c)) c <- c(100, 20) if(is.null(l)) l <- c(90, 50) ## get h/c/l and lty my.h <- rep(h, length.out = 2) ## positive and negative hue my.c <- rep(c, length.out = 2) ## significant and non-significant maximum chroma my.l <- rep(l, length.out = 2) ## maximum and minimum luminance lty <- rep(lty, length.out = 2) ## positive and negative lty ## model fitting (if necessary) if(is.null(expected) && !is.null(residuals)) stop("residuals without expected values specified") if(!is.null(expected) && is.null(df) && is.null(p.value)) { warning("no default inference available without degrees of freedom") p.value <- NA } if(is.null(expected) && !is.null(observed)) { expected <- loglin(observed, 1:length(dim(observed)), fit = TRUE, print = FALSE) df <- expected$df expected <- expected$fit } if(is.null(residuals) && !is.null(observed)) residuals <- (observed - expected)/sqrt(expected) ## conduct significance test (if specified) if(is.null(p.value)) p.value <- function(observed, residuals, expected, df) pchisq(sum(as.vector(residuals)^2), df, lower.tail = FALSE) if(!is.function(p.value) && is.na(p.value)) { max.c <- my.c[1] p.value <- NULL } else { if(is.function(p.value)) p.value <- p.value(observed, residuals, expected, df) max.c <- ifelse(p.value < (1-level), my.c[1], my.c[2]) } ## set up function for interpolation of saturation if(!is.function(interpolate)) { col.bins <- sort(interpolate) interpolate <- stepfun(col.bins, seq(0, 1, length = length(col.bins) + 1)) col.bins <- sort(unique(c(col.bins, 0, -col.bins))) } else { col.bins <- NULL } ## store color and lty information for legend legend <- NULL if(!is.null(col.bins)) { res2 <- col.bins res2 <- c(head(res2, 1) - 1, res2[-1] - diff(res2)/2, tail(res2, 1) + 1) legend.col <- hcl2hex(ifelse(res2 > 0, my.h[1], my.h[2]), max.c * pmax(pmin(interpolate(abs(res2)), 1), 0), my.l[1] + diff(my.l) * pmax(pmin(interpolate(abs(res2)), 1), 0), ...) lty.bins <- 0 legend.lty <- lty[2:1] legend <- list(col = legend.col, col.bins = col.bins, lty = legend.lty, lty.bins = lty.bins) } ## set up function that computes color/lty from residuals rval <- function(x) { res <- as.vector(x) fill <- hcl2hex(ifelse(res > 0, my.h[1], my.h[2]), max.c * pmax(pmin(interpolate(abs(res)), 1), 0), my.l[1] + diff(my.l) * pmax(pmin(interpolate(abs(res)), 1), 0), ...) dim(fill) <- dim(x) col <- rep(line_col, length.out = length(res)) if(!is.null(eps)) { eps <- abs(eps) col[res > eps] <- hcl2hex(my.h[1], max.c, my.l[2], ...) col[res < -eps] <- hcl2hex(my.h[2], max.c, my.l[2], ...) } dim(col) <- dim(x) lty <- ifelse(x > 0, lty[1], lty[2]) dim(lty) <- dim(x) return(structure(list(col = col, fill = fill, lty = lty), class = "gpar")) } attr(rval, "legend") <- legend attr(rval, "p.value") <- p.value return(rval) } class(shading_hcl) <- "grapcon_generator" shading_Friendly <- function(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = c(2/3, 0), lty = 1:2, interpolate = c(2, 4), eps = 0.01, line_col = "black", ...) { shading_hsv(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = h, v = 1, lty = lty, interpolate = interpolate, eps = eps, line_col = line_col, p.value = NA, ...) } class(shading_Friendly) <- "grapcon_generator" shading_sieve <- function(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = c(260, 0), lty = 1:2, interpolate = c(2, 4), eps = 0.01, line_col = "black", ...) { shading_hcl(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = h, c = 100, l = 50, lty = lty, interpolate = interpolate, eps = eps, line_col = line_col, p.value = NA, ...) } class(shading_sieve) <- "grapcon_generator" shading_max <- function(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = NULL, c = NULL, l = NULL, lty = 1, eps = NULL, line_col = "black", level = c(0.9, 0.99), n = 1000, ...) { stopifnot(length(dim(observed)) == 2) ## set defaults if(is.null(h)) h <- c(260, 0) if(is.null(c)) c <- c(100, 20) if(is.null(l)) l <- c(90, 50) obs.test <- coindep_test(observed, n = n) col.bins <- obs.test$qdist(sort(level)) rval <- shading_hcl(observed = NULL, residuals = NULL, expected = NULL, df = NULL, h = h, c = c, l = l, interpolate = col.bins, lty = lty, eps = eps, line_col = line_col, p.value = obs.test$p.value, ...) return(rval) } class(shading_max) <- "grapcon_generator" shading_binary <- function(observed = NULL, residuals = NULL, expected = NULL, df = NULL, col = NULL) { ## check col argument if(is.null(col)) col <- hcl2hex(c(260, 0), 50, 70) col <- rep(col, length.out = 2) ## store color information for legend legend <- list(col = col[2:1], col.bins = 0, lty = NULL, lty.bins = NULL) ## set up function that computes color/lty from residuals rval <- function(x) gpar(fill = ifelse(x > 0, col[1], col[2])) ## add meta information for legend attr(rval, "legend") <- legend attr(rval, "p.value") <- NULL rval } class(shading_binary) <- "grapcon_generator" vcd/R/agreementplot.R0000644000175300001440000001407411720274714014102 0ustar meyerusers## Modified 1/25/2012 11:43AM by M. friendly # -- added fill_col argument, specifying a function to be used to fill the tiles # -- added xscale, yscale arguments to show the marginal frequencies at top & right # -- added line_col to change the color of the diagonal line "agreementplot" <- function (x, ...) UseMethod ("agreementplot") "agreementplot.formula" <- function (formula, data = NULL, ..., subset) { m <- match.call(expand.dots = FALSE) edata <- eval(m$data, parent.frame()) if (inherits(edata, "ftable") || inherits(edata, "table")) { data <- as.table(data) varnames <- attr(terms(formula), "term.labels") if (all(varnames != ".")) data <- margin.table(data, match(varnames, names(dimnames(data)))) agreementplot(data, ...) } else { if (is.matrix(edata)) m$data <- as.data.frame(data) m$... <- NULL m[[1]] <- as.name("model.frame") mf <- eval(m, parent.frame()) if (length(formula) == 2) { by <- mf y <- NULL } else { i <- attr(attr(mf, "terms"), "response") by <- mf[-i] y <- mf[[i]] } by <- lapply(by, factor) x <- if (is.null(y)) do.call("table", by) else if (NCOL(y) == 1) tapply(y, by, sum) else { z <- lapply(as.data.frame(y), tapply, by, sum) array(unlist(z), dim = c(dim(z[[1]]), length(z)), dimnames = c(dimnames(z[[1]]), list(names(z)))) } x[is.na(x)] <- 0 agreementplot(x, ...) } } "agreementplot.default" <- function(x, reverse_y = TRUE, main = NULL, weights = c(1, 1 - 1 / (ncol(x) - 1)^2), margins = par("mar"), newpage = TRUE, pop = TRUE, xlab = names(dimnames(x))[2], ylab = names(dimnames(x))[1], xlab_rot = 0, xlab_just = "center", ylab_rot = 90, ylab_just = "center", fill_col = function(j) gray((1 - (weights[j]) ^ 2) ^ 0.5), line_col = "red", xscale = TRUE, yscale = TRUE, ...) { if (length(dim(x)) > 2) stop("Function implemented for two-way tables only!") if (ncol(x) != nrow(x)) stop("Dimensions must have equal length!") nc <- ncol(x) ## compute relative frequencies n <- sum(x) colFreqs <- colSums(x) / n rowFreqs <- rowSums(x) / n ## open viewport if (newpage) grid.newpage() pushViewport(plotViewport(margins)) pushViewport(viewport(width = unit(1, "snpc"), height = unit(1, "snpc"))) if(!is.null(main)) grid.text(main, y = unit(1.1, "npc"), gp = gpar(fontsize = 25)) ## axis labels grid.text(xlab, y = -0.12, gp = gpar(fontsize = 20)) grid.text(ylab, x = -0.1, gp = gpar(fontsize = 20), rot = 90) grid.rect(gp = gpar(fill = "transparent")) xc <- c(0, cumsum(colFreqs)) yc <- c(0, cumsum(rowFreqs)) my.text <- if(reverse_y) function(y, ...) grid.text(y = y, ...) else function(y, ...) grid.text(y = 1 - y, ...) my.rect <- if(reverse_y) function(xleft, ybottom, xright, ytop, ...) grid.rect(x = xleft, y = ybottom, width = xright - xleft, height = ytop - ybottom, just = c("left","bottom"), ...) else function(xleft, ybottom, xright, ytop, ...) grid.rect(x = xleft, y = 1 - ybottom, width = xright - xleft, height = ytop - ybottom, just = c("left","top"), ...) A <- matrix(0, length(weights), nc) for (i in 1:nc) { ## x - axis grid.text(dimnames(x)[[2]][i], x = xc[i] + (xc[i + 1] - xc[i]) / 2, y = - 0.04, check.overlap = TRUE, rot = xlab_rot, just = xlab_just, ...) ## y - axis my.text(dimnames(x)[[1]][i], y = yc[i] + (yc[i + 1] - yc[i]) / 2, x = - 0.03, check.overlap = TRUE, rot = ylab_rot, just = ylab_just, ...) ## expected rectangle my.rect(xc[i], yc[i], xc[i + 1], yc[i + 1]) ## observed rectangle y0 <- c(0, cumsum(x[i,])) / sum(x[i,]) x0 <- c(0, cumsum(x[,i])) / sum(x[,i]) rec <- function (col, dens, lb, tr) my.rect(xc[i] + (xc[i + 1] - xc[i]) * x0[lb], yc[i] + (yc[i + 1] - yc[i]) * y0[lb], xc[i] + (xc[i + 1] - xc[i]) * x0[tr], yc[i] + (yc[i + 1] - yc[i]) * y0[tr], gp = gpar(fill = fill_col(j), col = col, rot = 135) ) for (j in length(weights):1) { lb <- max(1, i - j + 1) tr <- 1 + min(nc, i + j - 1) A[j, i] <- sum(x[lb:(tr-1),i]) * sum(x[i, lb:(tr-1)]) rec("white", NULL, lb, tr) ## erase background rec("black", if (weights[j] < 1) weights[j] * 20 else NULL, lb, tr) } ## correct A[j,i] -> not done by Friendly==Bug? for (j in length(weights):1) if (j > 1) A[j, i] <- A[j, i] - A[j - 1, i] } if (reverse_y) grid.lines(c(0, 1), c(0, 1), gp = gpar(col = line_col, linetype = "longdash")) else grid.lines(c(0, 1), c(1, 0), gp = gpar(col = line_col, linetype = "longdash")) if (xscale) { cx <- xc[-(nc+1)] + diff(xc)/2 grid.text(colSums(x), x = cx, y = 1.02, rot = xlab_rot, just = xlab_just, ...) grid.xaxis(at = xc, label = FALSE, main=FALSE, gp = gpar(fontsize=10), draw = TRUE, vp = NULL) } if (yscale) { cy <- yc[-(nc+1)] + diff(yc)/2 my.text(rowSums(x), x = 1.03, y = cy, rot = 0, just = ylab_just, ...) grid.yaxis(at = yc, FALSE, main=FALSE, gp = gpar(fontsize=10), draw = TRUE, vp = NULL) } if (pop) popViewport(2) else upViewport(2) ## Statistics - Returned invisibly ads <- crossprod(diag(x)) ar <- n * n * crossprod(colFreqs, rowFreqs) invisible(list( Bangdiwala = ads / ar, Bangdiwala_Weighted = (sum(weights * A)) / ar, weights = weights ) ) } vcd/R/distplot.R0000644000175300001440000001155411566471033013077 0ustar meyerusersdistplot <- function(x, type = c("poisson", "binomial", "nbinomial"), size = NULL, lambda = NULL, legend = TRUE, xlim = NULL, ylim = NULL, conf_int = TRUE, conf_level = 0.95, main = NULL, xlab = "Number of occurrences", ylab = "Distribution metameter", gp = gpar(cex = 0.5), name = "distplot", newpage = TRUE, pop = TRUE, ...) { if(is.vector(x)) { x <- table(x) } if(is.table(x)) { if(length(dim(x)) > 1) stop ("x must be a 1-way table") freq <- as.vector(x) count <- as.numeric(names(x)) } else { if(!(!is.null(ncol(x)) && ncol(x) == 2)) stop("x must be a 2-column matrix or data.frame") freq <- as.vector(x[,1]) count <- as.vector(x[,2]) } myindex <- (1:length(freq))[freq > 0] mycount <- count[myindex] myfreq <- freq[myindex] switch(match.arg(type), "poisson" = { par.ml <- suppressWarnings(goodfit(x, type = type)$par$lambda) phi <- function(nk, k, N, size = NULL) ifelse(nk > 0, lgamma(k + 1) + log(nk/N), NA) y <- phi(myfreq, mycount, sum(freq)) if(!is.null(lambda)) y <- y + lambda - mycount * log(lambda) fm <- lm(y ~ mycount) par.estim <- exp(coef(fm)[2]) names(par.estim) <- "lambda" if(!is.null(lambda)) par.estim <- par.estim * lambda legend.text <- paste("exp(slope) =", round(par.estim, digits = 3)) if(is.null(main)) main <- "Poissoness plot" }, "binomial" = { if(is.null(size)) { size <- max(count) warning("size was not given, taken as maximum count") } par.ml <- suppressWarnings(goodfit(x, type = type, par = list(size = size))$par$prob) phi <- function(nk, k, N, size) log(nk) - log(N * choose(size, k)) y <- phi(myfreq, mycount, sum(freq), size = size) fm <- lm(y ~ mycount) par.estim <- exp(coef(fm)[2]) par.estim <- par.estim / (1 + par.estim) names(par.estim) <- "prob" legend.text <- paste("inv.logit(slope) =", round(par.estim, digits = 3)) if(is.null(main)) main <- "Binomialness plot" }, "nbinomial" = { if(is.null(size)) { par.ml <- suppressWarnings(goodfit(x, type = type)$par) size <- par.ml$size par.ml <- par.ml$prob }else{ xbar <- weighted.mean(mycount, myfreq) par.ml <- size / (size+xbar) } phi <- function(nk, k, N, size) log(nk) - log(N * choose(size + k - 1, k)) y <- phi(myfreq, mycount, sum(freq), size = size) fm <- lm(y ~ mycount) par.estim <- 1 - exp(coef(fm)[2]) names(par.estim) <- "prob" legend.text <- paste("1-exp(slope) =", round(par.estim, digits = 3)) if(is.null(main)) main <- "Negative binomialness plot" }) yhat <- ifelse(myfreq > 1.5, myfreq - 0.67, 1/exp(1)) yhat <- phi(yhat, mycount, sum(freq), size = size) if(!is.null(lambda)) yhat <- yhat + lambda - mycount * log(lambda) phat <- myfreq / sum(myfreq) ci.width <- qnorm(1-(1 - conf_level)/2) * sqrt(1-phat)/sqrt(myfreq - (0.25 * phat + 0.47)*sqrt(myfreq)) RVAL <- cbind(count, freq, NA, NA, NA, NA, NA) RVAL[myindex,3:7] <- cbind(y,yhat,ci.width, yhat-ci.width, yhat + ci.width) RVAL <- as.data.frame(RVAL) names(RVAL) <- c("Counts", "Freq", "Metameter", "CI.center", "CI.width", "CI.lower", "CI.upper") if(is.null(xlim)) xlim <- range(RVAL[,1]) if(is.null(ylim)) ylim <- range(RVAL[,c(3,6,7)], na.rm = TRUE) xlim <- xlim + c(-1, 1) * diff(xlim) * 0.04 ylim <- ylim + c(-1, 1) * diff(ylim) * 0.04 if(newpage) grid.newpage() pushViewport(plotViewport(xscale = xlim, yscale = ylim, default.units = "native", name = name)) grid.points(x = RVAL[,1], y = RVAL[,3], default.units = "native", gp = gp, ...) grid.lines(x = xlim, y = predict(fm, newdata = data.frame(mycount = xlim)), default.units = "native", gp = gpar(col = 2)) grid.rect(gp = gpar(fill = "transparent")) grid.xaxis() grid.yaxis() grid.text(xlab, y = unit(-3.5, "lines")) grid.text(ylab, x = unit(-3, "lines"), rot = 90) grid.text(main, y = unit(1, "npc") + unit(2, "lines"), gp = gpar(fontface = "bold")) if(conf_int) { grid.points(x = RVAL[,1], y = RVAL[,4], pch = 19, gp = gpar(cex = 0.3)) grid.segments(RVAL[,1], RVAL[,6], RVAL[,1], RVAL[,7], default.units = "native", gp = gpar(lty = 3)) } if(legend) { mymin <- which.min(RVAL[,5]) leg.x <- RVAL[mymin,1] if(RVAL[mymin,6] - ylim[1] > ylim[2] - RVAL[mymin,7]) leg.y <- ylim[1] + 0.7 * (RVAL[mymin,6] - ylim[1]) else leg.y <- ylim[2] legend.text <- c(paste("slope =", round(coef(fm)[2], digits = 3)), paste("intercept =", round(coef(fm)[1], digits = 3)), "", paste(names(par.estim),": ML =", round(par.ml, digits=3)), legend.text) legend.text <- paste(legend.text, collapse = "\n") grid.text(legend.text, leg.x, leg.y - 0.05 * abs(leg.y), default.units = "native", just = c("left", "top")) } if(pop) popViewport() else upViewport() invisible(RVAL) } vcd/R/doubledeckerplot.R0000644000175300001440000000547311720271060014555 0ustar meyerusers####################################### ### doubledecker plot doubledecker <- function(x, ...) UseMethod("doubledecker") doubledecker.formula <- function(formula, data = NULL, ..., main = NULL) { if (is.logical(main) && main) main <- deparse(substitute(data)) if (is.structable(data)) data <- as.table(data) m <- match.call(expand.dots = FALSE) edata <- eval(m$data, parent.frame()) fstr <- strsplit(paste(deparse(formula), collapse = ""), "~") vars <- strsplit(strsplit(gsub(" ", "", fstr[[1]][2]), "\\|")[[1]], "\\+") dep <- gsub(" ", "", fstr[[1]][1]) varnames <- vars[[1]] if (dep == "") stop("Need a dependent variable!") varnames <- c(varnames, dep) if(inherits(edata, "ftable") || inherits(edata, "table") || length(dim(edata)) > 2) { dat <- as.table(data) if(all(varnames != ".")) { ind <- match(varnames, names(dimnames(dat))) if (any(is.na(ind))) stop(paste("Can't find", paste(varnames[is.na(ind)], collapse=" / "), "in", deparse(substitute(data)))) dat <- margin.table(dat, ind) } else { ind <- match(dep, names(dimnames(dat))) if (is.na(ind)) stop(paste("Can't find", dep, "in", deparse(substitute(data)))) dat <- aperm(dat, c(seq_along(dim(dat))[-ind], ind)) } doubledecker.default(dat, main = main, ...) } else { tab <- if ("Freq" %in% colnames(data)) xtabs(formula(paste("Freq~", varnames, collapse = "+")), data = data) else xtabs(formula(paste("~", varnames, collapse = "+")), data = data) doubledecker.default(tab, main = main, ...) } } doubledecker.default <- function(x, depvar = length(dim(x)), margins = c(1, 4, length(dim(x)) + 1, 1), gp = gpar(fill = rev(gray.colors(tail(dim(x), 1)))), labeling = labeling_doubledecker, spacing = spacing_highlighting, main = NULL, keep_aspect_ratio = FALSE, ...) { x <- as.table(x) d <- dim(x) l <- length(d) if (is.character(depvar)) depvar <- match(depvar, names(dimnames(x))) condvars <- (1:l)[-depvar] x <- aperm(x, c(condvars, depvar)) strucplot(x, core = struc_mosaic(zero_split = FALSE, zero_shade = FALSE), condvars = l - 1, spacing = spacing, split_vertical = c(rep.int(TRUE, l - 1), FALSE), gp = gp, shade = TRUE, labeling = labeling, main = main, margins = margins, legend = NULL, keep_aspect_ratio = keep_aspect_ratio, ... ) } vcd/R/spacings.R0000644000175300001440000000344311566471033013042 0ustar meyerusers################################################################## ## spacings spacing_equal <- function(sp = unit(0.3, "lines")) { if (!is.unit(sp)) sp <- unit(sp, "lines") function(d, condvars = NULL) lapply(d, function(x) if(x > 1) rep(sp, x - 1) else NA) } class(spacing_equal) <- "grapcon_generator" spacing_dimequal <- function(sp) { if (!is.unit(sp)) sp <- unit(sp, "lines") function(d, condvars = NULL) lapply(seq_along(d), function(i) if(d[i] > 1) rep(sp[i], d[i] - 1) else NA) } class(spacing_dimequal) <- "grapcon_generator" spacing_increase <- function(start = unit(0.3, "lines"), rate = 1.5) { if (!is.unit(start)) start <- unit(start, "lines") function(d, condvars = NULL) { sp <- start * rev(cumprod(c(1, rep.int(rate, length(d) - 1)))) spacing_dimequal(sp)(d = d, condvars = condvars) } } class(spacing_increase) <- "grapcon_generator" spacing_highlighting <- function(start = unit(0.2, "lines"), rate = 1.5) { if (!is.unit(start)) start <- unit(start, "lines") function(d, condvars = NULL) c(spacing_increase(start, rate)(d, condvars)[-length(d)], list(unit(rep(0, d[length(d)]), "lines"))) } class(spacing_highlighting) <- "grapcon_generator" spacing_conditional <- function(sp = unit(0.3, "lines"), start = unit(2, "lines"), rate = 1.8) { condfun <- spacing_increase(start, rate) equalfun <- spacing_equal(sp) equalfun2 <- spacing_equal(start) function(d, condvars) { if (length(d) < 3) return(spacing_equal(sp)(d, condvars)) condvars <- seq(condvars) ret <- vector("list", length(d)) ret[condvars] <- if (length(condvars) < 3) equalfun2(d[condvars]) else condfun(d[condvars]) ret[-condvars] <- equalfun(d[-condvars]) ret } } class(spacing_conditional) <- "grapcon_generator" vcd/data/0000755000175300001440000000000011720426624011612 5ustar meyerusersvcd/data/WeldonDice.rda0000644000175300001440000000031711720426624014320 0ustar meyerusers r0b```b`cd`b2Y#s1WxjNJ~Kfr*3P!]&~+ dS@Jf\ FJ%. 30a c0acXP[X; ]U'n((D !\` `4ey0d* :&d%AlU0Ahqm$ 5Qj5H1/?] !9T1656sLu2&&pS])\T.cfkf@4JGP&$B.XUTfvcd/data/Saxony.rda0000644000175300001440000000032511720426624013563 0ustar meyerusers r0b```b`cd`b2Y#s1[pbE~^%3P: J>- =;_@ZڭB0@+S2sACxѤ9y@CA0!ac&0)ac0%dhgYFhc:(x&E+OI,FWZ Q~vcd/data/Bundesliga.rda0000644000175300001440000015070311566471043014370 0ustar meyerusersܽos\u滺A ȦĀ,whB֘HedI*JyKK2E@r7lF;醓yuQQ>ϳ^{?U5n]fUw.^߽x^u?U.//~O.~.~.~/!C^@~k0O 8?:8s#6ؿCm9eydg!(] x=?'~GVxwu!RGu7b)v5[w`{ {p 0p XOY./˧ uY'.)uR ?^?O/M_ /o.:^=|`Uj:ÛpIy]+qngqz;TȷMXZOr';XX5q纣k'Vpʷu|P9xgu:<č'*Խ]^Hk\_saX7@8w7,;vzv%V|;cg*kb \s$ rn51_GW7q<V?4ş)9YgQW˱MX&n<^UyZ=0*.v׭[_gO8Gv8Ox ^ 8S`o[5T,u&YL\dk8?u=\b*xg˟[qg]]:ΰcV>3'zd:|uqiy֭5,nSzauX=}+qz>^eXpnU+aܪֿëb"ĝ7q}b9Ai9ր9Zago:<~ |j58 xn!w*}~Ա:7==BxP#|^Ku~,qGÚ!+ͼVc= A殮CI rx3IN/x֣j<60uXsG>]oW;ǂaj{ZbzBMg;0ȫuXA:~o!8q5=:H0bWWz9vfΏSC` ݀?ή0k|r%[}?8ßm|Du{PWuuGc=Mܠ/$6l'ެZOwWz jwb7 =۔NSX=xh-88l#Ջ8_ƙz)~85לVk3^o8c^]Y$gqZǟ)Nżǟ)Ib?̟SzjԢZ=逅'{ɰv?߀p~k^L}nA݀<33v}<=Oz͇??1]ky\>+6~9[j]tZ7/N6ZEܩSxẘO|}WreLnG`O:8qlQzqy9ea 3ƺ/p摰V`d"ta<LuQO7[a}m8?k;ݿj)eO;]ux؋ 8)O`ˏՓ))zXӋYoI}kߛɁE'Z |Ԁ Kڗ 8?(l_סLMv^g^xų/LN :Mxn]Ƴ ;x{*\>ٯV Ŝ !l05zX1/s &{%2?jy/b{>ϻ#tpL⁵j7vF3񸖳KbM`q]Ts;S Xωu_v'}Xo ?8œ a=?Oak{QLJnygU=Zu1ϪUuy8q}Jy|r8˟`OGp\qn0㳔㗲Oj+ГxB0 <52KHg4B?jT8<cjȴ {Ov7N/:=TLya{0,;1]t^i5/kܭƟǧ󳱦ŽǟuܙT78Î y.pǡ)^2G5l{+j5mE2]Dy kq6p:mZclk 'ıoT;&4gXiWp8z8ԅu)*/YUL?a#˵|/{Z ?`myHة:p< 8ikbq:Ǻng*kzpl7 {:cĖ{u[y!<9Rkvtns~/sfVc`u NƝ\%\Ysѧ9:mDf% 1M&q]WxNXCW?Ћ;5)yH1UǶS+γ&Sq9v9ѱr"׭-Nk%valwk9 ͫ}>q P]m>9)Ї3`s(ysp޶ zn PCaI)[Hk.`#Gw[2=tH?K:a!;UҮX0|8#pߴ] ҋu3i1[J~zf}N,H 鶮?`wלpЇڔfSgX?0YmLróuq=?WxIYftossn^ǟLqq'1z"WgA猓l8pﴮyqbɝeOts5^51{9:y f/0|n}6߮񽗉Of0 tv\gI?^rl~;t[O.Kv ͟)J;)z8j1 g8j?xs?@ 3\xL=9輀`>rot;cS5ggOKq~ZL3(Txg9E'4sij^U3#w0l:r9_c$z,6Yc8sؖ"|q>3k8ﰦ9i;1Nڴ.=|Cu<ߧ9+o yς ]0gcX'jcb=p_ͳ[޳XΧonNjo.''ZgssR}Yx%&A'c788ef^h"5xOL8uw8u2~x:bڳz7 =/5?}]ȲslȲlr"ϭ &3E8p\ϬۮpJ0d+XؘvYݒm?pSc̉2l 'c{zⅾ胾'?a9 7[=buJ?T  e8f>~cfq~nטCiׇ0 YY˛uF 9j<;`>`|g3Zo~_X'}'¾pHomA7| Ϫc պ7~/>u_|۴0+&Gg|P82:DNpBϻ>[or^d>_L]5ɟMqVܝj/V?vğ<Uɀ3&xƠWEٰa^;-yO:yScx \<JqxxXvUgc~:>\٭iĪZ0ŗ <3 +cxSwr:¿j߼|1GJx<{8?rc5ȦoΏ}+`LdFCk,x'b ֺX;ά=̓|NLpz}ȉ\D!7S[7Z-{!==sr_8'{5_'r ^ sjZτXpqg{YC2Ϟ=RȭpV5>q)v/=pW&5`ڿ]\g>Gҗƌ\L `a|o%HD:X|y+s%-{Y ^c^=İ>},Lz˙CRd;gWzs "j98̖wq#N?՞Lj; 6p-g‚?v 0P$õPxpы3v+6~vW gޯA6z{اh!u| /ғ;; l߉drv>lUW*|y#c QLXmr}6gC?ѝ~?/Cs:< U>gZg<0>·EmW8|5k:<=uunԺs9p=: gO/̫}o)yh̕m.a 5#zFq\YO9ς laS?'Emo07$ގ59|<b|לNipݭg^ybYi52#߅@e^^Te;sΊ3lպgYH u6JӋ¤6!ZNa۪; V/9ϼPCXAG|yK̼3`Y7|g=\T=O#̣uZ_ k]XjU^M-D}Z9/{r̨ 5:U|Y~2"6 w{kd+YⰪq>ez-L|Wq\U5c'W'2T'p8j{'?PHXܯ>?S~,)8V6},8j}%su}N`rga=Gkm k7yI:~-rIqy 65v5.Uۿ\\?VOwPOKsH+xc^~K6qSm#g, yczcŘ>DEV/X I؃cyh%]g5֋02*n_j٥̽a xL}&?=˥5{'z¢ ]5~ IK_5#a 9鬋>G§ }>y]j72˸Wnd {OP>'þ,z#5Q8/߫Ɲa xcW-ju=z0r~Ω=%OO :P!?6LcS4=ő0=w{~O85gI|T_%άƳlzu/ ]gY/yzvl> f>8<繫B3{2a-Ag봨VۨE0󚧱QYϯg`8f{0/PCcP',=D+1 ?Qٖ{ =-ᒷؿOA1BKk<{Z;q_<3<3a=:|W?6F1[!6șaT؎.O:8TX`lx&ߡg/?g`& ZMF'x&&1џK^K\7L<,={M?xXbxGf>T?P^S!WEJg8E|I۱k/p^Zb?zXse<0Їյ^p=Yr׳Vߧs$j ?:18[Ыr#g%%?ΰlgZX {<N3G8G8Ô<~_rc_\ݪεsl70ެqd|S8V0eటOlv[xa[(nʇ =zl=׉.)/{nUu9jqGjnl,<yzh֤0'~ý: uAX~=yk>xSi)N\=>}τ&>Kςa\Y5Ray`q`U`QG9R`vjL#v7V'^|"g q]Tۏ{: | !/0o ܹ>[/7ݷe\NVxsvwo_ 7%/}Kߟaxy_<~wg_l$oWy?wٷ_z|Ͽ/._˳^~|6ݛvvՋW_~?ߝxfg_~_{b_>W,7~;?|/ ݫ?8׊{|~훷Ͽz ׫_+݋Wo/P߮>?՛/g/Οb߽ċ/^}wow/Qڻ ۓ??0ݫ ߝys_o-xy/~ O~}Yxտ~ÿ>;El~o.Qf\ rY_R ً_|5~y?]D;r;~onݛưtAo}]Xo)OV\3Ņz[bwoŅPto.21zvCoVpoY{Tz_˗_[~?\`ͻoe_ۣw~W߼"_oߞ]"6g?wAoW߽ӟ.g_2J/_>CE}˷//Jک?*%;wtoԸepV۽o ײq*өw\_~w>Gj'վ!/fßw'[x~g_u:Y|G;,k sbxjicF<sH{&Yz}#Ú?pzg}ƿ_G%_O>bf\ǺDžE~}x2lX9pAt\GĊ5*W<9;'^^x3a T`mN0\rW:vGޏ?qk%8w?5Lu1;xSq/}g8 3 j9;8==8t9Wbi^R{/\Iߣ 8$R0x{uUMٷ ^Ͼk`pbݚ yI~5΅ubO;kfb'y6r㨃>غMO+qnNq5k eCmxzߪ0qZy2|\Ǽ%8E{5[8ȼiS̳^]Jwt%GW?O#q ?vF fO=]nUu'5~ r~.l1dײ` Bޫ#Ppɝ}_‏ Of ;f(w7Ʀ$NV5gԻ =4YGKSd6*SpgS[bZn p |UUKaĩm 啰m#=j=vCpvgxf8)dCGc.o!om;{14Qm hT{gkl91?]ISb-`)=?v5հɀayf0X'[uZ0vf\ո/NkZtfcɀ56™jt*ְϼÇzu )|o9(q_3a%_TQZ3l֘}8<` #8~`Ù5M <.UlfgpꪏA5m_}ɳf [79j. S5:XWId'/qXAѷXֽ% g}tXo>sܑ'Ϭߔ2y:.'}jOգ']Szá8em\+U50Oo!%|&.kp8j`Ϸ;K>vt*5rTvjR׳\uZ>5<g5`or?6M]SLS+,=c0]ɵ]Ƀ=Aۼ[Wm[M`Xߟgyָ/ԃuQ=yǥg õ ɦ/VB >1Yje7q81rO&KXqOqPlz՘=;Kl5+' 2n/.u{yZ/c o [jʁ s#{:`?j=ms [+Y50Z#Y|B~Uclk`x~N_zpC:d\6GN6\ìfkd0&`^|0,O=,l<yiݺ^&d8Fq?gɼsV({g=-a|0!gX80f:N`+؄>b{6nro٫IVZ@:+\ɏ\s|3bo3ɩ]a} <>Or:m)wuxhEk`Vu"?==1&T{d? {Z'/݀ȧ?/׸hoC{!>Д ~`Z?cIi#߂1}5lBoz`Xz"ğMdž|n)#3|jq_0<'f1Gվv>wm7-9fƽ_cSnO:aNa[kM̒O-xRj3llus>61ğ<ހSŋ5NX<=*õ`N/vo槾8~LclߤO s._@ܫv:jp57rWs]Ǫ'µ,OYi}~odDO9zFlZ8jߪ/c{~`nrv×}~!ۈvz rًg\7-u#u;*AG>:JN9?f1q֦[ɜ qOHKzj0zo'5֏9bkᢃǵGk0%9i8%oz}ebYR0i5̥loa_Qeb;ݿG*p!'qGX5e*wOcA<؃8=]L!j/XGo %=q_`YP!A0X}ϳ18l$1ovm@{c{݉g|Lzڳ'j-zC덝b&u>r`a}Lop3m}ϳj{O:mk3?La.ܳMqǟ?ޞ?dw/c+v(L5o g2'ϰ{u5,;A{31Hs$g=9 `c~!FW560[T;)}aY\) vPSkܷphZk͡8ݓqot`B+ &yτ;#֘M`xL%_c>4G_bOC<7s|aYrgCp]IutZ_g 1Bzd>Ϝ5)wa={}lE` oPfl|lgyIvָ=~ྰAvr|nuMท貮ڸ;Ef:[绞?ȱ7K|FpuD@e:܇%dpxZXG<~'\[u>DqF x`{Xg_}bmc?6 yZLۄo[{όQCί;5VgO'cK8NjЏ;x'|~m|VW}23y7cz>6.}{{{~VL赯39< ^`z{y Sa%8 A_Ǧ]gL;d{ufNԭψ%o[uV|TXYT$xӁsCEb9_FoơŷҟoX!2Tvw}a& bu{%ާ_To{*;jO}fKNn `YSɯ:vAo%]AGϟ8wvk`ۖt3a3`"{IlЏY{K$֘WV;#cnpKoi\3C0s3a9SO/fwYm<֙~kOa wj9|bOFrήpݗE }ϙ8Nߒ[IݩVo<;c'}3a{I;^.}_v]{@lی^ష&y=G70>y9 zV{6ﰡG0>VC;GoQbmz y7wbz.xݩv~:lح>IMbe܋Zx@M@;5ؠ ܤ'yҳYXVC~ygXc89K7k`CV҇]CvoFjpJ`s3Adj{VmߓO ,|ơ 0Mp;p%g` ic}J n]Cԧ=<~̿Հ}+~?g|8b.P|/q &>"SjU؂zM:&6/1Ok.1wtݩ6 }aPkZʃߟ-j\pnėD`3g0K/| ,u-["<ξOLqGߣ#yld}bĄ:qUK#X o=I>^։u!>^Y yk\|ìIܮVKcO8;57*0]*&LY܆;XD̅{֝p0sfO/_Ak1q1wA9 ^E@O8р,vg8yy_]g[Ϛnf@ g?mHQWH\prM|O\ksl'Pk\ؿ39 Z@=E> 1}k]s }8ہz0|oZ|U8ȃMt}zW^+;N,IGCꇯ%N,,zmJyh_6B7|*IU" ; ٗVXd^ٟ3:9q,[X]V҇u/ bx"yb#spUW9lEnç5|w|;MN`q1}fz˞Y=q﹧Cj7=۟V$>yg3u>. p$O]@'VۃKV}>}(j16K '硰Y!߾pc0c.}a{'|J̫>O9ֻc,sy`J:syV{ո{-{X_ p!ǔh;cs0x)ְ>滑VҙZ\\c7A-XkG,kD+RCN zjMن:.j9ڬP c)jstZ;sxc]a_.}2r.p"Lܠnf\Iv}u'k|\v |{ {0=Ə[4`wy8`R~\6=% u>'5O'y/A/ð {wW%KI XUzCl'5;8&'61j=ɀ?5{Rg8ۃ # yp1oUpl5i}/znܠ߄kgzY.r6d`_л5>=CAEu'cƙUkZ=ƽj y6:O}.kޗgNzVj8Ч]۩^DW'3{s\L^gBL?q0 e5`+X3Uz 3q/У{̾d̞3>5j=|".ɗdX n}ӽ t&ʞ?؇0U _әy߫OyϏX"}1/@w{,8^zO++؏%O carM7mz|f|ͼ'Gf Nqmlts^ u2{a~9Խj7>ܧ5zaD2kp\_74pc}|}҇p4plj|3{:.҃3dq#NC ơgle8t$6e},:8`v>~t<=* Ls*ϭ 83}=~#s-k<~\ȽdRzo0ݎؕ,ra/pvszsCzl߃3a"|_?X85|#{"y}_vfϦR/헼C]_#N-=a߃-+Spsqvvk3q^y}8"y|'vr{r9q \s w,Lf>Gy|4}r ,d6Z?٬' vuoVaQ- 38U98Cl̀ú7>|ܫA}rܟR8^?0}$cv 7_-A?s ā}X՞]9YƼ~lW;p[.:baž]8=\̕^bJvGnn ⊞j Ϥ_s @k"srgdk /j9<v  rCa!r0= XMCar~~;i.3$GrT-l}ϝ,y ϰC>)5??,#F)ً>u{̣j\kG/@][`ԇUyCsWҿ[[Fp-3[A|TX:N@?e^Y :9T֥o!LbxWj"{u|g yO8>lgsq/prOw&q!QEwԻ /.q/3NVxsvwo_ 7%/}Kߟaxy_<~wg_l$oWy?wٷ_z|Ͽ/._˳^~|g4^^Cjwgś7?[}~vKݛ7ko߽b߿ߡ~\g^ŹVo߼}fx_߾^W_y^z{~vw|<{wu~w[E$^~߿{3{_マeޞ/Յ^]͛ >zxk[&ޯ [xHKo#o.b/Ʈ_o}s_P7z_\ꟾbo^|uvoo.w/ w"Zgߑ㿼~;p4}^ \{’__~VHWo/ž/./޾{/.\ ۿ>s/a׳zcFg2 ן_ҋ?Z\ۯo}.^/I7g/=Y=9ꅅ}JݟtA/>ŗmQf\^v_}}]IUm,ߪ{Cۖr^ߊg_ZFut=jcqccԑgZ55Sbތת g56u~Ћ5gq k~K2^2>t}u؋yo?ąZpKr-f0lvyupjMsFגk_;̫#TfČkm| ky]C&c &p{f\g:V`:^ѹvKc{r ƱYWիCirVe{ٶ`՟6{[w䩃s^?ۀ7?3q߬qrz1zU)z!kn#sM%kkboV]˵:^2a둵yVn k{5r?=1ʘg?ox%f+m[jw'ٯsݽĺ%u5z|~=W wƾm]3~ y-۝'佐}(neY};u~{Y{M/3SLu# ^d}!5 ƺug$7zr=}\^sl9'} __{W!Aڷjle=nE2_rzc<b[5YgYK ԣW#_'ưm{*-DlgKdm{9{dJ]l_Vkv`8vY{=}߫Yɋ=^$F2wemٝskΟj~O{Y:g׫uLݧr9{3t>gx遲U~ƪjܯ{tves.|m/kl_#)޸7˺t#qsސϽ3g,woc^kqHNX2'wNrړWտ'^ݷYzyn'˞͚39s;v:z~u3쪫f~.7kCǬRל9mMl7U7gontN͸6}kz{f96+SulW?%W5g9bo}Mz'SzݫS_S޻W߭{]vj\7q~j~zRq}F϶'yzރJXkX#kݬGf}\Ͻ3}p:|.뽙Ⱦ=ژzfUc?9&Yo3DQGUz7UGz{S?}/sPXGx\+]Gv=:eW~LMo6\CgVqO^dl֡j ̩gMe95W37c-c]WnvzM;#'\}&e9|+dz6em'j'd]+s h|c<=Em)3<ףkooՋog}7ާΩ^.o̴Xn*~3kXSuײ߳}{gYc81\oU8}Sa|j>jW?2G]'|V%gd^[y4nsKGf!cޫ;ֹ&v ae@grӶ87{8B=YVyg߱x~}qw9't %}6]܎=%f׋L~+p?c݌k{QϬ؎IjcX|j >(>57c]ϝ|֨qnfO2{#^n~iݹֳq:3ߪ|^oeH?q>̣js8=3vz-+z{ϰeNmU䞕٧Y~yk/{{P> kd]Y>wOcy79aswW?R8r=\{kLL뭷uN;3v%mz2eCrs d wۓ>܊Ёώ'1Ǎx?VUs%y:5Oc)>QWcQ&?9.u;!x_saXWck㒜8?o6?S̳^<g߈bny\1W].^upOz}Ž@oMzdV\k}\W%9ls_Ucd Q>\t,mco'{2E+=:$]:X7_zӔ#usrǼv| igV7ڬeDZK<dNgFөɸZl[3zk+8k/Gd~)oG3'X5ֵW󺪖CYדּ=۶8kfܓr=}u짶ρkѫ?SﲮN_+D=q]c_\uY?~ȱ?:[ohx_znBxϘ'Oχ%]s7+ۣKx~=&amvޟ=3c|s{~絜+㔼ճ'=9zκ59{}yM Vy٧YyF5W]ڌ_ﺴ1slU55gu>8 _z=_uwO33yd]{8z$瞐Xܵ/|`Zc0/=q² >{Uu5+G.~/޷쯊k̷1AwUux~z}ol?3X}ܳ>'52vK{<սaɮܗ'yY`|2W|!kp 7+ql7:6yxjtu_rX9czje՘_wKdz5v9>;8^gD %y <0aOiYSgF&M鬙߹^u*~\{\Xٿʵ-.=.lId#9ٵ5{gj3/}`[z}̺czslUkb~YǺpk{+krwڗ{Es}\G/G{3oܳ{A﹭k}zo1GzƬ+=]Aۙ9_s}}*gr_7*)gھuyN5iwR^;wg~`:r{m4z${c#_O':֣5-gdr&7KdS{lNԵg?ԫw?|V\߬{xƭ7uY׽^ O޾Ï+3d{wUWizϽ=ۜ7K~u-h)^P5^;yXoҧ&ޟ/{Uc܇2.[qMU?v-}匝>h_䞗>dt?#zsҟ|ސֽ_O=t'= ˏorS:eȺ{u}̗^|׭s 5N?`K7sݹ<5?Q2>̳^&[q;xñL^ǺKrΐWg(;կձك}~2?㱦s4`fM2VoWgo-zr6z浩c՞zOe rO~ۃxu5'9o˙\<ϱ2Rޑ5J̬5kDꔳ)=~?O^ˏ^,lkom={vkh?=}m1Zwmoߌs+eS&Y]]g'͐72˾Ylw&jmί:"׻rvgSqz=s6ߨݎ]5׸^K_o\eZ<#d9Şًma9-l}5Y̝^=0SYcڰ7ݒl25Υ ӫ3Sr}xGގ=]3/rȾ=IE;={oE6!,"jŀ7ԀQFD@ (pQn] %Hd a-컌 {TTzͩIo\~z>3]UNzg~*}o06ja1Mc껅 C C7=އ4{.ưn8pKfʦqUրsUߟ-9Z~A Bݳ#p`M_c|M1Eue/?V:F/=3+6O]~S7i\7ƨ܅1Z52!m~s8|cB0AwR([:6 |,ڀPƭ1:p;UH}RڰTk}\/PXuNMtcǧa-IU΍ wx3H>Y|}Ncڌs6qk7 5 co~?i6췎?Zj7'sFjΝ_j3q9=c8Z ~r16}AvPhY`i*o^Ә4 s`n|JykوC}JXKWhV^z.7ԯ5%Kc5cvw.P[qCV}KL}&چڄaȾ4 cnV Ӹq*q:p]uq6ns>9􌮅/\S_r{DGW||~ri|x? ǘJh\r~ʆ!')tXkVN1Iۊ5h VSaq^ۀG9Ck3u8b]1oGlYA8q6Zvtkc#?1f1 C7xs?r>D E.qޢ1oP p=~nIDc-mj څ: j.~ڌZz.։q~ڏ ]X?{C _4ݣkmU[qs#~bOox}Jڋc}!C˦1 ʹ\)]oN6n]mvtia^w!ˍ{(ݟ9IM9wMuǧJp.O!ۆぶ7@ m76v!(u+j<zO4uj.?w0Ƨ5Q +UO8[!]ZU%Ayxjch]06X8.p>87&A9Aqv`fpI5* 0N ډe~ƭ5u.%-pQ?]tZV~F1f/-c,ñxj t霮jXN9(16·h]X>1n;_Fc6}r$|My0N95cj3W.ƝPGۃusmQ)zݓSѸx}U C7e9c;}:2i;1fi>!zM Wa^ϨN'6q1{|?'*]. C=rcb*Q{iwrL^o ϣxڈU1c0ui4 9ԏ/c~b ǂ{G7ԖS FR jaȾjAu7ߜqƾ @rUmvpqgW%9\g7|=vjW>E~SgWmڀmE?bpDÍ 5&0Һ[ZPwT 8sm¹ #Ur1iù*4Y[Xcֆ4O$Σk4Zg0J˳6<{_X!?cʏuc8UW׷Quʲ>SL,3Q]X6$CڂH>P=p|T3hsWtmIG7? K7 AUFk*-㜖Y6)>ϯcuT}M4̣jNOq;8gy+nX6 =d\N 8t\.Aޗg\a_pp{n!j%ڄk,j3#*O3Z4^C__ j=NJ}8u>l@ŕKrmD?Q{lS:{UkZg9={TP\_.ܨ߹7=77pSU2ұ`@\u3f~Q;3DyhYu|bmQi!kڐd}UZ͇Mur~n88ty`ΡbBxq^V?C_sHT78W*?-C57Auìxok'j3W&^Cr3{VCXqNו\_qqA~R{Ĝܽ{nm7n?;mܽU<_z]tgGw^ TCA܇cKտV/t w}a˭wwY'8p~FmlHd'-˦|殏zDe#w0d{9[UP۸JdjTmǏU`TG1PՉʶGsߵ6Q#iL% U֡1{0Z{\}]Wce{]~+\"S\Էla<ѲBR˓2۠̕}kΏ8ݰL硲t(@mXEUB,-oϫs wQZ.p)/ 1 ^7:[n- A,]7`wj\sX&wIFiӵ MC׾tJ>*AV;:Qq)>֓\9`[mDZl>sym8?o~U58scLc7NUk6xRIY6r3gGy`{V=4*k#[pycQym@>.& ؇Y86%\>n'wcŲډc|k"z=ǜ] 1W? >ô8sk5{7V~U0x/9$sV~Jo-_qQ7G`98}̓vcg(8vrPw{\P}Tϸ'j1Z76h\q>8Zreօ}Җ㯹эc~k?j!m;=PT:}ǹ6qx|}R6ր8537}_cN 4OǍMn9k6 ]p76USN=7>>T!3rPsLCeΡl8fWiUVAP/h~7~GahW5 N^ Ush~z;ZcaoF߲T=a .9Dpk?NІKϷ6􋵖# #GNx[>nGJ"[:k|nHvT$y<&sSs6qqNc_`=\̃c'P]dXڊ:SPVV*&☾TLSrJD:g]E+81h$8=CqNAo3.n~3c IqCai;9 Si[i]xu۸1އtNTEϸb7Xqϟ(Vbpͥs2Nh9KUwuY] |b/gr`TsUS}aLP۰^, qc{U~6Í{n$U qn.66a9}0ntS՚^kiXέ񨽴|ƲO[\s+)7}ܵ3>D-Be?v`}ps-n 73\,qh~=r hٮGtN_vUZ~5j+֓HCq c \{P{lʡ~zإ߳ȀXӘ:'mh0~./aաvsq`g:ډ}Z}EJ$sb]n.sh7xω:=X-i*=7YzփmT5 j:ڎk7^ս~.9{T'ZCpi\*퇊LVscۂeZ'׏nqDڋGV9Wimm\SD>y9yӀI{h;s6>8OcqcW4}ڃjmXQ*2 ;h^G869? ,<9Nۣ5h|緞Mbc +kjrg8/ ; 5|-ܜs wk^kuNq *78{88ݨ`\%D(+,{ŕGGöƌak&Z'QٖO+s2-7jqn~+-[W|nq0eͯ4?։+:iut{&..>>ȭ?8vPrs( y߸ءjմ|nc9?}\W͓x.}Ʊ|:h[e~Pyc礊p܀h3701+j\jj'9A﮸øu~61Z͏t1 - |NK=DNیGrx|Ms>K8-Fmڮڇu_ewe ͛N!q|pnyŹsAQz\'1օcmtfGhp!ZRr&0JK$X>G~U|^º1y-њN5'rXn5[CpjJ1pUr\lqsHD[׉|Kי?h,`{_h\3JG\\sk\rkFW1}ƭIbˣELz.=&6pI:|,D۬"- Ǎ_g+JqmV)4&m3^qwk.wڮYY6sߨ_`>Kk-՘XDZ6c^̯>굎kZuU>esߩDUv9ʛ跒}w0><57a,5{UUk 8T]h!Xm }߸:_maÐ͍lu^ڇ8oZè#\y8U1L\kk֎0=ա/8C[}z>{|\  Ahj']p,#Q^nA >TygÜ;3=7QkTg2$^[2\la| /e9Wڇ>>4Z\ t9MyTk?@V^u>֩dU=OvYzu 5pQUcG:shJ3 EMx^CqƍqUlrd^wɍo\$&ϳssiUWFu&pm:p=bǸ:,>DJeM˲ڎP.=+n_>Xǭg=@[ 8_2PP-0JMuA7W~'-)-ۣ:S*Q}1%C&oO\=FPrNq9\:GbS.hFu}B[zۍk l?_nZ`?'k!i[PcConF?K(yPև6}] qms>RRP5~|KTòF_p~ڢZW:U~5m5ƚ5[ay=^41h\}}lG]|Ճa`˯a4 Z~19➖~._N9gS?%x>=:~^ևD>PgnN`[T㶬jraT3!FQNU[u4ySp@ }QX89?qqAm2>uL}JWF';W>j7ne`۸9;.yXݬrUYV>== uاxO3oV}g6$Av)Cu em|K^Wes1Z_t/* aՉmes(114 zSuJu-0K'UƭhlkWU}Dͭ C~ͯw\<`bscZη|D>j P ha6sq~Qj#=R~n_1|z=Wp}Z6е5oقe`𞻇1č+&p}JیFmQ5V,Z8;h\Z7p]>|xڦ{;ܸAZim9{_/ط;OOWML/ܽSUHls*?`FCMU_r}78cYan}:ONn|:-[Ða~nY6qqbGsaZ~W7h{=[LnMw>g~]9G;a|WDqm(pj,&ƍ#S\Qܬ2*{NNSpSoC]e5a$7˲ʣ%I"=nGآ1a[i*bnSj¹p'.ZG5"}ÕmKE|)j%_$c;a?ӶujMXUGamWOC?>1:eՁ}ƍY}9>k09sza0J7i>+օOtc*1cF*n5[}~@hhܩZj G{-~nߋb>kޣq>&α즟rm7.^qQ˵ܸc$v2 wﲬvXAFb98G8B%z1a>k4Ul)ێ\>GA [wѾV35H>zڎF}Ec J{ܳ\l { ׊XQ2i8sus84F5ܵ.ngX\np԰Ӝ/pLrk1(=Psp4@mcn5j! <[?⎞íqΧ?7cFL;1a0/#%****N*#U)#\FZF:tj2RJZ2R2R2R2R2e2R2R2ҙeHuHHzwǯ1lgvƳ1mg\vƷ1ngvƻ1ogvƿ v;`GvŽ^ьl)F:Fo#i:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:f#i:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uLu̮3fWj]}qvuή;gWj]vuЮChWj]}vuҮVKiW7j]Ǔӹ6y666^u^u֭ZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:F1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uL1cZǴi:uձ&oX/I'NI'NN: ^I't:btI<ꤓN:iN: I't:RtI<餓N:iN: 뤓N:iN: VꤓN:iN: I't:jtII't:ST'tNO5&7̏}a{~p7n*%Ox*84-.M XCo<'r;oz7W0 |;E[2bfEu(7yc壮8oN?.vFh/OƷgxK][fx;Swa`Ş8:Xk7&gx✟V{mq87N~7W]yckNOCoܻDp7wlIޘ;g| Wo>8v7}Cq{o|7>~7)xW,v%sol//kF/_v8??k?l/|pgpox޹&U'Z g,k3ǻ{]CWkf󇗼+~ 4Z0?vËQ8eS?䤏?>??L '>"y vy}c+/av?X/|%&^q8a?U_81ZNݗ73ݟ;2}5%|Y~K:3/>Sݞ8<#ك \ql\g+q>o1|AO{S]U /,&U7]>f 4l/Z y%_Kħ5iԂž5rqdf>(;žقQofb/| 8vxZ/38my/^^S.wtu^SՅV{cbªWy_ {f^8o|ᐵXZ|&5/) ?N. ׸BO9J UMp8pGOhZ\O,*';~'>|io[0臲gz\O3.XuO{}v}ޔW}}<+=MPEWxb=GE]l2;'C_'5&;~:E洶ar{_P6U,3׎wīE%6wŌ,̯gVNjkی-v#xGlW+|8/gew65B,rv8&{_[ek:Mްjd71y۴b1D?zD˯_,cV[ZukZsw-~oNΏ9bS=-ub}]b噽VYs#⾍wmirOk+G=_7놏NhgM^Z?G3GD? :e7k!㹞xYΐd9Է('oP'7qMn8/P'ʽoz }Ҝ|]#~z/|az_8K%(LO-T9eQ'o#3=qmp%plO;[;  w-8Ɔ;Uɬg.W|qGgz߫{M>y5?/:Beɥ Dy]V gnWDg7 lTMMFO,M3Ovg8)f*2qlw\N=~>t/kk5)P'lo(ϼ6/̬Yڈy&Z,-_ :A%W_)9S+yw?,-? l"O/z_/*I_̗S[UV-e.;A^_.xM0 8b.pĿ'6VsIW|("_]OW'k-ʹ7!D9DpN3E'tH\pI8ED)L3Y-+DzgiOE|9ö_nxQ9a=~]g$iכX?1H^]w,~MgxQ޷+¹CVsD8=≹EFɣ?၀hק- ]i&XIW/(5^0{֊'^R z"x󟅾Baǚ"?,i W\4yw|jÖx>qY#'H KD\qz?O/-Wϥn58o/آxNv_qM{-8sdȽ3~=&?9qÅo_(OΉ[zMgI̸3⊙{I݈+\P]nbi$[qC/x̳$.q7psň/|7*0o _=yWOqKW͒vKo|#=H`E YOF<Ѳg/\y(gkv dô$_q+.mbÿ#v5{9}}ef?qE?G?G"Mwxw|aJVn(߬UxWӈ'[ :w<2Vk_(?X?↯_KcU#xX^8"mw~u#^\WU%qEW?<Oy/|Cpt?̟QK*/F>D񿵭^$G<.$q1/'≵FJ_X(UaBxg2/#!V B0Qĕ!OsZq|v88pu~^4)/Pb1O ri`C괘/lTu!OZׇ\q@}@.m'NXı_| U3$NrŗJŽW^y=1_7aϪ!O<? ?fҤCX'K51fǐ' {.K/xsū70٬ySGcyg.G] i{t~MM:F]qXEQCy>4>OrT#>< ?s_Dݰȸ =A_x Y$k奚_ѶiQ_8fO3Qr#~w*˯jX~;)Ŀ֋z--uߧIb]7eHt?v8?5!wg;=w彻$51W+5qŇ ?uX$M7s_Ίz_f<7+5̘'$Isn ‹J+6Ϳ2-yb۫B]/<sŬX^2ne']󅳟 5}?wo0ʢCIMQ޺bhoՏܖ{y%抖ѽ2?<䄫j4瑕H̘J)|_`_:=7?kN*vjdb,dGT:%'J1ム#6][ =s/Όz8Z5g̹8Sq}gvgYpK*`gQG|iȷ4k :fN)nsĝd8n9ꏫ\s!SVј#~V.CCMBsğfeLל%~5<8t;Yst/\S#V̴wM=9S-`yڕ1G<(?'nsc,v[3e?3>\5@:ɋy#z>1eUsBy\qڼ'~rgaOcY2} G?4Suxmu?W q_FvKcAG<,_h[[i,hՉ}awk{zbi,~9舡w$wn#.b󵃪=*gi 9<?6'׹̘#N\/QW~XAOnk絉ykg{m@#k70YkwZr1G|/,Zh5PBrs!ˣc*ZC=vˠ孻t Xru&|a1'WU-k<1O̫ougɅ|n/0zlS~\qRyu%e/?'X@bLh׸!WPkrR-Ѿ 8c˗q^4]7Fyfa47k\ y#Pdc5CDIlt Xf{\户U/buii,/ύ¡{D> z⨚x_ԅ1O|6+!G2Pԗbj5F3юC:P1Wܲ! |SbyMBnX\GlvMϵ.>wh#^T8c9^/X-fRC¾+~xUGEy͞ĖX^S?숭Z*/ w;ʒg-޺DTˢˮ#votGjю;ΒlG-磸Y#NI$xJ,oe;b~,MLIOˍr8n WqA5a7$.._-OgaG\,Qƨ_|Z*z}n7?(ڷOqhǎOܳHV #Dw.W?(#S%~\5NS H:o>_ⅿyCz97Vg/s^-^!_2k9זx⹷G xg_h_.864.{L}дC'-lOB'^7[7Vc®/qS/|dCĜ]qy2]q4#OOwQ-Dk>n%s}+}7Oî܃b|=Gw 2TIS=qʒ_89omXoQ}q,_+8zoZxs'.]%)Wupc¿[?g+ns]928 Ou%^>|a?r|aSeN)rŔWE5.qXC|{cͷX6I<;94l㹩⎘q/1OeC®xųMj?.IY-[b" }a<Ѱ+f#?wƊ{z#4LI#8xg!8ⰛþU'6#rFI1/eI|lWwMVbRlq1<O'NMS.hYs;Ee/q e.-reD+J<5VM}D9r]~1۳xӦr畸bRen IsY%튧ϯaWRq])x|xV,{]ޡ,[<;/%!Ϲ/ /.a]=D{{';DI͒9+[aG|SDpi_EG~La3$?rHlG|ªKîmOfqtЯѿX|NXs(OcY"U6I}Re JUCs\16Y%tfSGTKxO#]y<u 7'ޞeqG0#bIf6W>'^ams;y; 5<w:^byvlGhǹɌA/lxr/lVͷ]cv _]i)"pVBvGv4쌷z 'vys-.sw|"]dzX[) E ;'sn{heí8T_\qAFSY97]QkK\q;,pg<Esr+NY8Whߋק\qfsѾ_%qYW*E|%Es[<'8Ooߗo~T^p ܝ?gExrѮb-~&ΏwWgpoVY~*oa>aˤV+rĜ<_/qRYiš5#"G==sKq\TAyw8 :70妴#neW>ȼߺeww/rȀ(KʓxN1g'-0RX~7$d|-ƫYW$z#'EEy,:숿v&gNwg1$6ɶ+s ߈M'͞*y=5|=nHB^;-^)Ebئs{RX^r{{\ea[JNmw|kI2'bk,{qĞkTdkm]+sfIBn~޼zikHW\ }9,Td\.3p\%WiE<8[soq'뱭9k:K|[\BؿQX.prW+C/ {V!qMEQG0G?&I2:SE{f ȷczssK{FOȷVm1"~X&H|k߫i򃍢YnsM~[l[/>W,Ŝ"rG'p2g8n] kH (E(PQ#.$E 8DdfG\wNWÎar㺈MqsRɭKXn*5,vȔ2;b%?"sR#^! X^rY#^zmUo1#漳inīNJwƝZ7|-[3mZUraG\vz{/qy7UK|E3&.+KGَb}q_)2Ӌ s\,KŒ;" ,5vƟ&"q'i44ggS$&N/;+<"ʩ!O)7 jwFd;鳅=5HT#qh_iYϬlY ywiP?漳a ϗslQ՝/E9ls4!z1?!3}*# tɗxؠƩBua#_~]7lGysTaϽeN/r=*q%hSypa%?wv.n8jCħn 8d_Iȱx,+!+_QE\S#_w3MN%qtG8䋻$%gVlqG?v "*Kynvv*wKDf4nI/dJ]ĊRϻ͒xrl{S,_f5n;bʢ]t[#nŠr^;Sv-~絫cLSPCpc9!Sw6_&djQN 3*sG#^8ʜ/v]IK1K%f$8:@M|oW`V+nlZ\OڮME%^ղ8r|tVmծo~{ ㈡//1(roV,XC%PPOmp_qġ ?<9 ; n͔Yӄ<05zQ3VJ?fI65MuϓE'l{Dܸ-Ni.;hT;-%3 ^&H^/^_K6<( ^JҒz3Kvls-6l*sOn$>}s^Tb%pPOVhb~TC,;]+z>FWat{"=tQv~k-%=n!KQ5ٓnߋzyT/D/ljziКrOL:3n%yQoޛ%Vٰx,ӾIȔJe%YdD}53d4agļVYHwf2?QXhwu{TSdM]տ~jv(W巬Rbޖ6K6M{!꽮gĶ넝׷ɱ{Dm-Λ%ddQ_i$z[&o9"zgz;6,dag{l)^ṉb: ]#_wǥcXjuT}GD 7l)ypKz%v>;nDk8dsnz.?*پpd/\3ߨ)ڳᆊ&vK[H|sZWg I[#qϩaw2\ۋN5?hǎJu+BiqwpغtW&9[KX+|Ŀd>q÷ '뱷s\%$Tox+zOvbCф"W( *qFolQ3jiWl,&9]k-rcGI|[]YbS%YbE9xc;PFIU+:yۆbo펑{5\vĻָ/t_j9ѮWdžmqQ_k= KbѰKL\2᥸+nuĭǣw~튻&7'슑KK.Nwŏx}+~RE7m"W<8į-qC7K<|I&Ka{+Dk%}\׳FI#WmwA-ro[\NQzmox#֛YEv?6Jx9Ikl.ra$fU⊗n8p+'KWlvkk-*rGI+pQd]%viwǿHv0xٮسI } ~pr=Oq ⋗835{H<;+.y6o^#q%QonvOo.q{A+zT➫%K\+6KtU+~`k_v-růN%1K+~fM 7$KaQjBxk#Í+[IWOwiIO͖xʾ}xjk%\4Gx:kl}k֯/kW"ŵ\*KrW׭Ĵ]q:掿? PSWcu KѮTq]Kx,RXM@#`(j),]k36&0_̹K搂= ſYۈ gvKbw74 LAt l5"׷L 7䳹Ig7.f2ٻ)հyԎL-[+]2IYt2}4|!duۖAfba$ f{h0/Ggj&KeBˑ{ l.DLdEiȪl-W<խ"& kfX=aÎCn~Ь C&@?'T i4I&:|5;\>ݰF\ܸ+VŻ䦕Z7*M^O-4s<&0]M9LO HnkC6pxT\OMR"{;˩!W\m?=`$ <}{fii~,C"AdWB$Y z aȽB&E#Uf5Ȫ5'=*?C^Or2#zȃbXbuB?Rhv#?RC?'yoD~>맧)"G/<34ex!qby*4^Hp?et$uf#vOT$;a/iZȮj1ɋJ _^;+ې fHhfC>'s:9 Hdiϓw=^s_! k5#R7]iA>\LiX_qGHYgc ljuZ_O`{zSO",ңsJhskg%𲆤ע0 . 4s/qJfv~Un1(9蜆䫳Kۡy iُ &i,DO7]ϛVr˴*BI]WӼ3 Vj!W.!&Ƚ0^]r";5 qoph1>i]#rR)"&cgrMq^6r ܨvͦIMHM h!750z*guhg;ې@{ҷh"9s[gۦ|9ssf5OFb?XmY񍅤r])2{ygzC ]RI}f6K '|daY'Ys#`=,),2a Yunq8eu{7yzxS=a]rxiWr_GeޔuJ|)u_VTvs+N?8=VCQ.񢼦@kBJYV x%)o<7e9meAvp\j)V ^,O5)pI</Svcd/data/Suicide.rda0000644000175300001440000000362511720426624013675 0ustar meyerusersoTeӖRI]`fs^`Hi;Ri;e"(A`%K,]te]B}<#iL|w3s7s?'zWJ6yVϦzGǧ'j|mkE{_ene=JmK\rJ,c._He*7*.+\JkO._U{[e}^~ɛ^K~r~32[.U]1o |S{_U/e=ge__ͭ/W\NH'z6קsOUe~izsչ)iL4q]SK9?7=hiv^wn]GW#͡eء:;zLlv&:4;yJgR=v[z[Sz[qr7kc뷩~ye  "D`l{`V7x={QS5E3\S>?Sz3W-Hf`vA K:lm\}BwTt}Tuhiouկ?a#6BmɦX6Rmd(ekւk֊[+Vj-c` ƀ1` ƀ1` #0F`\ #0F`1Bc#4Fh1A)2Fd1"cDƈ#2Fl1bcư(1bcH#1Fb1c$H#5Fj1RcH#5Fj12cdȌ#3Ff2rMMIOOOOOOOOOOHi 4@Hiiiiiiiiiii!i!i!i!i!i!i!i!i!i!iiiiiiiiiii1i1i1i1i1i1i1i1i1i1i i i i i i i i i i i)i)i)i)i)i)i)i)i)i)iiiiiiiiiit %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@.]t %K@tI@tI@tI@k.y։buhѺ/{p,6vcd/data/PreSex.rda0000644000175300001440000000037111720426624013511 0ustar meyerusersQ 0\S`-MPD f9T痉d+,lgvfْ60`vUja7RE `9:K1_UpNX%< BdBM<7zw(YHE7V\@1MД!D'W-,XGU;ExW\y$.d~Bľ^.!}Dϡ0ixB"vcd/data/SexualFun.rda0000644000175300001440000000034111566471043014215 0ustar meyerusersM @/RA:wdҩz_ a3;}qct 9΅Z&0hxr_{R&HW+4Ҽ@b#R׈,3WQӈSsRx2 GX}N +SJ[q^ VVA4Mwvcd/data/WomenQueue.rda0000644000175300001440000000027611720426624014401 0ustar meyerusers] 0 p AΝ ] l0>0 b4rj˸@Lu& 9zALjkbC%q{9x<{ĒJ׎mT}EپY bٰlYv,5˞!E"v.΍:wj÷uMܓ?vcd/data/JobSatisfaction.rda0000644000175300001440000000044411566471043015371 0ustar meyerusersPMO1MHwLHL [&+{Se`vvu:}o/Q2K ҈ڍ\ϟb*aVlY %zc~:7׀)x|_p>zN[6mFY݂oxal"ܺhg@\dY0oHHƔl{o,ݵ UZkِ3l~d%PQI #0NWjҍK\## ArHI*6\ikۄ/NqIvcd/data/Butterfly.rda0000644000175300001440000000037011720426624014262 0ustar meyerusers]@'((EB1E"1'7ff&g`Y/mղ@F+,s}yr;Oew{A-sd 9{.O@t1hb䊲cY|IfEe߷ny$' H&$!ɔ$"(oi6-`lSghyg@Z߲w_}Tvcd/data/Employment.rda0000644000175300001440000000045711720426624014441 0ustar meyeruserseQN@iƥ $Bcb1ڍW.\LAMh 鮟e py0w0NlcbBJC*KM\rp!uȣHI9q΀G>+>_}ܦ~&T_,.H/ۗ<1}s_ૻxZ]9vmǨ9>0-{ײߖ͋h7e|q-yu1_6{7fb[b,͒ǣq,K~v`IգS6Hm/vvcd/data/Baseball.rda0000644000175300001440000003602311566471043014016 0ustar meyerusers} \Gun{{EH-oYmlϢZ,Y#K2igZbD00l!@!! Bd@IB%!Uԩf}7wusUTඣicLl|dℊYLxiX,Z>}[RR\zp򘯌 JUr2>m-CiډXYeKJr,(ONWiӽLʧ}U:+f889J41UՓZԇ'gL fEObb2Q !gcAm/ +S2#%?r ,Jq?X@k ^X)MSm+=yREj?9t6PK9[ kikC+ҳ\΢3*2C'=RTLUf-8Vv898S>1"  NۇP 78k!i;qb մJuҏV6J۽pg`PPeY(vdv-RR_%ZU3T\d7]Z2 ]AځGlޕq/ˣZ1kZzjZ*ӗGƞa9Zvw Fi|r]M z\QgT PIx8g1C $XfkfemzzҽXIJZ{j1mcvo`r{CC}w}}EB UfPyb2hwZL Qno̾gҾ1}y1Z[ 7G5`ٳf$O-f^=&JsGʕiʹ|jكP Jry|t℟Gc-9?XtDP +"q*^c3)f<֡냪B9aHv`wX (aTLZ%9AȡSͯRg̊C oxUu3(f8:=PSV8Rm%J a%sD9UU WKghw|ӸP8:,"IǼ[8TswhΎzAhMqfOH6+ y≢4,潕JqL77T&Y}ձaiQ]YՇN|m՚'J۔:EfC#jiX=]E],p.)Rm¯#gu"U]Ъ|F~[ A1mM'S W9:$Bj C#E)jn+ǪЈw8YԼv)Z("n wdO6y_2\+̎_0!(ZM m@jxGj2n+-T4nܛԈJʀ8_W(Ѩ~WQB-y >VOAD& ƓqZv'Ξ -ROڒw-{BK>hB5>((R]}ȑ'/;Z6 o&kR^ đ``qo7-49x,(s˵~;ĦVPq0U+ԻX|K^.䣆! $^Y+yrM SȔgU-C h䱡,j8XUWngiXUS_FQ9O:m*^,#<݊c!C2!{Oﲻ2J xuFa7л"imOJ$08X%;䗔Oޣ$:)do񌗡b d)/Ǜ3^lT!(7JMWʄO(bٳ;(QZx*NH2N~q!@)wT?^=s =! u o۩e񾐇MdjȧXasYSjv3D'oTZ){ B`fWq2Eߒ V@AzE%V a$;K*XVNyx)2߅utƘ:*Q =]?utOׅttQIQTsJǨ.TWѝDۨO꟧OW7Aѵ]t]OPRGt}\*=ʋ3*?Nеܕ-?q_Kz!]kw_(;%]C<1V^BW;ѝt-#o|]t 5͡2/wsUKTz. t.=?Dwx=Q9*Mwt]m&r(ԍ31wkL't7L;5gtŷS+T^BYtu;z-(vGY#nNcq_LnG77:y24}LL?# 됙_q|'1,eR;/a~]'T_AtahĽKwr6tŮ H"s''ېcK(ft+]X6&C͏|1xb+f[D1lBNeHp,:y?O:=.ư=LSTn辍M_ K7=϶ONwL{^X8ىy{N 6 !ߠ-!/E0 !:#퉗~%$ՐaH 鮹.R` ?z<p)It>®C^BׇB5f8x0]D C\NWqpP=2=Y_y<Krn>Htz Frb`׾Gl!r|uy^,##K<ޫv~ 6ix ?8C̷K#L *~qDŽL@-yXt;̼>2. z1?O0lÆ 4쾁 fƁl.l<`BIWMZ1Q7 S2{N7x10|^yy{+7G{}iq:mx1sпk_0Y/: `H Ow2~LkȮCl>A4\?Gd2~, ȽKz~k"_ xks}&+0Vp #8gyÃ%nmn?q_, \jbp+V?-+2 cIp a^ }3G̴e4ZsXXɴ~1MMknb :~⶘ċ1 62[,fݔ\n#y >| A 7WWr;]Q]by ÷.1hf㧕̣5<[o1:Be;R-U[~{~ϰ0u ctX6s`nAC>z.C֕| ncܷs:.8'#b|y,>0>_x^sa ƹۯyc:pO6C 2-L̵iw- qd )c|mV.;a'070͌m|mlf:}ܷs \dKxۜaZmf~Ot@<Ƈ\ȼ:W?㸒) mofމ=lbz }73<g <9fZ/dCU_pzE<ȂU<`_Ϯ`zCΎ'7;㳘bc`ǔuJ~wGaC~'׻|A*Fuh n`]t.1/d?2}W̧qq[i4]cc pcX1n |c'?mh\Ug^x/wy+h1NO3/ \33e:]8r˙ &-c6sVnѵׅF^œBw1_633 g:Y*J*X`\x/bz-fdA~lb=]{%ШNm!Y{%rC,%uuኜ$ ׇhF~! Oʑ3Eϡ;_=5Gߣ$o _H_nL'9XB^Bo~$߭4GcR옱6 dx#YQrXuS )J&u3:@G맑M/bt,FٺkG%Gd@>r~w r1oW.w:\d*KMk46tlafӋig6{N~eH{\Df&'K>@c ː.D;1Q/%ŵӜ3N>|<|ͻ=&ksZM̐\& 7!{>"'#zs^_޷>ɷ;/&G MS GhcSdO։=}a:ɴz{G_2IrZ`3^A<#ߛu~ɞtۮ DžF%3n~2¸]}. #/0V\Ms9w4G\i7 b{Fo1 clHe7]ow37p8^f4/fhh$5^ F~|FgkROME )!Lͯ@/0]K#OH 'cw@Sفt'#cζ8B>"7zCW3#u$=M_Fnj]w/as!O`wc-h 9G -1lbdobxح#,/s(C]BGƞk}MbSca'@w,4ig5ټ6{BgF | 0Σ6]ě b!hـ̣,k{ϐo8:Y[g2'?Vp r78Yp(x>'ӭaj銘hŘC.ey{ae#QB5gXܞ9 ׍S\o/ 'Cm{6 1WX'.##ͺu`O`Os8Y(_G.Fż\mb8M3qV!?r' ߭^Q/řcd&ubVd K DW^ ggjW*C k8n^?bYi5| '_'Bq^&3@Xs?A.p k%~6~*1.N8_X~)ٞ'\Gdktg} ?ƍ;ZX.%Xo .غ۳3$s_wa7j_،Gy{FVƉ1trVFzzC;|bݎWNl v {8CGv"Ct`f|-'[^6h6% И \9wC}n-{3+F\}E{V9.5Pe š <؃6ۜ5.ş1 .ցAsWGQ==0:D|o~ ?:yKMn~6V-FlYp{} 76N$ayhi::yGCtcձ.- |繱93;ߐٵ܋ѯYcl|1/!q&6%Zď a7o^Y.O0 Ώw9[_? 'Sس:F[ Kı!q#9掾#s%>팳V>O8bNwo}IJcРTșC+ '/0-(~@Bgiho6.񓎮t;O:\cN|:{i}ʌ+v>cov2E1I#þ 'O8E>;b 7seW31|ם2=3ڝL[hyjÿɦo?p?|B|r5,gߊ8fN^LGGJĘ8?ipIU}^1b x~oد,ox''8lm.Ġxbnh ?\#@|= /֠qhsk+ |+)\EL7B_| a{yldu#^GYO9$+OX6x{mcW:;IIo#Lƚnz45uOg3L;\s{D?ts gLzM&gl7=fL:0[d=XslNsw6k6Fpmri[zKx C xKAφ,0ϔs\K+V3|Lw. l8=GmCz\*7_Do0g|6s}7,6c`5R8Z$"զ?ۀZ=2yl ܗTIInKq8=bCR?%e92zTOq3. JJuYX|N~ B>1v9Rǖo9jm峟da l#H 5{-L*i/xFScO~> N_I9^ʸ.75n,,bZIJ Ly?7z J?mZ-Ksl4^RދXiTx€_!_e\/"̒/"oVhz)tk{џ>. 3*Y=J ǾVfr^XEDbn+B9\TB#I39z%GĆ-9 (T[mxDn7 $7ЭeM]ø%)?cLGʾNd]Kio]~})ow'elzTʼnR42{m@}1Bϰͪ)FF(Lޯ1%|9rFM/4T!A;>bdbE^ĉ0dB`b)]!`a0+AT.֡Y eF2ȌȮ%;ZmQ"8 DV\c\np"aւ/~)mߦR*|߂/%?^nV_׷~ـG~|\is >î36do n{Tj`O.mܧp,IrҔ87h\Z:;GQ$s3e>H{?eRHIǧ3rצOY|j?"% 2S >ȸOEh&$}Ѹŧ';?f cG39뇴:cYH!ϾH+106-1O$qsd4tTG,O3O~~gp&'?N۸tS}n/io_2.,[ Rʴ>KcH;Jsç|f`۟f?gpLl2~=ƥgy !I<&>~3p,G\ ت3nϖ4JA")y-d&]ҏsZuNc|Zm68;r9i2?~i0H#Go~7h^'GKuÆ,HU|ŧF`~C%>"}% tq㎏\-.qwҘH>HM@ʊMS{\~> &,4 {æww' vK6tiis*_gYl[w PACn. ?@>`hڝeY= @\hѽ&Ini ;HفnS[s9mA~DަmÇ#]C*96`B}'s!K]| Oosx8 v r ?p6E=fl\emǫaЊR<0ot-gt"?Ua=`ʞ/+'Nב}g'u $엽Yً>7_)si`JYύџc0SRD ~[ c[٠,޼+aI^֋C}Jy'wr~f3Ǭџ@Udqd0)4HBӈ1ei)|cns- cɾ|oi6z=yɾ|w%Xd?:\fШȞ|L&x{N0'9”D_=D/5*"/˹Ȯ `l4]E7'Fm"~-sr~,4G.tۈ.G}=7eyɇK/Uy7HS·z^OK֕rwýM?yۓ˿O2.=|q<~ D}}}c蘻3=oX<՘b~G;0Ue~՞vϙo_wx#bwd~w|׶N2S(?PIc;_S~3%{7_;Α;[>lxsgݛ~*6pkskk.Ztg\g&%>/\Ifm&t8Gf?\fp/f\25\Φӌ?}nlLkrce/&̍g;7V~zuX{:$hXIq sc%7rX+dˍ=Lsc%hML2率+?|ש:Jj'7VdnL+?wJZXyaه3>dO:Wn ~͍}יrc<۹l"{?7xm8Z3nkÇ[Jʕ|qb8!㎔'}-?R-e>/0y`EVlwξeKہeo-{g١e))S8hnD>HH.* K,W( ,(3*l9)VE:/2 ]88Ҁ433mDwdFFy~ch?}uQ~G+[樧UEk,md:a*w\,/DILSKhs_=c0׌Ěa#;> VV1.LXs~]L%^m yP;pFc@NB*ӲdתlΗ¼F +N#~&ݍ5W{-&o=9K/wxKn$+ _/M#'qFr{}Z<"醭 FwQԦMY6Umj`LFG1tEt%tettUtȠȠȠȠȠȠȠȠȠȠ``````````(4Ju'ߓf!߿ 5fvcd/data/OvaryCancer.rda0000644000175300001440000000054311566471043014523 0ustar meyerusers=O0/i6EJt`F"&*b1u=%.&@6~2!wJK}_}?Z`8BT(ݻPfӥ'+!:ű\wBƹ?nτ:cࠦ\$ '2-U/U7OBRzτ;$qSEl^`(9]+ήS^p=. vYϵy ze]q-J1P0:Bvi Ŀ."(IU URF#x+/̇ӼQV2{o!H$e7G0ϷBDy8E }pWHi,]iybig{VIEI2iStPڪȃ!sύ8:\nHY=uf5G4AJD\#u|Y ou#d7Nⷦ]-$sExBw 0>qn>]Z &Wߑ?ܞ Ƃ+Ph;_uTWi&}"!__o` y#٩O\HN;~&61淾K~ o@^r_G_b+o֏F&BK3NB((;i{hYXWg;J3UG}{C]Џۊ"XmYS則Cm)jߐU k,quzlVs( _9?iJ^;y۹_-wAdu?LIZ'z^P|_jw)n ]Uv΢ГKfB݄'N`XУ=stF} I2:yK/%, g># $?z6kH"]9b6Dό-i¿c.@N1:RNtϦb0D}:!uo'c2 /p78\'<%&~{v~iUl $fףb(09oŸCē6 lҿX w :R߼c9O6f =ػMOM).w~hޭ TwC-sVpS{אo u&Y3h$C'Ⱦñb=dW:#ezxo=|N?;= z$u@M?k&qqhѼޕ凞#,;wzN_!K,4'dyFVO畮kk7ӇLX8Z>>>84~yŲLX+Q@TPAK~%%%%Jj4(iQB 28dp!C <2xd#G <2xd! C@ 2dB *dB *dB jdFjdFjdAdhAdhAZdhEZdhEZdhC:d萡C:d萡C2̔c2QD<&fZ&2єd4%)MhJFS2є1hq1hq1h<3h<3h<&0h &0h &0h*FS1T&]G ū?Z8:^-~(^_Dvcd/data/SpaceShuttle.rda0000644000175300001440000000075111566471043014714 0ustar meyerusersR0RPOpxmx)E;ϧR7On7KRgƘtl[LØkz[`,{#2Q/2 ͽSO>rnYTIŃ̝D>bF L|ȿt; w%DD"GCKD<8yp|ߔN3vcd/data/Bundestag2005.rda0000644000175300001440000000122611566471043014531 0ustar meyerusers]S]HQwa5!HE"i\3g#\wGgfmf@ʴ"2(z^J| ^"!;Xpf9;Fd^ȳTٿ<7j$rY0k!e�~zfWlE/m׎X͟?w; \ y r-a O~_ jT[|^2dAQugօs`1fR A SA9CtVָ w4˦QԞQ ̱S:dnyJjZ$#&=/1 ?U-|%QSdTL2]Av1ֶ橩/RhLD8hyB4YmS=E=e BLz{҅G]AD3Ԡ.#/.n%'%@λzFŶ&՜#x"˥f6Iit Ϳ `vcd/data/Federalist.rda0000644000175300001440000000024711720426624014367 0ustar meyerusers r0b```b`cd`b2Y#s1[jJjQbNfq 3/P=1H T#n\ bGJ% @30a c05P;fY|+?t9YKrR!<6vcd/data/MSPatients.rda0000644000175300001440000000041211720426624014326 0ustar meyerusers r0b```b`cd`b2Y#s1op@bIfj^I1PPD  Eց2 (C=oM=hPak+^+ӁsJf.1ArP̄,/17PP yvԢ<ĤT8?8_TVC]c`yyP>_jQNjb^1Xg #WK--O,.J"ǁHo `"=vcd/data/RepVict.rda0000644000175300001440000000070111720426624013654 0ustar meyerusers͓JPƯb-(Q)ZUDJ鵍IHAWTP\E|An͗C,R1)m LIJp5k7tX-:~jN%B'A8 =Zς K'I<#`)>3F4nz}yϳ|w*aqxe"^wOk9NЏ沈7/Jh~&8<J~蒮{=U ƒbdhyYvxFCKFRsymArnnБJOqOYÁWxmkDŽX8kgIϖĚbl0*(v//(\V׌]nq?:Vn7#7URnX[MGͣM0fӱ:JW~^}vڴPC~+u=4 '6L}|x Utq7esn૴pe6N$v':mrA09)<4 ,kfRQF((hJQ^ѴET0<;iH'.v4^>Jvcd/data/Punishment.rda0000644000175300001440000000074211566471043014442 0ustar meyerusersSMK@ݤڀRЃG= ՋxAÒmI0*i@ݚ1 6yq~t+1f3a1nh6?Ala8&c`}~+> lV}c" ~% =(_ ܨW>o úw (*uy`-_}B6sKcuƹ6atJF*ZU9X8͂[43mN)}ALmõGx7핥j93jPjeF4h0۸]*/hs;[3uEj=ғHRӯMW$z&XTV#Kv2-ȵ<$@III qbO, !%#F48ipAdsI' A4i!HCt~n$ܹI}J0vcd/data/DanishWelfare.rda0000644000175300001440000000212411566471043015020 0ustar meyerusersNGCDT.zBQTUys7mISF@X?ҵi;?Gi9)Q+[2xf~;;3x#h)zTkբZLO-V[e\güwy-~\V6F2(SAdr~Yiq``|-pV)ާGTzv܏C\j𹥸MS>T>}A{xgu/.󼣠 a9k]b>ؠܥ3zܟ0?yګ}Vm}:E^jo'Uy\>w?]f*>%LOns^7UMvRw4fO,?~]V<ɻg%F9\'AG5.xtG~Υq6>?(ghg[o"ԺO5~>iN 'lj$$kdEyd 2 `( `( ahahaha`a`ǥaaXaaX`8`8`8axaxH`$0 F#H`0R)F #Ha0R6䑹L7h[I%5ZI^DRbbbbbbbbbbєhJ4%MDS)єhJ4-MEӢiѴhZ4-͈fD3ьhF4#͈fDYѬhV4+͊fEYќhN4'͉Ds9ќhN4/͋EyѼh^4/-yХlmzyņvcd/data/HorseKicks.rda0000644000175300001440000000024011720426624014343 0ustar meyerusers r0b```b`cd`b2Y#s1G~Qqwfrv13/PsŀEsJ&H /TM( 4I*.5$hcF01af(+DI0A<Ē ?t9YKrR!;vcd/data/BrokenMarriage.rda0000644000175300001440000000056011566471043015176 0ustar meyerusersj@'_BECћAW]m1&&xk߬'nܙrhٙYrw=u2` 0l)?@$2њ#&[qy"ߊ]K OG ox~<*RUųNu\fL A,gp’x3XL I$$~)Jl4-_Zf6|'|grB~.?͔N<:(OyًنEt\Њ`Vf?$`IDo5]%h :]GЧ6\M-MmMM]M&m%򤪭R?Uvcd/data/VisualAcuity.rda0000644000175300001440000000065311566471043014733 0ustar meyerusersJAggWAz@r֯F@QgmaZW#z/GIYA߬g; n !Pے!ѡeII]9CZC?%^dV'o$~ݪ3mYtzx@^zJ!ԇc}|__݅SXߕ6Akmf>TH)ρE;Kb$ d_P0NH>Xx+ꇒFApl|}wf5ˆݒJ.V-/ǻ8{N~2?Ӝ^[y?3PPPPPѰ @Hy$"H%2R =z0`ЃC =z0pE}q6x m'xDvcd/data/Rochdale.rda0000644000175300001440000000101311720426624014016 0ustar meyerusersVKO@^ h%ƃ&F1A|,*O^亶KbbpN[Z#&2ٝY-5KhB-h'' 7smB?hJ\˴4޴Eud\^wV*/L?>(?~H#ocz8?_]?5djF$dMg]m,N`'=?yngKx+ ϡFYl{-> m,wQ\B> o9![Pul_o@eqxP#5;(-:8K {u3plQoIu1jt]b[XhX=aH&ImZx-~M_ysB~2*\WȹTRysͽB9Ź5q3%z#?CcfS2+[Y0 gdsI?& vcd/data/VonBort.rda0000644000175300001440000000210611566471043013675 0ustar meyerusers[kW{ ЛYs-T\ՖIdRӎd7s-×|g3QE櫩.IIӯiI~}1Y<|X>&Ig|寓į%jgN8yܮ!q]}E^|wv73`߫z kߙ]3߾';3tbc/w{4ynY|]|>6wv(mw&gm;sn|?r&#燑39?F#痑m>r9ȹ9#g>rM>τn>sy?||ԧZu~?7_]ׯ|^-I.,M|dxf΄%wLQng'f7e} ::׎R_Tk`=,[~z( =oǷwv?Y,YΗ_-uSMx(,EXʰTa҄ KܛJo[fC6dC6dC6dC6dC6dQ(l6 FaQ(m6JFiQ(m6*FeQ٨lT6*FmQۨm6jFmhl46Fchm6ZFkhm6:Fglt6:]05gkZV5kڲh9Zh9Zh9Є&4 MhBЄVhZVhZVh%ZVh%ZVh%ZVUhZVUhZVUh5ZVh5ZVh5Z֠5h Z֠5h Z֠5h-Z֢h-Z֢h-Z֡uhZ֡uhZ֡[ݲl~iH>+,vcd/data/UKSoccer.rda0000644000175300001440000000032611720426624013761 0ustar meyerusers r0b```b`cd`b2Y#s1Gwp~rrj3/` 72PJ{A9@:PZJh4yz 4ZJ34O\  VF ba:Z<ac0 P\ u$& G~n*XX kLI,i $&BT3hvcd/data/Arthritis.rda0000644000175300001440000000141011566471043014252 0ustar meyerusersՖYS@3 L"耂<!( sS!Ńeǜd:t:wXkݖeٖb?%gW5k~˶[;\ʼnvp10e  x2#  wkpiiY`R}J4sṕyp \ׁK<\<Gf@?j೬XdQ_&~ox.w uÁ ]'I}G?IFv,KjW$n&k񎹴ǖ7f!G?u#Zy6iD-t#ۗyե= XLZɸfJ3^^^=^Z֐fT4~r畖&jR#PZBM3sCZ#iCҲ\f)]W_8cXߣY\auL R|ag(>{xx G}os'{'$sŚZ=ޗ1ݾns篤 q4.tFׇ_n;n$ӵ\MVl$M}YI~XjkCײ{#n#YHvdϑ| R߄eBd˜(Se|)dRL..........>>>>>>>>>>!!!!!!!!!!ECѡPt(:EGDGDGDGDG$ vcd/data/NonResponse.rda0000644000175300001440000000052111566471043014554 0ustar meyerusersJ@76 ^*xYݺބ>Oֺag)6dvff2IjD1ƙz ,><B۷JL4Xs{jkYyu'NoPY ]_N?0cu\;ŗ__Wh =̖Ѩ& #HQ1Enԋ,tj+ͅ!'6"-4_1uf_ tO r!qy,EUb 45<#(R~7mPz7׻ǽ !8&8!8%8#8' G%L"D!:Cm;s`_^evcd/NAMESPACE0000644000175300001440000000762211566471033012131 0ustar meyerusersimport(MASS) import(stats) import(grDevices) importFrom("utils","head","tail") export( ## generic functions "agreementplot", "assoc", "cd_plot", "cotabplot", "distplot", "doubledecker", "fourfold", "goodfit", "mosaic", "oddsratio", "rootogram", "sieve", "spine", "tile", "structable", ## spacings "spacing_conditional", "spacing_equal", "spacing_dimequal", "spacing_increase", "spacing_highlighting", ## labelings "labeling_lboxed", "labeling_border", "labeling_cboxed", "labeling_left", "labeling_cells", "labeling_conditional", "labeling_list", "labeling_doubledecker", "labeling_values", "labeling_residuals", ## legends "legend_resbased", "legend_fixed", # shadings "shading_binary", "shading_hcl", "shading_hsv", "shading_max", "shading_Friendly", "shading_sieve", "hcl2hex", # core functions "struc_mosaic", "struc_assoc", "struc_sieve", ## panel functions "pairs_barplot", "pairs_text", "pairs_diagonal_text", "pairs_diagonal_mosaic", "pairs_strucplot", "pairs_mosaic", "pairs_assoc", "pairs_sieve", "cotab_mosaic", "cotab_assoc", "cotab_sieve", "cotab_fourfold", "cotab_coindep", ## `normal' functions "Kappa", "assocstats", "table2d_summary", "co_table", "coindep_test", "grid_barplot", "hls", "is.structable", "independence_table", "mar_table", "Ord_estimate", "Ord_plot", "strucplot", "ternaryplot", "grid_legend", "woolf_test") S3method("[", "structable") S3method("[[", "structable") S3method("[<-", "structable") S3method("[[<-", "structable") ## We cannot do the following: ## S3method("rbind", "structable") ## S3method("cbind", "structable") ## Instead, we currently have to use: export("rbind.structable") export("cbind.structable") S3method("str", "structable") S3method("is.na", "structable") S3method("length", "structable") S3method("as.table", "structable") S3method("as.matrix", "structable") S3method("as.vector", "structable") S3method("dim", "structable") S3method("t", "structable") S3method("dimnames", "structable") S3method("agreementplot", "default") S3method("agreementplot", "formula") S3method("assoc", "default") S3method("assoc", "formula") S3method("assoc", "loglm") S3method("cd_plot", "default") S3method("cd_plot", "formula") S3method("cotabplot", "default") S3method("cotabplot", "formula") S3method("doubledecker", "default") S3method("doubledecker", "formula") S3method("mosaic", "default") S3method("mosaic", "formula") S3method("mosaic", "loglm") S3method("tile", "default") S3method("tile", "formula") S3method("rootogram", "default") S3method("rootogram", "goodfit") S3method("sieve", "default") S3method("sieve", "formula") S3method("structable", "default") S3method("structable", "formula") S3method("spine", "default") S3method("spine", "formula") S3method("pairs", "table") S3method("pairs", "structable") S3method("fitted", "goodfit") S3method("fitted", "coindep_test") S3method("predict", "goodfit") S3method("confint", "Kappa") S3method("confint", "oddsratio") S3method("plot", "goodfit") S3method("plot", "oddsratio") S3method("plot", "loglm") S3method("plot", "structable") S3method("print", "Kappa") S3method("print", "summary.Kappa") S3method("print", "goodfit") S3method("print", "oddsratio") S3method("print", "summary.oddsratio") S3method("print", "assocstats") S3method("print", "summary.assocstats") S3method("print", "table2d_summary") S3method("print", "structable") S3method("summary", "Kappa") S3method("summary", "assocstats") S3method("summary", "goodfit") S3method("summary", "oddsratio") vcd/vignettes/0000755000175300001440000000000011720426624012711 5ustar meyerusersvcd/vignettes/vcd.bib0000644000175300001440000006127011720273431014145 0ustar meyerusers%% general graphics & original methods @Article{vcd:Cohen:1980, author = {A. Cohen}, title = {On the Graphical Display of the Significant Components in a Two-Way Contingency Table}, journal = {Communications in Statistics---Theory and Methods}, year = {1980}, volume = {A9}, pages = {1025--1041} } @InProceedings{vcd:Hartigan+Kleiner:1981, author = {J. A. Hartigan and B. Kleiner}, title = {Mosaics for Contingency Tables}, booktitle = {Computer Science and Statistics: Proceedings of the 13th Symposium on the Interface}, pages = {268--273}, year = {1981}, editor = {W. F. Eddy}, address = {New York}, publisher = {Springer-Verlag} } @Article{vcd:Hartigan+Kleiner:1984, author = {J. A. Hartigan and B. Kleiner}, title = {A Mosaic of Television Ratings}, journal = {The American Statistician}, year = {1984}, volume = {38}, pages = {32--35} } @TechReport{vcd:Young:1996, author = {Forrest W. Young}, title = {{\pkg{ViSta}}: The Visual Statistics System}, institution = {UNC L.~L.~Thurstone Psychometric Laboratory Research Memorandum}, year = 1996, number = {94--1(c)} } @Book{vcd:Cleveland:1993, author = {William S. Cleveland}, title = {Visualizing Data}, publisher = {Hobart Press}, year = 1993, address = {Summit, New Jersey} } @Article{vcd:Becker+Cleveland+Shyu:1996, author = {Richard A. Becker and William S. Cleveland and Ming-Jen Shyu}, title = {The Visual Design and Control of Trellis Display}, journal = {Journal of Computational and Graphical Statistics}, year = {1996}, volume = {5}, pages = {123--155} } @InProceedings{vcd:Riedwyl+Schuepbach:1994, author = {H. Riedwyl and M. Sch{\"u}pbach}, title = {Parquet Diagram to Plot Contingency Tables}, booktitle = {Softstat '93: Advances in Statistical Software}, pages = {293--299}, year = 1994, editor = {F. Faulbaum}, address = {New York}, publisher = {Gustav Fischer} } %% color @InProceedings{vcd:Ihaka:2003, author = {Ross Ihaka}, title = {Colour for Presentation Graphics}, booktitle = {Proceedings of the 3rd International Workshop on Distributed Statistical Computing, Vienna, Austria}, editor = {Kurt Hornik and Friedrich Leisch and Achim Zeileis}, year = {2003}, url = {http://www.ci.tuwien.ac.at/Conferences/DSC-2003/Proceedings/}, note = {{ISSN 1609-395X}}, } @Article{vcd:Lumley:2006, author = {Thomas Lumley}, title = {Color Coding and Color Blindness in Statistical Graphics}, journal = {ASA Statistical Computing \& Graphics Newsletter}, year = {2006}, volume = {17}, number = {2}, pages = {4--7} } @Book{vcd:Munsell:1905, author = {Albert H. Munsell}, title = {A Color Notation}, publisher = {Munsell Color Company}, year = {1905}, address = {Boston, Massachusetts} } @Article{vcd:Harrower+Brewer:2003, author = {Mark A. Harrower and Cynthia A. Brewer}, title = {\pkg{ColorBrewer.org}: An Online Tool for Selecting Color Schemes for Maps}, journal = {The Cartographic Journal}, year = {2003}, volume = {40}, pages = {27--37} } @InProceedings{vcd:Brewer:1999, author = {Cynthia A. Brewer}, title = {Color Use Guidelines for Data Representation}, booktitle = {Proceedings of the Section on Statistical Graphics, American Statistical Association}, address = {Alexandria, VA}, year = {1999}, pages = {55--60} } @Article{vcd:Cleveland+McGill:1983, author = {William S. Cleveland and Robert McGill}, title = {A Color-caused Optical Illusion on a Statistical Graph}, journal = {The American Statistician}, year = {1983}, volume = {37}, pages = {101--105} } @Book{vcd:CIE:2004, author = {{Commission Internationale de l'\'Eclairage}}, title = {Colorimetry}, edition = {3rd}, publisher = {Publication CIE 15:2004}, address = {Vienna, Austria}, year = {2004}, note = {{ISBN} 3-901-90633-9} } @InProceedings{vcd:Moretti+Lyons:2002, author = {Giovanni Moretti and Paul Lyons}, title = {Tools for the Selection of Colour Palettes}, booktitle = {Proceedings of the New Zealand Symposium On Computer-Human Interaction (SIGCHI 2002)}, address = {University of Waikato, New Zealand}, month = {July}, year = {2002} } @Article{vcd:MacAdam:1942, author = {D. L. MacAdam}, title = {Visual Sensitivities to Color Differences in Daylight}, journal = {Journal of the Optical Society of America}, year = {1942}, volume = {32}, number = {5}, pages = {247--274}, } @Book{vcd:Wyszecki+Stiles:2000, author = {G\"unter Wyszecki and W. S. Stiles}, title = {Color Science}, edition = {2nd}, publisher = {Wiley}, year = {2000}, note = {{ISBN} 0-471-39918-3} } @Misc{vcd:Poynton:2000, author = {Charles Poynton}, title = {Frequently-Asked Questions About Color}, year = {2000}, howpublished = {URL \url{http://www.poynton.com/ColorFAQ.html}}, note = {Accessed 2006-09-14}, } @Misc{vcd:Wiki+HSV:2006, author = {Wikipedia}, title = {{HSV} Color Space --- {W}ikipedia{,} The Free Encyclopedia}, year = {2006}, howpublished = {URL \url{http://en.wikipedia.org/w/index.php?title=HSV_color_space&oldid=74735552}}, note = {Accessed 2006-09-14}, } @Misc{vcd:Wiki+LUV:2006, author = {Wikipedia}, title = {{Lab} Color Space --- {W}ikipedia{,} The Free Encyclopedia}, year = {2006}, howpublished = {URL \url{http://en.wikipedia.org/w/index.php?title=Lab_color_space&oldid=72611029}}, note = {Accessed 2006-09-14}, } @Article{vcd:Smith:1978, author = {Alvy Ray Smith}, title = {Color Gamut Transform Pairs}, journal = {Computer Graphics}, pages = {12--19}, year = {1978}, volume = {12}, number = {3}, note = {ACM SIGGRAPH 78 Conference Proceedings}, } %% url = {http://www.alvyray.com/}, @Article{vcd:Meier+Spalter+Karelitz:2004, author = {Barbara J. Meier and Anne Morgan Spalter and David B. Karelitz}, title = {Interactive Color Palette Tools}, journal = {{IEEE} Computer Graphics and Applications}, volume = {24}, number = {3}, year = {2004}, pages = {64--72}, } %% url = {http://graphics.cs.brown.edu/research/color/} @InCollection{vcd:Mollon:1995, author = {J. Mollon}, editor = {T. Lamb and J. Bourriau}, booktitle = {Colour: Art and Science}, title = {Seeing Color}, publisher = {Cambridge Univesity Press}, year = 1995 } %% Friendly publications @Article{vcd:Friendly:1994, author = {Michael Friendly}, title = {Mosaic Displays for Multi-Way Contingency Tables}, journal = {Journal of the American Statistical Association}, year = {1994}, volume = {89}, pages = {190--200} } @Article{vcd:Friendly:1999, author = {Michael Friendly}, title = {Extending Mosaic Displays: Marginal, Conditional, and Partial Views of Categorical Data}, journal = {Journal of Computational and Graphical Statistics}, year = {1999}, volume = {8}, number = {3}, pages = {373--395} } @Book{vcd:Friendly:2000, author = {Michael Friendly}, title = {Visualizing Categorical Data}, publisher = {\textsf{SAS} Insitute}, year = {2000}, address = {Carey, NC}, URL = {http://www.math.yorku.ca/SCS/vcd/} } %% Augsburg publications @Article{vcd:Theus+Lauer:1999, author = {Martin Theus and Stephan R. W. Lauer}, title = {Visualizing Loglinear Models}, journal = {Journal of Computational and Graphical Statistics}, year = 1999, volume = 8, number = 3, pages = {396--412} } @Article{vcd:Hofmann:2003, author = {Heike Hofmann}, title = {Constructing and Reading Mosaicplots}, journal = {Computational Statistics \& Data Analysis}, year = {2003}, volume = {43}, pages = {565--580} } @Article{vcd:Hofmann:2001, author = {Heike Hofmann}, title = {Generalized Odds Ratios for Visual Modelling}, journal = {Journal of Computational and Graphical Statistics}, year = {2001}, volume = {10}, pages = {1--13} } @Article{vcd:Theus:2003, author = {Martin Theus}, title = {Interactive Data Visualization Using \pkg{Mondrian}}, journal = {Journal of Statistical Software}, volume = 7, number = 11, pages = {1--9}, year = 2003, url = {http://www.jstatsoft.org/v07/i11/}, } @Unpublished{vcd:Hofmann+Theus, author = {Heike Hofmann and Martin Theus}, title = {Interactive Graphics for Visualizing Conditional Distributions}, note = {Unpublished Manuscript}, year = {2005} } @Article{vcd:Hummel:1996, author = {J. Hummel}, title = {Linked Bar Charts: Analysing Categorical Data Graphically}, journal = {Computational Statistics}, year = 1996, volume = 11, pages = {23--33} } @Article{vcd:Unwin+Hawkins+Hofmann:1996, author = {Antony R. Unwin and G. Hawkins and Heike Hofmann and B. Siegl}, title = {Interactive Graphics for Data Sets with Missing Values -- \pkg{MANET}}, journal = {Journal of Computational and Graphical Statistics}, year = 1996, pages = {113--122}, volume = 4, number = 6 } @Manual{vcd:Urbanek+Wichtrey:2006, title = {\pkg{iplots}: Interactive Graphics for \textsf{R}}, author = {Simon Urbanek and Tobias Wichtrey}, year = {2006}, note = {\textsf{R} package version 1.0-3}, url = {http://www.rosuda.org/iPlots/} } %% Software @Manual{vcd:R:2006, title = {\textsf{R}: {A} Language and Environment for Statistical Computing}, author = {{\textsf{R} Development Core Team}}, organization = {\textsf{R} Foundation for Statistical Computing}, address = {Vienna, Austria}, year = {2006}, note = {{ISBN} 3-900051-00-3}, url = {http://www.R-project.org/} } @Article{vcd:Murrell:2002, author = {Paul Murrell}, title = {The \pkg{grid} Graphics Package}, journal = {\proglang{R} News}, year = 2002, volume = 2, number = 2, pages = {14--19}, month = {June}, url = {http://CRAN.R-project.org/doc/Rnews/} } @Book{vcd:Murrell:2006, author = {Paul Murrell}, title = {\textsf{R} Graphics}, publisher = {Chapmann \& Hall/CRC}, address = {Boca Raton, Florida}, year = {2006}, } @Book{vcd:Venables+Ripley:2002, author = {William N. Venables and Brian D. Ripley}, title = {Modern Applied Statistics with \textsf{S}}, edition = {4th}, publisher = {Springer-Verlag}, address = {New York}, year = {2002}, note = {{ISBN} 0-387-95457-0}, url = {http://www.stats.ox.ac.uk/pub/MASS4/} } @Manual{vcd:Ihaka:2006, title = {\pkg{colorspace}: Colorspace Manipulation}, author = {Ross Ihaka}, year = {2006}, note = {\textsf{R} package version 0.95} } @Manual{vcd:Meyer+Zeileis+Hornik:2006, title = {\pkg{vcd}: Visualizing Categorical Data}, author = {David Meyer and Achim Zeileis and Kurt Hornik}, year = {2006}, note = {\textsf{R} package version 1.0-6} } @article{vcd:Ligges+Maechler:2003, title = {\pkg{scatterplot3d} -- An {R} Package for Visualizing Multivariate Data}, author = {Uwe Ligges and Martin M{\"a}chler}, journal = {Journal of Statistical Software}, year = 2003, pages = {1--20}, number = 11, volume = 8, url = {http://www.jstatsoft.org/v08/i11/} } @Manual{vcd:SAS:2005, title = {\proglang{SAS/STAT} Version 9}, author = {\proglang{SAS} Institute Inc.}, year = {2005}, address = {Cary, NC} } @Manual{vcd:SPLUS:2005, title = {\proglang{S-PLUS} 7}, author = {{Insightful Inc.}}, year = {2005}, address = {Seattle, WA} } %% data @Article{vcd:Azzalini+Bowman:1990, author = {A. Azzalini and A. W. Bowman}, title = {A Look at Some Data on the {O}ld {F}aithful Geyser}, journal = {Applied Statistics}, year = {1990}, volume = {39}, pages = {357--365}, } @Article{vcd:Obel:1975, author = {E.B. Obel}, title = {A Comparative Study of Patients with Cancer of the Ovary Who Have Survived More or Less Than 10 Years}, journal = {Acta Obstetricia et Gynecologica Scandinavica}, year = 1975, volume = 55, pages = {429--439} } @InCollection{vcd:Koch+Edwards:1988, author = {G. Koch and S. Edwards}, title = {Clinical Efficiency Trials with Categorical Data}, booktitle = {Biopharmaceutical Statistics for Drug Development}, editor = {K. E. Peace}, publisher = {Marcel Dekker}, address = {New York}, year = {1988}, pages = {403--451} } @TechReport{vcd:Knorr-Held:1999, author = {Leonhard Knorr-Held}, title = {Dynamic Rating of Sports Teams}, institution = {SFB 386 ``Statistical Analysis of Discrete Structures''}, year = {1999}, type = {Discussion Paper}, number = {98}, url = {http://www.stat.uni-muenchen.de/sfb386/} } @Article{vcd:Snee:1974, author = {R. D. Snee}, title = {Graphical Display of Two-Way Contingency Tables}, journal = {The American Statistician}, year = 1974, volume = 28, pages = {9--12} } @Article{vcd:Bickel+Hammel+O'Connell:1975, author = {P. J. Bickel and E. A. Hammel and J. W. O'Connell}, title = {Sex Bias in Graduate Admissions: Data from {B}erkeley}, journal = {Science}, year = 1975, volume = 187, pages = {398--403} } @Book{vcd:Gilbert:1981, author = {G. N. Gilbert}, title = {Modelling Society: An Introduction to Loglinear Analysis for Social Researchers}, publisher = {Allen and Unwin}, year = 1981, address = {London} } @Book{vcd:Thornes+Collard:1979, author = {B. Thornes and J. Collard}, title = {Who Divorces?}, publisher = {Routledge \& Kegan}, year = 1979, address = {London} } @Article{vcd:Dawson:1995, author = {Robert J. MacG Dawson}, title = {The ``Unusual Episode'' Data Revisited}, journal = {Journal of Statistics Education}, year = 1995, volume = 3, url = {http://www.amstat.org/publications/jse/v3n3/datasets.dawson.html} } @Article{vcd:Haberman:1974, author = {S. J. Haberman}, title = {Log-linear Models for Frequency Tables with Ordered Classifications}, journal = {Biometrics}, year = 1974, volume = 30, pages = {689--700} } @Article{vcd:Wing:1962, author = {J. K. Wing}, title = {Institutionalism in Mental Hospitals}, journal = {British Journal of Social Clinical Psychology}, year = 1962, volume = 1, pages = {38--51} } @Book{vcd:Andersen:1991, author = {E. B. Andersen}, title = {The Statistical Analysis of Categorical Data}, publisher = {Springer-Verlag}, year = {1991}, address = {Berlin}, edition = {2nd} } @Article{vcd:Haberman:1973, author = {S. J. Haberman}, title = {The Analysis of Residuals in Cross-classified Tables}, journal = {Biometrics}, year = {1973}, volume = {29}, pages = {205--220} } @Book{vcd:Everitt+Hothorn:2006, author = {Brian S. Everitt and Torsten Hothorn}, title = {A Handbook of Statistical Analyses Using \textsf{R}}, publisher = {Chapman \& Hall/CRC}, address = {Boca Raton, Florida}, year = {2006} } @Article{vcd:Salib+Hillier:1997, author = {Emad Salib and Valerie Hillier}, title = {A Case-Control Study of Smoking and {A}lzheimer's Disease}, journal = {International Journal of Geriatric Psychiatry}, year = {1997}, volume = {12}, pages = {295--300} } %% inference @Book{vcd:Agresti:2002, author = {Alan Agresti}, title = {Categorical Data Analysis}, publisher = {John Wiley \& Sons}, year = {2002}, address = {Hoboken, New Jersey}, edition = {2nd} } @Book{vcd:Mazanec+Strasser:2000, author = {Josef A. Mazanec and Helmut Strasser}, title = {A Nonparametric Approach to Perceptions-based Market Segmentation: Foundations}, publisher = {Springer-Verlag}, year = {2000}, address = {Berlin} } @Article{vcd:Strasser+Weber:1999, author = {Helmut Strasser and Christian Weber}, title = {On the Asymptotic Theory of Permutation Statistics}, journal = {Mathematical Methods of Statistics}, volume = {8}, pages = {220--250}, year = {1999} } @Book{vcd:Pesarin:2001, author = {Fortunato Pesarin}, title = {Multivariate Permutation Tests}, year = {2001}, publisher = {John Wiley \& Sons}, address = {Chichester} } @Article{vcd:Ernst:2004, author = {Michael D. Ernst}, title = {Permutation Methods: A Basis for Exact Inference}, journal = {Statistical Science}, volume = {19}, year = {2004}, pages = {676--685} } @Article{vcd:Patefield:1981, author = {W. M. Patefield}, title = {An Efficient Method of Generating $R \times C$ Tables with Given Row and Column Totals}, note = {{A}lgorithm AS 159}, journal = {Applied Statistics}, volume = {30}, year = {1981}, pages = {91--97} } %% own @InProceedings{vcd:Meyer+Zeileis+Hornik:2003, author = {David Meyer and Achim Zeileis and Kurt Hornik}, title = {Visualizing Independence Using Extended Association Plots}, booktitle = {Proceedings of the 3rd International Workshop on Distributed Statistical Computing, Vienna, Austria}, editor = {Kurt Hornik and Friedrich Leisch and Achim Zeileis}, year = {2003}, url = {http://www.ci.tuwien.ac.at/Conferences/DSC-2003/Proceedings/}, note = {{ISSN 1609-395X}}, } @TechReport{vcd:Zeileis+Meyer+Hornik:2005, author = {Achim Zeileis and David Meyer and Kurt Hornik}, title = {Residual-based Shadings for Visualizing (Conditional) Independence}, institution = {Department of Statistics and Mathematics, Wirtschaftsuniversit\"at Wien, Research Report Series}, year = {2005}, type = {Report}, number = {20}, month = {August}, url = {http://epub.wu-wien.ac.at/dyn/openURL?id=oai:epub.wu-wien.ac.at:epub-wu-01_871} } @Article{vcd:Zeileis+Meyer+Hornik:2007, author = {Achim Zeileis and David Meyer and Kurt Hornik}, title = {Residual-based Shadings for Visualizing (Conditional) Independence}, journal = {Journal of Computational and Graphical Statistics}, year = {2007}, volume = {16}, number = {3}, pages = {507--525}, doi = {10.1198/106186007X237856}, url = {http://statmath.wu-wien.ac.at/~zeileis/papers/Zeileis+Meyer+Hornik-2007.pdf} } @TechReport{vcd:Meyer+Zeileis+Hornik:2005a, author = {David Meyer and Achim Zeileis and Kurt Hornik}, title = {The Strucplot Framework: Visualizing Multi-Way Contingency Tables with \pkg{vcd}}, institution = {Department of Statistics and Mathematics, Wirtschaftsuniversit\"at Wien, Research Report Series}, year = {2005}, type = {Report}, number = {22}, month = {November}, url = {http://epub.wu-wien.ac.at/dyn/openURL?id=oai:epub.wu-wien.ac.at:epub-wu-01_8a1} } @Article{vcd:Meyer+Zeileis+Hornik:2006b, author = {David Meyer and Achim Zeileis and Kurt Hornik}, title = {The Strucplot Framework: Visualizing Multi-way Contingency Tables with \pkg{vcd}}, year = {2006}, journal = {Journal of Statistical Software}, volume = {17}, number = {3}, pages = {1--48}, url = {http://www.jstatsoft.org/v17/i03/} } @InCollection{vcd:Meyer+Zeileis+Hornik:2006a, author = {David Meyer and Achim Zeileis and Kurt Hornik}, title = {Visualizing Contingency Tables}, editor = {Chun-Houh Chen and Wolfang H\"ardle and Antony Unwin}, booktitle = {Handbook of Data Visualization}, series = {Springer Handbooks of Computational Statistics}, year = {2006}, publisher = {Springer-Verlag}, address = {New York}, note = {{ISBN} 3-540-33036-4, to appear} } @Article{vcd:Hothorn+Hornik+VanDeWiel:2006, author = {Torsten Hothorn and Kurt Hornik and Mark A. van de Wiel and Achim Zeileis}, title = {A {L}ego System for Conditional Inference}, journal = {The American Statistician}, year = {2006}, volume = {60}, number = {3}, pages = {257--263}, doi = {10.1198/000313006X118430} } @TechReport{vcd:Zeileis+Hornik:2006, author = {Achim Zeileis and Kurt Hornik}, title = {Choosing Color Palettes for Statistical Graphics}, institution = {Department of Statistics and Mathematics, Wirtschaftsuniversit\"at Wien, Research Report Series}, year = {2006}, type = {Report}, number = {41}, month = {October}, url = {http://epub.wu-wien.ac.at/} } %% bad color examples @Article{vcd:Gneiting+Sevcikova+Percival:2006, author = {Tilmann Gneiting and Hana \v{S}ev\v{c}\'ikov\'a and Donald B. Percival and Martin Schlather and Yindeng Jiang}, title = {Fast and Exact Simulation of Large Gaussian Lattice Systems in {$\mathbb{R}^2$}: Exploring the Limits}, year = {2006}, journal = {Journal of Computational and Graphical Statistics}, volume = {15}, number = {3}, pages = {483--501}, note = {Figures~1--4} } @Article{vcd:Yang+Buckley+Dudoit:2002, author = {Yee Hwa Yang and Michael J. Buckley and Sandrine Dudoit and Terence P. Speed}, title = {Comparison of Methods for Image Analysis on {cDNA} Microarray Data}, year = {2002}, journal = {Journal of Computational and Graphical Statistics}, volume = {11}, number = {1}, pages = {108--136}, note = {Figure~4a} } @Article{vcd:Kneib:2006, author = {Thomas Kneib}, title = {Mixed Model-based Inference in Geoadditive Hazard Regression for Interval-censored Survival Times}, year = {2006}, journal = {Computational Statistics \& Data Analysis}, volume = {51}, pages = {777--792}, note = {Figure~5 (left)} } @Article{vcd:Friendly:2002, author = {Michael Friendly}, title = {A Brief History of the Mosaic Display}, year = {2002}, journal = {Journal of Computational and Graphical Statistics}, volume = {11}, number = {1}, pages = {89--107}, note = {Figure~11 (left, middle)} } @Article{vcd:Celeux+Hurn+Robert:2000, author = {Gilles Celeux and Merrilee Hurn and Christian P. Robert}, title = {Computational and Inferential Difficulties with Mixture Posterior Distributions}, year = {2000}, journal = {Journal of the American Statistical Association}, volume = {95}, number = {451}, pages = {957--970}, note = {Figure~3} } %% pointers from Hadley @article{cleveland:1987, Author = {Cleveland, William and McGill, Robert}, Journal = {Journal of the Royal Statistical Society A}, Number = {3}, Pages = {192-229}, Title = {Graphical Perception: The Visual Decoding of Quantitative Information on Graphical Displays of Data}, Volume = {150}, Year = {1987}} @article{cleveland:1984, Author = {Cleveland, William S. and McGill, M. E.}, Journal = {Journal of the American Statistical Association}, Number = 387, Pages = {531-554}, Title = {Graphical Perception: Theory, Experimentation and Application to the Development of Graphical Methods}, Volume = 79, Year = 1984} @article{huang:1997, Author = {Huang, Chisheng and McDonald, John Alan and Stuetzle, Werner}, Journal = {Journal of Computational and Graphical Statistics}, Pages = {383--396}, Title = {Variable resolution bivariate plots}, Volume = {6}, Year = {1997}} @article{carr:1987, Author = {Carr, D. B. and Littlefield, R. J. and Nicholson, W. L. and Littlefield, J. S.}, Journal = {Journal of the American Statistical Association}, Number = {398}, Pages = {424-436}, Title = {Scatterplot Matrix Techniques for Large N}, Volume = {82}, Year = {1987}} @book{cleveland:1994, Author = {Cleveland, William}, Publisher = {Hobart Press}, Title = {The Elements of Graphing Data}, Year = {1994}} @book{chambers:1983, Author = {Chambers, John and Cleveland, William and Kleiner, Beat and Tukey, Paul}, Publisher = {Wadsworth}, Title = {Graphical methods for data analysis}, Year = {1983}} @book{bertin:1983, Address = {Madison, WI}, Author = {Bertin, Jacques}, Publisher = {University of Wisconsin Press}, Title = {Semiology of Graphics}, Year = {1983}} @book{wilkinson:2006, Author = {Wilkinson, Leland}, Publisher = {Springer-Verlag}, Series = {Statistics and Computing}, Title = {The Grammar of Graphics}, Year = {2005}} vcd/vignettes/Z.cls0000644000175300001440000001703411720273431013626 0ustar meyerusers\def\fileversion{1.1} \def\filename{Z} \def\filedate{2006/10/11} %% %% Package `Z' to use with LaTeX2e for Z reports %% Copyright (C) 2004 Achim Zeileis %% \NeedsTeXFormat{LaTeX2e} \ProvidesClass{Z}[\filedate\space\fileversion\space Z class by Achim Zeileis] %% options \LoadClass[10pt,twoside]{article} \newif\if@notitle \@notitlefalse \newif\if@noheadings \@noheadingsfalse \DeclareOption{notitle}{\@notitletrue} \DeclareOption{noheadings}{\@noheadingstrue} \ProcessOptions %% required packages \RequirePackage{graphicx,color,hyperref,ae,fancyvrb} %\RequirePackage{thumbPDF} \RequirePackage[T1]{fontenc} \usepackage[authoryear,round,longnamesfirst]{natbib} \bibpunct{(}{)}{;}{a}{}{,} \bibliographystyle{jss} %% paragraphs \setlength{\parskip}{0.7ex plus0.1ex minus0.1ex} \setlength{\parindent}{0em} %% for all publications \newcommand{\Plaintitle}[1]{\def\@Plaintitle{#1}} \newcommand{\Shorttitle}[1]{\def\@Shorttitle{#1}} \newcommand{\Plainauthor}[1]{\def\@Plainauthor{#1}} \newcommand{\Keywords}[1]{\def\@Keywords{#1}} \newcommand{\Plainkeywords}[1]{\def\@Plainkeywords{#1}} \newcommand{\Abstract}[1]{\def\@Abstract{#1}} %% defaults \author{Firstname Lastname\\Affiliation} \title{Title} \Abstract{---!!!---an abstract is required---!!!---} \Plainauthor{\@author} \Plaintitle{\@title} \Shorttitle{\@title} \Keywords{---!!!---at least one keyword is required---!!!---} \Plainkeywords{\@Keywords} %% Sweave(-like) \DefineVerbatimEnvironment{Sinput}{Verbatim}{fontshape=sl} \DefineVerbatimEnvironment{Soutput}{Verbatim}{} \DefineVerbatimEnvironment{Scode}{Verbatim}{fontshape=sl} \newenvironment{Schunk}{}{} \setkeys{Gin}{width=0.8\textwidth} %% new \maketitle \def\maketitle{ \begingroup \def\thefootnote{\fnsymbol{footnote}} \def\@makefnmark{\hbox to 0pt{$^{\@thefnmark}$\hss}} \long\def\@makefntext##1{\parindent 1em\noindent \hbox to1.8em{\hss $\m@th ^{\@thefnmark}$}##1} \@maketitle \@thanks \endgroup \setcounter{footnote}{0} \if@noheadings %% \thispagestyle{empty} %% \markboth{\centerline{\@Shorttitle}}{\centerline{\@Plainauthor}} %% \pagestyle{myheadings} \else \thispagestyle{empty} \markboth{\centerline{\@Shorttitle}}{\centerline{\@Plainauthor}} \pagestyle{myheadings} \fi \let\maketitle\relax \let\@maketitle\relax \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\let\thanks\relax } % Author information can be set in various styles: % For several authors from the same institution: % \author{Author 1 \and ... \and Author n \\ % Address line \\ ... \\ Address line} % if the names do not fit well on one line use % Author 1 \\ {\bf Author 2} \\ ... \\ {\bf Author n} \\ % For authors from different institutions: % \author{Author 1 \\ Address line \\ ... \\ Address line % \And ... \And % Author n \\ Address line \\ ... \\ Address line} % To start a seperate ``row'' of authors use \AND, as in % \author{Author 1 \\ Address line \\ ... \\ Address line % \AND % Author 2 \\ Address line \\ ... \\ Address line \And % Author 3 \\ Address line \\ ... \\ Address line} \def\@maketitle{\vbox{\hsize\textwidth \linewidth\hsize {\centering {\LARGE\bf \@title\par} \vskip 0.2in plus 1fil minus 0.1in { \def\and{\unskip\enspace{\rm and}\enspace}% \def\And{\end{tabular}\hss \egroup \hskip 1in plus 2fil \hbox to 0pt\bgroup\hss \begin{tabular}[t]{c}\large\bf\rule{\z@}{24pt}\ignorespaces}% \def\AND{\end{tabular}\hss\egroup \hfil\hfil\egroup \vskip 0.1in plus 1fil minus 0.05in \hbox to \linewidth\bgroup\rule{\z@}{10pt} \hfil\hfil \hbox to 0pt\bgroup\hss \begin{tabular}[t]{c}\large\bf\rule{\z@}{24pt}\ignorespaces} \hbox to \linewidth\bgroup\rule{\z@}{10pt} \hfil\hfil \hbox to 0pt\bgroup\hss \begin{tabular}[t]{c}\large\bf\rule{\z@}{24pt}\@author \end{tabular}\hss\egroup \hfil\hfil\egroup} \vskip 0.3in minus 0.1in \hrule \begin{abstract} \@Abstract \end{abstract}} \textit{Keywords}:~\@Keywords. \vskip 0.1in minus 0.05in \hrule \vskip 0.2in minus 0.1in }} %% \def\@maketitle{\vbox{\hsize\textwidth \linewidth\hsize %% {\centering %% {\LARGE\bf \@title\par} %% \def\And{\end{tabular}\hfil\linebreak[0]\hfil %% \begin{tabular}[t]{c}\large\bf\rule{\z@}{24pt}\ignorespaces}% %% \begin{tabular}[t]{c}\large\bf\rule{\z@}{24pt}\@author\end{tabular}% %% \vskip 0.3in minus 0.1in %% \hrule %% \begin{abstract} %% \@Abstract %% \end{abstract}} %% \textit{Keywords}:~\@Keywords. %% \vskip 0.1in minus 0.05in %% \hrule %% \vskip 0.2in minus 0.1in %% }} %% sections, subsections, and subsubsections \newlength{\preXLskip} \newlength{\preLskip} \newlength{\preMskip} \newlength{\preSskip} \newlength{\postMskip} \newlength{\postSskip} \setlength{\preXLskip}{1.8\baselineskip plus 0.5ex minus 0ex} \setlength{\preLskip}{1.5\baselineskip plus 0.3ex minus 0ex} \setlength{\preMskip}{1\baselineskip plus 0.2ex minus 0ex} \setlength{\preSskip}{.8\baselineskip plus 0.2ex minus 0ex} \setlength{\postMskip}{.5\baselineskip plus 0ex minus 0.1ex} \setlength{\postSskip}{.3\baselineskip plus 0ex minus 0.1ex} \newcommand{\jsssec}[2][default]{\vskip \preXLskip% \pdfbookmark[1]{#1}{Section.\thesection.#1}% \refstepcounter{section}% \centerline{\textbf{\Large \thesection. #2}} \nopagebreak \vskip \postMskip \nopagebreak} \newcommand{\jsssecnn}[1]{\vskip \preXLskip% \centerline{\textbf{\Large #1}} \nopagebreak \vskip \postMskip \nopagebreak} \newcommand{\jsssubsec}[2][default]{\vskip \preMskip% \pdfbookmark[2]{#1}{Subsection.\thesubsection.#1}% \refstepcounter{subsection}% \textbf{\large \thesubsection. #2} \nopagebreak \vskip \postSskip \nopagebreak} \newcommand{\jsssubsecnn}[1]{\vskip \preMskip% \textbf{\large #1} \nopagebreak \vskip \postSskip \nopagebreak} \newcommand{\jsssubsubsec}[2][default]{\vskip \preSskip% \pdfbookmark[3]{#1}{Subsubsection.\thesubsubsection.#1}% \refstepcounter{subsubsection}% {\large \textit{#2}} \nopagebreak \vskip \postSskip \nopagebreak} \newcommand{\jsssubsubsecnn}[1]{\vskip \preSskip% {\textit{\large #1}} \nopagebreak \vskip \postSskip \nopagebreak} \newcommand{\jsssimplesec}[2][default]{\vskip \preLskip% %% \pdfbookmark[1]{#1}{Section.\thesection.#1}% \refstepcounter{section}% \textbf{\large #1} \nopagebreak \vskip \postSskip \nopagebreak} \newcommand{\jsssimplesecnn}[1]{\vskip \preLskip% \textbf{\large #1} \nopagebreak \vskip \postSskip \nopagebreak} \renewcommand{\section}{\secdef \jsssec \jsssecnn} \renewcommand{\subsection}{\secdef \jsssubsec \jsssubsecnn} \renewcommand{\subsubsection}{\secdef \jsssubsubsec \jsssubsubsecnn} %% colors \definecolor{Red}{rgb}{0.7,0,0} \definecolor{Blue}{rgb}{0,0,0.8} \hypersetup{% hyperindex = {true}, colorlinks = {true}, linktocpage = {true}, plainpages = {false}, linkcolor = {Blue}, citecolor = {Blue}, urlcolor = {Red}, pdfstartview = {Fit}, pdfpagemode = {UseOutlines}, pdfview = {XYZ null null null} } \AtBeginDocument{ \hypersetup{% pdfauthor = {\@Plainauthor}, pdftitle = {\@Plaintitle}, pdfkeywords = {\@Plainkeywords} } } \if@notitle %% \AtBeginDocument{\maketitle} \else \AtBeginDocument{\maketitle} \fi %% commands \makeatletter \newcommand\code{\bgroup\@makeother\_\@codex} \def\@codex#1{{\normalfont\ttfamily\hyphenchar\font=-1 #1}\egroup} \makeatother %%\let\code=\texttt \let\proglang=\textsf \newcommand{\pkg}[1]{{\normalfont\fontseries{b}\selectfont #1}} \newcommand{\email}[1]{\href{mailto:#1}{\normalfont\texttt{#1}}} \newcommand{\doi}[1]{\href{http://dx.doi.org/#1}{\normalfont\texttt{doi:#1}}} \newcommand{\E}{\mathsf{E}} \newcommand{\VAR}{\mathsf{VAR}} \newcommand{\COV}{\mathsf{COV}} \newcommand{\Prob}{\mathsf{P}} vcd/vignettes/struc.pdf0000644000175300001440000000622011720273431014540 0ustar meyerusers%PDF-1.4 % 1 0 obj << /Length 2 0 R /Filter /FlateDecode >> stream xZn7 ?l99Hrv$ ?;A /=CɥZIP "ݬ.6əˋ Ya!jU_ȿvy!"LN//Y,6Hh ƶNيȽŝpX470/kj4~r-.eQCx4 |6RIᢾaBZ[F$'%8+[~U[uR[K@L]tcҡú7Ӵ6VgwBu(HqkWiK1uґF[K@o$T'j2kHA6ĢĐNWd#@c6ZJl`)cVٸF0@еXh>NuA?Q`~E[JJ) -b-[yy ƕҀ~L~iiuuPiIn00-ݨJ.jS~#S(^" YQm"PSvg[*C3*Ne ~*=zKek08-RzY cAm3yAF3s),>7l^Z")h&n ٣LIkkFr^Z3%E%vmk(;,*XK憣Ξn?ⅅ3LӷҜ9E#:{h5lg!䰩\j鷣mN1,#QFvhMBp[cl嚢((.)oW좵ۀٷXw";!B%x5*Z-tM^?푉׫[wHδe!]=Wix09Es{kp5 R.l'DodP"!YFh-UdYrB;qڣaJSvR(AT^ -,na&Qr!t  \\UӸDtPt-3ݘslHAVsF@{Tf!.Sڳ 埝'n5n']y<,i|-xѰ&ؒl9ǩs5K( gsņaqRR$+ܕ< zֺ'-]{=`_Cby3?a:H}22Ԉ+cMBܘ0>5 Q 1DN!S=A”Duibj/VZT_f~5@Mx#CkƸF+sG/h<,p @4^SL2:QI'4#w}Ǘ v35 O kڻq:2H/k:o^a{ͣQ'}nLQ˟+?YgX< ݨy:,Ҩ1);mG@cEI7%.`4ڨUҏyB3|SWS܉1mZ@X#d~TƔJ_&endstream endobj 2 0 obj 1891 endobj 4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Courier /Encoding /WinAnsiEncoding >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >> endobj 6 0 obj << /F1 5 0 R /F2 4 0 R >> endobj 7 0 obj << /Font 6 0 R /ProcSet [ /PDF ] >> endobj 8 0 obj << /Type /Page /Parent 3 0 R /Resources 7 0 R /MediaBox [ 0 0 794 595 ] /Contents 1 0 R >> endobj 3 0 obj << /Type /Pages /Resources 7 0 R /MediaBox [ 0 0 595 842 ] /Kids [ 8 0 R ] /Count 1 >> endobj 9 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 10 0 obj << /Creator /Producer /CreationDate (D:20051019112228+02'00') >> endobj xref 0 11 0000000000 65535 f 0000000017 00000 n 0000001993 00000 n 0000002495 00000 n 0000002020 00000 n 0000002133 00000 n 0000002248 00000 n 0000002302 00000 n 0000002367 00000 n 0000002631 00000 n 0000002690 00000 n trailer << /Size 11 /Root 9 0 R /Info 10 0 R >> startxref 2901 %%EOF vcd/vignettes/strucplot.Rnw0000644000175300001440000031127011720273431015440 0ustar meyerusers\documentclass[noJSS]{jss} %% need no \usepackage{Sweave} \usepackage{thumbpdf} %% almost as usual \author{David Meyer, Achim Zeileis, \textnormal{and} Kurt Hornik\\Wirtschaftsuniversit\"at Wien, Austria} \title{The Strucplot Framework:\\ Visualizing Multi-way Contingency Tables with \pkg{vcd}} %% for pretty printing and a nice hypersummary also set: \Plainauthor{David Meyer, Achim Zeileis, Kurt Hornik} %% comma-separated \Shorttitle{The Strucplot Framework} %% a short title (if necessary) \Plaintitle{The Strucplot Framework: Visualizing Multi-way Contingency Tables with vcd} %% an abstract and keywords \Abstract{ This paper has been published in the Journal of Statistical Software \citep{vcd:Meyer+Zeileis+Hornik:2006b} and describes the ``strucplot'' framework for the visualization of multi-way contingency tables. Strucplot displays include hierarchical conditional plots such as mosaic, association, and sieve plots, and can be combined into more complex, specialized plots for visualizing conditional independence, GLMs, and the results of independence tests. The framework's modular design allows flexible customization of the plots' graphical appearance, including shading, labeling, spacing, and legend, by means of ``graphical appearance control'' functions. The framework is provided by the \proglang{R} package \pkg{vcd}. } \Keywords{contingency tables, mosaic plots, association plots, sieve plots, categorical data, independence, conditional independence, HSV, HCL, residual-based shading, \pkg{grid}, \proglang{R}} \Plainkeywords{contingency tables, mosaic plots, association plots, sieve plots, categorical data, independence, conditional independence, HSV, HCL, residual-based shading, grid, R} \SweaveOpts{engine=R,eps=TRUE,height=6,width=7,results=hide,fig=FALSE,echo=TRUE} \setkeys{Gin}{width=0.7\textwidth} %\VignetteIndexEntry{The Strucplot Framework: Visualizing Multi-way Contingency Tables with vcd} %\VignetteDepends{vcd} %\VignetteKeywords{contingency tables, mosaic plots, association plots, sieve plots, categorical data, independence, conditional independence, HSV, HCL, residual-based shading, grid, R} %\VignettePackage{vcd} <>= set.seed(1071) library(vcd) data(Titanic) data(HairEyeColor) data(PreSex) data(Arthritis) art <- xtabs(~Treatment + Improved, data = Arthritis) @ \newcommand{\var}[1]{\textit{\texttt{#1}}} \newcommand{\data}[1]{\texttt{#1}} \newcommand{\class}[1]{\textsf{#1}} %% \code without `-' ligatures \def\nohyphenation{\hyphenchar\font=-1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font=`-} {\catcode`\-=\active% \global\def\code{\bgroup% \catcode`\-=\active \let-\codedash% \Rd@code}} \def\codedash{-\discretionary{}{}{}} \def\Rd@code#1{\texttt{\nohyphenation#1}\egroup} \newcommand{\codefun}[1]{\code{#1()}} %% end of declarations %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{document} %% include your article here, just as usual %% Note that you should use the \pkg{}, \proglang{} and \code{} commands. \section[Introduction]{Introduction} %% Note: If there is markup in \(sub)section, then it has to be escape as above. In order to explain multi-dimensional categorical data, statisticians typically look for (conditional) independence structures. Whether the task is purely exploratory or model-based, techniques such as mosaic and association plots offer good support for visualization. Both visualize aspects of (possibly higher-dimensional) contingency tables, with several extensions introduced over the last two decades, and implementations available in many statistical environments. A \emph{mosaic plot} \citep{vcd:Hartigan+Kleiner:1984} is basically an area-proportional visualization of (typically, observed) frequencies, composed of tiles (corresponding to the cells) created by recursive vertical and horizontal splits of a rectangle. Thus, the area of each tile is proportional to the corresponding cell entry \emph{given} the dimensions of previous splits. An \emph{association plot} \citep{vcd:Cohen:1980} visualizes the standardized deviations of observed frequencies from those expected under a certain independence hypothesis. Each cell is represented by a rectangle that has (signed) height proportional to the residual and width proportional to the square root of the expected counts, so that the area of the box is proportional to the difference in observed and expected frequencies. Extensions to these techniques have mainly focused on the following aspects. \begin{enumerate} \item Varying the shape of bar plots and mosaic displays to yield, e.g., double-decker plots \citep{vcd:hofmann:2001}, spine plots, or spinograms \citep{vcd:hofmann+theus}. \item Using residual-based shadings to visualize log-linear models \citep{vcd:Friendly:1994,vcd:Friendly:2000} and significance of statistical tests \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Zeileis+Meyer+Hornik:2005}. \item Using pairs plots and trellis-like layouts for marginal, conditional and partial views \citep{vcd:Friendly:1999}. \item Adding direct user interaction, allowing quick exploration and modification of the visualized models \citep{vcd:Unwin+Hawkins+Hofmann:1996,vcd:Theus:2003}. \item Providing a modular and flexible implementation to easily allow user extensions \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Meyer+Zeileis+Hornik:2006b}. \end{enumerate} \noindent Current implementations of mosaic displays can be found, e.g., for \proglang{SAS} \citep{vcd:SAS:2005}, \pkg{ViSta} \citep{vcd:young:1996}, \pkg{MANET} \citep{vcd:Unwin+Hawkins+Hofmann:1996}, \pkg{Mondrian} \citep{vcd:Theus:2003}, \proglang{R} \citep{vcd:R:2006}, and \proglang{S-PLUS} \citep{vcd:SPLUS:2005}. For \proglang{R}, currently three implementations do exist in the packages \pkg{graphics} (in base \proglang{R}), \pkg{vcd} \citep{vcd:Meyer+Zeileis+Hornik:2006b}, and \pkg{iplots} \citep{vcd:urbanek+wichtrey:2006}, respectively. Table \ref{tab:compare} gives an overview of the available functionality in these systems. Most environments are available on Windows, MacOS, and Linux/Unix variants, except \pkg{MANET} which is only available for the Macinthosh platforms. \begin{table}[h] \centering \begin{tabular}{|l|c|c|c|c|c|c|c|c|c|} \hline & & &\multicolumn{3}{c|}{} & & &\\ & \proglang{SAS} & \proglang{S-PLUS} &\multicolumn{3}{c|}{\proglang{R}} & \pkg{ViSta} & \pkg{MANET} & \pkg{Mondrian}\\ & & &\pkg{base}&\pkg{vcd} &\pkg{iplots}& & &\\\hline Basic functionality & $\times$ & $\times$ & $\times$ &$\times$ &$\times$ & $\times$ & $\times$& $\times$\\ Shape & & & &$\times$ && $\times$ & $\times$&\\ Res.-based shadings & $\times$ & & $\times$ & $\times$ & ($\times$) & &($\times$)& ($\times$)\\ Highlighting & & & &$\times$ &$\times$ & $\times$ & $\times$& $\times$\\ Conditional views & $\times$ & & &$\times$ & & $\times$ & $\times$&\\ Interaction & & & & &$\times$ & $\times$ & $\times$& $\times$\\ Linking & & & & &$\times$ & $\times$ & $\times$& $\times$\\ Extensible design & & & &$\times$ & & & &\\ Language & \proglang{SAS} & \proglang{S} & \proglang{R} & \proglang{R} & \proglang{R}/\proglang{Java} & \proglang{XLisp} & \proglang{C++} & \proglang{Java}\\ \hline \end{tabular} \caption{Comparison of current software environments.} \label{tab:compare} \end{table} Figures \ref{fig:arthritis} to \ref{fig:titanic} illustrate some of these extensions. Figure~\ref{fig:arthritis} shows the results from a double-blind clinical trial investigating a new treatment for rheumatoid arthritis, using an extended mosaic plot with residual-based shading based on the maximum statistic: clearly, the new treatment is effective. The dark blue cell indicates that the rate of treated patients showing marked improvement is significant at the 1\% level. Figure \ref{fig:ucbadmissions} visualizes the well-known UCB admissions data by means of a conditional association plot. The panels show the residuals from a conditional independence model (independence of gender and admission, given department), stratified by department. Clearly, the situation in department A (more women/less men accepted than would be expected under the null hypothesis) causes the rejection of the hypothesis of conditional independence. Figure~\ref{fig:presex} illustrates the conditional independence of premarital and extramarital sex, given gender and marital status. The $\chi^2$ test of independence, based on the permutation distribution, rejects the null hypothesis: possibly, because the tendency of people to have extramarital sex when they had premarital sex is particularly marked among married people? The rate of such women and men ist significant at the 0.01 and 0.1 level, respectively. Finally, Figure~\ref{fig:titanic} visualizes the ``Survival on the Titanic'' data using a double-decker plot. Here, a binary response (survival of the disaster) is to be explained by other factors (class, gender, and age). The gray boxes represent the proportion of survived passengers in a particular stratum. The proportions of saved women and children are indeed higher than those of men, but they clearly decrease from the 1st to the 3rd class. In addition, the proportion of saved men in the 1st class is higher than in the others. \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[p] \begin{center} <>= mosaic(art, gp = shading_max, split_vertical = TRUE) @ \caption{Mosaic plot for the \data{Arthritis} data.} \label{fig:arthritis} \end{center} \end{figure} \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= cotabplot(UCBAdmissions, panel = cotab_coindep, shade = TRUE, legend = FALSE, type = "assoc") @ \caption{Conditional association plot for the \data{UCBAdmissions} data.} \label{fig:ucbadmissions} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[p] \begin{center} <>= presextest <- coindep_test(PreSex, margin = c(1,4), indepfun = function(x) sum(x^2), n = 5000) mosaic(PreSex, condvars = c(1, 4), shade = TRUE, gp_args = list(p.value = presextest$p.value)) @ \caption{Mosaic plot for the \data{PreSex} data.} \label{fig:presex} \end{center} \end{figure} \setkeys{Gin}{width=0.8\textwidth} \begin{figure}[p] \begin{center} <>= doubledecker(Survived ~ ., data = Titanic, labeling_args = list(set_varnames = c(Sex = "Gender"))) @ \caption{Double-decker plot for the \data{Titanic} data.} \label{fig:titanic} \end{center} \end{figure} This paper describes the strucplot framework provided by the \pkg{vcd} package for the \proglang{R} environment for statistical computing and graphics, available from the Comprehensive \proglang{R} Archive Network (\url{http://CRAN.R-project.org/}). The framework integrates displays such as mosaic, association, and sieve plots by their unifying property of being flat representations of contingency tables. These basic plots, as well as specialized displays for conditional independence, can be used both for exploratory visualization and model-based analysis. Exploratory techniques include specialized displays for the bivariate case, as well as pairs and trellis-type displays for higher-dimensional tables. Model-based tools include methods suitable for the visualization of conditional independence tests (including permutation tests), as well as for the visualization of particular GLMs (logistic regression, log-linear models). Additionally, two of the framework's further strengths are its flexibility and extensibility: graphical appearance aspects such as shading, labeling, and spacing are modularized by means of ``\underline{\vphantom{g}gr}aphical \underline{\vphantom{g}ap}pearance \underline{\vphantom{g}con}trol'' (\emph{grapcon}) functions, allowing fine-granular customization and user-level extensions. The remainder of the paper is organized as follows. In Section \ref{sec:strucplot}, we give an overview of the strucplot framework, describing the hierarchy of the main components and the basic functionality. In Section \ref{sec:shading}, we demonstrate how (residual-based) shadings support the visualization of log-linear models and the results of independence tests. Also, we explain step-by-step how the concepts of generating and grapcon functions can be combined to provide a flexible customization of complex graphical displays as created by the strucplot framework. Sections \ref{sec:labeling} and \ref{sec:spacing} discuss in detail the labeling and spacing features, respectively. Section \ref{sec:example} exemplifies the framework in the analysis of a four-way data set. Section \ref{sec:conclusion} concludes the work. \section[The strucplot framework]{The strucplot framework} \label{sec:strucplot} The strucplot framework in the \proglang{R} package \pkg{vcd}, used for visualizing multi-way contingency tables, integrates techniques such as mosaic displays, association plots, and sieve plots. The main idea is to visualize the tables' cells arranged in rectangular form. For multi-way tables, the variables are nested into rows and columns using recursive conditional splits, given the margins. The result is a ``flat'' representation that can be visualized in ways similar to a two-dimensional table. This principle defines a class of conditional displays which allows for granular control of graphical appearance aspects, including: \begin{itemize} \item the content of the tiles \item the split direction for each dimension \item the graphical parameters of the tiles' content \item the spacing between the tiles \item the labeling of the tiles \end{itemize} The strucplot framework is highly modularized: Figure~\ref{fig:struc} shows the hierarchical relationship between the various components. On the lowest level, there are several groups of workhorse and parameter functions that directly or indirectly influence the final appearance of the plot (see Table \ref{tab:grapcons} for an overview). These are examples of grapcon functions. They are created by generating functions (\emph{grapcon generators}), allowing flexible parameterization and extensibility (Figure~\ref{fig:struc} only shows the generators). The generator names follow the naming convention \code{\textit{group\_foo}()}, where \code{\textit{group}} reflects the group the generators belong to (strucplot core, labeling, legend, shading, or spacing). The workhorse functions (created by \code{struc\_\textit{foo}()}, \code{labeling\_\textit{foo}()}, and \code{legend\_\textit{foo}()}) directly produce graphical output (i.e., ``add ink to the canvas''), whereas the parameter functions (created by \code{spacing\_\textit{foo}()} and \code{shading\_\textit{foo}()}) compute graphical parameters used by the others. The grapcon functions returned by \code{struc\_\textit{foo}()} implement the core functionality, creating the tiles and their content. On the second level of the framework, a suitable combination of the low-level grapcon functions (or, alternatively, corresponding generating functions) is passed as ``hyperparameters'' to \codefun{strucplot}. This central function sets up the graphical layout using grid viewports (see Figure~\ref{fig:layout}), and coordinates the specified core, labeling, shading, and spacing functions to produce the plot. On the third level, we provide several convenience functions such as \codefun{mosaic}, \codefun{sieve}, \codefun{assoc}, and \codefun{doubledecker} which interface \codefun{strucplot} through sensible parameter defaults and support for model formulae. Finally, on the fourth level, there are ``related'' \pkg{vcd} functions (such as \codefun{cotabplot} and the \codefun{pairs} methods for table objects) arranging collections of plots of the strucplot framework into more complex displays (e.g., by means of panel functions). \begin{table} \begin{tabular}{|l|l|l|} \hline \textbf{Group} & \textbf{Grapcon generator} & \textbf{Description}\\\hline strucplot & \codefun{struc\_assoc} & core function for association plots\\ core & \codefun{struc\_mosaic} & core function for mosaic plots\\ & \codefun{struc\_sieve} & core function for sieve plots\\\hline\hline labeling & \codefun{labeling\_border} & border labels\\ & \codefun{labeling\_cboxed} & centered labels with boxes, all labels clipped,\\ && and on top and left border\\ & \codefun{labeling\_cells} & cell labels\\ & \codefun{labeling\_conditional} & border labels for conditioning variables\\ && and cell labels for conditioned variables\\ & \codefun{labeling\_doubledecker} & draws labels for doubledecker plot\\ & \codefun{labeling\_lboxed} & left-aligned labels with boxes\\ & \codefun{labeling\_left} & left-aligned border labels\\ & \codefun{labeling\_left2} & left-aligned border labels, all labels on top and left border\\ & \codefun{labeling\_list} & draws a list of labels under the plot\\\hline\hline shading & \codefun{shading\_binary} & visualizes the sign of the residuals\\ & \codefun{shading\_Friendly} & implements Friendly shading (based on HSV colors)\\ & \codefun{shading\_hcl} & shading based on HCL colors\\ & \codefun{shading\_hsv} & shading based on HSV colors\\ & \codefun{shading\_max} & shading visualizing the maximum test statistic\\ && (based on HCL colors)\\ & \codefun{shading\_sieve} & implements Friendly shading customized for sieve plots\\ && (based on HCL colors)\\\hline\hline spacing & \codefun{spacing\_conditional} & increasing spacing for conditioning variables,\\&& equal spacing for conditioned variables\\ & \codefun{spacing\_dimequal} & equal spacing for each dimension\\ & \codefun{spacing\_equal} & equal spacing for all dimensions\\ & \codefun{spacing\_highlighting} & increasing spacing, last dimension set to zero\\ & \codefun{spacing\_increase} & increasing spacing\\\hline\hline legend & \codefun{legend\_fixed} & creates a fixed number of bins (similar to \codefun{mosaicplot})\\ & \codefun{legend\_resbased} & suitable for an arbitrary number of bins\\&& (also for continuous shadings)\\\hline \end{tabular} \caption{Available grapcon generators in the strucplot framework} \label{tab:grapcons} \end{table} \begin{figure}[h] \begin{center} \includegraphics[width=0.8\textwidth]{struc} \caption{Components of the strucplot framework.} \label{fig:struc} \end{center} \end{figure} \setkeys{Gin}{width=0.6\textwidth} \begin{figure}[h] \begin{center} <>= pushViewport(vcd:::vcdViewport(legend = T, mar =4)) seekViewport("main") grid.rect(gp = gpar(lwd = 3)) grid.text("main", gp = gpar(fontsize = 20)) seekViewport("sub") grid.rect(gp = gpar(lwd = 3)) grid.text("sub", gp = gpar(fontsize = 20)) seekViewport("plot") grid.rect(gp = gpar(lwd = 3)) grid.text("plot", gp = gpar(fontsize = 20)) seekViewport("legend") grid.text("legend", rot = 90, gp = gpar(fontsize = 20)) grid.rect(gp = gpar(lwd = 3)) seekViewport("legend_sub") grid.rect(gp = gpar(lwd = 3)) grid.text("[F]", gp = gpar(fontsize = 20)) seekViewport("legend_top") grid.rect(gp = gpar(lwd = 3)) grid.text("[E]", gp = gpar(fontsize = 20)) seekViewport("margin_top") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_top", gp = gpar(fontsize = 20)) seekViewport("margin_bottom") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_bottom", gp = gpar(fontsize = 20)) seekViewport("margin_right") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_right", rot = 90, gp = gpar(fontsize = 20)) seekViewport("margin_left") grid.rect(gp = gpar(lwd = 3)) grid.text("margin_left", rot = 90, gp = gpar(fontsize = 20)) seekViewport("corner_top_left") grid.rect(gp = gpar(lwd = 3)) grid.text("[A]", gp = gpar(fontsize = 20)) seekViewport("corner_top_right") grid.rect(gp = gpar(lwd = 3)) grid.text("[B]", gp = gpar(fontsize = 20)) seekViewport("corner_bottom_left") grid.rect(gp = gpar(lwd = 3)) grid.text("[C]", gp = gpar(fontsize = 20)) seekViewport("corner_bottom_right") grid.rect(gp = gpar(lwd = 3)) grid.text("[D]", gp = gpar(fontsize = 20)) @ \caption{Viewport layout for strucplot displays with their names. [A] = ``corner\_top\_left'', [B] = ``corner\_top\_right'', [C] = ``corner\_bottom\_left'', [D] = ``corner\_bottom\_right'', [E] = ``legend\_top'', [F] = ``legend\_sub''.} \label{fig:layout} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \subsection{Mosaic, association, and sieve plots} As an example, consider the \data{HairEyeColor} data containing two polytomous variables (hair and eye color), as well as one (artificial) dichotomous gender variable (\code{Sex}). The ``flattened'' contingency table can be obtained using the \codefun{structable} function (quite similar to \codefun{ftable} in base \proglang{R}, but allowing the specification of split directions): <>= (HEC <- structable(Eye ~ Sex + Hair, data = HairEyeColor)) @ Let us first visualize the contingency table by means of a mosaic plot. % \citep{vcd:Hartigan+Kleiner:1984} which is basically % an area-proportional visualization of (typically, observed) frequencies, composed % of tiles (corresponding to the cells) created by recursive % vertical and horizontal splits of a square. Thus, the area of each tile % is proportional to the corresponding cell entry \emph{given} the % dimensions of previous splits. The effect of <>= mosaic(HEC) @ \noindent equivalent to <>= mosaic(~ Sex + Eye + Hair, data = HairEyeColor) @ %\setkeys{Gin}{width=0.75\textwidth} \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{HairEyeColor} data.} \label{fig:observed} \end{center} \end{figure} \noindent depicts the observed frequencies of the \code{HairEyeColor} data. If there are zero entries, tiles have zero area and are, additionally, marked by small bullets (see, e.g, Figure~\ref{fig:titanic}). By default, these cells are not split further. The bullets help distinguishing very small cells from zero entries, and are particularly useful when color shadings come into play (see the example using the \data{Bundesliga} data in Section \ref{sec:overview}). Note that in contrast to, e.g., \codefun{mosaicplot} in base \proglang{R}, the default split direction and level ordering in all strucplot displays correspond to the textual representation produced by the print methods. It is also possible to visualize the expected values instead of the observed values (see Figure~\ref{fig:expected}): <>= mosaic(HEC, type = "expected") @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{HairEyeColor} data (expected values).} \label{fig:expected} \end{center} \end{figure} %\setkeys{Gin}{width=0.7\textwidth} \noindent In order to compare observed and expected values, a sieve plot \citep{vcd:riedwyl+schuepbach:1994} could be used (see Figure~\ref{fig:sieve}): <>= sieve(~ Sex + Eye + Hair, data = HEC, spacing = spacing_dimequal(c(2,0,0))) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Sieve plot for the \data{HairEyeColor} data visualizing simultaneously observed and expected values.} \label{fig:sieve} \end{center} \end{figure} \noindent where \code{spacing\_dimequal} is used to set the spacing of the second and third dimension to zero. Alternatively, we can directly inspect the residuals. The Pearson residuals (standardized deviations of observed from expected values) are conveniently visualized using association plots \citep{vcd:Cohen:1980}. In contrast to \codefun{assocplot} in base \proglang{R}, \pkg{vcd}'s \codefun{assoc} function scales to more than two variables (see Figure~\ref{fig:residuals}): <>= assoc(HEC, compress = FALSE) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Association plot for the \data{HairEyeColor} data.} \label{fig:residuals} \end{center} \end{figure} \noindent where the \code{compress} argument keeps distances between tiles equal. For both mosaic plots and association plots, the splitting of the tiles can be controlled using the \code{split\_vertical} argument. The default is to alternate splits starting with a horizontal one (see Figure~\ref{fig:split}): <>= options(width=60) @ <>= mosaic(HEC, split_vertical = c(TRUE, FALSE, TRUE), labeling_args = list(abbreviate_labs = c(Eye = 3))) @ <>= options(width=70) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{HairEyeColor} data---alternative splitting.} \label{fig:split} \end{center} \end{figure} \noindent (Note that \code{HEC}, a \class{structable} object, already includes a splitting information which simply gets overloaded in this example.) For compatibility with \codefun{mosaicplot} in base \proglang{R}, the \codefun{mosaic} function also allows the use of a \code{direction} argument taking a vector of \code{"h"} and \code{"v"} characters: <>= mosaic(HEC, direction = c("v","h","v")) @ By a suitable combination of splitting, spacing, and labeling settings, the functions provided by the strucplot framework can be customized in a quite flexible way. For example, the default method for \codefun{doubledecker} is simply a wrapper for \codefun{strucplot}, setting the right defaults. Most default settings such as colors, spacing, and labeling are specified via the parameters and passed through to \codefun{strucplot}. The additional code just handles the dependent variable information, and in particular permutes the table to have the dependent variable as the last dimension as required for the doubledecker plot. Figure~\ref{fig:titanic} shows a doubledecker plot of the \data{Titanic} data, explaining the probability of survival (``survived'') by age, given sex, given class. It is created by: <>= doubledecker(Titanic) @ \noindent equivalent to: <>= doubledecker(Survived ~ Class + Sex + Age, data = Titanic) @ \subsection{Conditional and partial views} So far, we have visualized either full or collapsed tables, as suggested by the analysis task at hand. Subtables can be selected in a similar way as for objects of class \class{table} using indexing. Note, however, that subsetting of \class{structable} objects is more restrictive because of their inherent conditional structure. Since the variables on both the row and the columns side are nested, subsetting is only possible ``outside-in'', that is, indexing operates on blocks defined by the variable levels. In the following, we use the Titanic data again, this time collapsed over \code{Survived} to investigate the structure of crew and passengers (and having the \code{Child} and \code{Age} labels of the \code{Age} variable swapped for optical clarity): <>= options(width=75) @ <>= (STD <- structable(~ Sex + Class + Age, data = Titanic[,,2:1,])) STD["Male",] STD["Male", c("1st","2nd","3rd")] @ <>= options(width=70) @ \noindent \emph{Conditioning} on levels (i.e., choosing a table subset for fixed levels of the conditioning variable(s)) is done using the \code{[[} operator. %]] Here again, the sequence of conditioning levels is restricted by the hierarchical structure of the \class{structable} object. In the following examples, note that compared to subsetting, the first dimension(s) are dropped: <>= STD[["Male",]] STD[[c("Male", "Adult"),]] STD[["Male","1st"]] @ \noindent Now, there are several ways for visualizing conditional independence structures. The ``brute force'' method is to draw separate plots for the strata. The following example compares the association between hair and eye color, given gender, by using subsetting on the flat table and \pkg{grid}'s viewport framework to visualize the two groups besides each other: <>= pushViewport(viewport(layout = grid.layout(ncol = 2))) @ <>= pushViewport(viewport(layout.pos.col = 1)) mosaic(STD[["Male"]], margins = c(left = 2.5, top = 2.5, 0), sub = "Male", newpage = FALSE) popViewport() @ <>= pushViewport(viewport(layout.pos.col = 2)) mosaic(STD[["Female"]], margins = c(top = 2.5, 0), sub = "Female", newpage = FALSE) popViewport(2) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= <> <> <> @ \caption{Two mosaic displays put side-by-side, visualizing the distribution of class and age, given gender. The marginal distribution of gender cannot be seen.} \label{fig:parttable} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent Note the use of the \code{margins} argument: it takes a vector with up to four values whose unnamed components are recycled, but ``overruled'' by the named arguments. Thus, in the second example, only the top margin is set to 2.5 lines, and all other to 0. This idea applies to almost all vectorized arguments in the strucplot framework (with \code{split\_vertical} as a prominent exception). The \codefun{cotabplot} function does a much better job on this task: it arranges stratified strucplot displays in a lattice-like layout, conditioning on variable \emph{levels}. The plot in Figure~\ref{fig:cotabplot} shows class and age group, given sex: <>= cotabplot(~ Class + Age | Sex, data = STD, split_vertical = TRUE) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= <> @ \caption{Conditional table plot for the \data{Titanic} data, again visualizing the distribution of age and class, given gender, using separate mosaic displays like the ``manual'' plot in Figure~\ref{fig:parttable}.} \label{fig:cotabplot} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} %\noindent The \code{labeling\_args} argument modifies the labels' %appearance: here, to be left-aligned and unclipped %(see Section \ref{sec:labeling}). \noindent Visualizing the strata separately ``hides'' the distribution of the conditioning variable(s) which may or may not be appropriate or sensible in a particular analysis step. If we wish to keep the information on the marginal distribution(s), we can use one single mosaic for the stratified plot since mosaic displays are ``conditional plots'' by definition. We just need to make sure that conditioning variables are used first for splitting. Both the default and the formula interface of \codefun{mosaic} allow the specification of conditioning variables (see Figure~\ref{fig:conditioning}): <>= mosaic(STD, condvars = "Sex", split_vertical = c(TRUE, TRUE, FALSE)) @ <>= mosaic(~ Class + Age | Sex, data = STD, split_vertical = c(TRUE, TRUE, FALSE)) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[h] \begin{center} <>= <> @ \caption{Mosaic plot again visualizing the distribution of class and age, given gender, this time using a single mosaic plot. In contrast to Figures~\ref{fig:parttable} and \ref{fig:cotabplot}, this plot also visualizes the marginal distribution of gender.} \label{fig:conditioning} \end{center} \end{figure} \setkeys{Gin}{width=0.7} \noindent The effect of using this is that conditioning variables are permuted ahead of the the conditioned variables in the table, and that \codefun{spacing\_conditional} is used as default to better distinguish conditioning from conditioned dimensions. This spacing uses equal space between tiles of conditioned variables, and increasing space between tiles of conditioning variables (See Section~\ref{sec:spacing}). Another set of high-level functions for visualizing conditional independence models are the \codefun{pairs} methods for \class{table} and \class{structable} objects. In contrast to \codefun{cotabplot} which conditions on variables, the \codefun{pairs} methods create pairwise views of the table. They produce, by default, a plot matrix having strucplot displays in the off-diagonal panels, and the variable names (optionally, with univariate displays) in the diagonal cells. Figure~\ref{fig:pairs} shows a pairs display for the \data{Titanic} data with univariate mosaics in the diagonal, and mosaic plots visualizing the corresponding bivariate mosaics in the upper and lower triangles. Due to the inherent asymmetry of mosaic displays, the corresponding plots in the upper and lower triangle differ depending on which variable is used first for splitting---inspecting both views might help detecting patterns in a data set. Additionally, we are using a special spacing and shading normally used to `highlight' %' the second variable in the first (as will be discussed in Section \ref{sec:spacing}): here, the intention of the spacing is to emphasize the conditional distributions of the second variable, given the first one, and the shading helps identifying the factor levels in the second variable. <>= pairs(STD, highlighting = 2, diag_panel = pairs_diagonal_mosaic, diag_panel_args = list(fill = grey.colors)) @ %\setkeys{Gin}{width=\textwidth} \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[h] \begin{center} <>= <> @ \caption{Pairs plot for the \data{Titanic} data.} \label{fig:pairs} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent The labels of the variables are to be read from left to right and from top to bottom. In addition, the levels can be matched by position within the columns and by shading within the rows. In plots produced by \codefun{pairs}, each panel's row and column define two variables $X$ and $Y$ used for the specification of four different types of independence: pairwise, total, conditional, and joint. The pairwise mosaic matrix shows bivariate marginal relations between $X$ and $Y$, collapsed over all other variables. The total independence mosaic matrix shows mosaic plots for mutual independence, i.e., for marginal and conditional independence among all pairs of variables. The conditional independence mosaic matrix shows mosaic plots for marginal independence of $X$ and $Y$, given all other variables. The joint independence mosaic matrix shows mosaic plots for joint independence of all pairs ($X$, $Y$) of variables from the others. Upper and lower parts can independently be used to display different types of independence models, or different strucplot displays (mosaic, association, or sieve plots). The available panel functions (\codefun{pairs\_assoc}, \codefun{pairs\_mosaic}, and \codefun{pairs\_sieve}) are simple wrappers to \codefun{assoc}, \codefun{mosaic}, and \codefun{sieve}, respectively. Obviously, seeing patterns in strucplot matrices becomes increasingly difficult with higher dimensionality. Therefore, this plot is typically used with a suitable residual-based shading (see Section \ref{sec:shading}). \subsection{Interactive plot modifications} All strucplot core functions are supposed to produce conditional hierarchical plots by the means of nested viewports, corresponding to the provided splitting information. Thus, at the end of the plotting, each tile is associated with a particular viewport. Each of those viewports has to be conventionally named, enabling other strucplot modules, in particular the labeling functions, to access specific tiles after they have been plotted. The naming convention for the viewports is: \begin{center} \code{\emph{[Optional prefix]}cell:\emph{Variable1}=\emph{Level1},\emph{Variable2}=\emph{Level2}} \dots \end{center} \noindent Clearly, these names depend on the splitting. The following example shows how to access parts of the plot after it has been drawn (see Figure~\ref{fig:afterplot}): <>= mosaic(~ Hair + Eye, data = HEC, pop = FALSE) seekViewport("cell:Hair=Blond") grid.rect(gp = gpar(col = "red", lwd = 4)) seekViewport("cell:Hair=Blond,Eye=Blue") grid.circle(r = 0.2, gp = gpar(fill = "cyan")) @ \noindent Note that the viewport tree is removed by default. Therefore, the \texttt{pop} argument has to be set to \texttt{FALSE} when viewports shall be accessed. \setkeys{Gin}{width=0.6\textwidth} \begin{figure}[h] \begin{center} <>= <> @ \caption{Adding elements to a mosaic plot after drawing.} \label{fig:afterplot} \end{center} \end{figure} In addition to the viewports, the main graphical elements get names following a similar construction method. This allows to change graphical parameters of plot elements \emph{after} the plotting (see Figure~\ref{fig:changeplot}): <>= assoc(Eye ~ Hair, data = HEC, pop = FALSE) getNames()[1:6] grid.edit("rect:Hair=Blond,Eye=Blue", gp = gpar(fill = "red")) @ %% code-chunk reuse does not work with parameter changing \begin{figure}[h] \begin{center} <>= x <- tab <- margin.table(HairEyeColor, 1:2) x[] <- "light gray" x["Blond","Blue"] <- "Red" assoc(tab, gp = gpar(fill = x)) @ \caption{Changing graphical parameters of elements after drawing.} \label{fig:changeplot} \end{center} \end{figure} \subsection{Performance issues} \label{sec:performance} As stated above, the implementation of strucplot displays is based on creating and nesting \pkg{grid} viewports. The main time-consuming steps performed by the core functions are the following: \begin{enumerate} \item recursively, split the table until the individual cells are reached \item during the splits, add viewports to the plot \item for the individual cells, add plot-specific content (rectangles for mosaics, bars for association plots, etc.) \end{enumerate} \noindent All these operations scale linearly with the amount of created viewports. For a $d$-dimensional table with $k_i$ levels, $i=1 \dots d$, the total number of needed viewports $T_d$ can roughly be estimated as \begin{equation} \label{eq:numbervp} T_d \quad = \quad k_1 + k_1k_2 + \cdots + k_1 \cdots k_d \quad =\quad \sum_{i=1}^d \prod_{j \le i} k_j \end{equation} \noindent since we first push the $k_1$ viewports for the levels of the first dimension, then, for \emph{each} of these, the $k_2$ levels of the second dimension, etc. If the number of levels is equal ($k$) for all dimensions, $T_d$ simplifies to \begin{equation} \label{eq:equalvp} T_d \quad = \quad \sum_{i=1}^d k^i = \frac{k(k^d-1)}{k-1} \end{equation} \noindent and so the time complexity for drawing a strucplot display is of order $k^d$. \section{Shadings} \label{sec:shading} Unlike other graphics functions in base \proglang{R}, the strucplot framework allows almost full control over the graphical parameters of all plot elements. In particular, in association plots, mosaic plots, and sieve plots, the user can modify the graphical appearance of each tile individually. Built on top of this functionality, the framework supplies a set of shading functions choosing colors appropriate for the visualization of log-linear models. The tiles' graphical parameters are set using the \code{gp} argument of the functions of the strucplot framework. This argument basically expects an object of class \class{gpar} whose components are arrays of the same shape (length and dimensionality) as the data table (see Section \ref{sec:gp}). For convenience, however, the user can also supply a grapcon function that computes such an object given a vector of residuals, or, alternatively, a generating function that takes certain arguments and returns such a grapcon function (see Section \ref{sec:shadingcustom}). We provide several shading functions, including support for both HSV and HCL colors, and the visualization of significance tests (see Section \ref{sec:overview}). \subsection{Specifying graphical parameters of strucplot displays} \label{sec:gp} As an example, consider the \data{UCBAdmissions} data. In the table aggregated over departments, we would like to highlight the (incidentally wrong) impression that there were too many male students accepted compared to the presumably discriminated female students (see Figure~\ref{fig:ucb}): <>= (ucb <- margin.table(UCBAdmissions, 1:2)) (fill_colors <- matrix(c("dark cyan","gray","gray","dark magenta"), ncol = 2)) mosaic(ucb, gp = gpar(fill = fill_colors, col = 0)) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{UCBAdmissions} data with highlighted cells.} \label{fig:ucb} \end{center} \end{figure} \noindent As the example shows, we create a fourfold table with appropriate colors (dark cyan for admitted male students and dark magenta for rejected female students) and supply them to the \code{fill} component of the \class{gpar} object passed to the \code{gp} argument of \codefun{mosaic}. For visual clarity, we additionally hide the tiles' borders by setting the \code{col} component to 0 (transparent). If the parameters specified in the \class{gpar} object are ``incomplete'', they will be recycled along the last splitting dimension. In the following example based on the \data{Titanic} data, we will highlight all cells corresponding to survived passengers (see Figure~\ref{fig:recycling}): <>= mosaic(Titanic, gp = gpar(fill = c("gray","dark magenta")), spacing = spacing_highlighting, labeling_args = list(abbreviate_labs = c(Age = 3), rep = c(Survived = FALSE)) ) @ \noindent Note that \codefun{spacing\_highlighting} sets the spaces between tiles in the last dimension to 0. The \code{labeling\_args} argument ensures that labels do not overlap (see Section \ref{sec:labeling}). \begin{figure}[h] \begin{center} <>= <> @ \caption{Recycling of parameters, used for highlighting the survived passengers in the \data{Titanic} data.} \label{fig:recycling} \end{center} \end{figure} \subsection{Customizing residual-based shadings} \label{sec:shadingcustom} This flexible way of specifying graphical parameters is the basis for a suite of shading functions that modify the tiles' appearance with respect to a vector of residuals, resulting from deviations of observed from expected frequencies under a given log-linear model. The idea is to visualize at least sign and absolute size of the residuals, but some shadings, additionally, indicate overall significance. One particular shading, the maximum shading \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Zeileis+Meyer+Hornik:2005}, even allows to identify the cells that cause the rejection of the null hypothesis. Conceptually, the strucplot framework offers three alternatives to add residual-based shading to plots: \begin{enumerate} \item Precomputing the graphical parameters (e.g., fill colors), encapsulating them into an object of class \class{gpar} as demonstrated in the previous section, and passing this object to the \code{gp} argument. \item Providing a grapcon function to the \code{gp} argument that takes residuals as input and returns an object as described in alternative 1. \item Providing a grapcon generator taking parameters and returning a function as described in alternative~2. \end{enumerate} \noindent For each of these approaches, we will demonstrate the necessary steps to obtain a binary shading that visualizes the sign of the residuals by a corresponding fill color (for simplicity, we will treat 0 as positive). \subsubsection*{Alternative 1: Precomputed \class{gpar} object} The first method is precomputing the graphical parameters ``by hand''. We will use \code{royalblue4} color for positive and \code{mediumorchid4} color for negative residuals (see Figure~\ref{fig:binary}): <>= expected <- independence_table(ucb) (x <- (ucb - expected) / sqrt(expected)) (shading1_obj <- ifelse(x > 0, "royalblue4", "mediumorchid4")) mosaic(ucb, gp = gpar(fill = shading1_obj)) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Binary shading visualizing the sign of the residuals.} \label{fig:binary} \end{center} \end{figure} \subsubsection*{Alternative 2: Grapcon function} For implementing alternative 2, we need to create a ``shading function'' that computes \class{gpar} objects from residuals. For that, we can just reuse the code from the previous step: <>= shading2_fun <- function(x) gpar(fill = ifelse(x > 0, "royalblue4", "mediumorchid4")) @ \noindent To create a mosaic display with binary shading, it now suffices to specify the data table along with \codefun{shading2\_fun}: <>= mosaic(ucb, gp = shading2_fun) @ \noindent \codefun{mosaic} internally calls \codefun{strucplot} which computes the residuals from the specified independence model (total independence by default), passes them to \codefun{shading2\_fun}, and uses the \class{gpar} object returned to finally create the plot. Our \codefun{shading2\_fun} function might be useful, but can still be improved: the hard-wired colors should be customizable. We cannot simply extend the argument list to include, e.g., a \code{fill = c("royalblue4", "mediumorchid4")} argument because \codefun{strucplot} will neither know how to handle it, nor let us change the defaults. In fact, the interface of shading functions is fixed, they are expected to take exactly one argument: a table of residuals. This is where generating functions (alternative 3) come into play. \subsubsection*{Alternative 3: Grapcon generator} We simply wrap our grapcon shading function in another function that takes all additional arguments it needs to use, possibly preprocesses them, and returns the actual shading function. This returned function will have access to the parameters since in \proglang{R}, nested functions are lexically scoped. Thus, the grapcon generator returns (``creates'') a ``parameterized'' shading function with the minimal standard interface \codefun{strucplot} requires. The following example shows the necessary extensions for our running example: <>= shading3a_fun <- function(col = c("royalblue4", "mediumorchid4")) { col <- rep(col, length.out = 2) function(x) gpar(fill = ifelse(x > 0, col[1], col[2])) } @ \noindent The first statement just makes sure that exactly two colors are specified. In the call to \codefun{mosaic}, using the new \codefun{shading3a\_fun} function, we can now simply change the colors: <>= mosaic(ucb, gp = shading3a_fun(c("royalblue4","mediumorchid4"))) @ \noindent (figure not shown). The procedure described so far is a rather general concept, applicable to a wide family of user-level \pkg{grid} graphics. Indeed, the customization of other components of the strucplot framework (labeling, spacing, legend, and core functions) follows the same idea. Now for the shading functions, more customization is needed. Note that \codefun{shading3a\_fun} needs to be evaluated by the user, even if the defaults are to be used. It is a better idea to let \codefun{strucplot} call the generating function, which, in particular, allows the passing of arguments that are computed by \codefun{strucplot}. Since shading functions can be used for visualizing significance (see Section \ref{sec:overview}), it makes sense for generating functions to have access to the model, i.e., observed and expected values, residuals, and degrees of freedom. For example, the \codefun{shading\_max} generating function computes a permutation distribution of the maximum statistic and $p$ values for specified significance levels based on the observed table to create data-driven cut-off points. If this was done in the shading function itself, the permutation statistic would be recomputed every time the shading function is called, resulting in possibly severe performance loss and numerical inconsistencies. Therefore, generating functions for shadings are required to take at least the parameters \code{observed}, \code{expected}, \code{residuals}, and \code{df} (these are provided by the strucplot framework), followed by other parameters controlling the shading appearance (to be specified by the user): <>= shading3b_fun <- function(observed = NULL, residuals = NULL, expected = NULL, df = NULL, col = c("royalblue4", "mediumorchid4")) { col <- rep(col, length.out = 2) function(x) gpar(fill = ifelse(x > 0, col[1], col[2])) } class(shading3b_fun) <- "grapcon_generator" @ Note that in this simple binary shading example, the first four parameters are not used. In some sense, generating functions for shadings are parameterized both by the user and the strucplot framework. For shading functions that require model information, the user-specified parameters are to be passed to the \code{gp\_args} argument instead, and for this to work, the generating function needs a class attribute to be distinguishable from the ``normal'' shading functions. For others (like our simple \codefun{shading3b\_fun}) this is optional, but recommended for consistency: <>= mosaic(ucb, gp = shading3b_fun, gp_args = list(col = c("red","blue"))) @ \noindent The final \codefun{shading3b\_fun} pretty much resembles \codefun{shading\_binary}, one of the standard shading functions provided by the \pkg{vcd} package. \subsection[An overview of the shading functions in vcd]{An overview of the shading functions in \pkg{vcd}} \label{sec:overview} \cite{vcd:Friendly:1994} suggested a residual-based shading for the mosaic tiles that can also be applied to the rectangles in association plots \citep{vcd:Meyer+Zeileis+Hornik:2003}. Apart from \codefun{shading\_binary}, there are currently two basic shadings available in \pkg{vcd}: \codefun{shading\_hcl} and \codefun{shading\_hsv}, as well as two derived functions: \codefun{shading\_Friendly} building upon \codefun{shading\_hsv}, and \codefun{shading\_max} building upon \codefun{shading\_hcl}. \codefun{shading\_hsv} and \codefun{shading\_hcl} provide the same conceptual tools, but use different color spaces: the Hue-Saturation-Value (HSV) and the Hue-Chroma-Luminance (HCL) scheme, respectively. We will first expose the basic concept of these shading functions using HSV space, and then briefly explain the differences to HCL space \citep[a detailed discussion can be found in][]{vcd:Zeileis+Meyer+Hornik:2005}. Color palettes in HCL space are preferable to palettes derived from HSV space from a perceptual point of view. Functions for creating palettes (see, e.g., \codefun{diverge\_hcl}) are provided with the \pkg{vcd} package. In HSV space, colors are specified in three dimensions: Hue, Saturation (``colorfulness''), and Value (``lightness'', amount of gray). These three dimensions are used by \codefun{shading\_hsv} to visualize information about the residuals and the underlying independence model. The hue indicates the residuals' sign: by default, blue for positive, and red for negative residuals. The saturation of a residual is set according to its size: high saturation for large, and low saturation for small residuals. Finally, the overall lightness is used to indicate the significance of a test statistic: light colors for significant, and dark colors for non-significant results. As an example, we will visualize the association of hair and eye color in the \data{HairEyeColor} data set (see Figure~\ref{fig:haireye}, top): <>= haireye <- margin.table(HairEyeColor, 1:2) mosaic(haireye, gp = shading_hsv) @ \noindent As introduced before, the default shading scheme is not \codefun{shading\_hsv} but \codefun{shading\_hcl} due to the better perceptual characteristics of HCL color space. The following example again illustrates the \data{HairEyeColor} data, this time with HCL colors: <>= mosaic(haireye, gp = shading_hcl) @ <>= mosaic(haireye, gp = shading_hcl, gp_args = list(h = c(130, 43), c = 100, l = c(90, 70))) @ \noindent In Figure~\ref{fig:haireye}, the plot in the middle depicts the default palette, and the bottom plot an alternative setting for Hue (\code{h}), Chroma (\code{c}), and Luminance (\code{l}). \setkeys{Gin}{width=0.5\textwidth} \begin{figure}[htbp] \begin{center} <>= mosaic(haireye, gp = shading_hsv, margin = c(bottom = 1), keep_aspect_ratio = FALSE) @ <>= mosaic(haireye, gp = shading_hcl, margin = c(bottom = 1), keep_aspect_ratio = FALSE) @ <>= mosaic(haireye, gp = shading_hcl, margin = c(bottom = 1), gp_args = list(h = c(130, 43), c = 100, l = c(90, 70)), keep_aspect_ratio = FALSE) @ \caption{Three mosaic plots for the \data{HairEyeColor} data using different color palettes. Top: default HSV color palette. Middle: default HCL color palette. Bottom: a custom HCL color palette.} \label{fig:haireye} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent Large positive residuals (greater than $4$) can be found for brown eyes/black hair and blue eyes/blond hair, and are colored in deep blue. On the other hand, there is a large negative residual (less than $-4$) for brown eyes/blond hair, colored deep red. There are also three medium-sized positive (negative) residuals between 2 and 4 ($-2$ and $-4$): the colors for them are less saturated. Residuals between $-2$ and $2$ are shaded in white (gray for HCL-shading). The heuristic for choosing the cut-off points $2$ and $4$ is that the Pearson residuals are approximately standard normal which implies that the highlighted cells are those with residuals \emph{individually} significant at approximately the $\alpha = 0.05$ and $\alpha = 0.0001$ levels, respectively. These default cut-off points can be changed to alternative values using the \code{interpolate} argument (see Figure~\ref{fig:interpolatecontinuous}): <>= mosaic(haireye, shade = TRUE, gp_args = list(interpolate = 1:4)) @ \noindent The elements of the numeric vector passed to \code{interpolate} define the knots of an interpolating step function used to map the absolute residuals to saturation levels. The \code{interpolate} argument also accepts a user-defined function, which then is called with the absolute residuals to get a vector of cut-off points. Thus, it is possible to automatically choose the cut-off points in a data-driven way. For example, one might think that the extension from four cut-off points to a continuous shading---visualizing the whole range of residuals---could be useful. We simply need a one-to-one mapping from the residuals to the saturation values: <>= ipol <- function(x) pmin(x/4, 1) @ \noindent Note that this \codefun{ipol} function maps residuals greater than 4 to a saturation level of 1. However, the resulting plot (Figure~\ref{fig:interpolatecontinuous}, right) is deceiving: <>= mosaic(haireye, shade = TRUE, gp_args = list(interpolate = ipol), labeling_args = list(abbreviate_labs = c(Sex = TRUE))) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[htbp] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) mosaic(haireye, gp_args = list(interpolate = 1:4), margin = c(right = 1), keep_aspect_ratio= FALSE,newpage = FALSE,legend_width=5.5,shade = TRUE) popViewport(1) pushViewport(viewport(layout.pos.col = 2)) mosaic(haireye, gp_args = list(interpolate = ipol), margin = c(left=3,right = 1), keep_aspect_ratio = FALSE, newpage = FALSE, shade = TRUE) popViewport(2) @ \caption{\label{fig:interpolatecontinuous}The \data{HairEyeColor} data. Left: shading with 4 cut-off points. Right: continuous shading.} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent Too much color makes it difficult to interpret the image, and the subtle color differences are hard to catch. Therefore, we only included shadings with discrete cut-off points. The third remaining dimension, the value, is used for visualizing the significance of a test statistic. The user can either directly specify the $p$ value, or, alternatively, a function that computes it, to the \code{p.value} argument. Such a function must take observed and expected values, residuals, and degrees of freedom (used by the independence model) as arguments. If nothing is specified, the $p$ value is computed from a $\chi^2$ distribution with \code{df} degrees of freedom. The \code{level} argument is used to specify the confidence level: if \code{p.value} is smaller than \code{1 - level}, light colors are used, otherwise dark colors are employed. The following example using the \data{Bundesliga} data shows the relationship of home goals and away goals of Germany's premier soccer league in 1995: although there are two ``larger'' residuals (one greater than 2, one less then $-2$), the $\chi^2$ test does not reject the null hypothesis of independence. Consequently, the colors appear dark (see Figure~\ref{fig:bundesliga}, left): <>= BL <- xtabs(~ HomeGoals + AwayGoals, data = Bundesliga, subset = Year == 1995) mosaic(BL, shade = TRUE) @ \noindent Note that in extended mosaic plots, bullets drawn for zero cells are shaded, too, bringing out non-zero residuals, if any. A shading function building upon \codefun{shading\_hsv} is \codefun{shading\_Friendly}, implementing the shading introduced by \cite{vcd:Friendly:1994}. In addition to the defaults of the HSV shading, it uses the border color and line type to redundantly code the residuals' sign. The following example again uses the \data{Bundesliga} data from above, this time using the Friendly scheme and, in addition, an alternative legend (see Figure~\ref{fig:bundesliga}, right): <>= mosaic(BL, gp = shading_Friendly, legend = legend_fixed, zero_size = 0) @ \setkeys{Gin}{width=\textwidth} \begin{figure}[htbp] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2))) pushViewport(viewport(layout.pos.col = 1)) mosaic(BL, margin = c(right = 1), keep_aspect_ratio= FALSE, newpage = FALSE, legend_width=5.5, shade = TRUE) popViewport(1) pushViewport(viewport(layout.pos.col = 2)) mosaic(BL, gp = shading_Friendly, legend = legend_fixed, zero_size = 0, margin = c(right = 1), keep_aspect_ratio= FALSE, newpage = FALSE, legend_width=5.5) popViewport(2) @ \caption{The \data{Bundesliga} data for 1995. Left: Non-significant $\chi^2$ test. Right: using the Friendly shading and a legend with fixed bins.} \label{fig:bundesliga} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \noindent (The \code{zero\_size = 0} argument removes the bullets indicating zero observed values. This feature is not provided in the original \proglang{SAS} implementation of the Friendly mosaic plots.) % Figure~\ref{fig:shadingHSVHCL} depicts % HSV space in the upper panel and HCL space in the lower panel. % On the left (right) side, we see the color scales for red (blue) % hue, respectively. The $x$-axis represents the colorfulness, and the % $y$-axis the brightness. % The boxes represent the diverging color palettes used for the shadings. % For HSV space, we can see that the effect of changing the % level of brightness (`value') is not the same for different levels of % saturation, and again not the same for the two different hues. % In fact, in HSV space all dimensions are confounded, which % obviously is problematic for coding information. In contrast, HCL color % space offers perceptually uniform colors: as can be seen from the lower panel, % the chroma is homogeneous for different levels of luminance. % Unfortunately, this comes at the % price of the space being irregularly shaped, making it difficult to automatically select % diverging color palettes. % <>= % hue.slice <- function(hue, grid.n = 101, type = c("HCL", "HSV"), plot = TRUE, fixup = FALSE) % { % type <- match.arg(type) % if(type == "HCL") { % chroma = seq(0, 100, length = grid.n) % luminance = seq(0, 100, length = grid.n) % nc <- length(chroma) % nl <- length(luminance) % color.slice <- outer(chroma, luminance, function(y, x) hcl(hue, x, y, fixup = fixup)) % xlab <- "chroma" % ylab <- "luminance" % main <- paste("hue =", round(hue, digits = 0)) % } else { % chroma = seq(0, 1, length = grid.n) % luminance = seq(0, 1, length = grid.n) % nc <- length(chroma) % nl <- length(luminance) % color.slice <- outer(chroma, luminance, function(y, x) hsv(hue, x, y)) % xlab <- "saturation" % ylab <- "value" % main <- paste("hue =", round(hue, digits = 3)) % } % if(plot) { % plot(0.5, 0.5, xlim = range(chroma), ylim = range(luminance), type = "n", axes = FALSE, % xlab = xlab, ylab = ylab, yaxs = "i", xaxs = "i", main = main) % for(i in 1:(nc-1)) { % rect(chroma[i], luminance[-nl], chroma[i] + 100/(nc-1), luminance[-1], border = color.slice[,i+1], col = color.slice[,i+1]) % } % axis(1) % axis(2) % box() % } % colnames(color.slice) <- chroma % rownames(color.slice) <- luminance % attr(color.slice, "type") <- type % class(color.slice) <- "slice" % invisible(color.slice) % } % @ % \setkeys{Gin}{width=.8\textwidth} % \begin{figure}[p] % \begin{center} % <>= % ## generate colors % hue23 <- hue.slice(2/3, grid.n = 101, plot = FALSE, type = "HSV") % hue0 <- hue.slice(0, grid.n = 101, plot = FALSE, type = "HSV") % saturation <- as.numeric(colnames(hue23)) % value <- as.numeric(rownames(hue23)) % ## select those with value >= 0.5 % hue23 <- hue23[value >= .5, ] % hue0 <- hue0[value >= .5, ] % value <- value[value >= .5] % nl <- nrow(hue23) % nc <- ncol(hue23) % ## plot 2 slides from HSV space % plot(0.5, 0.5, xlim = c(-1, 1), ylim = c(0, 1), type = "n", axes = FALSE, % xlab = "", ylab = "", yaxs = "i", xaxs = "i", main = "") % for(i in 1:(nc-1)) { % rect(saturation[i], value[-nl], saturation[i] + 1/(nc-1), value[-1], border = hue23[,i+1], col = hue23[,i+1]) % } % for(i in 1:(nc-1)) { % rect(-saturation[i], value[-nl], -(saturation[i] + 1/(nc-1)), value[-1], border = hue0[,i+1], col = hue0[,i+1]) % } % axis(2, at = c(50, 75, 100)/100, labels = c(0.5, 0.75, 1)) % axis(4, at = c(50, 75, 100)/100, labels = c(0.5, 0.75, 1)) % axis(3, at = -4:4*.25, labels=c(4:0*.25, 1:4*.25)) % mtext(c("hue = 0", "hue = 2/3"), side = 3, at = c(-.5, .5), line = 3, cex = 1.2) % mtext("saturation", side = 3, at = 0, line = 2) % mtext("value", side = 2, at = .75, line = 2) % mtext("value", side = 4, at = .75, line = 2) % lines(c(-1, 1), c(.5, .5)) % ## significant colors % rect(-1, 0.95, -.90, 1, col = hsv(0, 1, 1)) % rect(-0.45, 0.95, -.55, 1, col = hsv(0, 0.5, 1)) % rect(-.05, .95, .05, 1, col = hsv(2/3, 0, 1)) % rect(0.45, 0.95, .55, 1, col = hsv(2/3, 0.5, 1)) % rect(.90, .95, 1, 1, col = hsv(2/3, 1, 1)) % text(-1, .33, "significant", pos = 4, cex = 1.2) % rect(-1, .20, -.80, .30, col = hsv(0, 1, 1)) % rect(-.40, .20, -0.6, .30, col = hsv(0, 0.5, 1)) % rect(-.20, .20, 0, .30, col = hsv(0, 0, 1)) % rect(0, .20, .20, .30, col = hsv(2/3, 0, 1)) % rect(0.4, .20, .60, .30, col = hsv(2/3, .5, 1)) % rect(.80, .20, 1, .30, col = hsv(2/3, 1, 1)) % lines(c(-.9, -.55), c(0.975, .975), lty = 2) % lines(c(-.45, -.05), c(0.975, .975), lty = 2) % lines(c(.45, .05), c(0.975, .975), lty = 2) % lines(c(.9, .55), c(0.975, .975), lty = 2) % ## non-significant colors % rect(-1, 0.5, -.90, 0.55, col = hsv(0, 1, 0.5)) % rect(-0.45, 0.5, -.55, 0.55, col = hsv(0, 0.5, 0.5)) % rect(-.05, .5, .05, 0.55, col = hsv(2/3, 0, 0.5)) % rect(0.45, 0.5, .55, 0.55, col = hsv(2/3, 0.5, 0.5)) % rect(.90, .5, 1, 0.55, col = hsv(2/3, 1, 0.5)) % text(-1, .13, "non-significant", pos = 4, cex = 1.2) % rect(-1, 0, -.80, .10, col = hsv(0, 1, 0.5)) % rect(-.60, 0, -.4, .10, col = hsv(0, 0.5, 0.5)) % rect(-.20, 0, 0, .10, col = hsv(0, 0, 0.5)) % rect(0, 0, .20, .10, col = hsv(2/3, 0, 0.5)) % rect(0.4, 0, .60, .1, col = hsv(2/3, .5, 0.5)) % rect(.80, 0, 1, .10, col = hsv(2/3, 1, 0.5)) % lines(c(-.9, -.55), c(0.525, .525), lty = 2) % lines(c(-.45, -.05), c(0.525, .525), lty = 2) % lines(c(.45, .05), c(0.525, .525), lty = 2) % lines(c(.9, .55), c(0.525, .525), lty = 2) % @ % <>= % ## generate colors % hue260 <- hue.slice(260, grid.n = 101, plot = FALSE) % hue360 <- hue.slice(360, grid.n = 101, plot = FALSE) % mychroma <- as.numeric(colnames(hue260)) % luminance <- as.numeric(rownames(hue260)) % ## select those with lumincance >= 50 % hue260 <- hue260[luminance >= 50, ] % hue360 <- hue360[luminance >= 50, ] % luminance <- luminance[luminance >= 50] % nc <- ncol(hue260) % nl <- nrow(hue260) % ## plot 2 slides from HCL space % plot(0.5, 0.5, xlim = c(-100, 100), ylim = c(0, 100), type = "n", axes = FALSE, % xlab = "", ylab = "", yaxs = "i", xaxs = "i", main = "") % for(i in 1:(nc-1)) { % rect(mychroma[i], luminance[-nl], mychroma[i] + 100/(nc-1), luminance[-1], border = hue260[,i+1], col = hue260[,i+1]) % } % for(i in 1:(nc-1)) { % rect(-mychroma[i], luminance[-nl], -(mychroma[i] + 100/(nc-1)), luminance[-1], border = hue360[,i+1], col = hue360[,i+1]) % } % axis(2, at = c(50, 70, 90, 100), labels = c(50, 70, 90, 100)) % axis(4, at = c(50, 70, 90, 100), labels = c(50, 70, 90, 100)) % axis(3, at = -4:4*25, labels=c(4:0*25, 1:4*25)) % mtext(c("hue = 0", "hue = 260"), side = 3, at = c(-50, 50), line = 3, cex = 1.2) % mtext("chroma", side = 3, at = 0, line = 2) % mtext("luminance", side = 2, at = 75, line = 2) % mtext("luminance", side = 4, at = 75, line = 2) % lines(c(-100, 100), c(50, 50)) % ## significant colors % rect(-100, 47.5, -90, 52.5, col = hcl(0, 100, 50)) % rect(-55, 67.5, -45, 72.5, col = hcl(0, 50, 70)) % rect(-5, 95, 5, 100, col = hcl(260, 0, 100)) ## grey vs. white % rect(-5, 87.5, 5, 92.5, col = hcl(260, 0, 90)) ## grey vs. white % rect(45, 67.5, 55, 72.5, col = hcl(260, 50, 70)) % rect(90, 47.5, 100, 52.5, col = hcl(260, 100, 50)) % text(-100, 33, "significant", pos = 4, cex = 1.2) % rect(-100, 20, -80, 30, col = hcl(0, 100, 50)) % rect(-60, 20, -40, 30, col = hcl(0, 50, 70)) % rect(-20, 20, 0, 30, col = hcl(0, 0, 90)) % rect(0, 20, 20, 30, col = hcl(260, 0, 90)) % #white# rect(-20, 20, 0, 30, col = hcl(0, 0, 100)) % #white# rect(0, 20, 20, 30, col = hcl(260, 0, 100)) % rect(40, 20, 60, 30, col = hcl(260, 50, 70)) % rect(80, 20, 100, 30, col = hcl(260, 100, 50)) % lines(c(-45, -5), c(72.5, 87.5), lty = 2) % lines(c(45, 5), c(72.5, 87.5), lty = 2) % lines(c(-95, -55), c(52.5, 67.5), lty = 2) % lines(c(95, 55), c(52.5, 67.5), lty = 2) % ## non-significant colors % rect(-25, 47.5, -15, 52.5, col = hcl(0, 20, 50)) % rect(-15, 67.5, -5, 72.5, col = hcl(0, 10, 70)) % rect(5, 67.5, 15, 72.5, col = hcl(260, 10, 70)) % rect(25, 47.5, 15, 52.5, col = hcl(260, 20, 50)) % text(-100, 13, "non-significant", pos = 4, cex = 1.2) % rect(-60, 0, -40, 10, col = hcl(0, 20, 50)) % rect(-40, 0, -20, 10, col = hcl(0, 10, 70)) % rect(-20, 0, 0, 10, col = hcl(0, 0, 90)) % rect(0, 0, 20, 10, col = hcl(260, 0, 90)) % rect(20, 0, 40, 10, col = hcl(260, 10, 70)) % rect(40, 0, 60, 10, col = hcl(260, 20, 50)) % lines(c(-18.75, -11.25), c(52.5, 67.5), lty = 2) % lines(c(-8.75, -1.25), c(72.5, 87.5), lty = 2) % lines(c(18.75, 11.75), c(52.5, 67.5), lty = 2) % lines(c(8.75, 1.25), c(72.5, 87.5), lty = 2) % @ % \caption{Residual-based shadings in HSV (upper) and HCL space (lower).} % \label{fig:shadingHSVHCL} % \end{center} % \end{figure} A more ``advanced'' function building upon \codefun{shading\_hcl} is \codefun{shading\_max}, using the maximum statistic both to conduct the independence test and to visualize significant \emph{cells} causing the rejection of the independence hypothesis \citep{vcd:Meyer+Zeileis+Hornik:2003,vcd:Zeileis+Meyer+Hornik:2005}. The \code{level} argument of \codefun{shading\_max} then can be used to specify several confidence levels from which the corresponding cut-off points are computed. By default, two cut-off points are computed corresponding to confidence levels of $90\%$ and $99\%$, respectively. In the following example, we investigate the effect of a new treatment for rheumatoid arthritis on a group of female patients using the maximum shading (see Figure~\ref{fig:maximum}): <>= set.seed(4711) mosaic(~ Treatment + Improved, data = Arthritis, subset = Sex == "Female", gp = shading_max) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{The \data{Arthritis} data (female patients) with significant maximum test.} \label{fig:maximum} \end{center} \end{figure} \noindent The maximum test is significant although the residuals are all in the $\left[-2,2\right]$ interval. The \codefun{shading\_hcl} function with default cut-off points would not have shown any color. In addition, since the test statistic is the maximum of the absolute Pearson residuals, \emph{each} colored residual violates the null hypotheses of independence, and thus, the ``culprits'' can immediately be identified. \clearpage \section[Labeling]{Labeling} \label{sec:labeling} One of the major enhancements in package \pkg{vcd} compared to \codefun{mosaicplot} and \codefun{assocplot} in base \proglang{R} is the labeling in the strucplot framework which offers more features and greater flexibility. Like shading, spacing, and drawing of legend and core plot, labeling is now carried out by grapcon functions, rendering labeling completely modular. The user supplies either a labeling function, or, alternatively, a generating function that parameterizes a labeling function, to \codefun{strucplot} which then draws the labels. Labeling is well-separated from the actual plotting that occurs in the low-level core functions. It only relies on the viewport tree produced by them, and the \code{dimnames} attribute of the visualized table. Labeling functions are grapcons that ``add ink to the canvas'': the drawing of the labels happens after the actual plot has been drawn by the core function. Thus, it is possible to supply one's own labeling function, or to combine some of the basic functions to produce a more complex labeling. In the following, we describe the three basic modules (\codefun{labeling\_text}, \codefun{labeling\_list}, and \codefun{labeling\_cells}) and derived functions that build upon them. \subsection[Labels in the borders]{Labels in the borders: \texttt{labeling\_text()}} \codefun{labeling\_text} is the default for all strucplot displays. It plots labels in the borders similar to the \codefun{mosaicplot} function in base \proglang{R}, but is much more flexible: it is not limited to 4 dimensions, and the positioning and graphical parameters of levels and variable names are customizable. In addition, the problem of overlapping labels can be handled in several ways. As an example, again consider the \data{Titanic} data: by default, the variable names and levels are plotted ``around'' the plot in a counter-clockwise way (see Figure~\ref{fig:labels1}, top left): <>= mosaic(Titanic) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Mosaic plot for the \data{Titanic} data with default settings % for labeling.} % \label{fig:defaults} % \end{center} % \end{figure} \noindent Note that the last two levels of the \code{survived} variable do overlap, as well as some adult and child labels of the \code{age} Variable. This issue can be addressed in several ways. The ``brute force'' method is to enable clipping for these dimensions (see Figure~\ref{fig:labels1}, top right): <>= mosaic(Titanic, labeling_args = list(clip = c(Survived = TRUE, Age = TRUE))) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{The effect of clipping.} % \label{fig:clipping} % \end{center} % \end{figure} \noindent The \code{clip} parameter is passed to the labeling function via the \code{labeling\_args} argument which takes a list of parameters. \code{clip} itself takes a vector of logicals (one for each dimension). % as mentioned before Almost all vectorized arguments in the strucplot framework can be abbreviated in the following way: unnamed components (or the defaults, if there are none) are recycled as needed, but overridden by the named components. Here, the default is \code{FALSE}, and therefore clipping is enabled only for the \code{survived} and \code{age} variables. A more sensible solution to the overlap problem is to abbreviate the levels (see Figure~\ref{fig:labels1}, middle left): <>= mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = TRUE, Age = 3))) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Abbreviating.} % \label{fig:abbreviating} % \end{center} % \end{figure} \noindent The \code{abbreviate} argument takes a vector of integers indicating the number of significant characters the levels should be abbreviated to (\code{TRUE} is interpreted as 1, obviously). Abbreviation is performed using the \codefun{abbreviate} function in base \proglang{R}. Another possibility is to rotate the levels (see Figure~\ref{fig:labels1}, bottom): <>= mosaic(Titanic, labeling_args = list(rot_labels = c(bottom = 90, right = 0), offset_varnames = c(right = 1), offset_labels = c(right = 0.3)), margins = c(right = 4, bottom = 3)) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Rotating labels.} % \label{fig:rotating} % \end{center} % \end{figure} \noindent Finally, we could also inhibit the output of repeated levels (see Figure~\ref{fig:labels1}, middle right): <>= mosaic(Titanic, labeling_args = list(rep = c(Survived = FALSE, Age = FALSE))) @ \setkeys{Gin}{width=0.9\textwidth} \begin{figure}[p] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2,nrow=3))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(Titanic, newpage = FALSE, keep = TRUE, margin = c(right = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(Titanic, labeling_args = list(clip = c(Survived = TRUE, Age = TRUE)), newpage = FALSE, keep = TRUE, margin = c(left = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = TRUE, Age = 2)), newpage = FALSE, keep = TRUE, margin = c(right = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(rep = c(Survived = FALSE, Age = FALSE)), newpage = FALSE, keep = TRUE, margin = c(left = 3), gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 1:2, layout.pos.row = 3)) pushViewport(viewport(width = 0.55)) mosaic(Titanic, labeling_args = list(rot_labels = c(bottom = 90, right = 0), offset_varnames = c(right = 1), offset_labels = c(right = 0.3)), margins = c(right = 4, bottom = 3), newpage = FALSE, keep = FALSE, gp_labels = gpar(fontsize = 10)) popViewport(3) @ \caption{Examples for possible labeling strategies for the Titanic data mosaic. Top left: default labeling (many labels overlap). Top right: with clipping turned on. Middle left: \texttt{Age} and \texttt{Survived} labels abbreviated. Middle right: \texttt{Age} labels not repeated. Bottom: \texttt{Age} and \texttt{Survived} labels rotated.} \label{fig:labels1} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} We now proceed with a few more ``cosmetic'' features (which do not all produce satisfactory results for our sample data). A first simple, but effectful modification is to position all labels and variables left-aligned (see Figure~\ref{fig:labels2}, top left): <>= mosaic(Titanic, labeling_args = list(pos_varnames = "left", pos_labels = "left", just_labels = "left", rep = FALSE)) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Left-aligning.} % \label{fig:left} % \end{center} % \end{figure} \noindent Note that obviously we need to change the justification to \code{"left"} as well. We can achieve the same effect by using the convenience function \codefun{labeling\_left}: <>= mosaic(Titanic, labeling = labeling_left) @ \noindent Next, we show how to put all levels to the bottom and right margins, and all variable names to the top and left margins (see Figure~\ref{fig:labels2}, top right): <>= mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, abbreviate_labs = c(Survived = 1, Age = 3))) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Changes in the margins.} % \label{fig:margins} % \end{center} % \end{figure} \noindent The tl\_\var{foo} (``top left'') arguments are \code{TRUE} by default. Now, we will add boxes to the labels and additionally enable clipping (see Figure~\ref{fig:labels2}, bottom left): <>= mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, boxes = TRUE, clip = TRUE)) @ % \begin{figure}[p] % \begin{center} % <>= % <> % @ % \caption{Boxes and Clipping.} % \label{fig:boxes} % \end{center} % \end{figure} \noindent The values to \code{boxes} and \code{clip} are recycled for all dimensions. The result is pretty close to what calling \codefun{mosaic} with the \codefun{labeling\_cboxed} wrapper does, except that variables and levels, by default, are put to the top and to the left of the plot: <>= mosaic(Titanic, labeling = labeling_cboxed) @ \noindent Another variant is to put the variable names into the same line as the levels (see Figure~\ref{fig:labels2}, bottom right---clipping for \code{Survived} and \code{Age} is, additionally, disabled, and \code{Age} abbreviated): <>= mosaic(Titanic, labeling_args = list(tl_labels = TRUE, boxes = TRUE, clip = c(Survived = FALSE, Age = FALSE, TRUE), abbreviate_labs = c(Age = 4), labbl_varnames = TRUE), margins = c(left = 4, right = 1, 3)) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Variable names beneath levels, and clipping disabled for the % survival variable.} % \label{fig:labbl} % \end{center} % \end{figure} \noindent \code{labbl\_varnames} (``variable names to the bottom/left of the labels'') is a vector of logicals indicating the side for the variable names. The resulting layout is close to what \codefun{labeling\_lboxed} produces, except that variables and levels, by default, are left-aligned and put to the bottom and to the right of the plot: <>= mosaic(Titanic, labeling = labeling_lboxed, margins = c(right = 4, left = 1, 3)) @ \noindent A similar design is used by the \codefun{doubledecker} function. \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2, nrow = 2))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(Titanic, labeling_args = list(pos_varnames = "left", pos_labels = "left", just_labels = "left", rep = FALSE), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 12)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, abbreviate_labs = c(Survived = 1, Age = 3)), newpage = FALSE, keep = TRUE, margins = c(left = 4, right = 1, 3), gp_labels = gpar(fontsize = 12)) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(tl_labels = FALSE, tl_varnames = TRUE, boxes = TRUE, clip = TRUE), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 12)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(tl_labels = TRUE, boxes = TRUE, clip = c(Survived = FALSE, Age = FALSE, TRUE), labbl_varnames = TRUE, abbreviate_labs = c(Age = 4)), margins = c(left = 4, right = 1, 3), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 12)) popViewport(2) @ \caption{Advanced strategies for labeling of the Titanic data. Top left: left aligning of both variable names and labels. Top right: changes in the margins (all variable names are in the top and left margins, and all labels in the bottom and right margins). Bottom left: clipping turned on, and boxes used. Bottom right: variable names beneath levels, clipping disabled for the survival and age variables, and \texttt{Age} abbreviated.} \label{fig:labels2} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \subsection[Labels in the cells]{Labels in the cells: \texttt{labeling\_cells()}} This labeling draws both variable names and levels in the cells. As an example, we use the \data{PreSex} data on pre- and extramarital sex and divorce (see Figure~\ref{fig:labels3}, top left): <>= mosaic(~ MaritalStatus + Gender, data = PreSex, labeling = labeling_cells) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Cell labeling for the \data{PreSex} data.} % \label{fig:cell} % \end{center} % \end{figure} \noindent In the case of narrow cells, it might be useful to abbreviate labels and/or variable names and turn off clipping (see Figure~\ref{fig:labels3}, top right): <>= mosaic(~ PremaritalSex + ExtramaritalSex, data = PreSex, labeling = labeling_cells(abbreviate_labels = TRUE, abbreviate_varnames = TRUE, clip = FALSE)) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Cell labeling for the \data{PreSex} data, labels abbreviated.} % \label{fig:cell2} % \end{center} % \end{figure} \noindent For some data, it might be convenient to combine cell labeling with border labeling as done by \codefun{labels\_conditional} (see Figure~\ref{fig:labels3}, bottom left): <>= mosaic(~ PremaritalSex + ExtramaritalSex | MaritalStatus + Gender, data = PreSex, labeling = labeling_conditional(abbreviate_varnames = TRUE, abbreviate_labels = TRUE, clip = FALSE, gp_text = gpar(col = "red"))) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{Conditional labeling for the \data{PreSex} data, labels (in % red for clarity) abbreviated.} % \label{fig:conditional} % \end{center} % \end{figure} \noindent Additionally, the cell labeling allows the user to add arbitrary text to the cells by supplying a character array in the same shape as the data array to the \code{text} argument (cells with missing values are ignored). In the following example using the \code{Titanic} data, this is used to add all observed values greater than 5 to the cells after the mosaic has been plotted (see Figure~\ref{fig:labels3}, bottom right): <>= mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = 1, Age = 4)), pop = FALSE) tab <- ifelse(Titanic < 6, NA, Titanic) labeling_cells(text = tab, clip = FALSE)(Titanic) @ % \begin{figure}[h] % \begin{center} % <>= % <> % @ % \caption{User-supplied text (observed frequencies exceeding 5) % added to a mosaic display of the \data{Titanic} data.} % \label{fig:text} % \end{center} % \end{figure} \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= grid.newpage() pushViewport(viewport(layout = grid.layout(ncol = 2, nrow = 2))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(~ MaritalStatus + Gender, data = PreSex, labeling = labeling_cells, newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(~ PremaritalSex + ExtramaritalSex, data = PreSex, labeling = labeling_cells(abbreviate_labels = TRUE, abbreviate_varnames = TRUE, clip = FALSE), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(~ PremaritalSex + ExtramaritalSex | MaritalStatus + Gender, data = PreSex, labeling = labeling_conditional(abbreviate_varnames = TRUE, abbreviate_labels = TRUE, clip = FALSE, gp_text = gpar(col = "red")), newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(Titanic, labeling_args = list(abbreviate_labs = c(Survived = 1, Age = 3)), pop = FALSE, newpage = FALSE, keep = TRUE, gp_labels = gpar(fontsize = 10)) tab <- ifelse(Titanic < 6, NA, Titanic) labeling_cells(text = tab, clip = FALSE)(Titanic) @ \caption{Cell labeling. Top left: default labeling using the \data{PreSex} data. Top right: abbreviated labels. Bottom left: conditional labeling (labels abbreviated and in red for clarity). Bottom right: user-supplied text (observed frequencies exceeding 5) added to a mosaic display of the \data{Titanic} data. Note that clipping is on by default (top left), and has explicitly been turned off for the three other plots.} \label{fig:labels3} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \subsection[A simple list of labels]{A simple list of labels: \texttt{labeling\_list()}} If problems with overlapping labels cannot satisfactorily resolved, the last remedy could be to simply list the levels below the plot (see Figure~\ref{fig:list}): <>= mosaic(Titanic, labeling = labeling_list, margins = c(bottom = 5)) @ \setkeys{Gin}{width=0.7\textwidth} \begin{figure}[p] \begin{center} <>= mosaic(Titanic, labeling = labeling_list, margins = c(bottom = 5), keep = TRUE) @ \caption{Labels indicated below the plot.} \label{fig:list} \end{center} \end{figure} \noindent The number of columns can be specified. \section{Spacing} \label{sec:spacing} Spacing of strucplot displays is customizable in a similar way than shading. The \code{spacing} argument of the \codefun{strucplot} function takes a list of \class{unit} vectors, one for each dimension, specifying the space between the tiles corresponding to the levels. Consider again the introductory example of the \data{Arthritis} data (Figure~\ref{fig:arthritis}). Since we are interested in the effect of the medicament in the placebo and treatment groups, a mosaic plot is certainly appropriate to visualize the three levels of \code{Improved} in the two \code{Treatment} strata. Another conceptual approach is to use spine plots with highlighting \citep{vcd:hummel:1996}. A spine plot is a variation of a bar plot where the heights of the bars are held constant, whereas the widths are used to represent the number of cases in each category. This is equivalent to a mosaic plot for a one-way table. If a second (indicator) variable is highlighted in a spine plot, we obtain a display equivalent to a simple mosaic display for a two-way table, except that no space between the levels of the highlighted variable is used. In the \data{Arthritis} example, we will highlight patients with \code{Marked} improvement in both groups. To obtain such a display within the strucplot framework, it suffices to set the space between the \code{Improved} tiles to 0 (see Figure~\ref{fig:artspine}): <>= (art <- structable(~Treatment + Improved, data = Arthritis, split_vertical = TRUE)) (my_spacing <- list(unit(0.5, "lines"), unit(c(0, 0), "lines"))) my_colors <- c("lightgray", "lightgray", "black") mosaic(art, spacing = my_spacing, gp = gpar(fill = my_colors, col = my_colors)) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Spine plot for the \data{Arthritis} data using the strucplot framework.} \label{fig:artspine} \end{center} \end{figure} \noindent Note that the default and formula methods for \codefun{mosaic} provide a convenience interface for highlighting. A similar plot (with slightly different shading) than the previous one can be obtained using: <>= mosaic(Improved ~ Treatment, data = Arthritis, split_vertical = TRUE) @ \noindent The strucplot framework also provides a set of spacing grapcon generators which compute suitable spacing objects for typical applications. The simplest spacing is \codefun{spacing\_equal} that uses the same space between all tiles (see Figure~\ref{fig:spacing}, top left): <>= mosaic(art, spacing = spacing_equal(unit(2, "lines"))) @ \noindent \codefun{spacing\_equal} is the default grapcon generator for two-dimensional tables. Slightly more flexible is \codefun{spacing\_dimequal} that allows an individual setting for each dimension (see Figure~\ref{fig:spacing}, top right): <>= mosaic(art, spacing = spacing_dimequal(unit(1:2, "lines"))) @ \noindent The default for multi-way contingency tables is \codefun{spacing\_increase} which uses increasing spaces for the dimensions. The user can specify a start value and the increase factor (see Figure~\ref{fig:spacing}, bottom left): <>= mosaic(art, spacing = spacing_increase(start = unit(0.5, "lines"), rate = 1.5)) @ \noindent For the arthritis example above, we could as well have used \codefun{spacing\_highlighting} which is similar to \codefun{spacing\_increase} but sets the spacing in the last splitting dimension to 0 (see Figure~\ref{fig:spacing}, bottom right): <>= mosaic(art, spacing = spacing_highlighting, gp = my_colors) @ \noindent Finally, \codefun{spacing\_conditional} can be used for visualizing conditional independence: it combines \codefun{spacing\_equal} (for the conditioned dimensions) and \codefun{spacing\_increase} (for the conditioning dimensions). As an example, consider Figure~\ref{fig:presex}: the spacing clearly allows to better distinguish the conditioning variables (\code{Gender} and \code{MaritalStatus}) from the conditioned variables (\code{PremaritalSex} and \code{ExtramaritalSex}). This spacing is the default when conditional variables are specified for a strucplot display (see Section \ref{sec:strucplot}). \setkeys{Gin}{width=\textwidth} \begin{figure}[p] \begin{center} <>= pushViewport(viewport(layout = grid.layout(ncol = 2, nrow = 2))) pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 1)) mosaic(art, spacing = spacing_equal(unit(2, "lines")), keep = TRUE, newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 1)) mosaic(art, spacing = spacing_dimequal(unit(c(0.5, 2), "lines")), keep = TRUE, newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 1, layout.pos.row = 2)) mosaic(art, spacing = spacing_increase(start = unit(0.3, "lines"), rate = 2.5), keep = TRUE, newpage = FALSE) popViewport() pushViewport(viewport(layout.pos.col = 2, layout.pos.row = 2)) mosaic(art, spacing = spacing_highlighting, keep = TRUE, newpage = FALSE) popViewport(2) @ \caption{Varying spacing for the Arthritis data. Top left: equal spacing for all dimensions. Top right: different spacings for individial dimensions. Bottom left: increasing spacing. Bottom right: spacing used for highlighting.} \label{fig:spacing} \end{center} \end{figure} \setkeys{Gin}{width=0.7\textwidth} \section{Example: Ovarian cancer survival} \label{sec:example} In the following, we demonstrate some of the described techniques in analyzing a data set originating from \citep{vcd:obel:1975} \cite[taken from][]{vcd:andersen:1991} about a retrospective study of ovary cancer carried out in 1973. Information was obtained from 299 women, who were operated for ovary cancer 10 years before. The data consists of four binary variables: the \code{stage} of the cancer at the time of operation (levels: \code{early}, \code{advanced}), the type of \code{operation} performed (\code{radical}, \code{limited}), the \code{survival} status after 10 years (\code{yes}, \code{no}), and \code{xray} indicating whether X-ray treatment was received (\code{yes}, \code{no}). The dataset in \pkg{vcd} comes pretabulated in a data frame, so we first create the four-way table: <>= tab <- xtabs(Freq ~ stage + operation + xray + survival, data = OvaryCancer) @ \noindent A ``flattened'' textual representation can be obtained using \codefun{structable}: <>= structable(survival ~ ., data = tab) @ \noindent A first overview can be obtained using a pairs plot (Figure~\ref{fig:ocpairs}): <>= dpa <- list(var_offset = 1.2, rot = -30, just_leveltext= "left") pairs(tab, diag_panel_args = dpa) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Pairs plot for the \data{OvaryCancer} data showing mosaic displays for all pairwise distributions and bar plots for all marginal distributions.} \label{fig:ocpairs} \end{center} \end{figure} \noindent The pairs plot, by default, creates mosaic displays for all pairwise variable combinations, and bar plots in the diagonal to visualize the absolute frequencies of the variables. The \texttt{var\_offset} argument modifies the offset of the (centered) variable names to avoid overlap with the bars. Additionally, we use the \texttt{rot} and the \texttt{just\_leveltext} arguments to rotate the level names, again to avoid their overlap. First, we consider the marginal distributions. The study design involved (nearly) the same number of survived (150) and deceased (149) patients. Similarly balanced, 158 cases were in an advanced and 141 in an early stage. Most patients (251, 84\%) were treated with a radical operation, and 186 (62\%) were submitted to X-ray treatment. Next, we inspect the two-way interaction of the influencing factors (\code{stage}, \code{operation}, and \code{xray}): the corresponding mosaics exhibit symmetric, regular shapes with aligned tiles, which indicate no marginal interaction between these variables. The same is true for the interactions of \code{survival} with \code{operation} and \code{xray}, respectively. Only the stage seems to influence survival: here, the tiles are ``shifted''. A different view on the data, focused on the influence of the explanatory variables on \code{Survival}, can be obtained using a doubledecker plot (Figure~\ref{fig:ocdoubledecker}): <>= doubledecker(survival ~ stage + operation + xray, data = tab) @ \begin{figure}[h] \begin{center} <>= <> @ \caption{Doubledecker plot for the \data{OvaryCancer} data showing the conditional distribution of X-ray, given operation, given stage, and with survival highlighted.} \label{fig:ocdoubledecker} \end{center} \end{figure} \noindent From a technical point of view, the display is constructed as a mosaic plot showing the conditional distribution of \code{survival}, given \code{xray}, given \code{operation}, given \code{stage}, with vertical splits for the conditioning variables and horizontal ones for \code{survival}. Additionally, there is zero space between the tiles of the last dimension and a binary shading is used for survived and deceased patients. Conceptually, this plot is interpreted as a mosaic plot of just the influencing variables, with \code{survival} highlighted in the tiles. Thus, the plot really shows the influence of the explanatory variables on \code{survival}. Clearly, the survival rate is higher among patients in an early stage, but neither radical operation nor X-ray treatment seem to improve the situation. From this exploratory phase, the survival rate seems to be slightly higher for patients who received a limited operation only, whereas the effect for X-ray treatment is less marked. To visualize inference results, we can make use of residual-based shadings, investigating log-linear models for the four-way table. Figure~\ref{fig:ocmosaicnull} visualizes the null model, where survival is independent from the combined effect of operation, X-ray treatment, and stage: <>= split <- c(TRUE, TRUE, TRUE, FALSE) mosaic(tab, expected = ~ survival + operation * xray * stage, split_vertical = split) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{OvaryCancer} data, with residual-based shading for the (clearly rejected) null model (survival)(operation, X-ray, stage).} \label{fig:ocmosaicnull} \end{center} \end{figure} \noindent The model is clearly rejected ($p$-value: 0.000). From the exploratory phase of our analysis, we (only) suspect \code{stage} to be influential on the survival rate. A corresponding hypothesis is that \code{survival} be independent of \code{xray} and \code{operation}, given \code{stage}. The model is specified using the \texttt{expected} argument, either using the \codefun{loglin} interface or the \codefun{loglm} formula interface (the resulting mosaic plot is shown in Figure \ref{fig:ocmosaicstage}): <>= mosaic(tab, expected = ~ (survival + operation * xray) * stage, split_vertical = split) @ \begin{figure}[p] \begin{center} <>= <> @ \caption{Mosaic plot for the \data{OvaryCancer} data, with residual-based shading for the hypothesis of survival being independent of X-ray and operation, given stage. The hypothesis is not rejected.} \label{fig:ocmosaicstage} \end{center} \end{figure} \noindent Thus, based on this data, only pre-diagnosis seems to matter in ovarian cancer therapy. \section{Conclusion} \label{sec:conclusion} In this paper, we describe the ``strucplot'' framework for the visualization of multi-way contingency tables. Strucplot displays include popular basic plots such as mosaic, association, and sieve plots, integrated in a unified framework: all can be seen as visualizations of hierarchical conditional flat tables. Additionally, these core strucplot displays can be combined into more complex, specialized plots, such as pairs and trellis-like displays for visualizing conditional independence. Residual-based shadings permit the visualization of log-linear models and the results of independence tests. The framework's modular design allows flexible customization of the plots' graphical appearance, including shading, labeling, spacing, and legend, by means of graphical appearance control (``grapcon'') functions. These ``graphical hyperparameters'' are customized and created by generating functions. Our work includes a set of predefined grapcon generators for typical analysis tasks, and user-level extensions can easily be added. \bibliography{vcd} \begin{appendix} \section{Data sets} \label{sex:data} The data set names in the paper are those from the \proglang{R} system. In the following, we give a short description of each data set. \begin{description} \item[\texttt{Arthritis}] Data from a double-blind clinical trial investigating a new treatment for rheumatoid arthritis. Source: \cite{vcd:Koch+Edwards:1988}. Taken from: \cite{vcd:Friendly:2000}. Package: \pkg{vcd}. \item[\texttt{Bundesliga}] Results from the first German soccer league in the years 1995/6 \citep{vcd:Knorr-Held:1999} and 2001/2 (Collected by: Achim Zeileis). Package: \pkg{vcd}. \item[\texttt{HairEyeColor}] Distribution of hair and eye color and gender in 592 statistics students. The gender information is artificial. Source: \cite{vcd:Snee:1974}. Taken from: \cite{vcd:Friendly:2000}. Package: \pkg{datasets} (included in base \proglang{R}). \item[\texttt{OvaryCancer}] Data about a retrospective study of ovary cancer carried out in 1973. Information was obtained from 299 women, who were operated for ovary cancer 10 years before. Source: \cite{vcd:obel:1975}. Taken fromn: \cite{vcd:andersen:1991}. Package: \pkg{vcd}. \item[\texttt{PreSex}] Data on pre- and extra-marital sex and divorce. Source: \cite{vcd:thornes+collard:1979}. Taken from \cite{vcd:gilbert:1981}. Package: \pkg{vcd}. \item[\texttt{Titanic}] Information on the fate of passengers on the fatal maiden voyage of the ocean liner ``Titanic'', summarized according to economic status (class), gender (\code{Sex}), age and survival. Data originally collected by the British Board of Trade in their investigation of the sinking. Taken from: \cite{vcd:dawson:1995}. Package: \pkg{datasets} (included in base \proglang{R}). \item[\texttt{UCBAdmissions}] Aggregate data on applicants to graduate school at Berkeley for the six largest departments in 1973 classified by admission and gender. Source: \cite{vcd:Bickel+Hammel+O'Connell:1975}. Taken from: \cite{vcd:Friendly:2000}. Package: \pkg{datasets} (included in base \proglang{R}). \end{description} \end{appendix} \end{document} vcd/vignettes/struc.sxi0000644000175300001440000002162011720273431014573 0ustar meyerusersPKJS3Xmimetypeapplication/vnd.sun.xml.impressPKJS3 content.xml\[~ϯ ReWZ/SJuص$O$2HF3 yIIN7!GGt>Ǖ/<{ap-H8kK7o~ۻ|As!WnW$H&N$WoV'釈8 b:}wNHew 􇿊>+޼iz8WiﵸLj: 55$IZn'0=f1zaS1:Z+xH0-: A(ϙp=7oޅwW`n$Y< RCDxAΈ4H,a~AuN&5FY8'qxxxlfxA+ /(7IzWԭ{5|Z 8/!IY{ZyY9q{sY 2۶UeN!WC?qB{R YKb?ˀ<ɨOL6E[,s^heΪh!6 =Vmh6_XBWV` sKBd~; # 1 IXFYd Ɇ.Đ_zOOR\> XFiD$U#l!~)zA|L:R5 QHzeuc?Ï[Jȕj8/rZ#,/d qsQuww2Q[d{y|h)v>Vs8A7mԭm+L %H鮹0V4{ -)mwn+YPs)~mdAB=ƋK4lC#~.ijmsDZU LDkӱ4wM`1W}Qw^+xx}GkauνGn":ETm,Zl5)i WOq2,@!@L$adt3swp6*Įߤo$_W8ObL]^YX&1[>I2횰cȟL?=faaW@Psʬ,4Ji\8!CNG؁'yHIy+}kڅ;>{XH/vyء t(:'!+]bꃎLU 1䗠KRRkoQGn(KeUdjrG9)(32J T8!nf.~ҏr T$Ea@ x$pYPO0(np16ۀ0eaSC <a"8ς~ a q=;B6tu hH95őXLv 'x dl:\򁒰dժ+VeYzmd8sYevϵA}G;RtR&}x"&VoviyvC-P_ LI<1qz&ux<c!j3`pct2~^%tzʼxjs;:MnS J> ogVY%3$̗8И:}:S^@cpLq}ė˯eg˯{-3a*cR!L!!k>,IIS;p34OoPXZI$d᭖ܧw_9I\fZmFxmeˬM6N7e9T|}FPy-+u$)reHBn[:*FѲN] }746-L7ZN}PKF1D *\PKJS3 styles.xml][6~_J޸ v&dk3S=UGd vw>_ .6`Ʒf|^@zqh".K0rGe,pۿ?Kh6]x!w(U5ˏ$+i OTJE\%>k$hϿʒ.z'6\k%7r"/tyiw1u]o9k@[S .—U`T{1XJ8\z^kJh|亼~QrhNaܮ HAe  Ҳ,N3snq;Tviy\#h@g=J8l8scٮ9 噧?_a,G ~!Z0b7>\^&.钩K1 -LY׽ l2C7_;DO~ ?P"V(;F0݉O]q PJ?0$M@e+0E0.ZEiuXwK ~/#k4zV6% `jJP7̔*+p@O`Q,hV-U.SBR,Ⱦu#Er銆e'r⓫T18x%)\u8*!J:Uh`6=6/x"Xu"j̻mk"Ϊk@W?^gaRa=,&EDbpV Y_,~OayMљOWU]gfU ɴ&84=S5Ϊ.l%9֦i;vPA:})S:HӐD ZnyXfbͷ3Pͫ6>U?8|Sa[Wm@<3߾ju>C?eFRu5$MnS [F纜8_{U6hj 2|٫+ڹ2ÿ*kad(8f|O|C³`2fdq6e|V-Ϗ;H)^OF1vVU{6U}s&쵻 8ccKXTuAd^yAd^yAOKS݉W*ݲͶmnoUlkmܖ[3u6 l溎sr܊5fW숀j4+Jd {ͼ.`n &`n &˼xXY7%L6Ra&6;=ni _/Z~)̯;R짘B~w=FPP@mUeg-ԮTz0@y&-]p~Wىy:N7uqd^ՈV#jZXk5|ǵ CT#Xb-̞g- j r[ZkEZkeLu#t)aS&oS/`l[RF{:>F矆"~̞'~ jJ.]D 蟠 '蟠Y8`')c2΢/wvQW=Isq?{IθwG;v{3@nwΏntιjv~xfǧl?Mő>U8NfvDZ]m7nImeK1.r"+,鼍aVۆ޾Z Ϫ6Z[mPjvY֞X^~ZϠKt} jt u>ku}@uTPj}Sj#eI>WD'Ų2 J;$6'+,tl2} `g>LWGzT0ma[3&v~nXUxmQvz=!ꑁ`T.sLC8Ů2xD_|g8'.X\Lmj['[#Vqǵw:f/2wK1v'/o}A,n6cLQgv_VTKP&Ed)]3n{ō.bHd!S96`d!{b56D42J[-Lp? Ucmߑ:ܑO%S|}ҍ#25(dJ | <;zԦ]U~yiUyOҗa2h9E/ձQ9gXial"e}T齆|$*ޔekZgۊ(gXi7PָɼL} HZ|lTaxG%PlGO(tޥ#TݟXNIwܿN[ILmwhJ7q^!w7?PK 8PKJS3*meta.xml OpenOffice.org 1.1.4 (Linux)2005-09-18T14:10:532005-10-19T11:22:15en-US8PT1H47M45SPKJS3 settings.xmlZ[W8~_u(.9I'I_?i/XӚYli}{d_' xhD]a:0?Ne0V cn#*Rn6*4;d!3tNauﬧiVFXz3.w+)8[=0Rg{)Ye'y|EQ2X.fhPP&d<`Z\ 16|cg7^D~lk }eGgisގa\!Ҹ<8*q~ d*xh}ύ~=9O?*Os_!<_*}8> 0PXY|Q+O0.c(fDc!؂2F$qFm.y!h}߅3Ԃ|ЧCiL"WָRV,]N]rtI( Dp{cUiDT 1uY&fk/$Ҏ7ʪ{.K^&\~l+!Ҹ4?wzM:!%HdyE1CX60ދ{!A|oɎ7* o9jd7}DԉK"q^6J- "Vv$M "cQ"gLU\Q5hLZ7L-($L7|PJY\1r_*|{'1.@|Q7ނ,L-12&0)}t_^w˞N1J[\qUVdxsc'b߷Cq(g{Qd,9A="b*݂]C6aДA5=]m5+W7!OZ ˡ@܁~}&acn05wt0AgЛ3>RIy5c3T2E0:/9lM.r ^a~r%ԗVI]Qw7XsRyB0$R ֗iSy>@~qSKaJ&Y'w61| ^~bq43Bz{ L&e[+(]{s5 NP~ +C]}HZ6c v7BG51 z+ttI_\+݀$HBIWI GZ UXwiz 0 ԑבXqTP㉟J)*_ajɞUi׌`}_W I6)O1E2 ee.0/_RJ9:cdu}aΚGh Zu0=ohyCh4Ok6_ƽzSJoQF:/['W-+~Y=awd?:!/KHwPZ kp㻠Dqt@*Qt͸Tӣ޶c- P^=Ұ0o՞3-ŲΫ޼B4tjjbATէ D+4--Wbyj_M5y~ So^e5>ndJm[z5T=-E,n*'NxJDڬݫXxw9[2^b*k~XM-ᥨq 7ZvSiJT-پ2CPKOץ1)PKJS3META-INF/manifest.xmlұj0Onө;)ڃ3t49Ȓ!~BI_piq+kRX6S8+l7Osʟb/ʨ<(o;bmj?"fe&`#A$n fe‰٭m Yj Ԩ*Q sZ_4FRu'aj#W)|h}P5aȣӅ1dphĢQ_툫sko6k PKI\zPKJS3XmimetypePKJS3F1D *\ Econtent.xmlPKJS3 8 3 styles.xmlPKJS3*meta.xmlPKJS3Oץ1) settings.xmlPKJS3I\z META-INF/manifest.xmlPKZ "vcd/vignettes/residual-shadings.Rnw0000644000175300001440000003655511720273431017021 0ustar meyerusers\documentclass{Z} %% need no \usepackage{Sweave} \usepackage{rotating} \newcommand{\given}{\, | \,} \title{Residual-based Shadings in \pkg{vcd}} \Plaintitle{Residual-based Shadings in vcd} \author{Achim Zeileis, David Meyer, \textnormal{and} Kurt Hornik\\Wirtschaftsuniversit\"at Wien, Austria} \Plainauthor{Achim Zeileis, David Meyer, Kurt Hornik} \Abstract{ This vignette is a companion paper to \cite{vcd:Zeileis+Meyer+Hornik:2005} which introduces several extensions to residual-based shadings for enhancing mosaic and association plots. The paper introduces (a)~perceptually uniform Hue-Chroma-Luminance (HCL) palettes and (b)~incorporates the result of an associated significance test into the shading. Here, we show how the examples can be easily reproduced using the \pkg{vcd} package. } \Keywords{association plots, conditional inference, contingency tables, HCL colors, HSV colors, mosaic plots} \begin{document} %\VignetteIndexEntry{Residual-based Shadings in vcd} %\VignetteDepends{vcd,colorspace,MASS,grid,HSAUR} %\VignetteKeywords{association plots, conditional inference, contingency tables, HCL colors, HSV colors, mosaic plots} %\VignettePackage{vcd} \SweaveOpts{engine=R,eps=FALSE} \section{Introduction} \label{sec:intro} In this vignette, we show how all empirical examples from \cite{vcd:Zeileis+Meyer+Hornik:2005} can be reproduced in \proglang{R}\citep[\mbox{\url{http://www.R-project.org/}}]{vcd:R:2006}, in particular using the package \pkg{vcd} \citep{vcd:Meyer+Zeileis+Hornik:2006}. Additionally, the pakcages \pkg{MASS} \citep[see][]{vcd:Venables+Ripley:2002}, \pkg{grid} \citep[see][]{vcd:Murrell:2002} and \pkg{colorspace} \citep{vcd:Ihaka:2004} are employed. All are automatically loaded together with \pkg{vcd}: <>= library("vcd") rseed <- 1071 @ Furthermore, we define a \code{rseed} which will be used as the random seed for making the results of the permutation tests (conditional inference) below exactly reproducible. In the following, we focus on the \proglang{R} code and output---for background information on the methods and the data sets, please consult \cite{vcd:Zeileis+Meyer+Hornik:2005}. \section{Arthritis data} \label{sec:arthritis} First, we take a look at the association of treatment type and improvement in the \code{Arthritis} data. The data set can be loaded and brought into tabular form via: <>= data("Arthritis", package = "vcd") (art <- xtabs(~ Treatment + Improved, data = Arthritis, subset = Sex == "Female")) @ Two basic explorative views of such a 2-way table are mosaic plots and association plots. They can be generated via \code{mosaic()} and \code{assoc()} from \pkg{vcd}, respectively. For technical documentation of these functions, please see \cite{vcd:Meyer+Zeileis+Hornik:2006b}. When no further arguments are supplied as in <>= mosaic(art) assoc(art) @ this yields the plain plots without any color shading, see Figure~\ref{fig:classic}. Both indicate that there are more patients in the treatment group with marked improvement and less without improvement than would be expected under independence---and vice versa in the placebo group. \setkeys{Gin}{width=\textwidth} \begin{figure}[b!] \begin{center} <>= grid.newpage() pushViewport(viewport(layout = grid.layout(1, 2))) pushViewport(viewport(layout.pos.col=1, layout.pos.row=1)) mosaic(art, newpage = FALSE, margins = c(2.5, 4, 2.5, 3)) popViewport() pushViewport(viewport(layout.pos.col=2, layout.pos.row=1)) assoc(art, newpage = FALSE, margins = c(5, 2, 5, 4)) popViewport(2) @ \caption{Classic mosaic and association plot for the arthritis data.} \label{fig:classic} \end{center} \end{figure} For 2-way tables, \cite{vcd:Zeileis+Meyer+Hornik:2005} suggest to extend the shading of \cite{vcd:Friendly:1994} to also visualize the outcome of an independence test---either using the sum of squares of the Pearson residuals as the test statistic or their absolute maximum. Both statistics and their corresponding (approximate) permutation distribution can easily be computed using the function \code{coindep_test()}. Its arguments are a contingency table, a specification of margins used for conditioning (only for conditional independence models), a functional for aggregating the Pearson residuals (or alternatively the raw counts) and the number of permutations that should be drawn. The conditional table needs to be a 2-way table and the default is to compute the maximum statistic (absolute maximum of Pearson residuals). For the Arthritis data, both, the maximum test <>= set.seed(rseed) (art_max <- coindep_test(art, n = 5000)) @ and the sum-of-squares test, indicate a significant departure from independence. <>= ss <- function(x) sum(x^2) set.seed(rseed) coindep_test(art, n = 5000, indepfun = ss) @ Thus, it can be concluded that the treatment is effective and leads to significantly more improvement than the placebo. The classic views from Figure~\ref{fig:classic} and the inference above can also be combined, e.g., using the maximum shading that highlights the cells in an association or mosaic plot when the associated residuals exceed critical values of the maximum test (by default at levels 90\% and 99\%). To compare this shading (using either HSV or HCL colors) with the Friendly shading (using HSV colors), we generate all three versions of the mosaic plot: <>= mosaic(art, gp = shading_Friendly(lty = 1, eps = NULL)) mosaic(art, gp = shading_hsv, gp_args = list( interpolate = art_max$qdist(c(0.9, 0.99)), p.value = art_max$p.value)) set.seed(rseed) mosaic(art, gp = shading_max, gp_args = list(n = 5000)) @ the results are shown in the upper row of Figure~\ref{fig:shadings}. The last plot could hae also been generated analogously to the second plot using \code{shading_hcl()} instead of \code{shading_hsv()}---\code{shading_max()} is simply a wrapper function which performs the inference and then visualizes it based on HCL colors. \section{Piston rings data} \label{sec:arthritis} Instead of bringing out the result of the maximum test in the shading, we could also use a sum-of-squares shading that visualizes the result of the sum-of-squares test. As an illustration, we use the \code{pistonrings} data from the \code{HSAUR} \citep{vcd:Everitt+Hothorn:2006} package giving the number of piston ring failurs in different legs of different compressors at an industry plant: <>= data("pistonrings", package = "HSAUR") pistonrings @ \begin{sidewaysfigure}[p] \begin{center} <>= mymar <- c(1.5, 0.5, 0.5, 2.5) grid.newpage() pushViewport(viewport(layout = grid.layout(2, 3))) pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 1)) mosaic(art, margins = mymar, newpage = FALSE, gp = shading_Friendly(lty = 1, eps = NULL)) popViewport() pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 2)) mosaic(art, gp = shading_hsv, margins = mymar, newpage = FALSE, gp_args = list(interpolate = art_max$qdist(c(0.9, 0.99)), p.value = art_max$p.value)) popViewport() pushViewport(viewport(layout.pos.row = 1, layout.pos.col = 3)) set.seed(rseed) mosaic(art, gp = shading_max, margins = mymar, newpage = FALSE, gp_args = list(n = 5000)) popViewport() pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 1)) mosaic(pistonrings, margins = mymar, newpage = FALSE, gp = shading_Friendly(lty = 1, eps = NULL, interpolate = c(1, 1.5))) popViewport() pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 2)) mosaic(pistonrings, gp = shading_hsv, margins = mymar, newpage = FALSE, gp_args = list(p.value = 0.069, interpolate = c(1, 1.5))) popViewport() pushViewport(viewport(layout.pos.row = 2, layout.pos.col = 3)) mosaic(pistonrings, gp = shading_hcl, margins = mymar, newpage = FALSE, gp_args = list(p.value = 0.069, interpolate = c(1, 1.5))) popViewport(2) @ \includegraphics[width=.9\textwidth,keepaspectratio]{residual-shadings-shadings} \caption{Upper row: Mosaic plot for the arthritis data with Friendly shading (left), HSV maximum shading (middle), HCL maximum shading (right). Lower row: Mosaic plot for the piston rings data with fixed user-defined cut offs 1 and 1.5 and Friendly shading (left), HSV sum-of-squares shading (middle), HCL sum-of-squares shading (right).} \label{fig:shadings} \end{center} \end{sidewaysfigure} Although there seems to be some slight association between the leg (especially center and South) and the compressor (especially numbers 1 and 4), there is no significant deviation from independence: <>= set.seed(rseed) coindep_test(pistonrings, n = 5000) set.seed(rseed) (pring_ss <- coindep_test(pistonrings, n = 5000, indepfun = ss)) @ This can also be brought out graphically in a shaded mosaicplot by enhancing the Friendly shading (based on the user-defined cut-offs 1 and 1.5, here) to use a less colorful palette, either based on HSV or HCL colors: <>= mosaic(pistonrings, gp = shading_Friendly(lty = 1, eps = NULL, interpolate = c(1, 1.5))) mosaic(pistonrings, gp = shading_hsv, gp_args = list(p.value = pring_ss$p.value, interpolate = c(1, 1.5))) mosaic(pistonrings, gp = shading_hcl, gp_args = list(p.value = pring_ss$p.value, interpolate = c(1, 1.5))) @ The resulting plots can be found in the lower row of Figure~\ref{fig:shadings}. The default in \code{shading_hcl()} and \code{shading_hsv()} is to use the asymptotical $p$~value, hence we set it explicitely to the permtuation-based $p$~value computed above. \section{Alzheimer and smoking} \label{sec:alzheimer} For illustrating that the same ideas can be employed for visualizing (conditional) independence in multi-way tables, \cite{vcd:Zeileis+Meyer+Hornik:2005} use a 3-way and a 4-way table. The former is taken from a case-control study of smoking and {A}lzheimer's disease (stratified by gender). The data set is available in \proglang{R} in the package \pkg{coin} \cite{vcd:Hothorn+Hornik+VanDeWiel:2006}. <>= data("alzheimer", package = "coin") alz <- xtabs(~ smoking + disease + gender, data = alzheimer) alz @ \begin{figure}[b!] \begin{center} <>= set.seed(rseed) cotabplot(~ smoking + disease | gender, data = alz, panel = cotab_coindep, n = 5000) @ \caption{Conditional mosaic plot with double maximum shading for conditional independence of smoking and disease given gender.} \label{fig:alz} \end{center} \end{figure} To assess whether smoking behaviour and disease status are conditionally independent given gender, \cite{vcd:Zeileis+Meyer+Hornik:2005} use three different types of test statistics: double maximum (maximum of maximum statistics in the two strata), maximum sum of squares (maximum of sum-of-squares statistics), and sum of squares (sum of sum-of-squares statistics). All three can be computed and assessed via permutation methods using the function \code{coindep_test()}: <>= set.seed(rseed) coindep_test(alz, 3, n = 5000) set.seed(rseed) coindep_test(alz, 3, n = 5000, indepfun = ss) set.seed(rseed) coindep_test(alz, 3, n = 5000, indepfun = ss, aggfun = sum) @ The conditional mosaic plot in Figure~\ref{fig:alz} shows clearly that the association of smoking and disease is present only in the group of male patients. The double maximum shading employed allows for identification of the male heavy smokers as the cells `responsible' for the dependence: other dementias are more frequent and Alzheimer's disease less frequent in this group than expected under independence. Interestingly, there seems to be another large residual for the light smoker group ($<$10 cigarettes) and Alzheimer's disease---however, this is only significant at 10\% and not at the 1\% level as the other two cells. <>= <> @ \section{Corporal punishment of children} As a 4-way example, data from a study of the Gallup Institute in Denmark in 1979 about the attitude of a random sample of 1,456 persons towards corporal punishment of children is used. The contingency table comprises four margins: memory of punishments as a child (yes/no), attitude as a binary variable (approval of ``moderate'' punishment or ``no'' approval), highest level of education (elementary/secondary/high), and age group (15--24, 25--39, $\ge$40 years). <>= data("Punishment", package = "vcd") pun <- xtabs(Freq ~ memory + attitude + age + education, data = Punishment) ftable(pun, row.vars = c("age", "education", "memory")) @ It is of interest whether there is an association between memories of corporal punishments as a child and attitude towards punishment of children as an adult, controlling for age and education. All three test statistics already used above confirm that memories and attitude are conditionally associated: \setkeys{Gin}{width=\textwidth} \begin{figure}[t!] \begin{center} <>= set.seed(rseed) cotabplot(~ memory + attitude | age + education, data = pun, panel = cotab_coindep, n = 5000, type = "assoc", test = "maxchisq", interpolate = 1:2) @ \caption{Conditional association plot with maximum sum-of-squares shading for conditional independence of memory and attitude given age and education.} \label{fig:pun} \end{center} \end{figure} \setkeys{Gin}{width=\textwidth} \begin{figure}[t!] \begin{center} <>= set.seed(rseed) cotabplot(~ memory + attitude | age + education, data = pun, panel = cotab_coindep, n = 5000, type = "mosaic", test = "maxchisq", interpolate = 1:2) @ \caption{Conditional mosaic plot with maximum sum-of-squares shading for conditional independence of memory and attitude given age and education.} \label{fig:pun2} \end{center} \end{figure} <>= set.seed(rseed) coindep_test(pun, 3:4, n = 5000) set.seed(rseed) coindep_test(pun, 3:4, n = 5000, indepfun = ss) set.seed(rseed) coindep_test(pun, 3:4, n = 5000, indepfun = ss, aggfun = sum) @ Graphically, this dependence can be brought out using conditional association or mosaic plots as shown in Figure~\ref{fig:pun} and \ref{fig:pun2}, respectively. Both reveal an association between memories and attitude for the lowest education group (first column) and highest age group (last row): experienced violence seems to engender violence again as there are less adults that disapprove punishment in the group with memories of punishments than expected under independence. For the remaining four age-education groups, there seems to be no association: all residuals of the conditional independence model are very close to zero in these cells. The figures employ the maximum sum-of-squares shading with user-defined cut offs 1 and 2, chosen to be within the range of the residuals. The full-color palette is used only for those strata associated with a sum-of-squares statistic significant at (overall) 5\% level, the reduced-color palette is used otherwise. This highlights that the dependence pattern is significant only for the middle and high age group in the low education column. The other panels in the first column and last row also show a similar dependence pattern, however, it is not significant at 5\% level and hence graphically down-weighted by using reduced color. <>= <> @ <>= <> @ \bibliography{vcd} \end{document} vcd/demo/0000755000175300001440000000000011720426624011625 5ustar meyerusersvcd/demo/hls.R0000644000175300001440000000403211566471034012540 0ustar meyerusersif(require("tcltk")) { hue <- tclVar("hue") luminance <- tclVar("luminance") saturation <- tclVar("saturation") hue <- tclVar(0) hue.sav <- 0 luminance <- tclVar(0.5) luminance.sav <- 0.5 saturation <- tclVar(1) saturation.sav <- 1 replot <- function(...) { hue.sav <- my.h <- as.numeric(tclvalue(hue)) saturation.sav <- my.s <- as.numeric(tclvalue(saturation)) luminance.sav <- my.l <- as.numeric(tclvalue(luminance)) barplot(1, col = hls(my.h, my.l, my.s), axes = FALSE) } replot.maybe <- function(...) { if(!((as.numeric(tclvalue(hue)) == hue.sav) && (as.numeric(tclvalue(saturation)) == saturation.sav) && (as.numeric(tclvalue(luminance)) == luminance.sav))) replot() } base <- tktoplevel() tkwm.title(base, "HLS Colors") spec.frm <- tkframe(base, borderwidth = 2) hue.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) saturation.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) luminance.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) tkpack(tklabel(hue.frm, text = "Hue")) tkpack(tkscale(hue.frm, command = replot.maybe, from = 0, to = 1, showvalue = TRUE, variable = hue, resolution = 0.01, orient = "horiz")) tkpack(tklabel(luminance.frm, text = "Luminance")) tkpack(tkscale(luminance.frm, command = replot.maybe, from = 0, to = 1, showvalue = TRUE, variable = luminance, resolution = 0.01, orient = "horiz")) tkpack(tklabel(saturation.frm, text = "Saturation")) tkpack(tkscale(saturation.frm, command = replot.maybe, from = 0, to = 1, showvalue = TRUE, variable = saturation, resolution = 0.01, orient = "horiz")) tkpack(hue.frm, luminance.frm, saturation.frm, fill="x") ## Bottom frame on base: q.but <- tkbutton(base, text = "Quit", command = function() tkdestroy(base)) tkpack(spec.frm, q.but) replot() } vcd/demo/00Index0000644000175300001440000000062611566471034012766 0ustar meyerusersdiscrete Fitting and Graphing Discrete Distributions twoway 2-Way Contingency Tables mosaic Mosaic displays hcl Tcl/Tk-Demo for `hcl' colors hsv Tcl/Tk-Demo for `hsv' colors hls Tcl/Tk-Demo for `hls' colors strucplot Demo for new strucplot suite (assoc, mosaic, doubledeckerplot) mondrian Demo for (re)producing modern art using mosaic() hullternary Demo for adding data point hulls to a ternary plot vcd/demo/mosaic.R0000644000175300001440000000651711566471034013237 0ustar meyerusers##################### ## Mosaic Displays ## ##################### ######################### ## Hair Eye Color Data ## ######################### data(HairEyeColor) ## Basic Mosaic Display ## HairEye <- margin.table(HairEyeColor, c(1,2)) mosaic(HairEye, main = "Basic Mosaic Display of Hair Eye Color data") ## Hair Mosaic Display with Pearson residuals ## Hair <- margin.table(HairEyeColor,1) Hair mHair <- as.table(rep(mean(margin.table(HairEyeColor, 1)), 4)) names(mHair) <- names(Hair) mHair ## Pearson residuals from Equiprobability model ## resid <- (Hair - mHair) / sqrt(mHair) resid ## First Step in a Mosaic Display ## mosaic(Hair, residuals = resid, main = "Hair Color Proportions") ## Hair Eye Mosais Display with Pearson residuals ## mosaic(HairEye, main = " Hair Eye Color with Pearson residuals") ## Show Pearson Residuals ## (HairEye - loglin(HairEye, c(1, 2), fit = TRUE)$fit) / sqrt(loglin(HairEye, c(1, 2), fit = TRUE)$fit) ################### ## UKSoccer Data ## ################### data(UKSoccer) ## UKSoccer Mosaic Display ## mosaic(UKSoccer, main = "UK Soccer Scores") ############################### ## Repeat Victimization Data ## ############################### data(RepVict) ## mosaic(RepVict[-c(4, 7), -c(4, 7)], main = "Repeat Victimization Data") ################## ## 3-Way Tables ## ################## ## Hair Eye Sex Mosais Display with Pearson residuals ## mosaic(HairEyeColor, main = "Hair Eye Color Sex" ) mosaic(HairEyeColor, expected = ~ Hair * Eye + Sex, main = "Model: (Hair Eye) (Sex)" ) mosaic(HairEyeColor, expected = ~ Hair * Sex + Eye*Sex, main = "Model: (Hair Sex) (Eye Sex)") #################### ## Premarital Sex ## #################### data(PreSex) ## Mosaic display for Gender and Premarital Sexual Expirience ## ## (Gender Pre) ## mosaic(margin.table(PreSex, c(3, 4)), legend = FALSE, main = "Gender and Premarital Sex") ## (Gender Pre)(Extra) ## mosaic(margin.table(PreSex,c(2,3,4)), legend = FALSE, expected = ~ Gender * PremaritalSex + ExtramaritalSex , main = "(PreMaritalSex Gender) (Sex)") ## (Gender Pre Extra)(Marital) ## mosaic(PreSex, expected = ~ Gender * PremaritalSex * ExtramaritalSex + MaritalStatus, legend = FALSE, main = "(PreMarital ExtraMarital) (MaritalStatus)") ## (GPE)(PEM) ## mosaic(PreSex, expected = ~ Gender * PremaritalSex * ExtramaritalSex + MaritalStatus * PremaritalSex * ExtramaritalSex, legend = FALSE, main = "(G P E) (P E M)") ############################ ## Employment Status Data ## ############################ data(Employment) ## Employment Status ## # mosaic(Employment, # expected = ~ LayoffCause * EmploymentLength + EmploymentStatus, # main = "(Layoff Employment) + (EmployStatus)") # mosaic(Employment, # expected = ~ LayoffCause * EmploymentLength + # LayoffCause * EmploymentStatus, # main = "(Layoff EmpL) (Layoff EmplS)") # ## Closure ## # mosaic(Employment[,,1], main = "Layoff : Closure") # ## Replaced ## # mosaic(Employment[,,2], main = "Layoff : Replaced") ##################### ## Mosaic Matrices ## ##################### data(UCBAdmissions) pairs(PreSex) pairs(UCBAdmissions) pairs(UCBAdmissions, type = "conditional") pairs(UCBAdmissions, type = "pairwise", gp = shading_max) vcd/demo/hcl.R0000644000175300001440000000467211566471034012532 0ustar meyerusersif(require("tcltk")) { hue <- tclVar("hue") chroma <- tclVar("chroma") luminance <- tclVar("luminance") fixup <- tclVar("fixup") hue <- tclVar(230) hue.sav <- 230 chroma <- tclVar(55) chroma.sav <- 55 luminance <- tclVar(75) luminance.sav <- 75 fixup <- tclVar(FALSE) replot <- function(...) { hue.sav <- my.h <- as.numeric(tclvalue(hue)) chroma.sav <- my.c <- as.numeric(tclvalue(chroma)) luminance.sav <- my.l <- as.numeric(tclvalue(luminance)) my.fixup <- as.logical(as.numeric(tclvalue(fixup))) barplot(1, col = hcl2hex(my.h, my.c, my.l, fixup = my.fixup), axes = FALSE) } replot.maybe <- function(...) { if(!((as.numeric(tclvalue(hue)) == hue.sav) && (as.numeric(tclvalue(chroma)) == chroma.sav) && (as.numeric(tclvalue(luminance)) == luminance.sav))) replot() } base <- tktoplevel() tkwm.title(base, "HCL Colors") spec.frm <- tkframe(base, borderwidth = 2) hue.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) chroma.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) luminance.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) fixup.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) tkpack(tklabel(hue.frm, text = "Hue")) tkpack(tkscale(hue.frm, command = replot.maybe, from = 0, to = 360, showvalue = TRUE, variable = hue, resolution = 1, orient = "horiz")) tkpack(tklabel(chroma.frm, text = "Chroma")) tkpack(tkscale(chroma.frm, command = replot.maybe, from = 0, to = 100, showvalue = TRUE, variable = chroma, resolution = 5, orient = "horiz")) tkpack(tklabel(luminance.frm, text = "Luminance")) tkpack(tkscale(luminance.frm, command = replot.maybe, from = 0, to = 100, showvalue = TRUE, variable = luminance, resolution = 5, orient = "horiz")) tkpack(tklabel(fixup.frm, text="Fixup")) for (i in c("TRUE", "FALSE") ) { tmp <- tkradiobutton(fixup.frm, command = replot, text = i, value = as.logical(i), variable = fixup) tkpack(tmp, anchor="w") } tkpack(hue.frm, chroma.frm, luminance.frm, fixup.frm, fill="x") ## Bottom frame on base: q.but <- tkbutton(base, text = "Quit", command = function() tkdestroy(base)) tkpack(spec.frm, q.but) replot() } vcd/demo/strucplot.R0000644000175300001440000000413111566471034014011 0ustar meyerusersdata("Titanic") data("UCBAdmissions") data("HairEyeColor") data("PreSex") mosaic(Titanic) mosaic(Titanic, shade = TRUE) mosaic(~ Sex + Class, data = Titanic, shade = TRUE) mosaic(~ Sex + Class + Survived, data = Titanic, shade = TRUE) mosaic(~ PremaritalSex + ExtramaritalSex | MaritalStatus + Gender, data = PreSex) mosaic(~ PremaritalSex + ExtramaritalSex | MaritalStatus + Gender, data = PreSex, labeling = labeling_conditional(abbreviate_varnames = TRUE)) mosaic(Titanic, spacing = spacing_increase()) mosaic(Titanic, spacing = spacing_equal()) mosaic(Titanic, labeling = labeling_border()) mosaic(Titanic, labeling = labeling_cells()) mosaic(Titanic, labeling = labeling_cells(abbreviate_labels = TRUE)) mosaic(Titanic, labeling = labeling_cells(abbreviate_varnames = TRUE)) mosaic(Titanic, labeling = labeling_cells(abbreviate_varnames = TRUE, abbreviate_labels = TRUE)) mosaic(Titanic, labeling = labeling_border(abbreviate = TRUE)) mosaic(Titanic, labeling = labeling_border(abbreviate = c(Survived = TRUE))) mosaic(Titanic, labeling = labeling_border(rot_labels = c(bottom = 45))) mosaic(Titanic, labeling = labeling_border(tl_labels = TRUE)) mosaic(Titanic, labeling = labeling_border(tl_labels = TRUE, tl_varnames = FALSE)) mosaic(Titanic, labeling = labeling_border(tl_labels = TRUE, tl_varnames = c(TRUE,TRUE,FALSE,FALSE), boxes = TRUE)) mosaic(Titanic, labeling = labeling_cboxed()) mosaic(Titanic, labeling = labeling_lboxed()) mosaic(Titanic, labeling = labeling_left()) mosaic(Titanic, labeling = labeling_list(), mar = c(2,2,4,2)) mosaic(Titanic, labeling = labeling_border(rep = FALSE)) mosaic(Titanic, labeling = labeling_border(labbl_varnames = c(TRUE,TRUE,FALSE,FALSE))) mosaic(~ Gender + Admit | Dept, data = UCBAdmissions, labeling = labeling_conditional(labels_varnames = TRUE, varnames = FALSE), keep_aspect_ratio = FALSE, split_vertical = c(Dept = TRUE)) doubledecker(Titanic) assoc(Hair ~ Eye, data = HairEyeColor) assoc(Hair ~ Eye, data = HairEyeColor, compress = FALSE) assoc(HairEyeColor, labeling = labeling_lboxed()) pairs(Titanic, shade = TRUE) pairs(Titanic, panel_upper = pairs_assoc, shade = TRUE) vcd/demo/twoway.R0000644000175300001440000001467711566471034013324 0ustar meyerusers ##################### ## Fourfold tables ## ##################### ### Berkeley Admission Data ### ############################### data(UCBAdmissions) ## unstratified ### no margin is standardized x <- margin.table(UCBAdmissions, 2:1) fourfold(x, std = "i", extended = FALSE) ### std. for gender fourfold(x, margin = 1, extended = FALSE) ### std. for both fourfold(x, extended = FALSE) ## stratified fourfold(UCBAdmissions, extended = FALSE) fourfold(UCBAdmissions) ## extended plots ## using cotabplot cotabplot(UCBAdmissions, panel = function(x, condlevels, ...) fourfold(co_table(x, names(condlevels))[[paste(condlevels, collapse = ".")]], newpage = F, ...) ) ### Coal Miners Lung Data ### ############################# data(CoalMiners) ## Fourfold display, both margins equated fourfold(CoalMiners, mfcol = c(2,4)) ## Log Odds Ratio Plot summary(l <- oddsratio(CoalMiners)) g <- seq(25, 60, by = 5) plot(l, xlab = "Age Group", main = "Breathelessness and Wheeze in Coal Miners") m <- lm(l ~ g + I(g^2)) lines(fitted(m), col = "red") ## Fourfold display, strata equated fourfold(CoalMiners, std = "ind.max", mfcol = c(2,4)) #################### ## Sieve Diagrams ## #################### ### Hair Eye Color ### ###################### data(HairEyeColor) ## aggregate over `sex': (tab <- margin.table(HairEyeColor, 1:2)) ## plot expected values: sieve(t(tab), sievetype = "expected", shade = TRUE) ## plot sieve diagram: sieve(t(tab), shade = TRUE) ### Visual Acuity ### ##################### data(VisualAcuity) attach(VisualAcuity) sieve(Freq ~ right + left, data = VisualAcuity, subset = gender == "female", main = "Unaided distant vision data", labeling_args = list(set_varnames = c(left = "Left Eye Grade", right = "Right Eye Grade")), shade = TRUE ) detach(VisualAcuity) ### Berkeley Admission ### ########################## ## -> Larger tables: e.g., Cross factors ### Cross Gender and Admission data(UCBAdmissions) (tab <- xtabs(Freq ~ Dept + I(Gender : Admit), data = UCBAdmissions)) sieve(tab, labeling_args = list(set_varnames = c("I(Gender:Admit)" = "Gender:Admission", Dept = "Department")), main = "Berkeley Admissions Data", shade = TRUE ) ## or use extended sieve plots: sieve(UCBAdmissions, shade = TRUE) ###################### ## Association Plot ## ###################### ### Hair Eye Color ### ###################### data(HairEyeColor) assoc(margin.table(HairEyeColor, 1:2), labeling_args = list(set_varnames = c(Hair = "Hair Color", Eye = "Eye Color")), main = "Association Plot") #################### ## Agreement Plot ## #################### ### Sexual Fun ### ################## data(SexualFun) ## Kappa statistics Kappa(SexualFun) ## Agreement Chart agreementplot(t(SexualFun), weights = 1) ## Partial Agreement Chart and B-Statistics (agreementplot(t(SexualFun), xlab = "Husband's Rating", ylab = "Wife's Rating", main = "Husband's and Wife's Sexual Fun") ) ### MS Diagnosis data ### ######################### data(MSPatients) ## use e.g., X11(width = 12), or expand graphics device agreementplot(t(MSPatients[,,1]), main = "Winnipeg Patients") agreementplot(t(MSPatients[,,2]), main = "New Orleans Patients") ################## ## Ternary Plot ## ################## ### sample data ### ################### (x <- rbind(c(A=10,B=10,C=80), c(40,30,30), c(20,60,20) ) ) ternaryplot(x, cex = 2, col = c("black", "blue", "red"), coordinates = TRUE ) ### Arthritis Treatment Data ### ################################ data(Arthritis) ## Build table by crossing Treatment and Sex (tab <- as.table(xtabs(~ I(Sex:Treatment) + Improved, data = Arthritis))) ## Mark groups col <- c("red", "red", "blue", "blue") pch <- c(1, 19, 1, 19) ## plot ternaryplot( tab, col = col, pch = pch, cex = 2, bg = "lightgray", grid_color = "white", labels_color = "white", main = "Arthritits Treatment Data" ) ## legend grid_legend(0.8, 0.7, pch, col, rownames(tab), title = "GROUP") ### Baseball Hitters Data ### ############################# data(Hitters) attach(Hitters) colors <- c("black","red","green","blue","red","black","blue") pch <- substr(levels(Positions), 1, 1) ternaryplot( Hitters[,2:4], pch = as.character(Positions), col = colors[as.numeric(Positions)], main = "Baseball Hitters Data" ) grid_legend(0.8, 0.9, pch, colors, levels(Positions), title = "POSITION(S)") detach(Hitters) ### Lifeboats on the Titanic ### ################################ data(Lifeboats) attach(Lifeboats) ternaryplot( Lifeboats[,4:6], pch = ifelse(side=="Port", 1, 19), col = ifelse(side=="Port", "red", "blue"), id = ifelse(men/total > 0.1, as.character(boat), NA), dimnames_position = "edge", dimnames = c("Men of Crew", "Men passengers", "Women and Children"), main = "Lifeboats on the Titanic" ) grid_legend(0.8, 0.9, c(1, 19), c("red", "blue"), c("Port", "Starboard"), title = "SIDE") ## Load against time for Port/Starboard boats plot(launch, total, pch = ifelse(side == "Port", 1, 19), col = ifelse(side == "Port", "red", "darkblue"), xlab = "Launch Time", ylab = "Total loaded", main = "Lifeboats on the Titanic" ) legend(as.POSIXct("1912-04-15 01:48:00"), 70, legend = c("SIDE","Port","Starboard"), pch = c(NA, 1, 19), col = c(NA, "red", "darkblue") ) text(as.POSIXct(launch), total, labels = as.character(boat), pos = 3, offset = 0.3 ) abline(lm(total ~ as.POSIXct(launch), subset = side == "Port"), col = "red") abline(lm(total ~ as.POSIXct(launch), subset = side == "Starboard"), col = "darkblue") detach(Lifeboats) vcd/demo/hullternary.R0000644000175300001440000000301211566471034014320 0ustar meyerusers###################################################### #### ternary plot demo #### Task: plotting data point hulls in a ternary plot #### data provided by Manuel Dominguez-Rodrigo ###################################################### library(vcd) ## data humans=matrix(c(18,19,17,21,7,9,8,62,70,53,69,81,73,71,20,10,30,10,12,18,19), ncol=3) colnames(humans)=c("young", "adult", "old") lions=matrix(c(41,59,62,49,45,21,12,5,11,13,38,29,33,40,42), ncol=3) colnames(lions)=c("young", "adult", "old") site=matrix(c(9,12,15,11,70,62,69,68,21,26,16,21), ncol=3) colnames(site)=c("young", "adult", "old") humans=matrix(c(18,19,17,21,7,9,8,62,70,53,69,81,73,71,20,10,30,10,12,18,19), ncol=3) ## regular ternary plot data = rbind(humans, lions, site) count = c(nrow(humans), nrow(lions), nrow(site)) rownames(data) = rep(c("humans", "lions", "site"), count) cols = rep(c("red", "green", "blue"), count) ternaryplot(data, col = cols) ## now try to draw hull prop2xy <- function(x) { x <- as.matrix(x) x <- x / rowSums(x) xp <- x[,2] + x[,3] / 2 yp <- x[,3] * sqrt(3) / 2 cbind(x = xp, y = yp) } hullpoints <- function(x) { ind <- chull(x) ind <- c(ind, ind[1]) x[ind,] } drawhull <- function(data, color) { hp <- hullpoints(prop2xy(data)) grid.lines(hp[,"x"], hp[,"y"], gp = gpar(col = color)) } ## setup plot region without data points ternaryplot(data, col = NA, pop = FALSE) ## grab plot viewport downViewport("plot") ## now plot hulls drawhull(humans, "blue") drawhull(site, "red") drawhull(lions, "green") vcd/demo/mondrian.R0000644000175300001440000000115011566471034013557 0ustar meyeruserslibrary(vcd) ## shape foo1 <- c(3, 7, 3, 1.5) foo2 <- c(2, 6.5, 1.5) foo <- outer(foo1/sum(foo1), foo2/sum(foo2), "*") ## color mondrian <- rep("#EAE6E3", 12) mondrian[1] <- "#DE1024" mondrian[3] <- "#FFD83B" mondrian[12] <- "#032349" ## plot ## best visualized with resized display, e.g. using: ## get(getOption("device"))(width = 4.9, height = 7.5) grid.newpage() grid.rect(gp = gpar(fill = 1)) mondrianMosaic <- function(x, fill) mosaic(x, gp = gpar(col = rep(0, length(fill)), fill = fill), legend = FALSE, margins = 0, newpage = FALSE, keep_aspect_ratio = FALSE) mondrianMosaic(foo, mondrian) vcd/demo/hsv.R0000644000175300001440000000373611566471034012564 0ustar meyerusersif(require("tcltk")) { hue <- tclVar("hue") saturation <- tclVar("saturation") value <- tclVar("value") hue <- tclVar(0) hue.sav <- 0 saturation <- tclVar(1) saturation.sav <- 1 value <- tclVar(1) value.sav <- 1 replot <- function(...) { hue.sav <- my.h <- as.numeric(tclvalue(hue)) saturation.sav <- my.s <- as.numeric(tclvalue(saturation)) value.sav <- my.v <- as.numeric(tclvalue(value)) barplot(1, col = hsv(my.h, my.s, my.v), axes = FALSE) } replot.maybe <- function(...) { if(!((as.numeric(tclvalue(hue)) == hue.sav) && (as.numeric(tclvalue(saturation)) == saturation.sav) && (as.numeric(tclvalue(value)) == value.sav))) replot() } base <- tktoplevel() tkwm.title(base, "HSV Colors") spec.frm <- tkframe(base, borderwidth = 2) hue.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) saturation.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) value.frm <- tkframe(spec.frm, relief = "groove", borderwidth = 2) tkpack(tklabel(hue.frm, text = "Hue")) tkpack(tkscale(hue.frm, command = replot.maybe, from = 0, to = 1, showvalue = TRUE, variable = hue, resolution = 0.01, orient = "horiz")) tkpack(tklabel(saturation.frm, text = "Saturation")) tkpack(tkscale(saturation.frm, command = replot.maybe, from = 0, to = 1, showvalue = TRUE, variable = saturation, resolution = 0.01, orient = "horiz")) tkpack(tklabel(value.frm, text = "Value")) tkpack(tkscale(value.frm, command = replot.maybe, from = 0, to = 1, showvalue = TRUE, variable = value, resolution = 0.01, orient = "horiz")) tkpack(hue.frm, saturation.frm, value.frm, fill="x") ## Bottom frame on base: q.but <- tkbutton(base, text = "Quit", command = function() tkdestroy(base)) tkpack(spec.frm, q.but) replot() } vcd/demo/discrete.R0000644000175300001440000001357211566471034013565 0ustar meyerusers ################################################# ## Fitting and Graphing Discrete Distributions ## ################################################# data(HorseKicks) barplot(HorseKicks, col = 2, xlab = "Number of Deaths", ylab = "Number of Corps-Years", main = "Deaths by Horse Kicks") data(Federalist) barplot(Federalist, col = 2, xlab = "Occurrences of 'may'", ylab = "Number of Blocks of Text", main = "'may' in Federalist papers") data(WomenQueue) barplot(WomenQueue, col = 2, xlab = "Number of women", ylab = "Number of queues", main = "Women in queues of length 10") data(WeldonDice) barplot(WeldonDice, names = c(names(WeldonDice)[-11], "10+"), col = 2, xlab = "Number of 5s and 6s", ylab = "Frequency", main = "Weldon's dice data") data(Butterfly) barplot(Butterfly, col = 2, xlab = "Number of individuals", ylab = "Number of Species", main = "Butterfly species im Malaya") ############################ ## Binomial distributions ## ############################ par(mfrow = c(1,2)) barplot(dbinom(0:10, p = 0.15, size = 10), names = 0:10, col = grey(0.7), main = "p = 0.15", ylim = c(0,0.35)) barplot(dbinom(0:10, p = 0.35, size = 10), names = 0:10, col = grey(0.7), main = "p = 0.35", ylim = c(0,0.35)) par(mfrow = c(1,1)) mtext("Binomial distributions", line = 2, cex = 1.5) plot(0:10, dbinom(0:10, p = 0.15, size = 10), type = "b", ylab = "Density", ylim = c(0, 0.4), main = "Binomial distributions, N = 10", pch = 19) lines(0:10, dbinom(0:10, p = 0.35, size = 10), type = "b", col = 2, pch = 19) lines(0:10, dbinom(0:10, p = 0.55, size = 10), type = "b", col = 4, pch = 19) lines(0:10, dbinom(0:10, p = 0.75, size = 10), type = "b", col = 3, pch = 19) legend(3, 0.4, c("p", "0.15", "0.35", "0.55", "0.75"), lty = rep(1,5), col = c(0,1,2,4,3), bty = "n") ########################### ## Poisson distributions ## ########################### par(mfrow = c(1,2)) dummy <- barplot(dpois(0:12, 2), names = 0:12, col = grey(0.7), ylim = c(0,0.3), main = expression(lambda == 2)) abline(v = dummy[3], col = 2) diff <- (dummy[3] - dummy[2]) * sqrt(2)/2 lines(c(dummy[3] - diff, dummy[3] + diff), c(0.3, 0.3), col = 2) dummy <- barplot(dpois(0:12, 5), names = 0:12, col = grey(0.7), ylim = c(0,0.3), main = expression(lambda == 5)) abline(v = dummy[6], col = 2) diff <- (dummy[6] - dummy[5]) * sqrt(5)/2 lines(c(dummy[6] - diff, dummy[6] + diff), c(0.3, 0.3), col = 2) par(mfrow = c(1,1)) mtext("Poisson distributions", line = 2, cex = 1.5) ##################################### ## Negative binomial distributions ## ##################################### nbplot <- function(p = 0.2, size = 2, ylim = c(0, 0.2)) { plot(0:20, dnbinom(0:20, p = p, size = size), type = "h", col = grey(0.7), xlab = "Number of failures (k)", ylab = "Density", ylim = ylim, yaxs = "i", bty = "L") nb.mean <- size * (1-p)/p nb.sd <- sqrt(nb.mean/p) abline(v = nb.mean, col = 2) lines(nb.mean + c(-nb.sd, nb.sd), c(0.01, 0.01), col = 2) legend(14, 0.2, c(paste("p = ", p), paste("n = ", size)), bty = "n") } par(mfrow = c(3,2)) nbplot() nbplot(size = 4) nbplot(p = 0.3) nbplot(p = 0.3, size = 4) nbplot(p = 0.4, size = 2) nbplot(p = 0.4, size = 4) par(mfrow = c(1,1)) mtext("Negative binomial distributions for the number of trials to observe n = 2 or n = 4 successes", line = 3) ##################### ## Goodness of fit ## ##################### p <- weighted.mean(as.numeric(names(HorseKicks)), HorseKicks) p.hat <- dpois(0:4, p) expected <- sum(HorseKicks) * p.hat chi2 <- sum((HorseKicks - expected)^2/expected) pchisq(chi2, df = 3, lower = FALSE) ## or: HK.fit <- goodfit(HorseKicks) summary(HK.fit) ## Are the dice fair? p.hyp <- 1/3 p.hat <- dbinom(0:12, prob = p.hyp, size = 12) expected <- sum(WeldonDice) * p.hat expected <- c(expected[1:10], sum(expected[11:13])) chi2 <- sum((WeldonDice - expected)^2/expected) G2 <- 2*sum(WeldonDice*log(WeldonDice/expected)) pchisq(chi2, df = 10, lower = FALSE) ## Are the data from a binomial distribution? p <- weighted.mean(as.numeric(names(WeldonDice))/12, WeldonDice) p.hat <- dbinom(0:12, prob = p, size = 12) expected <- sum(WeldonDice) * p.hat expected <- c(expected[1:10], sum(expected[11:13])) chi2 <- sum((WeldonDice - expected)^2/expected) G2 <- 2*sum(WeldonDice*log(WeldonDice/expected)) pchisq(chi2, df = 9, lower = FALSE) ## or: WD.fit1 <- goodfit(WeldonDice, type = "binomial", par = list(prob = 1/3, size = 12)) WD.fit1$fitted[11] <- sum(predict(WD.fit1, newcount = 10:12)) WD.fit2 <- goodfit(WeldonDice, type = "binomial", par = list(size = 12), method = "MinChisq") summary(WD.fit1) summary(WD.fit2) F.fit1 <- goodfit(Federalist) F.fit2 <- goodfit(Federalist, type = "nbinomial") summary(F.fit1) par(mfrow = c(2,2)) plot(F.fit1, scale = "raw", type = "standing") plot(F.fit1, type = "standing") plot(F.fit1) plot(F.fit1, type = "deviation") par(mfrow = c(1,1)) plot(F.fit2, type = "deviation") summary(F.fit2) data(Saxony) S.fit <- goodfit(Saxony, type = "binomial", par = list(size = 12)) summary(S.fit) plot(S.fit) ############### ## Ord plots ## ############### par(mfrow = c(2,2)) Ord_plot(HorseKicks, main = "Death by horse kicks") Ord_plot(Federalist, main = "Instances of 'may' in Federalist papers") Ord_plot(Butterfly, main = "Butterfly species collected in Malaya") Ord_plot(WomenQueue, main = "Women in queues of length 10") par(mfrow = c(1,1)) ############### ## Distplots ## ############### distplot(HorseKicks, type = "poisson") distplot(HorseKicks, type = "poisson", lambda = 0.61) distplot(Federalist, type = "poisson") distplot(Federalist, type = "nbinomial") distplot(Saxony, type = "binomial", size = 12) vcd/DESCRIPTION0000644000175300001440000000220011720430152012370 0ustar meyerusersPackage: vcd Version: 1.2-13 Date: 2012-02-19 Title: Visualizing Categorical Data Authors@R: c(person(given = "David", family = "Meyer", role = c("aut", "cre"), email = "David.Meyer@R-project.org"), person(given = "Achim", family = "Zeileis", role = c("aut")), person(given = "Kurt", family = "Hornik", role = c("aut")), person(given = "Michael", family = "Friendly", role = "ctb")) Author: David Meyer [aut, cre], Achim Zeileis [aut], Kurt Hornik [aut], Michael Friendly [ctb] Maintainer: David Meyer Description: Visualization techniques, data sets, summary and inference procedures aimed particularly at categorical data. Special emphasis is given to highly extensible grid graphics. The package was inspired by the book "Visualizing Categorical Data" by Michael Friendly. LazyLoad: yes LazyData: yes Depends: R (>= 2.4.0), MASS, grid, colorspace Suggests: KernSmooth, mvtnorm, kernlab, HSAUR, coin Imports: stats, utils, MASS, grDevices License: GPL-2 Packaged: 2012-02-20 11:25:08 UTC; meyer Repository: CRAN Date/Publication: 2012-02-20 11:37:14