Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

display submodule #28

Closed
craffel opened this issue Mar 26, 2014 · 52 comments
Closed

display submodule #28

craffel opened this issue Mar 26, 2014 · 52 comments
Milestone

Comments

@craffel
Copy link
Collaborator

craffel commented Mar 26, 2014

For making useful qualitative plots for eval-by-eye

@craffel craffel modified the milestones: 0.0.1, 0.0.2 Mar 26, 2014
@justinsalamon justinsalamon modified the milestones: 0.0.1, 0.0.2 Apr 11, 2014
@craffel craffel modified the milestones: 0.0.2, 0.0.1 Apr 14, 2014
@craffel craffel modified the milestones: 0.1, 0.0.2 Jul 3, 2014
@craffel craffel removed this from the 0.1 milestone Jul 21, 2014
@bmcfee
Copy link
Collaborator

bmcfee commented Feb 4, 2016

FWIW, this issue is starting to pop up in jams marl/jams#93 wrt pretty-printing annotations.

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

@craffel
Copy link
Collaborator Author

craffel commented Feb 4, 2016

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

@bmcfee
Copy link
Collaborator

bmcfee commented Feb 4, 2016

"plots" meaning ... what?

@craffel
Copy link
Collaborator Author

craffel commented Feb 4, 2016

You know, plots.

@bmcfee
Copy link
Collaborator

bmcfee commented Feb 4, 2016

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.

@craffel
Copy link
Collaborator Author

craffel commented Feb 4, 2016

Annotations.

@bmcfee
Copy link
Collaborator

bmcfee commented Feb 4, 2016

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.

@carlthome
Copy link
Contributor

Dead feature?

@bmcfee
Copy link
Collaborator

bmcfee commented May 7, 2016

Not dead, but (IMO) it's more natural to fit this into JAMS than mir_eval.

@carlthome
Copy link
Contributor

carlthome commented May 7, 2016

Yeah, thanks! 😃

@craffel craffel mentioned this issue May 25, 2016
@bmcfee
Copy link
Collaborator

bmcfee commented May 26, 2016

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 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.

@craffel
Copy link
Collaborator Author

craffel commented May 26, 2016

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.

@justinsalamon
Copy link
Collaborator

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 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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 26, 2016

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 26, 2016

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.

@craffel
Copy link
Collaborator Author

craffel commented May 26, 2016

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.

@justinsalamon
Copy link
Collaborator

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 26, 2016

Source separation viz demo .. 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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

Notebook updated 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
  • 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

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

Notebook updated 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.

@craffel
Copy link
Collaborator Author

craffel commented May 27, 2016

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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.

@craffel
Copy link
Collaborator Author

craffel commented May 27, 2016

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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.

@justinsalamon
Copy link
Collaborator

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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.

@justinsalamon
Copy link
Collaborator

Then I'd go with NW

@craffel
Copy link
Collaborator Author

craffel commented May 27, 2016

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.

@justinsalamon
Copy link
Collaborator

justinsalamon commented May 27, 2016

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.

@craffel
Copy link
Collaborator Author

craffel commented May 27, 2016

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.

@justinsalamon
Copy link
Collaborator

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 :)

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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

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

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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.

@craffel
Copy link
Collaborator Author

craffel commented May 27, 2016

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) 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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

Then I'd go with NW

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

@justinsalamon
Copy link
Collaborator

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

Because that's closest to how musicians annotate chords in charts and I find it more intuitive than the other 3 corners.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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

vs here:
image

@craffel
Copy link
Collaborator Author

craffel commented May 27, 2016

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 27, 2016

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?)

@craffel
Copy link
Collaborator Author

craffel commented May 28, 2016

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.

@bmcfee
Copy link
Collaborator

bmcfee commented May 28, 2016

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?

@craffel
Copy link
Collaborator Author

craffel commented May 28, 2016

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?

@bmcfee
Copy link
Collaborator

bmcfee commented May 28, 2016

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).

@bmcfee bmcfee mentioned this issue May 28, 2016
7 tasks
@craffel
Copy link
Collaborator Author

craffel commented May 28, 2016

Moving discussion to #196.

@craffel craffel added this to the 0.4 milestone Jun 1, 2016
@bmcfee bmcfee closed this as completed Jul 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants