Skip to content

Commit 62e1bc9

Browse files
committed
V3.1
1 parent e36e357 commit 62e1bc9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1844
-876
lines changed

ngcsimlib/__init__.py

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,5 @@
1-
from . import utils
1+
from ngcsimlib._src.component import Component as Component
2+
from ngcsimlib._src.process import Process
23

3-
import argparse, os, json
4-
from types import SimpleNamespace
5-
from importlib import import_module
6-
from ngcsimlib.configManager import init_config, get_config
7-
from ngcsimlib.logger import warn
8-
from pkg_resources import get_distribution
4+
import ngcsimlib.operations
95

10-
__version__ = get_distribution('ngcsimlib').version ## set software version
11-
12-
13-
###### Preload Modules
14-
def preload_modules(path=None):
15-
if path is None:
16-
module_config = get_config("modules")
17-
if module_config is None:
18-
module_path = None
19-
else:
20-
module_path = module_config.get("module_path", None)
21-
22-
if module_path is None:
23-
return
24-
25-
if not os.path.isfile(module_path):
26-
warn("Missing file to preload modules from. Attempted to locate file at \"" + str(module_path) +
27-
"\". No modules will be preloaded. "
28-
"\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/json_modules.html for additional information")
29-
return
30-
else:
31-
module_path = path
32-
33-
with open(module_path, 'r') as file:
34-
modules = json.load(file, object_hook=lambda d: SimpleNamespace(**d))
35-
36-
for module in modules:
37-
load_module(module)
38-
39-
def load_module(module):
40-
mod = import_module(module.absolute_path)
41-
utils.modules._Loaded_Modules[module.absolute_path] = mod
42-
43-
for attribute in module.attributes:
44-
atr = getattr(mod, attribute.name)
45-
utils.modules._Loaded_Attributes[attribute.name] = atr
46-
47-
utils.modules._Loaded_Attributes[
48-
".".join([module.absolute_path, attribute.name])] = atr
49-
if hasattr(attribute, "keywords"):
50-
for keyword in attribute.keywords:
51-
utils.modules._Loaded_Attributes[keyword] = atr
52-
53-
###### Initialize Config
54-
def configure():
55-
parser = argparse.ArgumentParser(description='Build and run a model using ngclearn')
56-
parser.add_argument("--config", type=str, help='location of config.json file')
57-
58-
## ngc-sim-lib only cares about --config argument
59-
args, unknown = parser.parse_known_args() # args = parser.parse_args()
60-
try:
61-
config_path = args.modules
62-
except:
63-
config_path = None
64-
65-
if config_path is None:
66-
config_path = "json_files/config.json"
67-
68-
if not os.path.isfile(config_path):
69-
warn("Missing configuration file. Attempted to locate file at \"" + str(config_path) +
70-
"\". Default Config will be used. "
71-
"\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/configuration.html for "
72-
"additional information")
73-
return
74-
75-
init_config(config_path)

