Repository: mir-evaluation/mir_eval
Issue: display submodule
Root cause: Unimplemented Feature Gap

For making useful qualitative plots for eval-by-eye


FWIW, this issue is starting to pop up in jams https://github.com/marl/jams/issues/93 wrt pretty-printing annotations.

It might be good to sync on this, just to figure out what reasonable requirements would be.


I think this issue was mainly for plots, not pretty-printing annotations, but the two are roughly related.


"plots" meaning ... what?


You know, [plots](https://en.wikipedia.org/wiki/Plot_%28graphics%29).


Er, plots of what? Scores?  Annotations?

I'd argue that score-plotting is best handled by collecting results in a dataframe and using seaborn.  (Or other custom code; point is we'd likely be reinventing the wheel to do that in mir_eval).

Annotation-plotting is a different story though.


Annotations.


> Annotations.

Ok; that's why I ask. :)  Note that by "pretty-printing" what I actually mean is notebook-embed and svg rendering.  (There are several good reasons to want direct svg output for this, rather than going through matplotlib, but i digress.)

It'd be good if we could minimize overlap in functionality/implementation on this.


Dead feature?


Not dead, but (IMO) it's more natural to fit this into [JAMS](https://github.com/marl/jams/pull/110) than mir_eval.


Yeah, thanks! :smiley:


Reversing my prior comments on this after discussing in the jams threads: mir_eval should have some basic viz/plotting, and JAMS can decorate these with metadata/subplots/etc.

Let's make a wish-list of how this should work?
- events (onsets, beats, etc): vertical lines or dotted points?  i can see a good case for either.
- disjoint intervals: i like how [msaf](https://github.com/urinieto/msaf) does this, but it might get dense for short annotations (ie chord labels)
- segment hierarchy: msaf does a nice job of this as well.
- overlapping intervals (eg instrument activations): i think the only sane thing here is to group intervals by label, and give each unique label a different vertical position.  I suspect an alpha channel setting here might be necessary for when similarly labeled intervals also overlap.
- source separation: ???  should we bother with this?
- tempo: ??
- pitch: log-frequency curves seem reasonable to me.  voicing can be indicated by solid/dashed style or different alpha values.

Additional issues:
- What kind of convention do we want for comparing annotations visually?  I imagine a standard use-case would be plotting a reference and estimate in a way that makes visual comparison easy.  This will be different for different types of annotations:
  - events and simple intervals: vertical separation makes sense, since only the horizontal axis here.  This can be done cleanly with tightly packed vertical subplots.  Plotting both on the same axes could also work though, provided the styles are clearly denoted.
  - overlapping intervals and hierarchies: this would be tricky to pull off, since both horizontal and vertical axes have meaning.  I think vertical subplots are the best bet here.
  - hierarchies: ?? no idea
  - pitch: same axes makes sense, again with style clearly denoted.


Thanks for starting this discussion.

> events (onsets, beats, etc): vertical lines or dotted points? i can see a good case for either.

Probably allow for either.

> disjoint intervals: i like how msaf does this, but it might get dense for short annotations (ie chord labels)
> segment hierarchy: msaf does a nice job of this as well.
> overlapping intervals (eg instrument activations): i think the only sane thing here is to group intervals by label, and give each unique label a different vertical position. I suspect an alpha channel setting here might be necessary for when similarly labeled intervals also overlap.

All sounds reasonable to me.

> source separation: ??? should we bother with this?

Sometimes a common plot is to do a time-frequency plot with different sources being different colors.  It would definitely be cool to have an automated method to create plots like Figure 1d here http://hearingbrain.org/docs/mesgarani_chang_nature_2012.pdf 

> tempo: ??

Not worth it, I don't think.  Same for key.

> pitch: log-frequency curves seem reasonable to me. voicing can be indicated by solid/dashed style or different alpha values.

Sounds good.

> What kind of convention do we want for comparing annotations visually? I imagine a standard use-case would be plotting a reference and estimate in a way that makes visual comparison easy. This will be different for different types of annotations:

As a first pass, I am fine with forcing the user to handle subplots.  This seems like something you will have to think about more in JAMS, because you will potentially have N things to compare.


> pitch: log-frequency curves seem reasonable to me. voicing can be indicated by solid/dashed style or different alpha values.

Again, same as sonification this needs to be separated into notes and continuous f0 (pitch contour). For the note case I'd go with overlapping piano rolls as in [this gist](https://gist.github.com/justinsalamon/3672e968a2cbee36853b0d4a4374d707) I cooked up a while back for a potential JAMS viz module.

For pitch contour continuous curves on a log-frequency scale (I think a cent scale would be most informative) sounds good to me. We'll have to think carefully about styling, since comparing curves with a large amount of overlap visually can get a little tricky (so alpha / color / thickness are things we'll have to play with).

Re: convention, for the JAMS example it actually takes a list of annotations and visualizes all of them (without any constraints on the length of the list). Being able to visualize 1, 2, or N annotations together would be my preference, though it might not fit into the ref/est paradigm of `mir_eval`.


> Probably allow for either.

I'd rather stick to one or the other, since they're pretty different from an api perspective.

> It would definitely be cool to have an automated method to create plots like Figure 1d here

Oooooh, those are slick!  Really difficult to automate well, but I have some thoughts on how to do it.  The trick will be getting it to work with more than two sources and not look like clown barf.

Jotting implementation thoughts for how this can work:
1. Compute magnitude spectrograms for all sources.  We can be sloppy here, and use scipy.signal.spectrogram
2. Assign each source a color via prop_cycler on a qualitative colormap (eg `pairs`), and make a colormap that interpolates from `(1,1,1,0)` to `(r,g,b,1)`
3. Normalize the magnitude of each time-frequency bin according to the total magnitude across all sources.
4. Render all spectrograms on top of eachother by `pcolormesh`.

> Not worth it, I don't think. Same for key.

Agreed.  Time-varying versions of this can dump into the disjoint interval plotter.

> As a first pass, I am fine with forcing the user to handle subplots.

Right.  As input, each viz function should accept a target axis, or create a new one if none is provided.  Each viz should return the constructed axis.


> Again, same as sonification this needs to be separated into notes and continuous f0 (pitch contour). For the note case I'd go with overlapping piano rolls as in this gist I cooked up a while back for a potential JAMS viz module.

Good point, I'd forgotten about piano-roll.  I like your version of it; the comparison can be done easily by plotting the reference first, then the estimate on the same axes, and giving both alpha values.

> For pitch contour continuous curves on a log-frequency scale (I think a cent scale would be most informative) sounds good to me. We'll have to think carefully about styling, since comparing curves with a large amount of overlap visually can get a little tricky (so alpha / color / thickness are things we'll have to play with).

Yup.  The styling, I'd imagine, should be set by pass-through kwargs, but we should try to cook up some good defaults.

> Re: convention, for the JAMS example it actually takes a list of annotations and visualizes all of them (without any constraints on the length of the list). Being able to visualize 1, 2, or N annotations together would be my preference, though it might not fit into the ref/est paradigm of mir_eval.

That, I think, is a separate issue.  In JAMS, I'd be happy to just stack up the entire list of annotations vertically, since they'll generally be heterogeneous anyway.

Ref-vs-est would be a separate function (functions?) on top of the core plotting routines that make head-to-head comparisons easier.


> I'd rather stick to one or the other, since they're pretty different from an api perspective.

The main difference in API is that for vlines you have to specify the top and bottom, right?  I would be fine with using the supplied axis' ylim, as long as that behavior was specified, and defaulting to dots.  Or, yeah, we can do one or the other.

> Assign each source a color via prop_cycler on a qualitative colormap (eg pairs), and make a colormap that interpolates from (1,1,1,0) to (r,g,b,1)

This is roughly what I was thinking too.

> Right. As input, each viz function should accept a target axis, or create a new one if none is provided. Each viz should return the constructed axis.

Yes.

