Skip to content

Commit

Permalink
Refactor/log/entry management (#579)
Browse files Browse the repository at this point in the history
* • System
  - show_graph():
    fixed bug producing empty image for graphs with just one Mechanism
    added auto-recurrent projections

* • Log
  - added numpy_array output method

* • Log
  - docstring corrections

* • Log
  - changed all references to LogEntry to use field names
  - EntryDict: added valiation of assignments as LogEntry in setter

* • Log
  - changed all references to LogEntry to use field names
  - EntryDict: added valiation of assignments as LogEntry in setter

* • Log
  - changed all references to LogEntry to use field names
  - EntryDict: added valiation of assignments as LogEntry in setter

• Tests
  - added TestLog

* • Component:
  - make_property (Line 2883): changed return value

* • Component:
  - make_property (Line 2883): changed return value

* -

* -

* • Log
  - refactored to keep data for a Compoent in its *own* Log,
    and have others that require that data to reference it

* • Log
  - refactored to keep data for a Compoent in its *own* Log,
    and have others that require that data to reference it

* -

* -
  • Loading branch information
jdcpni authored Dec 6, 2017
1 parent 6b38083 commit 20b5a07
Show file tree
Hide file tree
Showing 47 changed files with 793 additions and 398 deletions.
6 changes: 4 additions & 2 deletions Scripts/Examples/Multilayer-Learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ def show_target(system):
)

# Log Middle_Weights of MappingProjection to Hidden_Layer_2
Hidden_Layer_2.log_items('Middle Weights')
# Hidden_Layer_2.log_items('Middle Weights')
Middle_Weights.log_items('matrix')

mySystem.reportOutputPref = True
# Shows graph will full information:
Expand All @@ -125,4 +126,5 @@ def show_target(system):
)

# Print out logged weights for Middle_Weights
print('\nMiddle Weights (to Hidden_Layer_2): \n', Hidden_Layer_2.log.csv(entries='Middle Weights'))
# print('\nMiddle Weights (to Hidden_Layer_2): \n', Hidden_Layer_2.log.nparray(entries='Middle Weights', header=False))
print('\nMiddle Weights (to Hidden_Layer_2): \n', Middle_Weights.log.nparray(entries='matrix', header=False))
355 changes: 284 additions & 71 deletions Scripts/Scratch Pad.py

Large diffs are not rendered by default.

134 changes: 67 additions & 67 deletions psyneulink/components/functions/function.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ class ControlMechanism(AdaptiveMechanism_Base):
specifies the default form of modulation used by the ControlMechanism's `ControlSignals <ControlSignal>`,
unless they are `individually specified <ControlSignal_Specification>`.
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters
for the Mechanism, parameters for its function, and/or a custom function and its parameters. Values
specified for parameters in the dictionary override any assigned to those parameters in arguments of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class GatingMechanism(AdaptiveMechanism_Base):
specifies the default form of modulation used by the GatingMechanism's `GatingSignals <GatingSignal>`,
unless they are `individually specified <GatingSignal_Specification>`.
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters
for the Mechanism, parameters for its function, and/or a custom function and its parameters. Values
specified for parameters in the dictionary override any assigned to those parameters in arguments of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ class LearningMechanism(AdaptiveMechanism_Base):
specifies the learning rate for the LearningMechanism (see `learning_rate <LearningMechanism.learning_rate>`
for details).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that specifies the parameters for the
Projection, its function, and/or a custom function and its parameters. By default, it contains an entry for
the Projection's default `function <LearningProjection.function>` and parameter assignments. Values specified
Expand Down
7 changes: 4 additions & 3 deletions psyneulink/components/mechanisms/mechanism.py
Original file line number Diff line number Diff line change
Expand Up @@ -1123,13 +1123,14 @@ class ClassDefaults(Mechanism.ClassDefaults):
# Class-specific loggable items
@property
def _loggable_items(self):
# States and afferent Projections are loggable for a Mechanism
# States, afferent Projections are loggable for a Mechanism
# - this allows the value of InputStates and OutputStates to be logged
# - for MappingProjections, this logs the value of the Projection's matrix parameter
# - for ModulatoryProjections, this logs the value of the Projection
# IMPLEMENTATION NOTE: this needs to be a property as projections may be added after initialization
# IMPLEMENTATION NOTE: this needs to be a property as Projections may be added after instantiation
try:
return list(self.states) + list(self.afferents)
# return list(self.states) + list(self.afferents)
return list(self.states)
except:
return []

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class CompositionInterfaceMechanism(ProcessingMechanism_Base):
specifies the function used to integrate the input. Must take a single numeric value, or a list or np.array
of values, and return one of the same form.
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specifying_Parameters>` that can be used to specify the parameters for
the `Mechanism <Mechanism>`, parameters for its `function <CompositionInterfaceMechanism.function>`, and/or a
custom function and its parameters. Values specified for parameters in the dictionary override any assigned
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class IntegratorMechanism(ProcessingMechanism_Base):
specifies the function used to integrate the input. Must take a single numeric value, or a list or np.array
of values, and return one of the same form.
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for
the Mechanism, parameters for its `function <IntegratorMechanism.function>`, and/or a custom function and its
parameters. Values specified for parameters in the dictionary override any assigned to those parameters in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ class ObjectiveMechanism(ProcessingMechanism_Base):
role: Optional[LEARNING, CONTROL]
specifies if the ObjectiveMechanism is being used for learning or control (see `role` for details).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for the
Mechanism, its `function <Mechanism_Base.function>`, and/or a custom function and its parameters. Values
specified for parameters in the dictionary override any assigned to those parameters in arguments of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ class TransferMechanism(ProcessingMechanism_Base):
specified in **input_states**; see `note <TransferMechanism_OutputStates_Note>`, and `output_states
<TransferMechanism.output_states>` for additional details).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for
the Mechanism, its `function <Mechanism_Base.function>`, and/or a custom function and its parameters. Values
specified for parameters in the dictionary override any assigned to those parameters in arguments of the
Expand Down
2 changes: 1 addition & 1 deletion psyneulink/components/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2111,7 +2111,7 @@ def execute(self,
time_scale : TimeScale : default TimeScale.TRIAL
specifies whether Mechanisms are executed for a single time step or a trial.
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can include any of the parameters used
as arguments to instantiate the object. Use parameter's name as the keyword for its entry. Values specified
for parameters in the dictionary override any assigned to those parameters in arguments of the constructor.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@ class ControlProjection(ModulatoryProjection_Base):
specifies the value by which to exponentiate the ControlProjection's `value <ControlProjection.value>`
before combining it with others (see `exponent <ControlProjection.exponent>` for additional details).
control_signal_params pip install --updgrade Sphinx==1.6.2 sphinx-rtd-theme==0.2.4 sphinxcontrib-websupport==1.0.1: Dict[param keyword, param value]
control_signal_params pip install --updgrade Sphinx==1.6.2 sphinx-rtd-theme==0.2.4 sphinxcontrib-websupport==1.0.1: Dict[param keyword: param value]
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for the
ControlProjection's `sender <ControlProjection.sender>` (see `ControlSignal_Structure` for a description
of ControlSignal parameters).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for
the ControlProjection, its `function <ControlProjection.function>`, and/or a custom function and its parameters.
Values specified for parameters in the dictionary override any assigned to those parameters in arguments of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,12 @@ class GatingProjection(ModulatoryProjection_Base):
specifies the value by which to exponentiate the GatingProjection's `value <GatingProjection.value>`
before combining it with others (see `exponent <GatingProjection.exponent>` for additional details).
gating_signal_params : Dict[param keyword, param value]
gating_signal_params : Dict[param keyword: param value]
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for the
GatingProjection's `sender <ControlProjection.sender>` (see `GatingSignal_Structure` for a description
of GatingSignal parameters).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for
the GatingProjection, its `function <GatingProjection.function>`, and/or a custom function and its parameters.
Values specified for parameters in the dictionary override any assigned to those parameters in arguments of the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ class LearningProjection(ModulatoryProjection_Base):
specifies the value by which to exponentiate the LearningProjection's `value <LearningProjection.value>`
before combining it with others (see `exponent <LearningProjection.exponent>` for additional details).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that specifies the parameters for the
Projection, its function, and/or a custom function and its parameters. By default, it contains an entry for
the Projection's default `function <LearningProjection.function>` and parameter assignments. Values specified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class ModulatoryProjection_Base(Projection_Base):
specifies the value by which to exponentiate the ModulatoryProjection's `value <ModulatoryProjection.value>`
before combining it with others (see `exponent <ModulatoryProjection.exponent>` for additional details).
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that specifies the parameters for the
ModulatoryProjection, its `function <ModulatoryProject.function>`, and/or a custom function and its parameters.
By default, it contains an entry for the ModulatoryProjection's default `function <ModulatoryProject.function>`
Expand Down Expand Up @@ -244,43 +244,3 @@ def _assign_default_projection_name(self, state=None, sender_name=None, receiver
else:
raise ModulatoryProjectionError("PROGRAM ERROR: {} has unrecognized InitStatus ({})".
format(self, self.init_status))

@property
def value(self):
return self._value

@value.setter
def value(self, assignment):

# MODIFIED 7/8/17 OLD:
# from math import isnan
# if isinstance(assignment, np.ndarray) and assignment.ndim == 2 and isnan(assignment[0][0]):
# TEST = True
# MODIFIED 7/8/17 END

self._value = assignment

# STORE value IN log IF SPECIFIED

# Get context
try:
curr_frame = inspect.currentframe()
prev_frame = inspect.getouterframes(curr_frame, 2)
context = inspect.getargvalues(prev_frame[1][0]).locals['context']
except KeyError:
context = ""
if not isinstance(context, str):
context = ""

# Get logPref
log_pref = self.prefs.logPref if self.prefs else None
sender_log_pref = self.sender.owner.prefs.logPref if self.sender.owner.prefs else None

# If context is consistent with log_pref, record value to log
if (log_pref is LogLevel.ALL_ASSIGNMENTS or
(INITIALIZING in context and LogLevel.INITIALIZATION in {log_pref, sender_log_pref}) or
(EXECUTING in context and log_pref is LogLevel.EXECUTION) or
(all(c in context for c in {EXECUTING, kwAssign}) and log_pref is LogLevel.VALUE_ASSIGNMENT)
):
self.owner.log.entries[self.name] = LogEntry(CurrentTime(), context, assignment)
# self.owner.log.entries[self.name] = LogEntry(CentralClock, context, assignment)
72 changes: 34 additions & 38 deletions psyneulink/components/projections/pathway/mappingprojection.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ class MappingProjection(PathwayProjection_Base):
value of the `sender <MappingProjection.sender>` into a form suitable for the `variable <InputState.variable>`
of its `receiver <MappingProjection.receiver>`.
params : Dict[param keyword, param value] : default None
params : Dict[param keyword: param value] : default None
a `parameter dictionary <ParameterState_Specification>` that can be used to specify the parameters for
the Projection, its function, and/or a custom function and its parameters. By default, it contains an entry for
the Projection's default assignment (`LinearCombination`). Values specified for parameters in the dictionary
Expand Down Expand Up @@ -516,9 +516,11 @@ def _instantiate_parameter_states(self, context=None):
initializer=matrix,
# rate=initial_rate
)

self._parameter_states[MATRIX]._function = self._parameter_states[MATRIX].function_object.function

# # Assign ParameterState the same Log as the MappingProjection, so that its entries are accessible to Mechanisms
# self._parameter_states[MATRIX].log = self.log

def _instantiate_receiver(self, context=None):
"""Determine matrix needed to map from sender to receiver
Expand Down Expand Up @@ -656,42 +658,26 @@ def matrix(self, matrix):

self.function_object.matrix = matrix

# Log matrix value if specified by owner, sender, or sender's owner

# Get context
try:
curr_frame = inspect.currentframe()
prev_frame = inspect.getouterframes(curr_frame, 2)
context = inspect.getargvalues(prev_frame[2][0]).locals['context']
except KeyError:
context = ""

# Get logPref
self_log_pref = self.prefs.logPref if self.prefs else None

loggers = [

# Log to self for logPref
(self.name, self.log, self_log_pref),

# Use self.logPref to log to receiver's log if name of self is in receiver's log.entries;
# otherwise use receiver's logPref
(self.receiver.name, self.receiver.log,
self_log_pref if self.name in self.receiver.log.loggable_items else self.receiver.logPref),

# Use self.logPref to log to receiver owner's log if name of self is in receiver owner's log.entries
# otherwise use receiver owner's logPref
(self.receiver.owner.name, self.receiver.owner.log,
self_log_pref if self.name in self.receiver.owner.log.loggable_items else self.receiver.owner.logPref)
]

# Go through loggers, and if context is consistent with log_pref of logger, record value to logger's log
for log_name, log, log_pref in loggers:
if (log_pref is LogLevel.ALL_ASSIGNMENTS or
(INITIALIZING in context and log_pref is LogLevel.INITIALIZATION) or
(EXECUTING in context and log_pref is LogLevel.EXECUTION) or
(all(c in context for c in {EXECUTING, kwAssign}) and log_pref is LogLevel.VALUE_ASSIGNMENT)):
log.entries[self.name] = LogEntry(CurrentTime(), context, matrix)
# # Log matrix value if specified by owner, sender, or sender's owner
#
# # Get context
# try:
# curr_frame = inspect.currentframe()
# prev_frame = inspect.getouterframes(curr_frame, 2)
# context = inspect.getargvalues(prev_frame[2][0]).locals['context']
# except KeyError:
# context = ""

# # Get logPref
# self_log_pref = self.prefs.logPref if self.prefs else None
#
# # Go through loggers, and if context is consistent with log_pref of logger, record value to logger's log
# for log_name, log, log_pref in loggers:
# if (log_pref is LogLevel.ALL_ASSIGNMENTS or
# (INITIALIZING in context and log_pref is LogLevel.INITIALIZATION) or
# (EXECUTING in context and log_pref is LogLevel.EXECUTION) or
# (all(c in context for c in {EXECUTING, kwAssign}) and log_pref is LogLevel.VALUE_ASSIGNMENT)):
# log.entries[self.name] = LogEntry(CurrentTime(), context, matrix)


@property
Expand Down Expand Up @@ -726,3 +712,13 @@ def _matrix_spec(self, value):

else:
self.paramsCurrent[FUNCTION_PARAMS].__additem__(MATRIX, value)

@property
def logPref(self):
return self.prefs.logPref

# Always assign matrix Parameter state the same logPref as the MappingProjection
@logPref.setter
def logPref(self, setting):
self.prefs.logPref = setting
self.parameter_states[MATRIX].logPref = setting
Loading

0 comments on commit 20b5a07

Please sign in to comment.