<commit_before># BuildingOS Charts

Plug-and-play chart components built on d3 and React.

Please pardon the sawdust, and wear a hard hat. We are iterating fiercely to get to 0.1.0, but we're not there just yet.

[![Circle CI](https://circleci.com/gh/luciddg/building-os-charts/tree/master.svg?style=svg&circle-token=06fe431268ac4c460eaf5fefe44b7ffe57888d1c)](https://circleci.com/gh/luciddg/building-os-charts/tree/master)

[BuildingOS](http://luciddesigngroup.com/buildingos) is an integrated building management platform made by [Lucid](http://luciddesigngroup.com). It has extensive analytical abilities and incorporates many different types of charts. These charts are open source so you can use them in your own projects. They are designed with data from the BuildingOS API in mind, but they can be used in any project.


## Browser Support

* Chrome 26
* Chrome 26 (Android)
* Firefox 10
* IE 9
* Safari 6
* Safari 6 (iOS)


## Installation

### CommonJS

In your project:

* First: `npm install --save building-os-charts`
* Then in your project, in the module where you want to instantiate a chart: `var Charts = require('building-os-charts');`

The next steps depend on what kind of chart you want. See the examples for practical help.

### Download

First, grab [the archive of everything](https://github.com/luciddg/building-os-charts/archive/master.zip) and `npm install`. Then:

* To see the examples: `npm run examples`
* To build: `npm run build`
* To test: `npm test`
* To run tests continuously: `npm run watch-tests`


## API Reference

### Timeseries Chart

The timeseries chart renders values over time. Its horizontal axis represents a period of time, and its vertical axis (or axes) represent numeric values belonging to that period. Values can be rendered  as lines, bars, plot points, and more.

This chart type does much of the visualization in [BuildingOS](http://luciddesigngroup.com/buildingos) and it is more complex than the other charts. It's not really difficult to work with; you just have to understand the hierarchical relationship of its elements.

* **Chart:** the root chart component contains any number of "groups".
* **Group:** a group contains any number of "series".
* **Series:** a series renders a single set of timeseries data.

So for example, let's say that I have a building with four electricity meters, and I want to visualize their consumption last week. Here is the hierarchical structure of the chart:

* **Chart:** the root chart component contains one group.
* **Group:** the group contains four series, one for each meter.
* **Series:** each series is responsible for rendering one meter's data.

In JS, that results in the following config, which we pass to the chart component:

```
var groups = [
	// One group:
	{
		// Four series, one for each meter:
		series: [
			{data: [...]},
			{data: [...]},
			{data: [...]},
			{data: [...]}
		]
	}
];

<TimeseriesChart groups={groups} />
```

Obviously, there's more to it than that. Groups and series consume props for labeling, styles, and other features. But this is the structure of a timeseries chart in its most rudimentary form.

One further note about groups. Why would you ever want more than one group? You use multiple groups when some series are conceptually distinct from others. For example, let's say I want to compare electricity consumption to outdoor temperature. In this case, it makes sense to use two groups. The first group contains electricity series that belong to the main vertical axis on the left. The second group contains temperature values that belong to the second vertical axis on the right. Each group gets its own vertical axis, which means that in this case you'll have kW on the left and degrees fahrenheit on the right. In fact, in BuildingOS a group usually contains a set of meters that have the same unit type -- kW, gallons, etc. -- but instead of tying axes to units, we use the generic group construct because it's more flexible. Finally, note that although you can have as many groups as you want, the chart will only render a maximum of two vertical axes. With more than two vertical axes, presentation becomes messy and convoluted.

Run the examples to see timeseries charts in action. Once you have a feel for how they work in practice, read on to learn about the properties you can pass to the root chart, its groups, and their series.

####Chart Properties

###### height : Number (optional)
The height of the chart, in pixels. If you don't pass a value, the chart will use the height of its parent container.

###### groups : Array
An array of group objects. Without groups, there is no chart. See the [Group Properties](#group-properties) reference.

###### gutters : Number || Object (optional)
A number or an object containing gutter values in pixels. Pass a number to set the same value for all four gutters. Pass an object with number attributes for top, right, bottom, and left to set different values for each gutter.

* The left and right values set the width of the left and right axes. Any value for the right gutter is ignored if the chart has only one group and there is consequently no second vertical axis on the right of the chart.
* The bottom value sets the height of the bottom axis.
* The top value sets the height of the legend.

If you don't pass a value, the chart will set all gutters equally at a proportion of the chart's total width.

###### width : Number (optional)
The width of the chart, in pixels. If you don't pass a value, the chart will use the width of its parent container.

####Group Properties

###### clampToZero : Boolean (optional)
If true, the group's vertical axis starts at 0. If false, the group's vertical axis starts at the lowest value present in this group. The default is true. It is useful to be able to set false in rare cases, such as that of temperature data, where typically you don't want to clamp its axis arbitrarily to zero, but rather show the range of observed values. Note that if a group's data contains negative values, this property will be ignored and the axis will start at the lowest negative value.

###### className : String (optional)
A string that will be added to the group element's `class` attribute.

###### dividers : Boolean (optional)
If true, the group will render horizontal dividers: one to separate the time axis from chart data content; one to separate the linear axis from chart data content; and another that corresponds to zero on the linear axis. The default is false.

###### gridlines : Boolean (optional)
If true, the group will render horizontal background gridlines. The default is false.

###### label : String (optional)
The label for this group's vertical axis.

###### series : Array
An array of series objects. Without series, the group has nothing to render. See the [Series Properties](#series-properties) reference.

###### style : Object (optional)
Arbitrary style properties to be applied to the group element. These will be applied inline by React. See [the React docs](https://facebook.github.io/react/tips/inline-styles.html) for how to format style properties.

###### type : String (required)
Specifies how the series in the group should render. Pass one of:

* area
* bar
* clusteredBar
* differenceBar
* line
* plot
* stackedBar

####Series Properties

###### className : String (optional)
A string that will be added to the group element's `class` attribute.

###### data : Array
An array of data objects. Without data, series has nothing to render. See the [Datum Properties](#datum-properties) reference.

###### interaction : String (optional)
A string that specifies the type of interaction that the user can have with the series. Pass one of:

* mouseover
* none

The default is 'mouseover', which means that the chart responds to user interaction.

###### marker : String (optional)
A string that specifies the animation type of a marker on a line or area series in response to user interaction. Pass one of:

* smooth
* snap

The default is 'snap', because 'smooth' is performance intensive and should be used only with caution.

###### stretch : Boolean (optional)
A boolean that specifies whether a data series should be stretched to artificially fill a given time period. The default is false. Lucid timeseries data is inclusive, so if you request one day of data, from midnight to midnight in fifteen-minute increments, the last reading will be at 11:45pm. This creates a rendering problem because the last 15 minutes will be blank on line and area series. Setting stretch to true tells the series to clone its last reading and push it to the end of the period so that lines and areas render edge-to-edge.

###### style : Object (optional)
Arbitrary style properties to be applied to the series element. See [the React docs](https://facebook.github.io/react/tips/inline-styles.html) for how to format style properties.

###### type : String (optional)
Specifies how the series should render. Pass one of:

* area
* bar
* clusteredBar
* differenceBar
* line
* plot
* stackedBar

You only need to use this property when different series in the same group should have different render types (eg. bars overlaid with a line). If all series should use the same render type, set type on the parent group and its child series will inherit.

####Datum Properties

###### className : String (optional)
A string that will be added to the element that renders this data item.

###### style : Object (optional)
Arbitrary style properties to be applied to the element that renders this data item. This is useful when, for example, you need to assign a unique color or opacity to an individual bar. See [the React docs](https://facebook.github.io/react/tips/inline-styles.html) for how to format style properties.

###### timestamp : Date
All timeseries data items must have both a timestamp and a value.

###### value : Number
All timeseries data items must have both a timestamp and a value.<commit_msg>:memo: Update README to reflect changes to datum.<commit_after># BuildingOS Charts

Plug-and-play chart components built on d3 and React.

Please pardon the sawdust, and wear a hard hat. We are iterating fiercely to get to 0.1.0, but we're not there just yet.

[![Circle CI](https://circleci.com/gh/luciddg/building-os-charts/tree/master.svg?style=svg&circle-token=06fe431268ac4c460eaf5fefe44b7ffe57888d1c)](https://circleci.com/gh/luciddg/building-os-charts/tree/master)

[BuildingOS](http://luciddesigngroup.com/buildingos) is an integrated building management platform made by [Lucid](http://luciddesigngroup.com). It has extensive analytical abilities and incorporates many different types of charts. These charts are open source so you can use them in your own projects. They are designed with data from the BuildingOS API in mind, but they can be used in any project.


## Browser Support

* Chrome 26
* Chrome 26 (Android)
* Firefox 10
* IE 9
* Safari 6
* Safari 6 (iOS)


## Installation

### CommonJS

In your project:

* First: `npm install --save building-os-charts`
* Then in your project, in the module where you want to instantiate a chart: `var Charts = require('building-os-charts');`

The next steps depend on what kind of chart you want. See the examples for practical help.

### Download

First, grab [the archive of everything](https://github.com/luciddg/building-os-charts/archive/master.zip) and `npm install`. Then:

* To see the examples: `npm run examples`
* To build: `npm run build`
* To test: `npm test`
* To run tests continuously: `npm run watch-tests`


## API Reference

### Timeseries Chart

The timeseries chart renders values over time. Its horizontal axis represents a period of time, and its vertical axis (or axes) represent numeric values belonging to that period. Values can be rendered  as lines, bars, plot points, and more.

This chart type does much of the visualization in [BuildingOS](http://luciddesigngroup.com/buildingos) and it is more complex than the other charts. It's not really difficult to work with; you just have to understand the hierarchical relationship of its elements.

* **Chart:** the root chart component contains any number of "groups".
* **Group:** a group contains any number of "series".
* **Series:** a series renders a single set of timeseries data.

So for example, let's say that I have a building with four electricity meters, and I want to visualize their consumption last week. Here is the hierarchical structure of the chart:

* **Chart:** the root chart component contains one group.
* **Group:** the group contains four series, one for each meter.
* **Series:** each series is responsible for rendering one meter's data.

In JS, that results in the following config, which we pass to the chart component:

```
var groups = [
	// One group:
	{
		// Four series, one for each meter:
		series: [
			{data: [...]},
			{data: [...]},
			{data: [...]},
			{data: [...]}
		]
	}
];

<TimeseriesChart groups={groups} />
```

Obviously, there's more to it than that. Groups and series consume props for labeling, styles, and other features. But this is the structure of a timeseries chart in its most rudimentary form.

One further note about groups. Why would you ever want more than one group? You use multiple groups when some series are conceptually distinct from others. For example, let's say I want to compare electricity consumption to outdoor temperature. In this case, it makes sense to use two groups. The first group contains electricity series that belong to the main vertical axis on the left. The second group contains temperature values that belong to the second vertical axis on the right. Each group gets its own vertical axis, which means that in this case you'll have kW on the left and degrees fahrenheit on the right. In fact, in BuildingOS a group usually contains a set of meters that have the same unit type -- kW, gallons, etc. -- but instead of tying axes to units, we use the generic group construct because it's more flexible. Finally, note that although you can have as many groups as you want, the chart will only render a maximum of two vertical axes. With more than two vertical axes, presentation becomes messy and convoluted.

Run the examples to see timeseries charts in action. Once you have a feel for how they work in practice, read on to learn about the properties you can pass to the root chart, its groups, and their series.

####Chart Properties

###### height : Number (optional)
The height of the chart, in pixels. If you don't pass a value, the chart will use the height of its parent container.

###### groups : Array
An array of group objects. Without groups, there is no chart. See the [Group Properties](#group-properties) reference.

###### gutters : Number || Object (optional)
A number or an object containing gutter values in pixels. Pass a number to set the same value for all four gutters. Pass an object with number attributes for top, right, bottom, and left to set different values for each gutter.

* The left and right values set the width of the left and right axes. Any value for the right gutter is ignored if the chart has only one group and there is consequently no second vertical axis on the right of the chart.
* The bottom value sets the height of the bottom axis.
* The top value sets the height of the legend.

If you don't pass a value, the chart will set all gutters equally at a proportion of the chart's total width.

###### width : Number (optional)
The width of the chart, in pixels. If you don't pass a value, the chart will use the width of its parent container.

####Group Properties

###### clampToZero : Boolean (optional)
If true, the group's vertical axis starts at 0. If false, the group's vertical axis starts at the lowest value present in this group. The default is true. It is useful to be able to set false in rare cases, such as that of temperature data, where typically you don't want to clamp its axis arbitrarily to zero, but rather show the range of observed values. Note that if a group's data contains negative values, this property will be ignored and the axis will start at the lowest negative value.

###### className : String (optional)
A string that will be added to the group element's `class` attribute.

###### dividers : Boolean (optional)
If true, the group will render horizontal dividers: one to separate the time axis from chart data content; one to separate the linear axis from chart data content; and another that corresponds to zero on the linear axis. The default is false.

###### gridlines : Boolean (optional)
If true, the group will render horizontal background gridlines. The default is false.

###### label : String (optional)
The label for this group's vertical axis.

###### series : Array
An array of series objects. Without series, the group has nothing to render. See the [Series Properties](#series-properties) reference.

###### style : Object (optional)
Arbitrary style properties to be applied to the group element. These will be applied inline by React. See [the React docs](https://facebook.github.io/react/tips/inline-styles.html) for how to format style properties.

###### type : String (required)
Specifies how the series in the group should render. Pass one of:

* area
* bar
* clusteredBar
* differenceBar
* line
* plot
* stackedBar

####Series Properties

###### className : String (optional)
A string that will be added to the group element's `class` attribute.

###### data : Array
An array of data objects. Without data, series has nothing to render. See the [Datum Properties](#datum-properties) reference.

###### interaction : String (optional)
A string that specifies the type of interaction that the user can have with the series. Pass one of:

* mouseover
* none

The default is 'mouseover', which means that the chart responds to user interaction.

###### marker : String (optional)
A string that specifies the animation type of a marker on a line or area series in response to user interaction. Pass one of:

* smooth
* snap

The default is 'snap', because 'smooth' is performance intensive and should be used only with caution.

###### stretch : Boolean (optional)
A boolean that specifies whether a data series should be stretched to artificially fill a given time period. The default is false. Lucid timeseries data is inclusive, so if you request one day of data, from midnight to midnight in fifteen-minute increments, the last reading will be at 11:45pm. This creates a rendering problem because the last 15 minutes will be blank on line and area series. Setting stretch to true tells the series to clone its last reading and push it to the end of the period so that lines and areas render edge-to-edge.

###### style : Object (optional)
Arbitrary style properties to be applied to the series element. See [the React docs](https://facebook.github.io/react/tips/inline-styles.html) for how to format style properties.

###### type : String (optional)
Specifies how the series should render. Pass one of:

* area
* bar
* clusteredBar
* differenceBar
* line
* plot
* stackedBar

You only need to use this property when different series in the same group should have different render types (eg. bars overlaid with a line). If all series should use the same render type, set type on the parent group and its child series will inherit.

####Datum Properties

###### className : String (optional)
A string that will be added to the element that renders this data item.

###### style : Object (optional)
Arbitrary style properties to be applied to the element that renders this data item. This is useful when, for example, you need to assign a unique color or opacity to an individual bar. See [the React docs](https://facebook.github.io/react/tips/inline-styles.html) for how to format style properties.

###### date : Date
All timeseries data items must have both an ISO date and a value.

###### value : Number
All timeseries data items must have both an ISO date and a value.
{'fraction_non_alphanumeric': 0.07588279489105935, 'fraction_numerical': 0.0042073628850488355, 'mean_word_length': 4.277821834522865, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 12, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '551064', 'n_tokens_mistral': 5195, 'n_tokens_neox': 4862, 'n_words': 2976}