Giter Site home page Giter Site logo

clinical-genomics / scout Goto Github PK

View Code? Open in Web Editor NEW
147.0 15.0 43.0 89.67 MB

VCF visualization interface

Home Page: https://clinical-genomics.github.io/scout

License: BSD 3-Clause "New" or "Revised" License

CSS 0.21% Python 37.59% HTML 61.61% JavaScript 0.55% Dockerfile 0.02% Makefile 0.01%

scout's Introduction

Analyze VCFs and collaborate on solving rare diseases quicker

Build Status - GitHub PyPI Version GitHub Release Date GitHub commits latest GitHub commit rate GitHub commits GitHub issues-closed Average time to resolve an issue Percentage of issues still open Coverage Status CodeFactor Code style: black Woke

What is Scout?

  • Simple - Analyze variants in a simple to use web interface.
  • Aggregation - Combine results from multiple analyses and VCFs into a centralized database.
  • Collaboration - Write comments and share cases between users and institutes.

Documentation

This README only gives a brief overview of Scout, for a more complete reference, please check out our docs: https://clinical-genomics.github.io/scout .

Runnable demo image - does not require installing of software and database

A simple demo instance of Scout requires the installation of Docker and can be launched either by using the command: docker-compose up -d or make up.

The repository includes a Makefile with common shortcuts to simplify setting up and working with Scout. To see a full list and description of these shortcuts run: make help.

This demo is consisting of 3 containers:

  • a MongoDB instance, on the default port 27017 in the container, mapped to host port 27013
  • scout-cli --> the Scout command line, connected to the database. Populates the database with demo data
  • scout-web --> the Scout web app, that serves the app on localhost, port 8000.

Once the server has started you and open the app in the web browser at the following address: http://localhost:8000/

The command to stop the demo are either docker-compose down or make down.

Instructions on how to run a Scout image connected to your local database or a custom database are present on this page.

Installation

git clone https://github.com/Clinical-Genomics/scout
cd scout
pip install --editable .

Scout PDF reports are created using Flask-WeasyPrint. This library requires external dependencies which need be installed separately (namely Cairo and Pango). See platform-specific instructions for Linux, macOS and Windows available on the WeasyPrint installation pages.

NB: in order to convert HTML reports into PDF reports, we have recently switched from the WeasyPrint lib to python-pdfkit. For this reason, when upgrading to a Scout version >4.47, you need to install an additional wkhtmltopdf system library.

You also need to have an instance of MongoDB running. I've found that it's easiest to do using the official Docker image:

docker run --name mongo -p 27017:27017 mongo

Usage

Demo - requires pip-installing the app in a container and a running instance of mongodb

Once installed, you can setup Scout by running a few commands using the included command line interface. Given you have a MongoDB server listening on the default port (27017), this is how you would setup a fully working Scout demo:

scout setup demo

This will setup an instance of scout with a database called scout-demo. Now run

scout --demo serve

And play around with the interface. A user has been created with email [email protected] so use that address to get access

Initialize scout

To initialize a working instance with all genes, diseases etc run

scout setup database

for more info, run scout --help

The previous command initializes the database with a curated collection of gene definitions with links to OMIM along with HPO phenotype terms. Now we will load some example data. Scout expects the analysis to be accomplished using various gene panels so let's load one and then our first analysis case:

scout load panel scout/demo/panel_1.txt
scout load case scout/demo/643594.config.yaml

Integration with chanjo and chanjo2 for coverage report visualization

Scout may be configured to visualize coverage reports produced by Chanjo or chanjo2. Instructions on how to enable this feature can be found in the document chanjo_coverage_integration.

Integration with loqusdb for integrating local variant frequencies

Scout may be configured to visualize local variant frequencies monitored by Loqusdb. Instructions on how to enable this feature can be found in the document loqusdb integration.

Integration with Gens for displaying copy number profiles for variants

Scout may be configured to link to a local Gens installation. Instructions on how to enable this feature can be found in the document Gens integration.

Server setup

Scout needs a server config to know which databases to connect to etc. Depending on which information you provide you activate different parts of the interface automatically, including user authentication, coverage, and local observations.

This is an example of the config file:

# scoutconfig.py

# list of email addresses to send errors to in production
ADMINS = ['[email protected]']

MONGO_HOST = 'localhost'
MONGO_PORT = 27017
MONGO_DBNAME = 'scout'
MONGO_USERNAME = 'testUser'
MONGO_PASSWORD = 'testPass'

# enable user authentication using Google OAuth 2.0
GOOGLE = dict(
   client_id="client_id_string.apps.googleusercontent.com",
   client_secret="client_secret_string",
   discovery_url="https://accounts.google.com/.well-known/openid-configuration"
)

# enable Phenomizer gene predictions from phenotype terms
PHENOMIZER_USERNAME = '???'
PHENOMIZER_PASSWORD = '???'

# enable Chanjo coverage integration
SQLALCHEMY_DATABASE_URI = '???'
REPORT_LANGUAGE = 'en'  # or 'sv'

# other interesting settings
SQLALCHEMY_TRACK_MODIFICATIONS = False  # this is essential in production
TEMPLATES_AUTO_RELOAD = False  			# consider turning off in production
SECRET_KEY = 'secret key'               # override in production!

Most of the config settings are optional. A minimal config would consist of SECRET_KEY and MONGO_DBNAME.

Starting the server in now really easy, for the demo and local development we will use the CLI:

scout --flask-config config.py serve

Scout Interface demo

Hosting a production server

When running the server in production you will likely want to use a proper Python server solution such as Gunicorn. This is also how we can multiprocess the server and use encrypted HTTPS connections.

SCOUT_CONFIG=./config.py gunicorn --workers 4 --bind 0.0.0.0:8080 scout.server.auto:app

For added security and flexibility, we recommend a reverse proxy solution like NGINX.

Setting up a user login system

Scout currently supports 3 mutually exclusive types of login:

  • Google authentication via OpenID Connect (OAuth 2.0)
  • LDAP authentication
  • Simple authentication using userid and password

The first 2 solutions are both suitable for a production server. A description on how to set up an advanced login system is available in the admin guide

Integration with Matchmaker Exchange

Starting from release 4.4, Scout offers integration for patient data sharing via Matchmaker Exchange. General info about Matchmaker and patient matching could be found in this paper. For a technical guideline of our implementation of Matchmaker Exchange at Clinical Genomics and its integration with Scout check scouts matchmaker docs. A user-oriented guide describing how to share case and variant data to Matchmaker using Scout can be found here.

Development

To keep the code base consistent, formatting with Black is always applied as part of the PR submission process via GitHub Actions. While not strictly required, to avoid confusion, it is suggested that developers apply Black locally. Black defaults to 88 characters per line, we use 100.

To format all the files in the project run:

black --line-length 100 .

We recommend using Black with pre-commit. In .pre-commit-config.yaml you can find the pre-commit configuration. To enable this configuration run:

pre-commit install

Test

To run unit tests:

pytest

Contributing to Scout

If you want to contribute and make Scout better, you help is very appreciated! Bug reports or feature requests are really helpful and can be submitted via github issues. Feel free to open a pull request to add a new functionality or fixing a bug, we welcome any help, regardless of the amount of code provided or your skills as a programmer. More info on how to contribute to the project and a description of the Scout branching workflow can be found in CONTRIBUTING.

scout's People

Contributors

adrosenbaum avatar alkc avatar barrystokman avatar bjhall avatar dcrosta avatar dnil avatar elevu avatar fc-io avatar fevac avatar hassanfa avatar henrikstranneheim avatar ingkebil avatar ivadym avatar jakob37 avatar jessicahillert avatar lint-action avatar maehler avatar matsdahlberg avatar mayabrandi avatar mhkc avatar mikaell avatar moedarrah avatar moonso avatar northwestwitch avatar patrikgrenfeldt avatar pbiology avatar raysloks avatar robinandeer avatar teresebo avatar viktorhy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scout's Issues

