getter for ticks for colorbar #6170

Merged
merged 1 commit into from Mar 31, 2016

Conversation

Projects
None yet
4 participants
Contributor

yongzhez commented Mar 16, 2016

This is my proposed inclusion for #5792. I do note that it hands backs the ticks in a list instead of an array, is that a problem by any chance?

mdboom added the needs_review label Mar 16, 2016

Owner

tacaswell commented Mar 17, 2016

Can you add a simple test for this?

Is this consistent with similar method on the x and y axis?

Does this do the mapping to data space?

tacaswell added this to the 2.1 (next point release) milestone Mar 17, 2016

Contributor

yongzhez commented Mar 18, 2016

I've checked and it does work properly with both a horizontal and vertical axis for a colorbar. In relation to testing, what would be consider a good test? is simply comparing the ticks that are set and the ticks that are return by the method enough? Also, still wondering if having ticks returned in a list is acceptable.

@tacaswell tacaswell commented on an outdated diff Mar 21, 2016

lib/matplotlib/colorbar.py
@@ -396,6 +396,14 @@ def set_ticks(self, ticks, update_ticks=True):
self.update_ticks()
self.stale = True
+ def get_ticks(self):
+ """
+ gets the tick locations that are in the locator
+ :return: an array of all ticks in the locator
+ """
+
+ return self.locator.tick_values(0, 0)
@tacaswell

tacaswell Mar 21, 2016

Owner

self.locator can be None

Owner

tacaswell commented Mar 21, 2016

By consistent, I mean what would you use to get the ticks are for the x or y axis.

A good test would be to construct an example where you know what the tick should be and then check that they are in fact what you expect.

I think this is going to have to be a bit more involved and possible involve a refactor of _ticker

Contributor

yongzhez commented Mar 24, 2016

I've created the necessary implementation of xticks and yticks in correlation to the behaviour that axis class does. I'm creating the tests right now for my implementation . Also, refactoring _ticker might not be necessary considering that the 2 methods I created are the same as axis's ticker getters behaviour.

Owner

efiring commented Mar 24, 2016

@yongzhez I don't think those two methods are useful for Colorbar. It looks like #6216 is closer to doing the right thing, but still needs work. Notice that a Colorbar has ticks only on one axis; and that the tick locations as returned by your methods are not in data coordinates, so they don't address #5792.

Contributor

yongzhez commented Mar 24, 2016

I see, I used your suggestion to basically add a _tick_data_values field. I also added a test to correspond with this to test for the 2 returned list for a horizontal and vertical colorbar. I chose to go the path of a getter simply for consistency sake, but I can change when required.

Contributor

yongzhez commented Mar 25, 2016

I've added the case that the user does not set their own ticks and updated the tests to correspond.

Owner

efiring commented Mar 25, 2016

I'm sorry, but I think your approach is still not correct. We don't want to recalculate the data tick values, we want to save them at the point where they are already being calculated. And it looks to me like the values you are recalculating or grabbing are not the data values at all.

Contributor

yongzhez commented Mar 25, 2016

I apologize @efiring , I have noted that update_ticks() already calls _ticker() so I can just assign the ticks there. I also now return the data as a list of all the ticks. Is that sufficient?

Owner

efiring commented Mar 25, 2016

