如何自定义BokehJS中第二个y轴上刻度之间的距离。

huangapple go评论88阅读模式
英文:

How to customise distance between tickers on the 2nd y-axis in BokehJS

问题

我试图使用BokehJS创建一个图形。这个图形需要3个轴(左、右、底部):

如图所示,右侧的y轴看起来相当难看,你无法从底部读取任何数据,因为刻度值都挤在一起。

这是我创建绘图和线条的方式:

function zip(arr1, arr2, floatCast){
    var out = {};
    if (floatCast){
        arr1.map( (val,idx)=>{ out[parseFloat(val)] = arr2[idx]; } );
    }
    else{
        arr1.map( (val,idx)=>{ out[val] = arr2[idx]; } );
    }
    return out;
}

function createBokehPlot(PNVibe, staticPN, transX, transY){
    //清空先前的绘图
    $( "#graph-div" ).empty();

    //振动下PN与偏移频率的数据源
    const source = new Bokeh.ColumnDataSource({
        data: { x: Object.keys(PNVibe), y: Object.values(PNVibe) }
    });
                
    //静态PN与偏移频率的数据源
    const source1 = new Bokeh.ColumnDataSource({
        data: { x: Object.keys(staticPN), y: Object.values(staticPN) }
    });

    //传递线的数据源
    const source2 = new Bokeh.ColumnDataSource({
        data: { x: transX, y: transY}
    });

    //设置绘图的x/y范围
    var max_offset = Math.max(Object.keys(PNVibe));
    const xdr = new Bokeh.Range1d({ start: 1, end: 100000 });
    const ydr = new Bokeh.Range1d({ start: -180, end: -50 });
    const y2_range = new Bokeh.Range1d({start: 0.001, end: 10});

    //创建一个带有一些工具的绘图
    const plot = Bokeh.Plotting.figure({
        title: '随机数据示例',
        tools: "pan,wheel_zoom,box_zoom,reset,save",
        toolbar_location: "right",
        toolbar_sticky: false,
        height: 600,
        width: 700,
        outerWidth: 800,
        legend_location: "top_left",
        x_range: xdr,
        y_range: ydr,
        x_axis_type: "log",
        x_axis_label: "偏移频率(Hz)",
        y_axis_type: "linear",
        y_axis_label: "相位噪声(dBc/Hz)",
        extra_y_ranges: {y2_range},
        major_label_standoff: 1
    });

    //在右侧添加第二个y轴
    const second_y_axis = new Bokeh.LogAxis({y_range_name:"y2_range", axis_label:'振动轮廓(g^2/Hz)', x_range: xdr, bounds:[0.0001, 10]});
    second_y_axis.ticker = new Bokeh.FixedTicker({ticks: [0.0001, 0.001, 0.01, 0.1, 1, 10]});
    plot.add_layout(second_y_axis, "right");

    //为振动相位噪声添加线
    plot.line({ field: "x" }, { field: "y" }, {
        source: source,
        line_width: 2,
        line_color: "red",
        legend_label: "振动下的相位噪声"
    });
                
    //为静态相位噪声添加线
    plot.line({ field: "x" }, { field: "y" }, {
        source: source1,
        line_width: 2,
        line_color: "blue",
        legend_label: "静态相位噪声"
    });

    plot.line({ field: "x" }, { field: "y" }, {
        source: source2,
        line_width: 2,
        line_color: "green",
        y_range_name:"y2_range",
        legend_label: "传递度"
    });

    //显示绘图,将其附加到当前部分的末尾
    Bokeh.Plotting.show(plot, "#graph-div");
    return;
}

//调用函数
var PNVibe = zip([10, 100, 1000], [-95, -100, -105], false);
var staticPN = zip([10, 100, 1000], [-90, -105, -110], false);
var transX = [10, 100, 1000];
var transY = [0.0005, 0.003, 0.05];
createBokehPlot(PNVibe, staticPN, transX, transY);

我的问题是,如何能够使右侧的y轴显示得更好?最好每个刻度之间的距离都相同(即10^0和10^1之间的距离与10^1和10^2之间的距离相同)。

谢谢。

我还在Bokeh论坛上发布了这个问题:这里

英文:

So I'm trying to create a plot with BokehJS. This plot needs 3 axes (left, right, bottom):
The plot looks like this

如何自定义BokehJS中第二个y轴上刻度之间的距离。

As you can see, the right y-axis is pretty ugly, you can't read any data from towards the bottom as the tickers are bunched up.

This is how im creating my plot and lines

function zip(arr1, arr2, floatCast){
    var out = {};
    if (floatCast){
        arr1.map( (val,idx)=>{ out[parseFloat(val)] = arr2[idx]; } );
        }
    else{
        arr1.map( (val,idx)=>{ out[val] = arr2[idx]; } );
        }
    return out;
}

