Repository: Qiskit/qiskit

Issue:
Timeslots should have informative representation
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?
Currently `Interval`, `Timeslot` and `TimeslotCollection` have the standard python object representation. This should be replaced with an informative implementation of `__repr__`. As `TimeslotCollection` contains `Timeslot`s and `Timeslot`s contain `Interval`s the hierarchal nature of these data structure should be used to derive representations.

### Example
A possible representation might look like

Interval:
`(t0, tf)` eg. `(0, 10)`

Timeslot: Is an interval on a channel
`(channel, repr(interval))`: `(DriveChannel(0), (0, 10))`

TimeslotCollection: Is a dictionary of timeslots. Ie. it groups together intervals on channels.

`{channel1: [repr(interval1_c1), repr(interval2_c1), ...]), channel2: [repr(interval1_c2), repr(interval2_c2), ...]}`


Discussion:
I can work on making this addition
Currently, my code I'm testing would cause the following code:
```
print(Interval(0, 10))
print(Timeslot(Interval(0, 10), AcquireChannel(0)))
print(TimeslotCollection(Timeslot(Interval(0, 10), AcquireChannel(0)),
                         Timeslot(Interval(0, 10), AcquireChannel(1))))
```
to output
```
(begin: 0, end: 10)
(AcquireChannel(0), (begin: 0, end: 10))
{AcquireChannel(0): [(begin: 0, end: 10)], AcquireChannel(1): [(begin: 0, end: 10)]}
```

Does this seem ok?
This seems on the right track. What I think might communicate that these are objects is an output that looks something like
```
Interval(0, 10)
Timeslot(AcquireChannel(0), (0, 10))
TimeslotCollection(AcquireChannel(0): [(begin: 0, end: 10)], AcquireChannel(1): [(begin: 0, end: 10)])
```
Yeah, that would be helpful to have printed out as well. I will make that addition, and then open the PR.
Is it possible to have a `Timeslot` with multiple `Interval`s? For example, would this be valid:
```
Timeslot([Interval(0, 10), Interval(11, 20)], AcquireChannel(0))
```
Or any format of inputting more than one `Interval`.
Currently, this functionality is handled by the TimeslotCollection

Resolving patch:
diff --git a/qiskit/pulse/timeslots.py b/qiskit/pulse/timeslots.py
--- a/qiskit/pulse/timeslots.py
+++ b/qiskit/pulse/timeslots.py
@@ -98,6 +98,10 @@ def __eq__(self, other):
             return True
         return False
 
+    def __repr__(self):
+        """Return a readable representation of Interval Object"""
+        return "{}({}, {})".format(self.__class__.__name__, self.begin, self.end)
+
 
 class Timeslot:
     """Named tuple of (Interval, Channel)."""
@@ -134,6 +138,12 @@ def __eq__(self, other) -> bool:
             return True
         return False
 
+    def __repr__(self):
+        """Return a readable representation of Timeslot Object"""
+        return "{}({}, {})".format(self.__class__.__name__,
+                                   self.channel,
+                                   (self.interval.begin, self.interval.end))
+
 
 class TimeslotCollection:
     """Collection of `Timeslot`s."""
@@ -254,3 +264,10 @@ def __eq__(self, other) -> bool:
         if self.timeslots == other.timeslots:
             return True
         return False
+
+    def __repr__(self):
+        """Return a readable representation of TimeslotCollection Object"""
+        rep = dict()
+        for key, val in self._table.items():
+            rep[key] = [(interval.begin, interval.end) for interval in val]
+        return self.__class__.__name__ + str(rep)


Test patch: