예제 #1
0
def plotlinearPotentials(Pot,
                         t=0.,
                         min=-15.,
                         max=15,
                         ns=21,
                         savefilename=None):
    """
    NAME:

       plotlinearPotentials

    PURPOSE:

       plot a combination of potentials

    INPUT:

       t - time to evaluate potential at

       min - minimum x

       max - maximum x

       ns - grid in x

       savefilename - save to or restore from this savefile (pickle)

    OUTPUT:

       plot to output device

    HISTORY:

       2010-07-13 - Written - Bovy (NYU)

    """
    Pot = flatten(Pot)
    if not savefilename == None and os.path.exists(savefilename):
        print("Restoring savefile " + savefilename + " ...")
        savefile = open(savefilename, 'rb')
        potx = pickle.load(savefile)
        xs = pickle.load(savefile)
        savefile.close()
    else:
        xs = nu.linspace(min, max, ns)
        potx = nu.zeros(ns)
        for ii in range(ns):
            potx[ii] = evaluatelinearPotentials(Pot, xs[ii], t=t)
        if not savefilename == None:
            print("Writing savefile " + savefilename + " ...")
            savefile = open(savefilename, 'wb')
            pickle.dump(potx, savefile)
            pickle.dump(xs, savefile)
            savefile.close()
    return plot.bovy_plot(xs,
                          potx,
                          xlabel=r"$x/x_0$",
                          ylabel=r"$\Phi(x)$",
                          xrange=[min, max])
예제 #2
0
def LinShuReductionFactor(axiPot,R,sigmar,nonaxiPot=None,
                          k=None,m=None,OmegaP=None):
    """
    NAME:

       LinShuReductionFactor

    PURPOSE:

       Calculate the Lin & Shu (1966) reduction factor: the reduced linear response of a kinematically-warm stellar disk to a perturbation

    INPUT:

       axiPot - The background, axisymmetric potential

       R - Cylindrical radius (can be Quantity)
       
       sigmar - radial velocity dispersion of the population (can be Quantity)

       Then either provide:

       1) m= m in the perturbation's m x phi (number of arms for a spiral)

          k= wavenumber (see Binney & Tremaine 2008)

          OmegaP= pattern speed (can be Quantity)

       2) nonaxiPot= a non-axisymmetric Potential instance (such as SteadyLogSpiralPotential) that has functions that return OmegaP, m, and wavenumber

    OUTPUT:

       reduction factor

    HISTORY:

       2014-08-23 - Written - Bovy (IAS)

    """
    axiPot= flatten(axiPot)
    from galpy.potential import omegac, epifreq
    if nonaxiPot is None and (OmegaP is None or k is None or m is None):
        raise IOError("Need to specify either nonaxiPot= or m=, k=, OmegaP= for LinShuReductionFactor")
    elif not nonaxiPot is None:
        OmegaP= nonaxiPot.OmegaP()
        k= nonaxiPot.wavenumber(R)
        m= nonaxiPot.m()
    tepif= epifreq(axiPot,R)
    s= m*(OmegaP-omegac(axiPot,R))/tepif
    chi= sigmar**2.*k**2./tepif**2.
    return (1.-s**2.)/nu.sin(nu.pi*s)\
        *integrate.quad(lambda t: nu.exp(-chi*(1.+nu.cos(t)))\
                            *nu.sin(s*t)*nu.sin(t),
                        0.,nu.pi)[0]
예제 #3
0
def LinShuReductionFactor(axiPot,R,sigmar,nonaxiPot=None,
                          k=None,m=None,OmegaP=None):
    """
    NAME:

       LinShuReductionFactor

    PURPOSE:

       Calculate the Lin & Shu (1966) reduction factor: the reduced linear response of a kinematically-warm stellar disk to a perturbation

    INPUT:

       axiPot - The background, axisymmetric potential

       R - Cylindrical radius (can be Quantity)
       
       sigmar - radial velocity dispersion of the population (can be Quantity)

       Then either provide:

       1) m= m in the perturbation's m x phi (number of arms for a spiral)

          k= wavenumber (see Binney & Tremaine 2008)

          OmegaP= pattern speed (can be Quantity)

       2) nonaxiPot= a non-axisymmetric Potential instance (such as SteadyLogSpiralPotential) that has functions that return OmegaP, m, and wavenumber

    OUTPUT:

       reduction factor

    HISTORY:

       2014-08-23 - Written - Bovy (IAS)

    """
    axiPot= flatten(axiPot)
    from galpy.potential import omegac, epifreq
    if nonaxiPot is None and (OmegaP is None or k is None or m is None):
        raise IOError("Need to specify either nonaxiPot= or m=, k=, OmegaP= for LinShuReductionFactor")
    elif not nonaxiPot is None:
        OmegaP= nonaxiPot.OmegaP()
        k= nonaxiPot.wavenumber(R)
        m= nonaxiPot.m()
    tepif= epifreq(axiPot,R)
    s= m*(OmegaP-omegac(axiPot,R))/tepif
    chi= sigmar**2.*k**2./tepif**2.
    return (1.-s**2.)/nu.sin(nu.pi*s)\
        *integrate.quad(lambda t: nu.exp(-chi*(1.+nu.cos(t)))\
                            *nu.sin(s*t)*nu.sin(t),
                        0.,nu.pi)[0]
예제 #4
0
def plotlinearPotentials(Pot,t=0.,min=-15.,max=15,ns=21,savefilename=None):
    """
    NAME:

       plotlinearPotentials

    PURPOSE:

       plot a combination of potentials

    INPUT:

       t - time to evaluate potential at

       min - minimum x

       max - maximum x

       ns - grid in x

       savefilename - save to or restore from this savefile (pickle)

    OUTPUT:

       plot to output device

    HISTORY:

       2010-07-13 - Written - Bovy (NYU)

    """
    Pot= flatten(Pot)
    if not savefilename == None and os.path.exists(savefilename):
        print("Restoring savefile "+savefilename+" ...")
        savefile= open(savefilename,'rb')
        potx= pickle.load(savefile)
        xs= pickle.load(savefile)
        savefile.close()
    else:
        xs= nu.linspace(min,max,ns)
        potx= nu.zeros(ns)
        for ii in range(ns):
            potx[ii]= evaluatelinearPotentials(Pot,xs[ii],t=t)
        if not savefilename == None:
            print("Writing savefile "+savefilename+" ...")
            savefile= open(savefilename,'wb')
            pickle.dump(potx,savefile)
            pickle.dump(xs,savefile)
            savefile.close()
    return plot.bovy_plot(xs,potx,
                          xlabel=r"$x/x_0$",ylabel=r"$\Phi(x)$",
                          xrange=[min,max])
예제 #5
0
def toPlanarPotential(Pot):
    """
    NAME:

       toPlanarPotential

    PURPOSE:

       convert an Potential to a planarPotential in the mid-plane (z=0)

    INPUT:

       Pot - Potential instance or list of such instances (existing planarPotential instances are just copied to the output)

    OUTPUT:

       planarPotential instance(s)

    HISTORY:

       2016-06-11 - Written - Bovy (UofT)

    """
    Pot= flatten(Pot)
    if isinstance(Pot,list):
        out= []
        for pot in Pot:
            if isinstance(pot,planarPotential):
                out.append(pot)
            elif pot.isNonAxi:
                out.append(planarPotentialFromFullPotential(pot))
            else:
                out.append(planarPotentialFromRZPotential(pot))
        return out
    elif isinstance(Pot,Potential) and Pot.isNonAxi:
        return planarPotentialFromFullPotential(Pot)
    elif isinstance(Pot,Potential):
        return planarPotentialFromRZPotential(Pot)
    elif isinstance(Pot,planarPotential):
        return Pot
    else:
        raise PotentialError("Input to 'toPlanarPotential' is neither an Potential-instance or a list of such instances")