function createBokehPlot(PNVibe, staticPN, transX, transY){
    //empty the previous plot
    $( "#graph-div" ).empty();

    //Data Source for PN under vibration vs. offset frequency 
    const source = new Bokeh.ColumnDataSource({
    data: { x: Object.keys(PNVibe), y: Object.values(PNVibe) }
    });
                
    //Data source for Static PN vs offset frequency
    const source1 = new Bokeh.ColumnDataSource({
        data: { x: Object.keys(staticPN), y: Object.values(staticPN) }
    });

    //Data source for Transmissibility line
    const source2 = new Bokeh.ColumnDataSource({
        data: { x: transX, y: transY}
    });

    //Set plot x/y ranges
    var max_offset = Math.max(Object.keys(PNVibe));
    const xdr = new Bokeh.Range1d({ start: 1, end: 100000 });
    const ydr = new Bokeh.Range1d({ start: -180, end: -50 });
    const y2_range = new Bokeh.Range1d({start: 0.001, end: 10});

    // make a plot with some tools
    const plot = Bokeh.Plotting.figure({
        title: 'Example of random data',
        tools: "pan,wheel_zoom,box_zoom,reset,save",
        toolbar_location: "right",
        toolbar_sticky: false,
        height: 600,
        width: 700,
        outerWidth: 800,
        legend_location: "top_left",
        x_range: xdr,
        y_range: ydr,
        x_axis_type:"log",
        x_axis_label: "Offset Frequency (Hz)",
        y_axis_type: "linear",
        y_axis_label: "Phase Noise (dBc/Hz)",
        extra_y_ranges: {y2_range},
        major_label_standoff: 1
});

    //Add the second y axis on the right
    const second_y_axis = new Bokeh.LogAxis({y_range_name:"y2_range",     axis_label:'Vibration Profile (g^2/Hz)', x_range: xdr, bounds:[0.0001, 10]});
    second_y_axis.ticker = new Bokeh.FixedTicker({ticks: [0.0001, 0.001, 0.01, 0.1, 1, 10]})
    plot.add_layout(second_y_axis, "right");


    // add line for vibraiton phase noise
    plot.line({ field: "x" }, { field: "y" }, {
        source: source,
        line_width: 2,
        line_color: "red",
        legend_label: "Phase Noise under Vibrations"
        });
                
    //add line for static phase noise
    plot.line({ field: "x" }, { field: "y" }, {
        source: source1,
        line_width: 2,
        line_color: "blue",
        legend_label: "Static Phase Noise"
        });

    plot.line({ field: "x" }, { field: "y" }, {
        source: source2,
        line_width: 2,
        line_color: "green",
        y_range_name:"y2_range",
        legend_label: "Transmissibillity"
        });

    // show the plot, appending it to the end of the current section
    Bokeh.Plotting.show(plot, "#graph-div");
    return;
}

//Call function
var PNVibe = zip([10, 100, 1000], [-95, -100, -105], false);
var staticPN = zip([10, 100, 1000], [-90, -105, -110], false);
var transX = [10, 100, 1000];
var transY = [0.0005, 0.003, 0.05];
createBokehPlot(PNVibe, staticPN, transX, transY);

My question is, how would I be able to make it so that the right y-axis displays better? Preferably I want each tick to be the same distance from each other (ie. space between 10^0 and 10^1 is the same as space between 10^1 and 10^2)

Thanks

I also posted this on the bokeh forums:Here

答案1

得分: 1

修复了我的问题:

我相信我原始代码中可能存在一些无效的JavaScript,这就是为什么它没有正确渲染的原因。经过几个小时的尝试各种可能的方法,现在已经修复。

// 为y2定义范围
const y2_range = new Bokeh.Range1d({start: 0.0001, end: 10}); // 无法使用数组

// 创建一个带有一些工具的图表
const plot = Bokeh.Plotting.figure({
    title: '随机数据示例',
    tools: "pan,wheel_zoom,box_zoom,reset,save,hover",
    toolbar_location: "right",
    toolbar_sticky: false,
    height: 600,
    width: 700,
    outerWidth: 800,
    legend_location: "top_left",
    x_range: [1, 1000000],
    y_range: [-180, -70],
    x_axis_type: "log",
    x_axis_label: "偏移频率(Hz)",
    y_axis_label: "相位噪声(dBc/Hz)",
    extra_y_ranges: {"y2_range": y2_range}, // 这是错误的
    extra_y_scales: {"y2_range": new Bokeh.LogScale()}, // 这是错误的
    major_label_standoff: 5,
});

// 在右侧添加第二个y轴
const second_y_axis = new Bokeh.LogAxis({
    y_range_name: "y2_range",
    axis_label: '振动谱(g^2/Hz)',
    x_range: [1, 1000000],
    bounds: [0.0001, 10],
});

plot.add_layout(second_y_axis, "right");
英文:

Fixed my problem:

I believe I may have had some invalid javascript in my original code which is why it wasnt correctly rendering. After hours of messing around with whatever I could think of, it's fixed.

//Define range for y2
const y2_range = new Bokeh.Range1d({start: 0.0001, end: 10}); //Cannot use //array for this
// make a plot with some tools
const plot = Bokeh.Plotting.figure({
title: 'Example of random data',
tools: "pan,wheel_zoom,box_zoom,reset,save,hover",
toolbar_location: "right",
toolbar_sticky: false,
height: 600,
width: 700,
outerWidth: 800,
legend_location: "top_left",
x_range: [1, 1000000],
y_range: [-180, -70],
x_axis_type:"log",
x_axis_label: "Offset Frequency (Hz)",
y_axis_label: "Phase Noise (dBc/Hz)",
extra_y_ranges: {"y2_range": y2_range}, //This was incorrect
extra_y_scales: {"y2_range": new Bokeh.LogScale()}, //This was incorrect
major_label_standoff: 5,
});
//Add the second y axis on the right
const second_y_axis = new Bokeh.LogAxis({
y_range_name:"y2_range",
axis_label:'Vibration Profile (g^2/Hz)',
x_range: [1, 1000000],
bounds:[0.0001, 10],
});
plot.add_layout(second_y_axis, "right");

huangapple
  • 本文由 发表于 2023年2月14日 06:25:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75441774.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定