docs: def getSVD(data, k, getComponents=False, getS=False, normalization='mean'):
      """ Wrapper for computeSVD that will normalize and handle a Thunder Images object
  
      :param data: Thunder Images object
      :param k: number of components to keep
      :param getComponents: will return the components if true, otherwise will return None
  
      :returns: projections, components, s
      """
      if normalization == 'nanmean':
          data2 = data.tordd().sortByKey().values().map(lambda x: _convert_to_vector(x.flatten() - np.nanmean(x)))
      elif normalization == 'mean':
          data2 = data.tordd().sortByKey().values().map(lambda x: _convert_to_vector(x.flatten() - x.mean()))
      elif normalization is 'zscore':
          data2 = data.tordd().sortByKey().values().map(lambda x: _convert_to_vector(zscore(x.flatten())))
      elif normalization is None:
          data2 = data.tordd().sortByKey().values().map(lambda x: _convert_to_vector(x.flatten()))
      else:
          raise ValueError('Normalization should be one of: mean, nanmean, zscore, None. Got: %s' % normalization)
  
      mat = RowMatrix(data2)
      mat.rows.cache()
      mat.rows.count()
      svd = compute_svd(row_matrix=mat, k=k, compute_u=False)
      if getComponents:
          components = svd.call("V").toArray()
          components = components.transpose(1, 0).reshape((k,) + data.shape[1:])
      else:
          components = None
      projection = np.array(RowMatrix_new(data2).multiply(svd.call("V")).rows.collect())
      if getS:
          s = svd.call("s").toArray()
      else:
          s = None
      return projection, components, s