Commit 33c99515 authored by Jan Pöppel's avatar Jan Pöppel
Browse files

Merge branch 'master' into 'nestedDataKeys'

# Conflicts:
#   webviz/static/src/index.js
parent 7c73f4ed
......@@ -27,7 +27,8 @@ try:
"y2": [random.random() for i in range(20)],
"x": ["a","b","c","d"],
"d": [random.random() for i in range(4)],
"checked": {m: True if random.random()>0.5 else False for m in ["Expl1", "Expl2", "Expl3"]}
"checked": {m: True if random.random()>0.5 else False for m in ["Expl1", "Expl2", "Expl3"]},
"nested": {"t": random.random(), "t2": 0.2}
}
idx = random.randint(0,4)
......
import React, { PureComponent } from 'react';
class KeyBoardVis extends PureComponent {
render() {
var {directionProbs} = this.props;
return (
<div className={"arrowBox"}>
<div className={"arrowItem"}></div>
<div className={"arrowItem"}>&uarr; {parseFloat(directionProbs["Up"]).toFixed(3)}</div>
<div className={"arrowItem"}></div>
<div className={"arrowItem"}>&larr; {parseFloat(directionProbs["Left"]).toFixed(3)}</div>
<div className={"arrowItem"}>&darr; {parseFloat(directionProbs["Down"]).toFixed(3)}</div>
<div className={"arrowItem"}>&rarr; {parseFloat(directionProbs["Right"]).toFixed(3)}</div>
</div>
)
}
}
export default class ActionPrediction extends PureComponent {
render() {
var { actionPredictions } = this.props;
var elements = [];
for (var key in actionPredictions) {
elements.push(<div>
{key}:<KeyBoardVis directionProbs={actionPredictions[key]}/>
</div>)
}
return (
<div className={"flex"}>
{elements}
</div>
)
}
}
\ No newline at end of file
import React, { Component } from 'react';
//import PropTypes from 'prop-types';
import io from "socket.io-client";
import Chart from "./chart";
import TextOutput from "./textOutput";
import DashboardCtrl from "./dashboardCtrl";
import GridLayout from 'react-grid-layout';
......@@ -77,10 +71,6 @@ export default class Dashboard extends Component {
this.setState(config);
}
// componentDidMount() {
// this.socketConnection = new SocketConnection();
// }
closeConfig() {
this.setState({
moduleConfig: null
......@@ -104,9 +94,7 @@ export default class Dashboard extends Component {
var newTile = {
id: this.state.tileIDCounter,
config: JSON.parse(JSON.stringify(config)),
// title: config.moduleConfig.title,
type: type,
// dataSources: JSON.parse(JSON.stringify(config.dataConfig))
}
var newLayout = this.state.layout;
......
......@@ -94,8 +94,9 @@ class ExperimentView extends Component {
}
render() {
let { bgname, fgname, width, height, conditionName, pos, map, traj, visibles, beliefs } = this.props;
let { bgname, fgname, width, height, conditionName, pos, map, traj, visibles, beliefs, aggregates } = this.props;
console.log("experiment view props: ", this.props);
var renderAggregates = aggregates && aggregates.length > 0;
return (
<div>
<div className="condition">{conditionName}</div>
......@@ -112,9 +113,10 @@ class ExperimentView extends Component {
visiblesUpdated={this.state.visiblesUpdated}
beliefs={beliefs}
traj={traj}
aggregates={aggregates}
pos={pos}
/>
<div className={"controls flex"}>
<div className={"flex"}>
<div>
Show Targets:
<input type="checkbox" defaultChecked={this.state.showTargets} checked={this.state.showTargets} onChange={this.onChangeShowTargets} />
......@@ -137,7 +139,11 @@ class ExperimentView extends Component {
</div>
{this.props.traj ? <div>
Show Path:
<input type="checkbox" defaultChecked={this.state.showPath} checked={this.state.showPath} onChange={this.onChangeShowPath} />
<input type="checkbox" defaultChecked={this.state.showPath} checked={this.state.showPath} onChange={this.onChangeShowPath} disabled={renderAggregates}/>
</div> : ""}
<div>
Show Complete Path:
<input type="checkbox" defaultChecked={this.props.completePath} checked={this.props.completePath} onChange={this.props.onChangeCompletePath} />
</div> : ""}
{this.props.beliefs ? <div>
Show Visible area:
......
import { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import io from "socket.io-client";
import {getNestedData} from '../utils';
function mapDispatchToProps(dispatch) {
......@@ -66,8 +67,10 @@ export default class SocketConnection extends Component {
for (var i=0; i<channelConfig.length; i++) {
let dataKey = channelConfig[i].val;
let shouldLog = channelConfig[i].log;
if (dataKey in msg) {
this._updateStore(channel, dataKey, msg[dataKey], shouldLog)
let payload = getNestedData(msg, dataKey)
if (payload) {
this._updateStore(channel, dataKey, payload, shouldLog)
} else {
//Ignore
}
......
......@@ -19,7 +19,9 @@ export default class ModuleSelection extends Component {
<div>
<div className="module-selection">
{moduleList.map( (m) => {
return(<div key={m.id} className={classNames("module", {"selected": m.id === this.state.selectedID})} onClick={ (e) => {this.setState({selectedID: m.id})}}>
return(<div key={m.id} className={classNames("module", {"selected": m.id === this.state.selectedID})}
onClick={ (e) => {this.setState({selectedID: m.id})}}
onDoubleClick={ (e) => {this.props.addModule(m.id)}}>
<img src={m.img} alt={"Test"} width={80}/>
<span>{m.name}</span>
</div>)
......
import React, { Component } from 'react';
import CanvasGridworld from "./gridworld"
import CustomSlider from "./slider"
import { BarPlot } from './plots';
import {VerticalBarSeries, DiscreteColorLegend} from "react-vis";
import ListSelection from './listSelection';
import continuousColorLegend from 'react-vis/dist/legends/continuous-color-legend';
import CheckboxList from './checkboxList';
class StudyReview extends Component {
constructor (props, context) {
super(props, context)
let startMap = "";
for (var key in props.maps) {
startMap = key;
break;
}
this.state = {
curMap: startMap,
collapse: false,
stepNr: 0,
normalize: false,
dataSrc: {}
}
this.onChangeCollapse = this.onChangeCollapse.bind(this);
this.onChangeDataSource = this.onChangeDataSource.bind(this);
this.onSliderChange = this.onSliderChange.bind(this);
this.onMapSelect = this.onMapSelect.bind(this);
this.prevQP = this.prevQP.bind(this);
this.nextQP = this.nextQP.bind(this);
this.curQP = null;
}
onChangeCollapse() {
this.setState({
normalize: !this.state.normalize
})
}
onSliderChange(value) {
this.setState({stepNr: value})
}
onMapSelect(e) {
this.setState({curMap: e.target.value})
}
prevQP() {
let answersC = this.props.answers["Sampling"]
let curQP = this.state.stepNr;
while (curQP > 0) {
curQP -= 1;
if (curQP in answersC[this.state.curMap]) {
this.setState({stepNr: curQP});
break;
}
}
}
nextQP() {
let answersC = this.props.answers["Sampling"]
let curQP = this.state.stepNr;
while (curQP < this.props.trajs[this.state.curMap].length) {
curQP += 1;
if (curQP in answersC[this.state.curMap]) {
this.setState({stepNr: curQP});
break;
}
}
}
onChangeDataSource(name, newState) {
// let dataSource = e.target.id.slice(0,-5);
let newDataSrc = Object.assign({}, this.state.dataSrc);
newDataSrc[name] = newState;
this.setState({
dataSrc: newDataSrc
})
}
render() {
let {maps, trajs, answers, width, height } = this.props;
const colors = {"C1,C2;C1,C2": "blue",
"C1,C2;C2,C1": "orange",
"C2,C1;C1,C2": "green",
"C2,C1;C2,C1": "purple",
"Study2": "blue",
"Study3": "orange",
"Study3No": "black",
"twg": "green",
"tw": "purple",
"tw2": "lightblue" ,
"Sampling":"red"
}
let curMap = this.state.curMap;
let map = maps[curMap];
let traj = trajs[curMap];
let curStep = this.state.stepNr;
let pos = trajs[curMap][curStep];
let bars = [];
let barsControlled = [];
let answersC_Controlled = answers["collapsed_control"];
let answersI_Controlled = answers["individual_control"];
const answerOrder = ["R", "B", "O", "Y", "U", "Yes", "No"];
this.curQP = curStep;
var normalize = this.state.normalize || this.state.dataSrc["twg"] || this.state.dataSrc["tw"];
for (var dataSrc in this.state.dataSrc) {
if (this.state.dataSrc[dataSrc]) {
let vals = answers[dataSrc]
let data = [];
if (vals[curMap][this.curQP]) {
var norm = 0;
var normBelief = 0;
if (normalize) {
for (var i=0;i<answerOrder.length; i++) {
if (vals[curMap][this.curQP][answerOrder[i]]) {
if (answerOrder[i] === "Yes" || answerOrder[i] === "No") {
normBelief += vals[curMap][this.curQP][answerOrder[i]];
} else {
norm += vals[curMap][this.curQP][answerOrder[i]];
}
}
}
} else {
norm = 1;
normBelief = 1;
}
for (var i=0;i<answerOrder.length; i++) {
var answer = answerOrder[i];
if (answer in vals[curMap][this.curQP]) {
if (answer === "Yes" || answer === "No") {
data.push({"x": answer, "y": vals[curMap][this.curQP][answer]/normBelief})
} else {
data.push({"x": answer, "y": vals[curMap][this.curQP][answer]/norm})
}
}
}
}
if (data.length > 0) {
bars.push(<VerticalBarSeries key={dataSrc}
data={data}
color={colors[dataSrc]} />)
}
}
}
var data = [];
if (answersC_Controlled[curMap][this.curQP]) {
for (var i=0;i<answerOrder.length; i++) {
var answer = answerOrder[i];
if (answer in answersC_Controlled[curMap][this.curQP]) {
data.push({"x": answer, "y": answersC_Controlled[curMap][this.curQP][answer]})
}
}
}
if (data.length > 0) {
barsControlled.push(<VerticalBarSeries key={"collapsed"}
data={data}
color={"red"} />)
}
let barsIControlled = [];
for (var variant in answersI_Controlled) {
console.log("variant2: ", variant)
if (variant === "null") {
continue;
}
let data = [];
if (answersI_Controlled[variant][curMap][this.curQP]) {
for (var i=0;i<answerOrder.length; i++) {
var answer = answerOrder[i];
if (answer in answersI_Controlled[variant][curMap][this.curQP]) {
data.push({"x": answer, "y": answersI_Controlled[variant][curMap][this.curQP][answer]})
}
}
}
if (data.length > 0) {
barsIControlled.push(<VerticalBarSeries key={variant}
data={data}
color={colors[variant]} />)
}
}
return (
<div>
<div className="condition">{"Study Results"}</div>
<div className={"slider-controls"}>
<CanvasGridworld width={width/2} height={height}
map={map} bgname={"bg"}
showTargets={true}
showTrueColor={true}
showPath={true}
traj={traj.slice(0, curStep+1)}
pos={pos}
/>
<div>
<h3>Controlled:</h3>
<div className={"slider-controls"}>
{barsIControlled.length > 0 ? <BarPlot width={width/4} height={height/4} bars={barsControlled}/> : ""}
{barsIControlled.length > 0 ? <BarPlot width={width/4} height={height/4} bars={barsIControlled}/> : ""}
</div>
</div>
</div>
<div className={"flex"}>
<div>
<ListSelection name={"Select Map"} options1={Object.keys(answers["Sampling"])} onChange1={this.onMapSelect} selected1={Object.keys(answers["Sampling"])[0]} />
</div>
<div>
<button onClick={this.prevQP} >{"<"}</button>
<button onClick={this.nextQP} >{">"}</button>
</div>
<div>
Normalize:
<input type="checkbox" defaultChecked={this.state.normalize} checked={this.state.normalize} onChange={this.onChangeCollapse} />
</div>
</div>
<CheckboxList boxes={["Study2","Study3","Study3No", "Sampling","twg","tw","tw2"]} callback={this.onChangeDataSource} />
<CustomSlider value={curStep} min={0} max={traj.length-1} onSliderChange={this.onSliderChange}/>
{bars.length > 0 ? <DiscreteColorLegend
orientation="horizontal"
height={80}
items={[
{"title": "Study2", "color": colors["Study2"]},
{"title": "Study3", "color": colors["Study3"]},
{"title": "Study3No", "color": colors["Study3No"]},
{"title": "Sampling", "color": colors["Sampling"]},
{"title": "twg", "color": colors["twg"]},
{"title": "tw", "color": colors["tw"]},
{"title": "tw2", "color": colors["tw2"]},
]}
/>: ""}
<div className={"slider-controls"}>
{bars.length > 0 ? <BarPlot width={width} height={height/4} bars={bars} yDomain={normalize ? [0,1]: null}/> : ""}
</div>
</div>
)
}
}
export default StudyReview;
\ No newline at end of file
export function updateState(state, keys, value) {
// A function to update a nested state, where the key is given as a list of
// object keys or array indices.
var newState;
if (Object.prototype.toString.call(state) == '[object Array]') {
newState = [...state];
......@@ -15,4 +17,26 @@ export function updateState(state, keys, value) {
return value;
}
}
export function getNestedData(container, key) {
// Key may be something like "data.messages.0.name", i.e. a mix
// of dictionary keys and list indices, or directly a list of keys ["data","messages",0,"name"]
// This function will try to recursively apply the key to the container
// and return the final value, if present, otherwise undefined
let keyArr = []
if (typeof(key) === "string") {
keyArr = key.split(".");
} else {
keyArr = key;
}
let [head, ...tail] = keyArr;
if (tail.length === 0) {
return container[head]
} else {
return getNestedData(container[head], tail)
}
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment