From cbd15812f507f17b44e9d38b5a9cd7b1db25d993 Mon Sep 17 00:00:00 2001 From: Nicolau Manubens Date: Wed, 19 Apr 2017 18:41:22 +0200 Subject: [PATCH 01/61] Small docfixes. --- man/ColorBar.Rd | 2 +- man/Subset.Rd | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/man/ColorBar.Rd b/man/ColorBar.Rd index fb7cc7e5..c9923818 100644 --- a/man/ColorBar.Rd +++ b/man/ColorBar.Rd @@ -123,4 +123,4 @@ History:\cr 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens at bsc.es}) - New ColorBar\cr (V. Torralba, \email{veronica.torralba at bsc.es}) } -\keyword{dplot} +\keyword{hplot} diff --git a/man/Subset.Rd b/man/Subset.Rd index 2c883ffa..0d502cf3 100644 --- a/man/Subset.Rd +++ b/man/Subset.Rd @@ -46,4 +46,8 @@ PlotLayout(PlotEquiMap, c('lat', 'lon'), subset, sampleMap$lon, sampleMap$lat, titles = paste('Member', 1:3)) } -\keyword{dplot} +\author{ +History:\cr +0.0 - 2016-06 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Original code +} +\keyword{datagen} -- GitLab From 7ab6f5f5ab21f4fb00e924d339d7b4cc6b11713e Mon Sep 17 00:00:00 2001 From: ncortesi Date: Fri, 1 Feb 2019 16:37:54 +0100 Subject: [PATCH 02/61] Added PlotMatrix.R --- R/PlotMatrix.R | 115 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 R/PlotMatrix.R diff --git a/R/PlotMatrix.R b/R/PlotMatrix.R new file mode 100644 index 00000000..3fb79bae --- /dev/null +++ b/R/PlotMatrix.R @@ -0,0 +1,115 @@ +#'Function to convert any numerical table to a grid of coloured squares. +#' +#'@description This function converts a numerical data matrix in a coloured grid. Useful in a slide or article, to present tabular results as colors instead of numbers. +#' +#'@param table numerical matrix containing the values to be displayed in a colored image. +#'@param colors A vector with the color sequence to use in the grid. +#'@param brks A vector with the intervals to split the data into. There must be one \code{brks} more than the number of \code{colors}. +#'@param title The title of the grid. Default is NULL (no title). +#'@param title.color Color to use for the title (default is dark blue). +#'@param xtitle Title of the x-axis (default is NULL) +#'@param ytitle Title of the y-axis (default is NULL) +#'@param xlabels Vector of length ncol(\code{table}) with the labels of the x-axis (default is a sequence from 1 to the number of columns). +#'@param xvert If x-axis labels are too long, it is possible to place them vertically by setting \code{xvert} to TRUE (default is FALSE). +#'@param ylabels Vector of length nrow(\code{table}) with the labels of the y-axis (default is a sequence from 1 to the number of rows). +#'@param line Distance of the title of the x-axis from the x-axis (default is 3 lines). Adjust as necessary if your x-axis labels are long. +#'@param figure.width If the form of the grid cells is not perfectly squared, it is possible adjust it by multiplying the grid width for this factor (default is 1). +#'@param legend Set it to FALSE not to draw the grid color legend (default is TRUE). +#'@param legend.width If the width of the color legend is too small or too large, it can be adjusted by increasing or decreasing the legend width (default is 0.15) +#'@param file Set the path and the filename where the .png image of the grid will be saved (default is 'PlotMatrix.png' in the working directory). +#'@param ... Set additional parameters to pass to draw the color legend with function ColorBar() of package s2dverification. +#' +#'@return No data is returned. Only the grid image is saved in a .png file specified by the user. +#' +#'@examples +#'#Example with random data (by default it is saved in the working directory, but the user can specify a different one): +#' +#' PlotMatrix(table = matrix(rnorm(n = 120, mean = 0.3), 10, 12), +#' colors = c('white','#fef0d9','#fdd49e','#fdbb84','#fc8d59','#e34a33','#b30000', '#7f0000'), +#' brks = c(-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1), +#' title = "Mean Absolute Error", xtitle = "Forecast time (month)", ytitle = "Start date", +#' xlabels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")) +#' +#'@export + +PlotMatrix <- function(table, colors, brks, title = NULL, title.color = "royalblue4", xtitle = NULL, ytitle = NULL, xlabels = NULL, + xvert = FALSE, ylabels = NULL, line = 3, figure.width = 1, legend = TRUE, legend.width = 0.15, file = NULL, ...){ + + # Check variables: + if (!is.matrix(table)) + stop("Input values are not a matrix") + if (!is.numeric(table)) + stop("Input values are not always numbers") + if (is.null(colors) || length(colors) < 2) + stop("You have to specify a color palette of at least 2 colors") + if (is.null(brks) || length(brks) < 2) + stop("You have to specify 2 or more intervals") + n.colors <- length(colors) ## number of colours + n.brks <- length(brks) ## number of intervals + if (n.brks != n.colors + 1) + stop("There must be one break more than the number of colors") + n.cols <- ncol(table) ## number of columns of the image + n.rows <- nrow(table) ## number of rows of the image + if (n.cols < 2) + stop("Matrix must have at least two columns") + if (n.rows < 2) + stop("Matrix must have at least two rows") + if (!is.null(xlabels) && length(xlabels) != n.cols) + stop("The number of x labels must be equal to the number of columns of the data matrix") + if (!is.null(ylabels) && length(ylabels) != n.rows) + stop("The number of y labels must be equal to the number of rows of the data matrix") + if (!is.numeric(figure.width) || figure.width < 0) + stop("figure.width must be a positive number") + if (!is.numeric(legend.width) || legend.width < 0 || legend.width > 0.5) + stop("legend.width must be a number from 0 to 0.5") + + # Print output file: + if (is.null(file)) file.output <- paste0(getwd(), "/PlotMatrix.png") else file.output <- file + print(paste0("Saving grid image in: ", file.output)) + + # Generate image: + png(file = file.output, width = 55 * n.cols * figure.width, height = 50 * n.rows) + plot.new() + + # Draw empty plot: + par(mar = c(4, 4, 1, 0), fig = c(0.1, 1 - legend.width, 0.1, 0.9), new = TRUE) + plot(1, 1, type = "n", xaxt = "n", yaxt = "n", ylim = c(0.5, n.rows + 0.5), xlim = c(-0.5, n.cols - 1 + 0.5), ann = F, bty = "n") + + # Add axes titles: + label.size <- 1.2 * (max(n.cols, n.rows) / 10) ^ 0.5 + mtext(side = 1, text = xtitle, line = line, cex = label.size, font = 3) + mtext(side = 2, text = ytitle, line = 3, cex = label.size, font = 3) + + # Add plot title: + if (is.null(title.color)) title.color <- "royalblue4" + mtext(side = 3, text = title, cex = 1.75 * (n.rows / 10) ^ 0.7, col = title.color) + + # Add axis labels: + axis.size <- (max(n.cols, n.rows) / 10) ^ 0.3 + if (is.null(xlabels)) xlabels = 1:n.cols + if (is.null(ylabels)) ylabels = 1:n.rows + axis(1, at = seq(0, n.cols-1), las = ifelse(xvert, 2, 1), labels = xlabels, cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (n.rows / 10 - 1)) ## Add x-axis labels + axis(2, at = seq(1, n.rows), las = 1, labels = rev(ylabels), cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - n.cols / 10) ## Add y-axis labels + + # Create an array of colors instead of numbers (it starts all gray): + array.colors <- array("gray", c(n.rows, n.cols)) + for (int in n.colors:1) array.colors[table <= brks[int + 1]] <- colors[int] + + # fill with colors the cells in the figure: + for (p in 1:n.rows){ + for (l in 0:(n.cols - 1)){ + polygon(c(0.5 + l - 1, 0.5 + l - 1, 1.5 + l - 1, 1.5 + l - 1), + c(-0.5 + n.rows + 1 - p, 0.5 + n.rows + 1 - p, 0.5 + n.rows + 1 - p, -0.5 + n.rows + 1 - p), col = array.colors[p, 1 + l], border = "black") + } + } + + # Draw color legend: + if (legend){ + par(fig = c(1 - legend.width - 0.01, 1 - legend.width + legend.width * min(1, 10 / n.cols), 0.3, 0.8), new=TRUE) + legend.label.size <- (max(n.cols, n.rows) / 10) ^ 0.4 + ColorBar(brks, cols = colors, vert = TRUE, label_scale = legend.label.size, subsample = 1, ...) + } + + dev.off() +} + -- GitLab From c30009907c03f1217afac6a7e0a1c6c1b034e97b Mon Sep 17 00:00:00 2001 From: jpena Date: Wed, 13 Mar 2019 16:07:10 +0100 Subject: [PATCH 03/61] Addition of a vignette for scoring a forecast --- vignettes/NAO_BoxWhisker_Original.png | Bin 0 -> 48792 bytes vignettes/NAOpredictions.png | Bin 0 -> 33207 bytes vignettes/RMSSSplot.png | Bin 0 -> 82409 bytes vignettes/ScoringForecast.md | 244 ++++++++++++++++++++++++++ 4 files changed, 244 insertions(+) create mode 100644 vignettes/NAO_BoxWhisker_Original.png create mode 100644 vignettes/NAOpredictions.png create mode 100644 vignettes/RMSSSplot.png create mode 100644 vignettes/ScoringForecast.md diff --git a/vignettes/NAO_BoxWhisker_Original.png b/vignettes/NAO_BoxWhisker_Original.png new file mode 100644 index 0000000000000000000000000000000000000000..4006f603576f80664a8f3a14c3b9aab48d048096 GIT binary patch literal 48792 zcmdqJWmJ{x7d^TuDM3U!C8eZGLRwOgZs`z^mJ$I0X#}K81nCYbX#pjr1q5jjkd~IX zYoFiv-*La*Z+F~xj5FK^*qir#p0(zhbFTFe{zO$C4~GH=fk5CXD#&Ue5NLN12$VxC zRQQS#{TvtkgYB%K?}k9!GDH4{QYcaI41u_dP?VL@^2*ryWn*+_dJ=Qb1hF9(5fKqq zSjZyiA=h0OW^6<$S9Ley`L_Ke@llnzNmCdeE(_N2)2f{ub3+U%$=kPObCVI?Pj99V zO2m>$zr%KJ<+@O5 zW*m=FB^DjLvWz0+fS(8^ApiLPgC8kMprWRJfEsd>oIbxQEiKJ-`O6pSeIZX**QJY! zu&^-KH>AYGwPu|m@5NsVKL4qutE;P~Hq_VGH!|YV8G`3D-+F(t3>}Y3IF|NZd3pKx z32Q~3ax%`kSVIG zg0M39>|PZ0P@Hb-1A1g^@m+rY!_A2j-o}Z^3KK4qRu1>Q)BR<_r&m{(FKujoTMwoU zW=UMH4W^Hbj7(2Y>+9?9&b2hTEPuT?`)l~gmdCOuwx>rSRaTj;{KJQZ{$#ESleULm zdkgC$AInNhrDbHM@griDVqhDK!^rupiHL}_E*`#q{W`CyK{Z2I-N=ZexAw=6A5v0M zOX+VyLViw7Q9bn4J7)=>^*!A)TOZE$^Ye4SlvY@MgiS)HEo*7HlI4G;zyFU)+~?C_ zM{scPzmwg_Hs^0|sU00130qB+lbLPjpiyYE-oTJf+_#22O^jt zRlmyoO;gj$U!Py(waU1=AAXdN=@WZ#ak^h_+!XP7?|Y^wpUrn7k*P+v-yK1iLXNX3 zor_&xzrL67zxq*T7>Gx5-(WodaeC{ke@bNUTUuK3^O?ic(0`H{GDtuJ@ubn1zr@FIbBjRu-3p zL)djCY}`}WV=HB$JSj=X(UG&})#iAS#PvnZK*dZ(Mn)WiJWi_&KQFI{>q<`m3L1L) zU@G5lxGx6zw<=0X=5P1Bnnym$xA|W`RZ~-Yw+Ay-lc*clz(2gx8+rXM1n4_Y41| zaB*?DxVWwy?d&#d?I-)1hbJe6czEL4O3KP!{X2f1y%n+F&(#+E<_$R+*g z%}q|~R<;xsJyTbYW6b*b{rg*g?aT8c47G_O%~1d1mnS>$P&zs~dHzcq>+7dyXNj$D z9v*e+>4vEij1VwyTt5go&0#&Iq@-jgONp&}KGW)Rq*U3`*4AcetZZRH*Th6EtmE3++66;)b~Yro zv~G*{-$#{(Jv}|POI_hhwEWfsWSW|qSB@GQqkn%7*5 z?R#ebym7TNMn$=a<%F0T;`DG;uCv3%k04NtpGErfYHLd#iv2mS)ej{g_ z&yk&y5|01m#6;qTu*-`V#11;2mu!uUG8T5!BrX|ymmQuz$MEdF75y$SBqXH1-qYQk zKe<0TJe*wAqjW*PVz60BJ*3{&=%Q^Y7esmWz70=MnP+3{|Y9IC$ z`zV^}-aXtMCE=!4NH23o4VRb4Tl%fO-pgO3C&tG)?%%(>xG<=5=#}`lJtK6bd-@s; z6W!jkv8jnx)MKEpFQRji-(kvmEdQ~2KIhJ_rsTHgj*eHqv;6IBZMmB$C@9i}oa(Bo z7KH$(3l?et4g$HBrKP3wRWtkMCw}}mK04A~>6dz#jm|D0puNvSpn>ruP)=cDadY!$ znW2z%Q$vFnAc7c;+B;l;rlE`no%7E}axnZ!#6vr8Z*@Ujo8MqmRDHbdZ`Y+zf0fAs z8z610Q(Ro!c5x875EmSbZY|?%ms?!C*_X)vW;D(F?^>e19KD2ui8En4Ky$E?TTxLF z9*tN^8znLE(f+dh6=!JY{?XCI$jBn?qHYDE((%{lN6{4F|6*Mk4)^sH53q_*fdb`j zE;tMOU!4_1DD_@Xnwgp9+;GHw@amkuZH^d`edfM2Pl$6Qr+DfrUzoZ;)gEC#k|VeA zNs>kNVF%Bn!E_rYy{CP)P27n4*%Pk5@bJKIO}oFP}c~Upa1UMW|cb zyd&EEuGEH|$!ityeE(V{W$rHN|m4mMonop z*5VaFfEw4;zJLJ4+8+rX9+#udiKUr)%*;50+3?J7QjVb_tn|i1%vyWAdD>#!;v*m- zktIP?qyjM=*o}n%1|;Jf>q>u!qpfA2Y5kR1OG=AyzRjOhL_<%H#XYuvHOVnw0nj?I zX}~=gu*G9@TygJinU+GB*LaYeg0_XFC1Z-#^SNeyUpD8ZF6<6%M@G8Sq~Wh$A62%| zJ$P^yYJY@&;|7i@<@ngxor?pVTqyEbNr^Gh(f4cgRa8_qf*w736xaj_c6G{-XL3b*h*K zH=dk6!*=l7_07$``;VmAFoBI11!`$)!vb+C_CtNfB_U7FSlBz8_xm?EJRIAW{{HW>htm?Zi~?Dr)Qd}+J<;HZ=z3zBB6Ps zF?N4{|2GC!>%ZmysM|$E8l+g@8%AGWU!rS#PJVv(nY!nJ@~1^^z}PTIjn09emgrWT zHUX^*>^u;rdh1|wpFo3rgbX+)^UIh2)IUDDtn^eW?AUF)-dS8!x9$i016IB78AB^^ z^^Mk_o8cSW06vWvi{87ttgJ=yF*Nx2_-L5;mXE@|b$4e<__w-u9|NUP)Duxw6%!ZN zEi>p=D~2~-EUtL{z?=5s( zT+{+l4kTWLWo6eZbbz}0@liCSoQ+3hLtTYQ+cmr(6 zilpvtu20;qMrbg>8G*sp8Suiq8Q=56q5&a+i|+UEThWs#&bg~_Mx-}I?26ocYo-AHL$#o)Hhzeqj}129=;h~Hn*@~I(vD?U`wCS z&dv_GXF?CW4|0PiX@s36Sr7(Wsai6J5wWpsB~M#?mPiM%adH3cEu#6?!}>o?7bKnl z_I;D~q0wGX_?>&`okaJv4bB3<(-#Ixr zN)_Xob0`3-cYfCPfBP1i<#T>|ij{=ICm^s|;WgFl?bdOG3A-jHCgvynSgH=H<`Ag3 z^T$;Y5q+=~%#YI;*M7oBVq#!mCvM!!^~t%$!z$_#*l5AQ!2v`Klb38^ ztL-yj|42qNRP*m}LsL&r?_}o}#>^+jU+1u0p#H?5MnfJ0aqB5XSlHS9{2+xUFaJ#{ z=tklWr@1kJm*Z^1Z7M3zW{dEgP~j=b$)|t*1S#h-{6Pv5iJIFK(N?u^E{OP9?{qyR zaSh+02UQABz{DgcBhxuM+YGrV6N>-B&20?GmyqA(dF}Ac4q|p4tkz!RR^Kyt95+|j zlwYJ=PfLxPe$31ma?(;FK9rX~t+9T5=T1B@OA!$fe29thTwqdz;xCU?-iw{>Ep~!T z2#<^|TTp!Jg3=Nh4cf7qydXFv2lwhJ^Jn7hrXnx5d3nu9P&$nQU#-|n;uQ2gn8%P!R zIW!d|kq#4v7(!YbJ!CJq?)>is=s=_m!iywW@G2}yJx~s5e$ZR|-#`2RfgiDRz!vWNxv|s$fyhTGL=Cuc4Xl-r1_4N^~sY0MnW!Pw{n71o%;Wux(A(uek z`yH;UD=YV}uiJvot&?GZPh*r8*OP5zWMVRIaF){6KKfZ}|2T~wW%%=pKVTFX>gyXf zx-!wxy%wp0Pi2wV?4a*s;^nPwXqW;D+gnZ+O(9TSSGTtB1@4U%k05NXtTgQAYEDrR z_FZ;%<#k~b) z6=%#h+?zKu#9!8>DD(31VcsMoAR+m>wYk3T4&D&ZXCQMia79INz{SF%*WhfXrIk=o zQ4xXDf0^9f-R-tEFkSbY@>)R&dEp=cf}*0LKn}IHOCs3V*gzFQ;d#-xTN9u_<#KTL+X1@m>O3$o#9-g$3uoYme8$QqUv&SC8S@=UQGO;Bz3Rpq!MKl?^%p z{$SG5W@UIzByvg67~* zT4;TdA!A}9aqnJ%QI>QaQpmbzZ)|M*$1cPe7(VJ&JXMKpyS{27^87wDbPEfsvZ~6= zF$aR+MXbtuOw)lB9*uceC{_uH`QBc|bxL^?6Qob*5c;S%?!fQ5k6@xh;}O(*b#--w z$cxQ!07ozs%M9yLg>(vw#^lI&h5ds3W5VrbydfeaQ-@QZXkg00V-8nD? zkq%l<4>(AnwY4vxHg`9(1JRDx92$fKgm^+JHEDZVNvWu&whOcnG810SLsZfFUqHUx zT@?R4l;ywpOtjw_TZ(_O87ba{ImfXVCgC&T^s}Jm?i3|s;fH*+^(YoNWC`@ zO$bpJPfs9MqZ1QWqLR`pQHh_*KeIaB5O-TsSu?SL!YM`*BhlUl6&#{0Z-&eGbHX!j z`yU)v9V;uA9lF69K-`N@=K}~hlkIJ7u|9y%gJ9+Qg+DH#IZ6O-c$1ftrTq>hF*QuJO|D?vMi(e#z*_ z$g`QcZ4l4F6o0*%0|Qalq%bfr1nkBM{+3t{rU{%~n(-cPP1k^ULqKKas0p&`iKPRg zhvE!|-Wrz_q5Y52v*T?_f6uFnv#P49Q8_YNT8S5%T8M`aAFfhg$zd(JHiGIz+_*{B zE>T!sJ_l?a453kpWUL~eDV0ikdU_~_hX4-X9q`I~iOs>w)Ynr{AX2j)zWUkI6P8D& z55MgQ77_vG(g5afXJHT%0Qs2C7pE>D>FMa`9zLXztg#+MH~Ia{-X2!gWFY8x=a;DW z!3sDDI64^`QGlL&ln~HdH7M6!jeZ28!opZP<%adDo9M_ufM^#K6a<4Ieg{8T%LY^j z6nZ00AwcClOkwSt%oCXQnKIx%18D*YvYbqeAfTe+NHIn+eLBT1CL*~1`__R;Jc{#+ z7gmC(sHo5*Xz6^_J(&)MhHo(ui z=jm~AW=>9A#edRbi-R-Kk$kncyt$?2Z2kk}6sQbVgs108k!ArtIqwQ!lFI51$b>4w zf+aBat!-@3$R4=ne*P?SEgahE;^t;ihr!;AW_p7UCDymj*jwP)XfQ)6NPR`e9uvDK z1N|nt2GN?Nc^Fddtb;d`{Hjev>> zP~U_U1!$n_zyN`2g0$hNMG_wL`1cHC_;mnN z3yj$nuc?55fLpW=5vSna5FI~}F0Mq9k`$hxZ5Avu6j5ws_W-@s3T4kr%sQ3y<;#~H z>iPr8B@46v*rFr?#D#=B_m{fO4QM3%GO|qfZSZ-y^q8suc9XeG4hjw~V+Tk@m)ZuQ zopiqjCFYyO)yNSjqBFtQ-sFQE!ey1Agiy16V3k3Xn6&!#5|NsUc^?F)>NE47^02aE zC)%BQ$YJ4?6D~um2y#s&ZM582^!f8`pfk{ZfGQY4A^2U_$f((2n%5)rD<5?{L8hsd zr6sr1jnwSRh<$K&p#D&{1F%1fLeirMQ=6M4f6K@zDAH0>d#N5cFCc0l3iiwySg8fbeidDXG_meU;E(LI9ASb(h$U7ml>~`y-4vJ;4f>@O>gH ziym+M%+?n8tP>Q4(B!Uf-{h4;u5YnDjU>6B5*>PrHfcJ*r1||>b3})`Nl|fe5)DEg zZYBX&6gw$7nKS@$?g(H{Ps|b@LGxGF))HrwuqZ*n6EIApa@omK58Ir23VS7wf4G*7#eYkhrXxK zFGwlIW7jRWd^$)a;$8@vSLI&x+qbHTv<$ufJXb{#43DA+#@=O_{%ZFA3qJpVM>3~z z%KNr~0TrMIU0t&3$$-geS*ee+9=0sSDHlK)Q)!3d1BI1TBpp_Of&xbp;?X%1uko|j zK0P0QB`D$j-$KD6i{HZeV|0X#YNKp#Z>xgg#wt$m!bwvzdp72Qe@( z&~>ZA5kxqo777t5DdvqEyqFKD-d0p_@dfQ3{h0)N1VCOQo^#L2+8Rh>tci+!SJ>@$ zC%BK~<&_)in69rRKACo)S_^iSQ2`ty(N*LJjq-;B&%Io{D-#tIOk?$^w zU_QDB^qwuSwiXM_ATaeQZ{OZuA7S83{s#pU%73cAj-g=_SlM8#0A$;b<>MJju?>Ja zO~n%us;A|2++JHFxqTaD0Rj{Xkvaa4a^rtc!`{Aq3uX|c#QwoS8jr;z=xsr-AsLqH z&Ye5N#N7$p7{kyKGchq~d_@ud$#%pX{9CAzSEu_HpjG|J z0xUko|1IR(#h#-IG0!6)#|uS3@qxC4D~^DtSMWGJDL$SdNKM-eOw*hs4aW)c=dY>$ z&n!T(HhjW{GBE9Kr+9FIuC8D?2IQ~I7%zB^&~Ds}J?I3Dr~YuM&3`qbw);KyJj8P< zMK+MtcUrfc#tU!PC^1}l7K$Qk;r4XRJwQ*W>;T>Mm6gNrkmKW^WgH>kbxZa3fgr;s z**|-R($m{J-R#Zh|I4adQ(b);nyv5+U?I;O9f1irg6MH_Y6HRyrYN)=-pILbj51jV z&D{b}io?d=oySnrgD5(It(lsdii)}kxO0B=#}h1Zu<5n)Np9Di_Z4fGOyRHiBO9Uc zbz~y+jUsWT_;vTL$&at5C=2^u_f#{cs;zKq__GOMQ@{rI@$%~79$eb@(q?{EB5Y0M zYh~0Ci(CTN(iZxG-d=Kk+gRu>r%n?GfJOKXj0pehs|ODr5c}$AX^jJ>Q3}}Qf|pV6 zXpD&&3Myo2$($$IePc8aw&Wsk8G;gv?wv&eX5_c!XfmEa)_~lc9A1YhZc$NDcv1_C zWsn0YDJcN{(0E4xSku7$D=37Gi>ozxYy*%WaEM4+$qqF95xuz7`z%xcOh~e}j~4X>JC}miVK@nF1+*L}3okFP3-Gyt%OQ|O-sEEl@{?qlkp!Sx4Rq(Z znR0&fOK6r7shLGk0@`o=tW~yET!#0eV`B2HegN5`yYF)N-_rYTMRh=6fH2Ns++9n_ zSpolELu?gP0@Bf%uQcl%wMiFz{@G!=8rpgA9NVByfC+1edLo38jZFvHZ;)HI580V{y%=Bcw(D;pb9_(2kqwVfT#*456?TPPQYV`{Kg_wVBc zfTS+G0YeDT?Y5DY{sMt}4~)J~<<5<;2FQs9a|(W^IiqQuXb*@RFo&VuvCq7YE#8We zxGFsLKRZ4?27wZBhRL$=jSZ>jSEDGLF!yZJ@IyaPZ)@$&Xo+$REwfavY*&7rV; z_N>gPk+2<}5payX8_ZDE3>IrCdLRxEbP=;AG^J%_CeUI5BcTqBPCFIqE4UkMUUvZf zQ_*Fx=x{n!13@WsgXD%71yv0VncBmqFSE0=KuRBH2;XiGyUmbWG6Gg18e%9*g7mMC zIZ_S1Ylju}IoeDlQlkqF|3+|&i1_@E zzlY*eZ^E-c161_IrX_UB92_n-#tI0({Qmvh6J9`iQ&OgX_;45Ury~jIM3euupPt?nkQ-Qf zpd#;q_UKGae1j%CalLgp<%WFt`sRT5WX-;z^3^i32ZR2|5XSkQBgy!AmChp z8E^~X8riFwlyhOK2Wx_4_sHkRO$Tk z_%(vz$esTb>IFu(c8-^B&4eq1l5)C-o1L; zksPq2bACeSxe^xZ0Q(8K_Ns31P5jVhsF^D(37MIf02aBqjQL*Ao`K#5#{OQ^)6v$} z*2_zH>{s4`E%6525;U3~dLJ+vVv`_{b1!^+>NcspX8?j`);?@=?XS^n2Gf}Ghp(e4 zg}{Il@!a9CzKBgt)d!xjdgm?}iPG>29)mr<0}xb3TH5-125T#$Wv#~19gc^Pvx+!L zU>HCT8!nc+j2=7{O3%vdd7xI;IZV^%zlK>86_u#;^mImQ<6ISHW@hL_gYJPbC@i{a zt!S7=2qXLq2?7$iyIJRM?oumMDQG?M;6bIewzXxk4uFsnByMI}Mb2OZKZdSB>^zHz zGy;SrNHy632VzBM;S6NU3kFqm)UlNm6ixw!K~{1WOTjFbon0|lu=)A)PS)w$YbsNygaLC&r)M!?-ok|ZB|u%3(~Nr-5?dr%vB*tQ68RskbDwUm2oL4 zENdKmHerMu|Fh*|iwD}<7rG-!%_$t_TVH*RB9{rdX=ZoM@)Y18=i^7{D#!{z(eAIZ z_y%oYHBk>TNCWNYHP$6b1IO3I;B zKKWGKF%Sez(By!;wHA$4;-IHr0xItyFNIY^;N-LmY{Yue_zT!MoAzJ=09S+tlLMwk zxVI1Ts-~7(6@>T$Df#W|R|7r0NyKtgSr)XNJx74t}T`4B@TPIxB{)fN?WAIto_)D+o>ClMn}R zt*)-3z!Go^Ag|~1tt}rvT7dKbEvpw5Pav%~4*D3Xj_w{aWb9nCca6%@?JtYYY!4GO z<>c}}OYnxv;|x%Vuc@te-AuK*Vob!q#Rl$})Yf(l!*`vXo&BXHNm*I6|6SKW=YTo7 z2~)wO2{c}LEWWO9Y_L8w{Xzo3b^G>6{$on@KW=w4sNJ`wc=-4<$EO1W1Hn7h)}9E# zql~cYTyzG+zMr-Jp}6>bbAp`*4@`U^+u^&SqD{b9dRaqoTwPqMDl22>P1L(V@)+yt zdO{-}@}^HJ8~X89+UIDI0M@Lsxxj_DY zkuLTDH?Q3TYiYd95GmIkj4lX1fVCtM?~mrZ`HK(Bjjnc-jIa9U=e$sY)i| zZVQIU_SV+G;GkS|1JG3%@dH%ygT@^c$mOLaz=>+$&oJc10nQ~eht@0IF#`~v7BLOGd-82}ZP0oX{OneOiHaO+^W{(+BR zyL-yE1zHJ4Q$UK^K<)r9w*ao$?7E6G^BR78I@BEm_bZm*>@f5a02NSK`fx*V>oASw zbGS~|9ZLa5J2)#lGxfXh%h+{F!TH|=b}N=s_7IxU-eON395`lPYncz+{Q}$@s0@%K zBj`N<#oN97cLML==H@Ou{RKl_$@dLOC@DqZ1|sI83BGVbFBE8ldZN0t0`bQ%qy_d3 zBy!yeKNxrW`*GXi*mMy{jRDC8#i5!StEko0&Fy4sIzBeG9Ux-gs~NtP^kDZr%Y7y` zekCl{3ZUs=vvOms^c?~nfq_<-mJ0Xga3CQa$S@G4OSlLEd$T{1J%Rf zn+6OG)*&MXc3HDP)k>6vo)tNz(d7ZX85o(N6+~J~DK$`M!RyMQ2uaj}<}EmgAhf6O zWpg==KN~f9lmT^gz@*pk@DL2h$e^l2yS=geE#^W((F)oBOiW2m)-^Mu0MNJDLhP$T7ADP4Lm@dy7FS$y_R!*(sm7sqnwe&SsRk-h(n14!-&1q|NFEp{u*Q zr6{^I5tN*q=9GwPEnS_Pe0((^5+k2EgWB!t>H?S+dGLUhqqxrsKpG|qiJQY=s1w@# zmV_}x5Wv$u{B$?12?9rTv@J21^kl)3^G1q!2q(DvcWG%92$IPs48%5Yv({b&G2i}O zU5X<1BZtR06zC1KLC$JtZB2+-+u2jf7kAgFZ4r?<8otV1lMr2|3cqb}2u zZ+A#a&)tL*T{r2eckw}VGR}LZy^bzbO3vIRC~*f*o&@IUm_>xwe6Fgi)6vzn5yjCc z<9V@HMBzvLb$K5U>;zg*@L86lqr*)?-?Of>f?mJokdx_Clfq5{S6jWCg;^DfojX32 zFs%9Wx{m~`(8U85{`Bcnb4akNXYUSzCv9U9MwgM!wLKy=? z5o+7gk^SKxOurF!HMLK6FC4#T_({eunP-T+N#)azj!}37HyRf=(iMIu^d|Yz!onV` zJF=Ys39LIXrpR;zm<0?_B~wJZH}o@m4HQ=x-GCwh*?aIMVS`X}Fzez8gcAVU)Z3h{ z&QNDpX*;{#oj?q|dVI0DPxVe?$J=ND?UG8BY?yEGT`ROpek^rI5}(Ox6m0_%0RX}9 zlBFm?oR`>BXcNw;hw(wyL!ATQP2QHoqLUz@h0MEf!wOIRjWHx^9D zfKdXCOUUGK7Lkt8@p0&A6$R2N^}&4oAq)X?8P-K@OR`k~F@VAdo|DI2*{4vO05FcX zruowPRaWdSeWGY%pj>eCcOCs<5f2OT4_+hG!QmM1pb&Qc08NExXB%U%kZsp*m{GK{dC&zS|?yY*KkIKos25+hKt8dfbGx?psD(}fW2egQQ zc~RL1XQ!uNE`EiEI4q=@l;6Wg(dWB~S+xS3CLx9T;)CfQt(2Sn@DK&6W+U_%7>c$w@clzg<_Cyrp(Iah#skHaA~_4mC6m zjf|Dw4jW3Z%1eyH3=E7vjsWL`9uhK0axUb)!?dYB7IQa z;ri>BCrTdvm&8I&(&N>JAhb`8kD+HHbbWvE?{BZak8ZmV7QsY@f;Munva+%gz&LVS zGOSt8z`*0rkHNvg=xs^a>QA3wT6hMmtC`nfU8Un)%lkyfUH(^6-`;xd=U95q3Zr94 zDJxt4Lw4SVzDC2@jNT5-f)#4!B7#+=N*eHNp~VLv12?Vo`fS4J%wI~^dcZS;zU@Kr zd+30{;8*50i!5-l&(Jf4GBAZ7tgt!4;Qr^>Bpb>(nBt6CYaRZ|UQ5AS77V<(>quoL zBrH5NF>%xr$B;Kf1M{^IfFP2mryp=|sB~1_wgP!$X=8Kpr=sn@qJ@Kl1Km4r({@BY z?(0|_5w{!o_}7Vqzgn7d6AD+1j5{uVoE_hP+VbvI@aV|c7}|#lB!DW(x?t7_9z7Pk=qqi2DGt>Ox`^LD@rqSnl+= zo2UnK^}Lff&_;yLBwT$)dr4X(n77PN_pVu)M7&)aokk09`<)kA8hVF(Mv^Vyg`ZI0 z--Y4;9_Afp6=X{Uh;J8v4K%G=tH|JZh?~2+)*5YVq5(Jn5D1EwG8+9u@&&4t_tdVY zvV-_$sfb5dmKB{tg<8GgsiE+UR$ z;$(}*&3$FKL8_<)^cX}P6b^Gy0_l~!LacaZGZ5Iue0;%g5{;F#q&Yd6oUrFxI>!ol z!(w}a=m|@KJpgOqn*n~`2y6}p^ioc0tj{bwTuqAoGYHVZjb zT4GZONT2NN9d)1VGJUf!myArgL$CDc(bp6n3svpO2TqNRWDlwS9Vc!X7%q39eR9yx zeko{+@SBK?zsK&*PA?ImPzjZ!J?d5_6fa-{j8x}*FpdGag~GzYA?CgwYsA1P8l_@XD)cT zVvf@OD`nC$${yR>w@H|*pS)~rXh?9#5W`MmD$M}02JMPFl3+ir4P}{><6fUG-@1SQ zK7#*aEX&iUG^&|_@plFWd0q;llZNZ6zitsf-jUNFG^j-lSTgtWNs2PoW&?hP?5INa z^e6)xO=QhCWM{(luTsg{sPLyrOOgJFW;LX14D}evM6d?&9Qe3etzq- za+G(TcivsFe zpf;qIE@(C*D1d-}rnoOIYET0cwcrt<-_rvlUs_x-v=$4JzLy5oO{TAn{El2-+*hnr zecu&=XDU>626O2!?gZ0{a)}hDu*pRwC8QuVO7%4(>_K1BZFAWGev9~BG??p{;bLP? z*V-o+*1&Q@Q@?zG78G3x%z7!j@^*DSfFS^Alld=AYOzYVx&1|+)_T>*dwPg1B_-@j zHuN5Dp1b{n6dB(Q@s~LR*+C$4MB&`p&M$+<>2F`1;Jgheb&JL{Dt?z2&y?g(b&&GL^h|^eFedIbrL%W-+&GgXr zCN2K+=Pp8KNcbcV#m~0aB_ds3RW3Egb#n3!Q6>5VbH@&$l5Ej3p$n_p8e2*-X!36_ zgeZ*HR8;o*xf(q1AUyO{D;1tWnnQdZfR}-sI9Xe>3)dg4P5>tnlrjp`zu27-7;Atc zbf1I6GJlHy*=Sd1r_5)=aNQD}`||Sg>Na_QTK;7p9=angQ8xT)zN0-wC6T=U46Om( z@{;nAmAY22VZHMTmTK0cjV0~6Ix=wz2KgMF2iF=Ro?lmbO+|Qg%f5V&vYk{FMA7yB ze|lI7a%Cnla*;}FhZCjYd^W>n>AqR(n+ESpGezFqH&hB~QT`27lJ->QYabUI8%{eU zck5r=sRR?q8ZiACk5>C0-Nya_g%&xrlbHAdkka+VU21Wk1lHv_h^Gj2ZkSPmVK}Xc zh`kvUiD;@>Z^?w3Z)y<{-DSl# zGlTOAeg7a?_x`-pl~q7qVdKe@MVj)Tla2cn;htmZWI%x?rl&VKFMa`wUBF@L$-5G0 zB_weg<4DTMS;1HwF?M@TPa%{8V)AlXwu)P{&P(X{RFYZ=d#o}t!lD+3wo^07;$6i? z?(PeJaOLIqyu6NY8rDhvh;Pk{%gV}n_s-nf`YXs)m`?l9{5Mi@^~-p&Mw!BHLbr4su6f!9{=Va^1v??Sz3}qVBJi3 z*wOd>`wde>!&PMw7ON!xFimVZqsk3}Jts2l5U6F)AOsHW0L@S^D`8Al_~mgaSRtp% zpxQCrczNY zETZJ!9jUe=6DIiaqq@0`2)sammLq7vLD{OL!il?;Kc4!TP_1%RxwO)On|ZVInih1zp%r=F#G4R!7ha; z#M>&9j3wTu!7|+#IRJ+Mw;g(D(5-d`Sq@e$wDOU{5RTM5?)RaMPfPm@y)Xg$AC^{D zD3zZ+CG6pee3B_XXf{iifZl_#Y*Smg(-gN$B!RtYMPTG z-@?(9|D-z_lb$wonkL|;D1{scV81suH+PmRh%{?`ucEFlJGh>#t^@}J&<;e!HFgAL z7lk*A`Cdk(3yn0@OJ}KeA$4haxgWSv;F$-iq#}m#kp5L(T@e4f;LbBwpBjGv+c{9cSuwAjXv6f1D5ePCXOrkH?RCZRP0$A! znLHjG6awd2%Un;JV|z80pv`zXe>Fn3Ko!7c!tv_W#Ov)PF0j=aE(kd^Tws(7t!1*NZ$+^ z8F1zNyhXup3k{*#KGF0@Ejswnv9U2qIBuLG=rnhio8an-<<~9k3Yw5xp*1x<+J91+ zc#lwuBFA&lb^`?4udkkn`;(wJE!_BU`QxqxZ*S(xKl9vSu6=`paFFU=034@F zuqWg%`Uz7iXqfa&d6u3XsHMj2LD?CjF8>w8tgk!2v_jSNSvWgT!Cl^g5$BDKM$g@+ z&_Lm}3AVGh2Y1*XoNwdL?r}cSm_-yY+4XxMRdcOqTnim@xhIY{N$&%JvL)pZyhfMb|A~m>240 zI-QUT#eYLp{5dHGyVbF~G)@?Qfy8gW^Avk($W`S4dHf5KuaX)=^}QHt0kje5LT`2U zm#qAb3Auq!8&Wc^xoasak9m1c$ASe#jI~39go9Df7lyw3#9n5w#2j$8m)?A|(8Veo zYKj#wUsc4#nNIh5`-5eS{?|Ti(-MzMjP~>-5gng5Z{FAur_SZ`qbrARZqNynwfIy~ z-$Arb)G~J9;K@01u0OBiEyTI*j%V9CvOoQ|+;iLaio>^93hgF2s+t9(Lx zZU;Bod3@Dxu>{XFAB8kv<{6PN42uSXa@#E-ivv^OG^3ygdZfJfuW&p zw26J#KwhrtmY&gPM&FDgd=WdM&+cZ=6^ep4m;OE)puQ!6Amv^loBibywf!MMmHE&$ zTbnXMFQG+ANl~#1S^*%HNJuoL0g(p#`poUpSPGz4?p$wXiXZy%6Yhvuh%v2EZ}8mhsO&9G5#-oeZ!a95vjVGl045o~e8~YxZ}tAM+P8|f zrSF;Vet}7FB^DLk?{W=-15WKTGitfVwnIl9lr-1*MTI0wz*qsUYL+0HYp|-Jo}R3n zoch~5Zng;TfyK^HV3QmP#wftK@?cb#;O}M%LBO}pwZZj~<+iP2v(7H@mwRV?s##xS z=@MC+P}@6)+L&s8%=KV*TivxfOJ{x5OegqTnFtb%yXbUSwH?l)6SyUV+7|@Ln>Gwl)&= zUrljOD8>s`QRu$mm%T9HNDHAxsDA0jLy@_AX#>Xc zThlMW?=*5YH$j0pIz~iG8VIyg2NFm`VG>~JDpgM9g`r1okdO!vboKRZ!fino;DiOU zq!+T>qY0h?=b3KE*#US zl%wpBQR&BEAdW2pGeCiDF=77J_u-5)a&+85<~2T*t+h2A3$Y&JWMwKYiCkDvI=<8U z-`0}98Z))UinF2)Yi7+!4(MM+g&8HbzojnTzb#^m=^4?fMJ|$!Uu;K&g()4^lp1M0 z*$UlH>p|PYJ|ZI&j zID{w^=iRxds*=iUHO;&0{g>NbN72K|E~3ekeO`?bbJo(XgGlm{<3<&=YHfalh+dA4 zV?J?aN%n>BKvs;z^>*=sGxsYIK}XrdilI>|CsK<+-cs~R()iDGWDT5?_h6v$9~hnY z4L+@RA4kws4EN!oym^B5gfxpQ$A8dYbdQ1|Uvy{o(Je&lUUjDh$+8x*GX;K})+QsI zCzv*`V7NZ5vAvJl15D@PLQx1gWj6uvMm$#h9s6RyvNH29iNQ4$=!tsmrx6~sAwq$ z=P77u#eIZ%X>LubQyTH&TECVTIy#EFiHX`@Y5kk|xqDik>PV>i`8`B%CckVM7<>0@ zG&dZWz<6?h1_e&4YMON6D_I6prn|4c$>hbNT(&k`+{Qx`W^)siZ||uT4nD~cd}PNK zRg(>A!K@wUvPft)I&Xrg+f4k0LXVQ4qAJj}YJRdKC8w0R$WaG_5i3mW?2*0Y4k(fop2r+W z-s3pF{ykgfSIO5xQ_>7e!qS=bxTv4ZpHf69iIPn*Ffo%Gr~ZMINQp+yGBsX+lyJq4 z?3use?g{rZZsn1_yv-_HA4q>CHGxu&N~7tQ)*~9`a@=5ou1!;M)|aT)lD3_)vT(ik z4aJLhhEuqaLb;3IF?=#}Z;ws{Whw?+bU&S5nsH((^w!>CSKF$x$@EW}1?SH-lYCl=4>jsVE+Ir4u4TV_vkl}3LM-J797l!5lTwj>r1ZZL~nOG zEU7JPD3f?AJC|LiT4`$#r>CatPo}E1ixeNCF04fp4|wPXQ-9SXCW>t9!fl1xa&w20 zTaA*K?Y(LknGxsgY`d1}`0&Eo@20}yI%`pu)Wrayn;q#qn38vmSUb$+CW@0DC&1rD zp;|z#OzbV^k8LBax!_5wW^X;yLzP8i;Rr6UQCwXwUgZ4jy+Ck_3K4z#PL!Dn3itjj zLHoF)LTCr8aKE^cM)Y86Q0Oh?I%8ueG^eSkNBBm!dmMtZ|J)n55lY!qye+N=hkbCo zaMalr7s&)mnTKPhpNE~sJ8uNEO+_nB+tOj~p*o^wkaAV}i6?O;_6HFeJ>S7IxcSKT zAwMEz;SbYc$(sb)rx=pBjgDBR)+ztKL@J#UU=zaucSc5qxvM3)Olr|h?wOB|tZvf2 z_gsE-2`vF_%LjHaj+V#9_yfgXK+2szjYwvdKSb)GJtF}RR9@BzM(-TNzhfv{L_~$W zO{&5#$!I>A2VvD~YaNr4zC<}~yY5`*AP^;~nuQ6FudA-liBFGtFluisI#Aq1v86lV zxFOIj+RK#{B@RnZdt5P6&1AcRIOBndkgzbU@N^-RFW0~P{0?mk;8-#WhfzaiV7CF# z6X_6Oi>tJi+3?JM%x@5u@qbjzK%M*@{T0 z)%r=QKXbBL7yk*nj7|BU$IP=AiO1Q}xV5shzW<%EOFEO+!AzDI79Z#0FgtbiOO%MH{Rc_ClT2EC+7gsa zXuOs9?wh}W*_es7RpcBg^jKcJ9e9)T;CqXtAwq-YVR%u?zFJ}h+aT7hrn{W@#t1L- zADkS^bf(4S$OA^TG1`a=6ksqgMWlI)fbN#SlNe#bZw!rZ*l=2lW7BQXeo9OuwW7=)To ztc;)&AaC^?j`VJz^#8w@dhd9u`~QFZ*rRM2A$#wUm5`B<8JT6zNQfe2WUnM-Mo2=X zv?L-k$!G|vgvcmLA(G$yT<_oKcKe<`uG@9%>f)T&d5*{9{NXA>@&ORe^W`?Y)$#V6Vs;{N4@jRTp}X*PKP~%Kd5WS zHeT!UY9RSV?! zM=nrkM2qj9*wiCeaAz1qXr`}h)H)^--iF-t)? z2?h^_FKzAZ71mR%PC$~v!@}?fu5ED?m~s3~&8kT_y}FvXXHPNJ{5&;7_wdc9HcXap z-_-Nd=jGHiMsX$4Gi6jIer$CUexNuNko-F-S1I-QDV>PGe@4f;C)j^IBt7ESXmL+Z zn=OY#>6vY`-E*3|&mVvNn%r@CpT3k~;^8%F!8UNrP6Y)SnVNat|IZSb@&YpT@_J!gv6_8B+DRd*P1?{vWM=%s)f+Sft#hp(ue|Tj4T<{mic!@$`7FUYE1Z7D!EowDK_k!c z3+^-K$>D3qQpL>sem>jj^@R3)7hjH#>N6XOHU%@|auxP?gRmy*_xJtIe14XI(F)Mq z@Q4U+Pft*G@z(vu$)FyFj}if74Axz_%}*`R&wxFgu!9}nI<2%<&C#WyaqQMZEQH?+ z?BIGk4*CuJExVQZp-Dbef^hU{COwbC#ms62PEOTxkpgA3+Pf)4IHI$orA1B!=}_KE zurSnj_e(#XloiZSvETScZ>MfF|Em0y)1#^M-yTy;EvtqKUFWIfCD?ck{^HulQF*Se_ z=QF=kA+&zCvcHcv@dfP}qz6;LW#2Fpc3&piMZh#9hxJ6h7;`G$7W?p4LTIP(nY`Q} zfgPs`m78^x<({9KApBd?0t{NrZ9l;$R~Vw_d1th~q5Y=w5!K=t7SjCg^G5YC7w?$} zbe?Zi%_kfqp0=^Rraxjs^gQgIePVJX46n?-`tc(&fc?Oc_`s`{Fz^!m?{(MJ;)rol z7i;n3RM$RT{ps)R&rYb?)S6zkrnqtA?-SGgz9&(5$o~WrN3x_XVM1*+>RG61PIIhTY7*7y#fkLy52H(R zlnh*~?!>wiP918e4?OU#M$00!TaZIWQv9eUwaRdNfxiY}WWs86y-<>p5G~TC9<@7q zOJ6KgJyFEY+H=I^TW9&Mk+u(AIQWy~9ce~A$S#FRv1M|D7?BVjuAp_bg(Kj)n#v36 z9Sq%1!i(>;Xi7=xs07pLDNAO79ld$fJqZE?>B>KD!O}Y# ze(3WLCQkn)X{C?({Zsh+Coq|WbZ-dy#0jrHrmh>Iu_`@=FNHfcsq4wG5DyyHW zR&pzc)7hk5PHc_5s8u9r**OZhaQA1^iObOE<+&Um@%5XU)L-A2AseJrr#aq#&wzR} z{s%$H_2jx^TyC865mxb3d6w?dt7OLNnJNcp=aTi>A|`mt7zokPg)TH?ru7|HTJIL$ z(k8TiGx$Yc-`93*jBq&rU}og!FS&HTsN{I5C_f(*j1=D0m&AY>BEpm?oO(Bx@+TVG9T9ku^-;dbuolT zkK;N8crq(1xPDa!s}UX^^0b{Lai5TRo;)wamPR*X#LuoxTPW3ScKBlCHocXVkSJM9 zom5;L-@TjS?LpTlK9Y*Xr!!R9hHD(Typ{I7w$+|To&256`C%b3=@?(P)s4OXwl0TA zg%V8bs}*u$Ubni&i03#{`;&IXj3-=Dm%ZWn{JWZY-{bg;&o0Eg%)3+HT47L}6cE6n zc{Hry(A6-JOvNc&qv!v9FwK=^$*7xfCa4i!W-U_rS=yZyHa;A&I-NtZvL-t_=QbgE zRVC$Upw3CSkA;%Q5t_4;N@Je4-tTqd|M!aIkdD=?%~Ji$$c;pr?ecvwqpI8tQJ&Nd znv{~#FNMWZR$RV0^p!|%R?JRvb5JxoI>#I2^y zH^(8-turJ)a$47)WcuR)Z@Qyv?y-!spRx+n@;L1s+Y34Z*1Qb&#J*s6rEMi!Rcb5m zZJ1P0-L^P(r;0ZqJ7ea|-3hDGe(aDpBp9<(WM+y<=>;qN`$HAA$xK@vP_0X210DuO zOK8M%AlQHp1PGa60|B-2^z;l3{f!A0WX=VJL`Atxl#JzFhQXQ-oab~t3q441XIjak zc%b&cJnoY95!-j{=L7ngn8`Gp$ljTb5GMF$%=9L-|C&>;9CTqeKKqc4gCHyGw!{6~ z=Qbg`w)`v@09IZ~InQk5f7-k?f%C#MiU0~JOWm3ejzQ10O>c$`^6BXjVxDT5)|1zo z3E80mg|-@UljErD^t&O6p@_-Jd4s7orfY8+yv_M3?If$N4VSM>P>eb7edSk`%zK*^ zMEcsK#`Z+d4YrlTd+)Q!%(|T8ElK0w%hJu;UZ#1DI;4w>V>)$;up{P{jE)YUtn46- zq)`pBk<|)`BK94MsFsFL(dHcnyN@oa}7>jqDQ- zWX|hwg*Ca+#kA))a|G<&5S}MnrfO6*Xoy28IYc`<&4d(=gkbr9mbQ(Gc#Vtk4rfJWZ%FD4|KMd?<*(WMDs4R+lw^0#Wu4>e>%upcr4{^ z|D&g@(TY<~@BES>4=wpEc+Zs4DLZ`IXV@RU2Bd{Gl#78mMm5YsKa@AJ=&$#466&d& zKUAyMNIM2LR(4OQOD$zY$N#v`=$*0K^{Ykyqw(f=)~8vGabLcE1>jYNIs!QfcJ;l zjvZ-4E?9_D&>h|#`8-P!J-<5YeyHlI3*fwY9$)p3q_}3IdV3_E?kdO1PM%c06KU>i zgGcuK`I{lZWn96uO0Q0+w6IQpPD?wmzK`Oh!_-^GqiL-c1OwN1><e*jnimKo^VIUCdR9;sH&n*A_`

VhBY531lDmZb#u!>ZDTUY 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 literal 0 HcmV?d00001 diff --git a/vignettes/NAOpredictions.png b/vignettes/NAOpredictions.png new file mode 100644 index 0000000000000000000000000000000000000000..b76c2be37f6ed3c1eefcce0b5d2b9c4396cdb473 GIT binary patch literal 33207 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

cww3(*RI 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 z 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 Y(sTfa{|&9fQpDdW9#kP`%Nt$(Uq_+VjsO4v literal 0 HcmV?d00001 diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md new file mode 100644 index 00000000..febd5994 --- /dev/null +++ b/vignettes/ScoringForecast.md @@ -0,0 +1,244 @@ +--- +title: "Untitled" +output: github_document +--- + + +This vignette illustrates several examples of how to score a seasonal forecast using different functions in s2dverification. + + +### 1- Load dependencies + +This example requires the following system libraries: + +- libssl-dev +- libnecdf-dev +- cdo + + +The **s2dverification R package** should be loaded by running the following lines in R, onces it is integrated into CRAN mirror. + +```r +library(s2dverification) +library(devtools) +``` + + + +### 2- Define the problem and loading the data with the corresponding parameters + +In this vignette we will quantify how skilled a seasonal forecast is. The model will be the EUROSIP multi-model seasonal forecasting system and our real truth will be observations represented by the ERAinterim reanalysis dataset. + +For more information about both datasets see the next documentation: +- [**ERAinterim**](https://www.ecmwf.int/en/forecasts/datasets/archive-datasets/reanalysis-datasets/era-interim). +- [**EUROSIP system**](https://www.ecmwf.int/en/forecasts/documentation-and-support/long-range/seasonal-forecast-documentation/eurosip-user-guide/multi-model). + +Both datasets can be downloaded from the corresponding server. However in this example we will use the BSC esarchive database. Files path parameters for the Load() function are defined as follows: + +```r +path_exp_EUROSIP <- list(name = 'system4_m1', + path = file.path('/esarchive/exp/EUROSIP/ecmwf', + '$EXP_NAME$/monthly_mean', + '$VAR_NAME$_f6h/$VAR_NAME$_$START_DATE$.nc')) + +path_obs_eraI <- list(name = 'erainterim', + path = file.path('/esarchive/recon/ecmwf', + '$OBS_NAME$/monthly_mean', + '$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')) +``` + +Our case of study will be predicting the North Atlantic Oscillation index (**NAO**(https://en.wikipedia.org/wiki/North_Atlantic_oscillation)), usually defined as the difference in the sea level pressure anomaly between the permanent High pressure system over the Azores Island and the Low pressure system over Iceland. Changes in the NAO index have a direct impact on European season weather since it controls the intensity and pathways of the storms in the continent; Positive NAO values are related with stronger storms and thus wet winters in Central and Northern Europe and its Atlantic facade. Negative NAO values correspond to reduced storm activity and rainfall in Northern Europe but increased in the South and Mediterranean Sea. Especially during the months of November to April, the NAO is responsible for much of the variability of weather in the North Atlantic region, affecting wind speed and wind direction changes, changes in temperature and moisture distribution and the intensity, number and track of storms. + +For this vignette we will use the whole North Atlantic as geographical domain and we will select all forecasts starting in November for the 1980 - 2010 time period. The EUROSIP system provides 7-months long window forecast inluding 51 different members. + +```r +#North Atlantic domain definition +lonNA <- c(-90, 40) +latNA <- c(20, 80) + +#Selected time periods: +startDates <- paste(1990:2000, '1101', sep = '') + +Loading sea level pressure maps for the whole North Atlantic and for the specific period +data <- Load(var = 'psl', + exp = list(path_exp_EUROSIP), + obs = list(path_obs_eraI), + sdates = startDates, + output = 'lonlat', + lonmin = lonNA[1], lonmax = lonNA[2], + latmin = latNA[1], latmax = latNA[2]) + + +#Retrieving observational and forecast data +obs <- data$obs +exp <- data$mod + +``` + + +### 3- NAO index, Forecast vs Observations + +As a first step we will compare the predicted intensity of the NAO index for observations and for the forecast system. + +In s2dverification the NAO index is computed using a common alternative definition; The NAO is defined as the first mode of variability for the sea level pressure in the North Atlantic region [20N-80N, 80W-40E]. The NAO() function requires as input anomalies that are previously computed using Ano_CrossValid() function. + +```r +#Computing anomalies along sdates dimension +ano <- Ano_CrossValid(exp, obs) + +#Computing NAO index as the first mode of slp variability in the North Atlantic +nao <- NAO(ano$ano_exp, ano$ano_obs, data$lon, data$lat) + +#For clarification, we normalize the NAO index for each member dividing by the corresponding standard deviation +nao_exp_sd <- apply(nao$NAO_exp, MARGIN = 1, sd) +nao_obs_sd <- sd(nao$NAO_obs) +nao_exp_n <- nao$NAO_exp / nao_exp_sd +nao_obs_n <- nao$NAO_obs / nao_obs_sd + + +# Finally plot the NAO index using Box plots for all decembers. +PlotBoxWhisker(nao_exp_n, nao_obs_n, toptitle = "NAO index, DJF", ytitle = "NAO index (PC1) psl", + monini = 12, yearini = 1980, freq = 1, expname = "EUROSIP", obsname = "EraInterim", + fileout = "NAO_BoxWhisker_Original.png") + +``` + + + +The figure above does not represent a good agreement between observations (blue line) and forecast (whisker boxes) due to the large dispersion through the 51 model members. The NAO signal is too noisy within the model ensemble thus almost disappearing (close to 0). + + +###4 Quantifying the skillfulness of the prediction. The RMSSS + +Let's quantify how good or bad it is this prediction looking also for a better understanding of what is happening. To do so, we will use the Root Mean Square Error (RMSE), that it is just the squared and then rooted difference between the predicted and the true value. + +s2dverification includes the RMS() function to directly calculate the RMSE, however, in order to get a better understanding of the output values we will use the RMSSS() function (Root Mean Square Error Skill Score). The RMSSS equals the RMSE but it is normalized by a reference RMSE, usually asociated with the intrinsic variability of the system (for example the standard deviation of the climatology). In s2dverification the score is computed such the best RMSSS score would be 1 (RMSE equals 0), while if RMSSS equals 0, the RMSE equals the variability reference of the system (i.e. the standard deviation). RMSSS can also be negative, meaning RMSE is greater than the variability reference. + +```r +#Calculating a RMSSS for the ensemble of members average from the mean NAO timeseries of all members +rmsss_m = RMSSS(var_exp = array(apply(nao_exp_n, MARGIN = 2, FUN = mean), dim = c(1,11)), + var_obs = nao_obs_n, pval = F) + +#Computing the RMSSS for each member +rmsss =RMSSS(var_exp = nao_exp_n, var_obs = nao_obs_n, pval = F) + +#Plotting..... +layout(matrix(c(1, 2), 1 , 2, byrow = TRUE)) + +#Plotting RMSSS for all members +plot(rmsss, type = 'h', lwd = 5, col = 'grey', xlab = 'Members', mgp = c(3,1,0), + main = sprintf('RMSSS for each member (RMSSS average %1.3f )', rmsss_m), + ylim = c(-1,1)) +grid(col ='grey') +lines(rep(0, Lmember), lwd = 1, col = 'black') + +#Plotting boxplot for good members +igood = which(rmsss > 0.2) +rmsss_m_goods = RMSSS(var_exp = array(apply(nao_exp_n[igood,], MARGIN = 2, FUN = mean), dim = c(1,11)), + var_obs = nao_obs_n, pval = F) + +PlotBoxWhisker(nao_exp_n[igood,], nao_obs_n, + toptitle = sprintf("NAO index, good members only (RMSSS=%1.2f)", rmsss_m_goods), + ytitle = "NAO index (PC1) psl", + monini = 12, yearini = 1980, freq = 1, + expname = "EUROSIP", obsname = "EraInterim", + fileout = NULL) +``` + + + + +The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. The general RMSSS for the whole ensemble is 0.015, what means a not very useful ensemble prediction. + +However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 45 and 47 are used. Now most marked NAO events are correctly predicted giving a RMSSS of 0.66 for this 2-member ensemble. + + +###4 Quantifying the skillfulness of the prediction. The Brier Score + +Another option to quantify the goodness of this prediction is using the BrierScore() function. The BS measures the accuracy of a probabilistic categorical prediction. BS scores perfect prediction when BS equals 0 and worst score corresponds to 1 value. + +Moreover, the BS can be descomposed in 3 terms: reliability, resolution (negative contribution) and uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). + +In the case of the NAO index, we can define a NAO event always that the index is greater than 0. Therefore, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored 2-member ensemble of previous section. + + +```r + +#Defining NAO events +Lmember <- length(exp[1, , 1, 1, 1, 1]) +Lsdates <- length(startDates) + +#For observations +nao_event_obs <- rep(0, Lsdates) +nao_event_obs[which(nao_obs_n > 0)] <- 1 + +#For all members +nao_event_exp <- array(0, dim = c(Lmember, Lsdates)) +nao_event_exp[which(nao_exp_n > 0)] = 1 +nao_event_exp_prob <- apply(nao_event_exp, MARGIN = 2, mean) + +BS <- BrierScore(nao_event_obs, nao_event_exp_prob) + +BSscore <- BS$bs +BSrel <- BS$rel +BSres <- BS$res +BSunc <- BS$unc + +#For good members nly +nao_event_exp_good <- array(0, dim = c(length(igood), Lsdates)) +nao_event_exp_good[which(nao_exp_n[igood,] > 0)] = 1 +nao_event_exp_good_prob <- apply(nao_event_exp_good, MARGIN = 2, mean) + +BS_good <- BrierScore(nao_event_obs, nao_event_exp_good_prob) + +BSscore_good <- BS_good$bs +BSrel_good <- BS_good$rel +BSres_good <- BS_good$res +BSunc_good <- BS_good$unc + + +#Plotting NAO events and prediction probabilities +layout(matrix(c(1, 2), 1, 2, byrow = TRUE)) + +#For all ensemble members +plot(BS$obs - 0.5, type='p', lwd = 5, col = 'red', + xlab = 'NAO events', yaxt = 'n', ylab = 'NAO probabilities', mgp = c(3,1,0)) +grid(col = 'grey') +lines(BS$obs - 0.5, type = 'h', lwd = 5, col = 'red', yaxt = 'n') +lines(BS$pred - 0.5, type = 'h', lwd = 4, col = 'blue', yaxt = 'n') +lines(BS$pred - 0.5, type = 'p', lwd = 3, col = 'blue', yaxt = 'n') +axis(2, at = seq(-0.5, 0.5, 0.25), labels = seq(0, 1, 0.25), mgp = c(3,1,0)) +lines(rep(0, Lmember), lwd=2, col = 'black') +title('Predictions for all ensemble members') + +#For good ensemble members only +plot(BS_good$obs - 0.5, type = 'p', lwd = 5, col = 'red', + xlab = 'NAO events', yaxt = 'n', ylab = 'NAO probabilities', mgp = c(3,1,0)) +grid(col = 'grey') +lines(BS_good$obs - 0.5, type = 'h', lwd = 5, col = 'red', yaxt = 'n') +lines(BS_good$pred - 0.5, type = 'h', lwd = 4, col = 'blue', yaxt = 'n') +lines(BS_good$pred - 0.5, type = 'p', lwd = 3, col = 'blue', yaxt = 'n') +axis(2, at = seq(-0.5, 0.5, 0.25), labels = seq(0, 1, 0.25), mgp = c(3, 1, 0)) +lines(rep(0, Lmember), lwd = 2, col = 'black') +title('Predictions for good ensemble members') + +``` + + + +Following the analysis of the RMSSS, we compute the BS for the whole ensemble and for the ensemble with the best members. + +For the whole ensemble, the results are: +Total BS = 0.239 +Reliability = 0.021 +Resolution = 0.012 +Uncertainty = 0.248 + +For the ensemble of best members, the results are: +Total BS = 0.091 +Reliability = 0.0 +Resolution = 0.157 +Uncertainty = 0.248 + +As expected, the ensemble of best members presents a clearly better Brier Score (lower value). While the uncertainty is obviously the same for the two cases, since the observations to compare with are the same, the reliability and resolution scores are better for the second case. Specially the resolution scores much better in the 2-member ensemble due to the agreement of all the members in correctly detecting positive and negative NAO events. + -- GitLab From 02c2938fcb1f2376605d5ca3774cb45248256e1d Mon Sep 17 00:00:00 2001 From: jpena Date: Wed, 13 Mar 2019 16:34:58 +0100 Subject: [PATCH 04/61] Minor edit in the vignette --- vignettes/ScoringForecast.md | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index febd5994..e3284753 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -7,7 +7,7 @@ output: github_document This vignette illustrates several examples of how to score a seasonal forecast using different functions in s2dverification. -### 1- Load dependencies +### 1-Load dependencies This example requires the following system libraries: @@ -25,7 +25,7 @@ library(devtools) -### 2- Define the problem and loading the data with the corresponding parameters +### 2-Define the problem and loading the data with the corresponding parameters In this vignette we will quantify how skilled a seasonal forecast is. The model will be the EUROSIP multi-model seasonal forecasting system and our real truth will be observations represented by the ERAinterim reanalysis dataset. @@ -47,7 +47,7 @@ path_obs_eraI <- list(name = 'erainterim', '$VAR_NAME$_f6h/$VAR_NAME$_$YEAR$$MONTH$.nc')) ``` -Our case of study will be predicting the North Atlantic Oscillation index (**NAO**(https://en.wikipedia.org/wiki/North_Atlantic_oscillation)), usually defined as the difference in the sea level pressure anomaly between the permanent High pressure system over the Azores Island and the Low pressure system over Iceland. Changes in the NAO index have a direct impact on European season weather since it controls the intensity and pathways of the storms in the continent; Positive NAO values are related with stronger storms and thus wet winters in Central and Northern Europe and its Atlantic facade. Negative NAO values correspond to reduced storm activity and rainfall in Northern Europe but increased in the South and Mediterranean Sea. Especially during the months of November to April, the NAO is responsible for much of the variability of weather in the North Atlantic region, affecting wind speed and wind direction changes, changes in temperature and moisture distribution and the intensity, number and track of storms. +Our case of study will be predicting the North Atlantic Oscillation index ([**NAO**](https://en.wikipedia.org/wiki/North_Atlantic_oscillation)), usually defined as the difference in the sea level pressure anomaly between the permanent High pressure system over the Azores Island and the Low pressure system over Iceland. Changes in the NAO index have a direct impact on European season weather since it controls the intensity and pathways of the storms in the continent; Positive NAO values are related with stronger storms and thus wet winters in Central and Northern Europe and its Atlantic facade. Negative NAO values correspond to reduced storm activity and rainfall in Northern Europe but increased in the South and Mediterranean Sea. Especially during the months of November to April, the NAO is responsible for much of the variability of weather in the North Atlantic region, affecting wind speed and wind direction changes, changes in temperature and moisture distribution and the intensity, number and track of storms. For this vignette we will use the whole North Atlantic as geographical domain and we will select all forecasts starting in November for the 1980 - 2010 time period. The EUROSIP system provides 7-months long window forecast inluding 51 different members. @@ -76,7 +76,7 @@ exp <- data$mod ``` -### 3- NAO index, Forecast vs Observations +### 3-NAO index, Forecast vs Observations As a first step we will compare the predicted intensity of the NAO index for observations and for the forecast system. @@ -108,7 +108,7 @@ PlotBoxWhisker(nao_exp_n, nao_obs_n, toptitle = "NAO index, DJF", ytitle = "NAO The figure above does not represent a good agreement between observations (blue line) and forecast (whisker boxes) due to the large dispersion through the 51 model members. The NAO signal is too noisy within the model ensemble thus almost disappearing (close to 0). -###4 Quantifying the skillfulness of the prediction. The RMSSS +### 4-Quantifying the skillfulness of the prediction. The RMSSS Let's quantify how good or bad it is this prediction looking also for a better understanding of what is happening. To do so, we will use the Root Mean Square Error (RMSE), that it is just the squared and then rooted difference between the predicted and the true value. @@ -153,7 +153,7 @@ The above figure shows very different RMSSS for different members (left plot). M However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 45 and 47 are used. Now most marked NAO events are correctly predicted giving a RMSSS of 0.66 for this 2-member ensemble. -###4 Quantifying the skillfulness of the prediction. The Brier Score +### 5-Quantifying the skillfulness of the prediction. The Brier Score Another option to quantify the goodness of this prediction is using the BrierScore() function. The BS measures the accuracy of a probabilistic categorical prediction. BS scores perfect prediction when BS equals 0 and worst score corresponds to 1 value. @@ -229,16 +229,16 @@ title('Predictions for good ensemble members') Following the analysis of the RMSSS, we compute the BS for the whole ensemble and for the ensemble with the best members. For the whole ensemble, the results are: -Total BS = 0.239 -Reliability = 0.021 -Resolution = 0.012 -Uncertainty = 0.248 +Total BS = 0.239, +Reliability = 0.021, +Resolution = 0.012, +Uncertainty = 0.248. For the ensemble of best members, the results are: -Total BS = 0.091 -Reliability = 0.0 -Resolution = 0.157 -Uncertainty = 0.248 +Total BS = 0.091, +Reliability = 0.0, +Resolution = 0.157, +Uncertainty = 0.248. As expected, the ensemble of best members presents a clearly better Brier Score (lower value). While the uncertainty is obviously the same for the two cases, since the observations to compare with are the same, the reliability and resolution scores are better for the second case. Specially the resolution scores much better in the 2-member ensemble due to the agreement of all the members in correctly detecting positive and negative NAO events. -- GitLab From fa8d60f8975eb38290888b67c4122a1d012565ab Mon Sep 17 00:00:00 2001 From: jpena Date: Wed, 13 Mar 2019 16:53:51 +0100 Subject: [PATCH 05/61] Minor edits 2 --- vignettes/ScoringForecast.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index e3284753..53e1d5a7 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -57,7 +57,7 @@ lonNA <- c(-90, 40) latNA <- c(20, 80) #Selected time periods: -startDates <- paste(1990:2000, '1101', sep = '') +startDates <- paste(1980:1990, '1101', sep = '') Loading sea level pressure maps for the whole North Atlantic and for the specific period data <- Load(var = 'psl', -- GitLab From 0a9a167c53bfcf0fc47245d8dda07a1974fb8b18 Mon Sep 17 00:00:00 2001 From: jpena Date: Wed, 13 Mar 2019 17:29:00 +0100 Subject: [PATCH 06/61] Minor edits 3 --- vignettes/ScoringForecast.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 53e1d5a7..d8fae202 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -80,7 +80,7 @@ exp <- data$mod As a first step we will compare the predicted intensity of the NAO index for observations and for the forecast system. -In s2dverification the NAO index is computed using a common alternative definition; The NAO is defined as the first mode of variability for the sea level pressure in the North Atlantic region [20N-80N, 80W-40E]. The NAO() function requires as input anomalies that are previously computed using Ano_CrossValid() function. +In s2dverification the NAO index is computed using a common alternative definition; The NAO is defined as the first mode of variability for the sea level pressure in the North Atlantic region [20N-80N, 80W-40E]. The `NAO()` function requires as input anomalies that are previously computed using `Ano_CrossValid()` function. ```r #Computing anomalies along sdates dimension @@ -112,7 +112,7 @@ The figure above does not represent a good agreement between observations (blue Let's quantify how good or bad it is this prediction looking also for a better understanding of what is happening. To do so, we will use the Root Mean Square Error (RMSE), that it is just the squared and then rooted difference between the predicted and the true value. -s2dverification includes the RMS() function to directly calculate the RMSE, however, in order to get a better understanding of the output values we will use the RMSSS() function (Root Mean Square Error Skill Score). The RMSSS equals the RMSE but it is normalized by a reference RMSE, usually asociated with the intrinsic variability of the system (for example the standard deviation of the climatology). In s2dverification the score is computed such the best RMSSS score would be 1 (RMSE equals 0), while if RMSSS equals 0, the RMSE equals the variability reference of the system (i.e. the standard deviation). RMSSS can also be negative, meaning RMSE is greater than the variability reference. +s2dverification includes the `RMS()` function to directly calculate the RMSE, however, in order to get a better understanding of the output values we will use the `RMSSS()` function (Root Mean Square Error Skill Score). The RMSSS equals the RMSE but it is normalized by a reference RMSE, usually asociated with the intrinsic variability of the system (for example the standard deviation of the climatology). In s2dverification the score is computed such the best RMSSS score would be 1 (RMSE equals 0), while if RMSSS equals 0, the RMSE equals the variability reference of the system (i.e. the standard deviation). RMSSS can also be negative, meaning RMSE is greater than the variability reference. ```r #Calculating a RMSSS for the ensemble of members average from the mean NAO timeseries of all members @@ -155,7 +155,7 @@ However, we can select the members that present a better RMSSS, i.e. those close ### 5-Quantifying the skillfulness of the prediction. The Brier Score -Another option to quantify the goodness of this prediction is using the BrierScore() function. The BS measures the accuracy of a probabilistic categorical prediction. BS scores perfect prediction when BS equals 0 and worst score corresponds to 1 value. +Another option to quantify the goodness of this prediction is using the `BrierScore()` function. The BS measures the accuracy of a probabilistic categorical prediction. BS scores perfect prediction when BS equals 0 and worst score corresponds to 1 value. Moreover, the BS can be descomposed in 3 terms: reliability, resolution (negative contribution) and uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). -- GitLab From 4e50ac719ddd7c5b5720ea924616cf98dfcb742e Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 16:08:07 +0100 Subject: [PATCH 07/61] Format edits in figures --- vignettes/NAOindex_81to91.png | Bin 0 -> 50688 bytes vignettes/NAOpredictions.png | Bin 33207 -> 38181 bytes vignettes/RMSSSforNAOprediction.png | Bin 0 -> 84060 bytes vignettes/ScoringForecast.md | 104 ++++++++++++++++------------ 4 files changed, 58 insertions(+), 46 deletions(-) create mode 100644 vignettes/NAOindex_81to91.png create mode 100644 vignettes/RMSSSforNAOprediction.png diff --git a/vignettes/NAOindex_81to91.png b/vignettes/NAOindex_81to91.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee1220690eab76395e8d4dcde3f11a1c4d76553 GIT binary patch literal 50688 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 literal 33207 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

9t;FVXd@y5gC`lrA#HkAX)5kkp~ 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 IWcl0w0d@Q7qyPW_ literal 0 HcmV?d00001 diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index d8fae202..6ace894e 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -49,7 +49,7 @@ path_obs_eraI <- list(name = 'erainterim', Our case of study will be predicting the North Atlantic Oscillation index ([**NAO**](https://en.wikipedia.org/wiki/North_Atlantic_oscillation)), usually defined as the difference in the sea level pressure anomaly between the permanent High pressure system over the Azores Island and the Low pressure system over Iceland. Changes in the NAO index have a direct impact on European season weather since it controls the intensity and pathways of the storms in the continent; Positive NAO values are related with stronger storms and thus wet winters in Central and Northern Europe and its Atlantic facade. Negative NAO values correspond to reduced storm activity and rainfall in Northern Europe but increased in the South and Mediterranean Sea. Especially during the months of November to April, the NAO is responsible for much of the variability of weather in the North Atlantic region, affecting wind speed and wind direction changes, changes in temperature and moisture distribution and the intensity, number and track of storms. -For this vignette we will use the whole North Atlantic as geographical domain and we will select all forecasts starting in November for the 1980 - 2010 time period. The EUROSIP system provides 7-months long window forecast inluding 51 different members. +For this vignette we will use the whole North Atlantic as geographical domain and we will select all forecasts starting in November for the 1981 - 1991 time period. The EUROSIP system provides 7-months long window forecast inluding 51 different members. ```r #North Atlantic domain definition @@ -57,7 +57,7 @@ lonNA <- c(-90, 40) latNA <- c(20, 80) #Selected time periods: -startDates <- paste(1980:1990, '1101', sep = '') +startDates <- paste(1981:1991, '1101', sep = '') Loading sea level pressure maps for the whole North Atlantic and for the specific period data <- Load(var = 'psl', @@ -90,20 +90,20 @@ ano <- Ano_CrossValid(exp, obs) nao <- NAO(ano$ano_exp, ano$ano_obs, data$lon, data$lat) #For clarification, we normalize the NAO index for each member dividing by the corresponding standard deviation -nao_exp_sd <- apply(nao$NAO_exp, MARGIN = 1, sd) +nao_exp_sd <- apply(nao$NAO_exp, MARGIN = 1, sd, na.rm = T) nao_obs_sd <- sd(nao$NAO_obs) nao_exp_n <- nao$NAO_exp / nao_exp_sd nao_obs_n <- nao$NAO_obs / nao_obs_sd # Finally plot the NAO index using Box plots for all decembers. -PlotBoxWhisker(nao_exp_n, nao_obs_n, toptitle = "NAO index, DJF", ytitle = "NAO index (PC1) psl", - monini = 12, yearini = 1980, freq = 1, expname = "EUROSIP", obsname = "EraInterim", - fileout = "NAO_BoxWhisker_Original.png") - +PlotBoxWhisker(nao_exp_n, nao_obs_n, toptitle = "NAO index, DJF", + monini = 12, yearini = 1981, freq = 1, + drawleg = F, fileout = NULL) +legend(x = 3.8, y = 2.6, c('EUROSIP', 'EraInterim'), col = c(2, 4), pch = 15) ``` - + The figure above does not represent a good agreement between observations (blue line) and forecast (whisker boxes) due to the large dispersion through the 51 model members. The NAO signal is too noisy within the model ensemble thus almost disappearing (close to 0). @@ -112,9 +112,12 @@ The figure above does not represent a good agreement between observations (blue Let's quantify how good or bad it is this prediction looking also for a better understanding of what is happening. To do so, we will use the Root Mean Square Error (RMSE), that it is just the squared and then rooted difference between the predicted and the true value. -s2dverification includes the `RMS()` function to directly calculate the RMSE, however, in order to get a better understanding of the output values we will use the `RMSSS()` function (Root Mean Square Error Skill Score). The RMSSS equals the RMSE but it is normalized by a reference RMSE, usually asociated with the intrinsic variability of the system (for example the standard deviation of the climatology). In s2dverification the score is computed such the best RMSSS score would be 1 (RMSE equals 0), while if RMSSS equals 0, the RMSE equals the variability reference of the system (i.e. the standard deviation). RMSSS can also be negative, meaning RMSE is greater than the variability reference. +s2dverification includes the `RMS()` function to directly calculate the RMSE, however, in order to get a better understanding of the output values we will use the `RMSSS()` function (Root Mean Square Error Skill Score). The RMSSS equals the RMSE but it is normalized by a reference RMSE, usually asociated with the intrinsic variability of the system (for example the standard deviation of the climatology). In s2dverification the score is computed such that the best RMSSS score would be 1 (RMSE equals 0), while if RMSSS equals 0, the RMSE equals the variability reference of the system (i.e. the standard deviation). RMSSS can also be negative, meaning RMSE is greater than the variability reference. ```r +#Defining NAO events +Lmember <- length(exp[1, , 1, 1, 1, 1]) + #Calculating a RMSSS for the ensemble of members average from the mean NAO timeseries of all members rmsss_m = RMSSS(var_exp = array(apply(nao_exp_n, MARGIN = 2, FUN = mean), dim = c(1,11)), var_obs = nao_obs_n, pval = F) @@ -128,29 +131,29 @@ layout(matrix(c(1, 2), 1 , 2, byrow = TRUE)) #Plotting RMSSS for all members plot(rmsss, type = 'h', lwd = 5, col = 'grey', xlab = 'Members', mgp = c(3,1,0), main = sprintf('RMSSS for each member (RMSSS average %1.3f )', rmsss_m), - ylim = c(-1,1)) + ylim = c(-1,1), cex.lab=2, cex.axis=2, cex.main = 1.9) grid(col ='grey') lines(rep(0, Lmember), lwd = 1, col = 'black') #Plotting boxplot for good members -igood = which(rmsss > 0.2) +igood = which(rmsss > 0.1) rmsss_m_goods = RMSSS(var_exp = array(apply(nao_exp_n[igood,], MARGIN = 2, FUN = mean), dim = c(1,11)), var_obs = nao_obs_n, pval = F) PlotBoxWhisker(nao_exp_n[igood,], nao_obs_n, - toptitle = sprintf("NAO index, good members only (RMSSS=%1.2f)", rmsss_m_goods), - ytitle = "NAO index (PC1) psl", - monini = 12, yearini = 1980, freq = 1, - expname = "EUROSIP", obsname = "EraInterim", - fileout = NULL) + toptitle = sprintf('NAO index, selected-members (RMSSS=%1.2f)', rmsss_m_goods), + monini = 12, yearini = 1981, freq = 1, + drawleg = F, fileout = NULL) +legend(x = 4.95, y = 2.4, c('EUROSIP', 'EraInterim'), + col = c(2, 4), pch = 15, cex = 0.9, lty = 0) ``` - + The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. The general RMSSS for the whole ensemble is 0.015, what means a not very useful ensemble prediction. -However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 45 and 47 are used. Now most marked NAO events are correctly predicted giving a RMSSS of 0.66 for this 2-member ensemble. +However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 8, 23, 40 and 45 are used. Now most marked NAO events are correctly predicted giving a RMSSS of 0.66 for this selected-members ensemble. ### 5-Quantifying the skillfulness of the prediction. The Brier Score @@ -159,13 +162,12 @@ Another option to quantify the goodness of this prediction is using the `BrierSc Moreover, the BS can be descomposed in 3 terms: reliability, resolution (negative contribution) and uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). -In the case of the NAO index, we can define a NAO event always that the index is greater than 0. Therefore, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored 2-member ensemble of previous section. +In the case of the NAO index, we can define a NAO event always that the index is greater than 0. Therefore, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored selected-members ensemble of previous section. ```r -#Defining NAO events -Lmember <- length(exp[1, , 1, 1, 1, 1]) +#Defining number of sdates Lsdates <- length(startDates) #For observations @@ -184,17 +186,17 @@ BSrel <- BS$rel BSres <- BS$res BSunc <- BS$unc -#For good members nly -nao_event_exp_good <- array(0, dim = c(length(igood), Lsdates)) -nao_event_exp_good[which(nao_exp_n[igood,] > 0)] = 1 -nao_event_exp_good_prob <- apply(nao_event_exp_good, MARGIN = 2, mean) +#For selected members only +nao_event_exp_sel <- array(0, dim = c(length(isel), Lsdates)) +nao_event_exp_sel[which(nao_exp_n[isel, ] > 0)] = 1 +nao_event_exp_sel_prob <- apply(nao_event_exp_sel, MARGIN = 2, mean) -BS_good <- BrierScore(nao_event_obs, nao_event_exp_good_prob) +BS_sel <- BrierScore(nao_event_obs, nao_event_exp_sel_prob) -BSscore_good <- BS_good$bs -BSrel_good <- BS_good$rel -BSres_good <- BS_good$res -BSunc_good <- BS_good$unc +BSscore_sel <- BS_sel$bs +BSrel_sel <- BS_sel$rel +BSres_sel <- BS_sel$res +BSunc_sel <- BS_sel$unc #Plotting NAO events and prediction probabilities @@ -209,36 +211,46 @@ lines(BS$pred - 0.5, type = 'h', lwd = 4, col = 'blue', yaxt = 'n') lines(BS$pred - 0.5, type = 'p', lwd = 3, col = 'blue', yaxt = 'n') axis(2, at = seq(-0.5, 0.5, 0.25), labels = seq(0, 1, 0.25), mgp = c(3,1,0)) lines(rep(0, Lmember), lwd=2, col = 'black') -title('Predictions for all ensemble members') +title('Predictions for all members ensemble') -#For good ensemble members only -plot(BS_good$obs - 0.5, type = 'p', lwd = 5, col = 'red', +#For selected-member ensemble only +plot(BS_sel$obs - 0.5, type = 'p', lwd = 5, col = 'red', xlab = 'NAO events', yaxt = 'n', ylab = 'NAO probabilities', mgp = c(3,1,0)) grid(col = 'grey') -lines(BS_good$obs - 0.5, type = 'h', lwd = 5, col = 'red', yaxt = 'n') -lines(BS_good$pred - 0.5, type = 'h', lwd = 4, col = 'blue', yaxt = 'n') -lines(BS_good$pred - 0.5, type = 'p', lwd = 3, col = 'blue', yaxt = 'n') +lines(BS_sel$obs - 0.5, type = 'h', lwd = 5, col = 'red', yaxt = 'n') +lines(BS_sel$pred - 0.5, type = 'h', lwd = 4, col = 'blue', yaxt = 'n') +lines(BS_sel$pred - 0.5, type = 'p', lwd = 3, col = 'blue', yaxt = 'n') axis(2, at = seq(-0.5, 0.5, 0.25), labels = seq(0, 1, 0.25), mgp = c(3, 1, 0)) lines(rep(0, Lmember), lwd = 2, col = 'black') -title('Predictions for good ensemble members') +title('Predictions for selected-members ensemble') ``` -Following the analysis of the RMSSS, we compute the BS for the whole ensemble and for the ensemble with the best members. +Following the analysis of the RMSSS, we compute the BS for the whole ensemble and for the ensemble with the selected members. For the whole ensemble, the results are: -Total BS = 0.239, -Reliability = 0.021, -Resolution = 0.012, +Total BS = 0.213, +Reliability = 0.138, +Resolution = 0.172, Uncertainty = 0.248. -For the ensemble of best members, the results are: -Total BS = 0.091, -Reliability = 0.0, -Resolution = 0.157, +For the ensemble with the selected members, the results are: +Total BS = 0.136, +Reliability = 0.015, +Resolution = 0.126, Uncertainty = 0.248. -As expected, the ensemble of best members presents a clearly better Brier Score (lower value). While the uncertainty is obviously the same for the two cases, since the observations to compare with are the same, the reliability and resolution scores are better for the second case. Specially the resolution scores much better in the 2-member ensemble due to the agreement of all the members in correctly detecting positive and negative NAO events. +As expected, the slected-members ensemble presents a clearly better Brier Score (lower value). While the uncertainty is obviously the same for the two cases, since the observations to compare with are the same, the reliability and resolution scores are better for the second case. Specially the resolution scores much better in the selected-member ensemble due to the agreement of all the members in correctly detecting positive and negative NAO events. + + +### 6-Appendix: Forecast scores ranges + +SCORE RMSSS | BS (total) | Reliability | Resolution | Uncertainty + +Best 0 0 0 1 related with obs. +---- +Worst -Inf 1 1 0 related with obs. + -- GitLab From 61c401a2580af4587faabff3d1fcec6d4497a3a1 Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 16:18:57 +0100 Subject: [PATCH 08/61] Adding formatted table --- vignettes/ScoringForecast.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 6ace894e..d7c7eac2 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -253,4 +253,8 @@ Best 0 0 0 1 rela ---- Worst -Inf 1 1 0 related with obs. - +| ds | dsaas | sa | df | sd | +|----|-------|-----|----|-----| +| ad | dad | add | ad | daa | +| | | | | | +| | | | | | -- GitLab From e1759aea945db21cb02d8fdfa3f638004bb2149c Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 16:23:24 +0100 Subject: [PATCH 09/61] Adding formatted table 2 --- vignettes/ScoringForecast.md | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index d7c7eac2..72482a1c 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -247,14 +247,7 @@ As expected, the slected-members ensemble presents a clearly better Brier Score ### 6-Appendix: Forecast scores ranges -SCORE RMSSS | BS (total) | Reliability | Resolution | Uncertainty - -Best 0 0 0 1 related with obs. ----- -Worst -Inf 1 1 0 related with obs. - -| ds | dsaas | sa | df | sd | -|----|-------|-----|----|-----| -| ad | dad | add | ad | daa | -| | | | | | -| | | | | | +| SCORE | RMSSS | BS (total) | Reliability | Resolution | Uncertainty | +|:-----:|:-----:|:----------:|:-----------:|:----------:|:--------------:| +| Best | 0 | 0 | 0 | 1 | Obs. dependant | +| Worst | -Inf | 1 | 1 | 0 | Obs. dependant | -- GitLab From d343e588fbba85f2b7c3e49d17f3e93941e088d9 Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 16:56:54 +0100 Subject: [PATCH 10/61] More edits 1 --- vignettes/RMSSSforNAOpredictions.png | Bin 0 -> 85982 bytes vignettes/ScoringForecast.md | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 vignettes/RMSSSforNAOpredictions.png diff --git a/vignettes/RMSSSforNAOpredictions.png b/vignettes/RMSSSforNAOpredictions.png new file mode 100644 index 0000000000000000000000000000000000000000..6e394b353f118262080045fb28c7423945405514 GIT binary patch literal 85982 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

    nI4t5DdE^hf6NB!|>oHT;T zjfERE>vqg|(TASe{#)7Er|a+am2iIO!Ub~zNkL?>bf$89X{=w!E4+&s{!sM&1zm!} zI*omApM2FR{%Uvoh?D54U&I*e6>U1)Y& z8Aao}eQyiZgni03(RUIm&lXf|&E>hXzb;HzRPoJ}tIXt=Ij>>SJ2Ca<9LZJ=a_nih zvrMkHU7H!wa~Im$`zU(=L+>Ga?bOe?`i#U%O~>xln`ZRe9fg z&Dmnh*c+KMm=nN3R#iC4qL%LTRCL=ukHy(?EB}aNjVrSbUP_jJT)lp8pF6IIHFND! za~SXyUXl|oAn=CC^S3>Ga^*X(S>U(&05j&w^1hLMcJo`QPwBT9l#V^gD^BrZQ6_Qx zj*8bGSzB)_Q-VBa?b^T(Lj&d;FBcZd$#k$aIx4y`>!m((D!~M&E3+Q)(DaQeFXrPH zrZ_Ae&M&W#bfb;gK2Us{S4!1%3gX)V814Or&@;AHM?il$g_rXCk^4E0J#VjXt?PT_ z)lW75qd!bId5tgU&@ta~R=?u@D!NlR&JsmkAv~TZtCD@KG;fFmI?gNT^7pCoY!_ww zFE0I85WGJUp({z4aq-<8n%nq#a)nP#Y@3nG3~tp%)d2DNMZqVD_xdVG$7@hb$(uds z++mKK&Bt3yWSIpY!+)%ULDauznebw!A?~yM_4M(2VczQ_bq6lm7|Z|5R^Tf>R1}~| z@H(4*=C@A!$WOa{JLzf&#@1e3-`Gt|JThKMld)Zr8z4*eVcVsc9z!0q;9VcNAuS+w z-phAYT~w_81aAmk&r|9`p|76lSKnPf`>NqA z=iI=r6ld@FT0Dm#{JMg+dD56dy=~z1Cd&fKErCQ+fk5ThP8xeLo`xB_UM}g}{(-Rh zrOkKl6fD+Sa_kDsnHuDY<4tcnok!z5zJBSZkkJ!~L*1{$_BX7~=1UO*7Xz=o8Zd7A zB~A_}NLzOU^_cv$?cMqCo%3B^`e8AkcI2pj#`$0FFrajD0kV>)JzbNazlBvQ* z@hc5BMTJQgIk>>$QWK|;kPI}2^$iURi;Lfs<4AHZ=dv|tWdKY^rHAj>!oRIYWwKR- zGtlGRq~eM?#RS1i`1Q48Cn*FfMk=1#)3kaqQ!fQ-Y-77HH*@0M4D$)KFs`0yq3g42 zU(D7H2)FUqdPT2r2_9eHW_bL@=x$*THQzPMiHA=MT#g8R+bX1W@c!nb{w}Be;#r=) zW<~OY)-32;lp__yF0{0?rE_P8HvTI0ex2M+DQXc>JY;LvQ3@?5Jlx4!B)AEc4aITq zqiy~Q8-f@+)4z*z_~U6&_cWQ6m@;orFPuNMR3WtIY4hc`ywQuY-ov$Dwy9MJ@4jYT zGe)%8B(}Kqj*)_|8-&2|4>{I&z=w8KkF{belS)D^Pa6`Gl!A*EfG{iMqV7)_w8<+ied!x^MKG z*4d-Kq(Zx;%O3h?}!SoH@mF8tde;Hs>p8bbOxW zU@Q?eShO~EC#@$5a0?A>j=kX~ercx%WeQ4dQe_pNonu}!fL0SGp!-_s;1v1=#(D*@ayVY8bavN<~pSgzU#-srgvdrl-US~zJsr;>CUJxFpbA=f@Mb!_zB8fBW zMWJ5$J4yTby(haER52YBLuJ5!p^)6MIxq-7TSCGH6jH~tT^<-s6_qbbQ5;tpFq@Oz z;K?CjT)?Dw(3+g}{1^VVH*OM`|LA-7ZGKH)Ij@0-fc^Gkl}y?Mp+{~0=FTH@v4UsE z#63@vin#yOr8@M)+e5$Pe81<=qN5a?RD^5W!d5Yo@e(W(3HqA@DTz;RT)y=q=P4SeUy@@|9S+qc=0r%NQCJG<>-F&QtAL~($3F#= z?j{Crb&ozjQH(DCMe!d6ZTyRm!!{%|%v(^0EGINdb<)&NfaU^4ftlRuE{NgUS5fI? z7$i#VzNQc_NO^M7nDe3dT5_$mul%*M8;i_5B(JQAnLU#Lkuz8I-#rQz(44Amc49Q5+3YG`z9dMq)9SRZ9@%Dx1C#Hdik(+!d0y7z&d8n z1_uH?W7@#6PM73W+`|sV`N7_uiP(x>+ zKktp1Jvce>;(FMzweCFSpqljkS`TwRydxZ2|BhvoIkwYAJ`hmn+~M>y39!4!DeZvq%xF=|hh^_9KX1m?Wz%9r>|+NFzk>v%Kd}nZ%ze z=G{Sia`wii82{=yGETjxoS7<%;mwwP0((F+(5>vVZypfhjUeJDhQER)>i=2n5bA+By&Q*lz;e#b>g zTP;iA_a_`qls@G%H9f66%wGA9=~+9=h_#m0#^<3W-KKnKl`;zVr)d2U^V_PT8MA55 z_X=}#9q$?WcAM`?F)H^4X}{Bn_h=m?;Am=YlpLrK&_xR;)e=Sdf&1s0-dRfmZE$&Q zS=stZW&kX&Z*bg6`28uf#oO_p{<=dt24%cP;VO^%;-KnGo!)2%zvlb?OuvhOKNlAl zCpwGupIyJhk@GEwu9oHMuC}VJiodPV%4kqxjX6Vb?aLZ$97=gyht|(qjjFEFxP6(7 z$=NV3#6YLCI?P>&)JVRgJ7We`0VJt1+{A!+fUhuc-S8ij?spiY-728}F%^N9xnVHw z*&eY79#{0S+orM>`q?Yz1rFHWh;ERF;J|0U<(P)ZOEwvm5m4QGc{ga=t>d$9$lOLoF=HrfnJj^z{ zDyqt`Y-BGJ+}ubw&ey}T{j*XuSs_!NiuKpiUW&Z8?`4)*ib`q3Y|5ULBUssP(wo~e zuje7D++Z{2eV=C1>N~XtmBII*G~6Sp<3DR((zRvFmZ0wp7ii9GkQ<@gm54VprZmb8Y;Gj>)&`?j;4s*hsP=DTwV zovCbX*=aQ=@{@trv^s67<*AMl&d_(6ncPx7<3<3DIUB^HVg59SWOI*{8&Yt_0oCJc zvT1{`RrBcmabY$N$1Pk2L>)G@Z+54^vMB|-N;@e8V`P^!PBu5zdFkraPTau)QS&Ds z*~EIAepZ8j=*Qf4rzt@Y4(D z>Gc^PPF75iYi-{?_iaSo|EM+l0DC z{Y{epvCV@76UWjee8#JMhTRxgkMAnC`xn?q^YBl69TH#gz9R$&b=Od zCEwZo>51>rz|qy1x62)qZrzSb^+;7@XR#HfVQCe0^9RfdV=$!azRQZ)Jlxp`fP}}N z=)J%H=+6FkH<$7C`!-(u3#fENl$=RXYnz8IJx*!Ku5-FDJeIX3gs ztD12$!S)7U;oxH`lNxhaIOSkw0rQ#`{>O8<+S=rqUtF5gGx|!nsibRv81AFBm-U$!6(-92(62VT+SH4?kZM!{I=h`q_4gBojj|Nt)F9wTUEU^-N&YeLP!| z8Zpz!G{=~XP;#X_qT9l;$M;K;ZjO&b$f@7j9`WBMICW3jzh(BBefq*w;WOpumzrd? zcBX-5p9g3<(}^ZEvNAgvVluy;Sn++*P%e6j(!{5Yj8x(tE8Uf!9kN|1!@S=|3hS34MLq>(-NL)kk^_v31(3X}gU%24|nM zCA=-jJayQyQ&jbJ)yJ^4N#!+mVjm?{a(e){@n34Hne*yJB(4V9ytkgoSG0sMc+zCQD{Az{#Z=7nU%gz!qNHB0SS}6dt37bXTMSqg2=1_Vj5zMo-(gL zfYtW@@$pKdkk8$9JZsb!-aP6q3y*TszEcU$i8X?PM~ZCpc&z3gK6zr-XF|{}jAOau<{Q$9S@}4O>_LGoT9~psXn)4P^H%80eDpH?M*KEQrCm{On?+SeXH^pY8 zDJr_N+XgV(uWOT(fv>?9(U+9!ENdyBlB6|Rrv1zfeJhxIGg$>c*eGI?Dnuem)C57^Dgx$@(?b%vqF?7Wi{|p~4_tjHtt*(dn zUVB}0=x`eEj<~j!Y^^kdY<0MB_g&kaN3tGx$`W`P=RZqVPKAyc3LS6HIZWd=GBADo zwn^l%&!)B~LMbHUg40X3eJnFTw?R{rN%dQLcW_C=oX=p)HaG;?6nAE1Wb{CJ2#y+7 zIXqf05)ks8)Fwn`V6CU&6IugwDG*aehX#YM(G74Mr}|yItfa>U;_O$gFH>@yVa$VI z*G>zAi`QN^__h|Fkw##?y5;GM?W-$=T~p1{Nf^|#JTp6(0Fl90Xn!#EvFG&LX}A=} z`XBw=p3@sZL)sVq5!yk?drS=;oQfK5DRPt8yaoKn$~WQ8bCGK|(Cs_@GR3lfRI9YK z;FjV_q?Qi3Xuimpq)^0@qi-$Kl5fng;>!3taBhXNNzG#{Y4D&I0plz;gr37sPIE6uT-^ubbbXT5!U5pfSi{z-C)ArG~e^1b_56|eCI{lnUcmG+a)<0YgzCwU-m^r=s+#B=}(g*I6d^*4Y2o_W>&vv25-ybLVfCuBUAgvkc z=-M>W6=5q9W~>7^Cdu%Y^GcFo(qD%qp?_ZYG7GLEw0bJ6JUnnW%|YzZcpO&L)Sx4I zCC8kttEAU^DLJEWc`hb$I(1w1d~+wmEwaXQjf9bE+X&s-lk*)Xd>8{C1+Lj5XB%E@ zqIRi#%_ukzMZR6-R(Jh;6n+amQh}MZrb|$@?;?+M{mePs;^wRHoL1yWPF`V)e6Tmq zD!U7V6gQo24%9#EcU{JQazzn@dJcF4#1avM#gOiqn3zCuI^J6ofSq?gE_=05+-4&V>y5iH)u4##e3xhkV7X*mBh#&x@JYeN_()*FM|zJSQr0 z&tq14%<$ZWp$Qx=CYDS|bJO2HW%{lA>hf0&jnGfr(J6;TYSWJs>!m~*VTLU^zhDrP z!5|{?u9WRax%Iabgr|?f+2jl#({9>wv#y52zccFaCSWG9{dEs2YbuPpE%KA%U|=5?n&|Rn1$j6dg>vyfcxR8iZjne5*Vl` zt$(=sI8UCg{YE%pW2{(tvY)BVEyr;FOyjHFc5aIyal3DIXdTtfnK-veXA9THJ+J&y zX2*){UQt5PCPrc9dv3U8PFM}YOwS;j+BH23nH>Za4BT3~hbH3WkF}PZj;Q03nqd9x zXUO5RrJP4uHwP0`Bu6_qa+sP4kw5+EA@rK>jJA**RFfDPaY7@5F~Gg-4*#Su;dx($ z$VI4Ko*O(zW1HQ^V`W8<^*-v)yg)ury;^$i9z)w({?7B`NmRW~=Ck~%`!$yWX2;d4 zBUF|t<|TH%RM_2h|I==UEKYjbk9OLuJIXkzv@JNfxMYnz-|p8MGG-;RX-}DJTaa;m z=p~QLiAvUCaMeAW|M0%RM?3rLJ-fXnzAYXzcz)}Yo!fKUizCa^AAfu0yX9N!&aR=R zxy7qBgDo#7g<1_vql!dtJl#X3oLSQIIEaP3_S)9b&et5ZRkeJ(=H3t#2;2eFmCWEkH0)#@`16)m_|O?Cf%!1m%{-gI8jVS5=4U{`q6KNr+9MIaoCK-G!r@dP-d?-}K*ick&vxS8%E=CaeVAJ~Z!G z&uP@&wY0;L=5r12%N}2v)4Ly6q;)RI$((*1tSO1A zlt#%)E-)@3Q^J%J!m3jKg)MwB+jBdnkA!T2iEKeZ$+GYsn;QpmJMSK_k$Bjgy)KxC zWK)-w%z`Sdpw}LU~)-%KA~z#T3jtS&Ee>v@&wal()qj^8*(2vI_{c?;}6v- z<;_bA&mMc5FB6zaOyJ}>)^TU}t7mUWfvkR`U~JG>!?~_2HtT%*y~W$1nC<*63Tns` zFtZxtLDN_ahb}dk%|NkFNxJ8IJCSH=YU+zh3zP9BE2WHexVZO#si~d9wOhBuG51hr zAp|wXpn`OB@V#w+{)nF6e$_ab^{`2<%P=FMv|`ZXCS#F0TT=;$#_ zf`u_J^ab%Mv1ac{ukK+=Vseu8dw02{M`u45;rm!bcG~cGsnkv1Fnhw@8`pyNdkPqh zg?$lkCy5GSR6T~N#m&AhB!}vTEicvToOWcrqT>+9m_)?#x%+L?xu0}7z93C8+~`W2qK1vHqdSbOE$k(hlP z=MIJ_8{~}i`w?#Q$}_8a_K|6t9x5BzUaA?{qIpcz$4y4VJbL|`%hIfHhJ=|OmV7wu z6zTqy;g(Y$q`9L25s?~!mBC0N+B@96RFdnhrqF0uLG8~*VlYL`H#m)roD1aoVc`Iwh^;*yw< zU{P^moZJRBr|>U2Au~QcIC$*DWtzPD!FT-TBIMtw4-k~1)5VGcwv99CMAWOcYfp1l ze~8^V)}n0wAY-uDHI>}5sFeImC5>b8KtFwm4Q`VR-R1h=W`_ed0EXm-PHj8LMXv{G zq&|zfJ^RA!aS8SXi^sp!F2#;NdN}-CdmjfOTA*nr&W$mjIQV`m(M&rvbR|Nm=~I6M zTmE(9-Me=~%vs53b(D7)Hw6$vnFSrxwuCQB@2`K+@#O}#w^5Q@dSzwzBp3EH`ZD|? zxm+5;uGQXtLxonH;3VR+u(GQyyz?+mQ#fk%<|toG=;guA{b$dXnM%!k|2|Z~nw@nZ zmy4cicSlhgZdv)P%hvAzkl|)s@RuCwZ4ve7-4eO;_5&BmC54#>_WAOo?e(f9)CBhTzQF^G80dJ2tj}1^O))vlhfPdeaK{Zy zSb+pR+}hCCn4NcK`?JHW6;;q}x5=8J~k1tOLgC<^g%%KYDC7oJ8c*seZa)A>nE=T)f8Svp^kFUOoctRC^ma(s3L%~)H zW%~U?n@)bCIl^>Y=T{6-dY3!kNbYsj;ts_)_`+hKdNEghNG|)Z1Bv04x50!u_gJ^r zrqrY_(moaC_VX{8b{q9~Z7;PV&iPC>PVjbceLeN*^V+j~y-WOY#oMgv8y$y~`!DVY zu31{YSjR#`_Wvk*?|7`+|9|+D%xn@eA}f__vO8%BiHwA@N=C?DQOU?k%9c?QvMM7h zWhIKJh-4*^Ei>hQo?X}H^ZR}8`}epX_wBFiaaGRudAyI~c&+DHVJoT*`S9`4qo*$o zu3u*+RM*Tc_4#x2>G5ChR|vL@a`9^B(XR|kbLkKEoon0%-VqB5<|BZ6D4n=c+dZz(&GQBzowLo6?J!3nzhaD=oKf$hrq>I}6EV;an z=)VDibTaBa4Gj&Qoc0Rc?jtW~+)0WT4e#hEDq8=@bT%{}NTZ=3&N+zv86ltA*`rTY z?+^+WKAv_i z*>xghwFPf<23&oF0m7@%`RBiSABFwuFOMA&JwN(?K{f4PmWFiaelCWwm;qh z_6q1`j8)N&-R~N2`z%;y^?7oqrVGqiv4>U*uQCZZn(mF}r69yo-#d)Rke?iMrrh$e zygk`xV$YFDwFo6M6Emt7>7Esy2PN|72U}w#TBonyk_*!$e6cN8Yus(C=VDfOpp7hx z5FC6~t|)GZE-q6)WB3U}caz4gR?_`n~UKP8(Z_A9waUS<5kunFcWJb@_}k0CZkjUzT&6>S`;Ku-4>Sv}4RG?{^d zzhG~#1p{AgZJE!z<65xwsGtOm(g;oYQ^gy_#UvwjIG04L-V6w%Fs^+{_fI5d&P0s* z8=I(0?n)OlDsAQ-uA+3HYkn~xIiWf!b}fsW%(`Su{mChzcS_7jc)z<0B8D^(L!!)%A9Pqh;i!4AP%c+AUQ)GPn;5$}Knf5bn(WVk>fS>u~&O5;N8_ zb>iM1hd;M^TY_G_-8eWz>9RG5Qi_pI!e1r*+6=|BH#9{Ol28fu40(qu7unWZ%G8t- z78ZY?X#WM$vL8Nt5Qw#FisVeaeKbkW^Dr*$@2R_3wQ{=BRQ#ZP|G2Pl8VzHpOb=EG zSa~5SptcNev?8!SB2@TpO%NvwieU_4DD^RKVEG;E$y8r|f}p-7eQsrDpZCq0h%4WV zR@S#vzxv|OzP+}APBL}1^5#o{tCv;dpY-L=nNldG`dMGuZ}Q=N^_qQPg7|(XdV}1P z+`1dbpVh=Vu73bXE?d9FkY4=Fm1I5N8j{v4uH|_=_AnA*bAofV&{BGdfY};!p0}=`NX<+%q-?>9Z>N}y$?6_KF zpJED5>4(qUt+HEz_%|||H>co_htZ&Ga)(#cp{|~lvEZ@!OVQ_oSb0m5^hnA2&;SMv z&5@i74XnrAe_pBbly!c1GUL-!^iJMWza*tt` zn?(l0?R!3KDSkV)s|&5G)(=btRFEI}a)pWzmeD+A^3Z6nMRi4PZg|Oih+q;1(O9|I zKImNQ6GCbb&Tt08skk40eP0GxH(5w!64oIDileXMF>%{6`Ibddx`gFR3~QRcd@i=E z2MP$I3f8S#ZD0Js%ZCjLJTe93zO6&v_HcBfxUt;Ow{K-OEw?~BI_;v+s`od1;ifqM zI#}vdU`}^ezWx|CMKDvmey&ZCfB%UPs{IFc+>RTMjzFf%^{X)J7`ZZUyDGeNC-Jdt#3dX^-W=6B?$G=$?$JqxX@tVE3l>x?Ark7x~OB}y?vwZMxe*rc&VDl;rU zQ(IJ;BV^a!y#)^+cG$@vaRiI+(lce?c~sK`8Zt_lf2FVnrwKAm(418`9%|tfvE^%0 z*o!;YI8qze%-mx3g7J8pBVX2if=d z2z++U!vzMOirUQ{6TyY%uB%c{O;eS_`88I=Uo9g3f_iTH*oLO6Ku?tJ4C!Jg!_|GU z_vtR|<#$;JkzFYMQ%Z&~md|#3Xlu7^JL69xcBW&72+anh_h8bQ7Q|a}Bx!$x&CT}h zeaQE5C(TQBtKWMUrYYc{co?Aety{NF7LpVwZr`@4nn*qHH=E6Nyd+?TlH`4;z{?Nl z5*ivF3=p-3bnb5~FLn+_r7eFb$X>x6tAct?R7`WP^2NNK=DQ#*wO4Lk@`XB<+8)T1kVii4>i17d%+7 zW;c{XZ z$JNS~Qb-*85yWCulA6k$t$$RlTQj3aThyLd0^b$V*9QAOne*N|yML;ra47KVpk4wm z3%#nLM?@lb)KI1OQ}*`Q>sb;Mc~r$C3Y03>o#h8l(WDB#?F?6m4t##CT%5m*?ndCS z^Oo7WZy4v8&-H5x21$JO<=L%PzDoA!p1$R8U&4{2aPagu9`UWXNW@jkUWe0a;X5u= zzYTrR){Dvu+HOY@Pl~1CG((XGPq!bfgpcQmNj8r}ysNVl?@}Ctv-K6% zrK}pDSD(9&>*IGIrlNNEG~Q=lx<=|T-(A!Wa{(E(afK__>!kkGr!oW=xB6GHOL;eX zZgBWcsMEB@^}MHlM$lrepxoEzITlfJpR1NI9NSn{$*rTg*~*$M;{m0J?yPy#4|GS^ z{GKVoPN3eHBV@n-ibN24HeBs=Snm3bLWL*!y}iBgoAgwYlDc(m=NC!VyvL9A3yl1{ zy&=10qP(40)ICt?k&h;cghYozaI1;6we{u8wYoW&gE-|w6gC;eRJfl(&9F?|{1lq> z`uf9DQ#` z1mTA%eR+Pn_3?7JR^wlv&Vh4H#pB1F-QDug*7)KbB1Rxngq8K z5`L|$Kq~i?Tjj#S0vwzA+$s^V`s}ZvbI!hPo1c$Ql3G8W6bc+(%KfCzZJh0!a37e< zNwG}K$`T-bWbZTc`-(dCg|y9;KHeMqA5j&v6g`iWElZ}m6UF;uj=SnN^SNi4Ey7i$&%WB2 zRceTbu7HX(peE$de4z)Z&C;y)kZ%7rHT8a&0%r38(^t@-H(5fs>~8vqNK2 zPX0%4+j-)hgoO0{ZXpGl1xE1f8hBhT1Ql#pdy=`J_=2WKJnL?E#eVdm92^`zNump3 z=kuu+n+c(C++C4?Z-d;~akZ(aqGAOhVA2yZCTN_UW_JVO3`NcMr334HmD`54+ETyVFQUO4N1{ zurWx~^T%gLy8022;?q>qbQ9v^&nfi({bagFxw-oT)}9WziwFsw`bb^_3=)PtJ>(zW zzb|&%t^-WMgU63q)GuHDWA4>&`{{l-5@-lgEmaxAD0X7}ZF_rrON(XsZZR=a71H1c zQB1T?OxS>4-b!~93^l^Z5iLMxIaZ&sFrjX30Uf;B@ zHu{d-rz!47_E)zD#r6d9d494<_qu)aW(RgVgrrJ0_{FyVS=>j8Eh)~u`4XLCXo&$B zh>13I(%sPD`W50f()5j!0I30wlFZ9dw!9_0OPzfXPh};N5#p(VJGzfcAwsqr7FMb$a8O_= zb9!;BbyO;;%|`pgiCD{^BZBkG%kuAAqI2`};pieA$sEy$l2+JShAV1rUBS!CD@psD z)Pw5k)Tt+=g0Z@$MyH8w+qNgpJf|i-envLKv!#SbG+t9+?&nV#&YiJGdLG0Ksauuw z*hK2)NQ?JCB{ZiiDH6A&?SSHAHrj*c=4ma7d3j>>UM7MpyY6U#Vy)Z+tEqt2=K0xK zT(c5Bs>rC8bYvsUS?#3`6?Jdl#>&JrI5cD_^`N%)%ZmH%J6a_sj^9>yu}5fVXz1K! z#2#s)y5!|$EOtlO8r~eAmLG=96caNgI1Nlq?fu1UrIO6VQFH{IRcHrj@UTl;Ryq*B1=GENeEt4YnhKvfOQ)2J;MSJ!{e z&Px2bf(ON-OLOjI36BiS=n0dFlSI3@iQ?Dls;rz`a^ySv(x&tLqM{GsSLhuX8hY5) zHhXRyX|!-V)slST>X-;&~HDmP}=mZ`QnY|xHDH2 zwxq14qO6RTc$=D9wtnvO=g%pgZ->`vRA5rM|K+kVFMKK4KlB|FGfhauM`ns)({NHu zmeW9A-)cQ(erf4kdRCKl&+%}&M!cyc<@50MdT(Dkccte{W|Q?#UzO9ds8e8NFu$;n zlALV%r@(P+$>6xkXz`0M$52;No5qx1oF!cN_}$dxWZ$Hk%Q0?}8?*@0oi0;cr!6;3 z_H8yz@3K2T>Ficx;k*!-pjVtja>be2U~ug3t&WYS6j>>Q5*>BjvO3psisFQ()0i}) z$9eio>z_3HO)G1vIMUr&CW~Ae^q{4U zTawi~v~(I5+Uso%Ot8b1o*MNEBO$DT;3gF6(5?qS2%tZhfPO=GBl|h=A>#LBf@LDa z1TfDjnb|n3I4kBN%_@%-!q2B&%OPHQ!hJX-xTc+=EC<*zsD3m<#Oa7`0=f& z&C7dTAuq@tfpmp4M3T2&JXhl6==3x%6#Z2{N`#n`TX8@MiItP{f|RhD+Q3Rc1Tj;O zw14O4=Ofc=u?w(0ym5xA8gzZC_bMv(&N^E*BYoNaTx@ZE9(IM2e|PtK%q^{Kt?W)4 z?E?p{%=MXLcSA})PEz>OW(0j`7vb%*T5=42`^JtNVI7V`^H#<`I0Bb#q>@^Y{aBlf zhxg4S=`=n3U_UbBf}{)Eu_Y0mS`IHE1l_!Mc9G3tjaDOtNl0r>p1j@ShLh7$!Qr_p zswFWwnQLT*w@*Tr(|VoPLXZVI$oRYXbd_d|!sEv1s?NS%afjPsO5kP4ly9b@N{J-R zqg{_5&OIr{MjI!Il3DK0^ua@i)>c*$eWt@3hv9RDeTq<|U0aXrMc5iOXw=3Dsieq& zUXB=C>>+dG4Aj)H|548KTE9=S_YRAPFf zY;9d;wVwlA{+StPsc)cUG|}J2pC8TEA0gcpA>lWxTxt9Ng9UI>S;oB;wLKR)5RkJJ zwuTUb?Pu16*3rqXChs;higkMZCyQk3IT#rkM`)fnw!izj|6ccxsB{+nTx^PNn@FR4 z+rXqJfk!z*E-X6RDwRh)SBnk_Xeuks>Z0?UPn&aVyO0=2aVIX$dO=|c5FJBf<7Gv8o?A5~dMAzC3;K1aopSgoi#F@l*uE zJIf`IN050rog2fTk1qR_ui*=qxBOr+oK?kuf9EC%DUgb}f>cMjy!a_ogE(U@u*!xdiAjrCu zmY0%p8o(9PLi%cKY**=gB%pf}NI>})D{o97&1Cu@9{Nk~y_4(vy#}ThpYJ|^bhGEF zRD5VCa4{M>o}jf~g2P(K)SFzh*3!3hBq9v&wt;hj6{S8BW5=WE;$f^V7Gf;#J^s7ZTsv&gPpEjA)}Rj=Q^mHSM$WsAeAX@d)`39@QzIC)Nk zQ>T0Y2`#&8bo`1%5y0oNpV=ZBVeg0#i#+1)-HR3D*y#QjHq~E-bm6D+H~P8mkc`=z zaP_WQ;1}<=2Qei+T}!KW>1&wlcH37s`GpNwCVu>g;ofgm0Wr$`Hm{iC(jI=80M2v! zMX@`tu?12hU0-(vz(slFlRmOwVYS4m{rv>sPCtoToL1{csw{u^C-c^=AKkT zU&3@i>~Al*e?CgbPq%!I#hQTh3TBH^oN;)>&ut`atX4I9ME)j~X2|?LHPg3OK<+XQ z_)cr-m8N5nWWk}K7!vo}L=LePW8X4Eicsns`npZ#F(6aLJvUHHn?_SIB!wm123n@V zO1t*$Yk&1h;xn9H&&HKSaqg3(Wa8oBVPz#h2K|1Zt{#s*>1IaiEd-}n9E81R))SYZ zgK`-nH2}Zs?&r+gJLN-Rdj;b_NX}Z2?V;IJY|1*w0Bh(|>lYSKeGK@u_c}ZrKvQgTirf^st>uq{qP=-m2!vU_LCK|Kjv{F(%M^0UumvfE;{TRE54fT>EsX*+q z`y_p@&nAz(Gb0T?gW?(Zf=xyFQ3U{710x@jL$Q2r)0s`EMN%ZKDG_dMkwha|p0ycl zX7>sR=aepCP-oIA%!-gTe*B9PZtvZM>Jxs<{YpdaG53rJ3qi2T7y(wX+YAzOa){*h7F&}4a#3PGyx9tq2vj6Z{r0RI%Yhrl=H|a4^O}_8cAne+-HFM` zZ-3N(Y*Tp_cWB2JYUgF`r!t>gFSGQqR(+B`6i7gMgv4}{6Onni`0k6Q(Zux7w?fow zxPR#L_x2q}bIx*CmC80g4zCREc&!hggSC#j_6xJ^^R^?duB<@5NJv_G0m&IU4%q(q z3GuU)I(6yNd=MG=gX8I6@{RXRw~j>W=RRFwIYQ}pJ5p!DmHX#Bkx5xag;W-PlwEN= zvWNY2wSSNTSLoWfktiDqm8;*?OCZAk=vkQHP%HAZ=TPnnu_OT%z(BxqmZt`tdsJQR zkKKT?c>db@=Cxd>7}F+m7NdiQ=m4*<_QyYnPrGQ(KK;FP`854~TA4F>_VP<5 z3+qbc-MyEo`5UaJ?fl7iTf8(S@SUC3eiWDWEjq@2T%)ZvT9oiY^llWRlUa7a!;?(m zbrK4`Y#ts=Z;ugQjAYVW?`!2V6?Y;?IAQg>9=M)iSx!AS&Ek6M++z`HSAT)nhoeFi zG$qe)X_MR~K>@+Gz(B&J`0NY#4MCKT87NZ@($6akjUXLmxCh(8u))%31z-@_UfWka%jnFYH>X z9@xG#IsO&%kQK*+ii*TFyaO$*N;~q-V3`?Ppd*tMT&&Q^VMe1Yp_PiB z>nCQmq#nbsUepJ!)rCQ`JVeQCtqDK8BR&*r*CCZ@6X_CK+d{y zsJZ8(PKH}?8AmC4 z)4UGv(wnLyCp2_yx60fssKBA(3o!fQqJk$~ON;-uuUsgKY|ovG-Y)<4X2mC7o*IJx zsZ*aoV(Vczi4_Ef4T6|o@li%OJdn4Cwq^iYY3O_W(=}H0TY6+BKGVUxcV~vSXzY>q zBy+g_N(?gNmL(eQoIo>OW?Ne@tbE_Jx1TSXpB^7?dGTQ{4gcq}XYTHQ5g}t5ahUpy z@(HzVe8st6XRLm|+RqoWSchS%OWKaz>maclLiqm83-o7n&BZYq8!K zg*C1hO+(4o(NXB4Zn4wl<8Q+3BEg>6V)Gbk1?WV>P+9ZPA;lNJ42jeZxO*`6A*m>D zv)aldNY$~U!w@4Y@2l}$jL>{G(WUeFG*c6*8 zY8Ag={Ti)+#EF>d4t(YdkwZvkmOmkH1bSm~!1=9sykK0*W*Pb$H{)+>2?2uga`Y-` zoH_i8&S9>}Qsns^rs2mH4cmr92`=Pma>Ja`JJnu3`VqE?DblJwOPOC^?A;R)f{e^y zk0g4%^yu{>KEc2?d&yDa)A9`yaz(R}bZS=t~6;!Kfy3Jl&gH6Kz zwzF&VcLXzawsiz^MX0PB5yM*NiT#fLuP#0hrJ%P{iOJ@8!FN`?s)lrzC*NC})X28~ za^&bx3GKF*i|`>`o@`1dt)kstdu8U$1kQ|Th9?)@O=`o+yZvui5SoG zGvsrVIaWk&u8i$z_u3zJ zI+M0^VP>=xNG}|6URnFwwv5KPv#VnSm%*Ux6f&~17@|KZEPNxnjLH`au(IMUtwhR8 z&CF7-Z>6T~)_F(*%!9E6Z&Z?w-lRMA9j!%R4q+GVjDZ$Hva=E&G7iWCQZ5a7inVRV zZSfD7qcDl|)X^6hny*+2nz^^OH*V9{g#iQ^ zXFlzdKy@l{e`gUS(6-V(d*V{*N;rH~bW?+jwrn{U?vH^I?yTxYiegB@FU-$B`W(Ik zqt?oeKflhP?++NZx34b@0IOhVET`7+e@HY!uU}8%JY!)|i&O;x#n{+5LNg2Utv%KE zjoz&@3%F}#-iTM7EAH&SUgpZqw$X}?l&9a@9 z3a}ZSl6y&}aPaEsvpakjUp{lQv#Wb|k3*%h-Vc}EPb3o)Kl<8Sj~_jHBL4$wjJE9$ zNmd^#buSz0N0ZckO+JCG0G=EG)?Ba&keq*e5~ZYg-X2mjB&`Q9p#lPa!?F~)h6Ge? z@sH8aprR!G+|bMdk^`QA7<}NOd2s(eUTL}W81y{tI(D>fIPqk@v$NX|Aa$uJ=Fp-k zsnl%s66oe*EF7$Gg`{VSz>V(2%isQX`VrF zA`zM}Jb54+-;Qwemeo;KF-1jRfHux87isC}1c3Z$p3`MR*{vfQVhPQ~(!h<&1ays| zzz!Hk#%icZv5Pa>?dV=%8(CEyBdKK~1z8P6wL!8S{jY^($wKtyZzeAfIK&dCUUj#uX0Ok!afex>U5nu`b z)}For5zNbwj|ULTz}2-R>4jGIrOx|DovY_4n}>D)9upi5bU_9p3V*Nyb-l;jA?x(b z?nCBQVxpqdbq5EtJbvwx^>e=X>$MA~=~>xgZbC8B3cKB=2V~>~LTO!}GW&Tqu{)(D zdiQ_h(+kY2*n`Z(1F>>5XgETZ3BBbUYc#U_0ozLlW{@=J!b~59`l(a7AM80pVq0vm zevp)fkmzJz`M!NW!tMT0Gb>)X{8@`SLMjuv?*Wcvy{GIkPhsbC7fMgSvO7AcLzEXJ z`6Lze{t*_Xi_8(%A*c)0nO?38Jy8<&@9kBdt{rDR4>xs>Jb7+qwDq=nTWg}+=9Dvy zNp%IyMTYLn|F^Zfs_4!0Qo_@ZZrVH7YxssBON+?_t;ya^iJc{f?TSW5u6u8* zyI9Q``JF|RjQY@=ufOQbtLQ@a$qF8lS~4z8(n&C@=on5D6d9R3ML439EqpuRlLNc{ zX_WRgH8mpIiFI?XJU9R1et_o*8%1-|-ob%{;@k2s#D~97eCtm8A^Hpvse3MIGnc6O z1J{&P4KnEJY~9Uo9Gu)X@Z$8PlXIpCxj38{&|y;M;F+Z_>&&fiHsD|bH^wiZFrxXN zvqzACE5k_oF9fvvtIYGdUC2X;+++wz4VJ4}YqF2dl`k?uQ}E-HH~gb-&#kx=A2=X# zJgc&|N$GrdbO$X9dw1(!R~%qpcI@1FFL2`zH(&3&zd(SAtV(KUXJ<_5pvYr&{P^+9 zKT5VXw*+5GuI1%#kUDtqAUZb%Wy3nh4;&y1f|h9q#<7o85Vs-9O3$bId6;WY8P%H~ z7EM-+%ZEjR6PIaKe^Wns{Vp}Wl-BKYM}zZG&n&$R=QHiGLF>#a(uP`K5;{H zGmNo2;+3}U!FPrD^(wraNrK%#T34-b(*of}1bj%GWORkwACqZ;SWy`Ey@~pv#_c(* zkfet(H3^wgrY-zrU{MiqfCLTRRaPOkg020?X9a+-mjSF3!UFp;wh{Kdk5U(F#shwi zWmfyHGztt%)GQd@0YGH8~yw*44ZocS9qXkunq1Mt8dxMNzUy><*C13y4v{4s`Vd4hDalao&k5z8M<(Uo_Q{tCsyNF_L=JxIOyX zmyC>~MDBNc{N2fFw3wbUNUs())}9o5WI<0TTQLiI8V;NbI*ep+P=1h|t%3KRNz^{@lf5N@rn#}QDSf%Rqw`Gu>nID%N3U+f*s>7YchFx zJIX6ckGFwIP-@-G5Ld+UaYqFgRgxMy!+enMH#4JC7rO&~$gDXtGacS$bhy)Ayhvo6 zkg6;T!AG)1C?cOSzIW}bSEN;WE@HW)MoyQZVX4ni)dHg}8R(K@GFKpp7wy${dv^Ko zK<$xZ4$;@M7Tr8wda#0ic!Hbnoh5$LNpuw9y8QnA`>!)I$7ik{`GsrLRhuPTP+WXE zx}IBvbYjf9jta&fAltENRVB6s=?xQAqeL4f#CRy%%RLYl$kP+;t?cgVk`@voiQ#|q z%F^fGOHa_(e@J7y5BVFqDa~`tJn&5+p4-oUF@;vwrRoJ*RO|1Y40<EjM*Yh3* z6-b>p-X9!r&CzpTw zipTs&l;NUJ$v70Ij==H%%vTd+*Or=xa)R{lI`9YI?7J10BCl`YQ&8{Ys>u3!Hpxv_ zmm#6qL!03azAgpnxwuG=MO`#qQ*)rZ(T!TCPWvu{c~h4w&4oK!*A4Rtz;@LhbJb6k z%LH^hM^6;Uw`g9KysmMx^(@o>dHc`WPfpR>6ZdaUE0BIp&HQkve&}1s1L6BQeNyZ< zI9w{Z_wCq0n!qj0&Q?H4O02Bv`%4=sPMvE4S09`dGq1j*y*Y{$>Vnng)Y%9bvCUND`OVJ@%Cr>-WFl&HOx4 z+#F8#%$+KDs2BGvX2`8ABT`>ryhFR&coW+eTR!Y&_$_>%kHFj=KitMImHxeO zH9IgPcsFyNNL>==>&^Q&kS@(*Uk5*xapd^i|E?!2lJ0iG&K-5VJdYg?+fmR&;4VS} zyI(b{{_jphwKO2aWVL@GNe@GuHXR~0Kf6-ckm(BHdvt`k%bl4^N2KKk-SCPDdxpk4 zf}g&|;{F<0as9ri;7-k`YB$9&)|SM|$EW5psDApSh&LYgPljDl-+!|=>2w;QJ6b?7 z!q!eU#PaJUAM_ELN3pe^^t%13^j_}tnBxxLocN+EvmN)e0`DE#<`{BytsC^odXOW> z9iO^rxStAfrvd$luntlc|5WK5(F5IVSd^BO#9ltZN(`f)s^y_Rs3S@YtJlvhwxS^1 zzdvghzK|)*=KQ}uiY>T4Yp+yb<;%)Y!eWZoH;3Jmk4YyRoflfWvW8 za>}$_F^bGylq@)FRy=j2iknC+Id<2t?$EWnDiOC>@;zm7QJ{uMRq^{Me4U0zHq%=p zNpD?>VLN-c=JfQmGW$+FoY{YmnRS!HoaWh;y&+7*wm2k^eP4joK3GO-0u;}n$sxRynenwyZUKJGSkbFOpT%O@HO95wU}Eh zny3i9uteT1vZuWz9;Esld# zm9LM_+?vyl;0o?sw(xL5ox~BHQQT7pq%*w%N!1i!Ud#-0!DW4&cpyMjKo6T{+cpC} z1jR?q652@ePA}Wba1k0C13sl_gq%!BkWY$?)yifg9;S9x2Qp}d98qv~wjNg!+e4bh z?WLwu+B%|f+1ITkbsoE2Mq2^j`sw{xYPJ*_(t)8au|Nd?x>p-Rcz!Mo1>vOHton`) zyGy_jj-lZcO2=uHLra4MQ*3MeUUJct&z_`T3$6n!(Ljc?DzB-ow&Mxi{kJ)RwV>uN z%hD5t{8n$JaZ$IiVSlr**0U-;$Hfs)WA`QFFSx2}gvc}#%`1Yk1WcCZgsMD)jcykI z{jDi#EId2~-9J9qLxsc(Y&+@2?jxuFb4}si0}++1qz&VgUhOl+wPnV~Q z{ouXaZSHldoSZm0I$bq1dc9K7#`YBNmVy#B4ZxGXDeZ^{a*R>YHy^CJqld-g!Z zq`)7*qLEK>h2)l4i6~~gy%7p97G$4ImwJ%J{6Y-?mRw=EgQH^`Zn2mcdFgk%06A9F z^XCMx8pt1P`bIx*s8OK*h6c}$gx0-%*R+LGy0S;?s4e(^XC~krS3x> z3>}-23QAynN_ytE+yk;RiBICwpzlRJ)ef+T=>dOXuwT z{-c1>b_xn=#+jb_|CtA?Qqa$GC-yanfNpF{h4|5E>4exV# z{D3-pHnb6({6DX2YX18gT3WMx&JgwgwX9LJ0TV42I^M`#2D1&U)U?C7s>HDV&#=ew zPpDJ7llP3~&aKWNVKzws>c6-nr(mCEruy%C5_|7GWmEDz`@;x!X%8N3JZtUn^IdnX zn5Cm3h8-&=<+FOMH{>ym)6Vilp)`4hnV-j6m{m)Vh4V~adotZ7;$-mOwoT;H&%3;S zbT3{ge>hCd|CvjfLw}dOy~~`y`~oxc3$FuLac6%?OebBF=0-+M7M{RmB@d^ElS@6> zV(&zaYvV#SXKj>Irs_VGSDdv`3v6$_6k4`50BE&P%4j% zFl(uFnh!O8Uf@ciY*JHu{_vq_w8PG?(O4TM<1R**ukv#NS3K~^8iO30q@<~I6VDbd z|NMTBntn7_vm3_szhVN{N20rPb_VyPXyI#Z&p-|{ok%0Z9`XD8V}XV%N$tV6jtJtG z=1%zfNObF4-oL-vpv8-f;UPEKbE}t>+GI`BpT{lz6Ec^7zS>E>Wh7sH69Ii%zQA?K z0YfGrk>icb%(UmewzRz2?nvBULWgZ;t;%}Cq+XC1!BRTepe@W+a_gj6L1E#!zk!Uh zRt3!#{svpax{Ynh6sDyu7&e|lHb-x6&~_Q~6AaIOOiY028T@MWQtj?by614y-x(er26?}` zqXVe8k66XpR#)A>Z%bD8=5!tTz;JGSjR+i~55gx>%84s`iiM~R(2oRNJtce91Gu7M zf=eD2&Uty-j5=uR?r6sCo;7KVd@^=7tEzrsS^^x6{V6hl%b=orDVlfFf4=rLo%etl zK8T4quBXQ|FsiT@nSTSDZj(jPGF1~n=!oS)hRqS)WEcafM z%ADLQF0LEal@Z)I^8nY4nT{gUn`YOPptB5&=fA7`4i1%(_?;0prJ{0WriwqIJ}ayg zBkk=hEJVIkrkD5Z&Ti=lVnE{gZIY3DM-Ndkbx5FcP++VJh5cDO7k2(%l2@JWu6n;-q zngHhFvq!hNu$Qci%p;4MHRu5#YB!zXlXL7*nyHqyYM`FZ`zppN29gV~# ze&fgT6zJnL-7%Tnu4sgB)$b90PbO%<`g)UYPjDrsKxCjE50bEOXNvOjdVCuJ0nMecD?p^6TfzV0flJ(^6n#Iz;eLB2n$Bw#zf#+FS zn}UF-4)*AN&I~T)^XD4?#+e%$qR>69l8N4@oZJ!$0J?fiH1@xG`rVv^q!=UZhPGf+Ig_c7(ZLDH&(e^q%Bjuy0_mow&*1_|0aDiGeBhr1t3IN6phyN?P!miH4_V0Oei0QJh*GMLHo6ub!X z483X4HqMWPo*3q`RluEY z>F!}?f`CN&@Ex#({kI*YX3m2L-NKX9uyE!hwkdkK90znBMzeHw(l``vnS<2C67*lo z6$jrP=9}uTk|&Xi+zf63=G$^uq|6ZPtW&32ytcmGgYa8c7C$4#9nr#ddUrw&=^}Ag z{2?abWF?)sf++`4agr-5bcm_%3fQ{L?Rr$C0_Aoj`D7Ei3C=>quVT`fq%`p?_KQ=E z2wS)&2E=3S>0suu$P4|ebWuaIoAt(ajGWG0^t?SNl^J{;+gBcRvx3j$Z^8tdE-}e- z{koXJN??@nj}iHEm2XA-hRJRtJ3>=3m+@7 z_X0t;^@JhCs)r^d9nOE9GmpJlp~b2to&ZiKKy%X8Xclh<#nr_C-GIMZJt+&e#8W^< zH#9Y&o5!jS4VS*kpd(7}l#W+n!C%t8nstP5UtN~x%)&p9gY$$w zPQvZmiJbMd&Nin{aO3U%tD=MM1RPh5o*zPMK`8F4x5Kw#?7^WBVy5Ws-6K`B!*reR zocAo<-a#G2Cfg@@fo^HuoUJ4(!NRviTadb50%sGrL(pcNqL9m?=k?^cNAOLfhc}5j zqODj8doUnE8Tq~dV+yWG{=!M56H7A#j2RdRf4+U+2t~WC@xNDq<^IQITuccqd$CGZ~ zK6&cY`1JHeTk_kaEvBrj3<+Bq(){4wp)_S5mO6N~t|mNRzdlnLc9Xkdc5cO4)}L&1 zhQCM?{Y%%{2s8*1^C=y z^DnNFD0CoWm8+yDC9S?ynmMvR5QrTR+AkfyZld-wxlJnbq?qB+qv22CXfs3egvN$g z5>m=iik2Ate4xBkW?dTiHxMCq1w3z-Iz76UmP5EC*SAB$z0JF zWrJjgTc0CZWw2|l9IHtdzW2`L#EBPGHz>O*JsfroK-L2Q?QpOCnwnR4zzgJyp$x`o zsvr0iD`KO5$bZ;GrFo*Qy?xA_LWUoDwu?*gQ~Nf8V)x4YJh5h!tbWj7y4{@*^34R^ zm!1bLD6{7t-7AS53e61s{o_pMAzRx~K#PE0fI@2eqR4o%()K={^I2J0@cz69U_y_R zhXCsh*(6&c_IdV$2VW{ZS_cNsg(CJNi{^s7HBi?)j}D(DOVWGPvIh=^x3#hl{|>)NW2gq`B|0W( zmmpDz4!zHSbh6gZ`<2;a*Vt3SxBI&Ze*)&TVP*QzD8I3^4P?(1#CC^%Lko*&XS-YN zcI#*CoVNO~o)AduJ4&A1W%%VF8KG{YJ3LyeM9(;P^`QOr0ak^hZ#5p8QczMFo$>0x zmHit3+@YM$+@2sq3?*j z;&lQ@Z?)=Ioe@hHGcz@xMyy#N_5oKE z78LBeejqHS_h|Fl#M6w<%#ciW@F=CGX^Dwp{A}J*s2)2MSKy9S82vo3`ssx5k*cp_jZWV@>E>;HUcbCRBYX(cYj zi{eLhzb4QK{ibWLq9wSrSS71oV?Wy0|9v(_Mj`UXO8jO5!DIYz)%~dSan;&8G6E(v zi=lu8%ioz_D&2q{e=hTkc3DsQvSqbcNr z>HT-8*MZD?_H0JK`NXNZ8-$O^y=)(TbK4NF{J;uPM44iM&x{?7fw~zX@4h*YpU}=A5V$B#?>YJR zbk5Z=-PnGBY4d?W^XsW_qDO!3i{Yyzi=ut|nh)EA;H*k~vp)Pfc-WkRAmhQlrDo%@ zNLEgEsP%Y+vt0$>P`Mp}5cS`)^{#HzJMeo~PCIBQpI4(z3qI0&g*m)-S4`8&9>xb? z)0AQpHLfWMLhK}{>a`Y^QoQGsy|_y1k$mIMEn1J~3up<1)CBG3m$}6^U%KsD;}#O` z-2Y{(k0M>>A0~G8_~hh?w_c8b{ap;v7X5gWrqR@(HTZGLg~z$nr)onABW19LFX8U5$oCEI05SD(rmKg?MkZHS|VaK6NZYr^3;+d;;S zUT_N?fQd~IH%ANxp%QKLuH}M9kE&gUuI?@}041u%4^t1>n37+7H~PCpie@gn^*4Vu z&x6`92FpM^>PE)?I~RS@KZpKV3Iq%M4lG5xed)(vKf2QT5T1mDgf4pTJ9B1$ zeXnW7yrL&uRO)QJBKtS=gyX`kolp56HxOkjS2@Ji=o=WI_zVp8-zav@QH$-!`oZQC&Ek_VGR`*tr^6E|8q|1TXE_B8 zz_MTA31RQ;J@AbIYA59`pn%B@{=(bxg2sr>ls?xo=zl8!PG(=ZPR#t?Tbdu5;{Zf6 zlrcUnNdN~?ST+4vNmyFC%TA`37f3!Ax~Ga>)2T1c7OOx_>;1U%LeS7fv0WAlZvz0qJew<~ zicZHvKp_!~Jii{O2w|Cec-%<7&>L&+6YqBk3O490mROdU003|8_kDEq0}N)XtRoLu zpF8(p%F@n`L~7_K5h&ljeOsnd{iCo7jjaiDL!h;X>O;5B7|%pfOCsoPx`@F1eAb8j@qK|85{-3rbUYU5Jqd)2N}1O;L-eY0 zov$%w+8ny8L4xeVdHT^>=PhVg!G9M&2-7Fnpi_WK3qMZJGyVXajqXkQ-Me41k8N9K z+eN)8L~juc?7pWL-1_S2D6bjiM@2@uYaG>yvnV1pUY50<1_cG7IlGIq7a>hfuIxa5 z+_guK_7oVMo{{8JFaoa*JV4_RJx}A>K_UmiMV)PCqC4jPVj$*(o_nMC+N*>K1iKx- z?Gm1rM68A1*SndzPr)sgE>sWGNMuI0gh}!Pq+vZM2G|h96UT@>2yxHRb-@?1Id_is zs)SWT7&2gBRjV>lNu72$+M)N~+rQNDlN35DcZ}@-BZWpSeyxcK$K{}+T;wH*>LnvT ze)Q!T?l!i_1Ra|4+JPHBopv%vpy^L?5ndg?)%e&TS$%b_GlU*J;OgC*2tgrTcXbcx z9Uwbsmh(#b{e!(}-^^pjZdppK0v86pZus|-W?m&w2~IoLd_Xt1vPlK!0oDD=RQUiX zB^sL8(SLve{cMn9TF@jV`hcjR;kuXCpm1L&N;S|r6w?@3ADRxCDnIzYD*Fz2EZg_} zr;U)+plqRx%1ZWlWMx!B$|x#Z!!Dx;DIuhY?2?hnC@Uo)*(+Pi-lL)9f86x0@9+JM z|MPi2@2BEpI7A9_Mi~QC+^;`TP0u-`P2sTb5&ky=?3nG$5l zyU0lg>iepRSf(QA(yQX^BkeVDVwpLvQp}#me?f~r;65T)C~7#Jz3q1(m0&i*l4z1m zJ!aQ;%>6?B+PXWDg(alkGP}TmMNCkUF3H!`Y~}9VW*ST?gVwqR=v9N59tPc}+h)*q zk+QxA<#*~xU&$sX={NROi&@f*N0CV07qQ_acKV*(=cjxh^*s7|FhRyG*I!eL-z0ZI zlHRz`HT2Ml1x-5Np}d((t55CRWZk`L3rh&$@^|#ZNh26O_O|>wgnbIA+^Dd%8i3 zy(cd2340Scx$-i!8?1A#+4HPph|%Vok6F&0c}nS`IUMkt*?s)?ucF|H)FgQnTNs_C zS8eu?E?DTc`^+d)s;eiq78TAtDe&q-Mh_{W9iI`Ok~WSG=rMg}3{_}9*mT`xPpqcj zi%+n3?nS=*@&&dFbpqeZbO^f1JUB_MjdSFoX}^*6mfm*F}rl=EqXpyj39hLF&iW}zv*gp=Wssw>t9J{jrOe#5RnwTwhkrDFI|7aJrN7$Cx*Ash3_ zIMn~f`~H{cVdiQFvk|4qJMzOQLZcq>Xw-2x@)Dchu>~TY)YX-~%h$kb!Hw;_c!_sF zlVzUYLqIFeNLPFHEbmYL<)pfm92?#+i~O|w1~f=>KNHas36i!$fk>OBSf)`92H==L z-A<363EBCbBX7vOOy~akf^7&`Pm0{eM4Oiggk65zc`d6w{Fcao8k4CtY*aS7Zd^qo zjp=$&oQU|Cm8@7Xakdb=JaoJf;&cfK$05%ST>=d8IfbwS>H;X+;sxnmpcQCQP*i+@ zcuqtFV|pJXokK|va?b0%Hi5fvW`QH+&*M#G1QtrWE+Z_1R|KBo7-%K z1qDADukwx-Od0e__R?g$pXq3^hUOLWg*eK`#-Vx9b7zHKovS>zH5>#;dkncjWk(*` z&9FBM6A&_6ia~}3UF2HY+I?qVT;-sky8Lo%ji;poOk!Gdw=>lsCA3jk zWgMRXH%qMN_wdMt44|as(@bvYJ}D@WT4o-FMMNYwTMy6EAZ#r!FE`D1#6Y9HFu1C! zyKUWqV!|mem+6kM4Y3&h!39vet!qfVO6$dDu>~!6}g+4Zz_-vwagCEn{WFCPYcbSko{<;kCmr#%j z4`=GW{7xB%B8Z=HJ1=iaT$}=v3Kxv~1%q_hG(^#e7q>@flz-ew#%1sqhR>mQk`uGt|1jCJ)6Y7)tMNclYQ2y(ch)h4CpCbGXSl07oIf1u%1p0+xy z(zj~zmIzDG_K3ibrjx9cw6xBr-$$QfAR-THP1|?SII?+Xd-lFIQyJ=S=Coy)$|k&R z+lwt!pWY~$)Ye5U)E#Un-Ie|Rp!-Yzw}Rbi*su?azOY<1SWWU?9l4h|m$S*j=yk!C z;6}2Sawd2OMs`RF%UM<;(8b%4h{wO z`>wu-r+Bm$W)FvhMI>G!b9;pYlikm#y=v=B<02N4`HE5l9S*@~a54-Yr8eeH;G&Y= zTUl5&DY;4M48k133xjJM^x3Fz@0*Ctc^5@b<6o9c9*1T!lVo@yBB>3l)H5=AQ$V!`n*GQf3e!SF73oet+H??3yihYlbUzdL z*2KM^eDW+SE5v0zi6-@yn2+TT?K$rE=cR;xtCP2b9YE_DlC; zxU?^hQ!VXHi`Q!Lc%$dgHrWedCZ=T3MeHHAQo^@g%R|W5M)lVkKiy7_Mf(U-vY56q ziNq71QlT!VlDz*l=a4p;iXpNg{MpQg@dRvN<*jvY+crG7B^Ge`u@5KH?%&oPsVaZ+ zlvnXFD4Mj42khfd`Tc+;&TgBNoBJ;5#KX1Y@lSTyt4Hitki5-v%XACwv$rbAXfv`Z zp`uI7D*^7m#pbt*%1Aw-WF^Lec7qP(-9H_J{`P@;>ss%n3ekTL`7X+`Am;J5fD2E; zk%$g2Vj@*{o;>+F@`zUjD;ZWQ#_O8xVv=68PmrjY5+>))5SGZ>D5K9fAlmi(c|Jt< zr%vIN?^RVTIClF0a@2!I?EAD2@G@;se#Cu3>DVr&3WZ%(0Tsd9abkk&Tnej}k-Ybo zEL`fTuy`AjNQrXvKdg7QN|Y}K}c}}5CCNH(8wH?mYS8Q?gN}cnh4jN zeY(|pbv+|_#zBL7qo1w__gxj{AfSqd(;@r#p;Vh|cO=J%m5He-(^z^B4STc^Z}<=R z*==7f2#6G24BQY!!+<3;upgUuW-B|x8~*U21EG?Ko^MF?p_qV-)}>`NLZ%Xv*LOEt z{j{EtG^8w}A-?0zKIEtThkxC8j&1OaT_pb2*(1E+h{YTo#fDub74oWmq1ok9x;_+d zC*865`K;c*BKm%y`L@^<0`X6wJ@qu|%C;Eod-ayCI7nCk;Hy`!-o2rqrM=ns ziT<|kzGr-l54N4V1EL}c;Ss(%^!3BlwU??UpJEOu5S(p^_4f~??({#dO6QA+c;~BN|9tO`vWf^{-*V;gk5? z#v3za3$EGmfXiH5)bWx^zaz)1j)vz-b6hn(FZ>j!OZuf0x@bo69#X@vYnR(q=AUl( zux+RB2aL@Fl0TKHRD)z)MP=3a_D}ohR$eVbAh@Rr3VHJz5K!Dq_zcxa%>0;RmG$Qj z1lmX#!zXP=4Gk+0Fya+ES1)Y!kt2C378l)RHl0o*{ z>H1Q(>{EuivEi##H)ao?Q|8q>xMWLL#r8cUAAKpQ!sdW?#&QQvB~omo^CFPVu*xJ| z{t&I2>x-Fv1@EcF-IB$-{>13X|88@{atI2J;LyrXWL_NpflfZxmDKT1=~pgO=1=(} z@&05SU^_TF=j}~OA2jC^5LlbXVF8pBwt{sVBNYa|uk697H3YB29{J7IvS&V!ff9LK zxG?mU3RHuwTa&wqJy@~&pKgITG8Ri=^u_*wD_5Ast@Vm@7CwdPbQ8liyWMSS?(Cs4 zT#u*2=nJQSngE>Z;_iC7A(%)5@IXR>pt;F~sG@K!wx{Jxc;Q;h{C&I!L6^ZozO@v? zEEr;KS1M*13SuKXDJ+!f-db^+*cfU778SM+th&wlzbN^2Jv;H0W@{op z{@0&AVDE38An;whMzBNwI8;k+aUUn+15Xrb!1El9_pvz}x@a{>&Nv{L*7L!dmq=3f zCca-npqG-A`|dU<868OF;c{>oN2NNSmhi@YGZ~wDLh#&<`tSSG*_Sd!{PCWvOQ=57 zi-GFrxx}#Zgix+}yz9cZ2^e9Fxjgv$p=U7!{+Ig?7eL_@yks9rCTwvF9fh4_?_ z-m^0Q9>OgC^xqyVk<(qYH59xFbP=KiS6w*qt3hno7nV6jN2_0jYu^KUNf?x+_5L#; zkwYjBsf2~1uiYPw5uYg}{@WuZcEPI05S<{C_a=t^{&4;Oaew@;H<)ddp%hQlGf>j` z%g+46^#1!MBJPzi>E5h=v)g}evA=$b^2=Vjm6w(1q5D!m*Cw)w8iWl{d|fynC$|ox z%Qh<|IA#%gyDBiXDO4mrYty1#xElWe*gZ~i4}d;Ug~y;9AzhrXM?fGgJ^fk$XqTOb z%o?3Q*+N>=n)4L{Kgr=}vj^ywe;tdDVv?XW43dtndbn}VIhBMX;a zUfMIb1;PsaUWNw(!or^5)#yJo5vq;|P)n>Y{L*fNxk#zQt^0N4zJEfGod!99KmTDJ z?>3a@K*Y*3?kIp#Hk8dIC3^v;+}gC9RME`Lb>Xxv9dU4HxnZG+XYseMv4vtGWLhBV=u<*CQ96$-gcn$7|pedmEO608ODCMH0TAiYRY#o?d*gE#=XYxKYq0SQ1PQ?J}`bxmI~YM);?aW&Yw_i;o49kMLKl$W$F3H zz?8j>e@Cw}36?b+zqv%TriR8&e+CsoUb0~&=xS-WLuf=|R+2T;U)yZuFxCgnOu6rS2V1i1Fu6crvln2x^y&kzbux`)I~D0us^2^8sw$Y-@r zJQR0`{HJvoZkNa^U?KuMPc2r?F5kg4hQhR72lxPVNbw{fZbmn^13JgB&d@O!hu~Ws zLN%^A)Cv~9*LqC}Gh!PWhHg;ctR!E8rH5#Uf#|N}#zD|2VRxzjVIL|nv~#=N1>hIZ z9>|jINl>|psYTo5Lu;$UolG!9TD++&VWkj>;RD5aF; zxbA!Z+Af`dI+x5cPs8$G;Gcrs)oO2W`t$^v>XgWY!X8k|E>kqwlb$LbIMC3jBOmnR zhWdXSiX0Vu9WF5GfBHxQe_wyq$o0I~vfmEolKi08r+oV;XFToe%%Xk)XtY?kBkfX? z5kZ{6r>y_ug^?QvVWPcr~H;2d>AW9c6yCtjf`=l&lVj+}UL;ZBI>`NPJSYUpLAsjlN?w{TiR_O@CfJS&8K0f)W3T~AD z&YrsbuipbyhJyaE;7xF8=D~iyOAJrwTHOza8vAfVb9IS;Ae<6Ra&#-UY}GuALX3vm+r zOf0c?DpW$bUY?L*z(wk(8-_+lYmy1UbI?AwEQH(%4;KS(3earP(wy-D86EmYx;1Qd=inyMEA- z#`K`wpZTb}YTEl=?PH;|L{`6)tG#hUu8r4I-!1qA3mw!|{%^?t@A$3X3Q8>c(Xp{L z1$4wUvu<|w{@4tnx^dYs zkEmL;;}Qoy6ICZiFssjtxMphy>C3+Ejl;7TS8v!@u8olg_KFpNM+y9V2{R|YN8&7- zk~$C`gm8GdZd_#J{Fg9^_|1~*KmB#t)()%wfgyr{g8YRDsP;Gjog+g6zU22lS@Npy z&&s4++ncD7j35h++m`YYcrbp+QX|j~I|fXcKM-1@WxWX+VB$!4nK$Pc1~YMUU#WC_N#T&zo+^C2?G-s--c6e;`TWL z<@HJ7SKMY>o7hqO`hps&MhBwE_pD1m#UJMbP>$l?BuPeFOWbtBi2OB`U>A4{c`{_ijceE$^k@)^W}#0-+m z6%e1jVu^9`2%()=8=-IqMuSLdZK*5Fbg&Ce&>_fc#Jcs}{+@%XT`kZGpG%hzNo(;o zB4EJi=&mnd6@iIjFzsf$yU7{EBaLJRm3rl&(4H@qVSGDG3J3PgRyY*I#c_Zt0P%kO zq%9X+=71`kopb%0xSx-jdd<(mcLLV5cYO#tg%}Q-q~xuysw++t#USK%zo1b%DGZ)n z$zkX!Rbq2|Y0gMW@(sY;jQ72_KxW4jhUV&s1%!4N#-8@w2x7J*DIoyk77_|l_i*|+MM?Ef7@>6K-?C{-DqIL!4PF)m?p3ZV z@J>Nr&7Uw@qK}o>Q|-TjXdjI)-MNx*>+W694EKmeSA+dom`3av(mEnECr(ib@smx| z=%ghQ;UW`=jn&|vFy7_mt>75ACm3J?qysYrh6p7U;@xayzsQfzik(YjBTJA=uQBkw z1O6z~ZDFpU<)41tMjHwp`y6ux`0 z41o~Jxj2Fa9U9iw#28vaMEBIGX%t^@XbE@rGo-Qxs+v&T4Nzz2-X1}87^LZEe83{2 z4vet6LpDqs~(M-3W8$9 zt$<%daD{4hZfP9^+Q>n{_T!F}bU!(@4l69?KC^r6{P#b& z00T%IgIL4^T{v@K)ezoca2*TrYj~VNdqvG(Q+Ho(sw|bC%|NdpGP&47&q74yNOy+o z;#Z6-S^KY3X%??H&C<+!tEr>YPr!eRFNLr=6v2Q0h19FPX%TK){QJ58-#>R3uI)Ad zBVc+&w5g-gb$wMu?DOaHQg4~0-bSJJHZ=v>u`Mbdt5&WgK<^2m<)3&k-mARa-(|hi z)X#-3nL?#?JA!43l~BT1x4_pt?KL$uq2s~!YrPtqX}o`A|4Hmlx7Io`y4<%hQR)0L zX?%A`PY-kbP=f8gT%nJRefKUq0m`tRq#^!W-8M0?<78U1(V;`1hli^QLZsYWS5$r! znE8oJyj!7mp|YxUbAW?L=JZdhuGPx?e>@H|S`d$aze=|F>5hE?t|2%5Ry4yX2lXd3 zSdO=3bbuBFqM&PQvmt!2pTEBVQy}8b4z_E3(v`;_UBIYCh(g+9RF;{UnSz4C(W9M= zIx^6raxS;wt3Sp^c?rVJmyrJUXzpm&P)N|#4Q8Q=^(m^HGG(MC2Q*S$(YgBWAoRNC2jbd7)f z_nLyUpEb}YG&Fa87xD^RWYnqn(i#vL51u}KI%AZEifXQ0{@1Y_Bb(UEw5>;A=%EAB zl!n}{$(_0#W5wAoWMz)8lRyt`mh@UyqJ&A>&lF1eSq_4dQ2+q4yCA@XV;Q|K1&J>P z&Ibh`e)B|<4vno$aS0K?Cxy_#LBOv<#>_!rUunZ?Vm<2U_&`rAXtOAm?|2A1gc!Ev z_#;d|a70egu#14Y^BnGWZCb_Z+<+gWU&=-z`pN*Br^hg2m=Gw#+$qRqfRLnCE_nFy zr*W@^g03qAr{@hbT8@?a%}?9r3SxCWlhb^v5{f4?V|nmUF>s$6uHYh>G@TB;FRG_wkcCjqVn-St7S4Xz$Je#jT?Sea*Y!jA9MF$MLD$`1(U&BN8@qIdNW zu#e1a&Ex|Z?WQMB&zcFrnvMDkd=Fb9ba9!O+n01?E!edU-=8d9T8J6NXI==EUz*wT z18pOZI4B^;l+c<2fuTlMpDZXsDIXF&4a=ZO-0TuxI{O4ebp{0_KuE?%jXHHB zxJ|Zyiw^ofFNfn+Co3R7Ko;C~82|pl-a$d31a%Z)yAE2P{1Ge`)U-XVg9-MDc)8VWj5QSBgpb0H6rh7RcrkJLyZB)-))18@q+%ggIBxvW(G&{Q4+fqT62 zWP@p2bug|B5WLU^P0-@*x(}tIMs$8$O<(_J_WNEV8R>zY#M-^X1EPh+kFpyMlx~0$l`srqss1+@t9earu z6#zzjM~*SHPdFj;o&f+1Ceqp{*9^3XqErVv(>lG%kl%In6QgBNrQ8_@3SVKbtt?(Gd0cB3zCqaLERJo?Cs(bgg zxO*$b*IDNfM-+Ml2u;ak-_2=Zd&GL&@HCzn)9R-|o(6=<&;T(OEx49sm@iC=(?bn% zbI@zh0v{fJ(g$Nj7PD$d8q)k(_g*>&P6*!cY5?eivqs~W4OrXHt0ocQrvq`n=g!#? z5fWYt{qhUUau*0Sg0vo4#wFXb`RMh2S}3c8NFb3KmU{i=QHS$RF$%Hg@tuWk=g{wf zo(l2|05OQHsMRKxW(ELc3=G7by3Y;X`#Rczy6Knh^Wz>+lx+@H^dGOlg0gx2JhPvP z(0c_>wEK%|_Sfrb%J-2Gz)Hqwe?=3P4s>4tw1D&1u&f81V3>tu2POu`O~mH11&`Ms zP1{zbFH}!=2qRd#9u-9`_FNJ5gNN8IXc*;9KsZ2*56?9oIK2YXn(%tGRaw36SpV(n zKD1y_U7}mRKF7XGYOuxidVEohfRIqcn6UyG?!Oql;)n@0ARUB}K`@eG_=s!g&X52I zD@P)M)R))9{#?vfkgE9b2R8Wm++W+V3wC7eerlz{v~hS0l>EPp>?r=GaGVS96u)}KiXw5;{-x>6lc}|&?x{h80d3- zOxdk&2>Bom#+QH-)R7#$E#eI^N+-bN!lVk9I}rF3?U?N}%NBhRDeDE@8&-sd*#wBy zx+~Wheq`y|hN~?^kS&iB-SyGcWN_|?%?7@u{_``N<4ZG{p*d%F9+4fh z(S)LHIQDr=Hq0uNOW4U`cpEtGwUtlmOn~LJ1Ge8I+54DoK$5I!db!M0ni_OY-Heo#rpE*L z19ue7+z`76?%@w0NA~Ca&pWjszKsm{`-8H$0to`zA=GbP#4`;kqD( zuz`0=ZbI)4x_BhO^2oi1XFS}VGmJa{&GAks-@pzx%amZGFlKrNfM;v>tbHI$6nH_> z+YzIA6l)raSTQHO@$m^wt|62^ve&{*0r-G=fEpPU1zd^vIy#kIqM`@e_bzRR4O~yl z06Zr9d7(VuTp+kX6BuMt5q|mT8=FF;Zl0-52v3|?efp$R@hEwD{Q|H+!2G895=ym= zpmWs}i2B>(mKEJz3m${sK-Ld=v9UVW!__5k7=8CBvCkyCRXx|L9`)J`eVghP(Cy%0 ztpjW{1VcqUB@P@DE$nU%V-H3)Hcw1g>X^p92-@8pBIiYnGuaW0Gqmd%H^9+|ed_Hg`yU1qi`H?5Jglc{f4vq3GWBsv>d)SoXi?koyzn^7n zfl2MzQ&VRezAsqX1G#g0EN> zpF`_7k2nN`9+i)xfS5V=442*Q@zuCP-WbLZ{_`8q2Eu_8_Jj~L?za&ZRrEK0?@F;X zp-B4&S~F}-?_=9}K}Gvy%^l=TI+*HL|K%q@XPejnTAv?#e!Y*+hoLp&G|^hT)Q#~M zGnLmF`>qyApj#+hE1AU`_yOO7LwWR^0m?Ci&_KqK-Cqrw-_fwixT5q+4v&tusj5q* ztakCsxLqT;G%IG5Q)+}~KND(;3%HDyxgyv?uzb!z@<80Y3NEh@H5kpCf}9CNU>ubb z{6)$EJ2i|?=jPa{Q{_E9Ug+w_-#|xnE~q-~u2rL70D4*2-3Q`_3J~ys>552v zd)J{bG_1`c6#OwWSQ@XZb9r?>1&t#;%Yf7jR)9mG^R=l~GtO-+o)!G~-1qMUO?tH5 z3Eu(F*lTQH{`r#zKV{VTtx@fv#apO0Kmg+iD~fsI)GT8B!ooG><*Gx?I1<=yz2C@= zPd)7m7&I<@k%E+x1wII_+oAbE1e`Kz4yY)@1fGLvXgT(JuXb*a8MvaY?%r*-I8_Ig zlrA~m0)=gO)?T9Of>i>cqs9EoSQjMFY9Sw;ruP7a6r={vu~rzV`JxI~Zo1*4 z1mIopY13c7>L5rMi1(Mn;8skR==EAzT&IBRAa2K>4Qo&+TKI4ca8wj!&GM?J?vKG< zG`xVEfO7$21>iXb!}lzc4}5>U*`cZMF3J{2UeX1u9w7t(AVD+jZ$Y`Zj<`vufq0yx zy`a?)A9wbn#Z7-QQyGS-1B)PLtOG!ch|Mz;BpwsQ8_4AD?rua}!-#a<+`gloZymdw zAnP=yd!aVv-)t%*EnNVD1{?yJiIuerHU;|!(kci((QX$OfO67p^wfX+*jVD#xB5SK z)Rr}7#AT2KJL?^?RQ40;SkgyG;P37T1C*6rRDl5H0sC_lJS!^Htj3Xu+14J((C-k+ zR}EspG*#OIR6Xp*AER|Fav{L>KX-uNV#ds|+hwk_6cd?}KDvx`Zj;3!TKn`q6t9}1ZLnKuh?XnoEk?uepMr|` zU~&<9^}I&=Z`)-z{qreCiub0}}Y>nc^D< zS)P(>{r+Jw;--;?67P)4M(}u8a03^j;m2JD9nP|4K=+Y+jD1_5v;xg@8p$w2PgKr} z(f`LquUi5@EE}+^`0NNFzFfY<#KdHp#oiGnK2vO2_*qTBTDzjFflP?6%QDJ15S|_x zX;A&DZ7`0x^G?nUsoq6+k;q}qJAdRkh6ZQGtb$Lrf2t@z^!nWg&Bt5qwe!?k)eMEcL%i3BUKsh6A=P;iHQfa48>tjX@q9Ej6 z%xr99{r#;lo#@+7Ka!Vuvc&(?lArv;hlS7|y}pJ-^V)e2!lJIP)3x&F-Q1w|01iO@ z^&YrtY%yEuSQKB0vqSQ}u#NDKB0MxVpgCt?>hZZZ3mv|6`!TZ@a_XIWhs`m0JP4%v z9me@HNPHH%DDcM9lrYG36DWZj<=JbIp_!#(T#oXALwoj>08AYj9336~whEPpe|Mb4 zEk0loVn9h!;Wz!vxs8>aW9Y< zFq;|a1OD#yr41WYcKE65;)5W?x|*(|AWa>s@|6OE2zacpUH_*~P3{v2?}S*hu(JvF zMu)g4!9iJc(|J4oaMS$xaQ|d6jPC(W2qIuyRJ632p3?yclt8Cd593u|$IZoM>yilV z_--_g%^IY|Qi@|ijRfEhwK4|1XZe2tPuQ9OoqwcJ<(RtVT$r&vtPyVgeAU}r6TQt)IEod!}#h(cx!ML^G#kIe?+}mVg#$sN06Nn-x16;Y$U{y z++1nRD0TdVOjT;jIgD2V(=wsi8Zm$^U>Dv-;yypeVVNC44M8jYdtXXMG@5czyhONc zdVW-#3r(T!kbWf6j*T#>vq-_Ike!bBT5~gsM?shdR6Kln zqY1^@wcH5=Hs7*w>GFEl!s(ioNtoTpEKJjO=arC<5EswMY((xaY}|{PZlAy)X_AS< z{)L1QM*_F%btu|5%fvxN&$(8Oem}Vh>j7z>f+FmKND0_#o8l<_G>`X}H(JZ}VACO_ z3JG|7@`+>oQ6DCGoY5#9{X>V;H>2L4(~+#V9V!PZ`^7d126LlfD+Z)x7i)*85p=Ss2|jP0m<|1k(gMQGKC=J;7m=hwK~<2@3x>I3l=3JOl(Cgb03cuuI>%#h8LrvWm!N zlu^7vCP$tDVDm0Ed@K@&r4hOR6y>llogf!tds2g2F*DY69`=q9 zH^j6tCMp%&nd9?k#3mI#6}ocOD)r3>;&PM4n?L8Sd0MkU%7h>=Bn6=t&Z@NR1FPfS zc-?EnT(62yWUxIr(TibM&yLR^emD&g7#T_ym}@cetwCw&yT6vwQIX!U;M`(x252rY zHJ$L+V3WWk+}P5+QRny(H&B}*ZrpfTSl98)b@I4zfoVa>s z&W}A)ZO=;fXw8Nw18yq6pCy~<-_N}IOYX;rs8u4CsbO{E2SVqXSi8edQry{|LB^#a zxeE1^apX>V?tLW}S7;Y=EZ&)ShZzz@TL6Th;4s#MMhlidj+8bTL5$M{AvSsd0fzaT zyC5S8##Qx-8Ta`BdTyYaWq_(`XbkQm#KWOZ@0*4<17N_Nu+ZAwrK+-j_6+GchaiVF zh44_q4UQN|wVOAhF0nmfSVgTaR3FYAUb3HCOP~9KV(@B1Ce{X-;^d1b-FSAr4bM)O zIl=V((yj0~3QDRs!^;b#YuUfL^^KGkXCbMRUeQx)T3XZD)^lOq&hz6nos%;&Nvaxx z`aiKSs8<2m)6mq+X?8PZy_R%GootfF@DlRULbZ~5BglBIj=3FoX zLsU{)&Y6^&Y6S=bAa0ZmECwr5v9Fk;Dsr_c;{<58h=wor9Z~~W2h^C$*yPE{AZWU) zTwO;+m9Q3{m*OJ+*yzZS-L~%(BGHI%*>GkVDWD3t?Z~fF=xlr~M!9xvVuw6H8ja+J zhV@iimWwei{>LtYKV)x3?=v4_z!~-`G^&f6I#^nUsPT+EkAWzvFb#MSdksJ*R-2w} zX=%YeuRDa1M4$}dY=bKa0C0pBE#;Z|Y2ruft3vUEYype$dsl;knoTqvHu3mwk#@f3 z5vrZ2O>rB*x$(r;ufbQZ0@QK^bo9;#8hje3PTl)nrV}f3o9@Hs&&i_i;TsyyZ>HoF zxh;qp1u*w$Q8ayQK`G6bk5)@f&8szin6|fCdb$gn$;QTp#^J)xZ)fr!#l&D}y5Sa0{0(3gantd>Kz;qunEQzd70jJ4-`9KhC0_S1Xc&X^y{au*@j#uI$P>apXvJaPYdWvzRS-VZH9bgNbg| zjZM$J7SL~F?tFIS-LCdmb1`c|SG%HswQR-e0h@@>(E875tX1?@-XpuMR~w$9({Nly zbsGO?K7cds@pH1=DVGI%*V9wZ^s`e{-?Ax&%QUszcaFhOxtg2NZQrpYc>bX~B3@w| z8fv9o)M!xGxg$CGM&KdX<1Z^K)wf4zM~Q6%09jag^c3??S|y}4m7mW(J8EKT`cOX& z*c%HAi05wxnEf@fgw9ql{`t|DwVL|T!s&2l+d#f)H z{gMf7md%^dk7WDKjn3Fxe&Oen#6)gmls_wQH14IO6r&jk3?ADwWU#@JR6(5iBxXN! z9YPqrx!LKCCm}JGTw#Ajpk!pkc18UDk%KpKo}bR4J9DC9=f1;-Z%0ROHXa@uV_Uy| z7AYKV4#xaW*CB|i>{!oI>PI}t>RRqjGd#%N=a9a%vl~TK2|(GYVaPniZN`WL8JRnt z-vF#Ss;c^bk$?ph78Z7lh8vukZ9&wQ@PnF~8UbR;Np&RHNjlvF9eLwO5*;PR2L`~Q zVVC!m>G=Lgy@ehhYmH5 z{&@WL#6aOm9yH}-Cf7c$3kMoUM^|D}V?JHu6R_NZU0m9IWrwFmT;LitFquw%{ zODYcF$92CePeOZx^N$TJoS7t=#9IF|=gvKuLfw`S1PUo0fY@S7OG+0(G;{O;)xv&l z?^UhkVtiEbF{+X!zc2IF_QA-XP>7b2=D}7=DQJk5vOo+)-niMB?G-~W4D!I$@xtlrHC@Qb8fl2q zggNb<9mgp{>Tez1vwL@BRlJd3z;dzPa(1umyga@I`DCBwfUU~T7S^bzOSzoKq^$fG zfV!_q+IJhuE1XN9>vemj_eE;mqB~Xi26a0hA0J9iAt52?HjNBps|)C-$5o+@!@TRb zZ?Wthc`rE;ktw*_y~XBW{|>bF1qB6BT~<2plbAlu?#v9&PE)4Pw%Su!0^X)8;$NKz^3LgAN(fpXsB zh@qjH>D!8mxQEwRrS*S|3H5pPm|RZEug$ zAZGjnWy{Uowa`@?xS2b@`bgoj$0)c17Pd;m*5N)fsUo;c_(<-xViN;{uZXc$uUT^* z+8)x<=zb>{DX_#_f_rR_Q|hv_q(h;-xsSV%H;|f7D~fDdc;Wlw;;zSG1wBRQTkmuC zUx`@pX&14l_gzw4q$APgA+B%Kc@MZPBO?PF7yvQGH*|C?;FwEA*VU{5;G-YIO6>tu zZ*ax6k4v%hP&{Z5U~rWKGb0$&ChP)C8wjwAap*3e3| zhH?K&NxOD2r2sM)Gv-a#Z{5B<@FAbqZ4IVnLyn){tas<`22~0%($$AR=%5VVi?NWP=h z*|SqvAOO;3#cT`=$8*+%Suv=1OI6?56Gn&GiVh7F*SAv0mx2u%FfZQ7JbuKXsBG-T zx3!$#kN@Yzk;joyC%1A-N=nx0d_puNdfJ7$!|fYZP_nQK;5#S)S}{dCkf)=l!}5et z(TR<`(JWGtpPl_K5{lsqFY}!!WJ>z_PCENQSf@IaH$nrv2U<)u&X0Z$~1+Hu6~#%00N1l51Oo6TJ)U{oj*@(m6(w`L(cXNnpsBPGJ84iPX~k& zjvO!97tjb4JFf`Z+-ixF((5qjGo^Sx#xP*8rX4}~21|gb?suXF>gbpq7RKn|fx;?R zK5H<8fj2xjayT3TsC~4cs9==_d4}q-I}wz7O4{3vo*fmAtip`o`{(W=4v(Y3{D1?g zVmUk}6nhlx(Bl9NK@RlR`EEM*F%~ykik8mYTvR3CTtH-WCJdZ`v$M0v?Q5Au(7UW$ zQ@bW@RfPeQl63H<6$ni6s$&$}y*qfzo*SN9#=lVZWKZ{^Ny~ct(X(f_J@y_rdGciB z`P109ZT9L$Mp5sLDKn-y@=1r`i+1e_&BbhE@l-apE4yKJF&q-qK07qcsf1~KxcYQC zh9AU54@S3?^I}87?8L;xTtT~QB)~=OyK*tVT(N11-*j4@A2oxlFKQmC5;D8sdS)?XJ7yQmO`rleiY#x`t;j zkTVbNeh0&gdfG`nzUBIBv(PC3op0pDbIu4+_T8ldVbavV;FR^DT(0{)3h18AuWN6& z#$S)8kyZwQ)V>68%3 z0{k<>`(JV@=&!r_QjIoOn7BHUf*2&G29|f2x4xFMPtVV9XA!?bl}Cco3ovdZx}8l; zuWFb(FB@f~ti>f4MhM7sE(i5QcY6eOO14)Tu!nBPT3kp3$n*NY#r= zmYHP!D6DMk-6Nl4n?`9s*M11G2f}_HJJr8xLmp|6gNc)en_Icx9_YKdJL6$BHHw%m z5AJ=~(2IC~@FkE8r`$PU9|IhEU}4s>m5DCs5Y=&_aQG0A`_AiE3#r^Gq03%=k2E9@-il10rg!9!oK*G^SmXzm%xmaHc zpUJ!}7b=0&j8rxOBLd?Sh|tKTT#WVsU?s{E%^Xr|jtg`yM>xP+7opTj!(dSAWud~IXys`0gH^BxAv~Q z&hE9;)aXD@v(sG9Yrl+^S%e3zCA2#;AhCrc6wEmGUB}6o3jr7&Y0bb%w7VzP3J$+` zx(ZhVWij<1Mabe&*aML%veJU6OQKSQVGCV?OFell^87X;(>k|~-Fo>_Nl6Xi3(!)_ z=7v>1=lt+aBz-7Y&Vi=wg@g+xR7a;4^_feTmb)wJVtkJ@Tl>QU$@&gFOo(e#j?5OeL{r2z??oTh9WNn2`;5)7=ft+~g-u!j8yZpg#+{ zasjwEEQwUKq_p&@6DJ_;XFofk(z{HAx>Vaq?AXhd_6~Md%WJbxN$eT<2KGD7S!dw; z(B|czwo)yNRn5OF5WjdC`$SP0A{Z8E3@2ny)YU6ti%^|MPzrS>^W(>Pbz*I6lnc(U zpk3D9)@Fy%&Y(IVmleiG?%44hOl6c9fW3k#)<%#hO3wATv)Mnth;lLJS2}BJ*8ogL zQScoJN`#>yAsk_q>0TVUFTd;DGFh$SK3U`{XwQre(Jw%}u(qJufPdyO(R*tIHHtjP U+eYm>YKY%eSJ5VCDw$pSfAUjWod5s; literal 0 HcmV?d00001 diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 72482a1c..abcc3576 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -136,12 +136,12 @@ grid(col ='grey') lines(rep(0, Lmember), lwd = 1, col = 'black') #Plotting boxplot for good members -igood = which(rmsss > 0.1) -rmsss_m_goods = RMSSS(var_exp = array(apply(nao_exp_n[igood,], MARGIN = 2, FUN = mean), dim = c(1,11)), +isel = which(rmsss > 0.1) +rmsss_m_sel = RMSSS(var_exp = array(apply(nao_exp_n[isel, ], MARGIN = 2, FUN = mean), dim = c(1,11)), var_obs = nao_obs_n, pval = F) -PlotBoxWhisker(nao_exp_n[igood,], nao_obs_n, - toptitle = sprintf('NAO index, selected-members (RMSSS=%1.2f)', rmsss_m_goods), +PlotBoxWhisker(nao_exp_n[isel, ], nao_obs_n, + toptitle = sprintf('NAO index, selected-members (RMSSS=%1.2f)', rmsss_m_sel), monini = 12, yearini = 1981, freq = 1, drawleg = F, fileout = NULL) legend(x = 4.95, y = 2.4, c('EUROSIP', 'EraInterim'), @@ -239,10 +239,10 @@ Uncertainty = 0.248. For the ensemble with the selected members, the results are: Total BS = 0.136, Reliability = 0.015, -Resolution = 0.126, +Resolution = 0.127, Uncertainty = 0.248. -As expected, the slected-members ensemble presents a clearly better Brier Score (lower value). While the uncertainty is obviously the same for the two cases, since the observations to compare with are the same, the reliability and resolution scores are better for the second case. Specially the resolution scores much better in the selected-member ensemble due to the agreement of all the members in correctly detecting positive and negative NAO events. +As expected, the selected-members ensemble presents a better Brier Score (lower value). The uncertainty is obviously the same for the two cases, since the observations to compare with are the same. As expected from the RMSSS results, the reliability is much better (lower) for the second case since the prediction probabilities are much closer to the NAO ocurrence distribution than for the all-members ensemble prediction (see right plot in the figure above). However, the resolution scores are not that different. This is due to the fact than although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence or not of the NAO event. The all-members ensemble instead, although with a higher RMSSS/reliability tends to predict better the occurrence of positive/negative NAO events (left plot). ### 6-Appendix: Forecast scores ranges -- GitLab From 48053ea7226a466ba6456e6f6057f4d7f4a356ef Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 16:58:54 +0100 Subject: [PATCH 11/61] More edits 2 --- vignettes/RMSSSforNAOprediction.png | Bin 84060 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 vignettes/RMSSSforNAOprediction.png diff --git a/vignettes/RMSSSforNAOprediction.png b/vignettes/RMSSSforNAOprediction.png deleted file mode 100644 index e472047cdb29889b874d4b25a5882c04b6682772..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84060 zcmdSBhdbB*`!=p3t58<5lZdqJ9hI4pq!5y1uLzliQb;l@Sw+a66(MB{S!EN-dPzq1 zxX;)7{r&vz&wU*C?+>_N$I+4fdOjbI>v3J@b)M(-e5kFdyqju26$uH+ZdH{tIwT}J zkC2dTx1rdMudF{gGLHW!9aZ$5Nl0iu6aQ_ibx6BTLc&F&dPYIl{RN@l?FvKfmi!;d z5|@C}3TMw$?+ofXvFB00Wz~RSWw_&_-tsg4=-eo3vvpk-5Q^MZO)naLJ(REOIo`bB`i4^bu&+C-tjhgKLd_wY6 zjx^~%pPX`~P~7%EpWGqP1rV?NpI0|G1=)W-&Oc2@yvKiD*8{m2{_}AijROCFJ`Q8| z)BexLT+;vVzX7$`C6Y}owSQjss2KbD`?IpLw&=~b4armSu@Uc-|B^(g=jy`5)c2f= z0#PwBF*@lY!h#B~SVox0H_Dt#Z+!}&q%yL#vx^nA5%X9Wmv;O8AciY`u&L?Mh{WuR zA3uH!KdXJjTH74)?3tw7@4lWQo6`61JJT=JHa0fa)YN?b{OV$cp8w9>&*gnLBlxsL z?1J+etaWsC3vV<%|M>9~A0MBfprD1tn5^ewqzm`Vc2-ta4;eN&udc4n!;g;|l~noI zeXYb#wX84?jP@y|&!1tlD1}%5igZw=wDH=KCddI<9H zoX&MLi|V|F`0=}EJMck&Yj}pHcw1f4>A(=9xViD+>R`g%$Y;;22>T}zb<%s@I<$Ou z{qgDEg7*u@T}P;YHjLChwrGj(f9GVDqGM%eXY@+x5$ZQizHXRfoH*RpowwQ9FkMnSzVEiK>mIiu8yY`$mj7qzyOobSlgcmAGj zBoOr`nYA}rmA)h_Ue+_Z@SVuBXU}YZ`Y!(n%-5gs)ogk$I$=z;d$*{bsF=gR7awD- zc$vfgQNvuVXZ~bP8NEB5#HZ!vwnQM zWU2NR+f@sTTYkM0$H&W?qF-=BN^oR&IN!csYF4%PUG?rg?CeGrKHfzc!otFaB`)a! zozq=;pR23SPM@6W%t)OOe|siHZjB)9qZ4sRBPb~7psj?Tc1fIslb?}a&uuZ=E-vFs z{Ux`mo!dMWqtrUHjihC#=olCxqoU5n*k@c5M8uZQ4PV(!aJ$n53@uNpI%g-`0F=;+Kc{WKqO{lHH z*EjBbZa@I3p`oGA=3cU-YuBzV{}o^eYK%EHW%7spAcf){#Y37e(p;PI&F5lv0-ImA z*5|dRqv{(QSx;Vn@NK?nOWd|A_rr$|d+m<+Y5!#L)0R-F8YtrG2xdOU#>Te%$f(>) zQaU|ZfnV{#`}ZqZhHty>rR`QkdQrX-@#&MIw6yf>7eB6!uSuu>=CoKOcpsu@+V}R| z_4@jH4i1icl5-r@}-T1C-SabI6w zPEJl|XJ=OqeCSGPEx*rcTwGN2;`ED!cx}g64T`+tV*78I-O8Na3=9mTzkVHhD&@WE zQbIfd2LuFyg#LD3GKrIP{)Hp5SDr88K3AmXRu-48o*vW2iOpZJ4qd7eKk8gQ-970# zTDNEV65sCqB6aokPt48>L0Y_=qUUy`S_%?kkIj8{Y1hbz z;rn!?6*4k1a;xL7qJ<3ecS~nxWpT=SB#&)RkoByQ8!gDqwd^Uh8Z7tjE;zt_eX=9{ ze#}dwk+>HxkYLnHre|E}8v6RKOv~V`q#Korm9}@+CG>pOWm}bX|C87wIU)O_@4a*P z(%QnrXCEJ2IZlW3&6_WUb~l=?jIjODhHQGf;UyZ>T6B#%l#*!0O6a!itB% z<;x#D{szSb(1)JmW8)_#0Apk01>u`+ZnV_YvB)0StSX;(^S_!R%+4!^vYGOAW*NG* zC9C4(Sa+oDSt}n3Js>PRU+GVd@3P2xh}i9@7PO+9Oz_=IGIy%^rpOj>Ab^ydJb1)^ zl|1Q2OT3WrA?~Vg-}KZoRGn_#k-9bMg&Z7n)F|lDqcWF?wjf5q$<7SErxxEb^;aDT z_jj|Fd)kaO$E`ApkPcIODAG}pKkSlb3@Gtl6YJNR)hghk;2mH@;>pc*tPN%NOHC$p zzI)BpvAMBErfyi~QAFIBj*?qbU8;I|dX3RS>gwtvslUd?I3;f;Ys88XWJGPgCCeYJ z5jxt9V<&WEb8DZ|=Rn%jjh@YwG0vXm2a%)Ogks5BzJFipF0fc%tFEq2N=kAGfBRP4 z(AO%3L*C~cj|-}e;KVN;iWH8rj8UTx?oTwY4dz_TVDc8C*zno-`+a?_^UXywf0~8( zu#FEQ&|0Yi4HB!YHHha^9=6 zwVapIb*dX0-l#NW&R995mG?i;&d;W^CU}vPP*>Ez<`SwQeJUKv0ZOR z^j`T}2`9~imidYj6R*~Uu=q)K7WWFs)0upw|2I3Qb1`V_eWT5fRTFsnMwsF(^4Np8 zd4#>oUeauI7Ct!fW7%ML%Z+zscG3CIN;;4GZkCqJ=P4&%+gX) zK^2TO0vXZKnc|2W#<*$ZXcUugA{Ny_j7!tKe3$c=Ux#}0drWp57AhLvSf6ise*Z2l z71dsG_H$}#ZQ&I)4Gq?neq_T%SKi;e=Uv=_urVmIjvBi0II9hZ)pKE-`)C({hsI$e zGW))Fl}s`>M;|QzZp5!4H-67Cxg-!Ze9L>GRe4zM5O2?|6k~D)y2+f1O`YC^_26UW z+MYZ{FB@3hpH2@}Bs3rK+4QH^OiyrhU-i8RB-b4rkISWEs=i>Wv6l(i`3M1C~v1Ea)Z)-30_&KCSrc&K52+14ee~ z17)5CDTNl1TcZ(LUC+pO?Moc1v8Hrh7;hc<{C1h7@9)%i<&b?pe*QGKvzs0nX)p71 z6MF0`5h}>fe;H^7@GT=FIXN>iCO#{Zor2!O)RK~tHs3NQ+ES>u=;}H%%EyO6R5gwRw%Wv{H0XzK)296ao*2hKAzE+`W6(pPZJ4mXBCIH z&7%~;AJwq$W|(F8^XIGFBct^Z0#TFSO?>UT^LZ=EHa9m1eb($eJf!5e=Eqw2G@e(< zUs(9_$MSo2Kk}NWY!H9zjfV5|PIPb5(kziIgbWHDU0sU{3T(b6R%YrKShCW6e(N_P zQOvt%t3BfB)8&cOgl}o*dAPXl#9ipQbUF*@X|=RFMV)ze7wXHeFV8+VuK;zmtJ>1N z(MeHTU^>RnuaZj#Wa6XK5-;1${%L0tso>r-QfbIhc?Hwm1*tejA&+KJ*Df8uwXyn_ zFj***oJ`uXvT!b(D~rKl>RVQ!t?KCk3dQu=(3)%Ll+xY4j3xML=9F|r-z3O(YRPXT zFUC6p+%9M!G8C30fR9!p-dc)=T+|ct_S1g&@ZqpD|A|U}jY^HUq2zR7DK3iR!7Hn) z`LTLvdl(p!3&Qm&GL3YVq*HY5uQ3$GU( zYI-3V5qF`5i-GlO7WM(DoVBAkH`je*wJ1^L=FO9_6|Vp-dpw;jZrsqzy!@ou;l_>E zVpUC8Q0+|>oYg{FfrqBOM837G>ck?(JX*dF>=Rn{yN{>^xMJw z!9)|^ji|UJGZr?hQ*S3Q*_b+x@zPc=qPAt%H3w--(7tu7L+PW!E1V# zt(KRUH&32-yQp=?Rq~@>Pke0JeMQV4Y%BHpDNrwR$13fzn z(+z)Zzw9Q0@ID2)pk^y`^Xi)G5#izEw(2oQI~fA5nX#PtyzeVpZQ1Sl8#MmKUryRP z)$bR#KX*y$=BP?#2T)jUk(4XpX)~G6Y&EmXCd$mD{%)%jcbxtOj;7k$)H6m5djfPu zR{u^B^pzYh=aN?u1N2z?6m2i_5{irU45gWwS$E?#PR@kgtYVf_*?;!d(1^Dujn_pZ@P6`9F^ziw_GH22Qvww#WQEFmZQ~8*WI>ln{7IZCC;Ab+-SY6 zX95+Yzz6qPzv#W<=h6({+5@@({l|O=hk#jl%2vUQOmE1S_yJ~ z2hRu@7K>c}2QhSKu9S&*E&m~c>CWTA!e+g@RntCj2kI**Y-9I2)5rYyGo|uXWgce-)6vJhYdW;XGxsyb#MZ-MH8p~_U+q*%dHn)pZl>Hmk|7bBf*jFtzEB}>-`qFwR09l zWV72fmJ+sm>`VgEdd0h2zSrPIOjuar#L*bK15Xb=ICe%!Dc|IFQP(ULc%`8}BHgj+ zUFkmQ@tb}+`iTC^GW!5J5E}~Llfvy8v>H=+?Cu^ue7I0F@DL3R4Z6_Lu>_gh`Je%Y zUWua-78mCfwT`?Sbz+pORr8PF>!0bS!0?3WX;BTvkhlY;!avgY3 z^K~I@uq^ABXTpIRXO&MMZ!6z#@KyN&)jdBkCbNlufRF8ggDE=oN-?AgY4Tg^5u2XB z`y{0d&zvFk-olxA?x%g?#0lG1e}Pq_($?NM1*_|odE6?|nI-!Iq}~14YUy{s6my;N zncdg|ad9_b%18S}^NWg#3JT`u=VRr(OO{P@3w3l6B9^ltem2Cn;%LwkKVLTl&mnLr z`%ANShMrKRk435vz&bLN^j1$#&+|j&1lg`o6>x(6U-o_h^$11)q?bxwn zV(lcm%3jTr*#7G=EPMAV=4?M^RB~{|4>LfVOH~%H%()a+>eW))(Le!amHop+oR@mEjl6~ zBgm`^TSTc<*D(9}`;(=R?nyxozGzX@owK8Lf5UYI$V-r=z@$eXsDTcn;t-{b@7kk? zP3r^5D|&KdaV`GIlS(B{2CB0aJ{!N9V#QqvmlaOEm~PluUvVx@a*7hTm|swUs^j3g zsWb5)COrJp=5dgSpdP*F>iKX*bfj)OX*q0%l&n@<4j$9~D*430ucy?_LE&dCFkXCT z(O5wE6_$GPhnmACClnu`G0HM161g>1TwJUt9d+ndbn&yB9cSnQUIMl0ytOx~j78ZX zw4bc!Wbzcd8fz5smV2L-$!?*xwl+(d6m%)pW34O!4Gj$?s3b#FuJz%(1Q|arT{X3! z9?4XVSS4|xW5={E&;^aWJAC1FZU)ZWOi$5NTZ(#1f_zSkyC|B>-QFP@6wjpHvah~L zw3$Z2zI8NAgIyYl4#j2f9#2ot%JTwQ41YJ42HU&!a*VUKepO5<@K2YxOdR;l`la~~ z`gVDr^{1Qa?Ud~Sj+|b9wk^#h?(oz~(@Ec49-$T5=m5chlCcgd@?mW8{*25+27cPM zW}4{SoTlQ#!sw*@V`7-SP5$t7ygW-S8(6ECu8XyPNk;bQ{6zuAwIis@jO%NIUh})B zeUI+juKLv|y1eCegk|5myu|&)FULuFEjzBtdCKI@IJ3pX#x@q)e;o_qp&+5u`Iz5C zy1u^N)yT8R!{bodV0Fl!cKq`XlmW`;G6koZ zD14R?w`?pd^$yEu2db0E#mYY}P8{0O{1f@~X({;?`F!^LZ^kNe*ZrD zd!D}%Wv{y^ciZ^z@HMgiq(_f-Pj?-?{Yu1Js*TBg>9m z&?>5Cgm4qX^=k{-hZR14D=RC2b;fgX!WJ}JrYWyq=ga2@tW2u*5)lZE;>8@}IJroV zmARCw%fgE~3Uf*P60A6Fn(;EXkvJ}8U-@zDN3yqQ;nmMeV2UqEKSqXsoM%=`b<~O! zy~_&a^7yOA5I(l`qZ&CNGTuNHvQ24oPwUKa+spsKn$y`P_l2&La8iTCio z%gqflYMlGoNEQsv!uGoU^eg*qi=VWpsi}hjX;>}?l{o&`9;a-VN~Zz3sjjgxnA20` zPTbghi~OZ@-9q1EvUe=cc>^oF_~of+tf|>N=({EBG+c!a+w#r1pAAu+G@jQp^RFRr z37r)^3`u?}RcIepmdNB4S07)m97v;Yb==WcA*_)*ZAm&eH}~@8OP{rAaT600DS1!d zef##Q3^G5yyPuhP>9e6>v2D^!L9M_0t1eDq?`#gzZCsU|GQGjZVGoDUgV-v_ksP%9 z9%aui(P|#O9DVG>i6?PCe)pG#3m#iJPJiUMoSZQ+<)-N9@x_^RBB!@485UYrR_N>M zRxK_idCxY?oodr}78`3#P4E%mH^!Ic;!`X_+N8*DZZ$WY>8PgeD(2(#SvE~S7G#&D zM3D|WVQD%3^n_Uzd3f|8*8Aj1*f7QnS*^Mx3x#U}6Hn>bh>_>zm_)^HW2f<7^+maqMm zE)mht->=RP@W!NKGyOtp)q9^R1%3~sACr>}EhgI9r=*Xbi<63K-ybk+^v==rhy}FlQo4T* zKD8@8oW%f%>a0bYQE73rnhu5H1ect5!3Dq;=TNKHjgS9EJb$icF_du2rh@N!N=gbK zsP)R+PiSfksoiGM-O&m8GC~SzP&>Y=TIckWxgC1$6Hw(XE@C>vzezp^DPe#a=P z`QC)PWa1pa_Aev42E>OKE7)q${}h-{EXg7*Ygir#y)*XfSAGSxpS`G`=51Z8M-OTr z_89I_+`fG~dPzuL=^sAG6rJ7G&0mxdI!cy5kwI3=>VWpsq^$Z^OWWRmOEqPzw9cJS z=L5@(^t(C*-sv&3ogK~_+tvL=C+Fev28!40fMMP>GHKcb?fS6OPh?pO9R`g*C{dd1 zo`z7O!ki)|D0yivS{s_9?G3|t35v7xXT#p|*)0+pOwy)yDb50J0ZCQ3&klohDu}DT zeER;b)()qnkYIIcMMegO+?iljsdQZdSGR|~QV%FU5sB`XW@m1gn}eMQj#H!0P#3KJ z7QwNlsi`R?sQT=Q+fxZGM?Jl7)xpfMVs>g{&!ld>;X3hjUs=h|V{SzGbt^-gzso6j z;Rk`xht3Vi;LMpb2YGqzdI}%z_S0niShn#WF96UOTXg4P9v=Vl8?VHk4>0tlY1?M_ zOp`L-_Gtd%)Q7ehr27e%@vneOgQadc@7`VZ)OT&~2yL28;IaE&uVJTt9xU$aDq^2E z>+$Pnf91bWa6`;lr-m>ilzw7DM&idl<7k!DHzn`hxe&UZFpbd%aLW6AERx+jYFU;$oUMx4e8pGnc!) zZi*VCf&-7@gVNG9Fx4H|ntsrHC^Tsh)YQyJZ2{*2U(lPDT&t$43^X57dZ=p5)vKp@ zJdw%)s9}EaT8m1GG0SP1y_AIs=l@C$Mt=*mbl0fr_|5NnPD`;4*->S}j;yyeD*R99 z*U*jIZ38creL<+=R0|3Sw8`~)&Xg&e%=f?O=4)8pwfo$&*jREhG7U5-Adx|*df^Al zz1I{^pYFao_$|wj?6g;O#IQ#`Xc1qUuEjGD>tq)9o=@ndUo0J(nksdf(0Tr#y}9`} zSUuAbjVDi@+>d<8Kt(3o*4EzMJ>%zUt@Ow{25f(kZTC$m@(YrNxK~}>$R2gyAfKu5 z@Nf=j5HpmlB9@7Vk5}@kCT)Sf(EfTSn(mspxhS|jKfmoge(Wdg7-x@Hp z86FxsHQ!0;aelUIR$7(v6^V7;dk03Ud+w~A+4i^-yptK9s8w4sc=gK4%EiS+(BsT8 z=+2tp9WW`7T-hv5o|bygd+1R9bo_Yig6N>rD=$4`>KBfMk)1a`J^6EyH(=Mk<9CXm z$s=IHxKDR+>7sF%uvr0PFG`d}7bA8_`>`9`lp#ZMDzzbFF(U(4sI3^P9-rn$v3VR;Fz z>Fg!y?N2RjJuiEI@Yyi<)0}Ji8M&)kt_5Nk7&D>PYekN?Zpk|T`hxFNC8z+o{D6YP zDJNsz5J{9ax^nMwo@n^rU?h0S}SW5!!?%gTfeqP?*yKk$FPEPIz*xkGLBzj!LUHjA)*zxBYyjGdRQG%C# zZT34UXhFSC&f}YY{PRI}pqEUF4htt|OT}*}pI3L8yScf+M5fOfp=FmD=bzYyw4 zt9X5+oN$@Vei6&7rltx!<>=b!L#_#a1q+LoVpHx1dVP`K8NB1jbJ(0G5fPuaq~X*6 za7>H4Ko_NT?i`5R*XJ9ot)HYt1O}3OyMU1AiC6f;rZY`@`XPmV0Fm#fdHtGF+VLWK zK_(%CGlt;I%M9)I;F>)AZg6UCxT*Hux)~fAx;Q^?Hh6nuRn&8)>G6q6i&3c+>5$~m z7q)FTl=zV*l<_lw=SPMb#RQmLXw-w7D}R1`#`Y3Jnorce@2OGTKh1?;l$yucM)@dn zCpJC_-#IlmdXPb9v|Na{ckrIM^Fo?;o1s83j_odLYO}SeJ&I_aOSL*^CUgwC7Oxr9 zP?HyxqdP^u`1SMW9!1ybo|FweYpAb&ZiV9eh^Zc;!U}6E;vzQ!b_W^XO)sGx8DnE( z1x6|q+K4Ru>zo&~)EC3_G_{@=JOPRef9j)_mcSQF-7#jmz;`p8*p z!#L`JQN!}OGDhAFYfF>;YsYoizJCo=OmcK~p6Y!&gVbF6m{V);J9r&_hMBUZ0ZaR&f=tkzww05U!!@O7u|uIA{BU~&ib&sZkGKXkMD|pzgt?q* zp-eIjkwSTm(Yz;emE*m`ES5v(3=T7SCQnqH9+>#;{`_fdY{3}wY`eiWGz~q}zpzv> z$4q{i*sL@hW}qt8m?7%7f&0&%ek`*Y*v)U=>F|)FYa(YYuHEoc9FjK!;ue-?&BQjd3m6{;oW)sn_-yER z+4uVOgJpN-=jPg2whNQ4HS*e2$VZG$PdA0mt8kVCIkD9)R<|qL+7bYzm%qbvf$M!8 zfexWs$)_4}dDB3l8=>pG=V{#)3WFoq{|hpYd&D1(-;wcHuzaHDw{4r*wQE(LzzieM zI-?ieP3X&8mQfj@&Eh*gu-<@A&6B-C!A(g?=@rekLtO3L-1hF${I0Icv*Ea~{DFq1 zrcR4XD#T2s3hCI@=J@qGI`7FN3hBNNQXXi`D^q&3&F+5Ha8*!k0VOfZPPNyOl48{} zD3F=qmBwFA8F$C2Z$ch#5IrS027?X=P)&7bv&s?U%^nzXaNHR^%%p|B<(MRt%Xuzl z4taSl67&~M#HL;zvZX&*)OxO1h{F5Dp)7`A4l4jFzY#rZ(xi@|Ov`i|zR`StjqEZrOFTn`sx%3;|Lz~-kQJb2CD-d1wi*>8rxN*bMl7B7o zDpAsLe~Ivj`IZ|^l+{BE8^$P-w{Eg6RWqBAeki(LzxO~8SMGNfux3|EU9)-^^A6v| z+I8vr;!q8GFBvTw+Fom%J4cKhKFt?Hfv1MIWWAP;mu3(fL2}Z7{`<8Q{j5f#aY^litqx`2R&7CHmeCaZ}`SV{BG7~T={rG z6DR^#u6W?Pw%}v{_NZO^uSMjhJ$UdS_ig#|F!l3BqQGK1Sfk*-lV!6vi7d80jUhJh zgEW+w*Dds~S;g)900)z)Em*a@;Wr>86Kz@v@+N)JLGq(eD4WYAQ3}JeOBnJtR38H| z{hhq%`bI6KEmHFxg3Wfze1CYmGNf;~4=e>q#FlD-Aj$NzQ|en<5ZV6dWz1$bx*N#QLHCz{`+(IwOglmFM_z3f^&Yqn8;M6e&uD zZ|zL#x^qcMsRp^Bvsq7Dn<(C|<`fl)R+NEAW9jwhMr$6n9?U-1I5>#N`bcnZ08aB` zqk$2`EJp^LW2$mkfR8Uwj#H?crd2-hz13CnjJ;!&zX0$T4fKu+h?OplYnymIH;gVV zm1eKjp1yh!9QrV87RZmcaJK<4Kb-6E$;A`tDJi`2##ot@a*}Hw`{VCv=U;vO z`c=%XhhirK5=_EqOPny_xEbe#2js;=j-Q_V2;iB{XlSgfqjURW1-{N*=q8&=n{|9l z4BvRt7uvYq^b34Ww9<iPJS1__eVo`WWT-7L9zB+>nOCkuxi-i3AoVv)2<=%@J{>4*ILRw+pUaQjbW)B zH`Tv#NKwN4nD;$GK|z6*LuP2o_s@{RqK9F+Zrcy$l&F`M zfx8q{Ai8yOs9STxmlV69eq2S!^W0a@Paz?@T-P-hzmAGLe#!w-GyY0ptkf+5!`<-V zo$;ibL?kWi`&P+_av)Km~3ts6Rjc<4noAk6s2bZlgoeLiK- z2^IzPhBP|$FBQ_@VO(6%fb%K3lPEbG)jg!=8&B@*>kFr0>_IT?-TmOGGTj?A%Ijg> zjg5k^6;GS*T=TBDJ%6awn4CNijtL?C{Oj;b5jlg8C8(AQYqubW_*|xqPe?F1fBwmk z+j}g9-`y|W^S40^Ep!{f0Y*3p6s`=x3e*O)67FP4b_M{M@+8I7cMfoPolv*Ji7Is5K|+v7lXg zx{I?N<)k=azq!5r@1H**dWb3%+bTXtN%;wI(QtYe=4?TaQr|7PQr7OsKOeA4R2=7| zBqfP@cuL`m05aN}6x?VTm{K!;uEp%T97Oaze`SHjW>HidZa_3b6ubSMn^OZT712fO zU-pV=^wU*&K8>XSwptjIV(rE=qBAn4Y96t6bBc{bUsU%bY9dGgL?X%nia{^LB3}M$ zSLukhz2T~d&%ce2kH0gkrE%SaVM(Fjkg>LQ*wAwVoE#R^Xm78yKh@68&h|4={#`*A zATW^~Ax%+qqiMgw6yE?kOSp5$q?41Q#Qz+B#q<1P=H>HOSYVJoCU|Hiqrs^U{zuZ3 zF1>w6Bxw%Ti_*fuVzOh8BBUc&j8s;0hCS_xc{${{f=+`iQieI^CP(;9-fQ zf`Y-`bWQnh-);?VZKf8??cAA!0ytq_He_{N8-a)$hKQ;OP02I;yi?(@5Fdyv z+e-etYbaI>Z0c=lvt6|Tesr-IAxY<}qy9LsX60exnC1K96Pc81qbzr=6C6R19FdoO z&{?3%x(;Y+YI;8J+F7{rVRg6fFAukztbJ*?Lbf+*(ZdBots}s!g_%39X)y! zC43FsI=qn=1v=3U_EvPldaY0y5)uNKD8-OKqkx^@)!@>fKaN68niyoMadlwm z6Lg(uyQk?fH%i&7*zoOJ^zLu!6nL+tp~@Y_uM!N9PJyNF+y0L?VO_5EW&{%(n-`QX zg*{Pfe_NF~DSut}*A5pnt5bM+?;J`x! zq9UdhJ=UC}AfwgP)y<}6;EvoJvZhjmabHpUw%pHR_rM3Sj5rTkPme21U$D?Sb&ABZ z)lf4?or#^jNiOIHpibtM_c~Y3tf@*M#vA#2K^ryI*Y7!Y!GOq4_ZYYI_8PWC3x04r zim@kcaK%AhUS7-d4k{`S@-lYJu(?`RfY#VoD)suI9INGEd0F0+jt}vIw6vIaZEqr% z07unDJq7eQ_2Gp%Pwtt1Gm_8|L=L1taSZ<;s7p#q=l8VW10M{(tS!wjFLiZBcoB_+ zaHgXN9)Kvz%*ZFr85R^?Xz?RgoK1pg8*~) zFfm~-cwK#oOqX3aTAxD?VtrSB#@Ncj=AyBqstrYj_z?(Z@3qBSQ{Qg6xD*x@!3Ags zCmu|DD@P7mPrN@LxyTh6KsFZ?9L#gzzZ!B9;`6Akd8y+P_a>r zrUCeriHWJXxfv8WJhwy>-~kh)O``q-W}sWv8SDfqF|T?w>CT-}Qc^t_qDj9n2D9eZ z_=9=LoY8U${PBf3_YIDjlqYMXLbN^-uK>$ft&`tkvTZqqhC&(~39cEq&+hijMJ@(t zb54kD@70C$iy6_d#9_Py^H`WXa&-K|Y~tkvF?U*iH@X82SJy>c=C?dEWd{cbEG8;F z_zSHU66f2MbLJ0b>ZF60A^M15Bm+AHhB*mTAL@F~XN$dR(|zwFzKy~fd8}1W@SP63 z4o0IYNS}i#nF+j?-s0VtE;PRCw@IgqrXt*)$~NcMK!+IGj6Mbw%hq1zxy8{2Gl=2Dm{_-hb@ z=O~;U9o;wAC1Z#6_=NilNJ#G70Ms1zyvM-ENHo{hWYav2tg5O?cYq*ij}!pjb3GXq z7GzBuMWjypE*cs!V+{=^b_=QF$8*uj)MV{CB}u&OxtTqTB#AGUhl7tTGqcs=z}LTv z+IHbDp<7t0;|o+tHHN!zw{0WYS2r-=gFn4KmEf~_SXQ?G-QR5&+90aI>%2MxTlb3> zFJM#qLQA3Hy9sRy?RTMt0U0Hjhqn%c%@qidqN}95cifl~Xi+=v*JM+WP{5+yp1q0z zE(pzH_TC>4!r65$MQ4v98#{Y-H^;3{KN(2wB<>Bu zbxlnd`57=>VLkBSeZW1g{~qSl{C{z1)54TM6}cyL1k4<`un1Usbah8jN5{vBlZE#b zO$l%QGspT=jvg~UCAVy_9k6ng!O)F~K++4-)6>}ILGUg<=nG-=oD7RG!McB3;8}t>CyiDZ~vKq9qPaSTp>he{%1D!W8|}|L|wnLrR5km_g%W-kr82Zg0P5_ zlai)sY%#F2v+voH2RMmXS5!e{IrNwO93Qv5%FZFb_X+YMt3#0u&^)J^fcxp zLyYzuXUI;(7aKy(XD6OJ&ews!UZKD+pTC%WUz&FyGyylvBM>Je;SmRGKQc1%9b+FD zYuGVGM^8V$JUfCG)aF?&{B3lYFuguha*7^E2i-)JnmHlp=@E>Fpy6t#z8=E~AqkGS zn(TXrKXXJ!DJJ1cj_~vI``>!RE-fY`v|E9nKCy+7I3yfN_3DZO?sxLB{3cg`ZkE9< zTmpW5l>tBvTQY#T8Xg{=B|^8EJ6#an@We!Sj)}aGFi!iKByD$3PuB9I+EZ|3fUfHA z@9$zfp$}(E`lXzBNFjNG*Ybh&0Q_vAaGG7J62XLoNvW$4KYtzZC*h!h3o|}!{ zGOE%b(RTcU9~SS9j%lPIKm9I6S)4bzHaGxfd9-EjDYoKNBT*w{>h+3zFxVELGrG9n?slPUIbpRa-QaF>#&6@`Tu3K2d_{4Q6tnGRK{@uHMrBsJB z({=abzwDbo8)~xs4#T_%gVssnd&8Q5DS$kiZ6tp0|fxQv8jo;hTR|u05TpKQAfai zpnYQ_XHWwj5?Y#nmXCxak?lk!S4UT#*~%4lm@uvYRl1ZcYU;HzT&UMwVf7YPbRuaVyXawYA3yKwZ zDUc`7Hi7=pT;fG_?|`VNC}cNyIe@WcFr9e*{2mimoEi)!@W*-_;EU`FqgS(k@UmgI z_w4n1FSKu-{x^@(9k1kK;J)7a@+|mkqDhX^2qq}BJ-0JRsZA3=4h8EyQ^nm(h9)D3Ip{lJRw_!90O* z?7#4@1J@9BH{>^#l*55K=|>u$ewVImZ*RvTB?fjKC9gOZmGR$qB3|gJkCFb`#0K#W z@kL^G=?umHzJ&Kl$KwC{uC~AKW}lJgM$aQH-Anv?*v0=z9qO8zN){*dp&=vQUx$pm zOHMv$_We^Nret3yC+{m|y1F{xyX9SNh;f$Af(~p87O@-DAIhqMzCMo2^2!Rh#9y$> zvDMZanBrKwVF*^q|9>wqal`cfy#>FMbj-|{v6oz(K{C9>bbEEd3M&G)Xg&-fzVHyE zEMo=|vgdmY&$+w1!_pxIFC}1;q)nC~I65RxOkta#*Z@>IILx4|CrCOgeR>HUzI^3Z zEWQs|g6`!{u$0F_+M*7O3`lqIGh-+dqjokJy+c&YzM{p665jaj?g8~Bh1M2`$Y7_< z8BKm-O#BmLxMab9Ls@}^?o6EP%)kaLoj4^{&$j?&(S4uO(BKVt`s`T|ia%-@W^~~A zDZ?Rz{zAcxR@0{abrX^+nuMR(6$ZGg71;f{^o)=Z@gfq)ppqd|{H?eHz0wdMM^iJ@ z{XDuNXb2{N-PI{rCvlhn&>gL6UjOHXRe^y8Xf)ZLSk4R-%WjR?|y5on9>7{?ilo9Z3>V^)prO^-@n$lMwRNdPnVo@%)NQ zgO>L>LJ=fMH@9Q*e@~QsM~qHwD{}6GqN0D1b)Nrv z{OFP0V7V;k-TlX}e#Ee&R-60W?{O-!*5fGRJn-1@HKp5C*0P}ERr3x8Lb)&?{ zZNFG>qX`4Y(5HVzXvzI>eh8LfA&}GOtMhr{c*Du-6r6V_zh(7e#{fgwnV4#hS;Mjf zFC}wK5BU9eP9tz1B8{Ftefko3Hs8&4%q8qqMC$ce`W+V?t!KbWO+qrmHUHjuY=0@u zPem7(1q|q~eE0Yrfw`dtxEt2g1wEZyjR^hY!Ckb`$B&{*) zoD}>Ut*s|On!F&c8PUW9Rp_6!lma~O?=QnzRvAl6N+M+*k&`R`=f?&seC36OFQn^6 zSC)WJL@Ur#`(a3a8j*`P;1sb8lM}}Kcq3T_gn@DoxPRZixA+m=C#NewPSwKTCxA<8 ztE%V}Uuz|lyG|QaZhNK84^Q7|MMc-&eb1genFVry@OPV7s?YQ0<1MiIdlhj|I9XV_ zfwa(Cc|(bWMPmRR8E8o?2bfEE^b3#iiHa6MPKM(M6b$qmtjIKQ@gOz@Iu*t6f<4B2-Co-M z0c>s@IV}g`pq5xDBQ9RPoR&hCcSK@HB6I|u`K6$>>oB9D#L%W9#81b08Qz&F|>wKpz&_RDvR8^1=PQ*wl7? zb_vHspa_p<8LPH~n+?+~@>?)3jwx4XX(uTvDcyI!;gQ13#&+e(l}z)z!r(zXI^%#j z>#lZ)7K#s^J;T9mA&tPp4_1P_m-^kLVhX%gZurrOc5){pjbj}8x*?eks7v*9X=q-c1dcFHBfXLiR3CB+5oufyh@yB>_vZhGpLi3#?>a>T8COM3?LYv+ z>uF22EJ!_{aQBc8AUDu-?Nx-F4VTrK55K%rf)Uc$TZj0_uaB@mac)U+5_$~<^X z_i*-hyJRS8?zeLO@+Lf2A^NpV(!zqvW;NzkR+xdruYYfL>Vvlseg|Jd*NGQG+ei`% zxhTvC??iiG&NvlqT~i&jMim19U>3s zoyT+#(y2GAA>gkt!yf^3zBoHeNkKtDNjU*J3HMm`;RCWyHH%r*DH4+7yjauS|94O{ zN)O#doDVXgL~s7X#kvvYhF3ZlF03%$blIb!rRDpI+`Fd&E>R3kQU2;kMpj%8MjQBG z?Kj8-0y4$A&HjLw8qB^JqJ=@Fwz@j+ECf=qs~_*+(|NlFY-zFrU4!MnnC>6c^j}bv zi?fHB=s_f`0l>z?3B^5%;`^9W{`Jh*&!4l$mI>!mGH|+%deG@!6zWkjZoeRcVeid* z&6`f(yx{W|Bawg` zCmaOeBi?6Dca1iP^HCF2z}J~?4wHGiD~%{@XJKJkrIe|?>0!bb7xO)FPbK4Jc|PWXFc&QJjx$i z=t)Ra@F$V^|Q|!E!f1M8qgU7{NZx(+H z-3;iciwS1SSiBb;2M!!?IT}>_Bz1$F%<^iCQfOhCPD%q{6ABgYxbz?r5=?O4-dqgc ziYdOFJTgvXPLX;2Qt&LMX-r!k48ZeC(28r1^?+~aQ2hVjbNU`;tx~{sH1eCbfby1^ z0byHH3D|iM>F7ZUuqi4T$s!AauhJR0cWbuZdE$!4G~iK2bzi=OgoX}aq6vTt79kYP z^^J{*M0a9)azq$Yi_>lBYU(RM9o&_(AtxcBYj2HQs;K+J^vOIT@Sa24t~n=6-eQ1+ z?Pc13XZ2CE`_8a{D5^m4=&Dl6glhT6Yz+IH1wAwXZws23_A-EEU zO}-{AHSByuepXpI;}I$3_&>)$dZlh%Yieqm!eLC+WM6DT*`!lMX(v+WZWyilRPl9T z*W=CKJpEWIl^cEv{5``4`S~o~VuFI|N!ncE@4f!*MW4i8kwc>8VelkA=sgIsj{v9>5C$@$eb7nnE(7-{vI5Z}a%>)7Tc;Me2`;Jr zT&^@nldOL8e?j^G3faUCC$_h@rt~)df|?O&`i6R6eyauX)*LU}Siu62=_cNb;*Ys8 z(Ws`z##eb+Fyl;p*)l3Y+rxz6779tH;WGvX&#z9xe!611iQMqY`TW_lXTfF?xh+33 z>Z%Jkb1N3vXtZBDh}nD#@r^9S1CpE!`5?VacX1@Kv;nX zO>7=!;!eh}+s|ClyE^F|a||@Q#wI4L(Cz@}ocuqVYwgLSSKj>@t*2L1L8ny6W<+)G z8Y&!&*arh_`%8)tPyuv!@&s{g9FaCGVUJcC4ohejPq+%&aNywDuY0?cuAAP5Nc)@K z2`Ic^b;iNmJf)?re0{DF7sbrLa1IY`Ko{jwRRVdqd@U&}YZ}nI>i~!aAj1GUJo5}R z|7H_{7E*&T&@2omP&&*%EBWG)DrgufxG|qUg~q{q5V|ZHsW|K{@F=baJ;45+s})e9 zk%^E;4h3MSpd5vK)fU+O&eNB+CGk;Zn25qwqw%{(mk+)f0T=zVrvjJ-qF9Iteo%WS zVjYNsQTBr9>D!B-Y~fDflyE#X-GRq#ZOt_v3kZYqLUg_~-n1VqZz5NF5f=wTuJSFFSYd@4&;%LPs!t zRKG;!0)E|h^Fu-cXK5N#8#J<2vTbUUdC4@qfkxll@CPXr_ zN1>8X*?WtksAR7Q*(=2F@lNMl=Ukt2zMtFg`}^nD?VQ_nyL7zYukn07#{F@>-=C)H z+!;YZ&38`-Z&*LK<^2sHpi?106@S1cB``lgw+eZA{RKMBpFZh(o4syz{{B$nLJ^uN?lcLDA224s65-D= z3;MG*FX4g1ZFZC#mxNIf+Ux-ea^OwNqT4O=_RocoVUk6x<1?ZF0~tUURk6&O_wSd% z?)-8;j_e}nMd2yqv1te21KBzQSO!6If#F6>RFqMrGY4v*z1(>F^i;K_PC}gWr ztWBQaTP?@nt~@{IF2((>KeT1+Q6?{C;F8B9G=D-3tQ-IoWwZG_G(->B=v%0eKVKGf znpsb^P$LVB2LxIUTTKtv$y}5Q-h{Y4JRl!zaL$qfAb4!-5H=DdFt7=Oy>t-kJ5DlYuyln~61}tC9?YM}%I(H@df_o{{?5zNTdHD-XT#bR3zrW)oAD)y1B}%m+ zS^;(N01Y8oysS`m&%Dme>Rf>m9UL=`py%?f?DPh?y1F_mD^6y3 zqkv=5L4(>oI$8&lOz0U_(`EfL$e=wL0_cX2Q$kYm0IZEs>kyoo08v5P32xUPg1)5|s8JS1sHr*FMqfm} z2j7G1dZ2c>Z4+`xfKbrCmS`R@CJr*C65Iv%-J+K_n7}v7ak}PY#v$yb^xVr@I8nQj~_jHaCPR_whSC8_Fyne+Ftmy3=pf$ER1jsU=YDN4cQx( zh}Zhp3n_Z!@OfF!&@C0TNicXucX>c?dGihyAAk$+o+YC?Bi~sP2~CLepE}ivZm0n1 z044?c-EKmW0l07QJ?Ot+6~bIcTtq~KjZIz<;?f8pDtN5GiUza`=+R2tXb@O~^k31? zN#H{)j#QTer+B{}Bt__C2911+%K_vn$SEAbXvqT97GUFGVF>#iL4KeY;i6PE!;!8>{oRRA zzg{jI{xq!i##c#4t}%{W#ZlWdV0~|DT#*M)csxyUn?v!Af#H>rT-b(uH4+b~+ zh&D~`?9ccdbg1k_AV1UrLIgm*_2nnJrzS-N1d0K{>&}oy2?<>+vxQ1o(Qqw}F>8Z> zgd~yi+$`v@EL3_WGGiUJFGKEz#=` zkPfJvjf+*_b~h>U_hHRA8sy`A|6JeqLTo% z$=mFfl0jQ2OVSjM-w>pQ&KLb+a*A(3Vj6~(T;c=#J|2L!RqLt$sb)R`dj<#Dj2osjxHO0LGWUNufw-52D7m_$3ujK zW$L{-&w;`t|E32$=~G2e0rJjSDs`hC~i_!-VP&S#|xR_uu_$C<4|kZI;iXl zS~Z4Ol#x-{;o(c)UVXX-W!@FDvCC95Py|43Q0iv^DhRJ}#S4f7*D)!`D~ZCi-@o{C zsr_{k>72P*<=T0@gvwVFDoCIXnT-Lp6LcI8pSr+hF~Ki7{tW-U2GB2#`{=#1)KqRUv9VfUZPJ=|lFgZeBpbZ|hhw-BTCd|15p8U5C&6p{ z-}VkH?E6Vc`sA4zp~1n(%GTCbu4jsQSiGD`@Q6}-ZVsN>;DwoG_`8G-PncvtHJAX) z8i*%Xe)7kB!RLV0T$rw1dWj64Y#jZB+TZpFtii}%J1-Kw((RjnFU!-3=m_!uhaD6F z9LeCYFcl@GP7-;=X-o!r)#js}4;u}=&3}h6MMZuc0R3QO3%b3*bK&8}0kGfAer-f_ znEUJ7V$)yU-kzl7M$jEpr0nw}v7B93zgnQ3> zZbEaa4RygAU>SXu0FP{loiz7j&R>E@VJ?~~5lq1&Au(tr0v*;Hk{lyg0x;n>{=lUP zHr0Jr)5%(7usamEo%%JoNnnqp-FRgPTVxQ*RPcKSP@>0}0D-I!=WE#Rb3@WdX7Pq4Z(VGOFInXAHh7aL)sF|7lq5eSc8&T0ja~brLf&ZiNJvcu74tg65 zJY%q;=R^n%j9ahyZeE5} z|FYrV^9lt-TF{?vtgqjP-vgB4qK3xZMJh$Q2{);~rp>>E1gVgm@iyW?*2wAQ<#&8k zig~2}y8WifOG{TePT~=_-Z@s9OGf?xy;IFa=qgiH3xGiaSU{&{w&mZmXPk;bImzDk zNfdo^=){WIpmlioMhvVJa8Uwa>PCKVS#Pg4ddu)6J`(za3vg$%^r&|?Flam}$?;qN^(io!O|{j>Xr(o*OswT-TR#9m7;07HdcUiXYx({wpQUU6 zk>}&~P%b#LZ!rRV?Y7e-cD`{%L@YJgyi!(Dil#jy??y&p0b~b&rGEhEYJto89`j#Q zOr`AJwHp4bz18jqtEY=uB(CV?RG&Y8UL4q$u;t-*b^6b0>pi{vzg$ikX}09;rZkCy zYmCTqto9^#B&?Yx z__=5*&}P$JxY?YI1_wXaNgr02t0V}-a;TFrMh_d?ehD5d8zfa~y$vRgV3pcDQ4UtY z*bTsp0(S1wiV~C%x?mO+Hl~?(0>a^$)E)+T{0C`iwjy)@xmn=$6+!L=Rs@W$Anu)p z?e?ap1#-4{FonwZ;7PK`@Zpb3Bih@t1J8+X`@22Wqm`y(_JJXBUDU^-zGo@j!PBPz ze|FoL)8P^*1&{#14b=V?EGQsHa0!!HXNizx1Cs#c3$(yyfH1PMvH~+}gDwG9<=j3~ zK`Z~U_a}vfgaie(p$I|ew7)FxVdKVH54ZbV<_miJTlBV~8{dM0a2sQX<}!Gx2?O{8 z%wDx?F^c8#2cvbbU|QPP-|ym4}i%fEoqpuJx7g|0v`_gS}-j$0|)Ad zMVd!7=YOXq>I@A?jVE^Yr*bXKHfEu7>pdsn^z`7JY)LwP=Z$RX9+_=~on!i`49AM8Q0*JV~ zeSf9PSfmPA< zfiVKGw9#t>dQ2eDl|js*Q~c-0^1cm5MKGDYy0$&IJ#NQ69n31{l7&M?z}wm3Q8UMt zG&4PoM<;)|@FEA0$9QoG}F(Fzafc$E5xCLrfW?h&9@)3-waXr?&Oa?4 z-3$hV6^(YGu{=QTUY__JxX|6=UkhC8Q`mD?7Vnd0snRuJ(3&v?HeUI1=-?BOMR>FAlg`(mked`nQpdCr> z`3jqx#wo_|s@W^UR}n4$SmfnB!p>5_*L=q;Z`T;gw=FJ=J4eWXDIc%%l>R1``(V@@=$h{quq!dcI(~6=v=n=1>Eo(# zR>8<|MMYig5t3}cl?Gtm0b&Oq0P6t)_JNZC;6~CC5=3D4p|tdI81tS8WXs6mW zuH>GZWrNRpYSr=qEe5U!x~>885y;EXRgbMLZ@bTA0lER0OF?%7$H@EAB}XJbYsb42 zW4*;fy0Fxd@6at%bGy#>Gy z(XMcyq$bG%rX(<=1~^&&u|1BfcDBWPfU|+)hEXSX+LUU=;gd>r>YwE!aQ3ZSetnyG zFuEZ{%k<67(UfyX@<88{K#yr(6adlzIIk#5i_#K-`$xph*xgCtRz*T$;s*d|+*Qt9 z#FK3Q6B2=~aZYaidYT*M_Odb`GTLDkRLe1ZymXmiR5nZ%Axd5oeEp!=0qNfMk{bm) z0xf6{(-(V6`0iagYI~)b6yhTapV zmJzi|BQBQt+>u_;SDgVm8K|$U6F=Czq9ej_yB}pDL8KyzWV2glvOSY`#dF-VqA@ddeacTG&@A=Mf7Cg2y3|`aP!8E;R>hbgGbPZ0;6;frUI2N zmbdFOZUXKRrY#R@Hu~r`7~7!JGk95mm-MaOmWb%+nUi>}e^1n1p+?@TlGk&w9Jb|0 zDK;GLHd6;@DD?PG+*k7Wma%+Mc8iHnYM}vW5~t*@G)zzgvo;)HX4X-XtLDwJ_Fn~C z!sBUsFx@bRe)wYiKR4i&^z=UExkX;Xg*QU9{VPdnzM44-@M5i;#c^wCliSx$6Vt5>}R#DaE(RV4zO3U(%P9cy&S{CAjwV{~4t)lxK-@%iVxNx>A2(vx#3Iowe3Btm0t zD{5q8^91Tv`+YGT!`1CGnJ8l_a!!++eM z*L;l$@hQNJ_e`d^4Oas6C6C?YJ0U)7(0H>ZG<&Zu-ZA@0;_GXMff$llC_3(FZl4=OIAN3Jrxt z^y}aw)ZT0J)E+3t`cNjbB~N2uAQr8hyEol8b|wI3t5sS|KNH+F9Gv^4Wo9Dp+Et>#(uNx2Z*5rF`FZ$?2cCz z%aI~{FTC--R!x88E4jsG*goagu+a5D*`bEq=abBPNOwOV^DbgaEyhi;ng&*{J96rfu?u4q7l<@)sub7M!F1#A%w1~n%GWDUJ~D^93ur;=yW7+7 zKTaXEAZ`J48al;(Vc621v#YRQE?v45B@@>EmI3CS9KymMeAnid#W^@yZC?GlVNjm` zx?xDv_dBP5-7rj^0sgdG8UT0KJz0V2KA2(Ff*Nx0R7W!~y%^-M)07xUr-eEx zWnRgt=g+bcyf{$2yIt>%9zA0vFI1%_ZWOm;AkeD!Z5^gu%!6?i!he4Ea2p3<0pa%6 z7|xm$;M-pgv1f9>wY-Ub1t(Deq{`u?4gv@Q?k`KLu4fbRRT7XVc)Xz*1b4jjd^DXz0S)+@d&emHGLXO4^xR z?n~{WUJu$r?wN0M>DvZej4nK!Aiv=SK4ZW6EMYdmlgOxMK`Ti=>=!riCEb-XW%z5P z$m2#~)d~QQ1w@VmYcWS-JT`h_|lXY$;>4)O?X;4a29o_hziilSmL?5nQ}3r3&4 z%-GnX2Q#BSVWigF;~FO^#>M5rIoUYfL8{Ta=t^fi~F}P!eyFAld0C);024XPV zfW+DZnahvZ2)oix@ul{GrHSBXwmv(__T+yqZDnoE3+kmP@rfR>l3O$g5uL7Y+g%I! zW>6o{i7DIg@EbRbHyUtm*(W%_G!!VZE^BPSuQ-65e>FZVJTmJYYd;|MFgmj-F<2~y zAcdw>qV0cqbhW8wpf)WmES$%Y-VBBobQ!t_P*Xu$Ho(dLPnAz0z}xrr$Ln#!(_W&X ziF{3W*@=2!et_%;eB7GAE|6>a@*@Ihxm@01G_1`Slw$wfLwTxJmE$t|ynrYb;;XNd z0ApBsqEI$!23n#}*q>3VDvJKO&8+=!2@v86HM4Bs2q|D`fG4*okh`BhJ&h)OL!6O548iS6K$$RmP{v)=qZ;p7I z@R~^FKm|g>XQ%xGrGN;1ME~pLm=yP7jb2Yiq=D%(uWuf1x^-HZYpL z#Db8j74f+r*oKJBQj93U3-Ix&X?6goE1>`&B?Isw;S&dEW7&Klz97jUfBCtw1oS(= z>*Vmw-A(N1IFFINbmyPOiS{4hY!smLrKK?dR;or0NE}zjJx6x|0p4qO3%HFdF|+2& zlMhMMHhIqHG@;q{PmAlE*VuqY=KfWs8dxvD!&}={Ax7geuxdcx1%vD!ki^dEF5WJO z&fmDgF?-i7aDrfbm;CoIP;m;1(xbVc{nYHNKF|Wag{jD`<S+h_(7EjhlT`Q?84&{fdzNydgjo$Fxs4F0OxP7#GqeaonL>!{+Ma8@Ot%Ews0w4ph;9i0Xh8U+A*mW;EJO35{#9^U^!$D(y zKfR!009w=3RBrPjom#tQ0ZMwkTNnmxls;^Bd5 z6Cot0VdhVzr;XJue63X}$=!_!ZJwL-$Ry4s1eyJPA= zvVW-fK{a^;qfOH1?EAvChO>hw!e2t3N@z6o01*Vb1cr$TxHt&G$&capqm|8p1_B$i z$Vq_@kViE1Q<1BPZiWh4_03>TuA0Z~PYl?xJhTyy+Athn(6<%I5e0ms9U-S5 zx?a6_ewyS?U|j=Q)|nRs9?EV^Y!e$2!52Z+=>pLL{gnW&0ZZEt()G)iFTp-ZNeAHi zH^8lj7z6Y&5&L0-E<>!p!GImPC6tlj?2>*AfLf4IhlVjHrsE*JOl9x;tSKd@8yA#( zT<~yh-EF=}D==Qym|V^vZ4t(%Z*y#T{e#1?x>Iw0?b=m#rt-H=MsNy@g49{o#RkpF%;?qWl}J)vr9R<&B>Xa%k2vTE0Lx z@Amn6fHTH+p+67jb!XKuZN-d`zw;`9*$@khi!I)won*KMA0d@O#Ej!42$$jGa;=gB zvt)Ms1Rm~X_i}AlV)^?YLMsRk=S;bRN?px%onxJpXZ(ohBgb3CVzNm zfFV=Rxym{U8$%_SI~~eJ(Yy{^#>gnAL|NT2M|XJm|N!;5Fl1Orx+ zs|fkh@inI3GNdWrU%#t-(p?z;_=yu&fQ{&#sSnwJ&UizYLi;+zDD26h9HSF1T}!;q)%sz&-KtkFV=Hleq=?<8;xJyH|$kK5f{? zd#;ys_=blrrSyCSjSG58>V?Y{C;TS}qC5Z0B-6k5G4Zfx>uZcI`5I$Rk{q#Qf-RIU+RZ6iyugPSO-tiYIU)3o!^; zT4#Ns9bvq%W}%T8WB95!8!J%&_g=k37C}7c^|fQepl%VV@}5G z;4eYC^MhV0CEVt|U?*OC65ZWaTpR0t>X+uyo@dg3VPpeyoG85Ggqbm1#F?i!4Xp~E z;aVk7r{zS#PFnj#7W)2u2si2&@gFdtjmKj-S4&!QIp1zJmq)Eo1au}>;4`Mx<+WE}r=9*$ z?L09;e29u@GcoNT>3zN47hBzqS{iil!;|J=s8> zOE^D)Sa)vmONfjw%jEi!VfaGSa=*E#!iYK|SlEzc$I+Ta@h?k3OcAlO7h-jO7oFEi9Deso^{`85s4`-^VC%w!DZ@$zw)i#L@Kfkx4z|Jv|>Ogj! zL$ujLWAhwI0P);QdcKy??y_i1f`b>U6)#zIZDFrbGB9-4ddP=_hB^ymXhYd`k|Mi; zCRPesjPUd3sbUIO<%XY~XllBVe~J|=p?JlHBN;JPZei&zeGe|C|D_G<(y{$4Caq>~!{PTQFSnU^>mNrNeB~}!I~8~w zEdc=dI$%0a9mN4E6hKsfjWx{6nb3J7o-we)31-Ala=H<)@hC~T3S?XrzesH!fI$$D zxw2tg!->+djtg~OKU2UOn0?d3;DObE>Stmv7BD7>1>yetED|{tSSz|`muTH;^ z?Q@mE@s08mBQt=7`1vOUMk2l44sTmSyEI=W^?C&p!&v4dUrHXG>q&)gplvbPd|~C5R*Hw_6T4Wyd-D2H zX37Lim6jeCA-{hZHCnlHa7^pFO4-fN0;o8Hv7|ixef;h!gc;E?9Wk^WCXK2xd?uAM zrRKNrMDAkem{QDN_#0DfjDJ=xc^uH+Y<-`Y>dY+LJGp?`AZ{T>+E>O6d{|I@wIKZx zU|}%@#IQ7Ic<4$$QxNG>mO`4u<7skdTQea!;9ve~_99gy3)#oA^fF8Fk~%&$6Y6x@ zXm!WS6=yu!c(XH}bVAP47|Ri3yEQv;+DDiDzX?&1M@v{e;~Jc+ft8jV5jVfu?y*24 z#Ub`i8Wh1Sa9Hx3&i05zGH!8?)!6Y{^DJ(X%K2=E!W8~DHe1#%%&p)uF$MoP=U6@V zw$1zr%^LFT+^3%_(`Wsj-^VSEOD<%pzjKUqk`{58e%->q+4`NsKwF8zW33&VDdukt z;I9a)1=Cm5^_K9wJo)nLFcp~sEDORGAE-jjW}$@hgIZv}QZunzV}JM7fm0aC#oUSx zvhFLfZ*TQp4xG5`bDK80IgSmLkS`g|DZMgPSuZP6B>J{4v{JxKhxU0FfgZ!AQz=)X zK>8!@qtrtKU!Q%q+9ROuh*a5b`EQ!auQJaw5}F*J ztwBo(iEZvj7ob?#4F)DI*tLJYU0Hzbw$##-if9)zJ<(4}Z#zz;O+EggP230n!G(ei zA?oMn^c4;i<_fV%Sf5~t4kpQXo-8NyW4a^3_(Jun+4Mo1`MmQ+chDy~SLtxh3y#`u zY$-xyB21SCrs9&XoJd+6v+-WQ4;>;a@)hKff%iE9ee7@6aBd$rn#e%;>#cTN0^;uC zSp6X=l|s^2U=ZcM-XjL=Nl!SHkr0&+7*v{^YF<9@E0mLI%;mUjwM}=9Y5B&O6;BBd zW=nOGiAb5;YZ}P-o#Epj`?(y2k@9&8 z34+$>L4!>fnnTe$Lq;HnYwLwuCe!4IoIFz|qxrg-8m_ZVN5nR^M_-#kFUza-I3b)YQySKcb&)2%N%ikHwNp5wiNA>_(^W%{Wf=bwnR7xlL?0SM6f$1kxda7CdqBegoo=TPZapYKNA*}!^2Kyx0eL@Eaj8|1` zYZfG;ohmRdVz8eSqP{KCqte>;$6#-2bT%#**wP^KhN|+WXzJO|ylB!6AXwkQ0|wSX zdB6@W^wphgyX42^~ zeIe;zLuwK~KVot@lQ8rbs-?(WFc1mA$3dG)NhbktQV@jU)uvZN=YEu5a1M5`=1Kb> z@Juw~TI7=#QfNRwVV9?8>OqUu6TdG6X>vauFlH zC}BhF1#W9WnU#)eHoZruRO6Uut1_grN)PYDUGSC=XBWu~|Jxilk=GpA1OalxJ14Gw zF%4VPelA9Sf1p)cHm6-jB!N-oq>1@Bh7>jn?MLr}6an$zi&@+Lr#v|S_U#4lUmq@s z{_g1BM}wma*but3gp-#B^$ce&W26F@_`l1FhWWa~{*kU%ok2 zv*7*RbnRbDvkK0i9sp6`FGBI0+qZ9@%Sn-%n%?K>iz0^jp_`Vj-vTboCw(}xd)r6v zp}r4$j-klw)?6I>3t5W_l2;!FtIl69u$a3|R5cnzfI#-6abylS&raH|vMn`6=vnmQ zlJwUYslR3c>t6iJUB4r2`1zMTso63z<<^%Ho+L)e4I2bKpD%ll_&^9Xv%glj-@{Kn z@a6iR=Wwi%ztM(tAm$1giB!ZZWNm!Yq2@Fy#^4lQ?70J;{z6*j;Oj*brhEyhr=t&_ zI8*)xivR1&-oK_PX7Rtlr%=qaqw~{Q24}N9o?)ls!lM$x3IV#IetccT{vbG?x&5Pe zojNY3c}^9r&8ZC85UYc(T+C|YMS+{Tde(}ib-FU?%1QF^Jo0a$sia7 zv(`5a!sfrDVZn!drvoV@ICwlxKgQZKb=o_Ne4Yh;m&os3n1%_n>Rsrty_k=rZ`|_8>PU9_;nnROJ_6*JRBKe z)M)j%eWst(gHNrSO+Wx=2QoPW zy1O;@O3eR+G=A;*ID2+>_8M@ggfUJWWAH&+9Zm67)Q+0L&nbQ)ZJE|o2lLmvGXfs- z_|MAN4D5NbH46I4=?OKn`f=MH@LX8UmrUvm+18Mj;dG$S`80u#4nToA9KNVq*~3@9 zeGy&M`&H61KJfWfU^?fUUTvb;AjU%isZSH)jvDEh*qxfYXgwM5yCTY}TYQQWlMaV}QY?C^IocA`dr3^_XLH21)F{Mf0uSp(n&dALrjNn2AW_bMC8TlS~h z%gd(P`q6Qz(55}iIXuCM9K*dxf=5hz`!Yq#benZHKL@DD9u)*^4T}YG^*%pWKpB_i% z`_J_}Ed5Xs-Isig`jbh!B>|Ctj3jabnI>y{^yccAoo+XahkF#yvD=Y=H0G-Pw5xW=H@-GLmTbUclC9 zV&C+@zRoihk42+%E894_yH)NoWz4!K0>b`(jGZO_JC?tQudRQJ0;M zXh$fJreAHr2i@%jHMK7Qw8Lbdp-%lwPfG`31u0a8-&5BZdZ~xLD-@XR3|su@uyzjB zh7nx4u;p83|9z)#7Y~euK@$f*f`2a8!*s?B9tcdTo?d>+$&roo=T7@2*ZKveQ2@V} zZJ)W0D0EZF=RQ{ErGifs)jYY3j+$=#?G`t%F^!&&pMyR0llrIERDG$!&mMTv>7H(l zF#Q9^fTw68=77ElV9K$~q@D|WNJsag=Tcg`0FlPI9TnQ=Oj@lwEaC?up59_VL=|Tn z-w+O8{Lar#l>JyEMaXILJ3R{RJFthXb{oWoFu8+QVN`sd?r(h3BhZhc@C3KJ`(^8+~+XD0B<6Yv*N%JC8O!6bmM`!x@UT~ zltZWPU#;SbYK;dMG(hwKP-J7uIrml=O|K%8c#Eb-&Oaeb3LkC>CDzWo_Mwzxr_kOk zqfP6uxy<4oJ`3dl9GdzrYBzNN2;o4P5V`fSdq)4YL2sq72Iolx%Ne>1W}oG?YLBYI zOY5Z60&PFmFXoDKVQkV&T5Ni7Dtk2-nuri-Lq+0M!)TY@t<0adNoE6c44a8T@Jlum zon7{p2K6M^h+)84ZCM~zgu)Ko1C(HrhJijnW-9n0Fxf)HdwDNy&Dr4`#Tc3JMP9E%E`pL7cO0*cYZ0t?wYt_f* zubR~pN-CR>-iGh8qC?_?xVG)ae4g7s_8qk*9_)PDkTko$wiE>UXl8ek{=o?FB=VSQ zHr}hxpEETz1yMFe8W{1Rua_=*xQ87`VmE-!2#N~fqrnW%d7T9G6!erD46E|!!DR%y z;rk%#-p{~hkIOk;gAco)3}gQnNICY zf*CbVmV5}ovG!T;Ob#Br`1bQ{czlg<#@xZTXVe_ zM&(^^T?MSI=lb#ItKeYjjm1h51L)-CpkoE{n>q}{8S3O+MGVVvkW}Ii`PICi?OGn3 zJspWr&J?^&L0$QzzEDO}ne9ZwttxtD?Xs-7htcFWPU!t#8YnO2%H!NWu;j?g) zLw%m7Xv`lM3Bt(qkNI@%etKu_UFJ-GIEb778X*4c*RS7uaGWFyGhSu*OTsKq-{;3n z`;i}?g*a2n(2Xr0=}c1wY@%ag{ASbL`LESfm^NaH zK{AS_wBbzFN;u9dBBJYtojyf%8RnKpbG^#pk3}yAkt|ip;IKEEQ-L=94X^EBAZYoP zg$ox8x9MiHx_}wjz12T0V-8D`@^l6!FDzUqkLpC=QO&-6*V>|ZxO*C*CE8gOCOR?c zm~-)o0`5!Oh^y829)x`Ru$p<;L841^>Qs2;S$D4!ly}A_>mF8#Ge%6`P`sw}nOr2Y ziS^U9OopsYGPIL85V~Rbj&|()dBp>HteO6ViPzx8_~F6wVgD2ycLbE5s}Nd1%8C;d z2*r)TFKHv1^!zswGLwK)ql0^3Gq-wcx&!TH*Gn!t7gQWhRMM7-t?w!(G%*%Knuc^Y^>O zO2awCZukdN%nByM_{f1dd2`=4L}fCEUp1-1)vM)$9{iBGdem7(fyQ3UCkE$ zE3>}}C)dq|%#P6JipN@MFk+IqbMF`0%u4l54$OeS=1Ao(ZC^O4`Tgh+ZGLj{Kt|LW zvur-M$1J0OlIIXEv+vT}G2sC7hGx(Vm9n#}VC~z!k|Am^ZQ#l@{Vb@G>%nJ&=7&~1x%auUh1y&~ekkBSZ>ByMes_E=M093fP~Aj@qK z$1{Ja<%|^=Yffx0UAfpyy4ptnCI8+c931KkK%ZsL!%Z;MK>5FNnp&B@j|lq9C`UW@ zTrU8}D`@$EYVUW~D-)Mg!U# z+U34x-RQ`-DRV3CW&7sI-yFn43Rkln)|BoKEX?6g&=d5;qs7B`y&b%@I!0EaW z%4dYI(B!H#3o_=u>V}^GYROmk>2kz>hgCWH{o28jyq$t*iUxn>7fP-1%)^#C-;QoY z4WgUx+#1iKZqK7nEdr-P8o#!BJNl2$kHJ;-Kl?E-@br1r%J+Ge*97tL+B0-r%*sBx*?7=B9${%{rsVJ4Oih?=%+HM{`!jfHWL?y54O0*+_j&H3rN;=N;ay_~ zwsGtImzy84dDteW`f|tKkJmkF493^al#+GlSB_D5fE4g zI?50jra@-~ETuj0#agb_{j=Tu%LQw@iN1DtC;OGGD+Cj( z_2Ha^F7>|m^&dB1)^9e6=dN;P6|nY;HRxrh5G1jDt0VEAKP7T26liQI5wSAzZxZ)N z85|p@InJEvODTsGJt`AySVL=*6M$%>g&+J(C(+Nlqfp>3sJ_?(k_MvekKl3#q(G1t zDqQu%WBFaL4;=Gs0H;|v@d=DQ48TtI6#m(Uf8c!(ejf~4_=GWju&47haZzMarU)&G-@8~*Mdi%KtJ*~BL-*@HXz{Q_eR-iM924OgES5>ycxQ&XLfZHsOH zpoP^yV*-3_e&TZRQDeGgx0 zzgMM|zW@b5&QH=2J`>-~2fmn(B*7;e@-EcAMW0mviNsNP&sSiSQtNzAwo#>whc#kL zxGEHInB$IfCowl)w$#{<>o(@5a8-ecX6w$9$Du5L{e{9$uNF+AvOhlifg8Y*^*B$^ z%>Ph`6NiQ$kyFGDCH=%EXO~tK+M=kdu288EZWAf{s^awVra?=&#C|Ad(SkIlu#lgd z`Di&0jyCY`(8hgmMg%bFkS!p+!hw>IonRFFmpR~@&BFz3N=w^weSU(q`1zxm_Z?(cq|0HI~iAT#3c!^f%vhChsskuH2%&0UXGK#@)?r ztfh-O@$q+(llP~#$5aMO=|;){1|fYt;zf0`GiOt+AVt{n$vf&Fa1aNaMfI%C1L|^c zAH}2i*`~_+`z?GdO0O@@;RfCo`~=7@;1dk)7R31YAZw0qvC#Xc zRUSEbw>b=>;S)_ck448OKqqZRbuWB_Cy7 z&uJQ|{(SKO9E^crYVz3~n9o=&z)pqj6q0@kVkt0e9?U(~l8p{yZe#XmIsFEgmc)+P z*C2UyDlUTrA*M5JK)x>xQ4iHC$wHg$hJAg>QzjyJlWZRBni1%g&cf-Udr=U=FOpvK z`o^)za&$n6dLpmRVW8_*H%MmaNfi)EmwXuH9335jtO7oipFtu90yGJilem8q(){8q z{jTRDo+#3bvIvkOOx{GStfe339%85wDTC-Qh!kT{E|u%W5{=Yl5^K$CgE(WeC9Y?y z3Qb~~?nWdp+8UFZ38jF!m_ylMq>LT9K2GB2TdW2mCRoK5Kwq@Fd`r-D(LieN+3vs# zULWi{s>APWX;Kj(gzK@EJ$G_rzqlxhye`B=^+mqYcD9xd2H$Xo02L;8+X;hGEPq+r3dKP!893KhOr8C6hczOc8FhHsiRG4j7sfXMx$+F@2oE z!v|{mpXML*{$H@sZ_oK(iMUdvXWvfQb-e`K|91EG(4G)S>TmViEoV|R(iGxmOMlz) z#G!Vej*dDoy@(YnvpWZakeQog`QUe`w14NS2HJH7oWMP27b5SVnJ^N;@4LCX@y_iE z`efi1V|f%1yV=Tzoo7cm78-kOx5ppml<&?s`iM}TWUSD{&gxsXb}yJ49syunf_+CP!lf)en3l$;e2jKP0hiRkoOnq7k6+3Fh9q!wOWOyTrfapK~xpb>3Y3_S>8PM6X4E+5Z@E# zr@1*fOI6$7;jYkz^3dpky+!xUb(eS2?qHY6#@WmNTV&b~49|hK95iIM+Q=yp^c(+Q zngaYOIx6aZ>I9U$1FK|D0EGtT>FLF4h&o`dciN=R2l^&(y5Qz6c;TxYMskkP@$$3q z0`B~>izT(8m5nb*T0T{-$OPiVnlIdZSsWR~Q59Z=Gml%7<@bZ+W~*s%zzf|1%S@%s zd24+98E3MMGoxP2Q%gUYSZiL}y~z}+-=H8^40x|;WLr*}t$h7)FgCW_9;+@mWWb3{ zFCqGXNzo?m2Ut0UW57R;`uP$nFF2tHKLG1C1ys8_vXN+mi2sdfFDaBNaO$W|bb=H8 zz&W3I9CkfeB|R)+=C%8c)KAOw=TGutA=UnyCgG!( zi+t*D9^dO?<0j$`n(W}V&+=K9AmJ(H#uH+ToD{lK5KbaFh8I~7REp1s*YUBmJfVn} z&+Y@C-FsuTA?d3m@naXV^e!5UoQWUZ({) z7lecmh+dh`Cf-_YF*X?-8tQ3ClCko`KD52F?8!bBXyV^Ew=`#^{t2%$cW2UMhthjp zqUMcq1|@%l;?5NF`lz2bUcmP1;@FEXaStAlc;r=x;{+JT=$p(;?F8VYEVlU#4`Q2` z40Aq;s=)hnp&&og&kJlfy=rAno-_w8EU>2y>iwhx!1NAS;h3hhXz@2>R111l_mSKB zmZT*XZ>SLvi=ye_;}>~L3~Fo#OToDrXwJScD<2lg=BDf#fPZhp=^s5q0|NuMZ{JSP zULtr&9g9b2Ay4iuj5*G~_d#Bm8F!PN3a_>J+fKPG5vl1V=^Ogw{#;wjZONnJ?n5X# z)|7~M^-ax-J+muIHv2t~9>s4F(d*%*;p~3P_96B6B`$U}mZO}mc%UHbz$97!xl^KQ zLQS8FD(e<8X6YG6Jd*WGVV|aUKLkT`0~rveIBXy=G1}@nUHsyd&etEEK!9I{u_8b? z7!XtrW(54dEwX-o^k_yxmJ)X1p#6Fm`*eauWc&*{_jbaXq!BFEm8e8xwAs)%!(VNG5YrO1Z(Tb7TtmmSBOs0i@&zzD}8BM+SQOeeC; zAbNmLoO#3+&Fe5rJtbW; zn!S?)GRw{P75DRTFgU_{SzJ(U`MKX&1Swl$r^=#tguT~K`K*y=PzO3y5KM;m1bS4` z`93AzVLGUyQWr-#o@&}2A;2`MV@UT;UDBYt;TMyF2xXfUAD*vhSD@?~8}o;y27njJ zW5pC4Ee+9s9{zwse}rK1fyXE0phbY@8TY^ih6hX?J3GHEG7eUMcA8P&)Bd0L;Q8LL z=4XRn-7UwK^NV}Oa@)O=V(8MQD986TO`^9B}GH zF>@=hslw`I!rX&&JcstgTd(upl4A+z?R}pj?3uyrNVD~VzJ8JkhNzhzD6HWlhlkHVrG29-7cbgt}Mwp~`WnT*v zrelN~@0&0@$I?gUvJ_zhu+Q7U$K(+b0Wf2k@Lf)=jGF7M1ft`^pB(Fj>;~j8V&@&{4%QwYPR?Ot81sbn*4L?> zMe}Zo=KIBjr+C?tsZEbn*V6evmCtu^SX{x>J6ry&?#qWFBR}tE5jx_q4~N1Ib~gSl%j8p^A zqCt~b4eqIsG`^u{7ic>P|HGfaAV3?TN=f;^D?EPuIGBTE%0jJbdGPd0{(#LZLq4(g zHBE3?mQ0UX=D{m5@$;)|53XC-+XX0ZBq-Y~>hxzb=m{4xrQWrXJ2wiw6@(rT;bqDlPgc9KkDC3Qd(-`+m zpa)iaWLV>IhTg?*1%ySoMM*$>TV1^ZMFc3|7RA$ik79QuUOJbB{FS15;gq?{g|oRD z-12zpMS5lWbxXYK=~66YUCr!MKGe$5jZ3HJKH_}~+VK+c8w^Zb7op7bkK`)Enh9kW z<^O*#1gKWx1RJl22PK7JuHWrk#ABo!G68IfHPk&!)1vNJ;wMG7q|BT^xw zl$lu>3CYUd5!uSh=zm;2_w)Ro-~a!=?(hA5-FL5CKI8p9-{*Op$9WtzenA;tEqR*s z3QVFWO2LCr$x%!(FFg(^@#yyD(~gn zJ3D`jj~nRgABg^p{i*liQ8eUwDo*dM=HZH=RxR6Mr_@~~stJrvUq9OXm5a0UP8bf* z(&DgqrkzeDcG=-Wa?Ca>I_i+CY;5&ysfMznq`n4>uD;xAk+mXg8VzDK? z^!kZOEpTyoSN+D$#>8w&+axUo*+)?*=swql9R;di*?s$N#+FcAEjQ<9Jl1;bb93{n zmoKfoJ+bbg>H0(e2Q`keT{Pr&51ED!9zOiyI5R^oPO+aq9eygGmw_Y)9&ZuOef*Pm z{k?D=_W_~{B}8&?)c<&{q|{gEQknXWo$$^})m?nBL;7P9LA~W|j{nRJ0p>uXzE2-A z^13`J0=i!{R>eLUcKfMVa>Pr#J#Ce=%3)*XeA!%hy^iNSkq?92Gd~tUJ3XTi!Y9FQ z`feM+Z$+0WoYGV(6;hqTUb|`m3tnh;E^!8G!ir7txp*`^zVpo#26H9+EsR>13TeQjW`=C(oiHco1>mI$gO~qlZ zoSG{a?+bnj88>&7y~`6d^aM9aEyw?*HF%Ty@6{czOjWGOm9~N^g{r5{C{)YF`H|%j zp1S^0En7-$qZ?w2pqT0;Q@kL+B0N&cKKId+34>~SgxRuRUoIy5)^5}QD9hUuCI5|) z@r90{fY#%DtOrQzx|;G_hPcSmk#?*py z4%*0s>|Dha%!vV8D4#%eA>4)FJ z3}x)7u1i)nZFe_eXf(KV)?Ht}`h2zMS;|vJTX!SmT}c#=DRo*#Uh%HjcKR|sA%)ew z+aR{|_U#iOGq-;m`NU9>wQ$_DImBATaR0;lMhh#pahSId)b6rb9Xs*~9k0LTBaP30 z!tSx5p?d}p`p!t7UQNNIGdL`s>t2G=T>o1hO@TIW3Lu^jhbUp?Vj(O+n47Uj)I!f| z`DbQMPB}a@RCsSkMmo>6M&pA?D)$mO85v_C=hDja5L?&NV`5`tV_>ivtfW%Jx4@C^ zqbTHh-Al@v#IBZCq@*Ywj)kN7vgH zYJ1~4ZEe3hX?p{4@DtnkBGX^AIdg#xzHrscle1xw8(y+w9^TvP(tDR(yw!_4CPCCd zCh{sX^Y)!Pm*yoA`Tr5&|o%3x&KZKnR(5S`t9yWRUWR|zD-G^mtXWt-5zaA`M{$25sqxP zZ?+k7zfGg|cg=WCS1hvmF{y1qGs-(|g`5B6j#4HBl5EWdlYiYc`@0I9|7< zi8sC-ArKI9hF)@Sv&8Twh8wv{o0{H9_QvaA6#&4rJ=Ee*0M=FhoKrm_dBf+=1i)fx z&_d7IZ@?B&3!|#e4p>}a0I~hgn}C9X0({L8_6P#rXM9Y|w?7dUmo81>C%b2`DllIC zt;Q5*Ir6pffF4%QmiBfc`d?eCMu5IFq|kGEWl)a+RdoDg&0sG_iEmt1*y-%($}C!QNgPo-w`GgrOjI`t;?^ z+E-7Xjv#(b6W5c|FAt0ItI?ZUBszL}7?F+oMsAWkixaqL_BW(CAcFsE62rZ&Q|gvZ zPBXAgXiArbvsncf@vsA~{)H=}urMa6*M1B%44I^ziil%yE}Tw~IBRB>l$6x8_4^cP zGjjd7B}k4>d+F=zC#1^)Ux%@#q&5uC3*TERuBVq)R17S7z$(0GHpn>HdAX?6Qw(A~ z)4y!7{ru9`!SHsR>Z_eRer>}iAV9uHp`Rjn7}WV`k<)(ZrO%#yN8LL<(%X2t0 z?G-1_??oo*ZGgApw7pTcOj)orv=N`#(oZ{ev9d&G0&3{{n~u2;i{<*EJzC~AN+Gk{ zYi4c^C$GQXoE9Pzott0(@8WsG^#5HvwObP^rpG@l$I8Hvr`i-X|mT?BPgEulM>?Neb(#@cd7MM zdomq7a9|Sp>4^OSzP`uSZ(aF#D`xjqELI7+%Z`p4!=c=S;wy>OXe{=a2>W2Y5Is~M zJwo(A3WZmB6or_BEC5^xl9wYIC0oS-#C+>Q0l5Nx#*Gz$a@(<~5KUrip6OZaQ8KT(%1f+bEKRUB*Pjm21-8JllAhY(De@x%b>aW!9nx<`S>w~ zQ-@>U(w%J(n@(35x3(3J@35(@t5XLzn=34Urho&S^{yLp@1}Aw8;@m%$@JENk3vyT6?}r;oF_S!XFav z*w!7L#p4sV<``*~J%~=+qY6Py2_}+n-VT!}6e61?Tc!Clo=I44^?^MA^zmPrT#wz9 z?Vz1sdU)aQ2Na0~D^$l|!V;JinA_x1I&h6pghr7eCTANq_S(yH0uLd5ZxnGrM5Jg#{Qxsffw9xk z7jQ>koN?CCxkudQHql!2EG*-5b1uhj$uo?TK%EU~YK+45c+J|}Z+RP&uwBSPm>DQ* zWhxptViJKPGDcxIE-r3-{6dx(j{l%m}+FzX6LY9dBR)mcB^wFN0*UUhdGYRD&(HlFyLVqY`XWES zeUbb5xr5!I5o2*c6LHWD4GsO<&KP!hEhH@`mpDTnS4Z56H@cG}@zbfPK}o$e)_yVu zHpIx_IRZghRo?p@ad6;nc;bp=kQheTGS7WJ6DC@*>REMn>uuloYX~xj!z(yT3=En8@r!>S zh|{)>4}RY1Y_jFww_`ob$wf7N$MkpEhPt@A*PAp46%+<1-KL=hhWv1Hdw%)1o*K=n zbONFDui4Vl5@exbIGqmRRKfp&ELk}TDm)m2me-6I;T&I!o!DeG!9$Z=y-m1EGah^oL}&=jH=O2`N5lHm4k!c^Wi9N48`%cxM%kaY#8Q zuDSbMzztg&ehk1q*Op&mUa!G|S-x^+=gXHk;Y0@6WIQs0{rtwF4UeyVXKE;_IdkWh`_QOOk`<1ep!)&l7;TBmZxbf;*Clh*^De zbCF{K3{GL=W)uNYp*XuA)=Nz1{%YGLM@QSX&qlhL9++VB-}1~!O%R%-*Y@PqZNZiX0^kVOEB?AD*eDxD*b z>f5iC6&RTp_0*%H`n9;&D1~m9aV3k`6H)_EggiX*JJ^!WcrSiGS(q%T9aL`%AX9vh z`A!YIijhG8$$9wDreZfUv#swX(qGr`BV9#JFf0SMoD+K^`Ph|O_b;kwx|vkcDEQ2$ z*zK`HiD{t6$j;6V*&C3fam|7)YcgDiK5QeS@}wA9ZOjWOB~K-h}9 zbLTDlLtJ8aBbkbt0k^u zCPqffR|ua-#S5?feisZH&MszVpx7^#?r`@e`^}cD4ETxg@Vw{SuUwGM_bO!?WH@ZD z=!QV~6NH_YDf~&G*;cCHWS(!|GWAOK>W(GZ+2Y`&D4S5|v=DV%cd~rlEkf!-O4!;V zSAFgF%(E-MDyk-v0ZgLF9Z)@ZF0G}CYY2ztrC(&%mf!AENU2y_k#?h)p!_}4+qvjj z@Vsc?>SfexI$oRIZA7`3*3R&2)BQu; z0YT~)N3Iau+mqDYSvR)a+D};?pKk>Y2sW43+~DMe=Gr=LvZ~hSMrCnx4n7|m4hiO7 zR3cf0zYJHv?-tN?Hw}mW^-%0+N}aY=jd|}AYst5j5fz9Qt>?Nsc8h-pnGS3GaQTe{BO!PyDXOZHe-y>{ z^sP+ZW`a*A&hl2RYo(*3qtU0vpt=>ps7iz@Q5z%qd^ejuWH0d;%8&l2z@QaWT>5cA z5*DRT0+x6Cd9$*pZ?lG$7;=%AeuqPUSFZmx)YJR*Rhh0k?#jj8{w?RHr^ka7ds*d6 zk_7g$hRx1v<~#N^U1RLsBikjVR!NHZDU)<2MN3er@0(56YtrpBUkhlho(yGHS``GW zX9oL=#pLz=ntx#jAoG%huvSK+=A4t#!i`XYN07gRO&nS_-iRB>!!YjzG2UO^(WmUx z)M}x>1jZe-+PG&MM(-Nu6s|LBTyT7JSMR4A_wPj|dT6#@g|6nn(bYr^A(q~9|G?rs zMSo^+z`}TxQH3%bmR}qtVf@1lP#glpz5SLIu}fiF{{Y09!sNgUnQz{>gO&oPOv~Vn zZGSRl-Jp05hy8B(@oGuEfU2BbEoMJpx_sZ=K#p1<_6l#*?(Jmgxi zSqi7h@jEYKUoY;?CZ87=Z>p6ccX080^=+W`S0_E?UXJI@qfYw`C)wF|sPKx??&MSo zkPrFwKxf{^UTOH-V(7QidkBqj(Du5!yDzp{J}SOcr7R|5np&yvi3Yzzz{wLzi9{zd zTqXSC?39&15|PTorbOv`?CYDMp|EVj=S?TQB@-R&(BR*CDS6j%_=ta-nxI~AjQ=W8 zMW?8c7^%AdaE3ZnUNe)?Uy5-HRev#Fh4*^>+~lqQ%>@9Cp46{=;KQI&!%frJ(J?}M z7uTG?)2H_m@0Q86caF|mtapaBdjDByC=`O|EQBVU@mWPn^Pb?uN78y?*D7Z#?gy+V*vONt9La>6iJFc&%_s zB0i6N`?Kk@87+Z3bebBU2{3zSr)kSKVpKWiu$hc?HP!MBXZfqYiM%M()*u2SuL03B zly>(b+O-gK4PWocH_ovu%MG0GD&cc}o|00vD6i<^T>d;=Fr~ z$RjJ&90P@=c0B<6`1Q{eimSJuWeTUCl@D5)uKsAPaxHwntmmNIZ;8P%&c>w^Z)X;A z@4=78#N@JXecDd(ABT-i74H;tC>%+>t2T=M3MA)b7k4gyk)6vQy^)O@@&Sr^9m08g zY<^$eL;%J)_Qrp05!5uezA*(itOS+_|@2TcB&@9^^tC?AY2toXyl zll$=Ay?Ka-5?#}Awi1m;v2c(SV#tb3E%V&Vb1$JJ4d5jG*|V>-dLsq7yjyY)NIspF zBBgYeO{O1VzGm-3eFzXO!6=Aad!#K=`_@&GtjEJ-Lx-n#N6j40ZY38NzZP}#Wfoca z+hGbitqdGN#PK7}zZ+}twM%kR`ftpb^#mO)EiF7F@!7G%j_uYC3rp6CJhBQjz#)OV z1y~#mt)K0A(*h})M7=7UyD0VUYXBQmuP+W!jn`56S|-Z$x$Z~h)`VVqFzbJV@zHZi zRBr0ymvq=|y}VA)^Heiv4?mO=t)v%|Vp!VEby^UD$hh@8U7;ViHd08ZGqS*G zdof4@VhhpbHOBx1*mj&BFdp{$8Me%TCb9KVw4ZonMPI%MGcr1FjAcxn>_1D%E{%vC^i6$w)-Ge5N#R?=_OF zu9^5%|GjU_%%5+!wcRVlN_g`ogSv(x_pgEQ`8OdmikBoFV}{CPuzvM|NT1xxdvIgPBDd}s$V-C zR2+Nb25E`u;gn+mAx73mQp;Xaqx`_slMhn#+bYmqo+6nuq~^(naM}2eADBa!Hw#m~ zdv98`!9>wPiQz-}`PEgeMw|W0PE|I|mN_#Edlr6-vTak0d}p|Dkagd?K(*kbmkE}0 z=4F2lHrM!2=UN0NOS_R)!B~*!@Wr~1*Qxsrxgwm3p~sKtF5?cp-~SH-WE*-C8VUa% ztoH>aatNYs+cs}T&Qo1KTlx1|#c9_YgQEG2?+Mm!Y5Ny(h|<5}Q{LQev?P^Hfy0Tb z?&39jdly&E?|1U<_FrRg@qF(Y`O-r&;>A9epGAW@Cfje`n7dI%=rpXur2AtdA@eu3 zx2OJyK=6V@6m;^PUMWVr_ro^Vo4RWr0HO$dae|@sv2o6e0w0xPEYfg#rM`Gy;el-% zjV}8_d~(tk&Ps$6Ox0s|_%zmj@)liTA0dRKwU-HMhqXKWp4~x+h*+JGLZ@ISx>Dy3 z>SL7WL-dZ?o*rX@mw#)+xD&V`KRVl4%FUa*^Qhd&a||v^u&?FbpqCY+)zj7e;Jqt^ zUdcEvL1*;!!@*Nj3&!H@|N5Yvd9N9qe&jvk-M||u`WMe#&po+pFCn}qK3>jXShd(Z zGB!E60)o;&?k6VfSvh$R9(;mgS!v4Yg-vk zGM%lcgALk*^BN3pbZfRiy)*NmictHt_TvdC!+wCQ(M$BEoQqCKSVy{*=k0yg%7C~y zI6;3n@#_n*yX>YdEB1woI?#iI`ULsl82v~PO;8gjyAfR(SsD3|Gz(|l55>{zbQ9Ea z_0IaEYc5}JZyzkxK(f@W$+d24t0;7!*QnV`aJgr#)M?8p@9K#cHj3m z$Wemw-nWO5_Zg8)Es5(PR7u7;{NU-m5AzCqXOpH{Gy-8-g5l||FOsv(rzP@9} z4&p%z@&mjn)g#zuz^zx<86Ta2#shkfU$rCq`R-LwIWI3`qn)j<>|jgp0~_j zrH}cje9bp@($JtnPdLb$4d}+BKe#B=M?JK`h&Da{8b+G27EC~Y?2BZXY zimgjxyHAm6ZX?76vicnOvP*(J@%Rov(9063C_g|bv%m89advjLp+!K4pNy6yFfMDh z3*egJ!4sPVZ_(mLA=6!PhjaUiLAFt(TQb#=tQsg|KTXe_z9K%-%O^c zvwC`f3u!5W6%%wWw)~KJN1#%(V~<=k+v%pKKp>y-&nnw=$va3Qmf~32?Qb1Eoup}BY`Iffigq-Tz9U>MAWtz3AVan z$zq6LJGj&H7`^3GxaN<3qmdAZ6gc)k0Z5~Rp99Wu)aT`{!#4nYveD9h6pTKF|HQ?0 z0S0*C6hb>c z6A0I-Y&bK#(3M7!;_qYg-mm*PoB1O zewKHGvubA1 z)ammYgm#CcIT!vB@CNE_lB*8DTujqQOF~|$M^Z(Q;>7Y zhd*ZDKbL4Gt8_@i$W){byr%U5|6fh$-_UYM-y2mf-Sh9cnVl2iiEUWADqkwhatGYx z)ttKXefya{+x)p2LcfmIpeEdXYlEcZ(U2r;&4(&zJl9=c-pg{w5JM>L-!)1vzwSMg zpY69hG^vj}iQc;Rt4FzAgcG~^^J$k4D?5AvMl6EDG*2!M^L9_=# zvWwA%>Bb})7Q9|obD!Y`kxKu?`u%hq(nDic1pgE0eQyJInDlsuX5@X1NB8c*5N?Tk zC#%~N%?uc6y?lAl%OvyMyVF!)I3GI!hTj-Em;eZiBgo#z1Q|P{I0~lqibJ4eEb<_B`p|8Az}Q|mv+x>(_AUX z;4fJ8@n{-2IQ)b(IHIH7DEqc#t*j2PO{m~O9%Onr{a653GdPMU<`D4ROHAq8QnCeD z3Od`Yj->XbQWFhq01BZKdQ%Bj!Xgz7JRzYDzR=&e-&H+WVg!grU35=h;Wz-7TD_lYi}tD(*jmOaAdF-#g)z`VeAf4yYPkCm7{Tn9)xXW5Vo7 z-ur+s`@Q1UZHZCUTP8f8CWH`n!pbF)xFf?7a8_Yd0&q!T=qAWJKwV}6I-8qCjvTpy zcUkEDv}LdC9)kFhOzN?N*pQe?Xj)+Ck1?@RB5yTSZuR|_Jq3spvnSc}xiw5d!$oXL zVZDsERZua*gnVWP+)}V4@EX*vW-6uX2r?JR$EXE+50E5sZhzk40Laz1gfw%{;=MZ@ z)b|r`nbuOc@*CsFiTMF9)hiNiS_^uFR;Qm`yXs@p#dsQm?7H7g8%1!p!H}@vJl5_nh`|eMl zM+$Z}*Gy^({<`=D-FH*2PWcjj0cIYr6ykN^K~nLQy<7iAVaD1lEJ5}bq+)XIx_!^I z*moG@kOr3ftsSmWcIydwENZ2sp`oFwT7&cjE!bF#b9cm3!@d%ab_qPW5PI{7(t;CO zf<=}dUgNAhq(|NP{r$i8-A&}USgXWv< zBOwBLgvbfSfD>@Kn^$i9zA7(V$9LmJhXX7vGU!ydgD6)%m|T+N}rpg2c}BbX+VVP35Zla*31e@6(5or>S^2Q(J~|iU{F1 z-FM_B=)kGKb4uhJh#egrZl=_8|C3q2O`=w9ZVsUz;oULc8ztL4lh;+_A{Ij5+LPq{ zp_5fh3x!>DG}TTokI?BJ2ICVSM&3~$1r!q*HBo54Ma3XfVBF+Q9n#h8CGbco^|jkW z9EbhOR?kSb2oKyU_T-|xxHL@W|EVqYPT+Gn&d2v8$+uY!DRLaAeMr5&GD>&d)g$zO zoe+0_Zi_-f^@@4Mb35Y5f34)gBdKUl;gMj4e-_n*%7dvXN8K2ibgQF;w6E?*)|KdqD}nv#@}`3lN2p zGpKp0Z+rF8ggnJMtp>hnRKkd0;G0|h3*RV(H5(F%A5B4*MLg>Mspoy|%2Yf9DQx#I zeq{}0j^N9SnscY(dFJHZ*TT5nbCLgZ0|WbK?-N`qjou^!r@`}1pHlfsJlbpcKG?|; z&-AcEj&(j1yaaFSO2(_iQ{rCXfoL`fD#g=6%x=66N(*ZL<_U;-#x>)dZ}t+4sExf4 z#hyJ20qdBjy7a5DoKl#Mt!=)et=)ogXkDrRvkTxagRC*|j;9U5sxvgKLtWW*`#)6V z1zv%$>+kKo5*{PqNTs*rJ5KjcP2}bq&r}5D6H3UBruw8AWKGhn{L8MWjMa(JE=0P; zjkZ;3$6m&oP1nc7yR43poh9tqarGzj=g%BHkVk)uA_VFGfplg8kM@uekY*Pe#2t&Sv0z<_3^zjN96^6O8rZEy@noEgxagm^;XJ1|58Yz zA9i zoF*gOg8eH370qKjz;bgD#@h%%A*ZuC;F+z%9ZtpkQS|xq=k1{gm~{Xfz^@tbMh+O* z+RD5w=# zIU%NSA0A>l@Ne?wLxjcko91)``Kx<*g614FWZ47h{pNb9+R3&811?8Q@M(>VORx)> zP=E=&Xcn%X^8fP{K^y-5^Cuc4wSwKXbu%T79b3c7iH@8}@5w7&nd)rL^W z0p$RB_bW3|H+e4*w^0)}&;Kg0On;21!U?x2!OFL#taNVt)!x?Q_cc8J{JtbFYnCG{ zlQateM?^%##YOSjwJr2x;f)F$s%K9dCRj0++`UR`{#@6y?1FXZkt%<`IltW*B)Ze( z>sEeq69Ts4w7YL)3yIQ-A6Xa*_GjgH#RWwCLm8AVdIphQd*!`1`jjd!!$)&J3h+X5 zk3TiY!k}|%mK^>6!X8FcVnu9zUBG2dJ5ISQO$3SAtY*|ZHIlP*d8$)nkoc37{&>>a z=Nt%nSj5zx@v$+$lVgSIXnf=2GFOVR++OrGK%R0g^Vb?6J=7#Jf#ATT}rDl5yzMNLf&(d{3jwGq5`LRifRcrJ$A_y2ntSLc|LA0MCm zT6wH2^u~>tfwnxGZ-WmS#H>iUe4xxgR_4X<7i>ut-m}6V+htxe@#)M}_3Izhx3+#7 zu)--j)qxzVtWhw2*3^i`g|9< zQ_tPei1K2sl8ty_$9JSHx%6^DPhVdj8W1u$dwJ6Sg`Ll2xL}|}Fn})4%sc>H4F2j_ zIrSf)2&$tsZ)Ro&RU*nuTK@@oNF~SkQJS#JOx5o2Ul)ec)%)P$qq|CPKH;v7tjWI= zCr-XxacPMI8~z%)6$y_YPnY_E*ofT^496E3P3dKw%yZUxo2+WY_Px9%YA>(3#A1N6 z*TBx_?EZ+v7R;k3ezV73MU1k^FuNc7`SV_E=u=)5b?@2P|2y@4OnNf}!6|i(FZn%Q z<7`y4DUY;tSFNMNkHsDZrRpQdlMr&!U(*lzUr88f`(B?C!hJfjZ1LicWDS1CFXp2R z)^-@H1XpNfob~UuYiu(4V?TY?m#zN%{?cFm=1uFybtNsqf&X{9WoHKqY{$MZc|S|> z&CVizMp{nr)92?uQf(j2JgyYhaF<&ld5&=v$E!rD_z~Iu5Z)M^Yzb%Vlv+N>kK7{0 z`+vxfhWeven_fxBfx9!kEqxmngW@a6Tfg`FEYMObg&DevvV_MG*Bp|c?5AGfWlbI8 zeRjpsR_Qi)LZ_FGJvgBlcIUtD@$3D8Hf1^?NLPOH zrdZKjm3-?LH!hM>)-pOxn8l_`R5Rh$WZMbtC#KeEbQ65?N~`;#ttWJ*yU7UW&#$&U z`JZ1HuY=rrs8RbTAqdC6S{&R3*X)d)2+PguXQ`f11~k z>B^NmHf{}F`9Y!m*fwkB_fT-y-S3$yb1|?^?yTHeD(p<>3n_lArmQ8npBVR?6R7vG z+|lMC)A@0`PNX2Ts1eo1I^g~$oIh2G& zXbO((y{QC5@uPEtt@z`hIpS{tVy{p2hva(K-Al4!xeQJ#$uG2&JtQp18I}4P08xPJ zYh+-+!pQi+TiE}Uc4(ynErn_E*AgQ^uNf*c{X~SAfv-nvO!rGl7NU7xQNg7MaxK_Y zgS&hM_QdN{p8)9t9YAMC$KMMJC(oQ2FXd=fAy$qqdfRIx`_{GPTHmc~+bfa(y@r+V zLSst4nNnB*+7Gv^x~i<_9>KpCTs4Se@o7JaB)oPX8Ak?g`uZP~exnLGq_XZUM2Ll_Mv}4z6(4*>VYg@Iu zRI#k-NA@|Su9Bxo+4K~}8E?PY;q5nSDkM2qT^oNS9Rh6!%@6X2(0dc@xWEp0Sig;6 zv`vT-FlxHO>QLsHnTx18BOeiwcFZn)x-VZ$jYmIT7_W2Yhkn*ye#YB48EUK#6VqpD z5Cw>=W00BO?RsVA9yRbL$ZT(<%O={Yq zMUI6Xq7lI#U2FCvV7gLl|9+x|79c|?Pa*{wAEQnRUgKlD{S2ggRMr9yPYOKr?d{D0 z=U9FAFyrla-gAnk4buP31xSAKq*;{KY$8XC^mE9AhB1Ku(}gO$3rkA{>_f=`4>f{J zX-tGz4n?0rTWWy$6wMx_+apfr0+nCUPIolcpZ&?xdo!=lPy70Z$_MwFPadm|2ip^! zL}^ILXJ-plT;{3nU3+?I+s^4~X~KE7rHhW=OL>PEss!4JI(JorgO$Ks39ZlhM zhru6=<_K33MZ+qVdoF{IHIjQOS3DIN1CVbtA(&}y7MWRQy?LXXs+pg>Q;_Fp!ULY3xbW&!Y#BXWRq=H9?nE<)`sT*%P3h<;1W zkZ7lbqUWj_+4HxUl4*DF^eI->8ya&j*`Fi59TZX;nwKwMk|L|I;V9jTK*9?&8BJ0H zGqW5W!5+C(-ur@LVhc#rXg{JBD6Y?c|8D?II85>hMrEL^S8vOx^EQDPq`6YqgI272 zUlo5`ytCJ8(Nd@! z^cT52`4#SN5$vW(UC#CS(1h2ng@xkJ-m0XdEH3%dM4`g=rjMw4he^}pV%foeA@bbd8 zaN={lVGus=*5%81fS_XeUvsJctSC005ohiY0&K+#q=tYd;RplKQqs%4S$?HBMZ)|0 zofoq6Q(ku|?@>3Ut=^am-&Sk#SO)?KmQql{OFIAd!ue~b`5EOgm`eLm?)O(^@U1YU z--7*pOz?Jsrl8BXj{tL?7OshOA7Ts7Q?xw8TzB!g3wb4-upsb?Vq~;(i2L8gyu=aL z`!+Ew`s^p`1fBD2s#+Oe7+YJZ)n9L40GDdv`$O%*V?)pso9-q2o74t;%~A$T^z4Pz3y>brRXK1M$Bf zP}JW7tK04E+ikJb`-HF!i_e;xP7iU}tMTVOih3s26~Jjm&}doR#kIv(F9vie(NEKgoUeRN;Qz}8$Rr2_Uozk(xXpCZ)K?@g!^-RwIxr$8KfbTnI z1V3kKE{X1eb={Gh?k$&Ty;ynJ1G(8NYJ(px$PcPA?2m)d9j1|-qDr93PDUqZX;Ve) z^PyEGQ*anlVg6s`NGY$?ZX?8hZLI#`Z^+L-&>8}$6vZe8iX>}a&+X|pV5a7dkIhXsfhkQ@~9Kr-EfV33$@ zY++G(v6+hiG;{0)e~!UvEx}l96Wy#195Mc^BY8mdzq=o6n!J+qU!$*1$4}!DLE5$X z_z7nrr|)WBybkdDTra#3OwM0|HYIRMn@aTgl{W2K&#T{;{PpU}XFWDzcO1XMC zT)K%#TW+D6Nt?*;c*Z30$yRE4=&<>A2CgV4rLnOwm?-9;$d<>^-;vdcw)`5b%D^EY z9ulw0mmhan-m*fs*VM>}$`Z3jedjddb#ljnA2_etW4_f8(8)LOOu%^clu1IB7raA< z_!Lnx>b=n14ayj58jyKthQ?wowor9{@-|b^Sho89Pr`z5nMs5O$+YQh#@~eL53pT;cEQ?!E|eY@>w&s3eG0U&c2u zX$F2nXadcpt*|U#BO)4_k(+y=$WA<7_O}4>joas{B!Ew(ca4}VxE_E5&DO>mct>NU z^t^JtVq4c7GlMx4rB8WVIbKg3DFxwS!HbbieW*&ZZ~I;*b_XTTMCDjIZ*2seKK%1A zF3x`GaCu(d{eI~y<9FBYpeX{vFrhaHJqespTo=oE%FSIw*@}%ET=QvQSLQ$^vyjcM&+edD(A)VP}Bzaf5~`w-yzv+6S)dc9h8EBN-x zuxugOuA2#duB@IZ00Xt+48Ox`_#&s$XpqP)=#@4(WB$M#e&GrVf5CEGD|&r-wz1JL z@pf345#l)p_Ksye6i+p6`Y4`?k{j{}Sd$`vx~z-rx%C7d1;7*p90W}PCa7)b?9nDg z4ADi*kQRtO1$3dYUMHmQTcy}0!^T_c3c`rn66@XB$kW8I$n)%G33UPM?lKl$QJiSv z4^KUZr8GV<77}c<$fCv*Fi3*_MgoYM;Nm(ps=Jay&*CUuLkKCloc%v7kWnw6%{&MG zHkKs@w!9v;s|h^nKnv#gzMD0;;%qLm-zzop={F*3 zeQ5W9UblDm4{sYyA?JBBRH63Z*sn>)_fPEAc2+8=9~>NXA2%SFH15W3<{xnpNE)iG#biJ3 zRJ6AjtX#S$DQr=ZILFxc0miIC3Jm$bk({{n72hAd+V@r6=g;-|RBCGi^d|P$JUv_O zeHKiktvlOlaa>&&WvDW@)nR%WJn>dwz{gjBnes`i9~SQ(oIZwc?^Ew%yp1kUx^Ct( z-Af)G9(aGnLXAg!@HaFCrUomogB+uqsd?ti3lvBfQSQB;xmR!NZ&+6;B{sJ^+fG*J zpWa6%8D7q8eHpLF_B0=16^$}yfk*4}g_?r*HEfT$1qU0(Lv3LUrSazuRB+H@0G{Y> z`e6S;nWo^fyd1H|&hds(q^WMtv=@7%bKNTaxp@;tJlADg97cJR-U}wT1HWo!uwb%K z%6WJ^%sh?;Cev)D#Wr3!Ad;xS$igCtA%Nib z@O^gijJ|4^vYRA#+{x_RZ1<-S-pF6CiLEZgd;*p@LepyQ&3RQ1in*=8i`{#e=6@B% z9aQJ6Jj#G(oEB|cQrBOyEy7-=$EXsJ+29xYj3&kFpj`{`HV%&z*{CL+SGc z3m_~d?_nAy^ef1dTCvvLHV#PVaDe+O=?Zz?`{ zibjhlm}!3Z-(TjraiU?t_%6q>MaWH=2 zosU2?mvm&aP~RUyeqz&ulLq`O((b=jfYq>lTIK zlRKD?x~(#jU6+hmvGs-eu|fc>o}Nc3>mHnX?&jteIbHXXx<)cCyB2poxpbB5dSR~5 z8K&DRMVuc+@AgME?{uc)KHm4fax%pA#Z%JJ+8{07UAO0#dqGT9UpWB%hQD~ZAM&=O zcij>vJf~8KvaM)v^X6^7*5UaaYi<250xP7a9S*)_UqOzBp7_4&=Mlo82&g~mi{5g&RB4MX(zs(c z^(UA9pxs<=;UMuCZ~T`JkNQb%?Mjcy2OD<4q43&j*wQzD7(BzI8#L)ZTL7JYjU1T8 z2H$G8)te4kRkTw*bp!mNBf>51s<_qK-(QXbj>U$SLK!U34LdX>(V3}<1Df>g*|Sd; z#}_~GfkWAm`x3x5QK_}$?^TH5o>U?BgE3M$VZ3eh_f90IKXC*dP>GUR_I1)z`+oBK z@UWEx`;jA=+T1dJF<~0dpK2dZ?X>W&I?W;L1z`=(uGdyOeGU@{s}=yvFuobZck1QU zM$13L>Q`gJj;GZ>oVZfQGB4kv^Atln@OAIbYZm&>`N%rB{uKUxZ#6v`j5w)~cf-Afe_uJ6a{`%+Cd(E?6L(&==pe$YJ|1_>hsq-&1TE)Vg|^ z-Y)OlZ-#y9Px_XfTDjRI*4&q8qrQL8l9E7ZTuM=qq%L^!PS&6Cl+~kS)SehigF;KZ zh%hxoiGc0kLrs03|A3T~)PCYeeT!@f5?Dm06pDFCryl8ajdJs-lNmn|!jN;9&%Fi^ z7oo<4QQMFQ4*QeN{1_e8n~AnZmV|0RXm?M4zdS~gQacWufIFpHTIR9@w-NM|u3`w* zPasvutHP3xmSDtlGV1sANyp76p_Dl$>S^kCa;XUfj%WL4Y$(?=(p3)bI^g>;K8abH z8suJCj|m+~G7Krf{U8GaBz1LlS?8kpLr`N}B2IKkIuXmIsU>2Pi%JrwXQECzesey* zD|3#))YR0WcQpGhe@zL(Yn5;QiaP%veEk4X-9PYE28ge5K_hhy4OswfmgPPw)5$-I ziK(?tCM6?-W(wyyc7mX`rtg}$B-z-QYJz0Tk>;>mDqL;)v83(KryXgUp1!`*p1<3S z-t7LAuB9ltTi275lh3GNbVJU2w(qIx9Vpl8cX$xpWuOj0)B!?BWNg7^tiWi}kM>N1 ztUTKAED*4#YeqkBsmcK8=I2+z#6QJL-L5-z(Wr#4h$NSm`Vogd|9$X{W8*KXEHVj} zm2J%09)THL3~PT{muKRFNC`UZyH56BQjk6Kj7#aVncBA<6oomY}`y^*lTb>B(G-W?8f zQc^|0)$r7^9gl`O6FzOFNN(DT+`k1jdrw8upXFUqO5`olgy&?W~j3L~% zAF2wX%coJpI2)H-To?|O+N?K!@$F46ljJ*NV`2;z4i60}LJ_XG*vMnoDYzKly>$E< z(#45`kLvNR{kcAW2`D8T?L6`GkMw4YGLMRi2g=c_8*ax%Jm!b~F^-NB2wk;UE;m9se9Bl(VOu)I=kSO z4k?t^Hr(7#pt`GKe~e(wuN$@h(#7L>&sv1MSIjqNEu^k(tRg{tD@Q{h(DTN83Dpx| zm^^tU*;+Mr^c^#sCKm%kYTG12+foYao74Hm!l6$Oo}KXv4~jtQtrDB!8mBt8BVNa} z`w2C<0l>1M)KD%+Xe_L(s2j7iD=D-E^8DVEf2piOcUFyJ>1^iV1;1l43W3a|1VYd` ze$OjsMZf+Yg0zrdG}P0A5Oj{2Cl^uyrqB zEDMz-9-ZghfV_~95U>_3|L3|;FoT}EEwl~guS$TSk)3_lOcpY&;F?RPpNUWlUWavY zheJR>fU04t?I(1i@qBrZycQU9?%sXi9StG<&kX_17tLLiQ7=5)M3%nk8plt(BoL~O zJ#MXW{oMF$o`dF?cAoG=_C&bpebW7@VfMIhOtj%lKb&AD*Bcr&b_v{fDHdYsi zbVYf;!XpaLh&N=bq#p$}l(krc3#aenHzCt!k)qD2l~<0&J(po(7utO-`UL5E@y847 zn|GQN3!V?I=x{eGk`UUJ79-0x+s*8Ga!~k^qEgt{j<3~PTUJes;tvd14*KFb3 zG1NC}baeKVsc&a#EuAht#MyU(j7)GasQEhLI@Fbj(cx&7r6_$1Rtm!LA#G#JaD)AH%TtsIpp9fKWKK71 z{cfO>=nCcV?~Fud4r#sL6(5ln*^N!Vs@%Fd=!3ZMT94MORo9sP(v<_NLIq)IZBGwD z`SMAK`*|aU4<@otU{zi#}Vrl6FRopWg+H?Bun zfLSp4cAt4_$K^@8w`d(jJ=5wN=qFZkr zr259ChS2_{9K8a{N(u^W<63cg-CYZ!8S}e>tt_aL4_Y*=zhm7sYD_IZQHRoC>DQPQ zq>|6xS_yI#5|?(1E_TtG~`0&IJcR7u%dS9() zl5F}wQPt0i&WiY)3fmgBd+P<3oRWT4#XY} z{gW*Muk}?_F89(#YJ}gz+(O)BOuapZ&C!^xInUXxZE4Z=JbK~Qi2TLtXB8XtxdJk< zolJuZIjJMG7_4a3i4F1>o36BcdzVDCv@F`r`pG;L+Vt+(fn)bu!f|gBl@VIAsb{3E zhAS3Ja7D|8v2fXrxL#WF3~SWG)jrGfjjqn+!MxneyL2UTYKA) zcmc~lzt;iT^sV;Axe_S<7Fy8!va{Ao7mnQ1ef4#seT##d@{rzwuQ=6{4l)v{zpG3O zaa^5}sixpvcp5U&NJWHmB*lq%sSFWi@ROA@D zAAaK4E3wD=?$S6zt19^8sdSp%+&q(wC(6(C;}k{m*V&6}w$$j}I+hFg(V|}8Xz25! zpN~}1FU4qqDUW6%%`?)tk?vRxzMz9IU{eb%>Q5Qf`iWW??pOYqOqDqx%anIPWkbRs zOW%!NV-iX6sz8DbwMSX5;?o$_Yp3a@qKxG=iVbIzY7J)9qy5zQtQ=}*Xtb9C2t{Rj zdU|(^kn(t-lWKZz#}&m#yRpT;ypfL40-YS9CQe@+yu9-H-(Hmsp48wARym0`C)V#* z9vT`l3Mb1HxL#9y=%ljY3KEGUNmt@{z|H*=D{1C~yu(-`wALlY?%N_kh2wMbng)b; zN|0NoHaZ}L0?VHJ;O-_MZ#}R{hBcLbV?TZj1Ip3R(13^nBGNar-KK%~M)ZXv(`?GJ zP=Fytb0PShuC~r3yymzUPSx!--LR9KKi+Q-_HJeb1-i&GD-_0>fB#_3D!;L*sStnv zPxCu=_7=rx5x@R2WIyryduSJBdR4mi=<#IJH(!X-dI^&O}Xga zG&D54iI!j@A|6d1J!e~aIvgRAVxNxx@r^Xs6to>*g)Z!g6GCvJ8e1 z(ri*vMnB~ujWdn|$HBy8!~l2*;m2iSu3fuun(y5Iu%Ys9}^;G=pO?i0_2EoyoUHXb6%%5zd)M)&p+7EFd zDP=o{|MlHJ^;0L9XCuS+nQgk3%)2Fh^j#;vBkj8O(WRxv7OCDR8c$F8$Cb*|zl|IbG4Qx?#6cASJg(cDIWp*hX@Bp;S@xKnMsE`dubUgrXcb749 zb$y83KtNhL=7+ci5^3boL_;DYBPzlCNS8B(dUTfahpRS90hz=~Dc0P`W*W_y&wlj&i@*HBj;M95 zU2~f$$zVOKBgVlB#Yieg{m9%18*6Jz)<8D3@JEjx2~(Ga!Zp;^mdnxS|Au@EjG1A2 zvx{}j$mm@tZurrH=6#elF#Y#LoagDrGC;J*z>ONp54pLC9^X@e^2AFndIbTxbrD*h z))7+9$VT;M-6AU8A!C5UecIdGV0a4%eqeZ|n_-2{ANh;9C!*PtqVW!b%WlVo1;fUe zW!&v^g%*D)USozr^=;Ya3;Nhi@0D;-Wc{i{&_bA`4e+ABJXBdlbu~A~#TVP2Zp2qG z)gE+Tk!uKq8qp>m;af{#;8gy2suSK25iB5{DktY&cM5eLH62?XS`KOOE71CukWOq4 z(x%`3_bsud!RPNm1b#1nqfr;lrTzv`bqxfHxWP0K0oO7 za@$e}{<{N4!jo1$B~gg@f_TSz;^zPP;rjBBhXR^27Hu%q#j&)FNK5_{S<43v(_^_H zrzjGU&T^<{SmBqJhvM?Hf&!XrI3oy|)0l9XT9i|Xn-#*a#sgP0_^g%#5wB8#9mK`1 zi_vOiWMXQA*aak2p+ra>x}$UdHoA56N1>?#9E(-V_G+&ZF3~~m!M|Li4fUZzwYUs^ zF)crQRTyMtg^K4yB_$2q+3`yftpDq}zznw!i>z)$LGXVjVb)5xY|{BPzs%XMYbSij z@B+C_lS}7utAq?DK*B;ON&)@rX&%~*uPb@4XByI2yof)tg#o#M=DE%h(A^&dOrzpj$FLjl5V zFa-ntAdDA!El@JWHitF-f4WBak3MjV8&=gSovB`cB00x+o{+0O~y7(_#yJMte+vQ#5|1N}vr zo{eqz!Ai$00GfnsYg!IA6;DD}R~J~@h7u}?^(d5GRE3NGv`#%hC+$pzvU_Msn>5e5 z+4SxIwRuh=@<*xpBlNdh3TbJ;yeJy4kwr~A<9n?(`sKfXED^9joU4bym>(Vj2zy_V z;~7s>(~g!?@vj0(aB0h45-I8Fe!pEIRD_erKIixAR1=T~0Y~iRi4+hM%K^~`Gy^eT zVUW$y7LN8bv7NWb8WjjtkQ*(nQec2W;+}?luz1 z|9!SqDZaCnF7n#->*(;4N2Wn2MJrT-hMjgc;{cI3{533?oSI@Z^FIRb2c%4(@iQ+b z3yy2e?GKNPin@e=0PgPGx!vE8Y%>AXxOKtJ({mUaw?T}8pr%EIg`vd}qXe3u?F#mu zx3_m-=Hn^6XOY;oMC`UxJ;MNlpIYwNfuT^oFh9G?sihA3V5<81C)sb965F7;pV<9> zPqIt}kcb@6)Kr;}g;!7q(Dqt1UfGcSBLF$bx*t#mRtK575tLC4GEJw6QPR)7a}mWU zy915DPzNLT80@r?^(LfCTy$g+|1$<#KB&J=(2=5r8AlJS9cuM56`^2EFG4%T`F#ov zO*LkNB{xuPr^d&5VP0?mLU?7FpUf5H{{_d*E*BzE_6M4jWTH#Q|70IQB03Cc4Oy-^e;3|aT z`<**G)xt}{|INMyLerZk0k@?mu?@A1$z}`Q1VBs;sJgb?pnw2$;2%>Q(;;|MmZ+|%GKVm@(c;C0Gx|r- zpa|~eSq^kj{`SJs#oU$nrkbP{wG_-%lY{0FifK3}3V_8>8`=?qYNiy(EKqj(`sK@= z)8AqcsmSIiEgSIP;m2i*dW4K}v!XIWI8e0aL8;ln@^yH45l}f@Jv5N+oSkY_?|h7J zQ``V5;bTk_iKyhlhWNz(l(dtIZMU3#-L~;!ZnD*@(d$IK{QPjBZr!>C(YuHU&f?lx z6k8ya6do2N#Neif9aonjsO3D63F^@he$l)mm)g)r%mM+OvMIxa znn}Dj#_o;?+Y~5rA#4igfQ_M%_C$R`8E8D2pHfqBPz@w1&y9X5Lw7ZA^D1nWM)0?P zpqdJ!1*|GCbD!KAO=2PgA(K%J5x0GqD>L33z zxUxoCio2i1vh9Y_3kK8~O1!PE9>nK|1_Vrxlv1PK7<)KA0_ptYG+q4MBF8pZEQkmj z>~t)7-b05%QJD~-|}2Ozr>(7x_XSat9?>b{67LS!t_h$8q1?7h^)XI z6(Xp|WEIUgB$evzXoQ_TCG!Ds7D|U5APEvP0Sol-b)<9j`Lu!ELC_W$xiEC~zD_E% z2MT=`7f`!&x1fo$2g zZapHBfQn=35&w4Di8PfYz~>@s4)IhPpy1#42w6wl=Ngwc>ut$34z|%Ug@ci=bCB}V zGP+m#XPENH%!7DI=7nL)o&U1kg*FW&Z{^4Ed*JG|o@<2iIi}Jbn0Dh`#={7J{4Zfg z`!OJMDv%3Xiq1)-BGlU?tX{6ps~*I0g8C7~Gu=B3WEZUv{iE1caOOv*dXhH;L}PV$ zP)C1mJ{;Seb{h&cz%Z5JasIuA^Jfm0ja%DD6Rxp&4H{_&T3lx)`hXztZ{Hq6;Qy^T zgs9fCb|I7^F%1`bBg;n|od}3Dpjw9W-IS2Ns@vVjKR4GG8Vy6d<&UdoqwtzWl} z*6g>JSeklnzO8?Tg!tTT2{;HhZfvgC&tJFZcsVCWlse`pK7g>+p&P>N0s?PmEQ3|V zP$z=yZS@`b_Lu|zx95G5o1P9L&<>4hfRl*|2q@f;nyRd-;ujEr!^kioCnJ+Y$rEJ< z7+xjGLMTK;sb6C5`UQ9m$*!kpy#LqeuH(0`zZ$fq^du&nH-59H=MNY&@LTII87&*+ ze{2O}3ued7sqsZ$n&c$5$lvoMr(H*1Q*s1`gfJ4(Hi=|`oacVrUw~w!ItlBw1)iI; zZQXh`NoEeZ6aSXbMhZffZwIEaz*lpF4g*SU@UD+8Cv|Oi{8+VT{X%+v{?8_h*zrIj z?{Ajv$#qCZXG>wB9Dyugz{Ad+jIe-^%H*86jXUK=Omj3wYdJmK=!E@54DdnyU3t?N z+HBhI#n=Fo139&ij;e*njs*T!{H&-9ctP3Ew0V+!(g<0WlFp2{)Z0}n`<^RrB|05no1&%~ABGBOfpI8;Y ztJsPmIfTd`3Xb{`+b{*lAC9G-D2&-TC?~_^AnwDXCylkD+5$DCI2? zP(CpFJUq-sOA8W&OIHO=V!geq4>BE!05=r(S!dmcujA~O>bue@XG+`L6nxM6*v6}72Zt0G{dZq(ACH_&Y&}2 zpZ}J2?B5?w7!aye;Myn1C!=01*2P}Ra&tdqw}>zwybyR^Q6iQVBmTbB0;KBBKs@kI zN{Co7)1bM35(SAz|9+H?-VD8q-3U)dWT>cq5JO#1JH^X|eO*V0-D2B{9;XZS_TmN} ze!tECk-|Ozkp!3%@xkz@oNhsE0D#e$LSTBR`dM4wTgLQCF2Vky9RIS$&PCHm_TQq= z<>LjDihdVHv)>N>-@GKZp11c5Qh=VfF(*I2Tr;&Fz5nZX^40ZEV&VbXu#oXWK1%?4VOXb}sW;xp581MW9%C3PR8vH)TDCAY-Q7 zY(tb0|A$E=)~DpRl~2AB!9OB#db3LsC?HkE5d|b5*@U68x<++kXTG1V+VTx8|H=`f z%nVWl@b72u*Z=oN!)_NA7BcNRF7PyP$CA4hB2u^m2k_wO@Zk_Wg0?$>uLAPBKm8LX zgQz+!Sw-TTT-Y<8X;rWzwmuxJ^7ZDfaMk~`8gWP_5Gw@jj91T3-u!zo*Btv%pY|U> zLu4UKZP}k|@n^!lY+$s0s`FidlI~NdR#E;{a`N&}utDf|C^<^6eWJg47!paa`tTGF zP-8}-vYt(J8qC7)U{;GXlm}p9J8UGY%e4`iWH^MJoVGQC`l@7Ouafw_R4&B*UONRae!WJxVM_ z17`)iR(E!NXx8D%APT<8Y=6}8PGbC%+4L1+HVFR-@ydz{mu^{46rX9eF(giT(-AeC z*C;Nv8ejdgs<&_FphTGA>ke*@>G9(`XKF*AJi)}FYgG$eIwZ^`5Z;XY-Uko{`4{Lv zt|v>w^>-rc2ljxee=zsyXoCa6VfXHj6j`uFyBwPYqUU|q=jC*>L~evl1Wn1a)%PfB z3(&ETIyqExN1mC10q^8}8ukYN=`1`gwgl4Y6Qi45T(YZ%TrnU=9@m4i`Mym$Nf>hr zkB^NUu=AcehEPMGC%EdITjiTKn11OW7)Xn|Mt;$dqRkn7aCJ>>Eer(G=I~x60gBV) z`UiO9ALZl(RDf;X-fp6|0d&9dsi`}%o|!2t=}#arCYV;p?Fpm_1AUF39KU^Xw^frS z$lRE(VB>qM$sMiyLv`_`=(8f;1i^9>hF=I5mH}YmFGIo%5Hx5`6szM zKPomac6EQ*@QQlNY{9upnitiULJ#7$K2c#HgzRN-uA~P#7FY_`4^N z*Y4;rtv}VMhj#djpnZXEo_PyJeSnqZEG?L`W;Z9#91`xAv5>mdB-UAE}%sNnJp#N!bIsSRx4LHf~ z=a69=^yT&n;{p|(c`xML(0~kwo#E4Hlk`T`-9AR{7bM;R!K(1Sap%r)o6R>*JVS2i z0orWZ-OXTVPBG^Tt5Vs?RNCQjRdIOx^;>jix#!U&OjS#a0 z$?fsU9?hw4q#K}Qo4Iaob9{z&Sq!L|nV!Zl2R#W}oI^q5$HKm=Sy0DEsrZ4P+jZzY zde~WjB?s8&O=#ycPr?Wc6qiA!eYJs64(O7=E}{57HCAlR&mUjs)BYR+&kxu)Fo^>o z@|#Y@EVB1m7I$yo7PSeS-tOL_f;Qv@)mhBC#q}TB4Kbf7%!_)Y3kocHl)n*|ONiNw zTbz!{^iw+HYzVpA$lU+Nroz#WY9$?<)N7(Q2&;?h(bCbk@Sz>G(cGrz+fBh^Wy z&8s71FIHO5;4WH5u}uYQW`6#ZgXZ;Wi>uK^mtJ|>uWq3Di5ZXwkx!gF1EhFFWoji zyx}qUY}K}4M?45s9e3vSEp)>egYBPa{$2n(NMfcKe*sjKcj4z zXI)%r9`kZrUb>8ljt&S0k{%t+pXlMiE-E^Ea*wK4Wi*194LdT|`yvx84yfm^=fQoygn>*$dqL4%w*-g}|F3$BRRF}ti$ho2J7Uk3!BNOX182rtVQ!WJ$$==3QPrKpDlih;uu!~ za6lSDb6?!KO0;sOgL~mp(9&|9_BG9S5u^x~SQdd{z zEZE58dV7E?4mKtHS%qVxS-=SOqk1pw?*UafM(tBWlA`vLP7nT;wBdLdr$JdD?lcj8hOg88%t? zT=Rz;fm?KH7g9dMf?9v@K{*-%(QjF?Yyw2#KFFjWN)QuRMFs@(F$9a6+EeFn?y8%M zaTsuVPc4Gz|18>y>E%e_Z;Bt&Y4m~#1Q?8<2a5Uq*p5l7&}P$s{R&wDP=dc>WaKUp z_ZCLD3JiquNBOG%vvzluWWhLiX46RZ*AAX~oRY%lp{1wy>en7wI_Ri5zNQLcl{fA? z4~Xue$x6U?Z>u*{HEgA*_T3iF^?c@gx)T}EJ`yBUlt0WeRF7>CBh~|K63`^l`s4a^ z+&mEhEETRby~2j}S%YAsVD6lHk^>q@@QAzIBrmBi1tO#ya8P2e%F3XnYHMc)p?+i~ zVE6~E02FUS4qti7`_#HC-xR{ox@_H;rmqaOxhHs-B2rR6i=tue9NY5<>oE)uiBZ9L zJb|l_wxFA9zcNruw@gVHr}e(RzSm>SQajJh27hRGg;R#d-Ijp1jci?99F!r85NC71 zL}7kYx|Cu#nrOH@t}g8bMQ$#aK-5}uF8hv_ZDLHuXPe|Yl-2NXb5m^3`u4p!i_Ost z^+)}qbqL=u6g1s1)E_gK?1VQv6>nt8t4A((nBN?l=<4J?;FmZlg2r9Vrg~+NI0H=y zM6e_mG}X5Mjv$ky(~U~&G$~8;(K;!D+58r7BZ8(SCk~m9s6k>(95FL&F2B;+8|C4a z+2Q0n-s+Z@Bq9Zuyf^$z#nXqF8AARPU#{)#EmOt9n}Ff~ctvlLv6EnBF#oZ<28G^+ zIVJZN%_iRXI&)?m^NL#oSP64eQ-Qk}RR_Xac(dlhRQm}c%-FWt#K<@bb_r`XkrZv- zhTa*1h;qb?hRL2+yiU_TZoY1>Z2W~-OWHT5G3x#7)No^G=VJA)&N-Ou`C8uvh*#Yi zcu`kZw}hZP{Pxg>R$Xb_S?u(fbyFCs1Mc~EVZ3fx1R-EU2S%jtseP)d3J47#PQ@f< zOGI?t<-8g zAc8vq;3=N!n>nIc+Sc|Ph$}5-5&`?6qKrWR@D6lZDe1TeKQi3IV>WL*fUr$g4HmhL z2(-(uZfS_yvkImXp8}rY&clzo00SlTr=>cXQk2C_H&uG-Jb^HH@{ZlBWSkOF6+L)c zCKoM{Xc$A*@W2q31OqVACfC=0{$4Pw&WA`|8wzyc+y{^;H)dPy1%3s(6~bu3^ut#Y zNym$ru3}4!NY~LK$!N;66ph)sAn1Q-Y1QeN>=h=k?LS?ldCmsT z7V_U0L$|uEhF}AoTu|*2&_t+;>SfwH&wBVZoK^F(*%G^YQK(Qh|jxRX)FzZz=HG~4ywY9tnC{V&IP9fntU3_jH&e)J+Y-FStmJhofJqU;H zKtQ8QP0|)K$T7AmW;!S7-aTyNox65L`$K^aNb|dV*Q2*J5pv`qcB3T(lOR7YFE7tB zCofC?_hVeRHkL#LFQiYOFD(2fsP+!Q@$1)%aF=5jG1d9n-7XYvzkS7LK>+)84Pe{@ z=Q^xKE1&eTg8l|MZ=W5Qq;M_@M*G#!iEBdteEwX^_gH=LoEK&ek(i4;hs~$C@xlzMIyOTmUtHWhNpV#F8Fh)g@08- zJ^n3KmqLIE(cy@Op|>}s^L z^zn@jET##Ld;hjVbsk2`AWUu>A{n5h0el#bQye|AKcEGx9L<+hYWsdR5dIX_>uhsetCie0PVO+#I4+oKTcbVO1E& zZ)or^a`&UXO2jqq^52bDokvRuIGgDFX$DNSIGN@9@GCl~_MMx1Sk8Ks9Kc-4_co%; zfNnmJ3dRHjWk69PSQ2CMd4fo8>ycwMG{8aJqDr-p`ukpEyGm5iNO1y~32i-m3Ji<~ zlvS8N(orDBjLL@ZxGwt72hO!4=mZ#-={1PVsI@cYuFsg-^b3$lLgY;Vv>oJ$DC0(H z0lk~b2s$}si=^!o|F)`Obg(w(OA8@@I=1=;ctOrp1jPWyH!7JUAEkQ%*#H!Rzi$-=n1c3QqpLBJ&P=lHn8<-)E;sLDxHOv4ZR~t!`go^Z z6YDp#uvD`yws$TVAR)gCoj+D-H!fL;lixJT&t{qa{V`PpsE2c{B)RyZbrU1ouCtsu zeHv7;n}>w;zavs+m2!!j>qbpN_3Gvq4_}f0K*~l)$tXVtN`cTea3>y$lN+?{rd~i5 z-yZ42w`6n(OnT2F{)%tzZ{>8zoxukUp}Djy0;8xDrdo~?)He=z2;6`qqQ>_2S@2$9 z?J#tnJE0kYI+jM_P&e=nWiUAqa{2S2a)p=x`~W~QEk$Q#pLyz-nxZ?m+;r|^``>N) z7>73_B`LDhhnt?}Eab<3JclNqg?RC5{&-kmcKD!9L+s&0w`KGj$3eiGK-&Cny}X
      nI4t5DdE^hf6NB!|>oHT;T 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 U+eYm>YKY%eSJ5VCDw$pSfAUjWod5s; literal 0 HcmV?d00001 -- GitLab From fce94b64fb82c80418e08e7bebe00e9091409ca1 Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 17:07:03 +0100 Subject: [PATCH 13/61] More edits 4 --- vignettes/NAO_BoxWhisker_Original.png | Bin 48792 -> 0 bytes vignettes/RMSSSforNAOpredictions.png | Bin 85982 -> 0 bytes vignettes/RMSSSplot.png | Bin 82409 -> 0 bytes vignettes/ScoringForecast.md | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 vignettes/NAO_BoxWhisker_Original.png delete mode 100644 vignettes/RMSSSforNAOpredictions.png delete mode 100644 vignettes/RMSSSplot.png diff --git a/vignettes/NAO_BoxWhisker_Original.png b/vignettes/NAO_BoxWhisker_Original.png deleted file mode 100644 index 4006f603576f80664a8f3a14c3b9aab48d048096..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 48792 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

      VhBY531lDmZb#u!>ZDTUY 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 diff --git a/vignettes/RMSSSforNAOpredictions.png b/vignettes/RMSSSforNAOpredictions.png deleted file mode 100644 index 6e394b353f118262080045fb28c7423945405514..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85982 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

        nI4t5DdE^hf6NB!|>oHT;T zjfERE>vqg|(TASe{#)7Er|a+am2iIO!Ub~zNkL?>bf$89X{=w!E4+&s{!sM&1zm!} zI*omApM2FR{%Uvoh?D54U&I*e6>U1)Y& z8Aao}eQyiZgni03(RUIm&lXf|&E>hXzb;HzRPoJ}tIXt=Ij>>SJ2Ca<9LZJ=a_nih zvrMkHU7H!wa~Im$`zU(=L+>Ga?bOe?`i#U%O~>xln`ZRe9fg z&Dmnh*c+KMm=nN3R#iC4qL%LTRCL=ukHy(?EB}aNjVrSbUP_jJT)lp8pF6IIHFND! za~SXyUXl|oAn=CC^S3>Ga^*X(S>U(&05j&w^1hLMcJo`QPwBT9l#V^gD^BrZQ6_Qx zj*8bGSzB)_Q-VBa?b^T(Lj&d;FBcZd$#k$aIx4y`>!m((D!~M&E3+Q)(DaQeFXrPH zrZ_Ae&M&W#bfb;gK2Us{S4!1%3gX)V814Or&@;AHM?il$g_rXCk^4E0J#VjXt?PT_ z)lW75qd!bId5tgU&@ta~R=?u@D!NlR&JsmkAv~TZtCD@KG;fFmI?gNT^7pCoY!_ww zFE0I85WGJUp({z4aq-<8n%nq#a)nP#Y@3nG3~tp%)d2DNMZqVD_xdVG$7@hb$(uds z++mKK&Bt3yWSIpY!+)%ULDauznebw!A?~yM_4M(2VczQ_bq6lm7|Z|5R^Tf>R1}~| z@H(4*=C@A!$WOa{JLzf&#@1e3-`Gt|JThKMld)Zr8z4*eVcVsc9z!0q;9VcNAuS+w z-phAYT~w_81aAmk&r|9`p|76lSKnPf`>NqA z=iI=r6ld@FT0Dm#{JMg+dD56dy=~z1Cd&fKErCQ+fk5ThP8xeLo`xB_UM}g}{(-Rh zrOkKl6fD+Sa_kDsnHuDY<4tcnok!z5zJBSZkkJ!~L*1{$_BX7~=1UO*7Xz=o8Zd7A zB~A_}NLzOU^_cv$?cMqCo%3B^`e8AkcI2pj#`$0FFrajD0kV>)JzbNazlBvQ* z@hc5BMTJQgIk>>$QWK|;kPI}2^$iURi;Lfs<4AHZ=dv|tWdKY^rHAj>!oRIYWwKR- zGtlGRq~eM?#RS1i`1Q48Cn*FfMk=1#)3kaqQ!fQ-Y-77HH*@0M4D$)KFs`0yq3g42 zU(D7H2)FUqdPT2r2_9eHW_bL@=x$*THQzPMiHA=MT#g8R+bX1W@c!nb{w}Be;#r=) zW<~OY)-32;lp__yF0{0?rE_P8HvTI0ex2M+DQXc>JY;LvQ3@?5Jlx4!B)AEc4aITq zqiy~Q8-f@+)4z*z_~U6&_cWQ6m@;orFPuNMR3WtIY4hc`ywQuY-ov$Dwy9MJ@4jYT zGe)%8B(}Kqj*)_|8-&2|4>{I&z=w8KkF{belS)D^Pa6`Gl!A*EfG{iMqV7)_w8<+ied!x^MKG z*4d-Kq(Zx;%O3h?}!SoH@mF8tde;Hs>p8bbOxW zU@Q?eShO~EC#@$5a0?A>j=kX~ercx%WeQ4dQe_pNonu}!fL0SGp!-_s;1v1=#(D*@ayVY8bavN<~pSgzU#-srgvdrl-US~zJsr;>CUJxFpbA=f@Mb!_zB8fBW zMWJ5$J4yTby(haER52YBLuJ5!p^)6MIxq-7TSCGH6jH~tT^<-s6_qbbQ5;tpFq@Oz z;K?CjT)?Dw(3+g}{1^VVH*OM`|LA-7ZGKH)Ij@0-fc^Gkl}y?Mp+{~0=FTH@v4UsE z#63@vin#yOr8@M)+e5$Pe81<=qN5a?RD^5W!d5Yo@e(W(3HqA@DTz;RT)y=q=P4SeUy@@|9S+qc=0r%NQCJG<>-F&QtAL~($3F#= z?j{Crb&ozjQH(DCMe!d6ZTyRm!!{%|%v(^0EGINdb<)&NfaU^4ftlRuE{NgUS5fI? z7$i#VzNQc_NO^M7nDe3dT5_$mul%*M8;i_5B(JQAnLU#Lkuz8I-#rQz(44Amc49Q5+3YG`z9dMq)9SRZ9@%Dx1C#Hdik(+!d0y7z&d8n z1_uH?W7@#6PM73W+`|sV`N7_uiP(x>+ zKktp1Jvce>;(FMzweCFSpqljkS`TwRydxZ2|BhvoIkwYAJ`hmn+~M>y39!4!DeZvq%xF=|hh^_9KX1m?Wz%9r>|+NFzk>v%Kd}nZ%ze z=G{Sia`wii82{=yGETjxoS7<%;mwwP0((F+(5>vVZypfhjUeJDhQER)>i=2n5bA+By&Q*lz;e#b>g zTP;iA_a_`qls@G%H9f66%wGA9=~+9=h_#m0#^<3W-KKnKl`;zVr)d2U^V_PT8MA55 z_X=}#9q$?WcAM`?F)H^4X}{Bn_h=m?;Am=YlpLrK&_xR;)e=Sdf&1s0-dRfmZE$&Q zS=stZW&kX&Z*bg6`28uf#oO_p{<=dt24%cP;VO^%;-KnGo!)2%zvlb?OuvhOKNlAl zCpwGupIyJhk@GEwu9oHMuC}VJiodPV%4kqxjX6Vb?aLZ$97=gyht|(qjjFEFxP6(7 z$=NV3#6YLCI?P>&)JVRgJ7We`0VJt1+{A!+fUhuc-S8ij?spiY-728}F%^N9xnVHw z*&eY79#{0S+orM>`q?Yz1rFHWh;ERF;J|0U<(P)ZOEwvm5m4QGc{ga=t>d$9$lOLoF=HrfnJj^z{ zDyqt`Y-BGJ+}ubw&ey}T{j*XuSs_!NiuKpiUW&Z8?`4)*ib`q3Y|5ULBUssP(wo~e zuje7D++Z{2eV=C1>N~XtmBII*G~6Sp<3DR((zRvFmZ0wp7ii9GkQ<@gm54VprZmb8Y;Gj>)&`?j;4s*hsP=DTwV zovCbX*=aQ=@{@trv^s67<*AMl&d_(6ncPx7<3<3DIUB^HVg59SWOI*{8&Yt_0oCJc zvT1{`RrBcmabY$N$1Pk2L>)G@Z+54^vMB|-N;@e8V`P^!PBu5zdFkraPTau)QS&Ds z*~EIAepZ8j=*Qf4rzt@Y4(D z>Gc^PPF75iYi-{?_iaSo|EM+l0DC z{Y{epvCV@76UWjee8#JMhTRxgkMAnC`xn?q^YBl69TH#gz9R$&b=Od zCEwZo>51>rz|qy1x62)qZrzSb^+;7@XR#HfVQCe0^9RfdV=$!azRQZ)Jlxp`fP}}N z=)J%H=+6FkH<$7C`!-(u3#fENl$=RXYnz8IJx*!Ku5-FDJeIX3gs ztD12$!S)7U;oxH`lNxhaIOSkw0rQ#`{>O8<+S=rqUtF5gGx|!nsibRv81AFBm-U$!6(-92(62VT+SH4?kZM!{I=h`q_4gBojj|Nt)F9wTUEU^-N&YeLP!| z8Zpz!G{=~XP;#X_qT9l;$M;K;ZjO&b$f@7j9`WBMICW3jzh(BBefq*w;WOpumzrd? zcBX-5p9g3<(}^ZEvNAgvVluy;Sn++*P%e6j(!{5Yj8x(tE8Uf!9kN|1!@S=|3hS34MLq>(-NL)kk^_v31(3X}gU%24|nM zCA=-jJayQyQ&jbJ)yJ^4N#!+mVjm?{a(e){@n34Hne*yJB(4V9ytkgoSG0sMc+zCQD{Az{#Z=7nU%gz!qNHB0SS}6dt37bXTMSqg2=1_Vj5zMo-(gL zfYtW@@$pKdkk8$9JZsb!-aP6q3y*TszEcU$i8X?PM~ZCpc&z3gK6zr-XF|{}jAOau<{Q$9S@}4O>_LGoT9~psXn)4P^H%80eDpH?M*KEQrCm{On?+SeXH^pY8 zDJr_N+XgV(uWOT(fv>?9(U+9!ENdyBlB6|Rrv1zfeJhxIGg$>c*eGI?Dnuem)C57^Dgx$@(?b%vqF?7Wi{|p~4_tjHtt*(dn zUVB}0=x`eEj<~j!Y^^kdY<0MB_g&kaN3tGx$`W`P=RZqVPKAyc3LS6HIZWd=GBADo zwn^l%&!)B~LMbHUg40X3eJnFTw?R{rN%dQLcW_C=oX=p)HaG;?6nAE1Wb{CJ2#y+7 zIXqf05)ks8)Fwn`V6CU&6IugwDG*aehX#YM(G74Mr}|yItfa>U;_O$gFH>@yVa$VI z*G>zAi`QN^__h|Fkw##?y5;GM?W-$=T~p1{Nf^|#JTp6(0Fl90Xn!#EvFG&LX}A=} z`XBw=p3@sZL)sVq5!yk?drS=;oQfK5DRPt8yaoKn$~WQ8bCGK|(Cs_@GR3lfRI9YK z;FjV_q?Qi3Xuimpq)^0@qi-$Kl5fng;>!3taBhXNNzG#{Y4D&I0plz;gr37sPIE6uT-^ubbbXT5!U5pfSi{z-C)ArG~e^1b_56|eCI{lnUcmG+a)<0YgzCwU-m^r=s+#B=}(g*I6d^*4Y2o_W>&vv25-ybLVfCuBUAgvkc z=-M>W6=5q9W~>7^Cdu%Y^GcFo(qD%qp?_ZYG7GLEw0bJ6JUnnW%|YzZcpO&L)Sx4I zCC8kttEAU^DLJEWc`hb$I(1w1d~+wmEwaXQjf9bE+X&s-lk*)Xd>8{C1+Lj5XB%E@ zqIRi#%_ukzMZR6-R(Jh;6n+amQh}MZrb|$@?;?+M{mePs;^wRHoL1yWPF`V)e6Tmq zD!U7V6gQo24%9#EcU{JQazzn@dJcF4#1avM#gOiqn3zCuI^J6ofSq?gE_=05+-4&V>y5iH)u4##e3xhkV7X*mBh#&x@JYeN_()*FM|zJSQr0 z&tq14%<$ZWp$Qx=CYDS|bJO2HW%{lA>hf0&jnGfr(J6;TYSWJs>!m~*VTLU^zhDrP z!5|{?u9WRax%Iabgr|?f+2jl#({9>wv#y52zccFaCSWG9{dEs2YbuPpE%KA%U|=5?n&|Rn1$j6dg>vyfcxR8iZjne5*Vl` zt$(=sI8UCg{YE%pW2{(tvY)BVEyr;FOyjHFc5aIyal3DIXdTtfnK-veXA9THJ+J&y zX2*){UQt5PCPrc9dv3U8PFM}YOwS;j+BH23nH>Za4BT3~hbH3WkF}PZj;Q03nqd9x zXUO5RrJP4uHwP0`Bu6_qa+sP4kw5+EA@rK>jJA**RFfDPaY7@5F~Gg-4*#Su;dx($ z$VI4Ko*O(zW1HQ^V`W8<^*-v)yg)ury;^$i9z)w({?7B`NmRW~=Ck~%`!$yWX2;d4 zBUF|t<|TH%RM_2h|I==UEKYjbk9OLuJIXkzv@JNfxMYnz-|p8MGG-;RX-}DJTaa;m z=p~QLiAvUCaMeAW|M0%RM?3rLJ-fXnzAYXzcz)}Yo!fKUizCa^AAfu0yX9N!&aR=R zxy7qBgDo#7g<1_vql!dtJl#X3oLSQIIEaP3_S)9b&et5ZRkeJ(=H3t#2;2eFmCWEkH0)#@`16)m_|O?Cf%!1m%{-gI8jVS5=4U{`q6KNr+9MIaoCK-G!r@dP-d?-}K*ick&vxS8%E=CaeVAJ~Z!G z&uP@&wY0;L=5r12%N}2v)4Ly6q;)RI$((*1tSO1A zlt#%)E-)@3Q^J%J!m3jKg)MwB+jBdnkA!T2iEKeZ$+GYsn;QpmJMSK_k$Bjgy)KxC zWK)-w%z`Sdpw}LU~)-%KA~z#T3jtS&Ee>v@&wal()qj^8*(2vI_{c?;}6v- z<;_bA&mMc5FB6zaOyJ}>)^TU}t7mUWfvkR`U~JG>!?~_2HtT%*y~W$1nC<*63Tns` zFtZxtLDN_ahb}dk%|NkFNxJ8IJCSH=YU+zh3zP9BE2WHexVZO#si~d9wOhBuG51hr zAp|wXpn`OB@V#w+{)nF6e$_ab^{`2<%P=FMv|`ZXCS#F0TT=;$#_ zf`u_J^ab%Mv1ac{ukK+=Vseu8dw02{M`u45;rm!bcG~cGsnkv1Fnhw@8`pyNdkPqh zg?$lkCy5GSR6T~N#m&AhB!}vTEicvToOWcrqT>+9m_)?#x%+L?xu0}7z93C8+~`W2qK1vHqdSbOE$k(hlP z=MIJ_8{~}i`w?#Q$}_8a_K|6t9x5BzUaA?{qIpcz$4y4VJbL|`%hIfHhJ=|OmV7wu z6zTqy;g(Y$q`9L25s?~!mBC0N+B@96RFdnhrqF0uLG8~*VlYL`H#m)roD1aoVc`Iwh^;*yw< zU{P^moZJRBr|>U2Au~QcIC$*DWtzPD!FT-TBIMtw4-k~1)5VGcwv99CMAWOcYfp1l ze~8^V)}n0wAY-uDHI>}5sFeImC5>b8KtFwm4Q`VR-R1h=W`_ed0EXm-PHj8LMXv{G zq&|zfJ^RA!aS8SXi^sp!F2#;NdN}-CdmjfOTA*nr&W$mjIQV`m(M&rvbR|Nm=~I6M zTmE(9-Me=~%vs53b(D7)Hw6$vnFSrxwuCQB@2`K+@#O}#w^5Q@dSzwzBp3EH`ZD|? zxm+5;uGQXtLxonH;3VR+u(GQyyz?+mQ#fk%<|toG=;guA{b$dXnM%!k|2|Z~nw@nZ zmy4cicSlhgZdv)P%hvAzkl|)s@RuCwZ4ve7-4eO;_5&BmC54#>_WAOo?e(f9)CBhTzQF^G80dJ2tj}1^O))vlhfPdeaK{Zy zSb+pR+}hCCn4NcK`?JHW6;;q}x5=8J~k1tOLgC<^g%%KYDC7oJ8c*seZa)A>nE=T)f8Svp^kFUOoctRC^ma(s3L%~)H zW%~U?n@)bCIl^>Y=T{6-dY3!kNbYsj;ts_)_`+hKdNEghNG|)Z1Bv04x50!u_gJ^r zrqrY_(moaC_VX{8b{q9~Z7;PV&iPC>PVjbceLeN*^V+j~y-WOY#oMgv8y$y~`!DVY zu31{YSjR#`_Wvk*?|7`+|9|+D%xn@eA}f__vO8%BiHwA@N=C?DQOU?k%9c?QvMM7h zWhIKJh-4*^Ei>hQo?X}H^ZR}8`}epX_wBFiaaGRudAyI~c&+DHVJoT*`S9`4qo*$o zu3u*+RM*Tc_4#x2>G5ChR|vL@a`9^B(XR|kbLkKEoon0%-VqB5<|BZ6D4n=c+dZz(&GQBzowLo6?J!3nzhaD=oKf$hrq>I}6EV;an z=)VDibTaBa4Gj&Qoc0Rc?jtW~+)0WT4e#hEDq8=@bT%{}NTZ=3&N+zv86ltA*`rTY z?+^+WKAv_i z*>xghwFPf<23&oF0m7@%`RBiSABFwuFOMA&JwN(?K{f4PmWFiaelCWwm;qh z_6q1`j8)N&-R~N2`z%;y^?7oqrVGqiv4>U*uQCZZn(mF}r69yo-#d)Rke?iMrrh$e zygk`xV$YFDwFo6M6Emt7>7Esy2PN|72U}w#TBonyk_*!$e6cN8Yus(C=VDfOpp7hx z5FC6~t|)GZE-q6)WB3U}caz4gR?_`n~UKP8(Z_A9waUS<5kunFcWJb@_}k0CZkjUzT&6>S`;Ku-4>Sv}4RG?{^d zzhG~#1p{AgZJE!z<65xwsGtOm(g;oYQ^gy_#UvwjIG04L-V6w%Fs^+{_fI5d&P0s* z8=I(0?n)OlDsAQ-uA+3HYkn~xIiWf!b}fsW%(`Su{mChzcS_7jc)z<0B8D^(L!!)%A9Pqh;i!4AP%c+AUQ)GPn;5$}Knf5bn(WVk>fS>u~&O5;N8_ zb>iM1hd;M^TY_G_-8eWz>9RG5Qi_pI!e1r*+6=|BH#9{Ol28fu40(qu7unWZ%G8t- z78ZY?X#WM$vL8Nt5Qw#FisVeaeKbkW^Dr*$@2R_3wQ{=BRQ#ZP|G2Pl8VzHpOb=EG zSa~5SptcNev?8!SB2@TpO%NvwieU_4DD^RKVEG;E$y8r|f}p-7eQsrDpZCq0h%4WV zR@S#vzxv|OzP+}APBL}1^5#o{tCv;dpY-L=nNldG`dMGuZ}Q=N^_qQPg7|(XdV}1P z+`1dbpVh=Vu73bXE?d9FkY4=Fm1I5N8j{v4uH|_=_AnA*bAofV&{BGdfY};!p0}=`NX<+%q-?>9Z>N}y$?6_KF zpJED5>4(qUt+HEz_%|||H>co_htZ&Ga)(#cp{|~lvEZ@!OVQ_oSb0m5^hnA2&;SMv z&5@i74XnrAe_pBbly!c1GUL-!^iJMWza*tt` zn?(l0?R!3KDSkV)s|&5G)(=btRFEI}a)pWzmeD+A^3Z6nMRi4PZg|Oih+q;1(O9|I zKImNQ6GCbb&Tt08skk40eP0GxH(5w!64oIDileXMF>%{6`Ibddx`gFR3~QRcd@i=E z2MP$I3f8S#ZD0Js%ZCjLJTe93zO6&v_HcBfxUt;Ow{K-OEw?~BI_;v+s`od1;ifqM zI#}vdU`}^ezWx|CMKDvmey&ZCfB%UPs{IFc+>RTMjzFf%^{X)J7`ZZUyDGeNC-Jdt#3dX^-W=6B?$G=$?$JqxX@tVE3l>x?Ark7x~OB}y?vwZMxe*rc&VDl;rU zQ(IJ;BV^a!y#)^+cG$@vaRiI+(lce?c~sK`8Zt_lf2FVnrwKAm(418`9%|tfvE^%0 z*o!;YI8qze%-mx3g7J8pBVX2if=d z2z++U!vzMOirUQ{6TyY%uB%c{O;eS_`88I=Uo9g3f_iTH*oLO6Ku?tJ4C!Jg!_|GU z_vtR|<#$;JkzFYMQ%Z&~md|#3Xlu7^JL69xcBW&72+anh_h8bQ7Q|a}Bx!$x&CT}h zeaQE5C(TQBtKWMUrYYc{co?Aety{NF7LpVwZr`@4nn*qHH=E6Nyd+?TlH`4;z{?Nl z5*ivF3=p-3bnb5~FLn+_r7eFb$X>x6tAct?R7`WP^2NNK=DQ#*wO4Lk@`XB<+8)T1kVii4>i17d%+7 zW;c{XZ z$JNS~Qb-*85yWCulA6k$t$$RlTQj3aThyLd0^b$V*9QAOne*N|yML;ra47KVpk4wm z3%#nLM?@lb)KI1OQ}*`Q>sb;Mc~r$C3Y03>o#h8l(WDB#?F?6m4t##CT%5m*?ndCS z^Oo7WZy4v8&-H5x21$JO<=L%PzDoA!p1$R8U&4{2aPagu9`UWXNW@jkUWe0a;X5u= zzYTrR){Dvu+HOY@Pl~1CG((XGPq!bfgpcQmNj8r}ysNVl?@}Ctv-K6% zrK}pDSD(9&>*IGIrlNNEG~Q=lx<=|T-(A!Wa{(E(afK__>!kkGr!oW=xB6GHOL;eX zZgBWcsMEB@^}MHlM$lrepxoEzITlfJpR1NI9NSn{$*rTg*~*$M;{m0J?yPy#4|GS^ z{GKVoPN3eHBV@n-ibN24HeBs=Snm3bLWL*!y}iBgoAgwYlDc(m=NC!VyvL9A3yl1{ zy&=10qP(40)ICt?k&h;cghYozaI1;6we{u8wYoW&gE-|w6gC;eRJfl(&9F?|{1lq> z`uf9DQ#` z1mTA%eR+Pn_3?7JR^wlv&Vh4H#pB1F-QDug*7)KbB1Rxngq8K z5`L|$Kq~i?Tjj#S0vwzA+$s^V`s}ZvbI!hPo1c$Ql3G8W6bc+(%KfCzZJh0!a37e< zNwG}K$`T-bWbZTc`-(dCg|y9;KHeMqA5j&v6g`iWElZ}m6UF;uj=SnN^SNi4Ey7i$&%WB2 zRceTbu7HX(peE$de4z)Z&C;y)kZ%7rHT8a&0%r38(^t@-H(5fs>~8vqNK2 zPX0%4+j-)hgoO0{ZXpGl1xE1f8hBhT1Ql#pdy=`J_=2WKJnL?E#eVdm92^`zNump3 z=kuu+n+c(C++C4?Z-d;~akZ(aqGAOhVA2yZCTN_UW_JVO3`NcMr334HmD`54+ETyVFQUO4N1{ zurWx~^T%gLy8022;?q>qbQ9v^&nfi({bagFxw-oT)}9WziwFsw`bb^_3=)PtJ>(zW zzb|&%t^-WMgU63q)GuHDWA4>&`{{l-5@-lgEmaxAD0X7}ZF_rrON(XsZZR=a71H1c zQB1T?OxS>4-b!~93^l^Z5iLMxIaZ&sFrjX30Uf;B@ zHu{d-rz!47_E)zD#r6d9d494<_qu)aW(RgVgrrJ0_{FyVS=>j8Eh)~u`4XLCXo&$B zh>13I(%sPD`W50f()5j!0I30wlFZ9dw!9_0OPzfXPh};N5#p(VJGzfcAwsqr7FMb$a8O_= zb9!;BbyO;;%|`pgiCD{^BZBkG%kuAAqI2`};pieA$sEy$l2+JShAV1rUBS!CD@psD z)Pw5k)Tt+=g0Z@$MyH8w+qNgpJf|i-envLKv!#SbG+t9+?&nV#&YiJGdLG0Ksauuw z*hK2)NQ?JCB{ZiiDH6A&?SSHAHrj*c=4ma7d3j>>UM7MpyY6U#Vy)Z+tEqt2=K0xK zT(c5Bs>rC8bYvsUS?#3`6?Jdl#>&JrI5cD_^`N%)%ZmH%J6a_sj^9>yu}5fVXz1K! z#2#s)y5!|$EOtlO8r~eAmLG=96caNgI1Nlq?fu1UrIO6VQFH{IRcHrj@UTl;Ryq*B1=GENeEt4YnhKvfOQ)2J;MSJ!{e z&Px2bf(ON-OLOjI36BiS=n0dFlSI3@iQ?Dls;rz`a^ySv(x&tLqM{GsSLhuX8hY5) zHhXRyX|!-V)slST>X-;&~HDmP}=mZ`QnY|xHDH2 zwxq14qO6RTc$=D9wtnvO=g%pgZ->`vRA5rM|K+kVFMKK4KlB|FGfhauM`ns)({NHu zmeW9A-)cQ(erf4kdRCKl&+%}&M!cyc<@50MdT(Dkccte{W|Q?#UzO9ds8e8NFu$;n zlALV%r@(P+$>6xkXz`0M$52;No5qx1oF!cN_}$dxWZ$Hk%Q0?}8?*@0oi0;cr!6;3 z_H8yz@3K2T>Ficx;k*!-pjVtja>be2U~ug3t&WYS6j>>Q5*>BjvO3psisFQ()0i}) z$9eio>z_3HO)G1vIMUr&CW~Ae^q{4U zTawi~v~(I5+Uso%Ot8b1o*MNEBO$DT;3gF6(5?qS2%tZhfPO=GBl|h=A>#LBf@LDa z1TfDjnb|n3I4kBN%_@%-!q2B&%OPHQ!hJX-xTc+=EC<*zsD3m<#Oa7`0=f& z&C7dTAuq@tfpmp4M3T2&JXhl6==3x%6#Z2{N`#n`TX8@MiItP{f|RhD+Q3Rc1Tj;O zw14O4=Ofc=u?w(0ym5xA8gzZC_bMv(&N^E*BYoNaTx@ZE9(IM2e|PtK%q^{Kt?W)4 z?E?p{%=MXLcSA})PEz>OW(0j`7vb%*T5=42`^JtNVI7V`^H#<`I0Bb#q>@^Y{aBlf zhxg4S=`=n3U_UbBf}{)Eu_Y0mS`IHE1l_!Mc9G3tjaDOtNl0r>p1j@ShLh7$!Qr_p zswFWwnQLT*w@*Tr(|VoPLXZVI$oRYXbd_d|!sEv1s?NS%afjPsO5kP4ly9b@N{J-R zqg{_5&OIr{MjI!Il3DK0^ua@i)>c*$eWt@3hv9RDeTq<|U0aXrMc5iOXw=3Dsieq& zUXB=C>>+dG4Aj)H|548KTE9=S_YRAPFf zY;9d;wVwlA{+StPsc)cUG|}J2pC8TEA0gcpA>lWxTxt9Ng9UI>S;oB;wLKR)5RkJJ zwuTUb?Pu16*3rqXChs;higkMZCyQk3IT#rkM`)fnw!izj|6ccxsB{+nTx^PNn@FR4 z+rXqJfk!z*E-X6RDwRh)SBnk_Xeuks>Z0?UPn&aVyO0=2aVIX$dO=|c5FJBf<7Gv8o?A5~dMAzC3;K1aopSgoi#F@l*uE zJIf`IN050rog2fTk1qR_ui*=qxBOr+oK?kuf9EC%DUgb}f>cMjy!a_ogE(U@u*!xdiAjrCu zmY0%p8o(9PLi%cKY**=gB%pf}NI>})D{o97&1Cu@9{Nk~y_4(vy#}ThpYJ|^bhGEF zRD5VCa4{M>o}jf~g2P(K)SFzh*3!3hBq9v&wt;hj6{S8BW5=WE;$f^V7Gf;#J^s7ZTsv&gPpEjA)}Rj=Q^mHSM$WsAeAX@d)`39@QzIC)Nk zQ>T0Y2`#&8bo`1%5y0oNpV=ZBVeg0#i#+1)-HR3D*y#QjHq~E-bm6D+H~P8mkc`=z zaP_WQ;1}<=2Qei+T}!KW>1&wlcH37s`GpNwCVu>g;ofgm0Wr$`Hm{iC(jI=80M2v! zMX@`tu?12hU0-(vz(slFlRmOwVYS4m{rv>sPCtoToL1{csw{u^C-c^=AKkT zU&3@i>~Al*e?CgbPq%!I#hQTh3TBH^oN;)>&ut`atX4I9ME)j~X2|?LHPg3OK<+XQ z_)cr-m8N5nWWk}K7!vo}L=LePW8X4Eicsns`npZ#F(6aLJvUHHn?_SIB!wm123n@V zO1t*$Yk&1h;xn9H&&HKSaqg3(Wa8oBVPz#h2K|1Zt{#s*>1IaiEd-}n9E81R))SYZ zgK`-nH2}Zs?&r+gJLN-Rdj;b_NX}Z2?V;IJY|1*w0Bh(|>lYSKeGK@u_c}ZrKvQgTirf^st>uq{qP=-m2!vU_LCK|Kjv{F(%M^0UumvfE;{TRE54fT>EsX*+q z`y_p@&nAz(Gb0T?gW?(Zf=xyFQ3U{710x@jL$Q2r)0s`EMN%ZKDG_dMkwha|p0ycl zX7>sR=aepCP-oIA%!-gTe*B9PZtvZM>Jxs<{YpdaG53rJ3qi2T7y(wX+YAzOa){*h7F&}4a#3PGyx9tq2vj6Z{r0RI%Yhrl=H|a4^O}_8cAne+-HFM` zZ-3N(Y*Tp_cWB2JYUgF`r!t>gFSGQqR(+B`6i7gMgv4}{6Onni`0k6Q(Zux7w?fow zxPR#L_x2q}bIx*CmC80g4zCREc&!hggSC#j_6xJ^^R^?duB<@5NJv_G0m&IU4%q(q z3GuU)I(6yNd=MG=gX8I6@{RXRw~j>W=RRFwIYQ}pJ5p!DmHX#Bkx5xag;W-PlwEN= zvWNY2wSSNTSLoWfktiDqm8;*?OCZAk=vkQHP%HAZ=TPnnu_OT%z(BxqmZt`tdsJQR zkKKT?c>db@=Cxd>7}F+m7NdiQ=m4*<_QyYnPrGQ(KK;FP`854~TA4F>_VP<5 z3+qbc-MyEo`5UaJ?fl7iTf8(S@SUC3eiWDWEjq@2T%)ZvT9oiY^llWRlUa7a!;?(m zbrK4`Y#ts=Z;ugQjAYVW?`!2V6?Y;?IAQg>9=M)iSx!AS&Ek6M++z`HSAT)nhoeFi zG$qe)X_MR~K>@+Gz(B&J`0NY#4MCKT87NZ@($6akjUXLmxCh(8u))%31z-@_UfWka%jnFYH>X z9@xG#IsO&%kQK*+ii*TFyaO$*N;~q-V3`?Ppd*tMT&&Q^VMe1Yp_PiB z>nCQmq#nbsUepJ!)rCQ`JVeQCtqDK8BR&*r*CCZ@6X_CK+d{y zsJZ8(PKH}?8AmC4 z)4UGv(wnLyCp2_yx60fssKBA(3o!fQqJk$~ON;-uuUsgKY|ovG-Y)<4X2mC7o*IJx zsZ*aoV(Vczi4_Ef4T6|o@li%OJdn4Cwq^iYY3O_W(=}H0TY6+BKGVUxcV~vSXzY>q zBy+g_N(?gNmL(eQoIo>OW?Ne@tbE_Jx1TSXpB^7?dGTQ{4gcq}XYTHQ5g}t5ahUpy z@(HzVe8st6XRLm|+RqoWSchS%OWKaz>maclLiqm83-o7n&BZYq8!K zg*C1hO+(4o(NXB4Zn4wl<8Q+3BEg>6V)Gbk1?WV>P+9ZPA;lNJ42jeZxO*`6A*m>D zv)aldNY$~U!w@4Y@2l}$jL>{G(WUeFG*c6*8 zY8Ag={Ti)+#EF>d4t(YdkwZvkmOmkH1bSm~!1=9sykK0*W*Pb$H{)+>2?2uga`Y-` zoH_i8&S9>}Qsns^rs2mH4cmr92`=Pma>Ja`JJnu3`VqE?DblJwOPOC^?A;R)f{e^y zk0g4%^yu{>KEc2?d&yDa)A9`yaz(R}bZS=t~6;!Kfy3Jl&gH6Kz zwzF&VcLXzawsiz^MX0PB5yM*NiT#fLuP#0hrJ%P{iOJ@8!FN`?s)lrzC*NC})X28~ za^&bx3GKF*i|`>`o@`1dt)kstdu8U$1kQ|Th9?)@O=`o+yZvui5SoG zGvsrVIaWk&u8i$z_u3zJ zI+M0^VP>=xNG}|6URnFwwv5KPv#VnSm%*Ux6f&~17@|KZEPNxnjLH`au(IMUtwhR8 z&CF7-Z>6T~)_F(*%!9E6Z&Z?w-lRMA9j!%R4q+GVjDZ$Hva=E&G7iWCQZ5a7inVRV zZSfD7qcDl|)X^6hny*+2nz^^OH*V9{g#iQ^ zXFlzdKy@l{e`gUS(6-V(d*V{*N;rH~bW?+jwrn{U?vH^I?yTxYiegB@FU-$B`W(Ik zqt?oeKflhP?++NZx34b@0IOhVET`7+e@HY!uU}8%JY!)|i&O;x#n{+5LNg2Utv%KE zjoz&@3%F}#-iTM7EAH&SUgpZqw$X}?l&9a@9 z3a}ZSl6y&}aPaEsvpakjUp{lQv#Wb|k3*%h-Vc}EPb3o)Kl<8Sj~_jHBL4$wjJE9$ zNmd^#buSz0N0ZckO+JCG0G=EG)?Ba&keq*e5~ZYg-X2mjB&`Q9p#lPa!?F~)h6Ge? z@sH8aprR!G+|bMdk^`QA7<}NOd2s(eUTL}W81y{tI(D>fIPqk@v$NX|Aa$uJ=Fp-k zsnl%s66oe*EF7$Gg`{VSz>V(2%isQX`VrF zA`zM}Jb54+-;Qwemeo;KF-1jRfHux87isC}1c3Z$p3`MR*{vfQVhPQ~(!h<&1ays| zzz!Hk#%icZv5Pa>?dV=%8(CEyBdKK~1z8P6wL!8S{jY^($wKtyZzeAfIK&dCUUj#uX0Ok!afex>U5nu`b z)}For5zNbwj|ULTz}2-R>4jGIrOx|DovY_4n}>D)9upi5bU_9p3V*Nyb-l;jA?x(b z?nCBQVxpqdbq5EtJbvwx^>e=X>$MA~=~>xgZbC8B3cKB=2V~>~LTO!}GW&Tqu{)(D zdiQ_h(+kY2*n`Z(1F>>5XgETZ3BBbUYc#U_0ozLlW{@=J!b~59`l(a7AM80pVq0vm zevp)fkmzJz`M!NW!tMT0Gb>)X{8@`SLMjuv?*Wcvy{GIkPhsbC7fMgSvO7AcLzEXJ z`6Lze{t*_Xi_8(%A*c)0nO?38Jy8<&@9kBdt{rDR4>xs>Jb7+qwDq=nTWg}+=9Dvy zNp%IyMTYLn|F^Zfs_4!0Qo_@ZZrVH7YxssBON+?_t;ya^iJc{f?TSW5u6u8* zyI9Q``JF|RjQY@=ufOQbtLQ@a$qF8lS~4z8(n&C@=on5D6d9R3ML439EqpuRlLNc{ zX_WRgH8mpIiFI?XJU9R1et_o*8%1-|-ob%{;@k2s#D~97eCtm8A^Hpvse3MIGnc6O z1J{&P4KnEJY~9Uo9Gu)X@Z$8PlXIpCxj38{&|y;M;F+Z_>&&fiHsD|bH^wiZFrxXN zvqzACE5k_oF9fvvtIYGdUC2X;+++wz4VJ4}YqF2dl`k?uQ}E-HH~gb-&#kx=A2=X# zJgc&|N$GrdbO$X9dw1(!R~%qpcI@1FFL2`zH(&3&zd(SAtV(KUXJ<_5pvYr&{P^+9 zKT5VXw*+5GuI1%#kUDtqAUZb%Wy3nh4;&y1f|h9q#<7o85Vs-9O3$bId6;WY8P%H~ z7EM-+%ZEjR6PIaKe^Wns{Vp}Wl-BKYM}zZG&n&$R=QHiGLF>#a(uP`K5;{H zGmNo2;+3}U!FPrD^(wraNrK%#T34-b(*of}1bj%GWORkwACqZ;SWy`Ey@~pv#_c(* zkfet(H3^wgrY-zrU{MiqfCLTRRaPOkg020?X9a+-mjSF3!UFp;wh{Kdk5U(F#shwi zWmfyHGztt%)GQd@0YGH8~yw*44ZocS9qXkunq1Mt8dxMNzUy><*C13y4v{4s`Vd4hDalao&k5z8M<(Uo_Q{tCsyNF_L=JxIOyX zmyC>~MDBNc{N2fFw3wbUNUs())}9o5WI<0TTQLiI8V;NbI*ep+P=1h|t%3KRNz^{@lf5N@rn#}QDSf%Rqw`Gu>nID%N3U+f*s>7YchFx zJIX6ckGFwIP-@-G5Ld+UaYqFgRgxMy!+enMH#4JC7rO&~$gDXtGacS$bhy)Ayhvo6 zkg6;T!AG)1C?cOSzIW}bSEN;WE@HW)MoyQZVX4ni)dHg}8R(K@GFKpp7wy${dv^Ko zK<$xZ4$;@M7Tr8wda#0ic!Hbnoh5$LNpuw9y8QnA`>!)I$7ik{`GsrLRhuPTP+WXE zx}IBvbYjf9jta&fAltENRVB6s=?xQAqeL4f#CRy%%RLYl$kP+;t?cgVk`@voiQ#|q z%F^fGOHa_(e@J7y5BVFqDa~`tJn&5+p4-oUF@;vwrRoJ*RO|1Y40<EjM*Yh3* z6-b>p-X9!r&CzpTw zipTs&l;NUJ$v70Ij==H%%vTd+*Or=xa)R{lI`9YI?7J10BCl`YQ&8{Ys>u3!Hpxv_ zmm#6qL!03azAgpnxwuG=MO`#qQ*)rZ(T!TCPWvu{c~h4w&4oK!*A4Rtz;@LhbJb6k z%LH^hM^6;Uw`g9KysmMx^(@o>dHc`WPfpR>6ZdaUE0BIp&HQkve&}1s1L6BQeNyZ< zI9w{Z_wCq0n!qj0&Q?H4O02Bv`%4=sPMvE4S09`dGq1j*y*Y{$>Vnng)Y%9bvCUND`OVJ@%Cr>-WFl&HOx4 z+#F8#%$+KDs2BGvX2`8ABT`>ryhFR&coW+eTR!Y&_$_>%kHFj=KitMImHxeO zH9IgPcsFyNNL>==>&^Q&kS@(*Uk5*xapd^i|E?!2lJ0iG&K-5VJdYg?+fmR&;4VS} zyI(b{{_jphwKO2aWVL@GNe@GuHXR~0Kf6-ckm(BHdvt`k%bl4^N2KKk-SCPDdxpk4 zf}g&|;{F<0as9ri;7-k`YB$9&)|SM|$EW5psDApSh&LYgPljDl-+!|=>2w;QJ6b?7 z!q!eU#PaJUAM_ELN3pe^^t%13^j_}tnBxxLocN+EvmN)e0`DE#<`{BytsC^odXOW> z9iO^rxStAfrvd$luntlc|5WK5(F5IVSd^BO#9ltZN(`f)s^y_Rs3S@YtJlvhwxS^1 zzdvghzK|)*=KQ}uiY>T4Yp+yb<;%)Y!eWZoH;3Jmk4YyRoflfWvW8 za>}$_F^bGylq@)FRy=j2iknC+Id<2t?$EWnDiOC>@;zm7QJ{uMRq^{Me4U0zHq%=p zNpD?>VLN-c=JfQmGW$+FoY{YmnRS!HoaWh;y&+7*wm2k^eP4joK3GO-0u;}n$sxRynenwyZUKJGSkbFOpT%O@HO95wU}Eh zny3i9uteT1vZuWz9;Esld# zm9LM_+?vyl;0o?sw(xL5ox~BHQQT7pq%*w%N!1i!Ud#-0!DW4&cpyMjKo6T{+cpC} z1jR?q652@ePA}Wba1k0C13sl_gq%!BkWY$?)yifg9;S9x2Qp}d98qv~wjNg!+e4bh z?WLwu+B%|f+1ITkbsoE2Mq2^j`sw{xYPJ*_(t)8au|Nd?x>p-Rcz!Mo1>vOHton`) zyGy_jj-lZcO2=uHLra4MQ*3MeUUJct&z_`T3$6n!(Ljc?DzB-ow&Mxi{kJ)RwV>uN z%hD5t{8n$JaZ$IiVSlr**0U-;$Hfs)WA`QFFSx2}gvc}#%`1Yk1WcCZgsMD)jcykI z{jDi#EId2~-9J9qLxsc(Y&+@2?jxuFb4}si0}++1qz&VgUhOl+wPnV~Q z{ouXaZSHldoSZm0I$bq1dc9K7#`YBNmVy#B4ZxGXDeZ^{a*R>YHy^CJqld-g!Z zq`)7*qLEK>h2)l4i6~~gy%7p97G$4ImwJ%J{6Y-?mRw=EgQH^`Zn2mcdFgk%06A9F z^XCMx8pt1P`bIx*s8OK*h6c}$gx0-%*R+LGy0S;?s4e(^XC~krS3x> z3>}-23QAynN_ytE+yk;RiBICwpzlRJ)ef+T=>dOXuwT z{-c1>b_xn=#+jb_|CtA?Qqa$GC-yanfNpF{h4|5E>4exV# z{D3-pHnb6({6DX2YX18gT3WMx&JgwgwX9LJ0TV42I^M`#2D1&U)U?C7s>HDV&#=ew zPpDJ7llP3~&aKWNVKzws>c6-nr(mCEruy%C5_|7GWmEDz`@;x!X%8N3JZtUn^IdnX zn5Cm3h8-&=<+FOMH{>ym)6Vilp)`4hnV-j6m{m)Vh4V~adotZ7;$-mOwoT;H&%3;S zbT3{ge>hCd|CvjfLw}dOy~~`y`~oxc3$FuLac6%?OebBF=0-+M7M{RmB@d^ElS@6> zV(&zaYvV#SXKj>Irs_VGSDdv`3v6$_6k4`50BE&P%4j% zFl(uFnh!O8Uf@ciY*JHu{_vq_w8PG?(O4TM<1R**ukv#NS3K~^8iO30q@<~I6VDbd z|NMTBntn7_vm3_szhVN{N20rPb_VyPXyI#Z&p-|{ok%0Z9`XD8V}XV%N$tV6jtJtG z=1%zfNObF4-oL-vpv8-f;UPEKbE}t>+GI`BpT{lz6Ec^7zS>E>Wh7sH69Ii%zQA?K z0YfGrk>icb%(UmewzRz2?nvBULWgZ;t;%}Cq+XC1!BRTepe@W+a_gj6L1E#!zk!Uh zRt3!#{svpax{Ynh6sDyu7&e|lHb-x6&~_Q~6AaIOOiY028T@MWQtj?by614y-x(er26?}` zqXVe8k66XpR#)A>Z%bD8=5!tTz;JGSjR+i~55gx>%84s`iiM~R(2oRNJtce91Gu7M zf=eD2&Uty-j5=uR?r6sCo;7KVd@^=7tEzrsS^^x6{V6hl%b=orDVlfFf4=rLo%etl zK8T4quBXQ|FsiT@nSTSDZj(jPGF1~n=!oS)hRqS)WEcafM z%ADLQF0LEal@Z)I^8nY4nT{gUn`YOPptB5&=fA7`4i1%(_?;0prJ{0WriwqIJ}ayg zBkk=hEJVIkrkD5Z&Ti=lVnE{gZIY3DM-Ndkbx5FcP++VJh5cDO7k2(%l2@JWu6n;-q zngHhFvq!hNu$Qci%p;4MHRu5#YB!zXlXL7*nyHqyYM`FZ`zppN29gV~# ze&fgT6zJnL-7%Tnu4sgB)$b90PbO%<`g)UYPjDrsKxCjE50bEOXNvOjdVCuJ0nMecD?p^6TfzV0flJ(^6n#Iz;eLB2n$Bw#zf#+FS zn}UF-4)*AN&I~T)^XD4?#+e%$qR>69l8N4@oZJ!$0J?fiH1@xG`rVv^q!=UZhPGf+Ig_c7(ZLDH&(e^q%Bjuy0_mow&*1_|0aDiGeBhr1t3IN6phyN?P!miH4_V0Oei0QJh*GMLHo6ub!X z483X4HqMWPo*3q`RluEY z>F!}?f`CN&@Ex#({kI*YX3m2L-NKX9uyE!hwkdkK90znBMzeHw(l``vnS<2C67*lo z6$jrP=9}uTk|&Xi+zf63=G$^uq|6ZPtW&32ytcmGgYa8c7C$4#9nr#ddUrw&=^}Ag z{2?abWF?)sf++`4agr-5bcm_%3fQ{L?Rr$C0_Aoj`D7Ei3C=>quVT`fq%`p?_KQ=E z2wS)&2E=3S>0suu$P4|ebWuaIoAt(ajGWG0^t?SNl^J{;+gBcRvx3j$Z^8tdE-}e- z{koXJN??@nj}iHEm2XA-hRJRtJ3>=3m+@7 z_X0t;^@JhCs)r^d9nOE9GmpJlp~b2to&ZiKKy%X8Xclh<#nr_C-GIMZJt+&e#8W^< zH#9Y&o5!jS4VS*kpd(7}l#W+n!C%t8nstP5UtN~x%)&p9gY$$w zPQvZmiJbMd&Nin{aO3U%tD=MM1RPh5o*zPMK`8F4x5Kw#?7^WBVy5Ws-6K`B!*reR zocAo<-a#G2Cfg@@fo^HuoUJ4(!NRviTadb50%sGrL(pcNqL9m?=k?^cNAOLfhc}5j zqODj8doUnE8Tq~dV+yWG{=!M56H7A#j2RdRf4+U+2t~WC@xNDq<^IQITuccqd$CGZ~ zK6&cY`1JHeTk_kaEvBrj3<+Bq(){4wp)_S5mO6N~t|mNRzdlnLc9Xkdc5cO4)}L&1 zhQCM?{Y%%{2s8*1^C=y z^DnNFD0CoWm8+yDC9S?ynmMvR5QrTR+AkfyZld-wxlJnbq?qB+qv22CXfs3egvN$g z5>m=iik2Ate4xBkW?dTiHxMCq1w3z-Iz76UmP5EC*SAB$z0JF zWrJjgTc0CZWw2|l9IHtdzW2`L#EBPGHz>O*JsfroK-L2Q?QpOCnwnR4zzgJyp$x`o zsvr0iD`KO5$bZ;GrFo*Qy?xA_LWUoDwu?*gQ~Nf8V)x4YJh5h!tbWj7y4{@*^34R^ zm!1bLD6{7t-7AS53e61s{o_pMAzRx~K#PE0fI@2eqR4o%()K={^I2J0@cz69U_y_R zhXCsh*(6&c_IdV$2VW{ZS_cNsg(CJNi{^s7HBi?)j}D(DOVWGPvIh=^x3#hl{|>)NW2gq`B|0W( zmmpDz4!zHSbh6gZ`<2;a*Vt3SxBI&Ze*)&TVP*QzD8I3^4P?(1#CC^%Lko*&XS-YN zcI#*CoVNO~o)AduJ4&A1W%%VF8KG{YJ3LyeM9(;P^`QOr0ak^hZ#5p8QczMFo$>0x zmHit3+@YM$+@2sq3?*j z;&lQ@Z?)=Ioe@hHGcz@xMyy#N_5oKE z78LBeejqHS_h|Fl#M6w<%#ciW@F=CGX^Dwp{A}J*s2)2MSKy9S82vo3`ssx5k*cp_jZWV@>E>;HUcbCRBYX(cYj zi{eLhzb4QK{ibWLq9wSrSS71oV?Wy0|9v(_Mj`UXO8jO5!DIYz)%~dSan;&8G6E(v zi=lu8%ioz_D&2q{e=hTkc3DsQvSqbcNr z>HT-8*MZD?_H0JK`NXNZ8-$O^y=)(TbK4NF{J;uPM44iM&x{?7fw~zX@4h*YpU}=A5V$B#?>YJR zbk5Z=-PnGBY4d?W^XsW_qDO!3i{Yyzi=ut|nh)EA;H*k~vp)Pfc-WkRAmhQlrDo%@ zNLEgEsP%Y+vt0$>P`Mp}5cS`)^{#HzJMeo~PCIBQpI4(z3qI0&g*m)-S4`8&9>xb? z)0AQpHLfWMLhK}{>a`Y^QoQGsy|_y1k$mIMEn1J~3up<1)CBG3m$}6^U%KsD;}#O` z-2Y{(k0M>>A0~G8_~hh?w_c8b{ap;v7X5gWrqR@(HTZGLg~z$nr)onABW19LFX8U5$oCEI05SD(rmKg?MkZHS|VaK6NZYr^3;+d;;S zUT_N?fQd~IH%ANxp%QKLuH}M9kE&gUuI?@}041u%4^t1>n37+7H~PCpie@gn^*4Vu z&x6`92FpM^>PE)?I~RS@KZpKV3Iq%M4lG5xed)(vKf2QT5T1mDgf4pTJ9B1$ zeXnW7yrL&uRO)QJBKtS=gyX`kolp56HxOkjS2@Ji=o=WI_zVp8-zav@QH$-!`oZQC&Ek_VGR`*tr^6E|8q|1TXE_B8 zz_MTA31RQ;J@AbIYA59`pn%B@{=(bxg2sr>ls?xo=zl8!PG(=ZPR#t?Tbdu5;{Zf6 zlrcUnNdN~?ST+4vNmyFC%TA`37f3!Ax~Ga>)2T1c7OOx_>;1U%LeS7fv0WAlZvz0qJew<~ zicZHvKp_!~Jii{O2w|Cec-%<7&>L&+6YqBk3O490mROdU003|8_kDEq0}N)XtRoLu zpF8(p%F@n`L~7_K5h&ljeOsnd{iCo7jjaiDL!h;X>O;5B7|%pfOCsoPx`@F1eAb8j@qK|85{-3rbUYU5Jqd)2N}1O;L-eY0 zov$%w+8ny8L4xeVdHT^>=PhVg!G9M&2-7Fnpi_WK3qMZJGyVXajqXkQ-Me41k8N9K z+eN)8L~juc?7pWL-1_S2D6bjiM@2@uYaG>yvnV1pUY50<1_cG7IlGIq7a>hfuIxa5 z+_guK_7oVMo{{8JFaoa*JV4_RJx}A>K_UmiMV)PCqC4jPVj$*(o_nMC+N*>K1iKx- z?Gm1rM68A1*SndzPr)sgE>sWGNMuI0gh}!Pq+vZM2G|h96UT@>2yxHRb-@?1Id_is zs)SWT7&2gBRjV>lNu72$+M)N~+rQNDlN35DcZ}@-BZWpSeyxcK$K{}+T;wH*>LnvT ze)Q!T?l!i_1Ra|4+JPHBopv%vpy^L?5ndg?)%e&TS$%b_GlU*J;OgC*2tgrTcXbcx z9Uwbsmh(#b{e!(}-^^pjZdppK0v86pZus|-W?m&w2~IoLd_Xt1vPlK!0oDD=RQUiX zB^sL8(SLve{cMn9TF@jV`hcjR;kuXCpm1L&N;S|r6w?@3ADRxCDnIzYD*Fz2EZg_} zr;U)+plqRx%1ZWlWMx!B$|x#Z!!Dx;DIuhY?2?hnC@Uo)*(+Pi-lL)9f86x0@9+JM z|MPi2@2BEpI7A9_Mi~QC+^;`TP0u-`P2sTb5&ky=?3nG$5l zyU0lg>iepRSf(QA(yQX^BkeVDVwpLvQp}#me?f~r;65T)C~7#Jz3q1(m0&i*l4z1m zJ!aQ;%>6?B+PXWDg(alkGP}TmMNCkUF3H!`Y~}9VW*ST?gVwqR=v9N59tPc}+h)*q zk+QxA<#*~xU&$sX={NROi&@f*N0CV07qQ_acKV*(=cjxh^*s7|FhRyG*I!eL-z0ZI zlHRz`HT2Ml1x-5Np}d((t55CRWZk`L3rh&$@^|#ZNh26O_O|>wgnbIA+^Dd%8i3 zy(cd2340Scx$-i!8?1A#+4HPph|%Vok6F&0c}nS`IUMkt*?s)?ucF|H)FgQnTNs_C zS8eu?E?DTc`^+d)s;eiq78TAtDe&q-Mh_{W9iI`Ok~WSG=rMg}3{_}9*mT`xPpqcj zi%+n3?nS=*@&&dFbpqeZbO^f1JUB_MjdSFoX}^*6mfm*F}rl=EqXpyj39hLF&iW}zv*gp=Wssw>t9J{jrOe#5RnwTwhkrDFI|7aJrN7$Cx*Ash3_ zIMn~f`~H{cVdiQFvk|4qJMzOQLZcq>Xw-2x@)Dchu>~TY)YX-~%h$kb!Hw;_c!_sF zlVzUYLqIFeNLPFHEbmYL<)pfm92?#+i~O|w1~f=>KNHas36i!$fk>OBSf)`92H==L z-A<363EBCbBX7vOOy~akf^7&`Pm0{eM4Oiggk65zc`d6w{Fcao8k4CtY*aS7Zd^qo zjp=$&oQU|Cm8@7Xakdb=JaoJf;&cfK$05%ST>=d8IfbwS>H;X+;sxnmpcQCQP*i+@ zcuqtFV|pJXokK|va?b0%Hi5fvW`QH+&*M#G1QtrWE+Z_1R|KBo7-%K z1qDADukwx-Od0e__R?g$pXq3^hUOLWg*eK`#-Vx9b7zHKovS>zH5>#;dkncjWk(*` z&9FBM6A&_6ia~}3UF2HY+I?qVT;-sky8Lo%ji;poOk!Gdw=>lsCA3jk zWgMRXH%qMN_wdMt44|as(@bvYJ}D@WT4o-FMMNYwTMy6EAZ#r!FE`D1#6Y9HFu1C! zyKUWqV!|mem+6kM4Y3&h!39vet!qfVO6$dDu>~!6}g+4Zz_-vwagCEn{WFCPYcbSko{<;kCmr#%j z4`=GW{7xB%B8Z=HJ1=iaT$}=v3Kxv~1%q_hG(^#e7q>@flz-ew#%1sqhR>mQk`uGt|1jCJ)6Y7)tMNclYQ2y(ch)h4CpCbGXSl07oIf1u%1p0+xy z(zj~zmIzDG_K3ibrjx9cw6xBr-$$QfAR-THP1|?SII?+Xd-lFIQyJ=S=Coy)$|k&R z+lwt!pWY~$)Ye5U)E#Un-Ie|Rp!-Yzw}Rbi*su?azOY<1SWWU?9l4h|m$S*j=yk!C z;6}2Sawd2OMs`RF%UM<;(8b%4h{wO z`>wu-r+Bm$W)FvhMI>G!b9;pYlikm#y=v=B<02N4`HE5l9S*@~a54-Yr8eeH;G&Y= zTUl5&DY;4M48k133xjJM^x3Fz@0*Ctc^5@b<6o9c9*1T!lVo@yBB>3l)H5=AQ$V!`n*GQf3e!SF73oet+H??3yihYlbUzdL z*2KM^eDW+SE5v0zi6-@yn2+TT?K$rE=cR;xtCP2b9YE_DlC; zxU?^hQ!VXHi`Q!Lc%$dgHrWedCZ=T3MeHHAQo^@g%R|W5M)lVkKiy7_Mf(U-vY56q ziNq71QlT!VlDz*l=a4p;iXpNg{MpQg@dRvN<*jvY+crG7B^Ge`u@5KH?%&oPsVaZ+ zlvnXFD4Mj42khfd`Tc+;&TgBNoBJ;5#KX1Y@lSTyt4Hitki5-v%XACwv$rbAXfv`Z zp`uI7D*^7m#pbt*%1Aw-WF^Lec7qP(-9H_J{`P@;>ss%n3ekTL`7X+`Am;J5fD2E; zk%$g2Vj@*{o;>+F@`zUjD;ZWQ#_O8xVv=68PmrjY5+>))5SGZ>D5K9fAlmi(c|Jt< zr%vIN?^RVTIClF0a@2!I?EAD2@G@;se#Cu3>DVr&3WZ%(0Tsd9abkk&Tnej}k-Ybo zEL`fTuy`AjNQrXvKdg7QN|Y}K}c}}5CCNH(8wH?mYS8Q?gN}cnh4jN zeY(|pbv+|_#zBL7qo1w__gxj{AfSqd(;@r#p;Vh|cO=J%m5He-(^z^B4STc^Z}<=R z*==7f2#6G24BQY!!+<3;upgUuW-B|x8~*U21EG?Ko^MF?p_qV-)}>`NLZ%Xv*LOEt z{j{EtG^8w}A-?0zKIEtThkxC8j&1OaT_pb2*(1E+h{YTo#fDub74oWmq1ok9x;_+d zC*865`K;c*BKm%y`L@^<0`X6wJ@qu|%C;Eod-ayCI7nCk;Hy`!-o2rqrM=ns ziT<|kzGr-l54N4V1EL}c;Ss(%^!3BlwU??UpJEOu5S(p^_4f~??({#dO6QA+c;~BN|9tO`vWf^{-*V;gk5? z#v3za3$EGmfXiH5)bWx^zaz)1j)vz-b6hn(FZ>j!OZuf0x@bo69#X@vYnR(q=AUl( zux+RB2aL@Fl0TKHRD)z)MP=3a_D}ohR$eVbAh@Rr3VHJz5K!Dq_zcxa%>0;RmG$Qj z1lmX#!zXP=4Gk+0Fya+ES1)Y!kt2C378l)RHl0o*{ z>H1Q(>{EuivEi##H)ao?Q|8q>xMWLL#r8cUAAKpQ!sdW?#&QQvB~omo^CFPVu*xJ| z{t&I2>x-Fv1@EcF-IB$-{>13X|88@{atI2J;LyrXWL_NpflfZxmDKT1=~pgO=1=(} z@&05SU^_TF=j}~OA2jC^5LlbXVF8pBwt{sVBNYa|uk697H3YB29{J7IvS&V!ff9LK zxG?mU3RHuwTa&wqJy@~&pKgITG8Ri=^u_*wD_5Ast@Vm@7CwdPbQ8liyWMSS?(Cs4 zT#u*2=nJQSngE>Z;_iC7A(%)5@IXR>pt;F~sG@K!wx{Jxc;Q;h{C&I!L6^ZozO@v? zEEr;KS1M*13SuKXDJ+!f-db^+*cfU778SM+th&wlzbN^2Jv;H0W@{op z{@0&AVDE38An;whMzBNwI8;k+aUUn+15Xrb!1El9_pvz}x@a{>&Nv{L*7L!dmq=3f zCca-npqG-A`|dU<868OF;c{>oN2NNSmhi@YGZ~wDLh#&<`tSSG*_Sd!{PCWvOQ=57 zi-GFrxx}#Zgix+}yz9cZ2^e9Fxjgv$p=U7!{+Ig?7eL_@yks9rCTwvF9fh4_?_ z-m^0Q9>OgC^xqyVk<(qYH59xFbP=KiS6w*qt3hno7nV6jN2_0jYu^KUNf?x+_5L#; zkwYjBsf2~1uiYPw5uYg}{@WuZcEPI05S<{C_a=t^{&4;Oaew@;H<)ddp%hQlGf>j` z%g+46^#1!MBJPzi>E5h=v)g}evA=$b^2=Vjm6w(1q5D!m*Cw)w8iWl{d|fynC$|ox z%Qh<|IA#%gyDBiXDO4mrYty1#xElWe*gZ~i4}d;Ug~y;9AzhrXM?fGgJ^fk$XqTOb z%o?3Q*+N>=n)4L{Kgr=}vj^ywe;tdDVv?XW43dtndbn}VIhBMX;a zUfMIb1;PsaUWNw(!or^5)#yJo5vq;|P)n>Y{L*fNxk#zQt^0N4zJEfGod!99KmTDJ z?>3a@K*Y*3?kIp#Hk8dIC3^v;+}gC9RME`Lb>Xxv9dU4HxnZG+XYseMv4vtGWLhBV=u<*CQ96$-gcn$7|pedmEO608ODCMH0TAiYRY#o?d*gE#=XYxKYq0SQ1PQ?J}`bxmI~YM);?aW&Yw_i;o49kMLKl$W$F3H zz?8j>e@Cw}36?b+zqv%TriR8&e+CsoUb0~&=xS-WLuf=|R+2T;U)yZuFxCgnOu6rS2V1i1Fu6crvln2x^y&kzbux`)I~D0us^2^8sw$Y-@r zJQR0`{HJvoZkNa^U?KuMPc2r?F5kg4hQhR72lxPVNbw{fZbmn^13JgB&d@O!hu~Ws zLN%^A)Cv~9*LqC}Gh!PWhHg;ctR!E8rH5#Uf#|N}#zD|2VRxzjVIL|nv~#=N1>hIZ z9>|jINl>|psYTo5Lu;$UolG!9TD++&VWkj>;RD5aF; zxbA!Z+Af`dI+x5cPs8$G;Gcrs)oO2W`t$^v>XgWY!X8k|E>kqwlb$LbIMC3jBOmnR zhWdXSiX0Vu9WF5GfBHxQe_wyq$o0I~vfmEolKi08r+oV;XFToe%%Xk)XtY?kBkfX? z5kZ{6r>y_ug^?QvVWPcr~H;2d>AW9c6yCtjf`=l&lVj+}UL;ZBI>`NPJSYUpLAsjlN?w{TiR_O@CfJS&8K0f)W3T~AD z&YrsbuipbyhJyaE;7xF8=D~iyOAJrwTHOza8vAfVb9IS;Ae<6Ra&#-UY}GuALX3vm+r zOf0c?DpW$bUY?L*z(wk(8-_+lYmy1UbI?AwEQH(%4;KS(3earP(wy-D86EmYx;1Qd=inyMEA- z#`K`wpZTb}YTEl=?PH;|L{`6)tG#hUu8r4I-!1qA3mw!|{%^?t@A$3X3Q8>c(Xp{L z1$4wUvu<|w{@4tnx^dYs zkEmL;;}Qoy6ICZiFssjtxMphy>C3+Ejl;7TS8v!@u8olg_KFpNM+y9V2{R|YN8&7- zk~$C`gm8GdZd_#J{Fg9^_|1~*KmB#t)()%wfgyr{g8YRDsP;Gjog+g6zU22lS@Npy z&&s4++ncD7j35h++m`YYcrbp+QX|j~I|fXcKM-1@WxWX+VB$!4nK$Pc1~YMUU#WC_N#T&zo+^C2?G-s--c6e;`TWL z<@HJ7SKMY>o7hqO`hps&MhBwE_pD1m#UJMbP>$l?BuPeFOWbtBi2OB`U>A4{c`{_ijceE$^k@)^W}#0-+m z6%e1jVu^9`2%()=8=-IqMuSLdZK*5Fbg&Ce&>_fc#Jcs}{+@%XT`kZGpG%hzNo(;o zB4EJi=&mnd6@iIjFzsf$yU7{EBaLJRm3rl&(4H@qVSGDG3J3PgRyY*I#c_Zt0P%kO zq%9X+=71`kopb%0xSx-jdd<(mcLLV5cYO#tg%}Q-q~xuysw++t#USK%zo1b%DGZ)n z$zkX!Rbq2|Y0gMW@(sY;jQ72_KxW4jhUV&s1%!4N#-8@w2x7J*DIoyk77_|l_i*|+MM?Ef7@>6K-?C{-DqIL!4PF)m?p3ZV z@J>Nr&7Uw@qK}o>Q|-TjXdjI)-MNx*>+W694EKmeSA+dom`3av(mEnECr(ib@smx| z=%ghQ;UW`=jn&|vFy7_mt>75ACm3J?qysYrh6p7U;@xayzsQfzik(YjBTJA=uQBkw z1O6z~ZDFpU<)41tMjHwp`y6ux`0 z41o~Jxj2Fa9U9iw#28vaMEBIGX%t^@XbE@rGo-Qxs+v&T4Nzz2-X1}87^LZEe83{2 z4vet6LpDqs~(M-3W8$9 zt$<%daD{4hZfP9^+Q>n{_T!F}bU!(@4l69?KC^r6{P#b& z00T%IgIL4^T{v@K)ezoca2*TrYj~VNdqvG(Q+Ho(sw|bC%|NdpGP&47&q74yNOy+o z;#Z6-S^KY3X%??H&C<+!tEr>YPr!eRFNLr=6v2Q0h19FPX%TK){QJ58-#>R3uI)Ad zBVc+&w5g-gb$wMu?DOaHQg4~0-bSJJHZ=v>u`Mbdt5&WgK<^2m<)3&k-mARa-(|hi z)X#-3nL?#?JA!43l~BT1x4_pt?KL$uq2s~!YrPtqX}o`A|4Hmlx7Io`y4<%hQR)0L zX?%A`PY-kbP=f8gT%nJRefKUq0m`tRq#^!W-8M0?<78U1(V;`1hli^QLZsYWS5$r! znE8oJyj!7mp|YxUbAW?L=JZdhuGPx?e>@H|S`d$aze=|F>5hE?t|2%5Ry4yX2lXd3 zSdO=3bbuBFqM&PQvmt!2pTEBVQy}8b4z_E3(v`;_UBIYCh(g+9RF;{UnSz4C(W9M= zIx^6raxS;wt3Sp^c?rVJmyrJUXzpm&P)N|#4Q8Q=^(m^HGG(MC2Q*S$(YgBWAoRNC2jbd7)f z_nLyUpEb}YG&Fa87xD^RWYnqn(i#vL51u}KI%AZEifXQ0{@1Y_Bb(UEw5>;A=%EAB zl!n}{$(_0#W5wAoWMz)8lRyt`mh@UyqJ&A>&lF1eSq_4dQ2+q4yCA@XV;Q|K1&J>P z&Ibh`e)B|<4vno$aS0K?Cxy_#LBOv<#>_!rUunZ?Vm<2U_&`rAXtOAm?|2A1gc!Ev z_#;d|a70egu#14Y^BnGWZCb_Z+<+gWU&=-z`pN*Br^hg2m=Gw#+$qRqfRLnCE_nFy zr*W@^g03qAr{@hbT8@?a%}?9r3SxCWlhb^v5{f4?V|nmUF>s$6uHYh>G@TB;FRG_wkcCjqVn-St7S4Xz$Je#jT?Sea*Y!jA9MF$MLD$`1(U&BN8@qIdNW zu#e1a&Ex|Z?WQMB&zcFrnvMDkd=Fb9ba9!O+n01?E!edU-=8d9T8J6NXI==EUz*wT z18pOZI4B^;l+c<2fuTlMpDZXsDIXF&4a=ZO-0TuxI{O4ebp{0_KuE?%jXHHB zxJ|Zyiw^ofFNfn+Co3R7Ko;C~82|pl-a$d31a%Z)yAE2P{1Ge`)U-XVg9-MDc)8VWj5QSBgpb0H6rh7RcrkJLyZB)-))18@q+%ggIBxvW(G&{Q4+fqT62 zWP@p2bug|B5WLU^P0-@*x(}tIMs$8$O<(_J_WNEV8R>zY#M-^X1EPh+kFpyMlx~0$l`srqss1+@t9earu z6#zzjM~*SHPdFj;o&f+1Ceqp{*9^3XqErVv(>lG%kl%In6QgBNrQ8_@3SVKbtt?(Gd0cB3zCqaLERJo?Cs(bgg zxO*$b*IDNfM-+Ml2u;ak-_2=Zd&GL&@HCzn)9R-|o(6=<&;T(OEx49sm@iC=(?bn% zbI@zh0v{fJ(g$Nj7PD$d8q)k(_g*>&P6*!cY5?eivqs~W4OrXHt0ocQrvq`n=g!#? z5fWYt{qhUUau*0Sg0vo4#wFXb`RMh2S}3c8NFb3KmU{i=QHS$RF$%Hg@tuWk=g{wf zo(l2|05OQHsMRKxW(ELc3=G7by3Y;X`#Rczy6Knh^Wz>+lx+@H^dGOlg0gx2JhPvP z(0c_>wEK%|_Sfrb%J-2Gz)Hqwe?=3P4s>4tw1D&1u&f81V3>tu2POu`O~mH11&`Ms zP1{zbFH}!=2qRd#9u-9`_FNJ5gNN8IXc*;9KsZ2*56?9oIK2YXn(%tGRaw36SpV(n zKD1y_U7}mRKF7XGYOuxidVEohfRIqcn6UyG?!Oql;)n@0ARUB}K`@eG_=s!g&X52I zD@P)M)R))9{#?vfkgE9b2R8Wm++W+V3wC7eerlz{v~hS0l>EPp>?r=GaGVS96u)}KiXw5;{-x>6lc}|&?x{h80d3- zOxdk&2>Bom#+QH-)R7#$E#eI^N+-bN!lVk9I}rF3?U?N}%NBhRDeDE@8&-sd*#wBy zx+~Wheq`y|hN~?^kS&iB-SyGcWN_|?%?7@u{_``N<4ZG{p*d%F9+4fh z(S)LHIQDr=Hq0uNOW4U`cpEtGwUtlmOn~LJ1Ge8I+54DoK$5I!db!M0ni_OY-Heo#rpE*L z19ue7+z`76?%@w0NA~Ca&pWjszKsm{`-8H$0to`zA=GbP#4`;kqD( zuz`0=ZbI)4x_BhO^2oi1XFS}VGmJa{&GAks-@pzx%amZGFlKrNfM;v>tbHI$6nH_> z+YzIA6l)raSTQHO@$m^wt|62^ve&{*0r-G=fEpPU1zd^vIy#kIqM`@e_bzRR4O~yl z06Zr9d7(VuTp+kX6BuMt5q|mT8=FF;Zl0-52v3|?efp$R@hEwD{Q|H+!2G895=ym= zpmWs}i2B>(mKEJz3m${sK-Ld=v9UVW!__5k7=8CBvCkyCRXx|L9`)J`eVghP(Cy%0 ztpjW{1VcqUB@P@DE$nU%V-H3)Hcw1g>X^p92-@8pBIiYnGuaW0Gqmd%H^9+|ed_Hg`yU1qi`H?5Jglc{f4vq3GWBsv>d)SoXi?koyzn^7n zfl2MzQ&VRezAsqX1G#g0EN> zpF`_7k2nN`9+i)xfS5V=442*Q@zuCP-WbLZ{_`8q2Eu_8_Jj~L?za&ZRrEK0?@F;X zp-B4&S~F}-?_=9}K}Gvy%^l=TI+*HL|K%q@XPejnTAv?#e!Y*+hoLp&G|^hT)Q#~M zGnLmF`>qyApj#+hE1AU`_yOO7LwWR^0m?Ci&_KqK-Cqrw-_fwixT5q+4v&tusj5q* ztakCsxLqT;G%IG5Q)+}~KND(;3%HDyxgyv?uzb!z@<80Y3NEh@H5kpCf}9CNU>ubb z{6)$EJ2i|?=jPa{Q{_E9Ug+w_-#|xnE~q-~u2rL70D4*2-3Q`_3J~ys>552v zd)J{bG_1`c6#OwWSQ@XZb9r?>1&t#;%Yf7jR)9mG^R=l~GtO-+o)!G~-1qMUO?tH5 z3Eu(F*lTQH{`r#zKV{VTtx@fv#apO0Kmg+iD~fsI)GT8B!ooG><*Gx?I1<=yz2C@= zPd)7m7&I<@k%E+x1wII_+oAbE1e`Kz4yY)@1fGLvXgT(JuXb*a8MvaY?%r*-I8_Ig zlrA~m0)=gO)?T9Of>i>cqs9EoSQjMFY9Sw;ruP7a6r={vu~rzV`JxI~Zo1*4 z1mIopY13c7>L5rMi1(Mn;8skR==EAzT&IBRAa2K>4Qo&+TKI4ca8wj!&GM?J?vKG< zG`xVEfO7$21>iXb!}lzc4}5>U*`cZMF3J{2UeX1u9w7t(AVD+jZ$Y`Zj<`vufq0yx zy`a?)A9wbn#Z7-QQyGS-1B)PLtOG!ch|Mz;BpwsQ8_4AD?rua}!-#a<+`gloZymdw zAnP=yd!aVv-)t%*EnNVD1{?yJiIuerHU;|!(kci((QX$OfO67p^wfX+*jVD#xB5SK z)Rr}7#AT2KJL?^?RQ40;SkgyG;P37T1C*6rRDl5H0sC_lJS!^Htj3Xu+14J((C-k+ zR}EspG*#OIR6Xp*AER|Fav{L>KX-uNV#ds|+hwk_6cd?}KDvx`Zj;3!TKn`q6t9}1ZLnKuh?XnoEk?uepMr|` zU~&<9^}I&=Z`)-z{qreCiub0}}Y>nc^D< zS)P(>{r+Jw;--;?67P)4M(}u8a03^j;m2JD9nP|4K=+Y+jD1_5v;xg@8p$w2PgKr} z(f`LquUi5@EE}+^`0NNFzFfY<#KdHp#oiGnK2vO2_*qTBTDzjFflP?6%QDJ15S|_x zX;A&DZ7`0x^G?nUsoq6+k;q}qJAdRkh6ZQGtb$Lrf2t@z^!nWg&Bt5qwe!?k)eMEcL%i3BUKsh6A=P;iHQfa48>tjX@q9Ej6 z%xr99{r#;lo#@+7Ka!Vuvc&(?lArv;hlS7|y}pJ-^V)e2!lJIP)3x&F-Q1w|01iO@ z^&YrtY%yEuSQKB0vqSQ}u#NDKB0MxVpgCt?>hZZZ3mv|6`!TZ@a_XIWhs`m0JP4%v z9me@HNPHH%DDcM9lrYG36DWZj<=JbIp_!#(T#oXALwoj>08AYj9336~whEPpe|Mb4 zEk0loVn9h!;Wz!vxs8>aW9Y< zFq;|a1OD#yr41WYcKE65;)5W?x|*(|AWa>s@|6OE2zacpUH_*~P3{v2?}S*hu(JvF zMu)g4!9iJc(|J4oaMS$xaQ|d6jPC(W2qIuyRJ632p3?yclt8Cd593u|$IZoM>yilV z_--_g%^IY|Qi@|ijRfEhwK4|1XZe2tPuQ9OoqwcJ<(RtVT$r&vtPyVgeAU}r6TQt)IEod!}#h(cx!ML^G#kIe?+}mVg#$sN06Nn-x16;Y$U{y z++1nRD0TdVOjT;jIgD2V(=wsi8Zm$^U>Dv-;yypeVVNC44M8jYdtXXMG@5czyhONc zdVW-#3r(T!kbWf6j*T#>vq-_Ike!bBT5~gsM?shdR6Kln zqY1^@wcH5=Hs7*w>GFEl!s(ioNtoTpEKJjO=arC<5EswMY((xaY}|{PZlAy)X_AS< z{)L1QM*_F%btu|5%fvxN&$(8Oem}Vh>j7z>f+FmKND0_#o8l<_G>`X}H(JZ}VACO_ z3JG|7@`+>oQ6DCGoY5#9{X>V;H>2L4(~+#V9V!PZ`^7d126LlfD+Z)x7i)*85p=Ss2|jP0m<|1k(gMQGKC=J;7m=hwK~<2@3x>I3l=3JOl(Cgb03cuuI>%#h8LrvWm!N zlu^7vCP$tDVDm0Ed@K@&r4hOR6y>llogf!tds2g2F*DY69`=q9 zH^j6tCMp%&nd9?k#3mI#6}ocOD)r3>;&PM4n?L8Sd0MkU%7h>=Bn6=t&Z@NR1FPfS zc-?EnT(62yWUxIr(TibM&yLR^emD&g7#T_ym}@cetwCw&yT6vwQIX!U;M`(x252rY zHJ$L+V3WWk+}P5+QRny(H&B}*ZrpfTSl98)b@I4zfoVa>s z&W}A)ZO=;fXw8Nw18yq6pCy~<-_N}IOYX;rs8u4CsbO{E2SVqXSi8edQry{|LB^#a zxeE1^apX>V?tLW}S7;Y=EZ&)ShZzz@TL6Th;4s#MMhlidj+8bTL5$M{AvSsd0fzaT zyC5S8##Qx-8Ta`BdTyYaWq_(`XbkQm#KWOZ@0*4<17N_Nu+ZAwrK+-j_6+GchaiVF zh44_q4UQN|wVOAhF0nmfSVgTaR3FYAUb3HCOP~9KV(@B1Ce{X-;^d1b-FSAr4bM)O zIl=V((yj0~3QDRs!^;b#YuUfL^^KGkXCbMRUeQx)T3XZD)^lOq&hz6nos%;&Nvaxx z`aiKSs8<2m)6mq+X?8PZy_R%GootfF@DlRULbZ~5BglBIj=3FoX zLsU{)&Y6^&Y6S=bAa0ZmECwr5v9Fk;Dsr_c;{<58h=wor9Z~~W2h^C$*yPE{AZWU) zTwO;+m9Q3{m*OJ+*yzZS-L~%(BGHI%*>GkVDWD3t?Z~fF=xlr~M!9xvVuw6H8ja+J zhV@iimWwei{>LtYKV)x3?=v4_z!~-`G^&f6I#^nUsPT+EkAWzvFb#MSdksJ*R-2w} zX=%YeuRDa1M4$}dY=bKa0C0pBE#;Z|Y2ruft3vUEYype$dsl;knoTqvHu3mwk#@f3 z5vrZ2O>rB*x$(r;ufbQZ0@QK^bo9;#8hje3PTl)nrV}f3o9@Hs&&i_i;TsyyZ>HoF zxh;qp1u*w$Q8ayQK`G6bk5)@f&8szin6|fCdb$gn$;QTp#^J)xZ)fr!#l&D}y5Sa0{0(3gantd>Kz;qunEQzd70jJ4-`9KhC0_S1Xc&X^y{au*@j#uI$P>apXvJaPYdWvzRS-VZH9bgNbg| zjZM$J7SL~F?tFIS-LCdmb1`c|SG%HswQR-e0h@@>(E875tX1?@-XpuMR~w$9({Nly zbsGO?K7cds@pH1=DVGI%*V9wZ^s`e{-?Ax&%QUszcaFhOxtg2NZQrpYc>bX~B3@w| z8fv9o)M!xGxg$CGM&KdX<1Z^K)wf4zM~Q6%09jag^c3??S|y}4m7mW(J8EKT`cOX& z*c%HAi05wxnEf@fgw9ql{`t|DwVL|T!s&2l+d#f)H z{gMf7md%^dk7WDKjn3Fxe&Oen#6)gmls_wQH14IO6r&jk3?ADwWU#@JR6(5iBxXN! z9YPqrx!LKCCm}JGTw#Ajpk!pkc18UDk%KpKo}bR4J9DC9=f1;-Z%0ROHXa@uV_Uy| z7AYKV4#xaW*CB|i>{!oI>PI}t>RRqjGd#%N=a9a%vl~TK2|(GYVaPniZN`WL8JRnt z-vF#Ss;c^bk$?ph78Z7lh8vukZ9&wQ@PnF~8UbR;Np&RHNjlvF9eLwO5*;PR2L`~Q zVVC!m>G=Lgy@ehhYmH5 z{&@WL#6aOm9yH}-Cf7c$3kMoUM^|D}V?JHu6R_NZU0m9IWrwFmT;LitFquw%{ zODYcF$92CePeOZx^N$TJoS7t=#9IF|=gvKuLfw`S1PUo0fY@S7OG+0(G;{O;)xv&l z?^UhkVtiEbF{+X!zc2IF_QA-XP>7b2=D}7=DQJk5vOo+)-niMB?G-~W4D!I$@xtlrHC@Qb8fl2q zggNb<9mgp{>Tez1vwL@BRlJd3z;dzPa(1umyga@I`DCBwfUU~T7S^bzOSzoKq^$fG zfV!_q+IJhuE1XN9>vemj_eE;mqB~Xi26a0hA0J9iAt52?HjNBps|)C-$5o+@!@TRb zZ?Wthc`rE;ktw*_y~XBW{|>bF1qB6BT~<2plbAlu?#v9&PE)4Pw%Su!0^X)8;$NKz^3LgAN(fpXsB zh@qjH>D!8mxQEwRrS*S|3H5pPm|RZEug$ zAZGjnWy{Uowa`@?xS2b@`bgoj$0)c17Pd;m*5N)fsUo;c_(<-xViN;{uZXc$uUT^* z+8)x<=zb>{DX_#_f_rR_Q|hv_q(h;-xsSV%H;|f7D~fDdc;Wlw;;zSG1wBRQTkmuC zUx`@pX&14l_gzw4q$APgA+B%Kc@MZPBO?PF7yvQGH*|C?;FwEA*VU{5;G-YIO6>tu zZ*ax6k4v%hP&{Z5U~rWKGb0$&ChP)C8wjwAap*3e3| zhH?K&NxOD2r2sM)Gv-a#Z{5B<@FAbqZ4IVnLyn){tas<`22~0%($$AR=%5VVi?NWP=h z*|SqvAOO;3#cT`=$8*+%Suv=1OI6?56Gn&GiVh7F*SAv0mx2u%FfZQ7JbuKXsBG-T zx3!$#kN@Yzk;joyC%1A-N=nx0d_puNdfJ7$!|fYZP_nQK;5#S)S}{dCkf)=l!}5et z(TR<`(JWGtpPl_K5{lsqFY}!!WJ>z_PCENQSf@IaH$nrv2U<)u&X0Z$~1+Hu6~#%00N1l51Oo6TJ)U{oj*@(m6(w`L(cXNnpsBPGJ84iPX~k& zjvO!97tjb4JFf`Z+-ixF((5qjGo^Sx#xP*8rX4}~21|gb?suXF>gbpq7RKn|fx;?R zK5H<8fj2xjayT3TsC~4cs9==_d4}q-I}wz7O4{3vo*fmAtip`o`{(W=4v(Y3{D1?g zVmUk}6nhlx(Bl9NK@RlR`EEM*F%~ykik8mYTvR3CTtH-WCJdZ`v$M0v?Q5Au(7UW$ zQ@bW@RfPeQl63H<6$ni6s$&$}y*qfzo*SN9#=lVZWKZ{^Ny~ct(X(f_J@y_rdGciB z`P109ZT9L$Mp5sLDKn-y@=1r`i+1e_&BbhE@l-apE4yKJF&q-qK07qcsf1~KxcYQC zh9AU54@S3?^I}87?8L;xTtT~QB)~=OyK*tVT(N11-*j4@A2oxlFKQmC5;D8sdS)?XJ7yQmO`rleiY#x`t;j zkTVbNeh0&gdfG`nzUBIBv(PC3op0pDbIu4+_T8ldVbavV;FR^DT(0{)3h18AuWN6& z#$S)8kyZwQ)V>68%3 z0{k<>`(JV@=&!r_QjIoOn7BHUf*2&G29|f2x4xFMPtVV9XA!?bl}Cco3ovdZx}8l; zuWFb(FB@f~ti>f4MhM7sE(i5QcY6eOO14)Tu!nBPT3kp3$n*NY#r= zmYHP!D6DMk-6Nl4n?`9s*M11G2f}_HJJr8xLmp|6gNc)en_Icx9_YKdJL6$BHHw%m z5AJ=~(2IC~@FkE8r`$PU9|IhEU}4s>m5DCs5Y=&_aQG0A`_AiE3#r^Gq03%=k2E9@-il10rg!9!oK*G^SmXzm%xmaHc zpUJ!}7b=0&j8rxOBLd?Sh|tKTT#WVsU?s{E%^Xr|jtg`yM>xP+7opTj!(dSAWud~IXys`0gH^BxAv~Q z&hE9;)aXD@v(sG9Yrl+^S%e3zCA2#;AhCrc6wEmGUB}6o3jr7&Y0bb%w7VzP3J$+` zx(ZhVWij<1Mabe&*aML%veJU6OQKSQVGCV?OFell^87X;(>k|~-Fo>_Nl6Xi3(!)_ z=7v>1=lt+aBz-7Y&Vi=wg@g+xR7a;4^_feTmb)wJVtkJ@Tl>QU$@&gFOo(e#j?5OeL{r2z??oTh9WNn2`;5)7=ft+~g-u!j8yZpg#+{ zasjwEEQwUKq_p&@6DJ_;XFofk(z{HAx>Vaq?AXhd_6~Md%WJbxN$eT<2KGD7S!dw; z(B|czwo)yNRn5OF5WjdC`$SP0A{Z8E3@2ny)YU6ti%^|MPzrS>^W(>Pbz*I6lnc(U zpk3D9)@Fy%&Y(IVmleiG?%44hOl6c9fW3k#)<%#hO3wATv)Mnth;lLJS2}BJ*8ogL zQScoJN`#>yAsk_q>0TVUFTd;DGFh$SK3U`{XwQre(Jw%}u(qJufPdyO(R*tIHHtjP U+eYm>YKY%eSJ5VCDw$pSfAUjWod5s; diff --git a/vignettes/RMSSSplot.png b/vignettes/RMSSSplot.png deleted file mode 100644 index d43554801d0098524d90c49aab88081c84815caa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82409 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

        cww3(*RI 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 z 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 Y(sTfa{|&9fQpDdW9#kP`%Nt$(Uq_+VjsO4v diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index abcc3576..750d2828 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -242,7 +242,7 @@ Reliability = 0.015, Resolution = 0.127, Uncertainty = 0.248. -As expected, the selected-members ensemble presents a better Brier Score (lower value). The uncertainty is obviously the same for the two cases, since the observations to compare with are the same. As expected from the RMSSS results, the reliability is much better (lower) for the second case since the prediction probabilities are much closer to the NAO ocurrence distribution than for the all-members ensemble prediction (see right plot in the figure above). However, the resolution scores are not that different. This is due to the fact than although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence or not of the NAO event. The all-members ensemble instead, although with a higher RMSSS/reliability tends to predict better the occurrence of positive/negative NAO events (left plot). +As expected, the selected-members ensemble presents a better Brier Score (lower value). The uncertainty is obviously the same for the two cases, since the observations to compare with are the same. As expected from the RMSSS results, the reliability is much better (lower) for the second case since the prediction probabilities are much closer to the NAO ocurrence distribution than for the all-members ensemble prediction (see right plot in the figure above). However, the resolution scores are not that different. This is due to the fact that although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence or not of the NAO event. The all-members ensemble instead, although with a higher RMSSS/reliability tends to predict better the occurrence of positive/negative NAO events (left plot). ### 6-Appendix: Forecast scores ranges -- GitLab From 43e35340a97efbb41516538852db52e46f5b7ac7 Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 17:10:29 +0100 Subject: [PATCH 14/61] More edits 5 --- vignettes/ScoringForecast.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 750d2828..ddb7723e 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -151,9 +151,9 @@ legend(x = 4.95, y = 2.4, c('EUROSIP', 'EraInterim'), -The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. The general RMSSS for the whole ensemble is 0.015, what means a not very useful ensemble prediction. +The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. **The general RMSSS for the whole ensemble is 0.015**, what means a not very useful ensemble prediction. -However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 8, 23, 40 and 45 are used. Now most marked NAO events are correctly predicted giving a RMSSS of 0.66 for this selected-members ensemble. +However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 8, 23, 40 and 45 are used. Now most marked NAO events are correctly predicted giving a **RMSSS of 0.66 for this selected-members ensemble**. ### 5-Quantifying the skillfulness of the prediction. The Brier Score @@ -231,13 +231,13 @@ title('Predictions for selected-members ensemble') Following the analysis of the RMSSS, we compute the BS for the whole ensemble and for the ensemble with the selected members. For the whole ensemble, the results are: -Total BS = 0.213, +**Total BS = 0.213,** Reliability = 0.138, Resolution = 0.172, Uncertainty = 0.248. For the ensemble with the selected members, the results are: -Total BS = 0.136, +**Total BS = 0.136,** Reliability = 0.015, Resolution = 0.127, Uncertainty = 0.248. @@ -249,5 +249,5 @@ As expected, the selected-members ensemble presents a better Brier Score (lower | SCORE | RMSSS | BS (total) | Reliability | Resolution | Uncertainty | |:-----:|:-----:|:----------:|:-----------:|:----------:|:--------------:| -| Best | 0 | 0 | 0 | 1 | Obs. dependant | +| Best | 1 | 0 | 0 | 1 | Obs. dependant | | Worst | -Inf | 1 | 1 | 0 | Obs. dependant | -- GitLab From 44a79e45a6a783d08c7eaaef1ef0affa2208c414 Mon Sep 17 00:00:00 2001 From: jpena Date: Fri, 15 Mar 2019 10:24:40 +0100 Subject: [PATCH 15/61] More edits 6 --- vignettes/NAOpredictions.png | Bin 38181 -> 33781 bytes vignettes/ScoringForecast.md | 17 ++++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/vignettes/NAOpredictions.png b/vignettes/NAOpredictions.png index e4c18e715085fc16835ef74d86981bad752ee1da..ec96e8651f8ccf72933be25b53213ac1afa36d8f 100644 GIT binary patch literal 33781 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 diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index ddb7723e..ea82b44e 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -80,7 +80,7 @@ exp <- data$mod As a first step we will compare the predicted intensity of the NAO index for observations and for the forecast system. -In s2dverification the NAO index is computed using a common alternative definition; The NAO is defined as the first mode of variability for the sea level pressure in the North Atlantic region [20N-80N, 80W-40E]. The `NAO()` function requires as input anomalies that are previously computed using `Ano_CrossValid()` function. +In s2dverification the NAO index is computed using a common alternative definition; The NAO is defined as the first mode of variability (computed using Single Value Decomposition method) for the sea level pressure in the North Atlantic region [20N-80N, 80W-40E]. The `NAO()` function requires as input anomalies that are previously computed using `Ano_CrossValid()` function. ```r #Computing anomalies along sdates dimension @@ -105,7 +105,7 @@ legend(x = 3.8, y = 2.6, c('EUROSIP', 'EraInterim'), col = c(2, 4), pch = 15) -The figure above does not represent a good agreement between observations (blue line) and forecast (whisker boxes) due to the large dispersion through the 51 model members. The NAO signal is too noisy within the model ensemble thus almost disappearing (close to 0). +The figure above does not represent a good agreement between observations (blue line) and forecast (whisker boxes) due to the large dispersion through the 51 model members. The NAO signal is too weak due to the large dispersion among ensemble members thus almost disappearing (close to 0). ### 4-Quantifying the skillfulness of the prediction. The RMSSS @@ -153,14 +153,14 @@ legend(x = 4.95, y = 2.4, c('EUROSIP', 'EraInterim'), The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. **The general RMSSS for the whole ensemble is 0.015**, what means a not very useful ensemble prediction. -However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 8, 23, 40 and 45 are used. Now most marked NAO events are correctly predicted giving a **RMSSS of 0.66 for this selected-members ensemble**. +However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 8th, 23rd, 40th and 45th are used. Now most marked NAO events are correctly predicted giving a **RMSSS of 0.66 for this selected-members ensemble**. ### 5-Quantifying the skillfulness of the prediction. The Brier Score -Another option to quantify the goodness of this prediction is using the `BrierScore()` function. The BS measures the accuracy of a probabilistic categorical prediction. BS scores perfect prediction when BS equals 0 and worst score corresponds to 1 value. +Another option to quantify the goodness of this prediction is using the `BrierScore()` function. The BS measures the accuracy of a probabilistic categorical prediction calculating the mean squared difference between the predicted probability and the actual observation. BS scores perfect prediction when BS equals 0 (no difference between prediction and observation) and worst score corresponds to value of 1. -Moreover, the BS can be descomposed in 3 terms: reliability, resolution (negative contribution) and uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). +Moreover, the BS can be descomposed in 3 terms: BS = Reliability - Resolution + Uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). In the case of the NAO index, we can define a NAO event always that the index is greater than 0. Therefore, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored selected-members ensemble of previous section. @@ -211,7 +211,7 @@ lines(BS$pred - 0.5, type = 'h', lwd = 4, col = 'blue', yaxt = 'n') lines(BS$pred - 0.5, type = 'p', lwd = 3, col = 'blue', yaxt = 'n') axis(2, at = seq(-0.5, 0.5, 0.25), labels = seq(0, 1, 0.25), mgp = c(3,1,0)) lines(rep(0, Lmember), lwd=2, col = 'black') -title('Predictions for all members ensemble') +title('Predictions for all-members ensemble') #For selected-member ensemble only plot(BS_sel$obs - 0.5, type = 'p', lwd = 5, col = 'red', @@ -228,15 +228,14 @@ title('Predictions for selected-members ensemble') -Following the analysis of the RMSSS, we compute the BS for the whole ensemble and for the ensemble with the selected members. -For the whole ensemble, the results are: +For the all-members ensemble, the results are: **Total BS = 0.213,** Reliability = 0.138, Resolution = 0.172, Uncertainty = 0.248. -For the ensemble with the selected members, the results are: +For the selected-members ensemble, the results are: **Total BS = 0.136,** Reliability = 0.015, Resolution = 0.127, -- GitLab From 4f6a0218a9c0bdde00f91272d51efcf6c2d09f7d Mon Sep 17 00:00:00 2001 From: jpena Date: Fri, 15 Mar 2019 10:29:35 +0100 Subject: [PATCH 16/61] More edits 7 --- vignettes/ScoringForecast.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index ea82b44e..9a3ed3d1 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -241,7 +241,7 @@ Reliability = 0.015, Resolution = 0.127, Uncertainty = 0.248. -As expected, the selected-members ensemble presents a better Brier Score (lower value). The uncertainty is obviously the same for the two cases, since the observations to compare with are the same. As expected from the RMSSS results, the reliability is much better (lower) for the second case since the prediction probabilities are much closer to the NAO ocurrence distribution than for the all-members ensemble prediction (see right plot in the figure above). However, the resolution scores are not that different. This is due to the fact that although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence or not of the NAO event. The all-members ensemble instead, although with a higher RMSSS/reliability tends to predict better the occurrence of positive/negative NAO events (left plot). +As expected, the selected-members ensemble presents a better Brier Score (lower value). The uncertainty is obviously the same for the two cases, since the observations to compare with are the same. In agreement with the shown RMSSS results, the reliability is much better (lower) for the second case since the prediction probabilities are much closer to the NAO ocurrence distribution than for the all-members ensemble prediction (see right plot in the figure above). However, the resolution scores are not that different. This is due to the fact that although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence of the NAO event. The all-members ensemble instead, although with a higher RMSSS/reliability tends to predict better the occurrence of positive/negative NAO events (left plot). ### 6-Appendix: Forecast scores ranges -- GitLab From a11e2e289cac36c58fb6ddd425b83cdac9dfe715 Mon Sep 17 00:00:00 2001 From: jpena Date: Fri, 15 Mar 2019 10:56:46 +0100 Subject: [PATCH 17/61] More edits 8 --- vignettes/ScoringForecast.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 9a3ed3d1..28eb5959 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -151,7 +151,7 @@ legend(x = 4.95, y = 2.4, c('EUROSIP', 'EraInterim'), -The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. **The general RMSSS for the whole ensemble is 0.015**, what means a not very useful ensemble prediction. +The above figure shows very different RMSSS for different members (left plot). Most of them have RMSSS close to 0, thus the prediction error is close to the system variability. **The RMSSS for the whole ensemble is 0.091**, what means a not very useful ensemble prediction. However, we can select the members that present a better RMSSS, i.e. those closer to 1, and recompute the ensemble RMSSS. This is shown in the right plot where only members 8th, 23rd, 40th and 45th are used. Now most marked NAO events are correctly predicted giving a **RMSSS of 0.66 for this selected-members ensemble**. -- GitLab From cf879cf84a0eabb9450435f7e5265a294a3344a1 Mon Sep 17 00:00:00 2001 From: jpena Date: Fri, 15 Mar 2019 12:32:03 +0100 Subject: [PATCH 18/61] More edits 9 --- vignettes/ScoringForecast.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 28eb5959..c5a35062 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -135,7 +135,7 @@ plot(rmsss, type = 'h', lwd = 5, col = 'grey', xlab = 'Members', mgp = c(3,1,0), grid(col ='grey') lines(rep(0, Lmember), lwd = 1, col = 'black') -#Plotting boxplot for good members +#Plotting boxplot for selected members with higher rmsss isel = which(rmsss > 0.1) rmsss_m_sel = RMSSS(var_exp = array(apply(nao_exp_n[isel, ], MARGIN = 2, FUN = mean), dim = c(1,11)), var_obs = nao_obs_n, pval = F) @@ -162,7 +162,7 @@ Another option to quantify the goodness of this prediction is using the `BrierSc Moreover, the BS can be descomposed in 3 terms: BS = Reliability - Resolution + Uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). -In the case of the NAO index, we can define a NAO event always that the index is greater than 0. Therefore, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored selected-members ensemble of previous section. +In the case of the NAO index, we can discretize it in to a categorical variable defining a NAO event always that the index is greater than 0 and asociating the event with the value 1. Negative NAO index values then correspond to the non-ocurrance of a NAO event and thus they are assigned the value 0. For the forecast, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored selected-members ensemble of previous section. ```r @@ -241,7 +241,9 @@ Reliability = 0.015, Resolution = 0.127, Uncertainty = 0.248. -As expected, the selected-members ensemble presents a better Brier Score (lower value). The uncertainty is obviously the same for the two cases, since the observations to compare with are the same. In agreement with the shown RMSSS results, the reliability is much better (lower) for the second case since the prediction probabilities are much closer to the NAO ocurrence distribution than for the all-members ensemble prediction (see right plot in the figure above). However, the resolution scores are not that different. This is due to the fact that although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence of the NAO event. The all-members ensemble instead, although with a higher RMSSS/reliability tends to predict better the occurrence of positive/negative NAO events (left plot). +To put the total Brier Score values in to context, note that the BS definition is such that in general a forecast that always gives a 50% probability prediction for all cases would have a BS of 0.25. + +Taking this into account, the all-member ensemble prediction with a BS of 0.213 seems only a bit better than flipping a coin in terms of Brier Scoring. The selected-members ensemble instead presents a clear improvement in the total Brier Score (lower value). This is due to the better scoring (lower value) achieved by the reliability term, in agreement with the previous RMSSS results and also shown in the right plot of the figure above; The prediction probabilities are much closer to the NAO ocurrence distribution. However, the resolution scores are not that different between the all-members and the selected-members ensemble. This is due to the fact that although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence of the NAO event. The all-members ensemble instead, even with a higher RMSSS/reliability, tends to predict better the occurrence of positive/negative NAO events (left plot). Finally, the uncertainty is obviously the same for the two cases, since the observations to compare with are the same. ### 6-Appendix: Forecast scores ranges -- GitLab From f8379b7569a6e27d22511304115b3dfc80dc260a Mon Sep 17 00:00:00 2001 From: jpena Date: Fri, 15 Mar 2019 12:41:18 +0100 Subject: [PATCH 19/61] More edits 10 --- vignettes/ScoringForecast.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index c5a35062..069009ea 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -162,7 +162,7 @@ Another option to quantify the goodness of this prediction is using the `BrierSc Moreover, the BS can be descomposed in 3 terms: BS = Reliability - Resolution + Uncertainty. Reliability refers to how close the predicted probabilities are to the true probabilities (i.e. the lower the reliability, the lower the difference between prediction and observation and the better the score). Resolution relates with the difference between the predicted observation and the climatology (i.e. the higher the resolution, the greater the ability of the forecast to predict events different from the climatology). Uncertainty represents the inherent uncertainty of ocurring the event (i.e. the higher the uncertainty, the more difficult to correctly predict the event). -In the case of the NAO index, we can discretize it in to a categorical variable defining a NAO event always that the index is greater than 0 and asociating the event with the value 1. Negative NAO index values then correspond to the non-ocurrance of a NAO event and thus they are assigned the value 0. For the forecast, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored selected-members ensemble of previous section. +In the case of the NAO index, we can discretize it in to a categorical variable defining a NAO event always that the index is greater than 0 and asociating the event with the value 1. Negative NAO index values then correspond to the non-ocurrence of a NAO event and thus they are assigned the value 0. For the forecast, we can convert the NAO index prediction of all ensemble members in to a NAO prediction probability computing the proportion of members with a positive NAO prediction. For comparison we do the same for the good scored selected-members ensemble of previous section. ```r @@ -243,7 +243,7 @@ Uncertainty = 0.248. To put the total Brier Score values in to context, note that the BS definition is such that in general a forecast that always gives a 50% probability prediction for all cases would have a BS of 0.25. -Taking this into account, the all-member ensemble prediction with a BS of 0.213 seems only a bit better than flipping a coin in terms of Brier Scoring. The selected-members ensemble instead presents a clear improvement in the total Brier Score (lower value). This is due to the better scoring (lower value) achieved by the reliability term, in agreement with the previous RMSSS results and also shown in the right plot of the figure above; The prediction probabilities are much closer to the NAO ocurrence distribution. However, the resolution scores are not that different between the all-members and the selected-members ensemble. This is due to the fact that although the selected-members ensemble has a lower RMSSS/reliability, it does not always correctly predict the ocurrence of the NAO event. The all-members ensemble instead, even with a higher RMSSS/reliability, tends to predict better the occurrence of positive/negative NAO events (left plot). Finally, the uncertainty is obviously the same for the two cases, since the observations to compare with are the same. +Taking this into account, the all-members ensemble prediction with a BS of 0.213 seems only a bit better than flipping a coin in terms of Brier Scoring. The selected-members ensemble instead presents a clear improvement in the total Brier Score (lower value). This is due to the better scoring (lower value) achieved by the reliability term in this ensemble, in agreement with the previous RMSSS results and also shown in the right plot of the figure above; The prediction probabilities are much closer to the NAO ocurrence distribution. However, the resolution scores are not that different between the all-members and the selected-members ensemble. This is due to the fact that even with a notable difference in RMSSS and reliability, the two ensembles mostly predict equally the correct occurrence of positive/negative NAO events (left plot). Finally, the uncertainty is obviously the same for the two cases, since the observations to compare with are the same. ### 6-Appendix: Forecast scores ranges -- GitLab From 027a13bb1cde296f1c891d9d962f33b062e4e1e1 Mon Sep 17 00:00:00 2001 From: jpena Date: Tue, 26 Mar 2019 17:18:33 +0100 Subject: [PATCH 20/61] Minor edits 11 --- vignettes/ScoringForecast.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vignettes/ScoringForecast.md b/vignettes/ScoringForecast.md index 069009ea..2f3679f7 100644 --- a/vignettes/ScoringForecast.md +++ b/vignettes/ScoringForecast.md @@ -59,7 +59,7 @@ latNA <- c(20, 80) #Selected time periods: startDates <- paste(1981:1991, '1101', sep = '') -Loading sea level pressure maps for the whole North Atlantic and for the specific period +#Loading sea level pressure maps for the whole North Atlantic and for the specific period data <- Load(var = 'psl', exp = list(path_exp_EUROSIP), obs = list(path_obs_eraI), -- GitLab From 743ac6820f8efe0c64743738cd73492707aef41b Mon Sep 17 00:00:00 2001 From: nperez Date: Thu, 18 Apr 2019 15:43:26 +0200 Subject: [PATCH 21/61] Composite of 1 element return the same element. --- R/Composite.R | 77 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/R/Composite.R b/R/Composite.R index b5b54914..09aa360d 100644 --- a/R/Composite.R +++ b/R/Composite.R @@ -1,39 +1,54 @@ -Composite <- function(var, occ, lag=0, eno=FALSE, fileout=NULL) { - - if ( dim(var)[3]!=length(occ) ) { stop("temporal dimension of var is not equal to length of occ") } +Composite <- function(var, occ, lag = 0, eno = FALSE, fileout = NULL) { + if ( dim(var)[3] != length(occ) ) { + stop("temporal dimension of var is not equal to length of occ.") + } K <- max(occ) - composite <- array(dim = c(dim(var)[1:2], K)) - tvalue <- array(dim = dim(var)[1:2]) - dof <- array(dim = dim(var)[1:2]) - pvalue <- array(dim = c(dim(var)[1:2], K)) - - if ( eno==TRUE ) { n_tot <- Eno(var, posdim=3) } - else { n_tot <- length(occ) } - - mean_tot <- Mean1Dim(var, posdim=3, narm=TRUE) - stdv_tot <- apply(var, c(1,2), sd, na.rm=TRUE) - - for (k in 1:K) { - indices <- which(occ==k)+lag - - toberemoved=which(0>indices|indices>dim(var)[3]) - if ( length(toberemoved) > 0 ) { indices=indices[-toberemoved] } - - if ( eno==TRUE ) { n_k <- Eno(var[,,indices], posdim=3) } - else { n_k <- length(indices) } - - composite[,,k] <- Mean1Dim(var[,,indices], posdim=3, narm=TRUE) - stdv_k <- apply(var[,,indices], c(1,2), sd, na.rm=TRUE) + composite <- array(dim = c(dim(var)[1 : 2], K)) + tvalue <- array(dim = dim(var)[1 : 2]) + dof <- array(dim = dim(var)[1 : 2]) + pvalue <- array(dim = c(dim(var)[1 : 2], K)) + + if (eno == TRUE) { + n_tot <- Eno(var, posdim = 3) + } else { + n_tot <- length(occ) + } + mean_tot <- Mean1Dim(var, posdim = 3, narm = TRUE) + stdv_tot <- apply(var, c(1, 2), sd, na.rm = TRUE) + + for (k in 1 : K) { + + indices <- which(occ == k) + lag + toberemoved = which(0 > indices | indices > dim(var)[3]) + + if (length(toberemoved) > 0) { + indices=indices[-toberemoved] + } + if (eno == TRUE) { + n_k <- Eno(var[,, indices], posdim = 3) + } else { + n_k <- length(indices) + } + if (length(indices) == 1) { + composite[,, k] <- var[,, indices] + warning(paste("Composite", k, "has length 1 and pvalue is NA.")) + } else { + composite[,,k] <- Mean1Dim(var[,, indices], posdim = 3, narm = TRUE) + } + stdv_k <- apply(var[,, indices], c(1, 2), sd, na.rm = TRUE) - tvalue[,] <- (mean_tot - composite[,,k])/sqrt(stdv_tot^2/n_tot + stdv_k^2/n_k) - dof[,] <- (stdv_tot^2/n_tot + stdv_k^2/n_k)^2/((stdv_tot^2/n_tot)^2/(n_tot - 1) + (stdv_k^2/n_k)^2/(n_k - 1)) - pvalue[,,k] <- 2*pt(-abs(tvalue[,]), df=dof[,]) + tvalue <- (mean_tot - composite[,, k]) / + sqrt(stdv_tot ^ 2 / n_tot + stdv_k ^ 2 / n_k) + dof <- (stdv_tot ^ 2 / n_tot + stdv_k ^ 2 / n_k) ^ 2 / + ((stdv_tot ^ 2 / n_tot) ^ 2 / (n_tot - 1) + + (stdv_k ^ 2 / n_k) ^ 2 / (n_k - 1)) + pvalue[,, k] <- 2 * pt(-abs(tvalue), df = dof) } - if ( is.null(fileout)==FALSE ) { - output <- list(composite=composite, pvalue=pvalue) - save(output,file=paste(fileout,'.sav',sep='')) + if ( is.null(fileout) == FALSE ) { + output <- list(composite = composite, pvalue = pvalue) + save(output, file = paste(fileout, '.sav', sep = '')) } invisible(list(composite = composite, pvalue = pvalue)) -- GitLab From 8ea855733912dde79f9f912f95f4ca68651b732c Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 2 Jul 2019 11:20:15 +0200 Subject: [PATCH 22/61] Bugfix for issue #227. --- R/Ano.R | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/R/Ano.R b/R/Ano.R index 4b2b8767..9e5c38da 100644 --- a/R/Ano.R +++ b/R/Ano.R @@ -4,26 +4,56 @@ Ano <- function(var, clim) { # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # dimvar <- dim(var) - + if (length(dim(clim)) <= 2) { clim <- InsertDim(clim, 2, dimvar[2]) } + if ((length(dimvar) > length(dim(clim))) & (dim(clim)[2] != dimvar[2])) { clim <- InsertDim(clim, 2, dimvar[2]) } + if ((length(dimvar) > length(dim(clim))) & (dim(clim)[2] == dimvar[2])) { + if (is.null(names(dim(clim))) | is.null(names(dimvar))) { + stop('The dimensions have the same length. To clarify if they are the same variable, add dimension names to the arrays.') + } else { + if (names(dim(clim)[2]) != names(dimvar[2])) { + clim <- InsertDim(clim, 2, dimvar[2]) + } + } + } + if ((length(dimvar) > length(dim(clim))) & (dim(clim)[3] != dimvar[3])) { clim <- InsertDim(clim, 3, dimvar[3]) } + if ((length(dimvar) > length(dim(clim))) & (dim(clim)[3] == dimvar[3])) { + if (is.null(names(dim(clim))) | is.null(names(dimvar))) { + stop('The dimensions have the same length. To clarify if they are the same variable, add dimension names to the arrays.') + } else { + if (names(dim(clim)[3]) != names(dimvar[3])) { + clim <- InsertDim(clim, 3, dimvar[3]) + } + } + } + if ((length(dimvar) > length(dim(clim))) & (dim(clim)[4] != dimvar[4])) { clim <- InsertDim(clim, 4, dimvar[4]) } - + if ((length(dimvar) > length(dim(clim))) & (dim(clim)[4] == dimvar[4])) { + if (is.null(names(dim(clim))) | is.null(names(dimvar))) { + stop('The dimensions have the same length. To clarify if they are the same variable, add dimension names to the arrays.') + } else { + if (names(dim(clim)[4]) != names(dimvar[4])) { + clim <- InsertDim(clim, 4, dimvar[4]) + } + } + } + # # Raw anomalies # ~~~~~~~~~~~~~~~ # ano <- var - clim - + # # Outputs # ~~~~~~~~~ -- GitLab From a8dc27534b90664dde80ee6b2f00122d2b78b782 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 9 Jul 2019 17:14:02 +0200 Subject: [PATCH 23/61] Add unit test for Composite(); format adjustment for Composite(). --- DESCRIPTION | 6 ++++-- R/Composite.R | 26 ++++++++++++------------- tests/testthat.R | 4 ++++ tests/testthat/test-Composite.R | 34 +++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 tests/testthat.R create mode 100644 tests/testthat/test-Composite.R diff --git a/DESCRIPTION b/DESCRIPTION index f77ce597..6840cf5d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,7 +26,8 @@ Authors@R: c( person("Eleftheria", "Exarchou", , "eleftheria.exarchou@bsc.es", role = "ctb"), person("Ruben", "Cruz", , "ruben.cruzgarcia@bsc.es", role = "ctb"), person("Isabel", "Andreu-Burillo", , "isabel.andreu.burillo@ic3.cat", role = "ctb"), - person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb")) + person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb")), + person("An-Chi", "Ho", , "an.ho@bsc.es", role = "ctb")) Description: Set of tools to verify forecasts through the computation of typical prediction scores against one or more observational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the equations from a model, not a pure observational dataset). Intended for seasonal to decadal climate forecasts although can be useful to verify other kinds of forecasts. The package can be helpful in climate sciences for other purposes than forecasting. Depends: maps, @@ -44,7 +45,8 @@ Imports: plyr, SpecsVerification (>= 0.5.0) Suggests: - easyVerification + easyVerification, + testthat License: LGPL-3 URL: https://earth.bsc.es/gitlab/es/s2dverification/wikis/home BugReports: https://earth.bsc.es/gitlab/es/s2dverification/issues diff --git a/R/Composite.R b/R/Composite.R index 09aa360d..c8294fd2 100644 --- a/R/Composite.R +++ b/R/Composite.R @@ -4,10 +4,10 @@ Composite <- function(var, occ, lag = 0, eno = FALSE, fileout = NULL) { stop("temporal dimension of var is not equal to length of occ.") } K <- max(occ) - composite <- array(dim = c(dim(var)[1 : 2], K)) - tvalue <- array(dim = dim(var)[1 : 2]) - dof <- array(dim = dim(var)[1 : 2]) - pvalue <- array(dim = c(dim(var)[1 : 2], K)) + composite <- array(dim = c(dim(var)[1:2], K)) + tvalue <- array(dim = dim(var)[1:2]) + dof <- array(dim = dim(var)[1:2]) + pvalue <- array(dim = c(dim(var)[1:2], K)) if (eno == TRUE) { n_tot <- Eno(var, posdim = 3) @@ -20,33 +20,33 @@ Composite <- function(var, occ, lag = 0, eno = FALSE, fileout = NULL) { for (k in 1 : K) { indices <- which(occ == k) + lag - toberemoved = which(0 > indices | indices > dim(var)[3]) + toberemoved <- which(0 > indices | indices > dim(var)[3]) if (length(toberemoved) > 0) { - indices=indices[-toberemoved] + indices <- indices[-toberemoved] } if (eno == TRUE) { - n_k <- Eno(var[,, indices], posdim = 3) + n_k <- Eno(var[, , indices], posdim = 3) } else { n_k <- length(indices) } if (length(indices) == 1) { - composite[,, k] <- var[,, indices] + composite[, , k] <- var[, , indices] warning(paste("Composite", k, "has length 1 and pvalue is NA.")) } else { - composite[,,k] <- Mean1Dim(var[,, indices], posdim = 3, narm = TRUE) + composite[, , k] <- Mean1Dim(var[, , indices], posdim = 3, narm = TRUE) } - stdv_k <- apply(var[,, indices], c(1, 2), sd, na.rm = TRUE) + stdv_k <- apply(var[, , indices], c(1, 2), sd, na.rm = TRUE) - tvalue <- (mean_tot - composite[,, k]) / + tvalue <- (mean_tot - composite[, , k]) / sqrt(stdv_tot ^ 2 / n_tot + stdv_k ^ 2 / n_k) dof <- (stdv_tot ^ 2 / n_tot + stdv_k ^ 2 / n_k) ^ 2 / ((stdv_tot ^ 2 / n_tot) ^ 2 / (n_tot - 1) + (stdv_k ^ 2 / n_k) ^ 2 / (n_k - 1)) - pvalue[,, k] <- 2 * pt(-abs(tvalue), df = dof) + pvalue[, , k] <- 2 * pt(-abs(tvalue), df = dof) } - if ( is.null(fileout) == FALSE ) { + if (is.null(fileout) == FALSE) { output <- list(composite = composite, pvalue = pvalue) save(output, file = paste(fileout, '.sav', sep = '')) } diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 00000000..19e87e1d --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(s2dverification) + +test_check("s2dverification") diff --git a/tests/testthat/test-Composite.R b/tests/testthat/test-Composite.R new file mode 100644 index 00000000..42c003a0 --- /dev/null +++ b/tests/testthat/test-Composite.R @@ -0,0 +1,34 @@ +context("Generic tests") +test_that("Sanity checks", { + + expect_error( + Composite(var = array(1:20, dim = c(2, 5, 2)), c(1, 1, 0)), + "temporal dimension of var is not equal to length of occ.") + + expect_warning( + Composite(var = array(1:40, dim = c(2, 5, 4)), c(1, 2, 2, 2)), + "Composite 1 has length 1 and pvalue is NA.") + + var <- array(rep(c(1, 3, 2, 1, 2), 8), dim = c(x = 2, y = 4, time = 5)) + occ <- c(1, 2, 2, 2, 1) + output <- c(x = 2, y = 4, 2) #dim(asd$composite) + expect_equal( + dim(Composite(var, occ)$composite), + output + ) + output <- c(1.5, 2.0, 2.5, 2.0) + expect_equal( + Composite(var, occ)$composite[1, , 1], + output + ) + + var <- array(rep(c(1, 3, 2, 1, 2), 8), dim = c(x = 2, y = 4, time = 5)) + occ <- c(1, 2, 2, 3, 3) + output <- array(as.numeric(rep(NA, 8)), dim = c(2, 4)) + expect_equal( + Composite(var, occ)$pvalue[, , 1], + output + ) + +}) + -- GitLab From 1f84fa28897912b9e847c981a43cd9d64c9f8ce8 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 9 Jul 2019 17:45:11 +0200 Subject: [PATCH 24/61] syntax error fixed. --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6840cf5d..99c08ff6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -26,7 +26,7 @@ Authors@R: c( person("Eleftheria", "Exarchou", , "eleftheria.exarchou@bsc.es", role = "ctb"), person("Ruben", "Cruz", , "ruben.cruzgarcia@bsc.es", role = "ctb"), person("Isabel", "Andreu-Burillo", , "isabel.andreu.burillo@ic3.cat", role = "ctb"), - person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb")), + person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb"), person("An-Chi", "Ho", , "an.ho@bsc.es", role = "ctb")) Description: Set of tools to verify forecasts through the computation of typical prediction scores against one or more observational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the equations from a model, not a pure observational dataset). Intended for seasonal to decadal climate forecasts although can be useful to verify other kinds of forecasts. The package can be helpful in climate sciences for other purposes than forecasting. Depends: -- GitLab From 0347191acd483646e5f66515a77b4c9237e1b32b Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 9 Jul 2019 17:53:54 +0200 Subject: [PATCH 25/61] add .gitlab-ci.yml --- .gitlab-ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..b1cf9976 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,10 @@ +stages: + - build +build: + stage: build + script: + - module load R +# - module load CDO + - R CMD build --resave-data . + - R CMD check --as-cran --no-manual --run-donttest s2dverification_*.tar.gz + - R -e 'covr::package_coverage()' -- GitLab From dc6688cfec12c546136efdaca2bafa0b42e7eda1 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 19 Jul 2019 18:19:20 +0200 Subject: [PATCH 26/61] Add unit tests --- tests/testthat/test-Ano.R | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 tests/testthat/test-Ano.R diff --git a/tests/testthat/test-Ano.R b/tests/testthat/test-Ano.R new file mode 100644 index 00000000..4d483e01 --- /dev/null +++ b/tests/testthat/test-Ano.R @@ -0,0 +1,28 @@ +context("Generic tests") +test_that("Sanity checks", { + + var <- array(rnorm(16), c(2, 2, 2, 2)) + names(dim(var)) <- c("memb", "lon", "sdates", "lat") + clim <- apply(var, c(1, 2, 4), mean) + names(dim(clim)) <- NULL + expect_error( + Ano(var, clim), + "Provide dimension names on parameter \'var\' and \'clim\' to avoid ambiguity." + ) + + t <- array(rnorm(76), c(1, 3, 4, 3, 2, 2)) + names(dim(t)) <- c("mod", "memb", "sdates", "ltime", "lon", "lat") + c3 <- Clim(t, t, memb = TRUE)$clim_exp # Clim for each member + c1 <- InsertDim(c3[, 1, ,, ], 1, 1) # clim as if memb=FALSE but identical to member 1 + names(dim(c1)) <- c("mod", "ltime", "lon", "lat") + identical(c1[, , , ], c3[, 1, , , ]) # results in TRUE + a3 <- Ano(t, c3) # ano for each member individually + a1 <- Ano(t, c1) # ano for first member + identical(a1[, 1, , , , ], a3[, 1, , , , ]) + + expect_equal( + which(a1[, 1, , , , ], + a3[, 1, , , , ]) + ) + +}) -- GitLab From 4245975d673ddfcee1e2bc8da5cf64b72f140c44 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 19 Jul 2019 18:20:13 +0200 Subject: [PATCH 27/61] Revise stop messages. --- R/Ano.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/Ano.R b/R/Ano.R index 9e5c38da..ed3350a2 100644 --- a/R/Ano.R +++ b/R/Ano.R @@ -14,7 +14,7 @@ Ano <- function(var, clim) { } if ((length(dimvar) > length(dim(clim))) & (dim(clim)[2] == dimvar[2])) { if (is.null(names(dim(clim))) | is.null(names(dimvar))) { - stop('The dimensions have the same length. To clarify if they are the same variable, add dimension names to the arrays.') + stop('Provide dimension names on parameter \'var\' and \'clim\' to avoid ambiguity.') } else { if (names(dim(clim)[2]) != names(dimvar[2])) { clim <- InsertDim(clim, 2, dimvar[2]) @@ -27,7 +27,7 @@ Ano <- function(var, clim) { } if ((length(dimvar) > length(dim(clim))) & (dim(clim)[3] == dimvar[3])) { if (is.null(names(dim(clim))) | is.null(names(dimvar))) { - stop('The dimensions have the same length. To clarify if they are the same variable, add dimension names to the arrays.') + stop('Provide dimension names on parameter \'var\' and \'clim\' to avoid ambiguity.') } else { if (names(dim(clim)[3]) != names(dimvar[3])) { clim <- InsertDim(clim, 3, dimvar[3]) @@ -40,7 +40,7 @@ Ano <- function(var, clim) { } if ((length(dimvar) > length(dim(clim))) & (dim(clim)[4] == dimvar[4])) { if (is.null(names(dim(clim))) | is.null(names(dimvar))) { - stop('The dimensions have the same length. To clarify if they are the same variable, add dimension names to the arrays.') + stop('Provide dimension names on parameter \'var\' and \'clim\' to avoid ambiguity.') } else { if (names(dim(clim)[4]) != names(dimvar[4])) { clim <- InsertDim(clim, 4, dimvar[4]) -- GitLab From 6d18d9dcce196006954effa7a30dd1792686b8b6 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 19 Jul 2019 18:36:51 +0200 Subject: [PATCH 28/61] Bug fix. --- tests/testthat/test-Ano.R | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-Ano.R b/tests/testthat/test-Ano.R index 4d483e01..aa3d2796 100644 --- a/tests/testthat/test-Ano.R +++ b/tests/testthat/test-Ano.R @@ -18,11 +18,10 @@ test_that("Sanity checks", { identical(c1[, , , ], c3[, 1, , , ]) # results in TRUE a3 <- Ano(t, c3) # ano for each member individually a1 <- Ano(t, c1) # ano for first member - identical(a1[, 1, , , , ], a3[, 1, , , , ]) expect_equal( - which(a1[, 1, , , , ], - a3[, 1, , , , ]) + a1[, 1, , , , ], + a3[, 1, , , , ] ) }) -- GitLab From 524d8ba192d2793821af4a7e3ae22765f134eed0 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 22 Jul 2019 15:53:57 +0200 Subject: [PATCH 29/61] Change into Roxygen2 format. --- R/ACC.R | 52 +++++++++ R/Alpha.R | 14 +++ R/AnimateMap.R | 89 ++++++++++++++++ R/Ano.R | 23 ++++ R/Ano_CrossValid.R | 21 ++++ R/ArrayToNetCDF.R | 188 +++++++++++++++++++++++++++++++++ R/BrierScore.R | 63 +++++++++++ R/CDORemap.R | 156 +++++++++++++++++++++++++++ R/Clim.R | 41 +++++++ R/Cluster.R | 69 ++++++++++++ R/ColorBar.R | 55 ++++++++++ R/Composite.R | 60 +++++++++++ R/ConfigApplyMatchingEntries.R | 40 +++++++ R/ConfigEditDefinition.R | 33 ++++++ R/ConfigEditEntry.R | 51 +++++++++ R/ConfigFileOpen.R | 41 +++++++ R/ConfigShowSimilarEntries.R | 42 ++++++++ R/ConfigShowTable.R | 33 ++++++ R/Season.R | 27 +++++ 19 files changed, 1098 insertions(+) diff --git a/R/ACC.R b/R/ACC.R index 8c1210dc..3179ba7e 100644 --- a/R/ACC.R +++ b/R/ACC.R @@ -1,3 +1,55 @@ +#'Computes Anomaly Correlation Coefficient +#' +#'Calculates the Anomaly Correlation Coefficient for the ensemble mean of each model and the corresponding references for each startdate and each leadtime. The domain of interest can be specified by providing the list of longitudes/latitudes (lon/lat) of the grid together with the corners of the domain lonlatbox = c(lonmin, lonmax, latmin, latmax) +#' +#'@param var_exp Array of experimental anomalies with dimensions: c(nexp, nsdates, nltimes, nlat, nlon) or c(nexp, nsdates, nmembers, nltimes, nlat, nlon). +#'@param var_obs Array of observational anomalies, same dimensions as var_exp except along the first dimension and the second if it corresponds to the member dimension. +#'@param lon Array of longitudes of the var_exp/var_obs grids, optional. +#'@param lat Array of latitudes of the var_exp/var_obs grids, optional. +#'@param lonlatbox Domain to select : c(lonmin, lonmax, latmin, latmax), optional. +#'@param conf TRUE/FALSE: confidence intervals and significance level provided or not. +#'@param conftype "parametric" provides a confidence interval for the ACC computed by a Fisher transformation and a significance level for the ACC from a one-sided student-T distribution. "bootstrap" provides a confidence interval for the ACC and MACC computed from bootstrapping on the members with 100 drawings with replacement. To guarantee the statistical robustness of the result, make sure that your experiments/oservations/startdates/leadtimes always have the same number of members. +#'@param siglev The confidence level for the computed confidence intervals. +#'@return A list of length 2: +#'\itemize{ +#' \item\code{$ACC} {If \code{conf = TRUE}, array with dimensions: c(nexp, nobs, nsdates, nleadtimes, 4) The fifth dimension of length 4 corresponds to the lower limit of the \code{siglev}\% confidence interval, the ACC, the upper limit of the \code{siglev}\% confidence interval and the \code{siglev}\% significance level. If \code{conf = FALSE}, the array of the Anomaly Correlation Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes).} +#' \item\code{$MACC} {The array of the Mean Anomaly Correlation Coefficient with dimensions c(nexp, nobs, nleadtimes).}} +#' +#'@examples +#'# See ?Load for explanations on the first part of this example. +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) +#'sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'acc <- ACC(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) +#'PlotACC(acc$ACC, startDates) +#'@export ACC <- function(var_exp, var_obs, lon = NULL, lat = NULL, lonlatbox = NULL, conf = TRUE, conftype = "parametric", siglev = 0.95) { diff --git a/R/Alpha.R b/R/Alpha.R index c5b68f6f..e071fc82 100644 --- a/R/Alpha.R +++ b/R/Alpha.R @@ -1,3 +1,17 @@ +#'Estimates AutoCorrelation At Lag 1 following Guemas et al, BAMS, 2013b +#' +#'This function, relying on the \code{FitAcfCoef()} function, estimates the autocorrelation at lag 1 of the xdata array following the method described in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear detrending and/or a filtering of any frequency peak if requested, the sample autocorrelation is estimated.\cr Then the theoretical autocorrelation of an AR1 is fitted to the sample autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 process. +#'@param xdata Timeseries from which the autocorrelation at lag 1 is requested. +#'@param detrend TRUE applies a linear detrending to xdata prior to the estimation of the autocorrelation at lag 1. +#'@param filter TRUE applies a filtering of any frequency peak prior to the estimation of the autocorrelation at lag 1. +#'@return Autocorrelation at lag 1. +#' +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'alpha <- Alpha(sampleData$mod[1, 1, , 1]) +#'print(alpha) +#'@export Alpha <- function(xdata, detrend = FALSE, filter = FALSE) { tmp <- xdata diff --git a/R/AnimateMap.R b/R/AnimateMap.R index 86ca0bff..1652c668 100644 --- a/R/AnimateMap.R +++ b/R/AnimateMap.R @@ -1,3 +1,92 @@ +#'Animate Maps of Forecast/Observed Values or Scores Over Forecast Time +#' +#'Create animations of maps in an equi-rectangular or stereographic projection, showing the anomalies, the climatologies, the mean InterQuartile Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, the trends, the RMSE, the correlation or the RMSSS, between modelled and observed data along the forecast time (lead-time) for all input experiments and input observational datasets. +#' +#'@param var Matrix of dimensions (nltime, nlat, nlon) or (nexp/nmod, nltime, nlat, nlon) or (nexp/nmod, 3/4, nltime, nlat, nlon) or (nexp/nmod, nobs, 3/4, nltime, nlat, nlon) +#'@param lon Vector containing longtitudes (degrees) +#'@param lat Vector containing latitudes (degrees) +#'@param toptitle c('','', \dots) array of main title for each animation, optional. If RMS, RMSSS, correlations: first exp with successive obs, then second exp with successive obs, etc ... +#'@param sizetit Multiplicative factor to increase title size, optional +#'@param units Units, optional +#'@param monini Starting month between 1 and 12. Default = 1 +#'@param freq 1 = yearly, 12 = monthly, 4 = seasonal ... +#'@param msk95lev TRUE/FALSE grid points with dots if 95\% significance level reached. Default = FALSE +#'@param brks Limits of colour levels, optional. For example: seq(min(var), max(var), (max(var) - min(var)) / 10) +#'@param cols Vector of colours of length(brks) - 1, optional. +#'@param filled.continents Continents filled in grey (TRUE) or represented by a black line (FALSE). Default = TRUE. Filling unavailable if crossing Greenwich and equi = TRUE. Filling unavailable if square = FALSE and equi = TRUE. +#'@param lonmin Westward limit of the domain to plot (> 0 or < 0). Default : 0 degrees +#'@param lonmax Eastward limit of the domain to plot (> 0 or < 0). lonmax > lonmin. Default : 360 degrees +#'@param latmin Southward limit of the domain to plot. Default : -90 degrees +#'@param latmax Northward limit of the domain to plot. Default : 90 degrees +#'@param intlat Interval between latitude ticks on y-axis for equi = TRUE or between latitude circles for equi = FALSE. Default = 30 degrees. +#'@param intlon Interval between longitude ticks on x-axis. Default = 20 degrees. +#'@param drawleg Draw a colorbar. Can be FALSE only if square = FALSE or equi = FALSE. Default = TRUE +#'@param subsampleg Supsampling factor of the interval between ticks on colorbar. Default = 1 = every colour level. +#'@param colNA Color used to represent NA. Default = 'white' +#'@param equi TRUE/FALSE == cylindrical equidistant/stereographic projection. Default: TRUE +#'@param fileout c('', '', \dots) array of output file name for each animation. If RMS, RMSSS, correlations : first exp with successive obs, then second exp with successive obs, etc ... +#'@param ... Arguments to be passed to the method. Only accepts the following graphical parameters: adj ann ask bty cex cex.axis cex.lab cex.main cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. For more information about the parameters see `par`. +#'@return animations of maps +#' +#'@examples +#'# See ?Load for explanations on the first part of this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' output = 'lonlat', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'clim <- Clim(sampleData$mod, sampleData$obs, memb = FALSE) +#' \dontrun{ +#'AnimateMap(clim$clim_exp, sampleData$lon, sampleData$lat, +#' toptitle = "climatology of decadal prediction", sizetit = 1, +#' units = "degree", brks = seq(270, 300, 3), monini = 11, freq = 12, +#' msk95lev = FALSE, filled.continents = TRUE, intlon = 10, intlat = 10, +#' fileout = 'clim_dec.gif') +#' } +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'leadtimes_dimension <- 4 +#'initial_month <- 11 +#'mean_start_month <- 1 +#'mean_stop_month <- 12 +#'season_means_mod <- Season(ano_exp, leadtimes_dimension, initial_month, +#' mean_start_month, mean_stop_month) +#'season_means_obs <- Season(ano_obs, leadtimes_dimension, initial_month, +#' mean_start_month, mean_stop_month) +#' \dontrun{ +#'AnimateMap(Mean1Dim(season_means_mod, 2)[1, 1, , , ], sampleData$lon, +#' sampleData$lat, toptitle = "Annual anomalies 1985 of decadal prediction", +#' sizetit = 1, units = "degree", monini = 1, freq = 1, msk95lev = FALSE, +#' brks = seq(-0.5, 0.5, 0.1), intlon = 10, intlat = 10, +#' filled.continents = TRUE, fileout = 'annual_means_dec.gif') +#' } +#'dim_to_mean <- 2 # Mean along members +#'rms <- RMS(Mean1Dim(season_means_mod, dim_to_mean), +#' Mean1Dim(season_means_obs, dim_to_mean)) +#'AnimateMap(rms, sampleData$lon, sampleData$lat, toptitle = +#' "RMSE decadal prediction", sizetit = 1, units = "degree", +#' monini = 1, freq = 1, msk95lev = FALSE, brks = seq(0, 0.8, 0.08), +#' intlon = 10, intlat = 10, filled.continents = TRUE, +#' fileout = 'rmse_dec.gif') +#'@export AnimateMap <- function(var, lon, lat, toptitle = rep("", 11), sizetit = 1, units = "", monini = 1, freq = 12, msk95lev = FALSE, brks = NULL, cols = NULL, filled.continents = FALSE, diff --git a/R/Ano.R b/R/Ano.R index ed3350a2..ec4a2627 100644 --- a/R/Ano.R +++ b/R/Ano.R @@ -1,3 +1,26 @@ +#'Computes Forecast or Observed Anomalies +#' +#'This function computes anomalies from any experimental or observational matrix output from \code{Load()} and their climatologies output from \code{Clim()}. +#' +#'@param var Model or observational data: c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#'@param clim Climatologies from clim: c(nmod/nexp/nobs, nltime) up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or c(nmod/nexp/nobs, nmemb/nparam, nltime) up to c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) depending on the options provided to \code{Clim()} +#' +#'@return Array with same dimensions as 'var'. +#' +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_nb_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) +#'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, +#' toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), +#' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') +#'@export Ano <- function(var, clim) { # # Duplicate clim dimensions to heve same dimensions as var diff --git a/R/Ano_CrossValid.R b/R/Ano_CrossValid.R index a0727d14..e4375ca4 100644 --- a/R/Ano_CrossValid.R +++ b/R/Ano_CrossValid.R @@ -1,3 +1,24 @@ +#'Computes Anomalies In Cross-Validation Mode +#' +#'Computes the anomalies from the arrays of the experimental and observational data output from \code{load()} by subtracting the climatologies computed with a cross-validation technique and a per-pair method. +#' +#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) +#'@param memb memb: TRUE/FALSE (1 climatology for each member/1 climatology averaging all the members). Default = TRUE. +#' +#'@return A list of length 2: +#'\itemize{ +#' \item\code{$ano_exp} {Matrix with same dimensions as var_exp} +#' \item\code{$ano_obs}{Matrix with same dimensions as var_obs}} +#' +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'anomalies <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#'PlotAno(anomalies$ano_exp, anomalies$ano_obs, startDates, +#' toptitle = paste('anomalies'), ytitle = c('K', 'K', 'K'), +#' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano_crossvalid.eps') +#'@export Ano_CrossValid <- function(var_exp, var_obs, memb = TRUE) { # # Enlarge the number of dimensions of var_exp and var_obs to 7 if necessary diff --git a/R/ArrayToNetCDF.R b/R/ArrayToNetCDF.R index 47fe13ef..4331f480 100644 --- a/R/ArrayToNetCDF.R +++ b/R/ArrayToNetCDF.R @@ -1,3 +1,191 @@ +#'Save multidimensional R arrays into NetCDF files +#' +#'This function takes as input one or a list of multidimensional R arrays and stores them in a NetCDF file, using the \code{ncdf4} package. The full path and name of the resulting file must be specified. Metadata can be attached to the arrays and propagated into the NetCDF file in 3 possible ways: +#'\itemize{ +#' \item{Via the list names if a list of arrays is provided: Each name in the input list, corresponding to one multidimensional array, will be interpreted as the name of the variable it contains. +#'E.g: +#'\code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), +#' file_path = 'example.nc')}} +#' \item{Via the dimension names of each provided array: The dimension names of each of the provided arrays will be interpreted as names for the dimensions of the NetCDF files. Read further for special dimension names that will trigger special behaviours, such as 'time' and 'var'. +#'E.g: +#'\code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) +#' names(dim(temperature)) <- c('longitude', 'latitude', 'time') +#' ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')}} +#' \item{Via the attribute 'variables' of each provided array: The arrays can be provided with metadata in an attribute named 'variables', which is expected to be a named list of named lists, where the names of the container list are the names of the variables present in the provided array, and where each sub-list contains metadata for each of the variables. The attribute names and values supported in the sub-lists must follow the same format the package \code{ncdf4} uses to represent the NetCDF file headers. +#'E.g: +#'\code{a <- array(1:400, dim = c(5, 10, 4, 2)) +#' metadata <- list(tos = list(addOffset = 100, +#' scaleFact = 10, +#' dim = list(list(name = 'time', +#' unlim = FALSE)))) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc')}} +#'The special dimension names are 'var'/'variable' and 'time'.If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will interpret each array entry along such dimension corresponds to a separate new variable, hence will create a new variable inside the NetCDF file and will use it to store all the data in the provided array for the corresponding entry along the 'var'/'variable' dimension. +#'If a dimension is named 'time', by default it will be interpreted and built as an unlimited dimension. The 'time' dimension must be the last dimension of the array (the right-most). If a 'var'/'variable' dimension is present, the 'time' dimension can be also placed on its left (i.e. the one before the last dimension). The default behaviour of creating the 'time' as unlimited dimension can be disabled by setting manually the attribute \code{unlim = FALSE}, as shown in the previous example. +#' +#'@param arrays One or a list of multidimensional data arrays. The list can be provided with names, which will be interpreted as variable names. The arrays can be provided with dimension names. The arrays can be provided with metadata in the attribute 'variables' (read section Description for details). +#'@param file_path Path and name of the NetCDF file to be created. +#' +#'@return This function returns NULL. +#' +#'@examples +#' \dontrun{ +#'# Minimal use case +#'ArrayToNetCDF(array(1:9, c(3, 3)), 'tmp.nc') +#' +#'# Works with arrays of any number of dimensions +#'ArrayToNetCDF(array(1:27, c(3, 3, 3)), 'tmp.nc') +#' +#'# Arrays can also be provided in [named] lists +#'ArrayToNetCDF(list(tos = array(1:27, c(3, 3, 3))), 'tmp.nc') +#' +#'# Or with dimension names +#'# 'var' dimension name will generate multiple variables in the +#'# resulting NetCDF file +#'a <- array(1:27, dim = c(3, 3, 3)) +#'names(dim(a)) <- c('lon', 'lat', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# 'variable' as dimension name will do the same +#'a <- array(1:27, dim = c(3, 3, 3)) +#'names(dim(a)) <- c('lon', 'lat', 'variable') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# The 'time' dimension will be built as unlimited dimension, by default +#'a <- array(1:1600, dim = c(10, 20, 4, 2)) +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# Putting the 'time' dimension in a position which is not the last, or the one +#'# right before 'var'/'variable' will crash. Unlimited dimension must be in the +#'# last position +#'a <- array(1:1600, dim = c(10, 20, 4, 2)) +#'names(dim(a)) <- c('time', 'lat', 'lon', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#'a <- array(1:1600, dim = c(10, 20, 4, 2)) +#'names(dim(a)) <- c('lat', 'time', 'lon', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# The dimension 'var'/'variable' can be in any position and can have any length +#'a <- array(1:1600, dim = c(10, 20, 4, 2)) +#'names(dim(a)) <- c('lat', 'var', 'lon', 'time') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# Multiple arrays can be provided in a list +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(list(a, a), 'tmp.nc') +#' +#'# If no dimension names are given to an array, new names will be automatically +#'# generated +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'b <- array(1:400, dim = c(5, 11, 4, 2)) +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(list(a, b), 'tmp.nc') +#' +#'# If two arrays use a same dimension but their lengths differ, the function +#'# will crash +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'b <- array(1:400, dim = c(5, 11, 4, 2)) +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'names(dim(b)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(list(a, b), 'tmp.nc') +#' +#'# Metadata can be provided for each variable in each array, via the +#'# attribute 'variables'. In this example the metadata is empty. +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'metadata <- list( +#' tos = list(), +#' tas = list() +#' ) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# Variable names can be manually specified +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'metadata <- list( +#' tos = list(name = 'name1'), +#' tas = list(name = 'name2') +#' ) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# Units can be specified +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'metadata <- list( +#' tos = list(units = 'K'), +#' tas = list(units = 'K') +#' ) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# addOffset and scaleFactor can be specified +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'metadata <- list( +#' tos = list(addOffset = 100, +#' scaleFact = 10), +#' tas = list(addOffset = 100, +#' scaleFact = 10) +#' ) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# Unlimited dimensions can be manually created +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'metadata <- list( +#' tos = list(addOffset = 100, +#' scaleFact = 10, +#' dim = list(list(name = 'unlimited', +#' unlim = TRUE))), +#' tas = list(addOffset = 100, +#' scaleFact = 10, +#' dim = list(list(name = 'unlimited', +#' unlim = TRUE))) +#' ) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'unlimited', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# A 'time' dimension can be built without it necessarily being unlimited +#'a <- array(1:400, dim = c(5, 10, 4, 2)) +#'metadata <- list( +#' tos = list(addOffset = 100, +#' scaleFact = 10, +#' dim = list(list(name = 'time', +#' unlim = FALSE))), +#' tas = list(addOffset = 100, +#' scaleFact = 10, +#' dim = list(list(name = 'time', +#' unlim = FALSE))) +#' ) +#'attr(a, 'variables') <- metadata +#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#'ArrayToNetCDF(a, 'tmp.nc') +#' +#'# Multiple arrays with data for multiple variables can be saved into a +#'# NetCDF file at once. +#'tos <- array(1:400, dim = c(5, 10, 4)) +#'metadata <- list(tos = list(units = 'K')) +#'attr(tos, 'variables') <- metadata +#'names(dim(tos)) <- c('lat', 'lon', 'time') +#'lon <- seq(0, 360 - 360 / 10, length.out = 10) +#'dim(lon) <- length(lon) +#'metadata <- list(lon = list(units = 'degrees_east')) +#'attr(lon, 'variables') <- metadata +#'names(dim(lon)) <- 'lon' +#'lat <- seq(-90, 90, length.out = 5) +#'dim(lat) <- length(lat) +#'metadata <- list(lat = list(units = 'degrees_north')) +#'attr(lat, 'variables') <- metadata +#'names(dim(lat)) <- 'lat' +#'ArrayToNetCDF(list(tos, lon, lat), 'tmp.nc') +#'} +#'@export ArrayToNetCDF <- function(arrays, file_path) { # Check parameter arrays. if (is.array(arrays)) { diff --git a/R/BrierScore.R b/R/BrierScore.R index e1b01bcf..7995bed8 100644 --- a/R/BrierScore.R +++ b/R/BrierScore.R @@ -1,3 +1,66 @@ +#'Compute Brier Score And Its Decomposition And Brier Skill Score +#' +#'Computes the Brier score (BS) and the components of its standard decomposition as well with the two within-bin components described in Stephenson et al., (2008). It also returns the bias-corrected decomposition of the BS (Ferro and Fricker, 2012). BSS having the climatology as the reference forecast. BrierScore provides the same functionality, but taking a matrix of ensemble members (exp) as input. +#' +#'@param obs Vector of binary observations (1 or 0) +#'@param pred Vector of probablistic predictions with values in the range [0,1] +#'@param thresholds Values used to bin the forecasts. By default the bins are {[0,0.1), [0.1, 0.2), ... [0.9, 1]} +#'@param exp Matrix of predictions with values in the range [0,1] for the .BrierScore function +#' +#'@return Both BrierScore and .Brier score provide the same outputs: +#'\itemize{ +#' \item{$rel}{standard reliability} +#' \item{$res}{standard resolution} +#' \item{$unc}{standard uncertainty} +#' \item{$bs}{Brier score} +#' \item{$bs_check_res}{rel-res+unc} +#' \item{$bss_res}{res-rel/unc} +#' \item{$gres}{generalized resolution} +#' \item{$bs_check_gres}{rel-gres+unc} +#' \item{$bss_gres}{gres-rel/unc} +#' \item{$rel_bias_corrected}{bias-corrected rel} +#' \item{$gres_bias_corrected}{bias-corrected gres} +#' \item{$unc_bias_corrected}{bias-corrected unc} +#' \item{$bss_bias_corrected}{gres_bias_corrected-rel_bias_corrected/unc_bias_corrected} +#' \item{$nk}{number of forecast in each bin} +#' \item{$fkbar}{average probability of each bin} +#' \item{$okbar}{relative frequency that the observed event occurred} +#' \item{$bins}{bins used} +#' \item{$pred}{values with which the forecasts are verified} +#' \item{$obs}{probability forecasts of the event}} +#' +#'@examples +#'# Minimalist examples with BrierScore +#'a <- runif(10) +#'b <- round(a) +#'x <- BrierScore(b, a) +#'x$bs - x$bs_check_res +#'x$bs - x$bs_check_gres +#'x$rel_bias_corrected - x$gres_bias_corrected + x$unc_bias_corrected +#' \dontrun{ +#'a <- runif(10) +#'b <- cbind(round(a),round(a)) # matrix containing 2 identical ensemble members... +#'x2 <- BrierScore(a, b) +#' } +#' +#'# Example of BrierScore using UltimateBrier +#'# See ?UltimateBrier for more information +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'bs <- UltimateBrier(ano_exp, ano_obs, thr = c(1/3, 2/3)) +#' +#' \dontrun{ +#'# Example of .BrierScore with veriApply +#'require(easyVerification) +#'BrierScore2 <- s2dverification:::.BrierScore +#'bins_ano_exp <- ProbBins(ano_exp, thr = c(1/3, 2/3), posdates = 3, posdim = 2) +#'bins_ano_obs <- ProbBins(ano_obs, thr = c(1/3, 2/3), posdates = 3, posdim = 2) +#'bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_obs, 3), +#' tdim = 2, ensdim = 3) +#' } +#'@export BrierScore <- function(obs, pred, thresholds = seq(0, 1, 0.1)) { if (max(pred) > 1 | min(pred) < 0) { stop("Predictions outside [0,1] range. Are you certain this is a probability forecast? \n") diff --git a/R/CDORemap.R b/R/CDORemap.R index 88c2cd42..58686b02 100644 --- a/R/CDORemap.R +++ b/R/CDORemap.R @@ -1,3 +1,159 @@ +#'Interpolates arrays with longitude and latitude dimensions using CDO +#' +#'This function takes as inputs a multidimensional array (optional), a vector or matrix of longitudes, a vector or matrix of latitudes, a destination grid specification, and the name of a method to be used to interpolate (one of those available in the 'remap' utility in CDO). The interpolated array is returned (if provided) together with the new longitudes and latitudes. \code{CDORemap()} permutes by default the dimensions of the input array (if needed), splits it in chunks (CDO can work with data arrays of up to 4 dimensions), generates a file with the data of each chunk, interpolates it with CDO, reads it back into R and merges it into a result array. If no input array is provided, the longitude and latitude vectors will be transformed only. If the array is already on the desired destination grid, no transformation is performed (this behvaiour works only for lonlat and gaussian grids). Any metadata attached to the input data array, longitudes or latitudes will be preserved or accordingly modified. +#' +#'@param data_array Multidimensional numeric array to be interpolated. If provided, it must have at least a longitude and a latitude dimensions, identified by the array dimension names. The names for these dimensions must be one of the recognized by s2dverification (can be checked with \code{s2dverification:::.KnownLonNames()} and \code{s2dverification:::.KnownLatNames()}). +#'@param lons Numeric vector or array of longitudes of the centers of the grid cells. Its size must match the size of the longitude/latitude dimensions of the input array. +#'@param lats Numeric vector or array of latitudes of the centers of the grid cells. Its size must match the size of the longitude/latitude dimensions of the input array. +#'@param grid Character string specifying either a name of a target grid (recognized by CDO; e.g.: 'r256x128', 't106grid') or a path to another NetCDF file which to read the target grid from (a single grid must be defined in such file). +#'@param method Character string specifying an interpolation method (recognized by CDO; e.g.: 'con', 'bil', 'bic', 'dis'). The following long names are also supported: 'conservative', 'bilinear', 'bicubic' and 'distance-weighted'. +#'@param avoid_writes The step of permutation is needed when the input array has more than 3 dimensions and none of the longitude or latitude dimensions in the right-most position (CDO would not accept it without permuting previously). This step, executed by default when needed, can be avoided for the price of writing more intermediate files (whis usually is unconvenient) by setting the parameter \code{avoid_writes = TRUE}. +#'@param crop Whether to crop the data after interpolation with 'cdo sellonlatbox' (TRUE) or to extend interpolated data to the whole world as CDO does by default (FALSE). If \code{crop = TRUE} then the longitude and latitude borders which to crop at are taken as the limits of the cells at the borders ('lons' and 'lats' are perceived as cell centers), i.e. the resulting array will contain data that covers the same area as the input array. This is equivalent to specifying \code{crop = 'preserve'}, i.e. preserving area. If \code{crop = 'tight'} then the borders which to crop at are taken as the minimum and maximum cell centers in 'lons' and 'lats', i.e. the area covered by the resulting array may be smaller if interpolating from a coarse grid to a fine grid. The parameter 'crop' also accepts a numeric vector of custom borders which to crop at: c(western border, eastern border, southern border, northern border). +#'@param force_remap Whether to force remapping, even if the input data array is already on the target grid. +#'@param write_dir Path to the directory where to create the intermediate files for CDO to work. By default, the R session temporary directory is used (\code{tempdir()}). +#' +#'@return A list with the following components: +#'\itemize{ +#' \item\code{$data_array} {The interpolated data array (if an input array is provided at all, NULL otherwise).} +#' \item\code{$lons} {The longitudes of the data on the destination grid.} +#' \item\code{$lats} {The latitudes of the data on the destination grid.} +#' +#'@examples +#' \dontrun{ +#'# Interpolating only vectors of longitudes and latitudes +#'lon <- seq(0, 360 - 360/50, length.out = 50) +#'lat <- seq(-90, 90, length.out = 25) +#'tas2 <- CDORemap(NULL, lon, lat, 't170grid', 'bil', TRUE) +#' +#'# Minimal array interpolation +#'tas <- array(1:50, dim = c(25, 50)) +#'names(dim(tas)) <- c('lat', 'lon') +#'lon <- seq(0, 360 - 360/50, length.out = 50) +#'lat <- seq(-90, 90, length.out = 25) +#'tas2 <- CDORemap(tas, lon, lat, 't170grid', 'bil', TRUE) +#' +#'# Metadata can be attached to the inputs. It will be preserved and +#'# accordignly modified. +#'tas <- array(1:50, dim = c(25, 50)) +#'names(dim(tas)) <- c('lat', 'lon') +#'lon <- seq(0, 360 - 360/50, length.out = 50) +#'metadata <- list(lon = list(units = 'degrees_east')) +#'attr(lon, 'variables') <- metadata +#'lat <- seq(-90, 90, length.out = 25) +#'metadata <- list(lat = list(units = 'degrees_north')) +#'attr(lat, 'variables') <- metadata +#'metadata <- list(tas = list(dim = list(lat = list(len = 25, +#' vals = lat), +#' lon = list(len = 50, +#' vals = lon) +#' ))) +#'attr(tas, 'variables') <- metadata +#'tas2 <- CDORemap(tas, lon, lat, 't170grid', 'bil', TRUE) +#' +#'# Arrays of any number of dimensions in any order can be provided. +#'num_lats <- 25 +#'num_lons <- 50 +#'tas <- array(1:(10*num_lats*10*num_lons*10), +#' dim = c(10, num_lats, 10, num_lons, 10)) +#'names(dim(tas)) <- c('a', 'lat', 'b', 'lon', 'c') +#'lon <- seq(0, 360 - 360/num_lons, length.out = num_lons) +#'metadata <- list(lon = list(units = 'degrees_east')) +#'attr(lon, 'variables') <- metadata +#'lat <- seq(-90, 90, length.out = num_lats) +#'metadata <- list(lat = list(units = 'degrees_north')) +#'attr(lat, 'variables') <- metadata +#'metadata <- list(tas = list(dim = list(a = list(), +#' lat = list(len = num_lats, +#' vals = lat), +#' b = list(), +#' lon = list(len = num_lons, +#' vals = lon), +#' c = list() +#' ))) +#'attr(tas, 'variables') <- metadata +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', TRUE) +#'# The step of permutation can be avoided but more intermediate file writes +#'# will be performed. +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', FALSE) +#' +#'# If the provided array has the longitude or latitude dimension in the +#'# right-most position, the same number of file writes will be performed, +#'# even if avoid_wrties = FALSE. +#'num_lats <- 25 +#'num_lons <- 50 +#'tas <- array(1:(10*num_lats*10*num_lons*10), +#' dim = c(10, num_lats, 10, num_lons)) +#'names(dim(tas)) <- c('a', 'lat', 'b', 'lon') +#'lon <- seq(0, 360 - 360/num_lons, length.out = num_lons) +#'metadata <- list(lon = list(units = 'degrees_east')) +#'attr(lon, 'variables') <- metadata +#'lat <- seq(-90, 90, length.out = num_lats) +#'metadata <- list(lat = list(units = 'degrees_north')) +#'attr(lat, 'variables') <- metadata +#'metadata <- list(tas = list(dim = list(a = list(), +#' lat = list(len = num_lats, +#' vals = lat), +#' b = list(), +#' lon = list(len = num_lons, +#' vals = lon) +#' ))) +#'attr(tas, 'variables') <- metadata +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', TRUE) +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', FALSE) +#' +#'# An example of an interpolation from and onto a rectangular regular grid +#'num_lats <- 25 +#'num_lons <- 50 +#'tas <- array(1:(1*num_lats*num_lons), dim = c(num_lats, num_lons)) +#'names(dim(tas)) <- c('y', 'x') +#'lon <- array(seq(0, 360 - 360/num_lons, length.out = num_lons), +#' dim = c(num_lons, num_lats)) +#'metadata <- list(lon = list(units = 'degrees_east')) +#'names(dim(lon)) <- c('x', 'y') +#'attr(lon, 'variables') <- metadata +#'lat <- t(array(seq(-90, 90, length.out = num_lats), +#' dim = c(num_lats, num_lons))) +#'metadata <- list(lat = list(units = 'degrees_north')) +#'names(dim(lat)) <- c('x', 'y') +#'attr(lat, 'variables') <- metadata +#'tas2 <- CDORemap(tas, lon, lat, 'r100x50', 'bil') +#' +#'# An example of an interpolation from an irregular grid onto a gaussian grid +#'num_lats <- 25 +#'num_lons <- 50 +#'tas <- array(1:(10*num_lats*10*num_lons*10), +#' dim = c(10, num_lats, 10, num_lons)) +#'names(dim(tas)) <- c('a', 'j', 'b', 'i') +#'lon <- array(seq(0, 360 - 360/num_lons, length.out = num_lons), +#' dim = c(num_lons, num_lats)) +#'metadata <- list(lon = list(units = 'degrees_east')) +#'names(dim(lon)) <- c('i', 'j') +#'attr(lon, 'variables') <- metadata +#'lat <- t(array(seq(-90, 90, length.out = num_lats), +#' dim = c(num_lats, num_lons))) +#'metadata <- list(lat = list(units = 'degrees_north')) +#'names(dim(lat)) <- c('i', 'j') +#'attr(lat, 'variables') <- metadata +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil') +#' +#'# Again, the dimensions can be in any order +#'num_lats <- 25 +#'num_lons <- 50 +#'tas <- array(1:(10*num_lats*10*num_lons), +#' dim = c(10, num_lats, 10, num_lons)) +#'names(dim(tas)) <- c('a', 'j', 'b', 'i') +#'lon <- array(seq(0, 360 - 360/num_lons, length.out = num_lons), +#' dim = c(num_lons, num_lats)) +#'names(dim(lon)) <- c('i', 'j') +#'lat <- t(array(seq(-90, 90, length.out = num_lats), +#' dim = c(num_lats, num_lons))) +#'names(dim(lat)) <- c('i', 'j') +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil') +#'tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', FALSE) +#'# It is ossible to specify an external NetCDF file as target grid reference +#'tas2 <- CDORemap(tas, lon, lat, 'external_file.nc', 'bil') +#'} +#'@export CDORemap <- function(data_array = NULL, lons, lats, grid, method, avoid_writes = TRUE, crop = TRUE, force_remap = FALSE, write_dir = tempdir()) { #, mask = NULL) { diff --git a/R/Clim.R b/R/Clim.R index 4fdfa038..81b05cef 100644 --- a/R/Clim.R +++ b/R/Clim.R @@ -1,3 +1,44 @@ +#'Computes Bias Corrected Climatologies +#' +#'This function computes only per-pair climatologies from the experimental and observational matrices output from \code{Load()}. +#'To compute plain climatologies from only experimental or observational data from \code{Load()}, the following code can be used: +#' \code{ +#'clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), +#' dim = dim(obs_datta)[-c(2, 3)]) +#' } +#'The function \code{Clim()} computes per-pair climatologies using one of the following methods: +#' \itemize{ +#' \item{ +#'1) per-pair method (Garcia-Serrano and Doblas-Reyes, CD, 2012) +#' } +#' \item{ +#'2) Kharin method (Karin et al, GRL, 2012) +#' } +#' \item{ +#'3) Fuckar method (Fuckar et al, GRL, 2014) +#' } +#' } +#'\code{Clim()} computes climatologies using the startdates covered by the whole experiments/observational data sets. The startdates not available for all the data (model and obs) are excluded when computing the climatologies. +#' +#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) +#'@param memb TRUE/FALSE (1 climatology for each member). Default = TRUE. +#'@param kharin TRUE/FALSE (if Kharin method is applied or not). Default = FALSE. +#'@param NDV TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE. +#' +#'@return A list of length 2: +#'\itemize{ +#' \item{clim_exp}{Array with same dimensions as var_exp except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} +#' \item{clim_obs}{Array with same dimensions as var_obs except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'PlotClim(clim$clim_exp, clim$clim_obs, +#' toptitle = paste('sea surface temperature climatologies'), +#' ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') +#'@export Clim <- function(var_exp, var_obs, memb = TRUE, kharin = FALSE, NDV = FALSE) { # # Enlarge the number of dimensions of var_exp and var_obs to 7 if necessary diff --git a/R/Cluster.R b/R/Cluster.R index b72b5e49..0f7472c3 100644 --- a/R/Cluster.R +++ b/R/Cluster.R @@ -1,3 +1,72 @@ +#'K-means Clustering. +#' +#'This function computes cluster centers and their time series of occurrences, with the K-means clustering method using Euclidean distance, of an array of input data with any number of dimensions, one of them (the 'posdates'th) corresponding to time. By default the first dimension is expected to correspond to time. Specifically, it partitions the array along time axis in K groups or clusters in which each space vector/array belongs to (i.e., is a member of) the cluster with the nearest center or centroid. This function relies on the NbClust package (Charrad et al., 2014 JSS). +#' +#'@param var An array with any number of dimensions, one of them (the 'posdates'th) corresponding to time with either area-averages over a series of domains or the grid points for any sptial grid structure (x), (y), (z), (x,y), (x,y,z), (y,z), ... +#'@param weights A vector/array of multiplicative weights based on the areas covering each domain/region or grid-cell of var; the dimensions of weights vector must be equal to the dimensions of 'var' without the 'posdates'th dimension. +#'@param nclusters This is positive integer K that must be bigger than 1. K is the number of clusters to be computed, or K initial cluster centers to be used in the method. Default is NULL and then user has to specify which index from NbClust and the associated criteria for selecting the optimal number of clusters will be used for K-means clustering of var. +#'@param index A validity index from NbClust package that can be used to determine optimal K if K is not specified as positive integer bigger than 1 or initial/seed cluster centers in nclusters. 'sdindex' is deafult (Halkidi et al. 2001, JIIS). Other indices also available in NBClust are "kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw", "tracew", "friedman", "rubin", "cindex", "db", "silhouette", "duda", "pseudot2", "beale", "ratkowsky", "ball", "ptbiserial", "gap", "frey", "mcclain", "gamma", "gplus", "tau", "dunn", "hubert", "sdindex", and "sdbw". One can also use all of them with the option 'alllong' or almost all indices except gap, gamma, gplus and tau with 'all', when the optimal number of clusters K is detremined by the majority rule (the maximum of histogram of the results of all indices with finite solutions). Use of some indices on a big and/or unstructured dataset can be computationally intense and/or could lead to numerical singularity. +#'@param posdates The index of the dimension that corresponds to time in the provided array in the parameter 'var', the first by default. +#' +#'@return +#' \item{cluster}{ +#'A vector (time series) of integers indicating the occurrence of a cluster, i.e., when +#'certain data member in time is allocated to a specific cluster (e.g., 2 1 3 1 1 1 ..). +#' } +#' \item{centers}{ +#'A matrix of cluster centres or centroids (e.g. [1:K, 1:spatial degrees of freedom]). +#' } +#' \item{totss}{ +#'The total sum of squares. +#' } +#' \item{withinss}{ +#'A vector of within-cluster sum of squares, one component per cluster. +#' } +#' \item{tot.withinss}{ +#'Total within-cluster sum of squares, i.e., sum(withinss). +#' } +#' \item{betweenss}{ +#'The between-cluster sum of squares, i.e. totss-tot.withinss. +#' } +#' \item{size}{ +#'The number of points in each cluster. +#' } +#' +#'@examples +#'# Generating synthetic data +#'a1 <- array(dim = c(200, 4)) +#'mean1 <- 0 +#'sd1 <- 0.3 +#' +#'c0 <- seq(1, 200) +#'c1 <- sort(sample(x = 1:200, size = sample(x = 50:150, size = 1), replace = FALSE)) +#'x1 <- c(1, 1, 1, 1) +#'for (i1 in c1) { +#' a1[i1, ] <- x1 + rnorm(4, mean = mean1, sd = sd1) +#'} +#' +#'c1p5 <- c0[!(c0 \%in\% c1)] +#'c2 <- c1p5[seq(1, length(c1p5), 2)] +#'x2 <- c(2, 2, 4, 4) +#'for (i2 in c2) { +#' a1[i2, ] <- x2 + rnorm(4, mean = mean1, sd = sd1) +#'} +#' +#'c3 <- c1p5[seq(2, length(c1p5), 2)] +#'x3 <- c(3, 3, 1, 1) +#'for (i3 in c3) { +#' a1[i3, ] <- x3 + rnorm(4, mean = mean1, sd = sd1) +#'} +#' +#'# Computing the clusters +#'res1 <- Cluster(var = a1, weights = array(1, dim = dim(a1)[2]), nclusters = 3) +#'print(res1$cluster) +#'print(res1$centers) +#' +#'res2 <- Cluster(var = a1, weights = array(1, dim = dim(a1)[2])) +#'print(res2$cluster) +#'print(res2$centers) +#'@export Cluster <- function(var, weights, nclusters = NULL, index = 'sdindex', posdates = 1) { # Check var diff --git a/R/ColorBar.R b/R/ColorBar.R index d47c3103..1f64ac8d 100644 --- a/R/ColorBar.R +++ b/R/ColorBar.R @@ -1,3 +1,58 @@ +#'Draws a Color Bar +#' +#'Generates a color bar to use as colouring function for map plots and optionally draws it (horizontally or vertically) to be added to map multipanels or plots. It is possible to draw triangles at the ends of the colour bar to represent values that go beyond the range of interest. A number of options is provided to adjust the colours and the position and size of the components. The drawn colour bar spans a whole figure region and is compatible with figure layouts.\cr\cr The generated colour bar consists of a set of breaks that define the length(brks) - 1 intervals to classify each of the values in each of the grid cells of a two-dimensional field. The corresponding grid cell of a given value of the field will be coloured in function of the interval it belongs to.\cr\cr The only mandatory parameters are 'var_limits' or 'brks' (in its second format, see below). +#' +#'@param brks 'brks' can be provided in two formats: +#'a) A single value with the number of breaks to be generated automatically, between the minimum and maximum specified in 'var_limits' (both inclusive). Hence the parameter 'var_limits' is mandatory if 'brks' is provided with this format. If 'bar_limits' is additionally provided, values only between 'bar_limits' will be generated. The higher the value of 'brks', the smoother the plot will look. +#'b) A vector with the actual values of the desired breaks. Values will be reordered by force to ascending order. If provided in this format, no other parameters are required to generate/plot the colour bar. +#'This parameter is optional if 'var_limits' is specified. If 'brks' not specified but 'cols' is specified, it will take as value length(cols) + 1. If 'cols' is not specified either, 'brks' will take 21 as value.\cr\cr +#' +#'@param cols Vector of length(brks) - 1 valid colour identifiers, for each interval defined by the breaks. This parameter is optional and will be filled in with a vector of length(brks) - 1 colours generated with the function provided in 'color_fun' (\code{clim.colors} by default). +#''cols' can have one additional colour at the beginning and/or at the end with the aim to colour field values beyond the range of interest represented in the colour bar. If any of these extra colours is provided, parameter 'triangle_ends' becomes mandatory in order to disambiguate which of the ends the colours have been provided for. +#'@param vertical TRUE/FALSE for vertical/horizontal colour bar (disregarded if plot = FALSE). +#'@param subsampleg The first of each subsampleg breaks will be ticked on the colorbar. Takes by default an approximation of a value that yields a readable tick arrangement (extreme breaks always ticked). If set to 0 or lower, no labels are drawn. See the code of the function for details or use 'extra_labels' for customized tick arrangements. +#'@param bar_limits Vector of two numeric values with the extremes of the range of values represented in the colour bar. If 'var_limits' go beyond this interval, the drawing of triangle extremes is triggered at the corresponding sides, painted in 'col_inf' and 'col_sup'. Either of them can be set as NA and will then take as value the corresponding extreme in 'var_limits' (hence a triangle end won't be triggered for these sides). Takes as default the extremes of 'brks' if available, else the same values as 'var_limits'. +#'@param var_limits Vector of two numeric values with the minimum and maximum values of the field to represent. These are used to know whether to draw triangle ends at the extremes of the colour bar and what colour to fill them in with. If not specified, take the same value as the extremes of 'brks'. Hence the parameter 'brks' is mandatory if 'var_limits' is not specified. +#'@param triangle_ends Vector of two logical elements, indicating whether to force the drawing of triangle ends at each of the extremes of the colour bar. This choice is automatically made from the provided 'brks', 'bar_limits', 'var_limits', 'col_inf' and 'col_sup', but the behaviour can be manually forced to draw or not to draw the triangle ends with this parameter. If 'cols' is provided, 'col_inf' and 'col_sup' will take priority over 'triangle_ends' when deciding whether to draw the triangle ends or not. +#'@param col_inf Colour to fill the inferior triangle end with. Useful if specifying colours manually with parameter 'cols', to specify the colour and to trigger the drawing of the lower extreme triangle, or if 'cols' is not specified, to replace the colour automatically generated by ColorBar(). +#'@param col_sup Colour to fill the superior triangle end with. Useful if specifying colours manually with parameter 'cols', to specify the colour and to trigger the drawing of the upper extreme triangle, or if 'cols' is not specified, to replace the colour automatically generated by ColorBar(). +#'@param color_fun Function to generate the colours of the color bar. Must take an integer and must return as many colours. The returned colour vector can have the attribute 'na_color', with a colour to draw NA values. This parameter is set by default to clim.palette(). +#'@param plot Logical value indicating whether to only compute its breaks and colours (FALSE) or to also draw it on the current device (TRUE). +#'@param draw_ticks Whether to draw ticks for the labels along the colour bar (TRUE) or not (FALSE). TRUE by default. Disregarded if 'plot = FALSE'. +#'@param draw_separators Whether to draw black lines in the borders of each of the colour rectancles of the colour bar (TRUE) or not (FALSE). FALSE by default. Disregarded if 'plot = FALSE'. +#'@param triangle_ends_scale Scale factor for the drawn triangle ends of the colour bar, if drawn at all. Takes 1 by default (rectangle triangle proportional to the thickness of the colour bar). Disregarded if 'plot = FALSE'. +#'@param extra_labels Numeric vector of extra labels to draw along axis of the colour bar. The number of provided decimals will be conserved. Disregarded if 'plot = FALSE'. +#'@param title Title to draw on top of the colour bar, most commonly with the units of the represented field in the neighbour figures. Empty by default. +#'@param title_scale Scale factor for the 'title' of the colour bar. Takes 1 by default. +#'@param label_scale Scale factor for the labels of the colour bar. Takes 1 by default. +#'@param tick_scale Scale factor for the length of the ticks of the labels along the colour bar. Takes 1 by default. +#'@param extra_margin Extra margins to be added around the colour bar, in the format c(y1, x1, y2, x2). The units are margin lines. Takes rep(0, 4) by default. +#'@param label_digits Number of significant digits to be displayed in the labels of the colour bar, usually to avoid too many decimal digits overflowing the figure region. This does not have effect over the labels provided in 'extra_labels'. Takes 4 by default. +#'@param ... Arguments to be passed to the method. Only accepts the following graphical parameters: +#'adj ann ask bg bty cex.lab cex.main cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog +#'For more information about the parameters see `par` +#' +#'@return +#'\itemize{ +#' \item{brks}{ +#'Breaks used for splitting the range in intervals. +#' } +#' \item{cols}{ +#'Colours generated for each of the length(brks) - 1 intervals. Always of length length(brks) - 1. +#' } +#' \item{col_inf}{ +#'Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). +#' } +#' \item{col_sup}{ +#'Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). +#' } +#' +#'@examples +#'cols <- c("dodgerblue4", "dodgerblue1", "forestgreen", "yellowgreen", "white", +#' "white", "yellow", "orange", "red", "saddlebrown") +#'lims <- seq(-1, 1, 0.2) +#'ColorBar(lims, cols) +#'@export ColorBar <- function(brks = NULL, cols = NULL, vertical = TRUE, subsampleg = NULL, bar_limits = NULL, var_limits = NULL, triangle_ends = NULL, col_inf = NULL, col_sup = NULL, diff --git a/R/Composite.R b/R/Composite.R index c8294fd2..619fd800 100644 --- a/R/Composite.R +++ b/R/Composite.R @@ -1,3 +1,63 @@ +#'Computes composites. +#' +#'Composites a 3-d field var(x,y,time) according to the indices of mode/cluster occurrences in time and computes the pvalues (t-test). x and y are typically lon and lat, but function can accept other 2-d fields such as lat and depth, lon and depth, etc. +#' +#'@param var 3-dimensional array (x, y, time) containing the variable to composite. +#'@param occ 1-dimensional array for the occurrence time series of mode(s)/cluster(s) +#'(*1) when one wants to composite all modes, e.g., all K=3 clusters then +#'for example occurrences could look like: 1 1 2 3 2 3 1 3 3 2 3 2 2 3 2, +#'(*2) otherwise for compositing only the 2nd mode or cluster of the above +#'example occurrences should look like 0 0 1 0 1 0 0 0 0 1 0 1 1 0 1. +#'@param lag Lag time step (an integer), e.g., for lag=2 composite will use +2 occurrences (i.e., shifted 2 time steps forward). Deafult is lag=0. +#'@param eno For using the effective sample size (TRUE) or the total sample size (FALSE that is the default) for the number of degrees of freedom. +#'@param fileout Name of the .sav output file (NULL is the default). +#' +#'@return +#'\itemize{ +#' \item{$composite}{ +#' 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) +#' or only k=1 for any specific cluster, i.e., case (*2). +#' } +#' \item{$pvalue}{ +#' 3-d array (x, y, k) containing the pvalue of the +#' composites obtained through a t-test that accounts for the serial +#' dependence of the data with the same structure as Composite. +#' } +#'@examples +#'blank <- array(0, dim=c(20, 10, 30)) +#' +#'x1 <- blank +#'t1 <- blank +#'f1 <- blank +#' +#'for (i in 1:20) { +#' x1[i,,] <- i +#'} +#' +#'for (i in 1:30) { +#' t1[,,i] <- i +#'} +#' +#'# This is 2D propagating sin wave example, where we use (x,y,t) structure of +#'# f1 wave field. Compositing (like using stroboscopicc light) at different time +#'# steps can lead to modification or cancelation of wave pattern. +#' +#'for (i in 1:20) { +#' for (j in 1:30) { +#' f1[i,,j] <- 3*sin(2*pi*x1[i,,j]/5. - 2*pi*t1[i,,j]/6.) +#' } +#'} +#' +#'occ1 <- rep(0, 30) +#'occ1[c(2, 5, 8, 11, 14, 17, 20, 23)] <- 1 +#' +#'filled.contour(Composite(var=f1, occ=occ1)$composite[,,1]) +#' +#'occ2 <- rep(0, 30) +#'occ2[c(3, 9, 15, 21)] <- 1 +#' +#'filled.contour(Composite(var=f1, occ=occ2)$composite[,,1]) +#'@export Composite <- function(var, occ, lag = 0, eno = FALSE, fileout = NULL) { if ( dim(var)[3] != length(occ) ) { diff --git a/R/ConfigApplyMatchingEntries.R b/R/ConfigApplyMatchingEntries.R index 4f2c0109..fee390b0 100644 --- a/R/ConfigApplyMatchingEntries.R +++ b/R/ConfigApplyMatchingEntries.R @@ -1,3 +1,43 @@ +#'Apply Matching Entries To Dataset Name And Variable Name To Find Related Info +#' +#'Given a pair of dataset name and variable name, this function determines applies all the matching entries found in the corresponding configuration table to work out the dataset main path, file path, actual name of variable inside NetCDF files, ... +#' +#'@param configuration Configuration object obtained from ConfigFileOpen() or ConfigFileCreate(). +#'@param var Name of the variable to load. Will be interpreted as a string, regular expressions do not apply here. +#'Examples: 'tas' or 'tasmax_q90'. +#'@param exp Set of experimental dataset identifiers. Will be interpreted as a strings, regular expressions do not apply here. +#'Can be NULL (not to check in experimental dataset tables), and takes by default NULL. +#'Examples: c('EnsEcmwfSeas', 'EnsUkmoSeas'), c('i00k'). +#'@param obs Set of observational dataset identifiers. Will be interpreted as a strings, regular expressions do not apply here. +#'Can be NULL (not to check in observational dataset tables), and takes by default NULL. +#'Examples: c('GLORYS', 'ERAint'), c('NCEP'). +#'@param show_entries Flag to stipulate whether to show the found matching entries for all datasets and variable name. +#'@param show_result Flag to stipulate whether to show the result of applying all the matching entries (dataset main path, file path, ...). +#' +#'@return A list with the information resulting of applying the matching entries is returned. +#' +#'@examples +#'# Create an empty configuration file +#'config_file <- paste0(tempdir(), "/example.conf") +#'ConfigFileCreate(config_file, confirm = FALSE) +#'# Open it into a configuration object +#'configuration <- ConfigFileOpen(config_file) +#'# Add an entry at the bottom of 4th level of file-per-startdate experiments +#'# table which will associate the experiment "ExampleExperiment2" and variable +#'# "ExampleVariable" to some information about its location. +#'configuration <- ConfigAddEntry(configuration, "experiments", +#' "last", "ExampleExperiment2", "ExampleVariable", +#' "/path/to/ExampleExperiment2/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Edit entry to generalize for any variable. Changing variable needs . +#'configuration <- ConfigEditEntry(configuration, "experiments", 1, +#' var_name = ".*", +#' file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") +#'# Now apply matching entries for variable and experiment name and show the +#'# result +#'match_info <- ConfigApplyMatchingEntries(configuration, 'tas', +#' exp = c('ExampleExperiment2'), show_result = TRUE) +#'@export ConfigApplyMatchingEntries <- function(configuration, var, exp = NULL, obs = NULL, show_entries = FALSE, show_result = TRUE) { ## Function to tell if a regexpr() match is a complete match to a specified name isFullMatch <- function(x, name) { diff --git a/R/ConfigEditDefinition.R b/R/ConfigEditDefinition.R index eefb5662..5351b32a 100644 --- a/R/ConfigEditDefinition.R +++ b/R/ConfigEditDefinition.R @@ -1,3 +1,36 @@ +#'Add Modify Or Remove Variable Definitions In Configuration +#' +#'These functions help in adding, modifying or removing variable definitions in a configuration object obtained wit ConfigFileOpen() or ConfigFileCreate().\cr ConfigEditDefinition() will add the definition if not existing. +#' +#'@param configuration Configuration object obtained wit ConfigFileOpen() or ConfigFileCreate(). +#'@param name Name of the variable to add/modify/remove. +#'@param value Value to associate to the variable. +#'@param confirm Flag to stipulate whether to ask for confirmation if the variable is being modified. Takes by default TRUE. +#' +#'@return A modified configuration object is returned. +#' +#'@examples +#'# Create an empty configuration file +#'config_file <- paste0(tempdir(), "/example.conf") +#'ConfigFileCreate(config_file, confirm = FALSE) +#'# Open it into a configuration object +#'configuration <- ConfigFileOpen(config_file) +#'# Add an entry at the bottom of 4th level of file-per-startdate experiments +#'# table which will associate the experiment "ExampleExperiment2" and variable +#'# "ExampleVariable" to some information about its location. +#'configuration <- ConfigAddEntry(configuration, "experiments", +#' "last", "ExampleExperiment2", "ExampleVariable", +#' "/path/to/ExampleExperiment2/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Edit entry to generalize for any variable. Changing variable needs . +#'configuration <- ConfigEditEntry(configuration, "experiments", 1, +#' var_name = ".*", +#' file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") +#'# Now apply matching entries for variable and experiment name and show the +#'# result +#'match_info <- ConfigApplyMatchingEntries(configuration, 'tas', +#' exp = c('ExampleExperiment2'), show_result = TRUE) +#'@export ConfigEditDefinition <- function(configuration, name, value, confirm = TRUE) { continue <- TRUE if (name %in% names(configuration$definitions)) { diff --git a/R/ConfigEditEntry.R b/R/ConfigEditEntry.R index 40fe55d2..e3946bb7 100644 --- a/R/ConfigEditEntry.R +++ b/R/ConfigEditEntry.R @@ -1,3 +1,54 @@ +#'Add, Remove Or Edit Entries In The Configuration +#' +#'ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions to manage entries in a configuration object created with ConfigFileOpen(). +#'Before adding an entry, make sure the defaults don't do already what you want (ConfigShowDefinitions(), ConfigShowTable()). +#'Before adding an entry, make sure it doesn't override and spoil what other entries do (ConfigShowTable(), ConfigFileOpen()). +#'Before adding an entry, make sure there aren't other entries that already do what you want (ConfigShowSimilarEntries()). +#' +#'@param configuration Configuration object obtained via ConfigFileOpen() or ConfigFileCreate() that will be modified accordingly. +#'@param dataset_type Whether to modify a table of experimental datasets or a table of observational datasets. Can take values 'experiments' or 'observations' respectively. +#'@param position 'position' tells the index in the table of the entry to edit or remove. Use ConfigShowTable() to see the index of the entry. +#'In ConfigAddEntry() it can also take the value "last" (default), that will put the entry at the end of the corresponding level, or "first" at the beginning. See ?ConfigFileOpen for more information. +#'If 'dataset_name' and 'var_name' are specified this argument is ignored in ConfigRemoveEntry(). +#'@param dataset_name, var_name, main_path, file_path, nc_var_name, suffix, varmin, varmax +#'These parameters tell the dataset name, variable name, main path, ..., of the entry to add, edit or remove. +#''dataset_name' and 'var_name' can take as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen). +#'Other parameters can take as a value a shell globbing expression (see ?ConfigFileOpen). +#''dataset_name' and 'var_name' take by default the regular expression '.*' (match any dataset and variable name), and the others take by default '*' (associate to the pair 'dataset_name' and 'var_name' all the defined default values. In this case '*' has a special behaviour, it won't be used as a shell globbing expression. See ?ConfigFileOpen and ?ConfigShowDefinitions). +#''var_min' and 'var_max' must be a character string. +#'To define these values, you can use defined variables via $VARIABLE_NAME$ or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for more information. +#'@return The function returns an accordingly modified configuration object. To apply the changes in the configuration file it must be saved using ConfigFileSave(). +#' +#'@examples +#'# Create an empty configuration file +#'config_file <- paste0(tempdir(), "/example.conf") +#'ConfigFileCreate(config_file, confirm = FALSE) +#'# Open it into a configuration object +#'configuration <- ConfigFileOpen(config_file) +#'# Add an entry at the bottom of 4th level of file-per-startdate experiments +#'# table which will associate the experiment "ExampleExperiment" and variable +#'# "ExampleVariable" to some information about its location. +#'configuration <- ConfigAddEntry(configuration, "experiments", +#' "last", "ExampleExperiment", "ExampleVariable", +#' "/path/to/ExampleExperiment/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Add another entry +#'configuration <- ConfigAddEntry(configuration, "experiments", +#' "last", "ExampleExperiment2", "ExampleVariable", +#' "/path/to/ExampleExperiment2/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Edit second entry to generalize for any variable. Changing variable needs . +#'configuration <- ConfigEditEntry(configuration, "experiments", 2, +#' var_name = ".*", +#' file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") +#'# Remove first entry +#'configuration <- ConfigRemoveEntry(configuration, "experiments", +#' "ExampleExperiment", "ExampleVariable") +#'# Show results +#'ConfigShowTable(configuration, "experiments") +#'# Save the configuration +#'ConfigFileSave(configuration, config_file, confirm = FALSE) +#'@export ConfigEditEntry <- function(configuration, dataset_type, position, dataset_name = NULL, var_name = NULL, main_path = NULL, file_path = NULL, nc_var_name = NULL, suffix = NULL, varmin = NULL, varmax = NULL) { if (!(dataset_type %in% c('experiments', 'observations'))) { stop("Error: 'dataset_type' must be one of 'experiments' or 'observations'") diff --git a/R/ConfigFileOpen.R b/R/ConfigFileOpen.R index b4d2bc1a..45e8712a 100644 --- a/R/ConfigFileOpen.R +++ b/R/ConfigFileOpen.R @@ -1,3 +1,44 @@ +#'Functions To Create Open And Save Configuration File +#' +#'These functions help in creating, opening and saving configuration files. +#' +#'@param file_path Path to the configuration file to create/open/save. +#'@param silent Flag to activate or deactivate verbose mode. +#'Defaults to FALSE (verbose mode on). +#'@param configuration Configuration object to save in a file. +#'@param confirm Flag to stipulate whether to ask for confirmation when saving a configuration file that already exists. +#'Defaults to TRUE (confirmation asked). +#'@param stop TRUE/FALSE whether to raise an error if not all the mandatory default variables are defined in the configuration file. +#' +#'@return +#'ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work. +#'ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise. +#'ConfigFileCreate() returns nothing. +#' +#'@examples +#'# Create an empty configuration file +#'config_file <- paste0(tempdir(), "/example.conf") +#'ConfigFileCreate(config_file, confirm = FALSE) +#'# Open it into a configuration object +#'configuration <- ConfigFileOpen(config_file) +#'# Add an entry at the bottom of 4th level of file-per-startdate experiments +#'# table which will associate the experiment "ExampleExperiment2" and variable +#'# "ExampleVariable" to some information about its location. +#'configuration <- ConfigAddEntry(configuration, "experiments", +#' "last", "ExampleExperiment2", "ExampleVariable", +#' "/path/to/ExampleExperiment2/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Edit entry to generalize for any variable. Changing variable needs . +#'configuration <- ConfigEditEntry(configuration, "experiments", 1, +#' var_name = ".*", +#' file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") +#'# Now apply matching entries for variable and experiment name and show the +#'# result +#'match_info <- ConfigApplyMatchingEntries(configuration, 'tas', +#' exp = c('ExampleExperiment2'), show_result = TRUE) +#'# Finally save the configuration file. +#'ConfigFileSave(configuration, config_file, confirm = FALSE) +#'@export ConfigFileOpen <- function(file_path, silent = FALSE, stop = FALSE) { if (!silent) { .message(paste("Reading configuration file:", file_path)) diff --git a/R/ConfigShowSimilarEntries.R b/R/ConfigShowSimilarEntries.R index e16c35b0..111998d3 100644 --- a/R/ConfigShowSimilarEntries.R +++ b/R/ConfigShowSimilarEntries.R @@ -1,3 +1,45 @@ +#'Find Similar Entries In Tables Of Datasets +#' +#'These functions help in finding similar entries in tables of supported datasets by comparing all entries with some given information. +#'This is useful when dealing with complex configuration files and not sure if already support certain variables or datasets. +#'At least one field must be provided in ConfigShowSimilarEntries(). Other fields can be unspecified and won't be taken into account. If more than one field is provided, sameness is avreaged over all provided fields and entries are sorted from higher average to lower. +#' +#'@param configuration Configuration object obtained either from ConfigFileCreate() or ConfigFileOpen(). +#'@param dataset_name Optional dataset name to look for similars of. +#'@param var_name Optional variable name to look for similars of. +#'@param main_path Optional main path to look for similars of. +#'@param file_path Optional file path to look for similars of. +#'@param nc_var_name Optional variable name inside NetCDF file to look for similars of. +#'@param suffix Optional suffix to look for similars of. +#'@param varmin Optional variable minimum to look for similars of. +#'@param varmax Optional variable maximum to look for similars of. +#'@param n_results Top 'n_results' alike results will be shown only. +#'Defaults to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). +#' +#'@return These functions return information about the found matches. +#' +#'@examples +#'# Create an empty configuration file +#'config_file <- paste0(tempdir(), "/example.conf") +#'ConfigFileCreate(config_file, confirm = FALSE) +#'# Open it into a configuration object +#'configuration <- ConfigFileOpen(config_file) +#'# Add an entry at the bottom of 4th level of file-per-startdate experiments +#'# table which will associate the experiment "ExampleExperiment2" and variable +#'# "ExampleVariable" to some information about its location. +#'configuration <- ConfigAddEntry(configuration, "experiments", "last", +#' "ExampleExperiment2", "ExampleVariable", +#' "/path/to/ExampleExperiment2/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Edit entry to generalize for any variable. Changing variable needs . +#'configuration <- ConfigEditEntry(configuration, "experiments", 1, +#' var_name = "Var.*", +#' file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") +#'# Look for similar entries +#'ConfigShowSimilarEntries(configuration, dataset_name = "Exper", +#' var_name = "Vari") +#' +#'@export ConfigShowSimilarEntries <- function(configuration, dataset_name = NULL, var_name = NULL, main_path = NULL, file_path = NULL, nc_var_name = NULL, suffix = NULL, varmin = NULL, varmax = NULL, n_results = 10) { ## Simon White: http://www.catalysoft.com/articles/StrikeAMatch.html getBigrams <- function(str) { diff --git a/R/ConfigShowTable.R b/R/ConfigShowTable.R index 0f8837e9..0f7c9d20 100644 --- a/R/ConfigShowTable.R +++ b/R/ConfigShowTable.R @@ -1,3 +1,36 @@ +#'Show Configuration Tables And Definitions +#' +#'These functions show the tables of supported datasets and definitions in a configuration object obtained via ConfigFileCreate() or ConfigFileOpen(). +#' +#'@param configuration Configuration object obtained from ConfigFileCreate() or ConfigFileOpen(). +#'@param dataset_type In ConfigShowTable(), 'dataset_type' tells whether the table to show is of experimental datasets or of observational datasets. +#'Can take values 'experiments' or 'observations'. +#'@param line_numbers 'line_numbers' is an optional vector of numbers as long as the number of entries in the specified table. +#'Intended for internal use. +#' +#'@return These functions return nothing. +#' +#'@examples +#'# Create an empty configuration file +#'config_file <- paste0(tempdir(), "/example.conf") +#'ConfigFileCreate(config_file, confirm = FALSE) +#'# Open it into a configuration object +#'configuration <- ConfigFileOpen(config_file) +#'# Add an entry at the bottom of 4th level of file-per-startdate experiments +#'# table which will associate the experiment "ExampleExperiment2" and variable +#'# "ExampleVariable" to some information about its location. +#'configuration <- ConfigAddEntry(configuration, "experiments", "last", +#' "ExampleExperiment2", "ExampleVariable", +#' "/path/to/ExampleExperiment2/", +#' "ExampleVariable/ExampleVariable_$START_DATE$.nc") +#'# Edit entry to generalize for any variable. Changing variable needs . +#'configuration <- ConfigEditEntry(configuration, "experiments", 1, +#' var_name = ".*", +#' file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") +#'# Show tables, lists and definitions +#'ConfigShowTable(configuration, 'experiments') +#'ConfigShowDefinitions(configuration) +#'@export ConfigShowTable <- function(configuration, dataset_type, line_numbers = NULL) { table_name <- dataset_type header <- paste("| Matches in", gsub("_", " ", table_name), "|") diff --git a/R/Season.R b/R/Season.R index bf549a7e..afa4d2da 100644 --- a/R/Season.R +++ b/R/Season.R @@ -1,3 +1,30 @@ +#'Computes Seasonal Means +#' +#'@description Computes seasonal means on timeseries organized in a array of any number of dimensions up to 10 dimensions where the time dimension is one of those 10 dimensions +#' +#'@param var Array containing the timeseries along one of its dimensions. +#'@param posdim Dimension along which to compute seasonal means = Time dimension. +#'@param monini an integer indicating the first month of the time series: 1 to 12. +#'@param moninf an integer indicating the month when to start the seasonal means: 1 to 12. +#'@param monsup an integer indicating the month when to stop the seasonal means: 1 to 12. +#' +#'@return Array with the same dimensions as var except along the posdim dimension whose length corresponds to the number of seasons. Partial seasons are not accounted for. +#' +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'leadtimes_dimension <- 4 +#'initial_month <- 11 +#'mean_start_month <- 12 +#'mean_stop_month <- 2 +#'season_means_mod <- Season(sampleData$mod, leadtimes_dimension, initial_month, +#' mean_start_month, mean_stop_month) +#'season_means_obs <- Season(sampleData$obs, leadtimes_dimension, initial_month, +#' mean_start_month, mean_stop_month) +#'PlotAno(season_means_mod, season_means_obs, startDates, +#' toptitle = paste('winter (DJF) temperatures'), ytitle = c('K'), +#' legends = 'ERSST', biglab = FALSE, fileout = 'tos_season_means.eps') +#'@export Season <- function(var, posdim = 4, monini, moninf, monsup) { while (monsup < moninf) { monsup <- monsup + 12 -- GitLab From 8b91abaafad48c86ce8c7938d0b2bdacfd247825 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 25 Jul 2019 11:01:21 +0200 Subject: [PATCH 30/61] Roxygen2 modification. --- R/ACC.R | 55 ++- R/Alpha.R | 22 +- R/AnimateMap.R | 113 ++++- R/Ano.R | 22 +- R/Ano_CrossValid.R | 20 +- R/ArrayToNetCDF.R | 80 +++- R/BrierScore.R | 38 +- R/CDORemap.R | 76 ++- R/Clim.R | 57 ++- R/Cluster.R | 89 ++-- R/ColorBar.R | 173 +++++-- R/Composite.R | 32 +- R/ConfigApplyMatchingEntries.R | 44 +- R/ConfigEditDefinition.R | 18 +- R/ConfigEditEntry.R | 62 ++- R/ConfigFileOpen.R | 146 +++++- R/ConfigShowSimilarEntries.R | 31 +- R/ConfigShowTable.R | 22 +- R/Consist_Trend.R | 67 +++ R/Corr.R | 106 ++++- R/EOF.R | 96 ++++ R/Enlarge.R | 19 + R/Eno.R | 49 ++ R/EnoNew.R | 56 +++ R/Filter.R | 36 ++ R/FitAcfCoef.R | 28 ++ R/FitAutocor.R | 24 + R/GenSeries.R | 21 + R/Histo2Hindcast.R | 65 +++ R/IniListDims.R | 29 ++ R/InsertDim.R | 23 + R/LeapYear.R | 19 + R/Load.R | 841 +++++++++++++++++++++++++++++++++ R/Mean1Dim.R | 24 + R/MeanListDim.R | 22 + R/NAO.R | 119 +++++ R/Plot2VarsVsLTime.R | 84 ++++ R/PlotACC.R | 90 ++++ R/PlotAno.R | 73 +++ R/PlotBoxWhisker.R | 101 ++++ R/PlotClim.R | 56 +++ R/PlotEquiMap.R | 218 +++++++++ R/PlotLayout.R | 203 ++++++++ R/PlotSection.R | 47 ++ R/PlotStereoMap.R | 147 ++++++ R/PlotVsLTime.R | 97 ++++ R/ProbBins.R | 70 +++ R/ProjectField.R | 97 ++++ R/RMS.R | 98 ++++ R/RMSSS.R | 78 +++ R/RatioRMS.R | 105 ++++ R/RatioSDRMS.R | 71 +++ R/Regression.R | 65 +++ R/SVD.R | 103 ++++ R/Season.R | 25 +- R/SelIndices.R | 26 + R/Smoothing.R | 35 ++ R/Spectrum.R | 37 ++ R/Spread.R | 79 ++++ R/StatSeasAtlHurr.R | 70 +++ R/Subset.R | 36 ++ R/ToyModel.R | 104 ++++ R/Trend.R | 55 +++ R/UltimateBrier.R | 105 ++++ R/clim.palette.R | 24 + 65 files changed, 4889 insertions(+), 254 deletions(-) diff --git a/R/ACC.R b/R/ACC.R index 3179ba7e..c61b4165 100644 --- a/R/ACC.R +++ b/R/ACC.R @@ -1,19 +1,46 @@ #'Computes Anomaly Correlation Coefficient #' -#'Calculates the Anomaly Correlation Coefficient for the ensemble mean of each model and the corresponding references for each startdate and each leadtime. The domain of interest can be specified by providing the list of longitudes/latitudes (lon/lat) of the grid together with the corners of the domain lonlatbox = c(lonmin, lonmax, latmin, latmax) +#'Calculates the Anomaly Correlation Coefficient for the ensemble mean of +#'each model and the corresponding references for each startdate and each +#'leadtime. The domain of interest can be specified by providing the list +#'of longitudes/latitudes (lon/lat) of the grid together with the corners +#'of the domain lonlatbox = c(lonmin, lonmax, latmin, latmax). #' -#'@param var_exp Array of experimental anomalies with dimensions: c(nexp, nsdates, nltimes, nlat, nlon) or c(nexp, nsdates, nmembers, nltimes, nlat, nlon). -#'@param var_obs Array of observational anomalies, same dimensions as var_exp except along the first dimension and the second if it corresponds to the member dimension. +#'@param var_exp Array of experimental anomalies with dimensions: +#' c(nexp, nsdates, nltimes, nlat, nlon) or +#' c(nexp, nsdates, nmembers, nltimes, nlat, nlon). +#'@param var_obs Array of observational anomalies, same dimensions as var_exp +#' except along the first dimension and the second if it corresponds to the +#' member dimension. #'@param lon Array of longitudes of the var_exp/var_obs grids, optional. #'@param lat Array of latitudes of the var_exp/var_obs grids, optional. -#'@param lonlatbox Domain to select : c(lonmin, lonmax, latmin, latmax), optional. -#'@param conf TRUE/FALSE: confidence intervals and significance level provided or not. -#'@param conftype "parametric" provides a confidence interval for the ACC computed by a Fisher transformation and a significance level for the ACC from a one-sided student-T distribution. "bootstrap" provides a confidence interval for the ACC and MACC computed from bootstrapping on the members with 100 drawings with replacement. To guarantee the statistical robustness of the result, make sure that your experiments/oservations/startdates/leadtimes always have the same number of members. +#'@param lonlatbox Domain to select: c(lonmin, lonmax, latmin, latmax), +#' optional. +#'@param conf TRUE/FALSE: confidence intervals and significance level +#' provided or not. +#'@param conftype "Parametric" provides a confidence interval for the ACC +#' computed by a Fisher transformation and a significance level for the ACC +#' from a one-sided student-T distribution. "Bootstrap" provides a confidence +#' interval for the ACC and MACC computed from bootstrapping on the members +#' with 100 drawings with replacement. To guarantee the statistical robustness +#' of the result, make sure that your experiments/oservations/startdates/ +#' leadtimes always have the same number of members. #'@param siglev The confidence level for the computed confidence intervals. +#' #'@return A list of length 2: #'\itemize{ -#' \item\code{$ACC} {If \code{conf = TRUE}, array with dimensions: c(nexp, nobs, nsdates, nleadtimes, 4) The fifth dimension of length 4 corresponds to the lower limit of the \code{siglev}\% confidence interval, the ACC, the upper limit of the \code{siglev}\% confidence interval and the \code{siglev}\% significance level. If \code{conf = FALSE}, the array of the Anomaly Correlation Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes).} -#' \item\code{$MACC} {The array of the Mean Anomaly Correlation Coefficient with dimensions c(nexp, nobs, nleadtimes).}} +#' \item\code{$ACC} { +#' If \code{conf = TRUE}, array with dimensions: +#' c(nexp, nobs, nsdates, nleadtimes, 4) +#' The fifth dimension of length 4 corresponds to the lower limit of the +#' \code{siglev}\% confidence interval, the ACC, the upper limit of the +#' \code{siglev}\% confidence interval and the \code{siglev}\% significance +#' level. If \code{conf = FALSE}, the array of the Anomaly Correlation +#' Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes).} +#' \item\code{$MACC} { +#' The array of the Mean Anomaly Correlation Coefficient with dimensions +#' c(nexp, nobs, nleadtimes).} +#'} #' #'@examples #'# See ?Load for explanations on the first part of this example. @@ -49,6 +76,18 @@ #'ano_obs <- Ano(sampleData$obs, clim$clim_obs) #'acc <- ACC(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) #'PlotACC(acc$ACC, startDates) +#'@references Joliffe and Stephenson (2012). Forecast Verification: A +#' Practitioner's Guide in Atmospheric Science. Wiley-Blackwell. +#'@keywords datagen +#'@author History: +#' 0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN +#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - optimization +#' 1.2 - 2014-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Bug-fixes: handling of NA & selection of domain + Simplification of code +#' 1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Boostrapping over members +#' 1.3.1 - 2014-09 (C. Prodhomme, chloe.prodhomme@@bsc.es) - Add comments and minor style changes +#' 1.3.2 - 2015-02 (N. Manubens, nicolau.manubens@@bsc.es) - Fixed ACC documentation and examples +#' #'@export ACC <- function(var_exp, var_obs, lon = NULL, lat = NULL, lonlatbox = NULL, conf = TRUE, conftype = "parametric", diff --git a/R/Alpha.R b/R/Alpha.R index e071fc82..c6d74f05 100644 --- a/R/Alpha.R +++ b/R/Alpha.R @@ -1,9 +1,20 @@ #'Estimates AutoCorrelation At Lag 1 following Guemas et al, BAMS, 2013b #' -#'This function, relying on the \code{FitAcfCoef()} function, estimates the autocorrelation at lag 1 of the xdata array following the method described in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear detrending and/or a filtering of any frequency peak if requested, the sample autocorrelation is estimated.\cr Then the theoretical autocorrelation of an AR1 is fitted to the sample autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 process. +#'This function, relying on the \code{FitAcfCoef()} function, estimates the +#'autocorrelation at lag 1 of the xdata array following the method described +#'in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear +#'detrending and/or a filtering of any frequency peak if requested, the sample +#'autocorrelation is estimated. +#'Then the theoretical autocorrelation of an AR1 is fitted to the sample +#'autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to +#'obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 +#'process. #'@param xdata Timeseries from which the autocorrelation at lag 1 is requested. -#'@param detrend TRUE applies a linear detrending to xdata prior to the estimation of the autocorrelation at lag 1. -#'@param filter TRUE applies a filtering of any frequency peak prior to the estimation of the autocorrelation at lag 1. +#'@param detrend TRUE applies a linear detrending to xdata prior to the +#' estimation of the autocorrelation at lag 1. +#'@param filter TRUE applies a filtering of any frequency peak prior to the +#' estimation of the autocorrelation at lag 1. +#' #'@return Autocorrelation at lag 1. #' #'@examples @@ -11,6 +22,11 @@ #'example(Load) #'alpha <- Alpha(sampleData$mod[1, 1, , 1]) #'print(alpha) +#' +#'@keywords datagen +#'@author History: +#' 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN #'@export Alpha <- function(xdata, detrend = FALSE, filter = FALSE) { tmp <- xdata diff --git a/R/AnimateMap.R b/R/AnimateMap.R index 1652c668..1764214a 100644 --- a/R/AnimateMap.R +++ b/R/AnimateMap.R @@ -1,32 +1,97 @@ #'Animate Maps of Forecast/Observed Values or Scores Over Forecast Time #' -#'Create animations of maps in an equi-rectangular or stereographic projection, showing the anomalies, the climatologies, the mean InterQuartile Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, the trends, the RMSE, the correlation or the RMSSS, between modelled and observed data along the forecast time (lead-time) for all input experiments and input observational datasets. +#'Create animations of maps in an equi-rectangular or stereographic +#'projection, showing the anomalies, the climatologies, the mean InterQuartile +#'Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, +#'the trends, the RMSE, the correlation or the RMSSS, between modelled and +#'observed data along the forecast time (lead-time) for all input experiments +#'and input observational datasets. #' -#'@param var Matrix of dimensions (nltime, nlat, nlon) or (nexp/nmod, nltime, nlat, nlon) or (nexp/nmod, 3/4, nltime, nlat, nlon) or (nexp/nmod, nobs, 3/4, nltime, nlat, nlon) -#'@param lon Vector containing longtitudes (degrees) -#'@param lat Vector containing latitudes (degrees) -#'@param toptitle c('','', \dots) array of main title for each animation, optional. If RMS, RMSSS, correlations: first exp with successive obs, then second exp with successive obs, etc ... -#'@param sizetit Multiplicative factor to increase title size, optional -#'@param units Units, optional -#'@param monini Starting month between 1 and 12. Default = 1 +#'@param var Matrix of dimensions (nltime, nlat, nlon) or +#' (nexp/nmod, nltime, nlat, nlon) or (nexp/nmod, 3/4, nltime, nlat, nlon) or +#' (nexp/nmod, nobs, 3/4, nltime, nlat, nlon). +#'@param lon Vector containing longtitudes (degrees). +#'@param lat Vector containing latitudes (degrees). +#'@param toptitle c('','', \dots) array of main title for each animation, +#' optional. If RMS, RMSSS, correlations: first exp with successive obs, then +#' second exp with successive obs, etc ... +#'@param sizetit Multiplicative factor to increase title size, optional. +#'@param units Units, optional. +#'@param monini Starting month between 1 and 12. Default = 1. #'@param freq 1 = yearly, 12 = monthly, 4 = seasonal ... -#'@param msk95lev TRUE/FALSE grid points with dots if 95\% significance level reached. Default = FALSE -#'@param brks Limits of colour levels, optional. For example: seq(min(var), max(var), (max(var) - min(var)) / 10) +#'@param msk95lev TRUE/FALSE grid points with dots if 95\% significance level +#' reached. Default = FALSE. +#'@param brks Limits of colour levels, optional. For example: +#' seq(min(var), max(var), (max(var) - min(var)) / 10). #'@param cols Vector of colours of length(brks) - 1, optional. -#'@param filled.continents Continents filled in grey (TRUE) or represented by a black line (FALSE). Default = TRUE. Filling unavailable if crossing Greenwich and equi = TRUE. Filling unavailable if square = FALSE and equi = TRUE. -#'@param lonmin Westward limit of the domain to plot (> 0 or < 0). Default : 0 degrees -#'@param lonmax Eastward limit of the domain to plot (> 0 or < 0). lonmax > lonmin. Default : 360 degrees -#'@param latmin Southward limit of the domain to plot. Default : -90 degrees -#'@param latmax Northward limit of the domain to plot. Default : 90 degrees -#'@param intlat Interval between latitude ticks on y-axis for equi = TRUE or between latitude circles for equi = FALSE. Default = 30 degrees. -#'@param intlon Interval between longitude ticks on x-axis. Default = 20 degrees. -#'@param drawleg Draw a colorbar. Can be FALSE only if square = FALSE or equi = FALSE. Default = TRUE -#'@param subsampleg Supsampling factor of the interval between ticks on colorbar. Default = 1 = every colour level. -#'@param colNA Color used to represent NA. Default = 'white' -#'@param equi TRUE/FALSE == cylindrical equidistant/stereographic projection. Default: TRUE -#'@param fileout c('', '', \dots) array of output file name for each animation. If RMS, RMSSS, correlations : first exp with successive obs, then second exp with successive obs, etc ... -#'@param ... Arguments to be passed to the method. Only accepts the following graphical parameters: adj ann ask bty cex cex.axis cex.lab cex.main cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. For more information about the parameters see `par`. -#'@return animations of maps +#'@param filled.continents Continents filled in grey (TRUE) or represented by +#' a black line (FALSE). Default = TRUE. Filling unavailable if crossing +#' Greenwich and equi = TRUE. Filling unavailable if square = FALSE and +#' equi = TRUE. +#'@param lonmin Westward limit of the domain to plot (> 0 or < 0). +#' Default : 0 degrees. +#'@param lonmax Eastward limit of the domain to plot (> 0 or < 0). +#' lonmax > lonmin. Default : 360 degrees. +#'@param latmin Southward limit of the domain to plot. Default : -90 degrees. +#'@param latmax Northward limit of the domain to plot. Default : 90 degrees. +#'@param intlat Interval between latitude ticks on y-axis for equi = TRUE or +#' between latitude circles for equi = FALSE. Default = 30 degrees. +#'@param intlon Interval between longitude ticks on x-axis. +#' Default = 20 degrees. +#'@param drawleg Draw a colorbar. Can be FALSE only if square = FALSE or +#' equi = FALSE. Default = TRUE. +#'@param subsampleg Supsampling factor of the interval between ticks on +#' colorbar. Default = 1 = every colour level. +#'@param colNA Color used to represent NA. Default = 'white'. +#'@param equi TRUE/FALSE == cylindrical equidistant/stereographic projection. +#' Default: TRUE. +#'@param fileout c('', '', \dots) array of output file name for each animation. +#' If RMS, RMSSS, correlations : first exp with successive obs, then second +#' exp with successive obs, etc ... +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters: adj ann ask bty cex cex.axis cex.lab cex.main cex.sub +#' cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig +#' font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty +#' lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo +#' srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. +#' For more information about the parameters see `par`. +#' +#'Examples of input: +#'\enumerate{ +#' \item{ +#' Outputs from clim (exp, obs, memb = FALSE): +#' (nmod, nltime, nlat, nlon) +#' or (nobs, nltime, nlat, nlon) +#' } +#' \item{ +#' Model output from load/ano/smoothing: +#' (nmod, nmemb, sdate, nltime, nlat, nlon) +#' then passed through spread(var, posdim = 2, narm = TRUE) +#' & mean1dim(var, posdim = 3, narm = TRUE) +#' or through trend(mean1dim(var, 2), posTR = 2): +#' (nmod, 3, nltime, nlat, nlon) +#' animates average along start dates of IQR/MaxMin/SD/MAD across members +#' or trends of the ensemble-mean computed accross the start dates. +#' } +#' \item{ +#' model and observed output from load/ano/smoothing: +#' (nmod, nmemb, sdate, nltime, nlat, nlon) +#' & (nobs, nmemb, sdate, nltime, nlat, nlon) +#' then averaged along members mean1dim(var_exp/var_obs, posdim = 2): +#' (nmod, sdate, nltime, nlat, nlon) +#' (nobs, sdate, nltime, nlat, nlon) +#' then passed through corr(exp, obs, posloop = 1, poscor = 2) +#' or RMS(exp, obs, posloop = 1, posRMS = 2): +#' (nmod, nobs, 3, nltime, nlat, nlon) +#' animates correlations or RMS between each exp & each obs against leadtime. +#' } +#'} +#' +#'@keywords dynamic +#'@author History: +#' 1.0 - 2012-04 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code +#' 1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN +#' 1.2 - 2015-05 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Use of PlotEquiMap and PlotStereoMap #' #'@examples #'# See ?Load for explanations on the first part of this example diff --git a/R/Ano.R b/R/Ano.R index ec4a2627..72f57c45 100644 --- a/R/Ano.R +++ b/R/Ano.R @@ -1,11 +1,25 @@ #'Computes Forecast or Observed Anomalies #' -#'This function computes anomalies from any experimental or observational matrix output from \code{Load()} and their climatologies output from \code{Clim()}. +#'This function computes anomalies from any experimental or observational +#'matrix output from \code{Load()} and their climatologies output from +#'\code{Clim()}. #' -#'@param var Model or observational data: c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) -#'@param clim Climatologies from clim: c(nmod/nexp/nobs, nltime) up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or c(nmod/nexp/nobs, nmemb/nparam, nltime) up to c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) depending on the options provided to \code{Clim()} +#'@param var Model or observational data: +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#'@param clim Climatologies from clim: c(nmod/nexp/nobs, nltime) +#' up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or +#' c(nmod/nexp/nobs, nmemb/nparam, nltime) up to +#' c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#' depending on the options provided to \code{Clim()}. #' -#'@return Array with same dimensions as 'var'. +#'@return Array with same dimensions as 'var'. +#'@keywords datagen +#'@author History: +#' 0.1 - 2012-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN #' #'@examples #'# Load sample data as in Load() example: diff --git a/R/Ano_CrossValid.R b/R/Ano_CrossValid.R index e4375ca4..ef2a2e92 100644 --- a/R/Ano_CrossValid.R +++ b/R/Ano_CrossValid.R @@ -1,15 +1,25 @@ #'Computes Anomalies In Cross-Validation Mode #' -#'Computes the anomalies from the arrays of the experimental and observational data output from \code{load()} by subtracting the climatologies computed with a cross-validation technique and a per-pair method. +#'Computes the anomalies from the arrays of the experimental and observational +#'data output from \code{load()} by subtracting the climatologies computed +#'with a cross-validation technique and a per-pair method. #' -#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) -#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) -#'@param memb memb: TRUE/FALSE (1 climatology for each member/1 climatology averaging all the members). Default = TRUE. +#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to +#' c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon). +#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to +#' c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon). +#'@param memb TRUE/FALSE (1 climatology for each member/1 climatology +#' averaging all the members). Default = TRUE. #' #'@return A list of length 2: #'\itemize{ #' \item\code{$ano_exp} {Matrix with same dimensions as var_exp} -#' \item\code{$ano_obs}{Matrix with same dimensions as var_obs}} +#' \item\code{$ano_obs} {Matrix with same dimensions as var_obs} +#'} +#'@keywords datagen +#'@author History: +#' 0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN #' #'@examples #'# Load sample data as in Load() example: diff --git a/R/ArrayToNetCDF.R b/R/ArrayToNetCDF.R index 4331f480..72cc9a0f 100644 --- a/R/ArrayToNetCDF.R +++ b/R/ArrayToNetCDF.R @@ -1,33 +1,67 @@ #'Save multidimensional R arrays into NetCDF files #' -#'This function takes as input one or a list of multidimensional R arrays and stores them in a NetCDF file, using the \code{ncdf4} package. The full path and name of the resulting file must be specified. Metadata can be attached to the arrays and propagated into the NetCDF file in 3 possible ways: +#'This function takes as input one or a list of multidimensional R arrays and +#'stores them in a NetCDF file, using the \code{ncdf4} package. The full path +#'and name of the resulting file must be specified. Metadata can be attached +#'to the arrays and propagated into the NetCDF file in 3 possible ways: #'\itemize{ -#' \item{Via the list names if a list of arrays is provided: Each name in the input list, corresponding to one multidimensional array, will be interpreted as the name of the variable it contains. -#'E.g: -#'\code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), -#' file_path = 'example.nc')}} -#' \item{Via the dimension names of each provided array: The dimension names of each of the provided arrays will be interpreted as names for the dimensions of the NetCDF files. Read further for special dimension names that will trigger special behaviours, such as 'time' and 'var'. -#'E.g: -#'\code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) -#' names(dim(temperature)) <- c('longitude', 'latitude', 'time') -#' ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')}} -#' \item{Via the attribute 'variables' of each provided array: The arrays can be provided with metadata in an attribute named 'variables', which is expected to be a named list of named lists, where the names of the container list are the names of the variables present in the provided array, and where each sub-list contains metadata for each of the variables. The attribute names and values supported in the sub-lists must follow the same format the package \code{ncdf4} uses to represent the NetCDF file headers. -#'E.g: -#'\code{a <- array(1:400, dim = c(5, 10, 4, 2)) -#' metadata <- list(tos = list(addOffset = 100, -#' scaleFact = 10, -#' dim = list(list(name = 'time', -#' unlim = FALSE)))) -#'attr(a, 'variables') <- metadata -#'names(dim(a)) <- c('lat', 'lon', 'time', 'var') -#'ArrayToNetCDF(a, 'tmp.nc')}} -#'The special dimension names are 'var'/'variable' and 'time'.If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will interpret each array entry along such dimension corresponds to a separate new variable, hence will create a new variable inside the NetCDF file and will use it to store all the data in the provided array for the corresponding entry along the 'var'/'variable' dimension. -#'If a dimension is named 'time', by default it will be interpreted and built as an unlimited dimension. The 'time' dimension must be the last dimension of the array (the right-most). If a 'var'/'variable' dimension is present, the 'time' dimension can be also placed on its left (i.e. the one before the last dimension). The default behaviour of creating the 'time' as unlimited dimension can be disabled by setting manually the attribute \code{unlim = FALSE}, as shown in the previous example. +#' \item{Via the list names if a list of arrays is provided: Each name in +#' the input list, corresponding to one multidimensional array, will be +#' interpreted as the name of the variable it contains. +#' E.g: +#' \code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), +#' file_path = 'example.nc')}} +#' \item{Via the dimension names of each provided array: The dimension names +#' of each of the provided arrays will be interpreted as names for the +#' dimensions of the NetCDF files. Read further for special dimension names +#' that will trigger special behaviours, such as 'time' and 'var'. +#' E.g: +#' \code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) +#' names(dim(temperature)) <- c('longitude', 'latitude', 'time') +#' ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')}} +#' \item{Via the attribute 'variables' of each provided array: The arrays can +#' be provided with metadata in an attribute named 'variables', which is +#' expected to be a named list of named lists, where the names of the +#' container list are the names of the variables present in the provided +#' array, and where each sub-list contains metadata for each of the variables. +#' The attribute names and values supported in the sub-lists must follow the +#' same format the package \code{ncdf4} uses to represent the NetCDF +#' file headers. +#' E.g: +#' \code{a <- array(1:400, dim = c(5, 10, 4, 2)) +#' metadata <- list(tos = list(addOffset = 100, +#' scaleFact = 10, +#' dim = list(list(name = 'time', +#' unlim = FALSE)))) +#' attr(a, 'variables') <- metadata +#' names(dim(a)) <- c('lat', 'lon', 'time', 'var') +#' ArrayToNetCDF(a, 'tmp.nc')}} +#'} +#'The special dimension names are 'var'/'variable' and 'time'. +#'If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will +#'interpret each array entry along such dimension corresponds to a separate +#'new variable, hence will create a new variable inside the NetCDF file and +#'will use it to store all the data in the provided array for the +#'corresponding entry along the 'var'/'variable' dimension. +#'If a dimension is named 'time', by default it will be interpreted and built +#'as an unlimited dimension. The 'time' dimension must be the last dimension +#'of the array (the right-most). If a 'var'/'variable' dimension is present, +#'the 'time' dimension can be also placed on its left (i.e. the one before the +#'last dimension). The default behaviour of creating the 'time' as unlimited +#'dimension can be disabled by setting manually the attribute +#'\code{unlim = FALSE}, as shown in the previous example. #' -#'@param arrays One or a list of multidimensional data arrays. The list can be provided with names, which will be interpreted as variable names. The arrays can be provided with dimension names. The arrays can be provided with metadata in the attribute 'variables' (read section Description for details). +#'@param arrays One or a list of multidimensional data arrays. The list can be +#' provided with names, which will be interpreted as variable names. The +#' arrays can be provided with dimension names. The arrays can be provided +#' with metadata in the attribute 'variables' (read section Description for +#' details). #'@param file_path Path and name of the NetCDF file to be created. #' #'@return This function returns NULL. +#'@keywords datagen +#'@author History: +#' 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. #' #'@examples #' \dontrun{ diff --git a/R/BrierScore.R b/R/BrierScore.R index 7995bed8..546b578a 100644 --- a/R/BrierScore.R +++ b/R/BrierScore.R @@ -1,11 +1,18 @@ #'Compute Brier Score And Its Decomposition And Brier Skill Score #' -#'Computes the Brier score (BS) and the components of its standard decomposition as well with the two within-bin components described in Stephenson et al., (2008). It also returns the bias-corrected decomposition of the BS (Ferro and Fricker, 2012). BSS having the climatology as the reference forecast. BrierScore provides the same functionality, but taking a matrix of ensemble members (exp) as input. +#'Computes the Brier score (BS) and the components of its standard +#'decomposition as well with the two within-bin components described in +#'Stephenson et al., (2008). It also returns the bias-corrected decomposition +#'of the BS (Ferro and Fricker, 2012). BSS having the climatology as the +#'reference forecast. BrierScore provides the same functionality, but taking a +#'matrix of ensemble members (exp) as input. #' -#'@param obs Vector of binary observations (1 or 0) -#'@param pred Vector of probablistic predictions with values in the range [0,1] -#'@param thresholds Values used to bin the forecasts. By default the bins are {[0,0.1), [0.1, 0.2), ... [0.9, 1]} -#'@param exp Matrix of predictions with values in the range [0,1] for the .BrierScore function +#'@param obs Vector of binary observations (1 or 0). +#'@param pred Vector of probablistic predictions with values in the range [0,1]. +#'@param thresholds Values used to bin the forecasts. By default the bins are +#' {[0,0.1), [0.1, 0.2), ... [0.9, 1]}. +#'@param exp Matrix of predictions with values in the range [0,1] for the +#' .BrierScore function #' #'@return Both BrierScore and .Brier score provide the same outputs: #'\itemize{ @@ -27,7 +34,20 @@ #' \item{$okbar}{relative frequency that the observed event occurred} #' \item{$bins}{bins used} #' \item{$pred}{values with which the forecasts are verified} -#' \item{$obs}{probability forecasts of the event}} +#' \item{$obs}{probability forecasts of the event} +#'} +#' +#'@references +#'Wilks (2006) Statistical Methods in the Atmospheric Sciences. +#'Stephenson et al. (2008). Two extra components in the Brier score decomposition. +#' Weather and Forecasting, 23: 752-757. +#'Ferro and Fricker (2012). A bias-corrected decomposition of the BS. +#' Quarterly Journal of the Royal Meteorological Society, DOI: 10.1002/qj.1924. +#' +#'@keywords datagen +#'@author History: +#' 0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues@@ic3.cat}) - Original code +#' 0.2 - 2017-02 (A. Hunter, \email{alasdair.hunter@@bsc.es}) - Adapted to veriApply() #' #'@examples #'# Minimalist examples with BrierScore @@ -57,7 +77,9 @@ #'BrierScore2 <- s2dverification:::.BrierScore #'bins_ano_exp <- ProbBins(ano_exp, thr = c(1/3, 2/3), posdates = 3, posdim = 2) #'bins_ano_obs <- ProbBins(ano_obs, thr = c(1/3, 2/3), posdates = 3, posdim = 2) -#'bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_obs, 3), +#'bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_ob,s 3), +rt + #' tdim = 2, ensdim = 3) #' } #'@export @@ -136,7 +158,7 @@ BrierScore <- function(obs, pred, thresholds = seq(0, 1, 0.1)) { } } - +#'@export .BrierScore <- function(exp, obs, thresholds = seq(0, 1, 0.1)) { if (max(exp) > 1 || min(exp) < 0) { stop("Parameter 'exp' contains predictions outside [0,1] range. Are you certain this is a probability forecast?") diff --git a/R/CDORemap.R b/R/CDORemap.R index 58686b02..b7a92e6b 100644 --- a/R/CDORemap.R +++ b/R/CDORemap.R @@ -1,23 +1,75 @@ #'Interpolates arrays with longitude and latitude dimensions using CDO #' -#'This function takes as inputs a multidimensional array (optional), a vector or matrix of longitudes, a vector or matrix of latitudes, a destination grid specification, and the name of a method to be used to interpolate (one of those available in the 'remap' utility in CDO). The interpolated array is returned (if provided) together with the new longitudes and latitudes. \code{CDORemap()} permutes by default the dimensions of the input array (if needed), splits it in chunks (CDO can work with data arrays of up to 4 dimensions), generates a file with the data of each chunk, interpolates it with CDO, reads it back into R and merges it into a result array. If no input array is provided, the longitude and latitude vectors will be transformed only. If the array is already on the desired destination grid, no transformation is performed (this behvaiour works only for lonlat and gaussian grids). Any metadata attached to the input data array, longitudes or latitudes will be preserved or accordingly modified. +#'This function takes as inputs a multidimensional array (optional), a vector +#'or matrix of longitudes, a vector or matrix of latitudes, a destination grid +#'specification, and the name of a method to be used to interpolate (one of +#'those available in the 'remap' utility in CDO). The interpolated array is +#'returned (if provided) together with the new longitudes and latitudes. +#'\code{CDORemap()} permutes by default the dimensions of the input array (if +#'needed), splits it in chunks (CDO can work with data arrays of up to 4 +#'dimensions), generates a file with the data of each chunk, interpolates it +#'with CDO, reads it back into R and merges it into a result array. If no +#'input array is provided, the longitude and latitude vectors will be +#'transformed only. If the array is already on the desired destination grid, +#'no transformation is performed (this behvaiour works only for lonlat and +#'gaussian grids). Any metadata attached to the input data array, longitudes +#'or latitudes will be preserved or accordingly modified. #' -#'@param data_array Multidimensional numeric array to be interpolated. If provided, it must have at least a longitude and a latitude dimensions, identified by the array dimension names. The names for these dimensions must be one of the recognized by s2dverification (can be checked with \code{s2dverification:::.KnownLonNames()} and \code{s2dverification:::.KnownLatNames()}). -#'@param lons Numeric vector or array of longitudes of the centers of the grid cells. Its size must match the size of the longitude/latitude dimensions of the input array. -#'@param lats Numeric vector or array of latitudes of the centers of the grid cells. Its size must match the size of the longitude/latitude dimensions of the input array. -#'@param grid Character string specifying either a name of a target grid (recognized by CDO; e.g.: 'r256x128', 't106grid') or a path to another NetCDF file which to read the target grid from (a single grid must be defined in such file). -#'@param method Character string specifying an interpolation method (recognized by CDO; e.g.: 'con', 'bil', 'bic', 'dis'). The following long names are also supported: 'conservative', 'bilinear', 'bicubic' and 'distance-weighted'. -#'@param avoid_writes The step of permutation is needed when the input array has more than 3 dimensions and none of the longitude or latitude dimensions in the right-most position (CDO would not accept it without permuting previously). This step, executed by default when needed, can be avoided for the price of writing more intermediate files (whis usually is unconvenient) by setting the parameter \code{avoid_writes = TRUE}. -#'@param crop Whether to crop the data after interpolation with 'cdo sellonlatbox' (TRUE) or to extend interpolated data to the whole world as CDO does by default (FALSE). If \code{crop = TRUE} then the longitude and latitude borders which to crop at are taken as the limits of the cells at the borders ('lons' and 'lats' are perceived as cell centers), i.e. the resulting array will contain data that covers the same area as the input array. This is equivalent to specifying \code{crop = 'preserve'}, i.e. preserving area. If \code{crop = 'tight'} then the borders which to crop at are taken as the minimum and maximum cell centers in 'lons' and 'lats', i.e. the area covered by the resulting array may be smaller if interpolating from a coarse grid to a fine grid. The parameter 'crop' also accepts a numeric vector of custom borders which to crop at: c(western border, eastern border, southern border, northern border). -#'@param force_remap Whether to force remapping, even if the input data array is already on the target grid. -#'@param write_dir Path to the directory where to create the intermediate files for CDO to work. By default, the R session temporary directory is used (\code{tempdir()}). +#'@param data_array Multidimensional numeric array to be interpolated. If +#' provided, it must have at least a longitude and a latitude dimensions, +#' identified by the array dimension names. The names for these dimensions +#' must be one of the recognized by s2dverification (can be checked with +#' \code{s2dverification:::.KnownLonNames()} and +#' \code{s2dverification:::.KnownLatNames()}). +#'@param lons Numeric vector or array of longitudes of the centers of the grid +#' cells. Its size must match the size of the longitude/latitude dimensions +#' of the input array. +#'@param lats Numeric vector or array of latitudes of the centers of the grid +#' cells. Its size must match the size of the longitude/latitude dimensions +#' of the input array. +#'@param grid Character string specifying either a name of a target grid +#' (recognized by CDO; e.g.: 'r256x128', 't106grid') or a path to another +#' NetCDF file which to read the target grid from (a single grid must be +#' defined in such file). +#'@param method Character string specifying an interpolation method +#' (recognized by CDO; e.g.: 'con', 'bil', 'bic', 'dis'). The following +#' long names are also supported: 'conservative', 'bilinear', 'bicubic' and +#' 'distance-weighted'. +#'@param avoid_writes The step of permutation is needed when the input array +#' has more than 3 dimensions and none of the longitude or latitude dimensions +#' in the right-most position (CDO would not accept it without permuting +#' previously). This step, executed by default when needed, can be avoided +#' for the price of writing more intermediate files (whis usually is +#' unconvenient) by setting the parameter \code{avoid_writes = TRUE}. +#'@param crop Whether to crop the data after interpolation with +#' 'cdo sellonlatbox' (TRUE) or to extend interpolated data to the whole +#' world as CDO does by default (FALSE). If \code{crop = TRUE} then the +#' longitude and latitude borders which to crop at are taken as the limits of +#' the cells at the borders ('lons' and 'lats' are perceived as cell centers), +#' i.e. the resulting array will contain data that covers the same area as +#' the input array. This is equivalent to specifying \code{crop = 'preserve'}, +#' i.e. preserving area. If \code{crop = 'tight'} then the borders which to +#' crop at are taken as the minimum and maximum cell centers in 'lons' and +#' 'lats', i.e. the area covered by the resulting array may be smaller if +#' interpolating from a coarse grid to a fine grid. The parameter 'crop' also +#' accepts a numeric vector of custom borders which to crop at: +#' c(western border, eastern border, southern border, northern border). +#'@param force_remap Whether to force remapping, even if the input data array +#' is already on the target grid. +#'@param write_dir Path to the directory where to create the intermediate +#' files for CDO to work. By default, the R session temporary directory is +#' used (\code{tempdir()}). #' #'@return A list with the following components: #'\itemize{ -#' \item\code{$data_array} {The interpolated data array (if an input array is provided at all, NULL otherwise).} +#' \item\code{$data_array} {The interpolated data array (if an input array +#' is provided at all, NULL otherwise).} #' \item\code{$lons} {The longitudes of the data on the destination grid.} #' \item\code{$lats} {The latitudes of the data on the destination grid.} -#' +#'} +#'@keywords datagen +#'@author History: +#' 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Original code. #'@examples #' \dontrun{ #'# Interpolating only vectors of longitudes and latitudes diff --git a/R/Clim.R b/R/Clim.R index 81b05cef..3f052e9c 100644 --- a/R/Clim.R +++ b/R/Clim.R @@ -1,35 +1,44 @@ #'Computes Bias Corrected Climatologies #' -#'This function computes only per-pair climatologies from the experimental and observational matrices output from \code{Load()}. -#'To compute plain climatologies from only experimental or observational data from \code{Load()}, the following code can be used: -#' \code{ -#'clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), -#' dim = dim(obs_datta)[-c(2, 3)]) -#' } -#'The function \code{Clim()} computes per-pair climatologies using one of the following methods: -#' \itemize{ -#' \item{ -#'1) per-pair method (Garcia-Serrano and Doblas-Reyes, CD, 2012) -#' } -#' \item{ -#'2) Kharin method (Karin et al, GRL, 2012) -#' } -#' \item{ -#'3) Fuckar method (Fuckar et al, GRL, 2014) -#' } -#' } -#'\code{Clim()} computes climatologies using the startdates covered by the whole experiments/observational data sets. The startdates not available for all the data (model and obs) are excluded when computing the climatologies. +#'This function computes only per-pair climatologies from the experimental +#'and observational matrices output from \code{Load()}. +#'To compute plain climatologies from only experimental or observational +#'data from \code{Load()}, the following code can be used: +#'\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), +#' dim = dim(obs_datta)[-c(2, 3)])} +#'The function \code{Clim()} computes per-pair climatologies using one of the +#'following methods: +#'\enumerate{ +#' \item{per-pair method (Garcia-Serrano and Doblas-Reyes, CD, 2012)} +#' \item{Kharin method (Karin et al, GRL, 2012)} +#' \item{Fuckar method (Fuckar et al, GRL, 2014)} +#'} +#'\code{Clim()} computes climatologies using the startdates covered by the +#'whole experiments/observational data sets. The startdates not available for +#'all the data (model and obs) are excluded when computing the climatologies. #' -#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) -#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) +#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to +#' c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon). +#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to +#' c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon). #'@param memb TRUE/FALSE (1 climatology for each member). Default = TRUE. -#'@param kharin TRUE/FALSE (if Kharin method is applied or not). Default = FALSE. +#'@param kharin TRUE/FALSE (if Kharin method is applied or not). +#' Default = FALSE. #'@param NDV TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE. #' #'@return A list of length 2: #'\itemize{ -#' \item{clim_exp}{Array with same dimensions as var_exp except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} -#' \item{clim_obs}{Array with same dimensions as var_obs except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} +#' \item{clim_exp}{Array with same dimensions as var_exp except the third +#' (starting dates) and, depending on the parameters, the second (members), +#' which disappear.} +#' \item{clim_obs}{Array with same dimensions as var_obs except the third +#' (starting dates) and, depending on the parameters, the second (members), +#' which disappear.} +#'} +#'@keywords datagen +#'@author History: +#' 0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN #'@examples #'# Load sample data as in Load() example: #'example(Load) diff --git a/R/Cluster.R b/R/Cluster.R index 0f7472c3..fa4b075b 100644 --- a/R/Cluster.R +++ b/R/Cluster.R @@ -1,37 +1,64 @@ -#'K-means Clustering. +#'K-means Clustering #' -#'This function computes cluster centers and their time series of occurrences, with the K-means clustering method using Euclidean distance, of an array of input data with any number of dimensions, one of them (the 'posdates'th) corresponding to time. By default the first dimension is expected to correspond to time. Specifically, it partitions the array along time axis in K groups or clusters in which each space vector/array belongs to (i.e., is a member of) the cluster with the nearest center or centroid. This function relies on the NbClust package (Charrad et al., 2014 JSS). +#'This function computes cluster centers and their time series of occurrences, +#'with the K-means clustering method using Euclidean distance, of an array of +#'input data with any number of dimensions, one of them (the 'posdates'th) +#'corresponding to time. By default the first dimension is expected to +#'correspond to time. Specifically, it partitions the array along time axis in +#'K groups or clusters in which each space vector/array belongs to (i.e., is a +#'member of) the cluster with the nearest center or centroid. This function +#'relies on the NbClust package (Charrad et al., 2014 JSS). #' -#'@param var An array with any number of dimensions, one of them (the 'posdates'th) corresponding to time with either area-averages over a series of domains or the grid points for any sptial grid structure (x), (y), (z), (x,y), (x,y,z), (y,z), ... -#'@param weights A vector/array of multiplicative weights based on the areas covering each domain/region or grid-cell of var; the dimensions of weights vector must be equal to the dimensions of 'var' without the 'posdates'th dimension. -#'@param nclusters This is positive integer K that must be bigger than 1. K is the number of clusters to be computed, or K initial cluster centers to be used in the method. Default is NULL and then user has to specify which index from NbClust and the associated criteria for selecting the optimal number of clusters will be used for K-means clustering of var. -#'@param index A validity index from NbClust package that can be used to determine optimal K if K is not specified as positive integer bigger than 1 or initial/seed cluster centers in nclusters. 'sdindex' is deafult (Halkidi et al. 2001, JIIS). Other indices also available in NBClust are "kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw", "tracew", "friedman", "rubin", "cindex", "db", "silhouette", "duda", "pseudot2", "beale", "ratkowsky", "ball", "ptbiserial", "gap", "frey", "mcclain", "gamma", "gplus", "tau", "dunn", "hubert", "sdindex", and "sdbw". One can also use all of them with the option 'alllong' or almost all indices except gap, gamma, gplus and tau with 'all', when the optimal number of clusters K is detremined by the majority rule (the maximum of histogram of the results of all indices with finite solutions). Use of some indices on a big and/or unstructured dataset can be computationally intense and/or could lead to numerical singularity. -#'@param posdates The index of the dimension that corresponds to time in the provided array in the parameter 'var', the first by default. -#' -#'@return -#' \item{cluster}{ -#'A vector (time series) of integers indicating the occurrence of a cluster, i.e., when -#'certain data member in time is allocated to a specific cluster (e.g., 2 1 3 1 1 1 ..). -#' } -#' \item{centers}{ -#'A matrix of cluster centres or centroids (e.g. [1:K, 1:spatial degrees of freedom]). -#' } -#' \item{totss}{ -#'The total sum of squares. -#' } -#' \item{withinss}{ -#'A vector of within-cluster sum of squares, one component per cluster. -#' } -#' \item{tot.withinss}{ -#'Total within-cluster sum of squares, i.e., sum(withinss). -#' } -#' \item{betweenss}{ -#'The between-cluster sum of squares, i.e. totss-tot.withinss. -#' } -#' \item{size}{ -#'The number of points in each cluster. -#' } +#'@param var An array with any number of dimensions, one of them (the +#' 'posdates'th) corresponding to time with either area-averages over a +#' series of domains or the grid points for any sptial grid structure (x), +#' (y), (z), (x,y), (x,y,z), (y,z), ... +#'@param weights A vector/array of multiplicative weights based on the areas +#' covering each domain/region or grid-cell of var; the dimensions of weights +#' vector must be equal to the dimensions of 'var' without the +#' 'posdates'th dimension. +#'@param nclusters This is positive integer K that must be bigger than 1. +#' K is the number of clusters to be computed, or K initial cluster centers +#' to be used in the method. Default is NULL and then user has to specify +#' which index from NbClust and the associated criteria for selecting the +#' optimal number of clusters will be used for K-means clustering of var. +#'@param index A validity index from NbClust package that can be used to +#' determine optimal K if K is not specified as positive integer bigger than +#' 1 or initial/seed cluster centers in nclusters. 'sdindex' is deafult +#' (Halkidi et al. 2001, JIIS). Other indices also available in NBClust are +#' "kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw", "tracew", +#' "friedman", "rubin", "cindex", "db", "silhouette", "duda", "pseudot2", +#' "beale", "ratkowsky", "ball", "ptbiserial", "gap", "frey", "mcclain", +#' "gamma", "gplus", "tau", "dunn", "hubert", "sdindex", and "sdbw". +#' One can also use all of them with the option 'alllong' or almost all indices +#' except gap, gamma, gplus and tau with 'all', when the optimal number of +#' clusters K is detremined by the majority rule (the maximum of histogram of +#' the results of all indices with finite solutions). Use of some indices on +#' a big and/or unstructured dataset can be computationally intense and/or +#' could lead to numerical singularity. +#'@param posdates The index of the dimension that corresponds to time in the +#' provided array in the parameter 'var', the first by default. #' +#'@return +#'\itemize{ +#' \item{cluster}{A vector (time series) of integers indicating the occurrence +#' of a cluster, i.e., when 'certain data member in time is allocated to a +#' specific cluster (e.g., 2 1 3 1 1 1 ..).} +#' \item{centers}{A matrix of cluster centres or centroids (e.g. +#' [1:K, 1:spatial degrees of freedom]).} +#' \item{totss}{The total sum of squares.} +#' \item{withinss}{A vector of within-cluster sum of squares, one component +#' per cluster.} +#' \item{tot.withinss}{Total within-cluster sum of squares, +#' i.e., sum(withinss).} +#' \item{betweenss}{The between-cluster sum of squares, i.e. totss-tot.withinss.} +#' \item{size}{The number of points in each cluster.} +#'} +#'@references +#'Wilks, 2011, Statistical Methods in the Atmospheric Sciences, 3rd ed., Elsevire, pp 676. +#'@keywords datagen +#'@author History: +#' 1.0 # 2014-10 (N.S. Fuckar, neven.fuckar@@bsc.es) # Original code #'@examples #'# Generating synthetic data #'a1 <- array(dim = c(200, 4)) diff --git a/R/ColorBar.R b/R/ColorBar.R index 1f64ac8d..7453bfe8 100644 --- a/R/ColorBar.R +++ b/R/ColorBar.R @@ -1,52 +1,139 @@ #'Draws a Color Bar #' -#'Generates a color bar to use as colouring function for map plots and optionally draws it (horizontally or vertically) to be added to map multipanels or plots. It is possible to draw triangles at the ends of the colour bar to represent values that go beyond the range of interest. A number of options is provided to adjust the colours and the position and size of the components. The drawn colour bar spans a whole figure region and is compatible with figure layouts.\cr\cr The generated colour bar consists of a set of breaks that define the length(brks) - 1 intervals to classify each of the values in each of the grid cells of a two-dimensional field. The corresponding grid cell of a given value of the field will be coloured in function of the interval it belongs to.\cr\cr The only mandatory parameters are 'var_limits' or 'brks' (in its second format, see below). +#'Generates a color bar to use as colouring function for map plots and +#'optionally draws it (horizontally or vertically) to be added to map +#'multipanels or plots. It is possible to draw triangles at the ends of the +#'colour bar to represent values that go beyond the range of interest. A +#'number of options is provided to adjust the colours and the position and +#'size of the components. The drawn colour bar spans a whole figure region +#'and is compatible with figure layouts.\cr\cr The generated colour bar +#'consists of a set of breaks that define the length(brks) - 1 intervals to +#'classify each of the values in each of the grid cells of a two-dimensional +#'field. The corresponding grid cell of a given value of the field will be +#'coloured in function of the interval it belongs to. +#'The only mandatory parameters are 'var_limits' or 'brks' (in its second +#'format, see below). #' -#'@param brks 'brks' can be provided in two formats: -#'a) A single value with the number of breaks to be generated automatically, between the minimum and maximum specified in 'var_limits' (both inclusive). Hence the parameter 'var_limits' is mandatory if 'brks' is provided with this format. If 'bar_limits' is additionally provided, values only between 'bar_limits' will be generated. The higher the value of 'brks', the smoother the plot will look. -#'b) A vector with the actual values of the desired breaks. Values will be reordered by force to ascending order. If provided in this format, no other parameters are required to generate/plot the colour bar. -#'This parameter is optional if 'var_limits' is specified. If 'brks' not specified but 'cols' is specified, it will take as value length(cols) + 1. If 'cols' is not specified either, 'brks' will take 21 as value.\cr\cr -#' -#'@param cols Vector of length(brks) - 1 valid colour identifiers, for each interval defined by the breaks. This parameter is optional and will be filled in with a vector of length(brks) - 1 colours generated with the function provided in 'color_fun' (\code{clim.colors} by default). -#''cols' can have one additional colour at the beginning and/or at the end with the aim to colour field values beyond the range of interest represented in the colour bar. If any of these extra colours is provided, parameter 'triangle_ends' becomes mandatory in order to disambiguate which of the ends the colours have been provided for. -#'@param vertical TRUE/FALSE for vertical/horizontal colour bar (disregarded if plot = FALSE). -#'@param subsampleg The first of each subsampleg breaks will be ticked on the colorbar. Takes by default an approximation of a value that yields a readable tick arrangement (extreme breaks always ticked). If set to 0 or lower, no labels are drawn. See the code of the function for details or use 'extra_labels' for customized tick arrangements. -#'@param bar_limits Vector of two numeric values with the extremes of the range of values represented in the colour bar. If 'var_limits' go beyond this interval, the drawing of triangle extremes is triggered at the corresponding sides, painted in 'col_inf' and 'col_sup'. Either of them can be set as NA and will then take as value the corresponding extreme in 'var_limits' (hence a triangle end won't be triggered for these sides). Takes as default the extremes of 'brks' if available, else the same values as 'var_limits'. -#'@param var_limits Vector of two numeric values with the minimum and maximum values of the field to represent. These are used to know whether to draw triangle ends at the extremes of the colour bar and what colour to fill them in with. If not specified, take the same value as the extremes of 'brks'. Hence the parameter 'brks' is mandatory if 'var_limits' is not specified. -#'@param triangle_ends Vector of two logical elements, indicating whether to force the drawing of triangle ends at each of the extremes of the colour bar. This choice is automatically made from the provided 'brks', 'bar_limits', 'var_limits', 'col_inf' and 'col_sup', but the behaviour can be manually forced to draw or not to draw the triangle ends with this parameter. If 'cols' is provided, 'col_inf' and 'col_sup' will take priority over 'triangle_ends' when deciding whether to draw the triangle ends or not. -#'@param col_inf Colour to fill the inferior triangle end with. Useful if specifying colours manually with parameter 'cols', to specify the colour and to trigger the drawing of the lower extreme triangle, or if 'cols' is not specified, to replace the colour automatically generated by ColorBar(). -#'@param col_sup Colour to fill the superior triangle end with. Useful if specifying colours manually with parameter 'cols', to specify the colour and to trigger the drawing of the upper extreme triangle, or if 'cols' is not specified, to replace the colour automatically generated by ColorBar(). -#'@param color_fun Function to generate the colours of the color bar. Must take an integer and must return as many colours. The returned colour vector can have the attribute 'na_color', with a colour to draw NA values. This parameter is set by default to clim.palette(). -#'@param plot Logical value indicating whether to only compute its breaks and colours (FALSE) or to also draw it on the current device (TRUE). -#'@param draw_ticks Whether to draw ticks for the labels along the colour bar (TRUE) or not (FALSE). TRUE by default. Disregarded if 'plot = FALSE'. -#'@param draw_separators Whether to draw black lines in the borders of each of the colour rectancles of the colour bar (TRUE) or not (FALSE). FALSE by default. Disregarded if 'plot = FALSE'. -#'@param triangle_ends_scale Scale factor for the drawn triangle ends of the colour bar, if drawn at all. Takes 1 by default (rectangle triangle proportional to the thickness of the colour bar). Disregarded if 'plot = FALSE'. -#'@param extra_labels Numeric vector of extra labels to draw along axis of the colour bar. The number of provided decimals will be conserved. Disregarded if 'plot = FALSE'. -#'@param title Title to draw on top of the colour bar, most commonly with the units of the represented field in the neighbour figures. Empty by default. -#'@param title_scale Scale factor for the 'title' of the colour bar. Takes 1 by default. -#'@param label_scale Scale factor for the labels of the colour bar. Takes 1 by default. -#'@param tick_scale Scale factor for the length of the ticks of the labels along the colour bar. Takes 1 by default. -#'@param extra_margin Extra margins to be added around the colour bar, in the format c(y1, x1, y2, x2). The units are margin lines. Takes rep(0, 4) by default. -#'@param label_digits Number of significant digits to be displayed in the labels of the colour bar, usually to avoid too many decimal digits overflowing the figure region. This does not have effect over the labels provided in 'extra_labels'. Takes 4 by default. -#'@param ... Arguments to be passed to the method. Only accepts the following graphical parameters: -#'adj ann ask bg bty cex.lab cex.main cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog -#'For more information about the parameters see `par` +#'@param brks Can be provided in two formats: +#'\itemize{ +#' \item{A single value with the number of breaks to be generated +#' automatically, between the minimum and maximum specified in 'var_limits' +#' (both inclusive). Hence the parameter 'var_limits' is mandatory if 'brks' +#' is provided with this format. If 'bar_limits' is additionally provided, +#' values only between 'bar_limits' will be generated. The higher the value +#' of 'brks', the smoother the plot will look.} +#' \item{A vector with the actual values of the desired breaks. Values will +#' be reordered by force to ascending order. If provided in this format, no +#' other parameters are required to generate/plot the colour bar.} +#'} +#' This parameter is optional if 'var_limits' is specified. If 'brks' not +#' specified but 'cols' is specified, it will take as value length(cols) + 1. +#' If 'cols' is not specified either, 'brks' will take 21 as value. +#'@param cols Vector of length(brks) - 1 valid colour identifiers, for each +#' interval defined by the breaks. This parameter is optional and will be +#' filled in with a vector of length(brks) - 1 colours generated with the +#' function provided in 'color_fun' (\code{clim.colors} by default). 'cols' +#' can have one additional colour at the beginning and/or at the end with the +#' aim to colour field values beyond the range of interest represented in the +#' colour bar. If any of these extra colours is provided, parameter +#' 'triangle_ends' becomes mandatory in order to disambiguate which of the +#' ends the colours have been provided for. +#'@param vertical TRUE/FALSE for vertical/horizontal colour bar +#' (disregarded if plot = FALSE). +#'@param subsampleg The first of each subsampleg breaks will be ticked on the +#' colorbar. Takes by default an approximation of a value that yields a +#' readable tick arrangement (extreme breaks always ticked). If set to 0 or +#' lower, no labels are drawn. See the code of the function for details or +#' use 'extra_labels' for customized tick arrangements. +#'@param bar_limits Vector of two numeric values with the extremes of the +#' range of values represented in the colour bar. If 'var_limits' go beyond +#' this interval, the drawing of triangle extremes is triggered at the +#' corresponding sides, painted in 'col_inf' and 'col_sup'. Either of them +#' can be set as NA and will then take as value the corresponding extreme in +#' 'var_limits' (hence a triangle end won't be triggered for these sides). +#' Takes as default the extremes of 'brks' if available, else the same values +#' as 'var_limits'. +#'@param var_limits Vector of two numeric values with the minimum and maximum +#' values of the field to represent. These are used to know whether to draw +#' triangle ends at the extremes of the colour bar and what colour to fill +#' them in with. If not specified, take the same value as the extremes of +#' 'brks'. Hence the parameter 'brks' is mandatory if 'var_limits' is not +#' specified. +#'@param triangle_ends Vector of two logical elements, indicating whether to +#' force the drawing of triangle ends at each of the extremes of the colour +#' bar. This choice is automatically made from the provided 'brks', +#' 'bar_limits', 'var_limits', 'col_inf' and 'col_sup', but the behaviour +#' can be manually forced to draw or not to draw the triangle ends with this +#' parameter. If 'cols' is provided, 'col_inf' and 'col_sup' will take +#' priority over 'triangle_ends' when deciding whether to draw the triangle +#' ends or not. +#'@param col_inf Colour to fill the inferior triangle end with. Useful if +#' specifying colours manually with parameter 'cols', to specify the colour +#' and to trigger the drawing of the lower extreme triangle, or if 'cols' is +#' not specified, to replace the colour automatically generated by ColorBar(). +#'@param col_sup Colour to fill the superior triangle end with. Useful if +#' specifying colours manually with parameter 'cols', to specify the colour +#' and to trigger the drawing of the upper extreme triangle, or if 'cols' is +#' not specified, to replace the colour automatically generated by ColorBar(). +#'@param color_fun Function to generate the colours of the color bar. Must +#' take an integer and must return as many colours. The returned colour vector +#' can have the attribute 'na_color', with a colour to draw NA values. This +#' parameter is set by default to clim.palette(). +#'@param plot Logical value indicating whether to only compute its breaks and +#' colours (FALSE) or to also draw it on the current device (TRUE). +#'@param draw_ticks Whether to draw ticks for the labels along the colour bar +#' (TRUE) or not (FALSE). TRUE by default. Disregarded if 'plot = FALSE'. +#'@param draw_separators Whether to draw black lines in the borders of each of +#' the colour rectancles of the colour bar (TRUE) or not (FALSE). FALSE by +#' default. Disregarded if 'plot = FALSE'. +#'@param triangle_ends_scale Scale factor for the drawn triangle ends of the +#' colour bar, if drawn at all. Takes 1 by default (rectangle triangle +#' proportional to the thickness of the colour bar). Disregarded if +#' 'plot = FALSE'. +#'@param extra_labels Numeric vector of extra labels to draw along axis of +#' the colour bar. The number of provided decimals will be conserved. +#' Disregarded if 'plot = FALSE'. +#'@param title Title to draw on top of the colour bar, most commonly with the +#' units of the represented field in the neighbour figures. Empty by default. +#'@param title_scale Scale factor for the 'title' of the colour bar. +#' Takes 1 by default. +#'@param label_scale Scale factor for the labels of the colour bar. +#' Takes 1 by default. +#'@param tick_scale Scale factor for the length of the ticks of the labels +#' along the colour bar. Takes 1 by default. +#'@param extra_margin Extra margins to be added around the colour bar, +#' in the format c(y1, x1, y2, x2). The units are margin lines. Takes +#' rep(0, 4) by default. +#'@param label_digits Number of significant digits to be displayed in the +#' labels of the colour bar, usually to avoid too many decimal digits +#' overflowing the figure region. This does not have effect over the labels +#' provided in 'extra_labels'. Takes 4 by default. +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters: adj ann ask bg bty cex.lab cex.main cex.sub cin +#' col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin +#' font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty +#' lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt +#' tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. For more +#' information about the parameters see `par`. #' #'@return #'\itemize{ -#' \item{brks}{ -#'Breaks used for splitting the range in intervals. -#' } -#' \item{cols}{ -#'Colours generated for each of the length(brks) - 1 intervals. Always of length length(brks) - 1. -#' } -#' \item{col_inf}{ -#'Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). -#' } -#' \item{col_sup}{ -#'Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). -#' } -#' +#' \item{brks}{Breaks used for splitting the range in intervals.} +#' \item{cols}{Colours generated for each of the length(brks) - 1 intervals. +#' Always of length length(brks) - 1.} +#' \item{col_inf}{Colour used to draw the lower triangle end in the colour +#' bar (NULL if not drawn at all).} +#' \item{col_sup}{Colour used to draw the upper triangle end in the colour +#' bar (NULL if not drawn at all).} +#'} +#'@keywords dplot +#'@author History: +#' 0.1 - 2012-04 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code\cr +#' 0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo@@bsc.es}) - Vert option +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN +#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - Add cex option +#' 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - New ColorBar +#' (V. Torralba, \email{veronica.torralba@@bsc.es}) #'@examples #'cols <- c("dodgerblue4", "dodgerblue1", "forestgreen", "yellowgreen", "white", #' "white", "yellow", "orange", "red", "saddlebrown") diff --git a/R/Composite.R b/R/Composite.R index 619fd800..9e7dfda5 100644 --- a/R/Composite.R +++ b/R/Composite.R @@ -1,15 +1,22 @@ -#'Computes composites. +#'Computes composites #' -#'Composites a 3-d field var(x,y,time) according to the indices of mode/cluster occurrences in time and computes the pvalues (t-test). x and y are typically lon and lat, but function can accept other 2-d fields such as lat and depth, lon and depth, etc. +#'Composites a 3-d field var(x, y, time) according to the indices of +#'mode/cluster occurrences in time and computes the pvalues (t-test). x and y +#'are typically lon and lat, but function can accept other 2-d fields such as +#'lat and depth, lon and depth, etc. #' -#'@param var 3-dimensional array (x, y, time) containing the variable to composite. -#'@param occ 1-dimensional array for the occurrence time series of mode(s)/cluster(s) -#'(*1) when one wants to composite all modes, e.g., all K=3 clusters then -#'for example occurrences could look like: 1 1 2 3 2 3 1 3 3 2 3 2 2 3 2, -#'(*2) otherwise for compositing only the 2nd mode or cluster of the above -#'example occurrences should look like 0 0 1 0 1 0 0 0 0 1 0 1 1 0 1. -#'@param lag Lag time step (an integer), e.g., for lag=2 composite will use +2 occurrences (i.e., shifted 2 time steps forward). Deafult is lag=0. -#'@param eno For using the effective sample size (TRUE) or the total sample size (FALSE that is the default) for the number of degrees of freedom. +#'@param var 3-dimensional array (x, y, time) containing the variable to +#' composite. +#'@param occ 1-dimensional array for the occurrence time series of +#' mode(s)/cluster(s). +#' (*1) When one wants to composite all modes, e.g., all K = 3 clusters then +#' for example occurrences could look like: 1 1 2 3 2 3 1 3 3 2 3 2 2 3 2. +#' (*2) Otherwise for compositing only the 2nd mode or cluster of the above +#' example occurrences should look like 0 0 1 0 1 0 0 0 0 1 0 1 1 0 1. +#'@param lag Lag time step (an integer), e.g., for lag = 2 composite will +#' use +2 occurrences (i.e., shifted 2 time steps forward). Default is lag = 0. +#'@param eno For using the effective sample size (TRUE) or the total sample +#' size (FALSE that is the default) for the number of degrees of freedom. #'@param fileout Name of the .sav output file (NULL is the default). #' #'@return @@ -23,6 +30,11 @@ #' composites obtained through a t-test that accounts for the serial #' dependence of the data with the same structure as Composite. #' } +#'} +#'@keywords datagen +#'@author History: +#' 0.1 # 2014-08 (N.S. Fuckar, \email{neven.fuckar@@bsc.es}) # Original code +#' #'@examples #'blank <- array(0, dim=c(20, 10, 30)) #' diff --git a/R/ConfigApplyMatchingEntries.R b/R/ConfigApplyMatchingEntries.R index fee390b0..c051d2f2 100644 --- a/R/ConfigApplyMatchingEntries.R +++ b/R/ConfigApplyMatchingEntries.R @@ -1,21 +1,37 @@ #'Apply Matching Entries To Dataset Name And Variable Name To Find Related Info #' -#'Given a pair of dataset name and variable name, this function determines applies all the matching entries found in the corresponding configuration table to work out the dataset main path, file path, actual name of variable inside NetCDF files, ... +#'Given a pair of dataset name and variable name, this function determines +#'applies all the matching entries found in the corresponding configuration +#'table to work out the dataset main path, file path, actual name of variable +#'inside NetCDF files, ... #' -#'@param configuration Configuration object obtained from ConfigFileOpen() or ConfigFileCreate(). -#'@param var Name of the variable to load. Will be interpreted as a string, regular expressions do not apply here. -#'Examples: 'tas' or 'tasmax_q90'. -#'@param exp Set of experimental dataset identifiers. Will be interpreted as a strings, regular expressions do not apply here. -#'Can be NULL (not to check in experimental dataset tables), and takes by default NULL. -#'Examples: c('EnsEcmwfSeas', 'EnsUkmoSeas'), c('i00k'). -#'@param obs Set of observational dataset identifiers. Will be interpreted as a strings, regular expressions do not apply here. -#'Can be NULL (not to check in observational dataset tables), and takes by default NULL. -#'Examples: c('GLORYS', 'ERAint'), c('NCEP'). -#'@param show_entries Flag to stipulate whether to show the found matching entries for all datasets and variable name. -#'@param show_result Flag to stipulate whether to show the result of applying all the matching entries (dataset main path, file path, ...). -#' -#'@return A list with the information resulting of applying the matching entries is returned. +#'@param configuration Configuration object obtained from ConfigFileOpen() +#' or ConfigFileCreate(). +#'@param var Name of the variable to load. Will be interpreted as a string, +#' regular expressions do not apply here. +#' Examples: 'tas' or 'tasmax_q90'. +#'@param exp Set of experimental dataset identifiers. Will be interpreted as +#' a strings, regular expressions do not apply here. Can be NULL (not to +#' check in experimental dataset tables), and takes by default NULL. +#' Examples: c('EnsEcmwfSeas', 'EnsUkmoSeas'), c('i00k'). +#'@param obs Set of observational dataset identifiers. Will be interpreted as +#' a strings, regular expressions do not apply here. Can be NULL (not to +#' check in observational dataset tables), and takes by default NULL. +#' Examples: c('GLORYS', 'ERAint'), c('NCEP'). +#'@param show_entries Flag to stipulate whether to show the found matching +#' entries for all datasets and variable name. +#'@param show_result Flag to stipulate whether to show the result of applying +#' all the matching entries (dataset main path, file path, ...). #' +#'@return A list with the information resulting of applying the matching +#' entries is returned. +#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], +#' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], +#' [ConfigShowTable()]. +#'@keywords datagen +#'@author History: +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version +#' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage types #'@examples #'# Create an empty configuration file #'config_file <- paste0(tempdir(), "/example.conf") diff --git a/R/ConfigEditDefinition.R b/R/ConfigEditDefinition.R index 5351b32a..d831ffba 100644 --- a/R/ConfigEditDefinition.R +++ b/R/ConfigEditDefinition.R @@ -1,14 +1,24 @@ #'Add Modify Or Remove Variable Definitions In Configuration #' -#'These functions help in adding, modifying or removing variable definitions in a configuration object obtained wit ConfigFileOpen() or ConfigFileCreate().\cr ConfigEditDefinition() will add the definition if not existing. +#'These functions help in adding, modifying or removing variable definitions +#'in a configuration object obtained with \code{\link{ConfigFileOpen}} or +#'\code{\link{ConfigFileCreate}}. ConfigEditDefinition() will add the +#'definition if not existing. #' -#'@param configuration Configuration object obtained wit ConfigFileOpen() or ConfigFileCreate(). +#'@param configuration Configuration object obtained wit ConfigFileOpen() or +#' ConfigFileCreate(). #'@param name Name of the variable to add/modify/remove. #'@param value Value to associate to the variable. -#'@param confirm Flag to stipulate whether to ask for confirmation if the variable is being modified. Takes by default TRUE. +#'@param confirm Flag to stipulate whether to ask for confirmation if the +#' variable is being modified. Takes by default TRUE. #' #'@return A modified configuration object is returned. -#' +#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], +#' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], +#' [ConfigShowTable()]. +#'@author History: +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#'@keywords datagen #'@examples #'# Create an empty configuration file #'config_file <- paste0(tempdir(), "/example.conf") diff --git a/R/ConfigEditEntry.R b/R/ConfigEditEntry.R index e3946bb7..7d71dee4 100644 --- a/R/ConfigEditEntry.R +++ b/R/ConfigEditEntry.R @@ -1,24 +1,52 @@ #'Add, Remove Or Edit Entries In The Configuration #' -#'ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions to manage entries in a configuration object created with ConfigFileOpen(). -#'Before adding an entry, make sure the defaults don't do already what you want (ConfigShowDefinitions(), ConfigShowTable()). -#'Before adding an entry, make sure it doesn't override and spoil what other entries do (ConfigShowTable(), ConfigFileOpen()). -#'Before adding an entry, make sure there aren't other entries that already do what you want (ConfigShowSimilarEntries()). +#'ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions +#'to manage entries in a configuration object created with ConfigFileOpen(). +#'Before adding an entry, make sure the defaults don't do already what you +#'want (ConfigShowDefinitions(), ConfigShowTable()). +#'Before adding an entry, make sure it doesn't override and spoil what other +#'entries do (ConfigShowTable(), ConfigFileOpen()). +#'Before adding an entry, make sure there aren't other entries that already +#'do what you want (ConfigShowSimilarEntries()). #' -#'@param configuration Configuration object obtained via ConfigFileOpen() or ConfigFileCreate() that will be modified accordingly. -#'@param dataset_type Whether to modify a table of experimental datasets or a table of observational datasets. Can take values 'experiments' or 'observations' respectively. -#'@param position 'position' tells the index in the table of the entry to edit or remove. Use ConfigShowTable() to see the index of the entry. -#'In ConfigAddEntry() it can also take the value "last" (default), that will put the entry at the end of the corresponding level, or "first" at the beginning. See ?ConfigFileOpen for more information. -#'If 'dataset_name' and 'var_name' are specified this argument is ignored in ConfigRemoveEntry(). -#'@param dataset_name, var_name, main_path, file_path, nc_var_name, suffix, varmin, varmax -#'These parameters tell the dataset name, variable name, main path, ..., of the entry to add, edit or remove. -#''dataset_name' and 'var_name' can take as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen). -#'Other parameters can take as a value a shell globbing expression (see ?ConfigFileOpen). -#''dataset_name' and 'var_name' take by default the regular expression '.*' (match any dataset and variable name), and the others take by default '*' (associate to the pair 'dataset_name' and 'var_name' all the defined default values. In this case '*' has a special behaviour, it won't be used as a shell globbing expression. See ?ConfigFileOpen and ?ConfigShowDefinitions). -#''var_min' and 'var_max' must be a character string. -#'To define these values, you can use defined variables via $VARIABLE_NAME$ or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for more information. -#'@return The function returns an accordingly modified configuration object. To apply the changes in the configuration file it must be saved using ConfigFileSave(). +#'@param configuration Configuration object obtained via ConfigFileOpen() +#' or ConfigFileCreate() that will be modified accordingly. +#'@param dataset_type Whether to modify a table of experimental datasets or +#' a table of observational datasets. Can take values 'experiments' or +#' 'observations' respectively. +#'@param position 'position' tells the index in the table of the entry to +#' edit or remove. Use ConfigShowTable() to see the index of the entry. +#' In ConfigAddEntry() it can also take the value "last" (default), that will +#' put the entry at the end of the corresponding level, or "first" at the +#' beginning. See ?ConfigFileOpen for more information. +#' If 'dataset_name' and 'var_name' are specified this argument is ignored in +#' ConfigRemoveEntry(). +#'@param dataset_name,var_name,main_path,file_path,nc_var_name,suffix,varmin,varmax +#'These parameters tell the dataset name, variable name, main path, ..., of +#' the entry to add, edit or remove. 'dataset_name' and 'var_name' can take +#' as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen). +#' Other parameters can take as a value a shell globbing expression +#' (see ?ConfigFileOpen). +#' 'dataset_name' and 'var_name' take by default the regular expression '.*' +#' (match any dataset and variable name), and the others take by default '*' +#' (associate to the pair 'dataset_name' and 'var_name' all the defined +#' default values. In this case '*' has a special behaviour, it won't be +#' used as a shell globbing expression. See ?ConfigFileOpen and +#' ?ConfigShowDefinitions). +#' 'var_min' and 'var_max' must be a character string. +#' To define these values, you can use defined variables via $VARIABLE_NAME$ +#' or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for +#' more information. #' +#'@return The function returns an accordingly modified configuration object. +#' To apply the changes in the configuration file it must be saved using +#' ConfigFileSave(). +#' +#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], [ConfigShowTable()]. +#'@keywords datagen +#'@author History: +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats #'@examples #'# Create an empty configuration file #'config_file <- paste0(tempdir(), "/example.conf") diff --git a/R/ConfigFileOpen.R b/R/ConfigFileOpen.R index 45e8712a..d73961aa 100644 --- a/R/ConfigFileOpen.R +++ b/R/ConfigFileOpen.R @@ -4,17 +4,155 @@ #' #'@param file_path Path to the configuration file to create/open/save. #'@param silent Flag to activate or deactivate verbose mode. -#'Defaults to FALSE (verbose mode on). +#' Defaults to FALSE (verbose mode on). #'@param configuration Configuration object to save in a file. -#'@param confirm Flag to stipulate whether to ask for confirmation when saving a configuration file that already exists. -#'Defaults to TRUE (confirmation asked). -#'@param stop TRUE/FALSE whether to raise an error if not all the mandatory default variables are defined in the configuration file. +#'@param confirm Flag to stipulate whether to ask for confirmation when saving +#' a configuration file that already exists. +#' Defaults to TRUE (confirmation asked). +#'@param stop TRUE/FALSE whether to raise an error if not all the mandatory +#' default variables are defined in the configuration file. +#' +#'@details +#'ConfigFileOpen() loads all the data contained in the configuration file +#'specified as parameter 'file_path'. +#'Returns a configuration object with the variables needed for the +#'configuration file mechanism to work. +#'This function is called from inside the Load() function to load the +#'configuration file specified in 'configfile'.\cr\cr +#'ConfigFileCreate() creates an empty configuration file and saves it to +#'the specified path. It may be opened later with ConfigFileOpen() to be edited. +#' Some default values are set when creating a file with this function, you +#'can check these with ConfigShowDefinitions().\cr\cr +#'ConfigFileSave() saves a configuration object into a file, which may then +#'be used from Load().\cr\cr +#'Two examples of configuration files can be found inside the 'inst/config/' +#'folder in the package: +#' \itemize{ +#' \item{BSC.conf: configuration file used at BSC-CNS. Contains location +#' data on several datasets and variables.} +#' \item{template.conf: very simple configuration file intended to be used as +#' pattern when starting from scratch.} +#' } +#'How the configuration file works:\cr +#'~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#'It contains one list and two tables.\cr +#'Each of these have a header that starts with '!!'. These are key lines and +#'should not be removed or reordered.\cr +#'Lines starting with '#' and blank lines will be ignored. +#'The list should contains variable definitions and default value definitions.\cr +#'The first table contains information about experiments.\cr +#'The third table contains information about observations.\cr +#'Each table entry is a list of comma-separated elements.\cr +#'The two first are part of a key that is associated to a value formed by the +#'other elements.\cr +#'The key elements are a dataset identifier and a variable name.\cr +#'The value elements are the dataset main path, dataset file path, the +#'variable name inside the .nc file, a default suffix (explained below) and a +#'minimum and maximum vaues beyond which loaded data is deactivated. +#'Given a dataset name and a variable name, a full path is obtained +#'concatenating the main path and the file path.\cr +#'Also the nc variable name, the suffixes and the limit values are obtained.\cr +#'Any of the elements in the keys can contain regular expressions[1] that will +#'cause matching for sets of dataset names or variable names.\cr +#'The dataset path and file path can contain shell globbing expressions[2] +#'that will cause matching for sets of paths when fetching the file in the +#'full path.\cr +#'The full path can point to an OPeNDAP URL.\cr +#'Any of the elements in the value can contain variables that will be replaced +#'to an associated string.\cr +#'Variables can be defined only in the list at the top of the file. \cr +#'The pattern of a variable definition is\cr +#'VARIABLE_NAME = VARIABLE_VALUE\cr +#'and can be accessed from within the table values or from within the variable +#'values as\cr +#' $VARIABLE_NAME$\cr +#'For example:\cr +#' FILE_NAME = tos.nc\cr +#' !!table of experiments\cr +#' ecmwf, tos, /path/to/dataset/, $FILE_NAME$\cr +#'There are some reserved variables that will offer information about the +#'store frequency, the current startdate Load() is fetching, etc:\cr +#' $VAR_NAME$, $START_DATE$, $STORE_FREQ$, $MEMBER_NUMBER$\cr +#' for experiments only: $EXP_NAME$\cr +#' for observations only: $OBS_NAME$, $YEAR$, $MONTH$, $DAY$\cr +#'Additionally, from an element in an entry value you can access the other +#'elements of the entry as:\cr +#' $EXP_MAIN_PATH$, $EXP_FILE_PATH$, \cr$VAR_NAME$, $SUFFIX$, $VAR_MIN$, $VAR_MAX$\cr + +#'The variable $SUFFIX$ is useful because it can be used to take part in the +#'main or file path. For example: '/path/to$SUFFIX$/dataset/'.\cr +#'It will be replaced by the value in the column that corresponds to the +#'suffix unless the user specifies a different suffix via the parameter +#''suffixexp' or 'suffixobs'.\cr +#'This way the user is able to load two variables with the same name in the +#'same dataset but with slight modifications, with a suffix anywhere in the +#'path to the data that advices of this slight modification.\cr +#'The entries in a table will be grouped in 4 levels of specificity: +#' \enumerate{ +#' \item{ +#'General entries:\cr +#' - the key dataset name and variable name are both a regular expression +#'matching any sequence of characters (.*) that will cause matching for any +#'pair of dataset and variable names\cr +#' Example: .*, .*, /dataset/main/path/, file/path, nc_var_name, suffix, +#'var_min, var_max +#' } +#' \item{ +#'Dataset entries:\cr +#' - the key variable name matches any sequence of characters\cr +#' Example: ecmwf, .*, /dataset/main/path/, file/path, nc_var_name, +#' suffix, var_min, var_max +#' } +#' \item{ +#'Variable entries:\cr +#' - the key dataset name matches any sequence of characters\cr +#' Example: .*, tos, /dataset/main/path/, file/path, nc_var_name, +#' suffix, var_min, var_max +#' } +#' \item{ +#' Specific entries:\cr +#' - both key values are specified\cr +#' Example: ecmwf, tos, /dataset/main/path/, file/path, nc_var_name, +#' suffix, var_min, var_max +#' } +#' } +#'Given a pair of dataset name and variable name for which we want to know the +#'full path, all the rules that match will be applied from more general to +#'more specific.\cr +#'If there is more than one entry per group that match a given key pair, +#'these will be applied in the order of appearance in the configuration file +#'(top to bottom).\cr +#'An asterisk (*) in any value element will be interpreted as 'leave it as is +#'or take the default value if yet not defined'.\cr +#'The default values are defined in the following reserved variables:\cr +#' $DEFAULT_EXP_MAIN_PATH$, $DEFAULT_EXP_FILE_PATH$, $DEFAULT_NC_VAR_NAME$, +#'$DEFAULT_OBS_MAIN_PATH$, $DEFAULT_OBS_FILE_PATH$, $DEFAULT_SUFFIX$, +#'$DEFAULT_VAR_MIN$, $DEFAULT_VAR_MAX$, \cr +#'$DEFAULT_DIM_NAME_LATITUDES$, $DEFAULT_DIM_NAME_LONGITUDES$, \cr +#'$DEFAULT_DIM_NAME_MEMBERS$\cr +#'Trailing asterisks in an entry are not mandatory. For example\cr +#' ecmwf, .*, /dataset/main/path/, *, *, *, *, *\cr +#'will have the same effect as\cr +#' ecmwf, .*, /dataset/main/path/ +#'A double quote only (") in any key or value element will be interpreted as +#''fill in with the same value as the entry above'. +#'} #' #'@return #'ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work. #'ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise. #'ConfigFileCreate() returns nothing. #' +#'@seealso [ConfigApplyMatchingEntries()]., [ConfigEditDefinition()]., +#' [ConfigEditEntry()]., [ConfigFileOpen()]., [ConfigShowSimilarEntries()]., +#' [ConfigShowTable()]. +#'@references +#'[1] \url{https://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html}\cr +#'[2] \url{http://tldp.org/LDP/abs/html/globbingref.html} +#'@author History: +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats +#'@keywords datagen #'@examples #'# Create an empty configuration file #'config_file <- paste0(tempdir(), "/example.conf") diff --git a/R/ConfigShowSimilarEntries.R b/R/ConfigShowSimilarEntries.R index 111998d3..4b9a6fa9 100644 --- a/R/ConfigShowSimilarEntries.R +++ b/R/ConfigShowSimilarEntries.R @@ -1,10 +1,16 @@ #'Find Similar Entries In Tables Of Datasets #' -#'These functions help in finding similar entries in tables of supported datasets by comparing all entries with some given information. -#'This is useful when dealing with complex configuration files and not sure if already support certain variables or datasets. -#'At least one field must be provided in ConfigShowSimilarEntries(). Other fields can be unspecified and won't be taken into account. If more than one field is provided, sameness is avreaged over all provided fields and entries are sorted from higher average to lower. +#'These functions help in finding similar entries in tables of supported +#'datasets by comparing all entries with some given information. +#'This is useful when dealing with complex configuration files and not sure +#'if already support certain variables or datasets. +#'At least one field must be provided in ConfigShowSimilarEntries(). +#'Other fields can be unspecified and won't be taken into account. If more +#'than one field is provided, sameness is avreaged over all provided fields +#'and entries are sorted from higher average to lower. #' -#'@param configuration Configuration object obtained either from ConfigFileCreate() or ConfigFileOpen(). +#'@param configuration Configuration object obtained either from +#' ConfigFileCreate() or ConfigFileOpen(). #'@param dataset_name Optional dataset name to look for similars of. #'@param var_name Optional variable name to look for similars of. #'@param main_path Optional main path to look for similars of. @@ -13,11 +19,24 @@ #'@param suffix Optional suffix to look for similars of. #'@param varmin Optional variable minimum to look for similars of. #'@param varmax Optional variable maximum to look for similars of. -#'@param n_results Top 'n_results' alike results will be shown only. -#'Defaults to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). +#'@param n_results Top 'n_results' alike results will be shown only. Defaults +#' to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). +#' +#'Sameness is calculated with string distances as specified by Simon White +#'in [1]. #' #'@return These functions return information about the found matches. #' +#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], +#' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], +#' [ConfigShowTable()]. +#'@references +#'[1] Simon White, string seamness: +#' \url{http://www.catalysoft.com/articles/StrikeAMatch.html} +#'@keywords datagen +#'@author History:\cr +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats #'@examples #'# Create an empty configuration file #'config_file <- paste0(tempdir(), "/example.conf") diff --git a/R/ConfigShowTable.R b/R/ConfigShowTable.R index 0f7c9d20..2a834e62 100644 --- a/R/ConfigShowTable.R +++ b/R/ConfigShowTable.R @@ -1,13 +1,23 @@ #'Show Configuration Tables And Definitions #' -#'These functions show the tables of supported datasets and definitions in a configuration object obtained via ConfigFileCreate() or ConfigFileOpen(). +#'These functions show the tables of supported datasets and definitions in a +#'configuration object obtained via ConfigFileCreate() or ConfigFileOpen(). #' -#'@param configuration Configuration object obtained from ConfigFileCreate() or ConfigFileOpen(). -#'@param dataset_type In ConfigShowTable(), 'dataset_type' tells whether the table to show is of experimental datasets or of observational datasets. -#'Can take values 'experiments' or 'observations'. -#'@param line_numbers 'line_numbers' is an optional vector of numbers as long as the number of entries in the specified table. -#'Intended for internal use. +#'@param configuration Configuration object obtained from ConfigFileCreate() +#' or ConfigFileOpen(). +#'@param dataset_type In ConfigShowTable(), 'dataset_type' tells whether the +#' table to show is of experimental datasets or of observational datasets. +#' Can take values 'experiments' or 'observations'. +#'@param line_numbers 'line_numbers' is an optional vector of numbers as long +#' as the number of entries in the specified table. Intended for internal use. #' +#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], +#' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], +#' [ConfigShowTable()]. +#'@keywords datagen +#'@author History:cr +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats #'@return These functions return nothing. #' #'@examples diff --git a/R/Consist_Trend.R b/R/Consist_Trend.R index 48f8999f..7e4e00f4 100644 --- a/R/Consist_Trend.R +++ b/R/Consist_Trend.R @@ -1,3 +1,70 @@ +#'Computes Trends Using Only Model Data For Which Observations Are Available +#' +#'Computes the trend coefficients for a time series by least square fitting, +#'together with the associated error interval for both the observational and +#'model data.\cr +#'Provides also the detrended observational and modeled data.\cr +#'By default, the trend is computed along the second dimension of the input +#'array, which is expected to be the start date dimension. For arrays +#'containing multiple model members, the user will first have to calculate +#'the ensemble average using \code{Mean1Dim()} or elsewhise (see the example). +#' +#'@param var_exp Ensemble mean of model hindcasts with dimensions:\cr +#' c(nmod/nexp, nsdates, nltime) up to\cr +#' c(nmod/nexp, nsdates, nltime, nlevel, nlat, nlon) +#'@param var_obs Ensemble mean of observational data with dimensions:\cr +#' c(nobs, nsdates, nltime) up to\cr +#' c(nobs, nsdates, nltime, nlevel, nlat, nlon)\cr +#' Dimensions 2 to 6 should be the same as var_exp. +#'@param interval Number of months/years between 2 start dates. Default = 1. +#' The trends will be provided respectively in field unit per month or per year. +#' +#'@return +#'\itemize{ +#' \item{$trend}{Trend coefficients of model and observational data with +#' dimensions:\cr +#' c(nmod/nexp + nobs, 3, nltime) up to\cr +#' c(nmod/nexp + nobs, 3, nltime, nlevel, nlat, nlon)\cr +#' The length 3 dimension corresponds to the lower limit of the 95\% +#' confidence interval, the slope of the trends and the upper limit of the +#' 95\% confidence interval. +#' } +#' \item{$detrendedmod}{Same dimensions as var_exp with linearly detrended +#' values of var_exp along the second = start date dimension. +#' } +#' \item{$detrendedobs}{Same dimensions as var_exp with linearly detrended +#' values of var_obs along the second = start date dimension. +#' } +#'} +#'@keywords datagen +#'@author History:\cr +#' 0.1 - 2011-11 (V. Guemas, \email{vguemas@@ic3.cat}) - Original code\cr +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN +#'@examples +#'#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#'dim_to_mean <- 2 # Mean along members +#'years_between_startdates <- 5 +#'trend <- Consist_Trend(Mean1Dim(smooth_ano_exp, dim_to_mean), +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' years_between_startdates) +#' +#'PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K/(5 years)", +#' monini = 11, limits = c(-0.8, 0.8), listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, hlines = c(0), +#' fileout = 'tos_consist_trend.eps') +#'PlotAno(InsertDim(trend$detrendedmod,2,1), InsertDim(trend$detrendedobs,2,1), +#' startDates, "Detrended tos anomalies", ytitle = 'K', +#' legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_ano.eps') +#' +#'@export Consist_Trend <- function(var_exp, var_obs, interval = 1) { # # Enlarge the number of dimensions of var_exp and var_obs to 6 if necessary diff --git a/R/Corr.R b/R/Corr.R index 4654db2c..b2743ef3 100644 --- a/R/Corr.R +++ b/R/Corr.R @@ -1,3 +1,107 @@ +#'Computes the correlation coefficient between an array of forecasts and their corresponding observations +#' +#'Calculates the correlation coefficient (Pearson, Kendall or Spearman) for +#'an array of forecasts and observations. The input should be an array with +#'dimensions c(no. of datasets, no. of start dates, no. of forecast times, +#'no. of lons, no. of lats.), where the longitude and latitude dimensions are +#'optional. The correlations are computed along the poscor dimension which +#'should correspond to the startdate dimension. If compROW is given, the +#'correlations are computed only if rows along the compROW dimension are +#'complete between limits[1] and limits[2], i.e. there are no NAs between +#'limits[1] and limits[2]. This option can be activated if the user wishes to +#'account only for the forecasts for which observations are available at all +#'leadtimes. \cr +#'Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr +#'The confidence interval is computed by a Fisher transformation.\cr +#'The significance level relies on a one-sided student-T distribution.\cr +#'We can modifiy the treshold of the test modifying siglev (default value=0.95).\cr\cr +#.Corr calculates the correlation between the ensemble mean and the +#'observations, using an N by M matrix (exp) of forecasts and a vector of +#'observations (obs) as input. +#' +#'@param var_exp Array of experimental data. +#'@param var_obs Array of observational data, same dimensions as var_exp +#' except along posloop dimension, where the length can be nobs instead of nexp. +#'@param posloop Dimension nobs and nexp. +#'@param poscor Dimension along which correlation are to be computed (the +#' dimension of the start dates). +#'@param compROW Data taken into account only if (compROW)th row is complete. +#' \cr Default = NULL. +#'@param limits Complete between limits[1] & limits[2]. Default = NULL. +#'@param siglev Significance level. Default = 0.95. +#'@param method Type of correlation: 'pearson', 'spearman' or 'kendall'. +#' Default='pearson' +#'@param conf Whether to compute confidence intervals (default = 'TRUE') or +#' not (FALSE). +#'@param pval Whether to compute statistical significance p-value (default = 'TRUE') +#' or not (FALSE). +#'@param exp N by M matrix of N forecasts from M ensemble members. +#'@param obs Vector of the corresponding observations of length N. +#' +#'@return +#'Corr: Array with dimensions :\cr +#'c(# of datasets along posloop in var_exp, # of datasets along posloop in +#'var_obs, 4, all other dimensions of var_exp & var_obs except poscor).\cr +#'The third dimension, of length 4 maximum, contains to the lower limit of +#'the 95\% confidence interval, the correlation, the upper limit of the 95\% +#'confidence interval and the 95\% significance level given by a one-sided +#'T-test. If the p-value is disabled via \code{pval = FALSE}, this dimension +#'will be of length 3. If the confidence intervals are disabled via +#'\code{conf = FALSE}, this dimension will be of length 2. If both are +#'disabled, this will be of length 2. \cr\cr +#'.Corr: +#' \itemize{ +#' \item{$corr}{The correlation statistic.} +#' \item{$p_val}{Corresponds to the p values for the \code{siglev}\% +#' (only present if \code{pval = TRUE}) for the correlation.} +#' \item{$conf_low}{Corresponds to the upper limit of the \code{siglev}\% +#' (only present if \code{conf = TRUE}) for the correlation.} +#' \item{$conf_high}{Corresponds to the lower limit of the \code{siglev}\% +#' (only present if \code{conf = TRUE}) for the correlation.} +#' } +#' +#'@keywords datagen +#'@author History:\cr +#' 0.1 - 2011-04 (V. Guemas, \email{vguemas@@bsc.es}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to R CRAN\cr +#'1.1 - 2014-10 (M. Menegoz, \email{martin.menegoz@@bsc.es}) - Adding siglev argument\cr +#'1.2 - 2015-03 (L.P. Caron, \email{louis-philippe.caron@@bsc.es}) - Adding method argument\cr +#'1.3 - 2017-02 (A. Hunter, \email{alasdair.hunter@@bsc.es}) - Adapted to veriApply() +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 +#'# Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#'dim_to_mean <- 2 # Mean along members +#'required_complete_row <- 3 # Discard start dates which contain any NA lead-times +#'leadtimes_per_startdate <- 60 +#'corr <- Corr(Mean1Dim(smooth_ano_exp, dim_to_mean), +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' compROW = required_complete_row, +#' limits = c(ceiling((runmean_months + 1) / 2), +#' leadtimes_per_startdate - floor(runmean_months / 2))) +#'PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", +#' monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), +#' fileout = 'tos_cor.eps') +#' +#'# The following example uses veriApply combined with .Corr instead of Corr +#' \dontrun{ +#'require(easyVerification) +#'Corr2 <- s2dverification:::.Corr +#'corr2 <- veriApply("Corr2", +#' smooth_ano_exp, +#' # see ?veriApply for how to use the 'parallel' option +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' tdim = 3, ensdim = 2) +#' } +#'@export Corr <- function(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, limits = NULL, siglev = 0.95, method = 'pearson', conf = TRUE, pval = TRUE) { @@ -123,7 +227,7 @@ Corr <- function(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, # CORR } - +#'@export .Corr <- function(exp, obs, siglev = 0.95, method = 'pearson', conf = TRUE, pval = TRUE) { diff --git a/R/EOF.R b/R/EOF.R index 0ad1a97c..8450701c 100644 --- a/R/EOF.R +++ b/R/EOF.R @@ -1,3 +1,99 @@ +#'Area-Weighted Empirical Orthogonal Function Analysis Using SVD +#' +#'Performs an area-weighted EOF analysis using SVD based on a covariance matrix +#'by default, based on the correlation matrix if \code{corr} argument is set to +#'\code{TRUE}. +#' +#'@param ano Array of anomalies with dimensions (number of timesteps, +#' number of latitudes, number of longitudes). +#'@param lon Vector of longitudes of \code{ano}. +#'@param lat Vector of latitudes of \code{ano}. +#'@param neofs Number of modes to be kept. Default = 15. +#'@param corr Whether to base on a correlation matrix (\code{TRUE}) or on a +#' covariance matrix (default, \code{FALSE}). +#' +#'@return +#'\itemize{ +#' \item{EOFs}{An array of EOF patterns normalized to 1 (unitless) with +#' dimensions (number of modes, number of latitudes, number of longitues). +#' Multiplying \code{EOFs} by \code{PCs} gives the original reconstructed field.} +#' \item{PCs}{An array of pincipal components with the units of the original +#' field to the power of 2, with dimensions (number of time steps, number of +#' modes). \code{PCs} contains already the percentage of explained variance +#' so, to reconstruct the original field it's only needed to multiply +#' \code{EOFs} by \code{PCs}.} +#' \item{var}{Percentage (%) of variance fraction of total variance explained +#' by each mode (number of modes).} +#' \item{mask}{Mask with dimensions (number of latitudes, number of longitudes).} +#' \item{wght}{Weights with dimensions (number of latitudes, number of longitudes).} +#'} +#'@seealso [ProjectField()], [NAO()], [PlotBoxWhisker()]. +#'@keywords datagen +#'@author History:\cr +#' 0.1 - 2012-10 (F. Lienert, \email{fabian.lienert@@ic3.cat}) - Original +#' code, inspired by R. Benestad's EOF() in R package clim.pact.\cr +#' 0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte@@ic3.cat}) - Bug-fixes:\cr +#' 1- Reversion of latitudes in the weights\cr +#' 2- Correlation matrix was used instead of covariance\cr +#' 3- Double use of the weights\cr +#'0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas@@bsc.es}) - Bug-fixes:\cr +#' 1- Weight computation - division by sum of cos(lat)\cr +#' 2- Shuffling of EOFs in EOF.2 intermediate vector\cr +#' 3- Crash when neofs = 1 sorted out\cr +#' 4- Crash when neofs > nt sorted out\cr +#'0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte@@ic3.cat}) - Fixes:\cr +#' 1- BIG cleanup of code and clarification\cr +#' 2- Reduction of the number of transpositions and associated bug-fixes\cr +#' 4- Remove of the obsolete LINPACK options\cr +#'0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas@@bsc.es}) - Fixes:\cr +#' 1- Bug-fix in dimensions handling EOF composition restitutes now the\ +#'original field in all cases\cr +#' 2- Simplification of the convention transpose\cr +#' 3- Options to use the correlation matrix rather than the +#'covariance matrix\cr +#' 4- Security checks\cr +#' 5- New normalization of PCs so that PC*EOF only reconstruct the +#'original file\cr +#' 6- Weights = sqrt(cos(lat)) for ano so that covariance matrice +#'weighted by cos(lat)\cr +#' 7- Division of EOF by weights so that the reconstruction is simply +#'EOF * PC\cr +#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to R CRAN +#' +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'# This example computes the EOFs along forecast horizons and plots the one that +#'# explains the greatest amount of variability. The example data is very low +#'# resolution so it does not make a lot of sense. +#'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#'eof <- EOF(Mean1Dim(ano$ano_exp, 2)[1, , 1, , ], sampleData$lon, sampleData$lat) +#'PlotEquiMap(eof$EOFs[1, , ], sampleData$lon, sampleData$lat) +#'@export EOF <- function(ano, lon, lat, neofs = 15, corr = FALSE) { # Checking ano if (!is.numeric(ano) || !is.array(ano)) { diff --git a/R/Enlarge.R b/R/Enlarge.R index 16736c65..5ebd28c2 100644 --- a/R/Enlarge.R +++ b/R/Enlarge.R @@ -1,3 +1,22 @@ +#'Extends The Number Of Dimensions of A Matrix +#' +#'Extends the number of dimensions of var to numdims (the added dimensions +#'have length 1). +#' +#'@param var Matrix to be extended. +#'@param numdims Output number of dimensions. +#' +#'@return Output number of dimensions. +#' +#'@keywords datagen +#'@author History:\cr +#' 0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN\cr +#' 1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Improved\cr +#'@examples +#'data <- array(1, c(2, 2, 3)) +#'print(dim(Enlarge(data, 5))) +#'@export Enlarge <- function(var, numdims) { if (is.numeric(var) || is.logical(var)) { if (is.null(dim(var))) { diff --git a/R/Eno.R b/R/Eno.R index 0f63aafa..8d021d0c 100644 --- a/R/Eno.R +++ b/R/Eno.R @@ -1,3 +1,52 @@ +#'Computes Effective Sample Size With Classical Method +#' +#'Computes the effective number of independent values along the posdim +#'dimension of a matrix.\cr +#'This effective number of independent observations can be used in +#'statistical/inference tests.\cr +#'Based on eno function from Caio Coelho from rclim.txt. +#' +#'@param obs Matrix of any number of dimensions up to 10. +#'@param posdim Dimension along which to compute the effective sample size. +#' +#'@return Same dimensions as var but without the posdim dimension. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp <- list( +#' name = 'experiment', +#' path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', +#' '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') +#' ) +#'obs <- list( +#' name = 'observation', +#' path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', +#' '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#' ) +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(exp), list(obs), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'sampleData$mod <- Season(sampleData$mod, 4, 11, 1, 12) +#'eno <- Eno(sampleData$mod[1, 1, , 1, , ], 1) +#'PlotEquiMap(eno, sampleData$lon, sampleData$lat) +#'@export Eno <- function(obs, posdim) { dimsvar <- dim(obs) if (is.null(dimsvar)) { diff --git a/R/EnoNew.R b/R/EnoNew.R index c59e7563..ebd74362 100644 --- a/R/EnoNew.R +++ b/R/EnoNew.R @@ -1,3 +1,59 @@ +#'Computes Effective Sample Size Following Guemas et al, BAMS, 2013b +#' +#'This function computes the effective number of independent values in the +#'xdata array following the method described in +#'Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. \code{EnoNew} provides +#'similar functionality to \code{Eno} but with the added options to remove +#'the linear trend or filter the frequency. +#' +#'@param xdata A numeric vector. +#'@param detrend Should the linear trend be removed from the data prior to +#' the estimation of the equivalent number of independent values. +#'@param filter Should a filtering of the frequency peaks be applied prior +#' to the estimation of the equivalent number of independant data. +#' +#'@references +#'Guemas V, Auger L, Doblas-Reyes FJ, Rust H, Ribes A, 2014, Dependencies in +#' Statistical Hypothesis Tests for Climate Time Series. Bulletin of the +#' American Meteorological Society, 95 (11), 1666-1667. +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-06 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp <- list( +#' name = 'experiment', +#' path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', +#' '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') +#' ) +#'obs <- list( +#' name = 'observation', +#' path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', +#' '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#' ) +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(exp), list(obs), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'eno <- EnoNew(sampleData$mod[1, 1, , 1, 2, 3]) +#'print(eno) +#' +#'@export EnoNew <- function(xdata, detrend = FALSE, filter = FALSE) { alpha <- Alpha(xdata, detrend, filter) s <- 0 diff --git a/R/Filter.R b/R/Filter.R index bb5eba31..b11d4d37 100644 --- a/R/Filter.R +++ b/R/Filter.R @@ -1,3 +1,39 @@ +#'Filter Frequency Peaks From An Array +#' +#'This function filters out the selected frequency from a time series.\cr +#'The filtering is performed by dichotomy, seeking for a frequency around +#'the parameter \code{freq} and the phase that maximizes the signal to subtract +#'from the time series.\cr +#'The maximization of the signal to subtract relies on a minimization of the +#'mean square differences between the time series (xdata) and the cosine of +#'the specified frequency and phase. +#' +#'@param xdata Array to be filtered. +#'@param freq Frequency to filter. +#' +#'@return Filtered Array. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2012-02 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'ensmod <- Mean1Dim(sampleData$mod, 2) +#'for (jstartdate in 1:3) { +#' spectrum <- Spectrum(ensmod[1, jstartdate, ]) +#' for (jlen in 1:dim(spectrum)[1]) { +#' if (spectrum[jlen, 2] > spectrum[jlen, 4]) { +#' ensmod[1, jstartdate, ] <- Filter(ensmod[1, jstartdate, ], +#' spectrum[jlen, 1]) +#' } +#' } +#'} +#'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = +#' 'filtered_ensemble_mean.eps') +#' +#'@export Filter <- function(xdata, freq) { fac1 <- 1 fac2 <- 1 diff --git a/R/FitAcfCoef.R b/R/FitAcfCoef.R index 1561f386..1660fc59 100644 --- a/R/FitAcfCoef.R +++ b/R/FitAcfCoef.R @@ -1,3 +1,31 @@ +#'Fits an AR1 AutoCorrelation Function Using the Cardano Formula +#' +#'This function finds the minimum point of the fourth order polynom +#'(a - x)2 + 0.25(b - x2)2 written to fit the two autoregression coefficients +#'a and b.\cr +#'A consequence of the Cardano formula is that, provided a and b are in [0 1], +#'the problem is well posed, delta > 0 and there is only one minimum.\cr\cr +#'This function is called in Alpha() to minimize the mean square differences +#'between the theoretical autocorrelation function of an AR1 and the first +#'guess of the estimated autocorrelation function estacf, using only the +#'first two lags. +#' +#'@param a Coefficient a : first estimate of the autocorrelation at lag 1. +#'@param b Coefficient b : first estimate of the autocorrelation at lag 2. +#' +#'@return Best estimate of the autocorrelation at lag 1. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-06 (L. Auger, \email{ludovic.auger@meteo.fr}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'series <- GenSeries(1000, 0.35, 2, 1) +#'estacf <- acf(series[951:1000], plot = FALSE)$acf +#'alpha <- FitAcfCoef(max(estacf[2], 0), max(estacf[3], 0)) +#'print(alpha) +#' +#'@export FitAcfCoef <- function(a, b) { if ((a < 0) || (a > 1) || (b < 0) || (b > 1)) { stop("One of the coefficients is outside the [0 1] interval"); diff --git a/R/FitAutocor.R b/R/FitAutocor.R index 1818b09d..fae78687 100644 --- a/R/FitAutocor.R +++ b/R/FitAutocor.R @@ -1,3 +1,27 @@ +#'Fits an AR1 Autocorrelation Function Using Dichotomy +#' +#'This function fits the theoretical autocorrelation function of an AR1 to +#'the first guess of the estimated autocorrelation function estacf containing +#'any number of lags. The fitting relies on a dichotomial minimisation of the +#'mean square differences between both autocorrelation functions. It returns +#'the autocorrelation at lag 1 of the fitted AR1 process. +#' +#'@param estacf First guess for the autocorrelation function. +#'@param window Interval in which the autocorrelation at lag 1 should be found. +#'@param prec Precision to which the autocorrelation function at lag 1 is to be estimated. +#' +#'@return Best estimate of the autocorrelation at lag 1. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'series <- GenSeries(1000, 0.35, 2, 1) +#'estacf <- acf(series[951:1000], plot = FALSE)$acf +#'alpha <- FitAutocor(estacf, c(-1, 1), 0.01) +#'print(alpha) +#'@export FitAutocor <- function(estacf, window = c(-1, 1), prec = 0.01) { nacf <- length(estacf) alpha <- mean(window) diff --git a/R/GenSeries.R b/R/GenSeries.R index a4497c20..f9a4c06b 100644 --- a/R/GenSeries.R +++ b/R/GenSeries.R @@ -1,3 +1,24 @@ +#'Generates An AR1 Time Series +#' +#'This function generates AR1 processes containing n data points, where alpha +#'is the autocorrelation at lag 1, and the mean and standard deviation are +#'specified by the mean and std arguments. +#' +#'@param n Length of the timeseries to be generated. +#'@param alpha Autocorrelation at lag 1. +#'@param mean Mean of the data. +#'@param std Standard deviation of the data. +#' +#'@return AR1 timeseries. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-04 (L. Auger, \email{ludovic.auger@meteo.fr}) - Original code\cr +#'1.0 - 2012-04 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'series <- GenSeries(1000, 0.35, 2, 1) +#'plot(series, type = 'l') +#'@export GenSeries <- function(n, alpha, mean, std) { res <- vector("numeric", n) x <- mean diff --git a/R/Histo2Hindcast.R b/R/Histo2Hindcast.R index b8a312c7..efb77c91 100644 --- a/R/Histo2Hindcast.R +++ b/R/Histo2Hindcast.R @@ -1,3 +1,68 @@ +#'Chunks Long Simulations For Comparison With Hindcasts +#' +#'This function reorganizes a long run (historical typically) with only one +#'start date into chunks corresponding to a set of start dates. The expected +#'input structure is the one output from \code{Load()} with 4 to 7 dimensions. +#' +#'@param varin Array of model or observational data with dimensions:\cr +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes) up to\cr +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes, nlevel, nlat, nlon) +#'@param sdatesin Start date of the input matrix 'YYYYMMDD'. +#'@param sdateout List of start dates of the output matrix +#' c('YYYYMMDD', 'YYYYMMDD', ...). +#'@param nleadtimeout Number of leadtimes in the output matrix. +#' +#'@return An array with the same number of dimensions as varin, the same +#' dimensions 1 and 2 and potentially the same dimensions 5 to 7. Dimensions +#' 3 and 4 are set by the arguments sdatesout and nleadtimesout. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-11 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp <- list( +#' name = 'experiment', +#' path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', +#' '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') +#' ) +#'obs <- list( +#' name = 'observation', +#' path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', +#' '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#' ) +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(exp), list(obs), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19901101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'areave', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' +#' +#'start_dates_out <- c('19901101', '19911101', '19921101', '19931101', '19941101') +#'leadtimes_per_startdate <- 12 +#'experimental_data <- Histo2Hindcast(sampleData$mod, startDates[1], +#' start_dates_out, leadtimes_per_startdate) +#'observational_data <- Histo2Hindcast(sampleData$obs, startDates[1], +#' start_dates_out, leadtimes_per_startdate) +#'PlotAno(experimental_data, observational_data, start_dates_out, +#' toptitle = paste('anomalies reorganized into shorter chunks'), +#' ytitle = 'K', fileout='tos_histo2hindcast.eps') +#' +#'@export Histo2Hindcast <- function(varin, sdatesin, sdatesout, nleadtimesout) { # # Input parameters diff --git a/R/IniListDims.R b/R/IniListDims.R index b438faac..825ccacc 100644 --- a/R/IniListDims.R +++ b/R/IniListDims.R @@ -1,3 +1,32 @@ +#'Creates A List Of Integer Ranges +#' +#'This function generates a list of arrays containing integers greater than or +#'equal to 1. This list of arrays is used in other functions as a list of +#'indices of the elements of the matrices. +#' +#'@param dims The dimensions of a matrix for which we need the possible +#' indices for each dimension. For exemple, if the dimensions sent are +#' c(3,2,5), the following list of arrays will be generated:\cr +#' list(c(1:3), c(1:2), c(1:5)). +#'@param lenlist 'lenlist' is the length of the list because the list will +#' be complemented above length(dims) by arrays of length 1.\cr +#' For example, if lenlist is set to 7, the previous list of arrays will be +#' extended to:\cr +#' list(c(1:3), c(1:2), c(1:5), 1, 1, 1, 1). +#' +#'@return A list with lenlist elements, each with arrays with integers from 1 +#' to the numbers in dims array and with only 1 for the dimensions above +#' length(dims). +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-04 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr +#'1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improved +#'@examples +#'indices <- IniListDims(c(2, 2, 4, 3), 6) +#'print(indices) +#'@export IniListDims <- function(dims, lenlist) { indices <- as.list(rep(1, lenlist)) for (jdim in 1:min(length(dims), lenlist)) { diff --git a/R/InsertDim.R b/R/InsertDim.R index 04bc1270..ecfc9a08 100644 --- a/R/InsertDim.R +++ b/R/InsertDim.R @@ -1,3 +1,26 @@ +#'Adds A Dimension To An Array +#' +#'Inserts an extra dimension into an array at position 'posdim' with length +#''lendim' and which correspond to 'lendim' repetitions of the 'var' array. +#' +#'@param var Matrix to which a dimension should be added. +#'@param posdim Position of the new dimension. +#'@param lendim Length of the new dimension. +#' +#'@return Matrix with the added dimension. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr +#'1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improvements +#'@examples +#' <- array(rnorm(15), dim = c(3, 1, 5, 1)) +#'print(dim(a)) +#'print(dim(a[, , , ])) +#'print(dim(InsertDim(InsertDim(a[, , , ], 2, 1), 4, 1))) +#' +#'@export InsertDim <- function(var, posdim, lendim) { if (is.numeric(var) || is.logical(var)) { dimsvar <- dim(var) diff --git a/R/LeapYear.R b/R/LeapYear.R index 3e870922..4f63dbfe 100644 --- a/R/LeapYear.R +++ b/R/LeapYear.R @@ -1,3 +1,22 @@ +#'Checks Whether A Year Is Leap Year +#' +#'This function tells whether a year is a leap year or not. +#' +#'@param year A numeric value indicating the year in the Gregorian calendar. +#' +#'@return Boolean telling whether the year is a leap year or not. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'print(LeapYear(1990)) +#'print(LeapYear(1991)) +#'print(LeapYear(1992)) +#'print(LeapYear(1993)) + +#'@export LeapYear <- function(year) { leap <- FALSE if (year %% 4 == 0) { diff --git a/R/Load.R b/R/Load.R index 5cebec71..5d574b50 100644 --- a/R/Load.R +++ b/R/Load.R @@ -1,3 +1,844 @@ +#'Loads Experimental And Observational Data +#' +#'This function loads monthly or daily data from a set of specified +#'experimental datasets together with data that date-corresponds from a set +#'of specified observational datasets. See parameters 'storefreq', +#''sampleperiod', 'exp' and 'obs'.\cr\cr +#'A set of starting dates is specified through the parameter 'sdates'. Data of +#'each starting date is loaded for each model. +#'\code{Load()} arranges the data in two arrays with a similar format both +#'with the following dimensions: +#' \enumerate{ +#' \item{The number of experimental datasets determined by the user through +#' the argument 'exp' (for the experimental data array) or the number of +#' observational datasets available for validation (for the observational +#' array) determined as well by the user through the argument 'obs'.} +#' \item{The greatest number of members across all experiments (in the +#' experimental data array) or across all observational datasets (in the +#' observational data array).} +#' \item{The number of starting dates determined by the user through the +#' 'sdates' argument.} +#' \item{The greatest number of lead-times.} +#' \item{The number of latitudes of the selected zone.} +#' \item{The number of longitudes of the selected zone.} +#' } +#'Dimensions 5 and 6 are optional and their presence depends on the type of +#'the specified variable (global mean or 2-dimensional) and on the selected +#'output type (area averaged time series, latitude averaged time series, +#'longitude averaged time series or 2-dimensional time series).\cr +#'In the case of loading an area average the dimensions of the arrays will be +#'only the first 4.\cr\cr +#'Only a specified variable is loaded from each experiment at each starting +#'date. See parameter 'var'.\cr +#'Afterwards, observational data that matches every starting date and lead-time +#'of every experimental dataset is fetched in the file system (so, if two +#'predictions at two different start dates overlap, some observational values +#'will be loaded and kept in memory more than once).\cr +#'If no data is found in the file system for an experimental or observational +#'array point it is filled with an NA value.\cr\cr +#'If the specified output is 2-dimensional or latitude- or longitude-averaged +#'time series all the data is interpolated into a common grid. If the +#'specified output type is area averaged time series the data is averaged on +#'the individual grid of each dataset but can also be averaged after +#'interpolating into a common grid. See parameters 'grid' and 'method'.\cr +#'Once the two arrays are filled by calling this function, other functions in +#'the s2dverification package that receive as inputs data formatted in this +#'data structure can be executed (e.g: \code{Clim()} to compute climatologies, +#'\code{Ano()} to compute anomalies, ...).\cr\cr +#'Load() has many additional parameters to disable values and trim dimensions +#'of selected variable, even masks can be applied to 2-dimensional variables. +#'See parameters 'nmember', 'nmemberobs', 'nleadtime', 'leadtimemin', +#''leadtimemax', 'sampleperiod', 'lonmin', 'lonmax', 'latmin', 'latmax', +#''maskmod', 'maskobs', 'varmin', 'varmax'.\cr\cr +#'The parameters 'exp' and 'obs' can take various forms. The most direct form +#'is a list of lists, where each sub-list has the component 'path' associated +#'to a character string with a pattern of the path to the files of a dataset +#'to be loaded. These patterns can contain wildcards and tags that will be +#'replaced automatically by \code{Load()} with the specified starting dates, +#'member numbers, variable name, etc.\cr +#'See parameter 'exp' or 'obs' for details.\cr\cr +#'Only NetCDF files are supported. OPeNDAP URLs to NetCDF files are also +#'supported.\cr +#'\code{Load()} can load 2-dimensional or global mean variables in any of the +#'following formats: +#' \itemize{ +#' \item{experiments: +#' \itemize{ +#' \item{file per ensemble per starting date +#' (YYYY, MM and DD somewhere in the path)} +#' \item{file per member per starting date +#' (YYYY, MM, DD and MemberNumber somewhere in the path. Ensemble +#' experiments with different numbers of members can be loaded in +#' a single \code{Load()} call.)} +#' } +#' (YYYY, MM and DD specify the starting dates of the predictions) +#' } +#' \item{observations: +#' \itemize{ +#' \item{file per ensemble per month +#' (YYYY and MM somewhere in the path)} +#' \item{file per member per month +#' (YYYY, MM and MemberNumber somewhere in the path, obs with different +#' numbers of members supported)} +#' \item{file per dataset (No constraints in the path but the time axes +#' in the file have to be properly defined)} +#' } +#' (YYYY and MM correspond to the actual month data in the file) +#' } +#' } +#'In all the formats the data can be stored in a daily or monthly frequency, +#'or a multiple of these (see parameters 'storefreq' and 'sampleperiod').\cr +#'All the data files must contain the target variable defined over time and +#'potentially over members, latitude and longitude dimensions in any order, +#'time being the record dimension.\cr +#'In the case of a two-dimensional variable, the variables longitude and +#'latitude must be defined inside the data file too and must have the same +#'names as the dimension for longitudes and latitudes respectively.\cr +#'The names of these dimensions (and longitude and latitude variables) and the +#'name for the members dimension are expected to be 'longitude', 'latitude' +#'and 'ensemble' respectively. However, these names can be adjusted with the +#'parameter 'dimnames' or can be configured in the configuration file (read +#'below in parameters 'exp', 'obs' or see \code{?ConfigFileOpen} +#'for more information.\cr +#'All the data files are expected to have numeric values representable with +#'32 bits. Be aware when choosing the fill values or infinite values in the +#'datasets to load.\cr\cr +#'The Load() function returns a named list following a structure similar to +#'the used in the package 'downscaleR'.\cr +#'The components are the following: +#' \itemize{ +#' \item{'mod' is the array that contains the experimental data. It has the +#' attribute 'dimensions' associated to a vector of strings with the labels +#' of each dimension of the array, in order.} +#' \item{'obs' is the array that contains the observational data. It has +#' the attribute 'dimensions' associated to a vector of strings with the +#' labels of each dimension of the array, in order.} +#' \item{'obs' is the array that contains the observational data.} +#' \item{'lat' and 'lon' are the latitudes and longitudes of the grid into +#' which the data is interpolated (0 if the loaded variable is a global +#' mean or the output is an area average).\cr +#' Both have the attribute 'cdo_grid_des' associated with a character +#' string with the name of the common grid of the data, following the CDO +#' naming conventions for grids.\cr +#' The attribute 'projection' is kept for compatibility with 'downscaleR'. +#' } +#' \item{'Variable' has the following components: +#' \itemize{ +#' \item{'varName', with the short name of the loaded variable as +#' specified in the parameter 'var'.} +#' \item{'level', with information on the pressure level of the variable. +#' Is kept to NULL by now.} +#' } +#' And the following attributes: +#' \itemize{ +#' \item{'is_standard', kept for compatibility with 'downscaleR', +#' tells if a dataset has been homogenized to standards with +#' 'downscaleR' catalogs.} +#' \item{'units', a character string with the units of measure of the +#' variable, as found in the source files.} +#' \item{'longname', a character string with the long name of the +#' variable, as found in the source files.} +#' \item{'daily_agg_cellfun', 'monthly_agg_cellfun', 'verification_time', +#' kept for compatibility with 'downscaleR'.} +#' } +#' } +#' \item{'Datasets' has the following components: +#' \itemize{ +#' \item{'exp', a named list where the names are the identifying +#' character strings of each experiment in 'exp', each associated to a +#' list with the following components: +#' \itemize{ +#' \item{'members', a list with the names of the members of the +#' dataset.} +#' \item{'source', a path or URL to the source of the dataset.} +#' } +#' } +#' \item{'obs', similar to 'exp' but for observational datasets.} +#' } +#' } +#' \item{'Dates', with the follwing components: +#' \itemize{ +#' \item{'start', an array of dimensions (sdate, time) with the POSIX +#' initial date of each forecast time of each starting date.} +#' \item{'end', an array of dimensions (sdate, time) with the POSIX +#' final date of each forecast time of each starting date.} +#' } +#' } +#' \item{'InitializationDates', a vector of starting dates as specified in +#' 'sdates', in POSIX format.} +#' \item{'when', a time stamp of the date the \code{Load()} call to obtain +#' the data was issued.} +#' \item{'source_files', a vector of character strings with complete paths +#' to all the found files involved in the \code{Load()} call.} +#' \item{'not_found_files', a vector of character strings with complete +#' paths to not found files involved in the \code{Load()} call.} +#' } +#' +#'@param var Short name of the variable to load. It should coincide with the +#' variable name inside the data files.\cr +#' E.g.: \code{var = 'tos'}, \code{var = 'tas'}, \code{var = 'prlr'}.\cr +#' In some cases, though, the path to the files contains twice or more times +#' the short name of the variable but the actual name of the variable inside +#' the data files is different. In these cases it may be convenient to provide +#' \code{var} with the name that appears in the file paths (see details on +#' parameters \code{exp} and \code{obs}). +#'@param exp Parameter to specify which experimental datasets to load data +#' from.\cr +#' It can take two formats: a list of lists or a vector of character strings. +#' Each format will trigger a different mechanism of locating the requested +#' datasets.\cr +#' The first format is adequate when loading data you'll only load once or +#' occasionally. The second format is targeted to avoid providing repeatedly +#' the information on a certain dataset but is more complex to use.\cr\cr +#' IMPORTANT: Place first the experiment with the largest number of members +#' and, if possible, with the largest number of leadtimes. If not possible, +#' the arguments 'nmember' and/or 'nleadtime' should be filled to not miss +#' any member or leadtime.\cr +#' If 'exp' is not specified or set to NULL, observational data is loaded for +#' each start-date as far as 'leadtimemax'. If 'leadtimemax' is not provided, +#' \code{Load()} will retrieve data of a period of time as long as the time +#' period between the first specified start date and the current date.\cr\cr +#' List of lists:\cr +#' A list of lists where each sub-list contains information on the location +#' and format of the data files of the dataset to load.\cr +#' Each sub-list can have the following components: +#' \itemize{ +#' \item{'name': A character string to identify the dataset. Optional.} +#' \item{'path': A character string with the pattern of the path to the +#' files of the dataset. This pattern can be built up making use of some +#' special tags that \code{Load()} will replace with the appropriate +#' values to find the dataset files. The allowed tags are $START_DATE$, +#' $YEAR$, $MONTH$, $DAY$, $MEMBER_NUMBER$, $STORE_FREQ$, $VAR_NAME$, +#' $EXP_NAME$ (only for experimental datasets), $OBS_NAME$ (only for +#' observational datasets) and $SUFFIX$\cr +#' Example: /path/to/$EXP_NAME$/postprocessed/$VAR_NAME$/\cr +#' $VAR_NAME$_$START_DATE$.nc\cr +#' If 'path' is not specified and 'name' is specified, the dataset +#' information will be fetched with the same mechanism as when using +#' the vector of character strings (read below). +#' } +#' \item{'nc_var_name': Character string with the actual variable name +#' to look for inside the dataset files. Optional. Takes, by default, +#' the same value as the parameter 'var'. +#' } +#' \item{'suffix': Wildcard character string that can be used to build +#' the 'path' of the dataset. It can be accessed with the tag $SUFFIX$. +#' Optional. Takes '' by default. +#' } +#' \item{'var_min': Important: Character string. Minimum value beyond +#' which read values will be deactivated to NA. Optional. No deactivation +#' is performed by default. +#' } +#' \item{'var_max': Important: Character string. Maximum value beyond +#' which read values will be deactivated to NA. Optional. No deactivation +#' is performed by default. +#' } +#' } +#' The tag $START_DATES$ will be replaced with all the starting dates +#' specified in 'sdates'. $YEAR$, $MONTH$ and $DAY$ will take a value for each +#' iteration over 'sdates', simply these are the same as $START_DATE$ but +#' split in parts.\cr +#' $MEMBER_NUMBER$ will be replaced by a character string with each member +#' number, from 1 to the value specified in the parameter 'nmember' (in +#' experimental datasets) or in 'nmemberobs' (in observational datasets). It +#' will range from '01' to 'N' or '0N' if N < 10.\cr +#' $STORE_FREQ$ will take the value specified in the parameter 'storefreq' +#' ('monthly' or 'daily').\cr +#' $VAR_NAME$ will take the value specified in the parameter 'var'.\cr +#' $EXP_NAME$ will take the value specified in each component of the parameter +#' 'exp' in the sub-component 'name'.\cr +#' $OBS_NAME$ will take the value specified in each component of the parameter +#' 'obs' in the sub-component 'obs.\cr +#' $SUFFIX$ will take the value specified in each component of the parameters +#' 'exp' and 'obs' in the sub-component 'suffix'.\cr +#' Example: +#' \preformatted{ +#' list( +#' list( +#' name = 'experimentA', +#' path = file.path('/path/to/$DATASET_NAME$/$STORE_FREQ$', +#' '$VAR_NAME$$SUFFIX$', +#' '$VAR_NAME$_$START_DATE$.nc'), +#' nc_var_name = '$VAR_NAME$', +#' suffix = '_3hourly', +#' var_min = '-1e19', +#' var_max = '1e19' +#' ) +#' ) +#' } +#' This will make \code{Load()} look for, for instance, the following paths, +#' if 'sdates' is c('19901101', '19951101', '20001101'):\cr +#' /path/to/experimentA/monthly_mean/tas_3hourly/tas_19901101.nc\cr +#' /path/to/experimentA/monthly_mean/tas_3hourly/tas_19951101.nc\cr +#' /path/to/experimentA/monthly_mean/tas_3hourly/tas_20001101.nc\cr\cr +#' Vector of character strings: +#' To avoid specifying constantly the same information to load the same +#' datasets, a vector with only the names of the datasets to load can be +#' specified.\cr +#' \code{Load()} will then look for the information in a configuration file +#' whose path must be specified in the parameter 'configfile'.\cr +#' Check \code{?ConfigFileCreate}, \code{ConfigFileOpen}, +#' \code{ConfigEditEntry} & co. to learn how to create a new configuration +#' file and how to add the information there.\cr +#' Example: c('experimentA', 'experimentB') +#' +#'@param obs Argument with the same format as parameter 'exp'. See details on +#' parameter 'exp'.\cr +#' If 'obs' is not specified or set to NULL, no observational data is loaded.\cr +#'@param sdates Vector of starting dates of the experimental runs to be loaded +#' following the pattern 'YYYYMMDD'.\cr +#' This argument is mandatory.\cr +#' E.g. c('19601101', '19651101', '19701101') +#'@param nmember Vector with the numbers of members to load from the specified +#' experimental datasets in 'exp'.\cr +#' If not specified, the automatically detected number of members of the +#' first experimental dataset is detected and replied to all the experimental +#' datasets.\cr +#' If a single value is specified it is replied to all the experimental +#' datasets.\cr +#' Data for each member is fetched in the file system. If not found is +#' filled with NA values.\cr +#' An NA value in the 'nmember' list is interpreted as "fetch as many members +#' of each experimental dataset as the number of members of the first +#' experimental dataset".\cr +#' Note: It is recommended to specify the number of members of the first +#' experimental dataset if it is stored in file per member format because +#' there are known issues in the automatic detection of members if the path +#' to the dataset in the configuration file contains Shell Globbing wildcards +#' such as '*'.\cr +#' E.g., c(4, 9) +#'@param nmemberobs Vector with the numbers of members to load from the +#' specified observational datasets in 'obs'.\cr +#' If not specified, the automatically detected number of members of the +#' first observational dataset is detected and replied to all the +#' observational datasets.\cr +#' If a single value is specified it is replied to all the observational +#' datasets.\cr +#' Data for each member is fetched in the file system. If not found is +#' filled with NA values.\cr +#' An NA value in the 'nmemberobs' list is interpreted as "fetch as many +#' members of each observational dataset as the number of members of the +#' first observational dataset".\cr +#' Note: It is recommended to specify the number of members of the first +#' observational dataset if it is stored in file per member format because +#' there are known issues in the automatic detection of members if the path +#' to the dataset in the configuration file contains Shell Globbing wildcards +#' such as '*'.\cr +#' E.g., c(1, 5) +#'@param nleadtime Deprecated. See parameter 'leadtimemax'. +#'@param leadtimemin Only lead-times higher or equal to 'leadtimemin' are +#' loaded. Takes by default value 1. +#'@param leatimemax Only lead-times lower or equal to 'leadtimemax' are loaded. +#' Takes by default the number of lead-times of the first experimental +#' dataset in 'exp'.\cr +#' If 'exp' is NULL this argument won't have any effect +#' (see \code{?Load} description). +#'@param storefreq Frequency at which the data to be loaded is stored in the +#' file system. Can take values 'monthly' or 'daily'.\cr +#' By default it takes 'monthly'.\cr +#' Note: Data stored in other frequencies with a period which is divisible by +#' a month can be loaded with a proper use of 'storefreq' and 'sampleperiod' +#' parameters. It can also be loaded if the period is divisible by a day and +#' the observational datasets are stored in a file per dataset format or +#' 'obs' is empty. +#'@param sampleperiod To load only a subset between 'leadtimemin' and +#' 'leadtimemax' with the period of subsampling 'sampleperiod'.\cr +#' Takes by default value 1 (all lead-times are loaded).\cr +#' See 'storefreq' for more information. +#'@param lonmin If a 2-dimensional variable is loaded, values at longitudes +#' lower than 'lonmin' aren't loaded.\cr +#' Must take a value in the range [-360, 360] (if negative longitudes are +#' found in the data files these are translated to this range).\cr +#' It is set to 0 if not specified.\cr +#' If 'lonmin' > 'lonmax', data across Greenwich is loaded. +#'@param lonmax If a 2-dimensional variable is loaded, values at longitudes +#' higher than 'lonmax' aren't loaded.\cr +#' Must take a value in the range [-360, 360] (if negative longitudes are +#' found in the data files these are translated to this range).\cr +#' It is set to 360 if not specified.\cr +#' If 'lonmin' > 'lonmax', data across Greenwich is loaded. +#'@param latmin If a 2-dimensional variable is loaded, values at latitudes +#' lower than 'latmin' aren't loaded.\cr +#' Must take a value in the range [-90, 90].\cr +#' It is set to -90 if not specified. +#'@param latmax If a 2-dimensional variable is loaded, values at latitudes +#' higher than 'latmax' aren't loaded.\cr +#' Must take a value in the range [-90, 90].\cr +#' It is set to 90 if not specified. +#'@param output This parameter determines the format in which the data is +#' arranged in the output arrays.\cr +#' Can take values 'areave', 'lon', 'lat', 'lonlat'.\cr +#' \itemize{ +#' \item{'areave': Time series of area-averaged variables over the specified domain.} +#' \item{'lon': Time series of meridional averages as a function of longitudes.} +#' \item{'lat': Time series of zonal averages as a function of latitudes.} +#' \item{'lonlat': Time series of 2d fields.} +#' } +#' Takes by default the value 'areave'. If the variable specified in 'var' is +#' a global mean, this parameter is forced to 'areave'.\cr +#' All the loaded data is interpolated into the grid of the first experimental +#' dataset except if 'areave' is selected. In that case the area averages are +#' computed on each dataset original grid. A common grid different than the +#' first experiment's can be specified through the parameter 'grid'. If 'grid' +#' is specified when selecting 'areave' output type, all the loaded data is +#' interpolated into the specified grid before calculating the area averages. +#'@param method This parameter determines the interpolation method to be used +#' when regridding data (see 'output'). Can take values 'bilinear', 'bicubic', +#' 'conservative', 'distance-weighted'.\cr +#' See \code{remapcells} for advanced adjustments.\cr +#' Takes by default the value 'conservative'. +#'@param grid A common grid can be specified through the parameter 'grid' when +#' loading 2-dimensional data. Data is then interpolated onto this grid +#' whichever 'output' type is specified. If the selected output type is +#' 'areave' and a 'grid' is specified, the area averages are calculated after +#' interpolating to the specified grid.\cr +#' If not specified and the selected output type is 'lon', 'lat' or 'lonlat', +#' this parameter takes as default value the grid of the first experimental +#' dataset, which is read automatically from the source files.\cr +#' The grid must be supported by 'cdo' tools. Now only supported: rNXxNY +#' or tTRgrid.\cr +#' Both rNXxNY and tRESgrid yield rectangular regular grids. rNXxNY yields +#' grids that are evenly spaced in longitudes and latitudes (in degrees). +#' tRESgrid refers to a grid generated with series of spherical harmonics +#' truncated at the RESth harmonic. However these spectral grids are usually +#' associated to a gaussian grid, the latitudes of which are spaced with a +#' Gaussian quadrature (not evenly spaced in degrees). The pattern tRESgrid +#' will yield a gaussian grid.\cr +#' E.g., 'r96x72' +#' Advanced: If the output type is 'lon', 'lat' or 'lonlat' and no common +#' grid is specified, the grid of the first experimental or observational +#' dataset is detected and all data is then interpolated onto this grid. +#' If the first experimental or observational dataset's data is found shifted +#' along the longitudes (i.e., there's no value at the longitude 0 but at a +#' longitude close to it), the data is re-interpolated to suppress the shift. +#' This has to be done in order to make sure all the data from all the +#' datasets is properly aligned along longitudes, as there's no option so far +#' in \code{Load} to specify grids starting at longitudes other than 0. +#' This issue doesn't affect when loading in 'areave' mode without a common +#' grid, the data is not re-interpolated in that case. +#'@param maskmod List of masks to be applied to the data of each experimental +#' dataset respectively, if a 2-dimensional variable is specified in 'var'.\cr +#' Each mask can be defined in 2 formats:\cr +#' a) a matrix with dimensions c(longitudes, latitudes).\cr +#' b) a list with the components 'path' and, optionally, 'nc_var_name'.\cr +#' In the format a), the matrix must have the same size as the common grid +#' or with the same size as the grid of the corresponding experimental dataset +#' if 'areave' output type is specified and no common 'grid' is specified.\cr +#' In the format b), the component 'path' must be a character string with the +#' path to a NetCDF mask file, also in the common grid or in the grid of the +#' corresponding dataset if 'areave' output type is specified and no common +#' 'grid' is specified. If the mask file contains only a single variable, +#' there's no need to specify the component 'nc_var_name'. Otherwise it must +#' be a character string with the name of the variable inside the mask file +#' that contains the mask values. This variable must be defined only over 2 +#' dimensions with length greater or equal to 1.\cr +#' Whichever the mask format, a value of 1 at a point of the mask keeps the +#' original value at that point whereas a value of 0 disables it (replaces +#' by a NA value).\cr +#' By default all values are kept (all ones).\cr +#' The longitudes and latitudes in the matrix must be in the same order as in +#' the common grid or as in the original grid of the corresponding dataset +#' when loading in 'areave' mode. You can find out the order of the longitudes +#' and latitudes of a file with 'cdo griddes'.\cr +#' Note that in a common CDO grid defined with the patterns 'tgrid' or +#' 'rx' the latitudes and latitudes are ordered, by definition, from +#' -90 to 90 and from 0 to 360, respectively.\cr +#' If you are loading maps ('lonlat', 'lon' or 'lat' output types) all the +#' data will be interpolated onto the common 'grid'. If you want to specify +#' a mask, you will have to provide it already interpolated onto the common +#' grid (you may use 'cdo' libraries for this purpose). It is not usual to +#' apply different masks on experimental datasets on the same grid, so all +#' the experiment masks are expected to be the same.\cr +#' Warning: When loading maps, any masks defined for the observational data +#' will be ignored to make sure the same mask is applied to the experimental +#' and observational data.\cr +#' Warning: list() compulsory even if loading 1 experimental dataset only!\cr +#' E.g., list(array(1, dim = c(num_lons, num_lats))) +#'@param maskobs See help on parameter 'maskmod'. +#'@param configfile Path to the s2dverification configuration file from which +#' to retrieve information on location in file system (and other) of datasets.\cr +#' If not specified, the configuration file used at BSC-ES will be used +#' (it is included in the package).\cr +#' Check the BSC's configuration file or a template of configuration file in +#' the folder 'inst/config' in the package.\cr +#' Check further information on the configuration file mechanism in +#' \code{ConfigFileOpen()}. +#'@param varmin Loaded experimental and observational data values smaller +#' than 'varmin' will be disabled (replaced by NA values).\cr +#' By default no deactivation is performed. +#'@param varmax Loaded experimental and observational data values greater +#' than 'varmax' will be disabled (replaced by NA values).\cr +#' By default no deactivation is performed. +#'@param silent Parameter to show (FALSE) or hide (TRUE) information messages.\cr +#' Warnings will be displayed even if 'silent' is set to TRUE.\cr +#' Takes by default the value 'FALSE'. +#'@param nprocs Number of parallel processes created to perform the fetch +#' and computation of data.\cr +#' These processes will use shared memory in the processor in which Load() +#' is launched.\cr +#' By default the number of logical cores in the machine will be detected +#' and as many processes as logical cores there are will be created.\cr +#' A value of 1 won't create parallel processes.\cr +#' When running in multiple processes, if an error occurs in any of the +#' processes, a crash message appears in the R session of the original +#' process but no detail is given about the error. A value of 1 will display +#' all error messages in the original and only R session.\cr +#' Note: the parallel process create other blocking processes each time they +#' need to compute an interpolation via 'cdo'. +#'@param dimnames Named list where the name of each element is a generic +#' name of the expected dimensions inside the NetCDF files. These generic +#' names are 'lon', 'lat' and 'member'. 'time' is not needed because it's +#' detected automatically by discard.\cr +#' The value associated to each name is the actual dimension name in the +#' NetCDF file.\cr +#' The variables in the file that contain the longitudes and latitudes of +#' the data (if the data is a 2-dimensional variable) must have the same +#' name as the longitude and latitude dimensions.\cr +#' By default, these names are 'longitude', 'latitude' and 'ensemble. If any +#' of those is defined in the 'dimnames' parameter, it takes priority and +#' overwrites the default value. +#' E.g., list(lon = 'x', lat = 'y') +#' In that example, the dimension 'member' will take the default value 'ensemble'. +#'@param remapcells When loading a 2-dimensional variable, spatial subsets can +#' be requested via \code{lonmin}, \code{lonmax}, \code{latmin} and +#' \code{latmax}. When \code{Load()} obtains the subset it is then +#' interpolated if needed with the method specified in \code{method}.\cr +#' The result of this interpolation can vary if the values surrounding the +#' spatial subset are not present. To better control this process, the width +#' in number of grid cells of the surrounding area to be taken into account +#' can be specified with \code{remapcells}. A value of 0 will take into +#' account no additional cells but will generate less traffic between the +#' storage and the R processes that load data.\cr +#' A value beyond the limits in the data files will be automatically runcated +#' to the actual limit.\cr +#' The default value is 2. +#'@param path_glob_permissive In some cases, when specifying a path pattern +#' (either in the parameters 'exp'/'obs' or in a configuration file) one can +#' specify path patterns that contain shell globbing expressions. Too much +#' freedom in putting globbing expressions in the path patterns can be +#' dangerous and make \code{Load()} find a file in the file system for a +#' start date for a dataset that really does not belong to that dataset. +#' For example, if the file system contains two directories for two different +#' experiments that share a part of their path and the path pattern contains +#' globbing expressions: +#' /experiments/model1/expA/monthly_mean/tos/tos_19901101.nc +#' /experiments/model2/expA/monthly_mean/tos/tos_19951101.nc +#' And the path pattern is used as in the example right below to load data of +#' only the experiment 'expA' of the model 'model1' for the starting dates +#' '19901101' and '19951101', \code{Load()} will undesiredly yield data for +#' both starting dates, even if in fact there is data only for the +#' first one:\cr +#' \code{ +#' expA <- list(path = file.path('/experiments/*/expA/monthly_mean/$VAR_NAME$', +#' '$VAR_NAME$_$START_DATE$.nc') +#' data <- Load('tos', list(expA), NULL, c('19901101', '19951101')) +#' } +#' To avoid these situations, the parameter \code{path_glob_permissive} is +#' set by default to \code{'partial'}, which forces \code{Load()} to replace +#' all the globbing expressions of a path pattern of a data set by fixed +#' values taken from the path of the first found file for each data set, up +#' to the folder right before the final files (globbing expressions in the +#' file name will not be replaced, only those in the path to the file). +#' Replacement of globbing expressions in the file name can also be triggered +#' by setting \code{path_glob_permissive} to \code{FALSE} or \code{'no'}. If +#' needed to keep all globbing expressions, \code{path_glob_permissive} can +#' be set to \code{TRUE} or \code{'yes'}. +#' +#'The two output matrices have between 2 and 6 dimensions:\cr +#' \enumerate{ +#' \item{Number of experimental/observational datasets.} +#' \item{Number of members.} +#' \item{Number of startdates.} +#' \item{Number of leadtimes.} +#' \item{Number of latitudes (optional).} +#' \item{Number of longitudes (optional).} +#' } +#'but the two matrices have the same number of dimensions and only the first +#'two dimensions can have different lengths depending on the input arguments. +#'For a detailed explanation of the process, read the documentation attached +#'to the package or check the comments in the code. +#' +#'@return +#'\code{Load()} returns a named list following a structure similar to the +#'used in the package 'downscaleR'.\cr +#'The components are the following: +#' \itemize{ +#' \item{ +#' 'mod' is the array that contains the experimental data. It has the +#' attribute 'dimensions' associated to a vector of strings with the +#' labels of each dimension of the array, in order. The order of the +#' latitudes is always forced to be from 90 to -90 whereas the order of +#' the longitudes is kept as in the original files (if possible). The +#' longitude values provided in \code{lon} lower than 0 are added 360 +#' (but still kept in the original order). In some cases, however, if +#' multiple data sets are loaded in longitude-latitude mode, the +#' longitudes (and also the data arrays in \code{mod} and \code{obs}) are +#' re-ordered afterwards by \code{Load()} to range from 0 to 360; a +#' warning is given in such cases. The longitude and latitude of the +#' center of the grid cell that corresponds to the value [j, i] in 'mod' +#' (along the dimensions latitude and longitude, respectively) can be +#' found in the outputs \code{lon}[i] and \code{lat}[j] +#' } +#' \item{'obs' is the array that contains the observational data. The +#' same documentation of parameter 'mod' applies to this parameter.} +#' \item{'lat' and 'lon' are the latitudes and longitudes of the centers of +#' the cells of the grid the data is interpolated into (0 if the loaded +#' variable is a global mean or the output is an area average).\cr +#' Both have the attribute 'cdo_grid_des' associated with a character +#' string with the name of the common grid of the data, following the CDO +#' naming conventions for grids.\cr +#' 'lon' has the attributes 'first_lon' and 'last_lon', with the first +#' and last longitude values found in the region defined by 'lonmin' and +#' 'lonmax'. 'lat' has also the equivalent attributes 'first_lat' and +#' 'last_lat'.\cr +#' 'lon' has also the attribute 'data_across_gw' which tells whether the +#' requested region via 'lonmin', 'lonmax', 'latmin', 'latmax' goes across +#' the Greenwich meridian. As explained in the documentation of the +#' parameter 'mod', the loaded data array is kept in the same order as in +#' the original files when possible: this means that, in some cases, even +#' if the data goes across the Greenwich, the data array may not go +#' across the Greenwich. The attribute 'array_across_gw' tells whether +#' the array actually goes across the Greenwich. E.g: The longitudes in +#' the data files are defined to be from 0 to 360. The requested +#' longitudes are from -80 to 40. The original order is kept, hence the +#' longitudes in the array will be ordered as follows: +#' 0, ..., 40, 280, ..., 360. In that case, 'data_across_gw' will be TRUE +#' and 'array_across_gw' will be FALSE.\cr +#' The attribute 'projection' is kept for compatibility with 'downscaleR'. +#' } +#' \item{'Variable' has the following components: +#' \itemize{ +#' \item{'varName', with the short name of the loaded variable as +#' specified in the parameter 'var'. +#' } +#' \item{'level', with information on the pressure level of the +#' variable. Is kept to NULL by now. +#' } +#' } +#' And the following attributes: +#' \itemize{ +#' \item{'is_standard', kept for compatibility with 'downscaleR', +#' tells if a dataset has been homogenized to standards with +#' 'downscaleR' catalogs. +#' } +#' \item{'units', a character string with the units of measure of the +#' variable, as found in the source files. +#' } +#' \item{'longname', a character string with the long name of the +#' variable, as found in the source files. +#' } +#' \item{'daily_agg_cellfun', 'monthly_agg_cellfun', +#' 'verification_time', kept for compatibility with 'downscaleR'. +#' } +#' } +#' } +#' \item{'Datasets' has the following components: +#' \itemize{ +#' \item{'exp', a named list where the names are the identifying +#' character strings of each experiment in 'exp', each associated to +#' a list with the following components: +#' \itemize{ +#' \item{'members', a list with the names of the members of the dataset.} +#' \item{'source', a path or URL to the source of the dataset.} +#' } +#' } +#' \item{'obs', similar to 'exp' but for observational datasets.} +#' } +#' } +#' \item{'Dates', with the follwing components: +#' \itemize{ +#' \item{'start', an array of dimensions (sdate, time) with the POSIX +#' initial date of each forecast time of each starting date. +#' } +#' \item{'end', an array of dimensions (sdate, time) with the POSIX +#' final date of each forecast time of each starting date. +#' } +#' } +#' } +#' \item{'InitializationDates', a vector of starting dates as specified in +#' 'sdates', in POSIX format. +#' } +#' \item{'when', a time stamp of the date the \code{Load()} call to obtain +#' the data was issued. +#' } +#' \item{'source_files', a vector of character strings with complete paths +#' to all the found files involved in the \code{Load()} call. +#' } +#' \item{'not_found_files', a vector of character strings with complete +#' paths to not found files involved in the \code{Load()} call. +#' } +#' } +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr +#'1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Generalisation + parallelisation\cr +#'1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Improvements related to configuration file mechanism\cr +#'1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Added subsetting capabilities\cr +#'@examples +#'# Let's assume we want to perform verification with data of a variable +#'# called 'tos' from a model called 'model' and observed data coming from +#'# an observational dataset called 'observation'. +#'# +#'# The model was run in the context of an experiment named 'experiment'. +#'# It simulated from 1st November in 1985, 1990, 1995, 2000 and 2005 for a +#'# period of 5 years time from each starting date. 5 different sets of +#'# initial conditions were used so an ensemble of 5 members was generated +#'# for each starting date. +#'# The model generated values for the variables 'tos' and 'tas' in a +#'# 3-hourly frequency but, after some initial post-processing, it was +#'# averaged over every month. +#'# The resulting monthly average series were stored in a file for each +#'# starting date for each variable with the data of the 5 ensemble members. +#'# The resulting directory tree was the following: +#'# model +#'# |--> experiment +#'# |--> monthly_mean +#'# |--> tos_3hourly +#'# | |--> tos_19851101.nc +#'# | |--> tos_19901101.nc +#'# | . +#'# | . +#'# | |--> tos_20051101.nc +#'# |--> tas_3hourly +#'# |--> tas_19851101.nc +#'# |--> tas_19901101.nc +#'# . +#'# . +#'# |--> tas_20051101.nc +#'# +#'# The observation recorded values of 'tos' and 'tas' at each day of the +#'# month over that period but was also averaged over months and stored in +#'# a file per month. The directory tree was the following: +#'# observation +#'# |--> monthly_mean +#'# |--> tos +#'# | |--> tos_198511.nc +#'# | |--> tos_198512.nc +#'# | |--> tos_198601.nc +#'# | . +#'# | . +#'# | |--> tos_201010.nc +#'# |--> tas +#'# |--> tas_198511.nc +#'# |--> tas_198512.nc +#'# |--> tas_198601.nc +#'# . +#'# . +#'# |--> tas_201010.nc +#'# +#'# The model data is stored in a file-per-startdate fashion and the +#'# observational data is stored in a file-per-month, and both are stored in +#'# a monthly frequency. The file format is NetCDF. +#'# Hence all the data is supported by Load() (see details and other supported +#'# conventions in ?Load) but first we need to configure it properly. +#'# +#'# These data files are included in the package (in the 'sample_data' folder), +#'# only for the variable 'tos'. They have been interpolated to a very low +#'# resolution grid so as to make it on CRAN. +#'# The original grid names (following CDO conventions) for experimental and +#'# observational data were 't106grid' and 'r180x89' respectively. The final +#'# resolutions are 'r20x10' and 'r16x8' respectively. +#'# The experimental data comes from the decadal climate prediction experiment +#'# run at IC3 in the context of the CMIP5 project. Its name within IC3 local +#'# database is 'i00k'. +#'# The observational dataset used for verification is the 'ERSST' +#'# observational dataset. +#'# +#'# The next two examples are equivalent and show how to load the variable +#'# 'tos' from these sample datasets, the first providing lists of lists to +#'# the parameters 'exp' and 'obs' (see documentation on these parameters) and +#'# the second providing vectors of character strings, hence using a +#'# configuration file. +#'# +#'# The code is not run because it dispatches system calls to 'cdo' which is +#'# not allowed in the examples as per CRAN policies. You can run it on your +#'# system though. +#'# Instead, the code in 'dontshow' is run, which loads the equivalent +#'# already processed data in R. +#'# +#'# Example 1: Providing lists of lists to 'exp' and 'obs': +#'# +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp <- list( +#' name = 'experiment', +#' path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', +#' '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') +#' ) +#'obs <- list( +#' name = 'observation', +#' path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', +#' '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#' ) +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(exp), list(obs), startDates, +#' output = 'areave', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'# +#'# Example 2: Providing vectors of character strings to 'exp' and 'obs' +#'# and using a configuration file. +#'# +#'# The configuration file 'sample.conf' that we will create in the example +#'# has the proper entries to load these (see ?LoadConfigFile for details on +#'# writing a configuration file). +#'# +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' output = 'areave', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#'# +#'# Example 2: providing character strings in 'exp' and 'obs', and providing +#'# a configuration file. +#'# The configuration file 'sample.conf' that we will create in the example +#'# has the proper entries to load these (see ?LoadConfigFile for details on +#'# writing a configuration file). +#'# +#'configfile <- paste0(tempdir(), '/sample.conf') +#'ConfigFileCreate(configfile, confirm = FALSE) +#'c <- ConfigFileOpen(configfile) +#'c <- ConfigEditDefinition(c, 'DEFAULT_VAR_MIN', '-1e19', confirm = FALSE) +#'c <- ConfigEditDefinition(c, 'DEFAULT_VAR_MAX', '1e19', confirm = FALSE) +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp_data_path <- paste0(data_path, '/model/$EXP_NAME$/') +#'obs_data_path <- paste0(data_path, '/$OBS_NAME$/') +#'c <- ConfigAddEntry(c, 'experiments', dataset_name = 'experiment', +#' var_name = 'tos', main_path = exp_data_path, +#' file_path = '$STORE_FREQ$_mean/$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATE$.nc') +#'c <- ConfigAddEntry(c, 'observations', dataset_name = 'observation', +#' var_name = 'tos', main_path = obs_data_path, +#' file_path = '$STORE_FREQ$_mean/$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#'ConfigFileSave(c, configfile, confirm = FALSE) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', c('experiment'), c('observation'), startDates, +#' output = 'areave', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40, configfile = configfile) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'areave', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' +#'@export Load <- function(var, exp = NULL, obs = NULL, sdates, nmember = NULL, nmemberobs = NULL, nleadtime = NULL, leadtimemin = 1, leadtimemax = NULL, storefreq = 'monthly', sampleperiod = 1, diff --git a/R/Mean1Dim.R b/R/Mean1Dim.R index 300b9de4..d8abbfa9 100644 --- a/R/Mean1Dim.R +++ b/R/Mean1Dim.R @@ -1,3 +1,27 @@ +#'Averages An Array Along A Dimension +#' +#'Averages the array along the posdim dimension along the user specified +#'dimension. The user can specify a subset of the dimension to take the mean +#'along. +#' +#'@param var Matrix to average. +#'@param posdim Dimension to average along. +#'@param narm Ignore NA (TRUE) values or not (FALSE). +#'@param limits Limits to average between. Default is to take the mean along +#' the entire dimension. +#' +#'@return Array with one dimension less than the input array, containing +#' the average along the posdim dimension. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-04 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN +#'@examples +#'a <- array(rnorm(24), dim = c(2, 3, 4)) +#'print(a) +#'print(Mean1Dim(a, 2)) +#'@export Mean1Dim <- function(var, posdim, narm = TRUE, limits = NULL) { if (is.null(limits)) { limits <- c(1, dim(var)[posdim]) diff --git a/R/MeanListDim.R b/R/MeanListDim.R index 2a49e002..2b9a2537 100644 --- a/R/MeanListDim.R +++ b/R/MeanListDim.R @@ -1,3 +1,25 @@ +#'Averages An Array Along Multiple Dimensions +#' +#'Averages an array along a set of dimensions given by the argument dims. +#' +#'@param var Input array. +#'@param dims List of dimensions to average along. +#'@param narm Ignore NA (TRUE) values or not (FALSE). +#' +#'@return The averaged array, with the dimensions specified in \code{dims} +#' removed. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-04 (V. Guemas, \email{vguemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN\cr +#'1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Improved memory usage +#'@examples +#'a <- array(rnorm(24), dim = c(2, 3, 4)) +#'print(a) +#'print(Mean1Dim(a, 2)) +#'print(MeanListDim(a, c(2, 3))) +#'@export MeanListDim <- function(var, dims, narm = TRUE) { apply(var, setdiff(c(1:length(dim(var))), dims), mean, na.rm = narm) } diff --git a/R/NAO.R b/R/NAO.R index faccb821..bfafacf8 100644 --- a/R/NAO.R +++ b/R/NAO.R @@ -1,3 +1,122 @@ +#'Computes the North Atlantic Oscillation (NAO) Index +#' +#'Compute the North Atlantic Oscillation (NAO) index based on the leading EOF +#'of the sea level pressure (SLP) anomalies over the north Atlantic region +#'(20N-80N, 80W-40E). The PCs are obtained by projecting the forecast and +#'observed anomalies onto the observed EOF pattern (Pobs) or the forecast +#'anomalies onto the EOF pattern of the other years of the forecast (Pmod). +#'By default (ftime_average = 2:4) NAO() computes the NAO index for 1-month +#'lead seasonal forecasts that can be plotted with BoxPlot(). Returns +#'cross-validated PCs of the NAO index for forecast (ano_exp) and observations +#'(ano_obs) based on the leading EOF pattern. +#' +#'@param ano_exp Array of North Atlantic SLP (20N-80N, 80W-40E) forecast +#' anomalies from \code{Ano()} or \code{Ano_CrossValid()} with dimensions +#' (n. of experimental data sets, n. of ensemble members, n. of start dates, +#' n. of forecast time steps, n. of latitudes, n. of longitudes). If only +#' NAO of observational data needs to be computed, this parameter can be left +#' to NULL (default). +#'@param ano_obs Array of North Atlantic SLP (20N-80N, 80W-40E) observed +#' anomalies from \code{Ano()} or \code{Ano_CrossValid()} with dimensions +#' (n. of observational data sets, n. of obs. ensemble members, +#' n. of start dates, n. of forecast time steps, n. of latitudes, +#' n. of longitudes). If only NAO of experimental data needs to be computed, +#' this parameter can be left to NULL (default). +#'@param lon Vector with the longitudes of \code{ano_exp} and \code{ano_obs}. +#'@param lat Vector with the latitudes of \code{ano_exp} and \code{ano_obs}. +#'@param ftime_average A vector with the forecast time steps to average across +#' defining the target period. Takes by default 2:4, i.e. from 2nd to 4th +#' forecast time steps. +#'@param obsproj \code{obsproj = TRUE} will compute the NAO index by +#' projecting the forecast anomalies onto the leading EOF of observational +#' reference.\cr +#' \code{obsproj = FALSE} will compute the NAO by first computing the leading +#' EOF of the forecast anomalies (in cross-validation mode, i.e. leaving the +#' year you are evaluating out), and then projecting forecast anomalies onto +#' this EOF. +#' +#'@return +#'\itemize{ +#' \item{NAO_exp}{ +#' Array of forecast NAO index in verification format (ensemble members, +#' start dates). +#' } +#' \item{NAO_obs}{ +#' Array of observed NAO index in verification format (1, number of start +#' dates). +#' } +#' \item{EOFs_obs}{ +#' EOFs of the observational references. +#' } +#'} +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2013-08 (F. Lienert, \email{flienert at ic3.cat}) - Original code\cr +#'0.2 - 2014-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Removing the +#' rotation\cr +#'0.3 - 2014-05 (L. Batte, \email{lauriane.batte at ic3.cat}) - Changes to +#' simplify function and add Pobs and Pmod options for NAO projection +#' calculations\cr +#'0.4 - 2015-03 (L. Batte, \email{lauriane.batte at ic3.cat}) - Polarity +#' check and correction is wrong. Switched to have a negative NAO index when the +#' anomaly pattern corresponds to NAO-. +#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - +#' Formatted to CRAN +#'@references +#'Doblas-Reyes, F.J., Pavan, V. and Stephenson, D. (2003). The skill of +#' multi-model seasonal forecasts of the wintertime North Atlantic Oscillation. +#' Climate Dynamics, 21, 501-514. DOI: 10.1007/s00382-003-0350-4 +#' +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 20, latmax = 90, lonmin = -80, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#'# No example data is available over NAO region, so in this example we will +#'# tweak the available data. In a real use case, one can Load() the data over +#'# NAO region directly. +#'sampleData$lon[] <- c(40, 280, 340) +#'attr(sampleData$lon, 'first_lon') <- 280 +#'attr(sampleData$lon, 'last_lon') <- 40 +#'attr(sampleData$lon, 'data_across_gw') <- TRUE +#'sampleData$lat[] <- c(20, 80) +#'attr(sampleData$lat, 'first_lat') <- 20 +#'attr(sampleData$lat, 'last_lat') <- 80 +#' } +#' +#'# Now ready to compute the EOFs and project on, for example, the first +#'# variability mode. +#'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#'# Note that computing the NAO over the region for which there is available +#'# example data is not the full NAO area: NAO() will raise a warning. +#'nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) +#'# Finally plot the NAO index +#'PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", +#' monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") +#' +#'@export NAO <- function(ano_exp = NULL, ano_obs = NULL, lon, lat, ftime_average = 2:4, obsproj = TRUE) { # Checking ano_exp if (!is.null(ano_exp)) { diff --git a/R/Plot2VarsVsLTime.R b/R/Plot2VarsVsLTime.R index b23a25ad..3b5629a1 100644 --- a/R/Plot2VarsVsLTime.R +++ b/R/Plot2VarsVsLTime.R @@ -1,3 +1,87 @@ +#'Plot Two Scores With Confidence Intervals In A Common Plot +#' +#'Plots two input variables having the same dimensions in a common plot.\cr +#'One plot for all experiments.\cr +#'Input variables should have dimensions (nexp/nmod, nltime). +#' +#'@param var1 Matrix of dimensions (nexp/nmod, nltime). +#'@param var2 Matrix of dimensions (nexp/nmod, nltime). +#'@param toptitle Main title, optional. +#'@param ytitle Title of Y-axis, optional. +#'@param monini Starting month between 1 and 12. Default = 1. +#'@param freq 1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12. +#'@param nticks Number of ticks and labels on the x-axis, optional. +#'@param limits c(lower limit, upper limit): limits of the Y-axis, optional. +#'@param listexp List of experiment names, up to three, optional. +#'@param listvars List of names of input variables, optional. +#'@param biglab TRUE/FALSE for presentation/paper plot. Default = FALSE. +#'@param hlines c(a, b, ...) Add horizontal black lines at Y-positions a, b, +#' ...\cr +#' Default: NULL. +#'@param leg TRUE/FALSE if legend should be added or not to the plot. +#' Default = TRUE. +#'@param siglev TRUE/FALSE if significance level should replace confidence +#' interval.\cr +#' Default = FALSE. +#'@param sizetit Multiplicative factor to change title size, optional. +#'@param show_conf TRUE/FALSE to show/not confidence intervals for input +#' variables. +#'@param fileout Name of output file. Extensions allowed: eps/ps, jpeg, png, +#' pdf, bmp and tiff. \cr +#' Default = 'output_plot2varsvsltime.eps' +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +#' lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt +#' smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'Examples of input:\cr +#'------------------\cr +#'\cr +#'RMSE error for a number of experiments and along lead-time: (nexp, nltime) +#' +#'@keywords dynamic +#'@author History:\cr +#'1.0 - 2013-03 (I. Andreu-Burillo, \email{isabel.andreu-burillo@@ic3.cat}) +#' - Original code +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#'dim_to_mean <- 2 # Mean along members +#'required_complete_row <- 3 # Discard start dates that contain NA along lead-times +#'leadtimes_per_startdate <- 60 +#'rms <- RMS(Mean1Dim(smooth_ano_exp, dim_to_mean), +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' compROW = required_complete_row, +#' limits = c(ceiling((runmean_months + 1) / 2), +#' leadtimes_per_startdate - floor(runmean_months / 2))) +#'smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, +#' narm = TRUE), 2, dim(smooth_ano_exp)[2]) +#'spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) +#'Plot2VarsVsLTime(InsertDim(rms[, , , ], 1, 1), spread$sd, +#' toptitle = 'RMSE and spread', monini = 11, freq = 12, +#' listexp = c('CMIP5 IC3'), listvar = c('RMSE', 'spread'), +#' fileout = 'plot2vars.eps') +#' +#'@export Plot2VarsVsLTime <- function(var1, var2, toptitle = '', ytitle = '', monini = 1, freq = 12, nticks = NULL, limits = NULL, listexp = c('exp1', 'exp2', 'exp3'), listvars = c('var1', diff --git a/R/PlotACC.R b/R/PlotACC.R index 3f499e71..9e783016 100644 --- a/R/PlotACC.R +++ b/R/PlotACC.R @@ -1,3 +1,93 @@ +#'Plot Plumes/Timeseries Of Anomaly Correlation Coefficients +#' +#'Plots plumes/timeseries of ACC from an array with dimensions +#'(output from \code{ACC()}): \cr +#'c(nexp, nobs, nsdates, nltime, 4)\cr +#'where the fourth dimension is of length 4 and contains the lower limit of +#'the 95\% confidence interval, the ACC, the upper limit of the 95\% +#'confidence interval and the 95\% significance level given by a one-sided +#'T-test. +#' +#'@param ACC ACC matrix with with dimensions:\cr +#' c(nexp, nobs, nsdates, nltime, 4)\cr +#' with the fourth dimension of length 4 containing the lower limit of the +#' 95\% confidence interval, the ACC, the upper limit of the 95\% confidence +#' interval and the 95\% significance level. +#'@param sdates List of startdates: c('YYYYMMDD','YYYYMMDD'). +#'@param toptitle Main title, optional. +#'@param sizetit Multiplicative factor to scale title size, optional. +#'@param ytitle Title of Y-axis for each experiment: c('',''), optional. +#'@param limits c(lower limit, upper limit): limits of the Y-axis, optional. +#'@param legends List of flags (characters) to be written in the legend, +#' optional. +#'@param freq 1 = yearly, 12 = monthly, 4 = seasonal, ... Default: 12. +#'@param biglab TRUE/FALSE for presentation/paper plot, Default = FALSE. +#'@param fill TRUE/FALSE if filled confidence interval. Default = FALSE. +#'@param linezero TRUE/FALSE if a line at y=0 should be added. Default = FALSE. +#'@param points TRUE/FALSE if points instead of lines. Default = TRUE.\cr +#' Must be TRUE if only 1 leadtime. +#'@param vlines List of x location where to add vertical black lines, optional. +#'@param fileout Name of output file. Extensions allowed: eps/ps, jpeg, png, +#' pdf, bmp and tiff. \cr +#' Default = 'output_PlotACC.eps' +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param \dots Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg fig fin font font.axis font.lab font.main font.sub +#' lend lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page +#' plt smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog\cr +#' For more information about the parameters see `par`. +#' +#'@keywords dynamic +#'@author History:\cr +#'0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) +#'sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'acc <- ACC(Mean1Dim(sampleData$mod, 2), +#' Mean1Dim(sampleData$obs, 2)) +#'PlotACC(acc$ACC, startDates, toptitle = "Anomaly Correlation Coefficient") +#' +#'@export PlotACC <- function(ACC, sdates, toptitle = "", sizetit = 1, ytitle = "", limits = NULL, legends = NULL, freq = 12, biglab = FALSE, fill = FALSE, linezero = FALSE, points = TRUE, vlines = NULL, diff --git a/R/PlotAno.R b/R/PlotAno.R index a302e001..7e904cda 100644 --- a/R/PlotAno.R +++ b/R/PlotAno.R @@ -1,3 +1,76 @@ +#'Plot Raw Or Smoothed Anomalies +#' +#'Plots timeseries of raw or smoothed anomalies of any variable output from +#'\code{Load()} or \code{Ano()} or or \code{Ano_CrossValid()} or +#'\code{Smoothing()}. +#' +#'@param exp_ano Array containing the experimental data:\cr +#' c(nmod/nexp, nmemb/nparam, nsdates, nltime). +#'@param obs_ano Optional matrix containing the observational data:\cr +#' c(nobs, nmemb, nsdates, nltime) +#'@param sdates List of starting dates: c('YYYYMMDD','YYYYMMDD'). +#'@param toptitle Main title for each experiment: c('',''), optional. +#'@param ytitle Title of Y-axis for each experiment: c('',''), optional. +#'@param limits c(lower limit, upper limit): limits of the Y-axis, optional. +#'@param legends List of observational dataset names, optional. +#'@param freq 1 = yearly, 12 = monthly, 4 = seasonal, ... Default: 12. +#'@param biglab TRUE/FALSE for presentation/paper plot. Default = FALSE. +#'@param fill TRUE/FALSE if the spread between members should be filled. +#' Default = TRUE. +#'@param memb TRUE/FALSE if all members/only the ensemble-mean should be +#' plotted.\cr +#' Default = TRUE. +#'@param ensmean TRUE/FALSE if the ensemble-mean should be plotted. +#' Default = TRUE. +#'@param linezero TRUE/FALSE if a line at y=0 should be added. +#' Default = FALSE. +#'@param points TRUE/FALSE if points instead of lines should be shown. +#' Default = FALSE. +#'@param vlines List of x location where to add vertical black lines, optional. +#'@param sizetit Multiplicative factor to scale title size, optional. +#'@param fileout Name of the output file for each experiment: c('',''). +#' Extensions allowed: eps/ps, jpeg, png, pdf, bmp and tiff. If filenames +#' with different extensions are passed, it will be considered only the first +#' one and it will be extended to the rest. \cr +#' Default = c('output1_plotano.eps', 'output2_plotano.eps', +#' 'output3_plotano.eps', 'output4_plotano.eps', +#' 'output5_plotano.eps') +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param \dots Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +#' lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page plt smo +#' srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'@keywords dynamic +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_nb_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) +#'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, +#' toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), +#' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') +#' +#'@export PlotAno <- function(exp_ano, obs_ano = NULL, sdates, toptitle = rep('', 15), ytitle = rep('', 15), limits = NULL, legends = NULL, freq = 12, biglab = FALSE, fill = TRUE, memb = TRUE, diff --git a/R/PlotBoxWhisker.R b/R/PlotBoxWhisker.R index 1bf41ff1..46e9e478 100644 --- a/R/PlotBoxWhisker.R +++ b/R/PlotBoxWhisker.R @@ -1,3 +1,104 @@ +#'Box-And-Whisker Plot of Time Series with Ensemble Distribution +#' +#'Produce time series of box-and-whisker plot showing the distribution of the +#'members of a forecast vs. the observed evolution. The correlation between +#'forecast and observational data is calculated and displayed. Only works for +#'n-monthly to n-yearly time series. +#' +#'@param exp Forecast array of multi-member time series, e.g., the NAO index +#' of one experiment. The expected dimensions are +#' c(members, start dates/forecast horizons). A vector with only the time +#' dimension can also be provided. Only monthly or lower frequency time +#' series are supported. See parameter freq. +#'@param obs Observational vector or array of time series, e.g., the NAO index +#' of the observations that correspond the forecast data in \code{exp}. +#' The expected dimensions are c(start dates/forecast horizons) or +#' c(1, start dates/forecast horizons). Only monthly or lower frequency time +#' series are supported. See parameter freq. +#'@param toptitle Character string to be drawn as figure title. +#'@param ytitle Character string to be drawn as y-axis title. +#'@param monini Number of the month of the first time step, from 1 to 12. +#'@param yearini Year of the first time step. +#'@param freq Frequency of the provided time series: 1 = yearly, 12 = monthly, +# 4 = seasonal, ... Default = 12. +#'@param expname Experimental dataset name. +#'@param obsname Name of the observational reference dataset. +#'@param drawleg TRUE/FALSE: whether to draw the legend or not. +#'@param fileout Name of output file. Extensions allowed: eps/ps, jpeg, png, +#' pdf, bmp and tiff. \cr +#' Default = 'output_PlotBox.ps'. +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' ann ask bg cex.lab cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +#' lheight ljoin lmitre mex mfcol mfrow mfg mkh oma omd omi page pin plt pty +#' smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'@return Generates a file at the path specified via \code{fileout}. +#' +#'@seealso EOF, ProjectField, NAO +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2013-09 (F. Lienert, \email{flienert@@ic3.cat}) - Original code\cr +#'0.2 - 2015-03 (L. Batte, \email{lauriane.batte@@ic3.cat}) - Removed all\cr +#' normalization for sake of clarity. +#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to R CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 20, latmax = 80, +#' lonmin = -80, lonmax = 40) +#'# No example data is available over NAO region, so in this example we will +#'# tweak the available data. In a real use case, one can Load() the data over +#'# NAO region directly. +#'sampleData$lon[] <- c(40, 280, 340) +#'attr(sampleData$lon, 'first_lon') <- 280 +#'attr(sampleData$lon, 'last_lon') <- 40 +#'attr(sampleData$lon, 'data_across_gw') <- TRUE +#'sampleData$lat[] <- c(20, 80) +#'attr(sampleData$lat, 'first_lat') <- 20 +#'attr(sampleData$lat, 'last_lat') <- 80 +#' } +#'# Now ready to compute the EOFs and project on, for example, the first +#'# variability mode. +#'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#'nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) +#'# Finally plot the nao index +#'PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", +#' monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") +#' +#'@export PlotBoxWhisker <- function(exp, obs, toptitle = '', ytitle = '', monini = 1, yearini = 0, freq = 1, expname = "exp 1", obsname = "obs 1", drawleg = TRUE, diff --git a/R/PlotClim.R b/R/PlotClim.R index 7ce30c0d..fbb3c9e1 100644 --- a/R/PlotClim.R +++ b/R/PlotClim.R @@ -1,3 +1,59 @@ +#'Plots Climatologies +#' +#'Plots climatologies as a function of the forecast time for any index output +#'from \code{Clim()} and organized in matrix with dimensions:\cr +#'c(nmod/nexp, nmemb/nparam, nltime) or c(nmod/nexp, nltime) for the +#'experiment data\cr +#'c(nobs, nmemb, nltime) or c(nobs, nltime) for the observational data +#' +#'@param exp_clim Matrix containing the experimental data with dimensions:\cr +#' c(nmod/nexp, nmemb/nparam, nltime) or c(nmod/nexp, nltime) +#'@param obs_clim Matrix containing the observational data (optional) with +#' dimensions:\cr +#' c(nobs, nmemb, nltime) or c(nobs, nltime) +#'@param toptitle Main title, optional. +#'@param ytitle Title of Y-axis, optional. +#'@param monini Starting month between 1 and 12. Default = 1. +#'@param freq 1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12. +#'@param limits c(lower limit, upper limit): limits of the Y-axis, optional. +#'@param listexp List of experiment names, optional. +#'@param listobs List of observational dataset names, optional. +#'@param biglab TRUE/FALSE for presentation/paper plot. Default = FALSE. +#'@param leg TRUE/FALSE to plot the legend or not. +#'@param sizetit Multiplicative factor to scale title size, optional. +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param fileout Name of output file. Extensions allowed: eps/ps, jpeg, png, +#' pdf, bmp and tiff. \cr +#' Default = 'output_plotclim.eps'. +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +#' lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt +#' smo srt tck usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'PlotClim(clim$clim_exp, clim$clim_obs, toptitle = paste('climatologies'), +#' ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') +#' +#'@export PlotClim <- function(exp_clim, obs_clim = NULL, toptitle = '', ytitle = '', monini = 1, freq = 12, limits = NULL, listexp = c('exp1', 'exp2', 'exp3'), diff --git a/R/PlotEquiMap.R b/R/PlotEquiMap.R index 51599dc7..c30e2ca0 100644 --- a/R/PlotEquiMap.R +++ b/R/PlotEquiMap.R @@ -1,3 +1,221 @@ +#'Maps A Two-Dimensional Variable On A Cylindrical Equidistant Projection +#' +#'Map longitude-latitude array (on a regular rectangular or gaussian grid) +#'on a cylindrical equidistant latitude and longitude projection with coloured +#'grid cells. Only the region for which data has been provided is displayed. +#'A colour bar (legend) can be plotted and adjusted. It is possible to draw +#'superimposed arrows, dots, symbols, contour lines and boxes. A number of +#'options is provided to adjust the position, size and colour of the +#'components. This plot function is compatible with figure layouts if colour +#'bar is disabled. +#' +#'@param var Array with the values at each cell of a grid on a regular +#' rectangular or gaussian grid. The array is expected to have two +#' dimensions: c(latitude, longitude). Longitudes can be in ascending or +#' descending order and latitudes in any order. It can contain NA values +#' (coloured with 'colNA'). Arrays with dimensions c(longitude, latitude) +#' will also be accepted but 'lon' and 'lat' will be used to disambiguate so +#' this alternative is not appropriate for square arrays. +#'@param lon Numeric vector of longitude locations of the cell centers of the +#' grid of 'var', in ascending or descending order (same as 'var'). Expected +#' to be regularly spaced, within either of the ranges [-180, 180] or +#' [0, 360]. Data for two adjacent regions split by the limits of the +#' longitude range can also be provided, e.g. \code{lon = c(0:50, 300:360)} +#' ('var' must be provided consitently). +#'@param lat Numeric vector of latitude locations of the cell centers of the +#' grid of 'var', in any order (same as 'var'). Expected to be from a regular +#' rectangular or gaussian grid, within the range [-90, 90]. +#'@param varu Array of the zonal component of wind/current/other field with +#' the same dimensions as 'var'. +#'@param varv Array of the meridional component of wind/current/other field +#' with the same dimensions as 'var'. +#'@param toptitle Top title of the figure, scalable with parameter +#' 'title_scale'. +#'@param sizetit Scale factor for the figure top title provided in parameter +#' 'toptitle'. Deprecated. Use 'title_scale' instead. +#'@param units Title at the top of the colour bar, most commonly the units of +#' the variable provided in parameter 'var'. +#'@param brks,cols,bar_limits,triangle_ends Usually only providing 'brks' is +#' enough to generate the desired colour bar. These parameters allow to +#' define n breaks that define n - 1 intervals to classify each of the values +#' in 'var'. The corresponding grid cell of a given value in 'var' will be +#' coloured in function of the interval it belongs to. These parameters are +#' sent to \code{ColorBar()} to generate the breaks and colours. Additional +#' colours for values beyond the limits of the colour bar are also generated +#' and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are +#' properly provided to do so. See ?ColorBar for a full explanation. +#'@param col_inf,col_sup,colNA Colour identifiers to colour the values in +#' 'var' that go beyond the extremes of the colour bar and to colour NA +#' values, respectively. 'colNA' takes attr(cols, 'na_color') if available by +#' default, where cols is the parameter 'cols' if provided or the vector of +#' colors returned by 'color_fun'. If not available, it takes 'pink' by +#' default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not +#' specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators, +#'triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, +#'bar_tick_scale,bar_extra_margin Set of parameters to control the visual +#' aspect of the drawn colour bar. See ?ColorBar for a full explanation. +#'@param square Logical value to choose either to draw a coloured square for +#' each grid cell in 'var' (TRUE; default) or to draw contour lines and fill +#' the spaces in between with colours (FALSE). In the latter case, +#' 'filled.continents' will take the value FALSE if not specified. +#'@param filled.continents Colour to fill in drawn projected continents. +#' Takes the value gray(0.5) by default or, if 'square = FALSE', takes the +#' value FALSE. If set to FALSE, continents are not filled in. +#'@param coast_color Colour of the coast line of the drawn projected continents. +#' Takes the value gray(0.5) by default. +#'@param coast_width Line width of the coast line of the drawn projected +#' continents. Takes the value 1 by default. +#'@param contours Array of same dimensions as 'var' to be added to the plot +#' and displayed with contours. Parameter 'brks2' is required to define the +#' magnitude breaks for each contour curve. Disregarded if 'square = FALSE'. +#'@param brks2 Vector of magnitude breaks where to draw contour curves for the +#' array provided in 'contours' or if 'square = FALSE'. +#'@param contour_lwd Line width of the contour curves provided via 'contours' +#' and 'brks2', or if 'square = FALSE'. +#'@param contour_color Line color of the contour curves provided via 'contours' +#' and 'brks2', or if 'square = FALSE'. +#'@param contour_lty Line type of the contour curves. Takes 1 (solid) by +#' default. See help on 'lty' in par() for other accepted values. +#'@param contour_label_scale Scale factor for the superimposed labels when +#' drawing contour levels. +#'@param dots Array of same dimensions as 'var' or with dimensions +#' c(n, dim(var)), where n is the number of dot/symbol layers to add to the +#' plot. A value of TRUE at a grid cell will draw a dot/symbol on the +#' corresponding square of the plot. By default all layers provided in 'dots' +#' are plotted with dots, but a symbol can be specified for each of the +#' layers via the parameter 'dot_symbol'. +#'@param dot_symbol Single character/number or vector of characters/numbers +#' that correspond to each of the symbol layers specified in parameter 'dots'. +#' If a single value is specified, it will be applied to all the layers in +#' 'dots'. Takes 15 (centered square) by default. See 'pch' in par() for +#' additional accepted options. +#'@param dot_size Scale factor for the dots/symbols to be plotted, specified +#' in 'dots'. If a single value is specified, it will be applied to all +#' layers in 'dots'. Takes 1 by default. +#'@param arr_subsamp Subsampling factor to select a subset of arrows in +#' 'varu' and 'varv' to be drawn. Only one out of arr_subsamp arrows will +#' be drawn. Takes 1 by default. +#'@param arr_scale Scale factor for drawn arrows from 'varu' and 'varv'. +#' Takes 1 by default. +#'@param arr_ref_len Length of the refence arrow to be drawn as legend at the +#' bottom of the figure (in same units as 'varu' and 'varv', only affects the +#' legend for the wind or variable in these arrays). Defaults to 15. +#'@param arr_units Units of 'varu' and 'varv', to be drawn in the legend. +#' Takes 'm/s' by default. +#'@param arr_scale_shaft Parameter for the scale of the shaft of the arrows +#' (which also depend on the number of figures and the arr_scale parameter). +#' Defaults to 1. +#'@param arr_scale_shaft_angle Parameter for the scale of the angle of the +#' shaft of the arrows (which also depend on the number of figure and the +#' arr_scale parameter). Defaults to 1. +#'@param axelab Whether to draw longitude and latitude axes or not. +#' TRUE by default. +#'@param labW Whether to label the longitude axis with a 'W' instead of minus +#' for negative values. Defaults to FALSE. +#'@param intylat Interval between latitude ticks on y-axis, in degrees. +#' Defaults to 20. +#'@param intxlon Interval between latitude ticks on x-axis, in degrees. +#' Defaults to 20. +#'@param axes_tick_scale Scale factor for the tick lines along the longitude +#' and latitude axes. +#'@param axes_label_scale Scale factor for the labels along the longitude +#' and latitude axes. +#'@param drawleg Whether to plot a color bar (legend, key) or not. Defaults to +#' TRUE. It is not possible to plot the colour bar if 'add = TRUE'. Use +#' ColorBar() and the return values of PlotEquiMap() instead. +#'@param boxlim Limits of a box to be added to the plot, in degrees: +#' c(x1, y1, x2, y2). A list with multiple box specifications can also be +#' provided. +#'@param boxcol Colour of the box lines. A vector with a colour for each of +#' the boxes is also accepted. Defaults to 'purple2'. +#'@param boxlwd Line width of the box lines. A vector with a line width for +#' each of the boxes is also accepted. Defaults to 5. +#'@param margin_scale Scale factor for the margins around the map plot, with +#' the format c(y1, x1, y2, x2). Defaults to rep(1, 4). If drawleg = TRUE, +#' then margin_scale[1] is subtracted 1 unit. +#'@param title_scale Scale factor for the figure top title. Defaults to 1. +#'@param numbfig Number of figures in the layout the plot will be put into. +#' A higher numbfig will result in narrower margins and smaller labels, +#' axe labels, ticks, thinner lines, ... Defaults to 1. +#'@param fileout File where to save the plot. If not specified (default) a +#' graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, +#' bmp and tiff. +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of +#' the corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param \dots Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg font font.axis font.lab font.main font.sub lend +#' lheight ljoin lmitre mex mfcol mfrow mfg mkh omd omi page pch pin plt +#' pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'@return +#'\itemize{ +#' \item{brks}{ +#' Breaks used for colouring the map (and legend if drawleg = TRUE). +#' } +#' \item{cols}{ +#' Colours used for colouring the map (and legend if drawleg = TRUE). Always +#' of length length(brks) - 1. +#' } +#' \item{col_inf}{ +#' Colour used to draw the lower triangle end in the colour bar (NULL if not +#' drawn at all). +#' } +#' \item{col_sup}{ +#' Colour used to draw the upper triangle end in the colour bar (NULL if not +#' drawn at all). +#' } +#'} +#'@keywords dynamic +#'@author History:\cr +#' 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#' 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@@ic3.cat}) - LabW +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN +#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@ic3.cat}) - add winds +#' 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Refactored and added features, +#' and adapted to new ColorBar. +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'PlotEquiMap(sampleData$mod[1, 1, 1, 1, , ], sampleData$lon, sampleData$lat, +#' toptitle = 'Predicted sea surface temperature for Nov 1960 from 1st Nov', +#' sizetit = 0.5) +#' +#'@export PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, toptitle = NULL, sizetit = NULL, units = NULL, brks = NULL, cols = NULL, bar_limits = NULL, diff --git a/R/PlotLayout.R b/R/PlotLayout.R index 0eb1254e..1be60fcf 100644 --- a/R/PlotLayout.R +++ b/R/PlotLayout.R @@ -1,3 +1,206 @@ +#'Arrange and Fill Multi-Pannel Layouts With Optional Colour Bar +#' +#'This function takes an array or list of arrays and loops over each of them +#'to plot all the sub-arrays they contain on an automatically generated +#'multi-pannel layout. A different plot function (not necessarily from +#'s2dverification) can be applied over each of the provided arrays. The input +#'dimensions of each of the functions have to be specified, either with the +#'names or the indices of the corresponding input dimensions. It is possible +#'to draw a common colour bar at any of the sides of the multi-pannel for all +#'the s2dverification plots that use a colour bar. Common plotting arguments +#'for all the arrays in 'var' can be specified via the '...' parameter, and +#'specific plotting arguments for each array can be fully adjusted via +#''special_args'. It is possible to draw titles for each of the figures, +#'layout rows, layout columns and for the whole figure. A number of parameters +#'is provided in order to adjust the position, size and colour of the +#'components. Blank cells can be forced to appear and later be filled in +#'manually with customized plots.\cr +#'This function pops up a blank new device and fills it in, so it cannot be +#'nested in complex layouts. +#' +#'@param fun Plot function (or name of the function) to be called on the +#' arrays provided in 'var'. If multiple arrays are provided in 'var', a +#' vector of as many function names (character strings!) can be provided in +#' 'fun', one for each array in 'var'. +#'@param plot_dims Numeric or character string vector with identifiers of the +#' input plot dimensions of the plot function specified in 'fun'. If +#' character labels are provided, names(dim(var)) or attr('dimensions', var) +#' will be checked to locate the dimensions. As many plots as +#' prod(dim(var)[-plot_dims]) will be generated. If multiple arrays are +#' provided in 'var', 'plot_dims' can be sent a list with a vector of plot +#' dimensions for each. If a single vector is provided, it will be used for +#' all the arrays in 'var'. +#'@param var Multi-dimensional array with at least the dimensions expected by +#' the specified plot function in 'fun'. The dimensions reqired by the +#' function must be specified in 'plot_dims'. The dimensions can be +#' disordered and will be reordered automatically. Dimensions can optionally +#' be labelled in order to refer to them with names in 'plot_dims'. All the +#' available plottable sub-arrays will be automatically plotted and arranged +#' in consecutive cells of an automatically arranged layout. A list of +#' multiple (super-)arrays can be specified. The process will be repeated for +#' each of them, by default applying the same plot function to all of them +#' or, if properly specified in 'fun', a different plot function will be +#' applied to each of them. NAs can be passed to the list: a NA will yield a +#' blank cell in the layout, which can be populated after +#' (see .SwitchToFigure). +#'@param \dots Parameters to be sent to the plotting function 'fun'. If +#' multiple arrays are provided in 'var' and multiple functions are provided +#' in 'fun', the parameters provided through \dots will be sent to all the +#' plot functions, as common parameters. To specify concrete arguments for +#' each of the plot functions see parameter 'special_args'. +#'@param special_args List of sub-lists, each sub-list having specific extra +#' arguments for each of the plot functions provided in 'fun'. If you want to +#' fix a different value for each plot in the layout you can do so by +#' a) splitting your array into a list of sub-arrays (each with the data for +#' one plot) and providing it as parameter 'var', +#' b) providing a list of named sub-lists in 'special_args', where the names +#' of each sub-list match the names of the parameters to be adjusted, and +#' each value in a sub-list contains the value of the corresponding parameter. +#'@param nrow Numeric value to force the number of rows in the automatically +#' generated layout. If higher than the required, this will yield blank cells +#' in the layout (which can then be populated). If lower than the required +#' the function will stop. By default it is configured to arrange the layout +#' in a shape as square as possible. Blank cells can be manually populated +#' after with customized plots (see SwitchTofigure). +#'@param ncol Numeric value to force the number of columns in the +#' automatically generated layout. If higher than the required, this will +#' yield blank cells in the layout (which can then be populated). If lower +#' than the required the function will stop. By default it is configured to +#' arrange the layout in a shape as square as possible. Blank cells can be +#' manually populated after with customized plots (see SwitchTofigure). +#'@param toptitle Topt title for the multi-pannel. Blank by default. +#'@param row_titles Character string vector with titles for each of the rows +#' in the layout. Blank by default. +#'@param col_titles Character string vector with titles for each of the +#' columns in the layout. Blank by default. +#'@param bar_scale Scale factor for the common colour bar. Takes 1 by default. +#'@param title_scale Scale factor for the multi-pannel title. Takes 1 by +#' default. +#'@param title_margin_scale Scale factor for the margins surrounding the top +#' title. Takes 1 by default. +#'@param title_left_shift_scale When plotting row titles, a shift is added +#' to the horizontal positioning of the top title in order to center it to +#' the region of the figures (without taking row titles into account). This +#' shift can be reduced. A value of 0 will remove the shift completely, +#' centering the title to the total width of the device. This parameter will +#' be disregarded if no 'row_titles' are provided. +#'@param subtitle_scale Scale factor for the row titles and column titles +#' (specified in 'row_titles' and 'col_titles'). Takes 1 by default. +#'@param subtitle_margin_scale Scale factor for the margins surrounding the +#' subtitles. Takes 1 by default. +#'@param units Title at the top of the colour bar, most commonly the units of +#' the variable provided in parameter 'var'. +#'@param brks,cols,bar_limits,triangle_ends Usually only providing 'brks' is +#' enough to generate the desired colour bar. These parameters allow to +#' define n breaks that define n - 1 intervals to classify each of the values +#' in 'var'. The corresponding grid cell of a given value in 'var' will be +#' coloured in function of the interval it belongs to. These parameters are +#' sent to \code{ColorBar()} to generate the breaks and colours. Additional +#' colours for values beyond the limits of the colour bar are also generated +#' and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are +#' properly provided to do so. See ?ColorBar for a full explanation. +#'@param col_inf,col_sup Colour identifiers to colour the values in 'var' that +#' go beyond the extremes of the colour bar and to colour NA values, +#' respectively. 'colNA' takes 'white' by default. 'col_inf' and 'col_sup' +#' will take the value of 'colNA' if not specified. See ?ColorBar for a full +#' explanation on 'col_inf' and 'col_sup'. +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators, +#'triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, +#'bar_tick_scale,bar_extra_margin Set of parameters to control the visual +#' aspect of the drawn colour bar. See ?ColorBar for a full explanation. +#'@param drawleg Where to draw the common colour bar. Can take values TRUE, +#' FALSE or:\cr +#' 'up', 'u', 'U', 'top', 't', 'T', 'north', 'n', 'N'\cr +#' 'down', 'd', 'D', 'bottom', 'b', 'B', 'south', 's', 'S' (default)\cr +#' 'right', 'r', 'R', 'east', 'e', 'E'\cr +#' 'left', 'l', 'L', 'west', 'w', 'W' +#'@param titles Character string vector with titles for each of the figures in +#' the multi-pannel, from top-left to bottom-right. Blank by default. +#'@param bar_left_shift_scale When plotting row titles, a shift is added to +#' the horizontal positioning of the colour bar in order to center it to the +#' region of the figures (without taking row titles into account). This shift +#' can be reduced. A value of 0 will remove the shift completely, centering +#' the colour bar to the total width of the device. This parameter will be +#' disregarded if no 'row_titles' are provided. +#'@param extra_margin Extra margins to be added around the layout, in the +#' format c(y1, x1, y2, x2). The units are margin lines. Takes rep(0, 4) +#' by default. +#'@param fileout File where to save the plot. If not specified (default) a +#' graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, +#' bmp and tiff. +#'@param width Width in inches of the multi-pannel. 7 by default, or 11 if +#' 'fielout' has been specified. +#'@param height Height in inches of the multi-pannel. 7 by default, or 11 if +#' 'fileout' has been specified. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of +#' the corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param close_device Whether to close the graphics device after plotting +#' the layout and a 'fileout' has been specified. This is useful to avoid +#' closing the device when saving the layout into a file and willing to add +#' extra elements or figures. Takes TRUE by default. Disregarded if no +#' 'fileout' has been specified. +#' +#'@return +#'\itemize{ +#' \item{brks}{ +#' Breaks used for colouring the map (and legend if drawleg = TRUE). +#' } +#' \item{cols}{ +#' Colours used for colouring the map (and legend if drawleg = TRUE). +#' Always of length length(brks) - 1. +#' } +#' \item{col_inf}{ +#' Colour used to draw the lower triangle end in the colour bar +#' (NULL if not drawn at all). +#' } +#' \item{col_sup}{ +#' Colour used to draw the upper triangle end in the colour bar +#' (NULL if not drawn at all). +#' } +#' \item{layout_matrix}{ +#' Underlying matrix of the layout. Useful to later set any of the layout +#' cells as current figure to add plot elements. See .SwitchToFigure. +#' } +#'} +#'@keywords dynamic +#'@author History:\cr +#' 0.1 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Original code +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'PlotLayout(PlotEquiMap, c('lat', 'lon'), sampleData$mod[1, , 1, 1, , ], +#' sampleData$lon, sampleData$lat, +#' toptitle = 'Predicted tos for Nov 1960 from 1st Nov', +#' titles = paste('Member', 1:15)) +#' +#'@export PlotLayout <- function(fun, plot_dims, var, ..., special_args = NULL, nrow = NULL, ncol = NULL, toptitle = NULL, row_titles = NULL, col_titles = NULL, bar_scale = 1, diff --git a/R/PlotSection.R b/R/PlotSection.R index acefbdd8..0722fd42 100644 --- a/R/PlotSection.R +++ b/R/PlotSection.R @@ -1,3 +1,50 @@ +#'Plots A Vertical Section +#' +#'Plot a (longitude,depth) or (latitude,depth) section. +#' +#'@param var Matrix to plot with (longitude/latitude, depth) dimensions. +#'@param horiz Array of longitudes or latitudes. +#'@param depth Array of depths. +#'@param toptitle Title, optional. +#'@param sizetit Multiplicative factor to increase title size, optional. +#'@param units Units, optional. +#'@param brks Colour levels, optional. +#'@param cols List of colours, optional. +#'@param axelab TRUE/FALSE, label the axis. Default = TRUE. +#'@param intydep Interval between depth ticks on y-axis. Default: 200m. +#'@param intxhoriz Interval between longitude/latitude ticks on x-axis.\cr +#' Default: 20deg. +#'@param drawleg Draw colorbar. Default: TRUE. +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param fileout Name of output file. Extensions allowed: eps/ps, jpeg, png, +#' pdf, bmp and tiff. \cr +#' Default = NULL +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.lab cex.sub cin col.axis col.lab col.main col.sub +#' cra crt csi cxy err family fg fig fin font font.axis font.lab font.main +#' font.sub lend lheight ljoin lmitre lty lwd mex mfcol mfrow mfg mkh oma omd +#' omi page pch pin plt pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs +#' yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'@keywords dynamic +#'@author History:\cr +#'0.1 - 2012-09 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN +#'@examples +#'sampleData <- s2dverification::sampleDepthData +#'PlotSection(sampleData$mod[1, 1, 1, 1, , ], sampleData$lat, sampleData$depth, +#' toptitle = 'temperature 1995-11 member 0') +#'@export PlotSection <- function(var, horiz, depth, toptitle = '', sizetit = 1, units = '', brks = NULL, cols = NULL, axelab = TRUE, intydep = 200, intxhoriz = 20, drawleg = TRUE, diff --git a/R/PlotStereoMap.R b/R/PlotStereoMap.R index f14199e9..81ee27f1 100644 --- a/R/PlotStereoMap.R +++ b/R/PlotStereoMap.R @@ -1,3 +1,150 @@ +#'Maps A Two-Dimensional Variable On A Polar Stereographic Projection +#' +#'Map longitude-latitude array (on a regular rectangular or gaussian grid) on +#'a polar stereographic world projection with coloured grid cells. Only the +#'region within a specified latitude interval is displayed. A colour bar +#'(legend) can be plotted and adjusted. It is possible to draw superimposed +#'dots, symbols and boxes. A number of options is provided to adjust the +#'position, size and colour of the components. This plot function is +#'compatible with figure layouts if colour bar is disabled. +#' +#'@param var Array with the values at each cell of a grid on a regular +#' rectangular or gaussian grid. The array is expected to have two dimensions: +#' c(latitude, longitude). Longitudes can be in ascending or descending order +#' and latitudes in any order. It can contain NA values (coloured with +#' 'colNA'). Arrays with dimensions c(longitude, latitude) will also be +#' accepted but 'lon' and 'lat' will be used to disambiguate so this +#' alternative is not appropriate for square arrays. +#'@param lon Numeric vector of longitude locations of the cell centers of the +#' grid of 'var', in ascending or descending order (same as 'var'). Expected +#' to be regularly spaced, within either of the ranges [-180, 180] or +#' [0, 360]. Data for two adjacent regions split by the limits of the +#' longitude range can also be provided, e.g. \code{lon = c(0:50, 300:360)} +#' ('var' must be provided consitently). +#'@param lat Numeric vector of latitude locations of the cell centers of the +#' grid of 'var', in any order (same as 'var'). Expected to be from a regular +#' rectangular or gaussian grid, within the range [-90, 90]. +#'@param latlims Latitudinal limits of the figure.\cr +#' Example : c(60, 90) for the North Pole\cr +#' c(-90,-60) for the South Pole +#'@param toptitle Top title of the figure, scalable with parameter +#' 'title_scale'. +#'@param sizetit Scale factor for the figure top title provided in parameter +#' 'toptitle'. Deprecated. Use 'title_scale' instead. +#'@param units Title at the top of the colour bar, most commonly the units of +#' the variable provided in parameter 'var'. +#'@param brks,cols,bar_limits,triangle_ends Usually only providing 'brks' is +#' enough to generate the desired colour bar. These parameters allow to +#' define n breaks that define n - 1 intervals to classify each of the values +#' in 'var'. The corresponding grid cell of a given value in 'var' will be +#' coloured in function of the interval it belongs to. These parameters are +#' sent to \code{ColorBar()} to generate the breaks and colours. Additional +#' colours for values beyond the limits of the colour bar are also generated +#' and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are +#' properly provided to do so. See ?ColorBar for a full explanation. +#'@param col_inf,col_sup,colNA Colour identifiers to colour the values in +#' 'var' that go beyond the extremes of the colour bar and to colour NA +#' values, respectively. 'colNA' takes attr(cols, 'na_color') if available by +#' default, where cols is the parameter 'cols' if provided or the vector of +#' colors returned by 'color_fun'. If not available, it takes 'pink' by +#' default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not +#' specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks, +#'draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale, +#'units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control +#' the visual aspect of the drawn colour bar. See ?ColorBar for a +#' full explanation. +#'@param filled.continents Colour to fill in drawn projected continents. Takes +#' the value gray(0.5) by default. If set to FALSE, continents are not +#' filled in. +#'@param coast_color Colour of the coast line of the drawn projected +#' continents. Takes the value gray(0.5) by default. +#'@param coast_width Line width of the coast line of the drawn projected +#' continents. Takes the value 1 by default. +#'@param dots Array of same dimensions as 'var' or with dimensions +#' c(n, dim(var)), where n is the number of dot/symbol layers to add to the +#' plot. A value of TRUE at a grid cell will draw a dot/symbol on the +#' corresponding square of the plot. By default all layers provided in 'dots' +#' are plotted with dots, but a symbol can be specified for each of the +#' layers via the parameter 'dot_symbol'. +#'@param dot_symbol Single character/number or vector of characters/numbers +#' that correspond to each of the symbol layers specified in parameter 'dots'. +#' If a single value is specified, it will be applied to all the layers in +#' 'dots'. Takes 15 (centered square) by default. See 'pch' in par() for +#' additional accepted options. +#'@param dot_size Scale factor for the dots/symbols to be plotted, specified +#' in 'dots'. If a single value is specified, it will be applied to all +#' layers in 'dots'. Takes 1 by default. +#'@param intlat Interval between latitude lines (circles), in degrees. +#' Defaults to 10. +#'@param drawleg Whether to plot a color bar (legend, key) or not. +#' Defaults to TRUE. +#'@param boxlim Limits of a box to be added to the plot, in degrees: +#' c(x1, y1, x2, y2). A list with multiple box specifications can also +#' be provided. +#'@param boxcol Colour of the box lines. A vector with a colour for each of +#' the boxes is also accepted. Defaults to 'purple2'. +#'@param boxlwd Line width of the box lines. A vector with a line width for +#' each of the boxes is also accepted. Defaults to 5. +#'@param margin_scale Scale factor for the margins to be added to the plot, +#' with the format c(y1, x1, y2, x2). Defaults to rep(1, 4). If drawleg = TRUE, +#' margin_scale[1] is subtracted 1 unit. +#'@param title_scale Scale factor for the figure top title. Defaults to 1. +#'@param numbfig Number of figures in the layout the plot will be put into. +#' A higher numbfig will result in narrower margins and smaller labels, +#' axe labels, ticks, thinner lines, ... Defaults to 1. +#'@param fileout File where to save the plot. If not specified (default) a +#' graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, +#' bmp and tiff. +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of +#' the corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param \dots Arguments to be passed to the method. Only accepts the +#' following graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg font font.axis font.lab font.main font.sub lend +#' lheight ljoin lmitre mex mfcol mfrow mfg mkh omd omi page pch pin plt pty +#' smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'@return +#'\itemize{ +#' \item{brks}{ +#' Breaks used for colouring the map (and legend if drawleg = TRUE). +#' } +#' \item{cols}{ +#' Colours used for colouring the map (and legend if drawleg = TRUE). Always +#' of length length(brks) - 1. +#' } +#' \item{col_inf}{ +#' Colour used to draw the lower triangle end in the colour bar (NULL if not +#' drawn at all). +#' } +#' \item{col_sup}{ +#' Colour used to draw the upper triangle end in the colour bar (NULL if not +#' drawn at all). +#' } +#'} +#'@keywords dynamic +#'@author History:\cr +#'1.0 - 2014-07 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#'1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze@@meteo.fr}) - Box(es) drawing +#'1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Refacotred the function and +#' merged in Jean-Philippe circle +#' border and Constantin boxes. +#'@examples +#'data <- matrix(rnorm(100 * 50), 100, 50) +#'x <- seq(from = 0, to = 360, length.out = 100) +#'y <- seq(from = -90, to = 90, length.out = 50) +#'PlotStereoMap(data, x, y, latlims = c(60, 90), brks = 50, +#' toptitle = "This is the title") +#'@export PlotStereoMap <- function(var, lon, lat, latlims = c(60, 90), toptitle = NULL, sizetit = NULL, units = NULL, brks = NULL, cols = NULL, bar_limits = NULL, diff --git a/R/PlotVsLTime.R b/R/PlotVsLTime.R index ff7a37c1..29f16a05 100644 --- a/R/PlotVsLTime.R +++ b/R/PlotVsLTime.R @@ -1,3 +1,100 @@ +#'Plots A Score Along The Forecast Time With Its Confidence Interval +#' +#'Plots The Correlation (\code{Corr()}) or the Root Mean Square Error +#'(\code{RMS()}) between the forecasted values and their observational +#'counterpart or the slopes of their trends (\code{Trend()}) or the +#'InterQuartile Range, Maximum-Mininum, Standard Deviation or Median Absolute +#'Deviation of the Ensemble Members (\code{Spread()}), or the ratio between +#'the Ensemble Spread and the RMSE of the Ensemble Mean (\code{RatioSDRMS()}) +#'along the forecast time for all the input experiments on the same figure +#'with their confidence intervals. +#' +#'@param var Matrix containing any Prediction Score with dimensions:\cr +#' (nexp/nmod, 3/4 ,nltime)\cr +#' or (nexp/nmod, nobs, 3/4 ,nltime). +#'@param toptitle Main title, optional. +#'@param ytitle Title of Y-axis, optional. +#'@param monini Starting month between 1 and 12. Default = 1. +#'@param freq 1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12. +#'@param nticks Number of ticks and labels on the x-axis, optional. +#'@param limits c(lower limit, upper limit): limits of the Y-axis, optional. +#'@param listexp List of experiment names, optional. +#'@param listobs List of observation names, optional. +#'@param biglab TRUE/FALSE for presentation/paper plot. Default = FALSE. +#'@param hlines c(a,b, ..) Add horizontal black lines at Y-positions a,b, ...\cr +#' Default = NULL. +#'@param leg TRUE/FALSE if legend should be added or not to the plot. +#' Default = TRUE. +#'@param siglev TRUE/FALSE if significance level should replace confidence +#' interval.\cr +#' Default = FALSE. +#'@param sizetit Multiplicative factor to change title size, optional. +#'@param show_conf TRUE/FALSE to show/not confidence intervals for input +#' variables. +#'@param fileout Name of output file. Extensions allowed: eps/ps, jpeg, png, +#' pdf, bmp and tiff.\cr +#' Default = 'output_plotvsltime.eps' +#'@param width File width, in the units specified in the parameter size_units +#' (inches by default). Takes 8 by default. +#'@param height File height, in the units specified in the parameter +#' size_units (inches by default). Takes 5 by default. +#'@param size_units Units of the size of the device (file or window) to plot +#' in. Inches ('in') by default. See ?Devices and the creator function of the +#' corresponding device. +#'@param res Resolution of the device (file or window) to plot in. See +#' ?Devices and the creator function of the corresponding device. +#'@param ... Arguments to be passed to the method. Only accepts the following +#' graphical parameters:\cr +#' adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +#' csi cxy err family fg fig font font.axis font.lab font.main font.sub +#' lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt +#' smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +#' For more information about the parameters see `par`. +#' +#'Examples of input:\cr +#'Model and observed output from \code{Load()} then \code{Clim()} then +#'\code{Ano()} then \code{Smoothing()}:\cr +#'(nmod, nmemb, nsdate, nltime) and (nobs, nmemb, nsdate, nltime)\cr +#'then averaged over the members\cr +#'\code{Mean1Dim(var_exp/var_obs, posdim = 2)}:\cr +#'(nmod, nsdate, nltime) and (nobs, nsdate, nltime)\cr +#'then passed through\cr +#' \code{Corr(exp, obs, posloop = 1, poscor = 2)} or\cr +#' \code{RMS(exp, obs, posloop = 1, posRMS = 2)}:\cr +#' (nmod, nobs, 3, nltime)\cr +#'would plot the correlations or RMS between each exp & each obs as a function +#'of the forecast time. +#' +#'@keywords dynamic +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'0.2 - 2013-03 (I. Andreu-Burillo, \email{isabel.andreu-burillo@@ic3.cat}) - Introduced parameter sizetit\cr +#'0.3 - 2013-10 (I. Andreu-Burillo, \email{isabel.andreu-burillo@@ic3.cat}) - Introduced parameter show_conf\cr +#'1.0 - 2013-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#'dim_to_mean <- 2 # Mean along members +#'required_complete_row <- 3 # Discard startdates for which there are NA leadtimes +#'leadtimes_per_startdate <- 60 +#'corr <- Corr(Mean1Dim(smooth_ano_exp, dim_to_mean), +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' compROW = required_complete_row, +#' limits = c(ceiling((runmean_months + 1) / 2), +#' leadtimes_per_startdate - floor(runmean_months / 2))) +#'PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", +#' monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), +#' fileout = 'tos_cor.eps') +#' +#'@export PlotVsLTime <- function(var, toptitle = '', ytitle = '', monini = 1, freq = 12, nticks = NULL, limits = NULL, listexp = c('exp1', 'exp2', 'exp3'), diff --git a/R/ProbBins.R b/R/ProbBins.R index fef21045..e49c27b5 100644 --- a/R/ProbBins.R +++ b/R/ProbBins.R @@ -1,3 +1,73 @@ +#'Computes Probabilistic Information of a Forecast Relative to a Threshold or a Quantile +#' +#'Compute probabilistic bins of a set of forecast years ('fcyr') relative to +#'the forecast climatology over the whole period of anomalies, optionally excluding +#'the selected forecast years ('fcyr') or the forecast year for which the +#'probabilistic bins are being computed (see 'compPeriod'). +#' +#'@param ano Array of anomalies from Ano().\cr +#' Must be of dimension (nexp/nobs, nmemb, nsdates, nleadtime, nlat, nlon) +#'@param fcyr Indices of the forecast years of the anomalies which to compute +#' the probabilistic bins for, or 'all' to compute the bins for all the +#' years.\cr +#' E.g., c(1:5), c(1, 4), 4 or 'all'. +#'@param thr Values used as thresholds to bin the anomalies. +#'@param quantile If quantile is TRUE (default), the threshold ('thr') +#' are quantiles.\cr +#' If quantile is FALSE the thresholds ('thr') introduced are the absolute +#' thresholds of the bins. +#'@param posdates Position of the dimension in \code{ano} that corresponds to +#' the start dates (default = 3). +#'@param posdim Position of the dimension in \code{ano} which will be combined +#' with 'posdates' to compute the quantiles (default = 2, ensemble members). +#'@param compPeriod Three options: +#' "Full period"/"Without fcyr"/"Cross-validation" (The probabilities are +#' computed with the terciles based on ano/ano with all 'fcyr's +#' removed/cross-validation). The default is "Full period". +#' +#'@return Array with probabilistic information and dimensions:\cr +#' c(length('thr') + 1, length(fcyr), nmemb/nparam, nmod/nexp/nobs, +#' nltime, nlat, nlon)\cr +#' The values along the first dimension take values 0 or 1 depending on which +#' of the 'thr'+1 cathegories the forecast/observation at the corresponding +#' grid point, time step, member and starting date belongs to. +#' +#'@keywords datagen +#'@author History:\cr +#'1.0 - 2013 (F.Lienert) - Original code\cr +#'2.0 - 2014-03 (N. Gonzalez and V. Torralba, \email{veronica.torralba@@bsc.es}) - Debugging +#'2.1 - 2017-02 (V. Torralba and N. Manubens, \email{veronica.torralba@@bsc.es}) - Fix bug with cross-validation +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' output = 'lonlat', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'clim <- Clim(sampleMap$mod, sampleMap$obs) +#'ano_exp <- Ano(sampleMap$mod, clim$clim_exp) +#'PB <- ProbBins(ano_exp, fcyr = 3, thr = c(1/3, 2/3), quantile = TRUE, posdates = 3, +#' posdim = 2) +#' +#'@export ProbBins <- function(ano, fcyr = 'all', thr, quantile = TRUE, posdates = 3, posdim = 2, compPeriod = "Full period") { # define dimensions diff --git a/R/ProjectField.R b/R/ProjectField.R index d88fe355..3b5b3ed3 100644 --- a/R/ProjectField.R +++ b/R/ProjectField.R @@ -1,3 +1,100 @@ +#'Project Anomalies onto Modes of Variability +#' +#'Project anomalies onto modes of variability to get the temporal evolution of +#'the EOF mode selected. Returns principal components (PCs) by +#'area-weighted projection onto EOF pattern (from \code{EOF()}). +#'Able to handle NAs. +#' +#'@param ano Array of forecast or observational reference anomalies from +#' \code{Ano()} or \code{Ano_CrossValid} with dimensions (number of forecast +#' systems, ensemble members, start dates, forecast horizons, latitudes, +#' longitudes). +#'@param eof R object with EOFs from \code{EOF}. +#'@param mode Variability mode number in the provided EOF object which to +#' project onto. +#' +#'@return Array of principal components in verification format (number of +#' forecast systems, ensemble members, start dates, forecast horizons). +#' +#'@keywords datagen +#'@seealso EOF, NAO, PlotBoxWhisker +#'@author History:\cr +#'0.1 - 2012-03 (F. Lienert, \email{flienert at ic3.cat} - Original code +#'0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Bug-fixes:\cr +#' 1- Extra weighting of the anomalies before projection.\cr +#' 2- Reversion of the anomalies along latitudes.\cr +#' 3- Extra-normalisation not necessary.\cr +#'0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Bug-fixes:\cr +#' 1- Another extra-normalisation.\cr +#' 2- 15 lines to compute the em reduced to 1. +#'0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Normalization\cr +#'by std before returning PCs to be coherent with EOF().\cr +#'0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Fixes:\cr +#' 1- Removal of lon, lat, ncpu and neofs argument unused\cr +#' 2- Security checks ano and eof consistency\cr +#' 3- Removal of the mask which is already contained in the EOFs\cr +#' 4- Removal of the PC normalization since we have chosen in\cr +#'\code{EOF()} to normalize the EOFs and multiply the PCs by the normalization\cr +#'factor and the eigenvalue so that the restitution of the original field is \cr +#'done simply by PC * EOFs\cr +#' 5 - The new convention in \code{EOF()} is to divide by the weights\cr +#'so that the reconstruction of the original field rather than the weighted\cr +#'field is obtained by PC * EOFs. The EOFs need therefore to be multiplied \cr +#'back by the weights before projection so that EOF * t(EOF) = 1\cr +#' 6 - Since W *X = PC * EOF if EOF is multiplied back by the weights,\cr +#'PC = W * X * t(EOF) and X the input field to be projected (X) needs to be\cr +#'multiplied by W. Getting input dimensions. +#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN +#' (J.-P. Baudouin, \email{jean.baudouin at bsc.es}) - Example code and testing +#' +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'# Now ready to compute the EOFs and project. +#'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#' +#'# Compute the EOF of the observation. +#'eof <- EOF(ano$ano_obs[1, 1, , 1, , ], sampleData$lon, sampleData$lat) +#'# check the first mode represent the NAO +#'PlotEquiMap(eof$EOFs[1, , ], sampleData$lon, sampleData$lat, filled.continents = FALSE) +#' +#'mode1_exp <- ProjectField(ano$ano_exp, eof, 1) +#'mode1_obs <- ProjectField(ano$ano_obs, eof, 1) +#' +#'# Plot the forecast and the observation of the first mode +#'# for the last year of forecast +#'plot(mode1_obs[1, 1, dim(sampleData$mod)[3], ], type = "l", ylim = c(-1, 1), lwd = 2) +#'for (i in 1:dim(sampleData$mod)[2]) { +#' par(new = TRUE) +#' plot(mode1_exp[1, i, dim(sampleData$mod)[3], ], type = "l", col = rainbow(10)[i], +#' ylim = c(-15000, 15000)) +#'} +#' +#'@export ProjectField <- function(ano, eof, mode = 1) { # Checking ano if (!is.numeric(ano) || !is.array(ano)) { diff --git a/R/RMS.R b/R/RMS.R index b45f8cab..e8a2a241 100644 --- a/R/RMS.R +++ b/R/RMS.R @@ -1,3 +1,101 @@ +#'Computes Root Mean Square Error +#' +#'Computes the root mean square error for an array of forecasts, var_exp and +#'an array of observations, var_obs, which should have the same dimensions +#'except along the posloop dimension where the lengths can be different, with +#'the number of experiments/models for var_exp (nexp) and the number of +#'obserational datasets for var_obs (nobs).\cr +#'The RMSE is computed along the posRMS dimension which should correspond to +#'the startdate dimension.\cr +#'If compROW is given, the RMSE is computed only if rows along the compROW +#'dimension are complete between limits[1] and limits[2], i.e. there are no +#'NAs between limits[1] and limits[2]. This option can be activated if the +#'user wishes to account only for the forecasts for which observations are +#'available at all leadtimes.\cr +#'Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr +#'The confidence interval relies on a chi2 distribution.\cr +#'\cr +#'.RMS provides the same functionality but taking a matrix of ensemble +#'members as input (exp). +#' +#'@param var_exp Matrix of experimental data. +#'@param var_obs Matrix of observational data, same dimensions as var_exp +#' except along posloop dimension, where the length can be nobs instead of +#' nexp. +#'@param posloop Dimension nobs and nexp. +#'@param posRMS Dimension along which RMSE are to be computed (the dimension +#' of the start dates). +#'@param compROW Data taken into account only if (compROW)th row is complete.\cr +#' Default = NULL. +#'@param limits Complete between limits[1] & limits[2]. Default = NULL. +#'@param siglev Confidence level of the computed confidence interval. 0.95 +#' by default. +#'@param conf Whether to compute confidence interval or not. TRUE by default. +#'@param exp N by M matrix of N forecasts from M ensemble members. +#'@param obs Vector of the corresponding observations of length N. +#' +#'@return +#'RMS: Array with dimensions:\cr +#'c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 3, all +#' other dimensions of var_exp & var_obs except posRMS).\cr +#'The 3rd dimension corresponds to the lower limit of the 95\% confidence +#' interval (only present if \code{conf = TRUE}), the RMSE, and the upper +#' limit of the 95\% confidence interval (only present if +#' \code{conf = TRUE}).\cr +#'\cr +#'.RMS: +#'\itemize{ +#' \item{$rms}{ +#'The root mean square error, +#' } +#' \item{$conf_low}{ +#'Corresponding to the lower limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. +#' } +#' \item{$conf_high}{ +#'Corresponding to the upper limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. +#' } +#'} +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-05 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#'dim_to_mean <- 2 # Mean along members +#'# Discard start-dates for which some leadtimes are missing +#'required_complete_row <- 3 +#'leadtimes_per_startdate <- 60 +#'rms <- RMS(Mean1Dim(smooth_ano_exp, dim_to_mean), +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' compROW = required_complete_row, +#' limits = c(ceiling((runmean_months + 1) / 2), +#' leadtimes_per_startdate - floor(runmean_months / 2))) +#'PlotVsLTime(rms, toptitle = "Root Mean Square Error", ytitle = "K", +#' monini = 11, limits = NULL, listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, hlines = c(0), +#' fileout = 'tos_rms.eps') +#'# The following example uses veriApply combined with .RMS instead of RMS +#' \dontrun{ +#'require(easyVerification) +#'RMS2 <- s2dverification:::.RMS +#'rms2 <- veriApply("RMS2", +#' smooth_ano_exp, +#' # see ?veriApply for how to use the 'parallel' option +#' Mean1Dim(smooth_ano_obs, dim_to_mean), +#' tdim = 3, ensdim = 2) +#' } +#' +#'@export RMS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, limits = NULL, siglev = 0.95, conf = TRUE) { # diff --git a/R/RMSSS.R b/R/RMSSS.R index 42622477..a88e634c 100644 --- a/R/RMSSS.R +++ b/R/RMSSS.R @@ -1,3 +1,81 @@ +#'Computes Root Mean Square Skill Score +#' +#'Computes the root mean square error skill score between an array of +#'forecasts, var_exp and an array of observations, var_obs, which should +#'have the same dimensions except along posloop where the lengths can be +#'different, with the number of experiments/models for var_exp (nexp) and +#'the number of obserational datasets for var_obs (nobs).\cr +#'RMSSS computes the Root Mean Square Skill Score of each jexp in 1:nexp +#'against each jobs in 1:nobs which gives nexp x nobs RMSSS for each other +#'grid point of the matrix (each latitude/longitude/level/leadtime).\cr +#'The RMSSS are computed along the posRMS dimension which should correspond +#'to the startdate dimension.\cr +#'The p-value is optionally provided by a one-sided Fisher test.\cr +#'\cr +#'.RMSSS provides the same functionality but taking a matrix of ensemble +#'members as input (exp). +#' +#'@param var_exp Array of experimental data. +#'@param var_obs Array of observational data, same dimensions as var_exp +#' except along posloop dimension, where the length can be nobs instead of +#' nexp. +#'@param posloop Dimension nobs and nexp. +#'@param posRMS Dimension along which the RMSE are to be computed (the +#' dimension of the start dates). +#'@param pval Whether to compute or not the p-value of the test Ho : +#' RMSSS = 0. TRUE by default. +#'@param exp N by M matrix of N forecasts from M ensemble members. +#'@param obs Vector of the corresponding observations of length N. +#' +#'@return RMSSS: Array with dimensions:\cr +#'c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, +#' all other dimensions of var_exp & var_obs except posRMS).\cr +#'The 3rd dimension corresponds to the RMSSS and, if \code{pval = TRUE}, +#' the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr +#'\cr +#'.RMSSS: +#'\itemize{ +#' \itemize{ +#' \item{$rmsss}{ +#' The RMSSS. +#' } +#' \item{$p_val}{ +#' Corresponds to the p values (only present if \code{pval = TRUE}) for +#' the RMSSS. +#' } +#' } +#'} +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-04 (V. Guemas, \email{vguemas@@bsc.es}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to R CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@@bsc.es}) - Adapted to veriApply() +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'rmsss <- RMSSS(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) +#'rmsss_plot <- array(dim = c(dim(rmsss)[1:2], 4, dim(rmsss)[4])) +#'rmsss_plot[, , 2, ] <- rmsss[, , 1, ] +#'rmsss_plot[, , 4, ] <- rmsss[, , 2, ] +#'PlotVsLTime(rmsss_plot, toptitle = "Root Mean Square Skill Score", ytitle = "", +#' monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), +#' fileout = 'tos_rmsss.eps') +#'# The following example uses veriApply combined with .RMSSS instead of RMSSS +#' \dontrun{ +#'require(easyVerification) +#'RMSSS2 <- s2dverification:::.RMSSS +#'rmsss2 <- veriApply("RMSSS2", ano_exp, +#' # see ?veriApply for how to use the 'parallel' option +#' Mean1Dim(ano_obs, 2), +#' tdim = 3, ensdim = 2) +#' } +#' +#'@export RMSSS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, pval = TRUE) { # # Enlarge var_exp & var_obs & clim to 10 dim + move posloop & posRMS diff --git a/R/RatioRMS.R b/R/RatioRMS.R index 564f9658..be9355e8 100644 --- a/R/RatioRMS.R +++ b/R/RatioRMS.R @@ -1,3 +1,108 @@ +#'Computes the Ratio Between The RMSE of Two Experiments +#' +#'Calculates the ratio of the RMSE for two forecasts of the same observations.\cr +#'The ratio RMSE(ens, obs) / RMSE(ens.ref, obs) is output.\cr +#'The p-value is provided by a two-sided Fischer test.\cr +#'\cr +#'.RatioRMS provides the same functionality but taking two matrices of +#'ensemble members (ens and ens.ref) as input. +#' +#'@param var_exp1 Array of experimental data 1. +#'@param var_exp2 Array of experimental data 2. +#'@param var_obs Array of observations. +#'@param posRMS Dimension along which the RMSE are to be computed = the +#' position of the start dates. +#'@param pval Whether to compute the p-value of Ho : RMSE1/RMSE2 = 1 or not. +#' TRUE by default. +#'@param exp Matrix of experimental data 1. +#'@param exp_ref Matrix of experimental data 2. +#'@param obs Vector of observations. +#' +#'@return RatioRMS:\cr +#'Matrix with the same dimensions as var_exp1/var_exp2/var_obs except along +#' posRMS where the dimension has length 2 if 'pval = TRUE', or 1 otherwise. +#' The dimension of length 2 corresponds to the ratio between the RMSE +#' (RMSE1/RMSE2) and the p-value of the two-sided Fisher test with Ho: +#' RMSE1/RMSE2 = 1.\cr +#'\cr +#'.RatioRMS:\cr +#' \itemize{ +#' \item{ratiorms}{The ratio of the RMSE of the two experimental datasets} +#' \item{p_val}{The p-value} +#' } +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-11 (V. Guemas, \email{vguemas at bsc.es}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' output = 'lonlat', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'# Compute DJF seasonal means and anomalies. +#'leadtimes_dimension <- 4 +#'initial_month <- 11 +#'mean_start_month <- 12 +#'mean_stop_month <- 2 +#'sampleData$mod <- Season(sampleData$mod, leadtimes_dimension, initial_month, +#' mean_start_month, mean_stop_month) +#'sampleData$obs <- Season(sampleData$obs, leadtimes_dimension, initial_month, +#' mean_start_month, mean_stop_month) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'# Generate two experiments with 2 and 1 members from the only experiment +#'# available in the sample data. Take only data values for a single forecast +#'# time step. +#'ano_exp_1 <- Subset(ano_exp, 'member', c(1, 2)) +#'ano_exp_2 <- Subset(ano_exp, 'member', c(3)) +#'ano_exp_1 <- Subset(ano_exp_1, c('dataset', 'ftime'), list(1, 1), drop = 'selected') +#'ano_exp_2 <- Subset(ano_exp_2, c('dataset', 'ftime'), list(1, 1), drop = 'selected') +#'ano_obs <- Subset(ano_obs, c('dataset', 'ftime'), list(1, 1), drop = 'selected') +#'# Compute ensemble mean and provide as inputs to RatioRMS. +#'rrms <- RatioRMS(Mean1Dim(ano_exp_1, 1), +#' Mean1Dim(ano_exp_2, 1), +#' Mean1Dim(ano_obs, 1)) +#'# Plot the RatioRMS for the first forecast time step. +#'PlotEquiMap(rrms[1, , ], sampleData$lon, sampleData$lat, +#' toptitle = 'Ratio RMSE') +#' +#'# The following example uses veriApply combined with .RatioRMS instead of RatioRMS +#' \dontrun{ +#'require(easyVerification) +#'# The name of the function has to end in 'ss' in order for veriApply() to +#'# detect it as a skill score. +#'RatioRMSss <- s2dverification:::.RatioRMS +#'rrms2 <- veriApply("RatioRMSss", ano_exp_1, +#' # see ?veriApply for how to use the 'parallel' option +#' Mean1Dim(ano_obs, 1), +#' ano_exp_2, +#' tdim = 2, ensdim = 1) +#' } +#' +#'@export RatioRMS <- function(var_exp1, var_exp2, var_obs, posRMS = 1, pval = TRUE) { # # Enlarge var_exps & var_obs to 10 dim + move posRMS to 1st pos diff --git a/R/RatioSDRMS.R b/R/RatioSDRMS.R index 2bce490d..e71595cb 100644 --- a/R/RatioSDRMS.R +++ b/R/RatioSDRMS.R @@ -1,3 +1,74 @@ +#'Computes the ratio between the ensemble spread and RMSE +#' +#'Arrays var_exp & var_obs should have dimensions between\cr +#'c(nmod/nexp, nmemb/nparam, nsdates, nltime)\cr +#'and\cr +#'c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr +#'The ratio between the standard deviation of the members around the ensemble +#'mean in var_exp and the RMSE between var_exp and var_obs is output for each +#'experiment and each observational dataset.\cr +#'The p-value is provided by a one-sided Fischer test.\cr +#'\cr +#'.RatioSDRMS provides the same functionality but taking a matrix of ensemble +#'members as input (exp). +#' +#'@param var_exp Model data:\cr +#' c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to\cr +#' c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#'@param var_obs Observational data:\cr +#' c(nobs, nmemb, nsdates, nltime) up to\cr +#' c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) +#'@param pval Whether to compute the p-value of Ho : SD/RMSE = 1 or not. +#'@param exp N by M matrix of N forecasts from M ensemble members. +#'@param obs Vector of the corresponding observations of length N. +#' +#'@return RatioSDRMS: Array with dimensions c(nexp/nmod, nobs, 1 or 2, nltime) +#' up to c(nexp/nmod, nobs, 1 or 2, nltime, nlevel, nlat, nlon).\cr +#'The 3rd dimension corresponds to the ratio (SD/RMSE) and the p.value +#' (only present if \code{pval = TRUE}) of the one-sided Fisher test with +#'Ho: SD/RMSE = 1.\cr +#'\cr +#'.RatioSDRMS: +#' \itemize{ +#' \item{$ratio}{ +#' The ratio of the ensemble spread and RMSE, +#' } +#' \item{$p_val}{ +#' Corresponds to the p values of the ratio (only present if +#' \code{pval = TRUE}). +#' } +#' } +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-12 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau-manubens at ic3.cat}) - Formatting to CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'rsdrms <- RatioSDRMS(sampleData$mod, sampleData$obs) +#'# Reorder the data in order to plot it with PlotVsLTime +#'rsdrms_plot <- array(dim = c(dim(rsdrms)[1:2], 4, dim(rsdrms)[4])) +#'rsdrms_plot[, , 2, ] <- rsdrms[, , 1, ] +#'rsdrms_plot[, , 4, ] <- rsdrms[, , 2, ] +#'PlotVsLTime(rsdrms_plot, toptitle = "Ratio ensemble spread / RMSE", ytitle = "", +#' monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, siglev = TRUE, +#' fileout = 'tos_rsdrms.eps') +#' +#'# The following example uses veriApply combined with .RatioSDRMS instead of RatioSDRMS +#' \dontrun{ +#'require(easyVerification) +#'RatioSDRMS2 <- s2dverification:::.RatioSDRMS +#'rsdrms2 <- veriApply("RatioSDRMS2", +#' sampleData$mod, +#' # see ?veriApply for how to use the 'parallel' option +#' Mean1Dim(sampleData$obs, 2), +#' tdim = 3, ensdim = 2) +#' } +#' +#'@export RatioSDRMS <- function(var_exp, var_obs, pval = TRUE) { # # Enlarge the number of dimensions of var_exp and var_obs to 7 if necessary diff --git a/R/Regression.R b/R/Regression.R index 2f2aa4c5..c66a4166 100644 --- a/R/Regression.R +++ b/R/Regression.R @@ -1,3 +1,68 @@ +#'Computes The Regression Of An Array On Another Along A Dimension +#' +#'Computes the regression of the input matrice vary on the input matrice varx +#'along the posREG dimension by least square fitting. Provides the slope of +#'the regression, the associated confidence interval, and the intercept.\cr +#'Provides also the vary data filtered out from the regression onto varx.\cr +#'The confidence interval relies on a student-T distribution. +#' +#'@param vary Array of any number of dimensions up to 10. +#'@param varx Array of any number of dimensions up to 10. +#' Same dimensions as vary. +#'@param posREG Position along which to compute the regression. +#' +#'@return +#'\itemize{ +#' \item{$regression}{ +#' Array with same dimensions as varx and vary except along posREG +#' dimension which is replaced by a length 4 dimension, corresponding +#' to the lower limit of the 95\% confidence interval, the slope, +#' the upper limit of the 95\% confidence interval and the intercept. +#' } +#' \item{$filtered}{ +#' Same dimensions as vary filtered out from the regression onto varx +#' along the posREG dimension. +#' } +#'} +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2013-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' output = 'lonlat', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) +#'sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) +#'reg <- Regression(Mean1Dim(sampleData$mod, 2), +#' Mean1Dim(sampleData$obs, 2), 2) +#'PlotEquiMap(reg$regression[1, 2, 1, , ], sampleData$lon, sampleData$lat, +#' toptitle='Regression of the prediction on the observations', +#' sizetit = 0.5) +#' +#'@export Regression <- function(vary, varx, posREG = 2) { # # Enlarge the size of varx and vary to 10 diff --git a/R/SVD.R b/R/SVD.R index 86eb7092..8c5bde83 100644 --- a/R/SVD.R +++ b/R/SVD.R @@ -1,3 +1,106 @@ +#'Single Value Decomposition (Maximum Covariance Analysis) +#' +#'Computes a Maximum Covariance Analysis (MCA) between vary and varx, both +#'of dimensions c(n. of time steps, n. of latitudes, n. of longitudes), each +#'over a region of interest, e.g.: prlr over Europe and tos over North Atlantic. +#'The input fields are latitude-weighted by default (can be adjustable via +#'\code{weight}).\cr +#'Returns a vector of squared covariance fraction (SCFs) explained by +#'each pair of covariability modes, a vector of correlation coefficient +#'(RUVs) between expansion coefficients (ECs) that measures their linear +#'relationship, and a set of regression (MCAs) associated with the +#'covariability modes (ECs). Note that MCAs are 'homogeneous' patterns obtained +#'as regression/correlation between each field (predictor, predictand) +#'and its expansion coefficient.\cr +#'The MCA is computed by default with the covariance matrix. It can be computed +#'with the correlation matrix by setting \code{corr = TRUE}. +#' +#'@param vary Array containing the anomalies field for the predictor. The +#' expected dimensions are c(n. of time steps, n. of latitudes, n. of +#' longitudes). +#'@param varx Array containing the anomalies field for the predictand. The +#' expected dimensions are c(n. of time steps, n. of latitudes, n. of +#' longitudes). +#'@param laty Vector of latitudes of the array \code{vary}. Only required if +#' \code{weight = TRUE}. +#'@param latx Vector of latitudes of the array \code{varx}. Only required if +#' \code{weight = TRUE}. +#'@param nmodes Number of ECs/MCAs/modes retained and provided in the outputs. +#'@param corr Whether to compute the MCA over a covariance matrix (FALSE) or +#' a correlation matrix (TRUE). +#'@param weight Whether to apply latitude weights on the input fields or not. +#' TRUE by default. +#' +#'@return +#'\itemize{ +#' \item{$SC}{ +#'Vector of squared covariance (n. of modes). +#' } +#' \item{$SCFs}{ +#' Vector of squared covariance fractions (n. of modes). +#' } +#' \item{$RUVs}{ +#' Vector of correlations between expansion coefficients (n. of modes). +#' } +#' \item{$ECs_U}{ +#' Array of expansion coefficients of predictor field (n. of time steps, +#' n. of modes). +#' } +#' \item{$MCAs_U}{ +#' Array of covariability patterns of predictor field (c(dim), n. of modes). +#' } +#' \item{$ECs_V}{ +#' Array of expansion coefficients of predictand field (n. of time steps, +#' n. of modes). +#' } +#' \item{$MCAs_V}{ +#' Array of covariability patterns of predictand field (c(dim), n. of modes). +#' } +#'} +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2010-09 (J.-G. Serrano, \email{javier.garcia at bsc.es}) - Original code\cr +#'1.0 - 2016-04 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN +#'@examples +#'# See examples on Load() to understand the first lines in this example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'# This example computes the ECs and MCAs along forecast horizons and plots the +#'# one that explains the greatest amount of variability. The example data is +#'# very low resolution so it does not make a lot of sense. +#'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#'mca <- SVD(Mean1Dim(ano$ano_exp, 2)[1, , 1, , ], +#' Mean1Dim(ano$ano_obs, 2)[1, , 1, , ], +#' sampleData$lat, sampleData$lat) +#'PlotEquiMap(mca$MCAs_U[1, , ], sampleData$lon, sampleData$lat) +#'plot(mca$ECs_U[1, ]) +#'PlotEquiMap(mca$MCAs_V[1, , ], sampleData$lon, sampleData$lat) +#'plot(mca$ECs_V[1, ]) +#' +#'@export SVD <- function(vary, varx, laty = NULL, latx = NULL, nmodes = 15, corr = FALSE, weight = TRUE) { # Checking vary diff --git a/R/Season.R b/R/Season.R index afa4d2da..ac8d7d48 100644 --- a/R/Season.R +++ b/R/Season.R @@ -1,15 +1,26 @@ #'Computes Seasonal Means #' -#'@description Computes seasonal means on timeseries organized in a array of any number of dimensions up to 10 dimensions where the time dimension is one of those 10 dimensions +#'Computes seasonal means on timeseries organized in a array of any number of +#'dimensions up to 10 dimensions where the time dimension is one of those 10 +#'dimensions. #' #'@param var Array containing the timeseries along one of its dimensions. -#'@param posdim Dimension along which to compute seasonal means = Time dimension. -#'@param monini an integer indicating the first month of the time series: 1 to 12. -#'@param moninf an integer indicating the month when to start the seasonal means: 1 to 12. -#'@param monsup an integer indicating the month when to stop the seasonal means: 1 to 12. -#' -#'@return Array with the same dimensions as var except along the posdim dimension whose length corresponds to the number of seasons. Partial seasons are not accounted for. +#'@param posdim Dimension along which to compute seasonal means = Time +#' dimension. +#'@param monini an integer indicating the first month of the time series: 1 to +#' 12. +#'@param moninf an integer indicating the month when to start the seasonal +#' means: 1 to 12. +#'@param monsup an integer indicating the month when to stop the seasonal +#' means: 1 to 12. #' +#'@return Array with the same dimensions as var except along the posdim +#' dimension whose length corresponds to the number of seasons. Partial +#' seasons are not accounted for. +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN #'@examples #'# Load sample data as in Load() example: #'example(Load) diff --git a/R/SelIndices.R b/R/SelIndices.R index 59f0a1af..cbe04c21 100644 --- a/R/SelIndices.R +++ b/R/SelIndices.R @@ -1,3 +1,29 @@ +#'Slices A Matrix Along A Dimension +#' +#'This function selects a subset of ensemble members from an array containing +#'any number of dimensions. +#' +#'@param var An array with any number of dimensions. +#'@param posdim The dimension along which the ensemble subset should be +#' selected. +#'@param limits The lower and upper limits for the selection of ensemble +#' members along the posdim dimension. +#' +#'@return The subsetted array. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-04 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'a <- array(rnorm(24), dim = c(2, 3, 4, 1)) +#'print(a) +#'print(a[, , 2:3, ]) +#'print(dim(a[, , 2:3, ])) +#'print(SelIndices(a, 3, c(2, 3))) +#'print(dim(SelIndices(a, 3, c(2, 3)))) +#' +#'@export SelIndices <- function(var, posdim, limits) { # # A few security checks diff --git a/R/Smoothing.R b/R/Smoothing.R index c93dfc82..e8e3375f 100644 --- a/R/Smoothing.R +++ b/R/Smoothing.R @@ -1,3 +1,38 @@ +#'Smoothes An Array Along A Dimension +#' +#'Smoothes an array of any number of dimensions along one of its dimensions. +#' +#'@param var Array to be smoothed along one of its dimension (typically the +#' forecast time dimension). +#'@param runmeanlen Running mean length in number of sampling units +#' (typically months). +#'@param numdimt Dimension to smooth. +#' +#'@return Array with same the dimensions as 'var' but smoothed along the +#' 'numdimt'-th dimension. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN +#'1.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Adding +#' security checks, fixing computation in cases where runmeanlen is odd and +#' making it able to work on arrays of any number of dimensions. +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, +#' toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", +#' fileout = "tos_smoothed_ano.eps") +#' +#'@export Smoothing <- function(var, runmeanlen = 12, numdimt = 4) { # Check var if (!is.numeric(var)) { diff --git a/R/Spectrum.R b/R/Spectrum.R index 6c5d379d..3e0ef84b 100644 --- a/R/Spectrum.R +++ b/R/Spectrum.R @@ -1,3 +1,40 @@ +#'Estimates Frequency Spectrum +#' +#'This function estimates the frequency spectrum of the xdata array together +#'with its 95\% and 99\% significance level. The output is provided as an +#'array with dimensions c(number of frequencies, 4). The column contains the +#'frequency values, the power, the 95\% significance level and the 99\% one.\cr +#'The spectrum estimation relies on a R built-in function and the significance +#'levels are estimated by a Monte-Carlo method. +#' +#'@param xdata Array of which the frequency spectrum is required. +#' +#'@return Frequency spectrum with dimensions c(number of frequencies, 4). The +#' column contains the frequency values, the power, the 95\% significance +#' level and the 99\% one. +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#' +#'ensmod <- Mean1Dim(sampleData$mod, 2) +#'for (jstartdate in 1:3) { +#' spectrum <- Spectrum(ensmod[1, jstartdate, ]) +#' for (jlen in 1:dim(spectrum)[1]) { +#' if (spectrum[jlen, 2] > spectrum[jlen, 4]) { +#' ensmod[1, jstartdate, ] <- Filter(ensmod[1, jstartdate, ], +#' spectrum[jlen, 1]) +#' } +#' } +#'} +#'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = +#' 'filtered_ensemble_mean.eps') +#' +#'@export Spectrum <- function(xdata) { print('Warning : Your data are assumed to be evenly spaced in time') xdata <- xdata[is.na(xdata) == FALSE] diff --git a/R/Spread.R b/R/Spread.R index 53f59aa0..b25c356d 100644 --- a/R/Spread.R +++ b/R/Spread.R @@ -1,3 +1,82 @@ +#'Computes InterQuartile Range, Maximum-Minimum, Standard Deviation and +#'Median Absolute Deviation of the Ensemble Members +#' +#'Computes the InterQuartile Range, the Maximum minus Mininum, the Standard +#'Deviation and the Median Absolute Deviation along the list of dimensions +#'provided by the posdim argument (typically along the ensemble member and +#'start date dimension).\cr +#'The confidence interval is optionally computed by bootstrapping. +#' +#'@param var Matrix of any number of dimensions up to 10. +#'@param posdim List of dimensions along which to compute IQR/MaxMin/SD/MAD. +#'@param narm TRUE/FALSE if NA removed/kept for computation. Default = TRUE. +#'@param siglev Confidence level of the computed confidence interval. +#' 0.95 by default. +#'@param conf Whether to compute the confidence intervals or not. +#' TRUE by default. +#' +#'Example: +#'-------- +#'To compute IQR, Max-Min, SD & MAD accross the members and start dates of +#'var output from \code{Load()} or \code{Ano()} or \code{Ano_CrossValid()}, +#'call:\cr +#' spread(var, posdim = c(2, 3), narm = TRUE) +#' +#'@return +#'Matrix with the same dimensions as var except along the first posdim +#'dimension which is replaced by a length 1 or 3 dimension, corresponding to +#'the lower limit of the \code{siglev}\% confidence interval +#'(only present if \code{conf = TRUE}), the spread, and the upper limit of +#'the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) +#'for each experiment/leadtime/latitude/longitude. +#' \item{$iqr}{ +#' InterQuartile Range. +#' } +#' \item{$maxmin}{ +#' Maximum - Minimum. +#' } +#' \item{$sd}{ +#' Standard Deviation. +#' } +#' \item{$mad}{ +#' Median Absolute Deviation. +#' } +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'runmean_months <- 12 +#'dim_to_smooth <- 4 # Smooth along lead-times +#'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) +#'smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, +#' narm = TRUE), 2, dim(smooth_ano_exp)[2]) +#'spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) +#'PlotVsLTime(spread$iqr, +#' toptitle = "Inter-Quartile Range between ensemble members", +#' ytitle = "K", monini = 11, limits = NULL, +#' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, +#' hlines = c(0), fileout = 'tos_iqr.eps') +#'PlotVsLTime(spread$maxmin, toptitle = "Maximum minus minimum of the members", +#' ytitle = "K", monini = 11, limits = NULL, +#' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, +#' hlines = c(0), fileout = 'tos_maxmin.eps') +#'PlotVsLTime(spread$sd, toptitle = "Standard deviation of the members", +#' ytitle = "K", monini = 11, limits = NULL, +#' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, +#' hlines = c(0), fileout = 'tos_sd.eps') +#'PlotVsLTime(spread$mad, toptitle = "Median Absolute Deviation of the members", +#' ytitle = "K", monini = 11, limits = NULL, +#' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, +#' hlines = c(0), fileout = 'tos_mad.eps') +#'} +#' +#'@export Spread <- function(var, posdim = 2, narm = TRUE, siglev = 0.95, conf = TRUE) { # # Enlarge the size of var to 10 and move all posdim to first position diff --git a/R/StatSeasAtlHurr.R b/R/StatSeasAtlHurr.R index 73ce6322..43d41b65 100644 --- a/R/StatSeasAtlHurr.R +++ b/R/StatSeasAtlHurr.R @@ -1,3 +1,73 @@ +#'Compute estimate of seasonal mean of Atlantic hurricane activity +#' +#'Compute one of G. Villarini's statistically downscaled measure of mean +#'Atlantic hurricane activity and its variance. The hurricane activity is +#'estimated using seasonal averages of sea surface temperature anomalies over +#'the tropical Atlantic (bounded by 10N-25N and 80W-20W) and the tropics at +#'large (bounded by 30N-30S). The anomalies are for the JJASON season.\cr +#'The estimated seasonal average is either 1) number of hurricanes, 2) number +#'of tropical cyclones with lifetime >=48h or 3) power dissipation index +#'(PDI; in 10^11 m^3 s^{-2}).\cr +#'The statistical models used in this function are described in\cr +#' +#'@param atlano Array of Atlantic sea surface temperature anomalies. +#' Must have the same dimension as tropano. +#'@param tropano Array of tropical sea surface temperature anomalies. +#' Must have the same dimension as atlano. +#'@param hrvar The seasonal average to be estimated. The options are either\cr +#' "HR" (hurricanes) \cr +#' "TC" (tropical cyclones with lifetime >=48h) \cr +#' "PDI" (power dissipation index) \cr +#' +#'@return A list composed of two matrices:\cr +#'\enumerate{ +#' \item{ +#' A matrix (mean) with the seasonal average values of the desired quantity.\cr +#' } +#' \item{ +#' A matrix (var) of the variance of that quantity.\cr +#' } +#'} +#'The dimensions of the two matrices are the same as the dimensions of +#' atlano/tropano. +#' +#'@keywords datagen +#'@references +#'Villarini et al. (2010) Mon Wea Rev, 138, 2681-2705.\cr +#'Villarini et al. (2012) Mon Wea Rev, 140, 44-65.\cr +#'Villarini et al. (2012) J Clim, 25, 625-637.\cr +#'An example of how the function can be used in hurricane forecast studies +#' is given in\cr +#'Caron, L.-P. et al. (2014) Multi-year prediction skill of Atlantic hurricane +#' activity in CMIP5 decadal hindcasts. Climate Dynamics, 42, 2675-2690. +#' doi:10.1007/s00382-013-1773-1. +#'@author History:\cr +#'0.1 - 2015-11 (Louis-Philippe Caron, \email{louis-philippe.caron@@bsc.es}) - Original code +#'@examples +#'# Let AtlAno represents 5 different 5-year forecasts of seasonally averaged +#'# Atlantic sea surface temperature anomalies. +#'AtlAno <- matrix(c(-0.31, -0.36, 0.26, -0.16, -0.16, +#' -0.06, -0.22, -0.31, -0.36, -0.39, +#' 0.20, -0.14, 0.12, 0.22, 0.02, +#' -0.28, 0.26, -0.10, 0.18, 0.33, +#' 0.45, 0.46, 0.04, 0.12, 0.21), +#' nrow = 5, ncol = 5) +#'# Let TropAno represents 5 corresponding 5-year forecasts of seasonally averaged +#'# tropical sea surface temperature anomalies. +#'TropAno <- matrix(c(-0.22, -.13, 0.07, -0.16, -0.15, +#' 0.00, -0.03, -0.22, -0.13, -0.10, +#' 0.07, -0.07, 0.17, 0.10, -0.15, +#' -0.01, 0.08, 0.07, 0.17, 0.13, +#' 0.16, 0.15, -0.09, 0.03, 0.27), +#' nrow = 5, ncol = 5) +#'# The seasonal average of hurricanes for each of the five forecasted years, +#'# for each forecast, would then be given by +#'hr_count <- StatSeasAtlHurr(atlano = AtlAno, +#' tropano = TropAno, +#' hrvar = 'HR') +#'print(hr_count$mean) +#' +#'@export StatSeasAtlHurr <- function(atlano = NULL, tropano = NULL, hrvar = "HR") { # Verify that variables are either TC, HR or PDI. # ----------------------------------------------- diff --git a/R/Subset.R b/R/Subset.R index c82b0c67..7c1e9dcb 100644 --- a/R/Subset.R +++ b/R/Subset.R @@ -1,3 +1,39 @@ +#'Subset a Data Array +#' +#'This function allows to subset (i.e. slice, take a chunk of) an array, in a +#'similar way as done in the function \code{take()} in the package plyr. There +#'are two main inprovements:\cr\cr +#'The input array can have dimension names, either +#'in \code{names(dim(x))} or in the attribute 'dimensions', and the dimensions +#'to subset along can be specified via the parameter \code{along} either with +#'integer indices or either by their name.\cr\cr +#'There are additional ways to adjust which dimensions are dropped in the +#'resulting array: either to drop all, to drop none, to drop only the ones that +#'have been sliced or to drop only the ones that have not been sliced.\cr\cr +#'If an array is provided without dimension names, dimension names taken from +#'the parameter \code{dim_names} will be added to the array. +#' +#'@param x A multidimensional array to be sliced. It can have dimension names +#' either in \code{names(dim(x))} or either in the attribute 'dimensions'. +#'@param along Vector with references to the dimensions to take the subset +#' from: either integers or dimension names. +#'@param indices List of indices to take from each dimension specified in +#' 'along'. If a single dimension is specified in 'along' the indices can be +#' directly provided as a single integer or as a vector. +#'@param drop Whether to drop all the dimensions of length 1 in the resulting +#' array, none, only those that are specified in 'along', or only those that +#' are not specified in 'along'. The possible values are, respectively: 'all' +#' or TRUE, 'none' or FALSE, 'selected', and 'non-selected'. +#' +#'@keywords dplot +#'@examples +#'subset <- Subset(sampleMap$mod, c('dataset', 'sdate', 'ftime'), +#' list(1, 1, 1), drop = 'selected') +#'PlotLayout(PlotEquiMap, c('lat', 'lon'), subset, +#' sampleMap$lon, sampleMap$lat, +#' titles = paste('Member', 1:3)) +#' +#'@export Subset <- function(x, along, indices, drop = FALSE) { # Check x if (!is.array(x)) { diff --git a/R/ToyModel.R b/R/ToyModel.R index c5325ace..0ac6b6f1 100644 --- a/R/ToyModel.R +++ b/R/ToyModel.R @@ -1,3 +1,107 @@ +#'Synthetic forecast generator imitating seasonal to decadal forecasts. The +#'components of a forecast: (1) predictabiltiy (2) forecast error (3) +#'non-stationarity and (4) ensemble generation. The forecast can be computed +#'for real observations or observations generated artifically. +#' +#'The toymodel is based on the model presented in Weigel et al. (2008) QJRS +#'with an extension to consider non-stationary distributions prescribing a +#'linear trend. The toymodel allows to generate an aritifical forecast +#'based on obsevations provided by the input (from Load) or artificially +#'generated observations based on the input parameters (sig, trend). +#'The forecast can be specfied for any number of start-dates, lead-time and +#'ensemble members. It imitates components of a forecast: (1) predictabiltiy +#'(2) forecast error (3) non-stationarity and (4) ensemble generation. +#'The forecast can be computed for real observations or observations generated +#'artifically. +#' +#'@param alpha Predicabiltiy of the forecast on the observed residuals +#' Must be a scalar 0 < alpha < 1. +#'@param beta Standard deviation of forecast error +#' Must be a scalar 0 < beta < 1. +#'@param gamma Factor on the linear trend to sample model uncertainty. Can be +#' a scalar or a vector of scalars -inf < gammay < inf. +#' Defining a scalar results in multiple forecast, corresponding to different +#' models with different trends. +#'@param sig Standard deviation of the residual variability of the forecast. +#' If observations are provided 'sig' is computed from the observations. +#'@param trend Linear trend of the forecast. The same trend is used for each +#' lead-time. If observations are provided the 'trend' is computed from the +#' observations, with potentially different trends for each lead-time. The +#' trend has no unit and needs to be defined according to the time vector +#' [1,2,3,... nstartd]. +#'@param nstartd Number of start-dates of the forecast. +#' If observations are provided the 'nstartd' is computed from the observations. +#'@param nleadt Number of lead-times of the forecats. +#' If observations are provided the 'nleadt' is computed from the observations. +#'@param nmemb Number of members of the forecasts. +#'@param obsini Observations that can be used in the synthetic forecast coming +#' from Load (anomalies are expected). If no observations are provided +#' artifical observations are generated based on Gaussian variaiblity with +#' standard deviation from 'sig' and linear trend from 'trend'. +#'@param fxerr Provides a fixed error of the forecast instead of generating +#' one from the level of beta. This allows to perform pair of forecasts with +#' the same conditional error as required for instance in an attribution context. +#' +#'@return List of forecast with $mod including the forecast and $obs the +#' observations. The dimensions correspond to +#' c(length(gamma), nmemb, nstartd, nleadt) +#' +#'@keywords datagen +#'@author History:\cr +#'1.0 - 2014-08 (O.Bellprat) - Original code +#'1.1 - 2016-02 (O.Bellprat) - Include security check for parameters +#'@examples +#'# Example 1: Generate forecast with artifical observations +#'# Seasonal prediction example +#'a <- 0.1 +#'b <- 0.3 +#'g <- 1 +#'sig <- 1 +#'t <- 0.02 +#'ntd <- 30 +#'nlt <- 4 +#'nm <- 10 +#'toyforecast <- ToyModel(alpha = a, beta = b, gamma = g, sig = sig, trend = t, +#' nstartd = ntd, nleadt = nlt, nmemb = nm) +#' +#'# Example 2: Generate forecast from loaded observations +#'# Decadal prediction example +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' output = 'areave', latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' output = 'areave', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#' +#'a <- 0.1 +#'b <- 0.3 +#'g <- 1 +#'nm <- 10 +#' +#'toyforecast <- ToyModel(alpha = a, beta = b, gamma = g, nmemb = nm, +#' obsini = sampleData$obs, nstartd = 5, nleadt = 60) +#'PlotAno(toyforecast$mod, toyforecast$obs, startDates, +#' toptitle = c("Synthetic decadal temperature prediction"), +#' fileout = "ex_toymodel.eps") +#' +#'@export ToyModel <- function(alpha = 0.1, beta = 0.4, gamma = 1, sig = 1, trend = 0, nstartd = 30, nleadt = 4, nmemb = 10, obsini = NULL, fxerr = NULL) { diff --git a/R/Trend.R b/R/Trend.R index e035df2a..ade3a389 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -1,3 +1,58 @@ +#'Computes the Trend of the Ensemble Mean +#' +#'Computes the trend along the forecast time of the ensemble mean by least +#'square fitting, and the associated error interval.\cr +#'Trend() also provides the time series of the detrended ensemble mean +#'forecasts.\cr +#'The confidence interval relies on a student-T distribution. +#'.Trend provides the same functionality but taking a matrix ensemble members +#'as input (exp). +#' +#'@param var Array of any number of dimensions up to 10. +#'@param exp M by N matrix of M forecasts from N ensemble members. +#'@param interval Number of months/years between 2 points along posTR +#' dimension.\cr +#' Default = 1.\cr +#' The trend would be provided in number of units per month or year. +#'@param siglev Confidence level for the computation of confidence interval. +#' 0.95 by default. +#'@param conf Whether to compute the confidence levels or not. TRUE by default. +#'@param posTR Position along which to compute the trend. +#' +#'@return +#'\item{$trend}{ +#' The intercept and slope coefficients for the least squares fitting of the +#' trend. +#'} +#'\item{$conf.int}{ +#' Corresponding to the limits of the \code{siglev}\% confidence interval +#' (only present if \code{conf = TRUE}) for the slope coefficient. +#'} +#'\item{$detrended}{ +#' Same dimensions as var with linearly detrended var along the posTR +#' dimension. +#'} +#' +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2011-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN\cr +#'2.0 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapt to veriApply() +#'@examples +#'# Load sample data as in Load() example: +#'example(Load) +#'months_between_startdates <- 60 +#'trend <- Trend(sampleData$obs, 3, months_between_startdates) +#'PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K / (5 year)", +#' monini = 11, limits = c(-1,1), listexp = c('CMIP5 IC3'), +#' listobs = c('ERSST'), biglab = FALSE, hlines = 0, +#' fileout = 'tos_obs_trend.eps') +#'PlotAno(trend$detrended, NULL, startDates, +#' toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', +#' legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') +#' +#' +#'@export Trend <- function(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) { # # Enlarge the size of var to 10 and move posTR to first position diff --git a/R/UltimateBrier.R b/R/UltimateBrier.R index 23743b77..92e214da 100644 --- a/R/UltimateBrier.R +++ b/R/UltimateBrier.R @@ -1,3 +1,108 @@ +#'Computes Brier Scores +#' +#'Interface to compute probabilistic scores (Brier Score, Brier Skill Score) +#'from data obtained from s2dverification. +#' +#'@param ano_exp Array of forecast anomalies, as provided by \code{Ano()}. +#' Dimensions c(n. of experimental datasets, n. of members, n. of start dates, +#' n. of forecast time steps, n. of latitudes, n. of longitudes). Dimensions +#' in other orders are also supported. See parameters \code{posdatasets}, +#' \code{posmemb} and \code{posdates}. +#'@param ano_obs Array of observational reference anomalies, as provided by +#' \code{Ano()}. Dimensions c(n. of observational reference datasets, +#' n. of members, n. of start dates, n. of forecast time steps, +#' n. of latitudes, n. of longitudes). Dimensions in other orders are also +#' supported. See parameters \code{posdatasets}, \code{posmemb} and +#' \code{posdates}. +#'@param posdatasets Expected position of dimension corresponding to the +#' different evaluated datasets in input data (ano_exp and ano_obs). +#' By default 1. +#'@param posmemb Expected position of dimension corresponding to members in +#' input data (ano_exp and ano_obs). By default 2. +#'@param posdates Expected position of dimension corresponding to starting +#' dates in input data (ano_exp and ano_obs). By default 3. +#'@param quantile Flag to stipulate whether a quantile (TRUE) or a threshold +#' (FALSE) is used to estimate the forecast and observed probabilities. +#' Takes TRUE by default. +#'@param thr Values to be used as quantiles if 'quantile' is TRUE or as +#' thresholds if 'quantile' is FALSE. Takes by default \code{c(0.05, 0.95)} +#' if 'quantile' is TRUE. +#'@param type Type of score desired. Can take the following values: +#'\itemize{ +#' \item{'BS': Simple Brier Score.} +#' \item{'FairEnsembleBS': Corrected Brier Score computed across ensemble +#' members.} +#' \item{'FairStartDatesBS': Corrected Brier Score computed across starting +#' dates.} +#' \item{'BSS': Simple Brier Skill Score.} +#' \item{'FairEnsembleBSS': Corrected Brier Skill Score computed across +#' ensemble members.} +#' \item{'FairStartDatesBSS': Corrected Brier Skill Score computed across +#' starting dates.} +#'} +#'@param decomposition Flag to determine whether the decomposition of the +#' Brier Score into its components should be provided (TRUE) or not (FALSE). +#' Takes TRUE by default. The decomposition will be computed only if 'type' +#' is 'BS' or 'FairStartDatesBS'. +#'@return +#'If 'type' is 'FairEnsembleBS', 'BSS', 'FairEnsemblesBSS' or +#''FairStartDatesBSS' or 'decomposition' is FALSE and 'type' is 'BS' or +#''FairStartDatesBS', the Brier Score or Brier Skill Score will be returned +#'respectively. +#'If 'decomposition' is TRUE and 'type' is 'BS' or 'FairStartDatesBS' the +#'returned value is a named list with the following entries: +#' \itemize{ +#' \item{'BS': Brier Score.} +#' \item{'REL': Reliability component.} +#' \item{'UNC': Uncertainty component.} +#' \item{'RES': Resolution component.} +#' } +#'The dimensions of each of these arrays will be c(n. of experimental datasets, +#'n. of observational reference datasets, n. of bins, the rest of input +#'dimensions except for the ones pointed by 'posmemb' and 'posdates'). +#'@keywords datagen +#'@author History:\cr +#'0.1 - 2015-05 (V. Guemas \email{virginie.guemas at bsc.es},\cr +#' C. Prodhomme \email{chloe.prodhomme at bsc.es},\cr +#' O. Bellprat \email{omar.bellprat at bsc.es}\cr +#' V. Torralba \email{veronica.torralba at bsc.es}\cr +#' N. Manubens, \email{nicolau.manubens at bsc.es}) - First version +#'@examples +#'# See ?Load for an explanation on the first part of this example. +#' \dontrun{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'expA <- list(name = 'experiment', path = file.path(data_path, +#' 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', +#' '$VAR_NAME$_$START_DATE$.nc')) +#'obsX <- list(name = 'observation', path = file.path(data_path, +#' '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', +#' '$VAR_NAME$_$YEAR$$MONTH$.nc')) +#' +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(expA), list(obsX), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#' \dontshow{ +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), +#' c('observation'), startDates, +#' leadtimemin = 1, +#' leadtimemax = 4, +#' output = 'lonlat', +#' latmin = 27, latmax = 48, +#' lonmin = -12, lonmax = 40) +#' } +#'sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) +#'sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) +#'clim <- Clim(sampleData$mod, sampleData$obs) +#'ano_exp <- Ano(sampleData$mod, clim$clim_exp) +#'ano_obs <- Ano(sampleData$obs, clim$clim_obs) +#'bs <- UltimateBrier(ano_exp, ano_obs) +#'bss <- UltimateBrier(ano_exp, ano_obs, type = 'BSS') +#' +#'@export UltimateBrier <- function(ano_exp, ano_obs, posdatasets = 1, posmemb = 2, posdates = 3, quantile = TRUE, thr = c(5/100, 95/100), type = 'BS', diff --git a/R/clim.palette.R b/R/clim.palette.R index 5673c61d..0e9d24b3 100644 --- a/R/clim.palette.R +++ b/R/clim.palette.R @@ -1,7 +1,31 @@ +#'Generate Climate Color Palettes +#' +#'Generates a colorblind friendly color palette with color ranges useful in +#'climate temperature variable plotting. +#' +#'@param palette Which type of palette to generate: from blue through white +#' to red ('bluered'), from red through white to blue ('redblue'), from +#' yellow through orange to red ('yellowred'), or from red through orange +#' to red ('redyellow'). +#'@param n Number of colors to generate. +#' +#'@keywords datagen +#'@author History:\cr +#'0.0 - 2016-01 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Original code. +#'@examples +#'lims <- seq(-1, 1, length.out = 21) +#' +#'ColorBar(lims, color_fun = clim.palette('redyellow')) +#' +#'cols <- clim.colors(20) +#'ColorBar(lims, cols) +#' +#'@export clim.colors <- function(n, palette = "bluered") { clim.palette(palette)(n) } +#'@export clim.palette <- function(palette = "bluered") { if (palette == "bluered") { colorbar <- colorRampPalette(rev(c("#67001f", "#b2182b", "#d6604d", -- GitLab From 256eaab5f3edfa6a31bbadf3e7c74831c03f3c6b Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 25 Jul 2019 11:31:25 +0200 Subject: [PATCH 31/61] ugfix. --- man/ACC.Rd | 160 +++-- man/Alpha.Rd | 39 +- man/AnimateMap.Rd | 333 ++++----- man/Ano.Rd | 51 +- man/Ano_CrossValid.Rd | 50 +- man/ArrayToNetCDF.Rd | 177 +++-- man/BrierScore.Rd | 116 +-- man/CDORemap.Rd | 164 +++-- man/Clim.Rd | 96 +-- man/Cluster.Rd | 150 ++-- man/ColorBar.Rd | 273 ++++--- man/Composite.Rd | 94 ++- man/ConfigApplyMatchingEntries.Rd | 94 +-- man/ConfigEditDefinition.Rd | 64 +- man/ConfigEditEntry.Rd | 121 ++-- man/ConfigFileOpen.Rd | 271 +++---- man/ConfigShowSimilarEntries.Rd | 123 ++-- man/ConfigShowTable.Rd | 60 +- man/Consist_Trend.Rd | 96 +-- man/Corr.Rd | 178 ++--- man/EOF.Rd | 162 ++--- man/Enlarge.Rd | 31 +- man/Eno.Rd | 64 +- man/EnoNew.Rd | 71 +- man/Filter.Rd | 43 +- man/FitAcfCoef.Rd | 32 +- man/FitAutocor.Rd | 23 +- man/GenSeries.Rd | 24 +- man/Histo2Hindcast.Rd | 92 +-- man/IniListDims.Rd | 38 +- man/InsertDim.Rd | 31 +- man/LeapYear.Rd | 13 +- man/Load.Rd | 1102 ++++++++++++++++++----------- man/Mean1Dim.Rd | 42 +- man/MeanListDim.Rd | 30 +- man/NAO.Rd | 173 ++--- man/Plot2VarsVsLTime.Rd | 192 +++-- man/PlotACC.Rd | 193 +++-- man/PlotAno.Rd | 180 +++-- man/PlotBoxWhisker.Rd | 182 +++-- man/PlotClim.Rd | 152 ++-- man/PlotEquiMap.Rd | 493 +++++++------ man/PlotLayout.Rd | 386 ++++++---- man/PlotSection.Rd | 139 ++-- man/PlotStereoMap.Rd | 318 +++++---- man/PlotVsLTime.Rd | 215 +++--- man/ProbBins.Rd | 111 +-- man/ProjectField.Rd | 109 +-- man/RMS.Rd | 146 ++-- man/RMSSS.Rd | 120 ++-- man/RatioRMS.Rd | 131 ++-- man/RatioSDRMS.Rd | 109 ++- man/Regression.Rd | 87 +-- man/SVD.Rd | 154 ++-- man/Season.Rd | 55 +- man/SelIndices.Rd | 31 +- man/Smoothing.Rd | 40 +- man/Spectrum.Rd | 42 +- man/Spread.Rd | 114 +-- man/StatSeasAtlHurr.Rd | 100 +-- man/Subset.Rd | 57 +- man/ToyModel.Rd | 157 ++-- man/Trend.Rd | 92 +-- man/UltimateBrier.Rd | 169 +++-- man/clim.colors.Rd | 35 + 65 files changed, 4888 insertions(+), 4102 deletions(-) create mode 100644 man/clim.colors.Rd diff --git a/man/ACC.Rd b/man/ACC.Rd index d4d66aec..6441151f 100644 --- a/man/ACC.Rd +++ b/man/ACC.Rd @@ -1,89 +1,91 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ACC.R \name{ACC} \alias{ACC} -\title{ -Computes Anomaly Correlation Coefficient -} -\description{ -Calculates the Anomaly Correlation Coefficient for the ensemble mean of each model and the corresponding references for each startdate and each leadtime.\cr -The domain of interest can be specified by providing the list of longitudes/latitudes (lon/lat) of the grid together with the corners of the domain:\cr -lonlatbox = c(lonmin, lonmax, latmin, latmax) -} +\title{Computes Anomaly Correlation Coefficient} \usage{ -ACC(var_exp, var_obs, lon = NULL, lat = NULL, lonlatbox = NULL, - conf = TRUE, conftype = "parametric", siglev = 0.95) +ACC(var_exp, var_obs, lon = NULL, lat = NULL, lonlatbox = NULL, + conf = TRUE, conftype = "parametric", siglev = 0.95) } \arguments{ - \item{var_exp}{ -Array of experimental anomalies with dimensions:\cr - c(nexp, nsdates, nltimes, nlat, nlon)\cr -or\cr - c(nexp, nsdates, nmembers, nltimes, nlat, nlon)\cr - } - \item{var_obs}{ -Array of observational anomalies, same dimensions as var_exp except along the first dimension and the second if it corresponds to the member dimension. - } - \item{lon}{ -Array of longitudes of the var_exp/var_obs grids, optional. - } - \item{lat}{ -Array of latitudes of the var_exp/var_obs grids, optional. - } - \item{lonlatbox}{ -Domain to select : c(lonmin, lonmax, latmin, latmax), optional. - } - \item{conf}{ -TRUE/FALSE: confidence intervals and significance level provided or not. - } - \item{conftype}{ -"parametric" provides a confidence interval for the ACC computed by a Fisher transformation and a significance level for the ACC from a one-sided student-T distribution.\cr -"bootstrap" provides a confidence interval for the ACC and MACC computed from bootstrapping on the members with 100 drawings with replacement.\cr -To guarantee the statistical robustness of the result, make sure that your experiments/oservations/startdates/leadtimes always have the same number of members. - } - \item{siglev}{ -The confidence level for the computed confidence intervals. - } +\item{var_exp}{Array of experimental anomalies with dimensions: +c(nexp, nsdates, nltimes, nlat, nlon) or +c(nexp, nsdates, nmembers, nltimes, nlat, nlon).} + +\item{var_obs}{Array of observational anomalies, same dimensions as var_exp +except along the first dimension and the second if it corresponds to the +member dimension.} + +\item{lon}{Array of longitudes of the var_exp/var_obs grids, optional.} + +\item{lat}{Array of latitudes of the var_exp/var_obs grids, optional.} + +\item{lonlatbox}{Domain to select: c(lonmin, lonmax, latmin, latmax), +optional.} + +\item{conf}{TRUE/FALSE: confidence intervals and significance level +provided or not.} + +\item{conftype}{"Parametric" provides a confidence interval for the ACC +computed by a Fisher transformation and a significance level for the ACC +from a one-sided student-T distribution. "Bootstrap" provides a confidence +interval for the ACC and MACC computed from bootstrapping on the members +with 100 drawings with replacement. To guarantee the statistical robustness +of the result, make sure that your experiments/oservations/startdates/ +leadtimes always have the same number of members.} + +\item{siglev}{The confidence level for the computed confidence intervals.} } \value{ - \item{ACC}{ -If \code{conf = TRUE}, array with dimensions:\cr - c(nexp, nobs, nsdates, nleadtimes, 4) \cr -The fifth dimension of length 4 corresponds to the lower limit of the \code{siglev}\% confidence interval, the ACC, the upper limit of the \code{siglev}\% confidence interval and the \code{siglev}\% significance level.\cr -If \code{conf = FALSE}, the array of the Anomaly Correlation Coefficient has dimensions:\cr - c(nexp, nobs, nsdates, nleadtimes). - } - \item{MACC}{ -The array of the Mean Anomaly Correlation Coefficient with dimensions:\cr - c(nexp, nobs, nleadtimes) - } +A list of length 2: +\itemize{ + \item\code{$ACC} { + If \code{conf = TRUE}, array with dimensions: + c(nexp, nobs, nsdates, nleadtimes, 4) + The fifth dimension of length 4 corresponds to the lower limit of the + \code{siglev}\% confidence interval, the ACC, the upper limit of the + \code{siglev}\% confidence interval and the \code{siglev}\% significance + level. If \code{conf = FALSE}, the array of the Anomaly Correlation + Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes).} + \item\code{$MACC} { + The array of the Mean Anomaly Correlation Coefficient with dimensions + c(nexp, nobs, nleadtimes).} +} +} +\description{ +Calculates the Anomaly Correlation Coefficient for the ensemble mean of +each model and the corresponding references for each startdate and each +leadtime. The domain of interest can be specified by providing the list +of longitudes/latitudes (lon/lat) of the grid together with the corners +of the domain lonlatbox = c(lonmin, lonmax, latmin, latmax). } - \examples{ # See ?Load for explanations on the first part of this example. - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) clim <- Clim(sampleData$mod, sampleData$obs) @@ -92,17 +94,19 @@ ano_obs <- Ano(sampleData$obs, clim$clim_obs) acc <- ACC(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) PlotACC(acc$ACC, startDates) } -\references{ -Joliffe and Stephenson (2012). Forecast Verification: A Practitioner's Guide in Atmospheric Science. Wiley-Blackwell. -} \author{ -History:\cr -0.1 - 2013-08 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr -1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme at bsc.es}) - optimization\cr -1.2 - 2014-08 (V. Guemas, \email{virginie.guemas at bsc.es}) - Bug-fixes : handling of NA & selection of domain + Simplification of code\cr -1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas at bsc.es}) - Boostrapping over members\cr -1.3.1 - 2014-09 (C. Prodhomme, chloe.prodhomme at bsc.es) - Add comments and minor style changes\cr -1.3.2 - 2015-02 (N. Manubens, nicolau.manubens at bsc.es) - Fixed ACC documentation and examples\cr +History: + 0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN + 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - optimization + 1.2 - 2014-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Bug-fixes: handling of NA & selection of domain + Simplification of code + 1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Boostrapping over members + 1.3.1 - 2014-09 (C. Prodhomme, chloe.prodhomme@bsc.es) - Add comments and minor style changes + 1.3.2 - 2015-02 (N. Manubens, nicolau.manubens@bsc.es) - Fixed ACC documentation and examples +} +\references{ +Joliffe and Stephenson (2012). Forecast Verification: A + Practitioner's Guide in Atmospheric Science. Wiley-Blackwell. } \keyword{datagen} + diff --git a/man/Alpha.Rd b/man/Alpha.Rd index 3cc1eb55..b2992169 100644 --- a/man/Alpha.Rd +++ b/man/Alpha.Rd @@ -1,24 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Alpha.R \name{Alpha} \alias{Alpha} \title{Estimates AutoCorrelation At Lag 1 following Guemas et al, BAMS, 2013b} -\description{This function, relying on the \code{FitAcfCoef()} function, estimates the autocorrelation at lag 1 of the xdata array following the method described in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear detrending and/or a filtering of any frequency peak if requested, the sample autocorrelation is estimated.\cr Then the theoretical autocorrelation of an AR1 is fitted to the sample autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 process. +\usage{ +Alpha(xdata, detrend = FALSE, filter = FALSE) } -\usage{Alpha(xdata, detrend = FALSE, filter = FALSE)} \arguments{ - \item{xdata}{Timeseries from which the autocorrelation at lag 1 is requested.} - \item{detrend}{TRUE applies a linear detrending to xdata prior to the estimation of the autocorrelation at lag 1.} - \item{filter}{TRUE applies a filtering of any frequency peak prior to the estimation of the autocorrelation at lag 1.} +\item{xdata}{Timeseries from which the autocorrelation at lag 1 is requested.} + +\item{detrend}{TRUE applies a linear detrending to xdata prior to the +estimation of the autocorrelation at lag 1.} + +\item{filter}{TRUE applies a filtering of any frequency peak prior to the +estimation of the autocorrelation at lag 1.} +} +\value{ +Autocorrelation at lag 1. +} +\description{ +This function, relying on the \code{FitAcfCoef()} function, estimates the +autocorrelation at lag 1 of the xdata array following the method described +in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear +detrending and/or a filtering of any frequency peak if requested, the sample +autocorrelation is estimated. +Then the theoretical autocorrelation of an AR1 is fitted to the sample +autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to +obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 +process. } -\value{Autocorrelation at lag 1} \examples{ # Load sample data as in Load() example: example(Load) alpha <- Alpha(sampleData$mod[1, 1, , 1]) print(alpha) + } \author{ -History:\cr -0.1 - 2012-06 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +History: + 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/AnimateMap.Rd b/man/AnimateMap.Rd index 3376a685..a3576608 100644 --- a/man/AnimateMap.Rd +++ b/man/AnimateMap.Rd @@ -1,184 +1,162 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/AnimateMap.R \name{AnimateMap} \alias{AnimateMap} \title{Animate Maps of Forecast/Observed Values or Scores Over Forecast Time} -\description{ -Create animations of maps in an equi-rectangular or stereographic projection, -showing the anomalies, the climatologies, the mean InterQuartile Range, -Maximum-Mininum, Standard Deviation, Median Absolute Deviation, the trends, -the RMSE, the correlation or the RMSSS, between modelled and observed data -along the forecast time (lead-time) for all input experiments and input -observational datasets. -} \usage{ -AnimateMap(var, lon, lat, toptitle = rep("", 11), sizetit = 1, units = "", - monini = 1, freq = 12, msk95lev = FALSE, brks = NULL, cols = NULL, - filled.continents = FALSE, lonmin = 0, lonmax = 360, latmin = -90, - latmax = 90, intlon = 20, intlat = 30, drawleg = TRUE, - subsampleg = 1, colNA='white', equi = TRUE, - fileout = c("output1_animvsltime.gif", "output2_animvsltime.gif", - "output3_animvsltime.gif"), ...) +AnimateMap(var, lon, lat, toptitle = rep("", 11), sizetit = 1, units = "", + monini = 1, freq = 12, msk95lev = FALSE, brks = NULL, cols = NULL, + filled.continents = FALSE, lonmin = 0, lonmax = 360, latmin = -90, + latmax = 90, intlon = 20, intlat = 30, drawleg = TRUE, + subsampleg = 1, colNA = "white", equi = TRUE, + fileout = c("output1_animvsltime.gif", "output2_animvsltime.gif", + "output3_animvsltime.gif"), ...) } \arguments{ - \item{var}{ -Matrix of dimensions (nltime, nlat, nlon) - or (nexp/nmod, nltime, nlat, nlon) - or (nexp/nmod, 3/4, nltime, nlat, nlon) - or (nexp/nmod, nobs, 3/4, nltime, nlat, nlon) - } - \item{lat}{ -Vector containing latitudes (degrees) - } - \item{lon}{ -Vector containing longtitudes (degrees) - } - \item{toptitle}{ -c('','', \dots) array of main title for each animation, optional. -If RMS, RMSSS, correlations: first exp with successive obs, then second exp -with successive obs, etc ... - } - \item{sizetit}{ -Multiplicative factor to increase title size, optional - } - \item{units}{ -Units, optional - } - \item{monini}{ -Starting month between 1 and 12. Default = 1 - } - \item{freq}{ -1 = yearly, 12 = monthly, 4 = seasonal ... - } - \item{msk95lev}{ -TRUE/FALSE grid points with dots if 95\% significance level reached. -Default = FALSE - } - \item{brks}{ -Limits of colour levels, optional. For example: -seq(min(var), max(var), (max(var) - min(var)) / 10) - } - \item{cols}{ -Vector of colours of length(brks) - 1, optional. - } - \item{filled.continents}{ -Continents filled in grey (TRUE) or represented by a black line (FALSE). -Default = TRUE. -Filling unavailable if crossing Greenwich and equi = TRUE. -Filling unavailable if square = FALSE and equi = TRUE. - } - \item{lonmin}{ -Westward limit of the domain to plot (> 0 or < 0). -Default : 0 degrees - } - \item{lonmax}{ -Eastward limit of the domain to plot (> 0 or < 0). -lonmax > lonmin. Default : 360 degrees - } - \item{latmin}{ -Southward limit of the domain to plot. Default : -90 degrees - } - \item{latmax}{ -Northward limit of the domain to plot. Default : 90 degrees - } - \item{intlat}{ -Interval between latitude ticks on y-axis for equi = TRUE -or between latitude circles for equi = FALSE. Default = 30 degrees. - } - \item{intlon}{ -Interval between longitude ticks on x-axis. Default = 20 degrees. - } - \item{drawleg}{ -Draw a colorbar. Can be FALSE only if square = FALSE or equi = FALSE. -Default = TRUE - } - \item{subsampleg}{ -Supsampling factor of the interval between ticks on colorbar. -Default = 1 = every colour level. - } - \item{colNA}{ -Color used to represent NA. Default = 'white' - } - \item{equi}{ -TRUE/FALSE == cylindrical equidistant/stereographic projection. -Default: TRUE - } - \item{fileout}{ -c('', '', \dots) array of output file name for each animation. -If RMS, RMSSS, correlations : first exp with successive obs, then second exp -with successive obs, etc ... - } - \item{...}{ -Arguments to be passed to the method. Only accepts the following -graphical parameters: - -adj ann ask bty cex cex.axis cex.lab cex.main cex.sub cin col.axis col.lab -col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab -font.main font.sub las lheight ljoin lmitre lty lwd mai mar mex mfcol mfrow mfg -mgp mkh oma omd omi page pch plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog -xpd yaxp yaxs yaxt ylbias ylog - -For more information about the parameters see `par`. - } -} -\details{ -Examples of input: +\item{var}{Matrix of dimensions (nltime, nlat, nlon) or +(nexp/nmod, nltime, nlat, nlon) or (nexp/nmod, 3/4, nltime, nlat, nlon) or +(nexp/nmod, nobs, 3/4, nltime, nlat, nlon).} + +\item{lon}{Vector containing longtitudes (degrees).} + +\item{lat}{Vector containing latitudes (degrees).} + +\item{toptitle}{c('','', \dots) array of main title for each animation, +optional. If RMS, RMSSS, correlations: first exp with successive obs, then +second exp with successive obs, etc ...} + +\item{sizetit}{Multiplicative factor to increase title size, optional.} + +\item{units}{Units, optional.} + +\item{monini}{Starting month between 1 and 12. Default = 1.} + +\item{freq}{1 = yearly, 12 = monthly, 4 = seasonal ...} + +\item{msk95lev}{TRUE/FALSE grid points with dots if 95\% significance level +reached. Default = FALSE.} + +\item{brks}{Limits of colour levels, optional. For example: +seq(min(var), max(var), (max(var) - min(var)) / 10).} + +\item{cols}{Vector of colours of length(brks) - 1, optional.} + +\item{filled.continents}{Continents filled in grey (TRUE) or represented by +a black line (FALSE). Default = TRUE. Filling unavailable if crossing +Greenwich and equi = TRUE. Filling unavailable if square = FALSE and +equi = TRUE.} + +\item{lonmin}{Westward limit of the domain to plot (> 0 or < 0). +Default : 0 degrees.} -1- Outputs from clim (exp, obs, memb = FALSE): - (nmod, nltime, nlat, nlon) - or (nobs, nltime, nlat, nlon) - -2- Model output from load/ano/smoothing: - (nmod, nmemb, sdate, nltime, nlat, nlon) -then passed through spread(var, posdim = 2, narm = TRUE) - & mean1dim(var, posdim = 3, narm = TRUE) -or through trend(mean1dim(var, 2), posTR = 2): - (nmod, 3, nltime, nlat, nlon) -animates average along start dates of IQR/MaxMin/SD/MAD across members -or trends of the ensemble-mean computed accross the start dates. - -3- model and observed output from load/ano/smoothing: - (nmod, nmemb, sdate, nltime, nlat, nlon) - & (nobs, nmemb, sdate, nltime, nlat, nlon) -then averaged along members mean1dim(var_exp/var_obs, posdim = 2): - (nmod, sdate, nltime, nlat, nlon) - (nobs, sdate, nltime, nlat, nlon) -then passed through corr(exp, obs, posloop = 1, poscor = 2) - or RMS(exp, obs, posloop = 1, posRMS = 2): - (nmod, nobs, 3, nltime, nlat, nlon) -animates correlations or RMS between each exp & each obs against leadtime. +\item{lonmax}{Eastward limit of the domain to plot (> 0 or < 0). +lonmax > lonmin. Default : 360 degrees.} + +\item{latmin}{Southward limit of the domain to plot. Default : -90 degrees.} + +\item{latmax}{Northward limit of the domain to plot. Default : 90 degrees.} + +\item{intlon}{Interval between longitude ticks on x-axis. +Default = 20 degrees.} + +\item{intlat}{Interval between latitude ticks on y-axis for equi = TRUE or +between latitude circles for equi = FALSE. Default = 30 degrees.} + +\item{drawleg}{Draw a colorbar. Can be FALSE only if square = FALSE or +equi = FALSE. Default = TRUE.} + +\item{subsampleg}{Supsampling factor of the interval between ticks on +colorbar. Default = 1 = every colour level.} + +\item{colNA}{Color used to represent NA. Default = 'white'.} + +\item{equi}{TRUE/FALSE == cylindrical equidistant/stereographic projection. +Default: TRUE.} + +\item{fileout}{c('', '', \dots) array of output file name for each animation. + If RMS, RMSSS, correlations : first exp with successive obs, then second +exp with successive obs, etc ...} + +\item{...}{Arguments to be passed to the method. Only accepts the following + graphical parameters: adj ann ask bty cex cex.axis cex.lab cex.main cex.sub + cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig + font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty + lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo + srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. + For more information about the parameters see `par`. + +Examples of input: +\enumerate{ + \item{ + Outputs from clim (exp, obs, memb = FALSE): + (nmod, nltime, nlat, nlon) + or (nobs, nltime, nlat, nlon) + } + \item{ + Model output from load/ano/smoothing: + (nmod, nmemb, sdate, nltime, nlat, nlon) + then passed through spread(var, posdim = 2, narm = TRUE) + & mean1dim(var, posdim = 3, narm = TRUE) + or through trend(mean1dim(var, 2), posTR = 2): + (nmod, 3, nltime, nlat, nlon) + animates average along start dates of IQR/MaxMin/SD/MAD across members + or trends of the ensemble-mean computed accross the start dates. + } + \item{ + model and observed output from load/ano/smoothing: + (nmod, nmemb, sdate, nltime, nlat, nlon) + & (nobs, nmemb, sdate, nltime, nlat, nlon) + then averaged along members mean1dim(var_exp/var_obs, posdim = 2): + (nmod, sdate, nltime, nlat, nlon) + (nobs, sdate, nltime, nlat, nlon) + then passed through corr(exp, obs, posloop = 1, poscor = 2) + or RMS(exp, obs, posloop = 1, posRMS = 2): + (nmod, nobs, 3, nltime, nlat, nlon) + animates correlations or RMS between each exp & each obs against leadtime. + } +}} +} +\description{ +Create animations of maps in an equi-rectangular or stereographic +projection, showing the anomalies, the climatologies, the mean InterQuartile +Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, +the trends, the RMSE, the correlation or the RMSSS, between modelled and +observed data along the forecast time (lead-time) for all input experiments +and input observational datasets. } \examples{ # See ?Load for explanations on the first part of this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - output = 'lonlat', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } - \dontshow{ + output = 'lonlat', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } clim <- Clim(sampleData$mod, sampleData$obs, memb = FALSE) - \dontrun{ + \dontrun{ AnimateMap(clim$clim_exp, sampleData$lon, sampleData$lat, - toptitle = "climatology of decadal prediction", sizetit = 1, - units = "degree", brks = seq(270, 300, 3), monini = 11, freq = 12, - msk95lev = FALSE, filled.continents = TRUE, intlon = 10, intlat = 10, - fileout = 'clim_dec.gif') - } + toptitle = "climatology of decadal prediction", sizetit = 1, + units = "degree", brks = seq(270, 300, 3), monini = 11, freq = 12, + msk95lev = FALSE, filled.continents = TRUE, intlon = 10, intlat = 10, + fileout = 'clim_dec.gif') + } ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) leadtimes_dimension <- 4 @@ -186,29 +164,30 @@ initial_month <- 11 mean_start_month <- 1 mean_stop_month <- 12 season_means_mod <- Season(ano_exp, leadtimes_dimension, initial_month, - mean_start_month, mean_stop_month) + mean_start_month, mean_stop_month) season_means_obs <- Season(ano_obs, leadtimes_dimension, initial_month, - mean_start_month, mean_stop_month) - \dontrun{ + mean_start_month, mean_stop_month) + \dontrun{ AnimateMap(Mean1Dim(season_means_mod, 2)[1, 1, , , ], sampleData$lon, - sampleData$lat, toptitle = "Annual anomalies 1985 of decadal prediction", - sizetit = 1, units = "degree", monini = 1, freq = 1, msk95lev = FALSE, - brks = seq(-0.5, 0.5, 0.1), intlon = 10, intlat = 10, - filled.continents = TRUE, fileout = 'annual_means_dec.gif') - } + sampleData$lat, toptitle = "Annual anomalies 1985 of decadal prediction", + sizetit = 1, units = "degree", monini = 1, freq = 1, msk95lev = FALSE, + brks = seq(-0.5, 0.5, 0.1), intlon = 10, intlat = 10, + filled.continents = TRUE, fileout = 'annual_means_dec.gif') + } dim_to_mean <- 2 # Mean along members rms <- RMS(Mean1Dim(season_means_mod, dim_to_mean), - Mean1Dim(season_means_obs, dim_to_mean)) + Mean1Dim(season_means_obs, dim_to_mean)) AnimateMap(rms, sampleData$lon, sampleData$lat, toptitle = - "RMSE decadal prediction", sizetit = 1, units = "degree", - monini = 1, freq = 1, msk95lev = FALSE, brks = seq(0, 0.8, 0.08), - intlon = 10, intlat = 10, filled.continents = TRUE, - fileout = 'rmse_dec.gif') + "RMSE decadal prediction", sizetit = 1, units = "degree", + monini = 1, freq = 1, msk95lev = FALSE, brks = seq(0, 0.8, 0.08), + intlon = 10, intlat = 10, filled.continents = TRUE, + fileout = 'rmse_dec.gif') } \author{ -History:\cr -1.0 - 2012-04 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr -1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr -1.2 - 2015-05 (V. Guemas, \email{virginie.guemas at bsc.es}) - Use of PlotEquiMap and PlotStereoMap\cr +History: + 1.0 - 2012-04 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code + 1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN + 1.2 - 2015-05 (V. Guemas, \email{virginie.guemas@bsc.es}) - Use of PlotEquiMap and PlotStereoMap } \keyword{dynamic} + diff --git a/man/Ano.Rd b/man/Ano.Rd index 9614813f..7d21a2a8 100644 --- a/man/Ano.Rd +++ b/man/Ano.Rd @@ -1,32 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Ano.R \name{Ano} \alias{Ano} \title{Computes Forecast or Observed Anomalies} -\description{ -This function computes anomalies from any experimental or observational matrix output from \code{Load()} and their climatologies output from \code{Clim()}. +\usage{ +Ano(var, clim) } -\usage{Ano(var, clim)} \arguments{ - \item{var}{ -Model or observational data:\cr - c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to\cr - c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) - } - \item{clim}{ -Climatologies from clim:\cr - c(nmod/nexp/nobs, nltime) up to\cr - c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon)\cr -or\cr - c(nmod/nexp/nobs, nmemb/nparam, nltime) up to\cr - c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon)\cr -or\cr - c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to\cr - c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr -depending on the options provided to \code{Clim()} - } +\item{var}{Model or observational data: +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)} + +\item{clim}{Climatologies from clim: c(nmod/nexp/nobs, nltime) +up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or +c(nmod/nexp/nobs, nmemb/nparam, nltime) up to +c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +depending on the options provided to \code{Clim()}.} } \value{ Array with same dimensions as 'var'. } +\description{ +This function computes anomalies from any experimental or observational +matrix output from \code{Load()} and their climatologies output from +\code{Clim()}. +} \examples{ # Load sample data as in Load() example: example(Load) @@ -38,12 +38,13 @@ dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, - toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), - legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') + toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), + legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') } \author{ -History:\cr -0.1 - 2012-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN +History: + 0.1 - 2012-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN } \keyword{datagen} + diff --git a/man/Ano_CrossValid.Rd b/man/Ano_CrossValid.Rd index 7e488ca2..4d516922 100644 --- a/man/Ano_CrossValid.Rd +++ b/man/Ano_CrossValid.Rd @@ -1,43 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Ano_CrossValid.R \name{Ano_CrossValid} \alias{Ano_CrossValid} \title{Computes Anomalies In Cross-Validation Mode} -\description{ -Computes the anomalies from the arrays of the experimental and observational data output from \code{load()} by subtracting the climatologies computed with a cross-validation technique and a per-pair method. -} \usage{ Ano_CrossValid(var_exp, var_obs, memb = TRUE) } \arguments{ - \item{var_exp}{ -Model data:\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) - } - \item{var_obs}{ -Observational data:\cr - c(nobs, nmemb, nsdates, nltime) up to\cr - c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) - } - \item{memb}{ -memb: TRUE/FALSE (1 climatology for each member/1 climatology averaging all the members).\cr -Default = TRUE. - } +\item{var_exp}{Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to +c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon).} + +\item{var_obs}{Observational data: c(nobs, nmemb, nsdates, nltime) up to +c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon).} + +\item{memb}{TRUE/FALSE (1 climatology for each member/1 climatology +averaging all the members). Default = TRUE.} } \value{ - \item{$ano_exp}{Matrix with same dimensions as var_exp} - \item{$ano_obs}{Matrix with same dimensions as var_obs} +A list of length 2: +\itemize{ + \item\code{$ano_exp} {Matrix with same dimensions as var_exp} + \item\code{$ano_obs} {Matrix with same dimensions as var_obs} +} +} +\description{ +Computes the anomalies from the arrays of the experimental and observational +data output from \code{load()} by subtracting the climatologies computed +with a cross-validation technique and a per-pair method. } \examples{ # Load sample data as in Load() example: example(Load) anomalies <- Ano_CrossValid(sampleData$mod, sampleData$obs) PlotAno(anomalies$ano_exp, anomalies$ano_obs, startDates, - toptitle = paste('anomalies'), ytitle = c('K', 'K', 'K'), - legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano_crossvalid.eps') + toptitle = paste('anomalies'), ytitle = c('K', 'K', 'K'), + legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano_crossvalid.eps') } \author{ -History:\cr -0.1 - 2011-12 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +History: + 0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/ArrayToNetCDF.Rd b/man/ArrayToNetCDF.Rd index fcfb7700..a18f3af9 100644 --- a/man/ArrayToNetCDF.Rd +++ b/man/ArrayToNetCDF.Rd @@ -1,53 +1,77 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ArrayToNetCDF.R \name{ArrayToNetCDF} \alias{ArrayToNetCDF} \title{Save multidimensional R arrays into NetCDF files} -\description{This function takes as input one or a list of multidimensional R arrays and stores them in a NetCDF file, using the \code{ncdf4} package. The full path and name of the resulting file must be specified. Metadata can be attached to the arrays and propagated into the NetCDF file in 3 possible ways:\cr - \itemize{ - \item{Via the list names if a list of arrays is provided:}{Each name in the input list, corresponding to one multidimensional array, will be interpreted as the name of the variable it contains.\cr -E.g:\cr - \code{ -ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), - file_path = 'example.nc') - } - } - \item{Via the dimension names of each provided array:}{The dimension names of each of the provided arrays will be interpreted as names for the dimensions of the NetCDF files. Read further for special dimension names that will trigger special behaviours, such as 'time' and 'var'.\cr -E.g:\cr - \code{ -temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) -names(dim(temperature)) <- c('longitude', 'latitude', 'time') -ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc') - } - } - \item{Via the attribute 'variables' of each provided array:}{The arrays can be provided with metadata in an attribute named 'variables', which is expected to be a named list of named lists, where the names of the container list are the names of the variables present in the provided array, and where each sub-list contains metadata for each of the variables. The attribute names and values supported in the sub-lists must follow the same format the package \code{ncdf4} uses to represent the NetCDF file headers.\cr -E.g:\cr - \code{ -a <- array(1:400, dim = c(5, 10, 4, 2)) -metadata <- list( - tos = list(addOffset = 100, - scaleFact = 10, - dim = list(list(name = 'time', - unlim = FALSE))) - ) -attr(a, 'variables') <- metadata -names(dim(a)) <- c('lat', 'lon', 'time', 'var') -ArrayToNetCDF(a, 'tmp.nc') - } - } - } -The special dimension names are 'var'/'variable' and 'time'.\cr -If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will interpret each array entry along such dimension corresponds to a separate new variable, hence will create a new variable inside the NetCDF file and will use it to store all the data in the provided array for the corresponding entry along the 'var'/'variable' dimension.\cr -If a dimension is named 'time', by default it will be interpreted and built as an unlimited dimension. The 'time' dimension must be the last dimension of the array (the right-most). If a 'var'/'variable' dimension is present, the 'time' dimension can be also placed on its left (i.e. the one before the last dimension). The default behaviour of creating the 'time' as unlimited dimension can be disabled by setting manually the attribute \code{unlim = FALSE}, as shown in the previous example. -} \usage{ ArrayToNetCDF(arrays, file_path) } \arguments{ - \item{arrays}{One or a list of multidimensional data arrays. The list can be provided with names, which will be interpreted as variable names. The arrays can be provided with dimension names. The arrays can be provided with metadata in the attribute 'variables' (read section Description for details).} - \item{file_path}{Path and name of the NetCDF file to be created.} +\item{arrays}{One or a list of multidimensional data arrays. The list can be +provided with names, which will be interpreted as variable names. The +arrays can be provided with dimension names. The arrays can be provided +with metadata in the attribute 'variables' (read section Description for +details).} + +\item{file_path}{Path and name of the NetCDF file to be created.} +} +\value{ +This function returns NULL. +} +\description{ +This function takes as input one or a list of multidimensional R arrays and +stores them in a NetCDF file, using the \code{ncdf4} package. The full path +and name of the resulting file must be specified. Metadata can be attached +to the arrays and propagated into the NetCDF file in 3 possible ways: +\itemize{ + \item{Via the list names if a list of arrays is provided: Each name in + the input list, corresponding to one multidimensional array, will be + interpreted as the name of the variable it contains. + E.g: + \code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), + file_path = 'example.nc')}} + \item{Via the dimension names of each provided array: The dimension names + of each of the provided arrays will be interpreted as names for the + dimensions of the NetCDF files. Read further for special dimension names + that will trigger special behaviours, such as 'time' and 'var'. + E.g: + \code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) + names(dim(temperature)) <- c('longitude', 'latitude', 'time') + ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')}} + \item{Via the attribute 'variables' of each provided array: The arrays can + be provided with metadata in an attribute named 'variables', which is + expected to be a named list of named lists, where the names of the + container list are the names of the variables present in the provided + array, and where each sub-list contains metadata for each of the variables. + The attribute names and values supported in the sub-lists must follow the + same format the package \code{ncdf4} uses to represent the NetCDF + file headers. + E.g: + \code{a <- array(1:400, dim = c(5, 10, 4, 2)) + metadata <- list(tos = list(addOffset = 100, + scaleFact = 10, + dim = list(list(name = 'time', + unlim = FALSE)))) + attr(a, 'variables') <- metadata + names(dim(a)) <- c('lat', 'lon', 'time', 'var') + ArrayToNetCDF(a, 'tmp.nc')}} +} +The special dimension names are 'var'/'variable' and 'time'. +If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will +interpret each array entry along such dimension corresponds to a separate +new variable, hence will create a new variable inside the NetCDF file and +will use it to store all the data in the provided array for the +corresponding entry along the 'var'/'variable' dimension. +If a dimension is named 'time', by default it will be interpreted and built +as an unlimited dimension. The 'time' dimension must be the last dimension +of the array (the right-most). If a 'var'/'variable' dimension is present, +the 'time' dimension can be also placed on its left (i.e. the one before the +last dimension). The default behaviour of creating the 'time' as unlimited +dimension can be disabled by setting manually the attribute +\code{unlim = FALSE}, as shown in the previous example. } -\value{This function returns NULL} \examples{ - \dontrun{ + \dontrun{ # Minimal use case ArrayToNetCDF(array(1:9, c(3, 3)), 'tmp.nc') @@ -113,9 +137,9 @@ ArrayToNetCDF(list(a, b), 'tmp.nc') # attribute 'variables'. In this example the metadata is empty. a <- array(1:400, dim = c(5, 10, 4, 2)) metadata <- list( - tos = list(), - tas = list() - ) + tos = list(), + tas = list() + ) attr(a, 'variables') <- metadata names(dim(a)) <- c('lat', 'lon', 'time', 'var') ArrayToNetCDF(a, 'tmp.nc') @@ -123,9 +147,9 @@ ArrayToNetCDF(a, 'tmp.nc') # Variable names can be manually specified a <- array(1:400, dim = c(5, 10, 4, 2)) metadata <- list( - tos = list(name = 'name1'), - tas = list(name = 'name2') - ) + tos = list(name = 'name1'), + tas = list(name = 'name2') + ) attr(a, 'variables') <- metadata names(dim(a)) <- c('lat', 'lon', 'time', 'var') ArrayToNetCDF(a, 'tmp.nc') @@ -133,9 +157,9 @@ ArrayToNetCDF(a, 'tmp.nc') # Units can be specified a <- array(1:400, dim = c(5, 10, 4, 2)) metadata <- list( - tos = list(units = 'K'), - tas = list(units = 'K') - ) + tos = list(units = 'K'), + tas = list(units = 'K') + ) attr(a, 'variables') <- metadata names(dim(a)) <- c('lat', 'lon', 'time', 'var') ArrayToNetCDF(a, 'tmp.nc') @@ -143,11 +167,11 @@ ArrayToNetCDF(a, 'tmp.nc') # addOffset and scaleFactor can be specified a <- array(1:400, dim = c(5, 10, 4, 2)) metadata <- list( - tos = list(addOffset = 100, - scaleFact = 10), - tas = list(addOffset = 100, - scaleFact = 10) - ) + tos = list(addOffset = 100, + scaleFact = 10), + tas = list(addOffset = 100, + scaleFact = 10) + ) attr(a, 'variables') <- metadata names(dim(a)) <- c('lat', 'lon', 'time', 'var') ArrayToNetCDF(a, 'tmp.nc') @@ -155,15 +179,15 @@ ArrayToNetCDF(a, 'tmp.nc') # Unlimited dimensions can be manually created a <- array(1:400, dim = c(5, 10, 4, 2)) metadata <- list( - tos = list(addOffset = 100, - scaleFact = 10, - dim = list(list(name = 'unlimited', - unlim = TRUE))), - tas = list(addOffset = 100, - scaleFact = 10, - dim = list(list(name = 'unlimited', - unlim = TRUE))) - ) + tos = list(addOffset = 100, + scaleFact = 10, + dim = list(list(name = 'unlimited', + unlim = TRUE))), + tas = list(addOffset = 100, + scaleFact = 10, + dim = list(list(name = 'unlimited', + unlim = TRUE))) + ) attr(a, 'variables') <- metadata names(dim(a)) <- c('lat', 'lon', 'unlimited', 'var') ArrayToNetCDF(a, 'tmp.nc') @@ -171,15 +195,15 @@ ArrayToNetCDF(a, 'tmp.nc') # A 'time' dimension can be built without it necessarily being unlimited a <- array(1:400, dim = c(5, 10, 4, 2)) metadata <- list( - tos = list(addOffset = 100, - scaleFact = 10, - dim = list(list(name = 'time', - unlim = FALSE))), - tas = list(addOffset = 100, - scaleFact = 10, - dim = list(list(name = 'time', - unlim = FALSE))) - ) + tos = list(addOffset = 100, + scaleFact = 10, + dim = list(list(name = 'time', + unlim = FALSE))), + tas = list(addOffset = 100, + scaleFact = 10, + dim = list(list(name = 'time', + unlim = FALSE))) + ) attr(a, 'variables') <- metadata names(dim(a)) <- c('lat', 'lon', 'time', 'var') ArrayToNetCDF(a, 'tmp.nc') @@ -201,10 +225,11 @@ metadata <- list(lat = list(units = 'degrees_north')) attr(lat, 'variables') <- metadata names(dim(lat)) <- 'lat' ArrayToNetCDF(list(tos, lon, lat), 'tmp.nc') - } +} } \author{ -History:\cr -0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Original code. +History: + 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. } \keyword{datagen} + diff --git a/man/BrierScore.Rd b/man/BrierScore.Rd index e126729a..7d3ff7f4 100644 --- a/man/BrierScore.Rd +++ b/man/BrierScore.Rd @@ -1,56 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/BrierScore.R \name{BrierScore} \alias{BrierScore} -\alias{.BrierScore} -\title{ -Compute Brier Score And Its Decomposition And Brier Skill Score -} -\description{ -Computes the Brier score (BS) and the components of its standard decomposition as well with the two within-bin components described in Stephenson et al., (2008). It also returns the bias-corrected decomposition of the BS (Ferro and Fricker, 2012). BSS having the climatology as the reference forecast.\cr -\cr -.BrierScore provides the same functionality, but taking a matrix of ensemble members (exp) as input. -} +\title{Compute Brier Score And Its Decomposition And Brier Skill Score} \usage{ BrierScore(obs, pred, thresholds = seq(0, 1, 0.1)) - -.BrierScore(exp, obs, thresholds = seq(0, 1, 0.1)) } \arguments{ - \item{obs}{ -Vector of binary observations (1 or 0) - } - \item{pred}{ -Vector of probablistic predictions with values in the range [0,1] - } - \item{thresholds}{ -Values used to bin the forecasts. By default the bins are {[0,0.1), [0.1, 0.2), ... [0.9, 1]} - } - \item{exp}{ -Matrix of predictions with values in the range [0,1] for the .BrierScore function - } +\item{obs}{Vector of binary observations (1 or 0).} + +\item{pred}{Vector of probablistic predictions with values in the range [0,1].} + +\item{thresholds}{Values used to bin the forecasts. By default the bins are +{[0,0.1), [0.1, 0.2), ... [0.9, 1]}.} + +\item{exp}{Matrix of predictions with values in the range [0,1] for the +.BrierScore function} } \value{ Both BrierScore and .Brier score provide the same outputs: - \itemize{ - \item{$rel}{standard reliability} - \item{$res}{standard resolution} - \item{$unc}{standard uncertainty} - \item{$bs}{Brier score} - \item{$bs_check_res}{rel-res+unc} - \item{$bss_res}{res-rel/unc} - \item{$gres}{generalized resolution} - \item{$bs_check_gres}{rel-gres+unc} - \item{$bss_gres}{gres-rel/unc} - \item{$rel_bias_corrected}{bias-corrected rel} - \item{$gres_bias_corrected}{bias-corrected gres} - \item{$unc_bias_corrected}{bias-corrected unc} - \item{$bss_bias_corrected}{gres_bias_corrected-rel_bias_corrected/unc_bias_corrected} - \item{$nk}{number of forecast in each bin} - \item{$fkbar}{average probability of each bin} - \item{$okbar}{relative frequency that the observed event occurred} - \item{$bins}{bins used} - \item{$pred}{values with which the forecasts are verified} - \item{$obs}{probability forecasts of the event} - } +\itemize{ + \item{$rel}{standard reliability} + \item{$res}{standard resolution} + \item{$unc}{standard uncertainty} + \item{$bs}{Brier score} + \item{$bs_check_res}{rel-res+unc} + \item{$bss_res}{res-rel/unc} + \item{$gres}{generalized resolution} + \item{$bs_check_gres}{rel-gres+unc} + \item{$bss_gres}{gres-rel/unc} + \item{$rel_bias_corrected}{bias-corrected rel} + \item{$gres_bias_corrected}{bias-corrected gres} + \item{$unc_bias_corrected}{bias-corrected unc} + \item{$bss_bias_corrected}{gres_bias_corrected-rel_bias_corrected/unc_bias_corrected} + \item{$nk}{number of forecast in each bin} + \item{$fkbar}{average probability of each bin} + \item{$okbar}{relative frequency that the observed event occurred} + \item{$bins}{bins used} + \item{$pred}{values with which the forecasts are verified} + \item{$obs}{probability forecasts of the event} +} +} +\description{ +Computes the Brier score (BS) and the components of its standard +decomposition as well with the two within-bin components described in +Stephenson et al., (2008). It also returns the bias-corrected decomposition +of the BS (Ferro and Fricker, 2012). BSS having the climatology as the +reference forecast. BrierScore provides the same functionality, but taking a +matrix of ensemble members (exp) as input. } \examples{ # Minimalist examples with BrierScore @@ -60,11 +57,11 @@ x <- BrierScore(b, a) x$bs - x$bs_check_res x$bs - x$bs_check_gres x$rel_bias_corrected - x$gres_bias_corrected + x$unc_bias_corrected - \dontrun{ + \dontrun{ a <- runif(10) b <- cbind(round(a),round(a)) # matrix containing 2 identical ensemble members... x2 <- BrierScore(a, b) - } + } # Example of BrierScore using UltimateBrier # See ?UltimateBrier for more information @@ -74,24 +71,27 @@ ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) bs <- UltimateBrier(ano_exp, ano_obs, thr = c(1/3, 2/3)) - \dontrun{ + \dontrun{ # Example of .BrierScore with veriApply require(easyVerification) BrierScore2 <- s2dverification:::.BrierScore bins_ano_exp <- ProbBins(ano_exp, thr = c(1/3, 2/3), posdates = 3, posdim = 2) bins_ano_obs <- ProbBins(ano_obs, thr = c(1/3, 2/3), posdates = 3, posdim = 2) -bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_obs, 3), - tdim = 2, ensdim = 3) - } -} -\references{ -Wilks (2006) Statistical Methods in the Atmospheric Sciences.\cr -Stephenson et al. (2008). Two extra components in the Brier score decomposition. Weather and Forecasting, 23: 752-757.\cr -Ferro and Fricker (2012). A bias-corrected decomposition of the BS. Quarterly Journal of the Royal Meteorological Society, DOI: 10.1002/qj.1924.\cr +bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_ob,s 3), + tdim = 2, ensdim = 3) + } } \author{ -History:\cr -0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues at ic3.cat}) - Original code\cr -0.2 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +History: + 0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues@ic3.cat}) - Original code + 0.2 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() +} +\references{ +Wilks (2006) Statistical Methods in the Atmospheric Sciences. +Stephenson et al. (2008). Two extra components in the Brier score decomposition. + Weather and Forecasting, 23: 752-757. +Ferro and Fricker (2012). A bias-corrected decomposition of the BS. + Quarterly Journal of the Royal Meteorological Society, DOI: 10.1002/qj.1924. } \keyword{datagen} + diff --git a/man/CDORemap.Rd b/man/CDORemap.Rd index fa539dc6..f7edf1dd 100644 --- a/man/CDORemap.Rd +++ b/man/CDORemap.Rd @@ -1,33 +1,93 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/CDORemap.R \name{CDORemap} \alias{CDORemap} \title{Interpolates arrays with longitude and latitude dimensions using CDO} -\description{This function takes as inputs a multidimensional array (optional), a vector or matrix of longitudes, a vector or matrix of latitudes, a destination grid specification, and the name of a method to be used to interpolate (one of those available in the 'remap' utility in CDO). The interpolated array is returned (if provided) together with the new longitudes and latitudes.\cr\cr -\code{CDORemap()} permutes by default the dimensions of the input array (if needed), splits it in chunks (CDO can work with data arrays of up to 4 dimensions), generates a file with the data of each chunk, interpolates it with CDO, reads it back into R and merges it into a result array. If no input array is provided, the longitude and latitude vectors will be transformed only. If the array is already on the desired destination grid, no transformation is performed (this behvaiour works only for lonlat and gaussian grids).\cr\cr -Any metadata attached to the input data array, longitudes or latitudes will be preserved or accordingly modified. -} \usage{ -CDORemap(data_array = NULL, lons, lats, grid, method, - avoid_writes = TRUE, crop = TRUE, - force_remap = FALSE, write_dir = tempdir()) +CDORemap(data_array = NULL, lons, lats, grid, method, avoid_writes = TRUE, + crop = TRUE, force_remap = FALSE, write_dir = tempdir()) } \arguments{ - \item{data_array}{Multidimensional numeric array to be interpolated. If provided, it must have at least a longitude and a latitude dimensions, identified by the array dimension names. The names for these dimensions must be one of the recognized by s2dverification (can be checked with \code{s2dverification:::.KnownLonNames()} and \code{s2dverification:::.KnownLatNames()}).} - \item{lons}{Numeric vector or array of longitudes of the centers of the grid cells. Its size must match the size of the longitude/latitude dimensions of the input array.} - \item{lats}{Numeric vector or array of latitudes of the centers of the grid cells. Its size must match the size of the longitude/latitude dimensions of the input array.} - \item{grid}{Character string specifying either a name of a target grid (recognized by CDO; e.g.: 'r256x128', 't106grid') or a path to another NetCDF file which to read the target grid from (a single grid must be defined in such file).} - \item{method}{Character string specifying an interpolation method (recognized by CDO; e.g.: 'con', 'bil', 'bic', 'dis'). The following long names are also supported: 'conservative', 'bilinear', 'bicubic' and 'distance-weighted'.} - \item{avoid_writes}{The step of permutation is needed when the input array has more than 3 dimensions and none of the longitude or latitude dimensions in the right-most position (CDO would not accept it without permuting previously). This step, executed by default when needed, can be avoided for the price of writing more intermediate files (whis usually is unconvenient) by setting the parameter \code{avoid_writes = TRUE}.} - \item{crop}{Whether to crop the data after interpolation with 'cdo sellonlatbox' (TRUE) or to extend interpolated data to the whole world as CDO does by default (FALSE). If \code{crop = TRUE} then the longitude and latitude borders which to crop at are taken as the limits of the cells at the borders ('lons' and 'lats' are perceived as cell centers), i.e. the resulting array will contain data that covers the same area as the input array. This is equivalent to specifying \code{crop = 'preserve'}, i.e. preserving area. If \code{crop = 'tight'} then the borders which to crop at are taken as the minimum and maximum cell centers in 'lons' and 'lats', i.e. the area covered by the resulting array may be smaller if interpolating from a coarse grid to a fine grid. The parameter 'crop' also accepts a numeric vector of custom borders which to crop at: c(western border, eastern border, southern border, northern border). } - \item{force_remap}{Whether to force remapping, even if the input data array is already on the target grid.} - \item{write_dir}{Path to the directory where to create the intermediate files for CDO to work. By default, the R session temporary directory is used (\code{tempdir()}).} +\item{data_array}{Multidimensional numeric array to be interpolated. If +provided, it must have at least a longitude and a latitude dimensions, +identified by the array dimension names. The names for these dimensions +must be one of the recognized by s2dverification (can be checked with +\code{s2dverification:::.KnownLonNames()} and +\code{s2dverification:::.KnownLatNames()}).} + +\item{lons}{Numeric vector or array of longitudes of the centers of the grid +cells. Its size must match the size of the longitude/latitude dimensions +of the input array.} + +\item{lats}{Numeric vector or array of latitudes of the centers of the grid +cells. Its size must match the size of the longitude/latitude dimensions +of the input array.} + +\item{grid}{Character string specifying either a name of a target grid +(recognized by CDO; e.g.: 'r256x128', 't106grid') or a path to another +NetCDF file which to read the target grid from (a single grid must be +defined in such file).} + +\item{method}{Character string specifying an interpolation method +(recognized by CDO; e.g.: 'con', 'bil', 'bic', 'dis'). The following +long names are also supported: 'conservative', 'bilinear', 'bicubic' and +'distance-weighted'.} + +\item{avoid_writes}{The step of permutation is needed when the input array +has more than 3 dimensions and none of the longitude or latitude dimensions + in the right-most position (CDO would not accept it without permuting +previously). This step, executed by default when needed, can be avoided +for the price of writing more intermediate files (whis usually is +unconvenient) by setting the parameter \code{avoid_writes = TRUE}.} + +\item{crop}{Whether to crop the data after interpolation with +'cdo sellonlatbox' (TRUE) or to extend interpolated data to the whole +world as CDO does by default (FALSE). If \code{crop = TRUE} then the +longitude and latitude borders which to crop at are taken as the limits of +the cells at the borders ('lons' and 'lats' are perceived as cell centers), +i.e. the resulting array will contain data that covers the same area as +the input array. This is equivalent to specifying \code{crop = 'preserve'}, +i.e. preserving area. If \code{crop = 'tight'} then the borders which to +crop at are taken as the minimum and maximum cell centers in 'lons' and +'lats', i.e. the area covered by the resulting array may be smaller if +interpolating from a coarse grid to a fine grid. The parameter 'crop' also +accepts a numeric vector of custom borders which to crop at: +c(western border, eastern border, southern border, northern border).} + +\item{force_remap}{Whether to force remapping, even if the input data array +is already on the target grid.} + +\item{write_dir}{Path to the directory where to create the intermediate +files for CDO to work. By default, the R session temporary directory is +used (\code{tempdir()}).} +} +\value{ +A list with the following components: +\itemize{ + \item\code{$data_array} {The interpolated data array (if an input array + is provided at all, NULL otherwise).} + \item\code{$lons} {The longitudes of the data on the destination grid.} + \item\code{$lats} {The latitudes of the data on the destination grid.} } -\value{A list with the following components:\cr - \item{'data_array'}{The interpolated data array (if an input array is provided at all, NULL otherwise).} - \item{'lons'}{The longitudes of the data on the destination grid.} - \item{'lats'}{The latitudes of the data on the destination grid.} +} +\description{ +This function takes as inputs a multidimensional array (optional), a vector +or matrix of longitudes, a vector or matrix of latitudes, a destination grid +specification, and the name of a method to be used to interpolate (one of +those available in the 'remap' utility in CDO). The interpolated array is +returned (if provided) together with the new longitudes and latitudes. +\code{CDORemap()} permutes by default the dimensions of the input array (if +needed), splits it in chunks (CDO can work with data arrays of up to 4 +dimensions), generates a file with the data of each chunk, interpolates it +with CDO, reads it back into R and merges it into a result array. If no +input array is provided, the longitude and latitude vectors will be +transformed only. If the array is already on the desired destination grid, +no transformation is performed (this behvaiour works only for lonlat and +gaussian grids). Any metadata attached to the input data array, longitudes +or latitudes will be preserved or accordingly modified. } \examples{ - \dontrun{ + \dontrun{ # Interpolating only vectors of longitudes and latitudes lon <- seq(0, 360 - 360/50, length.out = 50) lat <- seq(-90, 90, length.out = 25) @@ -51,10 +111,10 @@ lat <- seq(-90, 90, length.out = 25) metadata <- list(lat = list(units = 'degrees_north')) attr(lat, 'variables') <- metadata metadata <- list(tas = list(dim = list(lat = list(len = 25, - vals = lat), - lon = list(len = 50, - vals = lon) - ))) + vals = lat), + lon = list(len = 50, + vals = lon) + ))) attr(tas, 'variables') <- metadata tas2 <- CDORemap(tas, lon, lat, 't170grid', 'bil', TRUE) @@ -62,7 +122,7 @@ tas2 <- CDORemap(tas, lon, lat, 't170grid', 'bil', TRUE) num_lats <- 25 num_lons <- 50 tas <- array(1:(10*num_lats*10*num_lons*10), - dim = c(10, num_lats, 10, num_lons, 10)) + dim = c(10, num_lats, 10, num_lons, 10)) names(dim(tas)) <- c('a', 'lat', 'b', 'lon', 'c') lon <- seq(0, 360 - 360/num_lons, length.out = num_lons) metadata <- list(lon = list(units = 'degrees_east')) @@ -71,13 +131,13 @@ lat <- seq(-90, 90, length.out = num_lats) metadata <- list(lat = list(units = 'degrees_north')) attr(lat, 'variables') <- metadata metadata <- list(tas = list(dim = list(a = list(), - lat = list(len = num_lats, - vals = lat), - b = list(), - lon = list(len = num_lons, - vals = lon), - c = list() - ))) + lat = list(len = num_lats, + vals = lat), + b = list(), + lon = list(len = num_lons, + vals = lon), + c = list() + ))) attr(tas, 'variables') <- metadata tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', TRUE) # The step of permutation can be avoided but more intermediate file writes @@ -90,7 +150,7 @@ tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', FALSE) num_lats <- 25 num_lons <- 50 tas <- array(1:(10*num_lats*10*num_lons*10), - dim = c(10, num_lats, 10, num_lons)) + dim = c(10, num_lats, 10, num_lons)) names(dim(tas)) <- c('a', 'lat', 'b', 'lon') lon <- seq(0, 360 - 360/num_lons, length.out = num_lons) metadata <- list(lon = list(units = 'degrees_east')) @@ -99,12 +159,12 @@ lat <- seq(-90, 90, length.out = num_lats) metadata <- list(lat = list(units = 'degrees_north')) attr(lat, 'variables') <- metadata metadata <- list(tas = list(dim = list(a = list(), - lat = list(len = num_lats, - vals = lat), - b = list(), - lon = list(len = num_lons, - vals = lon) - ))) + lat = list(len = num_lats, + vals = lat), + b = list(), + lon = list(len = num_lons, + vals = lon) + ))) attr(tas, 'variables') <- metadata tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', TRUE) tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', FALSE) @@ -115,12 +175,12 @@ num_lons <- 50 tas <- array(1:(1*num_lats*num_lons), dim = c(num_lats, num_lons)) names(dim(tas)) <- c('y', 'x') lon <- array(seq(0, 360 - 360/num_lons, length.out = num_lons), - dim = c(num_lons, num_lats)) + dim = c(num_lons, num_lats)) metadata <- list(lon = list(units = 'degrees_east')) names(dim(lon)) <- c('x', 'y') attr(lon, 'variables') <- metadata lat <- t(array(seq(-90, 90, length.out = num_lats), - dim = c(num_lats, num_lons))) + dim = c(num_lats, num_lons))) metadata <- list(lat = list(units = 'degrees_north')) names(dim(lat)) <- c('x', 'y') attr(lat, 'variables') <- metadata @@ -130,15 +190,15 @@ tas2 <- CDORemap(tas, lon, lat, 'r100x50', 'bil') num_lats <- 25 num_lons <- 50 tas <- array(1:(10*num_lats*10*num_lons*10), - dim = c(10, num_lats, 10, num_lons)) + dim = c(10, num_lats, 10, num_lons)) names(dim(tas)) <- c('a', 'j', 'b', 'i') lon <- array(seq(0, 360 - 360/num_lons, length.out = num_lons), - dim = c(num_lons, num_lats)) + dim = c(num_lons, num_lats)) metadata <- list(lon = list(units = 'degrees_east')) names(dim(lon)) <- c('i', 'j') attr(lon, 'variables') <- metadata lat <- t(array(seq(-90, 90, length.out = num_lats), - dim = c(num_lats, num_lons))) + dim = c(num_lats, num_lons))) metadata <- list(lat = list(units = 'degrees_north')) names(dim(lat)) <- c('i', 'j') attr(lat, 'variables') <- metadata @@ -148,23 +208,23 @@ tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil') num_lats <- 25 num_lons <- 50 tas <- array(1:(10*num_lats*10*num_lons), - dim = c(10, num_lats, 10, num_lons)) + dim = c(10, num_lats, 10, num_lons)) names(dim(tas)) <- c('a', 'j', 'b', 'i') lon <- array(seq(0, 360 - 360/num_lons, length.out = num_lons), - dim = c(num_lons, num_lats)) + dim = c(num_lons, num_lats)) names(dim(lon)) <- c('i', 'j') lat <- t(array(seq(-90, 90, length.out = num_lats), - dim = c(num_lats, num_lons))) + dim = c(num_lats, num_lons))) names(dim(lat)) <- c('i', 'j') tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil') tas2 <- CDORemap(tas, lon, lat, 't17grid', 'bil', FALSE) # It is ossible to specify an external NetCDF file as target grid reference tas2 <- CDORemap(tas, lon, lat, 'external_file.nc', 'bil') - } } -\note{This function was tested with CDO v.1.6.3.} +} \author{ -History:\cr -0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Original code. +History: + 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. } \keyword{datagen} + diff --git a/man/Clim.Rd b/man/Clim.Rd index fba9d492..5cfd655f 100644 --- a/man/Clim.Rd +++ b/man/Clim.Rd @@ -1,67 +1,67 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Clim.R \name{Clim} \alias{Clim} \title{Computes Bias Corrected Climatologies} -\description{ -This function computes only per-pair climatologies from the experimental and observational matrices output from \code{Load()}. -To compute plain climatologies from only experimental or observational data from \code{Load()}, the following code can be used:\cr - \code{ -clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), - dim = dim(obs_datta)[-c(2, 3)]) - } -The function \code{Clim()} computes per-pair climatologies using one of the following methods: - \itemize{ - \item{ -1) per-pair method (Garcia-Serrano and Doblas-Reyes, CD, 2012) - } - \item{ -2) Kharin method (Karin et al, GRL, 2012) - } - \item{ -3) Fuckar method (Fuckar et al, GRL, 2014) - } - } -\code{Clim()} computes climatologies using the startdates covered by the whole experiments/observational data sets. The startdates not available for all the data (model and obs) are excluded when computing the climatologies. -} \usage{ Clim(var_exp, var_obs, memb = TRUE, kharin = FALSE, NDV = FALSE) } \arguments{ - \item{var_exp}{ -Model data:\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) - } - \item{var_obs}{ -Observational data: \cr - c(nobs, nmemb, nsdates, nltime) up to\cr - c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) - } - \item{memb}{ -memb: TRUE/FALSE (1 climatology for each member). Default = TRUE. - } - \item{kharin}{ -TRUE/FALSE (if Kharin method is applied or not). Default = FALSE. - } - \item{NDV}{ -TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE. - } +\item{var_exp}{Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to +c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon).} + +\item{var_obs}{Observational data: c(nobs, nmemb, nsdates, nltime) up to +c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon).} + +\item{memb}{TRUE/FALSE (1 climatology for each member). Default = TRUE.} + +\item{kharin}{TRUE/FALSE (if Kharin method is applied or not). +Default = FALSE.} + +\item{NDV}{TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE.} } \value{ - \item{clim_exp}{Array with same dimensions as var_exp except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} - \item{clim_obs}{Array with same dimensions as var_obs except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} +A list of length 2: +\itemize{ + \item{clim_exp}{Array with same dimensions as var_exp except the third + (starting dates) and, depending on the parameters, the second (members), + which disappear.} + \item{clim_obs}{Array with same dimensions as var_obs except the third + (starting dates) and, depending on the parameters, the second (members), + which disappear.} +} +} +\description{ +This function computes only per-pair climatologies from the experimental +and observational matrices output from \code{Load()}. +To compute plain climatologies from only experimental or observational +data from \code{Load()}, the following code can be used: +\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), + dim = dim(obs_datta)[-c(2, 3)])} +The function \code{Clim()} computes per-pair climatologies using one of the +following methods: +\enumerate{ + \item{per-pair method (Garcia-Serrano and Doblas-Reyes, CD, 2012)} + \item{Kharin method (Karin et al, GRL, 2012)} + \item{Fuckar method (Fuckar et al, GRL, 2014)} +} +\code{Clim()} computes climatologies using the startdates covered by the +whole experiments/observational data sets. The startdates not available for +all the data (model and obs) are excluded when computing the climatologies. } \examples{ # Load sample data as in Load() example: example(Load) clim <- Clim(sampleData$mod, sampleData$obs) PlotClim(clim$clim_exp, clim$clim_obs, - toptitle = paste('sea surface temperature climatologies'), - ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') + toptitle = paste('sea surface temperature climatologies'), + ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') } \author{ -History:\cr -0.9 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN +History: + 0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN } \keyword{datagen} + diff --git a/man/Cluster.Rd b/man/Cluster.Rd index 16447731..4ed144e2 100644 --- a/man/Cluster.Rd +++ b/man/Cluster.Rd @@ -1,82 +1,71 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Cluster.R \name{Cluster} \alias{Cluster} -\title{ -K-means Clustering. -} -\description{ -This function computes cluster centers and their time series of occurrences, -with the K-means clustering method using Euclidean distance, of an array of -input data with any number of dimensions, one of them (the 'posdates'th) -corresponding to time. By default the first dimension is expected to correspond -to time. -Specifically, it partitions the array along time axis in K groups or clusters -in which each space vector/array belongs to (i.e., is a member of) the cluster -with the nearest center or centroid. This function relies on the NbClust -package (Charrad et al., 2014 JSS). -} +\title{K-means Clustering} \usage{ -Cluster(var, weights, nclusters = NULL, index = 'sdindex', posdates = 1) +Cluster(var, weights, nclusters = NULL, index = "sdindex", posdates = 1) } \arguments{ - \item{var}{ -An array with any number of dimensions, one of them (the 'posdates'th) -corresponding to time with either area-averages over a series of domains or -the grid points for any sptial grid structure (x), (y), (z), (x,y), (x,y,z), -(y,z), ... - } - \item{weights}{ -A vector/array of multiplicative weights based on the areas covering each -domain/region or grid-cell of var; the dimensions of weights vector must be -equal to the dimensions of 'var' without the 'posdates'th dimension. - } - \item{nclusters}{ -This is positive integer K that must be bigger than 1. K is the number of clusters -to be computed, or K initial cluster centers to be used in the method. Default is NULL -and then user has to specify which index from NbClust and the associated criteria for -selecting the optimal number of clusters will be used for K-means clustering of var. - } - \item{index}{ -A validity index from NbClust package that can be used to determine optimal K -if K is not specified as positive integer bigger than 1 or initial/seed cluster -centers in nclusters. 'sdindex' is deafult (Halkidi et al. 2001, JIIS). Other -indices also available in NBClust are "kl", "ch", "hartigan", "ccc", "scott", "marriot", -"trcovw", "tracew", "friedman", "rubin", "cindex", "db", "silhouette", "duda", "pseudot2", -"beale", "ratkowsky", "ball", "ptbiserial", "gap", "frey", "mcclain", "gamma", "gplus", -"tau", "dunn", "hubert", "sdindex", and "sdbw". One can also use all of them with -the option 'alllong' or almost all indices except gap, gamma, gplus and tau with 'all', -when the optimal number of clusters K is detremined by the majority rule (the maximum of -histogram of the results of all indices with finite solutions). Use of some indices on -a big and/or unstructured dataset can be computationally intense and/or could lead to -numerical singularity. - } - \item{posdates}{ -The index of the dimension that corresponds to time in the provided array in the parameter -'var', the first by default. - } +\item{var}{An array with any number of dimensions, one of them (the +'posdates'th) corresponding to time with either area-averages over a +series of domains or the grid points for any sptial grid structure (x), +(y), (z), (x,y), (x,y,z), (y,z), ...} + +\item{weights}{A vector/array of multiplicative weights based on the areas +covering each domain/region or grid-cell of var; the dimensions of weights +vector must be equal to the dimensions of 'var' without the +'posdates'th dimension.} + +\item{nclusters}{This is positive integer K that must be bigger than 1. +K is the number of clusters to be computed, or K initial cluster centers +to be used in the method. Default is NULL and then user has to specify +which index from NbClust and the associated criteria for selecting the +optimal number of clusters will be used for K-means clustering of var.} + +\item{index}{A validity index from NbClust package that can be used to +determine optimal K if K is not specified as positive integer bigger than +1 or initial/seed cluster centers in nclusters. 'sdindex' is deafult +(Halkidi et al. 2001, JIIS). Other indices also available in NBClust are +"kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw", "tracew", +"friedman", "rubin", "cindex", "db", "silhouette", "duda", "pseudot2", +"beale", "ratkowsky", "ball", "ptbiserial", "gap", "frey", "mcclain", +"gamma", "gplus", "tau", "dunn", "hubert", "sdindex", and "sdbw". +One can also use all of them with the option 'alllong' or almost all indices +except gap, gamma, gplus and tau with 'all', when the optimal number of +clusters K is detremined by the majority rule (the maximum of histogram of +the results of all indices with finite solutions). Use of some indices on +a big and/or unstructured dataset can be computationally intense and/or +could lead to numerical singularity.} + +\item{posdates}{The index of the dimension that corresponds to time in the +provided array in the parameter 'var', the first by default.} } \value{ - \item{cluster}{ -A vector (time series) of integers indicating the occurrence of a cluster, i.e., when -certain data member in time is allocated to a specific cluster (e.g., 2 1 3 1 1 1 ..). - } - \item{centers}{ -A matrix of cluster centres or centroids (e.g. [1:K, 1:spatial degrees of freedom]). - } - \item{totss}{ -The total sum of squares. - } - \item{withinss}{ -A vector of within-cluster sum of squares, one component per cluster. - } - \item{tot.withinss}{ -Total within-cluster sum of squares, i.e., sum(withinss). - } - \item{betweenss}{ -The between-cluster sum of squares, i.e. totss-tot.withinss. - } - \item{size}{ -The number of points in each cluster. - } +\itemize{ + \item{cluster}{A vector (time series) of integers indicating the occurrence + of a cluster, i.e., when 'certain data member in time is allocated to a + specific cluster (e.g., 2 1 3 1 1 1 ..).} + \item{centers}{A matrix of cluster centres or centroids (e.g. + [1:K, 1:spatial degrees of freedom]).} + \item{totss}{The total sum of squares.} + \item{withinss}{A vector of within-cluster sum of squares, one component + per cluster.} + \item{tot.withinss}{Total within-cluster sum of squares, + i.e., sum(withinss).} + \item{betweenss}{The between-cluster sum of squares, i.e. totss-tot.withinss.} + \item{size}{The number of points in each cluster.} +} +} +\description{ +This function computes cluster centers and their time series of occurrences, +with the K-means clustering method using Euclidean distance, of an array of +input data with any number of dimensions, one of them (the 'posdates'th) +corresponding to time. By default the first dimension is expected to +correspond to time. Specifically, it partitions the array along time axis in +K groups or clusters in which each space vector/array belongs to (i.e., is a +member of) the cluster with the nearest center or centroid. This function +relies on the NbClust package (Charrad et al., 2014 JSS). } \examples{ # Generating synthetic data @@ -88,20 +77,20 @@ c0 <- seq(1, 200) c1 <- sort(sample(x = 1:200, size = sample(x = 50:150, size = 1), replace = FALSE)) x1 <- c(1, 1, 1, 1) for (i1 in c1) { - a1[i1, ] <- x1 + rnorm(4, mean = mean1, sd = sd1) + a1[i1, ] <- x1 + rnorm(4, mean = mean1, sd = sd1) } -c1p5 <- c0[!(c0 \%in\% c1)] +c1p5 <- c0[!(c0 \\\%in\\\% c1)] c2 <- c1p5[seq(1, length(c1p5), 2)] x2 <- c(2, 2, 4, 4) for (i2 in c2) { - a1[i2, ] <- x2 + rnorm(4, mean = mean1, sd = sd1) + a1[i2, ] <- x2 + rnorm(4, mean = mean1, sd = sd1) } c3 <- c1p5[seq(2, length(c1p5), 2)] x3 <- c(3, 3, 1, 1) for (i3 in c3) { - a1[i3, ] <- x3 + rnorm(4, mean = mean1, sd = sd1) + a1[i3, ] <- x3 + rnorm(4, mean = mean1, sd = sd1) } # Computing the clusters @@ -113,11 +102,12 @@ res2 <- Cluster(var = a1, weights = array(1, dim = dim(a1)[2])) print(res2$cluster) print(res2$centers) } -\references{ -Wilks, 2011, Statistical Methods in the Atmospheric Sciences, 3rd ed., Elsevire, pp 676. -} \author{ History: -1.0 # 2014-10 (N.S. Fuckar, neven.fuckar@bsc.es) # Original code + 1.0 # 2014-10 (N.S. Fuckar, neven.fuckar@bsc.es) # Original code +} +\references{ +Wilks, 2011, Statistical Methods in the Atmospheric Sciences, 3rd ed., Elsevire, pp 676. } \keyword{datagen} + diff --git a/man/ColorBar.Rd b/man/ColorBar.Rd index 51ca5670..257c7c5d 100644 --- a/man/ColorBar.Rd +++ b/man/ColorBar.Rd @@ -1,126 +1,181 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ColorBar.R \name{ColorBar} \alias{ColorBar} \title{Draws a Color Bar} -\description{ -Generates a color bar to use as colouring function for map plots and optionally draws it (horizontally or vertically) to be added to map multipanels or plots. It is possible to draw triangles at the ends of the colour bar to represent values that go beyond the range of interest. A number of options is provided to adjust the colours and the position and size of the components. The drawn colour bar spans a whole figure region and is compatible with figure layouts.\cr\cr -The generated colour bar consists of a set of breaks that define the length(brks) - 1 intervals to classify each of the values in each of the grid cells of a two-dimensional field. The corresponding grid cell of a given value of the field will be coloured in function of the interval it belongs to.\cr\cr -The only mandatory parameters are 'var_limits' or 'brks' (in its second format, see below). -} \usage{ -ColorBar(brks = NULL, cols = NULL, vertical = TRUE, - subsampleg = NULL, bar_limits = NULL, var_limits = NULL, - triangle_ends = NULL, col_inf = NULL, col_sup = NULL, - color_fun = clim.palette(), plot = TRUE, draw_ticks = TRUE, - draw_separators = FALSE, triangle_ends_scale = 1, - extra_labels = NULL, title = NULL, title_scale = 1, - label_scale = 1, tick_scale = 1, - extra_margin = rep(0, 4), label_digits = 4, ...) +ColorBar(brks = NULL, cols = NULL, vertical = TRUE, subsampleg = NULL, + bar_limits = NULL, var_limits = NULL, triangle_ends = NULL, + col_inf = NULL, col_sup = NULL, color_fun = clim.palette(), + plot = TRUE, draw_ticks = TRUE, draw_separators = FALSE, + triangle_ends_scale = 1, extra_labels = NULL, title = NULL, + title_scale = 1, label_scale = 1, tick_scale = 1, + extra_margin = rep(0, 4), label_digits = 4, ...) } \arguments{ - \item{brks}{ -'brks' can be provided in two formats:\cr -a) A single value with the number of breaks to be generated automatically, between the minimum and maximum specified in 'var_limits' (both inclusive). Hence the parameter 'var_limits' is mandatory if 'brks' is provided with this format. If 'bar_limits' is additionally provided, values only between 'bar_limits' will be generated. The higher the value of 'brks', the smoother the plot will look.\cr -b) A vector with the actual values of the desired breaks. Values will be reordered by force to ascending order. If provided in this format, no other parameters are required to generate/plot the colour bar.\cr\cr - -This parameter is optional if 'var_limits' is specified. If 'brks' not specified but 'cols' is specified, it will take as value length(cols) + 1. If 'cols' is not specified either, 'brks' will take 21 as value.\cr\cr - } - \item{cols}{ -Vector of length(brks) - 1 valid colour identifiers, for each interval defined by the breaks. This parameter is optional and will be filled in with a vector of length(brks) - 1 colours generated with the function provided in 'color_fun' (\code{clim.colors} by default).\cr -'cols' can have one additional colour at the beginning and/or at the end with the aim to colour field values beyond the range of interest represented in the colour bar. If any of these extra colours is provided, parameter 'triangle_ends' becomes mandatory in order to disambiguate which of the ends the colours have been provided for.\cr - } - \item{vertical}{ -TRUE/FALSE for vertical/horizontal colour bar (disregarded if plot = FALSE). - } - \item{subsampleg}{ -The first of each subsampleg breaks will be ticked on the colorbar.\cr -Takes by default an approximation of a value that yields a readable tick arrangement (extreme breaks always ticked). If set to 0 or lower, no labels are drawn. See the code of the function for details or use 'extra_labels' for customized tick arrangements. - } - \item{bar_limits}{ -Vector of two numeric values with the extremes of the range of values represented in the colour bar. If 'var_limits' go beyond this interval, the drawing of triangle extremes is triggered at the corresponding sides, painted in 'col_inf' and 'col_sup'. Either of them can be set as NA and will then take as value the corresponding extreme in 'var_limits' (hence a triangle end won't be triggered for these sides). Takes as default the extremes of 'brks' if available, else the same values as 'var_limits'. - } - \item{var_limits}{ -Vector of two numeric values with the minimum and maximum values of the field to represent. These are used to know whether to draw triangle ends at the extremes of the colour bar and what colour to fill them in with. If not specified, take the same value as the extremes of 'brks'. Hence the parameter 'brks' is mandatory if 'var_limits' is not specified. - } - \item{triangle_ends}{ -Vector of two logical elements, indicating whether to force the drawing of triangle ends at each of the extremes of the colour bar. This choice is automatically made from the provided 'brks', 'bar_limits', 'var_limits', 'col_inf' and 'col_sup', but the behaviour can be manually forced to draw or not to draw the triangle ends with this parameter. If 'cols' is provided, 'col_inf' and 'col_sup' will take priority over 'triangle_ends' when deciding whether to draw the triangle ends or not. - } - \item{col_inf}{ -Colour to fill the inferior triangle end with. Useful if specifying colours manually with parameter 'cols', to specify the colour and to trigger the drawing of the lower extreme triangle, or if 'cols' is not specified, to replace the colour automatically generated by ColorBar(). - } - \item{col_sup}{ -Colour to fill the superior triangle end with. Useful if specifying colours manually with parameter 'cols', to specify the colour and to trigger the drawing of the upper extreme triangle, or if 'cols' is not specified, to replace the colour automatically generated by ColorBar(). - } - \item{color_fun}{ -Function to generate the colours of the color bar. Must take an integer and must return as many colours. The returned colour vector can have the attribute 'na_color', with a colour to draw NA values. This parameter is set by default to clim.palette(). - } - \item{plot}{ -Logical value indicating whether to only compute its breaks and colours (FALSE) or to also draw it on the current device (TRUE). - } - \item{draw_ticks}{ -Whether to draw ticks for the labels along the colour bar (TRUE) or not (FALSE). TRUE by default. Disregarded if 'plot = FALSE'. - } - \item{draw_separators}{ -Whether to draw black lines in the borders of each of the colour rectancles of the colour bar (TRUE) or not (FALSE). FALSE by default. Disregarded if 'plot = FALSE'. - } - \item{triangle_ends_scale}{ -Scale factor for the drawn triangle ends of the colour bar, if drawn at all. Takes 1 by default (rectangle triangle proportional to the thickness of the colour bar). Disregarded if 'plot = FALSE'. - } - \item{extra_labels}{ -Numeric vector of extra labels to draw along axis of the colour bar. The number of provided decimals will be conserved. Disregarded if 'plot = FALSE'. - } - \item{title}{ -Title to draw on top of the colour bar, most commonly with the units of the represented field in the neighbour figures. Empty by default. - } - \item{title_scale}{ -Scale factor for the 'title' of the colour bar. Takes 1 by default. - } - \item{label_scale}{ -Scale factor for the labels of the colour bar. Takes 1 by default. - } - \item{tick_scale}{ -Scale factor for the length of the ticks of the labels along the colour bar. Takes 1 by default. - } - \item{extra_margin}{ -Extra margins to be added around the colour bar, in the format c(y1, x1, y2, x2). The units are margin lines. Takes rep(0, 4) by default. - } - \item{label_digits}{ -Number of significant digits to be displayed in the labels of the colour bar, usually to avoid too many decimal digits overflowing the figure region. This does not have effect over the labels provided in 'extra_labels'. Takes 4 by default. - } - \item{...}{ -Arguments to be passed to the method. Only accepts the following graphical parameters: - -adj ann ask bg bty cex.lab cex.main cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - -For more information about the parameters see `par` - } +\item{brks}{Can be provided in two formats: +\itemize{ + \item{A single value with the number of breaks to be generated + automatically, between the minimum and maximum specified in 'var_limits' + (both inclusive). Hence the parameter 'var_limits' is mandatory if 'brks' + is provided with this format. If 'bar_limits' is additionally provided, + values only between 'bar_limits' will be generated. The higher the value + of 'brks', the smoother the plot will look.} + \item{A vector with the actual values of the desired breaks. Values will + be reordered by force to ascending order. If provided in this format, no + other parameters are required to generate/plot the colour bar.} +} + This parameter is optional if 'var_limits' is specified. If 'brks' not + specified but 'cols' is specified, it will take as value length(cols) + 1. + If 'cols' is not specified either, 'brks' will take 21 as value.} + +\item{cols}{Vector of length(brks) - 1 valid colour identifiers, for each +interval defined by the breaks. This parameter is optional and will be +filled in with a vector of length(brks) - 1 colours generated with the +function provided in 'color_fun' (\code{clim.colors} by default). 'cols' +can have one additional colour at the beginning and/or at the end with the +aim to colour field values beyond the range of interest represented in the +colour bar. If any of these extra colours is provided, parameter +'triangle_ends' becomes mandatory in order to disambiguate which of the +ends the colours have been provided for.} + +\item{vertical}{TRUE/FALSE for vertical/horizontal colour bar +(disregarded if plot = FALSE).} + +\item{subsampleg}{The first of each subsampleg breaks will be ticked on the +colorbar. Takes by default an approximation of a value that yields a +readable tick arrangement (extreme breaks always ticked). If set to 0 or +lower, no labels are drawn. See the code of the function for details or +use 'extra_labels' for customized tick arrangements.} + +\item{bar_limits}{Vector of two numeric values with the extremes of the +range of values represented in the colour bar. If 'var_limits' go beyond +this interval, the drawing of triangle extremes is triggered at the +corresponding sides, painted in 'col_inf' and 'col_sup'. Either of them +can be set as NA and will then take as value the corresponding extreme in +'var_limits' (hence a triangle end won't be triggered for these sides). +Takes as default the extremes of 'brks' if available, else the same values +as 'var_limits'.} + +\item{var_limits}{Vector of two numeric values with the minimum and maximum +values of the field to represent. These are used to know whether to draw +triangle ends at the extremes of the colour bar and what colour to fill +them in with. If not specified, take the same value as the extremes of +'brks'. Hence the parameter 'brks' is mandatory if 'var_limits' is not +specified.} + +\item{triangle_ends}{Vector of two logical elements, indicating whether to +force the drawing of triangle ends at each of the extremes of the colour +bar. This choice is automatically made from the provided 'brks', +'bar_limits', 'var_limits', 'col_inf' and 'col_sup', but the behaviour +can be manually forced to draw or not to draw the triangle ends with this +parameter. If 'cols' is provided, 'col_inf' and 'col_sup' will take +priority over 'triangle_ends' when deciding whether to draw the triangle +ends or not.} + +\item{col_inf}{Colour to fill the inferior triangle end with. Useful if +specifying colours manually with parameter 'cols', to specify the colour +and to trigger the drawing of the lower extreme triangle, or if 'cols' is +not specified, to replace the colour automatically generated by ColorBar().} + +\item{col_sup}{Colour to fill the superior triangle end with. Useful if +specifying colours manually with parameter 'cols', to specify the colour +and to trigger the drawing of the upper extreme triangle, or if 'cols' is +not specified, to replace the colour automatically generated by ColorBar().} + +\item{color_fun}{Function to generate the colours of the color bar. Must +take an integer and must return as many colours. The returned colour vector +can have the attribute 'na_color', with a colour to draw NA values. This +parameter is set by default to clim.palette().} + +\item{plot}{Logical value indicating whether to only compute its breaks and +colours (FALSE) or to also draw it on the current device (TRUE).} + +\item{draw_ticks}{Whether to draw ticks for the labels along the colour bar +(TRUE) or not (FALSE). TRUE by default. Disregarded if 'plot = FALSE'.} + +\item{draw_separators}{Whether to draw black lines in the borders of each of +the colour rectancles of the colour bar (TRUE) or not (FALSE). FALSE by +default. Disregarded if 'plot = FALSE'.} + +\item{triangle_ends_scale}{Scale factor for the drawn triangle ends of the +colour bar, if drawn at all. Takes 1 by default (rectangle triangle +proportional to the thickness of the colour bar). Disregarded if +'plot = FALSE'.} + +\item{extra_labels}{Numeric vector of extra labels to draw along axis of +the colour bar. The number of provided decimals will be conserved. +Disregarded if 'plot = FALSE'.} + +\item{title}{Title to draw on top of the colour bar, most commonly with the +units of the represented field in the neighbour figures. Empty by default.} + +\item{title_scale}{Scale factor for the 'title' of the colour bar. +Takes 1 by default.} + +\item{label_scale}{Scale factor for the labels of the colour bar. +Takes 1 by default.} + +\item{tick_scale}{Scale factor for the length of the ticks of the labels +along the colour bar. Takes 1 by default.} + +\item{extra_margin}{Extra margins to be added around the colour bar, +in the format c(y1, x1, y2, x2). The units are margin lines. Takes +rep(0, 4) by default.} + +\item{label_digits}{Number of significant digits to be displayed in the +labels of the colour bar, usually to avoid too many decimal digits +overflowing the figure region. This does not have effect over the labels +provided in 'extra_labels'. Takes 4 by default.} + +\item{...}{Arguments to be passed to the method. Only accepts the following + graphical parameters: adj ann ask bg bty cex.lab cex.main cex.sub cin + col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin + font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty + lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt + tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. For more +information about the parameters see `par`.} } \value{ - \item{brks}{ -Breaks used for splitting the range in intervals. - } - \item{cols}{ -Colours generated for each of the length(brks) - 1 intervals. Always of length length(brks) - 1. - } - \item{col_inf}{ -Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). - } - \item{col_sup}{ -Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). - } +\itemize{ + \item{brks}{Breaks used for splitting the range in intervals.} + \item{cols}{Colours generated for each of the length(brks) - 1 intervals. + Always of length length(brks) - 1.} + \item{col_inf}{Colour used to draw the lower triangle end in the colour + bar (NULL if not drawn at all).} + \item{col_sup}{Colour used to draw the upper triangle end in the colour + bar (NULL if not drawn at all).} +} +} +\description{ +Generates a color bar to use as colouring function for map plots and +optionally draws it (horizontally or vertically) to be added to map +multipanels or plots. It is possible to draw triangles at the ends of the +colour bar to represent values that go beyond the range of interest. A +number of options is provided to adjust the colours and the position and +size of the components. The drawn colour bar spans a whole figure region +and is compatible with figure layouts.\cr\cr The generated colour bar +consists of a set of breaks that define the length(brks) - 1 intervals to +classify each of the values in each of the grid cells of a two-dimensional +field. The corresponding grid cell of a given value of the field will be +coloured in function of the interval it belongs to. +The only mandatory parameters are 'var_limits' or 'brks' (in its second +format, see below). } \examples{ cols <- c("dodgerblue4", "dodgerblue1", "forestgreen", "yellowgreen", "white", - "white", "yellow", "orange", "red", "saddlebrown") + "white", "yellow", "orange", "red", "saddlebrown") lims <- seq(-1, 1, 0.2) ColorBar(lims, cols) } \author{ -History:\cr -0.1 - 2012-04 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr -0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo at bsc.es}) - Vert option\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr -1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme at bsc.es}) - Add cex option\cr -1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens at bsc.es}) - New ColorBar\cr - (V. Torralba, \email{veronica.torralba at bsc.es}) +History: + 0.1 - 2012-04 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code\cr + 0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo@bsc.es}) - Vert option + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN + 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - Add cex option + 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - New ColorBar + (V. Torralba, \email{veronica.torralba@bsc.es}) } \keyword{dplot} + diff --git a/man/Composite.Rd b/man/Composite.Rd index e2f28792..bf5009ad 100644 --- a/man/Composite.Rd +++ b/man/Composite.Rd @@ -1,50 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Composite.R \name{Composite} \alias{Composite} -\title{ - Computes composites. -} -\description{ - Composites a 3-d field var(x,y,time) according to the indices of - mode/cluster occurrences in time and computes the pvalues (t-test). - x and y are typically lon and lat, but function can accept other 2-d - fields such as lat and depth, lon and depth, etc. -} +\title{Computes composites} \usage{ - Composite(var, occ, lag=0, eno=FALSE, fileout=NULL) +Composite(var, occ, lag = 0, eno = FALSE, fileout = NULL) } \arguments{ - \item{var}{ - 3-dimensional array (x, y, time) containing the variable to composite. - } - \item{occ}{ - 1-dimensional array for the occurrence time series of mode(s)/cluster(s) - (*1) when one wants to composite all modes, e.g., all K=3 clusters then - for example occurrences could look like: 1 1 2 3 2 3 1 3 3 2 3 2 2 3 2, - (*2) otherwise for compositing only the 2nd mode or cluster of the above - example occurrences should look like 0 0 1 0 1 0 0 0 0 1 0 1 1 0 1. - } - \item{lag}{ - Lag time step (an integer), e.g., for lag=2 composite will use +2 - occurrences (i.e., shifted 2 time steps forward). Deafult is lag=0. - } - \item{eno}{ - For using the effective sample size (TRUE) or the total sample size - (FALSE that is the default) for the number of degrees of freedom. - } - \item{fileout}{ - Name of the .sav output file (NULL is the default). - } +\item{var}{3-dimensional array (x, y, time) containing the variable to +composite.} + +\item{occ}{1-dimensional array for the occurrence time series of +mode(s)/cluster(s). +(*1) When one wants to composite all modes, e.g., all K = 3 clusters then + for example occurrences could look like: 1 1 2 3 2 3 1 3 3 2 3 2 2 3 2. +(*2) Otherwise for compositing only the 2nd mode or cluster of the above + example occurrences should look like 0 0 1 0 1 0 0 0 0 1 0 1 1 0 1.} + +\item{lag}{Lag time step (an integer), e.g., for lag = 2 composite will +use +2 occurrences (i.e., shifted 2 time steps forward). Default is lag = 0.} + +\item{eno}{For using the effective sample size (TRUE) or the total sample +size (FALSE that is the default) for the number of degrees of freedom.} + +\item{fileout}{Name of the .sav output file (NULL is the default).} } \value{ - \item{$composite}{ - 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) - or only k=1 for any specific cluster, i.e., case (*2). - } - \item{$pvalue}{ - 3-d array (x, y, k) containing the pvalue of the - composites obtained through a t-test that accounts for the serial - dependence of the data with the same structure as Composite. - } +\itemize{ + \item{$composite}{ + 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) + or only k=1 for any specific cluster, i.e., case (*2). + } + \item{$pvalue}{ + 3-d array (x, y, k) containing the pvalue of the + composites obtained through a t-test that accounts for the serial + dependence of the data with the same structure as Composite. + } +} +} +\description{ +Composites a 3-d field var(x, y, time) according to the indices of +mode/cluster occurrences in time and computes the pvalues (t-test). x and y +are typically lon and lat, but function can accept other 2-d fields such as +lat and depth, lon and depth, etc. } \examples{ blank <- array(0, dim=c(20, 10, 30)) @@ -54,11 +52,11 @@ t1 <- blank f1 <- blank for (i in 1:20) { - x1[i,,] <- i + x1[i,,] <- i } for (i in 1:30) { - t1[,,i] <- i + t1[,,i] <- i } # This is 2D propagating sin wave example, where we use (x,y,t) structure of @@ -66,9 +64,9 @@ for (i in 1:30) { # steps can lead to modification or cancelation of wave pattern. for (i in 1:20) { - for (j in 1:30) { - f1[i,,j] <- 3*sin(2*pi*x1[i,,j]/5. - 2*pi*t1[i,,j]/6.) - } + for (j in 1:30) { + f1[i,,j] <- 3*sin(2*pi*x1[i,,j]/5. - 2*pi*t1[i,,j]/6.) + } } occ1 <- rep(0, 30) @@ -80,10 +78,10 @@ occ2 <- rep(0, 30) occ2[c(3, 9, 15, 21)] <- 1 filled.contour(Composite(var=f1, occ=occ2)$composite[,,1]) - } \author{ - History: - 0.1 # 2014-08 (N.S. Fuckar, \email{neven.fuckar@bsc.es}) # Original code +History: + 0.1 # 2014-08 (N.S. Fuckar, \email{neven.fuckar@bsc.es}) # Original code } \keyword{datagen} + diff --git a/man/ConfigApplyMatchingEntries.Rd b/man/ConfigApplyMatchingEntries.Rd index 15e50469..b97a3b36 100644 --- a/man/ConfigApplyMatchingEntries.Rd +++ b/man/ConfigApplyMatchingEntries.Rd @@ -1,48 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ConfigApplyMatchingEntries.R \name{ConfigApplyMatchingEntries} \alias{ConfigApplyMatchingEntries} -\title{ -Apply Matching Entries To Dataset Name And Variable Name To Find Related Info -} -\description{ -Given a pair of dataset name and variable name, this function determines applies all the matching entries found in the corresponding configuration table to work out the dataset main path, file path, actual name of variable inside NetCDF files, ... -} +\title{Apply Matching Entries To Dataset Name And Variable Name To Find Related Info} \usage{ -ConfigApplyMatchingEntries(configuration, var, exp = NULL, obs = NULL, - show_entries = FALSE, show_result = TRUE) +ConfigApplyMatchingEntries(configuration, var, exp = NULL, obs = NULL, + show_entries = FALSE, show_result = TRUE) } \arguments{ - \item{configuration}{ -Configuration object obtained from ConfigFileOpen() or ConfigFileCreate(). - } - \item{var}{ -Name of the variable to load. Will be interpreted as a string, regular expressions do not apply here.\cr -Examples: 'tas' or 'tasmax_q90'. - } - \item{exp}{ -Set of experimental dataset identifiers. Will be interpreted as a strings, regular expressions do not apply here.\cr -Can be NULL (not to check in experimental dataset tables), and takes by default NULL.\cr -Examples: c('EnsEcmwfSeas', 'EnsUkmoSeas'), c('i00k'). - } - \item{obs}{ -Set of observational dataset identifiers. Will be interpreted as a strings, regular expressions do not apply here.\cr -Can be NULL (not to check in observational dataset tables), and takes by default NULL.\cr -Examples: c('GLORYS', 'ERAint'), c('NCEP'). - } - \item{show_entries}{ -Flag to stipulate whether to show the found matching entries for all datasets and variable name. - } - \item{show_result}{ -Flag to stipulate whether to show the result of applying all the matching entries (dataset main path, file path, ...). - } +\item{configuration}{Configuration object obtained from ConfigFileOpen() +or ConfigFileCreate().} + +\item{var}{Name of the variable to load. Will be interpreted as a string, +regular expressions do not apply here. +Examples: 'tas' or 'tasmax_q90'.} + +\item{exp}{Set of experimental dataset identifiers. Will be interpreted as +a strings, regular expressions do not apply here. Can be NULL (not to +check in experimental dataset tables), and takes by default NULL. +Examples: c('EnsEcmwfSeas', 'EnsUkmoSeas'), c('i00k').} + +\item{obs}{Set of observational dataset identifiers. Will be interpreted as +a strings, regular expressions do not apply here. Can be NULL (not to +check in observational dataset tables), and takes by default NULL. +Examples: c('GLORYS', 'ERAint'), c('NCEP').} + +\item{show_entries}{Flag to stipulate whether to show the found matching +entries for all datasets and variable name.} + +\item{show_result}{Flag to stipulate whether to show the result of applying +all the matching entries (dataset main path, file path, ...).} } \value{ -A list with the information resulting of applying the matching entries is returned. +A list with the information resulting of applying the matching + entries is returned. } -\seealso{ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable} -\author{ -History:\cr -0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - First version -1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Removed grid column and storage types +\description{ +Given a pair of dataset name and variable name, this function determines +applies all the matching entries found in the corresponding configuration +table to work out the dataset main path, file path, actual name of variable +inside NetCDF files, ... } \examples{ # Create an empty configuration file @@ -54,16 +51,27 @@ configuration <- ConfigFileOpen(config_file) # table which will associate the experiment "ExampleExperiment2" and variable # "ExampleVariable" to some information about its location. configuration <- ConfigAddEntry(configuration, "experiments", - "last", "ExampleExperiment2", "ExampleVariable", - "/path/to/ExampleExperiment2/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "last", "ExampleExperiment2", "ExampleVariable", + "/path/to/ExampleExperiment2/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Edit entry to generalize for any variable. Changing variable needs . configuration <- ConfigEditEntry(configuration, "experiments", 1, - var_name = ".*", - file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") + var_name = ".*", + file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") # Now apply matching entries for variable and experiment name and show the # result match_info <- ConfigApplyMatchingEntries(configuration, 'tas', - exp = c('ExampleExperiment2'), show_result = TRUE) + exp = c('ExampleExperiment2'), show_result = TRUE) +} +\author{ +History: + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version + 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage types +} +\seealso{ +[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], + [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], + [ConfigShowTable()]. } \keyword{datagen} + diff --git a/man/ConfigEditDefinition.Rd b/man/ConfigEditDefinition.Rd index 9da8c09d..f17269ef 100644 --- a/man/ConfigEditDefinition.Rd +++ b/man/ConfigEditDefinition.Rd @@ -1,38 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ConfigEditDefinition.R \name{ConfigEditDefinition} \alias{ConfigEditDefinition} -\alias{ConfigRemoveDefinition} -\title{ -Add Modify Or Remove Variable Definitions In Configuration -} -\description{ -These functions help in adding, modifying or removing variable definitions in a configuration object obtained wit ConfigFileOpen() or ConfigFileCreate().\cr -ConfigEditDefinition() will add the definition if not existing. -} +\title{Add Modify Or Remove Variable Definitions In Configuration} \usage{ ConfigEditDefinition(configuration, name, value, confirm = TRUE) -ConfigRemoveDefinition(configuration, name) } \arguments{ - \item{configuration}{ -Configuration object obtained wit ConfigFileOpen() or ConfigFileCreate(). - } - \item{name}{ -Name of the variable to add/modify/remove. - } - \item{value}{ -Value to associate to the variable. - } - \item{confirm}{ -Flag to stipulate whether to ask for confirmation if the variable is being modified. Takes by default TRUE. - } +\item{configuration}{Configuration object obtained wit ConfigFileOpen() or +ConfigFileCreate().} + +\item{name}{Name of the variable to add/modify/remove.} + +\item{value}{Value to associate to the variable.} + +\item{confirm}{Flag to stipulate whether to ask for confirmation if the +variable is being modified. Takes by default TRUE.} } \value{ A modified configuration object is returned. } -\seealso{ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable} -\author{ -History:\cr -0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - First version +\description{ +These functions help in adding, modifying or removing variable definitions +in a configuration object obtained with \code{\link{ConfigFileOpen}} or +\code{\link{ConfigFileCreate}}. ConfigEditDefinition() will add the +definition if not existing. } \examples{ # Create an empty configuration file @@ -44,16 +36,26 @@ configuration <- ConfigFileOpen(config_file) # table which will associate the experiment "ExampleExperiment2" and variable # "ExampleVariable" to some information about its location. configuration <- ConfigAddEntry(configuration, "experiments", - "last", "ExampleExperiment2", "ExampleVariable", - "/path/to/ExampleExperiment2/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "last", "ExampleExperiment2", "ExampleVariable", + "/path/to/ExampleExperiment2/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Edit entry to generalize for any variable. Changing variable needs . configuration <- ConfigEditEntry(configuration, "experiments", 1, - var_name = ".*", - file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") + var_name = ".*", + file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") # Now apply matching entries for variable and experiment name and show the # result match_info <- ConfigApplyMatchingEntries(configuration, 'tas', - exp = c('ExampleExperiment2'), show_result = TRUE) + exp = c('ExampleExperiment2'), show_result = TRUE) +} +\author{ +History: + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version +} +\seealso{ +[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], + [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], + [ConfigShowTable()]. } \keyword{datagen} + diff --git a/man/ConfigEditEntry.Rd b/man/ConfigEditEntry.Rd index d7394588..e6f2fb88 100644 --- a/man/ConfigEditEntry.Rd +++ b/man/ConfigEditEntry.Rd @@ -1,57 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ConfigEditEntry.R \name{ConfigEditEntry} -\alias{ConfigAddEntry} \alias{ConfigEditEntry} -\alias{ConfigRemoveEntry} -\title{ -Add, Remove Or Edit Entries In The Configuration -} -\description{ -ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions to manage entries in a configuration object created with ConfigFileOpen().\cr -Before adding an entry, make sure the defaults don't do already what you want (ConfigShowDefinitions(), ConfigShowTable()).\cr -Before adding an entry, make sure it doesn't override and spoil what other entries do (ConfigShowTable(), ConfigFileOpen()).\cr -Before adding an entry, make sure there aren't other entries that already do what you want (ConfigShowSimilarEntries()).\cr -} +\title{Add, Remove Or Edit Entries In The Configuration} \usage{ -ConfigAddEntry(configuration, dataset_type, position = "last", - dataset_name = ".*", var_name = ".*", main_path = "*", - file_path = "*", nc_var_name = "*", suffix = "*", - varmin = "*", varmax = "*") -ConfigEditEntry(configuration, dataset_type, position, - dataset_name = NULL, var_name = NULL, main_path = NULL, - file_path = NULL, nc_var_name = NULL, - suffix = NULL, varmin = NULL, varmax = NULL) -ConfigRemoveEntry(configuration, dataset_type, - dataset_name = NULL, var_name = NULL, position = NULL) +ConfigEditEntry(configuration, dataset_type, position, dataset_name = NULL, + var_name = NULL, main_path = NULL, file_path = NULL, + nc_var_name = NULL, suffix = NULL, varmin = NULL, varmax = NULL) } \arguments{ - \item{configuration}{ -Configuration object obtained via ConfigFileOpen() or ConfigFileCreate() that will be modified accordingly. - } - \item{dataset_type}{ -Whether to modify a table of experimental datasets or a table of observational datasets. Can take values 'experiments' or 'observations' respectively. - } - \item{position}{ -'position' tells the index in the table of the entry to edit or remove. Use ConfigShowTable() to see the index of the entry.\cr -In ConfigAddEntry() it can also take the value "last" (default), that will put the entry at the end of the corresponding level, or "first" at the beginning. See ?ConfigFileOpen for more information.\cr -If 'dataset_name' and 'var_name' are specified this argument is ignored in ConfigRemoveEntry(). - } - \item{dataset_name,var_name,main_path,file_path,nc_var_name,suffix,varmin,varmax}{ -These parameters tell the dataset name, variable name, main path, ..., of the entry to add, edit or remove.\cr -'dataset_name' and 'var_name' can take as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen).\cr -Other parameters can take as a value a shell globbing expression (see ?ConfigFileOpen).\cr -'dataset_name' and 'var_name' take by default the regular expression '.*' (match any dataset and variable name), and the others take by default '*' (associate to the pair 'dataset_name' and 'var_name' all the defined default values. In this case '*' has a special behaviour, it won't be used as a shell globbing expression. See ?ConfigFileOpen and ?ConfigShowDefinitions).\cr -'var_min' and 'var_max' must be a character string.\cr -To define these values, you can use defined variables via $VARIABLE_NAME$ or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for more information.\cr - } +\item{configuration}{Configuration object obtained via ConfigFileOpen() +or ConfigFileCreate() that will be modified accordingly.} + +\item{dataset_type}{Whether to modify a table of experimental datasets or +a table of observational datasets. Can take values 'experiments' or +'observations' respectively.} + +\item{position}{'position' tells the index in the table of the entry to +edit or remove. Use ConfigShowTable() to see the index of the entry. +In ConfigAddEntry() it can also take the value "last" (default), that will +put the entry at the end of the corresponding level, or "first" at the +beginning. See ?ConfigFileOpen for more information. +If 'dataset_name' and 'var_name' are specified this argument is ignored in +ConfigRemoveEntry().} + +\item{dataset_name, var_name, main_path, file_path, nc_var_name, suffix, varmin, varmax}{These parameters tell the dataset name, variable name, main path, ..., of +the entry to add, edit or remove. 'dataset_name' and 'var_name' can take +as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen). +Other parameters can take as a value a shell globbing expression +(see ?ConfigFileOpen). +'dataset_name' and 'var_name' take by default the regular expression '.*' +(match any dataset and variable name), and the others take by default '*' +(associate to the pair 'dataset_name' and 'var_name' all the defined +default values. In this case '*' has a special behaviour, it won't be +used as a shell globbing expression. See ?ConfigFileOpen and +?ConfigShowDefinitions). +'var_min' and 'var_max' must be a character string. +To define these values, you can use defined variables via $VARIABLE_NAME$ +or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for +more information.} } \value{ -The function returns an accordingly modified configuration object. To apply the changes in the configuration file it must be saved using ConfigFileSave(). +The function returns an accordingly modified configuration object. + To apply the changes in the configuration file it must be saved using + ConfigFileSave(). } -\seealso{ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable} -\author{ -History:\cr -0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - First version -1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Removed grid column and storage formats +\description{ +ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions +to manage entries in a configuration object created with ConfigFileOpen(). +Before adding an entry, make sure the defaults don't do already what you +want (ConfigShowDefinitions(), ConfigShowTable()). +Before adding an entry, make sure it doesn't override and spoil what other +entries do (ConfigShowTable(), ConfigFileOpen()). +Before adding an entry, make sure there aren't other entries that already +do what you want (ConfigShowSimilarEntries()). } \examples{ # Create an empty configuration file @@ -63,24 +65,33 @@ configuration <- ConfigFileOpen(config_file) # table which will associate the experiment "ExampleExperiment" and variable # "ExampleVariable" to some information about its location. configuration <- ConfigAddEntry(configuration, "experiments", - "last", "ExampleExperiment", "ExampleVariable", - "/path/to/ExampleExperiment/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "last", "ExampleExperiment", "ExampleVariable", + "/path/to/ExampleExperiment/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Add another entry configuration <- ConfigAddEntry(configuration, "experiments", - "last", "ExampleExperiment2", "ExampleVariable", - "/path/to/ExampleExperiment2/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "last", "ExampleExperiment2", "ExampleVariable", + "/path/to/ExampleExperiment2/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Edit second entry to generalize for any variable. Changing variable needs . configuration <- ConfigEditEntry(configuration, "experiments", 2, - var_name = ".*", - file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") + var_name = ".*", + file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") # Remove first entry configuration <- ConfigRemoveEntry(configuration, "experiments", - "ExampleExperiment", "ExampleVariable") + "ExampleExperiment", "ExampleVariable") # Show results ConfigShowTable(configuration, "experiments") # Save the configuration ConfigFileSave(configuration, config_file, confirm = FALSE) } +\author{ +History: + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version + 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats +} +\seealso{ +[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], [ConfigShowTable()]. +} \keyword{datagen} + diff --git a/man/ConfigFileOpen.Rd b/man/ConfigFileOpen.Rd index c42153fb..d515646e 100644 --- a/man/ConfigFileOpen.Rd +++ b/man/ConfigFileOpen.Rd @@ -1,151 +1,157 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ConfigFileOpen.R \name{ConfigFileOpen} \alias{ConfigFileOpen} -\alias{ConfigFileCreate} -\alias{ConfigFileSave} -\title{ -Functions To Create Open And Save Configuration File -} -\description{ -These functions help in creating, opening and saving configuration files. -} +\title{Functions To Create Open And Save Configuration File} \usage{ ConfigFileOpen(file_path, silent = FALSE, stop = FALSE) -ConfigFileCreate(file_path, confirm = TRUE) -ConfigFileSave(configuration, file_path, confirm = TRUE) } \arguments{ - \item{file_path}{ -Path to the configuration file to create/open/save. - } - \item{silent}{ -Flag to activate or deactivate verbose mode.\cr -Defaults to FALSE (verbose mode on). - } - \item{configuration}{ -Configuration object to save in a file. - } - \item{confirm}{ -Flag to stipulate whether to ask for confirmation when saving a configuration file that already exists.\cr -Defaults to TRUE (confirmation asked). - } - \item{stop}{ -TRUE/FALSE whether to raise an error if not all the mandatory default variables are defined in the configuration file.\cr - } +\item{file_path}{Path to the configuration file to create/open/save.} + +\item{silent}{Flag to activate or deactivate verbose mode. +Defaults to FALSE (verbose mode on).} + +\item{stop}{TRUE/FALSE whether to raise an error if not all the mandatory +default variables are defined in the configuration file.} + +\item{configuration}{Configuration object to save in a file.} + +\item{confirm}{Flag to stipulate whether to ask for confirmation when saving +a configuration file that already exists. +Defaults to TRUE (confirmation asked).} +} +\value{ +ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work. +ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise. +ConfigFileCreate() returns nothing. +} +\description{ +These functions help in creating, opening and saving configuration files. } \details{ -ConfigFileOpen() loads all the data contained in the configuration file specified as parameter 'file_path'.\cr -Returns a configuration object with the variables needed for the configuration file mechanism to work.\cr -This function is called from inside the Load() function to load the configuration file specified in 'configfile'.\cr -\cr -ConfigFileCreate() creates an empty configuration file and saves it to the specified path. It may be opened later with ConfigFileOpen() to be edited. Some default values are set when creating a file with this function, you can check these with ConfigShowDefinitions().\cr -\cr -ConfigFileSave() saves a configuration object into a file, which may then be used from Load().\cr -\cr -Two examples of configuration files can be found inside the 'inst/config/' folder in the package: - \itemize{ - \item{BSC.conf: configuration file used at BSC-CNS. Contains location data on several datasets and variables.} - \item{template.conf: very simple configuration file intended to be used as pattern when starting from scratch.} - } +ConfigFileOpen() loads all the data contained in the configuration file +specified as parameter 'file_path'. +Returns a configuration object with the variables needed for the +configuration file mechanism to work. +This function is called from inside the Load() function to load the +configuration file specified in 'configfile'.\cr\cr +ConfigFileCreate() creates an empty configuration file and saves it to +the specified path. It may be opened later with ConfigFileOpen() to be edited. +Some default values are set when creating a file with this function, you +can check these with ConfigShowDefinitions().\cr\cr +ConfigFileSave() saves a configuration object into a file, which may then +be used from Load().\cr\cr +Two examples of configuration files can be found inside the 'inst/config/' +folder in the package: + \itemize{ + \item{BSC.conf: configuration file used at BSC-CNS. Contains location + data on several datasets and variables.} + \item{template.conf: very simple configuration file intended to be used as + pattern when starting from scratch.} + } How the configuration file works:\cr ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - It contains one list and two tables.\cr -Each of these have a header that starts with '!!'. These are key lines and should not be removed or reordered.\cr +Each of these have a header that starts with '!!'. These are key lines and +should not be removed or reordered.\cr Lines starting with '#' and blank lines will be ignored. - The list should contains variable definitions and default value definitions.\cr - The first table contains information about experiments.\cr The third table contains information about observations.\cr - Each table entry is a list of comma-separated elements.\cr -The two first are part of a key that is associated to a value formed by the other elements.\cr +The two first are part of a key that is associated to a value formed by the +other elements.\cr The key elements are a dataset identifier and a variable name.\cr -The value elements are the dataset main path, dataset file path, the variable name inside the .nc file, a default suffix (explained below) and a minimum and maximum vaues beyond which loaded data is deactivated. - -Given a dataset name and a variable name, a full path is obtained concatenating the main path and the file path.\cr -Also the nc variable name, the suffixes and the limit values are obtained. - -Any of the elements in the keys can contain regular expressions[1] that will cause matching for sets of dataset names or variable names. - -The dataset path and file path can contain shell globbing expressions[2] that will cause matching for sets of paths when fetching the file in the full path.\cr -The full path can point to an OPeNDAP URL. - -Any of the elements in the value can contain variables that will be replaced to an associated string.\cr +The value elements are the dataset main path, dataset file path, the +variable name inside the .nc file, a default suffix (explained below) and a +minimum and maximum vaues beyond which loaded data is deactivated. +Given a dataset name and a variable name, a full path is obtained +concatenating the main path and the file path.\cr +Also the nc variable name, the suffixes and the limit values are obtained.\cr +Any of the elements in the keys can contain regular expressions[1] that will +cause matching for sets of dataset names or variable names.\cr +The dataset path and file path can contain shell globbing expressions[2] +that will cause matching for sets of paths when fetching the file in the +full path.\cr +The full path can point to an OPeNDAP URL.\cr +Any of the elements in the value can contain variables that will be replaced +to an associated string.\cr Variables can be defined only in the list at the top of the file. \cr The pattern of a variable definition is\cr - VARIABLE_NAME = VARIABLE_VALUE\cr -and can be accessed from within the table values or from within the variable values as\cr - $VARIABLE_NAME$\cr +VARIABLE_NAME = VARIABLE_VALUE\cr +and can be accessed from within the table values or from within the variable +values as\cr + $VARIABLE_NAME$\cr For example:\cr - FILE_NAME = tos.nc\cr - !!table of experiments\cr - ecmwf, tos, /path/to/dataset/, $FILE_NAME$\cr -There are some reserved variables that will offer information about the store frequency, the current startdate Load() is fetching, etc:\cr - $VAR_NAME$, $START_DATE$, $STORE_FREQ$, $MEMBER_NUMBER$\cr - for experiments only: $EXP_NAME$\cr - for observations only: $OBS_NAME$, $YEAR$, $MONTH$, $DAY$\cr -Additionally, from an element in an entry value you can access the other elements of the entry as:\cr - $EXP_MAIN_PATH$, $EXP_FILE_PATH$, \cr$VAR_NAME$, $SUFFIX$, $VAR_MIN$, $VAR_MAX$\cr - -The variable $SUFFIX$ is useful because it can be used to take part in the main or file path. For example: '/path/to$SUFFIX$/dataset/'.\cr -It will be replaced by the value in the column that corresponds to the suffix unless the user specifies a different suffix via the parameter 'suffixexp' or 'suffixobs'.\cr -This way the user is able to load two variables with the same name in the same dataset but with slight modifications, with a suffix anywhere in the path to the data that advices of this slight modification. - + FILE_NAME = tos.nc\cr + !!table of experiments\cr + ecmwf, tos, /path/to/dataset/, $FILE_NAME$\cr +There are some reserved variables that will offer information about the +store frequency, the current startdate Load() is fetching, etc:\cr + $VAR_NAME$, $START_DATE$, $STORE_FREQ$, $MEMBER_NUMBER$\cr + for experiments only: $EXP_NAME$\cr + for observations only: $OBS_NAME$, $YEAR$, $MONTH$, $DAY$\cr +Additionally, from an element in an entry value you can access the other +elements of the entry as:\cr + $EXP_MAIN_PATH$, $EXP_FILE_PATH$, \cr$VAR_NAME$, $SUFFIX$, $VAR_MIN$, $VAR_MAX$\cr +The variable $SUFFIX$ is useful because it can be used to take part in the +main or file path. For example: '/path/to$SUFFIX$/dataset/'.\cr +It will be replaced by the value in the column that corresponds to the +suffix unless the user specifies a different suffix via the parameter +'suffixexp' or 'suffixobs'.\cr +This way the user is able to load two variables with the same name in the +same dataset but with slight modifications, with a suffix anywhere in the +path to the data that advices of this slight modification.\cr The entries in a table will be grouped in 4 levels of specificity: - \enumerate{ - \item{ + \enumerate{ + \item{ General entries:\cr - - the key dataset name and variable name are both a regular expression matching any sequence of characters (.*) that will cause matching for any pair of dataset and variable names\cr - Example: .*, .*, /dataset/main/path/, file/path, nc_var_name, suffix, var_min, var_max - } - \item{ +- the key dataset name and variable name are both a regular expression +matching any sequence of characters (.*) that will cause matching for any +pair of dataset and variable names\cr + Example: .*, .*, /dataset/main/path/, file/path, nc_var_name, suffix, +var_min, var_max + } + \item{ Dataset entries:\cr - - the key variable name matches any sequence of characters\cr - Example: ecmwf, .*, /dataset/main/path/, file/path, nc_var_name, suffix, var_min, var_max - } - \item{ +- the key variable name matches any sequence of characters\cr + Example: ecmwf, .*, /dataset/main/path/, file/path, nc_var_name, + suffix, var_min, var_max + } + \item{ Variable entries:\cr - - the key dataset name matches any sequence of characters\cr - Example: .*, tos, /dataset/main/path/, file/path, nc_var_name, suffix, var_min, var_max - } - \item{ -Specific entries:\cr - - both key values are specified\cr - Example: ecmwf, tos, /dataset/main/path/, file/path, nc_var_name, suffix, var_min, var_max - } - } - -Given a pair of dataset name and variable name for which we want to know the full path, all the rules that match will be applied from more general to more specific.\cr -If there is more than one entry per group that match a given key pair, these will be applied in the order of appearance in the configuration file (top to bottom). - -An asterisk (*) in any value element will be interpreted as 'leave it as is or take the default value if yet not defined'.\cr +- the key dataset name matches any sequence of characters\cr + Example: .*, tos, /dataset/main/path/, file/path, nc_var_name, + suffix, var_min, var_max + } + \item{ + Specific entries:\cr +- both key values are specified\cr + Example: ecmwf, tos, /dataset/main/path/, file/path, nc_var_name, + suffix, var_min, var_max + } + } +Given a pair of dataset name and variable name for which we want to know the +full path, all the rules that match will be applied from more general to +more specific.\cr +If there is more than one entry per group that match a given key pair, +these will be applied in the order of appearance in the configuration file +(top to bottom).\cr +An asterisk (*) in any value element will be interpreted as 'leave it as is +or take the default value if yet not defined'.\cr The default values are defined in the following reserved variables:\cr - $DEFAULT_EXP_MAIN_PATH$, $DEFAULT_EXP_FILE_PATH$, $DEFAULT_NC_VAR_NAME$, $DEFAULT_OBS_MAIN_PATH$, $DEFAULT_OBS_FILE_PATH$, $DEFAULT_SUFFIX$, $DEFAULT_VAR_MIN$, $DEFAULT_VAR_MAX$, \cr + $DEFAULT_EXP_MAIN_PATH$, $DEFAULT_EXP_FILE_PATH$, $DEFAULT_NC_VAR_NAME$, +$DEFAULT_OBS_MAIN_PATH$, $DEFAULT_OBS_FILE_PATH$, $DEFAULT_SUFFIX$, +$DEFAULT_VAR_MIN$, $DEFAULT_VAR_MAX$, \cr $DEFAULT_DIM_NAME_LATITUDES$, $DEFAULT_DIM_NAME_LONGITUDES$, \cr $DEFAULT_DIM_NAME_MEMBERS$\cr - Trailing asterisks in an entry are not mandatory. For example\cr - ecmwf, .*, /dataset/main/path/, *, *, *, *, *\cr + ecmwf, .*, /dataset/main/path/, *, *, *, *, *\cr will have the same effect as\cr - ecmwf, .*, /dataset/main/path/ - -A double quote only (") in any key or value element will be interpreted as 'fill in with the same value as the entry above'. -} -\value{ -ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work.\cr -ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise.\cr -ConfigFileCreate() returns nothing. -} -\seealso{ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable} -\references{ -[1] https://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html\cr -[2] http://tldp.org/LDP/abs/html/globbingref.html -} -\author{ -History:\cr -0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - First version -1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Removed grid column and storage formats + ecmwf, .*, /dataset/main/path/ +A double quote only (") in any key or value element will be interpreted as +'fill in with the same value as the entry above'. } \examples{ # Create an empty configuration file @@ -157,18 +163,33 @@ configuration <- ConfigFileOpen(config_file) # table which will associate the experiment "ExampleExperiment2" and variable # "ExampleVariable" to some information about its location. configuration <- ConfigAddEntry(configuration, "experiments", - "last", "ExampleExperiment2", "ExampleVariable", - "/path/to/ExampleExperiment2/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "last", "ExampleExperiment2", "ExampleVariable", + "/path/to/ExampleExperiment2/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Edit entry to generalize for any variable. Changing variable needs . configuration <- ConfigEditEntry(configuration, "experiments", 1, - var_name = ".*", - file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") + var_name = ".*", + file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") # Now apply matching entries for variable and experiment name and show the # result match_info <- ConfigApplyMatchingEntries(configuration, 'tas', - exp = c('ExampleExperiment2'), show_result = TRUE) + exp = c('ExampleExperiment2'), show_result = TRUE) # Finally save the configuration file. ConfigFileSave(configuration, config_file, confirm = FALSE) } +\author{ +History: + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version + 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats +} +\references{ +[1] \url{https://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html}\cr +[2] \url{http://tldp.org/LDP/abs/html/globbingref.html} +} +\seealso{ +[ConfigApplyMatchingEntries()]., [ConfigEditDefinition()]., + [ConfigEditEntry()]., [ConfigFileOpen()]., [ConfigShowSimilarEntries()]., + [ConfigShowTable()]. +} \keyword{datagen} + diff --git a/man/ConfigShowSimilarEntries.Rd b/man/ConfigShowSimilarEntries.Rd index 836a1ec9..d1498dd2 100644 --- a/man/ConfigShowSimilarEntries.Rd +++ b/man/ConfigShowSimilarEntries.Rd @@ -1,67 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ConfigShowSimilarEntries.R \name{ConfigShowSimilarEntries} \alias{ConfigShowSimilarEntries} -\title{ -Find Similar Entries In Tables Of Datasets -} -\description{ -These functions help in finding similar entries in tables of supported datasets by comparing all entries with some given information.\cr -This is useful when dealing with complex configuration files and not sure if already support certain variables or datasets.\cr -At least one field must be provided in ConfigShowSimilarEntries(). Other fields can be unspecified and won't be taken into account. If more than one field is provided, sameness is avreaged over all provided fields and entries are sorted from higher average to lower. -} +\title{Find Similar Entries In Tables Of Datasets} \usage{ -ConfigShowSimilarEntries(configuration, dataset_name = NULL, - var_name = NULL, main_path = NULL, - file_path = NULL, nc_var_name = NULL, - suffix = NULL, varmin = NULL, - varmax = NULL, n_results = 10) +ConfigShowSimilarEntries(configuration, dataset_name = NULL, + var_name = NULL, main_path = NULL, file_path = NULL, + nc_var_name = NULL, suffix = NULL, varmin = NULL, varmax = NULL, + n_results = 10) } \arguments{ - \item{configuration}{ -Configuration object obtained either from ConfigFileCreate() or ConfigFileOpen(). - } - \item{dataset_name}{ -Optional dataset name to look for similars of. - } - \item{var_name}{ -Optional variable name to look for similars of. - } - \item{main_path}{ -Optional main path to look for similars of. - } - \item{file_path}{ -Optional file path to look for similars of. - } - \item{nc_var_name}{ -Optional variable name inside NetCDF file to look for similars of. - } - \item{suffix}{ -Optional suffix to look for similars of. - } - \item{varmin}{ -Optional variable minimum to look for similars of. - } - \item{varmax}{ -Optional variable maximum to look for similars of. - } - \item{n_results}{ -Top 'n_results' alike results will be shown only.\cr -Defaults to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). - } -} -\details{ -Sameness is calculated with string distances as specified by Simon White in [1]. +\item{configuration}{Configuration object obtained either from +ConfigFileCreate() or ConfigFileOpen().} + +\item{dataset_name}{Optional dataset name to look for similars of.} + +\item{var_name}{Optional variable name to look for similars of.} + +\item{main_path}{Optional main path to look for similars of.} + +\item{file_path}{Optional file path to look for similars of.} + +\item{nc_var_name}{Optional variable name inside NetCDF file to look for similars of.} + +\item{suffix}{Optional suffix to look for similars of.} + +\item{varmin}{Optional variable minimum to look for similars of.} + +\item{varmax}{Optional variable maximum to look for similars of.} + +\item{n_results}{Top 'n_results' alike results will be shown only. Defaults + to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). + +Sameness is calculated with string distances as specified by Simon White +in [1].} } \value{ These functions return information about the found matches. } -\seealso{ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable} -\references{ -[1] Simon White, string seamness: http://www.catalysoft.com/articles/StrikeAMatch.html -} -\author{ -History:\cr -0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - First version -1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Removed grid column and storage formats +\description{ +These functions help in finding similar entries in tables of supported +datasets by comparing all entries with some given information. +This is useful when dealing with complex configuration files and not sure +if already support certain variables or datasets. +At least one field must be provided in ConfigShowSimilarEntries(). +Other fields can be unspecified and won't be taken into account. If more +than one field is provided, sameness is avreaged over all provided fields +and entries are sorted from higher average to lower. } \examples{ # Create an empty configuration file @@ -73,15 +58,31 @@ configuration <- ConfigFileOpen(config_file) # table which will associate the experiment "ExampleExperiment2" and variable # "ExampleVariable" to some information about its location. configuration <- ConfigAddEntry(configuration, "experiments", "last", - "ExampleExperiment2", "ExampleVariable", - "/path/to/ExampleExperiment2/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "ExampleExperiment2", "ExampleVariable", + "/path/to/ExampleExperiment2/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Edit entry to generalize for any variable. Changing variable needs . configuration <- ConfigEditEntry(configuration, "experiments", 1, - var_name = "Var.*", - file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") + var_name = "Var.*", + file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") # Look for similar entries ConfigShowSimilarEntries(configuration, dataset_name = "Exper", - var_name = "Vari") + var_name = "Vari") + +} +\author{ +History:\cr + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version + 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats +} +\references{ +[1] Simon White, string seamness: + \url{http://www.catalysoft.com/articles/StrikeAMatch.html} +} +\seealso{ +[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], + [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], + [ConfigShowTable()]. } \keyword{datagen} + diff --git a/man/ConfigShowTable.Rd b/man/ConfigShowTable.Rd index 0ba3fe28..1c6a24ec 100644 --- a/man/ConfigShowTable.Rd +++ b/man/ConfigShowTable.Rd @@ -1,37 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ConfigShowTable.R \name{ConfigShowTable} \alias{ConfigShowTable} -\alias{ConfigShowDefinitions} -\title{ -Show Configuration Tables And Definitions -} -\description{ -These functions show the tables of supported datasets and definitions in a configuration object obtained via ConfigFileCreate() or ConfigFileOpen(). -} +\title{Show Configuration Tables And Definitions} \usage{ ConfigShowTable(configuration, dataset_type, line_numbers = NULL) -ConfigShowDefinitions(configuration) } \arguments{ - \item{configuration}{ -Configuration object obtained from ConfigFileCreate() or ConfigFileOpen(). - } - \item{dataset_type}{ -In ConfigShowTable(), 'dataset_type' tells whether the table to show is of experimental datasets or of observational datasets.\cr -Can take values 'experiments' or 'observations'. - } - \item{line_numbers}{ -'line_numbers' is an optional vector of numbers as long as the number of entries in the specified table.\cr -Intended for internal use. - } +\item{configuration}{Configuration object obtained from ConfigFileCreate() +or ConfigFileOpen().} + +\item{dataset_type}{In ConfigShowTable(), 'dataset_type' tells whether the +table to show is of experimental datasets or of observational datasets. +Can take values 'experiments' or 'observations'.} + +\item{line_numbers}{'line_numbers' is an optional vector of numbers as long +as the number of entries in the specified table. Intended for internal use.} } \value{ These functions return nothing. } -\seealso{ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable} -\author{ -History:\cr -0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - First version -1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Removed grid column and storage formats +\description{ +These functions show the tables of supported datasets and definitions in a +configuration object obtained via ConfigFileCreate() or ConfigFileOpen(). } \examples{ # Create an empty configuration file @@ -43,15 +34,26 @@ configuration <- ConfigFileOpen(config_file) # table which will associate the experiment "ExampleExperiment2" and variable # "ExampleVariable" to some information about its location. configuration <- ConfigAddEntry(configuration, "experiments", "last", - "ExampleExperiment2", "ExampleVariable", - "/path/to/ExampleExperiment2/", - "ExampleVariable/ExampleVariable_$START_DATE$.nc") + "ExampleExperiment2", "ExampleVariable", + "/path/to/ExampleExperiment2/", + "ExampleVariable/ExampleVariable_$START_DATE$.nc") # Edit entry to generalize for any variable. Changing variable needs . configuration <- ConfigEditEntry(configuration, "experiments", 1, - var_name = ".*", - file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") + var_name = ".*", + file_path = "$VAR_NAME$/$VAR_NAME$_$START_DATE$.nc") # Show tables, lists and definitions ConfigShowTable(configuration, 'experiments') ConfigShowDefinitions(configuration) } +\author{ +History:cr + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version + 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats +} +\seealso{ +[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], + [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], + [ConfigShowTable()]. +} \keyword{datagen} + diff --git a/man/Consist_Trend.Rd b/man/Consist_Trend.Rd index 6f964bf8..aea78bc0 100644 --- a/man/Consist_Trend.Rd +++ b/man/Consist_Trend.Rd @@ -1,48 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Consist_Trend.R \name{Consist_Trend} \alias{Consist_Trend} -\title{ -Computes Trends Using Only Model Data For Which Observations Are Available -} -\description{ -Computes the trend coefficients for a time series by least square fitting, together with the associated error interval for both the observational and model data.\cr -Provides also the detrended observational and modeled data.\cr -By default, the trend is computed along the second dimension of the input array, which is expected to be the start date dimension. For arrays containing multiple model members, the user will first have to calculate the ensemble average using \code{Mean1Dim()} or elsewhise (see the example). -} +\title{Computes Trends Using Only Model Data For Which Observations Are Available} \usage{ Consist_Trend(var_exp, var_obs, interval = 1) } \arguments{ - \item{var_exp}{ -Ensemble mean of model hindcasts with dimensions:\cr - c(nmod/nexp, nsdates, nltime) up to\cr - c(nmod/nexp, nsdates, nltime, nlevel, nlat, nlon) - } - \item{var_obs}{ -Ensemble mean of observational data with dimensions:\cr - c(nobs, nsdates, nltime) up to\cr - c(nobs, nsdates, nltime, nlevel, nlat, nlon)\cr -Dimensions 2 to 6 should be the same as var_exp. - } - \item{interval}{ -Number of months/years between 2 start dates. Default = 1. The trends will be provided respectively in field unit per month or per year. - } +\item{var_exp}{Ensemble mean of model hindcasts with dimensions:\cr +c(nmod/nexp, nsdates, nltime) up to\cr +c(nmod/nexp, nsdates, nltime, nlevel, nlat, nlon)} + +\item{var_obs}{Ensemble mean of observational data with dimensions:\cr +c(nobs, nsdates, nltime) up to\cr +c(nobs, nsdates, nltime, nlevel, nlat, nlon)\cr +Dimensions 2 to 6 should be the same as var_exp.} + +\item{interval}{Number of months/years between 2 start dates. Default = 1. +The trends will be provided respectively in field unit per month or per year.} } \value{ - \item{$trend}{ -Trend coefficients of model and observational data with dimensions:\cr - c(nmod/nexp + nobs, 3, nltime) up to\cr - c(nmod/nexp + nobs, 3, nltime, nlevel, nlat, nlon)\cr -The length 3 dimension corresponds to the lower limit of the 95\% confidence interval, the slope of the trends and the upper limit of the 95\% confidence interval. - } - \item{$detrendedmod}{ -Same dimensions as var_exp with linearly detrended values of var_exp along the second = start date dimension. - } - \item{$detrendedobs}{ -Same dimensions as var_exp with linearly detrended values of var_obs along the second = start date dimension. - } +\itemize{ +\item{$trend}{Trend coefficients of model and observational data with + dimensions:\cr + c(nmod/nexp + nobs, 3, nltime) up to\cr + c(nmod/nexp + nobs, 3, nltime, nlevel, nlat, nlon)\cr + The length 3 dimension corresponds to the lower limit of the 95\% + confidence interval, the slope of the trends and the upper limit of the + 95\% confidence interval. +} +\item{$detrendedmod}{Same dimensions as var_exp with linearly detrended + values of var_exp along the second = start date dimension. +} +\item{$detrendedobs}{Same dimensions as var_exp with linearly detrended + values of var_obs along the second = start date dimension. +} +} +} +\description{ +Computes the trend coefficients for a time series by least square fitting, +together with the associated error interval for both the observational and +model data.\cr +Provides also the detrended observational and modeled data.\cr +By default, the trend is computed along the second dimension of the input +array, which is expected to be the start date dimension. For arrays +containing multiple model members, the user will first have to calculate +the ensemble average using \code{Mean1Dim()} or elsewhise (see the example). } \examples{ -# Load sample data as in Load() example: +#'# Load sample data as in Load() example: example(Load) clim <- Clim(sampleData$mod, sampleData$obs) ano_exp <- Ano(sampleData$mod, clim$clim_exp) @@ -54,20 +60,22 @@ smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) dim_to_mean <- 2 # Mean along members years_between_startdates <- 5 trend <- Consist_Trend(Mean1Dim(smooth_ano_exp, dim_to_mean), - Mean1Dim(smooth_ano_obs, dim_to_mean), - years_between_startdates) + Mean1Dim(smooth_ano_obs, dim_to_mean), + years_between_startdates) PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K/(5 years)", - monini = 11, limits = c(-0.8, 0.8), listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, hlines = c(0), - fileout = 'tos_consist_trend.eps') + monini = 11, limits = c(-0.8, 0.8), listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, hlines = c(0), + fileout = 'tos_consist_trend.eps') PlotAno(InsertDim(trend$detrendedmod,2,1), InsertDim(trend$detrendedobs,2,1), - startDates, "Detrended tos anomalies", ytitle = 'K', - legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_ano.eps') + startDates, "Detrended tos anomalies", ytitle = 'K', + legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_ano.eps') + } \author{ History:\cr -0.1 - 2011-11 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN + 0.1 - 2011-11 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN } \keyword{datagen} + diff --git a/man/Corr.Rd b/man/Corr.Rd index ae4b9f00..f54af99d 100644 --- a/man/Corr.Rd +++ b/man/Corr.Rd @@ -1,79 +1,84 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Corr.R \name{Corr} \alias{Corr} -\alias{.Corr} -\title{ -Computes the correlation coefficient between an array of forecasts and their corresponding observations. -} -\description{ -Calculates the correlation coefficient (Pearson, Kendall or Spearman) for an array of forecasts and observations. The input should be an array with dimensions c(no. of datasets, no. of start dates, no. of forecast times, no. of lons, no. of lats.), where the longitude and latitude dimensions are optional. The correlations are computed along the poscor dimension which should correspond to the startdate dimension. If compROW is given, the correlations are computed only if rows along the compROW dimension are complete between limits[1] and limits[2], i.e. there are no NAs between limits[1] and limits[2]. This option can be activated if the user wishes to account only for the forecasts for which observations are available at all leadtimes. \cr Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr The confidence interval is computed by a Fisher transformation.\cr The significance level relies on a one-sided student-T distribution.\cr We can modifiy the treshold of the test modifying siglev (default value=0.95). \cr -\cr -.Corr calculates the correlation between the ensemble mean and the observations, using an N by M matrix (exp) of forecasts and a vector of observations (obs) as input. -} +\title{Computes the correlation coefficient between an array of forecasts and their corresponding observations} \usage{ -Corr(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, - limits = NULL, siglev = 0.95, method = 'pearson', - conf = TRUE, pval = TRUE) - -.Corr(exp, obs, siglev = 0.95, method = 'pearson', - conf = TRUE, pval = TRUE) +Corr(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, + limits = NULL, siglev = 0.95, method = "pearson", conf = TRUE, + pval = TRUE) } \arguments{ - \item{var_exp}{ -Array of experimental data. - } - \item{var_obs}{ -Array of observational data, same dimensions as var_exp except along posloop dimension, where the length can be nobs instead of nexp. - } - \item{posloop}{ -Dimension nobs and nexp. - } - \item{poscor}{ -Dimension along which correlation are to be computed (the dimension of the start dates). - } - \item{compROW}{ -Data taken into account only if (compROW)th row is complete.\cr Default = NULL. - } - \item{limits}{ -Complete between limits[1] & limits[2]. Default = NULL. - } - \item{siglev}{ -Significance level. Default = 0.95. - } - \item{method}{ -Type of correlation: 'pearson', 'spearman' or 'kendall'. Default='pearson' - } - \item{conf}{ -Whether to compute confidence intervals (default = 'TRUE') or not (FALSE). - } - \item{pval}{ -Whether to compute statistical significance p-value (default = 'TRUE') or not (FALSE). - } - \item{exp}{ -N by M matrix of N forecasts from M ensemble members. - } - \item{obs}{ -Vector of the corresponding observations of length N. - } +\item{var_exp}{Array of experimental data.} + +\item{var_obs}{Array of observational data, same dimensions as var_exp +except along posloop dimension, where the length can be nobs instead of nexp.} + +\item{posloop}{Dimension nobs and nexp.} + +\item{poscor}{Dimension along which correlation are to be computed (the +dimension of the start dates).} + +\item{compROW}{Data taken into account only if (compROW)th row is complete. +\cr Default = NULL.} + +\item{limits}{Complete between limits[1] & limits[2]. Default = NULL.} + +\item{siglev}{Significance level. Default = 0.95.} + +\item{method}{Type of correlation: 'pearson', 'spearman' or 'kendall'. +Default='pearson'} + +\item{conf}{Whether to compute confidence intervals (default = 'TRUE') or +not (FALSE).} + +\item{pval}{Whether to compute statistical significance p-value (default = 'TRUE') +or not (FALSE).} + +\item{exp}{N by M matrix of N forecasts from M ensemble members.} + +\item{obs}{Vector of the corresponding observations of length N.} } \value{ -Corr: Array with dimensions :\cr c(# of datasets along posloop in var_exp, # of datasets along posloop in var_obs, 4, all other dimensions of var_exp & var_obs except poscor).\cr -The third dimension, of length 4 maximum, contains to the lower limit of the 95\% confidence interval, the correlation, the upper limit of the 95\% confidence interval and the 95\% significance level given by a one-sided T-test. If the p-value is disabled via \code{pval = FALSE}, this dimension will be of length 3. If the confidence intervals are disabled via \code{conf = FALSE}, this dimension will be of length 2. If both are disabled, this will be of length 2. \cr -\cr +Corr: Array with dimensions :\cr +c(# of datasets along posloop in var_exp, # of datasets along posloop in +var_obs, 4, all other dimensions of var_exp & var_obs except poscor).\cr +The third dimension, of length 4 maximum, contains to the lower limit of +the 95\% confidence interval, the correlation, the upper limit of the 95\% +confidence interval and the 95\% significance level given by a one-sided +T-test. If the p-value is disabled via \code{pval = FALSE}, this dimension +will be of length 3. If the confidence intervals are disabled via +\code{conf = FALSE}, this dimension will be of length 2. If both are +disabled, this will be of length 2. \cr\cr .Corr: - \itemize{ - \item{$corr}{ -The correlation statistic. - } - \item{$p_val}{ -Corresponds to the p values for the \code{siglev}\% (only present if \code{pval = TRUE}) for the correlation. - } - \item{$conf_low}{ -Corresponds to the upper limit of the \code{siglev}\% (only present if \code{conf = TRUE}) for the correlation. - } - \item{$conf_high}{ -Corresponds to the lower limit of the \code{siglev}\% (only present if \code{conf = TRUE}) for the correlation. - } - } + \itemize{ + \item{$corr}{The correlation statistic.} + \item{$p_val}{Corresponds to the p values for the \code{siglev}\% + (only present if \code{pval = TRUE}) for the correlation.} + \item{$conf_low}{Corresponds to the upper limit of the \code{siglev}\% + (only present if \code{conf = TRUE}) for the correlation.} + \item{$conf_high}{Corresponds to the lower limit of the \code{siglev}\% + (only present if \code{conf = TRUE}) for the correlation.} + } +} +\description{ +Calculates the correlation coefficient (Pearson, Kendall or Spearman) for +an array of forecasts and observations. The input should be an array with +dimensions c(no. of datasets, no. of start dates, no. of forecast times, +no. of lons, no. of lats.), where the longitude and latitude dimensions are +optional. The correlations are computed along the poscor dimension which +should correspond to the startdate dimension. If compROW is given, the +correlations are computed only if rows along the compROW dimension are +complete between limits[1] and limits[2], i.e. there are no NAs between +limits[1] and limits[2]. This option can be activated if the user wishes to +account only for the forecasts for which observations are available at all +leadtimes. \cr +Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr +The confidence interval is computed by a Fisher transformation.\cr +The significance level relies on a one-sided student-T distribution.\cr +We can modifiy the treshold of the test modifying siglev (default value=0.95).\cr\cr +observations, using an N by M matrix (exp) of forecasts and a vector of +observations (obs) as input. } \examples{ # Load sample data as in Load() example: @@ -90,32 +95,33 @@ dim_to_mean <- 2 # Mean along members required_complete_row <- 3 # Discard start dates which contain any NA lead-times leadtimes_per_startdate <- 60 corr <- Corr(Mean1Dim(smooth_ano_exp, dim_to_mean), - Mean1Dim(smooth_ano_obs, dim_to_mean), - compROW = required_complete_row, - limits = c(ceiling((runmean_months + 1) / 2), - leadtimes_per_startdate - floor(runmean_months / 2))) + Mean1Dim(smooth_ano_obs, dim_to_mean), + compROW = required_complete_row, + limits = c(ceiling((runmean_months + 1) / 2), + leadtimes_per_startdate - floor(runmean_months / 2))) PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", - monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), - fileout = 'tos_cor.eps') + monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), + fileout = 'tos_cor.eps') # The following example uses veriApply combined with .Corr instead of Corr - \dontrun{ + \dontrun{ require(easyVerification) Corr2 <- s2dverification:::.Corr corr2 <- veriApply("Corr2", - smooth_ano_exp, - # see ?veriApply for how to use the 'parallel' option - Mean1Dim(smooth_ano_obs, dim_to_mean), - tdim = 3, ensdim = 2) - } + smooth_ano_exp, + # see ?veriApply for how to use the 'parallel' option + Mean1Dim(smooth_ano_obs, dim_to_mean), + tdim = 3, ensdim = 2) + } } \author{ History:\cr -0.1 - 2011-04 (V. Guemas, \email{vguemas at bsc.es}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN\cr -1.1 - 2014-10 (M. Menegoz, \email{martin.menegoz at bsc.es}) - Adding siglev argument\cr -1.2 - 2015-03 (L.P. Caron, \email{louis-philippe.caron at bsc.es}) - Adding method argument\cr -1.3 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() + 0.1 - 2011-04 (V. Guemas, \email{vguemas@bsc.es}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN\cr +1.1 - 2014-10 (M. Menegoz, \email{martin.menegoz@bsc.es}) - Adding siglev argument\cr +1.2 - 2015-03 (L.P. Caron, \email{louis-philippe.caron@bsc.es}) - Adding method argument\cr +1.3 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() } \keyword{datagen} + diff --git a/man/EOF.Rd b/man/EOF.Rd index 7c914e15..7b256707 100644 --- a/man/EOF.Rd +++ b/man/EOF.Rd @@ -1,85 +1,72 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/EOF.R \name{EOF} \alias{EOF} -\title{ -Area-Weighted Empirical Orthogonal Function Analysis Using SVD -} -\description{ -Performs an area-weighted EOF analysis using SVD based on a covariance matrix -by default, based on the correlation matrix if \code{corr} argument is set to -\code{TRUE}. -} +\title{Area-Weighted Empirical Orthogonal Function Analysis Using SVD} \usage{ EOF(ano, lon, lat, neofs = 15, corr = FALSE) } \arguments{ - \item{ano}{ -Array of anomalies with dimensions (number of timesteps, number of latitudes, -number of longitudes). - } - \item{lon}{ -Vector of longitudes of \code{ano}. - } - \item{lat}{ -Vector of latitudes of \code{ano}. - } - \item{neofs}{ -Number of modes to be kept. Default = 15. - } - \item{corr}{ -Whether to base on a correlation matrix (\code{TRUE}) or on a covariance -matrix (default, \code{FALSE}). - } +\item{ano}{Array of anomalies with dimensions (number of timesteps, +number of latitudes, number of longitudes).} + +\item{lon}{Vector of longitudes of \code{ano}.} + +\item{lat}{Vector of latitudes of \code{ano}.} + +\item{neofs}{Number of modes to be kept. Default = 15.} + +\item{corr}{Whether to base on a correlation matrix (\code{TRUE}) or on a +covariance matrix (default, \code{FALSE}).} } \value{ - \item{EOFs}{ -An array of EOF patterns normalized to 1 (unitless) with dimensions (number of -modes, number of latitudes, number of longitues). Multiplying \code{EOFs} by -\code{PCs} gives the original reconstructed field. - } - \item{PCs}{ -An array of pincipal components with the units of the original field to the -power of 2, with dimensions (number of time steps, number of modes). \code{PCs} -contains already the percentage of explained variance so, to reconstruct the -original field it's only needed to multiply \code{EOFs} by \code{PCs}. - } - \item{var}{ -Percentage (%) of variance fraction of total variance explained by each mode -(number of modes). - } - \item{mask}{ -Mask with dimensions (number of latitudes, number of lonfitudes). - } - \item{wght}{ -Weights with dimensions (number of latitudes, number of longitudes). - } +\itemize{ + \item{EOFs}{An array of EOF patterns normalized to 1 (unitless) with + dimensions (number of modes, number of latitudes, number of longitues). + Multiplying \code{EOFs} by \code{PCs} gives the original reconstructed field.} + \item{PCs}{An array of pincipal components with the units of the original + field to the power of 2, with dimensions (number of time steps, number of + modes). \code{PCs} contains already the percentage of explained variance + so, to reconstruct the original field it's only needed to multiply + \code{EOFs} by \code{PCs}.} + \item{var}{Percentage (%) of variance fraction of total variance explained + by each mode (number of modes).} + \item{mask}{Mask with dimensions (number of latitudes, number of longitudes).} + \item{wght}{Weights with dimensions (number of latitudes, number of longitudes).} +} +} +\description{ +Performs an area-weighted EOF analysis using SVD based on a covariance matrix +by default, based on the correlation matrix if \code{corr} argument is set to +\code{TRUE}. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } # This example computes the EOFs along forecast horizons and plots the one that # explains the greatest amount of variability. The example data is very low # resolution so it does not make a lot of sense. @@ -89,35 +76,38 @@ PlotEquiMap(eof$EOFs[1, , ], sampleData$lon, sampleData$lat) } \author{ History:\cr -0.1 - 2012-10 (F. Lienert, \email{fabian.lienert at ic3.cat}) - Original\cr +0.1 - 2012-10 (F. Lienert, \email{fabian.lienert@ic3.cat}) - Original code, inspired by R. Benestad's EOF() in R package clim.pact.\cr -0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat}) - Bug-fixes:\cr - 1- Reversion of latitudes in the weights\cr - 2- Correlation matrix was used instead of covariance\cr - 3- Double use of the weights\cr -0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas at bsc.es}) - Bug-fixes:\cr - 1- Weight computation - division by sum of cos(lat)\cr - 2- Shuffling of EOFs in EOF.2 intermediate vector\cr - 3- Crash when neofs = 1 sorted out\cr - 4- Crash when neofs > nt sorted out\cr -0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat}) - Fixes:\cr - 1- BIG cleanup of code and clarification\cr - 2- Reduction of the number of transpositions and associated bug-fixes\cr - 4- Remove of the obsolete LINPACK options\cr -0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas at bsc.es}) - Fixes:\cr - 1- Bug-fix in dimensions handling EOF composition restitutes now the\ +0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte@ic3.cat}) - Bug-fixes:\cr + 1- Reversion of latitudes in the weights\cr + 2- Correlation matrix was used instead of covariance\cr + 3- Double use of the weights\cr +0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas@bsc.es}) - Bug-fixes:\cr + 1- Weight computation - division by sum of cos(lat)\cr + 2- Shuffling of EOFs in EOF.2 intermediate vector\cr + 3- Crash when neofs = 1 sorted out\cr + 4- Crash when neofs > nt sorted out\cr +0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte@ic3.cat}) - Fixes:\cr + 1- BIG cleanup of code and clarification\cr + 2- Reduction of the number of transpositions and associated bug-fixes\cr + 4- Remove of the obsolete LINPACK options\cr +0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas@bsc.es}) - Fixes:\cr + 1- Bug-fix in dimensions handling EOF composition restitutes now the\ original field in all cases\cr - 2- Simplification of the convention transpose\cr - 3- Options to use the correlation matrix rather than the + 2- Simplification of the convention transpose\cr + 3- Options to use the correlation matrix rather than the covariance matrix\cr - 4- Security checks\cr - 5- New normalization of PCs so that PC*EOF only reconstruct the + 4- Security checks\cr + 5- New normalization of PCs so that PC*EOF only reconstruct the original file\cr - 6- Weights = sqrt(cos(lat)) for ano so that covariance matrice + 6- Weights = sqrt(cos(lat)) for ano so that covariance matrice weighted by cos(lat)\cr - 7- Division of EOF by weights so that the reconstruction is simply + 7- Division of EOF by weights so that the reconstruction is simply EOF * PC\cr -1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN +1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN +} +\seealso{ +[ProjectField()], [NAO()], [PlotBoxWhisker()]. } -\seealso{ProjectField, NAO, PlotBoxWhisker} \keyword{datagen} + diff --git a/man/Enlarge.Rd b/man/Enlarge.Rd index ab700e68..76f5cccf 100644 --- a/man/Enlarge.Rd +++ b/man/Enlarge.Rd @@ -1,24 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Enlarge.R \name{Enlarge} \alias{Enlarge} -\title{ -Extends The Number Of Dimensions of A Matrix -} -\description{ -Extends the number of dimensions of var to numdims (the added dimensions have length 1). -} +\title{Extends The Number Of Dimensions of A Matrix} \usage{ Enlarge(var, numdims) } \arguments{ - \item{var}{ -Matrix to be extended. - } - \item{numdims}{ -Output number of dimensions. - } +\item{var}{Matrix to be extended.} + +\item{numdims}{Output number of dimensions.} } \value{ -Extended matrix. +Output number of dimensions. +} +\description{ +Extends the number of dimensions of var to numdims (the added dimensions +have length 1). } \examples{ data <- array(1, c(2, 2, 3)) @@ -26,8 +24,9 @@ print(dim(Enlarge(data, 5))) } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr -1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improved\cr + 0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr + 1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improved\cr } \keyword{datagen} + diff --git a/man/Eno.Rd b/man/Eno.Rd index 8aed1d5b..6ad23656 100644 --- a/man/Eno.Rd +++ b/man/Eno.Rd @@ -1,55 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Eno.R \name{Eno} \alias{Eno} -\title{ -Computes Effective Sample Size With Classical Method -} -\description{ -Computes the effective number of independent values along the posdim dimension of a matrix.\cr -This effective number of independent observations can be used in statistical/inference tests.\cr -Based on eno function from Caio Coelho from rclim.txt. -} +\title{Computes Effective Sample Size With Classical Method} \usage{ Eno(obs, posdim) } \arguments{ - \item{obs}{ -Matrix of any number of dimensions up to 10. - } - \item{posdim}{ -Dimension along which to compute the effective sample size. - } +\item{obs}{Matrix of any number of dimensions up to 10.} + +\item{posdim}{Dimension along which to compute the effective sample size.} } \value{ Same dimensions as var but without the posdim dimension. } +\description{ +Computes the effective number of independent values along the posdim +dimension of a matrix.\cr +This effective number of independent observations can be used in +statistical/inference tests.\cr +Based on eno function from Caio Coelho from rclim.txt. +} \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') exp <- list( - name = 'experiment', - path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', - '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') - ) + name = 'experiment', + path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', + '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') + ) obs <- list( - name = 'observation', - path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', - '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') - ) + name = 'observation', + path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', + '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + ) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(exp), list(obs), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } sampleData$mod <- Season(sampleData$mod, 4, 11, 1, 12) eno <- Eno(sampleData$mod[1, 1, , 1, , ], 1) PlotEquiMap(eno, sampleData$lon, sampleData$lat) @@ -60,3 +59,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN } \keyword{datagen} + diff --git a/man/EnoNew.Rd b/man/EnoNew.Rd index 20ed9321..cc2de760 100644 --- a/man/EnoNew.Rd +++ b/man/EnoNew.Rd @@ -1,55 +1,70 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/EnoNew.R \name{EnoNew} \alias{EnoNew} \title{Computes Effective Sample Size Following Guemas et al, BAMS, 2013b} -\description{ -This function computes the effective number of independent values in the xdata array following the method described in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. \code{EnoNew} provides similar functionality to \code{Eno} but with the added options to remove the linear trend or filter the frequency.} \usage{ EnoNew(xdata, detrend = FALSE, filter = FALSE) } \arguments{ - \item{xdata}{a numeric vector} - \item{detrend}{should the linear trend be removed from the data prior to the estimation of the equivalent number of independent values.} - \item{filter}{should a filtering of the frequency peaks be applied prior to the estimation of the equivalent number of independant data.} +\item{xdata}{A numeric vector.} + +\item{detrend}{Should the linear trend be removed from the data prior to +the estimation of the equivalent number of independent values.} + +\item{filter}{Should a filtering of the frequency peaks be applied prior +to the estimation of the equivalent number of independant data.} +} +\description{ +This function computes the effective number of independent values in the +xdata array following the method described in +Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. \code{EnoNew} provides +similar functionality to \code{Eno} but with the added options to remove +the linear trend or filter the frequency. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') exp <- list( - name = 'experiment', - path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', - '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') - ) + name = 'experiment', + path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', + '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') + ) obs <- list( - name = 'observation', - path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', - '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') - ) + name = 'observation', + path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', + '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + ) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(exp), list(obs), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } eno <- EnoNew(sampleData$mod[1, 1, , 1, 2, 3]) print(eno) -} -\references{ -Guemas V, Auger L, Doblas-Reyes FJ, Rust H, Ribes A, 2014, Dependencies in Statistical Hypothesis Tests for Climate Time Series. Bulletin of the American Meteorological Society, 95 (11), 1666-1667. + } \author{ History:\cr 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } +\references{ +Guemas V, Auger L, Doblas-Reyes FJ, Rust H, Ribes A, 2014, Dependencies in + Statistical Hypothesis Tests for Climate Time Series. Bulletin of the + American Meteorological Society, 95 (11), 1666-1667. +} \keyword{datagen} + diff --git a/man/Filter.Rd b/man/Filter.Rd index bb1bcf44..3ee7df89 100644 --- a/man/Filter.Rd +++ b/man/Filter.Rd @@ -1,34 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Filter.R \name{Filter} \alias{Filter} \title{Filter Frequency Peaks From An Array} -\description{ -This function filters out the selected frequency from a time series.\cr -The filtering is performed by dichotomy, seeking for a frequency around the parameter \code{freq} and the phase that maximizes the signal to subtract from the time series.\cr -The maximization of the signal to subtract relies on a minimization of the mean square differences between the time series (xdata) and the cosine of the specified frequency and phase. -} \usage{ Filter(xdata, freq) } \arguments{ - \item{xdata}{Array to be filtered.} - \item{freq}{Frequency to filter.} +\item{xdata}{Array to be filtered.} + +\item{freq}{Frequency to filter.} +} +\value{ +Filtered Array. +} +\description{ +This function filters out the selected frequency from a time series.\cr +The filtering is performed by dichotomy, seeking for a frequency around +the parameter \code{freq} and the phase that maximizes the signal to subtract +from the time series.\cr +The maximization of the signal to subtract relies on a minimization of the +mean square differences between the time series (xdata) and the cosine of +the specified frequency and phase. } -\value{Filtered Array} \examples{ # Load sample data as in Load() example: example(Load) ensmod <- Mean1Dim(sampleData$mod, 2) for (jstartdate in 1:3) { - spectrum <- Spectrum(ensmod[1, jstartdate, ]) - for (jlen in 1:dim(spectrum)[1]) { - if (spectrum[jlen, 2] > spectrum[jlen, 4]) { - ensmod[1, jstartdate, ] <- Filter(ensmod[1, jstartdate, ], - spectrum[jlen, 1]) - } - } + spectrum <- Spectrum(ensmod[1, jstartdate, ]) + for (jlen in 1:dim(spectrum)[1]) { + if (spectrum[jlen, 2] > spectrum[jlen, 4]) { + ensmod[1, jstartdate, ] <- Filter(ensmod[1, jstartdate, ], + spectrum[jlen, 1]) + } + } } PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = - 'filtered_ensemble_mean.eps') + 'filtered_ensemble_mean.eps') + } \author{ History:\cr @@ -36,3 +46,4 @@ History:\cr 1.0 - 2012-02 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/FitAcfCoef.Rd b/man/FitAcfCoef.Rd index 73db6dfc..aa8e1db6 100644 --- a/man/FitAcfCoef.Rd +++ b/man/FitAcfCoef.Rd @@ -1,21 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/FitAcfCoef.R \name{FitAcfCoef} \alias{FitAcfCoef} \title{Fits an AR1 AutoCorrelation Function Using the Cardano Formula} -\description{ -This function finds the minimum point of the fourth order polynom (a - x)2 + 0.25(b - x2)2 written to fit the two autoregression coefficients a and b.\cr -A consequence of the Cardano formula is that, provided a and b are in [0 1], the problem is well posed, delta > 0 and there is only one minimum.\cr\cr -This function is called in Alpha() to minimize the mean square differences between the theoretical autocorrelation function of an AR1 and the first guess of the estimated autocorrelation function estacf, using only the first two lags.} -\usage{FitAcfCoef(a, b)} +\usage{ +FitAcfCoef(a, b) +} \arguments{ - \item{a}{Coefficient a : first estimate of the autocorrelation at lag 1} - \item{b}{Coefficient b : first estimate of the autocorrelation at lag 2} +\item{a}{Coefficient a : first estimate of the autocorrelation at lag 1.} + +\item{b}{Coefficient b : first estimate of the autocorrelation at lag 2.} +} +\value{ +Best estimate of the autocorrelation at lag 1. +} +\description{ +This function finds the minimum point of the fourth order polynom +(a - x)2 + 0.25(b - x2)2 written to fit the two autoregression coefficients +a and b.\cr +A consequence of the Cardano formula is that, provided a and b are in [0 1], +the problem is well posed, delta > 0 and there is only one minimum.\cr\cr +This function is called in Alpha() to minimize the mean square differences +between the theoretical autocorrelation function of an AR1 and the first +guess of the estimated autocorrelation function estacf, using only the +first two lags. } -\value{Best estimate of the autocorrelation at lag 1} \examples{ series <- GenSeries(1000, 0.35, 2, 1) estacf <- acf(series[951:1000], plot = FALSE)$acf alpha <- FitAcfCoef(max(estacf[2], 0), max(estacf[3], 0)) print(alpha) + } \author{ History:\cr @@ -23,3 +38,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/FitAutocor.Rd b/man/FitAutocor.Rd index d5031fdb..0720821a 100644 --- a/man/FitAutocor.Rd +++ b/man/FitAutocor.Rd @@ -1,16 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/FitAutocor.R \name{FitAutocor} \alias{FitAutocor} \title{Fits an AR1 Autocorrelation Function Using Dichotomy} -\description{This function fits the theoretical autocorrelation function of an AR1 to the first guess of the estimated autocorrelation function estacf containing any number of lags. The fitting relies on a dichotomial minimisation of the mean square differences between both autocorrelation functions. It returns the autocorrelation at lag 1 of the fitted AR1 process.} \usage{ FitAutocor(estacf, window = c(-1, 1), prec = 0.01) } \arguments{ - \item{estacf}{First guess for the autocorrelation function} - \item{window}{Interval in which the autocorrelation at lag 1 should be found.} - \item{prec}{Precision to which the autocorrelation function at lag 1 is to be estimated.} +\item{estacf}{First guess for the autocorrelation function.} + +\item{window}{Interval in which the autocorrelation at lag 1 should be found.} + +\item{prec}{Precision to which the autocorrelation function at lag 1 is to be estimated.} +} +\value{ +Best estimate of the autocorrelation at lag 1. +} +\description{ +This function fits the theoretical autocorrelation function of an AR1 to +the first guess of the estimated autocorrelation function estacf containing +any number of lags. The fitting relies on a dichotomial minimisation of the +mean square differences between both autocorrelation functions. It returns +the autocorrelation at lag 1 of the fitted AR1 process. } -\value{Best estimate of the autocorrelation at lag 1} \examples{ series <- GenSeries(1000, 0.35, 2, 1) estacf <- acf(series[951:1000], plot = FALSE)$acf @@ -23,3 +35,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/GenSeries.Rd b/man/GenSeries.Rd index e616d6a1..deb6b1b3 100644 --- a/man/GenSeries.Rd +++ b/man/GenSeries.Rd @@ -1,17 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/GenSeries.R \name{GenSeries} \alias{GenSeries} \title{Generates An AR1 Time Series} -\description{This function generates AR1 processes containing n data points, where alpha is the autocorrelation at lag 1, and the mean and standard deviation are specified by the mean and std arguments.} \usage{ GenSeries(n, alpha, mean, std) } \arguments{ - \item{n}{Length of the timeseries to be generated.} - \item{alpha}{Autocorrelation at lag 1.} - \item{mean}{Mean of the data.} - \item{std}{Standard deviation of the data.} +\item{n}{Length of the timeseries to be generated.} + +\item{alpha}{Autocorrelation at lag 1.} + +\item{mean}{Mean of the data.} + +\item{std}{Standard deviation of the data.} +} +\value{ +AR1 timeseries. +} +\description{ +This function generates AR1 processes containing n data points, where alpha +is the autocorrelation at lag 1, and the mean and standard deviation are +specified by the mean and std arguments. } -\value{AR1 timeseries} \examples{ series <- GenSeries(1000, 0.35, 2, 1) plot(series, type = 'l') @@ -22,3 +33,4 @@ History:\cr 1.0 - 2012-04 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/Histo2Hindcast.Rd b/man/Histo2Hindcast.Rd index 06cf92e5..d94da235 100644 --- a/man/Histo2Hindcast.Rd +++ b/man/Histo2Hindcast.Rd @@ -1,74 +1,75 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Histo2Hindcast.R \name{Histo2Hindcast} \alias{Histo2Hindcast} -\title{ -Chunks Long Simulations For Comparison With Hindcasts -} -\description{ -This function reorganizes a long run (historical typically) with only one start date into chunks corresponding to a set of start dates. The expected input structure is the one output from \code{Load()} with 4 to 7 dimensions. -} +\title{Chunks Long Simulations For Comparison With Hindcasts} \usage{ Histo2Hindcast(varin, sdatesin, sdatesout, nleadtimesout) } \arguments{ - \item{varin}{ -Array of model or observational data with dimensions:\cr - c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes) up to\cr - c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes, nlevel, nlat, nlon) - } - \item{sdatesin}{ -Start date of the input matrix 'YYYYMMDD'. - } - \item{sdatesout}{ -List of start dates of the output matrix c('YYYYMMDD', 'YYYYMMDD', ...). - } - \item{nleadtimesout}{ -Number of leadtimes in the output matrix. - } +\item{varin}{Array of model or observational data with dimensions:\cr +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes) up to\cr +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes, nlevel, nlat, nlon)} + +\item{sdatesin}{Start date of the input matrix 'YYYYMMDD'.} + +\item{sdateout}{List of start dates of the output matrix +c('YYYYMMDD', 'YYYYMMDD', ...).} + +\item{nleadtimeout}{Number of leadtimes in the output matrix.} } \value{ -An array with the same number of dimensions as varin, the same dimensions 1 and 2 and potentially the same dimensions 5 to 7. Dimensions 3 and 4 are set by the arguments sdatesout and nleadtimesout. +An array with the same number of dimensions as varin, the same +dimensions 1 and 2 and potentially the same dimensions 5 to 7. Dimensions +3 and 4 are set by the arguments sdatesout and nleadtimesout. +} +\description{ +This function reorganizes a long run (historical typically) with only one +start date into chunks corresponding to a set of start dates. The expected +input structure is the one output from \code{Load()} with 4 to 7 dimensions. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') exp <- list( - name = 'experiment', - path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', - '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') - ) + name = 'experiment', + path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', + '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') + ) obs <- list( - name = 'observation', - path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', - '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') - ) + name = 'observation', + path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', + '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + ) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(exp), list(obs), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19901101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'areave', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'areave', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } start_dates_out <- c('19901101', '19911101', '19921101', '19931101', '19941101') leadtimes_per_startdate <- 12 experimental_data <- Histo2Hindcast(sampleData$mod, startDates[1], - start_dates_out, leadtimes_per_startdate) + start_dates_out, leadtimes_per_startdate) observational_data <- Histo2Hindcast(sampleData$obs, startDates[1], - start_dates_out, leadtimes_per_startdate) + start_dates_out, leadtimes_per_startdate) PlotAno(experimental_data, observational_data, start_dates_out, - toptitle = paste('anomalies reorganized into shorter chunks'), - ytitle = 'K', fileout='tos_histo2hindcast.eps') + toptitle = paste('anomalies reorganized into shorter chunks'), + ytitle = 'K', fileout='tos_histo2hindcast.eps') + } \author{ History:\cr @@ -76,3 +77,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/IniListDims.Rd b/man/IniListDims.Rd index 0af0253c..422a4c76 100644 --- a/man/IniListDims.Rd +++ b/man/IniListDims.Rd @@ -1,27 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/IniListDims.R \name{IniListDims} \alias{IniListDims} -\title{ -Creates A List Of Integer Ranges -} -\description{ -This function generates a list of arrays containing integers greater than or equal to 1. This list of arrays is used in other functions as a list of indices of the elements of the matrices. -} +\title{Creates A List Of Integer Ranges} \usage{ IniListDims(dims, lenlist) } \arguments{ - \item{dims}{ -The dimensions of a matrix for which we need the possible indices for each dimension. For exemple, if the dimensions sent are c(3,2,5), the following list of arrays will be generated:\cr - list(c(1:3), c(1:2), c(1:5)) - } - \item{lenlist}{ -'lenlist' is the length of the list because the list will be complemented above length(dims) by arrays of length 1.\cr -For example, if lenlist is set to 7, the previous list of arrays will be extended to:\cr - list(c(1:3), c(1:2), c(1:5), 1, 1, 1, 1) - } +\item{dims}{The dimensions of a matrix for which we need the possible +indices for each dimension. For exemple, if the dimensions sent are +c(3,2,5), the following list of arrays will be generated:\cr +list(c(1:3), c(1:2), c(1:5)).} + +\item{lenlist}{'lenlist' is the length of the list because the list will +be complemented above length(dims) by arrays of length 1.\cr +For example, if lenlist is set to 7, the previous list of arrays will be +extended to:\cr +list(c(1:3), c(1:2), c(1:5), 1, 1, 1, 1).} } \value{ -A list with lenlist elements, each with arrays with integers from 1 to the numbers in dims array and with only 1 for the dimensions above length(dims). +A list with lenlist elements, each with arrays with integers from 1 + to the numbers in dims array and with only 1 for the dimensions above + length(dims). +} +\description{ +This function generates a list of arrays containing integers greater than or +equal to 1. This list of arrays is used in other functions as a list of +indices of the elements of the matrices. } \examples{ indices <- IniListDims(c(2, 2, 4, 3), 6) @@ -34,3 +39,4 @@ History:\cr 1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improved } \keyword{datagen} + diff --git a/man/InsertDim.Rd b/man/InsertDim.Rd index 6b08a583..dfceebdb 100644 --- a/man/InsertDim.Rd +++ b/man/InsertDim.Rd @@ -1,33 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/InsertDim.R \name{InsertDim} \alias{InsertDim} -\title{ -Adds A Dimension To An Array -} -\description{ -Inserts an extra dimension into an array at position 'posdim' with length 'lendim' and which correspond to 'lendim' repetitions of the 'var' array. -} +\title{Adds A Dimension To An Array} \usage{ InsertDim(var, posdim, lendim) } \arguments{ - \item{var}{ -Matrix to which a dimension should be added. - } - \item{posdim}{ -Position of the new dimension. - } - \item{lendim}{ -Length of the new dimension. - } +\item{var}{Matrix to which a dimension should be added.} + +\item{posdim}{Position of the new dimension.} + +\item{lendim}{Length of the new dimension.} } \value{ Matrix with the added dimension. } +\description{ +Inserts an extra dimension into an array at position 'posdim' with length +'lendim' and which correspond to 'lendim' repetitions of the 'var' array. +} \examples{ -a <- array(rnorm(15), dim = c(3, 1, 5, 1)) +<- array(rnorm(15), dim = c(3, 1, 5, 1)) print(dim(a)) print(dim(a[, , , ])) print(dim(InsertDim(InsertDim(a[, , , ], 2, 1), 4, 1))) + } \author{ History:\cr @@ -36,3 +34,4 @@ History:\cr 1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improvements } \keyword{datagen} + diff --git a/man/LeapYear.Rd b/man/LeapYear.Rd index faf41456..8b9eb3bf 100644 --- a/man/LeapYear.Rd +++ b/man/LeapYear.Rd @@ -1,20 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/LeapYear.R \name{LeapYear} \alias{LeapYear} \title{Checks Whether A Year Is Leap Year} -\description{ -This function tells whether a year is a leap year or not. -} \usage{ LeapYear(year) } \arguments{ - \item{year}{ -A numeric value indicating the year in the Gregorian calendar. - } +\item{year}{A numeric value indicating the year in the Gregorian calendar.} } \value{ Boolean telling whether the year is a leap year or not. } +\description{ +This function tells whether a year is a leap year or not. +} \examples{ print(LeapYear(1990)) print(LeapYear(1991)) @@ -27,3 +27,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/Load.Rd b/man/Load.Rd index eef60299..5ee3db0d 100644 --- a/man/Load.Rd +++ b/man/Load.Rd @@ -1,161 +1,98 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Load.R \name{Load} \alias{Load} \title{Loads Experimental And Observational Data} -\description{ -This function loads monthly or daily data from a set of specified experimental datasets together with data that date-corresponds from a set of specified observational datasets. See parameters 'storefreq', 'sampleperiod', 'exp' and 'obs'.\cr\cr -A set of starting dates is specified through the parameter 'sdates'. Data of each starting date is loaded for each model. -\code{Load()} arranges the data in two arrays with a similar format both with the following dimensions: - \enumerate{ - \item{The number of experimental datasets determined by the user through the argument 'exp' (for the experimental data array) or the number of observational datasets available for validation (for the observational array) determined as well by the user through the argument 'obs'.} - \item{The greatest number of members across all experiments (in the experimental data array) or across all observational datasets (in the observational data array).} - \item{The number of starting dates determined by the user through the 'sdates' argument.} - \item{The greatest number of lead-times.} - \item{The number of latitudes of the selected zone.} - \item{The number of longitudes of the selected zone.} - } -Dimensions 5 and 6 are optional and their presence depends on the type of the specified variable (global mean or 2-dimensional) and on the selected output type (area averaged time series, latitude averaged time series, longitude averaged time series or 2-dimensional time series).\cr -In the case of loading an area average the dimensions of the arrays will be only the first 4.\cr\cr - -Only a specified variable is loaded from each experiment at each starting date. See parameter 'var'.\cr -Afterwards, observational data that matches every starting date and lead-time of every experimental dataset is fetched in the file system (so, if two predictions at two different start dates overlap, some observational values will be loaded and kept in memory more than once).\cr -If no data is found in the file system for an experimental or observational array point it is filled with an NA value.\cr\cr - -If the specified output is 2-dimensional or latitude- or longitude-averaged time series all the data is interpolated into a common grid. If the specified output type is area averaged time series the data is averaged on the individual grid of each dataset but can also be averaged after interpolating into a common grid. See parameters 'grid' and 'method'.\cr -Once the two arrays are filled by calling this function, other functions in the s2dverification package that receive as inputs data formatted in this data structure can be executed (e.g: \code{Clim()} to compute climatologies, \code{Ano()} to compute anomalies, ...).\cr\cr - -Load() has many additional parameters to disable values and trim dimensions of selected variable, even masks can be applied to 2-dimensional variables. See parameters 'nmember', 'nmemberobs', 'nleadtime', 'leadtimemin', 'leadtimemax', 'sampleperiod', 'lonmin', 'lonmax', 'latmin', 'latmax', 'maskmod', 'maskobs', 'varmin', 'varmax'.\cr\cr - -The parameters 'exp' and 'obs' can take various forms. The most direct form is a list of lists, where each sub-list has the component 'path' associated to a character string with a pattern of the path to the files of a dataset to be loaded. These patterns can contain wildcards and tags that will be replaced automatically by \code{Load()} with the specified starting dates, member numbers, variable name, etc.\cr -See parameter 'exp' or 'obs' for details.\cr\cr +\usage{ +Load(var, exp = NULL, obs = NULL, sdates, nmember = NULL, + nmemberobs = NULL, nleadtime = NULL, leadtimemin = 1, + leadtimemax = NULL, storefreq = "monthly", sampleperiod = 1, + lonmin = 0, lonmax = 360, latmin = -90, latmax = 90, + output = "areave", method = "conservative", grid = NULL, + maskmod = vector("list", 15), maskobs = vector("list", 15), + configfile = NULL, varmin = NULL, varmax = NULL, silent = FALSE, + nprocs = NULL, dimnames = NULL, remapcells = 2, + path_glob_permissive = "partial") +} +\arguments{ +\item{var}{Short name of the variable to load. It should coincide with the +variable name inside the data files.\cr +E.g.: \code{var = 'tos'}, \code{var = 'tas'}, \code{var = 'prlr'}.\cr +In some cases, though, the path to the files contains twice or more times +the short name of the variable but the actual name of the variable inside +the data files is different. In these cases it may be convenient to provide +\code{var} with the name that appears in the file paths (see details on +parameters \code{exp} and \code{obs}).} -Only NetCDF files are supported. OPeNDAP URLs to NetCDF files are also supported.\cr -\code{Load()} can load 2-dimensional or global mean variables in any of the following formats: +\item{exp}{Parameter to specify which experimental datasets to load data +from.\cr +It can take two formats: a list of lists or a vector of character strings. +Each format will trigger a different mechanism of locating the requested +datasets.\cr +The first format is adequate when loading data you'll only load once or +occasionally. The second format is targeted to avoid providing repeatedly +the information on a certain dataset but is more complex to use.\cr\cr +IMPORTANT: Place first the experiment with the largest number of members +and, if possible, with the largest number of leadtimes. If not possible, +the arguments 'nmember' and/or 'nleadtime' should be filled to not miss +any member or leadtime.\cr +If 'exp' is not specified or set to NULL, observational data is loaded for +each start-date as far as 'leadtimemax'. If 'leadtimemax' is not provided, +\code{Load()} will retrieve data of a period of time as long as the time +period between the first specified start date and the current date.\cr\cr +List of lists:\cr +A list of lists where each sub-list contains information on the location +and format of the data files of the dataset to load.\cr +Each sub-list can have the following components: \itemize{ - \item{experiments: - \itemize{ - \item{file per ensemble per starting date (YYYY, MM and DD somewhere in the path)} - \item{file per member per starting date (YYYY, MM, DD and MemberNumber somewhere in the path. Ensemble experiments with different numbers of members can be loaded in a single \code{Load()} call.)} - } -(YYYY, MM and DD specify the starting dates of the predictions) + \item{'name': A character string to identify the dataset. Optional.} + \item{'path': A character string with the pattern of the path to the + files of the dataset. This pattern can be built up making use of some + special tags that \code{Load()} will replace with the appropriate + values to find the dataset files. The allowed tags are $START_DATE$, + $YEAR$, $MONTH$, $DAY$, $MEMBER_NUMBER$, $STORE_FREQ$, $VAR_NAME$, + $EXP_NAME$ (only for experimental datasets), $OBS_NAME$ (only for + observational datasets) and $SUFFIX$\cr + Example: /path/to/$EXP_NAME$/postprocessed/$VAR_NAME$/\cr + $VAR_NAME$_$START_DATE$.nc\cr + If 'path' is not specified and 'name' is specified, the dataset + information will be fetched with the same mechanism as when using + the vector of character strings (read below). } - \item{observations: - \itemize{ - \item{file per ensemble per month (YYYY and MM somewhere in the path)} - \item{file per member per month (YYYY, MM and MemberNumber somewhere in the path, obs with different numbers of members supported)} - \item{file per dataset (No constraints in the path but the time axes in the file have to be properly defined)} - } -(YYYY and MM correspond to the actual month data in the file) + \item{'nc_var_name': Character string with the actual variable name + to look for inside the dataset files. Optional. Takes, by default, + the same value as the parameter 'var'. } - } -In all the formats the data can be stored in a daily or monthly frequency, or a multiple of these (see parameters 'storefreq' and 'sampleperiod').\cr -All the data files must contain the target variable defined over time and potentially over members, latitude and longitude dimensions in any order, time being the record dimension.\cr -In the case of a two-dimensional variable, the variables longitude and latitude must be defined inside the data file too and must have the same names as the dimension for longitudes and latitudes respectively.\cr -The names of these dimensions (and longitude and latitude variables) and the name for the members dimension are expected to be 'longitude', 'latitude' and 'ensemble' respectively. However, these names can be adjusted with the parameter 'dimnames' or can be configured in the configuration file (read below in parameters 'exp', 'obs' or see \code{?ConfigFileOpen} for more information.\cr -All the data files are expected to have numeric values representable with 32 bits. Be aware when choosing the fill values or infinite values in the datasets to load.\cr\cr - -The Load() function returns a named list following a structure similar to the used in the package 'downscaleR'.\cr -The components are the following: - \itemize{ - \item{'mod' is the array that contains the experimental data. It has the attribute 'dimensions' associated to a vector of strings with the labels of each dimension of the array, in order.} - \item{'obs' is the array that contains the observational data. It has the attribute 'dimensions' associated to a vector of strings with the labels of each dimension of the array, in order.} - \item{'obs' is the array that contains the observational data.} - \item{'lat' and 'lon' are the latitudes and longitudes of the grid into which the data is interpolated (0 if the loaded variable is a global mean or the output is an area average).\cr -Both have the attribute 'cdo_grid_des' associated with a character string with the name of the common grid of the data, following the CDO naming conventions for grids.\cr -The attribute 'projection' is kept for compatibility with 'downscaleR'.} - \item{'Variable' has the following components: - \itemize{ - \item{'varName', with the short name of the loaded variable as specified in the parameter 'var'.} - \item{'level', with information on the pressure level of the variable. Is kept to NULL by now.} - } -And the following attributes: - \itemize{ - \item{'is_standard', kept for compatibility with 'downscaleR', tells if a dataset has been homogenized to standards with 'downscaleR' catalogs.} - \item{'units', a character string with the units of measure of the variable, as found in the source files.} - \item{'longname', a character string with the long name of the variable, as found in the source files.} - \item{'daily_agg_cellfun', 'monthly_agg_cellfun', 'verification_time', kept for compatibility with 'downscaleR'.} - } + \item{'suffix': Wildcard character string that can be used to build + the 'path' of the dataset. It can be accessed with the tag $SUFFIX$. + Optional. Takes '' by default. } - \item{'Datasets' has the following components: - \itemize{ - \item{'exp', a named list where the names are the identifying character strings of each experiment in 'exp', each associated to a list with the following components: - \itemize{ - \item{'members', a list with the names of the members of the dataset.} - \item{'source', a path or URL to the source of the dataset.} - } - } - \item{'obs', similar to 'exp' but for observational datasets.} - } + \item{'var_min': Important: Character string. Minimum value beyond + which read values will be deactivated to NA. Optional. No deactivation + is performed by default. } - \item{'Dates', with the follwing components: - \itemize{ - \item{'start', an array of dimensions (sdate, time) with the POSIX initial date of each forecast time of each starting date.} - \item{'end', an array of dimensions (sdate, time) with the POSIX final date of each forecast time of each starting date.} - } + \item{'var_max': Important: Character string. Maximum value beyond + which read values will be deactivated to NA. Optional. No deactivation + is performed by default. } - \item{'InitializationDates', a vector of starting dates as specified in 'sdates', in POSIX format.} - \item{'when', a time stamp of the date the \code{Load()} call to obtain the data was issued.} - \item{'source_files', a vector of character strings with complete paths to all the found files involved in the \code{Load()} call.} - \item{'not_found_files', a vector of character strings with complete paths to not found files involved in the \code{Load()} call.} - } -} -\usage{ -Load(var, exp = NULL, obs = NULL, sdates, nmember = NULL, - nmemberobs = NULL, nleadtime = NULL, leadtimemin = 1, - leadtimemax = NULL, storefreq = 'monthly', sampleperiod = 1, - lonmin = 0, lonmax = 360, latmin = -90, latmax = 90, - output = 'areave', method = 'conservative', grid = NULL, - maskmod = vector("list", 15), maskobs = vector("list", 15), - configfile = NULL, varmin = NULL, varmax = NULL, - silent = FALSE, nprocs = NULL, dimnames = NULL, - remapcells = 2, path_glob_permissive = 'partial') -} -\arguments{ - \item{var}{ -Short name of the variable to load. It should coincide with the variable name inside the data files.\cr -E.g.: \code{var = 'tos'}, \code{var = 'tas'}, \code{var = 'prlr'}.\cr -In some cases, though, the path to the files contains twice or more times the short name of the variable but the actual name of the variable inside the data files is different. In these cases it may be convenient to provide \code{var} with the name that appears in the file paths (see details on parameters \code{exp} and \code{obs}). } - \item{exp}{ -Parameter to specify which experimental datasets to load data from.\cr -It can take two formats: a list of lists or a vector of character strings. Each format will trigger a different mechanism of locating the requested datasets.\cr -The first format is adequate when loading data you'll only load once or occasionally. The second format is targeted to avoid providing repeatedly the information on a certain dataset but is more complex to use.\cr\cr -IMPORTANT: Place first the experiment with the largest number of members and, if possible, with the largest number of leadtimes. If not possible, the arguments 'nmember' and/or 'nleadtime' should be filled to not miss any member or leadtime.\cr -If 'exp' is not specified or set to NULL, observational data is loaded for each start-date as far as 'leadtimemax'. If 'leadtimemax' is not provided, \code{Load()} will retrieve data of a period of time as long as the time period between the first specified start date and the current date.\cr -\cr -List of lists:\cr -A list of lists where each sub-list contains information on the location and format of the data files of the dataset to load.\cr -Each sub-list can have the following components: - \itemize{ - \item{ -'name': A character string to identify the dataset. Optional. - } - \item{ -'path': A character string with the pattern of the path to the files of the dataset. This pattern can be built up making use of some special tags that \code{Load()} will replace with the appropriate values to find the dataset files. The allowed tags are $START_DATE$, $YEAR$, $MONTH$, $DAY$, $MEMBER_NUMBER$, $STORE_FREQ$, $VAR_NAME$, $EXP_NAME$ (only for experimental datasets), $OBS_NAME$ (only for observational datasets) and $SUFFIX$\cr -Example: /path/to/$EXP_NAME$/postprocessed/$VAR_NAME$/\cr - $VAR_NAME$_$START_DATE$.nc\cr -If 'path' is not specified and 'name' is specified, the dataset information will be fetched with the same mechanism as when using the vector of character strings (read below). - } - \item{ -'nc_var_name': Character string with the actual variable name to look for inside the dataset files. Optional. Takes, by default, the same value as the parameter 'var'. - } - \item{ -'suffix': Wildcard character string that can be used to build the 'path' of the dataset. It can be accessed with the tag $SUFFIX$. Optional. Takes '' by default. - } - \item{ -'var_min': Important: Character string. Minimum value beyond which read values will be deactivated to NA. Optional. No deactivation is performed by default. - } - \item{ -'var_max': Important: Character string. Maximum value beyond which read values will be deactivated to NA. Optional. No deactivation is performed by default. - } - } -The tag $START_DATES$ will be replaced with all the starting dates specified in 'sdates'. $YEAR$, $MONTH$ and $DAY$ will take a value for each iteration over 'sdates', simply these are the same as $START_DATE$ but split in parts.\cr -$MEMBER_NUMBER$ will be replaced by a character string with each member number, from 1 to the value specified in the parameter 'nmember' (in experimental datasets) or in 'nmemberobs' (in observational datasets). It will range from '01' to 'N' or '0N' if N < 10.\cr -$STORE_FREQ$ will take the value specified in the parameter 'storefreq' ('monthly' or 'daily').\cr +The tag $START_DATES$ will be replaced with all the starting dates +specified in 'sdates'. $YEAR$, $MONTH$ and $DAY$ will take a value for each +iteration over 'sdates', simply these are the same as $START_DATE$ but +split in parts.\cr +$MEMBER_NUMBER$ will be replaced by a character string with each member +number, from 1 to the value specified in the parameter 'nmember' (in +experimental datasets) or in 'nmemberobs' (in observational datasets). It +will range from '01' to 'N' or '0N' if N < 10.\cr +$STORE_FREQ$ will take the value specified in the parameter 'storefreq' +('monthly' or 'daily').\cr $VAR_NAME$ will take the value specified in the parameter 'var'.\cr -$EXP_NAME$ will take the value specified in each component of the parameter 'exp' in the sub-component 'name'.\cr -$OBS_NAME$ will take the value specified in each component of the parameter 'obs' in the sub-component 'obs.\cr -$SUFFIX$ will take the value specified in each component of the parameters 'exp' and 'obs' in the sub-component 'suffix'.\cr - +$EXP_NAME$ will take the value specified in each component of the parameter +'exp' in the sub-component 'name'.\cr +$OBS_NAME$ will take the value specified in each component of the parameter +'obs' in the sub-component 'obs.\cr +$SUFFIX$ will take the value specified in each component of the parameters +'exp' and 'obs' in the sub-component 'suffix'.\cr Example: \preformatted{ list( @@ -171,255 +108,608 @@ list( ) ) } -This will make \code{Load()} look for, for instance, the following paths, if 'sdates' is c('19901101', '19951101', '20001101'):\cr +This will make \code{Load()} look for, for instance, the following paths, +if 'sdates' is c('19901101', '19951101', '20001101'):\cr /path/to/experimentA/monthly_mean/tas_3hourly/tas_19901101.nc\cr /path/to/experimentA/monthly_mean/tas_3hourly/tas_19951101.nc\cr /path/to/experimentA/monthly_mean/tas_3hourly/tas_20001101.nc\cr\cr - Vector of character strings: -To avoid specifying constantly the same information to load the same datasets, a vector with only the names of the datasets to load can be specified.\cr -\code{Load()} will then look for the information in a configuration file whose path must be specified in the parameter 'configfile'.\cr -Check \code{?ConfigFileCreate}, \code{ConfigFileOpen}, \code{ConfigEditEntry} & co. to learn how to create a new configuration file and how to add the information there. +To avoid specifying constantly the same information to load the same +datasets, a vector with only the names of the datasets to load can be +specified.\cr +\code{Load()} will then look for the information in a configuration file +whose path must be specified in the parameter 'configfile'.\cr +Check \code{?ConfigFileCreate}, \code{ConfigFileOpen}, +\code{ConfigEditEntry} & co. to learn how to create a new configuration +file and how to add the information there.\cr +Example: c('experimentA', 'experimentB')} -Example: c('experimentA', 'experimentB') - } - \item{obs}{ -Argument with the same format as parameter 'exp'. See details on parameter 'exp'.\cr -If 'obs' is not specified or set to NULL, no observational data is loaded.\cr - } - \item{sdates}{ -Vector of starting dates of the experimental runs to be loaded following the pattern 'YYYYMMDD'.\cr +\item{obs}{Argument with the same format as parameter 'exp'. See details on +parameter 'exp'.\cr +If 'obs' is not specified or set to NULL, no observational data is loaded.\cr} + +\item{sdates}{Vector of starting dates of the experimental runs to be loaded +following the pattern 'YYYYMMDD'.\cr This argument is mandatory.\cr -Ex: c('19601101', '19651101', '19701101') - } - \item{nmember}{ -Vector with the numbers of members to load from the specified experimental datasets in 'exp'.\cr -If not specified, the automatically detected number of members of the first experimental dataset is detected and replied to all the experimental datasets.\cr -If a single value is specified it is replied to all the experimental datasets.\cr -Data for each member is fetched in the file system. If not found is filled with NA values.\cr -An NA value in the 'nmember' list is interpreted as "fetch as many members of each experimental dataset as the number of members of the first experimental dataset".\cr -Note: It is recommended to specify the number of members of the first experimental dataset if it is stored in file per member format because there are known issues in the automatic detection of members if the path to the dataset in the configuration file contains Shell Globbing wildcards such as '*'.\cr -Ex: c(4, 9) - } - \item{nmemberobs}{ -Vector with the numbers of members to load from the specified observational datasets in 'obs'.\cr -If not specified, the automatically detected number of members of the first observational dataset is detected and replied to all the observational datasets.\cr -If a single value is specified it is replied to all the observational datasets.\cr -Data for each member is fetched in the file system. If not found is filled with NA values.\cr -An NA value in the 'nmemberobs' list is interpreted as "fetch as many members of each observational dataset as the number of members of the first observational dataset".\cr -Note: It is recommended to specify the number of members of the first observational dataset if it is stored in file per member format because there are known issues in the automatic detection of members if the path to the dataset in the configuration file contains Shell Globbing wildcards such as '*'.\cr -Ex: c(1, 5) - } - \item{nleadtime}{ -Deprecated. See parameter 'leadtimemax'.\cr - } - \item{leadtimemin}{ -Only lead-times higher or equal to 'leadtimemin' are loaded. Takes by default value 1. - } - \item{leadtimemax}{ -Only lead-times lower or equal to 'leadtimemax' are loaded. Takes by default the number of lead-times of the first experimental dataset in 'exp'.\cr -If 'exp' is NULL this argument won't have any effect (see \code{?Load} description). - } - \item{storefreq}{ -Frequency at which the data to be loaded is stored in the file system. Can take values 'monthly' or 'daily'.\cr +E.g. c('19601101', '19651101', '19701101')} + +\item{nmember}{Vector with the numbers of members to load from the specified +experimental datasets in 'exp'.\cr +If not specified, the automatically detected number of members of the +first experimental dataset is detected and replied to all the experimental +datasets.\cr +If a single value is specified it is replied to all the experimental +datasets.\cr +Data for each member is fetched in the file system. If not found is +filled with NA values.\cr +An NA value in the 'nmember' list is interpreted as "fetch as many members +of each experimental dataset as the number of members of the first +experimental dataset".\cr +Note: It is recommended to specify the number of members of the first +experimental dataset if it is stored in file per member format because +there are known issues in the automatic detection of members if the path +to the dataset in the configuration file contains Shell Globbing wildcards +such as '*'.\cr +E.g., c(4, 9)} + +\item{nmemberobs}{Vector with the numbers of members to load from the +specified observational datasets in 'obs'.\cr +If not specified, the automatically detected number of members of the +first observational dataset is detected and replied to all the +observational datasets.\cr +If a single value is specified it is replied to all the observational +datasets.\cr +Data for each member is fetched in the file system. If not found is +filled with NA values.\cr +An NA value in the 'nmemberobs' list is interpreted as "fetch as many +members of each observational dataset as the number of members of the +first observational dataset".\cr +Note: It is recommended to specify the number of members of the first +observational dataset if it is stored in file per member format because +there are known issues in the automatic detection of members if the path +to the dataset in the configuration file contains Shell Globbing wildcards +such as '*'.\cr +E.g., c(1, 5)} + +\item{nleadtime}{Deprecated. See parameter 'leadtimemax'.} + +\item{leadtimemin}{Only lead-times higher or equal to 'leadtimemin' are +loaded. Takes by default value 1.} + +\item{storefreq}{Frequency at which the data to be loaded is stored in the +file system. Can take values 'monthly' or 'daily'.\cr By default it takes 'monthly'.\cr -Note: Data stored in other frequencies with a period which is divisible by a month can be loaded with a proper use of 'storefreq' and 'sampleperiod' parameters. It can also be loaded if the period is divisible by a day and the observational datasets are stored in a file per dataset format or 'obs' is empty. - } - \item{sampleperiod}{ -To load only a subset between 'leadtimemin' and 'leadtimemax' with the period of subsampling 'sampleperiod'.\cr +Note: Data stored in other frequencies with a period which is divisible by +a month can be loaded with a proper use of 'storefreq' and 'sampleperiod' +parameters. It can also be loaded if the period is divisible by a day and +the observational datasets are stored in a file per dataset format or +'obs' is empty.} + +\item{sampleperiod}{To load only a subset between 'leadtimemin' and +'leadtimemax' with the period of subsampling 'sampleperiod'.\cr Takes by default value 1 (all lead-times are loaded).\cr -See 'storefreq' for more information. - } - \item{lonmin}{ -If a 2-dimensional variable is loaded, values at longitudes lower than 'lonmin' aren't loaded.\cr -Must take a value in the range [-360, 360] (if negative longitudes are found in the data files these are translated to this range).\cr +See 'storefreq' for more information.} + +\item{lonmin}{If a 2-dimensional variable is loaded, values at longitudes +lower than 'lonmin' aren't loaded.\cr +Must take a value in the range [-360, 360] (if negative longitudes are +found in the data files these are translated to this range).\cr It is set to 0 if not specified.\cr -If 'lonmin' > 'lonmax', data across Greenwich is loaded. - } - \item{lonmax}{ -If a 2-dimensional variable is loaded, values at longitudes higher than 'lonmax' aren't loaded.\cr -Must take a value in the range [-360, 360] (if negative longitudes are found in the data files these are translated to this range).\cr +If 'lonmin' > 'lonmax', data across Greenwich is loaded.} + +\item{lonmax}{If a 2-dimensional variable is loaded, values at longitudes +higher than 'lonmax' aren't loaded.\cr +Must take a value in the range [-360, 360] (if negative longitudes are +found in the data files these are translated to this range).\cr It is set to 360 if not specified.\cr -If 'lonmin' > 'lonmax', data across Greenwich is loaded. - } - \item{latmin}{ -If a 2-dimensional variable is loaded, values at latitudes lower than 'latmin' aren't loaded.\cr +If 'lonmin' > 'lonmax', data across Greenwich is loaded.} + +\item{latmin}{If a 2-dimensional variable is loaded, values at latitudes +lower than 'latmin' aren't loaded.\cr Must take a value in the range [-90, 90].\cr -It is set to -90 if not specified. - } - \item{latmax}{ -If a 2-dimensional variable is loaded, values at latitudes higher than 'latmax' aren't loaded.\cr +It is set to -90 if not specified.} + +\item{latmax}{If a 2-dimensional variable is loaded, values at latitudes +higher than 'latmax' aren't loaded.\cr Must take a value in the range [-90, 90].\cr -It is set to 90 if not specified. - } - \item{output}{ -This parameter determines the format in which the data is arranged in the output arrays.\cr +It is set to 90 if not specified.} + +\item{output}{This parameter determines the format in which the data is +arranged in the output arrays.\cr Can take values 'areave', 'lon', 'lat', 'lonlat'.\cr - \itemize{ - \item{'areave': Time series of area-averaged variables over the specified domain.} - \item{'lon': Time series of meridional averages as a function of longitudes.} - \item{'lat': Time series of zonal averages as a function of latitudes.} - \item{'lonlat': Time series of 2d fields.} - } -Takes by default the value 'areave'. If the variable specified in 'var' is a global mean, this parameter is forced to 'areave'.\cr -All the loaded data is interpolated into the grid of the first experimental dataset except if 'areave' is selected. In that case the area averages are computed on each dataset original grid. A common grid different than the first experiment's can be specified through the parameter 'grid'. If 'grid' is specified when selecting 'areave' output type, all the loaded data is interpolated into the specified grid before calculating the area averages. - } - \item{method}{ -This parameter determines the interpolation method to be used when regridding data (see 'output'). Can take values 'bilinear', 'bicubic', 'conservative', 'distance-weighted'.\cr + \itemize{ + \item{'areave': Time series of area-averaged variables over the specified domain.} + \item{'lon': Time series of meridional averages as a function of longitudes.} + \item{'lat': Time series of zonal averages as a function of latitudes.} + \item{'lonlat': Time series of 2d fields.} +} +Takes by default the value 'areave'. If the variable specified in 'var' is +a global mean, this parameter is forced to 'areave'.\cr +All the loaded data is interpolated into the grid of the first experimental +dataset except if 'areave' is selected. In that case the area averages are +computed on each dataset original grid. A common grid different than the +first experiment's can be specified through the parameter 'grid'. If 'grid' +is specified when selecting 'areave' output type, all the loaded data is +interpolated into the specified grid before calculating the area averages.} + +\item{method}{This parameter determines the interpolation method to be used +when regridding data (see 'output'). Can take values 'bilinear', 'bicubic', +'conservative', 'distance-weighted'.\cr See \code{remapcells} for advanced adjustments.\cr -Takes by default the value 'conservative'. - } - \item{grid}{ -A common grid can be specified through the parameter 'grid' when loading 2-dimensional data. Data is then interpolated onto this grid whichever 'output' type is specified. If the selected output type is 'areave' and a 'grid' is specified, the area averages are calculated after interpolating to the specified grid.\cr -If not specified and the selected output type is 'lon', 'lat' or 'lonlat', this parameter takes as default value the grid of the first experimental dataset, which is read automatically from the source files.\cr -The grid must be supported by 'cdo' tools. Now only supported: rNXxNY or tTRgrid.\cr -Both rNXxNY and tRESgrid yield rectangular regular grids. rNXxNY yields grids that are evenly spaced in longitudes and latitudes (in degrees). tRESgrid refers to a grid generated with series of spherical harmonics truncated at the RESth harmonic. However these spectral grids are usually associated to a gaussian grid, the latitudes of which are spaced with a Gaussian quadrature (not evenly spaced in degrees). The pattern tRESgrid will yield a gaussian grid.\cr -Ex: 'r96x72' -Advanced: If the output type is 'lon', 'lat' or 'lonlat' and no common grid is specified, the grid of the first experimental or observational dataset is detected and all data is then interpolated onto this grid. If the first experimental or observational dataset's data is found shifted along the longitudes (i.e., there's no value at the longitude 0 but at a longitude close to it), the data is re-interpolated to suppress the shift. This has to be done in order to make sure all the data from all the datasets is properly aligned along longitudes, as there's no option so far in \code{Load} to specify grids starting at longitudes other than 0. This issue doesn't affect when loading in 'areave' mode without a common grid, the data is not re-interpolated in that case. - } - \item{maskmod}{ -List of masks to be applied to the data of each experimental dataset respectively, if a 2-dimensional variable is specified in 'var'.\cr +Takes by default the value 'conservative'.} + +\item{grid}{A common grid can be specified through the parameter 'grid' when +loading 2-dimensional data. Data is then interpolated onto this grid +whichever 'output' type is specified. If the selected output type is +'areave' and a 'grid' is specified, the area averages are calculated after +interpolating to the specified grid.\cr +If not specified and the selected output type is 'lon', 'lat' or 'lonlat', +this parameter takes as default value the grid of the first experimental +dataset, which is read automatically from the source files.\cr +The grid must be supported by 'cdo' tools. Now only supported: rNXxNY +or tTRgrid.\cr +Both rNXxNY and tRESgrid yield rectangular regular grids. rNXxNY yields +grids that are evenly spaced in longitudes and latitudes (in degrees). +tRESgrid refers to a grid generated with series of spherical harmonics +truncated at the RESth harmonic. However these spectral grids are usually +associated to a gaussian grid, the latitudes of which are spaced with a +Gaussian quadrature (not evenly spaced in degrees). The pattern tRESgrid +will yield a gaussian grid.\cr +E.g., 'r96x72' +Advanced: If the output type is 'lon', 'lat' or 'lonlat' and no common +grid is specified, the grid of the first experimental or observational +dataset is detected and all data is then interpolated onto this grid. +If the first experimental or observational dataset's data is found shifted +along the longitudes (i.e., there's no value at the longitude 0 but at a +longitude close to it), the data is re-interpolated to suppress the shift. +This has to be done in order to make sure all the data from all the +datasets is properly aligned along longitudes, as there's no option so far +in \code{Load} to specify grids starting at longitudes other than 0. +This issue doesn't affect when loading in 'areave' mode without a common +grid, the data is not re-interpolated in that case.} + +\item{maskmod}{List of masks to be applied to the data of each experimental +dataset respectively, if a 2-dimensional variable is specified in 'var'.\cr Each mask can be defined in 2 formats:\cr a) a matrix with dimensions c(longitudes, latitudes).\cr b) a list with the components 'path' and, optionally, 'nc_var_name'.\cr -In the format a), the matrix must have the same size as the common grid or with the same size as the grid of the corresponding experimental dataset if 'areave' output type is specified and no common 'grid' is specified.\cr -In the format b), the component 'path' must be a character string with the path to a NetCDF mask file, also in the common grid or in the grid of the corresponding dataset if 'areave' output type is specified and no common 'grid' is specified. If the mask file contains only a single variable, there's no need to specify the component 'nc_var_name'. Otherwise it must be a character string with the name of the variable inside the mask file that contains the mask values. This variable must be defined only over 2 dimensions with length greater or equal to 1.\cr -Whichever the mask format, a value of 1 at a point of the mask keeps the original value at that point whereas a value of 0 disables it (replaces by a NA value).\cr +In the format a), the matrix must have the same size as the common grid +or with the same size as the grid of the corresponding experimental dataset +if 'areave' output type is specified and no common 'grid' is specified.\cr +In the format b), the component 'path' must be a character string with the +path to a NetCDF mask file, also in the common grid or in the grid of the +corresponding dataset if 'areave' output type is specified and no common +'grid' is specified. If the mask file contains only a single variable, +there's no need to specify the component 'nc_var_name'. Otherwise it must +be a character string with the name of the variable inside the mask file +that contains the mask values. This variable must be defined only over 2 +dimensions with length greater or equal to 1.\cr +Whichever the mask format, a value of 1 at a point of the mask keeps the +original value at that point whereas a value of 0 disables it (replaces +by a NA value).\cr By default all values are kept (all ones).\cr -The longitudes and latitudes in the matrix must be in the same order as in the common grid or as in the original grid of the corresponding dataset when loading in 'areave' mode. You can find out the order of the longitudes and latitudes of a file with 'cdo griddes'.\cr -Note that in a common CDO grid defined with the patterns 'tgrid' or 'rx' the latitudes and latitudes are ordered, by definition, from -90 to 90 and from 0 to 360, respectively.\cr -If you are loading maps ('lonlat', 'lon' or 'lat' output types) all the data will be interpolated onto the common 'grid'. If you want to specify a mask, you will have to provide it already interpolated onto the common grid (you may use 'cdo' libraries for this purpose). It is not usual to apply different masks on experimental datasets on the same grid, so all the experiment masks are expected to be the same.\cr -Warning: When loading maps, any masks defined for the observational data will be ignored to make sure the same mask is applied to the experimental and observational data.\cr +The longitudes and latitudes in the matrix must be in the same order as in +the common grid or as in the original grid of the corresponding dataset +when loading in 'areave' mode. You can find out the order of the longitudes +and latitudes of a file with 'cdo griddes'.\cr +Note that in a common CDO grid defined with the patterns 'tgrid' or +'rx' the latitudes and latitudes are ordered, by definition, from +-90 to 90 and from 0 to 360, respectively.\cr +If you are loading maps ('lonlat', 'lon' or 'lat' output types) all the +data will be interpolated onto the common 'grid'. If you want to specify +a mask, you will have to provide it already interpolated onto the common +grid (you may use 'cdo' libraries for this purpose). It is not usual to +apply different masks on experimental datasets on the same grid, so all +the experiment masks are expected to be the same.\cr +Warning: When loading maps, any masks defined for the observational data +will be ignored to make sure the same mask is applied to the experimental +and observational data.\cr Warning: list() compulsory even if loading 1 experimental dataset only!\cr -Ex: list(array(1, dim = c(num_lons, num_lats))) - } - \item{maskobs}{ -See help on parameter 'maskmod'. - } - \item{configfile}{ -Path to the s2dverification configuration file from which to retrieve information on location in file system (and other) of datasets.\cr -If not specified, the configuration file used at BSC-ES will be used (it is included in the package).\cr -Check the BSC's configuration file or a template of configuration file in the folder 'inst/config' in the package.\cr -Check further information on the configuration file mechanism in \code{ConfigFileOpen()}. - } - \item{varmin}{ -Loaded experimental and observational data values smaller than 'varmin' will be disabled (replaced by NA values).\cr -By default no deactivation is performed. - } - \item{varmax}{ -Loaded experimental and observational data values greater than 'varmax' will be disabled (replaced by NA values).\cr -By default no deactivation is performed. - } - \item{silent}{ -Parameter to show (FALSE) or hide (TRUE) information messages.\cr +E.g., list(array(1, dim = c(num_lons, num_lats)))} + +\item{maskobs}{See help on parameter 'maskmod'.} + +\item{configfile}{Path to the s2dverification configuration file from which +to retrieve information on location in file system (and other) of datasets.\cr +If not specified, the configuration file used at BSC-ES will be used +(it is included in the package).\cr +Check the BSC's configuration file or a template of configuration file in +the folder 'inst/config' in the package.\cr +Check further information on the configuration file mechanism in +\code{ConfigFileOpen()}.} + +\item{varmin}{Loaded experimental and observational data values smaller +than 'varmin' will be disabled (replaced by NA values).\cr +By default no deactivation is performed.} + +\item{varmax}{Loaded experimental and observational data values greater +than 'varmax' will be disabled (replaced by NA values).\cr +By default no deactivation is performed.} + +\item{silent}{Parameter to show (FALSE) or hide (TRUE) information messages.\cr Warnings will be displayed even if 'silent' is set to TRUE.\cr -Takes by default the value 'FALSE'. - } - \item{nprocs}{ -Number of parallel processes created to perform the fetch and computation of data.\cr -These processes will use shared memory in the processor in which Load() is launched.\cr -By default the number of logical cores in the machine will be detected and as many processes as logical cores there are will be created.\cr +Takes by default the value 'FALSE'.} + +\item{nprocs}{Number of parallel processes created to perform the fetch +and computation of data.\cr +These processes will use shared memory in the processor in which Load() +is launched.\cr +By default the number of logical cores in the machine will be detected +and as many processes as logical cores there are will be created.\cr A value of 1 won't create parallel processes.\cr -When running in multiple processes, if an error occurs in any of the processes, a crash message appears in the R session of the original process but no detail is given about the error. A value of 1 will display all error messages in the original and only R session.\cr -Note: the parallel process create other blocking processes each time they need to compute an interpolation via 'cdo'. - } - \item{dimnames}{ -Named list where the name of each element is a generic name of the expected dimensions inside the NetCDF files. These generic names are 'lon', 'lat' and 'member'. 'time' is not needed because it's detected automatically by discard.\cr -The value associated to each name is the actual dimension name in the NetCDF file.\cr -The variables in the file that contain the longitudes and latitudes of the data (if the data is a 2-dimensional variable) must have the same name as the longitude and latitude dimensions.\cr -By default, these names are 'longitude', 'latitude' and 'ensemble. If any of those is defined in the 'dimnames' parameter, it takes priority and overwrites the default value. -Ex.: list(lon = 'x', lat = 'y') -In that example, the dimension 'member' will take the default value 'ensemble'. - } - \item{remapcells}{ -When loading a 2-dimensional variable, spatial subsets can be requested via \code{lonmin}, \code{lonmax}, \code{latmin} and \code{latmax}. When \code{Load()} obtains the subset it is then interpolated if needed with the method specified in \code{method}.\cr -The result of this interpolation can vary if the values surrounding the spatial subset are not present. To better control this process, the width in number of grid cells of the surrounding area to be taken into account can be specified with \code{remapcells}. A value of 0 will take into account no additional cells but will generate less traffic between the storage and the R processes that load data.\cr -A value beyond the limits in the data files will be automatically runcated to the actual limit.\cr -The default value is 2. - } - \item{path_glob_permissive}{ -In some cases, when specifying a path pattern (either in the parameters 'exp'/'obs' or in a configuration file) one can specify path patterns that contain shell globbing expressions. Too much freedom in putting globbing expressions in the path patterns can be dangerous and make \code{Load()} find a file in the file system for a start date for a dataset that really does not belong to that dataset. For example, if the file system contains two directories for two different experiments that share a part of their path and the path pattern contains globbing expressions: - /experiments/model1/expA/monthly_mean/tos/tos_19901101.nc - /experiments/model2/expA/monthly_mean/tos/tos_19951101.nc -And the path pattern is used as in the example right below to load data of only the experiment 'expA' of the model 'model1' for the starting dates '19901101' and '19951101', \code{Load()} will undesiredly yield data for both starting dates, even if in fact there is data only for the first one:\cr - \code{ -expA <- list(path = file.path('/experiments/*/expA/monthly_mean/$VAR_NAME$', - '$VAR_NAME$_$START_DATE$.nc') -data <- Load('tos', list(expA), NULL, c('19901101', '19951101')) - } -To avoid these situations, the parameter \code{path_glob_permissive} is set by default to \code{'partial'}, which forces \code{Load()} to replace all the globbing expressions of a path pattern of a data set by fixed values taken from the path of the first found file for each data set, up to the folder right before the final files (globbing expressions in the file name will not be replaced, only those in the path to the file). Replacement of globbing expressions in the file name can also be triggered by setting \code{path_glob_permissive} to \code{FALSE} or \code{'no'}. If needed to keep all globbing expressions, \code{path_glob_permissive} can be set to \code{TRUE} or \code{'yes'}. - } -} -\details{ +When running in multiple processes, if an error occurs in any of the +processes, a crash message appears in the R session of the original +process but no detail is given about the error. A value of 1 will display +all error messages in the original and only R session.\cr +Note: the parallel process create other blocking processes each time they +need to compute an interpolation via 'cdo'.} + +\item{dimnames}{Named list where the name of each element is a generic +name of the expected dimensions inside the NetCDF files. These generic +names are 'lon', 'lat' and 'member'. 'time' is not needed because it's +detected automatically by discard.\cr +The value associated to each name is the actual dimension name in the +NetCDF file.\cr +The variables in the file that contain the longitudes and latitudes of +the data (if the data is a 2-dimensional variable) must have the same +name as the longitude and latitude dimensions.\cr +By default, these names are 'longitude', 'latitude' and 'ensemble. If any +of those is defined in the 'dimnames' parameter, it takes priority and +overwrites the default value. +E.g., list(lon = 'x', lat = 'y') +In that example, the dimension 'member' will take the default value 'ensemble'.} + +\item{remapcells}{When loading a 2-dimensional variable, spatial subsets can +be requested via \code{lonmin}, \code{lonmax}, \code{latmin} and +\code{latmax}. When \code{Load()} obtains the subset it is then +interpolated if needed with the method specified in \code{method}.\cr +The result of this interpolation can vary if the values surrounding the +spatial subset are not present. To better control this process, the width +in number of grid cells of the surrounding area to be taken into account +can be specified with \code{remapcells}. A value of 0 will take into +account no additional cells but will generate less traffic between the +storage and the R processes that load data.\cr +A value beyond the limits in the data files will be automatically runcated +to the actual limit.\cr +The default value is 2.} + +\item{path_glob_permissive}{In some cases, when specifying a path pattern + (either in the parameters 'exp'/'obs' or in a configuration file) one can + specify path patterns that contain shell globbing expressions. Too much + freedom in putting globbing expressions in the path patterns can be + dangerous and make \code{Load()} find a file in the file system for a + start date for a dataset that really does not belong to that dataset. + For example, if the file system contains two directories for two different + experiments that share a part of their path and the path pattern contains + globbing expressions: + /experiments/model1/expA/monthly_mean/tos/tos_19901101.nc + /experiments/model2/expA/monthly_mean/tos/tos_19951101.nc + And the path pattern is used as in the example right below to load data of + only the experiment 'expA' of the model 'model1' for the starting dates + '19901101' and '19951101', \code{Load()} will undesiredly yield data for + both starting dates, even if in fact there is data only for the + first one:\cr + \code{ + expA <- list(path = file.path('/experiments/*/expA/monthly_mean/$VAR_NAME$', + '$VAR_NAME$_$START_DATE$.nc') + data <- Load('tos', list(expA), NULL, c('19901101', '19951101')) + } + To avoid these situations, the parameter \code{path_glob_permissive} is + set by default to \code{'partial'}, which forces \code{Load()} to replace + all the globbing expressions of a path pattern of a data set by fixed + values taken from the path of the first found file for each data set, up + to the folder right before the final files (globbing expressions in the + file name will not be replaced, only those in the path to the file). + Replacement of globbing expressions in the file name can also be triggered + by setting \code{path_glob_permissive} to \code{FALSE} or \code{'no'}. If + needed to keep all globbing expressions, \code{path_glob_permissive} can + be set to \code{TRUE} or \code{'yes'}. + The two output matrices have between 2 and 6 dimensions:\cr - \enumerate{ - \item{Number of experimental/observational datasets.} - \item{Number of members.} - \item{Number of startdates.} - \item{Number of leadtimes.} - \item{Number of latitudes (optional).} - \item{Number of longitudes (optional).} - } -but the two matrices have the same number of dimensions and only the first two dimensions can have different lengths depending on the input arguments. - -For a detailed explanation of the process, read the documentation attached to the package or check the comments in the code. + \enumerate{ + \item{Number of experimental/observational datasets.} + \item{Number of members.} + \item{Number of startdates.} + \item{Number of leadtimes.} + \item{Number of latitudes (optional).} + \item{Number of longitudes (optional).} + } +but the two matrices have the same number of dimensions and only the first +two dimensions can have different lengths depending on the input arguments. +For a detailed explanation of the process, read the documentation attached +to the package or check the comments in the code.} + +\item{leatimemax}{Only lead-times lower or equal to 'leadtimemax' are loaded. +Takes by default the number of lead-times of the first experimental +dataset in 'exp'.\cr +If 'exp' is NULL this argument won't have any effect +(see \code{?Load} description).} } \value{ -\code{Load()} returns a named list following a structure similar to the used in the package 'downscaleR'.\cr +\code{Load()} returns a named list following a structure similar to the +used in the package 'downscaleR'.\cr The components are the following: - \itemize{ - \item{ -'mod' is the array that contains the experimental data. It has the attribute 'dimensions' associated to a vector of strings with the labels of each dimension of the array, in order. The order of the latitudes is always forced to be from 90 to -90 whereas the order of the longitudes is kept as in the original files (if possible). The longitude values provided in \code{lon} lower than 0 are added 360 (but still kept in the original order). In some cases, however, if multiple data sets are loaded in longitude-latitude mode, the longitudes (and also the data arrays in \code{mod} and \code{obs}) are re-ordered afterwards by \code{Load()} to range from 0 to 360; a warning is given in such cases. The longitude and latitude of the center of the grid cell that corresponds to the value [j, i] in 'mod' (along the dimensions latitude and longitude, respectively) can be found in the outputs \code{lon}[i] and \code{lat}[j] - } - \item{'obs' is the array that contains the observational data. The same documentation of parameter 'mod' applies to this parameter.} - \item{'lat' and 'lon' are the latitudes and longitudes of the centers of the cells of the grid the data is interpolated into (0 if the loaded variable is a global mean or the output is an area average).\cr -Both have the attribute 'cdo_grid_des' associated with a character string with the name of the common grid of the data, following the CDO naming conventions for grids.\cr -'lon' has the attributes 'first_lon' and 'last_lon', with the first and last longitude values found in the region defined by 'lonmin' and 'lonmax'. 'lat' has also the equivalent attributes 'first_lat' and 'last_lat'.\cr -'lon' has also the attribute 'data_across_gw' which tells whether the requested region via 'lonmin', 'lonmax', 'latmin', 'latmax' goes across the Greenwich meridian. As explained in the documentation of the parameter 'mod', the loaded data array is kept in the same order as in the original files when possible: this means that, in some cases, even if the data goes across the Greenwich, the data array may not go across the Greenwich. The attribute 'array_across_gw' tells whether the array actually goes across the Greenwich. E.g: The longitudes in the data files are defined to be from 0 to 360. The requested longitudes are from -80 to 40. The original order is kept, hence the longitudes in the array will be ordered as follows: 0, ..., 40, 280, ..., 360. In that case, 'data_across_gw' will be TRUE and 'array_across_gw' will be FALSE.\cr -The attribute 'projection' is kept for compatibility with 'downscaleR'.} - \item{'Variable' has the following components: - \itemize{ - \item{'varName', with the short name of the loaded variable as specified in the parameter 'var'.} - \item{'level', with information on the pressure level of the variable. Is kept to NULL by now.} - } -And the following attributes: - \itemize{ - \item{'is_standard', kept for compatibility with 'downscaleR', tells if a dataset has been homogenized to standards with 'downscaleR' catalogs.} - \item{'units', a character string with the units of measure of the variable, as found in the source files.} - \item{'longname', a character string with the long name of the variable, as found in the source files.} - \item{'daily_agg_cellfun', 'monthly_agg_cellfun', 'verification_time', kept for compatibility with 'downscaleR'.} - } - } - \item{'Datasets' has the following components: - \itemize{ - \item{'exp', a named list where the names are the identifying character strings of each experiment in 'exp', each associated to a list with the following components: - \itemize{ - \item{'members', a list with the names of the members of the dataset.} - \item{'source', a path or URL to the source of the dataset.} - } - } - \item{'obs', similar to 'exp' but for observational datasets.} - } - } - \item{'Dates', with the follwing components: - \itemize{ - \item{'start', an array of dimensions (sdate, time) with the POSIX initial date of each forecast time of each starting date.} - \item{'end', an array of dimensions (sdate, time) with the POSIX final date of each forecast time of each starting date.} - } - } - \item{'InitializationDates', a vector of starting dates as specified in 'sdates', in POSIX format.} - \item{'when', a time stamp of the date the \code{Load()} call to obtain the data was issued.} - \item{'source_files', a vector of character strings with complete paths to all the found files involved in the \code{Load()} call.} - \item{'not_found_files', a vector of character strings with complete paths to not found files involved in the \code{Load()} call.} - } + \itemize{ + \item{ + 'mod' is the array that contains the experimental data. It has the + attribute 'dimensions' associated to a vector of strings with the + labels of each dimension of the array, in order. The order of the + latitudes is always forced to be from 90 to -90 whereas the order of + the longitudes is kept as in the original files (if possible). The + longitude values provided in \code{lon} lower than 0 are added 360 + (but still kept in the original order). In some cases, however, if + multiple data sets are loaded in longitude-latitude mode, the + longitudes (and also the data arrays in \code{mod} and \code{obs}) are + re-ordered afterwards by \code{Load()} to range from 0 to 360; a + warning is given in such cases. The longitude and latitude of the + center of the grid cell that corresponds to the value [j, i] in 'mod' + (along the dimensions latitude and longitude, respectively) can be + found in the outputs \code{lon}[i] and \code{lat}[j] + } + \item{'obs' is the array that contains the observational data. The + same documentation of parameter 'mod' applies to this parameter.} + \item{'lat' and 'lon' are the latitudes and longitudes of the centers of + the cells of the grid the data is interpolated into (0 if the loaded + variable is a global mean or the output is an area average).\cr + Both have the attribute 'cdo_grid_des' associated with a character + string with the name of the common grid of the data, following the CDO + naming conventions for grids.\cr + 'lon' has the attributes 'first_lon' and 'last_lon', with the first + and last longitude values found in the region defined by 'lonmin' and + 'lonmax'. 'lat' has also the equivalent attributes 'first_lat' and + 'last_lat'.\cr + 'lon' has also the attribute 'data_across_gw' which tells whether the + requested region via 'lonmin', 'lonmax', 'latmin', 'latmax' goes across + the Greenwich meridian. As explained in the documentation of the + parameter 'mod', the loaded data array is kept in the same order as in + the original files when possible: this means that, in some cases, even + if the data goes across the Greenwich, the data array may not go + across the Greenwich. The attribute 'array_across_gw' tells whether + the array actually goes across the Greenwich. E.g: The longitudes in + the data files are defined to be from 0 to 360. The requested + longitudes are from -80 to 40. The original order is kept, hence the + longitudes in the array will be ordered as follows: + 0, ..., 40, 280, ..., 360. In that case, 'data_across_gw' will be TRUE + and 'array_across_gw' will be FALSE.\cr + The attribute 'projection' is kept for compatibility with 'downscaleR'. + } + \item{'Variable' has the following components: + \itemize{ + \item{'varName', with the short name of the loaded variable as + specified in the parameter 'var'. + } + \item{'level', with information on the pressure level of the + variable. Is kept to NULL by now. + } + } + And the following attributes: + \itemize{ + \item{'is_standard', kept for compatibility with 'downscaleR', + tells if a dataset has been homogenized to standards with + 'downscaleR' catalogs. + } + \item{'units', a character string with the units of measure of the + variable, as found in the source files. + } + \item{'longname', a character string with the long name of the + variable, as found in the source files. + } + \item{'daily_agg_cellfun', 'monthly_agg_cellfun', + 'verification_time', kept for compatibility with 'downscaleR'. + } + } + } + \item{'Datasets' has the following components: + \itemize{ + \item{'exp', a named list where the names are the identifying + character strings of each experiment in 'exp', each associated to + a list with the following components: + \itemize{ + \item{'members', a list with the names of the members of the dataset.} + \item{'source', a path or URL to the source of the dataset.} + } + } + \item{'obs', similar to 'exp' but for observational datasets.} + } + } + \item{'Dates', with the follwing components: + \itemize{ + \item{'start', an array of dimensions (sdate, time) with the POSIX + initial date of each forecast time of each starting date. + } + \item{'end', an array of dimensions (sdate, time) with the POSIX + final date of each forecast time of each starting date. + } + } + } + \item{'InitializationDates', a vector of starting dates as specified in + 'sdates', in POSIX format. + } + \item{'when', a time stamp of the date the \code{Load()} call to obtain + the data was issued. + } + \item{'source_files', a vector of character strings with complete paths + to all the found files involved in the \code{Load()} call. + } + \item{'not_found_files', a vector of character strings with complete + paths to not found files involved in the \code{Load()} call. + } + } } -\author{ -History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr -1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Generalisation + parallelisation\cr -1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Improvements related to configuration file mechanism\cr -1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Added subsetting capabilities\cr +\description{ +This function loads monthly or daily data from a set of specified +experimental datasets together with data that date-corresponds from a set +of specified observational datasets. See parameters 'storefreq', +'sampleperiod', 'exp' and 'obs'.\cr\cr +A set of starting dates is specified through the parameter 'sdates'. Data of +each starting date is loaded for each model. +\code{Load()} arranges the data in two arrays with a similar format both +with the following dimensions: + \enumerate{ + \item{The number of experimental datasets determined by the user through + the argument 'exp' (for the experimental data array) or the number of + observational datasets available for validation (for the observational + array) determined as well by the user through the argument 'obs'.} + \item{The greatest number of members across all experiments (in the + experimental data array) or across all observational datasets (in the + observational data array).} + \item{The number of starting dates determined by the user through the + 'sdates' argument.} + \item{The greatest number of lead-times.} + \item{The number of latitudes of the selected zone.} + \item{The number of longitudes of the selected zone.} + } +Dimensions 5 and 6 are optional and their presence depends on the type of +the specified variable (global mean or 2-dimensional) and on the selected +output type (area averaged time series, latitude averaged time series, +longitude averaged time series or 2-dimensional time series).\cr +In the case of loading an area average the dimensions of the arrays will be +only the first 4.\cr\cr +Only a specified variable is loaded from each experiment at each starting +date. See parameter 'var'.\cr +Afterwards, observational data that matches every starting date and lead-time +of every experimental dataset is fetched in the file system (so, if two +predictions at two different start dates overlap, some observational values +will be loaded and kept in memory more than once).\cr +If no data is found in the file system for an experimental or observational +array point it is filled with an NA value.\cr\cr +If the specified output is 2-dimensional or latitude- or longitude-averaged +time series all the data is interpolated into a common grid. If the +specified output type is area averaged time series the data is averaged on +the individual grid of each dataset but can also be averaged after +interpolating into a common grid. See parameters 'grid' and 'method'.\cr +Once the two arrays are filled by calling this function, other functions in +the s2dverification package that receive as inputs data formatted in this +data structure can be executed (e.g: \code{Clim()} to compute climatologies, +\code{Ano()} to compute anomalies, ...).\cr\cr +Load() has many additional parameters to disable values and trim dimensions +of selected variable, even masks can be applied to 2-dimensional variables. +See parameters 'nmember', 'nmemberobs', 'nleadtime', 'leadtimemin', +'leadtimemax', 'sampleperiod', 'lonmin', 'lonmax', 'latmin', 'latmax', +'maskmod', 'maskobs', 'varmin', 'varmax'.\cr\cr +The parameters 'exp' and 'obs' can take various forms. The most direct form +is a list of lists, where each sub-list has the component 'path' associated +to a character string with a pattern of the path to the files of a dataset +to be loaded. These patterns can contain wildcards and tags that will be +replaced automatically by \code{Load()} with the specified starting dates, +member numbers, variable name, etc.\cr +See parameter 'exp' or 'obs' for details.\cr\cr +Only NetCDF files are supported. OPeNDAP URLs to NetCDF files are also +supported.\cr +\code{Load()} can load 2-dimensional or global mean variables in any of the +following formats: + \itemize{ + \item{experiments: + \itemize{ + \item{file per ensemble per starting date + (YYYY, MM and DD somewhere in the path)} + \item{file per member per starting date + (YYYY, MM, DD and MemberNumber somewhere in the path. Ensemble + experiments with different numbers of members can be loaded in + a single \code{Load()} call.)} + } + (YYYY, MM and DD specify the starting dates of the predictions) + } + \item{observations: + \itemize{ + \item{file per ensemble per month + (YYYY and MM somewhere in the path)} + \item{file per member per month + (YYYY, MM and MemberNumber somewhere in the path, obs with different + numbers of members supported)} + \item{file per dataset (No constraints in the path but the time axes + in the file have to be properly defined)} + } + (YYYY and MM correspond to the actual month data in the file) + } + } +In all the formats the data can be stored in a daily or monthly frequency, +or a multiple of these (see parameters 'storefreq' and 'sampleperiod').\cr +All the data files must contain the target variable defined over time and +potentially over members, latitude and longitude dimensions in any order, +time being the record dimension.\cr +In the case of a two-dimensional variable, the variables longitude and +latitude must be defined inside the data file too and must have the same +names as the dimension for longitudes and latitudes respectively.\cr +The names of these dimensions (and longitude and latitude variables) and the +name for the members dimension are expected to be 'longitude', 'latitude' +and 'ensemble' respectively. However, these names can be adjusted with the +parameter 'dimnames' or can be configured in the configuration file (read +below in parameters 'exp', 'obs' or see \code{?ConfigFileOpen} +for more information.\cr +All the data files are expected to have numeric values representable with +32 bits. Be aware when choosing the fill values or infinite values in the +datasets to load.\cr\cr +The Load() function returns a named list following a structure similar to +the used in the package 'downscaleR'.\cr +The components are the following: + \itemize{ + \item{'mod' is the array that contains the experimental data. It has the + attribute 'dimensions' associated to a vector of strings with the labels + of each dimension of the array, in order.} + \item{'obs' is the array that contains the observational data. It has + the attribute 'dimensions' associated to a vector of strings with the + labels of each dimension of the array, in order.} + \item{'obs' is the array that contains the observational data.} + \item{'lat' and 'lon' are the latitudes and longitudes of the grid into + which the data is interpolated (0 if the loaded variable is a global + mean or the output is an area average).\cr + Both have the attribute 'cdo_grid_des' associated with a character + string with the name of the common grid of the data, following the CDO + naming conventions for grids.\cr + The attribute 'projection' is kept for compatibility with 'downscaleR'. + } + \item{'Variable' has the following components: + \itemize{ + \item{'varName', with the short name of the loaded variable as + specified in the parameter 'var'.} + \item{'level', with information on the pressure level of the variable. + Is kept to NULL by now.} + } + And the following attributes: + \itemize{ + \item{'is_standard', kept for compatibility with 'downscaleR', + tells if a dataset has been homogenized to standards with + 'downscaleR' catalogs.} + \item{'units', a character string with the units of measure of the + variable, as found in the source files.} + \item{'longname', a character string with the long name of the + variable, as found in the source files.} + \item{'daily_agg_cellfun', 'monthly_agg_cellfun', 'verification_time', + kept for compatibility with 'downscaleR'.} + } + } + \item{'Datasets' has the following components: + \itemize{ + \item{'exp', a named list where the names are the identifying + character strings of each experiment in 'exp', each associated to a + list with the following components: + \itemize{ + \item{'members', a list with the names of the members of the + dataset.} + \item{'source', a path or URL to the source of the dataset.} + } + } + \item{'obs', similar to 'exp' but for observational datasets.} + } + } + \item{'Dates', with the follwing components: + \itemize{ + \item{'start', an array of dimensions (sdate, time) with the POSIX + initial date of each forecast time of each starting date.} + \item{'end', an array of dimensions (sdate, time) with the POSIX + final date of each forecast time of each starting date.} + } + } + \item{'InitializationDates', a vector of starting dates as specified in + 'sdates', in POSIX format.} + \item{'when', a time stamp of the date the \code{Load()} call to obtain + the data was issued.} + \item{'source_files', a vector of character strings with complete paths + to all the found files involved in the \code{Load()} call.} + \item{'not_found_files', a vector of character strings with complete + paths to not found files involved in the \code{Load()} call.} + } } \examples{ # Let's assume we want to perform verification with data of a variable @@ -505,24 +795,24 @@ History:\cr # # Example 1: Providing lists of lists to 'exp' and 'obs': # - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') exp <- list( - name = 'experiment', - path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', - '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') - ) + name = 'experiment', + path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', + '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') + ) obs <- list( - name = 'observation', - path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', - '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') - ) + name = 'observation', + path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', + '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + ) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(exp), list(obs), startDates, - output = 'areave', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + output = 'areave', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } # # Example 2: Providing vectors of character strings to 'exp' and 'obs' # and using a configuration file. @@ -531,20 +821,20 @@ sampleData <- Load('tos', list(exp), list(obs), startDates, # has the proper entries to load these (see ?LoadConfigFile for details on # writing a configuration file). # - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - output = 'areave', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) + output = 'areave', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) # # Example 2: providing character strings in 'exp' and 'obs', and providing # a configuration file. @@ -561,26 +851,36 @@ data_path <- system.file('sample_data', package = 's2dverification') exp_data_path <- paste0(data_path, '/model/$EXP_NAME$/') obs_data_path <- paste0(data_path, '/$OBS_NAME$/') c <- ConfigAddEntry(c, 'experiments', dataset_name = 'experiment', - var_name = 'tos', main_path = exp_data_path, - file_path = '$STORE_FREQ$_mean/$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATE$.nc') + var_name = 'tos', main_path = exp_data_path, + file_path = '$STORE_FREQ$_mean/$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATE$.nc') c <- ConfigAddEntry(c, 'observations', dataset_name = 'observation', - var_name = 'tos', main_path = obs_data_path, - file_path = '$STORE_FREQ$_mean/$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + var_name = 'tos', main_path = obs_data_path, + file_path = '$STORE_FREQ$_mean/$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') ConfigFileSave(c, configfile, confirm = FALSE) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', c('experiment'), c('observation'), startDates, - output = 'areave', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40, configfile = configfile) - } - \dontshow{ + output = 'areave', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40, configfile = configfile) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - output = 'areave', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + output = 'areave', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } + +} +\author{ +History:\cr +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr +1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Generalisation + parallelisation\cr +1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Improvements related to configuration file mechanism\cr +1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Added subsetting capabilities\cr } \keyword{datagen} + diff --git a/man/Mean1Dim.Rd b/man/Mean1Dim.Rd index 0d56d083..613fc468 100644 --- a/man/Mean1Dim.Rd +++ b/man/Mean1Dim.Rd @@ -1,30 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Mean1Dim.R \name{Mean1Dim} \alias{Mean1Dim} -\title{ -Averages An Array Along A Dimension -} -\description{ -Averages the array along the posdim dimension along the user specified dimension. The user can specify a subset of the dimension to take the mean along. -} +\title{Averages An Array Along A Dimension} \usage{ Mean1Dim(var, posdim, narm = TRUE, limits = NULL) } \arguments{ - \item{var}{ -Matrix to average. - } - \item{posdim}{ -Dimension to average along. - } - \item{narm}{ -Ignore NA (TRUE) values or not (FALSE). - } - \item{limits}{ -Limits to average between. Default is to take the mean along the entire dimension. - } +\item{var}{Matrix to average.} + +\item{posdim}{Dimension to average along.} + +\item{narm}{Ignore NA (TRUE) values or not (FALSE).} + +\item{limits}{Limits to average between. Default is to take the mean along +the entire dimension.} } \value{ -Array with one dimension less than the input array, containing the average along the posdim dimension. +Array with one dimension less than the input array, containing + the average along the posdim dimension. +} +\description{ +Averages the array along the posdim dimension along the user specified +dimension. The user can specify a subset of the dimension to take the mean +along. } \examples{ a <- array(rnorm(24), dim = c(2, 3, 4)) @@ -33,7 +32,8 @@ print(Mean1Dim(a, 2)) } \author{ History:\cr -0.1 - 2011-04 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN +0.1 - 2011-04 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN } \keyword{datagen} + diff --git a/man/MeanListDim.Rd b/man/MeanListDim.Rd index f3667d75..98e07c8e 100644 --- a/man/MeanListDim.Rd +++ b/man/MeanListDim.Rd @@ -1,27 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/MeanListDim.R \name{MeanListDim} \alias{MeanListDim} -\title{ -Averages An Array Along Multiple Dimensions -} -\description{ -Averages an array along a set of dimensions given by the argument dims. -} +\title{Averages An Array Along Multiple Dimensions} \usage{ MeanListDim(var, dims, narm = TRUE) } \arguments{ - \item{var}{ -Input array. - } - \item{dims}{ -List of dimensions to average along. - } - \item{narm}{ -Ignore NA (TRUE) values or not (FALSE). - } +\item{var}{Input array.} + +\item{dims}{List of dimensions to average along.} + +\item{narm}{Ignore NA (TRUE) values or not (FALSE).} } \value{ -The averaged array, with the dimensions specified in \code{dims} removed. +The averaged array, with the dimensions specified in \code{dims} + removed. +} +\description{ +Averages an array along a set of dimensions given by the argument dims. } \examples{ a <- array(rnorm(24), dim = c(2, 3, 4)) @@ -36,3 +33,4 @@ History:\cr 1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improved memory usage } \keyword{datagen} + diff --git a/man/NAO.Rd b/man/NAO.Rd index c0963652..048c20ec 100644 --- a/man/NAO.Rd +++ b/man/NAO.Rd @@ -1,95 +1,95 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/NAO.R \name{NAO} \alias{NAO} -\title{ -Computes the North Atlantic Oscillation (NAO) Index -} -\description{ -Compute the North Atlantic Oscillation (NAO) index based on -the leading EOF of the sea level pressure (SLP) anomalies over the -north Atlantic region (20N-80N, 80W-40E). The PCs are obtained by projecting -the forecast and observed anomalies onto the observed EOF pattern (Pobs) or the -forecast anomalies onto the EOF pattern of the other years of the forecast -(Pmod). By default (ftime_average = 2:4) NAO() computes the NAO index for -1-month lead seasonal forecasts that can be plotted with BoxPlot(). Returns -cross-validated PCs of the NAO index for forecast (ano_exp) and observations -(ano_obs) based on the leading EOF pattern.\cr -} +\title{Computes the North Atlantic Oscillation (NAO) Index} \usage{ -NAO(ano_exp = NULL, ano_obs = NULL, lon, lat, ftime_average = 2:4, - obsproj = TRUE) +NAO(ano_exp = NULL, ano_obs = NULL, lon, lat, ftime_average = 2:4, + obsproj = TRUE) } \arguments{ - \item{ano_exp}{ -Array of North Atlantic SLP (20N-80N, 80W-40E) forecast anomalies from -\code{Ano()} or \code{Ano_CrossValid()} with dimensions (n. of experimental -data sets, n. of ensemble members, n. of start dates, n. of forecast time -steps, n. of latitudes, n. of longitudes). If only NAO of observational data -needs to be computed, this parameter can be left to NULL (default). - } - \item{ano_obs}{ -Array of North Atlantic SLP (20N-80N, 80W-40E) observed anomalies from -\code{Ano()} or \code{Ano_CrossValid()} with dimensions (n. of observational -data sets, n. of obs. ensemble members, n. of start dates, n. of forecast time -steps, n. of latitudes, n. of longitudes). If only NAO of experimental data -needs to be computed, this parameter can be left to NULL (default). - } - \item{lon}{ -Vector with the longitudes of \code{ano_exp} and \code{ano_obs}. - } - \item{lat}{ -Vector with the latitudes of \code{ano_exp} and \code{ano_obs}. - } - \item{ftime_average}{ -A vector with the forecast time steps to average across defining the target -period. Takes by default 2:4, i.e. from 2nd to 4th forecast time steps. - } - \item{obsproj}{ -\code{obsproj = TRUE} will compute the NAO index by projecting the forecast -anomalies onto the leading EOF of observational reference.\cr +\item{ano_exp}{Array of North Atlantic SLP (20N-80N, 80W-40E) forecast +anomalies from \code{Ano()} or \code{Ano_CrossValid()} with dimensions +(n. of experimental data sets, n. of ensemble members, n. of start dates, +n. of forecast time steps, n. of latitudes, n. of longitudes). If only +NAO of observational data needs to be computed, this parameter can be left +to NULL (default).} + +\item{ano_obs}{Array of North Atlantic SLP (20N-80N, 80W-40E) observed +anomalies from \code{Ano()} or \code{Ano_CrossValid()} with dimensions +(n. of observational data sets, n. of obs. ensemble members, +n. of start dates, n. of forecast time steps, n. of latitudes, +n. of longitudes). If only NAO of experimental data needs to be computed, +this parameter can be left to NULL (default).} + +\item{lon}{Vector with the longitudes of \code{ano_exp} and \code{ano_obs}.} + +\item{lat}{Vector with the latitudes of \code{ano_exp} and \code{ano_obs}.} + +\item{ftime_average}{A vector with the forecast time steps to average across +defining the target period. Takes by default 2:4, i.e. from 2nd to 4th +forecast time steps.} + +\item{obsproj}{\code{obsproj = TRUE} will compute the NAO index by +projecting the forecast anomalies onto the leading EOF of observational +reference.\cr \code{obsproj = FALSE} will compute the NAO by first computing the leading -EOF of the forecast anomalies (in cross-validation mode, i.e. leaving the year -you are evaluating out), and then projecting forecast anomalies onto this EOF. - } +EOF of the forecast anomalies (in cross-validation mode, i.e. leaving the +year you are evaluating out), and then projecting forecast anomalies onto +this EOF.} } \value{ - \item{NAO_exp}{ -Array of forecast NAO index in verification format (ensemble members, -start dates). - } - \item{NAO_obs}{ -Array of observed NAO index in verification format (1, number of start -dates). - } - \item{EOFs_obs}{ -EOFs of the observational references. - } +\itemize{ + \item{NAO_exp}{ + Array of forecast NAO index in verification format (ensemble members, + start dates). + } + \item{NAO_obs}{ + Array of observed NAO index in verification format (1, number of start + dates). + } + \item{EOFs_obs}{ + EOFs of the observational references. + } +} +} +\description{ +Compute the North Atlantic Oscillation (NAO) index based on the leading EOF +of the sea level pressure (SLP) anomalies over the north Atlantic region +(20N-80N, 80W-40E). The PCs are obtained by projecting the forecast and +observed anomalies onto the observed EOF pattern (Pobs) or the forecast +anomalies onto the EOF pattern of the other years of the forecast (Pmod). +By default (ftime_average = 2:4) NAO() computes the NAO index for 1-month +lead seasonal forecasts that can be plotted with BoxPlot(). Returns +cross-validated PCs of the NAO index for forecast (ano_exp) and observations +(ano_obs) based on the leading EOF pattern. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 20, latmax = 90, lonmin = -80, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 20, latmax = 90, lonmin = -80, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) # No example data is available over NAO region, so in this example we will # tweak the available data. In a real use case, one can Load() the data over # NAO region directly. @@ -100,7 +100,7 @@ attr(sampleData$lon, 'data_across_gw') <- TRUE sampleData$lat[] <- c(20, 80) attr(sampleData$lat, 'first_lat') <- 20 attr(sampleData$lat, 'last_lat') <- 80 - } + } # Now ready to compute the EOFs and project on, for example, the first # variability mode. @@ -110,24 +110,27 @@ ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) # Finally plot the NAO index PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", - monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") -} -\references{ -Doblas-Reyes, F.J., Pavan, V. and Stephenson, D. (2003). The skill of -multi-model seasonal forecasts of the wintertime North Atlantic Oscillation. -Climate Dynamics, 21, 501-514. DOI: 10.1007/s00382-003-0350-4 + monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") + } \author{ History:\cr 0.1 - 2013-08 (F. Lienert, \email{flienert at ic3.cat}) - Original code\cr 0.2 - 2014-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Removing the -rotation\cr + rotation\cr 0.3 - 2014-05 (L. Batte, \email{lauriane.batte at ic3.cat}) - Changes to -simplify function and add Pobs and Pmod options for NAO projection -calculations\cr + simplify function and add Pobs and Pmod options for NAO projection + calculations\cr 0.4 - 2015-03 (L. Batte, \email{lauriane.batte at ic3.cat}) - Polarity -check and correction is wrong. Switched to have a negative NAO index when the -anomaly pattern corresponds to NAO-. -1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatted to CRAN + check and correction is wrong. Switched to have a negative NAO index when the + anomaly pattern corresponds to NAO-. +1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - + Formatted to CRAN +} +\references{ +Doblas-Reyes, F.J., Pavan, V. and Stephenson, D. (2003). The skill of + multi-model seasonal forecasts of the wintertime North Atlantic Oscillation. + Climate Dynamics, 21, 501-514. DOI: 10.1007/s00382-003-0350-4 } \keyword{datagen} + diff --git a/man/Plot2VarsVsLTime.Rd b/man/Plot2VarsVsLTime.Rd index faeaed79..df5be414 100644 --- a/man/Plot2VarsVsLTime.Rd +++ b/man/Plot2VarsVsLTime.Rd @@ -1,104 +1,89 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Plot2VarsVsLTime.R \name{Plot2VarsVsLTime} \alias{Plot2VarsVsLTime} -\title{ -Plot Two Scores With Confidence Intervals In A Common Plot -} -\description{ -Plots two input variables having the same dimensions in a common plot.\cr -One plot for all experiments.\cr -Input variables should have dimensions (nexp/nmod, nltime). -} +\title{Plot Two Scores With Confidence Intervals In A Common Plot} \usage{ -Plot2VarsVsLTime(var1, var2, toptitle = "", ytitle = "", monini = 1, - freq = 12, nticks = NULL, limits = NULL, - listexp = c("exp1", "exp2", "exp3"), - listvars = c("var1", "var2"), biglab = FALSE, hlines = NULL, - leg = TRUE, siglev = FALSE, sizetit = 1, show_conf = TRUE, - fileout = "output_plot2varsvsltime.eps", - width = 8, height = 5, size_units = 'in', res = 100, ...) +Plot2VarsVsLTime(var1, var2, toptitle = "", ytitle = "", monini = 1, + freq = 12, nticks = NULL, limits = NULL, listexp = c("exp1", "exp2", + "exp3"), listvars = c("var1", "var2"), biglab = FALSE, hlines = NULL, + leg = TRUE, siglev = FALSE, sizetit = 1, show_conf = TRUE, + fileout = "output_plot2varsvsltime.eps", width = 8, height = 5, + size_units = "in", res = 100, ...) } \arguments{ - \item{var1}{ -Matrix of dimensions (nexp/nmod, nltime). - } - \item{var2}{ -Matrix of dimensions (nexp/nmod, nltime). - } - \item{toptitle}{ -Main title, optional. - } - \item{ytitle}{ -Title of Y-axis, optional. - } - \item{monini}{ -Starting month between 1 and 12. Default = 1. - } - \item{freq}{ -1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12. - } - \item{nticks}{ -Number of ticks and labels on the x-axis, optional. - } - \item{limits}{ -c(lower limit, upper limit): limits of the Y-axis, optional. - } - \item{listexp}{ -List of experiment names, up to three, optional. - } - \item{listvars}{ -List of names of input variables, optional. - } - \item{biglab}{ -TRUE/FALSE for presentation/paper plot. Default = FALSE. - } - \item{hlines}{ -c(a, b, ...) Add horizontal black lines at Y-positions a, b, ...\cr -Default: NULL. - } - \item{leg}{ -TRUE/FALSE if legend should be added or not to the plot. Default = TRUE. - } - \item{siglev}{ -TRUE/FALSE if significance level should replace confidence interval.\cr -Default = FALSE. - } - \item{sizetit}{ -Multiplicative factor to change title size, optional. - } - \item{show_conf}{ -TRUE/FALSE to show/not confidence intervals for input variables. - } - \item{fileout}{ -Name of output file. Extensions allowed: eps/ps, jpeg, png, pdf, bmp -and tiff. \cr -Default = 'output_plot2varsvsltime.eps' - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } -} -\details{ +\item{var1}{Matrix of dimensions (nexp/nmod, nltime).} + +\item{var2}{Matrix of dimensions (nexp/nmod, nltime).} + +\item{toptitle}{Main title, optional.} + +\item{ytitle}{Title of Y-axis, optional.} + +\item{monini}{Starting month between 1 and 12. Default = 1.} + +\item{freq}{1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12.} + +\item{nticks}{Number of ticks and labels on the x-axis, optional.} + +\item{limits}{c(lower limit, upper limit): limits of the Y-axis, optional.} + +\item{listexp}{List of experiment names, up to three, optional.} + +\item{listvars}{List of names of input variables, optional.} + +\item{biglab}{TRUE/FALSE for presentation/paper plot. Default = FALSE.} + +\item{hlines}{c(a, b, ...) Add horizontal black lines at Y-positions a, b, +...\cr +Default: NULL.} + +\item{leg}{TRUE/FALSE if legend should be added or not to the plot. +Default = TRUE.} + +\item{siglev}{TRUE/FALSE if significance level should replace confidence +interval.\cr +Default = FALSE.} + +\item{sizetit}{Multiplicative factor to change title size, optional.} + +\item{show_conf}{TRUE/FALSE to show/not confidence intervals for input +variables.} + +\item{fileout}{Name of output file. Extensions allowed: eps/ps, jpeg, png, +pdf, bmp and tiff. \cr +Default = 'output_plot2varsvsltime.eps'} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{...}{Arguments to be passed to the method. Only accepts the following + graphical parameters:\cr + adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt + csi cxy err family fg fig font font.axis font.lab font.main font.sub lend + lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt + smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr + For more information about the parameters see `par`. + Examples of input:\cr ------------------\cr \cr -RMSE error for a number of experiments and along lead-time: (nexp, nltime) +RMSE error for a number of experiments and along lead-time: (nexp, nltime)} +} +\description{ +Plots two input variables having the same dimensions in a common plot.\cr +One plot for all experiments.\cr +Input variables should have dimensions (nexp/nmod, nltime). } \examples{ # Load sample data as in Load() example: @@ -114,20 +99,23 @@ dim_to_mean <- 2 # Mean along members required_complete_row <- 3 # Discard start dates that contain NA along lead-times leadtimes_per_startdate <- 60 rms <- RMS(Mean1Dim(smooth_ano_exp, dim_to_mean), - Mean1Dim(smooth_ano_obs, dim_to_mean), - compROW = required_complete_row, - limits = c(ceiling((runmean_months + 1) / 2), - leadtimes_per_startdate - floor(runmean_months / 2))) + Mean1Dim(smooth_ano_obs, dim_to_mean), + compROW = required_complete_row, + limits = c(ceiling((runmean_months + 1) / 2), + leadtimes_per_startdate - floor(runmean_months / 2))) smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, - narm = TRUE), 2, dim(smooth_ano_exp)[2]) + narm = TRUE), 2, dim(smooth_ano_exp)[2]) spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) Plot2VarsVsLTime(InsertDim(rms[, , , ], 1, 1), spread$sd, - toptitle = 'RMSE and spread', monini = 11, freq = 12, - listexp = c('CMIP5 IC3'), listvar = c('RMSE', 'spread'), - fileout = 'plot2vars.eps') + toptitle = 'RMSE and spread', monini = 11, freq = 12, + listexp = c('CMIP5 IC3'), listvar = c('RMSE', 'spread'), + fileout = 'plot2vars.eps') + } \author{ History:\cr -1.0 - 2013-03 (I. Andreu-Burillo, \email{isabel.andreu-burillo at ic3.cat}) - Original code +1.0 - 2013-03 (I. Andreu-Burillo, \email{isabel.andreu-burillo@ic3.cat}) + - Original code } \keyword{dynamic} + diff --git a/man/PlotACC.Rd b/man/PlotACC.Rd index dc4b5c87..3427f652 100644 --- a/man/PlotACC.Rd +++ b/man/PlotACC.Rd @@ -1,128 +1,123 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotACC.R \name{PlotACC} \alias{PlotACC} -\title{ -Plot Plumes/Timeseries Of Anomaly Correlation Coefficients -} -\description{ -Plots plumes/timeseries of ACC from an array with dimensions (output from \code{ACC()}): \cr - c(nexp, nobs, nsdates, nltime, 4)\cr -where the fourth dimension is of length 4 and contains the lower limit of the 95\% confidence interval, the ACC, the upper limit of the 95\% confidence interval and the 95\% significance level given by a one-sided T-test. -} +\title{Plot Plumes/Timeseries Of Anomaly Correlation Coefficients} \usage{ -PlotACC(ACC, sdates, toptitle = "", sizetit = 1, ytitle = "", limits = NULL, - legends = NULL, freq = 12, biglab = FALSE, fill = FALSE, - linezero = FALSE, points = TRUE, vlines = NULL, - fileout = "output_PlotACC.eps", - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotACC(ACC, sdates, toptitle = "", sizetit = 1, ytitle = "", + limits = NULL, legends = NULL, freq = 12, biglab = FALSE, + fill = FALSE, linezero = FALSE, points = TRUE, vlines = NULL, + fileout = "output_PlotACC.eps", width = 8, height = 5, + size_units = "in", res = 100, ...) } \arguments{ - \item{ACC}{ -ACC matrix with with dimensions:\cr - c(nexp, nobs, nsdates, nltime, 4)\cr -with the fourth dimension of length 4 containing the lower limit of the 95\% confidence interval, the ACC, the upper limit of the 95\% confidence interval and the 95\% significance level. - } - \item{sdates}{ -List of startdates: c('YYYYMMDD','YYYYMMDD'). - } - \item{toptitle}{ -Main title, optional. - } - \item{sizetit}{ -Multiplicative factor to scale title size, optional. - } - \item{ytitle}{ -Title of Y-axis for each experiment: c('',''), optional. - } - \item{limits}{ -c(lower limit, upper limit): limits of the Y-axis, optional. - } - \item{legends}{ -List of flags (characters) to be written in the legend, optional. - } - \item{freq}{ -1 = yearly, 12 = monthly, 4 = seasonal, ... Default: 12. - } - \item{biglab}{ -TRUE/FALSE for presentation/paper plot, Default = FALSE. - } - \item{fill}{ -TRUE/FALSE if filled confidence interval. Default = FALSE. - } - \item{linezero}{ -TRUE/FALSE if a line at y=0 should be added. Default = FALSE. - } - \item{points}{ -TRUE/FALSE if points instead of lines. Default = TRUE.\cr -Must be TRUE if only 1 leadtime. - } - \item{vlines}{ -List of x location where to add vertical black lines, optional. - } - \item{fileout}{ -Name of output file. Extensions allowed: eps/ps, jpeg, png, pdf, bmp -and tiff. \cr -Default = 'output_PlotACC.eps' - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page plt smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } +\item{ACC}{ACC matrix with with dimensions:\cr +c(nexp, nobs, nsdates, nltime, 4)\cr +with the fourth dimension of length 4 containing the lower limit of the +95\% confidence interval, the ACC, the upper limit of the 95\% confidence +interval and the 95\% significance level.} + +\item{sdates}{List of startdates: c('YYYYMMDD','YYYYMMDD').} + +\item{toptitle}{Main title, optional.} + +\item{sizetit}{Multiplicative factor to scale title size, optional.} + +\item{ytitle}{Title of Y-axis for each experiment: c('',''), optional.} + +\item{limits}{c(lower limit, upper limit): limits of the Y-axis, optional.} + +\item{legends}{List of flags (characters) to be written in the legend, +optional.} + +\item{freq}{1 = yearly, 12 = monthly, 4 = seasonal, ... Default: 12.} + +\item{biglab}{TRUE/FALSE for presentation/paper plot, Default = FALSE.} + +\item{fill}{TRUE/FALSE if filled confidence interval. Default = FALSE.} + +\item{linezero}{TRUE/FALSE if a line at y=0 should be added. Default = FALSE.} + +\item{points}{TRUE/FALSE if points instead of lines. Default = TRUE.\cr +Must be TRUE if only 1 leadtime.} + +\item{vlines}{List of x location where to add vertical black lines, optional.} + +\item{fileout}{Name of output file. Extensions allowed: eps/ps, jpeg, png, +pdf, bmp and tiff. \cr +Default = 'output_PlotACC.eps'} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{\dots}{Arguments to be passed to the method. Only accepts the following +graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg fig fin font font.axis font.lab font.main font.sub +lend lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page +plt smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog\cr +For more information about the parameters see `par`.} +} +\description{ +Plots plumes/timeseries of ACC from an array with dimensions +(output from \code{ACC()}): \cr +c(nexp, nobs, nsdates, nltime, 4)\cr +where the fourth dimension is of length 4 and contains the lower limit of +the 95\% confidence interval, the ACC, the upper limit of the 95\% +confidence interval and the 95\% significance level given by a one-sided +T-test. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) clim <- Clim(sampleData$mod, sampleData$obs) ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) acc <- ACC(Mean1Dim(sampleData$mod, 2), - Mean1Dim(sampleData$obs, 2)) + Mean1Dim(sampleData$obs, 2)) PlotACC(acc$ACC, startDates, toptitle = "Anomaly Correlation Coefficient") + } \author{ History:\cr -0.1 - 2013-08 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{dynamic} + diff --git a/man/PlotAno.Rd b/man/PlotAno.Rd index f36ee3bb..8a42d9fe 100644 --- a/man/PlotAno.Rd +++ b/man/PlotAno.Rd @@ -1,100 +1,90 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotAno.R \name{PlotAno} \alias{PlotAno} -\title{ -Plot Raw Or Smoothed Anomalies -} -\description{ -Plots timeseries of raw or smoothed anomalies of any variable output from \code{Load()} or \code{Ano()} or or \code{Ano_CrossValid()} or \code{Smoothing()}. -} +\title{Plot Raw Or Smoothed Anomalies} \usage{ -PlotAno(exp_ano, obs_ano = NULL, sdates, toptitle = rep("", 15), - ytitle = rep("", 15), limits = NULL, legends = NULL, freq = 12, - biglab = FALSE, fill = TRUE, memb = TRUE, ensmean = TRUE, - linezero = FALSE, points = FALSE, vlines = NULL, sizetit = 1, - fileout = paste0("output", 1:5, "_plotano.eps"), - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotAno(exp_ano, obs_ano = NULL, sdates, toptitle = rep("", 15), + ytitle = rep("", 15), limits = NULL, legends = NULL, freq = 12, + biglab = FALSE, fill = TRUE, memb = TRUE, ensmean = TRUE, + linezero = FALSE, points = FALSE, vlines = NULL, sizetit = 1, + fileout = paste0("output", 1:5, "_plotano.eps"), width = 8, height = 5, + size_units = "in", res = 100, ...) } \arguments{ - \item{exp_ano}{ -Array containing the experimental data:\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime). - } - \item{obs_ano}{ -Optional matrix containing the observational data:\cr - c(nobs, nmemb, nsdates, nltime) - } - \item{sdates}{ -List of starting dates: c('YYYYMMDD','YYYYMMDD'). - } - \item{toptitle}{ -Main title for each experiment: c('',''), optional. - } - \item{ytitle}{ -Title of Y-axis for each experiment: c('',''), optional. - } - \item{limits}{ -c(lower limit, upper limit): limits of the Y-axis, optional. - } - \item{legends}{ -List of observational dataset names, optional. - } - \item{freq}{ -1 = yearly, 12 = monthly, 4 = seasonal, ... Default: 12. - } - \item{biglab}{ -TRUE/FALSE for presentation/paper plot. Default = FALSE. - } - \item{fill}{ -TRUE/FALSE if the spread between members should be filled. Default = TRUE. - } - \item{memb}{ -TRUE/FALSE if all members/only the ensemble-mean should be plotted.\cr -Default = TRUE. - } - \item{ensmean}{ -TRUE/FALSE if the ensemble-mean should be plotted. Default = TRUE. - } - \item{linezero}{ -TRUE/FALSE if a line at y=0 should be added. Default = FALSE. - } - \item{points}{ -TRUE/FALSE if points instead of lines should be shown. Default = FALSE. - } - \item{vlines}{ -List of x location where to add vertical black lines, optional. - } - \item{sizetit}{ -Multiplicative factor to scale title size, optional. - } - \item{fileout}{ -Name of the output file for each experiment: c('',''). -Extensions allowed: eps/ps, jpeg, png, pdf, bmp and tiff. If filenames with -different extensions are passed, it will be considered only the first one -and it will be extended to the rest. \cr +\item{exp_ano}{Array containing the experimental data:\cr +c(nmod/nexp, nmemb/nparam, nsdates, nltime).} + +\item{obs_ano}{Optional matrix containing the observational data:\cr +c(nobs, nmemb, nsdates, nltime)} + +\item{sdates}{List of starting dates: c('YYYYMMDD','YYYYMMDD').} + +\item{toptitle}{Main title for each experiment: c('',''), optional.} + +\item{ytitle}{Title of Y-axis for each experiment: c('',''), optional.} + +\item{limits}{c(lower limit, upper limit): limits of the Y-axis, optional.} + +\item{legends}{List of observational dataset names, optional.} + +\item{freq}{1 = yearly, 12 = monthly, 4 = seasonal, ... Default: 12.} + +\item{biglab}{TRUE/FALSE for presentation/paper plot. Default = FALSE.} + +\item{fill}{TRUE/FALSE if the spread between members should be filled. +Default = TRUE.} + +\item{memb}{TRUE/FALSE if all members/only the ensemble-mean should be +plotted.\cr +Default = TRUE.} + +\item{ensmean}{TRUE/FALSE if the ensemble-mean should be plotted. +Default = TRUE.} + +\item{linezero}{TRUE/FALSE if a line at y=0 should be added. +Default = FALSE.} + +\item{points}{TRUE/FALSE if points instead of lines should be shown. +Default = FALSE.} + +\item{vlines}{List of x location where to add vertical black lines, optional.} + +\item{sizetit}{Multiplicative factor to scale title size, optional.} + +\item{fileout}{Name of the output file for each experiment: c('',''). +Extensions allowed: eps/ps, jpeg, png, pdf, bmp and tiff. If filenames +with different extensions are passed, it will be considered only the first +one and it will be extended to the rest. \cr Default = c('output1_plotano.eps', 'output2_plotano.eps', 'output3_plotano.eps', 'output4_plotano.eps', - 'output5_plotano.eps') - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page plt smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } + 'output5_plotano.eps')} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{\dots}{Arguments to be passed to the method. Only accepts the following +graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page plt smo +srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} +} +\description{ +Plots timeseries of raw or smoothed anomalies of any variable output from +\code{Load()} or \code{Ano()} or or \code{Ano_CrossValid()} or +\code{Smoothing()}. } \examples{ # Load sample data as in Load() example: @@ -107,12 +97,14 @@ dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, - toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), - legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') + toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), + legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') + } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{dynamic} + diff --git a/man/PlotBoxWhisker.Rd b/man/PlotBoxWhisker.Rd index 31d11d9e..31b7d4d4 100644 --- a/man/PlotBoxWhisker.Rd +++ b/man/PlotBoxWhisker.Rd @@ -1,115 +1,103 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotBoxWhisker.R \name{PlotBoxWhisker} \alias{PlotBoxWhisker} -\title{ -Box-And-Whisker Plot of Time Series with Ensemble Distribution -} -\description{ -Produce time series of box-and-whisker plot showing the distribution of the -members of a forecast vs. the observed evolution. The correlation between -forecast and observational data is calculated and displayed. Only works for -n-monthly to n-yearly time series. -} +\title{Box-And-Whisker Plot of Time Series with Ensemble Distribution} \usage{ -PlotBoxWhisker(exp, obs, toptitle = '', ytitle = '', monini = 1, yearini = 0, - freq = 1, expname = "exp 1", obsname = "obs 1", drawleg = TRUE, - fileout = "output_PlotBoxWhisker.ps", - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotBoxWhisker(exp, obs, toptitle = "", ytitle = "", monini = 1, + yearini = 0, freq = 1, expname = "exp 1", obsname = "obs 1", + drawleg = TRUE, fileout = "output_PlotBoxWhisker.ps", width = 8, + height = 5, size_units = "in", res = 100, ...) } \arguments{ - \item{exp}{ -Forecast array of multi-member time series, e.g., the NAO index of one -experiment. The expected dimensions are c(members, -start dates/forecast horizons). A vector with only the time dimension can -also be provided. Only monthly or lower frequency time series are supported. -See parameter freq. - } - \item{obs}{ -Observational vector or array of time series, e.g., the NAO index of the -observations that correspond the forecast data in \code{exp}. +\item{exp}{Forecast array of multi-member time series, e.g., the NAO index +of one experiment. The expected dimensions are +c(members, start dates/forecast horizons). A vector with only the time +dimension can also be provided. Only monthly or lower frequency time +series are supported. See parameter freq.} + +\item{obs}{Observational vector or array of time series, e.g., the NAO index +of the observations that correspond the forecast data in \code{exp}. The expected dimensions are c(start dates/forecast horizons) or c(1, start dates/forecast horizons). Only monthly or lower frequency time -series are supported. See parameter freq. - } - \item{toptitle}{ -Character string to be drawn as figure title. - } - \item{ytitle}{ -Character string to be drawn as y-axis title. - } - \item{monini}{ -Number of the month of the first time step, from 1 to 12. - } - \item{yearini}{ -Year of the first time step. - } - \item{freq}{ -Frequency of the provided time series: 1 = yearly, 12 = monthly, -4 = seasonal, ... Default = 12. - } - \item{expname}{ -Experimental dataset name. - } - \item{obsname}{ -Name of the observational reference dataset. - } - \item{drawleg}{ -TRUE/FALSE: whether to draw the legend or not. - } - \item{fileout}{ -Name of output file. Extensions allowed: eps/ps, jpeg, png, pdf, bmp -and tiff. \cr -Default = 'output_PlotBox.ps' - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - ann ask bg cex.lab cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mex mfcol mfrow mfg mkh oma omd omi page pin plt pty smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } +series are supported. See parameter freq.} + +\item{toptitle}{Character string to be drawn as figure title.} + +\item{ytitle}{Character string to be drawn as y-axis title.} + +\item{monini}{Number of the month of the first time step, from 1 to 12.} + +\item{yearini}{Year of the first time step.} + +\item{freq}{Frequency of the provided time series: 1 = yearly, 12 = monthly,} + +\item{expname}{Experimental dataset name.} + +\item{obsname}{Name of the observational reference dataset.} + +\item{drawleg}{TRUE/FALSE: whether to draw the legend or not.} + +\item{fileout}{Name of output file. Extensions allowed: eps/ps, jpeg, png, +pdf, bmp and tiff. \cr +Default = 'output_PlotBox.ps'.} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{...}{Arguments to be passed to the method. Only accepts the following +graphical parameters:\cr +ann ask bg cex.lab cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +lheight ljoin lmitre mex mfcol mfrow mfg mkh oma omd omi page pin plt pty +smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} } \value{ Generates a file at the path specified via \code{fileout}. } +\description{ +Produce time series of box-and-whisker plot showing the distribution of the +members of a forecast vs. the observed evolution. The correlation between +forecast and observational data is calculated and displayed. Only works for +n-monthly to n-yearly time series. +} \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 20, latmax = 80, - lonmin = -80, lonmax = 40) + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 20, latmax = 80, + lonmin = -80, lonmax = 40) # No example data is available over NAO region, so in this example we will # tweak the available data. In a real use case, one can Load() the data over # NAO region directly. @@ -120,23 +108,25 @@ attr(sampleData$lon, 'data_across_gw') <- TRUE sampleData$lat[] <- c(20, 80) attr(sampleData$lat, 'first_lat') <- 20 attr(sampleData$lat, 'last_lat') <- 80 - } + } # Now ready to compute the EOFs and project on, for example, the first # variability mode. ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) # Finally plot the nao index PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", - monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") + monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") + } \author{ History:\cr -0.1 - 2013-09 (F. Lienert, \email{flienert at ic3.cat}) - Original code\cr -0.2 - 2015-03 (L. Batte, \email{lauriane.batte at ic3.cat}) - Removed all\cr -normalization for sake of clarity. -1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN +0.1 - 2013-09 (F. Lienert, \email{flienert@ic3.cat}) - Original code\cr +0.2 - 2015-03 (L. Batte, \email{lauriane.batte@ic3.cat}) - Removed all\cr + normalization for sake of clarity. +1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN } \seealso{ EOF, ProjectField, NAO } \keyword{datagen} + diff --git a/man/PlotClim.Rd b/man/PlotClim.Rd index 68403866..38c916cb 100644 --- a/man/PlotClim.Rd +++ b/man/PlotClim.Rd @@ -1,96 +1,88 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotClim.R \name{PlotClim} \alias{PlotClim} -\title{ -Plots Climatologies -} -\description{ -Plots climatologies as a function of the forecast time for any index output from \code{Clim()} and organized in matrix with dimensions:\cr - c(nmod/nexp, nmemb/nparam, nltime) or c(nmod/nexp, nltime) for the experiment data\cr - c(nobs, nmemb, nltime) or c(nobs, nltime) for the observational data -} +\title{Plots Climatologies} \usage{ -PlotClim(exp_clim, obs_clim = NULL, toptitle = "", ytitle = "", monini = 1, - freq = 12, limits = NULL, listexp = c("exp1", "exp2", "exp3"), - listobs = c("obs1", "obs2", "obs3"), biglab = FALSE, leg = TRUE, - sizetit = 1, fileout = "output_plotclim.eps", - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotClim(exp_clim, obs_clim = NULL, toptitle = "", ytitle = "", + monini = 1, freq = 12, limits = NULL, listexp = c("exp1", "exp2", + "exp3"), listobs = c("obs1", "obs2", "obs3"), biglab = FALSE, + leg = TRUE, sizetit = 1, fileout = "output_plotclim.eps", width = 8, + height = 5, size_units = "in", res = 100, ...) } \arguments{ - \item{exp_clim}{ -Matrix containing the experimental data with dimensions:\cr - c(nmod/nexp, nmemb/nparam, nltime) or c(nmod/nexp, nltime) - } - \item{obs_clim}{ -Matrix containing the observational data (optional) with dimensions:\cr - c(nobs, nmemb, nltime) or c(nobs, nltime) - } - \item{toptitle}{ -Main title, optional - } - \item{ytitle}{ -Title of Y-axis, optional. - } - \item{monini}{ -Starting month between 1 and 12. Default = 1. - } - \item{freq}{ -1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12. - } - \item{limits}{ -c(lower limit, upper limit): limits of the Y-axis, optional. - } - \item{listexp}{ -List of experiment names, optional. - } - \item{listobs}{ -List of observational dataset names, optional. - } - \item{biglab}{ -TRUE/FALSE for presentation/paper plot. Default = FALSE. - } - \item{leg}{ -TRUE/FALSE to plot the legend or not. - } - \item{sizetit}{ -Multiplicative factor to scale title size, optional. - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{fileout}{ -Name of output file. Extensions allowed: eps/ps, jpeg, png, pdf, bmp -and tiff. \cr -Default = 'output_plotclim.eps' - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt smo srt tck usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } +\item{exp_clim}{Matrix containing the experimental data with dimensions:\cr +c(nmod/nexp, nmemb/nparam, nltime) or c(nmod/nexp, nltime)} + +\item{obs_clim}{Matrix containing the observational data (optional) with +dimensions:\cr +c(nobs, nmemb, nltime) or c(nobs, nltime)} + +\item{toptitle}{Main title, optional.} + +\item{ytitle}{Title of Y-axis, optional.} + +\item{monini}{Starting month between 1 and 12. Default = 1.} + +\item{freq}{1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12.} + +\item{limits}{c(lower limit, upper limit): limits of the Y-axis, optional.} + +\item{listexp}{List of experiment names, optional.} + +\item{listobs}{List of observational dataset names, optional.} + +\item{biglab}{TRUE/FALSE for presentation/paper plot. Default = FALSE.} + +\item{leg}{TRUE/FALSE to plot the legend or not.} + +\item{sizetit}{Multiplicative factor to scale title size, optional.} + +\item{fileout}{Name of output file. Extensions allowed: eps/ps, jpeg, png, +pdf, bmp and tiff. \cr +Default = 'output_plotclim.eps'.} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{...}{Arguments to be passed to the method. Only accepts the following +graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt +smo srt tck usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} +} +\description{ +Plots climatologies as a function of the forecast time for any index output +from \code{Clim()} and organized in matrix with dimensions:\cr +c(nmod/nexp, nmemb/nparam, nltime) or c(nmod/nexp, nltime) for the +experiment data\cr +c(nobs, nmemb, nltime) or c(nobs, nltime) for the observational data } \examples{ # Load sample data as in Load() example: example(Load) clim <- Clim(sampleData$mod, sampleData$obs) PlotClim(clim$clim_exp, clim$clim_obs, toptitle = paste('climatologies'), - ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') + ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') + } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/PlotEquiMap.Rd b/man/PlotEquiMap.Rd index 85d92746..14f1d690 100644 --- a/man/PlotEquiMap.Rd +++ b/man/PlotEquiMap.Rd @@ -1,248 +1,295 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotEquiMap.R \name{PlotEquiMap} \alias{PlotEquiMap} -\title{ -Maps A Two-Dimensional Variable On A Cylindrical Equidistant Projection -} -\description{ -Map longitude-latitude array (on a regular rectangular or gaussian grid) on a cylindrical equidistant latitude and longitude projection with coloured grid cells. Only the region for which data has been provided is displayed. A colour bar (legend) can be plotted and adjusted. It is possible to draw superimposed arrows, dots, symbols, contour lines and boxes. A number of options is provided to adjust the position, size and colour of the components. This plot function is compatible with figure layouts if colour bar is disabled. -} +\title{Maps A Two-Dimensional Variable On A Cylindrical Equidistant Projection} \usage{ -PlotEquiMap(var, lon, lat, varu = NULL, varv = NULL, - toptitle = NULL, sizetit = NULL, units = NULL, - brks = NULL, cols = NULL, bar_limits = NULL, - triangle_ends = NULL, col_inf = NULL, col_sup = NULL, - colNA = NULL, color_fun = clim.palette(), - square = TRUE, filled.continents = NULL, - coast_color = NULL, coast_width = 1, - contours = NULL, brks2 = NULL, contour_lwd = 0.5, - contour_color = 'black', contour_lty = 1, - contour_label_scale = 1, - dots = NULL, dot_symbol = 4, dot_size = 1, - arr_subsamp = floor(length(lon) / 30), arr_scale = 1, - arr_ref_len = 15, arr_units = "m/s", - arr_scale_shaft = 1, arr_scale_shaft_angle = 1, - axelab = TRUE, labW = FALSE, - intylat = 20, intxlon = 20, - axes_tick_scale = 1, axes_label_scale = 1, - drawleg = TRUE, subsampleg = NULL, - bar_extra_labels = NULL, draw_bar_ticks = TRUE, - draw_separators = FALSE, triangle_ends_scale = 1, - bar_label_digits = 4, bar_label_scale = 1, - units_scale = 1, bar_tick_scale = 1, - bar_extra_margin = rep(0, 4), - boxlim = NULL, boxcol = 'purple2', boxlwd = 5, - margin_scale = rep(1, 4), title_scale = 1, - numbfig = NULL, fileout = NULL, - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotEquiMap(var, lon, lat, varu = NULL, varv = NULL, toptitle = NULL, + sizetit = NULL, units = NULL, brks = NULL, cols = NULL, + bar_limits = NULL, triangle_ends = NULL, col_inf = NULL, + col_sup = NULL, colNA = NULL, color_fun = clim.palette(), + square = TRUE, filled.continents = NULL, coast_color = NULL, + coast_width = 1, contours = NULL, brks2 = NULL, contour_lwd = 0.5, + contour_color = "black", contour_lty = 1, contour_label_scale = 1, + dots = NULL, dot_symbol = 4, dot_size = 1, + arr_subsamp = floor(length(lon)/30), arr_scale = 1, arr_ref_len = 15, + arr_units = "m/s", arr_scale_shaft = 1, arr_scale_shaft_angle = 1, + axelab = TRUE, labW = FALSE, intylat = 20, intxlon = 20, + axes_tick_scale = 1, axes_label_scale = 1, drawleg = TRUE, + subsampleg = NULL, bar_extra_labels = NULL, draw_bar_ticks = TRUE, + draw_separators = FALSE, triangle_ends_scale = 1, bar_label_digits = 4, + bar_label_scale = 1, units_scale = 1, bar_tick_scale = 1, + bar_extra_margin = rep(0, 4), boxlim = NULL, boxcol = "purple2", + boxlwd = 5, margin_scale = rep(1, 4), title_scale = 1, numbfig = NULL, + fileout = NULL, width = 8, height = 5, size_units = "in", res = 100, + ...) } \arguments{ - \item{var}{ -Array with the values at each cell of a grid on a regular rectangular or gaussian grid. The array is expected to have two dimensions: c(latitude, longitude). Longitudes can be in ascending or descending order and latitudes in any order. It can contain NA values (coloured with 'colNA'). Arrays with dimensions c(longitude, latitude) will also be accepted but 'lon' and 'lat' will be used to disambiguate so this alternative is not appropriate for square arrays. - } - \item{lon}{ -Numeric vector of longitude locations of the cell centers of the grid of 'var', in ascending or descending order (same as 'var'). Expected to be regularly spaced, within either of the ranges [-180, 180] or [0, 360]. Data for two adjacent regions split by the limits of the longitude range can also be provided, e.g. \code{lon = c(0:50, 300:360)} ('var' must be provided consitently). - } - \item{lat}{ -Numeric vector of latitude locations of the cell centers of the grid of 'var', in any order (same as 'var'). Expected to be from a regular rectangular or gaussian grid, within the range [-90, 90]. - } - \item{varu}{ -Array of the zonal component of wind/current/other field with the same dimensions as 'var'. - } - \item{varv}{ -Array of the meridional component of wind/current/other field with the same dimensions as 'var'. - } - \item{toptitle}{ -Top title of the figure, scalable with parameter 'title_scale'. - } - \item{sizetit}{ -Scale factor for the figure top title provided in parameter 'toptitle'. Deprecated. Use 'title_scale' instead. - } - \item{units}{ -Title at the top of the colour bar, most commonly the units of the variable provided in parameter 'var'. - } - \item{brks,cols,bar_limits,triangle_ends}{ -Usually only providing 'brks' is enough to generate the desired colour bar. These parameters allow to define n breaks that define n - 1 intervals to classify each of the values in 'var'. The corresponding grid cell of a given value in 'var' will be coloured in function of the interval it belongs to. These parameters are sent to \code{ColorBar()} to generate the breaks and colours. Additional colours for values beyond the limits of the colour bar are also generated and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are properly provided to do so. See ?ColorBar for a full explanation.\cr - } - \item{col_inf,col_sup,colNA}{ -Colour identifiers to colour the values in 'var' that go beyond the extremes of the colour bar and to colour NA values, respectively. 'colNA' takes attr(cols, 'na_color') if available by default, where cols is the parameter 'cols' if provided or the vector of colors returned by 'color_fun'. If not available, it takes 'pink' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. - } - \item{color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin}{ -Set of parameters to control the visual aspect of the drawn colour bar. See ?ColorBar for a full explanation. - } - \item{square}{ -Logical value to choose either to draw a coloured square for each grid cell in 'var' (TRUE; default) or to draw contour lines and fill the spaces in between with colours (FALSE). In the latter case, 'filled.continents' will take the value FALSE if not specified. - } - \item{filled.continents}{ -Colour to fill in drawn projected continents. Takes the value gray(0.5) by default or, if 'square = FALSE', takes the value FALSE. If set to FALSE, continents are not filled in. - } - \item{coast_color}{ -Colour of the coast line of the drawn projected continents. Takes the value gray(0.5) by default. - } - \item{coast_width}{ -Line width of the coast line of the drawn projected continents. Takes the value 1 by default. - } - \item{contours}{ -Array of same dimensions as 'var' to be added to the plot and displayed with contours. Parameter 'brks2' is required to define the magnitude breaks for each contour curve. Disregarded if 'square = FALSE'. - } - \item{brks2}{ -Vector of magnitude breaks where to draw contour curves for the array provided in 'contours' or if 'square = FALSE'. - } - \item{contour_lwd}{ -Line width of the contour curves provided via 'contours' and 'brks2', or if 'square = FALSE'. - } - \item{contour_color}{ -Line color of the contour curves provided via 'contours' and 'brks2', or if 'square = FALSE'. - } - \item{contour_lty}{ -Line type of the contour curves. Takes 1 (solid) by default. See help on 'lty' in par() for other accepted values. - } - \item{contour_label_scale}{ -Scale factor for the superimposed labels when drawing contour levels. - } - \item{dots}{ -Array of same dimensions as 'var' or with dimensions c(n, dim(var)), where n is the number of dot/symbol layers to add to the plot. A value of TRUE at a grid cell will draw a dot/symbol on the corresponding square of the plot. By default all layers provided in 'dots' are plotted with dots, but a symbol can be specified for each of the layers via the parameter 'dot_symbol'. - } - \item{dot_symbol}{ -Single character/number or vector of characters/numbers that correspond to each of the symbol layers specified in parameter 'dots'. If a single value is specified, it will be applied to all the layers in 'dots'. Takes 15 (centered square) by default. See 'pch' in par() for additional accepted options. - } - \item{dot_size}{ -Scale factor for the dots/symbols to be plotted, specified in 'dots'. If a single value is specified, it will be applied to all layers in 'dots'. Takes 1 by default. - } - \item{arr_subsamp}{ -Subsampling factor to select a subset of arrows in 'varu' and 'varv' to be drawn. Only one out of arr_subsamp arrows will be drawn. Takes 1 by default. - } - \item{arr_scale}{ -Scale factor for drawn arrows from 'varu' and 'varv'. Takes 1 by default. - } - \item{arr_ref_len}{ -Length of the refence arrow to be drawn as legend at the bottom of the figure (in same units as 'varu' and 'varv', only affects the -legend for the wind or variable in these arrays). Defaults to 15. - } - \item{arr_units}{ -Units of 'varu' and 'varv', to be drawn in the legend. Takes 'm/s' by default. - } - \item{arr_scale_shaft}{ -Parameter for the scale of the shaft of the arrows (which also depend on the -number of figures and the arr_scale parameter). Defaults to 1. - } - \item{arr_scale_shaft_angle}{ -Parameter for the scale of the angle of the shaft of the arrows (which also -depend on the number of figure and the arr_scale parameter). Defaults to 1. - } - \item{axelab}{ -Whether to draw longitude and latitude axes or not. TRUE by default. - } - \item{labW}{ -Whether to label the longitude axis with a 'W' instead of minus for negative values. Defaults to FALSE. - } - \item{intylat}{ -Interval between latitude ticks on y-axis, in degrees. Defaults to 20. - } - \item{intxlon}{ -Interval between latitude ticks on x-axis, in degrees. Defaults to 20. - } - \item{axes_tick_scale}{ -Scale factor for the tick lines along the longitude and latitude axes. - } - \item{axes_label_scale}{ -Scale factor for the labels along the longitude and latitude axes. - } - \item{drawleg}{ -Whether to plot a color bar (legend, key) or not. Defaults to TRUE. It is not possible to plot the colour bar if 'add = TRUE'. Use ColorBar() and the return values of PlotEquiMap() instead. - } - \item{boxlim}{ -Limits of a box to be added to the plot, in degrees: c(x1, y1, x2, y2). A list with multiple box specifications can also be provided. - } - \item{boxcol}{ -Colour of the box lines. A vector with a colour for each of the boxes is also accepted. Defaults to 'purple2'. - } - \item{boxlwd}{ -Line width of the box lines. A vector with a line width for each of the boxes is also accepted. Defaults to 5. - } - \item{margin_scale}{ -Scale factor for the margins around the map plot, with the format c(y1, x1, y2, x2). Defaults to rep(1, 4). If drawleg = TRUE, then margin_scale[1] is subtracted 1 unit. - } - \item{title_scale}{ -Scale factor for the figure top title. Defaults to 1. - } - \item{numbfig}{ -Number of figures in the layout the plot will be put into. A higher numbfig will result in narrower margins and smaller labels, axe labels, ticks, thinner lines, ... Defaults to 1. - } - \item{fileout}{ -File where to save the plot. If not specified (default) a graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, bmp and tiff. \cr - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{\dots}{ -Arguments to be passed to the method. Only accepts the following graphical parameters: - -adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mex mfcol mfrow mfg mkh omd omi page pch pin plt pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - -For more information about the parameters see `par`. - } +\item{var}{Array with the values at each cell of a grid on a regular +rectangular or gaussian grid. The array is expected to have two +dimensions: c(latitude, longitude). Longitudes can be in ascending or +descending order and latitudes in any order. It can contain NA values +(coloured with 'colNA'). Arrays with dimensions c(longitude, latitude) +will also be accepted but 'lon' and 'lat' will be used to disambiguate so +this alternative is not appropriate for square arrays.} + +\item{lon}{Numeric vector of longitude locations of the cell centers of the +grid of 'var', in ascending or descending order (same as 'var'). Expected +to be regularly spaced, within either of the ranges [-180, 180] or +[0, 360]. Data for two adjacent regions split by the limits of the +longitude range can also be provided, e.g. \code{lon = c(0:50, 300:360)} +('var' must be provided consitently).} + +\item{lat}{Numeric vector of latitude locations of the cell centers of the +grid of 'var', in any order (same as 'var'). Expected to be from a regular +rectangular or gaussian grid, within the range [-90, 90].} + +\item{varu}{Array of the zonal component of wind/current/other field with +the same dimensions as 'var'.} + +\item{varv}{Array of the meridional component of wind/current/other field +with the same dimensions as 'var'.} + +\item{toptitle}{Top title of the figure, scalable with parameter +'title_scale'.} + +\item{sizetit}{Scale factor for the figure top title provided in parameter +'toptitle'. Deprecated. Use 'title_scale' instead.} + +\item{units}{Title at the top of the colour bar, most commonly the units of +the variable provided in parameter 'var'.} + +\item{brks, cols, bar_limits, triangle_ends}{Usually only providing 'brks' is +enough to generate the desired colour bar. These parameters allow to +define n breaks that define n - 1 intervals to classify each of the values +in 'var'. The corresponding grid cell of a given value in 'var' will be +coloured in function of the interval it belongs to. These parameters are +sent to \code{ColorBar()} to generate the breaks and colours. Additional +colours for values beyond the limits of the colour bar are also generated +and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are +properly provided to do so. See ?ColorBar for a full explanation.} + +\item{col_inf, col_sup, colNA}{Colour identifiers to colour the values in +'var' that go beyond the extremes of the colour bar and to colour NA +values, respectively. 'colNA' takes attr(cols, 'na_color') if available by +default, where cols is the parameter 'cols' if provided or the vector of +colors returned by 'color_fun'. If not available, it takes 'pink' by +default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not +specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'.} + +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, }{triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, +bar_tick_scale,bar_extra_margin Set of parameters to control the visual + aspect of the drawn colour bar. See ?ColorBar for a full explanation.} + +\item{square}{Logical value to choose either to draw a coloured square for +each grid cell in 'var' (TRUE; default) or to draw contour lines and fill +the spaces in between with colours (FALSE). In the latter case, +'filled.continents' will take the value FALSE if not specified.} + +\item{filled.continents}{Colour to fill in drawn projected continents. +Takes the value gray(0.5) by default or, if 'square = FALSE', takes the +value FALSE. If set to FALSE, continents are not filled in.} + +\item{coast_color}{Colour of the coast line of the drawn projected continents. +Takes the value gray(0.5) by default.} + +\item{coast_width}{Line width of the coast line of the drawn projected +continents. Takes the value 1 by default.} + +\item{contours}{Array of same dimensions as 'var' to be added to the plot +and displayed with contours. Parameter 'brks2' is required to define the +magnitude breaks for each contour curve. Disregarded if 'square = FALSE'.} + +\item{brks2}{Vector of magnitude breaks where to draw contour curves for the +array provided in 'contours' or if 'square = FALSE'.} + +\item{contour_lwd}{Line width of the contour curves provided via 'contours' +and 'brks2', or if 'square = FALSE'.} + +\item{contour_color}{Line color of the contour curves provided via 'contours' +and 'brks2', or if 'square = FALSE'.} + +\item{contour_lty}{Line type of the contour curves. Takes 1 (solid) by +default. See help on 'lty' in par() for other accepted values.} + +\item{contour_label_scale}{Scale factor for the superimposed labels when +drawing contour levels.} + +\item{dots}{Array of same dimensions as 'var' or with dimensions +c(n, dim(var)), where n is the number of dot/symbol layers to add to the +plot. A value of TRUE at a grid cell will draw a dot/symbol on the +corresponding square of the plot. By default all layers provided in 'dots' +are plotted with dots, but a symbol can be specified for each of the +layers via the parameter 'dot_symbol'.} + +\item{dot_symbol}{Single character/number or vector of characters/numbers +that correspond to each of the symbol layers specified in parameter 'dots'. +If a single value is specified, it will be applied to all the layers in +'dots'. Takes 15 (centered square) by default. See 'pch' in par() for +additional accepted options.} + +\item{dot_size}{Scale factor for the dots/symbols to be plotted, specified +in 'dots'. If a single value is specified, it will be applied to all +layers in 'dots'. Takes 1 by default.} + +\item{arr_subsamp}{Subsampling factor to select a subset of arrows in +'varu' and 'varv' to be drawn. Only one out of arr_subsamp arrows will +be drawn. Takes 1 by default.} + +\item{arr_scale}{Scale factor for drawn arrows from 'varu' and 'varv'. +Takes 1 by default.} + +\item{arr_ref_len}{Length of the refence arrow to be drawn as legend at the +bottom of the figure (in same units as 'varu' and 'varv', only affects the +legend for the wind or variable in these arrays). Defaults to 15.} + +\item{arr_units}{Units of 'varu' and 'varv', to be drawn in the legend. +Takes 'm/s' by default.} + +\item{arr_scale_shaft}{Parameter for the scale of the shaft of the arrows +(which also depend on the number of figures and the arr_scale parameter). +Defaults to 1.} + +\item{arr_scale_shaft_angle}{Parameter for the scale of the angle of the +shaft of the arrows (which also depend on the number of figure and the +arr_scale parameter). Defaults to 1.} + +\item{axelab}{Whether to draw longitude and latitude axes or not. +TRUE by default.} + +\item{labW}{Whether to label the longitude axis with a 'W' instead of minus +for negative values. Defaults to FALSE.} + +\item{intylat}{Interval between latitude ticks on y-axis, in degrees. +Defaults to 20.} + +\item{intxlon}{Interval between latitude ticks on x-axis, in degrees. +Defaults to 20.} + +\item{axes_tick_scale}{Scale factor for the tick lines along the longitude +and latitude axes.} + +\item{axes_label_scale}{Scale factor for the labels along the longitude +and latitude axes.} + +\item{drawleg}{Whether to plot a color bar (legend, key) or not. Defaults to +TRUE. It is not possible to plot the colour bar if 'add = TRUE'. Use +ColorBar() and the return values of PlotEquiMap() instead.} + +\item{boxlim}{Limits of a box to be added to the plot, in degrees: +c(x1, y1, x2, y2). A list with multiple box specifications can also be +provided.} + +\item{boxcol}{Colour of the box lines. A vector with a colour for each of +the boxes is also accepted. Defaults to 'purple2'.} + +\item{boxlwd}{Line width of the box lines. A vector with a line width for +each of the boxes is also accepted. Defaults to 5.} + +\item{margin_scale}{Scale factor for the margins around the map plot, with +the format c(y1, x1, y2, x2). Defaults to rep(1, 4). If drawleg = TRUE, +then margin_scale[1] is subtracted 1 unit.} + +\item{title_scale}{Scale factor for the figure top title. Defaults to 1.} + +\item{numbfig}{Number of figures in the layout the plot will be put into. +A higher numbfig will result in narrower margins and smaller labels, +axe labels, ticks, thinner lines, ... Defaults to 1.} + +\item{fileout}{File where to save the plot. If not specified (default) a +graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, +bmp and tiff.} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of +the corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{\dots}{Arguments to be passed to the method. Only accepts the following +graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg font font.axis font.lab font.main font.sub lend +lheight ljoin lmitre mex mfcol mfrow mfg mkh omd omi page pch pin plt +pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} } \value{ - \item{brks}{ -Breaks used for colouring the map (and legend if drawleg = TRUE). - } - \item{cols}{ -Colours used for colouring the map (and legend if drawleg = TRUE). Always of length length(brks) - 1. - } - \item{col_inf}{ -Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). - } - \item{col_sup}{ -Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). - } +\itemize{ + \item{brks}{ + Breaks used for colouring the map (and legend if drawleg = TRUE). + } + \item{cols}{ + Colours used for colouring the map (and legend if drawleg = TRUE). Always + of length length(brks) - 1. + } + \item{col_inf}{ + Colour used to draw the lower triangle end in the colour bar (NULL if not + drawn at all). + } + \item{col_sup}{ + Colour used to draw the upper triangle end in the colour bar (NULL if not + drawn at all). + } +} +} +\description{ +Map longitude-latitude array (on a regular rectangular or gaussian grid) +on a cylindrical equidistant latitude and longitude projection with coloured +grid cells. Only the region for which data has been provided is displayed. +A colour bar (legend) can be plotted and adjusted. It is possible to draw +superimposed arrows, dots, symbols, contour lines and boxes. A number of +options is provided to adjust the position, size and colour of the +components. This plot function is compatible with figure layouts if colour +bar is disabled. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } PlotEquiMap(sampleData$mod[1, 1, 1, 1, , ], sampleData$lon, sampleData$lat, - toptitle = 'Predicted sea surface temperature for Nov 1960 from 1st Nov', - sizetit = 0.5) + toptitle = 'Predicted sea surface temperature for Nov 1960 from 1st Nov', + sizetit = 0.5) + } \author{ - History: - 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code - 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@ic3.cat}) - LabW - 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN - 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@ic3.cat}) - add winds - 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Refactored and added features, +History:\cr + 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code + 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@ic3.cat}) - LabW + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN + 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@ic3.cat}) - add winds + 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Refactored and added features, and adapted to new ColorBar. } \keyword{dynamic} + diff --git a/man/PlotLayout.Rd b/man/PlotLayout.Rd index 34331a37..75f24e2c 100644 --- a/man/PlotLayout.Rd +++ b/man/PlotLayout.Rd @@ -1,180 +1,256 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotLayout.R \name{PlotLayout} \alias{PlotLayout} -\title{ -Arrange and Fill Multi-Pannel Layouts With Optional Colour Bar -} -\description{ -This function takes an array or list of arrays and loops over each of them to plot all the sub-arrays they contain on an automatically generated multi-pannel layout. A different plot function (not necessarily from s2dverification) can be applied over each of the provided arrays. The input dimensions of each of the functions have to be specified, either with the names or the indices of the corresponding input dimensions. It is possible to draw a common colour bar at any of the sides of the multi-pannel for all the s2dverification plots that use a colour bar. Common plotting arguments for all the arrays in 'var' can be specified via the '...' parameter, and specific plotting arguments for each array can be fully adjusted via 'special_args'. It is possible to draw titles for each of the figures, layout rows, layout columns and for the whole figure. A number of parameters is provided in order to adjust the position, size and colour of the components. Blank cells can be forced to appear and later be filled in manually with customized plots. -This function pops up a blank new device and fills it in, so it cannot be nested in complex layouts. -} +\title{Arrange and Fill Multi-Pannel Layouts With Optional Colour Bar} \usage{ -PlotLayout(fun, plot_dims, var, ..., special_args = NULL, - nrow = NULL, ncol = NULL, toptitle = NULL, - row_titles = NULL, col_titles = NULL, bar_scale = 1, - title_scale = 1, title_margin_scale = 1, - title_left_shift_scale = 1, - subtitle_scale = 1, subtitle_margin_scale = 1, - brks = NULL, cols = NULL, drawleg = 'S', titles = NULL, - subsampleg = NULL, bar_limits = NULL, - triangle_ends = NULL, col_inf = NULL, col_sup = NULL, - color_fun = clim.colors, - draw_bar_ticks = TRUE, draw_separators = FALSE, - triangle_ends_scale = 1, bar_extra_labels = NULL, - units = NULL, units_scale = 1, bar_label_scale = 1, - bar_tick_scale = 1, bar_extra_margin = rep(0, 4), - bar_left_shift_scale = 1, bar_label_digits = 4, - extra_margin = rep(0, 4), - fileout = NULL, width = NULL, height = NULL, - size_units = 'in', res = 100, close_device = TRUE) +PlotLayout(fun, plot_dims, var, ..., special_args = NULL, nrow = NULL, + ncol = NULL, toptitle = NULL, row_titles = NULL, col_titles = NULL, + bar_scale = 1, title_scale = 1, title_margin_scale = 1, + title_left_shift_scale = 1, subtitle_scale = 1, + subtitle_margin_scale = 1, brks = NULL, cols = NULL, drawleg = "S", + titles = NULL, subsampleg = NULL, bar_limits = NULL, + triangle_ends = NULL, col_inf = NULL, col_sup = NULL, + color_fun = clim.colors, draw_bar_ticks = TRUE, draw_separators = FALSE, + triangle_ends_scale = 1, bar_extra_labels = NULL, units = NULL, + units_scale = 1, bar_label_scale = 1, bar_tick_scale = 1, + bar_extra_margin = rep(0, 4), bar_left_shift_scale = 1, + bar_label_digits = 4, extra_margin = rep(0, 4), fileout = NULL, + width = NULL, height = NULL, size_units = "in", res = 100, + close_device = TRUE) } \arguments{ - \item{fun}{ -Plot function (or name of the function) to be called on the arrays provided in 'var'. If multiple arrays are provided in 'var', a vector of as many function names (character strings!) can be provided in 'fun', one for each array in 'var'. - } - \item{plot_dims}{ -Numeric or character string vector with identifiers of the input plot dimensions of the plot function specified in 'fun'. If character labels are provided, names(dim(var)) or attr('dimensions', var) will be checked to locate the dimensions. As many plots as prod(dim(var)[-plot_dims]) will be generated. If multiple arrays are provided in 'var', 'plot_dims' can be sent a list with a vector of plot dimensions for each. If a single vector is provided, it will be used for all the arrays in 'var'. - } - \item{var}{ -Multi-dimensional array with at least the dimensions expected by the specified plot function in 'fun'. The dimensions reqired by the function must be specified in 'plot_dims'. The dimensions can be disordered and will be reordered automatically. Dimensions can optionally be labelled in order to refer to them with names in 'plot_dims'. All the available plottable sub-arrays will be automatically plotted and arranged in consecutive cells of an automatically arranged layout. A list of multiple (super-)arrays can be specified. The process will be repeated for each of them, by default applying the same plot function to all of them or, if properly specified in 'fun', a different plot function will be applied to each of them. NAs can be passed to the list: a NA will yield a blank cell in the layout, which can be populated after (see .SwitchToFigure). - } - \item{\dots}{ -Parameters to be sent to the plotting function 'fun'. If multiple arrays are provided in 'var' and multiple functions are provided in 'fun', the parameters provided through \dots will be sent to all the plot functions, as common parameters. To specify concrete arguments for each of the plot functions see parameter 'special_args'. - } - \item{special_args}{ -List of sub-lists, each sub-list having specific extra arguments for each of the plot functions provided in 'fun'. If you want to fix a different value for each plot in the layout you can do so by a) splitting your array into a list of sub-arrays (each with the data for one plot) and providing it as parameter 'var', b) providing a list of named sub-lists in 'special_args', where the names of each sub-list match the names of the parameters to be adjusted, and each value in a sub-list contains the value of the corresponding parameter. - } - \item{nrow}{ -Numeric value to force the number of rows in the automatically generated layout. If higher than the required, this will yield blank cells in the layout (which can then be populated). If lower than the required the function will stop. By default it is configured to arrange the layout in a shape as square as possible. Blank cells can be manually populated after with customized plots (see SwitchTofigure). - } - \item{ncol}{ -Numeric value to force the number of columns in the automatically generated layout. If higher than the required, this will yield blank cells in the layout (which can then be populated). If lower than the required the function will stop. By default it is configured to arrange the layout in a shape as square as possible. Blank cells can be manually populated after with customized plots (see SwitchTofigure). - } - \item{toptitle}{ -Topt title for the multi-pannel. Blank by default. - } - \item{row_titles}{ -Character string vector with titles for each of the rows in the layout. Blank by default. - } - \item{col_titles}{ -Character string vector with titles for each of the columns in the layout. Blank by default. - } - \item{bar_scale}{ -Scale factor for the common colour bar. Takes 1 by default. - } - \item{title_scale}{ -Scale factor for the multi-pannel title. Takes 1 by default. - } - \item{title_margin_scale}{ -Scale factor for the margins surrounding the top title. Takes 1 by default. - } - \item{title_left_shift_scale}{ -When plotting row titles, a shift is added to the horizontal positioning of the top title in order to center it to the region of the figures (without taking row titles into account). This shift can be reduced. A value of 0 will remove the shift completely, centering the title to the total width of the device. This parameter will be disregarded if no 'row_titles' are provided. - } - \item{subtitle_scale}{ -Scale factor for the row titles and column titles (specified in 'row_titles' and 'col_titles'). Takes 1 by default. - } - \item{subtitle_margin_scale}{ -Scale factor for the margins surrounding the subtitles. Takes 1 by default. - } - \item{units}{ -Title at the top of the colour bar, most commonly the units of the variable provided in parameter 'var'. - } - \item{brks,cols,bar_limits,triangle_ends}{ -Usually only providing 'brks' is enough to generate the desired colour bar. These parameters allow to define n breaks that define n - 1 intervals to classify each of the values in 'var'. The corresponding grid cell of a given value in 'var' will be coloured in function of the interval it belongs to. These parameters are sent to \code{ColorBar()} to generate the breaks and colours. Additional colours for values beyond the limits of the colour bar are also generated and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are properly provided to do so. See ?ColorBar for a full explanation.\cr - } - \item{col_inf,col_sup}{ -Colour identifiers to colour the values in 'var' that go beyond the extremes of the colour bar and to colour NA values, respectively. 'colNA' takes 'white' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. - } - \item{color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin}{ -Set of parameters to control the visual aspect of the drawn colour bar. See ?ColorBar for a full explanation. - } - \item{drawleg}{ -Where to draw the common colour bar. Can take values TRUE, FALSE or:\cr - 'up', 'u', 'U', 'top', 't', 'T', 'north', 'n', 'N'\cr - 'down', 'd', 'D', 'bottom', 'b', 'B', 'south', 's', 'S' (default)\cr - 'right', 'r', 'R', 'east', 'e', 'E'\cr - 'left', 'l', 'L', 'west', 'w', 'W' - } - \item{titles}{ -Character string vector with titles for each of the figures in the multi-pannel, from top-left to bottom-right. Blank by default. - } - \item{bar_left_shift_scale}{ -When plotting row titles, a shift is added to the horizontal positioning of the colour bar in order to center it to the region of the figures (without taking row titles into account). This shift can be reduced. A value of 0 will remove the shift completely, centering the colour bar to the total width of the device. This parameter will be disregarded if no 'row_titles' are provided. - } - \item{extra_margin}{ -Extra margins to be added around the layout, in the format c(y1, x1, y2, x2). The units are margin lines. Takes rep(0, 4) by default. - } - \item{fileout}{ -File where to save the plot. If not specified (default) a graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, bmp and tiff. \cr - } - \item{width}{ -Width in inches of the multi-pannel. 7 by default, or 11 if 'fielout' has been specified. - } - \item{height}{ -Height in inches of the multi-pannel. 7 by default, or 11 if 'fileout' has been specified. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{close_device}{ -Whether to close the graphics device after plotting the layout and a 'fileout' has been specified. This is useful to avoid closing the device when saving the layout into a file and willing to add extra elements or figures. Takes TRUE by default. Disregarded if no 'fileout' has been specified. - } +\item{fun}{Plot function (or name of the function) to be called on the +arrays provided in 'var'. If multiple arrays are provided in 'var', a +vector of as many function names (character strings!) can be provided in +'fun', one for each array in 'var'.} + +\item{plot_dims}{Numeric or character string vector with identifiers of the +input plot dimensions of the plot function specified in 'fun'. If +character labels are provided, names(dim(var)) or attr('dimensions', var) +will be checked to locate the dimensions. As many plots as +prod(dim(var)[-plot_dims]) will be generated. If multiple arrays are +provided in 'var', 'plot_dims' can be sent a list with a vector of plot +dimensions for each. If a single vector is provided, it will be used for +all the arrays in 'var'.} + +\item{var}{Multi-dimensional array with at least the dimensions expected by +the specified plot function in 'fun'. The dimensions reqired by the +function must be specified in 'plot_dims'. The dimensions can be +disordered and will be reordered automatically. Dimensions can optionally +be labelled in order to refer to them with names in 'plot_dims'. All the +available plottable sub-arrays will be automatically plotted and arranged +in consecutive cells of an automatically arranged layout. A list of +multiple (super-)arrays can be specified. The process will be repeated for +each of them, by default applying the same plot function to all of them +or, if properly specified in 'fun', a different plot function will be +applied to each of them. NAs can be passed to the list: a NA will yield a +blank cell in the layout, which can be populated after +(see .SwitchToFigure).} + +\item{special_args}{List of sub-lists, each sub-list having specific extra +arguments for each of the plot functions provided in 'fun'. If you want to +fix a different value for each plot in the layout you can do so by +a) splitting your array into a list of sub-arrays (each with the data for +one plot) and providing it as parameter 'var', +b) providing a list of named sub-lists in 'special_args', where the names +of each sub-list match the names of the parameters to be adjusted, and +each value in a sub-list contains the value of the corresponding parameter.} + +\item{nrow}{Numeric value to force the number of rows in the automatically +generated layout. If higher than the required, this will yield blank cells +in the layout (which can then be populated). If lower than the required +the function will stop. By default it is configured to arrange the layout +in a shape as square as possible. Blank cells can be manually populated +after with customized plots (see SwitchTofigure).} + +\item{ncol}{Numeric value to force the number of columns in the +automatically generated layout. If higher than the required, this will +yield blank cells in the layout (which can then be populated). If lower +than the required the function will stop. By default it is configured to +arrange the layout in a shape as square as possible. Blank cells can be +manually populated after with customized plots (see SwitchTofigure).} + +\item{toptitle}{Topt title for the multi-pannel. Blank by default.} + +\item{row_titles}{Character string vector with titles for each of the rows +in the layout. Blank by default.} + +\item{col_titles}{Character string vector with titles for each of the +columns in the layout. Blank by default.} + +\item{bar_scale}{Scale factor for the common colour bar. Takes 1 by default.} + +\item{title_scale}{Scale factor for the multi-pannel title. Takes 1 by +default.} + +\item{title_margin_scale}{Scale factor for the margins surrounding the top +title. Takes 1 by default.} + +\item{title_left_shift_scale}{When plotting row titles, a shift is added +to the horizontal positioning of the top title in order to center it to +the region of the figures (without taking row titles into account). This +shift can be reduced. A value of 0 will remove the shift completely, +centering the title to the total width of the device. This parameter will +be disregarded if no 'row_titles' are provided.} + +\item{subtitle_scale}{Scale factor for the row titles and column titles +(specified in 'row_titles' and 'col_titles'). Takes 1 by default.} + +\item{subtitle_margin_scale}{Scale factor for the margins surrounding the +subtitles. Takes 1 by default.} + +\item{brks, cols, bar_limits, triangle_ends}{Usually only providing 'brks' is +enough to generate the desired colour bar. These parameters allow to +define n breaks that define n - 1 intervals to classify each of the values +in 'var'. The corresponding grid cell of a given value in 'var' will be +coloured in function of the interval it belongs to. These parameters are +sent to \code{ColorBar()} to generate the breaks and colours. Additional +colours for values beyond the limits of the colour bar are also generated +and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are +properly provided to do so. See ?ColorBar for a full explanation.} + +\item{drawleg}{Where to draw the common colour bar. Can take values TRUE, +FALSE or:\cr +'up', 'u', 'U', 'top', 't', 'T', 'north', 'n', 'N'\cr +'down', 'd', 'D', 'bottom', 'b', 'B', 'south', 's', 'S' (default)\cr +'right', 'r', 'R', 'east', 'e', 'E'\cr +'left', 'l', 'L', 'west', 'w', 'W'} + +\item{titles}{Character string vector with titles for each of the figures in +the multi-pannel, from top-left to bottom-right. Blank by default.} + +\item{col_inf, col_sup}{Colour identifiers to colour the values in 'var' that +go beyond the extremes of the colour bar and to colour NA values, +respectively. 'colNA' takes 'white' by default. 'col_inf' and 'col_sup' +will take the value of 'colNA' if not specified. See ?ColorBar for a full +explanation on 'col_inf' and 'col_sup'.} + +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, }{triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, +bar_tick_scale,bar_extra_margin Set of parameters to control the visual + aspect of the drawn colour bar. See ?ColorBar for a full explanation.} + +\item{units}{Title at the top of the colour bar, most commonly the units of +the variable provided in parameter 'var'.} + +\item{bar_left_shift_scale}{When plotting row titles, a shift is added to +the horizontal positioning of the colour bar in order to center it to the +region of the figures (without taking row titles into account). This shift +can be reduced. A value of 0 will remove the shift completely, centering +the colour bar to the total width of the device. This parameter will be +disregarded if no 'row_titles' are provided.} + +\item{extra_margin}{Extra margins to be added around the layout, in the +format c(y1, x1, y2, x2). The units are margin lines. Takes rep(0, 4) +by default.} + +\item{fileout}{File where to save the plot. If not specified (default) a +graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, +bmp and tiff.} + +\item{width}{Width in inches of the multi-pannel. 7 by default, or 11 if +'fielout' has been specified.} + +\item{height}{Height in inches of the multi-pannel. 7 by default, or 11 if +'fileout' has been specified.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of +the corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{close_device}{Whether to close the graphics device after plotting +the layout and a 'fileout' has been specified. This is useful to avoid +closing the device when saving the layout into a file and willing to add +extra elements or figures. Takes TRUE by default. Disregarded if no +'fileout' has been specified.} + +\item{\dots}{Parameters to be sent to the plotting function 'fun'. If +multiple arrays are provided in 'var' and multiple functions are provided +in 'fun', the parameters provided through \dots will be sent to all the +plot functions, as common parameters. To specify concrete arguments for +each of the plot functions see parameter 'special_args'.} } \value{ - \item{brks}{ -Breaks used for colouring the map (and legend if drawleg = TRUE). - } - \item{cols}{ -Colours used for colouring the map (and legend if drawleg = TRUE). Always of length length(brks) - 1. - } - \item{col_inf}{ -Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). - } - \item{col_sup}{ -Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). - } - \item{layout_matrix}{ -Underlying matrix of the layout. Useful to later set any of the layout cells as current figure to add plot elements. See .SwitchToFigure. - } +\itemize{ + \item{brks}{ + Breaks used for colouring the map (and legend if drawleg = TRUE). + } + \item{cols}{ + Colours used for colouring the map (and legend if drawleg = TRUE). + Always of length length(brks) - 1. + } + \item{col_inf}{ + Colour used to draw the lower triangle end in the colour bar + (NULL if not drawn at all). + } + \item{col_sup}{ + Colour used to draw the upper triangle end in the colour bar + (NULL if not drawn at all). + } + \item{layout_matrix}{ + Underlying matrix of the layout. Useful to later set any of the layout + cells as current figure to add plot elements. See .SwitchToFigure. + } +} +} +\description{ +This function takes an array or list of arrays and loops over each of them +to plot all the sub-arrays they contain on an automatically generated +multi-pannel layout. A different plot function (not necessarily from +s2dverification) can be applied over each of the provided arrays. The input +dimensions of each of the functions have to be specified, either with the +names or the indices of the corresponding input dimensions. It is possible +to draw a common colour bar at any of the sides of the multi-pannel for all +the s2dverification plots that use a colour bar. Common plotting arguments +for all the arrays in 'var' can be specified via the '...' parameter, and +specific plotting arguments for each array can be fully adjusted via +'special_args'. It is possible to draw titles for each of the figures, +layout rows, layout columns and for the whole figure. A number of parameters +is provided in order to adjust the position, size and colour of the +components. Blank cells can be forced to appear and later be filled in +manually with customized plots.\cr +This function pops up a blank new device and fills it in, so it cannot be +nested in complex layouts. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } PlotLayout(PlotEquiMap, c('lat', 'lon'), sampleData$mod[1, , 1, 1, , ], - sampleData$lon, sampleData$lat, - toptitle = 'Predicted tos for Nov 1960 from 1st Nov', - titles = paste('Member', 1:15)) + sampleData$lon, sampleData$lat, + toptitle = 'Predicted tos for Nov 1960 from 1st Nov', + titles = paste('Member', 1:15)) + } \author{ - History: - 0.1 - 2016-08 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Original code +History:\cr + 0.1 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code } \keyword{dynamic} diff --git a/man/PlotSection.Rd b/man/PlotSection.Rd index f7f3349f..f7447319 100644 --- a/man/PlotSection.Rd +++ b/man/PlotSection.Rd @@ -1,89 +1,78 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotSection.R \name{PlotSection} \alias{PlotSection} -\title{ -Plots A Vertical Section -} -\description{ -Plot a (longitude,depth) or (latitude,depth) section. -} +\title{Plots A Vertical Section} \usage{ -PlotSection(var, horiz, depth, toptitle = "", sizetit = 1, units = "", - brks = NULL, cols = NULL, axelab = TRUE, intydep = 200, - intxhoriz = 20, drawleg = TRUE, fileout = NULL, - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotSection(var, horiz, depth, toptitle = "", sizetit = 1, units = "", + brks = NULL, cols = NULL, axelab = TRUE, intydep = 200, + intxhoriz = 20, drawleg = TRUE, fileout = NULL, width = 8, + height = 5, size_units = "in", res = 100, ...) } \arguments{ - \item{var}{ -Matrix to plot with (longitude/latitude, depth) dimensions. - } - \item{horiz}{ -Array of longitudes or latitudes. - } - \item{depth}{ -Array of depths. - } - \item{toptitle}{ -Title, optional. - } - \item{sizetit}{ -Multiplicative factor to increase title size, optional. - } - \item{units}{ -Units, optional. - } - \item{brks}{ -Colour levels, optional. - } - \item{cols}{ -List of colours, optional. - } - \item{axelab}{ -TRUE/FALSE, label the axis. Default = TRUE. - } - \item{intydep}{ -Interval between depth ticks on y-axis. Default: 200m. - } - \item{intxhoriz}{ -Interval between longitude/latitude ticks on x-axis.\cr -Default: 20deg. - } - \item{drawleg}{ -Draw colorbar. Default: TRUE. - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{fileout}{ -Name of output file. Extensions allowed: eps/ps, jpeg, png, pdf, bmp -and tiff. \cr -Default = NULL - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - adj ann ask bg bty cex.lab cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty lwd mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } +\item{var}{Matrix to plot with (longitude/latitude, depth) dimensions.} + +\item{horiz}{Array of longitudes or latitudes.} + +\item{depth}{Array of depths.} + +\item{toptitle}{Title, optional.} + +\item{sizetit}{Multiplicative factor to increase title size, optional.} + +\item{units}{Units, optional.} + +\item{brks}{Colour levels, optional.} + +\item{cols}{List of colours, optional.} + +\item{axelab}{TRUE/FALSE, label the axis. Default = TRUE.} + +\item{intydep}{Interval between depth ticks on y-axis. Default: 200m.} + +\item{intxhoriz}{Interval between longitude/latitude ticks on x-axis.\cr +Default: 20deg.} + +\item{drawleg}{Draw colorbar. Default: TRUE.} + +\item{fileout}{Name of output file. Extensions allowed: eps/ps, jpeg, png, +pdf, bmp and tiff. \cr +Default = NULL} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{...}{Arguments to be passed to the method. Only accepts the following +graphical parameters:\cr +adj ann ask bg bty cex.lab cex.sub cin col.axis col.lab col.main col.sub +cra crt csi cxy err family fg fig fin font font.axis font.lab font.main +font.sub lend lheight ljoin lmitre lty lwd mex mfcol mfrow mfg mkh oma omd +omi page pch pin plt pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs +yaxt ylbias ylog \cr +For more information about the parameters see `par`.} +} +\description{ +Plot a (longitude,depth) or (latitude,depth) section. } \examples{ sampleData <- s2dverification::sampleDepthData PlotSection(sampleData$mod[1, 1, 1, 1, , ], sampleData$lat, sampleData$depth, - toptitle = 'temperature 1995-11 member 0') + toptitle = 'temperature 1995-11 member 0') } \author{ History:\cr -0.1 - 2012-09 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2012-09 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{dynamic} + diff --git a/man/PlotStereoMap.Rd b/man/PlotStereoMap.Rd index 8b262b7f..5df0a95f 100644 --- a/man/PlotStereoMap.Rd +++ b/man/PlotStereoMap.Rd @@ -1,157 +1,199 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotStereoMap.R \name{PlotStereoMap} \alias{PlotStereoMap} -\title{ -Maps A Two-Dimensional Variable On A Polar Stereographic Projection -} -\description{ -Map longitude-latitude array (on a regular rectangular or gaussian grid) on a polar stereographic world projection with coloured grid cells. Only the region within a specified latitude interval is displayed. A colour bar (legend) can be plotted and adjusted. It is possible to draw superimposed dots, symbols and boxes. A number of options is provided to adjust the position, size and colour of the components. This plot function is compatible with figure layouts if colour bar is disabled.. -} +\title{Maps A Two-Dimensional Variable On A Polar Stereographic Projection} \usage{ -PlotStereoMap(var, lon, lat, latlims = c(60, 90), - toptitle = NULL, sizetit = NULL, units = NULL, - brks = NULL, cols = NULL, bar_limits = NULL, - triangle_ends = NULL, col_inf = NULL, col_sup = NULL, - colNA = NULL, color_fun = clim.palette(), - filled.continents = FALSE, coast_color = NULL, - coast_width = 1, - dots = NULL, dot_symbol = 4, dot_size = 0.8, - intlat = 10, - drawleg = TRUE, subsampleg = NULL, - bar_extra_labels = NULL, draw_bar_ticks = TRUE, - draw_separators = FALSE, triangle_ends_scale = 1, - bar_label_digits = 4, bar_label_scale = 1, - units_scale = 1, bar_tick_scale = 1, - bar_extra_margin = rep(0, 4), - boxlim = NULL, boxcol = "purple2", boxlwd = 5, - margin_scale = rep(1, 4), title_scale = 1, - numbfig = NULL, fileout = NULL, width = 6, height = 5, - size_units = 'in', res = 100, ...) +PlotStereoMap(var, lon, lat, latlims = c(60, 90), toptitle = NULL, + sizetit = NULL, units = NULL, brks = NULL, cols = NULL, + bar_limits = NULL, triangle_ends = NULL, col_inf = NULL, + col_sup = NULL, colNA = NULL, color_fun = clim.palette(), + filled.continents = FALSE, coast_color = NULL, coast_width = 1, + dots = NULL, dot_symbol = 4, dot_size = 0.8, intlat = 10, + drawleg = TRUE, subsampleg = NULL, bar_extra_labels = NULL, + draw_bar_ticks = TRUE, draw_separators = FALSE, triangle_ends_scale = 1, + bar_label_digits = 4, bar_label_scale = 1, units_scale = 1, + bar_tick_scale = 1, bar_extra_margin = rep(0, 4), boxlim = NULL, + boxcol = "purple2", boxlwd = 5, margin_scale = rep(1, 4), + title_scale = 1, numbfig = NULL, fileout = NULL, width = 6, + height = 5, size_units = "in", res = 100, ...) } \arguments{ - \item{var}{ -Array with the values at each cell of a grid on a regular rectangular or gaussian grid. The array is expected to have two dimensions: c(latitude, longitude). Longitudes can be in ascending or descending order and latitudes in any order. It can contain NA values (coloured with 'colNA'). Arrays with dimensions c(longitude, latitude) will also be accepted but 'lon' and 'lat' will be used to disambiguate so this alternative is not appropriate for square arrays. - } - \item{lon}{ -Numeric vector of longitude locations of the cell centers of the grid of 'var', in ascending or descending order (same as 'var'). Expected to be regularly spaced, within either of the ranges [-180, 180] or [0, 360]. Data for two adjacent regions split by the limits of the longitude range can also be provided, e.g. \code{lon = c(0:50, 300:360)} ('var' must be provided consitently). - } - \item{lat}{ -Numeric vector of latitude locations of the cell centers of the grid of 'var', in any order (same as 'var'). Expected to be from a regular rectangular or gaussian grid, within the range [-90, 90]. - } - \item{latlims}{ -Latitudinal limits of the figure.\cr +\item{var}{Array with the values at each cell of a grid on a regular +rectangular or gaussian grid. The array is expected to have two dimensions: +c(latitude, longitude). Longitudes can be in ascending or descending order +and latitudes in any order. It can contain NA values (coloured with +'colNA'). Arrays with dimensions c(longitude, latitude) will also be +accepted but 'lon' and 'lat' will be used to disambiguate so this +alternative is not appropriate for square arrays.} + +\item{lon}{Numeric vector of longitude locations of the cell centers of the +grid of 'var', in ascending or descending order (same as 'var'). Expected +to be regularly spaced, within either of the ranges [-180, 180] or +[0, 360]. Data for two adjacent regions split by the limits of the +longitude range can also be provided, e.g. \code{lon = c(0:50, 300:360)} +('var' must be provided consitently).} + +\item{lat}{Numeric vector of latitude locations of the cell centers of the +grid of 'var', in any order (same as 'var'). Expected to be from a regular +rectangular or gaussian grid, within the range [-90, 90].} + +\item{latlims}{Latitudinal limits of the figure.\cr Example : c(60, 90) for the North Pole\cr - c(-90,-60) for the South Pole - } - \item{toptitle}{ -Top title of the figure, scalable with parameter 'title_scale'. - } - \item{sizetit}{ -Scale factor for the figure top title provided in parameter 'toptitle'. Deprecated. Use 'title_scale' instead. - } - \item{units}{ -Title at the top of the colour bar, most commonly the units of the variable provided in parameter 'var'. - } - \item{brks,cols,bar_limits,triangle_ends}{ -Usually only providing 'brks' is enough to generate the desired colour bar. These parameters allow to define n breaks that define n - 1 intervals to classify each of the values in 'var'. The corresponding grid cell of a given value in 'var' will be coloured in function of the interval it belongs to. These parameters are sent to \code{ColorBar()} to generate the breaks and colours. Additional colours for values beyond the limits of the colour bar are also generated and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are properly provided to do so. See ?ColorBar for a full explanation.\cr - } - \item{col_inf,col_sup,colNA}{ -Colour identifiers to colour the values in 'var' that go beyond the extremes of the colour bar and to colour NA values, respectively. 'colNA' takes attr(cols, 'na_color') if available by default, where cols is the parameter 'cols' if provided or the vector of colors returned by 'color_fun'. If not available, it takes 'pink' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. - } - \item{color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin}{ -Set of parameters to control the visual aspect of the drawn colour bar. See ?ColorBar for a full explanation. - } - \item{filled.continents}{ -Colour to fill in drawn projected continents. Takes the value gray(0.5) by default. If set to FALSE, continents are not filled in. - } - \item{coast_color}{ -Colour of the coast line of the drawn projected continents. Takes the value gray(0.5) by default. - } - \item{coast_width}{ -Line width of the coast line of the drawn projected continents. Takes the value 1 by default. - } - \item{dots}{ -Array of same dimensions as 'var' or with dimensions c(n, dim(var)), where n is the number of dot/symbol layers to add to the plot. A value of TRUE at a grid cell will draw a dot/symbol on the corresponding square of the plot. By default all layers provided in 'dots' are plotted with dots, but a symbol can be specified for each of the layers via the parameter 'dot_symbol'. - } - \item{dot_symbol}{ -Single character/number or vector of characters/numbers that correspond to each of the symbol layers specified in parameter 'dots'. If a single value is specified, it will be applied to all the layers in 'dots'. Takes 15 (centered square) by default. See 'pch' in par() for additional accepted options. - } - \item{dot_size}{ -Scale factor for the dots/symbols to be plotted, specified in 'dots'. If a single value is specified, it will be applied to all layers in 'dots'. Takes 1 by default. - } - \item{intlat}{ -Interval between latitude lines (circles), in degrees. Defaults to 10. - } - \item{drawleg}{ -Whether to plot a color bar (legend, key) or not. Defaults to TRUE. - } - \item{boxlim}{ -Limits of a box to be added to the plot, in degrees: c(x1, y1, x2, y2). A list with multiple box specifications can also be provided. - } - \item{boxcol}{ -Colour of the box lines. A vector with a colour for each of the boxes is also accepted. Defaults to 'purple2'. - } - \item{boxlwd}{ -Line width of the box lines. A vector with a line width for each of the boxes is also accepted. Defaults to 5. - } - \item{margin_scale}{ -Scale factor for the margins to be added to the plot, with the format c(y1, x1, y2, x2). Defaults to rep(1, 4). If drawleg = TRUE, margin_scale[1] is subtracted 1 unit. - } - \item{title_scale}{ -Scale factor for the figure top title. Defaults to 1. - } - \item{numbfig}{ -Number of figures in the layout the plot will be put into. A higher numbfig will result in narrower margins and smaller labels, axe labels, ticks, thinner lines, ... Defaults to 1. - } - \item{fileout}{ -File where to save the plot. If not specified (default) a graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, bmp and tiff. \cr - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{\dots}{ -Arguments to be passed to the method. Only accepts the following graphical parameters: - -adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg font font.axis font.lab font.main font.sub lend lheight ljoin lmitre mex mfcol mfrow mfg mkh omd omi page pch pin plt pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - -For more information about the parameters see `par`. - } + c(-90,-60) for the South Pole} + +\item{toptitle}{Top title of the figure, scalable with parameter +'title_scale'.} + +\item{sizetit}{Scale factor for the figure top title provided in parameter +'toptitle'. Deprecated. Use 'title_scale' instead.} + +\item{units}{Title at the top of the colour bar, most commonly the units of +the variable provided in parameter 'var'.} + +\item{brks, cols, bar_limits, triangle_ends}{Usually only providing 'brks' is +enough to generate the desired colour bar. These parameters allow to +define n breaks that define n - 1 intervals to classify each of the values +in 'var'. The corresponding grid cell of a given value in 'var' will be +coloured in function of the interval it belongs to. These parameters are +sent to \code{ColorBar()} to generate the breaks and colours. Additional +colours for values beyond the limits of the colour bar are also generated +and applied to the plot if 'bar_limits' or 'brks' and 'triangle_ends' are +properly provided to do so. See ?ColorBar for a full explanation.} + +\item{col_inf, col_sup, colNA}{Colour identifiers to colour the values in +'var' that go beyond the extremes of the colour bar and to colour NA +values, respectively. 'colNA' takes attr(cols, 'na_color') if available by +default, where cols is the parameter 'cols' if provided or the vector of +colors returned by 'color_fun'. If not available, it takes 'pink' by +default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not +specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'.} + +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, }{draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale, +units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control + the visual aspect of the drawn colour bar. See ?ColorBar for a + full explanation.} + +\item{filled.continents}{Colour to fill in drawn projected continents. Takes +the value gray(0.5) by default. If set to FALSE, continents are not +filled in.} + +\item{coast_color}{Colour of the coast line of the drawn projected +continents. Takes the value gray(0.5) by default.} + +\item{coast_width}{Line width of the coast line of the drawn projected +continents. Takes the value 1 by default.} + +\item{dots}{Array of same dimensions as 'var' or with dimensions +c(n, dim(var)), where n is the number of dot/symbol layers to add to the +plot. A value of TRUE at a grid cell will draw a dot/symbol on the +corresponding square of the plot. By default all layers provided in 'dots' +are plotted with dots, but a symbol can be specified for each of the +layers via the parameter 'dot_symbol'.} + +\item{dot_symbol}{Single character/number or vector of characters/numbers +that correspond to each of the symbol layers specified in parameter 'dots'. +If a single value is specified, it will be applied to all the layers in +'dots'. Takes 15 (centered square) by default. See 'pch' in par() for +additional accepted options.} + +\item{dot_size}{Scale factor for the dots/symbols to be plotted, specified +in 'dots'. If a single value is specified, it will be applied to all +layers in 'dots'. Takes 1 by default.} + +\item{intlat}{Interval between latitude lines (circles), in degrees. +Defaults to 10.} + +\item{drawleg}{Whether to plot a color bar (legend, key) or not. +Defaults to TRUE.} + +\item{boxlim}{Limits of a box to be added to the plot, in degrees: +c(x1, y1, x2, y2). A list with multiple box specifications can also +be provided.} + +\item{boxcol}{Colour of the box lines. A vector with a colour for each of +the boxes is also accepted. Defaults to 'purple2'.} + +\item{boxlwd}{Line width of the box lines. A vector with a line width for +each of the boxes is also accepted. Defaults to 5.} + +\item{margin_scale}{Scale factor for the margins to be added to the plot, +with the format c(y1, x1, y2, x2). Defaults to rep(1, 4). If drawleg = TRUE, +margin_scale[1] is subtracted 1 unit.} + +\item{title_scale}{Scale factor for the figure top title. Defaults to 1.} + +\item{numbfig}{Number of figures in the layout the plot will be put into. +A higher numbfig will result in narrower margins and smaller labels, +axe labels, ticks, thinner lines, ... Defaults to 1.} + +\item{fileout}{File where to save the plot. If not specified (default) a +graphics device will pop up. Extensions allowed: eps/ps, jpeg, png, pdf, +bmp and tiff.} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of +the corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{\dots}{Arguments to be passed to the method. Only accepts the +following graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg font font.axis font.lab font.main font.sub lend +lheight ljoin lmitre mex mfcol mfrow mfg mkh omd omi page pch pin plt pty +smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} } \value{ - \item{brks}{ -Breaks used for colouring the map (and legend if drawleg = TRUE). - } - \item{cols}{ -Colours used for colouring the map (and legend if drawleg = TRUE). Always of length length(brks) - 1. - } - \item{col_inf}{ -Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). - } - \item{col_sup}{ -Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). - } +\itemize{ + \item{brks}{ + Breaks used for colouring the map (and legend if drawleg = TRUE). + } + \item{cols}{ + Colours used for colouring the map (and legend if drawleg = TRUE). Always + of length length(brks) - 1. + } + \item{col_inf}{ + Colour used to draw the lower triangle end in the colour bar (NULL if not + drawn at all). + } + \item{col_sup}{ + Colour used to draw the upper triangle end in the colour bar (NULL if not + drawn at all). + } +} +} +\description{ +Map longitude-latitude array (on a regular rectangular or gaussian grid) on +a polar stereographic world projection with coloured grid cells. Only the +region within a specified latitude interval is displayed. A colour bar +(legend) can be plotted and adjusted. It is possible to draw superimposed +dots, symbols and boxes. A number of options is provided to adjust the +position, size and colour of the components. This plot function is +compatible with figure layouts if colour bar is disabled. } \examples{ data <- matrix(rnorm(100 * 50), 100, 50) x <- seq(from = 0, to = 360, length.out = 100) y <- seq(from = -90, to = 90, length.out = 50) PlotStereoMap(data, x, y, latlims = c(60, 90), brks = 50, - toptitle = "This is the title") + toptitle = "This is the title") } \author{ History:\cr -1.0 - 2014-07 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code -1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze at meteo.fr}) - Box(es) drawing -1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Refacotred the function and - merged in Jean-Philippe circle - border and Constantin boxes. +1.0 - 2014-07 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze@meteo.fr}) - Box(es) drawing +1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Refacotred the function and + merged in Jean-Philippe circle + border and Constantin boxes. } \keyword{dynamic} + diff --git a/man/PlotVsLTime.Rd b/man/PlotVsLTime.Rd index cebb9e50..5c7ab282 100644 --- a/man/PlotVsLTime.Rd +++ b/man/PlotVsLTime.Rd @@ -1,107 +1,102 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotVsLTime.R \name{PlotVsLTime} \alias{PlotVsLTime} -\title{ -Plots A Score Along The Forecast Time With Its Confidence Interval -} -\description{ -Plots The Correlation (\code{Corr()}) or the Root Mean Square Error (\code{RMS()}) between the forecasted values and their observational counterpart or the slopes of their trends (\code{Trend()}) or the InterQuartile Range, Maximum-Mininum, Standard Deviation or Median Absolute Deviation of the Ensemble Members (\code{Spread()}), or the ratio between the Ensemble Spread and the RMSE of the Ensemble Mean (\code{RatioSDRMS()}) along the forecast time for all the input experiments on the same figure with their confidence intervals. -} +\title{Plots A Score Along The Forecast Time With Its Confidence Interval} \usage{ -PlotVsLTime(var, toptitle = "", ytitle = "", monini = 1, freq = 12, - nticks = NULL, limits = NULL, listexp = c("exp1", "exp2", "exp3"), - listobs = c("obs1", "obs2", "obs3"), biglab = FALSE, hlines = NULL, - leg = TRUE, siglev = FALSE, sizetit = 1, show_conf = TRUE, - fileout = "output_plotvsltime.eps", - width = 8, height = 5, size_units = 'in', res = 100, ...) +PlotVsLTime(var, toptitle = "", ytitle = "", monini = 1, freq = 12, + nticks = NULL, limits = NULL, listexp = c("exp1", "exp2", "exp3"), + listobs = c("obs1", "obs2", "obs3"), biglab = FALSE, hlines = NULL, + leg = TRUE, siglev = FALSE, sizetit = 1, show_conf = TRUE, + fileout = "output_plotvsltime.eps", width = 8, height = 5, + size_units = "in", res = 100, ...) } \arguments{ - \item{var}{ -Matrix containing any Prediction Score with dimensions:\cr - (nexp/nmod, 3/4 ,nltime)\cr - or (nexp/nmod, nobs, 3/4 ,nltime) - } - \item{toptitle}{ -Main title, optional. - } - \item{ytitle}{ -Title of Y-axis, optional. - } - \item{monini}{ -Starting month between 1 and 12. Default = 1. - } - \item{freq}{ -1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12. - } - \item{nticks}{ -Number of ticks and labels on the x-axis, optional. - } - \item{limits}{ -c(lower limit, upper limit): limits of the Y-axis, optional. - } - \item{listexp}{ -List of experiment names, optional. - } - \item{listobs}{ -List of observation names, optional. - } - \item{biglab}{ -TRUE/FALSE for presentation/paper plot. Default = FALSE. - } - \item{hlines}{ -c(a,b, ..) Add horizontal black lines at Y-positions a,b, ...\cr -Default = NULL. - } - \item{leg}{ -TRUE/FALSE if legend should be added or not to the plot. Default = TRUE. - } - \item{siglev}{ -TRUE/FALSE if significance level should replace confidence interval.\cr -Default = FALSE. - } - \item{sizetit}{ -Multiplicative factor to change title size, optional. - } - \item{show_conf}{ -TRUE/FALSE to show/not confidence intervals for input variables. - } - \item{fileout}{ -Name of output file. Extensions allowed: eps/ps, jpeg, png, pdf, bmp -and tiff.\cr -Default = 'output_plotvsltime.eps' - } - \item{width}{ -File width, in the units specified in the parameter size_units (inches by default). Takes 8 by default. - } - \item{height}{ -File height, in the units specified in the parameter size_units (inches by default). Takes 5 by default. - } - \item{size_units}{ -Units of the size of the device (file or window) to plot in. Inches ('in') by default. See ?Devices and the creator function of the corresponding device. - } - \item{res}{ -Resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device. - } - \item{...}{ - Arguments to be passed to the method. Only accepts the following - graphical parameters: - - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig font font.axis font.lab font.main font.sub lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog - - For more information about the parameters see `par` - } -} -\details{ +\item{var}{Matrix containing any Prediction Score with dimensions:\cr +(nexp/nmod, 3/4 ,nltime)\cr +or (nexp/nmod, nobs, 3/4 ,nltime).} + +\item{toptitle}{Main title, optional.} + +\item{ytitle}{Title of Y-axis, optional.} + +\item{monini}{Starting month between 1 and 12. Default = 1.} + +\item{freq}{1 = yearly, 12 = monthly, 4 = seasonal, ... Default = 12.} + +\item{nticks}{Number of ticks and labels on the x-axis, optional.} + +\item{limits}{c(lower limit, upper limit): limits of the Y-axis, optional.} + +\item{listexp}{List of experiment names, optional.} + +\item{listobs}{List of observation names, optional.} + +\item{biglab}{TRUE/FALSE for presentation/paper plot. Default = FALSE.} + +\item{hlines}{c(a,b, ..) Add horizontal black lines at Y-positions a,b, ...\cr +Default = NULL.} + +\item{leg}{TRUE/FALSE if legend should be added or not to the plot. +Default = TRUE.} + +\item{siglev}{TRUE/FALSE if significance level should replace confidence +interval.\cr +Default = FALSE.} + +\item{sizetit}{Multiplicative factor to change title size, optional.} + +\item{show_conf}{TRUE/FALSE to show/not confidence intervals for input +variables.} + +\item{fileout}{Name of output file. Extensions allowed: eps/ps, jpeg, png, +pdf, bmp and tiff.\cr +Default = 'output_plotvsltime.eps'} + +\item{width}{File width, in the units specified in the parameter size_units +(inches by default). Takes 8 by default.} + +\item{height}{File height, in the units specified in the parameter +size_units (inches by default). Takes 5 by default.} + +\item{size_units}{Units of the size of the device (file or window) to plot +in. Inches ('in') by default. See ?Devices and the creator function of the +corresponding device.} + +\item{res}{Resolution of the device (file or window) to plot in. See +?Devices and the creator function of the corresponding device.} + +\item{...}{Arguments to be passed to the method. Only accepts the following + graphical parameters:\cr + adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt + csi cxy err family fg fig font font.axis font.lab font.main font.sub + lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt + smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr + For more information about the parameters see `par`. + Examples of input:\cr - Model and observed output from \code{Load()} then \code{Clim()} then \code{Ano()} then \code{Smoothing()}:\cr - (nmod, nmemb, nsdate, nltime) and (nobs, nmemb, nsdate, nltime)\cr - then averaged over the members\cr - \code{Mean1Dim(var_exp/var_obs, posdim = 2)}:\cr - (nmod, nsdate, nltime) and (nobs, nsdate, nltime)\cr - then passed through\cr - \code{Corr(exp, obs, posloop = 1, poscor = 2)} or\cr - \code{RMS(exp, obs, posloop = 1, posRMS = 2)}:\cr - (nmod, nobs, 3, nltime)\cr - would plot the correlations or RMS between each exp & each obs as a function of the forecast time. +Model and observed output from \code{Load()} then \code{Clim()} then +\code{Ano()} then \code{Smoothing()}:\cr +(nmod, nmemb, nsdate, nltime) and (nobs, nmemb, nsdate, nltime)\cr +then averaged over the members\cr +\code{Mean1Dim(var_exp/var_obs, posdim = 2)}:\cr +(nmod, nsdate, nltime) and (nobs, nsdate, nltime)\cr +then passed through\cr + \code{Corr(exp, obs, posloop = 1, poscor = 2)} or\cr + \code{RMS(exp, obs, posloop = 1, posRMS = 2)}:\cr + (nmod, nobs, 3, nltime)\cr +would plot the correlations or RMS between each exp & each obs as a function +of the forecast time.} +} +\description{ +Plots The Correlation (\code{Corr()}) or the Root Mean Square Error +(\code{RMS()}) between the forecasted values and their observational +counterpart or the slopes of their trends (\code{Trend()}) or the +InterQuartile Range, Maximum-Mininum, Standard Deviation or Median Absolute +Deviation of the Ensemble Members (\code{Spread()}), or the ratio between +the Ensemble Spread and the RMSE of the Ensemble Mean (\code{RatioSDRMS()}) +along the forecast time for all the input experiments on the same figure +with their confidence intervals. } \examples{ # Load sample data as in Load() example: @@ -117,20 +112,22 @@ dim_to_mean <- 2 # Mean along members required_complete_row <- 3 # Discard startdates for which there are NA leadtimes leadtimes_per_startdate <- 60 corr <- Corr(Mean1Dim(smooth_ano_exp, dim_to_mean), - Mean1Dim(smooth_ano_obs, dim_to_mean), - compROW = required_complete_row, - limits = c(ceiling((runmean_months + 1) / 2), - leadtimes_per_startdate - floor(runmean_months / 2))) + Mean1Dim(smooth_ano_obs, dim_to_mean), + compROW = required_complete_row, + limits = c(ceiling((runmean_months + 1) / 2), + leadtimes_per_startdate - floor(runmean_months / 2))) PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", - monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), - fileout = 'tos_cor.eps') + monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), + fileout = 'tos_cor.eps') + } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -0.2 - 2013-03 (I. Andreu-Burillo, \email{isabel.andreu-burillo at ic3.cat}) - Introduced parameter sizetit\cr -0.3 - 2013-10 (I. Andreu-Burillo, \email{isabel.andreu-burillo at ic3.cat}) - Introduced parameter show_conf\cr -1.0 - 2013-11 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +0.2 - 2013-03 (I. Andreu-Burillo, \email{isabel.andreu-burillo@ic3.cat}) - Introduced parameter sizetit\cr +0.3 - 2013-10 (I. Andreu-Burillo, \email{isabel.andreu-burillo@ic3.cat}) - Introduced parameter show_conf\cr +1.0 - 2013-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{dynamic} + diff --git a/man/ProbBins.Rd b/man/ProbBins.Rd index 8bb76330..6df49cc2 100644 --- a/man/ProbBins.Rd +++ b/man/ProbBins.Rd @@ -1,80 +1,89 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ProbBins.R \name{ProbBins} \alias{ProbBins} -\title{ -Computes Probabilistic Information of a Forecast Relative to a Threshold or a Quantile. -} -\description{ -Compute probabilistic bins of a set of forecast years ('fcyr') relative to the forecast climatology over the whole period of anomalies, optionally excluding the selected forecast years ('fcyr') or the forecast year for which the probabilistic bins are being computed (see 'compPeriod'). -} +\title{Computes Probabilistic Information of a Forecast Relative to a Threshold or a Quantile} \usage{ -ProbBins(ano, fcyr = 'all', thr, quantile = TRUE, posdates = 3, posdim = 2, - compPeriod = "Full period") +ProbBins(ano, fcyr = "all", thr, quantile = TRUE, posdates = 3, + posdim = 2, compPeriod = "Full period") } \arguments{ - \item{ano}{ -Array of anomalies from Ano().\cr -Must be of dimension (nexp/nobs, nmemb, nsdates, nleadtime, nlat, nlon) - } - \item{fcyr}{ -Indices of the forecast years of the anomalies which to compute the probabilistic bins for, or 'all' to compute the bins for all the years.\cr -Ex: c(1:5), c(1, 4), 4 or 'all'. - } - \item{thr}{ -Values used as thresholds to bin the anomalies. - } - \item{quantile}{ -If quantile is TRUE (default), the threshold ('thr') are quantiles.\cr -If quantile is FALSE the thresholds ('thr') introduced are the absolute thresholds of the bins. - } - \item{posdates}{ -Position of the dimension in \code{ano} that corresponds to the start dates (default = 3). - } - \item{posdim}{ -Position of the dimension in \code{ano} which will be combined with 'posdates' to compute the quantiles (default = 2, ensemble members). - } - \item{compPeriod}{ -Three options: "Full period"/"Without fcyr"/"Cross-validation" (The probabilities are computed with the terciles based on ano/ano with all 'fcyr's removed/cross-validation). The default is "Full period". - } +\item{ano}{Array of anomalies from Ano().\cr +Must be of dimension (nexp/nobs, nmemb, nsdates, nleadtime, nlat, nlon)} + +\item{fcyr}{Indices of the forecast years of the anomalies which to compute +the probabilistic bins for, or 'all' to compute the bins for all the +years.\cr +E.g., c(1:5), c(1, 4), 4 or 'all'.} + +\item{thr}{Values used as thresholds to bin the anomalies.} + +\item{quantile}{If quantile is TRUE (default), the threshold ('thr') +are quantiles.\cr +If quantile is FALSE the thresholds ('thr') introduced are the absolute +thresholds of the bins.} + +\item{posdates}{Position of the dimension in \code{ano} that corresponds to +the start dates (default = 3).} + +\item{posdim}{Position of the dimension in \code{ano} which will be combined +with 'posdates' to compute the quantiles (default = 2, ensemble members).} + +\item{compPeriod}{Three options: +"Full period"/"Without fcyr"/"Cross-validation" (The probabilities are +computed with the terciles based on ano/ano with all 'fcyr's +removed/cross-validation). The default is "Full period".} } \value{ Array with probabilistic information and dimensions:\cr -c(length('thr') + 1, length(fcyr), nmemb/nparam, nmod/nexp/nobs, nltime, nlat, nlon)\cr -The values along the first dimension take values 0 or 1 depending on which of the 'thr'+1 cathegories the forecast/observation at the corresponding grid point, time step, member and starting date belongs to. + c(length('thr') + 1, length(fcyr), nmemb/nparam, nmod/nexp/nobs, + nltime, nlat, nlon)\cr + The values along the first dimension take values 0 or 1 depending on which + of the 'thr'+1 cathegories the forecast/observation at the corresponding + grid point, time step, member and starting date belongs to. +} +\description{ +Compute probabilistic bins of a set of forecast years ('fcyr') relative to +the forecast climatology over the whole period of anomalies, optionally excluding +the selected forecast years ('fcyr') or the forecast year for which the +probabilistic bins are being computed (see 'compPeriod'). } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - output = 'lonlat', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } - \dontshow{ + output = 'lonlat', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } clim <- Clim(sampleMap$mod, sampleMap$obs) ano_exp <- Ano(sampleMap$mod, clim$clim_exp) PB <- ProbBins(ano_exp, fcyr = 3, thr = c(1/3, 2/3), quantile = TRUE, posdates = 3, - posdim = 2) + posdim = 2) + } \author{ History:\cr 1.0 - 2013 (F.Lienert) - Original code\cr -2.0 - 2014-03 (N. Gonzalez and V. Torralba, \email{veronica.torralba at bsc.es}) - Debugging -2.1 - 2017-02 (V. Torralba and N. Manubens, \email{veronica.torralba at bsc.es}) - Fix bug with cross-validation +2.0 - 2014-03 (N. Gonzalez and V. Torralba, \email{veronica.torralba@bsc.es}) - Debugging +2.1 - 2017-02 (V. Torralba and N. Manubens, \email{veronica.torralba@bsc.es}) - Fix bug with cross-validation } \keyword{datagen} + diff --git a/man/ProjectField.Rd b/man/ProjectField.Rd index 91d33039..36aa4455 100644 --- a/man/ProjectField.Rd +++ b/man/ProjectField.Rd @@ -1,60 +1,59 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ProjectField.R \name{ProjectField} \alias{ProjectField} -\title{ -Project Anomalies onto Modes of Variability -} -\description{ -Project anomalies onto modes of variability to get the temporal evolution of the EOF mode\cr -selected. Returns principal components (PCs) by area-weighted projection -onto EOF pattern (from \code{EOF()}). Able to handle NAs. -} +\title{Project Anomalies onto Modes of Variability} \usage{ ProjectField(ano, eof, mode = 1) } \arguments{ - \item{ano}{ -Array of forecast or observational reference anomalies from \code{Ano()} or -\code{Ano_CrossValid} with dimensions (number of forecast systems, ensemble -members, start dates, forecast horizons, latitudes, longitudes). - } - \item{eof}{ -R object with EOFs from \code{EOF}. - } - \item{mode}{ -Variability mode number in the provided EOF object which to project onto. - } +\item{ano}{Array of forecast or observational reference anomalies from +\code{Ano()} or \code{Ano_CrossValid} with dimensions (number of forecast +systems, ensemble members, start dates, forecast horizons, latitudes, +longitudes).} + +\item{eof}{R object with EOFs from \code{EOF}.} + +\item{mode}{Variability mode number in the provided EOF object which to +project onto.} } \value{ -Array of principal components in verification format (number of forecast -systems, ensemble members, start dates, forecast horizons). +Array of principal components in verification format (number of + forecast systems, ensemble members, start dates, forecast horizons). +} +\description{ +Project anomalies onto modes of variability to get the temporal evolution of +the EOF mode selected. Returns principal components (PCs) by +area-weighted projection onto EOF pattern (from \code{EOF()}). +Able to handle NAs. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } # Now ready to compute the EOFs and project. ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) @@ -70,40 +69,44 @@ mode1_obs <- ProjectField(ano$ano_obs, eof, 1) # for the last year of forecast plot(mode1_obs[1, 1, dim(sampleData$mod)[3], ], type = "l", ylim = c(-1, 1), lwd = 2) for (i in 1:dim(sampleData$mod)[2]) { - par(new = TRUE) - plot(mode1_exp[1, i, dim(sampleData$mod)[3], ], type = "l", col = rainbow(10)[i], - ylim = c(-15000, 15000)) + par(new = TRUE) + plot(mode1_exp[1, i, dim(sampleData$mod)[3], ], type = "l", col = rainbow(10)[i], + ylim = c(-15000, 15000)) } + } \author{ History:\cr 0.1 - 2012-03 (F. Lienert, \email{flienert at ic3.cat} - Original code 0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Bug-fixes:\cr - 1- Extra weighting of the anomalies before projection.\cr - 2- Reversion of the anomalies along latitudes.\cr - 3- Extra-normalisation not necessary.\cr + 1- Extra weighting of the anomalies before projection.\cr + 2- Reversion of the anomalies along latitudes.\cr + 3- Extra-normalisation not necessary.\cr 0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Bug-fixes:\cr - 1- Another extra-normalisation.\cr - 2- 15 lines to compute the em reduced to 1. + 1- Another extra-normalisation.\cr + 2- 15 lines to compute the em reduced to 1. 0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Normalization\cr by std before returning PCs to be coherent with EOF().\cr 0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Fixes:\cr - 1- Removal of lon, lat, ncpu and neofs argument unused\cr - 2- Security checks ano and eof consistency\cr - 3- Removal of the mask which is already contained in the EOFs\cr - 4- Removal of the PC normalization since we have chosen in\cr + 1- Removal of lon, lat, ncpu and neofs argument unused\cr + 2- Security checks ano and eof consistency\cr + 3- Removal of the mask which is already contained in the EOFs\cr + 4- Removal of the PC normalization since we have chosen in\cr \code{EOF()} to normalize the EOFs and multiply the PCs by the normalization\cr factor and the eigenvalue so that the restitution of the original field is \cr done simply by PC * EOFs\cr - 5 - The new convention in \code{EOF()} is to divide by the weights\cr + 5 - The new convention in \code{EOF()} is to divide by the weights\cr so that the reconstruction of the original field rather than the weighted\cr field is obtained by PC * EOFs. The EOFs need therefore to be multiplied \cr back by the weights before projection so that EOF * t(EOF) = 1\cr - 6 - Since W *X = PC * EOF if EOF is multiplied back by the weights,\cr + 6 - Since W *X = PC * EOF if EOF is multiplied back by the weights,\cr PC = W * X * t(EOF) and X the input field to be projected (X) needs to be\cr multiplied by W. Getting input dimensions. 1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN - (J.-P. Baudouin, \email{jean.baudouin at bsc.es}) - Example code and testing + (J.-P. Baudouin, \email{jean.baudouin at bsc.es}) - Example code and testing +} +\seealso{ +EOF, NAO, PlotBoxWhisker } -\seealso{EOF, NAO, PlotBoxWhisker} \keyword{datagen} + diff --git a/man/RMS.Rd b/man/RMS.Rd index 874fb969..acab1529 100644 --- a/man/RMS.Rd +++ b/man/RMS.Rd @@ -1,72 +1,78 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RMS.R \name{RMS} \alias{RMS} -\alias{.RMS} -\title{ -Computes Root Mean Square Error -} -\description{ -Computes the root mean square error for an array of forecasts, var_exp and an array of observations, var_obs, which should have the same dimensions except along the posloop dimension where the lengths can be different, with the number of experiments/models for var_exp (nexp) and the number of obserational datasets for var_obs (nobs).\cr -The RMSE is computed along the posRMS dimension which should correspond to the startdate dimension.\cr -If compROW is given, the RMSE is computed only if rows along the compROW dimension are complete between limits[1] and limits[2], i.e. there are no NAs between limits[1] and limits[2]. This option can be activated if the user wishes to account only for the forecasts for which observations are available at all leadtimes.\cr -Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr -The confidence interval relies on a chi2 distribution.\cr -\cr -.RMS provides the same functionality but taking a matrix of ensemble members as input (exp). -} +\title{Computes Root Mean Square Error} \usage{ -RMS(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, - limits = NULL, siglev = 0.95, conf = TRUE) - -.RMS(exp, obs, siglev = 0.95, conf = TRUE) +RMS(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, + limits = NULL, siglev = 0.95, conf = TRUE) } \arguments{ - \item{var_exp}{ -Matrix of experimental data. - } - \item{var_obs}{ -Matrix of observational data, same dimensions as var_exp except along posloop dimension, where the length can be nobs instead of nexp. - } - \item{posloop}{ -Dimension nobs and nexp. - } - \item{posRMS}{ -Dimension along which RMSE are to be computed (the dimension of the start dates). - } - \item{compROW}{ -Data taken into account only if (compROW)th row is complete.\cr -Default = NULL. - } - \item{limits}{ -Complete between limits[1] & limits[2]. Default = NULL. - } - \item{siglev}{ -Confidence level of the computed confidence interval. 0.95 by default. - } - \item{conf}{ -Whether to compute confidence interval or not. TRUE by default. - } - \item{exp}{ -N by M matrix of N forecasts from M ensemble members. - } - \item{obs}{ -Vector of the corresponding observations of length N. - } +\item{var_exp}{Matrix of experimental data.} + +\item{var_obs}{Matrix of observational data, same dimensions as var_exp +except along posloop dimension, where the length can be nobs instead of +nexp.} + +\item{posloop}{Dimension nobs and nexp.} + +\item{posRMS}{Dimension along which RMSE are to be computed (the dimension +of the start dates).} + +\item{compROW}{Data taken into account only if (compROW)th row is complete.\cr +Default = NULL.} + +\item{limits}{Complete between limits[1] & limits[2]. Default = NULL.} + +\item{siglev}{Confidence level of the computed confidence interval. 0.95 +by default.} + +\item{conf}{Whether to compute confidence interval or not. TRUE by default.} + +\item{exp}{N by M matrix of N forecasts from M ensemble members.} + +\item{obs}{Vector of the corresponding observations of length N.} } \value{ RMS: Array with dimensions:\cr - c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 3, all other dimensions of var_exp & var_obs except posRMS).\cr -The 3rd dimension corresponds to the lower limit of the 95\% confidence interval (only present if \code{conf = TRUE}), the RMSE, and the upper limit of the 95\% confidence interval (only present if \code{conf = TRUE}). \cr +c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 3, all + other dimensions of var_exp & var_obs except posRMS).\cr +The 3rd dimension corresponds to the lower limit of the 95\% confidence + interval (only present if \code{conf = TRUE}), the RMSE, and the upper + limit of the 95\% confidence interval (only present if + \code{conf = TRUE}).\cr \cr .RMS: - \item{$rms}{ +\itemize{ + \item{$rms}{ The root mean square error, - } - \item{$conf_low}{ + } + \item{$conf_low}{ Corresponding to the lower limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. - } - \item{$conf_high}{ + } + \item{$conf_high}{ Corresponding to the upper limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. - } + } +} +} +\description{ +Computes the root mean square error for an array of forecasts, var_exp and +an array of observations, var_obs, which should have the same dimensions +except along the posloop dimension where the lengths can be different, with +the number of experiments/models for var_exp (nexp) and the number of +obserational datasets for var_obs (nobs).\cr +The RMSE is computed along the posRMS dimension which should correspond to +the startdate dimension.\cr +If compROW is given, the RMSE is computed only if rows along the compROW +dimension are complete between limits[1] and limits[2], i.e. there are no +NAs between limits[1] and limits[2]. This option can be activated if the +user wishes to account only for the forecasts for which observations are +available at all leadtimes.\cr +Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr +The confidence interval relies on a chi2 distribution.\cr +\cr +.RMS provides the same functionality but taking a matrix of ensemble +members as input (exp). } \examples{ # Load sample data as in Load() example: @@ -83,24 +89,25 @@ dim_to_mean <- 2 # Mean along members required_complete_row <- 3 leadtimes_per_startdate <- 60 rms <- RMS(Mean1Dim(smooth_ano_exp, dim_to_mean), - Mean1Dim(smooth_ano_obs, dim_to_mean), - compROW = required_complete_row, - limits = c(ceiling((runmean_months + 1) / 2), - leadtimes_per_startdate - floor(runmean_months / 2))) + Mean1Dim(smooth_ano_obs, dim_to_mean), + compROW = required_complete_row, + limits = c(ceiling((runmean_months + 1) / 2), + leadtimes_per_startdate - floor(runmean_months / 2))) PlotVsLTime(rms, toptitle = "Root Mean Square Error", ytitle = "K", - monini = 11, limits = NULL, listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, hlines = c(0), - fileout = 'tos_rms.eps') + monini = 11, limits = NULL, listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, hlines = c(0), + fileout = 'tos_rms.eps') # The following example uses veriApply combined with .RMS instead of RMS - \dontrun{ + \dontrun{ require(easyVerification) RMS2 <- s2dverification:::.RMS rms2 <- veriApply("RMS2", - smooth_ano_exp, - # see ?veriApply for how to use the 'parallel' option - Mean1Dim(smooth_ano_obs, dim_to_mean), - tdim = 3, ensdim = 2) - } + smooth_ano_exp, + # see ?veriApply for how to use the 'parallel' option + Mean1Dim(smooth_ano_obs, dim_to_mean), + tdim = 3, ensdim = 2) + } + } \author{ History:\cr @@ -109,3 +116,4 @@ History:\cr 1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() } \keyword{datagen} + diff --git a/man/RMSSS.Rd b/man/RMSSS.Rd index b7a994a7..0db83e95 100644 --- a/man/RMSSS.Rd +++ b/man/RMSSS.Rd @@ -1,59 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RMSSS.R \name{RMSSS} \alias{RMSSS} -\alias{.RMSSS} -\title{ -Computes Root Mean Square Skill Score -} -\description{ -Computes the root mean square error skill score between an array of forecasts, var_exp and an array of observations, var_obs, which should have the same dimensions except along posloop where the lengths can be different, with the number of experiments/models for var_exp (nexp) and the number of obserational datasets for var_obs (nobs).\cr -RMSSS computes the Root Mean Square Skill Score of each jexp in 1:nexp against each jobs in 1:nobs which gives nexp x nobs RMSSS for each other grid point of the matrix (each latitude/longitude/level/leadtime).\cr -The RMSSS are computed along the posRMS dimension which should correspond to the startdate dimension.\cr -The p-value is optionally provided by a one-sided Fisher test.\cr -\cr -.RMSSS provides the same functionality but taking a matrix of ensemble members as input (exp). -} +\title{Computes Root Mean Square Skill Score} \usage{ RMSSS(var_exp, var_obs, posloop = 1, posRMS = 2, pval = TRUE) - -.RMSSS(exp, obs, pval = TRUE) } \arguments{ - \item{var_exp}{ -Array of experimental data. - } - \item{var_obs}{ -Array of observational data, same dimensions as var_exp except along posloop dimension, where the length can be nobs instead of nexp. - } - \item{posloop}{ -Dimension nobs and nexp. - } - \item{posRMS}{ -Dimension along which the RMSE are to be computed (the dimension of the start dates). - } - \item{pval}{ -Whether to compute or not the p-value of the test Ho : RMSSS = 0. TRUE by default. - } - \item{exp}{ -N by M matrix of N forecasts from M ensemble members. - } - \item{obs}{ -Vector of the corresponding observations of length N. - } +\item{var_exp}{Array of experimental data.} + +\item{var_obs}{Array of observational data, same dimensions as var_exp +except along posloop dimension, where the length can be nobs instead of +nexp.} + +\item{posloop}{Dimension nobs and nexp.} + +\item{posRMS}{Dimension along which the RMSE are to be computed (the +dimension of the start dates).} + +\item{pval}{Whether to compute or not the p-value of the test Ho : +RMSSS = 0. TRUE by default.} + +\item{exp}{N by M matrix of N forecasts from M ensemble members.} + +\item{obs}{Vector of the corresponding observations of length N.} } \value{ RMSSS: Array with dimensions:\cr - c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, all other dimensions of var_exp & var_obs except posRMS).\cr -The 3rd dimension corresponds to the RMSSS and, if \code{pval = TRUE}, the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr +c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, + all other dimensions of var_exp & var_obs except posRMS).\cr +The 3rd dimension corresponds to the RMSSS and, if \code{pval = TRUE}, + the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr \cr .RMSSS: - \itemize{ - \item{$rmsss}{ -The RMSSS. - } - \item{$p_val}{ -Corresponds to the p values (only present if \code{pval = TRUE}) for the RMSSS. - } - } +\itemize{ + \itemize{ + \item{$rmsss}{ + The RMSSS. + } + \item{$p_val}{ + Corresponds to the p values (only present if \code{pval = TRUE}) for + the RMSSS. + } + } +} +} +\description{ +Computes the root mean square error skill score between an array of +forecasts, var_exp and an array of observations, var_obs, which should +have the same dimensions except along posloop where the lengths can be +different, with the number of experiments/models for var_exp (nexp) and +the number of obserational datasets for var_obs (nobs).\cr +RMSSS computes the Root Mean Square Skill Score of each jexp in 1:nexp +against each jobs in 1:nobs which gives nexp x nobs RMSSS for each other +grid point of the matrix (each latitude/longitude/level/leadtime).\cr +The RMSSS are computed along the posRMS dimension which should correspond +to the startdate dimension.\cr +The p-value is optionally provided by a one-sided Fisher test.\cr +\cr +.RMSSS provides the same functionality but taking a matrix of ensemble +members as input (exp). } \examples{ # Load sample data as in Load() example: @@ -66,23 +72,25 @@ rmsss_plot <- array(dim = c(dim(rmsss)[1:2], 4, dim(rmsss)[4])) rmsss_plot[, , 2, ] <- rmsss[, , 1, ] rmsss_plot[, , 4, ] <- rmsss[, , 2, ] PlotVsLTime(rmsss_plot, toptitle = "Root Mean Square Skill Score", ytitle = "", - monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), - fileout = 'tos_rmsss.eps') + monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), + fileout = 'tos_rmsss.eps') # The following example uses veriApply combined with .RMSSS instead of RMSSS - \dontrun{ + \dontrun{ require(easyVerification) RMSSS2 <- s2dverification:::.RMSSS rmsss2 <- veriApply("RMSSS2", ano_exp, - # see ?veriApply for how to use the 'parallel' option - Mean1Dim(ano_obs, 2), - tdim = 3, ensdim = 2) - } + # see ?veriApply for how to use the 'parallel' option + Mean1Dim(ano_obs, 2), + tdim = 3, ensdim = 2) + } + } \author{ History:\cr -0.1 - 2012-04 (V. Guemas, \email{vguemas at bsc.es}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN\cr -1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +0.1 - 2012-04 (V. Guemas, \email{vguemas@bsc.es}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN\cr +1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() } \keyword{datagen} + diff --git a/man/RatioRMS.Rd b/man/RatioRMS.Rd index aa179b76..48f63ec1 100644 --- a/man/RatioRMS.Rd +++ b/man/RatioRMS.Rd @@ -1,91 +1,86 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RatioRMS.R \name{RatioRMS} \alias{RatioRMS} -\alias{.RatioRMS} -\title{ -Computes the Ratio Between The RMSE of Two Experiments -} -\description{ -Calculates the ratio of the RMSE for two forecasts of the same observations.\cr -The ratio RMSE(ens, obs) / RMSE(ens.ref, obs) is output.\cr -The p-value is provided by a two-sided Fischer test.\cr -\cr -.RatioRMS provides the same functionality but taking two matrices of ensemble members (ens and ens.ref) as input. -} +\title{Computes the Ratio Between The RMSE of Two Experiments} \usage{ RatioRMS(var_exp1, var_exp2, var_obs, posRMS = 1, pval = TRUE) - -.RatioRMS(exp, exp_ref, obs, pval = TRUE) } \arguments{ - \item{var_exp1}{ -Array of experimental data 1. - } - \item{var_exp2}{ -Array of experimental data 2. - } - \item{var_obs}{ -Array of observations. - } - \item{posRMS}{ -Dimension along which the RMSE are to be computed = the position of the start dates. - } - \item{pval}{ -Whether to compute the p-value of Ho : RMSE1/RMSE2 = 1 or not. TRUE by default. - } - \item{exp}{ -Matrix of experimental data 1. - } - \item{exp_ref}{ -Matrix of experimental data 2. - } - \item{obs}{ -Vector of observations. - } +\item{var_exp1}{Array of experimental data 1.} + +\item{var_exp2}{Array of experimental data 2.} + +\item{var_obs}{Array of observations.} + +\item{posRMS}{Dimension along which the RMSE are to be computed = the +position of the start dates.} + +\item{pval}{Whether to compute the p-value of Ho : RMSE1/RMSE2 = 1 or not. +TRUE by default.} + +\item{exp}{Matrix of experimental data 1.} + +\item{exp_ref}{Matrix of experimental data 2.} + +\item{obs}{Vector of observations.} } \value{ RatioRMS:\cr -Matrix with the same dimensions as var_exp1/var_exp2/var_obs except along posRMS where the dimension has length 2 if 'pval = TRUE', or 1 otherwise. The dimension of length 2 corresponds to the ratio between the RMSE (RMSE1/RMSE2) and the p-value of the two-sided Fisher test with Ho: RMSE1/RMSE2 = 1.\cr +Matrix with the same dimensions as var_exp1/var_exp2/var_obs except along + posRMS where the dimension has length 2 if 'pval = TRUE', or 1 otherwise. + The dimension of length 2 corresponds to the ratio between the RMSE + (RMSE1/RMSE2) and the p-value of the two-sided Fisher test with Ho: + RMSE1/RMSE2 = 1.\cr \cr .RatioRMS:\cr - \itemize{ - \item{ratiorms}{The ratio of the RMSE of the two experimental datasets} - \item{p_val}{The p-value} - } + \itemize{ + \item{ratiorms}{The ratio of the RMSE of the two experimental datasets} + \item{p_val}{The p-value} + } +} +\description{ +Calculates the ratio of the RMSE for two forecasts of the same observations.\cr +The ratio RMSE(ens, obs) / RMSE(ens.ref, obs) is output.\cr +The p-value is provided by a two-sided Fischer test.\cr +\cr +.RatioRMS provides the same functionality but taking two matrices of +ensemble members (ens and ens.ref) as input. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - output = 'lonlat', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } - \dontshow{ + output = 'lonlat', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } # Compute DJF seasonal means and anomalies. leadtimes_dimension <- 4 initial_month <- 11 mean_start_month <- 12 mean_stop_month <- 2 sampleData$mod <- Season(sampleData$mod, leadtimes_dimension, initial_month, - mean_start_month, mean_stop_month) + mean_start_month, mean_stop_month) sampleData$obs <- Season(sampleData$obs, leadtimes_dimension, initial_month, - mean_start_month, mean_stop_month) + mean_start_month, mean_stop_month) clim <- Clim(sampleData$mod, sampleData$obs) ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) @@ -99,24 +94,25 @@ ano_exp_2 <- Subset(ano_exp_2, c('dataset', 'ftime'), list(1, 1), drop = 'select ano_obs <- Subset(ano_obs, c('dataset', 'ftime'), list(1, 1), drop = 'selected') # Compute ensemble mean and provide as inputs to RatioRMS. rrms <- RatioRMS(Mean1Dim(ano_exp_1, 1), - Mean1Dim(ano_exp_2, 1), - Mean1Dim(ano_obs, 1)) + Mean1Dim(ano_exp_2, 1), + Mean1Dim(ano_obs, 1)) # Plot the RatioRMS for the first forecast time step. PlotEquiMap(rrms[1, , ], sampleData$lon, sampleData$lat, - toptitle = 'Ratio RMSE') + toptitle = 'Ratio RMSE') # The following example uses veriApply combined with .RatioRMS instead of RatioRMS - \dontrun{ + \dontrun{ require(easyVerification) # The name of the function has to end in 'ss' in order for veriApply() to # detect it as a skill score. RatioRMSss <- s2dverification:::.RatioRMS rrms2 <- veriApply("RatioRMSss", ano_exp_1, - # see ?veriApply for how to use the 'parallel' option - Mean1Dim(ano_obs, 1), - ano_exp_2, - tdim = 2, ensdim = 1) - } + # see ?veriApply for how to use the 'parallel' option + Mean1Dim(ano_obs, 1), + ano_exp_2, + tdim = 2, ensdim = 1) + } + } \author{ History:\cr @@ -125,3 +121,4 @@ History:\cr 1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() } \keyword{datagen} + diff --git a/man/RatioSDRMS.Rd b/man/RatioSDRMS.Rd index 1e6a9f9d..23f07cdb 100644 --- a/man/RatioSDRMS.Rd +++ b/man/RatioSDRMS.Rd @@ -1,59 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RatioSDRMS.R \name{RatioSDRMS} \alias{RatioSDRMS} -\alias{.RatioSDRMS} -\title{ -Computes the ratio between the ensemble spread and RMSE -} -\description{ -Arrays var_exp & var_obs should have dimensions between\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime)\cr -and\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr -The ratio between the standard deviation of the members around the ensemble mean in var_exp and the RMSE between var_exp and var_obs is output for each experiment and each observational dataset.\cr -The p-value is provided by a one-sided Fischer test.\cr -\cr -.RatioSDRMS provides the same functionality but taking a matrix of ensemble members as input (exp). -} +\title{Computes the ratio between the ensemble spread and RMSE} \usage{ RatioSDRMS(var_exp, var_obs, pval = TRUE) - -.RatioSDRMS(exp, obs, pval = TRUE) } \arguments{ - \item{var_exp}{ -Model data:\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to\cr - c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) - } - \item{var_obs}{ -Observational data:\cr - c(nobs, nmemb, nsdates, nltime) up to\cr - c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon) - } - \item{pval}{ -Whether to compute the p-value of Ho : SD/RMSE = 1 or not. - } - \item{exp}{ -N by M matrix of N forecasts from M ensemble members. - } - \item{obs}{ -Vector of the corresponding observations of length N. - } +\item{var_exp}{Model data:\cr +c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to\cr +c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)} + +\item{var_obs}{Observational data:\cr +c(nobs, nmemb, nsdates, nltime) up to\cr +c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon)} + +\item{pval}{Whether to compute the p-value of Ho : SD/RMSE = 1 or not.} + +\item{exp}{N by M matrix of N forecasts from M ensemble members.} + +\item{obs}{Vector of the corresponding observations of length N.} } \value{ -RatioSDRMS: Array with dimensions c(nexp/nmod, nobs, 1 or 2, nltime) up to - c(nexp/nmod, nobs, 1 or 2, nltime, nlevel, nlat, nlon). \cr -The 3rd dimension corresponds to the ratio (SD/RMSE) and the p.value (only present if \code{pval = TRUE}) of the one-sided Fisher test with Ho: SD/RMSE = 1.\cr +RatioSDRMS: Array with dimensions c(nexp/nmod, nobs, 1 or 2, nltime) + up to c(nexp/nmod, nobs, 1 or 2, nltime, nlevel, nlat, nlon).\cr +The 3rd dimension corresponds to the ratio (SD/RMSE) and the p.value +(only present if \code{pval = TRUE}) of the one-sided Fisher test with +Ho: SD/RMSE = 1.\cr \cr .RatioSDRMS: - \itemize{ - \item{$ratio}{ -The ratio of the ensemble spread and RMSE, - } - \item{$p_val}{ -Corresponds to the p values of the ratio (only present if \code{pval = TRUE}). - } - } + \itemize{ + \item{$ratio}{ + The ratio of the ensemble spread and RMSE, + } + \item{$p_val}{ + Corresponds to the p values of the ratio (only present if + \code{pval = TRUE}). + } + } +} +\description{ +Arrays var_exp & var_obs should have dimensions between\cr +c(nmod/nexp, nmemb/nparam, nsdates, nltime)\cr +and\cr +c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr +The ratio between the standard deviation of the members around the ensemble +mean in var_exp and the RMSE between var_exp and var_obs is output for each +experiment and each observational dataset.\cr +The p-value is provided by a one-sided Fischer test.\cr +\cr +.RatioSDRMS provides the same functionality but taking a matrix of ensemble +members as input (exp). } \examples{ # Load sample data as in Load() example: @@ -64,20 +61,21 @@ rsdrms_plot <- array(dim = c(dim(rsdrms)[1:2], 4, dim(rsdrms)[4])) rsdrms_plot[, , 2, ] <- rsdrms[, , 1, ] rsdrms_plot[, , 4, ] <- rsdrms[, , 2, ] PlotVsLTime(rsdrms_plot, toptitle = "Ratio ensemble spread / RMSE", ytitle = "", - monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), - listobs = c('ERSST'), biglab = FALSE, siglev = TRUE, - fileout = 'tos_rsdrms.eps') + monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), + listobs = c('ERSST'), biglab = FALSE, siglev = TRUE, + fileout = 'tos_rsdrms.eps') # The following example uses veriApply combined with .RatioSDRMS instead of RatioSDRMS - \dontrun{ + \dontrun{ require(easyVerification) RatioSDRMS2 <- s2dverification:::.RatioSDRMS rsdrms2 <- veriApply("RatioSDRMS2", - sampleData$mod, - # see ?veriApply for how to use the 'parallel' option - Mean1Dim(sampleData$obs, 2), - tdim = 3, ensdim = 2) - } + sampleData$mod, + # see ?veriApply for how to use the 'parallel' option + Mean1Dim(sampleData$obs, 2), + tdim = 3, ensdim = 2) + } + } \author{ History:\cr @@ -86,3 +84,4 @@ History:\cr 1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() } \keyword{datagen} + diff --git a/man/Regression.Rd b/man/Regression.Rd index da4dca37..e65dd3fd 100644 --- a/man/Regression.Rd +++ b/man/Regression.Rd @@ -1,67 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Regression.R \name{Regression} \alias{Regression} -\title{ -Computes The Regression Of An Array On Another Along A Dimension -} -\description{ -Computes the regression of the input matrice vary on the input matrice varx along the posREG dimension by least square fitting. Provides the slope of the regression, the associated confidence interval, and the intercept.\cr -Provides also the vary data filtered out from the regression onto varx.\cr -The confidence interval relies on a student-T distribution. -} +\title{Computes The Regression Of An Array On Another Along A Dimension} \usage{ Regression(vary, varx, posREG = 2) } \arguments{ - \item{vary}{ -Array of any number of dimensions up to 10. - } - \item{varx}{ -Array of any number of dimensions up to 10. Same dimensions as vary. - } - \item{posREG}{ -Position along which to compute the regression. - } +\item{vary}{Array of any number of dimensions up to 10.} + +\item{varx}{Array of any number of dimensions up to 10. +Same dimensions as vary.} + +\item{posREG}{Position along which to compute the regression.} } \value{ - \item{$regression}{ -Array with same dimensions as varx and vary except along posREG dimension which is replaced by a length 4 dimension, corresponding to the lower limit of the 95\% confidence interval, the slope, the upper limit of the 95\% confidence interval and the intercept. - } - \item{$filtered}{ -Same dimensions as vary filtered out from the regression onto varx along the posREG dimension. - } +\itemize{ + \item{$regression}{ + Array with same dimensions as varx and vary except along posREG + dimension which is replaced by a length 4 dimension, corresponding + to the lower limit of the 95\% confidence interval, the slope, + the upper limit of the 95\% confidence interval and the intercept. + } + \item{$filtered}{ + Same dimensions as vary filtered out from the regression onto varx + along the posREG dimension. + } +} +} +\description{ +Computes the regression of the input matrice vary on the input matrice varx +along the posREG dimension by least square fitting. Provides the slope of +the regression, the associated confidence interval, and the intercept.\cr +Provides also the vary data filtered out from the regression onto varx.\cr +The confidence interval relies on a student-T distribution. } \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - output = 'lonlat', latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } - \dontshow{ + output = 'lonlat', latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } sampleData$mod <- Season(sampleData$mod, 4, 11, 12, 2) sampleData$obs <- Season(sampleData$obs, 4, 11, 12, 2) reg <- Regression(Mean1Dim(sampleData$mod, 2), - Mean1Dim(sampleData$obs, 2), 2) + Mean1Dim(sampleData$obs, 2), 2) PlotEquiMap(reg$regression[1, 2, 1, , ], sampleData$lon, sampleData$lat, - toptitle='Regression of the prediction on the observations', - sizetit = 0.5) + toptitle='Regression of the prediction on the observations', + sizetit = 0.5) + } \author{ History:\cr @@ -69,3 +75,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/SVD.Rd b/man/SVD.Rd index 3c157e22..0810f8a0 100644 --- a/man/SVD.Rd +++ b/man/SVD.Rd @@ -1,12 +1,66 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/SVD.R \name{SVD} \alias{SVD} -\title{ -Single Value Decomposition (Maximum Covariance Analysis) +\title{Single Value Decomposition (Maximum Covariance Analysis)} +\usage{ +SVD(vary, varx, laty = NULL, latx = NULL, nmodes = 15, corr = FALSE, + weight = TRUE) +} +\arguments{ +\item{vary}{Array containing the anomalies field for the predictor. The +expected dimensions are c(n. of time steps, n. of latitudes, n. of +longitudes).} + +\item{varx}{Array containing the anomalies field for the predictand. The +expected dimensions are c(n. of time steps, n. of latitudes, n. of +longitudes).} + +\item{laty}{Vector of latitudes of the array \code{vary}. Only required if +\code{weight = TRUE}.} + +\item{latx}{Vector of latitudes of the array \code{varx}. Only required if +\code{weight = TRUE}.} + +\item{nmodes}{Number of ECs/MCAs/modes retained and provided in the outputs.} + +\item{corr}{Whether to compute the MCA over a covariance matrix (FALSE) or +a correlation matrix (TRUE).} + +\item{weight}{Whether to apply latitude weights on the input fields or not. +TRUE by default.} +} +\value{ +\itemize{ + \item{$SC}{ +Vector of squared covariance (n. of modes). + } + \item{$SCFs}{ + Vector of squared covariance fractions (n. of modes). + } + \item{$RUVs}{ + Vector of correlations between expansion coefficients (n. of modes). + } + \item{$ECs_U}{ + Array of expansion coefficients of predictor field (n. of time steps, + n. of modes). + } + \item{$MCAs_U}{ + Array of covariability patterns of predictor field (c(dim), n. of modes). + } + \item{$ECs_V}{ + Array of expansion coefficients of predictand field (n. of time steps, + n. of modes). + } + \item{$MCAs_V}{ + Array of covariability patterns of predictand field (c(dim), n. of modes). + } +} } \description{ Computes a Maximum Covariance Analysis (MCA) between vary and varx, both of dimensions c(n. of time steps, n. of latitudes, n. of longitudes), each -over a region of interest, e.g.: prlr over Europe and tos over North Atlantic. +over a region of interest, e.g.: prlr over Europe and tos over North Atlantic. The input fields are latitude-weighted by default (can be adjustable via \code{weight}).\cr Returns a vector of squared covariance fraction (SCFs) explained by @@ -19,100 +73,45 @@ and its expansion coefficient.\cr The MCA is computed by default with the covariance matrix. It can be computed with the correlation matrix by setting \code{corr = TRUE}. } -\usage{ -SVD(vary, varx, laty = NULL, latx = NULL, nmodes = 15, corr = FALSE, - weight = TRUE) -} -\arguments{ - \item{vary}{ -Array containing the anomalies field for the predictor. The expected -dimensions are c(n. of time steps, n. of latitudes, n. of longitudes). - } - \item{varx}{ -Array containing the anomalies field for the predictand. The expected -dimensions are c(n. of time steps, n. of latitudes, n. of longitudes). - } - \item{laty}{ -Vector of latitudes of the array \code{vary}. Only required if -\code{weight = TRUE}. - } - \item{latx}{ -Vector of latitudes of the array \code{varx}. Only required if -\code{weight = TRUE}. - } - \item{nmodes}{ -Number of ECs/MCAs/modes retained and provided in the outputs. - } - \item{corr}{ -Whether to compute the MCA over a covariance matrix (FALSE) or a correlation -matrix (TRUE). - } - \item{weight}{ -Whether to apply latitude weights on the input fields or not. TRUE by -default. - } -} -\value{ - \item{$SC}{ -Vector of squared covariance (n. of modes). - } - \item{$SCFs}{ -Vector of squared covariance fractions (n. of modes). - } - \item{$RUVs}{ -Vector of correlations between expansion coefficients (n. of modes). - } - \item{$ECs_U}{ -Array of expansion coefficients of predictor field (n. of time steps, n. of modes). - } - \item{$MCAs_U}{ -Array of covariability patterns of predictor field (c(dim), n. of modes). - } - \item{$ECs_V}{ -Array of expansion coefficients of predictand field (n. of time steps, n. of modes). - } - \item{$MCAs_V}{ -Array of covariability patterns of predictand field (c(dim), n. of modes). - } -} \examples{ # See examples on Load() to understand the first lines in this example - \dontrun{ + \dontrun{ data_path <- system.file('sample_data', package = 's2dverification') expA <- list(name = 'experiment', path = file.path(data_path, - 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', - '$VAR_NAME$_$START_DATE$.nc')) + 'model/$EXP_NAME$/$STORE_FREQ$_mean/$VAR_NAME$_3hourly', + '$VAR_NAME$_$START_DATE$.nc')) obsX <- list(name = 'observation', path = file.path(data_path, - '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', - '$VAR_NAME$_$YEAR$$MONTH$.nc')) + '$OBS_NAME$/$STORE_FREQ$_mean/$VAR_NAME$', + '$VAR_NAME$_$YEAR$$MONTH$.nc')) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(expA), list(obsX), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } - \dontshow{ + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } + \dontshow{ startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), - c('observation'), startDates, - leadtimemin = 1, - leadtimemax = 4, - output = 'lonlat', - latmin = 27, latmax = 48, - lonmin = -12, lonmax = 40) - } + c('observation'), startDates, + leadtimemin = 1, + leadtimemax = 4, + output = 'lonlat', + latmin = 27, latmax = 48, + lonmin = -12, lonmax = 40) + } # This example computes the ECs and MCAs along forecast horizons and plots the # one that explains the greatest amount of variability. The example data is # very low resolution so it does not make a lot of sense. ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) mca <- SVD(Mean1Dim(ano$ano_exp, 2)[1, , 1, , ], - Mean1Dim(ano$ano_obs, 2)[1, , 1, , ], - sampleData$lat, sampleData$lat) + Mean1Dim(ano$ano_obs, 2)[1, , 1, , ], + sampleData$lat, sampleData$lat) PlotEquiMap(mca$MCAs_U[1, , ], sampleData$lon, sampleData$lat) plot(mca$ECs_U[1, ]) PlotEquiMap(mca$MCAs_V[1, , ], sampleData$lon, sampleData$lat) plot(mca$ECs_V[1, ]) + } \author{ History:\cr @@ -120,3 +119,4 @@ History:\cr 1.0 - 2016-04 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN } \keyword{datagen} + diff --git a/man/Season.Rd b/man/Season.Rd index aa143e27..b7aa1ff7 100644 --- a/man/Season.Rd +++ b/man/Season.Rd @@ -1,33 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Season.R \name{Season} \alias{Season} -\title{ -Computes Seasonal Means -} -\description{ -Computes seasonal means on timeseries organized in a array of any number of dimensions up to 10 dimensions where the time dimension is one of those 10 dimensions. -} +\title{Computes Seasonal Means} \usage{ Season(var, posdim = 4, monini, moninf, monsup) } \arguments{ - \item{var}{ -Array containing the timeseries along one of its dimensions. - } - \item{posdim}{ -Dimension along which to compute seasonal means = Time dimension - } - \item{monini}{ -First month of the time series: 1 to 12. - } - \item{moninf}{ -Month when to start the seasonal means: 1 to 12. - } - \item{monsup}{ -Month when to stop the seasonal means: 1 to 12. - } +\item{var}{Array containing the timeseries along one of its dimensions.} + +\item{posdim}{Dimension along which to compute seasonal means = Time +dimension.} + +\item{monini}{an integer indicating the first month of the time series: 1 to +12.} + +\item{moninf}{an integer indicating the month when to start the seasonal +means: 1 to 12.} + +\item{monsup}{an integer indicating the month when to stop the seasonal +means: 1 to 12.} } \value{ -Array with the same dimensions as var except along the posdim dimension whose length corresponds to the number of seasons. Partial seasons are not accounted for. +Array with the same dimensions as var except along the posdim + dimension whose length corresponds to the number of seasons. Partial + seasons are not accounted for. +} +\description{ +Computes seasonal means on timeseries organized in a array of any number of +dimensions up to 10 dimensions where the time dimension is one of those 10 +dimensions. } \examples{ # Load sample data as in Load() example: @@ -37,12 +39,12 @@ initial_month <- 11 mean_start_month <- 12 mean_stop_month <- 2 season_means_mod <- Season(sampleData$mod, leadtimes_dimension, initial_month, - mean_start_month, mean_stop_month) + mean_start_month, mean_stop_month) season_means_obs <- Season(sampleData$obs, leadtimes_dimension, initial_month, - mean_start_month, mean_stop_month) + mean_start_month, mean_stop_month) PlotAno(season_means_mod, season_means_obs, startDates, - toptitle = paste('winter (DJF) temperatures'), ytitle = c('K'), - legends = 'ERSST', biglab = FALSE, fileout = 'tos_season_means.eps') + toptitle = paste('winter (DJF) temperatures'), ytitle = c('K'), + legends = 'ERSST', biglab = FALSE, fileout = 'tos_season_means.eps') } \author{ History:\cr @@ -50,3 +52,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/SelIndices.Rd b/man/SelIndices.Rd index b6b1795f..09fdf055 100644 --- a/man/SelIndices.Rd +++ b/man/SelIndices.Rd @@ -1,28 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/SelIndices.R \name{SelIndices} \alias{SelIndices} -\title{ -Slices A Matrix Along A Dimension -} -\description{ -This function selects a subset of ensemble members from an array containing any number of dimensions. -} +\title{Slices A Matrix Along A Dimension} \usage{ SelIndices(var, posdim, limits) } \arguments{ - \item{var}{ -An array with any number of dimensions. - } - \item{posdim}{ -The dimension along which the ensemble subset should be selected. - } - \item{limits}{ -The lower and upper limits for the selection of ensemble members along the posdim dimension. - } +\item{var}{An array with any number of dimensions.} + +\item{posdim}{The dimension along which the ensemble subset should be +selected.} + +\item{limits}{The lower and upper limits for the selection of ensemble +members along the posdim dimension.} } \value{ The subsetted array. } +\description{ +This function selects a subset of ensemble members from an array containing +any number of dimensions. +} \examples{ a <- array(rnorm(24), dim = c(2, 3, 4, 1)) print(a) @@ -30,6 +29,7 @@ print(a[, , 2:3, ]) print(dim(a[, , 2:3, ])) print(SelIndices(a, 3, c(2, 3))) print(dim(SelIndices(a, 3, c(2, 3)))) + } \author{ History:\cr @@ -37,3 +37,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/Smoothing.Rd b/man/Smoothing.Rd index 841fb052..80bda29a 100644 --- a/man/Smoothing.Rd +++ b/man/Smoothing.Rd @@ -1,27 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Smoothing.R \name{Smoothing} \alias{Smoothing} -\title{ -Smoothes An Array Along A Dimension -} -\description{ -Smoothes an array of any number of dimensions along one of its dimensions -} +\title{Smoothes An Array Along A Dimension} \usage{ Smoothing(var, runmeanlen = 12, numdimt = 4) } \arguments{ - \item{var}{ -Array to be smoothed along one of its dimension (typically the forecast time dimension). - } - \item{runmeanlen}{ -Running mean length in number of sampling units (typically months). - } - \item{numdimt}{ -Dimension to smooth. - } +\item{var}{Array to be smoothed along one of its dimension (typically the +forecast time dimension).} + +\item{runmeanlen}{Running mean length in number of sampling units +(typically months).} + +\item{numdimt}{Dimension to smooth.} } \value{ -Array with same the dimensions as 'var' but smoothed along the 'numdimt'-th dimension. +Array with same the dimensions as 'var' but smoothed along the + 'numdimt'-th dimension. +} +\description{ +Smoothes an array of any number of dimensions along one of its dimensions. } \examples{ # Load sample data as in Load() example: @@ -34,14 +33,17 @@ dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, - toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", - fileout = "tos_smoothed_ano.eps") + toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", + fileout = "tos_smoothed_ano.eps") + } \author{ History:\cr 0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN 1.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Adding -security checks, fixing computation in cases where runmeanlen is odd and making it able to work on arrays of any number of dimensions. + security checks, fixing computation in cases where runmeanlen is odd and + making it able to work on arrays of any number of dimensions. } \keyword{datagen} + diff --git a/man/Spectrum.Rd b/man/Spectrum.Rd index eda82779..2f93d82e 100644 --- a/man/Spectrum.Rd +++ b/man/Spectrum.Rd @@ -1,31 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Spectrum.R \name{Spectrum} \alias{Spectrum} \title{Estimates Frequency Spectrum} -\description{ -This function estimates the frequency spectrum of the xdata array together with its 95\% and 99\% significance level. The output is provided as an array with dimensions c(number of frequencies, 4). The column contains the frequency values, the power, the 95\% significance level and the 99\% one.\cr -The spectrum estimation relies on a R built-in function and the significance levels are estimated by a Monte-Carlo method. +\usage{ +Spectrum(xdata) } -\usage{Spectrum(xdata)} \arguments{ - \item{xdata}{Array of which the frequency spectrum is required} +\item{xdata}{Array of which the frequency spectrum is required.} +} +\value{ +Frequency spectrum with dimensions c(number of frequencies, 4). The + column contains the frequency values, the power, the 95\% significance + level and the 99\% one. +} +\description{ +This function estimates the frequency spectrum of the xdata array together +with its 95\% and 99\% significance level. The output is provided as an +array with dimensions c(number of frequencies, 4). The column contains the +frequency values, the power, the 95\% significance level and the 99\% one.\cr +The spectrum estimation relies on a R built-in function and the significance +levels are estimated by a Monte-Carlo method. } -\value{Frequency spectrum with dimensions c(number of frequencies, 4). The column contains the frequency values, the power, the 95\% significance level and the 99\% one.} \examples{ # Load sample data as in Load() example: example(Load) ensmod <- Mean1Dim(sampleData$mod, 2) for (jstartdate in 1:3) { - spectrum <- Spectrum(ensmod[1, jstartdate, ]) - for (jlen in 1:dim(spectrum)[1]) { - if (spectrum[jlen, 2] > spectrum[jlen, 4]) { - ensmod[1, jstartdate, ] <- Filter(ensmod[1, jstartdate, ], - spectrum[jlen, 1]) - } - } + spectrum <- Spectrum(ensmod[1, jstartdate, ]) + for (jlen in 1:dim(spectrum)[1]) { + if (spectrum[jlen, 2] > spectrum[jlen, 4]) { + ensmod[1, jstartdate, ] <- Filter(ensmod[1, jstartdate, ], + spectrum[jlen, 1]) + } + } } PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = - 'filtered_ensemble_mean.eps') + 'filtered_ensemble_mean.eps') + } \author{ History:\cr @@ -33,3 +46,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/Spread.Rd b/man/Spread.Rd index 2d9007cc..70e20239 100644 --- a/man/Spread.Rd +++ b/man/Spread.Rd @@ -1,52 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Spread.R \name{Spread} \alias{Spread} -\title{ -Computes InterQuartile Range, Maximum-Minimum, Standard Deviation and Median Absolute Deviation of the Ensemble Members -} -\description{ -Computes the InterQuartile Range, the Maximum minus Mininum, the Standard Deviation and the Median Absolute Deviation along the list of dimensions provided by the posdim argument (typically along the ensemble member and start date dimension).\cr -The confidence interval is optionally computed by bootstrapping. -} +\title{Computes InterQuartile Range, Maximum-Minimum, Standard Deviation and +Median Absolute Deviation of the Ensemble Members} \usage{ Spread(var, posdim = 2, narm = TRUE, siglev = 0.95, conf = TRUE) } \arguments{ - \item{var}{ -Matrix of any number of dimensions up to 10. - } - \item{posdim}{ -List of dimensions along which to compute IQR/MaxMin/SD/MAD. - } - \item{narm}{ -TRUE/FALSE if NA removed/kept for computation. Default = TRUE. - } - \item{siglev}{ -Confidence level of the computed confidence interval. 0.95 by default. - } - \item{conf}{ -Whether to compute the confidence intervals or not. TRUE by default. - } -} -\details{ +\item{var}{Matrix of any number of dimensions up to 10.} + +\item{posdim}{List of dimensions along which to compute IQR/MaxMin/SD/MAD.} + +\item{narm}{TRUE/FALSE if NA removed/kept for computation. Default = TRUE.} + +\item{siglev}{Confidence level of the computed confidence interval. +0.95 by default.} + +\item{conf}{Whether to compute the confidence intervals or not. + TRUE by default. + Example: -------- -To compute IQR, Max-Min, SD & MAD accross the members and start dates of var output from \code{Load()} or \code{Ano()} or \code{Ano_CrossValid()}, call:\cr - spread(var, posdim = c(2, 3), narm = TRUE) +To compute IQR, Max-Min, SD & MAD accross the members and start dates of +var output from \code{Load()} or \code{Ano()} or \code{Ano_CrossValid()}, +call:\cr + spread(var, posdim = c(2, 3), narm = TRUE)} } \value{ -Matrix with the same dimensions as var except along the first posdim dimension which is replaced by a length 1 or 3 dimension, corresponding to the lower limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}), the spread, and the upper limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for each experiment/leadtime/latitude/longitude. - \item{$iqr}{ -InterQuartile Range. - } - \item{$maxmin}{ -Maximum - Minimum. - } - \item{$sd}{ -Standard Deviation. - } - \item{$mad}{ -Median Absolute Deviation. - } +Matrix with the same dimensions as var except along the first posdim +dimension which is replaced by a length 1 or 3 dimension, corresponding to +the lower limit of the \code{siglev}\% confidence interval +(only present if \code{conf = TRUE}), the spread, and the upper limit of +the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) +for each experiment/leadtime/latitude/longitude. + \item{$iqr}{ + InterQuartile Range. + } + \item{$maxmin}{ + Maximum - Minimum. + } + \item{$sd}{ + Standard Deviation. + } + \item{$mad}{ + Median Absolute Deviation. + } +} +\description{ +Computes the InterQuartile Range, the Maximum minus Mininum, the Standard +Deviation and the Median Absolute Deviation along the list of dimensions +provided by the posdim argument (typically along the ensemble member and +start date dimension).\cr +The confidence interval is optionally computed by bootstrapping. } \examples{ # Load sample data as in Load() example: @@ -57,25 +63,26 @@ runmean_months <- 12 dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, - narm = TRUE), 2, dim(smooth_ano_exp)[2]) + narm = TRUE), 2, dim(smooth_ano_exp)[2]) spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) PlotVsLTime(spread$iqr, - toptitle = "Inter-Quartile Range between ensemble members", - ytitle = "K", monini = 11, limits = NULL, - listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, - hlines = c(0), fileout = 'tos_iqr.eps') + toptitle = "Inter-Quartile Range between ensemble members", + ytitle = "K", monini = 11, limits = NULL, + listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, + hlines = c(0), fileout = 'tos_iqr.eps') PlotVsLTime(spread$maxmin, toptitle = "Maximum minus minimum of the members", - ytitle = "K", monini = 11, limits = NULL, - listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, - hlines = c(0), fileout = 'tos_maxmin.eps') + ytitle = "K", monini = 11, limits = NULL, + listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, + hlines = c(0), fileout = 'tos_maxmin.eps') PlotVsLTime(spread$sd, toptitle = "Standard deviation of the members", - ytitle = "K", monini = 11, limits = NULL, - listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, - hlines = c(0), fileout = 'tos_sd.eps') + ytitle = "K", monini = 11, limits = NULL, + listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, + hlines = c(0), fileout = 'tos_sd.eps') PlotVsLTime(spread$mad, toptitle = "Median Absolute Deviation of the members", - ytitle = "K", monini = 11, limits = NULL, - listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, - hlines = c(0), fileout = 'tos_mad.eps') + ytitle = "K", monini = 11, limits = NULL, + listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, + hlines = c(0), fileout = 'tos_mad.eps') + } \author{ History:\cr @@ -83,3 +90,4 @@ History:\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN } \keyword{datagen} + diff --git a/man/StatSeasAtlHurr.Rd b/man/StatSeasAtlHurr.Rd index e2ad65a7..9822eb90 100644 --- a/man/StatSeasAtlHurr.Rd +++ b/man/StatSeasAtlHurr.Rd @@ -1,73 +1,85 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/StatSeasAtlHurr.R \name{StatSeasAtlHurr} \alias{StatSeasAtlHurr} \title{Compute estimate of seasonal mean of Atlantic hurricane activity} -\description{ -Compute one of G. Villarini's statistically downscaled measure of mean Atlantic hurricane activity and its variance. The hurricane activity is estimated using seasonal averages of sea surface temperature anomalies over the tropical Atlantic (bounded by 10N-25N and 80W-20W) and the tropics at large (bounded by 30N-30S). The anomalies are for the JJASON season.\cr -The estimated seasonal average is either 1) number of hurricanes, 2) number of tropical cyclones with lifetime >=48h or 3) power dissipation index (PDI; in 10^11 m^3 s^{-2}).\cr -The statistical models used in this function are described in\cr -} \usage{ -StatSeasAtlHurr(atlano = NULL, tropano = NULL, hrvar = 'HR') +StatSeasAtlHurr(atlano = NULL, tropano = NULL, hrvar = "HR") } \arguments{ - \item{atlano}{ -Array of Atlantic sea surface temperature anomalies. Must have the same dimension as tropano. - } - \item{tropano}{ -Array of tropical sea surface temperature anomalies. Must have the same dimension as atlano. - } - \item{hrvar}{ -The seasonal average to be estimated. The options are either\cr +\item{atlano}{Array of Atlantic sea surface temperature anomalies. +Must have the same dimension as tropano.} + +\item{tropano}{Array of tropical sea surface temperature anomalies. +Must have the same dimension as atlano.} + +\item{hrvar}{The seasonal average to be estimated. The options are either\cr "HR" (hurricanes) \cr "TC" (tropical cyclones with lifetime >=48h) \cr -"PDI" (power dissipation index) \cr - } +"PDI" (power dissipation index) \cr} } \value{ A list composed of two matrices:\cr - \itemize{ - \item{ -1. a matrix (mean) with the seasonal average values of the desired quantity.\cr - } - \item{ -2. a matrix (var) of the variance of that quantity.\cr - } - } -The dimensions of the two matrices are the same as the dimensions of atlano/tropano. +\enumerate{ + \item{ + A matrix (mean) with the seasonal average values of the desired quantity.\cr + } + \item{ + A matrix (var) of the variance of that quantity.\cr + } +} +The dimensions of the two matrices are the same as the dimensions of + atlano/tropano. +} +\description{ +Compute one of G. Villarini's statistically downscaled measure of mean +Atlantic hurricane activity and its variance. The hurricane activity is +estimated using seasonal averages of sea surface temperature anomalies over +the tropical Atlantic (bounded by 10N-25N and 80W-20W) and the tropics at +large (bounded by 30N-30S). The anomalies are for the JJASON season.\cr +The estimated seasonal average is either 1) number of hurricanes, 2) number +of tropical cyclones with lifetime >=48h or 3) power dissipation index +(PDI; in 10^11 m^3 s^{-2}).\cr +The statistical models used in this function are described in\cr } \examples{ # Let AtlAno represents 5 different 5-year forecasts of seasonally averaged # Atlantic sea surface temperature anomalies. AtlAno <- matrix(c(-0.31, -0.36, 0.26, -0.16, -0.16, - -0.06, -0.22, -0.31, -0.36, -0.39, - 0.20, -0.14, 0.12, 0.22, 0.02, - -0.28, 0.26, -0.10, 0.18, 0.33, - 0.45, 0.46, 0.04, 0.12, 0.21), - nrow = 5, ncol = 5) + -0.06, -0.22, -0.31, -0.36, -0.39, + 0.20, -0.14, 0.12, 0.22, 0.02, + -0.28, 0.26, -0.10, 0.18, 0.33, + 0.45, 0.46, 0.04, 0.12, 0.21), + nrow = 5, ncol = 5) # Let TropAno represents 5 corresponding 5-year forecasts of seasonally averaged # tropical sea surface temperature anomalies. TropAno <- matrix(c(-0.22, -.13, 0.07, -0.16, -0.15, - 0.00, -0.03, -0.22, -0.13, -0.10, - 0.07, -0.07, 0.17, 0.10, -0.15, - -0.01, 0.08, 0.07, 0.17, 0.13, - 0.16, 0.15, -0.09, 0.03, 0.27), - nrow = 5, ncol = 5) + 0.00, -0.03, -0.22, -0.13, -0.10, + 0.07, -0.07, 0.17, 0.10, -0.15, + -0.01, 0.08, 0.07, 0.17, 0.13, + 0.16, 0.15, -0.09, 0.03, 0.27), + nrow = 5, ncol = 5) # The seasonal average of hurricanes for each of the five forecasted years, # for each forecast, would then be given by hr_count <- StatSeasAtlHurr(atlano = AtlAno, - tropano = TropAno, - hrvar = 'HR') + tropano = TropAno, + hrvar = 'HR') print(hr_count$mean) -} + +} +\author{ +History:\cr +0.1 - 2015-11 (Louis-Philippe Caron, \email{louis-philippe.caron@bsc.es}) - Original code +} \references{ Villarini et al. (2010) Mon Wea Rev, 138, 2681-2705.\cr Villarini et al. (2012) Mon Wea Rev, 140, 44-65.\cr Villarini et al. (2012) J Clim, 25, 625-637.\cr -An example of how the function can be used in hurricane forecast studies is given in\cr -Caron, L.-P. et al. (2014) Multi-year prediction skill of Atlantic hurricane activity in CMIP5 decadal hindcasts. Climate Dynamics, 42, 2675-2690. doi:10.1007/s00382-013-1773-1. -} - \author{ -History:\cr -0.1 - 2015-11 (Louis-Philippe Caron, \email{louis-philippe.caron@bsc.es}) - Original code +An example of how the function can be used in hurricane forecast studies + is given in\cr +Caron, L.-P. et al. (2014) Multi-year prediction skill of Atlantic hurricane + activity in CMIP5 decadal hindcasts. Climate Dynamics, 42, 2675-2690. + doi:10.1007/s00382-013-1773-1. } \keyword{datagen} + diff --git a/man/Subset.Rd b/man/Subset.Rd index 2c883ffa..4e52c6db 100644 --- a/man/Subset.Rd +++ b/man/Subset.Rd @@ -1,13 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Subset.R \name{Subset} \alias{Subset} \title{Subset a Data Array} +\usage{ +Subset(x, along, indices, drop = FALSE) +} +\arguments{ +\item{x}{A multidimensional array to be sliced. It can have dimension names +either in \code{names(dim(x))} or either in the attribute 'dimensions'.} + +\item{along}{Vector with references to the dimensions to take the subset +from: either integers or dimension names.} + +\item{indices}{List of indices to take from each dimension specified in +'along'. If a single dimension is specified in 'along' the indices can be +directly provided as a single integer or as a vector.} + +\item{drop}{Whether to drop all the dimensions of length 1 in the resulting +array, none, only those that are specified in 'along', or only those that +are not specified in 'along'. The possible values are, respectively: 'all' +or TRUE, 'none' or FALSE, 'selected', and 'non-selected'.} +} \description{ This function allows to subset (i.e. slice, take a chunk of) an array, in a similar way as done in the function \code{take()} in the package plyr. There are two main inprovements:\cr\cr The input array can have dimension names, either -in \code{names(dim(x))} or in the attribute 'dimensions', and the dimensions to -subset along can be specified via the parameter \code{along} either with +in \code{names(dim(x))} or in the attribute 'dimensions', and the dimensions +to subset along can be specified via the parameter \code{along} either with integer indices or either by their name.\cr\cr There are additional ways to adjust which dimensions are dropped in the resulting array: either to drop all, to drop none, to drop only the ones that @@ -15,35 +36,13 @@ have been sliced or to drop only the ones that have not been sliced.\cr\cr If an array is provided without dimension names, dimension names taken from the parameter \code{dim_names} will be added to the array. } -\usage{ -Subset(x, along, indices, drop = FALSE) -} -\arguments{ - \item{x}{ -A multidimensional array to be sliced. It can have dimension names either -in \code{names(dim(x))} or either in the attribute 'dimensions'. - } - \item{along}{ -Vector with references to the dimensions to take the subset from: either -integers or dimension names. - } - \item{indices}{ -List of indices to take from each dimension specified in 'along'. If a single -dimension is specified in 'along' the indices can be directly provided as a -single integer or as a vector. - } - \item{drop}{ -Whether to drop all the dimensions of length 1 in the resulting array, none, -only those that are specified in 'along', or only those that are not specified -in 'along'. The possible values are, respectively: 'all' or TRUE, 'none' or -FALSE, 'selected', and 'non-selected'. - } -} \examples{ subset <- Subset(sampleMap$mod, c('dataset', 'sdate', 'ftime'), - list(1, 1, 1), drop = 'selected') + list(1, 1, 1), drop = 'selected') PlotLayout(PlotEquiMap, c('lat', 'lon'), subset, - sampleMap$lon, sampleMap$lat, - titles = paste('Member', 1:3)) + sampleMap$lon, sampleMap$lat, + titles = paste('Member', 1:3)) + } \keyword{dplot} + diff --git a/man/ToyModel.Rd b/man/ToyModel.Rd index bfbd179e..da075960 100644 --- a/man/ToyModel.Rd +++ b/man/ToyModel.Rd @@ -1,10 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/ToyModel.R \name{ToyModel} \alias{ToyModel} -\title{ -Synthetic forecast generator imitating seasonal to decadal forecasts. The -components of a forecast: (1) predictabiltiy (2) forecast error (3) non-stationarity -and (4) ensemble generation. The forecast can be computed for real observations or -observations generated artifically. +\title{Synthetic forecast generator imitating seasonal to decadal forecasts. The +components of a forecast: (1) predictabiltiy (2) forecast error (3) +non-stationarity and (4) ensemble generation. The forecast can be computed +for real observations or observations generated artifically.} +\usage{ +ToyModel(alpha = 0.1, beta = 0.4, gamma = 1, sig = 1, trend = 0, + nstartd = 30, nleadt = 4, nmemb = 10, obsini = NULL, fxerr = NULL) +} +\arguments{ +\item{alpha}{Predicabiltiy of the forecast on the observed residuals +Must be a scalar 0 < alpha < 1.} + +\item{beta}{Standard deviation of forecast error +Must be a scalar 0 < beta < 1.} + +\item{gamma}{Factor on the linear trend to sample model uncertainty. Can be +a scalar or a vector of scalars -inf < gammay < inf. +Defining a scalar results in multiple forecast, corresponding to different +models with different trends.} + +\item{sig}{Standard deviation of the residual variability of the forecast. +If observations are provided 'sig' is computed from the observations.} + +\item{trend}{Linear trend of the forecast. The same trend is used for each +lead-time. If observations are provided the 'trend' is computed from the +observations, with potentially different trends for each lead-time. The +trend has no unit and needs to be defined according to the time vector +[1,2,3,... nstartd].} + +\item{nstartd}{Number of start-dates of the forecast. +If observations are provided the 'nstartd' is computed from the observations.} + +\item{nleadt}{Number of lead-times of the forecats. +If observations are provided the 'nleadt' is computed from the observations.} + +\item{nmemb}{Number of members of the forecasts.} + +\item{obsini}{Observations that can be used in the synthetic forecast coming +from Load (anomalies are expected). If no observations are provided +artifical observations are generated based on Gaussian variaiblity with +standard deviation from 'sig' and linear trend from 'trend'.} + +\item{fxerr}{Provides a fixed error of the forecast instead of generating +one from the level of beta. This allows to perform pair of forecasts with +the same conditional error as required for instance in an attribution context.} +} +\value{ +List of forecast with $mod including the forecast and $obs the + observations. The dimensions correspond to + c(length(gamma), nmemb, nstartd, nleadt) } \description{ The toymodel is based on the model presented in Weigel et al. (2008) QJRS @@ -18,64 +65,6 @@ ensemble members. It imitates components of a forecast: (1) predictabiltiy The forecast can be computed for real observations or observations generated artifically. } -\usage{ -ToyModel(alpha = 0.1, beta = 0.4, gamma = 1, sig = 1, trend = 0, - nstartd = 30, nleadt = 4, nmemb = 10, obsini = NULL, - fxerr = NULL) -} -\arguments{ - \item{alpha}{ -Predicabiltiy of the forecast on the observed residuals -Must be a scalar 0 Date: Thu, 25 Jul 2019 11:31:54 +0200 Subject: [PATCH 32/61] Bugfix. --- DESCRIPTION | 9 +++++- NAMESPACE | 72 ++++++++++++++++++++++++++++++++++++++++++++-- R/BrierScore.R | 2 -- R/ConfigFileOpen.R | 1 - R/Spread.R | 1 - 5 files changed, 78 insertions(+), 7 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 99c08ff6..ba2cbf28 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -28,7 +28,13 @@ Authors@R: c( person("Isabel", "Andreu-Burillo", , "isabel.andreu.burillo@ic3.cat", role = "ctb"), person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb"), person("An-Chi", "Ho", , "an.ho@bsc.es", role = "ctb")) -Description: Set of tools to verify forecasts through the computation of typical prediction scores against one or more observational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the equations from a model, not a pure observational dataset). Intended for seasonal to decadal climate forecasts although can be useful to verify other kinds of forecasts. The package can be helpful in climate sciences for other purposes than forecasting. +Description: Set of tools to verify forecasts through the computation of typical + prediction scores against one or more observational datasets or reanalyses (a + reanalysis being a physical extrapolation of observations that relies on the + equations from a model, not a pure observational dataset). Intended for seasonal + to decadal climate forecasts although can be useful to verify other kinds of + forecasts. The package can be helpful in climate sciences for other purposes + than forecasting. Depends: maps, methods, @@ -53,3 +59,4 @@ BugReports: https://earth.bsc.es/gitlab/es/s2dverification/issues LazyData: true SystemRequirements: cdo Encoding: UTF-8 +RoxygenNote: 5.0.0 diff --git a/NAMESPACE b/NAMESPACE index 7c49d6b9..52ccb16f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,2 +1,70 @@ -exportPattern("^[^\\.]") -import(abind, bigmemory, GEOmap, geomapdata, graphics, grDevices, mapproj, maps, methods, NbClust, ncdf4, parallel, plyr, stats, SpecsVerification) +# Generated by roxygen2: do not edit by hand + +export(.BrierScore) +export(.Corr) +export(ACC) +export(Alpha) +export(AnimateMap) +export(Ano) +export(Ano_CrossValid) +export(ArrayToNetCDF) +export(BrierScore) +export(CDORemap) +export(Clim) +export(Cluster) +export(ColorBar) +export(Composite) +export(ConfigApplyMatchingEntries) +export(ConfigEditDefinition) +export(ConfigEditEntry) +export(ConfigFileOpen) +export(ConfigShowSimilarEntries) +export(ConfigShowTable) +export(Consist_Trend) +export(Corr) +export(EOF) +export(Enlarge) +export(Eno) +export(EnoNew) +export(Filter) +export(FitAcfCoef) +export(FitAutocor) +export(GenSeries) +export(Histo2Hindcast) +export(IniListDims) +export(InsertDim) +export(LeapYear) +export(Load) +export(Mean1Dim) +export(MeanListDim) +export(NAO) +export(Plot2VarsVsLTime) +export(PlotACC) +export(PlotAno) +export(PlotBoxWhisker) +export(PlotClim) +export(PlotEquiMap) +export(PlotLayout) +export(PlotSection) +export(PlotStereoMap) +export(PlotVsLTime) +export(ProbBins) +export(ProjectField) +export(RMS) +export(RMSSS) +export(RatioRMS) +export(RatioSDRMS) +export(Regression) +export(SVD) +export(Season) +export(SelIndices) +export(Smoothing) +export(Spectrum) +export(Spread) +export(StatSeasAtlHurr) +export(Subset) +export(ToyModel) +export(Trend) +export(UltimateBrier) +export(clim.colors) +export(clim.palette) diff --git a/R/BrierScore.R b/R/BrierScore.R index 546b578a..62223099 100644 --- a/R/BrierScore.R +++ b/R/BrierScore.R @@ -78,8 +78,6 @@ #'bins_ano_exp <- ProbBins(ano_exp, thr = c(1/3, 2/3), posdates = 3, posdim = 2) #'bins_ano_obs <- ProbBins(ano_obs, thr = c(1/3, 2/3), posdates = 3, posdim = 2) #'bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_ob,s 3), -rt - #' tdim = 2, ensdim = 3) #' } #'@export diff --git a/R/ConfigFileOpen.R b/R/ConfigFileOpen.R index d73961aa..afa67272 100644 --- a/R/ConfigFileOpen.R +++ b/R/ConfigFileOpen.R @@ -136,7 +136,6 @@ #' ecmwf, .*, /dataset/main/path/ #'A double quote only (") in any key or value element will be interpreted as #''fill in with the same value as the entry above'. -#'} #' #'@return #'ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work. diff --git a/R/Spread.R b/R/Spread.R index b25c356d..2734b367 100644 --- a/R/Spread.R +++ b/R/Spread.R @@ -74,7 +74,6 @@ #' ytitle = "K", monini = 11, limits = NULL, #' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, #' hlines = c(0), fileout = 'tos_mad.eps') -#'} #' #'@export Spread <- function(var, posdim = 2, narm = TRUE, siglev = 0.95, conf = TRUE) { -- GitLab From 224fd3bba077a25388b698ac2b6c3ecce8d30457 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 26 Jul 2019 16:01:40 +0200 Subject: [PATCH 33/61] Roxygen2 format modification. --- NAMESPACE | 23 ++++++ R/ACC.R | 37 +++++---- R/Alpha.R | 6 +- R/AnimateMap.R | 12 +-- R/Ano.R | 22 +++--- R/Ano_CrossValid.R | 19 ++--- R/ArrayToNetCDF.R | 57 ++++++++------ R/BrierScore.R | 15 ++-- R/CDORemap.R | 18 ++--- R/Clim.R | 18 ++--- R/Cluster.R | 42 ++++++---- R/ColorBar.R | 50 +++++++----- R/Composite.R | 18 ++--- R/ConfigAddEntry.R | 42 ---------- R/ConfigApplyMatchingEntries.R | 12 +-- R/ConfigEditDefinition.R | 9 +++ R/ConfigEditEntry.R | 127 ++++++++++++++++++++++++++---- R/ConfigFileCreate.R | 14 ---- R/ConfigFileOpen.R | 105 ++++++++++++++++++++---- R/ConfigFileSave.R | 55 ------------- R/ConfigRemoveDefinition.R | 5 -- R/ConfigRemoveEntry.R | 50 ------------ R/ConfigShowDefinitions.R | 5 -- R/ConfigShowSimilarEntries.R | 12 +-- R/ConfigShowTable.R | 13 ++- R/Consist_Trend.R | 17 ++-- R/Corr.R | 7 +- R/EOF.R | 39 +++++---- R/FitAcfCoef.R | 2 +- R/FitAutocor.R | 4 +- R/GenSeries.R | 2 +- R/Histo2Hindcast.R | 8 +- R/InsertDim.R | 2 +- R/LeapYear.R | 4 +- R/Load.R | 15 ++-- R/NAO.R | 30 ++++--- R/Plot2VarsVsLTime.R | 4 +- R/PlotEquiMap.R | 35 ++++---- R/PlotLayout.R | 26 +++--- R/PlotStereoMap.R | 29 +++---- R/PlotVsLTime.R | 1 + R/ProjectField.R | 14 ++-- R/RMS.R | 34 ++++---- R/RMSSS.R | 16 ++-- R/RatioRMS.R | 17 ++-- R/RatioSDRMS.R | 17 ++-- R/Regression.R | 6 +- R/SVD.R | 6 +- R/Season.R | 4 +- R/SelIndices.R | 4 +- R/Smoothing.R | 8 +- R/Spectrum.R | 4 +- R/Spread.R | 9 ++- R/Trend.R | 12 +-- R/UltimateBrier.R | 12 +-- R/clim.palette.R | 11 +-- R/sampleDepthData.R | 27 +++++++ R/sampleMap.R | 46 +++++++++++ R/sampleTimeSeries.R | 48 +++++++++++ man/ACC.Rd | 33 ++++---- man/Alpha.Rd | 6 +- man/AnimateMap.Rd | 38 ++++----- man/Ano.Rd | 22 +++--- man/Ano_CrossValid.Rd | 21 +++-- man/ArrayToNetCDF.Rd | 56 +++++++------ man/BrierScore.Rd | 16 ++-- man/CDORemap.Rd | 17 ++-- man/Clim.Rd | 17 ++-- man/Cluster.Rd | 40 ++++++---- man/ColorBar.Rd | 49 +++++++----- man/Composite.Rd | 18 ++--- man/ConfigApplyMatchingEntries.Rd | 12 +-- man/ConfigEditDefinition.Rd | 4 + man/ConfigEditEntry.Rd | 33 +++++--- man/ConfigFileOpen.Rd | 38 +++++---- man/ConfigShowSimilarEntries.Rd | 20 ++--- man/ConfigShowTable.Rd | 8 +- man/Consist_Trend.Rd | 16 ++-- man/Corr.Rd | 7 +- man/EOF.Rd | 38 +++++---- man/FitAcfCoef.Rd | 2 +- man/FitAutocor.Rd | 4 +- man/GenSeries.Rd | 2 +- man/Histo2Hindcast.Rd | 8 +- man/InsertDim.Rd | 2 +- man/LeapYear.Rd | 4 +- man/Load.Rd | 112 +++++++++++++------------- man/NAO.Rd | 30 ++++--- man/Plot2VarsVsLTime.Rd | 22 +++--- man/PlotEquiMap.Rd | 34 ++++---- man/PlotLayout.Rd | 24 +++--- man/PlotStereoMap.Rd | 26 +++--- man/PlotVsLTime.Rd | 37 ++++----- man/ProjectField.Rd | 14 ++-- man/RMS.Rd | 33 ++++---- man/RMSSS.Rd | 14 ++-- man/RatioRMS.Rd | 16 ++-- man/RatioSDRMS.Rd | 16 ++-- man/Regression.Rd | 8 +- man/SVD.Rd | 8 +- man/Season.Rd | 4 +- man/SelIndices.Rd | 4 +- man/Smoothing.Rd | 7 +- man/Spectrum.Rd | 4 +- man/Spread.Rd | 21 ++--- man/Trend.Rd | 12 +-- man/UltimateBrier.Rd | 11 ++- man/clim.colors.Rd | 35 -------- man/clim.palette.Rd | 29 ++++--- man/s2dverification.Rd | 48 ++++++----- 110 files changed, 1314 insertions(+), 1092 deletions(-) delete mode 100644 R/ConfigAddEntry.R delete mode 100644 R/ConfigFileCreate.R delete mode 100644 R/ConfigFileSave.R delete mode 100644 R/ConfigRemoveDefinition.R delete mode 100644 R/ConfigRemoveEntry.R delete mode 100644 R/ConfigShowDefinitions.R create mode 100644 R/sampleDepthData.R create mode 100644 R/sampleMap.R create mode 100644 R/sampleTimeSeries.R delete mode 100644 man/clim.colors.Rd diff --git a/NAMESPACE b/NAMESPACE index 52ccb16f..5f8f409c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,6 +2,11 @@ export(.BrierScore) export(.Corr) +export(.RMS) +export(.RMSSS) +export(.RatioRMS) +export(.RatioSDRMS) +export(.Trend) export(ACC) export(Alpha) export(AnimateMap) @@ -14,10 +19,16 @@ export(Clim) export(Cluster) export(ColorBar) export(Composite) +export(ConfigAddEntry) export(ConfigApplyMatchingEntries) export(ConfigEditDefinition) export(ConfigEditEntry) +export(ConfigFileCreate) export(ConfigFileOpen) +export(ConfigFileSave) +export(ConfigRemoveDefinition) +export(ConfigRemoveEntry) +export(ConfigShowDefinitions) export(ConfigShowSimilarEntries) export(ConfigShowTable) export(Consist_Trend) @@ -68,3 +79,15 @@ export(Trend) export(UltimateBrier) export(clim.colors) export(clim.palette) +import(GEOmap) +import(NbClust) +import(SpecsVerification) +import(abind) +import(bigmemory) +import(geomapdata) +import(graphics) +import(mapproj) +import(maps) +import(ncdf4) +import(parallel) +import(plyr) diff --git a/R/ACC.R b/R/ACC.R index c61b4165..f71425b7 100644 --- a/R/ACC.R +++ b/R/ACC.R @@ -2,9 +2,11 @@ #' #'Calculates the Anomaly Correlation Coefficient for the ensemble mean of #'each model and the corresponding references for each startdate and each -#'leadtime. The domain of interest can be specified by providing the list +#'leadtime.\cr +#'The domain of interest can be specified by providing the list #'of longitudes/latitudes (lon/lat) of the grid together with the corners -#'of the domain lonlatbox = c(lonmin, lonmax, latmin, latmax). +#'of the domain:\cr +#' lonlatbox = c(lonmin, lonmax, latmin, latmax). #' #'@param var_exp Array of experimental anomalies with dimensions: #' c(nexp, nsdates, nltimes, nlat, nlon) or @@ -27,19 +29,19 @@ #' leadtimes always have the same number of members. #'@param siglev The confidence level for the computed confidence intervals. #' -#'@return A list of length 2: -#'\itemize{ -#' \item\code{$ACC} { +#'@return +#'\item{ACC}{ #' If \code{conf = TRUE}, array with dimensions: #' c(nexp, nobs, nsdates, nleadtimes, 4) #' The fifth dimension of length 4 corresponds to the lower limit of the #' \code{siglev}\% confidence interval, the ACC, the upper limit of the #' \code{siglev}\% confidence interval and the \code{siglev}\% significance #' level. If \code{conf = FALSE}, the array of the Anomaly Correlation -#' Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes).} -#' \item\code{$MACC} { +#' Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes). +#'} +#'\item{MACC}{ #' The array of the Mean Anomaly Correlation Coefficient with dimensions -#' c(nexp, nobs, nleadtimes).} +#' c(nexp, nobs, nleadtimes). #'} #' #'@examples @@ -79,15 +81,16 @@ #'@references Joliffe and Stephenson (2012). Forecast Verification: A #' Practitioner's Guide in Atmospheric Science. Wiley-Blackwell. #'@keywords datagen -#'@author History: -#' 0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code -#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN -#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - optimization -#' 1.2 - 2014-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Bug-fixes: handling of NA & selection of domain + Simplification of code -#' 1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Boostrapping over members -#' 1.3.1 - 2014-09 (C. Prodhomme, chloe.prodhomme@@bsc.es) - Add comments and minor style changes -#' 1.3.2 - 2015-02 (N. Manubens, nicolau.manubens@@bsc.es) - Fixed ACC documentation and examples -#' +#'@author +#'History:\cr +#' 0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code\cr +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN\cr +#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - optimization\cr +#' 1.2 - 2014-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Bug-fixes: handling of NA & selection of domain + Simplification of code\cr +#' 1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Boostrapping over members\cr +#' 1.3.1 - 2014-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - Add comments and minor style changes\cr +#' 1.3.2 - 2015-02 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Fixed ACC documentation and examples +#'@import abind #'@export ACC <- function(var_exp, var_obs, lon = NULL, lat = NULL, lonlatbox = NULL, conf = TRUE, conftype = "parametric", diff --git a/R/Alpha.R b/R/Alpha.R index c6d74f05..cc187239 100644 --- a/R/Alpha.R +++ b/R/Alpha.R @@ -4,7 +4,7 @@ #'autocorrelation at lag 1 of the xdata array following the method described #'in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear #'detrending and/or a filtering of any frequency peak if requested, the sample -#'autocorrelation is estimated. +#'autocorrelation is estimated.\cr #'Then the theoretical autocorrelation of an AR1 is fitted to the sample #'autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to #'obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 @@ -24,8 +24,8 @@ #'print(alpha) #' #'@keywords datagen -#'@author History: -#' 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#'@author History:\cr +#' 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr #' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN #'@export Alpha <- function(xdata, detrend = FALSE, filter = FALSE) { diff --git a/R/AnimateMap.R b/R/AnimateMap.R index 1764214a..733cfd5b 100644 --- a/R/AnimateMap.R +++ b/R/AnimateMap.R @@ -49,13 +49,15 @@ #' If RMS, RMSSS, correlations : first exp with successive obs, then second #' exp with successive obs, etc ... #'@param ... Arguments to be passed to the method. Only accepts the following -#' graphical parameters: adj ann ask bty cex cex.axis cex.lab cex.main cex.sub +#' graphical parameters:\cr +#' adj ann ask bty cex cex.axis cex.lab cex.main cex.sub #' cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig #' font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty #' lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo -#' srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. +#' srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. \cr #' For more information about the parameters see `par`. #' +#'@details #'Examples of input: #'\enumerate{ #' \item{ @@ -88,9 +90,9 @@ #'} #' #'@keywords dynamic -#'@author History: -#' 1.0 - 2012-04 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code -#' 1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN +#'@author History:\cr +#' 1.0 - 2012-04 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code\cr +#' 1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN\cr #' 1.2 - 2015-05 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Use of PlotEquiMap and PlotStereoMap #' #'@examples diff --git a/R/Ano.R b/R/Ano.R index 72f57c45..657e7f9b 100644 --- a/R/Ano.R +++ b/R/Ano.R @@ -4,21 +4,21 @@ #'matrix output from \code{Load()} and their climatologies output from #'\code{Clim()}. #' -#'@param var Model or observational data: -#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to -#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) -#'@param clim Climatologies from clim: c(nmod/nexp/nobs, nltime) -#' up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or -#' c(nmod/nexp/nobs, nmemb/nparam, nltime) up to -#' c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or -#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to -#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +#'@param var Model or observational data:\cr +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to \cr +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr +#'@param clim Climatologies from clim: c(nmod/nexp/nobs, nltime) \cr +#' up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or \cr +#' c(nmod/nexp/nobs, nmemb/nparam, nltime) up to \cr +#' c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or \cr +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to \cr +#' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) \cr #' depending on the options provided to \code{Clim()}. #' #'@return Array with same dimensions as 'var'. #'@keywords datagen -#'@author History: -#' 0.1 - 2012-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#'@author History:\cr +#' 0.1 - 2012-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr #' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN #' #'@examples diff --git a/R/Ano_CrossValid.R b/R/Ano_CrossValid.R index ef2a2e92..e42941f2 100644 --- a/R/Ano_CrossValid.R +++ b/R/Ano_CrossValid.R @@ -4,21 +4,22 @@ #'data output from \code{load()} by subtracting the climatologies computed #'with a cross-validation technique and a per-pair method. #' -#'@param var_exp Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to +#'@param var_exp Model data:\cr +#'c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to \cr #' c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon). -#'@param var_obs Observational data: c(nobs, nmemb, nsdates, nltime) up to +#'@param var_obs Observational data: \cr +#'c(nobs, nmemb, nsdates, nltime) up to \cr #' c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon). #'@param memb TRUE/FALSE (1 climatology for each member/1 climatology #' averaging all the members). Default = TRUE. #' -#'@return A list of length 2: -#'\itemize{ -#' \item\code{$ano_exp} {Matrix with same dimensions as var_exp} -#' \item\code{$ano_obs} {Matrix with same dimensions as var_obs} -#'} +#'@return +#' \item{$ano_exp}{Matrix with same dimensions as var_exp} +#' \item{$ano_obs}{Matrix with same dimensions as var_obs} +#' #'@keywords datagen -#'@author History: -#' 0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +#'@author History:\cr +#' 0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr #' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN #' #'@examples diff --git a/R/ArrayToNetCDF.R b/R/ArrayToNetCDF.R index 72cc9a0f..298a5706 100644 --- a/R/ArrayToNetCDF.R +++ b/R/ArrayToNetCDF.R @@ -5,44 +5,50 @@ #'and name of the resulting file must be specified. Metadata can be attached #'to the arrays and propagated into the NetCDF file in 3 possible ways: #'\itemize{ -#' \item{Via the list names if a list of arrays is provided: Each name in +#' \item{ +#' Via the list names if a list of arrays is provided: Each name in #' the input list, corresponding to one multidimensional array, will be -#' interpreted as the name of the variable it contains. -#' E.g: -#' \code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), -#' file_path = 'example.nc')}} -#' \item{Via the dimension names of each provided array: The dimension names +#' interpreted as the name of the variable it contains.\cr +#' E.g:\cr +#' \code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))),}\cr +#' \code{ file_path = 'example.nc')} +#' } +#' \item{ +#' Via the dimension names of each provided array: The dimension names #' of each of the provided arrays will be interpreted as names for the #' dimensions of the NetCDF files. Read further for special dimension names -#' that will trigger special behaviours, such as 'time' and 'var'. -#' E.g: -#' \code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) -#' names(dim(temperature)) <- c('longitude', 'latitude', 'time') -#' ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')}} -#' \item{Via the attribute 'variables' of each provided array: The arrays can +#' that will trigger special behaviours, such as 'time' and 'var'.\cr +#' E.g:\cr +#' \code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10))}\cr +#' \code{names(dim(temperature)) <- c('longitude', 'latitude', 'time')}\cr +#' \code{ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')} +#' } +#' \item{ +#' Via the attribute 'variables' of each provided array: The arrays can #' be provided with metadata in an attribute named 'variables', which is #' expected to be a named list of named lists, where the names of the #' container list are the names of the variables present in the provided #' array, and where each sub-list contains metadata for each of the variables. #' The attribute names and values supported in the sub-lists must follow the #' same format the package \code{ncdf4} uses to represent the NetCDF -#' file headers. -#' E.g: -#' \code{a <- array(1:400, dim = c(5, 10, 4, 2)) -#' metadata <- list(tos = list(addOffset = 100, -#' scaleFact = 10, -#' dim = list(list(name = 'time', -#' unlim = FALSE)))) -#' attr(a, 'variables') <- metadata -#' names(dim(a)) <- c('lat', 'lon', 'time', 'var') -#' ArrayToNetCDF(a, 'tmp.nc')}} +#' file headers.\cr +#' E.g:\cr +#' \code{a <- array(1:400, dim = c(5, 10, 4, 2))}\cr +#' \code{metadata <- list(tos = list(addOffset = 100,}\cr +#' \code{ scaleFact = 10,}\cr +#' \code{ dim = list(list(name = 'time',}\cr +#' \code{ unlim = FALSE))))}\cr +#' \code{attr(a, 'variables') <- metadata}\cr +#' \code{names(dim(a)) <- c('lat', 'lon', 'time', 'var')}\cr +#' \code{ArrayToNetCDF(a, 'tmp.nc')} +#' } #'} -#'The special dimension names are 'var'/'variable' and 'time'. +#'The special dimension names are 'var'/'variable' and 'time'.\cr #'If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will #'interpret each array entry along such dimension corresponds to a separate #'new variable, hence will create a new variable inside the NetCDF file and #'will use it to store all the data in the provided array for the -#'corresponding entry along the 'var'/'variable' dimension. +#'corresponding entry along the 'var'/'variable' dimension.\cr #'If a dimension is named 'time', by default it will be interpreted and built #'as an unlimited dimension. The 'time' dimension must be the last dimension #'of the array (the right-most). If a 'var'/'variable' dimension is present, @@ -60,7 +66,7 @@ #' #'@return This function returns NULL. #'@keywords datagen -#'@author History: +#'@author History:\cr #' 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. #' #'@examples @@ -219,6 +225,7 @@ #'names(dim(lat)) <- 'lat' #'ArrayToNetCDF(list(tos, lon, lat), 'tmp.nc') #'} +#'@import ncdf4 #'@export ArrayToNetCDF <- function(arrays, file_path) { # Check parameter arrays. diff --git a/R/BrierScore.R b/R/BrierScore.R index 62223099..ec922630 100644 --- a/R/BrierScore.R +++ b/R/BrierScore.R @@ -4,8 +4,9 @@ #'decomposition as well with the two within-bin components described in #'Stephenson et al., (2008). It also returns the bias-corrected decomposition #'of the BS (Ferro and Fricker, 2012). BSS having the climatology as the -#'reference forecast. BrierScore provides the same functionality, but taking a -#'matrix of ensemble members (exp) as input. +#'reference forecast. \cr\cr +#'.BrierScore provides the same functionality, but taking a matrix of ensemble +#'members (exp) as input. #' #'@param obs Vector of binary observations (1 or 0). #'@param pred Vector of probablistic predictions with values in the range [0,1]. @@ -38,15 +39,15 @@ #'} #' #'@references -#'Wilks (2006) Statistical Methods in the Atmospheric Sciences. +#'Wilks (2006) Statistical Methods in the Atmospheric Sciences.\cr #'Stephenson et al. (2008). Two extra components in the Brier score decomposition. -#' Weather and Forecasting, 23: 752-757. +#' Weather and Forecasting, 23: 752-757.\cr #'Ferro and Fricker (2012). A bias-corrected decomposition of the BS. #' Quarterly Journal of the Royal Meteorological Society, DOI: 10.1002/qj.1924. #' #'@keywords datagen -#'@author History: -#' 0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues@@ic3.cat}) - Original code +#'@author History:\cr +#' 0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues@@ic3.cat}) - Original code\cr #' 0.2 - 2017-02 (A. Hunter, \email{alasdair.hunter@@bsc.es}) - Adapted to veriApply() #' #'@examples @@ -80,6 +81,7 @@ #'bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_ob,s 3), #' tdim = 2, ensdim = 3) #' } +#'@rdname BrierScore #'@export BrierScore <- function(obs, pred, thresholds = seq(0, 1, 0.1)) { if (max(pred) > 1 | min(pred) < 0) { @@ -156,6 +158,7 @@ BrierScore <- function(obs, pred, thresholds = seq(0, 1, 0.1)) { } } +#'@rdname BrierScore #'@export .BrierScore <- function(exp, obs, thresholds = seq(0, 1, 0.1)) { if (max(exp) > 1 || min(exp) < 0) { diff --git a/R/CDORemap.R b/R/CDORemap.R index b7a92e6b..bc420873 100644 --- a/R/CDORemap.R +++ b/R/CDORemap.R @@ -4,7 +4,7 @@ #'or matrix of longitudes, a vector or matrix of latitudes, a destination grid #'specification, and the name of a method to be used to interpolate (one of #'those available in the 'remap' utility in CDO). The interpolated array is -#'returned (if provided) together with the new longitudes and latitudes. +#'returned (if provided) together with the new longitudes and latitudes.\cr\cr #'\code{CDORemap()} permutes by default the dimensions of the input array (if #'needed), splits it in chunks (CDO can work with data arrays of up to 4 #'dimensions), generates a file with the data of each chunk, interpolates it @@ -12,8 +12,9 @@ #'input array is provided, the longitude and latitude vectors will be #'transformed only. If the array is already on the desired destination grid, #'no transformation is performed (this behvaiour works only for lonlat and -#'gaussian grids). Any metadata attached to the input data array, longitudes -#'or latitudes will be preserved or accordingly modified. +#'gaussian grids). \cr\cr +#'Any metadata attached to the input data array, longitudes or latitudes will +#'be preserved or accordingly modified. #' #'@param data_array Multidimensional numeric array to be interpolated. If #' provided, it must have at least a longitude and a latitude dimensions, @@ -61,14 +62,12 @@ #' used (\code{tempdir()}). #' #'@return A list with the following components: -#'\itemize{ -#' \item\code{$data_array} {The interpolated data array (if an input array +#' \item{'data_array'}{The interpolated data array (if an input array #' is provided at all, NULL otherwise).} -#' \item\code{$lons} {The longitudes of the data on the destination grid.} -#' \item\code{$lats} {The latitudes of the data on the destination grid.} -#'} +#' \item{'lons'}{The longitudes of the data on the destination grid.} +#' \item{'lats'}{The latitudes of the data on the destination grid.} #'@keywords datagen -#'@author History: +#'@author History:\cr #' 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Original code. #'@examples #' \dontrun{ @@ -205,6 +204,7 @@ #'# It is ossible to specify an external NetCDF file as target grid reference #'tas2 <- CDORemap(tas, lon, lat, 'external_file.nc', 'bil') #'} +#'@import ncdf4 #'@export CDORemap <- function(data_array = NULL, lons, lats, grid, method, avoid_writes = TRUE, crop = TRUE, diff --git a/R/Clim.R b/R/Clim.R index 3f052e9c..8a390ad4 100644 --- a/R/Clim.R +++ b/R/Clim.R @@ -3,9 +3,9 @@ #'This function computes only per-pair climatologies from the experimental #'and observational matrices output from \code{Load()}. #'To compute plain climatologies from only experimental or observational -#'data from \code{Load()}, the following code can be used: -#'\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), -#' dim = dim(obs_datta)[-c(2, 3)])} +#'data from \code{Load()}, the following code can be used:\cr +#'\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean),}\cr +#'\code{ dim = dim(obs_datta)[-c(2, 3)])}\cr #'The function \code{Clim()} computes per-pair climatologies using one of the #'following methods: #'\enumerate{ @@ -26,18 +26,16 @@ #' Default = FALSE. #'@param NDV TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE. #' -#'@return A list of length 2: -#'\itemize{ -#' \item{clim_exp}{Array with same dimensions as var_exp except the third +#'@return +#'\item{clim_exp}{Array with same dimensions as var_exp except the third #' (starting dates) and, depending on the parameters, the second (members), #' which disappear.} -#' \item{clim_obs}{Array with same dimensions as var_obs except the third +#'\item{clim_obs}{Array with same dimensions as var_obs except the third #' (starting dates) and, depending on the parameters, the second (members), #' which disappear.} -#'} #'@keywords datagen -#'@author History: -#' 0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code +#'@author History:\cr +#' 0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr #' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN #'@examples #'# Load sample data as in Load() example: diff --git a/R/Cluster.R b/R/Cluster.R index fa4b075b..e37b1585 100644 --- a/R/Cluster.R +++ b/R/Cluster.R @@ -40,25 +40,38 @@ #' provided array in the parameter 'var', the first by default. #' #'@return -#'\itemize{ -#' \item{cluster}{A vector (time series) of integers indicating the occurrence +#'\item{cluster}{ +#' A vector (time series) of integers indicating the occurrence #' of a cluster, i.e., when 'certain data member in time is allocated to a -#' specific cluster (e.g., 2 1 3 1 1 1 ..).} -#' \item{centers}{A matrix of cluster centres or centroids (e.g. -#' [1:K, 1:spatial degrees of freedom]).} -#' \item{totss}{The total sum of squares.} -#' \item{withinss}{A vector of within-cluster sum of squares, one component -#' per cluster.} -#' \item{tot.withinss}{Total within-cluster sum of squares, -#' i.e., sum(withinss).} -#' \item{betweenss}{The between-cluster sum of squares, i.e. totss-tot.withinss.} -#' \item{size}{The number of points in each cluster.} +#' specific cluster (e.g., 2 1 3 1 1 1 ..). #'} +#'\item{centers}{ +#' A matrix of cluster centres or centroids (e.g. +#' [1:K, 1:spatial degrees of freedom]). +#'} +#'\item{totss}{ +#' The total sum of squares. +#'} +#'\item{withinss}{ +#' A vector of within-cluster sum of squares, one component +#' per cluster. +#'} +#'\item{tot.withinss}{ +#' Total within-cluster sum of squares, +#' i.e., sum(withinss). +#'} +#'\item{betweenss}{ +#' The between-cluster sum of squares, i.e. totss-tot.withinss. +#'} +#'\item{size}{ +#'The number of points in each cluster. +#'} +#' #'@references #'Wilks, 2011, Statistical Methods in the Atmospheric Sciences, 3rd ed., Elsevire, pp 676. #'@keywords datagen -#'@author History: -#' 1.0 # 2014-10 (N.S. Fuckar, neven.fuckar@@bsc.es) # Original code +#'@author History:\cr +#' 1.0 # 2014-10 (N.S. Fuckar, \email{neven.fuckar@@bsc.es}) - Original code #'@examples #'# Generating synthetic data #'a1 <- array(dim = c(200, 4)) @@ -93,6 +106,7 @@ #'res2 <- Cluster(var = a1, weights = array(1, dim = dim(a1)[2])) #'print(res2$cluster) #'print(res2$centers) +#'@import NbClust #'@export Cluster <- function(var, weights, nclusters = NULL, index = 'sdindex', posdates = 1) { diff --git a/R/ColorBar.R b/R/ColorBar.R index 7453bfe8..59f947ff 100644 --- a/R/ColorBar.R +++ b/R/ColorBar.R @@ -6,11 +6,12 @@ #'colour bar to represent values that go beyond the range of interest. A #'number of options is provided to adjust the colours and the position and #'size of the components. The drawn colour bar spans a whole figure region -#'and is compatible with figure layouts.\cr\cr The generated colour bar -#'consists of a set of breaks that define the length(brks) - 1 intervals to -#'classify each of the values in each of the grid cells of a two-dimensional -#'field. The corresponding grid cell of a given value of the field will be -#'coloured in function of the interval it belongs to. +#'and is compatible with figure layouts.\cr\cr +#'The generated colour bar consists of a set of breaks that define the +#'length(brks) - 1 intervals to classify each of the values in each of the +#'grid cells of a two-dimensional field. The corresponding grid cell of a +#'given value of the field will be coloured in function of the interval it +#'belongs to.\cr\cr #'The only mandatory parameters are 'var_limits' or 'brks' (in its second #'format, see below). #' @@ -32,7 +33,7 @@ #'@param cols Vector of length(brks) - 1 valid colour identifiers, for each #' interval defined by the breaks. This parameter is optional and will be #' filled in with a vector of length(brks) - 1 colours generated with the -#' function provided in 'color_fun' (\code{clim.colors} by default). 'cols' +#' function provided in 'color_fun' (\code{clim.colors} by default).\cr 'cols' #' can have one additional colour at the beginning and/or at the end with the #' aim to colour field values beyond the range of interest represented in the #' colour bar. If any of these extra colours is provided, parameter @@ -109,30 +110,37 @@ #' overflowing the figure region. This does not have effect over the labels #' provided in 'extra_labels'. Takes 4 by default. #'@param ... Arguments to be passed to the method. Only accepts the following -#' graphical parameters: adj ann ask bg bty cex.lab cex.main cex.sub cin +#' graphical parameters:\cr adj ann ask bg bty cex.lab cex.main cex.sub cin #' col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin #' font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty #' lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt -#' tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. For more +#' tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog.\cr For more #' information about the parameters see `par`. #' #'@return -#'\itemize{ -#' \item{brks}{Breaks used for splitting the range in intervals.} -#' \item{cols}{Colours generated for each of the length(brks) - 1 intervals. -#' Always of length length(brks) - 1.} -#' \item{col_inf}{Colour used to draw the lower triangle end in the colour -#' bar (NULL if not drawn at all).} -#' \item{col_sup}{Colour used to draw the upper triangle end in the colour -#' bar (NULL if not drawn at all).} +#'\item{brks}{ +#' Breaks used for splitting the range in intervals. #'} +#'\item{cols}{ +#' Colours generated for each of the length(brks) - 1 intervals. +#' Always of length length(brks) - 1. +#'} +#'\item{col_inf}{ +#' Colour used to draw the lower triangle end in the colour +#' bar (NULL if not drawn at all). +#'} +#'\item{col_sup}{ +#' Colour used to draw the upper triangle end in the colour +#' bar (NULL if not drawn at all). +#'} +#' #'@keywords dplot -#'@author History: +#'@author History:\cr #' 0.1 - 2012-04 (V. Guemas, \email{virginie.guemas@@bsc.es}) - Original code\cr -#' 0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo@@bsc.es}) - Vert option -#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN -#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - Add cex option -#' 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - New ColorBar +#' 0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo@@bsc.es}) - Vert option\cr +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to CRAN\cr +#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - Add cex option\cr +#' 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - New ColorBar\cr #' (V. Torralba, \email{veronica.torralba@@bsc.es}) #'@examples #'cols <- c("dodgerblue4", "dodgerblue1", "forestgreen", "yellowgreen", "white", diff --git a/R/Composite.R b/R/Composite.R index 9e7dfda5..606cdae1 100644 --- a/R/Composite.R +++ b/R/Composite.R @@ -20,16 +20,14 @@ #'@param fileout Name of the .sav output file (NULL is the default). #' #'@return -#'\itemize{ -#' \item{$composite}{ -#' 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) -#' or only k=1 for any specific cluster, i.e., case (*2). -#' } -#' \item{$pvalue}{ -#' 3-d array (x, y, k) containing the pvalue of the -#' composites obtained through a t-test that accounts for the serial -#' dependence of the data with the same structure as Composite. -#' } +#'\item{$composite}{ +#' 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) +#' or only k=1 for any specific cluster, i.e., case (*2). +#'} +#'\item{$pvalue}{ +#' 3-d array (x, y, k) containing the pvalue of the +#' composites obtained through a t-test that accounts for the serial +#' dependence of the data with the same structure as Composite. #'} #'@keywords datagen #'@author History: diff --git a/R/ConfigAddEntry.R b/R/ConfigAddEntry.R deleted file mode 100644 index a8d2fa54..00000000 --- a/R/ConfigAddEntry.R +++ /dev/null @@ -1,42 +0,0 @@ -ConfigAddEntry <- function(configuration, dataset_type, position = 'last', dataset_name = ".*", var_name = ".*", main_path = "*", file_path = "*", nc_var_name = "*", suffix = "*", varmin = "*", varmax = "*") { - table_name <- dataset_type - if (dataset_name == ".*") { - if (var_name == ".*") { - level <- 1 - } else { - level <- 3 - } - } else { - if (var_name == ".*") { - level <- 2 - } else { - level <- 4 - } - } - - index_of_first <- 0 - index_of_last <- 0 - for (i in 1:level) { - index_of_first <- index_of_first + ifelse(i == 1, 1, length(configuration[[table_name]][[i - 1]])) - index_of_last <- index_of_last + length(configuration[[table_name]][[i]]) - } - - if (position == 'last') { - position <- index_of_last - index_of_first + 1 + 1 - } else if (position == 'first') { - position <- 1 - } else { - if (position < index_of_first || position > index_of_last + 1) { - stop("'position' must be in the range [index of first table entry in corresponding level, index of last table entry in corresponding level + 1]") - } - position <- position - index_of_first + 1 - } - - if (dataset_type == 'experiments' || dataset_type == 'observations') { - configuration[[table_name]][[level]] <- append(configuration[[table_name]][[level]], list(c(dataset_name, var_name, main_path, file_path, nc_var_name, suffix, varmin, varmax)), after = position - 1) - } else { - stop("'dataset_type' must be one of 'experiments' or 'observations'") - } - - configuration -} diff --git a/R/ConfigApplyMatchingEntries.R b/R/ConfigApplyMatchingEntries.R index c051d2f2..5a5c8cfa 100644 --- a/R/ConfigApplyMatchingEntries.R +++ b/R/ConfigApplyMatchingEntries.R @@ -25,17 +25,17 @@ #' #'@return A list with the information resulting of applying the matching #' entries is returned. -#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], -#' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], -#' [ConfigShowTable()]. +#'@seealso ConfigApplyMatchingEntries, ConfigEditDefinition, +#' ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, +#' ConfigShowTable #'@keywords datagen -#'@author History: -#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version +#'@author History:\cr +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version\cr #' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage types #'@examples #'# Create an empty configuration file #'config_file <- paste0(tempdir(), "/example.conf") -#'ConfigFileCreate(config_file, confirm = FALSE) +#'s2dverification:::ConfigFileCreate(config_file, confirm = FALSE) #'# Open it into a configuration object #'configuration <- ConfigFileOpen(config_file) #'# Add an entry at the bottom of 4th level of file-per-startdate experiments diff --git a/R/ConfigEditDefinition.R b/R/ConfigEditDefinition.R index d831ffba..63f73971 100644 --- a/R/ConfigEditDefinition.R +++ b/R/ConfigEditDefinition.R @@ -40,6 +40,8 @@ #'# result #'match_info <- ConfigApplyMatchingEntries(configuration, 'tas', #' exp = c('ExampleExperiment2'), show_result = TRUE) +#' +#'@rdname ConfigEditDefinition #'@export ConfigEditDefinition <- function(configuration, name, value, confirm = TRUE) { continue <- TRUE @@ -57,3 +59,10 @@ ConfigEditDefinition <- function(configuration, name, value, confirm = TRUE) { configuration } +#'@rdname ConfigEditDefinition +#'@export +ConfigRemoveDefinition <- function(configuration, name) { + configuration$definitions[[name]] <- NULL + + configuration +} diff --git a/R/ConfigEditEntry.R b/R/ConfigEditEntry.R index 7d71dee4..619af304 100644 --- a/R/ConfigEditEntry.R +++ b/R/ConfigEditEntry.R @@ -1,11 +1,11 @@ #'Add, Remove Or Edit Entries In The Configuration #' #'ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions -#'to manage entries in a configuration object created with ConfigFileOpen(). +#'to manage entries in a configuration object created with ConfigFileOpen().\cr #'Before adding an entry, make sure the defaults don't do already what you -#'want (ConfigShowDefinitions(), ConfigShowTable()). +#'want (ConfigShowDefinitions(), ConfigShowTable()).\cr #'Before adding an entry, make sure it doesn't override and spoil what other -#'entries do (ConfigShowTable(), ConfigFileOpen()). +#'entries do (ConfigShowTable(), ConfigFileOpen()).\cr #'Before adding an entry, make sure there aren't other entries that already #'do what you want (ConfigShowSimilarEntries()). #' @@ -21,31 +21,32 @@ #' beginning. See ?ConfigFileOpen for more information. #' If 'dataset_name' and 'var_name' are specified this argument is ignored in #' ConfigRemoveEntry(). -#'@param dataset_name,var_name,main_path,file_path,nc_var_name,suffix,varmin,varmax -#'These parameters tell the dataset name, variable name, main path, ..., of -#' the entry to add, edit or remove. 'dataset_name' and 'var_name' can take -#' as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen). +#'@param dataset_name,var_name,main_path,file_path,nc_var_name,suffix,varmin,varmax +#' These parameters tell the dataset name, variable name, main path, ..., of +#' the entry to add, edit or remove.\cr 'dataset_name' and 'var_name' can take +#' as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen).\cr #' Other parameters can take as a value a shell globbing expression -#' (see ?ConfigFileOpen). +#' (see ?ConfigFileOpen).\cr #' 'dataset_name' and 'var_name' take by default the regular expression '.*' #' (match any dataset and variable name), and the others take by default '*' #' (associate to the pair 'dataset_name' and 'var_name' all the defined #' default values. In this case '*' has a special behaviour, it won't be #' used as a shell globbing expression. See ?ConfigFileOpen and -#' ?ConfigShowDefinitions). -#' 'var_min' and 'var_max' must be a character string. +#' ?ConfigShowDefinitions).\cr +#' 'var_min' and 'var_max' must be a character string.\cr #' To define these values, you can use defined variables via $VARIABLE_NAME$ #' or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for #' more information. -#' +#' #'@return The function returns an accordingly modified configuration object. #' To apply the changes in the configuration file it must be saved using #' ConfigFileSave(). #' -#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], [ConfigShowTable()]. +#'@seealso ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, +#' ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable #'@keywords datagen -#'@author History: -#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#'@author History:\cr +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version\cr #' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats #'@examples #'# Create an empty configuration file @@ -76,6 +77,7 @@ #'ConfigShowTable(configuration, "experiments") #'# Save the configuration #'ConfigFileSave(configuration, config_file, confirm = FALSE) +#'@rdname ConfigEditEntry #'@export ConfigEditEntry <- function(configuration, dataset_type, position, dataset_name = NULL, var_name = NULL, main_path = NULL, file_path = NULL, nc_var_name = NULL, suffix = NULL, varmin = NULL, varmax = NULL) { if (!(dataset_type %in% c('experiments', 'observations'))) { @@ -107,3 +109,100 @@ ConfigEditEntry <- function(configuration, dataset_type, position, dataset_name configuration } +#'@rdname ConfigEditEntry +#'@export +ConfigAddEntry <- function(configuration, dataset_type, position = 'last', dataset_name = ".*", var_name = ".*", main_path = "*", file_path = "*", nc_var_name = "*", suffix = "*", varmin = "*", varmax = "*") { + table_name <- dataset_type + if (dataset_name == ".*") { + if (var_name == ".*") { + level <- 1 + } else { + level <- 3 + } + } else { + if (var_name == ".*") { + level <- 2 + } else { + level <- 4 + } + } + + index_of_first <- 0 + index_of_last <- 0 + for (i in 1:level) { + index_of_first <- index_of_first + ifelse(i == 1, 1, length(configuration[[table_name]][[i - 1]])) + index_of_last <- index_of_last + length(configuration[[table_name]][[i]]) + } + + if (position == 'last') { + position <- index_of_last - index_of_first + 1 + 1 + } else if (position == 'first') { + position <- 1 + } else { + if (position < index_of_first || position > index_of_last + 1) { + stop("'position' must be in the range [index of first table entry in corresponding level, index of last table entry in corresponding level + 1]") + } + position <- position - index_of_first + 1 + } + + if (dataset_type == 'experiments' || dataset_type == 'observations') { + configuration[[table_name]][[level]] <- append(configuration[[table_name]][[level]], list(c(dataset_name, var_name, main_path, file_path, nc_var_name, suffix, varmin, varmax)), after = position - 1) + } else { + stop("'dataset_type' must be one of 'experiments' or 'observations'") + } + + configuration +} +#'@rdname ConfigEditEntry +#'@export +ConfigRemoveEntry <- function(configuration, dataset_type, dataset_name = NULL, var_name = NULL, position = NULL) { + table_name <- dataset_type + if (!is.null(dataset_name) && !is.null(var_name)) { + if (dataset_name == ".*") { + if (var_name == ".*") { + level <- 1 + } else { + level <- 3 + } + } else { + if (var_name == ".*") { + level <- 2 + } else { + level <- 4 + } + } + + position <- which(unlist(lapply(configuration[[table_name]][[level]], "[", 1)) == dataset_name & + unlist(lapply(configuration[[table_name]][[level]], "[", 2)) == var_name)[1] + if (is.na(position)) { + stop("No entry found that matches 'dataset_name' and 'var_name'.") + } + } else { + if (is.null(position)) { + stop("At least ('dataset_name', 'var_name') or 'position' must be specified.") + } + + all_entries <- length(unlist(configuration[[table_name]], recursive = FALSE)) + if (position < 1 || position > all_entries) { + stop("'position' must be in the range [1, # of table entries]") + } + + found <- FALSE + level <- 1 + index_of_first <- 1 + while (!found && level < 5) { + if (position <= (index_of_first + length(configuration[[table_name]][[level]]) - 1)) { + found <- TRUE + } else { + index_of_first <- index_of_first + length(configuration[[table_name]][[level]]) + level <- level + 1 + } + } + position <- position - index_of_first + 1 + } + + configuration[[table_name]][[level]][[position]] <- NULL + + configuration +} + diff --git a/R/ConfigFileCreate.R b/R/ConfigFileCreate.R deleted file mode 100644 index 98db52ff..00000000 --- a/R/ConfigFileCreate.R +++ /dev/null @@ -1,14 +0,0 @@ -ConfigFileCreate <- function(file_path, confirm = TRUE) { - success <- ConfigFileSave(list(definitions = list( - DEFAULT_EXP_MAIN_PATH = "$EXP_NAME$", - DEFAULT_EXP_FILE_PATH = "$STORE_FREQ$/$VAR_NAME$_$START_DATE$.nc", - DEFAULT_NC_VAR_NAME = "$VAR_NAME$", - DEFAULT_SUFFIX = "", DEFAULT_VAR_MIN = "", - DEFAULT_VAR_MAX = "", DEFAULT_OBS_MAIN_PATH = "$OBS_NAME$", - DEFAULT_OBS_FILE_PATH = "$STORE_FREQ$/$VAR_NAME$_$YEAR$$MONTH$.nc", - DEFAULT_DIM_NAME_LONGITUDES = "longitude", DEFAULT_DIM_NAME_LATITUDES = "latitude", - DEFAULT_DIM_NAME_MEMBERS = "ensemble")), file_path, confirm = confirm) - if (success) { - .warning("You have just created an empty configuration file. You can edit it with ConfigAddEntry(). You can edit the defaults according to your needs with the functions ConfigFileOpen(), ConfigEditDefinition() and ConfigFileSave() or edit the file manually as specified in ?ConfigFileOpen.") - } -} diff --git a/R/ConfigFileOpen.R b/R/ConfigFileOpen.R index afa67272..182b205e 100644 --- a/R/ConfigFileOpen.R +++ b/R/ConfigFileOpen.R @@ -6,8 +6,8 @@ #'@param silent Flag to activate or deactivate verbose mode. #' Defaults to FALSE (verbose mode on). #'@param configuration Configuration object to save in a file. -#'@param confirm Flag to stipulate whether to ask for confirmation when saving -#' a configuration file that already exists. +#'@param confirm Flag to stipulate whether to ask for confirmation when +#' saving a configuration file that already exists.\cr #' Defaults to TRUE (confirmation asked). #'@param stop TRUE/FALSE whether to raise an error if not all the mandatory #' default variables are defined in the configuration file. @@ -34,7 +34,7 @@ #' pattern when starting from scratch.} #' } #'How the configuration file works:\cr -#'~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#'~~~~~~~~~~~~~~~~~~~~~~~~~~~~\cr #'It contains one list and two tables.\cr #'Each of these have a header that starts with '!!'. These are key lines and #'should not be removed or reordered.\cr @@ -48,7 +48,7 @@ #'The key elements are a dataset identifier and a variable name.\cr #'The value elements are the dataset main path, dataset file path, the #'variable name inside the .nc file, a default suffix (explained below) and a -#'minimum and maximum vaues beyond which loaded data is deactivated. +#'minimum and maximum vaues beyond which loaded data is deactivated.\cr #'Given a dataset name and a variable name, a full path is obtained #'concatenating the main path and the file path.\cr #'Also the nc variable name, the suffixes and the limit values are obtained.\cr @@ -78,7 +78,7 @@ #'Additionally, from an element in an entry value you can access the other #'elements of the entry as:\cr #' $EXP_MAIN_PATH$, $EXP_FILE_PATH$, \cr$VAR_NAME$, $SUFFIX$, $VAR_MIN$, $VAR_MAX$\cr - +#'\cr #'The variable $SUFFIX$ is useful because it can be used to take part in the #'main or file path. For example: '/path/to$SUFFIX$/dataset/'.\cr #'It will be replaced by the value in the column that corresponds to the @@ -86,7 +86,7 @@ #''suffixexp' or 'suffixobs'.\cr #'This way the user is able to load two variables with the same name in the #'same dataset but with slight modifications, with a suffix anywhere in the -#'path to the data that advices of this slight modification.\cr +#'path to the data that advices of this slight modification.\cr\cr #'The entries in a table will be grouped in 4 levels of specificity: #' \enumerate{ #' \item{ @@ -121,7 +121,7 @@ #'more specific.\cr #'If there is more than one entry per group that match a given key pair, #'these will be applied in the order of appearance in the configuration file -#'(top to bottom).\cr +#'(top to bottom).\cr\cr #'An asterisk (*) in any value element will be interpreted as 'leave it as is #'or take the default value if yet not defined'.\cr #'The default values are defined in the following reserved variables:\cr @@ -129,22 +129,22 @@ #'$DEFAULT_OBS_MAIN_PATH$, $DEFAULT_OBS_FILE_PATH$, $DEFAULT_SUFFIX$, #'$DEFAULT_VAR_MIN$, $DEFAULT_VAR_MAX$, \cr #'$DEFAULT_DIM_NAME_LATITUDES$, $DEFAULT_DIM_NAME_LONGITUDES$, \cr -#'$DEFAULT_DIM_NAME_MEMBERS$\cr +#'$DEFAULT_DIM_NAME_MEMBERS$\cr\cr #'Trailing asterisks in an entry are not mandatory. For example\cr #' ecmwf, .*, /dataset/main/path/, *, *, *, *, *\cr #'will have the same effect as\cr -#' ecmwf, .*, /dataset/main/path/ +#' ecmwf, .*, /dataset/main/path/ \cr\cr #'A double quote only (") in any key or value element will be interpreted as #''fill in with the same value as the entry above'. #' #'@return -#'ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work. -#'ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise. +#'ConfigFileOpen() returns a configuration object with all the information for +#' the configuration file mechanism to work.\cr +#'ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise.\cr #'ConfigFileCreate() returns nothing. #' -#'@seealso [ConfigApplyMatchingEntries()]., [ConfigEditDefinition()]., -#' [ConfigEditEntry()]., [ConfigFileOpen()]., [ConfigShowSimilarEntries()]., -#' [ConfigShowTable()]. +#'@seealso ConfigApplyMatchingEntries, ConfigEditDefinition, +#' ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable #'@references #'[1] \url{https://stat.ethz.ch/R-manual/R-devel/library/base/html/regex.html}\cr #'[2] \url{http://tldp.org/LDP/abs/html/globbingref.html} @@ -175,6 +175,8 @@ #' exp = c('ExampleExperiment2'), show_result = TRUE) #'# Finally save the configuration file. #'ConfigFileSave(configuration, config_file, confirm = FALSE) +#' +#'@rdname ConfigFileOpen #'@export ConfigFileOpen <- function(file_path, silent = FALSE, stop = FALSE) { if (!silent) { @@ -316,3 +318,78 @@ ConfigFileOpen <- function(file_path, silent = FALSE, stop = FALSE) { experiments = exps, observations = obs)) } + +#'@rdname ConfigFileOpen +#'@export +ConfigFileCreate <- function(file_path, confirm = TRUE) { + success <- ConfigFileSave(list(definitions = list( + DEFAULT_EXP_MAIN_PATH = "$EXP_NAME$", + DEFAULT_EXP_FILE_PATH = "$STORE_FREQ$/$VAR_NAME$_$START_DATE$.nc", + DEFAULT_NC_VAR_NAME = "$VAR_NAME$", + DEFAULT_SUFFIX = "", DEFAULT_VAR_MIN = "", + DEFAULT_VAR_MAX = "", DEFAULT_OBS_MAIN_PATH = "$OBS_NAME$", + DEFAULT_OBS_FILE_PATH = "$STORE_FREQ$/$VAR_NAME$_$YEAR$$MONTH$.nc", + DEFAULT_DIM_NAME_LONGITUDES = "longitude", DEFAULT_DIM_NAME_LATITUDES = "latitude", + DEFAULT_DIM_NAME_MEMBERS = "ensemble")), file_path, confirm = confirm) + if (success) { + .warning("You have just created an empty configuration file. You can edit it with ConfigAddEntry(). You can edit the defaults according to your needs with the functions ConfigFileOpen(), ConfigEditDefinition() and ConfigFileSave() or edit the file manually as specified in ?ConfigFileOpen.") + } +} + +#'@rdname ConfigFileOpen +#'@export +ConfigFileSave <- function(configuration, file_path, confirm = TRUE) { + continue <- TRUE + if (file.exists(file_path)) { + if (confirm) { + while (continue != 'y' && continue != 'n') { + continue <- readline(paste0("WARNING: The configuration file '", file_path, "' already exists. It will be replaced. Continue? (y/n)\n")) + } + continue <- ifelse(continue == 'y', TRUE, FALSE) + } + } + if (continue) { + file_conn <- file(file_path) + file_text <- c( +"# s2dverification configuration file", +"#", +"# Check ?ConfigFileOpen after loading s2dverification for detailed ", +"# documentation on this configuration file.", +"" + ) + + file_text <- c(file_text, + paste(rep("#", nchar("definitions") + 2), collapse = ''), + paste0("!!definitions"), + paste(rep("#", nchar("definitions") + 2), collapse = '') + ) + defaults <- configuration$definitions[grep("^DEFAULT_", names(configuration$definitions))] + definitions <- configuration$definitions[-grep("^DEFAULT_", names(configuration$definitions))] + file_text <- c(file_text, as.vector(paste(names(defaults), unlist(defaults), sep = " = "))) + file_text <- c(file_text, as.vector(paste(names(definitions), unlist(definitions), sep = " = "))) + file_text <- c(file_text, "") + + table_names <- c("experiments", "observations") + for (table_name in table_names) { + if (table_name == "experiments") { + dataset_type <- 'exp' + } else { + dataset_type <- 'obs' + } + file_text <- c(file_text, +"", + paste(rep("#", nchar(table_name) + 11), collapse = ''), + paste0("!!table of ", gsub("_", " ", table_name)), + paste(rep("#", nchar(table_name) + 11), collapse = ''), + paste0("#", dataset_type, "_name, var_name[, ", dataset_type, "_main_path[, ", dataset_type, "_file_path[, nc_var_name[, suffix[, var_min[, var_max]]]]]]") + ) + # Some heavy entry processing still to do here, to put asterisks, empty spaces, double quotes, and reduce options + file_text <- c(file_text, unlist(lapply(configuration[[table_name]], function (x) lapply(x, function (y) paste(unlist(y), collapse = ", "))))) + } + + writeLines(file_text, file_conn) + close(file_conn) + } + + invisible(continue) +} diff --git a/R/ConfigFileSave.R b/R/ConfigFileSave.R deleted file mode 100644 index 7bb719f0..00000000 --- a/R/ConfigFileSave.R +++ /dev/null @@ -1,55 +0,0 @@ -ConfigFileSave <- function(configuration, file_path, confirm = TRUE) { - continue <- TRUE - if (file.exists(file_path)) { - if (confirm) { - while (continue != 'y' && continue != 'n') { - continue <- readline(paste0("WARNING: The configuration file '", file_path, "' already exists. It will be replaced. Continue? (y/n)\n")) - } - continue <- ifelse(continue == 'y', TRUE, FALSE) - } - } - if (continue) { - file_conn <- file(file_path) - file_text <- c( -"# s2dverification configuration file", -"#", -"# Check ?ConfigFileOpen after loading s2dverification for detailed ", -"# documentation on this configuration file.", -"" - ) - - file_text <- c(file_text, - paste(rep("#", nchar("definitions") + 2), collapse = ''), - paste0("!!definitions"), - paste(rep("#", nchar("definitions") + 2), collapse = '') - ) - defaults <- configuration$definitions[grep("^DEFAULT_", names(configuration$definitions))] - definitions <- configuration$definitions[-grep("^DEFAULT_", names(configuration$definitions))] - file_text <- c(file_text, as.vector(paste(names(defaults), unlist(defaults), sep = " = "))) - file_text <- c(file_text, as.vector(paste(names(definitions), unlist(definitions), sep = " = "))) - file_text <- c(file_text, "") - - table_names <- c("experiments", "observations") - for (table_name in table_names) { - if (table_name == "experiments") { - dataset_type <- 'exp' - } else { - dataset_type <- 'obs' - } - file_text <- c(file_text, -"", - paste(rep("#", nchar(table_name) + 11), collapse = ''), - paste0("!!table of ", gsub("_", " ", table_name)), - paste(rep("#", nchar(table_name) + 11), collapse = ''), - paste0("#", dataset_type, "_name, var_name[, ", dataset_type, "_main_path[, ", dataset_type, "_file_path[, nc_var_name[, suffix[, var_min[, var_max]]]]]]") - ) - # Some heavy entry processing still to do here, to put asterisks, empty spaces, double quotes, and reduce options - file_text <- c(file_text, unlist(lapply(configuration[[table_name]], function (x) lapply(x, function (y) paste(unlist(y), collapse = ", "))))) - } - - writeLines(file_text, file_conn) - close(file_conn) - } - - invisible(continue) -} diff --git a/R/ConfigRemoveDefinition.R b/R/ConfigRemoveDefinition.R deleted file mode 100644 index fff12908..00000000 --- a/R/ConfigRemoveDefinition.R +++ /dev/null @@ -1,5 +0,0 @@ -ConfigRemoveDefinition <- function(configuration, name) { - configuration$definitions[[name]] <- NULL - - configuration -} diff --git a/R/ConfigRemoveEntry.R b/R/ConfigRemoveEntry.R deleted file mode 100644 index 579a92bd..00000000 --- a/R/ConfigRemoveEntry.R +++ /dev/null @@ -1,50 +0,0 @@ -ConfigRemoveEntry <- function(configuration, dataset_type, dataset_name = NULL, var_name = NULL, position = NULL) { - table_name <- dataset_type - if (!is.null(dataset_name) && !is.null(var_name)) { - if (dataset_name == ".*") { - if (var_name == ".*") { - level <- 1 - } else { - level <- 3 - } - } else { - if (var_name == ".*") { - level <- 2 - } else { - level <- 4 - } - } - - position <- which(unlist(lapply(configuration[[table_name]][[level]], "[", 1)) == dataset_name & - unlist(lapply(configuration[[table_name]][[level]], "[", 2)) == var_name)[1] - if (is.na(position)) { - stop("No entry found that matches 'dataset_name' and 'var_name'.") - } - } else { - if (is.null(position)) { - stop("At least ('dataset_name', 'var_name') or 'position' must be specified.") - } - - all_entries <- length(unlist(configuration[[table_name]], recursive = FALSE)) - if (position < 1 || position > all_entries) { - stop("'position' must be in the range [1, # of table entries]") - } - - found <- FALSE - level <- 1 - index_of_first <- 1 - while (!found && level < 5) { - if (position <= (index_of_first + length(configuration[[table_name]][[level]]) - 1)) { - found <- TRUE - } else { - index_of_first <- index_of_first + length(configuration[[table_name]][[level]]) - level <- level + 1 - } - } - position <- position - index_of_first + 1 - } - - configuration[[table_name]][[level]][[position]] <- NULL - - configuration -} diff --git a/R/ConfigShowDefinitions.R b/R/ConfigShowDefinitions.R deleted file mode 100644 index b64772f7..00000000 --- a/R/ConfigShowDefinitions.R +++ /dev/null @@ -1,5 +0,0 @@ -ConfigShowDefinitions <- function(configuration) { - defaults <- grep("^DEFAULT_", names(configuration$definitions)) - invisible(lapply(as.vector(paste(names(configuration$definitions)[defaults], paste(unlist(configuration$definitions)[defaults], "\n", sep = ''), sep = " = ")), cat)) - invisible(lapply(as.vector(paste(names(configuration$definitions)[-defaults], paste(unlist(configuration$definitions)[-defaults], "\n", sep = ''), sep = " = ")), cat)) -} diff --git a/R/ConfigShowSimilarEntries.R b/R/ConfigShowSimilarEntries.R index 4b9a6fa9..47825b14 100644 --- a/R/ConfigShowSimilarEntries.R +++ b/R/ConfigShowSimilarEntries.R @@ -1,9 +1,9 @@ #'Find Similar Entries In Tables Of Datasets #' #'These functions help in finding similar entries in tables of supported -#'datasets by comparing all entries with some given information. +#'datasets by comparing all entries with some given information.\cr #'This is useful when dealing with complex configuration files and not sure -#'if already support certain variables or datasets. +#'if already support certain variables or datasets.\cr #'At least one field must be provided in ConfigShowSimilarEntries(). #'Other fields can be unspecified and won't be taken into account. If more #'than one field is provided, sameness is avreaged over all provided fields @@ -22,20 +22,20 @@ #'@param n_results Top 'n_results' alike results will be shown only. Defaults #' to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). #' +#'@details #'Sameness is calculated with string distances as specified by Simon White #'in [1]. #' #'@return These functions return information about the found matches. #' -#'@seealso [ConfigApplyMatchingEntries()], [ConfigEditDefinition()], -#' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], -#' [ConfigShowTable()]. +#'@seealso ConfigApplyMatchingEntries, ConfigEditDefinition, +#' ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable #'@references #'[1] Simon White, string seamness: #' \url{http://www.catalysoft.com/articles/StrikeAMatch.html} #'@keywords datagen #'@author History:\cr -#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version\cr #' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats #'@examples #'# Create an empty configuration file diff --git a/R/ConfigShowTable.R b/R/ConfigShowTable.R index 2a834e62..2610e883 100644 --- a/R/ConfigShowTable.R +++ b/R/ConfigShowTable.R @@ -15,8 +15,8 @@ #' [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], #' [ConfigShowTable()]. #'@keywords datagen -#'@author History:cr -#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version +#'@author History:\cr +#' 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - First version\cr #' 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Removed grid column and storage formats #'@return These functions return nothing. #' @@ -40,6 +40,8 @@ #'# Show tables, lists and definitions #'ConfigShowTable(configuration, 'experiments') #'ConfigShowDefinitions(configuration) +#' +#'@rdname ConfigShowTable #'@export ConfigShowTable <- function(configuration, dataset_type, line_numbers = NULL) { table_name <- dataset_type @@ -68,3 +70,10 @@ ConfigShowTable <- function(configuration, dataset_type, line_numbers = NULL) { } )) } +#'@rdname ConfigShowTable +#'@export +ConfigShowDefinitions <- function(configuration) { + defaults <- grep("^DEFAULT_", names(configuration$definitions)) + invisible(lapply(as.vector(paste(names(configuration$definitions)[defaults], paste(unlist(configuration$definitions)[defaults], "\n", sep = ''), sep = " = ")), cat)) + invisible(lapply(as.vector(paste(names(configuration$definitions)[-defaults], paste(unlist(configuration$definitions)[-defaults], "\n", sep = ''), sep = " = ")), cat)) +} diff --git a/R/Consist_Trend.R b/R/Consist_Trend.R index 7e4e00f4..827440fc 100644 --- a/R/Consist_Trend.R +++ b/R/Consist_Trend.R @@ -20,22 +20,23 @@ #' The trends will be provided respectively in field unit per month or per year. #' #'@return -#'\itemize{ -#' \item{$trend}{Trend coefficients of model and observational data with -#' dimensions:\cr +#'\item{$trend}{ +#' Trend coefficients of model and observational data with dimensions:\cr #' c(nmod/nexp + nobs, 3, nltime) up to\cr #' c(nmod/nexp + nobs, 3, nltime, nlevel, nlat, nlon)\cr #' The length 3 dimension corresponds to the lower limit of the 95\% #' confidence interval, the slope of the trends and the upper limit of the #' 95\% confidence interval. #' } -#' \item{$detrendedmod}{Same dimensions as var_exp with linearly detrended -#' values of var_exp along the second = start date dimension. +#'\item{$detrendedmod}{ +#' Same dimensions as var_exp with linearly detrended values of var_exp +#' along the second = start date dimension. #' } -#' \item{$detrendedobs}{Same dimensions as var_exp with linearly detrended -#' values of var_obs along the second = start date dimension. +#'\item{$detrendedobs}{ +#' Same dimensions as var_exp with linearly detrended values of var_obs +#' along the second = start date dimension. #' } -#'} +#' #'@keywords datagen #'@author History:\cr #' 0.1 - 2011-11 (V. Guemas, \email{vguemas@@ic3.cat}) - Original code\cr diff --git a/R/Corr.R b/R/Corr.R index b2743ef3..77fa2f91 100644 --- a/R/Corr.R +++ b/R/Corr.R @@ -15,7 +15,7 @@ #'The confidence interval is computed by a Fisher transformation.\cr #'The significance level relies on a one-sided student-T distribution.\cr #'We can modifiy the treshold of the test modifying siglev (default value=0.95).\cr\cr -#.Corr calculates the correlation between the ensemble mean and the +#'.Corr calculates the correlation between the ensemble mean and the #'observations, using an N by M matrix (exp) of forecasts and a vector of #'observations (obs) as input. #' @@ -26,7 +26,7 @@ #'@param poscor Dimension along which correlation are to be computed (the #' dimension of the start dates). #'@param compROW Data taken into account only if (compROW)th row is complete. -#' \cr Default = NULL. +#' Default = NULL. #'@param limits Complete between limits[1] & limits[2]. Default = NULL. #'@param siglev Significance level. Default = 0.95. #'@param method Type of correlation: 'pearson', 'spearman' or 'kendall'. @@ -101,6 +101,7 @@ #' Mean1Dim(smooth_ano_obs, dim_to_mean), #' tdim = 3, ensdim = 2) #' } +#'@rdname Corr #'@export Corr <- function(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, limits = NULL, siglev = 0.95, method = 'pearson', @@ -227,6 +228,8 @@ Corr <- function(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, # CORR } + +#'@rdname Corr #'@export .Corr <- function(exp, obs, siglev = 0.95, method = 'pearson', conf = TRUE, pval = TRUE) { diff --git a/R/EOF.R b/R/EOF.R index 8450701c..5c2116c3 100644 --- a/R/EOF.R +++ b/R/EOF.R @@ -13,21 +13,30 @@ #' covariance matrix (default, \code{FALSE}). #' #'@return -#'\itemize{ -#' \item{EOFs}{An array of EOF patterns normalized to 1 (unitless) with -#' dimensions (number of modes, number of latitudes, number of longitues). -#' Multiplying \code{EOFs} by \code{PCs} gives the original reconstructed field.} -#' \item{PCs}{An array of pincipal components with the units of the original -#' field to the power of 2, with dimensions (number of time steps, number of -#' modes). \code{PCs} contains already the percentage of explained variance -#' so, to reconstruct the original field it's only needed to multiply -#' \code{EOFs} by \code{PCs}.} -#' \item{var}{Percentage (%) of variance fraction of total variance explained -#' by each mode (number of modes).} -#' \item{mask}{Mask with dimensions (number of latitudes, number of longitudes).} -#' \item{wght}{Weights with dimensions (number of latitudes, number of longitudes).} +#'\item{EOFs}{ +#' An array of EOF patterns normalized to 1 (unitless) with dimensions +#' (number of modes, number of latitudes, number of longitues). +#' Multiplying \code{EOFs} by \code{PCs} gives the original reconstructed field. #'} -#'@seealso [ProjectField()], [NAO()], [PlotBoxWhisker()]. +#'\item{PCs}{ +#' An array of pincipal components with the units of the original field to +#' the power of 2, with dimensions (number of time steps, number of modes). +#' \code{PCs} contains already the percentage of explained variance so, +#' to reconstruct the original field it's only needed to multiply \code{EOFs} +#' by \code{PCs}. +#'} +#'\item{var}{ +#' Percentage (%) of variance fraction of total variance explained by each +#' mode (number of modes). +#'} +#'\item{mask}{ +#' Mask with dimensions (number of latitudes, number of longitudes). +#'} +#'\item{wght}{ +#' Weights with dimensions (number of latitudes, number of longitudes). +#'} +#' +#'@seealso ProjectField, NAO, PlotBoxWhisker #'@keywords datagen #'@author History:\cr #' 0.1 - 2012-10 (F. Lienert, \email{fabian.lienert@@ic3.cat}) - Original @@ -46,7 +55,7 @@ #' 2- Reduction of the number of transpositions and associated bug-fixes\cr #' 4- Remove of the obsolete LINPACK options\cr #'0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas@@bsc.es}) - Fixes:\cr -#' 1- Bug-fix in dimensions handling EOF composition restitutes now the\ +#' 1- Bug-fix in dimensions handling EOF composition restitutes now the #'original field in all cases\cr #' 2- Simplification of the convention transpose\cr #' 3- Options to use the correlation matrix rather than the diff --git a/R/FitAcfCoef.R b/R/FitAcfCoef.R index 1660fc59..311761ec 100644 --- a/R/FitAcfCoef.R +++ b/R/FitAcfCoef.R @@ -18,7 +18,7 @@ #'@keywords datagen #'@author History:\cr #'0.1 - 2012-06 (L. Auger, \email{ludovic.auger@meteo.fr}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'series <- GenSeries(1000, 0.35, 2, 1) #'estacf <- acf(series[951:1000], plot = FALSE)$acf diff --git a/R/FitAutocor.R b/R/FitAutocor.R index fae78687..903063b9 100644 --- a/R/FitAutocor.R +++ b/R/FitAutocor.R @@ -14,8 +14,8 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'series <- GenSeries(1000, 0.35, 2, 1) #'estacf <- acf(series[951:1000], plot = FALSE)$acf diff --git a/R/GenSeries.R b/R/GenSeries.R index f9a4c06b..132f0e48 100644 --- a/R/GenSeries.R +++ b/R/GenSeries.R @@ -14,7 +14,7 @@ #'@keywords datagen #'@author History:\cr #'0.1 - 2012-04 (L. Auger, \email{ludovic.auger@meteo.fr}) - Original code\cr -#'1.0 - 2012-04 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'1.0 - 2012-04 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'series <- GenSeries(1000, 0.35, 2, 1) #'plot(series, type = 'l') diff --git a/R/Histo2Hindcast.R b/R/Histo2Hindcast.R index efb77c91..cb93ae86 100644 --- a/R/Histo2Hindcast.R +++ b/R/Histo2Hindcast.R @@ -8,9 +8,9 @@ #' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes) up to\cr #' c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes, nlevel, nlat, nlon) #'@param sdatesin Start date of the input matrix 'YYYYMMDD'. -#'@param sdateout List of start dates of the output matrix +#'@param sdatesout List of start dates of the output matrix #' c('YYYYMMDD', 'YYYYMMDD', ...). -#'@param nleadtimeout Number of leadtimes in the output matrix. +#'@param nleadtimesout Number of leadtimes in the output matrix. #' #'@return An array with the same number of dimensions as varin, the same #' dimensions 1 and 2 and potentially the same dimensions 5 to 7. Dimensions @@ -18,8 +18,8 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2012-11 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2012-11 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'# See examples on Load() to understand the first lines in this example #' \dontrun{ diff --git a/R/InsertDim.R b/R/InsertDim.R index ecfc9a08..2e7a9b82 100644 --- a/R/InsertDim.R +++ b/R/InsertDim.R @@ -15,7 +15,7 @@ #'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr #'1.1 - 2015-03 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Improvements #'@examples -#' <- array(rnorm(15), dim = c(3, 1, 5, 1)) +#'a <- array(rnorm(15), dim = c(3, 1, 5, 1)) #'print(dim(a)) #'print(dim(a[, , , ])) #'print(dim(InsertDim(InsertDim(a[, , , ], 2, 1), 4, 1))) diff --git a/R/LeapYear.R b/R/LeapYear.R index 4f63dbfe..89865604 100644 --- a/R/LeapYear.R +++ b/R/LeapYear.R @@ -8,8 +8,8 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-03 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2011-03 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'print(LeapYear(1990)) #'print(LeapYear(1991)) diff --git a/R/Load.R b/R/Load.R index 5d574b50..fafadbae 100644 --- a/R/Load.R +++ b/R/Load.R @@ -328,7 +328,7 @@ #'@param nleadtime Deprecated. See parameter 'leadtimemax'. #'@param leadtimemin Only lead-times higher or equal to 'leadtimemin' are #' loaded. Takes by default value 1. -#'@param leatimemax Only lead-times lower or equal to 'leadtimemax' are loaded. +#'@param leadtimemax Only lead-times lower or equal to 'leadtimemax' are loaded. #' Takes by default the number of lead-times of the first experimental #' dataset in 'exp'.\cr #' If 'exp' is NULL this argument won't have any effect @@ -544,6 +544,7 @@ #' needed to keep all globbing expressions, \code{path_glob_permissive} can #' be set to \code{TRUE} or \code{'yes'}. #' +#'@details #'The two output matrices have between 2 and 6 dimensions:\cr #' \enumerate{ #' \item{Number of experimental/observational datasets.} @@ -671,11 +672,11 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr -#'1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Generalisation + parallelisation\cr -#'1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Improvements related to configuration file mechanism\cr -#'1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Added subsetting capabilities\cr +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN\cr +#'1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Generalisation + parallelisation\cr +#'1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Improvements related to configuration file mechanism\cr +#'1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Added subsetting capabilities #'@examples #'# Let's assume we want to perform verification with data of a variable #'# called 'tos' from a model called 'model' and observed data coming from @@ -837,7 +838,7 @@ #' latmin = 27, latmax = 48, #' lonmin = -12, lonmax = 40) #' } -#' +#'@import parallel bigmemory #'@export Load <- function(var, exp = NULL, obs = NULL, sdates, nmember = NULL, nmemberobs = NULL, nleadtime = NULL, leadtimemin = 1, diff --git a/R/NAO.R b/R/NAO.R index bfafacf8..c0d7c94d 100644 --- a/R/NAO.R +++ b/R/NAO.R @@ -36,32 +36,30 @@ #' this EOF. #' #'@return -#'\itemize{ -#' \item{NAO_exp}{ -#' Array of forecast NAO index in verification format (ensemble members, -#' start dates). -#' } -#' \item{NAO_obs}{ -#' Array of observed NAO index in verification format (1, number of start -#' dates). -#' } -#' \item{EOFs_obs}{ -#' EOFs of the observational references. +#'\item{NAO_exp}{ +#' Array of forecast NAO index in verification format (ensemble members, +#' start dates). #' } +#'\item{NAO_obs}{ +#' Array of observed NAO index in verification format (1, number of start +#' dates). +#'} +#'\item{EOFs_obs}{ +#' EOFs of the observational references. #'} #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2013-08 (F. Lienert, \email{flienert at ic3.cat}) - Original code\cr -#'0.2 - 2014-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Removing the +#'0.1 - 2013-08 (F. Lienert, \email{flienert@ic3.cat}) - Original code\cr +#'0.2 - 2014-03 (V. Guemas, \email{virginie.guemas@bsc.es}) - Removing the #' rotation\cr -#'0.3 - 2014-05 (L. Batte, \email{lauriane.batte at ic3.cat}) - Changes to +#'0.3 - 2014-05 (L. Batte, \email{lauriane.batte@ic3.cat}) - Changes to #' simplify function and add Pobs and Pmod options for NAO projection #' calculations\cr -#'0.4 - 2015-03 (L. Batte, \email{lauriane.batte at ic3.cat}) - Polarity +#'0.4 - 2015-03 (L. Batte, \email{lauriane.batte@ic3.cat}) - Polarity #' check and correction is wrong. Switched to have a negative NAO index when the #' anomaly pattern corresponds to NAO-. -#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - +#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - #' Formatted to CRAN #'@references #'Doblas-Reyes, F.J., Pavan, V. and Stephenson, D. (2003). The skill of diff --git a/R/Plot2VarsVsLTime.R b/R/Plot2VarsVsLTime.R index 3b5629a1..e5ee0556 100644 --- a/R/Plot2VarsVsLTime.R +++ b/R/Plot2VarsVsLTime.R @@ -46,9 +46,9 @@ #' smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr #' For more information about the parameters see `par`. #' +#'@details #'Examples of input:\cr -#'------------------\cr -#'\cr +#'------------------\cr\cr #'RMSE error for a number of experiments and along lead-time: (nexp, nltime) #' #'@keywords dynamic diff --git a/R/PlotEquiMap.R b/R/PlotEquiMap.R index c30e2ca0..70bf78ab 100644 --- a/R/PlotEquiMap.R +++ b/R/PlotEquiMap.R @@ -51,9 +51,7 @@ #' colors returned by 'color_fun'. If not available, it takes 'pink' by #' default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not #' specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. -#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators, -#'triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, -#'bar_tick_scale,bar_extra_margin Set of parameters to control the visual +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control the visual #' aspect of the drawn colour bar. See ?ColorBar for a full explanation. #'@param square Logical value to choose either to draw a coloured square for #' each grid cell in 'var' (TRUE; default) or to draw contour lines and fill @@ -159,29 +157,28 @@ #' For more information about the parameters see `par`. #' #'@return -#'\itemize{ -#' \item{brks}{ +#'\item{brks}{ #' Breaks used for colouring the map (and legend if drawleg = TRUE). -#' } -#' \item{cols}{ +#'} +#'\item{cols}{ #' Colours used for colouring the map (and legend if drawleg = TRUE). Always #' of length length(brks) - 1. -#' } -#' \item{col_inf}{ +#'} +#'\item{col_inf}{ #' Colour used to draw the lower triangle end in the colour bar (NULL if not -#' drawn at all). -#' } -#' \item{col_sup}{ +#' drawn at all). +#' } +#'\item{col_sup}{ #' Colour used to draw the upper triangle end in the colour bar (NULL if not -#' drawn at all). -#' } +#' drawn at all). #'} +#' #'@keywords dynamic #'@author History:\cr -#' 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code -#' 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@@ic3.cat}) - LabW -#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN -#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@ic3.cat}) - add winds +#' 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#' 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@@ic3.cat}) - LabW\cr +#' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to R CRAN\cr +#' 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@@ic3.cat}) - add winds\cr #' 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Refactored and added features, #' and adapted to new ColorBar. #'@examples @@ -214,7 +211,7 @@ #'PlotEquiMap(sampleData$mod[1, 1, 1, 1, , ], sampleData$lon, sampleData$lat, #' toptitle = 'Predicted sea surface temperature for Nov 1960 from 1st Nov', #' sizetit = 0.5) -#' +#'@import graphics GEOmap geomapdata maps #'@export PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, toptitle = NULL, sizetit = NULL, units = NULL, diff --git a/R/PlotLayout.R b/R/PlotLayout.R index 1be60fcf..8cc7d68a 100644 --- a/R/PlotLayout.R +++ b/R/PlotLayout.R @@ -104,10 +104,7 @@ #' respectively. 'colNA' takes 'white' by default. 'col_inf' and 'col_sup' #' will take the value of 'colNA' if not specified. See ?ColorBar for a full #' explanation on 'col_inf' and 'col_sup'. -#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators, -#'triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, -#'bar_tick_scale,bar_extra_margin Set of parameters to control the visual -#' aspect of the drawn colour bar. See ?ColorBar for a full explanation. +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control the visual aspect of the drawn colour bar. See ?ColorBar for a full explanation. #'@param drawleg Where to draw the common colour bar. Can take values TRUE, #' FALSE or:\cr #' 'up', 'u', 'U', 'top', 't', 'T', 'north', 'n', 'N'\cr @@ -144,27 +141,26 @@ #' 'fileout' has been specified. #' #'@return -#'\itemize{ -#' \item{brks}{ +#'\item{brks}{ #' Breaks used for colouring the map (and legend if drawleg = TRUE). -#' } -#' \item{cols}{ +#'} +#'\item{cols}{ #' Colours used for colouring the map (and legend if drawleg = TRUE). #' Always of length length(brks) - 1. -#' } -#' \item{col_inf}{ +#'} +#'\item{col_inf}{ #' Colour used to draw the lower triangle end in the colour bar #' (NULL if not drawn at all). -#' } -#' \item{col_sup}{ +#'} +#'\item{col_sup}{ #' Colour used to draw the upper triangle end in the colour bar #' (NULL if not drawn at all). -#' } -#' \item{layout_matrix}{ +#'} +#'\item{layout_matrix}{ #' Underlying matrix of the layout. Useful to later set any of the layout #' cells as current figure to add plot elements. See .SwitchToFigure. -#' } #'} +#' #'@keywords dynamic #'@author History:\cr #' 0.1 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Original code diff --git a/R/PlotStereoMap.R b/R/PlotStereoMap.R index 81ee27f1..cb3283ec 100644 --- a/R/PlotStereoMap.R +++ b/R/PlotStereoMap.R @@ -49,11 +49,8 @@ #' colors returned by 'color_fun'. If not available, it takes 'pink' by #' default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not #' specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'. -#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks, -#'draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale, -#'units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control -#' the visual aspect of the drawn colour bar. See ?ColorBar for a -#' full explanation. +#'@param color_fun,subsampleg,bar_extra_labels,draw_bar_ticks,draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control the visual +#' aspect of the drawn colour bar. See ?ColorBar for a full explanation. #'@param filled.continents Colour to fill in drawn projected continents. Takes #' the value gray(0.5) by default. If set to FALSE, continents are not #' filled in. @@ -114,27 +111,26 @@ #' For more information about the parameters see `par`. #' #'@return -#'\itemize{ -#' \item{brks}{ +#'\item{brks}{ #' Breaks used for colouring the map (and legend if drawleg = TRUE). -#' } -#' \item{cols}{ +#'} +#'\item{cols}{ #' Colours used for colouring the map (and legend if drawleg = TRUE). Always #' of length length(brks) - 1. -#' } -#' \item{col_inf}{ +#'} +#'\item{col_inf}{ #' Colour used to draw the lower triangle end in the colour bar (NULL if not #' drawn at all). -#' } -#' \item{col_sup}{ +#'} +#'\item{col_sup}{ #' Colour used to draw the upper triangle end in the colour bar (NULL if not #' drawn at all). -#' } #'} +#' #'@keywords dynamic #'@author History:\cr -#'1.0 - 2014-07 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code -#'1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze@@meteo.fr}) - Box(es) drawing +#'1.0 - 2014-07 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze@@meteo.fr}) - Box(es) drawing\cr #'1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Refacotred the function and #' merged in Jean-Philippe circle #' border and Constantin boxes. @@ -144,6 +140,7 @@ #'y <- seq(from = -90, to = 90, length.out = 50) #'PlotStereoMap(data, x, y, latlims = c(60, 90), brks = 50, #' toptitle = "This is the title") +#'@import mapproj #'@export PlotStereoMap <- function(var, lon, lat, latlims = c(60, 90), toptitle = NULL, sizetit = NULL, units = NULL, diff --git a/R/PlotVsLTime.R b/R/PlotVsLTime.R index 29f16a05..4e625337 100644 --- a/R/PlotVsLTime.R +++ b/R/PlotVsLTime.R @@ -51,6 +51,7 @@ #' smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr #' For more information about the parameters see `par`. #' +#'@details #'Examples of input:\cr #'Model and observed output from \code{Load()} then \code{Clim()} then #'\code{Ano()} then \code{Smoothing()}:\cr diff --git a/R/ProjectField.R b/R/ProjectField.R index 3b5b3ed3..07d890f6 100644 --- a/R/ProjectField.R +++ b/R/ProjectField.R @@ -19,17 +19,17 @@ #'@keywords datagen #'@seealso EOF, NAO, PlotBoxWhisker #'@author History:\cr -#'0.1 - 2012-03 (F. Lienert, \email{flienert at ic3.cat} - Original code -#'0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Bug-fixes:\cr +#'0.1 - 2012-03 (F. Lienert, \email{flienert@ic3.cat} - Original code\cr +#'0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte@ic3.cat} - Bug-fixes:\cr #' 1- Extra weighting of the anomalies before projection.\cr #' 2- Reversion of the anomalies along latitudes.\cr #' 3- Extra-normalisation not necessary.\cr -#'0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Bug-fixes:\cr +#'0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas@bsc.es} - Bug-fixes:\cr #' 1- Another extra-normalisation.\cr #' 2- 15 lines to compute the em reduced to 1. -#'0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Normalization\cr +#'0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte@ic3.cat} - Normalization\cr #'by std before returning PCs to be coherent with EOF().\cr -#'0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Fixes:\cr +#'0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas@bsc.es} - Fixes:\cr #' 1- Removal of lon, lat, ncpu and neofs argument unused\cr #' 2- Security checks ano and eof consistency\cr #' 3- Removal of the mask which is already contained in the EOFs\cr @@ -44,8 +44,8 @@ #' 6 - Since W *X = PC * EOF if EOF is multiplied back by the weights,\cr #'PC = W * X * t(EOF) and X the input field to be projected (X) needs to be\cr #'multiplied by W. Getting input dimensions. -#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN -#' (J.-P. Baudouin, \email{jean.baudouin at bsc.es}) - Example code and testing +#'1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN\cr +#' (J.-P. Baudouin, \email{jean.baudouin@bsc.es}) - Example code and testing #' #'@examples #'# See examples on Load() to understand the first lines in this example diff --git a/R/RMS.R b/R/RMS.R index e8a2a241..11406483 100644 --- a/R/RMS.R +++ b/R/RMS.R @@ -13,8 +13,7 @@ #'user wishes to account only for the forecasts for which observations are #'available at all leadtimes.\cr #'Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr -#'The confidence interval relies on a chi2 distribution.\cr -#'\cr +#'The confidence interval relies on a chi2 distribution.\cr\cr #'.RMS provides the same functionality but taking a matrix of ensemble #'members as input (exp). #' @@ -41,26 +40,25 @@ #'The 3rd dimension corresponds to the lower limit of the 95\% confidence #' interval (only present if \code{conf = TRUE}), the RMSE, and the upper #' limit of the 95\% confidence interval (only present if -#' \code{conf = TRUE}).\cr -#'\cr +#' \code{conf = TRUE}).\cr\cr #'.RMS: -#'\itemize{ -#' \item{$rms}{ +#'\item{$rms}{ #'The root mean square error, -#' } -#' \item{$conf_low}{ -#'Corresponding to the lower limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. -#' } -#' \item{$conf_high}{ -#'Corresponding to the upper limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. -#' } #'} +#'\item{$conf_low}{ +#' Corresponding to the lower limit of the \code{siglev}\% confidence interval +#' (only present if \code{conf = TRUE}) for the rms. +#'} +#'\item{$conf_high}{ +#' Corresponding to the upper limit of the \code{siglev}\% confidence interval +#' (only present if \code{conf = TRUE}) for the rms. +#'} #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-05 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN\cr -#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +#'0.1 - 2011-05 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens2@ic3.cat}) - Formatting to R CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() #'@examples #'# Load sample data as in Load() example: #'example(Load) @@ -95,6 +93,7 @@ #' tdim = 3, ensdim = 2) #' } #' +#'@rdname RMS #'@export RMS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, limits = NULL, siglev = 0.95, conf = TRUE) { @@ -198,7 +197,8 @@ RMS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, # enlrms } - +#'@rdname RMS +#'@export .RMS <- function(exp, obs, siglev = 0.95, conf = TRUE) { # # RMS & its confidence interval computation diff --git a/R/RMSSS.R b/R/RMSSS.R index a88e634c..a8c4bcee 100644 --- a/R/RMSSS.R +++ b/R/RMSSS.R @@ -10,8 +10,7 @@ #'grid point of the matrix (each latitude/longitude/level/leadtime).\cr #'The RMSSS are computed along the posRMS dimension which should correspond #'to the startdate dimension.\cr -#'The p-value is optionally provided by a one-sided Fisher test.\cr -#'\cr +#'The p-value is optionally provided by a one-sided Fisher test.\cr\cr #'.RMSSS provides the same functionality but taking a matrix of ensemble #'members as input (exp). #' @@ -28,13 +27,11 @@ #'@param obs Vector of the corresponding observations of length N. #' #'@return RMSSS: Array with dimensions:\cr -#'c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, +#' c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, #' all other dimensions of var_exp & var_obs except posRMS).\cr #'The 3rd dimension corresponds to the RMSSS and, if \code{pval = TRUE}, -#' the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr -#'\cr +#' the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr\cr #'.RMSSS: -#'\itemize{ #' \itemize{ #' \item{$rmsss}{ #' The RMSSS. @@ -44,8 +41,6 @@ #' the RMSSS. #' } #' } -#'} -#' #'@keywords datagen #'@author History:\cr #'0.1 - 2012-04 (V. Guemas, \email{vguemas@@bsc.es}) - Original code\cr @@ -74,7 +69,7 @@ #' Mean1Dim(ano_obs, 2), #' tdim = 3, ensdim = 2) #' } -#' +#'@rdname RMSSS #'@export RMSSS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, pval = TRUE) { # @@ -165,7 +160,8 @@ RMSSS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, pval = TRUE) { # enlRMSSS } - +#'@rdname RMSSS +#'@export .RMSSS <- function(exp, obs, pval = TRUE) { dif2 <- obs dif1 <- rowMeans(exp) - obs diff --git a/R/RatioRMS.R b/R/RatioRMS.R index be9355e8..9ac39041 100644 --- a/R/RatioRMS.R +++ b/R/RatioRMS.R @@ -2,8 +2,7 @@ #' #'Calculates the ratio of the RMSE for two forecasts of the same observations.\cr #'The ratio RMSE(ens, obs) / RMSE(ens.ref, obs) is output.\cr -#'The p-value is provided by a two-sided Fischer test.\cr -#'\cr +#'The p-value is provided by a two-sided Fischer test.\cr\cr #'.RatioRMS provides the same functionality but taking two matrices of #'ensemble members (ens and ens.ref) as input. #' @@ -23,8 +22,7 @@ #' posRMS where the dimension has length 2 if 'pval = TRUE', or 1 otherwise. #' The dimension of length 2 corresponds to the ratio between the RMSE #' (RMSE1/RMSE2) and the p-value of the two-sided Fisher test with Ho: -#' RMSE1/RMSE2 = 1.\cr -#'\cr +#' RMSE1/RMSE2 = 1.\cr\cr #'.RatioRMS:\cr #' \itemize{ #' \item{ratiorms}{The ratio of the RMSE of the two experimental datasets} @@ -33,9 +31,9 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-11 (V. Guemas, \email{vguemas at bsc.es}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN\cr -#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +#'0.1 - 2011-11 (V. Guemas, \email{vguemas@bsc.es}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() #'@examples #'# See examples on Load() to understand the first lines in this example #' \dontrun{ @@ -101,7 +99,7 @@ #' ano_exp_2, #' tdim = 2, ensdim = 1) #' } -#' +#'@rdname RatioRMS #'@export RatioRMS <- function(var_exp1, var_exp2, var_obs, posRMS = 1, pval = TRUE) { # @@ -189,7 +187,8 @@ RatioRMS <- function(var_exp1, var_exp2, var_obs, posRMS = 1, pval = TRUE) { # enlratiorms } - +#'@rdname RatioRMS +#'@export .RatioRMS <- function(exp, exp_ref, obs, pval = TRUE) { # # RMS ratio and its pvalue computation diff --git a/R/RatioSDRMS.R b/R/RatioSDRMS.R index e71595cb..d0664dd4 100644 --- a/R/RatioSDRMS.R +++ b/R/RatioSDRMS.R @@ -7,8 +7,7 @@ #'The ratio between the standard deviation of the members around the ensemble #'mean in var_exp and the RMSE between var_exp and var_obs is output for each #'experiment and each observational dataset.\cr -#'The p-value is provided by a one-sided Fischer test.\cr -#'\cr +#'The p-value is provided by a one-sided Fischer test.\cr\cr #'.RatioSDRMS provides the same functionality but taking a matrix of ensemble #'members as input (exp). #' @@ -26,8 +25,7 @@ #' up to c(nexp/nmod, nobs, 1 or 2, nltime, nlevel, nlat, nlon).\cr #'The 3rd dimension corresponds to the ratio (SD/RMSE) and the p.value #' (only present if \code{pval = TRUE}) of the one-sided Fisher test with -#'Ho: SD/RMSE = 1.\cr -#'\cr +#'Ho: SD/RMSE = 1.\cr\cr #'.RatioSDRMS: #' \itemize{ #' \item{$ratio}{ @@ -41,9 +39,9 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-12 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau-manubens at ic3.cat}) - Formatting to CRAN\cr -#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +#'0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau-manubens@ic3.cat}) - Formatting to CRAN\cr +#'1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() #'@examples #'# Load sample data as in Load() example: #'example(Load) @@ -67,7 +65,7 @@ #' Mean1Dim(sampleData$obs, 2), #' tdim = 3, ensdim = 2) #' } -#' +#'@rdname RatioSDRMS #'@export RatioSDRMS <- function(var_exp, var_obs, pval = TRUE) { # @@ -154,7 +152,8 @@ RatioSDRMS <- function(var_exp, var_obs, pval = TRUE) { # enlratiormssd } - +#'@rdname RatioSDRMS +#'@export .RatioSDRMS <- function(exp, obs, pval = TRUE) { # diff --git a/R/Regression.R b/R/Regression.R index c66a4166..c39c942d 100644 --- a/R/Regression.R +++ b/R/Regression.R @@ -12,7 +12,6 @@ #'@param posREG Position along which to compute the regression. #' #'@return -#'\itemize{ #' \item{$regression}{ #' Array with same dimensions as varx and vary except along posREG #' dimension which is replaced by a length 4 dimension, corresponding @@ -23,12 +22,11 @@ #' Same dimensions as vary filtered out from the regression onto varx #' along the posREG dimension. #' } -#'} #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2013-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2013-05 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'# See examples on Load() to understand the first lines in this example #' \dontrun{ diff --git a/R/SVD.R b/R/SVD.R index 8c5bde83..9f880da6 100644 --- a/R/SVD.R +++ b/R/SVD.R @@ -32,7 +32,6 @@ #' TRUE by default. #' #'@return -#'\itemize{ #' \item{$SC}{ #'Vector of squared covariance (n. of modes). #' } @@ -56,11 +55,10 @@ #' \item{$MCAs_V}{ #' Array of covariability patterns of predictand field (c(dim), n. of modes). #' } -#'} #'@keywords datagen #'@author History:\cr -#'0.1 - 2010-09 (J.-G. Serrano, \email{javier.garcia at bsc.es}) - Original code\cr -#'1.0 - 2016-04 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN +#'0.1 - 2010-09 (J.-G. Serrano, \email{javier.garcia@@bsc.es}) - Original code\cr +#'1.0 - 2016-04 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Formatting to R CRAN #'@examples #'# See examples on Load() to understand the first lines in this example #' \dontrun{ diff --git a/R/Season.R b/R/Season.R index ac8d7d48..d9f95a51 100644 --- a/R/Season.R +++ b/R/Season.R @@ -19,8 +19,8 @@ #' seasons are not accounted for. #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'# Load sample data as in Load() example: #'example(Load) diff --git a/R/SelIndices.R b/R/SelIndices.R index cbe04c21..6ef21ed8 100644 --- a/R/SelIndices.R +++ b/R/SelIndices.R @@ -13,8 +13,8 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-04 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2011-04 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN #'@examples #'a <- array(rnorm(24), dim = c(2, 3, 4, 1)) #'print(a) diff --git a/R/Smoothing.R b/R/Smoothing.R index e8e3375f..65aac018 100644 --- a/R/Smoothing.R +++ b/R/Smoothing.R @@ -13,9 +13,9 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN -#'1.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Adding +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr +#'1.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Adding #' security checks, fixing computation in cases where runmeanlen is odd and #' making it able to work on arrays of any number of dimensions. #'@examples @@ -31,7 +31,7 @@ #'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, #' toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", #' fileout = "tos_smoothed_ano.eps") -#' +#'@import plyr #'@export Smoothing <- function(var, runmeanlen = 12, numdimt = 4) { # Check var diff --git a/R/Spectrum.R b/R/Spectrum.R index 3e0ef84b..a0198351 100644 --- a/R/Spectrum.R +++ b/R/Spectrum.R @@ -15,8 +15,8 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2012-02 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN #'@examples #'# Load sample data as in Load() example: #'example(Load) diff --git a/R/Spread.R b/R/Spread.R index 2734b367..7cfe52ec 100644 --- a/R/Spread.R +++ b/R/Spread.R @@ -15,8 +15,9 @@ #'@param conf Whether to compute the confidence intervals or not. #' TRUE by default. #' -#'Example: -#'-------- +#'@details +#'Example:\cr +#'--------\cr #'To compute IQR, Max-Min, SD & MAD accross the members and start dates of #'var output from \code{Load()} or \code{Ano()} or \code{Ano_CrossValid()}, #'call:\cr @@ -44,8 +45,8 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +#'0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN #'@examples #'# Load sample data as in Load() example: #'example(Load) diff --git a/R/Trend.R b/R/Trend.R index ade3a389..40eb3f02 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -4,7 +4,7 @@ #'square fitting, and the associated error interval.\cr #'Trend() also provides the time series of the detrended ensemble mean #'forecasts.\cr -#'The confidence interval relies on a student-T distribution. +#'The confidence interval relies on a student-T distribution.\cr\cr #'.Trend provides the same functionality but taking a matrix ensemble members #'as input (exp). #' @@ -35,9 +35,9 @@ #' #'@keywords datagen #'@author History:\cr -#'0.1 - 2011-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN\cr -#'2.0 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapt to veriApply() +#'0.1 - 2011-05 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr +#'1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN\cr +#'2.0 - 2017-02 (A. Hunter, \email{alasdair.hunter@@bsc.es}) - Adapt to veriApply() #'@examples #'# Load sample data as in Load() example: #'example(Load) @@ -51,7 +51,7 @@ #' toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') #' -#' +#'@rdname Trend #'@export Trend <- function(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) { # @@ -134,6 +134,8 @@ Trend <- function(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) { invisible(list(trend = enltrend, detrended = enldetrend)) } +#'@rdname Trend +#'@export .Trend <- function(exp, interval = 1, siglev = 0.95, conf = TRUE) { ensmean <- rowMeans(exp, na.rm = TRUE) diff --git a/R/UltimateBrier.R b/R/UltimateBrier.R index 92e214da..01f407c8 100644 --- a/R/UltimateBrier.R +++ b/R/UltimateBrier.R @@ -62,11 +62,11 @@ #'dimensions except for the ones pointed by 'posmemb' and 'posdates'). #'@keywords datagen #'@author History:\cr -#'0.1 - 2015-05 (V. Guemas \email{virginie.guemas at bsc.es},\cr -#' C. Prodhomme \email{chloe.prodhomme at bsc.es},\cr -#' O. Bellprat \email{omar.bellprat at bsc.es}\cr -#' V. Torralba \email{veronica.torralba at bsc.es}\cr -#' N. Manubens, \email{nicolau.manubens at bsc.es}) - First version +#'0.1 - 2015-05 (V. Guemas \email{virginie.guemas@@bsc.es},\cr +#' C. Prodhomme \email{chloe.prodhomme@@bsc.es},\cr +#' O. Bellprat \email{omar.bellprat@@bsc.es}\cr +#' V. Torralba \email{veronica.torralba@@bsc.es}\cr +#' N. Manubens, \email{nicolau.manubens@@bsc.es}) - First version #'@examples #'# See ?Load for an explanation on the first part of this example. #' \dontrun{ @@ -101,7 +101,7 @@ #'ano_obs <- Ano(sampleData$obs, clim$clim_obs) #'bs <- UltimateBrier(ano_exp, ano_obs) #'bss <- UltimateBrier(ano_exp, ano_obs, type = 'BSS') -#' +#'@import SpecsVerification plyr #'@export UltimateBrier <- function(ano_exp, ano_obs, posdatasets = 1, posmemb = 2, posdates = 3, quantile = TRUE, diff --git a/R/clim.palette.R b/R/clim.palette.R index 0e9d24b3..1ca309b7 100644 --- a/R/clim.palette.R +++ b/R/clim.palette.R @@ -20,11 +20,7 @@ #'cols <- clim.colors(20) #'ColorBar(lims, cols) #' -#'@export -clim.colors <- function(n, palette = "bluered") { - clim.palette(palette)(n) -} - +#'@rdname clim.palette #'@export clim.palette <- function(palette = "bluered") { if (palette == "bluered") { @@ -54,3 +50,8 @@ clim.palette <- function(palette = "bluered") { } colorbar } +#'@rdname clim.palette +#'@export +clim.colors <- function(n, palette = "bluered") { + clim.palette(palette)(n) +} diff --git a/R/sampleDepthData.R b/R/sampleDepthData.R new file mode 100644 index 00000000..4785e16b --- /dev/null +++ b/R/sampleDepthData.R @@ -0,0 +1,27 @@ +#'Sample of Experimental Data for Forecast Verification In Function Of +#'Latitudes And Depths +#' +#'This data set provides data in function of latitudes and depths for the +#'variable 'tos', i.e. sea surface temperature, from the decadal climate +#'prediction experiment run at IC3 in the context of the CMIP5 project.\cr +#'Its name within IC3 local database is 'i00k'. +#' +#'@usage data(sampleDepthData) +#'@format The data set provides with a variable named 'sampleDepthData'.\cr\cr +#' +#'sampleDepthData$exp is an array that contains the experimental data and the +#'dimension meanings and values are:\cr +#' c(# of experimental datasets, # of members, # of starting dates, +#' # of lead-times, # of depths, # of latitudes)\cr +#' c(1, 5, 3, 60, 7, 21)\cr\cr +#' +#'sampleDepthData$obs should be an array that contained the observational data +#'but in this sample is not defined (NULL).\cr\cr +#' +#'sampleDepthData$depths is an array with the 7 longitudes covered by the data.\cr\cr +#' +#'sampleDepthData$lat is an array with the 21 latitudes covered by the data.\cr\cr +#'@name sampleDepthData +#'@docType data +#'@author Nicolau Manubens \email{nicolau.manubens@bsc.es} +#'@keywords data diff --git a/R/sampleMap.R b/R/sampleMap.R new file mode 100644 index 00000000..7f6ef817 --- /dev/null +++ b/R/sampleMap.R @@ -0,0 +1,46 @@ +#'Sample Of Observational And Experimental Data For Forecast Verification In Function Of Longitudes And Latitudes +#' +#'This data set provides data in function of longitudes and latitudes for the variable 'tos', i.e. sea surface temperature, over the mediterranean zone from the sample experimental and observational datasets attached to the package. See examples on how to use Load() for details.\cr\cr +#' +#'The data is provided through a variable named 'sampleMap' and is structured as expected from the 'Load()' function in the 's2dverification' package if was called as follows:\cr\cr +#' \preformatted{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp <- list( +#' name = 'experiment', +#' path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', +#' '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') +#' ) +#'obs <- list( +#' name = 'observation', +#' path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', +#' '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#' ) +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(exp), list(obs), startDates, +#' leadtimemin = 1, leadtimemax = 4, output = 'lonlat', +#' latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) +#' } +#'Check the documentation on 'Load()' in the package 's2dverification' for more information. +#' +#'@usage data(sampleMap) +#'@format +#'The data set provides with a variable named 'sampleMap'.\cr\cr +#' +#'sampleMap$mod is an array that contains the experimental data and the dimension meanings and values are:\cr +#' c(# of experimental datasets, # of members, # of starting dates, # of lead-times, # of latitudes, # of longitudes)\cr +#' c(1, 3, 5, 60, 2, 3)\cr\cr +#' +#'sampleMap$obs is an array that contains the observational data and the dimension meanings and values are:\cr +#' c(# of observational datasets, # of members, # of starting dates, # of lead-times, # of latitudes, # of longitudes)\cr +#' c(1, 1, 5, 60, 2, 3)\cr\cr +#' +#' sampleMap$lat is an array with the 2 latitudes covered by the data (see examples on Load() for details on why such low resolution).\cr\cr +#' +#' sampleMap$lon is an array with the 3 longitudes covered by the data (see examples on Load() for details on why such low resolution). +#' +#' @name sampleMap +#' @docType data +#' @author Nicolau Manubens \email{nicolau.manubens@bsc.es} +#' @keywords datasets + diff --git a/R/sampleTimeSeries.R b/R/sampleTimeSeries.R new file mode 100644 index 00000000..57f86b4f --- /dev/null +++ b/R/sampleTimeSeries.R @@ -0,0 +1,48 @@ +#'Sample Of Observational And Experimental Data For Forecast Verification As Area Averages +#' +#'This data set provides area averaged data for the variable 'tos', i.e. sea +#'surface temperature, over the mediterranean zone from the example datasets +#'attached to the package. See examples on Load() for more details.\cr\cr +#'The data is provided through a variable named 'sampleTimeSeries' and is +#'structured as expected from the 'Load()' function in the 's2dverification' +#'package if was called as follows:\cr\cr +#' \preformatted{ +#'data_path <- system.file('sample_data', package = 's2dverification') +#'exp <- list( +#' name = 'experiment', +#' path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', +#' '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') +#' ) +#'obs <- list( +#' name = 'observation', +#' path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', +#' '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') +#' ) +#'# Now we are ready to use Load(). +#'startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') +#'sampleData <- Load('tos', list(exp), list(obs), startDates, +#' output = 'areave', latmin = 27, latmax = 48, lonmin = -12, +#' lonmax = 40) +#' } +#'Check the documentation on 'Load()' in the package 's2dverification' for more information. +#' +#'@usage data(sampleTimeSeries) +#'@format The data set provides with a variable named 'sampleTimeSeries'.\cr\cr +#' +#'sampleTimeSeries$mod is an array that contains the experimental data and the dimension meanings and values are:\cr +#' c(# of experimental datasets, # of members, # of starting dates, # of lead-times)\cr +#' c(1, 3, 5, 60)\cr\cr +#' +#'sampleTimeSeries$obs is an array that contains the observational data and the dimension meanings and values are:\cr +#' c(# of observational datasets, # of members, # of starting dates, # of lead-times)\cr +#' c(1, 1, 5, 60)\cr\cr +#' +#'sampleTimeSeries$lat is an array with the 2 latitudes covered by the data that was area averaged to calculate the time series (see examples on Load() for details on why such low resolution).\cr\cr +#' +#'sampleTimeSeries$lon is an array with the 3 longitudes covered by the data that was area averaged to calculate the time series (see examples on Load() for details on why such low resolution). +#' +#' @name sampleTimeSeries +#' @docType data +#' @author Nicolau Manubens \email{nicolau.manubens@bsc.es} +#' @keywords datasets + diff --git a/man/ACC.Rd b/man/ACC.Rd index 6441151f..17e2d7cf 100644 --- a/man/ACC.Rd +++ b/man/ACC.Rd @@ -37,27 +37,28 @@ leadtimes always have the same number of members.} \item{siglev}{The confidence level for the computed confidence intervals.} } \value{ -A list of length 2: -\itemize{ - \item\code{$ACC} { +\item{ACC}{ If \code{conf = TRUE}, array with dimensions: c(nexp, nobs, nsdates, nleadtimes, 4) The fifth dimension of length 4 corresponds to the lower limit of the \code{siglev}\% confidence interval, the ACC, the upper limit of the \code{siglev}\% confidence interval and the \code{siglev}\% significance level. If \code{conf = FALSE}, the array of the Anomaly Correlation - Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes).} - \item\code{$MACC} { + Coefficient has dimensions c(nexp, nobs, nsdates, nleadtimes). +} +\item{MACC}{ The array of the Mean Anomaly Correlation Coefficient with dimensions - c(nexp, nobs, nleadtimes).} + c(nexp, nobs, nleadtimes). } } \description{ Calculates the Anomaly Correlation Coefficient for the ensemble mean of each model and the corresponding references for each startdate and each -leadtime. The domain of interest can be specified by providing the list +leadtime.\cr +The domain of interest can be specified by providing the list of longitudes/latitudes (lon/lat) of the grid together with the corners -of the domain lonlatbox = c(lonmin, lonmax, latmin, latmax). +of the domain:\cr +lonlatbox = c(lonmin, lonmax, latmin, latmax). } \examples{ # See ?Load for explanations on the first part of this example. @@ -95,14 +96,14 @@ acc <- ACC(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) PlotACC(acc$ACC, startDates) } \author{ -History: - 0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code - 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN - 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - optimization - 1.2 - 2014-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Bug-fixes: handling of NA & selection of domain + Simplification of code - 1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Boostrapping over members - 1.3.1 - 2014-09 (C. Prodhomme, chloe.prodhomme@bsc.es) - Add comments and minor style changes - 1.3.2 - 2015-02 (N. Manubens, nicolau.manubens@bsc.es) - Fixed ACC documentation and examples +History:\cr + 0.1 - 2013-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code\cr + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN\cr + 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - optimization\cr + 1.2 - 2014-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Bug-fixes: handling of NA & selection of domain + Simplification of code\cr + 1.3.0 - 2014-08 (V. Guemas, \email{virginie.guemas@bsc.es}) - Boostrapping over members\cr + 1.3.1 - 2014-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - Add comments and minor style changes\cr + 1.3.2 - 2015-02 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Fixed ACC documentation and examples } \references{ Joliffe and Stephenson (2012). Forecast Verification: A diff --git a/man/Alpha.Rd b/man/Alpha.Rd index b2992169..c2350b2a 100644 --- a/man/Alpha.Rd +++ b/man/Alpha.Rd @@ -23,7 +23,7 @@ This function, relying on the \code{FitAcfCoef()} function, estimates the autocorrelation at lag 1 of the xdata array following the method described in Guemas V., Auger L., Doblas-Reyes F., JAMC, 2013. After applying a linear detrending and/or a filtering of any frequency peak if requested, the sample -autocorrelation is estimated. +autocorrelation is estimated.\cr Then the theoretical autocorrelation of an AR1 is fitted to the sample autocorrelation using the Cardano's formula (see \code{FitAcfCoef()}) to obtain the autocorrelation at lag 1. This method assumes xdata is an AR1 @@ -37,8 +37,8 @@ print(alpha) } \author{ -History: - 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +History:\cr + 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/AnimateMap.Rd b/man/AnimateMap.Rd index a3576608..85eb04a9 100644 --- a/man/AnimateMap.Rd +++ b/man/AnimateMap.Rd @@ -78,13 +78,23 @@ Default: TRUE.} exp with successive obs, etc ...} \item{...}{Arguments to be passed to the method. Only accepts the following - graphical parameters: adj ann ask bty cex cex.axis cex.lab cex.main cex.sub - cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig - font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty - lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo - srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. - For more information about the parameters see `par`. - +graphical parameters:\cr +adj ann ask bty cex cex.axis cex.lab cex.main cex.sub + cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig +font font.axis font.lab font.main font.sub las lheight ljoin lmitre lty +lwd mai mar mex mfcol mfrow mfg mgp mkh oma omd omi page pch plt pty smo +srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. \cr +For more information about the parameters see `par`.} +} +\description{ +Create animations of maps in an equi-rectangular or stereographic +projection, showing the anomalies, the climatologies, the mean InterQuartile +Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, +the trends, the RMSE, the correlation or the RMSSS, between modelled and +observed data along the forecast time (lead-time) for all input experiments +and input observational datasets. +} +\details{ Examples of input: \enumerate{ \item{ @@ -114,15 +124,7 @@ Examples of input: (nmod, nobs, 3, nltime, nlat, nlon) animates correlations or RMS between each exp & each obs against leadtime. } -}} } -\description{ -Create animations of maps in an equi-rectangular or stereographic -projection, showing the anomalies, the climatologies, the mean InterQuartile -Range, Maximum-Mininum, Standard Deviation, Median Absolute Deviation, -the trends, the RMSE, the correlation or the RMSSS, between modelled and -observed data along the forecast time (lead-time) for all input experiments -and input observational datasets. } \examples{ # See ?Load for explanations on the first part of this example @@ -184,9 +186,9 @@ AnimateMap(rms, sampleData$lon, sampleData$lat, toptitle = fileout = 'rmse_dec.gif') } \author{ -History: - 1.0 - 2012-04 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code - 1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN +History:\cr + 1.0 - 2012-04 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code\cr + 1.1 - 2014-04 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN\cr 1.2 - 2015-05 (V. Guemas, \email{virginie.guemas@bsc.es}) - Use of PlotEquiMap and PlotStereoMap } \keyword{dynamic} diff --git a/man/Ano.Rd b/man/Ano.Rd index 7d21a2a8..a2deb373 100644 --- a/man/Ano.Rd +++ b/man/Ano.Rd @@ -7,16 +7,16 @@ Ano(var, clim) } \arguments{ -\item{var}{Model or observational data: -c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to -c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)} +\item{var}{Model or observational data:\cr +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to \cr +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr} -\item{clim}{Climatologies from clim: c(nmod/nexp/nobs, nltime) -up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or -c(nmod/nexp/nobs, nmemb/nparam, nltime) up to -c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or -c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to -c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) +\item{clim}{Climatologies from clim: c(nmod/nexp/nobs, nltime) \cr +up to c(nmod/nexp/nobs, nltime, nlevel, nlat, nlon) or \cr +c(nmod/nexp/nobs, nmemb/nparam, nltime) up to \cr +c(nmod/nexp/nobs, nmemb/nparam, nltime, nlevel, nlat, nlon) or \cr +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime) up to \cr +c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon) \cr depending on the options provided to \code{Clim()}.} } \value{ @@ -42,8 +42,8 @@ PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') } \author{ -History: - 0.1 - 2012-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +History:\cr + 0.1 - 2012-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN } \keyword{datagen} diff --git a/man/Ano_CrossValid.Rd b/man/Ano_CrossValid.Rd index 4d516922..bb2be436 100644 --- a/man/Ano_CrossValid.Rd +++ b/man/Ano_CrossValid.Rd @@ -7,21 +7,20 @@ Ano_CrossValid(var_exp, var_obs, memb = TRUE) } \arguments{ -\item{var_exp}{Model data: c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to -c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon).} +\item{var_exp}{Model data:\cr +c(nmod/nexp, nmemb/nparam, nsdates, nltime) up to \cr + c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon).} -\item{var_obs}{Observational data: c(nobs, nmemb, nsdates, nltime) up to -c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon).} +\item{var_obs}{Observational data: \cr +c(nobs, nmemb, nsdates, nltime) up to \cr + c(nobs, nmemb, nsdates, nltime, nlevel, nlat, nlon).} \item{memb}{TRUE/FALSE (1 climatology for each member/1 climatology averaging all the members). Default = TRUE.} } \value{ -A list of length 2: -\itemize{ - \item\code{$ano_exp} {Matrix with same dimensions as var_exp} - \item\code{$ano_obs} {Matrix with same dimensions as var_obs} -} +\item{$ano_exp}{Matrix with same dimensions as var_exp} + \item{$ano_obs}{Matrix with same dimensions as var_obs} } \description{ Computes the anomalies from the arrays of the experimental and observational @@ -37,8 +36,8 @@ PlotAno(anomalies$ano_exp, anomalies$ano_obs, startDates, legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano_crossvalid.eps') } \author{ -History: - 0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +History:\cr + 0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/ArrayToNetCDF.Rd b/man/ArrayToNetCDF.Rd index a18f3af9..77cbfaf8 100644 --- a/man/ArrayToNetCDF.Rd +++ b/man/ArrayToNetCDF.Rd @@ -24,44 +24,50 @@ stores them in a NetCDF file, using the \code{ncdf4} package. The full path and name of the resulting file must be specified. Metadata can be attached to the arrays and propagated into the NetCDF file in 3 possible ways: \itemize{ - \item{Via the list names if a list of arrays is provided: Each name in + \item{ + Via the list names if a list of arrays is provided: Each name in the input list, corresponding to one multidimensional array, will be - interpreted as the name of the variable it contains. - E.g: - \code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))), - file_path = 'example.nc')}} - \item{Via the dimension names of each provided array: The dimension names + interpreted as the name of the variable it contains.\cr + E.g:\cr + \code{ArrayToNetCDF(arrays = list(temperature = array(1:9, c(3, 3))),}\cr + \code{ file_path = 'example.nc')} + } + \item{ + Via the dimension names of each provided array: The dimension names of each of the provided arrays will be interpreted as names for the dimensions of the NetCDF files. Read further for special dimension names - that will trigger special behaviours, such as 'time' and 'var'. - E.g: - \code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10)) - names(dim(temperature)) <- c('longitude', 'latitude', 'time') - ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')}} - \item{Via the attribute 'variables' of each provided array: The arrays can + that will trigger special behaviours, such as 'time' and 'var'.\cr + E.g:\cr + \code{temperature <- array(rnorm(100 * 50 * 10), dim = c(100, 50, 10))}\cr + \code{names(dim(temperature)) <- c('longitude', 'latitude', 'time')}\cr + \code{ArrayToNetCDF(list(temperature = temperature), file_path = 'example.nc')} + } + \item{ + Via the attribute 'variables' of each provided array: The arrays can be provided with metadata in an attribute named 'variables', which is expected to be a named list of named lists, where the names of the container list are the names of the variables present in the provided array, and where each sub-list contains metadata for each of the variables. The attribute names and values supported in the sub-lists must follow the same format the package \code{ncdf4} uses to represent the NetCDF - file headers. - E.g: - \code{a <- array(1:400, dim = c(5, 10, 4, 2)) - metadata <- list(tos = list(addOffset = 100, - scaleFact = 10, - dim = list(list(name = 'time', - unlim = FALSE)))) - attr(a, 'variables') <- metadata - names(dim(a)) <- c('lat', 'lon', 'time', 'var') - ArrayToNetCDF(a, 'tmp.nc')}} + file headers.\cr + E.g:\cr + \code{a <- array(1:400, dim = c(5, 10, 4, 2))}\cr + \code{metadata <- list(tos = list(addOffset = 100,}\cr + \code{ scaleFact = 10,}\cr + \code{ dim = list(list(name = 'time',}\cr + \code{ unlim = FALSE))))}\cr + \code{attr(a, 'variables') <- metadata}\cr + \code{names(dim(a)) <- c('lat', 'lon', 'time', 'var')}\cr + \code{ArrayToNetCDF(a, 'tmp.nc')} + } } -The special dimension names are 'var'/'variable' and 'time'. +The special dimension names are 'var'/'variable' and 'time'.\cr If a dimension is named 'var' or 'variable', \code{ArrayToNetCDF} will interpret each array entry along such dimension corresponds to a separate new variable, hence will create a new variable inside the NetCDF file and will use it to store all the data in the provided array for the -corresponding entry along the 'var'/'variable' dimension. +corresponding entry along the 'var'/'variable' dimension.\cr If a dimension is named 'time', by default it will be interpreted and built as an unlimited dimension. The 'time' dimension must be the last dimension of the array (the right-most). If a 'var'/'variable' dimension is present, @@ -228,7 +234,7 @@ ArrayToNetCDF(list(tos, lon, lat), 'tmp.nc') } } \author{ -History: +History:\cr 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. } \keyword{datagen} diff --git a/man/BrierScore.Rd b/man/BrierScore.Rd index 7d3ff7f4..5094987c 100644 --- a/man/BrierScore.Rd +++ b/man/BrierScore.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/BrierScore.R \name{BrierScore} +\alias{.BrierScore} \alias{BrierScore} \title{Compute Brier Score And Its Decomposition And Brier Skill Score} \usage{ BrierScore(obs, pred, thresholds = seq(0, 1, 0.1)) + +.BrierScore(exp, obs, thresholds = seq(0, 1, 0.1)) } \arguments{ \item{obs}{Vector of binary observations (1 or 0).} @@ -46,8 +49,9 @@ Computes the Brier score (BS) and the components of its standard decomposition as well with the two within-bin components described in Stephenson et al., (2008). It also returns the bias-corrected decomposition of the BS (Ferro and Fricker, 2012). BSS having the climatology as the -reference forecast. BrierScore provides the same functionality, but taking a -matrix of ensemble members (exp) as input. +reference forecast. \cr\cr +.BrierScore provides the same functionality, but taking a matrix of ensemble +members (exp) as input. } \examples{ # Minimalist examples with BrierScore @@ -82,14 +86,14 @@ bs2 <- veriApply("BrierScore2", bins_ano_exp, Mean1Dim(bins_ano_ob,s 3), } } \author{ -History: - 0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues@ic3.cat}) - Original code +History:\cr + 0.1 - 2012-04 (L. Rodrigues, \email{lrodrigues@ic3.cat}) - Original code\cr 0.2 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() } \references{ -Wilks (2006) Statistical Methods in the Atmospheric Sciences. +Wilks (2006) Statistical Methods in the Atmospheric Sciences.\cr Stephenson et al. (2008). Two extra components in the Brier score decomposition. - Weather and Forecasting, 23: 752-757. + Weather and Forecasting, 23: 752-757.\cr Ferro and Fricker (2012). A bias-corrected decomposition of the BS. Quarterly Journal of the Royal Meteorological Society, DOI: 10.1002/qj.1924. } diff --git a/man/CDORemap.Rd b/man/CDORemap.Rd index f7edf1dd..b2d5eaa3 100644 --- a/man/CDORemap.Rd +++ b/man/CDORemap.Rd @@ -63,19 +63,17 @@ used (\code{tempdir()}).} } \value{ A list with the following components: -\itemize{ - \item\code{$data_array} {The interpolated data array (if an input array + \item{'data_array'}{The interpolated data array (if an input array is provided at all, NULL otherwise).} - \item\code{$lons} {The longitudes of the data on the destination grid.} - \item\code{$lats} {The latitudes of the data on the destination grid.} -} + \item{'lons'}{The longitudes of the data on the destination grid.} + \item{'lats'}{The latitudes of the data on the destination grid.} } \description{ This function takes as inputs a multidimensional array (optional), a vector or matrix of longitudes, a vector or matrix of latitudes, a destination grid specification, and the name of a method to be used to interpolate (one of those available in the 'remap' utility in CDO). The interpolated array is -returned (if provided) together with the new longitudes and latitudes. +returned (if provided) together with the new longitudes and latitudes.\cr\cr \code{CDORemap()} permutes by default the dimensions of the input array (if needed), splits it in chunks (CDO can work with data arrays of up to 4 dimensions), generates a file with the data of each chunk, interpolates it @@ -83,8 +81,9 @@ with CDO, reads it back into R and merges it into a result array. If no input array is provided, the longitude and latitude vectors will be transformed only. If the array is already on the desired destination grid, no transformation is performed (this behvaiour works only for lonlat and -gaussian grids). Any metadata attached to the input data array, longitudes -or latitudes will be preserved or accordingly modified. +gaussian grids). \cr\cr +Any metadata attached to the input data array, longitudes or latitudes will +be preserved or accordingly modified. } \examples{ \dontrun{ @@ -223,7 +222,7 @@ tas2 <- CDORemap(tas, lon, lat, 'external_file.nc', 'bil') } } \author{ -History: +History:\cr 0.0 - 2017-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. } \keyword{datagen} diff --git a/man/Clim.Rd b/man/Clim.Rd index 5cfd655f..3b11fe25 100644 --- a/man/Clim.Rd +++ b/man/Clim.Rd @@ -21,23 +21,20 @@ Default = FALSE.} \item{NDV}{TRUE/FALSE (if Fuckar method is applied or not). Default = FALSE.} } \value{ -A list of length 2: -\itemize{ - \item{clim_exp}{Array with same dimensions as var_exp except the third +\item{clim_exp}{Array with same dimensions as var_exp except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} - \item{clim_obs}{Array with same dimensions as var_obs except the third +\item{clim_obs}{Array with same dimensions as var_obs except the third (starting dates) and, depending on the parameters, the second (members), which disappear.} } -} \description{ This function computes only per-pair climatologies from the experimental and observational matrices output from \code{Load()}. To compute plain climatologies from only experimental or observational -data from \code{Load()}, the following code can be used: -\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean), - dim = dim(obs_datta)[-c(2, 3)])} +data from \code{Load()}, the following code can be used:\cr +\code{clim <- array(apply(obs_data, c(1, 4, 5, 6), mean),}\cr +\code{ dim = dim(obs_datta)[-c(2, 3)])}\cr The function \code{Clim()} computes per-pair climatologies using one of the following methods: \enumerate{ @@ -59,8 +56,8 @@ PlotClim(clim$clim_exp, clim$clim_obs, listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') } \author{ -History: - 0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code +History:\cr + 0.9 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN } \keyword{datagen} diff --git a/man/Cluster.Rd b/man/Cluster.Rd index 4ed144e2..70f22347 100644 --- a/man/Cluster.Rd +++ b/man/Cluster.Rd @@ -42,19 +42,31 @@ could lead to numerical singularity.} provided array in the parameter 'var', the first by default.} } \value{ -\itemize{ - \item{cluster}{A vector (time series) of integers indicating the occurrence +\item{cluster}{ + A vector (time series) of integers indicating the occurrence of a cluster, i.e., when 'certain data member in time is allocated to a - specific cluster (e.g., 2 1 3 1 1 1 ..).} - \item{centers}{A matrix of cluster centres or centroids (e.g. - [1:K, 1:spatial degrees of freedom]).} - \item{totss}{The total sum of squares.} - \item{withinss}{A vector of within-cluster sum of squares, one component - per cluster.} - \item{tot.withinss}{Total within-cluster sum of squares, - i.e., sum(withinss).} - \item{betweenss}{The between-cluster sum of squares, i.e. totss-tot.withinss.} - \item{size}{The number of points in each cluster.} + specific cluster (e.g., 2 1 3 1 1 1 ..). +} +\item{centers}{ + A matrix of cluster centres or centroids (e.g. + [1:K, 1:spatial degrees of freedom]). +} +\item{totss}{ + The total sum of squares. +} +\item{withinss}{ + A vector of within-cluster sum of squares, one component + per cluster. +} +\item{tot.withinss}{ + Total within-cluster sum of squares, + i.e., sum(withinss). +} +\item{betweenss}{ + The between-cluster sum of squares, i.e. totss-tot.withinss. +} +\item{size}{ +The number of points in each cluster. } } \description{ @@ -103,8 +115,8 @@ print(res2$cluster) print(res2$centers) } \author{ -History: - 1.0 # 2014-10 (N.S. Fuckar, neven.fuckar@bsc.es) # Original code +History:\cr + 1.0 # 2014-10 (N.S. Fuckar, \email{neven.fuckar@bsc.es}) - Original code } \references{ Wilks, 2011, Statistical Methods in the Atmospheric Sciences, 3rd ed., Elsevire, pp 676. diff --git a/man/ColorBar.Rd b/man/ColorBar.Rd index 257c7c5d..205c25e4 100644 --- a/man/ColorBar.Rd +++ b/man/ColorBar.Rd @@ -32,7 +32,7 @@ ColorBar(brks = NULL, cols = NULL, vertical = TRUE, subsampleg = NULL, \item{cols}{Vector of length(brks) - 1 valid colour identifiers, for each interval defined by the breaks. This parameter is optional and will be filled in with a vector of length(brks) - 1 colours generated with the -function provided in 'color_fun' (\code{clim.colors} by default). 'cols' +function provided in 'color_fun' (\code{clim.colors} by default).\cr 'cols' can have one additional colour at the beginning and/or at the end with the aim to colour field values beyond the range of interest represented in the colour bar. If any of these extra colours is provided, parameter @@ -129,22 +129,28 @@ overflowing the figure region. This does not have effect over the labels provided in 'extra_labels'. Takes 4 by default.} \item{...}{Arguments to be passed to the method. Only accepts the following - graphical parameters: adj ann ask bg bty cex.lab cex.main cex.sub cin + graphical parameters:\cr adj ann ask bg bty cex.lab cex.main cex.sub cin col.axis col.lab col.main col.sub cra crt csi cxy err family fg fig fin font font.axis font.lab font.main font.sub lend lheight ljoin lmitre lty lwd mai mex mfcol mfrow mfg mkh oma omd omi page pch pin plt pty smo srt - tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog. For more + tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog.\cr For more information about the parameters see `par`.} } \value{ -\itemize{ - \item{brks}{Breaks used for splitting the range in intervals.} - \item{cols}{Colours generated for each of the length(brks) - 1 intervals. - Always of length length(brks) - 1.} - \item{col_inf}{Colour used to draw the lower triangle end in the colour - bar (NULL if not drawn at all).} - \item{col_sup}{Colour used to draw the upper triangle end in the colour - bar (NULL if not drawn at all).} +\item{brks}{ + Breaks used for splitting the range in intervals. +} +\item{cols}{ + Colours generated for each of the length(brks) - 1 intervals. + Always of length length(brks) - 1. +} +\item{col_inf}{ + Colour used to draw the lower triangle end in the colour + bar (NULL if not drawn at all). +} +\item{col_sup}{ + Colour used to draw the upper triangle end in the colour + bar (NULL if not drawn at all). } } \description{ @@ -154,11 +160,12 @@ multipanels or plots. It is possible to draw triangles at the ends of the colour bar to represent values that go beyond the range of interest. A number of options is provided to adjust the colours and the position and size of the components. The drawn colour bar spans a whole figure region -and is compatible with figure layouts.\cr\cr The generated colour bar -consists of a set of breaks that define the length(brks) - 1 intervals to -classify each of the values in each of the grid cells of a two-dimensional -field. The corresponding grid cell of a given value of the field will be -coloured in function of the interval it belongs to. +and is compatible with figure layouts.\cr\cr +The generated colour bar consists of a set of breaks that define the +length(brks) - 1 intervals to classify each of the values in each of the +grid cells of a two-dimensional field. The corresponding grid cell of a +given value of the field will be coloured in function of the interval it +belongs to.\cr\cr The only mandatory parameters are 'var_limits' or 'brks' (in its second format, see below). } @@ -169,12 +176,12 @@ lims <- seq(-1, 1, 0.2) ColorBar(lims, cols) } \author{ -History: +History:\cr 0.1 - 2012-04 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code\cr - 0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo@bsc.es}) - Vert option - 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN - 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - Add cex option - 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - New ColorBar + 0.2 - 2013-04 (I. Andreu-Burillo, \email{isabel.andreu-burillo@bsc.es}) - Vert option\cr + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN\cr + 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@bsc.es}) - Add cex option\cr + 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - New ColorBar\cr (V. Torralba, \email{veronica.torralba@bsc.es}) } \keyword{dplot} diff --git a/man/Composite.Rd b/man/Composite.Rd index bf5009ad..4e990020 100644 --- a/man/Composite.Rd +++ b/man/Composite.Rd @@ -26,16 +26,14 @@ size (FALSE that is the default) for the number of degrees of freedom.} \item{fileout}{Name of the .sav output file (NULL is the default).} } \value{ -\itemize{ - \item{$composite}{ - 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) - or only k=1 for any specific cluster, i.e., case (*2). - } - \item{$pvalue}{ - 3-d array (x, y, k) containing the pvalue of the - composites obtained through a t-test that accounts for the serial - dependence of the data with the same structure as Composite. - } +\item{$composite}{ + 3-d array (x, y, k) containing the composites k=1,..,K for case (*1) + or only k=1 for any specific cluster, i.e., case (*2). +} +\item{$pvalue}{ + 3-d array (x, y, k) containing the pvalue of the + composites obtained through a t-test that accounts for the serial + dependence of the data with the same structure as Composite. } } \description{ diff --git a/man/ConfigApplyMatchingEntries.Rd b/man/ConfigApplyMatchingEntries.Rd index b97a3b36..626e385d 100644 --- a/man/ConfigApplyMatchingEntries.Rd +++ b/man/ConfigApplyMatchingEntries.Rd @@ -44,7 +44,7 @@ inside NetCDF files, ... \examples{ # Create an empty configuration file config_file <- paste0(tempdir(), "/example.conf") -ConfigFileCreate(config_file, confirm = FALSE) +s2dverification:::ConfigFileCreate(config_file, confirm = FALSE) # Open it into a configuration object configuration <- ConfigFileOpen(config_file) # Add an entry at the bottom of 4th level of file-per-startdate experiments @@ -64,14 +64,14 @@ match_info <- ConfigApplyMatchingEntries(configuration, 'tas', exp = c('ExampleExperiment2'), show_result = TRUE) } \author{ -History: - 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version +History:\cr + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version\cr 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage types } \seealso{ -[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], - [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], - [ConfigShowTable()]. +ConfigApplyMatchingEntries, ConfigEditDefinition, + ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, + ConfigShowTable } \keyword{datagen} diff --git a/man/ConfigEditDefinition.Rd b/man/ConfigEditDefinition.Rd index f17269ef..b1f7c882 100644 --- a/man/ConfigEditDefinition.Rd +++ b/man/ConfigEditDefinition.Rd @@ -2,9 +2,12 @@ % Please edit documentation in R/ConfigEditDefinition.R \name{ConfigEditDefinition} \alias{ConfigEditDefinition} +\alias{ConfigRemoveDefinition} \title{Add Modify Or Remove Variable Definitions In Configuration} \usage{ ConfigEditDefinition(configuration, name, value, confirm = TRUE) + +ConfigRemoveDefinition(configuration, name) } \arguments{ \item{configuration}{Configuration object obtained wit ConfigFileOpen() or @@ -47,6 +50,7 @@ configuration <- ConfigEditEntry(configuration, "experiments", 1, # result match_info <- ConfigApplyMatchingEntries(configuration, 'tas', exp = c('ExampleExperiment2'), show_result = TRUE) + } \author{ History: diff --git a/man/ConfigEditEntry.Rd b/man/ConfigEditEntry.Rd index e6f2fb88..83973231 100644 --- a/man/ConfigEditEntry.Rd +++ b/man/ConfigEditEntry.Rd @@ -1,12 +1,22 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/ConfigEditEntry.R \name{ConfigEditEntry} +\alias{ConfigAddEntry} \alias{ConfigEditEntry} +\alias{ConfigRemoveEntry} \title{Add, Remove Or Edit Entries In The Configuration} \usage{ ConfigEditEntry(configuration, dataset_type, position, dataset_name = NULL, var_name = NULL, main_path = NULL, file_path = NULL, nc_var_name = NULL, suffix = NULL, varmin = NULL, varmax = NULL) + +ConfigAddEntry(configuration, dataset_type, position = "last", + dataset_name = ".*", var_name = ".*", main_path = "*", + file_path = "*", nc_var_name = "*", suffix = "*", varmin = "*", + varmax = "*") + +ConfigRemoveEntry(configuration, dataset_type, dataset_name = NULL, + var_name = NULL, position = NULL) } \arguments{ \item{configuration}{Configuration object obtained via ConfigFileOpen() @@ -25,17 +35,17 @@ If 'dataset_name' and 'var_name' are specified this argument is ignored in ConfigRemoveEntry().} \item{dataset_name, var_name, main_path, file_path, nc_var_name, suffix, varmin, varmax}{These parameters tell the dataset name, variable name, main path, ..., of -the entry to add, edit or remove. 'dataset_name' and 'var_name' can take -as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen). +the entry to add, edit or remove.\cr 'dataset_name' and 'var_name' can take +as a value a POSIX 1003.2 regular expression (see ?ConfigFileOpen).\cr Other parameters can take as a value a shell globbing expression -(see ?ConfigFileOpen). +(see ?ConfigFileOpen).\cr 'dataset_name' and 'var_name' take by default the regular expression '.*' (match any dataset and variable name), and the others take by default '*' (associate to the pair 'dataset_name' and 'var_name' all the defined default values. In this case '*' has a special behaviour, it won't be used as a shell globbing expression. See ?ConfigFileOpen and -?ConfigShowDefinitions). -'var_min' and 'var_max' must be a character string. +?ConfigShowDefinitions).\cr +'var_min' and 'var_max' must be a character string.\cr To define these values, you can use defined variables via $VARIABLE_NAME$ or other entry attributes via $ATTRIBUTE_NAME$. See ?ConfigFileOpen for more information.} @@ -47,11 +57,11 @@ The function returns an accordingly modified configuration object. } \description{ ConfigAddEntry(), ConfigEditEntry() and ConfigRemoveEntry() are functions -to manage entries in a configuration object created with ConfigFileOpen(). +to manage entries in a configuration object created with ConfigFileOpen().\cr Before adding an entry, make sure the defaults don't do already what you -want (ConfigShowDefinitions(), ConfigShowTable()). +want (ConfigShowDefinitions(), ConfigShowTable()).\cr Before adding an entry, make sure it doesn't override and spoil what other -entries do (ConfigShowTable(), ConfigFileOpen()). +entries do (ConfigShowTable(), ConfigFileOpen()).\cr Before adding an entry, make sure there aren't other entries that already do what you want (ConfigShowSimilarEntries()). } @@ -86,12 +96,13 @@ ConfigShowTable(configuration, "experiments") ConfigFileSave(configuration, config_file, confirm = FALSE) } \author{ -History: - 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version +History:\cr + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version\cr 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats } \seealso{ -[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], [ConfigShowTable()]. +ConfigApplyMatchingEntries, ConfigEditDefinition, ConfigEditEntry, + ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable } \keyword{datagen} diff --git a/man/ConfigFileOpen.Rd b/man/ConfigFileOpen.Rd index d515646e..cff7427e 100644 --- a/man/ConfigFileOpen.Rd +++ b/man/ConfigFileOpen.Rd @@ -1,10 +1,16 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/ConfigFileOpen.R \name{ConfigFileOpen} +\alias{ConfigFileCreate} \alias{ConfigFileOpen} +\alias{ConfigFileSave} \title{Functions To Create Open And Save Configuration File} \usage{ ConfigFileOpen(file_path, silent = FALSE, stop = FALSE) + +ConfigFileCreate(file_path, confirm = TRUE) + +ConfigFileSave(configuration, file_path, confirm = TRUE) } \arguments{ \item{file_path}{Path to the configuration file to create/open/save.} @@ -15,15 +21,16 @@ Defaults to FALSE (verbose mode on).} \item{stop}{TRUE/FALSE whether to raise an error if not all the mandatory default variables are defined in the configuration file.} -\item{configuration}{Configuration object to save in a file.} - -\item{confirm}{Flag to stipulate whether to ask for confirmation when saving -a configuration file that already exists. +\item{confirm}{Flag to stipulate whether to ask for confirmation when +saving a configuration file that already exists.\cr Defaults to TRUE (confirmation asked).} + +\item{configuration}{Configuration object to save in a file.} } \value{ -ConfigFileOpen() returns a configuration object with all the information for the configuration file mechanism to work. -ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise. +ConfigFileOpen() returns a configuration object with all the information for + the configuration file mechanism to work.\cr +ConfigFileSave() returns TRUE if the file has been saved and FALSE otherwise.\cr ConfigFileCreate() returns nothing. } \description{ @@ -51,7 +58,7 @@ folder in the package: pattern when starting from scratch.} } How the configuration file works:\cr -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~\cr It contains one list and two tables.\cr Each of these have a header that starts with '!!'. These are key lines and should not be removed or reordered.\cr @@ -65,7 +72,7 @@ other elements.\cr The key elements are a dataset identifier and a variable name.\cr The value elements are the dataset main path, dataset file path, the variable name inside the .nc file, a default suffix (explained below) and a -minimum and maximum vaues beyond which loaded data is deactivated. +minimum and maximum vaues beyond which loaded data is deactivated.\cr Given a dataset name and a variable name, a full path is obtained concatenating the main path and the file path.\cr Also the nc variable name, the suffixes and the limit values are obtained.\cr @@ -95,6 +102,7 @@ store frequency, the current startdate Load() is fetching, etc:\cr Additionally, from an element in an entry value you can access the other elements of the entry as:\cr $EXP_MAIN_PATH$, $EXP_FILE_PATH$, \cr$VAR_NAME$, $SUFFIX$, $VAR_MIN$, $VAR_MAX$\cr +\cr The variable $SUFFIX$ is useful because it can be used to take part in the main or file path. For example: '/path/to$SUFFIX$/dataset/'.\cr It will be replaced by the value in the column that corresponds to the @@ -102,7 +110,7 @@ suffix unless the user specifies a different suffix via the parameter 'suffixexp' or 'suffixobs'.\cr This way the user is able to load two variables with the same name in the same dataset but with slight modifications, with a suffix anywhere in the -path to the data that advices of this slight modification.\cr +path to the data that advices of this slight modification.\cr\cr The entries in a table will be grouped in 4 levels of specificity: \enumerate{ \item{ @@ -137,7 +145,7 @@ full path, all the rules that match will be applied from more general to more specific.\cr If there is more than one entry per group that match a given key pair, these will be applied in the order of appearance in the configuration file -(top to bottom).\cr +(top to bottom).\cr\cr An asterisk (*) in any value element will be interpreted as 'leave it as is or take the default value if yet not defined'.\cr The default values are defined in the following reserved variables:\cr @@ -145,11 +153,11 @@ The default values are defined in the following reserved variables:\cr $DEFAULT_OBS_MAIN_PATH$, $DEFAULT_OBS_FILE_PATH$, $DEFAULT_SUFFIX$, $DEFAULT_VAR_MIN$, $DEFAULT_VAR_MAX$, \cr $DEFAULT_DIM_NAME_LATITUDES$, $DEFAULT_DIM_NAME_LONGITUDES$, \cr -$DEFAULT_DIM_NAME_MEMBERS$\cr +$DEFAULT_DIM_NAME_MEMBERS$\cr\cr Trailing asterisks in an entry are not mandatory. For example\cr ecmwf, .*, /dataset/main/path/, *, *, *, *, *\cr will have the same effect as\cr - ecmwf, .*, /dataset/main/path/ + ecmwf, .*, /dataset/main/path/ \cr\cr A double quote only (") in any key or value element will be interpreted as 'fill in with the same value as the entry above'. } @@ -176,6 +184,7 @@ match_info <- ConfigApplyMatchingEntries(configuration, 'tas', exp = c('ExampleExperiment2'), show_result = TRUE) # Finally save the configuration file. ConfigFileSave(configuration, config_file, confirm = FALSE) + } \author{ History: @@ -187,9 +196,8 @@ History: [2] \url{http://tldp.org/LDP/abs/html/globbingref.html} } \seealso{ -[ConfigApplyMatchingEntries()]., [ConfigEditDefinition()]., - [ConfigEditEntry()]., [ConfigFileOpen()]., [ConfigShowSimilarEntries()]., - [ConfigShowTable()]. +ConfigApplyMatchingEntries, ConfigEditDefinition, + ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable } \keyword{datagen} diff --git a/man/ConfigShowSimilarEntries.Rd b/man/ConfigShowSimilarEntries.Rd index d1498dd2..312da795 100644 --- a/man/ConfigShowSimilarEntries.Rd +++ b/man/ConfigShowSimilarEntries.Rd @@ -30,24 +30,25 @@ ConfigFileCreate() or ConfigFileOpen().} \item{varmax}{Optional variable maximum to look for similars of.} \item{n_results}{Top 'n_results' alike results will be shown only. Defaults - to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars(). - -Sameness is calculated with string distances as specified by Simon White -in [1].} +to 10 in ConfigShowSimilarEntries() and to 5 in ConfigShowSimilarVars().} } \value{ These functions return information about the found matches. } \description{ These functions help in finding similar entries in tables of supported -datasets by comparing all entries with some given information. +datasets by comparing all entries with some given information.\cr This is useful when dealing with complex configuration files and not sure -if already support certain variables or datasets. +if already support certain variables or datasets.\cr At least one field must be provided in ConfigShowSimilarEntries(). Other fields can be unspecified and won't be taken into account. If more than one field is provided, sameness is avreaged over all provided fields and entries are sorted from higher average to lower. } +\details{ +Sameness is calculated with string distances as specified by Simon White +in [1]. +} \examples{ # Create an empty configuration file config_file <- paste0(tempdir(), "/example.conf") @@ -72,7 +73,7 @@ ConfigShowSimilarEntries(configuration, dataset_name = "Exper", } \author{ History:\cr - 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version\cr 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats } \references{ @@ -80,9 +81,8 @@ History:\cr \url{http://www.catalysoft.com/articles/StrikeAMatch.html} } \seealso{ -[ConfigApplyMatchingEntries()], [ConfigEditDefinition()], - [ConfigEditEntry()], [ConfigFileOpen()], [ConfigShowSimilarEntries()], - [ConfigShowTable()]. +ConfigApplyMatchingEntries, ConfigEditDefinition, + ConfigEditEntry, ConfigFileOpen, ConfigShowSimilarEntries, ConfigShowTable } \keyword{datagen} diff --git a/man/ConfigShowTable.Rd b/man/ConfigShowTable.Rd index 1c6a24ec..a06b643e 100644 --- a/man/ConfigShowTable.Rd +++ b/man/ConfigShowTable.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/ConfigShowTable.R \name{ConfigShowTable} +\alias{ConfigShowDefinitions} \alias{ConfigShowTable} \title{Show Configuration Tables And Definitions} \usage{ ConfigShowTable(configuration, dataset_type, line_numbers = NULL) + +ConfigShowDefinitions(configuration) } \arguments{ \item{configuration}{Configuration object obtained from ConfigFileCreate() @@ -44,10 +47,11 @@ configuration <- ConfigEditEntry(configuration, "experiments", 1, # Show tables, lists and definitions ConfigShowTable(configuration, 'experiments') ConfigShowDefinitions(configuration) + } \author{ -History:cr - 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version +History:\cr + 0.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - First version\cr 1.0 - 2015-11 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Removed grid column and storage formats } \seealso{ diff --git a/man/Consist_Trend.Rd b/man/Consist_Trend.Rd index aea78bc0..a2911c64 100644 --- a/man/Consist_Trend.Rd +++ b/man/Consist_Trend.Rd @@ -20,21 +20,21 @@ Dimensions 2 to 6 should be the same as var_exp.} The trends will be provided respectively in field unit per month or per year.} } \value{ -\itemize{ -\item{$trend}{Trend coefficients of model and observational data with - dimensions:\cr +\item{$trend}{ + Trend coefficients of model and observational data with dimensions:\cr c(nmod/nexp + nobs, 3, nltime) up to\cr c(nmod/nexp + nobs, 3, nltime, nlevel, nlat, nlon)\cr The length 3 dimension corresponds to the lower limit of the 95\% confidence interval, the slope of the trends and the upper limit of the 95\% confidence interval. } -\item{$detrendedmod}{Same dimensions as var_exp with linearly detrended - values of var_exp along the second = start date dimension. -} -\item{$detrendedobs}{Same dimensions as var_exp with linearly detrended - values of var_obs along the second = start date dimension. +\item{$detrendedmod}{ + Same dimensions as var_exp with linearly detrended values of var_exp + along the second = start date dimension. } +\item{$detrendedobs}{ + Same dimensions as var_exp with linearly detrended values of var_obs + along the second = start date dimension. } } \description{ diff --git a/man/Corr.Rd b/man/Corr.Rd index f54af99d..fcaf149a 100644 --- a/man/Corr.Rd +++ b/man/Corr.Rd @@ -1,12 +1,16 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/Corr.R \name{Corr} +\alias{.Corr} \alias{Corr} \title{Computes the correlation coefficient between an array of forecasts and their corresponding observations} \usage{ Corr(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, limits = NULL, siglev = 0.95, method = "pearson", conf = TRUE, pval = TRUE) + +.Corr(exp, obs, siglev = 0.95, method = "pearson", conf = TRUE, + pval = TRUE) } \arguments{ \item{var_exp}{Array of experimental data.} @@ -20,7 +24,7 @@ except along posloop dimension, where the length can be nobs instead of nexp.} dimension of the start dates).} \item{compROW}{Data taken into account only if (compROW)th row is complete. -\cr Default = NULL.} +Default = NULL.} \item{limits}{Complete between limits[1] & limits[2]. Default = NULL.} @@ -77,6 +81,7 @@ Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr The confidence interval is computed by a Fisher transformation.\cr The significance level relies on a one-sided student-T distribution.\cr We can modifiy the treshold of the test modifying siglev (default value=0.95).\cr\cr +.Corr calculates the correlation between the ensemble mean and the observations, using an N by M matrix (exp) of forecasts and a vector of observations (obs) as input. } diff --git a/man/EOF.Rd b/man/EOF.Rd index 7b256707..118f6248 100644 --- a/man/EOF.Rd +++ b/man/EOF.Rd @@ -20,19 +20,27 @@ number of latitudes, number of longitudes).} covariance matrix (default, \code{FALSE}).} } \value{ -\itemize{ - \item{EOFs}{An array of EOF patterns normalized to 1 (unitless) with - dimensions (number of modes, number of latitudes, number of longitues). - Multiplying \code{EOFs} by \code{PCs} gives the original reconstructed field.} - \item{PCs}{An array of pincipal components with the units of the original - field to the power of 2, with dimensions (number of time steps, number of - modes). \code{PCs} contains already the percentage of explained variance - so, to reconstruct the original field it's only needed to multiply - \code{EOFs} by \code{PCs}.} - \item{var}{Percentage (%) of variance fraction of total variance explained - by each mode (number of modes).} - \item{mask}{Mask with dimensions (number of latitudes, number of longitudes).} - \item{wght}{Weights with dimensions (number of latitudes, number of longitudes).} +\item{EOFs}{ + An array of EOF patterns normalized to 1 (unitless) with dimensions + (number of modes, number of latitudes, number of longitues). + Multiplying \code{EOFs} by \code{PCs} gives the original reconstructed field. +} +\item{PCs}{ + An array of pincipal components with the units of the original field to + the power of 2, with dimensions (number of time steps, number of modes). + \code{PCs} contains already the percentage of explained variance so, + to reconstruct the original field it's only needed to multiply \code{EOFs} + by \code{PCs}. +} +\item{var}{ + Percentage (%) of variance fraction of total variance explained by each + mode (number of modes). +} +\item{mask}{ + Mask with dimensions (number of latitudes, number of longitudes). +} +\item{wght}{ + Weights with dimensions (number of latitudes, number of longitudes). } } \description{ @@ -92,7 +100,7 @@ code, inspired by R. Benestad's EOF() in R package clim.pact.\cr 2- Reduction of the number of transpositions and associated bug-fixes\cr 4- Remove of the obsolete LINPACK options\cr 0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas@bsc.es}) - Fixes:\cr - 1- Bug-fix in dimensions handling EOF composition restitutes now the\ + 1- Bug-fix in dimensions handling EOF composition restitutes now the original field in all cases\cr 2- Simplification of the convention transpose\cr 3- Options to use the correlation matrix rather than the @@ -107,7 +115,7 @@ EOF * PC\cr 1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN } \seealso{ -[ProjectField()], [NAO()], [PlotBoxWhisker()]. +ProjectField, NAO, PlotBoxWhisker } \keyword{datagen} diff --git a/man/FitAcfCoef.Rd b/man/FitAcfCoef.Rd index aa8e1db6..6ca51444 100644 --- a/man/FitAcfCoef.Rd +++ b/man/FitAcfCoef.Rd @@ -35,7 +35,7 @@ print(alpha) \author{ History:\cr 0.1 - 2012-06 (L. Auger, \email{ludovic.auger@meteo.fr}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/FitAutocor.Rd b/man/FitAutocor.Rd index 0720821a..ff3ab943 100644 --- a/man/FitAutocor.Rd +++ b/man/FitAutocor.Rd @@ -31,8 +31,8 @@ print(alpha) } \author{ History:\cr -0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2012-02 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/GenSeries.Rd b/man/GenSeries.Rd index deb6b1b3..61d53a9a 100644 --- a/man/GenSeries.Rd +++ b/man/GenSeries.Rd @@ -30,7 +30,7 @@ plot(series, type = 'l') \author{ History:\cr 0.1 - 2012-04 (L. Auger, \email{ludovic.auger@meteo.fr}) - Original code\cr -1.0 - 2012-04 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +1.0 - 2012-04 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/Histo2Hindcast.Rd b/man/Histo2Hindcast.Rd index d94da235..af494f1a 100644 --- a/man/Histo2Hindcast.Rd +++ b/man/Histo2Hindcast.Rd @@ -13,10 +13,10 @@ c(nmod/nexp/nobs, nmemb/nparam, nsdates, nltimes, nlevel, nlat, nlon)} \item{sdatesin}{Start date of the input matrix 'YYYYMMDD'.} -\item{sdateout}{List of start dates of the output matrix +\item{sdatesout}{List of start dates of the output matrix c('YYYYMMDD', 'YYYYMMDD', ...).} -\item{nleadtimeout}{Number of leadtimes in the output matrix.} +\item{nleadtimesout}{Number of leadtimes in the output matrix.} } \value{ An array with the same number of dimensions as varin, the same @@ -73,8 +73,8 @@ PlotAno(experimental_data, observational_data, start_dates_out, } \author{ History:\cr -0.1 - 2012-11 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2012-11 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/InsertDim.Rd b/man/InsertDim.Rd index dfceebdb..4cdc5377 100644 --- a/man/InsertDim.Rd +++ b/man/InsertDim.Rd @@ -21,7 +21,7 @@ Inserts an extra dimension into an array at position 'posdim' with length 'lendim' and which correspond to 'lendim' repetitions of the 'var' array. } \examples{ -<- array(rnorm(15), dim = c(3, 1, 5, 1)) +a <- array(rnorm(15), dim = c(3, 1, 5, 1)) print(dim(a)) print(dim(a[, , , ])) print(dim(InsertDim(InsertDim(a[, , , ], 2, 1), 4, 1))) diff --git a/man/LeapYear.Rd b/man/LeapYear.Rd index 8b9eb3bf..12b02b49 100644 --- a/man/LeapYear.Rd +++ b/man/LeapYear.Rd @@ -23,8 +23,8 @@ print(LeapYear(1993)) } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-03 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/Load.Rd b/man/Load.Rd index 5ee3db0d..c721e613 100644 --- a/man/Load.Rd +++ b/man/Load.Rd @@ -176,6 +176,12 @@ E.g., c(1, 5)} \item{leadtimemin}{Only lead-times higher or equal to 'leadtimemin' are loaded. Takes by default value 1.} +\item{leadtimemax}{Only lead-times lower or equal to 'leadtimemax' are loaded. +Takes by default the number of lead-times of the first experimental +dataset in 'exp'.\cr +If 'exp' is NULL this argument won't have any effect +(see \code{?Load} description).} + \item{storefreq}{Frequency at which the data to be loaded is stored in the file system. Can take values 'monthly' or 'daily'.\cr By default it takes 'monthly'.\cr @@ -374,56 +380,36 @@ to the actual limit.\cr The default value is 2.} \item{path_glob_permissive}{In some cases, when specifying a path pattern - (either in the parameters 'exp'/'obs' or in a configuration file) one can - specify path patterns that contain shell globbing expressions. Too much - freedom in putting globbing expressions in the path patterns can be - dangerous and make \code{Load()} find a file in the file system for a - start date for a dataset that really does not belong to that dataset. - For example, if the file system contains two directories for two different - experiments that share a part of their path and the path pattern contains - globbing expressions: - /experiments/model1/expA/monthly_mean/tos/tos_19901101.nc - /experiments/model2/expA/monthly_mean/tos/tos_19951101.nc - And the path pattern is used as in the example right below to load data of - only the experiment 'expA' of the model 'model1' for the starting dates - '19901101' and '19951101', \code{Load()} will undesiredly yield data for - both starting dates, even if in fact there is data only for the - first one:\cr - \code{ - expA <- list(path = file.path('/experiments/*/expA/monthly_mean/$VAR_NAME$', - '$VAR_NAME$_$START_DATE$.nc') - data <- Load('tos', list(expA), NULL, c('19901101', '19951101')) - } - To avoid these situations, the parameter \code{path_glob_permissive} is - set by default to \code{'partial'}, which forces \code{Load()} to replace - all the globbing expressions of a path pattern of a data set by fixed - values taken from the path of the first found file for each data set, up - to the folder right before the final files (globbing expressions in the - file name will not be replaced, only those in the path to the file). - Replacement of globbing expressions in the file name can also be triggered - by setting \code{path_glob_permissive} to \code{FALSE} or \code{'no'}. If - needed to keep all globbing expressions, \code{path_glob_permissive} can - be set to \code{TRUE} or \code{'yes'}. - -The two output matrices have between 2 and 6 dimensions:\cr - \enumerate{ - \item{Number of experimental/observational datasets.} - \item{Number of members.} - \item{Number of startdates.} - \item{Number of leadtimes.} - \item{Number of latitudes (optional).} - \item{Number of longitudes (optional).} - } -but the two matrices have the same number of dimensions and only the first -two dimensions can have different lengths depending on the input arguments. -For a detailed explanation of the process, read the documentation attached -to the package or check the comments in the code.} - -\item{leatimemax}{Only lead-times lower or equal to 'leadtimemax' are loaded. -Takes by default the number of lead-times of the first experimental -dataset in 'exp'.\cr -If 'exp' is NULL this argument won't have any effect -(see \code{?Load} description).} +(either in the parameters 'exp'/'obs' or in a configuration file) one can +specify path patterns that contain shell globbing expressions. Too much +freedom in putting globbing expressions in the path patterns can be +dangerous and make \code{Load()} find a file in the file system for a +start date for a dataset that really does not belong to that dataset. +For example, if the file system contains two directories for two different +experiments that share a part of their path and the path pattern contains +globbing expressions: + /experiments/model1/expA/monthly_mean/tos/tos_19901101.nc + /experiments/model2/expA/monthly_mean/tos/tos_19951101.nc +And the path pattern is used as in the example right below to load data of +only the experiment 'expA' of the model 'model1' for the starting dates +'19901101' and '19951101', \code{Load()} will undesiredly yield data for +both starting dates, even if in fact there is data only for the +first one:\cr + \code{ +expA <- list(path = file.path('/experiments/*/expA/monthly_mean/$VAR_NAME$', + '$VAR_NAME$_$START_DATE$.nc') +data <- Load('tos', list(expA), NULL, c('19901101', '19951101')) + } +To avoid these situations, the parameter \code{path_glob_permissive} is +set by default to \code{'partial'}, which forces \code{Load()} to replace +all the globbing expressions of a path pattern of a data set by fixed +values taken from the path of the first found file for each data set, up +to the folder right before the final files (globbing expressions in the +file name will not be replaced, only those in the path to the file). +Replacement of globbing expressions in the file name can also be triggered +by setting \code{path_glob_permissive} to \code{FALSE} or \code{'no'}. If +needed to keep all globbing expressions, \code{path_glob_permissive} can +be set to \code{TRUE} or \code{'yes'}.} } \value{ \code{Load()} returns a named list following a structure similar to the @@ -711,6 +697,21 @@ The components are the following: paths to not found files involved in the \code{Load()} call.} } } +\details{ +The two output matrices have between 2 and 6 dimensions:\cr + \enumerate{ + \item{Number of experimental/observational datasets.} + \item{Number of members.} + \item{Number of startdates.} + \item{Number of leadtimes.} + \item{Number of latitudes (optional).} + \item{Number of longitudes (optional).} + } +but the two matrices have the same number of dimensions and only the first +two dimensions can have different lengths depending on the input arguments. +For a detailed explanation of the process, read the documentation attached +to the package or check the comments in the code. +} \examples{ # Let's assume we want to perform verification with data of a variable # called 'tos' from a model called 'model' and observed data coming from @@ -872,15 +873,14 @@ sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) } - } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to CRAN\cr -1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Generalisation + parallelisation\cr -1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Improvements related to configuration file mechanism\cr -1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Added subsetting capabilities\cr +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@bsc.es}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to CRAN\cr +1.2 - 2015-02 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Generalisation + parallelisation\cr +1.3 - 2015-07 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Improvements related to configuration file mechanism\cr +1.4 - 2016-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Added subsetting capabilities } \keyword{datagen} diff --git a/man/NAO.Rd b/man/NAO.Rd index 048c20ec..2767f7e8 100644 --- a/man/NAO.Rd +++ b/man/NAO.Rd @@ -39,18 +39,16 @@ year you are evaluating out), and then projecting forecast anomalies onto this EOF.} } \value{ -\itemize{ - \item{NAO_exp}{ - Array of forecast NAO index in verification format (ensemble members, - start dates). - } - \item{NAO_obs}{ - Array of observed NAO index in verification format (1, number of start - dates). - } - \item{EOFs_obs}{ - EOFs of the observational references. +\item{NAO_exp}{ + Array of forecast NAO index in verification format (ensemble members, + start dates). } +\item{NAO_obs}{ + Array of observed NAO index in verification format (1, number of start + dates). +} +\item{EOFs_obs}{ + EOFs of the observational references. } } \description{ @@ -115,16 +113,16 @@ PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS" } \author{ History:\cr -0.1 - 2013-08 (F. Lienert, \email{flienert at ic3.cat}) - Original code\cr -0.2 - 2014-03 (V. Guemas, \email{virginie.guemas at bsc.es}) - Removing the +0.1 - 2013-08 (F. Lienert, \email{flienert@ic3.cat}) - Original code\cr +0.2 - 2014-03 (V. Guemas, \email{virginie.guemas@bsc.es}) - Removing the rotation\cr -0.3 - 2014-05 (L. Batte, \email{lauriane.batte at ic3.cat}) - Changes to +0.3 - 2014-05 (L. Batte, \email{lauriane.batte@ic3.cat}) - Changes to simplify function and add Pobs and Pmod options for NAO projection calculations\cr -0.4 - 2015-03 (L. Batte, \email{lauriane.batte at ic3.cat}) - Polarity +0.4 - 2015-03 (L. Batte, \email{lauriane.batte@ic3.cat}) - Polarity check and correction is wrong. Switched to have a negative NAO index when the anomaly pattern corresponds to NAO-. -1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - +1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatted to CRAN } \references{ diff --git a/man/Plot2VarsVsLTime.Rd b/man/Plot2VarsVsLTime.Rd index df5be414..e79fb34e 100644 --- a/man/Plot2VarsVsLTime.Rd +++ b/man/Plot2VarsVsLTime.Rd @@ -68,23 +68,23 @@ corresponding device.} ?Devices and the creator function of the corresponding device.} \item{...}{Arguments to be passed to the method. Only accepts the following - graphical parameters:\cr - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt - csi cxy err family fg fig font font.axis font.lab font.main font.sub lend - lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt - smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr - For more information about the parameters see `par`. - -Examples of input:\cr -------------------\cr -\cr -RMSE error for a number of experiments and along lead-time: (nexp, nltime)} +graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg fig font font.axis font.lab font.main font.sub lend +lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt +smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} } \description{ Plots two input variables having the same dimensions in a common plot.\cr One plot for all experiments.\cr Input variables should have dimensions (nexp/nmod, nltime). } +\details{ +Examples of input:\cr +------------------\cr\cr +RMSE error for a number of experiments and along lead-time: (nexp, nltime) +} \examples{ # Load sample data as in Load() example: example(Load) diff --git a/man/PlotEquiMap.Rd b/man/PlotEquiMap.Rd index 14f1d690..cb33fc60 100644 --- a/man/PlotEquiMap.Rd +++ b/man/PlotEquiMap.Rd @@ -77,9 +77,8 @@ colors returned by 'color_fun'. If not available, it takes 'pink' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'.} -\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, }{triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, -bar_tick_scale,bar_extra_margin Set of parameters to control the visual - aspect of the drawn colour bar. See ?ColorBar for a full explanation.} +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, triangle_ends_scale, bar_label_digits, bar_label_scale, units_scale, bar_tick_scale, bar_extra_margin}{Set of parameters to control the visual +aspect of the drawn colour bar. See ?ColorBar for a full explanation.} \item{square}{Logical value to choose either to draw a coloured square for each grid cell in 'var' (TRUE; default) or to draw contour lines and fill @@ -222,22 +221,20 @@ pty smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr For more information about the parameters see `par`.} } \value{ -\itemize{ - \item{brks}{ +\item{brks}{ Breaks used for colouring the map (and legend if drawleg = TRUE). - } - \item{cols}{ +} +\item{cols}{ Colours used for colouring the map (and legend if drawleg = TRUE). Always of length length(brks) - 1. - } - \item{col_inf}{ +} +\item{col_inf}{ Colour used to draw the lower triangle end in the colour bar (NULL if not - drawn at all). - } - \item{col_sup}{ + drawn at all). +} +\item{col_sup}{ Colour used to draw the upper triangle end in the colour bar (NULL if not - drawn at all). - } + drawn at all). } } \description{ @@ -280,14 +277,13 @@ sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), PlotEquiMap(sampleData$mod[1, 1, 1, 1, , ], sampleData$lon, sampleData$lat, toptitle = 'Predicted sea surface temperature for Nov 1960 from 1st Nov', sizetit = 0.5) - } \author{ History:\cr - 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code - 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@ic3.cat}) - LabW - 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN - 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@ic3.cat}) - add winds + 0.1 - 2011-11 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr + 0.2 - 2013-04 (R. Saurral \email{ramiro.saurral@ic3.cat}) - LabW\cr + 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr + 1.1 - 2013-09 (C. Prodhomme, \email{chloe.prodhomme@ic3.cat}) - add winds\cr 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Refactored and added features, and adapted to new ColorBar. } diff --git a/man/PlotLayout.Rd b/man/PlotLayout.Rd index 75f24e2c..e4cf4ecf 100644 --- a/man/PlotLayout.Rd +++ b/man/PlotLayout.Rd @@ -126,9 +126,7 @@ respectively. 'colNA' takes 'white' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'.} -\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, }{triangle_ends_scale,bar_label_digits,bar_label_scale,units_scale, -bar_tick_scale,bar_extra_margin Set of parameters to control the visual - aspect of the drawn colour bar. See ?ColorBar for a full explanation.} +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, triangle_ends_scale, bar_label_digits, bar_label_scale, units_scale, bar_tick_scale, bar_extra_margin}{Set of parameters to control the visual aspect of the drawn colour bar. See ?ColorBar for a full explanation.} \item{units}{Title at the top of the colour bar, most commonly the units of the variable provided in parameter 'var'.} @@ -174,26 +172,24 @@ plot functions, as common parameters. To specify concrete arguments for each of the plot functions see parameter 'special_args'.} } \value{ -\itemize{ - \item{brks}{ +\item{brks}{ Breaks used for colouring the map (and legend if drawleg = TRUE). - } - \item{cols}{ +} +\item{cols}{ Colours used for colouring the map (and legend if drawleg = TRUE). Always of length length(brks) - 1. - } - \item{col_inf}{ +} +\item{col_inf}{ Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). - } - \item{col_sup}{ +} +\item{col_sup}{ Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). - } - \item{layout_matrix}{ +} +\item{layout_matrix}{ Underlying matrix of the layout. Useful to later set any of the layout cells as current figure to add plot elements. See .SwitchToFigure. - } } } \description{ diff --git a/man/PlotStereoMap.Rd b/man/PlotStereoMap.Rd index 5df0a95f..3bf2f69c 100644 --- a/man/PlotStereoMap.Rd +++ b/man/PlotStereoMap.Rd @@ -69,10 +69,8 @@ colors returned by 'color_fun'. If not available, it takes 'pink' by default. 'col_inf' and 'col_sup' will take the value of 'colNA' if not specified. See ?ColorBar for a full explanation on 'col_inf' and 'col_sup'.} -\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, }{draw_separators,triangle_ends_scale,bar_label_digits,bar_label_scale, -units_scale,bar_tick_scale,bar_extra_margin Set of parameters to control - the visual aspect of the drawn colour bar. See ?ColorBar for a - full explanation.} +\item{color_fun, subsampleg, bar_extra_labels, draw_bar_ticks, draw_separators, triangle_ends_scale, bar_label_digits, bar_label_scale, units_scale, bar_tick_scale, bar_extra_margin}{Set of parameters to control the visual +aspect of the drawn colour bar. See ?ColorBar for a full explanation.} \item{filled.continents}{Colour to fill in drawn projected continents. Takes the value gray(0.5) by default. If set to FALSE, continents are not @@ -153,22 +151,20 @@ smo srt tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr For more information about the parameters see `par`.} } \value{ -\itemize{ - \item{brks}{ +\item{brks}{ Breaks used for colouring the map (and legend if drawleg = TRUE). - } - \item{cols}{ +} +\item{cols}{ Colours used for colouring the map (and legend if drawleg = TRUE). Always of length length(brks) - 1. - } - \item{col_inf}{ +} +\item{col_inf}{ Colour used to draw the lower triangle end in the colour bar (NULL if not drawn at all). - } - \item{col_sup}{ +} +\item{col_sup}{ Colour used to draw the upper triangle end in the colour bar (NULL if not drawn at all). - } } } \description{ @@ -189,8 +185,8 @@ PlotStereoMap(data, x, y, latlims = c(60, 90), brks = 50, } \author{ History:\cr -1.0 - 2014-07 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code -1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze@meteo.fr}) - Box(es) drawing +1.0 - 2014-07 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.1 - 2015-12 (C. Ardilouze, \email{constantin.ardilouze@meteo.fr}) - Box(es) drawing\cr 1.2 - 2016-08 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Refacotred the function and merged in Jean-Philippe circle border and Constantin boxes. diff --git a/man/PlotVsLTime.Rd b/man/PlotVsLTime.Rd index 5c7ab282..e908e57b 100644 --- a/man/PlotVsLTime.Rd +++ b/man/PlotVsLTime.Rd @@ -67,13 +67,24 @@ corresponding device.} ?Devices and the creator function of the corresponding device.} \item{...}{Arguments to be passed to the method. Only accepts the following - graphical parameters:\cr - adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt - csi cxy err family fg fig font font.axis font.lab font.main font.sub - lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt - smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr - For more information about the parameters see `par`. - +graphical parameters:\cr +adj ann ask bg bty cex.sub cin col.axis col.lab col.main col.sub cra crt +csi cxy err family fg fig font font.axis font.lab font.main font.sub +lheight ljoin lmitre mar mex mfcol mfrow mfg mkh oma omd omi page pch plt +smo srt tck tcl usr xaxp xaxs xaxt xlog xpd yaxp yaxs yaxt ylbias ylog \cr +For more information about the parameters see `par`.} +} +\description{ +Plots The Correlation (\code{Corr()}) or the Root Mean Square Error +(\code{RMS()}) between the forecasted values and their observational +counterpart or the slopes of their trends (\code{Trend()}) or the +InterQuartile Range, Maximum-Mininum, Standard Deviation or Median Absolute +Deviation of the Ensemble Members (\code{Spread()}), or the ratio between +the Ensemble Spread and the RMSE of the Ensemble Mean (\code{RatioSDRMS()}) +along the forecast time for all the input experiments on the same figure +with their confidence intervals. +} +\details{ Examples of input:\cr Model and observed output from \code{Load()} then \code{Clim()} then \code{Ano()} then \code{Smoothing()}:\cr @@ -86,17 +97,7 @@ then passed through\cr \code{RMS(exp, obs, posloop = 1, posRMS = 2)}:\cr (nmod, nobs, 3, nltime)\cr would plot the correlations or RMS between each exp & each obs as a function -of the forecast time.} -} -\description{ -Plots The Correlation (\code{Corr()}) or the Root Mean Square Error -(\code{RMS()}) between the forecasted values and their observational -counterpart or the slopes of their trends (\code{Trend()}) or the -InterQuartile Range, Maximum-Mininum, Standard Deviation or Median Absolute -Deviation of the Ensemble Members (\code{Spread()}), or the ratio between -the Ensemble Spread and the RMSE of the Ensemble Mean (\code{RatioSDRMS()}) -along the forecast time for all the input experiments on the same figure -with their confidence intervals. +of the forecast time. } \examples{ # Load sample data as in Load() example: diff --git a/man/ProjectField.Rd b/man/ProjectField.Rd index 36aa4455..7b2e9e93 100644 --- a/man/ProjectField.Rd +++ b/man/ProjectField.Rd @@ -77,17 +77,17 @@ for (i in 1:dim(sampleData$mod)[2]) { } \author{ History:\cr -0.1 - 2012-03 (F. Lienert, \email{flienert at ic3.cat} - Original code -0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Bug-fixes:\cr +0.1 - 2012-03 (F. Lienert, \email{flienert@ic3.cat} - Original code\cr +0.2 - 2014-03 (Lauriane Batte, \email{lauriane.batte@ic3.cat} - Bug-fixes:\cr 1- Extra weighting of the anomalies before projection.\cr 2- Reversion of the anomalies along latitudes.\cr 3- Extra-normalisation not necessary.\cr -0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Bug-fixes:\cr +0.3 - 2014-03 (Virginie Guemas, \email{virginie.guemas@bsc.es} - Bug-fixes:\cr 1- Another extra-normalisation.\cr 2- 15 lines to compute the em reduced to 1. -0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte at ic3.cat} - Normalization\cr +0.4 - 2014-03 (Lauriane Batte, \email{lauriane.batte@ic3.cat} - Normalization\cr by std before returning PCs to be coherent with EOF().\cr -0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas at bsc.es} - Fixes:\cr +0.5 - 2014-04 (Virginie Guemas, \email{virginie.guemas@bsc.es} - Fixes:\cr 1- Removal of lon, lat, ncpu and neofs argument unused\cr 2- Security checks ano and eof consistency\cr 3- Removal of the mask which is already contained in the EOFs\cr @@ -102,8 +102,8 @@ back by the weights before projection so that EOF * t(EOF) = 1\cr 6 - Since W *X = PC * EOF if EOF is multiplied back by the weights,\cr PC = W * X * t(EOF) and X the input field to be projected (X) needs to be\cr multiplied by W. Getting input dimensions. -1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN - (J.-P. Baudouin, \email{jean.baudouin at bsc.es}) - Example code and testing +1.0 - 2016-03 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN\cr + (J.-P. Baudouin, \email{jean.baudouin@bsc.es}) - Example code and testing } \seealso{ EOF, NAO, PlotBoxWhisker diff --git a/man/RMS.Rd b/man/RMS.Rd index acab1529..cf26c75c 100644 --- a/man/RMS.Rd +++ b/man/RMS.Rd @@ -1,11 +1,14 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/RMS.R \name{RMS} +\alias{.RMS} \alias{RMS} \title{Computes Root Mean Square Error} \usage{ RMS(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, limits = NULL, siglev = 0.95, conf = TRUE) + +.RMS(exp, obs, siglev = 0.95, conf = TRUE) } \arguments{ \item{var_exp}{Matrix of experimental data.} @@ -40,19 +43,18 @@ c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 3, all The 3rd dimension corresponds to the lower limit of the 95\% confidence interval (only present if \code{conf = TRUE}), the RMSE, and the upper limit of the 95\% confidence interval (only present if - \code{conf = TRUE}).\cr -\cr + \code{conf = TRUE}).\cr\cr .RMS: -\itemize{ - \item{$rms}{ +\item{$rms}{ The root mean square error, - } - \item{$conf_low}{ -Corresponding to the lower limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. - } - \item{$conf_high}{ -Corresponding to the upper limit of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the rms. - } +} +\item{$conf_low}{ + Corresponding to the lower limit of the \code{siglev}\% confidence interval + (only present if \code{conf = TRUE}) for the rms. +} +\item{$conf_high}{ + Corresponding to the upper limit of the \code{siglev}\% confidence interval + (only present if \code{conf = TRUE}) for the rms. } } \description{ @@ -69,8 +71,7 @@ NAs between limits[1] and limits[2]. This option can be activated if the user wishes to account only for the forecasts for which observations are available at all leadtimes.\cr Default: limits[1] = 1 and limits[2] = length(compROW dimension).\cr -The confidence interval relies on a chi2 distribution.\cr -\cr +The confidence interval relies on a chi2 distribution.\cr\cr .RMS provides the same functionality but taking a matrix of ensemble members as input (exp). } @@ -111,9 +112,9 @@ rms2 <- veriApply("RMS2", } \author{ History:\cr -0.1 - 2011-05 (V. Guemas, \email{vguemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN\cr -1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +0.1 - 2011-05 (V. Guemas, \email{vguemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens2@ic3.cat}) - Formatting to R CRAN\cr +1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() } \keyword{datagen} diff --git a/man/RMSSS.Rd b/man/RMSSS.Rd index 0db83e95..234170b8 100644 --- a/man/RMSSS.Rd +++ b/man/RMSSS.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/RMSSS.R \name{RMSSS} +\alias{.RMSSS} \alias{RMSSS} \title{Computes Root Mean Square Skill Score} \usage{ RMSSS(var_exp, var_obs, posloop = 1, posRMS = 2, pval = TRUE) + +.RMSSS(exp, obs, pval = TRUE) } \arguments{ \item{var_exp}{Array of experimental data.} @@ -27,13 +30,11 @@ RMSSS = 0. TRUE by default.} } \value{ RMSSS: Array with dimensions:\cr -c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, + c(length(posloop) in var_exp, length(posloop) in var_obs, 1 or 2, all other dimensions of var_exp & var_obs except posRMS).\cr The 3rd dimension corresponds to the RMSSS and, if \code{pval = TRUE}, - the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr -\cr + the p-value of the one-sided Fisher test with Ho: RMSSS = 0.\cr\cr .RMSSS: -\itemize{ \itemize{ \item{$rmsss}{ The RMSSS. @@ -44,7 +45,6 @@ The 3rd dimension corresponds to the RMSSS and, if \code{pval = TRUE}, } } } -} \description{ Computes the root mean square error skill score between an array of forecasts, var_exp and an array of observations, var_obs, which should @@ -56,8 +56,7 @@ against each jobs in 1:nobs which gives nexp x nobs RMSSS for each other grid point of the matrix (each latitude/longitude/level/leadtime).\cr The RMSSS are computed along the posRMS dimension which should correspond to the startdate dimension.\cr -The p-value is optionally provided by a one-sided Fisher test.\cr -\cr +The p-value is optionally provided by a one-sided Fisher test.\cr\cr .RMSSS provides the same functionality but taking a matrix of ensemble members as input (exp). } @@ -84,7 +83,6 @@ rmsss2 <- veriApply("RMSSS2", ano_exp, Mean1Dim(ano_obs, 2), tdim = 3, ensdim = 2) } - } \author{ History:\cr diff --git a/man/RatioRMS.Rd b/man/RatioRMS.Rd index 48f63ec1..44d13dbb 100644 --- a/man/RatioRMS.Rd +++ b/man/RatioRMS.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/RatioRMS.R \name{RatioRMS} +\alias{.RatioRMS} \alias{RatioRMS} \title{Computes the Ratio Between The RMSE of Two Experiments} \usage{ RatioRMS(var_exp1, var_exp2, var_obs, posRMS = 1, pval = TRUE) + +.RatioRMS(exp, exp_ref, obs, pval = TRUE) } \arguments{ \item{var_exp1}{Array of experimental data 1.} @@ -31,8 +34,7 @@ Matrix with the same dimensions as var_exp1/var_exp2/var_obs except along posRMS where the dimension has length 2 if 'pval = TRUE', or 1 otherwise. The dimension of length 2 corresponds to the ratio between the RMSE (RMSE1/RMSE2) and the p-value of the two-sided Fisher test with Ho: - RMSE1/RMSE2 = 1.\cr -\cr + RMSE1/RMSE2 = 1.\cr\cr .RatioRMS:\cr \itemize{ \item{ratiorms}{The ratio of the RMSE of the two experimental datasets} @@ -42,8 +44,7 @@ Matrix with the same dimensions as var_exp1/var_exp2/var_obs except along \description{ Calculates the ratio of the RMSE for two forecasts of the same observations.\cr The ratio RMSE(ens, obs) / RMSE(ens.ref, obs) is output.\cr -The p-value is provided by a two-sided Fischer test.\cr -\cr +The p-value is provided by a two-sided Fischer test.\cr\cr .RatioRMS provides the same functionality but taking two matrices of ensemble members (ens and ens.ref) as input. } @@ -112,13 +113,12 @@ rrms2 <- veriApply("RatioRMSss", ano_exp_1, ano_exp_2, tdim = 2, ensdim = 1) } - } \author{ History:\cr -0.1 - 2011-11 (V. Guemas, \email{vguemas at bsc.es}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN\cr -1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +0.1 - 2011-11 (V. Guemas, \email{vguemas@bsc.es}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN\cr +1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() } \keyword{datagen} diff --git a/man/RatioSDRMS.Rd b/man/RatioSDRMS.Rd index 23f07cdb..bb5848a5 100644 --- a/man/RatioSDRMS.Rd +++ b/man/RatioSDRMS.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/RatioSDRMS.R \name{RatioSDRMS} +\alias{.RatioSDRMS} \alias{RatioSDRMS} \title{Computes the ratio between the ensemble spread and RMSE} \usage{ RatioSDRMS(var_exp, var_obs, pval = TRUE) + +.RatioSDRMS(exp, obs, pval = TRUE) } \arguments{ \item{var_exp}{Model data:\cr @@ -26,8 +29,7 @@ RatioSDRMS: Array with dimensions c(nexp/nmod, nobs, 1 or 2, nltime) up to c(nexp/nmod, nobs, 1 or 2, nltime, nlevel, nlat, nlon).\cr The 3rd dimension corresponds to the ratio (SD/RMSE) and the p.value (only present if \code{pval = TRUE}) of the one-sided Fisher test with -Ho: SD/RMSE = 1.\cr -\cr +Ho: SD/RMSE = 1.\cr\cr .RatioSDRMS: \itemize{ \item{$ratio}{ @@ -47,8 +49,7 @@ c(nmod/nexp, nmemb/nparam, nsdates, nltime, nlevel, nlat, nlon)\cr The ratio between the standard deviation of the members around the ensemble mean in var_exp and the RMSE between var_exp and var_obs is output for each experiment and each observational dataset.\cr -The p-value is provided by a one-sided Fischer test.\cr -\cr +The p-value is provided by a one-sided Fischer test.\cr\cr .RatioSDRMS provides the same functionality but taking a matrix of ensemble members as input (exp). } @@ -75,13 +76,12 @@ rsdrms2 <- veriApply("RatioSDRMS2", Mean1Dim(sampleData$obs, 2), tdim = 3, ensdim = 2) } - } \author{ History:\cr -0.1 - 2011-12 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau-manubens at ic3.cat}) - Formatting to CRAN\cr -1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapted to veriApply() +0.1 - 2011-12 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau-manubens@ic3.cat}) - Formatting to CRAN\cr +1.1 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapted to veriApply() } \keyword{datagen} diff --git a/man/Regression.Rd b/man/Regression.Rd index e65dd3fd..55646576 100644 --- a/man/Regression.Rd +++ b/man/Regression.Rd @@ -15,8 +15,7 @@ Same dimensions as vary.} \item{posREG}{Position along which to compute the regression.} } \value{ -\itemize{ - \item{$regression}{ +\item{$regression}{ Array with same dimensions as varx and vary except along posREG dimension which is replaced by a length 4 dimension, corresponding to the lower limit of the 95\% confidence interval, the slope, @@ -27,7 +26,6 @@ Same dimensions as vary.} along the posREG dimension. } } -} \description{ Computes the regression of the input matrice vary on the input matrice varx along the posREG dimension by least square fitting. Provides the slope of @@ -71,8 +69,8 @@ PlotEquiMap(reg$regression[1, 2, 1, , ], sampleData$lon, sampleData$lat, } \author{ History:\cr -0.1 - 2013-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2013-05 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/SVD.Rd b/man/SVD.Rd index 0810f8a0..698df952 100644 --- a/man/SVD.Rd +++ b/man/SVD.Rd @@ -31,8 +31,7 @@ a correlation matrix (TRUE).} TRUE by default.} } \value{ -\itemize{ - \item{$SC}{ +\item{$SC}{ Vector of squared covariance (n. of modes). } \item{$SCFs}{ @@ -56,7 +55,6 @@ Vector of squared covariance (n. of modes). Array of covariability patterns of predictand field (c(dim), n. of modes). } } -} \description{ Computes a Maximum Covariance Analysis (MCA) between vary and varx, both of dimensions c(n. of time steps, n. of latitudes, n. of longitudes), each @@ -115,8 +113,8 @@ plot(mca$ECs_V[1, ]) } \author{ History:\cr -0.1 - 2010-09 (J.-G. Serrano, \email{javier.garcia at bsc.es}) - Original code\cr -1.0 - 2016-04 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Formatting to R CRAN +0.1 - 2010-09 (J.-G. Serrano, \email{javier.garcia@bsc.es}) - Original code\cr +1.0 - 2016-04 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Formatting to R CRAN } \keyword{datagen} diff --git a/man/Season.Rd b/man/Season.Rd index b7aa1ff7..08487256 100644 --- a/man/Season.Rd +++ b/man/Season.Rd @@ -48,8 +48,8 @@ PlotAno(season_means_mod, season_means_obs, startDates, } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/SelIndices.Rd b/man/SelIndices.Rd index 09fdf055..dbf34da2 100644 --- a/man/SelIndices.Rd +++ b/man/SelIndices.Rd @@ -33,8 +33,8 @@ print(dim(SelIndices(a, 3, c(2, 3)))) } \author{ History:\cr -0.1 - 2011-04 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-04 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/Smoothing.Rd b/man/Smoothing.Rd index 80bda29a..77a23cc9 100644 --- a/man/Smoothing.Rd +++ b/man/Smoothing.Rd @@ -35,13 +35,12 @@ smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", fileout = "tos_smoothed_ano.eps") - } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to R CRAN -1.1 - 2015-05 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Adding +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to R CRAN\cr +1.1 - 2015-05 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Adding security checks, fixing computation in cases where runmeanlen is odd and making it able to work on arrays of any number of dimensions. } diff --git a/man/Spectrum.Rd b/man/Spectrum.Rd index 2f93d82e..cd2dad7a 100644 --- a/man/Spectrum.Rd +++ b/man/Spectrum.Rd @@ -42,8 +42,8 @@ PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = } \author{ History:\cr -0.1 - 2012-02 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2012-02 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/Spread.Rd b/man/Spread.Rd index 70e20239..bc14fa7a 100644 --- a/man/Spread.Rd +++ b/man/Spread.Rd @@ -18,14 +18,7 @@ Spread(var, posdim = 2, narm = TRUE, siglev = 0.95, conf = TRUE) 0.95 by default.} \item{conf}{Whether to compute the confidence intervals or not. - TRUE by default. - -Example: --------- -To compute IQR, Max-Min, SD & MAD accross the members and start dates of -var output from \code{Load()} or \code{Ano()} or \code{Ano_CrossValid()}, -call:\cr - spread(var, posdim = c(2, 3), narm = TRUE)} +TRUE by default.} } \value{ Matrix with the same dimensions as var except along the first posdim @@ -54,6 +47,14 @@ provided by the posdim argument (typically along the ensemble member and start date dimension).\cr The confidence interval is optionally computed by bootstrapping. } +\details{ +Example:\cr +--------\cr +To compute IQR, Max-Min, SD & MAD accross the members and start dates of +var output from \code{Load()} or \code{Ano()} or \code{Ano_CrossValid()}, +call:\cr + spread(var, posdim = c(2, 3), narm = TRUE) +} \examples{ # Load sample data as in Load() example: example(Load) @@ -86,8 +87,8 @@ PlotVsLTime(spread$mad, toptitle = "Median Absolute Deviation of the members", } \author{ History:\cr -0.1 - 2011-03 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN +0.1 - 2011-03 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN } \keyword{datagen} diff --git a/man/Trend.Rd b/man/Trend.Rd index 0f75d2c4..da1fe956 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -1,10 +1,13 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/Trend.R \name{Trend} +\alias{.Trend} \alias{Trend} \title{Computes the Trend of the Ensemble Mean} \usage{ Trend(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) + +.Trend(exp, interval = 1, siglev = 0.95, conf = TRUE) } \arguments{ \item{var}{Array of any number of dimensions up to 10.} @@ -42,7 +45,7 @@ Computes the trend along the forecast time of the ensemble mean by least square fitting, and the associated error interval.\cr Trend() also provides the time series of the detrended ensemble mean forecasts.\cr -The confidence interval relies on a student-T distribution. +The confidence interval relies on a student-T distribution.\cr\cr .Trend provides the same functionality but taking a matrix ensemble members as input (exp). } @@ -59,13 +62,12 @@ PlotAno(trend$detrended, NULL, startDates, toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') - } \author{ History:\cr -0.1 - 2011-05 (V. Guemas, \email{virginie.guemas at ic3.cat}) - Original code\cr -1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens at ic3.cat}) - Formatting to CRAN\cr -2.0 - 2017-02 (A. Hunter, \email{alasdair.hunter at bsc.es}) - Adapt to veriApply() +0.1 - 2011-05 (V. Guemas, \email{virginie.guemas@ic3.cat}) - Original code\cr +1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@ic3.cat}) - Formatting to CRAN\cr +2.0 - 2017-02 (A. Hunter, \email{alasdair.hunter@bsc.es}) - Adapt to veriApply() } \keyword{datagen} diff --git a/man/UltimateBrier.Rd b/man/UltimateBrier.Rd index b0ad06a0..46fe124c 100644 --- a/man/UltimateBrier.Rd +++ b/man/UltimateBrier.Rd @@ -114,15 +114,14 @@ ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) bs <- UltimateBrier(ano_exp, ano_obs) bss <- UltimateBrier(ano_exp, ano_obs, type = 'BSS') - } \author{ History:\cr -0.1 - 2015-05 (V. Guemas \email{virginie.guemas at bsc.es},\cr - C. Prodhomme \email{chloe.prodhomme at bsc.es},\cr - O. Bellprat \email{omar.bellprat at bsc.es}\cr - V. Torralba \email{veronica.torralba at bsc.es}\cr - N. Manubens, \email{nicolau.manubens at bsc.es}) - First version +0.1 - 2015-05 (V. Guemas \email{virginie.guemas@bsc.es},\cr + C. Prodhomme \email{chloe.prodhomme@bsc.es},\cr + O. Bellprat \email{omar.bellprat@bsc.es}\cr + V. Torralba \email{veronica.torralba@bsc.es}\cr + N. Manubens, \email{nicolau.manubens@bsc.es}) - First version } \keyword{datagen} diff --git a/man/clim.colors.Rd b/man/clim.colors.Rd deleted file mode 100644 index 20f496a1..00000000 --- a/man/clim.colors.Rd +++ /dev/null @@ -1,35 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/clim.palette.R -\name{clim.colors} -\alias{clim.colors} -\title{Generate Climate Color Palettes} -\usage{ -clim.colors(n, palette = "bluered") -} -\arguments{ -\item{n}{Number of colors to generate.} - -\item{palette}{Which type of palette to generate: from blue through white -to red ('bluered'), from red through white to blue ('redblue'), from -yellow through orange to red ('yellowred'), or from red through orange -to red ('redyellow').} -} -\description{ -Generates a colorblind friendly color palette with color ranges useful in -climate temperature variable plotting. -} -\examples{ -lims <- seq(-1, 1, length.out = 21) - -ColorBar(lims, color_fun = clim.palette('redyellow')) - -cols <- clim.colors(20) -ColorBar(lims, cols) - -} -\author{ -History:\cr -0.0 - 2016-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. -} -\keyword{datagen} - diff --git a/man/clim.palette.Rd b/man/clim.palette.Rd index b82a5efd..95f8407c 100644 --- a/man/clim.palette.Rd +++ b/man/clim.palette.Rd @@ -1,22 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/clim.palette.R \name{clim.palette} \alias{clim.colors} \alias{clim.palette} \title{Generate Climate Color Palettes} -\description{ -Generates a colorblind friendly color palette with color ranges useful in climate temperature variable plotting.\cr -} \usage{ -clim.palette(palette = 'bluered') +clim.palette(palette = "bluered") -clim.colors(n, palette = 'bluered') +clim.colors(n, palette = "bluered") } \arguments{ - \item{palette}{ -Which type of palette to generate: from blue through white to red ('bluered'), from red through white to blue ('redblue'), from yellow through orange to red ('yellowred'), or from red through orange to red ('redyellow'). - } - \item{n}{ -Number of colors to generate. - } +\item{palette}{Which type of palette to generate: from blue through white +to red ('bluered'), from red through white to blue ('redblue'), from +yellow through orange to red ('yellowred'), or from red through orange +to red ('redyellow').} + +\item{n}{Number of colors to generate.} +} +\description{ +Generates a colorblind friendly color palette with color ranges useful in +climate temperature variable plotting. } \examples{ lims <- seq(-1, 1, length.out = 21) @@ -25,9 +28,11 @@ ColorBar(lims, color_fun = clim.palette('redyellow')) cols <- clim.colors(20) ColorBar(lims, cols) + } \author{ History:\cr -0.0 - 2016-01 (N. Manubens, \email{nicolau.manubens at bsc.es}) - Original code.\cr +0.0 - 2016-01 (N. Manubens, \email{nicolau.manubens@bsc.es}) - Original code. } \keyword{datagen} + diff --git a/man/s2dverification.Rd b/man/s2dverification.Rd index 27da42f0..33d06564 100644 --- a/man/s2dverification.Rd +++ b/man/s2dverification.Rd @@ -1,22 +1,28 @@ -\docType{package} -\name{s2dverification} -\alias{s2dverification-package} -\alias{s2dverification} -\title{Set of Common Tools for Forecast Verification} -\description{ -Set of tools to verify forecasts through the computation of typical prediction scores against one or more observational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the equations from a model, not a pure observational dataset). Intended for seasonal to decadal climate forecasts although can be useful to verify other kinds of forecasts. The package can be helpful in climate sciences for other purposes than forecasting. -} -\details{ - \tabular{ll}{ -Package: \tab s2dverification\cr -Type: \tab Package\cr -Version: \tab 2.8.4\cr -Date: \tab 2019-01-30\cr -License: \tab LGPLv3\cr - } -Check an overview of the package functionalities and its modules at \url{https://earth.bsc.es/gitlab/es/s2dverification/wikis/home}. -For more information load the package and check the help for each function or the documentation attached to the package. -} -\keyword{package} -\keyword{datagen} +\docType{package} +\name{s2dverification} +\alias{s2dverification-package} +\alias{s2dverification} +\title{Set of Common Tools for Forecast Verification} +\description{ +Set of tools to verify forecasts through the computation of typical prediction scores against one or more obser +vational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the +equations from a model, not a pure observational dataset). Intended for seasonal to decadal climate forecasts +although can be useful to verify other kinds of forecasts. The package can be helpful in climate sciences for o +ther purposes than forecasting. +} +\details{ + \tabular{ll}{ +Package: \tab s2dverification\cr +Type: \tab Package\cr +Version: \tab 2.8.4\cr +Date: \tab 2019-01-30\cr +License: \tab LGPLv3\cr + } +Check an overview of the package functionalities and its modules at \url{https://earth.bsc.es/gitlab/es/s2dveri +fication/wikis/home}. +For more information load the package and check the help for each function or the documentation attached to the +package. +} +\keyword{package} +\keyword{datagen} \keyword{dynamic} -- GitLab From 88f24573df095803e0217d6da98ac03c14a981ae Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 31 Jul 2019 11:56:43 +0200 Subject: [PATCH 34/61] Roxygen2 bugfix. Add NEWS.md. --- .Rbuildignore | 1 + DESCRIPTION | 7 ++-- NAMESPACE | 1 + NEWS.md | 3 ++ R/Load.R | 2 +- R/s2dverification.R | 27 ++++++++++++++++ R/sampleDepthData.R | 1 + R/sampleMap.R | 2 +- R/sampleTimeSeries.R | 2 +- man/s2dverification.Rd | 50 +++++++++++++++++------------ man/sampleDepthData.Rd | 44 +++++++++++++++---------- man/sampleMap.Rd | 64 +++++++++++++++++++------------------ man/sampleTimeSeries.Rd | 71 ++++++++++++++++++++++------------------- 13 files changed, 168 insertions(+), 107 deletions(-) create mode 100644 NEWS.md create mode 100644 R/s2dverification.R diff --git a/.Rbuildignore b/.Rbuildignore index 5493f6df..aa8227b1 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -8,3 +8,4 @@ README\.Rmd$ README\.md$ \..*\.RData$ vignettes +.gitlab-ci.yml diff --git a/DESCRIPTION b/DESCRIPTION index ba2cbf28..78935b85 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -4,7 +4,9 @@ Version: 2.8.5 Authors@R: c( person("BSC-CNS", role = c("aut", "cph")), person("Virginie", "Guemas", , "virginie.guemas@bsc.es", role = "aut"), - person("Nicolau", "Manubens", , "nicolau.manubens@bsc.es", role = c("aut", "cre")), + person("Nicolau", "Manubens", , "nicolau.manubens@bsc.es", role = "aut"), + person("An-Chi", "Ho", , "an.ho@bsc.es", role = c("ctb", "cre")), + person("Nuria", "Perez-Zanon", , "nuria.perez@bsc.es", role = "ctb"), person("Javier", "Garcia-Serrano", , "javier.garcia@bsc.es", role = "aut"), person("Neven", "Fuckar", , "neven.fuckar@bsc.es", role = "aut"), person("Louis-Philippe", "Caron", , "louis-philippe.caron@bsc.es", role = "aut"), @@ -26,8 +28,7 @@ Authors@R: c( person("Eleftheria", "Exarchou", , "eleftheria.exarchou@bsc.es", role = "ctb"), person("Ruben", "Cruz", , "ruben.cruzgarcia@bsc.es", role = "ctb"), person("Isabel", "Andreu-Burillo", , "isabel.andreu.burillo@ic3.cat", role = "ctb"), - person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb"), - person("An-Chi", "Ho", , "an.ho@bsc.es", role = "ctb")) + person("Ramiro", "Saurral", , "ramiro.saurral@ic3.cat", role = "ctb")) Description: Set of tools to verify forecasts through the computation of typical prediction scores against one or more observational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the diff --git a/NAMESPACE b/NAMESPACE index 5f8f409c..96cfff4d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -88,6 +88,7 @@ import(geomapdata) import(graphics) import(mapproj) import(maps) +import(methods) import(ncdf4) import(parallel) import(plyr) diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 00000000..51b198b1 --- /dev/null +++ b/NEWS.md @@ -0,0 +1,3 @@ +# s2dverification 2.9.0 (Release date: ) +- Apply Roxygen2 to all the files. (2019.07.31) (An-Chi) + diff --git a/R/Load.R b/R/Load.R index fafadbae..98e74f9e 100644 --- a/R/Load.R +++ b/R/Load.R @@ -838,7 +838,7 @@ #' latmin = 27, latmax = 48, #' lonmin = -12, lonmax = 40) #' } -#'@import parallel bigmemory +#'@import parallel bigmemory methods #'@export Load <- function(var, exp = NULL, obs = NULL, sdates, nmember = NULL, nmemberobs = NULL, nleadtime = NULL, leadtimemin = 1, diff --git a/R/s2dverification.R b/R/s2dverification.R new file mode 100644 index 00000000..d332f38d --- /dev/null +++ b/R/s2dverification.R @@ -0,0 +1,27 @@ +#'Set of Common Tools for Forecast Verification +#' +#'Set of tools to verify forecasts through the computation of typical +#'prediction scores against one or more observational datasets or reanalyses +#'(a reanalysis being a physical extrapolation of observations that relies on +#'the equations from a model, not a pure observational dataset). Intended for +#'seasonal to decadal climate forecasts although can be useful to verify other +#'kinds of forecasts. The package can be helpful in climate sciences for other +#'purposes than forecasting. +#' +#' \tabular{ll}{ +#'Package: \tab s2dverification\cr +#'Type: \tab Package\cr +#'Version: \tab 2.8.4\cr +#'Date: \tab 2019-01-30\cr +#'License: \tab LGPLv3\cr +#' } +#'Check an overview of the package functionalities and its modules at +#'\url{https://earth.bsc.es/gitlab/es/s2dverification/wikis/home}. +#'For more information load the package and check the help for each function +#'or the documentation attached to the package. +#' +#'@name s2dverification +#'@docType package +#'@author Nicolau Manubens \email{nicolau.manubens@bsc.es} +#'@keywords package datagen dynamic +"_PACKAGE" diff --git a/R/sampleDepthData.R b/R/sampleDepthData.R index 4785e16b..6a0e09ce 100644 --- a/R/sampleDepthData.R +++ b/R/sampleDepthData.R @@ -25,3 +25,4 @@ #'@docType data #'@author Nicolau Manubens \email{nicolau.manubens@bsc.es} #'@keywords data +sampleDepthData <- function(){} diff --git a/R/sampleMap.R b/R/sampleMap.R index 7f6ef817..b10aff23 100644 --- a/R/sampleMap.R +++ b/R/sampleMap.R @@ -1,7 +1,6 @@ #'Sample Of Observational And Experimental Data For Forecast Verification In Function Of Longitudes And Latitudes #' #'This data set provides data in function of longitudes and latitudes for the variable 'tos', i.e. sea surface temperature, over the mediterranean zone from the sample experimental and observational datasets attached to the package. See examples on how to use Load() for details.\cr\cr -#' #'The data is provided through a variable named 'sampleMap' and is structured as expected from the 'Load()' function in the 's2dverification' package if was called as follows:\cr\cr #' \preformatted{ #'data_path <- system.file('sample_data', package = 's2dverification') @@ -43,4 +42,5 @@ #' @docType data #' @author Nicolau Manubens \email{nicolau.manubens@bsc.es} #' @keywords datasets +sampleMap <- function(){} diff --git a/R/sampleTimeSeries.R b/R/sampleTimeSeries.R index 57f86b4f..86e38f42 100644 --- a/R/sampleTimeSeries.R +++ b/R/sampleTimeSeries.R @@ -45,4 +45,4 @@ #' @docType data #' @author Nicolau Manubens \email{nicolau.manubens@bsc.es} #' @keywords datasets - +sampleTimeSeries <- function(){} diff --git a/man/s2dverification.Rd b/man/s2dverification.Rd index 33d06564..698fa4ed 100644 --- a/man/s2dverification.Rd +++ b/man/s2dverification.Rd @@ -1,28 +1,36 @@ -\docType{package} -\name{s2dverification} -\alias{s2dverification-package} -\alias{s2dverification} -\title{Set of Common Tools for Forecast Verification} -\description{ -Set of tools to verify forecasts through the computation of typical prediction scores against one or more obser -vational datasets or reanalyses (a reanalysis being a physical extrapolation of observations that relies on the -equations from a model, not a pure observational dataset). Intended for seasonal to decadal climate forecasts -although can be useful to verify other kinds of forecasts. The package can be helpful in climate sciences for o -ther purposes than forecasting. -} -\details{ - \tabular{ll}{ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/s2dverification.R +\docType{package} +\name{s2dverification} +\alias{s2dverification} +\alias{s2dverification-package} +\title{Set of Common Tools for Forecast Verification} +\description{ +Set of tools to verify forecasts through the computation of typical +prediction scores against one or more observational datasets or reanalyses +(a reanalysis being a physical extrapolation of observations that relies on +the equations from a model, not a pure observational dataset). Intended for +seasonal to decadal climate forecasts although can be useful to verify other +kinds of forecasts. The package can be helpful in climate sciences for other +purposes than forecasting. +} +\details{ +\tabular{ll}{ Package: \tab s2dverification\cr Type: \tab Package\cr Version: \tab 2.8.4\cr Date: \tab 2019-01-30\cr License: \tab LGPLv3\cr } -Check an overview of the package functionalities and its modules at \url{https://earth.bsc.es/gitlab/es/s2dveri -fication/wikis/home}. -For more information load the package and check the help for each function or the documentation attached to the -package. -} -\keyword{package} -\keyword{datagen} +Check an overview of the package functionalities and its modules at +\url{https://earth.bsc.es/gitlab/es/s2dverification/wikis/home}. +For more information load the package and check the help for each function +or the documentation attached to the package. +} +\author{ +Nicolau Manubens \email{nicolau.manubens@bsc.es} +} +\keyword{datagen} \keyword{dynamic} +\keyword{package} + diff --git a/man/sampleDepthData.Rd b/man/sampleDepthData.Rd index c5ccfd3b..974fe6bd 100644 --- a/man/sampleDepthData.Rd +++ b/man/sampleDepthData.Rd @@ -1,25 +1,35 @@ -\name{sampleDepthData} +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sampleDepthData.R \docType{data} +\name{sampleDepthData} \alias{sampleDepthData} -\title{Sample of Experimental Data for Forecast Verification In Function Of Latitudes And Depths} -\description{ -This data set provides data in function of latitudes and depths for the variable 'tos', i.e. sea surface temperature, from the decadal climate prediction experiment run at IC3 in the context of the CMIP5 project.\cr -Its name within IC3 local database is 'i00k'. -} -\usage{ -data(sampleDepthData) -} -\format{ -The data set provides with a variable named 'sampleDepthData'.\cr\cr +\title{Sample of Experimental Data for Forecast Verification In Function Of +Latitudes And Depths} +\format{The data set provides with a variable named 'sampleDepthData'.\cr\cr -sampleDepthData$exp is an array that contains the experimental data and the dimension meanings and values are:\cr - c(# of experimental datasets, # of members, # of starting dates, # of lead-times, # of depths, # of latitudes)\cr - c(1, 5, 3, 60, 7, 21)\cr\cr +sampleDepthData$exp is an array that contains the experimental data and the +dimension meanings and values are:\cr + c(# of experimental datasets, # of members, # of starting dates, + # of lead-times, # of depths, # of latitudes)\cr + c(1, 5, 3, 60, 7, 21)\cr\cr -sampleDepthData$obs should be an array that contained the observational data but in this sample is not defined (NULL).\cr\cr +sampleDepthData$obs should be an array that contained the observational data +but in this sample is not defined (NULL).\cr\cr sampleDepthData$depths is an array with the 7 longitudes covered by the data.\cr\cr -sampleDepthData$lat is an array with the 21 latitudes covered by the data.\cr\cr +sampleDepthData$lat is an array with the 21 latitudes covered by the data.\cr\cr} +\usage{ +data(sampleDepthData) } -\keyword{datasets} +\description{ +This data set provides data in function of latitudes and depths for the +variable 'tos', i.e. sea surface temperature, from the decadal climate +prediction experiment run at IC3 in the context of the CMIP5 project.\cr +Its name within IC3 local database is 'i00k'. +} +\author{ +Nicolau Manubens \email{nicolau.manubens@bsc.es} +} +\keyword{data} + diff --git a/man/sampleMap.Rd b/man/sampleMap.Rd index fd5b9714..d33ab829 100644 --- a/man/sampleMap.Rd +++ b/man/sampleMap.Rd @@ -1,48 +1,50 @@ -\name{sampleMap} +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sampleMap.R \docType{data} +\name{sampleMap} \alias{sampleMap} \title{Sample Of Observational And Experimental Data For Forecast Verification In Function Of Longitudes And Latitudes} +\format{The data set provides with a variable named 'sampleMap'.\cr\cr + +sampleMap$mod is an array that contains the experimental data and the dimension meanings and values are:\cr + c(# of experimental datasets, # of members, # of starting dates, # of lead-times, # of latitudes, # of longitudes)\cr + c(1, 3, 5, 60, 2, 3)\cr\cr + +sampleMap$obs is an array that contains the observational data and the dimension meanings and values are:\cr + c(# of observational datasets, # of members, # of starting dates, # of lead-times, # of latitudes, # of longitudes)\cr + c(1, 1, 5, 60, 2, 3)\cr\cr + + sampleMap$lat is an array with the 2 latitudes covered by the data (see examples on Load() for details on why such low resolution).\cr\cr + + sampleMap$lon is an array with the 3 longitudes covered by the data (see examples on Load() for details on why such low resolution).} +\usage{ +data(sampleMap) +} \description{ This data set provides data in function of longitudes and latitudes for the variable 'tos', i.e. sea surface temperature, over the mediterranean zone from the sample experimental and observational datasets attached to the package. See examples on how to use Load() for details.\cr\cr - The data is provided through a variable named 'sampleMap' and is structured as expected from the 'Load()' function in the 's2dverification' package if was called as follows:\cr\cr - \preformatted{ + \preformatted{ data_path <- system.file('sample_data', package = 's2dverification') exp <- list( - name = 'experiment', - path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', - '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') - ) + name = 'experiment', + path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', + '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') + ) obs <- list( - name = 'observation', - path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', - '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') - ) + name = 'observation', + path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', + '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + ) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(exp), list(obs), startDates, - leadtimemin = 1, leadtimemax = 4, output = 'lonlat', - latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) - } + leadtimemin = 1, leadtimemax = 4, output = 'lonlat', + latmin = 27, latmax = 48, lonmin = -12, lonmax = 40) + } Check the documentation on 'Load()' in the package 's2dverification' for more information. } -\usage{ -data(sampleMap) -} -\format{ -The data set provides with a variable named 'sampleMap'.\cr\cr - -sampleMap$mod is an array that contains the experimental data and the dimension meanings and values are:\cr - c(# of experimental datasets, # of members, # of starting dates, # of lead-times, # of latitudes, # of longitudes)\cr - c(1, 3, 5, 60, 2, 3)\cr\cr - -sampleMap$obs is an array that contains the observational data and the dimension meanings and values are:\cr - c(# of observational datasets, # of members, # of starting dates, # of lead-times, # of latitudes, # of longitudes)\cr - c(1, 1, 5, 60, 2, 3)\cr\cr - - sampleMap$lat is an array with the 2 latitudes covered by the data (see examples on Load() for details on why such low resolution).\cr\cr - - sampleMap$lon is an array with the 3 longitudes covered by the data (see examples on Load() for details on why such low resolution). +\author{ +Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{datasets} diff --git a/man/sampleTimeSeries.Rd b/man/sampleTimeSeries.Rd index 869c91e4..ce2c6395 100644 --- a/man/sampleTimeSeries.Rd +++ b/man/sampleTimeSeries.Rd @@ -1,47 +1,54 @@ -\name{sampleTimeSeries} +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sampleTimeSeries.R \docType{data} +\name{sampleTimeSeries} \alias{sampleTimeSeries} \title{Sample Of Observational And Experimental Data For Forecast Verification As Area Averages} +\format{The data set provides with a variable named 'sampleTimeSeries'.\cr\cr + +sampleTimeSeries$mod is an array that contains the experimental data and the dimension meanings and values are:\cr + c(# of experimental datasets, # of members, # of starting dates, # of lead-times)\cr + c(1, 3, 5, 60)\cr\cr + +sampleTimeSeries$obs is an array that contains the observational data and the dimension meanings and values are:\cr + c(# of observational datasets, # of members, # of starting dates, # of lead-times)\cr + c(1, 1, 5, 60)\cr\cr + +sampleTimeSeries$lat is an array with the 2 latitudes covered by the data that was area averaged to calculate the time series (see examples on Load() for details on why such low resolution).\cr\cr + +sampleTimeSeries$lon is an array with the 3 longitudes covered by the data that was area averaged to calculate the time series (see examples on Load() for details on why such low resolution).} +\usage{ +data(sampleTimeSeries) +} \description{ -This data set provides area averaged data for the variable 'tos', i.e. sea surface temperature, over the mediterranean zone from the example datasets attached to the package. See examples on Load() for more details.\cr\cr -The data is provided through a variable named 'sampleTimeSeries' and is structured as expected from the 'Load()' function in the 's2dverification' package if was called as follows:\cr\cr - \preformatted{ +This data set provides area averaged data for the variable 'tos', i.e. sea +surface temperature, over the mediterranean zone from the example datasets +attached to the package. See examples on Load() for more details.\cr\cr +The data is provided through a variable named 'sampleTimeSeries' and is +structured as expected from the 'Load()' function in the 's2dverification' +package if was called as follows:\cr\cr + \preformatted{ data_path <- system.file('sample_data', package = 's2dverification') exp <- list( - name = 'experiment', - path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', - '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') - ) + name = 'experiment', + path = file.path(data_path, 'model/$EXP_NAME$/monthly_mean', + '$VAR_NAME$_3hourly/$VAR_NAME$_$START_DATES$.nc') + ) obs <- list( - name = 'observation', - path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', - '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') - ) + name = 'observation', + path = file.path(data_path, 'observation/$OBS_NAME$/monthly_mean', + '$VAR_NAME$/$VAR_NAME$_$YEAR$$MONTH$.nc') + ) # Now we are ready to use Load(). startDates <- c('19851101', '19901101', '19951101', '20001101', '20051101') sampleData <- Load('tos', list(exp), list(obs), startDates, - output = 'areave', latmin = 27, latmax = 48, lonmin = -12, - lonmax = 40) - } + output = 'areave', latmin = 27, latmax = 48, lonmin = -12, + lonmax = 40) + } Check the documentation on 'Load()' in the package 's2dverification' for more information. } -\usage{ -data(sampleTimeSeries) -} -\format{ -The data set provides with a variable named 'sampleTimeSeries'.\cr\cr - -sampleTimeSeries$mod is an array that contains the experimental data and the dimension meanings and values are:\cr - c(# of experimental datasets, # of members, # of starting dates, # of lead-times)\cr - c(1, 3, 5, 60)\cr\cr - -sampleTimeSeries$obs is an array that contains the observational data and the dimension meanings and values are:\cr - c(# of observational datasets, # of members, # of starting dates, # of lead-times)\cr - c(1, 1, 5, 60)\cr\cr - -sampleTimeSeries$lat is an array with the 2 latitudes covered by the data that was area averaged to calculate the time series (see examples on Load() for details on why such low resolution).\cr\cr - -sampleTimeSeries$lon is an array with the 3 longitudes covered by the data that was area averaged to calculate the time series (see examples on Load() for details on why such low resolution). +\author{ +Nicolau Manubens \email{nicolau.manubens@bsc.es} } \keyword{datasets} -- GitLab From 4941e026b54b4858def7b575d41b2f94f21f37d6 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 1 Aug 2019 14:30:25 +0200 Subject: [PATCH 35/61] Rename NEWS.md to NEWS. --- NEWS.md => NEWS | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename NEWS.md => NEWS (100%) diff --git a/NEWS.md b/NEWS similarity index 100% rename from NEWS.md rename to NEWS -- GitLab From 0787c2010821be9ec4112664809289e4b406de6e Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 2 Aug 2019 16:48:40 +0200 Subject: [PATCH 36/61] Bugfix. --- tests/testthat/test-Composite.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-Composite.R b/tests/testthat/test-Composite.R index 42c003a0..9788c4f3 100644 --- a/tests/testthat/test-Composite.R +++ b/tests/testthat/test-Composite.R @@ -3,7 +3,7 @@ test_that("Sanity checks", { expect_error( Composite(var = array(1:20, dim = c(2, 5, 2)), c(1, 1, 0)), - "temporal dimension of var is not equal to length of occ.") + "Temporal dimension of var is not equal to length of occ.") expect_warning( Composite(var = array(1:40, dim = c(2, 5, 4)), c(1, 2, 2, 2)), -- GitLab From 557fc09e6924a66733283b01d36ea0daf4c5994b Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 2 Aug 2019 17:11:16 +0200 Subject: [PATCH 37/61] Revision according to CRAN submission result. --- NAMESPACE | 3 +++ NEWS => NEWS.md | 0 R/ACC.R | 1 + R/Alpha.R | 1 + R/AnimateMap.R | 1 + R/CDORemap.R | 1 + R/Cluster.R | 2 ++ R/ColorBar.R | 1 + R/Composite.R | 3 ++- R/Corr.R | 2 ++ R/EOF.R | 2 ++ R/Eno.R | 2 ++ R/Filter.R | 1 + R/GenSeries.R | 2 ++ R/Load.R | 2 ++ R/Plot2VarsVsLTime.R | 2 ++ R/PlotACC.R | 2 ++ R/PlotAno.R | 2 ++ R/PlotBoxWhisker.R | 2 ++ R/PlotClim.R | 2 ++ R/PlotEquiMap.R | 2 ++ R/PlotLayout.R | 1 + R/PlotSection.R | 1 + R/PlotStereoMap.R | 2 ++ R/PlotVsLTime.R | 2 ++ R/RMS.R | 1 + R/RMSSS.R | 1 + R/RatioSDRMS.R | 1 + R/Regression.R | 1 + R/SVD.R | 1 + R/Spectrum.R | 1 + R/Spread.R | 1 + R/ToyModel.R | 1 + R/Trend.R | 1 + R/clim.palette.R | 1 + tests/testthat/test-Composite.R | 8 ++++---- 36 files changed, 55 insertions(+), 5 deletions(-) rename NEWS => NEWS.md (100%) diff --git a/NAMESPACE b/NAMESPACE index 96cfff4d..8b51222c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -92,3 +92,6 @@ import(methods) import(ncdf4) import(parallel) import(plyr) +importFrom(stats,cor) +importFrom(stats,pt) +importFrom(stats,qnorm) diff --git a/NEWS b/NEWS.md similarity index 100% rename from NEWS rename to NEWS.md diff --git a/R/ACC.R b/R/ACC.R index f71425b7..aeabc079 100644 --- a/R/ACC.R +++ b/R/ACC.R @@ -91,6 +91,7 @@ #' 1.3.1 - 2014-09 (C. Prodhomme, \email{chloe.prodhomme@@bsc.es}) - Add comments and minor style changes\cr #' 1.3.2 - 2015-02 (N. Manubens, \email{nicolau.manubens@@bsc.es}) - Fixed ACC documentation and examples #'@import abind +#'@importFrom stats qt qnorm quantile #'@export ACC <- function(var_exp, var_obs, lon = NULL, lat = NULL, lonlatbox = NULL, conf = TRUE, conftype = "parametric", diff --git a/R/Alpha.R b/R/Alpha.R index cc187239..a1ef1f0c 100644 --- a/R/Alpha.R +++ b/R/Alpha.R @@ -27,6 +27,7 @@ #'@author History:\cr #' 0.1 - 2012-06 (V. Guemas, \email{virginie.guemas@@ic3.cat}) - Original code\cr #' 1.0 - 2013-09 (N. Manubens, \email{nicolau.manubens@@ic3.cat}) - Formatting to CRAN +#'@importFrom stats lm confint acf #'@export Alpha <- function(xdata, detrend = FALSE, filter = FALSE) { tmp <- xdata diff --git a/R/AnimateMap.R b/R/AnimateMap.R index 733cfd5b..0f4d4b38 100644 --- a/R/AnimateMap.R +++ b/R/AnimateMap.R @@ -153,6 +153,7 @@ #' monini = 1, freq = 1, msk95lev = FALSE, brks = seq(0, 0.8, 0.08), #' intlon = 10, intlat = 10, filled.continents = TRUE, #' fileout = 'rmse_dec.gif') +#'@importFrom grDevices postscript dev.off #'@export AnimateMap <- function(var, lon, lat, toptitle = rep("", 11), sizetit = 1, units = "", monini = 1, freq = 12, msk95lev = FALSE, diff --git a/R/CDORemap.R b/R/CDORemap.R index bc420873..a04d88a5 100644 --- a/R/CDORemap.R +++ b/R/CDORemap.R @@ -205,6 +205,7 @@ #'tas2 <- CDORemap(tas, lon, lat, 'external_file.nc', 'bil') #'} #'@import ncdf4 +#'@importFrom stats lm predict setNames #'@export CDORemap <- function(data_array = NULL, lons, lats, grid, method, avoid_writes = TRUE, crop = TRUE, diff --git a/R/Cluster.R b/R/Cluster.R index e37b1585..da9c62a6 100644 --- a/R/Cluster.R +++ b/R/Cluster.R @@ -107,6 +107,8 @@ #'print(res2$cluster) #'print(res2$centers) #'@import NbClust +#'@importFrom stats kmeans +#'@importFrom grDevices pdf dev.off #'@export Cluster <- function(var, weights, nclusters = NULL, index = 'sdindex', posdates = 1) { diff --git a/R/ColorBar.R b/R/ColorBar.R index 59f947ff..b475d08a 100644 --- a/R/ColorBar.R +++ b/R/ColorBar.R @@ -147,6 +147,7 @@ #' "white", "yellow", "orange", "red", "saddlebrown") #'lims <- seq(-1, 1, 0.2) #'ColorBar(lims, cols) +#'@importFrom grDevices col2rgb rgb #'@export ColorBar <- function(brks = NULL, cols = NULL, vertical = TRUE, subsampleg = NULL, bar_limits = NULL, var_limits = NULL, diff --git a/R/Composite.R b/R/Composite.R index 606cdae1..865501d6 100644 --- a/R/Composite.R +++ b/R/Composite.R @@ -67,11 +67,12 @@ #'occ2[c(3, 9, 15, 21)] <- 1 #' #'filled.contour(Composite(var=f1, occ=occ2)$composite[,,1]) +#'@importFrom stats sd pt #'@export Composite <- function(var, occ, lag = 0, eno = FALSE, fileout = NULL) { if ( dim(var)[3] != length(occ) ) { - stop("temporal dimension of var is not equal to length of occ.") + stop("Temporal dimension of var is not equal to length of occ.") } K <- max(occ) composite <- array(dim = c(dim(var)[1:2], K)) diff --git a/R/Corr.R b/R/Corr.R index 77fa2f91..18ae9b14 100644 --- a/R/Corr.R +++ b/R/Corr.R @@ -102,6 +102,7 @@ #' tdim = 3, ensdim = 2) #' } #'@rdname Corr +#'@importFrom stats cor pt qnorm #'@export Corr <- function(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, limits = NULL, siglev = 0.95, method = 'pearson', @@ -230,6 +231,7 @@ Corr <- function(var_exp, var_obs, posloop = 1, poscor = 2, compROW = NULL, } #'@rdname Corr +#'@importFrom stats cor pt qnorm #'@export .Corr <- function(exp, obs, siglev = 0.95, method = 'pearson', conf = TRUE, pval = TRUE) { diff --git a/R/EOF.R b/R/EOF.R index 5c2116c3..6ed8c6f7 100644 --- a/R/EOF.R +++ b/R/EOF.R @@ -102,6 +102,8 @@ #'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) #'eof <- EOF(Mean1Dim(ano$ano_exp, 2)[1, , 1, , ], sampleData$lon, sampleData$lat) #'PlotEquiMap(eof$EOFs[1, , ], sampleData$lon, sampleData$lat) +#' +#'@importFrom stats sd #'@export EOF <- function(ano, lon, lat, neofs = 15, corr = FALSE) { # Checking ano diff --git a/R/Eno.R b/R/Eno.R index 8d021d0c..877710cb 100644 --- a/R/Eno.R +++ b/R/Eno.R @@ -46,6 +46,8 @@ #'sampleData$mod <- Season(sampleData$mod, 4, 11, 1, 12) #'eno <- Eno(sampleData$mod[1, 1, , 1, , ], 1) #'PlotEquiMap(eno, sampleData$lon, sampleData$lat) +#' +#'@importFrom stats acf na.pass #'@export Eno <- function(obs, posdim) { dimsvar <- dim(obs) diff --git a/R/Filter.R b/R/Filter.R index b11d4d37..42c847f9 100644 --- a/R/Filter.R +++ b/R/Filter.R @@ -33,6 +33,7 @@ #'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = #' 'filtered_ensemble_mean.eps') #' +#'@importFrom stats lm #'@export Filter <- function(xdata, freq) { fac1 <- 1 diff --git a/R/GenSeries.R b/R/GenSeries.R index 132f0e48..402170a9 100644 --- a/R/GenSeries.R +++ b/R/GenSeries.R @@ -18,6 +18,8 @@ #'@examples #'series <- GenSeries(1000, 0.35, 2, 1) #'plot(series, type = 'l') +#' +#'@importFrom stats rnorm #'@export GenSeries <- function(n, alpha, mean, std) { res <- vector("numeric", n) diff --git a/R/Load.R b/R/Load.R index 98e74f9e..de4be071 100644 --- a/R/Load.R +++ b/R/Load.R @@ -839,6 +839,7 @@ #' lonmin = -12, lonmax = 40) #' } #'@import parallel bigmemory methods +#'@importFrom stats ts window na.omit #'@export Load <- function(var, exp = NULL, obs = NULL, sdates, nmember = NULL, nmemberobs = NULL, nleadtime = NULL, leadtimemin = 1, @@ -872,6 +873,7 @@ Load <- function(var, exp = NULL, obs = NULL, sdates, nmember = NULL, if (x == 'sdates' && length(load_parameters[[x]]) > 4) { paste0("c('", load_parameters[[x]][1], "', '", load_parameters[[x]][2], "', ..., '", tail(load_parameters[[x]], 1), "')") + "', ..., '", tail(load_parameters[[x]], 1), "')") } else if ((x %in% c('exp', 'obs')) && is.list(load_parameters[[x]])) { paste0("list(", paste(unlist(lapply(load_parameters[[x]], function (y) { diff --git a/R/Plot2VarsVsLTime.R b/R/Plot2VarsVsLTime.R index e5ee0556..c5d5abcf 100644 --- a/R/Plot2VarsVsLTime.R +++ b/R/Plot2VarsVsLTime.R @@ -81,6 +81,8 @@ #' listexp = c('CMIP5 IC3'), listvar = c('RMSE', 'spread'), #' fileout = 'plot2vars.eps') #' +#'@importFrom grDevices png jpeg postscript pdf svg bmp tiff postscript dev.cur dev.new dev.off +#'@importFrom stats ts #'@export Plot2VarsVsLTime <- function(var1, var2, toptitle = '', ytitle = '', monini = 1, freq = 12, nticks = NULL, limits = NULL, listexp = diff --git a/R/PlotACC.R b/R/PlotACC.R index 9e783016..bff6511a 100644 --- a/R/PlotACC.R +++ b/R/PlotACC.R @@ -87,6 +87,8 @@ #' Mean1Dim(sampleData$obs, 2)) #'PlotACC(acc$ACC, startDates, toptitle = "Anomaly Correlation Coefficient") #' +#'@importFrom grDevices dev.cur dev.new dev.off +#'@importFrom stats ts #'@export PlotACC <- function(ACC, sdates, toptitle = "", sizetit = 1, ytitle = "", limits = NULL, legends = NULL, freq = 12, biglab = FALSE, diff --git a/R/PlotAno.R b/R/PlotAno.R index 7e904cda..cc897a92 100644 --- a/R/PlotAno.R +++ b/R/PlotAno.R @@ -70,6 +70,8 @@ #' toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') #' +#'@importFrom grDevices dev.cur dev.new dev.off +#'@importFrom stats ts #'@export PlotAno <- function(exp_ano, obs_ano = NULL, sdates, toptitle = rep('', 15), ytitle = rep('', 15), limits = NULL, legends = NULL, diff --git a/R/PlotBoxWhisker.R b/R/PlotBoxWhisker.R index 46e9e478..1574522c 100644 --- a/R/PlotBoxWhisker.R +++ b/R/PlotBoxWhisker.R @@ -98,6 +98,8 @@ #'PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", #' monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") #' +#'@importFrom grDevices dev.cur dev.new dev.off +#'@importFrom stats cor #'@export PlotBoxWhisker <- function(exp, obs, toptitle = '', ytitle = '', monini = 1, yearini = 0, freq = 1, expname = "exp 1", diff --git a/R/PlotClim.R b/R/PlotClim.R index fbb3c9e1..e7e6ac31 100644 --- a/R/PlotClim.R +++ b/R/PlotClim.R @@ -53,6 +53,8 @@ #' ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') #' +#'@importFrom grDevices dev.cur dev.new dev.off +#'@importFrom stats ts #'@export PlotClim <- function(exp_clim, obs_clim = NULL, toptitle = '', ytitle = '', monini = 1, freq = 12, limits = NULL, diff --git a/R/PlotEquiMap.R b/R/PlotEquiMap.R index 70bf78ab..8f3fcb9a 100644 --- a/R/PlotEquiMap.R +++ b/R/PlotEquiMap.R @@ -212,6 +212,8 @@ #' toptitle = 'Predicted sea surface temperature for Nov 1960 from 1st Nov', #' sizetit = 0.5) #'@import graphics GEOmap geomapdata maps +#'@importFrom grDevices dev.cur dev.new dev.off gray +#'@importFrom stats cor #'@export PlotEquiMap <- function(var, lon, lat, varu = NULL, varv = NULL, toptitle = NULL, sizetit = NULL, units = NULL, diff --git a/R/PlotLayout.R b/R/PlotLayout.R index 8cc7d68a..b5239f27 100644 --- a/R/PlotLayout.R +++ b/R/PlotLayout.R @@ -196,6 +196,7 @@ #' toptitle = 'Predicted tos for Nov 1960 from 1st Nov', #' titles = paste('Member', 1:15)) #' +#'@importFrom grDevices dev.cur dev.new dev.off #'@export PlotLayout <- function(fun, plot_dims, var, ..., special_args = NULL, nrow = NULL, ncol = NULL, toptitle = NULL, diff --git a/R/PlotSection.R b/R/PlotSection.R index 0722fd42..46a1e70a 100644 --- a/R/PlotSection.R +++ b/R/PlotSection.R @@ -44,6 +44,7 @@ #'sampleData <- s2dverification::sampleDepthData #'PlotSection(sampleData$mod[1, 1, 1, 1, , ], sampleData$lat, sampleData$depth, #' toptitle = 'temperature 1995-11 member 0') +#'@importFrom grDevices dev.cur dev.new dev.off rainbow #'@export PlotSection <- function(var, horiz, depth, toptitle = '', sizetit = 1, units = '', brks = NULL, cols = NULL, axelab = TRUE, diff --git a/R/PlotStereoMap.R b/R/PlotStereoMap.R index cb3283ec..5572f89a 100644 --- a/R/PlotStereoMap.R +++ b/R/PlotStereoMap.R @@ -141,6 +141,8 @@ #'PlotStereoMap(data, x, y, latlims = c(60, 90), brks = 50, #' toptitle = "This is the title") #'@import mapproj +#'@importFrom grDevices dev.cur dev.new dev.off gray +#'@importFrom stats median #'@export PlotStereoMap <- function(var, lon, lat, latlims = c(60, 90), toptitle = NULL, sizetit = NULL, units = NULL, diff --git a/R/PlotVsLTime.R b/R/PlotVsLTime.R index 4e625337..e3f7b7f7 100644 --- a/R/PlotVsLTime.R +++ b/R/PlotVsLTime.R @@ -95,6 +95,8 @@ #' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), #' fileout = 'tos_cor.eps') #' +#'@importFrom grDevices dev.cur dev.new dev.off +#'@importFrom stats ts #'@export PlotVsLTime <- function(var, toptitle = '', ytitle = '', monini = 1, freq = 12, nticks = NULL, limits = NULL, diff --git a/R/RMS.R b/R/RMS.R index 11406483..bb3dd389 100644 --- a/R/RMS.R +++ b/R/RMS.R @@ -198,6 +198,7 @@ RMS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, compROW = NULL, enlrms } #'@rdname RMS +#'@importFrom stats qchisq #'@export .RMS <- function(exp, obs, siglev = 0.95, conf = TRUE) { # diff --git a/R/RMSSS.R b/R/RMSSS.R index a8c4bcee..16623b32 100644 --- a/R/RMSSS.R +++ b/R/RMSSS.R @@ -161,6 +161,7 @@ RMSSS <- function(var_exp, var_obs, posloop = 1, posRMS = 2, pval = TRUE) { enlRMSSS } #'@rdname RMSSS +#'@importFrom stats pf #'@export .RMSSS <- function(exp, obs, pval = TRUE) { dif2 <- obs diff --git a/R/RatioSDRMS.R b/R/RatioSDRMS.R index d0664dd4..ec16bc3b 100644 --- a/R/RatioSDRMS.R +++ b/R/RatioSDRMS.R @@ -153,6 +153,7 @@ RatioSDRMS <- function(var_exp, var_obs, pval = TRUE) { enlratiormssd } #'@rdname RatioSDRMS +#'@importFrom stats sd pf #'@export .RatioSDRMS <- function(exp, obs, pval = TRUE) { diff --git a/R/Regression.R b/R/Regression.R index c39c942d..2afd14b8 100644 --- a/R/Regression.R +++ b/R/Regression.R @@ -60,6 +60,7 @@ #' toptitle='Regression of the prediction on the observations', #' sizetit = 0.5) #' +#'@importFrom stats lm na.omit confint #'@export Regression <- function(vary, varx, posREG = 2) { # diff --git a/R/SVD.R b/R/SVD.R index 9f880da6..687715b3 100644 --- a/R/SVD.R +++ b/R/SVD.R @@ -98,6 +98,7 @@ #'PlotEquiMap(mca$MCAs_V[1, , ], sampleData$lon, sampleData$lat) #'plot(mca$ECs_V[1, ]) #' +#'@importFrom stats sd cor lm #'@export SVD <- function(vary, varx, laty = NULL, latx = NULL, nmodes = 15, corr = FALSE, weight = TRUE) { diff --git a/R/Spectrum.R b/R/Spectrum.R index a0198351..bb9b2ca6 100644 --- a/R/Spectrum.R +++ b/R/Spectrum.R @@ -34,6 +34,7 @@ #'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = #' 'filtered_ensemble_mean.eps') #' +#'@importFrom stats spectrum cor rnorm sd quantile #'@export Spectrum <- function(xdata) { print('Warning : Your data are assumed to be evenly spaced in time') diff --git a/R/Spread.R b/R/Spread.R index 7cfe52ec..5a8e0189 100644 --- a/R/Spread.R +++ b/R/Spread.R @@ -76,6 +76,7 @@ #' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, #' hlines = c(0), fileout = 'tos_mad.eps') #' +#'@importFrom stats IQR sd mad runif quantile #'@export Spread <- function(var, posdim = 2, narm = TRUE, siglev = 0.95, conf = TRUE) { # diff --git a/R/ToyModel.R b/R/ToyModel.R index 0ac6b6f1..f0c9a22d 100644 --- a/R/ToyModel.R +++ b/R/ToyModel.R @@ -101,6 +101,7 @@ #' toptitle = c("Synthetic decadal temperature prediction"), #' fileout = "ex_toymodel.eps") #' +#'@importFrom stats rnorm #'@export ToyModel <- function(alpha = 0.1, beta = 0.4, gamma = 1, sig = 1, trend = 0, nstartd = 30, nleadt = 4, nmemb = 10, obsini = NULL, diff --git a/R/Trend.R b/R/Trend.R index 40eb3f02..15ec7ebe 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -135,6 +135,7 @@ Trend <- function(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) { } #'@rdname Trend +#'@importFrom stats lm na.omit confint #'@export .Trend <- function(exp, interval = 1, siglev = 0.95, conf = TRUE) { diff --git a/R/clim.palette.R b/R/clim.palette.R index 1ca309b7..d18dab16 100644 --- a/R/clim.palette.R +++ b/R/clim.palette.R @@ -21,6 +21,7 @@ #'ColorBar(lims, cols) #' #'@rdname clim.palette +#'@importFrom grDevices colorRampPalette #'@export clim.palette <- function(palette = "bluered") { if (palette == "bluered") { diff --git a/tests/testthat/test-Composite.R b/tests/testthat/test-Composite.R index 9788c4f3..13da826e 100644 --- a/tests/testthat/test-Composite.R +++ b/tests/testthat/test-Composite.R @@ -22,11 +22,11 @@ test_that("Sanity checks", { output ) - var <- array(rep(c(1, 3, 2, 1, 2), 8), dim = c(x = 2, y = 4, time = 5)) - occ <- c(1, 2, 2, 3, 3) - output <- array(as.numeric(rep(NA, 8)), dim = c(2, 4)) + var <- array(rep(c(1, 3, 2, 1, 2, 2), 8), dim = c(x = 2, y = 4, time = 6)) + occ <- c(1, 1, 2, 2, 3, 3) + output <- matrix(c(1.5, 2.5, 1.5, 2.0, 2.0, 1.5, 1.5, 2.5), 2, 4) expect_equal( - Composite(var, occ)$pvalue[, , 1], + Composite(var, occ)$composite[, , 2], output ) -- GitLab From 396fa6bc69484278253c72ad3bccc68ff73de047 Mon Sep 17 00:00:00 2001 From: aho Date: Fri, 2 Aug 2019 17:18:35 +0200 Subject: [PATCH 38/61] Bugfix. --- NAMESPACE | 36 ++++++++++++++++++++++++++++++++++++ R/Load.R | 1 - man/EOF.Rd | 1 + man/Eno.Rd | 1 + man/GenSeries.Rd | 1 + 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/NAMESPACE b/NAMESPACE index 8b51222c..3e35710e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -92,6 +92,42 @@ import(methods) import(ncdf4) import(parallel) import(plyr) +importFrom(grDevices,bmp) +importFrom(grDevices,col2rgb) +importFrom(grDevices,colorRampPalette) +importFrom(grDevices,dev.cur) +importFrom(grDevices,dev.new) +importFrom(grDevices,dev.off) +importFrom(grDevices,gray) +importFrom(grDevices,jpeg) +importFrom(grDevices,pdf) +importFrom(grDevices,png) +importFrom(grDevices,postscript) +importFrom(grDevices,rainbow) +importFrom(grDevices,rgb) +importFrom(grDevices,svg) +importFrom(grDevices,tiff) +importFrom(stats,IQR) +importFrom(stats,acf) +importFrom(stats,confint) importFrom(stats,cor) +importFrom(stats,kmeans) +importFrom(stats,lm) +importFrom(stats,mad) +importFrom(stats,median) +importFrom(stats,na.omit) +importFrom(stats,na.pass) +importFrom(stats,pf) +importFrom(stats,predict) importFrom(stats,pt) +importFrom(stats,qchisq) importFrom(stats,qnorm) +importFrom(stats,qt) +importFrom(stats,quantile) +importFrom(stats,rnorm) +importFrom(stats,runif) +importFrom(stats,sd) +importFrom(stats,setNames) +importFrom(stats,spectrum) +importFrom(stats,ts) +importFrom(stats,window) diff --git a/R/Load.R b/R/Load.R index de4be071..e17f3cfa 100644 --- a/R/Load.R +++ b/R/Load.R @@ -873,7 +873,6 @@ Load <- function(var, exp = NULL, obs = NULL, sdates, nmember = NULL, if (x == 'sdates' && length(load_parameters[[x]]) > 4) { paste0("c('", load_parameters[[x]][1], "', '", load_parameters[[x]][2], "', ..., '", tail(load_parameters[[x]], 1), "')") - "', ..., '", tail(load_parameters[[x]], 1), "')") } else if ((x %in% c('exp', 'obs')) && is.list(load_parameters[[x]])) { paste0("list(", paste(unlist(lapply(load_parameters[[x]], function (y) { diff --git a/man/EOF.Rd b/man/EOF.Rd index 118f6248..bd0b31e4 100644 --- a/man/EOF.Rd +++ b/man/EOF.Rd @@ -81,6 +81,7 @@ sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) eof <- EOF(Mean1Dim(ano$ano_exp, 2)[1, , 1, , ], sampleData$lon, sampleData$lat) PlotEquiMap(eof$EOFs[1, , ], sampleData$lon, sampleData$lat) + } \author{ History:\cr diff --git a/man/Eno.Rd b/man/Eno.Rd index 6ad23656..ba4f2088 100644 --- a/man/Eno.Rd +++ b/man/Eno.Rd @@ -52,6 +52,7 @@ sampleData <- s2dverification:::.LoadSampleData('tos', c('experiment'), sampleData$mod <- Season(sampleData$mod, 4, 11, 1, 12) eno <- Eno(sampleData$mod[1, 1, , 1, , ], 1) PlotEquiMap(eno, sampleData$lon, sampleData$lat) + } \author{ History:\cr diff --git a/man/GenSeries.Rd b/man/GenSeries.Rd index 61d53a9a..9a49ed9d 100644 --- a/man/GenSeries.Rd +++ b/man/GenSeries.Rd @@ -26,6 +26,7 @@ specified by the mean and std arguments. \examples{ series <- GenSeries(1000, 0.35, 2, 1) plot(series, type = 'l') + } \author{ History:\cr -- GitLab From f76412aa6c6528ba81a14229a347412b682432ac Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 5 Aug 2019 15:17:46 +0200 Subject: [PATCH 39/61] Bugfix. --- tests/testthat/test-Composite.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-Composite.R b/tests/testthat/test-Composite.R index 13da826e..f8edf1cd 100644 --- a/tests/testthat/test-Composite.R +++ b/tests/testthat/test-Composite.R @@ -25,7 +25,7 @@ test_that("Sanity checks", { var <- array(rep(c(1, 3, 2, 1, 2, 2), 8), dim = c(x = 2, y = 4, time = 6)) occ <- c(1, 1, 2, 2, 3, 3) output <- matrix(c(1.5, 2.5, 1.5, 2.0, 2.0, 1.5, 1.5, 2.5), 2, 4) - expect_equal( + expect_equivalent( Composite(var, occ)$composite[, , 2], output ) -- GitLab From ffe52eaf4f6989c952050f2d8e8280e0e3caed1b Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 3 Sep 2019 12:17:30 +0200 Subject: [PATCH 40/61] Modify PlotMatrix(). Update branch to master. --- NAMESPACE | 1 + R/PlotMatrix.R | 238 +++++++++++++++++++++++++++++++--------------- man/PlotMatrix.Rd | 89 +++++++++++++++++ 3 files changed, 252 insertions(+), 76 deletions(-) create mode 100644 man/PlotMatrix.Rd diff --git a/NAMESPACE b/NAMESPACE index 3e35710e..4e855789 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -56,6 +56,7 @@ export(PlotBoxWhisker) export(PlotClim) export(PlotEquiMap) export(PlotLayout) +export(PlotMatrix) export(PlotSection) export(PlotStereoMap) export(PlotVsLTime) diff --git a/R/PlotMatrix.R b/R/PlotMatrix.R index 3fb79bae..32a40c99 100644 --- a/R/PlotMatrix.R +++ b/R/PlotMatrix.R @@ -1,115 +1,201 @@ #'Function to convert any numerical table to a grid of coloured squares. #' -#'@description This function converts a numerical data matrix in a coloured grid. Useful in a slide or article, to present tabular results as colors instead of numbers. +#'This function converts a numerical data matrix into a coloured +#'grid. It is useful for a slide or article to present tabular results as +#'colors instead of numbers. #' -#'@param table numerical matrix containing the values to be displayed in a colored image. -#'@param colors A vector with the color sequence to use in the grid. -#'@param brks A vector with the intervals to split the data into. There must be one \code{brks} more than the number of \code{colors}. -#'@param title The title of the grid. Default is NULL (no title). -#'@param title.color Color to use for the title (default is dark blue). -#'@param xtitle Title of the x-axis (default is NULL) -#'@param ytitle Title of the y-axis (default is NULL) -#'@param xlabels Vector of length ncol(\code{table}) with the labels of the x-axis (default is a sequence from 1 to the number of columns). -#'@param xvert If x-axis labels are too long, it is possible to place them vertically by setting \code{xvert} to TRUE (default is FALSE). -#'@param ylabels Vector of length nrow(\code{table}) with the labels of the y-axis (default is a sequence from 1 to the number of rows). -#'@param line Distance of the title of the x-axis from the x-axis (default is 3 lines). Adjust as necessary if your x-axis labels are long. -#'@param figure.width If the form of the grid cells is not perfectly squared, it is possible adjust it by multiplying the grid width for this factor (default is 1). -#'@param legend Set it to FALSE not to draw the grid color legend (default is TRUE). -#'@param legend.width If the width of the color legend is too small or too large, it can be adjusted by increasing or decreasing the legend width (default is 0.15) -#'@param file Set the path and the filename where the .png image of the grid will be saved (default is 'PlotMatrix.png' in the working directory). -#'@param ... Set additional parameters to pass to draw the color legend with function ColorBar() of package s2dverification. -#' -#'@return No data is returned. Only the grid image is saved in a .png file specified by the user. +#'@param var A numerical matrix containing the values to be displayed in a +#' colored image. +#'@param brks A vector of the color bar intervals. The length must be one more +#' than the parameter 'cols'. Use ColorBar() to generate default values. +#'@param cols A vector of valid color identifiers for color bar. The length +#' must be one less than the parameter 'brks'. Use ColorBar() to generate +#' default values. +#'@param toptitle A string of the title of the grid. Set NULL as default. +#'@param title.color A string of valid color identifier to decide the title +#' color. Set "royalblue4" as default. +#'@param xtitle A string of title of the x-axis. Set NULL as default. +#'@param ytitle A string of title of the y-axis. Set NULL as default. +#'@param xlabels A vector of labels of the x-axis. The length must be +#' length of the column of parameter 'var'. Set the sequence from 1 to the +#' length of the column of parameter 'var' as default. +#'@param xvert A logical value to decide whether to place x-axis labels +#' vertically. Set FALSE as default, which keeps the labels horizontally. +#'@param ylabels A vector of labels of the y-axis The length must be +#' length of the row of parameter 'var'. Set the sequence from 1 to the +#' length of the row of parameter 'var' as default. +#'@param line An integer specifying the distance between the title of the +#' x-axis and the x-axis. Set 3 as default. Adjust if the x-axis labels +#' are long. +#'@param figure.width A positive number as a ratio adjusting the width of the +#' grids. Set 1 as default. +#'@param legend A logical value to decide to draw the grid color legend or not. +#' Set TRUE as default. +#'@param legend.width A number between 0 and 0.5 to adjust the legend width. +#' Set 0.15 as default. +#'@param fileout A string of full directory path and file name indicating where +#' to save the plot. If not specified (default), a graphics device will pop up. +#'@param size_units A string indicating the units of the size of the device +#' (file or window) to plot in. Set 'px' as default. See ?Devices and the +#' creator function of the corresponding device. +#'@param res A positive number indicating resolution of the device (file or window) +#' to plot in. See ?Devices and the creator function of the corresponding device. +#'@param ... The additional parameters to be passed to function ColorBar() in +#' s2dverification for color legend creation. +#'@return A figure in popup window by default, or saved to the specified path. #' #'@examples -#'#Example with random data (by default it is saved in the working directory, but the user can specify a different one): -#' -#' PlotMatrix(table = matrix(rnorm(n = 120, mean = 0.3), 10, 12), -#' colors = c('white','#fef0d9','#fdd49e','#fdbb84','#fc8d59','#e34a33','#b30000', '#7f0000'), -#' brks = c(-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1), -#' title = "Mean Absolute Error", xtitle = "Forecast time (month)", ytitle = "Start date", -#' xlabels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")) -#' +#'#Example with random data +#' PlotMatrix(var = matrix(rnorm(n = 120, mean = 0.3), 10, 12), +#' cols = c('white','#fef0d9','#fdd49e','#fdbb84','#fc8d59', +#' '#e34a33','#b30000', '#7f0000'), +#' brks = c(-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1), +#' toptitle = "Mean Absolute Error", +#' xtitle = "Forecast time (month)", ytitle = "Start date", +#' xlabels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", +#' "Aug", "Sep", "Oct", "Nov", "Dec")) +#'@importFrom grDevices dev.new dev.off dev.cur #'@export - -PlotMatrix <- function(table, colors, brks, title = NULL, title.color = "royalblue4", xtitle = NULL, ytitle = NULL, xlabels = NULL, - xvert = FALSE, ylabels = NULL, line = 3, figure.width = 1, legend = TRUE, legend.width = 0.15, file = NULL, ...){ +PlotMatrix <- function(var, brks = NULL, cols = NULL, + toptitle = NULL, title.color = "royalblue4", + xtitle = NULL, ytitle = NULL, xlabels = NULL, xvert = FALSE, + ylabels = NULL, line = 3, figure.width = 1, legend = TRUE, + legend.width = 0.15, fileout = NULL, + size_units = 'px', res = 100, ...) { # Check variables: - if (!is.matrix(table)) + if (!is.matrix(var)) stop("Input values are not a matrix") - if (!is.numeric(table)) + if (!is.numeric(var)) stop("Input values are not always numbers") - if (is.null(colors) || length(colors) < 2) - stop("You have to specify a color palette of at least 2 colors") - if (is.null(brks) || length(brks) < 2) - stop("You have to specify 2 or more intervals") - n.colors <- length(colors) ## number of colours + + # Build: brks, cols + colorbar <- ColorBar(brks = brks, cols = cols, vertical = FALSE, + plot = FALSE, ...) + brks <- colorbar$brks + cols <- colorbar$cols + + n.cols <- length(cols) ## number of colours n.brks <- length(brks) ## number of intervals - if (n.brks != n.colors + 1) + + if (n.brks != n.cols + 1) stop("There must be one break more than the number of colors") - n.cols <- ncol(table) ## number of columns of the image - n.rows <- nrow(table) ## number of rows of the image - if (n.cols < 2) + ncols <- ncol(var) ## number of columns of the image + nrows <- nrow(var) ## number of rows of the image + if (ncols < 2) stop("Matrix must have at least two columns") - if (n.rows < 2) + if (nrows < 2) stop("Matrix must have at least two rows") - if (!is.null(xlabels) && length(xlabels) != n.cols) - stop("The number of x labels must be equal to the number of columns of the data matrix") - if (!is.null(ylabels) && length(ylabels) != n.rows) - stop("The number of y labels must be equal to the number of rows of the data matrix") + if (!is.null(xlabels) && length(xlabels) != ncols) + stop(paste0("The number of x labels must be equal to the number of ", + "columns of the data matrix")) + if (!is.null(ylabels) && length(ylabels) != nrows) + stop(paste0("The number of y labels must be equal to the number of ", + "rows of the data matrix")) if (!is.numeric(figure.width) || figure.width < 0) stop("figure.width must be a positive number") if (!is.numeric(legend.width) || legend.width < 0 || legend.width > 0.5) stop("legend.width must be a number from 0 to 0.5") - - # Print output file: - if (is.null(file)) file.output <- paste0(getwd(), "/PlotMatrix.png") else file.output <- file - print(paste0("Saving grid image in: ", file.output)) - # Generate image: - png(file = file.output, width = 55 * n.cols * figure.width, height = 50 * n.rows) - plot.new() + # If there is any filenames to store the graphics, process them + # to select the right device + if (!is.null(fileout)) { + deviceInfo <- .SelectDevice(fileout = fileout, + width = 80 * ncols * figure.width, + height = 80 * nrows, + units = size_units, res = res) + saveToFile <- deviceInfo$fun + fileout <- deviceInfo$files + } + + # Open connection to graphical device + if (!is.null(fileout)) { + saveToFile(fileout) + } else if (names(dev.cur()) == 'null device') { + dev.new(units = size_units, res = res, + width = 8 * figure.width, height = 5) + } + + if (!is.null(fileout)) { + # Draw empty plot: - par(mar = c(4, 4, 1, 0), fig = c(0.1, 1 - legend.width, 0.1, 0.9), new = TRUE) - plot(1, 1, type = "n", xaxt = "n", yaxt = "n", ylim = c(0.5, n.rows + 0.5), xlim = c(-0.5, n.cols - 1 + 0.5), ann = F, bty = "n") + par(mar = c(4, 4, 1, 0), fig = c(0.1, 1 - legend.width, 0.1, 0.9)) + plot(1, 1, type = "n", xaxt = "n", yaxt = "n", ylim = c(0.5, nrows + 0.5), + xlim = c(-0.5, ncols - 1 + 0.5), ann = F, bty = "n") # Add axes titles: - label.size <- 1.2 * (max(n.cols, n.rows) / 10) ^ 0.5 - mtext(side = 1, text = xtitle, line = line, cex = label.size, font = 3) - mtext(side = 2, text = ytitle, line = 3, cex = label.size, font = 3) + label.size <- 1.2 * (max(ncols, nrows) / 10) ^ 0.5 + mtext(side = 1, text = xtitle, line = line, cex = label.size, font = 3) + mtext(side = 2, text = ytitle, line = 3, cex = label.size, font = 3) # Add plot title: - if (is.null(title.color)) title.color <- "royalblue4" - mtext(side = 3, text = title, cex = 1.75 * (n.rows / 10) ^ 0.7, col = title.color) + if (is.null(title.color)) title.color <- "royalblue4" + mtext(side = 3, text = toptitle, cex = 1.75 * (nrows / 10) ^ 0.7, + col = title.color) # Add axis labels: - axis.size <- (max(n.cols, n.rows) / 10) ^ 0.3 - if (is.null(xlabels)) xlabels = 1:n.cols - if (is.null(ylabels)) ylabels = 1:n.rows - axis(1, at = seq(0, n.cols-1), las = ifelse(xvert, 2, 1), labels = xlabels, cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (n.rows / 10 - 1)) ## Add x-axis labels - axis(2, at = seq(1, n.rows), las = 1, labels = rev(ylabels), cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - n.cols / 10) ## Add y-axis labels + axis.size <- (max(ncols, nrows) / 10) ^ 0.3 + if (is.null(xlabels)) xlabels = 1:ncols + if (is.null(ylabels)) ylabels = 1:nrows + axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, + cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) ## Add x-axis labels + axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), + cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) ## Add y-axis labels + + } else { + + # Draw empty plot: + par(mar = c(4, 4, 1, 0), fig = c(0.1, 1 - legend.width, 0.1, 0.9)) + plot(1, 1, type = "n", xaxt = "n", yaxt = "n", ylim = c(0.5, nrows + 0.5), + xlim = c(-0.5, ncols - 1 + 0.5), ann = F, bty = "n") + + # Add axes titles: + label.size <- 1.2 # * (max(ncols, nrows) / 10) ^ 0.5 + mtext(side = 1, text = xtitle, line = line, cex = label.size, font = 3) + mtext(side = 2, text = ytitle, line = 3, cex = label.size, font = 3) + + # Add plot title: + if (is.null(title.color)) title.color <- "royalblue4" + mtext(side = 3, text = toptitle, cex = 1.5, #* (nrows / 10) ^ 0.7, + col = title.color) + + # Add axis labels: + axis.size <- 1 #(max(ncols, nrows) / 10) ^ 0.3 + if (is.null(xlabels)) xlabels = 1:ncols + if (is.null(ylabels)) ylabels = 1:nrows + axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, + cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) ## Add x-axis labels + axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), + cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) ## Add y-axis labels + + } # Create an array of colors instead of numbers (it starts all gray): - array.colors <- array("gray", c(n.rows, n.cols)) - for (int in n.colors:1) array.colors[table <= brks[int + 1]] <- colors[int] + array.colors <- array("gray", c(nrows, ncols)) + for (int in n.cols:1) array.colors[var <= brks[int + 1]] <- cols[int] # fill with colors the cells in the figure: - for (p in 1:n.rows){ - for (l in 0:(n.cols - 1)){ + for (p in 1:nrows) { + for (l in 0:(ncols - 1)) { polygon(c(0.5 + l - 1, 0.5 + l - 1, 1.5 + l - 1, 1.5 + l - 1), - c(-0.5 + n.rows + 1 - p, 0.5 + n.rows + 1 - p, 0.5 + n.rows + 1 - p, -0.5 + n.rows + 1 - p), col = array.colors[p, 1 + l], border = "black") + c(-0.5 + nrows + 1 - p, 0.5 + nrows + 1 - p, + 0.5 + nrows + 1 - p, -0.5 + nrows + 1 - p), + col = array.colors[p, 1 + l], border = "black") } } # Draw color legend: - if (legend){ - par(fig = c(1 - legend.width - 0.01, 1 - legend.width + legend.width * min(1, 10 / n.cols), 0.3, 0.8), new=TRUE) - legend.label.size <- (max(n.cols, n.rows) / 10) ^ 0.4 - ColorBar(brks, cols = colors, vert = TRUE, label_scale = legend.label.size, subsample = 1, ...) + if (legend) { + par(fig = c(1 - legend.width - 0.01, + 1 - legend.width + legend.width * min(1, 10 / ncols), + 0.3, 0.8), new = TRUE) + #legend.label.size <- (max(ncols, nrows) / 10) ^ 0.4 + ColorBar(brks = brks, cols = cols, vertical = TRUE, ...) } - dev.off() + # If the graphic was saved to file, close the connection with the device + if (!is.null(fileout)) dev.off() + invisible(list(brks = brks, cols = cols)) + } - diff --git a/man/PlotMatrix.Rd b/man/PlotMatrix.Rd new file mode 100644 index 00000000..18d15c11 --- /dev/null +++ b/man/PlotMatrix.Rd @@ -0,0 +1,89 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PlotMatrix.R +\name{PlotMatrix} +\alias{PlotMatrix} +\title{Function to convert any numerical table to a grid of coloured squares.} +\usage{ +PlotMatrix(var, brks = NULL, cols = NULL, toptitle = NULL, + title.color = "royalblue4", xtitle = NULL, ytitle = NULL, + xlabels = NULL, xvert = FALSE, ylabels = NULL, line = 3, + figure.width = 1, legend = TRUE, legend.width = 0.15, fileout = NULL, + size_units = "px", res = 100, ...) +} +\arguments{ +\item{var}{A numerical matrix containing the values to be displayed in a +colored image.} + +\item{brks}{A vector of the color bar intervals. The length must be one more +than the parameter 'cols'. Use ColorBar() to generate default values.} + +\item{cols}{A vector of valid color identifiers for color bar. The length +must be one less than the parameter 'brks'. Use ColorBar() to generate +default values.} + +\item{toptitle}{A string of the title of the grid. Set NULL as default.} + +\item{title.color}{A string of valid color identifier to decide the title +color. Set "royalblue4" as default.} + +\item{xtitle}{A string of title of the x-axis. Set NULL as default.} + +\item{ytitle}{A string of title of the y-axis. Set NULL as default.} + +\item{xlabels}{A vector of labels of the x-axis. The length must be +length of the column of parameter 'var'. Set the sequence from 1 to the +length of the column of parameter 'var' as default.} + +\item{xvert}{A logical value to decide whether to place x-axis labels +vertically. Set FALSE as default, which keeps the labels horizontally.} + +\item{ylabels}{A vector of labels of the y-axis The length must be +length of the row of parameter 'var'. Set the sequence from 1 to the +length of the row of parameter 'var' as default.} + +\item{line}{An integer specifying the distance between the title of the +x-axis and the x-axis. Set 3 as default. Adjust if the x-axis labels +are long.} + +\item{figure.width}{A positive number as a ratio adjusting the width of the +grids. Set 1 as default.} + +\item{legend}{A logical value to decide to draw the grid color legend or not. +Set TRUE as default.} + +\item{legend.width}{A number between 0 and 0.5 to adjust the legend width. +Set 0.15 as default.} + +\item{fileout}{A string of full directory path and file name indicating where +to save the plot. If not specified (default), a graphics device will pop up.} + +\item{size_units}{A string indicating the units of the size of the device +(file or window) to plot in. Set 'px' as default. See ?Devices and the +creator function of the corresponding device.} + +\item{res}{A positive number indicating resolution of the device (file or window) +to plot in. See ?Devices and the creator function of the corresponding device.} + +\item{...}{The additional parameters to be passed to function ColorBar() in +s2dverification for color legend creation.} +} +\value{ +A figure in popup window by default, or saved to the specified path. +} +\description{ +This function converts a numerical data matrix into a coloured +grid. It is useful for a slide or article to present tabular results as +colors instead of numbers. +} +\examples{ +#Example with random data +PlotMatrix(var = matrix(rnorm(n = 120, mean = 0.3), 10, 12), + cols = c('white','#fef0d9','#fdd49e','#fdbb84','#fc8d59', + '#e34a33','#b30000', '#7f0000'), + brks = c(-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1), + toptitle = "Mean Absolute Error", + xtitle = "Forecast time (month)", ytitle = "Start date", + xlabels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec")) +} + -- GitLab From 58a7ee8b7de334b6aa5d3a04a5804ae7800e7b2e Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 3 Sep 2019 15:15:54 +0200 Subject: [PATCH 41/61] Correct bad documentation in Trend() --- R/Trend.R | 46 +++++++++++++++++++++++++--------------------- man/Trend.Rd | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/R/Trend.R b/R/Trend.R index 15ec7ebe..56819bb7 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -1,37 +1,41 @@ #'Computes the Trend of the Ensemble Mean #' #'Computes the trend along the forecast time of the ensemble mean by least -#'square fitting, and the associated error interval.\cr -#'Trend() also provides the time series of the detrended ensemble mean -#'forecasts.\cr -#'The confidence interval relies on a student-T distribution.\cr\cr -#'.Trend provides the same functionality but taking a matrix ensemble members +#'square fitting, and the associated error interval. The trend would be +#'provided in number of units per month or year. This function also returns the +#'time series of the detrended ensemble mean forecasts. The confidence interval +#'relies on a student-T distribution.\cr +#'.Trend() provides the same functionality but taking a matrix ensemble members #'as input (exp). #' -#'@param var Array of any number of dimensions up to 10. -#'@param exp M by N matrix of M forecasts from N ensemble members. -#'@param interval Number of months/years between 2 points along posTR -#' dimension.\cr -#' Default = 1.\cr -#' The trend would be provided in number of units per month or year. -#'@param siglev Confidence level for the computation of confidence interval. -#' 0.95 by default. -#'@param conf Whether to compute the confidence levels or not. TRUE by default. -#'@param posTR Position along which to compute the trend. +#'@param var An array of any number of dimensions up to 10. +#'@param exp An M by N matrix representing M forecasts from N ensemble members. +#'@param interval A number of months/years between 2 points along posTR +#' dimension. Set 1 as default. +#'@param siglev A numeric value indicating the confidence level for the +#' computation of confidence interval. Set 0.95 as default. +#'@param conf A logical value indicating whether to compute the confidence +#' levels or not. Set TRUE as default. +#'@param posTR An integer indicating the position along which to compute the +#' trend. #' #'@return #'\item{$trend}{ -#' The intercept and slope coefficients for the least squares fitting of the -#' trend. +#' An array with same dimensions as parameter 'var' except along the posTR +#' dimension, which is replaced by a length 4 (or length 2 if conf = FALSE) +#' dimension, corresponding to the lower limit of the confidence interval +#' (only present if conf = TRUE), the slope, the upper limit of the confidence +#' interval (only present if conf = TRUE), and the intercept. #'} -#'\item{$conf.int}{ -#' Corresponding to the limits of the \code{siglev}\% confidence interval -#' (only present if \code{conf = TRUE}) for the slope coefficient. -#'} #'\item{$detrended}{ #' Same dimensions as var with linearly detrended var along the posTR #' dimension. #'} +#'Only in .Trend: +#'\item{$conf.int}{ +#' Corresponding to the limits of the \code{siglev}\% confidence interval +#' (only present if \code{conf = TRUE}) for the slope coefficient. +#'} #' #'@keywords datagen #'@author History:\cr diff --git a/man/Trend.Rd b/man/Trend.Rd index da1fe956..e7035e3d 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -10,43 +10,47 @@ Trend(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) .Trend(exp, interval = 1, siglev = 0.95, conf = TRUE) } \arguments{ -\item{var}{Array of any number of dimensions up to 10.} +\item{var}{An array of any number of dimensions up to 10.} -\item{posTR}{Position along which to compute the trend.} +\item{posTR}{An integer indicating the position along which to compute the +trend.} -\item{interval}{Number of months/years between 2 points along posTR -dimension.\cr -Default = 1.\cr -The trend would be provided in number of units per month or year.} +\item{interval}{A number of months/years between 2 points along posTR +dimension. Set 1 as default.} -\item{siglev}{Confidence level for the computation of confidence interval. -0.95 by default.} +\item{siglev}{A numeric value indicating the confidence level for the +computation of confidence interval. Set 0.95 as default.} -\item{conf}{Whether to compute the confidence levels or not. TRUE by default.} +\item{conf}{A logical value indicating whether to compute the confidence +levels or not. Set TRUE as default.} -\item{exp}{M by N matrix of M forecasts from N ensemble members.} +\item{exp}{An M by N matrix representing M forecasts from N ensemble members.} } \value{ \item{$trend}{ - The intercept and slope coefficients for the least squares fitting of the - trend. + An array with same dimensions as parameter 'var' except along the posTR + dimension, which is replaced by a length 4 (or length 2 if conf = FALSE) + dimension, corresponding to the lower limit of the confidence interval + (only present if conf = TRUE), the slope, the upper limit of the confidence + interval (only present if conf = TRUE), and the intercept. } -\item{$conf.int}{ - Corresponding to the limits of the \code{siglev}\% confidence interval - (only present if \code{conf = TRUE}) for the slope coefficient. -} \item{$detrended}{ Same dimensions as var with linearly detrended var along the posTR dimension. } +Only in .Trend: +\item{$conf.int}{ + Corresponding to the limits of the \code{siglev}\% confidence interval + (only present if \code{conf = TRUE}) for the slope coefficient. +} } \description{ Computes the trend along the forecast time of the ensemble mean by least -square fitting, and the associated error interval.\cr -Trend() also provides the time series of the detrended ensemble mean -forecasts.\cr -The confidence interval relies on a student-T distribution.\cr\cr -.Trend provides the same functionality but taking a matrix ensemble members +square fitting, and the associated error interval. The trend would be +provided in number of units per month or year. This function also returns the +time series of the detrended ensemble mean forecasts. The confidence interval +relies on a student-T distribution.\cr +.Trend() provides the same functionality but taking a matrix ensemble members as input (exp). } \examples{ -- GitLab From 5d2d550c85db8965e790971e9284156b347a1fb8 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 3 Sep 2019 15:43:26 +0200 Subject: [PATCH 42/61] Revert "Merge branch 'develop-trend-doc' into 'master'" This reverts merge request !183 --- NAMESPACE | 1 - R/PlotMatrix.R | 201 ---------------------------------------------- R/Trend.R | 46 +++++------ man/PlotMatrix.Rd | 89 -------------------- man/Trend.Rd | 46 +++++------ 5 files changed, 42 insertions(+), 341 deletions(-) delete mode 100644 R/PlotMatrix.R delete mode 100644 man/PlotMatrix.Rd diff --git a/NAMESPACE b/NAMESPACE index 4e855789..3e35710e 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -56,7 +56,6 @@ export(PlotBoxWhisker) export(PlotClim) export(PlotEquiMap) export(PlotLayout) -export(PlotMatrix) export(PlotSection) export(PlotStereoMap) export(PlotVsLTime) diff --git a/R/PlotMatrix.R b/R/PlotMatrix.R deleted file mode 100644 index 32a40c99..00000000 --- a/R/PlotMatrix.R +++ /dev/null @@ -1,201 +0,0 @@ -#'Function to convert any numerical table to a grid of coloured squares. -#' -#'This function converts a numerical data matrix into a coloured -#'grid. It is useful for a slide or article to present tabular results as -#'colors instead of numbers. -#' -#'@param var A numerical matrix containing the values to be displayed in a -#' colored image. -#'@param brks A vector of the color bar intervals. The length must be one more -#' than the parameter 'cols'. Use ColorBar() to generate default values. -#'@param cols A vector of valid color identifiers for color bar. The length -#' must be one less than the parameter 'brks'. Use ColorBar() to generate -#' default values. -#'@param toptitle A string of the title of the grid. Set NULL as default. -#'@param title.color A string of valid color identifier to decide the title -#' color. Set "royalblue4" as default. -#'@param xtitle A string of title of the x-axis. Set NULL as default. -#'@param ytitle A string of title of the y-axis. Set NULL as default. -#'@param xlabels A vector of labels of the x-axis. The length must be -#' length of the column of parameter 'var'. Set the sequence from 1 to the -#' length of the column of parameter 'var' as default. -#'@param xvert A logical value to decide whether to place x-axis labels -#' vertically. Set FALSE as default, which keeps the labels horizontally. -#'@param ylabels A vector of labels of the y-axis The length must be -#' length of the row of parameter 'var'. Set the sequence from 1 to the -#' length of the row of parameter 'var' as default. -#'@param line An integer specifying the distance between the title of the -#' x-axis and the x-axis. Set 3 as default. Adjust if the x-axis labels -#' are long. -#'@param figure.width A positive number as a ratio adjusting the width of the -#' grids. Set 1 as default. -#'@param legend A logical value to decide to draw the grid color legend or not. -#' Set TRUE as default. -#'@param legend.width A number between 0 and 0.5 to adjust the legend width. -#' Set 0.15 as default. -#'@param fileout A string of full directory path and file name indicating where -#' to save the plot. If not specified (default), a graphics device will pop up. -#'@param size_units A string indicating the units of the size of the device -#' (file or window) to plot in. Set 'px' as default. See ?Devices and the -#' creator function of the corresponding device. -#'@param res A positive number indicating resolution of the device (file or window) -#' to plot in. See ?Devices and the creator function of the corresponding device. -#'@param ... The additional parameters to be passed to function ColorBar() in -#' s2dverification for color legend creation. -#'@return A figure in popup window by default, or saved to the specified path. -#' -#'@examples -#'#Example with random data -#' PlotMatrix(var = matrix(rnorm(n = 120, mean = 0.3), 10, 12), -#' cols = c('white','#fef0d9','#fdd49e','#fdbb84','#fc8d59', -#' '#e34a33','#b30000', '#7f0000'), -#' brks = c(-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1), -#' toptitle = "Mean Absolute Error", -#' xtitle = "Forecast time (month)", ytitle = "Start date", -#' xlabels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", -#' "Aug", "Sep", "Oct", "Nov", "Dec")) -#'@importFrom grDevices dev.new dev.off dev.cur -#'@export -PlotMatrix <- function(var, brks = NULL, cols = NULL, - toptitle = NULL, title.color = "royalblue4", - xtitle = NULL, ytitle = NULL, xlabels = NULL, xvert = FALSE, - ylabels = NULL, line = 3, figure.width = 1, legend = TRUE, - legend.width = 0.15, fileout = NULL, - size_units = 'px', res = 100, ...) { - - # Check variables: - if (!is.matrix(var)) - stop("Input values are not a matrix") - if (!is.numeric(var)) - stop("Input values are not always numbers") - - # Build: brks, cols - colorbar <- ColorBar(brks = brks, cols = cols, vertical = FALSE, - plot = FALSE, ...) - brks <- colorbar$brks - cols <- colorbar$cols - - n.cols <- length(cols) ## number of colours - n.brks <- length(brks) ## number of intervals - - if (n.brks != n.cols + 1) - stop("There must be one break more than the number of colors") - ncols <- ncol(var) ## number of columns of the image - nrows <- nrow(var) ## number of rows of the image - if (ncols < 2) - stop("Matrix must have at least two columns") - if (nrows < 2) - stop("Matrix must have at least two rows") - if (!is.null(xlabels) && length(xlabels) != ncols) - stop(paste0("The number of x labels must be equal to the number of ", - "columns of the data matrix")) - if (!is.null(ylabels) && length(ylabels) != nrows) - stop(paste0("The number of y labels must be equal to the number of ", - "rows of the data matrix")) - if (!is.numeric(figure.width) || figure.width < 0) - stop("figure.width must be a positive number") - if (!is.numeric(legend.width) || legend.width < 0 || legend.width > 0.5) - stop("legend.width must be a number from 0 to 0.5") - - - # If there is any filenames to store the graphics, process them - # to select the right device - if (!is.null(fileout)) { - deviceInfo <- .SelectDevice(fileout = fileout, - width = 80 * ncols * figure.width, - height = 80 * nrows, - units = size_units, res = res) - saveToFile <- deviceInfo$fun - fileout <- deviceInfo$files - } - - # Open connection to graphical device - if (!is.null(fileout)) { - saveToFile(fileout) - } else if (names(dev.cur()) == 'null device') { - dev.new(units = size_units, res = res, - width = 8 * figure.width, height = 5) - } - - if (!is.null(fileout)) { - - # Draw empty plot: - par(mar = c(4, 4, 1, 0), fig = c(0.1, 1 - legend.width, 0.1, 0.9)) - plot(1, 1, type = "n", xaxt = "n", yaxt = "n", ylim = c(0.5, nrows + 0.5), - xlim = c(-0.5, ncols - 1 + 0.5), ann = F, bty = "n") - - # Add axes titles: - label.size <- 1.2 * (max(ncols, nrows) / 10) ^ 0.5 - mtext(side = 1, text = xtitle, line = line, cex = label.size, font = 3) - mtext(side = 2, text = ytitle, line = 3, cex = label.size, font = 3) - - # Add plot title: - if (is.null(title.color)) title.color <- "royalblue4" - mtext(side = 3, text = toptitle, cex = 1.75 * (nrows / 10) ^ 0.7, - col = title.color) - - # Add axis labels: - axis.size <- (max(ncols, nrows) / 10) ^ 0.3 - if (is.null(xlabels)) xlabels = 1:ncols - if (is.null(ylabels)) ylabels = 1:nrows - axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, - cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) ## Add x-axis labels - axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), - cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) ## Add y-axis labels - - } else { - - # Draw empty plot: - par(mar = c(4, 4, 1, 0), fig = c(0.1, 1 - legend.width, 0.1, 0.9)) - plot(1, 1, type = "n", xaxt = "n", yaxt = "n", ylim = c(0.5, nrows + 0.5), - xlim = c(-0.5, ncols - 1 + 0.5), ann = F, bty = "n") - - # Add axes titles: - label.size <- 1.2 # * (max(ncols, nrows) / 10) ^ 0.5 - mtext(side = 1, text = xtitle, line = line, cex = label.size, font = 3) - mtext(side = 2, text = ytitle, line = 3, cex = label.size, font = 3) - - # Add plot title: - if (is.null(title.color)) title.color <- "royalblue4" - mtext(side = 3, text = toptitle, cex = 1.5, #* (nrows / 10) ^ 0.7, - col = title.color) - - # Add axis labels: - axis.size <- 1 #(max(ncols, nrows) / 10) ^ 0.3 - if (is.null(xlabels)) xlabels = 1:ncols - if (is.null(ylabels)) ylabels = 1:nrows - axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, - cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) ## Add x-axis labels - axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), - cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) ## Add y-axis labels - - } - - # Create an array of colors instead of numbers (it starts all gray): - array.colors <- array("gray", c(nrows, ncols)) - for (int in n.cols:1) array.colors[var <= brks[int + 1]] <- cols[int] - - # fill with colors the cells in the figure: - for (p in 1:nrows) { - for (l in 0:(ncols - 1)) { - polygon(c(0.5 + l - 1, 0.5 + l - 1, 1.5 + l - 1, 1.5 + l - 1), - c(-0.5 + nrows + 1 - p, 0.5 + nrows + 1 - p, - 0.5 + nrows + 1 - p, -0.5 + nrows + 1 - p), - col = array.colors[p, 1 + l], border = "black") - } - } - - # Draw color legend: - if (legend) { - par(fig = c(1 - legend.width - 0.01, - 1 - legend.width + legend.width * min(1, 10 / ncols), - 0.3, 0.8), new = TRUE) - #legend.label.size <- (max(ncols, nrows) / 10) ^ 0.4 - ColorBar(brks = brks, cols = cols, vertical = TRUE, ...) - } - - # If the graphic was saved to file, close the connection with the device - if (!is.null(fileout)) dev.off() - invisible(list(brks = brks, cols = cols)) - -} diff --git a/R/Trend.R b/R/Trend.R index 56819bb7..15ec7ebe 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -1,41 +1,37 @@ #'Computes the Trend of the Ensemble Mean #' #'Computes the trend along the forecast time of the ensemble mean by least -#'square fitting, and the associated error interval. The trend would be -#'provided in number of units per month or year. This function also returns the -#'time series of the detrended ensemble mean forecasts. The confidence interval -#'relies on a student-T distribution.\cr -#'.Trend() provides the same functionality but taking a matrix ensemble members +#'square fitting, and the associated error interval.\cr +#'Trend() also provides the time series of the detrended ensemble mean +#'forecasts.\cr +#'The confidence interval relies on a student-T distribution.\cr\cr +#'.Trend provides the same functionality but taking a matrix ensemble members #'as input (exp). #' -#'@param var An array of any number of dimensions up to 10. -#'@param exp An M by N matrix representing M forecasts from N ensemble members. -#'@param interval A number of months/years between 2 points along posTR -#' dimension. Set 1 as default. -#'@param siglev A numeric value indicating the confidence level for the -#' computation of confidence interval. Set 0.95 as default. -#'@param conf A logical value indicating whether to compute the confidence -#' levels or not. Set TRUE as default. -#'@param posTR An integer indicating the position along which to compute the -#' trend. +#'@param var Array of any number of dimensions up to 10. +#'@param exp M by N matrix of M forecasts from N ensemble members. +#'@param interval Number of months/years between 2 points along posTR +#' dimension.\cr +#' Default = 1.\cr +#' The trend would be provided in number of units per month or year. +#'@param siglev Confidence level for the computation of confidence interval. +#' 0.95 by default. +#'@param conf Whether to compute the confidence levels or not. TRUE by default. +#'@param posTR Position along which to compute the trend. #' #'@return #'\item{$trend}{ -#' An array with same dimensions as parameter 'var' except along the posTR -#' dimension, which is replaced by a length 4 (or length 2 if conf = FALSE) -#' dimension, corresponding to the lower limit of the confidence interval -#' (only present if conf = TRUE), the slope, the upper limit of the confidence -#' interval (only present if conf = TRUE), and the intercept. +#' The intercept and slope coefficients for the least squares fitting of the +#' trend. #'} -#'\item{$detrended}{ -#' Same dimensions as var with linearly detrended var along the posTR -#' dimension. -#'} -#'Only in .Trend: #'\item{$conf.int}{ #' Corresponding to the limits of the \code{siglev}\% confidence interval #' (only present if \code{conf = TRUE}) for the slope coefficient. #'} +#'\item{$detrended}{ +#' Same dimensions as var with linearly detrended var along the posTR +#' dimension. +#'} #' #'@keywords datagen #'@author History:\cr diff --git a/man/PlotMatrix.Rd b/man/PlotMatrix.Rd deleted file mode 100644 index 18d15c11..00000000 --- a/man/PlotMatrix.Rd +++ /dev/null @@ -1,89 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/PlotMatrix.R -\name{PlotMatrix} -\alias{PlotMatrix} -\title{Function to convert any numerical table to a grid of coloured squares.} -\usage{ -PlotMatrix(var, brks = NULL, cols = NULL, toptitle = NULL, - title.color = "royalblue4", xtitle = NULL, ytitle = NULL, - xlabels = NULL, xvert = FALSE, ylabels = NULL, line = 3, - figure.width = 1, legend = TRUE, legend.width = 0.15, fileout = NULL, - size_units = "px", res = 100, ...) -} -\arguments{ -\item{var}{A numerical matrix containing the values to be displayed in a -colored image.} - -\item{brks}{A vector of the color bar intervals. The length must be one more -than the parameter 'cols'. Use ColorBar() to generate default values.} - -\item{cols}{A vector of valid color identifiers for color bar. The length -must be one less than the parameter 'brks'. Use ColorBar() to generate -default values.} - -\item{toptitle}{A string of the title of the grid. Set NULL as default.} - -\item{title.color}{A string of valid color identifier to decide the title -color. Set "royalblue4" as default.} - -\item{xtitle}{A string of title of the x-axis. Set NULL as default.} - -\item{ytitle}{A string of title of the y-axis. Set NULL as default.} - -\item{xlabels}{A vector of labels of the x-axis. The length must be -length of the column of parameter 'var'. Set the sequence from 1 to the -length of the column of parameter 'var' as default.} - -\item{xvert}{A logical value to decide whether to place x-axis labels -vertically. Set FALSE as default, which keeps the labels horizontally.} - -\item{ylabels}{A vector of labels of the y-axis The length must be -length of the row of parameter 'var'. Set the sequence from 1 to the -length of the row of parameter 'var' as default.} - -\item{line}{An integer specifying the distance between the title of the -x-axis and the x-axis. Set 3 as default. Adjust if the x-axis labels -are long.} - -\item{figure.width}{A positive number as a ratio adjusting the width of the -grids. Set 1 as default.} - -\item{legend}{A logical value to decide to draw the grid color legend or not. -Set TRUE as default.} - -\item{legend.width}{A number between 0 and 0.5 to adjust the legend width. -Set 0.15 as default.} - -\item{fileout}{A string of full directory path and file name indicating where -to save the plot. If not specified (default), a graphics device will pop up.} - -\item{size_units}{A string indicating the units of the size of the device -(file or window) to plot in. Set 'px' as default. See ?Devices and the -creator function of the corresponding device.} - -\item{res}{A positive number indicating resolution of the device (file or window) -to plot in. See ?Devices and the creator function of the corresponding device.} - -\item{...}{The additional parameters to be passed to function ColorBar() in -s2dverification for color legend creation.} -} -\value{ -A figure in popup window by default, or saved to the specified path. -} -\description{ -This function converts a numerical data matrix into a coloured -grid. It is useful for a slide or article to present tabular results as -colors instead of numbers. -} -\examples{ -#Example with random data -PlotMatrix(var = matrix(rnorm(n = 120, mean = 0.3), 10, 12), - cols = c('white','#fef0d9','#fdd49e','#fdbb84','#fc8d59', - '#e34a33','#b30000', '#7f0000'), - brks = c(-1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 1), - toptitle = "Mean Absolute Error", - xtitle = "Forecast time (month)", ytitle = "Start date", - xlabels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", - "Aug", "Sep", "Oct", "Nov", "Dec")) -} - diff --git a/man/Trend.Rd b/man/Trend.Rd index e7035e3d..da1fe956 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -10,47 +10,43 @@ Trend(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) .Trend(exp, interval = 1, siglev = 0.95, conf = TRUE) } \arguments{ -\item{var}{An array of any number of dimensions up to 10.} +\item{var}{Array of any number of dimensions up to 10.} -\item{posTR}{An integer indicating the position along which to compute the -trend.} +\item{posTR}{Position along which to compute the trend.} -\item{interval}{A number of months/years between 2 points along posTR -dimension. Set 1 as default.} +\item{interval}{Number of months/years between 2 points along posTR +dimension.\cr +Default = 1.\cr +The trend would be provided in number of units per month or year.} -\item{siglev}{A numeric value indicating the confidence level for the -computation of confidence interval. Set 0.95 as default.} +\item{siglev}{Confidence level for the computation of confidence interval. +0.95 by default.} -\item{conf}{A logical value indicating whether to compute the confidence -levels or not. Set TRUE as default.} +\item{conf}{Whether to compute the confidence levels or not. TRUE by default.} -\item{exp}{An M by N matrix representing M forecasts from N ensemble members.} +\item{exp}{M by N matrix of M forecasts from N ensemble members.} } \value{ \item{$trend}{ - An array with same dimensions as parameter 'var' except along the posTR - dimension, which is replaced by a length 4 (or length 2 if conf = FALSE) - dimension, corresponding to the lower limit of the confidence interval - (only present if conf = TRUE), the slope, the upper limit of the confidence - interval (only present if conf = TRUE), and the intercept. + The intercept and slope coefficients for the least squares fitting of the + trend. } -\item{$detrended}{ - Same dimensions as var with linearly detrended var along the posTR - dimension. -} -Only in .Trend: \item{$conf.int}{ Corresponding to the limits of the \code{siglev}\% confidence interval (only present if \code{conf = TRUE}) for the slope coefficient. +} +\item{$detrended}{ + Same dimensions as var with linearly detrended var along the posTR + dimension. } } \description{ Computes the trend along the forecast time of the ensemble mean by least -square fitting, and the associated error interval. The trend would be -provided in number of units per month or year. This function also returns the -time series of the detrended ensemble mean forecasts. The confidence interval -relies on a student-T distribution.\cr -.Trend() provides the same functionality but taking a matrix ensemble members +square fitting, and the associated error interval.\cr +Trend() also provides the time series of the detrended ensemble mean +forecasts.\cr +The confidence interval relies on a student-T distribution.\cr\cr +.Trend provides the same functionality but taking a matrix ensemble members as input (exp). } \examples{ -- GitLab From d658814d49415c1d0ccc4262bb4c816b52cb6f62 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 3 Sep 2019 16:22:53 +0200 Subject: [PATCH 43/61] Correct Trend() documentation --- R/Trend.R | 20 ++++++++++++++++++++ man/Trend.Rd | 26 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/R/Trend.R b/R/Trend.R index 15ec7ebe..e66e135a 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -18,11 +18,26 @@ #' 0.95 by default. #'@param conf Whether to compute the confidence levels or not. TRUE by default. #'@param posTR Position along which to compute the trend. +#'@param var An array of any number of dimensions up to 10. +#'@param exp An M by N matrix representing M forecasts from N ensemble members. +#'@param interval A number of months/years between 2 points along posTR +#' dimension. Set 1 as default. +#'@param siglev A numeric value indicating the confidence level for the +#' computation of confidence interval. Set 0.95 as default. +#'@param conf A logical value indicating whether to compute the confidence +#' levels or not. Set TRUE as default. +#'@param posTR An integer indicating the position along which to compute the +#' trend. #' #'@return #'\item{$trend}{ #' The intercept and slope coefficients for the least squares fitting of the #' trend. +#' An array with same dimensions as parameter 'var' except along the posTR +#' dimension, which is replaced by a length 4 (or length 2 if conf = FALSE) +#' dimension, corresponding to the lower limit of the confidence interval +#' (only present if conf = TRUE), the slope, the upper limit of the confidence +#' interval (only present if conf = TRUE), and the intercept. #'} #'\item{$conf.int}{ #' Corresponding to the limits of the \code{siglev}\% confidence interval @@ -32,6 +47,11 @@ #' Same dimensions as var with linearly detrended var along the posTR #' dimension. #'} +#'Only in .Trend: +#'\item{$conf.int}{ +#' Corresponding to the limits of the \code{siglev}\% confidence interval +#' (only present if \code{conf = TRUE}) for the slope coefficient. +#'} #' #'@keywords datagen #'@author History:\cr diff --git a/man/Trend.Rd b/man/Trend.Rd index da1fe956..b8b1e5a2 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -25,11 +25,32 @@ The trend would be provided in number of units per month or year.} \item{conf}{Whether to compute the confidence levels or not. TRUE by default.} \item{exp}{M by N matrix of M forecasts from N ensemble members.} + +\item{var}{An array of any number of dimensions up to 10.} + +\item{exp}{An M by N matrix representing M forecasts from N ensemble members.} + +\item{interval}{A number of months/years between 2 points along posTR +dimension. Set 1 as default.} + +\item{siglev}{A numeric value indicating the confidence level for the +computation of confidence interval. Set 0.95 as default.} + +\item{conf}{A logical value indicating whether to compute the confidence +levels or not. Set TRUE as default.} + +\item{posTR}{An integer indicating the position along which to compute the +trend.} } \value{ \item{$trend}{ The intercept and slope coefficients for the least squares fitting of the trend. + An array with same dimensions as parameter 'var' except along the posTR + dimension, which is replaced by a length 4 (or length 2 if conf = FALSE) + dimension, corresponding to the lower limit of the confidence interval + (only present if conf = TRUE), the slope, the upper limit of the confidence + interval (only present if conf = TRUE), and the intercept. } \item{$conf.int}{ Corresponding to the limits of the \code{siglev}\% confidence interval @@ -39,6 +60,11 @@ The trend would be provided in number of units per month or year.} Same dimensions as var with linearly detrended var along the posTR dimension. } +Only in .Trend: +\item{$conf.int}{ + Corresponding to the limits of the \code{siglev}\% confidence interval + (only present if \code{conf = TRUE}) for the slope coefficient. +} } \description{ Computes the trend along the forecast time of the ensemble mean by least -- GitLab From 3a55dbec94a231c02a4131fb7173b0302be63957 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 3 Sep 2019 18:33:04 +0200 Subject: [PATCH 44/61] Correct Trend() documention --- R/Trend.R | 4 ---- man/Trend.Rd | 4 ---- 2 files changed, 8 deletions(-) diff --git a/R/Trend.R b/R/Trend.R index e66e135a..98a71bf3 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -39,10 +39,6 @@ #' (only present if conf = TRUE), the slope, the upper limit of the confidence #' interval (only present if conf = TRUE), and the intercept. #'} -#'\item{$conf.int}{ -#' Corresponding to the limits of the \code{siglev}\% confidence interval -#' (only present if \code{conf = TRUE}) for the slope coefficient. -#'} #'\item{$detrended}{ #' Same dimensions as var with linearly detrended var along the posTR #' dimension. diff --git a/man/Trend.Rd b/man/Trend.Rd index b8b1e5a2..4326a1e3 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -52,10 +52,6 @@ trend.} (only present if conf = TRUE), the slope, the upper limit of the confidence interval (only present if conf = TRUE), and the intercept. } -\item{$conf.int}{ - Corresponding to the limits of the \code{siglev}\% confidence interval - (only present if \code{conf = TRUE}) for the slope coefficient. -} \item{$detrended}{ Same dimensions as var with linearly detrended var along the posTR dimension. -- GitLab From e76c03c56b938f6b0b9f2147c099ccba2f744be0 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 12 Sep 2019 17:38:57 +0200 Subject: [PATCH 45/61] Correct Trend() parameter documentation. --- R/Trend.R | 16 +++------------- man/Trend.Rd | 22 +++------------------- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/R/Trend.R b/R/Trend.R index 98a71bf3..d8bfc601 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -8,26 +8,16 @@ #'.Trend provides the same functionality but taking a matrix ensemble members #'as input (exp). #' -#'@param var Array of any number of dimensions up to 10. -#'@param exp M by N matrix of M forecasts from N ensemble members. -#'@param interval Number of months/years between 2 points along posTR -#' dimension.\cr -#' Default = 1.\cr -#' The trend would be provided in number of units per month or year. -#'@param siglev Confidence level for the computation of confidence interval. -#' 0.95 by default. -#'@param conf Whether to compute the confidence levels or not. TRUE by default. -#'@param posTR Position along which to compute the trend. #'@param var An array of any number of dimensions up to 10. -#'@param exp An M by N matrix representing M forecasts from N ensemble members. +#'@param posTR An integer indicating the position along which to compute the +#' trend. #'@param interval A number of months/years between 2 points along posTR #' dimension. Set 1 as default. #'@param siglev A numeric value indicating the confidence level for the #' computation of confidence interval. Set 0.95 as default. #'@param conf A logical value indicating whether to compute the confidence #' levels or not. Set TRUE as default. -#'@param posTR An integer indicating the position along which to compute the -#' trend. +#'@param exp An M by N matrix representing M forecasts from N ensemble members. #' #'@return #'\item{$trend}{ diff --git a/man/Trend.Rd b/man/Trend.Rd index 4326a1e3..71d2e1be 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -10,25 +10,10 @@ Trend(var, posTR = 2, interval = 1, siglev = 0.95, conf = TRUE) .Trend(exp, interval = 1, siglev = 0.95, conf = TRUE) } \arguments{ -\item{var}{Array of any number of dimensions up to 10.} - -\item{posTR}{Position along which to compute the trend.} - -\item{interval}{Number of months/years between 2 points along posTR -dimension.\cr -Default = 1.\cr -The trend would be provided in number of units per month or year.} - -\item{siglev}{Confidence level for the computation of confidence interval. -0.95 by default.} - -\item{conf}{Whether to compute the confidence levels or not. TRUE by default.} - -\item{exp}{M by N matrix of M forecasts from N ensemble members.} - \item{var}{An array of any number of dimensions up to 10.} -\item{exp}{An M by N matrix representing M forecasts from N ensemble members.} +\item{posTR}{An integer indicating the position along which to compute the +trend.} \item{interval}{A number of months/years between 2 points along posTR dimension. Set 1 as default.} @@ -39,8 +24,7 @@ computation of confidence interval. Set 0.95 as default.} \item{conf}{A logical value indicating whether to compute the confidence levels or not. Set TRUE as default.} -\item{posTR}{An integer indicating the position along which to compute the -trend.} +\item{exp}{An M by N matrix representing M forecasts from N ensemble members.} } \value{ \item{$trend}{ -- GitLab From 0857be04c1630373ed502a7cb8ff687d465a9232 Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 26 Sep 2019 16:05:06 +0200 Subject: [PATCH 46/61] Modification for review --- R/PlotMatrix.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PlotMatrix.R b/R/PlotMatrix.R index 32a40c99..748a06ae 100644 --- a/R/PlotMatrix.R +++ b/R/PlotMatrix.R @@ -101,7 +101,7 @@ PlotMatrix <- function(var, brks = NULL, cols = NULL, # If there is any filenames to store the graphics, process them # to select the right device if (!is.null(fileout)) { - deviceInfo <- .SelectDevice(fileout = fileout, + deviceInfo <- s2dverification:::.SelectDevice(fileout = fileout, width = 80 * ncols * figure.width, height = 80 * nrows, units = size_units, res = res) -- GitLab From 81ab4f0422b3e6c0c82286307bbe2b4df3899ece Mon Sep 17 00:00:00 2001 From: ncortesi Date: Fri, 27 Sep 2019 11:51:53 +0200 Subject: [PATCH 47/61] Added two new arguments: xlab_dist and ylab_dist --- man/PlotMatrix.Rd | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/man/PlotMatrix.Rd b/man/PlotMatrix.Rd index 18d15c11..3ab1a85d 100644 --- a/man/PlotMatrix.Rd +++ b/man/PlotMatrix.Rd @@ -8,7 +8,7 @@ PlotMatrix(var, brks = NULL, cols = NULL, toptitle = NULL, title.color = "royalblue4", xtitle = NULL, ytitle = NULL, xlabels = NULL, xvert = FALSE, ylabels = NULL, line = 3, figure.width = 1, legend = TRUE, legend.width = 0.15, fileout = NULL, - size_units = "px", res = 100, ...) + size_units = "px", res = 100, xlab_dist = NULL, ylab_dist = NULL, ...) } \arguments{ \item{var}{A numerical matrix containing the values to be displayed in a @@ -64,6 +64,10 @@ creator function of the corresponding device.} \item{res}{A positive number indicating resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device.} +\item{xlab_dist}{A number specifying the distance between the x labels and the x axis.} + +\item{ylab_dist}{A number specifying the distance between the y labels and the y axis.} + \item{...}{The additional parameters to be passed to function ColorBar() in s2dverification for color legend creation.} } -- GitLab From 679aa5d1ca74b632adafdae8c31b46ea1875ce8c Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 30 Sep 2019 16:18:14 +0200 Subject: [PATCH 49/61] Add parameter 'xlab_dist' and 'ylab_dist' to PlotMatrix() --- R/PlotMatrix.R | 46 ++++++++++++++++++++++++++++++++++++---------- man/PlotMatrix.Rd | 15 +++++++++------ 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/R/PlotMatrix.R b/R/PlotMatrix.R index 748a06ae..c6395fc6 100644 --- a/R/PlotMatrix.R +++ b/R/PlotMatrix.R @@ -33,6 +33,10 @@ #' Set TRUE as default. #'@param legend.width A number between 0 and 0.5 to adjust the legend width. #' Set 0.15 as default. +#'@param xlab_dist A number specifying the distance between the x labels and +#' the x axis. If not specified, it equals to -1 - (nrow(var) / 10 - 1). +#'@param ylab_dist A number specifying the distance between the y labels and +#' the y axis. If not specified, it equals to 0.5 - ncol(var) / 10. #'@param fileout A string of full directory path and file name indicating where #' to save the plot. If not specified (default), a graphics device will pop up. #'@param size_units A string indicating the units of the size of the device @@ -60,8 +64,8 @@ PlotMatrix <- function(var, brks = NULL, cols = NULL, toptitle = NULL, title.color = "royalblue4", xtitle = NULL, ytitle = NULL, xlabels = NULL, xvert = FALSE, ylabels = NULL, line = 3, figure.width = 1, legend = TRUE, - legend.width = 0.15, fileout = NULL, - size_units = 'px', res = 100, ...) { + legend.width = 0.15, xlab_dist = NULL, ylab_dist = NULL, + fileout = NULL, size_units = 'px', res = 100, ...) { # Check variables: if (!is.matrix(var)) @@ -138,10 +142,21 @@ PlotMatrix <- function(var, brks = NULL, cols = NULL, axis.size <- (max(ncols, nrows) / 10) ^ 0.3 if (is.null(xlabels)) xlabels = 1:ncols if (is.null(ylabels)) ylabels = 1:nrows - axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, - cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) ## Add x-axis labels - axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), - cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) ## Add y-axis labels + + if(is.null(xlab_dist)) { ## Add x axis labels + axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, + cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) + } else { + axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, + cex.axis = axis.size, tck = 0, lwd = 0, line = xlab_dist) + } + if(is.null(ylab_dist)) { ## Add y axis labels + axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), + cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) + } else { + axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), + cex.axis = axis.size, tck = 0, lwd = 0, line = ylab_dist) + } } else { @@ -164,10 +179,21 @@ PlotMatrix <- function(var, brks = NULL, cols = NULL, axis.size <- 1 #(max(ncols, nrows) / 10) ^ 0.3 if (is.null(xlabels)) xlabels = 1:ncols if (is.null(ylabels)) ylabels = 1:nrows - axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, - cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) ## Add x-axis labels - axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), - cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) ## Add y-axis labels + + if(is.null(xlab_dist)){ ## Add x axis labels + axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, + cex.axis = axis.size, tck = 0, lwd = 0, line = - 1 - (nrows / 10 - 1)) + } else { + axis(1, at = seq(0, ncols - 1), las = ifelse(xvert, 2, 1), labels = xlabels, + cex.axis = axis.size, tck = 0, lwd = 0, line = xlab_dist) + } + if(is.null(ylab_dist)){ ## Add y axis labels + axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), + cex.axis = axis.size, tck = 0, lwd = 0, line = 0.5 - ncols / 10) + } else { + axis(2, at = seq(1, nrows), las = 1, labels = rev(ylabels), + cex.axis = axis.size, tck = 0, lwd = 0, line = ylab_dist) + } } diff --git a/man/PlotMatrix.Rd b/man/PlotMatrix.Rd index 3ab1a85d..70c1211e 100644 --- a/man/PlotMatrix.Rd +++ b/man/PlotMatrix.Rd @@ -7,8 +7,9 @@ PlotMatrix(var, brks = NULL, cols = NULL, toptitle = NULL, title.color = "royalblue4", xtitle = NULL, ytitle = NULL, xlabels = NULL, xvert = FALSE, ylabels = NULL, line = 3, - figure.width = 1, legend = TRUE, legend.width = 0.15, fileout = NULL, - size_units = "px", res = 100, xlab_dist = NULL, ylab_dist = NULL, ...) + figure.width = 1, legend = TRUE, legend.width = 0.15, + xlab_dist = NULL, ylab_dist = NULL, fileout = NULL, size_units = "px", + res = 100, ...) } \arguments{ \item{var}{A numerical matrix containing the values to be displayed in a @@ -54,6 +55,12 @@ Set TRUE as default.} \item{legend.width}{A number between 0 and 0.5 to adjust the legend width. Set 0.15 as default.} +\item{xlab_dist}{A number specifying the distance between the x labels and +the x axis. If not specified, it equals to -1 - (nrow(var) / 10 - 1).} + +\item{ylab_dist}{A number specifying the distance between the y labels and +the y axis. If not specified, it equals to 0.5 - ncol(var) / 10.} + \item{fileout}{A string of full directory path and file name indicating where to save the plot. If not specified (default), a graphics device will pop up.} @@ -64,10 +71,6 @@ creator function of the corresponding device.} \item{res}{A positive number indicating resolution of the device (file or window) to plot in. See ?Devices and the creator function of the corresponding device.} -\item{xlab_dist}{A number specifying the distance between the x labels and the x axis.} - -\item{ylab_dist}{A number specifying the distance between the y labels and the y axis.} - \item{...}{The additional parameters to be passed to function ColorBar() in s2dverification for color legend creation.} } -- GitLab From ee1cbfb6649d5f2d44ddc776ee3f4da42f8495d8 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 30 Sep 2019 16:37:08 +0200 Subject: [PATCH 50/61] Add PlotMatrix to NAMESPACE --- NAMESPACE | 1 + 1 file changed, 1 insertion(+) diff --git a/NAMESPACE b/NAMESPACE index 3e35710e..4e855789 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -56,6 +56,7 @@ export(PlotBoxWhisker) export(PlotClim) export(PlotEquiMap) export(PlotLayout) +export(PlotMatrix) export(PlotSection) export(PlotStereoMap) export(PlotVsLTime) -- GitLab From 85a7003c7e0489370d2305e71b3c43d77aa67ced Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 1 Oct 2019 11:01:40 +0200 Subject: [PATCH 51/61] Update NEWS.md --- NEWS.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 51b198b1..21dc20e7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ -# s2dverification 2.9.0 (Release date: ) -- Apply Roxygen2 to all the files. (2019.07.31) (An-Chi) +# s2dverification 2.8.6 (Release date: ) +- Apply Roxygen2 format to all the files. +- Bug fix in Composite(). +- Bug fix in Ano(). Recommend to assign the dimensions by name to avoid confusion when the dimensions have same length. +- Trend() documentation error fix. +- Introduce new function PlotMatrix(). -- GitLab From 03f069dbad25631911be61969db8720ab42e0d05 Mon Sep 17 00:00:00 2001 From: aho Date: Tue, 1 Oct 2019 12:45:58 +0200 Subject: [PATCH 52/61] Update NEWS.md --- NEWS.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/NEWS.md b/NEWS.md index 21dc20e7..6d81252d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,3 +5,136 @@ - Trend() documentation error fix. - Introduce new function PlotMatrix(). +# s2dverification 2.8.0 (Release date: 2017-02-13) +- Change licence from GPL-3 to LGPL-3. +- New veriApply compatible score functions (.BrierScore, .Corr, .RMS, .RMSSS, .RatioRMS, .RatioSDRMS and .Trend). +- New function CDORemap to interpolate R arrays with CDO. +- New function ArrayToNetCDF to save R arrays with metadata in NetCDF files. +- Enhance plot_timeseries.R and plot_maps.R example scripts to work with file-per-chunk data, for auto-ecearth v3.2.1a. +- Add colour-blind colour bars for the map plots. +- Add warning in Load when extrapolating data. +- Bug fix in ProbBins when called with cross-validation. +- Enhance documentation. +- Adapt UltimateBrier to SpecsVerification 0.5-0. +- Enhancements to adjust size and resolution in plotting functions. +- Solve PlotEquiMap bug when values equal to the lower limit. +- Bug fix in Ano. +- Bug fix in PlotVsLTime. +- Small update in the configuration file. + +# s2dverification 2.7.0 (Release date: 2016-08-24) +Enhanced PlotEquiMap() and PlotStereoMap() with lots of new options and fixed issues: +- Colour bar with triangle ends and lots of new features. +- Margins, labels, ticks, colour bar, titles now arranged properly. +- Now possibile to adjust colour and border of continents, size, colour and type of contour lines, size of labels, ticks and margins, colour and width of boxes, etc. +- Draw multiple superimposed dot/symbol layers. +- Draw boxes in PlotStereoMap(). +- PlotStereoMap() with bounding circle. +- Add function PlotLayout() to automatically generate complex figure layouts and populate with plots from multi-dimensional arrays. +- Fix and updated corrupted example scripts (required for new auto-ecearth releases to work). +- Add function Subset() to easily take chunks of data arrays. +- Fix bug in Load() under some particular configurations. +- Enhance margins in PlotAno(). +- Update sample data to be together with metadata as provided by Load(). +- Update and fix in the BSC Load() configuration file. + +# s2dverification 2.6.0 (Release date: 2016-06-06) +- Update configuration file. +- Functions to compute variability modes and project data on EOF() and ProjectField(). +- Function to compute co·variability modes: SVD(), by Javi. +- Function to compute the NAO: NAO(), by Fabian, Virginie, Lauriane, Martin. +- Brier score/skill score accounting for small ensemble/start date sample size: UltimateBrier(). +- K-means spatial clustering: Cluster(). +- Synthetic data generator: ToyModel(). +- Tropical cyclone downscaling: StatSeasAtlHurr(). +- Function to composite fields: Composite(). +- Function to generate map animations: AnimateMap(). +- Function to plot time series with box-and-whisker plots: PlotBoxWhisker(). +- Possible to disable computation of confidence intervals or p-values in ACC(), Corr(), RatioRMS(), RatioSDRMS(), RMS(), RMSSS(), Spread() and Trend(). +- Possible to adjust confidence level in all functions that provide confidence intervals: ACC(), Corr(), RMS(), Spread() and Trend(). +- Possible to plot arrows in PlotEquiMap(). +- Possible to save plots in multiple formats, to file or onscreen from all plot functions. +- Objects returned by Load() are now closer to the format in downscaleR. The initial and end date of each time step is provided now. +- Enhancements in Smoothing(). +- Load() now stops if the tag $START_DATE$/$YEAR$+$MONTH$+$DAY$ is not in the path pattern of any of the experiments. + +# s2dverification 2.5.0 (Release date: 2016-01-04) +- Fix bugs when using masks in Load() +- Able to specify masks with paths to NetCDF files + +# s2dverification 2.4.7 (Release date: 2015-11-15) +- Update plot_timeseries.R to new paths and to 'ncdf4'. +- Improve performance when retrieving subsets of data (regions of earth or time periods). +- Add possibility to use Load() without a configuration file. See details on parameters 'exp' and 'obs' in ?Load + +Load() now returns plenty of metadata. Highlighted: +- Paths to all loaded files +- Paths to not found files +- Stamp with all the provided parameters to exactly reproduce any Load() call +- The name of the common grid (if any), following CDO's naming conventions + +Other enhancements in Load(): +- Enhance error handling and error messages +- Add “progress bar” +- Detect automatically grid of the files. No need to specify it +- Detect automatically if the requested variable is 2-dimensional or global mean. No need to specify it +- Possibility to load observations only, from a limited period of time only +- Possibility to load NetCDF files with disordered dimensions +- Remove system dependency of 's2dverification' to NCO and some GNU tools +- Simplify configuration file: removed lists of variables and reduced from 5 tables to 2, one for experimental datasets and one for observational datasets. You can convert old configuration files to the new format with the script in /shared/earth/software/scripts/convertConfig.R as follows: /shared/earth/software/scripts/convertConfig.R /path/to/configfile.conf +- Fix and updated the sample script plot_timeseries.R +- Fix wrong entries in BSC configuration file for some ice variables. + +# s2dverification 2.4.0 (Release date: 2015-07-27) +- Option to draw rectangles in PlotEquiMap() +- Motification of Corr() to accomodate ranked correlation +- Add the possibility to load the second set of HadCM3 decadal data (i3p1) +- Add functions to assist in manipulating the configuration file +- Improve examples that use extremely reduced experimental and observational datasets +- Uniformize documentation style +- Add possibility to configure dimension names to look for inside NetCDF files +- Add the possibility to load ESA observations from SMHI +- Fix bug that happened in some cases when a common grid is not specified + +# s2dverification 2.3.2 (Release date: 2015-04-23) +- New CRPS() function to compute the continuous ranked probability score for ensemble forecasts. +- New ProbBins() function to compute probabilistic information of a forecast relative to a threshold or a quantile. +- Load() stops and warns if the masks provided are not in the correct grid. +- Load() didn't apply, as expected, the same masks in observations as in experiments when possible. Now fixed. +- Enhancement in Clim() documentation. +- Enhancements in Load() and configuration file documentation. +- HadSLP dataset is now loadable + +# s2dverification 2.3.1 (Release date: 2015-03-09) +- Loading observations only fixed +- Loading only one leadtime fixed +- Loading a 2D variable when the first observation was not stored in file-per-dataset format fixed +- Parameter 'ncores' changed to 'nprocs' +- Improvements in configuration file mechanism and documentation + +# s2dverification 2.3.0 (Release date: 2015-03-02) +- Configuration file mechanism to specify new dataset or variable paths, grids, etc. +- New parameters in Load() to specify maximum and minimum values. +- New supported dataset formats. See '?Load' in R after loadings2dverificationfor more information. +- More efficient memory usage in Load() and usage of multiple parallel processes (faster). +- NetCDF4 + OPeNDAP support + +# s2dverification 2.2.0 (Release date: 2014-12-16) +- ACC provides confidence intervals obtained with bootstrap method +- Function to plot ACC score +- Function to plot variables on a polar stereographic projection +- Possibility of loading observations only +- Possibility to load more ice variables +- Adjustable significance level in the Corr function +- Adjustable number size in ColorBar + +# s2dverification 2.1.0 (Release date: 2014-01-23) +- Demo scripts 'plot_timeseries.R' and 'plot_maps.R' available in the 'inst/doc' directory in thes2dverificationrepository. +- Documentation on how to specify the grids and masks to the function Load() has been added to its help page, code and package manual. + +# s2dverification 2.0.0 (Release date: 2013-08-02) +- Use of the standard R package structure. +- Use of the google's R style guide. +- Functions that involved RClim set of funcions have been kept apartfrom the package (AnimVsLTime, BlueRed, PlotMap, ProjMap) as well as the authors. +- New functions have been added: Alpha, EnoNew, Filter, FitAcfCoef, FitAutocor, GenSeries, Spectrum. +- Extended help. -- GitLab From ef34ec752bab610d871a47f864250dbe4b0721e5 Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 2 Oct 2019 10:58:01 +0200 Subject: [PATCH 53/61] Bumped version to v2.8.6 and fixes for CRAN. --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 78935b85..0045265c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: s2dverification Title: Set of Common Tools for Forecast Verification -Version: 2.8.5 +Version: 2.8.6 Authors@R: c( person("BSC-CNS", role = c("aut", "cph")), person("Virginie", "Guemas", , "virginie.guemas@bsc.es", role = "aut"), -- GitLab From 29964804a24d00d5c56ce3a35ddeb53200868930 Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 2 Oct 2019 11:17:33 +0200 Subject: [PATCH 54/61] Hotfix for PlotMatrix.R --- R/PlotMatrix.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/PlotMatrix.R b/R/PlotMatrix.R index c6395fc6..8c830d74 100644 --- a/R/PlotMatrix.R +++ b/R/PlotMatrix.R @@ -105,7 +105,7 @@ PlotMatrix <- function(var, brks = NULL, cols = NULL, # If there is any filenames to store the graphics, process them # to select the right device if (!is.null(fileout)) { - deviceInfo <- s2dverification:::.SelectDevice(fileout = fileout, + deviceInfo <- .SelectDevice(fileout = fileout, width = 80 * ncols * figure.width, height = 80 * nrows, units = size_units, res = res) -- GitLab From e57ebdaa770e64f5d626b72d86ef496a6e1cf35a Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 2 Oct 2019 13:34:57 +0200 Subject: [PATCH 55/61] Hotfix .Rbuildignore for CRAN --- .Rbuildignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.Rbuildignore b/.Rbuildignore index aa8227b1..985172c4 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -9,3 +9,4 @@ README\.md$ \..*\.RData$ vignettes .gitlab-ci.yml +^inst$ -- GitLab From 790829ee297015b211407473486bb1f8f28c3d74 Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 7 Oct 2019 12:10:56 +0200 Subject: [PATCH 56/61] fix for Debian problem --- .Rbuildignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.Rbuildignore b/.Rbuildignore index 985172c4..7559a09b 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -9,4 +9,4 @@ README\.md$ \..*\.RData$ vignettes .gitlab-ci.yml -^inst$ +^inst/doc$ -- GitLab From 31ca281d5019e675e23304815ea80d92e9a7a57d Mon Sep 17 00:00:00 2001 From: aho Date: Mon, 7 Oct 2019 13:29:17 +0200 Subject: [PATCH 57/61] Fix for CRAN --- .Rbuildignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.Rbuildignore b/.Rbuildignore index 7559a09b..aa8227b1 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -9,4 +9,3 @@ README\.md$ \..*\.RData$ vignettes .gitlab-ci.yml -^inst/doc$ -- GitLab From 1c5a7b053f66ef53e6474fb473d6a885b2b81b12 Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 16 Oct 2019 15:06:23 +0200 Subject: [PATCH 58/61] TRY to fix for CRAN Debian --- R/AnimateMap.R | 2 ++ R/Ano_CrossValid.R | 2 ++ R/Clim.R | 2 ++ R/Consist_Trend.R | 2 ++ R/Corr.R | 2 ++ R/Filter.R | 2 ++ R/Histo2Hindcast.R | 2 ++ R/Plot2VarsVsLTime.R | 2 ++ R/PlotACC.R | 2 ++ R/PlotAno.R | 2 ++ R/PlotBoxWhisker.R | 2 ++ R/PlotVsLTime.R | 2 ++ R/RMS.R | 2 ++ R/RMSSS.R | 2 ++ R/RatioSDRMS.R | 2 ++ R/Season.R | 2 ++ R/Smoothing.R | 2 ++ R/Spread.R | 2 ++ R/ToyModel.R | 4 +++- R/Trend.R | 2 ++ man/AnimateMap.Rd | 2 ++ man/Ano_CrossValid.Rd | 2 ++ man/Clim.Rd | 2 ++ man/Consist_Trend.Rd | 2 ++ man/Corr.Rd | 2 ++ man/Filter.Rd | 2 ++ man/Histo2Hindcast.Rd | 2 ++ man/Plot2VarsVsLTime.Rd | 2 ++ man/PlotACC.Rd | 2 ++ man/PlotAno.Rd | 2 ++ man/PlotBoxWhisker.Rd | 2 ++ man/PlotVsLTime.Rd | 2 ++ man/RMS.Rd | 2 ++ man/RMSSS.Rd | 2 ++ man/RatioSDRMS.Rd | 2 ++ man/Season.Rd | 2 ++ man/Smoothing.Rd | 2 ++ man/Spread.Rd | 2 ++ man/ToyModel.Rd | 4 +++- man/Trend.Rd | 2 ++ 40 files changed, 82 insertions(+), 2 deletions(-) diff --git a/R/AnimateMap.R b/R/AnimateMap.R index 0f4d4b38..83667d2a 100644 --- a/R/AnimateMap.R +++ b/R/AnimateMap.R @@ -148,11 +148,13 @@ #'dim_to_mean <- 2 # Mean along members #'rms <- RMS(Mean1Dim(season_means_mod, dim_to_mean), #' Mean1Dim(season_means_obs, dim_to_mean)) +#' \donttest{ #'AnimateMap(rms, sampleData$lon, sampleData$lat, toptitle = #' "RMSE decadal prediction", sizetit = 1, units = "degree", #' monini = 1, freq = 1, msk95lev = FALSE, brks = seq(0, 0.8, 0.08), #' intlon = 10, intlat = 10, filled.continents = TRUE, #' fileout = 'rmse_dec.gif') +#' } #'@importFrom grDevices postscript dev.off #'@export AnimateMap <- function(var, lon, lat, toptitle = rep("", 11), sizetit = 1, diff --git a/R/Ano_CrossValid.R b/R/Ano_CrossValid.R index e42941f2..954a0814 100644 --- a/R/Ano_CrossValid.R +++ b/R/Ano_CrossValid.R @@ -26,9 +26,11 @@ #'# Load sample data as in Load() example: #'example(Load) #'anomalies <- Ano_CrossValid(sampleData$mod, sampleData$obs) +#' \donttest{ #'PlotAno(anomalies$ano_exp, anomalies$ano_obs, startDates, #' toptitle = paste('anomalies'), ytitle = c('K', 'K', 'K'), #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano_crossvalid.eps') +#' } #'@export Ano_CrossValid <- function(var_exp, var_obs, memb = TRUE) { # diff --git a/R/Clim.R b/R/Clim.R index 8a390ad4..8445e462 100644 --- a/R/Clim.R +++ b/R/Clim.R @@ -41,10 +41,12 @@ #'# Load sample data as in Load() example: #'example(Load) #'clim <- Clim(sampleData$mod, sampleData$obs) +#' \donttest{ #'PlotClim(clim$clim_exp, clim$clim_obs, #' toptitle = paste('sea surface temperature climatologies'), #' ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') +#' } #'@export Clim <- function(var_exp, var_obs, memb = TRUE, kharin = FALSE, NDV = FALSE) { # diff --git a/R/Consist_Trend.R b/R/Consist_Trend.R index 827440fc..2a82fd9c 100644 --- a/R/Consist_Trend.R +++ b/R/Consist_Trend.R @@ -57,6 +57,7 @@ #' Mean1Dim(smooth_ano_obs, dim_to_mean), #' years_between_startdates) #' +#' \donttest{ #'PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K/(5 years)", #' monini = 11, limits = c(-0.8, 0.8), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = c(0), @@ -64,6 +65,7 @@ #'PlotAno(InsertDim(trend$detrendedmod,2,1), InsertDim(trend$detrendedobs,2,1), #' startDates, "Detrended tos anomalies", ytitle = 'K', #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_ano.eps') +#' } #' #'@export Consist_Trend <- function(var_exp, var_obs, interval = 1) { diff --git a/R/Corr.R b/R/Corr.R index 18ae9b14..41900230 100644 --- a/R/Corr.R +++ b/R/Corr.R @@ -86,10 +86,12 @@ #' compROW = required_complete_row, #' limits = c(ceiling((runmean_months + 1) / 2), #' leadtimes_per_startdate - floor(runmean_months / 2))) +#' \donttest{ #'PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", #' monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), #' fileout = 'tos_cor.eps') +#' } #' #'# The following example uses veriApply combined with .Corr instead of Corr #' \dontrun{ diff --git a/R/Filter.R b/R/Filter.R index 42c847f9..28a89dd2 100644 --- a/R/Filter.R +++ b/R/Filter.R @@ -30,9 +30,11 @@ #' } #' } #'} +#' \donttest{ #'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = #' 'filtered_ensemble_mean.eps') #' +#' } #'@importFrom stats lm #'@export Filter <- function(xdata, freq) { diff --git a/R/Histo2Hindcast.R b/R/Histo2Hindcast.R index cb93ae86..7693319c 100644 --- a/R/Histo2Hindcast.R +++ b/R/Histo2Hindcast.R @@ -58,9 +58,11 @@ #' start_dates_out, leadtimes_per_startdate) #'observational_data <- Histo2Hindcast(sampleData$obs, startDates[1], #' start_dates_out, leadtimes_per_startdate) +#' \donttest{ #'PlotAno(experimental_data, observational_data, start_dates_out, #' toptitle = paste('anomalies reorganized into shorter chunks'), #' ytitle = 'K', fileout='tos_histo2hindcast.eps') +#' } #' #'@export Histo2Hindcast <- function(varin, sdatesin, sdatesout, nleadtimesout) { diff --git a/R/Plot2VarsVsLTime.R b/R/Plot2VarsVsLTime.R index c5d5abcf..1e2fc6d9 100644 --- a/R/Plot2VarsVsLTime.R +++ b/R/Plot2VarsVsLTime.R @@ -76,10 +76,12 @@ #'smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, #' narm = TRUE), 2, dim(smooth_ano_exp)[2]) #'spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) +#' \donttest{ #'Plot2VarsVsLTime(InsertDim(rms[, , , ], 1, 1), spread$sd, #' toptitle = 'RMSE and spread', monini = 11, freq = 12, #' listexp = c('CMIP5 IC3'), listvar = c('RMSE', 'spread'), #' fileout = 'plot2vars.eps') +#' } #' #'@importFrom grDevices png jpeg postscript pdf svg bmp tiff postscript dev.cur dev.new dev.off #'@importFrom stats ts diff --git a/R/PlotACC.R b/R/PlotACC.R index bff6511a..872327f1 100644 --- a/R/PlotACC.R +++ b/R/PlotACC.R @@ -85,8 +85,10 @@ #'ano_obs <- Ano(sampleData$obs, clim$clim_obs) #'acc <- ACC(Mean1Dim(sampleData$mod, 2), #' Mean1Dim(sampleData$obs, 2)) +#' \donttest{ #'PlotACC(acc$ACC, startDates, toptitle = "Anomaly Correlation Coefficient") #' +#' } #'@importFrom grDevices dev.cur dev.new dev.off #'@importFrom stats ts #'@export diff --git a/R/PlotAno.R b/R/PlotAno.R index cc897a92..922806aa 100644 --- a/R/PlotAno.R +++ b/R/PlotAno.R @@ -66,9 +66,11 @@ #'dim_to_smooth <- 4 # Smooth along lead-times #'smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) #'smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) +#' \donttest{ #'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, #' toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') +#' } #' #'@importFrom grDevices dev.cur dev.new dev.off #'@importFrom stats ts diff --git a/R/PlotBoxWhisker.R b/R/PlotBoxWhisker.R index 1574522c..46c53355 100644 --- a/R/PlotBoxWhisker.R +++ b/R/PlotBoxWhisker.R @@ -95,8 +95,10 @@ #'ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) #'nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) #'# Finally plot the nao index +#' \donttest{ #'PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", #' monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") +#' } #' #'@importFrom grDevices dev.cur dev.new dev.off #'@importFrom stats cor diff --git a/R/PlotVsLTime.R b/R/PlotVsLTime.R index e3f7b7f7..8920438c 100644 --- a/R/PlotVsLTime.R +++ b/R/PlotVsLTime.R @@ -90,10 +90,12 @@ #' compROW = required_complete_row, #' limits = c(ceiling((runmean_months + 1) / 2), #' leadtimes_per_startdate - floor(runmean_months / 2))) +#' \donttest{ #'PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", #' monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), #' fileout = 'tos_cor.eps') +#' } #' #'@importFrom grDevices dev.cur dev.new dev.off #'@importFrom stats ts diff --git a/R/RMS.R b/R/RMS.R index bb3dd389..c83b4782 100644 --- a/R/RMS.R +++ b/R/RMS.R @@ -78,10 +78,12 @@ #' compROW = required_complete_row, #' limits = c(ceiling((runmean_months + 1) / 2), #' leadtimes_per_startdate - floor(runmean_months / 2))) +#' \donttest{ #'PlotVsLTime(rms, toptitle = "Root Mean Square Error", ytitle = "K", #' monini = 11, limits = NULL, listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = c(0), #' fileout = 'tos_rms.eps') +#' } #'# The following example uses veriApply combined with .RMS instead of RMS #' \dontrun{ #'require(easyVerification) diff --git a/R/RMSSS.R b/R/RMSSS.R index 16623b32..0ffe36f6 100644 --- a/R/RMSSS.R +++ b/R/RMSSS.R @@ -56,10 +56,12 @@ #'rmsss_plot <- array(dim = c(dim(rmsss)[1:2], 4, dim(rmsss)[4])) #'rmsss_plot[, , 2, ] <- rmsss[, , 1, ] #'rmsss_plot[, , 4, ] <- rmsss[, , 2, ] +#' \donttest{ #'PlotVsLTime(rmsss_plot, toptitle = "Root Mean Square Skill Score", ytitle = "", #' monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), #' fileout = 'tos_rmsss.eps') +#' } #'# The following example uses veriApply combined with .RMSSS instead of RMSSS #' \dontrun{ #'require(easyVerification) diff --git a/R/RatioSDRMS.R b/R/RatioSDRMS.R index ec16bc3b..62fe3ebc 100644 --- a/R/RatioSDRMS.R +++ b/R/RatioSDRMS.R @@ -50,10 +50,12 @@ #'rsdrms_plot <- array(dim = c(dim(rsdrms)[1:2], 4, dim(rsdrms)[4])) #'rsdrms_plot[, , 2, ] <- rsdrms[, , 1, ] #'rsdrms_plot[, , 4, ] <- rsdrms[, , 2, ] +#' \donttest{ #'PlotVsLTime(rsdrms_plot, toptitle = "Ratio ensemble spread / RMSE", ytitle = "", #' monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, siglev = TRUE, #' fileout = 'tos_rsdrms.eps') +#' } #' #'# The following example uses veriApply combined with .RatioSDRMS instead of RatioSDRMS #' \dontrun{ diff --git a/R/Season.R b/R/Season.R index d9f95a51..baa19bbc 100644 --- a/R/Season.R +++ b/R/Season.R @@ -32,9 +32,11 @@ #' mean_start_month, mean_stop_month) #'season_means_obs <- Season(sampleData$obs, leadtimes_dimension, initial_month, #' mean_start_month, mean_stop_month) +#' \donttest{ #'PlotAno(season_means_mod, season_means_obs, startDates, #' toptitle = paste('winter (DJF) temperatures'), ytitle = c('K'), #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_season_means.eps') +#' } #'@export Season <- function(var, posdim = 4, monini, moninf, monsup) { while (monsup < moninf) { diff --git a/R/Smoothing.R b/R/Smoothing.R index 65aac018..baf7edd2 100644 --- a/R/Smoothing.R +++ b/R/Smoothing.R @@ -28,9 +28,11 @@ #'dim_to_smooth <- 4 # Smooth along lead-times #'smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) #'smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) +#' \donttest{ #'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, #' toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", #' fileout = "tos_smoothed_ano.eps") +#' } #'@import plyr #'@export Smoothing <- function(var, runmeanlen = 12, numdimt = 4) { diff --git a/R/Spread.R b/R/Spread.R index 5a8e0189..f69aa1b8 100644 --- a/R/Spread.R +++ b/R/Spread.R @@ -58,6 +58,7 @@ #'smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, #' narm = TRUE), 2, dim(smooth_ano_exp)[2]) #'spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) +#' \donttest{ #'PlotVsLTime(spread$iqr, #' toptitle = "Inter-Quartile Range between ensemble members", #' ytitle = "K", monini = 11, limits = NULL, @@ -75,6 +76,7 @@ #' ytitle = "K", monini = 11, limits = NULL, #' listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, #' hlines = c(0), fileout = 'tos_mad.eps') +#' } #' #'@importFrom stats IQR sd mad runif quantile #'@export diff --git a/R/ToyModel.R b/R/ToyModel.R index f0c9a22d..4b06facf 100644 --- a/R/ToyModel.R +++ b/R/ToyModel.R @@ -97,9 +97,11 @@ #' #'toyforecast <- ToyModel(alpha = a, beta = b, gamma = g, nmemb = nm, #' obsini = sampleData$obs, nstartd = 5, nleadt = 60) +#' \donttest{ #'PlotAno(toyforecast$mod, toyforecast$obs, startDates, #' toptitle = c("Synthetic decadal temperature prediction"), -#' fileout = "ex_toymodel.eps") +#' fileout = "ex_toymodel.eps") +#' } #' #'@importFrom stats rnorm #'@export diff --git a/R/Trend.R b/R/Trend.R index d8bfc601..a70c6db1 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -53,9 +53,11 @@ #' monini = 11, limits = c(-1,1), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = 0, #' fileout = 'tos_obs_trend.eps') +#' \donttest{ #'PlotAno(trend$detrended, NULL, startDates, #' toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') +#' } #' #'@rdname Trend #'@export diff --git a/man/AnimateMap.Rd b/man/AnimateMap.Rd index 85eb04a9..96074b01 100644 --- a/man/AnimateMap.Rd +++ b/man/AnimateMap.Rd @@ -179,11 +179,13 @@ AnimateMap(Mean1Dim(season_means_mod, 2)[1, 1, , , ], sampleData$lon, dim_to_mean <- 2 # Mean along members rms <- RMS(Mean1Dim(season_means_mod, dim_to_mean), Mean1Dim(season_means_obs, dim_to_mean)) + \donttest{ AnimateMap(rms, sampleData$lon, sampleData$lat, toptitle = "RMSE decadal prediction", sizetit = 1, units = "degree", monini = 1, freq = 1, msk95lev = FALSE, brks = seq(0, 0.8, 0.08), intlon = 10, intlat = 10, filled.continents = TRUE, fileout = 'rmse_dec.gif') + } } \author{ History:\cr diff --git a/man/Ano_CrossValid.Rd b/man/Ano_CrossValid.Rd index bb2be436..85d1badb 100644 --- a/man/Ano_CrossValid.Rd +++ b/man/Ano_CrossValid.Rd @@ -31,9 +31,11 @@ with a cross-validation technique and a per-pair method. # Load sample data as in Load() example: example(Load) anomalies <- Ano_CrossValid(sampleData$mod, sampleData$obs) + \donttest{ PlotAno(anomalies$ano_exp, anomalies$ano_obs, startDates, toptitle = paste('anomalies'), ytitle = c('K', 'K', 'K'), legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano_crossvalid.eps') + } } \author{ History:\cr diff --git a/man/Clim.Rd b/man/Clim.Rd index 3b11fe25..1ef5e3da 100644 --- a/man/Clim.Rd +++ b/man/Clim.Rd @@ -50,10 +50,12 @@ all the data (model and obs) are excluded when computing the climatologies. # Load sample data as in Load() example: example(Load) clim <- Clim(sampleData$mod, sampleData$obs) + \donttest{ PlotClim(clim$clim_exp, clim$clim_obs, toptitle = paste('sea surface temperature climatologies'), ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') + } } \author{ History:\cr diff --git a/man/Consist_Trend.Rd b/man/Consist_Trend.Rd index a2911c64..d067dcd7 100644 --- a/man/Consist_Trend.Rd +++ b/man/Consist_Trend.Rd @@ -63,6 +63,7 @@ trend <- Consist_Trend(Mean1Dim(smooth_ano_exp, dim_to_mean), Mean1Dim(smooth_ano_obs, dim_to_mean), years_between_startdates) + \donttest{ PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K/(5 years)", monini = 11, limits = c(-0.8, 0.8), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = c(0), @@ -70,6 +71,7 @@ PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K/(5 years)", PlotAno(InsertDim(trend$detrendedmod,2,1), InsertDim(trend$detrendedobs,2,1), startDates, "Detrended tos anomalies", ytitle = 'K', legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_ano.eps') + } } \author{ diff --git a/man/Corr.Rd b/man/Corr.Rd index fcaf149a..e311813d 100644 --- a/man/Corr.Rd +++ b/man/Corr.Rd @@ -104,10 +104,12 @@ corr <- Corr(Mean1Dim(smooth_ano_exp, dim_to_mean), compROW = required_complete_row, limits = c(ceiling((runmean_months + 1) / 2), leadtimes_per_startdate - floor(runmean_months / 2))) + \donttest{ PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), fileout = 'tos_cor.eps') + } # The following example uses veriApply combined with .Corr instead of Corr \dontrun{ diff --git a/man/Filter.Rd b/man/Filter.Rd index 3ee7df89..118e2840 100644 --- a/man/Filter.Rd +++ b/man/Filter.Rd @@ -36,9 +36,11 @@ for (jstartdate in 1:3) { } } } + \donttest{ PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = 'filtered_ensemble_mean.eps') + } } \author{ History:\cr diff --git a/man/Histo2Hindcast.Rd b/man/Histo2Hindcast.Rd index af494f1a..7000628a 100644 --- a/man/Histo2Hindcast.Rd +++ b/man/Histo2Hindcast.Rd @@ -66,9 +66,11 @@ experimental_data <- Histo2Hindcast(sampleData$mod, startDates[1], start_dates_out, leadtimes_per_startdate) observational_data <- Histo2Hindcast(sampleData$obs, startDates[1], start_dates_out, leadtimes_per_startdate) + \donttest{ PlotAno(experimental_data, observational_data, start_dates_out, toptitle = paste('anomalies reorganized into shorter chunks'), ytitle = 'K', fileout='tos_histo2hindcast.eps') + } } \author{ diff --git a/man/Plot2VarsVsLTime.Rd b/man/Plot2VarsVsLTime.Rd index e79fb34e..8ba44e4e 100644 --- a/man/Plot2VarsVsLTime.Rd +++ b/man/Plot2VarsVsLTime.Rd @@ -106,10 +106,12 @@ rms <- RMS(Mean1Dim(smooth_ano_exp, dim_to_mean), smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, narm = TRUE), 2, dim(smooth_ano_exp)[2]) spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) + \donttest{ Plot2VarsVsLTime(InsertDim(rms[, , , ], 1, 1), spread$sd, toptitle = 'RMSE and spread', monini = 11, freq = 12, listexp = c('CMIP5 IC3'), listvar = c('RMSE', 'spread'), fileout = 'plot2vars.eps') + } } \author{ diff --git a/man/PlotACC.Rd b/man/PlotACC.Rd index 3427f652..fc66200a 100644 --- a/man/PlotACC.Rd +++ b/man/PlotACC.Rd @@ -111,8 +111,10 @@ ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) acc <- ACC(Mean1Dim(sampleData$mod, 2), Mean1Dim(sampleData$obs, 2)) + \donttest{ PlotACC(acc$ACC, startDates, toptitle = "Anomaly Correlation Coefficient") + } } \author{ History:\cr diff --git a/man/PlotAno.Rd b/man/PlotAno.Rd index 8a42d9fe..dd059310 100644 --- a/man/PlotAno.Rd +++ b/man/PlotAno.Rd @@ -96,9 +96,11 @@ runmean_nb_months <- 12 dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) + \donttest{ PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') + } } \author{ diff --git a/man/PlotBoxWhisker.Rd b/man/PlotBoxWhisker.Rd index 31b7d4d4..a536686b 100644 --- a/man/PlotBoxWhisker.Rd +++ b/man/PlotBoxWhisker.Rd @@ -114,8 +114,10 @@ attr(sampleData$lat, 'last_lat') <- 80 ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) # Finally plot the nao index + \donttest{ PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") + } } \author{ diff --git a/man/PlotVsLTime.Rd b/man/PlotVsLTime.Rd index e908e57b..2c71e9fa 100644 --- a/man/PlotVsLTime.Rd +++ b/man/PlotVsLTime.Rd @@ -117,10 +117,12 @@ corr <- Corr(Mean1Dim(smooth_ano_exp, dim_to_mean), compROW = required_complete_row, limits = c(ceiling((runmean_months + 1) / 2), leadtimes_per_startdate - floor(runmean_months / 2))) + \donttest{ PlotVsLTime(corr, toptitle = "correlations", ytitle = "correlation", monini = 11, limits = c(-1, 2), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), fileout = 'tos_cor.eps') + } } \author{ diff --git a/man/RMS.Rd b/man/RMS.Rd index cf26c75c..715f84d1 100644 --- a/man/RMS.Rd +++ b/man/RMS.Rd @@ -94,10 +94,12 @@ rms <- RMS(Mean1Dim(smooth_ano_exp, dim_to_mean), compROW = required_complete_row, limits = c(ceiling((runmean_months + 1) / 2), leadtimes_per_startdate - floor(runmean_months / 2))) + \donttest{ PlotVsLTime(rms, toptitle = "Root Mean Square Error", ytitle = "K", monini = 11, limits = NULL, listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = c(0), fileout = 'tos_rms.eps') + } # The following example uses veriApply combined with .RMS instead of RMS \dontrun{ require(easyVerification) diff --git a/man/RMSSS.Rd b/man/RMSSS.Rd index 234170b8..f602702b 100644 --- a/man/RMSSS.Rd +++ b/man/RMSSS.Rd @@ -70,10 +70,12 @@ rmsss <- RMSSS(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) rmsss_plot <- array(dim = c(dim(rmsss)[1:2], 4, dim(rmsss)[4])) rmsss_plot[, , 2, ] <- rmsss[, , 1, ] rmsss_plot[, , 4, ] <- rmsss[, , 2, ] + \donttest{ PlotVsLTime(rmsss_plot, toptitle = "Root Mean Square Skill Score", ytitle = "", monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = c(-1, 0, 1), fileout = 'tos_rmsss.eps') + } # The following example uses veriApply combined with .RMSSS instead of RMSSS \dontrun{ require(easyVerification) diff --git a/man/RatioSDRMS.Rd b/man/RatioSDRMS.Rd index bb5848a5..09484740 100644 --- a/man/RatioSDRMS.Rd +++ b/man/RatioSDRMS.Rd @@ -61,10 +61,12 @@ rsdrms <- RatioSDRMS(sampleData$mod, sampleData$obs) rsdrms_plot <- array(dim = c(dim(rsdrms)[1:2], 4, dim(rsdrms)[4])) rsdrms_plot[, , 2, ] <- rsdrms[, , 1, ] rsdrms_plot[, , 4, ] <- rsdrms[, , 2, ] + \donttest{ PlotVsLTime(rsdrms_plot, toptitle = "Ratio ensemble spread / RMSE", ytitle = "", monini = 11, limits = c(-1, 1.3), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, siglev = TRUE, fileout = 'tos_rsdrms.eps') + } # The following example uses veriApply combined with .RatioSDRMS instead of RatioSDRMS \dontrun{ diff --git a/man/Season.Rd b/man/Season.Rd index 08487256..cc97941c 100644 --- a/man/Season.Rd +++ b/man/Season.Rd @@ -42,9 +42,11 @@ season_means_mod <- Season(sampleData$mod, leadtimes_dimension, initial_month, mean_start_month, mean_stop_month) season_means_obs <- Season(sampleData$obs, leadtimes_dimension, initial_month, mean_start_month, mean_stop_month) + \donttest{ PlotAno(season_means_mod, season_means_obs, startDates, toptitle = paste('winter (DJF) temperatures'), ytitle = c('K'), legends = 'ERSST', biglab = FALSE, fileout = 'tos_season_means.eps') + } } \author{ History:\cr diff --git a/man/Smoothing.Rd b/man/Smoothing.Rd index 77a23cc9..4fa9c596 100644 --- a/man/Smoothing.Rd +++ b/man/Smoothing.Rd @@ -32,9 +32,11 @@ runmean_months <- 12 dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) smooth_ano_obs <- Smoothing(ano_obs, runmean_months, dim_to_smooth) + \donttest{ PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, toptitle = "Smoothed Mediterranean mean SST", ytitle = "K", fileout = "tos_smoothed_ano.eps") + } } \author{ History:\cr diff --git a/man/Spread.Rd b/man/Spread.Rd index bc14fa7a..f84cecf3 100644 --- a/man/Spread.Rd +++ b/man/Spread.Rd @@ -66,6 +66,7 @@ smooth_ano_exp <- Smoothing(ano_exp, runmean_months, dim_to_smooth) smooth_ano_exp_m_sub <- smooth_ano_exp - InsertDim(Mean1Dim(smooth_ano_exp, 2, narm = TRUE), 2, dim(smooth_ano_exp)[2]) spread <- Spread(smooth_ano_exp_m_sub, c(2, 3)) + \donttest{ PlotVsLTime(spread$iqr, toptitle = "Inter-Quartile Range between ensemble members", ytitle = "K", monini = 11, limits = NULL, @@ -83,6 +84,7 @@ PlotVsLTime(spread$mad, toptitle = "Median Absolute Deviation of the members", ytitle = "K", monini = 11, limits = NULL, listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = c(0), fileout = 'tos_mad.eps') + } } \author{ diff --git a/man/ToyModel.Rd b/man/ToyModel.Rd index da075960..ca47b449 100644 --- a/man/ToyModel.Rd +++ b/man/ToyModel.Rd @@ -112,9 +112,11 @@ nm <- 10 toyforecast <- ToyModel(alpha = a, beta = b, gamma = g, nmemb = nm, obsini = sampleData$obs, nstartd = 5, nleadt = 60) + \donttest{ PlotAno(toyforecast$mod, toyforecast$obs, startDates, toptitle = c("Synthetic decadal temperature prediction"), - fileout = "ex_toymodel.eps") + fileout = "ex_toymodel.eps") + } } \author{ diff --git a/man/Trend.Rd b/man/Trend.Rd index 71d2e1be..1f12a0dd 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -64,9 +64,11 @@ PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K / (5 year)", monini = 11, limits = c(-1,1), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = 0, fileout = 'tos_obs_trend.eps') + \donttest{ PlotAno(trend$detrended, NULL, startDates, toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') + } } \author{ -- GitLab From 7e972a0e8fbd5d21f31501c2ffda1cff03071c73 Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 16 Oct 2019 15:32:24 +0200 Subject: [PATCH 59/61] TRY to fix for CRAN Debian problem --- R/ACC.R | 2 ++ R/Ano.R | 2 ++ R/Filter.R | 2 +- R/NAO.R | 2 ++ man/ACC.Rd | 2 ++ man/Ano.Rd | 2 ++ man/Filter.Rd | 2 +- man/NAO.Rd | 2 ++ 8 files changed, 14 insertions(+), 2 deletions(-) diff --git a/R/ACC.R b/R/ACC.R index aeabc079..a00bacf7 100644 --- a/R/ACC.R +++ b/R/ACC.R @@ -77,7 +77,9 @@ #'ano_exp <- Ano(sampleData$mod, clim$clim_exp) #'ano_obs <- Ano(sampleData$obs, clim$clim_obs) #'acc <- ACC(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) +#' \donttest{ #'PlotACC(acc$ACC, startDates) +#' } #'@references Joliffe and Stephenson (2012). Forecast Verification: A #' Practitioner's Guide in Atmospheric Science. Wiley-Blackwell. #'@keywords datagen diff --git a/R/Ano.R b/R/Ano.R index 657e7f9b..1c8ffee9 100644 --- a/R/Ano.R +++ b/R/Ano.R @@ -31,9 +31,11 @@ #'dim_to_smooth <- 4 # Smooth along lead-times #'smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) #'smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) +#' \donttest{ #'PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, #' toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') +#' } #'@export Ano <- function(var, clim) { # diff --git a/R/Filter.R b/R/Filter.R index 28a89dd2..474c9c59 100644 --- a/R/Filter.R +++ b/R/Filter.R @@ -33,8 +33,8 @@ #' \donttest{ #'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = #' 'filtered_ensemble_mean.eps') -#' #' } +#' #'@importFrom stats lm #'@export Filter <- function(xdata, freq) { diff --git a/R/NAO.R b/R/NAO.R index c0d7c94d..bab4d3e0 100644 --- a/R/NAO.R +++ b/R/NAO.R @@ -111,8 +111,10 @@ #'# example data is not the full NAO area: NAO() will raise a warning. #'nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) #'# Finally plot the NAO index +#' \donttest{ #'PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", #' monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") +#' } #' #'@export NAO <- function(ano_exp = NULL, ano_obs = NULL, lon, lat, ftime_average = 2:4, obsproj = TRUE) { diff --git a/man/ACC.Rd b/man/ACC.Rd index 17e2d7cf..e3db377f 100644 --- a/man/ACC.Rd +++ b/man/ACC.Rd @@ -93,7 +93,9 @@ clim <- Clim(sampleData$mod, sampleData$obs) ano_exp <- Ano(sampleData$mod, clim$clim_exp) ano_obs <- Ano(sampleData$obs, clim$clim_obs) acc <- ACC(Mean1Dim(ano_exp, 2), Mean1Dim(ano_obs, 2)) + \donttest{ PlotACC(acc$ACC, startDates) + } } \author{ History:\cr diff --git a/man/Ano.Rd b/man/Ano.Rd index a2deb373..6143be88 100644 --- a/man/Ano.Rd +++ b/man/Ano.Rd @@ -37,9 +37,11 @@ runmean_nb_months <- 12 dim_to_smooth <- 4 # Smooth along lead-times smooth_ano_exp <- Smoothing(ano_exp, runmean_nb_months, dim_to_smooth) smooth_ano_obs <- Smoothing(ano_obs, runmean_nb_months, dim_to_smooth) + \donttest{ PlotAno(smooth_ano_exp, smooth_ano_obs, startDates, toptitle = paste('smoothed anomalies'), ytitle = c('K', 'K', 'K'), legends = 'ERSST', biglab = FALSE, fileout = 'tos_ano.eps') + } } \author{ History:\cr diff --git a/man/Filter.Rd b/man/Filter.Rd index 118e2840..3e40f105 100644 --- a/man/Filter.Rd +++ b/man/Filter.Rd @@ -39,8 +39,8 @@ for (jstartdate in 1:3) { \donttest{ PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = 'filtered_ensemble_mean.eps') - } + } \author{ History:\cr diff --git a/man/NAO.Rd b/man/NAO.Rd index 2767f7e8..24d58830 100644 --- a/man/NAO.Rd +++ b/man/NAO.Rd @@ -107,8 +107,10 @@ ano <- Ano_CrossValid(sampleData$mod, sampleData$obs) # example data is not the full NAO area: NAO() will raise a warning. nao <- NAO(ano$ano_exp, ano$ano_obs, sampleData$lon, sampleData$lat) # Finally plot the NAO index + \donttest{ PlotBoxWhisker(nao$NAO_exp, nao$NAO_obs, "NAO index, DJF", "NAO index (PC1) TOS", monini = 12, yearini = 1985, freq = 1, "Exp. A", "Obs. X") + } } \author{ -- GitLab From b4d0c378d66e570a44183d6da3ff07da9fcb7f61 Mon Sep 17 00:00:00 2001 From: aho Date: Wed, 16 Oct 2019 15:46:14 +0200 Subject: [PATCH 60/61] TRY to fix CRAN Debian problem --- R/PlotClim.R | 2 ++ R/Spectrum.R | 2 ++ R/Trend.R | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/R/PlotClim.R b/R/PlotClim.R index e7e6ac31..a002429f 100644 --- a/R/PlotClim.R +++ b/R/PlotClim.R @@ -49,9 +49,11 @@ #'# Load sample data as in Load() example: #'example(Load) #'clim <- Clim(sampleData$mod, sampleData$obs) +#' \donttest{ #'PlotClim(clim$clim_exp, clim$clim_obs, toptitle = paste('climatologies'), #' ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') +#' } #' #'@importFrom grDevices dev.cur dev.new dev.off #'@importFrom stats ts diff --git a/R/Spectrum.R b/R/Spectrum.R index bb9b2ca6..48f3823b 100644 --- a/R/Spectrum.R +++ b/R/Spectrum.R @@ -31,8 +31,10 @@ #' } #' } #'} +#' \donttest{ #'PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = #' 'filtered_ensemble_mean.eps') +#' } #' #'@importFrom stats spectrum cor rnorm sd quantile #'@export diff --git a/R/Trend.R b/R/Trend.R index a70c6db1..ba35b4d7 100644 --- a/R/Trend.R +++ b/R/Trend.R @@ -49,11 +49,11 @@ #'example(Load) #'months_between_startdates <- 60 #'trend <- Trend(sampleData$obs, 3, months_between_startdates) +#' \donttest{ #'PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K / (5 year)", #' monini = 11, limits = c(-1,1), listexp = c('CMIP5 IC3'), #' listobs = c('ERSST'), biglab = FALSE, hlines = 0, #' fileout = 'tos_obs_trend.eps') -#' \donttest{ #'PlotAno(trend$detrended, NULL, startDates, #' toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', #' legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') -- GitLab From 520acf41414d62f30006997477682b01e1cfcacc Mon Sep 17 00:00:00 2001 From: aho Date: Thu, 24 Oct 2019 09:20:47 +0200 Subject: [PATCH 61/61] hotfixes for v2.8.6 --- man/PlotClim.Rd | 2 ++ man/Spectrum.Rd | 2 ++ man/Trend.Rd | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/man/PlotClim.Rd b/man/PlotClim.Rd index 38c916cb..7ee001ee 100644 --- a/man/PlotClim.Rd +++ b/man/PlotClim.Rd @@ -74,9 +74,11 @@ c(nobs, nmemb, nltime) or c(nobs, nltime) for the observational data # Load sample data as in Load() example: example(Load) clim <- Clim(sampleData$mod, sampleData$obs) + \donttest{ PlotClim(clim$clim_exp, clim$clim_obs, toptitle = paste('climatologies'), ytitle = 'K', monini = 11, listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, fileout = 'tos_clim.eps') + } } \author{ diff --git a/man/Spectrum.Rd b/man/Spectrum.Rd index cd2dad7a..de5a2e5e 100644 --- a/man/Spectrum.Rd +++ b/man/Spectrum.Rd @@ -36,8 +36,10 @@ for (jstartdate in 1:3) { } } } + \donttest{ PlotAno(InsertDim(ensmod, 2, 1), sdates = startDates, fileout = 'filtered_ensemble_mean.eps') + } } \author{ diff --git a/man/Trend.Rd b/man/Trend.Rd index 1f12a0dd..3b7f7bfd 100644 --- a/man/Trend.Rd +++ b/man/Trend.Rd @@ -60,11 +60,11 @@ as input (exp). example(Load) months_between_startdates <- 60 trend <- Trend(sampleData$obs, 3, months_between_startdates) + \donttest{ PlotVsLTime(trend$trend, toptitle = "trend", ytitle = "K / (5 year)", monini = 11, limits = c(-1,1), listexp = c('CMIP5 IC3'), listobs = c('ERSST'), biglab = FALSE, hlines = 0, fileout = 'tos_obs_trend.eps') - \donttest{ PlotAno(trend$detrended, NULL, startDates, toptitle = 'detrended anomalies (along the startdates)', ytitle = 'K', legends = 'ERSST', biglab = FALSE, fileout = 'tos_detrended_obs.eps') -- GitLab

    9t;FVXd@y5gC`lrA#HkAX)5kkp~ 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 IWcl0w0d@Q7qyPW_ -- GitLab From b20b80c9fd22189e7a071f465ae1924a6b3ddcd5 Mon Sep 17 00:00:00 2001 From: jpena Date: Thu, 14 Mar 2019 17:03:07 +0100 Subject: [PATCH 12/61] More edits 3 --- vignettes/RMSSSforNAOprediction.png | Bin 0 -> 85982 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 vignettes/RMSSSforNAOprediction.png diff --git a/vignettes/RMSSSforNAOprediction.png b/vignettes/RMSSSforNAOprediction.png new file mode 100644 index 0000000000000000000000000000000000000000..6e394b353f118262080045fb28c7423945405514 GIT binary patch literal 85982 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