Commit 626ac773 authored by Flavio TARSETTI's avatar Flavio TARSETTI
Browse files

Merge branch 'docs' into 'master'


See merge request !6
parents 1eda1cdc 1f357814
Pipeline #22485 passed with stages
in 34 minutes and 41 seconds
This section includes information for using the Python API of
.. automodule:: beat.editor
......@@ -74,7 +74,7 @@ source_suffix = '.rst'
master_doc = 'index'
# General information about the project.
project = u'beat.backend.python'
project = u'beat.editor'
import time
copyright = u'%s, Idiap Research Institute' % time.strftime('%Y')
This section is a compilation of notes and advice about how to develop the ``beat.editor`` project, aimed at those less familiar with web development but familiar with Python.
Important Concepts
Before developing for ``beat.editor``, you'll need to familiarize yourself with at least the following concepts/tools:
* Flask & RESTful APIs
* JSON-schema, v4
* Node.js
* The DOM & browser APIs
* Javascript
* ES6
* React
* Redux
* Bootstrap
* D3 & SVG in general
* Flow typings
* Webpack
* Babel
* Karma
* Mocha
Configuring Your Editor
Your editor is probably adequately configured for editing Python code; it won't be properly configured for the JS part of ``beat.editor`` unless you do modern web development.
* Make sure to pick up JS & JSX syntax highlighting for your editor! Make sure your highlighting supports "ES6" (a landmark JS verion released a couple years ago) and "Flow" (the static typing language extension we are using).
* The configuration files for various linters/static analysis tools are found as dotfiles in the root folder for the JS (next to ``package.json``).
* The provided ``.tern-project`` file is configuration for Tern.js, a JS code analysis tool (autocompletion, etc.). If you're using a popular editor, it'll probably have a plugin for Tern.js.
* There's a few diferent linters available for the different code types (JS, HTML, CSS, JSX). I would suggest installing a linting engine that picks up the available linters for you, like "Syntastic" or "ALE" for Vim. If you aren't using a linting engine, here's some additional notes to get linting working:
- Linting via ESLint should be configured to use the local installation (from ``node_modules/``) - *not* a global installation. This lets ESLint properly find all the plugins on a per-project basis.
- Linting CSS via Stylelint should be configured similarly to ESLint. Since this linter is relatively new, your linting engine/editor might not pick it up automatically.
* Linting using Flow needs more configuration regardless of how you set up linting. You need to install the ``flow-typed`` package from NPM globally and pull the types for dependencies: ::
$ npm i -g flow-typed
$ cd conda/js
$ flow-typed update
Development Notes
- You'll probably want the `React devtools <>`_ and `Redux devtools <>`_ browser plugins to sanely debug and inspect React/Redux code.
- You might need to enable/configure sourcemaps in your browser manually.
- The Python server can be run in dev mode (doesn't try to launch a browser tab) via the ``--dev`` flag.
- You'll probably want Webpack's dev server (``npm start``) running in a separate terminal window/tab, as Webpack will automatically rebuild/update your project when files change (served at ``localhost:9101``. However, changes to the webpack config or other configuration files may not be watched. In general, anything under ``conda/js/src/`` should be hot-reloaded, while anything else may not be. If there's issues with the app when running the dev server that you don't expect or don't make sense (especially if the issue came up after a hot reload), try refreshing the page - sometimes the hot reloader doesn't properly handle complex changes (such as state management or async functionality).
- When changing/updating dependencies, you'll want to install/update flow types for them. Run ``flow-typed update`` again whenever you add JS dependencies.
- If you're quickly iterating test code, you can run the testing daemon in a terminal tab/pane with the ``test-start`` npm script. This lets you quickly trigger tests again with ``karma run`` (via a global ``karma-cli`` installation through npm) since it won't have to start up the daemon each time you want to run the tests. It will also rerun tests when the files change (this is configurable). The daemon is a bit buggy, so if you are getting unexpected errors, try restarting it.
JS Project Structure
All JS is stored under ``conda/js``. Unless otherwise noted, all future paths given in this section are relative to that one.
* All dependencies are stored in ``node_modules/``.
* All source is stored in ``src/``.
* All ``*.spec.*`` files are test files. They should be next to the file/component they are testing, which has the same name minus the ``.spec`` infix.
* All this source code is pulled together by ``main.jsx``, which is processed by Webpack via the ``webpack.config.js`` config file.
* ``test/`` holds test data and configures and runs the tests.
* There are 3 different folders in ``src/``, ``components/``, ``helpers``, and ``store/``. These three different folders are discussed further below.
``components/`` holds the UX components, written in a mix of HTML & JSX & CSS, and their associated processing code. Non-generic components (components related to a specific editor) are stored in their respective sub-folders, broken up by BEAT entity type:
* ``algorithm/`` holds the Algorithm Editor code.
* ``database/`` holds the Database Editor code.
* ``dataformat/`` holds the Dataformat Editor code.
* ``experiment/`` holds the Experiment Editor code, which also uses code from the toolchain editor.
* ``library/``: holds the Library Editor code.
* ``plotter/``: holds the Plotter Editor code, which is very similar to the Algorithm Editor.
* ``plotterparameter/``: holds the Plotterparameter code.
* ``toolchain/``: holds the Toolchain Editor code, which is by far the most complex module. The "Graphical Editor" files and the "ToolchainConnection" and "ToolchainBlock" hold most of the code concerned with actual SVG drawing/interaction, while the other files hold the processing code and methods to connect the Graphical Editor to the data.
Generic components, such as the components for the list views, navigation (using `react-router v4 <>`_, or common sub-components are just stored in ``components/``.
``helpers/`` holds code used in many different places or generic utility code. The ``helpers/schema/`` subfolder holds the code & schemas for validating BEAT objects via `JSON schema validation <>`_ (BEAT uses Draft-04). There's a schema for each entity type.
To talk to the ``beat.editor`` REST server, one would use the contents in the ``api`` helper file. For BEAT-wide helpers, see the ``beat`` helper.
``store/`` holds all the code for the Redux store, including the reducers, actions, and selectors. We use `reselect <>`_ to write memoized composable selectors, in ``selectors.js``.
How does the webapp operate on the local BEAT prefix? Through the small Python REST API server provided in ``beat/editor/`` in this project. This is a bare-bones REST API server using `Flask <>`_ that exposes the following API on ``localhost:5000``:
* ``/`` or ``/index.html``: Serves the production/distributable version of the webapp.
* ``<plural BEAT entity name>/``: For each type of BEAT object, there is an endpoint for it. This endpoint is the pluralized version of the type - to operate on databases, use ``/databases``, to operate on libraries, use ``/libraries``, etc. Each endpoint accepts the following HTTP verbs:
- ``GET``: GET requests fetch all the objects of the given type from the prefix.
- ``POST``: POST requests create an object given the ``obj`` field, the object to create, and the ``copiedObjName`` field, which is an optional field to specify the object being copied.
- ``PUT``: PUT requests update objects, overwriting the objects in the prefix with the given objects (matched by name).
- ``DELETE``: DELETE requests delete objects from the prefix.
* ``settings/``: Only accepts GET requests - fetches settings (not currently being used).
* ``environments/``: Only accepts GET requests - fetches the docker environments (can be slow because ``beat.core`` needs to query every docker container).
* ``layout/``: Only accepts POST requests - given the toolchain as the request body, generates a layout for the toolchain using Graphviz's ``dot`` layout algorithm and returns it.
.. automodule:: beat.editor
Editor Breakdowns
There is an editor for every BEAT object:
* Databases
* Libraries
* Dataformats
* Algorithms
* Toolchains
* Experiments
* Plotters
* Plotterparameters
Some of these editors are more complex than others - if you can't figure something out, look here!
.. note:: If the images are too small, right-click on the image in your browser and click `View Image` to see the image in another tab at full resolution!
Generic Editor Features
.. image:: ./img/editor_generic_breakdown.png
1. `Object Name`: The name of the object being edited.
2. `Validity Flag`: Whether the object as it is in your prefix has JSON metadata that is considered valid by the BEAT system.
3. `Path to object in filesystem`: The absolute path on your filesystem to the object's files.
4. `Editor tab`: The tab that displays the user-friendly editor for the specific object.
5. `JSON tab`: The tab that displays the object's raw JSON metadata (this is the metadata edited in the Editor tab).
6. `Save Changes button`: Saves all the changes you've made to the object to your prefix. Also has a small Validity flag indicating whether or not your unsaved changes are valid.
7. `Python file generation button`: Generates a Python file based off a template for the object's type. This button is only available when editing objects of types that have Python files associated with them.
8. `Description field`: A short description of the object.
Database Editor
.. image:: ./img/editor_database_breakdown.png
1. `Root Folder field`: The absolute path to the root folder for the data files for this database. This folder is used inside the BEAT system to provide the data files to the database Python code when indexing/executing the database views.
2. `Active Protocol`: Databases can have multiple protocols, but you only edit one at a time. The active protocol is shown, while the others are hidden. The active protocol in this image is "Main".
3. `Protocol Switcher`: A dropdown which lets you switch to other protocols.
4. `Protocol Delete & Clone buttons`: Buttons to delete and clone the active protocol.
5. `New Protocol Button`: Create (and switch to) a new protocol.
6. `Protocol Name field`: Change the protocol's name.
7. `Protocol Template field`: Change the protocol's template name.
8. `New Set button`: Add a new set to the protocol.
9. `Protocol Set`: A protocol has sets, each of which are shown in succession. The first set in this image is "training", the second is "testing".
10. `Set Delete & Clone buttons`: Buttons to delete or clone the set.
11. `Set Name field`: Field to change the set's name.
12. `Set Template field`: Field for changing the set's template name.
13. `Set View Name field`: Field for entering the name of the Python View class to use for this set.
14. `New Set Parameter button`: Creates a new parameter for the set, each of which having a name and a string value.
15. `New Set Output button`: Creates a new output for the set.
16. `Output Name field`: Field for changing the output's name.
17. `Output dataformat field`: Field for selecting the output's dataformat.
18. `Quick Jump menu`: An overview of the protocols and sets in your database. Clicking on a protocol name will switch you to that protocol, and clicking on a set will jump you to that set. You can also create protocols & sets using the corresponding buttons.
Dataformat Editor
.. image:: ./img/editor_dataformat_breakdown.png
1. `Fields`: Dataformats have fields, each with at least a name and a type (which could be any other dataformat, a dictionary, array, string, or number types).
2. `Field Name`: Change the field's (or subfield's) name.
3. `Field dataformat`: Select the field's type.
4. `Array dimensions`: Array-type (sub)fields have configurable dimensions, allowing for matrices and such.
5. `Array dimension restrictions`: You can restrict the lengths of a specific dimension. A value of "0" implies no restriction.
6. `Array field subtype`: Array fields have a subtype, which can be any valid type/dataformat.
7. `Dict field subfields`: Fields/subfields/array subtypes that are "dict" have subfields, allowing for arbitrarily complex dataformats.
8. `New Subfield button`: Each dict field can have any amount of subfields added to it.
9. `New Field button`: Dataformats can have any arbitrary amount of top-level fields.
Algorithm Editor
.. image:: ./img/editor_algorithm_breakdown.png
1. `Analyzer Flag`: Whether or not the algorithm is for analyzer blocks. If this flag is checked, a new algorithm tab, `Results`, will be available for adding & editing the result fields. These result fields are very similar to output fields in normal algorithm groups, but with restricted types. The algorithm shown in the image does not have this field checked, and so is not an analyzer algorithm.
2. `Splittable Flag`: Whether or not the algorithm is splittable (parallelizeable). Only available on non-analyzer algorithms.
3. `Endpoints tab`: The algorithm tab where the algorithm's groups & inputs & outputs are defined & edited.
4. `Parameters tab`: The algorithm tab where the algorithm's parameters are defined & edited.
5. `Libraries tab`: The algorithm tab where the algorithm's used BEAT libraries and their aliases are defined and edited.
6. `First Group`: All algorithms need at least one group, and the first group is the only group that can have outputs.
7. `Second Group`: All groups after the second group can only have inputs.
8. `Group Name field`: Field for changing the group's name.
9. `Input Name field`: Field changing the group's input's name.
10. `Input Dataformat field`: Field changing the group's input's dataformat.
11. `Output Name field`: Field changing the group's output's name.
12. `Output Dataformat field`: Field changing the group's output's dataformat.
13. `New Input button`: Adds a new input to the group.
14. `New Output button`: Adds a new output to the group.
Toolchain Editor
.. image:: ./img/editor_toolchain_breakdown.png
1. `Toolchain Graphical Editor`: Below the "Description" field in the Toolchain Editor in a window showing a custom editor made to graphically edit toolchains. This is a scrollable window, with blocks laid on the lined background.
2. `Menu Bar`: This is the menu bar for the graphical editor, with several buttons to help use this tool:
- Undo & Redo: Move backwards & forwards in editing history.
- Layout: Uses graphviz's dot layout algorithm to calculate a cleaner and more pleasing toolchain layout given the blocks and connection info.
- Zoom Out/In: Zooms out and in.
- Fit: Fits the toolchain to the Graphical Editor window.
- Pop Out/In: Expands the editor to almost fill your browser's tab, and shrinks it back down.
- See Help: Pops open a help modal that shows you how to do things in the Graphical Editor.
3. `Dataset blocks`: Dataset blocks only have outputs, and are typically on the lefthand side of the toolchain. Each dataset provides its own synchronization channel, which is a different random color. Each block with the same color as a dataset block is synchronized to that dataset block.
4. `Normal Blocks`: Normal blocks have inputs and outputs and are typically in the middle of the toolchain.
5. `Input Connectors`: These black rectangles are where connections are attached to.
6. `Output Connectors`: These block rectangles are where connections are started from - click and drag on the rectangle to start a connection from that output.
7. `Analyzer Blocks`: Analyzer blocks only have inputs and typically are at the right end of the toolchain. Only 1 Analyzer should be in a toolchain.
8. `Connections`: Connections go from a block's output to another block's input. Connections are colored according to the synchronization channel of the block it starts from.
9. `Background Canvas`: The background canvas, where blocks can be moved or created.
How to use the Graphical Editor:
* Everything in the editor can be right-clicked to open a contextual menu about it.
* Left-click blocks to open the Block Editor modal where you change the block's names, inputs, outputs, and synchronization channel. Left-clicking and dragging moves blocks.
* Right-click on the background canvas to create blocks, insert them from existing toolchains, or insert them based off of an algorithm or database protocol.
* Select and operate on multiple blocks by shift-clicking blocks or by click-dragging an area select box. When any blocks are selected, all connections will be hidden except for those connected to/from the selected blocks. Click anywhere on the background canvas to dismiss the selection.
Experiment Editor
.. image:: ./img/editor_experiment_breakdown.png
1. `Toolchain Viewer`: This is a stripped-down, read-only version of the the graphical toolchain editor. It lets you see the toolchain for the experiment. Clicking on the background canvas will jump you to the Global Settings section.
2. `Dataset Blocks`: Clicking a dataset block will jump you to that dataset block's settings for this experiment.
3. `Normal & Analyzer Blocks`: Clicking a normal or analyzer block will pop up the block's settings and jump you to those settings.
4. `Type Inference Toggle button`: When selecting an algorithm or dataset for a block, the experiment editor will filter results to be compatible with adjacent blocks' algorithms or datasets, if they have chosen any. If Type Inference is toggled off, the editor won't filter options based on types.
5. `Current Block`: The settings for the last clicked block are shown here. The name of the block is given, as well as the synchronized channel.
6. `Execution Defaults Toggle`: By default, all blocks are executed in the Global Environment. If you need to override the block's environment, first toggle this.
7. `Environment Name Selector`: If the "Execution Defaults Toggle" is using the global defaults, this is disabled. If not, it lets you choose a docker environment available on your system to execute the block in.
8. `Block Algorithm Selector`: This lets you select an algorithm for the block. Only algorithms with the same number of inputs and outputs as the block will be allowed. If Type Inference is enabled and adjacent blocks have algorithms/datasets selected, the options will be further filtered.
9. `Algorithm input/output name & type`: When you select an algorithm for a block, the Inputs & Outputs of the algorithm are shown (both the name and dataformat).
10. `Block input/output selector`: You must assign each input & output of the block to the correct input/output of the algorithm. The editor tries to assign them appropriately, but it's best to double-check.
11. `Protocol Selector`: As a shortcut for assigning datasets for your experiment, you may assign an entire protocol to all the dataset blocks at once, if any are available.
12. `Toolchain dataset info`: Each dataset block in the toolchain is listed here, giving its name and provided synchronization channel.
13. `Dataset Selector`: You need to assign a compatible set from a protocol from a database to each dataset block. The name format is "<Protocol>/<set> (<database>)".
14. `Global Environment Selector`: If you are using the docker executor, you may selector a docker environment to execute the experiment's blocks in.
.. automodule:: beat.editor
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment