Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
FransMeerhoff authored and FransMeerhoff committed Oct 11, 2017
2 parents 7cbc541 + f0f5363 commit ae8efcc
Show file tree
Hide file tree
Showing 195 changed files with 17,229 additions and 9,370 deletions.
8 changes: 6 additions & 2 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
## Environment (for bugs)
## Template for bug reports
<!--- Include as many relevant details about the environment you experienced the bug in -->
<!--- If possible please attach your data and/or JASP file to the issue -->
<!--- Note that github requires you to zip the file -->
* JASP version:
* OS name and version:
* Analysis:
## Environment (for enhancement requests)
* Steps to reproduce:

## Template for enhancement requests
<!--- Give a short and clear description of your enhancement request -->
* Enhancement:
* Purpose:
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ Resources/TestFiles


JASP-Engine/JASP/R/.Rhistory
*.autosave
20 changes: 19 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@

JASP Release Notes
==================


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

Changes:

- Remove unused R packages
- Additional Info for T-Test and Correlation Bayesian Pairs Robustness plots (Common module)


Version 0.5
-----------

Expand Down
7 changes: 7 additions & 0 deletions Docs/development/jasp-adding-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ and connect the above slot with the triggered() signal in the `addHelpTab()` fun

connect(newModule, SIGNAL(triggered()), this, SLOT(toggleNewModule()));

Add a declaration of `toggleNewModule()` to the private slots of the TabBar class definition in `tabbar.h`

private slots:
...
void toggleSummaryStats();
void toggleNewModule();


##### Modify the tabChanged function in MainWindow.cpp
`tabChanged()` in MainWindow.cpp contains an if-else ladder for the current Active tab. Add 'New Module' to it.
Expand Down
80 changes: 69 additions & 11 deletions Docs/development/r-analyses-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,38 @@ It is recommended to **only** use `.vf()` for display purposes. Using it to crea

JASP accepts images as SVGs encoded as base64 data URIs. The following functions are useful for creating images in this format.

`.beginSaveImage(width, height)`
`.endSaveImage(descriptor)`

`.beginSaveImage()` starts the image capturing process, and returns a descriptor. Once the analysis has performed all the rendering it needs, it should call `.endSaveImage()`, passing in the descriptor provided by `.beginSaveImage()`. `.endSaveImage()` returns a descriptor which can be assigned to the image object described below.
Recently, we moved to a new system for writing images, to support the saveImage functionality (saving JASP images to a file). Here is the quick overview:

1. Create a `ggplot2` plot in your code. If you're working with (deprecated) base-r plots, wrap your plotting routine in a function (don't choose this option):
```r
p <- ggplot2::ggplot(...)
```
__OR__
```r
.plotFunc() <- function() {
# add plotting routine here
plot(plotData, plotParameters)
}
```
2. Write the image to an object using the function `.writeImage()`:
```r
imgObj <- .writeImage(width = options$plotWidth,
height = options$plotHeight,
plot = p)
```
__OR__
```r
imgObj <- .writeImage(width = options$plotWidth,
height = options$plotHeight,
plot = .plotFunc)
```
3. Extract the necessary information from the image object to your plot object that will go into the output:
```r
plot[["data"]] <- imgObj[["png"]]
plot[["obj"]] <- imgObj[["obj"]]
plot[["convertible"]] <- TRUE
plot[["status"]] <- "complete"
```

### Cleaning data

Expand Down Expand Up @@ -200,7 +227,7 @@ An example of a results bundle might be:
- `results` : a results object, descriped below
- `status` : the status, this can be either `"inited"` (typically to be returned when `perform == "init"`) or `"complete"` (typically returned when `perform == "run"`)
- `state` : arbitrary data that can be retrieved in a subsequent call of this analysis with a call to `.retrieveState()`, explained below
- `keep` : a list of file descriptors (from `.endSaveImage()`). This instructs the temporary file system to keep these files, and not delete them.
- `keep` : a list of file descriptors (from `.writeImage()`). This instructs the temporary file system to keep these files, and not delete them.