예제 #6
0
def toPlanarPotential(Pot):
    """
    NAME:

       toPlanarPotential

    PURPOSE:

       convert an Potential to a planarPotential in the mid-plane (z=0)

    INPUT:

       Pot - Potential instance or list of such instances (existing planarPotential instances are just copied to the output)

    OUTPUT:

       planarPotential instance(s)

    HISTORY:

       2016-06-11 - Written - Bovy (UofT)

    """
    Pot= flatten(Pot)
    if isinstance(Pot,list):
        out= []
        for pot in Pot:
            if isinstance(pot,planarPotential):
                out.append(pot)
            elif pot.isNonAxi:
                out.append(planarPotentialFromFullPotential(pot))
            else:
                out.append(planarPotentialFromRZPotential(pot))
        return out
    elif isinstance(Pot,Potential) and Pot.isNonAxi:
        return planarPotentialFromFullPotential(Pot)
    elif isinstance(Pot,Potential):
        return planarPotentialFromRZPotential(Pot)
    elif isinstance(Pot,planarPotential):
        return Pot
    else:
        raise PotentialError("Input to 'toPlanarPotential' is neither an Potential-instance or a list of such instances")
예제 #7
0
def RZToplanarPotential(RZPot):
    """
    NAME:

       RZToplanarPotential

    PURPOSE:

       convert an RZPotential to a planarPotential in the mid-plane (z=0)

    INPUT:

       RZPot - RZPotential instance or list of such instances (existing planarPotential instances are just copied to the output)

    OUTPUT:

       planarPotential instance(s)

    HISTORY:

       2010-07-13 - Written - Bovy (NYU)

    """
    RZPot= flatten(RZPot)
    if isinstance(RZPot,list):
        out= []
        for pot in RZPot:
            if isinstance(pot,planarPotential):
                out.append(pot)
            else:
                out.append(planarPotentialFromRZPotential(pot))
        return out
    elif isinstance(RZPot,Potential):
        return planarPotentialFromRZPotential(RZPot)
    elif isinstance(RZPot,planarPotential):
        return RZPot
    else:
        raise PotentialError("Input to 'RZToplanarPotential' is neither an RZPotential-instance or a list of such instances")
예제 #8
0
def RZToplanarPotential(RZPot):
    """
    NAME:

       RZToplanarPotential

    PURPOSE:

       convert an RZPotential to a planarPotential in the mid-plane (z=0)

    INPUT:

       RZPot - RZPotential instance or list of such instances (existing planarPotential instances are just copied to the output)

    OUTPUT:

       planarPotential instance(s)

    HISTORY:

       2010-07-13 - Written - Bovy (NYU)

    """
    RZPot= flatten(RZPot)
    if isinstance(RZPot,list):
        out= []
        for pot in RZPot:
            if isinstance(pot,planarPotential):
                out.append(pot)
            else:
                out.append(planarPotentialFromRZPotential(pot))
        return out
    elif isinstance(RZPot,Potential):
        return planarPotentialFromRZPotential(RZPot)
    elif isinstance(RZPot,planarPotential):
        return RZPot
    else:
        raise PotentialError("Input to 'RZToplanarPotential' is neither an RZPotential-instance or a list of such instances")
예제 #9
0
def plotplanarPotentials(Pot,*args,**kwargs):
    """
    NAME:

       plotplanarPotentials

    PURPOSE:

       plot a planar potential

    INPUT:

       Rrange - range (can be Quantity)

       xrange, yrange - if relevant (can be Quantity)

       grid, gridx, gridy - number of points to plot

       savefilename - save to or restore from this savefile (pickle)

       ncontours - number of contours to plot (if applicable)

       +bovy_plot(*args,**kwargs) or bovy_dens2d(**kwargs)

    OUTPUT:

       plot to output device

    HISTORY:

       2010-07-13 - Written - Bovy (NYU)

    """
    Pot= flatten(Pot)
    Rrange= kwargs.pop('Rrange',[0.01,5.])
    xrange= kwargs.pop('xrange',[-5.,5.])
    yrange= kwargs.pop('yrange',[-5.,5.])
    if _APY_LOADED:
        if hasattr(Pot,'_ro'):
            tro= Pot._ro
        else:
            tro= Pot[0]._ro
        if isinstance(Rrange[0],units.Quantity):
            Rrange[0]= Rrange[0].to(units.kpc).value/tro
        if isinstance(Rrange[1],units.Quantity):
            Rrange[1]= Rrange[1].to(units.kpc).value/tro
        if isinstance(xrange[0],units.Quantity):
            xrange[0]= xrange[0].to(units.kpc).value/tro
        if isinstance(xrange[1],units.Quantity):
            xrange[1]= xrange[1].to(units.kpc).value/tro
        if isinstance(yrange[0],units.Quantity):
            yrange[0]= yrange[0].to(units.kpc).value/tro
        if isinstance(yrange[1],units.Quantity):
            yrange[1]= yrange[1].to(units.kpc).value/tro
    grid= kwargs.pop('grid',100)
    gridx= kwargs.pop('gridx',100)
    gridy= kwargs.pop('gridy',gridx)
    savefilename= kwargs.pop('savefilename',None)
    isList= isinstance(Pot,list)
    nonAxi= ((isList and Pot[0].isNonAxi) or (not isList and Pot.isNonAxi))
    if not savefilename is None and os.path.exists(savefilename):
        print("Restoring savefile "+savefilename+" ...")
        savefile= open(savefilename,'rb')
        potR= pickle.load(savefile)
        if nonAxi:
            xs= pickle.load(savefile)
            ys= pickle.load(savefile)
        else:
            Rs= pickle.load(savefile)
        savefile.close()
    else:
        if nonAxi:
            xs= nu.linspace(xrange[0],xrange[1],gridx)
            ys= nu.linspace(yrange[0],yrange[1],gridy)
            potR= nu.zeros((gridx,gridy))
            for ii in range(gridx):
                for jj in range(gridy):
                    thisR= nu.sqrt(xs[ii]**2.+ys[jj]**2.)
                    if xs[ii] >= 0.:
                        thisphi= nu.arcsin(ys[jj]/thisR)
                    else:
                        thisphi= -nu.arcsin(ys[jj]/thisR)+nu.pi
                    potR[ii,jj]= evaluateplanarPotentials(Pot,thisR,
                                                          phi=thisphi,
                                                          use_physical=False)
        else:
            Rs= nu.linspace(Rrange[0],Rrange[1],grid)
            potR= nu.zeros(grid)
            for ii in range(grid):
                potR[ii]= evaluateplanarPotentials(Pot,Rs[ii],
                                                   use_physical=False)
        if not savefilename is None:
            print("Writing planar savefile "+savefilename+" ...")
            savefile= open(savefilename,'wb')
            pickle.dump(potR,savefile)
            if nonAxi:
                pickle.dump(xs,savefile)
                pickle.dump(ys,savefile)
            else:
                pickle.dump(Rs,savefile)
            savefile.close()
    if nonAxi:
        if not 'orogin' in kwargs:
            kwargs['origin']= 'lower'
        if not 'cmap' in kwargs:
            kwargs['cmap']= 'gist_yarg'
        if not 'contours' in kwargs:
            kwargs['contours']= True
        if not 'xlabel' in kwargs:
            kwargs['xlabel']= r"$x / R_0$"
        if not 'ylabel' in kwargs:
            kwargs['ylabel']= "$y / R_0$"
        if not 'aspect' in kwargs:
            kwargs['aspect']= 1.
        if not 'cntrls' in kwargs:
            kwargs['cntrls']= '-'
        ncontours= kwargs.pop('ncontours',10)
        if not 'levels' in kwargs:
            kwargs['levels']= nu.linspace(nu.nanmin(potR),nu.nanmax(potR),ncontours)
        return plot.bovy_dens2d(potR.T,
                                xrange=xrange,
                                yrange=yrange,**kwargs)
    else:
        kwargs['xlabel']=r"$R/R_0$"
        kwargs['ylabel']=r"$\Phi(R)$"
        kwargs['xrange']=Rrange
        return plot.bovy_plot(Rs,potR,*args,**kwargs)
예제 #10
0
def plotplanarPotentials(Pot,*args,**kwargs):
    """
    NAME:

       plotplanarPotentials

    PURPOSE:

       plot a planar potential

    INPUT:

       Rrange - range (can be Quantity)

       xrange, yrange - if relevant (can be Quantity)

       grid, gridx, gridy - number of points to plot

       savefilename - save to or restore from this savefile (pickle)

       ncontours - number of contours to plot (if applicable)

       +bovy_plot(*args,**kwargs) or bovy_dens2d(**kwargs)

    OUTPUT:

       plot to output device

    HISTORY:

       2010-07-13 - Written - Bovy (NYU)

    """
    Pot= flatten(Pot)
    Rrange= kwargs.pop('Rrange',[0.01,5.])
    xrange= kwargs.pop('xrange',[-5.,5.])
    yrange= kwargs.pop('yrange',[-5.,5.])
    if _APY_LOADED:
        if hasattr(Pot,'_ro'):
            tro= Pot._ro
        else:
            tro= Pot[0]._ro
        if isinstance(Rrange[0],units.Quantity):
            Rrange[0]= Rrange[0].to(units.kpc).value/tro
        if isinstance(Rrange[1],units.Quantity):
            Rrange[1]= Rrange[1].to(units.kpc).value/tro
        if isinstance(xrange[0],units.Quantity):
            xrange[0]= xrange[0].to(units.kpc).value/tro
        if isinstance(xrange[1],units.Quantity):
            xrange[1]= xrange[1].to(units.kpc).value/tro
        if isinstance(yrange[0],units.Quantity):
            yrange[0]= yrange[0].to(units.kpc).value/tro
        if isinstance(yrange[1],units.Quantity):
            yrange[1]= yrange[1].to(units.kpc).value/tro
    grid= kwargs.pop('grid',100)
    gridx= kwargs.pop('gridx',100)
    gridy= kwargs.pop('gridy',gridx)
    savefilename= kwargs.pop('savefilename',None)
    isList= isinstance(Pot,list)
    nonAxi= ((isList and Pot[0].isNonAxi) or (not isList and Pot.isNonAxi))
    if not savefilename is None and os.path.exists(savefilename):
        print("Restoring savefile "+savefilename+" ...")
        savefile= open(savefilename,'rb')
        potR= pickle.load(savefile)
        if nonAxi:
            xs= pickle.load(savefile)
            ys= pickle.load(savefile)
        else:
            Rs= pickle.load(savefile)
        savefile.close()
    else:
        if nonAxi:
            xs= nu.linspace(xrange[0],xrange[1],gridx)
            ys= nu.linspace(yrange[0],yrange[1],gridy)
            potR= nu.zeros((gridx,gridy))
            for ii in range(gridx):
                for jj in range(gridy):
                    thisR= nu.sqrt(xs[ii]**2.+ys[jj]**2.)
                    if xs[ii] >= 0.:
                        thisphi= nu.arcsin(ys[jj]/thisR)
                    else:
                        thisphi= -nu.arcsin(ys[jj]/thisR)+nu.pi
                    potR[ii,jj]= evaluateplanarPotentials(Pot,thisR,
                                                          phi=thisphi,
                                                          use_physical=False)
        else:
            Rs= nu.linspace(Rrange[0],Rrange[1],grid)
            potR= nu.zeros(grid)
            for ii in range(grid):
                potR[ii]= evaluateplanarPotentials(Pot,Rs[ii],
                                                   use_physical=False)
        if not savefilename is None:
            print("Writing planar savefile "+savefilename+" ...")
            savefile= open(savefilename,'wb')
            pickle.dump(potR,savefile)
            if nonAxi:
                pickle.dump(xs,savefile)
                pickle.dump(ys,savefile)
            else:
                pickle.dump(Rs,savefile)
            savefile.close()
    if nonAxi:
        if not 'orogin' in kwargs:
            kwargs['origin']= 'lower'
        if not 'cmap' in kwargs:
            kwargs['cmap']= 'gist_yarg'
        if not 'contours' in kwargs:
            kwargs['contours']= True
        if not 'xlabel' in kwargs:
            kwargs['xlabel']= r"$x / R_0$"
        if not 'ylabel' in kwargs:
            kwargs['ylabel']= "$y / R_0$"
        if not 'aspect' in kwargs:
            kwargs['aspect']= 1.
        if not 'cntrls' in kwargs:
            kwargs['cntrls']= '-'
        ncontours= kwargs.pop('ncontours',10)
        if not 'levels' in kwargs:
            kwargs['levels']= nu.linspace(nu.nanmin(potR),nu.nanmax(potR),ncontours)
        return plot.bovy_dens2d(potR.T,
                                xrange=xrange,
                                yrange=yrange,**kwargs)
    else:
        kwargs['xlabel']=r"$R/R_0$"
        kwargs['ylabel']=r"$\Phi(R)$"
        kwargs['xrange']=Rrange
        return plot.bovy_plot(Rs,potR,*args,**kwargs)