Cross-platform Desktop Application to demonstrate basic HTM functionality to users using their own data files.
WARNING! UNDER HEAVY DEVELOPMENT.
Dual Commercial and AGPLv3 License. See LICENSE.txt and http://numenta.org/licenses/.
The app/
directory contains Cross-platform Desktop Application GUI code,
running Javascript/HTML/CSS/etc. on Node.js,
Electron, and
Google Chromium. It also contains non-GUI logic
to run and manage HTM Models on the model runner.
The py/
directory contains ModelRunner and supporting code
(Python / C++), which drives the main functionality of the app, which it is our
goal to demo to the user.
tree
output last updated Thu Apr 7 08:15:13 PDT 2016
:
./ # Git Repo Root
├── .babelrc # ES7 ES6 => JS transpiler global settings
├── .eslintrc # JS/ES lint settings
├── .pylintrc # Python lint settings
├── DEPENDENCIES.md # Module dependency overview file
├── LICENSE.txt # Dual: Commercial and AGPLv3
├── README.md # This file. A project overview.
├── app/ # Frontend+GUI that exposes NuPIC HTM models to User
│ ├── browser/ # JS+HTML+CSS as GUI in electron's Renderer Process
│ │ ├── actions/ # FLUX Fluxible Actions JS
│ │ ├── entry.js # Fluxible Web GUI App entry, compiles to bundle.js
│ │ ├── assets/ # Browser/GUI images, icons, and other assets
│ │ │ ├── bundle/ # Auto-generated WebPack output bundle target dir
│ │ │ ├── images/ # GUI imagery
│ │ │ └── styles/ # CSS for GUI (global-like styles, overrides, etc).
│ │ ├── components/ # FLUX React view components JSX
│ │ ├── index.html # App main startup browser window contents
│ │ ├── lib/ # Library code for the browser, extensions, plugins
│ │ └── stores/ # FLUX Fluxible Stores JS
│ ├── config/ # JS Config files, both auto-init with nconf, more.
│ ├── database/ # File-based database storage (levelup + leveldown)
│ │ └── schema/ # Database definition schemas in JSONSchema Draft-3
│ ├── main/ # JS for Electron's "Main Process", App init startup
│ │ ├── index.js # ES6 Electron App main entry, init GUI, run models
│ │ └── loader.js # Electron App entry loader for main.js ES5 => ES6
│ ├── node_modules/ # Where npm installs packages for distribution
│ ├── package.json # npm dependencies and config for distribution
│ └── samples/ # Sample .CSV data files to pre-load for user in GUI
├── build/ # Distribution assets, images, icons, etc.
├── coverage/ # JS Unit+Integration test coverage output (!git)
├── dist/ # Installers and disk images for distribution
├── docs/ # Output dir for generated JS docs (not in git)
├── esdoc.json # ESDoc configuration file
├── node_modules/ # Where npm installs packages for development
├── package.json # npm dependencies and config for development
├── py/ # ModelRunner and support Python/C++ code
│ └── README.md # Python Backend instructions
├── scripts/ # Building and cross-platform Portability scripts
├── tests/ # All tests, javascript, python, unit, integration
│ ├── data/ # Data tests, bad formats, etc.
│ ├── js/ # JS tests, config, unit and integration
│ └── py/ # Python tests, config, unit and integration
└── webpack.config.babel.js # JS build tooling config
See:
py/requirements.txt
The Machine Intelligence behind this app is a technology known as Hierarchical Temporal Memory (HTM). NuPIC is Numenta's open source HTM engine. NuPIC runs on streams of data, predicting future values, and detecting pattern anomalies.
See:
package.json
- Languages:
- ECMAScript 6 (Modern Javascript)
- via Babel
- Also a few ECMAScript 7 features.
- Some ECMAScript 5.1, the Web compile target.
- HTML5
- CSS3
- JSONSchema, Database definition
schemas in
JSONSchema Draft-3
.
- ECMAScript 6 (Modern Javascript)
- Framework: Electron
- Testing: Mocha
- Linting: eslint
The Frontend contains code to manage Models on the Backend. It also contains the Graphical User Interface that allows users to explore HTM Models on their own data.
The GUI for this application is web code. Javascript
, HTML
, and CSS
are
loaded into a browser. For Desktop, this browser is a bare-bones Chrome window
opened by the Electron framework. Electron also runs Node.js to connect with the
host Operating System, allowing for cross-platform native controls.
In the browser, we run a one-way Uni-directional data flow, an Architecture known as "Flux".
Below is an example of tracing of our way through GUI initialization, GUI first loop run, and GUI loop continuation:
- Electron loads
app/main.js
- .. which (or Browser directly) loads
app/browser/index.html
- .. which loads
app/browser/app.js
- .. which inits Fluxible
- .. and then Fluxible fires off an initial Action
- .. which dispatches Events with state data to Stores
- .. which then integrate state data into themselves
- .. and then View Components tied to updated Stores render
- .. and then The User interacts with the app firing off a new Action
- .. GOTO #6, RINSE and REPEAT.
- ECMAScript Styleguide:
npm run lint
, Rules:.eslintrc
- HTML5 and JSX @TODO
- CSS3 @TODO
IMPORTANT: These setup instructions are only about if you care about running
the full app with all its components (Electron app with packaged model
runner). If you care about the python only - for example - then change to
unicorn/py
and follow the README instructions there.
Example of setting up development environment on Mac OS/X:
brew install git node chromedriver
git clone https://github.com/numenta/numenta-apps
cd numenta-apps/unicorn
python py/setup.py install
npm install
To install without the lengthy python bundle, assuming the desired python bundle is already installed:
npm install --no-optional
Execute the following command after making changes to unicorn_backend
code:
npm run install:backend
IMPORTANT: run this if you updated the python code in py/unicorn_backend
and you
want these changes to take effect in the portable python distribution run
by the electron app.
npm run dev
# see pretty logs
npm run dev | `npm bin`/bunyan
# same thing, but explicit
NODE_ENV=development npm run dev
Frontend code documentation can be generated and viewed by following the directions below. Comments are in JSDoc format, with output generated by ESDoc.
npm run docs # generate and open documentation
We use electron-builder to build and package the application for distribution. The authors of electron-builder
strongly recommend to use two package.json
files.
-
For development In the root of the project. Here you declare dependencies for your development environment, tests and build scripts.
-
For your application In the app directory. Only this directory is distributed with real application.
Here are the npm
scripts available via npm run <script-name>
. Please see
package.json
for more info.
build:osx
: Run all steps required to build the application (OSX)build:win
: Run all steps required to build the application (Windows)clean
: Clean all build an runtime artifactsclean:backend
: Deletepython
backend packagesclean:dist
: Delete all build artifactsclean:osx
: Delete build artifacts (OSX)clean:win
: Delete build artifacts (Windows)clean:db:osx
: Delete database files (OSX)clean:docs
: Delete documentationclean:npm
: Deletenpm
installed packagesclean:portable_python:osx
: Delete cachedportable_python
package (OSX)clean:portable_python:win
: Delete cachedportable_python
package (Windows)clean:python
: Deletepython
build artifactsclean:webpack
: Clean compiled/packaged JS code
dev
: Launch Desktop applicationdev:debug
: Launch in debug mode. See Electron Documentation for instructions on how to use the debuggerdev:inspect
: Launchnode-inspector
used to debug Electron application. See Electron Documentation for detailed instructions on how to use the debuggerdocs
: Build documentation (esdoc)dist:osx
: Build Mac OSX distribution artifactsdist:win
: Build Windows distribution artifactselectron
: Launch Electronelectron:debug
: Launch Electron in debug mode. See Electron Documentation for instructions on how to use the debuggerelectron:packager
: Build installable packagesesfmt
: Format JS code (esformatter)lint
: Lint JS code (eslint)pack:osx
: Package the electron app as a Mac OSX Applicationpack:win
: Package the electron app as a Windows Applicationprepare
: Prepare code for packagingtest
: Run all JS tests using developer options. See mocha.optstest:integration
: Run all JS integration teststest:unit
: Run all JS unit teststest:functional
: Run all JS functional tests
test:pipeline
: Run all JS tests using pipeline options. See mocha.optstest:pipeline:integration
: Run all JS integration teststest:pipeline:unit
: Run all JS unit tests
test:coverage
: Run test coverage on all JS unit+integration tests, and open reports when done in browser.
- Maybe the DB stored bad data?
npm run clean:db:osx
. - Sometimes
node_modules/
directory can become corrupted, try cleaning and reinstalling (slow):npm run clean ; npm install
. - Local Git repo can get stuck with out-of-date JS somehow, so back up your current repo, and try again on a fresh repo clone.
- Do not upgrade the following node/npm packages without syncing with the
rest of the team first. The Mac build box is dependent on these versions,
and must be upgraded in parallel:
node
,npm
,electron-packager
,electron-prebuilt
- Make sure to update packages often, especially after pulling an update into
your branch:
npm oudated -depth 0
pip list --outdated
- Lint your code before creating pull requests:
npm run lint
- Manual access to LevelDB file database from
Lev command-line tool (Mac OS/X):
`npm bin`/lev $HOME/Library/Application\ Support/unicorn/database/
- Remember, this is cross-platform. We need to support all main operating
systems. Windows has no environment variables, etc. Paths should not be
defined manually, but use the
path
library helper instead.
Write Unit and Integration tests using mocha test framework.
Write Functional or e2e tests using selenium and webdriverio test automation frameworks.
npm run test # all
npm run test:unit # unit tests only
npm run test:integration # integration tests only
npm run test:functional # functional tests only
To run the (python) backend integration tests with the portable python distribution run:
npm run test:integration:backend
Optional: you might want to run a
npm run clean && npm install
before running the test to make you have an up-to-date portable python distribution.
This will make sure (among other things) that the model_runner and param_finder are giving results that are compatible with the NAB ones. That is to say:
- Make sure that the new system (param_finder + model_runner) detects the same set of anomalies as NAB.
- It is ok for the new system to detect anomalies earlier than the NAB results.
- It is not OK for the new system to have significantly more false positives than the NAB detections.
To generate reults appropriate for the pipeline mocha
needs to run
with a different set of options
(see mocha.pipeline.opts).
npm run test:pipeline # pipeline all
npm run test:pipeline:unit # pipeline unit tests only
npm run test:pipeline:integration # pipeline integration tests only
Use the following to generate JS Unit and Integration test code coverage
results, build the reports, and open them in browser for display. Output
data is in the untracked ./coverage/
directory.
npm run test:coverage # run code coverage on js unit+int tests
Problem:
Uncaught AssertionError: Fatal Python error: PyThreadState_Get: no current thread
Solution:
unset PYTHONPATH
Build the electron app with:
npm run build:osx
# same thing, but explicit
NODE_ENV=production npm run build:osx
The resulting artifacts can be found in dist/
npm run build:win
# same thing, but explicit
NODE_ENV=production npm run build:win
The resulting artifacts can be found in dist/
- You need a certificate type of “Developer ID Application” from Apple. This
certificate usually has a common name in the form of
Developer ID Application: YourCompany, Inc. (ABCDEFGHIJK)
. - Set the environment variable
CSC_NAME
and sign the app:export CSC_NAME="Developer ID Application: Numenta, Inc. (ABCDEFGHIJK)"
- Now when you package with
npm run build:osx
, the app will be signed. - See electron-builder#code-signing for more info.
- Set the environment variable
GA_TRACKING_ID
with Google Analytics tracking ID. See https://analytics.google.com/analytics for correct ID. It should be something like this:
export GA_TRACKING_ID="UA-XXXXXXXX-X"
- Currently, the instructions to release an Electron app on the app store can be found here: http://www.saschawise.com/blog/2015/08/12/electron-for-the-mac-app-store.html
npm run dev:debug # open http://localhost:5858 in browser
- @TODO Python, NuPIC, Models, debugging etc.
- Electron debugging switches
- Chrome switches supported in Electron
- Manual access to LevelDB file database from
Lev command-line tool (Mac OS/X):
`npm bin`/lev $HOME/Library/Application\ Support/unicorn/database/
Warning: React Chrome DevTools does not yet work with Electron.
- Create a branch called "htm-studio-vX" where X is the version number
- Update
app/package.json
with new version number - The convention for version numbers is semantic versioning
- For example, we have a branch called
htm-studio-v0.0.1
HTM Studio uses Electron built-in support for automatic updates based on Squirrel.Mac and Squirrel.Windows. For more information see http://electron.atom.io/docs/api/auto-updater/
- Create update package using
npm run build:osx
- Upload update package
dist/HTM Studio-darwin-x64/HTM Studio-version-mac.zip
to update site.
The update site URL is composed of the update URL specified in
app/config/default.json
underupdate:url
key and the platform name. For example, if the update URL points to http://public.numenta.com/updates/htmstudio then the darwin version should be uploaded to http://public.numenta.com/updates/htmstudio/darwin.
- Upload manifest to update site. The update manifest should be named after the old version describing the new version. For example, if updating from version
0.0.1
to version0.0.2
then the update manifest should be namedupdate.0.0.1.json
and point toHTM Studio-0.0.2-mac.zip
. For more information on theupdate.version.json
format see https://github.com/Squirrel/Squirrel.Mac#update-json-format.
Sample manifest file:
- update.0.0.2.json
{
"url": "http://public.numenta.com/updates/htmstudio/darwin/HTM%20Studio-0.0.3-mac.zip",
"name": "0.0.3",
"notes": "* Automatic Updates \n* Improved Charts \n* Fix timezone when exporting results",
"pub_date": "2016-02-02T21:51:58Z"
}
These variables can be used to format the update dialog shown to the user once a new update is available. See app/config/default.json
under update:message
and update:detail
.
Here is a sample message formatting:
```javascript
"update": {
"message": "A new version of HTM Studio (%name) is available",
"detail": "What's new in version %name:\n%notes",
...
}
```