@yongzhez I think you missed a critical point: the "ticks" returned by _ticker are not in data space, so they are not the values we want. What is needed is to save the b values that are generated in _ticker and used by it to calculate the "ticks" and "ticklabels".
Since you and a group led by @TheJenniferYu (#6216) are working on solving the same issue, please join forces and consolidate your work in a single PR.

Contributor

yongzhez commented Mar 25, 2016

@efiring it's pretty late where I live so I wasn't able to contact the other team, I think I understand what you want me to do and I pushed a fix.

@efiring efiring commented on an outdated diff Mar 28, 2016

lib/matplotlib/colorbar.py
@@ -592,6 +597,7 @@ def _ticker(self):
formatter.set_data_interval(*intv)
b = np.array(locator())
+ self._tick_data_values = b
@efiring

efiring Mar 28, 2016

Owner

It looks like you are close, but shouldn't you save the b values after all potential modifications? See the following lines.

@efiring efiring commented on an outdated diff Mar 28, 2016

lib/matplotlib/tests/test_colorbar.py
@@ -298,6 +298,26 @@ def test_colorbar_ticks():
assert len(cbar.ax.xaxis.get_ticklocs()) == len(clevs)
+@cleanup
+def test_colorbar_get_ticks():
+ # test feature for #5792
+ plt.figure()
+ data = np.arange(1200).reshape(30, 40)
+
+ plt.subplot()
+ plt.contourf(data)
@efiring

efiring Mar 28, 2016

Owner

For the test, it would be better to use the more OO style instead of the pyplot state machine style.
On second thought, I'm close to neutral on this; our tests seem to be about 50-50 between the styles, and for this particular test it doesn't make much difference.

@efiring efiring commented on an outdated diff Mar 28, 2016

lib/matplotlib/tests/test_colorbar.py
@@ -298,6 +298,26 @@ def test_colorbar_ticks():
assert len(cbar.ax.xaxis.get_ticklocs()) == len(clevs)
+@cleanup
+def test_colorbar_get_ticks():
+ # test feature for #5792
+ plt.figure()
+ data = np.arange(1200).reshape(30, 40)
+
+ plt.subplot()
+ plt.contourf(data)
+
+ userTicks = plt.colorbar(use_gridspec=True, ticks=[0, 600, 1200])
@efiring

efiring Mar 28, 2016

Owner

Is the use_gridspec kwarg significant or needed in any way? If not, I would omit it.

@efiring efiring commented on an outdated diff Mar 28, 2016

lib/matplotlib/tests/test_colorbar.py
+ # test feature for #5792
+ plt.figure()
+ data = np.arange(1200).reshape(30, 40)
+
+ plt.subplot()
+ plt.contourf(data)
+
+ userTicks = plt.colorbar(use_gridspec=True, ticks=[0, 600, 1200])
+ assert userTicks.get_ticks().tolist() == [0, 600, 1200]
+
+ defTicks = plt.colorbar(use_gridspec=True, orientation='horizontal')
+ assert defTicks.get_ticks().tolist() == [0.0, 150.0, 300.0, 450.0, 600.0,
+ 750.0, 900.0, 1050.0, 1200.0]
+
+ userTicks.set_ticks([600, 700, 800])
+ assert userTicks.get_ticks().tolist() == [600, 700, 800]
@efiring

efiring Mar 28, 2016

Owner

I think it would be good to have one more test, for the case where the ticks are set to include values outside the range, and these outside values are discarded.

@efiring efiring commented on an outdated diff Mar 28, 2016

lib/matplotlib/tests/test_colorbar.py
@@ -298,6 +298,26 @@ def test_colorbar_ticks():
assert len(cbar.ax.xaxis.get_ticklocs()) == len(clevs)
+@cleanup
+def test_colorbar_get_ticks():
+ # test feature for #5792
+ plt.figure()
+ data = np.arange(1200).reshape(30, 40)
+
+ plt.subplot()
+ plt.contourf(data)
+
+ userTicks = plt.colorbar(use_gridspec=True, ticks=[0, 600, 1200])
+ assert userTicks.get_ticks().tolist() == [0, 600, 1200]
+
+ defTicks = plt.colorbar(use_gridspec=True, orientation='horizontal')
+ assert defTicks.get_ticks().tolist() == [0.0, 150.0, 300.0, 450.0, 600.0,
@efiring

efiring Mar 28, 2016

Owner

If the default for selecting the contour levels were to change, this would break. I suggest generating an array of levels, using that as the levels kwarg to contourf and then testing against that same array.

@yongzhez yongzhez Getter for ticks for colorbar
Closes #5792
051183e
Contributor

yongzhez commented Mar 29, 2016

@efiring I made the changes.

@efiring efiring merged commit 5d0ca1d into matplotlib:master Mar 31, 2016

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

efiring removed the needs_revision label Mar 31, 2016

Owner

efiring commented Mar 31, 2016

Thank you, @yongzhez!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment