Skip to content

Commit 46912b7

Browse files
author
Alex
committed
Upload of .h5 files now possible.
1 parent a6bbd4b commit 46912b7

File tree

12 files changed

+1068
-804
lines changed

12 files changed

+1068
-804
lines changed

backend/server.py

Lines changed: 315 additions & 294 deletions
Large diffs are not rendered by default.

backend/translate/translate_keras.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ def translate_keras(filename):
2222
general_reader = open('translate/keras_loader.txt', 'rb')
2323
general_code = general_reader.read()
2424
if keras_ext in filename:
25-
return graph_from_model_file(filename)
25+
try:
26+
return graph_from_model_file(filename)
27+
except Exception as err:
28+
return {'error_class': '', 'line_number': 1,
29+
'detail': "Model could not be loaded correctly. Error: " + str(err)}
2630
else:
2731
with open(filename, 'rb') as myfile:
2832
keras_code = myfile.read()
@@ -66,9 +70,10 @@ def graph_from_external_file(keras_code, general_code):
6670
graph.resolve_input_names()
6771
return graph
6872

73+
6974
def graph_from_model_file(keras_model_file):
7075
model_keras = keras.models.load_model(keras_model_file)
71-
model_json = model_keras.to_json()
76+
model_json = json.loads(model_keras.to_json())
7277
layers_extracted = model_json['config']['layers']
7378
graph = Graph()
7479
previous_node = ''
@@ -81,6 +86,7 @@ def graph_from_model_file(keras_model_file):
8186
graph.resolve_input_names()
8287
return graph
8388

