docs: def fitNull(self, verbose=False, cache=False, out_dir='./cache', fname=None, rewrite=False, seed=None, n_times=10, factr=1e3, init_method=None):
          """
          Fit null model
          """
          if seed is not None:    sp.random.seed(seed)
  
          read_from_file = False
          if cache:
              assert fname is not None, 'MultiTraitSetTest:: specify fname'
              if not os.path.exists(out_dir):
                  os.makedirs(out_dir)
              out_file = os.path.join(out_dir,fname)
              read_from_file = os.path.exists(out_file) and not rewrite
  
          RV = {}
          if read_from_file:
              f = h5py.File(out_file,'r')
              for key in list(f.keys()):
                  RV[key] = f[key][:]
              f.close()
              self.setNull(RV)
          else:
              start = TIME.time()
              if self.bgRE:
                  self._gpNull = GP2KronSum(Y=self.Y, F=None, A=None, Cg=self.Cg, Cn=self.Cn, R=None, S_R=self.S_R, U_R=self.U_R)
              else:
                  self._gpNull = GP2KronSumLR(self.Y, self.Cn, G=sp.ones((self.N,1)), F=self.F, A=self.A)
                  # freezes Cg to 0
                  n_params = self._gpNull.covar.Cr.getNumberParams()
                  self._gpNull.covar.Cr.setParams(1e-9 * sp.ones(n_params))
                  self._gpNull.covar.act_Cr = False
              for i in range(n_times):
                  params0 = self._initParams(init_method=init_method)
                  self._gpNull.setParams(params0)
                  conv, info = self._gpNull.optimize(verbose=verbose, factr=factr)
                  if conv: break
              if not conv:    warnings.warn("not converged")
              LMLgrad = (self._gpNull.LML_grad()['covar']**2).mean()
              LML = self._gpNull.LML()
              if self._gpNull.mean.n_terms==1:
                  RV['B'] = self._gpNull.mean.B[0]
              elif self._gpNull.mean.n_terms>1:
                  warning.warn('generalize to more than 1 fixed effect term')
              if self.bgRE:
                  RV['params0_g'] = self.Cg.getParams()
              else:
                  RV['params0_g'] = sp.zeros_like(self.Cn.getParams())
              RV['params0_n'] = self.Cn.getParams()
              if self.bgRE:
                  RV['Cg'] = self.Cg.K()
              else:
                  RV['Cg'] = sp.zeros_like(self.Cn.K())
              RV['Cn'] = self.Cn.K()
              RV['conv'] = sp.array([conv])
              RV['time'] = sp.array([TIME.time()-start])
              RV['NLL0'] = sp.array([LML])
              RV['LMLgrad'] = sp.array([LMLgrad])
              RV['nit'] = sp.array([info['nit']])
              RV['funcalls'] = sp.array([info['funcalls']])
              self.null = RV
              if cache:
                  f = h5py.File(out_file,'w')
                  smartDumpDictHdf5(RV,f)
                  f.close()
          return RV