def __init__(
        self,
        confusion_matrices: np.ndarray | Sequence[np.ndarray],
        measure_qubits: Sequence[cirq.Qid] | Sequence[Sequence[cirq.Qid]],
        *,
        repetitions: int,
        timestamp: float,
    ):
        """Initializes `cirq.TensoredConfusionMatrices`.

        `confusion_matrices[i]` should correspond to the qubit sequence `measure_qubits[i]`.

        Args:
            confusion_matrices: Sequence of confusion matrices, computed for qubit patterns present
                                in `measure_qubits`. A single confusion matrix is also accepted.
            measure_qubits: Sequence of smaller qubit patterns, for which the confusion matrices
                            were computed. A single qubit pattern is also accepted. Note that
                            each qubit pattern is a sequence of qubits used to label the axes of
                            the corresponding confusion matrix.
            repetitions:    The number of repetitions that were used to estimate the confusion
                            matrices.
            timestamp:      The time the data was taken, in seconds since the epoch. This will be
                            zero for fake data (i.e. data not generated from an experiment).

        Raises:
            ValueError: If length of `confusion_matrices` and `measure_qubits` is different or if
                        the shape of any confusion matrix does not match the corresponding qubit
                        pattern.
        """
        if len(measure_qubits) == 0:
            raise ValueError("measure_qubits cannot be empty.")
        if isinstance(confusion_matrices, np.ndarray):
            confusion_matrices = [confusion_matrices]
        measure_qubits = cast(
            Sequence[Sequence['cirq.Qid']],
            [measure_qubits] if isinstance(measure_qubits[0], ops.Qid) else measure_qubits,
        )
        if len(confusion_matrices) != len(measure_qubits):
            raise ValueError(
                f"len(confusion_matrices): {len(confusion_matrices)} should be equal to "
                f"len(measure_qubits): {len(measure_qubits)}"
            )
        for i, (cm, q) in enumerate(zip(confusion_matrices, measure_qubits)):
            if cm.shape != (2 ** len(q),) * 2:
                raise ValueError(
                    f"Shape mismatch for confusion matrix {cm} at index {i} corresponding to {q}."
                    f"Confusion Matrix shape {cm.shape} should match {(2 ** len(q),) * 2}"
                )

        self._timestamp = timestamp
        self._repetitions = repetitions
        self._confusion_matrices = tuple(confusion_matrices)
        self._measure_qubits = tuple(tuple(q) for q in measure_qubits)
        self._qubits = tuple(sorted(set(q for ql in measure_qubits for q in ql)))
        self._qubits_to_idx = {q: i for i, q in enumerate(self._qubits)}
        self._cache: dict[tuple[cirq.Qid, ...], np.ndarray] = {}
        if sum(len(q) for q in self._measure_qubits) != len(self._qubits):
            raise ValueError(f"Repeated qubits not allowed in measure_qubits: {measure_qubits}.")
Initializes `cirq.TensoredConfusionMatrices`.

        `confusion_matrices[i]` should correspond to the qubit sequence `measure_qubits[i]`.

        Args:
            confusion_matrices: Sequence of confusion matrices, computed for qubit patterns present
                                in `measure_qubits`. A single confusion matrix is also accepted.
            measure_qubits: Sequence of smaller qubit patterns, for which the confusion matrices
                            were computed. A single qubit pattern is also accepted. Note that
                            each qubit pattern is a sequence of qubits used to label the axes of
                            the corresponding confusion matrix.
            repetitions:    The number of repetitions that were used to estimate the confusion
                            matrices.
            timestamp:      The time the data was taken, in seconds since the epoch. This will be
                            zero for fake data (i.e. data not generated from an experiment).

        Raises:
            ValueError: If length of `confusion_matrices` and `measure_qubits` is different or if
                        the shape of any confusion matrix does not match the corresponding qubit
                        pattern.
        
cirq-core/cirq/experiments/readout_confusion_matrix.py