Skip to content

Instantly share code, notes, and snippets.

@FelixBenning
Last active August 22, 2021 14:07
Show Gist options
  • Save FelixBenning/0341f47fe00de1a9eb806f9bee81a42d to your computer and use it in GitHub Desktop.
Save FelixBenning/0341f47fe00de1a9eb806f9bee81a42d to your computer and use it in GitHub Desktop.
Pruning Ticks From Plot which are too close
using ResumableFunctions: ResumableFunctions, @yield, @resumable
@resumable function cluster(metric, ordered_iter, max_distance)
start = 1
for (idx, elmt) in enumerate(ordered_iter)
if metric(elmt,ordered_iter[max(start,idx-1)]) > max_distance
@yield view(ordered_iter, start: idx-1)
start = idx
end
end
@yield view(ordered_iter, start:length(ordered_iter))
end
""" Recursive Implementation of `prune_positions` assuming a sorted `pos_id` list is provided as a first parameter
"""
function prune_positions_unsafe(sorted_pos_ids, tick_pos, min_distance)
metric(n,m) = abs(tick_pos[n]-tick_pos[m]) # distance between ids is real distance
# cluster all ids which are closer than the minimum distance, prune groups to
# single elements by removing the largest id (least important tick) and recursion
pruned = map(cluster(metric, sorted_pos_ids, min_distance)) do group
if length(group) == 1
return group
else
return prune_positions_unsafe(
deleteat!(copy(group), argmax(group)),
tick_pos,
min_distance
)
end
end
# concatenate single element lists
return hcat(pruned...)
end
"""
Prunes away (sortable) positions closer than `min_distance`, assumes that the order of positions reflect their importance and removes the violating positions from the end until positions are no longer closer than `min_distance`
`return`: indices of remaining positions
"""
function prune_positions(positions, min_distance)
return prune_positions_unsafe(sortperm(positions), positions, min_distance)
end
unzip(zip_iter) = map(idx -> getfield.(zip_iter, idx), fieldnames(eltype(zip_iter)))
"""
Takes zipped ticks [(0,"label 0"), (1, "label 1"), ...] and removes ticks which are closer than `min_distance`, assumes that the order of ticks reflect their importance and removes the violating ticks from the end until ticks are no longer closer than `min_distance`
"""
function prune_ticks(ticks, min_distance)
tick_pos, tick_labels = unzip(ticks)
pruned_tick_ids = prune_positions(tick_pos, min_distance)
return (tick_pos[pruned_tick_ids], tick_labels[pruned_tick_ids])
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment