Stim doesn't currently support recording errors when sampling from a circuit, but it does support recording errors when sampling from a detector error model via the
return_errors=True argument of
stim.CompiledDemSampler.sample. It can also replay errors via the
recorded_errors_to_replay argument, allowing you to e.g. remove or add one error and redo a simulation.
To get samples you would make a surface code stim circuit, get the dem via
stim.Circuit.detector_error_model, get the dem sampler via
stim.DetectorErrorModel.compile_sampler, and collect shots+errors via
To do error correction, take the detection event data returned by the sample method and feed it to pymatching. Use
pymatching.Matching.from_detector_error_model to get a decoder and then give your sampled detection event data to
pymatching.Matching.decode_batch to predict the observable flip data.
Whenever it predicts wrong, that's a logical error.
Interpreting the sampled errors is the hard part that requires a lot of glue coding. The error data is just a flat list of bits, with the k'th bit being set if the k'th error declared in the detector error model fired. You need to turn this list of bits into a representation that's useful for your purposes. Typically this would involve iterating through the dem's instructions (use
stim.DetectorErrorModel.flattened to simplify this by inlining loops and coordinate shifting), noting what each error does, creating some dictionary mapping from the error index k to the interpreation. For example, for each error, pull out which detectors it flips and use
stim.DetectorErrorModel.get_detector_coordinates to determine if it's an X type or Z type error. Note that you can sort of map back to circuit errors by using
An example of what I've done with this kind of workflow is to count how many times an edge is associated with a logical error, and make heat maps. This sort of tells a story of where the weakest error paths are.