Repository: Qiskit/qiskit-terra (python)

Issue:
marginal_counts is broken for pulse results
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: 0.18.0
- **Python version**: 3.9
- **Operating system**: OSx

### What is the current behavior?
`marginal_counts` is broken for pulse jobs. I


### Steps to reproduce the problem
```python
from qiskit import pulse, QuantumCircuit, schedule, transpile, execute, IBMQ
from qiskit.result import marginal_counts


IBMQ.load_account()
provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
backend = provider.get_backend('ibmq_armonk')

qc = QuantumCircuit(1,1)
qc.measure(0, 0)

job = backend.run(schedule(transpile(qc, backend), backend))
marginal_counts(job.result(), indices=[0])
```
Gives output
```
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-8e897d2c2a54> in <module>
     11 
     12 job = backend.run(schedule(transpile(qc, backend), backend))
---> 13 marginal_counts(job.result(), indices=[0])

~/opt/anaconda3/envs/python39/lib/python3.9/site-packages/qiskit/result/utils.py in marginal_counts(result, indices, inplace, format_marginal)
     55             experiment_result.data.counts = new_counts_hex
     56             experiment_result.header.memory_slots = len(indices)
---> 57             csize = experiment_result.header.creg_sizes
     58             experiment_result.header.creg_sizes = _adjust_creg_sizes(csize, indices)
     59         return result

AttributeError: 'QobjExperimentHeader' object has no attribute 'creg_sizes'
```


### What is the expected behavior?



### Suggested solutions
It seems like it is assuming `creg` will be present in the header. This is not true for pulse jobs which do not have classical registers and therefore this field won't be present. The fix should make marginal_counts work when the header is empty.


Pull request:
fix marginal_counts (which failed on pulse backend) (issue #6430)
Co-authored-by: rithikaadiga <56549493+rithikaadiga@users.noreply.github.com

When marginal_counts is passed a result that has ExperimentResults in it with headers that lack creg_sizes instance-variables, it just skips the "_adjust_creg_sizes" updating logic.

The test "test_result.py" is modified (by introducing a new test-class that subclasses the existing test) so that all the tests are run with versions of Result that have that field removed.  Again: there's a test there.  So subclass it, and in the subclass, during generation of Result-objects, remove the creg_sizes field.  Then all the tests will run (in the subclass).

<!--
⚠️ If you do not respect this template, your pull request will be closed.
⚠️ Your pull request title should be short detailed and understandable for all.
⚠️ Also, please add a release note file using reno if the change needs to be
  documented in the release notes.
⚠️ If your pull request fixes an open issue, please link to the issue.

- [x] I have added the tests to cover my changes.
- [x] I have updated the documentation accordingly.
- [x] I have read the CONTRIBUTING document.
-->

### Summary



### Details and comments


Fixes #6430 

Patch:
diff --git a/qiskit/result/utils.py b/qiskit/result/utils.py
index c26a5fec4..d518db6f9 100644
--- a/qiskit/result/utils.py
+++ b/qiskit/result/utils.py
@@ -75,8 +75,9 @@ def marginal_counts(
 
             if indices is not None:
                 experiment_result.header.memory_slots = len(indices)
-                csize = experiment_result.header.creg_sizes
-                experiment_result.header.creg_sizes = _adjust_creg_sizes(csize, indices)
+                csize = getattr(experiment_result.header, "creg_sizes", None)
+                if csize is not None:
+                    experiment_result.header.creg_sizes = _adjust_creg_sizes(csize, indices)
 
             if getattr(experiment_result.data, "memory", None) is not None and indices is not None:
                 if marginalize_memory is False:
diff --git a/releasenotes/fix-marginal_counts-on-pulse-backend.yaml b/releasenotes/fix-marginal_counts-on-pulse-backend.yaml
new file mode 100644
index 000000000..b3ce3e64b
--- /dev/null
+++ b/releasenotes/fix-marginal_counts-on-pulse-backend.yaml
@@ -0,0 +1,10 @@
+---
+fixes:
+  - |
+    The method :meth:`qiskit.result.marginal_counts`, when passed a :class:`.Result` from a
+    pulse backend, would fail, because it contains an array of
+    :class:`.ExperimentResult` objects, each of which have an :class:`QobjExperimentHeader`, and those
+    :class:`ExperimentHeaders` lack `creg_sizes` instance-variables.  If the :class:`Result` came
+    from a simulator backend (e.g. Aer), that instance-variable would be there.
+    We fix :class:`marginal_counts` so that it skips logic that needs `creg_sizes` if the
+    field is not present, or non-None.


Test patch:
diff --git a/test/python/result/test_result.py b/test/python/result/test_result.py
index 3d0f816af..9749ad252 100644
--- a/test/python/result/test_result.py
+++ b/test/python/result/test_result.py
@@ -731,3 +731,18 @@ class TestResultOperationsFailed(QiskitTestCase):
         self.assertEqual(
             'Result for experiment "99" could not be found.', context.exception.message
         )
+
+    def test_marginal_counts_no_cregs(self):
+        """Test that marginal_counts without cregs See qiskit-terra/6430."""
+        raw_counts_1 = {"0x0": 4, "0x1": 7, "0x2": 10, "0x6": 5, "0x9": 11, "0xD": 9, "0x12": 8}
+        data_1 = models.ExperimentResultData(counts=dict(**raw_counts_1))
+        exp_result_header_1 = QobjExperimentHeader(memory_slots=5)
+        exp_result_1 = models.ExperimentResult(
+            shots=54, success=True, data=data_1, header=exp_result_header_1
+        )
+
+        result = Result(results=[exp_result_1], **self.base_result_args)
+
+        _ = marginal_counts(result, indices=[0])
+        marginal_counts_result = marginal_counts(result, indices=[0])
+        self.assertEqual(marginal_counts_result.get_counts(), {"0": 27, "1": 27})