Interactive report¶
To help visualize and explore experiment results, an interactive report comes
with Forward. This report is built on top of the
forward.backend.Backend
which parses analysis results in standard
Python data structures.
Run the server¶
To run the server, the simplest alternative is to use the provided command-line interface (scripts/forward-cli.py).
$ forward-cli.py report experiment_name
Note
The current working directory needs to contain the experiment folder to use this command.
Alternative method for sharing¶
If you want to share the report with colleagues, or host it on a website after publication, it is best to use a more robust web server. The following script can be used:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/env python
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
import forward.backend
forward.backend.initialize_application("EXPERIMENT_NAME")
http_server = HTTPServer(WSGIContainer(forward.backend.app))
http_server.listen(5000) # Set the port here
IOLoop.instance().start()
|
It is also a good idea to use a process control system like supervisord when hosting the report on a server.
Extending the dynamic report¶
Backend¶
The backend can be used to do your analysis without leaving Python. This can be useful if you’re not interested in the dynamic report or if you want to do something specific without worrying about integration in the web report.
A documented example can be found on Github. It is a Jupyter notebook showing how to do a QQ plot of SKAT p-values using matplotlib. It is very simple and shows how to access data and how to get help interactively.
For the interactive report, we use a Flask binding of most Backend methods. These bindings make the Backend queryable using HTTP requests. The returned data is either HTML (rarely) and json (most of the time).
Front-end¶
Introduction¶
The interface for the report was built using modern web technologies. It communicates with the backend using the Flask API (described above). The tables are react components that take care of querying the server and re-rendering themselves following user interaction. Most of the plots are generated using d3.js, a JavaScript framework for DOM manipulation that is very popular for data visualization.
The javascript dependencies are managed using Bower. All
the files are in the forward/static subdirectory of the repo. If you want
to extend the report without adding js dependencies, you don’t need to take
care of Bower, because all of the required files are included in the repo. This
decision was made to make it easier for developers to play with the frond-end
without tedious configuration. If you want to update the js dependencies, you
may edit the bower.json
file and run bower update
.
Nonetheless, front-end developers will need to build their javascript. This is because react code uses JSX which needs to be converted to regular javascript. Documentation for this step is available here. To summarize, you need to install babel:
npm install --global babel
And then run the build command:
cd forward/static/js
babel src --watch --out-dir build
The --watch
flag looks at activity on your filesystem and runs the
conversion as soon as something changes.
Note
Extending the report is not easy. If you have feature requests, feel free to use the issue tracker. You can also email us (contact information is available through github) with questions or comments.
Rendering Sections¶
The report’s home page is rendered using jinja2. The template for this page is found in forward/templates/default.html.
This template is fairly empty. It loads some javascript and css, but it has no content whatsoever. Notice the following piece of code:
// Get the tasks.
$.getJSON(window.location.pathname + "/experiment/tasks.json", function(data) {
var tasks = data.tasks;
// For every task, fetch the html snippet.
tasks.map(function(task) {
forward.handleTask(task.type, task.name);
});
forward.xrefs.reNumber();
});
This snippet (included in the default.html template) queries the tasks that
were executed in this experiment and calls the forward.handleTask
function
to find an appropriate task handler. This function is basically a switch ...
case
dispatching different handlers based on the task type. Then, the
handler is responsible for populating the relavant report section.
Let’s take linear regression as an example. It’s handler is
forward._handleLinear
. The latter do the following:
- Create a new DOM element (a div) with id section_TaskName. It appends it to the results div.
- It fetches an html snippet from the backend (in this case, it will request
API_ROOT/tasks/linear_section.html
from the API which will renderforward/templates/lineartest.html
). This contains only a couple of DOM elements that are needed to hookup the dynamic tables and plots. The dispatch method will then include this piece of HTML as theinnerHTML
of the div we created in step 1. - The dispatch method also triggers the javascript rendering function, in this
case it is defined in
section_glm.js
. This function call is finally responsible for rendering everything you see on screen.