### Results

Expand Down Expand Up @@ -449,7 +476,40 @@ It will return a named list with TRUE/FALSE values indicating which options have

# otherwise continue

### State
Progress bar
------------

If an analysis is going to run for a long time it's nice to give the user some reassurance that something is actually happening. Of course we have the spinner, but this provides no actual progress indication. To this purpose the `.newProgressbar` function can be used. The function takes the following arguments:
- `ticks`: integer specifying the number of times the progress bar needs to be updated to reach completion.
- `callback`: callback function which is supplied to each analysis and described above.
- `skim`: integer specifying the percentage that should be "skimmed" from the total 100%. The progress bar generally captures only some portion of an analysis. If the remainder might also take some time we can reserve a portion of the progress bar. Default percentage is `5`.
- `response`: boolean, should the progressbar return the response of the callback? Default is `FALSE`.
Note that `.newProgressbar` itself returns a function. This function takes the optional arguments:
- `results`: results list. See above to read more about the results list structure.
- `complete`: boolean specifying if the progress bar should be forced to immediate (premature) completion.
### Example:
A typical analysis that takes a while is the Bayesian ANOVA.
Now, there are parts of this analysis that go quite quick; calculating descriptives or effects takes no time.
The model calculation is slow, however, in this part of the code a progress indicator makes a lot sense.
Say we have the number of models we will calculate stored in `nModels`. Before the first model is calculated we then run
```
progressbar <- .newProgressbar(ticks=nModels, callback=callback)
```
Now after each calculated model we simply call
```
progressbar()
```
to update the progress.
If we want to make the analysis responsive to user changes we can set `response` to `TRUE` and check the callback output as described above.
State
-----
The state is a storage system. This storage can be used to transfer useful data between different calls to an analysis.
The main goal of the state is to prevent recalculating things that were already calculated once (and thus make analyses quicker). Let's use the Bayesian ANOVA as an example of its practical relevance. This analysis may take up to several minutes to fully calculate its result -- which is not that unusual for a Bayesian analysis. Now if a user decides he would also like to see descriptive statistics the analysis will be run again. If we had no storage system in place it would take several minutes to give an additional table with descriptive statistics because the ANOVA has to be calculated all over again -- eventhough we already did this. With the state system it becomes possible to store the outcome of the ANOVA and then re-use it. Asking for additional output such as a descriptives table will now result in a very short calculation because the ANOVA calculation can be avoided. It may be clear that it is not always possible to re-use output from an earlier call to the analysis. For example, if the dependent variable of the ANOVA is swapped for a different one, the old results become unusable.
Expand All @@ -473,12 +533,10 @@ attr(state, "key") <- stateKey
```
Now if the analysis is called again and e.g. `sampleMode` changes, only the plot will be returned.
If there are state items you would like to keep indefinitely -- regardless of the options a user changes -- you may also specify this in the state, e.g.:
```
attr(state, "keep") <- c("model", "options")
```
If there are state items you would like to keep indefinitely -- regardless of the options a user changes -- you must omit these in the stateKey.
### Error handling
Error handling
--------------
#### Checking for errors
Expand Down
19 changes: 16 additions & 3 deletions JASP-Common/analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,31 @@
#include <boost/foreach.hpp>

#include "options/options.h"
#include "tempfiles.h"
#include "appinfo.h"

using namespace boost::uuids;
using namespace boost;
using namespace std;

Analysis::Analysis(int id, string name, Options *options, Version version, bool autorun, bool usedata)
Analysis::Analysis(int id, string name, Options *options, const Version &version, bool autorun, bool usedata)
{
_id = id;
_name = name;
_options = options;
_autorun = autorun;
_usedata = usedata;
_version = version;

_results = Json::nullValue;
_imgResults = Json::nullValue;
_userData = Json::nullValue;
_saveImgOptions = Json::nullValue;
_revision = 0;

_options->changed.connect(boost::bind(&Analysis::optionsChangedHandler, this, _1));

_status = Empty;
_progress = -1;
}

Analysis::~Analysis()
Expand All @@ -62,9 +68,10 @@ void Analysis::scheduleRun()
optionsChanged(this);
}

void Analysis::setResults(Json::Value results)
void Analysis::setResults(Json::Value results, int progress)
{
_results = results;
_progress = progress;
resultsChanged(this);
}

Expand Down Expand Up @@ -124,6 +131,7 @@ Json::Value Analysis::asJSON() const

analysisAsJson["id"] = _id;
analysisAsJson["name"] = _name;
analysisAsJson["progress"] = _progress;
analysisAsJson["version"] = _version.asString();
analysisAsJson["results"] = _results;

Expand Down Expand Up @@ -193,6 +201,11 @@ Analysis::Status Analysis::status() const

void Analysis::setStatus(Analysis::Status status)
{
if ((status == Analysis::Running || status == Analysis::Initing) && _version != AppInfo::version)
{
tempfiles_deleteList(tempfiles_retrieveList(_id));
_version = AppInfo::version;
}
_status = status;
}

Expand Down
5 changes: 3 additions & 2 deletions JASP-Common/analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class Analysis

enum Status { Empty, Initing, Inited, InitedAndWaiting, Running, Complete, Aborting, Aborted, Error, SaveImg, Exception };

Analysis(int id, std::string name, Options *options, Version version, bool isAutorun = true, bool usedata = true);
Analysis(int id, std::string name, Options *options, const Version &version, bool isAutorun = true, bool usedata = true);
virtual ~Analysis();

Options *options() const;
Expand All @@ -43,7 +43,7 @@ class Analysis
boost::signals2::signal<void (Analysis *source)> resultsChanged;
boost::signals2::signal<void (Analysis *source)> userDataLoaded;

void setResults(Json::Value results);
void setResults(Json::Value results, int progress = -1);
void setImageResults(Json::Value results);
void setUserData(Json::Value userData, bool silient = false);
const Json::Value &results() const;
Expand Down Expand Up @@ -89,6 +89,7 @@ class Analysis
Json::Value _imgResults;
Json::Value _userData;
Json::Value _saveImgOptions;
int _progress;

int callback(Json::Value results);

Expand Down
4 changes: 2 additions & 2 deletions JASP-Common/analysisloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@

#include "dirs.h"
#include "version.h"
#include "appinfo.h"

using namespace std;
using namespace boost;

Analysis *AnalysisLoader::load(int id, string analysisName, Json::Value *data)
Analysis *AnalysisLoader::load(int id, string analysisName, const Version &version, Json::Value *data)
{
Options *options = new Options();

Expand All @@ -47,7 +48,6 @@ Analysis *AnalysisLoader::load(int id, string analysisName, Json::Value *data)

bool autorun = analysisDesc.get("autorun", false).asBool();
bool usedata = analysisDesc.get("usedata", true).asBool();
Version version = Version(analysisDesc.get("version", "0.00").asString());

if (data != NULL)
options->set(*data);
Expand Down
3 changes: 2 additions & 1 deletion JASP-Common/analysisloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@
#define ANALYSISLOADER_H

#include "analysis.h"
#include "version.h"

class AnalysisLoader
{
public:

static Analysis *load(int id, std::string analysisName, Json::Value* data = NULL);
static Analysis *load(int id, std::string analysisName, const Version& version, Json::Value* data = NULL);

};

Expand Down
2 changes: 1 addition & 1 deletion JASP-Common/appinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

#include "appinfo.h"

const Version AppInfo::version = Version(0, 8, 2, 255);
const Version AppInfo::version = Version(0, 8, 3, 255);
const std::string AppInfo::name = "JASP";
const std::string AppInfo::builddate = __DATE__ " " __TIME__ " (Netherlands)" ;

Expand Down
Loading

0 comments on commit ae8efcc

Please sign in to comment.