> Re: convention, for the JAMS example it actually takes a list of annotations and visualizes all of them (without any constraints on the length of the list). Being able to visualize 1, 2, or N annotations together would be my preference, though it might not fit into the ref/est paradigm of mir_eval.

and

> That, I think, is a separate issue. In JAMS, I'd be happy to just stack up the entire list of annotations vertically, since they'll generally be heterogeneous anyway.
> Ref-vs-est would be a separate function (functions?) on top of the core plotting routines that make head-to-head comparisons easier.

This makes sense for JAMS and not `mir_eval`, I think.  For example, `sonify` doesn't provide mechanisms for sonifying multiple things and combining them together (in different channels? on top of each other? etc) and I am comfortable leaving this up to the end-user (or `mir_eval`-using library, like JAMS).  Giving axis-in, axis-out access provides the most generic, straightforward, and easy-to-use flexibility for this.  If anyone can come up with a clean and flexible way to do something which is otherwise hard for the end-user to do (i.e. more than a few lines of code), I'm happy to consider it, but I'm also very comfortable with `mir_eval` not trying to handle this stuff.


sgtm. once the viz is coded up (sonification is mostly there I guess) I think it'd be really nice for the community if we created a notebook illustrating these functionalities using both mir_eval and JAMS. Maybe even an LBD.


