Skip to content
This repository has been archived by the owner on Jun 16, 2018. It is now read-only.

Commit

Permalink
Merge 88b9047 into fa6a9e2
Browse files Browse the repository at this point in the history
  • Loading branch information
Asra Nizami committed Jul 14, 2014
2 parents fa6a9e2 + 88b9047 commit 40ba13e
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 4 deletions.
80 changes: 76 additions & 4 deletions wcsaxes/coordinate_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ def __init__(self, parent_axes=None, parent_map=None, transform=None, coord_inde
self.ticklabels = TickLabels(self.frame,
transform=None, # display coordinates
figure=parent_axes.get_figure())
self.ticks.display_minor_ticks(False)
self.minor_frequency = 5

# Initialize axis labels
self.axislabels = AxisLabels(self.frame,
Expand Down Expand Up @@ -364,6 +366,8 @@ def _update_ticks(self, renderer):

# First find the ticks we want to show
tick_world_coordinates, spacing = self._formatter_locator.locator(*coord_range[self.coord_index])
if self.ticks.get_display_minor_ticks():
minor_ticks_w_coordinates = self._formatter_locator.minor_locator(spacing, self.get_minor_frequency(), *coord_range[self.coord_index])

# We want to allow non-standard rectangular frames, so we just rely on
# the parent axes to tell us what the bounding frame is.
Expand All @@ -373,7 +377,7 @@ def _update_ticks(self, renderer):
self.ticklabels.clear()
lblinfo = []
lbl_world = []

lbl_minor_world = []
# Look up parent axes' transform from data to figure coordinates.
#
# See:
Expand Down Expand Up @@ -440,7 +444,7 @@ def _update_ticks(self, renderer):
tick_world_coordinates_unit = tick_world_coordinates.unit
tick_world_coordinates_values = tick_world_coordinates.value
if self.coord_type == 'longitude':
tick_world_coordinates_values = np.hstack([tick_world_coordinates_values,
tick_world_coordinates_values = np.hstack([tick_world_coordinates_values,
tick_world_coordinates_values + 360])

for t in tick_world_coordinates_values:
Expand Down Expand Up @@ -487,11 +491,79 @@ def _update_ticks(self, renderer):
axis_displacement=imin + frac))
lbl_world.append(world)

if self.ticks.get_display_minor_ticks():

minor_ticks_w_coordinates_values = minor_ticks_w_coordinates.value
if self.coord_type == 'longitude':
minor_ticks_w_coordinates_values = np.hstack([minor_ticks_w_coordinates_values,
minor_ticks_w_coordinates_values + 360])

for t in minor_ticks_w_coordinates_values:

# Find steps where a tick is present
intersections = np.nonzero(((t - w1) * (t - w2)) < 0)[0]

# Loop over ticks, and find exact pixel coordinates by linear
# interpolation
for imin in intersections:

imax = imin + 1

frac = (t - w1[imin]) / (w2[imin] - w1[imin])
x_data_i = spine.data[imin, 0] + frac * (spine.data[imax, 0] - spine.data[imin, 0])
y_data_i = spine.data[imin, 1] + frac * (spine.data[imax, 1] - spine.data[imin, 1])
x_pix_i = spine.pixel[imin, 0] + frac * (spine.pixel[imax, 0] - spine.pixel[imin, 0])
y_pix_i = spine.pixel[imin, 1] + frac * (spine.pixel[imax, 1] - spine.pixel[imin, 1])
delta_angle = tick_angle[imax] - tick_angle[imin]
if delta_angle > 180.:
delta_angle -= 360.
elif delta_angle < -180.:
delta_angle += 360.
angle_i = tick_angle[imin] + frac * delta_angle

if self.coord_type == 'longitude':
world = wrap_angle_at(t, self.coord_wrap)
else:
world = t

self.ticks.add_minor(minor_axis=axis,
minor_pixel=(x_data_i, y_data_i),
minor_world=world,
minor_angle=angle_i,
minor_axis_displacement=imin + frac)
lbl_minor_world.append(world)


# format tick labels, add to scene
text = self._formatter_locator.formatter(lbl_world * tick_world_coordinates_unit, spacing=spacing)
text = self._formatter_locator.formatter(lbl_world * tick_world_coordinates_unit, spacing=spacing)
for kwargs, txt in zip(lblinfo, text):
self.ticklabels.add(text=txt, **kwargs)

def display_minor_ticks(self, display_minor_ticks):
"""
Display minor ticks for this coordinate.
Parameters
----------
display_minor_ticks : bool
Whether or not to display minor ticks.
"""
self.ticks.display_minor_ticks(display_minor_ticks)

def get_minor_frequency(self):
return self.minor_frequency

def set_minor_frequency(self, frequency):
"""
Set the frequency of minor ticks per major ticks.
Parameters
----------
frequency : int
The number of minor ticks per major ticks.
"""
self.minor_frequency = frequency

def _update_grid_lines(self):

# For 3-d WCS with a correlated third axis, the *proper* way of
Expand Down Expand Up @@ -536,7 +608,7 @@ def _update_grid_contour(self):
tick_world_coordinates, spacing = self._formatter_locator.locator(*coord_range[self.coord_index])

field = field[self.coord_index]

# tick_world_coordinates is a Quantities array and we only needs its values
tick_world_coordinates_values = tick_world_coordinates.value

Expand Down
20 changes: 20 additions & 0 deletions wcsaxes/formatter_locator.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,16 @@ def locator(self, value_min, value_max):
values = np.arange(imin, imax + 1, dtype=int) * spacing_deg
return values * u.degree, spacing_deg * u.degree

def minor_locator(self, spacing, frequency, value_min, value_max):
if self.values is not None:
# values have been manually specified, minor_locator doesn't work for that then?
return [] * u.deg
minor_spacing = spacing.value / frequency
imin = np.ceil(value_min / minor_spacing)
imax = np.floor(value_max / minor_spacing)
values = np.arange(imin, imax + 1, dtype=int) * minor_spacing
return values * u.degree

def formatter(self, values, spacing):
if not isinstance(values, u.Quantity) and values is not None:
raise TypeError("values should be a Quantities array")
Expand Down Expand Up @@ -405,6 +415,16 @@ def locator(self, value_min, value_max):
values = np.arange(imin, imax + 1, dtype=int) * spacing
return values * self._unit, spacing * self._unit

def minor_locator(self, spacing, frequency, value_min, value_max):
if self.values is not None:
# values have been manually specified, minor_locator doesn't work for that then?
return [] * self._unit
minor_spacing = spacing.value / frequency
imin = np.ceil(value_min / minor_spacing)
imax = np.floor(value_max / minor_spacing)
values = np.arange(imin, imax + 1, dtype=int) * minor_spacing
return values * self._unit

def formatter(self, values, spacing):

if len(values) > 0:
Expand Down
64 changes: 64 additions & 0 deletions wcsaxes/ticks.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ def __init__(self, ticksize=None, tick_out=False, **kwargs):
line2d_kwargs.update(kwargs)
Line2D.__init__(self, [0.], [0.], **line2d_kwargs)
self.set_visible_axes('all')
self._display_minor_ticks = False

def display_minor_ticks(self, display_minor_ticks):
self._display_minor_ticks = display_minor_ticks

def get_display_minor_ticks(self):
return self._display_minor_ticks

def set_tick_out(self, tick_out):
"""
Expand Down Expand Up @@ -80,6 +87,10 @@ def clear(self):
self.pixel = {}
self.angle = {}
self.disp = {}
self.minor_world = {}
self.minor_pixel = {}
self.minor_angle = {}
self.minor_disp = {}

def add(self, axis, world, pixel, angle, axis_displacement):
if axis not in self.world:
Expand All @@ -93,6 +104,22 @@ def add(self, axis, world, pixel, angle, axis_displacement):
self.angle[axis].append(angle)
self.disp[axis].append(axis_displacement)

def get_minor_world(self):
return self.minor_world

def add_minor(self, minor_axis, minor_world, minor_pixel, minor_angle,
minor_axis_displacement):
if minor_axis not in self.minor_world:
self.minor_world[minor_axis] = [minor_world]
self.minor_pixel[minor_axis] = [minor_pixel]
self.minor_angle[minor_axis] = [minor_angle]
self.minor_disp[minor_axis] = [minor_axis_displacement]
else:
self.minor_world[minor_axis].append(minor_world)
self.minor_pixel[minor_axis].append(minor_pixel)
self.minor_angle[minor_axis].append(minor_angle)
self.minor_disp[minor_axis].append(minor_axis_displacement)

def __len__(self):
return len(self.world)

Expand Down Expand Up @@ -136,3 +163,40 @@ def draw(self, renderer):
marker_rotation.clear()

gc.restore()
if self._display_minor_ticks:
self._draw_minor_ticks(renderer)

def _draw_minor_ticks(self, renderer):
"""
Draw the minor ticks.
"""
path_trans = self.get_transform()

gc = renderer.new_gc()
gc.set_foreground(self.get_color())
gc.set_alpha(self.get_alpha())
gc.set_linewidth(self.get_linewidth())

offset = renderer.points_to_pixels(self.get_ticksize() * 0.5)
marker_scale = Affine2D().scale(offset, offset)
marker_rotation = Affine2D()
marker_transform = marker_scale + marker_rotation

initial_angle = 180. if self.get_tick_out() else 0.

for axis in self.get_visible_axes():

for loc, angle in zip(self.minor_pixel[axis], self.minor_angle[axis]):

# Set the rotation for this tick
marker_rotation.rotate_deg(initial_angle + angle)

# Draw the markers
locs = path_trans.transform_non_affine(np.array([loc, loc]))
renderer.draw_markers(gc, self._tickvert_path, marker_transform,
Path(locs), path_trans.get_affine())

# Reset the tick rotation before moving to the next tick
marker_rotation.clear()

gc.restore()

0 comments on commit 40ba13e

Please sign in to comment.