go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/funcs/scatter_chart.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package funcs
     9  
    10  import (
    11  	"bytes"
    12  	"context"
    13  
    14  	"github.com/wcharczuk/go-chart/v2"
    15  	"github.com/wcharczuk/go-chart/v2/drawing"
    16  	"go.charczuk.com/projects/nodes/pkg/types"
    17  )
    18  
    19  // ScatterChart renders a chart to svg.
    20  func ScatterChart(config ChartConfig) func(context.Context, []float64, []float64) (types.SVG, error) {
    21  	return func(ctx context.Context, xValues, yValues []float64) (types.SVG, error) {
    22  		if len(xValues) < 2 {
    23  			return types.SVG{}, nil
    24  		}
    25  		main, err := scatterMain(ctx, config, xValues, yValues)
    26  		if err != nil {
    27  			return types.SVG{}, err
    28  		}
    29  		thumbnail, err := scatterThumbnail(ctx, config, xValues, yValues)
    30  		if err != nil {
    31  			return types.SVG{}, err
    32  		}
    33  		return types.SVG{
    34  			Main:      main,
    35  			Thumbnail: thumbnail,
    36  		}, nil
    37  	}
    38  }
    39  
    40  func scatterMain(_ context.Context, config ChartConfig, xValues, yValues []float64) (string, error) {
    41  	primarySeries := chart.ContinuousSeries{
    42  		Style: chart.Style{
    43  			StrokeColor: chart.ColorBlue,
    44  			FillColor:   chart.ColorBlue.WithAlpha(100),
    45  		},
    46  		XValues: xValues,
    47  		YValues: yValues,
    48  	}
    49  	config.ApplyPrimaryContinuousSeries(&primarySeries)
    50  
    51  	var series []chart.Series
    52  	if !config.HideSeries {
    53  		series = append(series, primarySeries)
    54  	}
    55  
    56  	if !config.HideSeriesLastValue {
    57  		primarySeriesLastValue := chart.LastValueAnnotationSeries(primarySeries)
    58  		primarySeriesLastValue.Style.FillColor = drawing.ColorFromHex("252a31")
    59  		primarySeriesLastValue.Style.StrokeColor = drawing.ColorFromHex("2d72d2")
    60  		primarySeriesLastValue.Style.FontColor = drawing.ColorFromHex("abb3bf")
    61  		series = append(series, primarySeriesLastValue)
    62  	}
    63  
    64  	linRegSeries := &chart.LinearRegressionSeries{
    65  		Style: chart.Style{
    66  			StrokeColor: drawing.ColorFromHex("8E292C"),
    67  		},
    68  		InnerSeries: primarySeries,
    69  	}
    70  	config.ApplyRegressionSeries(linRegSeries)
    71  
    72  	if !config.HideRegression {
    73  		series = append(series, linRegSeries)
    74  	}
    75  	if !config.HideRegressionLastValue {
    76  		linearRegLastValue := chart.LastValueAnnotationSeries(linRegSeries)
    77  		linearRegLastValue.Style.FillColor = drawing.ColorFromHex("252a31")
    78  		linearRegLastValue.Style.StrokeColor = drawing.ColorFromHex("8E292C")
    79  		linearRegLastValue.Style.FontColor = drawing.ColorFromHex("abb3bf")
    80  		series = append(series, linearRegLastValue)
    81  	}
    82  
    83  	c := chart.Chart{
    84  		Width:  720,
    85  		Height: 405,
    86  		XAxis: chart.XAxis{
    87  			TickStyle: chart.Style{
    88  				StrokeColor: drawing.ColorFromHex("383e47"),
    89  				FontColor:   drawing.ColorFromHex("abb3bf"),
    90  			},
    91  		},
    92  		YAxis: chart.YAxis{
    93  			TickStyle: chart.Style{
    94  				StrokeColor: drawing.ColorFromHex("383e47"),
    95  				FontColor:   drawing.ColorFromHex("abb3bf"),
    96  			},
    97  		},
    98  		YAxisSecondary: chart.HideYAxis(),
    99  		Canvas: chart.Style{
   100  			FillColor: drawing.ColorTransparent,
   101  		},
   102  		Background: chart.Style{
   103  			FillColor: drawing.ColorTransparent,
   104  		},
   105  		Series: series,
   106  	}
   107  	config.ApplyChart(&c)
   108  	buf := new(bytes.Buffer)
   109  	if err := c.Render(chart.SVG, buf); err != nil {
   110  		return "", err
   111  	}
   112  	return buf.String(), nil
   113  }
   114  
   115  func scatterThumbnail(_ context.Context, config ChartConfig, xValues, yValues []float64) (string, error) {
   116  	primarySeries := chart.ContinuousSeries{
   117  		Style: chart.Style{
   118  			StrokeColor: chart.ColorBlue,
   119  			FillColor:   chart.ColorBlue.WithAlpha(100),
   120  		},
   121  		XValues: xValues,
   122  		YValues: yValues,
   123  	}
   124  	config.ApplyPrimaryContinuousSeries(&primarySeries)
   125  
   126  	c := chart.Chart{
   127  		Width:  300,
   128  		Height: 100,
   129  		XAxis: chart.XAxis{
   130  			Style:     chart.Hidden(),
   131  			TickStyle: chart.Hidden(),
   132  		},
   133  		YAxis: chart.YAxis{
   134  			Style:     chart.Hidden(),
   135  			TickStyle: chart.Hidden(),
   136  		},
   137  		YAxisSecondary: chart.HideYAxis(),
   138  		Canvas: chart.Style{
   139  			FillColor: drawing.ColorTransparent,
   140  		},
   141  		Background: chart.Style{
   142  			FillColor: drawing.ColorTransparent,
   143  		},
   144  		Series: []chart.Series{
   145  			primarySeries,
   146  		},
   147  	}
   148  	buf := new(bytes.Buffer)
   149  	if err := c.Render(chart.SVG, buf); err != nil {
   150  		return "", err
   151  	}
   152  	return buf.String(), nil
   153  }