Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
vig
Sublinear Algorithms for VA
pseudo
Commits
65a2a2ee
Commit
65a2a2ee
authored
Oct 30, 2020
by
Kruyff,D.L.W. (Dylan)
Browse files
Cleaned up code
parent
e3815982
Changes
15
Hide whitespace changes
Inline
Side-by-side
AngularApp/prototype/src/app/api.service.ts
View file @
65a2a2ee
...
...
@@ -5,6 +5,22 @@ export interface RawData {
values
:
number
[];
}
export
interface
LshData
{
candidates
:
number
[];
distances
:
number
[];
hash_functions
:
number
[][][][];
parameters
?:
number
[];
}
export
interface
TableInfoData
{
prototypes
:
{
average
:
number
[];
min
:
number
[];
max
:
number
[];
}[];
distances
:
number
[][];
}
@
Injectable
({
providedIn
:
'
root
'
})
...
...
@@ -15,13 +31,10 @@ export class ApiService {
// Read input data
async
readFile
():
Promise
<
RawData
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/read-data
'
);
const
temp
=
await
response
.
json
();
const
index
=
temp
.
index
;
const
values
=
temp
.
values
;
return
{
index
,
values
};
return
await
response
.
json
();
}
// Split data into windows and normalize
// Split data into windows and normalize
async
createWindows
(
parameters
):
Promise
<
any
>
{
const
postData
=
{
parameters
};
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/create-windows
'
,
{
...
...
@@ -32,11 +45,10 @@ export class ApiService {
},
body
:
JSON
.
stringify
(
postData
)
});
return
await
response
.
json
();
}
//
Generate LSH-tables by hashing each window
async
i
nitial
ize
(
query
):
Promise
<
any
>
{
//
Calculate parameters for LSH + find candidates using LSH
async
lshI
nitial
(
query
):
Promise
<
LshData
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/initialize
'
,
{
method
:
'
POST
'
,
headers
:
{
...
...
@@ -48,8 +60,8 @@ export class ApiService {
return
await
response
.
json
();
}
//
Update
async
u
pdate
(
query
,
hashFunctions
,
parameters
):
Promise
<
any
>
{
//
Find candidates using LSH with weights
async
lshU
pdate
(
query
,
hashFunctions
,
parameters
):
Promise
<
LshData
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/update
'
,
{
method
:
'
POST
'
,
headers
:
{
...
...
@@ -61,7 +73,8 @@ export class ApiService {
return
await
response
.
json
();
}
async
getQueryWindow
(
window
)
{
// Get query window based on windows labeled correct
async
getQueryWindow
(
window
):
Promise
<
number
[]
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/query
'
,
{
method
:
'
POST
'
,
headers
:
{
...
...
@@ -73,7 +86,8 @@ export class ApiService {
return
await
response
.
json
();
}
async
getWindow
(
indices
:
number
[])
{
// Get data of a window by indices
async
getWindowByIndices
(
indices
:
number
[]):
Promise
<
number
[][]
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/window
'
,
{
method
:
'
POST
'
,
headers
:
{
...
...
@@ -85,8 +99,8 @@ export class ApiService {
return
await
response
.
json
();
}
async
get
AverageWindows
(
windows
):
Promise
<
any
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/
average
'
,
{
async
get
TableInfo
(
windows
):
Promise
<
TableInfoData
>
{
const
response
=
await
fetch
(
'
http://127.0.0.1:5000/
table-info
'
,
{
method
:
'
POST
'
,
headers
:
{
'
Accept
'
:
'
application/json
'
,
...
...
AngularApp/prototype/src/app/labeling-window/labeling-window.component.html
View file @
65a2a2ee
<div
class=
"container"
>
<div
*ngIf=
"
candidates
"
class=
"subplot-container"
>
<div
*ngIf=
"
show
"
class=
"subplot-container"
>
<div
class=
"subplot"
*ngFor=
"let subplot of subplots"
>
<plotly-plot
[data]=
"subplot.data"
[layout]=
"subplot.layout"
></plotly-plot>
<div
class=
"button-holder"
>
...
...
@@ -10,8 +10,8 @@
</div>
</div>
<div
class=
"button-holder"
>
<button
*ngIf=
"
candidates
"
(click)=
"updateQuery()"
class=
"train-button"
>
Query
</button>
<button
*ngIf=
"
candidates
"
(click)=
"train()"
class=
"train-button"
>
Train
</button>
<button
*ngIf=
"
show
"
(click)=
"updateQuery()"
class=
"train-button"
>
Query
</button>
<button
*ngIf=
"
show
"
(click)=
"train()"
class=
"train-button"
>
Train
</button>
</div>
</div>
...
...
AngularApp/prototype/src/app/labeling-window/labeling-window.component.ts
View file @
65a2a2ee
import
{
Component
,
OnInit
}
from
'
@angular/core
'
;
import
{
Cach
eService
}
from
'
../
cach
e.service
'
;
import
{
Stat
eService
}
from
'
../
stat
e.service
'
;
@
Component
({
selector
:
'
app-labeling-window
'
,
...
...
@@ -7,25 +7,26 @@ import {CacheService} from '../cache.service';
styleUrls
:
[
'
./labeling-window.component.css
'
]
})
export
class
LabelingWindowComponent
implements
OnInit
{
public
topk
;
public
topk
:
number
[]
;
public
subplots
=
[];
public
labels
:
boolean
[]
=
[];
private
k
=
12
;
constructor
(
private
s
ervice
:
Cach
eService
)
{
}
constructor
(
private
s
tate
:
Stat
eService
)
{
}
ngOnInit
():
void
{
this
.
s
ervic
e
.
onNewTable
s
.
subscribe
(()
=>
{
this
.
getTopKSimilar
();
}
);
this
.
s
tat
e
.
onNewTable
.
subscribe
(()
=>
this
.
showSamples
()
);
}
public
train
()
{
this
.
service
.
labels
=
Object
.
assign
({},
this
.
service
.
labels
,
this
.
labels
);
this
.
service
.
update
();
async
train
()
{
this
.
state
.
labels
=
Object
.
assign
({},
this
.
state
.
labels
,
this
.
labels
);
await
this
.
state
.
getQueryWindow
(
this
.
state
.
labels
);
await
this
.
state
.
update
();
}
publi
c
updateQuery
()
{
this
.
s
ervic
e
.
labels
=
Object
.
assign
({},
this
.
s
ervic
e
.
labels
,
this
.
labels
);
this
.
s
ervic
e
.
getQueryWindow
(
this
.
s
ervic
e
.
labels
);
asyn
c
updateQuery
()
{
this
.
s
tat
e
.
labels
=
Object
.
assign
({},
this
.
s
tat
e
.
labels
,
this
.
labels
);
await
this
.
s
tat
e
.
getQueryWindow
(
this
.
s
tat
e
.
labels
);
}
public
labelCorrect
(
index
:
number
)
{
...
...
@@ -42,14 +43,10 @@ export class LabelingWindowComponent implements OnInit {
this
.
labels
[
index
]
=
false
;
}
async
getTopKSimilar
()
{
this
.
topk
=
this
.
service
.
candidates
.
slice
(
0
,
12
);
await
this
.
createPlots
();
}
async
createPlots
()
{
async
showSamples
()
{
this
.
topk
=
this
.
state
.
lshData
.
candidates
.
slice
(
0
,
this
.
k
);
this
.
subplots
=
[];
const
values
=
await
this
.
s
ervic
e
.
getWindow
(
this
.
topk
);
const
values
=
await
this
.
s
tat
e
.
getWindow
(
this
.
topk
);
this
.
topk
.
forEach
((
index
,
i
)
=>
{
this
.
subplots
.
push
(
{
...
...
@@ -90,7 +87,7 @@ export class LabelingWindowComponent implements OnInit {
});
}
public
get
candidates
()
{
return
this
.
s
ervice
.
candidates
;
public
get
show
()
{
return
!!
this
.
s
tate
.
lshData
;
}
}
AngularApp/prototype/src/app/labels/labels.component.ts
View file @
65a2a2ee
import
{
Component
,
OnInit
}
from
'
@angular/core
'
;
import
{
Cach
eService
}
from
'
../
cach
e.service
'
;
import
{
Stat
eService
}
from
'
../
stat
e.service
'
;
@
Component
({
selector
:
'
app-labels
'
,
...
...
@@ -10,24 +10,25 @@ export class LabelsComponent implements OnInit {
public
goodLabels
=
[];
public
badLabels
=
[];
constructor
(
private
service
:
CacheService
)
{
}
constructor
(
private
state
:
StateService
)
{
}
ngOnInit
():
void
{
this
.
s
ervic
e
.
onNewLabels
.
subscribe
(()
=>
{
this
.
createSubplots
();
});
this
.
s
tat
e
.
onNewLabels
.
subscribe
(()
=>
{
this
.
createSubplots
();
});
}
async
createSubplots
()
{
this
.
goodLabels
=
[];
this
.
badLabels
=
[];
const
windows
=
await
this
.
s
ervic
e
.
getWindow
(
Object
.
keys
(
this
.
s
ervic
e
.
labels
).
map
(
Number
));
Object
.
keys
(
this
.
s
ervic
e
.
labels
).
forEach
((
key
,
i
)
=>
{
const
labelWindows
:
number
[][]
=
await
this
.
s
tat
e
.
getWindow
(
Object
.
keys
(
this
.
s
tat
e
.
labels
).
map
(
Number
));
Object
.
keys
(
this
.
s
tat
e
.
labels
).
forEach
((
key
,
i
)
=>
{
const
index
=
Number
(
key
);
const
plot
=
{
index
,
data
:
[{
x
:
[...
Array
(
this
.
s
ervic
e
.
windowSize
).
keys
()],
y
:
w
indows
[
i
],
x
:
[...
Array
(
this
.
s
tat
e
.
windowSize
).
keys
()],
y
:
labelW
indows
[
i
],
type
:
'
line
'
}],
layout
:
{
...
...
@@ -51,7 +52,7 @@ export class LabelsComponent implements OnInit {
}
}
};
if
(
this
.
s
ervic
e
.
labels
[
key
])
{
if
(
this
.
s
tat
e
.
labels
[
key
])
{
this
.
goodLabels
.
push
(
plot
);
}
else
{
this
.
badLabels
.
push
(
plot
);
...
...
AngularApp/prototype/src/app/main/main.component.ts
View file @
65a2a2ee
import
{
Component
}
from
'
@angular/core
'
;
import
{
Cach
eService
}
from
'
../
cach
e.service
'
;
import
{
Stat
eService
}
from
'
../
stat
e.service
'
;
@
Component
({
selector
:
'
app-main
'
,
...
...
@@ -8,18 +8,18 @@ import {CacheService} from '../cache.service';
})
export
class
MainComponent
{
constructor
(
private
s
ervice
:
Cach
eService
)
{
constructor
(
private
s
tate
:
Stat
eService
)
{
}
changeTab
(
tab
)
{
this
.
s
ervic
e
.
currentTab
=
tab
.
index
;
this
.
s
tat
e
.
currentTab
=
tab
.
index
;
}
public
get
greyOut
()
{
return
this
.
s
ervic
e
.
querySelectionMode
;
return
this
.
s
tat
e
.
querySelectionMode
;
}
public
get
loadingProgress
():
number
{
return
this
.
s
ervic
e
.
loadingProgress
;
return
this
.
s
tat
e
.
loadingProgress
;
}
}
AngularApp/prototype/src/app/overview-window/overview-window.component.ts
View file @
65a2a2ee
import
{
Component
,
OnInit
}
from
'
@angular/core
'
;
import
{
Cach
eService
}
from
'
../
cach
e.service
'
;
import
{
Stat
eService
}
from
'
../
stat
e.service
'
;
import
zingchart
from
'
zingchart/es6
'
;
@
Component
({
...
...
@@ -9,7 +9,7 @@ import zingchart from 'zingchart/es6';
})
export
class
OverviewWindowComponent
implements
OnInit
{
public
config
;
public
id
=
"
overview
"
;
public
id
=
'
overview
'
;
public
markers
=
[];
public
series
=
[];
public
goodLabels
=
[];
...
...
@@ -18,25 +18,20 @@ export class OverviewWindowComponent implements OnInit {
public
data
;
public
layout
;
constructor
(
private
s
ervice
:
Cach
eService
)
{
constructor
(
private
s
tate
:
Stat
eService
)
{
}
async
ngOnInit
():
Promise
<
void
>
{
this
.
service
.
onNewData
.
subscribe
(()
=>
this
.
initializePlot
());
this
.
service
.
onNewTables
.
subscribe
(()
=>
{
if
(
this
.
service
.
queryWindow
)
{
this
.
updatePlot
();
}
});
this
.
service
.
onNewSlider
.
subscribe
((
v
)
=>
this
.
updateCandidates
(
v
));
this
.
state
.
onNewData
.
subscribe
(()
=>
this
.
initializePlot
());
this
.
state
.
onNewTable
.
subscribe
(()
=>
this
.
updatePlot
());
}
async
initializePlot
()
{
this
.
state
.
queryWindow
=
undefined
;
this
.
debugClicked
();
this
.
service
.
queryWindow
=
undefined
;
this
.
data
=
[];
for
(
let
i
=
0
;
i
<
this
.
s
ervice
.
rawV
alues
.
length
;
i
++
)
{
this
.
data
.
push
([
this
.
s
ervice
.
rawIndices
[
i
],
this
.
service
.
rawV
alues
[
i
]]);
for
(
let
i
=
0
;
i
<
this
.
s
tate
.
rawData
.
v
alues
.
length
;
i
++
)
{
this
.
data
.
push
([
this
.
s
tate
.
rawData
.
index
[
i
],
this
.
state
.
rawData
.
v
alues
[
i
]]);
}
this
.
series
=
[
{
...
...
@@ -68,19 +63,19 @@ export class OverviewWindowComponent implements OnInit {
zIndex
:
20
,
}];
this
.
config
=
{
type
:
"
mixed
"
,
type
:
'
mixed
'
,
preview
:
{
height
:
"
30px
"
,
position
:
"
0% 100%
"
,
height
:
'
30px
'
,
position
:
'
0% 100%
'
,
'
auto-fit
'
:
true
},
"
plotarea
"
:
{
"
margin-top
"
:
"
10px
"
,
"
margin-bottom
"
:
"
50%
"
plotarea
:
{
'
margin-top
'
:
'
10px
'
,
'
margin-bottom
'
:
'
50%
'
},
scaleX
:
{
zooming
:
true
,
zoomTo
:
[
0
,
this
.
s
ervic
e
.
windowSize
],
zoomTo
:
[
0
,
this
.
s
tat
e
.
windowSize
],
'
auto-fit
'
:
true
,
markers
:
this
.
markers
},
...
...
@@ -89,99 +84,93 @@ export class OverviewWindowComponent implements OnInit {
},
series
:
this
.
series
};
console
.
log
(
"
showing plot
"
);
}
async
updatePlot
()
{
console
.
log
(
'
updating plot
'
);
if
(
!
this
.
service
.
queryWindow
)
{
return
;
}
this
.
goodLabels
=
[];
this
.
badLabels
=
[];
this
.
markers
=
[];
for
(
const
index
in
this
.
s
ervic
e
.
labels
)
{
if
(
this
.
s
ervic
e
.
labels
[
index
])
{
for
(
const
index
in
this
.
s
tat
e
.
labels
)
{
if
(
this
.
s
tat
e
.
labels
[
index
])
{
this
.
goodLabels
.
push
([
Number
(
index
)
*
(
12000
/
6
),
0
]);
this
.
markers
.
push
({
type
:
'
area
'
,
// BUG: For some reason the range values are multiplied by 10
range
:
[
Number
(
index
)
*
(
12000
/
6
)
/
10
,
(
Number
(
index
)
*
(
12000
/
6
)
+
this
.
s
ervic
e
.
windowSize
)
/
10
],
backgroundColor
:
"
#4caf50
"
,
range
:
[
Number
(
index
)
*
(
12000
/
6
)
/
10
,
(
Number
(
index
)
*
(
12000
/
6
)
+
this
.
s
tat
e
.
windowSize
)
/
10
],
backgroundColor
:
'
#4caf50
'
,
});
}
else
{
this
.
badLabels
.
push
([
Number
(
index
)
*
(
12000
/
6
),
0
]);
this
.
markers
.
push
({
type
:
'
area
'
,
// BUG: For some reason the range values are multiplied by 10
range
:
[
Number
(
index
)
*
(
12000
/
6
)
/
10
,
(
Number
(
index
)
*
(
12000
/
6
)
+
this
.
s
ervic
e
.
windowSize
)
/
10
],
backgroundColor
:
"
#f44336
"
,
range
:
[
Number
(
index
)
*
(
12000
/
6
)
/
10
,
(
Number
(
index
)
*
(
12000
/
6
)
+
this
.
s
tat
e
.
windowSize
)
/
10
],
backgroundColor
:
'
#f44336
'
,
});
}
}
this
.
series
[
1
].
values
=
this
.
goodLabels
;
this
.
series
[
2
].
values
=
this
.
badLabels
;
this
.
config
.
scaleX
.
markers
=
this
.
markers
;
zingchart
.
exec
(
"
zingchart-ng-1
"
,
'
setdata
'
,
{
zingchart
.
exec
(
'
zingchart-ng-1
'
,
'
setdata
'
,
{
data
:
this
.
config
});
}
async
updateCandidates
(
sliderIndex
)
{
console
.
log
(
"
Updating chart
"
);
let
candidates
=
[];
for
(
let
i
=
sliderIndex
;
i
<
this
.
service
.
nrOfTables
;
i
++
)
{
candidates
=
candidates
.
concat
(
this
.
service
.
windowSimilarity
[
sliderIndex
.
toString
()]);
}
const
labels
=
[];
const
markers
=
[];
for
(
const
index
of
candidates
)
{
labels
.
push
([
Number
(
index
)
*
(
12000
/
6
),
0
]);
markers
.
push
({
type
:
'
area
'
,
// BUG: For some reason the range values are multiplied by 10
range
:
[
Number
(
index
)
*
(
12000
/
6
)
/
10
,
(
Number
(
index
)
*
(
12000
/
6
)
+
this
.
service
.
windowSize
)
/
10
],
backgroundColor
:
"
#b1a343
"
,
});
}
const
newSeries
=
this
.
config
.
series
.
slice
(
0
,
3
);
newSeries
.
push
({
type
:
'
scatter
'
,
values
:
labels
,
text
:
'
Similar windows
'
,
marker
:
{
backgroundColor
:
'
#b1a343
'
},
zIndex
:
20
,
});
this
.
config
.
series
=
newSeries
;
this
.
config
.
scaleX
.
markers
=
this
.
markers
.
concat
(
markers
);
zingchart
.
exec
(
"
zingchart-ng-1
"
,
'
setdata
'
,
{
data
:
this
.
config
});
// let candidates = [];
// for (let i = sliderIndex; i < this.service.nrOfTables; i++) {
// candidates = candidates.concat(this.service.windowSimilarity[sliderIndex.toString()]);
// }
// const labels = [];
// const markers = [];
// for (const index of candidates) {
// labels.push([Number(index) * (12000 / 6), 0]);
// markers.push({
// type: 'area',
// // BUG: For some reason the range values are multiplied by 10
// range: [Number(index) * (12000 / 6) / 10, (Number(index) * (12000 / 6) + this.state.windowSize) / 10],
// backgroundColor: '#b1a343',
// });
// }
// const newSeries = this.config.series.slice(0, 3);
// newSeries.push({
// type: 'scatter',
// values: labels,
// text: 'Similar windows',
// marker: {
// backgroundColor: '#b1a343'
// },
// zIndex: 20,
// });
// this.config.series = newSeries;
// this.config.scaleX.markers = this.markers.concat(markers);
// zingchart.exec('zingchart-ng-1', 'setdata', {
// data: this.config
// });
}
async
clicked
(
clickData
)
{
if
(
!
this
.
s
ervic
e
.
querySelectionMode
)
{
if
(
!
this
.
s
tat
e
.
querySelectionMode
)
{
return
;
}
this
.
s
ervic
e
.
querySelectionMode
=
false
;
const
xyInformation
=
zingchart
.
exec
(
"
zingchart-ng-1
"
,
'
getxyinfo
'
,
{
this
.
s
tat
e
.
querySelectionMode
=
false
;
const
xyInformation
=
zingchart
.
exec
(
'
zingchart-ng-1
'
,
'
getxyinfo
'
,
{
x
:
clickData
.
x
,
y
:
clickData
.
y
});
const
index
=
Math
.
floor
(
xyInformation
[
0
].
scalenumvalue
/
(
12000
/
6
));
await
this
.
s
ervic
e
.
getQueryWindow
(
index
);
await
this
.
s
ervice
.
i
nitial
();
//
const temp = {};
//
temp[index] = true;
//
this.s
ervic
e.labels = temp;
await
this
.
s
tat
e
.
getQueryWindow
(
index
);
await
this
.
s
tate
.
lshI
nitial
();
const
temp
=
{};
temp
[
index
]
=
true
;
this
.
s
tat
e
.
labels
=
temp
;
}
async
debugClicked
()
{
const
index
=
80503
;
// Math.floor(xyInformation[0].scalenumvalue / (12000 / 6));
await
this
.
s
ervic
e
.
getQueryWindow
(
index
);
await
this
.
s
ervice
.
i
nitial
();
const
index
=
80503
;
await
this
.
s
tat
e
.
getQueryWindow
(
index
);
await
this
.
s
tate
.
lshI
nitial
();
}
zoom
(
p
)
{
...
...
AngularApp/prototype/src/app/progress-view/progress-view.component.ts
View file @
65a2a2ee
import
{
Component
,
OnInit
}
from
'
@angular/core
'
;
import
{
Cach
eService
}
from
'
../
cach
e.service
'
;
import
{
Stat
eService
}
from
'
../
stat
e.service
'
;
import
*
as
d3
from
'
d3
'
;
@
Component
({
...
...
@@ -16,118 +16,18 @@ export class ProgressViewComponent implements OnInit {
private
_sliderValue
=
0
;
constructor
(
private
cache
:
Cach
eService
)
{
}
constructor
(
private
state
:
Stat
eService
)
{
}
ngOnInit
():
void
{
// this.cache.onNewSimilarity.subscribe(() => { this.showgraph(); });
this
.
cache
.
onNewTables
.
subscribe
(()
=>
{
this
.
showgraph
();
});
}
averagePlot
(
averages
)
{
console
.
log
(
averages
);
let
highest
=
0
;
averages
.
map
((
average
,
i
)
=>
{
if
(
average
.
average
.
length
!==
0
&&
i
>
highest
)
{
highest
=
i
;
}
});
let
data
=
averages
.
map
((
average
,
i
)
=>
{
return
[
{
x
:
[...
Array
(
average
.
average
.
length
).
keys
()],
y
:
average
.
average
,
type
:
'
line
'
,
visible
:
i
===
highest
,
line
:
{
color
:
'
red
'
,
width
:
3
}
},
{
x
:
[...
Array
(
average
.
average
.
length
).
keys
()],
y
:
average
.
max
,
type
:
'
scatter
'
,
visible
:
i
===
highest
,
fill
:
null
,
mode
:
'
lines
'
,
line
:
{
color
:
'
rgb(55, 128, 191)
'
,
width
:
3
}
},
{
x
:
[...
Array
(
average
.
average
.
length
).
keys
()],
y
:
average
.
min
,
type
:
'
scatter
'
,
visible
:
i
===
highest
,
fill
:
'
tonexty
'
,
mode
:
'
lines
'
,
line
:
{
color
:
'
rgb(55, 128, 191)
'
,
width
:
3
}
},
];
});
data
=
[].
concat
(...
data
);
const
visibility
=
Array
(
averages
.
length
*
3
).
fill
(
false
);
const
steps
=
[];
for
(
let
i
=
0
;
i
<
this
.
cache
.
nrOfTables
;
i
++
)
{
const
v
=
visibility
.
slice
();
v
[
i
*
3
+
2
]
=
true
;
v
[
i
*
3
+
1
]
=
true
;
v
[
i
*
3
]
=
true
;
steps
.
push
({
label
:
(
100
*
(
i
+
1
)
/
this
.
cache
.
nrOfTables
).
toString
()
+
'
%
'
,
method
:
'
restyle
'
,
args
:
[
'
visible
'
,
v
]
});
}
this
.
_sliderValue
=
highest
;
this
.
data
=
data
;
this
.
layout
=
{
showlegend
:
false
,
hovermode
:
'
closest
'
,
autosize
:
true
,
margin
:
{
l
:
50
,
r
:
30
,
t
:
30
,
pad
:
4