-
Notifications
You must be signed in to change notification settings - Fork 757
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
[classlib] Plotter: add multiple concurrent modes #4459
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is well written.
Are you sure that the semantic differentiation between plotMode
and plotModes
is worth the trouble? In sclang, we often treat arrays the same as elements, and I can't remember where I've seen a case in which we keep both singular and plural forms spearately as methods.
I'd prefer if plotMode
and plotModes
were synonyms.
The same goes for plotColors
. There is now an instance variable both in Plotter
and in Plot
.
I think we should briefly get clear on where all the state is kept. Right now it is confusing (it might have been a bit confusing already before).
Currently, the number of channels (and therefore the number of Plots) within a Plotter can change dynamically. The original reason to keep all the state in arrays in the Plotter was that it can be set once and then the values can change underneath.
Because every
(2) is more efficient, (1) is easier to understand and maintain. If we don't run into efficiency problems, (2) might be the best (I am sorry if I gave a different recommendation earlier). |
Sorry to drag on this, but I knew it would take some unwinding to get an idea of the scope of problem.
Yea... the state is smeared across both objects pretty well 😕 For the sake of background, I did a deep dive on how the state is managed, which I'll put below, but to keep this discussion on the practical issue of method/variable names...
This is helpful perspective! To clarify, you'd like to see if State storage in Plot vs. PlotterHere are some of the state variables that have some aspects of being shared between the two (omitting states which should clearly live in one instead of the other, like
Further, all these parameters belong exclusively to
So if you want to set any of those, you need to access
This seems sensible, but the state is also stored in p = 4.collect({15.collect({rrand(0,1.0)})}).plot;
p.plotColors_(4.collect{Color.rand}); p.refresh;
p.superpose = false;
p.value[0] === p.plots[0].value // true
p.superpose = true;
p.value[0] === p.plots[0].value // false Storing the same data multiple ways also happens in p.superpose = false;
p.data === p.value; // true
p.superpose = true;
p.data === p.value; // false As an aside, I'd imagine this is pretty inefficient for large datasets.
This is also complicated by p = 4.collect({15.collect({rrand(0,1.0)})}).plot;
p.plotColors_(4.collect{Color.rand}); p.refresh;
// observe Plotter's value wrt superpose
p.superpose = true;
p.value.shape
// -> [4, 15]
p.superpose = false;
p.value.shape
// -> [4, 15] // remains constant when superposed
// observe Plot's value wrt superpose
p.superpose = false;
p.plots
// -> [ a Plot, a Plot, a Plot, a Plot ] // four plots
x = p.plots[0].value // value at first plot
x.shape
// -> [15] // first channel of data in the first plot
p.superpose = true;
p.plots
// -> [ a Plot ] // one plots
x = p.plots[0].value // value at first plot
x.shape
// -> [15, 4] // all data stored in EACH plot, and multichannel data flopped (therefor copied) when superposed Because In any case, I'm not sure what the larger overhaul would look like exactly, but that seems beyond the scope of this PR. |
Thank you very much indeed for this careful analysis. If I remember correctly, the state in the Plot is mainly meant as optimization, but this may not be required. I'd suggest that you simplify this PR a little (no new plural forms for now, or only plural, whatever seems better), and then you could propose a refactoring as you have sketched above already. Would that be a good way to proceed? Alternatively, if you don't have the time to do this, you can also make an issue ticket with the proposed refactoring in this thread. |
I would use singular terms everywhere, and only add plural ones for backward compatibility where they are plural now.
We can then see if we deprecate the plural forms, but I don't mind to let them in if commented. The plotter is just a tool, so we don't build up much secondary code that depends on it. At the same time, probably there are a lot of snippets around which may break for people. |
0d93b35
to
aa930c6
Compare
OK, I've made these changes so that there are no plural method additions. I've also modified I also updated docs to reflect these changes.
I think this is a good way forward. I'll put together an issue that documents the points to be addressed in a future refactor. Thanks, Julian! |
Also note that I left the arguments to both plotColor_ { |colors| plotMode_ { |modes| This seemed OK to me to suggest that the argument need not be a single mode/color. But I'm OK changing those arg names to be singular if you think it's better. |
Hi @telephon, just checking in to see if you'd like any further changes with this PR. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks ok to me now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm having a weird problem testing this.
Something in domainSpecs
is sometimes breaking, but I can't pinpoint it. Reproducer:
a = { (0..100) }.dup(2).plot;
a.domainSpecs = [-6, 10.6].asSpec; a.refresh; // ERROR: Message '@' not understood.
//but these are fine:
a.domainSpecs = [-6, 10.7].asSpec; a.refresh;
a.domainSpecs = [-5, 10.6].asSpec; a.refresh;
Can't find where the problem is? Some kind of rounding issue?
EDIT: I tested with a different build and this error went away, it must've been a weird interaction between the SC version I was testing this on (just swapped class library). This PR looks good now to me (aside from a minor change below). I think we need to wait for #4678 to go in, merge 3.10 into develop and then rebase this to resolve conflicts.
aa930c6
to
ac1b556
Compare
PLEASE DON'T MERGE YET I think we need to wait for #4678 to go in, merge 3.10 into develop and then rebase this to resolve conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
marking as changes requested to avoid accidental merge, see above comment
please rebase after #4678 |
9ad5e80
to
ccd7d86
Compare
OK, it's been rebased and I think the conflicts have been resolved properly. |
Looks like this PR now includes sc-el updates (?). I'm not sure why/how that happens, submodules are still quite a mystery to me. @brianlheim since you marked it as changes requested (to block merging before conflict resolution) I think it would be great if you gave it a green light. The only remaining question is whether anything needs to be done about sc-el... edit: maybe this needs |
ccd7d86
to
540d1b7
Compare
Thanks for catching that @dyfer. I rewound and removed those sneaky submodule changes. It actually made the commit history more concise anyway. |
@dyfer sorry for the delay. i've simply dismissed my review, would prefer others to manage this PR. i don't have much interest in it and seems other people already know it better :) |
Purpose and Motivation
This PR adds the ability to specify multiple plot modes, as you can with plot colors.
It follows the same implementation as
plotColors
for consistency. This includes making aplotMode
variable local toPlot
, and settable throughPlotter
via-plotModes_
.Implementation Notes to review
-plotMode
(singular) getter and setter methods are left for backwards compatibility. This also offers syntax that suit the common case of a single plot (-plotMode
calls-plotModes
internally).plotColors
stores all the plot colors internally in an array,plotModes
an array of modes, even when it's a single mode. The getter method will return this array, unless there is only one mode or all modes of a multi-channel plot are identical, in which case it just returns theSymbol
of the mode. This mirrors the way all modes can be set by a single modeSymbol
.Open questions (Update: resolved):
-plotModes
and-plotMode
(singular) getters and setters, should this also be the case for-plotColors
? Should a-plotColor
(singular) getter and setter be added toPlotter
?-specs
and-domainSpecs
get/setters—should their singular counterparts (synonyms essentially) be added?Plotter
, a common case is aPlotter
that just contains onePlot
, for which it makes more semantic sense to say, e.g.myPlotter.domainSpec_([33, 45].asSpec)
-plotColors_
was changed fromargColors
tocolors
, which is technically a breaking change, but this method was only recently introduced in [classlib] Plotter: fix domain and superpose behavior. #4082, merged into 3.10, but has the 3.10.3 milestone, so isn't yet in the main distribution.argColors
originally because the the nearbyargSpecs
argument name, but after a closer look I see that's because there is an instance variablespecs
soargSpecs
was to differentiate it from that variable name. This is not the case withargColors
, so I decided to go with the cleaner name.Types of changes
To-do list