python/matplotlib - parasite twin axis scaling

前端 未结 2 669
醉话见心
醉话见心 2021-01-03 11:01

Trying to plot a spectrum, ie, velocity versus intensity, with lower x axis = velocity, on the upper twin axis = frequency

The relationship between them (doppler for

相关标签:
2条回答
  • 2021-01-03 11:35

    Your "linear function" is a "simple scaling law" (with an offset). Just replace the pm_to_kms definition with your function.

    0 讨论(0)
  • 2021-01-03 11:46

    The solution I ended up using was:

    ax_hz = ax_kms.twiny()
    x_1, x_2 = ax_kms.get_xlim()
    # i want the frequency in GHz so, divide by 1e9
    ax_hz.set_xlim(calc_frequency(x_1,data.restfreq/1e9),calc_frequency(x_2,data.restfreq/1e9))
    

    This works perfect, and much less complicated solution.

    EDIT : Found a very fancy answer. EDIT2 : Changed the transform call according to the comment by @u55

    This basically involves defining our own conversion/transform. Because of the excellent AstroPy Units equivalencies, it becomes even easier to understand and more illustrative.

    from matplotlib import transforms as mtransforms
    import astropy.constants as co
    import astropy.units as un
    import numpy as np 
    import matplotlib.pyplot as plt 
    plt.style.use('ggplot')
    from mpl_toolkits.axes_grid.parasite_axes import SubplotHost 
    
    
    class Freq2WavelengthTransform(mtransforms.Transform): 
        input_dims = 1 
        output_dims = 1 
        is_separable = False 
        has_inverse = True 
    
        def __init__(self):
            mtransforms.Transform.__init__(self)
    
        def transform_non_affine(self, fr): 
            return (fr*un.GHz).to(un.mm, equivalencies=un.spectral()).value 
    
        def inverted(self): 
            return Wavelength2FreqTransform() 
    
    class Wavelength2FreqTransform(Freq2WavelengthTransform): 
        input_dims = 1 
        output_dims = 1 
        is_separable = False 
        has_inverse = True 
    
        def __init__(self):
            mtransforms.Transform.__init__(self)
    
        def transform_non_affine(self, wl): 
            return (wl*un.mm).to(un.GHz, equivalencies=un.spectral()).value 
    
        def inverted(self): 
            return Freq2WavelengthTransform() 
    
    
    
    aux_trans = mtransforms.BlendedGenericTransform(Wavelength2FreqTransform(), mtransforms.IdentityTransform()) 
    
    fig = plt.figure(2) 
    
    ax_GHz = SubplotHost(fig, 1,1,1) 
    fig.add_subplot(ax_GHz) 
    ax_GHz.set_xlabel("Frequency (GHz)") 
    
    
    xvals = np.arange(199.9, 999.9, 0.1) 
    
    # data, noise + Gaussian (spectral) lines
    data = np.random.randn(len(xvals))*0.01 + np.exp(-(xvals-300.)**2/100.)*0.5 + np.exp(-(xvals-600.)**2/400.)*0.5
    
    ax_mm = ax_GHz.twin(aux_trans) 
    ax_mm.set_xlabel('Wavelength (mm)') 
    ax_mm.set_viewlim_mode("transform") 
    ax_mm.axis["right"].toggle(ticklabels=False) 
    
    ax_GHz.plot(xvals, data) 
    ax_GHz.set_xlim(200, 1000) 
    
    plt.draw() 
    plt.show() 
    

    This now produces the desired results: enter image description here

    0 讨论(0)
提交回复
热议问题