def set_normal_free_energy(self):
        """
		Set free energy as a function of odorant; normal tuning curve.
		"""

        self.eps_base = self.mu_eps + self.normal_eps_tuning_prefactor* \
            sp.exp(-(1.*sp.arange(self.Mm))**2.0/(2.0* \
            self.normal_eps_tuning_width)**2.0)

        self.eps_base += random_matrix(self.Mm,
                                       params=[0, self.sigma_eps],
                                       seed=self.seed_eps)

        # If dual signal, use the average of the FULL signal nonzero components
        if self.Kk_split == 0:
            self.eps = self.WL_scaling * sp.log(self.mu_Ss0) + self.eps_base
        else:
            self.eps = self.WL_scaling*sp.log(sp.average(self.Ss\
                [self.Ss != 0])) + self.eps_base

        # Apply max and min epsilon value to each component
        self.min_eps = random_matrix(
            self.Mm,
            params=[self.mu_min_eps, self.sigma_min_eps],
            seed=self.seed_eps)
        self.max_eps = random_matrix(
            self.Mm,
            params=[self.mu_max_eps, self.sigma_max_eps],
            seed=self.seed_eps)
        self.eps = sp.maximum(self.eps, self.min_eps)
        self.eps = sp.minimum(self.eps, self.max_eps)

        # If an array of signals, replicate for each signal.
        if len(self.Ss.shape) > 1:
            self.eps = sp.tile(self.eps, [self.Ss.shape[1], 1]).T
    def set_adapted_free_energy(self):
        """
		Set free energy based on adapted activity activity.
		"""

        activity_stats = [
            self.adapted_activity_mu, self.adapted_activity_sigma
        ]
        adapted_activity = random_matrix([self.Mm],
                                         params=activity_stats,
                                         seed=self.seed_adapted_activity)
        self.eps = free_energy(self.Ss, self.Kk1, self.Kk2, adapted_activity,
                               self.binding_competitive,
                               self.num_binding_sites)

        # Apply max and min epsilon value to each component
        self.min_eps = random_matrix(
            self.Mm,
            params=[self.mu_min_eps, self.sigma_min_eps],
            seed=self.seed_eps)
        self.max_eps = random_matrix(
            self.Mm,
            params=[self.mu_max_eps, self.sigma_max_eps],
            seed=self.seed_eps)
        self.eps = sp.maximum(self.eps.T, self.min_eps).T
        self.eps = sp.minimum(self.eps.T, self.max_eps).T
	def set_uniform_Kk(self, clip=True):	
		"""
		K1 and K2 are chosen from a uniform distribution.
		"""
		
		self.Kk1 = random_matrix([self.Mm, self.Nn], [self.uniform_Kk1_lo, 
								self.uniform_Kk1_hi], sample_type='uniform',
								seed = self.seed_Kk1)
		self.Kk2 = random_matrix([self.Mm, self.Nn], [self.uniform_Kk2_lo, 
								self.uniform_Kk2_hi], sample_type='uniform', 
								seed = self.seed_Kk2)
	def set_random_free_energy(self):
		"""
		Set free energy as random vector.
		"""
		
		self.eps = random_matrix([self.Mm], [self.mu_eps, self.sigma_eps], 
									seed = self.seed_eps)
    def set_normal_free_energy(self):
        """
		Set free energy as a function of odorant; normal tuning curve.
		"""

        self.eps_base = self.mu_eps + self.normal_eps_tuning_prefactor* \
            sp.exp(-(1.*sp.arange(self.Mm))**2.0/(2.0* \
            self.normal_eps_tuning_width)**2.0)

        self.eps_base += random_matrix(self.Mm,
                                       params=[0, self.sigma_eps],
                                       seed=self.seed_eps)

        # If dual signal, use the average of the FULL signal nonzero components
        if self.Kk_split == 0:
            self.eps = self.WL_scaling * sp.log(self.mu_Ss0) + self.eps_base
        else:
            self.eps = self.WL_scaling*sp.log(sp.average(self.Ss\
                [self.Ss != 0])) + self.eps_base

        # Apply max epsilon value to each component
        for iM in range(self.Mm):
            if self.eps[iM] > self.max_eps:
                self.eps[iM] = self.max_eps
            if self.eps[iM] < self.min_eps:
                self.eps[iM] = self.min_eps