Markdown service

When editing markdown on GitHub, the string is sent back to the server to be converted to HTML. The JSON package is then inserted into the page without a page reload. This seems like a very nice solution to editing markdown in the synopsis e.g.

  • Flask route to convert Markdown to HTML
  • Vue component to interface with new Flask route

Make backend API more strict

I need to go over my code and remove any direct references to the ODM. I also think we should discuss if code like this:

  @property
  def local_requency(self):
    """Returns a float with the local freauency for this position."""
    return (Variant.objects(variant_id=self.variant_id).count /
              Case.objects.count())

really belongs as a method in the ODM or fit better as a function call to the backend API?

Setup React (frontend framework)

Polymer wasn't stable enough to continue with. It also didn't work well in browsers other than Chrome.

The most similar yet more mature alternative is React. It's a UI framework built by Facebook that many people are already in production. It has a focus on building separate components which I think fit in very well with the idea of incrementally adding interactive region of pages.

This also means that styles needs to be looked over. Material design will still be a prevalent in driving the look and feel of the site. However, one promising project material-ui is unfortunately using Less and not SCSS. Another project with a similar goal react-material is using pure CSS to provide default styles for elements inline with JS which is an interesting approach but will add mental overhead when just learning React.

All in all, styles should be expected to take a few steps back until we are back on track again. The MVP might not need to look super polished.

Comments and activity

Many events should be logged on a case-by-case level generated by user actions.

  • Case comments
  • Variant comments
  • Case activity feed (variants + case activity)
  • Open research list
  • Solving a case
  • Assigning a user to a case

Get inheritance model from OMIM

OMIM has a pretty decent free API.

To get the inheritance model for a disorder - do:

http://api.omim.org/api/clinicalSynopsis?mimNumber=600334&include=clinicalSynopsis&apiKey=<REDACTED>&format=json
{"omim": { 
"version": "1.0",
"clinicalSynopsisList": [ 
{"clinicalSynopsis": { 
"mimNumber": 600334, 
"prefix": "#", 
"preferredTitle": "TIBIAL MUSCULAR DYSTROPHY, TARDIVE", 
"inheritance": "Autosomal dominant {SNOMEDCT:263681008} {UMLS:C0443147} {HPO HP:0000006 UMLS:C0443147}", 
"muscleSoftTissue": "Weakness of the muscles in the anterior compartment of the lower leg (particularly the tibialis anterior muscle) {UMLS:C1838245};\nAtrophy of the muscles in the anterior compartment of the lower leg {UMLS:C1838246};\n'Steppage' gait {SNOMEDCT:27253007} {UMLS:C0427149};\nReduced ankle dorsiflexion {UMLS:C1838247};\nReplacement of affected muscle tissue with fatty tissue {UMLS:C1838248};\nBiopsy shows rimmed vacuoles, central nuclei, and variation in fiber size {UMLS:C1838249};\nEMG shows myopathy {UMLS:C1842166};\nCardiomyopathy is not a feature {UMLS:C1838250}", 
"miscellaneous": "Adult onset (after age 35 years) {UMLS:C1838251} {HPO HP:0003581};\nSlow progression without marked disability {UMLS:C1838252};\nIncomplete penetrance {UMLS:C1836598} {HPO HP:0003829};\nAllelic disorder to a form of dilated cardiomyopathy (CMD1G, {604145})", 
"molecularBasis": "Caused by mutation in the titin gene (TTN, {188840.0004})"
} 
} ] 
} }

Perhaps we can write a simple Python API if we are going to get more information from there.

Problems with multi allelic calls

