mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
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:
@@ -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();
|
||||
};
|
||||
Reference in New Issue
Block a user