[Source separation viz demo](https://gist.github.com/5ab693745157de0989f8b35ce572106e) .. not too hard to get about 85% of the way there.

> Maybe even an LBD.

I'm into this idea.  Because we don't have enough things on our plate as is.


> I'm into this idea. Because we don't have enough things on our plate as is.

![more](http://s2.quickmeme.com/img/0d/0dc5e9ebd13f6720270f2975381dcfa2fad3326fa0bc7ee4f550f0129e02a3a0.jpg)


> Source separation viz demo .. not too hard to get about 85% of the way there.

Nice.


This is wonderful. It's like watching my source separation thesis being written for me so I have time catching up on Game of Thrones. :heart: 


For avoiding clown barf when there are multiple sources, one visualization could be to plot estimated waveforms (black) on top of the references (grey), and then having individual spectrograms instead. Might turn into a lot of subplots though. Example:
![image](https://cloud.githubusercontent.com/assets/1595907/15601637/d266a1e2-23f0-11e6-8db1-a7bf9ee5ed94.png)

Another silly way might be to take the original mix spectrogram and subtract an estimated mix from it, and plot the remaining sound instead, but this would not make a clear distinction between actual remaining source sound and introduced source separation artifacts, e.g. just something simple as:
![image](https://cloud.githubusercontent.com/assets/1595907/15601719/3d48e114-23f1-11e6-9024-3cfc49a6d1e2.png)


[Interval plotting notebook](https://gist.github.com/188c27935790e4c5add4c2da425437a7) is coming along.  Comments about missing functionality and/or API conventions would be welcome at this point.


> For avoiding clown barf when there are multiple sources, one visualization could be to plot estimated waveforms (black) on top of the references (grey), and then having individual spectrograms instead. Might turn into a lot of subplots though.

Yeah... If I can abstract a bit from @craffel 's previous comments, I think the plots you're describing can be easily done with existing primitives (except maybe for waveplot, which can be pulled from librosa if needed).

IMO mir_eval's display module should only implement routines that draw on a single axes and are otherwise difficult to do (eg, interval plots).  Anything requiring subplots should be kicked upstream to the user.


In principle one can use the non-overlapping viz for chords too, right? In the case of chords the overlapping viz is awesome for getting a birds-eye view of all chords in the track, but if you want to actually listen to the song and follow the chord annotation this viz is a little hard to follow because of the large vertical jumps, so the non-overlapping visualization would be more helpful in that scenario I think.

The issue is that given the large chord vocabulary, mapping each chord to a color and providing a legend can also get unwieldy/unhelpful. How about adding the option to actually plot the label name of each interval on the interval? I think this would be very helpful for chords (and probably other non-overlapping intervals).


> In principle one can use the non-overlapping viz for chords too, right?

Yup, and you can use overlapping for segments, which is perhaps better depending on what you're trying to communicate.  For example, if you have small segments `A->B->C`, this is hard to see as a larger pattern in the disjoint plot, but the shapes pop visually in the overlapping plot.  The disjoint plot is better for overlaying on a spectrogram though, so YMMV.

> The issue is that given the large chord vocabulary, mapping each chord to a color and providing a legend can also get unwieldy/unhelpful.

That's one issue. Another issue is that we quickly run out of color/texture-based styles in large vocabularies, so if you're relying solely on rectangle style (and not vertical position) to differentiate, it's easy to get lost.  We can chain up property cyclers to move from flat to cross-hatched, then to alpha channels, etc, but the returns on this diminish quickly.

The bigger issue is that chord intervals are often too small to fit a meaningful text decoration inside.  If we have `%matplotlib nbagg` or mpld3 enabled, we could use hover text for this, but I don't think it should be the primary mode of communicating segment identity.

Finally, we probably should put some thought into having some way to impose consistent styling of labels across plots.  When comparing an estimate to a reference (say, for chords), you probably want the same labels in the same positions with the same styles. I think the simplest way to do this is to allow the user to supply an ordered list `reference_labels` that are used to populate the first `n` positions.  Any labels in the input that are not in `reference_labels` are then printed starting at positions`n+1`.  This way, you could plot a reference and estimate side-by-side, or even on top of each other (with alpha channels and/or hatching), and still have a sane result.


[Notebook updated](https://gist.github.com/bmcfee/188c27935790e4c5add4c2da425437a7) to support optional text labels in disjoint intervals, and pre-set reference labels for overlapping intervals (not demoed in the notebook currently, but functional).

Short-term to-dos: 
- [ ] fix the property cycler to work with arbitrarily many inputs
- [ ] fix text positioning in disjoint interval labeler
- [x] figure out a clean way to override the cycler to support in-place comparison of overlapping intervals

Longer-term to-dos:
- hierarchy viz: I see two ways of doing this, both of which can be done with the two functions already in place:
  - msaf-style, which is a stack of disjoint interval plots
  - overlapping-style: throw all of the segments together as overlapping intervals, but impose a sane ordering between different hierarchical levels.
- piano roll:
  - should be not-too-hard on top of the overlapping interval plotter
- pitch contours
  - only hard thing here is getting the axes to line up nicely so that we can draw this directly on top of a spectrogram without any brute-force manipulation
- ref-vs-est comparison wrappers
- clean up source separation


[Notebook updated](https://gist.github.com/bmcfee/188c27935790e4c5add4c2da425437a7) for overlapping interval comparisons with inequal label sets.  Property cycling is still a little broken here, but it's good to know that the basic idea works.

Double-update: it can now infer reference labels from pre-existing tick markers.  This is somewhat brittle because detecting empty ticks in matplotlib isn't easy.  It's certainly possible to break it (say by overlapping a plot on top of another plot with no ticks), but I can't imagine it would happen frequently or in meaningful scenarios.


> Yeah... If I can abstract a bit from @craffel 's previous comments, I think the plots you're describing can be easily done with existing primitives (except maybe for waveplot, which can be pulled from librosa if needed).
> IMO mir_eval's display module should only implement routines that draw on a single axes and are otherwise difficult to do (eg, interval plots). Anything requiring subplots should be kicked upstream to the user.

Agreed here.

> That's one issue. Another issue is that we quickly run out of color/texture-based styles in large vocabularies, so if you're relying solely on rectangle style (and not vertical position) to differentiate, it's easy to get lost. We can chain up property cyclers to move from flat to cross-hatched, then to alpha channels, etc, but the returns on this diminish quickly.

It seems to me like a logical and sane way to handle this for chords (where we can have huge, but structured, vocabularies) would be to have color mapped to chord root and vertical position mapped to chord type. The same twelve colors would always correspond to the twelve roots, and for example in a min/maj vocabulary, we'd have two vertical positions.  The number of possible chord types could be inferred at call time or user-specified, and would have a consistent ordering (major on the bottom, then minor, then seventh, etc).  Does this seem reasonable?  I don't think we need a separate row for each chord type, as your example currently shows.  Otherwise looking good to me.

> The bigger issue is that chord intervals are often too small to fit a meaningful text decoration inside. If we have %matplotlib nbagg or mpld3 enabled, we could use hover text for this, but I don't think it should be the primary mode of communicating segment identity.

This would be very cool, but we should focus on nice visualization for the baseline of what people have installed first.


> It seems to me like a logical and sane way to handle this for chords (where we can have huge, but structured, vocabularies) would be to have color mapped to chord root and vertical position mapped to chord type. The same twelve colors would always correspond to the twelve roots, and for example in a min/maj vocabulary, we'd have two vertical positions. The number of possible chord types could be inferred at call time or user-specified, and would have a consistent ordering (major on the bottom, then minor, then seventh, etc). Does this seem reasonable?

I think a simpler version of this is to just reduce the color property to depend only on the root (+ no-chord) and leave the rest of the logic (lexicographic sorting) as is.  I've already dropped the hatching cycler from the overlap-interval plot, since vertical position is enough to disambiguate and even color is just eye-candy.

Some potential snags I see here:
1. how do we know when the labels being plotted are chords?  do we want a special plotter just for that?
2. overlaying two plots with different label sets would break the ordering.  Currently, you can plot the reference first, and then when you plot the estimate, any additional labels are tacked onto the end of the axis (this way we don't have to redraw anything).  If you have a quality in the estimate that wasn't in the reference, it'll end up out of order and away from the other chords of the same root.
3. Any ordering we impose on the labels is going to be wrong anyway.  Grouping by root might be a good heuristic, but so could grouping by key membership (or loads of other options).  I think we should do the simplest possible thing here (lex sort), but I'm open to persuasive arguments.

> I don't think we need a separate row for each chord type, as your example currently shows. Otherwise looking good to me.

I think we do.  If you want them plotted together, they should be reduced first by a helper routine.  In general, determining "equivalence" between different labels is a way bigger problem than we should hope to resolve within a plotting function.  Is "A" the same as "A/3"?  What about "verse" and "verse'"?  It's an endless rabbit hole.


> how do we know when the labels being plotted are chords? do we want a special plotter just for that?

Yes, I think so.  Chords are different enough from segments (mainly because of potential vocab size) that I think this is reasonable; they can use the same core routine but chord can have additional logic for e.g. coloring things by root.

> Any ordering we impose on the labels is going to be wrong anyway. Grouping by root might be a good heuristic, but so could grouping by key membership (or loads of other options). I think we should do the simplest possible thing here (lex sort), but I'm open to persuasive arguments.

I think grouping (assuming by "grouping" you mean putting things in the same vertical row) by root is totally sane and probably expected behavior.  Lexical sorting _after grouping by root_ sounds fine to me.

> I think we do. If you want them plotted together, they should be reduced first by a helper routine. In general, determining "equivalence" between different labels is a way bigger problem than we should hope to resolve within a plotting function. Is "A" the same as "A/3"? What about "verse" and "verse'"? It's an endless rabbit hole.

I think I wasn't clear, what I meant was each different _chord_.  To try to get on the same page, your example shows

```
C maj |     ---          --  ---        --------
D maj |           -----           ----
E min |                 -  -                        ------
C min | ----                          
```

I think it would be more sane if it was 

```
maj |     CCC   DDDD       CC  CCC   DD     CCCC
min | CC             EEEE               EE 
```

where all things labeled `C` are the same color, all things `D` are another color, etc.  Does this make sense?  The vertical ordering of maj, min, etc. is not that important I don't think.  Essentially, we'd use `chord.split` to get the root which determines the color, and then have a separate row for each quality, scale degree, and bass combination which appears in the chord labels.

Of course, if you decide it works best having a completely separate row for each individual chord label, I think that could work OK too, it will just have to be a very tall plot to get all of the labels visible on the y axis, and might be hard to follow.


> Yes. Chords are different enough from segments (mainly because of potential vocab size) that I think this is reasonable; they can use the same core routine but chord can have additional logic for e.g. coloring things by root.

Okay.  In that case, let me finish up a solid prototype of the current general-purpose plotter and then we can figure out how to build a chord plotter on top of it.  FWIW, I'm thinking much more generally than "segments" here, and designing more for things like time-varying labels, which can also have a large and open vocab.

> I think grouping (assuming by "grouping" you mean putting things in the same vertical row) by root is totally sane and probably expected behavior. Lexical sorting after grouping by root sounds fine to me.

If by "row" you mean "block of rows", then yes.  I don't expect/wouldn't understand how to read a plot with different qualities on the same root-oriented row.

> I think I wasn't clear, what I meant was each different chord. To try to get on the same page, your example shows
> 
> C maj |     ---          --  ---        --------
> D maj |           -----           ----
> E min |                 -  -                        ------
> C min | ----  
> I think it would be more sane if it was
> 
> maj |     CCC   DDDD       CC  CCC   DD     CCCC
> min | CC             EEEE               EE 
> where all things labeled C are the same color, etc. Does this make sense?

I would have a much harder time reading the second one than the first.  It would also require a lot more visual style differentiation to separate "C" from "D" and "E".

I would expect something more like

```
E min |                 -  -                        ------
D maj |           -----           ----
C min | ----                          
C maj |     ---          --  ---        --------
```

where chords sharing the same root have a common color.  This is essentially what we have now (except the color) -- your first example is not how the current implementation works.

> Of course, if you decide it works best having a completely separate row for each individual chord label, I think that could work OK too, it will just have to be a very tall plot to get all of the labels visible on the y axis, and might be hard to follow.

I'm not sure that it would.  Most songs don't have that many unique chords, and if we provide reduction mechanisms (say, collapse to 25 or 25+sevenths, etc), it would probably retain the info most people care about and still be simple enough to parse.

I'd be curious for @ejhumphrey's input here, since he knows a thing or two about chords.


> Short-term to-dos:
> - [ ] fix text positioning in disjoint interval labeler

My vote would be to place the label text in the middle of the rectangle (both vertically and horizontally) - I think it'd be the easiest to see this way. This might be overkill but an optional parameter for setting the label size might also be appreciated.


> My vote would be to place the label text in the middle of the rectangle (both vertically and horizontally) - I think it'd be the easiest to see this way. This might be overkill but an optional parameter for setting the label size might also be appreciated.

You can pass through arguments (eg font size) to the annotation object through `text_kw`.

I'm not a fan of centering the annotation inside the patch for two reasons:
1. if you're overlaying the rects on a spectrogram, it's more likely to interfere with the data if it's (vertically) centered)
2. if you're comparing two segmentations by vertical stacking, horizontal centering will look awkward.  I'd rather stick to one corner; fwiw, sonic-visualizer uses north-west.


Then I'd go with NW


> It would also require a lot more visual style differentiation to separate "C" from "D" and "E".

Don't you think there are at least ~~12~~ 13 easily distinguishable colors?  For example, Colorbrewer goes up to 12 for qualitative colormaps: http://colorbrewer2.org

> Most songs don't have that many unique chords,

I think this is the important question and is where we see things different (resulting in different visualization requirements), really.  Can you do some quick JAMS wizardry to get the statistics of the number of chord labels per song across the datasets you guys have converted?

> if we provide reduction mechanisms

Yeah, this would be good but it's a big if - do intuitive mechanisms exist?  Can we also indicate when a reduction has taken place in a reasonable way?  These are all questions I can't answer but @ejhumphrey probably can.


> Don't you think there are at least 12 13 easily distinguishable colors? For example, Colorbrewer goes up to 12 for qualitative colormaps: http://colorbrewer2.org

I'll just add to the mix that I don't think it's reasonable for a user to memorize a mapping from 12 colors to 12 chords (even if the colors are easily distinguishable), even with a legend at hand.

This is a bit of a side note, but I think it'd be cool to try and target these visualizations not just at MIR experts (or generally people who are good at parsing graphs). Looking into the future, I can see a mir_eval/JAMS based annotation collection tool targeted at amateur musicians; providing something they can make sense of would be neat.


> I'll just add to the mix that I don't think it's reasonable for a user to memorize a mapping from 12 colors to 12 chords (even if the colors are easily distinguishable), even with a legend at hand.

Sure, but the explicit values are much less important than just being able to compare them.  The most important operation when looking at the graph will be "Are these two chords the same?" both when comparing two (ref/est) graphs and when looking at a single one.  I mean, you could say the exact same thing about vertical positioning of different chords - of course we don't expect people to memorize a mapping between height and N different chords either.  In this case, we just want them to be able to see that the chords are different (because they have different vertical heights), and they can refer to the y labels as needed.


> Sure, but the explicit values are much less important than just being able to compare them. The most important operation when looking at the graph will be "Are these two chords the same?" both when comparing two (ref/est) graphs and when looking at a single one. I mean, you could say the exact same thing about vertical positioning of different chords - of course we don't expect people to memorize a mapping between height and N different chords either. In this case, we just want them to be able to see that the chords are different (because they have different vertical heights), and they can refer to the y labels as needed.

Yes, as long as labels are supported it should be ok. I actually disagree about the values being much less important - for a meaningful error analysis you really want to see how labels get misclassified. But perhaps I'm going off topic :)


> Don't you think there are at least 12 13 easily distinguishable colors? For example, Colorbrewer goes up to 12 for qualitative colormaps: http://colorbrewer2.org

That's not going to translate to print/colorblind-friendly modes very easily.

> Can you do some quick JAMS wizardry to get the statistics of the number of chord labels per song across the datasets you guys have converted?

Who needs jams when we've got shell scripts?  Here's the histogram on beatles:

![image](https://cloud.githubusercontent.com/assets/1190540/15618746/caca5fc8-241d-11e6-91ee-7977a171b308.png)

The max is 30 (Straweberry fields forever) and is only that high because of inversions.  I'm too lazy to script something that squashes inversions, but i imagine a more reasonable upper bound is something like 15.

> Yeah, this would be good but it's a big if - do intuitive mechanisms exist? Can we also indicate when a reduction has taken place in a reasonable way

Wat?  I'm imagining something very explicit, like

``` python
mir_eval.display.chords(intervals, mir_eval.chord.reduce_majmin(labels))
```

> The most important operation when looking at the graph will be "Are these two chords the same?"

I'm not sure I agree.  Easily spotting identical chords is important, but it's also important to be able to see patterns of repeating progressions.


One more comment that maybe got lost in the mix:

Using color to indicate identity basically means that we can't plot two annotations on top of each other, and I'd really hate to lose that ability.


> That's not going to translate to print/colorblind-friendly modes very easily.

Yes, of course.

> The max is 30 (Straweberry fields forever) and is only that high because of inversions. I'm too lazy to script something that squashes inversions, but i imagine a more reasonable upper bound is something like 15.

In that case it seems probably ok to do vertical spacing.  Though 30 is a lot of y labels.  Even 15 is going to mean a very tall figure though when you want the labels to be legible.  We could maybe do some kind of hierarchical labeling like I do in [Figure 1(h)](http://colinraffel.com/publications/ismir2016extracting.pdf) but that would be hard to do cleanly.

> it's also important to be able to see patterns of repeating progressions.

For sure, I think you could see it either way!  Colors show pattern too...

> Using color to indicate identity basically means that we can't plot two annotations on top of each other, and I'd really hate to lose that ability.

Assuming that you mean plotting two annotations on the same axis with alpha, color works fine for this as long as no combination of colors appears in the colormap, which seems true in general, especially for colormaps where the lightness is uniform.

But anyways, I can live with the vertical case.  I might just be a pain in the ass about y labeling.


> Then I'd go with NW

Why?  ("sonic-visualizer does it" is not an acceptable answer)


> Why? ("sonic-visualizer does it" is not an acceptable answer)

Because that's closest to how [musicians annotate chords in charts](http://www.simon-harris-projects.com/advancedguitarplayer/images/stories/SheetMusic/autumn-leaves-real-book-lead-sheet-em.gif) and I find it more intuitive than the other 3 corners.


> Assuming that you mean plotting two annotations on the same axis with alpha, color works fine for this as long as no combination of colors appears in the colormap, which seems true in general, especially for colormaps where the lightness is uniform.

I don't see how that would work?  Quick: tell me which chords came from which annotation here:
![image](https://cloud.githubusercontent.com/assets/1190540/15619078/ddbc3672-241f-11e6-82bf-bb2401f23926.png)

vs here:
![image](https://cloud.githubusercontent.com/assets/1190540/15619084/e290b358-241f-11e6-8c70-21f07086eeb4.png)


> I don't see how that would work? Quick: tell me which chords came from which annotation here:

Ah, yeah, I was thinking just being able to tell whether the two annotators agreed, not which annotator a chord came from.  I can understand if that's something that should be preserved.


Seems to me like this conversation went way off the rails here.. funny how chords always seems to do that.

More importantly: from an API perspective, is there anything that seems strange?  Anything that should be exposed/controllable?  (Embedded annotations are an obvious one, anything else?)


The API seems reasonable to me.  I think the functions could be named a little more clearly, i.e. overlap_intervals is useful even for disjoint intervals when they are dense (chords).  I might expect people to want to supply custom kwargs to `Rectangle` but we don't want to overdo it on the kwarg customization.  For `reference_labels`, my initial intuition was that people would find the union of the labels for all annotations being plotted and use them across all plots, so that name doesn't make total sense.  If you think that use-case is reasonable, we could provide a convenience function

```
def all_labels(*labels):
    return list(set().union(*labels))
```

or something.


> think the functions could be named a little more clearly, i.e. overlap_intervals is useful even for disjoint intervals when they are dense (chords).

Agreed.  Any suggestions?

> might expect people to want to supply custom kwargs to Rectangle but we don't want to overdo it on the kwarg customization.

You already can; `kwargs` gets added to the cycler properties.  This is how setting things like fixed color and alpha channel works.

> For reference_labels, my initial intuition was that people would find the union of the labels for all annotations being plotted and use them across all plots, so that name doesn't make total sense.

Yeah, I'm not sure what a better name would be though.  `labels` is reserved for the actual labels being plotted (for consistency with all other `(intervals, labels)` functions).  Maybe `label_set`?


> Agreed. Any suggestions?

Not really... maybe `flat_intervals` and `vertical_intervals`?

> You already can; kwargs gets added to the cycler properties. This is how setting things like fixed color and alpha channel works.

Ah, I see that.  

> Yeah, I'm not sure what a better name would be though. labels is reserved for the actual labels being plotted (for consistency with all other (intervals, labels) functions). Maybe label_set?

`y_labels`?


How about `segments` and `labeled_intervals`?

Unrelatedly: I think it actually makes sense to drop property cycling entirely from the labeled-interval display.  I think most of the time, what you'd actually want is annotation-level coloring, since height differentiates label.  If you have a fixed style for the entire annotation, then overlying two annotations becomes trivial, and intuitively works the way you'd expect most matplotlib routines to.

Similarly, for the segment display, I think it makes more sense to rely on the axes internal fill style cycler, rather than roll our own.  This way, if you draw multiple segmentations on the same plot (eg for hierarchies), the cycler maintains state naturally.  It also punts the styling decisions upstream to the matplotlib style sheets, so again, things work in a manner which is consistent with the rest of MPL.

I'll have a PR ready shortly, then we can move the discussion over there.

> y_labels?

ehh.. `y` is ambiguous here, in that it can mean `target` or `y-axis` (in this case, kinda both).  


Moving discussion to #196.