add random effects term for single trait models (no trait-trait covariance matrix)
        
        Args:
            K:          NxN sample covariance matrix
            is_noise:	bool labeling the noise term (noise term has K=eye)
            normalize:	if True, K and Ks are scales such that K.diagonal().mean()==1
            Ks:			NxN test cross covariance for predictions

def addSingleTraitTerm(self,K=None,is_noise=False,normalize=True,Ks=None):
        """
        add random effects term for single trait models (no trait-trait covariance matrix)
        
        Args:
            K:          NxN sample covariance matrix
            is_noise:	bool labeling the noise term (noise term has K=eye)
            normalize:	if True, K and Ks are scales such that K.diagonal().mean()==1
            Ks:			NxN test cross covariance for predictions
        """
        
        assert self.P == 1, 'Incompatible number of traits'
        
        assert K!=None or is_noise, 'Specify covariance structure'
        
        if is_noise:
            assert self.noisPos==None, 'noise term already exists'
            K = SP.eye(self.Nt)
            self.noisPos = self.n_terms
        else:
            assert K.shape[0]==self.Nt, 'Incompatible shape'
            assert K.shape[1]==self.Nt, 'Incompatible shape'
    
        if Ks!=None:
            assert Ks.shape[0]==self.N, 'Incompatible shape'

        if normalize:
            Norm = 1/K.diagonal().mean()
            K *= Norm
            if Ks!=None: Ks *= Norm

        self.vd.addTerm(limix.CSingleTraitTerm(K))
        if Ks!=None: self.setKstar(self.n_terms,Ks)
        self.n_terms+=1
    
        self.gp         = None
        self.init       = False
        self.fast       = False
        self.optimum    = None

        self.cache['Sigma']   = None
        self.cache['Hessian'] = None
        self.cache['Lparams'] = None
        self.cache['paramsST']= None