# Grapht Grapht is a server-side graphing library built on [PhantomJS](https://github.com/ariya/phantomjs/wiki) and utilizing [D3.js](http://d3js.org/). Grapht provides a CLI for simple Bash scripting. It also profides a light-weight [Ruby](https://www.ruby-lang.org/en/) API to make service-level integration simple. ### Why was Grapht built on PhantomJS? - PhantomJS allows us to leverage [D3.js](http://d3js.org/), a best-of-breed data visualization library authored by the formidable data visualization expert, Mike Bostock. [D3.js](http://d3js.org/) is a battlefield tested library. - Using PhantomJS allows us to reuse existing data visualization logic, originally authored for our client-side application. This means we get consistent visualizations across the various layers of our stack, and we minimize developer effort. ### How well does Grapht perform? While PhantomJS is able to run Javascript extremely fast, it has a slow startup time. When measured on a 2.4GHz Intel Core i7 laptop, with 16GB of DDR3 RAM, the benchmarks are as follows (_averaged over 10 runs_):
Bytes-In Average, Real Time ( Seconds )
1,323 1.559
13,527 1.675
135,252 1.715

time (sec.) / bytes

Note that even when incrementing the amount of data-in by an order of magnitude, time increases minimally (_roughly √n_). From this, we can infer a start-up time of ~1.5 seconds, for PhantomJS, on the aforementioned hardware. _All measurements were collected using the following command: `time -p bin/grapht bar-horizontal < data/bar_data.json > /dev/null`_ ## CLI ### Overview Grapht provides a CLI, accessed using the `bin/grapht` command. The basic invocation requires one argument specifying the desired graph type, and a JSON string provided via `STDIN`. For example, if we want a **horizontal bar graph**: bin/grapht bar-horizontal < ~/my-data.json The result will be a string of **svg** markup: 20 22 24 26 28 30 32 34 36 38 40 foo bar baz ### Usage bin/grapht GRAPH_TYPE [options] < JSON_INPUT ### Options Currently supported flags:
Flag Description Allowable Values
-f Specifies an output format for the generated graph. png|jpg|gif|pdf
## Ruby API To generate the same **horizontal bar graph** generated in the CLI section--using the Ruby API--we can do the following: json = "[{ \"name\": \"foo\", \"value\": 20 },{ \"name\": \"bar\", \"value\": 40 },{ \"name\": \"baz\", \"value\": 35 }]" type = Grapht::Type::BAR_HORIZONTAL graph = Grapht::Shell.exec type, json ## Supported Graphs Grapht is extensible, allowing users to create new graph definitions using Javascript and [D3.js](http://d3js.org). However, Grapht provides a handful of graph definitions out of the box: - Horizontal Bar Graph - Vertical Bar Graph - Line Graph - Pie Graph ### User Defined Graph Definitions Users may create their own graph definitions with Grapht. To do this, we first have to register a location where the new graph definitions will reside. This is done simply by setting the `EXT_GRAPHT_DEFINITIONS_HOME` environment variable. For example, if we have our custom definitions stored in `~/Development/my_project/my_graph_defs`, we set our environment variable to this path: export EXT_GRAPHT_DEFINITIONS_HOME=~/Development/my_project/my_graph_defs bin/grapht my-scatterplot < ~/my-data.json In the example above, we supply the name of our new graph definition (`my-scatterplot`) to the Grapht CLI. Grapht will first look in `EXT_GRAPHT_DEFINITIONS_HOME` for the file `my-scatterplot.js`. If it's not found, it will check its own internal set of graph definitions. If it is found, Grapht will load the new definition. ##### Creating Your First Graph Definition All graph definitions must comply with a short set of rules: - They must be wrapped within a function that takes a single data argument. - They must generate one, and only one root DOM node. Here's an example of a valid graph definition: function(data) { // <- our wrapper fuction var width = 200, height = 200; // our single root node added to document.body var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); // a bunch of D3 operations on svg... } ## Error Handling Grapht will raise an error in the following scenarios: - When any of its dependencies cannot be found. _Currently, Grapht depends upon the D3.js and JSON2 javascript libraries. These dependencies can be found in Grapht's `vendor` directory._ - When an unknown graph type is supplied to Grapht - When malformed JSON is supplied to Grapht - When PhantomJS raises an internal error When using Grapht's CLI, all errors are printed to `STDERR` and Grapht exits with an exit-code of `1`. When accessing Grapht's features through the Ruby API, all errors are presented as instances of `Grapht::Shell::Error`. The error messages, in this case, are consistent with the errors messages raised from the CLI. ## Rails Integration While Rails integration is not scripted by the Grapht library, it is quite simple to integrate. The following steps are all that is required for integration: - Add the following to your `Gemfile`:
gem 'grapht', git: 'https://github.com/ibpinc/grapht.git'
- In the Rails `app` directory, create a directory named `graph-definitions` - Create the file `config/initializers/grapht.rb`. In the file add the following:
ENV['EXT_GRAPHT_DEFINITIONS_HOME'] =
    Rails.root.join('app/graph-definitions')
- Place all user-defined graph definitions in the `app/graph-definitions` ## Contributing 1. Fork it (http://github.com/ibpinc/grapht/fork) 2. Create your feature branch `git checkout -b my-new-feature` 3. Commit your changes `git commit -am 'Add some feature'` 4. Push to the branch `git push origin my-new-feature` 5. Create a new pull request ## License Copyright (c) 2014 Trade Informatics, Inc [MIT License](https://github.com/ibpinc/grapht/blob/master/LICENSE.txt)