We should really think this one through. If we allow multiallelic variants it will be hard and ineffective to do searches in the database.
Imagine for example if we have apply a filter from the frontend where we remove all variants with a allele frequency > 0.01, how should we then filter a variant that have [0.05, 0.0001]? Same with caddscores, rank scores and many other things.
The indexes will also be inneffective when the values are arrays instead of scalars...

Roadmap

Just rough without deadlines.

How to represent missing data in database

How to handle missing data, for example if the variant is not present in a frequency database or if it is in a intergenic region. Should it be represented with None to show that we have actually looked for the entry?

I think it would be more easy to validate the analysis if we use default values for everything we searched for in the vcf.

Scout depends on ped-parser==1.2.4

As I'm writing the automation script for loading data into Scout I notice that it seems like load_mongo_db indirectly makes a call to:

for case in case_parser.to_json():

... but this fails since the to_json method in the current release of ped-parser requires an argument outfile. I've downgraded ped-parser in the mean time.

Go to next/prev variant

Wouldn't it be nice to be able to walk through variants one at a time without returning to the variants list?

This functionality needs to be implemented in the frontend, server, and apater I think.

Base class backend adapter

Write a base class that defines the interface with a backend; VCF, Mongo etc.

Write it as a Flask extension with init_app etc.

Software overview

It would be great to have an up-to-date overview of the project and the server. Perhaps a mindmap would work.

img_20141014_092814

Edit: This should also an effort to kickstart the Documentation so that it's setup in a way that enables quick iteration. The base structure should be in place for the MVP.

Variant JSON best practises

This is what I would like to see when it comes to a variant entry delivered to the Scout server interface.

[
    {
        "_id": "54325acbec3a4838edbecacf",
        "md5_key": "72925ed9255accf0a8bf144550a0ecc4",

        "chromosome": "5",
        "position": 177035488,
        "ref": "GCCC",
        "alt": "[G]",
        "rs_number" : 142034531,

        "common": {         
            "gene_ids": [{
                "ensembl": "ENSG00000027847",
                "hgnc_symbol": "B4GALT7"
            }],

            "set": "Intersection"
        }
    }
]

Edit: this is a work in progress - I will update this comment as we discuss what the structure should look like.

Edit 2: Changed intention to exclude how data is stored in Mongo.

Writing INI files

Hi @moonso!

I'm trying to create Scout config files on the fly. I can't seem to find a simple way to convert a dict to a ConfigParser object - do you know of any way?

Documentation

One of the most important points of the project will be to continually document new parts added to the project. It should be a hard requirement that anything new added to the repo also much touch the documentation in some way.

In the end we should also start thinking about some way to compose a usage manual that could be distributed to users.

Reading material:
http://jacobian.org/writing/great-documentation/
http://docs.writethedocs.org/#contents

Engine
I've had some time to think and read about how others write documentation.

RST isn't the perfect markup language (although powerful). I think that if I could write in Markdown it would lower the barrier to just get started.

This is where MkDocs comes in. It's much simpler to use than Sphinx and uses more a more modern workflow that makes docs development more painless. It can't read docstring and autogenerate API docs but this might not be something super useful anyways (yes, I know what I said before 😅)

You can watch a short intro here and read the docs.

I haven't researched the alternatives quite yet but I think we should look at Pelican before commiting.

Reloading data

Right now when I just rerun the load script for Scout, e.g. the case information will not be updated even if it's changed on the file system.

We need a clear path to reloading a case. Both taking into consideration possible new data as well as persisting comments and events and any other more temporary data.

Does the wipe script already offer this functionality?

Setup Vagrantfile + provisioning

To work effectively as a team we need some way to synchronise our development setups. Vagrant seems like the perfect tool to accomplish this. It's also nice for people that would like to try out the project to be able to install all dependencies like MongoDB without messing with their local environment.

We will setup a Vagrantfile with Ansible provisioning to get all collaborators up and going quickly.

Write a Vagrantfile that will setup a Ubuntu-box from scratch and install all dependencies. Preferably use Ansible as provisioner.

