tutorials - DaveL17/matplotlib GitHub Wiki

Apply Theme Action
Color Palettes
Creating Custom CSV Data
Using Adjustment Factors
Using Contextual Charts
Using Custom Axis Labels
Using Theme Manager
Creating Dynamic Radial Bar Charts


Color Palettes

One key to making good-looking charts is to select an appealing color palette.

There is a ton of information online about color selection and this is one area where you'll often find that a palette that looks good to one person will offend another. You should definitely use whatever looks good to you. When you look under the hood, the plugin uses the standard RGB color value -- which is a six digit hex code to reflect the proportion of Red, Green and Blue (R-G-B). When selecting colors with the OS X color picker, you should find that any color selected using that tool should work. However, it's recommended that you find one method within the tool to set your colors and stick with that. Some people prefer to use the Crayon view. I prefer the 'RGB Sliders' control where I enter the RGB code into the 'Hex Color #' field.

The RGB hex color code has two digits per color: #RRGGBB (the color picker tool takes care of the hashtag bit.) The values for each color are bounded by the numbers 0-9 and A-F. The values range from 0-F with 0 (zero) being no color and F being full color. In other words, a red value (the first two digits of RRGGBB) of 00 would mean no red. A red value of FF would mean full red. All zeroes (#000000) means no color (black) and all F's (#FFFFFF) means full color (white). Again, there's lots of information online that explains all this, but I wanted to make sure to explain this small part here because it factors directly into the colors I use and how I pick them.

Color Value
Black #000000
Shades of gray: #111111 - #999999
Red: #FF0000
Green: #00FF00
Blue: #0000FF
White: #FFFFFF

Note the F's in the values above. These colors are nice and contrasty, but you may find that you need more options than this. Then it's a matter of taste, but I like to use the inherent math for balance. Using the range: 0-1-2-3-4-5-6-7-8-9-A-B-C-D-E-F, there are 16 potential values for each digit. One of my additional colors is yellow (a combination of red and green) -- the yellow color I use is #FFFF00. You get the idea. After that, I try to find something discrete steps between two colors. For example, to get orange, I use #FF7F00 (full red, "half" green, no blue)--the value 7 is the middle of the green scale 00 through FF. How many combinations are there? A lot. (If memory serves, it's 6 digits with 16 choices or 16^6 = 16,777,216.)

Play with the color values in the color picker. While this may seem complex at first, it's really quite simple once you get the hang of it. There is a never ending, very "enthusiastic" debate about color selection out there. If you stick with colors you like, none of that matters.


Creating Custom CSV Data

The CSV Engine device works well for taking snapshots of data at routine intervals (I have mine set to log every 15 minutes). However, sometimes you may wish to have more granular logging to track the exact times that certain events take place or to log every change to a device. This is a fairly easy thing to do when you combine the power of Indigo Triggers and a bit of simple Python programming. You do not need to know how to program Python to use this method.

Note

that there are other ways to track all changes to a device--including using Indigo's built-in SQL Logger plugin--the benefit of the following method is that you have a greater level of control over the conditions governing when the logging takes place.


Example - Logging a Dehumidifier

I have my basement dehumidifier plugged into an Aeotec Smart Switch 6. The Smart Switch reads power usage, so I can use that to determine whether the dehumidifier is running or idle based on the power being consumed. When running, the dehumidifier uses approximately 80 Watts, so I decided to consider any draw greater than 75 Watts to be 'on' and any draw less than 75 Watts to be 'off'. To log the change in the dehumidifier's state, I created two Indigo Triggers: one for 'running' and one for 'not running'.

Trigger Criteria Basement Dehumidifier Load Becomes less than 75
Trigger Condition Optional.
Trigger Action Execute Script - Embedded Python

Trigger
View Full Size

Action
View Full Size

Paste the following code into the scripting window:

import os
import datetime

data_file = "/path/to/datafile/dehumidifier.csv"
heading = "dehumidifier"

if not os.path.isfile(data_file):
    with open(data_file, 'a') as outfile:
        outfile.write(u"{0},{1}\n".format("timestamp", heading))

with open(data_file, 'a') as outfile:
    outfile.write(u"{0},{1}\n".format(datetime.datetime.now(), 'False'))    

A few notes about the Python script. The first group of lines set the environment variables for the script--where to write the data, and a column heading for the data file. The second group of lines will check to determine if a valid file exists for the data to be stored and will create the file if it doesn't exist. The third group of lines will write the actual data to be logged.

You will need to change a couple lines to fit your installation: 1) data_file (change this to point to your folder and filename). To use the resulting data in the matplotlib plugin, you should save the file to the same folder where your other CSV data reside. 1) heading (change this to something appropriate for your needs.)

When the power draw becomes less than 75 Watts, the script writes a timestamp and 'false' to indicate the dehumidifier is not running.

Once you've saved the Trigger, duplicate it and change the trigger's name to 'Dehumidifier - On State', change 'Becomes Less Than' to 'Becomes Greater Than', and change the Python script to write 'true' instead of 'false'. Be sure to save your changes.