ngcsimlib/_src/__init__.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# from . import utils
2+
#
3+
# import argparse, os, json
4+
# from types import SimpleNamespace
5+
# from importlib import import_module
6+
# from ngcsimlib.configManager import init_config, get_config
7+
# from ngcsimlib.logger import warn
8+
# from pkg_resources import get_distribution
9+
#
10+
# __version__ = get_distribution('ngcsimlib').version ## set software version
11+
#
12+
#
13+
# ###### Preload Modules
14+
# def preload_modules(path=None):
15+
# if path is None:
16+
# module_config = get_config("modules")
17+
# if module_config is None:
18+
# module_path = None
19+
# else:
20+
# module_path = module_config.get("module_path", None)
21+
#
22+
# if module_path is None:
23+
# return
24+
#
25+
# if not os.path.isfile(module_path):
26+
# warn("Missing file to preload modules from. Attempted to locate file at \"" + str(module_path) +
27+
# "\". No modules will be preloaded. "
28+
# "\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/json_modules.html for additional information")
29+
# return
30+
# else:
31+
# module_path = path
32+
#
33+
# with open(module_path, 'r') as file:
34+
# modules = json.load(file, object_hook=lambda d: SimpleNamespace(**d))
35+
#
36+
# for module in modules:
37+
# load_module(module)
38+
#
39+
# def load_module(module):
40+
# mod = import_module(module.absolute_path)
41+
# utils.modules._Loaded_Modules[module.absolute_path] = mod
42+
#
43+
# for attribute in module.attributes:
44+
# atr = getattr(mod, attribute.name)
45+
# utils.modules._Loaded_Attributes[attribute.name] = atr
46+
#
47+
# utils.modules._Loaded_Attributes[
48+
# ".".join([module.absolute_path, attribute.name])] = atr
49+
# if hasattr(attribute, "keywords"):
50+
# for keyword in attribute.keywords:
51+
# utils.modules._Loaded_Attributes[keyword] = atr
52+
#
53+
# ###### Initialize Config
54+
# def configure():
55+
# parser = argparse.ArgumentParser(description='Build and run a model using ngclearn')
56+
# parser.add_argument("--config", type=str, help='location of config.json file')
57+
#
58+
# ## ngc-sim-lib only cares about --config argument
59+
# args, unknown = parser.parse_known_args() # args = parser.parse_args()
60+
# try:
61+
# config_path = args.modules
62+
# except:
63+
# config_path = None
64+
#
65+
# if config_path is None:
66+
# config_path = "json_files/config.json"
67+
#
68+
# if not os.path.isfile(config_path):
69+
# warn("Missing configuration file. Attempted to locate file at \"" + str(config_path) +
70+
# "\". Default Config will be used. "
71+
# "\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/configuration.html for "
72+
# "additional information")
73+
# return
74+
#
75+
# init_config(config_path)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .compartment import Compartment as Compartment
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
from .compartmentMeta import CompartmentMeta
2+
from ngcsimlib._src.global_state.manager import global_state_manager as gState
3+
from ngcsimlib._src.logger import warn
4+
import ast
5+
from typing import TypeVar, Union
6+
from ngcsimlib._src.operations.BaseOp import BaseOp
7+
from ngcsimlib._src.context.context_manager import global_context_manager as gcm
8+
9+
T = TypeVar('T')
10+
11+
class Compartment(metaclass=CompartmentMeta):
12+
"""
13+
Compartments exist as a layer between the global state of models and the
14+
use defined objects. At their core they function akin to pointers where
15+
each compartment stores a key that can be used to access a value in the
16+
global state. If another compartment is wired into a compartment only the
17+
target the compartment is pointing to changes, as such their build value in
18+
the global state will no longer change (it will still exist but just
19+
nothing will access it unless the user manually goes looking for it). The
20+
compartment should be reflected in the global state immediately after it is
21+
initialized. Compartments can be flagged as fixed which means that they
22+
exist in the global state and can be used in compiled methods but they can
23+
not be changed after creation.
24+
25+
Args
26+
initial_value: the initial value to set in the global state
27+
28+
fixed (default=False): sets the flag for if this compartment is fixed.
29+
"""
30+
def __init__(self, initial_value: T, fixed: bool = False):
31+
self._initial_value = initial_value
32+
33+
self.name = None
34+
self._root_target = None
35+
self._target = self._root_target
36+
self._fixed = fixed
37+
38+
@property
39+
def root(self):
40+
return self._root_target
41+
42+
@property
43+
def targeted(self) -> bool:
44+
return self._target != self._root_target
45+
46+
@property
47+
def fixed(self) -> bool:
48+
"""
49+
Returns: if this compartment is a fixed value.
50+
"""
51+
return self._fixed
52+
53+
def _setup(self, objName, compName, path):
54+
self.name = compName
55+
self._root_target = path + ":" + objName + ":" + self.name
56+
self._target = self._root_target
57+
self.set(self._initial_value)
58+
gState.add_compartment(self)
59+
60+
def set(self, value: T) -> None:
61+
"""
62+
Sets the value that this compartment is pointing to in the global state.
63+
This method will abort if either the compartment is flagged as fixed or
64+
the compartment is not pointing to the compartment assigned to it. This
65+
would be the case if something was wired into this compartment.
66+
67+
Args:
68+
value: The value to set in the global state.
69+
"""
70+
if self._fixed:
71+
warn(f"Attempting to set {self._root_target} which is a fixed compartment. Aborting!")
72+
return
73+
if self.target != self._root_target:
74+
warn(f"Attempting to set {self.target} in {self._root_target}. Aborting!")
75+
return
76+
gState.set_state({self.target: value})
77+
78+
def get(self) -> T:
79+
"""
80+
Returns: The value that this compartment is pointing to in the global state.
81+
"""
82+
return self._get_value()
83+
84+
def get_needed_keys(self):
85+
if isinstance(self.target, BaseOp):
86+
return self.target.get_needed_keys()
87+
return set(self.target)
88+
89+
def _get_value(self):
90+
if isinstance(self.target, BaseOp):
91+
return self.target.get()
92+
93+
return gState.from_global_key(self.target)
94+
95+
def __jax_array__(self):
96+
return self.get()
97+
98+
def __str__(self):
99+
return str(self._get_value())
100+
101+
def _to_ast(self, node, ctx):
102+
if isinstance(self.target, str):
103+
return ast.Subscript(
104+
value=ast.Name(id=ctx, ctx=ast.Load()),
105+
slice=ast.Constant(value=self.target),
106+
ctx=node.ctx
107+
)
108+
return self.target._to_ast(node, ctx)
109+
110+
def __rrshift__(self, other):
111+
gcm.current_context.add_connection(other, self)
112+
self.target = other
113+
114+
def __rshift__(self, other):
115+
if isinstance(other, Compartment):
116+
other.__rrshift__(self)
117+
118+
@property
119+
def target(self):
120+
"""
121+
Returns: the current target of the compartment
122+
"""
123+
return self._target
124+
125+
@target.setter
126+
def target(self, value: Union["Compartment", "BaseOp", str]):
127+
"""
128+
Sets the target of the compartment to the provided value. It will fail
129+
if the value is not either another compartment or an operation.
130+
131+
Args:
132+
value: The value to target this compartment at.
133+
"""
134+
if isinstance(value, (str, BaseOp)):
135+
self._target = value
136+
return
137+
138+
if isinstance(value, Compartment):
139+
self._target = value.target
140+
return
141+
142+
if isinstance(value, str):
143+
self._target = value
144+
145+
raise ValueError("Invalid compartment target ", value)

ngcsimlib/compartment/compartmentMeta.py renamed to ngcsimlib/_src/compartment/compartmentMeta.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import operator
2-
import types
2+
from typing import Any
33

4-
def _unwrap(x):
4+
5+
def _unwrap(x: Any) -> Any:
56
while hasattr(x, "_get_value"):
67
x = x._get_value()
78
return x
@@ -16,8 +17,6 @@ def _unwrap(x):
1617
'__floordiv__': operator.floordiv,
1718
'__mod__': operator.mod,
1819
'__pow__': operator.pow,
19-
'__lshift__': operator.lshift,
20-
'__rshift__': operator.rshift,
2120
'__and__': operator.and_,
2221
'__xor__': operator.xor,
2322
'__or__': operator.or_,
@@ -29,9 +28,15 @@ def _unwrap(x):
2928
'__ge__': operator.ge,
3029
}
3130

32-
_REVERSE_OPS = {f"__r{name[2:]}__": op for name, op in _BINARY_OPS.items()}
31+
_REVERSE_OPS = {f"__r{name[2:]}": op for name, op in _BINARY_OPS.items()}
3332

3433
class CompartmentMeta(type):
34+
"""
35+
This is the metaclass for compartments. It mostly exists to sit on top of
36+
objects that can be used as targets for compartments. It is rare that users
37+
of ngclearn will need to interface with this directly. If you are here
38+
trying to learn about compartments look at their file directly.
39+
"""
3540
def __new__(mcs, name, bases, namespace):
3641
def make_op(opfunc):
3742
def method(self, other):
@@ -45,5 +50,4 @@ def method(self, other):
4550
for dunder_name, opfunc in _REVERSE_OPS.items():
4651
if dunder_name not in namespace:
4752
namespace[dunder_name] = make_op(opfunc)
48-
4953
return super().__new__(mcs, name, bases, namespace)

ngcsimlib/_src/component.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from ngcsimlib._src.context.contextAwareObject import ContextAwareObject
2+
from ngcsimlib._src.context.contextObjectDecorators import component
3+
from ngcsimlib._src.compartment.compartment import Compartment
4+
from ngcsimlib._src.parser.utils import compilable
5+
from typing import List, Tuple, Dict, Any
6+
7+
8+
@component
9+
@compilable
10+
class Component(ContextAwareObject):
11+
"""
12+
Component is a base class of context aware objects that are also specially
13+
tracked by contexts. They are expected to make up a large amount of
14+
user-defined classes as they will be the various parts of models.
15+
"""
16+
def __init__(self, name):
17+
super().__init__(name)
18+
19+
@property
20+
def compartments(self) -> List[Tuple[str, Compartment]]:
21+
"""
22+
It is expected that components will have compartments, and this allows
23+
for easy iteration over all the compartments in a component.
24+
Returns: a list of compartments found on this component
25+
"""
26+
return [(n, v) for n, v in vars(self).items() if isinstance(v, Compartment)]

ngcsimlib/_src/context/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from .contextAwareObject import ContextAwareObject
2+
3+
from .context import Context as Context # Needs to be after ContextAwareObject
4+
from .context import ContextObjectTypes as ContextObjectTypes
5+
6+
from .context_manager import global_context_manager as global_context_manager
7+
from .contextObjectDecorators import (
8+
component as component,
9+
process as process
10+
)

0 commit comments

Comments
 (0)