示例#6
0
    def set_adapted_free_energy(self):
        """
		Set free energy based on adapted activity activity.
		"""

        activity_stats = [
            self.adapted_activity_mu, self.adapted_activity_sigma
        ]
        adapted_activity = random_matrix([self.Mm],
                                         params=activity_stats,
                                         seed=self.seed_adapted_activity)

        # Break adaptation slightly by adjusting A0 with log of s0
        sp.random.seed(self.seed_adapted_activity)
        if (self.mu_dSs_2 is not None):
            max_sig_comp = max(max(self.mu_dSs, self.mu_dSs_2), self.mu_Ss0)
        else:
            max_sig_comp = max(self.mu_dSs, self.mu_Ss0)
        factors = sp.random.uniform(self.imperfect_A0_mult_min,
                                    self.imperfect_A0_mult_max, self.Mm)
        factors *= sp.log(max_sig_comp) / sp.log(10) + self.imperfect_A0_const
        adapted_activity *= (1 + factors)
        adapted_activity = sp.minimum(adapted_activity, 0.99)
        if sp.mean(factors) > 1:
            print('activity factors:', sp.mean(factors), '+/-',
                  sp.std(factors))

        # Scale the beta factor instead (breaks WL from 0 to 1)
        sp.random.seed(self.seed_adapted_activity)
        beta_scale_factors = sp.random.uniform(self.adaptive_beta_scaling_min,
                                               self.adaptive_beta_scaling_max,
                                               self.Mm)

        self.eps = free_energy(self.Ss, self.Kk1, self.Kk2, adapted_activity,
                               self.binding_competitive,
                               self.num_binding_sites, beta_scale_factors)
        self.min_eps = random_matrix(
            self.Mm,
            params=[self.mu_min_eps, self.sigma_min_eps],
            seed=self.seed_eps)
        self.max_eps = random_matrix(
            self.Mm,
            params=[self.mu_max_eps, self.sigma_max_eps],
            seed=self.seed_eps)
        self.eps = sp.maximum(self.eps.T, self.min_eps).T
        self.eps = sp.minimum(self.eps.T, self.max_eps).T
    def set_Kk2_normal_activity(self, clip=True, **kwargs):
        """
		Fixed activity distributions for adapted individual odorant response, 
		where each activity is chosen from a normal distribution depending on
		the receptor. The means for each receptor are chosen normally and the 
		sigmas are chosen uniformly. Kk2 is then derived from these choices,
		while Kk1 is chosen from a single Gaussian distribution. The function
		allows for overriding of mu_eps and mu_Ss0 if system has adapted to 
		another background state.
		"""

        matrix_shape = [self.Mm, self.Nn]

        params_Kk1 = [self.mu_Kk1, self.sigma_Kk1]
        self.Kk1 = random_matrix(matrix_shape, params_Kk1, seed=self.seed_Kk1)

        mu_Ss0 = self.mu_Ss0
        mu_eps = self.mu_eps
        for key in kwargs:
            exec('%s = kwargs[key]' % key)

        mu_stats = [
            self.receptor_tuning_mu_hyper_mu,
            self.receptor_tuning_mu_hyper_sigma
        ]
        sigma_stats = [
            self.receptor_tuning_sigma_hyper_lo,
            self.receptor_tuning_sigma_hyper_hi
        ]
        activity_mus = random_matrix([self.Mm],
                                     params=mu_stats,
                                     sample_type='normal',
                                     seed=self.seed_receptor_activity)
        activity_sigmas = random_matrix([self.Mm],
                                        params=sigma_stats,
                                        sample_type='uniform',
                                        seed=self.seed_receptor_activity)

        self.Kk2 = Kk2_eval_normal_activity(matrix_shape, activity_mus,
                                            activity_sigmas, mu_Ss0, mu_eps,
                                            self.seed_Kk2)

        if clip == True:
            array_dict = clip_array(dict(Kk1=self.Kk1, Kk2=self.Kk2))
            self.Kk1 = array_dict['Kk1']
            self.Kk2 = array_dict['Kk2']
	def set_adapted_free_energy(self):
		"""
		Set free energy based on adapted activity activity.
		"""
		
		activity_stats = [self.adapted_activity_mu, self.adapted_activity_sigma]
		adapted_activity = random_matrix([self.Mm], params=activity_stats, 
									seed=self.seed_adapted_activity)
		self.eps = free_energy(self.Ss0, self.Kk1, self.Kk2, adapted_activity)