Warning

This script will continue to write to this file without any consideration to the total number of observations within the file. So, over time, the number of observations could become quite large.


Using Adjustment Factors

You can elect to use a chart adjustment factor to allow multiple sources to be displayed on the same chart with finer-grained control over how the data are displayed. For example, the following chart displays four binary data elements. Each has values of 0 or 1 so the chart wouldn't be useful because all four lines would be plotted on top of each other. By applying an adjustment factor to one or more of the lines, we can shift where they appear on the chart. Note that for visual appeal, we have raised the first device off the X axis by adding to its value (+1). In this instance, the effect was achieved by applying a simple linear transformation to the data to be charted:

Item Setting
Line 1 + 1 (plots on 1 and 2)
Line 2 + 3 (plots on 3 and 4)
Line 3 + 5 (plots on 5 and 6)
Line 4 + 7 (plots on 7 and 8)
Tick Labels off,on,off,on,off,on,off,on
Tick Locations 1,2,3,4,5,6,7,8
Y Axis Range 0-9

Line Chart with Adjustment
View Full Size

These transformations are applied in real time and do not change the underlying data.


Using Custom Axis Labels

Matplotlib helpfully tries to set axis ticks and labels for us. However, sometimes, its best guess isn't good enough, so you may find your axis labelled with values like (0, 0, 1, 1, 2, 2). You can often adjust the precision setting of the scale to a finer level and fix that condition. However, you can also elect to use custom labels on the Y axis of select chart types. This gives you greater control over how your axis will appear.

For example, consider the following wind direction chart:

Wind Direction Chart
View Full Size

Note the labels on the Y axis connoting direction. In this case, the data being plotted are compass directions in degrees (0-360).

To change the Y axis labels, go into the device settings and tick the Y axis controls group if it's not already displayed.

Custom Tick Labels
View Full Size

In this instance, we want five marks on the Y axis to represent compass degree direction values of 0, 90, 180, 270, and 360. Add corresponding custom labels int the 'Tick Labels' field. Note that the number of tick labels and tick locations must be equal in order for them to display properly. It's also best for the tick location data to be within the expected range of the data to be charted.

Label Location
N 360
W 270
S 180
E 90
N 0

You can also use this feature to force your charts to display Y axis values in a preferred way. For example, for a relative humidity chart, you might set the Y axis min/max to be 0 - 100, but you also might only want four Y axis labels:

Label Location
25 25
50 50
75 75
100 100

Or only three labels:

Label Location
25 25
50 50
75 75

or add units:

Label Location
25% 25
50% 50
75% 75
100% 100

Using Theme Manager

The next evolution in how the plugin controls the look and feel of your charts is the Theme Manager. You access the Theme Manager from the plugin's menu items. A configuration dialog will appear that is divided into two sections.

Current Theme

The top section of the configuration dialog contains all the controls related to the visual display of your charts, broken down into several categories. - Color Settings These settings control the colors of the various elements of your charts. - Font Settings These settings control the type and size of the fonts used in your charts. - Other Settings These settings include such things as grid style, tick size, and line weight. - Transparency Settings These settings control the transparency of the canvas (the area outside the plot) and the plot area.

The value of these settings shows the theme currently in effect. That is, the values that are being used to draw your charts right now. These values can change when a new theme is applied.

Theme Manager

The Theme Manager is used to manage various themes used in the plugin. You don't need to create any themes in order to use the plugin. If you would like one, consistent look to your charts, set the settings for the Current Theme and close the dialog. However, if you would like to maintain multiple themes, then read on.

First, it is highly recommended that you create a "default" theme--that is, a theme that you will consider to be your most common theme. You can call it whatever you like (it doesn't have to be "Default"). To do this, set the current theme above and then select the Theme Manager Action "Save". Give your theme a name and then "Execute Action". Repeat these steps to create new themes as needed. When you're done, be sure to select your preferred theme from the list and execute the Apply Action to make it the current theme.

Note

actions taken in the Theme Manager are immediate. Selecting "Cancel" will not undue them. Changes made to the current theme (that are not saved using the Theme Manager) will not be applied until you close the dialog box.


Using Contextual Charts

With a bit of creativity, you can extend the features of the Matplotlib plugin using Indigo. For example, you can change the appearance of a chart based on a specific context or event. You might want a darker theme for nighttime or change the overall look of a chart based on a particular condition in order to highlight that condition visually. In this example, we will be referring to a chart that displays the energy used by a pump motor (which, in this example) should be relatively constant over time.

First, create your chart as you would like it to appear in the chart image.

Warning

Be sure to set the image refresh frequency to MANUAL.

The pump in this example typically uses about 180 watts of energy and runs 24/7. As you can see, the energy usage is fairly constant. If something should go wrong with the pump causing its energy usage to change dramatically, I might want the chart to look different.

Once the chart settings are where you would like them to be, create an action group to control the image creation. Based on your triggers and conditionals, create the following steps:

  • change the Matplotlib theme to your alert theme.
  • redraw the chart.
  • change the Matplotlib theme back to your regular theme.

Note

Be sure to create a companion action group that creates the image with its normal properties.

Pump Energy Chart
View Full Size

Pump Energy Chart
View Full Size

Simple!

(Thanks to forum user Autolog for the idea!)


Apply Theme Action

The "Apply Theme Action" is used to replace the default color settings currently in effect. When used, the settings made through the Apply Theme action become the new settings for all charts. Only the settings you change in the action will be changed. Of course, you can (and should) create an "Apply Theme" action that holds your preferred settings so that you always have the ability to recall them at any time.

Example: Daytime / Nighttime Styles

One way to use the tool is to use different color styles for daytime vs. nighttime. Your daytime style could use a bright background and high contrast colors while your nighttime style could use a black or dark gray background and low contrast colors. Then, create a trigger that fires when the variable isDaylight changes (you may already have this trigger defined).

First, we'll create two Change Chart Theme actions that hold your preferences for daytime and nighttime color schemes. For this example, we'll call these:

Apply Theme - Daytime

Apply Theme - Nighttime

Now, we'll create two triggers that will change the theme based on the value of the Indigo system variable isDaylight

Daytime Trigger

Trigger Criteria isDaylight changes to True.
Trigger Condition Optional.
Trigger Action Apply Theme Action (daytime theme)

Daytime Chart
View Full Size

Nighttime Trigger

Trigger Criteria isDaylight changes to False.
Trigger Condition Optional.
Trigger Action Apply Theme Action (nighttime theme)

Nighttime Chart
View Full Size


"Dynamic" Radial Bar Chart

The Radial Bar chart device is a stock (or static) chart type and (like other charts) doesn't automatically change based on changes to the underlying data. However, it is very easy to create a dynamic Radial Bar chart using an Indigo Trigger.

Create your Radial Bar Chart, and use an Indigo trigger to update the chart whenever the source data value changes.

Trigger Criteria source data changes. Trigger Condition Optional. Trigger Action Refresh One Chart (your Radial chart.)


Creating Cycling Charts

What do I mean by cycling? I mean being able to replace one chart image with another chart image in "real time". This method works really well, but in order to implement it, you'll likely have to do a bit of refactoring if you're already using the plugin. It just might be worth it...

  1. Disable all your chart devices (not required, but this will keep log messages to a minimum.)

  2. Make the location of where your images are saved in the main plugin preferences to reflect your version of Indigo:

    /Library/Application Support/Perceptive Automation/Indigo 7.5/IndigoWebServer/images/controls/

    Note: you may get a warning message when you restart the plugin that your image save path may not match the current Indigo version. If your images appear where you want them to, you can ignore this warning.

  3. Change the figure save names of your existing charts to account for the new path. For example, if your save path was (like mine) saving images to the .../static/ images folder, change the save name of your exiting chart(s) from >save_name.png to /static/save_name.png. Of course, use your image names in place of save_name.

  4. Repeat this process for all your chart devices.

  5. Re-enable your chart devices.

That's all the refactoring that's required. This change now allows you to choose to save your images to the devices, static, or variables folder on a case by case basis.

Now on to the "replaceable" image bit. For the purposes of this example, we'll start fresh, but you could refactor existing images to do the same thing. Say you have two items with similar charts that you want to display on one control page and cycle through them rather than displaying them individually--for example, a weather chart at home and at the lake house.

  1. Create your first chart as desired, and make the figure save name to be something like my_chart+.png. Make sure to include the +. It's important.

  2. Create a duplicate of your first chart, change the save name to follow the same scheme--in this case, my_chart+1.png and change the source to your second source.

  3. Repeat this process for the remaining charts. Since we only have two, we're done.

  4. Create an Indigo variable called image_switcher (or whatever), and set its value to zero.

  5. On your control page, add a new control page item linked to the image_switcher variable, select the "as image" option and select my_chart+.png. You are actually displaying the variable on the control page, but you're displaying its value as an image.

  6. Still with the same image selected, select Server Actions, Script and File Actions, Execute Script.

  7. In the embedded script window, add the following Python Code (you'll need to adjust it to reflect the number of charts you're cycling through):

    val = int(indigo.variables['image_switcher'].value)
    
    if val == 1:
        val = 0
    else:
        val +=1
    
    indigo.variable.updateValue('image_switcher', str(val))

That's it. Once your chart images are built, you'll be able to cycle through them by simply tapping (or clicking) on the image in the browser, Indigo Touch, Domotics Pad, etc.

You may not have to take all of these steps depending on how your installation was configured. Also, for the curious, there are variations that you can use--like using button images to cycle the charts (to provide a visual cue that the image can be cycled), or use a timer to change the image_switcher variable every few seconds and skip the embedded code all together. There may be a slight delay when changing the image_switcher value externally, but the tap method works instantly.

⚠️ **GitHub.com Fallback** ⚠️