Log¶
Overview¶
A Log object is used to record the value
of PsyNeuLink Components during their “life cycle” (i.e.,
when they are created, validated, and/or executed). Every Component has a Log object, assigned to its log
attribute when the Component is created, that can be used to record its value and/or that of other
Components that belong to it. These are stored in entries
of the Log, that contain a sequential list
of the recorded values, along with the time and context of the recording. The conditions under which values are
recorded is specified by the logPref
property of a Component. While these can be set directly,
they are most easily specified using the Log’s set_log_conditions
method, together with its
loggable_items
and logged_items
attributes that identify and track the
items to be logged, respectively. Entries can also be made by the user programmatically, using the log_values
method. Logging can be useful not only for observing the behavior of a Component in a model, but also
in debugging the model during construction. The entries of a Log can be displayed in a “human readable” table using
its print_entries
method, and returned in CSV and numpy array formats using its and nparray
, nparray_dictionary
and csv
methods, respectively.
Creating Logs and Entries¶
A log object is automatically created for and assigned to a Component’s log
attribute when the
Component is created. An entry is automatically created and added to the Log’s entries
attribute
when its value
or that of a Component that belongs to it is recorded in the Log.
Structure¶
A Log is composed of entries
, each of which is a dictionary that maintains a record of the logged
values of a Component. The key for each entry is a string that is the name of the Component, and its value is a list
of LogEntry
tuples recording its values. Each LogEntry
tuple has three items:
The time is recorded only if the Component is executed within a System
; otherwise, the time field is None
.
A Log has several attributes and methods that make it easy to manage how and when it values are recorded, and
to access its entries
:
loggable_items
– a dictionary with the items that can be logged in a Component’slog
; the key for each entry is the name of a Component, and the value is the currently assigned condition(s) under which it will be logged.
set_log_conditions
– used to assign the condition for logging one or more Components. Components can be specified by their names, a reference to the Component object, in a tuple that specifies the condition(s) for logging that Component, or in a list with a condition to be assigned to multiple items at once.
log_values
– used to thevalue
of one or more Components in the Log programmatically (“manually”). Components can be specified by their names or references to the objects.
logged_items
– a dictionary with the items that currently have entries in a Component’slog
; the key for each entry is the name of a Component, and the condition(s) under which it is being logged.
print_entries
– this prints a formatted list of theentries
in the Log.
nparray_dictionary
– returns a dictionary of np.arrays with theentries
in the Log.
Loggable Items¶
Although every Component is assigned its own Log, that records the value
of that Component,
the Logs for Mechanisms and MappingProjections also provide access to and control
the Logs of their Ports. Specifically the Logs of these Components contain the following information:
Mechanisms
value – the
value
of the Mechanism.InputPorts – the
value
of any InputPort (listed in the Mechanism’sinput_ports
attribute).ParameterPorts – the
value
of ParameterPort (listed in the Mechanism’sparameter_ports
attribute); this includes all of theuser configurable
parameters of the Mechanism and itsfunction
.OutputPorts – the
value
of any OutputPort (listed in the Mechanism’soutput_ports
attribute).
Projections
value – the
value
of the Projection.matrix – the value of the
matrix
parameter (for MappingProjections only).
Logging Conditions¶
Configuring a Component to be logged is done using a condition, that specifies a LogCondition
under which its
value
should be entered in its Log. These can be specified in the set_log_conditions
method of a Log, or directly by specifying a LogCondition
for the value a Component’s
logPref
item of its prefs
attribute. The former is easier, and allows
multiple Components to be specied at once, while the latter affords more control over the specification (see
Preferences). LogConditions
are treated as binary “flags”, and can be combined to permit logging
under more than one condition using bitwise operators on the LogConditions
. For convenience, they
can also be referred to by their names, and combined by specifying a list. For example, all of the following specify
that the value
of my_mech
be logged both during execution and learning:
>>> import psyneulink as pnl
>>> my_mech = pnl.TransferMechanism()
>>> my_mech.set_log_conditions('value', pnl.LogCondition.EXECUTION | pnl.LogCondition.LEARNING)
>>> my_mech.set_log_conditions('value', pnl.LogCondition.EXECUTION + pnl.LogCondition.LEARNING)
>>> my_mech.set_log_conditions('value', [pnl.EXECUTION, pnl.LEARNING])
Note
Currently, the VALIDATION
LogCondition
is not implemented.
Note
Using LogCondition.INITIALIZATION
to log the value
of a Component during its initialization
requires that it be assigned in the prefs argument of the Component’s constructor. For example:
>>> my_mech = pnl.TransferMechanism(
... prefs={pnl.LOG_PREF: pnl.PreferenceEntry(pnl.LogCondition.INITIALIZATION, pnl.PreferenceLevel.INSTANCE)})
Hint
LogCondition.TRIAL
logs the value
of a Component at the end of a TRIAL
.
To log its value
at the start of a TRIAL
, use its log_values
method in the call_before_trial argument of the System’s run
method.
Execution¶
The value of a Component is recorded to a Log when the condition assigned to its logPref
is met.
This is specified as a LogCondition
or a boolean combination of them (see Logging Conditions). The default LogCondition
is OFF
.
Examples
The following example creates a Composition with two TransferMechanisms, one that projects to
another, and logs the noise
and RESULT OutputPort of the first and the
MappingProjection from the first to the second:
# Create a Process with two TransferMechanisms, and get a reference for the Projection created between them:
>>> my_mech_A = pnl.TransferMechanism(name='mech_A', input_shapes=2)
>>> my_mech_B = pnl.TransferMechanism(name='mech_B', input_shapes=3)
>>> my_composition = pnl.Composition(pathways=[my_mech_A, my_mech_B])
>>> proj_A_to_B = my_mech_B.path_afferents[0]
# Show the loggable items (and current condition assignments) for each Mechanism and the Projection between them:
>> my_mech_A.loggable_items
{'InputPort-0': 'OFF', 'slope': 'OFF', 'RESULT': 'OFF', 'integration_rate': 'OFF', 'intercept': 'OFF', 'noise': 'OFF'}
>> my_mech_B.loggable_items
{'InputPort-0': 'OFF', 'slope': 'OFF', 'RESULT': 'OFF', 'intercept': 'OFF', 'noise': 'OFF', 'integration_rate': 'OFF'}
>> proj_A_to_B.loggable_items
{'value': 'OFF', 'matrix': 'OFF'}
# Assign the noise parameter and RESULT OutputPort of my_mech_A, and the matrix of the Projection, to be logged
>>> my_mech_A.set_log_conditions([pnl.NOISE, pnl.RESULT])
>>> proj_A_to_B.set_log_conditions(pnl.MATRIX)
Note that since no condition was specified, the default (LogCondition.EXECUTION) is used. Executing the Process generates entries in the Logs, that can then be displayed in several ways:
# Execute the System twice (to generate some values in the logs):
>> my_system.execute()
[array([ 0., 0., 0.])]
>> my_system.execute()
[array([ 0., 0., 0.])]
# List the items of each Mechanism and the Projection that were actually logged:
>> my_mech_A.logged_items
{'RESULT': 'EXECUTION', 'noise': 'EXECUTION'}
>> my_mech_B.logged_items
{}
>> proj_A_to_B.logged_items
{'matrix': 'EXECUTION'}
Notice that entries dictionary of the Log for my_mech_B
is empty, since no items were specified to be logged for
it. The results of the two other logs can be printed to the console using the print_entries
method of a Log:
# Print the Log for ``my_mech_A``:
>> my_mech_A.log.print_entries()
Log for mech_A:
Logged Item: Time Context Value
'RESULT' 0:0:0 " EXECUTING System System-0| Mechanism: mech_A [in processes: ['Pro..." [ 0. 0.]
'RESULT' 0:1:0 " EXECUTING System System-0| Mechanism: mech_A [in processes: ['Pro..." [ 0. 0.]
'noise' 0:0:0 " EXECUTING System System-0| Mechanism: mech_A [in processes: ['Pro..." [ 0.]
'noise' 0:1:0 " EXECUTING System System-0| Mechanism: mech_A [in processes: ['Pro..." [ 0.]
They can also be exported in numpy array and CSV formats. The following shows the CSV-formatted output of the Logs
for my_mech_A
and proj_A_to_B
, using different formatting options:
>> print(my_mech_A.log.csv(entries=[pnl.NOISE, pnl.RESULT], owner_name=False, quotes=None))
'Run', 'Trial', 'Time_step', 'noise', 'RESULT'
0, 0, 0, 0.0, 0.0 0.0
0, 1, 0, 0.0, 0.0 0.0
# Display the csv formatted entry of Log for ``proj_A_to_B``
# with quotes around values and the Projection's name included in the header:
>> print(proj_A_to_B.log.csv(entries=pnl.MATRIX, owner_name=False, quotes=True))
'Run', 'Trial', 'Time_step', 'matrix'
'0', '0', '1', '1.0 1.0 1.0' '1.0 1.0 1.0'
'0', '1', '1', '1.0 1.0 1.0' '1.0 1.0 1.0'
Note that since the name
attribute of the Projection was not assigned, its default name is
reported.
The following shows the Log of proj_A_to_B
in numpy array format, with and without header information:
>> proj_A_to_B.log.nparray(entries=[pnl.MATRIX], owner_name=False, header=True)
[[['Run'] [0] [0]]
[['Trial'] [0] [1]]
[['Time_step'] [1] [1]]
['matrix' [[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]] [[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]]]]
>> proj_A_to_B.log.nparray(entries=[pnl.MATRIX], owner_name=False, header=False)
[[[0] [0]]
[[0] [1]]
[[1] [1]]
[[[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]] [[1.0, 1.0, 1.0], [1.0, 1.0, 1.0]]]]
Class Reference¶
- class psyneulink.core.globals.log.Log(owner, entries=None)¶
Maintain a Log for an object, which contains a dictionary of logged value(s).
- loggable_components¶
each item is a Component that is loggable for the Log’s
owner
- Type
ContentAddressableList
- loggable_items¶
identifies Components that can be logged by the owner; the key of each entry is the name of a Component, and the value is its currently assigned
LogCondition
.- Type
Dict[Component.name: List[LogEntry]]
- entries¶
contains the logged information for
loggable_components
; the key of each entry is the name of a Component, and its value is a list ofLogEntry
items for that Component. Only Components for which information has been logged appear in theentries
dict.- Type
Dict[Component.name: List[LogEntry]]
- logged_items¶
identifies Components that currently have entries in the Log; the key for each entry is the name of a Component, and the value is its currently assigned
LogCondition
.- Type
Dict[Component.name: List[LogEntry]]
- set_log_conditions(items, log_condition=LogCondition.EXECUTION)¶
Specifies items to be logged under the specified
LogCondition
(s).- Parameters
items (str, Component, tuple or List of these) – specifies items to be logged; these must be be
loggable_items
of the Log. Each item must be a: * string that is the name of aloggable_item
<Log.loggable_item>` of the Log’sowner
; * a reference to a Component; * tuple, the first item of which is one of the above, and the second aContextFlags
to use for the item.log_condition (LogCondition : default LogCondition.EXECUTION) – specifies
LogCondition
to use as the default for items not specified in tuples (see above). For convenience, the name of a LogCondition can be used in place of its full specification (e.g., EXECUTION instead ofLogCondition.EXECUTION
).params_set (list : default None) – list of parameters to include as loggable items; these must be attributes of the
owner
(for example, Mechanism
- _set_delivery_conditions(items, delivery_condition=LogCondition.EXECUTION)¶
Specifies items to be delivered via gRPC under the specified
LogCondition
(s).- Parameters
items (str, Component, tuple or List of these) – specifies items to be logged; these must be be
loggable_items
of the Log. Each item must be a: * string that is the name of aloggable_item
<Log.loggable_item>` of the Log’sowner
; * a reference to a Component; * tuple, the first item of which is one of the above, and the second aContextFlags
to use for the item.delivery_condition (LogCondition : default LogCondition.EXECUTION) – specifies
LogCondition
to use as the default for items not specified in tuples (see above). For convenience, the name of a LogCondition can be used in place of its full specification (e.g., EXECUTION instead ofLogCondition.EXECUTION
).params_set (list : default None) – list of parameters to include as loggable items; these must be attributes of the
owner
(for example, Mechanism
- _log_value(value, time=None, condition=None, context=None)¶
Add LogEntry to an entry in the Log
If value is a LogEntry, it is assigned to the entry If condition is specified, it is used to determine whether the value is logged; time must be passed. Otherwise, the Component’s
log_pref
attribute is used to determine whether value is logged. If value is specified, that is the value logged; otherwise the owner’svalue
attribute is logged.
- clear_entries(entries='all', delete_entry=True, confirm=False, contexts=NotImplemented)¶
Clear one or more entries either by deleting the entry or just removing its data.
- Parameters
entries (string, Component or list containing either : default ALL) – specifies the entries of the Log to be cleared; they must be
loggable_items
of the Log that have been logged (i.e., are alsologged_items
). If entries is ALL or is not specified, then alllogged_items
are cleared.delete_entry (bool : default True) –
specifies whether to delete the entry (if
True
) from the log to which it belongs, or just delete the data, but leave the entry itself (ifFalse
).Note
This option is included for generality and potential future state_features, but is not advised; the Log interface (e.g., the
logged_items
interface generally assumes that the onlyentries
in a log are ones with data.confirm (bool : default False) –
specifies whether user confirmation is required before clearing the entries.
Note
If confirm is
True
, only a single confirmation will occur for a list or ALL
- print_entries(entries='all', width=120, display='all', contexts=NotImplemented, exclude_sims=False)¶
Print summary of the Log’s entries in a (human-readable) table format.
- Parameters
entries (string, Component or list containing either : default ALL) – specifies the entries of the Log to printed; they must be
loggable_items
of the Log that have been logged (i.e., are alsologged_items
). If entries is ALL or is not specified, then alllogged_items
are printed.width (int : default 120) – specifies the width of the display. The widths of each column are adjusted accordingly, and based on which items are displayed (see display below); information that does not fit within its column’s width is truncated and suffixes with an ellipsis.
display (TIME, CONTEXT, VALUE, a list containing any of these, or ALL : default ALL) – specifies the information items to display. The name of the entry is always displayed, followed by the specified items; the widths of the columns for the items is dynamically adjusted, based on how many are specified, allowing more information about one to be shown by omitting others (this is useful if the context strings are long and/or the values are arrays).
exclude_sims –
set to True to exclude from output any values logged during simulations
- default value
False
- type
bool
- nparray(entries=None, header=True, owner_name=False, report_all_executions=False, exclude_sims=False, contexts=NotImplemented)¶
Return a 2d numpy array with headers (optional) and values for the specified entries.
Each row (axis 0) is a time series, with each item in each row the data for the corresponding time point. Rows are ordered in the same order as Components are specified in the entries argument.
If all of the data for every entry has a time value (i.e., the time field of its LogEntry is not
None
), then the first four rows are time indices for the run, trial, pass, and time_step of each data item, respectively. Each subsequent row is the times series of data for a given entry. If there is no data for a given entry at a given time point, it is entered asNone
.If any of the data for any entry does not have a time value (e.g., if that Component was not run within a Composition), then all of the entries must have the same number of data (LogEntry) items, and the first row is a sequential index (starting with 0) that simply designates the data item number.
Note
For data without time stamps, the nth items in each entry (i.e., ones in the same column) are not guaranteed to have been logged at the same time point.
If header is
True
, the first item of each row is a header field: for time indices it is either “Run”, “Trial”, and “Time_step”, or “Index” if any data are missing time stamps. For subsequent rows it is the name of the Component logged in that entry (see owner_name argument below for formatting).- Parameters
entries (string, Component or list containing either : default ALL) – specifies the entries of the Log to be included in the output; they must be
loggable_items
of the Log that have been logged (i.e., are alsologged_items
). If entries is ALL or is not specified, then alllogged_items
are included.report_all_executions (bool : default False) – specifies whether to report all executions within a given
TIME_STEP
(if True) or just the last (if False, the default). This in only relevant for Mechanisms that can be executed multiple times within aTIME_STEP
(e.g., TransferMechanism and DDM) when theirexecute_until_finished
attribute is set to True (seeComponent_Execute_Until_Finished
for additional details).exclude_sims – set to True to exclude from output any values logged during simulations :default value: False :type: bool
header (bool : default True) – specifies whether or not to include a header in each row with the name of the Component for that entry.
owner_name (bool : default False) – specifies whether or not to include the Log’s
owner
in the header of each field; if it is True, the format of the header for each field is “<Owner name>[<entry name>]”; otherwise, it is “<entry name>”.Returns – 2d np.array
- nparray_dictionary(entries=None, report_all_executions=False, exclude_sims=False)¶
Returns an OrderedDict
Keys:
Keys of the OrderedDict are strings.
Keys are the names of logged Components specified in the entries argument, plus either Run, Trial, Pass, and Time_step, or Index.
If all of the data for every entry has a time value (i.e., the time field of its LogEntry is not
None
), then the first four keys are Run, Trial, Pass, and Time_step, respectively.If any of the data for any entry does not have a time value (e.g., if that Component was not run within a System), then all of the entries must have the same number of data (LogEntry) items, and the first key is Index.
Then, the logged components follow in the same order as they were specified.
Values:
Values of the OrderedDict are numpy arrays.
The numpy array value for a given component key consists of that logged Component’s data over many time points or executions.
The numpy array values for Run, Trial, Pass, and Time_step are counters for each of those time scales. The ith elements of the Run, Trial, Pass, Time_step and component data arrays can be taken together to represent the value of that component during a particular time step of a particular trial of a particular run.
For example, if log_dict is a log dictionary in which log_dict[‘slope’][5] = 2.0, log_dict[‘Time_step’][5] = 1, log_dict[‘Pass’][5] = 0, log_dict[‘Trial’][5] = 2, and log_dict[‘Run’][5] = 0, then the value of slope was 2.0 during time step 1 of pass 0 of trial 2 of run 0. If there is no data for a given entry at a given time point, it is entered as
None
.The numpy array value for Index is a sequential index starting at zero.
Note
For data without time stamps, the nth item in each dictionary key (i.e., data in the same “column”) is not guaranteed to have been logged at the same time point across all keys (Components).
- Parameters
entries (string, Component or list containing either : default ALL) – specifies the entries of the Log to be included in the output; they must be
loggable_items
of the Log that have been logged (i.e., are alsologged_items
). If entries is ALL or is not specified, then alllogged_items
are included.report_all_executions (bool : default False) – specifies whether to report all executions within a given
TIME_STEP
(if True) or just the last (if False, the default). This in only relevant for Mechanisms that can be executed multiple times within aTIME_STEP
(e.g., TransferMechanism and DDM) when theirexecute_until_finished
attribute is set to True (seeComponent_Execute_Until_Finished
for additional details).exclude_sims –
set to True to exclude from output any values logged during simulations
- default value
False
- type
bool
Returns – 2d np.array
- csv(entries=None, owner_name=False, quotes="'", contexts=NotImplemented, exclude_sims=False)¶
Returns a CSV-formatted string with headers and values for the specified entries.
Each row (axis 0) is a time point, beginning with the time stamp and followed by the data for each Component at that time point, in the order they are specified in the entries argument. If all of the data for every Component have time values, then the first four items of each row are the time indices for the run, trial, pass, and time_step of that time point, respectively, followed by the data for each Component at that time point; if a Component has no data for a time point,
None
is entered.If any of the data for any Component does not have a time value (i.e., it has
None
in the time field of itsLogEntry
) then all of the entries must have the same number of data (LogEntry) items, and the first item of each row is a sequential index (starting with 0) that designates the data item number.Note
For data without time stamps, items in the same row are not guaranteed to refer to the same time point.
The owner_name argument can be used to prepend the header for each Component with its owner. The quotes argument can be used to suppress or specifiy quotes to use around numeric values.
- Parameters
entries (string, Component or list containing either : default ALL) – specifies the entries of the Log to be included in the output; they must be
loggable_items
of the Log that have been logged (i.e., are alsologged_items
). If entries is ALL or is not specified, then alllogged_items
are included.owner_name (bool : default False) – specifies whether or not to include the Component’s
owner
in the header of each field; if it is True, the format of the header for each field is “<Owner name>[<entry name>]”; otherwise, it is “<entry name>”.quotes (bool, str : default ') – specifies whether or not to enclose numeric values in quotes (may be useful for arrays); if not specified or
True
, single quotes are used for all items; if specified with a string, that is used in place of single quotes to enclose all items; ifFalse
orNone
, single quotes are used for headers (the items in the first row), but no others.exclude_sims –
set to True to exclude from output any values logged during simulations
- default value
False
- type
bool
Returns – CSV-formatted string
- _alias_owner_name(name)¶
Alias name of owner Component to VALUE in loggable_items and logged_items Component’s actual name is preserved and used in log_entries (i.e., as entered by _log_value)
- _dealias_owner_name(name)¶
De-alias VALUE to name of owner
- property loggable_items¶
Return dict of loggable items.
Keys are names of the Components, values their ContextStates
- property loggable_components¶
Return a list of owner’s Components that are loggable
The loggable items of a Component are the Components (typically Ports) specified in the _logagble_items property of its class, and its own
value
attribute.
- property logged_items¶
Dict of items that have logged
entries
, indicating their specifiedContextFlags
.
- exception psyneulink.core.globals.log.LogError(error_value)¶
- class psyneulink.core.globals.log.LogCondition(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)¶
Used to specify the context in which a value of the Component or its attribute is logged.
Note
The values of LogCondition are subset of (and directly reference) the ContextFlags bitwise enum, with the exception of TRIAL and RUN, which are bit-shifted to follow the ContextFlags.SIMULATION_MODE value.
- OFF = 0¶
No recording.
- INITIALIZATION = 2¶
Set during execution of the Component’s constructor.
- VALIDATION = 4¶
Set during validation of the value of a Component or its attribute.
- EXECUTION = 896¶
Set during all
phases of execution
of the Component.
- PROCESSING = 128¶
Set during the
processing phase
of execution of a Composition.
- LEARNING = 256¶
Set during the
learning phase
of execution of a Composition.
- CONTROL = 512¶
Set during the
control phase System_Execution_Control>
of execution of a Composition.
- TRIAL = 524288¶
Set at the end of a ‘TRIAL’.
- RUN = 1048576¶
Set at the end of a ‘RUN’.
- ALL_ASSIGNMENTS = 1835910¶
Specifies all contexts.
- classmethod _get_log_condition_string(condition, cond_str=None)¶
Return string with the names of all flags that are set in condition, prepended by cond_str