docstr: Check if ``X`` is a sample from a categorical distribution, i.e. an
  array of non-negative integers.
code: def _check_and_set_n_features(self, X):
      """
      Check if ``X`` is a sample from a categorical distribution, i.e. an
      array of non-negative integers.
      """
      if not np.issubdtype(X.dtype, np.integer):
          raise ValueError("Symbols should be integers")
      if X.min() < 0:
          raise ValueError("Symbols should be nonnegative")
      if self.n_features is not None:
          if self.n_features - 1 < X.max():
              raise ValueError(
                  f"Largest symbol is {X.max()} but the model only emits "
                  f"symbols up to {self.n_features - 1}"
              )
      else:
          self.n_features = X.max() + 1
  
imports: import functools
  import inspect
  import warnings
  import numpy
  from scipy import special
  from scipy.stats import multinomial, poisson
  from sklearn.utils import check_random_state
  from .base import BaseHMM, _AbstractHMM
  from .stats import log_multivariate_normal_density
  from .utils import fill_covars, log_normalize
label_desc: Use image node_id 2 for calling the BaseCategoricalHMM obj's underlying member method code with example usage: obj._check_and_set_n_features(X) without return types