diff --git a/app.py b/app.py
index ee5ac96..f916a09 100644
--- a/app.py
+++ b/app.py
@@ -1,9 +1,16 @@
-from flask import Flask, render_template
+import json
+from flask import Flask, render_template, request, jsonify
app = Flask(__name__)
@app.route('/')
-def hello():
+def index():
return render_template('index.html')
+@app.route('/download', methods=['POST'])
+def downloadModel():
+ modelNodeStates = request.get_json()
+ print(modelNodeStates)
+ return 'OK', 200
+
if __name__ == '__main__':
app.run()
\ No newline at end of file
diff --git a/static/__init__.py b/static/__init__.py
deleted file mode 100644
index 5456384..0000000
--- a/static/__init__.py
+++ /dev/null
@@ -1,34 +0,0 @@
-
-import argparse
-import sys
-import os
-
-from .server import start
-from .server import stop
-from .server import status
-from .server import wait
-from .server import serve
-from .__version__ import __version__
-
-def main():
- parser = argparse.ArgumentParser(description='Viewer for neural network, deep learning and machine learning models.')
- parser.add_argument('file', metavar='MODEL_FILE', help='model file to serve', nargs='?', default=None)
- parser.add_argument('-v', '--version', help="print version", action='store_true')
- parser.add_argument('-b', '--browse', help='launch web browser', action='store_true')
- parser.add_argument('-p', '--port', help='port to serve', type=int)
- parser.add_argument('--host', help="host to serve")
- parser.add_argument('--log', help='log details to console', action='store_true')
- args = parser.parse_args()
- if args.file and not os.path.exists(args.file):
- print("Model file '" + args.file + "' does not exist.")
- sys.exit(2)
- if args.version:
- print(__version__)
- sys.exit(0)
- address = (args.host, args.port) if args.host else args.port if args.port else None
- start(args.file, address=address, browse=args.browse, log=args.log)
- wait()
- sys.exit(0)
-
-if __name__ == '__main__':
- main()
diff --git a/static/__version__.py b/static/__version__.py
deleted file mode 100644
index 6853c36..0000000
--- a/static/__version__.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = '0.0.0'
\ No newline at end of file
diff --git a/static/server.py b/static/server.py
deleted file mode 100644
index a1919d5..0000000
--- a/static/server.py
+++ /dev/null
@@ -1,298 +0,0 @@
-
-import codecs
-import errno
-import os
-import random
-import re
-import socket
-import sys
-import threading
-import webbrowser
-import time
-
-from .__version__ import __version__
-
-if sys.version_info[0] > 2:
- from urllib.parse import urlparse
- from urllib.parse import unquote
- from http.server import HTTPServer
- from http.server import BaseHTTPRequestHandler
- from socketserver import ThreadingMixIn
-else:
- from urlparse import urlparse
- from urlparse import unquote
- from BaseHTTPServer import HTTPServer
- from BaseHTTPServer import BaseHTTPRequestHandler
- from SocketServer import ThreadingMixIn
-
-class HTTPRequestHandler(BaseHTTPRequestHandler):
- def handler(self):
- if not hasattr(self, 'mime_types_map'):
- self.mime_types_map = {
- '.html': 'text/html',
- '.js': 'text/javascript',
- '.css': 'text/css',
- '.png': 'image/png',
- '.gif': 'image/gif',
- '.jpg': 'image/jpeg',
- '.ico': 'image/x-icon',
- '.json': 'application/json',
- '.pb': 'application/octet-stream',
- '.ttf': 'font/truetype',
- '.otf': 'font/opentype',
- '.eot': 'application/vnd.ms-fontobject',
- '.woff': 'font/woff',
- '.woff2': 'application/font-woff2',
- '.svg': 'image/svg+xml'
- }
- pathname = urlparse(self.path).path
- folder = os.path.dirname(os.path.realpath(__file__))
- location = folder + pathname
- status_code = 0
- headers = {}
- buffer = None
- data = '/data/'
- if status_code == 0:
- if pathname == '/':
- meta = []
- meta.append('')
- meta.append('')
- if self.file:
- meta.append('')
- with codecs.open(location + 'index.html', mode="r", encoding="utf-8") as open_file:
- buffer = open_file.read()
- buffer = re.sub(r'', '\n'.join(meta), buffer)
- buffer = buffer.encode('utf-8')
- headers['Content-Type'] = 'text/html'
- headers['Content-Length'] = len(buffer)
- status_code = 200
- elif pathname.startswith(data):
- file = pathname[len(data):]
- if file == self.file and self.data:
- buffer = self.data
- else:
- file = self.folder + '/' + unquote(file)
- status_code = 404
- if os.path.exists(file):
- with open(file, 'rb') as binary:
- buffer = binary.read()
- if buffer:
- headers['Content-Type'] = 'application/octet-stream'
- headers['Content-Length'] = len(buffer)
- status_code = 200
- else:
- if os.path.exists(location) and not os.path.isdir(location):
- extension = os.path.splitext(location)[1]
- content_type = self.mime_types_map[extension]
- if content_type:
- with open(location, 'rb') as binary:
- buffer = binary.read()
- headers['Content-Type'] = content_type
- headers['Content-Length'] = len(buffer)
- status_code = 200
- else:
- status_code = 404
- if self.log:
- sys.stdout.write(str(status_code) + ' ' + self.command + ' ' + self.path + '\n')
- sys.stdout.flush()
- self.send_response(status_code)
- for key in headers:
- self.send_header(key, headers[key])
- self.end_headers()
- if self.command != 'HEAD':
- if status_code == 404 and buffer is None:
- self.wfile.write(bytes(status_code))
- elif (status_code in (200, 404)) and buffer is not None:
- self.wfile.write(buffer)
- def do_GET(self):
- self.handler()
- def do_HEAD(self):
- self.handler()
- def log_message(self, format, *args):
- return
-
-class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
- pass
-
-class HTTPServerThread(threading.Thread):
- def __init__(self, data, file, address, log):
- threading.Thread.__init__(self)
- self.address = address
- self.url = 'http://' + address[0] + ':' + str(address[1])
- self.file = file
- self.server = ThreadedHTTPServer(address, HTTPRequestHandler)
- self.server.timeout = 0.25
- if file:
- self.server.RequestHandlerClass.folder = os.path.dirname(file) if os.path.dirname(file) else '.'
- self.server.RequestHandlerClass.file = os.path.basename(file)
- else:
- self.server.RequestHandlerClass.folder = ''
- self.server.RequestHandlerClass.file = ''
- self.server.RequestHandlerClass.data = data
- self.server.RequestHandlerClass.log = log
- self.terminate_event = threading.Event()
- self.terminate_event.set()
- self.stop_event = threading.Event()
-
- def run(self):
- self.stop_event.clear()
- self.terminate_event.clear()
- try:
- while not self.stop_event.is_set():
- self.server.handle_request()
- except Exception:
- pass
- self.terminate_event.set()
- self.stop_event.clear()
-
- def stop(self):
- if self.alive():
- sys.stdout.write("Stopping " + self.url + "\n")
- self.stop_event.set()
- self.server.server_close()
- self.terminate_event.wait(1000)
-
- def alive(self):
- return not self.terminate_event.is_set()
-
-_thread_list = []
-
-def _add_thread(thread):
- global _thread_list
- _thread_list.append(thread)
-
-def _update_thread_list(address=None):
- global _thread_list
- _thread_list = [ thread for thread in _thread_list if thread.alive() ]
- threads = _thread_list
- if address is not None:
- address = _make_address(address)
- if address[1] is None:
- threads = [ thread for thread in threads if address[0] == thread.address[0] ]
- else:
- threads = [ thread for thread in threads if address[0] == thread.address[0] and address[1] == thread.address[1] ]
- return threads
-
-def _make_address(address):
- if address is None or isinstance(address, int):
- port = address
- address = ('localhost', port)
- if isinstance(address, tuple) and len(address) == 2:
- host = address[0]
- port = address[1]
- if isinstance(host, str) and (port is None or isinstance(port, int)):
- return address
- raise ValueError('Invalid address.')
-
-def _make_port(address):
- if address[1] is None or address[1] == 0:
- ports = []
- if address[1] != 0:
- ports.append(8080)
- ports.append(8081)
- rnd = random.Random()
- for _ in range(4):
- port = rnd.randrange(15000, 25000)
- if port not in ports:
- ports.append(port)
- ports.append(0)
- for port in ports:
- temp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- temp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- temp_socket.settimeout(1)
- try:
- temp_socket.bind((address[0], port))
- sockname = temp_socket.getsockname()
- address = (address[0], sockname[1])
- return address
- except:
- pass
- finally:
- temp_socket.close()
- if isinstance(address[1], int):
- return address
- raise ValueError('Failed to allocate port.')
-
-def stop(address=None):
- '''Stop serving model at address.
-
- Args:
- address (tuple, optional): A (host, port) tuple, or a port number.
- '''
- threads = _update_thread_list(address)
- for thread in threads:
- thread.stop()
- _update_thread_list()
-
-def status(adrress=None):
- '''Is model served at address.
-
- Args:
- address (tuple, optional): A (host, port) tuple, or a port number.
- '''
- threads = _update_thread_list(adrress)
- return len(threads) > 0
-
-def wait():
- '''Wait for console exit and stop all model servers.'''
- try:
- while len(_update_thread_list()) > 0:
- time.sleep(1000)
- except (KeyboardInterrupt, SystemExit):
- sys.stdout.write('\n')
- sys.stdout.flush()
- stop()
-
-def serve(file, data, address=None, browse=False, log=False):
- '''Start serving model from file or data buffer at address and open in web browser.
-
- Args:
- file (string): Model file to serve. Required to detect format.
- data (bytes): Model data to serve. None will load data from file.
- log (bool, optional): Log details to console. Default: False
- browse (bool, optional): Launch web browser. Default: True
- address (tuple, optional): A (host, port) tuple, or a port number.
-
- Returns:
- A (host, port) address tuple.
- '''
- if not data and file and not os.path.exists(file):
- raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), file)
-
- _update_thread_list()
- address = _make_address(address)
- if isinstance(address[1], int) and address[1] != 0:
- stop(address)
- else:
- address = _make_port(address)
- _update_thread_list()
-
- thread = HTTPServerThread(data, file, address, log)
- thread.start()
- while not thread.alive():
- time.sleep(10)
- _add_thread(thread)
-
- if file:
- sys.stdout.write("Serving '" + file + "' at " + thread.url + "\n")
- else:
- sys.stdout.write("Serving at " + thread.url + "\n")
- sys.stdout.flush()
- if browse:
- webbrowser.open(thread.url)
-
- return address
-
-def start(file=None, address=None, browse=True, log=False):
- '''Start serving model file at address and open in web browser.
-
- Args:
- file (string): Model file to serve.
- log (bool, optional): Log details to console. Default: False
- browse (bool, optional): Launch web browser, Default: True
- address (tuple, optional): A (host, port) tuple, or a port number.
-
- Returns:
- A (host, port) address tuple.
- '''
- return serve(file, None, browse=browse, address=address, log=log)
diff --git a/static/view-sidebar.js b/static/view-sidebar.js
index 26cd81f..bc7a28d 100644
--- a/static/view-sidebar.js
+++ b/static/view-sidebar.js
@@ -267,6 +267,19 @@ sidebar.NodeSidebar = class {
}
}
+
+ _strMapToObj(strMap){
+ let obj = Object.create(null);
+ for (let[k, v] of strMap) {
+ obj[k] = v;
+ }
+ return obj;
+ }
+
+ _mapToJson(map) {
+ return JSON.stringify(this._strMapToObj(map));
+ }
+
// My code
_addButton(title) {
const buttonElement = this._host.document.createElement('button');
@@ -293,6 +306,31 @@ sidebar.NodeSidebar = class {
});
}
+ if (title === 'Download') {
+ buttonElement.addEventListener('click', () => {
+ // console.log(this._host._view._graph._modelNodeName2State)
+ // https://healeycodes.com/talking-between-languages
+ fetch('/download', {
+ // Declare what type of data we're sending
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ // Specify the method
+ method: 'POST',
+ // https://blog.csdn.net/Crazy_SunShine/article/details/80624366
+ body: this._mapToJson(
+ this._host._view._graph._modelNodeName2State
+ )
+ }).then(function (response) {
+ return response.text();
+ }).then(function (text) {
+ console.log('POST response: ');
+ // Should be 'OK' if everything was successful
+ console.log(text);
+ });
+ });
+ }
+
}
diff --git a/static/weka.js b/static/weka.js
deleted file mode 100644
index d121dc3..0000000
--- a/static/weka.js
+++ /dev/null
@@ -1,256 +0,0 @@
-
-// Experimental
-
-var weka = weka || {};
-var json = json || require('./json');
-var java = {};
-
-weka.ModelFactory = class {
-
- match(context) {
- try {
- const stream = context.stream;
- if (stream.length >= 5) {
- const signature = [ 0xac, 0xed ];
- if (stream.peek(2).every((value, index) => value === signature[index])) {
- const reader = new java.io.InputObjectStream(stream);
- const obj = reader.read();
- if (obj && obj.$class && obj.$class.name) {
- return 'weka';
- }
- }
- }
- }
- catch (err) {
- // continue regardless of error
- }
- return undefined;
- }
-
- open(context) {
- return Promise.resolve().then(() => {
- const reader = new java.io.InputObjectStream(context.stream);
- const obj = reader.read();
- throw new weka.Error("Unsupported type '" + obj.$class.name + "'.");
- });
- }
-};
-
-weka.Error = class extends Error {
-
- constructor(message) {
- super(message);
- this.name = 'Error loading Weka model.';
- }
-};
-
-java.io = {};
-
-java.io.InputObjectStream = class {
-
- constructor(stream) {
- // Object Serialization Stream Protocol
- // https://www.cis.upenn.edu/~bcpierce/courses/629/jdkdocs/guide/serialization/spec/protocol.doc.html
- if (stream.length < 5) {
- throw new java.io.Error('Invalid stream size');
- }
- const signature = [ 0xac, 0xed ];
- if (!stream.peek(2).every((value, index) => value === signature[index])) {
- throw new java.io.Error('Invalid stream signature');
- }
- this._reader = new java.io.InputObjectStream.BinaryReader(stream.peek());
- this._references = [];
- this._reader.skip(2);
- const version = this._reader.uint16();
- if (version !== 0x0005) {
- throw new java.io.Error("Unsupported version '" + version + "'.");
- }
- }
-
- read() {
- return this._object();
- }
-
- _object() {
- const code = this._reader.byte();
- switch (code) {
- case 0x73: { // TC_OBJECT
- const obj = {};
- obj.$class = this._classDesc();
- this._newHandle(obj);
- this._classData(obj);
- return obj;
- }
- case 0x74: { // TC_STRING
- return this._newString(false);
- }
- }
- throw new java.io.Error("Unsupported code '" + code + "'.");
- }
-
- _classDesc() {
- const code = this._reader.byte();
- switch (code) {
- case 0x72: // TC_CLASSDESC
- this._reader.skip(-1);
- return this._newClassDesc();
- case 0x71: // TC_REFERENCE
- return this._references[this._reader.uint32() - 0x7e0000];
- case 0x70: // TC_NULL
- this._reader.byte();
- return null;
- }
- throw new java.io.Error("Unsupported code '" + code + "'.");
- }
-
- _newClassDesc() {
- const code = this._reader.byte();
- switch (code) {
- case 0x72: { // TC_CLASSDESC
- const classDesc = {};
- classDesc.name = this._reader.string(),
- classDesc.id = this._reader.uint64().toString();
- this._newHandle(classDesc);
- classDesc.flags = this._reader.byte();
- classDesc.fields = [];
- const count = this._reader.uint16();
- for (let i = 0; i < count; i++) {
- const field = {};
- field.type = String.fromCharCode(this._reader.byte());
- field.name = this._reader.string();
- if (field.type === '[' || field.type === 'L') {
- field.classname = this._object();
- }
- classDesc.fields.push(field);
- }
- if (this._reader.byte() !== 0x78) {
- throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
- }
- classDesc.superClass = this._classDesc();
- return classDesc;
- }
- case 0x7D: // TC_PROXYCLASSDESC
- break;
- }
- throw new java.io.Error("Unsupported code '" + code + "'.");
- }
-
- _classData(/* obj */) {
- /*
- const classname = obj.$class.name;
- let flags = obj.$class.flags;
- let superClass = obj.$class.superClass;
- while (superClass) {
- flags |= superClass.flags;
- superClass = superClass.superClass;
- }
- if (flags & 0x02) { // SC_SERIALIZABLE
- debugger;
- var customObject = objects[classname];
- var hasReadObjectMethod = customObject && customObject.readObject;
- if (flags & 0x01) { // SC_WRITE_METHOD
- if (!hasReadObjectMethod) {
- throw new Error('Class "'+ classname + '" dose not implement readObject()');
- }
- customObject.readObject(this, obj);
- if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
- throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
- }
- }
- else {
- if (hasReadObjectMethod) {
- customObject.readObject(this, obj);
- if (this._reader.byte() !== 0x78) { // TC_ENDBLOCKDATA
- throw new java.io.Error('Expected TC_ENDBLOCKDATA.');
- }
- }
- else {
- this._nowrclass(obj);
- }
- }
- }
- else if (flags & 0x04) { // SC_EXTERNALIZABLE
- if (flags & 0x08) { // SC_BLOCK_DATA
- this._objectAnnotation(obj);
- }
- else {
- this._externalContents();
- }
- }
- else {
- throw new Error('Illegal flags: ' + flags);
- }
- */
- }
-
- _newString(long) {
- const value = this._reader.string(long);
- this._newHandle(value);
- return value;
- }
-
- _newHandle(obj) {
- this._references.push(obj);
- }
-};
-
-java.io.InputObjectStream.BinaryReader = class {
-
- constructor(buffer) {
- this._buffer = buffer;
- this._position = 0;
- this._length = buffer.length;
- this._view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
- this._decoder = new TextDecoder('utf-8');
- }
-
- skip(offset) {
- this._position += offset;
- if (this._position > this._end) {
- throw new java.io.Error('Expected ' + (this._position - this._end) + ' more bytes. The file might be corrupted. Unexpected end of file.');
- }
- }
-
- byte() {
- const position = this._position;
- this.skip(1);
- return this._buffer[position];
- }
-
- uint16() {
- const position = this._position;
- this.skip(2);
- return this._view.getUint16(position, false);
- }
-
- uint32() {
- const position = this._position;
- this.skip(4);
- return this._view.getUint32(position, false);
- }
-
- uint64() {
- const position = this._position;
- this.skip(8);
- return this._view.getUint64(position, false);
- }
-
- string(long) {
- const size = long ? this.uint64().toNumber() : this.uint16();
- const position = this._position;
- this.skip(size);
- return this._decoder.decode(this._buffer.subarray(position, this._position));
- }
-};
-
-java.io.Error = class extends Error {
-
- constructor(message) {
- super(message);
- this.name = 'Error loading Object Serialization Stream Protocol.';
- }
-};
-
-if (typeof module !== 'undefined' && typeof module.exports === 'object') {
- module.exports.ModelFactory = weka.ModelFactory;
-}
\ No newline at end of file