Popupmenu mvc: fix anchor target in renderOptions; Visualizations registry: default link target to galaxy_main; Scatterplot (in registry): general refactoring and cleanup, paginate data instead of loading all, allow zoom and pan; pack scripts

This commit is contained in:
Carl Eberhard
2013-11-08 11:02:23 -05:00
parent a55fab57f8
commit 108f30d541
24 changed files with 1200 additions and 1403 deletions
@@ -0,0 +1,89 @@
var numericColumnStats = function( data, keys ){
var console = console || { debug: function(){} },
stats = {};
// precondition: keys is an array of keys accessible on each data in data
if( !keys || !keys.length ){
throw new Error( 'keys is a required parameter and must be an array:' + keys );
}
if( !data || !data.length ){
return stats;
}
function parseVal( val ){
if( val === null ){
throw new Error( 'Null value' );
}
val = Number( val );
if( isNaN( val ) || !isFinite( val ) ){
throw new Error( 'NaN or non-finite number' );
}
return val;
}
// does this effect the data in the other thread?
[ 'min', 'max', 'sum', 'mean', 'median', 'count' ].forEach( function( name, i ){
stats[ name ] = new Array( keys.length );
});
var keyIndex = 0,
separatedCols = new Array( keys.length );
keys.forEach( function( key, keyIndex ){
stats.min[ keyIndex ] = 0;
stats.max[ keyIndex ] = 0;
stats.sum[ keyIndex ] = 0;
separatedCols[ keyIndex ] = [];
});
// work backwards to prevent co-modification problems while splitting up data into columns
for( var dataIndex=( data.length - 1 ); dataIndex>=0; dataIndex-=1 ){
var datum = data.pop( dataIndex );
for( keyIndex=0; keyIndex<keys.length; keyIndex+=1 ){
var key = keys[ keyIndex ],
datumColVal = datum[ key ];
try {
//NOTE: parsing value as number
datumColVal = parseVal( datumColVal );
} catch( e ){
continue;
}
// separate the columns
separatedCols[ keyIndex ].unshift( datumColVal );
// get the other stats
stats.min[ keyIndex ] = Math.min( stats.min[ keyIndex ], datumColVal );
stats.max[ keyIndex ] = Math.max( stats.max[ keyIndex ], datumColVal );
stats.sum[ keyIndex ] += datumColVal;
}
}
// get counts, mean, median
function comparator( a, b ){
if( a < b ){ return -1; }
if( a < b ){ return 1; }
return 0;
}
for( keyIndex=0; keyIndex<keys.length; keyIndex+=1 ){
var count = separatedCols[ keyIndex ].length,
sum = stats.sum[ keyIndex ];
stats.count[ keyIndex ] = count;
stats.mean[ keyIndex ] = ( sum / count );
// sort columns for median
separatedCols[ keyIndex ].sort( comparator );
// odd count -> straight forward median
var middleDataIndex = Math.floor( count / 2 );
if( count % 2 === 1 ){
stats.median[ keyIndex ] = separatedCols[ keyIndex ][ middleDataIndex ];
} else {
var middleValA = separatedCols[ keyIndex ][ middleDataIndex ],
middleValB = separatedCols[ keyIndex ][( middleDataIndex + 1 )];
stats.median[ keyIndex ] = ( middleValA + middleValB ) / 2;
}
}
return stats;
};
File diff suppressed because one or more lines are too long
@@ -1,171 +1,199 @@
/*TODO: use/move into base.less*/
* { margin: 0px; padding: 0px; }
/* -------------------------------------------- general layout */
div.tab-pane {
padding: 8px;
}
* { margin: 0; padding: 0; }
/* -------------------------------------------- header */
.header {
margin-bottom: 8px;
}
.chart-header > * { margin: 0; padding: 0; }
#chart-header {
padding : 8px;
background-color: #ebd9b2;
.chart-header {
margin-bottom: 16px;
overflow: auto;
background-color: #ebd9b2;
padding : 16px 12px 12px 12px;
}
#chart-header .subtitle {
margin: -4px 0px 0px 4px;
padding : 0;
.chart-header h2 {
margin-bottom: 4px;
}
.chart-header p {
color: white;
font-size: small;
}
/* -------------------------------------------- main layout */
#scatterplot {
/*from width + margin of chart?*/
.scatterplot-editor > * { margin: 0; padding: 0; }
.scatterplot-editor .tab-pane {
padding: 8px;
}
.scatterplot-container .tab-pane {
.scatterplot-editor .help-text,
.scatterplot-editor .help-text-small {
color: grey;
margin-bottom: 8px;
}
/* -------------------------------------------- all controls */
.scatterplot-editor .help-text {
margin-top: 4px;
}
#scatterplot input[type=button],
#scatterplot select {
.scatterplot-editor .help-text-small {
font-size: smaller;
}
/* ============================================ config controls */
.scatterplot-config-control {
max-width: 768px;
}
.scatterplot-config-control input[type="button"],
.scatterplot-config-control button,
.scatterplot-config-control select {
width: 100%;
max-width: 256px;
margin-bottom: 8px;
}
#scatterplot .help-text,
#scatterplot .help-text-small {
color: grey;
.scatterplot-config-control input[type="text"] {
width: 100%;
max-width: 512px;
border: 1px solid lightgrey;
}
#scatterplot .help-text {
padding-bottom: 16px;
.scatterplot-config-control input[type="checkbox"] {
display: inline-block;
margin-top: -3px;
}
#scatterplot .help-text-small {
padding: 4px;
font-size: smaller;
}
#scatterplot > * {
}
#scatterplot input[value=Draw] {
.scatterplot-config-control .render-button {
display: block;
margin-top: 16px;
}
#scatterplot .numeric-slider-input {
max-width: 70%;
}
/* -------------------------------------------- data controls */
/* -------------------------------------------- chart controls */
#chart-control .form-input {
/*display: table-row;*/
}
#chart-control label {
/*text-align: right;*/
.scatterplot-config-control .form-input {
margin-bottom: 8px;
/*display: table-cell;*/
}
#chart-control .slider {
/*display: table-cell;*/
.scatterplot-config-control .slider {
height: 8px;
display: block;
margin: 8px 0px 0px 8px;
margin-bottom: 8px;
}
#chart-control .slider-output {
/*display: table-cell;*/
.scatterplot-config-control .slider-output {
float: right;
}
#chart-control input[type="text"] {
border: 1px solid lightgrey;
}
/* -------------------------------------------- statistics */
#stats-display table#chart-stats-table {
width: 100%;
}
#stats-display #chart-stats-table th {
width: 30%;
padding: 4px;
font-weight: bold;
color: grey;
}
#stats-display #chart-stats-table td {
border: solid lightgrey;
border-width: 1px 0px 0px 1px;
padding: 4px;
}
#stats-display #chart-stats-table td:nth-child(1) {
border-width: 1px 0px 0px 0px;
padding-right: 1em;
text-align: right;
font-weight: bold;
color: grey;
}
/* ============================================ plot display */
/* -------------------------------------------- load indicators */
#loading-indicator {
margin: 12px 0px 0px 8px;
.scatterplot-display .loading-indicator {
position: absolute;
margin: 10px 0px 0px 10px;
color: grey;
}
#scatterplot #loading-indicator .loading-message {
.scatterplot-display .loading-indicator .loading-indicator-message {
display: inline-block;
margin-left: 4px;
font-style: italic;
font-size: smaller;
color: grey;
}
/* -------------------------------------------- display controls */
.scatterplot-display .controls {
width: 100%;
margin-bottom: 4px;
border: 1px solid lightgrey;
border-radius: 3px;
padding: 8px 8px 4px 8px;
}
.scatterplot-display .controls button {
display: inline-block;
min-width: 0;
width: auto;
margin: 0px;
}
.scatterplot-display .controls .left {
float: left;
}
.scatterplot-display .controls .pagination {
display: inline-block;
margin: 0px;
}
.scatterplot-display .controls .data-prev-next {
display: inline-block;
margin: 0px 4px 0px 0px;
}
.scatterplot-display .controls .pagination-container {
display: inline-block;
overflow: auto;
max-width: 256px;
/*very tweaky*/
margin: 0px 8px 0px 0px;
height: 27px;
padding-top: 5px;
}
.scatterplot-display .controls .pagination-container a {
display: inline;
/* WTH, bootstrap? */
position: static;
float: none;
/* up from 4px -> 5px */
padding: 5px 10px 5px 10px;
}
.scatterplot-display .controls .right {
float: right;
margin-bottom: 4px;
}
.scatterplot-display .controls p {
display: inline-block;
margin: 0px 4px 0px 4px;
/*to better match the buttons*/
vertical-align: middle;
line-height: 24px;
}
.scatterplot-display button.rerender-btn {
margin-left: 4px;
}
.scatterplot-display button.stats-toggle-btn {
margin-left: 4px;
}
/* -------------------------------------------- chart area */
#chart-holder {
overflow: auto;
margin-left: 8px;
svg.scatterplot {
border: 1px solid lightgrey;
border-radius: 3px;
}
svg .grid-line {
svg.scatterplot .grid-line {
fill: none;
stroke: lightgrey;
stroke-opacity: 0.5;
stroke-opacity: 0.2;
shape-rendering: crispEdges;
stroke-dasharray: 3, 3;
}
svg .axis path, svg .axis line {
svg.scatterplot .axis path,
svg.scatterplot .axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
svg .axis text {
font-family: monospace;
font-size: 12px;
svg.scatterplot .axis text {
font-size: 9px;
}
svg #x-axis-label, svg #y-axis-label {
svg.scatterplot .axis-label {
font-family: sans-serif;
font-size: 10px;
font-size: 13px;
}
svg .glyph {
svg.scatterplot .glyph {
stroke: none;
fill: black;
fill-opacity: 0.2;
File diff suppressed because one or more lines are too long
@@ -0,0 +1,5 @@
onmessage = function( event ){
importScripts( 'numeric-column-stats.js' );
postMessage( numericColumnStats( event.data.data, event.data.keys ) );
self.close();
};