89+
8490
def add_layer_type(layer_json, model_layer, graph, previous_node):
8591
"""Add a Layer. Layers are identified by name and equipped using the spec.
8692

net2vis/package-lock.json

Lines changed: 306 additions & 247 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

net2vis/package.json

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,29 @@
33
"version": "0.1.0",
44
"private": true,
55
"dependencies": {
6-
"@material-ui/core": "^4.11.4",
6+
"@material-ui/core": "^4.12.3",
77
"@material-ui/icons": "^4.11.2",
88
"ace-builds": "^1.4.12",
99
"dagre": "^0.8.5",
1010
"file-saver": "^2.0.5",
11-
"http-proxy-middleware": "^2.0.0",
11+
"http-proxy-middleware": "^2.0.1",
1212
"jquery": "^3.6.0",
13-
"jszip": "^3.6.0",
13+
"jszip": "^3.7.1",
1414
"node-sass-chokidar": "^1.5.0",
15-
"npm": "^7.17.0",
15+
"npm": "^7.21.0",
1616
"npm-run-all": "^4.1.5",
1717
"prop-types": "^15.7.2",
1818
"randomstring": "^1.2.1",
1919
"react": "^17.0.2",
20-
"react-ace": "^9.4.1",
20+
"react-ace": "^9.4.3",
2121
"react-color": "^2.19.3",
2222
"react-dom": "^17.0.2",
23+
"react-dropzone": "^11.3.4",
2324
"react-redux": "^7.2.4",
2425
"react-router-dom": "^5.2.0",
2526
"react-scripts": "^4.0.3",
2627
"react-svg-tooltip": "0.0.11",
27-
"redux": "^4.1.0",
28+
"redux": "^4.1.1",
2829
"redux-thunk": "^2.3.0",
2930
"tinycolor2": "^1.4.2"
3031
},

net2vis/src/actions/index.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import LayerTypesApi from "../api/LayerTypesApi";
44
import PreferencesApi from "../api/PreferencesApi";
55
import LegendPreferencesApi from "../api/LegendPreferencesApi";
66
import GroupsApi from "../api/GroupsApi";
7+
import ModelApi from "../api/ModelApi";
78
import * as types from "./types";
89
import * as sort from "../groups/Sort";
910
import * as splitting from "../layers/Splitting";
@@ -54,6 +55,11 @@ export function toggleAlert() {
5455
return { type: types.TOGGLE_ALERT };
5556
}
5657

58+
// Toggle the Upload Alert View
59+
export function toggleUpload() {
60+
return { type: types.TOGGLE_UPLOAD };
61+
}
62+
5763
// Loading LayerTypes was Successful
5864
function loadLayerTypesSuccess(layerTypes, network, generationMode) {
5965
return {
@@ -273,6 +279,19 @@ export function loadCode(id) {
273279
};
274280
}
275281

282+
// Called to delte the model file
283+
export function deleteModel(id) {
284+
return function (dispatch) {
285+
return ModelApi.deleteModel(id)
286+
.then((code) => {
287+
dispatch(loadCodeSuccess(code));
288+
})
289+
.catch((error) => {
290+
throw error;
291+
});
292+
};
293+
}
294+
276295
// Updating Code was Succesful
277296
function updateCodeSuccess(code) {
278297
return { type: types.UPDATE_CODE_SUCESS, code };
@@ -334,6 +353,58 @@ export function updateCodeBackend(
334353
};
335354
}
336355

356+
export function updateModelBackend(
357+
file,
358+
id,
359+
groups,
360+
generationMode,
361+
preferences
362+
) {
363+
const loader = document.getElementById("loader");
364+
loader.style.display = "flex";
365+
return function (dispatch) {
366+
dispatch(toggleUpload());
367+
return ModelApi.updateModel(file, id)
368+
.then((code) => {
369+
dispatch(updateCodeSuccess(code));
370+
return NetworkApi.getNetwork(id)
371+
.then((network) => {
372+
loader.style.display = "none";
373+
if (network.success === true) {
374+
var net = network.data;
375+
if (preferences.add_splitting.value) {
376+
net = splitting.addSplitLayers(net);
377+
}
378+
return LayerTypesApi.getLayerTypes(id).then((layerTypes) => {
379+
networkLoaded(net, groups, JSON.parse(layerTypes), dispatch);
380+
dispatch(
381+
loadLayerTypesSuccess(
382+
JSON.parse(layerTypes),
383+
net,
384+
generationMode
385+
)
386+
);
387+
});
388+
} else {
389+
dispatch(
390+
updateAlertSnack({
391+
open: true,
392+
message: "Code not executeable.",
393+
})
394+
);
395+
dispatch(addError(network.data));
396+
}
397+
})
398+
.catch((error) => {
399+
throw error;
400+
});
401+
})
402+
.catch((error) => {
403+
console.warn("Current Network not executable.", error);
404+
});
405+
};
406+
}
407+
337408
// Select Layer
338409
export function selectLayer(id) {
339410
return { type: types.SELECT_LAYER, id };

net2vis/src/actions/types.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export const TOGGLE_CODE = "TOGGLE_CODE";
1212
export const TOGGLE_PREFERENCES = "TOGGLE_PREFERENCES";
1313
export const TOGGLE_LEGEND = "TOGGLE_LEGEND";
1414
export const TOGGLE_ALERT = "TOGGLE_ALERT";
15+
export const TOGGLE_UPLOAD = "TOGGLE_UPLOAD";
1516
export const LOAD_LAYER_TYPES_SUCCESS = "LOAD_LAYER_TYPES_SUCCESS";
1617
export const LOAD_PREFERENCES_SUCCESS = "LOAD_PREFERENCES_SUCCESS";
1718
export const UPDATE_PREFERENCES_SUCCESS = "UPDATE_PREFERENCES_SUCCESS";

net2vis/src/api/ModelApi.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Class for calling Backend functions related to Code
2+
class ModelApi {
3+
// Update the Model file on the Backend
4+
static updateModel(file, id) {
5+
let formData = new FormData();
6+
formData.append("model", file);
7+
8+
const request = new Request("/api/upload_model/" + id, {
9+
// Prepare the Request
10+
method: "POST",
11+
body: formData,
12+
});
13+
14+
return fetch(request)
15+
.then((response) => {
16+
// Return the Result of the Request
17+
return response.text();
18+
})
19+
.catch((error) => {
20+
return error;
21+
});
22+
}
23+
24+
// Delete the model from the Backend
25+
static deleteModel(id) {
26+
const request = new Request("/api/delete_model/" + id, {
27+
// Prepare the Request
28+
method: "GET",
29+
});
30+
31+
return fetch(request)
32+
.then((response) => {
33+
// Return the result of the Request
34+
return response.text();
35+
})
36+
.catch((error) => {
37+
return error;
38+
});
39+
}
40+
}
41+
42+
export default ModelApi;

net2vis/src/components/code/CodeComponent.js

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ import PropTypes from "prop-types";
44
import { bindActionCreators } from "redux";
55
import AceEditor from "react-ace";
66
import InputField from "../input/InputField";
7+
import Dialog from "@material-ui/core/Dialog";
8+
import DialogActions from "@material-ui/core/DialogActions";
9+
import DialogContent from "@material-ui/core/DialogContent";
10+
import DialogTitle from "@material-ui/core/DialogTitle";
11+
import Button from "@material-ui/core/Button";
12+
import Dropzone from "react-dropzone";
713
import "ace-builds/src-noconflict/mode-python";
814
import "ace-builds/src-noconflict/snippets/python";
915
import "ace-builds/src-min-noconflict/ext-language_tools";
@@ -28,10 +34,29 @@ class Code extends React.Component {
2834
);
2935
};
3036

37+
updateStoredModel = () => {
38+
this.props.actions.uploadModel(
39+
this.props.id,
40+
this.props.groups,
41+
this.props.color_mode.generation,
42+
this.props.preferences
43+
);
44+
};
45+
3146
componentDidUpdate() {
3247
this.refs.aceEditor.editor.resize(); // Triggering a resize of the editor, which is needed to be displayed correctly
3348
}
3449

50+
uploadFile(file) {
51+
this.props.actions.updateModelBackend(
52+
file,
53+
this.props.id,
54+
this.props.groups,
55+
this.props.color_mode.generation,
56+
this.props.preferences
57+
);
58+
}
59+
3560
// Render the Code into the Code View if Toggled
3661
render() {
3762
const code = this.props.code;
@@ -46,6 +71,7 @@ class Code extends React.Component {
4671
},
4772
];
4873
}
74+
const display = this.props.display;
4975
return (
5076
// Editor with Syntax highlighting
5177
<div className="preferencesWrapper">
@@ -68,15 +94,67 @@ class Code extends React.Component {
6894
scrollMargin={[10, 0, 0, 0]}
6995
/>
7096
</div>
71-
<div>
97+
{this.props.code === "No code loaded since model file is present." ? (
7298
<InputField
73-
value={"Update"}
99+
value={"Delete Model"}
74100
type={"codeButton"}
75-
description={"Update"}
76-
action={this.updateStoredCode}
101+
description={"Delete Model"}
102+
options={"secondary"}
103+
action={() => this.props.actions.deleteModel(this.props.id)}
77104
active={true}
78105
/>
79-
</div>
106+
) : (
107+
<div className="updateButtonContainer">
108+
<InputField
109+
value={"Upload Model"}
110+
type={"codeButton"}
111+
description={"Upload Model"}
112+
action={this.props.actions.toggleUpload}
113+
active={true}
114+
/>
115+
<InputField
116+
value={"Update"}
117+
type={"codeButton"}
118+
description={"Update"}
119+
action={this.updateStoredCode}
120+
active={true}
121+
/>
122+
</div>
123+
)}
124+
<Dialog
125+
open={display.upload_toggle}
126+
aria-labelledby="alert-dialog-title"
127+
aria-describedby="alert-dialog-description"
128+
>
129+
<DialogTitle id="alert-dialog-title">Upload h5 Model</DialogTitle>
130+
<DialogContent>
131+
<div className="dropzoneContainer">
132+
<Dropzone
133+
onDrop={(acceptedFiles) => this.uploadFile(acceptedFiles[0])}
134+
acceptedFiles=".h5"
135+
maxFiles={1}
136+
>
137+
{({ getRootProps, getInputProps }) => (
138+
<section>
139+
<div {...getRootProps()}>
140+
<input {...getInputProps()} />
141+
<p>Drag a model file here, or click to select a file.</p>
142+
</div>
143+
</section>
144+
)}
145+
</Dropzone>
146+
</div>
147+
</DialogContent>
148+
<DialogActions>
149+
<Button
150+
onClick={this.props.actions.toggleUpload}
151+
color="secondary"
152+
autoFocus
153+
>
154+
Cancel
155+
</Button>
156+
</DialogActions>
157+
</Dialog>
80158
</div>
81159
);
82160
}
@@ -90,6 +168,7 @@ Code.propTypes = {
90168
groups: PropTypes.array.isRequired,
91169
color_mode: PropTypes.object.isRequired,
92170
preferences: PropTypes.object.isRequired,
171+
display: PropTypes.object.isRequired,
93172
};
94173

95174
// Map the State to the Properties of this Component
@@ -103,6 +182,7 @@ function mapStateToProps(state, ownProps) {
103182
groups: state.groups,
104183
color_mode: state.color_mode,
105184
preferences: state.preferences,
185+
display: state.display,
106186
};
107187
} else {
108188
return {
@@ -112,6 +192,7 @@ function mapStateToProps(state, ownProps) {
112192
groups: state.groups,
113193
color_mode: state.color_mode,
114194
preferences: state.preferences,
195+
display: state.display,
115196
};
116197
}
117198
}

0 commit comments

Comments
 (0)