Skip to main content

Python Highcharts wrapper

Project description

highcharts-excentis

This version is a fork of the original project by Kyper Data.

Unfortunately, the original maintainers no longer respond to issues, pull requests, e-mails or any other attempts to contact them.

Therefor, we decided to fork their project and made some fixes for Python >= 3.10. A published version is also available at PyPI

License

The python-highcharts wrapper is licensed under the MIT license.

However, please be aware that the Highcharts project itself, as well as Highmaps and Highstock, are only free for non-commercial use under the Creative Commons Attribution-NonCommercial license. Commercial use requires the purchase of a separate license. Pop over to Highcharts for more information.

Overview

python-highcharts is a simple translation layer between Python and Javascript for Highcharts projects (highcharts, highmaps, and highstocks).

In addition, python-highcharts integrates with Jupyter notebook, which enables you to render Highcharts, Highmaps, and Highstock visualizations directly in notebooks. See examples here.

The original framework was inspired by python-nvd3 and PyHighcharts.

Installation

python-highcharts supports Python 2.7/3.4+ and is available on PyPI. To install:

pip install highcharts-excentis

Highcharts/Highstock

Basic Usage

Usage of python-highcharts is very similar to usage of the original Javascript library.

The main input is a python dictionary similar to Highcharts's 'options' object. The dictionary supports most options listed in the official Highcharts documentation.

However, the data_set(s) need to be input by a separate function.

from highcharts_excentis import Highchart

# A chart is the container that your data will be rendered in, it can (obviously) support multiple data series within it.
chart = Highchart()

# Adding a series requires at minimum an array of data points. 
# You can also change the series type, the name, or other series options as kwargs.
data = range(1,20)
chart.add_data_set(data, series_type='line', name='Example Series')

# This will generate and save a .html file at the location you assign
chart.save_file()

You can add chart options using set_options. Ex:

chart.set_options('chart', {'resetZoomButton': {'relativeTo': 'plot', 'position': {'x': 0,'y': -30}}})
chart.set_options('xAxis', {'events': {'afterBreaks': 'function(e){return}'}})
chart.set_options('tooltip', {'formatter': 'default_tooltip'})

The set_options function can update the options automatically if you input the same option_type. Ex:

chart.set_options('chart', {'style': {"fontSize": '22px'}})
chart.set_options('chart', {'resetZoomButton': {'position': {'x': 10}}})
chart.set_options('chart', {'resetZoomButton': {'relativeTo': 'chart'}})
chart.set_options('xAxis', {'plotBands': {'color': '#FCFFC5', 'from': 2, 'to': 4}})
chart.set_options('xAxis', {'plotBands': {'color': '#FCFFC5', 'from': 6, 'to': 8}})
chart.set_options('xAxis', {'plotBands': {'color': '#FCFFC5', 'from': 10, 'to': 12}})

However, the better practice is to construct chart options by a dictionary (as Highcharts suggests: http://www.highcharts.com/docs/getting-started/your-first-chart) and then input by the set_dict_options function. Ex:

options = {
    'title': {
        'text': 'Atmosphere Temperature by Altitude'
    },
    'subtitle': {
        'text': 'According to the Standard Atmosphere Model'
    },
    'xAxis': {
        'reversed': False,
        'title': {
            'enabled': True,
            'text': 'Altitude'
        },
        'labels': {
            'formatter': 'function () {\
                return this.value + "km";\
            }'
        },
        'maxPadding': 0.05,
        'showLastLabel': True
    },
    'yAxis': {
        'title': {
            'text': 'Temperature'
        },
        'labels': {
            'formatter': "function () {\
                return this.value + '°';\
            }"
        },
        'lineWidth': 2
    },
    'legend': {
        'enabled': False
    },
    'tooltip': {
        'headerFormat': '<b>{series.name}</b><br/>',
        'pointFormat': '{point.x} km: {point.y}°C'
    }
}

chart.set_dict_options(options)

Unlike Javascript Highcharts, the series option can't be included in the options dictionary. It needs to input by the add_data_set (and/or add_drilldown_data_set) function, Ex:

chart.add_data_set(data, 'scatter', 'Outlier', 
    marker={
        'fillColor': 'white',
        'lineWidth': 1,
        'lineColor': 'Highcharts.getOptions().colors[0]'
    },
    tooltip={'pointFormat': 'Observation: {point.y}'}
)

chart.add_drilldown_data_set(data_2, 'column', 'Chrome', name='Chrome')

Example Usage

from highcharts_excentis import Highchart
chart = Highchart()

chart.set_options('chart', {'inverted': True})

options = {
    'title': {
        'text': 'Atmosphere Temperature by Altitude'
    },
    'subtitle': {
        'text': 'According to the Standard Atmosphere Model'
    },
    'xAxis': {
        'reversed': False,
        'title': {
            'enabled': True,
            'text': 'Altitude'
        },
        'labels': {
            'formatter': 'function () {\
                return this.value + "km";\
            }'
        },
        'maxPadding': 0.05,
        'showLastLabel': True
    },
    'yAxis': {
        'title': {
            'text': 'Temperature'
        },
        'labels': {
            'formatter': "function () {\
                return this.value + '°';\
            }"
        },
        'lineWidth': 2
    },
    'legend': {
        'enabled': False
    },
    'tooltip': {
        'headerFormat': '<b>{series.name}</b><br/>',
        'pointFormat': '{point.x} km: {point.y}°C'
    }
}

chart.set_dict_options(options)
data =  [[0, 15], [10, -50], [20, -56.5], [30, -46.5], [40, -22.1], 
[50, -2.5], [60, -27.7], [70, -55.7], [80, -76.5]]
chart.add_data_set(data, 'spline', 'Temperature', marker={'enabled': False}) 

chart.save_file()

Hosting your local CDN

To avoid requesting Highcharts CDN every time you want to generate a graph, and eventually getting blocked by a rate limit, you can choose or download the Highcharts resources and static files and host them.

from highcharts_excentis import Highchart

# Define the CDN's url
chart = Highchart(offline=True, cdn_url="example.com/highcharts")

Jupyter/IPython notebook

To render charts in Jupyter notebooks, simply put the chart object on the last line of a cell:

chart.set_dict_options(options)
data =  [[0, 15], [10, -50], [20, -56.5], [30, -46.5], [40, -22.1], 
[50, -2.5], [60, -27.7], [70, -55.7], [80, -76.5]]
chart.add_data_set(data, 'spline', 'Temperature', marker={'enabled': False}) 

chart

Example notebooks:

Todo:

  • More charts support
  • Clean code and put more explanation

Reference: Highcharts API


Highmaps

Basic Usage

Usage of python-highcharts is very similar to usage of the original Javascript library.

The main input is a python dictionary similar to Highmaps's 'options' object. The dictionary supports most options listed in the official Highmaps documentation.

However, the data_set(s) need to be input by a separate function.

from highcharts_excentis import Highmap

# A chart is the container that your data will be rendered in, it can (obviously) support multiple data series within it.
chart = Highmap()

# Adding a series requires a minimum of one argument, an array of data points
chart.add_data_set(data, series_type='map', name='Example Series')

# This will generate and save a .html file at the location you assign
chart.save_file()

Although you can add chart option using set_options, but a better practice is to construct chart options by a dictionary (as highcharts suggests: http://www.highcharts.com/docs/getting-started/your-first-chart) and then input by set_dict_optoins function. Ex.

options = {
    'chart': {
        'borderWidth': 1,
        'marginRight': 50 
    },

    'title': {
        'text': 'US Counties unemployment rates, April 2015'
    },

    'legend': {
        'title': {
            'text': 'Unemployment<br>rate',
            'style': {
                'color': "(Highcharts.theme && Highcharts.theme.textColor) || 'black'"
            }
        },
        'layout': 'vertical',
        'align': 'right',
        'floating': True,
        'valueDecimals': 0,
        'valueSuffix': '%',
        'backgroundColor': "(Highcharts.theme && Highcharts.theme.legendBackgroundColor) || 'rgba(255, 255, 255, 0.85)'",
        'symbolRadius': 0,
        'symbolHeight': 14
    },

    'mapNavigation': {
        'enabled': True
    },

    'colorAxis': {
        'dataClasses': [{
            'from': 0,
            'to': 2,
            'color': "#F1EEF6"
        }, {
            'from': 2,
            'to': 4,
            'color': "#D4B9DA"
        }, {
            'from': 4,
            'to': 6,
            'color': "#C994C7"
        }, {
            'from': 6,
            'to': 8,
            'color': "#DF65B0"
        }, {
            'from': 8,
            'to': 10,
            'color': "#DD1C77"
        }, {
            'from': 10,
            'color': "#980043"
        }]
    },

    'plotOptions': {
        'map':{
        'mapData': 'geojson'

        },
        'mapline': {
            'showInLegend': False,
            'enableMouseTracking': False
        }
    },
} 

chart.set_dict_options(options)

The map data is set by set_map_source function. It is recommended to use the map collection on highcharts: http://code.highcharts.com/mapdata/

For the map properties visit: http://www.highcharts.com/docs/maps/map-collection

The default setting is to use the Highchart Javascript map.

# set_map_source requires a least one argument: the map data url
chart.set_map_source('http://code.highcharts.com/mapdata/countries/us/us-all-all.js', jsonp_map = False)

However, the better practice is to load map data using function in highmap_helper library and convert it in preparation to be added directly by the add_map or add_data_set functions.

from highmap_helper import jsonp_loader, js_map_loader, geojson_handler

map_url = 'http://code.highcharts.com/mapdata/countries/us/us-all-all.js'

# Load .js format map data from the source and convert to GeoJSON object
geojson = js_map_loader(map_url)

# Similarly, json format (jsonp) map data can be loaded using:
geojson = jsonp_loader("a_jsonp_map_url")

# Reconstruct a GeoJSON object in preparation to be read directly. 
# geojson_handler function is similar to Highcharts.geojson in Highcharts: http://api.highcharts.com/highmaps#Highcharts.geojson
mapdata = geojson_handler(geojson)

chart.add_map_data(mapdata)

The series option in Highmaps needs to be input separately using add_data_set (and/or add_drilldown_data_set) function, Ex.

chart.add_data_set(data, 'map', 'Unemployment rate', joinBy=['hc-key', 'code'], 
    tooltip={
        'valueSuffix': '%'
    },
    borderWidth = 0.5,
    states={
        'hover': {
            'color': '#bada55'
        }
    }
)
chart.add_drilldown_data_set(sub_data, 'map', id=mapkey, name=item['name'], 
    dataLabels={
        'enabled': True,
        'format': '{point.name}'
    }
)

The data set can be loaded directly from the url (jsonp format), but it is not recommended:

data_url = 'http://www.highcharts.com/samples/data/jsonp.php?filename=us-counties-unemployment.json&callback=?'
chart.add_data_from_jsonp(data_url, 'json_data', 'map', 'Unemployment rate', joinBy=['hc-key', 'code'], 
    tooltip={
        'valueSuffix': '%'
    },
    borderWidth = 0.5,
    states={
        'hover': {
            'color': '#bada55'
        }
    }
)

Furthermore, python-highcharts has a function to add Javascript in the beginning or the end of JQuery body: $(function(){}, but, again, it is not recommended unless it is really necessary.

# function requires at least two arguments: script (javascript) and location ('head' or 'end')
chart.add_JSscript("var lines = Highcharts.geojson(Highcharts.maps['countries/us/us-all-all'], 'mapline');", 'head')

Examples

Bad practice:

  1. load data directly and handle it in Javascript 2) insert javascript into thea head 3) use unquote function RawJavaScriptText to prepare Javascript:
from highcharts_excentis import Highmap
from common import RawJavaScriptText

chart = Highmap()

options = {
    'chart': {
        'borderWidth': 1,
        'marginRight': 50 
    },
    'title': {
        'text': 'US Counties unemployment rates, April 2015'
    },
    'legend': {
        'title': {
            'text': 'Unemployment<br>rate',
            'style': {
                'color': "(Highcharts.theme && Highcharts.theme.textColor) || 'black'"
            }
        },
        'layout': 'vertical',
        'align': 'right',
        'floating': True,
        'valueDecimals': 0,
        'valueSuffix': '%',
        'backgroundColor': "(Highcharts.theme && Highcharts.theme.legendBackgroundColor) || 'rgba(255, 255, 255, 0.85)'",
        'symbolRadius': 0,
        'symbolHeight': 14
    },
    'mapNavigation': {
        'enabled': True
    },
    'colorAxis': {
        'dataClasses': [{
            'from': 0,
            'to': 2,
            'color': "#F1EEF6"
        }, {
            'from': 2,
            'to': 4,
            'color': "#D4B9DA"
        }, {
            'from': 4,
            'to': 6,
            'color': "#C994C7"
        }, {
            'from': 6,
            'to': 8,
            'color': "#DF65B0"
        }, {
            'from': 8,
            'to': 10,
            'color': "#DD1C77"
        }, {
            'from': 10,
            'color': "#980043"
        }]
    },
    'plotOptions': {
        'mapline': {
            'showInLegend': False,
            'enableMouseTracking': False
        }
    }
} 

chart.set_dict_options(options)
data_url = 'http://www.highcharts.com/samples/data/jsonp.php?filename=us-counties-unemployment.json&callback=?'
chart.add_data_from_jsonp(data_url, 'json_data', 'map', 'Unemployment rate', 
    joinBy=['hc-key', 'code'], 
    tooltip={'valueSuffix': '%'},
    borderWidth=0.5,
    states={'hover': {'color': '#bada55'}}
)
chart.add_data_set(RawJavaScriptText('[lines[0]]'), 'mapline', 'State borders', color = 'white')
chart.add_data_set(RawJavaScriptText('[lines[1]]'), 'mapline', 'Separator', color = 'gray')
chart.set_map_source('http://code.highcharts.com/mapdata/countries/us/us-all-all.js', jsonp_map = False)
chart.add_JSscript("var lines = Highcharts.geojson(Highcharts.maps['countries/us/us-all-all'], 'mapline');", 'head')
chart.add_JSscript("Highcharts.each(geojson, function (mapPoint) {\
    mapPoint.name = mapPoint.name + ', ' + mapPoint.properties['hc-key'].substr(3, 2);\
});", 'head')

chart.save_file()

Better practice:

from highcharts_excentis import Highmap
from highmap_helper import jsonp_loader, js_map_loader, geojson_handler

chart = Highmap()
options = {
    'chart': {
        'borderWidth': 1,
        'marginRight': 50 
    },
    'title': {
        'text': 'US Counties unemployment rates, April 2015'
    },
    'legend': {
        'title': {
            'text': 'Unemployment<br>rate',
            'style': {
                'color': "(Highcharts.theme && Highcharts.theme.textColor) || 'black'"
            }
        },
        'layout': 'vertical',
        'align': 'right',
        'floating': True,
        'valueDecimals': 0,
        'valueSuffix': '%',
        'backgroundColor': "(Highcharts.theme && Highcharts.theme.legendBackgroundColor) || 'rgba(255, 255, 255, 0.85)'",
        'symbolRadius': 0,
        'symbolHeight': 14
    },
    'mapNavigation': {
        'enabled': True
    },
    'colorAxis': {
        'dataClasses': [{
            'from': 0,
            'to': 2,
            'color': "#F1EEF6"
        }, {
            'from': 2,
            'to': 4,
            'color': "#D4B9DA"
        }, {
            'from': 4,
            'to': 6,
            'color': "#C994C7"
        }, {
            'from': 6,
            'to': 8,
            'color': "#DF65B0"
        }, {
            'from': 8,
            'to': 10,
            'color': "#DD1C77"
        }, {
            'from': 10,
            'color': "#980043"
        }]
    },
    'plotOptions': {
        'map':{
            'mapData': 'geojson'
        },
        'mapline': {
            'showInLegend': False,
            'enableMouseTracking': False
        }
    }
} 

chart.set_dict_options(options)

# read data and map directly from url
data_url = 'http://www.highcharts.com/samples/data/jsonp.php?filename=us-counties-unemployment.json&callback=?'
map_url = 'http://code.highcharts.com/mapdata/countries/us/us-all-all.js'

data = jsonp_loader(data_url)
geojson = js_map_loader(map_url)
mapdata = geojson_handler(geojson)
lines = geojson_handler(geojson, 'mapline')
for x in mapdata:
    x.update({'name':x['name']+', '+x['properties']['hc-key'].split('-')[1].upper()})

#map(lambda x: x['properties'].update({'name':x['properties']['name']+', '+x['properties']['hc-key'].split('-')[1]}), geojson['features'])

chart.add_data_set(data, 'map', 'Unemployment rate', joinBy = ['hc-key', 'code'], 
    tooltip={'valueSuffix': '%'},
    borderWidth=0.5,
    states={
        'hover': {
            'color': '#bada55'
        }
    }
)
chart.add_data_set([lines[0]], 'mapline', 'State borders', color = 'white')
chart.add_data_set([lines[3]], 'mapline', 'Separator', color = 'gray')
chart.add_map_data(mapdata)

chart.save_file()

📦 HTTP Request Caching

Summary:
Added persistent, on-disk caching for Highcharts JavaScript library downloads to avoid repeated network requests and prevent hitting Highcharts CDN rate limits.

Key Changes:

  • Introduced diskcache to store downloaded JS files in ./.cache/highcharts-excentis (50 MB limit).
  • Default time-to-live (TTL) for cached files: 7 days.
  • Requests now go through a get_or_download(url) helper:
    • Cache hit → return stored content.
    • Cache miss → download via urllib.request, store in cache, return result.
  • Automatic cleanup of expired entries using cache.cull().

What Users Should Know:

  • First run may download required files; subsequent runs reuse local cache.
  • Cache directory path (./.cache/highcharts-excentis) works with project’s CI/CD and artifact/cache strategy. this directory is automatically generated in your working directory
  • Prevents repeated HTTP calls between test runs and across pipelines when artifacts/cache are reused.
  • Cache can be cleared manually by deleting ./.cache/highcharts-excentis.

Todo:

  • More examples
  • Clean code and put more explanation

Reference: Highcharts API

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

highcharts_excentis-0.4.7.tar.gz (62.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

highcharts_excentis-0.4.7-py3-none-any.whl (67.6 kB view details)

Uploaded Python 3

File details

Details for the file highcharts_excentis-0.4.7.tar.gz.

File metadata

  • Download URL: highcharts_excentis-0.4.7.tar.gz
  • Upload date:
  • Size: 62.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.2

File hashes

Hashes for highcharts_excentis-0.4.7.tar.gz
Algorithm Hash digest
SHA256 b24c53c366190c27992910afc362e3af4e937957bd4115c639a0f4f738ac1676
MD5 bf2158ff0e882658d2bc1f20e65b2ede
BLAKE2b-256 4c208135584a47ad1f3cf6d908773b643fc0a80079712a64fde89fb011ac3f0f

See more details on using hashes here.

File details

Details for the file highcharts_excentis-0.4.7-py3-none-any.whl.

File metadata

File hashes

Hashes for highcharts_excentis-0.4.7-py3-none-any.whl
Algorithm Hash digest
SHA256 ccfdcd5075e018793844a83383646d37715a0311bdbba741b2ec211e8724b8b5
MD5 9a4512100d104024235e7c50b171158d
BLAKE2b-256 6796542f0809d8f909a192d39ed3bd662683d7dafa323485a195ff8c41b52667

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page