Skip to content
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

Correct Recipe Type for Data Modification #4429

Closed
Algopaul opened this issue Aug 31, 2021 · 1 comment
Closed

Correct Recipe Type for Data Modification #4429

Algopaul opened this issue Aug 31, 2021 · 1 comment

Comments

@Algopaul
Copy link

Algopaul commented Aug 31, 2021

I hope this is the correct place to ask a question like this. I am implementing a recipe for removing data points from a plot that are unnecessary (i.e. that do not modify the overall shape of the resulting curve). This is important e.g. when exporting a figure to tikz. I am using the opheim-algorithm to perform this task (see in code below), which uses x and y data to determine superfluous points up to a given tolerance.
My question is: What is the best recipe type to implement the desired behavior? It seems to work okay for my current use-case as a series-recipe as shown in the code below. However, I see that this does not interact well with other plot recipes (e.g. the recipe designed for the Result type from the documentation of the package, where only the final line data is reduced but the surrounding epsilon-range is not). Therefore, I would like to know, if you see a better way of implementing the reduction of points than the series-recipe.
In case you need a more detailed problem description, please let me know.

using LinearAlgebra
using Plots 

@recipe function f(::Type{Val{:opheim}}, x, y, z; opheim_tol=0.1)
  xall, yall = plotattributes[:x], plotattributes[:y]
  @series begin
    seriestype := :path
    mask = opheim(xall, yall, opheim_tol)
    x := xall[mask]
    y := yall[mask]
  end
end
@shorthands opheim

"""
Computes a mask that masks points (x[i],y[i]) that do not contribute significantly to a plot of y over x
"""
function opheim(x,y,tol)
  mask=zeros(Bool, size(x))
  mask[1]=1
  mask[end]=1
  N=length(x)
  i=1
  while i<=N-2
    j=i+1
    v=[x[j]-x[i], y[j]-y[i]];
    while j<N && norm(v)<=tol
      j=j+1;
      v=[x[j]-x[i], y[j]-y[i]];
    end
    v=v/norm(v);
    normal = [v[2]; -v[1]];
    while j<N
      v1=[x[j+1]-x[i]; y[j+1]-y[i]];
      d=abs(transpose(normal)*v1);
      if d>tol
        break
      end
      v2=[x[j+1]-x[j]; y[j+1]-y[j]];
      anglecosine=transpose(v)*v2
      if anglecosine <= 0;
        break
      end
      j=j+1
    end
    i=j
    mask[i]=true
  end
  return mask
end

# Example Plot to show functionality
x = 0:0.01:2pi
y = sin.(x);
plot(x, y);
opheim!(x,y, markershape = :circle, opheim_tol=0.05)

opheim_functionality
(Plot 1: Funtionality of the Opheim Plot: Number of necessary points drastically reduced)

interaction_not_working
(Plot 2: The interactivity with other types is not given: Only the blue curve consists of fewer points but the gray shades are still at full resolution)

The second plot can be created by using the recipe function for the Result as in the documentation and then calling

res = Result(Vector(1:10), cumsum(rand(10)), cumsum(rand(10)) / 5)
opheim(res, opheim_tol=0.5)
@t-bltg t-bltg transferred this issue from JuliaPlots/RecipesBase.jl Oct 6, 2022
@Algopaul
Copy link
Author

Algopaul commented Aug 8, 2024

switched to gnuplot

@Algopaul Algopaul closed this as completed Aug 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants