diff --git a/ide/static/js/canvas.js b/ide/static/js/canvas.js index 6359309de..07e95f9be 100644 --- a/ide/static/js/canvas.js +++ b/ide/static/js/canvas.js @@ -23,7 +23,7 @@ class Canvas extends React.Component { this.disableZoom = true; } /* this function returns the layers between a specified output y and input y - it also sneaks in another functionallity of determining which direction is most crowded. this is specifically + it also sneaks in another functionallity of determining which direction is most crowded. this is specifically implemented in this function becuase performance will be very low if implemented in another loop. */ getBetween(net, output, input, x) { var toReturn = []; @@ -42,11 +42,11 @@ class Canvas extends React.Component { } }); var dir = 0; - if (neg>pos) dir = -1; else dir = 1; + if (neg>pos) dir = -1; else dir = 1; return [dir, toReturn]; } /* this function takes in a var of net and pos - net has an array of all the nodes, and pos is a array of x and y coordinates that this + net has an array of all the nodes, and pos is a array of x and y coordinates that this function checks to see whether a line will cut through nodes in the pathway. */ checkIfCuttingLine(net, pos) { @@ -64,7 +64,7 @@ class Canvas extends React.Component { var xcalc = ((y - pos[1][1]) / slope) + pos[1][0]; if (Math.abs(x - xcalc) < 100) { var extend = x - xcalc; - //the following code is used for positioning the direction of the line and the while loop controling the function iteslf. + //the following code is used for positioning the direction of the line and the while loop controling the function iteslf. if (extend < 0) { return 1; } @@ -123,7 +123,7 @@ class Canvas extends React.Component { componentWillUpdate() { this.placeholder = false; const net = this.props.net; - if (Object.keys(net).length > 0) { //enable zoom buttons if there are layers + if (Object.keys(net).length > 0) { //enable zoom buttons if there are layers this.disableZoom = false; } } @@ -188,7 +188,7 @@ class Canvas extends React.Component { lastLayerId = `l${lastLayerId}`; //add 'l' ahead of the index prevLayerId = `l${prevLayerId}`; const x1 = parseInt(net[prevLayerId].state.top.split('px')); - const x2 = parseInt(net[lastLayerId].state.top.split('px')); + const x2 = parseInt(net[lastLayerId].state.top.split('px')); const s = instance.getEndpoints(prevLayerId)[0]; var t = instance.getEndpoints(lastLayerId); // To handle case of loss layer being target @@ -202,7 +202,7 @@ class Canvas extends React.Component { instance.connect({ source: s, target: t}); - } + } } } allowDrop(event) { @@ -210,7 +210,11 @@ class Canvas extends React.Component { } clickLayerEvent(event, layerId) { // happens when layer is clicked and also dragged if (this.clickOrDraggedLayer === 0) { - this.props.changeSelectedLayer(layerId); // clicked + if (this.props.deleteMode){ + this.props.deleteLayer(layerId); + } + else + this.props.changeSelectedLayer(layerId); // clicked } else if (this.clickOrDraggedLayer === 1) { this.clickOrDraggedLayer = 0; // dragged } @@ -231,7 +235,7 @@ class Canvas extends React.Component { this.placeholder = false; event.preventDefault(); if (event.target.id === 'panZoomContainer' && !this.mouseState.pan) { - if (this.props.selectedLayer!=null) + if (this.props.selectedLayer!=null) this.props.modifyLayer(this.props.net[this.props.selectedLayer], this.props.selectedLayer); this.props.changeSelectedLayer(null); } @@ -248,8 +252,8 @@ class Canvas extends React.Component { layer.state.left = `${event.pos['0']}px`; layer.state.top = `${event.pos['1']}px`; this.props.modifyLayer(layer, layerId); - let net = this.props.net - this.checkCutting(net); + let net = this.props.net + this.checkCutting(net); } connectionEvent(connInfo, originalEvent) { if (originalEvent != null) { // user manually makes a connection @@ -466,7 +470,9 @@ Canvas.propTypes = { totalParameters: React.PropTypes.number, setDraggingLayer: React.PropTypes.func, draggingLayer: React.PropTypes.string, - selectedLayer: React.PropTypes.string + selectedLayer: React.PropTypes.string, + deleteLayer: React.PropTypes.func, + deleteMode: React.PropTypes.bool }; export default Canvas; diff --git a/ide/static/js/content.js b/ide/static/js/content.js index 925bb9992..4e6eb778b 100644 --- a/ide/static/js/content.js +++ b/ide/static/js/content.js @@ -11,7 +11,7 @@ import Modal from 'react-modal'; import ModelZoo from './modelZoo'; import ImportTextbox from './importTextbox'; import UrlImportModal from './urlImportModal'; -import $ from 'jquery' +import $ from 'jquery'; const infoStyle = { content : { @@ -45,7 +45,8 @@ class Content extends React.Component { modalIsOpen: false, totalParameters: 0, modelConfig: null, - modelFramework: 'caffe' + modelFramework: 'caffe', + deleteMode: false }; this.addNewLayer = this.addNewLayer.bind(this); this.changeSelectedLayer = this.changeSelectedLayer.bind(this); @@ -84,6 +85,7 @@ class Content extends React.Component { this.calculateParameters = this.calculateParameters.bind(this); this.getLayerParameters = this.getLayerParameters.bind(this); this.updateLayerShape = this.updateLayerShape.bind(this); + this.toggleDeleteMode = this.toggleDeleteMode.bind(this); this.modalContent = null; this.modalHeader = null; // Might need to improve the logic of clickEvent @@ -145,7 +147,6 @@ class Content extends React.Component { } this.setState({ net, hoveredLayer: layerId }); } - modifyLayer(layer, layerId = this.state.selectedLayer) { const net = this.state.net; var oldLayerParams = this.state.totalParameters; @@ -224,7 +225,7 @@ class Content extends React.Component { const input = net[layerId].connection.input; const output = net[layerId].connection.output; const layerIdNum = parseInt(layerId.substring(1,layerId.length)); //numeric value of the layerId - const nextLayerId = this.state.nextLayerId - 1 == layerIdNum ? layerIdNum : this.state.nextLayerId; + const nextLayerId = this.state.nextLayerId - 1 == layerIdNum ? layerIdNum : this.state.nextLayerId; //if last layer was deleted nextLayerId is replaced by deleted layer's id var totalParameters = this.state.totalParameters; let index; @@ -240,7 +241,9 @@ class Content extends React.Component { }); this.setState({ net, selectedLayer: null, nextLayerId: nextLayerId, totalParameters: totalParameters }); } - + toggleDeleteMode(){ + this.setState({deleteMode: !this.state.deleteMode}); + } updateLayerShape(net, layerId) { const netData = JSON.parse(JSON.stringify(net)); Object.keys(netData[layerId].params).forEach(param => { @@ -287,7 +290,7 @@ class Content extends React.Component { if(filter_layers.includes(layer.info.type)) { // if layer is Conv or DeConv calculating total parameter of the layer using: - // N_Input * K_H * K_W * N_Output + // N_Input * K_H * K_W * N_Output var kernel_params = 1; if(layer.params['kernel_h'][0] != '') kernel_params *= layer.params['kernel_h'][0]; @@ -326,7 +329,7 @@ class Content extends React.Component { if (layer.params['use_bias'][0] == false) bias_params = 0; } - + // Update the total parameters of model after considering this layer. return (weight_params + bias_params); } @@ -356,7 +359,7 @@ class Content extends React.Component { // call to intermediate method which will iterate over layers & calculate the parameters separately this.calculateParameters(net); // update the net object with shape attributes added - this.setState({ net }); + this.setState({ net }); }.bind(this), error() { //console.log('error'+response.error); @@ -850,7 +853,7 @@ class Content extends React.Component { infoModal() { this.modalHeader = "About" this.modalContent = `Fabrik is an online collaborative platform to build and visualize deep\ - learning models via a simple drag-and-drop interface. It allows researchers to\ + learning models via a simple drag-and-drop interface. It allows researchers to\ collaboratively develop and debug models using a web GUI that supports importing,\ editing and exporting networks written in widely popular frameworks like Caffe,\ Keras, and TensorFlow.`; @@ -917,11 +920,11 @@ class Content extends React.Component { const id = event.target.id; const prev = net[`l${this.state.nextLayerId-1}`]; const next = data[id]; - const zoom = instance.getZoom(); + const zoom = instance.getZoom(); const layer = {}; let phase = this.state.selectedPhase; - - if (this.state.nextLayerId>0 //makes sure that there are other layers + + if (this.state.nextLayerId>0 //makes sure that there are other layers &&data[prev.info.type].endpoint.src == "Bottom" //makes sure that the source has a bottom &&next.endpoint.trg == "Top") { //makes sure that the target has a top layer.connection = { input: [], output: [] }; @@ -932,17 +935,17 @@ class Content extends React.Component { } layer.params = { 'endPoint' : [next['endpoint'], false] //This key is endpoint in data.js, but endPoint in everywhere else. - } + } Object.keys(next.params).forEach(j => { layer.params[j] = [next.params[j].value, false]; //copys all params from data.js - }); + }); layer.props = JSON.parse(JSON.stringify(next.props)) //copys all props rom data.js layer.state = { top: `${(parseInt(prev.state.top.split('px')[0])/zoom + 80)}px`, // This makes the new layer is exactly 80px under the previous one. left: `${(parseInt(prev.state.left.split('px')[0])/zoom)}px`, // This aligns the new layer with the previous one. - class: '' + class: '' } - layer.props.name = `${next.name}${this.state.nextLayerId}`; + layer.props.name = `${next.name}${this.state.nextLayerId}`; prev.connection.output.push(`l${this.state.nextLayerId}`); layer.connection.input.push(`l${this.state.nextLayerId-1}`); this.addNewLayer(layer); @@ -957,10 +960,10 @@ class Content extends React.Component { } layer.params = { 'endPoint' : [next['endpoint'], false] //This key is endpoint in data.js, but endPoint in everywhere else. - } + } Object.keys(next.params).forEach(j => { layer.params[j] = [next.params[j].value, false]; //copys all params from data.js - }); + }); layer.props = JSON.parse(JSON.stringify(next.props)) //copys all props from data.js const height = Math.round(0.05*window.innerHeight, 0); // 5% of screen height, rounded to zero decimals const width = Math.round(0.35*window.innerWidth, 0); // 35% of screen width, rounded to zero decimals @@ -969,10 +972,10 @@ class Content extends React.Component { layer.state = { top: `${top}px`, left: `${left}px`, - class: '' + class: '' } - layer.props.name = `${next.name}${this.state.nextLayerId}`; - this.addNewLayer(layer); + layer.props.name = `${next.name}${this.state.nextLayerId}`; + this.addNewLayer(layer); } } render() { @@ -998,9 +1001,14 @@ class Content extends React.Component { zooModal={this.zooModal} textboxModal={this.textboxModal} urlModal={this.urlModal} + net={this.state.net} + selectedLayer={this.state.selectedLayer} + selectedPhase={this.state.selectedPhase} + deleteMode={this.state.deleteMode} + toggleDeleteMode={this.toggleDeleteMode} />
INSERT LAYER
- @@ -1014,12 +1022,12 @@ class Content extends React.Component {
- {loader} @@ -1041,6 +1049,8 @@ class Content extends React.Component { draggingLayer={this.state.draggingLayer} setDraggingLayer={this.setDraggingLayer} selectedLayer={this.state.selectedLayer} + deleteLayer={this.deleteLayer} + deleteMode={this.state.deleteMode} />
@@ -78,6 +95,16 @@ class TopBar extends React.Component {
+
+
+
+ +
+
+
@@ -86,13 +113,18 @@ class TopBar extends React.Component { } TopBar.propTypes = { + selectedLayer: React.PropTypes.string, + net: React.PropTypes.object, + selectedPhase: React.PropTypes.number, exportNet: React.PropTypes.func, importNet: React.PropTypes.func, saveDb: React.PropTypes.func, loadDb: React.PropTypes.func, zooModal: React.PropTypes.func, textboxModal: React.PropTypes.func, - urlModal: React.PropTypes.func + urlModal: React.PropTypes.func, + deleteMode: React.PropTypes.bool, + toggleDeleteMode: React.PropTypes.func }; export default TopBar;