Repository: airctic/icevision

Issue:
Better Record __repr__ to show ClassMap when it is stored internally
## 🚀 Feature
**Is your feature request related to a problem? Please describe.**
More informative to show `class_map` when a `Record` object is storing it

Take for example a record loaded from the main repo:
```python
from icevision.all import *

data_dir = Path("~/icevision/samples/")
class_map = icedata.coco.class_map()
parser = parsers.COCOMaskParser(annotations_filepath=data_dir/'annotations.json', img_dir=data_dir/'images')
records = parser.parse(data_splitter=SingleSplitSplitter())[0]
record = records[0]

print(record)

## Output:

BaseRecord

common: 
	- Filepath: /Users/rahulsomani/git/icevision-orig/samples/images/000000343934.jpg
	- Image: None
	- Image size ImgSize(width=640, height=480)
	- Image ID: 0
detection: 
	- Masks: <EncodedRLEs with 1 objects>
	- Labels: [4]
	- Areas: [43522.80595]
	- BBoxes: [<BBox (xmin:175.14, ymin:175.68, xmax:496.21999999999997, ymax:415.68)>]
	- Is Crowds: [0]
```


This record internally has access to the `class_map` via `record.detection.class_map`, which is great, but not known when you print the record. Additionally, if you print `record.components`, you get:
```python
{<icevision.core.record_components.AreasRecordComponent at 0x7fbb5b54a4d0>,
 <icevision.core.record_components.BBoxesRecordComponent at 0x7fbb5b54acd0>,
 <icevision.core.record_components.FilepathRecordComponent at 0x7fbb5b54a690>,
 <icevision.core.record_components.InstancesLabelsRecordComponent at 0x7fbb5b54a7d0>,
 <icevision.core.record_components.IsCrowdsRecordComponent at 0x7fbb5b54ad90>,
 <icevision.core.record_components.MasksRecordComponent at 0x7fbb5b54a150>,
 <icevision.core.record_components.RecordIDRecordComponent at 0x7fbb5b54a9d0>,
 <icevision.core.record_components.SizeRecordComponent at 0x7fbb5b54a810>}
```
I'd have expected `ClassMapRecordComponent` to be in there as well?



Discussion:
> I'd have expected ClassMapRecordComponent to be in there as well?

Hmm, yeah.. So currently what happens is that `LabelsRecordComponent` inherits from `ClassMapRecordComponent`. Do you think it's a good idea separating them? A drawback is that we would need to pass `ClassMapRecordComponent` when creating `BaseRecord`

---

To printing `class_map` that would be a good idea, and very easy to implement, we just need to add a `_repr` to `ClassMapRecordComponent`


>  Do you think it's a good idea separating them?

I think it is a good idea indeed - having clarity on inspecting `.components` is great because it reduces the expectation of a dev to know what's happening behind the scenes as they can just see what components are being stored.

---

>  A drawback is that we would need to pass ClassMapRecordComponent when creating BaseRecord

Right. I think that's not too bad. Alternatively, we could inclue `ClassMapRecordComponent` in `BaseRecord.base_components`? Can't think of any common scenario where you don't need a ClassMap (audio, video, images included)
> Alternatively, we could include ClassMapRecordComponent in BaseRecord.base_components? Can't think of any common scenario where you don't need a ClassMap (audio, video, images included)

That would not work because each `ClassMap` is specific to a task, this is also why it's not so straight forward to separate `labels` and `class_map` into two different components. We would need to do:
```python
BaseRecord(
        (
            FilepathRecordComponent(),
            ClassMapRecordComponent(task=tasks.detection),
            InstancesLabelsRecordComponent(),
            BBoxesRecordComponent(),
        )
    )
```

And if we have classification we would need a new class map component for each.

---

Let's us first address the issue of the class map not being displayed (which is a simple solution) and we can then come back to this (maybe with another more specific issue)


Resolving patch:
diff --git a/icevision/core/record_components.py b/icevision/core/record_components.py
--- a/icevision/core/record_components.py
+++ b/icevision/core/record_components.py
@@ -80,6 +80,9 @@ def __init__(self, task):
     def set_class_map(self, class_map: ClassMap):
         self.class_map = class_map
 
+    def _repr(self) -> List[str]:
+        return [f"Class Map: {self.class_map}"]
+
     def as_dict(self) -> dict:
         return {"class_map": self.class_map}
 


Test patch: