class_docstr: Abstract base class for PennyLane qutrit devices.
  
  The following abstract method **must** be defined:
  
  * :meth:`~.apply`: append circuit operations, compile the circuit (if applicable),
    and perform the quantum computation.
  
  Devices that generate their own samples (such as hardware) may optionally
  overwrite :meth:`~.probability`. This method otherwise automatically
  computes the probabilities from the generated samples, and **must**
  overwrite the following method:
  
  * :meth:`~.generate_samples`: Generate samples from the device from the
    exact or approximate probability distribution.
  
  Analytic devices **must** overwrite the following method:
  
  * :meth:`~.analytic_probability`: returns the probability or marginal probability from the
    device after circuit execution. :meth:`~.marginal_prob` may be used here.
  
  This device contains common utility methods for qutrit-based devices. These
  do not need to be overwritten. Utility methods include:
  
  * :meth:`~.expval`, :meth:`~.var`, :meth:`~.sample`: return expectation values,
    variances, and samples of observables after the circuit has been rotated
    into the observable eigenbasis.
  
  Args:
      wires (int, Iterable[Number, str]]): Number of subsystems represented by the device,
          or iterable that contains unique labels for the subsystems as numbers (i.e., ``[-1, 0, 2]``)
          or strings (``['ancilla', 'q1', 'q2']``). Default 1 if not specified.
      shots (None, int, list[int]): Number of circuit evaluations/random samples used to estimate
          expectation values of observables. If ``None``, the device calculates probability, expectation values,
          and variances analytically. If an integer, it specifies the number of samples to estimate these quantities.
          If a list of integers is passed, the circuit evaluations are batched over the list of shots.
      r_dtype: Real floating point precision type.
      c_dtype: Complex floating point precision type.
class_docstr_tok: ["Abstract","base","class","for","PennyLane","qutrit","devices",".","The","following","abstract","method","*","*","must","*","*","be","defined",":","*",":","meth",":","`","~.apply","`",":","append","circuit","operations",",","compile","the","circuit","(","if","applicable",")",",","and","perform","the","quantum","computation",".","Devices","that","generate","their","own","samples","(","such","as","hardware",")","may","optionally","overwrite",":","meth",":","`","~.probability","`",".","This","method","otherwise","automatically","computes","the","probabilities","from","the","generated","samples",",","and","*","*","must","*","*","overwrite","the","following","method",":","*",":","meth",":","`","~.generate_samples","`",":","Generate","samples","from","the","device","from","the","exact","or","approximate","probability","distribution",".","Analytic","devices","*","*","must","*","*","overwrite","the","following","method",":","*",":","meth",":","`","~.analytic_probability","`",":","returns","the","probability","or","marginal","probability","from","the","device","after","circuit","execution",".",":","meth",":","`","~.marginal_prob","`","may","be","used","here",".","This","device","contains","common","utility","methods","for","qutrit-based","devices",".","These","do","not","need","to","be","overwritten",".","Utility","methods","include",":","*",":","meth",":","`","~.expval","`",",",":","meth",":","`","~.var","`",",",":","meth",":","`","~.sample","`",":","return","expectation","values",",","variances",",","and","samples","of","observables","after","the","circuit","has","been","rotated","into","the","observable","eigenbasis",".","Args",":","wires","(","int",",","Iterable","[","Number",",","str","]","]",")",":","Number","of","subsystems","represented","by","the","device",",","or","iterable","that","contains","unique","labels","for","the","subsystems","as","numbers","(","i.e.",",","``","[","-1",",","0",",","2","]","``",")","or","strings","(","``","[","'ancilla","'",",","'q1","'",",","'q2","'","]","``",")",".","Default","1","if","not","specified",".","shots","(","None",",","int",",","list","[","int","]",")",":","Number","of","circuit","evaluations\/random","samples","used","to","estimate","expectation","values","of","observables",".","If","``","None","``",",","the","device","calculates","probability",",","expectation","values",",","and","variances","analytically",".","If","an","integer",",","it","specifies","the","number","of","samples","to","estimate","these","quantities",".","If","a","list","of","integers","is","passed",",","the","circuit","evaluations","are","batched","over","the","list","of","shots",".","r_dtype",":","Real","floating","point","precision","type",".","c_dtype",":","Complex","floating","point","precision","type","."]
code: def sample(
      self, observable, shot_range=None, bin_size=None, counts=False
  ):
      def _samples_to_counts(samples, no_observable_provided):
          """Group the obtained samples into a dictionary.
  
          **Example**
  
              >>> samples
              tensor([[0, 0, 1],
                      [0, 0, 1],
                      [1, 1, 1]], requires_grad=True)
              >>> self._samples_to_counts(samples)
              {'111':1, '001':2}
          """
          if no_observable_provided:
              # If we describe a state vector, we need to convert its list representation
              # into string (it's hashable and good-looking).
              # Before converting to str, we need to extract elements from arrays
              # to satisfy the case of jax interface, as jax arrays do not support str.
              samples = [
                  "".join([str(s.item()) for s in sample])
                  for sample in samples
              ]
          states, counts = np.unique(samples, return_counts=True)
          return dict(zip(states, counts))
  
      # TODO: Add special cases for any observables that require them once list of
      # observables is updated.
  
      # translate to wire labels used by device
      device_wires = self.map_wires(observable.wires)
      name = observable.name  # pylint: disable=unused-variable
      sample_slice = (
          Ellipsis if shot_range is None else slice(*shot_range)
      )
      no_observable_provided = isinstance(
          observable, MeasurementProcess
      )
  
      if (
          no_observable_provided
      ):  # if no observable was provided then return the raw samples
          if (
              len(observable.wires) != 0
          ):  # if wires are provided, then we only return samples from those wires
              samples = self._samples[
                  sample_slice, np.array(device_wires)
              ]
          else:
              samples = self._samples[sample_slice]
  
      else:
          # Replace the basis state in the computational basis with the correct eigenvalue.
          # Extract only the columns of the basis samples required based on ``wires``.
          samples = self._samples[
              sample_slice, np.array(device_wires)
          ]  # Add np.array here for Jax support.
          powers_of_three = 3 ** np.arange(samples.shape[-1])[::-1]
          indices = samples @ powers_of_three
          indices = np.array(
              indices
          )  # Add np.array here for Jax support.
          try:
              samples = observable.eigvals()[indices]
          except qml.operation.EigvalsUndefinedError as e:
              # if observable has no info on eigenvalues, we cannot return this measurement
              raise qml.operation.EigvalsUndefinedError(
                  f"Cannot compute samples of {observable.name}."
              ) from e
  
      if bin_size is None:
          if counts:
              return _samples_to_counts(samples, no_observable_provided)
          return samples
  
      num_wires = (
          len(device_wires) if len(device_wires) > 0 else self.num_wires
      )
      if counts:
          shape = (
              (-1, bin_size, num_wires)
              if no_observable_provided
              else (-1, bin_size)
          )
          return [
              _samples_to_counts(bin_sample, no_observable_provided)
              for bin_sample in samples.reshape(shape)
          ]
      return (
          samples.reshape((num_wires, bin_size, -1))
          if no_observable_provided
          else samples.reshape((bin_size, -1))
      )
  
imports: import itertools
  import numpy
  import pennylane
  from pennylane import QubitDevice
  from pennylane.measurements import MeasurementProcess
  from pennylane.wires import Wires
label_desc: Use image node_id 12 for calling the QutritDevice obj's underlying member method code with example usage: obj.sample(observable, shot_range, bin_size, counts) and returns: unknown, dict, samples, unknown, _samples_to_counts