Custom Visualization

hatra
edited February 11, 2022 in Analytics #1

Hi All,
Does anyone has a sample Custom Visualization please? from classic car database or else,
Never used this feature and I want create a number of reports ( highcharts),

thanks

Comments

  • Thanks Jeff

  • hatra
    edited March 22, 2019 #4

    I dont see anything under the link you forwarded that might help me to start, but thanks,
    template script seems to be well written but because my knowledge of script is limited I am not sure how and where to modify to apply my datasets
    I want to apply my report dataset "HeatMap" and take out all sample data from below code and I want to apply three columns just like the sample on the script x:city , x: area, y: code
    I appreciate any help thanks
    //
    // This example demonstrates how to create a Heat Map Chart

    /* ----------------------------------------------------------------------------------------- */

    var config = {

    * Example: 
    *   xAxisCategoriesColumn : "COUNTRY"
    */
    
    /* the column name for the X Axis value in String format */
    xAxisCategoriesColumn : "<Country>",
    /* the column name for the Y Axis value in String format */
    yAxisCategoriesColumn : "<Function Level 2>",
    /* the column name for the series value in numeric format */
    seriesValueColumn : "<Financial Impact Currency>"
    

    };

    /* --------------------------------------------------------------------------------------- */

    //Test if data mapping is configured, otherwise use sample data
    config.testMode = config.xAxisCategoriesColumn == null
    || config.xAxisCategoriesColumn == ""
    || config.yAxisCategoriesColumn == null
    || config.yAxisCategoriesColumn == ""
    || config.seriesValueColumn == null
    || config.seriesValueColumn == "";

    var customViz = this;

    var chartConfig = {
    chart : {
    type : 'heatmap',
    marginTop : 40,
    marginBottom : 40,
    style : {
    color : '#555555',
    fontFamily : 'Arial',
    fontSize : '14px'
    }
    },

    title : {
        text : 'Heat Map',
        style : {
            color : '#333333',
            fontSize : '16px',
            fontWeight : 'bold'
        }
    },
    
    credits:{
        enabled:false
    },
    
    xAxis : {
        categories : [ 'Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas',
                'Maria', 'Leon', 'Anna', 'Tim', 'Laura' ]
    },
    
    yAxis : {
        categories : [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' ],
        title : null
    },
    
    colorAxis : {
        minColor : '#FFFFFF',
        maxColor : '#7cb5ec'
    },
    legend : {
        align : 'right',
        layout : 'vertical',
        margin : 0,
        verticalAlign : 'top',
        y : 25
    },
    
    tooltip : {
        formatter : function() {
            return '<b>' + this.series.xAxis.categories[this.point.x]
                    + '</b> sold <br><b>' + this.point.value
                    + '</b> items on <br><b>'
                    + this.series.yAxis.categories[this.point.y] + '</b>';
        }
    },
    
    series : [ {
        name : 'Sales per employee',
        borderWidth : 1,
        borderColor : "#FFFFFF",
        data : [ [ 0, 0, 10 ], [ 0, 1, 19 ], [ 0, 2, 8 ], [ 0, 3, 24 ],
                [ 0, 4, 67 ], [ 1, 0, 92 ], [ 1, 1, 58 ], [ 1, 2, 78 ],
                [ 1, 3, 117 ], [ 1, 4, 48 ], [ 2, 0, 35 ], [ 2, 1, 15 ],
                [ 2, 2, 123 ], [ 2, 3, 64 ], [ 2, 4, 52 ], [ 3, 0, 72 ],
                [ 3, 1, 132 ], [ 3, 2, 114 ], [ 3, 3, 19 ], [ 3, 4, 16 ],
                [ 4, 0, 38 ], [ 4, 1, 5 ], [ 4, 2, 8 ], [ 4, 3, 117 ],
                [ 4, 4, 115 ], [ 5, 0, 88 ], [ 5, 1, 32 ], [ 5, 2, 12 ],
                [ 5, 3, 6 ], [ 5, 4, 120 ], [ 6, 0, 13 ], [ 6, 1, 44 ],
                [ 6, 2, 88 ], [ 6, 3, 98 ], [ 6, 4, 96 ], [ 7, 0, 31 ],
                [ 7, 1, 1 ], [ 7, 2, 82 ], [ 7, 3, 32 ], [ 7, 4, 30 ],
                [ 8, 0, 85 ], [ 8, 1, 97 ], [ 8, 2, 123 ], [ 8, 3, 64 ],
                [ 8, 4, 84 ], [ 9, 0, 47 ], [ 9, 1, 114 ], [ 9, 2, 31 ],
                [ 9, 3, 48 ], [ 9, 4, 91 ] ],
        states : {
            hover : {
                color : "#777777"
            }
        },
        dataLabels : {
            enabled : true,
            style : {
                color : '#333333',
                textShadow : 'none',
                HcTextStroke : null,
                fontSize : '16px',
                fontWeight : 'bold'
            }
        }
    } ]
    

    }

    customize();

    function customize() {
    if (!config.testMode && customViz.getData()) {

        var data = customViz.getData();
    
        chartConfig.xAxis.categories = getAxisArray(data,
                config.xAxisCategoriesColumn);
        chartConfig.yAxis.categories = getAxisArray(data,
                config.yAxisCategoriesColumn);
        chartConfig.series[0].data = transform(data);
        if (!chartConfig.colorAxis.min && chartConfig.series[0].data[0]
                && chartConfig.series[0].data[0].length == 3) {
            chartConfig.colorAxis.min = chartConfig.series[0].data[0][2];
        }
    
        if (!chartConfig.colorAxis.max && chartConfig.series[0].data
                && chartConfig.series[0].data.length > 0) {
            chartConfig.colorAxis.max = chartConfig.series[0].data[chartConfig.series[0].data.length - 1][2];
        }
    }
    
    var birtOpts = customViz.getBirtOpts();
    
    if (birtOpts.theme == "Modern") {
        chartConfig.colorAxis.minColor = "#B0D24E";
        chartConfig.colorAxis.maxColor = "#C53C34";
    } else if (birtOpts.theme == "Clean Blue") {
        chartConfig.colorAxis.minColor = "#FFFFFF";
        chartConfig.colorAxis.maxColor = "#7CADD1";
    } else if (birtOpts.theme == "Warm Red") {
        chartConfig.colorAxis.minColor = "#FFFFFF";
        chartConfig.colorAxis.maxColor = "#C44E32";
    } else if (birtOpts.theme == "Grayscale") {
        chartConfig.colorAxis.minColor = "#FFFFFF";
        chartConfig.colorAxis.maxColor = "#9C9C9C";
    }
    

    }

    function getAxisArray(data, columnName) {
    if (!data) {
    return null;
    }
    var axisArr = [];
    var pos = $.inArray(columnName, data.columns);
    if (pos < 0) {
    return null;
    }
    var rawdata = data.rows;
    for (var i = 0; i < rawdata.length; i++) {
    if ($.inArray(rawdata[i][pos], axisArr) < 0) {
    axisArr.push(rawdata[i][pos]);
    }
    }
    return axisArr;
    }

    function getIndexByCategories(data, index, categories, type, columnName) {
    if (!categories.length || categories.length <= 0) {
    return null;
    }

    if (type == "x") {
        var pos = $.inArray(columnName, data.columns);
        if (pos < 0) {
            return null;
        }
        for (var i = 0; i < categories.length; i++) {
            if (data.rows[index][pos] == categories[i]) {
                return i;
            }
        }
    } else if (type == "y") {
        var pos = $.inArray(columnName, data.columns);
        if (pos < 0) {
            return null;
        }
        for (var i = 0; i < categories.length; i++) {
            if (data.rows[index][pos] == categories[i]) {
                return i;
            }
        }
    } else {
        return null;
    }
    return null;
    

    }

    function transform(data) {
    if (!data) {
    return null;
    }
    var dataArray = [];
    var totalCountNum = data.rows.length;
    xCategories = getAxisArray(data, config.xAxisCategoriesColumn);
    yCategories = getAxisArray(data, config.yAxisCategoriesColumn);

    if (xCategories && xCategories.length > 0 && yCategories
            && yCategories.length > 0) {
        for (var i = 0; i < totalCountNum; i++) {
            var item = [];
            item.push(getIndexByCategories(data, i, xCategories, "x",
                    config.xAxisCategoriesColumn));
            item.push(getIndexByCategories(data, i, yCategories, "y",
                    config.yAxisCategoriesColumn));
            var pos = $.inArray(config.seriesValueColumn, data.columns);
            if (pos < 0) {
                item.push(null);
            }
            var dataVal = data.rows[i][pos];
            item.push(format(dataVal));
            dataArray.push(item);
        }
    }
    dataArray.sort(function(a, b) {
        if (a.length == 3 && b.length == 3) {
            return Number(a[2]) - Number(b[2]);
        }
        return a;
    });
    return dataArray;
    

    }

    // format the float to 2 digits.
    function format(val) {
    if (!Number(val)) {
    return 0;
    }
    val = Number(val);
    if (isFloat(val)) {
    val = val.toFixed(2);
    }
    return val;
    }

    function isFloat(n) {
    return n === +n && n !== (n | 0);
    }

    var callback = function() {

    var heatmapChart = $('#' + customViz.getId()).highcharts(chartConfig);
    customViz.setDelegate(heatmapChart);
    customViz.setPrintReady();
    

    }

    head.load('http://code.highcharts.com/highcharts.js',
    'http://code.highcharts.com/modules/heatmap.js', callback);

  • It sounds like you have a report that runs using the code in your last message and the sample, hard-coded data. Can you please post it? Also, what version of BIRT are you running?

    I have some experience with Custom Visualizations in the OpenText BIRT Pro version. Commercial BIRT includes Custom Visualization report elements that have an interface to bind data set data to the CV. Seeing your code helps me understand what you are doing, but it would be a bigger help to have a sample report that I can run, if you can provide one.

    Warning No formatter is installed for the format ipb
  • Hi,
    I the BIRT OpenText Analytics Designer
    Version: 24.4.0
    I am trying to use Custom Visualization > Heat Map chart from > choose Template>
    if of course I run this it does work with the sample hard coded data, but I want to change it to my dataset and selected columns
    dataset = HeatMap" and and columns x:city , x: area, y: code
    the code above it the template code and I dont know how to apply my dataset column to the script posted above and how to take all the hard coded data out.
    I haven't done any coding yet hence I am asking how to modify the above code from template.
    :)

  • There is code that shows how to get the data dynamically for a Heat Map Custom Visualization in the OpenText Analytics Designer User Guide. It's on p.730 ( page numbers on the bottom of the page), or p.756 (PDF navigator).

    Warning No formatter is installed for the format ipb
  • hatra
    edited April 2, 2019 #8

    Hey Jeff,
    I am not sure if there is a pdf available anywhere that I can have a look but I dont think it would talk about how to exclude hard coded data from the code in the chosen Template,
    I only want to know how and where to exclude the hard coded template .
    the code I posted above is from the template and it has hard coded data, and I want to be able to select my dataset and columns without having them hard coded.
    Has anyone got a custom Visualization report with sample dataset ( not hard coded ) that I can use to understand feature better?
    thanks

  • jfranken
    edited April 4, 2019 #9

    Sorry, I forgot that this question was unanswered. I re-read the posts and I believe I have a simple answer for you. The hardcoded data does not need to be removed. It will be ignored automatically by the template when you supply data. The issue is that you need to remove the < > from your column names.

    Change:

    /* the column name for the X Axis value in String format */
    xAxisCategoriesColumn : "<Country>",
    /* the column name for the Y Axis value in String format */
    yAxisCategoriesColumn : "<Function Level 2>",
    /* the column name for the series value in numeric format */
    seriesValueColumn : "<Financial Impact Currency>"
    

    To:

    /* the column name for the X Axis value in String format */
    xAxisCategoriesColumn : "Country",
    /* the column name for the Y Axis value in String format */
    yAxisCategoriesColumn : "Function Level 2",
    /* the column name for the series value in numeric format */
    seriesValueColumn : "Financial Impact Currency"
    

    If the custom visualization still doesn't work, make sure the column names are correct and that the case matches.

    Warning No formatter is installed for the format ipb
  • Hi, thanks again Jeff
    I have used the sample database

    I have changed

    /* the column name for the X Axis value in String format */
    xAxisCategoriesColumn : "COUNTRY",
    /* the column name for the Y Axis value in String format */
    yAxisCategoriesColumn : "CITY",
    /* the column name for the series value in numeric format */
    seriesValueColumn : "CREDITLIMIT"
    

    I have also changed
    //Test if data mapping is configured, otherwise use sample data
    config.testMode = config.xAxisCategoriesColumn == null
    || config.xAxisCategoriesColumn == "COUNTRY"
    || config.yAxisCategoriesColumn == null
    || config.yAxisCategoriesColumn == "CITY"
    || config.seriesValueColumn == null
    || config.seriesValueColumn == "CREDITLIMIT";

    it didnt work, then I comment the below out and stil not right
    // xAxis : {
    // categories : [ 'Alexander', 'Marie', 'Maximilian', 'Sophia', 'Lukas',
    // 'Maria', 'Leon', 'Anna', 'Tim', 'Laura' ]
    //},

    //yAxis : {
    //  categories : [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' ],
    //  title : null
    //},
    
  • All you should need to do is add the data set on the "Data" tab and make the first set of changes on the "Script" tab. Do this:

    /* the column name for the X Axis value in String format */
    xAxisCategoriesColumn : "COUNTRY",
    /* the column name for the Y Axis value in String format */
    yAxisCategoriesColumn : "CITY",
    /* the column name for the series value in numeric format */
    seriesValueColumn : "CREDITLIMIT"
    

    Do not make the other changes. I almost made the same mistake of changing the second section. It is very misleading. There should be a comment on the second section explaining that it should not be changed.

    Warning No formatter is installed for the format ipb
  • perfect , thanks Jeff
    thats fine now

  • @jfranken and anyone else could comment
    I have a column for Y and other Column for X and they usually return 5 values so the heatmap would be 5x5, however, there might be time when all 5 values for Y or X might not be available in datasource. any way to have the heatmap to have fixed 5x5 ?
    thanks

  • Looking at the standard heat map template in the custom visualization report element, the getAxisArray() method might be the place to add your code. Check the axisArr size and add more rows if it has fewer than 5 rows. I have not tested this.

    Another possibility is to create a static data set having 1 column and 5 rows. The column contains integer data with the row values set to the numbers 1 thru 5. Add a computed column to your existing data set with a RunningCount aggregation. Create a Join data set on the two data sets using an outer join that joins the two count columns and includes the data from the original data set that is used in the heat map. Change the source for the heatmap to the Join data set. It will always have a minimum of 5 rows.

    Warning No formatter is installed for the format ipb
  • how do you set 1 to 5 on expression filed, is the code for it?
    cheers

  • I have applied
    var i=0;
    while (i<5)
    {
    i++;

    }
    to my computed column but it doesnt stop at 5 and it runs over

  • Your "while loop" code should work. Maybe the variable "i" value is getting overwritten. Try a different variable name. Also, the following code will write the value of i to the browser debugger (F12):

    console.log(i);

    Warning No formatter is installed for the format ipb