You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Plots.jl中Type Recipe与User Recipe的差异及协同使用疑问

Can Type Recipes and User Recipes in Plots.jl Be Used Together?

Absolutely! Type Recipes and User Recipes in Plots.jl are designed to complement each other, not conflict—combining them lets you build modular, reusable plotting logic with ease. Let’s break down how they work together with a concrete example.

First, a quick recap to align on definitions:

  • Type Recipe: Binds default plotting behavior to a custom type. Whenever you call plot(my_custom_type_instance), this recipe automatically triggers to handle how the type is visualized.
  • User Recipe: Creates a custom plotting interface (like a dedicated function) for specialized workflows. Users call this function directly (e.g., foo(x)) to generate tailored plots.

Example: Combining Both Recipes

Let’s build a scenario where we have a custom data type, a Type Recipe for its default visualization, and a User Recipe that extends this with additional elements.

  1. Define a Custom Type

    struct ExperimentalData
        measurements::Vector{Float64}
        timepoints::Vector{Float64}
    end
    
  2. Add a Type Recipe
    This sets the default behavior when plotting an ExperimentalData instance—we’ll make it a scatter plot of time vs. measurements:

    using Plots
    
    @recipe function f(data::ExperimentalData)
        seriestype := :scatter
        xlabel := "Time (s)"
        ylabel := "Measurement Value"
        label := "Raw Data"
        data.timepoints, data.measurements
    end
    

    Now calling plot(my_data) will automatically render this scatter plot.

  3. Create a User Recipe for Enhanced Visualization
    Let’s make a trendplot function that plots the raw data (using our Type Recipe) plus a rolling mean trend line:

    @userplot TrendPlot
    
    @recipe function f(tp::TrendPlot)
        data = tp.args[1]
        # First, use the Type Recipe to plot raw data
        @series begin
            data  # Plots.jl automatically uses the ExperimentalData Type Recipe here
        end
        # Add a rolling mean trend line
        rolling_mean = [mean(data.measurements[i-2:i]) for i in 3:length(data.measurements)]
        @series begin
            seriestype := :line
            color := :red
            label := "Rolling Mean"
            data.timepoints[3:end], rolling_mean
        end
    end
    
  4. Use Them Together
    Now we can call our User Recipe, which leverages the Type Recipe under the hood:

    # Generate sample data
    test_data = ExperimentalData(randn(20), 1:20)
    # Plot raw data + trend line in one call
    trendplot(test_data)
    

How It Works

The key is the @series macro in the User Recipe: when you pass an instance of your custom type to @series, Plots.jl automatically resolves and uses the corresponding Type Recipe to render that part of the plot. This lets you reuse the default type visualization as a building block for more complex, custom plots.

You can also go the other way—if your Type Recipe needs to include specialized elements defined in a User Recipe, you can call the User Recipe’s function within the Type Recipe using @series as well.

Final Takeaway

Type Recipes handle the "default look" for your custom types, while User Recipes let you build specialized, reusable plotting workflows on top of those defaults. Combining them keeps your code DRY (Don’t Repeat Yourself) and makes your plotting logic both modular and flexible.

内容的提问来源于stack exchange,提问作者Hamlet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:00:52