This will benefit everybody related to the project as well as the project itself.

Gene description from VCF

@henrikstranneheim wants to put gene description into the variant detail page. I can't find it in the ODM - what's the status?

Add the vcf annotation “Gene_description” to the variant page where appropriate in layout.

Frontend assets and compilation

Flask can compile assets using Flask-Assets but not much else. The plan is therefore to integrate Node.js based solutions for added features like live reloading, CSS injection etc.

The solution needs to be able to compile at least SCSS and CoffeeScript. It needs to enable live reloading features including CSS injection.

The initial plan is to rely on Gulp and BrowserSync.

Study the SCSS structure of Foundation for Apps:
https://github.com/zurb/foundation-apps/tree/master/scss/components

Plan for a "third-party" API to Scout

We should probably (during the next refactor) this about how to expose an API to Scout for other services to import. It would be good if we could use the same API internally as well. Mainly to extract data from the database I guess.

This will be in addition to the CLI "scouttools" but I think we should keep it Python native and perhaps just use it in the CLI interface.

Related to: Clinical-Genomics/pymip#2

Sanger email format

Generally how should it look, what should it include?

  • What do the clinicians want to display in the old "protein change" list?

How to handle config files?

Since the config file is central to all parts of scout i think we should store them in a folder directly in the base of the scout package named configs.
Here we can have some different versions, from a minimal all the way up to the the one used for fully annotated vcf:s.
I make one example on my feature and see what you think.

Update summary box

  • Change label "Matches expected inheritance model" to "Matches OMIM inheritance model"

Landing page

The default view that all users who aren't logged in will arrive at. This page is also known as a "splash page". It's main purpose is to introduce potentially new users to the website. It's important that it provides a clear call to action, commonly with a big button for signing in/up.

  • Tagline
  • Logo
  • 2-3 sentence summary
  • 4 key features that sets Scout apart
  • Call to action (sign up/in, read documentation, tour, video, contact us)
  • Link to about page or how is behind the project (logos)

Basic Flask structure

We need to make up out own conventions about how to structure the Flask server. What extensions to use, how to structure the folders, etc.

A core goal should be to decouple at least each blueprint as much as possible. Always think in terms of APIs. Janking out a Blueprint shouldn't mess up to much of the rest of the app.

To get a rough idea I will model the conventions after however GitHub has solved the problems (like routes) but implemented in Flask.

Frontend framework

I think we will eventually need some kind of abstraction layer for frontend JS stuff. What this layer is I don't know but I have a preference for something that allows us to write separate components that allow part of the page to be interactive and others that are static.

From this there are two main contenders; Polymer and React. They are both similar in their approach to web development but have some individual pros and cons.

Polymer
By Google. Likely the future of web development. Standards are being implemented but today only Chrome has native support. No support at all for semi-old browsers > 2 generations ago. Even in current browsers the support isn't complete.

However, when the stuff works it has additional features that no other framework can compete with like Shadow DOM, intuitive HTML imports, and material design elements. This is the project I would pick to work with if I didn't have to worry about compatibility outside Chrome.

One things to note is also the lack of development tools available. Gulp and Grunt plugins are pretty rare and the workflow isn't very mature - no one knows what the best way to work on web component is. This can make it a problem especially when integrating with SCSS and CoffeScript etc.

React
By Facebook. Mature project in use in large projects today. Seems very well architected and does support the idea of making parts of a page interactive. I also read that it's possible to render components on the server side initially to avoid long startup times.

React is less intuitive than Polymer. They impose some best practises that can be hard to wrap your head around like synthetic events and virtual DOM. However, in the end frameworks like Ember are adopting ideas from React as best practises.

The plugin ecosystem is also in favor of React.

Where React can't compete with Polymer is with the nice layout attributes (not a deal breaker) and encapsulated styles. In the end though, these are things 99.9% of web developers have to deal with already so it's not that we would be missing out on something just for choosing React.

React should be the default with Polymer as an option to consider if we can.

Allow to start scout without mongodb

We should allow the user to start scout without an existing mongodb.
In this way we could just start with a simple vcf-viewer with the same frontend.

Enable SSL

To run the app on clinical-db SSL must be enabled I think.

Search/filter cases

Page: cases.

The number of active cases will grow over time. At some point it will be necessary to filter (fuzzy match) cases.

Compare "Go to case": https://clinical-db.scilifelab.se:8081/#/cust002

To make this easy to use we need a client side approach. This is a good candidate case to see how easy it is to implement a custom Polymer component.

EDIT: clarified purpose.

Don't fail on missing madeline file

Hi @moonso,

will you have time to look into this or should I try to fix it?

IOError: [Errno 2] No such file or directory: u'/home/scout/new/analysis-data/14044/madeline_14044.xml'

Restricting access

Access to VCFs will be restricted based on "institutes". My idea would be to couple institutes to uploaded VCFs (or families). This way, we don't impose access restriction on the core product but only when you include the user management component.

Simple to load any VCF

New class that can load general VCF files and serve as a MongoDB backend API.

The focus is first to provide demo data for the MVP.

User management and login

Scout needs some way to manage users with different roles and belonging to different sub-projects.

It should be simple to author (CRUD) users. We therefore need an admin interface (Flask-Admin).

We need to loosely couple Users with Comments/Activity records and the login procedures.

load_mongo not working

Trying to load case 1 on clinical-db. Getting error related to ODM.

I already fixed and issue with calling "split" on a list:

-      ind['capture_kits'] = config_info.get('capture_kit', '').split(',')
+      ind['capture_kits'] = config_info.get('capture_kit', [])
[scout@clinical-db scout-new]$ vex scout-new scouttools load_mongo -u robin -p andeer -scout_config tests/for_clinical_db/1/scout_config_clinical.ini -vt clinical
Traceback (most recent call last):
  File "/home/scout/.virtualenvs/scout-new/bin/scouttools", line 8, in <module>
    execfile(__file__)
  File "/home/scout/scoutApp/scout-new/scripts/scouttools", line 66, in <module>
    scouttools()
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/click/core.py", line 610, in __call__
    return self.main(*args, **kwargs)
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/click/core.py", line 590, in main
    rv = self.invoke(ctx)
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/click/core.py", line 936, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/click/core.py", line 782, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/click/core.py", line 416, in invoke
    return callback(*args, **kwargs)
  File "/home/scout/scoutApp/scout-new/scout/commands/load_mongo.py", line 150, in load_mongo
    verbose=verbose
  File "/home/scout/scoutApp/scout-new/scout/ext/backend/load_mongo.py", line 229, in load_mongo_db
    if case not in institute.cases:
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/mongoengine/base/fields.py", line 208, in __get__
    name=self.name
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/mongoengine/dereference.py", line 65, in __call__
    self.object_map = self._fetch_objects(doc_type=doc_type)
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/mongoengine/dereference.py", line 131, in _fetch_objects
    doc = doc_type._from_son(ref)
  File "/home/scout/.virtualenvs/scout-new/lib/python2.7/site-packages/mongoengine/base/document.py", line 587, in _from_son
    raise InvalidDocumentError(msg)
mongoengine.errors.InvalidDocumentError: Invalid data to create a `Case` instance.
research_gene_lists - 'unicode' object has no attribute 'get'

Setup testing

Once the MVP is complete we should move to more proper development and keep testing and peer review in mind.

TravisCI is a continuous testing tools with GitHub integration. Coveralls is tied into Travis and calculated test coverage which is reported back to the repo as a comment on pull requests.

Display a list of samples (VCFs, families)

The core of Scout will be built around a VCF visualizer interface.

Initially this will be built to provide core functionality that will be extended later.

This component will always exists as part of the overall Scout project.

Q: Would it be weird to rename families to cases? No...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.