diff --git a/.gitignore b/.gitignore index e8e696e9aa..feba783d34 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,6 @@ JASP.pro.user.b601785 #Extracted testfiles Resources/TestFiles - -JASP-Engine/JASP/R/.Rhistory *.autosave +JASP-Engine/JASP/R/.Rhistory +JASP-Tests/.Rhistory diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..7d3cb83153 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,25 @@ +language: r +r: "3.3" +cache: packages + +matrix: + include: + - os: linux + dist: trusty + sudo: required + before_install: [ + "sudo add-apt-repository \"deb http://archive.ubuntu.com/ubuntu/ xenial main\" -y", + "sudo apt-get update -q", + "echo 'Installing R package dependencies'", + "sudo apt-get install libfreetype6=2.6.1-0.1ubuntu2", + "sudo apt-get install libfreetype6-dev=2.6.1-0.1ubuntu2", + "sudo apt-get install libnlopt-dev", + "sudo apt-get install r-cran-rcppeigen", + "sudo apt-get install r-cran-plogr" + ] + install: Rscript -e 'install.packages(c("testthat", "vdiffr"))' + script: + - Rscript Tools/requiredPackages.R JASP-Engine/JASP/R true + - Rscript Tools/showVersion.R + - cd JASP-Tests/R/tests/ + - R < testthat.R --no-save \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index e9c14c1a29..1452f5e2cd 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,23 +2,71 @@ JASP Release Notes ================== +Version 0.8.4 +------------- + +New Features: + - Added meta analysis + - Added network analysis + - Improved the module layout + - Added stepwise methods to logistic regression + - Added effect size measures to post-hoc analyses in ANOVA / ANCOVA + - Improved backwards compatibility for Linux users with older R versions + +Bugfixes: + - Fixed situation where JASPEngine process would linger after closing JASP + - Better handling of utf8 characters ((#1695), (#1704) and (#1719) + - Fixed confidence intervals cohens d (t-test) + - Fixed bug where prior posterior plot could not be made + - Fixed confusion in Subjective priors widget + + +Version 0.8.3.1 +--------------- + +Hotfix: + - p-value chi-square Logistic Regression (#2054) + + Version 0.8.3 ------------- New Features: - - Frequentist Logistic Regression - - Hierarchical model testing for Linear and Logistic Regression - New Progressbar (implemented for Bayesian ANOVAs and Regression) - Preference menu - specify missing values and number of decimals - - ANOVA - post-hoc tests, change y-axis label for descriptives plot - JASPTools package + - Added logistic regression + - Added hierarchical regression + - Added ability to add/change missing values + - Added progress bar to Bayesian ANOVA’s and regression + - Added preference option to change the number of decimals that are displayed + - Reworked the layout of the Preferences window + - Added option to toggle frequentist correlation table to pairwise display + - Added ability to change y-axis in RM ANOVA descriptives plots + - Added effect sizes to post-hoc tests ANOVA + - Added confidence intervals to rank correlations + - Changed display of Bayesian and frequentist correlations to below diagonal + - Removed autofilling of options when another instance of an analysis is started Changes: - Remove unused R packages - Additional Info for T-Test and Correlation Bayesian Pairs Robustness plots (Common module) +Bugfixes: + + - Fixed analysis crash when RM and between factors name match (#1906) + - Fixed bug where JASP crashes if you load data between running analyses + - Fixed issue where files from old JASP versions cause problems in newer versions + - Fixed bug where About window would go behind main window + - Fixed analysis crash when vovk-sellke was selected in correlations (#1959) + - Fixed issue with importing of PSPP files (#1966) + - Fixed issue where RM factor is reset when the analysis options are refreshed (#1921) + - Changed base of logarithm to e in Bayesian correlation matrix (#1981) + - Fixed vanishing of footnotes in Bayesian correlation matrix + - Fixed plot for logBF robustness in correlation pairs + Version 0.5 ----------- @@ -35,7 +83,7 @@ Changed: - Refinement of all the T-Tests (these are *really* polished now) -Fixed: +Bugfixes: - Fixes to add Linux support - Several bug fixes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..5edd30a196 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,12 @@ +# Contributing to jasp + +Anyone is welcome to contribute to JASP. If you would like to create a new module/analysis, fix a +bug you found, or implemented a feature, please submit a pull request. See +[Dev Docs](Docs/development) for more details about the development. + +## Pull request process + +A pull request must be reviewed by at least one member of JASP. To ensure that (if applicable): + + - The code should match the JASP style guide + - Tests should accompany any new analysis/module diff --git a/Docs/development/jasp-building-guide.md b/Docs/development/jasp-building-guide.md index 319f4cd501..c86e5f6c18 100644 --- a/Docs/development/jasp-building-guide.md +++ b/Docs/development/jasp-building-guide.md @@ -33,7 +33,7 @@ Windows Building JASP under windows is the most temperamental, and the versions listed here are known to work; slight variations on these numbers probably won't work. - [Qt 5.2.1 win64 GCC 4.8.2](https://static.jasp-stats.org/development/x64-Qt-5.2.1+QtCreator-3.0.1-(gcc-4.8.2-seh).7z) - - [R 3.3.3 win64](https://static.jasp-stats.org/development/R3.3%20Win%20JASP%200.8.4.zip) + - [R 3.3.3 win64](https://static.jasp-stats.org/development/R3.3%20Win%20JASP%200.8.5.zip) - [boost 1.64.0](https://static.jasp-stats.org/development/boost_1_64_0.zip) - [boost 1.64.0 binaries, libarchive binaries](https://static.jasp-stats.org/development/Additional%20Binary%20Deps%20Win64%20for%20JASP%20(2017-06-06).zip) @@ -64,21 +64,32 @@ To build JASP on mac you need to clone the JASP repository and download the foll 0. Clone the JASP repository 1. [XCode](https://developer.apple.com/xcode/) Easiest would be via the App Store. 2. [Qt 5.4.0](https://download.qt.io/archive/qt/) Newer version not supported yet. - 3. [R 3.3.3](https://static.jasp-stats.org/development/R3.3%20OSX%20JASP%200.8.3.zip) This contains R and the packages + 3. [R 3.3.3](https://static.jasp-stats.org/development/R3.3%20OSX%20JASP%200.8.5.zip) This contains R and the packages 4. [boost 1.64.0](https://static.jasp-stats.org/development/boost_1_64_0.zip) 5. [boost 1.64.0 binaries, libarchive binaries](https://static.jasp-stats.org/development/Additional%20Binary%20Deps%20OSX%20for%20JASP%20(2017-06-06).zip) The directory structure should be as follows: - [+] jasp-desktop < from github > - [+] boost_1_64_0 - [-] Frameworks - [+] R.framework - [+] build-JASP- ... < build directory, created by QtCreator > - - libboost_system-clang-mt-1_64.a - - libboost_filesystem-clang-mt-1_64.a - - libarchive.a - - libz.a + [+] JASP + [-] code + [+] jasp-desktop < from github > + [-] build + [-] debug < Build debug directory for QtCreator > + - libboost_system-clang-mt-1_64.a + - libboost_filesystem-clang-mt-1_64.a + - libarchive.a + - libz.a + [-] release < Build release directory for QtCreator > + - libboost_system-clang-mt-1_64.a + - libboost_filesystem-clang-mt-1_64.a + - libarchive.a + - libz.a + [+] boost_1_64_0 + [-] Frameworks + [-] R.framework + [-] Versions + [+] 3.3 + 0. **Clone** the JASP repository into a folder of your choice. Our default choice is *~/desktop/JASP/* and cloning results in the creating of *~/desktop/JASP/jasp-desktop*. 1. **XCode**: Qt on OS X relies on XCode to function, you can install this through the App Store. It's easiest if you install this, run it, accept the license agreement, and then close it down before installing Qt. diff --git a/Docs/development/jasp-r-packages-list.md b/Docs/development/jasp-r-packages-list.md index 9514da2763..e33b266f74 100644 --- a/Docs/development/jasp-r-packages-list.md +++ b/Docs/development/jasp-r-packages-list.md @@ -1,101 +1,195 @@ -JASP 0.7 R Packages -=================== +JASP 0.8.4 R-Packages +===================== -Dependencies (C++ API) ----------------------- +The complete list of R packages in the current version: +------------------------------------------------------ -* BayesFactor (0.9.12 - e1b9bbadd7d805817b9b4ac40082df5800366001) -* lme4 (1.1-7) -* Rcpp (0.11.3) -* RInside (0.2.11) -Dependencies of depedencies (C++ API) -------------------------------------- +| Package | Version | Depends | +|----------------|-------------|--------------------------------------------------------------------------------| +| BAS | 1.4.7 | R (>= 3.0), | +| BDgraph | 2.41 | R (>= 3.0.0), Matrix, igraph | +| BMS | 0.3.4 | R (>= 2.5) | +| BayesFactor | 0.9.12-2 | R (>= 3.0.2), coda, Matrix (>= 1.1-1) | +| Epi | 2.10 | R (>= 3.0.0), utils | +| Formula | 1.2-2 | R (>= 2.0.0), stats | +| GPArotation | 2014.11-1 | R (>= 2.0.0) | +| GeneNet | 1.2.13 | R (>= 3.0.2), corpcor (>= 1.6.8), longitudinal (>= 1.1.12),fdrtool (>= 1.2.15) | +| Hmisc | 4.0-3 | lattice, survival (>= 2.40-1), Formula, ggplot2 (>= 2.2) | +| IsingFit | 0.3.1 | R (>= 3.0.0) | +| IsingSampler | 0.2 | Rcpp (>= 0.10.4), R (>= 3.0.0) | +| KernSmooth | 2.23-15 | R (>= 2.5.0), stats | +| MASS | 7.3-45 | R (>= 3.1.0), grDevices, graphics, stats, utils | +| Matrix | 1.2-8 | R (>= 3.0.1) | +| MatrixModels | 0.4-1 | R (>= 3.0.1) | +| R6 | 2.2.2 | R (>= 3.0) | +| RColorBrewer | 1.1-2 | R (>= 2.0.0) | +| Rcpp | 0.12.13 | R (>= 3.0.0) | +| SparseM | 1.77 | R (>= 2.15), methods | +| SuppDists | 1.1-9.4 | R (>= 3.3.0) | +| TH.data | 1.0-8 | R (>= 2.10.0), survival, MASS | +| TTR | 0.23-2 | NA | +| abind | 1.4-5 | R (>= 1.5.0) | +| acepack | 1.4.1 | NA | +| afex | 0.18-0 | R (>= 3.1.0), lme4 (>= 1.1-8), lsmeans (>= 2.17) | +| arm | 1.9-3 | R (>= 3.1.0), MASS, Matrix (>= 1.0), stats, lme4 (>= 1.0) | +| assertthat | 0.2.0 | NA | +| backports | 1.1.1 | R (>= 3.0.0) | +| base | 3.3.3 | NA | +| base64enc | 0.1-3 | R (>= 2.9.0) | +| bindr | 0.1 | NA | +| bindrcpp | 0.2 | NA | +| boot | 1.3-18 | R (>= 3.0.0), graphics, stats | +| bootnet | 1.0.2 | ggplot2, R (>= 3.0.0) | +| ca | 0.70 | R (>= 3.0.0) | +| car | 2.1-5 | R (>= 3.2.0) | +| checkmate | 1.8.5 | R (>= 3.0.0) | +| class | 7.3-14 | R (>= 3.0.0), stats, utils | +| cluster | 2.0.5 | R (>= 3.0.1) | +| cmprsk | 2.2-7 | R (>= 2.15.0), survival | +| coda | 0.19-1 | R (>= 2.14.0) | +| codetools | 0.2-15 | R (>= 2.1) | +| coin | 1.2-1 | R (>= 2.14.0), methods, survival | +| colorspace | 1.3-2 | R (>= 2.13.0), methods | +| compiler | 3.3.3 | NA | +| contfrac | 1.1-11 | NA | +| conting | 1.6 | R (>= 2.15.0) | +| corpcor | 1.6.9 | R (>= 3.0.2) | +| curl | 3.0 | R (>= 3.0.0) | +| d3Network | 0.5.2.1 | R (>= 3.0.0) | +| data.table | 1.10.4-3 | R (>= 3.0.0) | +| datasets | 3.3.3 | NA | +| deSolve | 1.20 | R (>= 2.15.0) | +| dichromat | 2.0-0 | R (>= 2.10), stats | +| digest | 0.6.12 | R (>= 2.4.1) | +| doSNOW | 1.0.15 | R (>= 2.5.0), foreach(>= 1.2.0), iterators(>= 1.0.0), snow(>=0.3.0), utils | +| dplyr | 0.7.4 | R (>= 3.1.2) | +| ellipse | 0.3-8 | R (>= 2.0.0),graphics,stats | +| elliptic | 1.3-7 | R (>= 2.5.0) | +| estimability | 1.2 | stats | +| etm | 0.6-2 | R (>= 2.14), survival | +| evaluate | 0.10.1 | R (>= 3.0.2) | +| fdrtool | 1.2.15 | R (>= 3.0.2) | +| foreach | 1.4.3 | R (>= 2.5.0) | +| foreign | 0.8-67 | R (>= 3.0.0) | +| ggm | 2.3 | igraph | +| ggplot2 | 2.2.1 | R (>= 3.1) | +| glasso | 1.8 | NA | +| glmnet | 2.0-13 | Matrix (>= 1.0-6), utils, foreach | +| glue | 1.2.0 | R (>= 3.1) | +| gnm | 1.0-8 | R (>= 2.3.0) | +| grDevices | 3.3.3 | NA | +| graphics | 3.3.3 | NA | +| grid | 3.3.3 | NA | +| gridExtra | 2.3 | NA | +| gtable | 0.2.0 | R (>= 2.14) | +| gtools | 3.5.0 | R (>= 2.10) | +| highr | 0.6 | R (>= 3.0.2) | +| hmeasure | 1.0 | R (>= 2.10) | +| htmlTable | 1.9 | NA | +| htmltools | 0.3.6 | R (>= 2.14.1) | +| htmlwidgets | 0.9 | NA | +| huge | 1.2.7 | R (>= 3.0.0), Matrix, lattice, igraph, MASS | +| hypergeo | 1.2-13 | R (>= 3.1.0), | +| igraph | 1.1.2 | methods | +| irlba | 2.3.1 | Matrix | +| iterators | 1.0.8 | R (>= 2.5.0), utils | +| jpeg | 0.1-8 | R (>= 2.9.0) | +| jsonlite | 1.5 | methods | +| knitr | 1.17 | R (>= 3.1.0) | +| labeling | 0.3 | NA | +| lattice | 0.20-34 | R (>= 3.0.0) | +| latticeExtra | 0.6-28 | R (>= 2.10.0), lattice, RColorBrewer | +| lavaan | 0.5-23.1097 | R(>= 3.1.0) | +| lazyeval | 0.2.1 | R (>= 3.1.0) | +| lme4 | 1.1-14 | R (>= 3.0.2), Matrix (>= 1.1.1), methods, stats | +| lmerTest | 2.0-33 | R (>= 3.0.0), Matrix, stats, methods, lme4 (>= 1.0) | +| lmtest | 0.9-35 | R (>= 2.10.0), stats, zoo | +| logspline | 2.1.9 | NA | +| longitudinal | 1.1.12 | R (>= 3.0.2), corpcor (>= 1.6.8) | +| lsmeans | 2.27-2 | estimability, methods, R (>= 3.2) | +| magrittr | 1.5 | NA | +| markdown | 0.8 | R (>= 2.11.1) | +| matrixcalc | 1.0-3 | R (>= 2.0.1) | +| metafor | 2.0-0 | R (>= 3.2.0), methods, Matrix | +| methods | 3.3.3 | NA | +| mgcv | 1.8-17 | R (>= 2.14.0), nlme (>= 3.1-64) | +| mgm | 1.2-1 | NA | +| mi | 1.0 | R (>= 3.0.0), methods, Matrix, stats4 | +| mime | 0.5 | NA | +| minqa | 1.2.4 | NA | +| mitools | 2.3 | R (>= 2.10) | +| mnormt | 1.5-5 | R (>= 2.2.0) | +| modeltools | 0.2-21 | stats, stats4 | +| multcomp | 1.4-7 | stats, graphics, mvtnorm (>= 1.0-3), survival (>= 2.39-4),TH.data (>= 1.0-2) | +| munsell | 0.4.3 | NA | +| mvtnorm | 1.0-6 | R(>= 1.9.0) | +| network | 1.13.0 | R (>= 2.10), utils | +| nlme | 3.1-131 | R (>= 3.0.2) | +| nloptr | 1.0.4 | NA | +| nnet | 7.3-12 | R (>= 2.14.0), stats, utils | +| numDeriv | 2016.8-1 | R (>= 2.11.1) | +| parallel | 3.3.3 | NA | +| parcor | 0.2-6 | MASS, glmnet, ppls, Epi, GeneNet | +| pbapply | 1.3-3 | R (>= 3.2.0) | +| pbivnorm | 0.6.0 | NA | +| pbkrtest | 0.4-7 | R (>= 3.2.3), lme4 (>= 1.1.10) | +| pkgconfig | 2.0.1 | NA | +| plotrix | 3.6-6 | NA | +| plyr | 1.8.4 | R (>= 3.1.0) | +| png | 0.1-7 | R (>= 2.9.0) | +| ppls | 1.6-1 | splines, MASS | +| psych | 1.7.8 | R (>= 2.10) | +| purrr | 0.2.4 | R (>= 3.1) | +| qgraph | 1.4.4 | R (>= 3.0.0) | +| quadprog | 1.5-5 | R (>= 2.15.0) | +| quantmod | 0.4-11 | R (>= 3.2.0), xts(>= 0.9-0), zoo, TTR(>= 0.2), methods | +| quantreg | 5.34 | R (>= 2.6), stats, SparseM | +| qvcalc | 0.9-1 | NA | +| relaimpo | 2.2-2 | R(>= 2.2.1), MASS, boot, survey, mitools, graphics | +| relimp | 1.0-5 | R (>= 2.0.0) | +| reshape2 | 1.4.2 | NA | +| rjson | 0.2.15 | R (>= 3.1.0) | +| rlang | 0.1.2 | R (>= 3.1.0) | +| rpart | 4.1-10 | R (>= 2.15.0), graphics, stats, grDevices | +| sandwich | 2.4-0 | R (>= 2.10.0) | +| scales | 0.5.0 | R (>= 2.13) | +| sem | 3.1-9 | R (>= 2.14.0), stats | +| semTools | 0.4-14 | R(>= 3.0), methods, lavaan(>= 0.5-22), utils, stats, graphics | +| sna | 2.4 | R (>= 2.0.0), utils, statnet.common, network | +| snow | 0.4-2 | R (>= 2.13.1), utils | +| spatial | 7.3-11 | R (>= 3.0.0), graphics, stats, utils | +| splines | 3.3.3 | NA | +| statnet.common | 4.0.0 | NA | +| stats | 3.3.3 | NA | +| stats4 | 3.3.3 | NA | +| stringi | 1.1.5 | R (>= 2.14) | +| stringr | 1.2.0 | R (>= 2.14) | +| survey | 3.32-1 | R (>= 2.16.0), grid, methods, Matrix, survival | +| survival | 2.40-1 | R (>= 2.13.0) | +| tcltk | 3.3.3 | NA | +| tibble | 1.3.4 | R (>= 3.1.0) | +| tidyr | 0.7.2 | R (>= 3.1.0) | +| tidyselect | 0.2.2 | R (>= 3.1.0) | +| tools | 3.3.3 | NA | +| tseries | 0.10-42 | R (>= 2.10.0) | +| utils | 3.3.3 | NA | +| vcd | 1.4-3 | R (>= 2.4.0), grid | +| vcdExtra | 0.7-1 | R (>= 2.10), vcd, gnm (>= 1.0.3), grid | +| viridis | 0.4.0 | R (>= 2.10), viridisLite (>= 0.2.0) | +| viridisLite | 0.2.0 | R (>= 2.10) | +| whisker | 0.3-2 | NA | +| xtable | 1.8-2 | R (>= 2.10.0) | +| xts | 0.10-0 | zoo (>= 1.7-12) | +| yaml | 2.1.14 | NA | +| zoo | 1.8-0 | R (>= 2.10.0), stats | -* minqa (1.2.4) -* plyr (1.8.1) -* RcppEigen (0.3.2.2.0) -* reshape2 (1.4.1) -Dependencies of dependences (Modified!) -------------------------------------- -* gnm (1.0-7) **removed imports from the relimp package** +How to install current JASP packages from R +------------------------------------------- -Dependencies (C API) ------------- - -* afex (0.12-135) -* base64 (1.1) -* car (2.0-22) -* effects (3.0-3) -* qgraph (1.3) -* hypergeo (1.2-9) -* lavaan (0.5-17) -* logspline (2.1.5) -* lsmeans (2.15) -* plotrix (3.5-10) -* semTools (0.4-6) -* vcd (1.3-2) -* vcdExtra (0.6-3) - -Dependencies of dependencies (C API) ------------------------------------- - -* acepack (1.3-3.3) -* coda (0.16-1) -* coin (1.0-24) -* colorspace (1.2-4) -* contfrac (1.1-9) -* corpcor (1.6.7) -* d3Network (0.5.1) -* dichromat (2.0-0) -* digest (0.6.6) -* ellipse (0.3-8) -* elliptic (1.3-5) -* estimability (1.1) -* fdrtool (1.2.13) -* Formula (1.1-2) -* ggm (2.2) -* ggplot2 (1.0.0) -* glasso (1.8) -* gnm (1.0-7) -* gtable (0.1.2) -* gtools (3.4.1) -* Hmisc (3.14-6) -* huge (1.2.6) -* igraph (0.7.1) -* jpeg (0.1-8) -* labeling (0.3) -* latticeExtra (0.6-26) -* matrixcalc (1.0-3) -* MatrixModels (0.4-0) -* mnormt (1.5-1) -* modeltools (0.2-21) -* munsell (0.4.2) -* multcomp (1.3-9) -* mvtnorm (1.0-1) -* nloptr(1.0.4) -* pbapply (1.1-1) -* pbivnorm (0.5-1) -* pbkrtest (0.4-2) -* pixmap (0.4-11) -* png (0.1-7) -* proto (0.3-10) -* psych (1.6.12) -* quadprog (1.5-5) -* qvcalc (0.8-8) -* RColorBrewer (1.1-2) -* relimp (1.0-3) -* rjson (0.2.15) -* rtiff (1.4.4) -* sandwich (2.3-2) -* scales (0.2.4) -* sem (3.1-5) -* sendplot (4.0.0) -* sna (2.3-2) -* stringr (0.6.2) -* TH.data (1.0-6) -* whisker (0.3-2) -* zoo (1.7-11) +>install.packages(c('BAS', 'BayesFactor', 'GPArotation', 'IsingSampler', 'SuppDists', 'afex', 'car', 'conting', 'corpcor', 'doSNOW', 'dplyr', 'foreach', 'ggplot2', 'gtools', 'hmeasure', 'hypergeo', 'lavaan', 'logspline', 'lsmeans', 'metafor', 'multcomp', 'mvtnorm', 'plotrix', 'plyr', 'psych', 'qgraph', 'reshape2', 'rjson', 'semTools', 'snow', 'stringr', 'vcd', 'vcdExtra'), repos = 'https://cloud.r-project.org', dependencies = c('Depends', 'Imports')) +>install.packages("devtools",repos="http://cran.us.r-project.org",dep=TRUE) +>devtools::install_github("SachaEpskamp/bootnet") diff --git a/Docs/development/new-jasp-r-analyses.md b/Docs/development/new-jasp-r-analyses.md new file mode 100644 index 0000000000..6a153f04af --- /dev/null +++ b/Docs/development/new-jasp-r-analyses.md @@ -0,0 +1,998 @@ +# Guide to rewriting R analyses + +Previously, R analyses were designed to provide output that was as closely to JSON as possible. +This meant that tables were represented as a nested list of rows, where each cell had the column name. +Plots were also represented as a list, containing the saved png file and its width and height. +To the R programmer these concepts are not sensible, as we have native structures for tables (data.frames) and plots (recordedplots, ggplot2 objects). + +In addition to having complicated output types, the R code was further complicated by the fact that its output needed a special description. +This meant that on the one hand programmers had to tell the engine which elements were tables, which were plots, etc. +and on the other how the tables should be parsed (e.g., is a column numeric? integer?). + +The changes to the code flow relate to the above issues. +The ultimate goal is to create R-like output and separate description from code. + +This guide will detail the changes and show how they can be incorporated. +Note that this guide assumes a lot of prior knowledge of how to program in JASP. +It should be made much more friendly to new programmers still. + +## Analysis description file +Up to this point it was only necessary to create a description file for the input of an analysis. +This description file (JSON, but will become TOML; syntax is given for both) contains all the options that the analysis needs to run. +A partial excerpt of the Binomial Test: + +``` +{ + "name": "BinomialTest", + "options": [ + { + "name": "variables", + "type": "Variables" + }, + { + "format": "", + "name": "testValue", + "type": "Number", + "value": 0.5, + "max": 1, + "min": 0 + }, + { + "name": "hypothesis", + "options": ["notEqualToTestValue", "greaterThanTestValue", "lessThanTestValue"], + "default": "notEqualToTestValue", + "type": "List" + }, + ... +``` + +Up to this point, the description file was only tasked with the input into an analysis, despite the fact that the R code also provides output which must be described. +Instead, the output description was included inline in the R code. Some examples: + +``` +descriptivesPlotsMeta <- list() + +for (j in .indices(variables)){ + descriptivesPlotsMeta[[j]] <- list(name = variables[j], type = "collection", + meta = "image") +} + +results[["title"]] <- "Binomial Test" +results[[".meta"]] <- list(list(name = "binomial", type = "table"), + list(name = "descriptives", type = "object", + meta = descriptivesPlotsMeta)) +``` + +``` +fields <- list( + list(name="case", title="", type="string", combine=TRUE), + list(name="level", title="Level", type="string"), + list(name="counts", title="Counts", type="integer"), + ... +``` + +One of the largest changes is that this description is now included in the same description file. +Five new types (`title`, `dataset`, `results`, `init` and `state`) were added to the description file in addition to `options` and `name`. +These will be exemplified using the Binomial Test. + +#### title +Simply the title of the analysis that must be displayed above the analysis results. +For the Binomial Test this would be: + +``` +<- JSON syntax -> + + ... + "title": "Binomial Test", + ... +``` +``` +<- TOML syntax -> + +title = "Binomial Test" +``` + +#### dataset +Instructions for the reading of the dataset that is then supplied to R. If no dataset is required simply omit the field. +This replaces the inline `.readDataSetToEnd` and `.readDataSetHeader`. +There are five options: + +- `numeric`: all `options` that must be read as numeric. +- `factor`: all `options` that must be read as factors. +- `ordinal`: all `options` that must be read as ordered factors. +- `auto`: all `options` that must be read as the type they currently have in JASP Desktop. +- `excludeNA`: all `options` that receive listwise exclusion of `NA` values. + +The same condition applies to all the above: data is only read when a UI option is actually populated by the user. + +For the Binomial Test: +``` +<- JSON syntax -> + + ... + "dataset": { + "factor": "variables" + }, + ... +``` +``` +<- TOML syntax -> + +[dataset] +factor = "variables" +``` + +And another example, given we have five UI fields that allow variables to be read and they are all of different types: + +``` +<- JSON syntax -> + + ... + "dataset": { + "numeric": "variables1", + "factor": ["variables2", "variables3"], + "ordinal": "variables4", + "auto": "variables5", + "excludeNA": "variables1" + }, + ... +``` +``` +<- TOML syntax -> + +[dataset] +numeric = "variables1" +factor = ["variables2", "variables3"] +ordinal = "variables4" +auto = "variables5" +excludeNA = "variables1" +``` + +#### results +This field describes the results that can be expected to be returned from an analysis. +The JavaScript uses this to create the HTML tables the user ultimately sees. +There are three main `type`'s of output elements: +- table +- image +- container + +##### table +Describes what a table looks like; a table should have the following properties: +- `title`: the title which appears at the top of the table +- `type`: set to `table` +- `show`: boolean specifying if the table should be shown (only has effect when [`init`](#init) is set to `false`) +- `columns`: description of each column in the table, the descriptions may contain any of the following (\* denotes required fields): + - `name`\*: the column name + - `title`\*: optional, displayed at the top of the column; if not specified the column name is used + - `type`\*: one of `string`, `number` or `integer` + - `format`: format specifiers for `type` is `number` (multiple can be specified, separated with semicolons) + - `dp:X` - format to X decimal places + - `sf:X` - format to X significant figures + - `p:X` - if the value is less than X, substitute `p < X` in it's place (`p:.001` is common) + - `pc` - format the number as a percentage (multiply it by 100, and add a % sign) (does not work in conjunction with sf) + - `combine`: boolean specifying if cells should be merged if they contain the same value + - `show`: boolean specifying if the column should be shown (only has effect when [`init`](#init) is set to `false`) + +##### image +Describes what an image looks like; an image should have the following properties: +- `title`: the title which appears at the top of the image +- `type`: set to `image` +- `width`: the width of the image +- `height`: the height of the image +- `show`: boolean specifying if the image should be shown (only has effect when [`init`](#init) is set to `false`) + +##### container +An array of `table`'s and/or `image`'s that are grouped together in the output. +A container only has two properties (`show` is not supported as the way the items are grouped is unclear): +- `type`: set to `container` +- `items`: an array of output items which should be grouped together (the way [the items are grouped](#meta) is determined from the results list that is returned from the R analysis). + +For the Binomial Test we find: +``` +<- JSON syntax -> + +... +"results": { + "binomial": { + "type": "table", + "title": "Binomial Test", + "columns": [ + { + "name": "case", + "title": "", + "type": "string", + "combine": true + }, + { + "name": "level", + "title": "Level", + "type": "string" + }, + { + "name": "counts", + "title": "Counts", + "type": "integer" + }, + { + "name": "total", + "title": "Total", + "type": "string" + }, + { + "name": "proportion", + "title": "Proportion", + "type": "number", + "format": "sf:4;dp:3" + }, + { + "name": "p", + "title": "p", + "type": "number", + "format": "dp:3;p:.001" + }, + { + "name": "VovkSellkeMPR", + "title": "VS-MPR\u002A", + "type": "number", + "format": "sf:4;dp:3" + }, + { + "name": "lowerCI", + "title": "Lower", + "type": "number", + "format": "sf:4;dp:3" + }, + { + "name": "upperCI", + "title": "Upper", + "type": "number", + "format": "sf:4;dp:3" + } + ] + }, + "descriptives": { + "type": "container", + "items": { + "descriptivesPlot": { + "type": "image", + "width": 160, + "height": 300 + } + } + } +}, +... +``` + +``` +<- TOML syntax -> + +[results] + +[results.binomial] +title = "Binomial Test" +type = "table" + +[[results.binomial.columns]] +combine = true +name = "case" +title = "" +type = "string" + +[[results.binomial.columns]] +name = "level" +title = "Level" +type = "string" + +[[results.binomial.columns]] +name = "counts" +title = "Counts" +type = "integer" + +[[results.binomial.columns]] +name = "total" +title = "Total" +type = "string" + +[[results.binomial.columns]] +format = "sf:4;dp:3" +name = "proportion" +title = "Proportion" +type = "number" + +[[results.binomial.columns]] +format = "dp:3;p:.001" +name = "p" +title = "p" +type = "number" + +[[results.binomial.columns]] +format = "sf:4;dp:3" +name = "VovkSellkeMPR" +title = "VS-MPR*" +type = "number" + +[[results.binomial.columns]] +format = "sf:4;dp:3" +name = "lowerCI" +overTitle = "{{percent}}% Confidence Interval" +title = "Lower" +type = "number" + +[[results.binomial.columns]] +format = "sf:4;dp:3" +name = "upperCI" +overTitle = "{{percent}}% Confidence Interval" +title = "Upper" +type = "number" + +[results.descriptives] +type = "container" + +[results.descriptives.items] + +[results.descriptives.items.descriptivesPlot] +height = 300 +type = "image" +width = 160 +``` + + +#### init +Boolean that specifies whether the analysis utilises the init phase. +If this is set to `false` then each output element must use `show` for it to be shown by default. + +Now the Binomial Test has some complicated nesting in its output elements, so `init` is `true`: + +``` +<- JSON syntax -> + + ... + "init": true, + ... +``` +``` +<- TOML syntax -> + +init = true +``` + +But for a simple analysis it could be set to `false`. +If we re-use the syntax for the Binomial Test table, but only want to see the columns `case` and `level` by default: + +``` +<- JSON syntax -> + +"init": false, + ... + "binomial": { + "type": "table", + "title": "Binomial Test", + "show": true, + "columns": [ + { + "name": "case", + "title": "", + "type": "string", + "combine": true, + "show": true + }, + { + "name": "level", + "title": "Level", + "type": "string", + "show": true + }, + { + "name": "counts", + "title": "Counts", + "type": "integer" + }, + ... +``` +``` +<- TOML syntax -> + +init = false +... +[results.binomial] +title = "Binomial Test" +type = "table" +show = true + +[[results.binomial.columns]] +combine = true +name = "case" +title = "" +type = "string" +show = true + +[[results.binomial.columns]] +name = "level" +title = "Level" +type = "string" +show = true + +[[results.binomial.columns]] +name = "counts" +title = "Counts" +type = "integer" +... +``` + +#### state +Instructions for the parsing of the state RData file that is then supplied to R. If no state is required simply omit the field. +This replaces the inline `.retrieveState` and `.diff`. + +The basic premise of the state is that calculations should not needlessly be performed multiple times. +Calculated the main fit object once? Store it in the state and specify the `options` that must not change for the object to be reusable. +For the Binomial Test: + +``` +<- JSON syntax -> + + ... + "state": { + "binomResults": ["variables", "confidenceIntervalInterval", "hypothesis", "testValue"], + "descriptPlots": ["variables", "descriptivesPlots", "descriptivesPlotsConfidenceInterval", "plotWidth", "plotHeight"] + } +``` +``` +<- TOML syntax -> + +[state] +binomResults = ["variables", "confidenceIntervalInterval", "hypothesis", "testValue"] +descriptPlots = ["variables", "descriptivesPlots", "descriptivesPlotsConfidenceInterval", "plotWidth", "plotHeight"] + +``` + +Multiple objects in the state may depend on the same set of options. To prevent needless repetition there is one reserved field: +- `baseSets`: sets of placeholders that each have `options` which are added to the relevant state items + +To exemplify the use of `baseSets`: + +``` +<- JSON syntax -> + +... +"state": { + "baseSets": { + "mainModelOpts": ["opt1", "opt2", "opt3", "opt4", "opt5"], + "mainPlotOpts": ["opts6", "opts7", "opts8"] + }, + "modelFit": ["mainModelOpts", "opts9"], + "analysisPlots": ["mainModelOpts", "mainPlotOpts"] +} +``` +``` +<- TOML syntax -> + +[state] +modelFit = ["mainModelOpts", "opts9"] +analysisPlots = ["mainModelOpts", "mainPlotOpts"] + +[state.baseSets] +mainModelOpts = ["opt1", "opt2", "opt3", "opt4", "opt5"] +mainPlotOpts = ["opts6", "opts7", "opts8"] +``` + +In the example `modelFit` depends on `opts1` until `opts5` and `opts9`; `analysisPlots` depends on `opts1` until `opts8`. + +## Analysis R code +The analysis definition remains of the same form as previously, with the changed dataset and state: + +`AnalysisName <- function(dataset, options, perform="run", callback=function(...) 0, state=NULL, ...) {` + +* `dataset` : data.frame with base64 encoded column names, if `perform`=`"init"` then only the header, otherwise the full columns according to [the JSON (TOML)](#dataset) +* `options` : a list containing values corresponding to the state of each of the user interface elements in the analysis' user interface +* `perform` : will either be equal to `"init"` or `"run"`, for initializing and running the analysis respectively (may be omitted if [`init`](#init) is set to `false`) +* `callback` : a function to call periodically to notify JASP that the analysis is still running, and (not implemented yet) to provide progress updates (such as percentage complete). this function will return a non-zero value if the user has aborted the analysis, and your function should terminate in response to this +* `state` : a list containing reusable items stored at the end of the previous analysis (granted the analysis uses the state system, omit otherwise). + +In practice this means that the following items can be removed at the beginning of the analysis: + +1. Reading of the `dataset` +``` +if (is.null(dataset)) { + if (perform == "run") { + dataset <- .readDataSetToEnd(columns.as.numeric=NULL, + columns.as.factor=variables, + exclude.na.listwise=NULL) + } else { + dataset <- .readDataSetHeader(columns.as.numeric=NULL, + columns.as.factor=variables) + } +} else { + dataset <- .vdf(dataset, columns.as.numeric=NULL, + columns.as.factor=variables) +} +``` + +2. Retrieving the `state` and parsing it +``` +state <- .retrieveState() + descriptPlots <- NULL + binomResults <- NULL + + if (!is.null(state)){ + + diff <- .diff(state$options, options) + + if (is.list(diff) && !any(diff[["variables"]], + diff[["confidenceIntervalInterval"]], + diff[["hypothesis"]], + diff[["testValue"]])){ + + binomResults <- state$binomResults + } + + if (is.list(diff) && options[["descriptivesPlots"]] && + !any(diff[["variables"]], diff[["testValue"]], + diff[["descriptivesPlots"]], + diff[["descriptivesPlotsConfidenceInterval"]], + diff[["plotWidth"]], + diff[["plotHeight"]])){ + descriptPlots <- state$descriptPlots + } + + } +``` + +3. Creating [`.meta`](#meta) and adding an analysis `title` +``` +descriptivesPlotsMeta <- list() + +for (j in .indices(variables)){ + descriptivesPlotsMeta[[j]] <- list(name = variables[j], type = "collection", + meta = "image") +} + +results[["title"]] <- "Binomial Test" +results[[".meta"]] <- list(list(name = "binomial", type = "table"), + list(name = "descriptives", type = "object", + meta = descriptivesPlotsMeta)) +``` + +4. Creating `keep` +``` +plotPaths <- list() +for (i in 1:length(descriptPlots)){ + if (is.list(descriptPlots[[i]])){ + for (j in 1:length(descriptPlots[[i]]$collection)){ + plotPaths[[length(plotPaths)+1]] <- + descriptPlots[[i]]$collection[[j]]$data + } + } +} +``` + +This also means that return value from the analysis should omit keep. The structure should be + +``` +return(list(results=results, status="inited", state=state)) +``` + +if `perform`=`run` or if `init` is `false`, and otherwise + +``` +return(list(results=results, status="complete", state=state)) +``` + +#### .meta +Note that in number 3 of [this section](#analysis-r-code) we stated that .meta no longer needs to be specified explicitly. +Rather, it is deduced from the description file and the structure of the results list. +This means two things: +###### 1. The results list should adhere to certain constraints imposed by JASP (which are the same they've always been). +For simple result items of type `image` or `table` this is not a problem, e.g. for, + +``` +results <- list() +results[["binomial"]] <- data.frame(...) +``` + +the structure is always the same and the meta will be taken from the description file. +However, results that are nested lists within lists (and thus should be specified as type `container` in the description file) are a bit different. +The nesting in these containers can be of two types and may be used together: `collection` and `object`. +- `collection`: array of repeated elements of a single type + +A collection may be an array of type `table` + +``` +results[["resultName"]] <- list( + collection=list( + data.frame(...), + data.frame(...) + ), + title="Table Collection Title" +) +``` + +or type `image` + +``` +results[["resultName"]] <- list( + collection=list( + ggplot2(...), + ggplot2(...) + ), + title="Plot Collection Title" +) +``` + +or have an object (more about that below) to obtain deeper nesting +``` +results[["resultName"]] <- list( + collection=list( + list( + priorPosterior=ggplot2(...), + robustness=ggplot2(...), + sequential=ggplot2(...), + title="Plot Sub-Collection Title 1" + ), + list( + priorPosterior=ggplot2(...), + robustness=ggplot2(...), + sequential=ggplot2(...), + title="Plot Sub-Collection Title 2" + ) + ), + title="Plot Collection Title" +) +``` + +- `object`: set of named elements that may be of different types (`image`, `table`, or have a `collection`) + +Again, for a `table`: + +``` +results[["resultName"]] <- list( + modelTable=data.frame(...), + descriptivesTable=data.frame(...), + title="Table Object Title" +) +``` + +or an `image` + +``` +results[["resultName"]] <- list( + priorPosterior=ggplot2(...), + robustness=ggplot2(...), + title="Plot Object Title" +) +``` + +or a mixture + +``` +results[["resultName"]] <- list( + modelTable=data.frame(...), + priorPosterior=ggplot2(...), + title="Mixture Object Title" +) +``` + +We can use a collection in an object + +``` +results[["resultName"]] <- list( + descriptivesTable=data.frame(...), + descriptivesPlots=list( + collection=list( + ggplot2(...), + ggplot2(...) + ), + title="Plot Collection Title" + ), + title="Mixture Object Title" +) +``` + +###### 2. You cannot add partially completed results (for type `container`). + +Only add entries to the results list when it has been fully computed. +This is bad: + +``` +# don't do this: +results[["resultName"]] <- list( + descriptivesTable=list() +) +``` + +The backend will not know how to parse this to a proper `.meta` object. + +#### Tables + +To create a table in JASP simply use a `(jasp.)data.frame` or `matrix` and place this in the results list. +It is no longer necessary to use `.clean` to clean your results or make use of row lists. +Neither is it necessary to specify `.isNewGroup` in combination with `combine` from the [description file](#table). + +##### jasp.data.frame +The jasp.data.frame is a normal data.frame with improved methods for a number of S3 generics (`rbind`, `cbind`, `[]`, `subset`). +The fact that `tableResults` is a `jasp.data.frame` has the following consequences: + +* A data.frame is never reduced to a vector when it only has a single column or row +* Column names are preserved when row binding to an empty `jasp.data.frame` +* Strings are never converted to factors and subsequently, you can `rbind` new 'levels' easily +* `rbind` supports a mixed vector and types will be coerced to numeric if possible +* Attributes that have names starting with `jasp.` are never lost (the various possible attributes are listed below) + +To create an empty data.frame with column names simply add the `colnames` argument + +``` +tableResults <- jasp.data.frame(colnames=c("colName1", "colName2", "colName3")) +``` + +Now you can rbind results + +``` +tableResults <- rbind(tableResults, c("varName", 99, 99)) +``` + +And cbind + +``` +tableResults <- cbind(tableResults, colName4=99) +``` + +And subset + +``` +tableResults <- tableResults[1, ] +``` + +##### Initing +Granted that `init` is set to `true` in the description file, then the analysis will have to both initialize and run. +If it is initializing then use dots to fill the cells. +As an example, suppose we created an empty data.frame, then it is sufficient to return the following +``` +tableResults <- jasp.data.frame(colnames=c("colName1", "colName2", "colName3")) +tableResults <- rbind(tableResults, rep(".", ncol(tableResults))) +results[["tableName"]] <- tableResults +``` + +##### Errors +Previously, when we knew we could not compute a table, errors were stored in the table list under the name `error`. +Now, given we've moved away from table lists, this method is no longer possible. +Instead, this information has to be conveyed in the attributes of the data.frame + +``` +if (status$error == TRUE) { + tableResults <- jasp.data.frame(colnames=c("colName1", "colName2", "colName3")) + tableResults <- rbind(tableResults, rep(".", ncol(tableResults))) + attr(tableResults, "jasp.error") <- status$errorMessage +} +``` + +##### Footnotes +Footnotes can be added as was the case previously. Only this time it is not possible to place it directly in the table rows. + +To create a general note below a table + +``` +footnotes <- .newFootnotes() +.addFootnote(footnotes, symbol="Note.", txt="Some interesting footnote") +attr(tableResults, "jasp.footnote") <- footnotes +``` + +To add it to the fifth row of column "col1" + +``` +footnotes <- .newFootnotes() +.addFootnote(footnotes, txt="Some interesting footnote", row=5, cols="col1") +attr(tableResults, "jasp.footnote") <- footnotes +``` + +To add it to all rows of columns "col1" and "col2" + +``` +footnotes <- .newFootnotes() +.addFootnote(footnotes, txt="Some interesting footnote", cols=c("col1", "col2")) +attr(tableResults, "jasp.footnote") <- footnotes +``` + +##### Custom schema +It is possible that there are dynamic properties for some columns (or columns themselves are dynamic). +As an example, the Binomial Test uses an `overTitle` that specifies the width of the confidence interval (e.g., 95%). +Currently, it is not possible to make properties change based on a variable. +Instead, these properties must be overwritten in the `jasp.schema` + +``` +schema <- list( + list(name="lowerCI", overTitle=paste0(options$confidenceIntervalInterval * 100, "% Confidence Interval")), + list(name="upperCI", overTitle=paste0(options$confidenceIntervalInterval * 100, "% Confidence Interval")) +) +attr(tableResults, "jasp.schema") <- schema +``` + +As a result, the column titled "lowerCI" will get an additional property `overTitle` with a dynamic value. +It is also possible to add an entirely new column, which works in an identical way + +``` +schema <- list( + list(name="newCol", type="string", title="New Col Title") +) +attr(tableResults, "jasp.schema") <- schema +``` + +##### Table name in a container +There is one situation where the name of a table may have to be added directly to the data.frame. +This is the case when the table is part of a `container` and its name cannot be found in its parents (the lists in which it's nested). +Suppose we have a `container` named `resultName` in our description file, which holds a table named `resultsTable`. +If our results look as follows + +``` +results[["resultName"]] <- list( + resultsPlot=ggplot2(...), + resultsTables=list( + collection=list( + data.frame(...) + ), + title="Table Collection Title" + ), + title="Mixture Object Title" +) + +``` + +then it is not possible to pair the data.frame(s) with a corresponding `table` in the description file. +In this case we must add the name + +``` +table <- data.frame(...) +attr(table, "jasp.name") <- "resultsTable" + +results[["resultName"]] <- list( + resultsPlot=ggplot2(...), + resultsTables=list( + collection=list( + table + ), + title="Table Collection Title" + ), + title="Mixture Object Title" +) + +``` + +Note that if the name can be inferred from the (indirect) parents of the table then the attribute is not necessary. + +##### Dynamic titles +Although it is possible to add dynamic titles through the [custom schema](#custom-schema), a dedicated attribute is available. +This is to create consistency between dynamic titles of tables and plots. Plots do not have a schema attribute. +Suppose we want the title of the table to include a variable name, then + +``` +tableResults <- jasp.data.frame(colnames=c("colName1", "colName2", "colName3")) +attr(tableResults, "jasp.title") <- paste("Results -", varName) +``` + +If `varName` holds `contBinom` then the title will show `Results - contBinom`. + +#### Plots +To create a plot in JASP simply use `ggplot2` (`recordedplot` is supported but discouraged as this is not editable) and place the object in the results list. +Plots are no longer lists and it is no longer necessary to use `.writeImage` to create the actual .png file. + +##### Initing +Granted that `init` is set to `true` in the description file, then the analysis will have to both initialize and run. +If it is initializing then supply the function `plot.new` as your plot + +``` +results[["resultName"]] <- plot.new +``` + +`plot.new` has a special meaning in JASP and will be interpreted to mean that the plot should be blank and a loading indicator should be shown. + +Of course, it is also possible to create your own `ggplot2` code to make an empty plot. + +##### Errors +Previously, when we knew we could not compute a plot, or if the plot code itself returned an error, then errors were stored in the plot list under the name `error`. +Now, given we've moved away from plot lists, this method is no longer possible. +Instead, this information has to be conveyed in the attributes of the plot object + +``` +if (status$error == TRUE) { + plotResults <- plot.new + attr(plotResults, "jasp.error") <- status$errorMessage +} +``` + +If it turns out that the `ggplot2` code itself generates an error, then an empty plot will be shown with the associated error message on top. + +##### Footnotes +To add a general footnote at the bottom of a plot simply add it in the `jasp.footnote` attribute + +``` +footnotes <- .newFootnotes() +.addFootnote(footnotes, symbol="Note.", txt="Some interesting footnote") +attr(plotResults, "jasp.footnote") <- footnotes +``` + +##### Plot name in a container +There is one situation where the name of a plot may have to be added directly to the `ggplot2` object +This is the case when the plot is part of a `container` and its name cannot be found in its parents (the lists in which it's nested). +Suppose we have a `container` named `resultName` in our description file, which holds a plot named `resultsPlot`. +If our results look as follows + +``` +results[["resultName"]] <- list( + resultsTable=data.frame(...), + resultsPlots=list( + collection=list( + ggplot2(...) + ), + title="Plot Collection Title" + ), + title="Mixture Object Title" +) + +``` + +then it is not possible to pair the plot(s) with a corresponding `image` in the description file. +In this case we must add the name + +``` +plot <- ggplot2(...) +attr(plot, "jasp.name") <- "resultsPlot" + +results[["resultName"]] <- list( + resultsTable=data.frame(...), + resultsPlots=list( + collection=list( + plot + ), + title="Table Collection Title" + ), + title="Mixture Object Title" +) + +``` + +Note that if the name can be inferred from the (indirect) parents of the plot then the attribute is not necessary. + +##### Dynamic titles +Suppose we want the title of the plot to include the level of a variable, then + +``` +plotResults <- ggplot2(...) +attr(plotResults, "jasp.title") <- paste("Level -", levelVar) +``` + +If `levelVar` holds `1` then the title will show `Level - 1`. + +## Stepwise implementation of the changes +It is not necessary to change an existing analysis entirely in one go. +You can change it bit by bit until finally all the tables are data.frames, plots are objects and the unnecessary overhead (`.meta`, `keep`, etc.) is gone. +However, there are certain steps that require certain actions to be taken first. +These actions will mostly involve adding stuff to the JSON (TOML). + +- To move data reading outside the analysis the entry [`dataset`](#dataset) is required +- To move state parsing outside the analysis the entry [`state`](#state) is required +- To add a title the entries [`title`](#title) and [`results`](#results) are required +- To remove .meta from an analysis the entry [`results`](#results) is required +- To remove keep from an analysis the entries [`results`](#results) and [`state`](#state) are required +- To remove initing from an analysis the entries [`init`](#init) and [`results`](#results) are required +- Changing tables from row lists to data.frames + - tables can be converted on a table-by-table basis, as long as the [`results`](#results) entry is added + - schema and title can be removed even when it is still a row list + - .isNewGroup and status cannot be removed when it is still a row list + - footnotes and errors cannot be changed to attributes when it is still a row list +- Changing plots from lists to objects + - plots can be converted on a plot-by-plot basis, as long as the [`results`](#results) entry is added + - title/width/height/status/data/obj cannot be removed when it is still a list and not an object + - footnotes and errors cannot be changed to attributes when it is still a list and not an object + +## Open issues +- Problem with analyses that have partially filled in results. Analysis meta cannot be properly deduced from those (see [here](#2-you-cannot-add-partially-completed-results-for-type-container)). +- Footnotes might not have the full flexibility yet that is needed (e.g. how to specify same footnote for several different rows, but not all rows) +- Titles must still be specified in the results list for containers +- Cannot create empty init’s for container type +- Init phase must save output objects, so not every time empty tables with dots are shown, but rather the already calculated result +- No placeholders / variable types yet in the JSON (e.g., stuff that may make it easier to specify dynamic columns) +- No support for `casesAcrossColumns` +- We do not use the `version` field in the JSON (TOML), should probably use this for the analysis conversion +- Result parser for callback with partial results need to be added (the engine needs row lists) +- At the moment does not support 'all columns' in data reading +- Does not support array of titles/array of names in tables (BF10, BF01, LogBF10 should be an usable option for a single column) +- Exact constraints on nesting arrays (collections) and objects needs to be given in the guide \ No newline at end of file diff --git a/Docs/development/r-style-guide.md b/Docs/development/r-style-guide.md index 79280c0eac..ac4d30d9b1 100644 --- a/Docs/development/r-style-guide.md +++ b/Docs/development/r-style-guide.md @@ -149,7 +149,8 @@ The JASP style guide is based on the [google style guide](https://google.github. y <- 4 ``` 8. Indentations: - - Use four spaces (Insert spaces for tab [tab width=4]) + - Use two spaces (Insert spaces for tab [tab width=2]) + 9. Spacing - Spaces: Between binary operators (e.g., `+`, `*`, `||`, `<-`, commas. * BAD: diff --git a/Docs/user-guide/index.md b/Docs/user-guide/index.md index 3a66075430..e419b11151 100644 --- a/Docs/user-guide/index.md +++ b/Docs/user-guide/index.md @@ -4,8 +4,7 @@ JASP User Guide Hi, and welcome to the JASP User Guide! -Installation ------------- +### 1. Installation JASP is available for: @@ -13,63 +12,54 @@ JASP is available for: - Mac OS X - Linux -### Windows +It can be downloaded from the JASP download page: https://jasp-stats.org/download -JASP installs under Windows like any normal application, and can be downloaded from the JASP download page, here: https://jasp-stats.org/download +#### Windows -### Mac OS X +JASP installs under Windows like any normal application. -JASP is available for Mac OS X, version 10.8 (Mountain Lion) and above ([Which version do I have?](http://pondini.org/OSX/OSXversion.html)). +#### Mac OS X -JASP for OS X can be downloaded from the JASP download page, here: https://jasp-stats.org/download +Available for Mac OS X, version 10.8 (Mountain Lion) and above ([Which version do I have?](http://pondini.org/OSX/OSXversion.html)). -JASP for OS X currently depends on [XQuartz](http://xquartz.macosforge.org/landing/). This should be installed before commencing installation of JASP. +Currently JASP depends on [XQuartz](http://xquartz.macosforge.org/landing/). This should be installed before commencing installation. -JASP is installed by downloading and double clicking the .dmg file, and dragging the JASP icon to the Applications folder. This places JASP in your applications folder. +JASP can be installed by downloading and double clicking the .dmg file, and dragging the JASP icon to the Applications folder. This places JASP in your applications folder. -OS X actively discourages people from downloading software from the internet (rather wanting to channel people through their app store), so there will likely be some additional steps to make JASP run. - -Newer versions of OS X need to have their "Gatekeeper" options relaxed, before they will allow software to be used that was downloaded from the internet. More Info: [About Gatekeeper](https://support.apple.com/en-us/HT202491). - -You will need to change your Gatekeeper settings to "Allow applications downloaded from anywhere". - -Having relaxed the Gatekeeper settings, the next step is to 'right click' or 'control-click' JASP in your Applications directory, and select 'Open' from the menu. This will present a window saying that JASP is from an unidentified developer; selecting "Open" will start JASP. +OS X actively discourages people from downloading software from the internet (rather wanting to channel people through their app store), so there will likely be some additional steps to make JASP run. Newer versions of OS X need to have their "Gatekeeper" options relaxed, before they will allow software to be used that was downloaded from the internet. More Info: [About Gatekeeper](https://support.apple.com/en-us/HT202491). You will need to change your Gatekeeper settings to "Allow applications downloaded from anywhere". Having relaxed the Gatekeeper settings, the next step is to 'right click' or 'control-click' JASP in your Applications directory, and select 'Open' from the menu. This will present a window saying that JASP is from an unidentified developer; selecting "Open" will start JASP. ![Gatekeeper "Open"](https://raw.githubusercontent.com/jasp-stats/jasp-desktop/development/Docs/user-guide/gakekeeper.png) From then on, you will be able to start JASP in the usual way. -### Linux +#### Linux -JASP is available for the Linux versions: +JASP is available for the following Linux versions: - - Ubuntu Vivid (15.04) - - Ubuntu Trusty (14.04 LTS) + - Ubuntu Xenial (16.04 LTS) + - Ubuntu Wily (15.10) - Arch Linux -The current JASP beta (0.7.5) is available for Ubuntu Wily +For other verions, JASP can be built from the source. The debian folder is located in the github repository – https://github.com/jasp-stats/jasp-desktop/tree/development/Tools/debian -#### Ubuntu +##### Ubuntu -JASP for Vivid, Trusty and Wily are available from Jonathon's *Personal Package Archive* (PPA). Once the PPA is added to your system, you will be able to install JASP, and JASP will be automatically kept up-to-date by Ubuntu. +The latest version of JASP for Xenial and Wiley are available from JASP’s Personal Package Archive (PPA). Once the PPA is added to your system, you will be able to install JASP, and JASP will be automatically kept up-to-date by Ubuntu. The PPA and JASP can be installed by issuing the following commands at the terminal: -The PPA and JASP can be installed by issuing the following commands at the terminal: - - sudo add-apt-repository ppa:jonathon-love/jasp + sudo add-apt-repository ppa:jasp-uva/jasp sudo apt-get update sudo apt-get install jasp -#### Arch Linux +##### Arch Linux JASP is made generously available for Arch Linux by Stephen Martin, and can be installed with the following commands: git clone https://aur.archlinux.org/jasp-desktop-git.git cd jasp-desktop-git makepkg -si - -Data Sets ---------- + +### 2. Data Sets JASP comes with a handful of example data sets, which can be accessed from the 'File tab'. Selecting these will load up the data, allowing you to inspect and analyse it. @@ -79,23 +69,14 @@ If you find a .csv file that JASP opens incorrectly, you can submit this to the When opening a .csv file, JASP makes a "best guess" to assign variable types. More details below. -Variable Types --------------- +### 3. Variable Types In JASP there are 4 variable types: -1. Nominal Text -2. Nominal -3. Ordinal -4. Continuous - -*Nominal Text* variables are categorical variables with no order, and with no meaningful numeric value. An example might be a variable called *Gender*, with two levels; *Male* and *Female*. - -*Nominal* variables are categorical variables with no order, however they do have meaningful numeric values. An example might be a variable called *Group* with levels *1* and *2*. - -*Ordinal* variables are categorical variables with a numeric value, and an inherent order. An example might be *Time point* with levels *1*, *2*, *3*, *4*, and *5*. - -*Continuous* variables are variables with values which exist on a continuum, such as *Height* or *Weight*. +1. **Nominal Text** variables are categorical variables with no order, and with no meaningful numeric value. An example might be a variable called *Gender*, with two levels; *Male* and *Female*. +2. **Nominal** variables are categorical variables with no order, however they do have meaningful numeric values. An example might be a variable called *Group* with levels *1* and *2*. +3. **Ordinal** variables are categorical variables with a numeric value, and an inherent order. An example might be *Time point* with levels *1*, *2*, *3*, *4*, and *5*. +4. **Continuous** variables are variables with values which exist on a continuum, such as *Height* or *Weight*. Some users prefer not to have to specify the variable types (which can be arduous, particularly for data sets with many columns), and so the variable types in JASP are generally not enforced. They usually serve only as guides; you can, for example, assign a nominal variable as a dependent variable in a t-test. In this situation, the variable is treated as a continuous variable. (It should be noted that this is the same behaviour as SPSS) @@ -116,8 +97,7 @@ Should these automatic assignments be incorrect for your particular dataset, it Values are changed to the new data type, and any incompatibilities are converted to missing values. But be careful! JASP at present does not implement an *undo*, so if you change a *Nominal Text* column full of text values to *Nominal* or *Continuous*, it will convert the entire column to missing values. At present, there is no way to *undo* this and it will be necessary to reload the data set. -Analyses --------- +### 4. Analyses Having loaded a dataset, it is now possible to run analyses. Selecting an analysis from the Ribbon along the top, shows options for that analysis in the left panel, and results in the right panel. As the options are specified, the analysis results automatically update, providing immediate feedback. diff --git a/JASP-Common/analysis.cpp b/JASP-Common/analysis.cpp index 88364857cd..c28e3ff3b4 100644 --- a/JASP-Common/analysis.cpp +++ b/JASP-Common/analysis.cpp @@ -28,12 +28,17 @@ using namespace boost::uuids; using namespace boost; using namespace std; -Analysis::Analysis(int id, string module, string name, Options *options, const Version &version, bool autorun, bool usedata) +Analysis::Analysis(int id, string module, string name, string title, Json::Value &requiresInit, Json::Value &dataKey, Json::Value &stateKey, Json::Value &resultsMeta, Options *options, const Version &version, bool autorun, bool usedata) { _id = id; _module = module; _name = name; + _title = title; + _requiresInit = requiresInit; _options = options; + _dataKey = dataKey; + _stateKey = stateKey; + _resultsMeta = resultsMeta; _autorun = autorun; _usedata = usedata; _version = version; @@ -132,6 +137,11 @@ Json::Value Analysis::asJSON() const analysisAsJson["id"] = _id; analysisAsJson["name"] = _name; + analysisAsJson["title"] = _title; + analysisAsJson["requiresInit"] = _requiresInit; + analysisAsJson["dataKey"] = _dataKey; + analysisAsJson["stateKey"] = _stateKey; + analysisAsJson["resultsMeta"] = _resultsMeta; analysisAsJson["module"] = _module; analysisAsJson["progress"] = _progress; analysisAsJson["version"] = _version.asString(); @@ -216,6 +226,31 @@ const string &Analysis::name() const return _name; } +const string &Analysis::title() const +{ + return _title; +} + +const Json::Value &Analysis::requiresInit() const +{ + return _requiresInit; +} + +const Json::Value &Analysis::dataKey() const +{ + return _dataKey; +} + +const Json::Value &Analysis::stateKey() const +{ + return _stateKey; +} + +const Json::Value &Analysis::resultsMeta() const +{ + return _resultsMeta; +} + const string &Analysis::module() const { return _module; diff --git a/JASP-Common/analysis.h b/JASP-Common/analysis.h index 6e0971bb76..9c96a7ad2a 100644 --- a/JASP-Common/analysis.h +++ b/JASP-Common/analysis.h @@ -31,7 +31,7 @@ class Analysis enum Status { Empty, Initing, Inited, InitedAndWaiting, Running, Complete, Aborting, Aborted, Error, SaveImg, Exception }; - Analysis(int id, std::string module, std::string name, Options *options, const Version &version, bool isAutorun = true, bool usedata = true); + Analysis(int id, std::string module, std::string name, std::string title, Json::Value &requiresInit, Json::Value &dataKey, Json::Value &stateKey, Json::Value &resultsMeta, Options *options, const Version &version, bool isAutorun = true, bool usedata = true); virtual ~Analysis(); Options *options() const; @@ -49,8 +49,12 @@ class Analysis const Json::Value &results() const; const Json::Value &userData() const; Json::Value asJSON() const; - + const Json::Value &requiresInit() const; + const Json::Value &dataKey() const; + const Json::Value &stateKey() const; + const Json::Value &resultsMeta() const; const std::string &name() const; + const std::string &title() const; const std::string &module() const; int id() const; bool isAutorun() const; @@ -85,7 +89,6 @@ class Analysis bool _refreshBlocked = false; Options* _options; - Json::Value _results; Json::Value _imgResults; Json::Value _userData; @@ -97,7 +100,12 @@ class Analysis private: std::string _name; + std::string _title; + Json::Value _requiresInit; std::string _module; + Json::Value _dataKey; + Json::Value _stateKey; + Json::Value _resultsMeta; int _id; bool _autorun; bool _usedata; diff --git a/JASP-Common/analysisloader.cpp b/JASP-Common/analysisloader.cpp index b2e041474e..2d7cd81708 100644 --- a/JASP-Common/analysisloader.cpp +++ b/JASP-Common/analysisloader.cpp @@ -39,8 +39,14 @@ Analysis *AnalysisLoader::load(int id, string moduleName, string analysisName, c Json::Value analysisDesc; Json::Reader parser; parser.parse(file, analysisDesc); - + + string analysisTitle = analysisDesc.get("title", Json::nullValue).asString(); + Json::Value requiresInit = analysisDesc.get("init", Json::nullValue); + Json::Value dataKey = analysisDesc.get("dataset", Json::nullValue); + Json::Value stateKey = analysisDesc.get("state", Json::nullValue); + Json::Value resultsMeta = analysisDesc.get("results", Json::nullValue); Json::Value optionsJson = analysisDesc.get("options", Json::nullValue); + if (optionsJson != Json::nullValue) options->init(optionsJson); else @@ -54,7 +60,7 @@ Analysis *AnalysisLoader::load(int id, string moduleName, string analysisName, c file.close(); - return new Analysis(id, moduleName, analysisName, options, version, autorun, usedata); + return new Analysis(id, moduleName, analysisName, analysisTitle, requiresInit, dataKey, stateKey, resultsMeta, options, version, autorun, usedata); } throw runtime_error(analysisName + " does not exist in your JASP version."); diff --git a/JASP-Common/appinfo.cpp b/JASP-Common/appinfo.cpp index 75ec01365e..0ad81da9d1 100644 --- a/JASP-Common/appinfo.cpp +++ b/JASP-Common/appinfo.cpp @@ -17,7 +17,7 @@ #include "appinfo.h" -const Version AppInfo::version = Version(0, 8, 4, 255); +const Version AppInfo::version = Version(0, 8, 5, 256); const std::string AppInfo::name = "JASP"; const std::string AppInfo::builddate = __DATE__ " " __TIME__ " (Netherlands)" ; diff --git a/JASP-Desktop/JASP-Desktop.pri b/JASP-Desktop/JASP-Desktop.pri index 22e35792f9..e3f287e96e 100644 --- a/JASP-Desktop/JASP-Desktop.pri +++ b/JASP-Desktop/JASP-Desktop.pri @@ -1,652 +1,495 @@ - macx:ICON = $$PWD/icon.icns windows:RC_FILE = $$PWD/icon.rc -SOURCES += $$PWD/main.cpp \ - $$PWD/aboutdialog.cpp \ - $$PWD/analyses.cpp \ - $$PWD/mainwindow.cpp \ - $$PWD/datasettablemodel.cpp \ - $$PWD/enginesync.cpp \ - $$PWD/availablefields.cpp \ - $$PWD/asyncloader.cpp \ - $$PWD/maintableview.cpp \ - $$PWD/datasetloader.cpp \ - $$PWD/maintablehorizontalheader.cpp \ - $$PWD/widgets/assignbutton.cpp \ - $$PWD/widgets/availablefieldslistview.cpp \ - $$PWD/widgets/boundcheckbox.cpp \ - $$PWD/widgets/boundlistview.cpp \ - $$PWD/widgets/expanderbutton.cpp \ - $$PWD/widgets/infopopup.cpp \ - $$PWD/widgets/ribbonbutton.cpp \ - $$PWD/widgets/toolbutton.cpp \ - $$PWD/widgets/boundtextbox.cpp \ - $$PWD/widgets/boundgroupbox.cpp \ - $$PWD/widgets/progresswidget.cpp \ - $$PWD/widgets/anovamodelwidget.cpp \ - $$PWD/widgets/subjectivepriorswidget.cpp \ - $$PWD/widgets/listview.cpp \ - $$PWD/widgets/draganddrop.cpp \ - $$PWD/widgets/assignbuttonmenu.cpp \ - $$PWD/widgets/tableview.cpp \ - $$PWD/widgets/boundpairstable.cpp \ - $$PWD/widgets/boundcombobox.cpp \ - $$PWD/widgets/boundtableview.cpp \ - $$PWD/widgets/tableviewmenueditor.cpp \ - $$PWD/widgets/tableviewmenueditordelegate.cpp \ - $$PWD/analysisforms/analysisform.cpp \ - $$PWD/analysisforms/anovabayesianform.cpp \ - $$PWD/analysisforms/ttestpairedsamplesform.cpp \ - $$PWD/analysisforms/anovamultivariateform.cpp \ - $$PWD/analysisforms/ttestbayesianonesampleform.cpp \ - $$PWD/analysisforms/ancovaform.cpp \ - $$PWD/analysisforms/anovaform.cpp \ - $$PWD/analysisforms/descriptivesform.cpp \ - $$PWD/analysisforms/anovaonewayform.cpp \ - $$PWD/analysisforms/ttestonesampleform.cpp \ - $$PWD/analysisforms/ttestindependentsamplesform.cpp \ - $$PWD/analysisforms/ancovamultivariateform.cpp \ - $$PWD/analysisforms/regressionlinearform.cpp \ - $$PWD/analysisforms/correlationform.cpp \ - $$PWD/widgets/boundassignwidget.cpp \ - $$PWD/analysisforms/anovarepeatedmeasuresform.cpp \ - $$PWD/analysisforms/contingencytablesform.cpp \ - $$PWD/analysisforms/correlationpartialform.cpp \ - $$PWD/ribbons/ribbonwidget.cpp \ - $$PWD/ribbons/ribbonsem.cpp \ - $$PWD/ribbons/ribbonnetworkanalysis.cpp \ - $$PWD/ribbons/ribbonanalysis.cpp \ - $$PWD/ribbons/ribbonhome.cpp \ - $$PWD/widgets/boundtextedit.cpp \ - $$PWD/widgets/stealthbutton.cpp \ - $$PWD/analysisforms/ttestbayesianindependentsamplesform.cpp \ - $$PWD/analysisforms/ttestbayesianpairedsamplesform.cpp \ - $$PWD/widgets/itemmodelselectitem.cpp \ - $$PWD/widgets/itemmodelselectvariable.cpp \ - $$PWD/widgets/tabbar.cpp \ - $$PWD/widgets/textmodellavaan.cpp \ - $$PWD/terms.cpp \ - $$PWD/term.cpp \ - $$PWD/widgets/tablemodelanovamodelnuisancefactors.cpp \ - $$PWD/widgets/tablemodelpairsassigned.cpp \ - $$PWD/widgets/tablemodelvariables.cpp \ - $$PWD/widgets/tablemodelvariablesassigned.cpp \ - $$PWD/widgets/tablemodelvariablesavailable.cpp \ - $$PWD/widgets/tablemodelvariableslevels.cpp \ - $$PWD/widgets/tablemodelvariablesoptions.cpp \ - $$PWD/widgets/tablemodelanovamodel.cpp \ - $$PWD/widgets/tablemodelcontrasts.cpp \ - $$PWD/widgets/tablemodelanovadesign.cpp \ - $$PWD/appdirs.cpp \ - $$PWD/widgets/tablemodelanovawithinsubjectcells.cpp \ - $$PWD/analysisforms/ancovabayesianform.cpp \ - $$PWD/analysisforms/anovarepeatedmeasuresbayesianform.cpp \ - $$PWD/analysisforms/correlationbayesianform.cpp \ - $$PWD/analysisforms/contingencytablesbayesianform.cpp \ - $$PWD/analysisforms/correlationbayesianpairsform.cpp \ - $$PWD/application.cpp \ - $$PWD/analysisforms/regressionlinearbayesianform.cpp \ - $$PWD/qutils.cpp \ - $$PWD/activitylog.cpp \ - $$PWD/lrnamreply.cpp \ - $$PWD/lrnam.cpp \ - $$PWD/widgets/webview.cpp \ - $$PWD/widgets/button.cpp \ - $$PWD/ribbons/ribbonr11tlearn.cpp \ - $$PWD/backstage/breadcrumbs.cpp \ - $$PWD/backstage/verticaltabbar.cpp \ - $$PWD/backstage/verticaltabwidget.cpp \ - $$PWD/backstagewidget.cpp \ - $$PWD/backstage/fsentrywidget.cpp \ - $$PWD/backstage/fsbrowser.cpp \ - $$PWD/backstage/verticalscrollarea.cpp \ - $$PWD/backstage/elidelabel.cpp \ - $$PWD/backstage/backstageosf.cpp \ - $$PWD/backstage/backstagecomputer.cpp \ - $$PWD/backstage/backstagepage.cpp \ - $$PWD/backstage/opensavewidget.cpp \ - $$PWD/analysisforms/regressionloglinearform.cpp \ - $$PWD/analysisforms/regressionloglinearbayesianform.cpp \ - $$PWD/backstage/fsbmexamples.cpp \ - $$PWD/backstage/fsbmodel.cpp \ - $$PWD/backstage/fsbmcomputer.cpp \ - $$PWD/backstage/fsbmrecent.cpp \ - $$PWD/backstage/fsbmcurrent.cpp \ - $$PWD/backstage/fsbmrecentfolders.cpp \ - $$PWD/fileevent.cpp \ - $$PWD/widgets/boundsingleitemview.cpp \ - $$PWD/analysisforms/binomialtestform.cpp \ - $$PWD/analysisforms/binomialtestbayesianform.cpp \ - $$PWD/analysisforms/bffromtform.cpp \ - $$PWD/ribbons/ribbonsummarystatistics.cpp \ - $$PWD/variableswidget.cpp \ - $$PWD/variablespage/levelstablemodel.cpp \ - $$PWD/variablespage/variablestablemodel.cpp \ - $$PWD/backstage/fsbmosf.cpp \ - $$PWD/osfnam.cpp \ - $$PWD/onlinedatamanager.cpp \ - $$PWD/onlinedataconnection.cpp \ - $$PWD/onlinedatanodeosf.cpp \ - $$PWD/onlinedatanode.cpp \ - $$PWD/onlineusernode.cpp \ - $$PWD/onlinenode.cpp \ - $$PWD/onlineusernodeosf.cpp \ - $$PWD/backstage/authwidget.cpp \ - $$PWD/exporters/dataexporter.cpp \ - $$PWD/exporters/exporter.cpp \ - $$PWD/exporters/jaspexporter.cpp \ - $$PWD/exporters/resultexporter.cpp \ - $$PWD/importers/spss/characterencodingrecord.cpp \ - $$PWD/importers/spss/datainforecord.cpp \ - $$PWD/importers/spss/datarecords.cpp \ - $$PWD/importers/spss/dictionaryterminationrecord.cpp \ - $$PWD/importers/spss/documentrecord.cpp \ - $$PWD/importers/spss/extnumbercasesrecord.cpp \ - $$PWD/importers/spss/fileheaderrecord.cpp \ - $$PWD/importers/spss/floatinforecord.cpp \ - $$PWD/importers/spss/integerinforecord.cpp \ - $$PWD/importers/spss/longvarnamesrecord.cpp \ - $$PWD/importers/spss/miscinforecord.cpp \ - $$PWD/importers/spss/missingvaluechecker.cpp \ - $$PWD/importers/spss/numericconvertor.cpp \ - $$PWD/importers/spss/readablerecord.cpp \ - $$PWD/importers/spss/stringutils.cpp \ - $$PWD/importers/spss/valuelabelvarsrecord.cpp \ - $$PWD/importers/spss/vardisplayparamrecord.cpp \ - $$PWD/importers/spss/variablerecord.cpp \ - $$PWD/importers/spss/verylongstringrecord.cpp \ - $$PWD/importers/spss/spssimportcolumn.cpp \ - $$PWD/importers/spss/spssimportdataset.cpp \ - $$PWD/importers/ods/odsimportcolumn.cpp \ - $$PWD/importers/ods/odsimportdataset.cpp \ - $$PWD/importers/ods/odssheetcell.cpp \ - $$PWD/importers/ods/odstypes.cpp \ - $$PWD/importers/ods/odsxmlcontentshandler.cpp \ - $$PWD/importers/ods/odsxmlhandler.cpp \ - $$PWD/importers/ods/odsxmlmanifesthandler.cpp \ - $$PWD/importers/odsimporter.cpp \ - $$PWD/importers/csv.cpp \ - $$PWD/importers/csvimporter.cpp \ - $$PWD/importers/jaspimporter.cpp \ - $$PWD/importers/spssimporter.cpp \ - $$PWD/importers/codepageconvert.cpp \ - $$PWD/analysisforms/exploratoryfactoranalysisform.cpp \ - $$PWD/analysisforms/principalcomponentanalysisform.cpp \ - $$PWD/analysisforms/reliabilityanalysisform.cpp \ - $$PWD/analysisforms/basregressionlinearlinkform.cpp \ - $$PWD/analysisforms/SEM/semsimpleform.cpp \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianindependentsamplesform.cpp \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianonesampleform.cpp \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianpairedsamplesform.cpp \ - $$PWD/analysisforms/SummaryStatistics/summarystatsbinomialtestbayesianform.cpp \ - $$PWD/analysisforms/SummaryStatistics/summarystatsregressionlinearbayesianform.cpp \ - $$PWD/analysisforms/SummaryStatistics/summarystatscorrelationbayesianpairsform.cpp \ - $$PWD/analysisforms/Network/networkanalysisform.cpp \ - $$PWD/analysisforms/R11tLearn/r11tlearnform.cpp \ - $$PWD/simplecrypt.cpp \ - $$PWD/importers/convertedstringcontainer.cpp \ - $$PWD/importers/importer.cpp \ - $$PWD/importers/importdataset.cpp \ - $$PWD/importers/importcolumn.cpp \ - $$PWD/importers/csvimportcolumn.cpp \ - $$PWD/preferencesdialog.cpp \ - $$PWD/analysisforms/regressionlogisticform.cpp \ - $$PWD/analysisforms/multinomialtestform.cpp \ - $$PWD/ribbons/ribbonmeta_analysis.cpp \ - $$PWD/analysisforms/classicalmetaanalysisform.cpp \ - $$PWD/module.cpp +SOURCES += \ + $$PWD/aboutdialog.cpp \ + $$PWD/activitylog.cpp \ + $$PWD/analyses.cpp \ + $$PWD/analysisforms/analysisform.cpp \ + $$PWD/appdirs.cpp \ + $$PWD/application.cpp \ + $$PWD/asyncloader.cpp \ + $$PWD/availablefields.cpp \ + $$PWD/backstage/authwidget.cpp \ + $$PWD/backstage/backstagecomputer.cpp \ + $$PWD/backstage/backstageosf.cpp \ + $$PWD/backstage/backstagepage.cpp \ + $$PWD/backstage/breadcrumbs.cpp \ + $$PWD/backstage/elidelabel.cpp \ + $$PWD/backstage/fsbmcomputer.cpp \ + $$PWD/backstage/fsbmcurrent.cpp \ + $$PWD/backstage/fsbmexamples.cpp \ + $$PWD/backstage/fsbmodel.cpp \ + $$PWD/backstage/fsbmosf.cpp \ + $$PWD/backstage/fsbmrecent.cpp \ + $$PWD/backstage/fsbmrecentfolders.cpp \ + $$PWD/backstage/fsbrowser.cpp \ + $$PWD/backstage/fsentrywidget.cpp \ + $$PWD/backstage/opensavewidget.cpp \ + $$PWD/backstage/verticalscrollarea.cpp \ + $$PWD/backstage/verticaltabbar.cpp \ + $$PWD/backstage/verticaltabwidget.cpp \ + $$PWD/backstagewidget.cpp \ + $$PWD/datasetloader.cpp \ + $$PWD/datasettablemodel.cpp \ + $$PWD/enginesync.cpp \ + $$PWD/exporters/dataexporter.cpp \ + $$PWD/exporters/exporter.cpp \ + $$PWD/exporters/jaspexporter.cpp \ + $$PWD/exporters/resultexporter.cpp \ + $$PWD/fileevent.cpp \ + $$PWD/importers/codepageconvert.cpp \ + $$PWD/importers/convertedstringcontainer.cpp \ + $$PWD/importers/csv.cpp \ + $$PWD/importers/csvimportcolumn.cpp \ + $$PWD/importers/csvimporter.cpp \ + $$PWD/importers/importcolumn.cpp \ + $$PWD/importers/importdataset.cpp \ + $$PWD/importers/importer.cpp \ + $$PWD/importers/jaspimporter.cpp \ + $$PWD/importers/ods/odsimportcolumn.cpp \ + $$PWD/importers/ods/odsimportdataset.cpp \ + $$PWD/importers/ods/odssheetcell.cpp \ + $$PWD/importers/ods/odstypes.cpp \ + $$PWD/importers/ods/odsxmlcontentshandler.cpp \ + $$PWD/importers/ods/odsxmlhandler.cpp \ + $$PWD/importers/ods/odsxmlmanifesthandler.cpp \ + $$PWD/importers/odsimporter.cpp \ + $$PWD/importers/spss/characterencodingrecord.cpp \ + $$PWD/importers/spss/datainforecord.cpp \ + $$PWD/importers/spss/datarecords.cpp \ + $$PWD/importers/spss/dictionaryterminationrecord.cpp \ + $$PWD/importers/spss/documentrecord.cpp \ + $$PWD/importers/spss/extnumbercasesrecord.cpp \ + $$PWD/importers/spss/fileheaderrecord.cpp \ + $$PWD/importers/spss/floatinforecord.cpp \ + $$PWD/importers/spss/integerinforecord.cpp \ + $$PWD/importers/spss/longvarnamesrecord.cpp \ + $$PWD/importers/spss/miscinforecord.cpp \ + $$PWD/importers/spss/missingvaluechecker.cpp \ + $$PWD/importers/spss/numericconvertor.cpp \ + $$PWD/importers/spss/readablerecord.cpp \ + $$PWD/importers/spss/spssimportcolumn.cpp \ + $$PWD/importers/spss/spssimportdataset.cpp \ + $$PWD/importers/spss/stringutils.cpp \ + $$PWD/importers/spss/valuelabelvarsrecord.cpp \ + $$PWD/importers/spss/vardisplayparamrecord.cpp \ + $$PWD/importers/spss/variablerecord.cpp \ + $$PWD/importers/spss/verylongstringrecord.cpp \ + $$PWD/importers/spssimporter.cpp \ + $$PWD/lrnam.cpp \ + $$PWD/lrnamreply.cpp \ + $$PWD/main.cpp \ + $$PWD/maintablehorizontalheader.cpp \ + $$PWD/maintableview.cpp \ + $$PWD/mainwindow.cpp \ + $$PWD/module.cpp \ + $$PWD/onlinedataconnection.cpp \ + $$PWD/onlinedatamanager.cpp \ + $$PWD/onlinedatanode.cpp \ + $$PWD/onlinedatanodeosf.cpp \ + $$PWD/onlinenode.cpp \ + $$PWD/onlineusernode.cpp \ + $$PWD/onlineusernodeosf.cpp \ + $$PWD/osfnam.cpp \ + $$PWD/preferencesdialog.cpp \ + $$PWD/qutils.cpp \ + $$PWD/ribbons/ribbonhome.cpp \ + $$PWD/ribbons/ribbonwidget.cpp \ + $$PWD/simplecrypt.cpp \ + $$PWD/term.cpp \ + $$PWD/terms.cpp \ + $$PWD/variablespage/levelstablemodel.cpp \ + $$PWD/variablespage/variablestablemodel.cpp \ + $$PWD/variableswidget.cpp \ + $$PWD/widgets/anovamodelwidget.cpp \ + $$PWD/widgets/assignbutton.cpp \ + $$PWD/widgets/assignbuttonmenu.cpp \ + $$PWD/widgets/availablefieldslistview.cpp \ + $$PWD/widgets/boundassignwidget.cpp \ + $$PWD/widgets/boundcheckbox.cpp \ + $$PWD/widgets/boundcombobox.cpp \ + $$PWD/widgets/boundgroupbox.cpp \ + $$PWD/widgets/boundlistview.cpp \ + $$PWD/widgets/boundpairstable.cpp \ + $$PWD/widgets/boundsingleitemview.cpp \ + $$PWD/widgets/boundtableview.cpp \ + $$PWD/widgets/boundtextbox.cpp \ + $$PWD/widgets/boundtextedit.cpp \ + $$PWD/widgets/button.cpp \ + $$PWD/widgets/draganddrop.cpp \ + $$PWD/widgets/expanderbutton.cpp \ + $$PWD/widgets/infopopup.cpp \ + $$PWD/widgets/itemmodelselectitem.cpp \ + $$PWD/widgets/itemmodelselectvariable.cpp \ + $$PWD/widgets/listview.cpp \ + $$PWD/widgets/progresswidget.cpp \ + $$PWD/widgets/ribbonbutton.cpp \ + $$PWD/widgets/stealthbutton.cpp \ + $$PWD/widgets/subjectivepriorswidget.cpp \ + $$PWD/widgets/tabbar.cpp \ + $$PWD/widgets/tablemodelanovadesign.cpp \ + $$PWD/widgets/tablemodelanovamodel.cpp \ + $$PWD/widgets/tablemodelanovamodelnuisancefactors.cpp \ + $$PWD/widgets/tablemodelanovawithinsubjectcells.cpp \ + $$PWD/widgets/tablemodelcontrasts.cpp \ + $$PWD/widgets/tablemodelpairsassigned.cpp \ + $$PWD/widgets/tablemodelvariables.cpp \ + $$PWD/widgets/tablemodelvariablesassigned.cpp \ + $$PWD/widgets/tablemodelvariablesavailable.cpp \ + $$PWD/widgets/tablemodelvariableslevels.cpp \ + $$PWD/widgets/tablemodelvariablesoptions.cpp \ + $$PWD/widgets/tableview.cpp \ + $$PWD/widgets/tableviewmenueditor.cpp \ + $$PWD/widgets/tableviewmenueditordelegate.cpp \ + $$PWD/widgets/textmodellavaan.cpp \ + $$PWD/widgets/toolbutton.cpp \ + $$PWD/widgets/webview.cpp HEADERS += \ - $$PWD/aboutdialog.h \ - $$PWD/analyses.h \ - $$PWD/datasettablemodel.h \ - $$PWD/enginesync.h \ - $$PWD/availablefields.h \ - $$PWD/analysisforms/analysisform.h \ - $$PWD/datasetloader.h \ - $$PWD/widgets/assignbutton.h \ - $$PWD/widgets/availablefieldslistview.h \ - $$PWD/widgets/boundcheckbox.h \ - $$PWD/widgets/boundlistview.h \ - $$PWD/widgets/expanderbutton.h \ - $$PWD/widgets/infopopup.h \ - $$PWD/widgets/ribbonbutton.h \ - $$PWD/widgets/toolbutton.h \ - $$PWD/widgets/boundtextbox.h \ - $$PWD/widgets/boundgroupbox.h \ - $$PWD/analysisforms/anovabayesianform.h \ - $$PWD/analysisforms/ttestpairedsamplesform.h \ - $$PWD/analysisforms/anovamultivariateform.h \ - $$PWD/analysisforms/ttestbayesianonesampleform.h \ - $$PWD/widgets/boundpairstable.h \ - $$PWD/asyncloader.h \ - $$PWD/widgets/progresswidget.h \ - $$PWD/widgets/anovamodelwidget.h \ - $$PWD/widgets/subjectivepriorswidget.h \ - $$PWD/bound.h \ - $$PWD/widgets/boundmodel.h \ - $$PWD/widgets/listview.h \ - $$PWD/widgets/draganddrop.h \ - $$PWD/widgets/assignbuttonmenu.h \ - $$PWD/widgets/enhanceddroptarget.h \ - $$PWD/widgets/tableview.h \ - $$PWD/maintableview.h \ - $$PWD/widgets/droptarget.h \ - $$PWD/widgets/tablemodel.h \ - $$PWD/analysisforms/ancovaform.h \ - $$PWD/analysisforms/anovaform.h \ - $$PWD/analysisforms/descriptivesform.h \ - $$PWD/analysisforms/anovaonewayform.h \ - $$PWD/analysisforms/ttestindependentsamplesform.h \ - $$PWD/analysisforms/ttestonesampleform.h \ - $$PWD/analysisforms/ancovamultivariateform.h \ - $$PWD/maintablehorizontalheader.h \ - $$PWD/analysisforms/regressionlinearform.h \ - $$PWD/mainwindow.h \ - $$PWD/analysisforms/correlationform.h \ - $$PWD/widgets/boundcombobox.h \ - $$PWD/widgets/boundtableview.h \ - $$PWD/widgets/tableviewmenueditor.h \ - $$PWD/widgets/tableviewmenueditordelegate.h \ - $$PWD/widgets/boundassignwidget.h \ - $$PWD/analysisforms/anovarepeatedmeasuresform.h \ - $$PWD/analysisforms/contingencytablesform.h \ - $$PWD/analysisforms/correlationpartialform.h \ - $$PWD/ribbons/ribbonwidget.h \ - $$PWD/ribbons/ribbonsem.h \ - $$PWD/ribbons/ribbonnetworkanalysis.h \ - $$PWD/ribbons/ribbonanalysis.h \ - $$PWD/ribbons/ribbonhome.h \ - $$PWD/widgets/boundtextedit.h \ - $$PWD/widgets/stealthbutton.h \ - $$PWD/analysisforms/ttestbayesianindependentsamplesform.h \ - $$PWD/analysisforms/ttestbayesianpairedsamplesform.h \ - $$PWD/widgets/itemmodelselectitem.h \ - $$PWD/widgets/itemmodelselectvariable.h \ - $$PWD/widgets/tabbar.h \ - $$PWD/widgets/textmodellavaan.h \ - $$PWD/term.h \ - $$PWD/terms.h \ - $$PWD/variableinfo.h \ - $$PWD/widgets/tablemodelanovamodelnuisancefactors.h \ - $$PWD/widgets/tablemodelpairsassigned.h \ - $$PWD/widgets/tablemodelvariables.h \ - $$PWD/widgets/tablemodelvariablesassigned.h \ - $$PWD/widgets/tablemodelvariablesavailable.h \ - $$PWD/widgets/tablemodelvariableslevels.h \ - $$PWD/widgets/tablemodelvariablesoptions.h \ - $$PWD/widgets/tablemodelanovamodel.h \ - $$PWD/widgets/tablemodelcontrasts.h \ - $$PWD/widgets/tablemodelanovadesign.h \ - $$PWD/appdirs.h \ - $$PWD/widgets/tablemodelanovawithinsubjectcells.h \ - $$PWD/analysisforms/ancovabayesianform.h \ - $$PWD/analysisforms/anovarepeatedmeasuresbayesianform.h \ - $$PWD/analysisforms/correlationbayesianform.h \ - $$PWD/analysisforms/contingencytablesbayesianform.h \ - $$PWD/analysisforms/correlationbayesianpairsform.h \ - $$PWD/application.h \ - $$PWD/analysisforms/regressionlinearbayesianform.h \ - $$PWD/qutils.h \ - $$PWD/activitylog.h \ - $$PWD/lrnamreply.h \ - $$PWD/lrnam.h \ - $$PWD/widgets/groupbox.h \ - $$PWD/widgets/button.h \ - $$PWD/widgets/webview.h \ - $$PWD/ribbons/ribbonr11tlearn.h \ - $$PWD/backstage/breadcrumbs.h \ - $$PWD/backstage/verticaltabbar.h \ - $$PWD/backstage/verticaltabwidget.h \ - $$PWD/backstagewidget.h \ - $$PWD/backstage/fsentrywidget.h \ - $$PWD/backstage/fsbrowser.h \ - $$PWD/backstage/fsentry.h \ - $$PWD/backstage/verticalscrollarea.h \ - $$PWD/backstage/elidelabel.h \ - $$PWD/backstage/backstageosf.h \ - $$PWD/backstage/backstagecomputer.h \ - $$PWD/backstage/backstagepage.h \ - $$PWD/backstage/opensavewidget.h \ - $$PWD/analysisforms/regressionloglinearform.h \ - $$PWD/analysisforms/regressionloglinearbayesianform.h \ - $$PWD/backstage/fsbmexamples.h \ - $$PWD/backstage/fsbmodel.h \ - $$PWD/backstage/fsbmcomputer.h \ - $$PWD/backstage/fsbmrecent.h \ - $$PWD/backstage/fsbmcurrent.h \ - $$PWD/backstage/fsbmrecentfolders.h \ - $$PWD/fileevent.h \ - $$PWD/widgets/boundsingleitemview.h \ - $$PWD/analysisforms/binomialtestform.h \ - $$PWD/analysisforms/binomialtestbayesianform.h \ - $$PWD/analysisforms/bffromtform.h \ - $$PWD/ribbons/ribbonsummarystatistics.h \ - $$PWD/variableswidget.h \ - $$PWD/variablespage/levelstablemodel.h \ - $$PWD/variablespage/variablestablemodel.h \ - $$PWD/backstage/fsbmosf.h \ - $$PWD/osfnam.h \ - $$PWD/onlinedatamanager.h \ - $$PWD/onlinedataconnection.h \ - $$PWD/onlinedatanodeosf.h \ - $$PWD/onlinedatanode.h \ - $$PWD/onlineusernode.h \ - $$PWD/onlinenode.h \ - $$PWD/onlineusernodeosf.h \ - $$PWD/backstage/authwidget.h \ - $$PWD/exporters/dataexporter.h \ - $$PWD/exporters/exporter.h \ - $$PWD/exporters/jaspexporter.h \ - $$PWD/exporters/resultexporter.h \ - $$PWD/importers/spss/characterencodingrecord.h \ - $$PWD/importers/spss/cpconverter.h \ - $$PWD/importers/spss/datainforecord.h \ - $$PWD/importers/spss/datarecords.h \ - $$PWD/importers/spss/dictionaryterminationrecord.h \ - $$PWD/importers/spss/documentrecord.h \ - $$PWD/importers/spss/extnumbercasesrecord.h \ - $$PWD/importers/spss/fileheaderrecord.h \ - $$PWD/importers/spss/floatinforecord.h \ - $$PWD/importers/spss/integerinforecord.h \ - $$PWD/importers/spss/longvarnamesrecord.h \ - $$PWD/importers/spss/measures.h \ - $$PWD/importers/spss/miscinforecord.h \ - $$PWD/importers/spss/missingvaluechecker.h \ - $$PWD/importers/spss/numericconverter.h \ - $$PWD/importers/spss/readablerecord.h \ - $$PWD/importers/spss/spssstream.h \ - $$PWD/importers/spss/stringutils.h \ - $$PWD/importers/spss/systemfileformat.h \ - $$PWD/importers/spss/valuelabelvarsrecord.h \ - $$PWD/importers/spss/vardisplayparamrecord.h \ - $$PWD/importers/spss/variablerecord.h \ - $$PWD/importers/spss/verylongstringrecord.h \ - $$PWD/importers/codepageconvert.h \ - $$PWD/importers/csv.h \ - $$PWD/importers/csvimporter.h \ - $$PWD/importers/jaspimporter.h \ - $$PWD/importers/spssimporter.h \ - $$PWD/importers/spss/spssformattype.h \ - $$PWD/analysisforms/exploratoryfactoranalysisform.h \ - $$PWD/analysisforms/principalcomponentanalysisform.h \ - $$PWD/analysisforms/reliabilityanalysisform.h \ - $$PWD/analysisforms/basregressionlinearlinkform.h \ - $$PWD/analysisforms/SEM/semsimpleform.h \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianindependentsamplesform.h \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianonesampleform.h \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianpairedsamplesform.h \ - $$PWD/analysisforms/SummaryStatistics/summarystatsbinomialtestbayesianform.h \ - $$PWD/analysisforms/SummaryStatistics/summarystatsregressionlinearbayesianform.h \ - $$PWD/analysisforms/SummaryStatistics/summarystatscorrelationbayesianpairsform.h \ - $$PWD/analysisforms/R11tLearn/r11tlearnform.h \ - $$PWD/analysisforms/Network/networkanalysisform.h \ - $$PWD/simplecrypt.h \ - $$PWD/simplecryptkey.h \ - $$PWD/importers/convertedstringcontainer.h \ - $$PWD/importers/importer.h \ - $$PWD/importers/importdataset.h \ - $$PWD/importers/importcolumn.h \ - $$PWD/importers/importerutils.h \ - $$PWD/importers/odsimporter.h \ - $$PWD/importers/csvimportcolumn.h \ - $$PWD/importers/spss/spssimportcolumn.h \ - $$PWD/importers/spss/spssimportdataset.h \ - $$PWD/preferencesdialog.h \ - $$PWD/importers/ods/odsimportcolumn.h \ - $$PWD/importers/ods/odsimportdataset.h \ - $$PWD/importers/ods/odssheetcell.h \ - $$PWD/importers/ods/odstypes.h \ - $$PWD/importers/ods/odsxmlcontentshandler.h \ - $$PWD/importers/ods/odsxmlhandler.h \ - $$PWD/importers/ods/odsxmlmanifesthandler.h \ - $$PWD/analysisforms/regressionlogisticform.h \ - $$PWD/analysisforms/multinomialtestform.h \ - $$PWD/ribbons/ribbonmeta_analysis.h \ - $$PWD/analysisforms/classicalmetaanalysisform.h \ - $$PWD/module.h + $$PWD/aboutdialog.h \ + $$PWD/activitylog.h \ + $$PWD/analyses.h \ + $$PWD/analysisforms/analysisform.h \ + $$PWD/appdirs.h \ + $$PWD/application.h \ + $$PWD/asyncloader.h \ + $$PWD/availablefields.h \ + $$PWD/backstage/authwidget.h \ + $$PWD/backstage/backstagecomputer.h \ + $$PWD/backstage/backstageosf.h \ + $$PWD/backstage/backstagepage.h \ + $$PWD/backstage/breadcrumbs.h \ + $$PWD/backstage/elidelabel.h \ + $$PWD/backstage/fsbmcomputer.h \ + $$PWD/backstage/fsbmcurrent.h \ + $$PWD/backstage/fsbmexamples.h \ + $$PWD/backstage/fsbmodel.h \ + $$PWD/backstage/fsbmosf.h \ + $$PWD/backstage/fsbmrecent.h \ + $$PWD/backstage/fsbmrecentfolders.h \ + $$PWD/backstage/fsbrowser.h \ + $$PWD/backstage/fsentry.h \ + $$PWD/backstage/fsentrywidget.h \ + $$PWD/backstage/opensavewidget.h \ + $$PWD/backstage/verticalscrollarea.h \ + $$PWD/backstage/verticaltabbar.h \ + $$PWD/backstage/verticaltabwidget.h \ + $$PWD/backstagewidget.h \ + $$PWD/bound.h \ + $$PWD/datasetloader.h \ + $$PWD/datasettablemodel.h \ + $$PWD/enginesync.h \ + $$PWD/exporters/dataexporter.h \ + $$PWD/exporters/exporter.h \ + $$PWD/exporters/jaspexporter.h \ + $$PWD/exporters/resultexporter.h \ + $$PWD/fileevent.h \ + $$PWD/importers/codepageconvert.h \ + $$PWD/importers/convertedstringcontainer.h \ + $$PWD/importers/csv.h \ + $$PWD/importers/csvimportcolumn.h \ + $$PWD/importers/csvimporter.h \ + $$PWD/importers/importcolumn.h \ + $$PWD/importers/importdataset.h \ + $$PWD/importers/importer.h \ + $$PWD/importers/importerutils.h \ + $$PWD/importers/jaspimporter.h \ + $$PWD/importers/ods/odsimportcolumn.h \ + $$PWD/importers/ods/odsimportdataset.h \ + $$PWD/importers/ods/odssheetcell.h \ + $$PWD/importers/ods/odstypes.h \ + $$PWD/importers/ods/odsxmlcontentshandler.h \ + $$PWD/importers/ods/odsxmlhandler.h \ + $$PWD/importers/ods/odsxmlmanifesthandler.h \ + $$PWD/importers/odsimporter.h \ + $$PWD/importers/spss/characterencodingrecord.h \ + $$PWD/importers/spss/cpconverter.h \ + $$PWD/importers/spss/datainforecord.h \ + $$PWD/importers/spss/datarecords.h \ + $$PWD/importers/spss/dictionaryterminationrecord.h \ + $$PWD/importers/spss/documentrecord.h \ + $$PWD/importers/spss/extnumbercasesrecord.h \ + $$PWD/importers/spss/fileheaderrecord.h \ + $$PWD/importers/spss/floatinforecord.h \ + $$PWD/importers/spss/integerinforecord.h \ + $$PWD/importers/spss/longvarnamesrecord.h \ + $$PWD/importers/spss/measures.h \ + $$PWD/importers/spss/miscinforecord.h \ + $$PWD/importers/spss/missingvaluechecker.h \ + $$PWD/importers/spss/numericconverter.h \ + $$PWD/importers/spss/readablerecord.h \ + $$PWD/importers/spss/spssformattype.h \ + $$PWD/importers/spss/spssimportcolumn.h \ + $$PWD/importers/spss/spssimportdataset.h \ + $$PWD/importers/spss/spssstream.h \ + $$PWD/importers/spss/stringutils.h \ + $$PWD/importers/spss/systemfileformat.h \ + $$PWD/importers/spss/valuelabelvarsrecord.h \ + $$PWD/importers/spss/vardisplayparamrecord.h \ + $$PWD/importers/spss/variablerecord.h \ + $$PWD/importers/spss/verylongstringrecord.h \ + $$PWD/importers/spssimporter.h \ + $$PWD/lrnam.h \ + $$PWD/lrnamreply.h \ + $$PWD/maintablehorizontalheader.h \ + $$PWD/maintableview.h \ + $$PWD/mainwindow.h \ + $$PWD/module.h \ + $$PWD/onlinedataconnection.h \ + $$PWD/onlinedatamanager.h \ + $$PWD/onlinedatanode.h \ + $$PWD/onlinedatanodeosf.h \ + $$PWD/onlinenode.h \ + $$PWD/onlineusernode.h \ + $$PWD/onlineusernodeosf.h \ + $$PWD/osfnam.h \ + $$PWD/preferencesdialog.h \ + $$PWD/qutils.h \ + $$PWD/ribbons/ribbonhome.h \ + $$PWD/ribbons/ribbonwidget.h \ + $$PWD/simplecrypt.h \ + $$PWD/simplecryptkey.h \ + $$PWD/term.h \ + $$PWD/terms.h \ + $$PWD/variableinfo.h \ + $$PWD/variablespage/levelstablemodel.h \ + $$PWD/variablespage/variablestablemodel.h \ + $$PWD/variableswidget.h \ + $$PWD/widgets/anovamodelwidget.h \ + $$PWD/widgets/assignbutton.h \ + $$PWD/widgets/assignbuttonmenu.h \ + $$PWD/widgets/availablefieldslistview.h \ + $$PWD/widgets/boundassignwidget.h \ + $$PWD/widgets/boundcheckbox.h \ + $$PWD/widgets/boundcombobox.h \ + $$PWD/widgets/boundgroupbox.h \ + $$PWD/widgets/boundlistview.h \ + $$PWD/widgets/boundmodel.h \ + $$PWD/widgets/boundpairstable.h \ + $$PWD/widgets/boundsingleitemview.h \ + $$PWD/widgets/boundtableview.h \ + $$PWD/widgets/boundtextbox.h \ + $$PWD/widgets/boundtextedit.h \ + $$PWD/widgets/button.h \ + $$PWD/widgets/draganddrop.h \ + $$PWD/widgets/droptarget.h \ + $$PWD/widgets/enhanceddroptarget.h \ + $$PWD/widgets/expanderbutton.h \ + $$PWD/widgets/groupbox.h \ + $$PWD/widgets/infopopup.h \ + $$PWD/widgets/itemmodelselectitem.h \ + $$PWD/widgets/itemmodelselectvariable.h \ + $$PWD/widgets/listview.h \ + $$PWD/widgets/progresswidget.h \ + $$PWD/widgets/ribbonbutton.h \ + $$PWD/widgets/stealthbutton.h \ + $$PWD/widgets/subjectivepriorswidget.h \ + $$PWD/widgets/tabbar.h \ + $$PWD/widgets/tablemodel.h \ + $$PWD/widgets/tablemodelanovadesign.h \ + $$PWD/widgets/tablemodelanovamodel.h \ + $$PWD/widgets/tablemodelanovamodelnuisancefactors.h \ + $$PWD/widgets/tablemodelanovawithinsubjectcells.h \ + $$PWD/widgets/tablemodelcontrasts.h \ + $$PWD/widgets/tablemodelpairsassigned.h \ + $$PWD/widgets/tablemodelvariables.h \ + $$PWD/widgets/tablemodelvariablesassigned.h \ + $$PWD/widgets/tablemodelvariablesavailable.h \ + $$PWD/widgets/tablemodelvariableslevels.h \ + $$PWD/widgets/tablemodelvariablesoptions.h \ + $$PWD/widgets/tableview.h \ + $$PWD/widgets/tableviewmenueditor.h \ + $$PWD/widgets/tableviewmenueditordelegate.h \ + $$PWD/widgets/textmodellavaan.h \ + $$PWD/widgets/toolbutton.h \ + $$PWD/widgets/webview.h FORMS += \ - $$PWD/analysisforms/anovabayesianform.ui \ - $$PWD/analysisforms/ttestpairedsamplesform.ui \ - $$PWD/analysisforms/anovamultivariateform.ui \ - $$PWD/analysisforms/ttestbayesianonesampleform.ui \ - $$PWD/widgets/progresswidget.ui \ - $$PWD/widgets/anovamodelwidget.ui \ - $$PWD/widgets/subjectivepriorswidget.ui \ - $$PWD/analysisforms/ancovaform.ui \ - $$PWD/analysisforms/anovaform.ui \ - $$PWD/analysisforms/descriptivesform.ui \ - $$PWD/analysisforms/anovaonewayform.ui \ - $$PWD/analysisforms/ttestindependentsamplesform.ui \ - $$PWD/analysisforms/ttestonesampleform.ui \ - $$PWD/analysisforms/ancovamultivariateform.ui \ - $$PWD/analysisforms/regressionlinearform.ui \ - $$PWD/mainwindow.ui \ - $$PWD/analysisforms/correlationform.ui \ - $$PWD/widgets/boundassignwidget.ui \ - $$PWD/analysisforms/anovarepeatedmeasuresform.ui \ - $$PWD/analysisforms/contingencytablesform.ui \ - $$PWD/analysisforms/correlationpartialform.ui \ - $$PWD/ribbons/ribbonhome.ui \ - $$PWD/ribbons/ribbonsem.ui \ - $$PWD/ribbons/ribbonanalysis.ui \ - $$PWD/ribbons/ribbonnetworkanalysis.ui \ - $$PWD/analysisforms/ttestbayesianindependentsamplesform.ui \ - $$PWD/analysisforms/ttestbayesianpairedsamplesform.ui \ - $$PWD/analysisforms/ancovabayesianform.ui \ - $$PWD/analysisforms/anovarepeatedmeasuresbayesianform.ui \ - $$PWD/analysisforms/correlationbayesianform.ui \ - $$PWD/analysisforms/correlationbayesianpairsform.ui \ - $$PWD/analysisforms/contingencytablesbayesianform.ui \ - $$PWD/analysisforms/regressionlinearbayesianform.ui \ - $$PWD/ribbons/ribbonr11tlearn.ui \ - $$PWD/backstage/backstagecomputer.ui \ - $$PWD/analysisforms/regressionloglinearform.ui \ - $$PWD/analysisforms/regressionloglinearbayesianform.ui \ - $$PWD/analysisforms/binomialtestform.ui \ - $$PWD/analysisforms/binomialtestbayesianform.ui \ - $$PWD/analysisforms/bffromtform.ui \ - $$PWD/ribbons/ribbonsummarystatistics.ui \ - $$PWD/ribbons/ribbonmeta_analysis.ui \ - $$PWD/variableswidget.ui \ - $$PWD/backstage/authwidget.ui\ - $$PWD/aboutdialog.ui \ - $$PWD/preferencesdialog.ui \ - $$PWD/analysisforms/exploratoryfactoranalysisform.ui \ - $$PWD/analysisforms/principalcomponentanalysisform.ui \ - $$PWD/analysisforms/reliabilityanalysisform.ui \ - $$PWD/analysisforms/basregressionlinearlinkform.ui \ - $$PWD/analysisforms/SEM/semsimpleform.ui \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianindependentsamplesform.ui \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianonesampleform.ui \ - $$PWD/analysisforms/SummaryStatistics/summarystatsttestbayesianpairedsamplesform.ui \ - $$PWD/analysisforms/SummaryStatistics/summarystatsbinomialtestbayesianform.ui \ - $$PWD/analysisforms/SummaryStatistics/summarystatsregressionlinearbayesianform.ui \ - $$PWD/analysisforms/SummaryStatistics/summarystatscorrelationbayesianpairsform.ui \ - $$PWD/analysisforms/R11tLearn/r11tlearnform.ui \ - $$PWD/analysisforms/Network/networkanalysisform.ui \ - $$PWD/analysisforms/regressionlogisticform.ui \ - $$PWD/analysisforms/multinomialtestform.ui \ - $$PWD/analysisforms/classicalmetaanalysisform.ui + $$PWD/aboutdialog.ui \ + $$PWD/backstage/authwidget.ui\ + $$PWD/backstage/backstagecomputer.ui \ + $$PWD/mainwindow.ui \ + $$PWD/preferencesdialog.ui \ + $$PWD/ribbons/ribbonhome.ui \ + $$PWD/variableswidget.ui \ + $$PWD/widgets/anovamodelwidget.ui \ + $$PWD/widgets/boundassignwidget.ui \ + $$PWD/widgets/progresswidget.ui \ + $$PWD/widgets/subjectivepriorswidget.ui RESOURCES += \ - $$PWD/backstage/backstage.qrc \ - $$PWD/html/html.qrc \ - $$PWD/resources/icons.qrc \ - $$PWD/resources/resources.qrc + $$PWD/backstage/backstage.qrc \ + $$PWD/html/html.qrc \ + $$PWD/resources/icons.qrc \ + $$PWD/resources/resources.qrc unix:OTHER_FILES += $$PWD/icon.icns windows:OTHER_FILES += $$PWD/icon.rc OTHER_FILES += \ - $$PWD/html/index.html \ - $$PWD/html/css/jquery-ui-1.10.1.custom.css \ - $$PWD/html/css/jquery-ui-1.10.1.custom.min.css \ - $$PWD/html/css/images/animated-overlay.gif \ - $$PWD/html/css/images/ui-bg_flat_0_aaaaaa_40x100.png \ - $$PWD/html/css/images/ui-bg_flat_75_ffffff_40x100.png \ - $$PWD/html/css/images/ui-bg_glass_55_fbf9ee_1x400.png \ - $$PWD/html/css/images/ui-bg_glass_65_ffffff_1x400.png \ - $$PWD/html/css/images/ui-bg_glass_75_dadada_1x400.png \ - $$PWD/html/css/images/ui-bg_glass_75_e6e6e6_1x400.png \ - $$PWD/html/css/images/ui-bg_glass_95_fef1ec_1x400.png \ - $$PWD/html/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png \ - $$PWD/html/css/images/ui-icons_2e83ff_256x240.png \ - $$PWD/html/css/images/ui-icons_222222_256x240.png \ - $$PWD/html/css/images/ui-icons_454545_256x240.png \ - $$PWD/html/css/images/ui-icons_888888_256x240.png \ - $$PWD/html/css/images/ui-icons_cd0a0a_256x240.png \ - $$PWD/html/js/jquery-1.9.1.js \ - $$PWD/html/js/jquery-ui-1.10.1.custom.js \ - $$PWD/html/js/jquery-ui-1.10.1.custom.min.js \ - $$PWD/html/js/main.js \ - $$PWD/html/js/underscore-min.js \ - $$PWD/html/js/underscore.js \ - $$PWD/html/js/table.js \ - $$PWD/html/js/tables.js \ - $$PWD/resources/expanded.png \ - $$PWD/resources/expander-arrow-down-disabled.png \ - $$PWD/resources/expander-arrow-down-hover.png \ - $$PWD/resources/expander-arrow-down.png \ - $$PWD/resources/expander-arrow-up-disabled.png \ - $$PWD/resources/expander-arrow-up-hover.png \ - $$PWD/resources/expander-arrow-up.png \ - $$PWD/resources/icons/accessories-calculator.png \ - $$PWD/resources/icons/accessories-text-editor.png \ - $$PWD/resources/icons/application-exit.png \ - $$PWD/resources/icons/application-vnd.oasis.opendocument.spreadsheet.png \ - $$PWD/resources/icons/application-x-kchart.png \ - $$PWD/resources/icons/applications-development.png \ - $$PWD/resources/icons/applications-education-mathematics.png \ - $$PWD/resources/icons/applications-education.png \ - $$PWD/resources/icons/applications-system.png \ - $$PWD/resources/icons/applications-toys.png \ - $$PWD/resources/icons/bookcase.png \ - $$PWD/resources/icons/core.png \ - $$PWD/resources/icons/dialog-close.png \ - $$PWD/resources/icons/document-new.png \ - $$PWD/resources/icons/document-open.png \ - $$PWD/resources/icons/document-print.png \ - $$PWD/resources/icons/document-save-as.png \ - $$PWD/resources/icons/document-save.png \ - $$PWD/resources/icons/edit-copy.png \ - $$PWD/resources/icons/edit-delete-shred.png \ - $$PWD/resources/icons/edit-find.png \ - $$PWD/resources/icons/edit-paste.png \ - $$PWD/resources/icons/edit-redo.png \ - $$PWD/resources/icons/edit-undo.png \ - $$PWD/resources/icons/emblem-favorite.png \ - $$PWD/resources/icons/folder-blue.png \ - $$PWD/resources/icons/folder-cyan.png \ - $$PWD/resources/icons/folder-grey.png \ - $$PWD/resources/icons/folder-orange.png \ - $$PWD/resources/icons/folder-red.png \ - $$PWD/resources/icons/folder-txt.png \ - $$PWD/resources/icons/folder-violet.png \ - $$PWD/resources/icons/folder-yellow.png \ - $$PWD/resources/icons/help-about.png \ - $$PWD/resources/icons/kbrunch.png \ - $$PWD/resources/icons/kchart.png \ - $$PWD/resources/icons/kcmpartitions.png \ - $$PWD/resources/icons/kcoloredit.png \ - $$PWD/resources/icons/preferences-system-session-services.png \ - $$PWD/resources/icons/roll.png \ - $$PWD/resources/icons/text-x-moc.png \ - $$PWD/resources/icons/tools-wizard.png \ - $$PWD/resources/icons/user-home.png \ - $$PWD/resources/arrow-left.png \ - $$PWD/resources/arrow-right.png \ - $$PWD/resources/osx/ribbonbutton.css \ - $$PWD/html/js/displaydefs.js \ - $$PWD/html/css/theme-spss.css \ - $$PWD/html/css/theme-jasp.css \ - $$PWD/resources/icons/variable-nominal.png \ - $$PWD/resources/icons/variable-ordinal.png \ - $$PWD/resources/icons/variable-scale.png \ - $$PWD/resources/icons/analysis-ttest.png \ - $$PWD/html/css/images/copy.png \ - $$PWD/html/css/images/running.gif \ - $$PWD/html/css/images/waiting.gif \ - $$PWD/resources/icons/toolbutton-descriptives.png \ - $$PWD/resources/icons/analysis-bayesian-crosstabs.png \ - $$PWD/resources/icons/analysis-bayesian-regression.png \ - $$PWD/resources/icons/analysis-bayesian-anova.png \ - $$PWD/resources/icons/analysis-bayesian-ttest.png \ - $$PWD/resources/icons/analysis-classical-anova.png \ - $$PWD/resources/icons/analysis-classical-crosstabs.png \ - $$PWD/resources/icons/analysis-classical-regression.png \ - $$PWD/resources/icons/analysis-classical-ttest.png \ - $$PWD/resources/icons/analysis-descriptives.png \ - $$PWD/resources/icons/analysis-background-mouseover.png \ - $$PWD/resources/icons/analysis-background-clicked.png \ - $$PWD/resources/icons/analysis-descriptives.svg \ - $$PWD/resources/icons/toolbutton-menu-indicator.svg \ - $$PWD/resources/icons/variable-scale.svg \ - $$PWD/resources/icons/variable-ordinal.svg \ - $$PWD/resources/icons/variable-nominal.svg \ - $$PWD/resources/icons/analysis-classical-regression.svg \ - $$PWD/resources/icons/analysis-classical-anova.svg \ - $$PWD/resources/icons/analysis-classical-ttest.svg \ - $$PWD/resources/icons/analysis-bayesian-ttest.svg \ - $$PWD/resources/icons/analysis-bayesian-anova.svg \ - $$PWD/resources/icons/analysis-bayesian-crosstabs.svg \ - $$PWD/resources/icons/analysis-classical-crosstabs.svg \ - $$PWD/resources/icons/analysis-bayesian-regression.svg \ - $$PWD/resources/icons/toolbutton-menu-indicator.svg \ - $$PWD/html/js/image.js \ - $$PWD/resources/icons/variable-scale-inactive.svg \ - $$PWD/resources/icons/variable-ordinal-inactive.svg \ - $$PWD/resources/icons/variable-nominal-inactive.svg \ - $$PWD/html/css/images/logo.svg \ - $$PWD/html/js/images.js \ - $$PWD/html/js/analysis.js \ - $$PWD/resources/icons/variable-nominal-text.svg \ - $$PWD/html/css/images/waiting.svg \ - $$PWD/resources/icons/analysis-classical-sem.svg \ - $$PWD/html/js/jaspwidget.js \ - $$PWD/html/js/backbone-min-1.1.2.js \ - $$PWD/html/css/images/resizer.png \ - $$PWD/html/css/images/arrowsmalldownbtn.png + $$PWD/html/css/images/animated-overlay.gif \ + $$PWD/html/css/images/arrowsmalldownbtn.png \ + $$PWD/html/css/images/copy.png \ + $$PWD/html/css/images/logo.svg \ + $$PWD/html/css/images/resizer.png \ + $$PWD/html/css/images/running.gif \ + $$PWD/html/css/images/ui-bg_flat_0_aaaaaa_40x100.png \ + $$PWD/html/css/images/ui-bg_flat_75_ffffff_40x100.png \ + $$PWD/html/css/images/ui-bg_glass_55_fbf9ee_1x400.png \ + $$PWD/html/css/images/ui-bg_glass_65_ffffff_1x400.png \ + $$PWD/html/css/images/ui-bg_glass_75_dadada_1x400.png \ + $$PWD/html/css/images/ui-bg_glass_75_e6e6e6_1x400.png \ + $$PWD/html/css/images/ui-bg_glass_95_fef1ec_1x400.png \ + $$PWD/html/css/images/ui-bg_highlight-soft_75_cccccc_1x100.png \ + $$PWD/html/css/images/ui-icons_222222_256x240.png \ + $$PWD/html/css/images/ui-icons_2e83ff_256x240.png \ + $$PWD/html/css/images/ui-icons_454545_256x240.png \ + $$PWD/html/css/images/ui-icons_888888_256x240.png \ + $$PWD/html/css/images/ui-icons_cd0a0a_256x240.png \ + $$PWD/html/css/images/waiting.gif \ + $$PWD/html/css/images/waiting.svg \ + $$PWD/html/css/jquery-ui-1.10.1.custom.css \ + $$PWD/html/css/jquery-ui-1.10.1.custom.min.css \ + $$PWD/html/css/theme-jasp.css \ + $$PWD/html/css/theme-spss.css \ + $$PWD/html/index.html \ + $$PWD/html/js/analysis.js \ + $$PWD/html/js/backbone-min-1.1.2.js \ + $$PWD/html/js/displaydefs.js \ + $$PWD/html/js/image.js \ + $$PWD/html/js/images.js \ + $$PWD/html/js/jaspwidget.js \ + $$PWD/html/js/jquery-1.9.1.js \ + $$PWD/html/js/jquery-ui-1.10.1.custom.js \ + $$PWD/html/js/jquery-ui-1.10.1.custom.min.js \ + $$PWD/html/js/main.js \ + $$PWD/html/js/table.js \ + $$PWD/html/js/tables.js \ + $$PWD/html/js/underscore-min.js \ + $$PWD/html/js/underscore.js \ + $$PWD/resources/arrow-left.png \ + $$PWD/resources/arrow-right.png \ + $$PWD/resources/expanded.png \ + $$PWD/resources/expander-arrow-down-disabled.png \ + $$PWD/resources/expander-arrow-down-hover.png \ + $$PWD/resources/expander-arrow-down.png \ + $$PWD/resources/expander-arrow-up-disabled.png \ + $$PWD/resources/expander-arrow-up-hover.png \ + $$PWD/resources/expander-arrow-up.png \ + $$PWD/resources/icons/accessories-calculator.png \ + $$PWD/resources/icons/accessories-text-editor.png \ + $$PWD/resources/icons/analysis-background-clicked.png \ + $$PWD/resources/icons/analysis-background-mouseover.png \ + $$PWD/resources/icons/analysis-bayesian-anova.png \ + $$PWD/resources/icons/analysis-bayesian-anova.svg \ + $$PWD/resources/icons/analysis-bayesian-crosstabs.png \ + $$PWD/resources/icons/analysis-bayesian-crosstabs.svg \ + $$PWD/resources/icons/analysis-bayesian-regression.png \ + $$PWD/resources/icons/analysis-bayesian-regression.svg \ + $$PWD/resources/icons/analysis-bayesian-ttest.png \ + $$PWD/resources/icons/analysis-bayesian-ttest.svg \ + $$PWD/resources/icons/analysis-classical-anova.png \ + $$PWD/resources/icons/analysis-classical-anova.svg \ + $$PWD/resources/icons/analysis-classical-crosstabs.png \ + $$PWD/resources/icons/analysis-classical-crosstabs.svg \ + $$PWD/resources/icons/analysis-classical-regression.png \ + $$PWD/resources/icons/analysis-classical-regression.svg \ + $$PWD/resources/icons/analysis-classical-sem.svg \ + $$PWD/resources/icons/analysis-classical-ttest.png \ + $$PWD/resources/icons/analysis-classical-ttest.svg \ + $$PWD/resources/icons/analysis-descriptives.png \ + $$PWD/resources/icons/analysis-descriptives.svg \ + $$PWD/resources/icons/analysis-ttest.png \ + $$PWD/resources/icons/application-exit.png \ + $$PWD/resources/icons/application-vnd.oasis.opendocument.spreadsheet.png \ + $$PWD/resources/icons/application-x-kchart.png \ + $$PWD/resources/icons/applications-development.png \ + $$PWD/resources/icons/applications-education-mathematics.png \ + $$PWD/resources/icons/applications-education.png \ + $$PWD/resources/icons/applications-system.png \ + $$PWD/resources/icons/applications-toys.png \ + $$PWD/resources/icons/bookcase.png \ + $$PWD/resources/icons/core.png \ + $$PWD/resources/icons/dialog-close.png \ + $$PWD/resources/icons/document-new.png \ + $$PWD/resources/icons/document-open.png \ + $$PWD/resources/icons/document-print.png \ + $$PWD/resources/icons/document-save-as.png \ + $$PWD/resources/icons/document-save.png \ + $$PWD/resources/icons/edit-copy.png \ + $$PWD/resources/icons/edit-delete-shred.png \ + $$PWD/resources/icons/edit-find.png \ + $$PWD/resources/icons/edit-paste.png \ + $$PWD/resources/icons/edit-redo.png \ + $$PWD/resources/icons/edit-undo.png \ + $$PWD/resources/icons/emblem-favorite.png \ + $$PWD/resources/icons/folder-blue.png \ + $$PWD/resources/icons/folder-cyan.png \ + $$PWD/resources/icons/folder-grey.png \ + $$PWD/resources/icons/folder-orange.png \ + $$PWD/resources/icons/folder-red.png \ + $$PWD/resources/icons/folder-txt.png \ + $$PWD/resources/icons/folder-violet.png \ + $$PWD/resources/icons/folder-yellow.png \ + $$PWD/resources/icons/help-about.png \ + $$PWD/resources/icons/kbrunch.png \ + $$PWD/resources/icons/kchart.png \ + $$PWD/resources/icons/kcmpartitions.png \ + $$PWD/resources/icons/kcoloredit.png \ + $$PWD/resources/icons/preferences-system-session-services.png \ + $$PWD/resources/icons/roll.png \ + $$PWD/resources/icons/text-x-moc.png \ + $$PWD/resources/icons/toolbutton-descriptives.png \ + $$PWD/resources/icons/toolbutton-menu-indicator.svg \ + $$PWD/resources/icons/toolbutton-menu-indicator.svg \ + $$PWD/resources/icons/tools-wizard.png \ + $$PWD/resources/icons/user-home.png \ + $$PWD/resources/icons/variable-nominal-inactive.svg \ + $$PWD/resources/icons/variable-nominal-text.svg \ + $$PWD/resources/icons/variable-nominal.png \ + $$PWD/resources/icons/variable-nominal.svg \ + $$PWD/resources/icons/variable-ordinal-inactive.svg \ + $$PWD/resources/icons/variable-ordinal.png \ + $$PWD/resources/icons/variable-ordinal.svg \ + $$PWD/resources/icons/variable-scale-inactive.svg \ + $$PWD/resources/icons/variable-scale.png \ + $$PWD/resources/icons/variable-scale.svg \ + $$PWD/resources/osx/ribbonbutton.css HELP_PATH = $${PWD}/../Docs/help RESOURCES_PATH = $${PWD}/../Resources win32 { + RESOURCES_PATH_DEST = $${OUT_PWD}/../Resources/ - RESOURCES_PATH_DEST = $${OUT_PWD}/../Resources/ - - RESOURCES_PATH ~= s,/,\\,g - RESOURCES_PATH_DEST ~= s,/,\\,g + RESOURCES_PATH ~= s,/,\\,g + RESOURCES_PATH_DEST ~= s,/,\\,g - copyres.commands += $$quote(cmd /c xcopy /S /I /Y $${RESOURCES_PATH} $${RESOURCES_PATH_DEST}) + copyres.commands += $$quote(cmd /c xcopy /S /I /Y $${RESOURCES_PATH} $${RESOURCES_PATH_DEST}) } macx { + RESOURCES_PATH_DEST = $${OUT_PWD}/../../Resources/ - RESOURCES_PATH_DEST = $${OUT_PWD}/../../Resources/ - - copyres.commands += $(MKDIR) $$RESOURCES_PATH_DEST ; - copyres.commands += cp -R $$RESOURCES_PATH/* $$RESOURCES_PATH_DEST ; + copyres.commands += $(MKDIR) $$RESOURCES_PATH_DEST ; + copyres.commands += cp -R $$RESOURCES_PATH/* $$RESOURCES_PATH_DEST ; } linux { + RESOURCES_PATH_DEST = $${OUT_PWD}/../Resources/ - RESOURCES_PATH_DEST = $${OUT_PWD}/../Resources/ - - copyres.commands += $(MKDIR) $$RESOURCES_PATH_DEST ; - copyres.commands += cp -R $$RESOURCES_PATH/* $$RESOURCES_PATH_DEST ; + copyres.commands += $(MKDIR) $$RESOURCES_PATH_DEST ; + copyres.commands += cp -R $$RESOURCES_PATH/* $$RESOURCES_PATH_DEST ; } ! equals(PWD, $${OUT_PWD}) { - - QMAKE_EXTRA_TARGETS += copyres - POST_TARGETDEPS += copyres + QMAKE_EXTRA_TARGETS += copyres + POST_TARGETDEPS += copyres } DISTFILES += \ - $$PWD/backstage/firsttabsstylesheet.qss \ - $$PWD/backstage/secondtabsstylesheet.qss \ - $$PWD/resources/icons/file-jasp.svg \ - $$PWD/html/css/images/tinylogo.svg + $$PWD/backstage/firsttabsstylesheet.qss \ + $$PWD/backstage/secondtabsstylesheet.qss \ + $$PWD/html/css/images/tinylogo.svg \ + $$PWD/resources/icons/file-jasp.svg diff --git a/JASP-Desktop/JASP-Desktop.pro b/JASP-Desktop/JASP-Desktop.pro index de5cb96664..650ad8c8d6 100644 --- a/JASP-Desktop/JASP-Desktop.pro +++ b/JASP-Desktop/JASP-Desktop.pro @@ -1,12 +1,8 @@ - QT += core gui webkit webkitwidgets svg network printsupport xml greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -windows:CONFIG += c++11 -linux:CONFIG += c++11 -macx:CONFIG += c++11 - +CONFIG += c++11 DESTDIR = .. @@ -45,13 +41,33 @@ macx:QMAKE_CXXFLAGS += -stdlib=libc++ windows:QMAKE_CXXFLAGS += -DBOOST_USE_WINDOWS_H linux { - _R_HOME = $$(R_HOME) - isEmpty(_R_HOME):_R_HOME = /usr/lib/R - QMAKE_CXXFLAGS += -D\'R_HOME=\"$$_R_HOME\"\' + _R_HOME = $$(R_HOME) + isEmpty(_R_HOME):_R_HOME = /usr/lib/R + QMAKE_CXXFLAGS += -D\'R_HOME=\"$$_R_HOME\"\' } include(JASP-Desktop.pri) -HEADERS += +# List all pri files in the analysis +defineReplace(list_pri_files) { + FILES = $$files($$1) + PRI_FILES = + for(file, $$list($$FILES)) { + exists($$file) + { + PRI_FILES *= $$find(file, .*\.pri) + PRI_FILES *= $$list_pri_files($$file/*) + } + } + return($$PRI_FILES) +} -SOURCES += +# Directory containing the analysis forms +ANALYSIS_DIR = $$PWD/analysisforms +# Directory containing the modules +MODULES_DIR = $$list_pri_files($$ANALYSIS_DIR) + +# Include all the module pri files +for(file, $$list($$MODULES_DIR)) { + include($$file) +} diff --git a/JASP-Desktop/aboutdialog.cpp b/JASP-Desktop/aboutdialog.cpp index 9a0f433c7e..dbf5beec30 100755 --- a/JASP-Desktop/aboutdialog.cpp +++ b/JASP-Desktop/aboutdialog.cpp @@ -79,6 +79,9 @@ void AboutDialog::aboutPageLoaded(bool success) if (success) { QString version = tq(AppInfo::version.asString()); +#ifdef QT_DEBUG + version+="-Debug"; +#endif QString builddate = tq(AppInfo::builddate); ui->aboutView->page()->mainFrame()->evaluateJavaScript("window.setAppYear()"); ui->aboutView->page()->mainFrame()->evaluateJavaScript("window.setAppVersion('" + version +"')"); diff --git a/JASP-Desktop/aboutdialog.ui b/JASP-Desktop/aboutdialog.ui index 66b8bb9c3a..5a5b51b586 100755 --- a/JASP-Desktop/aboutdialog.ui +++ b/JASP-Desktop/aboutdialog.ui @@ -7,7 +7,7 @@ 0 0 800 - 400 + 470 diff --git a/JASP-Desktop/analysisforms/Common/Common.pri b/JASP-Desktop/analysisforms/Common/Common.pri new file mode 100644 index 0000000000..dcfb64ca50 --- /dev/null +++ b/JASP-Desktop/analysisforms/Common/Common.pri @@ -0,0 +1,104 @@ +SOURCES += \ + $$PWD/../../ribbons/ribbonanalysis.cpp \ + $$PWD/ancovabayesianform.cpp \ + $$PWD/ancovaform.cpp \ + $$PWD/ancovamultivariateform.cpp \ + $$PWD/anovabayesianform.cpp \ + $$PWD/anovaform.cpp \ + $$PWD/anovamultivariateform.cpp \ + $$PWD/anovaonewayform.cpp \ + $$PWD/anovarepeatedmeasuresbayesianform.cpp \ + $$PWD/anovarepeatedmeasuresform.cpp \ + $$PWD/binomialtestbayesianform.cpp \ + $$PWD/binomialtestform.cpp \ + $$PWD/contingencytablesbayesianform.cpp \ + $$PWD/contingencytablesform.cpp \ + $$PWD/correlationbayesianform.cpp \ + $$PWD/correlationbayesianpairsform.cpp \ + $$PWD/correlationform.cpp \ + $$PWD/correlationpartialform.cpp \ + $$PWD/descriptivesform.cpp \ + $$PWD/exploratoryfactoranalysisform.cpp \ + $$PWD/principalcomponentanalysisform.cpp \ + $$PWD/regressionlinearbayesianform.cpp \ + $$PWD/regressionlinearform.cpp \ + $$PWD/regressionlogisticform.cpp \ + $$PWD/regressionloglinearbayesianform.cpp \ + $$PWD/regressionloglinearform.cpp \ + $$PWD/reliabilityanalysisform.cpp \ + $$PWD/ttestbayesianindependentsamplesform.cpp \ + $$PWD/ttestbayesianonesampleform.cpp \ + $$PWD/ttestbayesianpairedsamplesform.cpp \ + $$PWD/ttestindependentsamplesform.cpp \ + $$PWD/ttestonesampleform.cpp \ + $$PWD/ttestpairedsamplesform.cpp + +HEADERS += \ + $$PWD/../../ribbons/ribbonanalysis.h \ + $$PWD/ancovabayesianform.h \ + $$PWD/ancovaform.h \ + $$PWD/ancovamultivariateform.h \ + $$PWD/anovabayesianform.h \ + $$PWD/anovaform.h \ + $$PWD/anovamultivariateform.h \ + $$PWD/anovaonewayform.h \ + $$PWD/anovarepeatedmeasuresbayesianform.h \ + $$PWD/anovarepeatedmeasuresform.h \ + $$PWD/binomialtestbayesianform.h \ + $$PWD/binomialtestform.h \ + $$PWD/contingencytablesbayesianform.h \ + $$PWD/contingencytablesform.h \ + $$PWD/correlationbayesianform.h \ + $$PWD/correlationbayesianpairsform.h \ + $$PWD/correlationform.h \ + $$PWD/correlationpartialform.h \ + $$PWD/descriptivesform.h \ + $$PWD/exploratoryfactoranalysisform.h \ + $$PWD/principalcomponentanalysisform.h \ + $$PWD/regressionlinearbayesianform.h \ + $$PWD/regressionlinearform.h \ + $$PWD/regressionlogisticform.h \ + $$PWD/regressionloglinearbayesianform.h \ + $$PWD/regressionloglinearform.h \ + $$PWD/reliabilityanalysisform.h \ + $$PWD/ttestbayesianindependentsamplesform.h \ + $$PWD/ttestbayesianonesampleform.h \ + $$PWD/ttestbayesianpairedsamplesform.h \ + $$PWD/ttestindependentsamplesform.h \ + $$PWD/ttestonesampleform.h \ + $$PWD/ttestpairedsamplesform.h + +FORMS += \ + $$PWD/../../ribbons/ribbonanalysis.ui \ + $$PWD/ancovabayesianform.ui \ + $$PWD/ancovaform.ui \ + $$PWD/ancovamultivariateform.ui \ + $$PWD/anovabayesianform.ui \ + $$PWD/anovaform.ui \ + $$PWD/anovamultivariateform.ui \ + $$PWD/anovaonewayform.ui \ + $$PWD/anovarepeatedmeasuresbayesianform.ui \ + $$PWD/anovarepeatedmeasuresform.ui \ + $$PWD/binomialtestbayesianform.ui \ + $$PWD/binomialtestform.ui \ + $$PWD/contingencytablesbayesianform.ui \ + $$PWD/contingencytablesform.ui \ + $$PWD/correlationbayesianform.ui \ + $$PWD/correlationbayesianpairsform.ui \ + $$PWD/correlationform.ui \ + $$PWD/correlationpartialform.ui \ + $$PWD/descriptivesform.ui \ + $$PWD/exploratoryfactoranalysisform.ui \ + $$PWD/principalcomponentanalysisform.ui \ + $$PWD/regressionlinearbayesianform.ui \ + $$PWD/regressionlinearform.ui \ + $$PWD/regressionlogisticform.ui \ + $$PWD/regressionloglinearbayesianform.ui \ + $$PWD/regressionloglinearform.ui \ + $$PWD/reliabilityanalysisform.ui \ + $$PWD/ttestbayesianindependentsamplesform.ui \ + $$PWD/ttestbayesianonesampleform.ui \ + $$PWD/ttestbayesianpairedsamplesform.ui \ + $$PWD/ttestindependentsamplesform.ui \ + $$PWD/ttestonesampleform.ui \ + $$PWD/ttestpairedsamplesform.ui diff --git a/JASP-Desktop/analysisforms/ancovabayesianform.cpp b/JASP-Desktop/analysisforms/Common/ancovabayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/ancovabayesianform.cpp rename to JASP-Desktop/analysisforms/Common/ancovabayesianform.cpp diff --git a/JASP-Desktop/analysisforms/ancovabayesianform.h b/JASP-Desktop/analysisforms/Common/ancovabayesianform.h similarity index 98% rename from JASP-Desktop/analysisforms/ancovabayesianform.h rename to JASP-Desktop/analysisforms/Common/ancovabayesianform.h index baf816b89e..39ca868713 100644 --- a/JASP-Desktop/analysisforms/ancovabayesianform.h +++ b/JASP-Desktop/analysisforms/Common/ancovabayesianform.h @@ -19,7 +19,7 @@ #ifndef ANCOVABAYESIANFORM_H #define ANCOVABAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -31,13 +31,13 @@ class AncovaBayesianForm; class AncovaBayesianForm : public AnalysisForm { Q_OBJECT - + public: explicit AncovaBayesianForm(QWidget *parent = 0); ~AncovaBayesianForm(); void bindTo(Options *options, DataSet *dataSet) OVERRIDE; - + private: Ui::AncovaBayesianForm *ui; @@ -55,7 +55,7 @@ class AncovaBayesianForm : public AnalysisForm TableModelVariablesAssigned *_horizontalAxisTableModel; TableModelVariablesAssigned *_seperateLinesTableModel; TableModelVariablesAssigned *_seperatePlotsTableModel; - + private slots: void factorsChanging(); void factorsChanged(); diff --git a/JASP-Desktop/analysisforms/ancovabayesianform.ui b/JASP-Desktop/analysisforms/Common/ancovabayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ancovabayesianform.ui rename to JASP-Desktop/analysisforms/Common/ancovabayesianform.ui diff --git a/JASP-Desktop/analysisforms/ancovaform.cpp b/JASP-Desktop/analysisforms/Common/ancovaform.cpp similarity index 81% rename from JASP-Desktop/analysisforms/ancovaform.cpp rename to JASP-Desktop/analysisforms/Common/ancovaform.cpp index 8d04dfb659..5644a97e33 100644 --- a/JASP-Desktop/analysisforms/ancovaform.cpp +++ b/JASP-Desktop/analysisforms/Common/ancovaform.cpp @@ -107,9 +107,30 @@ AncovaForm::AncovaForm(QWidget *parent) : ui->buttonAssignSeperateLines->setSourceAndTarget(ui->plotVariables, ui->plotSeparateLines); ui->buttonAssignSeperatePlots->setSourceAndTarget(ui->plotVariables, ui->plotSeparatePlots); + _simpleEffectsAvailableTableModel = new TableModelVariablesAvailable(); + _simpleEffectsAvailableTableModel->setInfoProvider(this); + ui->simpleEffectsVariables->setModel(_simpleEffectsAvailableTableModel); + + _simpleFactorTableModel = new TableModelVariablesAssigned(this); + _simpleFactorTableModel->setSource(_simpleEffectsAvailableTableModel); + ui->simpleFactor->setModel(_simpleFactorTableModel); + + _moderatorOneTableModel = new TableModelVariablesAssigned(this); + _moderatorOneTableModel->setSource(_simpleEffectsAvailableTableModel); + ui->moderatorFactorOne->setModel(_moderatorOneTableModel); + + _moderatorTwoTableModel = new TableModelVariablesAssigned(this); + _moderatorTwoTableModel->setSource(_simpleEffectsAvailableTableModel); + ui->moderatorFactorTwo->setModel(_moderatorTwoTableModel); + + ui->buttonAssignSimpleFactor->setSourceAndTarget(ui->simpleEffectsVariables, ui->simpleFactor); + ui->buttonAssignModeratorOne->setSourceAndTarget(ui->simpleEffectsVariables, ui->moderatorFactorOne); + ui->buttonAssignModeratorTwo->setSourceAndTarget(ui->simpleEffectsVariables, ui->moderatorFactorTwo); + ui->containerModel->hide(); ui->containerFactors->hide(); ui->containerOptions->hide(); + ui->containerSimpleEffect->hide(); ui->containerPostHocTests->hide(); ui->containerDescriptivesPlot->hide(); ui->containerAssumptions->hide(); @@ -161,7 +182,8 @@ void AncovaForm::factorsChanged() factorsAvailable.add(_randomFactorsListModel->assigned()); _contrastsModel->setVariables(factorsAvailable); - _plotFactorsAvailableTableModel->setVariables(factorsAvailable); + _plotFactorsAvailableTableModel->setVariables(factorsAvailable); + _simpleEffectsAvailableTableModel->setVariables(factorsAvailable); Terms plotVariablesAssigned; plotVariablesAssigned.add(_horizontalAxisTableModel->assigned()); @@ -169,7 +191,13 @@ void AncovaForm::factorsChanged() plotVariablesAssigned.add(_seperatePlotsTableModel->assigned()); _plotFactorsAvailableTableModel->notifyAlreadyAssigned(plotVariablesAssigned); - ui->postHocTestsVariables->setVariables(factorsAvailable); + Terms simpleEffectsVariablesAssigned; + simpleEffectsVariablesAssigned.add(_simpleFactorTableModel->assigned()); + simpleEffectsVariablesAssigned.add(_moderatorOneTableModel->assigned()); + simpleEffectsVariablesAssigned.add(_moderatorTwoTableModel->assigned()); + _simpleEffectsAvailableTableModel->notifyAlreadyAssigned(simpleEffectsVariablesAssigned); + + ui->postHocTestsVariables->setVariables(factorsAvailable); if (_options != NULL) _options->blockSignals(false); @@ -180,4 +208,5 @@ void AncovaForm::termsChanged() Terms terms = _anovaModel->terms(); terms.discardWhatDoesContainTheseComponents(_covariatesListModel->assigned()); ui->marginalMeansTerms->setVariables(terms); + } diff --git a/JASP-Desktop/analysisforms/ancovaform.h b/JASP-Desktop/analysisforms/Common/ancovaform.h similarity index 87% rename from JASP-Desktop/analysisforms/ancovaform.h rename to JASP-Desktop/analysisforms/Common/ancovaform.h index b6696b84cd..74b25df0e1 100644 --- a/JASP-Desktop/analysisforms/ancovaform.h +++ b/JASP-Desktop/analysisforms/Common/ancovaform.h @@ -19,7 +19,7 @@ #ifndef ANCOVAFORM_H #define ANCOVAFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -32,13 +32,13 @@ class AncovaForm; class AncovaForm : public AnalysisForm { Q_OBJECT - + public: explicit AncovaForm(QWidget *parent = 0); ~AncovaForm(); virtual void bindTo(Options *options, DataSet *dataSet) OVERRIDE; - + private slots: void factorsChanging(); void factorsChanged(); @@ -63,6 +63,11 @@ private slots: TableModelVariablesAssigned *_seperateLinesTableModel; TableModelVariablesAssigned *_seperatePlotsTableModel; + TableModelVariablesAvailable *_simpleEffectsAvailableTableModel; + TableModelVariablesAssigned *_simpleFactorTableModel; + TableModelVariablesAssigned *_moderatorOneTableModel; + TableModelVariablesAssigned *_moderatorTwoTableModel; + }; #endif // ANCOVAFORM_H diff --git a/JASP-Desktop/analysisforms/ancovaform.ui b/JASP-Desktop/analysisforms/Common/ancovaform.ui similarity index 81% rename from JASP-Desktop/analysisforms/ancovaform.ui rename to JASP-Desktop/analysisforms/Common/ancovaform.ui index 78e0bee12a..2e12892a6a 100644 --- a/JASP-Desktop/analysisforms/ancovaform.ui +++ b/JASP-Desktop/analysisforms/Common/ancovaform.ui @@ -1660,6 +1660,389 @@ + + + + 0 + + + 3 + + + 0 + + + 3 + + + + + + + + + 0 + + + 0 + + + 0 + + + 3 + + + 0 + + + 3 + + + + + + 0 + 0 + + + + Factors + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 3 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Simple effect factor + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Moderator factor 1 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Moderator factor 2 + + + + + + + + + + + + + + + + + 0 + 0 + + + + Simple Main Effects + + + + + + + Qt::Vertical diff --git a/JASP-Desktop/analysisforms/ancovamultivariateform.cpp b/JASP-Desktop/analysisforms/Common/ancovamultivariateform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/ancovamultivariateform.cpp rename to JASP-Desktop/analysisforms/Common/ancovamultivariateform.cpp diff --git a/JASP-Desktop/analysisforms/ancovamultivariateform.h b/JASP-Desktop/analysisforms/Common/ancovamultivariateform.h similarity index 98% rename from JASP-Desktop/analysisforms/ancovamultivariateform.h rename to JASP-Desktop/analysisforms/Common/ancovamultivariateform.h index 5f25550aa6..df12abd67b 100644 --- a/JASP-Desktop/analysisforms/ancovamultivariateform.h +++ b/JASP-Desktop/analysisforms/Common/ancovamultivariateform.h @@ -19,7 +19,7 @@ #ifndef ANCOVAMULTIVARIATEFORM_H #define ANCOVAMULTIVARIATEFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" diff --git a/JASP-Desktop/analysisforms/ancovamultivariateform.ui b/JASP-Desktop/analysisforms/Common/ancovamultivariateform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ancovamultivariateform.ui rename to JASP-Desktop/analysisforms/Common/ancovamultivariateform.ui diff --git a/JASP-Desktop/analysisforms/anovabayesianform.cpp b/JASP-Desktop/analysisforms/Common/anovabayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/anovabayesianform.cpp rename to JASP-Desktop/analysisforms/Common/anovabayesianform.cpp diff --git a/JASP-Desktop/analysisforms/anovabayesianform.h b/JASP-Desktop/analysisforms/Common/anovabayesianform.h similarity index 98% rename from JASP-Desktop/analysisforms/anovabayesianform.h rename to JASP-Desktop/analysisforms/Common/anovabayesianform.h index b7c82a0216..3f776ba088 100644 --- a/JASP-Desktop/analysisforms/anovabayesianform.h +++ b/JASP-Desktop/analysisforms/Common/anovabayesianform.h @@ -19,7 +19,7 @@ #ifndef ANOVABAYESIANFORM_H #define ANOVABAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -31,13 +31,13 @@ class AnovaBayesianForm; class AnovaBayesianForm : public AnalysisForm { Q_OBJECT - + public: explicit AnovaBayesianForm(QWidget *parent = 0); ~AnovaBayesianForm(); virtual void bindTo(Options *options, DataSet *dataSet) OVERRIDE; - + private: Ui::AnovaBayesianForm *ui; diff --git a/JASP-Desktop/analysisforms/anovabayesianform.ui b/JASP-Desktop/analysisforms/Common/anovabayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/anovabayesianform.ui rename to JASP-Desktop/analysisforms/Common/anovabayesianform.ui diff --git a/JASP-Desktop/analysisforms/anovaform.cpp b/JASP-Desktop/analysisforms/Common/anovaform.cpp similarity index 80% rename from JASP-Desktop/analysisforms/anovaform.cpp rename to JASP-Desktop/analysisforms/Common/anovaform.cpp index eb63ad8f9d..ac31be9159 100644 --- a/JASP-Desktop/analysisforms/anovaform.cpp +++ b/JASP-Desktop/analysisforms/Common/anovaform.cpp @@ -95,12 +95,35 @@ AnovaForm::AnovaForm(QWidget *parent) : ui->buttonAssignSeperateLines->setSourceAndTarget(ui->plotVariables, ui->plotSeparateLines); ui->buttonAssignSeperatePlots->setSourceAndTarget(ui->plotVariables, ui->plotSeparatePlots); + + _simpleEffectsAvailableTableModel = new TableModelVariablesAvailable(); + _simpleEffectsAvailableTableModel->setInfoProvider(this); + ui->simpleEffectsVariables->setModel(_simpleEffectsAvailableTableModel); + + _simpleFactorTableModel = new TableModelVariablesAssigned(this); + _simpleFactorTableModel->setSource(_simpleEffectsAvailableTableModel); + ui->simpleFactor->setModel(_simpleFactorTableModel); + + _moderatorOneTableModel = new TableModelVariablesAssigned(this); + _moderatorOneTableModel->setSource(_simpleEffectsAvailableTableModel); + ui->moderatorFactorOne->setModel(_moderatorOneTableModel); + + _moderatorTwoTableModel = new TableModelVariablesAssigned(this); + _moderatorTwoTableModel->setSource(_simpleEffectsAvailableTableModel); + ui->moderatorFactorTwo->setModel(_moderatorTwoTableModel); + + ui->buttonAssignSimpleFactor->setSourceAndTarget(ui->simpleEffectsVariables, ui->simpleFactor); + ui->buttonAssignModeratorOne->setSourceAndTarget(ui->simpleEffectsVariables, ui->moderatorFactorOne); + ui->buttonAssignModeratorTwo->setSourceAndTarget(ui->simpleEffectsVariables, ui->moderatorFactorTwo); + ui->containerModel->hide(); ui->containerFactors->hide(); ui->containerOptions->hide(); ui->containerPostHocTests->hide(); ui->containerDescriptivesPlot->hide(); ui->containerAssumptions->hide(); + ui->containerSimpleEffect->hide(); + ui->confidenceIntervalInterval->setLabel("Confidence interval"); @@ -148,6 +171,7 @@ void AnovaForm::factorsChanged() _contrastsModel->setVariables(factorsAvailable); _plotFactorsAvailableTableModel->setVariables(factorsAvailable); + _simpleEffectsAvailableTableModel->setVariables(factorsAvailable); Terms plotVariablesAssigned; plotVariablesAssigned.add(_horizontalAxisTableModel->assigned()); @@ -155,7 +179,14 @@ void AnovaForm::factorsChanged() plotVariablesAssigned.add(_seperatePlotsTableModel->assigned()); _plotFactorsAvailableTableModel->notifyAlreadyAssigned(plotVariablesAssigned); - ui->postHocTestsVariables->setVariables(factorsAvailable); + Terms simpleEffectsVariablesAssigned; + simpleEffectsVariablesAssigned.add(_simpleFactorTableModel->assigned()); + simpleEffectsVariablesAssigned.add(_moderatorOneTableModel->assigned()); + simpleEffectsVariablesAssigned.add(_moderatorTwoTableModel->assigned()); + _simpleEffectsAvailableTableModel->notifyAlreadyAssigned(simpleEffectsVariablesAssigned); + + ui->postHocTestsVariables->setVariables(factorsAvailable); + if (_options != NULL) _options->blockSignals(false); diff --git a/JASP-Desktop/analysisforms/anovaform.h b/JASP-Desktop/analysisforms/Common/anovaform.h similarity index 87% rename from JASP-Desktop/analysisforms/anovaform.h rename to JASP-Desktop/analysisforms/Common/anovaform.h index b8f5b4d569..dea6982e96 100644 --- a/JASP-Desktop/analysisforms/anovaform.h +++ b/JASP-Desktop/analysisforms/Common/anovaform.h @@ -19,7 +19,7 @@ #ifndef ANOVAFORM_H #define ANOVAFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -32,13 +32,13 @@ class AnovaForm; class AnovaForm : public AnalysisForm { Q_OBJECT - + public: explicit AnovaForm(QWidget *parent = 0); ~AnovaForm(); virtual void bindTo(Options *options, DataSet *dataSet) OVERRIDE; - + private slots: void factorsChanging(); void factorsChanged(); @@ -62,6 +62,11 @@ private slots: TableModelVariablesAssigned *_seperateLinesTableModel; TableModelVariablesAssigned *_seperatePlotsTableModel; + TableModelVariablesAvailable *_simpleEffectsAvailableTableModel; + TableModelVariablesAssigned *_simpleFactorTableModel; + TableModelVariablesAssigned *_moderatorOneTableModel; + TableModelVariablesAssigned *_moderatorTwoTableModel; + }; #endif // ANOVAFORM_H diff --git a/JASP-Desktop/analysisforms/anovaform.ui b/JASP-Desktop/analysisforms/Common/anovaform.ui similarity index 79% rename from JASP-Desktop/analysisforms/anovaform.ui rename to JASP-Desktop/analysisforms/Common/anovaform.ui index f710505317..026ed1f1b7 100644 --- a/JASP-Desktop/analysisforms/anovaform.ui +++ b/JASP-Desktop/analysisforms/Common/anovaform.ui @@ -1521,6 +1521,389 @@ + + + + 0 + + + 3 + + + 0 + + + 3 + + + + + + + + + 0 + + + 0 + + + 0 + + + 3 + + + 0 + + + 3 + + + + + + 0 + 0 + + + + Factors + + + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 3 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Simple effect factor + + + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Moderator factor 1 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 0 + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 35 + + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + + 50 + 16777215 + + + + + + + + + + + + 0 + 0 + + + + Moderator factor 2 + + + + + + + + + + + + + + + + + 0 + 0 + + + + Simple Main Effects + + + + + + + Qt::Vertical @@ -1534,6 +1917,7 @@ + groupSimpleEffect widget_14 widget_13 groupOptions @@ -1647,63 +2031,55 @@ _1confidenceInterval confidenceIntervalInterval _2standardError - expanderOptions - marginalMeansCompareMainEffects - marginalMeansCIAdjustment - descriptives - effectSizeEstimates - effectSizeEtaSquared - effectSizePartialEtaSquared - effectSizeOmegaSquared - VovkSellkeMPR + expanderOptionsSimpleEffects - marginalMeansCompareMainEffects + _1confidenceInterval toggled(bool) - widgetCIAdjustmentTypes + widgetConfidenceIntervalInterval setEnabled(bool) - 203 - 1494 + 120 + 1932 - 194 - 1523 + 120 + 1962 - effectSizeEstimates + marginalMeansCompareMainEffects toggled(bool) - widgetEffectSizeTypes + widgetCIAdjustmentTypes setEnabled(bool) - 122 - 1615 + 185 + 2346 - 119 - 1645 + 182 + 2377 - _1confidenceInterval + effectSizeEstimates toggled(bool) - widgetConfidenceIntervalInterval + widgetEffectSizeTypes setEnabled(bool) - 120 - 1932 + 139 + 2472 - 120 - 1962 + 142 + 2500 diff --git a/JASP-Desktop/analysisforms/anovamultivariateform.cpp b/JASP-Desktop/analysisforms/Common/anovamultivariateform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/anovamultivariateform.cpp rename to JASP-Desktop/analysisforms/Common/anovamultivariateform.cpp diff --git a/JASP-Desktop/analysisforms/anovamultivariateform.h b/JASP-Desktop/analysisforms/Common/anovamultivariateform.h similarity index 98% rename from JASP-Desktop/analysisforms/anovamultivariateform.h rename to JASP-Desktop/analysisforms/Common/anovamultivariateform.h index fe6b1e6f02..5c97d79e5d 100644 --- a/JASP-Desktop/analysisforms/anovamultivariateform.h +++ b/JASP-Desktop/analysisforms/Common/anovamultivariateform.h @@ -19,7 +19,7 @@ #ifndef ANOVAMULTIVARIATEFORM_H #define ANOVAMULTIVARIATEFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" diff --git a/JASP-Desktop/analysisforms/anovamultivariateform.ui b/JASP-Desktop/analysisforms/Common/anovamultivariateform.ui similarity index 100% rename from JASP-Desktop/analysisforms/anovamultivariateform.ui rename to JASP-Desktop/analysisforms/Common/anovamultivariateform.ui diff --git a/JASP-Desktop/analysisforms/anovaonewayform.cpp b/JASP-Desktop/analysisforms/Common/anovaonewayform.cpp similarity index 99% rename from JASP-Desktop/analysisforms/anovaonewayform.cpp rename to JASP-Desktop/analysisforms/Common/anovaonewayform.cpp index 14dc4cacd2..b0a64a3b95 100644 --- a/JASP-Desktop/analysisforms/anovaonewayform.cpp +++ b/JASP-Desktop/analysisforms/Common/anovaonewayform.cpp @@ -19,8 +19,6 @@ #include "anovaonewayform.h" #include "ui_anovaonewayform.h" -#include "analysisform.h" - AnovaOneWayForm::AnovaOneWayForm(QWidget *parent) : AnalysisForm("AnovaOneWayForm", parent), ui(new Ui::AnovaOneWayForm) diff --git a/JASP-Desktop/analysisforms/anovaonewayform.h b/JASP-Desktop/analysisforms/Common/anovaonewayform.h similarity index 97% rename from JASP-Desktop/analysisforms/anovaonewayform.h rename to JASP-Desktop/analysisforms/Common/anovaonewayform.h index 01fa8cdb40..7f9dddcd44 100644 --- a/JASP-Desktop/analysisforms/anovaonewayform.h +++ b/JASP-Desktop/analysisforms/Common/anovaonewayform.h @@ -22,7 +22,7 @@ #include "options/options.h" #include "dataset.h" -#include "analysisform.h" +#include "../analysisform.h" #include "availablefields.h" #include "widgets/tablemodelcontrasts.h" @@ -34,7 +34,7 @@ class AnovaOneWayForm; class AnovaOneWayForm : public AnalysisForm { Q_OBJECT - + public: explicit AnovaOneWayForm(QWidget *parent = 0); ~AnovaOneWayForm(); diff --git a/JASP-Desktop/analysisforms/anovaonewayform.ui b/JASP-Desktop/analysisforms/Common/anovaonewayform.ui similarity index 100% rename from JASP-Desktop/analysisforms/anovaonewayform.ui rename to JASP-Desktop/analysisforms/Common/anovaonewayform.ui diff --git a/JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.cpp b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.cpp rename to JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.cpp diff --git a/JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.h b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.h similarity index 98% rename from JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.h rename to JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.h index 9e6ebbea80..524aad5ab3 100644 --- a/JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.h +++ b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.h @@ -19,7 +19,7 @@ #ifndef ANOVAREPEATEDMEASURESBAYESIANFORM_H #define ANOVAREPEATEDMEASURESBAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -34,13 +34,13 @@ class AnovaRepeatedMeasuresBayesianForm; class AnovaRepeatedMeasuresBayesianForm : public AnalysisForm { Q_OBJECT - + public: explicit AnovaRepeatedMeasuresBayesianForm(QWidget *parent = 0); ~AnovaRepeatedMeasuresBayesianForm(); virtual void bindTo(Options *options, DataSet *dataSet) OVERRIDE; - + private slots: void withinSubjectsDesignChanged(); diff --git a/JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.ui b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/anovarepeatedmeasuresbayesianform.ui rename to JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresbayesianform.ui diff --git a/JASP-Desktop/analysisforms/anovarepeatedmeasuresform.cpp b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/anovarepeatedmeasuresform.cpp rename to JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.cpp diff --git a/JASP-Desktop/analysisforms/anovarepeatedmeasuresform.h b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.h similarity index 98% rename from JASP-Desktop/analysisforms/anovarepeatedmeasuresform.h rename to JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.h index e118934acf..4e1acc96a5 100644 --- a/JASP-Desktop/analysisforms/anovarepeatedmeasuresform.h +++ b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.h @@ -19,7 +19,7 @@ #ifndef ANOVAREPEATEDMEASURESFORM_H #define ANOVAREPEATEDMEASURESFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -34,13 +34,13 @@ class AnovaRepeatedMeasuresForm; class AnovaRepeatedMeasuresForm : public AnalysisForm { Q_OBJECT - + public: explicit AnovaRepeatedMeasuresForm(QWidget *parent = 0); ~AnovaRepeatedMeasuresForm(); virtual void bindTo(Options *options, DataSet *dataSet) OVERRIDE; - + private slots: void factorsChanging(); void factorsChanged(bool changed = true); diff --git a/JASP-Desktop/analysisforms/anovarepeatedmeasuresform.ui b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.ui similarity index 99% rename from JASP-Desktop/analysisforms/anovarepeatedmeasuresform.ui rename to JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.ui index c550ed3edf..8905574305 100644 --- a/JASP-Desktop/analysisforms/anovarepeatedmeasuresform.ui +++ b/JASP-Desktop/analysisforms/Common/anovarepeatedmeasuresform.ui @@ -773,6 +773,27 @@ + + + + 12 + + + + + Effect size + + + + + + + Pool error term for RM factors + + + + + @@ -816,20 +837,6 @@ - - - - 12 - - - - - Effect size - - - - - @@ -1243,14 +1250,14 @@ - Standard error + Standard &error - Confidence interval + Confidence &interval @@ -1742,7 +1749,6 @@ expanderContrasts contrasts expanderPosthoc - postHocTestEffectSize postHocTestsBonferroni postHocTestsHolm postHocTestsTukey diff --git a/JASP-Desktop/analysisforms/binomialtestbayesianform.cpp b/JASP-Desktop/analysisforms/Common/binomialtestbayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/binomialtestbayesianform.cpp rename to JASP-Desktop/analysisforms/Common/binomialtestbayesianform.cpp diff --git a/JASP-Desktop/analysisforms/binomialtestbayesianform.h b/JASP-Desktop/analysisforms/Common/binomialtestbayesianform.h similarity index 97% rename from JASP-Desktop/analysisforms/binomialtestbayesianform.h rename to JASP-Desktop/analysisforms/Common/binomialtestbayesianform.h index 84d9da300d..ca5d481de6 100644 --- a/JASP-Desktop/analysisforms/binomialtestbayesianform.h +++ b/JASP-Desktop/analysisforms/Common/binomialtestbayesianform.h @@ -19,7 +19,7 @@ #ifndef BINOMIALTESTBAYESIANFORM_H #define BINOMIALTESTBAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class BinomialTestBayesianForm; diff --git a/JASP-Desktop/analysisforms/binomialtestbayesianform.ui b/JASP-Desktop/analysisforms/Common/binomialtestbayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/binomialtestbayesianform.ui rename to JASP-Desktop/analysisforms/Common/binomialtestbayesianform.ui diff --git a/JASP-Desktop/analysisforms/binomialtestform.cpp b/JASP-Desktop/analysisforms/Common/binomialtestform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/binomialtestform.cpp rename to JASP-Desktop/analysisforms/Common/binomialtestform.cpp diff --git a/JASP-Desktop/analysisforms/binomialtestform.h b/JASP-Desktop/analysisforms/Common/binomialtestform.h similarity index 97% rename from JASP-Desktop/analysisforms/binomialtestform.h rename to JASP-Desktop/analysisforms/Common/binomialtestform.h index b59b18b517..f0fc3f540b 100644 --- a/JASP-Desktop/analysisforms/binomialtestform.h +++ b/JASP-Desktop/analysisforms/Common/binomialtestform.h @@ -19,7 +19,7 @@ #ifndef BINOMIALTESTFORM_H #define BINOMIALTESTFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class BinomialTestForm; diff --git a/JASP-Desktop/analysisforms/binomialtestform.ui b/JASP-Desktop/analysisforms/Common/binomialtestform.ui similarity index 100% rename from JASP-Desktop/analysisforms/binomialtestform.ui rename to JASP-Desktop/analysisforms/Common/binomialtestform.ui diff --git a/JASP-Desktop/analysisforms/contingencytablesbayesianform.cpp b/JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/contingencytablesbayesianform.cpp rename to JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.cpp diff --git a/JASP-Desktop/analysisforms/contingencytablesbayesianform.h b/JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.h similarity index 98% rename from JASP-Desktop/analysisforms/contingencytablesbayesianform.h rename to JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.h index 34b6e76569..0b74f27064 100644 --- a/JASP-Desktop/analysisforms/contingencytablesbayesianform.h +++ b/JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.h @@ -20,7 +20,7 @@ #define CONTINGENCYTABLESBAYESIANFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariableslevels.h" namespace Ui { diff --git a/JASP-Desktop/analysisforms/contingencytablesbayesianform.ui b/JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/contingencytablesbayesianform.ui rename to JASP-Desktop/analysisforms/Common/contingencytablesbayesianform.ui diff --git a/JASP-Desktop/analysisforms/contingencytablesform.cpp b/JASP-Desktop/analysisforms/Common/contingencytablesform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/contingencytablesform.cpp rename to JASP-Desktop/analysisforms/Common/contingencytablesform.cpp diff --git a/JASP-Desktop/analysisforms/contingencytablesform.h b/JASP-Desktop/analysisforms/Common/contingencytablesform.h similarity index 97% rename from JASP-Desktop/analysisforms/contingencytablesform.h rename to JASP-Desktop/analysisforms/Common/contingencytablesform.h index a4bebbe0a9..68507bb3ec 100644 --- a/JASP-Desktop/analysisforms/contingencytablesform.h +++ b/JASP-Desktop/analysisforms/Common/contingencytablesform.h @@ -20,7 +20,7 @@ #define CONTINGENCYTABLESFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariableslevels.h" namespace Ui { diff --git a/JASP-Desktop/analysisforms/contingencytablesform.ui b/JASP-Desktop/analysisforms/Common/contingencytablesform.ui similarity index 100% rename from JASP-Desktop/analysisforms/contingencytablesform.ui rename to JASP-Desktop/analysisforms/Common/contingencytablesform.ui diff --git a/JASP-Desktop/analysisforms/correlationbayesianform.cpp b/JASP-Desktop/analysisforms/Common/correlationbayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/correlationbayesianform.cpp rename to JASP-Desktop/analysisforms/Common/correlationbayesianform.cpp diff --git a/JASP-Desktop/analysisforms/correlationbayesianform.h b/JASP-Desktop/analysisforms/Common/correlationbayesianform.h similarity index 97% rename from JASP-Desktop/analysisforms/correlationbayesianform.h rename to JASP-Desktop/analysisforms/Common/correlationbayesianform.h index f108b05837..3eeaf833ca 100644 --- a/JASP-Desktop/analysisforms/correlationbayesianform.h +++ b/JASP-Desktop/analysisforms/Common/correlationbayesianform.h @@ -19,7 +19,7 @@ #ifndef CORRELATIONBAYESIANFORM_H #define CORRELATIONBAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" namespace Ui { diff --git a/JASP-Desktop/analysisforms/correlationbayesianform.ui b/JASP-Desktop/analysisforms/Common/correlationbayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/correlationbayesianform.ui rename to JASP-Desktop/analysisforms/Common/correlationbayesianform.ui diff --git a/JASP-Desktop/analysisforms/correlationbayesianpairsform.cpp b/JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/correlationbayesianpairsform.cpp rename to JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.cpp diff --git a/JASP-Desktop/analysisforms/correlationbayesianpairsform.h b/JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.h similarity index 97% rename from JASP-Desktop/analysisforms/correlationbayesianpairsform.h rename to JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.h index efb32391b7..ed511884c0 100644 --- a/JASP-Desktop/analysisforms/correlationbayesianpairsform.h +++ b/JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.h @@ -19,7 +19,7 @@ #ifndef CORRELATIONBAYESIANPAIRSFORM_H #define CORRELATIONBAYESIANPAIRSFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class CorrelationBayesianPairsForm; @@ -28,11 +28,11 @@ class CorrelationBayesianPairsForm; class CorrelationBayesianPairsForm : public AnalysisForm { Q_OBJECT - + public: explicit CorrelationBayesianPairsForm(QWidget *parent = 0); ~CorrelationBayesianPairsForm(); - + private: Ui::CorrelationBayesianPairsForm *ui; }; diff --git a/JASP-Desktop/analysisforms/correlationbayesianpairsform.ui b/JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.ui similarity index 100% rename from JASP-Desktop/analysisforms/correlationbayesianpairsform.ui rename to JASP-Desktop/analysisforms/Common/correlationbayesianpairsform.ui diff --git a/JASP-Desktop/analysisforms/correlationform.cpp b/JASP-Desktop/analysisforms/Common/correlationform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/correlationform.cpp rename to JASP-Desktop/analysisforms/Common/correlationform.cpp diff --git a/JASP-Desktop/analysisforms/correlationform.h b/JASP-Desktop/analysisforms/Common/correlationform.h similarity index 97% rename from JASP-Desktop/analysisforms/correlationform.h rename to JASP-Desktop/analysisforms/Common/correlationform.h index 43f776c8f5..048e1dd48e 100644 --- a/JASP-Desktop/analysisforms/correlationform.h +++ b/JASP-Desktop/analysisforms/Common/correlationform.h @@ -19,7 +19,7 @@ #ifndef CORRELATIONFORM_H #define CORRELATIONFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" namespace Ui { diff --git a/JASP-Desktop/analysisforms/correlationform.ui b/JASP-Desktop/analysisforms/Common/correlationform.ui similarity index 100% rename from JASP-Desktop/analysisforms/correlationform.ui rename to JASP-Desktop/analysisforms/Common/correlationform.ui diff --git a/JASP-Desktop/analysisforms/correlationpartialform.cpp b/JASP-Desktop/analysisforms/Common/correlationpartialform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/correlationpartialform.cpp rename to JASP-Desktop/analysisforms/Common/correlationpartialform.cpp diff --git a/JASP-Desktop/analysisforms/correlationpartialform.h b/JASP-Desktop/analysisforms/Common/correlationpartialform.h similarity index 97% rename from JASP-Desktop/analysisforms/correlationpartialform.h rename to JASP-Desktop/analysisforms/Common/correlationpartialform.h index 4d8e005298..1052ce8d4a 100644 --- a/JASP-Desktop/analysisforms/correlationpartialform.h +++ b/JASP-Desktop/analysisforms/Common/correlationpartialform.h @@ -20,7 +20,7 @@ #define CORRELATIONPARTIALFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class CorrelationPartialForm; diff --git a/JASP-Desktop/analysisforms/correlationpartialform.ui b/JASP-Desktop/analysisforms/Common/correlationpartialform.ui similarity index 100% rename from JASP-Desktop/analysisforms/correlationpartialform.ui rename to JASP-Desktop/analysisforms/Common/correlationpartialform.ui diff --git a/JASP-Desktop/analysisforms/descriptivesform.cpp b/JASP-Desktop/analysisforms/Common/descriptivesform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/descriptivesform.cpp rename to JASP-Desktop/analysisforms/Common/descriptivesform.cpp diff --git a/JASP-Desktop/analysisforms/descriptivesform.h b/JASP-Desktop/analysisforms/Common/descriptivesform.h similarity index 97% rename from JASP-Desktop/analysisforms/descriptivesform.h rename to JASP-Desktop/analysisforms/Common/descriptivesform.h index 3f8db9abb9..86d06a4f5c 100644 --- a/JASP-Desktop/analysisforms/descriptivesform.h +++ b/JASP-Desktop/analysisforms/Common/descriptivesform.h @@ -21,7 +21,7 @@ #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class DescriptivesForm; @@ -30,7 +30,7 @@ class DescriptivesForm; class DescriptivesForm : public AnalysisForm { Q_OBJECT - + public: explicit DescriptivesForm(QWidget *parent = 0); ~DescriptivesForm(); diff --git a/JASP-Desktop/analysisforms/descriptivesform.ui b/JASP-Desktop/analysisforms/Common/descriptivesform.ui similarity index 100% rename from JASP-Desktop/analysisforms/descriptivesform.ui rename to JASP-Desktop/analysisforms/Common/descriptivesform.ui diff --git a/JASP-Desktop/analysisforms/exploratoryfactoranalysisform.cpp b/JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.cpp similarity index 99% rename from JASP-Desktop/analysisforms/exploratoryfactoranalysisform.cpp rename to JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.cpp index 6c51f7a9a6..d89a734503 100644 --- a/JASP-Desktop/analysisforms/exploratoryfactoranalysisform.cpp +++ b/JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.cpp @@ -19,7 +19,6 @@ #include "exploratoryfactoranalysisform.h" #include "ui_exploratoryfactoranalysisform.h" -#include "analysisform.h" ExploratoryFactorAnalysisForm::ExploratoryFactorAnalysisForm(QWidget *parent) : AnalysisForm("ExploratoryFactorAnalysisForm", parent), diff --git a/JASP-Desktop/analysisforms/exploratoryfactoranalysisform.h b/JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.h similarity index 97% rename from JASP-Desktop/analysisforms/exploratoryfactoranalysisform.h rename to JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.h index 7cd7201778..e1184ed505 100644 --- a/JASP-Desktop/analysisforms/exploratoryfactoranalysisform.h +++ b/JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.h @@ -20,7 +20,7 @@ #define EXPLORATORYFACTORANALYSISFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class ExploratoryFactorAnalysisForm; @@ -29,18 +29,18 @@ class ExploratoryFactorAnalysisForm; class ExploratoryFactorAnalysisForm : public AnalysisForm { Q_OBJECT - + public: explicit ExploratoryFactorAnalysisForm(QWidget *parent = 0); ~ExploratoryFactorAnalysisForm(); - + private: Ui::ExploratoryFactorAnalysisForm *ui; - + private slots: void HandleSlider(int i); void HandleLineEdit(QString s); - + }; diff --git a/JASP-Desktop/analysisforms/exploratoryfactoranalysisform.ui b/JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.ui similarity index 100% rename from JASP-Desktop/analysisforms/exploratoryfactoranalysisform.ui rename to JASP-Desktop/analysisforms/Common/exploratoryfactoranalysisform.ui diff --git a/JASP-Desktop/analysisforms/principalcomponentanalysisform.cpp b/JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.cpp similarity index 99% rename from JASP-Desktop/analysisforms/principalcomponentanalysisform.cpp rename to JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.cpp index b0f7464d7f..2aa602eab5 100644 --- a/JASP-Desktop/analysisforms/principalcomponentanalysisform.cpp +++ b/JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.cpp @@ -19,8 +19,6 @@ #include "principalcomponentanalysisform.h" #include "ui_principalcomponentanalysisform.h" -#include "analysisform.h" - PrincipalComponentAnalysisForm::PrincipalComponentAnalysisForm(QWidget *parent) : AnalysisForm("PrincipalComponentAnalysisForm", parent), ui(new Ui::PrincipalComponentAnalysisForm) diff --git a/JASP-Desktop/analysisforms/principalcomponentanalysisform.h b/JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.h similarity index 97% rename from JASP-Desktop/analysisforms/principalcomponentanalysisform.h rename to JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.h index f259d937d4..fc881d0b20 100644 --- a/JASP-Desktop/analysisforms/principalcomponentanalysisform.h +++ b/JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.h @@ -20,7 +20,7 @@ #define PRINCIPALCOMPONENTANALYSISFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class PrincipalComponentAnalysisForm; @@ -29,18 +29,18 @@ class PrincipalComponentAnalysisForm; class PrincipalComponentAnalysisForm : public AnalysisForm { Q_OBJECT - + public: explicit PrincipalComponentAnalysisForm(QWidget *parent = 0); ~PrincipalComponentAnalysisForm(); - + private: Ui::PrincipalComponentAnalysisForm *ui; - + private slots: void HandleSlider(int i); void HandleLineEdit(QString s); - + }; diff --git a/JASP-Desktop/analysisforms/principalcomponentanalysisform.ui b/JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.ui similarity index 100% rename from JASP-Desktop/analysisforms/principalcomponentanalysisform.ui rename to JASP-Desktop/analysisforms/Common/principalcomponentanalysisform.ui diff --git a/JASP-Desktop/analysisforms/regressionlinearbayesianform.cpp b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/regressionlinearbayesianform.cpp rename to JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.cpp diff --git a/JASP-Desktop/analysisforms/regressionlinearbayesianform.h b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.h similarity index 98% rename from JASP-Desktop/analysisforms/regressionlinearbayesianform.h rename to JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.h index ad4ce7a6ee..9a72bc465c 100644 --- a/JASP-Desktop/analysisforms/regressionlinearbayesianform.h +++ b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.h @@ -19,7 +19,7 @@ #ifndef REGRESSIONLINEARBAYESIANFORM_H #define REGRESSIONLINEARBAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -31,7 +31,7 @@ class RegressionLinearBayesianForm; class RegressionLinearBayesianForm : public AnalysisForm { Q_OBJECT - + public: explicit RegressionLinearBayesianForm(QWidget *parent = 0); ~RegressionLinearBayesianForm(); @@ -41,7 +41,7 @@ class RegressionLinearBayesianForm : public AnalysisForm private slots: void factorsChanging(); void factorsChanged(); - + private: Ui::RegressionLinearBayesianForm *ui; diff --git a/JASP-Desktop/analysisforms/regressionlinearbayesianform.ui b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/regressionlinearbayesianform.ui rename to JASP-Desktop/analysisforms/Common/regressionlinearbayesianform.ui diff --git a/JASP-Desktop/analysisforms/basregressionlinearlinkform.cpp b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.cpp similarity index 65% rename from JASP-Desktop/analysisforms/basregressionlinearlinkform.cpp rename to JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.cpp index c1ca11edcc..eee64340d4 100644 --- a/JASP-Desktop/analysisforms/basregressionlinearlinkform.cpp +++ b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.cpp @@ -16,13 +16,13 @@ // . // -#include "basregressionlinearlinkform.h" -#include "ui_basregressionlinearlinkform.h" +#include "regressionlinearbayesianform.h" +#include "ui_regressionlinearbayesianform.h" -BASRegressionLinearLinkForm::BASRegressionLinearLinkForm(QWidget *parent) : - AnalysisForm("BASRegressionLinearLinkForm", parent), - ui(new Ui::BASRegressionLinearLinkForm) +RegressionLinearBayesianForm::RegressionLinearBayesianForm(QWidget *parent) : + AnalysisForm("RegressionLinearBayesianForm", parent), + ui(new Ui::RegressionLinearBayesianForm) { ui->setupUi(this); @@ -82,46 +82,50 @@ BASRegressionLinearLinkForm::BASRegressionLinearLinkForm(QWidget *parent) : retain.setRetainSizeWhenHidden(true); ui->bernoulliParam->setSizePolicy(retain); - retain = ui->gPriorParameter->sizePolicy(); + retain = ui->alpha->sizePolicy(); retain.setRetainSizeWhenHidden(true); - ui->gPriorParameter->setSizePolicy(retain); + ui->alpha->setSizePolicy(retain); + + retain = ui->rScale->sizePolicy(); + retain.setRetainSizeWhenHidden(true); + ui->rScale->setSizePolicy(retain); defaultOptions(); } -BASRegressionLinearLinkForm::~BASRegressionLinearLinkForm() +RegressionLinearBayesianForm::~RegressionLinearBayesianForm() { delete ui; } -void BASRegressionLinearLinkForm::defaultOptions() +void RegressionLinearBayesianForm::defaultOptions() { // default behaviour: hide the number of iterations for MCMC ui->label_iterationsMCMC->hide(); ui->iterationsMCMC->hide(); - // hide the g prior parameter, alpha - ui->label_gPriorParameter->hide(); - ui->gPriorParameter->hide(); + // hide the alpha parameter + ui->label_alpha->hide(); + ui->alpha->hide(); // default behaviour: show beta binomial parameters, hide bernoulli params defaultOptionsModelPrior(); } -void BASRegressionLinearLinkForm::defaultOptionsModelPrior() +void RegressionLinearBayesianForm::defaultOptionsModelPrior() { - ui->label_betaBinomialParamA->show(); - ui->label_betaBinomialParamB->show(); - ui->betaBinomialParamA->show(); - ui->betaBinomialParamB->show(); + ui->label_betaBinomialParamA->hide(); + ui->label_betaBinomialParamB->hide(); + ui->betaBinomialParamA->hide(); + ui->betaBinomialParamB->hide(); ui->label_bernoulliParam->hide(); ui->bernoulliParam->hide(); } -void BASRegressionLinearLinkForm::bindTo(Options *options, DataSet *dataSet) +void RegressionLinearBayesianForm::bindTo(Options *options, DataSet *dataSet) { AnalysisForm::bindTo(options, dataSet); @@ -133,7 +137,7 @@ void BASRegressionLinearLinkForm::bindTo(Options *options, DataSet *dataSet) } -void BASRegressionLinearLinkForm::on_BAS_clicked() +void RegressionLinearBayesianForm::on_BAS_clicked() { ui->label_numberOfModels->show(); ui->numberOfModels->show(); @@ -142,7 +146,7 @@ void BASRegressionLinearLinkForm::on_BAS_clicked() } -void BASRegressionLinearLinkForm::on_MCMC_clicked() +void RegressionLinearBayesianForm::on_MCMC_clicked() { ui->label_numberOfModels->hide(); ui->numberOfModels->hide(); @@ -151,25 +155,21 @@ void BASRegressionLinearLinkForm::on_MCMC_clicked() } -void BASRegressionLinearLinkForm::on_MCMCBAS_clicked() -{ - ui->label_numberOfModels->show(); - ui->numberOfModels->show(); - ui->label_iterationsMCMC->show(); - ui->iterationsMCMC->show(); -} - - -void BASRegressionLinearLinkForm::on_betaBinomial_clicked() +void RegressionLinearBayesianForm::on_betaBinomial_clicked() { if (ui->betaBinomial->isChecked()) { - defaultOptionsModelPrior(); + ui->label_betaBinomialParamA->show(); + ui->label_betaBinomialParamB->show(); + ui->betaBinomialParamA->show(); + ui->betaBinomialParamB->show(); + ui->label_bernoulliParam->hide(); + ui->bernoulliParam->hide(); } } -void BASRegressionLinearLinkForm::on_Bernoulli_clicked() +void RegressionLinearBayesianForm::on_Bernoulli_clicked() { if (ui->Bernoulli->isChecked()) { @@ -183,7 +183,7 @@ void BASRegressionLinearLinkForm::on_Bernoulli_clicked() } -void BASRegressionLinearLinkForm::on_uniformPrior_clicked() +void RegressionLinearBayesianForm::on_uniformPrior_clicked() { if (ui->uniformPrior->isChecked()) { @@ -196,71 +196,86 @@ void BASRegressionLinearLinkForm::on_uniformPrior_clicked() } } +void RegressionLinearBayesianForm::defaultOptionsPriorParams() { + ui->label_alpha->hide(); + ui->alpha->hide(); + ui->label_rScale->hide(); + ui->rScale->hide(); +} + +void RegressionLinearBayesianForm::on_g_prior_clicked() +{ + defaultOptionsPriorParams(); +} -void BASRegressionLinearLinkForm::on_g_prior_clicked() +void RegressionLinearBayesianForm::on_jzs_clicked() { - ui->label_gPriorParameter->show(); - ui->gPriorParameter->show(); + ui->label_alpha->hide(); + ui->alpha->hide(); + ui->label_rScale->show(); + ui->rScale->show(); } -void BASRegressionLinearLinkForm::on_hyper_g_clicked() +void RegressionLinearBayesianForm::on_hyper_g_clicked() { - ui->label_gPriorParameter->show(); - ui->gPriorParameter->show(); + ui->label_alpha->show(); + ui->alpha->show(); + ui->label_rScale->hide(); + ui->rScale->hide(); } -void BASRegressionLinearLinkForm::on_hyper_g_laplace_clicked() +void RegressionLinearBayesianForm::on_hyper_g_laplace_clicked() { - ui->label_gPriorParameter->show(); - ui->gPriorParameter->show(); + ui->label_alpha->show(); + ui->alpha->show(); + ui->label_rScale->hide(); + ui->rScale->hide(); } -void BASRegressionLinearLinkForm::on_hyper_g_n_clicked() +void RegressionLinearBayesianForm::on_hyper_g_n_clicked() { - ui->label_gPriorParameter->show(); - ui->gPriorParameter->show(); + ui->label_alpha->show(); + ui->alpha->show(); + ui->label_rScale->hide(); + ui->rScale->hide(); } -void BASRegressionLinearLinkForm::on_aic_clicked() +void RegressionLinearBayesianForm::on_aic_clicked() { - ui->label_gPriorParameter->hide(); - ui->gPriorParameter->hide(); + defaultOptionsPriorParams(); } -void BASRegressionLinearLinkForm::on_bic_clicked() +void RegressionLinearBayesianForm::on_bic_clicked() { - ui->label_gPriorParameter->hide(); - ui->gPriorParameter->hide(); + defaultOptionsPriorParams(); } -void BASRegressionLinearLinkForm::on_eb_global_clicked() +void RegressionLinearBayesianForm::on_eb_global_clicked() { - ui->label_gPriorParameter->hide(); - ui->gPriorParameter->hide(); + defaultOptionsPriorParams(); } -void BASRegressionLinearLinkForm::on_eb_local_clicked() +void RegressionLinearBayesianForm::on_eb_local_clicked() { - ui->label_gPriorParameter->hide(); - ui->gPriorParameter->hide(); + defaultOptionsPriorParams(); } -void BASRegressionLinearLinkForm::factorsChanging() +void RegressionLinearBayesianForm::factorsChanging() { if (_options != NULL) _options->blockSignals(true); } -void BASRegressionLinearLinkForm::factorsChanged() +void RegressionLinearBayesianForm::factorsChanged() { if (_options != NULL) _options->blockSignals(false); diff --git a/JASP-Desktop/analysisforms/basregressionlinearlinkform.h b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.h similarity index 79% rename from JASP-Desktop/analysisforms/basregressionlinearlinkform.h rename to JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.h index bd71272a80..a40af0d847 100644 --- a/JASP-Desktop/analysisforms/basregressionlinearlinkform.h +++ b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.h @@ -16,10 +16,10 @@ // . // -#ifndef BASREGRESSIONLINEARLINKFORM_H -#define BASREGRESSIONLINEARLINKFORM_H +#ifndef REGRESSIONLINEARBAYESIANFORM_H +#define REGRESSIONLINEARBAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -29,26 +29,26 @@ namespace Ui { -class BASRegressionLinearLinkForm; +class RegressionLinearBayesianForm; } -class BASRegressionLinearLinkForm : public AnalysisForm +class RegressionLinearBayesianForm : public AnalysisForm { Q_OBJECT public: - explicit BASRegressionLinearLinkForm(QWidget *parent = 0); - ~BASRegressionLinearLinkForm(); + explicit RegressionLinearBayesianForm(QWidget *parent = 0); + ~RegressionLinearBayesianForm(); void defaultOptions(); void defaultOptionsModelPrior(); + void defaultOptionsPriorParams(); virtual void bindTo(Options *options, DataSet *dataSet) OVERRIDE; private slots: void on_BAS_clicked(); void on_MCMC_clicked(); - void on_MCMCBAS_clicked(); void on_betaBinomial_clicked(); void on_Bernoulli_clicked(); void on_uniformPrior_clicked(); @@ -56,6 +56,7 @@ private slots: void on_hyper_g_clicked(); void on_hyper_g_laplace_clicked(); void on_hyper_g_n_clicked(); + void on_jzs_clicked(); void on_aic_clicked(); void on_bic_clicked(); void on_eb_global_clicked(); @@ -64,7 +65,7 @@ private slots: void factorsChanged(); private: - Ui::BASRegressionLinearLinkForm *ui; + Ui::RegressionLinearBayesianForm *ui; TableModelVariablesAssigned *_dependentListModel; TableModelVariablesAssigned *_covariatesListModel; @@ -75,4 +76,4 @@ private slots: TableModelVariablesAvailable *_factorsAvailableListModel; }; -#endif // BASREGRESSIONLINEARLINKFORM_H +#endif // REGRESSIONLINEARBAYESIANFORM_H diff --git a/JASP-Desktop/analysisforms/basregressionlinearlinkform.ui b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.ui similarity index 90% rename from JASP-Desktop/analysisforms/basregressionlinearlinkform.ui rename to JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.ui index 6f59a6b787..9dce744eea 100644 --- a/JASP-Desktop/analysisforms/basregressionlinearlinkform.ui +++ b/JASP-Desktop/analysisforms/Common/regressionlinearbayesianform_BAS.ui @@ -1,7 +1,7 @@ - BASRegressionLinearLinkForm - + RegressionLinearBayesianForm + 0 @@ -71,20 +71,63 @@ 0 - - + + - Log marginal likelihoods + Descriptives - - + + + + + 0 + 0 + + + + + Best model + + + + + Most complex model + + + + + Median model + + + + + Model averaged + + + + + + - Descriptives + Posterior summary + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -132,7 +175,7 @@ - Limit shown models + Limit no. models shown @@ -147,31 +190,6 @@ 12 - - - - false - - - - 0 - 0 - - - - - 60 - 0 - - - - - 60 - 16777215 - - - - @@ -199,6 +217,31 @@ + + + + false + + + + 0 + 0 + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + @@ -315,7 +358,7 @@ - Posterior distributions + Averaged posterior distributions @@ -340,7 +383,7 @@ - Residuals vs fitted + Residuals vs. fitted @@ -362,14 +405,14 @@ - Log posterior odds + Posterior log odds - Model complexity + Log(P(data|M)) vs. model size @@ -696,174 +739,6 @@ 0 - - - - - 0 - 0 - - - - - 300 - 16777215 - - - - Prior - - - - QLayout::SetNoConstraint - - - 0 - - - 0 - - - - - g-prior - - - - - - - ZS-null - - - - - - - Hyper-g-Laplace - - - - - - - Hyper-g-n - - - - - - - EB-global - - - - - - - EB-&local - - - - - - - BIC - - - - - - - AIC - - - - - - - Hyper-g - - - - - - - - 0 - 0 - - - - - 60 - 0 - - - - - 60 - 16777215 - - - - - - - - ZS-full - - - - - - - Qt::Horizontal - - - - 293 - 20 - - - - - - - - alpha: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - @@ -923,7 +798,7 @@ - p: + p @@ -943,14 +818,14 @@ - b: + b - a: + a @@ -991,29 +866,8 @@ 0 - - - - MCMC samples - - - - - - - BAS - - - - - - - MCMC - - - - - + + 0 @@ -1034,15 +888,22 @@ - - + + + + BAS + + + + + - BAS + MCMC + No. models - + 0 @@ -1064,18 +925,218 @@ - + + + No. samples + + + + + - Number of models: + MCMC + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 300 + 16777215 + + + + Prior + + + + QLayout::SetNoConstraint + + + 0 + + + 0 + + + + + g-prior + + + + + + + JZS + + + + + + + Hyper-g-Laplace + + + + + + + Hyper-g-n + + + + + + + EB-global + + + + + + + EB-&local + + + + + + + BIC + + + + + + + AIC + + + + + + + Hyper-g + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + + + + + r scale + + + + + + + alpha + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 110 + 20 + + + + + + + @@ -1145,6 +1206,11 @@
widgets/anovamodelwidget.h
1 + + BoundComboBox + QComboBox +
widgets/boundcombobox.h
+
listAvailableFields @@ -1162,7 +1228,7 @@ numShownModels __1 __2 - logmarg + postSummary descriptives expanderModel_2 expanderModel @@ -1181,9 +1247,7 @@ hyper_g hyper_g_laplace hyper_g_n - zs_full - zs_null - gPriorParameter + jzs betaBinomial betaBinomialParamA betaBinomialParamB @@ -1191,38 +1255,7 @@ bernoulliParam uniformPrior BAS - MCMC - MCMCBAS - numberOfModels iterationsMCMC - g_prior_2 - zs_null_2 - hyper_g_laplace_2 - hyper_g_n_2 - eb_global_2 - eb_local_2 - bic_2 - aic_2 - hyper_g_2 - zs_full_2 - gPriorParameter_2 - g_prior_3 - zs_null_3 - hyper_g_laplace_3 - hyper_g_n_3 - eb_global_3 - eb_local_3 - bic_3 - aic_3 - hyper_g_3 - zs_full_3 - gPriorParameter_3 - plotInclusionProbabilities_2 - plotCoefficientsPosterior_2 - plotLogPosteriorOdds_2 - plotModelComplexity_2 - plotModelProbabilities_2 - plotResidualsVsFitted_2 diff --git a/JASP-Desktop/analysisforms/regressionlinearform.cpp b/JASP-Desktop/analysisforms/Common/regressionlinearform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/regressionlinearform.cpp rename to JASP-Desktop/analysisforms/Common/regressionlinearform.cpp diff --git a/JASP-Desktop/analysisforms/regressionlinearform.h b/JASP-Desktop/analysisforms/Common/regressionlinearform.h similarity index 98% rename from JASP-Desktop/analysisforms/regressionlinearform.h rename to JASP-Desktop/analysisforms/Common/regressionlinearform.h index 46d710d211..b91fe6c87c 100644 --- a/JASP-Desktop/analysisforms/regressionlinearform.h +++ b/JASP-Desktop/analysisforms/Common/regressionlinearform.h @@ -19,7 +19,7 @@ #ifndef REGRESSIONLINEARFORM_H #define REGRESSIONLINEARFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelvariableslevels.h" #include "widgets/tablemodelanovamodel.h" diff --git a/JASP-Desktop/analysisforms/regressionlinearform.ui b/JASP-Desktop/analysisforms/Common/regressionlinearform.ui similarity index 100% rename from JASP-Desktop/analysisforms/regressionlinearform.ui rename to JASP-Desktop/analysisforms/Common/regressionlinearform.ui diff --git a/JASP-Desktop/analysisforms/regressionlogisticform.cpp b/JASP-Desktop/analysisforms/Common/regressionlogisticform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/regressionlogisticform.cpp rename to JASP-Desktop/analysisforms/Common/regressionlogisticform.cpp diff --git a/JASP-Desktop/analysisforms/regressionlogisticform.h b/JASP-Desktop/analysisforms/Common/regressionlogisticform.h similarity index 98% rename from JASP-Desktop/analysisforms/regressionlogisticform.h rename to JASP-Desktop/analysisforms/Common/regressionlogisticform.h index 0e5d7eede8..893bbda68f 100644 --- a/JASP-Desktop/analysisforms/regressionlogisticform.h +++ b/JASP-Desktop/analysisforms/Common/regressionlogisticform.h @@ -19,7 +19,7 @@ #ifndef REGRESSIONLOGISTICFORM_H #define REGRESSIONLOGISTICFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelvariableslevels.h" #include "widgets/tablemodelanovamodel.h" diff --git a/JASP-Desktop/analysisforms/regressionlogisticform.ui b/JASP-Desktop/analysisforms/Common/regressionlogisticform.ui similarity index 95% rename from JASP-Desktop/analysisforms/regressionlogisticform.ui rename to JASP-Desktop/analysisforms/Common/regressionlogisticform.ui index 1121a4b083..e5356b909c 100644 --- a/JASP-Desktop/analysisforms/regressionlogisticform.ui +++ b/JASP-Desktop/analysisforms/Common/regressionlogisticform.ui @@ -1120,65 +1120,6 @@
- - - - Stepping method criteria - - - - 9 - - - - - Removal p-value - - - - - - - - 60 - 16777215 - - - - - - - - - 60 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Entry p-value - - - - - -
diff --git a/JASP-Desktop/analysisforms/regressionloglinearbayesianform.cpp b/JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/regressionloglinearbayesianform.cpp rename to JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.cpp diff --git a/JASP-Desktop/analysisforms/regressionloglinearbayesianform.h b/JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.h similarity index 98% rename from JASP-Desktop/analysisforms/regressionloglinearbayesianform.h rename to JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.h index b38f703fce..231cf5a59b 100644 --- a/JASP-Desktop/analysisforms/regressionloglinearbayesianform.h +++ b/JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.h @@ -19,7 +19,7 @@ #ifndef REGRESSIONLOGLINEARBAYESIANFORM_H #define REGRESSIONLOGLINEARBAYESIANFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodel.h" @@ -31,7 +31,7 @@ class RegressionLogLinearBayesianForm; class RegressionLogLinearBayesianForm : public AnalysisForm { Q_OBJECT - + public: explicit RegressionLogLinearBayesianForm(QWidget *parent = 0); ~RegressionLogLinearBayesianForm(); @@ -41,7 +41,7 @@ class RegressionLogLinearBayesianForm : public AnalysisForm private slots: void factorsChanging(); void factorsChanged(); - + private: Ui::RegressionLogLinearBayesianForm *ui; diff --git a/JASP-Desktop/analysisforms/regressionloglinearbayesianform.ui b/JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.ui similarity index 100% rename from JASP-Desktop/analysisforms/regressionloglinearbayesianform.ui rename to JASP-Desktop/analysisforms/Common/regressionloglinearbayesianform.ui diff --git a/JASP-Desktop/analysisforms/regressionloglinearform.cpp b/JASP-Desktop/analysisforms/Common/regressionloglinearform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/regressionloglinearform.cpp rename to JASP-Desktop/analysisforms/Common/regressionloglinearform.cpp diff --git a/JASP-Desktop/analysisforms/regressionloglinearform.h b/JASP-Desktop/analysisforms/Common/regressionloglinearform.h similarity index 98% rename from JASP-Desktop/analysisforms/regressionloglinearform.h rename to JASP-Desktop/analysisforms/Common/regressionloglinearform.h index fd6f0f4ff6..4a6624f732 100644 --- a/JASP-Desktop/analysisforms/regressionloglinearform.h +++ b/JASP-Desktop/analysisforms/Common/regressionloglinearform.h @@ -19,7 +19,7 @@ #ifndef REGRESSIONLOGLINEARFORM_H #define REGRESSIONLOGLINEARFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelvariableslevels.h" #include "widgets/tablemodelanovamodel.h" diff --git a/JASP-Desktop/analysisforms/regressionloglinearform.ui b/JASP-Desktop/analysisforms/Common/regressionloglinearform.ui similarity index 100% rename from JASP-Desktop/analysisforms/regressionloglinearform.ui rename to JASP-Desktop/analysisforms/Common/regressionloglinearform.ui diff --git a/JASP-Desktop/analysisforms/reliabilityanalysisform.cpp b/JASP-Desktop/analysisforms/Common/reliabilityanalysisform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/reliabilityanalysisform.cpp rename to JASP-Desktop/analysisforms/Common/reliabilityanalysisform.cpp diff --git a/JASP-Desktop/analysisforms/reliabilityanalysisform.h b/JASP-Desktop/analysisforms/Common/reliabilityanalysisform.h similarity index 97% rename from JASP-Desktop/analysisforms/reliabilityanalysisform.h rename to JASP-Desktop/analysisforms/Common/reliabilityanalysisform.h index 56bb13a4d1..607fb0fcdf 100644 --- a/JASP-Desktop/analysisforms/reliabilityanalysisform.h +++ b/JASP-Desktop/analysisforms/Common/reliabilityanalysisform.h @@ -19,7 +19,7 @@ #ifndef RELIABILITYANALYSISFORM_H #define RELIABILITYANALYSISFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class ReliabilityAnalysisForm; diff --git a/JASP-Desktop/analysisforms/reliabilityanalysisform.ui b/JASP-Desktop/analysisforms/Common/reliabilityanalysisform.ui similarity index 100% rename from JASP-Desktop/analysisforms/reliabilityanalysisform.ui rename to JASP-Desktop/analysisforms/Common/reliabilityanalysisform.ui diff --git a/JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.cpp b/JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.cpp similarity index 98% rename from JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.cpp rename to JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.cpp index dc784f10eb..dbe4bbc7d6 100644 --- a/JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.cpp +++ b/JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.cpp @@ -19,7 +19,6 @@ #include "ttestbayesianindependentsamplesform.h" #include "ui_ttestbayesianindependentsamplesform.h" -#include "analysisform.h" TTestBayesianIndependentSamplesForm::TTestBayesianIndependentSamplesForm(QWidget *parent) : AnalysisForm("TTestBayesianIndependentSamplesForm", parent), diff --git a/JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.h b/JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.h similarity index 97% rename from JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.h rename to JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.h index e15a97e3ee..c3d66f8017 100644 --- a/JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.h +++ b/JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.h @@ -20,7 +20,7 @@ #define TTESTBAYESIANINDEPENDENTSAMPLESFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class TTestBayesianIndependentSamplesForm; @@ -29,11 +29,11 @@ class TTestBayesianIndependentSamplesForm; class TTestBayesianIndependentSamplesForm : public AnalysisForm { Q_OBJECT - + public: explicit TTestBayesianIndependentSamplesForm(QWidget *parent = 0); ~TTestBayesianIndependentSamplesForm(); - + private: Ui::TTestBayesianIndependentSamplesForm *ui; }; diff --git a/JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.ui b/JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ttestbayesianindependentsamplesform.ui rename to JASP-Desktop/analysisforms/Common/ttestbayesianindependentsamplesform.ui diff --git a/JASP-Desktop/analysisforms/ttestbayesianonesampleform.cpp b/JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/ttestbayesianonesampleform.cpp rename to JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.cpp diff --git a/JASP-Desktop/analysisforms/ttestbayesianonesampleform.h b/JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.h similarity index 97% rename from JASP-Desktop/analysisforms/ttestbayesianonesampleform.h rename to JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.h index 533c590c1f..8b4b58f45a 100644 --- a/JASP-Desktop/analysisforms/ttestbayesianonesampleform.h +++ b/JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.h @@ -19,7 +19,7 @@ #ifndef TTESTBAYESONESAMPLEFORM_H #define TTESTBAYESONESAMPLEFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { diff --git a/JASP-Desktop/analysisforms/ttestbayesianonesampleform.ui b/JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ttestbayesianonesampleform.ui rename to JASP-Desktop/analysisforms/Common/ttestbayesianonesampleform.ui diff --git a/JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.cpp b/JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.cpp rename to JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.cpp diff --git a/JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.h b/JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.h similarity index 97% rename from JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.h rename to JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.h index 3914398e66..31a8f7a9a1 100644 --- a/JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.h +++ b/JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.h @@ -19,7 +19,7 @@ #ifndef TTESTBAYESIANPAIREDSAMPLESFORM_H #define TTESTBAYESIANPAIREDSAMPLESFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class TTestBayesianPairedSamplesForm; @@ -28,11 +28,11 @@ class TTestBayesianPairedSamplesForm; class TTestBayesianPairedSamplesForm : public AnalysisForm { Q_OBJECT - + public: explicit TTestBayesianPairedSamplesForm(QWidget *parent = 0); ~TTestBayesianPairedSamplesForm(); - + private: Ui::TTestBayesianPairedSamplesForm *ui; }; diff --git a/JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.ui b/JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ttestbayesianpairedsamplesform.ui rename to JASP-Desktop/analysisforms/Common/ttestbayesianpairedsamplesform.ui diff --git a/JASP-Desktop/analysisforms/ttestindependentsamplesform.cpp b/JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.cpp similarity index 98% rename from JASP-Desktop/analysisforms/ttestindependentsamplesform.cpp rename to JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.cpp index ad028904d6..aa2a114381 100644 --- a/JASP-Desktop/analysisforms/ttestindependentsamplesform.cpp +++ b/JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.cpp @@ -19,7 +19,6 @@ #include "ttestindependentsamplesform.h" #include "ui_ttestindependentsamplesform.h" -#include "analysisform.h" TTestIndependentSamplesForm::TTestIndependentSamplesForm(QWidget *parent) : AnalysisForm("TTestIndependentSamplesForm", parent), diff --git a/JASP-Desktop/analysisforms/ttestindependentsamplesform.h b/JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.h similarity index 97% rename from JASP-Desktop/analysisforms/ttestindependentsamplesform.h rename to JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.h index d66a9ac7d5..698f2f2693 100644 --- a/JASP-Desktop/analysisforms/ttestindependentsamplesform.h +++ b/JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.h @@ -20,7 +20,7 @@ #define TTESTINDEPENDENTSAMPLESFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class TTestIndependentSamplesForm; @@ -29,11 +29,11 @@ class TTestIndependentSamplesForm; class TTestIndependentSamplesForm : public AnalysisForm { Q_OBJECT - + public: explicit TTestIndependentSamplesForm(QWidget *parent = 0); ~TTestIndependentSamplesForm(); - + private: Ui::TTestIndependentSamplesForm *ui; }; diff --git a/JASP-Desktop/analysisforms/ttestindependentsamplesform.ui b/JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ttestindependentsamplesform.ui rename to JASP-Desktop/analysisforms/Common/ttestindependentsamplesform.ui diff --git a/JASP-Desktop/analysisforms/ttestonesampleform.cpp b/JASP-Desktop/analysisforms/Common/ttestonesampleform.cpp similarity index 98% rename from JASP-Desktop/analysisforms/ttestonesampleform.cpp rename to JASP-Desktop/analysisforms/Common/ttestonesampleform.cpp index ce81e23db0..2e0e312400 100644 --- a/JASP-Desktop/analysisforms/ttestonesampleform.cpp +++ b/JASP-Desktop/analysisforms/Common/ttestonesampleform.cpp @@ -19,7 +19,6 @@ #include "ttestonesampleform.h" #include "ui_ttestonesampleform.h" -#include "analysisform.h" #include "widgets/tablemodelvariablesassigned.h" TTestOneSampleForm::TTestOneSampleForm(QWidget *parent) : diff --git a/JASP-Desktop/analysisforms/ttestonesampleform.h b/JASP-Desktop/analysisforms/Common/ttestonesampleform.h similarity index 97% rename from JASP-Desktop/analysisforms/ttestonesampleform.h rename to JASP-Desktop/analysisforms/Common/ttestonesampleform.h index 0ae1d3b4c1..96b268950c 100644 --- a/JASP-Desktop/analysisforms/ttestonesampleform.h +++ b/JASP-Desktop/analysisforms/Common/ttestonesampleform.h @@ -20,7 +20,7 @@ #define ONESAMPLETTESTFORM_H #include -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class TTestOneSampleForm; @@ -29,11 +29,11 @@ class TTestOneSampleForm; class TTestOneSampleForm : public AnalysisForm { Q_OBJECT - + public: explicit TTestOneSampleForm(QWidget *parent = 0); ~TTestOneSampleForm(); - + private: Ui::TTestOneSampleForm *ui; }; diff --git a/JASP-Desktop/analysisforms/ttestonesampleform.ui b/JASP-Desktop/analysisforms/Common/ttestonesampleform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ttestonesampleform.ui rename to JASP-Desktop/analysisforms/Common/ttestonesampleform.ui diff --git a/JASP-Desktop/analysisforms/ttestpairedsamplesform.cpp b/JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/ttestpairedsamplesform.cpp rename to JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.cpp diff --git a/JASP-Desktop/analysisforms/ttestpairedsamplesform.h b/JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.h similarity index 97% rename from JASP-Desktop/analysisforms/ttestpairedsamplesform.h rename to JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.h index f0f67a6cb9..4dfe899323 100644 --- a/JASP-Desktop/analysisforms/ttestpairedsamplesform.h +++ b/JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.h @@ -19,7 +19,7 @@ #ifndef TTESTPAIREDSAMPLESFORM_H #define TTESTPAIREDSAMPLESFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class TTestPairedSamplesForm; @@ -28,11 +28,11 @@ class TTestPairedSamplesForm; class TTestPairedSamplesForm : public AnalysisForm { Q_OBJECT - + public: explicit TTestPairedSamplesForm(QWidget *parent = 0); ~TTestPairedSamplesForm(); - + private: Ui::TTestPairedSamplesForm *ui; }; diff --git a/JASP-Desktop/analysisforms/ttestpairedsamplesform.ui b/JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.ui similarity index 100% rename from JASP-Desktop/analysisforms/ttestpairedsamplesform.ui rename to JASP-Desktop/analysisforms/Common/ttestpairedsamplesform.ui diff --git a/JASP-Desktop/analysisforms/MetaAnalysis/MetaAnalysis.pri b/JASP-Desktop/analysisforms/MetaAnalysis/MetaAnalysis.pri new file mode 100644 index 0000000000..50ec5c72b0 --- /dev/null +++ b/JASP-Desktop/analysisforms/MetaAnalysis/MetaAnalysis.pri @@ -0,0 +1,14 @@ +SOURCES += \ + $$PWD/../../ribbons/ribbonmeta_analysis.cpp \ + $$PWD/classicalmetaanalysisform.cpp \ + $$PWD/multinomialtestform.cpp + +HEADERS += \ + $$PWD/../../ribbons/ribbonmeta_analysis.h \ + $$PWD/classicalmetaanalysisform.h \ + $$PWD/multinomialtestform.h + +FORMS += \ + $$PWD/../../ribbons/ribbonmeta_analysis.ui \ + $$PWD/classicalmetaanalysisform.ui \ + $$PWD/multinomialtestform.ui diff --git a/JASP-Desktop/analysisforms/classicalmetaanalysisform.cpp b/JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/classicalmetaanalysisform.cpp rename to JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.cpp diff --git a/JASP-Desktop/analysisforms/classicalmetaanalysisform.h b/JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.h similarity index 97% rename from JASP-Desktop/analysisforms/classicalmetaanalysisform.h rename to JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.h index e68272381f..e668cde850 100644 --- a/JASP-Desktop/analysisforms/classicalmetaanalysisform.h +++ b/JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.h @@ -19,13 +19,11 @@ #ifndef CLASSICALMETAANALYSISFORM_H #define CLASSICALMETAANALYSISFORM_H -#include "analysisform.h" +#include "../analysisform.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelvariableslevels.h" #include "widgets/tablemodelanovamodel.h" -#include "common.h" - namespace Ui { class ClassicalMetaAnalysisForm; } diff --git a/JASP-Desktop/analysisforms/classicalmetaanalysisform.ui b/JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.ui similarity index 100% rename from JASP-Desktop/analysisforms/classicalmetaanalysisform.ui rename to JASP-Desktop/analysisforms/MetaAnalysis/classicalmetaanalysisform.ui diff --git a/JASP-Desktop/analysisforms/multinomialtestform.cpp b/JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.cpp similarity index 100% rename from JASP-Desktop/analysisforms/multinomialtestform.cpp rename to JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.cpp diff --git a/JASP-Desktop/analysisforms/multinomialtestform.h b/JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.h similarity index 97% rename from JASP-Desktop/analysisforms/multinomialtestform.h rename to JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.h index cd5a3317fa..40ce2dad1a 100644 --- a/JASP-Desktop/analysisforms/multinomialtestform.h +++ b/JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.h @@ -19,7 +19,7 @@ #ifndef MULTINOMIALTESTFORM_H #define MULTINOMIALTESTFORM_H -#include "analysisform.h" +#include "../analysisform.h" namespace Ui { class MultinomialTestForm; diff --git a/JASP-Desktop/analysisforms/multinomialtestform.ui b/JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.ui similarity index 100% rename from JASP-Desktop/analysisforms/multinomialtestform.ui rename to JASP-Desktop/analysisforms/MetaAnalysis/multinomialtestform.ui diff --git a/JASP-Desktop/analysisforms/Network/Network.pri b/JASP-Desktop/analysisforms/Network/Network.pri new file mode 100644 index 0000000000..8c71861fc1 --- /dev/null +++ b/JASP-Desktop/analysisforms/Network/Network.pri @@ -0,0 +1,11 @@ +SOURCES += \ + $$PWD/../../ribbons/ribbonnetworkanalysis.cpp \ + $$PWD/networkanalysisform.cpp + +HEADERS += \ + $$PWD/../../ribbons/ribbonnetworkanalysis.h \ + $$PWD/networkanalysisform.h + +FORMS += \ + $$PWD/../../ribbons/ribbonnetworkanalysis.ui \ + $$PWD/networkanalysisform.ui diff --git a/JASP-Desktop/analysisforms/Network/networkanalysisform.cpp b/JASP-Desktop/analysisforms/Network/networkanalysisform.cpp index 2e3977fa14..0160f4e1ae 100644 --- a/JASP-Desktop/analysisforms/Network/networkanalysisform.cpp +++ b/JASP-Desktop/analysisforms/Network/networkanalysisform.cpp @@ -95,6 +95,18 @@ NetworkAnalysisForm::NetworkAnalysisForm(QWidget *parent) : ui->_1spring->setChecked(true); ui->label_repulsion->setVisible(true); ui->repulsion->setVisible(true); + ui->_4parametric->hide(); + ui->_5person->hide(); + ui->_6jackknife->hide(); + ui->showMgmVariableType->setVisible(false); + + // for the next release +#ifdef QT_NO_DEBUG +// ui->plotClustering->setVisible(false); +// ui->tableClustering->setVisible(false); + ui->parallelBootstrap->setVisible(false); +#endif + } NetworkAnalysisForm::~NetworkAnalysisForm() @@ -119,7 +131,6 @@ void NetworkAnalysisForm::on_estimator_currentIndexChanged(const QString &choice ui->gridLayout_3->removeWidget(ui->thresholdBox); ui->gridLayout_3->removeWidget(ui->network); ui->gridLayout_3->removeWidget(ui->normalizeCentrality); - ui->gridLayout_12->removeWidget(ui->showMgmVariableType); ui->correlationMethod->hide(); ui->tuningParameterBox->hide(); @@ -134,7 +145,7 @@ void NetworkAnalysisForm::on_estimator_currentIndexChanged(const QString &choice ui->thresholdBox->hide(); ui->network->hide(); ui->normalizeCentrality->hide(); - ui->showMgmVariableType->hide(); + ui->showMgmVariableType->setVisible(false); if (choice_str.compare("EBICglasso") == 0) { ui->correlationMethod->setVisible(true); @@ -212,20 +223,24 @@ void NetworkAnalysisForm::on_estimator_currentIndexChanged(const QString &choice ui->boxMgmVariableType->setVisible(true); ui->crossValidation->setVisible(false); ui->showMgmVariableType->setVisible(true); - - ui->_4cv->setEnabled(true); + +// ui->_4cv->setEnabled(true); ui->analysisOptionsExpander->setText("Analysis Options - mgm"); - ui->gridLayout_3->addWidget(ui->tuningParameterBox, 1, 1); + ui->gridLayout_3->addWidget(ui->tuningParameterBox, 1, 0); ui->gridLayout_3->addWidget(ui->criterion, 0, 0); ui->gridLayout_3->addWidget(ui->rule, 0, 1); - ui->gridLayout_3->addWidget(ui->boxMgmVariableType, 1, 0); + ui->gridLayout_3->addWidget(ui->boxMgmVariableType, 2, 0); ui->gridLayout_3->addWidget(ui->crossValidation, 1, 1); - ui->gridLayout_12->addWidget(ui->showMgmVariableType, 5, 1); + ui->showMgmVariableType->setVisible(true); + + if(ui->_4cv->isChecked()) { + ui->crossValidation->setVisible(true); + } } ui->analysisOptions->setLayout(ui->gridLayout_3); - ui->analysisOptions->setLayout(ui->gridLayout_12); + } void NetworkAnalysisForm::on__4cv_clicked() diff --git a/JASP-Desktop/analysisforms/Network/networkanalysisform.ui b/JASP-Desktop/analysisforms/Network/networkanalysisform.ui index 3f834653bf..fc45d9c6e1 100644 --- a/JASP-Desktop/analysisforms/Network/networkanalysisform.ui +++ b/JASP-Desktop/analysisforms/Network/networkanalysisform.ui @@ -266,10 +266,10 @@
- + - false + true @@ -288,7 +288,7 @@ - false + true @@ -307,7 +307,7 @@ - Run in Parallel + Run in parallel @@ -324,6 +324,16 @@ + + + + true + + + Bootstrap network + + + @@ -342,8 +352,8 @@ false - - + + 0 @@ -351,12 +361,12 @@ - &Node + Parametric - - + + 0 @@ -364,12 +374,12 @@ - Person + &Jackknife - - + + 0 @@ -377,12 +387,12 @@ - &Jackknife + &Nonparametric - - + + 0 @@ -390,12 +400,12 @@ - Nonparametric + Person - - + + 0 @@ -403,12 +413,25 @@ - Parametric + &Node - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + 0 @@ -420,15 +443,15 @@ - - + + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 40 @@ -530,169 +553,6 @@ QLayout::SetNoConstraint - - - - - 0 - 0 - - - - Ising Estimator - - - false - - - - - - Qt::Vertical - - - - 20 - 5 - - - - - - - - - 0 - 0 - - - - Pseudo-li&kelihood - - - - - - - - 0 - 0 - - - - Bivariate regressions - - - - - - - - 0 - 0 - - - - &Loglinear - - - - - - - - 0 - 0 - - - - &Univariate regressions - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - 0 - 0 - - - - Tuning Parameter - - - false - - - - - - - 60 - 0 - - - - - 60 - 16777215 - - - - - - - - value - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - @@ -999,7 +859,7 @@ - + @@ -1064,8 +924,8 @@ - - + + 0 @@ -1073,41 +933,233 @@ - Cross-validation + Ising Estimator false - - - - - nFolds - - - - - - - - 60 - 0 - + + + + + Qt::Vertical - + - 60 - 16777215 + 20 + 5 - + - - - - Qt::Horizontal - - + + + + + 0 + 0 + + + + Pseudo-li&kelihood + + + + + + + + 0 + 0 + + + + Bivariate regressions + + + + + + + + 0 + 0 + + + + &Loglinear + + + + + + + + 0 + 0 + + + + &Univariate regressions + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 0 + + + + Tuning Parameter + + + false + + + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + + + + + value + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 0 + 0 + + + + Centrality Measures + + + false + + + + + + + 0 + 0 + + + + Relative + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Raw + + + + + + + + 0 + 0 + + + + Normali&zed + + + + + + + Qt::Horizontal + + 40 20 @@ -1119,6 +1171,60 @@ + + + + 0 + 0 + + + + Cross-validation + + + false + + + + + + nFolds + + + + + + + + 60 + 0 + + + + + 60 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + @@ -1405,7 +1511,7 @@ - + @@ -1427,111 +1533,15 @@ - - - - Weighted - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - 0 - 0 - - - - Centrality Measures - - - false - - - - - - - 0 - 0 - - - - Relative - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - Raw - - - - - - - - 0 - 0 - - + + - Normali&zed + Weighted - - + + Qt::Horizontal @@ -1543,6 +1553,19 @@ + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -1874,7 +1897,7 @@ - Color scheme: + Edge palette @@ -2685,7 +2708,7 @@ - Color scheme: + Node palette @@ -2714,8 +2737,8 @@ QLayout::SetNoConstraint - - + + 0 @@ -2723,40 +2746,98 @@ - Results + Estimator false - - - + + + - Qt::Vertical + Qt::Horizontal - 20 - 5 + 40 + 20 - - + + + + true + 0 0 - - Network plot - + + + EBICglasso + + + + + cor + + + + + pcor + + + + + IsingFit + + + + + IsingSampler + + + + + huge + + + + + adalasso + + + + + mgm + + + + + + + + + + 0 + 0 + + + + Plots + + + false + + - + 0 @@ -2764,12 +2845,12 @@ - Centrality plot + Network plot - + Qt::Horizontal @@ -2782,7 +2863,7 @@ - + 0 @@ -2790,7 +2871,51 @@ - Weights matrix + Centrality plot + + + + + + + + 0 + 0 + + + + Clustering plot + + + + + + + + + + + 0 + 0 + + + + Tables + + + false + + + + + + + 0 + 0 + + + + Clustering table @@ -2807,7 +2932,7 @@ - + @@ -2820,7 +2945,7 @@ - + false @@ -2845,101 +2970,41 @@ - - - - - - - - 0 - 0 - - - - Estimator - - - false - - - - - - true - + + 0 0 - - - EBICglasso - - - - - cor - - - - - pcor - - - - - IsingFit - - - - - IsingSampler - - - - - huge - - - - - adalasso - - + + Weights matrix + - - + + - Qt::Vertical + Qt::Horizontal - 20 - 5 + 40 + 20 - - - - Bootstrap Network - - - - - + + - Qt::Horizontal + Qt::Vertical - 40 - 20 + 20 + 5 @@ -3011,38 +3076,6 @@ - - bootstrapOnOff - clicked(bool) - bootstrapOptions - setEnabled(bool) - - - 108 - 558 - - - 454 - 1617 - - - - - bootstrapOnOff - clicked(bool) - numberOfBootstraps - setEnabled(bool) - - - 108 - 558 - - - 233 - 1507 - - - thresholdOptValue toggled(bool) diff --git a/JASP-Desktop/analysisforms/ReinforcementLearning/ReinforcementLearning.pri b/JASP-Desktop/analysisforms/ReinforcementLearning/ReinforcementLearning.pri new file mode 100644 index 0000000000..33771796f8 --- /dev/null +++ b/JASP-Desktop/analysisforms/ReinforcementLearning/ReinforcementLearning.pri @@ -0,0 +1,12 @@ +SOURCES += \ + $$PWD/../../ribbons/ribbonreinforcementlearning.cpp \ + $$PWD/reinforcementlearningr11tlearningform.cpp + +HEADERS += \ + $$PWD/../../ribbons/ribbonreinforcementlearning.h \ + $$PWD/reinforcementlearningr11tlearningform.h + +FORMS += \ + $$PWD/../../ribbons/ribbonreinforcementlearning.ui \ + $$PWD/reinforcementlearningr11tlearningform.ui + diff --git a/JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.cpp b/JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.cpp similarity index 89% rename from JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.cpp rename to JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.cpp index 57b08c1523..b339e71b59 100644 --- a/JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.cpp +++ b/JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.cpp @@ -16,16 +16,17 @@ // . // -#include "r11tlearnform.h" -#include "ui_r11tlearnform.h" + +#include "reinforcementlearningr11tlearningform.h" +#include "ui_reinforcementlearningr11tlearningform.h" #include "column.h" #include "widgets/tablemodelvariablesassigned.h" #include "widgets/tablemodelanovamodelnuisancefactors.h" -R11tLearnForm::R11tLearnForm(QWidget *parent) : - AnalysisForm("R11tLearnForm", parent), - ui(new Ui::R11tLearnForm) +ReinforcementLearningR11tLearningForm::ReinforcementLearningR11tLearningForm(QWidget *parent) : + AnalysisForm("ReinforcementLearningR11tLearningForm", parent), + ui(new Ui::ReinforcementLearningR11tLearningForm) { ui->setupUi(this); @@ -75,7 +76,7 @@ R11tLearnForm::R11tLearnForm(QWidget *parent) : ui->containerSampling->hide(); } -R11tLearnForm::~R11tLearnForm() +ReinforcementLearningR11tLearningForm::~ReinforcementLearningR11tLearningForm() { delete ui; } diff --git a/JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.h b/JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.h similarity index 74% rename from JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.h rename to JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.h index b1a5627625..1fb3721676 100644 --- a/JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.h +++ b/JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.h @@ -16,8 +16,9 @@ // . // -#ifndef R11TLEARNFORM_H -#define R11TLEARNFORM_H + +#ifndef REINFORCEMENTLEARNINGR11TLEARNINGFORM_H +#define REINFORCEMENTLEARNINGR11TLEARNINGFORM_H #include "../analysisform.h" @@ -26,19 +27,19 @@ #include "widgets/tablemodelvariablesoptions.h" namespace Ui { -class R11tLearnForm; +class ReinforcementLearningR11tLearningForm; } -class R11tLearnForm : public AnalysisForm +class ReinforcementLearningR11tLearningForm : public AnalysisForm { Q_OBJECT - + public: - explicit R11tLearnForm(QWidget *parent = 0); - ~R11tLearnForm(); + explicit ReinforcementLearningR11tLearningForm(QWidget *parent = 0); + ~ReinforcementLearningR11tLearningForm(); private: - Ui::R11tLearnForm *ui; + Ui::ReinforcementLearningR11tLearningForm *ui; TableModelVariablesAssigned *_subjectIdListModel; TableModelVariablesAssigned *_groupListModel; @@ -46,7 +47,6 @@ class R11tLearnForm : public AnalysisForm TableModelVariablesAssigned *_deckListModel; TableModelVariablesAssigned *_rewardListModel; TableModelVariablesAssigned *_lossListModel; - }; -#endif // R11TLEARNFORM_H +#endif // REINFORCEMENTLEARNINGR11TLEARNINGFORM_H diff --git a/JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.ui b/JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.ui similarity index 99% rename from JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.ui rename to JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.ui index bea315ea67..032d668e0a 100644 --- a/JASP-Desktop/analysisforms/R11tLearn/r11tlearnform.ui +++ b/JASP-Desktop/analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.ui @@ -1,7 +1,7 @@ - R11tLearnForm - + ReinforcementLearningR11tLearningForm + 0 diff --git a/JASP-Desktop/analysisforms/SEM/SEM.pri b/JASP-Desktop/analysisforms/SEM/SEM.pri new file mode 100644 index 0000000000..3e7418f15e --- /dev/null +++ b/JASP-Desktop/analysisforms/SEM/SEM.pri @@ -0,0 +1,11 @@ +SOURCES += \ + $$PWD/../../ribbons/ribbonsem.cpp \ + $$PWD/semsimpleform.cpp + +HEADERS += \ + $$PWD/../../ribbons/ribbonsem.h \ + $$PWD/semsimpleform.h + +FORMS += \ + $$PWD/../../ribbons/ribbonsem.ui \ + $$PWD/semsimpleform.ui diff --git a/JASP-Desktop/analysisforms/SummaryStatistics/SummaryStatistics.pri b/JASP-Desktop/analysisforms/SummaryStatistics/SummaryStatistics.pri new file mode 100644 index 0000000000..bb783f7b2c --- /dev/null +++ b/JASP-Desktop/analysisforms/SummaryStatistics/SummaryStatistics.pri @@ -0,0 +1,26 @@ +SOURCES += \ + $$PWD/../../ribbons/ribbonsummarystatistics.cpp \ + $$PWD/summarystatsbinomialtestbayesianform.cpp \ + $$PWD/summarystatscorrelationbayesianpairsform.cpp \ + $$PWD/summarystatsregressionlinearbayesianform.cpp \ + $$PWD/summarystatsttestbayesianindependentsamplesform.cpp \ + $$PWD/summarystatsttestbayesianonesampleform.cpp \ + $$PWD/summarystatsttestbayesianpairedsamplesform.cpp + +HEADERS += \ + $$PWD/../../ribbons/ribbonsummarystatistics.h \ + $$PWD/summarystatsbinomialtestbayesianform.h \ + $$PWD/summarystatscorrelationbayesianpairsform.h \ + $$PWD/summarystatsregressionlinearbayesianform.h \ + $$PWD/summarystatsttestbayesianindependentsamplesform.h \ + $$PWD/summarystatsttestbayesianonesampleform.h \ + $$PWD/summarystatsttestbayesianpairedsamplesform.h + +FORMS += \ + $$PWD/../../ribbons/ribbonsummarystatistics.ui \ + $$PWD/summarystatsbinomialtestbayesianform.ui \ + $$PWD/summarystatscorrelationbayesianpairsform.ui \ + $$PWD/summarystatsregressionlinearbayesianform.ui \ + $$PWD/summarystatsttestbayesianindependentsamplesform.ui \ + $$PWD/summarystatsttestbayesianonesampleform.ui \ + $$PWD/summarystatsttestbayesianpairedsamplesform.ui diff --git a/JASP-Desktop/analysisforms/bffromtform.cpp b/JASP-Desktop/analysisforms/bffromtform.cpp deleted file mode 100644 index 2865a0ea13..0000000000 --- a/JASP-Desktop/analysisforms/bffromtform.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include "bffromtform.h" -#include "ui_bffromtform.h" - -BFFromTForm::BFFromTForm(QWidget *parent) : - AnalysisForm("BFFromTForm", parent), - ui(new Ui::BFFromTForm) -{ - ui->setupUi(this); -} - -BFFromTForm::~BFFromTForm() -{ - delete ui; -} diff --git a/JASP-Desktop/analysisforms/bffromtform.h b/JASP-Desktop/analysisforms/bffromtform.h deleted file mode 100644 index da49c9c7be..0000000000 --- a/JASP-Desktop/analysisforms/bffromtform.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef BFFROMTFORM_H -#define BFFROMTFORM_H - -#include "analysisform.h" - -namespace Ui { -class BFFromTForm; -} - -class BFFromTForm : public AnalysisForm -{ - Q_OBJECT - -public: - explicit BFFromTForm(QWidget *parent = 0); - ~BFFromTForm(); - -private: - Ui::BFFromTForm *ui; -}; - -#endif // BFFROMTFORM_H diff --git a/JASP-Desktop/analysisforms/bffromtform.ui b/JASP-Desktop/analysisforms/bffromtform.ui deleted file mode 100644 index e4079d3304..0000000000 --- a/JASP-Desktop/analysisforms/bffromtform.ui +++ /dev/null @@ -1,25 +0,0 @@ - - - BFFromTForm - - - - 0 - 0 - 400 - 300 - - - - - 400 - 0 - - - - Form - - - - - diff --git a/JASP-Desktop/enginesync.cpp b/JASP-Desktop/enginesync.cpp index c787611eac..a251a519fc 100644 --- a/JASP-Desktop/enginesync.cpp +++ b/JASP-Desktop/enginesync.cpp @@ -171,16 +171,24 @@ void EngineSync::sendToProcess(int processNo, Analysis *analysis) json["id"] = analysis->id(); json["perform"] = perform; + json["requiresInit"] = analysis->requiresInit(); json["revision"] = analysis->revision(); if (analysis->status() != Analysis::Aborted) { json["name"] = analysis->name(); + json["title"] = analysis->title(); if (perform == "saveImg") + { json["image"] = analysis->getSaveImgOptions(); + } else + { + json["dataKey"] = analysis->dataKey(); + json["stateKey"] = analysis->stateKey(); + json["resultsMeta"] = analysis->resultsMeta(); json["options"] = analysis->options()->asJSON(); - + } Json::Value settings; settings["ppi"] = _ppi; diff --git a/JASP-Desktop/html/about.html b/JASP-Desktop/html/about.html index d814ee6a0f..0b1dbe09f3 100644 --- a/JASP-Desktop/html/about.html +++ b/JASP-Desktop/html/about.html @@ -17,46 +17,80 @@ - - - - - - - - - - - - - - + + +
-
- -
-
- +
+
+ +
+
+ +
+ +
+ +
+ Copyright 2013- University of Amsterdam +
+
Version:
+
Built on:
(Netherlands)
+
Download:
http://jasp-stats.org/download/
+
Citation:
JASP Team (). JASP()[ Computer software] (BibTeX)
+
+

This program is provided AS IS with NO WARANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MECHANDISING AND FITNESS FOR A PARTICULAR PURPOSE

+ OK +
-
- Copyright 2013- University of Amsterdam -
-
Built on:
(Netherlands)
-
Download:
http://jasp-stats.org/download/
-
Citation:
JASP Team (). JASP()[ Computer software] (BibTeX)
-
-

This program is provided AS IS with NO WARANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MECHANDISING AND FITNESS FOR A PARTICULAR PURPOSE

- OK -
- +
+
+ + + diff --git a/JASP-Desktop/html/css/style.css b/JASP-Desktop/html/css/style.css index c0786fd34c..b968547472 100644 --- a/JASP-Desktop/html/css/style.css +++ b/JASP-Desktop/html/css/style.css @@ -37,38 +37,64 @@ h1, h2, h3, h4, h5, h6 { --------------------------------------------------------------*/ #about-box { - width: 100%; - height:100%; - background-color: white; - padding: 134px 24px 24px 24px; - background-image: url('../img/jasp-wave-down-blue-120-squat.svg'); - background-repeat: repeat-x; - background-position: top center; - background-position: calc(50% + 10px) top; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + min-height: 20rem; + min-width: 36rem; + font-weight: 300; + font-family: Lato, sans-serif; + background-color: #8dc448; +} + +/*-------------------------------------------------------------- +# Top wave +--------------------------------------------------------------*/ + +#top-about { + position: relative; + padding-top: 4px; + padding-bottom: 100px; + background-image: url('../img/jasp-wave-down-blue-120.svg'); + background-repeat: repeat-x; + background-position: bottom center; + background-position: calc(50% + 100px) bottom; + background-color: white; } /*-------------------------------------------------------------- -# Logo version +# Logo and version --------------------------------------------------------------*/ +#about-content{ + background-color: white; +} + #logo-version{ width: 220px; - float: left; + padding-left: 50px; + display: inline-block; + vertical-align: top; + margin-top: 50px; } .logo{ margin-bottom: 0.3em; } -.jasp-version { - display: block; - margin-left: 64px; -} /*-------------------------------------------------------------- # More info --------------------------------------------------------------*/ +.jasp-version { + display: block; + margin-left: 64px; +} + #more-info{ width: 430px; - float: left; + display: inline-block; + padding-left: 50px; } .copyright{ font-size: 1rem; @@ -94,3 +120,18 @@ dt{ padding: 0.2em 1.2em; font-size: 1rem; } + +/*-------------------------------------------------------------- +# Bottom wave +--------------------------------------------------------------*/ + +#bottom-about{ + position: relative; + min-height: 100px; + /*padding-top: 100px;*/ + background-image: url('../img/jasp-wave-up-green-100.svg'); + background-repeat: repeat-x; + background-position: bottom center; + background-position: calc(50% + 60px) bottom; + background-color: white; +} diff --git a/JASP-Desktop/html/html.qrc b/JASP-Desktop/html/html.qrc index 936c38865e..ff3aefbc9a 100644 --- a/JASP-Desktop/html/html.qrc +++ b/JASP-Desktop/html/html.qrc @@ -68,5 +68,6 @@ css/style.css css/bootstrap.min.css img/jasp-logo-black.svg + img/snow.gif diff --git a/JASP-Desktop/html/img/jasp-logo-black.svg b/JASP-Desktop/html/img/jasp-logo-black.svg index c9022fe281..7046ebba6e 100644 --- a/JASP-Desktop/html/img/jasp-logo-black.svg +++ b/JASP-Desktop/html/img/jasp-logo-black.svg @@ -1 +1 @@ -jasp-logo-blue +jasp-logo-blue diff --git a/JASP-Desktop/html/img/snow.gif b/JASP-Desktop/html/img/snow.gif new file mode 100644 index 0000000000..15a70dbe88 Binary files /dev/null and b/JASP-Desktop/html/img/snow.gif differ diff --git a/JASP-Desktop/html/js/main.js b/JASP-Desktop/html/js/main.js index 61415e3725..8fe7d05b8e 100644 --- a/JASP-Desktop/html/js/main.js +++ b/JASP-Desktop/html/js/main.js @@ -10,6 +10,12 @@ window.getPPI = function () { $(document).ready(function () { + var d = new Date(); + var month = d.getMonth(); + var day = d.getDate(); + if ((month == 11 && day >= 19) || (month == 0 && day <= 5)) + $("#note").css("background-image", "url('img/snow.gif')"); + var ua = navigator.userAgent.toLowerCase(); if (ua.indexOf("windows") !== -1) diff --git a/JASP-Desktop/importers/ods/odsimportcolumn.cpp b/JASP-Desktop/importers/ods/odsimportcolumn.cpp index bff105c078..bfc55716bb 100644 --- a/JASP-Desktop/importers/ods/odsimportcolumn.cpp +++ b/JASP-Desktop/importers/ods/odsimportcolumn.cpp @@ -33,8 +33,8 @@ using namespace std; using namespace ods; -ODSImportColumn::ODSImportColumn(ODSImportDataSet* importDataSet, int columnNumber) - : ImportColumn(importDataSet, _colNumberAsExcel(columnNumber)) +ODSImportColumn::ODSImportColumn(ODSImportDataSet* importDataSet, int columnNumber, string name) + : ImportColumn(importDataSet, name) , _columnNumber(columnNumber) , _columnType(Column::ColumnTypeUnknown) { @@ -95,37 +95,15 @@ void ODSImportColumn::createSpace(size_t row) #endif } -/** - * @brief setValue Inserts one cell value. - * @param row Row to insert - * @param type ODS data type. - * @param data ODS cell value. - */ -void ODSImportColumn::setValue(int row, XmlDatatype type, const QString &data) +void ODSImportColumn::setValue(int row, const string &data) { - DEBUG_COUT9("Inserting ", data.toStdString(), " as ", ODSTYPE_STR[type], ", row ", row, ", column ", _columnNumber, "."); - - // Big enough? - createSpace(row); - - // insert the data - _rows.at(row).setTypeAndValue(type, data); -} - -/** - * @brief insert Inserts string value for cell, irrespective of type. - * @param row - * @param data - */ -void ODSImportColumn::setValue(int row, const QString& data) -{ - DEBUG_COUT7("Inserting ", data.toStdString(), ", row ", row, ", column ", _columnNumber, "."); + DEBUG_COUT7("Inserting ", data, ", row ", row, ", column ", _columnNumber, "."); // Big enough? createSpace(row); ODSSheetCell & cell = _rows.at(row); - cell.setValue(data); + cell.setValue(data); } /** @@ -138,19 +116,6 @@ void ODSImportColumn::setValue(int row, const QString& data) */ void ODSImportColumn::postLoadProcess() { - // Sanity check: Do we have a heading? - if ((_rows.size() == 0) || (_rows[0].xmlType() != odsType_string)) - { - string msg("No column header found in sheet row 1, column "); - msg.append(_colNumberAsExcel(_columnNumber)); - msg.append("."); - throw runtime_error(msg); - } - - // Get the long name, rename this column, and erase the first cell. -// setLongName(_rows[0]._string); - setName(_rows[0]._string); - _rows.erase(_rows.begin()); } vector ODSImportColumn::getData() diff --git a/JASP-Desktop/importers/ods/odsimportcolumn.h b/JASP-Desktop/importers/ods/odsimportcolumn.h index 4b3d18caf4..bf4be20d23 100644 --- a/JASP-Desktop/importers/ods/odsimportcolumn.h +++ b/JASP-Desktop/importers/ods/odsimportcolumn.h @@ -43,7 +43,7 @@ class ODSImportColumn : public ImportColumn // The constainer used to hold rows within the column. typedef std::vector Cases; - ODSImportColumn(ODSImportDataSet* importDataSet, int columnNumber); + ODSImportColumn(ODSImportDataSet* importDataSet, int columnNumber, std::string name); virtual ~ODSImportColumn(); /** @@ -85,21 +85,12 @@ class ODSImportColumn : public ImportColumn */ void createSpace(size_t row); - - /** - * @brief setValue Inserts one cell value. - * @param row Row to insert - * @param type ODS data type. - * @param data ODS cell value. - */ - void setValue(int row, XmlDatatype type, const QString& data); - /** * @brief setValue Inserts string value for cell, irrespective of type. * @param row * @param data */ - void setValue(int row, const QString& data); + void setValue(int row, const std::string& data); const ODSSheetCell &getCell(int row) const { return _rows.at(row); } diff --git a/JASP-Desktop/importers/ods/odsimportdataset.cpp b/JASP-Desktop/importers/ods/odsimportdataset.cpp index 338f58d49f..6c48d3c9b5 100644 --- a/JASP-Desktop/importers/ods/odsimportdataset.cpp +++ b/JASP-Desktop/importers/ods/odsimportdataset.cpp @@ -42,30 +42,12 @@ ODSImportDataSet::~ODSImportDataSet() } -/** - * @brief createSpace Ensure that we have enough columns for the passed value. - * @param column The column number to check for. - * @return The number of columns available. - Maybe greater than column. - */ -size_t ODSImportDataSet::createSpace(int column) +ODSImportColumn & ODSImportDataSet::createColumn(string name) { -#ifndef QT_NO_DEBUG - size_t numAdded = 0; -#endif - while(column >= columnCount()) -#ifndef QT_NO_DEBUG - { - numAdded++; -#endif - addColumn(new ODSImportColumn(this, columnCount())); -#ifndef QT_NO_DEBUG - } - - if (numAdded != 0) - DEBUG_COUT7("ODSImportDataSet::createSpace(", column, ") - added ", numAdded, " column", - ((numAdded != 1) ? "s" : ""), "."); -#endif - return columnCount(); + DEBUG_COUT2("ODSImportDataSet::createColumn: ", name); + ODSImportColumn* column = new ODSImportColumn(this, columnCount(), name); + addColumn(column); + return *column; } @@ -79,6 +61,23 @@ ODSImportColumn & ODSImportDataSet::operator [] (const int index) return static_cast(*(_columns[index])); } +/** + * @brief get or Create the underlying vector of the ImportDataSet. + * @param index The bracketed value. + * @return A reference to the indexed value. + */ +ODSImportColumn & ODSImportDataSet::getOrCreate (const int index) +{ + if (index < columnCount()) + return static_cast(*(_columns[index])); + else + { + stringstream ss; + ss << "_col" << columnCount() + 1; + return createColumn(ss.str()); + } +} + /** * @brief postLoadProcess Performs post load processing. diff --git a/JASP-Desktop/importers/ods/odsimportdataset.h b/JASP-Desktop/importers/ods/odsimportdataset.h index e3b3a93af7..5c47a3a246 100644 --- a/JASP-Desktop/importers/ods/odsimportdataset.h +++ b/JASP-Desktop/importers/ods/odsimportdataset.h @@ -60,24 +60,7 @@ class ODSImportDataSet : public ImportDataSet */ const std::string &getContentFilename() const { return _contentFilename; } - /** - * @brief minRow Gets the lowest numbered row in the sheet. - * @return The lowest numbered row in the sheet. - */ - int minRow() const; - - /** - * @brief maxRow Gets the highest numbered row in the sheet. - * @return The highest numbered row in the sheet. - */ - int maxRow() const; - - /** - * @brief createSpace Ensure that we have enough columns for the passed value. - * @param column The column number to check for. - * @return The number of columns available. - Maybe greater than column. - */ - size_t createSpace(int column); + ODSImportColumn & createColumn(std::string name); /** * @brief operator [] Exposes the underlying vector of the ImportDataSet. @@ -85,6 +68,7 @@ class ODSImportDataSet : public ImportDataSet * @return A reference to the indexed value. */ ODSImportColumn & operator [] (const int index); + ODSImportColumn & getOrCreate (const int index); /** * @brief postLoadProcess Performs post load processing. diff --git a/JASP-Desktop/importers/ods/odssheetcell.cpp b/JASP-Desktop/importers/ods/odssheetcell.cpp index b9634f5e89..f8e8e19960 100644 --- a/JASP-Desktop/importers/ods/odssheetcell.cpp +++ b/JASP-Desktop/importers/ods/odssheetcell.cpp @@ -94,6 +94,14 @@ void ODSSheetCell::setValue(const QString &value) _xmlType = odsType_string; } +void ODSSheetCell::setValue(const string &value) +{ + _string = value; + // if no type set to date, then it becomes a string. + if (xmlType() == odsType_unknown) + _xmlType = odsType_string; +} + const string &ODSSheetCell::valueAsString() const { diff --git a/JASP-Desktop/importers/ods/odssheetcell.h b/JASP-Desktop/importers/ods/odssheetcell.h index 48de6f3def..b5a8b71426 100644 --- a/JASP-Desktop/importers/ods/odssheetcell.h +++ b/JASP-Desktop/importers/ods/odssheetcell.h @@ -52,6 +52,7 @@ class ODSSheetCell std::string _string; void setValue(const QString &value); + void setValue(const std::string &value); }; } // end namespace ods diff --git a/JASP-Desktop/importers/ods/odsxmlcontentshandler.cpp b/JASP-Desktop/importers/ods/odsxmlcontentshandler.cpp index 974d6bbcc2..86c5f3745c 100644 --- a/JASP-Desktop/importers/ods/odsxmlcontentshandler.cpp +++ b/JASP-Desktop/importers/ods/odsxmlcontentshandler.cpp @@ -1,4 +1,5 @@ #include "odsxmlcontentshandler.h" +#include "../importerutils.h" using namespace std; using namespace ods; @@ -17,6 +18,7 @@ const QString XmlContentsHandler::_attDateValue("office:date-value"); const QString XmlContentsHandler::_attTimeValue("office:time-value"); const QString XmlContentsHandler::_attBoolValue("office:boolean-value"); const QString XmlContentsHandler::_attCellRepeatCount("table:number-columns-repeated"); +const QString XmlContentsHandler::_attRowRepeatCount("table:number-rows-repeated"); const QString XmlContentsHandler::_typeFloat("float"); const QString XmlContentsHandler::_typeCurrency("currency"); @@ -32,9 +34,11 @@ XmlContentsHandler::XmlContentsHandler(ODSImportDataSet *dta) , _docDepth(not_in_doc) , _row(0) , _column(0) + , _lastNotEmptyColumn(-1) , _tableRead(false) , _lastType(odsType_unknown) - , _colSpan(0) + , _colRepeat(1) + , _rowRepeat(1) { @@ -55,6 +59,8 @@ bool XmlContentsHandler::startElement(const QString &namespaceURI, const QString { if (_tableRead == false) { + DEBUG_COUT6("XmlContentsHandler::startElement. docDepth: ", _docDepth, ", localName: ", localName.toStdString(), ", qName: ", qName.toStdString()); + // Where were we? switch(_docDepth) { @@ -76,7 +82,10 @@ bool XmlContentsHandler::startElement(const QString &namespaceURI, const QString break; case table: if (localName == _nameTableRow) + { _docDepth = table_row; + _rowRepeat = _findRowRepeat(atts); + } break; case table_row: if (localName == _nameTableCell) @@ -85,38 +94,10 @@ bool XmlContentsHandler::startElement(const QString &namespaceURI, const QString // Arrived at a cell. // Get it's type and value. - QString value; - _setLastTypeGetValue(value, atts); - - // Deal with headers / create the column. - if ((_row == 0) && (_lastType != odsType_unknown)) - _dataSet->createSpace(_column); - + _setLastTypeGetValue(_currentCell, atts); + // Find column span for this cell. - _colSpan = _findColspan(atts); - - // Blank row? - Skip it. - if ((_row != 0) && (_colSpan > _dataSet->columnCount()) && (_column == 0)) - break; - - // Is the end column off the end of the active area? - int effectiveColSpan = _colSpan; - if ((_column + _colSpan) >= _dataSet->columnCount()) - effectiveColSpan = _dataSet->columnCount() - _column; - // Give up - if (effectiveColSpan == 0) - break; - - // Create a blank cells, one for each spanned column. - if (effectiveColSpan > 0) - { - for (int column = _column; column < (effectiveColSpan + _column); ++column) - (*_dataSet)[column].createSpace(_row); - } - - // Data cells (i.e. not first row), and we actually have a value to insert? - if ((_row > 0) && (value.isEmpty() == false)) - (*_dataSet)[_column].setValue(_row, _lastType, value); + _colRepeat = _findColRepeat(atts); } break; @@ -148,6 +129,8 @@ bool XmlContentsHandler::endElement(const QString &namespaceURI, const QString & { if (_tableRead == false) { + DEBUG_COUT6("XmlContentsHandler::endElement. docDepth: ", _docDepth, ", localName: ", localName.toStdString(), ", qName: ", qName.toStdString()); + switch(_docDepth) { case not_in_doc: @@ -175,17 +158,70 @@ bool XmlContentsHandler::endElement(const QString &namespaceURI, const QString & if (localName == _nameTableRow) { _docDepth = table; + if (_row > 0 && _lastNotEmptyColumn > -1) + { + // Repeat the last row + for (int i = 1; i < _rowRepeat; i++) + { + for (int j = 0; j < _dataSet->columnCount(); j++) + { + (*_dataSet)[j].setValue(_row, (*_dataSet)[j].getCell(_row - 1).valueAsString()); + } + _row++; + } + } _row++; // Starting next column. _column = 0; - _colSpan = 0; + _lastNotEmptyColumn = -1; + _currentCell.clear(); + _colRepeat = 1; + _rowRepeat = 1; } break; case table_cell: if (localName == _nameTableCell) { + if (!_currentCell.isEmpty()) + { + if (_row == 0) + { + // Deals with header + // First add columns that had no name + for (int i = _lastNotEmptyColumn + 1; i < _column; i++) + { + // Set some names for columns that have no header. + stringstream ss; + ss << "_col" << (i + 1); + _dataSet->createColumn(ss.str()); + } + // Create the column with the current cell name + _dataSet->createColumn(_currentCell.toStdString()); + // Repeat create column if necessary + for (int i = 1; i < _colRepeat; i++) + { + stringstream ss; + ss << "_col" << (_column + i + 1); + _dataSet->createColumn(ss.str()); + } + } + else + { + for (int i = _lastNotEmptyColumn + 1; i < _column; i++) + { + // Set empty values + _dataSet->getOrCreate(i).setValue(_row - 1, string()); + } + for (int i = 0; i < _colRepeat; i++) + _dataSet->getOrCreate(_column + i).setValue(_row - 1, _currentCell.toStdString()); + } + _lastNotEmptyColumn = _column + _colRepeat - 1; + } + _docDepth = table_row; - _column += _colSpan; + _column += _colRepeat; + _colRepeat = 1; + _currentCell.clear(); } break; @@ -210,16 +246,10 @@ bool XmlContentsHandler::characters(const QString &ch) if (_tableRead == false) { - // Always save the string. - if ((_docDepth == text) && (ch.isEmpty() == false)) + if ((_docDepth == text) && (ch.isEmpty() == false) && _currentCell.isEmpty()) { - for (int column = _column; column < (_colSpan + _column); ++column) - { - if ((*_dataSet)[column].getCell(_row).xmlType() == odsType_unknown) - (*_dataSet)[column].setValue(_row, odsType_string, ch); - else - (*_dataSet)[column].setValue(_row, ch); - } + DEBUG_COUT2("Characters: ", ch.toStdString()); + _currentCell = ch; } } return true; @@ -234,6 +264,12 @@ void XmlContentsHandler::resetDocument() _docDepth = not_in_doc; _row = 0; _column = 0; + _lastNotEmptyColumn = -1; + _tableRead = false; + _lastType = odsType_unknown; + _colRepeat = 1; + _rowRepeat = 1; + _dataSet->clear(); } @@ -293,10 +329,18 @@ XmlDatatype XmlContentsHandler::_setLastTypeGetValue(QString &value, const QXmlA * @param defaultValue The value to return if not found. * @return The found value or default. */ -int XmlContentsHandler::_findColspan(const QXmlAttributes &atts, int defaultValue) +int XmlContentsHandler::_findColRepeat(const QXmlAttributes &atts, int defaultValue) { int result = 0; bool okay = false; result = atts.value(_attCellRepeatCount).toInt(&okay); return (okay) ? result : defaultValue; } + +int XmlContentsHandler::_findRowRepeat(const QXmlAttributes &atts, int defaultValue) +{ + int result = 0; + bool okay = false; + result = atts.value(_attRowRepeatCount).toInt(&okay); + return (okay) ? result : defaultValue; +} diff --git a/JASP-Desktop/importers/ods/odsxmlcontentshandler.h b/JASP-Desktop/importers/ods/odsxmlcontentshandler.h index 413aedfa94..091f2a2656 100644 --- a/JASP-Desktop/importers/ods/odsxmlcontentshandler.h +++ b/JASP-Desktop/importers/ods/odsxmlcontentshandler.h @@ -69,10 +69,12 @@ class XmlContentsHandler : public XmlHandler DocDepth _docDepth; ///< Current depth of document. int _row; ///< Current row in document/table. int _column; ///< Current column in document/table. + int _lastNotEmptyColumn; bool _tableRead; ///< True if first table read. XmlDatatype _lastType; ///< The last type we found in a opening tag. - int _colSpan; ///< Number cells this XML element spans. - + int _colRepeat; ///< Number cells this XML element spans. + int _rowRepeat; + QString _currentCell; // Names we search for. static const QString _nameDocContent; @@ -90,6 +92,7 @@ class XmlContentsHandler : public XmlHandler static const QString _attTimeValue; static const QString _attBoolValue; static const QString _attCellRepeatCount; + static const QString _attRowRepeatCount; // Values of the attribute attValueType. static const QString _typeFloat; @@ -110,12 +113,13 @@ class XmlContentsHandler : public XmlHandler XmlDatatype _setLastTypeGetValue(QString &value, const QXmlAttributes &atts); /** - * @brief _findColspan Finds the column span from attributes. + * @brief _findColRepeat/_findRowRepeat Finds the column/row repeat from attributes. * @param atts The attribuyes to search. * @param defaultValue The value to return if not found. * @return The found value or default. */ - static int _findColspan(const QXmlAttributes &atts, int defaultValue = 1); + static int _findColRepeat(const QXmlAttributes &atts, int defaultValue = 1); + static int _findRowRepeat(const QXmlAttributes &atts, int defaultValue = 1); }; diff --git a/JASP-Desktop/importers/spss/spssimportdataset.cpp b/JASP-Desktop/importers/spss/spssimportdataset.cpp index 86fe6b8fb8..aef0072ab7 100644 --- a/JASP-Desktop/importers/spss/spssimportdataset.cpp +++ b/JASP-Desktop/importers/spss/spssimportdataset.cpp @@ -33,6 +33,7 @@ using namespace spss; SPSSImportDataSet::SPSSImportDataSet(SPSSImporter* importer) : ImportDataSet(importer), _numCases(-1L) { + setStrCnvrtr( new CodePageConvert(CodePageConvert::findIANANameFromSPSS(2))); //Set UTF-8 per default } SPSSImportDataSet::~SPSSImportDataSet() diff --git a/JASP-Desktop/mainwindow.cpp b/JASP-Desktop/mainwindow.cpp index dac0b63202..01bb5e031d 100644 --- a/JASP-Desktop/mainwindow.cpp +++ b/JASP-Desktop/mainwindow.cpp @@ -19,62 +19,56 @@ #include "mainwindow.h" #include "ui_mainwindow.h" -#include "analysisforms/descriptivesform.h" - -#include "analysisforms/ttestbayesianindependentsamplesform.h" -#include "analysisforms/ttestbayesianpairedsamplesform.h" -#include "analysisforms/ttestbayesianonesampleform.h" -#include "analysisforms/ttestindependentsamplesform.h" -#include "analysisforms/ttestpairedsamplesform.h" -#include "analysisforms/ttestonesampleform.h" - - -#include "analysisforms/anovaonewayform.h" -#include "analysisforms/anovaform.h" -#include "analysisforms/anovarepeatedmeasuresform.h" -#include "analysisforms/ancovaform.h" -#include "analysisforms/anovamultivariateform.h" -#include "analysisforms/ancovamultivariateform.h" - -#include "analysisforms/anovabayesianform.h" -#include "analysisforms/ancovabayesianform.h" -#include "analysisforms/anovarepeatedmeasuresbayesianform.h" - -#include "analysisforms/regressionlinearform.h" -#include "analysisforms/regressionlinearbayesianform.h" -#include "analysisforms/regressionlogisticform.h" -#include "analysisforms/regressionloglinearform.h" -#include "analysisforms/regressionloglinearbayesianform.h" -#include "analysisforms/correlationform.h" -#include "analysisforms/correlationbayesianform.h" -#include "analysisforms/correlationbayesianpairsform.h" -#include "analysisforms/correlationpartialform.h" -#include "analysisforms/contingencytablesform.h" -#include "analysisforms/contingencytablesbayesianform.h" -#include "analysisforms/classicalmetaanalysisform.h" - -#include "analysisforms/binomialtestform.h" -#include "analysisforms/multinomialtestform.h" -#include "analysisforms/binomialtestbayesianform.h" -#include "analysisforms/bffromtform.h" -#include "analysisforms/SummaryStatistics/summarystatsttestbayesianindependentsamplesform.h" -#include "analysisforms/SummaryStatistics/summarystatsttestbayesianpairedsamplesform.h" -#include "analysisforms/SummaryStatistics/summarystatsttestbayesianonesampleform.h" +#include "analysisforms/Common/ancovabayesianform.h" +#include "analysisforms/Common/ancovaform.h" +#include "analysisforms/Common/ancovamultivariateform.h" +#include "analysisforms/Common/anovabayesianform.h" +#include "analysisforms/Common/anovaform.h" +#include "analysisforms/Common/anovamultivariateform.h" +#include "analysisforms/Common/anovaonewayform.h" +#include "analysisforms/Common/anovarepeatedmeasuresbayesianform.h" +#include "analysisforms/Common/anovarepeatedmeasuresform.h" +#include "analysisforms/Common/binomialtestbayesianform.h" +#include "analysisforms/Common/binomialtestform.h" +#include "analysisforms/Common/contingencytablesbayesianform.h" +#include "analysisforms/Common/contingencytablesform.h" +#include "analysisforms/Common/correlationbayesianform.h" +#include "analysisforms/Common/correlationbayesianpairsform.h" +#include "analysisforms/Common/correlationform.h" +#include "analysisforms/Common/correlationpartialform.h" +#include "analysisforms/Common/descriptivesform.h" +#include "analysisforms/Common/exploratoryfactoranalysisform.h" +#include "analysisforms/Common/principalcomponentanalysisform.h" +#include "analysisforms/Common/regressionlinearbayesianform.h" +#include "analysisforms/Common/regressionlinearform.h" +#include "analysisforms/Common/regressionlogisticform.h" +#include "analysisforms/Common/regressionloglinearbayesianform.h" +#include "analysisforms/Common/regressionloglinearform.h" +#include "analysisforms/Common/reliabilityanalysisform.h" +#include "analysisforms/Common/ttestbayesianindependentsamplesform.h" +#include "analysisforms/Common/ttestbayesianonesampleform.h" +#include "analysisforms/Common/ttestbayesianpairedsamplesform.h" +#include "analysisforms/Common/ttestindependentsamplesform.h" +#include "analysisforms/Common/ttestonesampleform.h" +#include "analysisforms/Common/ttestpairedsamplesform.h" + #include "analysisforms/SummaryStatistics/summarystatsbinomialtestbayesianform.h" -#include "analysisforms/SummaryStatistics/summarystatsregressionlinearbayesianform.h" #include "analysisforms/SummaryStatistics/summarystatscorrelationbayesianpairsform.h" +#include "analysisforms/SummaryStatistics/summarystatsregressionlinearbayesianform.h" +#include "analysisforms/SummaryStatistics/summarystatsttestbayesianindependentsamplesform.h" +#include "analysisforms/SummaryStatistics/summarystatsttestbayesianonesampleform.h" +#include "analysisforms/SummaryStatistics/summarystatsttestbayesianpairedsamplesform.h" + +#include "analysisforms/SEM/semsimpleform.h" + +#include "analysisforms/ReinforcementLearning/reinforcementlearningr11tlearningform.h" -#ifdef QT_DEBUG -#include "analysisforms/basregressionlinearlinkform.h" -#endif #include "analysisforms/Network/networkanalysisform.h" -#include "analysisforms/SEM/semsimpleform.h" -#include "analysisforms/R11tLearn/r11tlearnform.h" +#include "analysisforms/MetaAnalysis/classicalmetaanalysisform.h" +#include "analysisforms/MetaAnalysis/multinomialtestform.h" -#include "analysisforms/reliabilityanalysisform.h" -#include "analysisforms/exploratoryfactoranalysisform.h" -#include "analysisforms/principalcomponentanalysisform.h" +///// 1-analyses headers #include #include @@ -104,7 +98,6 @@ #include "processinfo.h" #include "appinfo.h" - #include "lrnam.h" #include "activitylog.h" #include "aboutdialog.h" @@ -118,6 +111,7 @@ #include "options/optionvariablesgroups.h" + using namespace std; MainWindow::MainWindow(QWidget *parent) : @@ -157,9 +151,11 @@ MainWindow::MainWindow(QWidget *parent) : ui->ribbonAnalysis->setDataSetLoaded(false); ui->ribbonSEM->setDataSetLoaded(false); - ui->ribbonR11tLearn->setDataSetLoaded(false); + ui->ribbonReinforcementLearning->setDataSetLoaded(false); ui->ribbonSummaryStatistics->setDataSetLoaded(false); - ui->ribbonMetaAnalysis->setDataSetLoaded(false); + ui->ribbonMetaAnalysis->setDataSetLoaded(false); + ui->ribbonNetworkAnalysis->setDataSetLoaded(false); +///// 2-ribbon setDataSetLoaded #ifdef QT_DEBUG ui->webViewResults->page()->settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); @@ -202,11 +198,12 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->ribbonAnalysis, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); connect(ui->ribbonSEM, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); - connect(ui->ribbonR11tLearn, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); + connect(ui->ribbonReinforcementLearning, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); connect(ui->ribbonSummaryStatistics, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); - connect(ui->ribbonMetaAnalysis, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); + connect(ui->ribbonMetaAnalysis, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); connect(ui->ribbonNetworkAnalysis, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString))); - connect(ui->backStage, SIGNAL(dataSetIORequest(FileEvent*)), this, SLOT(dataSetIORequest(FileEvent*))); +///// 3-connect ribbon itemSelected + connect(ui->backStage, SIGNAL(dataSetIORequest(FileEvent*)), this, SLOT(dataSetIORequest(FileEvent*))); connect(ui->backStage, SIGNAL(exportSelected(QString)), this, SLOT(exportSelected(QString))); connect(ui->variablesPage, SIGNAL(columnChanged(QString)), this, SLOT(refreshAnalysesUsingColumn(QString))); connect(ui->variablesPage, SIGNAL(resetTableView()), this, SLOT(resetTableView())); @@ -305,6 +302,7 @@ MainWindow::MainWindow(QWidget *parent) : } } + void MainWindow::open(QString filepath) { _openedUsingArgs = true; @@ -314,6 +312,7 @@ void MainWindow::open(QString filepath) _openOnLoadFilename = filepath; } + MainWindow::~MainWindow() { delete _engineSync; @@ -325,12 +324,14 @@ MainWindow::~MainWindow() delete ui; } + void MainWindow::resizeEvent(QResizeEvent *event) { QMainWindow::resizeEvent(event); adjustOptionsPanelWidth(); } + void MainWindow::dragEnterEvent(QDragEnterEvent *event) { const QMimeData *data = event->mimeData(); @@ -352,6 +353,7 @@ void MainWindow::dragEnterEvent(QDragEnterEvent *event) } } + void MainWindow::dropEvent(QDropEvent *event) { const QMimeData *data = event->mimeData(); @@ -361,6 +363,7 @@ void MainWindow::dropEvent(QDropEvent *event) event->accept(); } + void MainWindow::closeEvent(QCloseEvent *event) { _odm->clearAuthenticationOnExit(OnlineDataManager::OSF); @@ -387,6 +390,7 @@ void MainWindow::closeEvent(QCloseEvent *event) if (rd) rd->close(); } + void MainWindow::saveKeysSelected() { if (_package->isModified()) @@ -395,21 +399,25 @@ void MainWindow::saveKeysSelected() } } + void MainWindow::openKeysSelected() { } + void MainWindow::refreshKeysSelected() { refreshAllAnalyses(); } + void MainWindow::syncKeysSelected() { ui->backStage->sync(); } + void MainWindow::illegalOptionStateChanged() { if (_currentOptionsWidget == NULL) @@ -426,6 +434,7 @@ void MainWindow::illegalOptionStateChanged() } } + void MainWindow::packageChanged(DataSetPackage *package) { QString title = windowTitle(); @@ -440,9 +449,10 @@ void MainWindow::packageChanged(DataSetPackage *package) } } -void MainWindow::refreshAnalysesUsingColumns(vector &changedColumns - , vector &missingColumns - , map &changeNameColumns) + +void MainWindow::refreshAnalysesUsingColumns(vector &changedColumns, + vector &missingColumns, + map &changeNameColumns) { vector oldColumnNames; for (map::iterator it = changeNameColumns.begin(); it != changeNameColumns.end(); ++it) @@ -512,10 +522,11 @@ void MainWindow::refreshAnalysesUsingColumns(vector &changedColumns } } -void MainWindow::packageDataChanged(DataSetPackage *package - , vector &changedColumns - , vector &missingColumns - , map &changeNameColumns) + +void MainWindow::packageDataChanged(DataSetPackage *package, + vector &changedColumns, + vector &missingColumns, + map &changeNameColumns) { _tableModel->setDataSet(_package->dataSet); ui->variablesPage->setDataSet(_package->dataSet); @@ -559,6 +570,7 @@ QString MainWindow::escapeJavascriptString(const QString &str) return out; } + void MainWindow::analysisUserDataLoadedHandler(Analysis *analysis) { QString results = tq(analysis->userData().toStyledString()); @@ -567,6 +579,7 @@ void MainWindow::analysisUserDataLoadedHandler(Analysis *analysis) results = "window.loadUserData(" + QString::number(analysis->id()) + ", JSON.parse('" + results + "'));"; } + void MainWindow::analysisResultsChangedHandler(Analysis *analysis) { static bool showInstructions = true; @@ -609,6 +622,7 @@ void MainWindow::analysisResultsChangedHandler(Analysis *analysis) _package->setModified(true); } + void MainWindow::analysisSaveImageHandler(int id, QString options) { Analysis *analysis = _analyses->get(id); @@ -622,16 +636,16 @@ void MainWindow::analysisSaveImageHandler(int id, QString options) QString caption = "Save JASP Image"; QString filter = "Portable Network Graphics (*.png);;Portable Document Format (*.pdf);;Encapsulated PostScript (*.eps);;300 dpi Tagged Image File (*.tiff)"; - QString selectedFilter; + QString selectedFilter; - QString finalPath = QFileDialog::getSaveFileName(this, caption, QString(), filter, &selectedFilter); + QString finalPath = QFileDialog::getSaveFileName(this, caption, QString(), filter, &selectedFilter); if (!finalPath.isEmpty()) { - if (selectedFilter == "Encapsulated PostScript (*.eps)") + if (selectedFilter == "Encapsulated PostScript (*.eps)") { root["type"] = "eps"; - root["finalPath"] = finalPath.toStdString(); - analysis->saveImage(analysis, root); + root["finalPath"] = finalPath.toStdString(); + analysis->saveImage(analysis, root); } else if (selectedFilter == "Portable Document Format (*.pdf)") { @@ -647,16 +661,17 @@ void MainWindow::analysisSaveImageHandler(int id, QString options) } else { - QString imagePath = QString::fromStdString(tempfiles_sessionDirName()) + "/" + root.get("name", Json::nullValue).asCString(); + QString imagePath = QString::fromStdString(tempfiles_sessionDirName()) + "/" + root.get("name", Json::nullValue).asCString(); if (QFile::exists(finalPath)) { QFile::remove(finalPath); } QFile::copy(imagePath, finalPath); - } + } } } + void MainWindow::analysisImageSavedHandler(Analysis *analysis) { Json::Value results = analysis->getImgResults(); @@ -678,11 +693,13 @@ void MainWindow::analysisImageSavedHandler(Analysis *analysis) } } + AnalysisForm* MainWindow::loadForm(Analysis *analysis) { return loadForm(analysis->name()); } + AnalysisForm* MainWindow::loadForm(const string name) { if (_analysisForms.find(name) != _analysisForms.end()) @@ -748,22 +765,18 @@ AnalysisForm* MainWindow::loadForm(const string name) form = new AncovaBayesianForm(contentArea); else if (name == "AnovaRepeatedMeasuresBayesian") form = new AnovaRepeatedMeasuresBayesianForm(contentArea); - else if (name == "R11tLearn") - form = new R11tLearnForm(contentArea); else if (name == "BinomialTest") form = new BinomialTestForm(contentArea); else if (name == "MultinomialTest") form = new MultinomialTestForm(contentArea); else if (name == "BinomialTestBayesian") form = new BinomialTestBayesianForm(contentArea); - else if (name == "BFFromT") - form = new BFFromTForm(contentArea); else if (name == "ReliabilityAnalysis") form = new ReliabilityAnalysisForm(contentArea); else if (name == "ExploratoryFactorAnalysis") - form = new ExploratoryFactorAnalysisForm(contentArea); - else if (name == "PrincipalComponentAnalysis") - form = new PrincipalComponentAnalysisForm(contentArea); + form = new ExploratoryFactorAnalysisForm(contentArea); + else if (name == "PrincipalComponentAnalysis") + form = new PrincipalComponentAnalysisForm(contentArea); else if (name == "SummaryStatsTTestBayesianOneSample") form = new SummaryStatsTTestBayesianOneSampleForm(contentArea); else if (name == "SummaryStatsTTestBayesianIndependentSamples") @@ -776,15 +789,14 @@ AnalysisForm* MainWindow::loadForm(const string name) form = new SummaryStatsRegressionLinearBayesianForm(contentArea); else if (name == "SummaryStatsCorrelationBayesianPairs") form = new SummaryStatsCorrelationBayesianPairsForm(contentArea); - else if (name == "ClassicalMetaAnalysis") - form = new ClassicalMetaAnalysisForm(contentArea); -#ifdef QT_DEBUG - else if (name == "BASRegressionLinearLink") - form = new BASRegressionLinearLinkForm(contentArea); -#endif + else if (name == "ClassicalMetaAnalysis") + form = new ClassicalMetaAnalysisForm(contentArea); else if (name == "NetworkAnalysis") form = new NetworkAnalysisForm(contentArea); - else + else if (name == "ReinforcementLearningR11tLearning") + form = new ReinforcementLearningR11tLearningForm(contentArea); +///// 4-analysis if-else ladder + else qDebug() << "MainWindow::loadForm(); form not found : " << name.c_str(); if (form != NULL) @@ -793,6 +805,7 @@ AnalysisForm* MainWindow::loadForm(const string name) return form; } + void MainWindow::showForm(Analysis *analysis) { closeCurrentOptionsWidget(); @@ -801,7 +814,6 @@ void MainWindow::showForm(Analysis *analysis) if (_currentOptionsWidget != NULL) { - //sizing of options widget and panel to fit buttons and conform to largest size for consistency QObjectList siblings = _currentOptionsWidget->children(); @@ -821,8 +833,6 @@ void MainWindow::showForm(Analysis *analysis) } _currentOptionsWidget->setMinimumWidth(ui->panel_2_Options->minimumWidth() - _scrollbarWidth); - //######################### - Options *options = analysis->options(); DataSet *dataSet = _package->dataSet; _currentOptionsWidget->bindTo(options, dataSet); @@ -847,6 +857,7 @@ void MainWindow::showForm(Analysis *analysis) } } + void MainWindow::closeCurrentOptionsWidget() { if (_currentOptionsWidget != NULL) @@ -859,14 +870,13 @@ void MainWindow::closeCurrentOptionsWidget() } } + void MainWindow::analysisSelectedHandler(int id) { _currentAnalysis = _analyses->get(id); if (_currentAnalysis != NULL) { - QString currentModuleName = QString::fromStdString(_currentAnalysis->module()); - ui->tabBar->setCurrentTab(currentModuleName); showForm(_currentAnalysis); QString info("%1,%2"); @@ -878,9 +888,9 @@ void MainWindow::analysisSelectedHandler(int id) } } + void MainWindow::analysisUnselectedHandler() { - if (_currentAnalysis->useData()) hideOptionsPanel(); @@ -894,6 +904,7 @@ void MainWindow::analysisUnselectedHandler() } } + void MainWindow::tabChanged(int index) { if (index == 0) @@ -910,10 +921,10 @@ void MainWindow::tabChanged(int index) const Module& module = Module::getModule(currentActiveTab); ui->ribbon->setCurrentIndex(module.ribbonIndex()); } - } } + void MainWindow::helpToggled(bool on) { if (_log != NULL) @@ -943,6 +954,7 @@ void MainWindow::helpToggled(bool on) } } + void MainWindow::checkUsedModules() { QStringList usedModules; @@ -960,6 +972,7 @@ void MainWindow::checkUsedModules() ui->tabBar->setModulePlusMenu(usedModules); } + void MainWindow::dataSetIORequest(FileEvent *event) { if (event->operation() == FileEvent::FileOpen) @@ -981,7 +994,6 @@ void MainWindow::dataSetIORequest(FileEvent *event) } ui->tabBar->setCurrentModuleActive(); - } else if (event->operation() == FileEvent::FileSave) { @@ -1027,7 +1039,6 @@ void MainWindow::dataSetIORequest(FileEvent *event) _loader.io(event, _package); _progressIndicator->show(); - } else if (event->operation() == FileEvent::FileExportData) { @@ -1050,7 +1061,7 @@ void MainWindow::dataSetIORequest(FileEvent *event) { QString title = windowTitle(); title.chop(1); - QMessageBox::StandardButton reply = QMessageBox::warning(this, "Save Workspace?", QString("Save changes to workspace \"") + title + QString("\" before closing?\n\nYour changes will be lost if you don't save them."), QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel); + QMessageBox::StandardButton reply = QMessageBox::warning(this, "Save Workspace?", QString("Save changes to workspace \"") + title + QString("\" before closing?\n\nYour changes will be lost if you don't save them."), QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel); if (reply == QMessageBox::Save) { @@ -1079,6 +1090,7 @@ void MainWindow::dataSetIORequest(FileEvent *event) } } + void MainWindow::dataSetIOCompleted(FileEvent *event) { this->analysisOKed(); @@ -1090,7 +1102,7 @@ void MainWindow::dataSetIOCompleted(FileEvent *event) if (event->successful()) { populateUIfromDataSet(); - QString name = QFileInfo(event->path()).baseName(); + QString name = QFileInfo(event->path()).baseName(); setWindowTitle(name); _currentFilePath = event->path(); @@ -1126,7 +1138,7 @@ void MainWindow::dataSetIOCompleted(FileEvent *event) { if (event->successful()) { - QString name = QFileInfo(event->path()).baseName(); + QString name = QFileInfo(event->path()).baseName(); _package->setModified(false); setWindowTitle(name); @@ -1164,8 +1176,6 @@ void MainWindow::dataSetIOCompleted(FileEvent *event) if (_applicationExiting) QApplication::exit(); - - } else { @@ -1176,10 +1186,10 @@ void MainWindow::dataSetIOCompleted(FileEvent *event) if (showAnalysis) { ui->tabBar->setCurrentModuleActive(); - } } + void MainWindow::populateUIfromDataSet() { _tableModel->setDataSet(_package->dataSet); @@ -1206,7 +1216,6 @@ void MainWindow::populateUIfromDataSet() } else { - Json::Value analysesDataList = analysesData; if (!analysesData.isArray()) { analysesDataList = analysesData.get("analyses", Json::arrayValue); @@ -1245,7 +1254,6 @@ void MainWindow::populateUIfromDataSet() analysis->setUserData(userDataJson); analysis->setResults(resultsJson); - } catch (runtime_error e) { @@ -1276,17 +1284,20 @@ void MainWindow::populateUIfromDataSet() checkUsedModules(); } + void MainWindow::updateMenuEnabledDisabledStatus() { bool loaded = _package->isLoaded(); ui->ribbonAnalysis->setDataSetLoaded(loaded); ui->ribbonSEM->setDataSetLoaded(loaded); - ui->ribbonR11tLearn->setDataSetLoaded(loaded); - ui->ribbonMetaAnalysis->setDataSetLoaded(loaded); + ui->ribbonReinforcementLearning->setDataSetLoaded(loaded); + ui->ribbonMetaAnalysis->setDataSetLoaded(loaded); ui->ribbonNetworkAnalysis->setDataSetLoaded(loaded); +///// 5-ribbon updateMenuEnabledDisabledStatus } + void MainWindow::resultsPageLoaded(bool success) { // clear history, to prevent backspace from going 'back' @@ -1296,6 +1307,9 @@ void MainWindow::resultsPageLoaded(bool success) if (success) { QString version = tq(AppInfo::version.asString()); +#ifdef QT_DEBUG + version+="-Debug"; +#endif ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.setAppVersion('" + version + "')"); setExactPValuesHandler(_settings.value("displayExactPVals", 0).toBool()); @@ -1319,7 +1333,6 @@ void MainWindow::resultsPageLoaded(bool success) this->resize(this->width() + (ui->webViewResults->width() * (zoom - 1)), this->height() + (ui->webViewResults->height() * (zoom - 1))); #endif - _engineSync->setPPI(ppi); if (_openOnLoadFilename != "") @@ -1335,6 +1348,7 @@ void MainWindow::resultsPageLoaded(bool success) _engineSync->start(); } + void MainWindow::fatalError() { if (_log != NULL) @@ -1351,12 +1365,14 @@ void MainWindow::fatalError() } } + void MainWindow::helpFirstLoaded(bool ok) { if (ok) requestHelpPage("index"); } + void MainWindow::requestHelpPage(const QString &pageName) { QFile file(AppDirs::help() + "/" + pageName + ".md"); @@ -1384,6 +1400,7 @@ void MainWindow::requestHelpPage(const QString &pageName) ui->webViewHelp->page()->mainFrame()->evaluateJavaScript(js); } + void MainWindow::setExactPValuesHandler(bool exactPValues) { QString exactPValueString = (exactPValues ? "true" : "false"); @@ -1391,6 +1408,7 @@ void MainWindow::setExactPValuesHandler(bool exactPValues) ui->webViewResults->page()->mainFrame()->evaluateJavaScript(js); } + void MainWindow::setFixDecimalsHandler(QString numDecimals) { if (numDecimals == "") @@ -1399,6 +1417,7 @@ void MainWindow::setFixDecimalsHandler(QString numDecimals) ui->webViewResults->page()->mainFrame()->evaluateJavaScript(js); } + void MainWindow::emptyValuesChangedHandler() { if (_package->isLoaded()) @@ -1439,11 +1458,13 @@ void MainWindow::emptyValuesChangedHandler() } } + void MainWindow::linkClickedSlot(QUrl url) { QDesktopServices::openUrl ( url ); } + void MainWindow::itemSelected(const QString &item) { try @@ -1472,6 +1493,7 @@ void MainWindow::itemSelected(const QString &item) } } + void MainWindow::saveTextToFileHandler(const QString &filename, const QString &data) { if (filename == "%PREVIEW%" || filename == "%EXPORT%") @@ -1492,11 +1514,13 @@ void MainWindow::saveTextToFileHandler(const QString &filename, const QString &d } } + void MainWindow::exportSelected(const QString &filename) { ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.exportHTML('" + filename + "');"); } + void MainWindow::adjustOptionsPanelWidth() { if (ui->panel_2_Options->width() == ui->panel_2_Options->maximumWidth() && ui->panel_1_Data->isHidden()) @@ -1511,12 +1535,14 @@ void MainWindow::adjustOptionsPanelWidth() _buttonPanel->move(ui->panel_2_Options->width() - _buttonPanel->width() - _scrollbarWidth, 0); } + void MainWindow::splitterMovedHandler(int, int) { adjustOptionsPanelWidth(); _tableViewWidthBeforeOptionsMadeVisible = -1; } + void MainWindow::hideOptionsPanel() { int newTableWidth = 0; @@ -1545,6 +1571,7 @@ void MainWindow::hideOptionsPanel() ui->splitter->setSizes(sizes); } + void MainWindow::showOptionsPanel() { QList sizes = ui->splitter->sizes(); @@ -1591,6 +1618,7 @@ void MainWindow::showOptionsPanel() _buttonPanel->move(ui->panel_2_Options->width() - _buttonPanel->width() - _scrollbarWidth, 0); } + void MainWindow::showDataPanel() { QList sizes = ui->splitter->sizes(); @@ -1604,6 +1632,7 @@ void MainWindow::showDataPanel() ui->panel_1_Data->show(); } + void MainWindow::hideDataPanel() { QList sizes = ui->splitter->sizes(); @@ -1622,6 +1651,7 @@ void MainWindow::hideDataPanel() ui->splitter->setSizes(sizes); } + void MainWindow::showVariablesPage() { QList datacurrentSizes = ui->data_splitter->sizes(); @@ -1636,6 +1666,7 @@ void MainWindow::showVariablesPage() } } + void MainWindow::analysisOKed() { if (_currentOptionsWidget != NULL) @@ -1657,6 +1688,7 @@ void MainWindow::analysisOKed() hideOptionsPanel(); } + void MainWindow::analysisRunned() { if (_currentAnalysis == NULL) @@ -1668,6 +1700,7 @@ void MainWindow::analysisRunned() _currentAnalysis->scheduleRun(); } + void MainWindow::removeAnalysis(Analysis *analysis) { bool selected = false; @@ -1700,6 +1733,7 @@ void MainWindow::removeAnalysis(Analysis *analysis) checkUsedModules(); } + void MainWindow::removeAllAnalyses() { QMessageBox::StandardButton reply; @@ -1716,6 +1750,7 @@ void MainWindow::removeAllAnalyses() } } + void MainWindow::refreshAllAnalyses() { for (Analyses::iterator it = _analyses->begin(); it != _analyses->end(); ++it) @@ -1726,6 +1761,7 @@ void MainWindow::refreshAllAnalyses() } } + void MainWindow::refreshAnalysesUsingColumn(QString col) { std::vector changedColumns, missingColumns; @@ -1736,11 +1772,13 @@ void MainWindow::refreshAnalysesUsingColumn(QString col) _package->setModified(false); } + void MainWindow::resetTableView() { ui->tableView->reset(); } + void MainWindow::pushToClipboardHandler(const QString &mimeType, const QString &data, const QString &html) { if (_log != NULL) @@ -1760,6 +1798,7 @@ void MainWindow::pushToClipboardHandler(const QString &mimeType, const QString & //qDebug() << clipboard->mimeData(QClipboard::Clipboard)->data("text/html"); } + void MainWindow::pushImageToClipboardHandler(const QByteArray &base64, const QString &html) { if (_log != NULL) @@ -1782,7 +1821,6 @@ void MainWindow::pushImageToClipboardHandler(const QByteArray &base64, const QSt #else mimeData->setImageData(pm); #endif - } if ( ! html.isEmpty()) @@ -1797,6 +1835,7 @@ void MainWindow::pushImageToClipboardHandler(const QByteArray &base64, const QSt //qDebug() << clipboard->mimeData(QClipboard::Clipboard)->data("text/html"); } + void MainWindow::saveTempImageHandler(int id, QString path, QByteArray data) { QByteArray byteArray = QByteArray::fromBase64(data); @@ -1812,11 +1851,13 @@ void MainWindow::saveTempImageHandler(int id, QString path, QByteArray data) ui->webViewResults->page()->mainFrame()->evaluateJavaScript(eval); } + void MainWindow::displayMessageFromResultsHandler(QString msg) { QMessageBox::warning(this, "Results Warning", msg); } + void MainWindow::showAnalysesMenuHandler(QString options) { Json::Value menuOptions; @@ -1882,7 +1923,6 @@ void MainWindow::showAnalysesMenuHandler(QString options) } } - if (menuOptions["hasRemove"].asBool()) { _analysisMenu->addSeparator(); @@ -1907,12 +1947,14 @@ void MainWindow::showAnalysesMenuHandler(QString options) _analysisMenu->show(); } + void MainWindow::removeAnalysisRequestHandler(int id) { Analysis *analysis = _analyses->get(id); removeAnalysis(analysis); } + Json::Value MainWindow::getResultsMeta() { QVariant metaData = ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.getResultsMeta();"); @@ -1924,6 +1966,7 @@ Json::Value MainWindow::getResultsMeta() return meta; } + void MainWindow::getAnalysesUserData() { QVariant userData = ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.getAllUserData();"); @@ -1944,11 +1987,13 @@ void MainWindow::getAnalysesUserData() } } + void MainWindow::resultsDocumentChangedHandler() { _package->setModified(true); } + void MainWindow::simulatedMouseClickHandler(int x, int y, int count) { int diff = count; @@ -1957,7 +2002,7 @@ void MainWindow::simulatedMouseClickHandler(int x, int y, int count) { QMouseEvent * clickEvent = new QMouseEvent ((QEvent::MouseButtonDblClick), QPoint(x * _webViewZoom, y * _webViewZoom), Qt::LeftButton, Qt::LeftButton, - Qt::NoModifier ); + Qt::NoModifier); qApp->postEvent((QObject*)ui->webViewResults,(QEvent *)clickEvent); @@ -1969,19 +2014,20 @@ void MainWindow::simulatedMouseClickHandler(int x, int y, int count) { QMouseEvent * clickEvent1 = new QMouseEvent ((QEvent::MouseButtonPress), QPoint(x * _webViewZoom, y * _webViewZoom), Qt::LeftButton, Qt::LeftButton, - Qt::NoModifier ); + Qt::NoModifier); qApp->postEvent((QObject*)ui->webViewResults,(QEvent *)clickEvent1); QMouseEvent * clickEvent2 = new QMouseEvent ((QEvent::MouseButtonRelease), QPoint(x * _webViewZoom, y * _webViewZoom), Qt::LeftButton, Qt::LeftButton, - Qt::NoModifier ); + Qt::NoModifier); qApp->postEvent((QObject*)ui->webViewResults,(QEvent *)clickEvent2); } } + void MainWindow::updateUserDataHandler(int id, QString key) { _package->setModified(true); @@ -1993,34 +2039,40 @@ void MainWindow::collapseSelected() ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.collapseMenuClicked();"); } + void MainWindow::removeSelected() { ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.removeMenuClicked();"); } + void MainWindow::editTitleSelected() { ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.editTitleMenuClicked();"); _package->setModified(true); } + void MainWindow::copySelected() { tempfiles_purgeClipboard(); ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.copyMenuClicked();"); } + void MainWindow::citeSelected() { tempfiles_purgeClipboard(); ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.citeMenuClicked();"); } + void MainWindow::saveImage() { ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.saveImageClicked();"); } + void MainWindow::noteSelected() { QAction *action = (QAction *)this->sender(); @@ -2031,17 +2083,20 @@ void MainWindow::noteSelected() _package->setModified(true); } + void MainWindow::menuHidding() { ui->webViewResults->page()->mainFrame()->evaluateJavaScript("window.analysisMenuHidden();"); } + void MainWindow::scrollValueChangedHandle() { if ( ! _analysisMenu->isHidden()) _analysisMenu->hide(); } + void MainWindow::analysisChangedDownstreamHandler(int id, QString options) { Analysis *analysis = _analyses->get(id); @@ -2131,9 +2186,9 @@ void MainWindow::startDataEditorHandler() } else startDataEditor(path); - } + void MainWindow::startDataEditorEventCompleted(FileEvent* event) { _progressIndicator->hide(); @@ -2147,6 +2202,7 @@ void MainWindow::startDataEditorEventCompleted(FileEvent* event) } } + void MainWindow::startDataEditor(QString path) { QFileInfo fileInfo(path); diff --git a/JASP-Desktop/mainwindow.h b/JASP-Desktop/mainwindow.h index 1418e3b2aa..e5f74bf1a2 100644 --- a/JASP-Desktop/mainwindow.h +++ b/JASP-Desktop/mainwindow.h @@ -209,9 +209,9 @@ private slots: void helpFirstLoaded(bool ok); void requestHelpPage(const QString &pageName); - void setExactPValuesHandler(bool exactPValues); - void setFixDecimalsHandler(QString numDecimals); - void emptyValuesChangedHandler(); + void setExactPValuesHandler(bool exactPValues); + void setFixDecimalsHandler(QString numDecimals); + void emptyValuesChangedHandler(); void linkClickedSlot(QUrl url); }; diff --git a/JASP-Desktop/mainwindow.ui b/JASP-Desktop/mainwindow.ui index 8dd3918400..3269d09feb 100644 --- a/JASP-Desktop/mainwindow.ui +++ b/JASP-Desktop/mainwindow.ui @@ -181,10 +181,11 @@ QPushButton::menu-indicator { - + + @@ -634,17 +635,18 @@ QTableView::item::last 1 - RibbonR11tLearn + RibbonSummaryStatistics QWidget -
ribbons/ribbonr11tlearn.h
+
ribbons/ribbonsummarystatistics.h
1
- RibbonSummaryStatistics + RibbonReinforcementLearning QWidget -
ribbons/ribbonsummarystatistics.h
+
ribbons/ribbonreinforcementlearning.h
1
+ TabBar QWidget diff --git a/JASP-Desktop/module.cpp b/JASP-Desktop/module.cpp index b02aa1bc33..e58ab060ed 100644 --- a/JASP-Desktop/module.cpp +++ b/JASP-Desktop/module.cpp @@ -9,10 +9,11 @@ map Module::AllModules = { #ifndef __linux__ {"SEM", Module("SEM", 1)}, #endif - {"R11tLearn", Module("R11tLearn", "Reinforcement Learning", 2, false)}, + { "ReinforcementLearning", Module("ReinforcementLearning", "Reinforcement Learning", 2, false)}, {"SummaryStats", Module("SummaryStats", "Summary Stats", 3)}, {"MetaAnalysis", Module("MetaAnalysis", "Meta Analysis", 4)}, - {"Network", Module("Network", 5)} + {"Network", Module("Network", 5)}, +///// ribbon tab number: 6 }; diff --git a/JASP-Desktop/ribbons/ribbonanalysis.cpp b/JASP-Desktop/ribbons/ribbonanalysis.cpp index e5916d130a..551ffc4679 100644 --- a/JASP-Desktop/ribbons/ribbonanalysis.cpp +++ b/JASP-Desktop/ribbons/ribbonanalysis.cpp @@ -33,12 +33,8 @@ RibbonAnalysis::RibbonAnalysis(QWidget *parent) : addRibbonButton(ui->anovaButton); addRibbonButton(ui->frequenciesButton); addRibbonButton(ui->regressionButton); - addRibbonButton(ui->BFFromT); addRibbonButton(ui->factoranalysisButton); - ui->BFFromT->setDataSetNotNeeded(); - - // connect(ui->Descriptives, SIGNAL(clicked()), this, SLOT(itemSelected())); QMenu *menu; @@ -90,10 +86,6 @@ RibbonAnalysis::RibbonAnalysis(QWidget *parent) : menu->addAction(QString("Bayesian Correlation Pairs"), this, SLOT(itemSelected()))->setObjectName("CorrelationBayesianPairs"); menu->addAction(QString("Bayesian Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLinearBayesian"); -#ifdef QT_DEBUG - menu->addSeparator(); - menu->addAction(QString("BAS Regression Linear link"), this, SLOT(itemSelected()))->setObjectName("BASRegressionLinearLink"); -#endif ui->regressionButton->setMenu(menu); @@ -118,15 +110,6 @@ RibbonAnalysis::RibbonAnalysis(QWidget *parent) : menu->addAction(QString("Exploratory Factor Analysis"), this, SLOT(itemSelected()))->setObjectName("ExploratoryFactorAnalysis"); ui->factoranalysisButton->setMenu(menu); - -#ifndef QT_DEBUG - ui->BFFromT->hide(); -#else - menu = new QMenu(this); - menu->addAction(QString("BF From t"), this, SLOT(itemSelected()))->setObjectName("BFFromT"); - - ui->BFFromT->setMenu(menu); -#endif } RibbonAnalysis::~RibbonAnalysis() diff --git a/JASP-Desktop/ribbons/ribbonanalysis.ui b/JASP-Desktop/ribbons/ribbonanalysis.ui index 3ecbb245e5..da2b0b99c7 100644 --- a/JASP-Desktop/ribbons/ribbonanalysis.ui +++ b/JASP-Desktop/ribbons/ribbonanalysis.ui @@ -172,35 +172,6 @@
- - - - - 76 - 0 - - - - BF from t - - - - :/icons/analysis-bayesian-ttest.svg:/icons/analysis-bayesian-ttest.svg - - - - 37 - 28 - - - - QToolButton::InstantPopup - - - Qt::ToolButtonTextUnderIcon - - -
@@ -419,6 +390,7 @@ + diff --git a/JASP-Desktop/ribbons/ribbonreinforcementlearning.cpp b/JASP-Desktop/ribbons/ribbonreinforcementlearning.cpp new file mode 100644 index 0000000000..3777267f66 --- /dev/null +++ b/JASP-Desktop/ribbons/ribbonreinforcementlearning.cpp @@ -0,0 +1,41 @@ +// +// Copyright (C) 2013-2017 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with this program. If not, see +// . +// + +#include "ribbonreinforcementlearning.h" +#include "ui_ribbonreinforcementlearning.h" + +///// additional Headers + +RibbonReinforcementLearning::RibbonReinforcementLearning(QWidget *parent) : + RibbonWidget(parent), + ui(new Ui::RibbonReinforcementLearning) +{ + ui->setupUi(this); + + addRibbonButton(ui->buttonR11tLearning); + + ui->buttonR11tLearning->setObjectName("ReinforcementLearningR11tLearning"); + connect(ui->buttonR11tLearning, SIGNAL(clicked()), this, SLOT(itemSelected())); +///// Ribbon Buttons and Menu + +} + +RibbonReinforcementLearning::~RibbonReinforcementLearning() +{ + delete ui; +} diff --git a/JASP-Desktop/ribbons/ribbonreinforcementlearning.h b/JASP-Desktop/ribbons/ribbonreinforcementlearning.h new file mode 100644 index 0000000000..45ba52219f --- /dev/null +++ b/JASP-Desktop/ribbons/ribbonreinforcementlearning.h @@ -0,0 +1,40 @@ +// +// Copyright (C) 2013-2017 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with this program. If not, see +// . +// + +#ifndef RIBBONREINFORCEMENTLEARNING_H +#define RIBBONREINFORCEMENTLEARNING_H + +#include "ribbonwidget.h" + +namespace Ui { + class RibbonReinforcementLearning; +} + +class RibbonReinforcementLearning : public RibbonWidget +{ + Q_OBJECT + +public: + explicit RibbonReinforcementLearning(QWidget *parent = 0); + ~RibbonReinforcementLearning(); + +private: + Ui::RibbonReinforcementLearning *ui; +}; + +#endif // RIBBONREINFORCEMENTLEARNING_H diff --git a/JASP-Desktop/ribbons/ribbonr11tlearn.ui b/JASP-Desktop/ribbons/ribbonreinforcementlearning.ui similarity index 58% rename from JASP-Desktop/ribbons/ribbonr11tlearn.ui rename to JASP-Desktop/ribbons/ribbonreinforcementlearning.ui index c0341c9df5..95ff845e91 100644 --- a/JASP-Desktop/ribbons/ribbonr11tlearn.ui +++ b/JASP-Desktop/ribbons/ribbonreinforcementlearning.ui @@ -1,7 +1,7 @@ - RibbonR11tLearn - + RibbonReinforcementLearning + 0 @@ -13,55 +13,53 @@ Form - + - 0 + 4 0 - 3 + 4 - - - - - 1 - - - 12 - - - 1 - - - 12 - - - + + 0 + + + + + Qt::Horizontal + + + + 61 + 20 + + + - - - - 0 - + + - 6 + 0 6 - 6 + 0 - 0 + 6 - - - + + 3 + + + + 0 @@ -74,11 +72,17 @@ 0 - - 3 + + 5 - + + + + 76 + 0 + + R11t Learning @@ -100,6 +104,8 @@ + + @@ -107,36 +113,24 @@ - - - - 1 - - - 12 - - - 1 - - - 12 - + + + QWidget { color : #929292 ; } + + + + + + QFrame::Plain + + + Qt::Vertical + + + - - - - Qt::Horizontal - - - - 630 - 20 - - - - @@ -149,25 +143,9 @@ - - - R11tLearn - clicked() - RibbonR11tLearn - itemSelected() - - - 72 - 33 - - - 383 - 41 - - - - + itemSelected() + diff --git a/JASP-Desktop/ribbons/ribbonsummarystatistics.cpp b/JASP-Desktop/ribbons/ribbonsummarystatistics.cpp index 418914ac89..0ac6a09242 100644 --- a/JASP-Desktop/ribbons/ribbonsummarystatistics.cpp +++ b/JASP-Desktop/ribbons/ribbonsummarystatistics.cpp @@ -47,7 +47,7 @@ RibbonSummaryStatistics::RibbonSummaryStatistics(QWidget *parent) : menu = new QMenu(this); menu->addAction(QString("Bayesian Correlation Pairs"), this, SLOT(itemSelected()))->setObjectName("SummaryStatsCorrelationBayesianPairs"); menu->addAction(QString("Bayesian Linear Regression"), this, SLOT(itemSelected()))->setObjectName("SummaryStatsRegressionLinearBayesian"); - + ui->regressionButton->setMenu(menu); menu = new QMenu(this); diff --git a/JASP-Desktop/widgets/tabbar.cpp b/JASP-Desktop/widgets/tabbar.cpp index 0f61338200..a4382fbe4f 100755 --- a/JASP-Desktop/widgets/tabbar.cpp +++ b/JASP-Desktop/widgets/tabbar.cpp @@ -24,10 +24,10 @@ using namespace std; + TabBar::TabBar(QWidget *parent) : QWidget(parent) { - _helpTab = NULL; _background = new QWidget(this); @@ -236,15 +236,17 @@ void TabBar::init() } + void TabBar::showAbout() { _aboutDialog->show(); _aboutDialog->raise(); _aboutDialog->activateWindow(); - //The last function performs the same operation as clicking the mouse on the title bar - //If you want to ensure that the window is stacked on top as well you should also call raise(). //Note that the window must be visible, otherwise activateWindow() has no effect. + // The last function performs the same operation as clicking the mouse on the title bar + // If you want to ensure that the window is stacked on top as well you should also call raise(). //Note that the window must be visible, otherwise activateWindow() has no effect. } + void TabBar::showPreferences() { _preferencesDialog->show(); @@ -252,6 +254,7 @@ void TabBar::showPreferences() _preferencesDialog->activateWindow(); } + void TabBar::toggleHelp() { static bool on; @@ -301,11 +304,13 @@ void TabBar::handleModuleButton() _modulesButton->setAttribute(Qt::WA_UnderMouse, false); } + int TabBar::count() const { return _tabButtons.length(); } + PreferencesDialog *TabBar::getPreferencesDialog() { return _preferencesDialog; @@ -317,21 +322,25 @@ void TabBar::setCurrentModuleActive() setCurrentTab(_currentModule->objectName()); } + void TabBar::setExactPValues(bool exactPValues) { emit setExactPValuesHandler(exactPValues); } + void TabBar::setFixDecimals(QString numDecimals) { emit setFixDecimalsHandler(numDecimals); } + void TabBar::emptyValuesChanged() { emit emptyValuesChangedHandler(); } + void TabBar::setCurrentTab(QString name) { int i = 0, index = -1; @@ -367,6 +376,7 @@ QString TabBar::getCurrentActiveTab() return _currentTab ? _currentTab->objectName() : QString(); } + void TabBar::helpToggledHandler(bool on) { emit helpToggled(on); diff --git a/JASP-Desktop/widgets/tablemodelvariablesoptions.cpp b/JASP-Desktop/widgets/tablemodelvariablesoptions.cpp index 6188d706aa..870ec53b2c 100644 --- a/JASP-Desktop/widgets/tablemodelvariablesoptions.cpp +++ b/JASP-Desktop/widgets/tablemodelvariablesoptions.cpp @@ -159,13 +159,29 @@ void TableModelVariablesOptions::setVariables(const Terms &variables) beginResetModel(); - _rows.clear(); + std::vector oldRows = _rows; + _rows.clear(); + + // BOOST_FOREACH(const Term &term, variables) { Options *row = static_cast(_boundTo->rowTemplate()->clone()); - OptionTerms *termCell = static_cast(row->get(0)); - termCell->setValue(term.scomponents()); + OptionTerms *termCell = static_cast(row->get(0)); + bool found = false; + BOOST_FOREACH(Options* option, oldRows) + { + Json::Value json = option->asJSON(); + string var = json["variable"].asString(); + if (term.asString() == var) + { + row = option; + found = true; + break; + } + } + if (!found) + termCell->setValue(term.scomponents()); _rows.push_back(row); } diff --git a/JASP-Engine/JASP-Engine.pro b/JASP-Engine/JASP-Engine.pro index c6d3f54207..82f3f985aa 100644 --- a/JASP-Engine/JASP-Engine.pro +++ b/JASP-Engine/JASP-Engine.pro @@ -75,6 +75,7 @@ INCLUDEPATH += \ linux:INCLUDEPATH += \ /usr/share/R/include \ + /usr/lib/R/library/include \ $$_R_HOME/site-library/Rcpp/include macx:LIBS += \ @@ -124,8 +125,6 @@ OTHER_FILES += \ JASP/R/anovarepeatedmeasures.R \ JASP/R/anovarepeatedmeasuresbayesian.R \ JASP/R/base64.R \ - JASP/R/basregressionlinearlink.R \ - JASP/R/bffromt.R \ JASP/R/binomialtest.R \ JASP/R/binomialtestbayesian.R \ JASP/R/common.R \ diff --git a/JASP-Engine/JASP/R/basregressionlinearlink.R b/JASP-Engine/JASP/R/BASregressionlinearbayesian.R similarity index 63% rename from JASP-Engine/JASP/R/basregressionlinearlink.R rename to JASP-Engine/JASP/R/BASregressionlinearbayesian.R index 39fccb821a..188cb875ea 100644 --- a/JASP-Engine/JASP/R/basregressionlinearlink.R +++ b/JASP-Engine/JASP/R/BASregressionlinearbayesian.R @@ -15,7 +15,7 @@ # along with this program. If not, see . # -BASRegressionLinearLink <- function ( +RegressionLinearBayesian <- function ( dataset = NULL, options, perform = "run", @@ -26,11 +26,12 @@ BASRegressionLinearLink <- function ( # Configure the state modelOpts <- c("dependent", "covariates", "wlsWeights", "modelTerms", - "priorRegressionCoefficients", "gPriorParameter", + "priorRegressionCoefficients", "alpha", "rScale", "modelPrior", "betaBinomialParamA", "betaBinomialParamB", "bernoulliParam", "samplingMethod", "iterationsMCMC", "numberOfModels") stateKey <- list( bas_obj = modelOpts, + postSummary = c(modelOpts, "postSummary", "summaryType"), descriptives = c("dependent", "covariates"), plotPosteriorLogOdds = c(modelOpts, "plotLogPosteriorOdds"), plotCoefficientsPosterior = c(modelOpts, "plotCoefficientsPosterior"), @@ -42,6 +43,7 @@ BASRegressionLinearLink <- function ( # Initialize the variables bas_obj <- state$bas_obj + postSummary <- state$postSummary descriptives <- state$descriptives plotPosteriorLogOdds <- state$plotPosteriorLogOdds plotCoefficientsPosterior <- state$plotCoefficientsPosterior @@ -93,6 +95,12 @@ BASRegressionLinearLink <- function ( options = options ) } + + if (options$postSummary && is.null(postSummary)) { + postSummary <- .posteriorSummaryTable.basReg( + bas_obj, status, perform, options + ) + } if (options$descriptives && is.null(descriptives)) { descriptives <- .descriptivesTable.basReg( @@ -139,11 +147,15 @@ BASRegressionLinearLink <- function ( # Assign to results results <- list() results[[".meta"]] <- .createMeta.basReg() - results[["title"]] <- "Bayesian Adaptive Sampling" + results[["title"]] <- "Bayesian Linear Regression" results[["regressionTable"]] <- .fillRegTable.basReg(data = regTableData, status = status, perform = perform, options = options) + if (options$postSummary) { + results[["posteriorSummaryTable"]] <- postSummary + } + if (options$descriptives) { results[["descriptivesTable"]] <- descriptives } @@ -184,9 +196,16 @@ BASRegressionLinearLink <- function ( plotInclusionProbabilities$data ) + # code below tries to avoid weird behaviour from bas_obj that chrashes base::save. + attr(attr(bas_obj[["model"]], "terms"), ".Environment") <- NULL + attr(bas_obj$terms, ".Environment") <- NULL + # reparsing the object seems to avoid errors with base::save. + try(bas_obj[["mle.se"]] <- eval(parse(text = capture.output(dput(bas_obj[["mle.se"]]))))) + state <- list( options = options, bas_obj = bas_obj, + postSummary = postSummary, descriptives = descriptives, plotPosteriorLogOdds = plotPosteriorLogOdds, plotCoefficientsPosterior = plotCoefficientsPosterior, @@ -200,7 +219,7 @@ BASRegressionLinearLink <- function ( attr(state, "key") <- stateKey } - return (list( + return(list( keep = keep, results = results, status = statusAnalysis, @@ -217,8 +236,9 @@ BASRegressionLinearLink <- function ( meta <- list() meta[[1]] <- list(name = "regressionTable", type = "table") - meta[[2]] <- list(name = "descriptivesTable", type = "table") - meta[[3]] <- list( + meta[[2]] <- list(name = "posteriorSummaryTable", type = "table") + meta[[3]] <- list(name = "descriptivesTable", type = "table") + meta[[4]] <- list( name="inferentialPlots", type="object", meta=list( @@ -238,7 +258,7 @@ BASRegressionLinearLink <- function ( ))) ) - return (meta) + return(meta) } .readData.basReg <- function(perform, options) { @@ -262,7 +282,7 @@ BASRegressionLinearLink <- function ( dataset <- .readDataSetHeader(columns.as.numeric = vars) } - return (dataset) + return(dataset) } .setStatus.basReg <- function(dataset, perform, options) { @@ -282,7 +302,7 @@ BASRegressionLinearLink <- function ( status$ready <- FALSE } - customChecks <- list( + customChecks <- list( #TODO: add these to hasErrors officially function() { nuisanceTerms <- sapply(options$modelTerms, function(term) term$isNuisance) if (sum(nuisanceTerms) == length(options$modelTerms)) { @@ -390,52 +410,34 @@ BASRegressionLinearLink <- function ( wlsWeights <- dataset[[ .v(weightsVar) ]] } - # sampling method - if (options$samplingMethod == "MCMCBAS") { - samplingMethod <- "MCMC+BAS" - } else { - samplingMethod <- options$samplingMethod - } - # select the type of model prior if (options$modelPrior == "beta.binomial") { - modelPrior = BAS::beta.binomial(options$betaBinomialParamA, options$betaBinomialParamB) + modelPrior <- BAS::beta.binomial(options$betaBinomialParamA, options$betaBinomialParamB) } else if (options$modelPrior == "uniform") { - modelPrior = BAS::uniform() + modelPrior <- BAS::uniform() } else if (options$modelPrior == "Bernoulli") { - modelPrior = BAS::Bernoulli(options$bernoulliParam) + modelPrior <- BAS::Bernoulli(options$bernoulliParam) } # number of models - n.models <- options$numberOfModels - if (n.models == 0) { - n.models <- NULL + n.models <- NULL + if (options$samplingMethod == "BAS" && options$numberOfModels > 0) { + n.models <- options$numberOfModels } # iterations for MCMC - MCMC.iterations <- options$iterationsMCMC - if (grepl("MCMC", samplingMethod, fixed = TRUE)) { - # if iterations is not set by user - if (MCMC.iterations == 0) { - MCMC.iterations <- NULL - } - - if (is.null(n.models)) { - MCMC.iterations <- NULL - } else { - MCMC.iterations <- options$numberOfModels * 10 #FIXME: should we allow models to influence MCMC samples? - } + MCMC.iterations <- NULL + if (options$samplingMethod == "MCMC" && options$iterationsMCMC > 0) { + MCMC.iterations <- options$numberOfModels } - # hyper parameter for g-prior + # parameter for hyper-g's or jzs (all use same alpha param in bas.lm) alpha <- switch( options$priorRegressionCoefficients, - g_prior =, - hyper_g =, - hyper_g_laplace =, - hyper_g_n=, - zs_null =, - zs_full = options$gPriorParameter, + hyper_g = options$alpha, + hyper_g_laplace = options$alpha, + hyper_g_n = options$alpha, + JZS = options$rScale^2, NULL ) @@ -447,10 +449,11 @@ BASRegressionLinearLink <- function ( alpha = alpha, modelprior = modelPrior, n.models = n.models, - method = samplingMethod, + method = options$samplingMethod, MCMC.iterations = MCMC.iterations, initprobs = initProbs, - weights = wlsWeights + weights = wlsWeights, + renormalize = TRUE )) if (isTryError(bas_lm)) { @@ -494,7 +497,6 @@ BASRegressionLinearLink <- function ( } # ordered indices based on posterior probabilities of the models - # TODO: determine if we like this functionality ^.^ models.ordered <- order(bas_obj$postprobs, decreasing = TRUE) if (options$bayesFactorOrder == "nullModelTop") { bestModelIndices <- models.ordered[1:nRows] @@ -502,7 +504,8 @@ BASRegressionLinearLink <- function ( index <- which(bestModelIndices == 1) models.ordered <- c(1, bestModelIndices[-index]) # change position of null model } else { - models.ordered <- c(1, bestModelIndices[-nRows]) # remove last model + nRows <- nRows + 1 # show null model + best n + models.ordered <- c(1, bestModelIndices) } } else { # best model top models.ordered <- models.ordered[1:nRows] @@ -545,46 +548,41 @@ BASRegressionLinearLink <- function ( bas_obj$logmarg[models.ordered][1] } + # calculate the BFM for the models + nModels <- length(bas_obj$postprobs) + postProbs <- bas_obj$postprobs + priorProbs <- bas_obj$priorprobs + index <- which(is.finite(postProbs)) + BFM <- sapply(1:nModels, function(m) { + if (m %in% index) { + i <- which(index == m) + (postProbs[m] / (1 - postProbs[m])) / (priorProbs[m] / (1 - priorProbs[m])) + } else { + NA + } + }) + BFM <- BFM[models.ordered] + + # populate the row list output.rows <- vector("list", nRows) - - # TODO: microbenchmark - compare for loop against using mapply for (i in 1:nRows) { output.rows[[i]] <- list( - "Models" = model.names[i], - "BF" = models.bf[i], - "P(M|data)" = bas_obj$postprobs[[models.ordered[i]]], - "R2" = bas_obj$R2[[models.ordered[i]]], - "P(M)" = bas_obj$priorprobs[[models.ordered[i]]], - "logmarg" = bas_obj$logmarg[[models.ordered[i]]] + "Models" = .clean(model.names[i]), + "BF" = .clean(models.bf[i]), + "BFM" = .clean(BFM[i]), + "P(M|data)" = .clean(bas_obj$postprobs[[models.ordered[i]]]), + "R2" = .clean(bas_obj$R2[[models.ordered[i]]]), + "P(M)" = .clean(bas_obj$priorprobs[[models.ordered[i]]]) ) } # notes - footnotes <- NULL + footnotes <- .newFootnotes() if (sum(nuisanceTerms) > 0) { - footnotes <- .newFootnotes() footnote <- paste("All models include ", paste(.unvf(names(which(nuisanceTerms))), collapse = ", "), ".", sep = "") .addFootnote(footnotes, symbol = "Note.", text = footnote) } - # output.list <- as.list(data.frame(mapply(c, models.names, models.bf))) - # - # # Generate the output row - # output.rows <- vector("list", length(output.list)) - # row.number <- 1 - # - # for (row in output.list) { - # output.rows - # } - # - # output.row <- base::lapply( - # output.list, - # function(x) { - # names(x) <- c("model", "bf") - # return (as.list(x)) - # } - # ) - return(list(rows=output.rows, notes=footnotes)) } @@ -613,14 +611,11 @@ BASRegressionLinearLink <- function ( list(name = "Models", type = "string"), list(name = "P(M)", type = "number", format = "sf:4;dp:3"), list(name = "P(M|data)", type = "number", format = "sf:4;dp:3"), + list(name = "BFM", type = "number", format = "sf:4;dp:3", title = "BFM"), list(name = "BF", type = "number", format = "sf:4;dp:3", title = paste(bf.title, sep = "")), list(name = "R2", type = "number", format = "dp:3", title = "R\u00B2") ) - if (options$logmarg) { - fields[[length(fields)+1]] <- list(name = "logmarg", type = "number", format = "sf:4;dp:3", title = "Log likelihood") - } - table <- list() table[["title"]] <- "Model Comparison" table[["citation"]] <- list( @@ -640,7 +635,72 @@ BASRegressionLinearLink <- function ( table[["error"]] <- list(errorType = "badData", errorMessage = status$error.message) } - return (table) + return(table) +} + +.posteriorSummaryTable.basReg <- function(bas_obj, status, perform, options) { + # Generate a posterior summary table of the coefficients + # + # Args: + # bas_obj: data read by .readData.basReg() + # status: current status of the analysis + # perform: 'run' or 'init' + # options: a list of user options + # + # Return: + # List with completed posterior table; may be inserted in results as is + + posterior <- list() + + posterior[["title"]] <- "Marginal Posterior Summaries of Coefficients" + + fields <- + list( + list(name="coefficient", title="Coefficient", type="string"), + list(name="mean", title="Mean", type="number", format="sf:4;dp:3"), + list(name="sd", title="SD", type="number", format="sf:4;dp:3"), + list(name="pIncl", title ="P(incl|data)", type="number", format="sf:4;dp:3") + ) + + posterior[["schema"]] <- list(fields=fields) + + if (status$ready && perform == "run") { + rows <- list() + + estimator <- switch( + options$summaryType, + best="HPM", + median="MPM", + "BMA" + ) + + coef <- BAS:::coef.bas(bas_obj, estimator=estimator) + coefficients <- coef$namesx + nModels <- coef$n.models + + for (i in 1:length(coefficients)) { + + coefficient <- .clean(coefficients[i]) + pIncl <- .clean(coef$probne0[i]) + if (options$summaryType == "complex") { + mean <- .clean(unname(coef$conditionalmeans[nModels, i])) # most complex model is in the final row + sd <- .clean(unname(coef$conditionalsd[nModels, i])) + } else { + mean <- .clean(coef$postmean[i]) + sd <- .clean(coef$postsd[i]) + } + + rows[[length(rows) + 1]] <- list(coefficient = coefficient, mean = mean, sd = sd, pIncl = pIncl) + + } + posterior[["data"]] <- rows + + } else { + names <- sapply(fields, function(x) x$name) + posterior[["data"]][[1]] <- setNames(as.list(rep(".", length(names))), names) + } + + return(posterior) } .descriptivesTable.basReg <- function(dataset, status, perform, options) { @@ -696,7 +756,7 @@ BASRegressionLinearLink <- function ( descriptives[["data"]][[1]] <- setNames(as.list(rep(".", length(names))), names) } - return (descriptives) + return(descriptives) } @@ -724,6 +784,7 @@ BASRegressionLinearLink <- function ( plotFunc <- function() { BAS:::image.bas(bas_obj, rotate = FALSE) } + # plotObj <- .plotImage.basReg(bas_obj) # to be implemented later content <- .writeImage(width = 530, height = 400, plot = plotFunc) plot[["convertible"]] <- TRUE @@ -782,11 +843,9 @@ BASRegressionLinearLink <- function ( p <- try(silent = FALSE, expr = { - plotFunc <- function() { - BAS:::plot.coef.bas(BAS:::coef.bas(bas_obj), subset = list(i), ask = FALSE, - bty = "n") - } - content <- .writeImage(width = 530, height = 400, plot = plotFunc) + # the function BAS:::coef.bas calls list2matrix.bas which appears pretty broken + plotObj <- .plotCoef.basReg(BAS:::coef.bas(bas_obj), subset = list(i)) + content <- .writeImage(width = 530, height = 400, plot = plotObj) plot[["convertible"]] <- TRUE plot[["obj"]] <- content[["obj"]] @@ -837,7 +896,7 @@ BASRegressionLinearLink <- function ( titles <- c( "Residuals vs Fitted", "Model Probabilities", - "Model Complexity", + "Log(P(data|M)) vs. model size", "Inclusion Probabilities" ) @@ -851,11 +910,8 @@ BASRegressionLinearLink <- function ( p <- try(silent = FALSE, expr = { - plotFunc <- function() { - BAS:::plot.bas(bas_obj, ask = FALSE, which = c(which), caption = "", - bty = "n") - } - content <- .writeImage(width = 530, height = 400, plot = plotFunc) + plotObj <- .plotBas.basReg(bas_obj, which = c(which)) + content <- .writeImage(width = 530, height = 400, plot = plotObj) plot[["convertible"]] <- TRUE plot[["obj"]] <- content[["obj"]] @@ -921,3 +977,300 @@ BASRegressionLinearLink <- function ( return(plot) } + +.plotCoef.basReg <- function (x, e = 1e-04, subset = 1:x$n.vars, ...) { + + # based on BAS:::plot.coef.bas. + + # start of copied code + df = x$df + i <- subset[[1]] + + sel = x$conditionalmeans[, i] != 0 + prob0 = 1 - x$probne0[i] + mixprobs = x$postprobs[sel]/(1 - prob0) + means = x$conditionalmeans[sel, i, drop = TRUE] + sds = x$conditionalsd[sel, i, drop = TRUE] + name = x$namesx[i] + df.sel = df[sel] + + df <- df.sel # modified from original + + nsteps = 500 + if (prob0 == 1 | length(means) == 0) { + xlower = -0 + xupper = 0 + xmax = 1 + } else { + qmin = min(qnorm(e/2, means, sds)) + qmax = max(qnorm(1 - e/2, means, sds)) + xlower = min(qmin, 0) + xupper = max(0, qmax) + } + + xx = seq(xlower, xupper, length.out = nsteps) + yy = rep(0, times = length(xx)) + maxyy = 1 + if (prob0 < 1 & length(sds) > 0) { + yy = mixprobs %*% apply(matrix(xx, ncol = 1), 1, + FUN = function(x, d, m, s) { + dt(x = (x - m)/s, df = d)/s + }, d = df, m = means, s = sds) + maxyy = max(yy) + } + ymax = max(prob0, 1 - prob0) + # end of copied code + + dfLines <- data.frame( + x = c(0, 0, xx), + y = c(0, prob0, (1 - prob0) * yy/maxyy), + g = factor(rep(1:2, c(2, length(xx)))) + ) + xBreaks <- pretty(range(xx), 3) + + g <- JASPgraphs::drawLines(dat = dfLines, + mapping = ggplot2::aes(x = x, y = y, group = g, color = g), + show.legend = FALSE) + + ggplot2::ylab("log(Marginal)") + + ggplot2::scale_x_continuous(name = name, breaks = xBreaks, limits = range(xBreaks)) + g <- g + ggplot2::scale_color_manual(values = c("gray", "black")) + g <- JASPgraphs::themeJasp(g) + + return(g) +} + +.plotBas.basReg <- function(x, which = c(which), id.n = 3, + labels.id = NULL, sub.caption = NULL, ...) { + # based on BAS::plot.bas + + # browser() + show <- rep(FALSE, 4) + show[which] <- TRUE + iid <- 1:id.n + if (show[1]) { + yhat = fitted(x, estimator = "BMA") + r = x$Y - yhat + n <- length(r) + if (id.n > 0) { + if (is.null(labels.id)) + labels.id <- paste(1:n) + show.r <- sort.list(abs(r), decreasing = TRUE)[iid] + } + } + # text.id <- function(x, y, ind, adj.x = TRUE) { + # labpos <- if (adj.x) + # label.pos[1 + as.numeric(x > mean(range(x)))] + # else 3 + # text(x, y, labels.id[ind], cex = cex.id, xpd = TRUE, + # pos = labpos, offset = 0.25) + # } + # if (any(show[2:3])) { + # show.m = sort.list(x$logmarg, decreasing = TRUE)[iid] + # label.m = paste(1:x$n.models) + # } + if (is.null(sub.caption)) { + cal <- x$call + if (!is.na(m.f <- match("formula", names(cal)))) { + cal <- cal[c(1, m.f)] + names(cal)[2] <- "" + } + cc <- deparse(cal, 80) + nc <- nchar(cc[1]) + abbr <- length(cc) > 1 || nc > 75 + if (abbr) { + sub.caption <- paste(substr(cc[1], 1, min(75, nc)), "...") + } else { + sub.caption <- cc[1] + } + } + # one.fig <- prod(par("mfcol")) == 1 + + if (show[1]) { + # browser() + dfPoints <- data.frame( + x = yhat, + y = r + ) + + xBreaks <- JASPgraphs::getPrettyAxisBreaks(dfPoints[["x"]], 3) + g <- JASPgraphs::drawAxis() + g <- g + ggplot2::geom_hline(yintercept = 0, linetype = 2, col = "gray") + g <- JASPgraphs::drawSmooth(g, dat = dfPoints, color = "red", alpha = .7) + g <- JASPgraphs::drawPoints(g, dat = dfPoints, size = 2, alpha = .85) + + ggplot2::ylab("Residuals") + + ggplot2::scale_x_continuous(name = "Predictions under BMA", breaks = xBreaks, limits = range(xBreaks)) + g <- JASPgraphs::themeJasp(g) + + return(g) + + } + if (show[2]) { + # browser() + cum.prob = cumsum(x$postprobs) + m.index = 1:x$n.models + + dfPoints <- data.frame( + x = m.index, + y = cum.prob + ) + + xBreaks <- round(seq(1, x$n.models, length.out = min(5, x$n.models))) + g <- JASPgraphs::drawSmooth(dat = dfPoints, color = "red", alpha = .7) + g <- JASPgraphs::drawPoints(g, dat = dfPoints, size = 4) + + ggplot2::ylab("Cumulative Probability") + + ggplot2::scale_x_continuous(name = "Model Search Order", breaks = xBreaks) + g <- JASPgraphs::themeJasp(g) + return(g) + } + if (show[3]) { + # browser() + logmarg = x$logmarg + dim = x$size + + dfPoints <- data.frame( + x = dim, + y = logmarg + ) + + # gonna assume here that dim (the number of parameters) is always an integer + xBreaks <- unique(round(pretty(dim))) + g <- JASPgraphs::drawPoints(dat = dfPoints, size = 4) + + ggplot2::ylab("log(Marginal)") + + ggplot2::xlab("Model Dimension") + + ggplot2::scale_x_continuous(breaks = xBreaks) + g <- JASPgraphs::themeJasp(g) + return(g) + + } + if (show[4]) { + # browser() + probne0 = x$probne0 + variables = x$namesx # 1:x$n.vars + priorProb <- x$priorprobs[1:x$n.vars] + + # reorder from high to low + o <- order(probne0, decreasing = FALSE) + probne0 <- probne0[o] + variables <- variables[o] + priorProb <- priorProb[o] + + width <- .8 # width of the bars + dfBar <- data.frame( + x = factor(variables, levels = variables), + y = probne0 + ) + dfLine <- data.frame( + x = rep(1:x$n.vars, each = 2) + c(-width/2, width/2), + y = rep(priorProb, each = 2), + g = rep(factor(variables), each = 2) + ) + + g <- JASPgraphs::drawBars(dat = dfBar, width = width) + g <- JASPgraphs::drawLines(g, dat = dfLine, + mapping = ggplot2::aes(x = x, y = y, group = g), linetype = 2) + + ggplot2::ylab("Marginal Inclusion Probability") + + ggplot2::xlab("") + # ggplot2::xlab(paste0("Model Dimension\n", sub.caption)) + g <- JASPgraphs::themeJasp(g, horizontal = TRUE) + return(g) + + } +} + +.plotImage.basReg <- function(x, top.models = 20, intensity = TRUE, prob = TRUE, + log = TRUE, rotate = TRUE, color = "rainbow", subset = NULL, + offset = 0.75, digits = 3, vlas = 2, plas = 0, rlas = 0, + ...) { + # code from BAS:::image.bas + postprob = x$postprobs + top.models = min(top.models, x$n.models) + best = order(-x$postprobs)[1:top.models] + postprob = postprob[best]/sum(postprob[best]) + which.mat <- BAS:::list2matrix.which(x, best) + nvar <- ncol(which.mat) + if (is.null(subset)) + subset = 1:nvar + which.mat = which.mat[, subset, drop = FALSE] + nvar = ncol(which.mat) + namesx = x$namesx[subset] + scale = postprob + prob.lab = "Posterior Probability" + if (log) { + scale = log(postprob) - min(log(postprob)) + prob.lab = "Log Posterior Odds" + } + if (intensity) + which.mat = sweep(which.mat, 1, scale + offset, "*") + if (rotate) + scale = rev(scale) + if (prob) + m.scale = cumsum(c(0, scale)) + else m.scale = seq(0, top.models) + mat = (m.scale[-1] + m.scale[-(top.models + 1)])/2 + colors = switch(color, + rainbow = c("black", rainbow(top.models +1, start = 0.75, end = 0.05)), + blackandwhite = gray(seq(0, 1, length = top.models))) + + # end of code from BAS:::image.bas + + w <- diff(mat) + w <- c(w[1], w) + + dfHeat <- data.frame( + x = rep(rev(mat), ncol(which.mat)), + y = rep(1:nvar, each = nrow(which.mat)), + z = c(which.mat[, nvar:1]), + zCat = 1* (abs(c(which.mat[, nvar:1])) > .Machine$double.eps), + w = rev(w) + ) + dfHeat$x <- dfHeat$x - dfHeat$w / 2 + # above line is required since width expands half of widht left and half of width right + # check code below to verify + # cbind(dfHeat$x - dfHeat$w / 2, dfHeat$x + dfHeat$w / 2) + nr <- nrow(dfHeat) + dfLines <- data.frame( + x = rep(c(mat - w, mat[length(mat)]), each = 2), + y = rep(c(.5, nvar+.5), length(mat)+1), + g = factor(rep(1:(length(mat)+1), each = 2)) + ) + + # browser() + discrete <- TRUE + if (discrete) { + show.legend <- FALSE + colors[colors != "black"] <- "green" + colors[colors == "black"] <- "white" + mapping = ggplot2::aes(x = x, y = y, fill = zCat, width = w) + } else { + show.legend <- TRUE + mapping = ggplot2::aes(x = x, y = y, fill = z, width = w) + } + + g <- JASPgraphs::drawHeatmap(dat = dfHeat, show.legend = show.legend, fillColor = colors, + mapping = mapping, + geom = "tile") + g + xBreaks <- mat - w/2 + g <- JASPgraphs::drawAxis(graph = g, xName = prob.lab, xBreaks = xBreaks, xLabels = round(scale, digits = digits), + yName = "", yBreaks = 1:nvar, yLabels = namesx, xLimits = NULL, yLimits = NULL, + secondaryXaxis = list(~.,name = "Model Rank", breaks = xBreaks, labels = top.models:1), + xTrans = scales::reverse_trans()) + g <- JASPgraphs::drawLines(g, dat = dfLines, mapping = ggplot2::aes(x = x, y = y, group = g), + color = "gray50", alpha = .7, size = 2) + g <- JASPgraphs::themeJasp(graph = g, legend.position = "right", axisTickLength = 0, + bty = "o") + + # this plot needs some additional treatment + unit <- JASPgraphs::graphOptions("axisTickLengthUnit") + fillLg <- ggplot2::guide_colorbar(title = "", default.unit = unit, + barheight = 5, barwidth = 1) + # browser() + g <- g + ggplot2::theme( + axis.text.x.bottom = ggplot2::element_text(margin = ggplot2::margin(0, 0, .5, 0, unit)), + axis.text.x.top = ggplot2::element_text(margin = ggplot2::margin(.5, 0, 0, 0, unit)) + ) + ggplot2::guides(fill = fillLg) + + return(g) + +} + diff --git a/JASP-Engine/JASP/R/ancova.R b/JASP-Engine/JASP/R/ancova.R index 754a5aff32..2334847eeb 100644 --- a/JASP-Engine/JASP/R/ancova.R +++ b/JASP-Engine/JASP/R/ancova.R @@ -21,7 +21,7 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) numeric.variables <- numeric.variables[numeric.variables != ""] factor.variables <- c(unlist(options$fixedFactors),unlist(options$randomFactors),unlist(options$repeatedMeasures)) factor.variables <- factor.variables[factor.variables != ""] - + if (is.null(dataset)) { if (perform == "run") { @@ -53,6 +53,7 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) stateContrasts <- NULL stateLevene <- NULL stateMarginalMeans <- NULL + stateSimpleEffects <- NULL stateDescriptivesTable <- NULL if ( ! is.null(state)) { # is there state? @@ -118,6 +119,15 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) stateMarginalMeans <- state$stateMarginalMeans } + + if (is.list(diff) && diff[['modelTerms']] == FALSE && diff[['dependent']] == FALSE && diff[['wlsWeights']] == FALSE && + diff[['simpleFactor']] == FALSE && diff[['moderatorFactorOne']] == FALSE && diff[['moderatorFactorTwo']] == FALSE) { + + # old simple effects tables can be used + + stateSimpleEffects <- state$stateSimpleEffects + + } } @@ -245,7 +255,6 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) ## Create Marginal Means Table if (is.null(stateMarginalMeans)) { - result <- .anovaMarginalMeans(dataset, options, perform, model, status, singular, stateMarginalMeans) results[["marginalMeans"]] <- list(collection=result$result, title = "Marginal Means") status <- result$status @@ -257,6 +266,20 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) } + ## Create Simple Effects Table + + if (is.null(stateSimpleEffects)) { + + result <- .anovaSimpleEffects(dataset, options, perform, results[["anova"]], status, singular, stateSimpleEffects) + results[["simpleEffects"]] <- result$result + status <- result$status + stateSimpleEffects <- result$stateSimpleEffects + + } else { + + results[["simpleEffects"]] <- stateSimpleEffects + + } ## Create Descriptives Table @@ -304,13 +327,13 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) # META definitions - .meta <- list( list(name="anova", type="table"), list(name="assumptionsObj", type="object", meta=list(list(name="levene", type="table"), list(name="qqPlot", type="image"))), list(name="contrasts", type="collection", meta="table"), list(name="posthoc", type="collection", meta="table"), - list(name="marginalMeans", type="collection", meta="table") + list(name="marginalMeans", type="collection", meta="table"), + list(name="simpleEffects", type="table") ) if (length(descriptivesPlot) == 1) { @@ -325,9 +348,7 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) results[[".meta"]] <- .meta - keepDescriptivesPlot <- lapply(stateDescriptivesPlot, function(x) x$data) - state[["model"]] <- anovaModel state[["options"]] <- options state[["statePostHoc"]] <- statePostHoc @@ -337,14 +358,14 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) state[["stateLevene"]] <- stateLevene state[["stateDescriptivesTable"]] <- stateDescriptivesTable state[["stateMarginalMeans"]] <- stateMarginalMeans - + state[["stateSimpleEffects"]] <- stateSimpleEffects if (perform == "init" && status$ready && status$error == FALSE) { - + return(list(results=results, status="inited", state=state, keep=c(stateqqPlot$data, keepDescriptivesPlot))) } else { - + return(list(results=results, status="complete", state=state, keep=c(stateqqPlot$data, keepDescriptivesPlot))) } } @@ -419,13 +440,12 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) for (i in 1:n.levels-1) { contr[c(1,i+1),i]<- c(1,-1) } + + contr <- contr * -1 } else if (contrast.type == "simple") { - treatment <- contr.treatment(levels) - - coding <- matrix(rep(1 / n.levels, prod(dim(treatment))), ncol=n.levels - 1) - contr <- (treatment-coding)*n.levels + contr <- contr.treatment(levels) - 1/n.levels } else if (contrast.type == "Helmert") { @@ -439,16 +459,17 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) } else if (contrast.type == "repeated") { - contr <- matrix(0,nrow = n.levels, ncol = n.levels - 1) - - for (i in 1:n.levels-1) { - contr[i,i] <- 1 - contr[i+1,i] <- -1 - } + contr <- MASS::contr.sdif(levels) * -1 } else if (contrast.type == "difference") { - contr <- contr.helmert(levels) + contr <- matrix(0,nrow = n.levels, ncol = n.levels - 1) + + for (i in 1:(n.levels - 1)) { + + k <- 1 / (i +1) + contr[1:(i+1),i] <- c( rep(-k, i), k * i) + } } else if (contrast.type == "polynomial") { @@ -897,7 +918,6 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) if (perform == "run" && status$ready && status$error == FALSE) contrast.summary <- summary.lm(model)[["coefficients"]] - for (contrast in options$contrasts) { if (contrast$contrast != "none") { @@ -1606,6 +1626,146 @@ Ancova <- function(dataset=NULL, options, perform="run", callback=function(...) list(result=marginalMeans, status=status, stateMarginalMeans=stateMarginalMeans) } +.anovaSimpleEffects <- function(dataset, options, perform, fullAnovaTable, status, singular, stateMarginalMeans) { + + if (identical(options$simpleFactor, "") | identical(options$moderatorFactorOne, "")) + return (list(result=NULL, status=status)) + + + terms <- c(options$moderatorFactorOne,options$moderatorFactorTwo) + terms.base64 <- c() + terms.normal <- c() + simpleFactor.base64 <- .v(options$simpleFactor) + + for (term in terms) { + + components <- unlist(term) + term.base64 <- paste(.v(components), collapse=":", sep="") + term.normal <- paste(components, collapse=" \u273B ", sep="") + + terms.base64 <- c(terms.base64, term.base64) + terms.normal <- c(terms.normal, term.normal) + } + simpleEffectsTable <- list() + simpleEffectsTable[["title"]] <- paste("Simple Main Effects - ", options$simpleFactor, sep = "") + + fields <- list( + list(name="ModOne", type="string", combine = TRUE, title = paste0("Level of ", terms.normal[1])), + list(name="ModTwo", type="string", combine = TRUE, title = paste0("Level of ", terms.normal[2])), + list(name="SumSquares", type="number", format="sf:4;dp:3", title = "Sum of Squares"), + list(name="df", type="integer", title = "df"), + list(name="MeanSquare", type="number", format="sf:4;dp:3", title = "Mean Square"), + list(name="F", type="number", format="sf:4;dp:3", title = "F"), + list(name="p", type="number", format="dp:3;p:.001", title = "p")) + + if (identical(options$moderatorFactorTwo, "")) + fields <- fields[-2] + + footnotes <- .newFootnotes() + + simpleEffectsTable[["schema"]] <- list(fields=fields) + + + tableCounter <- 1 + fullAnovaMS <- fullAnovaTable$data[[length(fullAnovaTable$data)]]$`Mean Square` + fullAnovaDf <- fullAnovaTable$data[[length(fullAnovaTable$data)]]$df + simpleEffectRows <- list() + rows <- list() + + termsBothModerators <- as.vector(c(options$moderatorFactorOne, options$moderatorFactorTwo)) + lvls <- list() + factors <- list() + + for (variable in termsBothModerators) { + + factor <- dataset[[ .v(variable) ]] + factors[[length(factors)+1]] <- factor + lvls[[variable]] <- levels(factor) + } + if (perform == "run" && status$ready && status$error == FALSE) { + + for (level in lvls[[1]]) { + # For each level of the first moderator factor, take a subset of the dataset, and adjust the options object + # Suboptions is the same as options, except that the first moderator factor has been removed as a predictor + # (because each subset only has one level of that factor). The same procedure is applied to the second moderator, if specified. + subDataset <- subset(dataset, dataset[terms.base64[1]] == level) + subOptions <- options + subOptions$fixedFactors <- options$fixedFactors[options$fixedFactors != options$moderatorFactorOne] + subOptions$modelTerms <- options$modelTerms[ !grepl(options$moderatorFactorOne, unlist(options$modelTerms, recursive = FALSE)) ] + model <- NULL + singular <- FALSE + if (identical(options$moderatorFactorTwo, "")) { + newGroup <- ifelse( level == lvls[[1]][1], TRUE, FALSE ) + if (nrow(subDataset) < 2 || nrow(unique(subDataset[simpleFactor.base64])) < nrow(unique(dataset[simpleFactor.base64]))) { + row <- list("ModOne"=level, "SumSquares"=".", "df"=".", "MeanSquare"=".", "F"=".", "p"=".", ".isNewGroup" = newGroup) + .addFootnote(footnotes, text = "Not enough observations in cell", symbol = "Note.") + } else { + anovaModel <- .anovaModel(subDataset, subOptions) + model <- anovaModel$model + singular <- anovaModel$singular + modelSummary <- summary(model)[[1]] + modOneIndex <- which(subOptions$fixedFactors == options$simpleFactor) + df <- modelSummary$Df[modOneIndex] + MS <- modelSummary$`Mean Sq`[modOneIndex] + SS <- modelSummary$`Sum Sq`[modOneIndex] + F <- MS / fullAnovaMS + p <- pf(F, df, fullAnovaDf, lower.tail = FALSE) + row <- list("ModOne"=level, "SumSquares"=SS, "df"=df, "MeanSquare"=MS, "F"=F, "p"=p, ".isNewGroup" = newGroup) + + } + simpleEffectRows[[length(simpleEffectRows) + 1]] <- row + } else { + for (levelTwo in lvls[[2]]) { + newGroup <- ifelse( levelTwo == lvls[[2]][1], TRUE, FALSE ) + subSubDataset <- subset(subDataset, subDataset[terms.base64[2]] == levelTwo) + subSubOptions <- subOptions + subSubOptions$fixedFactors <- subOptions$fixedFactors[subOptions$fixedFactors != subOptions$moderatorFactorTwo] + subSubOptions$modelTerms <- subOptions$modelTerms[ !grepl(subOptions$moderatorFactorTwo, unlist(subOptions$modelTerms, recursive = FALSE)) ] + if (nrow(subSubDataset) < 2 || nrow(unique(subSubDataset[simpleFactor.base64])) < nrow(unique(dataset[simpleFactor.base64]))) { + row <- list("ModOne"=level, "ModTwo" = levelTwo, "SumSquares"=".", "df"=".", "MeanSquare"=".", "F"=".", "p"=".", ".isNewGroup" = newGroup) + .addFootnote(footnotes, text = "Not enough observations in cell", symbol = "Note.") + } else { + anovaModel <- .anovaModel(subSubDataset, subSubOptions) + model <- anovaModel$model + singular <- anovaModel$singular + modTwoIndex <- which(subSubOptions$fixedFactors == options$simpleFactor) + modelSummary <- summary(model)[[1]] + df <- modelSummary$Df[modTwoIndex] + MS <- modelSummary$`Mean Sq`[modTwoIndex] + SS <- modelSummary$`Sum Sq`[modTwoIndex] + F <- MS / fullAnovaMS + p <- pf(F, df, fullAnovaDf, lower.tail = FALSE) + row <- list("ModOne"=level, "ModTwo" = levelTwo, "SumSquares"=SS, "df"=df, "MeanSquare"=MS, "F"=F, "p"=p, ".isNewGroup" = newGroup) + } + simpleEffectRows[[length(simpleEffectRows) + 1]] <- row + } + } + + + } + + simpleEffectsTable[["data"]] <- simpleEffectRows + + } else { + + simpleEffectsTable[["data"]] <- list(list("ModOne"=terms.normal, "SumSquares"=".", "df"=".", "MeanSquare"=".", "F"=".", "p"=".", ".isNewGroup" = TRUE)) + } + + simpleEffectsTable[["footnotes"]] <- as.list(footnotes) + simpleEffectsTable[["status"]] <- "complete" + + if (perform == "run" && status$ready && status$error == FALSE) { + + stateSimpleEffects <- simpleEffectsTable + + } else { + + stateSimpleEffects <- NULL + + } + + list(result=simpleEffectsTable, status=status, stateSimpleEffects=stateSimpleEffects) +} .anovaDescriptivesPlot <- function(dataset, options, perform, status, stateDescriptivesPlot) { diff --git a/JASP-Engine/JASP/R/anovarepeatedmeasures.R b/JASP-Engine/JASP/R/anovarepeatedmeasures.R index 147078a3fa..28c07485cc 100644 --- a/JASP-Engine/JASP/R/anovarepeatedmeasures.R +++ b/JASP-Engine/JASP/R/anovarepeatedmeasures.R @@ -56,7 +56,7 @@ AnovaRepeatedMeasures <- function(dataset=NULL, options, perform="run", callback diff <- .diff(options, state$options) # compare old and new options - if (is.list(diff) && diff[['withinModelTerms']] == FALSE && diff[['betweenModelTerms']] == FALSE && diff[['repeatedMeasuresCells']] == FALSE && + if (is.list(diff) && diff[['withinModelTerms']] == FALSE && diff[['betweenModelTerms']] == FALSE && diff[['repeatedMeasuresCells']] == FALSE && diff[['postHocTestPooledError']] && diff[['repeatedMeasuresFactors']] == FALSE && diff[['sumOfSquares']] == FALSE && diff[['covariates']] == FALSE && diff[['betweenSubjectFactors']] == FALSE) { # old model can be used @@ -162,10 +162,10 @@ AnovaRepeatedMeasures <- function(dataset=NULL, options, perform="run", callback ## Create Between Subjects Effects Table # if(length(unique(unlist(options$betweenSubjectFactors))) > 0 ){ - result <- .rmAnovaBetweenSubjectsTable(dataset, options, perform, model, status) - - results[["betweenSubjectsEffects"]] <- result$result - status <- result$status + result <- .rmAnovaBetweenSubjectsTable(dataset, options, perform, model, status) + + results[["betweenSubjectsEffects"]] <- result$result + status <- result$status # } @@ -635,38 +635,40 @@ AnovaRepeatedMeasures <- function(dataset=NULL, options, perform="run", callback orderOfTerms <- unlist(options$withinModelTerms[[length(options$withinModelTerms)]]$components) indexofOrderFactors <- match(allNames,orderOfTerms) - if(any(var == allNames)){ ## If the variable is a repeated measures factor - - levelsOfThisFactor <- unlist(lapply(options$repeatedMeasuresFactors[rmFactorIndex], function(x) x$levels)) # Levels within Factor - numberOfLevels <- length(unique(levelsOfThisFactor)) - splitNames <- unlist(lapply(strsplit(factorNamesV, split = "_"), function(x) x[indexofOrderFactors[rmFactorIndex]])) + if (any(var == allNames)) { ## If the variable is a repeated measures factor - listVarNamesToLevel <- list() # create a list of vectors of variable names, used to group the dataset for the post-hoc t-tests - for(i in 1:numberOfLevels){ - listVarNamesToLevel[[i]] <- factorNamesV[grep(splitNames, pattern = .v(levelsOfThisFactor[i]))] - } - - countr <- 1 - allEstimates <- allTees <- allSE <- allPees <- numeric() - for (k in 1:numberOfLevels) { ### Loop over all the levels within factor and do pairwise t.tests on them - for (i in .seqx(k+1, numberOfLevels)) { - tResult <- t.test(unlist(postHocData[listVarNamesToLevel[[k]]]),unlist(postHocData[listVarNamesToLevel[[i]]]), paired= T, var.equal = F) - allEstimates[countr] <- tResult$estimate - allTees[countr] <- tResult$statistic - allSE[countr] <- tResult$estimate / tResult$statistic - allPees[countr] <- tResult$p.value - countr <- countr + 1 + if (!options$postHocTestPooledError) { + + levelsOfThisFactor <- unlist(lapply(options$repeatedMeasuresFactors[rmFactorIndex], function(x) x$levels)) # Levels within Factor + numberOfLevels <- length(unique(levelsOfThisFactor)) + splitNames <- unlist(lapply(strsplit(factorNamesV, split = "_"), function(x) x[indexofOrderFactors[rmFactorIndex]])) + listVarNamesToLevel <- list() # create a list of vectors of variable names, used to group the dataset for the post-hoc t-tests + for(i in 1:numberOfLevels){ + listVarNamesToLevel[[i]] <- factorNamesV[grep(splitNames, pattern = .v(levelsOfThisFactor[i]))] } - } - bonferPvals <- p.adjust(allPees, method = "bonferroni") # correct all pvalues according to bonf - resultGeneral <- list(estimate = allEstimates, t.ratio = allTees, SE = allSE, p.value = bonferPvals ) - resultBonf['t.ratio'] <- allTees - resultBonf['p.value'] <- bonferPvals - resultBonf['SE'] <- allSE - resultBonf['estimate'] <- allEstimates - resultHolm['p.value'] <- p.adjust(allPees, method = "holm") # correct all pvalues according to holm - resultScheffe['p.value'] <- rep("-", length(allPees)) - resultTukey['p.value'] <- rep("-", length(allPees)) + + countr <- 1 + allEstimates <- allTees <- allSE <- allPees <- numeric() + for (k in 1:numberOfLevels) { ### Loop over all the levels within factor and do pairwise t.tests on them + for (i in .seqx(k+1, numberOfLevels)) { + tResult <- t.test(unlist(postHocData[listVarNamesToLevel[[k]]]),unlist(postHocData[listVarNamesToLevel[[i]]]), paired= T, var.equal = F) + allEstimates[countr] <- tResult$estimate + allTees[countr] <- tResult$statistic + allSE[countr] <- tResult$estimate / tResult$statistic + allPees[countr] <- tResult$p.value + countr <- countr + 1 + } + } + bonferPvals <- p.adjust(allPees, method = "bonferroni") # correct all pvalues according to bonf + resultGeneral <- list(estimate = allEstimates, t.ratio = allTees, SE = allSE, p.value = bonferPvals ) + resultBonf['t.ratio'] <- allTees + resultBonf['p.value'] <- bonferPvals + resultBonf['SE'] <- allSE + resultBonf['estimate'] <- allEstimates + resultHolm['p.value'] <- p.adjust(allPees, method = "holm") # correct all pvalues according to holm + } + resultScheffe['p.value'] <- rep("-", length(resultScheffe['p.value'])) + resultTukey['p.value'] <- rep("-", length(resultTukey['p.value'])) rmFactorIndex <- rmFactorIndex + 1 } @@ -990,7 +992,7 @@ AnovaRepeatedMeasures <- function(dataset=NULL, options, perform="run", callback } - indexResidual <- 2 + indexResidual <- 1 SS <- result[indexResidual,"Error SS"] df <- result[indexResidual,"den Df"] @@ -1941,7 +1943,7 @@ AnovaRepeatedMeasures <- function(dataset=NULL, options, perform="run", callback posthoc.variables <- unlist(options$postHocTestsVariables) posthoc.tables <- list() - + for (posthoc.var in posthoc.variables) { posthoc.table <- list() diff --git a/JASP-Engine/JASP/R/bffromt.R b/JASP-Engine/JASP/R/bffromt.R deleted file mode 100644 index d22929334a..0000000000 --- a/JASP-Engine/JASP/R/bffromt.R +++ /dev/null @@ -1,17 +0,0 @@ - -BFFromT <- function(dataset=NULL, options, perform = 'run', callback = function(...) 0, ...) { - - results <- list() - - results[[".meta"]] <- list(list(name="table", type="table")) - - table <- list() - table[["title"]] <- "BF from t" - - table[["schema"]] <- list(fields=list()) - table[["data"]] <- list() - - results[["table"]] <- table - - list(results=results, status="complete") -} diff --git a/JASP-Engine/JASP/R/binomialtest.R b/JASP-Engine/JASP/R/binomialtest.R index 276b4a01ac..cf4f97b30c 100644 --- a/JASP-Engine/JASP/R/binomialtest.R +++ b/JASP-Engine/JASP/R/binomialtest.R @@ -1,5 +1,5 @@ # -# Copyright (C) 2015 University of Amsterdam +# Copyright (C) 2017 University of Amsterdam # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -15,243 +15,48 @@ # along with this program. If not, see . # -BinomialTest <- function(dataset = NULL, options, perform = "run", - callback = function(...) 0, ...) { - - variables <- unlist(options$variables) - results <- list() - - if (is.null(dataset)) { - if (perform == "run") { - dataset <- .readDataSetToEnd(columns.as.numeric=NULL, - columns.as.factor=variables, - exclude.na.listwise=NULL) - } else { - dataset <- .readDataSetHeader(columns.as.numeric=NULL, - columns.as.factor=variables) - } - } else { - dataset <- .vdf(dataset, columns.as.numeric=NULL, - columns.as.factor=variables) - } - - - # Retrieve state - state <- .retrieveState() - descriptPlots <- NULL - binomResults <- NULL - - if (!is.null(state)){ - - diff <- .diff(state$options, options) - - if (is.list(diff) && !any(diff[["variables"]], - diff[["confidenceIntervalInterval"]], - diff[["hypothesis"]], - diff[["testValue"]])){ - - binomResults <- state$binomResults - } - - if (is.list(diff) && options[["descriptivesPlots"]] && - !any(diff[["variables"]], diff[["testValue"]], - diff[["descriptivesPlots"]], - diff[["descriptivesPlotsConfidenceInterval"]], - diff[["plotWidth"]], - diff[["plotHeight"]])){ - descriptPlots <- state$descriptPlots - } - - } - - - # Meta information - descriptivesPlotsMeta <- list() - - for (j in .indices(variables)){ - descriptivesPlotsMeta[[j]] <- list(name = variables[j], type = "collection", - meta = "image") - } - - results[["title"]] <- "Binomial Test" - results[[".meta"]] <- list(list(name = "binomial", type = "table"), - list(name = "descriptives", type = "object", - meta = descriptivesPlotsMeta)) - - - # Generate results - if (is.null(binomResults)){ - - binomResults <- .binomialTest(dataset, options, variables, perform) - - } +BinomialTest <- function(dataset, options, perform, state, ...) { + variables <- unlist(options$variables) - results[["binomial"]] <- .binomialTable(binomResults, options, variables, - perform) + binomResults <- state$binomResults + if (is.null(binomResults)) + binomResults <- .binomialTest(dataset, options, perform, variables) + descriptPlots <- state$descriptPlots + if (options[["descriptivesPlots"]] && is.null(descriptPlots)) + descriptPlots <- .binomialDescriptivesPlot(dataset, options, perform, variables) - if (options[["descriptivesPlots"]]){ - - if (is.null(descriptPlots)) { - descriptPlots <- .binomialDescriptivesPlot(dataset, options, variables, - perform) - } - - # select list of plot paths to keep when rerunning analysis. - plotPaths <- list() - for (i in 1:length(descriptPlots)){ - if (is.list(descriptPlots[[i]])){ - for (j in 1:length(descriptPlots[[i]]$collection)){ - plotPaths[[length(plotPaths)+1]] <- - descriptPlots[[i]]$collection[[j]]$data - } - } - } + results <- list() + results[["binomial"]] <- .BinomialTable(binomResults, options) - results[["descriptives"]] <- descriptPlots + if (! is.null(descriptPlots)) { + results[["descriptives"]] <- descriptPlots results[["descriptives"]][["title"]] <- "Descriptive Plots" - - } else { - - results[["descriptives"]] <- NULL - plotPaths <- list() - } + if (perform == "init") + return(list(results=results, status="inited", state=state)) + state <- list( + options = options, + binomResults = binomResults, + descriptPlots = descriptPlots + ) - if (perform == "run") { - - state <- list() - state[["options"]] <- options - state[["binomResults"]] <- binomResults - state[["binomTable"]] <- results[["binomial"]] - state[["descriptPlots"]] <- results[["descriptives"]] - - return(list(results=results, status="complete", state=state, - keep = plotPaths)) - - } else { - - return(list(results=results, status="inited", state=state, - keep = plotPaths)) - - } - + return(list(results=results, status="complete", state=state)) } -.binomialTable <- function(r, options, variables, perform){ - - table <- list() - footnotes <- .newFootnotes() - table[["title"]] <- "Binomial Test" - - fields <- list( - list(name="case", title="", type="string", combine=TRUE), - list(name="level", title="Level", type="string"), - list(name="counts", title="Counts", type="integer"), - list(name="total", title="Total", type="integer"), - list(name="proportion", title="Proportion", type="number", - format="sf:4;dp:3"), - list(name="p", title="p", type="number", format="dp:3;p:.001") - ) - - if (options$VovkSellkeMPR) { - .addFootnote(footnotes, symbol = "\u002A", text = "Vovk-Sellke Maximum - p-Ratio: Based the p-value, the maximum - possible odds in favor of H\u2081 over H\u2080 equals - 1/(-e p log(p)) for p \u2264 .37 - (Sellke, Bayarri, & Berger, 2001).") - fields[[length(fields) + 1]] <- list(name = "VovkSellkeMPR", - title = "VS-MPR\u002A", - type = "number", - format = "sf:4;dp:3") - } - - if (options$confidenceInterval) { - - interval <- 100 * options$confidenceIntervalInterval - title <- paste0(interval, "% Confidence Interval") - - fields[[length(fields)+1]] <- list(name = "lowerCI", - type = "number", - format = "sf:4;dp:3", title = "Lower", - overTitle = title) - fields[[length(fields)+1]] <- list(name = "upperCI", - type = "number", - format = "sf:4;dp:3", title = "Upper", - overTitle = title) - } - - table[["schema"]] <- list(fields = fields) - - if (options$hypothesis == "notEqualToTestValue") { - - message <- paste0("Proportions tested against value: ", options$testValue, - ".") - - } else if (options$hypothesis == "greaterThanTestValue") { - - note <- "For all tests, the alternative hypothesis specifies that the - proportion is greater than " - message <- paste0(note, options$testValue, ".") +.binomialTest <- function(dataset, options, perform, variables) { - } else { - - note <- "For all tests, the alternative hypothesis specifies that the - proportion is less than " - message <- paste0(note, options$testValue, ".") - - } + binomResults <- jasp.data.frame(colnames=c("case", "level", "counts", "total", "proportion", "p", "VovkSellkeMPR", "lowerCI", "upperCI")) - .addFootnote(footnotes, symbol="Note.", text=message) - table[["footnotes"]] <- as.list(footnotes) + if (perform == "init" || is.null(variables)) { - if (!is.null(r)){ - - table[["data"]] <- r - if (options$VovkSellkeMPR){ - for (row in 1:length(table[["data"]])){ - table[["data"]][[row]][["VovkSellkeMPR"]] <- .VovkSellkeMPR(table[["data"]][[row]][["p"]]) - } - } - table[["status"]] <- "complete" + binomResults <- rbind(binomResults, rep(".", ncol(binomResults))) } else { - data <- list() - - if (is.null(variables)){ - variables <- "" - } - - for (var in variables){ - if (options$VovkSellkeMPR){ - data[[length(data) + 1]] <- list(case=var, level=".", counts=".", - total=".", proportion=".", p=".", - VovkSellkeMPR=".", lowerCI=".", - upperCI=".") - } else { - data[[length(data) + 1]] <- list(case=var, level=".", counts=".", - total=".", proportion=".", p=".", - lowerCI=".", upperCI=".") - } - } - - table[["data"]] <- data - - } - - return(table) -} - -.binomialTest <- function(dataset, options, variables, perform){ - - binomResults <- NULL - - if (perform == "run" && !is.null(variables)) { - if (options$hypothesis == "notEqualToTestValue") { hyp <- "two.sided" } else if (options$hypothesis == "greaterThanTestValue") { @@ -260,27 +65,22 @@ BinomialTest <- function(dataset = NULL, options, perform = "run", hyp <- "less" } - data <- list() - for (var in variables) { - d <- dataset[[.v(var)]] d <- d[!is.na(d)] - levels <- levels(d) n <- length(d) # !! Test each level in each variable against test value !! for (lev in levels) { - counts <- sum(d == lev) prop <- counts/n - r <- stats::binom.test(counts, n, p = options$testValue, alternative = hyp, conf.level = options$confidenceIntervalInterval) p <- r$p.value + vovk <- .VovkSellkeMPR(p) cilo <- r$conf.int[1] ciup <- r$conf.int[2] @@ -290,34 +90,52 @@ BinomialTest <- function(dataset = NULL, options, perform = "run", p <- 1 } - row <- list(case = var, level = lev, counts = .clean(counts), - total = .clean(n), proportion = .clean(prop), p = .clean(p), - lowerCI = .clean(cilo), upperCI = .clean(ciup)) - - if (lev == levels[1]) { - row[[".isNewGroup"]] <- TRUE - } else { - row[[".isNewGroup"]] <- FALSE - } - - data[[length(data)+1]] <- row - + binomResults <- rbind(binomResults, c(var, lev, counts, n, prop, p, vovk, cilo, ciup)) } - } - binomResults <- data - } return(binomResults) +} + +.BinomialTable <- function(binomResults, options) { + footnotes <- .newFootnotes() + .addFootnote(footnotes, symbol="Note.", + text = switch(options$hypothesis, + "notEqualToTestValue" = .messages("footnote", "binomNeq", value=options$testValue), + "greaterThanTestValue" = .messages("footnote", "binomGreater", value=options$testValue), + "lessThanTestValue" = .messages("footnote", "binomLess", value=options$testValue))) + + if (options$VovkSellkeMPR) + .addFootnote(footnotes, symbol = "\u002A", text = .messages("footnote", "VovkSellkeMPR")) + + attr(binomResults, "jasp.footnotes") <- footnotes + + if (options$confidenceInterval) { + schema <- list( + list(name="lowerCI", overTitle=paste0(options$confidenceIntervalInterval * 100, "% Confidence Interval")), + list(name="upperCI", overTitle=paste0(options$confidenceIntervalInterval * 100, "% Confidence Interval")) + ) + attr(binomResults, "jasp.schema") <- schema + } + + if (! options$VovkSellkeMPR) + binomResults <- subset(binomResults, select=-VovkSellkeMPR) + + if (! options$confidenceInterval) + binomResults <- subset(binomResults, select=-c(lowerCI, upperCI)) + + return(binomResults) } -.binomialDescriptivesPlot <- function(dataset, options, variables, perform) { +.binomialDescriptivesPlot <- function(dataset, options, perform, variables) { - descriptivesPlotCollection <- list() + if (is.null(variables)) + return(NULL) + descriptivesPlotCollection <- list() testValue <- options$testValue confLevel <- options$descriptivesPlotsConfidenceInterval @@ -335,35 +153,28 @@ BinomialTest <- function(dataset = NULL, options, perform = "run", var <- options$variables[[i]] - - d <- dataset[[.v(var)]] d <- d[!is.na(d)] nObs <- length(d) descriptivesPlotList <- list() - - for (k in .indices(levels(d))){ + for (k in .indices(levels(d))) { level <- levels(d)[k] - descriptivesPlot <- list("title" = level) + if (perform == "init") { - if (perform == "run") { + descriptivesPlot <- plot.new + + } else { count <- sum(d == level) rate <- count/nObs - - descriptivesPlot[["width"]] <- options$plotWidth - descriptivesPlot[["height"]] <- options$plotHeight - descriptivesPlot[["custom"]] <- list(width = "plotWidth", - height = "plotHeight") - r <- stats::binom.test(x = count, n = nObs, p = testValue, - alternative = "two.sided", - conf.level = confLevel) + alternative = "two.sided", + conf.level = confLevel) ciLower <- r$conf.int[1] ciUpper <- r$conf.int[2] @@ -372,7 +183,7 @@ BinomialTest <- function(dataset = NULL, options, perform = "run", dfTestValue <- data.frame(testValue = testValue) - p <- ggplot2::ggplot(summaryStat, ggplot2::aes(x = label, + descriptivesPlot <- ggplot2::ggplot(summaryStat, ggplot2::aes(x = label, y = rate, group = 1)) + ggplot2::geom_errorbar(ggplot2::aes(ymin = ciLower, ymax = ciUpper), colour = "black", width = 0.2, position = pd) + @@ -412,34 +223,16 @@ BinomialTest <- function(dataset = NULL, options, perform = "run", plot.margin = grid::unit(c(0.5, 0, 0.5, 0.5), "cm")) + base_breaks_y(summaryStat, dfTestValue$testValue) - - content <- .writeImage(width = options$plotWidth, - height = options$plotHeight, - plot = p, obj = TRUE) - - descriptivesPlot[["convertible"]] <- TRUE - descriptivesPlot[["obj"]] <- content[["obj"]] - descriptivesPlot[["data"]] <- content[["png"]] - descriptivesPlot[["status"]] <- "complete" - - } else { - - descriptivesPlot[["width"]] <- options$plotWidth - descriptivesPlot[["height"]] <- options$plotHeight - descriptivesPlot[["custom"]] <- list(width = "plotWidth", - height = "plotHeight") - descriptivesPlot[["data"]] <- "" - } + attr(descriptivesPlot, "jasp.title") <- level + attr(descriptivesPlot, "jasp.name") <- "descriptivesPlot" descriptivesPlotList[[k]] <- descriptivesPlot } descriptivesPlotVar <- list(collection = descriptivesPlotList, title = var) - descriptivesPlotCollection[[var]] <- descriptivesPlotVar } - return(descriptivesPlotCollection) } diff --git a/JASP-Engine/JASP/R/binomialtestbayesian.R b/JASP-Engine/JASP/R/binomialtestbayesian.R index 6711797685..3085bb8e99 100644 --- a/JASP-Engine/JASP/R/binomialtestbayesian.R +++ b/JASP-Engine/JASP/R/binomialtestbayesian.R @@ -422,9 +422,14 @@ BinomialTestBayesian <- function(dataset = NULL, options, perform = "run", plot[["width"]] <- 530 plot[["height"]] <- 400 - image <- .beginSaveImage(530, 400) - .plotSequentialBF.binomTest(dontPlotData = TRUE, hypothesis = hyp, BFH1H0 = BFH1H0) - plot[["data"]] <- .endSaveImage(image) + .plotFunc <- function() { + .plotSequentialBF.binomTest(dontPlotData = TRUE, hypothesis = hyp, BFH1H0 = BFH1H0) + } + content <- .writeImage(width = 530, height = 400, plot = .plotFunc, obj = TRUE) + + plot[["convertible"]] <- TRUE + plot[["obj"]] <- content[["obj"]] + plot[["data"]] <- content[["png"]] } diff --git a/JASP-Engine/JASP/R/classicalmetaanalysis.R b/JASP-Engine/JASP/R/classicalmetaanalysis.R index 46280a54f6..5d89f7e2d5 100644 --- a/JASP-Engine/JASP/R/classicalmetaanalysis.R +++ b/JASP-Engine/JASP/R/classicalmetaanalysis.R @@ -372,7 +372,7 @@ ClassicalMetaAnalysis <- function(dataset=NULL, options, perform="run", callback table <- list(title = title) if (! is.null(egger)) { - table$x <- coef(summary(egger$fit))[egger$predictor, c(paste0(cols[1], "val"), "pval")] + table$x <- metafor::coef.summary.rma(summary(egger$fit))[egger$predictor, c(paste0(cols[1], "val"), "pval")] colnames(table$x) <- cols } else { table$x <- cols diff --git a/JASP-Engine/JASP/R/common.R b/JASP-Engine/JASP/R/common.R index 5b34e0b204..4fb611fb46 100644 --- a/JASP-Engine/JASP/R/common.R +++ b/JASP-Engine/JASP/R/common.R @@ -15,9 +15,13 @@ # along with this program. If not, see . # -run <- function(name, options.as.json.string, perform="run") { +run <- function(name, title, dataKey, options, resultsMeta, stateKey, requiresInit=TRUE, perform="run") { + + dataKey <- rjson::fromJSON(dataKey) + options <- rjson::fromJSON(options) + resultsMeta <- rjson::fromJSON(resultsMeta) + stateKey <- rjson::fromJSON(stateKey) - options <- rjson::fromJSON(options.as.json.string) analysis <- eval(parse(text=name)) env <- new.env() @@ -44,26 +48,54 @@ run <- function(name, options.as.json.string, perform="run") { } } - state <- NULL + dataset <- NULL + if (! is.null(dataKey)) { + cols <- .getDataSetCols(dataKey, options) + if (perform == "run") + dataset <- do.call(.readDataSetToEnd, cols) + else + dataset <- do.call(.readDataSetHeader, cols) + } + + oldState <- NULL if ('state' %in% names(formals(analysis))) { - state <- .retrieveState() - if (! is.null(state) && 'key' %in% names(attributes(state))) { - state <- .getStateItems(state=state, options=options, key=attributes(state)$key) - } + oldState <- .getStateFromKey(stateKey, options) } + if (perform == "init" && ! requiresInit) { + + emptyResults <- try(.createEmptyResults(resultsMeta), silent=TRUE) + if (inherits(emptyResults, "try-error")) { + msg <- .sanitizeForJson(emptyResults) + return(paste("{ \"status\" : \"error\", \"results\" : { \"error\" : 1, \"errorMessage\" : \"", msg, "\" } }", sep="")) + } + + results <- list() + results[["results"]] <- emptyResults + results[["results"]][["title"]] <- title + results[["status"]] <- "inited" + + json <- try({ rjson::toJSON(results) }) + + if (inherits(results, "try-error")) + return(paste("{ \"status\" : \"error\", \"results\" : { \"error\" : 1, \"errorMessage\" : \"", "Unable to jsonify", "\" } }", sep="")) + + return(json) + + } + results <- tryCatch(expr={ withCallingHandlers(expr={ - analysis(dataset=NULL, options=options, perform=perform, callback=the.callback, state=state) + analysis(dataset=dataset, options=options, perform=perform, callback=the.callback, state=oldState) }, error=.addStackTrace) }, error=function(e) e) - + if (inherits(results, "expectedError")) { errorResponse <- paste("{ \"status\" : \"error\", \"results\" : { \"title\" : \"error\", \"error\" : 1, \"errorMessage\" : \"", results$message, "\" } }", sep="") @@ -72,11 +104,9 @@ run <- function(name, options.as.json.string, perform="run") { } else if (inherits(results, "error")) { - error <- gsub("\"", "'", as.character(results), fixed=TRUE) + error <- .sanitizeForJson(results) - stackTrace <- as.character(results$stackTrace) - stackTrace <- gsub("\"", "'", stackTrace, fixed=TRUE) - stackTrace <- gsub("\\\\", "", stackTrace) + stackTrace <- .sanitizeForJson(results$stackTrace) stackTrace <- paste(stackTrace, collapse="

") errorMessage <- .generateErrorMessage(type='exception', error=error, stackTrace=stackTrace) @@ -90,25 +120,31 @@ run <- function(name, options.as.json.string, perform="run") { } else { - keep <- NULL + keep <- newState <- NULL if ("state" %in% names(results)) { - state <- results$state + newState <- results$state results$state <- NULL - - if (! is.null(names(state))) { - state[["figures"]] <- c(state[["figures"]], .imgToState(results$results)) - } - keep <- .saveState(state)$relativePath } if ("results" %in% names(results)) { + results <- try(.parseResults(results, title, resultsMeta, oldState), silent=TRUE) + if (inherits(results, "try-error")) { + msg <- .sanitizeForJson(results) + return(paste("{ \"status\" : \"error\", \"results\" : { \"error\" : 1, \"errorMessage\" : \"", msg, "\" } }", sep="")) + } + + if (! is.null(names(newState))) + newState[["figures"]] <- .imgToState(results$results) + results <- .imgToResults(results) results$results <- .addCitationToResults(results$results) - results$keep <- c(results$keep, keep) # keep the state file + + keep <- .saveState(newState)$relativePath + results$keep <- c(results$keep, keep) # keep the state file } else { @@ -130,10 +166,984 @@ run <- function(name, options.as.json.string, perform="run") { } checkPackages <- function() { - rjson::toJSON(.checkPackages()) } +.sanitizeForJson <- function(obj) { + # Removes elements that are not translatable to json + # + # Args: + # - obj: character string or obj coercible to string (e.g. a try-error) + # + # Return: + # - character string ready to be put into rjson::toJSON + # + str <- as.character(obj) + str <- gsub("\"", "'", str, fixed=TRUE) + str <- gsub("\\n", "
", str) + str <- gsub("\\\\", "", str) + return(str) +} + +.createEmptyResults <- function(resultsMeta) { + # Dispatches functions which build a fully completed results & .meta list that mimics the output + # of the init phase of an analysis (empty tables, empty plots) + # + # Args: + # - resultsMeta: full (named) list taken from the analysis json file, + # contains all output descriptions of tables/plots/containers + # + # Return: + # - results list with row lists for tables and png's for plots and a .meta entry + # + if (length(resultsMeta) == 0) + stop("No items to show, please add a results description or set init to true") + + showItems <- logical(length(resultsMeta)) + for (i in 1:length(resultsMeta)) { + item <- resultsMeta[[i]] + if (! is.null(item[["show"]]) && item[["show"]] && item[["type"]] != "container") + showItems[i] <- TRUE + } + if (sum(showItems) == 0) + stop("None of the result items has show set to 'true', cannot skip init phase") + + results <- .resultsFromResultsMeta(resultsMeta[showItems]) + results[[".meta"]] <- .getAnalysisMeta(results, resultsMeta) + + return(results) +} + +.resultsFromResultsMeta <- function(resultsMeta) { + # Builds a fully completed results list which mimics the output of the init phase + # of an analysis (empty tables, empty plots) + # + # Args: + # - resultsMeta: condensed (named) list of results elements that had + # "show": true in the analysis json file + # + # Return: + # - results list with row lists for tables and png's for plots + # + results <- list() + for (i in 1:length(resultsMeta)) { + item <- resultsMeta[[i]] + name <- names(resultsMeta)[i] + type <- item[["type"]] + if (type == "table") { + table <- .makeEmptyTable(item[["columns"]]) + if (is.null(table)) # show=TRUE in the table but in none of the columns + next + results[[name]] <- .convertTable(table, resultsMeta, name) + } else if (type == "image") { + results[[name]] <- .convertPlot(plot.new, resultsMeta, oldState=NULL, name, createObj=FALSE) + } else { + stop(paste("Cannot create empty placeholder for element of type", type)) + } + } + return(results) +} + +.makeEmptyTable <- function(colsMeta) { + # Creates a list table without data based on which columns have the flag "show": true; + # used in analyses that skip the init phase + # + # Args: + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file + # + # Return: + # - a list with all columns to be shown with a single dot-filled row + # + cols <- NULL + for (i in 1:length(colsMeta)) { + col <- colsMeta[[i]] + if (! is.null(col[["show"]]) && col[["show"]]) + cols <- c(cols, col[["name"]]) + } + if (length(cols) == 0) + return(NULL) + + table <- matrix(".", nrow=1, ncol=length(cols)) + colnames(table) <- cols + return(table) +} + +.parseResults <- function(results, title, resultsMeta, oldState) { + # Dispatches functions that (1) convert data.frames/matrices + # to row lists, (2) convert ggplot2/recordedPlot objects to png's, (3) add .meta, + # and (4) add a keep object containing all png's + # + # Args: + # - results: list with (non-parsed) output elements from an analysis + # - title: the title of the analysis, taken from the analysis json file + # - resultsMeta: full (named) list taken from the analysis json file, + # contains all output descriptions of tables/plots/containers + # - oldState: state file that was retrieved before the current analysis ran + # + # Return: + # - results list with row lists for tables and png's for plots, a .meta entry and keep; + # can be returned from run as is + # + if (is.null(resultsMeta)) # old analysis type + return(results) + + if (length(resultsMeta) == 0) + stop("Cannot locate any items in the results description") + + if (! is.null(title)) + results[["results"]][["title"]] <- title + + if (! ".meta" %in% names(results$results)) + results[["results"]][[".meta"]] <- .getAnalysisMeta(results$results, resultsMeta) + + resultsMeta <- .simplifyResultsMeta(resultsMeta) # this basically flattens the nested table/images in containers + + results$results <- .convertResults(results$results, resultsMeta, oldState) # make the results Qt ready + + if (is.null(results$keep)) + results$keep <- .getKeepImages(results$results) + + return(results) +} + +.getAnalysisMeta <- function(results, resultsMeta) { + # Builds the .meta element of the analysis and dispatches a function to discover + # nested structures. .meta describes all elements in results such as their name, title and type + # + # Args: + # - results: list with (parsed or non-parsed) output elements from an analysis + # - resultsMeta: full (named) list taken from the analysis json file, + # contains all output descriptions of tables/plots/containers + # + # Return: + # - the description of the results ready to be returned by run as is + # + meta <- list() + for (itemName in names(resultsMeta)) { + if (! itemName %in% names(results)) + next + item <- resultsMeta[[itemName]] + type <- item[["type"]] + if (type == "image" || type == "table") { + meta[[length(meta)+1]] <- list(type=type, name=itemName) + } else if (type == "container") { + meta[[length(meta)+1]] <- .analysisMetaFromResults(result=results[itemName], objectName=itemName) + } else { + stop(paste0("Unknown type (", type, ") provided in results description")) + } + } + return(meta) +} + +.analysisMetaFromResults <- function(result, inCollection=FALSE, parent="", objectName="", depth=0) { + # Recursive function that loops through the results and describes the contents for the .meta description; + # it is specifically designed to parse results that are of type 'container'. + # Note: collections can contain objects and objects can contain collections + # + # Args: + # - result: list with (parsed or non-parsed) output elements from an analysis [recursive] + # - inCollection: boolean specifying whether the current branch in the results is of type collection. + # collections are a repetition of structures, this means that we can describe + # the content of the collection by only seeing one of its structures + # - parent: character name of the direct parent of the current result, can be + # 'object' or 'collection' + # - objectName: name of the container in the analysis json, only there for debug purposes + # - depth: current depth of the recursion, only there for debug purposes + # + # Return: + # - list with the .meta description of a single results element + # + meta <- list() + parsedNames <- NULL + for (i in 1:length(result)) { + name <- "" + if (! is.null(names(result))) + name <- names(result)[i] + + type <- .getResultType(result[i]) + if (is.null(type)) # probably a title + next + else if (type == "collection") { + inCollection <- TRUE + collectionType <- .getTerminalType(result[[i]][["collection"]][[1]]) # expecting list(collection=list(...)), let's skip that + if (! is.null(collectionType) && (collectionType == "image" || collectionType == "table")) { # we found the end; the collection is not nested + meta[[length(meta)+1]] <- list(name=name, type=type, meta=collectionType) + next + } + } + else if (type == "image" || type == "table") { + if (name %in% parsedNames) + next + meta[[length(meta)+1]] <- list(name=name, type=type) + parsedNames <- c(parsedNames, name) + next + } + + nextLevel <- result[[i]] + if (type == "collection") + nextLevel <- result[[i]][["collection"]] + + if (parent == "object") # we want list(list()) instead of just list() as each branch may be a different type + meta[[length(meta)+1]] <- list(name=name, type=type, meta=.analysisMetaFromResults(nextLevel, inCollection, parent=type, objectName=objectName, depth=depth+1)) + else + meta <- list(name=name, type=type, meta=.analysisMetaFromResults(nextLevel, inCollection, parent=type, objectName=objectName, depth=depth+1)) + + if (inCollection) # we only needed to follow a single branch and have done so + break + } + + if (length(meta) == 0) { # this is an error, we could not figure out the type + classes <- paste(class(result), collapse=", ") + childClasses <- paste(class(unlist(result, recursive=FALSE)), collapse=", ") + resultNames <- paste(names(result), collapse=", ") + childNames <- paste(names(unlist(result, recursive=FALSE)), collapse=", ") + if (resultNames == "") resultNames <- "" + if (childNames == "") childNames <- "" + stop(paste0("Could not create meta for ", objectName, " at depth ", depth, " (class: ", classes, ", names: ", resultNames, ", class children: ", childClasses, ", names children: ", childNames, ")")) + } + + return(meta) +} + +.getResultType <- function(result) { + # Describes the type of the result to the recursive .analysisMetaFromResults() + # (in which it's called repeatedly); these types are later stored in .meta + # + # Args: + # - result: list with (parsed or non-parsed) output elements from an analysis [arbitrary depth] + # + # Return: + # - NULL if unknown/invalid type, otherwise a string with 'collection', 'object', + # 'image' or 'table' + # + types <- NULL + acceptedClasses <- c("recordedplot", "ggplot", "function", "list", "matrix", "data.frame") + for (item in result) { # look through the contents of the current level in results + if (! any(acceptedClasses %in% class(item))) # unknown type (a title?) + next + type <- NULL + if ("collection" %in% names(item)) + type <- "collection" + else + type <- .getTerminalType(item) + + if (! is.null(type)) + types <- c(types, type) + else + types <- c(types, "object") + } + + type <- unique(types) + if (length(type) != 1) # multiple different types, not sure which to pick + return(NULL) + + return(type) +} + +.getTerminalType <- function(result) { + # Determines if the result is of type 'table' or 'image' (at which point .analysisMetaFromResults() + # knows that it has reached the terminal node) + # + # Args: + # - result: list with (parsed or non-parsed) output elements from an analysis [arbitrary depth] + # + # Return: + # - NULL if not a plot/table, otherwise a string with 'image' or 'table' + # + + # old analysis + if (is.list(result) && "data" %in% names(result)) { + if (is.list(result[["data"]]) && "schema" %in% names(result)) + return("table") + if (is.character(result[["data"]]) && grepl("\\.png$", result[["data"]])) + return("image") + } + # new analysis + if (is.data.frame(result) || is.matrix(result)) + return("table") + if (any(c("recordedplot", "ggplot", "function") %in% class(result))) + return("image") + + return(NULL) +} + +.simplifyResultsMeta <- function(resultsMeta) { + # Changes the resultsMeta so that each table or plot is placed on the top level, + # specifically meant for container types + # + # Args: + # - resultsMeta: full (named) list taken from the analysis json file, + # contains all output descriptions of tables/plots/containers + # + # Return: + # - named list identical to input except for the fact that containers are removed + # and their contents are placed on the top level + # + items <- list() + for (itemName in names(resultsMeta)) { + item <- resultsMeta[[itemName]] + type <- item[["type"]] + if (type == "container") { + container <- item[["items"]] + if (is.list(container) && is.null(names(container))) # it is an array of items + container <- unlist(container, recursive=FALSE) + if (is.null(names(container))) + stop(paste("Could not figure out the container structure in", itemName)) + for (containerItemName in names(container)) + items[[containerItemName]] <- container[[containerItemName]] + } else { + items[[itemName]] <- item + } + } + return(items) +} + +.getKeepImages <- function(results) { + # Finds all the png's that were created with writeImage() + # + # Args: + # - results: list with (parsed) output elements from an analysis + # + # Return: + # - vector of names of each png detected in the results + # + keep <- NULL + items <- unlist(results, use.name=FALSE) + if (is.list(items)) { # guess it had a formula or something + keep <- lapply(items, function(x) { + if (is.character(x) && grepl("\\.png$", x)) + return(x) + }) + keep <- unlist(keep) + } else { # unlist worked fine + items <- items[is.character(items)] + indices <- which(grepl("\\.png$", items)) + if (length(indices) > 0) + keep <- items[indices] + } + return(keep) +} + +.convertResults <- function(results, resultsMeta, oldState, name=NULL) { + # Recursive function that iterates over results and calls functions to convert + # data.frames/matrices to row lists and ggplot2/recordedPlot objects to png's + # + # Args: + # - results: list with (non-parsed) output elements from an analysis [recursive] + # - resultsMeta: expanded (named) list taken from the analysis json file and + # parsed by .simplifyResultsMeta(), contains all output descriptions of tables/plots + # - oldState: state file that was retrieved before the current analysis ran + # - name: last name of a results element that was found in resultsMeta, intended for + # container types that have dynamic names and do not have a jasp.name attribute. + # E.g., if descriptives is a table in resultsMeta, then results->descriptives->contBinom->table + # resolves to name="descriptives" [recursive] + # + # Return: + # - results list with row lists for tables and png's for plots + # + for (i in 1:length(results)) { + result <- results[[i]] + + type <- .getTerminalType(result) + if (is.null(type) && ! "list" %in% class(result)) # e.g., a title + next + + proposal <- names(results)[i] + if (is.character(proposal) && proposal %in% names(resultsMeta)) + name <- proposal + + if (! is.null(type) && (type == "image" || type == "table")) { + if (type == "table") { + results[[i]] <- .convertTable(result, resultsMeta, name) + } else { # image + results[[i]] <- .convertPlot(result, resultsMeta, oldState, name) + } + } else { # go deeper + results[[i]] <- .convertResults(result, resultsMeta, oldState, name) + } + + } + return(results) +} + +.convertPlot <- function(plotObj, resultsMeta, oldState, name, createObj=TRUE) { + # Converts ggplot2/recordedPlot objects to png's, given they have not been converted previously + # + # Args: + # - plotObj: plot.new function if initing and ggplot2 or recordedPlot object if running + # - resultsMeta: expanded (named) list taken from the analysis json file and + # parsed by .simplifyResultsMeta(), contains all output descriptions of tables/plots + # - oldState: state file that was retrieved before the current analysis ran + # - name: NULL or a character string with the name of the plot object in the analysis json + # - createObj: boolean specifying if a plot object should be added to the output + # + # Return: + # - list with the converted plot along with the title, width, height, etc. + # + if (! any(class(plotObj) %in% c("recordedplot", "ggplot", "function"))) + return(plotObj) + + attr <- attributes(plotObj) + plotMeta <- .getItemMeta(resultsMeta, attr, name, type="image") + if (is.null(plotMeta)) + stop("Could not find meta description for current plot") + + plot <- list() + plot[["title"]] <- .getItemTitle(plotObj, attr, plotMeta) + + if (! is.null(attr) && "jasp.error" %in% names(attr)) { # error specified in analysis + plot[["data"]] <- "" + plot[["error"]] <- list(error="badData", errorMessage=attr[["jasp.error"]]) + return(plot) + } + + p <- plotObj + attributes(p) <- NULL + if (identical(p, plot.new)) + plot[["status"]] <- "running" + else + plot[["status"]] <- "complete" + + existingPlot <- .getExistingPlotName(plotObj, oldState) + if (! is.null(existingPlot)) { + plot[["obj"]] <- plotObj + plot[["data"]] <- existingPlot + } else { # this plot was not previously made + content <- tryCatch( + .writeImage(width=plotMeta[["width"]], height=plotMeta[["height"]], plot=plotObj, obj=createObj), + error = function(e) e + ) + if (inherits(content, "error")) { + plot[["data"]] <- "" + plot[["error"]] <- list(error="badData", errorMessage=content[["message"]]) + return(plot) + } + plot[["obj"]] <- content[["obj"]] + plot[["data"]] <- content[["png"]] + } + + plot[["convertible"]] <- TRUE + plot[["width"]] <- plotMeta[["width"]] + plot[["height"]] <- plotMeta[["height"]] + + if (! is.null(attr) && "jasp.footnotes" %in% names(attr)) + plot[["footnotes"]] <- attr[["jasp.footnotes"]] + + return(plot) +} + +.convertTable <- function(table, resultsMeta, name) { + # Converts data.frame/matrix to a row list with the required schema + # + # Args: + # - table: data.frame, matrix or a row list + # - resultsMeta: expanded (named) list taken from the analysis json file and + # parsed by .simplifyResultsMeta(), contains all output descriptions of tables/plots + # - name: NULL or a character string with the name of the table in the analysis json + # + # Return: + # - list with the converted table along with the title, status, schema taken from the resultsMeta, etc. + # + attr <- attributes(table) + tableMeta <- .getItemMeta(resultsMeta, attr, name, type="table") + if (is.null(tableMeta)) + stop("Could not find meta description for current table") + + footnotes <- customSchema <- error <- NULL + if (! is.null(attr) && (is.matrix(table) || is.data.frame(table))) { + if ("jasp.footnotes" %in% names(attr)) + footnotes <- attr[["jasp.footnotes"]] + if ("jasp.schema" %in% names(attr)) + customSchema <- attr[["jasp.schema"]] + if ("jasp.error" %in% names(attr)) + error <- attr[["jasp.error"]] + } + + if (is.matrix(table)) + table <- as.data.frame(table) + + if (is.jasp.data.frame(table)) # at this point we want to have the default drop behaviour again + attr(table, "class") <- "data.frame" + + combine <- .getCellsToCombine(tableMeta[["columns"]]) + if (is.data.frame(table) && ! is.null(combine)) # if it's a row list row combining should be handled in the analysis + table <- .combineCells(table, combine) + + if (is.data.frame(table)) + table <- list(data=.toListTable(table, tableMeta[["columns"]])) + + table[["title"]] <- .getItemTitle(table, attr, tableMeta) + table[["status"]] <- "complete" + + if (is.null(table[["schema"]])) + table[["schema"]] <- .createTableSchema(table, tableMeta[["columns"]], customSchema) + + if (! is.null(footnotes)) + table <- .addTableFootnotes(table, footnotes) + + if (! is.null(error)) + table[["error"]] <- list(errorType="badData", errorMessage=error) + + return(table) +} + +.getItemMeta <- function(resultsMeta, attr, name, type) { + # Retrieves the appropriate meta description of an output item; it will attempt to + # find it by name (from .convertResults()) or in the attributes (from the object itself) + # + # Args: + # - resultsMeta: expanded (named) list taken from the analysis json file and + # parsed by .simplifyResultsMeta(), contains all output descriptions of tables/plots + # - attr: named list with attributes of the output item + # - name: NULL or a character string with the name of the item + # - type: 'table' or 'image' + # + # Return: + # - NULL if not found and otherwise a selected (named) list for a specific output item, + # taken from the analysis json file + # + itemMeta <- NULL + if ("jasp.name" %in% names(attr)) { # found in attributes + itemMeta <- resultsMeta[[attr[["jasp.name"]]]] + } else if (! is.null(name)) { # found in results list names + itemMeta <- resultsMeta[[name]] + } + if (! is.null(itemMeta) && itemMeta[["type"]] == type) + return(itemMeta) + return(NULL) +} + +.getItemTitle <- function(obj, attr, itemMeta) { + # Retrieves the title of an output item; it will attempt to find it in the obj, + # meta or results. Multiple sources must be checked as the title may be dynamic + # + # Args: + # - obj: the output item itself (plot obj, data.frame, row list, etc.) + # - attr: named list with attributes of the output item + # - itemMeta: selected (named) list for a specific output item, taken from the analysis json file + # + # Return: + # - character string with the title or "" if none was found + # + title <- "" + if (! is.null(itemMeta[["title"]])) + title <- itemMeta[["title"]] + else if ("jasp.title" %in% names(attr)) + title <- attr[["jasp.title"]] + else if (is.list(obj) && ! is.null(obj[["title"]])) + title <- obj[["title"]] + return(title) +} + +.getExistingPlotName <- function(plotObj, oldState) { + # Checks if a plot object has previously been converted to png and if so, returns it + # + # Args: + # - plotObj: plot.new function, or ggplot2 or recordedPlot object + # - oldState: state file that was retrieved before the current analysis ran + # + # Return: + # - the png name if the object was found in the state and NULL otherwise + # + if (is.null(oldState) || ! "figures" %in% names(oldState)) + return(NULL) + + plotName <- NULL + attributes(plotObj) <- NULL + samePlot <- vapply(oldState[["figures"]], + function(obj) { + attributes(obj) <- NULL + identical(plotObj, obj) # note: all.equal is very slow for deeply nested lists + }, logical(1)) + if (any(samePlot)) + plotName <- names(oldState[["figures"]])[samePlot] + return(plotName) +} + +.getCellsToCombine <- function(colsMeta) { + # Checks if any columns have the flag "combine": true and if so, returns them + # + # Args: + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file + # + # Return: + # - NULL if no columns have the combine flag, otherwise the names of the columns that do + # + toCombine <- lapply(colsMeta, + function(col) { + if (! is.null(col[["combine"]])) + col[["name"]] + }) + toCombine <- unlist(toCombine) + if (length(toCombine) > 0) + return(toCombine) + return(NULL) +} + +.combineCells <- function(table, which) { + # Adds .isNewGroup flag to rows that have cells that must be combined + # + # Args: + # - table: data.frame + # - which: character vector of columns with cells to combine + # + # Return: + # - data.frame with one additional column named ".isNewGroup" containing logicals + # + if (nrow(table) == 0 || ! any(which %in% colnames(table))) + return(table) + if (nrow(table) == 1) + return(cbind(table, .isNewGroup=TRUE)) + + grouping <- table[which] + isNewGroup <- logical(nrow(grouping)) + isNewGroup[1] <- TRUE + lastRow <- grouping[1, ] + lastDiff <- ncol(grouping) + ctr <- 1 + for (i in 2:nrow(grouping)) { + row <- grouping[i, ] + if (all(row != lastRow)) { + isNewGroup[i] <- TRUE + } else if (any(row != lastRow)) { + nDiff <- sum(row != lastRow) + if (ctr > 1 && nDiff > lastDiff) { + isNewGroup[i] <- TRUE + } + lastDiff <- nDiff + } + lastRow <- row + ctr <- ctr + 1 + if (isNewGroup[i]) { + ctr <- 1 + lastDiff <- ncol(grouping) + } + } + table <- cbind(table, .isNewGroup=isNewGroup) + return(table) +} + +.createTableSchema <- function(table, colsMeta, customMeta) { + # Dispatches functions that create the schema which describes the table (column + # meta for columns not in the table is discarded) + # + # Args: + # - table: row list + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file + # - customMeta: unnamed list taken from a jasp.schema attribute containing custom meta; + # the meta may contain complete new columns, or changes to existing columns + # + # Return: + # - an unnamed schema list that describes the actual columns in the table + # (with stuff like format="sf:4;dp:3") + # + if (! is.null(customMeta)) # a custom fields list was added to the table + colsMeta <- .addCustomTableMeta(colsMeta, customMeta) + + fields <- .matchMetaToTable(table, colsMeta) + return(list(fields=fields)) +} + +.addCustomTableMeta <- function(colsMeta, customMeta) { + # Adds (dynamic) analysis-specified column meta to the (static)json-specified column meta + # + # Args: + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file + # - customMeta: unnamed list taken from a jasp.schema attribute containing custom meta; + # the meta may contain complete new columns, or changes to existing columns + # + # Return: + # - a valid schema list that contains both static and dynamic properties; + # dynamic properties take precedence over duplicate static properties + # + for (custom in customMeta) { + if (! "name" %in% names(custom)) + stop("Could not locate 'name' in custom table meta") + + metaAdded <- FALSE + name <- custom[["name"]] + for (i in 1:length(colsMeta)) { + col <- colsMeta[[i]] + if (col[["name"]] == name) { + colsMeta[[i]] <- Reduce(modifyList, list(col, custom)) + metaAdded <- TRUE + break + } + } + + if (! metaAdded) # it is not an existing column + colsMeta[[length(colsMeta)+1]] <- custom + } + return(colsMeta) +} + +.matchMetaToTable <- function(table, colsMeta) { + # Finds columns that exist in both the meta and the table and returns the corresponding meta + # + # Args: + # - table: row list + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file and + # possibly combined with custom supplementary meta (see .addCustomTableMeta()) + # + # Return: + # - basically a subset of colsMeta with only the elements that are actually in the table + # + if (length(table[["data"]]) == 0) + stop("Could not find any data in the table, cannot fetch items from the results description") + + metaColNames <- vapply(colsMeta, function(col) col[["name"]], "character") + row <- table[["data"]][[1]] # any row works and we know at least one exists + indices <- which(metaColNames %in% names(row)) + if (length(indices) == 0) + stop("Could not locate any of the columns specified in the results description") + + schema <- colsMeta[indices] + return(schema) +} + +.toListTable <- function(df, colsMeta) { + # Converts a data.frame to a list of rows and then dispatches functions to perform + # type coercion and .clean()'ing + # + # Args: + # - df: data.frame + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file + # + # Return: + # - list with sub-lists for each rows; each row contains named cells that are + # string, numeric or integer + # + if (! is.data.frame(df) && is.list(df)) + return(df) + + if (! is.data.frame(df)) + stop("expecting output to be a data.frame") + + df <- .coerceColTypes(df, colsMeta) + rowList <- do.call(mapply, c(FUN=list, df, SIMPLIFY=FALSE, USE.NAMES=FALSE)) + rowList <- lapply(rowList, .clean) + + return(rowList) +} + +.coerceColTypes <- function(df, colsMeta) { + # Coerces columns of a data.frame to the types that are specified in the + # corresponding column descriptions (numeric/integer) + # + # Args: + # - df: data.frame + # - colsMeta: full (unnamed) list of table columns taken from the analysis json file + # + # Return: + # - data.frame with correct modes for each column + # + for (col in colsMeta) { + name <- col[["name"]] + if (! name %in% colnames(df)) + next + if (any(df[[name]] == ".")) + next + type <- col[["type"]] + if (type == "integer" && ! is.integer(df[[name]])) { + df[[name]] <- suppressWarnings(as.integer(as.character(df[[name]]))) + } else if (type == "number" && ! is.numeric(df[[name]])) { + df[[name]] <- suppressWarnings(as.numeric(as.character(df[[name]]))) + } + } + return(df) +} + +.addTableFootnotes <- function(table, footnotes) { + # Adds footnotes to a table + # + # Args: + # - table: row list + # - footnotes: object created by .newFootnotes() + # + # Return: + # - row list with footnotes added at the top level and inside the rows + # + footnotes <- as.list(footnotes) + for (i in 1:length(footnotes)) { + footnote <- footnotes[[i]] + row <- footnote[["row"]] + cols <- footnote[["cols"]] + if (is.null(row) && is.null(cols)) + next + if (is.character(cols)) { + for (col in cols) { # add note to all cols + newFootnote <- list() + newFootnote[[col]] <- list(i-1) # the numbering of footnote indices starts at 0 + if (! is.numeric(row)) { # add note to all rows for the col + for (j in 1:length(table[["data"]])) { + footnotesRow <- table[["data"]][[j]][[".footnotes"]] + table[["data"]][[j]][[".footnotes"]] <- c(footnotesRow, newFootnote) + } + } else { # add note to a single row + footnotesRow <- table[["data"]][[row]][[".footnotes"]] + table[["data"]][[row]][[".footnotes"]] <- c(footnotesRow, newFootnote) + } + } + } + } + table[["footnotes"]] <- footnotes + return(table) +} + +jasp.data.frame <- function(colnames=NULL, ..., stringsAsFactors=FALSE) { + # Creates a data.frame with class 'jasp.data.frame'; the function works just like data.frame(), + # except when creating empty data.frames with column names, e.g.: + # x <- jasp.data.frame(colnames=c("col1", "col2", "col3")) # or: + # x <- setNames(data.frame(matrix(ncol=3, nrow=0)), c("col1", "col2", "col3")) + # + # Args: + # - colnames: character vector of column names + # - ...: arguments passed on to data.frame() + # - stringsAsFactors: setting for stringsAsFactors passed on to data.frame() + # + # Return: + # - jasp.data.frame which has more robust methods for rbind'ing, cbind'ing, etc. + # + x <- data.frame(..., stringsAsFactors=stringsAsFactors) + if (is.character(colnames) && nrow(x) == 0) { + x <- data.frame(matrix(ncol=length(colnames), nrow=0)) + colnames(x) <- colnames + } + class(x) <- c("jasp.data.frame", "data.frame") + return(x) +} + +is.jasp.data.frame <- function(df) { + inherits(df, "jasp.data.frame") +} + +.extractAttr <- function(pattern, ...) { + # Extracts all attributes matching 'pattern' from the supplied arguments + # + # Args: + # - pattern: character string containing a regular expression + # - ...: anything really as long as it is not nested (e.g., data.frames, matrices, vectors, lists) + # + # Return: + # - list with all the named attributes matching the pattern + # + args <- list(...) + if (length(args) == 0) + return(NULL) + + attrList <- lapply(args, attributes) + attr <- unlist(attrList, recursive=FALSE) # we do not want to unlist the attributes themselves + matches <- attr[grepl(pattern, names(attr))] + if (length(matches) == 0) + return(NULL) + + return(matches) +} + +.restoreAttrJaspDataFrame <- function(df, jaspAttr) { + # Ensures that the data.frame still has the correct class and attributes + # + # Args: + # - df: data.frame + # - jaspAttr: list of attributes starting with "jasp." + # + # Return: + # - data.frame with class "jasp.data.frame" and its attributes restored + # + class(df) <- c("jasp.data.frame", "data.frame") + attributes(df) <- c(attributes(df), jaspAttr) + return(df) +} + +`[.jasp.data.frame` <- function(x, i, j, drop=FALSE) { + # Extracts parts of a data.frame as usual, but with the added benefit that + # (1) attributes starting with "jasp." are never dropped and + # (2) a data.frame is never reduced ('dropped') to a vector + # + # Args: + # - see ?`[.data.frame` + # + # Return: + # - see ?`[.data.frame` + # + jaspAttr <- .extractAttr("^jasp\\.", x) + x <- `[.data.frame`(x, i, j, drop) + x <- .restoreAttrJaspDataFrame(x, jaspAttr) + return(x) +} + +rbind.jasp.data.frame <- function(..., stringsAsFactors=FALSE) { + # Row binds to a data.frame as usual, but with the added benefit that + # (1) names remain intact when row binding to an empty data.frame, + # (2) attributes starting with "jasp." are never dropped, + # (3) a 'mixed' vector with characters and numeric can be supplied and will be coerced appropriately, + # (4) a data.frame never creates factors and so rbinding new char values to a col works + # + # Args: + # - see ?rbind.data.frame + # + # Return: + # - see ?rbind.data.frame + # + jaspAttr <- .extractAttr("^jasp\\.", ...) + args <- list(...) + jaspTable <- NULL + for (i in 1:length(args)) { + arg <- args[[i]] + classes <- class(arg) + if ("jasp.data.frame" %in% classes) { # identify the jasp data frame element so we know what names to store + jaspTable <- arg + } else if (is.vector(arg) && is.character(arg)) { # find possible vectors that may have mixed types + args[[i]] <- lapply(arg, function(val) { # characters vector will be a mixed list + valAsNum <- suppressWarnings(as.numeric(val)) + ifelse(is.na(valAsNum), val, valAsNum) + }) + } + } + names <- colnames(jaspTable) # we need to save the col names of the jasp data frame + + x <- do.call(rbind.data.frame, c(args, list(stringsAsFactors=stringsAsFactors))) + x <- .restoreAttrJaspDataFrame(x, jaspAttr) + + if (length(names) > 0) + colnames(x) <- names + + return(x) +} + +cbind.jasp.data.frame <- function(..., stringsAsFactors=FALSE) { + # Column binds to a data.frame as usual, but with the added benefit that + # (1) attributes starting with "jasp." are never dropped, + # (2) a data.frame never will never have any factors by default + # + # Args: + # - see ?cbind.data.frame + # + # Return: + # - see ?cbind.data.frame + # + jaspAttr <- .extractAttr("^jasp\\.", ...) + x <- cbind.data.frame(..., stringsAsFactors=stringsAsFactors) + x <- .restoreAttrJaspDataFrame(x, jaspAttr) + return(x) +} + +subset.jasp.data.frame <- function(x, ...) { + # Subsets a data.frame as usual, but with the added benefit that + # attributes starting with "jasp." are never dropped + # + # Args: + # - see ?subset.data.frame + # + # Return: + # - see ?subset.data.frame + # + jaspAttr <- .extractAttr("^jasp\\.", x) + x <- subset.data.frame(x, ...) + x <- .restoreAttrJaspDataFrame(x, jaspAttr) + return(x) +} + isTryError <- function(obj){ if (is.list(obj)){ return(any(sapply(obj, function(obj) { @@ -211,7 +1221,83 @@ isTryError <- function(obj){ results } -.readDataSetToEnd <- function(columns=c(), columns.as.numeric=c(), columns.as.ordinal=c(), columns.as.factor=c(), all.columns=FALSE, exclude.na.listwise=c(), ...) { +.getDataSetCols <- function(dataKey, options) { + # Parses the data key so JASP knows how to read the different columns in the dataset + # + # Args: + # - dataKey: named list (from the analysis json) with the possible entries 'factor', + # 'numeric', 'ordinal', 'auto' and 'excludeNA'; the values for these entries + # should be names of options + # - options: named list (from the analysis json) with options to run the analysis with + # + # Return: + # - named list with structure colType=>optionVals (e.g., list(columns.as.factor="contBinom")) + # + if (length(dataKey) == 0) + stop("no columns found to be imported") + + colsToLoad <- vector("list", length(dataKey)) + names(colsToLoad) <- names(dataKey) + for (colType in names(dataKey)) { + opts <- dataKey[[colType]] + if (! is.null(opts)) + colsToLoad[[colType]] <- .optsToColNames(opts, options) + else + colsToLoad[[colType]] <- NULL + } + + auto <- excludeNA <- NULL + if ("auto" %in% names(colsToLoad)) { + auto <- colsToLoad[["auto"]] + colsToLoad[[auto]] <- NULL + } + + if ("excludeNA" %in% names(colsToLoad)) { + excludeNA <- colsToLoad[["excludeNA"]] + colsToLoad[["excludeNA"]] <- NULL + } + + names(colsToLoad) <- sapply(names(colsToLoad), function(name) paste0("columns.as.", name)) + + if (! is.null(auto)) + colsToLoad[["columns"]] <- auto + + if (! is.null(excludeNA)) + colsToLoad[["exclude.na.listwise"]] <- excludeNA + + return(colsToLoad) +} + +.optsToColNames <- function(opts, options) { + # Looks up the options associated with a given colType in the general options list + # and returns their values + # + # Args: + # - opts: options that correspond with a certain colType (e.g., in + # "factor": "fixedFactor" this is "fixedFactor") + # - options: named list (from the analysis json) with options to run the analysis with + # + # Return: + # - NULL if the options have no values, otherwise the values as a character vector + # + if (is.null(names(options))) + stop("expecting the JASP options to be a named list") + + if (any(! opts %in% names(options))) { + indices <- which(! opts %in% names(options)) + stop(paste0("Trying to find dataset columns to read, but it appears some options don't exist: '", paste(opts[indices], collapse=", "), "'")) + } + + result <- NULL + for (opt in opts) { + value <- options[[opt]] + if (is.character(value) && value != "") + result <- c(result, value) + } + return(result) +} + +.readDataSetToEnd <- function(columns=c(), columns.as.numeric=c(), columns.as.ordinal=c(), columns.as.factor=c(), all.columns=FALSE, exclude.na.listwise=c(), ...) { if (is.null(columns) && is.null(columns.as.numeric) && is.null(columns.as.ordinal) && is.null(columns.as.factor) && all.columns == FALSE) return (data.frame()) @@ -385,6 +1471,13 @@ isTryError <- function(obj){ relativePath <- location$relativePath root <- location$root + + # when run in jasptools do not save the state, but store it internally + searchPath <- search() + if ("package:jasptools" %in% searchPath) { + jasptools:::.setInternal("state", state) + return(list(relativePath = relativePath, root = root)) + } base::Encoding(relativePath) <- "UTF-8" base::Encoding(root) <- "UTF-8" @@ -393,7 +1486,7 @@ isTryError <- function(obj){ setwd(root) on.exit(setwd(oldwd)) - base::save(state, file=relativePath, compress=FALSE) + try(suppressWarnings(base::save(state, file=relativePath, compress=FALSE)), silent = FALSE) } result <- list(relativePath = relativePath, root = root) return(result) @@ -417,12 +1510,74 @@ isTryError <- function(obj){ setwd(root) on.exit(setwd(oldwd)) - base::try(base::load(relativePath), silent=TRUE) + base::tryCatch( + base::load(relativePath), + error=function(e) e, + warning=function(w) w + ) } state } +.getStateFromKey <- function(stateKey, options) { + # Loads the state and then parses it based on a key, so only the reusable items are returned + # + # Args: + # - stateKey: named list (from the analysis json) where each name corresponds to a + # name in the state and the value to options in the options list. + # the named entry 'baseSets' contains a list with placeholders that must be + # replaced in the values of the other lists + # - options: named list (from the analysis json) with options to run the analysis with + # + # Return: + # - NULL if no statekey was found or no reusable items were found; otherwise + # the reusable items in the state as they were returned from the analysis + # + state <- .retrieveState() + if (! is.null(state)) { + if (! is.null(stateKey)) { # new method, from json + if ("baseSets" %in% names(stateKey)) # special placeholders will be used in state items + key <- .addBaseSetsState(stateKey) + else # no special placeholders in any set of options + key <- stateKey + } else if ("key" %in% names(attributes(state))) { # old method, from analysis + key <- attributes(state)$key + } else { + return(NULL) + } + state <- .getStateItems(state=state, options=options, key=key) + } + return(state) +} + +.addBaseSetsState <- function(stateKey) { + # Replaces placeholders in state keys with the options associated with those + # placeholders + # + # Args: + # - stateKey: named list (from the analysis json) where each name corresponds to a + # name in the state and the value to options in the options list. + # the named entry 'baseSets' contains a list with placeholders that must be + # replaced in the values of the other lists + # + # Return: + # - the altered state keys, now only containing options from the options list + # + baseSets <- stateKey[["baseSets"]] + stateKey[["baseSets"]] <- NULL + key <- lapply(stateKey, function(x) { + if (any(names(baseSets) %in% x)) { + sets <- baseSets[which(names(baseSets) %in% x)] + set <- unlist(sets, use.names=FALSE) + x <- x[which(! x %in% names(baseSets))] + return(c(x, set)) + } + return(x) + }) + return(key) +} + .shortToLong <- function(dataset, rm.factors, rm.vars, bt.vars) { f <- rm.factors[[length(rm.factors)]] @@ -763,6 +1918,50 @@ callback <- function(results=NULL, progress=NULL) { stop("could not clean value") } +.parseMessage <- function(message, class, ...) { + args <- list(...) + + if (class == "error") { + # If a grouping argument is added, the message 'after grouping on {{}}' is automatically included. + if (! is.null(args[['grouping']])) { + message <- paste(message, .messages('error', 'grouping')) + } + } + + # Find all {{string}}'s that needs to be replaced by values. + toBeReplaced <- regmatches(message, gregexpr("(?<=\\{{)\\S*?(?=\\}})", message, perl=TRUE))[[1]] + if (base::identical(toBeReplaced, character(0)) == FALSE) { # Were there any {{string}}'s? + + if (all(toBeReplaced %in% names(args)) == FALSE) { # Were all replacements provided in the arguments? + missingReplacements <- toBeReplaced[! toBeReplaced %in% names(args)] + stop('Missing required replacement(s): "', paste(missingReplacements, collapse=','), '"') + } + + for (i in 1:length(toBeReplaced)) { + value <- args[[ toBeReplaced[i] ]] + if (length(value) > 1) { # Some arguments may have multiple values, e.g. amount = c('< 3', '> 5000'). + if (toBeReplaced[i] %in% c('variables', 'grouping')) { + value <- paste(value, collapse=', ') + } else { + value <- paste(value, collapse=' or ') + } + } + message <- gsub(paste0('{{', toBeReplaced[i], '}}'), value, message, fixed=TRUE) + } + + } + + # Find all values we do not want in the output, e.g. we do not want to show != + replaceInMessage <- list('!=' = '≠', '==' = '=') + for (i in 1:length(replaceInMessage)) { + if (grepl(names(replaceInMessage)[i], message)) { + message <- gsub(names(replaceInMessage)[i], replaceInMessage[[i]], message) + } + } + + return(message) +} + .newFootnotes <- function() { @@ -780,8 +1979,14 @@ as.list.footnotes <- function(footnotes) { footnotes$footnotes } -.addFootnote <- function(footnotes, text, symbol=NULL) { - +.addFootnote <- function(footnotes, text, symbol=NULL, row=NULL, cols=NULL) { + + if (! is.null(row) && ! is.numeric(row)) + stop("Expecting row to be a numeric index") + + if (! is.null(cols) && ! is.character(cols)) + stop("Expecting cols to be a (vector of) character name(s)") + if (length(footnotes$footnotes) == 0) { if (is.null(symbol)) { @@ -790,7 +1995,7 @@ as.list.footnotes <- function(footnotes) { footnotes$next.symbol <- symbol + 1 } - footnotes$footnotes <- list(list(symbol=symbol, text=text)) + footnotes$footnotes <- list(list(symbol=symbol, text=text, row=row, cols=cols)) return(0) @@ -816,7 +2021,7 @@ as.list.footnotes <- function(footnotes) { footnotes$next.symbol <- symbol + 1 } - new.footnote <- list(symbol=symbol, text=text) + new.footnote <- list(symbol=symbol, text=text, row=row, cols=cols) index <- length(footnotes$footnotes)+1 footnotes$footnotes[[index]] <- new.footnote diff --git a/JASP-Engine/JASP/R/commonMPR.R b/JASP-Engine/JASP/R/commonMPR.R index 2fd5fa4d10..90fe17aca1 100644 --- a/JASP-Engine/JASP/R/commonMPR.R +++ b/JASP-Engine/JASP/R/commonMPR.R @@ -20,8 +20,9 @@ # Testing Precise Null Hypotheses. The American Statistician. 55(1) 62-71 .VovkSellkeMPR <- function(p){ MPR <- ifelse(p >= 1/exp(1), 1, 1/(-exp(1)*p*log(p))) - if (is.nan(MPR)) MPR <- Inf - return(.clean(MPR)) + if (any(is.nan(MPR))) + MPR[is.nan(MPR)] <- Inf + return(sapply(MPR, .clean)) } # Type I error probability / posterior probability from same paper diff --git a/JASP-Engine/JASP/R/commonerrorcheck.R b/JASP-Engine/JASP/R/commonerrorcheck.R index 95c151521e..935b42d64f 100644 --- a/JASP-Engine/JASP/R/commonerrorcheck.R +++ b/JASP-Engine/JASP/R/commonerrorcheck.R @@ -62,52 +62,12 @@ stop('Non-valid type argument provided') } - replaceInMessage <- list('!=' = '≠', '==' = '=') - args <- c(list(grouping=grouping), list(...)) - # Retrieve the error message; spaces indicate that it is already an error message. if (grepl(' ', type, fixed=TRUE) == TRUE) { message <- type } else { - message <- .messages('error', type) - if (is.null(message)) { - stop('Could not find error message for "', type, '" (if you were trying to pass on a message, note that it must be a complete sentence)') - } - } - - # If a grouping argument is added, the message 'after grouping on {{}}' is automatically included. - if (! is.null(args[['grouping']])) { - message <- paste(message, .messages('error', 'grouping')) - } - - # Find all {{string}}'s that needs to be replaced by values. - toBeReplaced <- regmatches(message, gregexpr("(?<=\\{{)\\S*?(?=\\}})", message, perl=TRUE))[[1]] - if (base::identical(toBeReplaced, character(0)) == FALSE) { # Were there any {{string}}'s? - - if (all(toBeReplaced %in% names(args)) == FALSE) { # Were all replacements provided in the arguments? - missingReplacements <- toBeReplaced[! toBeReplaced %in% names(args)] - stop('Missing required replacement(s): "', paste(missingReplacements, collapse=','), '"') - } - - for (i in 1:length(toBeReplaced)) { - value <- args[[ toBeReplaced[i] ]] - if (length(value) > 1) { # Some arguments may have multiple values, e.g. amount = c('< 3', '> 5000'). - if (toBeReplaced[i] %in% c('variables', 'grouping')) { - value <- paste(value, collapse=', ') - } else { - value <- paste(value, collapse=' or ') - } - } - message <- gsub(paste0('{{', toBeReplaced[i], '}}'), value, message, fixed=TRUE) - } - - } - - # Find all values we do not want in the output, e.g. we do not want to show != - for (i in 1:length(replaceInMessage)) { - if (grepl(names(replaceInMessage)[i], message)) { - message <- gsub(names(replaceInMessage)[i], replaceInMessage[[i]], message) - } + args <- c(list(grouping=grouping, class='error', type=type), list(...)) + message <- do.call(.messages, args) } # Turn the message in a html list item diff --git a/JASP-Engine/JASP/R/commonglm.R b/JASP-Engine/JASP/R/commonglm.R index c76fc8eac7..ea0ef2a62e 100644 --- a/JASP-Engine/JASP/R/commonglm.R +++ b/JASP-Engine/JASP/R/commonglm.R @@ -10,17 +10,9 @@ # calculate null and full models nullMod <- glm(nf, family = "binomial", data = dataset) fullMod <- glm(ff, family = "binomial", data = dataset) - - # Maximum number of steps is 2 times the number of terms in the full model - maxStep <- length(attr(fullMod[["terms"]], "term.labels")) * 2 - - + glmRes <- .glmStep(nullMod, fullMod, dataset, - method = options[["method"]], - test = "LR", - pentry = options[["entryPval"]], - premove = options[["removalPval"]], - maxk = maxStep) + method = options[["method"]]) } else { .quitAnalysis("GLM type not supported") @@ -102,8 +94,7 @@ return(formula(paste(.v(dependent), "~", paste(t, collapse = "+")))) } -.glmStep <- function(nullModel, fullModel, dataset, method = "enter", - test = "LR", pentry = 0.05, premove = 0.10, maxk = 1000) { +.glmStep <- function(nullModel, fullModel, dataset, method = "enter") { # .glmStep function # ----------------- # INPUT: calculated glm objects: nullModel, fullModel, and a dataset @@ -113,147 +104,39 @@ # (method = enter, forward, stepwise) or the fullModel (method = backward) # The last model is the final model that was converged on. - - # first, create temporary environment with dataset for update() calls + # first, create temporary environment with dataset for stepAIC() calls tempenv <- new.env() datname <- as.character(as.list(getCall(fullModel))$data) assign(datname, dataset, envir = tempenv) null <- nullModel$formula full <- fullModel$formula - dropscope <- as.formula(paste0("~. -", null[3])) - - converged <- FALSE - modlist <- vector("list", maxk) + assign("nf", null, envir = tempenv) + assign("ff", full, envir = tempenv) - currentk <- 1 if (method == "enter") { + modlist <- vector("list", 2) modlist[[1]] <- nullModel modlist[[2]] <- fullModel - currentk <- 2 - } else if (method == "forward") { - currentModel <- nullModel - modlist[[currentk]] <- currentModel - while (!converged) { - if (currentk > maxk) { - # nonconvergence - break - } - # check addition - a <- try(add1(currentModel, full, test = test, - x = model.matrix(fullModel)), - silent = TRUE) - if (inherits(a, "try-error")) { - # currentmodel == fullmodel - converged <- TRUE - next - } - if (any(na.omit(a[["Pr(>Chi)"]]) < pentry)) { - # add 1! - addition <- as.formula(paste("~ . +",rownames(a)[which.max(a$LRT)])) - newF <- update.formula(currentModel$formula, addition) - # run the update in the temporary environment - currentModel <- evalq(update(currentModel, newF), tempenv) - currentk <- currentk + 1 - } else { - converged <- TRUE - next - } - - modlist[[currentk]] <- currentModel - } } else if (method == "backward") { - currentModel <- fullModel - modlist[[currentk]] <- currentModel - while (!converged) { - if (currentk > maxk) { - # nonconvergence - break - } - # check addition - a <- try(drop1(currentModel, dropscope, test = test), silent = TRUE) - if (inherits(a, "try-error")) { - # currentmodel == nullmodel - converged <- TRUE - next - } - if (any(na.omit(a[["Pr(>Chi)"]]) > premove)) { - # drop 1! - removal <- as.formula(paste("~ . -",rownames(a)[which.min(a$LRT)])) - newF <- update.formula(currentModel$formula, removal) - # run the update in the temporary environment - currentModel <- evalq(update(currentModel, newF), tempenv) - currentk <- currentk + 1 - } else { - converged <- TRUE - next - } - - modlist[[currentk]] <- currentModel - } - } else if (method == "stepwise") { - currentModel <- nullModel - modlist[[currentk]] <- currentModel - while (!converged) { - if (currentk > maxk) { - # nonconvergence - break - } - # check addition - a <- try(add1(currentModel, full, test = test, - x = model.matrix(fullModel)), - silent = TRUE) - # check removal - b <- try(drop1(currentModel, dropscope, test = test), silent = TRUE) - - if (inherits(a, "try-error")) ( - addany <- FALSE - ) else { - addany <- any(na.omit(a[["Pr(>Chi)"]]) < pentry) - } - if (inherits(b, "try-error")) ( - dropany <- FALSE - ) else { - dropany <- any(na.omit(b[["Pr(>Chi)"]]) > premove) - } - - - if (addany & dropany) { - maxa <- max(na.omit(a$LRT)) - maxb <- max(na.omit(b$LRT)) - - if (maxa > maxb) { - dropany <- FALSE - } else { - addany <- FALSE - } - } - - if (addany) { - # add 1! - addition <- as.formula(paste("~ . +",rownames(a)[which.max(a$LRT)])) - newF <- update.formula(currentModel$formula, addition) - # run the update in the temporary environment - currentModel <- evalq(update(currentModel, newF), tempenv) - currentk <- currentk + 1 - } else if (dropany) { - # drop 1! - removal <- as.formula(paste("~ . -",rownames(b)[which.min(b$LRT)])) - newF <- update.formula(currentModel$formula, removal) - # run the update in the temporary environment - currentModel <- evalq(update(currentModel, newF), tempenv) - currentk <- currentk + 1 - } else { - converged <- TRUE - next - } - - modlist[[currentk]] <- currentModel - } + stepOut <- MASS::stepAIC(fullModel, + scope = list(upper=full, lower = null), + trace = 0, + direction = "backward", + keep = function(m, b) list(m)) + modlist <- as.list(stepOut$keep[,1:ncol(stepOut$keep)]) + } else { + # translate method to stepAIC direction + direct <- ifelse(method == "forward", method, "both") + #browser() + stepOut <- JASPstepAIC(nullModel, full, trace = 0, + direction = direct, + keep = function(m, b) list(m)) + modlist <- as.list(stepOut$keep[,1:ncol(stepOut$keep)]) } - return(modlist[1:currentk]) + return(modlist) } .glmModelSummary <- function(glmObj, options, perform, type) { @@ -275,27 +158,30 @@ list(name="tju", title="Tjur R²", type="number", format="sf:4;dp:3") ) + if (options[["method"]] != "enter") { + fields[[6]][["title"]] <- "\u0394\u03A7\u00B2" + } + out[["schema"]] <- list(fields=fields) if (perform == "run" && !is.null(glmObj)) { hasNuisance <- .hasNuisance(options) + if (hasNuisance) { + terms <- rownames(summary(glmObj[[1]])[["coefficients"]]) + terms <- sapply(terms[terms!="(Intercept)"], .formatTerm, + glmModel=glmObj[[1]]) + footnotes <- .newFootnotes() + msg <- paste0("Null model contains nuisance parameters: ", + paste(terms, collapse = ", ")) + .addFootnote(footnotes, symbol="Note.", text = msg) + out[["footnotes"]] <- as.list(footnotes) + } if (options[["method"]] == "enter") { # Two rows: h0 and h1 lr <- .lrtest(glmObj[[1]], glmObj[[2]]) - if (hasNuisance) { - terms <- rownames(summary(glmObj[[1]])[["coefficients"]]) - terms <- sapply(terms[terms!="(Intercept)"], .formatTerm, - glmModel=glmObj[[1]]) - footnotes <- .newFootnotes() - msg <- paste0("Null model contains nuisance parameters: ", - paste(terms, collapse = ", ")) - .addFootnote(footnotes, symbol="Note.", text = msg) - out[["footnotes"]] <- as.list(footnotes) - } - rows <- list( list(mod = "H\u2080", dev = .clean(glmObj[[1]][["deviance"]]), @@ -322,11 +208,11 @@ } else { # multiple rows: m1 - mk rows <- vector("list", length(glmObj)) - + for (midx in 1:length(glmObj)) { mObj <- glmObj[[midx]] if (midx > 1) { - if (options[["method"]] == "forward" || + if (options[["method"]] == "forward" || options[["method"]] == "stepwise") { fadden <- .mcFadden(mObj, glmObj[[1]]) nagel <- .nagelkerke(mObj, glmObj[[1]]) @@ -334,7 +220,7 @@ fadden <- -1*.mcFadden(glmObj[[1]], mObj) nagel <- -1*.nagelkerke(glmObj[[1]], mObj) } - + lr <- .lrtest(glmObj[[midx]], glmObj[[midx-1]]) rows[[midx]] <- list( mod = as.character(midx), @@ -435,7 +321,7 @@ } if (options[["VovkSellkeMPR"]]) { .addFootnote(footnotes, symbol = "\u002A", text = "Vovk-Sellke Maximum - p-Ratio: Based the p-value, the maximum + p-Ratio: Based on the p-value, the maximum possible odds in favor of H\u2081 over H\u2080 equals 1/(-e p log(p)) for p \u2264 .37 (Sellke, Bayarri, & Berger, 2001).") @@ -784,7 +670,7 @@ predictors <- predictors[.v(predictors) %in% attr(mObj[["terms"]], "term.labels")] plots <- vector("list", length(predictors)) - + for (i in seq_along(predictors)) { resPlot <- list() gg <- .plotGlmResiduals(mObj, predictors[i], @@ -831,7 +717,7 @@ if (type == "binomial") { if (!is.null(glmObj)) { resPlot <- list() - gg <- .plotGlmResiduals(glmObj[[length(glmObj)]], + gg <- .plotGlmResiduals(glmObj[[length(glmObj)]], type = options[["residualType"]]) plotObj <- .writeImage(width = options[["plotWidth"]], height = options[["plotHeight"]], @@ -982,7 +868,7 @@ chisq <- max(0, subModel[["deviance"]] - superModel[["deviance"]]) df <- subModel[["df.residual"]] - superModel[["df.residual"]] - + if (chisq == 0 || df == 0) { p <- NULL } else { @@ -1027,7 +913,7 @@ ps <- predict(glmModel, type = "response") ys <- glmModel[["y"]] return(max(c(0,mean(ps[ys])-mean(ps[-ys])))) - + } .bic <- function(glmModel) { diff --git a/JASP-Engine/JASP/R/commonmessages.R b/JASP-Engine/JASP/R/commonmessages.R index 95b2217e77..b943cdb7c1 100644 --- a/JASP-Engine/JASP/R/commonmessages.R +++ b/JASP-Engine/JASP/R/commonmessages.R @@ -15,9 +15,7 @@ # along with this program. If not, see . # -.messages <- function(class, type) { - - +.messages <- function(class, type, ...) { m <- list() ### Error general @@ -49,8 +47,22 @@ ### Footnotes m$footnote$leveneSign <- "Levene's test is significant (p < .05), suggesting a violation of the equal variance assumption" + m$footnote$VovkSellkeMPR <- + "Vovk-Sellke Maximum p-Ratio: Based the p-value, the maximum possible odds in favor of H\u2081 over H\u2080 equals 1/(-e p log(p)) for p \u2264 .37 (Sellke, Bayarri, & Berger, 2001)." + m$footnote$binomNeq <- + "Proportions tested against value: {{value}}." + m$footnote$binomLess <- + "For all tests, the alternative hypothesis specifies that the proportion is less than {{value}}." + m$footnote$binomGreater <- + "For all tests, the alternative hypothesis specifies that the proportion is greater than {{value}}." + message <- m[[class]][[type]] + if (is.null(message)) + stop(paste("Could not find message for class", class, "and type", type)) - return(m[[class]][[type]]) - + args <- list(...) + if (length(args) > 0) + message <- .parseMessage(message, class, ...) + + return(message) } diff --git a/JASP-Engine/JASP/R/descriptives.R b/JASP-Engine/JASP/R/descriptives.R index ed3d77231f..0907bcfebd 100644 --- a/JASP-Engine/JASP/R/descriptives.R +++ b/JASP-Engine/JASP/R/descriptives.R @@ -1256,8 +1256,7 @@ Descriptives <- function(dataset=NULL, options, perform="run", } if (variable %in% names(stateTabs) && - "data" %in% names(stateTabs[[variable]])) { - print(paste(variable, "in state")) + "data" %in% names(stateTabs[[variable]])) { freqTabs[[length(freqTabs) + 1]] <- stateTabs[[variable]] next } @@ -1284,9 +1283,8 @@ Descriptives <- function(dataset=NULL, options, perform="run", for (lev in splitLevels) { t <- table(column[splitFactor==lev]) total <- sum(t) + alltotal <- length(column[splitFactor==lev]) cFreq <- 0 - print(lev) - print(t) for (i in seq_along(names(t))) { row <- list() @@ -1294,7 +1292,7 @@ Descriptives <- function(dataset=NULL, options, perform="run", row[["Level"]] <- names(t)[i] row[["Frequency"]] <- as.vector(t[i]) cFreq <- cFreq + row[["Frequency"]] - row[["Percent"]] <- row[["Frequency"]]/total*100 + row[["Percent"]] <- row[["Frequency"]]/alltotal*100 row[["Valid Percent"]] <- row[["Frequency"]]/total*100 row[["Cumulative Percent"]] <- cFreq/total*100 if (i==1) { @@ -1305,38 +1303,55 @@ Descriptives <- function(dataset=NULL, options, perform="run", rows[[length(rows) + 1]] <- row } + rows[[length(rows) + 1]] <- list( + "factor" = "", + "Level" = "Missing", + "Frequency" = alltotal - total, + "Percent" = (alltotal - total)/alltotal*100, + "Valid Percent" = "", + "Cumulative Percent" = "" + ) + rows[[length(rows) + 1]] <- list( "factor" = "", "Level" = "Total", - "Frequency" = total, + "Frequency" = alltotal, "Percent" = 100, - "Valid Percent" = 100, + "Valid Percent" = "", "Cumulative Percent" = "" ) } - print(rows) } else { t <- table(column) total <- sum(t) cFreq <- 0 + alltotal <- length(column) for (lev in names(t)) { row <- list() row[["Level"]] <- lev row[["Frequency"]] <- as.numeric(t[lev]) cFreq <- cFreq + row[["Frequency"]] - row[["Percent"]] <- row[["Frequency"]]/total*100 + row[["Percent"]] <- row[["Frequency"]]/alltotal*100 row[["Valid Percent"]] <- row[["Frequency"]]/total*100 row[["Cumulative Percent"]] <- cFreq/total*100 rows[[length(rows) + 1]] <- row } + rows[[length(rows) + 1]] <- list( + "Level" = "Missing", + "Frequency" = alltotal - total, + "Percent" = (alltotal - total)/alltotal*100, + "Valid Percent" = "", + "Cumulative Percent" = "" + ) + rows[[length(rows) + 1]] <- list( "Level" = "Total", - "Frequency" = total, + "Frequency" = alltotal, "Percent" = 100, - "Valid Percent" = 100, + "Valid Percent" = "", "Cumulative Percent" = "" ) } diff --git a/JASP-Engine/JASP/R/exploratoryfactoranalysis.R b/JASP-Engine/JASP/R/exploratoryfactoranalysis.R index 54c91ecb9a..a7887eb554 100644 --- a/JASP-Engine/JASP/R/exploratoryfactoranalysis.R +++ b/JASP-Engine/JASP/R/exploratoryfactoranalysis.R @@ -8,893 +8,15 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # - -.DotIfNULL <- function(x){ - - if (is.null(x) || any(is.na(x)) || !is.finite(x)){ - return(".") - } else { - return(x) - } -} - - ExploratoryFactorAnalysis <- function(dataset = NULL, options, perform = "run", - callback = function(...) 0, ...) { - - - - ## call the common initialization function - init <- .initializeEFA(dataset, options, perform) - - - results <- init[["results"]] - dataset <- init[["dataset"]] - - # States: - state <- .retrieveState() - analysisResults <- NULL - newAnalysis <- TRUE - # if ( ! is.null(state) && state$complete) { # is there state? - - if ( !is.null(state)) { # is there state? - - diff <- .diff(options, state$options) # compare old and new options - - nVariable <- length(options$variables) - - if (is.list(diff) && !diff[['rotationMethod']] && !diff[['orthogonalSelector']] && !diff[['obliqueSelector']] && !diff[['variables']] && !diff[['factorMethod']] && - !diff[['eigenValuesBox']] && !diff[['numberOfFactors']]) { - - # old results can be used - newAnalysis <- FALSE - analysisResults <- state$analysisResults - - } - - } - - - # Number of factors: - nVariable <- length(options$variables) - - # Rotation method: - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - - # Number of factors: - - if (options$factorMethod == "parallelAnalysis"){ - - if (nrow(dataset)>0 && nVariable > 0){ - image <- .beginSaveImage() - pa <- psych::fa.parallel(dataset) - .endSaveImage(image) - if (is.na(pa$nfact)) pa$nfact <- 1 - nFactor <- max(1,pa$nfact) - - } else { - if (is.null(state$nFactor)){ - nFactor <- 1 - } else { - nFactor <- state$nFactor - } - } - - } else if (options$factorMethod == "eigenValues"){ - if (nrow(dataset)>0 && nVariable > 0){ - # Compute ev: - image <- .beginSaveImage() - pa <- psych::fa.parallel(dataset) - .endSaveImage(image) - - # Number of factors: - nFactor <- sum(pa$fa.values > options$eigenValuesBox) - } else { - if (is.null(state$nFactor)){ - nFactor <- 1 - } else { - nFactor <- state$nFactor - } - - } - } else if (options$factorMethod == "manual"){ - nFactor <- options$numberOfFactors - } - - - # Check if number of factors is correct: - if (length(options$variables) > 0 && nFactor > length(options$variables)){ - error <- TRUE - errorMessage <- "Too many factors requested" - } else { - error <- FALSE - errorMessage <- "" - } - - - if (perform == "run" && nrow(dataset) > 0 && is.null(analysisResults) && length(options$variables) > 1 && !error){ - - analysisResults <- .estimateEFA(dataset, options, perform,nFactor) - - } else { - # Otherwise just keep the state - # analysisResults <- NULL - } - - # Make factor loadings table: - # if (newAnalysis){ - results[["factorLoadings"]] <- .getLoadingsEFA(analysisResults, options,perform,nFactor,dataset) - # } else { - # results[["factorLoadings"]] <- state$results[["factorLoadings"]] - # } - - - # Create factor correlation table: - # if (newAnalysis || (is.list(diff) && diff[['incl_correlations']] && options$incl_correlations)){ - results[["factorCorrelations"]] <- .getFactorCorrelationsEFA(analysisResults, options,perform) - # } else { - # results[["factorCorrelations"]] <- state$results[["factorCorrelations"]] - # } - - - # Create fit measures tables: - results[["goodnessOfFit"]] <- .goodnessOfFitEFA(analysisResults, options,perform) - results[["fitMeasures"]] <- .fitMeasuresEFA(analysisResults, options,perform) - - # Create path diagram: - results[["pathDiagram"]] <- .pathDiagramEFA(analysisResults, options,perform) - - # Scree plot: - results[["screePlot"]] <- .screePlotFA(dataset, options,perform) - - ## TEMP DEBUG THING: - # save(dataset,results,init,options,perform,callback,...,file = "/Users/sachaepskamp/Dropbox/work/JASP/Rcodes/JASPinit.RData") - - - #### META - meta <- list( - list(name = "title", type = "title") - ) - - if (isTRUE(options$incl_loadings)){ - meta[[length(meta)+1]] <- list(name = "factorLoadings", type = "table") - - } - - if (isTRUE(options$incl_correlations)){ - meta[[length(meta)+1]] <- list(name = "factorCorrelations", type = "table") - } - - if (isTRUE(options$incl_GoF)){ - meta[[length(meta)+1]] <- list(name = "goodnessOfFit", type = "table") - } - if (isTRUE(options$incl_fitIndices)){ - meta[[length(meta)+1]] <- list(name = "fitMeasures", type = "table") - } - if (isTRUE(options$incl_pathDiagram)){ - meta[[length(meta)+1]] <- list(name = "pathDiagram", type = "image") - } - if (isTRUE(options$incl_screePlot)){ - meta[[length(meta)+1]] <- list(name = "screePlot", type = "image") - } - - - - results[[".meta"]] <- meta - - # Dummies: - status <- list(ready=TRUE, error=error,errorMessage=errorMessage) - - if (status$error == TRUE){ - results[["factorLoadings"]][["error"]] <- list(errorType="badData", errorMessage=status$errorMessage) - results[["factorCorrelations"]][["error"]] <- list(errorType="badData") - results[["goodnessOfFit"]][["error"]] <- list(errorType="badData") - results[["fitMeasures"]][["error"]] <- list(errorType="badData") - results[["pathDiagram"]][["error"]] <- list(errorType="badData") - results[["screePlot"]][["error"]] <- list(errorType="badData") - } else { - results[["factorLoadings"]][["error"]] <- NULL - results[["factorCorrelations"]][["error"]] <- NULL - results[["goodnessOfFit"]][["error"]] <- NULL - results[["fitMeasures"]][["error"]] <- NULL - results[["pathDiagram"]][["error"]] <- NULL - results[["screePlot"]][["error"]] <- NULL - } - - if (perform == "run" && status$ready) { - state <- list(options=options,analysisResults=analysisResults,nFactor=nFactor,results=results,complete=TRUE) - retList <- list(results=results, status="complete", state=state) - - } else { - state <- list(options=options,nFactor=nFactor,analysisResults=analysisResults,results=results,complete=FALSE) - - retList <- list(results=results, status="inited",state=state) - - } - - return(retList) -} - -### Inner functions ### -# Estimate EFA: -.estimateEFA <- function(dataset, options, perform, nFactor=1) { - - nVariable <- length(options$variables) - - # Rotation method: - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - - # # Number of factors: - # if (options$factorMethod == "eigenValues"){ - # # Covariance matrix: - # corMatrix <- cor(dataset, use = "pairwise.complete.obs") ### ADD MISSING OPTION - # - # # Eigenvalues: - # EV <- eigen(corMatrix,only.values = TRUE)$values - # - # # Number of factors: - # nFactor <- sum(EV > options$eigenValuesBox) - # } else if (options$factorMethod == "manual"){ - # nFactor <- options$numberOfFactors - # } - - if (nFactor == 0) stop("Number of factors must be > 0") - if (nFactor > nVariable){ - stop("Too many factors requested") - } - - Results <- psych::fa(dataset,nFactor, rotate = Rotation) - # Results <- factanal(dataset, nFactor, rotation = Rotation) - - return(Results) -} - -# Get loadings matrix: -.getLoadingsEFA <- function(analysisResults, options,perform, nFactor=1,dataset){ - - # Extract loadings: - # if (!is.null(analysisResults) & perform == "run"){ - if (!is.null(analysisResults)){ - - loadingsMatrix <- as.matrix(loadings(analysisResults)) - # loadingsMatrix <- matrix(unlist(loadingsMatrix),nrow(loadingsMatrix),ncol(loadingsMatrix)) - - - # loadingsMatrix <- matrix(1,12,1) - - - if (ncol(loadingsMatrix) > 0){ - colnames(loadingsMatrix) <- paste("Factor",seq_len(ncol(loadingsMatrix))) - } - - # Add uniqueness: - - loadingsMatrix <- cbind(loadingsMatrix, Uniqueness = unname(analysisResults$uniquenesses)) - - } else { - - if (is.null(options$numberOfFactors)){ - nFact <- 0 - } else { - nFact <- options$numberOfFactors - } - - loadingsMatrix <- matrix(NA,length(options$variables),nFactor+1) - colnames(loadingsMatrix) <- c( paste("Factor",seq_len(nFactor)),"Uniqueness") - rownames(loadingsMatrix) <- colnames(dataset) - - } - - # Create JASP table: - Loadings <- list() - Loadings[["title"]] <- "Factor Loadings" - Loadings[["schema"]] <- list(fields = list( - # list(name="model", title = "", type="text"), - # list(name="cn_05", title = "Hoelter Critical N (CN) alpha=0.05", type="number", format = "dp:3"), - # list(name="cn_01", title = "Hoelter Critical N (CN) alpha=0.01", type="number", format = "dp:3"), - # list(name="gfi", title = "Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="agfi", title = "Parsimony Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="mfi", title = "McDonald Fit Index (MFI)", type="number", format = "dp:3"), - # list(name="ecvi", title = "Expected Cross-Validation Index (ECVI)", type="number", format = "dp:3") - )) - - # Add columns: - Loadings[["schema"]][["fields"]][[1]] <- list(name = "VAR", title = "", type="string") - - for (j in seq_len(ncol(loadingsMatrix))){ - Loadings[["schema"]][["fields"]][[j+1]] <- list(name = colnames(loadingsMatrix)[j], title = colnames(loadingsMatrix)[j], type="number", format = "dp:3") - } - - Loadings[["data"]] <- list() - - # Add rows: - if (nrow(loadingsMatrix)==0){ - Loadings[["data"]][[1]] <- as.list(rep(".",ncol(loadingsMatrix)+1)) - } - - for (i in seq_len(nrow(loadingsMatrix))){ - - dat <- loadingsMatrix[i,] - - Loadings[["data"]][[i]] <- list(VAR = .unv(rownames(loadingsMatrix)[i])) - for (j in seq_along(dat)){ - if (is.na(dat[j])){ - Loadings[["data"]][[i]][[j+1]] <- "." - } else { - Loadings[["data"]][[i]][[j+1]] <- unname(ifelse(abs(dat[j]) < options$highlightText & j != length(dat),".",dat[j])) - } - - } - - names( Loadings[["data"]][[i]]) <- sapply(Loadings[["schema"]][["fields"]],"[[",'name') - } - - return(Loadings) -} - -# Init: -.initializeEFA <- function(dataset, options, perform) { - - groups <- options$groupingVariable - depvars <- unlist(options$variables) - - - if (!is.null(groups) && groups == "") groups <- NULL - - if (is.null(dataset)) { - ## if we are ready to run, read in the dataset - if (perform == "run" && length(options$variables) > 1) { - # - # if (options$missingValues == "excludeListwise") { - # exclude <- depvars - # } else { - # exclude <- NULL - # } - # - dataset <- .readDataSetToEnd(columns.as.numeric = depvars, - columns.as.factor = groups) - - ## else just read in the headers (and create an empty table) - } else { - dataset <- .readDataSetHeader(columns.as.numeric = depvars, - columns.as.factor = groups) - } - } - - ## this is the main object; we add stuff to it and return it - results <- list( - "title" = "Exploratory Factor Analysis", - "citation" = list("Revelle, W. (2015) psych: Procedures for Personality and Psychological Research, Northwestern University, - Evanston, Illinois, USA, http://CRAN.R-project.org/package=psych Version = 1.5.8.") - ) - - #### META - # meta <- list() - # meta[[1]] <- list(name = "title", type = "title") - # meta[[2]] <- list(name = "ttest", type = "table") - # meta[[3]] <- list(name="assumptionChecks", type="object", meta=list(list(name="shapiroWilk", type="table"), list(name="levene", type="table"))) - # meta[[4]] <- list(name="descriptives", type="object", meta=list(list(name="descriptivesTable", type="table"), list(name = "descriptivesPlots", type = "collection", meta="image"))) - # - # results[[".meta"]] <- meta - list("results" = results, "dataset" = dataset) -} - - -# Path diagram: -.pathDiagramEFA <- function(analysisResults, options, perform){ - - pathDiagram <- list() - pathDiagram$title <- "Path Diagram" - pathDiagram$width <- options$plotWidthPathDiagram - pathDiagram$height <- options$plotHeightPathDiagram - if (pathDiagram$height==0){ - pathDiagram$height <- 1 + 299 * (length(options$variables)/5) - } - pathDiagram$custom <- list(width="plotWidthPathDiagram", height="plotHeightPathDiagram") - - - # filename <- .requestTempFileNameNative("svg") - # grDevices::svg(filename=filename, width=width/72, height=height/72, bg="transparent") - # - # relativePath <- filename$relativePath - # base::Encoding(filename) <- "UTF-8" - # - - # if (perform != "run" | is.null(analysisResults) | !isTRUE(options$incl_pathDiagram)){ - - if (is.null(analysisResults) || !isTRUE(options$incl_pathDiagram) || perform == "init"){ - - pathDiagram$data <- NULL - - } else { - - # image <- .beginSaveImage(pathDiagram$width,pathDiagram$height) - # Lambda <- loadings(analysisResults) - # labels <- .unv(rownames(Lambda)) - # Lambda <- matrix(c(Lambda),nrow(Lambda),ncol(Lambda)) - # Theta <- analysisResults$uniquenesses - # Psi <- analysisResults$r.scores - # - # qgraph::qgraph.loadings(Lambda, factorCors = Psi, resid = Theta,model="reflective", - # cut = options$highlightText, residSize = 0.25,labels = - # labels) - # - - # Via qgraph: - # Model matrices: - LY <- as.matrix(loadings(analysisResults)) - TE <- diag(analysisResults$uniqueness) - PS <- analysisResults$r.scores - - # Variable names: - labels <- .unv(rownames(LY)) - factors <- paste0("F",seq_len(ncol(LY))) - - # Number of variables: - nFactor <- length(factors) - nIndicator <- length(labels) - nTotal <- nFactor + nIndicator - - # Make layout: - # For each manifest, find strongest loading: - strongest <- apply(abs(LY),1,which.max) - ord <- order(strongest) - - # Reshuffle labels and LY: - labels <- labels[ord] - LY <- LY[ord,] - - # Edgelist: - # Factor loadings - E_loadings <- data.frame(from = rep(factors,each=nIndicator), to = rep(labels,times=nFactor),weight=c(LY), - stringsAsFactors = FALSE) - - # Residuals: - E_resid <- data.frame(from=labels,to=labels,weight=diag(TE)) - - # Factor correlations: - E_cor <- data.frame(from = c(factors[col(PS)]), to = c(factors[row(PS)]),weight=c(PS), - stringsAsFactors = FALSE) - E_cor <- E_cor[E_cor$from != E_cor$to,] - - # Total: - E <- rbind(E_loadings,E_resid,E_cor) - - # Make the layout: - sq <- function(x){ - seq(-1,1,length.out = x+2)[-c(1,x+2)] - } - - L <- cbind( - c(rep(-1,nFactor),rep(1,nIndicator)), - c(sq(nFactor),sq(nIndicator)) - ) - - # Compute curvature of correlations: - # Numeric edgelist: - E_cor_numeric <- cbind(match(E_cor$from,factors),match(E_cor$to,factors)) - - # Compute distance: - dist <- abs(L[E_cor_numeric[,1],2] - L[E_cor_numeric[,2],2]) - - - - # Max has curvature of 8! - # Min has curvature of 4! - - min <- 2 - max <- 8 - # Scale to max: - dist <- min + dist/(max(dist))*(max - min) - if (length(unique(dist))==1){ - dist[] <- mean(c(max,min)) - } - - # Scale such that this is true when nfactor = 2 and nIndicator == 5: - # dist <- dist/((nFactor/2)*(nIndicator/2)) - - # Scale to plot width: - Scale <- sqrt(pathDiagram$width^2 + pathDiagram$height^2)/sqrt(480^2 + 300^2) - dist <- 1/Scale * dist - # - - # Curvature: - curve <- c(rep(0,nrow(E_loadings)), - rep(0,nrow(E_resid)), - dist) - - # Edge connectpoints: - ECP <- matrix(NA,nrow(E),2) - ECP[nrow(E_loadings) + nrow(E_resid) + seq_len(nrow(E_cor)),1:2] <- 1.5*pi - ECP[seq_len(nrow(E_loadings)),2] <- 1.5*pi - - - # Loop rotation: - loopRotation <- 0.5*pi - - # bidirectional: - bidir <- c(rep(FALSE,nrow(E_loadings) + nrow(E_resid)), rep(TRUE, nrow(E_cor))) - - # Shape: - shape <- c(rep("circle",nFactor), rep("rectangle",nIndicator)) - - - - # Just some observations: - # 10 indicators, height of 6 works well - # 50 indicators, height of 1 works well - # Good function: exp(2.25 - 0.05 * nIndicator) - # OIther idea: keep size constant, just increase plot size in JASP! - - # Size: - size1 <- c( - rep(12,nFactor), - rep(30,nIndicator) - ) - size2 <- c( - rep(12,nFactor), - rep( 7,nIndicator) - ) - - # Plot: - label.scale.equal <- c(rep(1,nFactor),rep(2,nIndicator)) - - .plotFunc <- function() { - # Run once without plotting to obtain the scaled label sizes: - qgraph::qgraph(E, layout = L, directed=TRUE, bidirectional=bidir, residuals = TRUE, residScale = 10, - labels = c(factors,labels), curve = curve, curveScale = FALSE, edgeConnectPoints = ECP, - loopRotation=loopRotation, shape = shape, vsize = size1, vsize2 = size2,label.scale.equal=label.scale.equal, - residScale = 2, mar = c(5,10,5,12), normalize = FALSE, label.fill.vertical = 0.75, cut = options$highlightText, - bg = "transparent" - ) - } - - content <- .writeImage(width = pathDiagram$width, height = pathDiagram$height, plot = .plotFunc, obj = TRUE) - pathDiagram[["convertible"]] <- TRUE - pathDiagram[["obj"]] <- content[["obj"]] - pathDiagram[["data"]] <- content[["png"]] - - # pathDiagram$data <- .endSaveImage(image) - pathDiagram$status <- "complete" - - } - - - - # grDevices::dev.off() - - return(pathDiagram) -} - -# Factor correlations: -.getFactorCorrelationsEFA <- function(analysisResults, options,perform){ - - # Extract loadings: - if (!is.null(analysisResults)){ - - corMatrix <- as.matrix(analysisResults$r.scores) - # loadingsMatrix <- matrix(unlist(loadingsMatrix),nrow(loadingsMatrix),ncol(loadingsMatrix)) - - - # loadingsMatrix <- matrix(1,12,1) - - } else { - - if (is.null(options$numberOfFactors)){ - nFact <- 0 - } else { - nFact <- options$numberOfFactors - } - - corMatrix <- matrix(,0,0) - - } - - if (ncol(corMatrix) > 0){ - colnames(corMatrix) <- rownames(corMatrix) <- paste("Factor",seq_len(ncol(corMatrix))) - } - - # Create JASP table: - FactorCorrelations <- list() - FactorCorrelations[["title"]] <- "Factor Correlations" - FactorCorrelations[["schema"]] <- list(fields = list( - # list(name="model", title = "", type="text"), - # list(name="cn_05", title = "Hoelter Critical N (CN) alpha=0.05", type="number", format = "dp:3"), - # list(name="cn_01", title = "Hoelter Critical N (CN) alpha=0.01", type="number", format = "dp:3"), - # list(name="gfi", title = "Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="agfi", title = "Parsimony Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="mfi", title = "McDonald Fit Index (MFI)", type="number", format = "dp:3"), - # list(name="ecvi", title = "Expected Cross-Validation Index (ECVI)", type="number", format = "dp:3") - )) - - # Add columns: - FactorCorrelations[["schema"]][["fields"]][[1]] <- list(name = "VAR", title = "", type="string") - - for (j in seq_len(ncol(corMatrix))){ - FactorCorrelations[["schema"]][["fields"]][[j+1]] <- list(name = colnames(corMatrix)[j], title = colnames(corMatrix)[j], type="number", format = "dp:3") - } - - FactorCorrelations[["data"]] <- list() - - # Add rows: - for (i in seq_len(nrow(corMatrix))){ - - dat <- corMatrix[i,] - FactorCorrelations[["data"]][[i]] <- list(VAR = rownames(corMatrix)[i]) - for (j in 1:i){ - FactorCorrelations[["data"]][[i]][[j+1]] <- unname(dat[j]) - } - - names(FactorCorrelations[["data"]][[i]]) <- sapply(FactorCorrelations[["schema"]][["fields"]],"[[",'name')[seq_along(FactorCorrelations[["data"]][[i]])] - } - - return(FactorCorrelations) -} - -# Goodness of fit -.goodnessOfFitEFA <- function(analysisResults, options,perform){ - - # Extract loadings: - if (!is.null(analysisResults)){ - - # print(analysisResults) - # print(analysisResults$RMSEA) - # - # Fits <- list( - # CHI = analysisResults$STATISTIC, - # PVAL = analysisResults$PVAL, - # DF = analysisResults$dof, - # RMSEA = analysisResults$RMSEA['RMSEA'], - # RMSEAlower = analysisResults$RMSEA['lower'], - # RMSEAupper = analysisResults$RMSEA['upper'], - # TLI = analysisResults$TLI, - # RMS = analysisResults$rms, - # CRMS = analysisResults$crms, - # BIC = analysisResults$BIC - # ) - - - Fits <- list( - CHI = .DotIfNULL(analysisResults$STATISTIC), - PVAL = .DotIfNULL(analysisResults$PVAL), - DF = .DotIfNULL(analysisResults$dof), - RMSEA = .DotIfNULL(unname(analysisResults$RMSEA['RMSEA'])), - RMSEAlower = .DotIfNULL(unname(analysisResults$RMSEA['lower'])), - RMSEAupper = .DotIfNULL(unname(analysisResults$RMSEA['upper'])), - TLI = .DotIfNULL(analysisResults$TLI), - RMS = .DotIfNULL(analysisResults$rms), - CRMS = .DotIfNULL(analysisResults$crms), - BIC = .DotIfNULL(analysisResults$BIC) - ) - - } else { - - Fits <- list( - CHI = ".", - PVAL = ".", - DF = ".", - RMSEA = ".", - RMSEAlower = ".", - RMSEAupper = ".", - TLI = ".", - RMS = ".", - CRMS = ".", - BIC = "." - ) - - } - - - # Create JASP table: - goodnessOfFit <- list() - goodnessOfFit[["title"]] <- "Chi-squared Test" - - # Create the columns: - goodnessOfFit[["schema"]] <- list(fields = list( - list(name = "model", title="", type = "string"), - list(name = "chisq", title = "Value", type="number", format = "dp:3"), - list(name = "df", title = "df", type="integer"), - list(name = "p", title = "p", type="number", format = "dp:3;p:.001") - )) - - # Create and fill the row(s): - goodnessOfFit[["data"]] <- list( - list( - model = "Model", - chisq = ifelse(Fits$DF>0,Fits$CHI,"."), - df = ifelse(Fits$DF>0,Fits$DF,"."), - p = ifelse(Fits$DF>0,Fits$PVAL,".") - ) - ) - - - return(goodnessOfFit) -} - - -# fitMeasures -.fitMeasuresEFA <- function(analysisResults, options,perform){ - - # browser() - - # Extract loadings: - if (!is.null(analysisResults)){ - - Fits <- list( - CHI = .DotIfNULL(analysisResults$STATISTIC), - PVAL = .DotIfNULL(analysisResults$PVAL), - DF = .DotIfNULL(analysisResults$dof), - RMSEA = .DotIfNULL(unname(analysisResults$RMSEA['RMSEA'])), - RMSEAlower = .DotIfNULL(unname(analysisResults$RMSEA['lower'])), - RMSEAupper = .DotIfNULL(unname(analysisResults$RMSEA['upper'])), - TLI = .DotIfNULL(analysisResults$TLI), - RMS = .DotIfNULL(analysisResults$rms), - CRMS = .DotIfNULL(analysisResults$crms), - BIC = .DotIfNULL(analysisResults$BIC) - ) - - } else { - - Fits <- list( - CHI = ".", - PVAL = ".", - DF = ".", - RMSEA = ".", - RMSEAlower = ".", - RMSEAupper = ".", - TLI = ".", - RMS = ".", - CRMS = ".", - BIC = "." - ) - - } - - - # Create JASP table: - FitMeasures <- list() - FitMeasures[["title"]] <- "Additional fit indices" - - # Create the columns: - FitMeasures[["schema"]] <- list(fields = list( - list(name = "model", title="", type = "string"), - list(name = "RMSEA", title = "RMSEA", type="number", format = "dp:3"), - list(name = "RMSEAci", title = "RMSEA 90% confidence", type="string"), - list(name = "TLI", title = "TLI", type="number", format = "dp:3"), - list(name = "BIC", title = "BIC", type="number", format = "dp:3") - )) - - # Create and fill the row(s): - if (is.numeric(Fits$RMSEAlower)) - { - Fits$RMSEAlower <- round(Fits$RMSEAlower,3) - } - - if (is.numeric(Fits$RMSEAupper)) - { - Fits$RMSEAupper <- round(Fits$RMSEAupper,3) - } - - FitMeasures[["data"]] <- list( - list( - model = "Model", - RMSEA = Fits$RMSEA, - RMSEAci = paste(Fits$RMSEAlower,"-",Fits$RMSEAupper), - TLI = Fits$TLI, - BIC = Fits$BIC - ) - ) - - - return(FitMeasures) -} - - -### Screeplot: -.screePlotFA <- function(dataset, options, perform) { - - screePlot <- list() - - # if (perform == "run" && status$ready && !status$error && !is.null(model)) { - # - if (perform == "run" && ncol(dataset) > 0 && nrow(dataset)> 0 && length(options$variables) > 1) { - - screePlot$title <- "Scree Plot" - screePlot$width <- options$plotWidthScreePlot - screePlot$height <- options$plotHeightScreePlot - screePlot$custom <- list(width="plotWidthScreePlot", height="plotHeightScreePlot") - - # Compute ev: - image <- .beginSaveImage() - pa <- psych::fa.parallel(dataset) - .endSaveImage(image) - - # Eigenvalues: - EV <- data.frame( - id = seq_len(ncol(dataset)), - ev = pa$fa.values, - type = "Data" - ) - - # Parallel analysis: - PA <- data.frame( - id = seq_len(ncol(dataset)), - ev = pa$fa.sim, - type = "Simulated (95th quantile)" - ) - - combined <- rbind(EV,PA) - - p <- ggplot2::ggplot(combined, ggplot2::aes_string(x="id",y="ev",lty="type",pch="type")) + ggplot2::geom_point(na.rm = TRUE, size=3) + - ggplot2::xlab("") + ggplot2::ylab("Eigenvalue")+ ggplot2::xlab("Factors") +ggplot2::geom_line(na.rm = TRUE) + - ggplot2::ggtitle("") + ggplot2::theme_bw() + ggplot2::geom_hline(yintercept = options$eigenValuesBox) + - ggplot2::theme(panel.grid.minor=ggplot2::element_blank(), plot.title = ggplot2::element_text(size=18), - panel.grid.major=ggplot2::element_blank(), axis.line = ggplot2::element_line(colour = "black", size=1.2), - axis.title.x = ggplot2::element_text(size=18,vjust=-.2), axis.title.y = ggplot2::element_text(size=18,vjust=1.2), - axis.text.x = ggplot2::element_text(size=15), axis.text.y = ggplot2::element_text(size=15), - panel.background = ggplot2::element_rect(fill = 'transparent', colour = NA), - plot.background = ggplot2::element_rect(fill = 'transparent', colour = NA), - panel.border = ggplot2::element_blank(), - axis.ticks = ggplot2::element_line(size = 0.5), - axis.ticks.margin = grid::unit(1,"mm"), - axis.ticks.length = grid::unit(3, "mm"), - plot.margin = grid::unit(c(0,0,.5,.5), "cm")) + - ggplot2::scale_linetype_discrete("") + ggplot2::scale_shape_discrete("") + - ggplot2::theme(legend.position = c(0.99,0.99),legend.justification = c(1,1), - legend.text=ggplot2::element_text(size=12.5), - panel.background=ggplot2::element_rect(fill="transparent",colour=NA), - plot.background=ggplot2::element_rect(fill="transparent",colour=NA), - legend.key = ggplot2::element_rect(fill = "transparent", colour = "transparent"), - legend.background=ggplot2::element_rect(fill="transparent",colour=NA)) - - # image <- .beginSaveImage(options$plotWidthScreePlot, options$plotHeightScreePlot) - # print(p) - # content <- .endSaveImage(image) - - content <- .writeImage(width = options$plotWidthScreePlot, - height = options$plotHeightScreePlot, - plot = p, obj = TRUE) - screePlot$data <- content[["png"]] - screePlot[["convertible"]] <- TRUE - screePlot[["obj"]] <- content[["obj"]] - - # screePlot$data <- content - screePlot$status <- "complete" - - statescreePlot <- screePlot - - } else { - - screePlot$title <- "Scree Plot" - screePlot$width <- options$plotWidthScreePlot - screePlot$height <- options$plotHeightScreePlot - screePlot$custom <- list(width="plotWidthScreePlot", height="plotHeightScreePlot") - - screePlot$data <- NULL - - statescreePlot <- NULL - - # if (status$error) - # screePlot$error <- list(errorType="badData") - - } - - return(screePlot) + callback = function(...) list(status="ok"), state = NULL, ...) { + return(mainFunctionPCAEFA(type = "efa", dataset = NULL, options, perform = "run", + callback = function(...) list(status="ok"), state = NULL, ...)) } diff --git a/JASP-Engine/JASP/R/massStepAIC.R b/JASP-Engine/JASP/R/massStepAIC.R new file mode 100644 index 0000000000..d8e0cb1a97 --- /dev/null +++ b/JASP-Engine/JASP/R/massStepAIC.R @@ -0,0 +1,362 @@ +# MASS replacements for JASP + +getDatasetFromNearestAncestor <- function(name, i=1) { + var <- try(get(name, envir=parent.frame(i)), silent = TRUE) + if (inherits(var, "try-error") || class(var)!="data.frame") { + var <- getDatasetFromNearestAncestor(name, i+1) + } + var +} + + +JASPaddterm <- + function(object, scope, scale = 0, test = c("none", "Chisq", "F"), + k = 2, sorted = FALSE, trace = FALSE, ...) +{ + Fstat <- function(table, rdf) { + dev <- table$Deviance + df <- table$Df + diff <- pmax(0, (dev[1L] - dev)/df) + Fs <- diff/(dev/(rdf-df)) + Fs[df < .Machine$double.eps] <- NA + P <- Fs + nnas <- !is.na(Fs) + P[nnas] <- safe_pf(Fs[nnas], df[nnas], rdf - df[nnas], lower.tail=FALSE) + list(Fs=Fs, P=P) + } + if(missing(scope) || is.null(scope)) stop("no terms in scope") + if(!is.character(scope)) + scope <- add.scope(object, update.formula(object, scope)) + if(!length(scope)) + stop("no terms in scope for adding to object") + oTerms <- attr(terms(object), "term.labels") + int <- attr(object$terms, "intercept") + ns <- length(scope) + dfs <- dev <- numeric(ns+1) + names(dfs) <- names(dev) <- c("", scope) + add.rhs <- paste(scope, collapse = "+") + add.rhs <- eval(parse(text = paste("~ . +", add.rhs))) + new.form <- update.formula(object, add.rhs) + oc <- object$call + Terms <- terms(new.form) + oc$formula <- Terms + ## model.frame.glm looks at the terms part for the environment + fob <- list(call = oc, terms=Terms) + class(fob) <- class(object) + + ########################################################################### + ######### HERE IS THE EDIT, USE DATA FROM 2nd ORDER PARENT FRAME ########## + ########################################################################### + + dname <- as.character(as.list(fob$call)$data) + dset <- parent.frame(2)[[dname]] + + x <- model.matrix(Terms, model.frame(fob, xlev = object$xlevels, data=dset), + contrasts = object$contrasts) + + ########################################################################### + + n <- nrow(x) + oldn <- length(object$residuals) + y <- object$y + newn <- length(y) + if(newn < oldn) + warning(sprintf(ngettext(newn, + "using the %d/%d row from a combined fit", + "using the %d/%d rows from a combined fit"), + newn, oldn), domain = NA) + wt <- object$prior.weights + if(is.null(wt)) wt <- rep(1, n) + Terms <- attr(Terms, "term.labels") + asgn <- attr(x, "assign") + ousex <- match(asgn, match(oTerms, Terms), 0L) > 0L + if(int) ousex[1L] <- TRUE + X <- x[, ousex, drop = FALSE] + z <- glm.fit(X, y, wt, offset=object$offset, + family=object$family, control=object$control) + dfs[1L] <- z$rank + dev[1L] <- z$deviance + ## workaround for PR#7842. terms.formula may have flipped interactions + sTerms <- sapply(strsplit(Terms, ":", fixed=TRUE), + function(x) paste(sort(x), collapse=":")) + for(tt in scope) { + if(trace) { + message(gettextf("trying + %s", tt), domain = NA) + utils::flush.console() + } + stt <- paste(sort(strsplit(tt, ":")[[1L]]), collapse=":") + usex <- match(asgn, match(stt, sTerms), 0L) > 0L + X <- x[, usex|ousex, drop = FALSE] + z <- glm.fit(X, y, wt, offset=object$offset, + family=object$family, control=object$control) + dfs[tt] <- z$rank + dev[tt] <- z$deviance + } + if (is.null(scale) || scale == 0) + dispersion <- summary(object, dispersion = NULL)$dispersion + else dispersion <- scale + fam <- object$family$family + if(fam == "gaussian") { + if(scale > 0) loglik <- dev/scale - n + else loglik <- n * log(dev/n) + } else loglik <- dev/dispersion + aic <- loglik + k * dfs + aic <- aic + (extractAIC(object, k = k)[2L] - aic[1L]) # same baseline for AIC + dfs <- dfs - dfs[1L] + dfs[1L] <- NA + aod <- data.frame(Df = dfs, Deviance = dev, AIC = aic, + row.names = names(dfs), check.names = FALSE) + o <- if(sorted) order(aod$AIC) else seq_along(aod$AIC) + if(all(is.na(aic))) aod <- aod[, -3] + test <- match.arg(test) + if(test == "Chisq") { + dev <- pmax(0, loglik[1L] - loglik) + dev[1L] <- NA + LRT <- if(dispersion == 1) "LRT" else "scaled dev." + aod[, LRT] <- dev + nas <- !is.na(dev) + dev[nas] <- safe_pchisq(dev[nas], aod$Df[nas], lower.tail=FALSE) + aod[, "Pr(Chi)"] <- dev + } else if(test == "F") { + if(fam == "binomial" || fam == "poisson") + warning(gettextf("F test assumes 'quasi%s' family", fam), + domain = NA) + rdf <- object$df.residual + aod[, c("F value", "Pr(F)")] <- Fstat(aod, rdf) + } + aod <- aod[o, ] + head <- c("Single term additions", "\nModel:", deparse(formula(object))) + if(scale > 0) + head <- c(head, paste("\nscale: ", format(scale), "\n")) + class(aod) <- c("anova", "data.frame") + attr(aod, "heading") <- head + aod +} + +# file MASS/R/stepAIC.R +# copyright (C) 1994-2007 W. N. Venables and B. D. Ripley +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 or 3 of the License +# (at your option). +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# A copy of the GNU General Public License is available at +# http://www.r-project.org/Licenses/ +# +JASPstepAIC <- + function(object, scope, scale = 0, + direction = c("both", "backward", "forward"), + trace = 1, keep = NULL, steps = 1000, use.start = FALSE, k = 2, ...) +{ + mydeviance <- function(x, ...) + { + dev <- deviance(x) + if(!is.null(dev)) dev else extractAIC(x, k=0)[2L] + } + + cut.string <- function(string) + { + if(length(string) > 1L) + string[-1L] <- paste("\n", string[-1L], sep = "") + string + } + + re.arrange <- function(keep) + { + namr <- names(k1 <- keep[[1L]]) + namc <- names(keep) + nc <- length(keep) + nr <- length(k1) + array(unlist(keep, recursive = FALSE), c(nr, nc), list(namr, namc)) + } + + step.results <- function(models, fit, object, usingCp=FALSE) + { + change <- sapply(models, "[[", "change") + rd <- sapply(models, "[[", "deviance") + dd <- c(NA, abs(diff(rd))) + rdf <- sapply(models, "[[", "df.resid") + ddf <- c(NA, abs(diff(rdf))) + AIC <- sapply(models, "[[", "AIC") + heading <- c("Stepwise Model Path \nAnalysis of Deviance Table", + "\nInitial Model:", deparse(formula(object)), + "\nFinal Model:", deparse(formula(fit)), + "\n") + aod <- + if(usingCp) + data.frame(Step = change, Df = ddf, Deviance = dd, + "Resid. Df" = rdf, "Resid. Dev" = rd, + Cp = AIC, check.names = FALSE) + else data.frame(Step = change, Df = ddf, Deviance = dd, + "Resid. Df" = rdf, "Resid. Dev" = rd, + AIC = AIC, check.names = FALSE) + attr(aod, "heading") <- heading + class(aod) <- c("Anova", "data.frame") + fit$anova <- aod + fit + } + + Terms <- terms(object) + object$formula <- Terms + if(inherits(object, "lme")) object$call$fixed <- Terms + else if(inherits(object, "gls")) object$call$model <- Terms + else object$call$formula <- Terms + if(use.start) warning("'use.start' cannot be used with R's version of 'glm'") + md <- missing(direction) + direction <- match.arg(direction) + backward <- direction == "both" | direction == "backward" + forward <- direction == "both" | direction == "forward" + if(missing(scope)) { + fdrop <- numeric() + fadd <- attr(Terms, "factors") + if(md) forward <- FALSE + } else { + if(is.list(scope)) { + fdrop <- if(!is.null(fdrop <- scope$lower)) + attr(terms(update.formula(object, fdrop)), "factors") + else numeric() + fadd <- if(!is.null(fadd <- scope$upper)) + attr(terms(update.formula(object, fadd)), "factors") + } else { + fadd <- if(!is.null(fadd <- scope)) + attr(terms(update.formula(object, scope)), "factors") + fdrop <- numeric() + } + } + models <- vector("list", steps) + if(!is.null(keep)) keep.list <- vector("list", steps) + n <- nobs(object, use.fallback = TRUE) # might be NA + fit <- object + bAIC <- extractAIC(fit, scale, k = k, ...) + edf <- bAIC[1L] + bAIC <- bAIC[2L] + if(is.na(bAIC)) + stop("AIC is not defined for this model, so 'stepAIC' cannot proceed") + if(bAIC == -Inf) + stop("AIC is -infinity for this model, so 'stepAIC' cannot proceed") + nm <- 1 + Terms <- terms(fit) + if(trace) { + cat("Start: AIC=", format(round(bAIC, 2)), "\n", + cut.string(deparse(formula(fit))), "\n\n", sep='') + utils::flush.console() + } + models[[nm]] <- list(deviance = mydeviance(fit), df.resid = n - edf, + change = "", AIC = bAIC) + if(!is.null(keep)) keep.list[[nm]] <- keep(fit, bAIC) + usingCp <- FALSE + while(steps > 0) { + steps <- steps - 1 + AIC <- bAIC + ffac <- attr(Terms, "factors") + ## don't drop strata terms + if(!is.null(sp <- attr(Terms, "specials")) && + !is.null(st <- sp$strata)) ffac <- ffac[-st,] + scope <- factor.scope(ffac, list(add = fadd, drop = fdrop)) + aod <- NULL + change <- NULL + if(backward && length(scope$drop)) { + aod <- MASS::dropterm(fit, scope$drop, scale = scale, + trace = max(0, trace - 1), k = k, ...) + rn <- row.names(aod) + row.names(aod) <- c(rn[1L], paste("-", rn[-1L], sep=" ")) + ## drop all zero df terms first. + if(any(aod$Df == 0, na.rm=TRUE)) { + zdf <- aod$Df == 0 & !is.na(aod$Df) + nc <- match(c("Cp", "AIC"), names(aod)) + nc <- nc[!is.na(nc)][1L] + ch <- abs(aod[zdf, nc] - aod[1, nc]) > 0.01 + if(any(is.finite(ch) & ch)) { + warning("0 df terms are changing AIC") + zdf <- zdf[!ch] + } + ## drop zero df terms first: one at time since they + ## may mask each other + if(length(zdf) > 0L) + change <- rev(rownames(aod)[zdf])[1L] + } + } + if(is.null(change)) { + if(forward && length(scope$add)) { + ## EDIT: USE JASPaddterm + aodf <- JASPaddterm(fit, scope$add, scale = scale, + trace = max(0, trace - 1), k = k, ...) + rn <- row.names(aodf) + row.names(aodf) <- c(rn[1L], paste("+", rn[-1L], sep=" ")) + aod <- + if(is.null(aod)) aodf + else rbind(aod, aodf[-1, , drop=FALSE]) + } + attr(aod, "heading") <- NULL + if(is.null(aod) || ncol(aod) == 0) break + ## need to remove any terms with zero df from consideration + nzdf <- if(!is.null(aod$Df)) aod$Df != 0 | is.na(aod$Df) + aod <- aod[nzdf, ] + if(is.null(aod) || ncol(aod) == 0) break + nc <- match(c("Cp", "AIC"), names(aod)) + nc <- nc[!is.na(nc)][1L] + o <- order(aod[, nc]) + if(trace) { + print(aod[o, ]) + utils::flush.console() + } + if(o[1L] == 1) break + change <- rownames(aod)[o[1L]] + } + usingCp <- match("Cp", names(aod), 0) > 0 + ## may need to look for a 'data' argument in parent + fit <- update(fit, paste("~ .", change), evaluate = FALSE) + fit <- eval.parent(fit) + nnew <- nobs(fit, use.fallback = TRUE) + if(all(is.finite(c(n, nnew))) && nnew != n) + stop("number of rows in use has changed: remove missing values?") + Terms <- terms(fit) + bAIC <- extractAIC(fit, scale, k = k, ...) + edf <- bAIC[1L] + bAIC <- bAIC[2L] + if(trace) { + cat("\nStep: AIC=", format(round(bAIC, 2)), "\n", + cut.string(deparse(formula(fit))), "\n\n", sep='') + utils::flush.console() + } + ## add a tolerance as dropping 0-df terms might increase AIC slightly + if(bAIC >= AIC + 1e-7) break + nm <- nm + 1 + models[[nm]] <- + list(deviance = mydeviance(fit), df.resid = n - edf, + change = change, AIC = bAIC) + if(!is.null(keep)) keep.list[[nm]] <- keep(fit, bAIC) + } + if(!is.null(keep)) fit$keep <- re.arrange(keep.list[seq(nm)]) + step.results(models = models[seq(nm)], fit, object, usingCp) +} + +extractAIC.loglm <- function(fit, scale, k = 2, ...) +{ + edf <- fit$n - fit$df + c(edf, fit$deviance + k * edf) +} + +extractAIC.lme <- function(fit, scale, k = 2, ...) +{ + if(fit$method != "ML") stop("AIC undefined for REML fit") + res <- logLik(fit) + edf <- attr(res, "df") + c(edf, -2*res + k * edf) +} + +extractAIC.gls <- function(fit, scale, k = 2, ...) +{ + if(fit$method != "ML") stop("AIC undefined for REML fit") + res <- logLik(fit) + edf <- attr(res, "df") + c(edf, -2*res + k * edf) +} + +terms.gls <- terms.lme <- function(x, ...) terms(formula(x), ...) diff --git a/JASP-Engine/JASP/R/networkanalysis.R b/JASP-Engine/JASP/R/networkanalysis.R index 9a85701021..d945342f40 100644 --- a/JASP-Engine/JASP/R/networkanalysis.R +++ b/JASP-Engine/JASP/R/networkanalysis.R @@ -109,9 +109,11 @@ NetworkAnalysis <- function ( list(name = "weightmatrixTB", type = "table"), list(name = "layoutTB", type = "table"), list(name = "centralityTB", type = "table"), + list(name = "clusteringTB", type = "table"), list(name = "mgmTB", type = "table"), list(name = "networkPLT", type = "collection", meta="image"), list(name = "centralityPLT", type = "image"), + list(name = "clusteringPLT", type = "image"), list(name = "bootstrapEdgePLT", type = "collection", meta="image"), list(name = "bootstrapCentPLT", type = "collection", meta="image") ) @@ -137,6 +139,8 @@ NetworkAnalysis <- function ( bootstrap = bootstrapArgs, # depends also on normalization of centrality measures centrality = c(defArgs, "normalizeCentrality", "maxEdgeStrength", "minEdgeStrength"), + # depends on everything but plotting arguments + clustering = defArgs, # depends also on plotting arguments networkPLT = c(defArgs, # depends also on plotting arguments @@ -168,6 +172,8 @@ NetworkAnalysis <- function ( ## Do Analysis ## ---- + doBootstrap <- options[["bootstrapOnOff"]] && options[["numberOfBootstraps"]] > 0 + # Sort out whether things are set to defaults or not. if (length(variables) > 2) { @@ -179,6 +185,32 @@ NetworkAnalysis <- function ( # check for errors, but only if there was a change in the data (which implies state[["network"]] is NULL) if (is.null(state[["network"]])) { + customChecks <- NULL + + # check if data must be binarized + if (options[["estimator"]] %in% c("IsingFit", "IsingSampler")) { + idx <- colnames(dataset) != .v(options[["groupingVariable"]]) + dataset[idx] <- bootnet::binarize(dataset[idx], split = options[["split"]], verbose = FALSE, removeNArows = FALSE) + + if (options[["estimator"]] == "IsingFit") { + # required check since IsingFit removes these variables from the analyses + customChecks <- c(customChecks, + function() { + tbs <- apply(dataset, 2, table) + if (any(tbs <= 1)) { + idx <- which(tbs <= 1, arr.ind = TRUE) + return(sprintf( + "After binarizing the data too little variance remained in variable(s): %s.", + paste0(.unv(colnames(tbs[, idx[, 2], drop = FALSE])), collapse = ", ") + )) + } + return(NULL) + } + ) + } + } + + # default error checks checks <- c("infinity", "variance", "observations", "varCovData") @@ -218,16 +250,13 @@ NetworkAnalysis <- function ( varCovData.grouping = groupingVariable, varCovData.corFun = fun, varCovData.corArgs = list(use = "pairwise"), + custom = customChecks, exitAnalysisIfErrors = TRUE) } network <- .networkAnalysisRun(dataset = dataset, options = options, variables = variables, perform = perform, oldNetwork = state) - if (options[["bootstrapOnOff"]] ) { - - # results[["generalTB"]] <- .networkAnalysisGeneralTable(NULL, dataset, options, perform = perform) # any errors will appear top of this table - # # initialize progress table - # results[["bootstrapTB"]] <- .networkAnalysisBootstrapTable(network, dataset, options, perform) + if (doBootstrap) { network <- .networkAnalysisBootstrap(network, options, variables, perform, oldNetwork = state, results = results, callback = callback) if (is.null(network) && perform == "run") { # bootstrap was aborted @@ -252,7 +281,7 @@ NetworkAnalysis <- function ( if (FALSE && options[["tableFitMeasures"]]) { results[["fitMeasuresTB"]] <- .fitMeasuresTB(network, options, perform) } - if (options[["bootstrapOnOff"]]) { + if (doBootstrap) { results[["bootstrapTB"]] <- .networkAnalysisBootstrapTable(network, dataset, options, perform) if (options[["StatisticsEdges"]]) { @@ -278,6 +307,9 @@ NetworkAnalysis <- function ( if (options[["tableCentrality"]]) { results[["centralityTB"]] <- .networkAnalysisCentralityTable(network, options, perform) } + if (options[["tableClustering"]]) { + results[["clusteringTB"]] <- .networkAnalysisClusteringTable(network, options, perform) + } if (options[["plotNetwork"]]) { results[["networkPLT"]] <- .networkAnalysisNetworkPlot(network, options, perform, oldPlot = state[["networkPLT"]]) allNetworkPlots <- results[["networkPLT"]][["collection"]] @@ -288,6 +320,10 @@ NetworkAnalysis <- function ( results[["centralityPLT"]] <- .networkAnalysisCentralityPlot(network, options, perform, oldPlot = state[["centralityPLT"]]) keep <- c(keep, results[["centralityPLT"]][["data"]]) } + if (options[["plotClustering"]]) { + results[["clusteringPLT"]] <- .networkAnalysisClusteringPlot(network, options, perform, oldPlot = state[["clusteringPLT"]]) + keep <- c(keep, results[["clusteringPLT"]][["data"]]) + } } results <- .networkAnalysisAddReferencesToTables(results, options) ## Exit Analysis ## ---- @@ -305,6 +341,7 @@ NetworkAnalysis <- function ( network = network[["network"]], bootstrap = network[["bootstrap"]], centrality = network[["centrality"]], + clustering = network[["clustering"]], layout = network[["layout"]], networkPLT = results[["networkPLT"]], centralityPLT = results[["centralityPLT"]], @@ -348,6 +385,7 @@ NetworkAnalysis <- function ( networkList <- list( network = oldNetwork[["network"]], centrality = oldNetwork[["centrality"]], + clustering = oldNetwork[["clustering"]], layout = oldNetwork[["layout"]] ) @@ -583,6 +621,23 @@ NetworkAnalysis <- function ( } } + + if (is.null(networkList[["clustering"]])) { + + for (nw in seq_along(dataset)) { + + network <- networkList[["network"]][[nw]] + clust <- qgraph::clusteringTable(network, labels = .unv(network$labels)) + clust <- reshape2::dcast(clust, graph + node + type ~ measure, value.var = "value") + TBclust <- as.data.frame(clust[-c(1, 3)]) + TBclust <- TBclust[c(1, order(colnames(TBclust)[-1])+1)] # alphabetical order + + networkList[["clustering"]][[nw]] <- TBclust + + } + + } + if (is.null(names(dataset))) { nms <- "Network" @@ -618,7 +673,7 @@ NetworkAnalysis <- function ( } - names(networkList[["network"]]) <- names(networkList[["centrality"]]) <- nms + names(networkList[["network"]]) <- names(networkList[["centrality"]]) <- names(networkList[["clustering"]]) <- nms networkList[["status"]] <- .networkAnalysisNetworkHasErrors(networkList) @@ -737,36 +792,41 @@ NetworkAnalysis <- function ( table <- list( title = "Summary of Network", schema = list(fields = list( - list(name = "info", title = "", type = "string") - #list(name = "value", title = "", type = "number", format="sf:4;dp:3") + list(name = "info", title = "Network", type = "string"), + list(name = "nodes", title = "Number of nodes", type = "integer"), + list(name = "nonZero", title = "Number of non-zero edges"), + list(name = "Sparsity", title = "Sparsity", type = "number", format="sf:4;dp:3") )) ) - for (i in seq_len(nGraphs)) { - table[["schema"]][["fields"]][[i+1]] <- - list(name = paste0("value", i), title = names(network[["network"]])[i], type = "number", format="sf:4;dp:3") - } + + # we only want to show this if there are more than 2 networks (but as the first column not the last) + if (nGraphs == 1) + table[["schema"]][["fields"]][[1]] <- NULL footnotes <- .newFootnotes() msg <- NULL - - TBcolumns <- list(info = c("Number of nodes", "Number of non-zero edges", "Sparsity")) - + # browser() if (is.null(network[["network"]])) { # fill in with . - TBcolumns[["value"]] <- rep(".", 3*nGraphs) - table[["schema"]][["fields"]][[2]][["title"]] <- "Network" + TBcolumns <- list( + info = paste("Network", 1:nGraphs), + nodes = rep(".", nGraphs), + nonZero = rep(".", nGraphs), + Sparsity = rep(".", nGraphs) + ) } else { # fill in with info from bootnet:::print.bootnet + + TBcolumns <- list(info = names(network[["network"]]), + nodes = NULL, nonZero = NULL, Sparsity = NULL) + nVar <- ncol(network[["network"]][[1]][["graph"]]) for (i in seq_len(nGraphs)) { nw <- network[["network"]][[i]] - - TBcolumns[[paste0("value", i)]] <- c( - nrow(nw[["graph"]]), - sum(nw[["graph"]][upper.tri(nw[["graph"]], diag = FALSE)] == 0), - mean(nw[["graph"]][upper.tri(nw[["graph"]], diag = FALSE)] == 0) - ) + TBcolumns[["nodes"]][i] <- nrow(nw[["graph"]]) + TBcolumns[["nonZero"]][i] <- paste(sum(nw[["graph"]][upper.tri(nw[["graph"]], diag = FALSE)] != 0), "/", nVar * (nVar-1) / 2) + TBcolumns[["Sparsity"]][i] <- mean(nw[["graph"]][upper.tri(nw[["graph"]], diag = FALSE)] == 0) } @@ -807,6 +867,29 @@ NetworkAnalysis <- function ( if (!is.null(options[["colorNodesByDataMessage"]])) { .addFootnote(footnotes = footnotes, text = options[["colorNodesByDataMessage"]], symbol = "Warning: ") } + if (options[["minEdgeStrength"]] != 0) { + + ignored <- logical(nGraphs) + for (i in seq_along(network[["network"]])) { + ignored[i] <- all(abs(qgraph::getWmat(network[["network"]][[i]])) <= options[["minEdgeStrength"]]) + } + + if (any(ignored)) { + if (nGraphs == 1) { + text <- "Minimum edge strength ignored in the network plot because it was larger than the absolute value of the strongest edge." + } else { + text <- sprintf("Minimum edge strength ignored in the network plot of group%s %s because it was larger than the absolute value of the strongest edge.", + ifelse(sum(ignored) == 2, "s", ""), + paste0(names(network[["network"]])[ignored], collapse = ", ") + ) + } + .addFootnote(footnotes = footnotes, symbol = "Warning: ", text = text) + } + } + if (xor(options[["bootstrapOnOff"]], options[["numberOfBootstraps"]] > 0)) { + text <- "Bootstrapping is only done when 'Bootstrap network' is ticked and 'Number of Bootstraps' is larger than 0." + .addFootnote(footnotes = footnotes, symbol = "Warning: ", text = text) + } table[["footnotes"]] <- as.list(footnotes) return(table) @@ -971,6 +1054,107 @@ NetworkAnalysis <- function ( } +.networkAnalysisClusteringTable <- function(network, options, perform) { + + nGraphs <- max(1, length(network[["network"]])) + if (is.null(network[["clustering"]])) { + measureNms <- list(c("Barrat", "Onnela", "WS", "Zhang")) + } else { + measureNms <- NULL + for (i in seq_len(nGraphs)) + measureNms[[i]] <- colnames(network[["clustering"]][[i]])[-1] + + } + + + nMeasures <- lengths(measureNms) + + table <- list( + title = "Clustering measures per variable", + schema = list(fields = list( + list(name = "Variable", title = "Variable", type = "string") + )) + ) + + # shared titles + overTitles <- names(network[["network"]]) + if (is.null(overTitles)) + overTitles <- "Network" # paste0("Network", 1:nGraphs) + + # create the fields + idx <- 2 + for (i in seq_len(nGraphs)) { + for (j in seq_len(nMeasures[i])) { # four clustering columns per network + table[["schema"]][["fields"]][[idx]] <- list( + name = paste0(measureNms[[i]][j], i), + title = measureNms[[i]][j], + type = "number", + format="sf:4;dp:3", + overTitle = overTitles[i]) + idx <- idx + 1 + } + } + + + if (is.null(network[["clustering"]])) { # make empty table + + # same length restriction for running analyses + if (!is.null(options[["variables"]]) || !(length(options[["variables"]]) > 0)) { + + TBcolumns <- rep(list("."), nMeasures + 1) + names(TBcolumns) <- c("Variable", measureNms) + + } else { + + TBcolumns <- data.frame( + .v(options[["variables"]]), + rep( + list(rep(".", length(options[["variables"]]))), + nMeasures) + ) + } + names(TBcolumns) <- c("Variable", measureNms) + + } else { # fill with results + + TBcolumns <- NULL + for (i in seq_len(nGraphs)) { + + toAdd <- network[["clustering"]][[i]] + names(toAdd) <- c("Variable", paste0(measureNms[[i]], i)) + if (i == 1) {# if more than 1 network drop additional variable column + TBcolumns <- toAdd + } else { + toAdd <- toAdd[, -1] + TBcolumns <- cbind(TBcolumns, toAdd) + } + + } + + } + + data <- .TBcolumns2TBrows(TBcolumns) + table[["data"]] <- data + + footnotes <- .newFootnotes() + if (!all(nMeasures == 4)) { + nms <- names(network[["network"]])[nMeasures != 4] + if (length(nms) == 1) + s <- "" + else s <- "s" + text <- sprintf("Clustering measures could not be computed for network%s: %s", + s, + paste0(nms, collapse = ", ") + ) + .addFootnote(footnotes = footnotes, text = text, symbol = "Warning: ") + } + + table[["footnotes"]] <- as.list(footnotes) + + return(table) + +} + .networkAnalysisWeightMatrixTable <- function(network, options, variables, perform) { nGraphs <- max(1, length(network[["network"]])) @@ -1151,6 +1335,87 @@ NetworkAnalysis <- function ( } +.networkAnalysisClusteringPlot <- function(network, options, perform, oldPlot = NULL) { + + if (!is.null(oldPlot) && !identical(oldPlot[["data"]], "")) + return(oldPlot) + + plot <- list( + title = "Clustering Plot", + width = options[["plotWidthClustering"]], + height = options[["plotHeightClustering"]], + custom = list(width = "plotWidthClustering", height = "plotHeightClustering"), + data = "", + status = "complete" + ) + + if (perform == "run" && !is.null(network)) { + wide <- network[["clustering"]] + + len <- lengths(wide) + idx <- which.max(len) + if (!all(len == len[idx])) { + + cnms <- colnames(wide[[idx]])[-1] + for (i in which(len != len[idx])) { + + cnmsToAdd <- cnms[!(cnms %in% colnames(wide[[i]]))] + for (nms in cnmsToAdd) + wide[[i]][[nms]] <- NA + wide[[i]] <- wide[[i]][colnames(wide[[idx]])] + + } + } + + wideDf <- Reduce(rbind, wide) + if (length(wide) > 1) { + wideDf[["type"]] <- rep(names(network[["clustering"]]), each = nrow(wideDf) / length(wide)) + Long <- reshape2::melt(wideDf, id.vars = c("node", "type")) + colnames(Long)[3] <- "measure" + Long[["graph"]] <- Long[["type"]] + Long[["type"]] <- TRUE # options[["separateCentrality"]] + } else { + Long <- reshape2::melt(wideDf, id.vars = "node") + colnames(Long)[2] <- "measure" + Long[["graph"]] <- NA + } + + if (options[["abbreviateLabels"]]) + Long[["node"]] <- base::abbreviate(Long[["node"]], options[["abbreviateNoChars"]]) + + # code modified from qgraph::centralityPlot(). Type and graph are switched so the legend title says graph + + Long <- Long[gtools::mixedorder(Long$node), ] + Long$node <- factor(as.character(Long$node), levels = unique(gtools::mixedsort(as.character(Long$node)))) + if (length(unique(Long$graph)) > 1) { + g <- ggplot2::ggplot(Long, ggplot2::aes(x = value, y = node, group = graph, + colour = graph)) + + ggplot2::guides(color = ggplot2::guide_legend(title = options[["groupingVariable"]])) # change the name graph into the variable name for splitting + } else { + g <- ggplot2::ggplot(Long, ggplot2::aes(x = value, y = node, group = graph)) + } + g <- g + ggplot2::geom_path() + ggplot2::xlab("") + ggplot2::ylab("") + ggplot2::geom_point() + if (length(unique(Long$type)) > 1) { + g <- g + ggplot2::facet_grid(type ~ measure, scales = "free") + + } else { + g <- g + ggplot2::facet_grid(~measure, scales = "free") + } + g <- g + ggplot2::theme_bw() + + content <- .writeImage(width = plot[["width"]], height = plot[["height"]], plot = g) + + plot[["convertible"]] <- TRUE + plot[["data"]] <- content[["png"]] + plot[["obj"]] <- content[["obj"]] + plot[["status"]] <- "complete" + + } + + return(plot) + +} + .networkAnalysisOneNetworkPlot <- function() { # eval(quote()) construction because this function is evaluated inside .writeImage() @@ -1164,7 +1429,8 @@ NetworkAnalysis <- function ( if (!options[["signedNetwork"]]) { wMat <- abs(wMat) } - + if (all(abs(wMat) <= minE)) + minE <- NULL qgraph::qgraph( input = wMat, diff --git a/JASP-Engine/JASP/R/packagecheck.R b/JASP-Engine/JASP/R/packagecheck.R index 9fab24d6b0..aa7b169057 100644 --- a/JASP-Engine/JASP/R/packagecheck.R +++ b/JASP-Engine/JASP/R/packagecheck.R @@ -21,7 +21,7 @@ #--auto-generated expected <- rbind(expected, c('BAS', '1.4.7')) - expected <- rbind(expected, c('BDgraph', '2.41')) + expected <- rbind(expected, c('BDgraph', '2.43')) expected <- rbind(expected, c('BMS', '0.3.4')) expected <- rbind(expected, c('BayesFactor', '0.9.12-2')) expected <- rbind(expected, c('Epi', '2.10')) @@ -31,13 +31,14 @@ expected <- rbind(expected, c('Hmisc', '4.0-3')) expected <- rbind(expected, c('IsingFit', '0.3.1')) expected <- rbind(expected, c('IsingSampler', '0.2')) + expected <- rbind(expected, c('JASPgraphs', '0.1.0')) expected <- rbind(expected, c('KernSmooth', '2.23-15')) - expected <- rbind(expected, c('MASS', '7.3-45')) + expected <- rbind(expected, c('MASS', '7.3-47')) expected <- rbind(expected, c('Matrix', '1.2-8')) expected <- rbind(expected, c('MatrixModels', '0.4-1')) expected <- rbind(expected, c('R6', '2.2.2')) expected <- rbind(expected, c('RColorBrewer', '1.1-2')) - expected <- rbind(expected, c('Rcpp', '0.12.13')) + expected <- rbind(expected, c('Rcpp', '0.12.14')) expected <- rbind(expected, c('SparseM', '1.77')) expected <- rbind(expected, c('SuppDists', '1.1-9.4')) expected <- rbind(expected, c('TH.data', '1.0-8')) @@ -55,14 +56,14 @@ expected <- rbind(expected, c('boot', '1.3-18')) expected <- rbind(expected, c('bootnet', '1.0.2')) expected <- rbind(expected, c('ca', '0.70')) - expected <- rbind(expected, c('car', '2.1-5')) + expected <- rbind(expected, c('car', '2.1-6')) expected <- rbind(expected, c('checkmate', '1.8.5')) expected <- rbind(expected, c('class', '7.3-14')) expected <- rbind(expected, c('cluster', '2.0.5')) expected <- rbind(expected, c('cmprsk', '2.2-7')) expected <- rbind(expected, c('coda', '0.19-1')) expected <- rbind(expected, c('codetools', '0.2-15')) - expected <- rbind(expected, c('coin', '1.2-1')) + expected <- rbind(expected, c('coin', '1.2-2')) expected <- rbind(expected, c('colorspace', '1.3-2')) expected <- rbind(expected, c('compiler', '3.3.3')) expected <- rbind(expected, c('contfrac', '1.1-11')) @@ -99,7 +100,7 @@ expected <- rbind(expected, c('gtools', '3.5.0')) expected <- rbind(expected, c('highr', '0.6')) expected <- rbind(expected, c('hmeasure', '1.0')) - expected <- rbind(expected, c('htmlTable', '1.9')) + expected <- rbind(expected, c('htmlTable', '1.11.0')) expected <- rbind(expected, c('htmltools', '0.3.6')) expected <- rbind(expected, c('htmlwidgets', '0.9')) expected <- rbind(expected, c('huge', '1.2.7')) @@ -116,25 +117,25 @@ expected <- rbind(expected, c('lavaan', '0.5-23.1097')) expected <- rbind(expected, c('lazyeval', '0.2.1')) expected <- rbind(expected, c('lme4', '1.1-14')) - expected <- rbind(expected, c('lmerTest', '2.0-33')) + expected <- rbind(expected, c('lmerTest', '2.0-36')) expected <- rbind(expected, c('lmtest', '0.9-35')) expected <- rbind(expected, c('logspline', '2.1.9')) expected <- rbind(expected, c('longitudinal', '1.1.12')) - expected <- rbind(expected, c('lsmeans', '2.27-2')) + expected <- rbind(expected, c('lsmeans', '2.27-61')) expected <- rbind(expected, c('magrittr', '1.5')) expected <- rbind(expected, c('markdown', '0.8')) expected <- rbind(expected, c('matrixcalc', '1.0-3')) expected <- rbind(expected, c('metafor', '2.0-0')) expected <- rbind(expected, c('methods', '3.3.3')) expected <- rbind(expected, c('mgcv', '1.8-17')) - expected <- rbind(expected, c('mgm', '1.2-1')) + expected <- rbind(expected, c('mgm', '1.2-2')) expected <- rbind(expected, c('mi', '1.0')) expected <- rbind(expected, c('mime', '0.5')) expected <- rbind(expected, c('minqa', '1.2.4')) expected <- rbind(expected, c('mitools', '2.3')) expected <- rbind(expected, c('mnormt', '1.5-5')) expected <- rbind(expected, c('modeltools', '0.2-21')) - expected <- rbind(expected, c('multcomp', '1.4-7')) + expected <- rbind(expected, c('multcomp', '1.4-8')) expected <- rbind(expected, c('munsell', '0.4.3')) expected <- rbind(expected, c('mvtnorm', '1.0-6')) expected <- rbind(expected, c('network', '1.13.0')) @@ -148,7 +149,7 @@ expected <- rbind(expected, c('pbivnorm', '0.6.0')) expected <- rbind(expected, c('pbkrtest', '0.4-7')) expected <- rbind(expected, c('pkgconfig', '2.0.1')) - expected <- rbind(expected, c('plotrix', '3.6-6')) + expected <- rbind(expected, c('plotrix', '3.7')) expected <- rbind(expected, c('plyr', '1.8.4')) expected <- rbind(expected, c('png', '0.1-7')) expected <- rbind(expected, c('ppls', '1.6-1')) @@ -156,15 +157,16 @@ expected <- rbind(expected, c('purrr', '0.2.4')) expected <- rbind(expected, c('qgraph', '1.4.4')) expected <- rbind(expected, c('quadprog', '1.5-5')) - expected <- rbind(expected, c('quantmod', '0.4-11')) + expected <- rbind(expected, c('quantmod', '0.4-12')) expected <- rbind(expected, c('quantreg', '5.34')) expected <- rbind(expected, c('qvcalc', '0.9-1')) expected <- rbind(expected, c('relaimpo', '2.2-2')) expected <- rbind(expected, c('relimp', '1.0-5')) expected <- rbind(expected, c('reshape2', '1.4.2')) expected <- rbind(expected, c('rjson', '0.2.15')) - expected <- rbind(expected, c('rlang', '0.1.2')) + expected <- rbind(expected, c('rlang', '0.1.4')) expected <- rbind(expected, c('rpart', '4.1-10')) + expected <- rbind(expected, c('rstudioapi', '0.7')) expected <- rbind(expected, c('sandwich', '2.4-0')) expected <- rbind(expected, c('scales', '0.5.0')) expected <- rbind(expected, c('sem', '3.1-9')) @@ -176,25 +178,25 @@ expected <- rbind(expected, c('statnet.common', '4.0.0')) expected <- rbind(expected, c('stats', '3.3.3')) expected <- rbind(expected, c('stats4', '3.3.3')) - expected <- rbind(expected, c('stringi', '1.1.5')) + expected <- rbind(expected, c('stringi', '1.1.6')) expected <- rbind(expected, c('stringr', '1.2.0')) expected <- rbind(expected, c('survey', '3.32-1')) expected <- rbind(expected, c('survival', '2.40-1')) expected <- rbind(expected, c('tcltk', '3.3.3')) expected <- rbind(expected, c('tibble', '1.3.4')) expected <- rbind(expected, c('tidyr', '0.7.2')) - expected <- rbind(expected, c('tidyselect', '0.2.2')) + expected <- rbind(expected, c('tidyselect', '0.2.3')) expected <- rbind(expected, c('tools', '3.3.3')) expected <- rbind(expected, c('tseries', '0.10-42')) expected <- rbind(expected, c('utils', '3.3.3')) - expected <- rbind(expected, c('vcd', '1.4-3')) + expected <- rbind(expected, c('vcd', '1.4-4')) expected <- rbind(expected, c('vcdExtra', '0.7-1')) expected <- rbind(expected, c('viridis', '0.4.0')) expected <- rbind(expected, c('viridisLite', '0.2.0')) expected <- rbind(expected, c('whisker', '0.3-2')) expected <- rbind(expected, c('xtable', '1.8-2')) expected <- rbind(expected, c('xts', '0.10-0')) - expected <- rbind(expected, c('yaml', '2.1.14')) + expected <- rbind(expected, c('yaml', '2.1.15')) expected <- rbind(expected, c('zoo', '1.8-0')) #--auto-generated diff --git a/JASP-Engine/JASP/R/principalcomponentanalysis.R b/JASP-Engine/JASP/R/principalcomponentanalysis.R index f05af6bcf2..245b5d1860 100644 --- a/JASP-Engine/JASP/R/principalcomponentanalysis.R +++ b/JASP-Engine/JASP/R/principalcomponentanalysis.R @@ -8,929 +8,839 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# along with this program. If not, see . # -.DotIfNULL <- function(x){ +PrincipalComponentAnalysis <- function(dataset = NULL, options, perform = "run", + callback = function(...) list(status="ok"), state = NULL, ...) { + return(mainFunctionPCAEFA(type = "pca", dataset = NULL, options, perform = "run", + callback = function(...) list(status="ok"), state = NULL, ...)) +} + +mainFunctionPCAEFA <- function(type, dataset = NULL, options, perform = "run", + callback = function(...) list(status="ok"), state = NULL, ...) { + ## call the common initialization function + init <- .initializePCAEFA(dataset, options, perform) + + results <- init[["results"]] + dataset <- init[["dataset"]] + + ## initialize result ## ---- + results[["title"]] = ifelse(type =="pca","Principal Component Analysis","Exploratory Factor Analysis") + meta <- list( + list(name="title", type="title"), + list(name="factorLoadings", type = "table"), + list(name="factorCorrelations", type = "table"), + list(name="goodnessOfFit", type="table"), + list(name="fitMeasures", type="table"), + list(name="pathDiagram", type="image"), + list(name="screePlot", type="image") + ) + results[[".meta"]] = meta + + ## initialize state ## ---- + stateKey <- list( + analysisResults = c( + 'rotationMethod', + 'orthogonalSelector', + 'obliqueSelector', + 'variables', + 'factorMethod', + 'eigenValuesBox', + 'numberOfFactors'), + pathDiagram = c( + 'rotationMethod', + 'orthogonalSelector', + 'obliqueSelector', + 'variables', + 'factorMethod', + 'eigenValuesBox', + 'numberOfFactors', + 'highlightSlider', + 'highlightText', + 'plotWidthPathDiagram', + 'plotHeightPathDiagram'), + screePlot = c( + 'rotationMethod', + 'orthogonalSelector', + 'obliqueSelector', + 'variables', + 'factorMethod', + 'eigenValuesBox', + 'numberOfFactors', + 'plotWidthScreePlot', + 'plotHeightScreePlot') + ) + + keep <- NULL + + if (is.null(state[["analysisResults"]])) { + state <- NULL + analysisResults <- NULL + + if (perform == "run" && !is.null(dataset) && nrow(dataset) > 1) { + customChecksPCAEFA <- list( + function(){ + if (length(options$variables) > 0 && options$numberOfFactors > length(options$variables)) { + return(paste0("Too many factors requested (", options$numberOfFactors, ") for the amount of included variables")) + } + }, + function(){ + if(nrow(dataset) < 3){ + return(paste0("Not enough valid cases (", nrow(dataset),") to run this analysis")) + } + }, + # check whether all row variance == 0 + function(){ + varianceZero <- 0 + for (i in 1:nrow(dataset)){ + if(sd(dataset[i,], na.rm = TRUE) == 0) varianceZero <- varianceZero + 1 + } + if(varianceZero == nrow(dataset)){ + return("Data not valid: variance is zero in each row") + } + }, + # check whether all variables correlates to each other + function(){ + allCorr <- 0 + nVar <- ncol(dataset) + for (i in 1:(nVar-1)) { + for (j in (i+1):nVar) { + thisCor <- cor(dataset[,i],dataset[,j]) + if(!is.na(thisCor) && thisCor == 1) allCorr <- allCorr + 1 + } + } + if(allCorr == nVar*(nVar-1)/2){ + return("Data not valid: all variables correlate with each other") + } + } + ) + error <- .hasErrors(dataset=dataset, perform=perform, type=c("infinity", "variance"), custom=customChecksPCAEFA, exitAnalysisIfErrors=TRUE) + analysisResults <- try(silent = FALSE, expr = { + .estimatePCAEFA(dataset, options, perform, type) + }) + } + + } else { + + analysisResults <- state[["analysisResults"]] + + } + # Output table + # Create fit measures tables: + results[["goodnessOfFit"]] <- .goodnessOfFit(analysisResults, options, perform) + # Create factor correlation table: + results[["factorLoadings"]] <- .getLoadings(analysisResults, dataset, options, perform, "pca") + + if (options$incl_correlations) { + results[["factorCorrelations"]] <- .getFactorCorrelations(analysisResults, options, perform, "pca") + } + + if (type == "efa" && options$incl_fitIndices) { + results[["fitMeasures"]] <- .fitMeasures(analysisResults, options, perform) + } + + # Output Plot + # Create path diagram: + if (isTRUE(options$incl_pathDiagram)) { + p <- try(silent = FALSE, expr = { + .pathDiagramPCAEFA(analysisResults, options, perform, type, oldPlot = state[["pathDiagram"]]) + }) + + if (isTryError(p)) { + errorMessage <- .extractErrorMessage(p) + results[["pathDiagram"]][["error"]] <- list(error="badData", errorMessage=errorMessage) + } else { + results[["pathDiagram"]] <- p + keep <- c(keep, results[["pathDiagram"]][["data"]]) + } + } + + # Scree plot: + if (isTRUE(options$incl_screePlot)) { + p <- try(silent = FALSE, expr = { + .screePlot(dataset, options, perform, oldPlot = state[["screePlot"]],"pca") + }) + + if (isTryError(p)) { + errorMessage <- .extractErrorMessage(p) + results[["screePlot"]][["error"]] <- list(error="badData", errorMessage=errorMessage) + } else { + results[["screePlot"]] <- p + keep <- c(keep, results[["screePlot"]][["data"]]) + } + } - if (is.null(x) || any(is.na(x)) || !is.finite(x)){ - return(".") - } else { - return(x) - } + #save state + state <- list( + options = options, + analysisResults = analysisResults, + pathDiagram = results[["pathDiagram"]], + screePlot = results[["screePlot"]] + ) + + attr(state, "key") <- stateKey + + + if (perform == "run") { + + return(list(results = results, status = "complete", state = state, keep = keep)) + + } else { + + return(list(results = results, status = "inited", state = state, keep = keep)) + + } } +.estimateNFactorPCAEFA <- function(dataset, options, perform, type){ + # Number of factors: + nVariable <- length(options$variables) + + # get nFactor + nFactor <- 1 + message <- NULL + + if(perform == "run" && !is.null(dataset) && nrow(dataset)>1 && nVariable > 0) { + + if (options$factorMethod == "parallelAnalysis") { + + parallelAnalysis <- try(silent = FALSE, expr = { + pa <- .suppressPlotFA(dataset) + }) + + if (isTryError(parallelAnalysis)) { + nFactor <- 1 + } else { + if (type == "pca") { + if (is.na(pa$ncomp)) pa$ncomp <- 1 + nFactor <- max(1,pa$ncomp) + } else { + if (is.na(pa$nfact)) pa$nfact <- 1 + nFactor <- max(1,pa$nfact) + } + } + + } else if (options$factorMethod == "eigenValues") { + # Compute ev: + eigenValues <- try(silent = FALSE, expr = { + pa <- .suppressPlotFA(dataset) + }) + if (isTryError(eigenValues)) { + nFactor <- 1 + } else { + if (type == "pca") { + nFactor <- sum(pa$pc.values > options$eigenValuesBox) + } else { + nFactor <- sum(pa$fa.values > options$eigenValuesBox) + } + } + } else if (options$factorMethod == "manual"){ + nFactor <- options$numberOfFactors + } + } + + return(list(nFactor = nFactor, message = NULL)) -PrincipalComponentAnalysis <- function(dataset = NULL, options, perform = "run", - callback = function(...) 0, ...) { - - - ## call the common initialization function - init <- .initializePCA(dataset, options, perform) - - - results <- init[["results"]] - dataset <- init[["dataset"]] - - # States: - state <- .retrieveState() - analysisResults <- NULL - newAnalysis <- TRUE - # if ( ! is.null(state) && state$complete) { # is there state? - - if ( !is.null(state)) { # is there state? - - diff <- .diff(options, state$options) # compare old and new options - - nVariable <- length(options$variables) - - if (is.list(diff) && !diff[['rotationMethod']] && !diff[['orthogonalSelector']] && !diff[['obliqueSelector']] && !diff[['variables']] && !diff[['factorMethod']] && - !diff[['eigenValuesBox']] && !diff[['numberOfFactors']]) { - - # old results can be used - newAnalysis <- FALSE - analysisResults <- state$analysisResults - - } - - } - - - # Number of factors: - nVariable <- length(options$variables) - - # Rotation method: - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - - # Number of factors: - - if (options$factorMethod == "parallelAnalysis"){ - - if (nrow(dataset)>0 && nVariable > 0){ - image <- .beginSaveImage() - pa <- psych::fa.parallel(dataset) - .endSaveImage(image) - if (is.na(pa$ncomp)) pa$ncomp <- 1 - nFactor <- max(1,pa$ncomp) - - } else { - if (is.null(state$nFactor)){ - nFactor <- 1 - } else { - nFactor <- state$nFactor - } - } - - } else if (options$factorMethod == "eigenValues"){ - if (nrow(dataset)>0 && nVariable > 0){ - # Compute ev: - image <- .beginSaveImage() - pa <- psych::fa.parallel(dataset) - .endSaveImage(image) - - # Number of factors: - nFactor <- sum(pa$pc.values > options$eigenValuesBox) - } else { - if (is.null(state$nFactor)){ - nFactor <- 1 - } else { - nFactor <- state$nFactor - } - - } - } else if (options$factorMethod == "manual"){ - nFactor <- options$numberOfFactors - } - - # Check if number of factors is correct: - if (length(options$variables) > 0 && nFactor > length(options$variables)){ - error <- TRUE - errorMessage <- "Too many factors requested" - } else { - error <- FALSE - errorMessage <- "" - } - - - - if (perform == "run" && nrow(dataset) > 0 && is.null(analysisResults) && length(options$variables) > 1 && !error){ - - analysisResults <- .estimatePCA(dataset, options, perform,nFactor) - - } else { - # Otherwise just keep the state - # analysisResults <- NULL - } - - # Make factor loadings table: - # if (newAnalysis){ - results[["factorLoadings"]] <- .getLoadingsPCA(analysisResults, options,perform,nFactor,dataset) -# } else { -# results[["factorLoadings"]] <- state$results[["factorLoadings"]] -# } - - - # Create factor correlation table: - # if (newAnalysis || (is.list(diff) && diff[['incl_correlations']] && options$incl_correlations)){ - results[["factorCorrelations"]] <- .getFactorCorrelationsPCA(analysisResults, options,perform) -# } else { -# results[["factorCorrelations"]] <- state$results[["factorCorrelations"]] -# } - - - # Create fit measures tables: - results[["goodnessOfFit"]] <- .goodnessOfFitPCA(analysisResults, options,perform) - results[["fitMeasures"]] <- .fitMeasuresPCA(analysisResults, options,perform) - - # Create path diagram: - results[["pathDiagram"]] <- .pathDiagramPCA(analysisResults, options,perform) - - # Scree plot: - results[["screePlot"]] <- .screePlot(dataset, options,perform) - - ## TEMP DEBUG THING: - # save(dataset,results,init,options,perform,callback,...,file = "/Users/sachaepskamp/Dropbox/work/JASP/Rcodes/JASPinit.RData") - - - #### META - meta <- list( - list(name = "title", type = "title") - ) - - if (isTRUE(options$incl_loadings)){ - meta[[length(meta)+1]] <- list(name = "factorLoadings", type = "table") - - } - - if (isTRUE(options$incl_correlations)){ - meta[[length(meta)+1]] <- list(name = "factorCorrelations", type = "table") - } - - if (isTRUE(options$incl_GoF)){ - meta[[length(meta)+1]] <- list(name = "goodnessOfFit", type = "table") - } - if (isTRUE(options$incl_fitIndices)){ - meta[[length(meta)+1]] <- list(name = "fitMeasures", type = "table") - } - if (isTRUE(options$incl_pathDiagram)){ - meta[[length(meta)+1]] <- list(name = "pathDiagram", type = "image") - } - if (isTRUE(options$incl_screePlot)){ - meta[[length(meta)+1]] <- list(name = "screePlot", type = "image") - } - - - - results[[".meta"]] <- meta - - # Dummies: - status <- list(ready=TRUE, error=error,errorMessage=errorMessage) - - if (status$error == TRUE){ - results[["factorLoadings"]][["error"]] <- list(errorType="badData", errorMessage=status$errorMessage) - results[["factorCorrelations"]][["error"]] <- list(errorType="badData") - results[["goodnessOfFit"]][["error"]] <- list(errorType="badData") - results[["fitMeasures"]][["error"]] <- list(errorType="badData") - results[["pathDiagram"]][["error"]] <- list(errorType="badData") - results[["screePlot"]][["error"]] <- list(errorType="badData") - } else { - results[["factorLoadings"]][["error"]] <- NULL - results[["factorCorrelations"]][["error"]] <- NULL - results[["goodnessOfFit"]][["error"]] <- NULL - results[["fitMeasures"]][["error"]] <- NULL - results[["pathDiagram"]][["error"]] <- NULL - results[["screePlot"]][["error"]] <- NULL - } - - if (perform == "run" && status$ready) { - state <- list(options=options,analysisResults=analysisResults,nFactor=nFactor,results=results,complete=TRUE) - - return(list(results=results, status="complete", state=state)) - - - } else { - state <- list(options=options,nFactor=nFactor,analysisResults=analysisResults,results=results,complete=FALSE) - return(list(results=results, status="inited",state=state)) - } } + ### Inner functions ### # Estimate PCA: -.estimatePCA <- function(dataset, options, perform, nFactor=1) { - - nVariable <- length(options$variables) - - # Rotation method: - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - - # # Number of factors: - # if (options$factorMethod == "eigenValues"){ - # # Covariance matrix: - # corMatrix <- cor(dataset, use = "pairwise.complete.obs") ### ADD MISSING OPTION - # - # # Eigenvalues: - # EV <- eigen(corMatrix,only.values = TRUE)$values - # - # # Number of factors: - # nFactor <- sum(EV > options$eigenValuesBox) - # } else if (options$factorMethod == "manual"){ - # nFactor <- options$numberOfFactors - # } - - if (nFactor == 0) stop("Number of factors must be > 0") - if (nFactor > nVariable){ - stop("Too many factors requested") - } - - Results <- psych::principal(dataset,nFactor, rotate = Rotation) - # Results <- factanal(dataset, nFactor, rotation = Rotation) - - return(Results) +.estimatePCAEFA <- function(dataset, options, perform, type) { + + if (options$rotationMethod == "orthogonal") { + Rotation <- options$orthogonalSelector + } else { + Rotation <- options$obliqueSelector + } + + res <- .estimateNFactorPCAEFA(dataset, options, perform, type) + nFactor <- res$nFactor + message <- res$message + + if (type == "pca") { + Results <- psych::principal(dataset, nFactor, rotate = Rotation) + } else { + Results <- psych::fa(dataset, nFactor, rotate = Rotation) + } + + return(list(Results = Results, nFactor = nFactor, message = message)) + } # Get loadings matrix: -.getLoadingsPCA <- function(analysisResults, options,perform, nFactor=1,dataset){ - - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - # Extract loadings: - # if (!is.null(analysisResults) & perform == "run"){ - if (!is.null(analysisResults)){ - - loadingsMatrix <- as.matrix(loadings(analysisResults)) - # loadingsMatrix <- matrix(unlist(loadingsMatrix),nrow(loadingsMatrix),ncol(loadingsMatrix)) - - - # loadingsMatrix <- matrix(1,12,1) - - - if (ncol(loadingsMatrix) > 0){ - colnames(loadingsMatrix) <- paste(ifelse(Rotation=="none","PC","RC"),seq_len(ncol(loadingsMatrix))) - } - - # Add uniqueness: - - loadingsMatrix <- cbind(loadingsMatrix, Uniqueness = unname(analysisResults$uniquenesses)) - - } else { - - if (is.null(options$numberOfFactors)){ - nFact <- 0 - } else { - nFact <- options$numberOfFactors - } - - loadingsMatrix <- matrix(NA,length(options$variables),nFactor+1) - - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - colnames(loadingsMatrix) <- c( paste(ifelse(Rotation=="none","PC","RC"),seq_len(nFactor)),"Uniqueness") - rownames(loadingsMatrix) <- colnames(dataset) - - } - - # Create JASP table: - Loadings <- list() - Loadings[["title"]] <- "Component Loadings" - Loadings[["schema"]] <- list(fields = list( - # list(name="model", title = "", type="text"), - # list(name="cn_05", title = "Hoelter Critical N (CN) alpha=0.05", type="number", format = "dp:3"), - # list(name="cn_01", title = "Hoelter Critical N (CN) alpha=0.01", type="number", format = "dp:3"), - # list(name="gfi", title = "Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="agfi", title = "Parsimony Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="mfi", title = "McDonald Fit Index (MFI)", type="number", format = "dp:3"), - # list(name="ecvi", title = "Expected Cross-Validation Index (ECVI)", type="number", format = "dp:3") - )) - - # Add columns: - Loadings[["schema"]][["fields"]][[1]] <- list(name = "VAR", title = "", type="string") - - for (j in seq_len(ncol(loadingsMatrix))){ - Loadings[["schema"]][["fields"]][[j+1]] <- list(name = colnames(loadingsMatrix)[j], title = colnames(loadingsMatrix)[j], type="number", format = "dp:3") - } - - Loadings[["data"]] <- list() - - # Add rows: - if (nrow(loadingsMatrix)==0){ - Loadings[["data"]][[1]] <- as.list(rep(".",ncol(loadingsMatrix)+1)) - } - - for (i in seq_len(nrow(loadingsMatrix))){ - - dat <- loadingsMatrix[i,] - - Loadings[["data"]][[i]] <- list(VAR = .unv(rownames(loadingsMatrix)[i])) - for (j in seq_along(dat)){ - if (is.na(dat[j])){ - Loadings[["data"]][[i]][[j+1]] <- "." - } else { - Loadings[["data"]][[i]][[j+1]] <- unname(ifelse(abs(dat[j]) < options$highlightText & j != length(dat),".",dat[j])) - } - - } - - names( Loadings[["data"]][[i]]) <- sapply(Loadings[["schema"]][["fields"]],"[[",'name') - } - - return(Loadings) +.getLoadings <- function(analysisResults, dataset, options, perform, type){ + + # Create JASP table: + Loadings <- list() + Loadings[["title"]] <- "Component Loadings" + Loadings[["schema"]] <- list(fields = list()) + + if (options$rotationMethod == "orthogonal") { + Rotation <- options$orthogonalSelector + } else { + Rotation <- options$obliqueSelector + } + + if (type == "pca") { + colName = ifelse(Rotation=="none","PC","RC") + } + + if (type == "efa") { + colName = "Factor" + } + + footnotes <- .newFootnotes() + # Extract loadings: + if (is.null(analysisResults) || isTryError(analysisResults)) { + if (is.null(options$numberOfFactors)){ + nFactor <- 0 + } else { + nFactor <- options$numberOfFactors + } + + loadingsMatrix <- matrix(NA,length(options$variables),nFactor+1) + + colnames(loadingsMatrix) <- c( paste(colName,seq_len(nFactor)),"Uniqueness") + rownames(loadingsMatrix) <- colnames(dataset) + + } else { + + message <- analysisResults$message + .addFootnote(footnotes, symbol = "", text = message) + + analysisResults <- analysisResults$Results + loadingsMatrix <- as.matrix(loadings(analysisResults)) + + if (ncol(loadingsMatrix) > 0) { + colnames(loadingsMatrix) <- paste(colName,seq_len(ncol(loadingsMatrix))) + } + + # Add uniqueness: + loadingsMatrix <- cbind(loadingsMatrix, Uniqueness = unname(analysisResults$uniquenesses)) + } + + # Add columns: + Loadings[["schema"]][["fields"]][[1]] <- list(name = "VAR", title = "", type="string") + + for (j in seq_len(ncol(loadingsMatrix))) { + Loadings[["schema"]][["fields"]][[j+1]] <- list(name = colnames(loadingsMatrix)[j], title = colnames(loadingsMatrix)[j], type="number", format = "dp:3") + } + + Loadings[["data"]] <- list() + + # Add rows: + if (nrow(loadingsMatrix)==0) { + Loadings[["data"]][[1]] <- as.list(rep(".",ncol(loadingsMatrix)+1)) + } + + for (i in seq_len(nrow(loadingsMatrix))) { + + dat <- loadingsMatrix[i,] + + Loadings[["data"]][[i]] <- list(VAR = .unv(rownames(loadingsMatrix)[i])) + + for (j in seq_along(dat)) { + if (is.na(dat[j])) { + Loadings[["data"]][[i]][[j+1]] <- "." + } else { + Loadings[["data"]][[i]][[j+1]] <- unname(ifelse(abs(dat[j]) < options$highlightText & j != length(dat),".",dat[j])) + } + } + names( Loadings[["data"]][[i]]) <- sapply(Loadings[["schema"]][["fields"]],"[[",'name') + } + return(Loadings) } # Init: -.initializePCA <- function(dataset, options, perform) { - - groups <- options$groupingVariable - depvars <- unlist(options$variables) - - - if (!is.null(groups) && groups == "") groups <- NULL - - if (is.null(dataset)) { - ## if we are ready to run, read in the dataset - if (perform == "run" && length(options$variables) > 1) { - # - # if (options$missingValues == "excludeListwise") { - # exclude <- depvars - # } else { - # exclude <- NULL - # } - # - dataset <- .readDataSetToEnd(columns.as.numeric = depvars, - columns.as.factor = groups) - - ## else just read in the headers (and create an empty table) - } else { - dataset <- .readDataSetHeader(columns.as.numeric = depvars, - columns.as.factor = groups) - } - } - - ## this is the main object; we add stuff to it and return it - results <- list( - "title" = "Principal Component Analysis", - "citation" = list("Revelle, W. (2015) psych: Procedures for Personality and Psychological Research, Northwestern University, - Evanston, Illinois, USA, http://CRAN.R-project.org/package=psych Version = 1.5.8.") - ) - - #### META - # meta <- list() - # meta[[1]] <- list(name = "title", type = "title") - # meta[[2]] <- list(name = "ttest", type = "table") - # meta[[3]] <- list(name="assumptionChecks", type="object", meta=list(list(name="shapiroWilk", type="table"), list(name="levene", type="table"))) - # meta[[4]] <- list(name="descriptives", type="object", meta=list(list(name="descriptivesTable", type="table"), list(name = "descriptivesPlots", type = "collection", meta="image"))) - # - # results[[".meta"]] <- meta - list("results" = results, "dataset" = dataset) +.initializePCAEFA <- function(dataset, options, perform) { + + groups <- options$groupingVariable + depvars <- unlist(options$variables) + depvars <- depvars[depvars != ""] + + + if (!is.null(groups) && groups == "") groups <- NULL + + if (is.null(dataset)) { + ## if we are ready to run, read in the dataset + if (perform == "run" && length(options$variables) > 1) { + + dataset <- .readDataSetToEnd(columns.as.numeric = depvars, columns.as.factor = groups, exclude.na.listwise = c(depvars, groups)) + } else { + dataset <- .readDataSetHeader(columns.as.numeric = depvars, columns.as.factor = groups) + } + } + + ## this is the main object; we add stuff to it and return it + results <- list( + "citation" = list("Revelle, W. (2015) psych: Procedures for Personality and Psychological Research, Northwestern University, + Evanston, Illinois, USA, http://CRAN.R-project.org/package=psych Version = 1.5.8.") + ) + + list("results" = results, "dataset" = dataset) } # Path diagram: -.pathDiagramPCA <- function(analysisResults, options, perform){ - - pathDiagram <- list() - pathDiagram$title <- "Path Diagram" - pathDiagram$width <- options$plotWidthPathDiagram - pathDiagram$height <- options$plotHeightPathDiagram - if (pathDiagram$height==0){ - pathDiagram$height <- 1 + 299 * (length(options$variables)/5) - } - pathDiagram$custom <- list(width="plotWidthPathDiagram", height="plotHeightPathDiagram") - - - # filename <- .requestTempFileNameNative("svg") - # grDevices::svg(filename=filename, width=width/72, height=height/72, bg="transparent") - # - # relativePath <- filename$relativePath - # base::Encoding(filename) <- "UTF-8" - # - - # if (perform != "run" | is.null(analysisResults) | !isTRUE(options$incl_pathDiagram)){ - - if (is.null(analysisResults) || !isTRUE(options$incl_pathDiagram) || perform == "init"){ - - pathDiagram$data <- NULL - - } else { - - - # image <- .beginSaveImage(pathDiagram$width,pathDiagram$height) -# Lambda <- loadings(analysisResults) -# labels <- .unv(rownames(Lambda)) -# Lambda <- matrix(c(Lambda),nrow(Lambda),ncol(Lambda)) -# Theta <- analysisResults$uniquenesses -# Psi <- analysisResults$r.scores -# -# qgraph::qgraph.loadings(Lambda, factorCors = Psi, resid = Theta,model="reflective", -# cut = options$highlightText, residSize = 0.25,labels = -# labels) -# - - # Via qgraph: - # Model matrices: - LY <- as.matrix(loadings(analysisResults)) - TE <- diag(analysisResults$uniqueness) - PS <- analysisResults$r.scores - - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - - # Variable names: - labels <- .unv(rownames(LY)) - factors <- paste0(ifelse(Rotation == "none", "PC", "RC"),seq_len(ncol(LY))) - - # Number of variables: - nFactor <- length(factors) - nIndicator <- length(labels) - nTotal <- nFactor + nIndicator - - # Make layout: - # For each manifest, find strongest loading: - strongest <- apply(abs(LY),1,which.max) - ord <- order(strongest) - - # Reshuffle labels and LY: - labels <- labels[ord] - LY <- LY[ord,] - - # Edgelist: - # Factor loadings - E_loadings <- data.frame(from = rep(labels,times=nFactor), to = rep(factors,each=nIndicator) ,weight=c(LY), - stringsAsFactors = FALSE) - - # Residuals: - E_resid <- data.frame(from=labels,to=labels,weight=diag(TE)) - E_resid$weight <- 0 - - # Factor correlations: - E_cor <- data.frame(from = c(factors[col(PS)]), to = c(factors[row(PS)]),weight=c(PS), - stringsAsFactors = FALSE) - E_cor <- E_cor[E_cor$from != E_cor$to,] - - # Total: - E <- rbind(E_loadings,E_resid,E_cor) - - # Make the layout: - sq <- function(x){ - seq(-1,1,length.out = x+2)[-c(1,x+2)] - } - - L <- cbind( - c(rep(-1,nFactor),rep(1,nIndicator)), - c(sq(nFactor),sq(nIndicator)) - ) - - # Compute curvature of correlations: - # Numeric edgelist: - E_cor_numeric <- cbind(match(E_cor$from,factors),match(E_cor$to,factors)) - - # Compute distance: - dist <- abs(L[E_cor_numeric[,1],2] - L[E_cor_numeric[,2],2]) - - - - # Max has curvature of 8! - # Min has curvature of 4! - - min <- 2 - max <- 8 - # Scale to max: - dist <- min + dist/(max(dist))*(max - min) - if (length(unique(dist))==1){ - dist[] <- mean(c(max,min)) - } - - # Scale such that this is true when nfactor = 2 and nIndicator == 5: - # dist <- dist/((nFactor/2)*(nIndicator/2)) - - # Scale to plot width: - Scale <- sqrt(pathDiagram$width^2 + pathDiagram$height^2)/sqrt(480^2 + 300^2) - dist <- 1/Scale * dist -# - - # Curvature: - curve <- c(rep(0,nrow(E_loadings)), - rep(0,nrow(E_resid)), - dist) - - # Edge connectpoints: - ECP <- matrix(NA,nrow(E),2) - ECP[nrow(E_loadings) + nrow(E_resid) + seq_len(nrow(E_cor)),1:2] <- 1.5*pi - ECP[seq_len(nrow(E_loadings)),1] <- 1.5*pi - - - # Loop rotation: - loopRotation <- 0.5*pi - - # bidirectional: - bidir <- c(rep(FALSE,nrow(E_loadings) + nrow(E_resid)), rep(TRUE, nrow(E_cor))) - - # Shape: - shape <- c(rep("circle",nFactor), rep("rectangle",nIndicator)) - - - - # Just some observations: - # 10 indicators, height of 6 works well - # 50 indicators, height of 1 works well - # Good function: exp(2.25 - 0.05 * nIndicator) - # OIther idea: keep size constant, just increase plot size in JASP! - - # Size: - size1 <- c( - rep(12,nFactor), - rep(30,nIndicator) - ) - size2 <- c( - rep(12,nFactor), - rep( 7,nIndicator) - ) - - # Plot: - label.scale.equal <- c(rep(1,nFactor),rep(2,nIndicator)) - - .plotFunc <- function() { - # Run once without plotting to obtain the scaled label sizes: - qgraph::qgraph(E, layout = L, directed=TRUE, bidirectional=bidir, residuals = TRUE, residScale = 10, - labels = c(factors,labels), curve = curve, curveScale = FALSE, edgeConnectPoints = ECP, - loopRotation=loopRotation, shape = shape, vsize = size1, vsize2 = size2,label.scale.equal=label.scale.equal, - residScale = 2, mar = c(5,10,5,12), normalize = FALSE, label.fill.vertical = 0.75, cut = options$highlightText, - bg = "transparent" - ) - } - - content <- .writeImage(width = pathDiagram$width, height = pathDiagram$height, plot = .plotFunc, obj = TRUE) - pathDiagram[["convertible"]] <- TRUE - pathDiagram[["obj"]] <- content[["obj"]] - pathDiagram[["data"]] <- content[["png"]] - - - # pathDiagram$data <- .endSaveImage(image) - pathDiagram$status <- "complete" - - } - - - - # grDevices::dev.off() - - return(pathDiagram) +.pathDiagramPCAEFA <- function(analysisResults, options, perform, type, oldPlot=NULL){ + + if (!is.null(oldPlot) && !identical(oldPlot[["data"]], "")) { + return(oldPlot) + } + + pathDiagram <- list() + pathDiagram$title <- "Path Diagram" + + if (options$rotationMethod == "orthogonal") { + Rotation <- options$orthogonalSelector + } else { + Rotation <- options$obliqueSelector + } + + xName <- ifelse(Rotation == "none", "PC", "RC") + + pathDiagram$width <- options$plotWidthPathDiagram + pathDiagram$height <- options$plotHeightPathDiagram + if (pathDiagram$height==0) { + pathDiagram$height <- 1 + 299 * (length(options$variables)/5) + } + pathDiagram$custom <- list(width="plotWidthPathDiagram", height="plotHeightPathDiagram") + + if (is.null(analysisResults) || isTryError(analysisResults)) { + + pathDiagram$data <- NULL + + } else { + + analysisResults <- analysisResults$Results + + LY <- as.matrix(loadings(analysisResults)) + TE <- diag(analysisResults$uniqueness) + PS <- analysisResults$r.scores + + # Variable names: + labels <- .unv(rownames(LY)) + if (type == "pca") { + factors <- paste0(xName,seq_len(ncol(LY))) + } else { + factors <- paste0("F",seq_len(ncol(LY))) + } + + # Number of variables: + nFactor <- length(factors) + nIndicator <- length(labels) + nTotal <- nFactor + nIndicator + + # Make layout: + # For each manifest, find strongest loading: + strongest <- apply(abs(LY),1,which.max) + ord <- order(strongest) + + # Reshuffle labels and LY: + labels <- labels[ord] + LY <- LY[ord,] + + # Edgelist: + # Factor loadings + if (type == "pca") { + E_loadings <- data.frame(from = rep(labels,times=nFactor), to = rep(factors,each=nIndicator) ,weight=c(LY), + stringsAsFactors = FALSE) + } else { + E_loadings <- data.frame(from = rep(factors,each=nIndicator), to = rep(labels,times=nFactor),weight=c(LY), + stringsAsFactors = FALSE) + } + + # Residuals: + E_resid <- data.frame(from=labels,to=labels,weight=diag(TE)) + E_resid$weight <- 0 + + # Factor correlations: + E_cor <- data.frame(from = c(factors[col(PS)]), to = c(factors[row(PS)]),weight=c(PS), + stringsAsFactors = FALSE) + E_cor <- E_cor[E_cor$from != E_cor$to,] + + # Total: + E <- rbind(E_loadings,E_resid,E_cor) + + # Make the layout: + sq <- function(x){ + seq(-1,1,length.out = x+2)[-c(1,x+2)] + } + + L <- cbind( + c(rep(-1,nFactor),rep(1,nIndicator)), + c(sq(nFactor),sq(nIndicator)) + ) + + # Compute curvature of correlations: + # Numeric edgelist: + E_cor_numeric <- cbind(match(E_cor$from,factors),match(E_cor$to,factors)) + + # Compute distance: + dist <- abs(L[E_cor_numeric[,1],2] - L[E_cor_numeric[,2],2]) + + min <- 2 + max <- 8 + # Scale to max: + dist <- min + dist/(max(dist))*(max - min) + if (length(unique(dist))==1){ + dist[] <- mean(c(max,min)) + } + + # Scale to plot width: + Scale <- sqrt(pathDiagram$width^2 + pathDiagram$height^2)/sqrt(480^2 + 300^2) + dist <- 1/Scale * dist + + # Curvature: + curve <- c(rep(0,nrow(E_loadings)), + rep(0,nrow(E_resid)), + dist) + + # Edge connectpoints: + ECP <- matrix(NA,nrow(E),2) + ECP[nrow(E_loadings) + nrow(E_resid) + seq_len(nrow(E_cor)),1:2] <- 1.5*pi + if (type == "pca") { + ECP[seq_len(nrow(E_loadings)),1] <- 1.5*pi + } else { + ECP[seq_len(nrow(E_loadings)),2] <- 1.5*pi + } + + # Loop rotation: + loopRotation <- 0.5*pi + + # bidirectional: + bidir <- c(rep(FALSE,nrow(E_loadings) + nrow(E_resid)), rep(TRUE, nrow(E_cor))) + + # Shape: + shape <- c(rep("circle",nFactor), rep("rectangle",nIndicator)) + + # Size: + size1 <- c( + rep(12,nFactor), + rep(30,nIndicator) + ) + size2 <- c( + rep(12,nFactor), + rep( 7,nIndicator) + ) + + # Plot: + label.scale.equal <- c(rep(1,nFactor),rep(2,nIndicator)) + + # Run once without plotting to obtain the scaled label sizes: + .plotFunc <- function(){ + qgraph::qgraph(E, layout = L, directed=TRUE, bidirectional=bidir, residuals = TRUE, residScale = 10, + labels = c(factors,labels), curve = curve, curveScale = FALSE, edgeConnectPoints = ECP, + loopRotation=loopRotation, shape = shape, vsize = size1, vsize2 = size2,label.scale.equal=label.scale.equal, + residScale = 2, mar = c(5,10,5,12), normalize = FALSE, label.fill.vertical = 0.75, cut = options$highlightText, + bg = "transparent" + ) + } + + content <- .writeImage(width = pathDiagram$width, + height = pathDiagram$height, plot = .plotFunc, obj = TRUE) + pathDiagram[["convertible"]] <- TRUE + pathDiagram[["obj"]] <- content[["obj"]] + pathDiagram[["data"]] <- content[["png"]] + pathDiagram[["status"]] <- "complete" + + } + + return(pathDiagram) + } # Factor correlations: -.getFactorCorrelationsPCA <- function(analysisResults, options,perform){ - - # Extract loadings: - if (!is.null(analysisResults)){ - - corMatrix <- as.matrix(analysisResults$r.scores) - # loadingsMatrix <- matrix(unlist(loadingsMatrix),nrow(loadingsMatrix),ncol(loadingsMatrix)) - - - # loadingsMatrix <- matrix(1,12,1) - - } else { - - if (is.null(options$numberOfFactors)){ - nFact <- 0 - } else { - nFact <- options$numberOfFactors - } - - corMatrix <- matrix(,0,0) - - } - - - if (options$rotationMethod == "orthogonal"){ - Rotation <- options$orthogonalSelector - } else { - Rotation <- options$obliqueSelector - } - - if (ncol(corMatrix) > 0){ - colnames(corMatrix) <- rownames(corMatrix) <- paste(ifelse(Rotation == "none","PC","RC"),seq_len(ncol(corMatrix))) - } - - # Create JASP table: - FactorCorrelations <- list() - FactorCorrelations[["title"]] <- "Component Correlations" - FactorCorrelations[["schema"]] <- list(fields = list( - # list(name="model", title = "", type="text"), - # list(name="cn_05", title = "Hoelter Critical N (CN) alpha=0.05", type="number", format = "dp:3"), - # list(name="cn_01", title = "Hoelter Critical N (CN) alpha=0.01", type="number", format = "dp:3"), - # list(name="gfi", title = "Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="agfi", title = "Parsimony Goodness of Fit Index (GFI)", type="number", format = "dp:3"), - # list(name="mfi", title = "McDonald Fit Index (MFI)", type="number", format = "dp:3"), - # list(name="ecvi", title = "Expected Cross-Validation Index (ECVI)", type="number", format = "dp:3") - )) - - # Add columns: - FactorCorrelations[["schema"]][["fields"]][[1]] <- list(name = "VAR", title = "", type="string") - - for (j in seq_len(ncol(corMatrix))){ - FactorCorrelations[["schema"]][["fields"]][[j+1]] <- list(name = colnames(corMatrix)[j], title = colnames(corMatrix)[j], type="number", format = "dp:3") - } - - FactorCorrelations[["data"]] <- list() - - # Add rows: - for (i in seq_len(nrow(corMatrix))){ - - dat <- corMatrix[i,] - FactorCorrelations[["data"]][[i]] <- list(VAR = rownames(corMatrix)[i]) - for (j in 1:i){ - FactorCorrelations[["data"]][[i]][[j+1]] <- unname(dat[j]) - } - - names(FactorCorrelations[["data"]][[i]]) <- sapply(FactorCorrelations[["schema"]][["fields"]],"[[",'name')[seq_along(FactorCorrelations[["data"]][[i]])] - } - - return(FactorCorrelations) +.getFactorCorrelations <- function(analysisResults, options, perform, type){ + + # Create JASP table: + FactorCorrelations <- list() + FactorCorrelations[["title"]] <- ifelse(type == "pca","Component Correlations", "Factor Correlations") + + # Extract loadings + if (is.null(analysisResults) || isTryError(analysisResults)) {#|| perform == "init" + if (is.null(options$numberOfFactors)) { + nFact <- 0 + } else { + nFact <- options$numberOfFactors + } + + corMatrix <- matrix(,0,0) + + } else { + + analysisResults <- analysisResults$Results + corMatrix <- as.matrix(analysisResults$r.scores) + + } + + if (options$rotationMethod == "orthogonal") { + Rotation <- options$orthogonalSelector + } else { + Rotation <- options$obliqueSelector + } + + xName = ifelse(type == "pca",ifelse(Rotation == "none","PC","RC"), "Factor") + + if (ncol(corMatrix) > 0) { + colnames(corMatrix) <- rownames(corMatrix) <- paste(xName,seq_len(ncol(corMatrix))) + } + + + # Add columns: + FactorCorrelations[["schema"]] <- list(fields = list()) + FactorCorrelations[["schema"]][["fields"]][[1]] <- list(name = "VAR", title = "", type="string") + + for (j in seq_len(ncol(corMatrix))) { + FactorCorrelations[["schema"]][["fields"]][[j+1]] <- list(name = colnames(corMatrix)[j], title = colnames(corMatrix)[j], type="number", format = "dp:3") + } + + FactorCorrelations[["data"]] <- list() + + # Add rows: + for (i in seq_len(nrow(corMatrix))) { + + dat <- corMatrix[i,] + FactorCorrelations[["data"]][[i]] <- list(VAR = rownames(corMatrix)[i]) + for (j in 1:i) { + FactorCorrelations[["data"]][[i]][[j+1]] <- unname(dat[j]) + } + + names(FactorCorrelations[["data"]][[i]]) <- sapply(FactorCorrelations[["schema"]][["fields"]],"[[",'name')[seq_along(FactorCorrelations[["data"]][[i]])] + } + + return(FactorCorrelations) +} + + +# for number, this function switch NA, Inf and null to "." in tables +.DotIfNULLPCAEFA <- function(x){ + + if (is.null(x) || is.na(x) || !is.finite(x)) { + return(".") + } else { + return(x) + } } + # Goodness of fit -.goodnessOfFitPCA <- function(analysisResults, options,perform){ - - # Extract loadings: - if (!is.null(analysisResults)){ - -# print(analysisResults) -# print(analysisResults$RMSEA) -# -# Fits <- list( -# CHI = analysisResults$STATISTIC, -# PVAL = analysisResults$PVAL, -# DF = analysisResults$dof, -# RMSEA = analysisResults$RMSEA['RMSEA'], -# RMSEAlower = analysisResults$RMSEA['lower'], -# RMSEAupper = analysisResults$RMSEA['upper'], -# TLI = analysisResults$TLI, -# RMS = analysisResults$rms, -# CRMS = analysisResults$crms, -# BIC = analysisResults$BIC -# ) - - - Fits <- list( - CHI = .DotIfNULL(analysisResults$STATISTIC), - PVAL = .DotIfNULL(analysisResults$PVAL), - DF = .DotIfNULL(analysisResults$dof) - # RMS = .DotIfNULL(analysisResults$rms) -# RMSEA = .DotIfNULL(unname(analysisResults$RMSEA['RMSEA'])), -# RMSEAlower = .DotIfNULL(unname(analysisResults$RMSEA['lower'])), -# RMSEAupper = .DotIfNULL(unname(analysisResults$RMSEA['upper'])), -# TLI = .DotIfNULL(analysisResults$TLI), -# RMS = .DotIfNULL(analysisResults$rms), -# CRMS = .DotIfNULL(analysisResults$crms), -# BIC = .DotIfNULL(analysisResults$BIC) - ) - - } else { - - Fits <- list( - CHI = ".", - PVAL = ".", - DF = "." - # RMS = "." -# RMSEA = ".", -# RMSEAlower = ".", -# RMSEAupper = ".", -# TLI = ".", -# RMS = ".", -# CRMS = ".", -# BIC = "." - ) - - } - - print(analysisResults$rms) - - # Create JASP table: - goodnessOfFit <- list() - goodnessOfFit[["title"]] <- "Chi-squared Test" - - # Create the columns: - goodnessOfFit[["schema"]] <- list(fields = list( - list(name = "model", title="", type = "string"), - list(name = "chisq", title = "Value", type="number", format = "dp:3"), - list(name = "df", title = "df", type="integer"), - list(name = "p", title = "p", type="number", format = "dp:3;p:.001") - # list(name = "RMS", title = "RMS", type="number", format = "dp:3") - )) - - # Create and fill the row(s): - goodnessOfFit[["data"]] <- list( - list( - model = "Model", - chisq = ifelse(Fits$DF>0,Fits$CHI,"."), - df = ifelse(Fits$DF>0,Fits$DF,"."), - p = ifelse(Fits$DF>0,Fits$PVAL,".") - # RMS = Fits$RMS - ) - ) - - - return(goodnessOfFit) +.goodnessOfFit <- function(analysisResults, options, perform){ + + # Create JASP table: + goodnessOfFit <- list() + goodnessOfFit[["title"]] <- "Chi-squared Test" + + footnotes <- .newFootnotes() + + # Create the columns: + goodnessOfFit[["schema"]] <- list(fields = list( + list(name = "model", title="", type = "string"), + list(name = "chisq", title = "Value", type="number", format = "dp:3"), + list(name = "df", title = "df", type="integer"), + list(name = "p", title = "p", type="number", format = "dp:3;p:.001") )) + + # Extract loadings: + if(is.null(analysisResults) || isTryError(analysisResults)){ + Fits <- list( + CHI = ".", + PVAL = ".", + DF = "." + ) + + }else{ + analysisResults <- analysisResults$Results + + Fits <- list( + CHI = .DotIfNULLPCAEFA(analysisResults$STATISTIC), + PVAL = .DotIfNULLPCAEFA(analysisResults$PVAL), + DF = .DotIfNULLPCAEFA(analysisResults$dof) + ) + } + + # Create and fill the row(s): + goodnessOfFit[["data"]] <- list( + list( + model = "Model", + chisq = ifelse(Fits$DF>0,Fits$CHI,"."), + df = ifelse(Fits$DF>0,Fits$DF,"."), + p = ifelse(Fits$DF>0,Fits$PVAL,".") + ) + ) + + return(goodnessOfFit) + } # fitMeasures -.fitMeasuresPCA <- function(analysisResults, options,perform){ - - # browser() - - # Extract loadings: - if (!is.null(analysisResults)){ - - Fits <- list( - CHI = .DotIfNULL(analysisResults$STATISTIC), - PVAL = .DotIfNULL(analysisResults$PVAL), - DF = .DotIfNULL(analysisResults$dof), - RMSEA = .DotIfNULL(unname(analysisResults$RMSEA['RMSEA'])), - RMSEAlower = .DotIfNULL(unname(analysisResults$RMSEA['lower'])), - RMSEAupper = .DotIfNULL(unname(analysisResults$RMSEA['upper'])), - TLI = .DotIfNULL(analysisResults$TLI), - RMS = .DotIfNULL(analysisResults$rms), - CRMS = .DotIfNULL(analysisResults$crms), - BIC = .DotIfNULL(analysisResults$BIC) - ) - - } else { - - Fits <- list( - CHI = ".", - PVAL = ".", - DF = ".", - RMSEA = ".", - RMSEAlower = ".", - RMSEAupper = ".", - TLI = ".", - RMS = ".", - CRMS = ".", - BIC = "." - ) - - } - - - # Create JASP table: - FitMeasures <- list() - FitMeasures[["title"]] <- "Additional fit indices" - - # Create the columns: - FitMeasures[["schema"]] <- list(fields = list( - list(name = "model", title="", type = "string"), - list(name = "RMSEA", title = "RMSEA", type="number", format = "dp:3"), - list(name = "RMSEAci", title = "RMSEA 90% confidence", type="string"), - list(name = "TLI", title = "TLI", type="number", format = "dp:3"), - list(name = "BIC", title = "BIC", type="number", format = "dp:3") - )) - - # Create and fill the row(s): - if (is.numeric(Fits$RMSEAlower)) - { - Fits$RMSEAlower <- round(Fits$RMSEAlower,3) - } - - if (is.numeric(Fits$RMSEAupper)) - { - Fits$RMSEAupper <- round(Fits$RMSEAupper,3) - } - - FitMeasures[["data"]] <- list( - list( - model = "Model", - RMSEA = Fits$RMSEA, - RMSEAci = paste(Fits$RMSEAlower,"-",Fits$RMSEAupper), - TLI = Fits$TLI, - BIC = Fits$BIC - ) - ) - - - return(FitMeasures) +.fitMeasures <- function(analysisResults, options, perform){ + + # Create JASP table: + FitMeasures <- list() + FitMeasures[["title"]] <- "Additional fit indices" + + # Create the columns: + FitMeasures[["schema"]] <- list(fields = list( + list(name = "model", title="", type = "string"), + list(name = "RMSEA", title = "RMSEA", type="number", format = "dp:3"), + list(name = "RMSEAci", title = "RMSEA 90% confidence", type="string"), + list(name = "TLI", title = "TLI", type="number", format = "dp:3"), + list(name = "BIC", title = "BIC", type="number", format = "dp:3") + )) + + # Extract loadings: + if(is.null(analysisResults) || isTryError(analysisResults)){ + Fits <- list( + CHI = ".", + PVAL = ".", + DF = ".", + RMSEA = ".", + RMSEAlower = ".", + RMSEAupper = ".", + TLI = ".", + RMS = ".", + CRMS = ".", + BIC = "." + ) + + }else{ + analysisResults <- analysisResults$Results + Fits <- list( + CHI = .DotIfNULLPCAEFA(analysisResults$STATISTIC), + PVAL = .DotIfNULLPCAEFA(analysisResults$PVAL), + DF = .DotIfNULLPCAEFA(analysisResults$dof), + RMSEA = .DotIfNULLPCAEFA(unname(analysisResults$RMSEA['RMSEA'])), + RMSEAlower = .DotIfNULLPCAEFA(unname(analysisResults$RMSEA['lower'])), + RMSEAupper = .DotIfNULLPCAEFA(unname(analysisResults$RMSEA['upper'])), + TLI = .DotIfNULLPCAEFA(analysisResults$TLI), + RMS = .DotIfNULLPCAEFA(analysisResults$rms), + CRMS = .DotIfNULLPCAEFA(analysisResults$crms), + BIC = .DotIfNULLPCAEFA(analysisResults$BIC) + ) + } + + # Create and fill the row(s): + if (is.numeric(Fits$RMSEAlower)) { + Fits$RMSEAlower <- round(Fits$RMSEAlower,3) + } + + if (is.numeric(Fits$RMSEAupper)) { + Fits$RMSEAupper <- round(Fits$RMSEAupper,3) + } + + FitMeasures[["data"]] <- list( + list( + model = "Model", + RMSEA = Fits$RMSEA, + RMSEAci = paste(Fits$RMSEAlower,"-",Fits$RMSEAupper), + TLI = Fits$TLI, + BIC = Fits$BIC + ) + ) + + return(FitMeasures) + } ### Screeplot: -.screePlot <- function(dataset, options, perform) { - - screePlot <- list() - - # if (perform == "run" && status$ready && !status$error && !is.null(model)) { - # - if (perform == "run" && ncol(dataset) > 0 && nrow(dataset)> 0 && length(options$variables) > 1) { - - screePlot$title <- "Scree Plot" - screePlot$width <- options$plotWidthScreePlot - screePlot$height <- options$plotHeightScreePlot - screePlot$custom <- list(width="plotWidthScreePlot", height="plotHeightScreePlot") - - # Compute ev: - - # Compute ev: - image <- .beginSaveImage() - pa <- psych::fa.parallel(dataset) - .endSaveImage(image) - - # Eigenvalues: - EV <- data.frame( - id = seq_len(ncol(dataset)), - ev = pa$pc.values, - type = "Data" - ) - - # Parallel analysis: - PA <- data.frame( - id = seq_len(ncol(dataset)), - ev = pa$pc.sim, - type = "Simulated (95th quantile)" - ) - - combined <- rbind(EV,PA) - - p <- ggplot2::ggplot(combined, ggplot2::aes_string(x="id",y="ev",lty="type",pch="type")) + ggplot2::geom_point(na.rm = TRUE, size=3) + - ggplot2::xlab("") + ggplot2::ylab("Eigenvalue")+ ggplot2::xlab("Components") +ggplot2::geom_line(na.rm = TRUE) + - ggplot2::ggtitle("") + ggplot2::theme_bw() + ggplot2::geom_hline(yintercept = options$eigenValuesBox) + - ggplot2::theme(panel.grid.minor=ggplot2::element_blank(), plot.title = ggplot2::element_text(size=18), - panel.grid.major=ggplot2::element_blank(), axis.line = ggplot2::element_line(colour = "black", size=1.2), - axis.title.x = ggplot2::element_text(size=18,vjust=-.2), axis.title.y = ggplot2::element_text(size=18,vjust=1.2), - axis.text.x = ggplot2::element_text(size=15), axis.text.y = ggplot2::element_text(size=15), - panel.background = ggplot2::element_rect(fill = 'transparent', colour = NA), - plot.background = ggplot2::element_rect(fill = 'transparent', colour = NA), - panel.border = ggplot2::element_blank(), - axis.ticks = ggplot2::element_line(size = 0.5), - axis.ticks.margin = grid::unit(1,"mm"), - axis.ticks.length = grid::unit(3, "mm"), - plot.margin = grid::unit(c(0,0,.5,.5), "cm")) + - ggplot2::scale_linetype_discrete("") + ggplot2::scale_shape_discrete("") + - ggplot2::theme(legend.position = c(0.99,0.99),legend.justification = c(1,1), - legend.text=ggplot2::element_text(size=12.5), - panel.background=ggplot2::element_rect(fill="transparent",colour=NA), - plot.background=ggplot2::element_rect(fill="transparent",colour=NA), - legend.key = ggplot2::element_rect(fill = "transparent", colour = "transparent"), - legend.background=ggplot2::element_rect(fill="transparent",colour=NA)) - - # image <- .beginSaveImage(options$plotWidthScreePlot, options$plotHeightScreePlot) - # print(p) - # content <- .endSaveImage(image) - - content <- .writeImage(width = options$plotWidthScreePlot, - height = options$plotHeightScreePlot, - plot = p, obj = TRUE) - screePlot$data <- content[["png"]] - screePlot[["convertible"]] <- TRUE - screePlot[["obj"]] <- content[["obj"]] - - # screePlot$data <- content - screePlot$status <- "complete" - - statescreePlot <- screePlot - - } else { - - screePlot$title <- "Scree Plot" - screePlot$width <- options$plotWidthScreePlot - screePlot$height <- options$plotHeightScreePlot - screePlot$custom <- list(width="plotWidthScreePlot", height="plotHeightScreePlot") - - screePlot$data <- NULL - - statescreePlot <- NULL - - # if (status$error) - # screePlot$error <- list(errorType="badData") - - } - - return(screePlot) +.screePlot <- function(dataset, options, perform, oldPlot = NULL, plotType) { + + # After image can be wrote to file, the state system can be used to return unchanged screePlot + if (!is.null(oldPlot) && !identical(oldPlot[["data"]], "") && !is.null(oldPlot[["data"]])) { + return(oldPlot) + } + + screePlot <- list() + screePlot$title <- "Scree Plot" + screePlot$width <- options$plotWidthScreePlot + screePlot$height <- options$plotHeightScreePlot + screePlot$custom <- list(width="plotWidthScreePlot", height="plotHeightScreePlot") + + if (!is.null(dataset) && nrow(dataset)> 1 && length(options$variables) > 1) { + + # Compute ev: + pa <- .suppressPlotFA(dataset) + + if (plotType == "pca") { + ev_ev <- pa$pc.values + pa_ev <- pa$pc.sim + xName = "Components" + } + + if (plotType == "efa") { + ev_ev <- pa$fa.values + pa_ev <- pa$fa.sim + xName = "Factors" + } + # Eigenvalues: + EV <- data.frame( + id = seq_len(ncol(dataset)), + ev = ev_ev, + type = "Data" + ) + + # Parallel analysis: + PA <- data.frame( + id = seq_len(ncol(dataset)), + ev = pa_ev, + type = "Simulated (95th quantile)" + ) + + combined <- rbind(EV,PA) + + p <- ggplot2::ggplot(combined, ggplot2::aes_string(x="id",y="ev",lty="type",pch="type")) + ggplot2::geom_point(na.rm = TRUE, size=3) + + ggplot2::xlab("") + ggplot2::ylab("Eigenvalue")+ ggplot2::xlab(xName) +ggplot2::geom_line(na.rm = TRUE) + + ggplot2::ggtitle("") + ggplot2::theme_bw() + ggplot2::geom_hline(yintercept = options$eigenValuesBox) + + ggplot2::theme(panel.grid.minor=ggplot2::element_blank(), plot.title = ggplot2::element_text(size=18), + panel.grid.major=ggplot2::element_blank(), axis.line = ggplot2::element_line(colour = "black", size=1.2), + axis.title.x = ggplot2::element_text(size=18,vjust=-.2), axis.title.y = ggplot2::element_text(size=18,vjust=1.2), + axis.text.x = ggplot2::element_text(size=15), axis.text.y = ggplot2::element_text(size=15), + panel.background = ggplot2::element_rect(fill = 'transparent', colour = NA), + plot.background = ggplot2::element_rect(fill = 'transparent', colour = NA), + panel.border = ggplot2::element_blank(), + axis.ticks = ggplot2::element_line(size = 0.5), + axis.ticks.margin = grid::unit(1,"mm"), + axis.ticks.length = grid::unit(3, "mm"), + plot.margin = grid::unit(c(0,0,.5,.5), "cm")) + + ggplot2::scale_linetype_discrete("") + ggplot2::scale_shape_discrete("") + + ggplot2::theme(legend.position = c(0.99,0.99),legend.justification = c(1,1),#legend.key = ggplot2::element_blank(), + legend.text=ggplot2::element_text(size=12.5), + panel.background=ggplot2::element_rect(fill="transparent",colour=NA), + plot.background=ggplot2::element_rect(fill="transparent",colour=NA), + legend.key = ggplot2::element_rect(fill = "transparent", colour = "transparent"), + legend.background=ggplot2::element_rect(fill="transparent",colour=NA)) + + content <- .writeImage(width = options$plotWidthScreePlot, height = options$plotHeightScreePlot, plot = p, obj = TRUE) + screePlot[["convertible"]] <- TRUE + screePlot[["obj"]] <- content[["obj"]] + screePlot[["data"]] <- content[["png"]] + screePlot[["status"]] <- "complete" + + } else { + + screePlot$data <- NULL + + } + + return(screePlot) } + +.suppressPlotFA <- function(...) { + tempfile <- tempfile() + png(filename=tempfile) + result <- psych::fa.parallel(...) + dev.off() + unlink(tempfile) + return(result) +} \ No newline at end of file diff --git a/JASP-Engine/JASP/R/regressionlinearbayesian.R b/JASP-Engine/JASP/R/regressionlinearbayesian.R index 18f550b848..74b69308b4 100644 --- a/JASP-Engine/JASP/R/regressionlinearbayesian.R +++ b/JASP-Engine/JASP/R/regressionlinearbayesian.R @@ -29,7 +29,7 @@ RegressionLinearBayesian <- function (dataset = NULL, options, perform = "run", base::options (BFprogress = interactive()) if (is.null (base::options ()$BFfactorsMax)) base::options (BFfactorsMax = 5) - + print("here0") .callbackBFpackage <- function(...) { response <- .callbackBayesianLinearModels () if(response$status == "ok") @@ -48,7 +48,7 @@ RegressionLinearBayesian <- function (dataset = NULL, options, perform = "run", } return (response) } - + print("here1") state <- .retrieveState () if ( ! is.null (state)) { change <- .diff (options, state$options) @@ -68,7 +68,7 @@ RegressionLinearBayesian <- function (dataset = NULL, options, perform = "run", meta [[4]] <- list (name = "estimates", type = "table") results [[".meta"]] <- meta results [["title"]] <- "Bayesian Linear Regression" - + print("here2") ## DATA if (is.null(state)) { dataset <- .readBayesianLinearModelData (dataset, options, perform) diff --git a/JASP-Engine/JASP/R/regressionlogistic.R b/JASP-Engine/JASP/R/regressionlogistic.R index c915096d6f..4438f05c52 100644 --- a/JASP-Engine/JASP/R/regressionlogistic.R +++ b/JASP-Engine/JASP/R/regressionlogistic.R @@ -15,7 +15,8 @@ # along with this program. If not, see . # -RegressionLogistic <- function(dataset=NULL, options, perform="run", callback=function(...) 0, ...) { +RegressionLogistic <- function(dataset=NULL, options, perform="run", + callback=function(...) 0, ...) { # DATASET LOADING numericVars <- unlist(c(options[["covariates"]], @@ -85,7 +86,7 @@ RegressionLogistic <- function(dataset=NULL, options, perform="run", callback=fu diff <- .diff(options, state[["options"]]) with(diff, { # with(diff, {}) makes us need "<<-" to assign to global env if (!any(dependent, covariates, factors, wlsWeights, modelTerms, - includeIntercept, wlsWeights, method, entryPval, removalPval)) { + includeIntercept, wlsWeights, method)) { lrObj <<- state[["lrObj"]] modelSummary <<- state[["modelSummary"]] @@ -132,7 +133,7 @@ RegressionLogistic <- function(dataset=NULL, options, perform="run", callback=fu } }) } else if (!is.null(state)) { - lrObj <<- state[["lrObj"]] + lrObj <- state[["lrObj"]] modelSummary <- state[["modelSummary"]] estimatesTable <- state[["estimatesTable"]] confusionMatrix <- state[["confusionMatrix"]] @@ -173,7 +174,7 @@ RegressionLogistic <- function(dataset=NULL, options, perform="run", callback=fu if (is.null(modelSummary)) { modelSummary <- .glmModelSummary(lrObj, options, perform, type = "binomial") } - + if (is.null(estimatesTable) && options[["coeffEstimates"]]) { estimatesTable <- .glmEstimatesTable(lrObj, options, perform, type = "binomial") diff --git a/JASP-Engine/JASP/R/regressionloglinearbayesian.R b/JASP-Engine/JASP/R/regressionloglinearbayesian.R index 43554bc593..71b1ebebf5 100644 --- a/JASP-Engine/JASP/R/regressionloglinearbayesian.R +++ b/JASP-Engine/JASP/R/regressionloglinearbayesian.R @@ -763,8 +763,6 @@ RegressionLogLinearBayesian <- function(dataset, options, perform="run", callbac BayesianSublogregression.result[[ len.Blogreg ]]$"upper_lim" <- as.numeric(logBlm.subestimates$upper[var]) } - BayesianSublogregression.result[[ len.Blogreg ]]$ "footnotes" <- as.list (footnotes) - len.Blogreg <- len.Blogreg + 1 } } diff --git a/JASP-Tests/run_tests.R b/JASP-Engine/JASP/R/reinforcementlearningr11tlearning.R similarity index 52% rename from JASP-Tests/run_tests.R rename to JASP-Engine/JASP/R/reinforcementlearningr11tlearning.R index d4d0fafae8..d3a99dbfc1 100644 --- a/JASP-Tests/run_tests.R +++ b/JASP-Engine/JASP/R/reinforcementlearningr11tlearning.R @@ -1,5 +1,5 @@ # -# Copyright (C) 2017 University of Amsterdam +# Copyright (C) 2013-2017 University of Amsterdam # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,19 +16,23 @@ # -library(testthat) +ReinforcementLearningR11tLearning <- function ( + dataset = NULL, + options, + perform = "run", + callback = function(...) list(status = "ok"), + state = NULL, + ... +) { -# include all analyses source files -file.sources = list.files( - "../JASP-Engine/JASP/R/", - pattern = "*.R$", - full.names = TRUE, - ignore.case = TRUE - ) -sapply(file.sources,source, .GlobalEnv) + table <- list() + table[["title"]] <- "R11t Learning" + table[["schema"]] <- list(fields = list()) + table[["data"]] <- list() -# define the test directory and store the test results in variable -test_results <- test_dir("analysesTests/", reporter = "summary") + results <- list() + results[[".meta"]] <- list(list(name = "table", type = "table")) + results[["table"]] <- table -# yet to implement - print test_results list to test-log file -# lapply(test_results, write, "test.txt", append=TRUE) + return (list(results = results, status = "complete")) +} diff --git a/JASP-Engine/JASP/R/ttestbayesianonesample.R b/JASP-Engine/JASP/R/ttestbayesianonesample.R index eb5f386702..c6d68136ec 100644 --- a/JASP-Engine/JASP/R/ttestbayesianonesample.R +++ b/JASP-Engine/JASP/R/ttestbayesianonesample.R @@ -4517,9 +4517,9 @@ TTestBayesianOneSample <- function(dataset=NULL, options, perform="run", callbac oneSided = FALSE, options) { tValue <- unname(t.test(x, y, paired = paired, var.equal = TRUE)$statistic) - - n1 <- length(x) - n2 <- ifelse(paired, 0, length(y)) + # numeric multiplication is more robust in R + n1 <- as.numeric(length(x)) + n2 <- ifelse(paired, 0, as.numeric(length(y))) if(options[["effectSizeStandardized"]] == "default") { diff --git a/JASP-Engine/engine.cpp b/JASP-Engine/engine.cpp index 02426486c1..010f15f85c 100644 --- a/JASP-Engine/engine.cpp +++ b/JASP-Engine/engine.cpp @@ -116,7 +116,7 @@ void Engine::runAnalysis() RCallback callback = boost::bind(&Engine::callback, this, _1, _2); _currentAnalysisKnowsAboutChange = false; - _analysisResultsString = rbridge_run(_analysisName, _analysisOptions, perform, _ppi, callback); + _analysisResultsString = rbridge_run(_analysisName, _analysisTitle, _analysisRequiresInit, _analysisDataKey, _analysisOptions, _analysisResultsMeta, _analysisStateKey, perform, _ppi, callback); if (_status == initing || _status == running) // if status hasn't changed receiveMessages(); @@ -259,10 +259,20 @@ bool Engine::receiveMessages(int timeout) if (_status == toInit || _status == toRun || _status == changed || _status == saveImg) { _analysisName = jsonRequest.get("name", Json::nullValue).asString(); + _analysisTitle = jsonRequest.get("title", Json::nullValue).asString(); + _analysisDataKey = jsonRequest.get("dataKey", Json::nullValue).toStyledString(); _analysisOptions = jsonRequest.get("options", Json::nullValue).toStyledString(); + _analysisResultsMeta = jsonRequest.get("resultsMeta", Json::nullValue).toStyledString(); + _analysisStateKey = jsonRequest.get("stateKey", Json::nullValue).toStyledString(); _analysisRevision = jsonRequest.get("revision", -1).asInt(); _imageOptions = jsonRequest.get("image", Json::nullValue); + Json::Value analysisRequiresInit = jsonRequest.get("requiresInit", Json::nullValue); + if (analysisRequiresInit.isNull()) // not defined in the analysis json + _analysisRequiresInit = true; + else + _analysisRequiresInit = analysisRequiresInit.asBool(); + Json::Value settings = jsonRequest.get("settings", Json::nullValue); if (settings.isObject()) { diff --git a/JASP-Engine/engine.h b/JASP-Engine/engine.h index 6cbec3aafc..7060b1b996 100644 --- a/JASP-Engine/engine.h +++ b/JASP-Engine/engine.h @@ -65,7 +65,12 @@ class Engine int _analysisRevision; int _progress; std::string _analysisName; + std::string _analysisTitle; + bool _analysisRequiresInit; + std::string _analysisDataKey; std::string _analysisOptions; + std::string _analysisResultsMeta; + std::string _analysisStateKey; std::string _analysisResultsString; Json::Value _imageOptions; int _ppi; diff --git a/JASP-Engine/rbridge.cpp b/JASP-Engine/rbridge.cpp index eb92da036d..43090eec47 100644 --- a/JASP-Engine/rbridge.cpp +++ b/JASP-Engine/rbridge.cpp @@ -124,7 +124,7 @@ SEXP rbridge_requestStateFileNameSEXP() return paths; } -string rbridge_run(const string &name, const string &options, const string &perform, int ppi, RCallback callback) +string rbridge_run(const string &name, const string &title, bool &requiresInit, const string &dataKey, const string &options, const string &resultsMeta, const string &stateKey, const string &perform, int ppi, RCallback callback) { SEXP results; @@ -133,11 +133,16 @@ string rbridge_run(const string &name, const string &options, const string &perf RInside &rInside = rbridge_rinside->instance(); rInside["name"] = name; - rInside["options.as.json.string"] = options; + rInside["title"] = title; + rInside["requiresInit"] = requiresInit; + rInside["dataKey"] = dataKey; + rInside["options"] = options; + rInside["resultsMeta"] = resultsMeta; + rInside["stateKey"] = stateKey; rInside["perform"] = perform; rInside[".ppi"] = ppi; - rInside.parseEval("run(name=name, options.as.json.string=options.as.json.string, perform)", results); + rInside.parseEval("run(name=name, title=title, requiresInit=requiresInit, dataKey=dataKey, options=options, resultsMeta=resultsMeta, stateKey=stateKey, perform=perform)", results); rbridge_runCallback = NULL; diff --git a/JASP-Engine/rbridge.h b/JASP-Engine/rbridge.h index a0280ebc67..7056f61ac8 100644 --- a/JASP-Engine/rbridge.h +++ b/JASP-Engine/rbridge.h @@ -48,7 +48,7 @@ void rbridge_setFileNameSource(boost::function source); void rbridge_setStateFileSource(boost::function source); void rbridge_setDataSetSource(boost::function source); - std::string rbridge_run(const std::string &name, const std::string &options, const std::string &perform = "run", int ppi = 96, RCallback callback = NULL); + std::string rbridge_run(const std::string &name, const std::string &title, bool &requiresInit, const std::string &dataKey, const std::string &options, const std::string &resultsMeta, const std::string &stateKey, const std::string &perform = "run", int ppi = 96, RCallback callback = NULL); std::string rbridge_saveImage(const std::string &name, const std::string &type, const int &height, const int &width, const int ppi = 96); std::string rbridge_check(); diff --git a/JASP-Tests/JASP-Tests-app.pro b/JASP-Tests/JASP-Tests-app.pro index 13e7b47124..9690033b33 100644 --- a/JASP-Tests/JASP-Tests-app.pro +++ b/JASP-Tests/JASP-Tests-app.pro @@ -58,7 +58,8 @@ SOURCES += \ textfileread_test.cpp \ osf_test.cpp \ spssimporter_test.cpp \ - csvimporter_test.cpp + csvimporter_test.cpp \ + odsimporter_test.cpp HEADERS += \ AutomatedTests.h \ @@ -66,7 +67,8 @@ HEADERS += \ osf_test.h \ csviterator.h \ spssimporter_test.h \ - csvimporter_test.h + csvimporter_test.h \ + odsimporter_test.h HELP_PATH = $${PWD}/../Docs/help RESOURCES_PATH = $${PWD}/../Resources diff --git a/JASP-Tests/R/DESCRIPTION b/JASP-Tests/R/DESCRIPTION new file mode 100644 index 0000000000..47eb9a5148 --- /dev/null +++ b/JASP-Tests/R/DESCRIPTION @@ -0,0 +1,12 @@ +Package: SomePkg +Type: Package +Title: +Version: 0 +Author: JASP +Maintainer: Tim de Jong +Description: We need to pretend that the unit tests are a package. If we do not do this we cannot take full advantage of vdiffr. +License: GNU General Public License +Encoding: UTF-8 +LazyData: true +Imports: +Suggests: diff --git a/JASP-Tests/R/tests/datasets/test.csv b/JASP-Tests/R/tests/datasets/test.csv new file mode 100644 index 0000000000..ce1ec839b1 --- /dev/null +++ b/JASP-Tests/R/tests/datasets/test.csv @@ -0,0 +1,101 @@ +,contNormal,contGamma,contBinom,contExpon,contWide,contNarrow,contOutlier,contcor1,contcor2,facGender,facExperim,facFive,facFifty,facOutlier,debString,debMiss1,debMiss30,debMiss80,debMiss99,debBinMiss20,debNaN,debNaN10,debInf,debCollin1,debCollin2,debCollin3,debEqual1,debEqual2,debSame +1,0.99122228,0.780975715,1,1.70E-20,8.38E+98,-9.96E-100,0.269038564,1.521033162,1.480950383,m,control,1,1,f1,h,12.29505445,-12.50897286,,,1,,19.33621882,Inf,0.642038201,2.642038201,1.284076402,12.59439792,12.59439792,12.3 +2,-1.953344972,1.661185538,0,18858693.53,3.87E+99,-1.27E-100,-0.751745664,-0.910386819,-1.013220053,f,experimental,2,2,f2,l,15.81197434,,,,,,-19.8459184,Inf,0.515440275,2.515440275,1.03088055,3.203714829,3.203714829,12.3 +3,1.576301642,1.176677112,0,1.37E-24,7.02E+99,-8.78E-100,-0.70719854,-0.612928686,-0.296117034,m,control,3,3,f1,o,2.213892619,-6.105561134,-27.5946802,,0,,-15.38229892,Inf,0.447585321,2.447585321,0.895170641,2.039632761,2.039632761,12.3 +4,0.947933415,1.331417271,1,1.02E+27,2.26E+98,-9.53E-100,-3.315197368,-1.332980719,0.089105927,f,experimental,4,4,f2,m,-9.146498869,-0.81577699,,,0,,-14.57178797,Inf,0.642930641,2.642930641,1.285861281,23.28135794,23.28135794,12.3 +5,-0.532552496,1.18426484,1,2.98E-26,5.76E+99,8.33E-100,0.452474276,-0.027805872,0.517458031,m,control,5,5,f1,z,14.17165658,,,,0,,,Inf,0.585416105,2.585416105,1.170832209,11.94984212,11.94984212,12.3 +6,-1.363597632,2.478443291,1,1.90E+33,-4.65E+99,-8.30E-100,0.484832885,1.276411515,0.630621107,m,experimental,1,6,f2,x,-5.247577291,25.74968991,,,0,,-0.538542085,Inf,0.544931008,2.544931008,1.089862015,5.86162875,5.86162875,12.3 +7,-0.654979378,1.529750756,0,2.96E+29,-6.49E+99,1.28E-100,0.246931163,0.145010456,0.338049419,f,control,2,7,f1,n,34.91974603,9.318638024,,,1,,7.379238519,Inf,0.743580248,2.743580248,1.487160496,1.860119237,1.860119237,12.3 +8,-0.751445953,0.348246238,0,1.01E+20,1.57E+99,7.53E-100,1.454038184,-0.964470142,-1.540254853,m,experimental,3,8,f2,v,-11.49774025,-37.34994081,34.97482541,,0,,47.63552969,Inf,0.651916557,2.651916557,1.303833114,2.172089504,2.172089504,12.3 +9,0.310181524,0.37865767,0,1.56E+35,5.14E+99,5.50E-100,0.314986582,2.006165806,1.370681986,f,control,4,9,f1,r,16.27130461,-26.24251961,,,0,,41.06299019,Inf,0.696833552,2.696833552,1.393667105,4.794362541,4.794362541,12.3 +10,-0.675270732,2.777961973,0,1.74E-49,-3.52E+99,-9.97E-100,1.254507244,0.86064292,1.330696219,f,experimental,5,10,f2,q,-26.32751885,64.50668921,,,1,,7.391813158,Inf,0.694601235,2.694601235,1.389202469,2.772569488,2.772569488,12.3 +11,0.364848251,3.977031334,0,3.29E-21,-7.75E+98,-3.43E-100,-1.056739214,-0.828902249,-0.102756392,f,control,1,11,f1,z,22.51349443,,,,0,,12.56673523,Inf,0.711955085,2.711955085,1.42391017,29.32237861,29.32237861,12.3 +12,0.525950287,2.656664043,1,8.89E-23,7.21E+99,-7.73E-100,0.027473107,-0.611646545,0.424124199,m,experimental,2,12,f2,e,-22.29764163,5.185419296,-9.039264777,,0,,40.18473672,Inf,0.593240305,2.593240305,1.186480609,3.289304957,3.289304957,12.3 +13,-0.954597608,0.441790033,0,3.38E-27,-2.24E+99,2.59E-100,2.010655929,1.858228623,2.024579557,f,control,3,13,f1,p,2.079802765,0.490318741,,,1,,7.186747009,Inf,0.694789138,2.694789138,1.389578277,29.60816458,29.60816458,12.3 +14,-0.399043745,0.678039819,0,5606.730444,-6.56E+99,-5.86E-100,-0.473325284,0.642043149,0.171809484,m,experimental,4,14,f2,g,-23.85909038,-1.708067004,,,1,,17.26707742,Inf,0.736839036,2.736839036,1.473678072,12.81628158,12.81628158,12.3 +15,-2.336742886,2.530188739,0,3427.815043,8.55E+99,-7.26E-100,-0.218319199,-0.913900494,0.063506238,m,control,5,15,f1,i,-15.10502073,-3.724596596,,,1,,13.43839211,Inf,0.698094646,2.698094646,1.396189293,10.33111466,10.33111466,12.3 +16,-0.632883125,3.306006111,0,2.04E+25,2.80E+98,-3.51E-100,-0.362584916,0.348716082,1.57988411,m,experimental,1,16,f2,a,58.3179159,31.93803283,,,1,,-6.017744385,Inf,0.526075461,2.526075461,1.052150922,7.339607773,7.339607773,12.3 +17,0.588682079,1.900242487,1,1.25E-32,-6.29E+99,3.96E-100,0.133472482,0.976441678,0.905650485,m,control,2,17,f1,c,-29.50332183,,,,1,,-10.5254181,Inf,0.633042095,2.633042095,1.26608419,14.74490268,14.74490268,12.3 +18,0.391750556,1.761105829,0,10641603.08,-1.85E+99,2.61E-100,1.301359718,-0.526381444,-0.728247624,f,experimental,3,18,f2,p,18.62680303,,43.63876663,,0,,60.33055091,Inf,0.671483094,2.671483094,1.342966187,19.04092749,19.04092749,12.3 +19,-1.264009159,2.29457509,0,0.042666202,-2.42E+99,-6.76E-100,4.5,0.332000711,0.590554201,m,control,4,19,f1,y,-34.4206158,,59.98295451,,1,,-33.17939265,Inf,0.644589319,2.644589319,1.289178637,4.457849079,4.457849079,12.3 +20,1.058565048,0.942826432,0,0.008650772,-2.29E+99,-1.10E-100,0.02063217,-0.106530923,-0.336862124,m,experimental,5,20,f2,j,8.60973483,3.171606677,,,0,,42.13211,Inf,0.638244615,2.638244615,1.27648923,0.981495504,0.981495504,12.3 +21,-0.850244619,2.833575102,0,2.26E-17,5.73E+99,8.56E-100,-0.660865856,-1.002178797,-0.636844309,m,control,1,21,f1,s,-18.56055899,,,,0,,41.63230666,Inf,0.869855592,2.869855592,1.739711184,18.86640292,18.86640292,12.3 +22,-0.359553637,1.839209197,1,7.84E+29,-7.10E+99,-1.42E-100,0.813252697,0.626378919,1.831881884,f,experimental,2,22,f2,k,2.276286087,-26.03093825,,,0,,18.08252447,Inf,0.801496435,2.801496435,1.60299287,7.09200338,7.09200338,12.3 +23,0.108920494,5.078108173,0,2043267.37,1.82E+99,5.85E-100,0.453708481,1.484293596,2.134815938,m,control,3,23,f1,s,-7.071277306,45.18686658,,,0,,23.19866523,Inf,0.704276279,2.704276279,1.408552559,36.20041863,36.20041863,12.3 +24,0.01096381,1.383094211,0,204310864.6,-1.43E+99,6.65E-100,1.142966476,0.374450749,1.026428056,f,experimental,4,24,f2,z,-59.86347421,8.83853789,20.18332567,,1,,-4.140889402,Inf,0.666621926,2.666621926,1.333243853,10.76760955,10.76760955,12.3 +25,2.739343353,0.527073852,0,5.37E-12,-5.25E+99,-6.96E-100,0.524149442,1.270672337,1.285324181,m,control,5,25,f1,m,31.04606599,12.71106193,-21.97367833,,,,-2.585273933,Inf,0.690001843,2.690001843,1.380003687,11.75533742,11.75533742,12.3 +26,-0.59740969,4.618063242,0,85379971.27,-8.03E+99,-4.88E-100,-0.795363656,-2.073133408,-0.768743297,m,experimental,1,26,f2,x,16.19107226,,,,,,-2.452483948,Inf,0.563699434,2.563699434,1.127398868,1.470873667,1.470873667,12.3 +27,-0.470163224,5.157894077,0,8.75E-07,3.15E+99,3.83E-100,-1.138422,-1.058258102,-1.489765825,f,control,2,27,f1,r,54.33924971,-17.99711621,,,,,2.645337056,Inf,0.698381203,2.698381203,1.396762406,0.058757922,0.058757922,12.3 +28,-1.447375559,2.363390504,1,0.503955858,8.72E+99,1.01E-100,0.336652361,0.421280454,-0.01636327,f,experimental,3,28,f2,g,-4.974043519,,,,,,27.43954953,Inf,0.590536511,2.590536511,1.181073022,3.088944846,3.088944846,12.3 +29,0.505173357,2.838679609,1,1.20E+22,-4.66E+99,9.31E-101,0.209776766,-1.356023197,-1.257525134,f,control,4,29,f1,a,-0.555140607,18.40487547,,,0,,,Inf,0.6716216,2.6716216,1.343243199,3.702698217,3.702698217,12.3 +30,0.307537423,0.660057008,0,6.18E-06,-5.21E+99,2.63E-100,-0.86190895,0.648830867,-0.014202675,m,experimental,5,30,f2,f,45.47605434,-3.166165593,,,,,-4.010210335,Inf,0.634324908,2.634324908,1.268649816,8.499626141,8.499626141,12.3 +31,-1.395443011,3.930940809,0,0.002978766,-1.80E+99,1.21E-100,1.856756889,-0.082624118,-0.068970666,m,control,1,31,f1,m,1.330889209,16.22066096,9.750882176,,0,,-14.27635326,Inf,0.7115023,2.7115023,1.423004601,1.481335791,1.481335791,12.3 +32,-0.367996707,2.230799959,0,28940.10745,-5.99E+99,7.31E-100,-0.966375392,-0.425815213,0.510773233,f,experimental,2,32,f2,w,20.89165938,,,,0,,-6.324200517,Inf,0.579010829,2.579010829,1.158021658,12.29630114,12.29630114,12.3 +33,0.793185108,1.160636689,1,1.61E-07,8.93E+99,7.23E-101,-0.440281387,0.393831644,0.104634243,f,control,3,33,f1,o,34.32134416,37.15164556,,,1,,-52.57099368,Inf,0.603432164,2.603432164,1.206864328,10.31847212,10.31847212,12.3 +34,0.596201293,0.197333889,0,8.58E+33,6.23E+99,5.62E-100,-23,1.836337366,0.226108977,f,experimental,4,34,f2,z,-15.30218115,-5.230861965,,,,,14.9125812,Inf,0.685082521,2.685082521,1.370165042,0.921557925,0.921557925,12.3 +35,-0.556843301,0.676660939,0,1.67E-13,2.24E+99,2.77E-101,1.227390828,0.277718896,-0.155389747,f,control,5,35,f1,a,-10.51401033,20.6970882,,,1,,-23.5585338,Inf,0.652887496,2.652887496,1.305774992,0.817209248,0.817209248,12.3 +36,0.644058891,4.975727839,1,4.17E-07,2.10E+98,4.68E-101,-0.266525133,-0.833115983,-1.127839217,m,experimental,1,36,f2,e,34.00566913,11.63175636,,,1,,9.777477989,Inf,0.581590324,2.581590324,1.163180647,1.75851692,1.75851692,12.3 +37,-0.242813433,2.77466792,1,5.22E+17,7.75E+99,7.61E-100,-1.0809194,1.055700614,0.45790074,f,control,2,37,f1,x,10.87473713,20.93077096,,,0,,27.81169355,Inf,0.675894708,2.675894708,1.351789417,1.302255697,1.302255697,12.3 +38,1.410001008,1.532106738,1,1.19E+23,3.74E+99,-2.98E-100,0.817291146,-1.585812858,-1.217982555,m,experimental,3,38,f2,t,15.06146133,-9.456293275,,,1,,-9.855238762,Inf,0.665411145,2.665411145,1.33082229,60.62183473,60.62183473,12.3 +39,-0.342746069,3.959582989,1,5.37E+36,2.51E+99,3.41E-100,2.856221513,0.03507676,-0.407814327,m,control,4,39,f1,d,14.96051082,12.23958598,,,1,,56.14853606,Inf,0.757228652,2.757228652,1.514457304,5.902888641,5.902888641,12.3 +40,-0.618288772,0.991611379,0,6.68E-23,1.53E+99,4.91E-100,1.371816795,-0.397021392,-0.298569173,m,experimental,5,40,f2,g,-40.08210082,,,,1,,-1.074534587,Inf,0.62041137,2.62041137,1.24082274,11.62692353,11.62692353,12.3 +41,-0.692689912,0.722313192,0,5.87E-12,-3.32E+99,-1.72E-100,-3.12,1.43939299,0.768509543,f,control,1,41,f1,i,8.218437573,7.192798371,,,1,,-21.10145059,Inf,0.650746613,2.650746613,1.301493226,4.086470137,4.086470137,12.3 +42,-1.415363942,0.614345924,1,1.16E-26,-7.78E+99,7.21E-100,1.569206836,-0.148337753,0.874278791,m,experimental,2,42,f2,l,-9.872269548,-8.749054106,-9.424529551,,0,,14.2327728,Inf,0.679484841,2.679484841,1.358969682,10.21653027,10.21653027,12.3 +43,-0.786160472,0.483241669,0,527.1268561,-6.47E+99,3.70E-100,0.104621969,-1.355751095,-0.520476438,f,control,3,43,f1,u,13.46850734,,,,1,,7.749639899,Inf,0.599784155,2.599784155,1.199568311,5.023304044,5.023304044,12.3 +44,-0.840984252,2.359102511,0,48530.464,5.92E+99,5.64E-100,-1.024937933,-2.147231812,-1.729626099,m,experimental,4,44,f2,h,-20.01871895,,,,0,,64.30898882,Inf,0.673688173,2.673688173,1.347376346,16.0212847,16.0212847,12.3 +45,-0.999014305,1.750826816,1,5.54E-13,-6.90E+98,7.70E-100,0.658332312,-0.560945149,0.399656151,f,control,5,45,f1,j,16.38070237,,,,,,8.578501694,Inf,0.767064874,2.767064874,1.534129747,6.029500724,6.029500724,12.3 +46,1.007309698,4.321780883,0,6.20E-06,3.40E+99,-8.03E-100,-0.72708755,0.612323493,0.714870906,f,experimental,1,46,f2,d,-6.508017194,-12.76054352,,,0,,27.56515752,Inf,0.584264788,2.584264788,1.168529577,7.594024222,7.594024222,12.3 +47,-0.611664173,1.195401638,1,9.36E-22,8.46E+99,7.79E-100,0.01846117,-0.432126651,-0.906914708,f,control,2,47,f1,f,21.73765541,-4.580751279,2.329880838,,0,,13.10111222,Inf,0.572718084,2.572718084,1.145436168,6.529850511,6.529850511,12.3 +48,0.46937728,2.984005893,1,3.44E+57,7.81E+99,7.98E-100,-1.329301737,-0.265197642,-0.692746481,m,experimental,3,48,f2,e,18.83402554,9.135909664,,,,,,Inf,0.659782958,2.659782958,1.319565916,35.44104618,35.44104618,12.3 +49,-3.023963827,0.410306148,1,1.22E-17,-5.17E+99,-2.71E-100,0.202589917,0.299985335,-0.188711694,f,control,4,49,f1,q,-39.15662657,53.11149213,,,1,,55.13509021,Inf,0.661300458,2.661300458,1.322600917,3.763125443,3.763125443,12.3 +50,0.166778121,0.302480929,0,9.71E-10,-2.94E+99,2.99E-100,-0.539687644,0.825507709,0.967936613,m,experimental,5,50,f2,o,22.31499477,,,,0,,11.36083995,Inf,0.617465311,2.617465311,1.234930622,0.227627757,0.227627757,12.3 +51,-0.658287055,0.494589392,1,11470440.29,8.27E+99,6.78E-100,-0.05383627,0.132982528,0.112492177,f,control,1,1,f1,q,-7.964379196,55.8084898,,,0,,24.14384346,Inf,0.783959893,2.783959893,1.567919787,2.532787387,2.532787387,12.3 +52,-1.649937891,0.715926748,1,3.72E-16,-3.59E+99,-7.99E-100,-0.011038078,-0.535487932,0.194084995,m,experimental,2,2,f2,z,8.850454495,19.40455001,,,,,-11.84490983,Inf,0.706065325,2.706065325,1.41213065,0.800762803,0.800762803,12.3 +53,0.757371551,1.281209304,0,1.65E-08,1.42E+99,3.03E-100,-0.144103418,-0.758838087,-1.10097767,m,control,3,3,f1,c,21.78692693,,,,0,,17.55972289,Inf,0.625826063,2.625826063,1.251652125,10.4416378,10.4416378,12.3 +54,-0.412828649,2.775624599,1,4.10E-05,1.88E+99,-3.22E-100,-0.118616735,0.512946962,1.076899229,f,experimental,4,4,f2,d,-24.76457867,15.80012906,,,1,,5.154103894,Inf,0.574662184,2.574662184,1.149324368,2.735722696,2.735722696,12.3 +55,3.356094448,1.644354059,0,6.13E-06,7.64E+99,2.76E-100,0.435547301,2.361887648,1.458690501,m,control,5,5,f1,c,-16.98676191,14.80356943,,,1,,-16.43481581,Inf,0.738471737,2.738471737,1.476943475,20.92707249,20.92707249,12.3 +56,-0.656919662,2.248620658,1,8.00E+15,-5.38E+99,5.83E-100,-0.440890933,1.277235754,0.464273155,f,experimental,1,6,f2,m,-32.34628474,8.247581677,,,1,,11.79509032,Inf,0.754113413,2.754113413,1.508226826,7.41450701,7.41450701,12.3 +57,0.260454418,4.279672814,0,0.037113115,-2.17E+99,-9.45E-100,-1.602644626,0.963233262,1.892438271,f,control,2,7,f1,d,0.451974986,-38.22842921,,,1,,25.67878301,Inf,0.684338249,2.684338249,1.368676499,0.197014145,0.197014145,12.3 +58,0.092206944,0.849437567,0,3.03E-11,-5.74E+99,-6.37E-100,0.488347655,-0.92409465,-1.107328768,m,experimental,3,8,f2,j,-1.984585065,21.37372726,,,1,,-26.56105033,Inf,0.763499072,2.763499072,1.526998143,8.010464244,8.010464244,12.3 +59,-0.0767995,1.68140103,0,4.61E-22,5.71E+99,-7.84E-100,5.7,-0.328788884,0.765559844,f,control,4,9,f1,y,8.052450308,,,,1,,30.89992274,Inf,0.843919117,2.843919117,1.687838235,3.893310436,3.893310436,12.3 +60,0.284253602,2.563488535,0,6.71E-18,-5.49E+99,9.94E-100,-0.199209337,-0.614385435,-0.468164112,m,experimental,5,10,f2,g,-9.245006147,-4.16753873,,,,,-7.803536699,Inf,0.72013878,2.72013878,1.440277559,9.851298775,9.851298775,12.3 +61,0.972104397,1.255015115,0,0.02922171,4.57E+99,-2.60E-100,0.734678153,0.882268499,-0.051912676,m,control,1,11,f1,f,-13.79539297,,-21.05597816,,,,26.07333913,Inf,0.733252493,2.733252493,1.466504987,27.54739748,27.54739748,12.3 +62,-1.375547175,1.333092118,0,7.25E-26,1.95E+99,-8.29E-100,0.191952071,-0.61508922,-0.255179814,f,experimental,2,12,f2,b,14.90191342,21.74813188,-5.761227735,,0,,0.047147038,Inf,0.699404524,2.699404524,1.398809047,24.8250967,24.8250967,12.3 +63,-1.627592736,1.478328803,1,9.81E+46,4.34E+98,2.76E-100,0.951021036,-0.233919845,1.765082916,f,control,3,13,f1,r,40.55177378,,,,0,,-25.21252526,Inf,0.687269622,2.687269622,1.374539244,11.10667539,11.10667539,12.3 +64,2.179421126,2.674861547,1,1.90E+12,-8.00E+99,-1.21E-100,-0.12373379,0.125705487,-0.716611431,m,experimental,4,14,f2,w,37.27318614,25.43540058,,,1,,-10.13829937,Inf,0.565707078,2.565707078,1.131414156,1.720398897,1.720398897,12.3 +65,0.376149862,0.432771654,1,1.82E-07,6.50E+99,1.69E-100,-1.111496413,0.75460153,-0.386964684,m,control,5,15,f1,t,-11.1602374,4.292728936,31.63156258,,,,,Inf,0.688885545,2.688885545,1.37777109,21.90849398,21.90849398,12.3 +66,-1.144123942,2.692449102,1,0.009103734,-5.20E+99,9.69E-100,0.795501903,-0.916583292,-0.700729698,f,experimental,1,16,f2,s,40.89152002,50.93755334,,,,,1.945479714,Inf,0.673945048,2.673945048,1.347890096,9.618616708,9.618616708,12.3 +67,1.889051803,0.862784728,1,2.67E+47,-8.71E+99,-3.93E-100,-0.05334565,-0.838739629,-0.327938549,m,control,2,17,f1,w,23.25180016,-7.708338532,,,1,,2.40498707,Inf,0.721324295,2.721324295,1.442648591,8.150790987,8.150790987,12.3 +68,0.176474657,3.999781721,0,1.11E-07,-3.60E+99,-4.51E-100,-1.520094148,-1.044104412,-0.893630608,f,experimental,3,18,f2,m,,23.94322819,,,,,26.67366838,Inf,0.561952238,2.561952238,1.123904475,48.06656736,48.06656736,12.3 +69,-0.667823773,4.661099397,0,29946.53013,5.97E+99,7.86E-100,1.5008575,1.835611751,2.130133368,f,control,4,19,f1,o,35.52541498,37.88150118,-16.87864345,,1,,,Inf,0.487838809,2.487838809,0.975677618,5.430236147,5.430236147,12.3 +70,0.570675169,4.949013358,0,2.42E-16,4.46E+99,3.20E-100,-0.337265933,1.257452217,0.465795486,m,experimental,5,20,f2,x,9.557958862,2.621664702,,,0,,9.211564035,Inf,0.531128923,2.531128923,1.062257846,58.16481289,58.16481289,12.3 +71,-0.881899561,1.792365981,1,1.84E+40,-3.25E+99,-5.13E-101,0.087851546,-1.004617321,-0.753844325,f,control,1,21,f1,z,41.20062693,15.76586814,34.91209272,,,,,Inf,0.687233474,2.687233474,1.374466948,5.466777644,5.466777644,12.3 +72,-0.801894546,0.683131832,0,1.33E-21,1.89E+99,1.17E-100,-0.539954703,-0.167033164,-0.499094509,m,experimental,2,22,f2,m,24.67674538,,4.100531341,,1,,33.32843989,Inf,0.678345322,2.678345322,1.356690644,0.211640329,0.211640329,12.3 +73,-0.120997408,0.343003988,1,3.42E-07,7.65E+99,4.28E-100,1.120564996,-0.246003096,0.140877166,f,control,3,23,f1,h,1.061635707,33.32318658,,,1,,48.54918845,Inf,0.565085458,2.565085458,1.130170917,4.725582498,4.725582498,12.3 +74,-0.937671609,2.029515062,0,4.54E-08,-8.96E+99,-9.44E-100,-0.547097953,0.440896777,-0.003659941,m,experimental,4,24,f2,q,-8.666785017,-32.93533803,,,0,,31.83812445,Inf,0.682553643,2.682553643,1.365107287,9.065711464,9.065711464,12.3 +75,-2.15616121,2.231032155,0,2.07E+37,-5.84E+99,-1.79E-100,1.184352504,0.399083534,-1.333467086,f,control,5,25,f1,j,-16.22418308,-37.27169159,,,1,,16.92271037,Inf,0.507997006,2.507997006,1.015994012,20.76629463,20.76629463,12.3 +76,0.441266475,1.800714959,0,2.28E-11,-7.03E+99,-6.95E-100,-0.424653255,1.085484471,0.184361022,m,experimental,1,26,f2,a,28.56596845,,,,1,,6.075765038,Inf,0.761748559,2.761748559,1.523497119,25.86267557,25.86267557,12.3 +77,-0.712944476,1.294544523,1,1.18E-13,-2.52E+99,6.20E-100,2.797608158,-0.186281719,1.191267816,f,control,2,27,f1,m,58.3438749,12.79755723,,,1,,24.82786846,Inf,0.758175022,2.758175022,1.516350044,2.230258842,2.230258842,12.3 +78,0.503236412,0.934617004,0,2.99E+49,6.34E+99,-1.94E-100,1.333281907,0.831242032,0.813489745,m,experimental,3,28,f2,f,25.17760652,38.54814123,,,1,,35.73968397,Inf,0.747018421,2.747018421,1.494036842,17.35546794,17.35546794,12.3 +79,-1.352650303,8.768291675,0,1.22E-31,4.60E+99,-8.60E-100,-0.070558974,-0.337926213,-0.413833871,m,control,4,29,f1,t,-40.14831628,25.13557785,,,1,,21.48868763,Inf,0.629427634,2.629427634,1.258855267,14.00530378,14.00530378,12.3 +80,0.259356367,3.491491238,0,340227.7108,2.84E+99,-1.14E-100,-1.314625747,-0.035583912,1.13960029,m,experimental,5,30,f2,c,30.55579311,,25.39075658,,1,,38.94721253,Inf,0.694269237,2.694269237,1.388538473,1.853272735,1.853272735,12.3 +81,-0.934349142,2.403076495,0,1.85E-20,-1.34E+99,8.19E-100,-0.946906667,-0.876635575,-0.394914455,m,control,1,31,f1,t,-49.21614118,-15.59242229,,,1,,51.92014548,Inf,0.678784917,2.678784917,1.357569834,16.34066342,16.34066342,12.3 +82,0.518141224,1.711351491,0,7259386.785,-7.76E+99,8.23E-100,-0.87197756,0.242603932,-2.709936005,m,experimental,2,32,f2,d,39.49936214,,,,0,,24.98712874,Inf,0.600199885,2.600199885,1.20039977,53.17142645,53.17142645,12.3 +83,2.958797116,0.781081083,0,6.71E+13,4.62E+99,8.32E-100,12,0.475305793,0.777086628,f,control,3,33,f1,b,54.04293202,-27.14959186,,,1,,-36.71891581,Inf,0.56663707,2.56663707,1.133274141,7.493237606,7.493237606,12.3 +84,-0.118805371,1.125291522,1,1.36E-15,-4.08E+99,-2.06E-100,-1.589177705,1.922957002,-0.166163139,m,experimental,4,34,f2,f,6.362484276,-23.45857139,,,0,,,Inf,0.699231378,2.699231378,1.398462756,2.078883849,2.078883849,12.3 +85,-0.805832374,0.43534484,1,1.12E-15,-6.32E+99,7.01E-100,-1.08767037,-0.864830262,0.11573855,f,control,5,35,f1,b,23.68813974,,,,0,,21.12029096,Inf,0.702445078,2.702445078,1.404890156,3.16479117,3.16479117,12.3 +86,-0.096001487,2.236351222,1,1.33E+35,-2.17E+99,-4.90E-100,1.9003493,-1.50569819,-1.558703131,f,experimental,1,36,f2,i,-21.46913233,,,,0,,-11.41658279,Inf,0.799151871,2.799151871,1.598303742,6.252009424,6.252009424,12.3 +87,0.239571257,0.636380241,0,4.56E+11,5.62E+99,4.28E-100,0.497966746,0.290460747,-0.004748574,m,control,2,37,f1,o,-7.895855523,4.844530415,,,1,,43.90869498,Inf,0.68889492,2.68889492,1.377789839,8.378574001,8.378574001,12.3 +88,-0.199426499,5.869967659,1,0.404686533,-7.33E+99,5.30E-100,0.314781235,-1.151350671,-1.094781613,m,experimental,3,38,f2,f,43.29461563,,,,1,,7.78832157,Inf,0.550942502,2.550942502,1.101885004,13.73741003,13.73741003,12.3 +89,-0.805996397,1.268093974,1,33.46701836,-1.60E+99,-4.09E-100,1.783908111,1.06322576,1.255144556,m,control,4,39,f1,d,-23.70390365,,,,0,,5.924135526,Inf,0.654394642,2.654394642,1.308789284,13.20115916,13.20115916,12.3 +90,-0.707972381,1.710853925,0,0.000189243,-2.90E+98,2.49E-100,-0.496077535,0.645660111,-0.097987678,f,experimental,5,40,f2,i,-36.82168652,16.89675221,,,0,,45.41756515,Inf,0.636740024,2.636740024,1.273480047,1.613181883,1.613181883,12.3 +91,-1.625143884,1.78856175,0,5.20E-34,7.42E+99,-5.59E-100,-0.968971249,2.263460985,1.955082542,f,control,1,41,f1,z,-56.19342872,,18.95203462,,,,,Inf,0.570627192,2.570627192,1.141254385,5.389407967,5.389407967,12.3 +92,-0.648908102,1.314785303,1,1.43E-12,1.89E+99,-8.53E-100,-0.918706246,-1.339377181,0.457211285,f,experimental,2,42,f2,e,14.40925333,,-22.60679192,,,,,Inf,0.495749838,2.495749838,0.991499677,8.377217386,8.377217386,12.3 +93,-0.051036508,2.035091245,1,281634780.2,-8.89E+99,9.64E-100,-0.259830143,-1.036964374,-2.417509866,f,control,3,43,f1,x,5.212835789,44.97152935,36.00956513,24.1187081,1,,8.333502869,Inf,0.757810004,2.757810004,1.515620007,1.275822202,1.275822202,12.3 +94,-0.433036966,3.096990053,1,32618642448,-1.36E+99,6.61E-100,0.597605669,0.793807358,1.274912805,f,experimental,4,44,f2,a,-13.17381705,,,,1,,40.0390802,Inf,0.82636797,2.82636797,1.652735939,25.99118845,25.99118845,12.3 +95,-0.398710373,0.820566944,1,5.50E-22,2.57E+99,-8.08E-100,0.930721996,-1.508132028,-0.354674221,f,control,5,45,f1,z,-36.23515279,-3.027361501,,,1,,19.71146144,Inf,0.75677294,2.75677294,1.513545881,18.38902919,18.38902919,12.3 +96,0.337436519,5.539742862,0,4.21E-21,5.97E+98,-5.14E-100,0.522670913,-0.507807907,-1.066068935,m,experimental,1,46,f2,f,-48.99978309,16.68448256,,,,,27.47115607,Inf,0.662298439,2.662298439,1.324596877,9.893418768,9.893418768,12.3 +97,-0.434493855,0.540298922,1,6.00E-26,5.77E+98,-3.69E-100,-0.921371121,0.361178166,-1.327338048,f,control,2,47,f1,u,2.878536633,20.0129414,,,1,,-3.416596104,Inf,0.602703674,2.602703674,1.205407348,2.66166856,2.66166856,12.3 +98,-0.443990603,0.479334111,0,1.22E-06,-3.79E+99,5.88E-100,-0.725693462,0.817098677,0.127761789,f,experimental,3,48,f2,z,-14.26476856,-40.50763657,,,1,,,Inf,0.807596206,2.807596206,1.615192412,6.540878081,6.540878081,12.3 +99,-1.030775205,3.015264007,1,3.61E+35,6.66E+98,-6.07E-100,0.124421245,-1.345254585,-0.456583351,m,control,4,49,f3,r,40.20161446,43.54728062,,,0,,28.32081039,Inf,0.584414672,2.584414672,1.168829344,0.43232324,0.43232324,12.3 +100,0.544538215,1.236351257,0,1.61E+34,2.83E+99,-3.75E-101,1.162498447,1.43303512,0.568722799,f,experimental,5,50,totallyridiculoussuperlongfactorme,s,3.309375769,-21.40626084,,,,,32.97384623,Inf,0.690641762,2.690641762,1.381283524,6.381575258,6.381575258,12.3 diff --git a/JASP-Tests/R/tests/figs/Anova/anova-descriptives-ci.svg b/JASP-Tests/R/tests/figs/Anova/anova-descriptives-ci.svg new file mode 100644 index 0000000000..d62786ace3 --- /dev/null +++ b/JASP-Tests/R/tests/figs/Anova/anova-descriptives-ci.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-1.5 +1.0 + + + + +0 +1 +contBinom +contNormal + +facFive + + + + + +1 +2 +3 +4 +5 +Anova-descriptives-ci + diff --git a/JASP-Tests/R/tests/figs/Anova/anova-descriptives-se.svg b/JASP-Tests/R/tests/figs/Anova/anova-descriptives-se.svg new file mode 100644 index 0000000000..46841f2834 --- /dev/null +++ b/JASP-Tests/R/tests/figs/Anova/anova-descriptives-se.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-1.5 +1.0 + + + + +0 +1 +contBinom +contNormal + +facFive + + + + + +1 +2 +3 +4 +5 +Anova-descriptives-se + diff --git a/JASP-Tests/R/tests/figs/Anova/anova-q-q.svg b/JASP-Tests/R/tests/figs/Anova/anova-q-q.svg new file mode 100644 index 0000000000..a3b5c671f3 --- /dev/null +++ b/JASP-Tests/R/tests/figs/Anova/anova-q-q.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-2 +0 +2 + + + + + + + + + +-2 +-1 +0 +1 +2 +Theoretical Quantiles +Standardized Residuals + diff --git a/JASP-Tests/R/tests/figs/BinomialTest/binomialtest-descriptives-1.svg b/JASP-Tests/R/tests/figs/BinomialTest/binomialtest-descriptives-1.svg new file mode 100644 index 0000000000..6940e30a09 --- /dev/null +++ b/JASP-Tests/R/tests/figs/BinomialTest/binomialtest-descriptives-1.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + +0.0 +0.5 +1.0 + + + + +0 +BinomialTest-descriptives-1 + diff --git a/JASP-Tests/R/tests/figs/BinomialTest/binomialtest-descriptives-2.svg b/JASP-Tests/R/tests/figs/BinomialTest/binomialtest-descriptives-2.svg new file mode 100644 index 0000000000..cae789a8a8 --- /dev/null +++ b/JASP-Tests/R/tests/figs/BinomialTest/binomialtest-descriptives-2.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + +0.0 +0.5 +1.0 + + + + +1 +BinomialTest-descriptives-2 + diff --git a/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-prior-posterior-1.svg b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-prior-posterior-1.svg new file mode 100644 index 0000000000..17241b959b --- /dev/null +++ b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-prior-posterior-1.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +0 +0.2 +0.4 +0.6 +0.8 +1 + + + + + + + + +0.0 +2.0 +4.0 +6.0 +8.0 +10.0 +12.0 +Density +Population proportion + +θ + + + + + + + + + + + + + + + +B +F +10 += +0.444 +B +F +0 +1 += +2.252 +median = 0.579 +95% CI: [0.482, 0.672] + + +data|H0 + + +Posterior +Prior + diff --git a/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-prior-posterior-2.svg b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-prior-posterior-2.svg new file mode 100644 index 0000000000..4686b59f51 --- /dev/null +++ b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-prior-posterior-2.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +0 +0.2 +0.4 +0.6 +0.8 +1 + + + + + + + + +0.0 +2.0 +4.0 +6.0 +8.0 +10.0 +12.0 +Density +Population proportion + +θ + + + + + + + + + + + + + + + +B +F +10 += +0.444 +B +F +0 +1 += +2.252 +median = 0.421 +95% CI: [0.328, 0.518] + + +data|H0 + + +Posterior +Prior + diff --git a/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-sequential-analysis-1.svg b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-sequential-analysis-1.svg new file mode 100644 index 0000000000..afab18c84c --- /dev/null +++ b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-sequential-analysis-1.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 +120 + + + + + + + +1/10 +1/3 +1 +3 +10 +30 +Anecdotal +Moderate +Strong +Anecdotal +Moderate + + + + + + + +B +F +1 +0 +n + + +Evidence for H1 + + +Evidence for H0 +B +F +10 += +0.444 +B +F +0 +1 += +2.252 + + +data|H0 + +Evidence for H0: + Anecdotal + diff --git a/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-sequential-analysis-2.svg b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-sequential-analysis-2.svg new file mode 100644 index 0000000000..afab18c84c --- /dev/null +++ b/JASP-Tests/R/tests/figs/BinomialTestBayesian/binomialtestbayesian-sequential-analysis-2.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 +120 + + + + + + + +1/10 +1/3 +1 +3 +10 +30 +Anecdotal +Moderate +Strong +Anecdotal +Moderate + + + + + + + +B +F +1 +0 +n + + +Evidence for H1 + + +Evidence for H0 +B +F +10 += +0.444 +B +F +0 +1 += +2.252 + + +data|H0 + +Evidence for H0: + Anecdotal + diff --git a/JASP-Tests/R/tests/figs/ContingencyTablesBayesian/contingencytablesbayesian-log-odds-ratio.svg b/JASP-Tests/R/tests/figs/ContingencyTablesBayesian/contingencytablesbayesian-log-odds-ratio.svg new file mode 100644 index 0000000000..78db802d03 --- /dev/null +++ b/JASP-Tests/R/tests/figs/ContingencyTablesBayesian/contingencytablesbayesian-log-odds-ratio.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +-2.0 +-1.5 +-1.0 +-0.5 +0.0 +0.5 +1.0 + + + + + + + + +0.0 +0.2 +0.4 +0.6 +0.8 +1.0 +1.2 +Density +Log odds ratio + + + +B +F +10 += +0.334 +B +F +0 +1 += +2.994 +median Log OR = -0.325 +95% CI: [-1.116, 0.456] + + +data|H0 + diff --git a/JASP-Tests/R/tests/figs/Correlation/correlation-correlation-matrix.svg b/JASP-Tests/R/tests/figs/Correlation/correlation-correlation-matrix.svg new file mode 100644 index 0000000000..4fa6973aa1 --- /dev/null +++ b/JASP-Tests/R/tests/figs/Correlation/correlation-correlation-matrix.svg @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +2 +4 +6 +8 +10 + +Density + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-4 +-2 +0 +2 +4 + + + + + + + +0e+00 +2 +4 +6 +8 +10 + + + + + + + + + + + + + + + +r += +-0.059 +95% CI: [-0.253, 0.139] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-4 +-2 +0 +2 +4 + +Density + + + + + + + + + + + +contGamma +contGamma +contNormal +contNormal + diff --git a/JASP-Tests/R/tests/figs/CorrelationBayesian/correlationbayesian-correlation.svg b/JASP-Tests/R/tests/figs/CorrelationBayesian/correlationbayesian-correlation.svg new file mode 100644 index 0000000000..893b7be796 --- /dev/null +++ b/JASP-Tests/R/tests/figs/CorrelationBayesian/correlationbayesian-correlation.svg @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 + +Density + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 + + + + + + + + +-3e+00 +-2e+00 +-1e+00 +0e+00 +1 +2 +3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-1 +-0.75 +-0.25 +0 +0.25 +0.5 +0.75 +1 + +Density +ρ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 + +Density + + + + + + + + + + + +contcor1 +contcor1 +contcor2 +contcor2 + diff --git a/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-prior-posterior.svg b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-prior-posterior.svg new file mode 100644 index 0000000000..237a515c21 --- /dev/null +++ b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-prior-posterior.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-1 +-0.75 +-0.5 +-0.25 +0 +0.25 +0.5 +0.75 +1 + + + + + + + +0.0 +2.0 +4.0 +6.0 +8.0 +10.0 +Density +Population correlation + +ρ + + + + + + + + + + + + + + + +B +F +10 += +7.661e+10 +B +F +0 +1 += +1.305e-11 +median = 0.646 +95% CI: [0.522, 0.751] + + +data|H0 + + +Posterior +Prior + diff --git a/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-robustness-check.svg b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-robustness-check.svg new file mode 100644 index 0000000000..aef8095036 --- /dev/null +++ b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-robustness-check.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +0.5 +1 +1.5 +2 + + + + + + + + + + +1/100 +1 +100 +10000 +1e+06 +1e+08 +1e+10 +1e+12 +1e+14 +B +F +1 +0 +Stretched beta prior width + + +Evidence for H1 + + +Evidence for H0 + + diff --git a/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-scatterplot.svg b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-scatterplot.svg new file mode 100644 index 0000000000..45e15d8d00 --- /dev/null +++ b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-scatterplot.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 +contcor1 +contcor2 + diff --git a/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-sequential-analysis.svg b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-sequential-analysis.svg new file mode 100644 index 0000000000..fca8cdb80a --- /dev/null +++ b/JASP-Tests/R/tests/figs/CorrelationBayesianPairs/correlationbayesianpairs-sequential-analysis.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 +120 + + + + + + + + + +1/100 +1 +100 +10000 +1e+06 +1e+08 +1e+10 +1e+12 +B +F +1 +0 +n + + +Evidence for H1 + + +Evidence for H0 +B +F +10 += +7.661e+10 +B +F +0 +1 += +1.305e-11 + + +data|H0 + +Evidence for H1: + Extreme + diff --git a/JASP-Tests/R/tests/figs/Descriptives/descriptives-boxplot.svg b/JASP-Tests/R/tests/figs/Descriptives/descriptives-boxplot.svg new file mode 100644 index 0000000000..782a6dcd9e --- /dev/null +++ b/JASP-Tests/R/tests/figs/Descriptives/descriptives-boxplot.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +25 +49 +55 +83 + + + + + + +-4 +-3 +-2 +-1 +0 +1 +2 +3 +4 + + + + + + + + + + + +0 +1 +contBinom +contNormal +Descriptives-boxplot + diff --git a/JASP-Tests/R/tests/figs/Descriptives/descriptives-correlation.svg b/JASP-Tests/R/tests/figs/Descriptives/descriptives-correlation.svg new file mode 100644 index 0000000000..c3b9209083 --- /dev/null +++ b/JASP-Tests/R/tests/figs/Descriptives/descriptives-correlation.svg @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-4 +-2 +0 +2 +4 + +Density + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +2 +4 +6 +8 +10 + + + + + + +-4 +-2 +0 +2 +4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +2 +4 +6 +8 +10 + +Density + + + + + + + + + + + +contNormal +contNormal +contGamma +contGamma + diff --git a/JASP-Tests/R/tests/figs/Descriptives/descriptives-distribution.svg b/JASP-Tests/R/tests/figs/Descriptives/descriptives-distribution.svg new file mode 100644 index 0000000000..7c7f26a398 --- /dev/null +++ b/JASP-Tests/R/tests/figs/Descriptives/descriptives-distribution.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-4 +-2 +0 +2 +4 +contNormal + +Density + + + + + + + diff --git a/JASP-Tests/R/tests/figs/ExploratoryFactorAnalysis/exploratoryfactoranalysis-path-diagram.svg b/JASP-Tests/R/tests/figs/ExploratoryFactorAnalysis/exploratoryfactoranalysis-path-diagram.svg new file mode 100644 index 0000000000..8bdf085205 --- /dev/null +++ b/JASP-Tests/R/tests/figs/ExploratoryFactorAnalysis/exploratoryfactoranalysis-path-diagram.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +F1 +F2 +facFifty +contExpon +contWide +contcor1 + diff --git a/JASP-Tests/R/tests/figs/PrincipalComponentAnalysis/principalcomponentanalysis-path-diagram.svg b/JASP-Tests/R/tests/figs/PrincipalComponentAnalysis/principalcomponentanalysis-path-diagram.svg new file mode 100644 index 0000000000..587789742d --- /dev/null +++ b/JASP-Tests/R/tests/figs/PrincipalComponentAnalysis/principalcomponentanalysis-path-diagram.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + +RC1 +contNormal +contGamma + diff --git a/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-covariates.svg b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-covariates.svg new file mode 100644 index 0000000000..69c29ab86a --- /dev/null +++ b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-covariates.svg @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +2 +4 +6 +8 +10 + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 +4 +contGamma +Residuals + + + + + + + +-2 +-1 +0 +1 +2 +3 +Standardized Residuals + diff --git a/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-dependent.svg b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-dependent.svg new file mode 100644 index 0000000000..92f94fa9c6 --- /dev/null +++ b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-dependent.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-4 +-2 +0 +2 +4 + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 +4 +contNormal +Residuals + + + + + + + +-2 +-1 +0 +1 +2 +3 +Standardized Residuals + diff --git a/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-histogram.svg b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-histogram.svg new file mode 100644 index 0000000000..fd51b313a5 --- /dev/null +++ b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-histogram.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 +4 +Standardized Residuals + +Density + + + + + + + diff --git a/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-predicted.svg b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-predicted.svg new file mode 100644 index 0000000000..e1db6918a0 --- /dev/null +++ b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-predicted.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.5 +-0.4 +-0.3 +-0.2 +-0.1 + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 +4 +Predicted Values +Residuals + + + + + + + +-2 +-1 +0 +1 +2 +3 +Standardized Residuals + diff --git a/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-q-q.svg b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-q-q.svg new file mode 100644 index 0000000000..a8c6a4326b --- /dev/null +++ b/JASP-Tests/R/tests/figs/RegressionLinear/regressionlinear-residuals-q-q.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 + + + + + + + + + +-3 +-2 +-1 +0 +1 +2 +3 +4 +Theoretical Quantiles +Standardized Residuals + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-descriptives.svg b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-descriptives.svg new file mode 100644 index 0000000000..f6e2cf39cf --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-descriptives.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.6 +0.2 + + + + +0 +1 +contBinom +contNormal +TTestBayesianIndependentSamples-descriptives + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-prior-posterior.svg b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-prior-posterior.svg new file mode 100644 index 0000000000..24c04b8421 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-prior-posterior.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + +-2.0 +-1.0 +0.0 +1.0 +2.0 + + + + + + + + +0.0 +0.5 +1.0 +1.5 +2.0 +2.5 +3.0 +Density +Effect size + +δ + + + + + + + + + + + + + + + +B +F +10 += +0.276 +B +F +0 +1 += +3.629 +median = 0.136 +95% CI: [-0.234, 0.515] + + +data|H0 + + +Posterior +Prior + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-robustness-check.svg b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-robustness-check.svg new file mode 100644 index 0000000000..e608c1f612 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-robustness-check.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +0.25 +0.5 +0.75 +1 +1.25 +1.5 + + + + + + +1/30 +1/10 +1/3 +1 +3 +Anecdotal +Anecdotal +Moderate +Strong + + + + + + +B +F +1 +0 +Cauchy prior width + + +Evidence for H1 + + +Evidence for H0 + + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-sequential-analysis.svg b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-sequential-analysis.svg new file mode 100644 index 0000000000..0ac66f4a42 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianIndependentSamples/ttestbayesianindependentsamples-sequential-analysis.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 +120 + + + + + + +1/30 +1/10 +1/3 +1 +3 +Anecdotal +Anecdotal +Moderate +Strong + + + + + + +B +F +1 +0 +n + + +Evidence for H1 + + +Evidence for H0 +B +F +10 += +0.276 +B +F +0 +1 += +3.629 + + +data|H0 + + + + + +user prior +wide prior +ultrawide prior + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-descriptives.svg b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-descriptives.svg new file mode 100644 index 0000000000..e293517039 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-descriptives.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + +-0.4 +0.0 +0.0 + + + +TTestBayesianOneSample-descriptives + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-prior-posterior.svg b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-prior-posterior.svg new file mode 100644 index 0000000000..85014164ab --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-prior-posterior.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + +-2.0 +-1.0 +0.0 +1.0 +2.0 + + + + + + + +0.0 +1.0 +2.0 +3.0 +4.0 +5.0 +Density +Effect size + +δ + + + + + + + + + + + + + + + +B +F +10 += +0.508 +B +F +0 +1 += +1.968 +median = -0.173 +95% CI: [-0.367, 0.021] + + +data|H0 + + +Posterior +Prior + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-robustness-check.svg b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-robustness-check.svg new file mode 100644 index 0000000000..b1b58d5ac0 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-robustness-check.svg @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +0.25 +0.5 +0.75 +1 +1.25 +1.5 + + + + + + + +1/30 +1/10 +1/3 +1 +3 +10 +Anecdotal +Moderate +Anecdotal +Moderate +Strong + + + + + + + +B +F +1 +0 +Cauchy prior width + + +Evidence for H1 + + +Evidence for H0 + + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-sequential-analysis.svg b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-sequential-analysis.svg new file mode 100644 index 0000000000..aff670c9d8 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianOneSample/ttestbayesianonesample-sequential-analysis.svg @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 +120 + + + + + + +1/30 +1/10 +1/3 +1 +3 +Anecdotal +Anecdotal +Moderate +Strong + + + + + + +B +F +1 +0 +n + + +Evidence for H1 + + +Evidence for H0 +B +F +10 += +0.508 +B +F +0 +1 += +1.968 + + +data|H0 + + + + + +user prior +wide prior +ultrawide prior + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-descriptives.svg b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-descriptives.svg new file mode 100644 index 0000000000..b781617e03 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-descriptives.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.5 +2.5 + + + + +contGamma +contNormal +TTestBayesianPairedSamples-descriptives + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-prior-posterior.svg b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-prior-posterior.svg new file mode 100644 index 0000000000..1bfaccc196 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-prior-posterior.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +-3.0 +-2.0 +-1.0 +0.0 +1.0 +2.0 + + + + + + + + +0.0 +0.5 +1.0 +1.5 +2.0 +2.5 +3.0 +Density +Effect size + +δ + + + + + + + + + + + + + + + +B +F +10 += +1.429e+17 +B +F +0 +1 += +6.999e-18 +median = -1.617 +95% CI: [-1.941, -1.308] + + +data|H0 + + +Posterior +Prior + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-robustness-check.svg b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-robustness-check.svg new file mode 100644 index 0000000000..7835bf1654 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-robustness-check.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +0.25 +0.5 +0.75 +1 +1.25 +1.5 + + + + + + + + + +1/10000 +1 +10000 +1e+08 +1e+12 +1e+16 +1e+20 +1e+24 +B +F +1 +0 +Cauchy prior width + + +Evidence for H1 + + +Evidence for H0 + + diff --git a/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-sequential-analysis.svg b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-sequential-analysis.svg new file mode 100644 index 0000000000..d262cc44c5 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestBayesianPairedSamples/ttestbayesianpairedsamples-sequential-analysis.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +0 +20 +40 +60 +80 +100 +120 + + + + + + + + + +1/10000 +1 +10000 +1e+08 +1e+12 +1e+16 +1e+20 +1e+24 +B +F +1 +0 +n + + +Evidence for H1 + + +Evidence for H0 +B +F +10 += +1.429e+17 +B +F +0 +1 += +6.999e-18 + + +data|H0 + + + + + +wide prior +ultrawide prior +user prior + diff --git a/JASP-Tests/R/tests/figs/TTestIndependentSamples/ttestindependentsamples-descriptives.svg b/JASP-Tests/R/tests/figs/TTestIndependentSamples/ttestindependentsamples-descriptives.svg new file mode 100644 index 0000000000..99bf4f903e --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestIndependentSamples/ttestindependentsamples-descriptives.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.6 +0.2 + + + + +0 +1 +contBinom +contNormal +TTestIndependentSamples-descriptives + diff --git a/JASP-Tests/R/tests/figs/TTestOneSample/ttestonesample-descriptives.svg b/JASP-Tests/R/tests/figs/TTestOneSample/ttestonesample-descriptives.svg new file mode 100644 index 0000000000..beca449517 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestOneSample/ttestonesample-descriptives.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + +0.0 +0.0 +2.5 + + + +TTestOneSample-descriptives + diff --git a/JASP-Tests/R/tests/figs/TTestPairedSamples/ttestpairedsamples-descriptives.svg b/JASP-Tests/R/tests/figs/TTestPairedSamples/ttestpairedsamples-descriptives.svg new file mode 100644 index 0000000000..b8b3a836c7 --- /dev/null +++ b/JASP-Tests/R/tests/figs/TTestPairedSamples/ttestpairedsamples-descriptives.svg @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +-0.5 +2.5 + + + + +contNormal +contGamma +TTestPairedSamples-descriptives + diff --git a/JASP-Tests/R/tests/figs/deps.txt b/JASP-Tests/R/tests/figs/deps.txt new file mode 100644 index 0000000000..bab4350e49 --- /dev/null +++ b/JASP-Tests/R/tests/figs/deps.txt @@ -0,0 +1,6 @@ +Fontconfig: 2.11.94 +FreeType: 2.6.1 +Cairo: 1.14.6 +vdiffr: 0.2.1 +svglite: 1.2.1 +ggplot2: 2.2.1 diff --git a/JASP-Tests/R/tests/testthat.R b/JASP-Tests/R/tests/testthat.R new file mode 100644 index 0000000000..6f7dfc3a2a --- /dev/null +++ b/JASP-Tests/R/tests/testthat.R @@ -0,0 +1,7 @@ +library(jasptools, lib.loc=file.path("..", "..", "..", "Tools")) +library(testthat) +result <- test_dir("testthat") +result <- as.data.frame(result) + +if (sum(result$failed) > 0 || sum(result$error) > 0) + quit(save = "no", status = 1) \ No newline at end of file diff --git a/JASP-Tests/R/tests/testthat/helper-misc.R b/JASP-Tests/R/tests/testthat/helper-misc.R new file mode 100644 index 0000000000..de82deed3e --- /dev/null +++ b/JASP-Tests/R/tests/testthat/helper-misc.R @@ -0,0 +1,11 @@ +initNamespace <- function(ns) { + if (ns %in% loadedNamespaces()) + unloadNamespace(ns) + loadNamespace(ns) +} + +restoreOptions <- function(opts) { + options(opts) # overwrite changed options + addedOpts <- setdiff(names(options()), names(opts)) + options(Map(function(x) NULL, addedOpts)) # remove added options +} diff --git a/JASP-Tests/R/tests/testthat/helper-plots.R b/JASP-Tests/R/tests/testthat/helper-plots.R new file mode 100644 index 0000000000..8fe8cd446d --- /dev/null +++ b/JASP-Tests/R/tests/testthat/helper-plots.R @@ -0,0 +1,3 @@ +expect_equal_plots <- function(test, name, dir) { + vdiffr::expect_doppelganger(paste(dir, name, sep="-"), test, path=dir) +} diff --git a/JASP-Tests/R/tests/testthat/helper-tables.R b/JASP-Tests/R/tests/testthat/helper-tables.R new file mode 100644 index 0000000000..9291804087 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/helper-tables.R @@ -0,0 +1,4 @@ +expect_equal_tables <- function(test, ref, ...) { + test <- jasptools:::collapseTable(test) + expect_equal(test, ref, tolerance=1e-5, ...) +} diff --git a/JASP-Tests/R/tests/testthat/test-ancova.R b/JASP-Tests/R/tests/testthat/test-ancova.R new file mode 100644 index 0000000000..ad5cced9ff --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ancova.R @@ -0,0 +1,266 @@ +context("ANCOVA") + +# does not test +# - descriptives table/plot & Q-Q plot (uses same code as ANOVA) +# - if analysis handles too few observations + +test_that("Main table results match", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$covariates <- "contGamma" + options$wlsWeights <- "facFifty" + options$modelTerms <- list( + list(components="facFive"), + list(components="contGamma") + ) + options$effectSizeEstimates <- TRUE + options$effectSizeEtaSquared <- TRUE + options$effectSizeOmegaSquared <- TRUE + options$effectSizePartialEtaSquared <- TRUE + options$VovkSellkeMPR <- TRUE + + refTables <- list( + type1 = list("facFive", 181.151987151139, 4, 45.2879967877848, 1.86433860843651, + 0.123166554163148, "TRUE", 0.0733818170125722, 0.0735023545150279, + 0.0336895280828883, 1.42623435171942, "contGamma", 4.04832694150032, + 1, 4.04832694150032, 0.166654582934621, 0.684030683889986, "TRUE", + 0.00163991348646033, 0.00176978340871019, 0, 1, "Residual", + 2283.42194856002, 94, 24.2917228570215, "", "", "TRUE", "", + "", "", ""), + type2 = list("facFive", 185.196464516179, 4, 46.2991161290447, 1.90596263597919, + 0.115857414147638, "TRUE", 0.0748974625326393, 0.0750202880830827, + 0.0352547206519188, 1.47317659150752, "contGamma", 4.04832694150036, + 1, 4.04832694150036, 0.166654582934623, 0.684030683889984, "TRUE", + 0.00163723112216545, 0.00176978340871021, 0, 1, "Residual", + 2283.42194856002, 94, 24.2917228570215, "", "", "TRUE", "", + "", "", ""), + type3 = list("facFive", 185.196464516179, 4, 46.2991161290447, 1.9059626359792, + 0.115857414147638, "TRUE", 0.0748974625326393, 0.0750202880830827, + 0.0352547206519188, 1.47317659150752, "contGamma", 4.04832694150036, + 1, 4.04832694150036, 0.166654582934621, 0.684030683889986, "TRUE", + 0.00163723112216545, 0.00176978340871021, 0, 1, "Residual", + 2283.42194856002, 94, 24.2917228570215, "", "", "TRUE", "", + "", "", "") + ) + + for (type in c("type1", "type2", "type3")) { + options$sumOfSquares <- type + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["anova"]][["data"]] + expect_equal_tables(table, refTables[[type]], label=paste("Table with SS", type)) + } +}) + +test_that("Homogeneity of Variances table results match", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$fixedFactors <- "facExperim" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="facExperim"), + list(components="contGamma") + ) + options$homogeneityTests <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["assumptionsObj"]][["levene"]][["data"]] + expect_equal_tables(table, list(2.72159218177061, 1, 98, 0.102201011380302, 1.57819444559362, 1)) +}) + +# Contrasts verified with SPSS +test_that("Contrasts table results match", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="facFive"), + list(components="contGamma") + ) + + refTables <- list( + deviation = list("2 - 1, 2, 3, 4, 5", -0.200720248979633, 0.213572066533121, -0.939824445386938, + 0.349716429527485, "TRUE", "3 - 1, 2, 3, 4, 5", 0.326355030521638, + 0.213419672724688, 1.52917032603005, 0.129580520593874, "FALSE", + "4 - 1, 2, 3, 4, 5", -0.163006179525351, 0.213771994762986, + -0.762523546202018, 0.447656831363019, "FALSE", "5 - 1, 2, 3, 4, 5", + 0.17396802464162, 0.214943819683978, 0.809365093155025, 0.42034917204134, + "FALSE"), + simple = list("2 - 1", -0.0641236223213591, 0.343277644425165, -0.186798130792167, + 0.852221484436515, "TRUE", "3 - 1", 0.462951657179913, 0.342949539026206, + 1.34991188060625, 0.180285987179755, "FALSE", "4 - 1", -0.0264095528670768, + 0.337118098977225, -0.0783391723766838, 0.937724778659558, "FALSE", + "5 - 1", 0.310564651299894, 0.345720813950643, 0.898310540667163, + 0.371315247360673, "FALSE"), + difference = list("2 - 1", -0.0641236223213588, 0.343277644425165, -0.186798130792167, + 0.852221484436515, "TRUE", "3 - 1, 2", 0.495013468340592, 0.292959120347178, + 1.68970151109808, 0.0943992176806134, "FALSE", "4 - 1, 2, 3", + -0.159352231153261, 0.275116843578239, -0.579216557883866, 0.563828556165238, + "FALSE", "5 - 1, 2, 3, 4", 0.217460030802025, 0.268679774604972, + 0.809365093155025, 0.42034917204134, "FALSE"), + Helmert = list("1 - 2, 3, 4, 5", -0.170745783322843, 0.272701151705157, -0.626127840880747, + 0.532748563022963, "TRUE", "2 - 3, 4, 5", -0.313159207525603, + 0.274645898379152, -1.14022896163293, 0.257087871753455, "FALSE", + "3 - 4, 5", 0.320874107963505, 0.291421643235482, 1.10106478160314, + 0.273679968781506, "FALSE", "4 - 5", -0.336974204166971, 0.340503320254199, + -0.98963558979515, 0.324892868709605, "FALSE"), + repeated = list("1 - 2", 0.0641236223213587, 0.343277644425165, 0.186798130792166, + 0.852221484436516, "TRUE", "2 - 3", -0.527075279501272, 0.336088495268646, + -1.56826337979812, 0.120179976824791, "FALSE", "3 - 4", 0.489361210046989, + 0.338686060204421, 1.444881462649, 0.151816532688129, "FALSE", + "4 - 5", -0.336974204166971, 0.340503320254199, -0.98963558979515, + 0.324892868709605, "FALSE"), + polynomial = list("linear", 0.208344567699659, 0.240588115184784, 0.865980298069335, + 0.388705894709638, "TRUE", "quadratic", -0.0572582720504826, + 0.238398138250912, -0.240179191291413, 0.810714351679878, "FALSE", + "cubic", 0.0743566940225005, 0.243521087108506, 0.305339857444745, + 0.760782433052004, "FALSE", "quartic", 0.412402551299919, 0.237982457186854, + 1.73291156068751, 0.0863908131438485, "FALSE") + ) + + contrasts <- c("deviation", "simple", "difference", "Helmert", "repeated", "polynomial") + for (contrast in contrasts) { + options$contrasts <- list(list(contrast=contrast, variable="facFive")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["contrasts"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, refTables[[contrast]], label=paste("Table with contrast", contrast)) + } +}) + +test_that("Post Hoc table results match", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$fixedFactors <- "facExperim" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="facExperim"), + list(components="contGamma") + ) + options$postHocTestEffectSize <- TRUE + options$postHocTestsBonferroni <- TRUE + options$postHocTestsHolm <- TRUE + options$postHocTestsScheffe <- TRUE + options$postHocTestsTukey <- TRUE + options$postHocTestsVariables <- "facExperim" + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["posthoc"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, + list("control", "experimental", -0.0830902357515323, 0.21391801479091, + -0.388420937024623, -0.0388420937024623, 0.698555762823947, + 0.927393971055831, 0.698555762823947, 0.698555762823947, "TRUE") + ) +}) + +test_that("Marginal Means table results match", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$fixedFactors <- "facExperim" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="facExperim"), + list(components="contGamma") + ) + options$marginalMeansCompareMainEffects <- TRUE + options$marginalMeansTerms <- "facExperim" + + refTables <- list( + none = list("control", -0.230293705415766, 0.151049119466849, -0.530084395048618, + 0.0694969842170856, -1.52462792387419, 0.13060580966841, "TRUE", + "experimental", -0.147203469664234, 0.151049119466849, -0.446994159297086, + 0.152587219968618, -0.974540402379113, 0.332212375969363, "FALSE"), + Bonferroni = list("control", -0.230293705415766, 0.151049119466849, -0.530084395048618, + 0.0694969842170856, -1.52462792387419, 0.13060580966841, "TRUE", + "experimental", -0.147203469664234, 0.151049119466849, -0.446994159297086, + 0.152587219968618, -0.974540402379113, 0.332212375969363, "FALSE"), + Sidak = list("control", -0.230293705415766, 0.151049119466849, -0.530084395048618, + 0.0694969842170856, -1.52462792387419, 0.13060580966841, "TRUE", + "experimental", -0.147203469664234, 0.151049119466849, -0.446994159297086, + 0.152587219968618, -0.974540402379113, 0.332212375969363, "FALSE") + ) + + for (adjustment in c("none", "Bonferroni", "Sidak")) { + options$marginalMeansCIAdjustment <- adjustment + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["marginalMeans"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, refTables[[adjustment]], label=paste("Table with CI adjustment", adjustment)) + } +}) + +test_that("Simple Main Effects table results match", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$fixedFactors <- c( "facFive", "facExperim") + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="facExperim"), + list(components="facFive"), + list(components="contGamma") + ) + options$simpleFactor <- "facExperim" + options$moderatorFactorOne <- "facFive" + options$moderatorFactorTwo <- "" + options$homogeneityTests <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("Ancova", "debug.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["simpleEffects"]][["data"]] + expect_equal_tables(table, list(1, 0.350864897951646, 1, 0.350864897951646, 0.307765411627339, + 0.580386465552355, "TRUE", 2, 2.72259751707838, 1, 2.72259751707838, + 2.38815951789705, 0.125653693703876, "FALSE", 3, 0.300954391532799, + 1, 0.300954391532799, 0.263985804028512, 0.608613599742434, + "FALSE", 4, 3.47907983036715, 1, 3.47907983036715, 3.05171717754702, + 0.0839531695276169, "FALSE", 5, 0.313611321775938, 1, 0.313611321775938, + 0.275087984294933, 0.601186887502708, "FALSE")) +}) + + + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "debInf" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Inf dependent check") + + options <- jasptools::analysisOptions("Ancova") + options$dependent <- "contNormal" + options$covariates <- "debInf" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Inf covariate check") + + options$dependent <- "contNormal" + options$covariates <- "" + options$fixedFactors <- "contBinom" + options$wlsWeights <- "debInf" + options$modelTerms <- list(list(components="contBinom")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Inf WLS weights check") + + options$dependent <- "contNormal" + options$fixedFactors <- "debSame" + options$modelTerms <- list(list(components="debSame")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="1-level factor check") + + options$dependent <- "debSame" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="No variance check") + + options$dependent <- "contGamma" + options$fixedFactors <- "facFive" + options$wlsWeights <- "contNormal" + options$modelTerms <- list(list(components="facFive")) + results <- jasptools::run("Ancova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Negative WLS weights check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-ancovabayesian.R b/JASP-Tests/R/tests/testthat/test-ancovabayesian.R new file mode 100644 index 0000000000..8a7513538f --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ancovabayesian.R @@ -0,0 +1,157 @@ +context("Bayesian ANCOVA") + +# does not test +# - descriptives table (code from regular ANOVA) +# - descriptives plot (code from regular ANOVA) +# - bftype (01, 10) + +initOpts <- function() { + options <- jasptools::analysisOptions("AncovaBayesian") + options$sampleMode <- "manual" + options$fixedSamplesNumber <- 50 + return(options) +} + +test_that("Main table results match", { + set.seed(0) + options <- initOpts() + options$dependent <- "contNormal" + options$fixedFactors <- "facGender" + options$randomFactors <- "facFive" + options$covariates <- "contGamma" + options$priorCovariates <- 0.3 + options$priorRandomEffects <- 1.2 + options$modelTerms <- list( + list(components="facGender", isNuisance=FALSE), + list(components="facFive", isNuisance=TRUE), + list(components="contGamma", isNuisance=FALSE) + ) + + refTables <- list( + nullModelTop = list("Null model (incl. facFive)", 0.25, -0.557159597272472, 0.0609616076207224, + 0, "", "facGender", 0.25, -0.293047614582535, 0.493235485474366, + 0.264111982689937, 29.6656710072444, "contGamma", 0.25, -1.12934210184216, + -0.61871766039617, -0.572182504569689, 15.885810482332, "facGender + contGamma", + 0.25, -0.856200286718923, -0.313955333846312, -0.299040689446451, + 9.83211717425022), + bestModelTop = list("facGender", 0.25, -0.267241266752112, 0.547550995086289, 0, "", + "Null model (incl. facFive)", 0.25, -0.581045856142161, 0.0282510445044043, + -0.313804589390049, 10.5414217188718, "facGender + contGamma", + 0.25, -0.904975901109745, -0.370131448423163, -0.637734634357633, + 14.932174588461, "contGamma", 0.25, -1.13850449013975, -0.628606544880642, + -0.871263223387639, 15.235554204653) + ) + + for (order in c("nullModelTop", "bestModelTop")) { + options$bayesFactorOrder <- order + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["model comparison"]][["data"]] + expect_equal_tables(table, refTables[[order]], label=paste("Table with order", order)) + } +}) + +test_that("Effects table results match", { + set.seed(0) + options <- initOpts() + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$fixedFactors <- "contBinom" + options$effects <- TRUE + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE), + list(components="contBinom", isNuisance=FALSE), + list(components=c("contGamma", "contBinom"), isNuisance=FALSE) + ) + + refTables <- list( + allModels = list("contGamma", 0.6, 0.226438035053417, 0.195147508378382, "contBinom", + 0.6, 0.244646736629283, 0.215922578651091, "contGammacontBinom", + 0.2, 0.0356936478531283, 0.148059370442442), + matchedModels = list("contGamma", 0.4, 0.193766080181001, 0.251463756140853, "contBinom", + 0.4, 0.211903947712595, 0.281631799589681, "contGammacontBinom", + 0.2, 0.0356812041725066, 0.784742840790345) + ) + + for (effectsType in c("allModels", "matchedModels")) { + options$effectsType <- effectsType + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["effects"]][["data"]] + expect_equal_tables(table, refTables[[effectsType]], label=paste("Table with effects type", effectsType)) + } +}) + +test_that("Post-hoc Comparisons table results match", { + options <- jasptools::analysisOptions("AncovaBayesian") + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$modelTerms <- list( + list(components="facFive", isNuisance=FALSE) + ) + options$postHocTestsNullControl <- TRUE + options$postHocTestsVariables <- "facFive" + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["posthoc"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, + list(1, 2, 0.319507910772894, 0.0997312866070229, -0.505650193633655, + 0.00713501139221108, "TRUE", 1, 3, 0.319507910772894, 0.260338331517325, + -0.0889434982573415, 0.00346528957238797, "FALSE", 1, 4, 0.319507910772894, + 0.0988240290518637, -0.509619059344969, 0.0071287698725277, + "FALSE", 1, 5, 0.319507910772894, 0.139031227413715, -0.361369258553702, + 0.00848479926592481, "FALSE", 2, 3, 0.319507910772894, 0.30046754229221, + -0.0266840507861397, 0.00368467308944596, "FALSE", 2, 4, 0.319507910772894, + 0.0989443005428758, -0.509090832692873, 0.00712946511175494, + "FALSE", 2, 5, 0.319507910772894, 0.151606948038875, -0.323762510268505, + 0.00859149880568525, "FALSE", 3, 4, 0.319507910772894, 0.23744955199206, + -0.12891026091494, 0.0042533257083258, "FALSE", 3, 5, 0.319507910772894, + 0.104702418542221, -0.484524901778361, 0.00721167204576887, + "FALSE", 4, 5, 0.319507910772894, 0.138002738227672, -0.364593911742112, + 0.00846064110496598, "FALSE") + ) +}) + +test_that("Analysis handles errors", { + options <- initOpts() + options$dependent <- "debInf" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive", isNuisance=FALSE)) + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Inf dependent check") + + options$dependent <- "contNormal" + options$fixedFactors <- list() + options$covariates <- "debInf" + options$modelTerms <- list(list(components="debInf", isNuisance=FALSE)) + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Inf covariate check") + + options$dependent <- "contNormal" + options$fixedFactors <- "debSame" + options$covariates <- list() + options$modelTerms <- list(list(components="debSame", isNuisance=FALSE)) + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="1-level factor check") + + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive", isNuisance=TRUE)) + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="All nuisance check") + + # options$dependent <- "debSame" + # options$fixedFactors <- "facFive" + # options$modelTerms <- list(list(components="facFive", isNuisance=FALSE)) + # results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + # expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + # label="No variance check") + + options$dependent <- "debMiss99" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive", isNuisance=FALSE)) + results <- jasptools::run("AncovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-anova.R b/JASP-Tests/R/tests/testthat/test-anova.R new file mode 100644 index 0000000000..a8d0c5b99a --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-anova.R @@ -0,0 +1,295 @@ +context("ANOVA") + +# does not test +# - if analysis handles too few observations + +test_that("Main table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- c("facFive", "contBinom") + options$wlsWeights <- "facFifty" + options$modelTerms <- list( + list(components="facFive"), + list(components="contBinom"), + list(components=c("facFive", "contBinom")) + ) + options$contrasts <- list( + list(contrast="none", variable="facFive"), + list(contrast="none", variable="contBinom") + ) + options$effectSizeEstimates <- TRUE + options$effectSizeEtaSquared <- TRUE + options$effectSizeOmegaSquared <- TRUE + options$effectSizePartialEtaSquared <- TRUE + options$VovkSellkeMPR <- TRUE + + refTables <- list( + type1 = list("facFive", 181.151987151139, 4, 45.2879967877848, 1.82424792091397, + 0.131040166930968, "TRUE", 0.0733818170125722, 0.0749970945389635, + 0.0328259131508147, 1.3814133611929, "contBinom", 24.5000310074981, + 1, 24.5000310074981, 0.98688689714382, 0.323167856084615, "FALSE", + 0.00992457670748362, 0.0108464739348588, 0, 1.00776449783097, + "facFive contBinom", 28.6688295533663, 4, 7.16720738834158, + 0.288702616682483, 0.884618241388975, "FALSE", 0.011613291343553, + 0.0126686727866262, 0, 1, "Residual", 2234.30141494065, 90, + 24.8255712771184, "", "", "TRUE", "", "", "", ""), + type2 = list("facFive", 174.090039449647, 4, 43.5225098624118, 1.75313225933803, + 0.145323959824188, "TRUE", 0.0707234506472374, 0.0722847770997921, + 0.0300789007673393, 1.31245187936232, "contBinom", 24.5000310074979, + 1, 24.5000310074979, 0.986886897143812, 0.323167856084617, "FALSE", + 0.00995304923413341, 0.0108464739348588, 0, 1.00776449783097, + "facFive contBinom", 28.6688295533663, 4, 7.16720738834158, + 0.288702616682483, 0.884618241388975, "FALSE", 0.0116466086080589, + 0.0126686727866262, 0, 1, "Residual", 2234.30141494066, 90, + 24.8255712771184, "", "", "TRUE", "", "", "", ""), + type3 = list("facFive", 165.514600111922, 4, 41.3786500279805, 1.66677534088083, + 0.164641950089634, "TRUE", 0.0675231783920824, 0.0689697039580327, + 0.0267410840853991, 1.23860485419559, "contBinom", 22.7415942746311, + 1, 22.7415942746311, 0.916055224702601, 0.341076850898726, "FALSE", + 0.00927763910910521, 0.0100758355874387, 0, 1.00272840654715, + "facFive contBinom", 28.6688295533663, 4, 7.16720738834158, + 0.288702616682484, 0.884618241388975, "FALSE", 0.0116957083599583, + 0.0126686727866262, 0, 1, "Residual", 2234.30141494065, 90, + 24.8255712771184, "", "", "TRUE", "", "", "", "") + ) + + for (type in c("type1", "type2", "type3")) { + options$sumOfSquares <- type + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["anova"]][["data"]] + expect_equal_tables(table, refTables[[type]], label=paste("Table with SS", type)) + } +}) + +test_that("Homogeneity of Variances table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- "facExperim" + options$modelTerms <- list(list(components="facExperim")) + options$homogeneityTests <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["assumptionsObj"]][["levene"]][["data"]] + expect_equal_tables(table, list(3.1459013381035, 1, 98, 0.0792241296904395, 1.83142365040653, 1)) +}) + +# Contrasts verified with SPSS +test_that("Contrasts table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive")) + + refTables <- list( + deviation = list("2 - 1, 2, 3, 4, 5", -0.19513913461, 0.211517937182488, -0.922565420263354, + 0.35857088018682, "TRUE", "3 - 1, 2, 3, 4, 5", 0.33149855864, + 0.211517937182488, 1.56723615526752, 0.12038454371847, "FALSE", + "4 - 1, 2, 3, 4, 5", -0.16911442746, 0.211517937182488, -0.799527594267789, + 0.425979159402386, "FALSE", "5 - 1, 2, 3, 4, 5", 0.18254372644, + 0.211517937182488, 0.86301771316212, 0.390301247101765, "FALSE"), + simple = list("2 - 1", -0.0453504116000002, 0.334439223738541, -0.135601354090735, + 0.892423350599012, "TRUE", "3 - 1", 0.48128728165, 0.334439223738541, + 1.43908742601993, 0.153412521131058, "FALSE", "4 - 1", -0.0193257044500001, + 0.334439223738541, -0.0577854003904418, 0.954040939034334, "FALSE", + "5 - 1", 0.33233244945, 0.334439223738541, 0.993700576550232, + 0.322892982956191, "FALSE"), + difference = list("2 - 1", -0.0453504116, 0.334439223738541, -0.135601354090734, + 0.892423350599013, "TRUE", "3 - 1, 2", 0.50396248745, 0.289632863779524, + 1.74000450388679, 0.0850966309951808, "FALSE", "4 - 1, 2, 3", + -0.164637994466667, 0.273068482710641, -0.602918333278054, 0.547999665617461, + "FALSE", "5 - 1, 2, 3, 4", 0.22817965805, 0.26439742147811, + 0.86301771316212, 0.390301247101765, "FALSE"), + Helmert = list("1 - 2, 3, 4, 5", -0.1872359037625, 0.26439742147811, -0.708160853898499, + 0.480579313597282, "TRUE", "2 - 3, 4, 5", -0.31011508715, 0.273068482710641, + -1.13566781516348, 0.25895260195633, "FALSE", "3 - 4, 5", 0.32478390915, + 0.289632863779524, 1.12136414670551, 0.264959410721321, "FALSE", + "4 - 5", -0.3516581539, 0.334439223738541, -1.05148597694067, + 0.295702769469608, "FALSE"), + repeated = list("1 - 2", 0.0453504115999998, 0.334439223738541, 0.135601354090733, + 0.892423350599014, "TRUE", "2 - 3", -0.52663769325, 0.334439223738541, + -1.57468878011066, 0.118652819171739, "FALSE", "3 - 4", 0.5006129861, + 0.334439223738541, 1.49687282641037, 0.137741463128169, "FALSE", + "4 - 5", -0.3516581539, 0.334439223738541, -1.05148597694067, + 0.295702769469608, "FALSE"), + polynomial = list("linear", 0.218415231132241, 0.236484243000287, 0.923593167820386, + 0.358038105335522, "TRUE", "quadratic", -0.0623342877876619, + 0.236484243000287, -0.263587488945664, 0.792668695639493, "FALSE", + "cubic", 0.0886332780579033, 0.236484243000287, 0.374795702806278, + 0.70864779281998, "FALSE", "quartic", 0.415791419838834, 0.236484243000287, + 1.75822039795831, 0.0819306308915546, "FALSE") + ) + + contrasts <- c("deviation", "simple", "difference", "Helmert", "repeated", "polynomial") + for (contrast in contrasts) { + options$contrasts <- list(list(contrast=contrast, variable="facFive")) + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["contrasts"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, refTables[[contrast]], label=paste("Table with contrast", contrast)) + } +}) + +test_that("Post Hoc table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + options$postHocTestEffectSize <- TRUE + options$postHocTestsBonferroni <- TRUE + options$postHocTestsHolm <- TRUE + options$postHocTestsScheffe <- TRUE + options$postHocTestsTukey <- TRUE + options$postHocTestsVariables <- "contBinom" + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["posthoc"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, + list(0, 1, 0.163364220743842, 0.214904085649005, 0.760172707980336, + 0.0760172707980336, 0.448976320466698, 0.448976320466698, 0.448976320466698, + 0.448976320466698, "TRUE") + ) +}) + +test_that("Marginal Means table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + options$marginalMeansCompareMainEffects <- TRUE + options$marginalMeansTerms <- "contBinom" + + refTables <- list( + none = list(0, -0.120135614827586, 0.139273765411964, -0.396519869554477, + 0.156248639899304, -0.862586104943973, 0.390471041862811, "TRUE", + 1, -0.283499835571429, 0.163666075582597, -0.608289835972217, + 0.0412901648293597, -1.73218447721841, 0.0863869418751253, "FALSE"), + Bonferroni = list(0, -0.120135614827586, 0.139273765411964, -0.396519869554477, + 0.156248639899304, -0.862586104943973, 0.390471041862811, "TRUE", + 1, -0.283499835571429, 0.163666075582597, -0.608289835972217, + 0.0412901648293597, -1.73218447721841, 0.0863869418751253, "FALSE"), + Sidak = list(0, -0.120135614827586, 0.139273765411964, -0.396519869554477, + 0.156248639899304, -0.862586104943973, 0.390471041862811, "TRUE", + 1, -0.283499835571429, 0.163666075582597, -0.608289835972217, + 0.0412901648293597, -1.73218447721841, 0.0863869418751253, "FALSE") + ) + + for (adjustment in c("none", "Bonferroni", "Sidak")) { + options$marginalMeansCIAdjustment <- adjustment + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["marginalMeans"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, refTables[[adjustment]], label=paste("Table with CI adjustment", adjustment)) + } +}) + +test_that("Descriptives table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + options$descriptives <- TRUE + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptivesObj"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list(0, 58, -0.120135614827586, 1.10575982846952, "TRUE", 1, 42, -0.283499835571429, + 0.994612407217046, "FALSE") + ) +}) + +test_that("Q-Q plot matches", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + options$qqPlot <- TRUE + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "q-q", dir="Anova") +}) + +test_that("Descriptives plots match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- c("facFive", "contBinom") + options$wlsWeights <- "facFifty" + options$modelTerms <- list( + list(components="facFive"), + list(components="contBinom"), + list(components=c("facFive", "contBinom")) + ) + options$plotHorizontalAxis <- "contBinom" + options$plotSeparateLines <- "facFive" + options$plotErrorBars <- TRUE + options$confidenceIntervalInterval <- 0.90 + + options$errorBarType <- "confidenceInterval" + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives-ci", dir="Anova") + + options$errorBarType <- "standardError" + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives-se", dir="Anova") +}) + +test_that("Simple Main Effects table results match", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "contNormal" + options$fixedFactors <- c( "facFive", "facExperim") + options$modelTerms <- list( + list(components="facExperim"), + list(components="facFive") + ) + options$simpleFactor <- "facExperim" + options$moderatorFactorOne <- "facFive" + options$moderatorFactorTwo <- "" + options$homogeneityTests <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("Anova", "debug.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["simpleEffects"]][["data"]] + expect_equal_tables(table, list(1, 0.350864897951646, 1, 0.350864897951646, 0.310783783968887, + 0.578524772558188, "TRUE", 2, 2.72259751707838, 1, 2.72259751707838, + 2.41158110578085, 0.123801175704108, "FALSE", 3, 0.300954391532799, + 1, 0.300954391532799, 0.266574813122249, 0.606851206017453, + "FALSE", 4, 3.47907983036715, 1, 3.47907983036715, 3.08164652754846, + 0.0824380354608798, "FALSE", 5, 0.313611321775938, 1, 0.313611321775938, + 0.27778587668933, 0.599397784945329, "FALSE")) +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("Anova") + options$dependent <- "debInf" + options$fixedFactors <- "contBinom" + options$modelTerms <- list(list(components="contBinom")) + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Inf dependent check") + + options$dependent <- "contNormal" + options$fixedFactors <- "contBinom" + options$wlsWeights <- "debInf" + options$modelTerms <- list(list(components="contBinom")) + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Inf WLS weights check") + + options$dependent <- "contNormal" + options$fixedFactors <- "debSame" + options$modelTerms <- list(list(components="debSame")) + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="1-level factor check") + + options$dependent <- "debSame" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive")) + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="No variance check") + + options$dependent <- "contGamma" + options$fixedFactors <- "facFive" + options$wlsWeights <- "contNormal" + options$modelTerms <- list(list(components="facFive")) + results <- jasptools::run("Anova", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["anova"]][["error"]][["errorType"]], "badData", + label="Negative WLS weights check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-anovabayesian.R b/JASP-Tests/R/tests/testthat/test-anovabayesian.R new file mode 100644 index 0000000000..a21708dc1b --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-anovabayesian.R @@ -0,0 +1,151 @@ +context("Bayesian ANOVA") + +# does not test +# - descriptives table (code is from regular ANOVA) +# - descriptives plot (code is from regular ANOVA) +# - bftype (01, 10) + +initOpts <- function() { + options <- jasptools::analysisOptions("AnovaBayesian") + options$sampleMode <- "manual" + options$fixedSamplesNumber <- 50 + return(options) +} + +test_that("Main table results match", { + set.seed(0) + options <- initOpts() + options$dependent <- "contNormal" + options$fixedFactors <- c("facGender", "facFive") + options$randomFactors <- "facExperim" + options$priorFixedEffects <- 0.4 + options$priorRandomEffects <- 1.5 + options$modelTerms <- list( + list(components="facGender", isNuisance=FALSE), + list(components="facFive", isNuisance=FALSE), + list(components="facExperim", isNuisance=TRUE), + list(components=c("facGender", "facFive"), isNuisance=FALSE) + ) + + refTables <- list( + nullModelTop = list("Null model (incl. facExperim)", 0.2, -0.594672751877366, 0.134816578924395, + 0, "", "facGender", 0.2, -0.28722095052267, 0.630131621377202, + 0.307451801354696, 13.7355911669398, "facFive", 0.2, -1.24424524718345, + -0.61670420719205, -0.649572495306089, 12.4382643482459, "facGender + facFive", + 0.2, -0.997414136054835, -0.349308383227457, -0.40274138417747, + 9.31843477413068, "facGender + facFive + facGenderfacFive", + 0.2, -1.14281197270266, -0.508311164396966, -0.548139220825293, + 27.3699066120848), + bestModelTop = list("facGender", 0.2, -0.224979999753508, 0.77036505277832, 0, "", + "Null model (incl. facExperim)", 0.2, -0.63697968879273, 0.0789763886292554, + -0.411999689039223, 20.3818205689136, "facGender + facFive", + 0.2, -1.06635989051332, -0.42532677067774, -0.84137989075981, + 21.4710504386678, "facFive", 0.2, -1.33455292282619, -0.711911214299153, + -1.10957292307269, 21.0528996183343, "facGender + facFive + facGenderfacFive", + 0.2, -1.3818577904349, -0.761385841073298, -1.1568777906814, + 21.731493430306) + ) + + for (order in c("nullModelTop", "bestModelTop")) { + options$bayesFactorOrder <- order + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["model comparison"]][["data"]] + expect_equal_tables(table, refTables[[order]], label=paste("Table with order", order)) + } +}) + +test_that("Effects table results match", { + set.seed(0) + options <- initOpts() + options$dependent <- "contNormal" + options$fixedFactors <- list("facFive", "contBinom") + options$effects <- TRUE + options$modelTerms <- list( + list(components="facFive", isNuisance=FALSE), + list(components="contBinom", isNuisance=FALSE), + list(components=c("facFive", "contBinom"), isNuisance=FALSE) + ) + + refTables <- list( + allModels = list("facFive", 0.6, 0.130329318915725, 0.0999070274533764, "contBinom", + 0.6, 0.215198578129195, 0.182805120830189, "facFivecontBinom", + 0.2, 0.00408798728805838, 0.0164190701020926), + matchedModels = list("facFive", 0.4, 0.125726268310478, 0.144492921488286, "contBinom", + 0.4, 0.210639434646256, 0.26825960145967, "facFivecontBinom", + 0.2, 0.0041531263651184, 0.182973144016417) + ) + + for (effectsType in c("allModels", "matchedModels")) { + options$effectsType <- effectsType + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["effects"]][["data"]] + expect_equal_tables(table, refTables[[effectsType]], label=paste("Table with effects type", effectsType)) + } +}) + +test_that("Post-hoc Comparisons table results match", { + options <- jasptools::analysisOptions("AnovaBayesian") + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$modelTerms <- list( + list(components="facFive", isNuisance=FALSE) + ) + options$postHocTestsNullControl <- TRUE + options$postHocTestsVariables <- "facFive" + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["posthoc"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, + list(1, 2, 0.319507910772894, 0.0997312866070229, -0.505650193633655, + 0.00713501139221108, "TRUE", 1, 3, 0.319507910772894, 0.260338331517325, + -0.0889434982573415, 0.00346528957238797, "FALSE", 1, 4, 0.319507910772894, + 0.0988240290518637, -0.509619059344969, 0.0071287698725277, + "FALSE", 1, 5, 0.319507910772894, 0.139031227413715, -0.361369258553702, + 0.00848479926592481, "FALSE", 2, 3, 0.319507910772894, 0.30046754229221, + -0.0266840507861397, 0.00368467308944596, "FALSE", 2, 4, 0.319507910772894, + 0.0989443005428758, -0.509090832692873, 0.00712946511175494, + "FALSE", 2, 5, 0.319507910772894, 0.151606948038875, -0.323762510268505, + 0.00859149880568525, "FALSE", 3, 4, 0.319507910772894, 0.23744955199206, + -0.12891026091494, 0.0042533257083258, "FALSE", 3, 5, 0.319507910772894, + 0.104702418542221, -0.484524901778361, 0.00721167204576887, + "FALSE", 4, 5, 0.319507910772894, 0.138002738227672, -0.364593911742112, + 0.00846064110496598, "FALSE") + ) +}) + +test_that("Analysis handles errors", { + options <- initOpts() + options$dependent <- "debInf" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive", isNuisance=FALSE)) + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Inf check") + + options$dependent <- "contNormal" + options$fixedFactors <- "debSame" + options$modelTerms <- list(list(components="debSame", isNuisance=FALSE)) + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="1-level factor check") + + options$dependent <- "contNormal" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive", isNuisance=TRUE)) + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="All nuisance check") + + # options$dependent <- "debSame" + # options$fixedFactors <- "facFive" + # options$modelTerms <- list(list(components="facFive", isNuisance=FALSE)) + # results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + # expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + # label="No variance check") + + options$dependent <- "debMiss99" + options$fixedFactors <- "facFive" + options$modelTerms <- list(list(components="facFive", isNuisance=FALSE)) + results <- jasptools::run("AnovaBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-anovarepeatedmeasuresbayesian.R b/JASP-Tests/R/tests/testthat/test-anovarepeatedmeasuresbayesian.R new file mode 100644 index 0000000000..d84f5e4cb6 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-anovarepeatedmeasuresbayesian.R @@ -0,0 +1,183 @@ +context("Bayesian Repeated Measures ANOVA") + +# does not test +# - descriptives table (code from regular ANOVA) +# - descriptives plot (code from regular ANOVA) +# - bftype (01, 10) + +initOpts <- function() { + options <- jasptools::analysisOptions("AnovaRepeatedMeasuresBayesian") + options$sampleMode <- "manual" + options$fixedSamplesNumber <- 50 + return(options) +} + +test_that("Main table results match", { + set.seed(0) + options <- initOpts() + options$repeatedMeasuresCells <- c("contNormal", "contGamma") + options$repeatedMeasuresFactors <- list( + list(levels=c("Level 1", "Level 2"), name="RM Factor 1") + ) + options$betweenSubjectFactors <- "facGender" + options$covariates <- "contcor1" + options$modelTerms <- list( + list(components="RM Factor 1", isNuisance=FALSE), + list(components="facGender", isNuisance=FALSE), + list(components="contcor1", isNuisance=FALSE), + list(components=c("RM Factor 1", "facGender"), isNuisance=FALSE) + ) + options$priorCovariates <- 0.3 + options$priorFixedEffects <- 0.8 + options$priorRandomEffects <- 0.8 + + refTables <- list( + nullModelTop = list("Null model (incl. subject)", 0.1, -23.8744941250848, -22.9202516156455, + 0, "", "RM Factor 1", 0.1, -0.52191065188766, 0.587649376228934, + 23.3525834731972, 39.1063682924946, "facGender", 0.1, -24.2606062414806, + -23.3063637320413, -0.386112116395769, 7.76323643953116, "RM Factor 1 + facGender", + 0.1, -0.333725484709657, 0.891141584222282, 23.5407686403752, + 9.48562764001249, "RM Factor 1 + facGender + RM Factor 1facGender", + 0.1, -1.22109858280499, -0.239935999954474, 22.6533955422798, + 12.5735651534712, "contcor1", 0.1, -24.4965580075927, -23.5423154981534, + -0.622063882507853, 16.2455760987562, "RM Factor 1 + contcor1", + 0.1, -1.04768016045519, -0.0526687357727608, 22.8268139646297, + 12.8879892201747, "facGender + contcor1", 0.1, -24.9098326377401, + -23.9555901283008, -1.03533851265525, 13.7488070754196, "RM Factor 1 + facGender + contcor1", + 0.1, -1.11529732351552, -0.126405348442144, 22.7591968015693, + 15.7870140533182, "RM Factor 1 + facGender + RM Factor 1facGender + contcor1", + 0.1, -2.03617619580061, -1.0779193502007, 21.8383179292842, + 11.0628049253349), + bestModelTop = list("RM Factor 1 + facGender", 0.1, -0.367321960540044, 0.830450364907295, + 0, "", "RM Factor 1", 0.1, -0.457519307040247, 0.682957515126908, + -0.0901973465002028, 11.0954992966344, "RM Factor 1 + facGender + contcor1", + 0.1, -0.991089350964165, 0.00991210164236568, -0.623767390424122, + 32.3366583310552, "RM Factor 1 + contcor1", 0.1, -1.08270023626127, + -0.0909876647379188, -0.715378275721224, 19.6531753785511, "RM Factor 1 + facGender + RM Factor 1facGender", + 0.1, -1.61472220777918, -0.649804181052933, -1.24740024723913, + 57.5970298850713, "RM Factor 1 + facGender + RM Factor 1facGender + contcor1", + 0.1, -1.88460906299348, -0.924664607527325, -1.51728710245343, + 18.7536425473633, "Null model (incl. subject)", 0.1, -23.9062736764081, + -22.9520311669687, -23.538951715868, 10.0789056479773, "facGender", + 0.1, -24.2732563884872, -23.3190138790478, -23.9059344279471, + 11.1219703306485, "contcor1", 0.1, -24.6183358489862, -23.6640933395468, + -24.2510138884461, 12.5005001657945, "facGender + contcor1", + 0.1, -25.0129223005788, -24.0586797911395, -24.6456003400388, + 15.8888968826608) + ) + + for (order in c("nullModelTop", "bestModelTop")) { + options$bayesFactorOrder <- order + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["model comparison"]][["data"]] + expect_equal_tables(table, refTables[[order]], label=paste("Table with order", order)) + } +}) + +test_that("Effects table results match", { + options <- initOpts() + options$repeatedMeasuresCells <- c("contNormal", "contGamma") + options$repeatedMeasuresFactors <- list( + list(levels=c("Level 1", "Level 2"), name="RM Factor 1") + ) + options$betweenSubjectFactors <- "facGender" + options$modelTerms <- list( + list(components="RM Factor 1", isNuisance=FALSE), + list(components="facGender", isNuisance=FALSE), + list(components=c("RM Factor 1", "facGender"), isNuisance=FALSE) + ) + options$effects <- TRUE + + refTables <- list( + allModels = list("RM Factor 1", 0.6, 1, "", "facGender", 0.6, 0.757389476581774, + 2.08122183080559, "RM Factor 1facGender", + 0.2, 0.0790846685097528, 0.343504623304625), + matchedModels = list("RM Factor 1", 0.4, 0.920915331490247, 1.02806370019033e+24, "facGender", + 0.4, 0.678304808072022, 2.79585896982186, "RM Factor 1facGender", + 0.2, 0.0790846685097528, 0.1165916378133) + ) + + effectsTypes <- c("allModels", "matchedModels") + for (effectsType in effectsTypes) { + options$effectsType <- effectsType + set.seed(5) # setting seed at start gives aberrant behaviour + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["effects"]][["data"]] + expect_equal_tables(table, refTables[[effectsType]], label=paste("Table with effects type", effectsType)) + } +}) + +test_that("Post-hoc Comparisons table results match", { + options <- jasptools::analysisOptions("AnovaRepeatedMeasuresBayesian") + options$repeatedMeasuresCells <- c("contNormal", "contGamma", "contcor1") + options$repeatedMeasuresFactors <- list( + list(levels=c("Level 1", "Level 2", "Level 3"), name="RM Factor 1") + ) + options$modelTerms <- list( + list(components="RM Factor 1", isNuisance=FALSE) + ) + options$postHocTestsNullControl <- TRUE + options$postHocTestsVariables <- "RM Factor 1" + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["posthoc"]][["collection"]][[1]][["data"]] + expect_equal_tables(table, + list("Level 1", "Level 2", 0.587401051968199, 83932041568197648, 17.1549930670883, + 2.78226779130567e-20, "TRUE", "Level 1", "Level 3", 0.587401051968199, + 0.30644539432695, -0.282581621383003, 2.74342774324035e-05, + "FALSE", "Level 2", "Level 3", 0.587401051968199, 48708968131887.4, + 13.9186742094611, 1.07201998003854e-19, "FALSE") + ) +}) + +test_that("Analysis handles errors", { + options <- initOpts() + options$repeatedMeasuresFactors <- list( + list(levels=c("Level 1", "Level 2"), name="RM Factor 1") + ) + + options$repeatedMeasuresCells <- c("contNormal", "debInf") + options$modelTerms <- list(list(components="RM Factor 1", isNuisance=FALSE)) + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Inf RM factor check") + + options$repeatedMeasuresCells <- c("contNormal", "contGamma") + options$covariates <- "debInf" + options$modelTerms <- list( + list(components="RM Factor 1", isNuisance=FALSE), + list(components="debInf", isNuisance=FALSE) + ) + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Inf covariate check") + + options$repeatedMeasuresCells <- c("contNormal", "contGamma") + options$betweenSubjectFactors <- "debSame" + options$covariates <- list() + options$modelTerms <- list( + list(components="RM Factor 1", isNuisance=FALSE), + list(components="debSame", isNuisance=FALSE) + ) + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="1-level factor check") + + options$repeatedMeasuresCells <- c("contNormal", "contGamma") + options$betweenSubjectFactors <- list() + options$modelTerms <- list(list(components="RM Factor 1", isNuisance=TRUE)) + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="All nuisance check") + + # options$repeatedMeasuresCells <- c("contNormal", "debSame") + # options$modelTerms <- list(list(components="RM Factor 1", isNuisance=FALSE)) + # results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + # expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + # label="No variance check") + + options$repeatedMeasuresCells <- c("contNormal", "debMiss99") + options$modelTerms <- list(list(components="RM Factor 1", isNuisance=FALSE)) + results <- jasptools::run("AnovaRepeatedMeasuresBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model comparison"]][["error"]][["errorType"]], "badData", + label="Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-binomialtest.R b/JASP-Tests/R/tests/testthat/test-binomialtest.R new file mode 100644 index 0000000000..2e4fd52ff3 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-binomialtest.R @@ -0,0 +1,31 @@ +context("Binomial Test") + +test_that("Main table results match", { + options <- jasptools::analysisOptions("BinomialTest") + options$variables <- "contBinom" + options$testValue <- 0.6 + options$hypothesis <- "greaterThanTestValue" + options$confidenceInterval <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("BinomialTest", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["binomial"]][["data"]] + expect_equal_tables(table, + list("contBinom", 0, 58, 100, 0.58, 0.696739870156555, 1, 0.492841460660175, + 1, "TRUE", "contBinom", 1, 42, 100, 0.42, 0.999903917924738, + 1, 0.336479745077558, 1, "FALSE") + ) +}) + +test_that("Descriptives plots match", { + options <- jasptools::analysisOptions("BinomialTest") + options$variables <- "contBinom" + options$descriptivesPlots <- TRUE + options$descriptivesPlotsConfidenceInterval <- 0.90 + results <- jasptools::run("BinomialTest", "test.csv", options, view=FALSE, quiet=TRUE) + + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives-1", dir="BinomialTest") + + testPlot <- results[["state"]][["figures"]][[2]] + expect_equal_plots(testPlot, "descriptives-2", dir="BinomialTest") +}) diff --git a/JASP-Tests/R/tests/testthat/test-binomialtestbayesian.R b/JASP-Tests/R/tests/testthat/test-binomialtestbayesian.R new file mode 100644 index 0000000000..1ed59244d2 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-binomialtestbayesian.R @@ -0,0 +1,44 @@ +context("Binomial Test Bayesian") + +test_that("Main table results match", { + options <- jasptools::analysisOptions("BinomialTestBayesian") + options$variables <- "contBinom" + options$bayesFactorType <- "BF01" + options$hypothesis <- "notEqualToTestValue" + options$priorA <- 4 + options$priorB <- 2 + options$testValue <- 0.2 + results <- jasptools::run("BinomialTestBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["binomial"]][["data"]] + expect_equal_tables(table, + list("contBinom", 0, 58, 100, 0.58, 4.32337507642424e-15, "TRUE", "contBinom", + 1, 42, 100, 0.42, 3.43240614623212e-05, "FALSE") + ) +}) + +test_that("Prior posterior plots match", { + options <- jasptools::analysisOptions("BinomialTestBayesian") + options$variables <- "contBinom" + options$plotPriorAndPosterior <- TRUE + options$plotPriorAndPosteriorAdditionalInfo <- TRUE + results <- jasptools::run("BinomialTestBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "prior-posterior-1", dir="BinomialTestBayesian") + + testPlot <- results[["state"]][["figures"]][[2]] + expect_equal_plots(testPlot, "prior-posterior-2", dir="BinomialTestBayesian") +}) + +test_that("Sequential analysis plots match", { + options <- jasptools::analysisOptions("BinomialTestBayesian") + options$variables <- "contBinom" + options$plotSequentialAnalysis <- TRUE + results <- jasptools::run("BinomialTestBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "sequential-analysis-1", dir="BinomialTestBayesian") + + testPlot <- results[["state"]][["figures"]][[2]] + expect_equal_plots(testPlot, "sequential-analysis-2", dir="BinomialTestBayesian") +}) diff --git a/JASP-Tests/R/tests/testthat/test-contingencytables.R b/JASP-Tests/R/tests/testthat/test-contingencytables.R new file mode 100644 index 0000000000..ccabe271d3 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-contingencytables.R @@ -0,0 +1,174 @@ +context("Contingency Tables") + +# does not test +# - row/column order (ascending/descending) + +test_that("Main table results match", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$counts <- "facFifty" + options$layers <- list(list( + name = "Layer 1", + variables = "facGender" + )) + options$countsObserved <- TRUE + options$countsExpected <- TRUE + options$percentagesRow <- TRUE + options$percentagesColumn <- TRUE + options$percentagesTotal <- TRUE + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Counts Table 1"]][["data"]] + expect_equal_tables(table, + list("Count", "% of Total", 320, 495, 815, "Expected count", 394.529977794227, + 420.470022205773, 815, " % within row", 0.392638036809816, 0.607361963190184, + 1, " % within column", 0.489296636085627, 0.710186513629842, + 0.603256846780163, " % within row", 0.392638036809816, 0.607361963190184, + 1, " % of Total", 0.236861584011843, 0.36639526276832, 0.603256846780163, + "control", "f", "Count", "% of Total", 334, 202, 536, "Expected count", + 259.470022205773, 276.529977794227, 536, " % within row", 0.623134328358209, + 0.376865671641791, 1, " % within column", 0.510703363914373, + 0.289813486370158, 0.396743153219837, " % within row", 0.623134328358209, + 0.376865671641791, 1, " % of Total", 0.247224278312361, 0.149518874907476, + 0.396743153219837, "experimental", "f", "Count", "% of Total", + 654, 697, 1351, "Expected count", 654, 697, 1351, " % within row", + 0.484085862324204, 0.515914137675796, 1, " % within column", + 1, 1, 1, " % within row", 0.484085862324204, 0.515914137675796, + 1, 0.484085862324204, 0.515914137675796, 1, "Total", "f", "Count", + "% of Total", 253, 182, 435, "Expected count", 271.013344453711, + 163.986655546289, 435, " % within row", 0.581609195402299, 0.418390804597701, + 1, " % within column", 0.338688085676037, 0.402654867256637, + 0.362802335279399, " % within row", 0.581609195402299, 0.418390804597701, + 1, " % of Total", 0.211009174311927, 0.151793160967473, 0.3628023352794, + "control", "m", "Count", "% of Total", 494, 270, 764, "Expected count", + 475.986655546289, 288.013344453711, 764, " % within row", 0.646596858638743, + 0.353403141361257, 1, " % within column", 0.661311914323963, + 0.597345132743363, 0.6371976647206, " % within row", 0.646596858638743, + 0.353403141361257, 1, " % of Total", 0.412010008340284, 0.225187656380317, + 0.6371976647206, "experimental", "m", "Count", "% of Total", + 747, 452, 1199, "Expected count", 747, 452, 1199, " % within row", + 0.62301918265221, 0.37698081734779, 1, " % within column", 1, + 1, 1, " % within row", 0.62301918265221, 0.37698081734779, 1, + 0.62301918265221, 0.37698081734779, 1, "Total", "m", "Count", + "% of Total", 573, 677, 1250, "Expected count", 686.764705882353, + 563.235294117647, 1250, " % within row", 0.4584, 0.5416, 1, + " % within column", 0.408993576017131, 0.589208006962576, 0.490196078431373, + " % within row", 0.4584, 0.5416, 1, " % of Total", 0.224705882352941, + 0.265490196078431, 0.490196078431373, "control", "Total", "Count", + "% of Total", 828, 472, 1300, "Expected count", 714.235294117647, + 585.764705882353, 1300, " % within row", 0.636923076923077, + 0.363076923076923, 1, " % within column", 0.591006423982869, + 0.410791993037424, 0.509803921568627, " % within row", 0.636923076923077, + 0.363076923076923, 1, " % of Total", 0.324705882352941, 0.185098039215686, + 0.509803921568627, "experimental", "Total", "Count", "% of Total", + 1401, 1149, 2550, "Expected count", 1401, 1149, 2550, " % within row", + 0.549411764705882, 0.450588235294118, 1, " % within column", + 1, 1, 1, " % within row", 0.549411764705882, 0.450588235294118, + 1, 0.549411764705882, 0.450588235294118, 1, "Total", "Total") + ) +}) + +test_that("Multiple row and column variables give multiple main tables", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- c("facExperim", "facGender") + options$columns <- c("contBinom", "facFive") + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + + pairs <- list( + c("facExperim", "contBinom"), + c("facExperim", "facFive"), + c("facGender", "contBinom"), + c("facGender", "facFive") + ) + + for (i in 1:4) { + rows <- results[["results"]][[paste("Counts Table", i)]][["schema"]][["fields"]][[1]][["name"]] + cols <- results[["results"]][[paste("Counts Table", i)]][["schema"]][["fields"]][[2]][["overTitle"]] + expect_identical(c(rows, cols), pairs[[i]], label=paste("Table", i)) + } +}) + +test_that("Chi-Squared test table results match", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$counts <- "facFifty" + options$chiSquared <- TRUE + options$chiSquaredContinuityCorrection <- TRUE + options$likelihoodRatio <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Tests Table 1"]][["data"]] + expect_equal_tables(table, + list("N", "", "", "", 2550, "", 82.0397085317219, + 1, 1.33379878452991e-19, 63462127883801120, " continuity correction", + 81.3201582621313, 1, 1.91958529099645e-19, 44468347240355080, + "Likelihood ratio", 82.4643894680383, 1, 0, "") + ) +}) + +test_that("Nominal table results match", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$contingencyCoefficient <- TRUE + options$phiAndCramersV <- TRUE + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Nominal Table 1"]][["data"]] + expect_equal_tables(table, + list("Contingency coefficient", 0.0807792391722019, "Phi-coefficient", + 0.0810440898473108, "Cramer's V ", 0.0810440898473108) + ) +}) + +test_that("Log Odds Ratio table results match", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$oddsRatio <- TRUE + options$oddsRatioConfidenceIntervalInterval <- 0.90 + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Odds Ratio Table 1"]][["data"]] + expect_equal_tables(table, + list("Odds ratio", -0.329205575243527, -0.998167649205055, 0.339756498718001, + "Fisher's exact test ", -0.325882968750928, -1.07370478788709, + 0.415368461868818) + ) +}) + +test_that("Ordinal Gamma table results match", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$gamma <- TRUE + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Ordinal Table 1"]][["data"]] + expect_equal_tables(table, + list("Gamma coefficient", -0.163132137030995, 0.197938461395245, -0.551084392520947, + 0.224820118458957) + ) +}) + +test_that("Kendall's Tau table results match", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$kendallsTauB <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Kendalls Table 1"]][["data"]] + expect_equal_tables(table, + list("Kendall's Tau-b", -0.0810440898473108, 0.420024632711394, 1, + -0.806378512498144) + ) +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("ContingencyTables") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$counts <- "contNormal" + results <- jasptools::run("ContingencyTables", "test.csv", options, view=FALSE, quiet=TRUE) + errorMsg <- results[["results"]][["Counts Table 1"]][["error"]][["errorMessage"]] + expect_is(errorMsg, "character") +}) diff --git a/JASP-Tests/R/tests/testthat/test-contingencytablesbayesian.R b/JASP-Tests/R/tests/testthat/test-contingencytablesbayesian.R new file mode 100644 index 0000000000..258f92689b --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-contingencytablesbayesian.R @@ -0,0 +1,111 @@ +context("Bayesian Contingency Tables") + +# does not test +# - row/column order (ascending/descending) +# - different hypothesis options +# - bftype (01, 10, log) +# - log odds for different sampling models +# - error handling in plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("ContingencyTablesBayesian") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$counts <- "facFifty" + options$layers <- list(list( + name = "Layer 1", + variables = "facGender" + )) + results <- jasptools::run("ContingencyTablesBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Counts Table 1"]][["data"]] + expect_equal_tables(table, + list(320, 495, "Count", 815, "control", "f", "TRUE", 334, 202, "Count", + 536, "experimental", "f", 654, 697, "Count", 1351, "Total", + "TRUE", "f", 253, 182, "Count", 435, "control", "m", "TRUE", + 494, 270, "Count", 764, "experimental", "m", 747, 452, "Count", + 1199, "Total", "TRUE", "m", 573, 677, "Count", 1250, "control", + "Total", "TRUE", 828, 472, "Count", 1300, "experimental", "Total", + 1401, 1149, "Count", 2550, "Total", "TRUE", "Total") + ) +}) + +test_that("Multiple row and column variables give multiple main tables", { + options <- jasptools::analysisOptions("ContingencyTablesBayesian") + options$rows <- c("facExperim", "facGender") + options$columns <- c("contBinom", "facFive") + results <- jasptools::run("ContingencyTablesBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + + pairs <- list( + c("facExperim", "contBinom"), + c("facExperim", "facFive"), + c("facGender", "contBinom"), + c("facGender", "facFive") + ) + + for (i in 1:4) { + rows <- results[["results"]][[paste("Counts Table", i)]][["schema"]][["fields"]][[1]][["name"]] + cols <- results[["results"]][[paste("Counts Table", i)]][["schema"]][["fields"]][[2]][["overTitle"]] + expect_identical(c(rows, cols), pairs[[i]], label=paste("Table", i)) + } +}) + +test_that("Bayesian Contingency Tables Tests table results match", { + options <- jasptools::analysisOptions("ContingencyTablesBayesian") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$priorConcentration <- 1.5 + + samplingModels <- c("poisson", "jointMultinomial", "independentMultinomialRowsFixed", + "independentMultinomialColumnsFixed", "hypergeometric") + refTables <- list( + poisson = list("BF Poisson", "N", 100, 0.523118843924781), + jointMultinomial = list("BF joint multinomial", "N", 100, 0.440084106793853), + independentMultinomialRowsFixed = list("BF independent multinomial", "N", 100, 0.35545254779504), + independentMultinomialColumnsFixed = list("BF independent multinomial", "N", 100, 0.364069579256729), + hypergeometric = list("BF hypergeometric", "N", 100, 0.269648117146104) + ) + + for (samplingModel in samplingModels) { + options$samplingModel <- samplingModel + results <- jasptools::run("ContingencyTablesBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Tests Table 1"]][["data"]] + expect_equal_tables(table, refTables[[samplingModel]], label=paste("Sampling model", samplingModel)) + } +}) + +test_that("Log Odds Ratio table results match", { + set.seed(0) + options <- jasptools::analysisOptions("ContingencyTablesBayesian") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$oddsRatio <- TRUE + options$oddsRatioCredibleIntervalInterval <- 0.90 + results <- jasptools::run("ContingencyTablesBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Odds Ratio Table 1"]][["data"]] + expect_equal_tables(table, + list("Odds ratio", -0.325226942981456, -0.981898524010587, 0.337174584207703, + "TRUE") + ) +}) + +# test_that("Log Odds Ratio Plot matches", { +# set.seed(0) +# options <- jasptools::analysisOptions("ContingencyTablesBayesian") +# options$rows <- "facExperim" +# options$columns <- "contBinom" +# options$plotPosteriorOddsRatio <- TRUE +# options$plotPosteriorOddsRatioAdditionalInfo <- TRUE +# results <- jasptools::run("ContingencyTablesBayesian", "test.csv", options, view=FALSE, quiet=TRUE) +# testPlot <- results[["state"]][["figures"]][[1]] +# expect_equal_plots(testPlot, "log-odds-ratio", dir="ContingencyTablesBayesian") +# }) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("ContingencyTablesBayesian") + options$rows <- "facExperim" + options$columns <- "contBinom" + options$counts <- "contNormal" + results <- jasptools::run("ContingencyTablesBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + errorMsg <- results[["results"]][["Counts Table 1"]][["error"]][["errorMessage"]] + expect_is(errorMsg, "character") +}) diff --git a/JASP-Tests/R/tests/testthat/test-correlation.R b/JASP-Tests/R/tests/testthat/test-correlation.R new file mode 100644 index 0000000000..ed286ca447 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-correlation.R @@ -0,0 +1,66 @@ +context("Correlation") + +# does not test +# - hypothesis + +test_that("Correlation table results match", { + options <- jasptools::analysisOptions("Correlation") + options$variables <- list("contGamma", "contNormal") + options$kendallsTauB <- TRUE + options$spearman <- TRUE + options$confidenceIntervals <- TRUE + options$confidenceIntervalsInterval <- 0.99 + options$VovkSellkeMPR <- TRUE + options$reportSignificance <- TRUE + results <- jasptools::run("Correlation", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["correlations"]][["data"]] + expect_equal_tables(table, + list("Pearson's r", "p-value", "VS-MPR*", "Upper 99% CI", "Lower 99% CI", + "", "", "", "", "", + "Spearman's rho", "p-value", "VS-MPR*", "Upper 99% CI", "Lower 99% CI", + "", "", "", "", "", + "Kendall's tau B", "p-value", "VS-MPR*", "Upper 99% CI", "Lower 99% CI", + "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "contGamma", "Pearson's r", "p-value", "VS-MPR*", "Upper 99% CI", + "Lower 99% CI", -0.0592003859505642, 0.558497687623534, 1, 0.199552209614306, + -0.310235105822658, "Spearman's rho", "p-value", "VS-MPR*", + "Upper 99% CI", "Lower 99% CI", -0.0341794179417942, 0.73526094223706, + 1, 0.223505684391118, -0.287398829792082, "Kendall's tau B", + "p-value", "VS-MPR*", "Upper 99% CI", "Lower 99% CI", -0.0266666666666667, + 0.694237192757787, 1, 0.135964685981942, -0.189298019315275, + "", "", "", "", "", + "", "", "", "", "", + "", "", "", "", "", + "contNormal") + ) +}) + +test_that("Correlation matrix plot matches", { + options <- jasptools::analysisOptions("Correlation") + options$variables <- list("contGamma", "contNormal") + options$plotCorrelationMatrix <- TRUE + options$plotDensities <- TRUE + options$plotStatistics <- TRUE + results <- jasptools::run("Correlation", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "correlation-matrix", dir="Correlation") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("Correlation") + options$variables <- list("contGamma", "debInf") + results <- jasptools::run("Correlation", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlations"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$variables <- list("contGamma", "debSame") + results <- jasptools::run("Correlation", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlations"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$variables <- list("contGamma", "debMiss99") + results <- jasptools::run("Correlation", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlations"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-correlationbayesian.R b/JASP-Tests/R/tests/testthat/test-correlationbayesian.R new file mode 100644 index 0000000000..166b9081e4 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-correlationbayesian.R @@ -0,0 +1,61 @@ +context("Bayesian Correlation") + +# does not test +# - bftype (01, 10) +# - missing value exclusion +# - errors whilst plotting + +test_that("Main table results match", { + options <- jasptools::analysisOptions("CorrelationBayesian") + options$variables <- c("contcor1", "contcor2") + options$kendallsTauB <- TRUE + options$reportBayesFactors <- TRUE + options$flagSupported <- TRUE + options$credibleInterval <- TRUE + options$priorWidth <- 1.5 + results <- jasptools::run("CorrelationBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["correlations"]][["data"]] + expect_equal_tables(table, + list("Pearson's r", "", "", "BF", "", + "", "Upper 95% CI", "", "", "Lower 95% CI", "", + "", "Kendall's tau", "", "", "BF", + "", "", "Upper 95% CI", "", "", "Lower 95% CI", + "", "", "contcor1", "Pearson's r", 0.657010063712354, + "", "BF", 71191291327.7147, "", + "Upper 95% CI", 0.753487301516087, "", "Lower 95% CI", + 0.524567068817447, "", "Kendall's tau", 0.503030303030303, + "", "BF", 78878934747.8062, "", + "Upper 95% CI", 0.62124248496994, "", "Lower 95% CI", + 0.360721442885771, "", "contcor2", "***", "***") + ) +}) + +test_that("Correlation plot matches", { + options <- jasptools::analysisOptions("CorrelationBayesian") + options$variables <- c("contcor1", "contcor2") + options$plotCorrelationMatrix <- TRUE + options$plotDensitiesForVariables <- TRUE + options$plotPosteriors <- TRUE + results <- jasptools::run("CorrelationBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "correlation", dir="CorrelationBayesian") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("CorrelationBayesian") + + options$variables <- c("contNormal", "debInf") + results <- jasptools::run("CorrelationBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlations"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$variables <- c("contNormal", "debSame") + results <- jasptools::run("CorrelationBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlations"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$variables <- c("contNormal", "debMiss99") + results <- jasptools::run("CorrelationBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlations"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-correlationbayesianpairs.R b/JASP-Tests/R/tests/testthat/test-correlationbayesianpairs.R new file mode 100644 index 0000000000..31e4848dba --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-correlationbayesianpairs.R @@ -0,0 +1,77 @@ +context("Bayesian Correlation Pairs") + +# does not test +# - bftype (01, 10) +# - missing value exclusion +# - errors whilst plotting + +test_that("Main table results match", { + options <- jasptools::analysisOptions("CorrelationBayesianPairs") + options$pairs <- list(c("contcor1", "contcor2")) + options$corcoefficient <- "Pearson" + options$priorWidth <- 2 + options$credibleInterval <- TRUE + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["correlation"]][["data"]] + expect_equal_tables(table, + list("contcor1", "-", "contcor2", 0.657010063712354, 64323420095.6619, + 0.754530668995209, 0.526024457777752) + ) +}) + +test_that("Scatterplot matches", { + options <- jasptools::analysisOptions("CorrelationBayesianPairs") + options$pairs <- list(c("contcor1", "contcor2")) + options$plotScatter <- TRUE + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "scatterplot", dir="CorrelationBayesianPairs") +}) + +test_that("Prior posterior plot matches", { + options <- jasptools::analysisOptions("CorrelationBayesianPairs") + options$pairs <- list(c("contcor1", "contcor2")) + options$plotPriorAndPosterior <- TRUE + options$plotPriorAndPosteriorAdditionalInfo <- TRUE + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "prior-posterior", dir="CorrelationBayesianPairs") +}) + +test_that("BF robustness check plot matches", { + options <- jasptools::analysisOptions("CorrelationBayesianPairs") + options$pairs <- list(c("contcor1", "contcor2")) + options$plotBayesFactorRobustness <- TRUE + options$plotBayesFactorRobustnessAdditionalInfo <- FALSE + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "robustness-check", dir="CorrelationBayesianPairs") +}) + +test_that("Sequential analysis plot matches", { + options <- jasptools::analysisOptions("CorrelationBayesianPairs") + options$pairs <- list(c("contcor1", "contcor2")) + options$plotSequentialAnalysis <- TRUE + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "sequential-analysis", dir="CorrelationBayesianPairs") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("CorrelationBayesianPairs") + + options$pairs <- list(c("contNormal", "debInf")) + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlation"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$pairs <- list(c("contNormal", "debSame")) + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlation"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$pairs <- list(c("contNormal", "debMiss99")) + results <- jasptools::run("CorrelationBayesianPairs", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["correlation"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-descriptives.R b/JASP-Tests/R/tests/testthat/test-descriptives.R new file mode 100644 index 0000000000..ad601dae38 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-descriptives.R @@ -0,0 +1,112 @@ +context("Descriptives") + +# does not test +# - error handling + +test_that("Main table results match", { + options <- jasptools::analysisOptions("Descriptives") + options$variables <- "contNormal" + options$splitby <- "contBinom" + options$median <- TRUE + options$mode <- TRUE + options$sum <- TRUE + options$variance <- TRUE + options$range <- TRUE + options$standardErrorMean <- TRUE + options$kurtosis <- TRUE + options$skewness <- TRUE + options$mode <- TRUE + options$percentileValuesEqualGroups <- TRUE + options$percentileValuesEqualGroupsNo <- 5 + options$percentileValuesPercentiles <- TRUE + options$percentileValuesPercentilesPercentiles <- c(2, 5, 8) + options$percentileValuesQuartiles <- TRUE + results <- jasptools::run("Descriptives", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["stats"]][["data"]] + expect_equal_tables(table, + list("contNormal", 0, 58, 0, -0.120135614827586, -0.2223981035, 0, + -2.336742886, -6.96786566, 3.356094448, -2.336742886, 5.692837334, + 1.10575982846952, 0.145193378675912, 1.22270479825695, 1.89652072756094, + 0.618135836828014, 0.885861572513177, 0.313719932561217, -0.7900939905, + -0.2223981035, 0.40412953575, -0.8670655236, -0.6057613228, + 0.201713297, 0.5234206222, -2.30423818432, -1.9634857839, -1.45975925544, + "contNormal", 1, 42, 0, -0.283499835571429, -0.405769511, 0, + -3.023963827, -11.906993094, 2.179421126, -3.023963827, 5.203384953, + 0.994612407217046, 0.15347202634745, 0.989253840590086, 0.972132667292966, + 0.716632727345669, 0.166587887409046, 0.365360605557062, -0.824972188, + -0.405769511, 0.47832629925, -1.011718665, -0.5958418376, -0.2081038858, + 0.5510430038, -3.023963827, -1.64658611775, -1.54829717812) + ) +}) + +test_that("Frequencies table matches", { + options <- jasptools::analysisOptions("Descriptives") + options$variables <- "facGender" + options$splitby <- "contBinom" + options$frequencyTables <- TRUE + results <- jasptools::run("Descriptives", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["tables"]][[1]][["data"]] + expect_equal_tables(table, + list(0, "f", 26, 44.8275862068966, 44.8275862068966, 44.8275862068966, + "TRUE", 0, "m", 32, 55.1724137931034, 55.1724137931034, 100, + "FALSE", "", "Missing", 0, 0, "", "", "", "Total", 58, 100, + "", "", 1, "f", 24, 57.1428571428571, 57.1428571428571, 57.1428571428571, + "TRUE", 1, "m", 18, 42.8571428571429, 42.8571428571429, 100, + "FALSE", "", "Missing", 0, 0, "", "", "", "Total", 42, 100, + "", "") + ) +}) + +test_that("Frequencies table matches with missing values", { + options <- jasptools::analysisOptions("Descriptives") + x <- c(rep(NA, 10), rep(1:2, times=10)) + split <- rep(1:2, each=15) + data <- data.frame(x=as.factor(x), split=as.factor(split)) + options$variables <- "x" + options$splitby <- "split" + options$frequencyTables <- TRUE + results <- jasptools::run("Descriptives", data, options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["tables"]][[1]][["data"]] + expect_equal_tables(table, + list(1, 1, 3, 20, 60, 60, "TRUE", 1, 2, 2, 13.3333333333333, 40, 100, + "FALSE", "", "Missing", 10, 66.6666666666667, "", "", "", "Total", + 15, 100, "", "", 2, 1, 7, 46.6666666666667, 46.6666666666667, + 46.6666666666667, "TRUE", 2, 2, 8, 53.3333333333333, 53.3333333333333, + 100, "FALSE", "", "Missing", 0, 0, "", "", "", "Total", 15, + 100, "", "") + ) +}) + +test_that("Distribution plot matches", { + options <- jasptools::analysisOptions("Descriptives") + options$variables <- "contNormal" + options$plotVariables <- TRUE + results <- jasptools::run("Descriptives", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "distribution", dir="Descriptives") +}) + +test_that("Correlation plot matches", { + options <- jasptools::analysisOptions("Descriptives") + options$variables <- c("contNormal", "contGamma") + options$plotCorrelationMatrix <- TRUE + results <- jasptools::run("Descriptives", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "correlation", dir="Descriptives") +}) + +test_that("Boxplot matches", { + set.seed(0) + options <- jasptools::analysisOptions("Descriptives") + options$variables <- "contNormal" + options$splitby <- "contBinom" + options$splitPlotBoxplot <- TRUE + options$splitPlotColour <- TRUE + options$splitPlotJitter <- TRUE + options$splitPlotOutlierLabel <- TRUE + options$splitPlotViolin <- TRUE + options$splitPlots <- TRUE + results <- jasptools::run("Descriptives", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "boxplot", dir="Descriptives") +}) diff --git a/JASP-Tests/R/tests/testthat/test-exploratoryfactoranalysis.R b/JASP-Tests/R/tests/testthat/test-exploratoryfactoranalysis.R new file mode 100644 index 0000000000..6c55b4720f --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-exploratoryfactoranalysis.R @@ -0,0 +1,57 @@ +context("Exploratory Factor Analysis") + +# does not test +# - error handling +# - orthogonal rotation +# - Eigen values above / manual +# - contents of screeplot (set.seed does not work) + +test_that("Main tables' results match", { + options <- jasptools::analysisOptions("ExploratoryFactorAnalysis") + options$variables <- list("contWide", "contcor1", "facFifty", "contExpon", "contBinom") + options$factorMethod <- "parallelAnalysis" + options$highlightText <- 0 + options$rotationMethod <- "oblique" + options$obliqueSelector <- "oblimin" + results <- jasptools::run("ExploratoryFactorAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + + table <- results[["results"]][["factorLoadings"]][["data"]] + expect_equal_tables(table, + list("contWide", -0.0259163777157326, 0.999328341366095, "contcor1", + -0.302932576039401, 0.908231854374133, "facFifty", 0.320261312722698, + 0.897432691573134, "contExpon", 0.275659841743814, 0.924011651649776, + "contBinom", 0.444974142157851, 0.801998012810884), + label="Factor loadings table" + ) + + table <- results[["results"]][["goodnessOfFit"]][["data"]] + expect_equal_tables(table, list("Model", 4.94262899224083, 5, 0.422921921501767), + label="Chi squared table" + ) +}) + +test_that("Path diagram matches", { + options <- jasptools::analysisOptions("ExploratoryFactorAnalysis") + options$variables <- list("contWide", "contcor1", "facFifty", "contExpon") + options$incl_pathDiagram <- TRUE + results <- jasptools::run("ExploratoryFactorAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "path-diagram", dir="ExploratoryFactorAnalysis") +}) + +test_that("Scree plot option creates .png", { + options <- jasptools::analysisOptions("ExploratoryFactorAnalysis") + options$variables <- list("contNormal", "contGamma") + options$incl_screePlot <- TRUE + results <- jasptools::run("ExploratoryFactorAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + expect_match(results[["results"]][["screePlot"]][["data"]], ".*\\.png") +}) + +test_that("Factor correlation table matches", { + options <- jasptools::analysisOptions("ExploratoryFactorAnalysis") + options$variables <- list("contWide", "contcor1", "facFifty", "contExpon") + options$incl_correlations <- TRUE + results <- jasptools::run("ExploratoryFactorAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + table <- results[["results"]][["factorCorrelations"]][["data"]] + expect_equal_tables(table, list("RC 1", 1, "RC 2", 0.0433504307183835, 1)) +}) diff --git a/JASP-Tests/R/tests/testthat/test-networkanalysis.R b/JASP-Tests/R/tests/testthat/test-networkanalysis.R new file mode 100644 index 0000000000..341cffad87 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-networkanalysis.R @@ -0,0 +1,53 @@ +context("Network Analysis") + +# does not test +# - error handling +# - bootstrapping +# - plots or graphical options + +options <- jasptools::analysisOptions("NetworkAnalysis") +options$variables <- c("contNormal", "contcor1", "contcor2") +options$tableCentrality <- TRUE +options$tableClustering <- TRUE +options$tableWeightsMatrix <- TRUE +options$tableLayout <- TRUE +results <- jasptools::run("NetworkAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects = "pkgLoading") + +test_that("generalTB table results match", { + table <- results[["results"]][["generalTB"]][["data"]] + expect_equal_tables(table, + list("Network", 3, "2 / 3", 0.333333333333333) + ) +}) + +test_that("centralityTB table results match", { + table <- results[["results"]][["centralityTB"]][["data"]] + expect_equal_tables(table, + list("contNormal", -0.577350269189626, -1.12003079401266, -1.14291478283658, + "contcor1", 1.15470053837925, 0.803219560925303, 0.713968266021615, + "contcor2", -0.577350269189626, 0.316811233087358, 0.428946516814968) + ) +}) + +test_that("clusteringTB table results match", { + table <- results[["results"]][["clusteringTB"]][["data"]] + expect_equal_tables(table, + list("contcor1", 0, 0, 0, 0, "contcor2", 0, 0, 0, 0, "contNormal", + 0, 0, 0, 0) + ) +}) + +test_that("weightmatrixTB table results match", { + table <- results[["results"]][["weightmatrixTB"]][["data"]] + expect_equal_tables(table, + list("contNormal", 0, 0.0939476582188346, 0, "contcor1", 0.0939476582188346, + 0, 0.612057902640958, "contcor2", 0, 0.612057902640958, 0) + ) +}) + +test_that("layoutTB table results match", { + table <- results[["results"]][["layoutTB"]][["data"]] + expect_equal_tables(table, + list(1, 1, -1, 0.0611664081106051, -0.270697752594105, -1) + ) +}) diff --git a/JASP-Tests/R/tests/testthat/test-principalcomponentanalysis.R b/JASP-Tests/R/tests/testthat/test-principalcomponentanalysis.R new file mode 100644 index 0000000000..32f9ee8607 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-principalcomponentanalysis.R @@ -0,0 +1,59 @@ +context("Principal Component Analysis") + +# does not test +# - error handling +# - oblique rotation +# - Parallel analysis / manual +# - contents of screeplot (set.seed does not work) +# - slider + +test_that("Main tables' results match", { + options <- jasptools::analysisOptions("PrincipalComponentAnalysis") + options$variables <- list("contNormal", "contGamma", "debCollin1", "contcor1", "facFifty") + options$factorMethod <- "eigenValues" + options$eigenValuesBox <- 0.95 + options$rotationMethod <- "orthogonal" + options$orthogonalSelector <- "varimax" + results <- jasptools::run("PrincipalComponentAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + + table <- results[["results"]][["factorLoadings"]][["data"]] + expect_equal_tables(table, + list("contNormal", 0.709068975944499, ".", 0.494098364850579, "contGamma", + ".", -0.730807163622534, 0.426552751857732, "debCollin1", ".", + 0.766942636295035, 0.388000487607395, "contcor1", 0.613519408318389, + ".", 0.556716214776696, "facFifty", -0.560112933829558, ".", + 0.683577731988681), + label="Factor loadings table" + ) + + table <- results[["results"]][["goodnessOfFit"]][["data"]] + expect_equal_tables(table, list("Model", 56.1723464768203, 1, 6.63887442169672e-14), + label="Chi squared table" + ) +}) + +test_that("Path diagram matches", { + options <- jasptools::analysisOptions("PrincipalComponentAnalysis") + options$variables <- list("contNormal", "contGamma") + options$incl_pathDiagram <- TRUE + results <- jasptools::run("PrincipalComponentAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "path-diagram", dir="PrincipalComponentAnalysis") +}) + +test_that("Scree plot option creates .png", { + options <- jasptools::analysisOptions("PrincipalComponentAnalysis") + options$variables <- list("contNormal", "contGamma") + options$incl_screePlot <- TRUE + results <- jasptools::run("PrincipalComponentAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + expect_match(results[["results"]][["screePlot"]][["data"]], ".*\\.png") +}) + +test_that("Factor correlation table matches", { + options <- jasptools::analysisOptions("PrincipalComponentAnalysis") + options$variables <- list("contNormal", "contGamma", "contcor1", "debCollin1") + options$incl_correlations <- TRUE + results <- jasptools::run("PrincipalComponentAnalysis", "test.csv", options, view=FALSE, quiet=TRUE, sideEffects="pkgLoading") + table <- results[["results"]][["factorCorrelations"]][["data"]] + expect_equal_tables(table, list("RC 1", 1, "RC 2", 0.143153250525087, 1)) +}) diff --git a/JASP-Tests/R/tests/testthat/test-regressionlinear.R b/JASP-Tests/R/tests/testthat/test-regressionlinear.R new file mode 100644 index 0000000000..df4b509ea1 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-regressionlinear.R @@ -0,0 +1,314 @@ +context("Linear Regression") + +# does not test +# - stepwise methods (currently gives an error if I set p entry too high) +# - plots handle errors + +test_that("Main table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$wlsWeights <- "facFifty" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$rSquaredChange <- TRUE + options$residualsDurbinWatson <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["model summary"]][["data"]] + expect_equal_tables(table, + list(1, 0.00124876050417603, 1.55940279678998e-06, -0.0102025063175828, + 5.01896242334011, 1.55940279678998e-06, 0.000152821712396024, + 1, 98, 0.990161847660694, 2.22918408630401) + ) +}) + +test_that("Coefficients table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$regressionCoefficientsEstimates <- TRUE + options$regressionCoefficientsConfidenceIntervals <- TRUE + options$regressionCoefficientsConfidenceIntervalsInterval <- 0.9 + options$collinearityDiagnostics <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["regression"]][["data"]] + expect_equal_tables(table, + list(1, "(Intercept)", -0.105623204281424, 0.176988347288719, "", -0.596780555892316, + 0.552030096201664, 1, -0.107624744624094, -0.103621663938754, + "", "", "TRUE", "", "contGamma", -0.0408888274744623, 0.0696473684093105, + -0.0592003859505643, -0.587083595666713, 0.558497687623533, + 1, -0.0416764613484857, -0.0401011936004389, 1, 1) + ) +}) + +test_that("ANOVA table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "debCollin1" + options$covariates <- "debCollin2" + options$modelTerms <- list( + list(components="debCollin2", isNuisance=FALSE) + ) + options$modelFit <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["anova"]][["data"]] + expect_equal_tables(table, + list(1, "Regression", 0.666902167813857, 1, 0.666902167813857, 3.08946572909727e+30, + 0, "", "TRUE", "", "Residual", 2.11546002372568e-29, + 98, 2.15863267727111e-31, "", "", "", "", "Total", 0.666902167813857, + 99, "", "", "", "") + ) +}) + +test_that("Coefficients Covariance table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- c("contGamma", "contcor1") + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE), + list(components="contcor1", isNuisance=FALSE) + ) + options$regressionCoefficientsCovarianceMatrix <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["coefficient covariances"]][["data"]] + expect_equal_tables(table, + list(1, "contGamma", "TRUE", 0.00490486111017858, 0.00116294327838645, + "", "contcor1", "", 0.0112500585702943) + ) +}) + +test_that("Descriptive table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$descriptives <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["data"]] + expect_equal_tables(table, + list("contNormal", 100, -0.18874858754, 1.05841360919316, 0.105841360919316, + "contGamma", 100, 2.03296079621, 1.53241112621044, 0.153241112621044) + ) +}) + +test_that("Part and Partial Correlations table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- c("debCollin2", "debCollin3", "contGamma") + options$modelTerms <- list( + list(components="debCollin2", isNuisance=FALSE), + list(components="debCollin3", isNuisance=FALSE), + list(components="contGamma", isNuisance=FALSE) + ) + options$partAndPartialCorrelations <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["correlations"]][["data"]] + expect_equal_tables(table, + list(1, "debCollin2", -0.0322303841661185, -0.0321675047221584, "TRUE", + "", "debCollin3", 0.0322303963842314, 0.0321675169163488, "", + "contGamma", -0.0617173111983368, -0.0617145529439823) + ) +}) + +test_that("Collinearity Diagonistic table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contcor1" + options$modelTerms <- list( + list(components="contcor1", isNuisance=FALSE) + ) + options$collinearityDiagnostics <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["collinearity diagnostics"]][["data"]] + expect_equal_tables(table, + list(1, 1, "TRUE", 1.05212452477783, 1, 0.473937737611082, 0.473937737611089, + "", 2, 0.947875475222171, 1.0535567372186, 0.526062262388918, + 0.526062262388911) + ) +}) + +test_that("Residuals Statistics table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contcor1" + options$modelTerms <- list( + list(components="contcor1", isNuisance=FALSE) + ) + options$residualsDurbinWatson <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["residuals statistics"]][["data"]] + expect_equal_tables(table, + list("Predicted Value", -0.559288923489434, 0.200246244240391, -0.18874858754, + 0.170438384014894, 100, "Residual", -2.87689451816188, 3.15584820375961, + 9.84238732182341e-18, 1.04460046208093, 100, "Std. Predicted Value", + -2.17404276678107, 2.28231940844029, 6.76021738588162e-17, 1, + 100, "Std. Residual", -2.75476210882495, 3.10457788320998, 0.000645077391284091, + 1.00643569133304, 100) + ) +}) + +test_that("Casewise Diagnostics table results match", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contOutlier" + options$modelTerms <- list( + list(components="contOutlier", isNuisance=FALSE) + ) + options$residualsCasewiseDiagnostics <- TRUE + options$residualsCasewiseDiagnosticsType <- "outliersOutside" + options$residualsCasewiseDiagnosticsOutliersOutside <- 3 + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["residuals statistics"]][["data"]] + expect_equal_tables(table, + list("Predicted Value", -0.275779454672472, -0.143545494526366, -0.18874858754, + 0.0109677571683762, 100, "Residual", -2.83584638233813, 3.54333175330668, + 1.8570756911418e-17, 1.05835678125479, 100, "Std. Predicted Value", + -7.93515627638173, 4.12145275644591, 7.10605890536647e-16, 1, + 100, "Std. Residual", -2.6793890904309, 3.34810934796608, 0.00829531757614864, + 1.01553841838244, 100) + ) +}) + +test_that("Residuals vs. Dependent plot matches", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$plotResidualsDependent <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "residuals-dependent", dir="RegressionLinear") +}) + +test_that("Residuals vs. Covariates plot matches", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$plotResidualsCovariates <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "residuals-covariates", dir="RegressionLinear") +}) + +test_that("Residuals vs. Predicted plot matches", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$plotResidualsPredicted <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "residuals-predicted", dir="RegressionLinear") +}) + +test_that("Standardized Residuals Histogram matches", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$plotResidualsHistogram <- TRUE + options$plotResidualsHistogramStandardized <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "residuals-histogram", dir="RegressionLinear") +}) + +test_that("Q-Q Plot Standardized Residuals matches", { + options <- jasptools::analysisOptions("RegressionLinear") + options$dependent <- "contNormal" + options$covariates <- "contGamma" + options$modelTerms <- list( + list(components="contGamma", isNuisance=FALSE) + ) + options$plotResidualsQQ <- TRUE + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "residuals-q-q", dir="RegressionLinear") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("RegressionLinear") + + options$dependent <- "debInf" + options$covariates <- "contGamma" + options$modelTerms <- list(list(components="contGamma", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Inf dependent check") + + options$dependent <- "contNormal" + options$covariates <- "debInf" + options$modelTerms <- list(list(components="debInf", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Inf covariate check") + + options$covariates <- "contGamma" + options$wlsWeights <- "debInf" + options$modelTerms <- list(list(components="contGamma", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Inf wlsWeights check") + + options$dependent <- "debSame" + options$covariates <- "contGamma" + options$wlsWeights <- "" + options$modelTerms <- list(list(components="contGamma", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="No variance dependent check") + + options$dependent <- "contNormal" + options$covariates <- "debSame" + options$modelTerms <- list(list(components="debSame", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="No variance covariate check") + + options$dependent <- "contGamma" + options$covariates <- "contcor1" + options$wlsWeights <- "contNormal" + options$modelTerms <- list(list(components="contcor1", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Negative wlsWeights check") + + options$dependent <- "debNaN" + options$covariates <- "contcor1" + options$wlsWeights <- "" + options$modelTerms <- list(list(components="contcor1", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Too few obs dependent check") + + options$dependent <- "contGamma" + options$covariates <- "debNaN" + options$modelTerms <- list(list(components="debNaN", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Too few obs covariate check") + + options$dependent <- "contGamma" + options$covariates <- "contNormal" + options$wlsWeights <- "debNaN" + options$modelTerms <- list(list(components="contNormal", isNuisance=FALSE)) + results <- jasptools::run("RegressionLinear", "test.csv", options, view=FALSE, quiet=TRUE) + expect_identical(results[["results"]][["model summary"]][["error"]][["errorType"]], "badData", + label="Too few obs wlsWeights check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-regressionloglinear.R b/JASP-Tests/R/tests/testthat/test-regressionloglinear.R new file mode 100644 index 0000000000..d032036569 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-regressionloglinear.R @@ -0,0 +1,61 @@ +context("Log-Linear Regression") + +# does not test +# - error handling + +test_that("Main table results match", { + options <- jasptools::analysisOptions("RegressionLogLinear") + options$counts <- "facFifty" + options$factors <- c("contBinom", "facGender") + options$modelTerms <- list( + list(components="contBinom"), + list(components="facGender"), + list(components=c("contBinom", "facGender")) + ) + results <- jasptools::run("RegressionLogLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["logregressionanova"]][["data"]] + expect_equal_tables(table, + list("NULL", "", " ", 99, 936.356249443911, " ", " ", "contBinom", + "", 9.73545292814663, 98, 926.620796515764, 0.00180747470901472, + 1, "facGender", "", 7.02546792150429, 97, 919.59532859426, 0.00803584702758609, + 1, "contBinomfacGender", "", 0.769509416901883, + 96, 918.825819177358, 0.380368860922424, 1) + ) +}) + +test_that("Coefficients table matches", { + options <- jasptools::analysisOptions("RegressionLogLinear") + options$counts <- "facFifty" + options$factors <- c("contBinom", "facFive") + options$modelTerms <- list( + list(components="contBinom"), + list(components="facFive"), + list(components=c("contBinom", "facFive")) + ) + options$regressionCoefficientsEstimates <- TRUE + options$regressionCoefficientsConfidenceIntervals <- TRUE + options$regressionCoefficientsConfidenceIntervalsInterval <- 0.95 + results <- jasptools::run("RegressionLogLinear", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["logregression"]][["data"]] + expect_equal_tables(table, + list("(Intercept)", 3.36441813015886, 0.0536828127084252, 3.25920175066154, + 3.46963450965618, 62.6721656414034, 0, "contBinom = 1", -0.63167531645938, + 0.104937579028612, -0.837349191980285, -0.426001440938476, -6.01953392013314, + 1.74920000092307e-09, "facFive = 2", -0.379859157202991, 0.0921944777734458, + -0.560557013212423, -0.199161301193559, -4.1201942499901, 3.78553110594005e-05, + "facFive = 3", -0.343993244014492, 0.0833479734033365, -0.507352270069434, + -0.18063421795955, -4.1271938592897, 3.67216813648207e-05, "facFive = 4", + -0.250902820948484, 0.085593742903271, -0.418663474340876, -0.0831421675560923, + -2.93132199198285, 0.00337522739489266, "facFive = 5", -0.0685812641545293, + 0.0731503942633908, -0.211953402365681, 0.0747908740566221, + -0.937537860802095, 0.348481958057894, "contBinom = 1*facFive = 2", + 0.992224258514625, 0.140836788661736, 0.716189225039344, 1.26825929198991, + 7.04520649713029, 1.85186666239764e-12, "contBinom = 1*facFive = 3", + 1.10775799178149, 0.137349243064596, 0.838558422071047, 1.37695756149194, + 8.06526462807306, 7.30773999647178e-16, "contBinom = 1*facFive = 4", + 0.935886690862371, 0.136875960028964, 0.667614738856258, 1.20415864286848, + 6.83748037759394, 8.05981239553115e-12, "contBinom = 1*facFive = 5", + 0.703134280441524, 0.142750071638859, 0.423349281238848, 0.982919279644201, + 4.92563171681182, 8.40882439228307e-07) + ) +}) diff --git a/JASP-Tests/R/tests/testthat/test-regressionloglinearbayesian.R b/JASP-Tests/R/tests/testthat/test-regressionloglinearbayesian.R new file mode 100644 index 0000000000..d8e030df6a --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-regressionloglinearbayesian.R @@ -0,0 +1,96 @@ +context("Bayesian Log-Linear Regression") + +# does not test +# - error handling + +initOpts <- function() { + options <- jasptools::analysisOptions("RegressionLogLinearBayesian") + options$sampleMode <- "manual" + options$fixedSamplesNumber <- 100 + return(options) +} + +test_that("Main table results match", { + set.seed(0) + options <- initOpts() + options$counts <- "facFifty" + options$factors <- c("contBinom", "facGender") + options$modelTerms <- list( + list(components="contBinom"), + list(components="facGender"), + list(components=c("contBinom", "facGender")) + ) + options$priorScale <- 1 + options$priorShape <- 0 + options$maxModels <- 2 + options$posteriorProbabilityCutOff <- 0.001 + results <- jasptools::run("RegressionLogLinearBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["posteriorTable"]][["data"]] + expect_equal_tables(table, + list(1, "contBinom + facGender", 0.963333333333333, 1, 2, + "contBinom + facGender + contBinomfacGender", + 0.0366666666666667, 0.0380622837370242) + ) +}) + +test_that("General summary statistics table matches", { + set.seed(0) + options <- initOpts() + options$factors <- c("contBinom", "facFive") + options$modelTerms <- list( + list(components="contBinom"), + list(components="facFive"), + list(components=c("contBinom", "facFive")) + ) + options$regressionCoefficientsEstimates <- TRUE + options$regressionCoefficientsCredibleIntervals <- TRUE + options$regressionCoefficientsCredibleIntervalsInterval <- 0.90 + results <- jasptools::run("RegressionLogLinearBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["Bayesianlogregression"]][["data"]] + expect_equal_tables(table, + list("(Intercept)", 1, 2.28941355597128, 0.0114477565469203, 2.12177466183418, + 2.45495750281602, "contBinom = 0", 1, 0.0303566571915708, 0.00356265251723887, + -0.0378564465631073, 0.144271031109649, "facFive = 1", 1, -0.00552214172853799, + 0.00720162344071968, -0.130345670875483, 0.138580850953902, + "facFive = 2", 1, -0.00240692298068409, 0.00784162472732633, + -0.121705317175139, 0.165537141029262, "facFive = 3", 1, 0.00293548076176623, + 0.00745020526106448, -0.0900898563442242, 0.187558384342406, + "facFive = 4", 1, 0.00138448207875663, 0.00779485819569601, + -0.122842441315205, 0.155851155312602, "contBinom = 0*facFive = 1", + 0.571428571428571, 0.00197519410432235, 0.00569094808602158, + -0.125500914290167, 0.103584632765005, "contBinom = 0*facFive = 2", + 0.571428571428571, -0.0270367686155361, 0.00624820819787772, + -0.180746332353481, 0.0610871410555307, "contBinom = 0*facFive = 3", + 0.571428571428571, 0.00343309539396836, 0.00598953855547496, + -0.145370964229942, 0.0973020746027855, "contBinom = 0*facFive = 4", + 0.571428571428571, -0.0218844778500034, 0.00501003480774965, + -0.131413707533984, 0.101000867077934) + ) +}) + +test_that("Submodel summary statistics table matches", { + set.seed(0) + options <- initOpts() + options$factors <- c("contBinom", "facFive") + options$modelTerms <- list( + list(components="contBinom"), + list(components="facFive"), + list(components=c("contBinom", "facFive")) + ) + options$regressionCoefficientsSubmodel <- TRUE + options$regressionCoefficientsSubmodelCredibleIntervals <- TRUE + options$regressionCoefficientsSubmodelEstimates <- TRUE + options$regressionCoefficientsSubmodelNo <- 2 + results <- jasptools::run("RegressionLogLinearBayesian", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["BayesianSublogregression"]][["data"]] + expect_equal_tables(table, + list("(Intercept)", 2.29560729883006, 0.00945972825329099, 2.12809954463567, + 2.52220705393406, "contBinom = 0", 0.045757962353209, 0.00487119274553831, + -0.0378564465631073, 0.235518792759572, "facFive = 1", -0.00411654631578624, + 0.00919225838347475, -0.189678327954162, 0.225524507296169, + "facFive = 2", -0.00755884938209783, 0.0107688538955323, -0.230464286621307, + 0.203303292163532, "facFive = 3", 0.00693535371456428, 0.00958840576151784, + -0.151633708350598, 0.242411127225971, "facFive = 4", 0.00306711588492548, + 0.0107120223942474, -0.234264000793185, 0.230287649489829) + ) +}) diff --git a/JASP-Tests/R/tests/testthat/test-reliabilityanalysis.R b/JASP-Tests/R/tests/testthat/test-reliabilityanalysis.R new file mode 100644 index 0000000000..f46ca6314e --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-reliabilityanalysis.R @@ -0,0 +1,47 @@ +context("Reliability Analysis") + +# does not test +# - missing values exclusion + +test_that("Main table results match", { + options <- jasptools::analysisOptions("ReliabilityAnalysis") + options$variables <- c("contcor1", "contcor2", "contNormal") + options$reverseScaledItems <- "contcor2" + options$alphaScale <- TRUE + options$averageInterItemCor <- TRUE + options$confAlpha <- TRUE + options$glbScale <- TRUE + options$gutmannScale <- TRUE + options$mcDonaldScale <- TRUE + options$meanScale <- TRUE + options$sdScale <- TRUE + results <- jasptools::run("ReliabilityAnalysis", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["reliabilityScale"]][["data"]] + expect_equal_tables(table, + list("scale", -0.757822989578577, -0.0677657928415725, 0.667932535083157, + 0.622700230679449, -0.175972651899464, -0.02217061461, 0.144515070286093, + -1.45211881901153, -0.235388804018903) + ) +}) + +test_that("Item Statistics table matches", { + options <- jasptools::analysisOptions("ReliabilityAnalysis") + options$variables <- c("contcor1", "contcor2", "contNormal") + options$alphaItem <- TRUE + options$confAlpha <- TRUE + options$gutmannItem <- TRUE + options$itemRestCor <- TRUE + options$mcDonaldItem <- TRUE + options$meanItem <- TRUE + options$sdItem <- TRUE + results <- jasptools::run("ReliabilityAnalysis", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["reliabilityItemsObj"]][["reliabilityItems"]][["data"]] + expect_equal_tables(table, + list("contcor1", 0.0618194975467092, 0.0319398198963565, 0.061902485553013, + 0.560156128034403, 0.05254867287, 1.01183864387684, "contcor2", + 0.277152727398941, 0.161031927910319, 0.27739448681683, 0.442807451055322, + 0.06968807084, 1.0041493380131, "contNormal", 0.79299280264282, + 0.657010063712354, 0.793006727117146, 0.106272823965938, -0.18874858754, + 1.05841360919316) + ) +}) diff --git a/JASP-Tests/R/tests/testthat/test-ttestbayesianindependentsamples.R b/JASP-Tests/R/tests/testthat/test-ttestbayesianindependentsamples.R new file mode 100644 index 0000000000..0999787fdd --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ttestbayesianindependentsamples.R @@ -0,0 +1,122 @@ +context("Bayesian Independent Samples T-Test") + +# does not test +# - bftype (01, 10) +# - missing value exclusion +# - informed prior Normal/t distributions +# - error handling of plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$hypothesis <- "groupOneGreater" + options$effectSizeStandardized <- "informative" + options$informativeCauchyLocation <- 1 + options$informativeCauchyScale <- 0.5 + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, list("contNormal", 0.123677493243643, 0.0895633315624481)) +}) + +test_that("Prior posterior plot matches", { + set.seed(0) + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$plotPriorAndPosterior <- TRUE + options$plotPriorAndPosteriorAdditionalInfo <- TRUE + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "prior-posterior", dir="TTestBayesianIndependentSamples") +}) + +test_that("BF robustness check plot matches", { + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$plotBayesFactorRobustness <- TRUE + options$plotBayesFactorRobustnessAdditionalInfo <- FALSE + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "robustness-check", dir="TTestBayesianIndependentSamples") +}) + +test_that("Sequential analysis plot matches", { + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$plotSequentialAnalysis <- TRUE + options$plotSequentialAnalysisRobustness <- TRUE + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "sequential-analysis", dir="TTestBayesianIndependentSamples") +}) + +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$descriptivesPlots <- TRUE + options$descriptivesPlotsCredibleInterval <- 0.90 + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestBayesianIndependentSamples") +}) + +test_that("Descriptives table matches", { + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$descriptives <- TRUE + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list("contNormal", 0, 58, -0.120135614827586, 1.10575982846952, 0.145193378675912, + -0.410880340543859, 0.170609110888686, "TRUE", "contNormal", + 1, 42, -0.283499835571429, 0.994612407217046, 0.15347202634745, + -0.593442880596763, 0.0264432094539058) + ) +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + + options$variables <- "debInf" + options$groupingVariable <- "contBinom" + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$variables <- "debSame" + options$groupingVariable <- "contBinom" + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$variables <- "debMiss99" + options$groupingVariable <- "contBinom" + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") + + options$dependent <- "contNormal" + options$groupingVariable <- "debSame" + results <- jasptools::run("TTestBayesianIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + msg <- results[["results"]][["errorMessage"]] + expect_true(any(grepl("levels", msg, ignore.case=TRUE)), label = "1-level factor check") +}) + +test_that("Analysis handles integer overflow", { + set.seed(4491) + dat <- data.frame(dependent_var = rnorm(2e5), + grouping = rep(c(1, 2), each = 1e5)) + + options <- jasptools::analysisOptions("TTestBayesianIndependentSamples") + options$variables <- 'dependent_var' + options$groupingVariable <- 'grouping' + results <- jasptools::run("TTestBayesianIndependentSamples", dat, options, view=FALSE, quiet=TRUE) + + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, list("dependent_var", 0.00511047418810093, 0.311955453811728)) +}) \ No newline at end of file diff --git a/JASP-Tests/R/tests/testthat/test-ttestbayesianonesample.R b/JASP-Tests/R/tests/testthat/test-ttestbayesianonesample.R new file mode 100644 index 0000000000..02eef0e301 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ttestbayesianonesample.R @@ -0,0 +1,90 @@ +context("Bayesian One Sample T-Test") + +# does not test +# - bftype (01, 10) +# - missing value exclusion +# - default cauchy and informed prior cauchy/Normal +# - error handling of plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("TTestBayesianOneSample") + options$variables <- "contNormal" + options$effectSizeStandardized <- "default" + options$defaultStandardizedEffectSize <- "cauchy" + options$priorWidth <- 0.707 + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, list("contNormal", 0.508160332089536, 2.80907441042415e-05)) +}) + +test_that("Prior posterior plot matches", { + set.seed(0) + options <- jasptools::analysisOptions("TTestBayesianOneSample") + options$variables <- "contNormal" + options$plotPriorAndPosterior <- TRUE + options$plotPriorAndPosteriorAdditionalInfo <- TRUE + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "prior-posterior", dir="TTestBayesianOneSample") +}) + +test_that("BF robustness check plot matches", { + options <- jasptools::analysisOptions("TTestBayesianOneSample") + options$variables <- "contNormal" + options$plotBayesFactorRobustness <- TRUE + options$plotBayesFactorRobustnessAdditionalInfo <- FALSE + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "robustness-check", dir="TTestBayesianOneSample") +}) + +test_that("Sequential analysis plot matches", { + options <- jasptools::analysisOptions("TTestBayesianOneSample") + options$variables <- "contNormal" + options$plotSequentialAnalysis <- TRUE + options$plotSequentialAnalysisRobustness <- TRUE + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "sequential-analysis", dir="TTestBayesianOneSample") +}) + +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestBayesianOneSample") + options$variables <- "contNormal" + options$descriptivesPlots <- TRUE + options$descriptivesPlotsCredibleInterval <- 0.90 + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestBayesianOneSample") +}) + +test_that("Descriptives table matches", { + options <- jasptools::analysisOptions("TTestBayesianOneSample") + options$variables <- "contNormal" + options$descriptives <- TRUE + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list("contNormal", 100, -0.18874858754, 1.05841360919316, 0.105841360919316, + -0.398760810055083, 0.0212636349750834) + ) +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("TTestBayesianOneSample") + + options$variables <- "debInf" + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$variables <- "debSame" + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$variables <- "debMiss99" + results <- jasptools::run("TTestBayesianOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-ttestbayesianpairedsamples.R b/JASP-Tests/R/tests/testthat/test-ttestbayesianpairedsamples.R new file mode 100644 index 0000000000..927e5532fb --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ttestbayesianpairedsamples.R @@ -0,0 +1,94 @@ +context("Bayesian Paired Samples T-Test") + +# does not test +# - bftype (01, 10) +# - missing value exclusion +# - default cauchy and informed prior cauchy/Normal +# - error handling of plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$hypothesis <- "groupOneGreater" + options$effectSizeStandardized <- "informative" + options$informativeStandardizedEffectSize <- "t" + options$informativeTLocation <- 0.2 + options$informativeTScale <- 0.5 + options$informativeTDf <- 2 + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, list("contNormal", "-", "contGamma", 293915424756.037, 1.32616895200622e-19)) +}) + +test_that("Prior posterior plot matches", { + set.seed(0) + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$plotPriorAndPosterior <- TRUE + options$plotPriorAndPosteriorAdditionalInfo <- TRUE + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "prior-posterior", dir="TTestBayesianPairedSamples") +}) + +test_that("BF robustness check plot matches", { + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$plotBayesFactorRobustness <- TRUE + options$plotBayesFactorRobustnessAdditionalInfo <- FALSE + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "robustness-check", dir="TTestBayesianPairedSamples") +}) + +test_that("Sequential analysis plot matches", { + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$plotSequentialAnalysis <- TRUE + options$plotSequentialAnalysisRobustness <- TRUE + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "sequential-analysis", dir="TTestBayesianPairedSamples") +}) + +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$descriptivesPlots <- TRUE + options$descriptivesPlotsCredibleInterval <- 0.90 + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestBayesianPairedSamples") +}) + +test_that("Descriptives table matches", { + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$descriptives <- TRUE + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list("contNormal", 100, -0.18874858754, 1.05841360919316, 0.105841360919316, + -0.398760810055083, 0.0212636349750834, "contGamma", 100, 2.03296079621, + 1.53241112621044, 0.153241112621044, 1.72889718286736, 2.33702440955264) + ) +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("TTestBayesianPairedSamples") + + options$pairs <- list(c("contNormal", "debInf")) + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$pairs <- list(c("contNormal", "debSame")) + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$pairs <- list(c("contNormal", "debMiss99")) + results <- jasptools::run("TTestBayesianPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-ttestindependentsamples.R b/JASP-Tests/R/tests/testthat/test-ttestindependentsamples.R new file mode 100644 index 0000000000..c083e3e51b --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ttestindependentsamples.R @@ -0,0 +1,104 @@ +context("Independent Samples TTest") + +# does not test +# - missing values exclusion +# - error handling of plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$welchs <- TRUE + options$mannWhitneyU <- TRUE + options$meanDifference <- TRUE + options$effectSize <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, + list("contNormal", "Student", 98, 0.448976320466698, 0.163364220743842, + 0.15401876311258, -0.263105943067512, 0.589834384555196, 0, + 0, 0.214904085649005, 0.760172707980336, 1, "contNormal", "Welch", + 93.4114683704755, 0.441326472332004, 0.163364220743842, 0.155340050635411, + -0.256150680877671, 0.582879122365355, 0, 0, 0.211269449004155, + 0.773250564688269, 1, "contNormal", "Mann-Whitney", "", 0.617539087467476, + 0.0932984248674163, 0.0591133004926108, -0.269303374938764, + 0.553341045241524, -0.169577908162339, 0.281763520076616, "", + 1290, 1) + ) +}) + +test_that("Normality table matches", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$normalityTests <- TRUE + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["assumptionChecks"]][["shapiroWilk"]][["data"]] + expect_equal_tables(table, + list("contNormal", 0, 0.933547444665698, 0.00342000811150064, "TRUE", + "contNormal", 1, 0.972586424088514, 0.401705854633909, "FALSE") + ) +}) + +test_that("Equality of variances table matches", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$equalityOfVariancesTests<- TRUE + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["assumptionChecks"]][["levene"]][["data"]] + expect_equal_tables(table, list("contNormal", 0.474760708390762, 1, 0.492433247088434)) +}) + +test_that("Descriptives table matches", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$descriptives <- TRUE + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list("contNormal", 0, 58, -0.120135614827586, 1.10575982846952, 0.145193378675912, + "TRUE", "contNormal", 1, 42, -0.283499835571429, 0.994612407217046, + 0.15347202634745) + ) +}) + +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$descriptivesPlots <- TRUE + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestIndependentSamples") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + + options$variables <- "debInf" + options$groupingVariable <- "contBinom" + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$variables <- "debSame" + options$groupingVariable <- "contBinom" + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$variables <- "debMiss99" + options$groupingVariable <- "contBinom" + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") + + options$dependent <- "contNormal" + options$groupingVariable <- "debSame" + results <- jasptools::run("TTestIndependentSamples", "test.csv", options, view=FALSE, quiet=TRUE) + msg <- results[["results"]][["errorMessage"]] + expect_true(any(grepl("levels", msg, ignore.case=TRUE)), label = "1-level factor check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-ttestonesample.R b/JASP-Tests/R/tests/testthat/test-ttestonesample.R new file mode 100644 index 0000000000..655066b266 --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ttestonesample.R @@ -0,0 +1,70 @@ +context("One Sample TTest") + +# does not test +# - missing values exclusion +# - error handling of plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("TTestOneSample") + options$variables <- "contGamma" + options$wilcoxonSignedRank <- TRUE + options$meanDifference <- TRUE + options$effectSize <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, + list("contGamma", 99, 1.08315413981152e-23, 2.03296079621, 1.32664189226908, + 1.72889718286736, 2.33702440955264, 0, 0, 13.2664189226908, + 6.42284229078859e+20) + ) +}) + +test_that("Normality table matches", { + options <- jasptools::analysisOptions("TTestOneSample") + options$variables <- "contGamma" + options$normalityTests <- TRUE + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["assumptionChecks"]][["shapiroWilk"]][["data"]] + expect_equal_tables(table, list("contGamma", 0.876749741598208, 1.32551553117109e-07, "TRUE")) +}) + +test_that("Descriptives table matches", { + options <- jasptools::analysisOptions("TTestOneSample") + options$variables <- "contGamma" + options$descriptives <- TRUE + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list("contGamma", 100, 2.03296079621, 1.53241112621044, 0.153241112621044, + "TRUE") + ) +}) + +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestOneSample") + options$variables <- "contGamma" + options$descriptivesPlots <- TRUE + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestOneSample") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("TTestOneSample") + + options$variables <- "debInf" + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$variables <- "debSame" + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$variables <- "debMiss99" + results <- jasptools::run("TTestOneSample", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/R/tests/testthat/test-ttestpairedsamples.R b/JASP-Tests/R/tests/testthat/test-ttestpairedsamples.R new file mode 100644 index 0000000000..a69ac2eb1c --- /dev/null +++ b/JASP-Tests/R/tests/testthat/test-ttestpairedsamples.R @@ -0,0 +1,76 @@ +context("Paired Samples TTest") + +# does not test +# - missing values exclusion +# - error handling of plots + +test_that("Main table results match", { + options <- jasptools::analysisOptions("TTestPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$wilcoxonSignedRank <- TRUE + options$hypothesis <- "groupOneGreater" + options$meanDifference <- TRUE + options$effectSize <- TRUE + options$VovkSellkeMPR <- TRUE + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["ttest"]][["data"]] + expect_equal_tables(table, + list(99, 1, -2.22170938375, -1.16121720596087, -2.53938523225467, "", + 0, 0, 0.191325909773409, 1, -11.6121720596087, "contNormal", + "-", "contGamma", "Student", "", 0.999999999999999, -2.1796113893332, + -0.921188118811881, -2.48184167915216, "", -0.94536640190499, + "", "", 1, 199, "", "", "", "Wilcoxon") + ) +}) + +test_that("Normality table matches", { + options <- jasptools::analysisOptions("TTestPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$normalityTests <- TRUE + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["assumptionChecks"]][["shapiroWilk"]][["data"]] + expect_equal_tables(table, + list("contNormal", "-", "contGamma", 0.969542808533914, 0.0203952735337306, + "TRUE") + ) +}) + +test_that("Descriptives table matches", { + options <- jasptools::analysisOptions("TTestPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$descriptives <- TRUE + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + table <- results[["results"]][["descriptives"]][["descriptivesTable"]][["data"]] + expect_equal_tables(table, + list("contNormal", 100, -0.18874858754, 1.05841360919316, 0.105841360919316, + "contGamma", 100, 2.03296079621, 1.53241112621044, 0.153241112621044) + ) +}) + +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestPairedSamples") + options$pairs <- list(c("contNormal", "contGamma")) + options$descriptivesPlots <- TRUE + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestPairedSamples") +}) + +test_that("Analysis handles errors", { + options <- jasptools::analysisOptions("TTestPairedSamples") + + options$pairs <- list(c("contNormal", "debInf")) + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("infinity", notes, ignore.case=TRUE)), label = "Inf check") + + options$pairs <- list(c("contNormal", "debSame")) + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("variance", notes, ignore.case=TRUE)), label = "No variance check") + + options$pairs <- list(c("contNormal", "debMiss99")) + results <- jasptools::run("TTestPairedSamples", "test.csv", options, view=FALSE, quiet=TRUE) + notes <- unlist(results[["results"]][["ttest"]][["footnotes"]]) + expect_true(any(grepl("observations", notes, ignore.case=TRUE)), label = "Too few obs check") +}) diff --git a/JASP-Tests/README.md b/JASP-Tests/README.md index 3881265439..c4b3fc63a9 100644 --- a/JASP-Tests/README.md +++ b/JASP-Tests/README.md @@ -1,5 +1,5 @@ -Unit Tests +Core - Unit Tests ========== Guide to build Unit test project and run @@ -44,11 +44,122 @@ Analyses - Unit Tests Running the tests ----------------- -Currently, the Analyses unit tests are not integrated into the JASP-Tests app. -To run the tests, R commandline is required. Working directory must point to JASP-Tests folder and then run +Currently, the analysis unit tests are not integrated into the JASP-Tests app. +To run the tests, the R package [jasptools](https://github.com/jasp-stats/jasptools) is required. +Note that this package does not need to be installed manually; it is installed automatically when you clone the jasp-desktop environment. +To load the package simply type `library(jasptools, lib.loc="path/to/jasp-desktop/Tools")` +To run all tests type ``` -source("run_tests.R") +jasptools::testAll() ``` -Any test fails are shown up in the console. \ No newline at end of file +Any test that fails is shown in the console. +Warnings may be ignored, but should be minimized. + +It is also possible to test a specific analysis, as running all unit tests may take some time +``` +jasptools::testAnalysis("Anova") +``` + +Fixing the tests +---------------- +If a test shows up as failed, you should verify why this is and fix it before making a pull request. +If you made a legitimate change that the test does not cover, then the unit test should be updated. +Locate it under [JASP-Tests/R/tests/testthat](https://github.com/jasp-stats/jasp-desktop/tree/development/JASP-Tests/R/tests/testthat) and change the offending test. +Note that if the failed test was related to plotting, then you may use +``` +jasptools::inspectTestPlots("Anova") +``` +to inspect differences between the saved reference plot and the failing plot. +If you validate the failing plot (because it was a legitimate change), it will replace the reference plot in the figs folder. +Please ensure that there are no changes to figs/deps.txt as a result of your change (see the section below about "Dependencies related to plots"). + +Writing new tests +----------------- +The analysis tests in JASP are based on the R package testthat. +For more information about this package see [this online book chapter by Hadley Wickam](http://r-pkgs.had.co.nz/tests.html). + +The general structure of the tests is as follows: +\- A folder titled testthat contains a number of test-analysisName.R files. +-- Each test file has an analysis specific context and consists of tests that check that specific analysis. +--- Each test in a file checks a specific expectation of a small portion of analysis functionality (e.g., a table, a plot, error handling, etc.) + +The testthat package offers a number of expectations useful for testing. +JASP offers two additional expectations: +``` +expect_equal_tables(test, ref, ...) +expect_equal_plots(test, name, dir) +``` +`expect_equal_tables` takes the data of a JASP table list and compares it to a reference list. +This reference list can be created by supplying a table to jasptools. +``` +options <- jasptools::analysisOptions("BinomialTest") +options[["variables"]] <- "contBinom" +results <- jasptools::run("BinomialTest", "debug.csv", options, view=FALSE) +table <- results[["results"]][["binomial"]][["data"]] +jasptools::makeTestTable(table) +``` +The above returns the output + +`list("contBinom", 0, 58, 100, 0.58, 0.133210619207213, 0.477119195723914, + 0.678014460645203, "TRUE", "contBinom", 1, 42, 100, 0.42, 0.133210619207213, + 0.321985539354797, 0.522880804276086, "FALSE")` + +We can now write the expectation +``` +test_that("Binomial table results match", { + options <- jasptools::analysisOptions("BinomialTest") + options[["variables"]] <- "contBinom" + results <- jasptools::run("BinomialTest", "debug.csv", options, view=FALSE) + table <- results[["results"]][["binomial"]][["data"]] + expect_equal_tables(table, + list("contBinom", 0, 58, 100, 0.58, 0.133210619207213, 0.477119195723914, + 0.678014460645203, "TRUE", "contBinom", 1, 42, 100, 0.42, 0.133210619207213, + 0.321985539354797, 0.522880804276086, "FALSE")) +}) +``` + +`expect_equal_tables` is a wrapper around `testthat::expect_equal` and accepts the same arguments. + +In a similar fashion `expect_equal_plots` may be used to test regression of plots. +This function is a wrapper around `vdiffr::expect_doppelganger` (for more information about vdffir see their [github page](https://github.com/lionel-/vdiffr)). +The function takes a plot object or recorded plot and compares it to a stored .svg file. +This results in an expectation like +``` +test_that("Descriptives plot matches", { + options <- jasptools::analysisOptions("TTestIndependentSamples") + options$variables <- "contNormal" + options$groupingVariable <- "contBinom" + options$descriptivesPlots <- TRUE + results <- jasptools::run("TTestIndependentSamples", "debug.csv", options, view=FALSE) + testPlot <- results[["state"]][["figures"]][[1]] + expect_equal_plots(testPlot, "descriptives", dir="TTestIndependentSamples") +}) +``` +To validate a plot for a newly created test, run +``` +jasptools::inspectTestPlots("TTestIndependentSamples") +``` +This function starts a Shiny application that allows you to view and then validate your new plot. +Validating a plot places it in figs/analysisName. + +As noted earlier, testthat offers a number of expectations as well. +You should use whatever is most suitable for the situation. + +#### Dependencies related to plots +Note that it is very important that all plots are created with equal versions of certain dependencies. +If this is not the case, then we cannot compare plots across different systems and platforms. +The settings you must use can be found in [figs/deps.txt](https://github.com/jasp-stats/jasp-desktop/blob/development/JASP-Tests/R/tests/figs/deps.txt) +This file will look something like (but not necessarily the same as) +``` +Fontconfig: 2.11.94 +FreeType: 2.6.1 +Cairo: 1.14.6 +vdiffr: 0.2.1 +svglite: 1.2.1 +ggplot2: 2.2.1 +``` +You must never edit deps.txt unless the travis-CI config is updated as well. +If you have different versions of the dependencies installed the plots will be skipped. +In this case either update your configuration or rely on the automatic test that start when you make a pull request. diff --git a/JASP-Tests/analysesTests/test_summarystatsttestbayesianindepenedentsamples.R b/JASP-Tests/analysesTests/test_summarystatsttestbayesianindepenedentsamples.R deleted file mode 100644 index a296dee47e..0000000000 --- a/JASP-Tests/analysesTests/test_summarystatsttestbayesianindepenedentsamples.R +++ /dev/null @@ -1,102 +0,0 @@ -# -# Copyright (C) 2017 University of Amsterdam -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - - -# initialize function parameters -options <- list( - bayesFactorType = "BF10", - hypothesis = "groupsNotEqual", - n1Size = 0, - n2Size = 0, - tStatistic = 0, - plotBayesFactorRobustness = FALSE, - plotPriorAndPosterior = FALSE, - plotPriorAndPosteriorAdditionalInfo = FALSE, - priorWidth = 0.707 - ) - -perform <- "init" - - -test_that("T-Test Independent Samples Init", { - output <- SummaryStatsTTestBayesianIndependentSamples( - options = options, - perform = perform, - callback = NULL - ) - - # sanity check - output should not be NULL - expect_equal(!is.null(output["results"]), TRUE) - - expectedOutput <- list() - - if (perform == "init") { - expectedOutput = list(list( - BF = ".", - tStatistic = 0, - n1Size = ".", - errorEstimate = ".", - n2Size = "." - ) - ) - } - - perform <- output$status - - # status is 'inited' after 'init' in performed - expect_equal(perform, "inited") - expect_equal(output$results$table$data, expectedOutput) -}) - -perform <- "run" - -test_that("T-Test Independent Samples Run", { - - # generate random group1 and group2 sizes - n1Size = floor(runif(1, min = 2, max = 999999)) - n2Size = floor(runif(1, min = 2, max = 999999)) - - # generate a random t value in the range (-10,10) - tStatistic = runif(1, min = -10, max = 10) - - expectedBF <- BayesFactor::ttest.tstat( - t = tStatistic, - n1 = n1Size, - n2 = n2Size, - rscale = options$priorWidth, - nullInterval = NULL - ) - - expectedOutput <- list( - BF = .clean(exp(expectedBF$bf)), - tStatistic = .clean(tStatistic), - n1Size = n1Size, - errorEstimate = .clean(expectedBF$properror), - n2Size = n2Size - ) - - options$tStatistic <- tStatistic - options$n1Size <- n1Size - options$n2Size <- n2Size - output <- SummaryStatsTTestBayesianIndependentSamples( - options = options, - perform = perform, - callback = NULL - ) - - expect_equal(output$state$rowsTTestBayesianIndependentSamples, expectedOutput) -}) diff --git a/JASP-Tests/analysesTests/test_summarystatsttestbayesianonesample.R b/JASP-Tests/analysesTests/test_summarystatsttestbayesianonesample.R deleted file mode 100644 index 26fa583e4c..0000000000 --- a/JASP-Tests/analysesTests/test_summarystatsttestbayesianonesample.R +++ /dev/null @@ -1,98 +0,0 @@ -# -# Copyright (C) 2017 University of Amsterdam -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - - -# initialize function parameters -options <- list( - bayesFactorType = "BF10", - hypothesis = "notEqualToTestValue", - n1Size = 0, - tStatistic = 0, - plotBayesFactorRobustness = FALSE, - plotPriorAndPosterior = FALSE, - plotPriorAndPosteriorAdditionalInfo = FALSE, - priorWidth = 0.707 - ) - -perform <- "init" - - -test_that("T-Test One Sample Init", { - output <- SummaryStatsTTestBayesianOneSample( - options = options, - perform = perform, - callback = NULL - ) - - # Sanity Check - output should not be NULL - expect_equal(!is.null(output["results"]), TRUE) - - expectedOutput <- list() - - if (perform == "init") { - expectedOutput = list(list( - BF = ".", - tStatistic = 0, - n1Size = ".", - errorEstimate = "." - ) - ) - } - - perform <- output$status - - # status is 'inited' after 'init' in performed - expect_equal(perform, "inited") - expect_equal(output$results$table$data, expectedOutput) -}) - -perform <- "run" - -test_that("T-Test One Sample Run", { - - # generate a random sample size - n1Size = floor(runif(1, min = 2, max = 999999)) - - # generate a random t value in the range (-10,10) - tStatistic = runif(1, min = -10, max = 10) - - expectedBF <- BayesFactor::ttest.tstat( - t = tStatistic, - n1 = n1Size, - n2 = 0, - rscale = options$priorWidth, - nullInterval = NULL - ) - - expectedOutput <- list( - BF = .clean(exp(expectedBF$bf)), - tStatistic = .clean(tStatistic), - n1Size = n1Size, - errorEstimate = .clean(expectedBF$properror) - ) - - options$tStatistic <- tStatistic - options$n1Size <- n1Size - output <- SummaryStatsTTestBayesianOneSample( - options = options, - perform = perform, - callback = NULL - ) - - expect_equal(output$state$rowsTTestBayesianOneSample, expectedOutput) -}) - diff --git a/JASP-Tests/analysesTests/test_summarystatsttestbayesianpairedsamples.R b/JASP-Tests/analysesTests/test_summarystatsttestbayesianpairedsamples.R deleted file mode 100644 index bd167b7606..0000000000 --- a/JASP-Tests/analysesTests/test_summarystatsttestbayesianpairedsamples.R +++ /dev/null @@ -1,98 +0,0 @@ -# -# Copyright (C) 2017 University of Amsterdam -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - - -# initialize function parameters -options <- list( - bayesFactorType = "BF10", - hypothesis = "groupsNotEqual", - n1Size = 0, - tStatistic = 0, - plotBayesFactorRobustness = FALSE, - plotPriorAndPosterior = FALSE, - plotPriorAndPosteriorAdditionalInfo = FALSE, - priorWidth = 0.707 - ) - -perform <- "init" - - -test_that("T-Test Paired Samples Init", { - output <- SummaryStatsTTestBayesianPairedSamples( - options = options, - perform = perform, - callback = NULL - ) - - # Sanity Check - output should not be NULL - expect_equal(!is.null(output["results"]), TRUE) - - expectedOutput <- list() - - if (perform == "init") { - expectedOutput = list(list( - BF = ".", - tStatistic = 0, - n1Size = ".", - errorEstimate = "." - ) - ) - } - - perform <- output$status - - # status is 'inited' after 'init' in performed - expect_equal(perform, "inited") - expect_equal(output$results$table$data, expectedOutput) -}) - -perform <- "run" - -test_that("T-Test Paired Samples Run", { - - # generate a random sample size - n1Size = floor(runif(1, min = 2, max = 999999)) - - # generate a random t value in the range (-10,10) - tStatistic = runif(1, min = -10, max = 10) - - expectedBF <- BayesFactor::ttest.tstat( - t = tStatistic, - n1 = n1Size, - n2 = 0, - rscale = options$priorWidth, - nullInterval = NULL - ) - - expectedOutput <- list( - BF = .clean(exp(expectedBF$bf)), - tStatistic = .clean(tStatistic), - n1Size = n1Size, - errorEstimate = .clean(expectedBF$properror) - ) - - options$tStatistic <- tStatistic - options$n1Size <- n1Size - output <- SummaryStatsTTestBayesianPairedSamples( - options = options, - perform = perform, - callback = NULL - ) - - expect_equal(output$state$rowsTTestBayesianPairedSamples, expectedOutput) -}) - diff --git a/JASP-Tests/odsimporter_test.cpp b/JASP-Tests/odsimporter_test.cpp new file mode 100644 index 0000000000..1f2f704f54 --- /dev/null +++ b/JASP-Tests/odsimporter_test.cpp @@ -0,0 +1,182 @@ +// +// Copyright (C) 2017 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "odsimporter_test.h" +#include +#include + + +void ODSImporterTest::init() +{ + fe_ods = new FileEvent(); + asl_ods = new AsyncLoader(); + fe_csv = new FileEvent(); + asl_csv = new AsyncLoader(); +} + + +void ODSImporterTest::cleanup() +{ + fe_ods->~FileEvent(); + asl_ods->~AsyncLoader(); + fe_csv->~FileEvent(); + asl_csv->~AsyncLoader(); +} + + +void ODSImporterTest::odsTester_data() +{ + QTest::addColumn("filename"); + + boost::filesystem::path _path(TESTFILE_FOLDER "odsimporter_test/ods_files"); + + //add files to be tested in a folder "Resources/TestFiles/odsimporter_test/ods_files" + for (auto i = boost::filesystem::directory_iterator(_path); i != boost::filesystem::directory_iterator(); i++) + { + if (!boost::filesystem::is_directory(i->path())) //we eliminate directories + { + QTest::newRow("ods file test") << QString::fromStdString(i->path().filename().string()); + } + } +} + + +void ODSImporterTest::odsTester() +{ + QFETCH(QString, filename); + qDebug() << "File: " << filename; + + //ods file open + QString fullPath_ods = QString(TESTFILE_FOLDER "odsimporter_test/ods_files/").append(filename); + + DataSetPackage *ds_ods = new DataSetPackage(); + fe_ods->setPath(fullPath_ods); + asl_ods->loadTask(fe_ods, ds_ods); //load the ods file + asl_ods->_thread.quit(); + + struct fileContent fc_ods; + copyToStructure(ds_ods, &fc_ods); //copy contents of ds_ods to file contents structure + SharedMemory::deleteDataSet(ds_ods->dataSet); //clear shared memory + ds_ods->~DataSetPackage(); + + //csv file open + QString csvFile = filename; + csvFile.replace(filename.size()-3, 3, "csv"); + QString fullPath_csv = QString(TESTFILE_FOLDER "odsimporter_test/csv_files/").append(csvFile); + + DataSetPackage *ds_csv = new DataSetPackage(); + fe_csv->setPath(fullPath_csv); + asl_csv->loadTask(fe_csv, ds_csv); //load the corresponding csv file - this is the expected output + asl_csv->_thread.quit(); + + struct fileContent fc_csv; + copyToStructure(ds_csv, &fc_csv); //copy contents of ds_csv to fc_csv structure + SharedMemory::deleteDataSet(ds_csv->dataSet); //clear the shared memory + ds_csv->~DataSetPackage(); + + QVERIFY(checkIfEqual(&fc_ods, &fc_csv)); // end of test +} + + +/* copy from the DataSetPackage to fileContents structure - required since dataset is deleted in the sharedmemory */ +void ODSImporterTest::copyToStructure(DataSetPackage *dsPackage, struct fileContent *fc) +{ + fc->columns = dsPackage->dataSet->columnCount();//copy column count + fc->rows = dsPackage->dataSet->rowCount(); //copy row count + + //copy header names + std::vector headerNames; + for(int i=0; icolumns; ++i) + { + headerNames.push_back(dsPackage->dataSet->column(i).name()); + } + fc->headers = headerNames; + + //copy data + std::vector< std::vector > fileRows; + for(int j=0; jrows; ++j) + { + std::vector tempRow; + for(int i=0; icolumns; ++i) + { + tempRow.push_back(dsPackage->dataSet->column(i)[j]); + } + fileRows.push_back(tempRow); + tempRow.clear(); + } + + fc->data = fileRows; + return; +} + + +/* checks if data read from ods file is same as in corresponding csv file */ +bool ODSImporterTest::checkIfEqual(struct fileContent *fc1, struct fileContent *fc2) +{ + if(fc1->columns != fc2->columns) + { + qDebug() << "Column size mismatch: " << QString::number(fc1->columns) << " " << QString::number(fc2->columns); + return false; + } + + if(fc1->rows != fc2->rows) + { + qDebug() << "Row size mismatch: " << QString::number(fc1->rows) << " " << QString::number(fc2->rows); + return false; + } + + for(int i=0; icolumns; ++i) + { + if(QString::fromStdString(fc1->headers[i]) != QString::fromStdString(fc2->headers[i])) + { + // qDebug() << "Warning: Header name mismatch: " << QString::fromStdString(fc1->headers[i]) << " " << QString::fromStdString(fc2->headers[i]); + //return false; + } + + for(int j=0; jrows; ++j) + { + std::string str1 = fc1->data[j][i]; + std::string str2 = fc2->data[j][i]; + if(str1 != str2) + { + bool success = false; + try + { + int v1 = boost::lexical_cast(str1); + int v2 = boost::lexical_cast(str2); + if (v1 == v2) success = true; + } + catch (...) + { + // Remove "" + str1.erase(std::remove(str1.begin(), str1.end(), '"'), str1.end()); + str2.erase(std::remove(str2.begin(), str2.end(), '"'), str2.end()); + if (str1 == str2) success = true; + } + if (!success) + { + qDebug() << "Data mismatch at row: " << QString::number(j+1) << " and column: " << QString::fromStdString(fc1->headers[i]) << " (number " << QString::number(i) << ")"; + qDebug() << "CSV: " << QString::fromStdString(str2); + qDebug() << "ODS: " << QString::fromStdString(str1); + return false; + } + } + } + } + + return true; +} diff --git a/JASP-Tests/odsimporter_test.h b/JASP-Tests/odsimporter_test.h new file mode 100644 index 0000000000..8b1d2051aa --- /dev/null +++ b/JASP-Tests/odsimporter_test.h @@ -0,0 +1,66 @@ +// +// Copyright (C) 2017 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef ODSIMPORTERTEST_H +#define ODSIMPORTERTEST_H + +#pragma once +#include +#define private public + +#include +#include +#include +#include "AutomatedTests.h" +#include "asyncloader.h" +#include "sharedmemory.h" +#include "fileevent.h" +#include "mainwindow.h" +#include "datasetpackage.h" + + +class ODSImporterTest : public QObject +{ + Q_OBJECT + +public: + + struct fileContent + { + int columns; + int rows; + std::vector headers; + std::vector< std::vector > data; + }; + + FileEvent *fe_ods, *fe_csv; + AsyncLoader *asl_ods, *asl_csv; + + bool checkIfEqual(struct fileContent*, struct fileContent*); + void copyToStructure(DataSetPackage*, struct fileContent*); + +private slots: + void init(); + void cleanup(); + void odsTester(); + void odsTester_data(); +}; + + +DECLARE_TEST(ODSImporterTest) + +#endif // ODSIMPORTERTEST_H diff --git a/JASP-Tests/utils_test.R b/JASP-Tests/utils_test.R deleted file mode 100644 index 368b6238f9..0000000000 --- a/JASP-Tests/utils_test.R +++ /dev/null @@ -1,200 +0,0 @@ -# -# Copyright (C) 2017 University of Amsterdam -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# - -.readFromResourcesLibrary <- function(analysis) { - # Converts the json file in the Resources folder to a R - list for the - # analysis passed as argument - # - # Args: - # analysis: Analysis name passed as string - # - # Returns: - # 'NA' if there is an error converting json into R - list - # list containing the json data as keys and values - - file.relative.path = paste0("../../Resources/Library/", analysis, ".json") - - analysis.resources <- tryCatch({ - rjson::fromJSON(file = file.relative.path) - }, - warning = function(warn) { - message("Warning: ") - message(warn) - }, - error = function(err) { - message("Error: ") - message(err) - return(NA) - }, - finally = {} - ) - - return(analysis.resources) -} - -.createOptions <- function(analysis, type = 'default') { - # Fetches the json data for the analysis and returns an 'options' - # list with default selections - # - # Args: - # analysis: Analysis name passed as string - # type: can be either 'default' or 'random' - # - # Returns: - # empty list if file read is unsuccessful - # 'options' list containing the different options available to the user - - options <- list() - - # fetch options from json file for the analysis - analysis.resources <- .readFromResourcesLibrary(analysis) - - if (analysis.resources[[1]] == 'NA') { - return(options) - } - - analysis.name <- analysis.resources[[1]] - number.of.options <- length(analysis.resources$options) - - # create options list with NULL values - options.names <- NULL - for (i in 1:number.of.options) { - options.names <- c(options.names, - analysis.resources[["options"]][[i]][["name"]]) - } - - options[options.names] <- list(NULL) - - if (type == 'default') { - options <- .createDefaultOptions(options, analysis.resources) - } else if (type == 'random') { - options <- .createRandomOptions(options, analysis.resources) - } else { - message("argument 'type' unknown") - return(list(NULL)) - } - - return(options) -} - -.createDefaultOptions <- function(options, analysis.resources) { - # Fetches the json data for the analysis and returns an 'options' - # list with default selections - # - # Args: - # options: contains list of names of options initialized to NULL - # analysis.resources: json file converted list list - # - # Returns: - # 'options' list containing the different options available to the user - - number.of.options <- length(analysis.resources$options) - - # give default values to options - for (i in 1:number.of.options) { - options.attribute <- analysis.resources[["options"]][[i]] - if ("default" %in% names(options.attribute)) { - options[[options.attribute[["name"]]]] <- options.attribute[["default"]] - } else if ("value" %in% names(options.attribute)) { - options[[options.attribute[["name"]]]] <- options.attribute[["value"]] - } else if (options.attribute[["type"]] != "Variables") { - options[[options.attribute[["name"]]]] <- 0 - } - } - - return(options) -} - -.createRandomOptions <- function(options, analysis.resources) { - # Fetches the json data for the analysis and returns an 'options' - # list with default selections - # - # Args: - # options: contains list of names of options initialized to NULL - # analysis.resources: json file converted list list - # - # Returns: - # 'options' list containing the different options available to the user - # and gives random values to them. - - # FIXME: Currently random values are given only to types: List, Number - # Integer, Boolean. Other types to be handled: Variable, Variables, - # Item, Items, Table - - number.of.options <- length(analysis.resources$options) - - # give default values to options - for (i in 1:number.of.options) { - options.attribute <- analysis.resources[["options"]][[i]] - - if (options.attribute[["name"]] == "plotWidth" || - options.attribute[["name"]] == "plotHeight") { - - options[[options.attribute[["name"]]]] <- options.attribute[["default"]] - next - } - - options.type <- options.attribute[["type"]] - - min.value <- -999999 - if ("min" %in% names(options.attribute)) { - min.value <- options.attribute[["min"]] - } - - max.value <- 999999 - if ("max" %in% names(options.attribute)) { - max.value <- options.attribute[["max"]] - } - - if (options.type == "List") { - options[[options.attribute[["name"]]]] <- sample( - options.attribute[["options"]], - 1 - ) - } else if (options.type == "Number") { - options[[options.attribute[["name"]]]] <- runif( - 1, - min = min.value, - max = max.value - ) - } else if (options.type == "Integer") { - options[[options.attribute[["name"]]]] <- floor(runif( - 1, - min = min.value, - max = max.value - ) - ) - } else if (options.type == "Boolean") { - options[[options.attribute[["name"]]]] <- sample(c(TRUE, FALSE), - 1, replace = T) - } - } - - return(options) -} - -.createBehaviourEmpty <- function() { - - # Create a series of GUI selections/flow input by user - # FIXME: yet to be implemented -} - -.createBehaviourEJ <- function() { - - # Create a series of GUI selections/flow input by user - # FIXME: yet to be implemented -} diff --git a/JASP.pro b/JASP.pro index 3fda1e3477..7674f119a0 100644 --- a/JASP.pro +++ b/JASP.pro @@ -1,4 +1,3 @@ - cache() TEMPLATE = subdirs diff --git a/README.md b/README.md index 35ec6bb285..fcd7d5d303 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,57 @@ - -JASP -==== - -JASP aims to be a complete statistical package for both Bayesian and Frequentist statistical methods, that is easy to use and familiar to users of SPSS - -[https://jasp-stats.org](https://jasp-stats.org) - -User Guide ----------- - -[JASP User Guide](Docs/user-guide/index.md) - -Development ------------ - -[Guide to Building JASP](Docs/development/jasp-building-guide.md) - -[The JASP Guide for Implementing Analyses in R](Docs/development/r-analyses-guide.md) - -[Guide to Adding Analyses](Docs/development/jasp-adding-analyses.md) - -[Guide to creating a Module](Docs/development/jasp-adding-module.md) - -[JASP Licensing](Docs/development/jasp-licensing.md) - -[The JASP Error List](Docs/development/jasp-error-list.md) - -[The JASP Guide to Writing Analyses for Humans](Docs/development/jasp-human-guide.md) - -[The JASP R style guide](Docs/development/r-style-guide.md) - -[Guide to Rebasing Your Repo](Docs/development/git-guide.md) - -[The JASP R Package List](Docs/development/jasp-r-packages-list.md) +

+ +

+ A Fresh Way to do Statistics +

+ +
+ Home | + Download | + How to use | + Blog | + Contact +
+ +
+ TravisCI +
+ +

+ JASP is a cross-platform software program which allows you to conduct statistical analyses in seconds, and without having to learn programming or risking a programming mistake. It aims to be a complete statistical package for both Bayesian and Frequentist statistical methods, that is easy to use and familiar to users of SPSS. +

+ + +### User guide + + - [JASP User Guide](Docs/user-guide/index.md) + +### Citation details + +

+ One of the best ways that you can support the JASP project is by citing it (given below in BiBTeX format) +

+ + @MISC{JASP2017, + AUTHOR = {{JASP Team}}, + TITLE = {{JASP (Version 0.8.4)[Computer software]}}, + YEAR = {2017}, + URL = {https://jasp-stats.org/} + } + +

+ Citations are an important measure of how widely the software is used, and an important indicator to funding bodies of JASP’s relevance. +

+ +### Development + + - [Licensing](Docs/development/jasp-licensing.md) + - [Rebasing your Repository](Docs/development/git-guide.md) + - [Guide to Building JASP](Docs/development/jasp-building-guide.md) + - [Implementing Analyses in R](Docs/development/r-analyses-guide.md) + - [Writing Unit Tests for Analyses](JASP-Tests/README.md) + - [The JASP R style guide](Docs/development/r-style-guide.md) + - [The JASP Guide to Writing Analyses for Humans](Docs/development/jasp-human-guide.md) + - [The Error list](Docs/development/jasp-error-list.md) + - [Adding new Analyses](Docs/development/jasp-adding-analyses.md) + - [Creating a Module](Docs/development/jasp-adding-module.md) + - [The JASP R package list](Docs/development/jasp-r-packages-list.md) diff --git a/Resources/Data Sets/Bugs (Ryan, Wilde & Crist, 2013).csv b/Resources/Data Sets/Bugs (Ryan, Wilde & Crist, 2013).csv index d4e6bdec79..55539b9c74 100644 --- a/Resources/Data Sets/Bugs (Ryan, Wilde & Crist, 2013).csv +++ b/Resources/Data Sets/Bugs (Ryan, Wilde & Crist, 2013).csv @@ -8,7 +8,7 @@ Subject,Gender,Region,Education,"Lo D, Lo F","Lo D, Hi F","Hi D, Lo F","Hi D, Hi 7,Female,North,some,10,10,10,10 8,Female,North,high,10,10,9,10 9,Female,North,high,9.5,9.5,6,10 -10,Female,Other,high,8.5,10,7, +10,Female,Other,high,8.5,10,7,NA 11,Male,North,some,0,2.5,0,0 12,Male,North,some,9.5,7.5,8.5,10 13,Female,North,less,7,8.5,6.5,8.5 @@ -36,7 +36,7 @@ Subject,Gender,Region,Education,"Lo D, Lo F","Lo D, Hi F","Hi D, Lo F","Hi D, Hi 37,Female,North,some,4,10,7,10 38,Female,North,some,4.5,7,10,10 39,Male,North,some,7,7,10,9 -40, ,,,8,8.5,8,9.5 +40,NA,NA,NA,8,8.5,8,9.5 41,Female,North,some,5,7.5,7.5,7.5 42,Female,North,high,5,8.5, ,9.5 43,Female,North,some,2,2,0,5.5 @@ -57,7 +57,7 @@ Subject,Gender,Region,Education,"Lo D, Lo F","Lo D, Hi F","Hi D, Lo F","Hi D, Hi 60,Male,North,less,3.5,7.5,8,8 61,Female,North,college,2.5,7.5,5,7.5 62,Male,North,less,3.5,9.5,3.5,8 -64,Female,Europe,some,8.5,6, ,5 +64,Female,Europe,some,8.5,6,NA,5 65,Female,North,less,3,8.5,10,2.5 66,Male,North,less,6,10,3,8.5 67,Male,North,high,5.5,8,4.5,9.5 @@ -72,7 +72,7 @@ Subject,Gender,Region,Education,"Lo D, Lo F","Lo D, Hi F","Hi D, Lo F","Hi D, Hi 77,Female,North,some,6,6,7.5,6 78,Female,North,less,5,6.5,0.5,5.5 79,Male,North,less,6,8,9,7 -80,Female,North,less,1.5, ,9,9.5 +80,Female,North,less,1.5,NA,9,9.5 81,Male,North,high,5.5,4,10,5.5 82,Female,North,high,9.5,9.5,9.5,8.5 83,Female,North,high,8,8,8.5,10 @@ -88,7 +88,7 @@ Subject,Gender,Region,Education,"Lo D, Lo F","Lo D, Hi F","Hi D, Lo F","Hi D, Hi 93,Female,North,less,6.5,10,10,10 95,Female,North,less,3,4,2,2 96,Male,North,high,10,10,10,10 -97,Female,North,,8.5,10,8.5,10 +97,Female,North,NA,8.5,10,8.5,10 98,Female,North,some,1.5,10,8.5,10 99,Female,North,some,9,10,10,10 100,Female,Europe,some,5.5,5.5,2,3 diff --git a/Resources/Help/analyses/classicalmetaanalysis.md b/Resources/Help/analyses/classicalmetaanalysis.md index eba7776be0..632655bca4 100644 --- a/Resources/Help/analyses/classicalmetaanalysis.md +++ b/Resources/Help/analyses/classicalmetaanalysis.md @@ -1,6 +1,6 @@ Classical Meta Analysis ========================== -You can read this blog to have more information about Meta Analysis. +You can read this blog to have more information about Meta Analysis. Additional documentation will be available in future releases of JASP. diff --git a/Resources/Help/analyses/networkanalysis.md b/Resources/Help/analyses/networkanalysis.md index 4d8fa077d9..43997ba5a8 100644 --- a/Resources/Help/analyses/networkanalysis.md +++ b/Resources/Help/analyses/networkanalysis.md @@ -196,7 +196,7 @@ Friedman, J., Hastie, T., & Tibshirani, R. (2008). Sparse inverse covariance est Friedman, J. H., Hastie, T., & Tibshirani, R. (2014). glasso: Graphical lasso estimation of gaussian graphical models. Retrieved from https://CRAN.R-project.org/package=glasso -Fruchterman, T. M., & Reingold, E. M. (1991). Graph drawing by force‐directed placement. Software: Practice and experience, 21(11), 1129-1164. +Fruchterman, T. M., & Reingold, E. M. (1991). Graph drawing by force-directed placement. Software: Practice and experience, 21(11), 1129-1164. Haslbeck, J., & Waldorp, L. J. (2015). mgm: Structure Estimation for time-varying mixed graphical models in high-dimensional data. arXiv preprint arXiv:1510.06871. diff --git a/Resources/Help/analyses/regressionlinearbayesian.md b/Resources/Help/analyses/regressionlinearbayesian.md deleted file mode 100644 index d4a918a187..0000000000 --- a/Resources/Help/analyses/regressionlinearbayesian.md +++ /dev/null @@ -1,81 +0,0 @@ -Bayesian Linear Regression -========================== - -Bayesian Linear regression allows you to model a linear relationship between one or more explanatory variable(s) (predictors) and a continuous dependent (response) variable. - -Assumptions ------------ -- Continuous response variable -- Linearity and additivity: The response variable is linearly related to all predictors and the effects of the predictors are additive. -- Independence of errors: The errors are uncorrelated with each other. -- Homoscedasticity: The error variance of each predictor is constant across all values of that predictor. -- Normality of errors: The errors are normally distributed with mean zero. - -Assignment Box -------- -- Dependent Variable: Dependent (response) variable -- Covariates: Predictors - -Default Options -------- -### Bayes Factor: -- BF10: Bayes factor to quantify evidence for the alternative hypothesis relative to the null hypothesis -- BF01: Bayes factor to quantify evidence for the null hypothesis relative to the alternative hypothesis -- Log(BF10): Natural logarithm of BF10 - -### Prior: -- Cauchy prior width: Scale of the Cauchy prior density on effect size under the alternative hypothesis; the default is 0.5 - -Default Output -------- - -### Model Comparison -- Models: The regression models considered; Contains the null model (intercept only, if not some covariates are declared as nuisance, see "Additional Options"), and all possible additive models. -- P(M): Prior probability of the model; by default, all models have equal prior probability. -- P(M|data): Probability of the model given the data; i.e., Posterior probability of the model -- BFM: Bayes factor in favor of the model relative to the remaining models -- BF10: Bayes factor in favor of the model compared to the null model (i.e., intercept only, if not some covariates are declared as nuisance, see "Additional Options"). -- % error: Proportional error of the computation of the Bayes factor. - -Example -------- -### Data set: -- Physical Activity and BMI - -### Input: -- The null hypothesis that Physical Activity is unrelated to Body Mass Index (BMI) in college-aged females is tested against -the two-sided alternative that Physical Activity predicts BMI. - -### Output: -- The Bayes factor in favor of including physical activity as a predictor in the regression model as opposed to not including physical activity as a predictor is 284.3 with error % 0.002. The data are 284.3 times more likely when including physical activity as a predictor in the regression model. - - - -### Output -- Effects: Displays the analysis of effects. - - Stepwise: Displays the Bayes factors and % errors for a forward and backward stepwise analysis of effects. - - - -### Analysis of Effects -- Effects: The different covariates for which the effect analysis is displayed. -- P(incl): Prior probability of including the covariate in the regression model; is by default 0.5 (i.e., equally likely to include and not to include). -- P(incl|data): Posterior probability of including the covariate in the regression model (i.e., probability of inclusion given the data). -- BFInclusion: Bayes factor in favor of including the covariate. -- BFBackward: Bayes factor in favor of including the covariate when using the backward stepwise procedure. -- % errorB: Proportional error of the computation of BFBackward. -- BFForward: Bayes factor in favor of including the covariate when using the forward stepwise procedure. -- % errorF: Proportional error of the computation of BFForward. - -Additional Options -------- -### Model: -- Factors: The covariates. Can be manually moved to model terms if they are not already inlcuded in the model. -- Model Terms: The model terms. Can be manually removed. -- Is Nuisance: Allows to declare a covariate as nuisance. The covariate is then included in all models and is not displayed in the output tables (a footnote is displayed which tells that the covariate is included in all models). - -References -------- -- Liang, F., Paulo, R., Molina, G., Clyde, M. A., & Berger, J.O. (2008). Mixtures of g-priors for Bayesian variable selection. *Journal of the American Statistical Association, 103*, 410-423. -- Rouder, J. N., & Morey, R. D. (2012). Default Bayes factors for model selection in regression. *Multivariate Behavioral Research, 47*, 877-903. -- Zellner, A., & Siow, A. (1980) Posterior odds ratios for selected regression hypotheses. In J. M. Bernardo, D. V. Lindley, & A. F. M. Smith (Eds), *Bayesian statistics: Proceedings of the first international meeting held in Valencia (Spain)* (pp. 585-603). University of Valencia. \ No newline at end of file diff --git a/Resources/Help/marked.js b/Resources/Help/marked.js index 142eccf00a..32521d9934 100644 --- a/Resources/Help/marked.js +++ b/Resources/Help/marked.js @@ -75,8 +75,9 @@ block.normal = merge({}, block); */ block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/, - paragraph: /^/ + fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, + paragraph: /^/, + heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ }); block.gfm.paragraph = replace(block.paragraph) @@ -188,7 +189,7 @@ Lexer.prototype.token = function(src, top, bq) { this.tokens.push({ type: 'code', lang: cap[2], - text: cap[3] + text: cap[3] || '' }); continue; } @@ -359,7 +360,8 @@ Lexer.prototype.token = function(src, top, bq) { type: this.options.sanitize ? 'paragraph' : 'html', - pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style', + pre: !this.options.sanitizer + && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), text: cap[0] }); continue; @@ -454,7 +456,7 @@ var inline = { reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, + em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, br: /^ {2,}\n(?!\s*$)/, del: noop, @@ -606,8 +608,10 @@ InlineLexer.prototype.output = function(src) { } src = src.substring(cap[0].length); out += this.options.sanitize - ? escape(cap[0]) - : cap[0]; + ? this.options.sanitizer + ? this.options.sanitizer(cap[0]) + : escape(cap[0]) + : cap[0] continue; } @@ -678,7 +682,7 @@ InlineLexer.prototype.output = function(src) { // text if (cap = this.rules.text.exec(src)) { src = src.substring(cap[0].length); - out += escape(this.smartypants(cap[0])); + out += this.renderer.text(escape(this.smartypants(cap[0]))); continue; } @@ -712,7 +716,9 @@ InlineLexer.prototype.smartypants = function(text) { if (!this.options.smartypants) return text; return text // em-dashes - .replace(/--/g, '\u2014') + .replace(/---/g, '\u2014') + // en-dashes + .replace(/--/g, '\u2013') // opening singles .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') // closing singles & apostrophes @@ -730,6 +736,7 @@ InlineLexer.prototype.smartypants = function(text) { */ InlineLexer.prototype.mangle = function(text) { + if (!this.options.mangle) return text; var out = '' , l = text.length , i = 0 @@ -868,7 +875,7 @@ Renderer.prototype.link = function(href, title, text) { } catch (e) { return ''; } - if (prot.indexOf('javascript:') === 0) { + if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) { return ''; } } @@ -889,6 +896,10 @@ Renderer.prototype.image = function(href, title, text) { return out; }; +Renderer.prototype.text = function(text) { + return text; +}; + /** * Parsing & Compiling */ @@ -1083,7 +1094,8 @@ function escape(html, encode) { } function unescape(html) { - return html.replace(/&([#\w]+);/g, function(_, n) { + // explicitly match decimal, hex, and named HTML entities + return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) { n = n.toLowerCase(); if (n === 'colon') return ':'; if (n.charAt(0) === '#') { @@ -1232,6 +1244,8 @@ marked.defaults = { breaks: false, pedantic: false, sanitize: false, + sanitizer: null, + mangle: true, smartLists: false, silent: false, highlight: null, diff --git a/Resources/Library/Ancova.json b/Resources/Library/Ancova.json index 7804a74038..1bc7181db8 100644 --- a/Resources/Library/Ancova.json +++ b/Resources/Library/Ancova.json @@ -102,6 +102,18 @@ "default": "none", "type": "List" }, + { + "name": "simpleFactor", + "type": "Variable" + }, + { + "name": "moderatorFactorOne", + "type": "Variable" + }, + { + "name": "moderatorFactorTwo", + "type": "Variable" + }, { "name": "descriptives", "type": "Boolean" diff --git a/Resources/Library/Anova.json b/Resources/Library/Anova.json index 00cf0d6b33..85cd255439 100644 --- a/Resources/Library/Anova.json +++ b/Resources/Library/Anova.json @@ -122,6 +122,18 @@ "name": "plotSeparatePlots", "type": "Variable" }, + { + "name": "simpleFactor", + "type": "Variable" + }, + { + "name": "moderatorFactorOne", + "type": "Variable" + }, + { + "name": "moderatorFactorTwo", + "type": "Variable" + }, { "name": "plotErrorBars", "type": "Boolean" diff --git a/Resources/Library/AnovaRepeatedMeasures.json b/Resources/Library/AnovaRepeatedMeasures.json index 529f8ff30d..ae04d6811e 100644 --- a/Resources/Library/AnovaRepeatedMeasures.json +++ b/Resources/Library/AnovaRepeatedMeasures.json @@ -105,6 +105,10 @@ "name": "postHocTestEffectSize", "type": "Boolean" }, + { + "name": "postHocTestPooledError", + "type": "Boolean" + }, { "name": "postHocTestsHolm", "type": "Boolean" diff --git a/Resources/Library/BFFromT.json b/Resources/Library/BFFromT.json deleted file mode 100644 index 3d1ef54dc1..0000000000 --- a/Resources/Library/BFFromT.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "BFFromT", - "autorun": true, - "version": "1.0", - "options": [ - ] -} diff --git a/Resources/Library/BinomialTest.json b/Resources/Library/BinomialTest.json index 1ce57a69db..d4c7140ba2 100644 --- a/Resources/Library/BinomialTest.json +++ b/Resources/Library/BinomialTest.json @@ -1,26 +1,31 @@ { - "name": "BinomialTest", + "version": "2.00", "autorun": true, - "version": "1.00", + "init": true, + "name": "BinomialTest", + "title": "Binomial Test", + "dataset": { + "factor": "variables" + }, "options": [ - { - "name": "variables", - "type": "Variables" - }, + { + "name": "variables", + "type": "Variables" + }, { "format": "", - "name": "testValue", + "name": "testValue", "type": "Number", - "value": 0.5, - "max": 1, - "min": 0 + "value": 0.5, + "max": 1, + "min": 0 + }, + { + "name": "hypothesis", + "options": ["notEqualToTestValue", "greaterThanTestValue", "lessThanTestValue"], + "default": "notEqualToTestValue", + "type": "List" }, - { - "name": "hypothesis", - "options": [ "notEqualToTestValue", "greaterThanTestValue", "lessThanTestValue" ], - "default": "notEqualToTestValue", - "type": "List" - }, { "name": "confidenceInterval", "type": "Boolean" @@ -46,19 +51,82 @@ "value": 0.950 }, { - "name": "VovkSellkeMPR", - "type": "Boolean", - "default": false - }, - { - "name": "plotWidth", - "type": "Integer", - "default": 160 + "name": "VovkSellkeMPR", + "type": "Boolean", + "default": false + } + ], + "results": { + "binomial": { + "type": "table", + "title": "Binomial Test", + "columns": [ + { + "name": "case", + "title": "", + "type": "string", + "combine": true + }, + { + "name": "level", + "title": "Level", + "type": "string" + }, + { + "name": "counts", + "title": "Counts", + "type": "integer" + }, + { + "name": "total", + "title": "Total", + "type": "string" + }, + { + "name": "proportion", + "title": "Proportion", + "type": "number", + "format": "sf:4;dp:3" + }, + { + "name": "p", + "title": "p", + "type": "number", + "format": "dp:3;p:.001" + }, + { + "name": "VovkSellkeMPR", + "title": "VS-MPR\u002A", + "type": "number", + "format": "sf:4;dp:3" + }, + { + "name": "lowerCI", + "title": "Lower", + "type": "number", + "format": "sf:4;dp:3" + }, + { + "name": "upperCI", + "title": "Upper", + "type": "number", + "format": "sf:4;dp:3" + } + ] }, - { - "name": "plotHeight", - "type": "Integer", - "default": 300 + "descriptives": { + "type": "container", + "items": [{ + "descriptivesPlot": { + "type": "image", + "width": 160, + "height": 300 + } + }] } - ] -} + }, + "state": { + "binomResults": ["variables", "confidenceIntervalInterval", "hypothesis", "testValue"], + "descriptPlots": ["variables", "descriptivesPlots", "descriptivesPlotsConfidenceInterval", "plotWidth", "plotHeight"] + } +} \ No newline at end of file diff --git a/Resources/Library/NetworkAnalysis.json b/Resources/Library/NetworkAnalysis.json index 5a1c40c1c7..6a816ace54 100644 --- a/Resources/Library/NetworkAnalysis.json +++ b/Resources/Library/NetworkAnalysis.json @@ -52,6 +52,11 @@ "name": "tableCentrality", "type": "Boolean" }, + { + "name": "tableClustering", + "type": "Boolean", + "default": false + }, { "default": false, "name": "plotNetwork", @@ -62,6 +67,11 @@ "name": "plotCentrality", "type": "Boolean" }, + { + "default": false, + "name": "plotClustering", + "type": "Boolean" + }, { "name": "tableWeightsMatrix", "type": "Boolean", @@ -186,9 +196,9 @@ { "name": "numberOfBootstraps", "type": "Integer", - "min": 1, + "min": 0, "max": 100000, - "default": 3 + "default": 0 }, { "name": "parallelBootstrap", @@ -208,7 +218,7 @@ { "name": "BootstrapType", "type": "List", - "options": ["nonparametric", "parametric", "node", "person", "case", "jackknife"], + "options": ["nonparametric", "case", "node", "parametric", "person", "jackknife"], "default": "nonparametric" }, { @@ -377,6 +387,16 @@ "type": "Integer", "default": 320 }, + { + "name": "plotWidthClustering", + "type": "Integer", + "default": 480 + }, + { + "name": "plotHeightClustering", + "type": "Integer", + "default": 320 + }, { "name": "plotWidthBootstrapPlot", "type": "Integer", diff --git a/Resources/Library/PrincipalComponentAnalysis.json b/Resources/Library/PrincipalComponentAnalysis.json index b13b1ff2d1..dd1635231e 100644 --- a/Resources/Library/PrincipalComponentAnalysis.json +++ b/Resources/Library/PrincipalComponentAnalysis.json @@ -22,7 +22,7 @@ { "name": "numberOfFactors", "type": "Integer", - "default": 1, + "default": 1, "min": 1 }, { diff --git a/Resources/Library/BASRegressionLinearLink.json b/Resources/Library/RegressionLinearBayesian_BAS.json similarity index 84% rename from Resources/Library/BASRegressionLinearLink.json rename to Resources/Library/RegressionLinearBayesian_BAS.json index 0a9a3b5390..96f2d547e9 100644 --- a/Resources/Library/BASRegressionLinearLink.json +++ b/Resources/Library/RegressionLinearBayesian_BAS.json @@ -1,5 +1,5 @@ { - "name": "BASRegressionLinearLink", + "name": "RegressionLinearBayesian", "autorun": true, "version": "1.00", "options": [ @@ -31,10 +31,21 @@ "max": 1 }, { - "name": "logmarg", + "name": "postSummary", "type": "Boolean", "default": false }, + { + "name": "summaryType", + "type": "List", + "options": [ + "best", + "complex", + "median", + "averaged" + ], + "default": "best" + }, { "name": "descriptives", "type": "Boolean", @@ -99,14 +110,14 @@ "type": "Boolean" }, { - "options": ["AIC", "BIC", "EB-global", "EB-local", "g-prior", "hyper-g", "hyper-g-laplace", "hyper-g-n", "ZS-full", "ZS-null"], - "default": "ZS-null", + "options": ["AIC", "BIC", "EB-global", "EB-local", "g-prior", "hyper-g", "hyper-g-laplace", "hyper-g-n", "JZS"], + "default": "JZS", "name": "priorRegressionCoefficients", "type": "List" }, { "name": "samplingMethod", - "options": ["BAS", "MCMC", "MCMCBAS"], + "options": ["BAS", "MCMC"], "default": "BAS", "type": "List" }, @@ -121,15 +132,20 @@ }, { "options": ["Bernoulli", "beta.binomial", "uniform"], - "default": "beta.binomial", + "default": "uniform", "name": "modelPrior", "type": "List" }, { - "name": "gPriorParameter", + "name": "alpha", "type": "Number", "value": 3 }, + { + "name": "rScale", + "type": "Number", + "value": 0.354 + }, { "name": "modelTerms", "template": [ diff --git a/Resources/Library/RegressionLogistic.json b/Resources/Library/RegressionLogistic.json index 287e42455e..8131263bd7 100644 --- a/Resources/Library/RegressionLogistic.json +++ b/Resources/Library/RegressionLogistic.json @@ -13,20 +13,6 @@ "default": "enter", "options": [ "enter", "backward", "forward", "stepwise" ] }, - { - "name": "entryPval", - "type": "Number", - "value": 0.050, - "max": 1, - "min": 0 - }, - { - "name": "removalPval", - "type": "Number", - "value": 0.100, - "max": 1, - "min": 0 - }, { "name": "covariates", "type": "Variables" @@ -45,7 +31,7 @@ { "name": "components", "type": "Term" - }, + }, { "default": false, "name": "isNuisance", diff --git a/Resources/Library/ReinforcementLearningR11tLearning.json b/Resources/Library/ReinforcementLearningR11tLearning.json new file mode 100644 index 0000000000..41a8a432ef --- /dev/null +++ b/Resources/Library/ReinforcementLearningR11tLearning.json @@ -0,0 +1,151 @@ +{ + "name": "ReinforcementLearningR11tLearning", + "autorun": true, + "version": "1.0", + "options": [ + { + "name": "subjectId", + "type": "Variable" + }, + { + "name": "group", + "type": "Variable" + }, + { + "name": "trialNumber", + "type": "Variable" + }, + { + "name": "deck", + "type": "Variable" + }, + { + "name": "reward", + "type": "Variable" + }, + { + "name": "loss", + "type": "Variable" + }, + { + "name": "model", + "type": "List", + "options": [ "pvl-delta", "pvl", "ev", "vpp" ] + }, + { + "name": "estimation", + "type": "List", + "options": [ "individual", "group", "groupComparison" ] + }, + { + "name": "outputConvergenceCheck", + "type": "Boolean" + }, + { + "name": "outputIndividualEstimates", + "type": "Boolean", + "default": true + }, + { + "name": "outputGroupEstimates", + "type": "Boolean", + "default": true + }, + { + "name": "centralTendency", + "type": "List", + "options": [ "means", "median", "mode" ] + }, + { + "name": "distribution", + "type": "List", + "options": [ "sd", "hdi", "ci" ] + }, + { + "name": "plotIndividualLevelPosteriors", + "type": "Boolean" + }, + { + "name": "plotGroupLevelPosteriors", + "type": "Boolean" + }, + { + "name": "plotWorstChain", + "type": "Boolean" + }, + { + "name": "AInitial", + "type": "Number", + "value": 0.5 + }, + { + "name": "AUpper", + "type": "Number", + "value": 1 + }, + { + "name": "WInitial", + "type": "Number", + "value": 2.5 + }, + { + "name": "WUpper", + "type": "Number", + "value": 5 + }, + { + "name": "aInitial", + "type": "Number", + "value": 0.5 + }, + { + "name": "aUpper", + "type": "Number", + "value": 1 + }, + { + "name": "cInitial", + "type": "Number", + "value": 2.5 + }, + { + "name": "cUpper", + "type": "Number", + "value": 5 + }, + { + "name": "samples", + "type": "List", + "options": [ "many", "some", "few", "custom" ] + }, + { + "name": "customIterations", + "type": "Number", + "value": 10 + }, + { + "name": "customBurnin", + "type": "Number", + "value": 5 + }, + { + "name": "customChains", + "type": "Number", + "value": 4 + }, + { + "name": "customThinning", + "type": "Number", + "value": 1 + }, + { + "name": "specificSeed", + "type": "Boolean" + }, + { + "name": "specificSeedValue", + "type": "Number", + "value": 4 + } + ] +} diff --git a/Resources/Library/ReliabilityAnalysis.json b/Resources/Library/ReliabilityAnalysis.json index ea0eb748b3..b27646d944 100644 --- a/Resources/Library/ReliabilityAnalysis.json +++ b/Resources/Library/ReliabilityAnalysis.json @@ -3,97 +3,97 @@ "autorun": true, "version": "1.00", "options": [ - { - "name": "variables", - "type": "Variables" - }, - { - "name": "alphaScale", - "type": "Boolean", + { + "name": "variables", + "type": "Variables" + }, + { + "name": "alphaScale", + "type": "Boolean", "default" : true - }, - { - "name": "gutmannScale", - "type": "Boolean", + }, + { + "name": "gutmannScale", + "type": "Boolean", "default" : false - }, - { - "name": "averageInterItemCor", - "type": "Boolean", + }, + { + "name": "averageInterItemCor", + "type": "Boolean", "default" : false - }, - { - "name": "mcDonaldScale", - "type": "Boolean", + }, + { + "name": "mcDonaldScale", + "type": "Boolean", "default" : false - }, - { - "name": "glbScale", - "type": "Boolean", + }, + { + "name": "glbScale", + "type": "Boolean", "default" : false - }, - { - "name": "meanScale", - "type": "Boolean", + }, + { + "name": "meanScale", + "type": "Boolean", "default" : false - }, - { - "name": "sdScale", - "type": "Boolean", + }, + { + "name": "sdScale", + "type": "Boolean", "default" : false - }, - { - "name": "alphaItem", - "type": "Boolean", + }, + { + "name": "alphaItem", + "type": "Boolean", "default" : false - }, - { - "name": "gutmannItem", - "type": "Boolean", + }, + { + "name": "gutmannItem", + "type": "Boolean", "default" : false - }, - { - "name": "mcDonaldItem", - "type": "Boolean", + }, + { + "name": "mcDonaldItem", + "type": "Boolean", "default" : false - }, - { - "name": "itemRestCor", - "type": "Boolean", + }, + { + "name": "itemRestCor", + "type": "Boolean", "default" : false - }, - { - "name": "meanItem", - "type": "Boolean", + }, + { + "name": "meanItem", + "type": "Boolean", "default" : false - }, - { - "name": "sdItem", - "type": "Boolean", + }, + { + "name": "sdItem", + "type": "Boolean", "default" : false - }, - { - "name": "reverseScaledItems", - "type": "Variables" - }, - { - "name": "missingValues", - "options": ["excludeCasesListwise", "excludeCasesPairwise"], - "default": "excludeCasesListwise", - "type": "List" - }, + }, + { + "name": "reverseScaledItems", + "type": "Variables" + }, + { + "name": "missingValues", + "options": ["excludeCasesListwise", "excludeCasesPairwise"], + "default": "excludeCasesListwise", + "type": "List" + }, { - "name": "confAlpha", - "type": "Boolean", + "name": "confAlpha", + "type": "Boolean", "default" : false - }, + }, { - "name": "confAlphaLevel", + "name": "confAlphaLevel", "type": "Number", - "format": "%", + "format": "%", "max": 0.999, "min": 0.000, "value": 0.950 - }, + } ] } diff --git a/Resources/TestFiles.zip b/Resources/TestFiles.zip index 955ad4b9ea..afd96cdedd 100644 Binary files a/Resources/TestFiles.zip and b/Resources/TestFiles.zip differ diff --git a/Resources/modules.json b/Resources/modules.json new file mode 100644 index 0000000000..5ad4c3faba --- /dev/null +++ b/Resources/modules.json @@ -0,0 +1,127 @@ +[ + { + "name": "Common", + "ribbon": [ + { + "name": "Descriptives", + "analyses": ["Descriptive Statistics", "Reliability Analysis"] + }, + { + "name": "T-Tests", + "analyses": [ + "Independent Samples T-Test", + "Paired Samples T-Test", + "One Sample T-Test", + "Bayesian Independent Samples T-Test", + "Bayesian Paired Samples T-Test", + "Bayesian One Sample T-Test" + ] + }, + { + "name": "ANOVA", + "analyses": [ + "ANOVA", + "Repeated Measures ANOVA", + "ANCOVA", + "Bayesian ANOVA", + "Bayesian Repeated Measures ANOVA", + "Bayesian ANCOVA" + ] + }, + { + "name": "Regression", + "analyses": [ + "Correlation Matrix", + "Linear Regression", + "Logistic Regression", + "Bayesian Correlation Matrix", + "Bayesian Correlation Pairs", + "Bayesian Linear Regression" + ] + }, + { + "name": "Frequencies", + "analyses": [ + "Binomial Test", + "Contingency Tables", + "Log-Linear Regression", + "Bayesian Binomial Test", + "Bayesian Contingency Tables", + "Bayesian Log-Linear Regression" + ] + }, + { + "name": "Factor", + "analyses": [ + "Principal Component Analysis", + "Exploratory Factor Analysis" + ] + } + ] + }, + { + "name": "SEM", + "ribbon": [ + { + "name": "Lavaan" + } + ] + }, + { + "name": "Reinforcement Learning", + "ribbon": [ + { + "name": "R11t Learning" + } + ] + }, + { + "name": "Summary Statistics", + "ribbon": [ + { + "name": "T-Tests", + "dataSetRequired": false, + "analyses": [ + "Bayesian Independent Samples T-Test", + "Bayesian Paired Samples T-Test", + "Bayesian One Sample T-Test" + ] + }, + { + "name": "Regression", + "dataSetRequired": false, + "analyses": [ + "Bayesian Correlation Pairs", + "Bayesian Linear Regression" + ] + }, + { + "name": "Frequencies", + "dataSetRequired": false, + "analyses": ["Bayesian Binomial Test"] + } + ] + }, + { + "name": "Meta Analysis", + "ribbon": [ + { + "name": "Classical" + }, + { + "name": "Multilevel" + }, + { + "name": "2 x 2" + } + ] + }, + { + "name": "Network", + "ribbon": [ + { + "name": "Network" + } + ] + } +] diff --git a/Tools/JASPTools/Meta/Rd.rds b/Tools/JASPTools/Meta/Rd.rds deleted file mode 100644 index 69e0eb1c55..0000000000 Binary files a/Tools/JASPTools/Meta/Rd.rds and /dev/null differ diff --git a/Tools/JASPTools/Meta/hsearch.rds b/Tools/JASPTools/Meta/hsearch.rds deleted file mode 100644 index bb173105d5..0000000000 Binary files a/Tools/JASPTools/Meta/hsearch.rds and /dev/null differ diff --git a/Tools/JASPTools/Meta/links.rds b/Tools/JASPTools/Meta/links.rds deleted file mode 100644 index b35834c81f..0000000000 Binary files a/Tools/JASPTools/Meta/links.rds and /dev/null differ diff --git a/Tools/JASPTools/Meta/package.rds b/Tools/JASPTools/Meta/package.rds deleted file mode 100644 index 8266e59905..0000000000 Binary files a/Tools/JASPTools/Meta/package.rds and /dev/null differ diff --git a/Tools/JASPTools/R/JASPTools.rdb b/Tools/JASPTools/R/JASPTools.rdb deleted file mode 100644 index 62bff5254c..0000000000 Binary files a/Tools/JASPTools/R/JASPTools.rdb and /dev/null differ diff --git a/Tools/JASPTools/R/JASPTools.rdx b/Tools/JASPTools/R/JASPTools.rdx deleted file mode 100644 index e6f9c07c73..0000000000 Binary files a/Tools/JASPTools/R/JASPTools.rdx and /dev/null differ diff --git a/Tools/JASPTools/help/JASPTools.rdb b/Tools/JASPTools/help/JASPTools.rdb deleted file mode 100644 index 08ba13b080..0000000000 Binary files a/Tools/JASPTools/help/JASPTools.rdb and /dev/null differ diff --git a/Tools/JASPTools/help/JASPTools.rdx b/Tools/JASPTools/help/JASPTools.rdx deleted file mode 100644 index 1656bbfe3a..0000000000 Binary files a/Tools/JASPTools/help/JASPTools.rdx and /dev/null differ diff --git a/Tools/JASPTools/help/paths.rds b/Tools/JASPTools/help/paths.rds deleted file mode 100644 index 216a213bf3..0000000000 Binary files a/Tools/JASPTools/help/paths.rds and /dev/null differ diff --git a/Tools/createModule/create-module.py b/Tools/createModule/create-module.py new file mode 100644 index 0000000000..0984f7287c --- /dev/null +++ b/Tools/createModule/create-module.py @@ -0,0 +1,401 @@ +import json +import os + + +current_path = os.path.dirname(__file__) +ribbon_button_replacement_text = '///// Ribbon Buttons and Menu' +additional_headers = '///// additional Headers' +add_buttons = '' +menu_selected_slot = '' +analyses_headers_replacement = '///// 1-analyses headers' +ribbon_datasetloaded_replacement = '///// 2-ribbon setDataSetLoaded' +ribbon_itemselected_replacement = '///// 3-connect ribbon itemSelected' +if_else_ladder_replacement = '///// 4-analysis if-else ladder' +tab_changed_ribbon_number = '///// ribbon tab number:' +ribbon_update_status_replacement = '///// 5-ribbon updateMenuEnabledDisabledStatus' +ribbon_widget_replacement = '' +customwidget_definition_replacement = '' + + +def create_module_ribbon(module, ribbon): + ''' Create ribbon files for the new module- .ui, .h, .cpp ''' + print('- {0} Ribbon'.format(module)) + ribbon_path = current_path + '/../../JASP-Desktop/ribbons/' + # Read ribbon.h template + with open(current_path + '/templates/ribbon.h', 'r') as f: + ribbon_header = f.read() + # {0, 1, 2} -> {SUMMARYSTATISTICS, SummaryStatistics, summarystatistics} + ribbon_header = ribbon_header.format(module.upper(), module, module.lower()) + + # Create ribbon.h + ribbon_filename = 'ribbon{0}'.format(module.lower()) + with open(ribbon_path + ribbon_filename + '.h', 'w+') as f: + f.write(ribbon_header) + print(' Created Ribbon Header') + + # Read ribbon.cpp template + with open(current_path + '/templates/ribbon.cpp', 'r') as f: + ribbon_source = f.read() + ribbon_source = ribbon_source.format(module.upper(), module, module.lower()) + + # Create ribbon buttons + ribbon_buttons = [analysis['name'] for analysis in ribbon] + menu_header_required = False + + button_text = '' + for obj in ribbon: + button_name = obj['name'] + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + button_name = button_name.replace('-', '') + button_name = button_name.replace(' ', '') + button_text += '\taddRibbonButton(ui->{0});\n'.format('button' + button_name) + # dataSetRequired + dataSetRequired = obj.get('dataSetRequired') + if dataSetRequired is not None and (not dataSetRequired): + button_text += '\tui->{0}->setDataSetNotNeeded();\n'.format('button' + button_name) + + button_text += '\n' + # Button menu - analyses + analyses = obj.get('analyses') + if analyses is not None: + menu_header_required = True + button_text += '\tQMenu *menu{0} = new QMenu(this);\n'.format(button_name); + # Create Menu + for analysis in analyses: + # FIXME: Make this more general. Use regex. + analysis_name = analysis.replace('-', '') + analysis_name = analysis_name.replace(' ', '') + button_text += '\tmenu{0}->addAction(QString("{1}"), this, SLOT(itemSelected()))->setObjectName("{2}{3}");\n'.format(button_name, analysis, module, analysis_name) + + # Set Menu + button_text += '\tui->{0}->setMenu({1});\n\n'.format('button' + button_name, 'menu' + button_name) + else: + button_text += '\tui->button{button_name}->setObjectName("{module}{button_name}");\n'.format(button_name=button_name, module=module) + button_text += '\tconnect(ui->button{0}, SIGNAL(clicked()), this, SLOT(itemSelected()));\n'.format(button_name) + + button_text += (ribbon_button_replacement_text + '\n') + ribbon_source = ribbon_source.replace(ribbon_button_replacement_text, ('\n' + button_text)) + + if menu_header_required: + ribbon_source = ribbon_source.replace(additional_headers, '#include \n{0}'.format(additional_headers)) + + # Create ribbon.cpp + with open(ribbon_path + ribbon_filename + '.cpp', 'w+') as f: + f.write(ribbon_source) + print(' Created Ribbon Source') + + # Read ribbon.ui template + with open(current_path + '/templates/ribbon.ui', 'r') as f: + ribbon_ui = f.read() + # {0, 1, 2} -> {SUMMARYSTATISTICS, SummaryStatistics, summarystatistics} + ribbon_ui = ribbon_ui.format(ribbon_name=module) + + # Read ribbon_button.ui template + with open(current_path + '/templates/ribbon_button.ui', 'r') as f: + ribbon_button = f.read() + + button_ui = '' + column_number = 0 + for obj in ribbon: + button_name = obj['name'] + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + button_name = button_name.replace('-', '') + button_name = button_name.replace(' ', '') + button_ui += ribbon_button.format(column_number=str(column_number), button_name=button_name, + button_text=obj['name']) + button_ui += '\n' + column_number += 1 + + ribbon_ui = ribbon_ui.replace(add_buttons, button_ui) + + if menu_header_required: + ribbon_ui = ribbon_ui.replace(menu_selected_slot, ' menuItemSelected()') + + # Create ribbon.ui + with open(ribbon_path + ribbon_filename + '.ui', 'w+') as f: + f.write(ribbon_ui) + print(' Created Ribbon Ui') + + +def create_layout_files(module, ribbon): + ''' Create layout files for each analysis ''' + print('- Layout Files') + + analysis_path = current_path + '/../../JASP-Desktop/analysisforms/{0}/'.format(module) + + # Read layout.h template + with open(current_path + '/templates/layout.h', 'r') as f: + layout_header = f.read() + # Read layout.cpp template + with open(current_path + '/templates/layout.cpp', 'r') as f: + layout_source = f.read() + # Read layout.ui template + with open(current_path + '/templates/layout.ui', 'r') as f: + layout_ui = f.read() + + for obj in ribbon: + analyses = obj.get('analyses') + if analyses is None: + analyses = [obj['name']] + + for analysis in analyses: + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + analysis_name = analysis.replace('-', '') + analysis_name = analysis_name.replace(' ', '') + analysis_name = module + analysis_name + 'Form' + + analysis_header = layout_header.format(analysis_name.upper(), analysis_name, analysis_name.lower()) + analysis_source = layout_source.format(analysis_name.upper(), analysis_name, analysis_name.lower()) + analysis_ui = layout_ui.format(analysis_name.upper(), analysis_name, analysis_name.lower()) + + # Create ribbon.cpp + with open(analysis_path + analysis_name.lower() + '.h', 'w+') as f: + f.write(analysis_header) + # Create ribbon.cpp + with open(analysis_path + analysis_name.lower() + '.cpp', 'w+') as f: + f.write(analysis_source) + # Create ribbon.cpp + with open(analysis_path + analysis_name.lower() + '.ui', 'w+') as f: + f.write(analysis_ui) + + print(' Created {0} Files'.format(analysis)) + + +def modify_mainwindow(module, ribbon): + ''' Add analyses to mainwindow ''' + # 1. Analyses headers + # 2. constructor - ribbon datasetloaded false + # 3. constructor - connect ribbon to itemSelected slot + # 4. Add analyses to if-else ladder + # 5. Add ribbon number to tabChanged + # 6. update menu (enabled) if dataset required by module + # 7. update ribbon from ui options + + # 8. Add ribbon page to mainwindow ui file + + mainwindow_path = current_path + '/../../JASP-Desktop/mainwindow.' + module_name = module.replace(' ', '') + analyses_headers = '' + analyses_if_else = '' + mainwindow_source = '' + with open(mainwindow_path + 'cpp', 'r') as f: + mainwindow_source = f.read() + + for obj in ribbon: + analyses = obj.get('analyses') + if analyses is None: + analyses = [obj['name']] + + for analysis in analyses: + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + analysis_name = analysis.replace('-', '') + analysis_name = analysis_name.replace(' ', '') + analysis_name = module_name + analysis_name + analyses_if_else += ('\telse if (name == "{0}")\n\t\tform = new {1}(contentArea);\n'.format(analysis_name, (analysis_name + 'Form'))) + + analysis_name += 'Form' + analyses_headers += ('#include "analysisforms/{0}/{1}.h"\n'.format(module_name, analysis_name.lower())) + + analyses_headers += ('\n' + analyses_headers_replacement) + analyses_if_else += if_else_ladder_replacement + + ribbon_datasetloaded = '\tui->ribbon{0}->setDataSetLoaded(false);\n'.format(module_name) + ribbon_datasetloaded += ribbon_datasetloaded_replacement + + ribbon_itemselected = '\tconnect(ui->ribbon{0}, SIGNAL(itemSelected(QString)), this, SLOT(itemSelected(QString)));\n'.format(module_name) + ribbon_itemselected += ribbon_itemselected_replacement + + mainwindow_source = mainwindow_source.replace(analyses_headers_replacement, analyses_headers) + mainwindow_source = mainwindow_source.replace(ribbon_datasetloaded_replacement, ribbon_datasetloaded) + mainwindow_source = mainwindow_source.replace(ribbon_itemselected_replacement, ribbon_itemselected) + mainwindow_source = mainwindow_source.replace(if_else_ladder_replacement, analyses_if_else) + + ribbon_update_status = '\tui->ribbon{0}->setDataSetLoaded(loaded);\n'.format(module_name) + ribbon_update_status += ribbon_update_status_replacement + + mainwindow_source = mainwindow_source.replace(ribbon_update_status_replacement, ribbon_update_status) + + # Write to mainwindow.cpp + with open(mainwindow_path + 'cpp', 'w') as f: + f.write(mainwindow_source) + + # Modify mainwindow ui + mainwindow_ui = '' + with open(mainwindow_path + 'ui', 'r') as f: + mainwindow_ui = f.read() + + replacement_text = ' \n'.format(name=module_name) + replacement_text += ribbon_widget_replacement + mainwindow_ui = mainwindow_ui.replace(ribbon_widget_replacement, replacement_text) + + replacement_text = ' \n Ribbon{name}\n QWidget\n'.format(name=module_name) + replacement_text += '
ribbons/ribbon{header}.h
\n 1\n
\n'.format(header=module_name.lower()) + replacement_text += customwidget_definition_replacement + mainwindow_ui = mainwindow_ui.replace(customwidget_definition_replacement, replacement_text) + + # Write to mainwindow.ui + with open(mainwindow_path + 'ui', 'w') as f: + f.write(mainwindow_ui) + + print('- Modified mainwindow') + + +def modify_module_file(module, ribbon): + ''' Add ribbon to module.cpp ''' + module_path = current_path + '/../../JASP-Desktop/module.cpp' + module_name = module.replace(' ', '') + module_source = '' + + with open(module_path, 'r') as f: + module_source = f.read() + + for line in module_source.splitlines(): + if tab_changed_ribbon_number in line: + next_tab = line.split()[-1] + replacement_text = '\t{{"{module_name}", Module("{module_name}", "{module}", {next_tab})}},\n'.format(module_name=module_name, module=module, next_tab=next_tab) + replacement_text += (tab_changed_ribbon_number + ' {0}'.format(str(int(next_tab) + 1))) + + module_source = module_source.replace(line, replacement_text) + break + + # Write to mainwindow.ui + with open(module_path, 'w') as f: + f.write(module_source) + + print('- Modified module file') + + +def create_resource_files(module, ribbon): + ''' Create options resource files for each analysis ''' + print('- Resource Files') + + resource_path = current_path + '/../../Resources/Library/' + + for obj in ribbon: + analyses = obj.get('analyses') + if analyses is None: + analyses = [obj['name']] + + for analysis in analyses: + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + analysis_name = analysis.replace('-', '') + analysis_name = analysis_name.replace(' ', '') + analysis_name = module + analysis_name + + content = '{{\n\t"name": "{0}",\n\t"autorun": true,\n\t"version": "1.0",\n\t"options": []\n}}'.format(analysis_name) + + # Create resource file + with open(resource_path + analysis_name + '.json', 'w+') as f: + f.write(content) + + print(' Created {0} resource file'.format(analysis)) + + +def create_analyses_files(module, ribbon): + ''' Create Analyses files ''' + print('- Analyses Files') + + analysis_path = current_path + '/../../JASP-Engine/JASP/R/' + + # Read analysis.R template + with open(current_path + '/templates/analysis.R', 'r') as f: + analysis_source = f.read() + + for obj in ribbon: + analyses = obj.get('analyses') + if analyses is None: + analyses = [obj['name']] + + for analysis in analyses: + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + analysis_name = analysis.replace('-', '') + analysis_name = analysis_name.replace(' ', '') + analysis_name = module + analysis_name + + analysis_source_temp = analysis_source.format(analysis_name, analysis) + + # Create resource file + with open(analysis_path + analysis_name.lower() + '.R', 'w+') as f: + f.write(analysis_source_temp) + + print(' Created {0} analysis file'.format(analysis)) + + +def create_pri_file(module, ribbon): + ''' Create pri file to include the layout and ribbon files ''' + print('- pri File') + + pri_file_path = current_path + '/../../JASP-Desktop/analysisforms/{0}/'.format(module) + + file_types = { + 'SOURCES': 'cpp', + 'HEADERS': 'h', + 'FORMS': 'ui' + } + + content = '' + for t in file_types.keys(): + content += (t + ' += \\\n') + # FIXME: Ribbon path is hardcoded + content += (' $$PWD/../../ribbons/ribbon{0}.{1} \\\n'.format(module.lower(), file_types[t])) + + for j in range(len(ribbon)): + analyses = ribbon[j].get('analyses') + if analyses is None: + analyses = [ribbon[j]['name']] + + for idx in range(0, len(analyses)): + # FIXME: Write more general statements, use regex + # FIXME: Handle duplicate ribbon and analyses names + analysis_name = analyses[idx].replace('-', '') + analysis_name = analysis_name.replace(' ', '') + analysis_name = module + analysis_name + 'Form' + content += (' $$PWD/{0}.{1}'.format(analysis_name.lower(), file_types[t])) + if idx == len(analyses) - 1 and j == len(ribbon) - 1: + content += ('\n') + else: + content += (' \\\n') + + content += '\n' + + # Create module.pri + with open(pri_file_path + module + '.pri', 'w+') as f: + f.write(content) + + +def create_new_module(): + try: + # Read the modules file + with open(current_path + '/../../Resources/modules.json', 'r') as f: + modules = json.load(f) + except Exception as e: + print('Exception occured - {exception}.'.format(exception=str(e))) + exit(1) + + # TODO: Check if module name is unique + for module in modules: + module_name = module['name'].replace(' ', '') + module_dir = current_path + '/../../JASP-Desktop/analysisforms/{0}'.format(module_name) + + # Check if module exists or not + # FIXME: This is only temporary. + # Find a better way to check module existence + if not os.path.exists(module_dir): + os.makedirs(module_dir) + + create_module_ribbon(module_name, module['ribbon']) + create_layout_files(module_name, module['ribbon']) + create_resource_files(module_name, module['ribbon']) + create_analyses_files(module_name, module['ribbon']) + create_pri_file(module_name, module['ribbon']) + modify_mainwindow(module['name'], module['ribbon']) + modify_module_file(module['name'], module['ribbon']) + +if __name__ == '__main__': + create_new_module() diff --git a/Tools/createModule/templates/analysis.R b/Tools/createModule/templates/analysis.R new file mode 100644 index 0000000000..d62551cf3d --- /dev/null +++ b/Tools/createModule/templates/analysis.R @@ -0,0 +1,38 @@ +# +# Copyright (C) 2013-2017 University of Amsterdam +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + + +{0} <- function ( + dataset = NULL, + options, + perform = "run", + callback = function(...) list(status = "ok"), + state = NULL, + ... +) {{ + + table <- list() + table[["title"]] <- "{1}" + table[["schema"]] <- list(fields = list()) + table[["data"]] <- list() + + results <- list() + results[[".meta"]] <- list(list(name = "table", type = "table")) + results[["table"]] <- table + + return (list(results = results, status = "complete")) +}} diff --git a/Tools/createModule/templates/layout.cpp b/Tools/createModule/templates/layout.cpp new file mode 100644 index 0000000000..1efab357e1 --- /dev/null +++ b/Tools/createModule/templates/layout.cpp @@ -0,0 +1,33 @@ +// +// Copyright (C) 2013-2017 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with this program. If not, see +// . +// + + +#include "{2}.h" +#include "ui_{2}.h" + +{1}::{1}(QWidget *parent) : + AnalysisForm("{1}", parent), + ui(new Ui::{1}) +{{ + ui->setupUi(this); +}} + +{1}::~{1}() +{{ + delete ui; +}} diff --git a/Tools/createModule/templates/layout.h b/Tools/createModule/templates/layout.h new file mode 100644 index 0000000000..b0bd6fada6 --- /dev/null +++ b/Tools/createModule/templates/layout.h @@ -0,0 +1,41 @@ +// +// Copyright (C) 2013-2017 University of Amsterdam +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public +// License along with this program. If not, see +// . +// + + +#ifndef {0}_H +#define {0}_H + +#include "../analysisform.h" + +namespace Ui {{ +class {1}; +}} + +class {1} : public AnalysisForm +{{ + Q_OBJECT + +public: + explicit {1}(QWidget *parent = 0); + ~{1}(); + +private: + Ui::{1} *ui; +}}; + +#endif // {0}_H diff --git a/Tools/createModule/templates/layout.ui b/Tools/createModule/templates/layout.ui new file mode 100644 index 0000000000..c6d506bca0 --- /dev/null +++ b/Tools/createModule/templates/layout.ui @@ -0,0 +1,26 @@ + + + {1} + + + + 0 + 0 + 459 + 436 + + + + + 0 + 0 + + + + Form + + + + + + diff --git a/JASP-Desktop/ribbons/ribbonr11tlearn.cpp b/Tools/createModule/templates/ribbon.cpp similarity index 79% rename from JASP-Desktop/ribbons/ribbonr11tlearn.cpp rename to Tools/createModule/templates/ribbon.cpp index 739171cd3f..ff621114b4 100644 --- a/JASP-Desktop/ribbons/ribbonr11tlearn.cpp +++ b/Tools/createModule/templates/ribbon.cpp @@ -16,17 +16,20 @@ // . // -#include "ribbonr11tlearn.h" -#include "ui_ribbonr11tlearn.h" +#include "ribbon{2}.h" +#include "ui_ribbon{2}.h" -RibbonR11tLearn::RibbonR11tLearn(QWidget *parent) : +///// additional Headers + +Ribbon{1}::Ribbon{1}(QWidget *parent) : RibbonWidget(parent), - ui(new Ui::RibbonR11tLearn) -{ + ui(new Ui::Ribbon{1}) +{{ ui->setupUi(this); -} +///// Ribbon Buttons and Menu +}} -RibbonR11tLearn::~RibbonR11tLearn() -{ +Ribbon{1}::~Ribbon{1}() +{{ delete ui; -} +}} diff --git a/JASP-Desktop/ribbons/ribbonr11tlearn.h b/Tools/createModule/templates/ribbon.h similarity index 74% rename from JASP-Desktop/ribbons/ribbonr11tlearn.h rename to Tools/createModule/templates/ribbon.h index 6fd3824e96..a45e55ed61 100644 --- a/JASP-Desktop/ribbons/ribbonr11tlearn.h +++ b/Tools/createModule/templates/ribbon.h @@ -16,25 +16,25 @@ // . // -#ifndef RIBBONR11TLEARN_H -#define RIBBONR11TLEARN_H +#ifndef RIBBON{0}_H +#define RIBBON{0}_H #include "ribbonwidget.h" -namespace Ui { -class RibbonR11tLearn; -} +namespace Ui {{ + class Ribbon{1}; +}} -class RibbonR11tLearn : public RibbonWidget -{ +class Ribbon{1} : public RibbonWidget +{{ Q_OBJECT public: - explicit RibbonR11tLearn(QWidget *parent = 0); - ~RibbonR11tLearn(); + explicit Ribbon{1}(QWidget *parent = 0); + ~Ribbon{1}(); private: - Ui::RibbonR11tLearn *ui; -}; + Ui::Ribbon{1} *ui; +}}; -#endif // RIBBONR11TLEARN_H +#endif // RIBBON{0}_H diff --git a/Tools/createModule/templates/ribbon.ui b/Tools/createModule/templates/ribbon.ui new file mode 100644 index 0000000000..28ef38bb5b --- /dev/null +++ b/Tools/createModule/templates/ribbon.ui @@ -0,0 +1,121 @@ + + + Ribbon{ribbon_name} + + + + 0 + 0 + 768 + 83 + + + + Form + + + + 4 + + + 0 + + + 4 + + + 0 + + + + + Qt::Horizontal + + + + 61 + 20 + + + + + + + + + 0 + + + 6 + + + 0 + + + 6 + + + 3 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 5 + + + + + + + + + + + + QWidget {{ color : #929292 ; }} + + + + + + QFrame::Plain + + + Qt::Vertical + + + + + + + + + + + RibbonButton + QToolButton +
widgets/ribbonbutton.h
+
+
+ + + + + + itemSelected() + + +
diff --git a/Tools/createModule/templates/ribbon_button.ui b/Tools/createModule/templates/ribbon_button.ui new file mode 100644 index 0000000000..f3f866800d --- /dev/null +++ b/Tools/createModule/templates/ribbon_button.ui @@ -0,0 +1,29 @@ + + + + + 76 + 0 + + + + {button_text} + + + + :/icons/analysis-bayesian-ttest.svg:/icons/analysis-bayesian-ttest.svg + + + + 37 + 28 + + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextUnderIcon + + + diff --git a/Tools/debian/changelog b/Tools/debian/changelog index 70aa0bc83c..94f56140ce 100644 --- a/Tools/debian/changelog +++ b/Tools/debian/changelog @@ -1,5 +1,5 @@ -jasp (0.7.5.261-0ubuntu0ppa1~wily) wily; urgency=low +jasp (0.8.5.0-0ubuntu0ppa0~xenial) xenial; urgency=low * Initial release. - -- JASP-UvA Fri, 21 Apr 2016 14:12:11 +0100 + -- JASP-UvA Mon, 18 Dec 2017 10:00:14 +0200 diff --git a/Tools/debian/control b/Tools/debian/control index 966add6a98..e5a50680b4 100644 --- a/Tools/debian/control +++ b/Tools/debian/control @@ -7,5 +7,5 @@ Build-Depends: libboost-dev, r-base-core, r-cran-rcpp, r-cran-rinside, qt5-defau Package: jasp Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, r-base-core, r-cran-rcpp, r-cran-rinside, r-cran-bayesfactor, r-cran-lme4, r-cran-afex, r-cran-car, r-cran-effects, r-cran-logspline, r-cran-lsmeans, r-cran-plotrix, r-cran-rjson, r-cran-vcd, r-cran-vcdextra, r-cran-ggplot2, r-cran-hypergeo, libqt5webkit5, libqt5svg5 +Depends: ${shlibs:Depends}, ${misc:Depends}, r-base-core, r-cran-rcpp, r-cran-rinside, r-cran-bayesfactor, r-cran-lme4, r-cran-afex, r-cran-car, r-cran-effects, r-cran-logspline, r-cran-lsmeans, r-cran-plotrix, r-cran-rjson, r-cran-vcd, r-cran-vcdextra, r-cran-ggplot2, r-cran-hypergeo, libqt5webkit5, libqt5svg5, openssl Description: JASP! diff --git a/Tools/JASPTools/DESCRIPTION b/Tools/jasptools/DESCRIPTION similarity index 73% rename from Tools/JASPTools/DESCRIPTION rename to Tools/jasptools/DESCRIPTION index ace943b05d..3f0fb80f27 100644 --- a/Tools/JASPTools/DESCRIPTION +++ b/Tools/jasptools/DESCRIPTION @@ -1,12 +1,13 @@ -Package: JASPTools +Package: jasptools Type: Package Title: Helps preview and debug JASP analyses -Version: 0.4.0 +Version: 0.5.3 Author: Tim de Jong Maintainer: Tim de Jong Description: This package assists JASP developers when writing R code. It removes the necessity of building JASP every time a change is made. Rather, analyses can be called directly in R and be debugged interactively. License: GNU General Public License Encoding: UTF-8 LazyData: true -Imports: rjson, jsonlite, stringi, vdiffr, testthat -Built: R 3.3.3; ; 2017-11-03 16:01:03 UTC; unix +Imports: jsonlite, stringi, vdiffr, testthat +RoxygenNote: 6.0.1 +Built: R 3.3.3; ; 2017-12-11 17:57:57 UTC; unix diff --git a/Tools/JASPTools/INDEX b/Tools/jasptools/INDEX similarity index 77% rename from Tools/JASPTools/INDEX rename to Tools/jasptools/INDEX index 3da5ef1fe5..dd7370c8d4 100644 --- a/Tools/JASPTools/INDEX +++ b/Tools/jasptools/INDEX @@ -2,8 +2,8 @@ analysisOptions Obtain options to run JASP analyses with. inspectTestPlots Visually inspect new/failed test plots. makeTestTable Aids in the creation of tests for tables. run Run a JASP analysis in R. -setPkgOption Change the value of an option in JASPTools. +setPkgOption Change the value of an option in jasptools. testAll Test all JASP analyses. testAnalysis Test a specific JASP analysis. view View the tables and plots in a results object. -viewPkgOptions View the configuration of JASPTools. +viewPkgOptions View the configuration of jasptools. diff --git a/Tools/jasptools/Meta/Rd.rds b/Tools/jasptools/Meta/Rd.rds new file mode 100644 index 0000000000..b244c1f184 Binary files /dev/null and b/Tools/jasptools/Meta/Rd.rds differ diff --git a/Tools/jasptools/Meta/hsearch.rds b/Tools/jasptools/Meta/hsearch.rds new file mode 100644 index 0000000000..567c2ec78a Binary files /dev/null and b/Tools/jasptools/Meta/hsearch.rds differ diff --git a/Tools/jasptools/Meta/links.rds b/Tools/jasptools/Meta/links.rds new file mode 100644 index 0000000000..f695caa0a8 Binary files /dev/null and b/Tools/jasptools/Meta/links.rds differ diff --git a/Tools/JASPTools/Meta/nsInfo.rds b/Tools/jasptools/Meta/nsInfo.rds similarity index 100% rename from Tools/JASPTools/Meta/nsInfo.rds rename to Tools/jasptools/Meta/nsInfo.rds diff --git a/Tools/jasptools/Meta/package.rds b/Tools/jasptools/Meta/package.rds new file mode 100644 index 0000000000..491b228fdc Binary files /dev/null and b/Tools/jasptools/Meta/package.rds differ diff --git a/Tools/JASPTools/NAMESPACE b/Tools/jasptools/NAMESPACE similarity index 100% rename from Tools/JASPTools/NAMESPACE rename to Tools/jasptools/NAMESPACE diff --git a/Tools/JASPTools/R/JASPTools b/Tools/jasptools/R/jasptools similarity index 100% rename from Tools/JASPTools/R/JASPTools rename to Tools/jasptools/R/jasptools diff --git a/Tools/jasptools/R/jasptools.rdb b/Tools/jasptools/R/jasptools.rdb new file mode 100644 index 0000000000..fa1d586f4e Binary files /dev/null and b/Tools/jasptools/R/jasptools.rdb differ diff --git a/Tools/jasptools/R/jasptools.rdx b/Tools/jasptools/R/jasptools.rdx new file mode 100644 index 0000000000..303ebbb1cc Binary files /dev/null and b/Tools/jasptools/R/jasptools.rdx differ diff --git a/Tools/JASPTools/help/AnIndex b/Tools/jasptools/help/AnIndex similarity index 100% rename from Tools/JASPTools/help/AnIndex rename to Tools/jasptools/help/AnIndex diff --git a/Tools/JASPTools/help/aliases.rds b/Tools/jasptools/help/aliases.rds similarity index 100% rename from Tools/JASPTools/help/aliases.rds rename to Tools/jasptools/help/aliases.rds diff --git a/Tools/jasptools/help/jasptools.rdb b/Tools/jasptools/help/jasptools.rdb new file mode 100644 index 0000000000..3d30aee592 Binary files /dev/null and b/Tools/jasptools/help/jasptools.rdb differ diff --git a/Tools/jasptools/help/jasptools.rdx b/Tools/jasptools/help/jasptools.rdx new file mode 100644 index 0000000000..58b2d3a14e Binary files /dev/null and b/Tools/jasptools/help/jasptools.rdx differ diff --git a/Tools/jasptools/help/paths.rds b/Tools/jasptools/help/paths.rds new file mode 100644 index 0000000000..b55121355f Binary files /dev/null and b/Tools/jasptools/help/paths.rds differ diff --git a/Tools/JASPTools/html/00Index.html b/Tools/jasptools/html/00Index.html similarity index 90% rename from Tools/JASPTools/html/00Index.html rename to Tools/jasptools/html/00Index.html index 01ffd5b534..5ea32dd299 100644 --- a/Tools/JASPTools/html/00Index.html +++ b/Tools/jasptools/html/00Index.html @@ -11,7 +11,7 @@

Helps preview and debug JASP analyses
[Up] [Top] -

Documentation for package ‘JASPTools’ version 0.4.0

+

Documentation for package ‘jasptools’ version 0.5.3

@@ -29,7 +29,7 @@

Help Pages

run Run a JASP analysis in R. setPkgOption -Change the value of an option in JASPTools. +Change the value of an option in jasptools. testAll Test all JASP analyses. testAnalysis @@ -37,6 +37,6 @@

Help Pages

view View the tables and plots in a results object. viewPkgOptions -View the configuration of JASPTools. +View the configuration of jasptools. diff --git a/Tools/JASPTools/html/R.css b/Tools/jasptools/html/R.css similarity index 100% rename from Tools/JASPTools/html/R.css rename to Tools/jasptools/html/R.css diff --git a/Tools/make-dmg.sh b/Tools/make-dmg.sh index 3568c9030a..3fa8ee8f1c 100755 --- a/Tools/make-dmg.sh +++ b/Tools/make-dmg.sh @@ -1,7 +1,7 @@ QT_DIR=~/Qt/5.5 R_FRAMEWORK=~/JASP/Build/Frameworks/R.framework JASP_DESKTOP=~/JASP/Build/jasp-desktop -JASP_VERSION=0.8.4 +JASP_VERSION=0.8.5 # This script builds the JASP.dmg installer # Check that you R.framework is unique (no other test versions). diff --git a/Tools/make-win-installer.nsi b/Tools/make-win-installer.nsi index 54ebb9a2c4..8324edc636 100644 --- a/Tools/make-win-installer.nsi +++ b/Tools/make-win-installer.nsi @@ -5,7 +5,7 @@ !include "nsProcess.nsh" !include "x64.nsh" -!define VERSION "0.8.4.0" +!define VERSION "0.8.5.0" !define APP_NAME "JASP" !define INSTALLER_NAME "${APP_NAME}-${VERSION}-Setup.exe" !define CONTENTS_DIR "C:\Jasp\Install" @@ -16,7 +16,7 @@ !define DESCRIPTION "${APP_NAME} - A Fresh Way to Do Statistics" !define LICENSE_TXT "${CONTENTS_DIR}\AGPL.txt" !define MAIN_APP_EXE "${APP_NAME}.exe" -!define MAIN_APP_ICO "${APP_NAME}.ico" +!define MAIN_APP_ICO "icon.ico" !define INSTALL_TYPE "SetShellVarContext all" !define REG_ROOT "HKLM" !define VERSION_TRACKING "SOFTWARE\${APP_NAME}\Versions" @@ -53,7 +53,7 @@ InstallDir "$PROGRAMFILES64\${APP_DISPLAY_NAME}" !include "MUI.nsh" -!define MUI_ICON "${CONTENTS_DIR}\icon.ico" +!define MUI_ICON "${CONTENTS_DIR}\${MAIN_APP_ICO}" #!define MUI_HEADERIMAGE #!define MUI_HEADERIMAGE_BITMAP "${CONTENTS_DIR}\JASP.bmp" #!define MUI_HEADERIMAGE_RIGHT diff --git a/Tools/pkglist.csv b/Tools/pkglist.csv index 8bf6e5da71..9f4b624e73 100644 --- a/Tools/pkglist.csv +++ b/Tools/pkglist.csv @@ -1,153 +1,177 @@ -"Package","Version" -"BAS","1.4.6" -"BDgraph","2.40" -"BMS","0.3.4" -"BayesFactor","0.9.12-2" -"Formula","1.2-2" -"GPArotation","2014.11-1" -"Hmisc","4.0-3" -"KernSmooth","2.23-15" -"MASS","7.3-45" -"Matrix","1.2-8" -"MatrixModels","0.4-1" -"R6","2.2.2" -"RColorBrewer","1.1-2" -"Rcpp","0.12.12" -"RcppEigen","0.3.3.3.0" -"SparseM","1.77" -"SuppDists","1.1-9.4" -"TH.data","1.0-8" -"TTR","0.23-2" -"abind","1.4-5" -"acepack","1.4.1" -"afex","0.18-0" -"arm","1.9-3" -"backports","1.1.0" -"base","3.3.3" -"base64enc","0.1-3" -"boot","1.3-18" -"ca","0.70" -"car","2.1-5" -"checkmate","1.8.3" -"class","7.3-14" -"cluster","2.0.5" -"coda","0.19-1" -"codetools","0.2-15" -"coin","1.2-1" -"colorspace","1.3-2" -"compiler","3.3.3" -"contfrac","1.1-11" -"conting","1.6" -"corpcor","1.6.9" -"crayon","1.3.2" -"curl","2.8.1" -"d3Network","0.5.2.1" -"data.table","1.10.4" -"datasets","3.3.3" -"deSolve","1.20" -"dichromat","2.0-0" -"digest","0.6.12" -"ellipse","0.3-8" -"elliptic","1.3-7" -"estimability","1.2" -"evaluate","0.10.1" -"fdrtool","1.2.15" -"foreign","0.8-67" -"ggm","2.3" -"ggplot2","2.2.1" -"glasso","1.8" -"gnm","1.0-8" -"grDevices","3.3.3" -"graphics","3.3.3" -"grid","3.3.3" -"gridExtra","2.2.1" -"gtable","0.2.0" -"gtools","3.5.0" -"highr","0.6" -"hmeasure","1.0" -"htmlTable","1.9" -"htmltools","0.3.6" -"htmlwidgets","0.9" -"huge","1.2.7" -"hypergeo","1.2-13" -"igraph","1.1.2" -"irlba","2.2.1" -"jpeg","0.1-8" -"jsonlite","1.5" -"knitr","1.17" -"labeling","0.3" -"lattice","0.20-34" -"latticeExtra","0.6-28" -"lavaan","0.5-23.1097" -"lazyeval","0.2.0" -"lme4","1.1-13" -"lmerTest","2.0-33" -"lmtest","0.9-35" -"logspline","2.1.9" -"lsmeans","2.27-2" -"magrittr","1.5" -"markdown","0.8" -"matrixcalc","1.0-3" -"methods","3.3.3" -"mgcv","1.8-17" -"mi","1.0" -"mime","0.5" -"minqa","1.2.4" -"mnormt","1.5-5" -"modeltools","0.2-21" -"multcomp","1.4-7" -"munsell","0.4.3" -"mvtnorm","1.0-6" -"network","1.13.0" -"nlme","3.1-131" -"nloptr","1.0.4" -"nnet","7.3-12" -"numDeriv","2016.8-1" -"parallel","3.3.3" -"pbapply","1.3-3" -"pbivnorm","0.6.0" -"pbkrtest","0.4-7" -"pkgconfig","2.0.1" -"plotrix","3.6-6" -"plyr","1.8.4" -"png","0.1-7" -"praise","1.0.0" -"psych","1.7.8" -"qgraph","1.4.4" -"quadprog","1.5-5" -"quantmod","0.4-10" -"quantreg","5.33" -"qvcalc","0.9-0" -"relimp","1.0-5" -"reshape2","1.4.2" -"rjson","0.2.15" -"rlang","0.1.2" -"rpart","4.1-10" -"sandwich","2.4-0" -"scales","0.5.0" -"sem","3.1-9" -"semTools","0.4-14" -"sna","2.4" -"spatial","7.3-11" -"splines","3.3.3" -"statnet.common","4.0.0" -"stats","3.3.3" -"stats4","3.3.3" -"stringi","1.1.5" -"stringr","1.2.0" -"survival","2.40-1" -"tcltk","3.3.3" -"testthat","1.0.2" -"tibble","1.3.4" -"tools","3.3.3" -"tseries","0.10-42" -"utils","3.3.3" -"vcd","1.4-3" -"vcdExtra","0.7-0" -"viridis","0.4.0" -"viridisLite","0.2.0" -"whisker","0.3-2" -"xtable","1.8-2" -"xts","0.10-0" -"yaml","2.1.14" -"zoo","1.8-0" +"Package","Version","Depends" +"BAS","1.4.7","R (>= 3.0)," +"BDgraph","2.41","R (>= 3.0.0), Matrix, igraph" +"BMS","0.3.4","R (>= 2.5)" +"BayesFactor","0.9.12-2","R (>= 3.0.2), coda, Matrix (>= 1.1-1)" +"Epi","2.10","R (>= 3.0.0), utils" +"Formula","1.2-2","R (>= 2.0.0), stats" +"GPArotation","2014.11-1","R (>= 2.0.0)" +"GeneNet","1.2.13","R (>= 3.0.2), corpcor (>= 1.6.8), longitudinal (>= 1.1.12),fdrtool (>= 1.2.15)" +"Hmisc","4.0-3","lattice, survival (>= 2.40-1), Formula, ggplot2 (>= 2.2)" +"IsingFit","0.3.1","R (>= 3.0.0)" +"IsingSampler","0.2","Rcpp (>= 0.10.4), R (>= 3.0.0)" +"KernSmooth","2.23-15","R (>= 2.5.0), stats" +"MASS","7.3-45","R (>= 3.1.0), grDevices, graphics, stats, utils" +"Matrix","1.2-8","R (>= 3.0.1)" +"MatrixModels","0.4-1","R (>= 3.0.1)" +"R6","2.2.2","R (>= 3.0)" +"RColorBrewer","1.1-2","R (>= 2.0.0)" +"Rcpp","0.12.13","R (>= 3.0.0)" +"SparseM","1.77","R (>= 2.15), methods" +"SuppDists","1.1-9.4","R (>= 3.3.0)" +"TH.data","1.0-8","R (>= 2.10.0), survival, MASS" +"TTR","0.23-2",NA +"abind","1.4-5","R (>= 1.5.0)" +"acepack","1.4.1",NA +"afex","0.18-0","R (>= 3.1.0), lme4 (>= 1.1-8), lsmeans (>= 2.17)" +"arm","1.9-3","R (>= 3.1.0), MASS, Matrix (>= 1.0), stats, lme4 (>= 1.0)" +"assertthat","0.2.0",NA +"backports","1.1.1","R (>= 3.0.0)" +"base","3.3.3",NA +"base64enc","0.1-3","R (>= 2.9.0)" +"bindr","0.1",NA +"bindrcpp","0.2",NA +"boot","1.3-18","R (>= 3.0.0), graphics, stats" +"bootnet","1.0.2","ggplot2, R (>= 3.0.0)" +"ca","0.70","R (>= 3.0.0)" +"car","2.1-5","R (>= 3.2.0)" +"checkmate","1.8.5","R (>= 3.0.0)" +"class","7.3-14","R (>= 3.0.0), stats, utils" +"cluster","2.0.5","R (>= 3.0.1)" +"cmprsk","2.2-7","R (>= 2.15.0), survival" +"coda","0.19-1","R (>= 2.14.0)" +"codetools","0.2-15","R (>= 2.1)" +"coin","1.2-1","R (>= 2.14.0), methods, survival" +"colorspace","1.3-2","R (>= 2.13.0), methods" +"compiler","3.3.3",NA +"contfrac","1.1-11",NA +"conting","1.6","R (>= 2.15.0)" +"corpcor","1.6.9","R (>= 3.0.2)" +"curl","3.0","R (>= 3.0.0)" +"d3Network","0.5.2.1","R (>= 3.0.0)" +"data.table","1.10.4-3","R (>= 3.0.0)" +"datasets","3.3.3",NA +"deSolve","1.20","R (>= 2.15.0)" +"dichromat","2.0-0","R (>= 2.10), stats" +"digest","0.6.12","R (>= 2.4.1)" +"doSNOW","1.0.15","R (>= 2.5.0), foreach(>= 1.2.0), iterators(>= 1.0.0), snow(>=0.3.0), utils" +"dplyr","0.7.4","R (>= 3.1.2)" +"ellipse","0.3-8","R (>= 2.0.0),graphics,stats" +"elliptic","1.3-7","R (>= 2.5.0)" +"estimability","1.2","stats" +"etm","0.6-2","R (>= 2.14), survival" +"evaluate","0.10.1","R (>= 3.0.2)" +"fdrtool","1.2.15","R (>= 3.0.2)" +"foreach","1.4.3","R (>= 2.5.0)" +"foreign","0.8-67","R (>= 3.0.0)" +"ggm","2.3","igraph" +"ggplot2","2.2.1","R (>= 3.1)" +"glasso","1.8",NA +"glmnet","2.0-13","Matrix (>= 1.0-6), utils, foreach" +"glue","1.2.0","R (>= 3.1)" +"gnm","1.0-8","R (>= 2.3.0)" +"grDevices","3.3.3",NA +"graphics","3.3.3",NA +"grid","3.3.3",NA +"gridExtra","2.3",NA +"gtable","0.2.0","R (>= 2.14)" +"gtools","3.5.0","R (>= 2.10)" +"highr","0.6","R (>= 3.0.2)" +"hmeasure","1.0","R (>= 2.10)" +"htmlTable","1.9",NA +"htmltools","0.3.6","R (>= 2.14.1)" +"htmlwidgets","0.9",NA +"huge","1.2.7","R (>= 3.0.0), Matrix, lattice, igraph, MASS" +"hypergeo","1.2-13","R (>= 3.1.0)," +"igraph","1.1.2","methods" +"irlba","2.3.1","Matrix" +"iterators","1.0.8","R (>= 2.5.0), utils" +"jpeg","0.1-8","R (>= 2.9.0)" +"jsonlite","1.5","methods" +"knitr","1.17","R (>= 3.1.0)" +"labeling","0.3",NA +"lattice","0.20-34","R (>= 3.0.0)" +"latticeExtra","0.6-28","R (>= 2.10.0), lattice, RColorBrewer" +"lavaan","0.5-23.1097","R(>= 3.1.0)" +"lazyeval","0.2.1","R (>= 3.1.0)" +"lme4","1.1-14","R (>= 3.0.2), Matrix (>= 1.1.1), methods, stats" +"lmerTest","2.0-33","R (>= 3.0.0), Matrix, stats, methods, lme4 (>= 1.0)" +"lmtest","0.9-35","R (>= 2.10.0), stats, zoo" +"logspline","2.1.9",NA +"longitudinal","1.1.12","R (>= 3.0.2), corpcor (>= 1.6.8)" +"lsmeans","2.27-2","estimability, methods, R (>= 3.2)" +"magrittr","1.5",NA +"markdown","0.8","R (>= 2.11.1)" +"matrixcalc","1.0-3","R (>= 2.0.1)" +"metafor","2.0-0","R (>= 3.2.0), methods, Matrix" +"methods","3.3.3",NA +"mgcv","1.8-17","R (>= 2.14.0), nlme (>= 3.1-64)" +"mgm","1.2-1",NA +"mi","1.0","R (>= 3.0.0), methods, Matrix, stats4" +"mime","0.5",NA +"minqa","1.2.4",NA +"mitools","2.3","R (>= 2.10)" +"mnormt","1.5-5","R (>= 2.2.0)" +"modeltools","0.2-21","stats, stats4" +"multcomp","1.4-7","stats, graphics, mvtnorm (>= 1.0-3), survival (>= 2.39-4),TH.data (>= 1.0-2)" +"munsell","0.4.3",NA +"mvtnorm","1.0-6","R(>= 1.9.0)" +"network","1.13.0","R (>= 2.10), utils" +"nlme","3.1-131","R (>= 3.0.2)" +"nloptr","1.0.4",NA +"nnet","7.3-12","R (>= 2.14.0), stats, utils" +"numDeriv","2016.8-1","R (>= 2.11.1)" +"parallel","3.3.3",NA +"parcor","0.2-6","MASS, glmnet, ppls, Epi, GeneNet" +"pbapply","1.3-3","R (>= 3.2.0)" +"pbivnorm","0.6.0",NA +"pbkrtest","0.4-7","R (>= 3.2.3), lme4 (>= 1.1.10)" +"pkgconfig","2.0.1",NA +"plotrix","3.6-6",NA +"plyr","1.8.4","R (>= 3.1.0)" +"png","0.1-7","R (>= 2.9.0)" +"ppls","1.6-1","splines, MASS" +"psych","1.7.8","R (>= 2.10)" +"purrr","0.2.4","R (>= 3.1)" +"qgraph","1.4.4","R (>= 3.0.0)" +"quadprog","1.5-5","R (>= 2.15.0)" +"quantmod","0.4-11","R (>= 3.2.0), xts(>= 0.9-0), zoo, TTR(>= 0.2), methods" +"quantreg","5.34","R (>= 2.6), stats, SparseM" +"qvcalc","0.9-1",NA +"relaimpo","2.2-2","R(>= 2.2.1), MASS, boot, survey, mitools, graphics" +"relimp","1.0-5","R (>= 2.0.0)" +"reshape2","1.4.2",NA +"rjson","0.2.15","R (>= 3.1.0)" +"rlang","0.1.2","R (>= 3.1.0)" +"rpart","4.1-10","R (>= 2.15.0), graphics, stats, grDevices" +"sandwich","2.4-0","R (>= 2.10.0)" +"scales","0.5.0","R (>= 2.13)" +"sem","3.1-9","R (>= 2.14.0), stats" +"semTools","0.4-14","R(>= 3.0), methods, lavaan(>= 0.5-22), utils, stats, graphics" +"sna","2.4","R (>= 2.0.0), utils, statnet.common, network" +"snow","0.4-2","R (>= 2.13.1), utils" +"spatial","7.3-11","R (>= 3.0.0), graphics, stats, utils" +"splines","3.3.3",NA +"statnet.common","4.0.0",NA +"stats","3.3.3",NA +"stats4","3.3.3",NA +"stringi","1.1.5","R (>= 2.14)" +"stringr","1.2.0","R (>= 2.14)" +"survey","3.32-1","R (>= 2.16.0), grid, methods, Matrix, survival" +"survival","2.40-1","R (>= 2.13.0)" +"tcltk","3.3.3",NA +"tibble","1.3.4","R (>= 3.1.0)" +"tidyr","0.7.2","R (>= 3.1.0)" +"tidyselect","0.2.2","R (>= 3.1.0)" +"tools","3.3.3",NA +"tseries","0.10-42","R (>= 2.10.0)" +"utils","3.3.3",NA +"vcd","1.4-3","R (>= 2.4.0), grid" +"vcdExtra","0.7-1","R (>= 2.10), vcd, gnm (>= 1.0.3), grid" +"viridis","0.4.0","R (>= 2.10), viridisLite (>= 0.2.0)" +"viridisLite","0.2.0","R (>= 2.10)" +"whisker","0.3-2",NA +"xtable","1.8-2","R (>= 2.10.0)" +"xts","0.10-0","zoo (>= 1.7-12)" +"yaml","2.1.14",NA +"zoo","1.8-0","R (>= 2.10.0), stats" diff --git a/Tools/requiredPackages.R b/Tools/requiredPackages.R index 7be73bc5c1..998e510ff4 100644 --- a/Tools/requiredPackages.R +++ b/Tools/requiredPackages.R @@ -49,6 +49,8 @@ for (file in files) { # Temporarly add the GPArotation manually (incorrectly marked as "Suggest' in psych) reqPkgs <- c(reqPkgs, "GPArotation") +# Exclude jasptools manually (should not be shipped) +basePkgs <- c(basePkgs, "jasptools") reqPkgs <- sort(unique(reqPkgs)) reqPkgs <- reqPkgs[! reqPkgs %in% basePkgs] diff --git a/Tools/showVersion.R b/Tools/showVersion.R new file mode 100644 index 0000000000..ce4bd47b96 --- /dev/null +++ b/Tools/showVersion.R @@ -0,0 +1,10 @@ +# sessionInfo of R +sessionInfo() + +# gdtools version info +cat("\nCairo version:") +gdtools::version_cairo() +cat("\nFreetype version:") +gdtools::version_freetype() +cat("\nFontconfig version: ") +gdtools::version_fontconfig() \ No newline at end of file