def _instantiate_control_signal_type(self, gating_signal_spec, context): """Instantiate actual ControlSignal, or subclass if overridden""" from psyneulink.core.components.ports.port import _instantiate_port from psyneulink.core.components.projections.projection import ProjectionError allocation_parameter_default = self.parameters.gating_allocation.default_value gating_signal = _instantiate_port(port_type=GatingSignal, owner=self, variable=self.default_allocation # User specified value or allocation_parameter_default, # Parameter default reference_value=allocation_parameter_default, modulation=self.modulation, port_spec=gating_signal_spec, context=context) if not type(gating_signal) in convert_to_list(self.outputPortTypes): raise ProjectionError(f'{type(gating_signal)} inappropriate for {self.name}') return gating_signal
def _instantiate_sender(self, sender, params=None, context=None): """Check that sender is not a process and that, if specified as a Mechanism, it is a GatingMechanism """ # A Process can't be the sender of a GatingProjection if isinstance(sender, Process_Base): raise ProjectionError( "PROGRAM ERROR: attempt to add a {} from a Process {0} " "to a Mechanism {0} in pathway list".format( GATING_PROJECTION, self.name, sender.name)) # If sender is specified as a Mechanism, validate that it is a GatingMechanism if isinstance(sender, Mechanism): if not isinstance(sender, GatingMechanism): raise GatingProjectionError( "Mechanism specified as sender for {} ({}) must be a {} (but it is a {})" .format(GATING_MECHANISM, self.name, sender.name, sender.__class__.__name__)) # Call super to instantiate sender super()._instantiate_sender(sender, context=context)
def _instantiate_sender(self, sender, params=None, context=None): """Check if DefaultController is being assigned and if so configure it for the requested ControlProjection If self.sender is a Mechanism, re-assign to <Mechanism>.outputPort Insure that sender.value = self.defaults.variable This method overrides the corresponding method of Projection, before calling it, to check if the DefaultController is being assigned as sender and, if so: - creates projection-dedicated inputPort and outputPort in DefaultController - puts them in DefaultController's input_ports and outputPorts attributes - lengthens variable of DefaultController to accommodate the ControlProjection - updates value of the DefaultController (in response to the new variable) Notes: * the default function of the DefaultControlMechanism simply maps the inputPort value to the outputPort * the params arg is assumed to be a dictionary of params for the ControlSignal of the ControlMechanism :return: """ # A Process can't be the sender of a ControlMechanism if isinstance(sender, Process_Base): raise ProjectionError( "PROGRAM ERROR: attempt to add a ControlProjection from a Process {0} " "to a Mechanism {0} in pathway list".format(self.name, sender.name) ) # If sender is specified as a Mechanism, validate that it is a ControlMechanism if isinstance(sender, Mechanism): # If sender is a ControlMechanism, call it to instantiate its ControlSignal projection if not isinstance(sender, ControlMechanism): raise ControlProjectionError( "Mechanism specified as sender for {} ({}) must be a " "ControlMechanism (but it is a {})".format( self.name, sender.name, sender.__class__.__name__ ) ) # Call super to instantiate sender super()._instantiate_sender(sender, context=context)
def _instantiate_receiver(self, context=None): """Determine matrix needed to map from sender to receiver Assign specification to self.matrix_spec attribute Assign matrix to self.matrix attribute """ self.reshapedWeightMatrix = False # Get sender and receiver lengths # Note: if either is a scalar, manually set length to 1 to avoid TypeError in call to len() try: mapping_input_len = len(self.defaults.variable) except TypeError: mapping_input_len = 1 try: receiver_len = self.receiver.socket_width except TypeError: receiver_len = 1 # Compare length of MappingProjection output and receiver's variable to be sure matrix has proper dimensions try: mapping_output_len = len(self.defaults.value) except TypeError: mapping_output_len = 1 matrix_spec = self.defaults.matrix if (type(matrix_spec) == str and matrix_spec == AUTO_ASSIGN_MATRIX): if mapping_input_len == receiver_len: matrix_spec = IDENTITY_MATRIX else: matrix_spec = FULL_CONNECTIVITY_MATRIX # Length of the output of the Projection doesn't match the length of the receiving InputPort # so consider reshaping the matrix if mapping_output_len != receiver_len: if 'projection' in self.name or 'Projection' in self.name: projection_string = '' else: projection_string = 'projection' if all(string in self.name for string in {'from', 'to'}): states_string = '' else: states_string = "from \'{}\' OuputState of \'{}\' to \'{}\'".format(self.sender.name, self.sender.owner.name, self.receiver.owner.name) if not isinstance(matrix_spec, str): # if all(string in self.name for string in {'from', 'to'}): raise ProjectionError("Width ({}) of the {} of \'{}{}\'{} " "does not match the length of its \'{}\' InputPort ({})". format(mapping_output_len, VALUE, self.name, projection_string, states_string, self.receiver.name, receiver_len)) elif matrix_spec == IDENTITY_MATRIX or matrix_spec == HOLLOW_MATRIX: # Identity matrix is not reshapable raise ProjectionError("Output length ({}) of \'{}{}\' from {} to Mechanism \'{}\'" " must equal length of it InputPort ({}) to use {}". format(mapping_output_len, self.name, projection_string, self.sender.name, self.receiver.owner.name, receiver_len, matrix_spec)) else: # Flag that matrix is being reshaped self.reshapedWeightMatrix = True if self.prefs.verbosePref: print("Length ({}) of the output of {}{} does not match the length ({}) " "of the InputPort for the receiver {}; the width of the matrix (number of columns); " "the width of the matrix (number of columns) will be adjusted to accomodate the receiver". format(mapping_output_len, self.name, projection_string, receiver_len, self.receiver.owner.name)) self.parameters.matrix._set( get_matrix(matrix_spec, mapping_input_len, receiver_len, context=context), context ) # Since matrix shape has changed, output of self.function may have changed, so update value self._instantiate_value(context=context) super()._instantiate_receiver(context=context)