Changeset 2055


Ignore:
Timestamp:
Oct 10, 2011, 6:09:59 PM (5 years ago)
Author:
tjeerd@…
Message:

VIS-31 and VIS-23, added some aggregation and other advanced settings. The option "no aggregation" is not present yet. There is also an error with the count-aggregation (see VIS-34)

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/dbnp/visualization/VisualizeController.groovy

    r2054 r2055  
    405405                        // Retrieve data from GSCF itself
    406406                        def closure = valueCallback( parsedField.type )
    407                        
     407
    408408                        if( closure ) {
    409409                                samples.each { sample ->
     
    606606                                // The computation for mean and error will return null if no (numerical) values are found
    607607                                // In that case, the user won't see this category
    608                                 def dataForGroup = computeMeanAndError( values );
     608                def dataForGroup = null;
     609                switch( params.get( 'aggregation') ) {
     610                                case "average":
     611                        dataForGroup = computeMeanAndError( values );
     612                        break;
     613                    case "count":
     614                        dataForGroup = computeCount( values );
     615                        break;
     616                    case "median":
     617                        dataForGroup = computeMedian( values );
     618                        break;
     619                    case "none":
     620                        // Currently disabled, create another function
     621                        dataForGroup = computeMeanAndError( values );
     622                        break;
     623                    case "sum":
     624                        dataForGroup = computeSum( values );
     625                        break;
     626                    default:
     627                        // Default is "average"
     628                        dataForGroup = computeMeanAndError( values );
     629                }
     630
    609631
    610632                                if( showEmptyCategories || dataForGroup.value != null ) {
     
    742764            if(it instanceof Number) {
    743765                try{
    744                     tmpDateContainer << new java.util.Date( it ).toString()
     766                    tmpDateContainer << new java.util.Date( (Long) it ).toString()
    745767                } catch(IllegalArgumentException e){
    746768                    tmpDateContainer << it
     
    878900        /**
    879901         * Computes the mean of the given values. Values that can not be parsed to a number
    880          * are ignored. If no values are given, the mean of 0 is returned.
     902         * are ignored. If no values are given, null is returned.
    881903         * @param values        List of values to compute the mean for
    882904         * @return                      Arithmetic mean of the values
     
    890912                                sumOfValues += num;
    891913                                sizeOfValues++
    892                         } 
     914                        }
    893915                }
    894916
     
    896918                        return sumOfValues / sizeOfValues;
    897919                else
    898                         return null; 
     920                        return null;
    899921        }
    900922
     
    902924        * Computes the standard error of mean of the given values.
    903925        * Values that can not be parsed to a number are ignored.
    904         * If no values are given, the standard deviation of 0 is returned.
     926        * If no values are given, null is returned.
    905927        * @param values         List of values to compute the standard deviation for
    906928        * @param mean           Mean of the list (if already computed). If not given, the mean
     
    929951       }
    930952    }
     953
     954    /**
     955         * Computes the median of the given values. Values that can not be parsed to a number
     956         * are ignored. If no values are given, null is returned.
     957         * @param values        List of values to compute the median for
     958         * @return                      Median of the values
     959         */
     960        protected def computeMedian( List values ) {
     961                def listOfValues = [];
     962                values.each { value ->
     963                        def num = getNumericValue( value );
     964                        if( num != null ) {
     965                                listOfValues << num;
     966                        }
     967                }
     968
     969        listOfValues.sort();
     970
     971        def listSize = listOfValues.size();
     972
     973                if( listSize > 0 ) {
     974            def listHalf = (int) Math.abs(listSize/2);
     975            if(listSize%2==0) {
     976                // If the list is of an even size, take the mean of the middle two value's
     977                return ["value": (listOfValues.get(listHalf)+listOfValues.get(listHalf-1))/2];
     978            } else {
     979                // If the list is of an odd size, take the middle value
     980                return ["value": listOfValues.get(listHalf-1)];
     981            }
     982        } else
     983                        return ["value": null];
     984        }
     985
     986    /**
     987         * Computes the count of the given values. Values that can not be parsed to a number
     988         * are ignored. If no values are given, null is returned.
     989         * @param values        List of values to compute the count for
     990         * @return                      Count of the values
     991         */
     992        protected def computeCount( List values ) {
     993                def sumOfValues = 0;
     994                def sizeOfValues = 0;
     995                values.each { value ->
     996                        def num = getNumericValue( value );
     997                        if( num != null ) {
     998                                sumOfValues += num;
     999                                sizeOfValues++
     1000                        }
     1001                }
     1002
     1003                if( sizeOfValues > 0 )
     1004                        return ["value": sizeOfValues];
     1005                else
     1006                        return ["value": null];
     1007        }
     1008
     1009    /**
     1010         * Computes the sum of the given values. Values that can not be parsed to a number
     1011         * are ignored. If no values are given, null is returned.
     1012         * @param values        List of values to compute the sum for
     1013         * @return                      Arithmetic sum of the values
     1014         */
     1015        protected def computeSum( List values ) {
     1016                def sumOfValues = 0;
     1017                def sizeOfValues = 0;
     1018                values.each { value ->
     1019                        def num = getNumericValue( value );
     1020                        if( num != null ) {
     1021                                sumOfValues += num;
     1022                                sizeOfValues++
     1023                        }
     1024                }
     1025
     1026                if( sizeOfValues > 0 )
     1027                        return ["value": sumOfValues];
     1028                else
     1029                        return ["value": null];
     1030        }
    9311031   
    9321032        /**
  • trunk/grails-app/views/visualize/index.gsp

    r2051 r2055  
    4747
    4848                <span class="topmenu_item" id="menu_study">
    49                     <span class="topmenu_item_label"><img src="${fam.icon( name: 'report' )}" style="vertical-align: text-bottom; display: inline-block;"/>&nbsp;Study<img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" />:</span>
    50                     <span class="topmenu_item_info">no study selected</span>
     49                    <div class="topmenu_item_label"><img src="${fam.icon( name: 'report' )}" style="vertical-align: text-bottom; display: inline-block;"/>&nbsp;Study<img src="${resource(dir: 'images', file: 'spinner.gif')}" class="spinner" />:</div>
     50                    <div class="topmenu_item_info">no study selected</div>
    5151                    <img src="${fam.icon( name: 'bullet_arrow_down' )}" style="vertical-align: text-bottom; display: inline-block;"/>
    5252                    <div class="formulier">
     
    5858                </span>
    5959
    60                
     60                <span class="menu_seperator">&nbsp;</span>
     61
     62                <span class="topmenu_item" id="menu_aggregation">
     63                    <span class="topmenu_item_label"><img src="${fam.icon( name: 'server_chart' )}" style="vertical-align: text-bottom; display: inline-block;"/>&nbsp;Aggregation:</span>
     64                    <span class="topmenu_item_info">AVERAGE</span>
     65                    <img src="${fam.icon( name: 'bullet_arrow_down' )}" style="vertical-align: text-bottom; display: inline-block;"/>
     66                    <div class="formulier">
     67                        <p class="info">Select a way to aggregate the data.</p>
     68                        <p>
     69                            <select name="aggregation" size="5" onchange="$('#menu_aggregation').children('.topmenu_item_info').html($(this).val().toUpperCase()); changeVis();">
     70                                <option value="average" SELECTED>Average</option>
     71                                <option value="count">Count</option>
     72                                <option value="median">Median</option>
     73                                <option value="none" disabled>No aggregation</option>
     74                                <option value="sum">Sum</option>
     75                            </select>
     76                        </p>
     77                    </div>
     78                </span>
    6179
    6280                <span class="menu_seperator">&nbsp;</span>
     
    6684                    <img src="${fam.icon( name: 'bullet_arrow_down' )}" style="vertical-align: text-bottom; display: inline-block;"/>
    6785                    <div class="formulier">
    68                         <p class="info">Advanced settings.</p>
    69                         <p>
    70                             Visualize the data as soon as enough parameters are known.
    71                             <input type="checkbox" name="autovis" id="autovis" CHECKED/>
    72                         </p>
     86                        <table>
     87                            <tr>
     88                                <td>Visualize the data as soon as enough parameters are known.</td>
     89                                <td><input type="checkbox" name="autovis" id="autovis" CHECKED/></td>
     90                            </tr>
     91                            <tr>
     92                                <td>Always show values in the graph.<br />(if this box is unchecked, value's are only shown when you hover over a datapoint)</td>
     93                                <td><input type="checkbox" name="showvalues" id="showvalues" onClick="changeVis();"/></td>
     94                            </tr>
     95                        </table>
    7396                    </div>
    7497                </span>
  • trunk/web-app/css/visualization.css

    r2051 r2055  
    113113}
    114114
    115 .menu_item:hover {
    116     background-color: #EEE;
    117 }
    118 
    119115.menu_item_done {
    120116    background-color: #67E667;
     
    183179    position: relative;
    184180    padding: 3px;
     181    height: 14px;
     182    vertical-align: top;
    185183}
    186184
     
    191189
    192190.topmenu_item_label {
     191    display: inline-block;
     192    vertical-align: text-bottom;
    193193    color: #000033;
    194194}
    195195
    196196.topmenu_item_info {
     197    display: inline-block;
     198    vertical-align: top;
    197199    color: #000066;
     200    overflow: hidden;
     201    width:auto;
     202    max-width: 200px;
     203    max-height: 18px;
    198204}
    199205
     
    201207    font-size: 10px;
    202208    position: absolute;
    203     top: 22px;
     209    top: 21px;
    204210    left: 0px;
    205211    display: none;
     
    214220    width: 100%;
    215221    font-size: 10px;
     222}
     223
     224.formulier table {
     225    border-style: none;
     226}
     227
     228.formulier table td {
     229    font-size: 10px;
     230    padding: 6px 2px;
     231}
     232
     233#menu_advanced .formulier {
     234    width: 300px;
    216235}
    217236
  • trunk/web-app/js/visualization.js

    r2051 r2055  
    1010    $(".topmenu_item").click(
    1111        function(event) {
    12             if(openForm!=null && this!=openForm) {
    13                 $(openForm).children('.formulier').hide();
     12            if(this!=openForm) {
     13                toggleForm(this, "open");
     14            } else {
     15                toggleForm(this, "close");
    1416            }
    15             $(this).children('.formulier').toggle();
    16             openForm = this;
    1717            return false;
    1818                }
     
    2121    $(document).keyup(
    2222        function(event) {
    23             if ( event.which == 27 && openForm!=null ) {
    24                 $(openForm).children('.formulier').hide();
    25                 openForm = null;
     23            if ( event.which == 27 ) {
     24                toggleForm(openForm, "close");
    2625            }
    2726        }
     
    3029    $(document).click(
    3130        function() {
    32             if(openForm!=null) {
    33                 $(openForm).children('.formulier').hide();
    34                 openForm = null;
    35             }
     31            toggleForm(openForm, "close");
    3632        }
    3733    );
     
    4945function changeStudy() {
    5046
    51 
    52     $("#menu_study").children('.formulier').hide();
    53     openForm = null;
    54 
    55     $( '#rows, #columns, #types' ).empty();
     47    toggleForm(openForm, "close");
     48
     49    $( '#rows, #columns, #types, #visualization' ).empty();
    5650    clearStep(".menu_item");
    5751
     
    6155    if($( '#study option:selected' ).length>0) {
    6256        $( "#menu_row, #menu_column" ).find("img.spinner").show();
    63         $( "#menu_study" ).find("span.topmenu_item_info").html($( '#study option:selected' ).text());
     57        $( "#menu_study" ).find("div.topmenu_item_info").html($( '#study option:selected' ).text());
    6458
    6559        executeAjaxCall( "getFields", {
     
    8983                    $( "#rows, #columns" ).html(strOptions);
    9084                       
    91                         $( "#menu_study" ).find("span.topmenu_item_info").html($( '#study option:selected' ).text());
     85                        $( "#menu_study" ).find("div.topmenu_item_info").html($( '#study option:selected' ).text());
    9286                    $( "#menu_row, #menu_column" ).find("img.spinner").hide();
    9387                        $( "#menu_row, #menu_column" ).addClass("menu_item_fill");
     
    10296 */
    10397function changeFields(divid) {
    104 
    105     var type = "rows";
    106     if(divid=="menu_column") type = "columns";
    10798
    10899    clearStep("#"+divid);
     
    163154        visType = $( '#types option:selected' ).text();
    164155    } else {
    165         $( "#menu_vis" ).removeClass().addClass("menu_item menu_item_fill");
     156        if( $( "#menu_row" ).hasClass("menu_item_done") && $( "#menu_column" ).hasClass("menu_item_done") ) {
     157            $( "#menu_vis" ).removeClass().addClass("menu_item menu_item_fill");
     158        }
    166159    }
    167160    $( "#menu_go" ).removeClass().addClass("menu_item");
     
    179172function visualize() {
    180173
    181     if(!$( "#menu_vis" ).hasClass("menu_item_done") ||
    182         !$( "#menu_row" ).hasClass("menu_item_done") ||
    183         !$( "#menu_column" ).hasClass("menu_item_done")
     174    if($( "#menu_vis" ).hasClass("menu_item_done") &&
     175        $( "#menu_row" ).hasClass("menu_item_done") &&
     176        $( "#menu_column" ).hasClass("menu_item_done")
    184177       ) {
    185         $( ".menu_item" ).not(".menu_item_done").removeClass().addClass("menu_item menu_item_warning");
    186     } else {
    187 
    188178        executeAjaxCall( "getData", {
    189179            "errorMessage": "An error occurred while retrieving data from the server. Please try again or contact a system administrator.",
     
    229219                // chosen by the user
    230220                var plotOptions = null;
     221
     222                var showDataValues = $("#showvalues").attr("checked")=="checked" ? true : false;
    231223               
    232224                switch( returnData.type ) {
     
    244236                                    highlightMouseDown: true,
    245237                                    barDirection: 'horizontal'
    246                                 }
     238                                },
     239                                pointLabels: {show: showDataValues}
    247240                            },
    248241                            highlighter: {
    249                                 show: true,
     242                                show: !showDataValues,
    250243                                sizeAdjust: 7.5,
    251                                 tooltipAxes: "y"
     244                                tooltipAxes: "x"
    252245                            },
    253246                            series: series,
    254247                            axes: {
    255248                                xaxis: {
    256                                     //ticks: returnData.series[ 0 ].y,          // Use the x-axis of the first serie
    257249                                    label: ylabel,
    258250                                    formatString:'%.2f',
     
    261253                                yaxis: {
    262254                                    renderer: $.jqplot.CategoryAxisRenderer,
     255                                    ticks: returnData.series[ 0 ].x,            // Use the x-axis of the first serie
    263256                                    label: xlabel,
    264257                                    labelRenderer: $.jqplot.CanvasAxisLabelRenderer
     
    276269                            stackSeries: true,
    277270                            seriesDefaults:{
    278                                 renderer:$.jqplot.LineRenderer
     271                                renderer:$.jqplot.LineRenderer,
     272                                pointLabels: {show: showDataValues}
    279273                            },
    280274                            series: series,
    281275                            highlighter: {
    282                                 show: true,
     276                                show: !showDataValues,
    283277                                sizeAdjust: 7.5,
    284278                                tooltipAxes: "y"
     
    302296                            stackSeries: true,
    303297                            seriesDefaults:{
    304                                 renderer:$.jqplot.LineRenderer
     298                                renderer:$.jqplot.LineRenderer,
     299                                pointLabels: {show: showDataValues}
    305300                            },
    306301                            series: series,
    307302                            highlighter: {
    308                                 show: true,
     303                                show: !showDataValues,
    309304                                sizeAdjust: 7.5,
    310305                                tooltipAxes: "y"
     
    337332                                    // Disables default highlighting on mouse over.
    338333                                    highlightMouseDown: true
    339                                 }
     334                                },
     335                                pointLabels: {show: showDataValues}
    340336                            },
    341337                            highlighter: {
    342                                 show: true,
     338                                show: !showDataValues,
    343339                                sizeAdjust: 7.5,
    344340                                tooltipAxes: "y"
     
    441437        $( '#message_counter' ).children(".formulier").toggle();
    442438        openForm = null;
     439    }
     440}
     441
     442function toggleForm(selector, action) {
     443    if( action=="close" || openForm !=null ) {
     444        $(openForm).children('.formulier').hide();
     445        $(openForm).removeClass("topmenu_item_selected");
     446        openForm = null;
     447    }
     448    if( action=="open" ) {
     449        $(selector).children('.formulier').show();
     450        $(selector).addClass("topmenu_item_selected");
     451        openForm = selector;
    443452    }
    444453}
Note: See TracChangeset for help on using the changeset viewer.