Skip to content

Commit

Permalink
#psyneu-139 - Load dependencies of model scripts, fix bugs with code …
Browse files Browse the repository at this point in the history
…loading models.
  • Loading branch information
jrmartin committed Oct 22, 2024
1 parent 4895a29 commit 0f929b9
Show file tree
Hide file tree
Showing 25 changed files with 196 additions and 112 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,8 @@ yalc.lock

.idea

package/.eggs
package/.eggs

psyneulinkviewer-darwin-x64/
package/psyneulinkviewer/__pycache__
package/__pycache__
8 changes: 4 additions & 4 deletions installation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ else
echo " - please use the option desidered to run the script again."
fi

pip uninstall -y grpcio && pip uninstall -y grpcio-tools
conda install -c -y conda-forge grpcio
pip install -y modeci_mdf
conda install -y python-graphviz
pip uninstall grpcio && pip uninstall grpcio-tools
conda install conda-forge grpcio
pip install modeci_mdf
conda install python-graphviz
Empty file added installers/psyneulinkviewer.dmg
Empty file.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@
"process": "^0.11.10",
"ps-tree": "^1.2.0",
"python-shell": "^5.0.0",
"react": "^17.0.2",
"react": "17.0.2",
"react-app-rewired": "^2.2.1",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^17.0.2",
"react-dom": "17.0.2",
"react-plotly.js": "^2.6.0",
"react-redux": "^7.2.0",
"react-rnd": "^10.3.7",
Expand Down
Empty file modified pre_installation.sh
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions public/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ async function createWindow() {
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
// WARNING extension has to be loaded before create the window
createWindow();
const isMac = process.platform === 'darwin';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export class NodeFactory {
);

const link = new MetaLinkModel(Object.fromEntries(options));
link.setSourcePort(sourcePort);
link.setTargetPort(targetPort);
link?.setSourcePort(sourcePort);
link?.setTargetPort(targetPort);

return link;
}
Expand Down
2 changes: 1 addition & 1 deletion src/client/model/Interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ export default class ModelInterpreter {
modelMap[newNode.getType()].set(newNode.getName(), newNode);
this.pnlModel[newNode.getType()].push(newNode);
} else {
throw new Error('Unknown node type, class ' + newNode.getType() + ' not found in modelMap');
//throw new Error('Unknown node type, class ' + newNode.getType() + ' not found in modelMap');
}
return newNode;
}
Expand Down
2 changes: 1 addition & 1 deletion src/client/model/ModelSingleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export default class ModelSingleton {
static getNodeType(nodeName: string) {
if (ModelSingleton.summaries[nodeName]) {
// Note, the replace below is required due to a transformation done by the library PSNL itself
return ModelSingleton.summaries[nodeName][nodeName.replace('-', '_')].metadata.type;
return ModelSingleton.summaries[nodeName][nodeName.replace('-', '_')]?.metadata?.type;
}
return 'unknown';
}
Expand Down
14 changes: 11 additions & 3 deletions src/client/model/graph/MetaGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,17 @@ export class MetaGraph {
const source = this.getNodeDFS(child.getSourceId());
const target = this.getNodeDFS(child.getTargetId());
if (source && target) {
link.setSourcePort(source.getPort(child.getSourcePortId()));
link.setTargetPort(target.getPort(child.getTargetPortId()));
this.links.push(link);
let sourcePort = source.getPort(child.getSourcePortId());
let targetPort = target.getPort(child.getTargetPortId())
if ( sourcePort != undefined && link != undefined ) {
link?.setSourcePort(sourcePort);
}
if ( targetPort != undefined && link != undefined ) {
link?.setTargetPort(targetPort);
}
if ( sourcePort != undefined && targetPort != undefined ){
this.links.push(link);
}
}
});
this.notify({type: MetaGraphEventTypes.LINK_ADDED, payload: links})
Expand Down
2 changes: 1 addition & 1 deletion src/client/model/links/ProjectionLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default class ProjectionLink implements IMetaLinkConverter {
}
});
if (result === '') {
throw Error('There is no port with that name.');
//throw Error('There is no port with that name.');
}
return result;
}
Expand Down
24 changes: 19 additions & 5 deletions src/client/model/nodes/composition/CompositionNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@ export default class CompositionNode extends MechanismNode {

addChild(child: MechanismNode|CompositionNode) {
if (!this.childrenMap.has(child.getName())) {
this.childrenMap.set(child.getName(), child);
this.metaChildren.push(child.getMetaNode());
this.childrenMap?.set(child.getName(), child);
this.metaChildren?.push(child.getMetaNode());
}
this.children[child.getType()].push(child);
this.children[child.getType()]?.push(child);
}

removeChild(child: MechanismNode|CompositionNode) {
if (this.childrenMap.has(child.getName())) {
this.childrenMap.delete(child.getName());
this.metaChildren = this.metaChildren.filter((item: MetaNode) => item.getId() !== child.getName());
this.metaChildren = this.metaChildren?.filter((item: MetaNode) => item.getId() !== child.getName());
}

this.children[child.getType()] = this.children[child.getType()].filter( (item: any) => {
this.children[child.getType()] = this.children[child.getType()]?.filter( (item: any) => {
return item.getName() !== child.getName()
});
}
Expand Down Expand Up @@ -118,6 +118,20 @@ export default class CompositionNode extends MechanismNode {
this.metaChildren,
new Map(Object.entries({
name: this.name,
learning_rate: '',
learn_field_weights : '',
enable_learning : '',
device : '',
field_weights: '',
field_names : [],
softmax_gain : '',
seed : '',
memory_capacity : '',
memory_fill : '',
memory_decay_rate : '',
softmax_threshold : '',
normalize_field_weights : '',
concatenate_keys : '',
variant: 'node-gray',
pnlClass: PNLClasses.COMPOSITION,
shape: PNLClasses.COMPOSITION,
Expand Down
26 changes: 21 additions & 5 deletions src/client/model/nodes/mechanism/MechanismNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,15 @@ export default class MechanismNode implements IMetaDiagramConverter {
}

getOptionsFromType(summaries: any, defaults: any) : Map<string, any> {
let classParams = JSON.parse(JSON.stringify(MetaNodeToOptions[this.innerClass]));
console.log("Summaries ", summaries)
console.log(MetaNodeToOptions[this.innerClass])
let classParams;
try {
classParams = JSON.parse(JSON.stringify(MetaNodeToOptions[this.innerClass]));
} catch (error) {
console.error("Failed to parse MetaNodeToOptions:", error);
classParams = {}; // or some sensible default
}
if (summaries !== undefined && summaries.hasOwnProperty(this.name)) {
const summary = summaries[this.name];
classParams = extractParams(summary[this.name], classParams, true);
Expand Down Expand Up @@ -147,24 +155,32 @@ export default class MechanismNode implements IMetaDiagramConverter {
let summary_inputs: any = {};
let summary_outputs: any = {};
if (summaries !== undefined && summaries.hasOwnProperty(this.name)) {
summary_inputs = summaries[this.name][this.name]['input_ports'];
summary_outputs = summaries[this.name][this.name]['output_ports'];
summary_inputs = summaries[this.name][this.name]?.['input_ports'];
summary_outputs = summaries[this.name][this.name]?.['output_ports'];
for (const inputPort in summary_inputs) {
let portEntries = new Map()
if ( summary_inputs?.[inputPort]?.metadata ){
portEntries = new Map(Object.entries(summary_inputs[inputPort].metadata))
}
ports.push(new MetaPort(
inputPort,
inputPort,
PortTypes.INPUT_PORT,
new Point(0, 0),
new Map(Object.entries(summary_inputs[inputPort].metadata)))
portEntries)
);
}
for (const outputPort in summary_outputs) {
let portEntries = new Map()
if ( summary_outputs?.[outputPort]?.metadata ){
portEntries = new Map(Object.entries(summary_outputs[outputPort].metadata))
}
ports.push(new MetaPort(
outputPort,
outputPort,
PortTypes.OUTPUT_PORT,
new Point(0, 0),
new Map(Object.entries(summary_outputs[outputPort].metadata)))
portEntries)
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/client/model/nodes/mechanism/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FunctionsParams, OptionsTypes } from "../utils";

export const extractParams = (base, params, isThisFromSummary) => {
if (base.hasOwnProperty('functions') && base.hasOwnProperty('metadata')) {
if (base?.hasOwnProperty('functions') && base?.hasOwnProperty('metadata')) {
for (const key in params) {
if (key === 'function') {
params[key] = extractFunction(base.functions[Object.keys(base.functions)[0]], isThisFromSummary)
Expand Down
7 changes: 3 additions & 4 deletions src/client/model/state/CreateLinkState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class CreateLinkState extends State<DiagramEngine> {
const link = this.sourcePort?.createLinkModel()! as MetaLinkModel;
const id = link.getID().replaceAll('-', '_');
link.setOption('id', 'projection_' + id.substring(id.length - 12));
link.setSourcePort(this.sourcePort);
link?.setSourcePort(this.sourcePort);

isSourceInPort =
!(this.sourcePort as DefaultPortModel).getOptions()['in'] ?? true;
Expand All @@ -132,7 +132,7 @@ export class CreateLinkState extends State<DiagramEngine> {
clientX - (ox + DEFAULT_EXCLUDE),
clientY - (oy + DEFAULT_EXCLUDE)
);

this.link = this.engine.getModel().addLink(link) as MetaLinkModel;
} else if (
(element instanceof MetaPortModel &&
Expand Down Expand Up @@ -216,8 +216,7 @@ export class CreateLinkState extends State<DiagramEngine> {
createMetaLink(link: MetaLinkModel) {
const modelHandler = ModelSingleton.getInstance();
const metaGraph = modelHandler.getMetaGraph();

metaGraph.addLink(link);
metaGraph?.addLink(link);
}

getEngine() {
Expand Down
6 changes: 3 additions & 3 deletions src/client/services/queryService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ export default class QueryService {
if (summary.hasOwnProperty(nodeName)) {
const nodeInfo: any = summary[nodeName][nodeName];
let ports: string = '[';
for (const inputPort in nodeInfo.input_ports) {
for (const inputPort in nodeInfo?.input_ports) {
ports += `(InputPort ${inputPort}), `;
}
for (const outputPort in nodeInfo.output_ports) {
for (const outputPort in nodeInfo?.output_ports) {
ports += `(OutputPort ${outputPort}), `;
}
return ports.slice(0, -2) + ']';
return ports?.slice(0, -2) + ']';
}
return '[]';
}
Expand Down
43 changes: 42 additions & 1 deletion src/server/api/psnl_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
from os.path import expanduser
from xml.etree.cElementTree import fromstring
import ast
import os
import importlib.util
import sys
import json
import threading
import numpy as np
Expand Down Expand Up @@ -83,14 +86,52 @@ def hashable_pnl_objects(self):
}

def loadScript(self, filepath):
# Expand and set the main filepath
filepath = pnls_utils.expand_path(filepath)
self.filepath = filepath

# Preload modules from the same folder
self.preload_dependencies(filepath)

# Load and parse the main script
with open(filepath, 'r') as f:
f.seek(0)
self.ast = f.read()

# Parse the main script (without parsing the dependencies)
self.modelParser.parse_model(self.ast)

# Generate and return the model
model = self.modelParser.get_graphviz()
return model
return model

def preload_dependencies(self, filepath):
folder = os.path.dirname(filepath)

# Load the main file's AST and find imports
with open(filepath, 'r') as f:
script_ast = ast.parse(f.read())

for node in ast.walk(script_ast):
if isinstance(node, ast.ImportFrom) and node.level == 0: # relative import
module_name = node.module.lstrip()
if module_name and module_name != "psyneulink" : # Only process if the module is specified
self.load_module_from_same_folder(module_name, folder)
elif isinstance(node, ast.Import) : # relative import
for alias in node.names:
if alias.name.lstrip() != "psyneulink":
self.load_module_from_same_folder(alias.name, folder)

def load_module_from_same_folder(self, module_name, folder):
# Convert module name to file path (relative imports)
module_file = os.path.join(folder, module_name.replace('.', '/') + '.py')

if os.path.exists(module_file):
# Import the module dynamically without parsing it with modelParser
spec = importlib.util.spec_from_file_location(module_name, module_file)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

def pnlAPIcall(self, data):
callData = json.loads(data)
Expand Down
Loading

0 comments on commit 0f929b9

Please sign in to comment.