calendarheatmap icon indicating copy to clipboard operation
calendarheatmap copied to clipboard

Added ability to specify the max possible count manually

Open NightMachinery opened this issue 4 years ago • 6 comments

I wanted to use this to visualize my habit tracking data, and so I needed to specify the maximum possible count manually (instead of it being the max of counts present in input data).

Sample usage:

echo '{
    "2020-05-16": 2,
    "2020-05-17": 6,
    "2020-05-18": 1,
    "2020-05-19": 10,
    "2020-05-20": 30
}' | calendarheatmap -maxcount 10 > chart.png

image

I wanted to make the counts be float instead of int, but I had doubts on whether your code assumes that they are ints. floats are more general and usable.

PS: I have also fixed os.Setenv("CALENDAR_HEATMAP_ASSETS_PATH", "charts/assets") with a default value for the actual Getenv.

PPS: Take a look at https://github.com/NightMachinary/calendarheatmap/blob/master/tests2.org for the later commits' effects.

NightMachinery avatar Feb 21 '21 21:02 NightMachinery

Cool stuff! I like how it looks and new functions! So you added a bunch of things: max count, negative values with alternative color scheme, added color schemes.

I will go through the PR.

One thing stands out right away is colorschemes assets, they are growing too large, that would need to be moved to files, maybe CSV or JSON.

Second, could you split PR into pieces so that max_count change is separate from say color schemes and negative values? That would speed-up review..

nikolaydubina avatar Feb 26 '21 02:02 nikolaydubina

For colorscales, I like how it looks, but I think better to keep single colorscale for day counts. If you have a colorscales (say from negative to positives as here) that visually combines two different colorscales, IMO better to make single colorscale by using values from both of them. This is called diverging coloscales: https://plotly.com/python/colorscales/#setting-the-midpoint-of-a-color-range-for-a-diverging-color-scale

If you need to "fix" certain point in the middle better to think mechanism how to fix colorscale values to values v, so you would get "mapping colorscale spec" like -colorscale-values="[-100, -50, 0, 50, 100]" if you have color scale [blue, light-blue, white, light-green, green]. Or maybe some parameter to fix mid-point like -midpoint=0.

In fact, plotly does just set midpoint to average, we might do the same and in your case set midpoint to 0. image

nikolaydubina avatar Feb 26 '21 03:02 nikolaydubina

I’ll try to break up the PR into multiple parts, but 1. I don’t know how to do that currently and need to find time to learn that, 2. The tests of earlier commits were fixed in later commits because I didn’t notice they were there at first.

On refactoring the color scheme data to JSON, it’s not that hard since I have a script that spits out the Go code from the Julia sources. I can just change that to spit out JSON. But what’s the point? JSON is just JS code, there will not be any benefit. We would also need to add some machinery to parse out the JSON into Go objects. That’ll also slow down the code.

On the alternative color schemes being redundant ... I know, the feature is somewhat specialized (I needed a way to differentiate the data of the past year from the current year), and it can be done without if one creates a specialized color scheme. Generally speaking, this fork has been optimized for my own needs, and I understand that these might otherwise be feature bloat for others.

Perhaps the best solution is for you to cherry pick what you like from my changes.

NightMachinery avatar Feb 26 '21 09:02 NightMachinery

Alright, to proceed with this work please make two PRs:

PR1: adds colorranges

Let's try to match plotly API, I think matplotlib and R is similar.

Docs:

  • https://plotly.com/python/colorscales/
  • https://plotly.com/python/colorscales/#explicitly-setting-a-color-range

color ranges represent the minimum to maximum range of data to be mapped onto the 0 to 1 input range of the color scale. Color ranges default to the range of the input data and can be explicitly specified using either the range_color or color_continuous_midpoint arguments for many Plotly Express functions, or cmin/cmid/cmax or zmin/zmid/zmax for various graph_objects such as layout.coloraxis.cmin or marker.cmin in go.Scatter traces or cmin in go.Heatmap traces. For example, if a color range of [100, 200] is used with the color scale above, then any mark with a color value of 100 or less will be blue, and 200 or more will be red. Marks with values in between will be various shades of purple.

Such that charts.HeatmapConfig{ accepts new prameter ColorRange which is struct of {Min: *float64, Max: *float64, Mid: *float64}. If value is nil, then ignore it. Each value is from the same range as input data (i.e. no scaling applied yet). Use available values to adjust colors. Midpoint in your case is 0.

Next, CLI should accept -midpoint, -min, -max arguments to fills this out.

PR 2: adds different colorsscales

Here you can add new colorscales, including divergent colorscales. As well as scripts from Juilia, and bash scripts to process them.

Please put colorscales into JSON or CSV files. Please do not add "alternative colorscale". For divergent case, just create a new colorscale based on two non-divergent colorscales that you like. Please do not add any new CLI arguments.

In both PRs:

Please don't update environment variable with assets for now. Similarly, don't do other modifications or new testing scripts for now. I am okay to change it though in separate PR.

nikolaydubina avatar Feb 26 '21 09:02 nikolaydubina

Okay, I see. It is up to you if you want to make these changes. If not, I will try to do it myself later on to accommodate your usecase.

One note on JSON for configs, if you are interested. As for why JSON/CSV for configuration: so that Go code will not be 70K lines of code; Go is easier to review and maintain; CSV/JSON is declarative, meaning harder to make mistakes; it is also dynamic, meaning you can add colorschemes with the same build of executable; it is interoprable with other tools and programs, say maybe Python executable or other program can use the same config. Many benefits, but primarily so that it is not bloat Go code..

Thanks for submission anyways!

nikolaydubina avatar Feb 26 '21 10:02 nikolaydubina

Thanks. I am very busy this semester, I don't think I'll find the opportunity to do this. I am also probably going to take that fork further off its current road. It's probably best if it lives as a divergent fork. Feel free to close this PR as you see fit.

BTW, thank you for this package! It has helped me quite a bit in tracking my time. 3>

NightMachinery avatar Feb 26 '21 11:02 NightMachinery