2010-06-30 6 views
3

Essayer de tracer un spectre, à savoir, la vitesse par rapport à l'intensité, à faible axe x = vitesse, sur l'axe double supérieure = fréquencepython/matplotlib - axe doubles parasites échelle

La relation entre eux (formule doppler) est

f = (1-v/c)*f_0 

où f est la fréquence résultante, la vitesse v, c la vitesse de la lumière, et f_0 la fréquence à v = 0, c. le v_lsr.

J'ai essayé de le résoudre en regardant http://matplotlib.sourceforge.net/examples/axes_grid/parasite_simple2.html, où il est résolu par

pm_to_kms = 1./206265.*2300*3.085e18/3.15e7/1.e5 
aux_trans = matplotlib.transforms.Affine2D().scale(pm_to_kms, 1.) 
ax_pm = ax_kms.twin(aux_trans) 
ax_pm.set_viewlim_mode("transform") 

mon problème est, comment puis-je remplacer les pm_to_kms avec ma fonction de la fréquence?

Quelqu'un sait-il comment résoudre ce problème?

Répondre

4

La solution que je fini par utiliser est:

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)) 

Cela fonctionne parfaitement, et d'une solution beaucoup moins compliquée.

EDIT: Trouvé une réponse très chic. EDIT2: Changement de la transformation de l'appel en fonction du commentaire par @ U55

Cela consiste essentiellement à définir notre propre conversion/transformation. En raison des excellentes équivalences AstroPy Units, il devient encore plus facile à comprendre et plus illustratif.

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() 

Ce produit maintenant les résultats souhaités: enter image description here

+0

Cela s'est avéré fonctionner correctement, par hasard, parce que l'équation de conversion entre la fréquence et la longueur d'onde (νλ = c) est symétrique par rapport à l'échange de fréquence et de longueur d'onde. Cependant, pour les transformations générales, cela donnera des résultats incorrects. Vous devez remplacer 'Freq2WavelengthTransform()' par 'Wavelength2FreqTransform()' dans la ligne: ' – u55

0

Votre "fonction linéaire" est une "loi d'échelle simple" (avec un décalage). Remplacez simplement la définition pm_to_kms par votre fonction.

+0

bien oui ... donc vous dire que je fais deux, une mise à l'échelle des transformations et une traduction? comme kms_to_deltafreq = -F0/c deltafreq_to_freq = f0 matplotlib.transforms.Affine2D() échelle. (Kms_to_deltafreq, 1.). Traduire (deltafreq_to_freq, 1) = ax_freq ax_kms.twin (aux_trans) ax_freq.set_viewlim_mode ("transformer") ?? –

+0

Donc une réponse pour maintenant existe ici: http://matplotlib.1069221.n5.nabble.com/Dual-x-axes-with-transformation-td10865.html si le temps le permet, j'en écrirai un ici. –