示例#9
0
    def set_temporal_adapted_epsilon(self):
        """
		Set adapted epsilon based on current value and adaptation rate.
		The adapted value is set by linear decay rate equation, 
		d(eps)/dt = beta*(a_0 - a). a_0 is set by passing the manually
		chosen variables temporal_adaptation_mu_eps and 
		temporal_adaptation_mu_Ss0 to the activity. 
		"""

        # Perfectly adapted activity level is set manually
        activity_stats = [
            self.adapted_activity_mu, self.adapted_activity_sigma
        ]
        perfect_adapt_Yy = random_matrix([self.Mm],
                                         params=activity_stats,
                                         seed=self.seed_adapted_activity)
        beta_scale_factors = sp.random.uniform(self.adaptive_beta_scaling_min,
                                               self.adaptive_beta_scaling_max,
                                               self.Mm)

        # This is a kind of hacky way to incorporate WL breaking.
        # Requires Kk1 to be small
        Kk2_sum = sp.dot(self.Kk2**-1.0, self.Ss).T
        den = perfect_adapt_Yy.T*(1 - (1/Kk2_sum)**beta_scale_factors)\
          + (1/Kk2_sum)**beta_scale_factors
        perfect_adapt_Yy = (perfect_adapt_Yy.T / den)

        # Make adaptation rate into a vector if it has not yet been set.
        try:
            self.temporal_adaptation_rate_vector
        except AttributeError:
            assert self.temporal_adaptation_rate_sigma == 0, "Before "\
             "setting new epsilon with set_temporal_adapted_epsilon, "\
             "you must call set_ordered_temporal_adaptation_rate, since "\
             "temporal_adaptation_rate_sigma is nonzero"
            self.temporal_adaptation_rate_vector = sp.ones(self.Mm)*\
             self.temporal_adaptation_rate

        # Receptor activity used for adaptation is not firing rate; just
        # get the Or/Orco activity, w/o LN functions at backend.
        current_Yy = receptor_activity(self.Ss, self.Kk1, self.Kk2, self.eps,
                                       self.binding_competitive,
                                       self.num_binding_sites)

        if self.temporal_adaptation_type == 'imperfect':
            d_eps_dt = (self.temporal_adaptation_rate_vector*\
               (current_Yy.T - perfect_adapt_Yy)).T
            delta_t = self.signal_trace_Tt[1] - self.signal_trace_Tt[0]
            self.eps += delta_t * d_eps_dt
        elif self.temporal_adaptation_type == 'perfect':
            self.eps = free_energy(self.Ss, self.Kk1, self.Kk2,
                                   perfect_adapt_Yy)

        # Enforce epsilon limits
        self.eps = sp.maximum(self.eps.T, self.min_eps).T
        self.eps = sp.minimum(self.eps.T, self.max_eps).T
    def set_mixture_Kk(self, clip=True):
        """
		Set K1 and K2 matrices where each receptor response is chosen from 
		a Gaussian mixture with stats mu_Kk1_1, sigma_Kk2_1, 
		mu_Kk1_2, sigma_Kk2_2.
		"""

        assert 0 <= self.Kk1_p <= 1., "Kk1 Mixture ratio must be between 0 and 1"
        assert 0 <= self.Kk2_p <= 1., "Kk2 Mixture ratio must be between 0 and 1"

        self.Kk1 = sp.zeros((self.Mm, self.Nn))
        self.Kk2 = sp.zeros((self.Mm, self.Nn))

        num_comp1 = int(self.Kk1_p * self.Mm)
        num_comp2 = self.Mm - num_comp1
        params_Kk1_1 = [self.mu_Kk1_1, self.sigma_Kk1_1]
        params_Kk1_2 = [self.mu_Kk1_2, self.sigma_Kk1_2]
        self.Kk1[:num_comp1, :] = random_matrix([num_comp1, self.Nn],
                                                params_Kk1_1,
                                                seed=self.seed_Kk1)
        self.Kk1[num_comp1:, :] = random_matrix([num_comp2, self.Nn],
                                                params_Kk1_2,
                                                seed=self.seed_Kk1)

        num_comp1 = int(self.Kk2_p * self.Mm)
        num_comp2 = self.Mm - num_comp1
        params_Kk2_1 = [self.mu_Kk2_1, self.sigma_Kk2_1]
        params_Kk2_2 = [self.mu_Kk2_2, self.sigma_Kk2_2]

        self.Kk2[:num_comp1, :] = random_matrix([num_comp1, self.Nn],
                                                params_Kk2_1,
                                                seed=self.seed_Kk2)
        self.Kk2[num_comp1:, :] = random_matrix([num_comp2, self.Nn],
                                                params_Kk2_2,
                                                seed=self.seed_Kk2)

        if clip == True:
            array_dict = clip_array(dict(Kk1=self.Kk1, Kk2=self.Kk2))
            self.Kk1 = array_dict['Kk1']
            self.Kk2 = array_dict['Kk2']
	def set_normal_Kk(self, clip=True):	
		"""
		Set K1 and K2 where each receptor from a distinct Gaussian with 
		uniform prior on means and sigmas (mu_Kk1_hyper_lo, mu_Kk1_hyper_hi, 
		sigma_Kk1_hyper_lo, sigma_Kk1_hyper_hi, etc.)
		"""
		
		Kk1_mus = random_matrix([self.Mm], params=[self.mu_Kk1_hyper_lo, 
							self.mu_Kk1_hyper_hi], sample_type='uniform',
							seed=self.seed_Kk1)
		Kk1_sigmas = random_matrix([self.Mm], params=[self.sigma_Kk1_hyper_lo, 
							self.sigma_Kk1_hyper_hi], sample_type='uniform',
							seed=self.seed_Kk1)
		Kk2_mus = random_matrix([self.Mm], params=[self.mu_Kk2_hyper_lo, 
							self.mu_Kk2_hyper_hi], sample_type='uniform',
							seed=self.seed_Kk2)
		Kk2_sigmas = random_matrix([self.Mm], params=[self.sigma_Kk2_hyper_lo,
							self.sigma_Kk2_hyper_hi], sample_type='uniform',
							seed=self.seed_Kk2)
		
		self.Kk1 = random_matrix([self.Mm, self.Nn], [Kk1_mus, Kk1_sigmas], 
									sample_type='rank2_row_gaussian', 
									seed = self.seed_Kk1)
		self.Kk2 = random_matrix([self.Mm, self.Nn], [Kk2_mus, Kk2_sigmas],
									sample_type='rank2_row_gaussian', 
									seed = self.seed_Kk2)
		

		if clip == True:
			array_dict = clip_array(dict(Kk1 = self.Kk1, Kk2 = self.Kk2))
			self.Kk1 = array_dict['Kk1']
			self.Kk2 = array_dict['Kk2']
	def set_uniform_ordered_Kk(self, clip=True):
		"""
		Set K1 and K2 where each receptor from same Gaussian, and the 
		tuning curves are ordered such that row one is centered at N1, etc.
		"""
		self.Kk1 = random_matrix([self.Mm, self.Nn], [self.uniform_Kk1_lo, 
								self.uniform_Kk1_hi], sample_type='uniform',
								seed = self.seed_Kk1)
		
		self.Kk2 = random_matrix([self.Mm, self.Nn], [self.uniform_Kk2_lo, 
								self.uniform_Kk2_hi], sample_type='uniform', 
								seed = self.seed_Kk2)
		if clip == True:
			array_dict = clip_array(dict(Kk1 = self.Kk1, Kk2 = self.Kk2))
			self.Kk1 = array_dict['Kk1']
			self.Kk2 = array_dict['Kk2']
							
		for iM in range(self.Mm):
			self.Kk2[iM, :] = sp.sort(self.Kk2[iM, :])
			tmp = sp.hstack((self.Kk2[iM, :], self.Kk2[iM, ::-1]))
			self.Kk2[iM, :] = tmp[::2]
			self.Kk2[iM, :] = sp.roll(self.Kk2[iM, :], iM*int(self.Nn/self.Mm))
    def set_normal_free_energy(self):
        """
		Set free energy as a function of odorant; normal tuning curve.
		"""

        self.eps_base = self.mu_eps + self.normal_eps_tuning_prefactor* \
            sp.exp(-(1.*sp.arange(self.Mm))**2.0/(2.0* \
            self.normal_eps_tuning_width)**2.0)

        self.eps_base += random_matrix(self.Mm,
                                       params=[0, self.sigma_eps],
                                       seed=self.seed_eps)

        self.eps = self.WL_scaling * sp.log(self.mu_dSs) + self.eps_base
    def set_temporal_adapted_epsilon(self):
        """
		Set adapted epsilon based on current value and adaptation rate.
		The adapted value is set by linear decay rate equation, 
		d(eps)/dt = beta*(a_0 - a). a_0 is set by passing the manually
		chosen variables temporal_adaptation_mu_eps and 
		temporal_adaptation_mu_Ss0 to the activity. 
		"""

        # Perfectly adapted activity level is based on the variables:
        #  temporal_adaptation_mu_eps, temporal_adaptation_sigma_eps,
        #  temporal_adaptation_mu_Ss0. These functions take the activity
        #  level set by these variables at that signal intensity, to
        #  adapt epsilon to the current Ss
        perfect_adapt_eps_base = sp.ones(self.Mm)*\
          self.temporal_adaptation_mu_eps + random_matrix(self.Mm,
          params=[0, self.temporal_adaptation_sigma_eps],
          seed=self.seed_eps)
        perfect_adapt_Ss = sp.zeros(self.Nn)
        perfect_adapt_Ss[self.Ss0 != 0] = self.temporal_adaptation_mu_Ss0
        perfect_adapt_Yy = receptor_activity(perfect_adapt_Ss, self.Kk1,
                                             self.Kk2, perfect_adapt_eps_base)

        # Make adaptation rate into a vector if it has not yet been set.
        try:
            self.temporal_adaptation_rate_vector
        except AttributeError:
            assert self.temporal_adaptation_rate_sigma == 0, "Before "\
             "setting new epsilon with set_temporal_adapted_epsilon, "\
             "you must call set_ordered_temporal_adaptation_rate, since "\
             "temporal_adaptation_rate_sigma is nonzero"
            self.temporal_adaptation_rate_vector = sp.ones(self.Mm)*\
             self.temporal_adaptation_rate

        if self.temporal_adaptation_type == 'imperfect':
            d_eps_dt = self.temporal_adaptation_rate_vector*\
               (self.Yy - perfect_adapt_Yy)
            delta_t = self.signal_trace_Tt[1] - self.signal_trace_Tt[0]
            self.eps += delta_t * d_eps_dt
        elif self.temporal_adaptation_type == 'perfect':
            self.eps = free_energy(self.Ss, self.Kk1, self.Kk2,
                                   perfect_adapt_Yy)
	def set_Kk2_uniform_activity(self, clip=True, **kwargs):
		"""
		Fixed activity distributions for adapted individual odorant response, 
		where each activity is chosen from a single uniform distribution.
		"""
		
		matrix_shape = [self.Mm, self.Nn]
		
		params_Kk1 = [self.mu_Kk1, self.sigma_Kk1]
		self.Kk1 = random_matrix(matrix_shape, params_Kk1, seed=self.seed_Kk1)
	
		params_Kk2 = [self.uniform_activity_lo, self.uniform_activity_hi]
		self.Kk2 = Kk2_eval_uniform_activity(matrix_shape, params_Kk2, 
											self.mu_Ss0, self.mu_eps, 
											self.seed_Kk2)
		
		if clip == True:
			array_dict = clip_array(dict(Kk1 = self.Kk1, Kk2 = self.Kk2))
			self.Kk1 = array_dict['Kk1']
			self.Kk2 = array_dict['Kk2']
    def set_Kk2_normal_activity_mixture(self, clip=True, **kwargs):
        """
		Fixed activity distributions for adapted individual odorant response, 
		where each activity is chosen from a Gaussian mixture.
		"""

        matrix_shape = [self.Mm, self.Nn]

        params_Kk1 = [self.mu_Kk1, self.sigma_Kk1]
        self.Kk1 = random_matrix(matrix_shape, params_Kk1, seed=self.seed_Kk1)

        mu_Ss0 = self.mu_Ss0
        mu_eps = self.mu_eps
        for key in kwargs:
            exec('%s = kwargs[key]' % key)

        assert 0 <= self.activity_p <= 1., "Mixture ratio must be between 0 and 1"

        activity_mus = sp.zeros(self.Mm)
        activity_sigmas = sp.zeros(self.Mm)

        num_comp1 = int(self.activity_p * self.Mm)
        num_comp2 = self.Mm - num_comp1

        activity_mus[:num_comp1] = self.receptor_tuning_mixture_mu_1
        activity_mus[num_comp1:] = self.receptor_tuning_mixture_mu_2
        activity_sigmas[:num_comp1] = self.receptor_tuning_mixture_sigma_1
        activity_sigmas[num_comp1:] = self.receptor_tuning_mixture_sigma_2

        self.Kk2 = Kk2_eval_normal_activity(matrix_shape, activity_mus,
                                            activity_sigmas, mu_Ss0, mu_eps,
                                            self.seed_Kk2)

        if clip == True:
            array_dict = clip_array(dict(Kk1=self.Kk1, Kk2=self.Kk2))
            self.Kk1 = array_dict['Kk1']
            self.Kk2 = array_dict['Kk2']
    def set_power_Kk(self):
        """
		Set K1 and K2 martrices where each receptor response is chosen from
		a power law. The clip_vals is a 2-element array that enforces the 
		values to be drawn from a reduced range.		
		"""

        Kk1_los = random_matrix(
            [self.Mm],
            params=[self.lo_Kk1_hyper_lo, self.lo_Kk1_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk1)
        Kk1_his = random_matrix(
            [self.Mm],
            params=[self.hi_Kk1_hyper_lo, self.hi_Kk1_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk1)
        Kk2_los = random_matrix(
            [self.Mm],
            params=[self.lo_Kk2_hyper_lo, self.lo_Kk2_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk2)
        Kk2_his = random_matrix(
            [self.Mm],
            params=[self.hi_Kk2_hyper_lo, self.hi_Kk2_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk2)

        self.Kk1 = random_matrix([self.Mm, self.Nn],
                                 [Kk1_los, Kk1_his, self.power_exp],
                                 sample_type='rank2_row_power',
                                 seed=self.seed_Kk1)
        self.Kk2 = random_matrix([self.Mm, self.Nn],
                                 [Kk2_los, Kk2_his, self.power_exp],
                                 sample_type='rank2_row_power',
                                 seed=self.seed_Kk2)

        # Replace some low responders with specialist responders
        if self.high_responders == True:
            self.manual_Kk_replace()
    def set_uniform_Kk(self, clip=True):
        """
		Set K1 and K2 where each receptor from a distinct uniform with 
		uniform prior on the uniform bounds (lo_Kk1_hyper_lo, lo_Kk1_hyper_hi, 
		hi_Kk1_hyper_lo, hi_Kk1_hyper_hi, etc.)
		"""

        Kk1_los = random_matrix(
            [self.Mm],
            params=[self.lo_Kk1_hyper_lo, self.lo_Kk1_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk1)
        Kk1_his = random_matrix(
            [self.Mm],
            params=[self.hi_Kk1_hyper_lo, self.hi_Kk1_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk1)
        Kk2_los = random_matrix(
            [self.Mm],
            params=[self.lo_Kk2_hyper_lo, self.lo_Kk2_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk2)
        Kk2_his = random_matrix(
            [self.Mm],
            params=[self.hi_Kk2_hyper_lo, self.hi_Kk2_hyper_hi],
            sample_type='uniform',
            seed=self.seed_Kk2)

        self.Kk1 = random_matrix([self.Mm, self.Nn], [Kk1_los, Kk1_his],
                                 sample_type='rank2_row_uniform',
                                 seed=self.seed_Kk1)
        self.Kk2 = random_matrix([self.Mm, self.Nn], [Kk2_los, Kk2_his],
                                 sample_type='rank2_row_uniform',
                                 seed=self.seed_Kk2)

        if clip == True:
            array_dict = clip_array(dict(Kk1=self.Kk1, Kk2=self.Kk2))
            self.Kk1 = array_dict['Kk1']
            self.Kk2 = array_dict['Kk2']
    def set_sparse_signals(self):
        """
		Set random sparse signals
		"""

        # Possibly override manual indices
        if self.manual_dSs_idxs is not None:
            self.set_manual_signals()
            return

        # Can override Kk_split with this; manually set compelxity of signal 2
        if (self.Kk_1 is not None) and (self.Kk_2 is not None):
            self.Kk = self.Kk_1 + self.Kk_2
            self.Kk_split = self.Kk_2

        params_dSs = [self.mu_dSs, self.sigma_dSs]
        params_Ss0 = [self.mu_Ss0, self.sigma_Ss0]
        self.dSs, self.idxs = sparse_vector([self.Nn, self.Kk],
                                            params_dSs,
                                            seed=self.seed_dSs)

        # Replace components with conflicting background odor
        if (self.Kk_split is not None) and (self.Kk_split != 0):
            assert 0 <= self.Kk_split <= self.Kk, \
             "Splitting sparse signal into two levels requires Kk_split" \
             " to be non-negative and less than or equal to Kk."
            assert self.mu_dSs_2 is not None \
             and self.sigma_dSs_2 is not None, \
             "Splitting sparse signal into two levels requires that" \
             " mu_dSs_2 and sigma_dSs_2 are set."

            if self.seed_dSs_2 is None:

                # Want both odor 1 and odor 2 to be determined by seed_dSs
                sp.random.seed(self.seed_dSs)
                self.idxs_2 = sp.random.choice(self.idxs[0],
                                               self.Kk_split,
                                               replace=False)
            else:

                # Want odor 1 and 2 to be determined by respective seeds.
                self.dSs, self.idxs = sparse_vector([self.Nn, self.Kk_1],
                                                    params_dSs,
                                                    seed=self.seed_dSs)
                _, self.idxs_2 = sparse_vector([self.Nn, self.Kk_split],
                                               params_dSs,
                                               seed=self.seed_dSs_2)

                # Re-define the full idxs and the odor 2 idxs subset
                self.idxs = ((list(self.idxs[0]) + list(self.idxs_2[0])), )
                self.idxs_2 = self.idxs_2[0]

            for idx_2 in self.idxs_2:
                self.dSs[idx_2] = random_matrix(
                    1, params=[self.mu_dSs_2, self.sigma_dSs_2])
        else:
            self.idxs_2 = []
            self.Kk_split = 0

        # Ss0 is the ideal (learned) background stimulus without noise
        self.Ss0, self.Ss0_noisy = sparse_vector_bkgrnd([self.Nn, self.Kk],
                                                        self.idxs,
                                                        params_Ss0,
                                                        seed=self.seed_Ss0)

        self.Ss = self.dSs + self.Ss0_noisy