def evalMetricFromSamples(self, q_samples, grad_samples=None, method=None):
        '''Evaluates the horsetail matching metric from given samples of the quantity
        of interest and gradient instead of evaluating them at a design.

        :param np.ndarray q_samples: samples of the quantity of interest,
            size (M_int, M_prob)
        :param np.ndarray grad_samples: samples of the gradien,
            size (M_int, M_prob, n_x)

        :return: metric_value - value of the metric

        :rtype: float

        '''
        # Make sure dimensions are correct
#        u_sample_dimensions = self._processDimensions()

        q_samples = np.array(q_samples)
        if not (q_samples.shape[0] == self.samples_int and
                q_samples.shape[1] == self.samples_prob):
            raise ValueError('Shape of q_samples should be [M_int, M_prob]')

        if grad_samples is not None:
            grad_samples = np.array(grad_samples)
            if not (grad_samples.shape[0] == self.samples_int and
                    grad_samples.shape[1] == self.samples_prob):
                raise ValueError('''Shape of grad_samples
                        should be [M_int, M_prob, n_dv]''')

        if method is None:
            method = self.method

        if method.lower() == 'empirical':
            return self._evalMetricEmpirical(q_samples, grad_samples)
        elif method.lower() == 'kernel':
            return self._evalMetricKernel(q_samples, grad_samples)
        else:
            raise ValueError('Unsupported metric evalation method')
Evaluates the horsetail matching metric from given samples of the quantity
        of interest and gradient instead of evaluating them at a design.

        :param np.ndarray q_samples: samples of the quantity of interest,
            size (M_int, M_prob)
        :param np.ndarray grad_samples: samples of the gradien,
            size (M_int, M_prob, n_x)

        :return: metric_value - value of the metric

        :rtype: float