started to add a histogram on key.
This commit is contained in:
1 parent
cfe5340961
commit
082157bc5f
8 files changed
+148
-4
No files matched your search
+3
-1
@@ -22,6 +22,8 @@
|
|||||||
"codemirror": "~3.19.0",
|
"codemirror": "~3.19.0",
|
||||||
"angular-ui-codemirror": "~0.1.1",
|
"angular-ui-codemirror": "~0.1.1",
|
||||||
"spin.js": "~2.0.1",
|
"spin.js": "~2.0.1",
|
||||||
"angular-spinner": "~0.4.0"
|
"angular-spinner": "~0.4.0",
|
||||||
|
"highcharts-ng": "~0.0.6",
|
||||||
|
"highcharts": "~3.0.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,10 +4,17 @@ humanValueOfStatisticalAbreviation =
|
|||||||
mean: "mean"
|
mean: "mean"
|
||||||
std: "standard deviation"
|
std: "standard deviation"
|
||||||
var: "variance"
|
var: "variance"
|
||||||
|
min: "minimum"
|
||||||
|
max: "maximum"
|
||||||
|
n: "number of documents"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getAxisLabel = (min, stepSize, numberOfBins) ->
|
||||||
|
return (min + 0.5 * stepSize + i * stepSize for i in [0... numberOfBins])
|
||||||
|
|
||||||
root.controllers.controller('keyStatCtrl', ['$scope', '$routeParams', 'util', ($scope, $routeParams, util) ->
|
root.controllers.controller('keyStatCtrl', ['$scope', '$routeParams', 'util', ($scope, $routeParams, util) ->
|
||||||
$scope.name = "didier!"
|
$scope.name = $routeParams.key
|
||||||
$scope.stats = []
|
$scope.stats = []
|
||||||
|
|
||||||
url = "/api/#{ $routeParams.server }/#{ $routeParams.database }/#{ $routeParams.collection }"
|
url = "/api/#{ $routeParams.server }/#{ $routeParams.database }/#{ $routeParams.collection }"
|
||||||
@@ -18,5 +25,25 @@ root.controllers.controller('keyStatCtrl', ['$scope', '$routeParams', 'util', ($
|
|||||||
$scope.stats.push({name: humanValueOfStatisticalAbreviation[key], value: val })
|
$scope.stats.push({name: humanValueOfStatisticalAbreviation[key], value: val })
|
||||||
)
|
)
|
||||||
|
|
||||||
|
$scope.chartConfig =
|
||||||
|
options:
|
||||||
|
chart:
|
||||||
|
type: 'column'
|
||||||
|
plotOptions:
|
||||||
|
column:
|
||||||
|
groupPadding: 0
|
||||||
|
pointPadding: 0
|
||||||
|
borderWidth: 0
|
||||||
|
xAxis:
|
||||||
|
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
|
||||||
|
title:
|
||||||
|
text: 'Distribution'
|
||||||
|
loading: false
|
||||||
|
series: [{
|
||||||
|
data: [10, 15, 12, 8, 7, 4, 12, 12, 9, 11],
|
||||||
|
name: $routeParams.key
|
||||||
|
color: '#008CBA'
|
||||||
|
}]
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -5,6 +5,7 @@ angular.module('vulture', [
|
|||||||
'ngRoute'
|
'ngRoute'
|
||||||
'ui.codemirror'
|
'ui.codemirror'
|
||||||
'angularSpinner'
|
'angularSpinner'
|
||||||
|
'highcharts-ng'
|
||||||
'leaflet-directive'
|
'leaflet-directive'
|
||||||
'vulture.filters'
|
'vulture.filters'
|
||||||
'vulture.services'
|
'vulture.services'
|
||||||
|
|||||||
@@ -56,6 +56,8 @@
|
|||||||
<script src="bower_components/spin.js/spin.js"></script>
|
<script src="bower_components/spin.js/spin.js"></script>
|
||||||
<script src="bower_components/angular-spinner/angular-spinner.js"></script>
|
<script src="bower_components/angular-spinner/angular-spinner.js"></script>
|
||||||
<script type="text/javascript" src="bower_components/angular-ui-codemirror/ui-codemirror.js"></script>
|
<script type="text/javascript" src="bower_components/angular-ui-codemirror/ui-codemirror.js"></script>
|
||||||
|
<script type="text/javascript" src="bower_components/highcharts/highcharts.js"></script>
|
||||||
|
<script type="text/javascript" src="bower_components/highcharts-ng/dist/highcharts-ng.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,4 +8,8 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<highchart id="chart1" config="chartConfig" class="columns large-12"></highchart>
|
||||||
</div>
|
</div>
|
||||||
@@ -96,7 +96,6 @@ func serveApi(router *mux.Router) {
|
|||||||
router.Handle("/{server}/{database}/{collection}/query/{query}/idx/{index:[0-9]+}", ApiHandler(getDocumentByQueryAndIndex))
|
router.Handle("/{server}/{database}/{collection}/query/{query}/idx/{index:[0-9]+}", ApiHandler(getDocumentByQueryAndIndex))
|
||||||
router.Handle("/{server}/{database}/{collection}/query/{query}/all", ApiHandler(getAllDocuments))
|
router.Handle("/{server}/{database}/{collection}/query/{query}/all", ApiHandler(getAllDocuments))
|
||||||
|
|
||||||
// getAllDocuments
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMuxRouter() http.Handler {
|
func createMuxRouter() http.Handler {
|
||||||
|
|||||||
@@ -11,10 +11,55 @@ const initialLength int = 1024
|
|||||||
const verySmall float64 = -100000
|
const verySmall float64 = -100000
|
||||||
const veryBig float64 = 100000
|
const veryBig float64 = 100000
|
||||||
|
|
||||||
|
type Histogram struct {
|
||||||
|
Min float64 `json:"min"`
|
||||||
|
StepSize float64 `json:"step_size"`
|
||||||
|
Values []int `json:"values"`
|
||||||
|
}
|
||||||
|
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
Mean float64 `json:"mean"`
|
Mean float64 `json:"mean"`
|
||||||
Var float64 `json:"var"`
|
Var float64 `json:"var"`
|
||||||
Std float64 `json:"std"`
|
Std float64 `json:"std"`
|
||||||
|
Min float64 `json:"min"`
|
||||||
|
Max float64 `json:"max"`
|
||||||
|
N int `json:"n"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Stats) findMinHistogramValue() float64 {
|
||||||
|
return math.Max(this.Min, this.Mean-3*this.Std)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Stats) findMaxHistogramValue() float64 {
|
||||||
|
return math.Min(this.Max, this.Mean+3*this.Std)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Stats) findSuitableBinForDatum(min, step, val float64) int {
|
||||||
|
var i int
|
||||||
|
var act float64 = min
|
||||||
|
for i = 0; act < val; act += step {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return i - 1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Stats) MakeHistogram(numberOfBins int, dataChannel chan float64, outputChannel chan *Histogram) {
|
||||||
|
min := this.findMinHistogramValue()
|
||||||
|
max := this.findMaxHistogramValue()
|
||||||
|
step := (max - min) / float64(numberOfBins)
|
||||||
|
hist := make([]int, numberOfBins)
|
||||||
|
|
||||||
|
for datum := range dataChannel {
|
||||||
|
if datum < min || datum > max {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
i := this.findSuitableBinForDatum(min, step, datum)
|
||||||
|
hist[i]++
|
||||||
|
}
|
||||||
|
|
||||||
|
outputChannel <- &Histogram{min, step, hist}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type StatAggregator struct {
|
type StatAggregator struct {
|
||||||
@@ -50,7 +95,9 @@ func (this *StatAggregator) getFinalStats() *Stats {
|
|||||||
stats.Mean = this.sum / float64(this.n)
|
stats.Mean = this.sum / float64(this.n)
|
||||||
stats.Var = this.sumOfTheSquares/float64(this.n) - stats.Mean*stats.Mean
|
stats.Var = this.sumOfTheSquares/float64(this.n) - stats.Mean*stats.Mean
|
||||||
stats.Std = math.Sqrt(stats.Var)
|
stats.Std = math.Sqrt(stats.Var)
|
||||||
|
stats.Min = this.min
|
||||||
|
stats.Max = this.max
|
||||||
|
stats.N = this.n
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,8 @@ func TestAddStatsBasic(t *testing.T) {
|
|||||||
func TestGetFinalStats(t *testing.T) {
|
func TestGetFinalStats(t *testing.T) {
|
||||||
s := NewStatAggregator()
|
s := NewStatAggregator()
|
||||||
s.sumOfTheSquares = 5000
|
s.sumOfTheSquares = 5000
|
||||||
|
s.max = 900
|
||||||
|
s.min = -900
|
||||||
s.sum = 200
|
s.sum = 200
|
||||||
s.n = 10
|
s.n = 10
|
||||||
stats := s.getFinalStats()
|
stats := s.getFinalStats()
|
||||||
@@ -49,4 +51,64 @@ func TestGetFinalStats(t *testing.T) {
|
|||||||
if stats.Std != 10. {
|
if stats.Std != 10. {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
|
if stats.Min != -900 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if stats.Max != 900 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if stats.N != 10 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMinHistogramValue(t *testing.T) {
|
||||||
|
stats := &Stats{
|
||||||
|
Mean: 10,
|
||||||
|
Std: 2,
|
||||||
|
Min: 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
if stats.findMinHistogramValue() != 4 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.Min = 7
|
||||||
|
if stats.findMinHistogramValue() != 7 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindMaxHistogramValue(t *testing.T) {
|
||||||
|
stats := &Stats{
|
||||||
|
Mean: 10,
|
||||||
|
Std: 2,
|
||||||
|
Max: 22,
|
||||||
|
}
|
||||||
|
|
||||||
|
if stats.findMaxHistogramValue() != 16 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
stats.Max = 14
|
||||||
|
if stats.findMaxHistogramValue() != 14 {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindSuitableBinForDatum(t *testing.T) {
|
||||||
|
stats := new(Stats)
|
||||||
|
if bin := stats.findSuitableBinForDatum(-4, 1, -3.2); bin != 0 {
|
||||||
|
t.Error("wrong bin: ", bin)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bin := stats.findSuitableBinForDatum(-4, 1, -2.2); bin != 1 {
|
||||||
|
t.Error("wrong bin: ", bin)
|
||||||
|
}
|
||||||
|
|
||||||
|
if bin := stats.findSuitableBinForDatum(-4, 1, 10.1); bin != 14 {
|
||||||
|
t.Error("wrong bin: ", bin)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user