Last active
August 22, 2021 14:07
-
-
Save FelixBenning/0341f47fe00de1a9eb806f9bee81a42d to your computer and use it in GitHub Desktop.
Pruning Ticks From Plot which are too close
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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