returns samples according to the KDE
		
			Parameters
			----------
				sample_inices: list of ints
					Indices into the training data used as centers for the samples
				
				num_samples: int
					if samples_indices is None, this specifies how many samples
					are drawn.

def sample(self, sample_indices=None, num_samples=1):
		""" returns samples according to the KDE
		
			Parameters
			----------
				sample_inices: list of ints
					Indices into the training data used as centers for the samples
				
				num_samples: int
					if samples_indices is None, this specifies how many samples
					are drawn.
				
		"""
		if sample_indices is None:
			sample_indices = np.random.choice(self.data.shape[0], size=num_samples)

		samples = self.data[sample_indices]

		delta = np.random.normal(size=num_samples)*self.bw
		samples += delta
		oob_idx  = np.argwhere(np.logical_or(samples > 1, samples < 0)).flatten()

		while len(oob_idx) > 0:
			samples[oob_idx] -= delta[oob_idx]		# revert move
			delta[oob_idx] = np.random.normal(size=len(oob_idx))*self.bw
			samples[oob_idx] += delta[oob_idx]
			oob_idx = oob_idx[np.argwhere(np.logical_or(samples[oob_idx] > 1, samples[oob_idx] < 0))].flatten()

		return(samples)