docs: def add(self, es=None, more_data=[], modulo=None):
          """append some logging data from `CMAEvolutionStrategy` class instance `es`,
          if ``number_of_times_called % modulo`` equals to zero, never if ``modulo==0``.
  
          The sequence ``more_data`` must always have the same length.
  
          When used for a different optimizer class, this function can be
          (easily?) adapted by changing the assignments under INTERFACE
          in the implemention.
  
          """
          mod = modulo if modulo is not None else self.modulo
          self.counter += 1
          if mod == 0 or (self.counter > 3 and (self.counter - 1) % mod):
              return
          if es is None:
              try:
                  es = self.es  # must have been registered
              except AttributeError :
                  raise _Error('call `add` with argument `es` or ``register(es)`` before ``add()``')
          elif not self.registered:
              self.register(es)
  
          if 1 < 3:
              if self.counter == 1 and not self.append and self.modulo != 0:
                  self.initialize()  # write file headers
                  self.counter = 1
  
          # --- INTERFACE, can be changed if necessary ---
          if not isinstance(es, CMAEvolutionStrategy):  # not necessary
              _print_warning('type CMAEvolutionStrategy expected, found '
                             + str(type(es)), 'add', 'CMADataLogger')
          evals = es.countevals
          iteration = es.countiter
          eigen_decompositions = es.count_eigen
          sigma = es.sigma
          axratio = es.D.max() / es.D.min()
          xmean = es.mean  # TODO: should be optionally phenotype?
          fmean_noise_free = es.fmean_noise_free
          fmean = es.fmean
          # TODO: find a different way to communicate current x and f?
          try:
              besteverf = es.best.f
              bestf = es.fit.fit[0]
              worstf = es.fit.fit[-1]
              medianf = es.fit.fit[es.sp.popsize // 2]
          except:
              if iteration > 0:  # first call without f-values is OK
                  raise
          try:
              xrecent = es.best.last.x
          except:
              xrecent = None
          maxD = es.D.max()
          minD = es.D.min()
          diagD = es.D
          diagC = es.sigma * es.sigma_vec * sqrt(es.dC)
          more_to_write = es.more_to_write
          es.more_to_write = []
          # --- end interface ---
  
          try:
              # fit
              if iteration > self.last_iteration:
                  fn = self.name_prefix + 'fit.dat'
                  with open(fn, 'a') as f:
                      f.write(str(iteration) + ' '
                              + str(evals) + ' '
                              + str(sigma) + ' '
                              + str(axratio) + ' '
                              + str(besteverf) + ' '
                              + '%.16e' % bestf + ' '
                              + str(medianf) + ' '
                              + str(worstf) + ' '
                              # + str(es.sp.popsize) + ' '
                              # + str(10**es.noiseS) + ' '
                              # + str(es.sp.cmean) + ' '
                              + ' '.join(str(i) for i in more_to_write) + ' '
                              + ' '.join(str(i) for i in more_data) + ' '
                              + '\n')
              # axlen
              fn = self.name_prefix + 'axlen.dat'
              if 1 < 3:
                  with open(fn, 'a') as f:  # does not rely on reference counting
                      f.write(str(iteration) + ' '
                              + str(evals) + ' '
                              + str(sigma) + ' '
                              + str(maxD) + ' '
                              + str(minD) + ' '
                              + ' '.join(map(str, diagD))
                              + '\n')
              # correlation matrix eigenvalues
              if 1 < 3:
                  fn = self.name_prefix + 'axlencorr.dat'
                  c = es.correlation_matrix()
                  if c is not None:
                      # accept at most 50% internal loss
                      if self._eigen_counter < eigen_decompositions / 2:
                          self.last_correlation_spectrum = \
                              sorted(es.opts['CMA_eigenmethod'](c)[0]**0.5)
                          self._eigen_counter += 1
                      if self.last_correlation_spectrum is None:
                          self.last_correlation_spectrum = len(diagD) * [1]
                      c = c[c < 1 - 1e-14]  # remove diagonal elements
                      c[c > 1 - 1e-14] = 1 - 1e-14
                      c[c < -1 + 1e-14] = -1 + 1e-14
                      c_min = np.min(c)
                      c_max = np.max(c)
                      if np.min(abs(c)) == 0:
                          c_medminus = 0  # thereby zero "is negative"
                          c_medplus = 0  # thereby zero "is positive"
                      else:
                          c_medminus = c[np.argmin(1/c)]  # c is flat
                          c_medplus = c[np.argmax(1/c)]  # c is flat
  
                      with open(fn, 'a') as f:
                          f.write(str(iteration) + ' '
                                  + str(evals) + ' '
                                  + str(c_min) + ' '
                                  + str(c_medminus) + ' ' # the one closest to 0
                                  + str(c_medplus) + ' ' # the one closest to 0
                                  + str(c_max) + ' '
                                  + ' '.join(map(str,
                                          self.last_correlation_spectrum))
                                  + '\n')
  
              # stddev
              fn = self.name_prefix + 'stddev.dat'
              with open(fn, 'a') as f:
                  f.write(str(iteration) + ' '
                          + str(evals) + ' '
                          + str(sigma) + ' '
                          + '0 0 '
                          + ' '.join(map(str, diagC))
                          + '\n')
              # xmean
              fn = self.name_prefix + 'xmean.dat'
              with open(fn, 'a') as f:
                  f.write(str(iteration) + ' '
                          + str(evals) + ' '
                          # + str(sigma) + ' '
                          + '0 '
                          + str(fmean_noise_free) + ' '
                          + str(fmean) + ' '  # TODO: this does not make sense
                          # TODO should be optional the phenotyp?
                          + ' '.join(map(str, xmean))
                          + '\n')
              # xrecent
              fn = self.name_prefix + 'xrecentbest.dat'
              if iteration > 0 and xrecent is not None:
                  with open(fn, 'a') as f:
                      f.write(str(iteration) + ' '
                              + str(evals) + ' '
                              + str(sigma) + ' '
                              + '0 '
                              + str(bestf) + ' '
                              + ' '.join(map(str, xrecent))
                              + '\n')
          except (IOError, OSError):
              if iteration <= 1:
                  _print_warning(('could not open/write file %s: ' % fn,
                                  sys.exc_info()))
          self.last_iteration = iteration